Skip to main content
Senior
August 21, 2026
Solved

CMSIS RTOS: Event fired in SW Timer callback does not immediately run waiting thread

  • August 21, 2026
  • 6 replies
  • 152 views

Hello,

I implement kind of “lazy write cache” for flash and have problem.

The consumer thread sends out cache write requests to the flash thread using events.

The flash thread starts a SW timer which fires an event if no more cache write occurs.

In the oscilloscope I see that the timer callback is run after timeout occured but the flash thread, which is triggered by the callback, is not executed immediately (it is run as soon as the next cache write event is received).

I’m afraid this is a priority problem, but fiddling with task prios doesn’t help.

Any idea is greatly appreciated!

Thanks, 
Jochen

uint32_t NCB_Cache_Write(eREQID_t eRid, ePNORNUM_t eFid, uint32_t ulOfs, uint8_t bData) {
psNcbTaskArgs_t psArgs = &asNcbTaskArgs[eFid];

psArgs->pusBuf[ulOfs] = bData;
psArgs->ulAdr = ulOfs;

// run core thread after send request called by upper layer / send notification
osEventFlagsSet(psArgs->phEventId, NCB_FLAG_FLUSH_REQ);
}

static void NCB_Timer_CB(void *arg) {
// set TIMER event flag of appropriate thread
uint32_t ulTID = (uint32_t)arg;
psNcbTaskArgs_t psArgs = &asNcbTaskArgs[ulTID];

TEST_TRIGGER(1);
osEventFlagsSet(psArgs->phEventId, NCB_FLAG_TIMER_EXP);
TEST_TRIGGER(0);
}

static void NCB_CoreThread(void *argument) {
// configuration data passed via task argument
psNcbTaskArgs_t psArgs = (psNcbTaskArgs_t) argument;
:
while (1) {
psArgs->eEvtFlag = osEventFlagsWait(psArgs->phEventId, 0xffff,
osFlagsWaitAny, osWaitForever);

if(psArgs->eEvtFlag & NCB_FLAG_TIMER_EXP) {
TEST_TRIGGER(1);
osDelay(2);
TEST_TRIGGER(0);
} else if(psArgs->eEvtFlag & NCB_FLAG_FLUSH_REQ) {
TEST_TRIGGER(1);
osTimerStart(psArgs->phTimerId, NCB_CACHE_TIMEOUT_MS);
TEST_TRIGGER(0);
}
} // while(1)
} // NCB_CoreThread()


void NCB_Init(void) {
for (uint32_t iTID = 0; iTID < NCB_TASK_CNT; iTID++) {
psNcbTaskArgs_t psArgs = &asNcbTaskArgs[iTID];

ahNCBCoreThread[iTID] = osThreadNew(NCB_CoreThread, (void*) psArgs,
&NCB_Thread_attributes);

psArgs->phEventId = osEventFlagsNew(NULL);

// creates a one-shot timer, iTID passed as an argument to the callback function
psArgs->phTimerId = osTimerNew(NCB_Timer_CB, osTimerOnce, (void *)iTID, NULL);
} // for()
} // PNOR_CoreInit()

 

Best answer by Pavel A.

>  “Wait for any flag which is included in the flag mask t

But you wait with mask of 0xffff, which does contain your NCB_FLAG_FLUSH_REQ?

Also, check for possible error returns from osEventFlagsWait just in case.

 

6 replies

regjoeAuthor
Senior
August 21, 2026

I hate to reply to my own thread but some cups of coffee later I probably found my mistake.

But probably I misunderstood the the meaning of the “flags” parameter in osEventFlagsWait().

 

osFlagsWaitAny Wait for any flag (default).

 

The docs say “Wait for any flag”, and I understood “Any flag set will release the thread from blocked state”.

In the meantime, I guess it means “Wait for any flag which is included in the flag mask to release the thread from blocked state”.

Am I right? Unfortunately, I cannot check this today, will reply next week.

Thank you

Pavel A.
Pavel A.Best answer
August 22, 2026

>  “Wait for any flag which is included in the flag mask t

But you wait with mask of 0xffff, which does contain your NCB_FLAG_FLUSH_REQ?

Also, check for possible error returns from osEventFlagsWait just in case.

 

ST Employee
August 24, 2026

Hello ​@regjoe ,

your design sounds reasonable, and the behavior you describe indeed looks like it could be related to thread scheduling / priority, rather than the timer itself.

Maybe you need to check these points:

  1. The timer callback does not run the flash thread directly
    It only sets an event flag. The flash thread still needs to be scheduled by the RTOS before it can execute.

  2. Check the priority of the flash thread
    Make sure it is high enough compared with other runnable threads in the system. If another thread is continuously ready to run at the same or higher priority, your flash thread may be delayed.

  3. Also check the timer service context
    Depending on the RTOS configuration, the software timer callback may be executed by a timer thread/task. If that thread has low priority or is blocked, the wakeup of your flash thread can appear delayed.

  4. Verify whether the event is really set when expected
    Your oscilloscope trace suggests the callback runs, so it would be useful to add tracing/logging around:

    • osEventFlagsSet() in the timer callback
    • osEventFlagsWait() return in the flash thread
  5. Be careful with osDelay(2) in the flash thread That delay can make the timing look more confusing during debugging.

kind regards,

DK

"Please mark my answer as best by clicking on the “Accept as solution"" button if it fully answered your question. This will help other users find this solution faster.​"
regjoeAuthor
Senior
August 24, 2026

@Pavel A. :

Yes, the flag wasn’t included in the mask because I thought that mask is ignored if osFlagsWaitAny is specified. Now I setup the mask correctly and the thread is started immediately if receiver has higher prio than sender. Problem solved, thank you!

@Khaled_DHIF :  

Regarding topic 3 of your checklist, I’m puzzled if there are other priorities involved than the sender and receiver thread priority. As you said, the timer CB only sets an event flag which tells the receiver that this thread is runnable. Does the software timer also have a priority which has to be configured? Is there a scenario which can lead to block the timer CB execution? 

Bob S
Super User
August 24, 2026

One more thing to look at:  it is possible for osEventFlagsWait() to return MULTIPLE flags from a single call. Your code uses an “if/else if” structure which presumes only 1 event is returned at a time.  This needs to be a series of independent if() statements.  

regjoeAuthor
Senior
August 25, 2026

My first idea was that events are queued because I read somewhere that in FreeRTOS “everything is a queue”. Have to remove the “else”. Thank you