FreeRTOS multithreading issues (Interrupt+Queue+Tasks)

zouzman wrote on Friday, October 28, 2016:

Hi,

I am working with STM32L476xx microcontrroller and I am using FreeRTOS V8.1.2 with** heap4.c** configuration.

In my application , I have configured 2 tasks and one interrupt routine service.
The first task create a queue before entering the infinite loop . In its while(1) , if the queue is successfully created I activate the interrupt for receiving data through UART and I check if the queue has a new data to print on the terminal using this function :

if( xQueueReceive( RxQueue, &bRxBuffer, portMAX_DELAY ))
{
UART4->TDR = bRxBuffer;
}

Now , let’s go back to my uart callback . Once I get a new data from the terminal I disable the interrupt which has been enabled in my first thread . Then, I read data from the UART register and I send my buffer contents to the queue using this function :

if ( xQueueSendToBackFromISR( RxQueue, &aRxBuffer, &xHigherPriorityTaskWoken ))
** portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );

When I only implement the first task and the uart callback only without any other task , the application runs very well !!! After adding a simple task which only outputs using printf inside my IDE terminal IO window , the application crushs :(((

Following is my printf task implementation :

void CCW_DoNothing()
{
osThreadDef(NothingTask, NothingTask_Thread, osPriorityNormal, 0, configMINIMAL_STACK_SIZE*1);
NothingTaskxHandle = osThreadCreate(osThread(NothingTask), NULL);
}

static void NothingTask_Thread(void const argument)
{
while (1)
{
** BSW_PRINTF(" NOTHING TO DOOOO !!! \n\r");
osThreadSuspend(NULL);

}
}
*

To switch between my threads , I’m using osThreadResume(NothingTaskxHandle) inside my first task and I use osThreadSuspend(NULL) in the printf task.

The first thing I thought about when facing this issue is trying to change Tasks priorities but it doesn’t work.

My first task has osPriorityAboveNormal as priority and the uart callback priority is set to the lowest NVIC available level which is 15.

I have also tried to change stack sizes and it doesn’t work too :(((

Please need urgent help :frowning:

rtel wrote on Friday, October 28, 2016:

I don’t understand “To switch between my threads , I’m using
osThreadResume(NothingTaskxHandle)” first because the RTOS switches
between threads, second because you do not show where it is being
called, and third because it is not a FreeRTOS API function so
presumably has some form of abstraction layer code between it and the
actual FreeRTOS function.

A few notes:

  1. Do you still get the problem if you remove the call to printf()?

  2. Passing characters from a UART into a task using a queue is very
    inefficient. If characters are arriving slowly, for example characters
    typed into a terminal, then it is simple an convenient. If characters
    are arriving quickly then use a DMA interface ideally, and if that is
    not possible, simply place the characters in a circular buffer then use
    the efficient vTaskNotificationGiveFromISR()
    API function to unblock a task when the buffer contains a complete message.

  3. Do you have configASSERT()
    defined and stack
    overflow protection
    set to 2?

zouzman wrote on Friday, October 28, 2016:

Thanks for your replay ! Let me answer your questions :

  1. Yes . When I remove printf from the NothingTask and replace it by incrementing an integer , the application runs well .

  2. Sorry but I didn’t get well the difference between queues and circular buffers and how to implement the circular buffers too. I thought that in my use case , creating a queue that receives data in an interrupt callback then display it in the task by using these APIs : xQueueSendToBackFromISR and xQueueReceive will simply make me able to fill the queue and then retrieve data as a FIFO . Could you please clarify more the need for the circular buffer and if possible of course could you provide me with an example of implementation ?

  3. Yes . I do have configASSERT() defined and the configCHECK_FOR_STACK_OVERFLOW is set to 0.

rtel wrote on Friday, October 28, 2016:

  1. Yes . When I remove printf from the NothingTask and replace it by
    incrementing an integer , the application runs well .

printf() would seem to be the problem then. Some implementations of
printf() are massive, not thread safe, use huge amounts of stack, call
malloc(), etc. - all things that are really bad in small embedded
systems. Other implementations of printf() are tiny and designed to
work nicely in embedded systems. The FreeRTOS distribution has multiple
copies of a file called printf-stdarg.c, some of which are better than
others, that shows a light weight version. You just need to implement
the function at the very top of the file to output the characters how
you want (UART, terminal, whatever).

  1. Sorry but I didn’t get well the difference between queues and
    circular buffers and how to implement the circular buffers too. I
    thought that in my use case , creating a queue that receives data in an
    interrupt callback then display it in the task by using these APIs :
    xQueueSendToBackFromISR and xQueueReceive will simply make me able to
    fill the queue and then retrieve data as a FIFO . Could you please
    clarify more the need for the circular buffer and if possible of course
    could you provide me with an example of implementation ?

This is just a simple array, with a write pointer and a read pointer.
Each time you write data to the buffer move the write pointer onto the
next position until you reach the end, where you wrap back to the
beginning. Likewise the read pointer. Nothing fancy.

Searching “thread safe circular buffer” or “thread safe circular queue”
on the web will no doubt through up lots of implementations.

zouzman wrote on Friday, October 28, 2016:

Thanks again ! :)) I will try these tips , hope they resolve my problem ! :wink: