static int transceive(struct device *dev, const struct spi_config *spi_cfg, const struct spi_buf_set *tx_bufs, const struct spi_buf_set *rx_bufs) { struct spi_nrfx_data *dev_data = get_dev_data(dev); int error; error = configure(dev, spi_cfg); if (error != 0) { /* Invalid configuration. */ } else if ((tx_bufs && tx_bufs->count > 1) || (rx_bufs && rx_bufs->count > 1)) { LOG_ERR("Scattered buffers are not supported"); error = -ENOTSUP; } else if (tx_bufs && tx_bufs->buffers[0].len && !nrfx_is_in_ram(tx_bufs->buffers[0].buf)) { LOG_ERR("Only buffers located in RAM are supported"); error = -ENOTSUP; } else { spi_context_buffers_setup(&dev_data->ctx, tx_bufs, rx_bufs, 1); prepare_for_transfer(dev); error = spi_context_wait_for_completion(&dev_data->ctx); } spi_context_release(&dev_data->ctx, error); return error; }
nrfx_err_t nrfx_i2s_next_buffers_set(nrfx_i2s_buffers_t const * p_buffers) { NRFX_ASSERT(m_cb.state == NRFX_DRV_STATE_POWERED_ON); NRFX_ASSERT(p_buffers); nrfx_err_t err_code; if (!m_cb.buffers_needed) { err_code = NRFX_ERROR_INVALID_STATE; NRFX_LOG_WARNING("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); return err_code; } if (((p_buffers->p_rx_buffer != NULL) && !nrfx_is_in_ram(p_buffers->p_rx_buffer)) || ((p_buffers->p_tx_buffer != NULL) && !nrfx_is_in_ram(p_buffers->p_tx_buffer))) { err_code = NRFX_ERROR_INVALID_ADDR; NRFX_LOG_WARNING("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); return err_code; } if (m_cb.use_tx) { NRFX_ASSERT(p_buffers->p_tx_buffer != NULL); nrf_i2s_tx_buffer_set(NRF_I2S, p_buffers->p_tx_buffer); } if (m_cb.use_rx) { NRFX_ASSERT(p_buffers->p_rx_buffer != NULL); nrf_i2s_rx_buffer_set(NRF_I2S, p_buffers->p_rx_buffer); } m_cb.next_buffers = *p_buffers; m_cb.buffers_needed = false; return NRFX_SUCCESS; }
uint32_t nrfx_pwm_complex_playback(nrfx_pwm_t const * const p_instance, nrf_pwm_sequence_t const * p_sequence_0, nrf_pwm_sequence_t const * p_sequence_1, uint16_t playback_count, uint32_t flags) { pwm_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED); NRFX_ASSERT(playback_count > 0); NRFX_ASSERT(nrfx_is_in_ram(p_sequence_0->values.p_raw)); NRFX_ASSERT(nrfx_is_in_ram(p_sequence_1->values.p_raw)); nrf_pwm_sequence_set(p_instance->p_registers, 0, p_sequence_0); nrf_pwm_sequence_set(p_instance->p_registers, 1, p_sequence_1); nrf_pwm_loop_set(p_instance->p_registers, playback_count); uint32_t shorts_mask; if (flags & NRFX_PWM_FLAG_STOP) { shorts_mask = NRF_PWM_SHORT_LOOPSDONE_STOP_MASK; } else if (flags & NRFX_PWM_FLAG_LOOP) { shorts_mask = NRF_PWM_SHORT_LOOPSDONE_SEQSTART0_MASK; } else { shorts_mask = 0; } nrf_pwm_shorts_set(p_instance->p_registers, shorts_mask); NRFX_LOG_INFO("Function: %s, sequence 0 length: %d.", __func__, p_sequence_0->length); NRFX_LOG_INFO("Function: %s, sequence 1 length: %d.", __func__, p_sequence_1->length); NRFX_LOG_DEBUG("Sequence 0 data:"); NRFX_LOG_HEXDUMP_DEBUG(p_sequence_0->values.p_raw, p_sequence_0->length * sizeof(uint16_t)); NRFX_LOG_DEBUG("Sequence 1 data:"); NRFX_LOG_HEXDUMP_DEBUG(p_sequence_1->values.p_raw, p_sequence_1->length * sizeof(uint16_t)); return start_playback(p_instance, p_cb, flags, NRF_PWM_TASK_SEQSTART0); }
uint32_t nrfx_pwm_simple_playback(nrfx_pwm_t const * const p_instance, nrf_pwm_sequence_t const * p_sequence, uint16_t playback_count, uint32_t flags) { pwm_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED); NRFX_ASSERT(playback_count > 0); NRFX_ASSERT(nrfx_is_in_ram(p_sequence->values.p_raw)); // To take advantage of the looping mechanism, we need to use both sequences // (single sequence can be played back only once). nrf_pwm_sequence_set(p_instance->p_registers, 0, p_sequence); nrf_pwm_sequence_set(p_instance->p_registers, 1, p_sequence); bool odd = (playback_count & 1); nrf_pwm_loop_set(p_instance->p_registers, (playback_count / 2) + (odd ? 1 : 0)); uint32_t shorts_mask; if (flags & NRFX_PWM_FLAG_STOP) { shorts_mask = NRF_PWM_SHORT_LOOPSDONE_STOP_MASK; } else if (flags & NRFX_PWM_FLAG_LOOP) { shorts_mask = odd ? NRF_PWM_SHORT_LOOPSDONE_SEQSTART1_MASK : NRF_PWM_SHORT_LOOPSDONE_SEQSTART0_MASK; } else { shorts_mask = 0; } nrf_pwm_shorts_set(p_instance->p_registers, shorts_mask); NRFX_LOG_INFO("Function: %s, sequence length: %d.", __func__, p_sequence->length); NRFX_LOG_DEBUG("Sequence data:"); NRFX_LOG_HEXDUMP_DEBUG((uint8_t *)p_sequence->values.p_raw, p_sequence->length * sizeof(uint16_t)); return start_playback(p_instance, p_cb, flags, odd ? NRF_PWM_TASK_SEQSTART1 : NRF_PWM_TASK_SEQSTART0); }
nrfx_err_t nrfx_uarte_rx(nrfx_uarte_t const * p_instance, uint8_t * p_data, size_t length) { uarte_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; NRFX_ASSERT(m_cb[p_instance->drv_inst_idx].state == NRFX_DRV_STATE_INITIALIZED); NRFX_ASSERT(p_data); NRFX_ASSERT(length > 0); NRFX_ASSERT(UARTE_LENGTH_VALIDATE(p_instance->drv_inst_idx, length)); nrfx_err_t err_code; // EasyDMA requires that transfer buffers are placed in DataRAM, // signal error if the are not. if (!nrfx_is_in_ram(p_data)) { err_code = NRFX_ERROR_INVALID_ADDR; NRFX_LOG_WARNING("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); return err_code; } bool second_buffer = false; if (p_cb->handler) { nrf_uarte_int_disable(p_instance->p_reg, NRF_UARTE_INT_ERROR_MASK | NRF_UARTE_INT_ENDRX_MASK); } if (p_cb->rx_buffer_length != 0) { if (p_cb->rx_secondary_buffer_length != 0) { if (p_cb->handler) { nrf_uarte_int_enable(p_instance->p_reg, NRF_UARTE_INT_ERROR_MASK | NRF_UARTE_INT_ENDRX_MASK); } err_code = NRFX_ERROR_BUSY; NRFX_LOG_WARNING("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); return err_code; } second_buffer = true; } if (!second_buffer) { p_cb->rx_buffer_length = length; p_cb->p_rx_buffer = p_data; p_cb->rx_secondary_buffer_length = 0; } else { p_cb->p_rx_secondary_buffer = p_data; p_cb->rx_secondary_buffer_length = length; } NRFX_LOG_INFO("Transfer rx_len: %d.", length); err_code = NRFX_SUCCESS; nrf_uarte_event_clear(p_instance->p_reg, NRF_UARTE_EVENT_ENDRX); nrf_uarte_event_clear(p_instance->p_reg, NRF_UARTE_EVENT_RXTO); nrf_uarte_rx_buffer_set(p_instance->p_reg, p_data, length); if (!second_buffer) { nrf_uarte_task_trigger(p_instance->p_reg, NRF_UARTE_TASK_STARTRX); } else { nrf_uarte_shorts_enable(p_instance->p_reg, NRF_UARTE_SHORT_ENDRX_STARTRX); } if (m_cb[p_instance->drv_inst_idx].handler == NULL) { bool endrx; bool rxto; bool error; do { endrx = nrf_uarte_event_check(p_instance->p_reg, NRF_UARTE_EVENT_ENDRX); rxto = nrf_uarte_event_check(p_instance->p_reg, NRF_UARTE_EVENT_RXTO); error = nrf_uarte_event_check(p_instance->p_reg, NRF_UARTE_EVENT_ERROR); } while ((!endrx) && (!rxto) && (!error)); m_cb[p_instance->drv_inst_idx].rx_buffer_length = 0; if (error) { err_code = NRFX_ERROR_INTERNAL; } if (rxto) { err_code = NRFX_ERROR_FORBIDDEN; } } else { nrf_uarte_int_enable(p_instance->p_reg, NRF_UARTE_INT_ERROR_MASK | NRF_UARTE_INT_ENDRX_MASK); } NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); return err_code; }
nrfx_err_t nrfx_uarte_tx(nrfx_uarte_t const * p_instance, uint8_t const * p_data, size_t length) { uarte_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; NRFX_ASSERT(p_cb->state == NRFX_DRV_STATE_INITIALIZED); NRFX_ASSERT(p_data); NRFX_ASSERT(length > 0); NRFX_ASSERT(UARTE_LENGTH_VALIDATE(p_instance->drv_inst_idx, length)); nrfx_err_t err_code; // EasyDMA requires that transfer buffers are placed in DataRAM, // signal error if the are not. if (!nrfx_is_in_ram(p_data)) { err_code = NRFX_ERROR_INVALID_ADDR; NRFX_LOG_WARNING("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); return err_code; } if (nrfx_uarte_tx_in_progress(p_instance)) { err_code = NRFX_ERROR_BUSY; NRFX_LOG_WARNING("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); return err_code; } p_cb->tx_buffer_length = length; p_cb->p_tx_buffer = p_data; NRFX_LOG_INFO("Transfer tx_len: %d.", p_cb->tx_buffer_length); NRFX_LOG_DEBUG("Tx data:"); NRFX_LOG_HEXDUMP_DEBUG(p_cb->p_tx_buffer, p_cb->tx_buffer_length * sizeof(p_cb->p_tx_buffer[0])); err_code = NRFX_SUCCESS; nrf_uarte_event_clear(p_instance->p_reg, NRF_UARTE_EVENT_ENDTX); nrf_uarte_event_clear(p_instance->p_reg, NRF_UARTE_EVENT_TXSTOPPED); nrf_uarte_tx_buffer_set(p_instance->p_reg, p_cb->p_tx_buffer, p_cb->tx_buffer_length); nrf_uarte_task_trigger(p_instance->p_reg, NRF_UARTE_TASK_STARTTX); if (p_cb->handler == NULL) { bool endtx; bool txstopped; do { endtx = nrf_uarte_event_check(p_instance->p_reg, NRF_UARTE_EVENT_ENDTX); txstopped = nrf_uarte_event_check(p_instance->p_reg, NRF_UARTE_EVENT_TXSTOPPED); } while ((!endtx) && (!txstopped)); if (txstopped) { err_code = NRFX_ERROR_FORBIDDEN; } p_cb->tx_buffer_length = 0; } NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); return err_code; }
__STATIC_INLINE nrfx_err_t twim_xfer(twim_control_block_t * p_cb, NRF_TWIM_Type * p_twim, nrfx_twim_xfer_desc_t const * p_xfer_desc, uint32_t flags) { nrfx_err_t err_code = NRFX_SUCCESS; nrf_twim_task_t start_task = NRF_TWIM_TASK_STARTTX; nrf_twim_event_t evt_to_wait = NRF_TWIM_EVENT_STOPPED; if (!nrfx_is_in_ram(p_xfer_desc->p_primary_buf)) { err_code = NRFX_ERROR_INVALID_ADDR; NRFX_LOG_WARNING("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); return err_code; } /* Block TWI interrupts to ensure that function is not interrupted by TWI interrupt. */ nrf_twim_int_disable(p_twim, NRF_TWIM_ALL_INTS_MASK); if (p_cb->busy) { nrf_twim_int_enable(p_twim, p_cb->int_mask); err_code = NRFX_ERROR_BUSY; NRFX_LOG_WARNING("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); return err_code; } else { p_cb->busy = ((NRFX_TWIM_FLAG_NO_XFER_EVT_HANDLER & flags) || (NRFX_TWIM_FLAG_REPEATED_XFER & flags)) ? false: true; } p_cb->xfer_desc = *p_xfer_desc; p_cb->repeated = (flags & NRFX_TWIM_FLAG_REPEATED_XFER) ? true : false; nrf_twim_address_set(p_twim, p_xfer_desc->address); nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_STOPPED); nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_ERROR); twim_list_enable_handle(p_twim, flags); switch (p_xfer_desc->type) { case NRFX_TWIM_XFER_TXTX: NRFX_ASSERT(!(flags & NRFX_TWIM_FLAG_REPEATED_XFER)); NRFX_ASSERT(!(flags & NRFX_TWIM_FLAG_HOLD_XFER)); NRFX_ASSERT(!(flags & NRFX_TWIM_FLAG_NO_XFER_EVT_HANDLER)); if (!nrfx_is_in_ram(p_xfer_desc->p_secondary_buf)) { err_code = NRFX_ERROR_INVALID_ADDR; NRFX_LOG_WARNING("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); return err_code; } nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTTX_SUSPEND_MASK); nrf_twim_tx_buffer_set(p_twim, p_xfer_desc->p_primary_buf, p_xfer_desc->primary_length); nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_TXSTARTED); nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_LASTTX); nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_SUSPENDED); nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME); nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_STARTTX); while (!nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_TXSTARTED)) {} NRFX_LOG_DEBUG("TWIM: Event: %s.", EVT_TO_STR_TWIM(NRF_TWIM_EVENT_TXSTARTED)); nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_TXSTARTED); nrf_twim_tx_buffer_set(p_twim, p_xfer_desc->p_secondary_buf, p_xfer_desc->secondary_length); p_cb->int_mask = NRF_TWIM_INT_SUSPENDED_MASK | NRF_TWIM_INT_ERROR_MASK; break; case NRFX_TWIM_XFER_TXRX: nrf_twim_tx_buffer_set(p_twim, p_xfer_desc->p_primary_buf, p_xfer_desc->primary_length); if (!nrfx_is_in_ram(p_xfer_desc->p_secondary_buf)) { err_code = NRFX_ERROR_INVALID_ADDR; NRFX_LOG_WARNING("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); return err_code; } nrf_twim_rx_buffer_set(p_twim, p_xfer_desc->p_secondary_buf, p_xfer_desc->secondary_length); nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTTX_STARTRX_MASK | NRF_TWIM_SHORT_LASTRX_STOP_MASK); p_cb->int_mask = NRF_TWIM_INT_STOPPED_MASK | NRF_TWIM_INT_ERROR_MASK; break; case NRFX_TWIM_XFER_TX: nrf_twim_tx_buffer_set(p_twim, p_xfer_desc->p_primary_buf, p_xfer_desc->primary_length); if (NRFX_TWIM_FLAG_TX_NO_STOP & flags) { nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTTX_SUSPEND_MASK); p_cb->int_mask = NRF_TWIM_INT_SUSPENDED_MASK | NRF_TWIM_INT_ERROR_MASK; nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_SUSPENDED); evt_to_wait = NRF_TWIM_EVENT_SUSPENDED; } else { nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTTX_STOP_MASK); p_cb->int_mask = NRF_TWIM_INT_STOPPED_MASK | NRF_TWIM_INT_ERROR_MASK; } nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME); break; case NRFX_TWIM_XFER_RX: nrf_twim_rx_buffer_set(p_twim, p_xfer_desc->p_primary_buf, p_xfer_desc->primary_length); nrf_twim_shorts_set(p_twim, NRF_TWIM_SHORT_LASTRX_STOP_MASK); p_cb->int_mask = NRF_TWIM_INT_STOPPED_MASK | NRF_TWIM_INT_ERROR_MASK; start_task = NRF_TWIM_TASK_STARTRX; nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME); break; default: err_code = NRFX_ERROR_INVALID_PARAM; break; } if (!(flags & NRFX_TWIM_FLAG_HOLD_XFER) && (p_xfer_desc->type != NRFX_TWIM_XFER_TXTX)) { nrf_twim_task_trigger(p_twim, start_task); } if (p_cb->handler) { if (flags & NRFX_TWIM_FLAG_NO_XFER_EVT_HANDLER) { p_cb->int_mask = NRF_TWIM_INT_ERROR_MASK; } nrf_twim_int_enable(p_twim, p_cb->int_mask); #if NRFX_CHECK(NRFX_TWIM_NRF52_ANOMALY_109_WORKAROUND_ENABLED) if ((flags & NRFX_TWIM_FLAG_HOLD_XFER) && ((p_xfer_desc->type == NRFX_TWIM_XFER_TX) || (p_xfer_desc->type == NRFX_TWIM_XFER_TXRX))) { p_cb->flags = flags; twim_list_enable_handle(p_twim, 0); p_twim->FREQUENCY = 0; nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_TXSTARTED); nrf_twim_int_enable(p_twim, NRF_TWIM_INT_TXSTARTED_MASK); } #endif } else { while (!nrf_twim_event_check(p_twim, evt_to_wait)) { if (nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_ERROR)) { NRFX_LOG_DEBUG("TWIM: Event: %s.", EVT_TO_STR_TWIM(NRF_TWIM_EVENT_ERROR)); nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_ERROR); nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME); nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_STOP); evt_to_wait = NRF_TWIM_EVENT_STOPPED; } } uint32_t errorsrc = nrf_twim_errorsrc_get_and_clear(p_twim); p_cb->busy = false; if (errorsrc) { err_code = twi_process_error(errorsrc); } } return err_code; }
nrfx_err_t nrfx_i2s_start(nrfx_i2s_buffers_t const * p_initial_buffers, uint16_t buffer_size, uint8_t flags) { NRFX_ASSERT(p_initial_buffers != NULL); NRFX_ASSERT(p_initial_buffers->p_rx_buffer != NULL || p_initial_buffers->p_tx_buffer != NULL); NRFX_ASSERT(buffer_size != 0); (void)(flags); nrfx_err_t err_code; if (m_cb.state != NRFX_DRV_STATE_INITIALIZED) { err_code = NRFX_ERROR_INVALID_STATE; NRFX_LOG_WARNING("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); return err_code; } if (((p_initial_buffers->p_rx_buffer != NULL) && !nrfx_is_in_ram(p_initial_buffers->p_rx_buffer)) || ((p_initial_buffers->p_tx_buffer != NULL) && !nrfx_is_in_ram(p_initial_buffers->p_tx_buffer))) { err_code = NRFX_ERROR_INVALID_ADDR; NRFX_LOG_WARNING("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); return err_code; } m_cb.use_rx = (p_initial_buffers->p_rx_buffer != NULL); m_cb.use_tx = (p_initial_buffers->p_tx_buffer != NULL); m_cb.rx_ready = false; m_cb.tx_ready = false; m_cb.buffers_needed = false; m_cb.buffer_size = buffer_size; // Set the provided initial buffers as next, they will become the current // ones after the IRQ handler is called for the first time, what will occur // right after the START task is triggered. m_cb.next_buffers = *p_initial_buffers; m_cb.current_buffers.p_rx_buffer = NULL; m_cb.current_buffers.p_tx_buffer = NULL; nrf_i2s_transfer_set(NRF_I2S, m_cb.buffer_size, m_cb.next_buffers.p_rx_buffer, m_cb.next_buffers.p_tx_buffer); nrf_i2s_enable(NRF_I2S); m_cb.state = NRFX_DRV_STATE_POWERED_ON; nrf_i2s_event_clear(NRF_I2S, NRF_I2S_EVENT_RXPTRUPD); nrf_i2s_event_clear(NRF_I2S, NRF_I2S_EVENT_TXPTRUPD); nrf_i2s_event_clear(NRF_I2S, NRF_I2S_EVENT_STOPPED); nrf_i2s_int_enable(NRF_I2S, (m_cb.use_rx ? NRF_I2S_INT_RXPTRUPD_MASK : 0) | (m_cb.use_tx ? NRF_I2S_INT_TXPTRUPD_MASK : 0) | NRF_I2S_INT_STOPPED_MASK); nrf_i2s_task_trigger(NRF_I2S, NRF_I2S_TASK_START); NRFX_LOG_INFO("Started."); return NRFX_SUCCESS; }