示例#1
0
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);
}
示例#2
0
/**
 * @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);
}
示例#3
0
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);
}
示例#4
0
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);
}
示例#5
0
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;
}