Learn STM32F3DISCOVERY: From Zero to STM32F3DISCOVERY Master

Goal: Build a deep, practical understanding of the STM32F3DISCOVERY board and the STM32F303VCT6 MCU so you can design real-time firmware with confidence. You will learn how the Cortex-M4 core, clock tree, memory map, GPIO, timers, mixed-signal peripherals, interrupts, DMA, and power modes cooperate under real-world constraints. You will also learn to instrument, measure, and validate behavior (timing, sampling, latency, power) instead of relying on guesses. By the end, you will be able to plan, build, and debug reliable sensor-and-actuator systems using a repeatable engineering process.


Introduction: What This Guide Covers

STM32F3DISCOVERY is an STM32 Discovery kit built around the STM32F303VCT6 Cortex-M4F MCU. It includes an on-board ST-LINK/V2 (or V2-B) debugger, USB, MEMS sensors (gyro + accel/magnetometer), LEDs, and push-buttons so you can build complete mixed-signal embedded systems without extra hardware. The MCU runs up to 72 MHz and includes rich analog peripherals (fast ADCs, DACs, comparators, op-amps) plus timers, DMA, and common serial interfaces. citeturn3view0turn0search0

What you will build (by the end of this guide):

  • A verified bring-up and clock audit with measurable timing accuracy
  • A full GPIO/alternate-function map for the board and repeatable peripheral validation
  • Timer-driven PWM control, ADC sampling pipelines, DAC waveform generation, and DMA streaming
  • Robust I2C/SPI/UART drivers, interrupt-latency profiling, and a fault-tolerant watchdog flow
  • A sensor-fusion dashboard using on-board MEMS devices
  • A final, integrated real-time environmental monitor with control outputs

Scope (what’s included):

  • Cortex-M4 startup, boot flow, vector tables, and reset behavior
  • Clock tree configuration and timing validation
  • GPIO, timers, PWM, ADC/DAC, DMA, NVIC/interrupts
  • I2C, SPI, UART, USB FS, and basic CAN concepts (where available)
  • Power modes, reliability, and watchdog recovery
  • On-board sensor integration and calibration

Out of scope (for this guide):

  • Full RTOS design (we stay mostly bare-metal or HAL/LL)
  • High-speed USB device stack development
  • Advanced digital signal processing (DSP) or control theory proofs
  • External RF or high-voltage design

The Big Picture (Mental Model)

Physical World
  (motion, light, temp, position)
           |
           v
  Analog Front-End -> ADC -> DMA -> Buffers -> Control Logic -> PWM/DAC -> Actuators
           ^                                  |
           |                                  v
     I2C/SPI Sensors ----------------------> UART/USB Logs

                  ^
                  |
             NVIC + Timers
        (real-time scheduling)

Key Terms You’ll See Everywhere

  • Cortex-M4F: 32-bit Arm MCU core with floating-point support for real-time numeric processing. citeturn0search0
  • Clock Tree: The system of oscillators, PLLs, and prescalers that sets the timing of the CPU and peripherals.
  • NVIC: Nested Vectored Interrupt Controller, the hardware that prioritizes and dispatches interrupts.
  • DMA: Direct Memory Access engine that moves data between peripherals and memory without CPU involvement.
  • Alternate Function: A pin multiplexer selection that routes a pin to a peripheral (SPI, UART, timer, etc.).

How to Use This Guide

  1. Read the Theory Primer first. This is your mini-book. It builds the mental model you need for every project.
  2. Keep a lab notebook. Record clock settings, measured timings, pin maps, and observed issues.
  3. Do projects in order unless you already have strong embedded experience. Later projects reuse earlier tooling.
  4. Measure everything. If the project says 1 kHz, verify it. If it says 100 Hz sampling, log it.
  5. Use the “Definition of Done” checklists to decide when a project is truly complete.

Prerequisites & Background Knowledge

Before starting these projects, you should have foundational understanding in these areas:

Essential Prerequisites (Must Have)

Programming Skills:

  • C fundamentals (variables, structs, pointers, arrays)
  • Bitwise operations and masks
  • Comfortable reading function prototypes and simple header files

Embedded Fundamentals:

  • Voltage, current, and ground basics
  • Reading a pinout diagram or board schematic
  • Basic timing math (Hz, period, ms/us)

Recommended Reading:

  • “Making Embedded Systems, 2nd Edition” by Elecia White - Ch. 1-3
  • “Effective C, 2nd Edition” by Robert C. Seacord - Ch. 3-6

Helpful But Not Required

ARM Core Details:

  • Exception model, vector tables, stack usage
  • Can learn during: Projects 1, 7, 12

Signal Processing Basics:

  • Nyquist, aliasing, quantization
  • Can learn during: Projects 5, 6, 8, 15

Hardware Debugging Tools:

  • Logic analyzer or oscilloscope use
  • Can learn during: Projects 3, 4, 7, 8

Self-Assessment Questions

  1. Can you explain what a pull-up resistor does?
  2. Can you read a C header file and find a register definition?
  3. Can you compute a timer period from a clock frequency?
  4. Can you describe what an interrupt is and why it matters?
  5. Can you read a board pinout without guessing?

If you answered “no” to 1-3: Spend 1-2 weeks on the recommended reading above before starting.

Development Environment Setup

Required Tools:

  • STM32F3DISCOVERY board with USB cable
  • STM32CubeIDE (includes GCC toolchain and STM32CubeMX) citeturn3view0
  • ST-LINK drivers (installed with STM32CubeIDE)

Recommended Tools:

  • Logic analyzer or oscilloscope (for timing verification)
  • Multimeter (for power and voltage checks)
  • Serial terminal (screen/minicom/putty)

Testing Your Setup:

# Verify STM32CubeIDE installs a GCC toolchain
$ arm-none-eabi-gcc --version
arm-none-eabi-gcc (version output)

# Verify ST-LINK is detected (Linux/macOS)
$ lsusb | grep -i st-link
STMicroelectronics ST-LINK/V2

Time Investment

  • Simple projects (1, 2): Weekend (4-8 hours each)
  • Moderate projects (3-6, 9-12): 1-2 weeks each
  • Complex projects (7, 8, 13-15): 2+ weeks each
  • Final integration: 1 month+

Important Reality Check

STM32 development is real engineering. The first pass is about making it work, the second is about making it correct, and the third is about making it robust. Expect to re-read datasheets, change configurations, and re-measure. This is normal.


Big Picture / Mental Model

                 +--------------------+      +--------------------+
Sensors (I2C/SPI)|  MEMS / External   |----->|  Drivers + Calib    |
                 +--------------------+      +--------------------+
                             |                         |
                             v                         v
                        +----------+              +-----------+
Analog Signals -------->|   ADC    |--DMA------->|  Buffers   |
                        +----------+              +-----------+
                             |                         |
                             v                         v
                        +----------+              +-----------+
                        | Control  |<---Timers----| Scheduler |
                        |  Logic   |              | + NVIC    |
                        +----------+              +-----------+
                             |                         |
                             v                         v
                        +----------+              +-----------+
                        | PWM/DAC  |------------->| Actuators |
                        +----------+              +-----------+
                             |
                             v
                         UART/USB Logs

Mental model: The MCU is a dataflow engine. Signals enter, are sampled, moved by DMA, processed by control logic, and turned into outputs. Timers and interrupts define when things happen. Power and reliability features ensure the system survives real-world faults.


Theory Primer (Read This Before Coding)

This is your mini-book. Each chapter gives you the concepts you must internalize to complete the projects.

Chapter 1: Board Anatomy and MCU Architecture

Fundamentals

STM32F3DISCOVERY is a complete system built around the STM32F303VCT6 MCU, which integrates a Cortex-M4 core, flash, SRAM, and a large suite of peripherals. The board provides power, USB connectivity, sensors, LEDs, and debugging in a single unit, so you can treat it like a small embedded computer with real-world I/O. Understanding the board means understanding how the MCU core connects to peripherals through buses, how memory is mapped, and how external devices (sensors, LEDs, headers) are wired to MCU pins. The STM32F303 family is designed for mixed-signal work: it includes fast ADCs, DACs, comparators, op-amps, timers, and DMA on the same silicon. This is what makes it suitable for control loops, sensor acquisition, and motor control. citeturn3view0turn0search0

Deep Dive into the Concept

The STM32F303VCT6 is a microcontroller that combines a high-performance Cortex-M4F CPU with a set of tightly coupled peripherals on a shared bus fabric. The CPU executes code from flash, reads and writes SRAM, and configures peripherals through memory-mapped registers. Every peripheral is visible as a register block in the MCU address space; writing to those registers flips bits in hardware. This means your C code, at the lowest level, is just performing memory reads and writes to specific addresses. The MCU uses an AHB (Advanced High-performance Bus) for core access and APB (Advanced Peripheral Bus) for most peripherals. The clock tree drives these buses, and prescalers decide how fast each bus runs. If the bus runs slower than the CPU, peripheral access can stall; if it’s too fast, a peripheral may misbehave. So architecture is not just a block diagram: it determines latency and throughput.

The STM32F303 family includes up to 256 KB flash and 48 KB SRAM in the STM32F303VCT6 variant on the discovery board. It provides multiple ADCs (up to four 12-bit ADCs at 5 Msps), DAC channels, comparators, and op-amps; and a large suite of timers (general-purpose, advanced-control, and basic timers) plus DMA channels. This is the reason it is called a “mixed-signal” MCU: analog and digital are deeply integrated. citeturn0search0

Board-level anatomy matters because it constrains what you can use. The STM32F3DISCOVERY includes an on-board ST-LINK/V2 or ST-LINK/V2-B debugger, USB connectors, user LEDs, push buttons, and MEMS sensors. These are wired to specific pins on the MCU. Some pins are already in use by sensors or LEDs, which means you cannot use them for other peripherals without conflicts. The board also has expansion headers that expose the LQFP100 pinout so you can connect external hardware. You should treat the board like a real product PCB: document which pins are used, confirm voltage rails, and know which peripherals are safe to use. citeturn3view0

The architecture also defines performance ceilings. The Cortex-M4F core at 72 MHz can do a lot, but data movement can become the bottleneck if you sample fast ADC channels and do heavy computation in interrupts. This is where DMA and buffering patterns become essential. Another architectural detail: the core includes a floating-point unit (FPU) and efficient arithmetic support, which makes real-time filtering and sensor fusion possible without a separate DSP. citeturn0search0 For example, you can implement a complementary filter or simple Kalman-style estimator directly on the MCU. If you understand the architecture, you will know when to use the CPU and when to offload to DMA or timers.

Finally, architecture shapes debugging. The ST-LINK interface gives you SWD access to the CPU, letting you halt, inspect memory, and program flash. But that also changes timing; when you halt the core, peripherals may continue running. That means you must design your firmware to be observable without stopping the CPU (UART logs, GPIO toggles, LED indicators). The architecture therefore impacts not just what you build, but how you build and validate it.

How This Fits in Projects

  • Projects 1-2 rely on understanding board wiring, memory map, and pin availability.
  • Projects 3-8 use timers, ADCs, DMA, and interrupts, all of which are architectural building blocks.
  • Projects 9-15 depend on knowing which pins and buses are already in use on the board.

Definitions & Key Terms

  • Memory-mapped I/O: Peripherals are controlled by writing to special addresses in memory.
  • AHB/APB buses: Internal buses that connect the CPU to memory and peripherals.
  • Mixed-signal MCU: A microcontroller with advanced analog peripherals on-chip.
  • ST-LINK: On-board debug and programming interface.

Mental Model Diagram

         +-------------------+         +----------------------+
CPU <--> | AHB Bus + Matrix  | <-----> | Flash / SRAM / DMA    |
         +-------------------+         +----------------------+
                  |
                  v
          +-----------------+    +-----------------+
          | APB Peripherals |<-->| Timers / ADC /   |
          +-----------------+    | GPIO / UART /    |
                                  | I2C / SPI / DAC |
                                  +-----------------+

How It Works (Step-by-Step, with Invariants and Failure Modes)

  1. CPU fetches instructions from flash, executes C code.
  2. Code writes peripheral registers (memory-mapped) to configure hardware.
  3. Peripherals run independently based on clock signals.
  4. Data moves via CPU reads or DMA transfers into SRAM.
  5. Interrupts trigger when events occur (timer overflow, ADC conversion, etc.).

Invariant: Peripherals only work if their clocks are enabled and configured. Failure mode: If a peripheral’s clock is off or misconfigured, its registers appear to change but nothing happens physically.

Minimal Concrete Example

// Minimal memory-mapped GPIO toggle (register names simplified)
#define GPIOE_ODR (*(volatile unsigned int*)0x48001014)

int main(void) {
    // Configure GPIO pin elsewhere...
    while (1) {
        GPIOE_ODR ^= (1 << 13); // Toggle PE13
        for (volatile int i = 0; i < 100000; i++); // crude delay
    }
}

Common Misconceptions

  • “The CPU does everything.” -> Many peripherals run without CPU involvement once configured.
  • “If the register writes, it must work.” -> The peripheral might be clock-gated or pinned out incorrectly.
  • “Debugging with breakpoints shows real-time behavior.” -> Halting the core changes timing.

Check-Your-Understanding Questions

  1. What does it mean that peripherals are “memory-mapped”?
  2. Why do bus clocks matter for peripheral timing?
  3. Why might a GPIO not toggle even if you write to the output register?

Check-Your-Understanding Answers

  1. Peripherals appear at fixed memory addresses; writing those addresses configures hardware.
  2. Peripheral clocks derive from bus clocks, so timing depends on prescalers and source.
  3. The GPIO clock may be disabled, or the pin may be mapped to an alternate function.

Real-World Applications

  • Motor control (timers + ADC + comparators)
  • Data acquisition (ADC + DMA)
  • Sensor fusion (I2C/SPI + CPU arithmetic acceleration)

Where You’ll Apply It

Projects 1-2, 3-6, 8-15

References

  • STM32F3DISCOVERY product page (board features) citeturn3view0
  • STM32F303VC product page (core/peripheral summary) citeturn0search0

Key Insight

Architecture determines what is possible, what is fast, and what is fragile.

Summary

You are programming a system of buses, clocks, and peripherals, not just a CPU. Treat the board like a real product design.

Homework/Exercises to Practice the Concept

  1. Draw the data path for an ADC reading to PWM output.
  2. Identify which board pins are already used by LEDs and sensors.
  3. List which peripherals are required for a sensor logging system.

Solutions to the Homework/Exercises

  1. ADC -> DMA -> SRAM buffer -> control logic -> timer/PWM.
  2. LEDs and sensors are connected to specific port E and I2C/SPI pins; verify with the board schematic or UM1570. citeturn1search6
  3. ADC, timer, DMA, UART for logging, plus GPIO for control.

