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

un-init and then re-init buarte_async module will report NRF_LIBUARTE_ASYNC_EVT_ERROR

Hi, support team 

       I need to realize two-wire uarte receiver(with low power), in the scenario there is no data come from TX in most time, so after receiving the data I need to un-initialize the uarte module and step into low-power mode. I choose libuarte sample on SDK16.0.0 + nrf52840 platform. the logic is like this :

      gpiote init(waiting port event)-> libuarte_async_init->received data until timeout -> libuarte_async_uninit->re-init gpiote (waiting for port event and new data)

      So I directly made some modification on our libuarte sample.

      First, I defined my instance as easy as possible:

           NRF_LIBUARTE_ASYNC_DEFINE(libuarte, 0, 0, 0, NRF_LIBUARTE_PERIPHERAL_NOT_USED, 1, 3);

      Then in my main loop, once gpio port event coming , myGPIOTE_EVENT_FLAG will be set, and then prepares to receive uarte data(un-init gpiote/init+enable libuarte_async) ; when the timeout event coming(myRX_DONE_FLAG be set) , it un-init libuarte_async module and re-init the two PORT to gpio mode(wait event). My main C file is here:

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "nrf_libuarte_async.h"
#include "nrf_drv_clock.h"
#include <bsp.h>
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
#include "nrf_queue.h"
#include "nrf_log.h"
#include "nrf_drv_gpiote.h"
volatile bool myGPIOTE_EVENT_FLAG=false;
volatile bool myRX_DONE_FLAG=false;
NRF_LIBUARTE_ASYNC_DEFINE(libuarte, 0, 0, 0, NRF_LIBUARTE_PERIPHERAL_NOT_USED, 1, 3);
volatile uint8_t myindex=0;
uint8_t rxdata_array[10]={0};
#define RXD_GPIOTE_PIN 26
#define TXD_GPIOTE_PIN 27
nrf_libuarte_async_config_t nrf_libuarte_async_config = {
        .tx_pin     = TXD_GPIOTE_PIN,
        .rx_pin     = RXD_GPIOTE_PIN,
        .baudrate   = NRF_UARTE_BAUDRATE_115200,
        .parity     = NRF_UARTE_PARITY_EXCLUDED,
        .hwfc       = NRF_UARTE_HWFC_DISABLED,
        .timeout_us = 100,
        .int_prio   = APP_IRQ_PRIORITY_LOW
};

static void in_pin_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
{
    myGPIOTE_EVENT_FLAG=true;
    for(int i=0;i<50;i++);
}

static void gpio_init(void)
{
    ret_code_t err_code;
    err_code = nrf_drv_gpiote_init();
    APP_ERROR_CHECK(err_code);
    nrf_drv_gpiote_in_config_t in_config = GPIOTE_CONFIG_IN_SENSE_TOGGLE(false);
    in_config.pull = NRF_GPIO_PIN_PULLUP; //Pin pull-up resistor enabled.
    err_code = nrf_drv_gpiote_in_init(RXD_GPIOTE_PIN, &in_config, in_pin_handler);
    APP_ERROR_CHECK(err_code);
    nrf_drv_gpiote_in_event_enable(RXD_GPIOTE_PIN, true);
	myGPIOTE_EVENT_FLAG=false;
}

static void gpio_uninit(void)
{
    nrf_drv_gpiote_in_event_disable(RXD_GPIOTE_PIN);
    nrf_drv_gpiote_in_uninit(RXD_GPIOTE_PIN);
    nrf_drv_gpiote_uninit();
}

void uart_event_handler(void * context, nrf_libuarte_async_evt_t * p_evt)
{
    nrf_libuarte_async_t * p_libuarte = (nrf_libuarte_async_t *)context;
    switch (p_evt->type)
    {
        case NRF_LIBUARTE_ASYNC_EVT_ERROR:
            NRF_LOG_INFO("uart_event_handler:NRF_LIBUARTE_ASYNC_EVT_ERROR");
            break;
        case NRF_LIBUARTE_ASYNC_EVT_RX_DATA:
            NRF_LOG_INFO("received %d byte %d",p_evt->data.rxtx.length,p_evt->data.rxtx.p_data[0]);
            rxdata_array[myindex]=p_evt->data.rxtx.p_data[0];
            myindex+=p_evt->data.rxtx.length;
            nrf_libuarte_async_rx_free(p_libuarte, p_evt->data.rxtx.p_data, p_evt->data.rxtx.length);
            break;
        case NRF_LIBUARTE_ASYNC_EVT_TIMEROUT:
            myRX_DONE_FLAG=true;
            NRF_LOG_INFO("Timeout+++++++");
            
        default:
            break;
    }
}

