Skip to content

Latest commit

Β 

History

8 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

LED Pattern Control - FreeRTOS Application

A professional FreeRTOS-based embedded application demonstrating advanced task architecture, thread-safe UART communication, and LED pattern control on STM32F407VG.

πŸ“š For comprehensive technical documentation, detailed architecture analysis, timing diagrams, and design decisions, see Architecture.md

🎯 Project Overview

This project showcases a production-ready FreeRTOS application with an interactive UART menu system for controlling LED patterns. The standout feature is a dedicated print task architecture that eliminates the need for mutex protection by providing exclusive UART TX ownership.

Key Innovation: Instead of using mutexes to protect concurrent UART access (common approach), this implementation uses a dedicated print task with a message queue. This results in cleaner code, better performance, and guaranteed thread safety.

✨ Features

  • 🎨 4 LED Patterns: Static ON, Different frequency blinking, Synchronized blinking, OFF
  • πŸ’¬ Interactive UART Menu: Hierarchical menu system with command processing
  • πŸ”’ Thread-Safe Design: Queue-based architecture eliminates race conditions
  • ⚑ Non-Blocking I/O: Print operations return immediately, no task blocking
  • βš™οΈ Efficient UART RX: Stream Buffer mode with TRUE task blocking (zero CPU waste)
  • πŸ• Watchdog System: Detects hung or deadlocked tasks automatically
  • πŸ”‹ Power Efficient: ~98% CPU idle time, WFI sleep mode in idle hook
  • πŸ“Š Well Architected: Clean separation of concerns (RX, TX, commands, LEDs)
  • πŸ“š Comprehensive Documentation: Detailed architecture documentation included

πŸ—οΈ Architecture Highlights

Task Structure

Priority 4: Watchdog Task   β†’ Monitors task health, detects deadlocks
Priority 3: Print Task      β†’ Exclusive UART TX owner
Priority 2: UART Task       β†’ Character reception & buffering
Priority 2: Command Handler β†’ Menu state machine & LED control
Priority 2: Timer Service   β†’ Software timer callbacks for LED patterns
Priority 0: Idle Task       β†’ Power save (WFI instruction)

Print Task Design

Problem with Traditional Mutex Approach:

// Multiple tasks competing for UART
xSemaphoreTake(uart_mutex, portMAX_DELAY);
HAL_UART_Transmit(&huart2, data, len, timeout);  // Task blocks here
xSemaphoreGive(uart_mutex);

Issues: Priority inversion, blocking delays, complex error handling

Our Solution - Dedicated Print Task:

// Any task, anywhere
print_message("Hello World\r\n");  // Returns immediately!
print_char('A');                    // Non-blocking echo

Benefits:

  • βœ… Non-blocking (enqueue ~20-50ΞΌs, return immediately)
  • βœ… No priority inversion (queue-based synchronization)
  • βœ… Cleaner code (no mutex boilerplate in 10+ locations)
  • βœ… FIFO ordering guaranteed
  • βœ… Single point of control (easy to extend)

Memory Usage

Component Size Utilization
Total Heap 75 KB 17% used
Print Queue ~5.1 KB 10 messages Γ— 512 bytes
Task Stacks ~6.7 KB 5 tasks
Free Memory ~62 KB Available for expansion

UART RX Architecture (Stream Buffer Mode)

Efficient interrupt-driven reception:

UART RX (PA3)
     ↓
 RX Interrupt (ISR)
     ↓
Stream Buffer ──> UART Task (BLOCKED)
 (Lock-free)      Wakes instantly!

Benefits:

  • βœ… TRUE blocking - Task enters BLOCKED state, yields CPU
  • βœ… Zero CPU waste - No polling loop
  • βœ… Instant wake-up - ISR immediately unblocks task
  • βœ… Thread-safe - Lock-free ISR-to-Task communication

Watchdog System (Deadlock Detection)

All tasks actively monitored:

UART_task, CMD_Handler, Print_Task
         ↓ Register & feed every 2 seconds
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚ Watchdog Task   β”‚  Checks every 1 second
  β”‚  (Priority 4)   β”‚  β†’ If task hasn't fed in 5s β†’ ALERT!
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Implementation:

// All three tasks use finite timeouts for watchdog monitoring
void uart_task_handler(void *parameters) {
    watchdog_id_t wd_id = watchdog_register("UART_task", 5000);

    while(1) {
        // Finite 2s timeout (instead of portMAX_DELAY)
        xStreamBufferReceive(buffer, &ch, 1, pdMS_TO_TICKS(2000));

        watchdog_feed(wd_id);  // Prove I'm alive every 2s
    }
}

Active Monitoring:

  • βœ… UART_task - Feeds every 2s (5s timeout)
  • βœ… CMD_Handler - Feeds every 2s (5s timeout)
  • βœ… Print_Task - Feeds every 2s (5s timeout)

