Vous êtes sur la page 1sur 49

Chapitre 3

PERIPHERIQUE 1: Programmation bas


niveau des GPIOs

Objectifs

Utiliser le C embarqu pour:


Dfinir les registres relatifs au GPIO par un code en langage C
Adresser les diffrents registres
Manipuler entirement ou par bits les registres
Programmer les registres de STM32 par adressage de ses registres en se
rfrant au mapping de mmoire (Memory Map)

Plateforme embarque utiliser: STM32


F4Discovery

Architecture de lSTM32
Architecture de type RISC (Reduced Instructions Set Computer)

Bus des

Instructions et bus des Donnes sont spars -> Architecture Harvard.


CPU CortexM4 fait le calcul la cadence du Bus (AHB: ARM Hi-Speed Bus).
Les priphriques, moins rapides, sont monts sur les Bus APB1 et APB2.
Dans le cas dun tansfert DMA (Direct Memory Acces) c--d dune adresse mmoire ou
dun priphrique vers un autre, le DMA devient le matre du bus AHB.
Flash I/F

I-bus
D-bus

CORTEX-M4
Master 1
BusMatrix

System

SRAM
Slave
APB2
AHB

GP-DMA
Master 2

FLASH

AHB-APB2
AHB-APB1

Arbiter

Peripheral Bus APB2

Bridges

APB1
Peripheral Bus APB1

Architecture dtaille dun STM32 F40x

JTAG/SW Debug
Nested vect IT Ctrl

1 x Systick Timer

DMA
up to 12 Channels

Flash I/F

CPU

ARM Lite Hi-Speed 36us


Matrix / Arbiter (max 24MHz)

CORTEXTM-M4
24 MHz

256KB-512kB
Flash Memory

24KB-32kB SRAM

Power Supply
Reg 1.8V

POR/PDR/PVD

XTAL oscillators
32KHz + 4~25MHz

84B Backup Data


Int. RC oscillators
40KHz + 8MHz

FSMC
SRAM/ NOR/ LCD parallel interface

Clock Control
Bridge

PLL

RTC / AWU

ARM Peripheral Bus


(max 24MHz)

Bridge

51/80/112 I/Os
1 x SPI

10 x 16-bit Timer

(independent & window)

4 x USART/LIN
2-channel 12-bit DAC

Smartcard / IrDa
Modem Control

1 x 12-bit ADC
up to 16 channels

2 x SPI

Temperature Sensor

2 x I2 C

1 x USART/LIN
Smartcard/IrDa
Modem Control

1 x CEC

2 x Watchdog
(max 24MHz)

Up to 16 Ext. ITs

ARM Peripheral Bus

1 x 16-bit PWM Synchronized AC Timer

Tools and Software


Outils de dveloppements
IAR Embedded Workbench

Loutil utiliser:
http://www.keil.com/uvision/

kEIL Vision IDE


Raisonnance Ride7
MikroC Pro for ARM
CooCox (riche en exemples)

Circle OS (couche applicative de lOS circleOS)


La plupart des outils sont btis autour de CMSIS - Cortex Microcontroller
Software Interface Standard:
http://www.keil.com/pack/doc/CMSIS/General/html/index.html

E/S bidirectionnels de STM32


GPIO standard (tolre une valeur de 5v en entre) et gnre une sortie de 3v
GPIOs dlivre un courant 25mA
Temps de monte en sorite configurable (max 50 MHz)
Toutes les broches peuvent tre programmes comme entre analogique
Toutes les broches peuvent tre programmes en fonctions alterns
(USARTx, TIMx, I2Cx, SPIx,)
Toute entre pourrait tre configure comme source dinterruption
9 ports de GPIO standard (GPIOA..GPIOI) (1 port = 16 broches dE/S)

Registres de contrle des GPIOs


Pour la manipulation des 9 GPIOx(x=A..I), nous avons recours lutilisation
des registres de contrle suivants
GPIOx_MODER : registre utilis pour slectionner la direction (Entre ou Sortie),
Fonction alterne et analogique (input, output, AF, analog)
GPIOx_OTYPER : Registre utilis pour slectionner le type de sortie PP(pushpull
) ou OD (open-drain)
GPIOx_OSPEEDR : Registre utilis pour slectionner la vitesse quelque soit la
direction I/O
GPIOx_PUPDR : Registre utilis pour la slection du mode PU ou PD ( pullup/pull-down) quelque soit la direction I/O

Registres des donnes


GPIOx_IDR (x=A..I): rcuprer les donnes entrantes du
port x, accd en lecture seule
GPIOx_ODR (x=A..I): envoyer les donnes en sorties du
port x, accd en criture et en lecture
Rq: Il existe dautres registres GPIO non traits 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)
GPIO alternate function low register
(GPIOx_AFRL) (x = A..I)
GPIO alternate function high register
(GPIOx_AFRH) (x = A..I)