Chapter 2: Boot, Reset, Debug, and Toolchain

Fundamentals

Every embedded system starts at reset. On STM32F3, the CPU reads the initial stack pointer and reset vector from flash, then jumps into your startup code. Boot configuration pins and option bytes select whether the MCU boots from internal flash, system memory (factory bootloader), or SRAM. Debugging via SWD (Serial Wire Debug) is provided by the on-board ST-LINK, which also programs flash. This boot path and toolchain flow matter because a misconfigured vector table or startup file can leave the MCU “dead” even though hardware is fine.

Deep Dive into the Concept

On Cortex-M devices, the first 8 bytes of the vector table hold the initial stack pointer and the reset handler address. When reset occurs, the CPU loads SP and PC from these addresses and begins execution. Your startup code then initializes the data and BSS sections, sets up the clock (if you override defaults), and finally calls main(). If you set the wrong vector table base address, or if your linker script puts it somewhere unexpected, the CPU will fetch the wrong addresses and crash immediately. This is why linker scripts, startup code, and the build system must match.

Boot modes on STM32F3 are controlled by BOOT pins and option bytes. Booting from system memory launches the factory ROM bootloader, which can accept firmware over supported interfaces. This is critical for recovery if you corrupt flash. Booting from SRAM is useful for development and special debugging workflows but is uncommon in production. The key is: if the MCU does not boot, the first question is “what did it try to boot from”?

The ST-LINK/V2 or ST-LINK/V2-B on the discovery board provides programming and debugging. It connects to the MCU via SWD, allowing you to read and write memory, set breakpoints, and program flash. On some board revisions, ST-LINK/V2-B also exposes a USB virtual COM port, which is a convenient way to do printf-style logging without extra hardware. citeturn3view0

The toolchain matters because each layer has assumptions. STM32CubeIDE generates startup code and linker scripts for you if you use CubeMX. If you switch to a pure makefile, you must ensure the same memory layout and startup steps. The CMSIS layer provides core register definitions, while HAL (Hardware Abstraction Layer) and LL (Low-Layer) libraries provide peripheral drivers. HAL is slower but easier; LL is closer to the metal and gives tighter control. Understanding which layer you’re using is essential for debugging: if HAL is reconfiguring a peripheral every time you call a function, your manual register writes might be undone.

A subtle but important point: debugging can change timing. When you pause the CPU, peripherals might continue running or might halt depending on debug configuration. This can cause timers to drift or DMA transfers to complete unexpectedly. To avoid this, develop observability that works while the CPU runs (UART logs, GPIO pulses, LED states). Treat the debugger as a microscope, not the primary data source.

How This Fits in Projects

  • Project 1 validates boot and clock setup.
  • Project 12 uses UART for observability to avoid reliance on the debugger.
  • Project 14 relies on reset cause logging and watchdog recovery.

Definitions & Key Terms

  • Vector table: Table of exception and interrupt handler addresses.
  • Reset handler: First function executed after reset.
  • Option bytes: Non-volatile configuration bits controlling boot mode and other settings.
  • CMSIS: Arm standard for core/peripheral register definitions.
  • HAL/LL: ST’s high-level and low-level peripheral libraries.

Mental Model Diagram

Reset -> Vector Table -> Startup -> Clock Init -> main()
          |                 |
          |                 v
          +-> Interrupts  Runtime + HAL/LL

Debugger (ST-LINK) <-> SWD <-> CPU core

How It Works (Step-by-Step, with Invariants and Failure Modes)

  1. Reset occurs; CPU reads SP and PC from vector table.
  2. Startup code initializes RAM (data, BSS) and stack.
  3. Clock and system init run (if configured).
  4. main() executes.
  5. Debugger can halt, read memory, and program flash.

Invariant: Vector table must be at the configured base address and valid. Failure mode: Incorrect linker script -> MCU jumps to an invalid address.

Minimal Concrete Example

// Bare-minimum reset handler pattern (startup file)
extern int main(void);
void Reset_Handler(void) {
    SystemInit(); // clock setup
    __libc_init_array();
    main();
    while (1) {}
}

Common Misconceptions

  • “If it doesn’t run, the MCU is dead.” -> It might be booting from the wrong memory.
  • “Breakpoints never affect timing.” -> They often do.
  • “HAL and LL can be mixed freely.” -> They can, but you must understand ownership of registers.

Check-Your-Understanding Questions

  1. What are the first two words in the vector table used for?
  2. How does the MCU decide whether to boot from flash or system memory?
  3. Why can debugging distort timing measurements?

Check-Your-Understanding Answers

  1. Initial stack pointer and reset handler address.
  2. BOOT pins and option bytes select the boot memory.
  3. Halting the CPU changes timer and peripheral behavior.

Real-World Applications

  • In-field firmware updates using system bootloader
  • Debugging production failures
  • Safe recovery after watchdog resets

Where You’ll Apply It

Projects 1, 12, 14, 16

References

  • STM32F3DISCOVERY product page (ST-LINK/V2-B VCP and debugger) citeturn3view0
  • STM32F303 documentation list (reference manual and programming manual) citeturn0search1

Key Insight

Boot and debug pathways are part of the product design, not just development tools.

Summary

Mastering reset flow, vector tables, and debug behavior makes firmware reliable and recoverable.

Homework/Exercises to Practice the Concept

  1. Locate the vector table address in your linker map.
  2. Identify how to enter system bootloader mode on STM32F3.
  3. Write a short note on how you will log reset causes.

Solutions to the Homework/Exercises

  1. The linker map lists the .isr_vector section in flash at the base address.
  2. Use BOOT configuration (pins/option bytes) to select system memory boot.
  3. Read and log reset cause flags early in main().

Chapter 3: Clock Tree and Timing Domains

Fundamentals

The STM32F303 has multiple clock sources (internal and external), a PLL, and prescalers that feed the CPU and peripherals. Every timing assumption in firmware depends on this clock tree. If you misconfigure the PLL or prescalers, your UART baud rate, PWM frequency, and ADC sample rate will all be wrong. The system clock (SYSCLK) feeds the CPU and buses, and peripherals derive their clocks from these buses. The discovery board can run from internal HSI or external HSE sources depending on configuration.

Deep Dive into the Concept

Clock configuration is the hidden backbone of deterministic firmware. The STM32F303 uses an internal 8 MHz RC oscillator (HSI) and can use an external crystal (HSE) for greater accuracy. The PLL multiplies and divides these sources to create SYSCLK, which then feeds the AHB bus (core + DMA) and the APB buses (peripherals). Prescalers allow you to slow down peripheral clocks to meet timing limits or reduce power.

In practice, clock configuration sets the timebase for nearly everything: SysTick uses the core clock to produce millisecond ticks; timers run off APB clocks (which may be multiplied when prescaled); UART baud rates are computed from bus clocks; ADC sampling time depends on ADC clock; and USB requires a precise 48 MHz clock domain. If any of these are wrong, your system will “sort of work” but fail under verification. A 5% clock error might look fine for LED blinking but will corrupt serial communication or sampling accuracy.

You must also understand clock domains. The core might run at 72 MHz while a peripheral runs at 36 MHz. Some timers have special behavior when the APB prescaler is not 1 (the timer clock may double). This means that your timer math must use the correct clock source. The safest approach is to read the clock configuration registers at runtime and compute derived frequencies, or use the HAL clock API to query actual rates.

Clock startup sequence matters too. Many systems boot from HSI and then switch to HSE+PLL after initialization. If you switch clocks without waiting for stabilization, the CPU can mis-execute instructions or peripherals can glitch. The correct pattern is: enable source, wait for ready, configure PLL, wait for lock, switch system clock. A reliable firmware includes a fallback in case the external oscillator fails.

Finally, timing domains influence jitter and latency. If your ADC is triggered by a timer but DMA transfers are delayed by bus contention, your sampling jitter increases. If you update PWM from an ISR but the ISR is delayed due to other interrupts, your output may jitter. Clock configuration is not just about frequency, but about determinism.

How This Fits in Projects

  • Project 1 validates the clock tree in real measurements.
  • Projects 3-6 depend on accurate timer and ADC clocks.
  • Project 7 measures interrupt latency, which is tied to core clock.

Definitions & Key Terms

  • HSI/HSE: Internal and external clock sources.
  • PLL: Phase-locked loop that multiplies clock frequency.
  • SYSCLK: System clock feeding CPU and buses.
  • APB/AHB prescaler: Divider that sets peripheral and core clock rates.

Mental Model Diagram

HSI/HSE -> PLL -> SYSCLK -> AHB (CPU/DMA)
                        \-> APB1 (peripherals)
                        \-> APB2 (timers/ADC)

How It Works (Step-by-Step, with Invariants and Failure Modes)

  1. Enable HSI or HSE oscillator.
  2. Wait for ready flag.
  3. Configure PLL multipliers/dividers.
  4. Enable PLL and wait for lock.
  5. Select PLL as SYSCLK source.

Invariant: Peripheral clocks are derived from SYSCLK and prescalers. Failure mode: Incorrect prescaler leads to wrong UART baud or ADC timing.

Minimal Concrete Example

// Pseudocode for clock switch
RCC->CR |= HSE_ON;
while (!(RCC->CR & HSE_RDY));
RCC->CFGR = PLL_CONFIG;
RCC->CR |= PLL_ON;
while (!(RCC->CR & PLL_RDY));
RCC->CFGR |= SYSCLK_PLL;

Common Misconceptions

  • “If the LED blinks, the clock is correct.” -> LEDs tolerate large timing errors.
  • “Timer frequency equals SYSCLK.” -> Timers often use APB clocks with multipliers.
  • “PLL lock means stable forever.” -> Temperature and power can cause drift.

Check-Your-Understanding Questions

  1. Why does UART baud rate depend on the clock tree?
  2. What happens if the PLL is misconfigured?
  3. Why might a timer run at double the APB frequency?

Check-Your-Understanding Answers

  1. UART baud dividers are computed from the peripheral clock.
  2. All timing outputs (UART, PWM, ADC) will be wrong.
  3. Some STM32 timers double the clock when APB prescaler != 1.

Real-World Applications

  • Motor control with precise PWM timing
  • Accurate sampling for sensor data acquisition
  • USB device operation (requires accurate 48 MHz clock)

Where You’ll Apply It

Projects 1, 3, 4, 5, 6, 7

References

  • STM32F303 clock and peripheral summary (clock sources, PLL, buses) citeturn0search0

Key Insight

Your firmware is only as accurate as your clock tree.

Summary

The clock tree determines frequency, jitter, and correctness for every peripheral.

Homework/Exercises to Practice the Concept

  1. Compute timer prescaler values for 1 kHz tick at 72 MHz.
  2. Sketch your clock tree with source and prescalers.
  3. Identify which peripherals depend on APB1 vs APB2.

Solutions to the Homework/Exercises

  1. Prescaler = (72 MHz / 1 kHz) - 1.
  2. HSI/HSE -> PLL -> SYSCLK -> AHB/APB.
  3. Use the reference manual bus mapping. citeturn0search1

Chapter 4: GPIO and Alternate Functions

Fundamentals

GPIO is more than input/output. Every STM32 pin can be configured for multiple roles: basic digital IO, analog input, or alternate functions for peripherals (UART, SPI, I2C, timers). You must plan pin usage early because multiple peripherals can conflict on the same pin. GPIO configuration also includes electrical properties: push-pull vs open-drain, pull-up vs pull-down, and speed/drive strength. These choices affect signal integrity, power, and reliability.

Deep Dive into the Concept

In the STM32F3, each pin has a mode register (input, output, alternate, analog), output type (push-pull or open-drain), speed setting, and pull-up/pull-down configuration. Alternate function selection maps the pin to a peripheral signal. A single pin might carry UART TX, a timer channel, or an ADC input, but only one at a time. If you choose the wrong alternate function or forget to set the mode, the peripheral will appear “dead.” This is one of the most common beginner errors.

Electrical configuration matters just as much. Push-pull outputs actively drive high and low; open-drain outputs can only pull low and require external pull-ups. I2C requires open-drain so multiple devices can share the bus. If you accidentally configure I2C pins as push-pull, you can short devices together. Pull-up/pull-down resistors define default logic states and help prevent floating inputs from causing noise or false interrupts.

Speed settings control slew rate and drive strength. High speed can cause ringing on long lines, while low speed reduces EMI and power. For LED control, low speed is enough; for SPI at high speeds, you may need high speed. The tradeoff is noise vs edge rate.

GPIO is also a debugging tool. A single GPIO pin toggled in an ISR can reveal timing and jitter when measured with a logic analyzer. Many projects in this guide use GPIO as a “truth probe” to verify timing behavior without trusting software timestamps.

Finally, on the STM32F3DISCOVERY, many pins are already connected to LEDs and sensors. These pins are accessible but may be shared. You must account for these connections in your pin plan to avoid conflicts.

How This Fits in Projects

  • Project 2 builds a full pin/alternate-function map.
  • Projects 3-4 use GPIO for LED and PWM outputs.
  • Projects 9-10 use GPIO for I2C/SPI pins and chip selects.

Definitions & Key Terms

  • Alternate Function (AF): Pin multiplexer selection for a peripheral signal.
  • Open-drain: Output mode that can only pull low; requires pull-up.
  • Pull-up/pull-down: Resistors that define default logic state.
  • Slew rate: Speed of output transition, tied to GPIO speed setting.

Mental Model Diagram

Pin PA9
  |-- GPIO Output
  |-- USART1_TX
  |-- TIM1_CH2
  |-- ADC1_IN2

Only ONE of these at a time.

How It Works (Step-by-Step, with Invariants and Failure Modes)

  1. Enable GPIO port clock.
  2. Set pin mode (input/output/AF/analog).
  3. Configure output type, speed, pull-ups.
  4. Select alternate function if needed.

Invariant: GPIO clock must be enabled, or writes are ignored. Failure mode: Wrong AF selection -> peripheral appears dead.

Minimal Concrete Example

// Configure PA9 as USART1 TX (alternate function)
GPIOA->MODER &= ~(3 << (9 * 2));
GPIOA->MODER |=  (2 << (9 * 2)); // AF mode
GPIOA->AFR[1] |= (7 << ((9 - 8) * 4)); // AF7 for USART1

Common Misconceptions

  • “Pins are dedicated.” -> They are multiplexed; you must choose.
  • “Default state is fine.” -> Floating inputs can cause random interrupts.
  • “I2C works as push-pull.” -> It does not; needs open-drain.

Check-Your-Understanding Questions

  1. Why must I2C pins be open-drain?
  2. What happens if you forget to enable the GPIO port clock?
  3. Why can GPIO speed affect signal quality?

Check-Your-Understanding Answers

  1. Multiple devices share the bus; open-drain prevents contention.
  2. Writes to GPIO registers are ignored; pin remains default.
  3. Faster edges create ringing and EMI on long traces.

