0
votes

I have a specific task routine which performs some operations in a specific order, and these operations handle few volatile variables. There is a specific interrupt which updates these volatile variables asynchronously. Hence, the task routine should restart if such an interrupt occurs. Normally FreeRTOS will resume the task, but this will result in wrong derived values, hence the requirement for restarting the routine. I also cannot keep the task routine under critical section, because I should not be missing any interrupts.

Is there a way in FreeRTOS with which I can achieve this? Like a vtaskRestart API. I could have deleted the task and re-created it, but this adds a lot of memory management complications, which I would like to avoid. Currently my only option is to add checks in the routine on a flag to see if a context switch have occured and if yes, restart, else continue.

Googling did not fetch any clue on this. Seems like people never faced such a problem or may be its that this design is poor. In FreeRTOS forum, few who asked for a task-restart didn't seem to have this same problem. stackOverflow didn't have a result on freertos + task + restart. So, this could be the first post with this tag combination ;)

Can someone please tell me if this is directly possible in FreeRTOS?

2

2 Answers

0
votes

You can use semaphore for this purpose. If you decide using semaphore, you should do the steps below.

  • Firstly, you should create a binary semaphore.
  • The semaphore must be given in the interrupt routine with xSemaphoreGiveFromISR( Example_xSemaphore, &xHigherPriorityTaskWoken );
  • And, you must check taking semaphore in the task.

    void vExample_Task( void * pvParameters ) {
    for( ;; ) {
    if (xSemaphoreTake( Example_xSemaphore, Example_PROCESS_TIME)==pdTRUE) {

    } } }

0
votes

For this purpose you should use a queue and use the queue peek function to yield at your volatile data.

I'm using it as I have a real time timer and this way I make the time available to all my task, without any blocking.

Here it how it goes: Declare the queue:

xQueueHandle     RTC_Time_Queue;

Create the queue of 1 element:

RTC_Time_Queue = xQueueCreate( 1, sizeof(your volatile struct) );

Overwrite the queue everytime your interrupt occurs:

xQueueOverwriteFromISR(RTC_Time_Queue, (void*) &time);

And from other task peek the queue:

xQueuePeek(RTC_GetReadQueue(), (void*) &TheTime, 0);

The 0 at the end of xQueuePeek means you don't want to wait if the queue is empty. The queue peek won't delete the value in the queue so it will be present every time you peek and the code will never stop.

Also you should avoid having variable being accessed from ISR and the RTOS code as you may get unexpected corruption.