Skip to main content
Visitor II
March 17, 2021
Question

UART DMA receive via RTOS

  • March 17, 2021
  • 5 replies
  • 3333 views

hey there

there is a simple question: how can I receive data on my UART in DMA mode using RTOS? recently I ran a project where I just get all the data right when they arrived using UART DMA. but not I what the whole process to be done using RTOS. how can I do that?

    This topic has been closed for replies.

    5 replies

    Super User
    March 17, 2021

    If you already have a cyclic DMA receive buffer, there are several options. If the serial data is more or less a countinous data stream you write a consumer task blocking on a semaphore or task event. You also implement the half-full+full handlers/callbacks and let them fire the semaphore/task event, thereby unblocking the task which can now process half of the DMA receive buffer.

    You could further decouple the interrupts from the consumer task by using a queue.

    If the serial data is only some spontaneous sending of few bytes, you can implement a consumer task having a timer/wait, periodically polling for new data.

    Finally, you can combine both approaches.

    hth

    KnarfB

    AlaAuthor
    Visitor II
    March 17, 2021

    ok then I'll try.

    an other question: what to do if I want a task to be done only once in main()?

    Super User
    March 17, 2021

    A task can suspend itself and will never be scheduled again (unless Resumed by someone else). In addition, it might be also deleted but I somehow recall that there were issues with that.

    AlaAuthor
    Visitor II
    March 17, 2021

    dear KnarfB

    here is my code

    void SENDATTask(void const * arg)
    {
    	while(1)
    	{
    	
    	if (Sim800_at_sendCommand("AT\r\n", 5000, (char*)SIM800.msg.buff, sizeof(SIM800.msg.buff), 1, "\r\nOK\r\n") == 1)
    	{
    		osDelay(500);
    		HAL_IWDG_Refresh(&hiwdg); //Reload Watchdog inorder to prevent Micro Reset	
    	}
    			
    	}
    	vTaskDelete(SENDATTaskHandle);
    	vTaskSuspend(SENDATTaskHandle);
    		}
    }

    eigther I use vTaskDelete() or vTaskSuspend(), the task continues to run... why is that?

    Super User
    March 17, 2021

    maybe the MCU resets and restarts because you stopped feeding the watchdog?

    AlaAuthor
    Visitor II
    March 17, 2021

    HELP:

    I added some tasks to just check state of a pin, but what happens is that the scheduler stucks in the task of UART receive... why? I mean the added task do not need any resources and all of them have same priority...

    void UARTTask(void const * arg)
    {
    		while(1)
    		{
    			 HAL_IWDG_Refresh(&hiwdg); //Reload Watchdog inorder to prevent Micro Reset	
    				UartDataRec_FUN();
    		}
    }
     
    void SEND_Initial_AT_Task(void const * arg)
    {
    		while(1)
    		{
     
     //stuff that I mentioned in privious posts ....
    	}
    	vTaskSuspend(SEND_Initial_AT_TaskHandle);
    		}
    }
     
    void CheckAntenna_Task(void const * arg)
    {
    		while(1)
    		{
    			 HAL_IWDG_Refresh(&hiwdg); //Reload Watchdog inorder to prevent Micro Reset	
    				CheckAntenna();
    		}
    }

    it doesn't go through CheckAntenna_Task() and stucks in UARTTask() where it receives via UART DMA, whyyyyy????

    ST Employee
    March 17, 2021

    Usually application isn't aware of length of data to receive. You may implement the approach as described on Github article:

    https://github.com/MaJerle/stm32-usart-uart-dma-rx-tx

    In a nutshell, it works like this:

    • DMA TC and HT events are writing to message queue
    • UART IDLE is writing to message queue
    • dedicated thread is waiting for data from message queue and does processing of the data
    • Process repeats forever