diff --git a/nrfx/drivers/include/nrfx_twim.h b/nrfx/drivers/include/nrfx_twim.h index 33fa1127..c557f804 100644 --- a/nrfx/drivers/include/nrfx_twim.h +++ b/nrfx/drivers/include/nrfx_twim.h @@ -49,18 +49,80 @@ extern "C" { * @brief Two Wire Interface Master with EasyDMA (TWIM) peripheral driver. */ +/** @brief TWIM driver transfer types. */ +typedef enum +{ + NRFX_TWIM_XFER_TX, ///< TX transfer. + NRFX_TWIM_XFER_RX, ///< RX transfer. + NRFX_TWIM_XFER_TXRX, ///< TX transfer followed by RX transfer with repeated start. + NRFX_TWIM_XFER_TXTX ///< TX transfer followed by TX transfer with repeated start. +} nrfx_twim_xfer_type_t; + +/** @brief TWIM driver event types. */ +typedef enum +{ + NRFX_TWIM_EVT_DONE, ///< Transfer completed event. + NRFX_TWIM_EVT_ADDRESS_NACK, ///< Error event: NACK received after sending the address. + NRFX_TWIM_EVT_DATA_NACK, ///< Error event: NACK received after sending a data byte. + NRFX_TWIM_EVT_OVERRUN, ///< Error event: The unread data is replaced by new data. + NRFX_TWIM_EVT_BUS_ERROR ///< Error event: An unexpected transition occurred on the bus. +} nrfx_twim_evt_type_t; + +/** @brief Structure for a TWIM transfer descriptor. */ +typedef struct +{ + nrfx_twim_xfer_type_t type; ///< Type of transfer. + uint8_t address; ///< Slave address. + size_t primary_length; ///< Number of bytes transferred. + size_t secondary_length; ///< Number of bytes transferred. + uint8_t * p_primary_buf; ///< Pointer to transferred data. + uint8_t * p_secondary_buf; ///< Pointer to transferred data. +} nrfx_twim_xfer_desc_t; + +/** @brief Structure for a TWIM event. */ +typedef struct +{ + nrfx_twim_evt_type_t type; ///< Event type. + nrfx_twim_xfer_desc_t xfer_desc; ///< Transfer details. +} nrfx_twim_evt_t; + +/** @brief TWIM event handler prototype. */ +typedef void (* nrfx_twim_evt_handler_t)(nrfx_twim_evt_t const * p_event, + void * p_context); + +// Control block - driver instance local data. +typedef struct +{ + nrfx_twim_evt_handler_t handler; + void * p_context; + volatile uint32_t int_mask; + nrfy_twim_xfer_desc_t xfer_desc_primary; + nrfy_twim_xfer_desc_t xfer_desc_secondary; + uint32_t flags; + nrfx_twim_xfer_type_t xfer_type; + uint8_t address; + nrfx_drv_state_t state; + bool error; + volatile bool busy; + bool repeated; + bool hold_bus_uninit; + bool skip_gpio_cfg; +#if NRFX_CHECK(NRFX_TWIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED) + nrf_twim_frequency_t bus_frequency; +#endif +} twim_control_block_t; + /** @brief Structure for the TWIM driver instance. */ typedef struct { NRF_TWIM_Type * p_twim; ///< Pointer to a structure with TWIM registers. - uint8_t drv_inst_idx; ///< Index of the driver instance. For internal use only. + twim_control_block_t m_cb; } nrfx_twim_t; /** @brief Macro for creating a TWIM driver instance. */ -#define NRFX_TWIM_INSTANCE(id) \ +#define NRFX_TWIM_INSTANCE(reg) \ { \ - .p_twim = NRFX_CONCAT(NRF_, TWIM, id), \ - .drv_inst_idx = NRFX_CONCAT(NRFX_TWIM, id, _INST_IDX), \ + .p_twim = (NRF_TWIM_Type *)reg, \ } #ifndef __NRFX_DOXYGEN__ @@ -129,36 +191,6 @@ typedef struct /** @brief Flag indicating that checks for spurious STOP condition will not be performed. */ #define NRFX_TWIM_FLAG_NO_SPURIOUS_STOP_CHECK (1UL << 6) -/** @brief TWIM driver event types. */ -typedef enum -{ - NRFX_TWIM_EVT_DONE, ///< Transfer completed event. - NRFX_TWIM_EVT_ADDRESS_NACK, ///< Error event: NACK received after sending the address. - NRFX_TWIM_EVT_DATA_NACK, ///< Error event: NACK received after sending a data byte. - NRFX_TWIM_EVT_OVERRUN, ///< Error event: The unread data is replaced by new data. - NRFX_TWIM_EVT_BUS_ERROR ///< Error event: An unexpected transition occurred on the bus. -} nrfx_twim_evt_type_t; - -/** @brief TWIM driver transfer types. */ -typedef enum -{ - NRFX_TWIM_XFER_TX, ///< TX transfer. - NRFX_TWIM_XFER_RX, ///< RX transfer. - NRFX_TWIM_XFER_TXRX, ///< TX transfer followed by RX transfer with repeated start. - NRFX_TWIM_XFER_TXTX ///< TX transfer followed by TX transfer with repeated start. -} nrfx_twim_xfer_type_t; - -/** @brief Structure for a TWIM transfer descriptor. */ -typedef struct -{ - nrfx_twim_xfer_type_t type; ///< Type of transfer. - uint8_t address; ///< Slave address. - size_t primary_length; ///< Number of bytes transferred. - size_t secondary_length; ///< Number of bytes transferred. - uint8_t * p_primary_buf; ///< Pointer to transferred data. - uint8_t * p_secondary_buf; ///< Pointer to transferred data. -} nrfx_twim_xfer_desc_t; - /** @brief Macro for setting the transfer descriptor. */ #define NRFX_TWIM_XFER_DESC(transfer, addr, p_buf1, buf_len1, p_buf2, buf_len2) \ { \ @@ -186,17 +218,6 @@ typedef struct #define NRFX_TWIM_XFER_DESC_TXTX(addr, p_tx, tx_len, p_tx2, tx_len2) \ NRFX_TWIM_XFER_DESC(NRFX_TWIM_XFER_TXTX, addr, p_tx, tx_len, p_tx2, tx_len2) -/** @brief Structure for a TWIM event. */ -typedef struct -{ - nrfx_twim_evt_type_t type; ///< Event type. - nrfx_twim_xfer_desc_t xfer_desc; ///< Transfer details. -} nrfx_twim_evt_t; - -/** @brief TWIM event handler prototype. */ -typedef void (* nrfx_twim_evt_handler_t)(nrfx_twim_evt_t const * p_event, - void * p_context); - /** * @brief Function for initializing the TWIM driver instance. * @@ -218,7 +239,7 @@ typedef void (* nrfx_twim_evt_handler_t)(nrfx_twim_evt_t const * p_event, * possible only if @ref nrfx_prs module * is enabled. */ -nrfx_err_t nrfx_twim_init(nrfx_twim_t const * p_instance, +nrfx_err_t nrfx_twim_init(nrfx_twim_t * p_instance, nrfx_twim_config_t const * p_config, nrfx_twim_evt_handler_t event_handler, void * p_context); @@ -234,7 +255,7 @@ nrfx_err_t nrfx_twim_init(nrfx_twim_t const * p_instance, * @retval NRFX_ERROR_INVALID_STATE The driver is uninitialized. * @retval NRFX_ERROR_INVALID_PARAM Requested frequency is not available on the specified pins. */ -nrfx_err_t nrfx_twim_reconfigure(nrfx_twim_t const * p_instance, +nrfx_err_t nrfx_twim_reconfigure(nrfx_twim_t * p_instance, nrfx_twim_config_t const * p_config); /** @@ -242,7 +263,7 @@ nrfx_err_t nrfx_twim_reconfigure(nrfx_twim_t const * p_instance, * * @param[in] p_instance Pointer to the driver instance structure. */ -void nrfx_twim_uninit(nrfx_twim_t const * p_instance); +void nrfx_twim_uninit(nrfx_twim_t * p_instance); /** * @brief Function for checking if the TWIM driver instance is initialized. @@ -252,21 +273,21 @@ void nrfx_twim_uninit(nrfx_twim_t const * p_instance); * @retval true Instance is already initialized. * @retval false Instance is not initialized. */ -bool nrfx_twim_init_check(nrfx_twim_t const * p_instance); +bool nrfx_twim_init_check(nrfx_twim_t * p_instance); /** * @brief Function for enabling the TWIM instance. * * @param[in] p_instance Pointer to the driver instance structure. */ -void nrfx_twim_enable(nrfx_twim_t const * p_instance); +void nrfx_twim_enable(nrfx_twim_t * p_instance); /** * @brief Function for disabling the TWIM instance. * * @param[in] p_instance Pointer to the driver instance structure. */ -void nrfx_twim_disable(nrfx_twim_t const * p_instance); +void nrfx_twim_disable(nrfx_twim_t * p_instance); /** * @brief Function for performing a TWIM transfer. @@ -323,7 +344,7 @@ void nrfx_twim_disable(nrfx_twim_t const * p_instance); * @retval NRFX_ERROR_DRV_TWI_ERR_ANACK NACK is received after sending the address. * @retval NRFX_ERROR_DRV_TWI_ERR_DNACK NACK is received after sending a data byte. */ -nrfx_err_t nrfx_twim_xfer(nrfx_twim_t const * p_instance, +nrfx_err_t nrfx_twim_xfer(nrfx_twim_t * p_instance, nrfx_twim_xfer_desc_t const * p_xfer_desc, uint32_t flags); @@ -335,7 +356,7 @@ nrfx_err_t nrfx_twim_xfer(nrfx_twim_t const * p_instance, * @retval true The TWIM driver is currently busy performing a transfer. * @retval false The TWIM driver is ready for a new transfer. */ -bool nrfx_twim_is_busy(nrfx_twim_t const * p_instance); +bool nrfx_twim_is_busy(nrfx_twim_t * p_instance); /** @@ -349,7 +370,7 @@ bool nrfx_twim_is_busy(nrfx_twim_t const * p_instance); * * @return Start task address (TX or RX) depending on the value of xfer_type. */ -uint32_t nrfx_twim_start_task_address_get(nrfx_twim_t const * p_instance, +uint32_t nrfx_twim_start_task_address_get(nrfx_twim_t * p_instance, nrfx_twim_xfer_type_t xfer_type); /** @@ -362,7 +383,7 @@ uint32_t nrfx_twim_start_task_address_get(nrfx_twim_t const * p_instance, * * @return STOPPED event address. */ -uint32_t nrfx_twim_stopped_event_address_get(nrfx_twim_t const * p_instance); +uint32_t nrfx_twim_stopped_event_address_get(nrfx_twim_t * p_instance); /** * @brief Function for recovering the bus. @@ -388,32 +409,7 @@ NRFX_STATIC_INLINE nrfx_err_t nrfx_twim_bus_recover(uint32_t scl_pin, uint32_t s } #endif -/** - * @brief Macro returning TWIM interrupt handler. - * - * param[in] idx TWIM index. - * - * @return Interrupt handler. - */ -#define NRFX_TWIM_INST_HANDLER_GET(idx) NRFX_CONCAT_3(nrfx_twim_, idx, _irq_handler) - -/** @} */ - -/* - * Declare interrupt handlers for all enabled driver instances in the following format: - * nrfx_\_\_irq_handler (for example, nrfx_twim_0_irq_handler). - * - * A specific interrupt handler for the driver instance can be retrieved by using - * the NRFX_TWIM_INST_HANDLER_GET macro. - * - * Here is a sample of using the NRFX_TWIM_INST_HANDLER_GET macro to map an interrupt handler - * in a Zephyr application: - * - * IRQ_CONNECT(NRFX_IRQ_NUMBER_GET(NRF_TWIM_INST_GET(\)), \, - * NRFX_TWIM_INST_HANDLER_GET(\), 0, 0); - */ -NRFX_INSTANCE_IRQ_HANDLERS_DECLARE(TWIM, twim) - +void nrfx_twim_irq_handler(nrfx_twim_t * p_instance); #ifdef __cplusplus } diff --git a/nrfx/drivers/src/nrfx_twim.c b/nrfx/drivers/src/nrfx_twim.c index c5038677..3449aca2 100644 --- a/nrfx/drivers/src/nrfx_twim.c +++ b/nrfx/drivers/src/nrfx_twim.c @@ -35,10 +35,6 @@ #if NRFX_CHECK(NRFX_TWIM_ENABLED) -#if !NRFX_FEATURE_PRESENT(NRFX_TWIM, _ENABLED) -#error "No enabled TWIM instances. Check ." -#endif - #include #include #include "prs/nrfx_prs.h" @@ -92,30 +88,6 @@ #define USE_WORKAROUND_FOR_TWIM_FREQ_ANOMALY 0 #endif -// Control block - driver instance local data. -typedef struct -{ - nrfx_twim_evt_handler_t handler; - void * p_context; - volatile uint32_t int_mask; - nrfy_twim_xfer_desc_t xfer_desc_primary; - nrfy_twim_xfer_desc_t xfer_desc_secondary; - uint32_t flags; - nrfx_twim_xfer_type_t xfer_type; - uint8_t address; - nrfx_drv_state_t state; - bool error; - volatile bool busy; - bool repeated; - bool hold_bus_uninit; - bool skip_gpio_cfg; -#if NRFX_CHECK(NRFX_TWIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED) - nrf_twim_frequency_t bus_frequency; -#endif -} twim_control_block_t; - -static twim_control_block_t m_cb[NRFX_TWIM_ENABLED_COUNT]; - static nrfx_err_t twi_process_error(uint32_t errorsrc) { nrfx_err_t ret = NRFX_ERROR_INTERNAL; @@ -138,7 +110,7 @@ static nrfx_err_t twi_process_error(uint32_t errorsrc) return ret; } -static bool xfer_completeness_check(NRF_TWIM_Type * p_twim, twim_control_block_t const * p_cb) +static bool xfer_completeness_check(NRF_TWIM_Type * p_twim, twim_control_block_t * p_cb) { // If the actual number of transferred bytes is not equal to what was requested, // but there was no error signaled by the peripheral, this means that something @@ -193,7 +165,7 @@ static bool xfer_completeness_check(NRF_TWIM_Type * p_twim, twim_control_block_t return transfer_complete; } -static void twim_configure(nrfx_twim_t const * p_instance, +static void twim_configure(nrfx_twim_t * p_instance, nrfx_twim_config_t const * p_config) { nrfy_twim_config_t nrfy_config = @@ -215,7 +187,7 @@ static void twim_configure(nrfx_twim_t const * p_instance, #endif nrfy_twim_periph_configure(p_instance->p_twim, &nrfy_config); - if (m_cb[p_instance->drv_inst_idx].handler) + if (p_instance->m_cb.handler) { nrfy_twim_int_init(p_instance->p_twim, 0, p_config->interrupt_priority, false); } @@ -275,14 +247,14 @@ static bool pins_configure(nrfx_twim_config_t const * p_config) return true; } -nrfx_err_t nrfx_twim_init(nrfx_twim_t const * p_instance, +nrfx_err_t nrfx_twim_init(nrfx_twim_t * p_instance, nrfx_twim_config_t const * p_config, nrfx_twim_evt_handler_t event_handler, void * p_context) { NRFX_ASSERT(p_config); - twim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; + twim_control_block_t * p_cb = &p_instance->m_cb; nrfx_err_t err_code; if (p_cb->state != NRFX_DRV_STATE_UNINITIALIZED) @@ -299,6 +271,7 @@ nrfx_err_t nrfx_twim_init(nrfx_twim_t const * p_instance, } #if NRFX_CHECK(NRFX_PRS_ENABLED) + /* FIXME */ static nrfx_irq_handler_t const irq_handlers[NRFX_TWIM_ENABLED_COUNT] = { NRFX_INSTANCE_IRQ_HANDLERS_LIST(TWIM, twim) }; @@ -345,12 +318,12 @@ nrfx_err_t nrfx_twim_init(nrfx_twim_t const * p_instance, return err_code; } -nrfx_err_t nrfx_twim_reconfigure(nrfx_twim_t const * p_instance, +nrfx_err_t nrfx_twim_reconfigure(nrfx_twim_t * p_instance, nrfx_twim_config_t const * p_config) { NRFX_ASSERT(p_config); - twim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; + twim_control_block_t * p_cb = &p_instance->m_cb; if (p_cb->state == NRFX_DRV_STATE_UNINITIALIZED) { @@ -375,9 +348,9 @@ nrfx_err_t nrfx_twim_reconfigure(nrfx_twim_t const * p_instance, return err_code; } -void nrfx_twim_uninit(nrfx_twim_t const * p_instance) +void nrfx_twim_uninit(nrfx_twim_t * p_instance) { - twim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; + twim_control_block_t * p_cb = &p_instance->m_cb; NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED); @@ -398,30 +371,30 @@ void nrfx_twim_uninit(nrfx_twim_t const * p_instance) } p_cb->state = NRFX_DRV_STATE_UNINITIALIZED; - NRFX_LOG_INFO("Instance uninitialized: %d.", p_instance->drv_inst_idx); + NRFX_LOG_INFO("Instance uninitialized: %p.", p_instance->p_twim); } -bool nrfx_twim_init_check(nrfx_twim_t const * p_instance) +bool nrfx_twim_init_check(nrfx_twim_t * p_instance) { - twim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; + twim_control_block_t * p_cb = &p_instance->m_cb; return (p_cb->state != NRFX_DRV_STATE_UNINITIALIZED); } -void nrfx_twim_enable(nrfx_twim_t const * p_instance) +void nrfx_twim_enable(nrfx_twim_t * p_instance) { - twim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; + twim_control_block_t * p_cb = &p_instance->m_cb; NRFX_ASSERT(p_cb->state == NRFX_DRV_STATE_INITIALIZED); nrfy_twim_enable(p_instance->p_twim); p_cb->state = NRFX_DRV_STATE_POWERED_ON; - NRFX_LOG_INFO("Instance enabled: %d.", p_instance->drv_inst_idx); + NRFX_LOG_INFO("Instance enabled: %p.", p_instance->p_twim); } -void nrfx_twim_disable(nrfx_twim_t const * p_instance) +void nrfx_twim_disable(nrfx_twim_t * p_instance) { - twim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; + twim_control_block_t * p_cb = &p_instance->m_cb; NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED); @@ -429,12 +402,12 @@ void nrfx_twim_disable(nrfx_twim_t const * p_instance) nrfy_twim_stop(p_instance->p_twim); p_cb->state = NRFX_DRV_STATE_INITIALIZED; p_cb->busy = false; - NRFX_LOG_INFO("Instance disabled: %d.", p_instance->drv_inst_idx); + NRFX_LOG_INFO("Instance disabled: %p.", p_instance->p_twim); } -bool nrfx_twim_is_busy(nrfx_twim_t const * p_instance) +bool nrfx_twim_is_busy(nrfx_twim_t * p_instance) { - twim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; + twim_control_block_t * p_cb = &p_instance->m_cb; return p_cb->busy; } @@ -651,15 +624,16 @@ static nrfx_err_t twim_xfer(twim_control_block_t * p_cb, } -nrfx_err_t nrfx_twim_xfer(nrfx_twim_t const * p_instance, +nrfx_err_t nrfx_twim_xfer(nrfx_twim_t * p_instance, nrfx_twim_xfer_desc_t const * p_xfer_desc, uint32_t flags) { - NRFX_ASSERT(TWIM_LENGTH_VALIDATE(p_instance->drv_inst_idx, - p_xfer_desc->primary_length, - p_xfer_desc->secondary_length)); + /* FIXME */ + /*NRFX_ASSERT(TWIM_LENGTH_VALIDATE(p_instance->drv_inst_idx,*/ + /*p_xfer_desc->primary_length,*/ + /*p_xfer_desc->secondary_length));*/ - twim_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; + twim_control_block_t * p_cb = &p_instance->m_cb; NRFX_ASSERT(p_cb->state == NRFX_DRV_STATE_POWERED_ON); @@ -683,24 +657,27 @@ nrfx_err_t nrfx_twim_xfer(nrfx_twim_t const * p_instance, return twim_xfer(p_cb, p_instance->p_twim, p_xfer_desc, flags); } -uint32_t nrfx_twim_start_task_address_get(nrfx_twim_t const * p_instance, +uint32_t nrfx_twim_start_task_address_get(nrfx_twim_t * p_instance, nrfx_twim_xfer_type_t xfer_type) { - NRFX_ASSERT(m_cb[p_instance->drv_inst_idx].state != NRFX_DRV_STATE_UNINITIALIZED); + NRFX_ASSERT(p_instance->m_cb.state != NRFX_DRV_STATE_UNINITIALIZED); return nrfy_twim_task_address_get(p_instance->p_twim, (xfer_type != NRFX_TWIM_XFER_RX) ? NRF_TWIM_TASK_STARTTX : NRF_TWIM_TASK_STARTRX); } -uint32_t nrfx_twim_stopped_event_address_get(nrfx_twim_t const * p_instance) +uint32_t nrfx_twim_stopped_event_address_get(nrfx_twim_t * p_instance) { - NRFX_ASSERT(m_cb[p_instance->drv_inst_idx].state != NRFX_DRV_STATE_UNINITIALIZED); + NRFX_ASSERT(p_instance->m_cb.state != NRFX_DRV_STATE_UNINITIALIZED); return nrfy_twim_event_address_get(p_instance->p_twim, NRF_TWIM_EVENT_STOPPED); } -static void irq_handler(NRF_TWIM_Type * p_twim, twim_control_block_t * p_cb) +void nrfx_twim_irq_handler(nrfx_twim_t * p_instance) { + NRF_TWIM_Type * p_twim = p_instance->p_twim; + twim_control_block_t * p_cb = &p_instance->m_cb; + nrfy_twim_xfer_desc_t * p_xfer = p_cb->xfer_type == NRFX_TWIM_XFER_RX ? &p_cb->xfer_desc_primary : &p_cb->xfer_desc_secondary; @@ -895,6 +872,4 @@ static void irq_handler(NRF_TWIM_Type * p_twim, twim_control_block_t * p_cb) } } -NRFX_INSTANCE_IRQ_HANDLERS(TWIM, twim) - #endif // NRFX_CHECK(NRFX_TWIM_ENABLED)