chap3 gpio addr reg
DESCRIPTION
STM32F4TRANSCRIPT
Chapitre 3Chapitre 3
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 -> Archit ecture 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 B us 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.
I-bus
Fla
sh
I/
FFla
sh
I/
F
Bu
sM
atr
ixB
usM
atr
ix
System
D-busCORTEX-M4
Master 1
CORTEX-M4Master 1
GP-DMAMaster 2
GP-DMAMaster 2
SRAMSlave
SRAMSlave
FLASHFLASH
Fla
sh
I/
FFla
sh
I/
F
AHB-APB2AHB-APB2
AHB-APB1AHB-APB1
AHB
Bridges
APB1
APB2
ArbiterPeripheral Bus APB1 Peripheral Bus APB1
Peripheral Bus APB2
Architecture détaillée d’un STM32 F40x
CORTEXTM-M4 CPU24 MHz
FSMCSRAM/ NOR/ LCD parallel interface
JTAG/SW Debug
Power SupplyReg 1.8V
POR/PDR/PVD
DMA
Nested vect IT Ctrl
1 x Systick Timer
AR
M ®
Lite
Hi-S
peed
36u
sM
atrix
/ A
rbite
r (m
ax 2
4MH
z) XTAL oscillators32KHz + 4~25MHz
Int. RC oscillators40KHz + 8MHz
PLL
24KB-32kB SRAM
Fla
sh I/
F
256KB-512kBFlash Memory
84B Backup Data
AR
M®
Per
iphe
ral B
us(m
ax 2
4MH
z)
2 x I2C
4 x USART/LINSmartcard / IrDaModem Control
51/80/112 I/Os
Up to 16 Ext. ITs
DMAup to 12 Channels
1 x USART/LINSmartcard/IrDaModem Control
1 x SPI
Bridge
Bridge
AR
M
Mat
rix /
Arb
iter
RTC / AWU
ARM® Peripheral Bus(max 24MHz)
Clock Control
2-channel 12-bit DAC
1 x 12-bit ADCup to 16 channels
Temperature Sensor
2 x Watchdog(independent & window)
10 x 16-bit Timer
2 x SPI
1 x CEC1 x 16-bit PWM Synchronized AC Timer
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/
7
– Circle OS (couche applicative de l’OS circleOS)
– La plupart des outils sont bâtis autour de CMSIS - C ortex MicrocontrollerSoftware Interface Standard: http://www.keil.com/pack/doc/CMSIS/General/html/ind ex.html
� 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 ) 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 d ans 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)
Address offset: 0x0C
GPIO port pull-up/pull-down register (GPIOx_PUPDR) (x = A..I/)
GPIO port input data register(GPIOx_IDR) (x = A..I)
GPIO port output data register(GPIOx_ODR) (x = A..I)
� GPIO port bit set/reset register� (GPIOx_BSRR) (x = A..I)
� GPIO port configuration lock register�(GPIOx_LCKR ) (x = A..I)
Les Autres Registres GPIO
�(GPIOx_LCKR ) (x = A..I)
� GPIO alternate function low register �(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 « ReferenceManual » 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 datasheetSTM32F40x
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_ODRGPIOA_AFRHGPIOB_PUPDR
28
GPIOB_PUPDR
Exemples de calcul des adresses
Calculer les adresses des registres suivants:
GPIOC_ODR = GPIOC_BASE + OFFSET_ODR = 0x4002 0800 + 0x14= 0x4002 0814
29
= 0x4002 0814
GPIOA_AFRH = GPIOA_BASE + OFFSET_AFRH= 0x4002 0000 + 0x24 = 0x4002 0024
GPIOH_PUPDR = 0x4002 1C00 + 0x0C= 0x4002 1C0C
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_AHB1RSTR = @base_RCC + @offset AHB1RSTR� = 0x4002 3800 + 0x10 = 0x4002 3810
RCC AHB1 peripheral reset register(RCC_AHB1RSTR)
�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 PD12connecté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: GPIOD adresse de base:RCC adresse de base:0x4002 3800
AHB1ENR: @offset= 0x30
@ AHB1ENR = 0x40023830
GPIOD adresse de base:@ 0x4002 0C00
MODREG : @offset= 0x00
ODR: @offset= 0x14
@ DMODREG = 0x40020C00
@DODR= 0x40020C14
AHB1RSTR: @offset= 0x10
@ AHB1RSTR = 0x40023810
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;
volatile unsigned int * PUPPDR = (unsigned int *) 0x40020C0C;
//RCC_AHB1ENR
volatile unsigned int *AHB1_ENR =(unsigned int*) 0x40023830; //RCC_AHB1ENRvolatile unsigned int *AHB1_RSTR =(unsigned int*) 0x40023810;
Remarque : volatile neutralise l’effet de l’optimisation (taille du cod e + Speed) sur les variables déclarées. Ici les @ des registres.
Configurer les PD12 en mode General Purpose Output Push Pull (GP Output 50 Mhz):
Principe de programmation des registres (4/5)ETAPE 3: Lecture/écriture dans les registres
Mettre le Bit3 de AHB1_RSTR à 1 puis 0Mettre le Bit3 de AHB1_ENR à 1
Réinitialiser le GPIODActiver l’horloge de GPIOD
Bits [25 -24] Bit [12] =0 Bits [25 -24] Bits [25 -24] Bits [25 -24] =01
Bit [12] =0 Bits [25 -24] =01=50Mhz
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;
…..….….…..…..…..
// SPEED = 50 Mhz bits 25-24 = 0-1*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;
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
Principe de programmation des registres (5/5)ETAPE 3 suite: Lecture/écriture dans les registres
Ecriture dans le registre DODR
Désactiver l’état de la sortie PD12 :Mettre le bit 12 à 0 dans le registre EODR
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;
volatile unsigned int * AHB1_ENR = (unsigned int *) 0x40023830;
//RCC_AHB1ENR//RCC_AHB1ENR
volatile unsigned int * AHB1_RSTR = (unsigned int *) 0x40023810;
//RCC_AHB1ENR
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
// SPEED = 50 Mhz bits 25-24 = 0-1
*DSPEED &= 0xFCFFFFFF;
*DSPEED |= 0x01000000;
// Bits 25-24 = 00
*PUPPDR &= 0xFCFFFFFF;
while(1){// Enable GPIOD Clock
*AHB1_ENR |= 1<<3;
// Configuration MODREG
// bits 25-24 = 01
*MODREG &= 0xFCFFFFFF;
*MODREG |= 0x01000000;
// Bit 12 = 0
*DOTYPE &= ~(1<<12);
while(1){
*DODR |= 1<<12;
tempo(0xffffff);
*DODR &= ~(1<<12);
tempo(0xffffff);
}
}
Clignotez les 4 LEDS en même Clignotez les 4 LEDS en même temps? ? temps? ?
Défiler les 4 Défiler les 4 ledsleds ??
Utiliser le bouton USER pour Utiliser le bouton USER pour inverser les inverser les ledsleds deux à deux à deux à deux à
chaque chaque appui appui ? ?