- C 78.8%
- CMake 18.5%
- Linker Script 2.7%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| 01_simple_blink | ||
| 02_uart_systick | ||
| 03_hal_blink | ||
| 04_usb_mouse | ||
| common | ||
| .gitignore | ||
| CMakeLists.txt | ||
| README.md | ||
| toolchain.cmake | ||
📊 STM32F411CEU6 (Blackpill) vs. RP2350 (Pi Pico 2) Reference Guide
If you are coming from the Pi Pico C SDK (RP2040 / RP2350), the STM32F411 will feel both familiar and distinct. While the Pi Pico 2 is a modern, general-purpose microcontroller focused on raw speed, flexible I/O, and dual cores, the STM32F411 is an industrial workhorse focused on dedicated hardware acceleration and robust, deterministic execution.
⚙️ Architectural & Hardware Comparison
| Feature | RP2350 (Pi Pico 2) | STM32F411CEU6 (Blackpill) | Takeaway for Pico Developers |
|---|---|---|---|
| CPU Core | Dual ARM Cortex-M33 (or Hazard3 RISC-V) | Single ARM Cortex-M4 | Pico 2 is faster/multi-core. STM32 is single-core but features a very capable M4 with DSP extensions and a hardware Floating Point Unit (FPU). |
| Clock Speed | 150 MHz | 100 MHz | Pico 2 runs faster, but STM32 instructions run deterministically from zero-wait-state internal flash. |
| Flash Memory | External QSPI (usually 4MB - 8MB) | 512 KB Internal Flash | STM32 Flash is internal: You don't need external flash chips. However, 512KB is a hard limit (no mega-sized programs). |
| SRAM | 520 KB | 128 KB | Pico 2 has 4x more RAM. On STM32, memory management (especially buffers) must be more conservative. |
| Operating Voltage | 3.3V (Pico 2 GPIOs are 5V tolerant when powered, except ADC; Pico 1 is not) | 3.3V (with 5V tolerant pins!) | Many STM32 pins are 5V tolerant (marked FT in the datasheet). This is a huge help when interfacing with older 5V sensors/displays (unlike Pico 1, which is strictly 3.3V only). |
| USB Support | USB 1.1 Device/Host | USB 2.0 OTG Full Speed | STM32 has a more advanced USB controller (OTG), supporting host/device modes with dedicated hardware FIFOs. |
🛠️ Peripheral Differences: "Smart Hardware" vs. "Programmable I/O"
The biggest philosophical difference between the RP2350 and the STM32F411 is how they handle complex interfaces:
1. The Pico 2 approach: PIO (Programmable I/O)
On the Pico 2, if you want a custom interface (like driving WS2812B LEDs, an 8-bit parallel display, or DVI video), you write small assembly programs for the PIO state machines.
- Pros: Infinitely flexible.
- Cons: Consumes CPU-adjacent resources, requires learning PIO assembly.
2. The STM32 approach: Advanced Timers & Dedicated Engines
The STM32 has no PIO. Instead, it has highly specialized hardware modules designed to run completely independent of the CPU.
- Advanced Timers (TIM1, TIM2, etc.): These are not just for PWM. They have hardware support for:
- Quadrature Encoder Interface (QEI): Connect a rotary encoder directly to the timer pins; the hardware increments/decrements a counter register automatically without any CPU interrupts.
- Input Capture: Measures pulse widths down to nanosecond precision entirely in hardware.
- Complementary PWM: Used in motor control to drive H-bridges safely with hardware-inserted "dead time" (preventing short circuits).
- DMA (Direct Memory Access): The STM32 DMA controllers are deeply integrated. You can map them to transfer data directly from an ADC to RAM, or RAM to SPI/USART, completely in the background without waking the CPU.
📂 Software Ecosystem Comparison
| Development Area | Pi Pico C SDK | STM32 Ecosystem |
|---|---|---|
| SDK Style | Clean, modular APIs (e.g. hardware_i2c, gpio_put). |
Three choices depending on your preferences: 1. STM32 HAL: High-level, official, boilerplate-heavy. 2. STM32 LL (Low-Layer): Lightweight register wrappers. 3. libopencm3: Open-source, very similar to Pico SDK. |
| Pin Configuration | Pins can be dynamically routed to functions (gpio_set_function). |
Pins have fixed alternate functions (AF) mapped in the datasheet. You configure them via GPIOx_AFR registers. |
| Clock Trees | Simple configuration helper clocks_init(). |
Complex Clock Tree: The STM32 clock tree allows routing the internal HSI (16MHz) or external HSE (25MHz crystal on Blackpill) through a PLL to generate separate clocks for USB (48MHz), AHB, APB1, and APB2 buses. |
🚀 Recommended Path Forward
Since you are comfortable with the CMake/GCC compilation flow from the Pico C SDK, you have two great options for your next project:
Option A: Continue with Register-Level C (Bare-Metal)
If you want to understand how ARM microcontrollers work at the lowest level, writing registers is extremely satisfying. We can build:
- A high-resolution delay timer using the SysTick timer.
- A Serial console (
printf) using the USART peripheral registers. - A basic ADC reader using registers.
Option B: Integrate libopencm3 or the STM32 HAL
If you want to build projects without writing raw register addresses every time:
- libopencm3: A clean, open-source library that looks very similar to the Pico SDK.
- STM32 HAL / CMSIS: The industry standard. We can fetch it via CMake's
FetchContentto write standard STM32 code.