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