Using Raspberry Pi for Embedded Systems Development — Part 2

<rawat.s>
16 min readJun 30, 2021

.

This is the second part of the blog series: “Using Raspberry Pi for Embedded Systems Development”. The readers are recommended to read the first part of this series before proceeding.

List of Topics:

  • Programming STM32 with Arduino IDE: ST-Nucleo Boards
  • FreeRTOS-based STM32 Programming with Arduino IDE
  • RTOS Programming using CMSIS RTOS2 API for STM32
  • FreeRTOS-based SAMD21 Programming with Arduino IDE
  • STM32 Programming with VS Code and PlatformIO
  • FreeRTOS-STM32 Programming with VS Code and PlatformIO
  • Mbed-based STM32 Programming with VS Code and PlatformIO

It should be noted that this blog does not aim at providing you with detailed guidelines for microcontroller programming with Arm Cortex-M Series MCUs (such as STM32 or SAMD21) and FreeRTOS. However, it should help you get started with using embedded system development tools such as Arduino IDE that can run on Raspberry Pi.

[>] Programming STM32 with Arduino IDE: ST-Nucleo Boards

.

If you have STM32 microcontroller boards (such as ST-Nucleo or Discovery boards), you can install the Arduino Core for STM32 provided by the STM32duino project so that you can write an Arduino sketch for the STM32.

Two STM32 boards, namely ST- Nucleo L432KC and Nucleo F446RE, will be used as target boards for the next examples.

Nucleo L432KC Board Layout (source: https://os.mbed.com/platforms/ST-Nucleo-L432KC/)
STM32 Nucleo-32 with onboard ST-LINK/V2–1
Raspberry Pi 4 / Nucleo L432KC / Nucleo F446RE (from left to right)

STM32Duino Package Installation for Arduino IDE

1) Start the Arduino IDE and go to Files → Preferences → Setting Tab and install the Arduino Board Manager for STM32 by specifying the URL of a JSON file:

https://raw.githubusercontent.com/koendv/stm32duino-raspberrypi/master/BoardManagerFiles/package_stm_index.json

This JSON file is provided by the “stm32duino-raspberrypi” project on github.

2) Enter the URL as shown below and click the “OK” button:

3) Click on the menu Tools → Board Manager to open the Board Manager Window and install the board manager “STM32 MCU based boards”:

After installation, software tools provided by STM32duino are located under ~/.arduino15/packages/STM32.

$ tree -L 4 ~/.arduino15/packages
/home/pi/.arduino15/packages
├── arduino
│ ├── hardware
│ │ ├── mbed_nano
│ │ │ └── 2.2.0
│ │ ├── mbed_rp2040
│ │ │ └── 2.2.0
│ │ └── samd
│ │ └── 1.8.11
│ └── tools
│ ├── arduinoOTA
│ │ └── 1.2.1
│ ├── arm-none-eabi-gcc
│ │ └── 7-2017q4
│ ├── bossac
│ │ ├── 1.7.0-arduino3
│ │ └── 1.9.1-arduino2
│ ├── CMSIS
│ │ └── 4.5.0
│ ├── CMSIS-Atmel
│ │ └── 1.2.0
│ ├── dfu-util
│ │ └── 0.10.0-arduino1
│ ├── openocd
│ │ ├── 0.10.0-arduino7
│ │ └── 0.11.0-arduino2
│ └── rp2040tools
│ └── 1.0.2
└── STM32
├── hardware
│ └── stm32
│ └── 1.9.0
└── tools
├── CMSIS
│ └── 5.5.1
├── STM32Tools
│ └── 1.4.0
└── xpack-arm-none-eabi-gcc
└── 9.2.1-1.1

Next you can see a list of available STM32 boards by grouping:

4) Select “Nucleo-32” → “Nucleo L432KC” as an example for the STM32 target board:

Board Selection: Nucleo-32 STM32L432KC
Select Upload Method: Mass Storage
Board Selection: Nucleo-64 STM32F446RE

