Interlude : horloges / CMSIS

Horloges

Lorsque l'on démarre un processeur, une des premières choses à faire est de configurer les différents éléments intervenant dans la génération des horloges afin d'obtenir les différentes fréquences d'horloges désirées.

Dans le processeur utilisé sur vos cartes de TP, le coeur et les périphériques utilisent des horloges différentes. Le schéma de la manuel de référence page 208 détaille les différentes sources d'horloge et les différents composants intervenant dans la génération des horloges utilisées au sein de la puce.

Comme vous pouvez le constater, c'est un sujet complexe. Mais pour la suite du TP, nous allons avoir besoin d'avoir des horloges précises (notamment pour l'UART et les timers).

Pour l'instant nous allons vous donner un fichier objet contenant une fonction void clocks_init(void), qui initialise les horloges ainsi :

  • SYSCLK: 80MHz
  • PCLK1 : 80MHz
  • PCLK2 : 80MHz
  • LSE : 32.768kHz
  • HSI / LSI : inutilisées
  • MSI : 4MHz

Récupérez-donc le fichier clocks.tgz, décompressez-le, puis comittez-le dans votre dépôt (oui, pour une fois vous avez le droit de committer un objet ! :) ).

Appelez la fonction clocks_init() au début de votre main. Puis passez à la suite. Ce n'est qu'à la fin du TP que vous ferez vous-même l'initialisation des horloges.

Attention, votre processeur fonctionne maintenant à pleine vitesse (80MHz au lieu de 4MHz), donc vos LED clignotent 20 fois plus vite !

CMSIS

ARM a défini un standard d'écriture de code pour s'interfacer avec le processeur et les périphériques : le Cortex Microcontroller Software Interface Standard (CMSIS). Cela permet d'écrire du code réutilisable facilement, portable entre différent Cortex et de faciliter la conception et l'utilisation de bibliothèques. Le CMSIS contient aussi du code, dont des headers, des drivers, un OS temps-réel (RTOS), etc. 

Jusqu'à présent, vous avez défni vous-même vos registres à la main et souvent utilisé des constantes numériques pour initialiser / modifier des registres. Cela n'est pas pratique : pour vérifier / débugger votre code, on doit sns cesse se reporter à la documentation pour vérifier ces constantes.

Les constructeurs utilisant des coeurs ARM ont l'obligation de fournir des headers au standard CMSIS spécifiques à leurs microcontrôleurs, nommant les différents objets selon des règles bien précises. Pour ST, on les trouve sur leur site web ou dans un outil appelé STM32CubeMX. Téléchargez l'archive cmsis.tgz en bas de cette page, et décompressez-la à la racine de votre projet. Elle contient des définitions d'accès aux différents Cortex ainsi qu'un fichier spécifiant tous les registres et les bits du STM32L475 : stm32l475xx.h.

Le nommage des registres / bits est extrêmement simple et clair. Les noms sont exactement les mêmes que dans la datasheet.

Exemple 1

Si on cherche à modifier le bit USART1RST dans le registre APB2RSTR du bloc de contrôle des horloges et du reset, le RCC : 

  • le registre est RCC->APB2RSTR
  • le bit est RCC_APB2RSTR_USART1RST

On peut donc écrire : RCC->APB2RSTR |= RCC_APB2RSTR_USART1RST;  

Exemple 2

Vous avez aussi des masques (qui se finissent par Msk) et la position de chaque bit / champ de bits (qui se finit par Pos).

Si on cherche à mettre à zéro les 4 bits du champs USART1SEL dans le registre CCIPR du RCC : 

RCC->CCIPR = RCC->CCIPR & ~RCC_CCIPR_USART1SEL_Msk;

Si on cherche à mettre 40 dans le champ PLLN du registre PLLCFGR du RCC, ainsi que mettre à 1 le bit MSI du même registre : 

RCC->PLLCFGR = (40 << RCC_PLLCFGR_PLLN_Pos) | RCC_PLLCFGR_PLLSRC_MSI;

Enfin, dans le fichier stm32l4xx.h, vous avez des macros bien pratiques que vous pouvez utiliser si vous le souhaitez. Si les noms ne parlent pas d'eux-mêmes, allez voir leur définition dans le fichier en question.

  • SET_BIT(REG, BIT)
  • CLEAR_BIT(REG, BIT)
  • READ_BIT(REG, BIT)

Les macros suivantes sont très discutables, nous ne les utiliserons donc PAS

  • CLEAR_REG(REG)
  • WRITE_REG(REG, VAL)
  • MODIFY_REG(REG, CLEARMASK, SETMASK)

À votre tour

Modifiez votre Makefile pour permettre à gcc d'accéder aux répertoires CMSIS/Device/ST/STM32L4xx/Include et CMSIS/Include. Puis modifiez votre code des LED de façon à utiliser les noms de registres / bits tels que définis dans le fichier stm32l475xx.h (qu'il faudra donc inclure dans les .c qui en ont besoin).

Fichier attachéTaille
Fichier clocks.tgz780 octets
Fichier cmsis.tgz295.86 Ko