Blue Pill - Sources d'horloge

Table des matières

TL;DR

Configuration des sources d'horloge. Pas très digeste.

L'horlogier (arbre sur lequel pousse les horloges)

Le manuel de référence, page 93, présente une vue de cet arbre singulier. Ce n'est pas ce qu'il y a de plus digeste, aussi je vais essayer de simplifier: SYSCLK peut donc valoir:
  1. HSI
  2. HSI / 2 * PLLMUL
  3. HSE
  4. HSE / 2 * PLLMUL
  5. HSE * PLLMUL
J'utilise 1) pour faire clignoter des LEDs car il n'y a aucune configuration à faire et aucun besoin de précision. A mon humble avis de moi que j'ai le cristal à 8 MHz de la Blue Pill rend 2) sans grand intéret. Je pense que 4) sert à réduire la consommation électrique mais je ne suis pas encore assez outillé pour faire ce genre de mesure. Pour basculer sur HSE:
RCC->CR |= RCC_CR_HSEON;                   // set High Speed External ON (== enable)
while ( !(RCC->CR & RCC_CR_HSERDY) );      // wait for High Speed External ReaDY flag
RCC->CFGR &= ~RCC_CFGR_SW;                 // reset system clock SWitch
RCC->CFGR |=  RCC_CFGR_SW_HSE;             // SWitch to HSE
while ( !(RCC->CFGR & RCC_CFGR_SWS_HSE) ); // wait for SWitch Status to HSE
On peut maintenant connecter l'hyperpropulseur:
RCC->CFGR |=  RCC_CFGR_PLLSRC;             // set PLL SouRCe to HSE
RCC->CFGR &= ~RCC_CFGR_PLLMULL;            // reset PLL MULtipLication
RCC->CFGR |=  RCC_CFGR_PLLMULL9;           // set light speed
RCC->CR   |=  RCC_CR_PLLON;                // set PLL ON (== enable)
while ( !(RCC->CR & RCC_CR_PLLRDY) );      // wait for the PLLReaDY flag
RCC->CFGR &= ~RCC_CFGR_SW;                 // reset system clock SWitch
RCC->CFGR |=  RCC_CFGR_SW_PLL;             // SWitch to PLL
while ( !(RCC->CFGR & RCC_CFGR_SWS_PLL) ); // wait for SWitch Status to PLL
et voilà une Blue Pill qui passe en vitesse lumière (HSE à 8 MHz * PLLMULL9 == 72 MHz, soit le maximum supporté). Oui mais non, ça pas marche. C'est quoi ce bordel, Chewie ? Comme toujours, ce n'est pas du côté obscur de la Force qu'il faut regarder mais le manuel de référence, page 58 où on apprend que l'accès à la FLASH (donc au code) est dépendant de SYSCLK: C'est dans le registre ACR (Access Control Register, page 60) qu'il faut placer la valeur adéquate AVANT d'activer la PLL:
...
FLASH->ACR |= FLASH_ACR_LATENCY_2; // 2 wait states !!! REQUIRED !!!
RCC->CR    |=  RCC_CR_PLLON;       // set PLL ON (== enable)
...
Pour ne rien arranger, APB1 ne pouvant pas dépasser 36 MHz, il faut régler son diviseur en conséquence:
RCC->CFGR |= RCC_CFGR_PPRE1_2; // div SYSCLK by 2 == 72 MHz / 2 == 36 MHz
Histoire d'enfoncer le clou, le composant ADC est limité à 14 MHz:
RCC->CFGR |= RCC_CFGR_ADCPRE_DIV6; // div SYSCLK by 6 == 72 MHz / 6 == 12 MHz
Le coup de grâce est porté par les TIMERs mais je préfère m'arrêter là. On l'aura compris, modifier la fréquence ne se fait pas sur un coup de tête.

Projet

Faire clignoter plus ou moins vite la LED intégrée à la carte suivant la source de SYSCLK: La sélection de la source se fait depuis le Makefile:
...
#CFLAGS += -DUSE_HYPERDRIVE
#CFLAGS += -DUSE_LIGHT_SPEED
Le code source complet: https://gitlab.com/dsx/blue-pill/-/tree/master/stm32f103c8t6/01_clocks_hse_pll

Il est à noter que c'est bien le registre SWS qui est testé:

Set and cleared by hardware to indicate which clock source is used as system clock
Ne pas hésiter à triturer ce code: modifier les valeurs de multiplication, ne pas configurer correctement la FLASH ...

A suivre

Passer d'une source d'horloge à une autre: Changer la sourcde d'horloge

A retenir

Utiliser HSE pour plus de précision. Réfléchir à deux fois avant de vouloir passer à des vitesses supérieures: utiliser PLL passe au minimum à 16 MHz, supérieur au 14 MHz max de l'ADC.