I would like to perform all memory allocation early before starting the scheduler.
I understand that this is possible and permissible from here: https://forums.freertos.org/t/give-semaphore-before-starting-kernel/13131 and here: https://forums.freertos.org/t/create-kernel-objs-before-scheduler-start/8574
However, when I attempt to call xSemaphoreCreateBinary() before starting the scheduler, I note that interrupts are turned off once xSemaphoreCreateBinary() returns.
This is referenced here: https://www.freertos.org/FreeRTOS_Support_Forum_Archive/July_2017/freertos_Using_Mutex_before_scheduler_starts_34ad0b10j.html
…and is a side effect of ulCriticalNesting being intentionally set to a large number in port.c and only initialised to 0 when xPortStartScheduler() is called. I am inferring that this behaviour is a feature not a bug.
Can someone explain a) why pre-scheduler-start API calls breaking my interrupts would be desirable?
and b) what is the best/safest/most-canonical way to initialise FreeRTOS kernel objects/Semaphores before starting the scheduler?
The reasoning is that you normally shouldn’t be using interrupts (at least that get disabled) before the scheduler starts, as before the scheduler starts, ISRs should call any FreeRTOS APIs.
A normal application will create all the needed resources and tasks before the scheduler starts, and might do simple basic initialization of the hardware (which won’t need interrupts) and then starts the scheduler, which enable the interrupts and THEN any initialization that needs interrupts can run, and that code can use all the FreeRTOS resources, including blocking and releasing tasks.
you normally shouldn’t be using interrupts (at least that get disabled) before the scheduler starts
^^This was my hang-up: It’s taken some world-view realignment to picture interrupts as a principally OS thing, not a hardware thing.
initialization of the hardware (which won’t need interrupts)
^^Again I found this idea initially jarring: Of course hardware peripherals can require ISRs as part of their normal functioning and initialisation, and it’s not for an OS to preclude this.
My current rationalisation is to split interrupts into two categories: I’ve rearranged my interrupt priorities to better separate “system” interrupts (that do not make FreeRTOS API calls) and “application” interrupts (which are part of the normal operation of the device business logic, and can make API calls).
I think/hope this is aligned to the FreeRTOS world view, as per the basepri masking/configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY?
The key is to ask yourself, “Why do devices use interrupts?”, and the answer is to let the application do something else while the device is processing. Since that is also the reason you are using an RTOS, when you want to use interrupts, you should be using the RTOS.
A “Bare Metal” application might employ some ad-hoc method to achieve this sharing, like start up the operations, let the ISR pass chucks of data, and then later check if it is done while doing some other task, and then maybe prepare another chunk to go out.
Under a RTOS, those two operations are broken into two tasks, so rather than the “main loop” periodically checking if the device needs to be feed, there is a task that is doing that which “blocks” waiting for the completion signal, and then it gets unblocked an processes as soon as possible, without needing the rest of the system to finish a step and get back to checking it. (But if some more important operation is active, it needs to wait for that to finish needing the CPU).
Depending on what you think of as “System” interrupts, many of those likely should be connecting with FreeRTOS as the “Real Time” tasks will be needing the notifications from them. My normal use of higher than MAX_SYSCALL_INTERRUPT_PRIORITY ISRs are ultra-time critical control loops that do all their work inside the ISR, and thus don’t need FreeRTOS calls (which might use a companion lower priority interrupt to signal tasks with slower operations.)