5) Write an Arduino Sketch to blink the onboard LED:

// the Arduino pin number for onboard LED
#define LED_PIN (D13) // or PB3 for L432KC
void setup() {
Serial.begin( 115200 );
Serial.println( "\nSTM32Duino demo..." );
Serial.printf( "CPU frequency: %lu Hz\n", SystemCoreClock );
pinMode( LED_PIN, OUTPUT );
}
void loop() {
bool next_state = !digitalRead( LED_PIN );
Serial.printf( "LED state: %d\n", next_state );
digitalWrite( LED_PIN, next_state );
delay(500);
}

6) Connect the STM32 Nucleo board to the USB port of the RPi and run the lsusb command to list the USB devices.

$ lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 004: ID 0483:374b STMicroelectronics ST-LINK/V2.1
Bus 001 Device 002: ID 2109:3431 VIA Labs, Inc. Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

From the sample output, you can see that the ST-LINK/V2.1 on the Nucleo board is active and ready to use.

In addition, a new USB mass storage drive is mounted automatically for the Nucleo board so that you can flash the firmware by copying the .bin file to the USB flash drive.

For flashing the binary executable file using the USB mass storage upload method, STM32Duino will run a shell script named “massStorageCopy.sh”. An extra step is required as follows.

# create a soft link for a shell script
$ cd ~/.arduino15/packages/STM32/tools/STM32Tools/1.4.0/tools/linux
$ ln -s ./massStorageCopy ./massStorageCopy.sh
# change the directory to home
cd ~/

7) Upload the Arduino sketch to the target board and open the Arduino Serial Monitor to receive incoming messages from the Nucleo board.

// Arduino Sketch Example 1
// File: stm32fl432kc_led_blink.ino
#define LED_PIN (PB3) // PB3/D13 (LED1)
void setup() {
Serial.begin( 115200 );
Serial.println( "\nSTM32Duino demo..." );
Serial.printf( "CPU frequency: %lu Hz\n", SystemCoreClock );
pinMode( LED_PIN, OUTPUT );
}
void loop() {
bool next_state = !digitalRead( LED_PIN );
Serial.printf( "LED state: %d\n", next_state );
digitalWrite( LED_PIN, next_state );
delay(500);
}
A successful sketch upload

After uploading the sketch, the output should look like this:

Sample output from /dev/ttyACM0

You should also see that the onboard LED is blinking slowly.

Let’s try another Arduino sketch which is used to generate a 1kHz PWM signal (with 50% duty cycle, 10-bit resolution). It also counts the number of pulses in the time interval of 1000 msec and measures the high pulse width of the PWM signal.

The output pin for the PWM signal is the PA11 or D10, which is a hardware PWM pin of the STM32L432KC. The input pin for the pulse signal is PB4 or D12, which is connected to the PWM output pin via a jumper wire. Each time an falling edge occurs on the input PWM signal, the associated interrupt routine is executed to increment the pulse counter.

// Arduino Sketch Example 2
// File: stm32fl432kc_pwm_demo.ino
#define PULSE_OUT_PIN (D10) // PA11 (Hardware PWM pin)
#define PULSE_IN_PIN (D12) // PB4
#define IRQ_PIN digitalPinToInterrupt(PULSE_IN_PIN)
#define PWM_RESOLUTION_BITS (10)
#define PWM_FREQ_HZ (1000)
volatile uint32_t count = 0; // pulse countervoid pulse_isr() {
count++; // increment the pulse counter
}
void setup() {
Serial.begin( 115200 );
Serial.println( "STM32 PWM Output and Pulse Counting Demo...\n" );
pinMode( PULSE_OUT_PIN, OUTPUT );
pinMode( PULSE_IN_PIN, INPUT_PULLUP );
analogWriteResolution( PWM_RESOLUTION_BITS );
analogWriteFrequency( PWM_FREQ_HZ );
analogWrite(PULSE_OUT_PIN, 0 );
}
void loop() {
count = 0;
// enable the external interrupt on the pulse input pin
attachInterrupt( IRQ_PIN, pulse_isr, FALLING );
// generate a PWM signal on the output pin (with 50% duty cycle)
analogWrite( PULSE_OUT_PIN, (1 << PWM_RESOLUTION_BITS)/2 - 1 );
// wait for 1000 msec
delay( 1000 );
// disable the external interrupt on the pulse input pin
detachInterrupt( IRQ_PIN );
// wait until the PWM signal goes low.
while (digitalRead(PULSE_IN_PIN) == HIGH) {}
// measure the high pulse width
uint32_t pulse_width_us = pulseIn( PULSE_IN_PIN, 1, 10000 );
// turn off the PWM signal (0% duty cycle)
analogWrite( PULSE_OUT_PIN, 0 );
Serial.printf( "PWM frequency : %u Hz\n", PWM_FREQ_HZ );
Serial.printf( "High pulse width : %u us\n", pulse_width_us );
Serial.printf( "Pulses per second : %u\n\n", count );
Serial.flush();
}

