🛠 Bare metal total : clignoter PC13 en écrivant aux registres (CMSIS)
Le principe
Un STM32F103, c'est une carte de registres mémoire. Tout firmware, du plus gros projet Cube au plus petit blink, se réduit à : activer l'horloge du périphérique, configurer les broches, écrire des bits. Les définitions utilisées ici proviennent uniquement de l'en-tête CMSIS officiel de ST, stm32f103xb.h (dépôt STMicroelectronics/cmsis_device_f1).
Le code complet
/* Blink PC13 nu — arm-none-eabi-gcc -mcpu=cortex-m3 -O1 blink.c
-nostartfiles -T flash.ld */
#include <stm32f1xx.h> /* en-tête CMSIS device (ST) */
static void delay(void) { for (volatile int i = 0; i < 4000000; i++) __NOP; }
int main(void)
{
/* 1. GPIOC est sur APB2 : activer sa porte d'horloge. */
RCC->APB2ENR |= RCC_APB2ENR_IOPCEN;
/* 2. Config PC13 dans CRH (broches 8..15), champs bits 23:20.
CNF13 = 00 (push-pull), MODE13 = 11 (sortie, 2 MHz max sur PC13). */
GPIOC->CRH = (GPIOC->CRH & ~(0xFu << 20)) | (0x3u << 20);
while (1) {
GPIOC->BRR = (1u << 13); /* bit LOW -> LED ALLUMÉE (câblage sink) */
delay;
GPIOC->BSRR = (1u << 13); /* bit HIGH -> LED ÉTEINTE */
delay;
}
}
Les quatre notions à retenir
- Portes d'horloge : chaque périphérique a son bit dans
RCC->APB2ENR(GPIOC, USART1, SPI1, ADC1…) ouAPB1ENR(USART2/3, SPI2, CAN1, les timers…). Oublier cette ligne est le bug bare-metal n°1 : les registres semblent lire 0 et rien ne bouge. - CRH/CRL : sur F1, chaque broche GPIO se configure par 4 bits (MODE+CNF) dans CRL (broches 0–7) ou CRH (8–15). PC13 tombe dans CRH, bits 23:20.
- BSRR/BRR : écritures atomiques sur ODR sans lecture-modification-écriture — sûr même si une interruption touche le même port.
- Le câblage de la LED : la LED utilisateur étant entre VCC et PC13 (mode sink, stm32-base), c'est BRR (mettre à 0) qui l'allume.
Limites de PC13
La broche PC13 est une broche de commande à capacité réduite sur F103 — d'où le mode sortie 2 MHz dans tous les exemples.
Pour aller plus loin : le lien flash.ld (flash à 0x8000000, 64 Ko ; RAM 20 Ko), un vector table correcte, et le démarrage par Reset_Handler — ou laissez CubeMX générer ces bases, puis lisez-les ligne par ligne.
Autres tutoriels pour cette carte
- Découvrir la Blue Pill : que trouve-t-on dans la boîte ?
- Premier programme Arduino sur la Blue Pill (core officiel stm32duino)
- Alimenter et flasher la Blue Pill : BOOT0, port série, ST-Link et DFU
- Série, ADC et chasse aux contrefaçons : diagnostiquer sa Blue Pill
- Dompter l'USB natif de la Blue Pill : CDC, DFU et la résistance rebelle
- Passer au niveau supérieur : STM32CubeIDE, HAL et LL sur F103