Chapitre 22 Chapitre
PERIPHERIQUE 1: Programmation bas PERIPHERIQUE 1: Programmation bas
niveau des GPIOs
Objectifs
Utiliser le C embarqué pour:
– Définir les registres relatifs au GPIO par un code en langage C
– Adresser les différents registres
– Manipuler entièrement ou par bits les registres
– Programmer les registres de STM32 par adressage de ses registres en se
référant au mapping de mémoire (Memory Map)
Plateforme embarquée à utiliser: STM32 F4Discovery
4
Architecture de l’STM32
Architecture de type RISC (Reduced Instructions Set Computer) Bus des Instructions
et bus des Données sont séparés -> Architecture Harvard.
CPU CortexM4 fait le calcul à la cadence du Bus (AHB: ARM Hi-Speed Bus).
Les périphériques, moins rapides, sont montés sur les Bus APB1 et APB2.
Dans le cas d’un tansfert DMA (Direct Memory Acces) c-à-d d’une adresse mémoire ou
d’un périphérique vers un autre, le DMA devient le maître du bus AHB.
CORTEX-M4 CORTEX-M4 Master 1 Master 1
D-bus
System
I-bus I-bus
B B u u s s M M a a t t r r i i x x
F F / / I I h h s s a a l l F F
FLASH FLASH
SRAM SRAM Slave Slave
GP-DMA GP-DMA Master 2 Master 2
AHB
AHB-APB2 AHB-APB2
AHB-APB1 AHB-APB1
Arbiter
Bridges
APB2
APB1
Peripheral Bus APB2
Peripheral Bus APB1 Peripheral Bus APB1
Architecture détaillée d’un STM32 F40x
CORTEXTM-M4 CPU 24 MHz
JTAG/SW Debug
Nested vect IT Ctrl
1 x Systick Timer
DMA up to 12 Channels
1 x 16-bit PWM Synchronized AC Timer
Up to 16 Ext. ITs
51/80/112 I/Os
1 x SPI
1 x USART/LIN Smartcard/IrDa Modem Control
F
/ I
h s a l F
256KB-512kB Flash Memory
24KB-32kB SRAM
84B Backup Data
FSMC
SRAM/ NOR/ LCD parallel interface
Clock Control
Bridge
ARM® Peripheral Bus
(max 24MHz)
10 x 16-bit Timer
2 x Watchdog (independent & window)
2-channel 12-bit DAC
1 x 12-bit ADC up to 16 channels
Temperature Sensor
s u 6 3 d e e p S
- i
H e t i L ® M R A
) z H M 4 2
Publicité
x a m
(
r e t i b r A
/ x i r t a M
Bridge
s u B
l a r e h p i r e P ® M R A
) z H M 4 2
x a m
(
Power Supply Reg 1.8V POR/PDR/PVD
XTAL oscillators 32KHz + 4~25MHz
Int. RC oscillators 40KHz + 8MHz
PLL
RTC / AWU
1 x CEC
4 x USART/LIN Smartcard / IrDa Modem Control
2 x SPI
2 x I2C
Tools and Software
Outils de développements
– IAR Embedded Workbench
– kEIL µVision IDE
– Raisonnance Ride7
– MikroC Pro for ARM
– CooCox (riche en exemples)
L’outil à utiliser: http://www.keil.com/uvision/
– Circle OS (couche applicative de l’OS circleOS)
– La plupart des outils sont bâtis autour de CMSIS - Cortex Microcontroller
Software Interface Standard: http://www.keil.com/pack/doc/CMSIS/General/html/index.html
7
E/S bidirectionnels de STM32
GPIO standard (tolère une valeur de 5v en entrée) et génère une sortie de 3v
GPIOs délivre un courant 25mA
Temps de montée en sorite configurable (max 50 MHz)
Toutes les broches peuvent être programmeés comme entrée analogique
Toutes les broches peuvent être programmeés en fonctions alternés (USARTx, TIMx, I2Cx, SPIx,…)
Toute entrée pourrait être configurée comme source d’interruption
9 ports de GPIO standard (GPIOA..GPIOI) (1 port = 16 broches d’E/S)
Registres de contrôle des GPIOs
Pour la manipulation des 9 GPIOx(x=A..I), nous avons recours à l’utilisation
des registres de contrôle suivants :
– GPIOx_MODER : registre utilisé pour sélectionner la direction (Entrée ou Sortie),
Fonction alternée et analogique (input, output, AF, analog)
– GPIOx_OTYPER : Registre utilisé pour sélectionner le type de sortie PP(pushpull – GPIOx_OTYPER : Registre utilisé pour sélectionner le type de sortie PP(pushpull
) ou OD (open-drain)
– GPIOx_OSPEEDR : Registre utilisé pour sélectionner la vitesse quelque soit la
direction I/O
– GPIOx_PUPDR : Registre utilisé pour la sélection du mode PU ou PD ( pull-
up/pull-down) quelque soit la direction I/O
Registres des données
– GPIOx_IDR (x=A..I): récupérer les données entrantes du
port x, accédé en lecture seule
– GPIOx_ODR (x=A..I): envoyer les données en sorties du
port x, accédé en écriture et en lecture
Rq: Il existe d’autres registres GPIO non traités dans ce
chapitre
GPIO port mode register (GPIOx_MODER) (x = A..I)
GPIO port output type register (GPIOx_OTYPER) (x = A..I)
GPIO port output speed register (GPIOx_OSPEEDR) (x = A..I)
GPIO port pull-up/pull-down register (GPIOx_PUPDR) (x = A..I/)
Address offset: 0x0C
GPIO port input data register (GPIOx_IDR) (x = A..I)
GPIO port output data register (GPIOx_ODR) (x = A..I)
Les Autres Registres GPIO
GPIO port bit set/reset register (GPIOx_BSRR) (x = A..I)
GPIO port configuration lock register
(GPIOx_LCKR) (x = A..I) (GPIOx_LCKR) (x = A..I)
GPIO alternate function low register
Publicité
(GPIOx_AFRL) (x = A..I)
GPIO alternate function high register
(GPIOx_AFRH) (x = A..I)
L’adresse d’un registre d’un périphérique donnée est la somme de: l’adresse de base d’un périphérique l’adresse d’offset du registre
l’adresse de base du périphérique est définie dans le memory map (Table 10 page 71 du datasheet STM32F40x) (Table 10 page 71 du datasheet STM32F40x)
Les adresses d’offset des registres sont définies dans la description des registres du RM (Table 32 pages 203/204 du fichier « Reference Manual » de STM32F40x)
Remarque: Les adresses de base des GPIOs et d’offset des principaux registres sont présentées par la suite
Memory MAP: Table 10 page 71 du datasheet STM32F40x
Adresses de base des PORTS d’E/S (GPIOs)
@ d’offset des registres GPIOs Table 32 pages 203/204 du « Reference Manual » de STM32F40x
Suite …
Suite …
Exemples de calcul des adresses
Calculer les adresses des registres suivants:
GPIOC_ODR GPIOA_AFRH GPIOB_PUPDR GPIOB_PUPDR
28
Exemples de calcul des adresses
Calculer les adresses des registres suivants:
GPIOC_ODR = GPIOC_BASE + OFFSET_ODR = 0x4002 0800 + 0x14 = 0x4002 0814 = 0x4002 0814
GPIOA_AFRH = GPIOA_BASE + OFFSET_AFRH = 0x4002 0000 + 0x24 = 0x4002 0024
GPIOH_PUPDR = 0x4002 1C00 + 0x0C
= 0x4002 1C0C
29
RCC ( Reset Clock Control) est le contrôleur de la circuiterie de Reset et d’horloge.
Permet de synchroniser les trois bus du Cortex-M4 (AHB, APB1 et APB2) avec le bus interne du système: le bus matrix
Les GPIOs sont montés sur le bus AHB1. Tout GPIO(composant en général) doit être activé par RCC avant utilisation.
L’avantage de RCC est la possibilité d’activer, suivant le besoin de l’application, les composants nécessaires à l’application.
En conséquent, une meilleure gestion de la consommation du système embarqué.
RCC AHB1 peripheral clock enable register (RCC_AHB1ENR)
RCC AHB1 peripheral clock enable register (RCC_AHB1ENR) @ RCC_AHB1ENR = @base_RCC + @offset AHB1ENR
= 0x4002 3800 + 0x30 = 0x4002 3830
RCC AHB1 peripheral reset register (RCC_AHB1RSTR)
@ RCC_AHB1RSTR = @base_RCC + @offset AHB1RSTR
= 0x4002 3800 + 0x10 = 0x4002 3810
Ce registre permet de remettre à l’état initial le périphérique à utiliser par une écriture de 1. Suite à cette écriture de 1, il faut écrire 0 pour que le périphérique sorte de son état de reset.
Applications: 4 Leds et Bouton utilisateurs de STM32f4Discovery
TP1: Clignotement de la LED connectée au PD12 connectée au PD12
Principe de programmation des registres (1/5)
Un programme C qui utilise uniquement les registres d’un périphérique pourrait être vu comme étant une fonction des registres mis en jeu.
PROG = f(registres)
La programmation dans ce cas consiste à : La programmation dans ce cas consiste à :
ETAPE 1: Définir les registres à utiliser: chaque registre est équivalent
à une adresse donc un pointeur en langage C
ETAPE 2: Initialiser ces pointeurs par les adresses adéquates
ETAPE 3: Lecture et/ou écriture des contenus des registres
- Lecture: lire l’état du système
- Ecriture: commander le système
Principe de programmation des registres (2/5) ETAPE 1: Définir les adresses des registres
Les périphériques à utiliser dans notre cas sont :
RCC (Reset and Clock Control): pour l’activation de l’horloge
- Le registre à utiliser de l’RCC est RCC_AHB1ENR + RCC_AHB1RSTR
GPIOD: pour commander la broche PD12 connectée au LED4
- Les registres à utiliser du périphérique GPIOD sont MODREG , DOTYPE , DSPEED, PUPPDR et ODR (de même pour les autres)
RCC adresse de base: RCC adresse de base: 0x4002 3800
GPIOD adresse de base: GPIOD adresse de base: @ 0x4002 0C00
AHB1ENR: @offset= 0x30
AHB1RSTR: @offset= 0x10
MODREG : @offset= 0x00
ODR: @offset= 0x14
@ AHB1RSTR = 0x40023810
@ DMODREG = 0x40020C00
@ AHB1ENR = 0x40023830
@DODR= 0x40020C14
Principe de programmation des registres (3/5) ETAPE 2: définir des pointeurs et les initialiser
Définition et initialisation des pointeurs des registres
volatile unsigned int* MODREG = (unsigned int *) 0x40020C00;
volatile unsigned int * DOTYPE = (unsigned int *) 0x40020C04;
volatile unsigned int * DSPEED = (unsigned int *) 0x40020C08;
volatile unsigned int * DODR = (unsigned int *) 0x40020C14; volatile unsigned int * DODR = (unsigned int *) 0x40020C14;
Publicité
volatile unsigned int * PUPPDR = (unsigned int *) 0x40020C0C;
//RCC_AHB1ENR
volatile unsigned int *AHB1_ENR =(unsigned int*) 0x40023830; //RCC_AHB1RSTR volatile unsigned int *AHB1_RSTR =(unsigned int*) 0x40023810;
Remarque: volatile neutralise l’effet de l’optimisation (taille du code + Speed) sur les variables déclarées. Ici les @ des registres.
Principe de programmation des registres (4/5) ETAPE 3: Lecture/écriture dans les registres
Réinitialiser le GPIOD Activer l’horloge de GPIOD
Mettre le Bit3 de AHB1_RSTR à 1 puis 0 Mettre le Bit3 de AHB1_ENR à 1
Configurer la PD12 en mode General Purpose Output Push Pull (GP Output 50 Mhz):
Bits [25-24] Bit [12] =0 Bits [25-24] Bit [12] =0 =01
Bits [25-24] Bits [25-24] =01=50Mhz
Bits [25-24] Bits [25-24] =01
Principe de programmation des registres (4/5) ETAPE 3: Lecture/écriture dans les registres (suite …)
int main() {
// SET GPIOD DENIT
*AHB1_RSTR |= 1<<3;
// RESET GPIOD DENIT
*AHB1_RSTR &= ~(1<<3);
….. …. …. ….. ….. …..
// Enable GPIOD Clock *AHB1_ENR |= 1<<3; *AHB1_ENR |= 1<<3;
// Configuration MODREG
// bits 25-24 = 01 *MODREG &= 0xFCFFFFFF; *MODREG |= 0x01000000; // Bit 12 = 0 *DOTYPE &= ~(1<<12);
// SPEED = 50 Mhz bits 25-24 = 0-1 // SPEED = 50 Mhz bits 25-24 = 0-1
*DSPEED &= 0xFCFFFFFF; *DSPEED |= 0x01000000;
// Bits 25-24 = 00 *PUPPDR &= 0xFCFFFFFF;
Principe de programmation des registres (5/5) ETAPE 3 suite: Lecture/écriture dans les registres
Activer l’état de la sortie PD12 :
Mettre le bit 12 à 1 dans le registre DODR
Insérrer un delay en utilisant la boucle for
Ecriture dans le registre DODR
Désactiver l’état de la sortie PD12 :
Mettre le bit 12 à 0 dans le registre DODR
Insérrer un delay en utilisant la boucle for
Ecriture dans le registre DODR
Principe de programmation des registres (5/5) ETAPE 3: Lecture/écriture dans les registres (suite …)
while(1){
*DODR |= 1<<12; tempo(0xffffff);
*DODR &= ~(1<<12); tempo(0xffffff);
}
Code complet de l’application (1/2)
volatile unsigned int * MODREG = (unsigned int *) 0x40020C00; volatile unsigned int * DOTYPE = (unsigned int *) 0x40020C04; volatile unsigned int * DSPEED = (unsigned int *) 0x40020C08; volatile unsigned int * DODR = (unsigned int *) 0x40020C14; volatile unsigned int * PUPPDR = (unsigned int *) 0x40020C0C;
//RCC_AHB1ENR //RCC_AHB1ENR volatile unsigned int * AHB1_ENR = (unsigned int *) 0x40023830;
//RCC_AHB1RSTR volatile unsigned int * AHB1_RSTR = (unsigned int *) 0x40023810;
void tempo(volatile unsigned int CNT){
for(; CNT > 0 ;CNT --);
}
Code de l’application (2/2)
int main() { // SET GPIOD DENIT
*AHB1_RSTR |= 1<<3; // RESET GPIOD DENIT *AHB1_RSTR &= ~(1<<3);
// Enable GPIOD Clock
*AHB1_ENR |= 1<<3; // Configuration MODREG
// bits 25-24 = 01
*MODREG &= 0xFCFFFFFF; *MODREG |= 0x01000000; // Bit 12 = 0 *DOTYPE &= ~(1<<12);
// SPEED = 50 Mhz bits 25-24 = 0-1 *DSPEED &= 0xFCFFFFFF; *DSPEED |= 0x01000000;
// Bits 25-24 = 00 *PUPPDR &= 0xFCFFFFFF;
while(1){
*DODR |= 1<<12; tempo(0xffffff); *DODR &= ~(1<<12); tempo(0xffffff);
}
}
LEDS en même Clignotez les 4 4 LEDS en même Clignotez les temps? ? temps? ?
Défiler les 4 4 leds Défiler les
leds ??
Utiliser le bouton USER pour Utiliser le bouton USER pour
inverser les leds inverser les
deux à deux à leds deux à deux à
chaque appui ? chaque appui ?