The output message should look like this:

PWM frequency     : 1000 Hz
High pulse width : 500 us
Pulses per second : 1000

The next Arduino sketch shows how to generate an analog output signal with a sinusoidal waveform by using the DAC module of the STM32L432KC. In addition, the internal ADC module is also used to measure the voltage level of the generated analog signal. The DAC output pin is PA4, whereas the ADC input pin is PA0. Both pins must be connected together via a jumper wire.

// Arduino Sketch Example 3
// File: stm32l432kc_dac_adc.ino
#include <math.h>
#define AOUT_PIN (PA4) // analog output pin (DAC output pin)
#define AIN_PIN (PA0) // analog input pin (ADC input pin)
#define ADC_RESOLUTION (12)
#define DAC_RESOLUTION (10)
void setup() {
Serial.begin( 115200 );
analogReadResolution( ADC_RESOLUTION );
analogWriteResolution( DAC_RESOLUTION );
analogWrite( AOUT_PIN, 0 );
}
const uint16_t N = 512;
const uint16_t OFFSET = (1<<DAC_RESOLUTION)/2;
const uint16_t A = (1<<DAC_RESOLUTION)/2-8;
const uint16_t VREF = 3300; // 3300 mV
void loop() {
static uint16_t write_value = 0;
static uint32_t milli_volt;
for ( int i=0; i < N; i++ ) {
write_value = A*sin( 2*M_PI*i/N ) + OFFSET;
analogWrite( AOUT_PIN, write_value );
delayMicroseconds(10);
milli_volt = analogRead( AIN_PIN );
milli_volt = milli_volt * VREF/ (1<<ADC_RESOLUTION);
Serial.printf("%u\n", milli_volt );
delay(10);
}
}

The output values sent from the MCU board can be visualized by using the Arduino Serial Plotter. The expected waveform should look like a sine wave.

Waveform visualization using Arduino Serial Plotter

In the previously given Arduino sketches, some Arduino functions were used for demonstration purposes:

pinMode(), Serial.begin(), digitalRead(), digitalWrite(), delay(), delayMicroseconds(), Serial.println(), Serial.printf(), Serial.flush(), attachInterrupt(), detachInterrupt(), digitalPinToInterrupt(), analogWriteResolution(), analogWriteFrequency(), analogWrite(), analogReadResolution(), analogRead(), pulseIn()

[>] FreeRTOS-based STM32 Programming with Arduino IDE

.

FreeRTOS is a widely used, open source real-time operating system (RTOS). For those who want to learn RTOS-based microcontroller programming, FreeRTOS is a good choice.

If you want to use FreeRTOS for STM32 MCUs together with the Arduino IDE, you can import the STM32FreeRTOS library which is maintained by the STM32duino project on github.

Source: https://www.arduino.cc/reference/en/libraries/stm32duino-freertos/

To install this library, open the Library Manager (Tools → Manage Libraries…) in the Arduino IDE and install it from there. As of this writing, the latest version of the “STM32duino FreeRTOS” is v10.2.1.

