A complete STM32 FreeRTOS project example for a basic multitasking application

ampheoampheo
2 min read

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

FeatureDescription
MCUSTM32F407VG (any STM32F4 will work similarly)
RTOSFreeRTOS (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 NameFunctionStack SizePriority
BlinkTaskblinkLED128osPriorityNormal
UARTTaskuartTask128osPriorityLow
ADCTaskadcTask128osPriorityLow

4. Generate Code

  • Click Project > Generate Code

  • Open blinkLED.c, uartTask.c, adcTask.c or define them in app_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

0
Subscribe to my newsletter

Read articles from ampheo directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

ampheo
ampheo