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

NRF UART RX done event only fires once

I'm trying to communicate between two devices (nrf52840 and teensy 3.6) over RS485, but I'm having some issues using the UART library in the SDK. I'm trying to create an interrupt-based response to a packet received over the 485 line, so I've taken the example found under Nordic\examples\peripheral\serial\ and created my own event handler to respond to RX events. 

#define OP_QUEUES_SIZE          3
#define APP_TIMER_PRESCALER     NRF_SERIAL_APP_TIMER_PRESCALER

#define RS485_EN                ARDUINO_2_PIN
#define RS485_TX                ARDUINO_1_PIN
#define RS485_RX                ARDUINO_0_PIN

static void rs485_evt_handler(nrf_serial_t const * p_serial,
                              nrf_serial_event_t event)
{
    uint32_t ret = 0;
    uint8_t rxbyte;
    switch(event)
    {
        case NRF_SERIAL_EVENT_RX_DATA:
        {
            printf("RX event!\n");
            break;
        }
        case NRF_SERIAL_EVENT_TX_DONE:
        {
            break;
        }
        default:
        {
            printf("UART EVENT - %#010x\n", nrf_drv_uart_errorsrc_get(&p_serial->instance));
            break;
        }
    }
}
 
static void sleep_handler(void)
{
    __WFE();
    __SEV();
    __WFE();
}

NRF_SERIAL_DRV_UART_CONFIG_DEF(m_uart0_drv_config,
                      RS485_RX, RS485_TX,
                      RTS_PIN_NUMBER, CTS_PIN_NUMBER,
                      NRF_UART_HWFC_DISABLED, NRF_UART_PARITY_EXCLUDED,
                      NRF_UART_BAUDRATE_9600,
                      UART_DEFAULT_CONFIG_IRQ_PRIORITY);

#define SERIAL_FIFO_TX_SIZE 32
#define SERIAL_FIFO_RX_SIZE 255

NRF_SERIAL_QUEUES_DEF(serial_queues, SERIAL_FIFO_TX_SIZE, SERIAL_FIFO_RX_SIZE);


#define SERIAL_BUFF_TX_SIZE 1
#define SERIAL_BUFF_RX_SIZE 1

NRF_SERIAL_BUFFERS_DEF(serial_buffs, SERIAL_BUFF_TX_SIZE, SERIAL_BUFF_RX_SIZE);

NRF_SERIAL_CONFIG_DEF(serial_config, NRF_SERIAL_MODE_IRQ,
                      &serial_queues, &serial_buffs, rs485_evt_handler, sleep_handler);

NRF_SERIAL_UART_DEF(serial_uart, 0);

int main(void)
{
    ret_code_t ret;

    ret = nrf_drv_clock_init();
    APP_ERROR_CHECK(ret);
    ret = nrf_drv_power_init(NULL);
    APP_ERROR_CHECK(ret);

    nrf_drv_clock_lfclk_request(NULL);
    ret = app_timer_init();
    APP_ERROR_CHECK(ret);

    // Initialize LEDs and buttons.
    bsp_board_init(BSP_INIT_LEDS | BSP_INIT_BUTTONS);

    ret = nrf_serial_init(&serial_uart, &m_uart0_drv_config, &serial_config);
    APP_ERROR_CHECK(ret);
    
    nrf_gpio_cfg_output(RS485_EN);
    nrf_gpio_pin_clear(RS485_EN);

//    static char tx_message[] = "Hello nrf_serial!\n\r";
//
//    ret = nrf_serial_write(&serial_uart,
//                           tx_message,
//                           strlen(tx_message),
//                           NULL,
//                           NRF_SERIAL_MAX_TIMEOUT);
//    APP_ERROR_CHECK(ret);
    
    printf("UART ERROR OVERRUN - %#10x\n", NRF_UART_ERROR_OVERRUN_MASK);
    printf("UART ERROR BREAK - %#10x\n", NRF_UART_ERROR_BREAK_MASK);
    printf("UART ERROR FRAMING - %#10x\n", NRF_UART_ERROR_FRAMING_MASK);
    printf("UART ERROR PARITY - %#10x\n", NRF_UART_ERROR_PARITY_MASK);

    while (true)
    {
//        char c;
//        ret = nrf_serial_read(&serial_uart, &c, sizeof(c), NULL, 1000);
//        if (ret != NRF_SUCCESS)
//        {
//            continue;
//        }
//        (void)nrf_serial_write(&serial_uart, &c, sizeof(c), NULL, 0);
//        (void)nrf_serial_flush(&serial_uart, 0);
        bsp_board_led_invert(0);
        nrf_delay_ms(1000);
        printf("UART Ready? %d\n", nrf_drv_uart_rx_ready(&serial_uart.instance));
    }
}

