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

What exactly does the nrf_serial_flush?

Hello, 

I'm doing a project with Zigbee using the nRF52840 and I want to read some sensors that talk via UART. 

I have ported with success the nrf_uart example but after discovering that this library doesn't have support for multiple UART instances I've changed to the nrf_serial library. 

Everything is working, but I'm lacking some understandings regarding for instance the nrf_serial_flush() function. What is the purpose of this function? In the beginning, I thought that the purpose of this function was to clear out the buffer and assure the transmission in a blocking state. However, that's not true.

I want to be able to toggle a GPIO pin after the transmission done, like having a transmission done pin. How can I do that? I'm using DMA and for now, the only way that I discover to do that was by using the nrf_queue_is_empty() function to constantly check if the queue is already empty.... That solves the problem but creates an unnecessary overhead to the CPU in my option because I'm polling the nrf_queue_is_empty() function.

Thanks in advance,

Best regards,

Fernando

Parents
  • Everything is working, but I'm lacking some understandings regarding for instance the nrf_serial_flush() function. What is the purpose of this function?

     I understand that the name is a bit confusing to what this function actually does. When you define the instance for nrf_serial using NRF_SERIAL_CONFIG_DEF you have a _sleep variable which is the function pointer for the application-specific sleep function.

    nrf_serial_flush only keeping calling this sleep function until the serial queue is being handled in the background (in the uart interrupt) or the timeout happens. It does not brute force a flush as the name suggests.

     

    I want to be able to toggle a GPIO pin after the transmission done, like having a transmission done pin. How can I do that?

     nrf_serial_flush is a synchronous cal which does not return with NRF_SUCCESS until the transmit queue is empty. So you can check the return value of nrf_serial_flush and toggle the pin.

  • Hi Susheel,

    Thank you very much for your explanation. It seems to work. However, now I'm having a strange behavior on the serial communication. 

    Everything is working for a while and suddenly I start to receive strange characters on the serial port and the 

    nrf_serial_read function stops working.
    Increasing the FIFO size seems to improve, but does not fixes the issue... Do you have any idea of what could be the reason? I'm handling the serial port on a task (using freertos) and I understand that it could happen to lose some characters if the FIFO overruns, but why stop receiving at all? And what is the reason for the strange characters on the serial TX port?
    Do you have any idea of a possible reason for that? Maybe I should give up on using DMA ... 
    Best regards,
    Fernando
  • Do you have XO HFCLK on your board? If so you should also call nrf_drv_clock_hfclk_request to be able to explicitly start the crystal. If you have not done this, then most probably you are using internal RC HFCLK which is less accurate and would explain why you get framing errors so often.

  • Yes, I have both 32Mhz and 32.768kHz external clocks. I tried to call the nrf_drv_clock_hfclk_request and the behavior is still the same. One of the tasks that I'm running in parallel is a Zigbee application and I noticed that with that task off, the framing errors are very low. So, I did a quick search to see if the easyDMA of UART1 is using repeated addresses but I guess no. I'm starting to think that this is somehow a priority-related issue... Is that possible? How are the DMA to RAM transfers being handled? Do I need to change the priority values?

  • Fernando Fontes said:
    I'm starting to think that this is somehow a priority-related issue... Is that possible? How are the DMA to RAM transfers being handled? Do I need to change the priority values?

     The priority of ISR handling becomes very important if you are not using HW flow control. But with this, i would still expect to see overrun errors and not framing errors. 

     

    Fernando Fontes said:
    One of the tasks that I'm running in parallel is a Zigbee application and I noticed that with that task off, the framing errors are very low.

    I cannot put my head around this behavior. Are you seeing less errors per average transaction or are you seeing less errors per average time? Because if it is the second, I could understand as Zigbee task and stack taking more time to process its data and giving UART ISR less time to process its data.

    Fernando Fontes said:
    Yes, I have both 32Mhz and 32.768kHz external clocks. I tried to call the nrf_drv_clock_hfclk_request

    nrf_serial is somewhat less preffered library over libuarte and is also a reason we removed it from latest SDKs. Can you please try to move to libuarte? I know that this sounds like work, but there could be only two possibilities to explore. One is clock inaccuracies and the other is possible nrf_serial bug. I know that the libuarte is very stable so atleast we can exclude one suspecting direction.

  • Well, I switched to the app_uart_fifo implementation. It's a lot more stable than the nrf_serial. Libuarte would be my next option. But since app_uart_fifo seems to be stable I will stick with this one. 

    However, I've just finished the implementation a few minutes ago. It would be great if you could explain a few things about app_uart_fifo implementation. 

    How is handled the reception in this implementation? Is it by interrupts? I know that there is an event handler putting the RX data into a buffer, but is this module still using easyDMA?

  • Fernando Fontes said:
    How is handled the reception in this implementation? Is it by interrupts? I know that there is an event handler putting the RX data into a buffer, but is this module still using easyDMA?

     Yes, it is interrupt based which is handled in nrfx_uarte.c/nrfx_uart.c. If EasyDMA is used or not depends on what you have set in nRF5_SDK_17.0.2_d674dde\integration\nrfx\legacy\apply_old_config.h NRFX_UARTE_ENABLED which inturn depends on your settings in sdk_config.h.   Just set UARTX_ENABLED and UART_EASY_DMA_SUPPORT to 1 in sdk_config.h and you will see that easydma will be used though the hal driver nrfx_uarte.c

Reply
  • Fernando Fontes said:
    How is handled the reception in this implementation? Is it by interrupts? I know that there is an event handler putting the RX data into a buffer, but is this module still using easyDMA?

     Yes, it is interrupt based which is handled in nrfx_uarte.c/nrfx_uart.c. If EasyDMA is used or not depends on what you have set in nRF5_SDK_17.0.2_d674dde\integration\nrfx\legacy\apply_old_config.h NRFX_UARTE_ENABLED which inturn depends on your settings in sdk_config.h.   Just set UARTX_ENABLED and UART_EASY_DMA_SUPPORT to 1 in sdk_config.h and you will see that easydma will be used though the hal driver nrfx_uarte.c

Children
Related