Real-World Applications

  • Configuring UART pins for debugging
  • Mapping PWM outputs for motor control
  • Setting I2C/SPI pins for sensor integration

Where You’ll Apply It

Projects 2-4, 9-12, 15-16

References

  • STM32F3DISCOVERY board features and headers (pin access) citeturn3view0

Key Insight

GPIO is the hardware contract between your firmware and the physical world.

Summary

Correct pin configuration is required before any peripheral can work.

Homework/Exercises to Practice the Concept

  1. Identify three alternate functions on a single pin and explain tradeoffs.
  2. Sketch a pin map for UART, I2C, and PWM on the board.
  3. Measure a GPIO toggle with a logic analyzer (or LED + stopwatch).

Solutions to the Homework/Exercises

  1. Example: PA9 could be GPIO, USART1_TX, or TIM1_CH2; only one at a time.
  2. Choose pins that are exposed on headers and not used by sensors.
  3. A toggled pin yields measurable period (frequency = 1/period).

Chapter 5: Timers, PWM, and Capture/Encoder

Fundamentals

Timers are the heartbeat of embedded systems. They create precise timebases for periodic interrupts, PWM outputs, and input capture. The STM32F303 includes multiple timer types: basic timers for timekeeping, general-purpose timers for capture/compare, and advanced timers for motor control with dead-time and emergency stop. Timers allow you to build deterministic behavior without relying on blocking delays.

Deep Dive into the Concept

Timers are counter peripherals driven by a clock derived from the APB bus. The counter increments (or decrements) at a known rate, then triggers events when it reaches a compare value or overflows. In PWM mode, a compare register defines how long the output stays high relative to the period. In input capture mode, the timer captures the counter value when an external signal edge arrives, allowing you to measure pulse widths or frequencies. Encoder mode uses two quadrature signals to increment/decrement a counter based on direction.

The key to timer configuration is math: period = (prescaler + 1) * (auto-reload + 1) / timer_clock. If you want 1 kHz, you compute prescaler and ARR from the known timer clock. Mistakes here cause systematic timing errors. Another subtlety: if APB prescaler is not 1, some STM32 timers get a doubled clock. This is why your clock tree and timer math must match.

Timers also generate interrupts on update events. The interrupt latency depends on NVIC priority, current execution context, and flash wait states. For many control loops, you want consistent jitter and small latency. If you overload the CPU or put too much in the ISR, you can miss timer deadlines or cause PWM jitter.

Advanced timers add features such as dead-time insertion and break inputs, critical for motor control. Dead-time ensures that both high-side and low-side MOSFETs are not on at the same time. Even if you do not use advanced features, understanding them helps when you move to real motor drives.

Finally, timers are essential for accurate time measurement. For example, using a free-running timer as a timestamp source lets you measure ISR latency by capturing the counter value at entry and exit. This is more accurate than using software delays.

How This Fits in Projects

  • Project 3 uses timer interrupts to drive LED sequences.
  • Project 4 uses PWM output to control LED brightness or motor speed.
  • Project 11 uses encoder mode to read quadrature signals.
  • Project 7 measures interrupt latency using timer capture.

Definitions & Key Terms

  • Prescaler (PSC): Divides timer clock to set counting speed.
  • Auto-Reload (ARR): Counter top value; defines period.
  • PWM: Pulse-width modulation for analog-like control.
  • Input Capture: Timer captures counter value on external edges.
  • Encoder Mode: Timer counts quadrature signals for position/speed.

Mental Model Diagram

Timer Clock -> Counter -> Compare Match -> Output / Interrupt
                     |-> Capture Register (on input edge)

How It Works (Step-by-Step, with Invariants and Failure Modes)

  1. Enable timer clock in RCC.
  2. Configure PSC and ARR.
  3. Configure mode (PWM, capture, encoder).
  4. Enable timer and interrupts if needed.

Invariant: Timer clock is derived from APB; if APB changes, timer changes. Failure mode: Wrong prescaler leads to wrong PWM frequency or capture errors.

Minimal Concrete Example

// Pseudocode: 1 kHz timer interrupt
TIM2->PSC = 7200 - 1; // 72 MHz / 7200 = 10 kHz
TIM2->ARR = 10 - 1;   // 10 kHz / 10 = 1 kHz
TIM2->DIER |= TIM_DIER_UIE; // update interrupt
TIM2->CR1 |= TIM_CR1_CEN;

Common Misconceptions

  • “Delays are fine for timing.” -> Blocking delays destroy determinism.
  • “PWM frequency doesn’t matter.” -> It affects motor response and LED flicker.
  • “Capture is the same as polling.” -> Capture gives precise timestamps.

Check-Your-Understanding Questions

  1. What parameters determine timer period?
  2. How does PWM duty relate to compare value?
  3. Why is input capture better than polling for pulse measurement?

Check-Your-Understanding Answers

  1. Prescaler, auto-reload, and timer clock.
  2. Duty = compare / period.
  3. Capture stores the timestamp of the edge in hardware.

Real-World Applications

  • Motor control and LED dimming
  • Measuring tachometer signals
  • Precise periodic sampling

Where You’ll Apply It

Projects 3, 4, 7, 11, 16

References

  • STM32F303 timer capabilities (general/advanced timers) citeturn0search0

Key Insight

Timers are your hardware scheduler; use them instead of delays.

Summary

Deterministic embedded systems start with correct timer configuration and measurement.

Homework/Exercises to Practice the Concept

  1. Compute settings for 20 kHz PWM with 10-bit resolution.
  2. Design a timer-based schedule with 1 ms tick and 100 ms task.
  3. Draw a quadrature signal and explain how the timer counts it.

Solutions to the Homework/Exercises

  1. Choose timer clock and ARR for 1024 counts, then compute PSC.
  2. Use a 1 kHz timer interrupt, increment a counter, trigger task at 100.
  3. A leads B -> increment; B leads A -> decrement.

Chapter 6: Mixed-Signal Peripherals (ADC, DAC, Comparators, Op-Amps)

Fundamentals

The STM32F303 is built for mixed-signal tasks. It includes fast 12-bit ADCs (up to 5 Msps), DAC channels, comparators, and op-amps. This allows you to sample real-world analog signals, convert them to digital data, process them, and output analog-like signals again. citeturn0search0 Understanding sampling, quantization, and reference voltage is critical for trustworthy data.

Deep Dive into the Concept

Analog-to-digital conversion (ADC) is the process of sampling a voltage at discrete times and converting it into a digital number. The STM32F303 provides multiple ADCs and supports different resolutions (12/10/8/6 bits). Higher resolution means smaller voltage steps but may reduce speed. The ADC uses a sample-and-hold circuit; the input signal must be stable during sampling. This is why you configure sampling time based on source impedance. If your source is high impedance and sampling time is too short, the ADC will read incorrect values.

Sampling theory matters. Nyquist says you must sample at least twice the highest signal frequency to avoid aliasing. In real systems, you often sample much higher and then filter or decimate. You also need to consider noise: the least significant bit (LSB) is the smallest resolvable voltage step (Vref / 2^N). If noise exceeds 1 LSB, your data will jitter. Averaging or oversampling can reduce noise, but it costs time and CPU.

The DAC converts digital values into analog voltages. The output is a staircase waveform; the smoothness depends on update rate and filtering. DAC output can be used for waveform generation, bias control, or feedback. However, the output has limited drive capability and may require buffering with an op-amp for external loads.

The STM32F303 also includes comparators and op-amps. Comparators allow fast threshold detection without CPU involvement (e.g., zero-cross detection). Op-amps can act as programmable gain amplifiers (PGA) to scale sensor signals before ADC. These features let you build analog signal chains without extra external ICs, which is powerful but also risky: you must respect voltage ranges and timing constraints.

A real mixed-signal system combines these elements: a sensor signal passes through filtering and amplification, is sampled by ADC at a controlled rate, moved via DMA, processed by CPU, and then output via PWM or DAC. Each step has error sources: offset, gain error, timing jitter, quantization noise. A good engineer quantifies these errors and builds margin.

How This Fits in Projects

  • Project 5 samples analog sensors and logs data.
  • Project 6 generates DAC waveforms.
  • Project 8 uses DMA to sustain ADC streaming.
  • Project 15 uses sensor data for fusion.

Definitions & Key Terms

  • Sampling time: Duration the ADC input is sampled before conversion.
  • Quantization: Mapping continuous voltage to discrete digital steps.
  • Vref: Reference voltage for ADC/DAC conversion range.
  • LSB: Smallest voltage step (Vref / 2^N).

Mental Model Diagram

Analog Signal -> [Sample & Hold] -> [Quantize] -> Digital Value
Digital Value -> [DAC] -> Staircase Voltage -> (Optional Filter) -> Output

How It Works (Step-by-Step, with Invariants and Failure Modes)

  1. Configure ADC clock, resolution, and sampling time.
  2. Trigger ADC via software or timer.
  3. ADC samples input and converts to digital value.
  4. DMA or CPU reads value into memory.
  5. DAC outputs digital values as analog voltages.

Invariant: Input voltage must be within ADC reference range. Failure mode: Too-short sampling time for high-impedance source -> incorrect readings.

Minimal Concrete Example

// Pseudocode: start ADC conversion and read result
ADC1->CR |= ADC_CR_ADSTART;
while (!(ADC1->ISR & ADC_ISR_EOC));
uint16_t val = ADC1->DR;

Common Misconceptions

  • “More bits always means better.” -> Noise can overwhelm LSBs.
  • “DAC output is smooth.” -> It’s a staircase unless filtered.
  • “Sampling at any rate is fine.” -> Aliasing can corrupt signals.

Check-Your-Understanding Questions

  1. How does sampling time affect accuracy?
  2. What does 12-bit ADC resolution mean in voltage steps?
  3. Why is Vref critical for ADC accuracy?

Check-Your-Understanding Answers

  1. Too short sampling prevents capacitor from charging to true signal value.
  2. 2^12 = 4096 steps; step size = Vref / 4096.
  3. Vref defines the full-scale range; drift changes measurements.

Real-World Applications

  • Sensor data acquisition (temperature, light, pressure)
  • Motor control feedback loops
  • Audio or waveform generation

Where You’ll Apply It

Projects 5, 6, 8, 15, 16

References

  • STM32F303 analog peripherals (ADCs, DACs, comparators, op-amps) citeturn0search0

Key Insight

Trustworthy sensor data requires correct sampling, timing, and analog front-end design.

Summary

Mixed-signal peripherals are powerful but only if you respect sampling theory and signal integrity.

Homework/Exercises to Practice the Concept

  1. Compute the LSB size for a 12-bit ADC with 3.3 V reference.
  2. Choose a sampling rate for a 50 Hz sensor signal and justify it.
  3. Design a simple DAC sine table with 64 samples.

Solutions to the Homework/Exercises

  1. 3.3 V / 4096 ~ 0.000806 V (0.806 mV).
  2. Sample at 200 Hz or higher for margin (Nyquist).
  3. Use a sine lookup table with values scaled to 0-4095.

Chapter 7: Interrupts, NVIC, and Real-Time Behavior

Fundamentals

Interrupts let the MCU react to events immediately instead of polling. The NVIC handles priority and dispatch. Real-time behavior depends on interrupt latency, priority configuration, and how much work you do inside ISRs. Understanding interrupts is essential for reliable scheduling and responsiveness.

Deep Dive into the Concept

The Cortex-M interrupt system uses the NVIC to prioritize and dispatch events. Each interrupt has a priority level, and lower numerical values usually represent higher priority. When an interrupt fires, the CPU pushes context onto the stack, jumps to the ISR, and executes it. When it returns, the previous context is restored. This adds overhead and latency. If a higher-priority interrupt fires while a lower-priority ISR is running, it can preempt. This is good for real-time response but can starve low-priority tasks.

Latency is the time between an event and the start of its ISR. It depends on current CPU state, flash wait states, bus contention, and other interrupts. If you do too much work in an ISR, you increase latency for everything else. The correct pattern is to keep ISRs short: capture data, set flags, and let the main loop or a lower-priority task do the heavy work. DMA can reduce ISR load by moving data automatically.

Shared data between ISRs and main code must be protected. Use volatile qualifiers, atomic operations, or critical sections. Without protection, you can read half-updated values. This is one of the most common bugs in embedded systems.

Interrupt priority design is also a systems problem. You must decide what is truly time-critical. For example, an ADC sampling ISR might need higher priority than a UART RX ISR if you cannot miss samples. But if UART RX overruns, you lose logs. There is no free lunch; you must choose based on system requirements.

A good engineer measures interrupt latency and jitter. Project 7 forces you to do this. Measuring it with a timer is the only way to know whether your system meets deadlines.

How This Fits in Projects

  • Project 3 relies on timer interrupts for scheduling.
  • Project 7 profiles interrupt latency under load.
  • Project 8 uses DMA interrupts for buffer management.

Definitions & Key Terms

  • ISR: Interrupt Service Routine.
  • Latency: Time between event and ISR execution.
  • Priority: Ordering rule for interrupt preemption.
  • Critical section: Code region protected from interrupts.

Mental Model Diagram

Event -> NVIC -> ISR -> Flag -> Main Loop
            ^
            |
     Priority + Latency

How It Works (Step-by-Step, with Invariants and Failure Modes)

  1. Peripheral triggers interrupt.
  2. NVIC checks priority and pending state.
  3. CPU saves context and jumps to ISR.
  4. ISR does minimal work and returns.

Invariant: ISR must not block or run too long. Failure mode: Long ISR delays other interrupts, causing missed events.

Minimal Concrete Example

volatile int flag = 0;
void TIM2_IRQHandler(void) {
    TIM2->SR &= ~TIM_SR_UIF; // clear flag
    flag = 1; // signal main loop
}

int main(void) {
    while (1) {
        if (flag) { flag = 0; do_work(); }
    }
}

Common Misconceptions

  • “ISR can do everything.” -> It should be minimal and fast.
  • “Priorities don’t matter.” -> They define real-time behavior.
  • “Volatile fixes all concurrency issues.” -> It does not provide atomicity.

Check-Your-Understanding Questions

  1. Why must ISRs be short?
  2. What happens if two interrupts fire at the same time?
  3. How do you protect shared data?

Check-Your-Understanding Answers

  1. Long ISRs delay other interrupts and increase latency.
  2. The higher priority interrupt runs first; the other is pending.
  3. Use volatile + critical sections or atomic operations.

Real-World Applications

  • Sensor sampling loops
  • Motor control feedback
  • Communication stacks

Where You’ll Apply It

Projects 3, 7, 8, 12, 16

References

  • ARM Cortex-M interrupt concepts (see programming manual and reference manual) citeturn0search1

