Configuring FreeRTOS on Teensy 4.0

I have been working to get FreeRTOS working as a library in the /lib folder. I am hoping to learn how to configure this so that I can apply it to more microcontrollers than the Teensy 4.0 I am currently using, and so that the code can be easily sent to my teammates.

So far, I have gotten the workspace to successfully build, and the compiler is even satisfied with my includes in the main.c script. However, when I call vTaskStartScheduler(), everything comes grinding to a halt and nothing happens on the microcontroller anymore.

Here is my folder setup:

Any help or suggestions would be super great!

The library.json:

and the main.cpp script:

And also platform.ini

FYI, the Teensy4 can host a GDB server via serial, which PlatformIO can connect to. This would enable you to do line-by-line debugging.

https://github.com/ftrias/TeensyDebug#installing-for-platformio

Step into the vTaskStartScheduler() and see if the apprpriate interrupt functions are entered for the systick handler, the SVC_Handler, PendSV handler et cetera.

Especially take note that you have to tell FreeRTOS the name of these interrupt functions so that they’re called in the way the Teensy startup assembly file is expecting them to be. For example, for STM32 and the standard CMSIS names

but the Teensy 4 startup and vectors is special in the sense that the interrupt function is called differently and already implemented by the EventResponder system. See

Exception numbers “14” = PendSV, “15 = SysTick”, “11 = SVCall”, see https://developer.arm.com/documentation/dui0646/c/The-Cortex-M7-Processor/Exception-model/Exception-types.

Since FreeRTOS does need to be called by a timer (e.g. SysTick, but could also be any other hardware timer) and the PendSV and SVC_Handler (“calls into FreeRTOS kernel code”), you’re kind of fighting against the existing implementation in the Arduino core here.

In short: This is pretty fricking complicated. If you were in a baremetal environment with no other framework code interfering, you could tell FreeRTOS to take complete control over those interrupt functions and be done.

Luckily, someone has already done all the hard work hacking the interrupt handlers to call the FreeRTOS code and not break the existing Arduino code, with stuff like

So, I see no point in what you’re trying to do manually, you should use that existing library.

Ok. I see your point. No wonder I was struggling for so long with something kind of pointless! I think I’ll go for the premade library instead. On that note though, does this mean that doing this method is basically pointless for anything using the Arduino framework? Would I have to find a new FreeRTOS library adaptation for every single time I want a different kind of microcontroller to use FreeRTOS?

It is very common for Arduino core implementations to at least “steal” (or “use normally”) at least the SysTick interrupt handler, since that is the basis for the millis() function to work.

It is uncommon for an Arduino core to hook PendSV or the SVC handler though. The Teensy framework is unique in this regard. It is also unique in the regards that it uses the ISR table reloacted to RAM instead of having the function just be in flash with a default name that can be easily overwritten.

Other Arduino cores are way more friendlier to hook into their SysTick handler or other handler functions: They are made with an operating system sitting on top in-mind, like e.g. the Arduino STM32 core: It allows the definition of a osSystickHandler() in regular usercode, which the FreeRTOS kernel can then be configured to provide, and the existing SysTick_Handler will then handle both the millis() tick increment and calling the OS systick handler.

And this core also does not hook PendSV or SVC_Handler, so FreeRTOS can grab those directly. This makes configuring FreeRTOS to work on top of the STM32Duino Arduino core much more seamless.

Teensy-Arduino is an exception there for being more complicated.

To answer this concisely: Porting FreeRTOS to a new microcontroller should, in the most ideal setting, only be an adaption of the FreeRTOSConfig.h together with selecting which port from the portable/ folder you need (e.g., Cortex M7, et cetera) and maybe the addition of a few compiler flags (like activating the FPU). So, “ports” or configurations can be very minimal and concise.

Additional work only needs to be done when you’re fighting against existing framework code (like the one in Arduino Teensy): The more stones that framework throws in your path, the more work you have to put in to clear them, while also not breaking the existing framework’s code.

That’s why you’ll find FreeRTOS ports specifically targeted at for example, AVR Arduino, STM32 Arduino, or Teensy Arduino.