FreeRTOS on STM32: RTC and LED Menu

Project Overview

This is a firmware project targeting an STM32 “Nucleo” style board, built using FreeRTOS, whose goal is to provide a user-interactive menu interface via some input (buttons or serial) to configure and display the real-time clock (RTC), plus LED control. The project uses the STM32 HAL (hardware abstraction layer) drivers for RTC and GPIO, and integrates FreeRTOS tasks to manage concurrency — one task handles the menu interaction, another manages the real-time clock functionality, another for LEDs. The project is scaffolded using STM32CubeMX / CubeIDE (the .ioc file is present) to generate peripheral initialization, clock setup, and driver files. At runtime, the system initializes the MCU, starts FreeRTOS, schedules the tasks, and allows a user to navigate menus to view or set RTC parameters and observe LED state changes.

Video Demo

System Design

ardware design (STM32 + RTC + user I/O)

  • MCU board: ST Nucleo-class STM32 (CubeMX .ioc present; HAL drivers + FreeRTOS sources in repo). GitHub
  • Clock/RTC: On-chip RTC peripheral (backup domain). (Assumption: LSE or LSI as time base, configured in CubeMX.)
  • User input:
    • (Assumption) UART (Virtual COM) for a text menu, and/or
    • On-board USER button (short/long press events).
  • User output:
    • (Assumption) On-board LED (e.g., LD2) for status/heartbeat,
    • UART console prints for menu + confirmations.
  • Power: USB 5 V to Nucleo; RTC domain backed by VBAT if present (optional coin cell).

Hardware block diagram (text)

[USB 5V]──►[Nucleo Power]──►[STM32 MCU]
                               │
                               ├──►[RTC Peripheral + Backup Domain]
                               │
         [PC <──USB CDC UART──► MCU USART]   (menu I/O)
                               │
                       [USER Button] [User LED]

Software design (FreeRTOS + HAL)

  • Platform stack: STM32 HAL drivers + FreeRTOS (present under Middlewares/Third_Party/FreeRTOS/Source in repo; app sources under Core/Src). GitHub
  • Init path: SystemClock_Config() → peripheral init (RTC/UART/GPIO) → MX_FREERTOS_Init() → create tasks/queues → vTaskStartScheduler(). (Names typical of CubeMX projects.)
  • Tasks & responsibilities (suggested split):
    • MenuTask (priority: normal): UART RX/parse; render menu; enqueue commands (e.g., SET_TIME, GET_TIME, LED_MODE).
    • RTCTask (priority: above normal): Owns RTC access; handles set/get; publishes time updates periodically.
    • LEDTask (priority: low): Status/heartbeat; optional blink modes tied to system state.
    • UartTxTask (optional): Serial printing to avoid blocking MenuTask when formatting text.
  • Inter-task comms:
    • Queue: CmdQueue (Menu→RTC/LED).
    • Queue/StreamBuffer: LogQueue (any→UartTx).
    • Mutex: RtcMutex (serialize HAL RTC calls if accessed from multiple contexts).
  • Error handling & watchdog (optional): Basic assert hooks; feed IWDG in a low-prio task.
  • Timing:
    • RTCTask tick every 1 s (read time; broadcast update).
    • LEDTask tick 100–250 ms (heartbeat).
    • MenuTask event-driven (UART RX IRQ → ring buffer → task notification).

RTOS interaction diagram (text)

[MenuTask] --CmdQueue--> [RTCTask] --(HAL RTC)--> [RTC]
     │                         │
     └--CmdQueue--> [LEDTask]  └--LogQueue--> [UartTxTask] --> UART TX
            ^                                  ^
            └----------- UART RX --------------┘

Menu flows (high level)

  • Top-level choices:
    1. Show current date/time
    2. Set date/time (validate fields; send SET_TIME)
    3. LED control (ON/OFF/BLINK modes)
    4. About / Help
  • Validation: MenuTask validates user fields (range-check) before posting SET_TIME.
  • Ownership: Only RTCTask touches HAL RTC to avoid race conditions.

Menu state machine (text)

[IDLE]
  │ (key)
  v
[MAIN_MENU] --1--> [SHOW_TIME] --back--> [MAIN_MENU]
          --2--> [SET_TIME_INPUT] --ok--> [CONFIRM_SET] --post--> [MAIN_MENU]
          --3--> [LED_MENU] --mode--> [MAIN_MENU]
          --4--> [HELP] --back--> [MAIN_MENU]

Data & concurrency notes

  • Command struct (example): typedef enum { CMD_GET_TIME, CMD_SET_TIME, CMD_LED_MODE } cmd_id_t; typedef struct { cmd_id_t id; union { rtc_time_t t; uint8_t led_mode; }; } cmd_t;
  • Time model: rtc_time_t mirrors HAL (RTC_TimeTypeDef/RTC_DateTypeDef), stored in 24-hour format; conversions done at MenuTask edge.
  • Thread-safety: All HAL RTC calls behind RtcMutex and centralized in RTCTask.
  • Non-blocking UART: RX via IRQ → ring buffer; MenuTask parses on notification; TX via UartTxTask.

Suggested file/module layout (matches a typical CubeMX + FreeRTOS repo)

  • Core/Src/main.c – system init, scheduler start. GitHub
  • Core/Src/freertos.c – task creation & queues; hooks. GitHub
  • Core/Src/rtc.c, usart.c, gpio.c – HAL init glue. GitHub
  • Core/Src/app_menu.c – MenuTask + parser.
  • Core/Src/app_rtc.c – RTCTask + RTC API.
  • Core/Src/app_led.c – LEDTask.
  • Middlewares/.../FreeRTOS/Source – RTOS kernel. GitHub
  • Nucleo_RTOS_Menu_LED_Proj.ioc – CubeMX project config. GitHub