Hello. I have recently started learning about Zephyr and nRF52 microcontrollers.
I use nRF Connect SDK and I run all experiments on nRF52DK nRF52832 development board from nordic.

I have a lot of trouble understanding how to use Async UART. I have been watching your video on Youtube:
https://www.youtube.com/watch?v=uAG5EVSWGKs&ab_channel=CircuitDojo
and you mentioned you used Async UART so I thought you be able to help.

I have posted my question regarding Async UART in Zephyr git, Zephyr discord as well as nordic devzone (nordic community forum) but havent been able to get help regarding this. It seems to be very obvious problem but there is no clear response about this.

My problem

The issue I have with Async UART is that I am not able to receive incoming serial messages properly. Most of the time, when I use UART, I want to be able to send various length messages to the device and respond back with whatever data I want. That appears to be an issue with Async UART. I believe what happens is when the RX buffer is filled up to declared RX buffer size and rolls over to the beggining and I am not able to track what was the full message because half of the message got stuck at the end of the rx buffer and the rest rolled over to the beggining.

To summarise above

I want to be able to use the Async UART in a simillar way as eho_bot sample project:
https://docs.zephyrproject.org/latest/samples/drivers/uart/echo_bot/README.html

Whatever is being sent to the device via serial terminal is printed.

You can look at my source code here:
https://github.com/krupis/nrf52_learning

When I try to send various messages via serial terminal, see what happens:
https://ibb.co/cCzRwRg

You can read through our discussion at the nordic devzone here:
https://devzone.nordicsemi.com/f/nordic-q-a/104641/nrf52dk-nrf52832-uart-asynchronous-receive

I would really appreciate if you took your time to look at this, perhaps you got any ideas. Thanks in advance!

and rolls over to the beggining

The idea behind the async UART is a “double buffer” approach. See UART_RX_BUF_REQUEST/UART_RX_BUF_RELEASED for implementation.

If only one buffer is used and that is processed, when filled up, the UART would need to signal a pause (HW signals). with two buffers, swapping the buffers is very fast and may be even done overlapping (requesting the new one while still writing to the old one). Hope that helps.

To be frank, Jared’s forum is more for Jared’s products, so I’m not sure, if he really welcomes an answer on such foreign topic.

    Thanks for your reply.

    I am aware of double buffer approach. I have updated my repository main branch.

    I am using double buffer and have bunch of printf statements to monitor how exactly everything works but from what I understand, there is currently no easy way to keep track of which data has been placed to which buffer and what index.

    I have noticed that uart_event data.rx.len and uart_event.data.rx.offset does not seem to return proper values once the first buffer filled up and we select second buffer as our active buffer.

    For more details regarding this, you can look at my latest post here:
    https://devzone.nordicsemi.com/f/nordic-q-a/104641/nrf52dk-nrf52832-uart-asynchronous-receive

    AchimKraus To be frank, Jared’s forum is more for Jared’s products, so I’m not sure, if he really welcomes an answer on such foreign topic.

    Ahh, I was not fully aware of this.. Anyways, it was worth a shot since I am desperate to find answers and get the Async UART to work properly.

    I’m not sure, what happens in your case.
    I use it in my case for a cmd-shell and Firmware Update via XMODEM.
    I’m not aware, that UART_RX_RDY has any issue. I didn’t try to verify the buffers and how these are filled. I just copy the stuff out of that region into my buffers, where I process the data.

    From the issue in the nordic forum,

    case UART_RX_RDY:
    		printf("rx rdy \n");
    		if((evt->data.rx.len) != 0){
    			printf("data received = %s \n", evt->data.rx.buf[evt->data.rx.offset]);
    		}
    
    		break;
    case UART_RX_BUF_REQUEST:
    		printf("requesting buffer \n");
    		// do something
    		break;
    
    case UART_RX_BUF_RELEASED:
    		printf("buffer released \n");
    		// do something
    		break;

    If UART_RX_BUF_REQUEST/UART_RX_BUF_RELEASED are not implemented in the required way, the async UART just stops. The way the received content is logged, works only the first time. later it would require to fill the terminating 0.

    I will try to answer in the Nordic Forum on your further comments.

      AchimKraus

      The code has evolved since the beggining of our discussion in Nordic forum. To see the latest code that I am currently running all tests please look at my repository.

      I saw it. My guess would be, that a 8 byte DMA buffer is too small ..

      Just as “shortcut” for other readers:
      using that async UART comes also with a specific “prj.conf”.
      Using:

      CONFIG_SERIAL=y
      CONFIG_UART_ASYNC_API=y

      isn’t enough, it requires additionally:

      CONFIG_UART_0_ASYNC=y
      CONFIG_UART_0_NRF_HW_ASYNC=y
      CONFIG_UART_0_NRF_HW_ASYNC_TIMER=2
      CONFIG_NRFX_TIMER2=y

      (or similar)

        jaredwolff

        Ahh! I was not able to join sadly but I really appreciate what you did. I have watched the whole video and you covered most basics. I think Async UART deserves a second part video where you go into actual real world applications and showcase how to work with dual buffer. Some of the topics worth discussing:

        1. How to setup dual buffering for Async UART
        2. How to “echo” the command to the console when data is received (same as echo_bot example from zephyr).
        3. How to ensure that when first buffer fills up, you are still able to receive a full message at once (dual buffering magic). Considering that the being received is variable length
        4. How to properly handle data in UART_RX_RDY since you cannot use printf/printk statements because they will add additional delay and can cause issues with data reception
        5. How to ensure that no data is being lost when you have other time critical threads running.

        I think you should also familiarise yourself with the whole discussion about this in Nordic forum:
        https://devzone.nordicsemi.com/f/nordic-q-a/104641/nrf52dk-nrf52832-uart-asynchronous-receive

        Appreciate your work and your videos about Zephyr are really useful 🙂

        AchimKraus

        I can confirm that by adding the options that you have suggested I was able to get it to work. It is quite strange as I am not too sure what is exactly the difference and why would it work when adding extra options that you have suggested.

        Terms and Conditions | Privacy Policy