Key Insight

Real-time performance is about predictable interrupt latency, not just fast code.

Summary

Interrupt design is a scheduling problem; treat it like one.

Homework/Exercises to Practice the Concept

  1. Measure ISR latency with a GPIO toggle.
  2. Design an interrupt priority scheme for ADC and UART.
  3. Identify shared variables in your project and protect them.

Solutions to the Homework/Exercises

  1. Toggle a GPIO at ISR entry and measure with logic analyzer.
  2. Give ADC higher priority if missing samples is worse than losing UART logs.
  3. Use volatile and disable interrupts briefly around updates.

Chapter 8: DMA and Data Streaming

Fundamentals

DMA lets peripherals move data to memory without CPU intervention. It is essential for high-throughput ADC sampling, UART/SPI transfers, and low-jitter pipelines. Understanding DMA modes (normal, circular) and buffer management is key for continuous data capture.

Deep Dive into the Concept

DMA is a hardware engine that reads from a peripheral data register and writes directly to memory (or vice versa). You configure a source address, destination address, transfer length, and mode. Once enabled, DMA moves data on each peripheral request. The CPU is freed to do other work or sleep. For high-speed ADC sampling, DMA is the only practical way to avoid data loss.

DMA supports circular mode, which automatically wraps the transfer buffer and generates half-transfer and full-transfer interrupts. This enables double-buffering: while DMA fills the second half of the buffer, the CPU processes the first half. This pattern is critical for streaming data with bounded latency.

The tricky part is synchronization. If the CPU processes too slowly, it will fall behind and the DMA will overwrite unprocessed data. You must compute buffer size based on sampling rate and processing time, then design your processing loop to meet deadlines. This is a real-time scheduling problem.

DMA also has constraints: not all peripherals support it, and some peripherals share DMA channels. If you configure two peripherals for the same channel, they can conflict. The reference manual provides the DMA mapping table (which is why you must read it). citeturn0search1

Finally, DMA can transfer between memory and peripherals for SPI or UART, improving throughput. But you must understand data alignment and memory boundaries. For example, using 16-bit data width with a 12-bit ADC can cause confusion if you interpret the buffer incorrectly. Always document the buffer format.

How This Fits in Projects

  • Project 8 builds a DMA-driven ADC ring buffer.
  • Project 6 can use DMA for DAC waveform output.
  • Project 10 can use DMA to boost SPI display throughput.

Definitions & Key Terms

  • DMA channel: Logical DMA stream assigned to a peripheral.
  • Circular mode: DMA wraps buffer and continues indefinitely.
  • Half-transfer interrupt: Trigger when half buffer is filled.
  • Double-buffering: Two alternating buffers for continuous data.

Mental Model Diagram

ADC -> DMA -> [Half Buffer | Half Buffer]
             ^            ^
             |            |
         HT IRQ       TC IRQ

How It Works (Step-by-Step, with Invariants and Failure Modes)

  1. Configure DMA channel (source, destination, length).
  2. Enable DMA requests in peripheral.
  3. Start peripheral; DMA transfers data to memory.
  4. Handle half/full transfer interrupts.

Invariant: CPU processing must be faster than buffer fill rate. Failure mode: Overrun -> data loss or corruption.

Minimal Concrete Example

// Pseudocode: configure DMA for ADC buffer
DMA1_Channel1->CPAR = (uint32_t)&ADC1->DR;
DMA1_Channel1->CMAR = (uint32_t)adc_buffer;
DMA1_Channel1->CNDTR = BUFFER_SIZE;
DMA1_Channel1->CCR = DMA_CCR_CIRC | DMA_CCR_MINC | DMA_CCR_EN;

Common Misconceptions

  • “DMA removes all CPU work.” -> You still must process buffers.
  • “Bigger buffer is always better.” -> It increases latency.
  • “DMA data is always aligned.” -> You must match data width.

Check-Your-Understanding Questions

  1. Why is circular mode useful for continuous sampling?
  2. What happens if CPU processing is too slow?
  3. How do you choose buffer size?

Check-Your-Understanding Answers

  1. DMA wraps automatically, allowing continuous capture.
  2. DMA overwrites data before it’s processed.
  3. Based on sample rate and maximum processing time.

Real-World Applications

  • Audio capture
  • Motor control feedback
  • Sensor fusion pipelines

Where You’ll Apply It

Projects 6, 8, 10, 16

References

  • STM32F303 DMA controller and peripheral list citeturn0search0

Key Insight

DMA turns the MCU into a streaming data engine, but you must meet the schedule.

Summary

DMA is required for reliable high-rate sampling and transfer.

Homework/Exercises to Practice the Concept

  1. Compute buffer size for 10 kHz sampling with 50 ms processing.
  2. Design a double-buffer processing loop.
  3. Identify which peripherals share DMA channels.

Solutions to the Homework/Exercises

  1. 10 kHz * 0.05 s = 500 samples minimum per buffer half.
  2. Process first half on HT interrupt, second half on TC interrupt.
  3. Use the DMA mapping table in the reference manual. citeturn0search1

Chapter 9: Serial Communications (I2C, SPI, UART, USB, CAN)

Fundamentals

Most embedded systems communicate with sensors and other chips using serial buses. STM32F303 provides I2C, SPI, USART/UART, USB FS, and CAN interfaces. citeturn0search0 Each bus has different electrical and protocol rules: I2C is open-drain and multi-drop; SPI is full-duplex with chip select; UART is asynchronous point-to-point; USB is packetized and requires strict timing. Understanding these differences is essential for robust integration.

Deep Dive into the Concept

I2C uses two open-drain lines (SCL/SDA) with pull-up resistors. Devices share the bus, and each has an address. Transactions start with a START condition and end with a STOP. If a device NACKs, you must handle errors gracefully. Bus timing depends on pull-up strength and bus capacitance; long wires can break I2C. The STM32F303 supports I2C Fast Mode Plus, which increases speed but tightens electrical requirements. citeturn0search2

SPI uses separate lines for clock (SCK), data in/out (MOSI/MISO), and chip select (CS). It is fast and simple but lacks addressing, so each device needs a chip select. SPI modes (CPOL/CPHA) must match the peripheral. A mismatch yields corrupted data.

UART is asynchronous serial communication. It depends on precise baud rate generation from the clock tree. If baud rates are off by more than a few percent, framing errors occur. UART is widely used for debugging because it is simple and reliable when configured correctly.

USB FS is supported on the STM32F3DISCOVERY board. USB requires a 48 MHz clock domain and complex packet handling. It is powerful for host communication but requires more software. CAN provides robust differential communication for automotive/industrial networks, but you must understand message IDs and arbitration.

The key integration principle: always start with a minimal transaction (read device ID register, send a known command). Verify wiring, timing, and protocol at the simplest level before building full drivers. Then build a consistent error-handling strategy: retry on NACK, timeouts, and log errors. Many real-world bugs are bus errors, not logic errors.

How This Fits in Projects

  • Project 9 uses I2C to integrate sensors.
  • Project 10 uses SPI for a display or LED matrix.
  • Project 12 uses UART for diagnostics.
  • Project 16 can use multiple buses simultaneously.

Definitions & Key Terms

  • START/STOP: I2C bus transaction boundaries.
  • CPOL/CPHA: SPI clock polarity and phase.
  • Baud rate: UART data rate derived from clock.
  • Arbitration: CAN/I2C multi-master bus conflict resolution.

Mental Model Diagram

I2C:  SDA/SCL (open-drain, shared bus)
SPI:  SCK + MOSI + MISO + CS (per-device)
UART: TX/RX (point-to-point)

How It Works (Step-by-Step, with Invariants and Failure Modes)

  1. Configure GPIO pins for alternate functions.
  2. Configure peripheral timing (baud, clock, mode).
  3. Initiate transaction (START, CS assert, etc.).
  4. Handle errors (NACK, framing, timeouts).

Invariant: Pins must be in correct electrical mode (open-drain for I2C). Failure mode: Wrong SPI mode yields garbage data.

Minimal Concrete Example

// Pseudocode: I2C read of WHO_AM_I register
I2C_Start();
I2C_Write(DEVICE_ADDR | WRITE);
I2C_Write(WHO_AM_I_REG);
I2C_Start();
I2C_Write(DEVICE_ADDR | READ);
uint8_t id = I2C_Read_NACK();
I2C_Stop();

Common Misconceptions

  • “I2C always works at 400 kHz.” -> Pull-ups and wiring limit speed.
  • “SPI has no errors.” -> Wrong mode or CS timing corrupts data.
  • “UART is tolerant to any clock error.” -> Too much error causes framing failures.

Check-Your-Understanding Questions

  1. Why does I2C require pull-up resistors?
  2. What do CPOL and CPHA control in SPI?
  3. Why does UART depend on accurate clocks?

Check-Your-Understanding Answers

  1. I2C is open-drain; pull-ups define logic high.
  2. They set clock idle level and sampling edge.
  3. UART timing depends on the derived baud rate.

Real-World Applications

  • Sensor integration and calibration
  • Display updates
  • Debugging consoles and telemetry

Where You’ll Apply It

Projects 9, 10, 12, 15, 16

References

  • STM32F303 communication interfaces (I2C, SPI, UART, CAN, USB) citeturn0search0
  • STM32F3DISCOVERY board includes USB and MEMS sensors citeturn3view0

Key Insight

Communication is a system of electrical, timing, and protocol constraints.

Summary

Pick the right bus, configure it correctly, and validate with minimal transactions first.

Homework/Exercises to Practice the Concept

  1. Draw an I2C transaction for reading two bytes.
  2. Define SPI timing for a device using CPOL=1, CPHA=1.
  3. Calculate UART baud divider for 72 MHz at 115200 baud.

Solutions to the Homework/Exercises

  1. START -> address+W -> reg -> RESTART -> address+R -> byte1 -> byte2 -> STOP.
  2. Clock idle high, sample on second edge.
  3. Divider ~ 72,000,000 / 115200 = 625 (approx; depends on UART oversampling).

Chapter 10: Power Modes and Reliability (Watchdogs, Reset Causes)

Fundamentals

Embedded systems live under power constraints and must recover from faults. STM32F303 supports low-power modes (Sleep, Stop, Standby) and includes watchdogs. Proper power management extends battery life, while watchdogs ensure recovery when firmware hangs.

Deep Dive into the Concept

Power management is not just about lowering clock speeds; it is about shutting down unused peripherals, using low-power modes, and waking correctly. Sleep mode stops the CPU but leaves peripherals running. Stop mode reduces power by stopping clocks and more aggressively gating peripherals, while Standby is the deepest mode and often causes a reset on wake. Each mode has different wake sources and tradeoffs. If you enter Stop mode without properly saving state, you may lose configuration and require reinitialization on wake.

The STM32F303 includes independent and window watchdogs. The watchdog is a timer that must be periodically refreshed; if not, the MCU resets. This protects against firmware hangs or deadlocks. The window watchdog adds a timing window to prevent both early and late refresh, catching certain failure modes.

Reset cause analysis is crucial for reliability. On boot, you should read reset flags to determine whether the MCU reset due to power-on, watchdog, software reset, or brown-out. Logging this information helps diagnose failures in the field.

Power management also affects analog accuracy. In low-power modes, some analog blocks shut down or lose calibration. After wake-up, you may need to re-run calibration sequences and wait for stabilization. Similarly, clock sources may switch or restart, changing timing behavior.

Reliability design means thinking in failure modes: what if a sensor read hangs, what if DMA stops, what if the system enters an unintended sleep? Projects 13 and 14 are about making these scenarios visible and recoverable.

How This Fits in Projects

  • Project 13 explores power modes and wake sources.
  • Project 14 implements watchdog recovery.
  • Final project integrates fault recovery in a real system.

Definitions & Key Terms

  • Sleep/Stop/Standby: Low-power modes with different power and state retention.
  • Watchdog: Timer that resets system if not refreshed.
  • Reset flags: Registers indicating why the MCU reset.
  • Brown-out: Reset caused by low supply voltage.

Mental Model Diagram

Active -> Sleep -> Stop -> Standby
   ^        |        |        |
   +--------+--------+--------+
         Wake sources (RTC, GPIO, etc.)

How It Works (Step-by-Step, with Invariants and Failure Modes)

  1. Save state and configure wake source.
  2. Enter low-power mode.
  3. Wake on event, restore clocks/peripherals.
  4. Resume normal operation.

Invariant: Clocks and peripherals may need reinit after wake. Failure mode: Wake source misconfigured -> system never wakes.

Minimal Concrete Example

// Pseudocode: enter sleep
__WFI(); // wait for interrupt

Common Misconceptions

  • “Sleep mode keeps everything.” -> Some peripherals stop or reset.
  • “Watchdog is only for safety.” -> It’s also for reliability and recovery.
  • “Power measurement is optional.” -> Without measurement, power claims are guesses.

Check-Your-Understanding Questions

  1. What is the difference between Stop and Standby?
  2. Why must you log reset causes?
  3. What happens if you refresh the watchdog too late?

Check-Your-Understanding Answers

  1. Standby is deeper and often resets the MCU; Stop retains more state.
  2. It helps diagnose failures and determine recovery flow.
  3. The MCU resets because watchdog expired.

Real-World Applications

  • Battery-powered sensors
  • Consumer electronics
  • Industrial controllers with reliability requirements

Where You’ll Apply It

Projects 13, 14, 16

References

  • STM32F303 power modes and watchdog features citeturn0search0

Key Insight

Power and reliability are design constraints, not afterthoughts.

Summary

If you cannot wake reliably or recover from faults, your system is not complete.

Homework/Exercises to Practice the Concept

  1. Estimate battery life for a duty-cycled system.
  2. List which peripherals must be reinitialized after Stop mode.
  3. Design a watchdog refresh strategy.

Solutions to the Homework/Exercises

  1. Average current = (active % * active current) + (sleep % * sleep current).
  2. Clocks, timers, and ADCs often need reinit.
  3. Refresh in a periodic task only if system is healthy.

Chapter 11: Sensor Integration and Fusion (On-Board MEMS)

Fundamentals

STM32F3DISCOVERY includes MEMS sensors: a 3-axis gyroscope and a combined 3-axis accelerometer + 3-axis magnetometer. These sensors communicate over I2C/SPI and provide raw measurements that must be scaled and calibrated before use. Fusing these sensors yields orientation and motion estimates.

Deep Dive into the Concept

The board integrates an L3GD20 3-axis gyroscope and an LSM303DLHC accelerometer/magnetometer. The gyro provides angular rate measurements in degrees per second, while the accelerometer measures linear acceleration and the magnetometer measures magnetic field. These sensors expose registers accessed via I2C or SPI. Each device has configuration registers for output data rate, full-scale range, and filtering. The L3GD20 supports full-scale ranges of 250/500/2000 dps, while the LSM303DLHC supports accel ranges of +/-2g/+/-4g/+/-8g/+/-16g and magnetic ranges up to +/-8.1 gauss. citeturn1search1turn1search0