Select the “STM32duino FreeRTOS” and click the “Install” button.

Now, let’s start with an Arduino sketch that creates a simple FreeRTOS task for led blinking. This task is assigned a priority of 1 (an integer value between 0 to configMAX_PRIORITIES-1) and a stack size of 512. The ST-Nucleo L432KC is chosen as the target MCU.

// File: stm32_freertos_demo-1.ino
#include <STM32FreeRTOS.h>
#include <FreeRTOSConfig.h>
#define LED_PIN LED_BUILTINvoid led_blink_task( void *pvParameters ) {
(void) pvParameters; // this function doesn't use any parameter.
pinMode( LED_PIN, OUTPUT );
for (;;) {
int state = !digitalRead(LED_PIN);
digitalWrite( LED_PIN, state );
Serial.printf( "LED: %d\n", state );
vTaskDelay( 500/portTICK_PERIOD_MS ); // wait for 500ms
}
}
void create_user_task() {
xTaskCreate(
led_blink_task, // task entry function
"led_blink", // task name
512, // stack size
NULL , // no task argument
1, // task priority = 1 (0 being the lowest)
NULL );
}
void setup() {
Serial.begin( 115200 );
Serial.printf( "\n\nSystemCoreClock: %d Hz\n", SystemCoreClock );

// show some information about FreeRTOS configuration settings
// which are defined in the FreeRTOSConfig.h file.
Serial.printf( "FreeRTOS\n" );
Serial.printf( " CPU clock frequency: %d Hz\n",
configCPU_CLOCK_HZ );
Serial.printf( " System Tick Rate: %d Hz\n",
configTICK_RATE_HZ );
Serial.printf( " Priority levels: %d\n",
configMAX_PRIORITIES );
Serial.printf( " Min. stack size: %d\n",
configMINIMAL_STACK_SIZE );

// create a task
create_user_task();

// start the FreeRTOS scheduler
vTaskStartScheduler();
while(1) {}
}
void loop() {
// empty
}

The output of the program shown in the Arduino Serial Monitor should look like this:

[>] RTOS Programming using CMSIS RTOS2 API for STM32

.

The CMSIS-RTOS v2 (CMSIS-RTOS2) provides generic RTOS interfaces for Arm Cortex processor-based devices. It provides a standardized programming interface that is portable to many RTOS and enables software components that can work across multiple RTOS systems. The CMSIS-RTOS2 API enables programmers to create portable application code to be used with different RTOS kernels (e.g., Keil RTX5 and CMSIS-FreeRTOS).

Since the “STM32duino FreeRTOS” does support the CMSIS-RTOS2 API, the next Arduino sketch shows how to write code for STM32.

// File: stm32_freertos_demo-2.ino
#define LED_PIN LED_BUILTIN
osThreadId_t task_id;const osThreadAttr_t thread_attr = { // thread attributes
.stack_size = 1024, // stack size 1024 bytes
.priority = osPriorityNormal
};
void led_blink_func( void *arg ) { // thread-entry function
(void) arg; // no argument used
pinMode( LED_PIN, OUTPUT );
for (;;) {
int state = !digitalRead(LED_PIN);
digitalWrite( LED_PIN, state );
Serial.printf( "LED: %d\n", state );
osDelay( 500 ); // wait for 500 ticks
}
}
void setup() {
Serial.begin( 115200 );
Serial.println( "\n\nFreeRTOS - CMSIS RTOSv2 demo...\n" );
// initialize the OS kernel
osKernelInitialize();
// create a new thread (for led blinking)
task_id = osThreadNew( led_blink_func, NULL, &thread_attr );
if (osKernelGetState() == osKernelReady) {
osKernelStart(); // start thread execution
}
while(1) {}
}
void loop() {
// empty
}

Note that configUSE_CMSIS_RTOS_V2 has to be defined and set to 1 to use CMSIS-​RTOSv2. In addition to a sketch file (.ino), a header file named “STM32FreeRTOSConfig_extra.h” must be added to the Arduino sketch directory. Inside this header file, the following text line must be inserted.

