Post Go back to editing

How to Prevent UART Data Loss When FreeRTOS Task Dispatches Overlap with Interrupts?

Category: Hardware
Product Number: ADSP-SC594

I am experiencing an issue where UART data is lost when a FreeRTOS task dispatch overlaps with a UART DMA interrupt.

・Problem:
When a FreeRTOS task is dispatched while waiting for UART data, several hundred bytes of data are lost.
The UART DMA interrupt callback function is not triggered during this time.

Suspected Cause:
I suspect that the FreeRTOS task dispatch has a higher priority than the UART DMA interrupt, which prevents the callback function from being executed.
I would appreciate your advice on this.

Question:
How can I ensure that the UART DMA interrupt callback is always triggered, even when a FreeRTOS task is dispatched?
Are there specific priority settings or configurations I should adjust to prevent data loss?

Current Configuration:
- UART DMA interrupt priority: Set using adi_sec_SetPriority().
- FreeRTOS task priority: Set using xTaskCreateStatic().

・Environment:
- Processor: ADSP-SC594 Core0 (Arm Cortex-A5)
- IDE: CrossCore Embedded Studio 3.0.1.0
- FreeRTOS Version: V10.5.1 (installed via add-in)

Sample Code:

#include <sys/platform.h>
#include <sys/adi_core.h>
#include <services/spu/adi_spu.h>
#include <services/int/adi_sec.h>
#include <drivers/uart/adi_uart.h>
#include "FreeRTOSConfig.h"
#include "FreeRTOS.h"
#include "task.h"