Raw sensor outputs are not directly usable. You must apply scale factors to convert raw counts into physical units (g, dps, gauss). You must also calibrate offset and scale errors. For example, an accelerometer at rest should read 1g on one axis and 0g on others; any bias indicates offset error. Magnetometers require calibration to remove hard-iron and soft-iron distortions caused by nearby metals and magnetic fields. A simple calibration method is to collect data while rotating the board and fit an ellipsoid.

Sensor fusion combines data to produce stable orientation estimates. A gyroscope is accurate short-term but drifts over time; an accelerometer provides absolute reference for tilt but is noisy; a magnetometer provides heading reference but is sensitive to disturbances. A complementary filter combines high-frequency gyro data with low-frequency accel/mag corrections. A simple fusion algorithm is often enough for many applications.

Timing matters. If you sample gyro and accel at different times, the fusion result is inaccurate. This is why synchronized sampling or timestamped data is important. In practice, you configure sensors to output data at a fixed rate, then read them in a timer-driven loop. You should also log timestamps for each sample.

Finally, sensor integration is a systems problem: correct wiring, correct bus configuration, correct scaling, correct calibration, and correct timing. Many bugs appear as “wrong physics” rather than code errors.

How This Fits in Projects

  • Project 9 integrates I2C sensor drivers.
  • Project 15 builds a sensor fusion dashboard.
  • Final project uses sensor data for control decisions.

Definitions & Key Terms

  • Bias/Offset: Constant error added to sensor output.
  • Scale factor: Counts-to-units conversion constant.
  • Complementary filter: Simple fusion method combining high/low frequency data.
  • Hard-iron / Soft-iron: Magnetic distortions due to nearby materials.

Mental Model Diagram

Gyro (fast, drifts) ---->
                          \  Fusion -> Orientation
Accel (slow, absolute) -->/
Mag (heading reference) --/

How It Works (Step-by-Step, with Invariants and Failure Modes)

  1. Configure sensor ODR and scale.
  2. Read raw data registers.
  3. Convert counts to units.
  4. Calibrate offsets and scale.
  5. Fuse data with filter.

Invariant: Sampling rate and scale factors must be known. Failure mode: Unsynchronized samples cause unstable fusion output.

Minimal Concrete Example

// Pseudocode: scale raw accelerometer counts
float accel_g = (raw_accel / 16384.0f); // example for +/-2g

Common Misconceptions

  • “Raw data is accurate.” -> It always needs calibration.
  • “Gyro alone gives orientation.” -> It drifts over time.
  • “Magnetometer is always stable.” -> It is disturbed by nearby metals.

Check-Your-Understanding Questions

  1. Why does gyro drift over time?
  2. What is the role of the magnetometer in fusion?
  3. Why must sensor samples be time-aligned?

Check-Your-Understanding Answers

  1. Bias errors integrate into large angle errors.
  2. It provides absolute heading reference.
  3. Misalignment introduces phase errors and incorrect estimates.

Real-World Applications

  • Drones and robotics
  • Motion-controlled interfaces
  • Orientation tracking devices

Where You’ll Apply It

Projects 9, 15, 16

References

  • STM32F3DISCOVERY sensors (gyro + accel/mag) citeturn3view0
  • L3GD20 features and ranges citeturn1search1
  • LSM303DLHC features and ranges citeturn1search0

Key Insight

Sensor fusion is about managing error sources, not just averaging numbers.

Summary

Reliable motion data requires calibration, synchronization, and simple filtering.

Homework/Exercises to Practice the Concept

  1. Log 100 samples from the accelerometer and compute bias.
  2. Plot gyro drift over 60 seconds and estimate drift rate.
  3. Implement a basic complementary filter in pseudocode.

Solutions to the Homework/Exercises

  1. Average samples at rest; subtract from future readings.
  2. Integrate gyro rate and compare to known stationary orientation.
  3. fused = alpha(gyro_integrated) + (1-alpha)(accel_angle).

Glossary (High-Signal)

  • ADC: Converts analog voltage to a digital number.
  • DAC: Converts digital number to analog voltage.
  • DMA: Hardware engine that moves data without CPU intervention.
  • GPIO: General Purpose Input/Output pins.
  • NVIC: Interrupt controller for Cortex-M.
  • PWM: Pulse-width modulation for analog-like control.
  • SysTick: Core timer for periodic interrupts.
  • Vector Table: Table of interrupt handler addresses.

Why STM32F3DISCOVERY Matters

The Modern Problem It Solves

Embedded systems now power everything from sensors to appliances to robotics. The STM32F3DISCOVERY board provides a low-cost path to learn real mixed-signal embedded design with on-board sensors, debugging, and analog peripherals. It is a microcontroller class platform capable of the timing, sampling, and control tasks that define real embedded products.

Real-world impact (with sources and year):

  • Arm reported partners have shipped more than a quarter of a trillion Arm-based chips (250 billion) by 2023, showing the massive footprint of Arm MCUs and SoCs. citeturn5search0
  • Arm reported a record 4.4 billion Cortex-M processors shipped in a single quarter (2020), highlighting the scale of embedded devices. citeturn5search1
  • STMicroelectronics announced in 2015 it had shipped over one billion STM32 microcontrollers, demonstrating STM32’s adoption in embedded systems. citeturn5search2

These numbers show why learning an STM32 mixed-signal MCU translates directly to the skills needed in high-volume real-world products.

OLD APPROACH (toy MCU)             NEW APPROACH (mixed-signal MCU)
+-----------------------+          +------------------------------+
| Simple IO + delays    |          | Timers + ADC + DMA + NVIC    |
| Limited analog        |          | Deterministic control loops  |
| Minimal debug         |          | Real debugging + logging     |
+-----------------------+          +------------------------------+

Context & Evolution (Optional)

STM32 Discovery boards made professional-grade ARM microcontrollers accessible to learners. The F3 family emphasized mixed-signal features, pushing learning beyond basic digital IO into real-time sampling and control. citeturn3view0turn0search0


Concept Summary Table

Concept Cluster What You Need to Internalize
Board anatomy & MCU architecture How buses, memory, and peripherals interact on STM32F303.
Boot, reset, and debug Vector table, boot modes, and how to recover from failures.
Clock tree & timing All timing depends on clock sources and prescalers.
GPIO & alternate functions Pin multiplexing and electrical configuration define capability.
Timers/PWM/capture Hardware timing for control, measurement, and scheduling.
Mixed-signal peripherals Sampling theory, ADC/DAC behavior, and analog accuracy.
Interrupts & NVIC Latency, priority, and concurrency tradeoffs.
DMA & data streaming High-throughput data movement without CPU bottlenecks.
Serial communications I2C/SPI/UART/USB/CAN differences and error handling.
Power & reliability Low-power modes, watchdogs, and reset cause analysis.
Sensor integration & fusion Calibration, synchronization, and stable motion outputs.

Project-to-Concept Map

Project What It Builds Primer Chapters It Uses
Project 1: Board Bring-Up and Clock Audit Verified clocks and timing measurement 1, 2, 3
Project 2: GPIO Map and Alternate-Function Explorer Pin capability map + verification 1, 4
Project 3: Timer-Driven LED Sequencer Deterministic timer scheduling 3, 5, 7
Project 4: PWM Motor/LED Controller Hardware PWM + duty mapping 3, 5
Project 5: ADC Sensor Sampler + Logging Stable analog sampling 3, 6, 7
Project 6: DAC Waveform Generator Analog output synthesis 3, 6, 8
Project 7: Interrupt Latency Profiler Latency and priority analysis 3, 7
Project 8: DMA-Based ADC Ring Buffer Streaming acquisition 6, 8
Project 9: I2C Sensor Driver + Calibration Bus integration + scaling 4, 9, 11
Project 10: SPI Display/LED Matrix High-speed SPI + buffering 4, 8, 9
Project 11: Quadrature Encoder Reader Encoder mode + capture 5, 7
Project 12: UART Command Console Debug observability 2, 9
Project 13: Power Mode Explorer Low-power + wake sources 3, 10
Project 14: Fault Injection + Watchdog Recovery flow 2, 10
Project 15: On-Board Sensor Fusion Dashboard Multi-sensor fusion 6, 9, 11
Final Project: Environmental Monitor + Actuator Control Full system integration 1-11

Deep Dive Reading by Concept

Fundamentals & Architecture

Concept Book & Chapter Why This Matters
MCU architecture “Code: The Hidden Language of Computer Hardware and Software” by Charles Petzold - Ch. 10-12 Builds intuition about how hardware executes code.
C and low-level control “Effective C, 2nd Edition” by Robert C. Seacord - Ch. 3-6 Prevents undefined behavior in firmware.
ARM core basics “The Definitive Guide to ARM Cortex-M3/M4” by Joseph Yiu - Ch. 1-3 Core, memory map, and exceptions.

Real-Time and Timing

Concept Book & Chapter Why This Matters
Timing + scheduling “Making Embedded Systems, 2nd Edition” by Elecia White - Ch. 3-4 Foundations for deterministic behavior.
Interrupts and latency “The Definitive Guide to ARM Cortex-M3/M4” by Joseph Yiu - Ch. 7 Explains NVIC and exception handling.

Mixed-Signal & Sensors

Concept Book & Chapter Why This Matters
Sampling basics “Making Embedded Systems, 2nd Edition” by Elecia White - Ch. 7 Sampling and data integrity.
Sensor integration “Making Embedded Systems, 2nd Edition” by Elecia White - Ch. 6 Calibration and sensor processing.

STM32-Specific References

Concept Reference Why This Matters
STM32F3 reference manual RM0316 (STM32F303 reference manual) Official register and peripheral details. citeturn0search1
STM32F303 datasheet STM32F303VC datasheet Electrical limits, features, timing. citeturn0search0
STM32F3DISCOVERY user manual UM1570 Board wiring, LED/sensor connections. citeturn1search6

Quick Start: Your First 48 Hours

Day 1 (4 hours):

  1. Read “Chapter 1: Board Anatomy” and “Chapter 3: Clock Tree”.
  2. Skim the STM32F3DISCOVERY features list to understand board hardware. citeturn3view0
  3. Start Project 1 and make the LED blink at 1 Hz using SysTick.
  4. Do not optimize; just make timing visible and measured.

Day 2 (4 hours):

  1. Extend Project 1 with clock reporting over UART.
  2. Start Project 2 and build a pin map for the LEDs and one UART pin pair.
  3. Verify by toggling LED and printing UART output.

End of Weekend: You can explain how clock settings affect real-world timing and you can prove it with measurements. That is 80% of the embedded mental model.


Best for: Newcomers who want a structured path.

  1. Project 1 (Bring-Up + Clock Audit)
  2. Project 2 (GPIO Map)
  3. Project 3 (Timer Sequencer)
  4. Project 4 (PWM Controller)
  5. Then proceed to Projects 5-12 in order

Path 2: The Data Acquisition Path

Best for: Learners focused on sensors and signal processing.

  1. Project 1
  2. Project 5 (ADC Logging)
  3. Project 8 (DMA Ring Buffer)
  4. Project 9 (I2C Sensor)
  5. Project 15 (Sensor Fusion)

Path 3: The Real-Time Control Path

Best for: Motor control or timing-critical systems.

  1. Project 1
  2. Project 3 (Timers)
  3. Project 4 (PWM)
  4. Project 7 (Latency Profiler)
  5. Project 11 (Encoder)

Path 4: The Reliability Path

Best for: Embedded engineers focused on robustness.

  1. Project 1
  2. Project 12 (UART Diagnostics)
  3. Project 13 (Power Modes)
  4. Project 14 (Watchdog Recovery)
  5. Final Project (Full system + recovery)

Path 5: The Completionist

Best for: Learners who want full mastery.

Phase 1 (Weeks 1-2): Projects 1-3 Phase 2 (Weeks 3-4): Projects 4-6 Phase 3 (Weeks 5-6): Projects 7-10 Phase 4 (Weeks 7-8): Projects 11-15 Phase 5 (Weeks 9+): Final Project


Success Metrics

  • You can compute timer settings and verify them with measurements.
  • You can produce a pin map and route peripherals without conflict.
  • You can sample ADC data at a fixed rate and prove it.
  • You can generate PWM and DAC outputs with stable frequency.
  • You can measure interrupt latency and reason about jitter.
  • You can stream data with DMA without losing samples.
  • You can build a UART console that works without a debugger.
  • You can enter/exit low-power modes and explain wake sources.
  • You can recover from faults via watchdog and log reset causes.

Optional Appendices

Appendix A: Debugging & Measurement Toolkit

  • ST-LINK + SWD: Primary debugger and flash programmer. citeturn3view0
  • UART logging: Use a serial terminal for runtime observability.
  • GPIO pulse probes: Toggle a pin to measure ISR timing.
  • Logic analyzer/oscilloscope: Validate PWM and ADC timing.

Appendix B: Timing & Sampling Checklist

  • Confirm clock source and PLL settings.
  • Verify timer clock with measured output.
  • Confirm ADC sampling rate and buffer size.
  • Measure ISR latency under load.

Project Overview Table

Project Difficulty Time Core Outcome
1. Board Bring-Up and Clock Audit Beginner Weekend Verified timing and clock configuration
2. GPIO Map and Alternate-Function Explorer Beginner 1-2 weeks Pin map and peripheral validation
3. Timer-Driven LED Sequencer Intermediate 1-2 weeks Deterministic timer scheduling
4. PWM Motor/LED Controller Intermediate 1-2 weeks Hardware PWM control
5. ADC Sensor Sampler + Logging Intermediate 1-2 weeks Verified sampling pipeline
6. DAC Waveform Generator Intermediate 1-2 weeks Analog output synthesis
7. Interrupt Latency Profiler Advanced 1-2 weeks Measured ISR latency
8. DMA-Based ADC Ring Buffer Advanced 1-2 weeks Continuous streaming data
9. I2C Sensor Driver + Calibration Intermediate 1-2 weeks External sensor integration
10. SPI Display/LED Matrix Driver Intermediate 1-2 weeks High-speed SPI transfer
11. Quadrature Encoder Reader Advanced 1-2 weeks Motion sensing via encoder mode
12. UART Command Console + Diagnostics Intermediate 1-2 weeks Debug observability
13. Power Mode Explorer Advanced 1-2 weeks Power profiling & wake control
14. Fault Injection + Watchdog Recovery Advanced 1-2 weeks Reliability recovery flow
15. On-Board Sensor Fusion Dashboard Advanced 1 month+ Multi-sensor fusion output
16. Final: Environmental Monitor + Actuator Control Expert 1 month+ Full system integration

