xTimerIsTimerActive on v10.4.3 does not return NOT pdFALSE

I have 5 one shot timers that I set up to fire off some events. Each timer gets re-used (new period assigned and re-started, I know just changing the period automatically restarts the timer) at least once.

Everything works. I can see my flag values change, the event chain works without issue. The only problem I have is that I have a debug function to display the current state of the timers and my flags and the timers NEVER report as being active. Even though they must be for my outputs and flags to be changing in the exact way I expect.

They are 15s+ timers, I should have no problem seeing that they are active. I can see the flags I have as part of the event chain being set, and yet nothing I do has xTimerIsTimerActive return anything other than pdFALSE.

There are some other threads about this as well, but none of them seem to resolve in an actionable way. Help would be appreciated, thank you!

The issue you describe is

but the subject says xTimerIsTimerActive does NOT return pdFALSE ?
Is there a typo ?

No typo.
The title is “does not return NOT pdFALSE” double negative, because xTimerIsTimerActive is defined as returning pdFALSE if inactive, or some other value if active.

I wanted to make it clear that I knew what the function actually returns

I see - my bad. You wanted to make it more clear and confused me :grin:
However, I’m pretty sure xTimerIsTimerActive is working properly.
Hard to tell what’s wrong without the code ..
Did you do a simple check like starting a timer and verify it immediately with xTimerIsTimerActive ?

My first guess is your code (which you don’t show) is doing something wrong.

One thing to note, is that the timer won’t report “active” until the timer task runs an processes the request, the call to the timer function just queues up a request, so if the task isn’t lower in priority than the timer service tasks, if it checks right away, it likely won’t be set.

The code to track “active” is so simple, it is hard to see a problem with it in FreeRTOS (at least once you remember that it won’t get active until the Timer Task processes the queue entry).

Yeah there’s not really much to show?
I schedule a timer (in this case 15 seconds)

static int
doScheduleTimer(
OSUTILS_tTimerPtr theTimer,
const char timerName,
uint16 theTimeoutInMs,
uint8 autoRestart,
void
param,
OSUTILS_tTimerFunction theCallbackFunction
)
{
/* Locals */
int theStatus = -1;

/* Create the timer if needed */
if (theTimer == NULL)
theTimer = OSUTILS_TimerCreate(timerName, OSUTILS_ConvertMsToTicks(theTimeoutInMs), autoRestart, param, theCallbackFunction);

/* Sanity check /
if (theTimer != NULL)
{
/
Update the period (This will start the timer, but manually start afterwards just in case) /
if (OSUTILS_TimerChangePeriod(theTimer, OSUTILS_ConvertMsToTicks(theTimeoutInMs)) == 0)
{
if (OSUTILS_TimerStart(theTimer) == 0)
{
/
Successful, update theStatus */
theStatus = 0;
}
}
}

return theStatus;
}

The project here has an abstraction layer, but here is what it is doing:
OSUTILS_tTimerPtr
OSUTILS_TimerCreate(
const char *timerName,
uint32 periodInTicks,
uint8 isAuto,
void * param,
OSUTILS_tTimerFunction timerFunction
)
{
TimerHandle_t timerHandle = NULL;

if (timerName == NULL || timerFunction == NULL) return NULL;

timerHandle = xTimerCreate((const RTOS_CHAR_PTR)timerName, (TickType_t) periodInTicks, (UBaseType_t) isAuto, param, timerFunction);

return (OSUTILS_tTimerPtr) timerHandle;
}

and then starting it:
int
OSUTILS_TimerStart(OSUTILS_tTimerPtr theTimer)
{
BaseType_t retVal;

if (theTimer == NULL) return -1;

retVal = xTimerStart((TimerHandle_t) theTimer, portMAX_DELAY);

return (retVal == pdFALSE) ? -1 : 0;
}

So we start the timers, and I can see based on my logging that the GPIOs are toggling how I want them to according to that time, so I know the timers are working, hitting the callback function, sending the event for the next step in the process.