ADI_SPU_HANDLE Handle_Spu;
uint8_t Wk_Mem_Spu[ADI_SPU_MEMORY_SIZE];
ADI_UART_HANDLE Handle_Uart;
uint8_t Wk_Mem_Uart[ADI_UART_BIDIR_MEMORY_SIZE];
char RecvBuf_Uart_Rx[1024];
char *RecvBuf_Uart_Rx_Curr = RecvBuf_Uart_Rx;
ADI_PDMA_DESC_LIST DescList_Uart_Rx[2] __attribute__((section (".l2_uncached_data"))) __attribute__((aligned(4U)));
uint8_t Dma_RecvBuf_Uart_Rx[2] __attribute__((section (".l2_uncached_data"))) __attribute__((aligned(4U)));
TaskHandle_t Handle_Task_A;
TaskHandle_t Handle_Task_B;
StackType_t Stack_Task_A[1024];
StackType_t Stack_Task_B[1024];
StaticTask_t StaticTask_Task_A;
StaticTask_t StaticTask_Task_B;
---------------------------
void callback_uart_rx(void *param, uint32_t event, void *arg)
{
	switch (event)
	{
	case ADI_UART_EVENT_RX_PROCESSED:
		*RecvBuf_Uart_Rx_Curr++ = *(char *)arg;
		if (RecvBuf_Uart_Rx_Curr >= &RecvBuf_Uart_Rx[1024]) RecvBuf_Uart_Rx_Curr = RecvBuf_Uart_Rx;
		break;

	default:
		break;
	}
}
---------------------------
void task_a(void *param)
{
	while (true)
	{
		for (volatile size_t cycle_cnt = 1000000UL; _cycle_cnt; _cycle_cnt--) __asm volatile("NOP");
		vTaskDelay((TickType_t)100 / portTICK_PERIOD_MS);	/* dispatch */
	}
}
---------------------------
void task_b(void *param)
{
	while (true)
	{
		vTaskDelay((TickType_t)100 / portTICK_PERIOD_MS);	/* dispatch */
		for (volatile size_t cycle_cnt = 1000000UL; _cycle_cnt; _cycle_cnt--) __asm volatile("NOP");
	}
}
---------------------------
	/* Initialize SPU */
	adi_spu_Init(0u, Wk_Mem_Spu, NULL, NULL, &Handle_Spu);
	adi_spu_EnableMasterSecure(Handle_Spu, 29, true);	/* UART0 */
	adi_spu_EnableMasterSecure(Handle_Spu, 79, true);	/* UART0 Rx DMA */

	/* Initialize SEC */
	adi_sec_SetPriority(SEC_UART0_RXDMA, 100);	/* Set Priority to UART0 Rx DMA */

	/* Set Descriptor List */
	DescList_Uart_Rx[0].pNxtDscp   = &DescList_Uart_Rx[1];
	DescList_Uart_Rx[0].pStartAddr = &Dma_RecvBuf_Uart_Rx[0];
	DescList_Uart_Rx[0].Config     = ENUM_DMA_CFG_XCNT_INT;
	DescList_Uart_Rx[0].XCount     = 1;
	DescList_Uart_Rx[0].XModify    = 1;
	DescList_Uart_Rx[0].YCount     = 0;
	DescList_Uart_Rx[0].YModify    = 0;
	DescList_Uart_Rx[1].pNxtDscp   = &DescList_Uart_Rx[0];
	DescList_Uart_Rx[1].pStartAddr = &Dma_RecvBuf_Uart_Rx[1];
	DescList_Uart_Rx[1].Config     = ENUM_DMA_CFG_XCNT_INT;
	DescList_Uart_Rx[1].XCount     = 1;
	DescList_Uart_Rx[1].XModify    = 1;
	DescList_Uart_Rx[1].YCount     = 0;
	DescList_Uart_Rx[1].YModify    = 0;

	/* Initialize UART */
	adi_uart_Open(ADI_UART_0, ADI_UART_DIR_BIDIRECTION, Wk_Mem_Uart, ADI_UART_BIDIR_MEMORY_SIZE, &Handle_Uart);
	adi_uart_ConfigBaudRate(Handle_Uart, 1, 135);
	adi_uart_SetWordLen(Handle_Uart, ADI_UART_WORDLEN_8BITS);
	adi_uart_EnableParity(Handle_Uart, false);
	adi_uart_RegisterCallback(Handle_Uart, callback_uart_rx, NULL);
	adi_uart_DMARead(Handle_Uart, DescList_Uart_Rx, 2, ADI_PDMA_DESCRIPTOR_LIST);

	/* Create Task */
	Handle_Task_A = xTaskCreateStatic(task_a, "task_a", 1024, NULL, tskIDLE_PRIORITY + 3, Stack_Task_A, &StaticTask_Task_A);
	Handle_Task_B = xTaskCreateStatic(task_b, "task_b", 1024, NULL, tskIDLE_PRIORITY + 2, Stack_Task_B, &StaticTask_Task_B);

Edit Notes

The question is the same but the writing style has been adjusted.
[edited by: MrKK at 7:08 AM (GMT -4) on 23 Apr 2025]

