vTaskDelay()/vTaskDelayUntil() not yielding on NXP LPC1769 using MCUXpresso IDE v11.0.1 [Build 2563] [2019-09-01]

takiszoo wrote on Wednesday, October 09, 2019:

Hello,

I have three tasks to flash Red, Green and Blue LEDs on the board. The objective is to get the colours to blink periodically (all flashing at the same period) but out of phase so that no two colours are on at the same time.

I am trying to do this using a task for each LED colour, with task priorities 3 for red, 2 for green and 1 for blue. The tasks use vTaskDelayUntil() to synchronize their operations, i.e., while one LED is on, the other LEDs are off and delaying (presumably in blocked states).

However, I am having the problem that the highest priority task (Red LED Task) does not seem to enter the blocked state. Only the Red LED flashes. Using the debugger (and setting breakpoints within each task’s while (1) loop), I notice that the the lower priority tasks have the opportunity to run only once! After that, the highest priority task never yields (the scheduler stays in the Red task’s loop, even while executing the vTaskDelayUntil() API function).

And I attach the code and my FreeRTOSConfig.h file.

Any feedback would be appreciated.

Thanks,
Takis

takiszoo wrote on Wednesday, October 09, 2019:

Sorry, the source code is attached here…

rtel wrote on Wednesday, October 09, 2019:

Not looked at code in detail yet, but have you checked the value of
delayTicks inside the functions?

Start with one task only, and a long delay time to make it obvious when
the LED is toggling. With just a single task, if the LED does not seem
to be toggle at the frequency you think, set a break point in that task
and check the values are as you expect. Once you have that one task
working as expected you can add in the others.

takiszoo wrote on Wednesday, October 09, 2019:

Richard,

First of all thanks for responding so quickly!

Second, you figured out my problem! I set numticks manually, and the whole application works now.

I will now have to determine why my parameter passing through pvParameters is not working correctly. Pointers are the bane of my existence!

Thanks again

richard_damon wrote on Wednesday, October 09, 2019:

The problem may be that you are creating the structures you pass on the main stack. The main stack is reused in some ports for the interrupt stack, so its contents might not be preserved. Make those structures globals instead of function locals in main to see if that makes things work.

takiszoo wrote on Wednesday, October 09, 2019:

Richard,

Thanks for this point. I think it is spot on! I could not understand why the parameters were not being passed into the task functions. I wrote the code in this way to illustrate to my students that it is possible to pass in fairly complex data structures using type casting of void pointers within the task function.

Everything works now!

Cheers

richard_damon wrote on Thursday, October 10, 2019:

And if you put just a bit more data into the structures, you could make all three task use the same function to show the real power of it.

takiszoo wrote on Thursday, October 10, 2019:

Thanks again, to both Richards!

I added a mutex and now there is just a single task function! :slight_smile:

rtel wrote on Friday, October 11, 2019:

A couple of comments:

  1. A mutex is a very heavy object to use here, a simple and fast
    critical section is all that is needed.

  2. You are holding the mutex across the vTaskDelay() call - that should
    not be necessary especially if toggling will interleave with other tasks
    in which case you will serialise access by holding the mutex that long.

takiszoo wrote on Friday, October 11, 2019:

Richard, thank you for taking the time to look over the code and provide feedback! I cannot argue with your assessment because no one knows this kernel better than you.

However, I was hesitant to use taskENTER_CRITICAL()/taskEXIT_CRITICAL() because I thought all context switches are suspended during that section of code, whereas the mutex localizes the impact on context switching to a single resource (in this case, we are trying to have only one LED colour displaying at any time).

This example is admittedly contrived, but we are intentionally serializing access to prevent colour mixing, which is why I was using the mutex across the vTaskDelay()…

rtel wrote on Friday, October 11, 2019:

You are right in that you cannot call vTaskDelay() inside a critical
section created with taskENTER/EXIT_CRITICAL(), so my suggestion was not
clear, in that I only meant to protect accessing the LED with the
critical section. However from your last reply it sounds like you want
to protect access across the delay too.