Posting to queues before scheduler starts?

mr68360 wrote on Thursday, May 12, 2011:

I have been instantiating and populating queues, using xQueueSend(), in a setup routine called from main(), **before **calling vTaskStartScheduler().  This seems to work, but the FreeRTOS manual indicates only task, queue, and semaphore **creation ** calls should be done before starting the scheduler.

Is there a definitive “yes” or “no” to the question of calling xQueueSend() before the scheduler starts?

Thanks, any and all.

edwards3 wrote on Thursday, May 12, 2011:

It is probably ok as long as the block time is always 0.

richard_damon wrote on Saturday, May 14, 2011:

When I have had to do this, I used the FromISR api functions, as these by definition will not try to block, and need less of the system set up. They also are less apt to mess up the interrupt structure.  Note that the normal API functions use critical sections that require some information to be set up ahead of time, and may enable the interrupts on exit, before the system is really set up to handle them.

mr68360 wrote on Saturday, May 14, 2011:

Thanks, Richard.  Interesting info on the ‘ISR’ functions.

If we wish to start the program with a know number of available resources available (that are dispensed from a queue), then there seems to be no other way to do so, except with doing a pre-scheduler-start post.

I’m wondering if it would be better to create a “master” init thread that (1) has init code that initializes queues, mutexes, etc, then (2) spawns the rest of the worker tasks in the system in order.  The init code would then be guaranteed to be called from within a running thread.  (That task would either suspend, or it could remain active as a “monitor task” or something-so as not to “waste” the task’s resources-we don’t use dynamic memory, so we have no task deletions.)

All the FreeRTOS examples I’ve seen show the creation of all tasks in main(), then a final vTaskStartScheduler() call.  I have not attempted making xTaskCreate() calls from within a running task, but, if that is ok to do, it just might fix some of the problems inherent with calling APIs before the scheduler has started.

Might anyone know the legality of tasks spawning tasks?

richard_damon wrote on Saturday, May 14, 2011:

Task spawning task is perfectly legal. Having an "init’ thread, that then becomes something else can be a workable strategy. My first thought is you may want it to be a “high” priority task, so that as you create/start tasks you don’t interrupt the init task and delay the rest of the creation. You could start it high, and it can then change its priority low when done with the init.

mr68360 wrote on Saturday, May 14, 2011:

An EXCELLENT idea regarding the change of priority.  Thank you very much.

destremps wrote on Sunday, May 15, 2011:

There’s more to say that may help. The ‘highest priority at the time’ init task that spawns all other tasks is indeed a nice way to kick it all off. You can even suspend the init task ‘until’ a newly created task signals it’s okay to continue. This way you can initialize hardware in a known predictable order. For example in the init task:

create a binary semaphore
take it
create a new ‘lower priority task’ … say a driver task for some piece of hardware
SUSPEND the init task
(now what happens?)
the newly created task is the only other task that has ‘anything’ to do so it runs (remember this is very early on in the
startup)…it runs till it gives the semaphore
now the startup task continues
(you can repeat this)

I’ve managed the startup this way.

mr68360 wrote on Monday, May 16, 2011:

Nice, mizer.  I assume that your suspend is actually a pend on the semaphore you created (init waits for the dependent task to signal that it-the dependent task-is ready to allow more init to occur)?

One might wish to provide an upper-bound time limit on that pend, given that the dependent task might not itself finish its own initialization in a timely manner.

On the other hand, if one doesn’t care about start-up order, one could create a unique semaphore for each non-init task (let’s call them ‘child tasks’).  These semaphores begin life in the non-signaled state.  When the init task spawns each child, it simply waits on all of the semaphores-waiting for each child to signal that its initial operations are complete.  The order of wait would not be critical: regardless of signaling order, the init task would only fall through when it can take all the semaphores it is waiting on.

(An example of what I mean:  child 1 is spawned, then child 2, but child 2 signals before child 1 does.  If init waits first for child 1, then fine-it waits.  After init takes child 1’s semaphore, it immediately takes child 2’s semaphore-because it had previously been signaled.  Regardless of the order, eventually everyone’s semaphore get’s taken.)

But, again, some upper time limit for waiting on each child might be in order.

I like mizer’s idea because only one semaphore is involved (less resources), and it lends itself to fine-grained start-up control.  However, if the start-up sequence changes, there there must be code rearrangement.  If the order is less important than not having to modify code-that is, if one simply wants to provide a more coarse-grained, “bulk” approach, perhaps my scheme would serve.

I love lots of tools for lots of different problems!