mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
SPI: chip select can now be kept active if the bus has been acquired
The user can now request the chip select to remain active after the current transfer. In order to do so, he MUST acquire the bus first with `spi_device_acquire_bus()` function, else, an error is returned.
This commit is contained in:
parent
a1b5c38218
commit
a6e14c37b2
@ -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));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user