#define configUSE_CMSIS_RTOS_V2  (1)

After uploading the sketch, the output of the demo program should look like this:

[>] FreeRTOS-based SAMD21 Programming with Arduino IDE

.

The Atmel SAMD21 is a microcontroller based on the Arm Cortex-M0+ architecture. The Arduino Zero and MKR Series boards are based on the Atmel SAMD21 (ATSAMD21G18).

There is a FreeRTOS library which has been ported to the SAMD21 MCU so that it can be programmed with the Arduino IDE.

To install this library, open the Library Manager (Tools → Manage Libraries…) in the Arduino IDE and search for “FreeRTOS_SAMD21”. As of this writing, the latest version of the FreeRTOS ported to Arduino-SAMD21 is v10.2.1.

Make sure that you can installed the Board Manager for “Arduino SAMD Board (32-bit ARM Cortex-M0+)

Here is an Arduino sketch that creates two FreeRTOS tasks, each of which will make the corresponding LED blink at a constant rate.

#include <FreeRTOS_SAMD21.h>#define LED1_PIN    25 // PB03
#define LED2_PIN 26 // PA7

TaskHandle_t task1_handle;
TaskHandle_t task2_handle;
void led1_blink(void* pvParameters) {
(void) pvParameters; // no argument used
int pin = LED1_PIN;
pinMode( pin, OUTPUT );
digitalWrite( pin, HIGH );
while (1) {
digitalWrite( pin, !digitalRead( pin ) );
vTaskDelay( 250/portTICK_PERIOD_MS ); // wait for 250ms
}
}
void led2_blink(void* pvParameters) {
(void)pvParameters; // no argument used
int pin = LED2_PIN;
pinMode( pin, OUTPUT );
digitalWrite( pin, LOW );
while (1) {
digitalWrite( pin, !digitalRead( pin ) );
vTaskDelay( 250/portTICK_PERIOD_MS ); // wait for 250ms
}
}

void setup() {
SerialUSB.begin(115200);
xTaskCreate( led1_blink,
"Task 1",
256,
NULL,
tskIDLE_PRIORITY + 1,
&task1_handle );
xTaskCreate(
led2_blink,
"Task 2",
256,
NULL,
tskIDLE_PRIORITY + 1,
&task2_handle );

vTaskStartScheduler();
while(1){}
}

void loop() {
// empty
}

Connect the Arduino Zero compatible board to the Raspberry Pi’s USB port. Run the ‘lsusb’ command to detect the Arduino board.

$ lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 028: ID 2341:804d Arduino SA
Bus 001 Device 002: ID 2109:3431 VIA Labs, Inc. Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Verify and upload the Arduino sketch.

[>] STM32 Programming with VS Code and PlatformIO

.

Before proceeding with this section, please make sure that you have already installed the VS Code IDE and the Platform IO extension in your system.

See also: https://docs.platformio.org/en/latest/integration/ide/vscode.html

1) Open the VS Code and then open a new Terminal and try to run the pio command:

$ ~/.platformio/penv/bin/pio --version
PlatformIO Core, version 5.1.1

2) Run the following command line to install the ststm32 platform.

$ ~/.platformio/penv/bin/pio platform install ststm32

Problem: Unfortunately, I found an error during installation, which is caused by the wrong version of the available toolchain-gccarmnoneeabi package.

Platform Manager: ststm32 @ 14.0.1 has been installed!
Tool Manager: Installing platformio/toolchain-gccarmnoneeabi @ >=1.60301.0,<1.80000.0
Error: Could not find the package with 'platformio/toolchain-gccarmnoneeabi @ >=1.60301.0,<1.80000.0' requirements for your system 'linux_aarch64'

Solution:

Step 1) Edit the file ~/.platformio/platforms/ststm32/platform.json.

In the “packages” section, search for “toolchain-gccarmnoneeabi” and modify the version number:

See: the online original version of platform.json

It should be modified like this:

"packages": {
"toolchain-gccarmnoneeabi": {
"type": "toolchain",
"owner": "platformio",
"version": ">=1.60301.0,<2.0",
"optionalVersions": [
"~1.60301.0",
"~1.80201.0",
"~1.90301.0"
]
},

Problem: Another problem found during the installation process was due to missing installation files of the DFU utility program for the linux_aarch64 architecture.

Error: Could not find the package with 'platformio/tool-dfuutil @ ~1.9.190708' requirements for your system 'linux_aarch64'

Solution: In the “packages” section, search for “tool-dfuutil” and just remove this configuration block (from line 433 to 438) to avoid installation errors.

Step 2) Re-run the command line again.

The ststm32 package is located at ~/.platformio/platforms/ststm32/.

$ tree -L 1 ~/.platformio/platforms/ststm32//home/pi/.platformio/platforms/ststm32/
├── boards
├── builder
├── examples
├── ldscripts
├── LICENSE
├── misc
├── platform.json
├── platform.py
├── __pycache__
├── README.md
└── tests

Step 3) Edit the ~/.platformio/platforms/ststm32/platform.py file to make modifications to match the correct version of the required toolchain (search for “toolchain-gccarmnoneeabi”).

3) Go to “PIO Home” and create a new project.

In the Project Wizard window, specify the project name (e.g. stm32_led_blink), select the STM32 board (e.g. ST Nucleo L432KC) and select the Arduino framework.

4) Open the main.cpp file, edit the source code and save the change.

#include <Arduino.h>#define LED_PIN (D13) // PB3/D13 (LED1)void setup() {
Serial.begin( 115200 );
Serial.println( "\nSTM32Duino demo..." );
Serial.printf( "CPU frequency: %lu Hz\n", SystemCoreClock );
pinMode( LED_PIN, OUTPUT );
}
void loop() {
bool next_state = !digitalRead( LED_PIN );
Serial.printf( "LED state: %d\n", next_state );
digitalWrite( LED_PIN, next_state );
delay(100);
}

5) Edit the platformio.ini configuration file of the project.

[env:nucleo_l432kc]platform = ststm32
board = nucleo_l432kc
framework = arduino
; upload_protocol = stlink
; upload_protocol = cmsis-dap
; upload_protocol = jlink
upload_protocol = mbed
upload_port = /media/pi/NODE_L432KC/
monitor_speed = 115200
monitor_port = /dev/ttyACM0

6) Build the project and upload the output binary file (firmware.bin) to the target board (using either “mbed” or “stlink” as the upload protocol).

Build the project
Upload the .bin file using the USB mass storage drive (the mbed upload protocol)

[>] FreeRTOS-STM32 Programming with VS Code and PlatformIO

.

The PlatformIO can support the FreeRTOS library for STM32. You can add the library dependency (lib_deps) to the platformio.ini file of the project.

1) Create a new project and using the FreeRTOS-STM32 demo code as given in the previous section.

2) Edit the platformio.ini configuration file.

[env:nucleo_l432kc]platform = ststm32
board = nucleo_l432kc
framework = arduino
upload_protocol = stlink
; upload_protocol = cmsis-dap
; upload_protocol = jlink
; upload_protocol = mbed
; upload_port = /media/pi/NODE_L432KC/
monitor_speed = 115200
monitor_port = /dev/ttyACM0
lib_deps =
stm32duino/STM32duino FreeRTOS @ ^10.2.1

3) Edit the main.cpp file (use the demo code provided below).