Ladresse dun registre dun priphrique donne est la somme de:


ladresse de base dun priphrique
ladresse doffset du registre

ladresse de base du priphrique est dfinie dans le memory map


(Table 10 page 71 du datasheet STM32F40x)

Les adresses doffset des registres sont dfinies 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 doffset des
principaux registres sont prsentes par la suite

Memory MAP: Table 10 page 71 du datasheet


STM32F40x

Adresses de base des


PORTS dE/S (GPIOs)

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

28

Exemples de calcul des adresses

Calculer les adresses des registres suivants:


GPIOC_ODR = GPIOC_BASE + OFFSET_ODR
= 0x4002 0800 + 0x14
= 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 contrleur de la circuiterie de Reset


et dhorloge.
Permet de synchroniser les trois bus du Cortex-M4 (AHB, APB1 et
APB2) avec le bus interne du systme: le bus matrix
Les GPIOs sont monts sur le bus AHB1. Tout GPIO(composant en
gnral) doit tre activ par RCC avant utilisation.
Lavantage de RCC est la possibilit dactiver, suivant le besoin de
lapplication, les composants ncessaires lapplication.
En consquent, une meilleure gestion de la consommation du
systme 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 ltat initial le priphrique utiliser


par une criture de 1. Suite cette criture de 1, il faut crire 0 pour que
le priphrique sorte de son tat de reset.

Applications: 4 Leds et Bouton utilisateurs de


STM32f4Discovery

TP1: Clignotement de la LED


connecte au PD12

Principe de programmation des registres (1/5)

Un programme C qui utilise uniquement les registres dun priphrique


pourrait tre vu comme tant une fonction des registres mis en jeu.

PROG = f(registres)
La programmation dans ce cas consiste :
ETAPE 1: Dfinir les registres utiliser: chaque registre est quivalent
une adresse donc un pointeur en langage C
ETAPE 2: Initialiser ces pointeurs par les adresses adquates
ETAPE 3: Lecture et/ou criture des contenus des registres
- Lecture: lire ltat du systme
- Ecriture: commander le systme

Principe de programmation des registres (2/5)


ETAPE 1: Dfinir les adresses des registres
Les priphriques utiliser dans notre cas sont :
RCC (Reset and Clock Control): pour lactivation de lhorloge
- Le registre utiliser de lRCC est RCC_AHB1ENR + RCC_AHB1RSTR
GPIOD: pour commander la broche PD12 connecte au LED4
- Les registres utiliser du priphrique GPIOD sont MODREG ,
DOTYPE , DSPEED, PUPPDR et ODR (de mme pour les autres)

RCC adresse de base:


0x4002 3800

AHB1ENR:
@offset= 0x30

AHB1RSTR:
@offset= 0x10

@ AHB1RSTR = 0x40023810
@ AHB1ENR = 0x40023830

GPIOD adresse de base:


@ 0x4002 0C00

MODREG : @offset= 0x00


ODR: @offset= 0x14
@ DMODREG = 0x40020C00
@DODR= 0x40020C14

Principe de programmation des registres (3/5)


ETAPE 2: dfinir des pointeurs et les initialiser
Dfinition 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 leffet de loptimisation (taille du code


+ Speed) sur les variables dclares. Ici les @ des registres.

Principe de programmation des registres (4/5)


ETAPE 3: Lecture/criture dans les registres
Rinitialiser le GPIOD
Activer lhorloge de GPIOD

Mettre le Bit3 de AHB1_RSTR 1 puis 0


Mettre le Bit3 de AHB1_ENR 1

Configurer les PD12 en mode General Purpose Output Push Pull


(GP Output 50 Mhz):

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;
// 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;

Principe de programmation des registres (5/5)


ETAPE 3 suite: Lecture/criture dans les registres

Activer ltat de la sortie PD12 :


Mettre le bit 12 1 dans le registre DODR

Ecriture dans le
registre DODR

Insrrer un delay en utilisant la boucle for

Dsactiver ltat de la sortie PD12 :


Mettre le bit 12 0 dans le registre EODR
Insrrer 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 lapplication (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
volatile unsigned int * AHB1_RSTR = (unsigned int *) 0x40023810;
//RCC_AHB1ENR
void tempo(volatile unsigned int CNT){
for(; CNT > 0 ;CNT --);
}

Code de lapplication (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);
}
}

Clignotez les 4 LEDS en mme


temps? ?

Dfiler les 4 leds ?

Utiliser le bouton USER pour


inverser les leds deux deux
chaque appui ?