The overview, with examples running, is on the board page and The STM32 Blue Pill model (every register).

The STM32 Blue Pill

An STM32F103C8T6 on our Cortex-M3 core at 72 MHz: GPIO through CRL and CRH, TIM1 to TIM4, USART1, a twelve-bit ADC and SysTick.

What it is

The board everybody calls the Blue Pill, an STM32F103C8T6 running on our own Cortex-M core in its ARMv7-M profile. A Cortex-M3 is ARMv7-M without the M4's DSP extension and without an FPU, and the core refuses both here, so a program that reaches for them stops rather than quietly working.

The registers come from RM0008 and the STM32F103x8/xB datasheet at their real addresses, so the same firmware runs on the board on your desk. The clock is fixed: 72 MHz for the CPU and the timers, from power-on.

This is not the Black Pill with different numbers

The F1 is a different generation of the family, and the differences are the ones a program can see. The F411 is a Cortex-M4 at 84 MHz with 512 KB of flash; the F103 is a Cortex-M3 at 72 MHz with 64 KB of flash and 20 KB of SRAM. The F411 configures a pin with MODER, OTYPER, PUPDR and AFRL/AFRH; the F103 uses one four-bit field in CRL or CRH, and takes an input's pull direction out of that pin's ODR bit. Not one peripheral address is shared.

The pins

40 pins on a 0.1 inch pitch, 2 by 20, with the micro-USB socket at the top.

Left header, top to bottom: VBAT, PC13, PC14, PC15, PA0 to PA7, PB0, PB1, PB10, PB11, NRST, 3V3, GND, 5V.

Right header: GNDb, GNDc, 3V3b, PB12 to PB15, PA8 to PA12, PA15, PB3 to PB9.

A pin here is a port and a number, not a board number: PA5, not 5. The silkscreen prints the short forms (VB, C13, R, A0); the catalog spells them out, and suffixes the repeats (GNDb, GNDc, 3V3b) because two pins of one part may not share a name.

PA13 and PA14 are on the separate SWD header and PB2 is the BOOT1 jumper, so no wire reaches them here, exactly as on the board.

This is a 3.3 volt board, always powered over USB. 3V3 and 3V3b supply 3.3 V, 5V supplies 5 V, and the three grounds are the return.

The LED is the other way around, and there is no button

PC13 carries the on-board green LED with its anode to 3.3 V through 1 k and its cathode on the pin. It lights when PC13 is driven low. 1 k rather than the Black Pill's 470 ohms, which is why a Blue Pill's LED is the dimmer of the two, and PC13 to PC15 sit on the backup power domain and can sink only 3 mA between them: they drive an indicator and not much else.

There is no user button. The Blue Pill's one button is RESET. A sketch that wants a button needs one on the breadboard, which is why so many Blue Pill tutorials start by wiring one.

Why your sketch cannot drive PA15, PB3 or PB4

The SWJ debug port holds them out of reset: PA15 and PB4 pulled up, PB3 floating. Write SWJ_CFG in AFIO_MAPR once in setup() and they are yours. This is the most common surprise on the board and the model reproduces it rather than hiding it.

What is modeled

GPIO on ports A to C through CRL and CRH, TIM1 to TIM4 in their counting and PWM modes, USART1 on PA9 and PA10 wired to the serial monitor, a twelve-bit ADC1 single conversion on ten pins at the part's own conversion rate, AFIO and EXTI, SysTick and the NVIC, and enough of RCC to answer the register reads a program makes on the way up.

Every peripheral on a real STM32 starts with its clock switched off, and that is true here: enabling the clock before touching a peripheral is part of the exercise, not a formality this model skips.

What is not

The clock tree and flash latency, DMA, USB, CAN, I2C, SPI, the RTC and the backup registers, the watchdogs, ADC2, the ADC's injected group and analog watchdog, TIM1's break input and complementary outputs, input capture, the low-power modes, the option bytes and flash programming. Their registers are unmapped, so touching one is a bus fault rather than a silent zero.

Vendor stacks (the STM32Cube HAL, libopencm3 and the STM32duino core) are out of scope for the same reason the Pico SDK is: they bring up hardware that is not here. Write the sketch against the runtime and press Run.

The clock tree not being modeled cuts both ways. The core runs at 72 MHz whatever RCC is programmed to, so a sketch that forgets to start the PLL keeps time here and runs nine times slow on a real board. ADC1 has no error in it either: no sample-and-hold, no nonlinearity, no noise and no offset, and ADC_CR2's calibration bit is accepted and does nothing. And the 3V3 and 5V pins are ideal sources that cannot sag, which matters on this board more than most: a clone Blue Pill's regulator is frequently the wrong part, and that is a failure nothing here can show you.

The register tables are in the STM32 Blue Pill model, whose section 7 sorts every address and every approximation.

Stock Arduino libraries

A tutorial that includes Servo.h, Wire.h, SPI.h, EEPROM.h, LiquidCrystal_I2C.h, Adafruit_GFX.h with Adafruit_SSD1306.h and DHT.h compiles here as it stands. Each is Mokxi's own header under the upstream name, written on the drivers for the parts in the bin, and none of it is the upstream library's code.

  • Wire.begin() puts the I2C bus on PB7 (SDA) and PB6 (SCL).
  • EEPROM.h works, but this board's model has no EEPROM or writable flash, so the bytes live in 4 KB of RAM: they read back within a Run and are gone at a reset.
  • Adafruit_NeoPixel.h stops with a message: a WS2812 bit is too short to make by hand on this board, and only the ESP32-C3 and ESP32-C6 drive the strip.

The code editor and compiling lists what each one covers and how it differs from the upstream library.

The examples

Blink, Button, Fade and Serial.

Elsewhere