Algorithm of work with GNSS via UART

Good Day.

I am using a custom board based on an nRF52840 microcontroller and a RYS8830 GNSS receiver connected to it via UART0. 

SDK v2.5.99 (Toolchain v2.5.0).

I want to get the coordinates of the board location (via asynchronous UART0) and output them to the terminal (via RTT and SWDIO programming connector ).

Could you please tell me how to correctly process incoming data from GNSS (NMEA message packet that arrives once per second) via UART? 

1. What is the correct action I should take in the UART callback function (uart_cb) when an NMEA data packet arrives (UART_RX_RDY)? 

2. In which part of the program should actions be performed to process incoming data? In the callback function (UART_RX_RDY), in the main function (main) or in an infinite loop (while(1))? 

I apologize for such basic questions, it's just that I'm new to programming.

I hope for your understanding and help.

Thanks.

  • Any idea how to implement this, assuming that the interrupt from the UART consumes almost all of the CPU time because the data from GNSS is coming almost continuously? 

  • Hi,

    In the original post you wrote that one character is recevied every second. If that is the case, then you should have ample time to receive and process one character at a time as you describe. Why did you conclude that CPU is a limiting factor here? Do you do a lot of other work every time a character is received?

    If it is so that this casue a lot of CPU activity, then I would start to figure out what parts of the handling contribute to the CPU usage, as that is not obvious to me.

  • Hi, Einar.

    When I start GNSS I get a data packet like the one below once per second. And as time passes, the amount of data (number of characters) increases. 

    $GNRMC,,V,,,,,,,,,,N*4D
    $GNVTG,,,,,,,,,N*2E
    $GNGGA,,,,,,0,00,99.99,,,,,,*56
    $GNGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*2E
    $GNGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*2E
    $GPGSV,1,1,00*79
    $GLGSV,1,1,00*65
    $GNGLL,,,,,,V,N*7A

    The result is that the interrupt from the UART is triggered as many times as there are characters in the packet, which is several hundred times per second. The time between UART interrupts is not enough time for gnss_work_cb to execute. This can be seen on the screenshot (underlined with a red line), the thread does not have time to print the copied character in the sentence array.

    I don't have any other tasks in my program at the moment. I only need to parsing the string $GNRMC, but so far I can't do it.

    What can you advise me based on your experience?

    Thank you.

  • I see. If you receive data rapitly, it is not viable to receive single bytes at a time. I would use a larger receive buffer, so that data is received directly with DMA, without the CPU needing to handle it continiously. You can still set a timeout if you want to handle the data withing reasonable time. The Async UART API is probably what you want to use for this. (This API can be a bit confusing, but this video explains it in a good way).

Related