/**
 * @brief Function for main application entry.
 */
int main(void)
{
    bsp_board_init(BSP_INIT_LEDS);
    ret_code_t err_code = nrf_drv_clock_init();
    APP_ERROR_CHECK(err_code);
    nrf_drv_clock_lfclk_request(NULL);
    err_code = NRF_LOG_INIT(app_timer_cnt_get);
    APP_ERROR_CHECK(err_code);
    NRF_LOG_DEFAULT_BACKENDS_INIT();

    gpio_init();
    NRF_LOG_INFO("Main");
    while(true){
        __WFE();
        __SEV();
        if(myGPIOTE_EVENT_FLAG){
            NRF_LOG_INFO("step into main loop!");
            NRF_LOG_FLUSH();
            bsp_board_led_on(BSP_BOARD_LED_0); 
            gpio_uninit();
            err_code = nrf_libuarte_async_init(&libuarte, &nrf_libuarte_async_config, uart_event_handler, (void *)&libuarte);
            APP_ERROR_CHECK(err_code);
            nrf_libuarte_async_enable(&libuarte);
            bsp_board_led_off(BSP_BOARD_LED_0);
            while(!myRX_DONE_FLAG);
            myRX_DONE_FLAG=false;
            NRF_LOG_INFO("DONE!,index =%d,last value:%d", myindex, rxdata_array[myindex-1]);
            NRF_LOG_FLUSH();
            //nrf_libuarte_async_disable(&libuarte);
            nrf_libuarte_async_uninit(&libuarte);
            gpio_init();
            memset(rxdata_array,0x0,10);
            myindex=0;
        }
        __SEV();
        __WFE();
    }
}

/** @} */

I add an NRF_LIBUARTE_ASYNC_EVT_TIMEROUT event to inform the main loop that it ‘s time to change to gpio mode.

It defined in components\libraries\libuarte\nrf_libuarte_async.c => nrf_libuarte_async_timeout_handler(), I added the logic:

    ......
    if (capt_rx_count > p_libuarte->p_ctrl_blk->rx_count)
    {
       ......//default code
    }
    else if(capt_rx_count = p_libuarte->p_ctrl_blk->rx_count){
        nrf_libuarte_async_evt_t evt = {
            .type = NRF_LIBUARTE_ASYNC_EVT_TIMEROUT
            .data = NULL
        };
        p_libuarte->p_ctrl_blk->evt_handler(p_libuarte->p_ctrl_blk->context, &evt);
    }
    ......

    In my test demo, I choose TX send 5Byte data each round and then sleep 10s, then sending 5Byte, then sleep…always looping .

     I run my RX code in nrf52840DK, The first round of receiving 5Byte data is right(in fact, in each round the first Byte is for triggering gpio port event , I do not care its detail), But when the second round of data coming, it reports error. like this :

Maybe before I un-init the module, I need to clear something or recover something to default?  so the next the re-init & receiving can becomes normal??

And also I'm not sure of the right using of timeout event.

Please help to give some advices, thanks!

BR

Smile

Top Replies

Parents
  • Can you toggle a GPIO when you call nrf_libuarte_async_enable() so you can monitor on a logic analyzer to make sure that no UART byte is in the middle of a transaction when you enable it?

    Also, instead of modifying libuarte, have you considered starting an app_timer in application to handle if no data is received on UART after nrf_libuarte_async_enable?

    The timeout in libuarte is used to detect inactivity on the UART lines (e.g. no more data received since last byte), the timeout will likely not start unless it first receive a byte.

    Best regards,
    Kenneth

Reply
  • Can you toggle a GPIO when you call nrf_libuarte_async_enable() so you can monitor on a logic analyzer to make sure that no UART byte is in the middle of a transaction when you enable it?

    Also, instead of modifying libuarte, have you considered starting an app_timer in application to handle if no data is received on UART after nrf_libuarte_async_enable?

    The timeout in libuarte is used to detect inactivity on the UART lines (e.g. no more data received since last byte), the timeout will likely not start unless it first receive a byte.

    Best regards,
    Kenneth

Children
No Data
Related