kopia lustrzana https://github.com/espressif/esp-idf
Merge branch 'feature/spi_keep_cs_low' into 'master'
SPI: chip select can now be kept active if the bus has been acquired Closes IDF-3125 See merge request espressif/esp-idf!13546pull/7325/head
commit
74d939fd71
|
@ -105,7 +105,7 @@ typedef struct {
|
|||
#define SPI_TRANS_VARIABLE_ADDR (1<<6) ///< Use the ``address_bits`` in ``spi_transaction_ext_t`` rather than default value in ``spi_device_interface_config_t``.
|
||||
#define SPI_TRANS_VARIABLE_DUMMY (1<<7) ///< Use the ``dummy_bits`` in ``spi_transaction_ext_t`` rather than default value in ``spi_device_interface_config_t``.
|
||||
#define SPI_TRANS_SET_CD (1<<7) ///< Set the CD pin
|
||||
|
||||
#define SPI_TRANS_CS_KEEP_ACTIVE (1<<8) ///< Keep CS active after data transfer
|
||||
/**
|
||||
* This structure describes one SPI transaction. The descriptor should not be modified until the transaction finishes.
|
||||
*/
|
||||
|
@ -194,7 +194,8 @@ esp_err_t spi_bus_remove_device(spi_device_handle_t handle);
|
|||
* @param ticks_to_wait Ticks to wait until there's room in the queue; use portMAX_DELAY to
|
||||
* never time out.
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG if parameter is invalid
|
||||
* - ESP_ERR_INVALID_ARG if parameter is invalid. This can happen if SPI_DEVICE_CS_KEEP_LOW flag is specified while
|
||||
* the bus was not acquired (`spi_device_acquire_bus()` should be called first)
|
||||
* - ESP_ERR_TIMEOUT if there was no room in the queue before ticks_to_wait expired
|
||||
* - ESP_ERR_NO_MEM if allocating DMA-capable temporary buffer failed
|
||||
* - ESP_ERR_INVALID_STATE if previous transactions are not finished
|
||||
|
@ -257,7 +258,8 @@ esp_err_t spi_device_transmit(spi_device_handle_t handle, spi_transaction_t *tra
|
|||
* currently only portMAX_DELAY is supported.
|
||||
*
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG if parameter is invalid
|
||||
* - ESP_ERR_INVALID_ARG if parameter is invalid. This can happen if SPI_DEVICE_CS_KEEP_LOW flag is specified while
|
||||
* the bus was not acquired (`spi_device_acquire_bus()` should be called first)
|
||||
* - ESP_ERR_TIMEOUT if the device cannot get control of the bus before ``ticks_to_wait`` expired
|
||||
* - ESP_ERR_NO_MEM if allocating DMA-capable temporary buffer failed
|
||||
* - ESP_ERR_INVALID_STATE if previous transactions are not finished
|
||||
|
|
|
@ -466,14 +466,13 @@ int spi_get_actual_clock(int fapb, int hz, int duty_cycle)
|
|||
static SPI_MASTER_ISR_ATTR void spi_setup_device(spi_device_t *dev)
|
||||
{
|
||||
spi_bus_lock_dev_handle_t dev_lock = dev->dev_lock;
|
||||
|
||||
if (!spi_bus_lock_touch(dev_lock)) {
|
||||
//if the configuration is already applied, skip the following.
|
||||
return;
|
||||
}
|
||||
spi_hal_context_t *hal = &dev->host->hal;
|
||||
spi_hal_dev_config_t *hal_dev = &(dev->hal_dev);
|
||||
spi_hal_setup_device(hal, hal_dev);
|
||||
|
||||
if (spi_bus_lock_touch(dev_lock)) {
|
||||
/* Configuration has not been applied yet. */
|
||||
spi_hal_setup_device(hal, hal_dev);
|
||||
}
|
||||
}
|
||||
|
||||
static SPI_MASTER_ISR_ATTR spi_device_t *get_acquiring_dev(spi_host_t *host)
|
||||
|
@ -512,12 +511,11 @@ static void spi_bus_intr_disable(void *host)
|
|||
// Setup the transaction-specified registers and linked-list used by the DMA (or FIFO if DMA is not used)
|
||||
static void SPI_MASTER_ISR_ATTR spi_new_trans(spi_device_t *dev, spi_trans_priv_t *trans_buf)
|
||||
{
|
||||
spi_transaction_t *trans = NULL;
|
||||
spi_transaction_t *trans = trans_buf->trans;
|
||||
spi_host_t *host = dev->host;
|
||||
spi_hal_context_t *hal = &(host->hal);
|
||||
spi_hal_dev_config_t *hal_dev = &(dev->hal_dev);
|
||||
|
||||
trans = trans_buf->trans;
|
||||
host->cur_cs = dev->id;
|
||||
|
||||
//Reconfigure according to device settings, the function only has effect when the dev_id is changed.
|
||||
|
@ -531,6 +529,7 @@ static void SPI_MASTER_ISR_ATTR spi_new_trans(spi_device_t *dev, spi_trans_priv_
|
|||
hal_trans.send_buffer = (uint8_t*)host->cur_trans_buf.buffer_to_send;
|
||||
hal_trans.cmd = trans->cmd;
|
||||
hal_trans.addr = trans->addr;
|
||||
hal_trans.cs_keep_active = (trans->flags & SPI_TRANS_CS_KEEP_ACTIVE) ? 1 : 0;
|
||||
//Set up QIO/DIO if needed
|
||||
hal_trans.io_mode = (trans->flags & SPI_TRANS_MODE_DIO ?
|
||||
(trans->flags & SPI_TRANS_MODE_DIOQIO_ADDR ? SPI_LL_IO_MODE_DIO : SPI_LL_IO_MODE_DUAL) :
|
||||
|
@ -784,6 +783,12 @@ esp_err_t SPI_MASTER_ATTR spi_device_queue_trans(spi_device_handle_t handle, spi
|
|||
|
||||
SPI_CHECK(!spi_bus_device_is_polling(handle), "Cannot queue new transaction while previous polling transaction is not terminated.", ESP_ERR_INVALID_STATE );
|
||||
|
||||
/* Even when using interrupt transfer, the CS can only be kept activated if the bus has been
|
||||
* acquired with `spi_device_acquire_bus()` first. */
|
||||
if (host->device_acquiring_lock != handle && (trans_desc->flags & SPI_TRANS_CS_KEEP_ACTIVE)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
spi_trans_priv_t trans_buf;
|
||||
ret = setup_priv_desc(trans_desc, &trans_buf, (host->bus_attr->dma_enabled));
|
||||
if (ret != ESP_OK) return ret;
|
||||
|
@ -921,8 +926,16 @@ esp_err_t SPI_MASTER_ISR_ATTR spi_device_polling_start(spi_device_handle_t handl
|
|||
|
||||
SPI_CHECK(!spi_bus_device_is_polling(handle), "Cannot send polling transaction while the previous polling transaction is not terminated.", ESP_ERR_INVALID_STATE );
|
||||
|
||||
/* If device_acquiring_lock is set to handle, it means that the user has already
|
||||
* acquired the bus thanks to the function `spi_device_acquire_bus()`.
|
||||
* In that case, we don't need to take the lock again. */
|
||||
if (host->device_acquiring_lock != handle) {
|
||||
ret = spi_bus_lock_acquire_start(handle->dev_lock, ticks_to_wait);
|
||||
/* The user cannot ask for the CS to keep active has the bus is not locked/acquired. */
|
||||
if ((trans_desc->flags & SPI_TRANS_CS_KEEP_ACTIVE) != 0) {
|
||||
ret = ESP_ERR_INVALID_ARG;
|
||||
} else {
|
||||
ret = spi_bus_lock_acquire_start(handle->dev_lock, ticks_to_wait);
|
||||
}
|
||||
} else {
|
||||
ret = spi_bus_lock_wait_bg_done(handle->dev_lock, ticks_to_wait);
|
||||
}
|
||||
|
@ -963,6 +976,9 @@ esp_err_t SPI_MASTER_ISR_ATTR spi_device_polling_end(spi_device_handle_t handle,
|
|||
uninstall_priv_desc(&host->cur_trans_buf);
|
||||
|
||||
host->polling = false;
|
||||
/* Once again here, if device_acquiring_lock is set to `handle`, it means that the user has already
|
||||
* acquired the bus thanks to the function `spi_device_acquire_bus()`.
|
||||
* In that case, the lock must not be released now because . */
|
||||
if (host->device_acquiring_lock != handle) {
|
||||
assert(host->device_acquiring_lock == NULL);
|
||||
spi_bus_lock_acquire_end(handle->dev_lock);
|
||||
|
|
|
@ -496,6 +496,16 @@ static inline void spi_ll_master_select_cs(spi_dev_t *hw, int cs_id)
|
|||
hw->pin.cs2_dis = (cs_id == 2) ? 0 : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep Chip Select activated after the current transaction.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param keep_active if 0 don't keep CS activated, else keep CS activated
|
||||
*/
|
||||
static inline void spi_ll_master_keep_cs(spi_dev_t *hw, int keep_active) {
|
||||
hw->pin.cs_keep_active = (keep_active != 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Configs: parameters
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
|
|
@ -604,6 +604,16 @@ static inline void spi_ll_master_select_cs(spi_dev_t *hw, int cs_id)
|
|||
hw->misc.cs5_dis = (cs_id == 5) ? 0 : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep Chip Select activated after the current transaction.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param keep_active if 0 don't keep CS activated, else keep CS activated
|
||||
*/
|
||||
static inline void spi_ll_master_keep_cs(spi_dev_t *hw, int keep_active) {
|
||||
hw->misc.cs_keep_active = (keep_active != 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Configs: parameters
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
|
|
@ -603,6 +603,16 @@ static inline void spi_ll_master_select_cs(spi_dev_t *hw, int cs_id)
|
|||
hw->misc.cs5_dis = (cs_id == 5) ? 0 : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep Chip Select activated after the current transaction.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param keep_active if 0 don't keep CS activated, else keep CS activated
|
||||
*/
|
||||
static inline void spi_ll_master_keep_cs(spi_dev_t *hw, int keep_active) {
|
||||
hw->misc.cs_keep_active = (keep_active != 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Configs: parameters
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
|
|
@ -566,6 +566,16 @@ static inline void spi_ll_master_select_cs(spi_dev_t *hw, int cs_id)
|
|||
hw->misc.cs5_dis = (cs_id == 5) ? 0 : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep Chip Select activated after the current transaction.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param keep_active if 0 don't keep CS activated, else keep CS activated
|
||||
*/
|
||||
static inline void spi_ll_master_keep_cs(spi_dev_t *hw, int keep_active) {
|
||||
hw->misc.cs_keep_active = (keep_active != 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Configs: parameters
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
|
|
@ -612,6 +612,16 @@ static inline void spi_ll_master_select_cs(spi_dev_t *hw, int cs_id)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep Chip Select activated after the current transaction.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param keep_active if 0 don't keep CS activated, else keep CS activated
|
||||
*/
|
||||
static inline void spi_ll_master_keep_cs(spi_dev_t *hw, int keep_active) {
|
||||
hw->misc.cs_keep_active = (keep_active != 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Configs: parameters
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
|
|
@ -101,6 +101,7 @@ typedef struct {
|
|||
uint8_t *send_buffer; ///< Data to be sent
|
||||
uint8_t *rcv_buffer; ///< Buffer to hold the receive data.
|
||||
spi_ll_io_mode_t io_mode; ///< IO mode of the master
|
||||
int cs_keep_active; ///< Keep CS active after transaction
|
||||
} spi_hal_trans_config_t;
|
||||
|
||||
/**
|
||||
|
|
|
@ -131,6 +131,9 @@ void spi_hal_setup_trans(spi_hal_context_t *hal, const spi_hal_dev_config_t *dev
|
|||
spi_ll_set_command(hw, trans->cmd, cmdlen, dev->tx_lsbfirst);
|
||||
spi_ll_set_address(hw, trans->addr, addrlen, dev->tx_lsbfirst);
|
||||
|
||||
//Configure keep active CS
|
||||
spi_ll_master_keep_cs(hw, trans->cs_keep_active);
|
||||
|
||||
//Save the transaction attributes for internal usage.
|
||||
memcpy(&hal->trans_config, trans, sizeof(spi_hal_trans_config_t));
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue