Skip to main content
Ala
Senior
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

KnarfB
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

Ala
AlaAuthor
Senior
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()?

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

Ala
AlaAuthor
Senior
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?

KnarfB
Super User
March 17, 2021

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

Ala
AlaAuthor
Senior
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????

Tilen MAJERLE
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