STM32 course
intro
hardware
- STM32F405
- RTG6
- pinout LQFP64
compatible boards
- adafruit feather
- adafruit board
- stlink v3 debug (swd inteface)
- swd cable
- swd 2x5 pad to solder onto bottom of ada board
- stm32f407VGt6 discovery board
setup
- stm32cube ide
- stm32programmer is separate application to flash mcu
- download manuals
- user manual microcontroller
- data sheet microcontroller
- user manual development board
peripherals
- board has ports, ports have pins
- .e.g PA1 = Port A, pin 1
- -> red led next to USB jack is GPIO 13, connected to PC1 on MCU
- memory for peripherals, look up in Memory Map in datasheet
- peripheral addresses start at 0x4000 0000, end at 0xE00F FFFF
- peripherals need buses. Look in Block Diagram
- ever module needs access to the clock
- buses carry clock to all parts of the microcontroller
- types of Advanced Peripheral Buses (APB)
- AHB1 168 MhZ
- APB1 42 MhZ
- APB2 84 MhZ
- addresses
- every peripheral has a range of addresses with Boundaries
- we define GPIO addresses as offsets of a base of memory addresses
RCC Reset Clock Control
- register RCC_AHB1ENR enables the clock
- 32 bits
- registers we need:
- RCC_AHB1EN_R enable clock register
- MODE_R mode register (direction register, input or output)
- OD_R output data register
GPIO port mode register
- 2 bits for each pin
- options are
- 00 input
- 01 general purpose output mode
- 10 alternate function mode
- 11 analog mode
ODR Output Data Register
- high bits not used
- set bit 2 for pin 1
- setting only the particular bit, we use the pipe | to “and” the existing value with a byte
- unsetting only a particular bit, we use the negate
~&= the existing value
- build and run
structs
- creating a struct with members with exact number of bytes
- each member occupies 4 bytes
- creates pointers to exactly these addresses, that can be accessed (and autocompleted) through the struct
GPIO
- gpio pins can be configured for different use. to use alternate functions
- e.g. as uart / special purpose pins
- typical gpio registers
- direction (mode register)
- data register
- you can configure gpio
buses
- AHB advanced high performance bus (1 clock cycle to access)
- APB advanced peripheral bus (2 clock cycles)
- if you need speed, use AHB, otherwise you can use APB
clock sources
- on chip RC oscillator
- externally connected crystal
- phase locked loop PLL (is programmable)
GPIO output driver
- we download header file to get access to registers
- STM and ADA both use cortex core chips, they add their own peripherals
- Files
- specific board headers:
Drivers/CMSIS/Device/ST/STM32F4XX/Include
- generic cortex chip headers:
Drivers/CMSIS/Include
system_stm32f4xx.c is a startup c file that can be used as template
- add includes
bsrr (bit reset)
- bit reset
- numbers correspond to pins, we use 5 here for PA5
- set a bit with the lower 16 values, reset with the upper 16 values
- push button is on PC13
- part of GPIOC
- GPIOC is connected to AHB1, so clock needs to be enabled
- pin should be set as input, thats values 00 on MODER
- reading uses GPIOC_IDR
uart universal asynchronous receiver tranceiver
- serial communication
- UART synchronous - clock is transmitted with the data
- USART asynchronous - no clock transmitted, transmitter and receiver agree on clock speed for data transmission (baud)
- duplex: data can be transmitted and received
- simplex: transmitted or received only
- half-duplex: transmitted only in one way at the same time
- full-duplex: data can be transmitted both ways at a time
- start and stop bit
- value of start bit is alway 0,
- value of stop bit can be 1 or 2 bits. value of stop bit is always 1
- frame:
- e.g. asci A
- 11 0100 0001 0
- baudrate: connection speed in bits per second
- stop bit: number of stop bits (1 or 2
- parity: partiy wether odd or even (used for error checking)
- mode: RX, TX mode or both
- word length: number of data bits transmitted (8 bit or 9 bit)
- hardware flow control:
implementing USART communication
- we are going to communicate with our microcontroller via usb
- were using USART2, connected to APB1, has TX and RX lines
- alternate function mapping of AF07
- PA2 -> USART2_TX
- PA3 -> USART2_RX
- alternate function register (AFR) needs to be set to the specific alternate function\
- in our case: AF7, bits 0111 need to be set to the specfic PA2 pin
- calculate uart baudrate
- For the uart, we want to read in a specific baudrate that is commonly used.
- the peripheral clock operates at a certain frequency.
- the APB clock operates at certain frequency.
- “what divider value should i put in BRR so that clock / divider = the desired baud rate”
- (clock + (baudrate / 2)) / baudrate
- the formula is weird because we add half of the baudrate to round to the next integer, instead of getting a double value
- set the usart clockrate it in the Usartx BRR register
- using the control register to enable the uart transmitter
- specifically setting the TE bit with = instead of |=, to clear the values
- setting the CR1_UE to enable the USART
- we can now use terminal to listen to the uart output: `screen /dev/tty.usbmodem2103 115200
- kill window with
Ctrl+A k
- we can also enable rx, to receive uart from the console
analog to digital conversion (ADC)
- vref as 5v
- step size is based on the amount of bit resolution
- ADC independent modes
- single channel, single conversion mode
- case: measure of volatage level to determine if a system should be started
- multichannel(scan) single conversion mode
- different sampling times per channel are possible
- case: measurement of multiple sensors to determine wether system should start or not
- single channel continuous
- measurement of room temperature continuous to adjust air-conditioner
- multichannel continuous conversion
- case: continuously measureing multiple accelerometers to adjust joints of robot arm
- injected conversion mode
- injected group has priority over regular channel group
- interrupts the conversion of the current channel
- case: synchronizing the conversion of channels to an event.
implement ADC
- board has
- 1 ADC module
- 16 inputs connected, in this case PC1 (PA1)
- 1 internal temperature sensor connected to ADC_IN18 input
- configure ADC sequence
- first we need to specify which channel is read first, which one second and so forth.
- specify the first channel in SQ1, second in SQ2
- specify sequence length (1 for 1 sensor)
- enable th module with CR2_ADON
- before we can read, we need to wait for conversion to be complete
- status register, end of conversion
- add CONT status to keep continuously checking
- add wire from A1 to 3v or GND to check
SYSTICK
- core peripheral for any arm cortex, every mcu has it
- 24-bit downcounter, driven by processor clock
- count down from 16million to 0
- initial value can be set
- take actions periodically
- creating tick / time for real time operating systems (heartbeat)
- popular registers
- systick current value register (STCVR)
- systick control register (STCSR)
- configure clock source, enable interrupts, enable timer
- systick reload value register (STRVR)
- place initial count value
- compute delays
- count from 0
- system clock is 16MHz, 16million cycles per second
- e.g.
1/16mil = 62.5*10^-9 62 nanoseconds per cycle
- n/systemclock
- example: 1ms delay, 0.001
- N = 16.000
- implement systick
- need to see cortex m4 user guide for information on systick register
general purpose timers / counters
- can be used as time base generator
- measure frequency of ecternal event
- one pulse mode
- registers
- timer count register (TIMx_CNT)
- timer auto-reload register (TIMx_ARR)
- value that the counter counts to before raising a flag and sending interrupt
- upcounter by default
- timer pre-scaler register (TIMx_PSC)
- slows down counting speed of the timer
- can slow down both APB1 and APB2
- timer control register
- timer status register
- e.g. check update interrupt flag
- capture/compare registers (CCR)
- one for each of the channels (CCR1 to CCR4)
- read captured value
- capture compare mode (CCMR1)
- capture compare enable register (CCER)
- status register
- glossary
- update event: when timeout occurs
- period: value loaded into auto-reload register
output compare timer
- we connect a timer directly to a gpio pin, for exact timing with a timer
- this will not use the output data register, it will toggle the pin internally
- example: PA5 wit AF01 connects PA5 with TIM2_CH1
- set OC1M bits 4-6 to toggle mode (110)
- timer connected to input pin, we want to capture the toggle rate
- pa6 timer3 channel 1
- make sure we use the right documentation for Tim2, which is not the advanced timer
- Status registers CC1IF -> is Interrupt Flag, is set when the capture has occurred
- flow of electricity:
- PA5 configured to be set high and low on a timer, it will be the source
- PA6 is the destination, so we need to add a wire from PA5 to PA6
- PA6 will read the value at a specific timer interval, we check it with the status register checking for interrupt flag
- helpful for development of ultrasonic sensor etc.
interrupts in arm
- processor can serve multiple modules using interrupts
- when cpu receives interrupt, it wil stop what it is doing and handle the interrupt -> services the module
- interrupt vs polling
- interrupt service routine (ISR), function that is called whin interrupt
- Nested Vector Interrupt Controller (NVIC)
- all modules lead to NVIC
- processor core generates interrupts
- systick is example module that generate interrupts, handled by
- GPIO’s go through EXTI controller, and through that lead to NVIC
- interrupts from core is called exception
- interrupts from outside cpu core are called “interrupt requests” (IRQ)
- vector table contains addresses of interrupt handlers
- e.g. process finds address of ISR and executes that
- External Interrupt Lines (EXTI)
- GPIO pins are connected to EXTI lines
- pin0 of every port is connected to EXTI0_IRQ
- we cannot have PB0 and PA0 as interrupt pins at the same time, as they are connected to the same multiplexer
- interrupt state
- disabled, enabled, pending, active (ISR is running)
- pending state is set when lower priority interrupt occurs
- pending state is cleared when interrupt becomes active
- vector table
- some priorities are fixed (exceptions from cpu)
- some interrupt priorities are settable
- interrupt priority registers (IPR) 8 bits -> IPR0 holds priorities of IRQ0 through IRQ3
- stm only uses high bits, so we have 16 priority levels
- interrupts
- calculate priorities with shift left by 4 (divide by 16)
- we can choose to create an interrupt when a specific pin goes high (rising edge) or low (falling edge)
- after configuration, the interrupt will ensure a specific handler is called
- setup
- enable clock tot syscfg
- select portc for External Interrupt Line 13
- unmask Exit13 through Interrupt Mask Register
- select falling edge in falling trigger selection register
- enable the specific IRQ in the NVIC with NVIC_EnableIRQ with EXT15_10_IRQn
- dont forget to disable and enable global interrupts at the start and end of config
- ADC end of conversion can also send an interupt.
- ADC CR1 has an end-of-conversion interrupt enable bit CR1_EOCIE
- then enable in the NVIC
- create ADC_IRQHandler and check the EOC bit in status register
- then don’t add blocking code but immediately read the ADC1 data register
DMA (Direct Memory Access)
- data transfer in the background without intervention of CPU
- two ports for DMA: memory port, peripheral port
- F4 has 2 DMA modules, each with 8 different streams
- each stream has eight selectable channels, but only 1 channel can be active at the same time
- each stream is dedicated to managing memory access requests from 1 or more peripherals
- all peripherals are internally linked to specific streams and channels and need to be configured for information to flow between DMA and peripherals
- stream priority is software configurable
- source address, destination address should both be in the same AHB or APB memory ranges
- modes
- memory to peripheral
- peripheral to memory
- memory to memory (only on DMA2)
- transfer size defines volume of data
- automatically increment source and data to copy larger volumes of data
- data width -> byte (8 bit), half-word (16bit) or word (32bit)
- transfer types
- circular mode -> collect sensor values,
- normal mode -> when flag is set, stream is disabled
- fifo mode
- reduces SRAM access
- allows software to do burst transactions
- allows packing / unpacking data
implement DMA
- first find dma conneciton to the peripheral
- usar2tx is connected to DMA1 channel 6
- Stream Control Register (DMASrCR)
- to first disable stream
- select the channel,
- enable memory increment
- configure transfer direction (e.lg. memory to peripheral)
- enable transfer complete interrupt (TCIE)
- HI Flag Clear Register (HIFCR)
- clear interrupt flags for specific stream
- peripheral Address Register (PAR )
- set the destination buffer in the peripheral address register
- Memory0 Address Register (M0AR))
- set dst in the memory buffer
- Number of Data transfer register (NDTR)
- set the length of the data transfer
- DMA Stream CR
- set len
- set DIR to
- TCIE (bit 4)
- Fifo Control Register (FR)
- set to 0 to enable direct mode
inter-itegrated circuit i2c protocol
- also called two wire interface (TWI)
- 2 lines
- SCL Serial Clock -> syncronising data transfer between master and slave
- SDA Serial Data -> the data line
- operation modes
- master or slave is transmitter or receiver
- protocol
- trasnactions are initiated and completed by the master
- all messages have address frame and data frame
- data is placed on the SDA line after SCL goes low, and sampled after SCL line goes high
- start and stop condition
- the bus is considered to be free certain time after the stop condition
- byte format
- any information must be 8 bits long
- each byte is followed by acknowledge bit
- data transferred with MSB most significant bit first
- address frame
- address frame is first sent out
- 7 bit address first, then Read (1) /Write (0) bit
- data frame
- master will continue generate clock pulses
- data will be placed on SDA line by master or slave (based on operation mode)
- i2c parameters
- clock speed
- standard 100KHz
- fast-mode 400 KHz
- fastmode plus 1 MHz
- high-speed mode 3.4 MHz
- duty cycle
- ration between time low and time high
- e.g. the time we remain high or low
- I2C_DUTYCYCLE_2 = 2:1
- I2C_DUTYCYCLE_16_9 = 16:9
implement i2c init
- I2C1 is connected to APB1
- PB8 I2C1 SCL line via Alternate Type Function 4
- PB9 I2C1 SDA line via Alternate Type Function 4
- OTYPER register
- -> “open drain” mode needs to be set on PB8 and PB9 pins
- PUPDR register
- -> pullup needs to be enabled for PB8 and PB9 pins
- i2c CR1 (control register 1) needs reset to be set and reset
- SWRST to 1
- and reset it later to 0 (dont know why)
- set frequency in CR2
- 16mhz bit position 4 0x01000
- CCR register (clock control)
- a specific speed, 100KHZ in this case (value 80)
- TRISE Maximum rise time in Fm/Sm mode
- a specific speed, 100KHZ in this case (value 80)
- CR1 enable the peripheral
i2c read data
- wait till i2c is not busy anymore (I2C->SR2)
- generate start condition
- set the start bit (CR1_START)
- wait until start flag is set (SR1_SB)
- send slave address + write
- wait for address to be set
- clear address flag
- send memory location
- wait until transmitter is not empty
- generate start condition
- wait for start flag to be set
- send the slave address to read
- generate stop condition
- wait for data to be available
- read data and store in variable
SPI interface
- full duplex -> communication both ways
- pins
- SDI / MOSI
- Master Out Slave In (MOSI)
- SDO / MISO
- Master In Slave Out (MISO)
- SCLK / SCK pin to synchronise data transfer
- serial clock, generates clock from master
- CE / SS pin to initiate and terminate data transfer
- slave select line in multiple slave configuration
- spi devices have no address, select with slave select line
- modes single slave or multiple slaves
- flow
- enable SCK to start transaction
- master sets SS line low
- data is shifted out with the MSB first
- sending data on MOSI line is by default always happening on rising edge of SCK
- SPI bus modes
- Clock Polarity (CPOL)
- 0 means sampling on the first edge
- Clock Phase (CPHA)
- defines if data is captured and output on rising edge or falling edge
- NSS output disabled
- allows multi-master capability
- TI mode
- Texas Instrument protocl requirements
SPI driver implementation
- look for which bus the SPI is ocnnected to (SPI1 to APB2)
- PA5 -> clock
- PA6 -> MISO
- PA7 -> MOSI
- PA9 -> SS
risc architecture
- risc focuses on reducing complexity for processor, and optimise with increased complexity compilers
- philosophy
- instructions: reduced number of instructions
- pipelines: instructions executed in parallel by pipelines
- registers: large general-purpose register set
- load-store: processor operatos on data held in registers
memory
- memory width
- number of bits memory returns on each access
- arm processor is capable of running multiple instruction sets
- ARM-32 thumb2
- thumb 16 bit
- 16&32 bit
- types
- ROM (read only)
- Flash ROM (readwrite)
- DRAM (dynamc random access)
- lower cost per megabyte compared to other rams
- SRAM (Static random access)
- SDRAM Synchronous dynamic random access memory
- runs on higher clock rate
- EEPROM
- SFR (special function registers)
- 32bit -> 4GB addressable space
cache
- Tightly Coupled Memory (TCM)
- provide predictable real time response
- AMBA bus
memory protection hardware
- Memory Protection Unit (MPU)
- often used for systems that require memory protection
- but usually for simple memory maps
- Memory Management Unit (MMU)
- comprehensive solution
- tables are stored in main memory
- access permissions
resources