1-STM32 GPIO Reg

Télécharger au format pdf ou txt
Télécharger au format pdf ou txt
Vous êtes sur la page 1sur 59

Chapitre-I STM32

Programmation GPIO par


adressage des registres
Plan

2
INTRODUCTION

3
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 plan mémoire (Memory Map)

– Utiliser les registres des bibliothèques et interpréter les


différences

4
Plateforme embarquée à utiliser:
STM32 F4Discovery

5
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’une périphérique vers une autre, le DMA devient le maître du bus AHB.

I-bus

Flash I/F
D-bus FLASH
CORTEX-M4
Master 1
System
BusMatrix

SRAM
Slave

APB2
Peripheral Bus APB2
AHB AHB-APB2
GP-DMA
Master 2 APB1
AHB-APB1
Peripheral Bus APB1
Arbiter Bridges

6
Architecture détaillée d’un STM32 F40x
CORTEXTM-M4 CPU
24 MHz

Flash I/F
256KB-512kB Power Supply
Reg 1.8V
Flash Memory
POR/PDR/PVD

Matrix / Arbiter (max 24MHz)


ARM ® Lite Hi-Speed 36us
24KB-32kB SRAM XTAL oscillators
32KHz + 4~25MHz

JTAG/SW Debug 84B Backup Data


Int. RC oscillators
Nested vect IT Ctrl 40KHz + 8MHz

1 x Systick Timer FSMC


SRAM/ NOR/ LCD parallel interface PLL

DMA RTC / AWU


up to 12 Channels Clock Control

ARM® Peripheral Bus


Bridge
(max 24MHz)

Bridge
1 x 16-bit PWM Synchronized AC Timer
10 x 16-bit Timer
1 x CEC
ARM® Peripheral Bus

Up to 16 Ext. ITs 2 x Watchdog


(max 24MHz)

(independent & window)

51/80/112 I/Os 4 x USART/LIN


2-channel 12-bit DAC Smartcard / IrDa
Modem Control
1 x SPI
1 x 12-bit ADC
up to 16 channels 2 x SPI
1 x USART/LIN
Smartcard/IrDa
Modem Control Temperature Sensor 2 x I2C

7
Tools and Software
• Outils de
développements
– IAR Embedded Workbench
IDE à utiliser:
– kEIL µVision IDE
http://www.keil.com/uvision/
– Raisonnance Ride7
– MikroC Pro for ARM
– CooCox (riche en exemples)
– Circle OS (couche applicative de
l’OS circleOS)
– CubeMX: Outil graphique L’outil de configuration à
permettant de configurer un STM32
utiliser:
et générer le code associé.
http://www.st.com/en/develop
ment-tools/stm32cubemx.html
– La plupart des outils sont bâtis
autour de CMSIS - Cortex
Microcontroller Software Interface
Standard:
http://www.keil.com/pack/doc/CM
SIS/General/html/index.html
8
8
9
• 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 100 MHz)
Toutes les pines peuvent être programmeés comme entrée
analogique
Toutes les pines 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 pines d’E/S)
Push-Pull Open-Drain
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

15
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


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

20
GPIO port input data register
(GPIOx_IDR) (x = A..I)
GPIO port output data register
(GPIOx_ODR) (x = A..I)
Les Autres
Autres Registres
registres GPIOGPIO

 GPIO port bit set/reset register


 (GPIOx_BSRR) (x = A..I)

 GPIO port configuration lock register


(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)
CALCUL DES ADRESSES DES
REGISTRES GPIO

