I've been trying to create a simple SPI to UART bridge starting with the peripheral template example from the nRF5 SDK 16. I want to read 5 bytes from uart, send them via SPI, and return the SPI result. Unfortunately, my uart handler isn't being called, after initializing successfully and nrfx_uarte_rx (successfully).
Is there some 'enable' I'm supposed to be calling after nrfx_uarte_init?
I'm using the nRF52840 DK. I've attached my code at the bottom.
For relevant config I have:
$ grep -e "#define.*UART.* 1" ../config/sdk_config.h
#define NRFX_UARTE_ENABLED 1
#define NRFX_UARTE1_ENABLED 1
#define NRFX_UARTE_CONFIG_LOG_ENABLED 1
#define NRFX_UART_ENABLED 1
#define UART_ENABLED 1
#define UART_EASY_DMA_SUPPORT 1
#define UART_LEGACY_SUPPORT 1
#define UART0_ENABLED 1
#define UART0_CONFIG_USE_EASY_DMA 1
#define UART1_ENABLED 1
#define APP_UART_ENABLED 1
#define NRF_CLI_UART_ENABLED 1
#define NRF_LOG_BACKEND_UART_ENABLED 1
/*
* SPI <-> UART bridge
*/
#include <stdbool.h>
#include <stdint.h>
#include "nrf.h"
#include "nordic_common.h"
#include "nrf_delay.h"
#include "nrf_gpio.h"
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
#include "nrfx.h"
#include "nrfx_spim.h"
#include "nrfx_uarte.h"
#include "boards.h"
#include "app_config.h"
#define MESSAGE_LENGTH 5
#ifdef DEBUG
#define DEBUG_BLINK_ALL \
for(int i=0; i < LEDS_NUMBER; i++) { \
bsp_board_led_invert(i % LEDS_NUMBER); \
}
#else
#define DEDEBUG_BLINK_ALL
#endif
static uint8_t data_to_device[MESSAGE_LENGTH], data_from_device[MESSAGE_LENGTH];
typedef enum {
IDLE,
AWAITING_INPUT,
TRANSCEIVING,
OUTPUTTING,
} state_t;
static volatile state_t state = IDLE;
static volatile nrfx_err_t return_code;
static const nrfx_spim_t spim = NRFX_SPIM_INSTANCE(SPI_ID); /**< SPI instance. */
static const nrfx_uarte_t uarte = NRFX_UARTE_INSTANCE(UART_ID); /**< UART instance. */
static void receive() {
NRF_LOG_INFO("receive called");
return_code = nrfx_uarte_rx(&uarte, data_to_device, MESSAGE_LENGTH);
if (return_code != NRFX_SUCCESS) {
DEBUG_BLINK_ALL
APP_ERROR_CHECK(return_code);
state = IDLE;
} else {
state = AWAITING_INPUT;
}
}
void spi_handler(nrfx_spim_evt_t *p_event, __unused void *p_context) {
return_code = nrfx_uarte_tx(&uarte, p_event->xfer_desc.p_rx_buffer, p_event->xfer_desc.rx_length);
if (return_code != NRFX_SUCCESS) {
DEBUG_BLINK_ALL
APP_ERROR_CHECK(return_code);
state = IDLE;
} else {
state = OUTPUTTING;
}
}
void uart_handler(nrfx_uarte_event_t *p_event, __unused void *p_context) {
state_t event_state = state;
NRF_LOG_INFO("uart handling state %d", p_event->type);
switch (p_event->type) {
case NRFX_UARTE_EVT_TX_DONE:
if (event_state != OUTPUTTING) break;
receive();
break;
case NRFX_UARTE_EVT_RX_DONE:
if (event_state != AWAITING_INPUT) break;
return_code = nrfx_spim_xfer(&spim, &((nrfx_spim_xfer_desc_t) {
.p_tx_buffer = p_event->data.rxtx.p_data,
.p_rx_buffer = data_from_device,
.tx_length = p_event->data.rxtx.bytes,
.rx_length = MESSAGE_LENGTH,
}), 0);
if (return_code != NRFX_SUCCESS) {
DEBUG_BLINK_ALL
APP_ERROR_CHECK(return_code);
state = IDLE;
} else {
state = TRANSCEIVING;
}
break;
case NRFX_UARTE_EVT_ERROR:
DEBUG_BLINK_ALL
// TODO: log error info
state = IDLE;
break;
}
}
int main(void) {
NRF_LOG_INIT(NULL);
NRF_LOG_DEFAULT_BACKENDS_INIT();
NRF_LOG_INFO("Setup success");
nrfx_spim_config_t spim_cfg = NRFX_SPIM_DEFAULT_CONFIG;
spim_cfg.frequency = NRF_SPIM_FREQ_1M;
spim_cfg.mode = NRF_SPIM_MODE_3;
spim_cfg.sck_pin = SPI_3_SCK_PIN;
spim_cfg.miso_pin = SPI_3_MISO_PIN;
spim_cfg.mosi_pin = SPI_3_MOSI_PIN;
spim_cfg.ss_pin = SPI_3_SS_PIN;
nrfx_uarte_config_t uarte_cfg = NRFX_UARTE_DEFAULT_CONFIG;
uarte_cfg.pseltxd = UART_RX_PIN;
uarte_cfg.pselrxd = UART_TX_PIN;
return_code = nrfx_spim_init(&spim, &spim_cfg, (nrfx_spim_evt_handler_t) &spi_handler, NULL);
APP_ERROR_CHECK(return_code);
return_code = nrfx_uarte_init(&uarte, &uarte_cfg, (nrfx_uarte_event_handler_t) &uart_handler);
APP_ERROR_CHECK(return_code);
#ifdef DEBUG
bsp_board_init(BSP_INIT_LEDS);
uint i=0, j=0;
nrf_gpio_cfg_output(GPIO_DEBUG_PIN);
#endif
while(true) {
#ifdef DEBUG
if(!(j%100)) {
bsp_board_led_invert(i % LEDS_NUMBER);
i++;
nrf_gpio_pin_toggle(GPIO_DEBUG_PIN);
}
j++;
#endif
if (state == IDLE) {
receive();
}
nrf_delay_ms(5);
NRF_LOG_PROCESS();
}
}