ArenaLor
ArenaLor

Reputation: 485

FreeRTOS stuck in osDelay

I'm working on a project using a STM32F446 with a boilerplate created with STM32CubeMX (for peripherals initialization and middleware like the FreeRTOS with the CMSIS-V1 interface). I have two threads which communicate using mailboxes but I encountered a problem: one of the thread body is

void StartDispatcherTask(void const * argument)
{
    mailCommand *commandData = NULL;
    mailCommandResponse *commandResponse = NULL;
    osEvent event;
    for(;;)
    {       
        event = osMailGet(commandMailHandle, osWaitForever);
        commandData = (mailCommand *)event.value.p;

        // Here is the problem
        osDelay(5000);
    }
}

It gets to the delay but never gets out. Is there a problem with using the mailbox and the delay in the same thread? I tried also bringing the delay before the for(;;) and it works.

EDIT: I guess I can try to add more detail to the problem. The first thread send a mail of a certain type and then waits for a mail of another type; the thread in which I get the problem receive the mail go the first type and execute some code based on what it receive and then send the result as a mail of the second type; sometimes it is that it has to wait using osDelay and there it stop working but without going into any fault handler

Upvotes: 2

Views: 4683

Answers (3)

HelpingHand
HelpingHand

Reputation: 1468

As P__J__ pointed out in an earlier answer, you shouldn't use the osDelay() call in the loop1 because your task loop will wait at the osMailGet() call for the next request/mail until it arrives anyhow. But this hint called my attention to another possible reason for your observation, so I'm opening this new answer:2

As the loop execution is interrupted by a delay of 5000 ticks - could it be that the producer of the mails is filling the mailbox faster than the task is consuming mails? Then, you should inspect if this situation is detected/handled in the producer context.

If the producer ignores "queue full" return values and discards the mails before they have been transmitted, the system will only process a few mails every 5000 ticks (or it may lose all but a few mails after the first fill of the mailbox, if the producer in your example only fills the mailbox queue once). This could look like the consumer task being stuck, even if the main problem is about the producer context (task/ISR).


1 The osDelay() call can only help you if you want to avoid to process another mail within 5000 ticks if request mails are produced faster than the task processes them. But then, you'd have a different problem, and you should open a different question...

2 Edit: I just noticed that Clifford already mentioned this option in one of his comments to the question. I think this option must be covered by an answer.

Upvotes: 0

Babajan
Babajan

Reputation: 382

osStatus osDelay (uint32_t millisec)

The millisec value specifies the number of timer ticks.

The exact time delay depends on the actual time elapsed since the last timer tick.

For a value of 1, the system waits until the next timer tick occurs.

=> You have to check whether timer tick is running or not.

check this link

Upvotes: 0

0___________
0___________

Reputation: 67564

I would rather use standard freeRTOS API. ARM CMSIS wrapper is rubbish.

BTW I rather suspect osMailGet(commandMailHandle, osWaitForever);

the delay is in this case not needed at all. If you wait for the data in the BLOCKED state the task does not consume any processing power

If another guesses are:

  1. You are landing in the HF
  2. You are stacked in the context switch (wrong interrupt priorities )

use your debugger and see what is going on.

Upvotes: 1

Related Questions