Translating make file for freeRTOS, libopencm3 to platformio.ini

I am trying to get the examples at: stm32f103c8t6/rtos/blinky2 at master · ve3wwg/stm32f103c8t6 · GitHub to compile from within platformIO and let me use the debugger.

Board: stm32f103c8t6

Using the author’s makefile I can compile, and the uploaded binaries run, but when I compile and run it from within platformio, it just does nothing - the PC13 LED turns on and does not blink. The blackmagic gdb debugger shows the device refusing to enter the task function, but it does pause on main, and then pause on a line in the RTOS code. I am trying to use openlibcm3.

Can anyone provide any advice on moving forward? There is a linker .ld provided with the rtos example code above. It does not seem to make any difference, and when I compile other projects with it, they continue to work, so it seems like the linker config in platformio.ini is good.

The examples above seem to rely on a series of make files and a specific directory structure, but I have made both freeRTOS and openlibcm3 available, and the code compiles and skips around in the debugger, it just never enters the task.

The .elf files produced are slightly different sizes. Both are bigger than 128kb, but seem to program in ok. Produced with shell make command: 271kb(!), made with platformio build: 137kb

Here is my current platformio.ini, and below that is the output from compiling my current blinky project.

[env:genericSTM32F103CB]
platform = ststm32
board = genericSTM32F103CB
framework = libopencm3
;debug_tool = stlink

;build_flags = -ggdb, -DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG=1 
build_flags =-Wl,-T'"$PROJECT_DIR/src/stm32f103c8t6.ld"',-v

; set CKS mcu ID for knock off of STM chip
;https://community.platformio.org/t/cannot-upload-to-stm32-bluepill-board-over-stlink-v2/3492/19
;upload_flags = -c set CPUTAPID 0x2ba01477

monitor_speed = 115200
;monitor_port = \\.\COM36

debug_tool = blackmagic
debug_port = \\.\COM37

upload_port = \\.\COM37

; SWD interface
upload_protocol = blackmagic

; JTAG interface
;upload_protocol = blackmagic-jtag

The compiler output from the non-working platformio configuration.
> Executing task in folder freeRTOS1: C:\Users\Robert.platformio\penv\Scripts\platformio.exe run --verbose <

Processing genericSTM32F103CB (platform: ststm32; board: genericSTM32F103CB; framework: libopencm3; build_flags: -Wl,-T'"$PROJECT_DIR/src/stm32f103c8t6.ld"',-v; monitor_speed: 115200; debug_tool: blackmagic; debug_port: \\.\COM37; upload_port: \\.\COM37; upload_protocol: blackmagic)
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
CONFIGURATION: https://docs.platformio.org/page/boards/ststm32/genericSTM32F103CB.html
PLATFORM: ST STM32 5.7.0 > STM32F103CB (20k RAM. 128k Flash)
HARDWARE: STM32F103CBT6 72MHz, 20KB RAM, 128KB Flash
DEBUG: Current (blackmagic) External (blackmagic, jlink, stlink)
PACKAGES: toolchain-gccarmnoneeabi 1.70201.0 (7.2.1), framework-libopencm3 1.1.0
LDF: Library Dependency Finder -> http://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Framework incompatible library C:\Users\Robert\.platformio\lib\Adafruit GFX Library_ID13
Framework incompatible library C:\Users\Robert\.platformio\lib\Adafruit SSD1306_ID135
Framework incompatible library C:\Users\Robert\.platformio\lib\Adafruit ST7735 and ST7789 Library_ID12
Framework incompatible library C:\Users\Robert\.platformio\lib\ArduinoMenu library_ID1468
Framework incompatible library C:\Users\Robert\.platformio\lib\FreeRTOS_ID507
Framework incompatible library C:\Users\Robert\.platformio\lib\HID-Project_ID523
Framework incompatible library C:\Users\Robert\.platformio\lib\Joystick_ID6628
Framework incompatible library C:\Users\Robert\.platformio\lib\Keypad_ID165
Framework incompatible library C:\Users\Robert\.platformio\lib\LCDWIKI GUI Library
Framework incompatible library C:\Users\Robert\.platformio\lib\LibPrintf_ID6768
Framework incompatible library C:\Users\Robert\.platformio\lib\SSD1283A
Framework incompatible library C:\Users\Robert\.platformio\lib\Tasker_ID1423
Framework incompatible library C:\Users\Robert\.platformio\lib\USBComposite for STM32F1
Framework incompatible library C:\Users\Robert\.platformio\lib\Yet Another Arduino PcInt Library_ID795
Framework incompatible library C:\Users\Robert\.platformio\lib\arduino-menusystem_ID163
Framework incompatible library C:\Users\Robert\.platformio\lib\lv_arduino_ID6228
Found 4 compatible libraries
More details about "Library Compatibility Mode": https://docs.platformio.org/page/librarymanager/ldf.html#ldf-compat-mode
Scanning dependencies...
Dependency Graph
|-- <freeRTOS> (C:\Users\Robert\Documents\PlatformIO\Projects\freeRTOS1\lib\freeRTOS)
Building in release mode
MethodWrapper(["checkprogsize"], [".pio\build\genericSTM32F103CB\firmware.elf"])
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"
DATA:    [========= ]  86.2% (used 17648 bytes from 20480 bytes)
PROGRAM: [          ]   2.2% (used 2940 bytes from 131072 bytes)
.pio\build\genericSTM32F103CB\firmware.elf  :

