Electronics - FreeRTOS - SPI, I2C, UART with stack watermark and IWDG watchdog on STM32F3Discovery

Two sensors, two buses, six tasks, one watchdog.

This tutorial makes a firmware production-ready: strict periodic scheduling, stack size validation, and hardware-level crash recovery.

Ready? Let's go.

Shopping list

  • Logic Analyzer for I2C, SPI and UART bus communication

 

First of all

Every sensor task in this project uses vTaskDelayUntil instead of vTaskDelay.

The difference matters in real embedded systems.

vTaskDelay(100) means "sleep for 100ms after I finish executing."

If the task takes 10ms to read a sensor, the actual period is 110ms.

Over time this drifts.

vTaskDelayUntil measures from the moment the task last woke up.

The period is exactly 100ms regardless of execution time.

The gyroscope is read every 50ms.

The accelerometer every 100ms.

Both periods are guaranteed to be constant for as long as the firmware runs.

This matters for signal processing, data logging, and any application where irregular sampling introduces errors.

 

 

Stack watermark

Every FreeRTOS task has a fixed stack allocated at creation.

FreeRTOS fills it with a known pattern at startup.

As the task runs, function calls consume stack from the top.

The watermark is the lowest point ever reached: The minimum free space observed since the task started.

Every 5 seconds, stats_task calls uxTaskGetStackHighWaterMark() on every task and prints the result on UART:

--- stack watermarks (words free) ---

watchdog:  98

gyro    : 187

accel   : 142

display : 201

stats   :  89

leds    : 112

---

A value close to zero means the stack is about to overflow.

A large value means the stack is oversized and RAM is being wasted.

This output tells you exactly how to tune each stack for the real workload.

 

 

IWDG hardware watchdog

The Independent Watchdog is a hardware timer clocked by its own oscillator, completely independent of the CPU and the RTOS.

Once started it cannot be stopped.

If the firmware does not write a specific value to a register within the configured timeout, the MCU resets unconditionally.

watchdog_task runs at the highest priority in the system (priority 4) and pets the IWDG every 500ms using vTaskDelayUntil.

The timeout is set to 1000ms, giving a 2x safety margin.

If any task enters an infinite loop, deadlocks on a mutex, or otherwise monopolises the CPU long enough to prevent watchdog_task from running, the IWDG fires and the MCU reboots.

No human intervention required, no silent hang, the system recovers on its own.

This is not a FreeRTOS feature, it is a hardware feature of the STM32.

FreeRTOS simply provides the task structure to use it correctly.

 

 

Two sensors, two buses, two mutexes

The gyroscope (L3GD20) runs on SPI1.

The accelerometer (LSM303DLHC) runs on I2C1.

Each has its own mutex.

Each has its own task.

Each has its own queue feeding display_task.

The gyroscope reads at 50ms, the accelerometer at 100ms. display_task is driven by the gyroscope queue and picks up accelerometer data whenever it is available.

On cycles where no new accelerometer data has arrived, it prints "---" for those columns.

  GX      GY      GZ    |   AX     AY     AZ

   -12     34    1024   |    -8     22    -15

   -11     33    1023   |   ---    ---    ---

   -13     35    1022   |    -9     21    -14

The two buses run truly in parallel.

Neither blocks the other.

Neither shares any register or hardware resource.

The mutexes exist as a matter of good practice for when a second device is added to each bus.

 

Reading signals

Connect the following pins to your logic analyzer:

  • PA5: SPI SCK
  • PA6: SPI MISO
  • PA7: SPI MOSI
  • PB6: I2C SCL
  • PB7: I2C SDA
  • PA9: UART TX

 

Building and running

$ cd firmware/stm32f3discovery/

$ chmod +x run.sh

$ ./run.sh all

 

Conclusion

Six tasks running concurrently, two hardware buses active simultaneously, a watchdog ensuring the system never hangs silently, and stack watermarks giving a clear picture of memory usage.

This is what production embedded firmware looks like.

Good job, you did it cool

 

Add new comment

Plain text

  • No HTML tags allowed.
  • Lines and paragraphs break automatically.