🛠 FreeRTOS sur le Nucleo STM32H743ZI : le projet officiel CubeH7, tâches et file d'attente
What you will build
STM32CubeH7 ships a ready-made FreeRTOS application for this exact board at Projects/NUCLEO-H743ZI/Applications/FreeRTOS — the fastest route to a working RTOS baseline on the H743ZI. We will open it, then add a producer/consumer pair: a sensor task sampling one of the 3× 16-bit ADCs and a logging task draining a queue to the ST-LINK virtual COM port.
Why FreeRTOS on this board
- Official ST project, not a port: it lives in the same package (v1.13.0) as the HAL you compile against.
- The CubeH7 middleware family covers FreeRTOS, LwIP, FatFS and USB — your RTOS skeleton grows into the LwIP web-server demo later.
- The timer roster is huge for control loops: 2× 32-bit + 12× 16-bit general-purpose timers, 2× PWM motor-control timers including HRTIM, 5 low-power timers and a 2.1 ns high-resolution timer.
Step 1 — Open the official project
git clone --recursive https://github.com/STMicroelectronics/STM32CubeH7.git- Open
Projects/NUCLEO-H743ZI/Applications/FreeRTOSin STM32CubeIDE (or regenerate your own variant from CubeMX with FreeRTOS enabled in the middleware tree). - Build and flash through the on-board ST-LINK/V2-1.
Step 2 — Producer/consumer tasks
/* Add to the generated project (CubeMX FreeRTOS skeleton). */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
static QueueHandle_t q_samples;
void SensorTask(void *arg)
{
uint32_t raw;
for (;;) {
HAL_ADC_Start(&hadc1); /* 16-bit ADC, up to 3.6 MSPS */
HAL_ADC_PollForConversion(&hadc1, 10);
raw = HAL_ADC_GetValue(&hadc1);
xQueueSend(q_samples, &raw, pdMS_TO_TICKS(10));
vTaskDelay(pdMS_TO_TICKS(100));
}
}
void LogTask(void *arg)
{
uint32_t raw;
for (;;) {
if (xQueueReceive(q_samples, &raw, portMAX_DELAY) == pdTRUE) {
printf("ADC1=%lu\r\n", raw); /* retarget printf to UART3 / ST-LINK VCP */
}
}
}
void start_tasks(void) /* called after HAL init and clock config */
{
q_samples = xQueueCreate(16, sizeof(uint32_t));
xTaskCreate(SensorTask, "sensor", 128, NULL, 3, NULL);
xTaskCreate(LogTask, "log", 128, NULL, 2, NULL);
vTaskStartScheduler;
for (;;) {}
}
Step 3 — Priorities that make sense
Give the sensor task the higher priority and let the log task run at low priority: the ADC producer never waits on the slow console, and the queue (16 deep) absorbs console stalls. On a 480 MHz M7 with 192 KB of TCM RAM, context switches are tiny — but keep stacks in the default RAM sections before micro-optimizing placement (see the advanced memory tutorial).
Expected result
The official demo's LED choreography runs; after your edit, the terminal on the ST-LINK VCP (115200) prints one ADC1=... line every 100 ms while the LED tasks keep their timing — that is preemptive scheduling proving itself.
Common pitfalls
- Blocking calls inside a critical section:
printfon the VCP can block for milliseconds — always run it at the lowest task priority. - Using
HAL_Delayinside tasks: it busy-waits on the tick; usevTaskDelayinstead. - Expecting the project to build after a non-recursive clone: submodules are mandatory.
Other tutorials for this board
- Premiers pas sur le Nucleo-144 STM32H743ZI : core STM32duino, ST-LINK et premier Blink
- GPIO, ADC 16 bits et DAC sur le Nucleo STM32H743ZI : bouton, LED et potentiomètre
- MicroPython sur le Nucleo STM32H743ZI : le REPL 480 MHz via le port série ST-LINK
- Zephyr RTOS sur le Nucleo STM32H743ZI : west build, flash et le piège des 96 MHz
- STM32Cube HAL à 480 MHz sur le STM32H743ZI : VOS0, latence flash et HSE bypass
- Serveur web sur l'Ethernet du STM32H743ZI : démo LwIP officielle, RMII et errata