Project List

Project 1: Board Bring-Up and Clock Audit

  • Main Programming Language: C
  • Alternative Programming Languages: C++, Rust, Ada
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 1: Beginner
  • Knowledge Area: Boot + Clocking
  • Software or Tool: STM32CubeIDE + ST-LINK
  • Main Book: “Making Embedded Systems” by Elecia White

What you’ll build: A bring-up checklist that validates the MCU clock tree, system tick, and LED timing against measured outputs.

Why it teaches STM32F3DISCOVERY: It forces you to understand the boot path, clock sources, and how timing assumptions affect every peripheral.

Core challenges you’ll face:

  • Identifying the default clock configuration and verifying it physically
  • Mapping SysTick timing to real-world time
  • Separating board-level issues from firmware issues

Real World Outcome

You will produce a written bring-up report and a physical timing validation using LEDs and UART logs.

What you will see:

  1. LED toggling at a measured 1 Hz (verified with stopwatch or logic analyzer)
  2. UART log that prints system clock source and computed frequencies
  3. A deviation report if timing is off

Command Line Outcome Example:

# Flash firmware and open serial console
$ make flash
Flashing... OK

$ screen /dev/tty.usbmodem* 115200
BOOT OK
Clock source: HSI
SYSCLK: 72 MHz
AHB: 72 MHz
APB1: 36 MHz
APB2: 72 MHz
Measured LED period: 0.99 s
Status: within 1% tolerance

The Core Question You’re Answering

“How do I prove the MCU is running at the frequency I think it is?”

If you cannot answer this, every later timing assumption is unreliable.

Concepts You Must Understand First

  1. Clock Sources
    • What is the difference between HSI and HSE?
    • How does PLL multiplication affect peripheral timing?
    • Book Reference: “Making Embedded Systems” Ch. 3 - White
  2. SysTick Timer
    • What generates SysTick interrupts?
    • Why is SysTick tied to the core clock?
    • Book Reference: “The Definitive Guide to ARM Cortex-M3/M4” Ch. 4 - Yiu

Questions to Guide Your Design

  1. Measurement Method
    • How will you confirm frequency without an oscilloscope?
    • What counts as “good enough” accuracy?
  2. Reporting
    • How will you log timing without a debugger?

Thinking Exercise

“Timing Without Tools”

1) Start a stopwatch
2) Count 20 LED transitions
3) Record total time
4) Compute average period

Questions while tracing:

  • If the average period is 0.9 s, what does that imply about your clock?
  • If the average period is 1.1 s, what could cause that?

The Interview Questions They’ll Ask

  1. “How do you validate MCU clock frequency without lab equipment?”
  2. “What is the difference between HSI and HSE?”
  3. “Why does SysTick drift when PLL is misconfigured?”
  4. “How do prescalers affect peripheral timing?”

Hints in Layers

Hint 1: Starting Point Use the default clock config and blink an LED at 1 Hz.

HAL_Delay(500);

Hint 2: Next Step Read RCC registers and print SYSCLK and prescalers.

Hint 3: Key Technique Measure with a stopwatch or logic analyzer and average over many cycles.

Hint 4: Debugging/Verification If timing is off, verify prescalers before changing clock sources.

Books That Will Help

Topic Book Chapter
Embedded bring-up “Making Embedded Systems” by Elecia White Ch. 2-3
Cortex-M timing “The Definitive Guide to ARM Cortex-M3/M4” by Joseph Yiu Ch. 4

Common Pitfalls & Debugging

Problem 1: “LED timing is off by ~10%”

  • Why: Clock source not switched to intended PLL/HSE.
  • Fix: Verify RCC clock source bits and prescalers.
  • Quick test: Print clock source register and recompute SysTick.

Problem 2: “No UART output”

  • Why: Wrong baud due to clock mismatch.
  • Fix: Recompute UART divider for actual clock.
  • Quick test: Toggle a GPIO in UART init and verify with LED.

Definition of Done

  • SysTick tick rate measured within 2% of target
  • Clock source and prescalers logged over UART
  • Bring-up report includes measured vs expected timing
  • LED timing verified without debugger

Project 2: GPIO Map and Alternate-Function Explorer

  • Main Programming Language: C
  • Alternative Programming Languages: C++, Rust, Ada
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 1: Beginner
  • Knowledge Area: GPIO / Pin Multiplexing
  • Software or Tool: STM32CubeIDE
  • Main Book: “Making Embedded Systems” by Elecia White

What you’ll build: A pin-function map that documents each usable pin on the board and validates at least three alternate functions with visible outputs.

Why it teaches STM32F3DISCOVERY: It forces you to see the MCU as a routing problem, not just a pile of pins.

Core challenges you’ll face:

  • Reading the board schematic and matching pins to headers
  • Selecting alternate functions without conflicts
  • Verifying function selection with observable behavior

Real World Outcome

You will produce a “pin capability map” document and a test firmware that validates at least three alternate functions.

Command Line Outcome Example:

$ pinmap_verify
PA9: USART1_TX -> verified (serial output)
PA8: TIM1_CH1  -> verified (PWM on LED)
PA1: ADC1_IN2  -> verified (analog read changes)
Status: 3/3 functions confirmed

The Core Question You’re Answering

“How do I know which pins can actually do the job I want?”

Concepts You Must Understand First

  1. GPIO Modes
    • Input vs output vs analog vs alternate
    • Book Reference: “Making Embedded Systems” Ch. 5 - White
  2. Pin Multiplexing
    • What is an alternate function and why it matters?
    • Book Reference: “The Definitive Guide to ARM Cortex-M3/M4” Ch. 8 - Yiu

Questions to Guide Your Design

  1. Which pins are exposed on headers vs reserved on-board?
  2. Which alternate functions overlap on the same pin?
  3. Which pins are already used by LEDs or sensors?

Thinking Exercise

“Pin Conflict Resolution”

Peripheral A -> Pin X or Pin Y
Peripheral B -> Pin Y or Pin Z
Peripheral C -> Pin X or Pin Z
Decision: choose Pin Y for B, Pin Z for C, Pin X for A

The Interview Questions They’ll Ask

  1. “Explain alternate-function GPIO and why it matters.”
  2. “How do you resolve pin conflicts in an MCU design?”
  3. “What is the difference between open-drain and push-pull?”

Hints in Layers

Hint 1: Starting Point Start with LED pins on Port E and verify simple toggles.

Hint 2: Next Step Pick one UART and map TX/RX pins using the datasheet.

Hint 3: Key Technique Verify each alternate function with a physical effect (LED, serial output, ADC).

Hint 4: Debugging/Verification If a pin seems dead, check if it is shared with a sensor.

Books That Will Help

Topic Book Chapter
GPIO configuration “Making Embedded Systems” by Elecia White Ch. 5
MCU pin multiplexing “The Definitive Guide to ARM Cortex-M3/M4” by Joseph Yiu Ch. 8

Common Pitfalls & Debugging

Problem 1: “Pin won’t toggle”

  • Why: GPIO clock disabled or wrong port.
  • Fix: Enable GPIO port clock in RCC.
  • Quick test: Toggle another known pin on same port.

Problem 2: “UART TX pin outputs nothing”

  • Why: Wrong alternate function selection.
  • Fix: Check AF mapping in datasheet.
  • Quick test: Use LED or scope to verify pin changes.

Definition of Done

  • Pin map lists at least 20 usable pins with AFs
  • Three alternate functions verified in hardware
  • Conflicts with on-board hardware documented

Project 3: Timer-Driven LED Sequencer

  • Main Programming Language: C
  • Alternative Programming Languages: C++, Rust, Ada
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: Timers / Scheduling
  • Software or Tool: STM32CubeIDE
  • Main Book: “Making Embedded Systems” by Elecia White

What you’ll build: A deterministic LED sequencer where each LED pattern is driven by hardware timers instead of delays.

Why it teaches STM32F3DISCOVERY: It demonstrates the difference between software delays and hardware-scheduled events.

Core challenges you’ll face:

  • Configuring timer prescalers and auto-reload values
  • Using timer interrupts to trigger state transitions
  • Building a deterministic state machine

Real World Outcome

You will see a repeatable LED sequence with measured drift near zero.

$ led_sequencer
Pattern: 4-LED chase
Step interval: 250 ms
Observed drift after 10 minutes: 0.2 ms

The Core Question You’re Answering

“Why are timers better than software delays in embedded systems?”

Concepts You Must Understand First

  1. Timers and Prescalers
    • How does a timer count at a different rate from the CPU?
    • Book Reference: “Making Embedded Systems” Ch. 4 - White
  2. Interrupts and Latency
    • What happens when an ISR is delayed?
    • Book Reference: “The Definitive Guide to ARM Cortex-M3/M4” Ch. 7 - Yiu

Questions to Guide Your Design

  1. How will you measure drift over time?
  2. How will you represent the LED sequence without blocking?

Thinking Exercise

“Timer Math on Paper”

Target tick frequency = 1 kHz
Prescaler = (72 MHz / 1 kHz) - 1
Auto-reload = 250 - 1

The Interview Questions They’ll Ask

  1. “Explain how a hardware timer generates periodic interrupts.”
  2. “Why are blocking delays dangerous?”
  3. “How do you compute timer prescaler values?”

Hints in Layers

Hint 1: Starting Point Blink one LED with a timer interrupt.

Hint 2: Next Step Implement a state machine for the sequence.

Hint 3: Key Technique Use a timer-driven tick, not delay loops.

Hint 4: Debugging/Verification Measure drift with a logic analyzer over many cycles.

Books That Will Help

Topic Book Chapter
Timer configuration “Making Embedded Systems” by Elecia White Ch. 4
NVIC behavior “The Definitive Guide to ARM Cortex-M3/M4” by Joseph Yiu Ch. 7

Common Pitfalls & Debugging

Problem 1: “Timing drifts over minutes”

  • Why: Using delay loops instead of timer interrupts.
  • Fix: Replace delays with timer tick schedule.
  • Quick test: Verify timer interrupt rate via GPIO toggle.

Definition of Done

  • Timer-driven sequence runs for 10 minutes with <1 ms drift
  • No blocking delays in main loop
  • Timer settings documented and verified

Project 4: PWM Motor or LED Brightness Controller

  • Main Programming Language: C
  • Alternative Programming Languages: C++, Rust, Ada
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: Timers / PWM
  • Software or Tool: STM32CubeIDE
  • Main Book: “Making Embedded Systems” by Elecia White

What you’ll build: A PWM-based control system that changes LED brightness or motor speed in predictable steps.

Why it teaches STM32F3DISCOVERY: It shows how timers create analog-like control outputs.

Core challenges you’ll face:

  • Configuring PWM mode and duty cycle
  • Mapping percentages to compare values
  • Choosing PWM frequency for perception or motor response

Real World Outcome

$ pwm_controller
PWM freq: 1 kHz
Duty cycle: 10%
Duty cycle: 30%
Duty cycle: 50%
Duty cycle: 70%
Duty cycle: 90%

The Core Question You’re Answering

“How does a digital timer create analog-like control?”

Concepts You Must Understand First

  1. PWM Duty Cycle
    • What does duty cycle represent physically?
    • Book Reference: “Making Embedded Systems” Ch. 6 - White
  2. Timer Output Compare
    • What does the compare register do?
    • Book Reference: “The Definitive Guide to ARM Cortex-M3/M4” Ch. 9 - Yiu

Questions to Guide Your Design

  1. What PWM frequency avoids visible flicker?
  2. How will you map 0-100% to compare values?

Thinking Exercise

“Duty Cycle Mapping”

Period = 1000 ticks
0% -> 0
25% -> 250
50% -> 500
75% -> 750
100% -> 1000

The Interview Questions They’ll Ask

  1. “Explain PWM and how it controls motor speed.”
  2. “What tradeoffs exist between PWM frequency and resolution?”
  3. “How do you verify PWM output without a scope?”

Hints in Layers

Hint 1: Starting Point Start at 50% duty and verify LED brightness.

Hint 2: Next Step Change duty cycle in steps and log values.

Hint 3: Key Technique Keep frequency fixed, vary compare register.

Hint 4: Debugging/Verification Use a GPIO pin and logic analyzer for duty measurement.

Books That Will Help

Topic Book Chapter
PWM fundamentals “Making Embedded Systems” by Elecia White Ch. 6
Timer compare “The Definitive Guide to ARM Cortex-M3/M4” by Joseph Yiu Ch. 9

Common Pitfalls & Debugging

Problem 1: “LED flickers”

  • Why: PWM frequency too low.
  • Fix: Increase timer clock or reduce period.
  • Quick test: Measure PWM frequency on pin.

Definition of Done

  • PWM output stable at target frequency
  • Duty cycle maps correctly to brightness or motor speed
  • Output verified with measurement tool

Project 5: ADC Sensor Sampler + Logging

  • Main Programming Language: C
  • Alternative Programming Languages: C++, Rust, Ada
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: ADC / Sampling
  • Software or Tool: STM32CubeIDE
  • Main Book: “Making Embedded Systems” by Elecia White

What you’ll build: A consistent ADC sampling tool that logs sensor values at a fixed sample rate with timestamped output.

Why it teaches STM32F3DISCOVERY: It forces you to confront sampling rate, quantization, and noise.

Core challenges you’ll face:

  • Setting ADC sample rate and resolution
  • Triggering sampling with timers
  • Logging values without disturbing sampling

Real World Outcome

$ adc_logger
Sample rate: 100 Hz
Vref: 3.3 V
t=0.00s raw=1834 volts=1.48
t=0.01s raw=1840 volts=1.48
t=0.02s raw=1837 volts=1.48
Min=1810 Max=1860 Mean=1838

The Core Question You’re Answering

“How do I trust the data coming from an analog sensor?”

Concepts You Must Understand First

  1. Sampling Rate
    • What is aliasing in practical terms?
    • Book Reference: “Making Embedded Systems” Ch. 7 - White
  2. ADC Resolution
    • How does bit depth translate into voltage steps?
    • Book Reference: “Making Embedded Systems” Ch. 7 - White

Questions to Guide Your Design

  1. How will you ensure fixed sampling intervals?
  2. How will you log data without missing samples?

Thinking Exercise

“Sampling Rate Selection”

If sensor changes once per second, sample at 20 Hz
If sensor changes faster, increase sampling rate

The Interview Questions They’ll Ask

  1. “Explain aliasing in ADC sampling.”
  2. “How do you choose a sample rate?”
  3. “Why does ADC resolution matter?”

Hints in Layers

Hint 1: Starting Point Start with low sample rate, verify timing.

Hint 2: Next Step Trigger ADC conversions with a timer.

Hint 3: Key Technique Log timestamps outside the ISR to reduce jitter.

Hint 4: Debugging/Verification If readings jump, verify Vref and input wiring.

