STM32L476 Parallel I/O Ports
References: STM32L4x6 Reference Manual
STM32L476xx Data Sheet
stm32l476xx.h Header File
NVIC, System Tick Timer
External
ARM Cortex-M4 memory
CPU Flash
SRAM
STMicroelectronics
STM32L476xx
microcontroller GPIO
Source:
STM32L476xx Datasheet
STM32L476xx
Peripherals
LCD
STM32 microcontrollers
General-Purpose Input/Output (GPIO)
Modules GPIOA, GPIOB, …GPIOH each comprise 16 GPIO pins
# of GPIO ports/pins varies among microcontroller parts
STM32L476VGTx has 82 GPIO pins (only 2 in GPIOH)
Pin options (each pin is configurable via GPIO registers):
Output: push-pull or open-drain+pull-up/pull-down
Selectable output speed
Input: floating, pull-up/pull-down
Analog: input or output
Alternate functions: up to 16 per pin
Data to/from peripherals (Timers, I2C/SPI, USART, USB, etc.)
Digital data input/output via GPIO registers
Input data reg. (IDR) – parallel (16-bit) data from pins
Output data reg. (ODR) – parallel (16-bit) data to pins
Bit set/reset registers (BSRR) for bitwise access to pins
STM32 GPIO pin structure
Analog IO
Alt. Function
LDR
PIN
IDR
BSRR
ODR
STR
Alt. Function
Addressing I/O registers (in C)
(from stm32l476xx.h header file)
#define PERIPH_BASE ((uint32_t)0x40000000) /* Peripheral base address in the alias region */
#define AHB2PERIPH_BASE (PERIPH_BASE + 0x08000000) /* AHB1 bus peripherals */
#define GPIOD_BASE (AHB2PERIPH_BASE + 0x0C00) /* GPIO Port D base address */
#define GPIOD ((GPIO_TypeDef *) GPIOD_BASE) /* GPIO Port D pointer */
/ * General Purpose I/O */
typedef struct /* Treat GPIO register set as a “record” data structure */
{
__IO uint32_t MODER; /* GPIO port mode register, Address offset: 0x00 */
__IO uint32_t OTYPER; /* GPIO port output type register, Address offset: 0x04 */
__IO uint32_t OSPEEDR; /* GPIO port output speed register, Address offset: 0x08 */
__IO uint32_t PUPDR; /* GPIO port pull-up/pull-down register, Address offset: 0x0C */
__IO uint32_t IDR; /* GPIO port input data register, Address offset: 0x10 */
__IO uint32_t ODR; /* GPIO port output data register, Address offset: 0x14 */
__IO uint32_t BSRR; /* GPIO port bit set/reset register, Address offset: 0x18 */
__IO uint32_t LCKR; /* GPIO port configuration lock register, Address offset: 0x1C */
__IO uint32_t AFR[2]; /* GPIO alternate function registers, Address offset: 0x20-0x24 */
} GPIO_TypeDef;
GPIOD->ODR = value; /* write data to ODR of GPIOD */
GPIO data registers
16-bit memory-mapped data registers for each port GPIOx
x = A…H (GPIOA, GPIOB, …, GPIOH)
GPIOx_IDR (Input Data Register)
Data input through the 16 pins
Read-only
GPIOx_ODR (Output Data Register)
Write data to be output to the 16 pins
Read last value written to ODR
Read/write (for read-modify-write operations)
C examples:
GPIOA->ODR = 0x45; //send data to output pins
N = GPIOA->IDR; //copy data from input pins to N
GPIO port bit set/reset registers
GPIO output pins can be individually set and cleared, without
affecting other bits in that port
GPIOx_BSRR (Bit Set/Reset Register)
Bits [15..0] = Port x set bit y (y = 15..0) (BSRR-Low)
Bits [31..16] = Port x reset bit y (y = 15..0) (BSRR-High)
Bits are write-only
1 = Set/reset the corresponding GPIOx bit
0 = No action on the corresponding GPIOx bit
(“set” has precedence if bit=1 in both BSSR-Low and BSSR-High)
C examples:
(0x00000010)
GPIOA->BSRR = (1 << 4); //set bit 4 of GPIOA
GPIOA->BSRR = ((1 << 5) << 16); //reset bit 5 of GPIOA
(0x00200000)
GPIO “mode” register
GPIOx_MODER selects operating mode for each pin
31 7 6 5 4 3 2 1 0
… Pin 3 Pin 2 Pin 1 Pin 0
2 bits per pin:
00 – Input mode (reset state):
Pin value captured in IDR every bus clock (through Schmitt trigger)
01 – General purpose output mode:
Write pin value to ODR
Read IDR to determine pin state
Read ODR for last written value
10 – Alternate function mode:
Select alternate function via AF mux/register (see later slide)
11 – Analog mode:
Disable output buffer, input Schmitt trigger, pull resistors
(so as not to alter the analog voltage on the pin)
Alternate function selection
(Table in μC data sheet lists specific AF options for each pin.)
Each pin defaults to GPIO pin at reset (mux input 0)
With a few exceptions: PA13-15, PC14-15, PH0-1
GPIOx->AFR[0] GPIOx->AFR[1]
(low pins 0..7) (high pins 8..15)
GPIO pin option registers
Input
GPIOx_PUPDR – pull-up/down
00 – no pull-up/pull-down
01 – pull-up
10 – pull-down
GPIOx_OTYPER – output type
0 = push/pull, 1 = open drain
(both on) (P-MOS off)
GPIOx_OSPEEDR – output speed
00 – 2 MHz low speed
01 – 25 MHz medium speed
10 – 50 MHz fast speed
11 – 100 MHz high speed (on 30 pf)
Discovery Board connections
User LEDs (positive logic)
LED4 (red) – PB2
LED5 (green) – PE8
Joystick (5 positions – positive logic)
Pull-down Rs NOT installed.
Activate GPIO pull-down devices.
Pull-down resistors create normal logic 0 on PA0,PA1,PA2,PA3,PA5
Pressing Joystick connects COMMON (3V) to one pin, pulling it up to logic 1
Joystick schematic
LEFT: PA1 UP: PA3
PA0 +3v
DOWN: PA5 RIGHT: PA2
Enable GPIO pull-down on pins 1-2-3-4-6
GPIO port initialization ritual
• Initialization (executed once at beginning)
1. Turn on GPIOx clock in register RCC_AHB2ENR
(Reset and Clock Control - AHB2 peripheral clock enable register)
• RCC register block base address = 0x4800 1000
• AHB2ENR register offset = 0x4C
• AHB2ENR bits 7-0 enable clocks for GPIOH-GPIOA, respectively
2. Configure “mode” of each pin in GPIOx_MODER
• Input/Output/Analog/Alternate Function
3. Optionally (if other than reset configuration required)
o Configure speed of each output pin in GPIOx_OSPEEDR
o Configure type of each pin in GPIOx_OTYPER
o Configure pull-up/pulldown of each pin in GPIOx_PUPDR
• Input from switches, output to LEDs
Read/write 16-bit data via GPIOx_IDR/ODR
Set/clear output pins via GPIOx_BSRR
To set bits
OR operation to set bits 3-0 of GPIOD_MODER, to select analog mode for pins
PD1 and PD0.
( The other 28 bits of GPIOD_MODER are to remain constant.)
Friendly software modifies just the bits that need to be.
GPIOD->MODER |= 0x0F; // PD1,PD0 analog
Assembly:
LDR R0,=GPIOD_MODER
LDR R1,[R0] ; read previous value
ORR R1,R1,#0x0F ; set bits 0-3
STR R1,[R0] ; update
c7 c6 c5 c4 c3 c2 c1 c0 value of R1
0 0 0 0 1 1 1 1 0x0F constant
c7 c6 c5 c4 1 1 1 1 result of the ORR
Bard, Gerstlauer, Valvano, Yerraballi
To clear bits
AND or BIC operations to clear bits 3-0 of GPIOD_MODER to select “input mode”
for pins PD1 and PD0. (Without altering other bits of GPIOD_MODER.)
Friendly software modifies just the bits that need to be.
GPIOD->MODER &= ~0x0F; // PD1,PD0 output
Assembly:
LDR R0,=GPIOD_MODER
LDR R1,[R0] ; read previous value
BIC R1,R1,#0x0F ; clear bits 3-0
STR R1,[R0] ; update
c7 c6 c5 c4 c3 c2 c1 c0 value of R1
1 1 1 1 0 0 0 0 BIC #x0F = AND #0xFFFFFFF0
c7 c6 c5 c4 0 0 0 0 result of the BIC
Bard, Gerstlauer, Valvano, Yerraballi
To toggle bits
XOR operation to toggle bits.
GPIOD->ODR ^= 0x80; /* toggle PD7 */
Assembly:
LDR R0,=GPIOD_ODR
LDRH R1,[R0] ; read port D
EOR R1,R1,#0x80 ; toggle state of pin PD7
STRH R1,[R0] ; update port D
b7 b6 b5 b4 b3 b2 b1 b0 value of R1
1 0 0 0 0 0 0 0 0x80 constant
~b7 b6 b5 b4 b3 b2 b1 b0 result of the EOR
Bard, Gerstlauer, Valvano, Yerraballi
To set or reset bits using BSSR
BSSR register to set or reset selected GPIO bits, without affecting the other bits
GPIOD->ODR |= 0x0080; // PD7 = 1 using ODR and mask
GPIOD->BSRR = 0x0080; // PD7 = 1 using BSRR
GPIOD->ODR &= ~0x0400; // PD10 = 0 using ODR and mask
GPIOD->BSRR = 0x0400 << 16; // PD10 = 0 using BSRR
Assembly:
LDR R0,=GPIOD ; GPIOD base address
MOV R1,#0x0400 ; select PD10 in BSSR Low
MOVT R1,#0x0080 ; select PD7 in BSSR High
STR R1,[R0,#BSSR] ; PD10=0 and PD7=1
Software drivers for GPIO pins
Initialize pin mode and options
Force output pin to 0
Force output pin to 1
Toggle state of output pin
Get state of input pin
See HAL and BSP driver documentation
GPIO register addresses
Base addresses of GPIOx register “blocks”
GPIOA = 0x4802_0000 • GPIOE = 0x4802_1000
GPIOB = 0x4802_0400 • GPIOF = 0x4802_1400
GPIOC = 0x4802_0800 • GPIOG = 0x4802_1800
GPIOD = 0x4802_0C00 • GPIOH = 0x4802_1C00
Register address offsets within each GPIOx register block
MODER = 0x00 pin direction/mode register
OTYPER = 0x04 pin output type register
OSPEEDR = 0x08 pin output speed register
PUPDR = 0x0C pull=up/pull-down register
IDR = 0x10 input data register
ODR = 0x14 output data register
BSRR = 0x18 bit set/reset register
LCKR = 0x1C lock register
AFRL = 0x20 alt. function register – low
AFRH = 0x24 alt. function register - high
Assembly language example
;Symbols for GPIO register block and register offsets
GPIOA EQU 0x48020000 ;GPIOA base address
ODR EQU 0x14 ;ODR reg offset
IDR EQU 0x10 ;IDR reg offset
;Alternative – symbol for each register address
GPIOA_ODR EQU GPIOA + GPIO_ODR ;addr of GPIOA_ODR
GPIOA_IDR EQU GPIOA + GPIO_IDR ;addr of GPIOA_IDR
;Using addresses = GPIO base + register offset
LDR r0,=GPIOA ;GPIOA base address
LDR r1,[r0,#ODR] ;GPIOA base + ODR offset
STR r1,[r0,#IDR] ;GPIOA base + IDR offset
;Using separate address for each GPIO register
LDR r0,=GPIOA_ODR ;GPIOA_ODR address
LDR r1,[r0]
LDR r0,=GPIOA_IDR ;GPIOA_IDR address
STR r1,[r0]
How would we address GPIOD ODR/IDR?