Solution using STM32 + CMSIS + ARM RTX

I’ve been struggling for a while now to create a PlatformIO project that works with the following configurations:

  • STM32F103C8T6 as the Microcontroller
  • CMSIS as the Framework
  • RTX as the RTOS

I know that there is no “official support” for CMSIS-RTOS2 or RTX in PlatformIO, so I placed the files from the official RTX repository inside the /lib folder, added the default RTX configuration files (RTX_Config.h), as well as “RTE_Components.h”. Naturally, I configured the “platform.ini” by adding the paths to build as build flags, so that the files related to RTOS2 and RTX would be compiled. I made this setup based on this project.

Everything compiles fine. However, I discovered that when I load the firmware into the microcontroller, the “osKernelInitialize()” function never returns. Does anyone have any clues as to what it could be? Has anyone had a similar problem? Where can I start investigating this?

EDIT: The basic setup code is in this repository if you want to check out the code.

If you load the firmware using a debugger like the ST-Link, you can just use the debug sidebar to step into the code and see why the function doesn’t return.

Without seeing the full code, it’s extremely hard to see why.

Thanks for replaying, Maximilian.

I tried to debug using a STLink. Check it out:
From main.cpp, Stepping into, we hit rtx_kernel.c and finally we got stuck on startup_stm32f103xb.S:

By the way, removing GPIO stuff from the code, the basic scaffolding is available on this repository: GitHub - marcusvinoli/pio-stm32-cmsis-rtx: Skeleton Firmware for using PlatformIO + CMSIS + RTX (also included this at the Original Post).

That means it tried to do a SVC (supervisor call) instruction, which is supposed to catapult it into the SVC_Handler() interrupt function provided the by the RTOS, but there was no such interrupt function defined, causing it to go into the the default handler (infinite loop) instead.

Looking at the original project, there is a lib/RTOS2/RTX/Source/GCC/irq_cm4f.S file that defines all the interrupt functions that the RTOS needs (SysTick_Handler, PendSV_Handler, SVC_Handler). With a STM32F103C8, you obviously have a Cortex-M3 instead of a Cortex-M4F.

The original RTOS2 source in CMSIS5 has a “GCC” folder here:

https://github.com/ARM-software/CMSIS_5/tree/5.9.0/CMSIS/RTOS2/RTX/Source

which is completely not present in your project. And, while they seemed to have renamed the files in this new version, your Cortex-M3 still falls under the ARMv7-M architecture.

Thus, I would suggest:

  • copy RTOS2/RTX/Source/GCC/irq_armv7m.S into your project’s lib\rtos\rtx\Source\GCC folder
  • set lib_archive = no (docs) in your platformio.ini. This is extremely important, too. When a libary (something in lib/) defines an interrupt handler, the intermediate packing of the object files to an archive file and then linking it can cause the interrupt handler to not be found, you have to disable the archiving step for it to work.
    • note: In this project, it seems to work without it, too, but for safety reasons I would still add it.

Can confirm, interrupt handlers on any platform tend to be subject to some linking issues like this due to the fact that (unlike functions in general) they need to be located at a specific absolute address. (With the SDCC compiler, for example, at least the prototype has to be declared in the first file supplied to the linker, though I realize you’re not using sdcc…)