Books That Will Help

Topic Book Chapter
Sampling theory “Making Embedded Systems” by Elecia White Ch. 7
C accuracy “Effective C” by Robert C. Seacord Ch. 6

Common Pitfalls & Debugging

Problem 1: “ADC readings unstable”

  • Why: Floating input or insufficient sampling time.
  • Fix: Use a stable sensor or add a resistor divider.
  • Quick test: Connect ADC to known voltage and verify.

Definition of Done

  • Sample rate measured within 2% of target
  • Raw values converted to volts correctly
  • Data logged without missing samples

Project 6: DAC Waveform Generator

  • Main Programming Language: C
  • Alternative Programming Languages: C++, Rust, Ada
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: DAC / Signal Generation
  • Software or Tool: STM32CubeIDE
  • Main Book: “Making Embedded Systems” by Elecia White

What you’ll build: A DAC-based waveform generator that outputs a triangle or sine-like waveform.

Why it teaches STM32F3DISCOVERY: It makes you think about discrete time outputs and reconstruction.

Core challenges you’ll face:

  • Timing DAC updates to produce stable frequency
  • Creating a waveform lookup table
  • Verifying output without a scope

Real World Outcome

$ dac_wavegen
Waveform: triangle
Frequency: 400 Hz
Samples per cycle: 64
DAC resolution: 12-bit

The Core Question You’re Answering

“How do I create a smooth analog signal from discrete digital values?”

Concepts You Must Understand First

  1. DAC Resolution
    • What does 12-bit resolution mean in voltage steps?
    • Book Reference: “Making Embedded Systems” Ch. 7 - White
  2. Update Rate
    • How does sample rate determine output frequency?
    • Book Reference: “Making Embedded Systems” Ch. 7 - White

Questions to Guide Your Design

  1. How many samples per cycle do you need?
  2. How will you confirm output frequency without a scope?

Thinking Exercise

“Waveform Table Size”

More samples -> smoother waveform
Fewer samples -> lower CPU/DMA load

The Interview Questions They’ll Ask

  1. “How does a DAC generate an analog signal?”
  2. “What determines waveform frequency?”
  3. “How do you test DAC output without a scope?”

Hints in Layers

Hint 1: Starting Point Use a simple triangle wave table.

Hint 2: Next Step Trigger DAC updates with a timer.

Hint 3: Key Technique Consider DMA to reduce CPU load.

Hint 4: Debugging/Verification Use a multimeter to verify average voltage changes.

Books That Will Help

Topic Book Chapter
Waveform generation “Making Embedded Systems” by Elecia White Ch. 7
Low-level C “Effective C” by Robert C. Seacord Ch. 5

Common Pitfalls & Debugging

Problem 1: “Waveform unstable”

  • Why: Timer jitter or irregular update intervals.
  • Fix: Use hardware timer trigger or DMA.
  • Quick test: Toggle GPIO each DAC update and measure.

Definition of Done

  • Stable DAC waveform at target frequency
  • Table size and update rate documented
  • Output verified with measurement tool

Project 7: Interrupt Latency Profiler

  • Main Programming Language: C
  • Alternative Programming Languages: C++, Rust, Ada
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Interrupts / Latency
  • Software or Tool: STM32CubeIDE
  • Main Book: “Making Embedded Systems” by Elecia White

What you’ll build: A small experiment that measures interrupt latency under different load conditions and logs results.

Why it teaches STM32F3DISCOVERY: It reveals real-time behavior under stress.

Core challenges you’ll face:

  • Measuring latency without skewing results
  • Controlling background load
  • Interpreting the effect of priorities

Real World Outcome

$ irq_latency
Load: idle -> latency min/avg/max = 3/4/6 us
Load: moderate -> latency min/avg/max = 6/8/12 us
Load: heavy -> latency min/avg/max = 15/20/28 us

The Core Question You’re Answering

“How quickly can my system react, and what makes it slower?”

Concepts You Must Understand First

  1. NVIC Priorities
    • How are priorities encoded?
    • Book Reference: “The Definitive Guide to ARM Cortex-M3/M4” Ch. 7 - Yiu
  2. Timer Measurement
    • How can a timer be used as a stopwatch?
    • Book Reference: “Making Embedded Systems” Ch. 4 - White

Questions to Guide Your Design

  1. How will you measure latency without adding bias?
  2. What background load represents real-world work?

Thinking Exercise

“Latency Budget”

Control loop must respond within 1 ms
Allocate 0.2 ms to ISR entry
Allocate 0.5 ms to processing
Allocate 0.3 ms to output update

The Interview Questions They’ll Ask

  1. “What determines interrupt latency on Cortex-M?”
  2. “How do you measure ISR response time?”
  3. “Why can high load increase latency?”

Hints in Layers

Hint 1: Starting Point Use a timer as a free-running counter.

Hint 2: Next Step Capture the counter value at ISR entry.

Hint 3: Key Technique Simulate load with a busy loop or dummy task.

Hint 4: Debugging/Verification Toggle a GPIO at ISR entry and measure with logic analyzer.

Books That Will Help

Topic Book Chapter
Interrupts “The Definitive Guide to ARM Cortex-M3/M4” by Joseph Yiu Ch. 7
Real-time design “Making Embedded Systems” by Elecia White Ch. 4

Common Pitfalls & Debugging

Problem 1: “Latency measurements inconsistent”

  • Why: Measurement method adds jitter.
  • Fix: Use hardware timer capture and GPIO pulse.
  • Quick test: Compare timer-based measurement to GPIO pulse.

Definition of Done

  • Latency measured under at least 3 load levels
  • Priority effects documented
  • Results logged and reproducible

Project 8: DMA-Based ADC Ring Buffer

  • Main Programming Language: C
  • Alternative Programming Languages: C++, Rust, Ada
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 3: Advanced
  • Knowledge Area: DMA / Data Streaming
  • Software or Tool: STM32CubeIDE
  • Main Book: “Making Embedded Systems” by Elecia White

What you’ll build: A DMA-driven ADC capture system that fills a circular buffer and allows continuous processing.

Why it teaches STM32F3DISCOVERY: It demonstrates high-throughput acquisition without CPU bottlenecks.

Core challenges you’ll face:

  • Configuring DMA in circular mode
  • Handling half-transfer and full-transfer events
  • Ensuring processing keeps up with data rate

Real World Outcome

$ dma_adc
Buffer size: 1024 samples
Half-transfer event at t=0.128s
Full-transfer event at t=0.256s
Overruns: 0

The Core Question You’re Answering

“How do I move large amounts of data without losing samples?”

Concepts You Must Understand First

  1. DMA Transfer Modes
    • What is circular mode and why is it useful?
    • Book Reference: “Making Embedded Systems” Ch. 9 - White
  2. Buffer Management
    • How do you avoid overwriting unread data?
    • Book Reference: “Making Embedded Systems” Ch. 9 - White

Questions to Guide Your Design

  1. How do you choose buffer size for a given sample rate?
  2. When do you process half vs full buffer?

Thinking Exercise

“Buffer Capacity”

Duration = buffer_samples / sample_rate
1024 / 8000 = 0.128 s

The Interview Questions They’ll Ask

  1. “What is DMA and why is it useful?”
  2. “Explain circular buffer mode.”
  3. “What is the tradeoff between buffer size and latency?”

Hints in Layers

Hint 1: Starting Point Start with small buffer and verify interrupts.

Hint 2: Next Step Process half-buffer to reduce latency.

Hint 3: Key Technique Keep processing time less than buffer duration.

Hint 4: Debugging/Verification Log overrun counter and stop if it increments.

Books That Will Help

Topic Book Chapter
DMA and buffering “Making Embedded Systems” by Elecia White Ch. 9
C memory safety “Effective C” by Robert C. Seacord Ch. 6

Common Pitfalls & Debugging

Problem 1: “Overruns occur”

  • Why: Processing slower than buffer fill rate.
  • Fix: Increase buffer size or reduce sample rate.
  • Quick test: Log processing time and compare to buffer duration.

Definition of Done

  • Continuous streaming for 10 minutes with 0 overruns
  • Half/full interrupts handled correctly
  • Buffer size calculation documented

Project 9: I2C Sensor Driver and Calibration Log

  • Main Programming Language: C
  • Alternative Programming Languages: C++, Rust, Ada
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 2. The “Micro-SaaS / Pro Tool”
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: I2C / Sensor Integration
  • Software or Tool: STM32CubeIDE
  • Main Book: “Making Embedded Systems” by Elecia White

What you’ll build: A driver and calibration log for an I2C sensor (on-board LSM303DLHC or external sensor).

Why it teaches STM32F3DISCOVERY: It moves you from on-chip peripherals to external hardware integration.

Core challenges you’ll face:

  • Reading sensor datasheets and register maps
  • Handling I2C timing and NACKs
  • Converting raw values into calibrated units

Real World Outcome

$ i2c_sensor
WHO_AM_I: 0x3A
Accel raw: 512  -48  16384
Accel g:   0.03 -0.02 0.98
Bias:      +0.01g  -0.02g  +0.04g

The Core Question You’re Answering

“How do I turn raw sensor bytes into trusted real-world values?”

Concepts You Must Understand First

  1. I2C Transactions
    • Start/stop, address, ACK/NACK behavior
    • Book Reference: “Making Embedded Systems” Ch. 11 - White
  2. Calibration
    • Why do raw data need offsets or scaling?
    • Book Reference: “Making Embedded Systems” Ch. 6 - White

Questions to Guide Your Design

  1. How will you detect failed I2C transactions?
  2. How will you store and apply calibration constants?

Thinking Exercise

“Calibration Table”

Raw 500 -> 24.0 C
Raw 520 -> 25.0 C
Raw 540 -> 26.0 C

The Interview Questions They’ll Ask

  1. “Explain the I2C read sequence.”
  2. “How do you handle bus errors?”
  3. “Why do sensors require calibration?”

Hints in Layers

Hint 1: Starting Point Read WHO_AM_I register to verify bus.

Hint 2: Next Step Read a single axis and verify it changes with motion.

Hint 3: Key Technique Implement scaling using datasheet constants.

Hint 4: Debugging/Verification Check pull-up resistors and bus speed if NACKs occur.

Books That Will Help

Topic Book Chapter
I2C basics “Making Embedded Systems” by Elecia White Ch. 11
Calibration “Making Embedded Systems” by Elecia White Ch. 6

Common Pitfalls & Debugging

Problem 1: “No ACK from sensor”

  • Why: Wrong device address or bus pull-ups missing.
  • Fix: Verify address and check SDA/SCL pull-ups.
  • Quick test: Scan I2C bus for addresses.

Definition of Done

  • Sensor WHO_AM_I read correctly
  • Raw readings converted to physical units
  • Calibration offsets logged and applied

Project 10: SPI Display or LED Matrix Driver

  • Main Programming Language: C
  • Alternative Programming Languages: C++, Rust, Ada
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 2. The “Micro-SaaS / Pro Tool”
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: SPI / Display Control
  • Software or Tool: STM32CubeIDE
  • Main Book: “Making Embedded Systems” by Elecia White

What you’ll build: A simple SPI driver that pushes pixels or patterns to a small display or LED matrix.

Why it teaches STM32F3DISCOVERY: It forces you to manage high-speed data transfers and peripheral control.

Core challenges you’ll face:

  • Configuring SPI mode and clock polarity
  • Managing chip select timing
  • Updating display memory efficiently

Real World Outcome

$ spi_display
Pattern: checkerboard
Frame rate: 30 fps
Status: stable

The Core Question You’re Answering

“How do I push lots of data quickly and reliably to a peripheral?”

Concepts You Must Understand First

  1. SPI Modes
    • CPOL/CPHA meaning
    • Book Reference: “Making Embedded Systems” Ch. 11 - White
  2. Frame Buffering
    • Buffer size vs memory use
    • Book Reference: “Making Embedded Systems” Ch. 9 - White

Questions to Guide Your Design

  1. How often do you need to update the display?
  2. Will you use DMA or CPU-driven transfers?

Thinking Exercise

“SPI Transaction Breakdown”

1) Assert chip select
2) Send command byte
3) Send data bytes
4) Deassert chip select

The Interview Questions They’ll Ask

  1. “Explain how SPI differs from I2C.”
  2. “What do CPOL and CPHA mean?”
  3. “How do you improve SPI throughput?”

Hints in Layers

Hint 1: Starting Point Send a static pattern first to verify wiring.

Hint 2: Next Step Update a small region before full frame.

Hint 3: Key Technique Use DMA for large frames.

Hint 4: Debugging/Verification If display is blank, check SPI mode and CS polarity.

Books That Will Help

Topic Book Chapter
SPI fundamentals “Making Embedded Systems” by Elecia White Ch. 11
DMA transfers “Making Embedded Systems” by Elecia White Ch. 9

Common Pitfalls & Debugging

Problem 1: “Display shows garbage”

  • Why: Wrong SPI mode or byte order.
  • Fix: Verify CPOL/CPHA and endianness.
  • Quick test: Send known single-byte pattern.

Definition of Done

  • Display shows correct pattern or text
  • Frame rate measured and stable
  • SPI mode and timing documented

Project 11: Quadrature Encoder Reader

  • Main Programming Language: C
  • Alternative Programming Languages: C++, Rust, Ada
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Timers / Input Capture
  • Software or Tool: STM32CubeIDE
  • Main Book: “Making Embedded Systems” by Elecia White

What you’ll build: A quadrature encoder interface that measures position and speed from a rotary encoder.

Why it teaches STM32F3DISCOVERY: It combines timer encoder mode with real-time signal interpretation.

Core challenges you’ll face:

  • Configuring timer encoder mode
  • Debouncing/filtering signals
  • Converting counts to speed and direction

Real World Outcome

$ encoder_read
Position: 124 counts
Direction: CW
Speed: 45 counts/sec

The Core Question You’re Answering

“How do I interpret two phase-shifted signals as precise motion?”

Concepts You Must Understand First

  1. Quadrature Signals
    • Phase shift and direction detection
    • Book Reference: “Making Embedded Systems” Ch. 6 - White
  2. Timer Encoder Mode
    • Hardware counting without CPU involvement
    • Book Reference: “The Definitive Guide to ARM Cortex-M3/M4” Ch. 9 - Yiu

Questions to Guide Your Design

  1. What counts-per-revolution does your encoder provide?
  2. How will you handle noise or bouncing?

Thinking Exercise

“Direction Detection”

A leads B -> CW
B leads A -> CCW

The Interview Questions They’ll Ask

  1. “How does a quadrature encoder determine direction?”
  2. “What is timer encoder mode and why use it?”
  3. “How do you compute speed from counts?”

Hints in Layers

Hint 1: Starting Point Test encoder outputs with slow manual rotation.