Now the debug function that I call from my console is just:
static void
doDisplayDeApp(
TCTHACT_tDevID theID
)
{
/* Locals /
static const char
trueStr = “TRUE”;
static const char* falseStr = “FALSE”;
static const char* segmentCompleteStr = " segment complete: ";
static const char* timerRunningStr = " timer running: ";
static const char* nextEventStr = "\tNext event to post: ";

/* It shouldn’t be possible to fail this, but just in case /
if (theID < PLATFORM_ID_MAX)
{
/
More locals /
const tHandler
theHandler = &(gMyHandlers[theID]);

/* Print the DeApp config, this also gets printed by "thermalctl actuator deapp config <id>" */
doPrintDeAppConfig(theHandler);

/* Print the relevant flags */
CONSOLE_Printn("\r\nDeApp Flags:");
CONSOLE_Printn("DeApp in progress:             %s", (theHandler->fFlags & FLAG_DEAPP_IN_PROGRESS) ? trueStr : falseStr);
CONSOLE_Printn("DeApp return%s%s", segmentCompleteStr, (theHandler->fFlags & FLAG_DEAPP_RETURN_COMPLETE) ? trueStr : falseStr);
CONSOLE_Printn("DeApp vacuum%s%s", segmentCompleteStr, (theHandler->fFlags & FLAG_DEAPP_VACUUM_COMPLETE) ? trueStr : falseStr);
CONSOLE_Printn("DeApp purge0%s%s", segmentCompleteStr, (theHandler->fFlags & FLAG_DEAPP_PURGE0_COMPLETE) ? trueStr : falseStr);
CONSOLE_Printn("DeApp purge1%s%s", segmentCompleteStr, (theHandler->fFlags & FLAG_DEAPP_PURGE1_COMPLETE) ? trueStr : falseStr);

/* Print the timer information */
CONSOLE_Printn("\r\nDeApp Timers:");
CONSOLE_Printn("ReturnSv%s %s", timerRunningStr, OSUTILS_TimerIsActive(theHandler->fReturnSvTimer) ? trueStr : falseStr);
CONSOLE_Printn("%s%d", nextEventStr, theHandler->fReturnSvTimerBundle.fEventToPost);
CONSOLE_Printn("VacuumSv%s %s", timerRunningStr, OSUTILS_TimerIsActive(theHandler->fVacuumSvTimer) ? trueStr : falseStr);
CONSOLE_Printn("%s%d", nextEventStr, theHandler->fVacuumSvTimerBundle.fEventToPost);
CONSOLE_Printn("Purge0Sv%s %s", timerRunningStr, OSUTILS_TimerIsActive(theHandler->fPurge0SvTimer) ? trueStr : falseStr);
CONSOLE_Printn("%s%d", nextEventStr, theHandler->fPurge0SvTimerBundle.fEventToPost);
CONSOLE_Printn("Purge1Sv%s %s", timerRunningStr, OSUTILS_TimerIsActive(theHandler->fPurge1SvTimer) ? trueStr : falseStr);
CONSOLE_Printn("%s%d", nextEventStr, theHandler->fPurge1SvTimerBundle.fEventToPost);
CONSOLE_Printn("Disengage%s%s", timerRunningStr, OSUTILS_TimerIsActive(theHandler->fDisengageTimer) ? trueStr : falseStr);
CONSOLE_Printn("%s%d", nextEventStr, theHandler->fDisengageTimerBundle.fEventToPost);

}

return;
}

with OSUTILS_TimerIsActive being:
int
OSUTILS_TimerIsActive(OSUTILS_tTimerPtr theTimer)
{
BaseType_t retVal;

if (theTimer == NULL) return FALSE;

retVal = xTimerIsTimerActive((TimerHandle_t) theTimer);

return (retVal == pdFALSE) ? FALSE : TRUE;
}

And I’ve tried this with calls directly to xTimerIsTimerActive and same thing, it never reports that it is active.

Sorry if the debug prints are a little difficult to read, I have to scrape the walls for bytes in this project. I’ve had to do a release with less than 300 Bytes of flash space free before.

I know that there is no guarantee that xTimerIsTimerActive will immediately report that it is active because it just queues up the timer task, but this is me manually triggering that debug print function repeatedly over 15 seconds and never once seeing it report TRUE, but all the other things, flags, next event to send etc. all do update as expected.

One thing I’m wondering is if calling xTimerStart after xTimerChangePeriod (which itself starts the timer) could be messing up xTimerIsTimerActive? If that was the case that’d be a problem with FreeRTOS

One thing, I don’t see gMyHandlers ever getting filled in, or tHandler defined. That seems to be in your abstraction layer, where the problem might be.

You should make sure that your timer handle being used in the active check matches that handle that is actually being used.

1 Like

Yeah sorry, I didn’t include where doScheduleTimer is being called from, here is a sample (the file is almost 9000 lines and does a bunch of other stuff so I can’t just put everything in here):

/* Only schedule the timer if the timeout in the configuration is > 0 /
/
otherwise, just send the event that it would have triggered right now */
if (theHandler->fDeAppConfig.fPreReturnMs > 0)
doScheduleTimer(theHandler->fReturnSvTimer, gReturnTimerName, theHandler->fDeAppConfig.fPreReturnMs, FALSE, &(theHandler->fReturnSvTimerBundle), doDeAppTimerCallback);
else
doPostEvent(theHandler->fDeviceID, theHandler->fReturnSvTimerBundle.fEventToPost);

Yeah I’m stupid, passing the timer into doScheduleTimer was not passing the pointer to theHandler through, it was sending a copy of whatever was in the handler through, but then not saving it anywhere. So trying to access via theHandler later didn’t do anything because nothing got saved back to it. Replacing the calls with &(theHandler→timerXXX) and in doScheduleTimer de-referencing it again fixed it.

My apologies for the stupid question! Actually keep track of your timer handlers folks!