section            size        addr

.text              2924   134217728

.preinit_array        0   134220652

.init_array           0   134220652

.fini_array           0   134220652

.data                16   536871148

.bss              17632   536871164

.comment            126           0

.ARM.attributes      51           0

Total             20749

The main.c:
/* Simple LED task demo, using timed delays:

 *

 * The LED on PC13 is toggled in task1.

 */

#include <FreeRTOS.h>

#include <task.h>

#include <libopencm3/stm32/rcc.h>

#include <libopencm3/stm32/gpio.h>

extern void vApplicationStackOverflowHook(

    xTaskHandle *pxTask,

    signed portCHAR *pcTaskName);

void

vApplicationStackOverflowHook(

  xTaskHandle *pxTask __attribute((unused)),

  signed portCHAR *pcTaskName __attribute((unused))

) {

    for(;;);    // Loop forever here..

}

static void

task1(void *args __attribute((unused))) {

    for (;;) {

        gpio_toggle(GPIOC,GPIO13);

        vTaskDelay(pdMS_TO_TICKS(500));

    }

}

int

main(void) {

    rcc_clock_setup_in_hse_8mhz_out_72mhz(); // For "blue pill"

    rcc_periph_clock_enable(RCC_GPIOC);

    gpio_set_mode(

        GPIOC,

        GPIO_MODE_OUTPUT_2_MHZ,

        GPIO_CNF_OUTPUT_PUSHPULL,

        GPIO13);

    xTaskCreate(task1,"LED",100,NULL,configMAX_PRIORITIES-1,NULL);

    vTaskStartScheduler();

    for (;;);

    return 0;

}

// End1

Can you upload your whole PlatformIO project to github for a 1:1 reproduction?

1 Like

I have tried a variety of memory configurations in the linker file… 120k for isntance I have seen people use instead of 128k, presumably to leave space for a DFU or other bootloader. This BluePill board has no USB\special bootloader on it though.

The same board and compiler\linker file all work with a simpler blink example that does not have freeRTOS involved.

Maybe it helps if I rephrase the issue as a question: has anyone gotten a project working in platformIO using their libopencm3 project base and freeRTOS? How did you include the libraries? I currently have no special treatment of libraries in my .ini file. Also it occurs to me the version of cm3 is different in the examples - it is 2-3 years older.

I am trying to follow along with a book about this combination of software specifically on STM32F103, and I can do so if I am willing to compile and upload outside platformIO, but the pleasant experience of hitting a button to upload and program and switch to terminal has spoiled me!

Struggling wth the same issue. I have a compiling project using the provided libopencm3 framework, and simply copying the freertos files to my project’s lib directory. It compiles, and uploads fine using my stlink. It’s actually the same blinky2 from the “Beginning STM32” book as you posted above. Although it compiles and flashes, it still doesn’t work correctly somehow, since the led stays on (or flashes very very fast, can’t tell…).

looking at your github project, you have actually done the same thing. 2 tiny differences:

  • I use board: bluepill_f103c8
  • I have deleted all the heap_x.c files, except heap_4.c

I tried with the bluepill board profile also with the same result…

I didnt see it noted, but maybe we need to have ‘the right heap’ file renamed or something? I suppose one of us should talk to the author on his github, he seems approachable.

I think it is staying on because when i follow it with the debugger, the task never runs a single time. The configuration seems to set the pin low, as the PC13 LED is low active. If other approaches dont work, I will hook a logic analyzer to the board and see what the pins are all doing.

Also a possible hint: the platformio compiled project is only 2k… Pretty sure RTOS alone is like 20K… something isnt compiling right…

@robear I’ve contacted Warren, and he was very quick to reply, and had some great pointers. One of the issues, at least in my repo, was that a piece of ‘glue-code’ between RTOS and libopencm3 was missing. This file is needed next to the rtos source files: stm32f103c8t6/opencm3.c at master · ve3wwg/stm32f103c8t6 · GitHub

Although it’s one piece of the puzzle, it still didn’t solve the issue in my case. This is what I have so far:

Other suggestions we might investigate he mentioned in the mail are:

  • Has vTaskStartScheduler() been called?
  • Or did something call vTaskSuspendAll()?
  • The reference manual says that for some ARM7 and ARM9 microcontrollers, that the processor must be in Supervisor mode before calling vTaskStartScheduler().
  • Compiler support (below)
  • and finally, the optimization level has been known to be an issue (-Os vs -O3 IIRC)