Detects:

  • πŸ” Hung tasks (stuck in infinite loop)
  • πŸ” Deadlocked tasks (waiting on mutex forever)
  • πŸ” Crashed tasks (hard fault before feeding)
  • πŸ” Starved tasks (priority inversion)

See: WATCHDOG_USAGE.md for complete guide

Communication Flow

User Terminal
     ↓
  UART RX (PA3) β†’ RX ISR β†’ Stream Buffer β†’ UART Task β†’ Command Queue β†’ Command Handler
                            (Instant)       (BLOCKED)                           ↓
                                                                          LED Effects
                                                                                ↓
  UART TX (PA2) ←─────────── Print Task ← Print Queue ←────────── Response Messages
     ↓
User Terminal

πŸ› οΈ Hardware Requirements

  • Board: STM32F407VG Discovery Board
  • Debugger: ST-LINK/V2 (integrated on Discovery board)
  • USB-UART Adapter: FTDI FT232RL or similar (3.3V logic level)
  • LEDs: On-board LEDs (PD12-Green, PD13-Orange)

Hardware Setup Diagram


    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚                  β”‚
    β”‚    PC / Laptop   β”‚
    β”‚                  β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
             β”‚
      β”Œβ”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”
      β”‚               β”‚
   USB-A          USB Mini-B
      β”‚               β”‚
      β”‚               β”‚
      β”‚        β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
      β”‚        β”‚  STM32F407VG Discovery Board            β”‚
      β”‚        β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
      β”‚        β”‚  β”‚                                 β”‚    β”‚
      β”‚        β”‚  β”‚      STM32F407VG MCU           β”‚    β”‚
      β”‚        β”‚  β”‚    (ARM Cortex-M4F)            β”‚    β”‚
      β”‚        β”‚  β”‚                                 β”‚    β”‚
      β”‚        β”‚  β”‚  PA2 (UART2 TX) ────────┐      β”‚    β”‚
      β”‚        β”‚  β”‚  PA3 (UART2 RX) ────────┼──┐   β”‚    β”‚
      β”‚        β”‚  β”‚  GND ────────────────────┼──┼─┐ β”‚    β”‚
      β”‚        β”‚  β”‚                          β”‚  β”‚ β”‚ β”‚    β”‚
      β”‚        β”‚  β”‚  PD12 β†’ [LED] Green ●   β”‚  β”‚ β”‚ β”‚    β”‚
      β”‚        β”‚  β”‚  PD13 β†’ [LED] Orange ●  β”‚  β”‚ β”‚ β”‚    β”‚
      β”‚        β”‚  β”‚                          β”‚  β”‚ β”‚ β”‚    β”‚
      β”‚        β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚ β”‚ β”‚    β”‚
      β”‚        β”‚         β–²                       β”‚ β”‚ β”‚    β”‚
      β”‚        β”‚         β”‚ SWD (Debug/Flash)    β”‚ β”‚ β”‚    β”‚
      β”‚        β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”               β”‚ β”‚ β”‚    β”‚
      β”‚        β”‚  β”‚  ST-LINK/V2 β”‚               β”‚ β”‚ β”‚    β”‚
      β”‚        β”‚  β”‚  (On-board) β”‚               β”‚ β”‚ β”‚    β”‚
      β”‚        β”‚  β””β”€β”€β”€β”€β”€β”€β–²β”€β”€β”€β”€β”€β”€β”˜               β”‚ β”‚ β”‚    β”‚
      β”‚        β”‚         β”‚                       β”‚ β”‚ β”‚    β”‚
      β”‚        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”Όβ”€β”Όβ”€β”€β”€β”€β”˜
      β”‚                  β”‚                       β”‚ β”‚ β”‚
      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                       β”‚ β”‚ β”‚
             USB Mini-B (Debug/Flash)            β”‚ β”‚ β”‚
                                                 β”‚ β”‚ β”‚
      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚
      β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
      β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
      β”‚  β”‚  β”‚                                       β”‚
   β”Œβ”€β”€β–Όβ”€β”€β–Όβ”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”                                β”‚
   β”‚  FTDI FT232RL β”‚                                β”‚
   β”‚  USB-to-UART  β”‚                                β”‚
   β”‚               β”‚                                β”‚
   β”‚  RX ────────────────> PA2 (TX)                 β”‚
   β”‚  TX ────────────────> PA3 (RX)                 β”‚
   β”‚  GND β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
   β”‚               β”‚
   β””β”€β”€β”€β”€β”€β”€β”€β–²β”€β”€β”€β”€β”€β”€β”€β”˜
           β”‚
       USB-A to PC
       (Serial Terminal)


