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.

Parents Reply Children
  • Thanks.

    I would also like to ask why when I connect GNSS to my board (UART speed is 9600) and try to output incoming data via RTT Terminal, I see missing messages?

  • Hi,

    Logs are dropped, so you are logging faster than the logs can be processed output. If the logging is in bursts, you can solve this issue by increasing the log buffers like this (adjust the values as needed):

    CONFIG_LOG_BUFFER_SIZE=15360
    CONFIG_SEGGER_RTT_BUFFER_SIZE_UP=15360

    You can also consider adding CONFIG_LOG_MODE_IMMEDIATE=y to process log, but this will impact the timing/performance more though, as logs are processed in place wherever you do any logging. (If you do this th einternal log buffer is not used, so there would be no point in increasing CONFIG_LOG_BUFFER_SIZE.

  • Hi. At the moment I have the following problem. 

    I want to receive one symbol at a time from GNSS (rx_buf size = 1) and pass it immediately to the queue for further processing. 

    static void uart_cb(const struct device *dev, struct uart_event *evt, void *user_data)
    {
    	switch (evt->type) {
    
    	case UART_RX_RDY:
    		LOG_DBG("rx_buf[0] = %c \n", rx_buf[0]);
    			k_work_submit_to_queue(&gnss_work_q, &gnss_work);
    		break;
    
    	case UART_RX_DISABLED:
    		uart_rx_enable(dev, rx_buf, sizeof(rx_buf), RECEIVE_TIMEOUT);
    		break;
    
    	default:
    		break;
    	}
    }

    In the thread, I write the received characters to the "sentence" array until the end of line character is received.
    Then the parser decodes the sentence array.

    int i = 0;
    
    static void gnss_work_cb (struct k_work *work){
    
    if (rx_buf[0] != '\n')
    {
    	sentence[i] = rx_buf[0];
    	LOG_DBG("sentence[%d] = %c \n", i, sentence[i]);
    	i++;
    }
      else
     {
    	LOG_DBG("%s \r\n", sentence);
    	struct minmea_sentence_rmc frame;
    	if(minmea_parse_rmc(&frame, sentence)){
                        LOG_DBG(INDENT_SPACES "$xxRMC floating point degree coordinates and speed: (%f,%f) %f\n",
                                minmea_tocoord(&frame.latitude),
                                minmea_tocoord(&frame.longitude),
                                minmea_tofloat(&frame.speed));
                    }
                    else {
                        LOG_DBG(INDENT_SPACES "$xxRMC sentence is not parsed\n");
                    }
                    
    	memset(sentence, 0, sizeof(sentence));
    	LOG_DBG("i = %d \r\n", i);
    	i = 0;
    }

    When I connect GNSS and test the program I get the following results as on the screenshot

    It seems that there is not enough CPU time for the workflow.

    How can this be fixed?   

    If I disable GNSS and manually enter the NMEA string (simulating sending a message from GNSS), everything works correctly. 

    Can you please tell me where I'm making a mistake?
    Thank you.

  • 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.

Related