Quality RTOS & Embedded Software

 Real time embedded FreeRTOS RSS feed 
Quick Start Supported MCUs PDF Books Trace Tools Ecosystem


Loading

Getting Stuck Inside Timer Callback

Posted by masoandro on June 5, 2018

Hello! First time poster, long time lurker. I'm getting a bit lost trying to track down a callback issue I am having. Basically, after a short time (not right away), I get stuck inside the callback and it loops indefinitely through the callback function. I'm using RTOS 7.3.0 on an ARM processor. I am using a timer to switch between a task, much like in this example.

I create the timer using xTimerCreate and the callback function is called successfully after taking the semaphore in the parent function. Inside the callback function, I am also calling other functions that take semaphores. The way I understand it, taking an additional semaphore, even in the callback, should allow a queue of the taken processes to form. This is because I have multiple functions communicating over the same bus - they have to wait their turn.

When, during the callback, the function is called, there is a xSemaphoreTake() followed by instructions, and then xSemaphoreGive(). It then returns to the callback function and - shoud - return to the parent function after I call xTimerStopFromISR(xTimer, &xHigherPriorityTaskWoken) and xSemaphoreGiveFromISR(parentSemaphore, &HigherPriorityTaskWoken).

One of my guesses is that, somewhere along the line, the semaphore address is being written over. But I don't see a change in the semaphore that would indicate this behavior. My other guess is that there is some kind of race condition where the routine I am calling from within my callback is trying to take a semaphore while a same priority semaphore is being taken elsewhere (all of my semaphores/tasks have the same priority).

Can anyone speak to this issue as to why the callback loops without ever returning back to its parent function?

Thank you!


Getting Stuck Inside Timer Callback

Posted by rtel on June 5, 2018

First time poster, long time lurker.

Welcome.

I'm getting a bit lost trying to track down a callback issue I am having. Basically, after a short time (not right away), I get stuck inside the callback and it loops indefinitely through the callback function. I'm using RTOS 7.3.0 on an ARM processor. I am using a timer to switch between a task, much like in this example https://www.freertos.org/a00124.html.

So, to be clear, you are using a semaphore from a HARDWARE timer to switch tasks, but the problem you are having is in the callback function of a SOFTWARE timer - correct?

I create the timer using xTimerCreate and the callback function is called successfully after taking the semaphore in the parent function.

It is not clear how taking the semaphore relates to the software timer callback function.

Inside the callback function, I am also calling other functions that take semaphores.

Timer callback functions are not supposed to do anything that could cause the calling task (in this case, the timer task, in which all software timer callback functions execute). Taking a semaphore inside a timer callback function is ok provided the block time (the last parameter in the function that takes the semaphore) is zero.

The way I understand it, taking an additional semaphore, even in the callback, should allow a queue of the taken processes to form. This is because I have multiple functions communicating over the same bus - they have to wait their turn.

I don't really understand that part.

When, during the callback, the function is called, there is a xSemaphoreTake() followed by instructions, and then xSemaphoreGive(). It then returns to the callback function and - shoud - return to the parent function after I call xTimerStopFromISR(xTimer, &xHigherPriorityTaskWoken) and xSemaphoreGiveFromISR(parentSemaphore, &HigherPriorityTaskWoken).

I'm afraid I am not following this. Timer callback functions are executed when a timer expires, do not loop, and do not return to a caller (at least, not as viewed by anything).

One of my guesses is that, somewhere along the line, the semaphore address is being written over. But I don't see a change in the semaphore that would indicate this behavior. My other guess is that there is some kind of race condition where the routine I am calling from within my callback is trying to take a semaphore while a same priority semaphore is being taken elsewhere (all of my semaphores/tasks have the same priority).

Can anyone speak to this issue as to why the callback loops without ever returning back to its parent function?

Perhaps if you posted some pseudo code that shows the structure of what you are describing - in particular the software timer callback function and the task woken by the semaphore - I might understand better.


Getting Stuck Inside Timer Callback

Posted by masoandro on June 5, 2018

So, to be clear, you are using a semaphore from a HARDWARE timer to switch tasks, but the problem you are having is in the callback function of a SOFTWARE timer - correct?

Yes, that is correct.

Perhaps if you posted some pseudo code

That will be easiest I think...

