This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

nrfx_uarte event handler not being called

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();
    }
}
app_config.h

Parents Reply Children
  • It's not that.:

    #define NRFX_UARTE_DEFAULT_CONFIG_HWFC 0

    Are there other config settings I should be looking at? Given the inconsistency between all the various example configs and the template and the 'generic' SDK one, I suspect I'm just missing some config, but it's *really* hard to figure out what that might be.

  • I have put together a small example that I'm hoping you can test on your board. It uses nrfx API directly as you did, and it toggles LED 1 for every 5 byte it receives.  To build it, you first need to extract it to  \nRF5_SDK_16.0.0_98a08e2\examples\peripheral\, then change the UART pins if you don't wish to receive the UART data through the Segger VCOM. 

    uart_drv.zip

    Also, since you're using the nrfx API, note that the apply_old_config header will override NRFX_* options such as NRFX_UARTE_DEFAULT_CONFIG_HWFC if the corresponding legacy option has the opposite setting.  So HW flow control will get enabled if UART_DEFAULT_CONFIG_HWFC==1 even if NRFX_UARTE_DEFAULT_CONFIG_HWFC  was '0' before building. You can remove the UART_* symbols from your config header to avoid this. 

Related