What is normal method for running initialization code in FreerTOS?

daveharr wrote on Monday, March 27, 2017:

Hi, I’m using FreeRTSO 9.0.0. I have substantial initialization code that currently runs before I start up the task scheduler. Part of it involves timer interrupt handlers and SDMMC card access code that also has to function when the scheduler is running. Should I wait until all the initialization is done and then startup the scheduler or should I run all the initialization code as a run once task, delete the task and start the scheduler earlier on?

If the latter case, should I create only the initialization task first and then create the frequenty running application tasks from within that init task after all the initialization ahd been performed? Is that even possible?


rtel wrote on Monday, March 27, 2017:

There are several ways of doing this.

You can run the initialisation code before you start the scheduler, but
if you do, be aware that calling any FreeRTOS API functions will leave
interrupts disabled until the scheduler is started. You can manually
re-enable them, but if you do be sure no interrupt service routines
attempt to use any FreeRTOS functions, or force a context switch, until
such time that the scheduler is running.

You can also create an initialisation task, start the scheduler, perform
the initialisation in the created task, then have that task create all
the other tasks needed by your application. The initialisation task
could then either delete itself, or better yet, re-purpose itself and
then perform some application functionality.

Yet another way if you are using software timers (configUSE_TIMERS is
set to 1), and the timer daemon/service task has a priority above any
other tasks, would be to use the vApplicationDaemonTaskStartupHook()
callback. Set configUSE_DAEMON_TASK_STARTUP_HOOK to 1 in
FreeRTOSConfig.h, then provide an implementation of the above function
(it doesn’t take any parameters and returns void), and the function will
get called exactly once when the timer task starts. Provided the
priority of the time task is higher than any other task the callback
function is guaranteed to execute before any application tasks - but of
course you cannot make any blocking calls otherwise the time task will
sleep and one of your application tasks will execute.

richard_damon wrote on Wednesday, March 29, 2017:

My personal preference is to setup all quick to setup hardware and software before the schedule, things like the built-in peripheral or devices on the local bus that don’t need delays or waiting for interrupts to setup, Queue/Semaphores/Mutex/Tasks. This will finish in negligable time. Things that take ‘real I/O’ to initialize (devices out on a communication bus) will be initialized at the beginning of a task that is in charge of that device (if there is one, otherwise put it in the beginning of the most appropriate task). Any other tasks that depend on that device might not be created until after that initialization is complete.

I try to avoid creating a one-shot initialization task as its TCB/Stack then becomes dead space as my policy is to avoid heap usage after the system is initialized, so any heap issues will happen right at startup or not at all. Nothing much worse than trying to figure out why the heap gets exhausted after running 24 hours.

jackfarmersedge wrote on Wednesday, March 29, 2017:

I do the minimum necessary for hardware first, mostly enabling memory areas and configuring oscillators and clocks. After starting the scheduler with one task I start up all other tasks and device drivers with RTOS running to take advantage of interrupts and semaphores. Each task is responsible for initing certain peripherals, so effectively I have initialization driver code from each tasks running in parallel, no wasted time in spinlocks. The startup task becomes one of the application tasks after running through the startup sequence, no wasted task space.

spachner wrote on Thursday, March 30, 2017:


so far I understand FreeRTOS one could create a task dedicated for init stuff and delete the task by vTaskDelete() afterwards without any backdraw regarding the heap. Right?



richard_damon wrote on Thursday, March 30, 2017:

The guildlines I work under restrict most heap usage to startup time. Therefore, if I delete a task at the end of startup time, that space that is freed is ‘dead’ as after that point nothing is allowed to allocate from the heap. (If you work under different rules, you may get a different situation). This rule is to allow me to verify that no critical operation (and almost all operations tend to be critical) can fail due to a heap allocation failure on an untested path. (Heap fragmentation can cause delayed failures in some cases).

This is why I avoid creating a special initilization task, but put the initialization code at the beginning of some other task that will be needed.

Yes, at times you have functionality that is allowed to indicate that it isn’t available at the moment, and that sort of code could use the heap (and it is best if you can show that periodically you reach a state where all transitory allocations have been freed to reset the heap fragmentation), I just don’t seem to have such cases very often.