#include <Arduino.h>
#include <STM32FreeRTOS.h>
#include <FreeRTOSConfig.h>
#define LED_PIN LED_BUILTINvoid led_blink_task( void *pvParameters ) {
(void) pvParameters; // this function doesn't use any parameter.
pinMode( LED_PIN, OUTPUT );
for (;;) {
int state = !digitalRead(LED_PIN);
digitalWrite( LED_PIN, state );
Serial.printf( "LED: %d\n", state );
vTaskDelay( 500/portTICK_PERIOD_MS ); // wait for 500ms
}
}
void create_user_task() {
xTaskCreate(
led_blink_task, // task entry function
"led_blink", // task name
512, // stack size
NULL , // no task argument
1, // task priority = 1 (0 being the lowest)
NULL );
}
void setup() {
Serial.begin( 115200 );
Serial.printf( "\n\nSystemCoreClock: %d Hz\n", SystemCoreClock );

// show some information about FreeRTOS configuration settings
// which are defined in the FreeRTOSConfig.h file.
Serial.printf( "FreeRTOS\n" );
Serial.printf( " CPU clock frequency: %d Hz\n",
configCPU_CLOCK_HZ );
Serial.printf( " System Tick Rate: %d Hz\n",
configTICK_RATE_HZ );
Serial.printf( " Priority levels: %d\n",
configMAX_PRIORITIES );
Serial.printf( " Min. stack size: %d\n",
configMINIMAL_STACK_SIZE );

// create a task
create_user_task();

// start the FreeRTOS scheduler
vTaskStartScheduler();
while(1) {}
}
void loop() {
// empty
}

4) Build the project and upload the binary file to the target board (ST-Nucleo L432KC).

Build the project
Upload the .bin file using the stlink method.
Open the serial monitor on the /dev/ttyACM0 port (baud: 115200)

[>] Mbed-based STM32 Programming with VS Code and PlatformIO

.

The PlatformIO also supports Mbed OS 6.x, so you can learn or use Mbed OS which is an open-source RTOS developed by ARM Ltd.

1) Create a new project and select “mbed” as the framework.

2) Edit the platformio.ini configuration file.

[env:nucleo_l432kc]
platform = ststm32
board = nucleo_l432kc
framework = mbed
build_flags = -DPIO_FRAMEWORK_MBED_RTOS_PRESENT
upload_protocol = mbed
upload_port = /media/pi/NODE_L432KC/
;upload_protocol = stlink
;upload_protocol = cmsis-dap
;upload_protocol = jlink
;upload_protocol = dfu

3) Create and add the mbed_app.json file to the project (see the following sample JSON text).

{
"target_overrides": {
"*": {
"target.printf_lib": "minimal-printf",
"platform.stdio-baud-rate": 115200,
"platform.stdio-convert-newlines": true,
"platform.stdio-buffered-serial": true,
"platform.minimal-printf-enable-floating-point": true,
"platform.minimal-printf-set-floating-point-max-decimals": 6,
"platform.minimal-printf-enable-64-bit": false
},
"NUCLEO_L432KC": {
"rtos.main-thread-stack-size": 8192
}
}
}

3) Edit the main.cpp code as follows:

#include <mbed.h>DigitalOut led1(LED1); // use onboard LEDint main() {
printf( "Hello Mbed OS..\n" );
while(1) {
led1 = !led1; // toggle LED output
ThisThread::sleep_for(500ms);
}
}

4) Build the project and upload the binary file to the target board (ST-Nucleo L432KC).

In the terminal you can see information about the version of the tools used by PlatformIO such as:

 - framework-mbed 6.60900.210318 (6.9.0) 
- toolchain-gccarmnoneeabi 1.90301.200702 (9.3.1)

Note: You can use openocd to flash the firmware file manually:

$ PROJ_PATH=~/Documents/PlatformIO/Projects/nucleo_l432kc_mbed_demo-1
$ FIRMWARE=${PROJ_PATH}/.pio/build/nucleo_l432kc/firmware.bin
$ openocd -d2 \
-f interface/stlink.cfg \
-f target/stm32l4x.cfg \
-c "adapter speed 1000" \
-c "transport select hla_swd" \
-c "reset_config srst_only srst_nogate" \
-c "init" \
-c "program ${FIRMWARE} 0x8000000 verify" \
-c "sleep 100" \
-c "reset run; exit"

Update: 2021–09–11

--

--