System hangs after some time

zaunpfosten wrote on Wednesday, May 07, 2008:

Hello,

I`ve been working with FreeRTOS now for some weeks.

I have 3 tasks
1) a simple "Blink LED Task" (LED on -> task delay -> led off -> task delay)
2) a task which polls a sensor (Mouse Sensor ADNS2610) (reads data -> wake up Com task -> self-suspend )
3) a Com Task which sends the sensor-data over the UART (sends data to PC -> wake up sensor task -> self-suspend )

If I use a long task delay (some seconds) in the com task instead of the self-suspend, everything works fine. But if I want to poll the sensor and transmit the data at "full speed" my system hangs after a while (seconds to 1 Minute).

What could be the Problem?
What could you recommend for reading the sensor and transmitting the data as fas as possible?

System:
ATMEL ATMEGA32 with 16 MHz
Preemption = 1
Based on the "AVR_ATMEGA323_WinAVR"-Demo
Compiler avr-gcc 4.2.2

rtel wrote on Wednesday, May 07, 2008:

How are you doing the self-suspend, and what un-suspends the task?  Are you really suspending or just delaying?

Regards.

zaunpfosten wrote on Wednesday, May 07, 2008:

basically

blinkTask(void)
{
  LEDon
  vTaskDelay( 500ms );
  LEDoff
  vTaskDelay( 500ms );
}

sensorTask( void )
{
  getSensorData
  vTaskResume( HandleComTask );
  vTaskSuspend( NULL );
}

comTask
{
  sendDataToPC
  vTaskResume( HandleSensorTask );
  vTaskSuspend( NULL );  // if replaced with vTaskDelay( 2000ms ) everything works fine
}

davedoors wrote on Wednesday, May 07, 2008:

So the com task un suspends the sensor task, and the sensor task un suspends the com task.  If this is correct then there is the opportunity for deadlock here which could be what your problem is.

A scenario -

i/ The sensor task calls vTaskResume( HandleComTask ), before the sensor task leaves the function call the com task starts to execute.

ii/ The com task does its thing then suspends itself.  Once suspended the sensor task can run again.

iii/ The sensor task leaves the vTaskResume() function call and then suspends itself.

iv/ Both tasks are suspended and nothing runs - deadlock.

Could this happen? If one task has a higher priority than the other it definitely could happen. If the tasks have the same priority then it could happen sporadically depending ont he phase of the tick interrupt.

If for example the com task has a higher priority than the sensor task then you never need to suspend the sensor task as it will not run until the com task has suspended again anyway - unless the com task makes any blocking calls.

To avoid the dead lock you could pass a binary semaphore between the tasks.

/* Assume semaphore is already created and the tasks have the appropriate infinite loops. */

sensorTask( void )
{
getSensorData
/* Give the semaphore to unblock the com task. */
xSemaphoreGive( xSem );
/* Wait for the com task to give the semaphore back. */
xSemaphoreTake( xSem, portMAX_DELAY );
}

comTask
{
/* Wait for the sensor task to give the semaphore back. */
xSemaphoreTake( xSem, portMAX_DELAY );
sendDataToPC
/* Give the semaphore to unblock the sensor task. */
xSemaphoreGive( xSem );
}

zaunpfosten wrote on Thursday, May 08, 2008:

Hey thanks for the explanation, I will try this later.

Another point is, that I completely forgot about two other tasks (serialTransmit, serialReceive) , which were already in the demo available (serial.c).
If I now start “spamming” the queues of my serialTransmit-Task, without checking if it’s not full, I am soon in another deadlock.

Thanks so far for the fast help, I will now try to modify my program.