How to use the usart in a task which doesn't have the highest priority, and avoid losing data?

alvaromuro wrote on Friday, May 25, 2018:


I’m using a SAML21 Xplained Pro A with several tasks running at the same time at different priorities, with tickless iddle sleep.

The highest priority task reads and processes a sensor every 500ms (blocking with a vTaskDelay). The second most prioritary task sends messages throught GPRS (SIM900), using the USART to connect with a server, with usart_read_buffer_job (Atmel’s ASF routines). When a character is received in the serial port, the USART interrupt executes the read callback, storing the character in a circular buffer, which will be processed outside of the callback routine.

Some of the messages are correctly sent and the server responses are correctly received, however, in many occassions, the GPRS task wait for the response of the server and never receives the expected characters. I have tested the GPRS system without FreeRTOS, connecting the SIM900 directly to the CPU, and it works perfectly.
This makes me wonder if some data is getting lost when a context switch occurs and the usart interrupt and callback are being preempted by other task or by a FreeRTOS interrupt (as I don’t have any other interrupts).

The usart is setup to run in standby. I know that all interrupts have higher priority than any FreeRTOS tasks, so I wonder what might be causing this loss.

I have read that using DMA might be a solution, could it?
Also, I have found freertos.peripheral_control and FreeRTOS+IO, but it seems there is no support for the SAML21.
Could this be due to an incorrect priority assignment to the usart interrupt?

What’s the proper method to use the usart in a task which doesn’t have the highest priority, and avoid losing data?

I would appreciate any insights on this issue.


rtel wrote on Friday, May 25, 2018:

Is you UART ISR making any FreeRTOS API calls?

You say with FreeRTOS and tickless idle you have a problem, without
FreeRTOS you don’t have a problem - have you tried with FreeRTOS but
WITHOUT tickless idle? I suspect, without much evidence, the issue will
be processing as you leave low power mode rather than anything to do
with context switching.

alvaromuro wrote on Monday, May 28, 2018:

Thanks Richard,

The USART ISR doesn’t use FreeRTOS API calls, just saves the received byte in a circular buffer:

void usartGPRS_read_callback(struct usart_module *const usart_module)
	GPRS_data_rx[data_in_GPRS_RX_buffer] = *rx_bufferGPRS;

I am trying without tickless idle, and even without entering into sleep mode, and still some USART messages are not properly received.

I have configured the GPRS task to have the same priority as the sensor task, with the same result.

I am trying to find how to set up interrupt priorities, thinking that this could be the cause, does it make sense?

alvaromuro wrote on Tuesday, June 12, 2018:

Fixed. I post my findings in case it helps anyone with similar issues:

The issue was caused by an incorrect management of the USART interrupts. I was activating the USART interrupt calling usart_read_buffer_job only at the points of the code when I was expecting to receive a message. However, this seems to be wrong, as some data may arrive a bit before the interrupt was active, therefore getting lost.

Thus, we configured the interrupt to be active all the time, by executing usart_read_buffer_job at the beginning of the program, and by activating again the interrupt every time the USART callback is called:

void usartGPRS_read_callback(struct usart_module *const usart_module)
	//store the received data in a circular buffer//
    GPRS_data_rx[data_in_GPRS_RX_buffer] = *rx_bufferGPRS; 
    //Activate the USART interrupt to be ready for the next coming data
	usart_read_buffer_job(&usartGPRS_instance, (uint8_t *)rx_bufferGPRS, MAX_RX_BUFFER_LENGTH_GPRS);

In this way, the USART interrupt receives all data and the systems works as expected.

rtel wrote on Wednesday, June 13, 2018:

Thanks for taking the time to report back.