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