Thread Notes

  • Hi,

    Thank you for your inquiry.

    We have created a RTOS project with three tasks and integrated UART stop mode code into that. This code will send the data from UART0 to UART1. We are able to see the correct data continuously in the Rxbuffer. We didn't set the priority for UART Rx DMA also.

    Did you check the behavior of the application with default priorities.

    Could you please share your complete project which simulates this observation in SC594 evaluation kit. This would be helpful for us to assist you better.

    Waiting for your reply.

    Best Regards,
    Santhakumari.V

  • Hi Santhakumari.V,
    Thank you for your reply.
    I am sorry for the delay in replying as I was absent for a week due to the May holiday week (* commonly known as Golden Week).

    > We have created a RTOS project with three tasks and integrated UART stop mode code into that.
    > This code will send the data from UART0 to UART1.
    > We are able to see the correct data continuously in the Rxbuffer.
    > We didn't set the priority for UART Rx DMA also.
    Thank you for creating it.
    But where can I get the integrated project?
    I can't find it.

    > Could you please share your complete project which simulates this observation in SC594 evaluation kit.
    Thanks for the sharing suggestion.
    I would like to share the same code and review it with you.
    However, how exactly can I share my project?
    I can't seem to attach a zip file?

    Best Regards,

  • I discovered that you can insert it from the menu "[Insert]->[External Content]".

    InsertMenu

    But, the company I am currently working for prohibits me from accessing these network storage for security reasons.
    However, I think you can send it as an attachment to an e-mail.

  • Hi,

    Please find the attached project that we created early in UART DMA stop mode which works fine in our eval kit. You can share your project to us via processor.tools.support@analog.com mail. While sending this please add this Ezone link as a reference. 

    SC594_UART_FreeRTOS.zip

    Best Regards,

    Santhakumari.V

  • Hi,
    Thank you for replying and providing the project.
    I finally learned that I can add zip files from the menu "[Insert]->[Image/video/file]".
    I am sorry for the trouble you went through to provide me with your email address.
    The zip file attached below is the project we have identified.
    This project is designed to connect the P3 connector (*USB Type-C connector) on the EV-SC594-SOM board to a PC via USB, send data from the PC via UART, and receive data from the SC594.
    SampleForEngineerZone.zip

  • Hi,
    We have checked the "SC594_UART_FreeRTOS.zip" you provided.
    However, this approach was not what we wanted to do for the following reasons.

    • The UART communication is done only in the closed environment of SC594.
    • Transmitter and receiver are synchronizing with each other to perform UART communication.

    Unfortunately, the "SC594_UART_FreeRTOS.zip" was not a reference.

    What we want to do is as follows:

    • We want to receive data from outside the SC594 via UART communication.
    • We want to receive data without synchronization.
    • We want to give priority to UART in case of interference with FreeRTOS.

    I would appreciate your advice.
    Thank you and best regards,

  • Hi,

    We tested your project in EV-SC594-SOM that you shared earlier, by providing the input from Tera Term application by connecting P3 connector from SC594 SOM to PC using type-c USB connector and it is working fine. Please find the attached image for your reference.

    Also for setting the UART interrupt priority in ARM core the GIC API need to be used, since in ARM core the interrupt will process via Generic Interrupt Controller(GIC). Please refer the below snippet:

    #include <services/int/adi_gic.h>

    adi_gic_SetIntPriority(INTR_UART0_RXDMA, 100);

    Hope this helps.

    Best Regards,
    Santhakumari.V

  • Hi,
    Thank you for confirming the my project and for the advice about "adi_gic_SetIntPriority".

    My apologies, I did not explain myself well enough.
    As you say, it is true that when we carefully sent 1byte at a time via TeraTerm, we were able to confirm my environment that SC594 received the data without missing 1byte.

    However, what about when multiple bytes are sent at once using the TeraTerm menu "[Edit]->[Paste]"? (e.g. Paste "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" string.)
    Our environment checks showed that most of the bytes were not received.
    How about confirmation in your environment?
    The expected behavior is to be able to receive multiple bytes sent without missing 1byte.

    I would appreciate your advice.
    Thank you and best regards,

  • Hi,
    Currently, my project is designed to trigger an interrupt upon UART reception, and the received data is obtained within the interrupt handler.
    This interrupt mechanism operates independently of FreeRTOS's task dispatching.
    Would this approach to obtaining UART reception data potentially cause issues for the system as a whole when using FreeRTOS as the OS?
    (*Note: In practice, we are experiencing issues.)
    If this method itself is problematic, I would greatly appreciate any suggestions for alternative approaches to obtaining UART reception data.
    On the other hand, if the method is not inherently flawed, I would be grateful for your guidance on why the UART reception data cannot be obtained correctly in the current situation.
    Thank you very much for your assistance.
    Best regards,

  • Hi,

    We suspect this UART reception won't create any issue in RTOS task dispatching. 

    We have tried to send 10bytes of data by modifying the descriptor xcount to 10 and we could receive the data in the RecvBuf_Uart_Rx.

    Please find the attached modified code for your reference.  

    Could you please check and let us know whether this meet your requirement. 

    Best Regards,
    Santhakumari.V

    SampleForEngineerZone_Core.zip