The compiler issue he is referring to is one regarding arm-none-eabi-gcc version 6.3.1, which had something to do with memcopy() not working correctly. This is the default version (still) for a lot of Ubuntu distros. However, my current version of arm-none-eabi-gcc within platformio is 7.2.1 (20170904). On my Mac, which has Warren’s working set-up, it uses 9.2.1.

I’m going to try and update the arm-none-eabi toolchain within my platformio setup, to see if this solves the issue… I’ll keep you posted.

Updated the toolchain with the version (9.2.1, from: Downloads | GNU Arm Embedded Toolchain Downloads – Arm Developer). Doesn’t make a difference.

Also a possible hint: the platformio compiled project is only 2k… Pretty sure RTOS alone is like 20K… something isnt compiling right…

Not entirely true. Indeed, the generated bin file is 3k. However, the elf file that gets created by PlatformIO is 206k, compared to 270k from Warren’s project/Makefile. The bin files are 3.4k for pio vs 3.5k using Makefile.

I’ve tried adding:

-Wl,-Map=main.map

to the build arguments, which lets ld create a map file for inspection. I’ve compared the map files from PlatformIO and Warren’s project, but for me this doesn’t provide more clues as to why the task doesn’t get scheduled… Maybe it does for someone else with more experience?

Update:
I finally was able to debug my code, and I think I am on to something… The ‘glue-code’ (opencm3.c) implements some handlers that are called from the libopencm3 code (vector.c). In the Makefile project checking out the map file, this handler is actually implemented:

.text.sv_call_handler
            0x0000000008000a78        0x4 rtos/opencm3.o
            0x0000000008000a78                sv_call_handler

However, in the pio set up, somehow the implementation of this handler is gone or not linked correctly:

.text.null_handler
            0x0000000008000ca6        0x2 .pio/build/bluepill_f103c8/libFrameworkLibOpenCM3.a(vector.o)
            0x0000000008000ca6                null_handler
            0x0000000008000ca6                sv_call_handler

This seems to be the issue, since it looks like the ‘glue-code’ isn’t hit/found at all, which causes our code to jump to the null-handler upon executing rtos’ prvPortStartFirstTask.

Well looking at this opencm3.c file:

These are supposed to be the ISR handlers. Looking at vector.c file

At the end of the file, WEAK symbols are defined. It may be the case that when the linking is done for libopencm3, the opencm3.c file is not yet known so it links it with the empty handlers.

A way around that may be to not link the frameworks seperately, but all at once. This can be achieved using lib_archive = no in the platformio.ini (docs).

This increases the size of the code in the flash from

RAM:   [========= ]  86.2% (used 17664 bytes from 20480 bytes)
Flash: [=         ]   5.2% (used 3424 bytes from 65536 bytes)

to

RAM:   [========= ]  86.2% (used 17664 bytes from 20480 bytes)
Flash: [=         ]   5.5% (used 3596 bytes from 65536 bytes)

Does that help?

Also, it shold be easily debuggable using a STLinkv2 to check if the handlers in opencm3.c are called at all, which would give further insight into the problem. PIO’s debugger is free to use in VSCode.

2 Likes

Thanks for the hints, Max - I will check into that today or this evening when I have a chance. I have been meaning to follow the execution with the debugger, but I have other aspects of my project which I have been able to work on productively in the meantime!

bjwschaap,

Thanks for contacting Warren! I will try and work off of the new info you have provided and see where I end up, and report back.

YES!!! It completely solved my issues :smile:
I have a blinking LED :partying_face:

@robear check my github repo (see link above). I’ve tested it against the ‘stock’ gcc toolchain provided by pio (7.2.1), and ‘stock’ libopencm3 framework.

To recap, the missing pieces were:

  • opencm3.c ‘glue-code’ file
  • lib_archive = no setting for the weak symbols

Thanks @maxgerhardt !

This is why I :heart: open-source

1 Like

Woohoo.

Great news, thanks Max and BJ.
I will give it a go in a little bit.

Yep.

It works for me too.

Just to recap - The version of RTOS wasnt the issue, neither were the slightly different freeRTOS files in the RTOS directory? It was the ‘glue’ file, and the lib_archive setting?

I see you have v 10.x of freeRTOS and the book is about V 9.x.

Thanks again guys, and happy holidays.

Robear

Roger that

I wish you all a happy new year’s eve, and a great 2020 :smile:

Just for documentation purposes, and anyone reading this thread, in Warren’s “Beginning STM32” book, the ‘glue-code’ is actually mentioned/described in chapter 20 “New Projects”, page 353.

2 Likes

For more documentation: I found debugging to not work with @bjwschaap’s otherwise excellent example project. I described my odyssey and a solution to the issue in Debugging FreeRTOS on STM32 Bluepill - #11 by deltaphi.