ARM Cortex-M3 and STM32 Basics
Objective
All the datasheets and reference manuals which describe a processor architecture in detail, taken together, may run into thousands of pages. Very often, the systems programmer who wishes to write / port something like a real time OS will need only a core set of information regarding the:
- The processor memory map
- Reset behaviour
- System clock
- Interrupts
- Timer
- Basic instruction set
- Toolchain
This wiki page is an experiment in gathering just the amount of information about an ARM Cortex-M3 based processor which will help us understand the working of a simple RTOS (in this case, FreeRTOS).
About ARM Cortex-M3
Check out the the official description of the Cortex-M3 core. An ARM whitepaper is also available. From a programmer’s point of view, some of the interesting points about this new architecture are:
- A new Thumb-2 instruction set with 16 bit and 32 bit instructions.
- Hardware stack manipulation - registers are pushed/popped automatically during ISR entry/exit
- A SysTick timer integrated into the processor core - useful for writing RTOS code.
About STM32F103RBT6
Luminary Micro was the first company to bring out Cortex-M3 based processors. This was followed by STMicro bringing out STM32. Cortex-M3 based processors have been announced by NXP, but they are not yet available in the market.
The STM32F103RB device comes with 128Kb of flash and 20Kb RAM. An innovative evaluation board, the STM32 Primer, is based on the STM32F103RB.
Memory Map
The Cortex-M3 has a linear 32 bit address space. The first 1Gb is split evenly between
code and data; code (flash) is from 0x0
to 0x1fffffff
and data (SRAM) is from 0x20000000
to 0x3fffffff
. Peripherals are mapped to locations 0x40000000
to 0x5fffffff
.
Note: The STM32F10xxx processor's flash is mapped to location 0x08000000; but it
can also be accessed from location 0x0.
There is a special System control space
from 0xe000e000
to 0xe000efff
. This
region holds, among other things, registers related to the Nested Vectored
Interrupt controller and the SysTick timer.
Cortex-M3 processors are little endian.
Interrupt Vectors
The interrupt vector table starts at address 0x4
(the cortex processor uses
the 4 byte value at address 0x0
to initialize the stack pointer).
Each entry is 4 bytes long and should contain the address of the routine
to be executed. The table starts with the reset vector at location 0x4
.
For the cortex core to start executing code, the only requirement is initializing the first two locations properly. The stack pointer can be made to point to the top of available SRAM and the reset vector should point to the code which is to be executed.
GPIO Ports
GPIO ports are configured as input floating
upon reset and alternate functions are
not enabled. Each port will have upto 16 pins.
Each GPIO port has two 32 bit configuration registers - GPIOx_CRL
and GPIOx_CRH
,
two 32 bit data registers, GPIOx_IDR
and GPIOx_ODR
, a 32 bit set-reset register,
GPIO_xBSRR
, a 16 bit reset register, GPIOx_BRR
and a 32 bit locking register, GPIOx_LCKR
.
Each GPIO pin can be configured as one of:
- Input floating
- Input pull-up
- Input pull-down
- Analog input
- Output open-drain
- Output push-pull
- Alternate function push-pull
- Alternate function open-drain
Configuring the GPIO ports
Each I/O pin of a GPIO port has four configuration bits - GPIOx_CRL
holds configuration
bits for 8 pins and GPIOx_CRH
holds the configuration bits for the remaining 8 pins.
The four configuration bits are divided into two MODE bits and two CNF bits -
with MODE bits occupying lower bit positions. For example, in the case GPIO port B,
bits 0 and 1 of GPIOB_CRL
a
re the MODE bits and bits 2 and 3 are the CNF bits for pin 0.
The MODE bits can have the following values:
00
- Input mode (reset state)01
- Output mode (max 10MHz speed)10
- Output mode (max 2MHz speed)11
- Output mode (max 50MHz speed)
The CNF bit values are interp
reted differently according to the MODE. If MODE is input,
the CNF bit values are interpreted as:
00
- Analog input01
- Floating input10
- Input with pull-up/pull-down11
- reserved`
`If MODE is output, the CNF bit values are interpreted as:
00
- General purpose output push-pull01
- General purpose output open-drain10
- Alternate function output push-pull11
- Alternate function output open-drain
Here is a link which explains difference between push-pull and open-drain configurations. Normally, to drive LED’s, we will configure the output pins as push-pull.
The Bit Set/Reset register
Bits 0 to 15 of GPIOx_BSRR
are used to “set” the corresponding port pin - writing a
0 to these bits have no effect while writing a 1 will set the port pin.
Bits 16 to 31 are used to “reset” the corresponding port pin - writing a
0 to these bits have no effect while writing a 1 will reset the port pin.
Clocking
Upon reset, an internal RC oscillator of 8MHz frequency is used as the system clock. For better precision, an external crystal can be used as the clock source. An internal PLL can be used to multiply the base clock (either internal or external) to the maximum system clock frequency of 72MHz.
Clocks to all peripherals (except SRAM and flash) are disabled on reset - so
if we wish to use say the GPIO ports, it’s corresponding peripheral clock
has to be enabled.
Enabling GPIO Clock
No peripheral unit will work without its clock being enabled. Lighting up an LED on a GPIO port requires that the corresponding peripheral clock is enabled.
Bits 2 to 8 of the RCC_APB2ENR register (address 0x40021018
) control the clocks
to IO ports A to G.
Boot Modes
The STM32F10xxx has 3 different boot modes - mode selection is done using two pins BOOT0 and BOOT1.
| BOOT 1 | BOOT 0 | Boot Mode |
| x | 0 | Main Flash memory |
| 0 | 1 | System memory |
| 1 | 1 | Embedded SRAM |
SysTick Timer
A timer which generates interrupts periodically is at the heart of most real-time
operating systems. The Cortex-M3 core has a very interesting feature -
it provides a SysTick
timer integrated into the CPU core which can be used for
providing the RTOS tick
. Because this timer is part of the processor core,
all Cortex-M3 devices, irrespective of the vendor, will have this feature.
Note: the SysTick timer may not be properly documented in the vendor's processor
reference manual - it is better to check out the official ARM documentation.
The SysTick timer’s operation is very simple. The counter starts counting down from
the value specified in the reload
register (address 0xe000e014
) - when the value
reaches 0, it optionally generates an interrupt and once again starts counting down
from the initial value specified in the reload
register.
The SysTick interrupt is by default enabled in the NVIC (nested vectored interrupt
controller) - we only have to enable it in the timer by setting the SysTick control
and status register’s (address 0xe000e010
) D1’th bit to 1. Setting the D0’th bit
of the same register enables the timer. Setting the D2’th bit to 1 chooses the CPU
clock as the clock source of the timer.
Note: A bit of confusion here - is it the cpu clock or the AHB clock?
What if the bit is zero?