24
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 d’un périphérique est définie dans le memory map (Table
10 page 71 de la 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 de la datasheet STM32F40x

Adresses de base des


PORTS d’E/S (GPIOs)

26
@ 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

30
30
Exemples de calcul des adresses
Calculer les adresses des registres suivants:

GPIOC_ODR = GPIOC_BASE + OFSET_ODR


= 0x4002 0800 + 0x14
= 0x4002 0814

GPIOA_AFRH = GPIOA_BASE + PFSET_AFRH


= 0x4002 0000 + 0x24 = 0x4002 0024

GPIOH_PUPDR = 0x4002 1C00 + 0x0C


= 0x4002 1C0C
31
31
ACTIVATION DE L’HORLOGE
D’UN GPIO

32
RCC ( Reset Clock Control) est le contrôleur de la circuiterie de Reset est
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.
EXEMPLE DE PROGRAMMATION D’UN GPIO:
CLIGNOTEMENT DE LA LED CONNECTÉE AU PD12

36
Applications: 4 Leds et Bouton utilisateurs de
STM32f4Discovery
Principe de programmation des registres (1/5)

Un programme C qui utilise uniquement les registres d’une périphérique


pourrait être vu comme étant une fonction de registres mis en jeu.

PROG = f(registres)
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


- Les registres à utiliser de l’RCC est RCC_AHB1ENR + RCC_AHB1RSTR
GPIOD: pour commander la pine 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:


0x4002 3800 @ 0x4002 0C00

AHB1ENR: AHB1RSTR: MODREG : @offset= 0x00


@offset= 0x30 @offset= 0x10
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 * PUPPDR = (unsigned int *) 0x40020C0C;

//RCC_AHB1ENR
volatile unsigned int * AHB1_ENR =(unsigned int*) 0x40023830;
//RCC_AHB1ENR
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 Mettre le Bit3 de AHB1_RSTR à 1 puis 0
Activer l’horloge de GPIOD Mettre le Bit3 de AHB1_ENR à 1

Configurer les PD12 en mode General Purpose Output Push Pull


(GP Output 50 Mhz):

Bits [25-24] Bit [12] =0 Bits [25-24] Bits [25-24]


=01 =01=50Mhz =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
*DSPEED &= 0xFCFFFFFF;
// Configuration MODREG *DSPEED |= 0x01000000;
// bits 25-24 = 01
*MODREG &= 0xFCFFFFFF; // Bits 25-24 = 00
*MODREG |= 0x01000000; *PUPPDR &= 0xFCFFFFFF;
// Bit 12 = 0
*DOTYPE &= ~(1<<12);
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 Ecriture dans le
registre DODR
Insérrer un delay en utilisant la boucle for

Désactiver l’état de la sortie PD12 :


Mettre le bit 12 à 0 dans le registre EODR Ecriture dans le
registre DODR
Insérrer un delay en utilisant la boucle for
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;
volatile unsigned int * AHB1_RSTR=(unsigned int*) 0x40023810;

void tempo(volatile unsigned int CNT)


{
for(; CNT > 0 ;CNT --);
}
Code Complet de l’application (2/2)
int main() { // SPEED = 50 Mhz bits 25-24 = 0-1
// SET GPIOD DENIT *DSPEED &= 0xFCFFFFFF;
*AHB1_RSTR |= 1<<3; *DSPEED |= 0x01000000;
// RESET GPIOD DENIT // Bits 25-24 = 00
*AHB1_RSTR &= ~(1<<3); *PUPPDR &= 0xFCFFFFFF;
// Enable GPIOD Clock while(1)
*AHB1_ENR |= 1<<3; {
// Configuration MODREG *DODR |= 1<<12;
// bits 25-24 = 01 tempo(0xffffff);
*MODREG &= 0xFCFFFFFF; *DODR &= ~(1<<12);
*MODREG |= 0x01000000; tempo(0xffffff);
// Bit 12 = 0 }
*DOTYPE &= ~(1<<12); }
Clignotez les 4 LEDS en
même temps? ?
Défiler les 4 leds ?
Utiliser le bouton USER pour
inverser les leds deux à deux
à chaque appui ?
DÉFINITION DES REGISTRES DANS LA BIBLIOTHÈQUE DE
STM32

50
Interprétation des macros dans STM32F4xx.h
#define GPIOD ((GPIO_TypeDef *) GPIOD_BASE)
#define GPIOD_BASE (AHB1PERIPH_BASE + 0x0C00U)
#define AHB1PERIPH_BASE (PERIPH_BASE + 0x00020000U)
#define PERIPH_BASE 0x40000000U
 AHB1PERIPH_BASE sera remplacé par 0x40000000U + 0x00020000U = 0x40020000U. Le suffixe
U est utilisé pour forcer le compilateur à utiliser le type Unsigned int pour une constante.
 GPIOD_BASE sera alors remplacé par 0x40020000U + 0x0C00U = 0x40020C00U
 GPIOD par 0x40020C00U. Cette valeur sera convertie en une adresse sur GPIO_TypeDef:
#define GPIOD (GPIO_TypeDef *) 0x40020C00U

GPIOD: 0xX…XX…..X 0x40020C00U


…. ….. typedef struct {
__IO uint32_t MODER; /* Address offset: 0x00 */
0x40020C00U MODER
__IO uint32_t OTYPER; /* Address offset: 0x04 */
+0x04 OTYPER En Mémoire
__IO uint32_t OSPEEDR; / Address offset: 0x08 */
__IO uint32_t PUPDR; /* Address offset: 0x0C */
+0x08 OSPEEDR __IO uint32_t IDR; /* Address offset: 0x10 */
__IO uint32_t ODR; /* Address offset: 0x14 */
+0x0C PUPDR __IO uint32_t BSRR; /* Address offset: 0x18 */
+0x10 IDR ……
} GPIO_TypeDef;
+0x10 ODR
+0x14 BSRR #define __IO volatile 51
Suite ….
Chaque case est 32 bits (4 octets) d’où les offsets 0x04, 0x08 … 0x18.
Les adresses des registres étudiés en première partie sont alors vérifiées.
GPIOD est un pointeur sur la structure GPIO_TypeDef.
L’accès au champ IDR (ou autre) de la structure se fait comme suit:
(*GPIOD).IDR ou encore GPIOD->IDR en utilisant l’écriture simplifiée.

0xX…XX…..XXX 0x40020C00U GPIOD: une case mémoire quelconque


…. ….. typedef struct {
__IO uint32_t MODER; /* Address offset: 0x00 */
0x40020C00U MODER __IO uint32_t OTYPER; /* Address offset: 0x04 */
+0x04 OTYPER __IO uint32_t OSPEEDR; / Address offset: 0x08 */
__IO uint32_t PUPDR; /* Address offset: 0x0C */
+0x08 OSPEEDR __IO uint32_t IDR; /* Address offset: 0x10 */
__IO uint32_t ODR; /* Address offset: 0x14 */
+0x0C PUPDR __IO uint32_t BSRR; /* Address offset: 0x18 */
+0x10 IDR ……
} GPIO_TypeDef;
+0x10 ODR
+0x14 BSRR #define __IO volatile
52
Principe de Programmation
• Sans Bibliothèque
volatile unsigned int * DIDR = 0x40020C10U

if ((*DIDR & 0xFFFF) == 0x0000) …..


• Avec Bibliothèque
#include "STM32F4xx.h"
if (GPIOD->IDR & 0xFFFF) == 0x0000) …..

53
Exemple
• Modifier l’exemple de la première
partie:

Clignoter la diode LED connectée à PD12 en utilisant


les registres prédéfinis dans CMSIS en modifiant
l’exercice ci-dessous?

54
Compléter ?

int main() { // SPEED = 50 Mhz bits 25-24 = 0-1


// Enable GPIOD Clock *DSPEED &= 0xFCFFFFFF;
*AHB1_ENR |= 1<<3; ……………………………….
………………………………. *DSPEED |= 0x01000000;
// Configuration MODREG ……………………………….
// bits 25-24 = 01 // Bits 25-24 = 00
*MODREG &= 0xFCFFFFFF; *PUPPDR &= 0xFCFFFFFF;
………………………………. ……………………………….
*MODREG |= 0x01000000; while(1){
………………………………. *DODR |= 1<<12;
// Bit 12 = 0 ……………………………….
*DOTYPE &= ~(1<<12); tempo(0xffffff);
………………………………. *DODR &= ~(1<<12);
……………………………….
tempo(0xffffff);
}
}
26/01/2017 LAHBIB YOUNES 55
55
Réponse
// SPEED = 50 Mhz bits 25-24 = 0-1
*DSPEED &= 0xFCFFFFFF;
int main() { *DSPEED |= 0x01000000;
// Enable GPIOD Clock ……………………………….
*AHB1_ENR |= 1<<3; GPIOD->OSPEEDR &= 0xFCFFFFFF;
……………………………….
GPIOD->OSPEEDR |= 0x01000000;
……………………………….
RCC->AHB1ENR |= 1<<3; //CMSIS ……………………………….
// Bits 25-24 = 00
// Configuration MODREG *PUPPDR &= 0xFCFFFFFF;
// bits 25-24 = 01 ……………………………….
*MODREG &= 0xFCFFFFFF; GPIOD->PUPDR
………………………………. &= 0xFCFFFFFF;
……………………………….
GPIOD->MODER &= 0xFCFFFFFF; while(1){
*DODR |= 1<<12;
*MODREG |= 0x01000000; ……………………………….
GPIOD->MODER |= 0x01000000;
………………………………. GPIOD->ODR |= 1<<12;
……………………………….
tempo(0xffffff);
// Bit 12 = 0 *DODR &= ~(1<<12);
*DOTYPE &= ~(1<<12); ……………………………….
GPIOD->ODR &= ~(1<<12);
……………………………….
GPIOD->OTYPER &= ~(1<<12);
………………………………. tempo(0xffffff);
}
}
26/01/2017 LAHBIB YOUNES 5656
Utiliser les registres prédéfinis en
bibliothèque pour clignotez les 4
LEDS en même temps? ?
Utiliser les registres prédéfinis en
bibliothèque pour défiler les 4 leds ?
Utiliser les registres prédéfinis en
bibliothèque et le bouton USER pour
inverser les leds deux à deux à chaque
appui ?

Vous aimerez peut-être aussi