void i2c_transfer_asynch(i2c_t *obj, const void *tx, size_t tx_length, void *rx, size_t rx_length, uint32_t address, uint32_t stop, uint32_t handler, uint32_t event, DMAUsage hint) { (void)hint; twi_info_t *twi_info = TWI_INFO(obj); if (twi_info->active) { return; } twi_info->active = true; twi_info->events = 0; twi_info->handler = (void (*)(void))handler; twi_info->evt_mask = event; twi_info->tx_length = tx_length; twi_info->tx = tx; twi_info->rx_length = rx_length; twi_info->rx = rx; twi_info->stop = stop; NRF_TWI_Type *twi = m_twi_instances[TWI_IDX(obj)]; nrf_twi_event_clear(twi, NRF_TWI_EVENT_TXDSENT); nrf_twi_event_clear(twi, NRF_TWI_EVENT_RXDREADY); nrf_twi_event_clear(twi, NRF_TWI_EVENT_STOPPED); nrf_twi_event_clear(twi, NRF_TWI_EVENT_SUSPENDED); nrf_twi_event_clear(twi, NRF_TWI_EVENT_ERROR); (void)nrf_twi_errorsrc_get_and_clear(twi); nrf_twi_address_set(twi, twi_address(address)); nrf_twi_task_trigger(twi, NRF_TWI_TASK_RESUME); // TX only, or TX + RX (after a repeated start). if (tx_length > 0) { nrf_twi_task_trigger(twi, NRF_TWI_TASK_STARTTX); nrf_twi_txd_set(twi, *(twi_info->tx)); ++(twi_info->tx); // RX only. } else if (rx_length > 0) { start_asynch_rx(twi_info, twi); // Both 'tx_length' and 'rx_length' are 0 - this case may be used // to test if the slave is presentand ready for transfer (by just // sending the address and checking if it is acknowledged). } else { nrf_twi_task_trigger(twi, NRF_TWI_TASK_STARTTX); if (stop) { nrf_twi_task_trigger(twi, NRF_TWI_TASK_STOP); } else { nrf_twi_task_trigger(twi, NRF_TWI_TASK_SUSPEND); nrf_twi_int_enable(twi, NRF_TWI_INT_SUSPENDED_MASK); } twi_info->events |= I2C_EVENT_TRANSFER_COMPLETE; } nrf_twi_int_enable(twi, NRF_TWI_INT_TXDSENT_MASK | NRF_TWI_INT_RXDREADY_MASK | NRF_TWI_INT_STOPPED_MASK | NRF_TWI_INT_ERROR_MASK); }
/** * @brief Function for prepering shortcut register. * * @param[in] p_instance TWI. */ static void txrx_shorts_set_task_start(volatile nrf_drv_twi_t const * const p_instance) { uint32_t short_mask; volatile transfer_t * p_transfer = &(m_cb[p_instance->instance_id].transfer); nrf_twi_shorts_clear(p_instance->p_reg, NRF_TWI_SHORTS_BB_SUSPEND_MASK | NRF_TWI_SHORTS_BB_STOP_MASK); // if the last one and no pending transfer prepare to wait for stopped event if (((p_transfer->count + 1) == p_transfer->length) && p_transfer->xfer_pending == false) { short_mask = NRF_TWI_SHORTS_BB_STOP_MASK; p_transfer->end_event = NRF_TWI_EVENTS_STOPPED; nrf_twi_event_clear(p_instance->p_reg, p_transfer->end_event); if (m_handlers[p_instance->instance_id]) { nrf_twi_int_disable(p_instance->p_reg, p_transfer->end_int); p_transfer->end_int = NRF_TWI_INT_STOPPED_MASK; nrf_twi_int_enable(p_instance->p_reg, p_transfer->end_int); } state_machine(p_instance, TO_STOP); } else { short_mask = NRF_TWI_SHORTS_BB_SUSPEND_MASK; } nrf_twi_shorts_set(p_instance->p_reg, short_mask); nrf_twi_tasks_t prev_task = p_transfer->task; p_transfer->task = NRF_TWI_TASKS_RESUME; nrf_twi_task_set(p_instance->p_reg, prev_task); }
static void on_error(volatile nrf_drv_twi_t const * const p_instance) { volatile transfer_t * p_transfer = &(m_cb[p_instance->instance_id].transfer); p_transfer->end_event = NRF_TWI_EVENTS_STOPPED; nrf_twi_event_clear(p_instance->p_reg, p_transfer->end_event); if (m_handlers[p_instance->instance_id]) { nrf_twi_int_disable(p_instance->p_reg, p_transfer->end_int); p_transfer->end_int = NRF_TWI_INT_STOPPED_MASK; nrf_twi_int_enable(p_instance->p_reg, p_transfer->end_int); } nrf_twi_task_set(p_instance->p_reg, NRF_TWI_TASKS_RESUME); nrf_twi_task_set(p_instance->p_reg, NRF_TWI_TASKS_STOP); }
static void rx_address_req(volatile nrf_drv_twi_t const * const p_instance) { volatile transfer_t * p_transfer = &(m_cb[p_instance->instance_id].transfer); nrf_twi_address_set(p_instance->p_reg, p_transfer->address); p_transfer->task = NRF_TWI_TASKS_STARTRX; p_transfer->end_event = NRF_TWI_EVENTS_RXDREADY; nrf_twi_event_clear(p_instance->p_reg, p_transfer->end_event); if (m_handlers[p_instance->instance_id]) { nrf_twi_int_disable(p_instance->p_reg, p_transfer->end_int); p_transfer->end_int = NRF_TWI_INT_RXDREADY_MASK; nrf_twi_int_enable(p_instance->p_reg, p_transfer->end_int); } rx_prepare(p_instance); }
void nrf_drv_twi_enable(nrf_drv_twi_t const * const p_instance) { ASSERT(m_cb[p_instance->instance_id].state == NRF_DRV_STATE_INITIALIZED); nrf_twi_event_clear(p_instance->p_reg, NRF_TWI_EVENTS_STOPPED); nrf_twi_event_clear(p_instance->p_reg, NRF_TWI_EVENTS_RXDREADY); nrf_twi_event_clear(p_instance->p_reg, NRF_TWI_EVENTS_TXDSENT); nrf_twi_event_clear(p_instance->p_reg, NRF_TWI_EVENTS_ERROR); if (m_handlers[p_instance->instance_id]) { nrf_twi_int_enable(p_instance->p_reg, NRF_TWI_INT_ERROR_MASK); } nrf_twi_enable(p_instance->p_reg); m_cb[p_instance->instance_id].state = NRF_DRV_STATE_POWERED_ON; m_cb[p_instance->instance_id].substate = NRF_DRV_TWI_SUBSTATE_IDLE; }