Definitions in main: ~~~ volatile portBASETYPE commTaskHandle; volatile xSemaphoreHandle commTaskSemaphore; volatile portBASETYPE anotherTaskHandle; volatile xSemaphoreHandle anotherTaskSemaphore; volatile xTimerHandle xTimer; ~~~

Then during setup: ~~~ /* xTimerCreate ( text name, timer period in ticks, auto-reload timer, timer ID ) */ xTimer = xTimerCreate( (const signed char *) "Comm Timer", 1, pdTRUE,
(void *) 0), vTimerCallback);

/* Start the timer with no block time */ xTimerStart( xTimer, 0 )

/* Create the commTask */ commTaskHandle = xTaskCreate(commtask, "Comm", 2024, NULL, 1, NULL); anotherTaskHandle = xTaskCreate(anothertask, "Another", 2024, NULL, 1, NULL);

/* Now set up the tasks */ vSemaphoreCreateBinary(commTaskSemaphore); vSemaphoreCreateBinary(anotherTaskSemaphore);

/* Start the scheduler */ vTaskStartScheduler();

void comm_task(void * arg){ while(1){ xSemaphoreGive(anotherTaskSemaphore); xSemaphoreTake(commTaskSemaphore); comm(...); } }

void another_task(void * arg){ while(1){ /* ... */ } } ~~~

Then, the comm() code is what switches back and forth between the timer ~~~ BaseType_t xHigherPriorityTaskWoken = pdFALSE; volatile xTimerHandle commTimer; /used for the vTimerCallback/ volatile xSemaphoreHandle commSemaphore; /synch between comm() and vTimerCallback()/

/* initialize the semaphore */ vSemaphoreCreateBinary(commSemaphore); xSemaphoreTake(commSemaphore, portMAX_DELAY);

/* Now the callback function / void vTimerCallback(xTimerHandle xTimer){ / ... / / calls to other semaphore controlled tasks / / ... / / End of callback task, should only run once */ xTimerStopFromISR( xTimer, &xHigherPriorityTaskWoken );

/* Event has occured, unblock the caller task now */
xSemaphoreGiveFromISR( sensorSemaphore, &xHigherPriorityTaskWoken);

}

/* And the parent function (called from main) void comm(...){ xSemaphoreTake(commSemaphore, portMAX_DELAY); /* ... / / uses data from the callback / / ... */ xTimerStart( commTimer, 0 ); } ~~~

The switching occurs just fine for about a minute into the operation before looping exclusively inside vTimerCallback, which includes the calls to other semaphore-controlled functions.

Timer callback functions are executed when a timer expires, do not loop, and do not return to a caller

That is why I am confused as to why the vTimerCallback does not complete and give the semaphore back to comm(), causing it to resume to where it was set up in the first place. I don't see any change in the semaphore or the timer in memory but somehow it loses the association.


Getting Stuck Inside Timer Callback

Posted by masoandro on June 6, 2018

Ok I tracked it down...very carefully. Here are my thoughts: my code elsewhere in the program was using vTaskDelay during the execution of the timer code. I'm not sure if this would be considered a race condition, but if vTaskDelay was called during the timerCallback, the return address was somehow corrupted by the delay and it simply restarts at the top of function memory pointer. I changed to a standard hardware delay and it is no longer an issue. Does this analysis make sense? What would be a way to modify vTaskDelay to properly switch and restore the timer's location?


[ Back to the top ]    [ About FreeRTOS ]    [ Privacy ]    [ Sitemap ]    [ ]


Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.

Latest News

FreeRTOS v10.2.1 is available for immediate download. MIT licensed, includes 64-bit RISC-V, NXP Cortex-M33 demo & Nuvoton Cortex-M23 demo.

NXP tweet showing LPC5500 (ARMv8-M Cortex-M33) running FreeRTOS.

View a recording of the "OTA Update Security and Reliability" webinar, presented by TI and AWS.


Careers

FreeRTOS and other embedded software careers at AWS.



FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

Cadence Tensilica Cortes

Espressif ESP32

IAR Partner

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

Mediatek

Renesas

RISC-V

SiFIve RISC-V

STMicro RTOS partner supporting ARM7, ARM Cortex-M3, ARM Cortex-M4 and ARM Cortex-M0

Texas Instruments MCU Developer Network RTOS partner for ARM and MSP430 microcontrollers

OpenRTOS and SafeRTOS

Xilinx Microblaze and Zynq partner