Introduction
The Nucleo-32 STM32F042 development board features the ARM Cortex-M0 based STM32F042K6 microcontroller with 48 MHz clock speed, 32 KB Flash storage and 6 KB static RAM.
Hardware
The hardware is described in the STM32 Nucleo-32 board user manual, which applies to all Nucleo-32 boards. The board is sized like an Arduino Micro, 20 pins tall (one-tenth-inch pin spacing) and 7 pins wide. The pins on the board are compatible with the Arduino Nano so that the same extension boards can be attached.
Pin Layout
Solder Bridges
There are a number of solder bridges on both sides of a Nucleo-32 board. They are labeled with the SB prefix. Solder bridges are used for (permanently) reconfiguring the board. They are cheaper than, for example, DIP switches and take little space on circuit boards. Some solder bridges on the Nucleo have solder on both ends and an air gap in between. These are in OFF state. The two ends need to be short-circuited with solder to switch them to the ON state. Other solder bridges have a resistor between the soldered ends. These bridges are in ON state. The resistor needs to be desoldered to switch them to the OFF state. Some of the solder bridges that are ON by default are explained in the table below.
Bridge | Description |
---|---|
SB9 | Connects the NRST reset signal from ST-LINK to the NRST pin of STM32. Disconnect when using an external power supply. |
SB10 | Connects VREF+ to VDD by default. Otherwise VREF+ is provided by pin 13 on header row CN4. |
SB11 | Connects VSS to pin 16 of the STM32 (U2). Disconnecting frees up pin 16 on Nucleo STM32F031 boards for use as GPIO pin PB2. |
SB13 | Connects VSS to pin 32 of the STM32. Disconnecting frees up pin 32 on Nucleo STM32F031 boards for use as GPIO pin PB8. |
SB12 | Connects pin 31 of the STM32 to Ground via a 10 kΩ pull-down resistor so that pin 31 is used as BOOT0 pin. Disconnecting frees pin 31 on Nucleo STM32F042 boards for use as GPIO pin PB8. |
SB15 | Connects the green LED LD3 to the Arduino pin D13. |
SB16 | Connects pin 7 on header row CN4 to STM32 pin PB6 so that Arduino Nano pin A5 can be used as I2C SDA. Disconnecting makes pin 7 usable as Arduino Nano analog input A5 while breaking I2C capability. |
SB18 | Connects pin 8 on header row CN4 to STM32 pin PB7 so that Arduino Nano pin A4 can be used as I2C SCL. Disconnecting makes pin 8 usable as Arduino Nano analog input A4 while breaking I2C capability. |
SB2 and SB3 are for disconnecting the USART interface from ST-LINK/V2-1 with which the STM32 is can be flashed and debugged via USB.
Clock speed
The value for the high-speed external clock (HSE) speed is set by the HSE_VALUE preprocessor definition. The default value is 8 MHz. You shouldn't need to change this. The clock speed multiplier for is given by RCC_CFGR_PLLMULL (RCC = Reset and Clock Control, PLL = Phase Locked Loop). When setting up a new project, GNU MCU Eclipse Plugin pops up a dialog where CPU parameters such as Flash memory size, RAM size, and clock speed can be specified. The given value for the clock speed is then placed into the compiler command line argument -DHSE_VALUE.
Debugging
Debugging from Eclipse
Open the debug configurations window and create a new GDB OpenOCD Debugging configuration.
- Under Main, enter Debug/<executable-name>.elf in the C/C++ Application text field
- Under Debugger, enter the path to the configuration file for the target chip in the Config options text area in the OpenOCD Setup section. For a standard OpenOCD installation on Linux, the configuration files are located in /usr/share/openocd/scripts/board/. Don't forget the leading -f to indicate that the configuration is read from file. Example: -f /usr/share/openocd/scripts/board/st_nucleo_f0.cfg. Note that the scripts folder may be located elsewhere when OpenOCD is installed on your work system as part of a micro-controller development tools package.
- The value for the GDB port field under Debugger should be 3333
Running without Debugging
Use OpenOCD to flash the Release build to the microcontroller
cd <project-directory> openocd -f /usr/share/openocd/scripts/board/st_nucleo_f0.cfg -c "program Release/<executable-name>.elf verify reset exit"
Bootloader
STM32 microcontrollers come with a built-in bootloader on an integrated ROM. Depending on the logical value of the BOOT0 hardware pin or the value of the BOOT0 option byte (OB - stored in a special region in flash memory), the bootloader is executed instead of the user program in flash memory. The bootloader thus runs after the system has been initialized as usual (plus I2C and USB Full Speed drivers). The bootloader will check for data on the USART, I2C and USB serial communication lines, in that order, and run the appropriate subroutine for storing the incoming data in the user program region of the flash memory.
On STM32F042, the bootloader is activated by one of these combinations
- Boot0 (hardware pin) = 1 and nBoot1(bit) = 1 and nBoot0_SW(bit) = 1
- nBoot0 (software bit) = 0 and nBoot1(bit) = 1 and nBoot0_SW(bit) = 0
- Boot0 (hardware pin) = 0 and nBoot0_SW (software bit) = 1 and main flash memory is empty
The BOOT0 hardware pin is pin 31 of the STM32. By default, it is connected to Ground via a pull-down resistor and a solder bridge that can be desoldered for changing the configuration permanently.
Refer to chapter 7 of the application note AN2606 for the specific of the STM32F04xxx bootloader.
OpenOCD and the USART Bootloader
Some STM32 experimentation boards are designed so that the user can select the boot mode with a jumper. The Nucleo STM32F042 does not expose the BOOT0 pin with a header. Furthermore, OpenOCD does not require a physical change on the board in order to flash the user program. So, how does this software-only method of activating the bootloader work?
Using the DFU Bootloader
DFU (Device Firmware Update) is part of the USB standard and specifies the process of sending (firmware) code to a USB-connected device.
The schematic below shows how an external pull-up resistor can be connected to USB_DP if needed.
STM32F04 configuration for DFU system memory boot mode (from AN2606)
Feature/Peripheral | State | Comment |
---|---|---|
USB | Enabled | USB used in FS mode |
USB_DM line | Input/Output | Connect to pin PA11 on STM32. |
USB_DP line | Input/Output | Connect to pin PA12 on STM32. No external pull-up resistor required. |
Interestingly, connecting the USB cable to a USB power outlet prevents the Nucleo from booting into the flashed user program.
Programming
Please download from STMicroelectronics the Programming Manual PM0215 for their STM32F0xxx series Cortex-M0 microcontrollers. The manual is a guide to the low-level instruction set of the processor for programming in ARM Assembly.
STM32F0xxx Instruction Set
Being an ARM Cortex-M0 compatible processor, the STM32F042 implements the ARMv6-M architecture with a modified Thumb instruction set.
Mnemonic | Operands | Brief description | Flags |
---|---|---|---|
ADCS | {Rd,} Rn, Rm | Add with Carry | N,Z,C,V |
ADD{S} | {Rd,} Rn, <Rm|#imm> | Add | N,Z,C,V |
ADR | Rd | label PC-relative Address to Register | - |
ANDS | {Rd,} Rn, Rm | Bitwise AND | N,Z |
ASRS | {Rd,} Rm, <Rs|#imm> | Arithmetic Shift Right | N,Z,C |
B{cc} | label | Branch {conditionally} | - |
BICS | {Rd,} Rn, Rm | Bit Clear | N,Z |
BKPT | #imm | Breakpoint | - |
BL | label | Branch with Link | - |
BLX | Rm | Branch indirect with Link | - |
BX | Rm | Branch indirect | - |
CMN | Rn, Rm | Compare Negative | N,Z,C,V |
CMP | Rn, <Rm|#imm> | Compare | N,Z,C,V |
CPSID | i | Change Processor State, Disable Interrupts | - |
CPSIE | i | Change Processor State, Enable Interrupts | - |
DMB | - | Data Memory Barrier | - |
DSB | - | Data Synchronization Barrier | - |
EORS | {Rd,} Rn, Rm | Exclusive OR | N,Z |
ISB | - | Instruction Synchronization Barrier | - |
LDM | Rn{!}, reglist | Load Multiple registers, increment after | - |
LDR | Rt, label | Load Register from PC-relative address | - |
LDR | Rt, [Rn, <Rm|#imm>] | Load Register with word | - |
LDRB | Rt, [Rn, <Rm|#imm>] | Load Register with byte | - |
LDRH | Rt, [Rn, <Rm|#imm>] | Load Register with halfword | - |
LDRSB | Rt, [Rn, <Rm|#imm>] | Load Register with signed byte | - |
LDRSH | Rt, [Rn, <Rm|#imm>] | Load Register with signed halfword | - |
LSLS | {Rd,} Rn, <Rs|#imm> | Logical Shift Left | N,Z,C |
LSRS | {Rd,} Rn, <Rs|#imm> | Logical Shift Right | N,Z,C |
MOV{S } | Rd, Rm | Move | N,Z |
MRS | Rd, spec_reg | Move to general register from special register | - |
MSR | spec_reg, Rm | Move to special register from general register | N,Z,C,V |
MULS | Rd, Rn, Rm | Multiply, 32-bit result | N,Z |
MVNS | Rd, Rm | Bitwise NOT | N,Z |
NOP | - | No Operation | - |
ORRS | {Rd,} Rn, Rm | Logical OR | N,Z |
POP | reglist | Pop registers from stack | - |
PUSH | reglist | Push registers onto stack | - |
REV | Rd, Rm | Byte-Reverse word | - |
REV16 | Rd, Rm | Byte-Reverse packed halfwords | - |
REVSH | Rd, Rm | Byte-Reverse signed halfword | - |
RORS | {Rd,} Rn, Rs | Rotate Right | N,Z,C |
RSBS | {Rd,} Rn, #0 | Reverse Subtract | N,Z,C,V |
SBCS | {Rd,} Rn, Rm | Subtract with Carry | N,Z,C,V |
SEV | - | Send Event | - |
STM | Rn!, reglist | Store Multiple registers, increment after | - |
STR | Rt, [Rn, <Rm|#imm>] | Store Register as word | - |
STRB | Rt, [Rn, <Rm|#imm>] | Store Register as byte | - |
STRH | Rt, [Rn, <Rm|#imm>] | Store Register as halfword | - |
SUB{S} | {Rd,} Rn, <Rm|#imm> | Subtract | N,Z,C,V |
SVC | #imm | Supervisor Call | - |
SXTB | Rd, Rm | Sign extend byte | - |
SXTH | Rd, Rm | Sign extend halfword | - |
TST | Rn, Rm | Logical AND based test | N,Z |
UXTB | Rd, Rm | Zero extend a byte | - |
UXTH | Rd, Rm | Zero extend a halfword | - |
WFE | - | Wait For Event | - |
WFI | - | Wait For Interrupt | - |
Memory Model
Start | End | Size | Label | Access Type | Description |
---|---|---|---|---|---|
0x00000000 | 0x1FFFFFFF | 512 MB | Code | Normal | Region for executable code and data. |
0x20000000 | 0x3FFFFFFF | 512 MB | SRAM | Normal | Region for executable code and data. |
0x40000000 | 0x5FFFFFFF | 512 MB | Peripheral | Device | external |
0x60000000 | 0x9FFFFFFF | 1 GB | External RAM | Normal | Data-only region |
0xA0000000 | 0xDFFFFFFF | 1 GB | External Device | Device | external |
0xE0000000 | 0xE00FFFFF | 1 MB | Private Peripheral Bus | Strongly Ordered | Reserved for core peripheral registers (NVIC, system timer, system control block). Access performed word by word. |
0xE010.0000 | 0xFFFFFFFF | 511 MB | Device | Device | Includes all the STM32 standard peripherals. |
Type | Description |
---|---|
Normal | The sequence of access can be changed by the processor in order to predictively minimize wait times. |
Device | The sequence is preserved relative to other memory accesses of this type or of the Strongly Ordered type. |
Strongly Ordered | The sequence is preserved relative to all other memory accesses |
STM32F042 addresses of interest
- On reset, the main stack pointer (MSP) points at 0x200017e8 in SRAM.
- Option Bytes start at 0x1FFFF800
- GPIO ports (only A, B, and F available)
- A starts at 0x48000000
- B starts at 0x48000400
- F starts at 0x48001400
- SysTick base address is 0xE000E010
- NVIC base address is 0xE000E100
- System Control Block (SCB) base address is 0xE000ED00
Memory Barrier Instructions
In order to optimize performance, the processor may fetch memory contents ahead of execution of a memory access instruction while a previous instruction is being executed. Memory barrier instructions should be used if the program logic depends on the sequence of memory access. These are
DMB ; Data Memory Barrier DSB ; Data Synchronization Barrier ISB ; Instruction Synchronisation Barrier
GPIO
Control Registers
The GPIO port control registers are accessed through memory locations that connect to the Advanced High-performance Bus (AHB) of the Cortex-M0 processor. Each GPIO port is controlled by the registers listed below. In each register, the setting for an individual pin of a GPIO port is stored in certain bits inside the register. Since each port has up to 16 pins and registers are at most 32 bits wide, the setting for each pin can be up to 2 bits wide.
register name | length (bytes) | offset (bytes) | description |
---|---|---|---|
MODER | 4 | 0x00 | mode register, 2 bits per pin, modes: In (0x00), Out (0x01), Alternate Function (0x02), Analog In/Out (0x03) |
OTYPER | 2 | 0x04 | output type register, 1 bit per pin, two types defined: PP (0x00), OD (0x01) |
RESERVED0 | 2 | 0x06 | reserved |
OSPEEDR | 4 | 0x08 | output speed register, 2 bits per pin, three speeds defined: Level1 (0x00), Level2 (0x01), Level3 (0x03) |
PUPDR | 4 | 0x0C | pull-up/pull-down register, 2 bits per pin, three modes defined: NoPull (0x00), Up (0x01), Down (0x02) |
IDR | 2 | 0x10 | input data register, 1 bit per pin, two modes defined: |
RESERVED1 | 2 | 0x12 | reserved |
ODR | 2 | 0x14 | output data register, 1 bit per pin, two modes defined: |
RESERVED2 | 2 | 0x16 | reserved |
BSRR | 4 | 0x18 | bit set/reset register, 2 bits per pin, 1 bit for set in the lower half word, 1 bit for reset in the upper half word |
LCKR | 4 | 0x1C | configuration lock register, 1 bit per pin within the lower half word, upper half word for locking the complete port |
AFRL | 4 | 0x20 | alternate function register for pins 0 through 7, 4 bits per pin |
AFRH | 4 | 0x24 | alternate function register for pins 8 through 15, 4 bits per pin |
BRR | 2 | 0x28 | bit reset register, 1 bit per pin, two modes defined: |
RESERVED3 | 2 | 0x2A | reserved |
Available GPIO Pins
The Nucleo-32 STM32F042 board comes with GPIO header pins for ports A (registers' base address: 0x48000000), B (registers' base address: 0x48000400) and F (registers' base address: 0x48001400). Specifically, the pins are A0–A12, B0, B1, B3–B7, F0, and F1.
Initialization
System Timer (SysTick)
Control Registers
SysTick, the 24-bit system timer, is controlled and accessed through four consecutive 32-bit memory locations (starting at 0xE000E010) that connect to the registers of the timer over the Private Peripheral Bus.
Address | Name | Access Type | Description |
---|---|---|---|
0xE000E010 | CTRL (SYST_CSR) | read/write | Control and status |
0xE000E014 | LOAD (SYST_RVR) | read/write | Reload value |
0xE000E018 | VAL (SYST_CVR) | read/write | Current value |
0xE000E01C | CALIB (SYST_CALIB) | read-only | Calibration |
Usage
Please refer to section 4.4 of the ARM Cortex-M0 Devices Generic User Guide to learn more about SysTick and how it is used.
CMSIS
We usually want to avoid programming in assembly because it's a tedious and error prone activity. Fortunately, ARM has specified a standard C interface for programming Cortex-M processor. The Cortex-M Standard Interface (CMSIS)
Configuration
Pretty much at the top of the CMSIS header file stm32f0xx.h are the defines for various STM32F0 CPUs. Remove the comment markers from the line
/* #define STM32F042 */
Intrinsic Functions
Instruction | CMSIS intrinsic function |
---|---|
CPSIE I | void __enable_irq(void) |
CPSID I | void __disable_irq(void) |
ISB | void __ISB(void) |
DSB | void __DSB(void) |
DMB | void __DMB(void) |
NOP | void __NOP(void) |
REV | uint32_t __REV(uint32_t int value) |
REV16 | uint32_t __REV16(uint32_t int value) |
REVSH | uint32_t __REVSH(uint32_t int value) |
SEV | void __SEV(void) |
WFE | void __WFE(void) |
WFI | void __WFI(void) |
Register | CMSIS read function | CMSIS write function |
---|---|---|
PRIMASK | uint32_t __get_PRIMASK (void) | void __set_PRIMASK (uint32_t value) |
CONTROL | uint32_t __get_CONTROL (void) | void __set_CONTROL (uint32_t value) |
MSP | uint32_t __get_MSP (void) | void __set_MSP (uint32_t TopOfMainStack) |
PSP | uint32_t __get_PSP (void) | void __set_PSP (uint32_t TopOfProcStack) |