A complete STM32 FreeRTOS project example for a basic multitasking application


Here’s a complete STM32 FreeRTOS project example for a basic multitasking application:
LED blinking + UART message + ADC voltage readout, running on STM32F4 (e.g., STM32F407VG) using FreeRTOS and STM32CubeIDE.
Project Overview
Feature | Description |
MCU | STM32F407VG (any STM32F4 will work similarly) |
RTOS | FreeRTOS (CMSIS-RTOS v2) |
Tasks | - Task 1: Blink LED every 500 ms |
arduino
- Task 2: Send UART message every 1 s
- Task 3: Read ADC and print result every 2 s |
| Tool | STM32CubeIDE (no external libraries needed)
Step-by-Step: Creating the Project
1. Create a New Project
Open STM32CubeIDE
Create New STM32 Project
Select target (e.g., STM32F407VG)
Name it:
RTOS_Blink_UART_ADC
2. Enable Peripherals
In .ioc (Pinout & Configuration) view:
PA5 – Output GPIO (for LED)
USART2 – Asynchronous (e.g., TX = PA2, RX = PA3)
ADC1 – IN0 (e.g., PA0)
SYS → Timebase Source =
TIM6
Middleware > FreeRTOS → Enable CMSIS v2 interface
3. Configure FreeRTOS
Go to Middleware > FreeRTOS > Configuration
Create 3 Tasks:
Task Name | Function | Stack Size | Priority |
BlinkTask | blinkLED | 128 | osPriorityNormal |
UARTTask | uartTask | 128 | osPriorityLow |
ADCTask | adcTask | 128 | osPriorityLow |
4. Generate Code
Click Project > Generate Code
Open
blinkLED.c
,uartTask.c
,adcTask.c
or define them inapp_freertos.c
Example Task Implementations
blinkLED
Task
c
void blinkLED(void *argument) {
for(;;) {
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
osDelay(500);
}
}
uartTask
Task
c
extern UART_HandleTypeDef huart2;
void uartTask(void *argument) {
char msg[] = "Hello from UART!\r\n";
for(;;) {
HAL_UART_Transmit(&huart2, (uint8_t*)msg, strlen(msg), HAL_MAX_DELAY);
osDelay(1000);
}
}
adcTask
Task
c
extern ADC_HandleTypeDef hadc1;
void adcTask(void *argument) {
char buffer[64];
uint32_t adcValue;
for(;;) {
HAL_ADC_Start(&hadc1);
if (HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY) == HAL_OK) {
adcValue = HAL_ADC_GetValue(&hadc1);
float voltage = (adcValue / 4095.0) * 3.3;
snprintf(buffer, sizeof(buffer), "ADC: %lu (%.2f V)\r\n", adcValue, voltage);
HAL_UART_Transmit(&huart2, (uint8_t*)buffer, strlen(buffer), HAL_MAX_DELAY);
}
HAL_ADC_Stop(&hadc1);
osDelay(2000);
}
}
Final Steps
Compile and flash to your STM32 board
Open Serial Monitor (baud: 115200)
You should see:
LED toggling
UART message every second
ADC voltage printed every 2 seconds
Optional Enhancements
Use Queue or Semaphore to synchronize ADC and UART
Add button interrupt to start/stop tasks dynamically
Use CubeMX timers instead of
osDelay
for more precision
Subscribe to my newsletter
Read articles from ampheo directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