/** @} */

I'm toggling an activity LED and I've added some prints and comments just for debugging. I've defined SERIAL_BUFF_RX_SIZE to 1, so that the event should fire on every byte received and I made sure to pass my custom event handler to NRF_SERIAL_CONFIG_DEF. Baud rate is set to 9600 and the UART is in IRQ mode.

The problem is that the NRF_SERIAL_EVENT_RX_DATA only fires once, and then the UART appears to lock up and the event doesn't fire again unless I restart the device. I've searched through the UART source files to see why this might be happening, but I can't find anything. My guess is that the RX buffer is overflowing/overrunning, but to be honest the documentation on this module is quite light so I thought I'd post on here to see if anyone could help.

Thanks!

Parents
  • Hi,

    Do you write anything on UART? In the code you attached, nrf_serial_read is commented out, and I can't see any other calls to this in your code. I tried commenting it out and running your code with nothing connected, and I hit a breakpoint inside NRF_SERIAL_EVENT_RX_DATA event multiple times.

    Best regards,
    Jørgen

  • Hey Jorgen thanks for the reply.

    I'm not currently writing or reading anything on the UART because I've been trying to debug this issue.

    The Teensy I'm trying to communicate with is sending up to 1000 bytes (under normal conditions its at lot less, usually between 15 and 100 bytes) at 9600 baud. I've discovered that if I reduce the packet size being sent by the Teensy to 7 bytes or less with the SERIAL_BUFF_RX_SIZE defined as 1, the RX_DATA event works as expected. However if the packet is any larger, I get the issue described above which can be resolved by re-enabling the RXRDY interrupt flag, however this results in some data loss.

    If I increase SERIAL_BUFF_RX_SIZE by a given amount, the packet size that causes the error increases by the same amount (i.e. for a SERIAL_BUFF_RX_SIZE of 2 the maximum packet size without causing an error is 8, for 3, it's 9 and so on).

    Is there away to get around this? Or should I change the UART to polling mode? I need to keep SERIAL_BUFF_RX_SIZE defined as 1 because the received packet size will be variable, so I need the event to fire on every byte.

    Thanks,

    Thomas

Reply
  • Hey Jorgen thanks for the reply.

    I'm not currently writing or reading anything on the UART because I've been trying to debug this issue.

    The Teensy I'm trying to communicate with is sending up to 1000 bytes (under normal conditions its at lot less, usually between 15 and 100 bytes) at 9600 baud. I've discovered that if I reduce the packet size being sent by the Teensy to 7 bytes or less with the SERIAL_BUFF_RX_SIZE defined as 1, the RX_DATA event works as expected. However if the packet is any larger, I get the issue described above which can be resolved by re-enabling the RXRDY interrupt flag, however this results in some data loss.

    If I increase SERIAL_BUFF_RX_SIZE by a given amount, the packet size that causes the error increases by the same amount (i.e. for a SERIAL_BUFF_RX_SIZE of 2 the maximum packet size without causing an error is 8, for 3, it's 9 and so on).

    Is there away to get around this? Or should I change the UART to polling mode? I need to keep SERIAL_BUFF_RX_SIZE defined as 1 because the received packet size will be variable, so I need the event to fire on every byte.

    Thanks,

    Thomas

Children
No Data
Related