Hint 2: Next Step Configure timer in encoder mode and read counts.

Hint 3: Key Technique Use a rolling time window for speed calculation.

Hint 4: Debugging/Verification If counts jump, add input filtering or debounce.

Books That Will Help

Topic Book Chapter
Encoder signals “Making Embedded Systems” by Elecia White Ch. 6
Timer input capture “The Definitive Guide to ARM Cortex-M3/M4” by Joseph Yiu Ch. 9

Common Pitfalls & Debugging

Problem 1: “Counts jump randomly”

  • Why: Signal noise or bouncing.
  • Fix: Enable input filter or add RC filter.
  • Quick test: Slow rotation should yield steady counts.

Definition of Done

  • Encoder counts stable and direction correct
  • Speed computed over known interval
  • Noise handling documented

Project 12: UART Command Console + Boot Diagnostics

  • Main Programming Language: C
  • Alternative Programming Languages: C++, Rust, Ada
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 2. The “Micro-SaaS / Pro Tool”
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: UART / Diagnostics
  • Software or Tool: STM32CubeIDE
  • Main Book: “Making Embedded Systems” by Elecia White

What you’ll build: A UART-based console that prints boot diagnostics and responds to simple commands.

Why it teaches STM32F3DISCOVERY: It builds a debugging interface used in real products.

Core challenges you’ll face:

  • Configuring UART baud correctly
  • Implementing a simple command parser
  • Keeping the console non-blocking

Real World Outcome

$ screen /dev/tty.usbmodem* 115200
STM32F3 Boot v1.0
Clock: 72 MHz
ADC: ready
Type 'status' for system state
> status
Uptime: 12.4 s
ADC rate: 100 Hz
DMA overruns: 0

The Core Question You’re Answering

“How do I make firmware observable without a debugger?”

Concepts You Must Understand First

  1. UART Timing
    • Baud rate derivation from clock
    • Book Reference: “Making Embedded Systems” Ch. 11 - White
  2. Non-blocking I/O
    • Avoid blocking reads in real-time system
    • Book Reference: “Making Embedded Systems” Ch. 4 - White

Questions to Guide Your Design

  1. What diagnostics are most useful during bring-up?
  2. How will you avoid blocking the main loop?

Thinking Exercise

“Minimal Command Set”

status -> prints clocks and uptime
adc -> prints latest ADC value
help -> lists commands

The Interview Questions They’ll Ask

  1. “How do you configure UART baud rate on an MCU?”
  2. “What is the risk of blocking UART reads?”
  3. “How do you implement a simple parser?”

Hints in Layers

Hint 1: Starting Point Print a boot banner on UART.

Hint 2: Next Step Add a ring buffer for input characters.

Hint 3: Key Technique Parse commands on newline only.

Hint 4: Debugging/Verification If text is garbled, verify baud and clock.

Books That Will Help

Topic Book Chapter
UART basics “Making Embedded Systems” by Elecia White Ch. 11
Non-blocking design “Making Embedded Systems” by Elecia White Ch. 4

Common Pitfalls & Debugging

Problem 1: “Garbled characters”

  • Why: Baud mismatch due to wrong clock.
  • Fix: Recalculate baud divider.
  • Quick test: Print a repeating pattern and verify on terminal.

Definition of Done

  • UART banner prints reliably at boot
  • At least 3 commands implemented
  • Console remains responsive under load

Project 13: Power Mode Explorer

  • Main Programming Language: C
  • Alternative Programming Languages: C++, Rust, Ada
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 2. The “Micro-SaaS / Pro Tool”
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Power / Low-Power Modes
  • Software or Tool: STM32CubeIDE
  • Main Book: “Making Embedded Systems” by Elecia White

What you’ll build: A test program that cycles through power modes and logs wake-up sources and timing.

Why it teaches STM32F3DISCOVERY: It connects firmware design to real-world energy constraints.

Core challenges you’ll face:

  • Entering/exiting low-power modes safely
  • Measuring time in each mode
  • Reinitializing peripherals after wake

Real World Outcome

$ power_modes
Mode: Sleep -> wake by SysTick in 100 ms
Mode: Stop  -> wake by button in 2.4 s
Mode: Standby -> wake by reset

The Core Question You’re Answering

“How do I trade performance for power without breaking functionality?”

Concepts You Must Understand First

  1. Power Modes
    • Differences between Sleep, Stop, Standby
    • Book Reference: “Making Embedded Systems” Ch. 8 - White
  2. Wake-up Sources
    • Which peripherals can wake the MCU?
    • Book Reference: “Making Embedded Systems” Ch. 8 - White

Questions to Guide Your Design

  1. How will you measure time spent in each mode?
  2. What state must be saved before sleep?

Thinking Exercise

“Power Budget”

Active current: 20 mA
Stop current: 0.2 mA
Average = (0.1 * 20) + (0.9 * 0.2)

The Interview Questions They’ll Ask

  1. “Explain the differences between Sleep, Stop, and Standby.”
  2. “How do you decide which power mode to use?”
  3. “How do you estimate battery life?”

Hints in Layers

Hint 1: Starting Point Start with Sleep mode and timer wake-up.

Hint 2: Next Step Add external interrupt as wake source.

Hint 3: Key Technique Reinitialize clocks after wake.

Hint 4: Debugging/Verification Log reset flags to detect Standby exit.

Books That Will Help

Topic Book Chapter
Low-power design “Making Embedded Systems” by Elecia White Ch. 8
Reliability “Making Embedded Systems” by Elecia White Ch. 10

Common Pitfalls & Debugging

Problem 1: “System never wakes”

  • Why: Wake source not configured or clock not restored.
  • Fix: Verify wake source interrupt enable and clock reinit.
  • Quick test: Toggle LED before sleep and after wake.

Definition of Done

  • Entered and exited Sleep, Stop, Standby
  • Wake source logged correctly
  • Power mode behavior documented

Project 14: Fault Injection and Watchdog Recovery

  • Main Programming Language: C
  • Alternative Programming Languages: C++, Rust, Ada
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 3. The “Service & Support” Model
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Reliability / Watchdogs
  • Software or Tool: STM32CubeIDE
  • Main Book: “Making Embedded Systems” by Elecia White

What you’ll build: A fault-injection test that deliberately hangs the system and verifies watchdog recovery behavior.

Why it teaches STM32F3DISCOVERY: It teaches reliability engineering and recovery design.

Core challenges you’ll face:

  • Configuring watchdog timers
  • Simulating hangs safely
  • Logging reset causes

Real World Outcome

$ watchdog_test
Injecting fault: infinite loop
System reset detected
Reset reason: watchdog
Recovery time: 250 ms

The Core Question You’re Answering

“How does the system recover when my code gets stuck?”

Concepts You Must Understand First

  1. Watchdog Timers
    • Why they exist and how they reset the MCU
    • Book Reference: “Making Embedded Systems” Ch. 10 - White
  2. Reset Cause Analysis
    • How to log reset reasons early in boot
    • Book Reference: “Making Embedded Systems” Ch. 10 - White

Questions to Guide Your Design

  1. What faults should trigger watchdog reset?
  2. What should system do after reset?

Thinking Exercise

“Failure Tree”

- Infinite loop -> watchdog reset
- Sensor hang -> watchdog reset
- Memory corruption -> safe mode

The Interview Questions They’ll Ask

  1. “What is a watchdog and why use it?”
  2. “How do you detect reset cause?”
  3. “How do you avoid reset loops?”

Hints in Layers

Hint 1: Starting Point Configure watchdog with generous timeout.

Hint 2: Next Step Skip refresh to induce reset.

Hint 3: Key Technique Log reset cause on boot and clear flags.

Hint 4: Debugging/Verification If reset is too fast, verify watchdog clock source.

Books That Will Help

Topic Book Chapter
Watchdog design “Making Embedded Systems” by Elecia White Ch. 10
Reliability “Making Embedded Systems” by Elecia White Ch. 10

Common Pitfalls & Debugging

Problem 1: “Watchdog resets immediately”

  • Why: Timeout configured too short.
  • Fix: Increase prescaler or reload value.
  • Quick test: Print countdown before refresh.

Definition of Done

  • Watchdog reset triggered intentionally
  • Reset cause logged correctly
  • Recovery behavior defined and repeatable

Project 15: On-Board Sensor Fusion Dashboard

  • Main Programming Language: C
  • Alternative Programming Languages: C++, Rust, Ada
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 2. The “Micro-SaaS / Pro Tool”
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Sensors / Data Fusion
  • Software or Tool: STM32CubeIDE
  • Main Book: “Making Embedded Systems” by Elecia White

What you’ll build: A dashboard that reads onboard sensors and outputs fused orientation or motion status.

Why it teaches STM32F3DISCOVERY: It integrates buses, calibration, sampling, and timing in one system.

Core challenges you’ll face:

  • Synchronizing multi-sensor data
  • Calibrating offsets and scale
  • Producing stable fused output

Real World Outcome

$ sensor_fusion
Accel: stable
Gyro: slow rotation
Orientation: tilt-right
Update rate: 50 Hz

The Core Question You’re Answering

“How do I combine imperfect sensor data into a trustworthy signal?”

Concepts You Must Understand First

  1. Sensor Calibration
    • Bias and scale corrections
    • Book Reference: “Making Embedded Systems” Ch. 6 - White
  2. Synchronization
    • Why samples must be time-aligned
    • Book Reference: “Making Embedded Systems” Ch. 7 - White

Questions to Guide Your Design

  1. What update rate is appropriate for motion tracking?
  2. What fusion strategy will you use (complementary filter, etc.)?

Thinking Exercise

“Data Alignment”

t0: read accel
t0+2ms: read gyro
t0+4ms: fuse -> output

The Interview Questions They’ll Ask

  1. “Why is sensor fusion necessary?”
  2. “How do you calibrate a gyroscope?”
  3. “How do you detect drift?”

Hints in Layers

Hint 1: Starting Point Log each sensor independently at fixed rate.

Hint 2: Next Step Align timestamps and compute a simple fused status.

Hint 3: Key Technique Use a complementary filter to reduce noise.

Hint 4: Debugging/Verification Verify stable output when board is still.

Books That Will Help

Topic Book Chapter
Calibration “Making Embedded Systems” by Elecia White Ch. 6
Sampling and filtering “Making Embedded Systems” by Elecia White Ch. 7

Common Pitfalls & Debugging

Problem 1: “Orientation drifts quickly”

  • Why: Gyro bias not calibrated.
  • Fix: Estimate bias when board is still and subtract.
  • Quick test: Keep board still for 30s and verify output stability.

Definition of Done

  • Sensors sampled at fixed rate
  • Calibration offsets applied
  • Fused output stable and repeatable

Project 16: Final - Real-Time Environmental Monitor + Actuator Control

  • Main Programming Language: C
  • Alternative Programming Languages: C++, Rust, Ada
  • Coolness Level: Level 5: Pure Magic (Super Cool)
  • Business Potential: 3. The “Service & Support” Model
  • Difficulty: Level 4: Expert
  • Knowledge Area: Real-Time Embedded System
  • Software or Tool: STM32CubeIDE + ST-LINK
  • Main Book: “Making Embedded Systems” by Elecia White

What you’ll build: A complete embedded system that samples sensors, runs a control loop, and drives an actuator with a UART dashboard.

Why it teaches STM32F3DISCOVERY: It integrates clocks, GPIO, timers, ADC, DMA, interrupts, power modes, and communications into a full system.

Core challenges you’ll face:

  • Balancing real-time sampling with actuator control
  • Coordinating multiple peripherals with minimal latency
  • Designing a robust watchdog and recovery strategy

Real World Outcome

$ env_monitor
Temp: 26.4 C
Humidity: 42%
Fan PWM: 45%
Mode: active
Watchdog: healthy

The Core Question You’re Answering

“Can I design a full embedded system that is observable, reliable, and real-time?”

Concepts You Must Understand First

  1. System Scheduling
    • How do you avoid timing conflicts across peripherals?
    • Book Reference: “Making Embedded Systems” Ch. 4 - White
  2. Control Loops
    • How do you map sensor readings to actuator output?
    • Book Reference: “Making Embedded Systems” Ch. 7 - White

Questions to Guide Your Design

  1. What is the end-to-end path from sensor to actuator?
  2. How will you detect and recover from faults?

Thinking Exercise

“System Block Diagram”

Sensor -> ADC -> DMA -> Buffer -> Control Logic -> PWM -> Actuator
UART -> Diagnostics
Watchdog -> Reset Logic

The Interview Questions They’ll Ask

  1. “How do you design a real-time embedded control system?”
  2. “How do you integrate ADC, PWM, and DMA together?”
  3. “What is your strategy for fault recovery?”

Hints in Layers

Hint 1: Starting Point Start with one sensor and one actuator path.

Hint 2: Next Step Add UART diagnostics to observe state.

Hint 3: Key Technique Use DMA for acquisition and timers for PWM control.

Hint 4: Debugging/Verification Keep a fault log so you know why the system reset.

Books That Will Help

Topic Book Chapter
Scheduling “Making Embedded Systems” by Elecia White Ch. 4
Control loops “Making Embedded Systems” by Elecia White Ch. 7

Common Pitfalls & Debugging

Problem 1: “Control loop unstable”

  • Why: Sampling rate too low or inconsistent.
  • Fix: Increase sampling rate and use timer-triggered ADC.
  • Quick test: Log sampling intervals and verify jitter.

Definition of Done

  • Stable sensor sampling with verified rate
  • Actuator responds predictably to sensor thresholds
  • UART dashboard shows system health
  • Watchdog recovery tested

Summary

# Project Core Outcome
1 Board Bring-Up and Clock Audit Verified clocking and timing accuracy
2 GPIO Map and Alternate-Function Explorer Pin mapping and alternate-function validation
3 Timer-Driven LED Sequencer Deterministic scheduling without delays
4 PWM Motor or LED Brightness Controller Hardware PWM control and duty mapping
5 ADC Sensor Sampler + Logging Reliable sampling with known rate
6 DAC Waveform Generator Analog waveform output and timing control
7 Interrupt Latency Profiler Measured response time under load
8 DMA-Based ADC Ring Buffer High-throughput data capture
9 I2C Sensor Driver and Calibration Log External sensor integration and calibration
10 SPI Display or LED Matrix Driver High-speed data transfer and display updates
11 Quadrature Encoder Reader Motion sensing via timer encoder mode
12 UART Command Console + Boot Diagnostics Observable firmware with command interface
13 Power Mode Explorer Measured power tradeoffs and wake behavior
14 Fault Injection and Watchdog Recovery Reliable reset and recovery behavior
15 On-Board Sensor Fusion Dashboard Multi-sensor integration and fusion
16 Final: Real-Time Environmental Monitor + Actuator Control Full system integration with real-time control