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

Related