Connections Summary:
╔═══════════════════╦══════════════════════════════════════════╗
β•‘ Connection Type   β•‘ Details                                  β•‘
╠═══════════════════╬══════════════════════════════════════════╣
β•‘ Debug & Flash     β•‘ PC USB β†’ STM32 Discovery USB (ST-LINK)  β•‘
β•‘ Serial Terminal   β•‘ PC USB β†’ FTDI adapter β†’ STM32 UART2     β•‘
β•‘ UART Wiring       β•‘ FTDI RX ← PA2 (TX)                      β•‘
β•‘                   β•‘ FTDI TX β†’ PA3 (RX)                      β•‘
β•‘                   β•‘ FTDI GND β†’ STM32 GND                    β•‘
β•‘ LEDs              β•‘ PD12 (Green), PD13 (Orange) - On-board  β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•©β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•

Power: STM32 powered via USB (ST-LINK connection)

Pin Connections Detail

FTDI FT232RL         STM32F407VG Discovery
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚             β”‚      β”‚                  β”‚
β”‚  RX (In)    │◄────── PA2 (UART2 TX)   β”‚  (Yellow wire)
β”‚  TX (Out)   │─────►│ PA3 (UART2 RX)   β”‚  (Orange wire)
β”‚  GND        │─────── GND              β”‚  (Black wire)
β”‚  VCC (3.3V) β”‚  βœ—   β”‚ (Not connected)  β”‚  (Board self-powered)
β”‚             β”‚      β”‚                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
     β”‚
     β”‚ USB
     β–Ό
    PC (Serial Terminal: 115200 baud, 8N1)

πŸ’» Software Requirements

  • IDE: STM32CubeIDE (or command-line ARM GCC)
  • Toolchain: ARM GCC (arm-none-eabi)
  • RTOS: FreeRTOS v10.x (included)
  • HAL: STM32F4 HAL Driver (included)
  • Terminal: minicom, screen, PuTTY, or similar (115200 baud, 8N1)

πŸš€ Getting Started

1. Build the Project

Using STM32CubeIDE:

# Import project into STM32CubeIDE
File β†’ Import β†’ Existing Projects into Workspace
# Select Debug or Release configuration
# Build: Ctrl+B or Project β†’ Build All

Using Command Line:

cd Debug/
make clean
make -j4

2. Flash to STM32

# Using ST-LINK utility or STM32CubeIDE
# Flash the generated .elf or .bin file

3. Connect Terminal

# Linux/macOS
screen /dev/ttyUSB0 115200
# or
screen /dev/tty.usbserial-XXXXX 115200

# Windows
# Use PuTTY: COM port, 115200 baud, 8N1

4. Interact with Menu

****************************************
*                                      *
*   LED Pattern Control Application   *
*        FreeRTOS UART Interface       *
*                                      *
****************************************

========================================
              MAIN MENU
========================================
  1 - LED Patterns
  2 - Exit Application
========================================
Enter selection: 1

========================================
        LED Pattern Selection
========================================
  0 - Return to main menu
  1 - All LEDs ON
  2 - Different Frequency Blinking
  3 - Same Frequency Blinking
  4 - All LEDs OFF
========================================
Enter selection:

πŸ“ Project Structure

rtos-led-control-uart-menu/
β”œβ”€β”€ includes/
β”‚   β”œβ”€β”€ main.h
β”‚   β”œβ”€β”€ uart_task.h
β”‚   β”œβ”€β”€ print_task.h           ← Print task API
β”‚   β”œβ”€β”€ command_handler.h
β”‚   β”œβ”€β”€ led_effects.h
β”‚   └── watchdog.h             ← Watchdog API
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ main.c                  ← Initialization & task creation
β”‚   β”œβ”€β”€ uart_task.c             ← Character RX & buffering
β”‚   β”œβ”€β”€ print_task.c            ← Print task implementation
β”‚   β”œβ”€β”€ command_handler.c       ← Menu state machine
β”‚   β”œβ”€β”€ led_effects.c           ← LED pattern control
β”‚   β”œβ”€β”€ watchdog.c              ← Watchdog implementation
β”‚   └── stm32f4xx_it.c          ← Interrupt handlers
β”‚   └── Startup/
β”‚       └── startup_stm32f407vgtx.s
β”œβ”€β”€ Drivers/                         ← STM32 HAL & CMSIS
β”œβ”€β”€ common/ThirdParty/
β”‚   β”œβ”€β”€ FreeRTOS/                   ← FreeRTOS kernel
β”‚   └── SEGGER/                     ← SEGGER SystemView (optional)
β”œβ”€β”€ Debug/                          ← Build output
β”œβ”€β”€ Architecture.md                 ← Detailed architecture docs
β”œβ”€β”€ README.md                       ← This file
└── STM32F407VGTX_FLASH.ld         ← Linker script

πŸ”§ Configuration

Key Parameters (print_task.h)

#define PRINT_MESSAGE_MAX_SIZE 512      // Max message length
#define PRINT_QUEUE_DEPTH 10            // Number of queued messages
#define PRINT_TASK_PRIORITY 3           // Highest app priority
#define PRINT_TASK_STACK_SIZE 512       // Stack in words (2048 bytes)

FreeRTOS Config (FreeRTOSConfig.h)

#define configTOTAL_HEAP_SIZE       (75 * 1024)  // 75 KB heap
#define configTICK_RATE_HZ          1000         // 1ms tick
#define configMAX_PRIORITIES        5            // Priority levels 0-4
#define configUSE_PREEMPTION        1            // Preemptive scheduling
#define configUSE_IDLE_HOOK         1            // Enable WFI sleep
#define configUSE_TIMERS            1            // Software timers
#define configTIMER_TASK_PRIORITY   2            // Timer service priority

πŸ§ͺ Testing & Verification

Tested Scenarios

βœ… Character Echo - Immediate feedback, no lag βœ… Menu Navigation - All menus display completely, no truncation βœ… LED Patterns - All 4 patterns work correctly βœ… Thread Safety - No text corruption under rapid input βœ… Error Handling - Buffer overflow and queue full handled gracefully βœ… Backspace - Visual feedback works correctly βœ… Power Efficiency - CPU ~98% idle, WFI sleep active

Performance Metrics

Metric Value
Character Echo Latency ~50-100ΞΌs
Command Processing <6ms
CPU Load (Active) ~2%
CPU Load (Idle) ~98%
Average Power ~22 mA @ 3.3V
Heap Utilization 17% (62 KB free)

πŸŽ“ Learning Outcomes

This project demonstrates:

  1. FreeRTOS Task Design - Multiple cooperating tasks with proper priorities
  2. Queue-Based Communication - Producer-consumer patterns
  3. Resource Management - Exclusive ownership vs mutex protection
  4. State Machines - Menu navigation and command processing
  5. Software Timers - LED pattern control without blocking
  6. Power Management - WFI sleep mode in idle task
  7. Professional Practices - Clean code, documentation, error handling

πŸ“– Documentation

πŸ“š Architecture.md - Complete Technical Reference

1000+ lines of comprehensive documentation including:

  • Task Architecture - Detailed analysis of all 5 tasks with priorities, stack sizes, responsibilities
  • FreeRTOS Objects - Queues, timers, synchronization primitives
  • Data Flow Diagrams - Complete system communication paths
  • Timing Analysis - Worst-case response times, latency measurements
  • Memory Maps - Heap allocation, stack usage, resource utilization
  • Interrupt Configuration - UART RX, SysTick, priority levels
  • Critical Section Analysis - Thread safety implementation details
  • Power Management - WFI sleep mode, power consumption estimates
  • Troubleshooting Guide - Common issues and solutions
  • Design Decisions - Evolution from mutex to print task architecture
  • Testing Verification - Complete test results and validation
  • Performance Metrics - CPU load, memory usage, response times

This README provides a quick start guide. For deep technical understanding, refer to Architecture.md.

🚧 Future Enhancements

Recommended Next Steps

  1. SEGGER RTT Logging

    • Add dedicated debug logging via SWD (no UART pins needed)
    • SystemView integration for visual task analysis
    • Log task states, queue depths, heap usage
  2. Advanced Features

    • User-configurable LED patterns stored in flash
    • Command history with up/down arrow support
    • Runtime statistics menu (CPU usage, stack watermarks)
  3. Production Hardening

    • Watchdog timer integration
    • Stack overflow detection hooks
    • Comprehensive fault handlers with diagnostics

πŸ› Troubleshooting

Common Issues

No output on terminal:

  • Check UART connections (TX ↔ RX, RX ↔ TX)
  • Verify baud rate: 115200, 8N1
  • Press STM32 RESET button after connecting terminal

Text corruption:

  • Ensure you flashed the latest firmware
  • Print task priority must be 3 (highest)
  • Only print task should call HAL_UART_Transmit()

LEDs not blinking:

  • Verify led_effects_init() called before scheduler starts
  • Check timer priorities (should be 2)
  • Ensure patterns 2 or 3 selected (1 is static ON)

πŸ“„ License

This project is for educational and personal use. Feel free to learn from, modify, and extend it.

πŸ™ Acknowledgments

  • STMicroelectronics - STM32 HAL libraries and CMSIS
  • FreeRTOS - Real-time operating system kernel
  • SEGGER - SystemView debugging tools

πŸ“§ Contact

For questions or discussions about this project, please refer to the detailed Architecture.md documentation.


About

STM32 LED Pattern Controller with FreeRTOS and UART Menu

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages