Table of Contents
STM32 Toolchain Setup
There are two peripheral libraries which can be used. Firstly is the official ST libraries, or alternately libopencm3. There are more examples available for the ST libraries, however libopencm3 is nicer to use, but still in development.
STM32 Intro (Jon) slides here: stm32_intro_ukhas14.pdf
Linux, libopencm3
Step 1 - Install toolchain
Ideally you should be able to apt-get install the tools, however the version in the repo is broken slightly and doesnt have the 'nano' version of newlib (printf etc)
- For use of newlib-nano, best to grab the binary tarball from https://launchpad.net/gcc-arm-embedded. Latest at time of writing is gcc-arm-none-eabi-4_8-2014q2 (-linux or -mac one as appropriate).
- Extract to somewhere like /usr/local and add /usr/local/gcc-arm-none-eabi-4_8-2014q2/bin to PATH, by adding:
export PATH=/usr/local/gcc-arm-none-eabi-4_8-2014q2/bin:$PATH
to your ~/.bashrc (assuming using bash).
- Then to use the amended PATH:
$ source ~/.bashrc
- Alternatively (and for when they fix newlib nano in the repos), install from ppa:
$ sudo add-apt-repository ppa:terry.guo/gcc-arm-embedded
$ sudo apt-get update
$ sudo apt-get install gcc-arm-none-eabi
- Check install is working by running
$ arm-none-eabi-gcc –version
Step 2 - Clone a blank project
Step 3 - Fetch and build libopencm3
cd
into the root of the repo- Run
$ git submodule update –init
to fetch libopencm3. cd
to the libopencm3 directory and run$ make
to build.
Step 4 - Adjust for your device
We've not got things set up for the F1 (or other) series yet, give us a shout if this is what you're after and we can help.
Open up Makefile in firmware/src/. Adjust the last line for either the F0 or F4 as appropriate
include ../common/Makefile.f0.include
ORinclude ../common/Makefile.f4.include
Now open up common/stm32f0-discovery.ld or common/stm32f4-discovery. Adjust the RAM and ROM lengths as appropriate for your particular device. If you want to change the name of this file to satisfy your OCD, do so and then make the relevant change in firmware/common/Makefile.fx.include (where x=0 or 4 as appropriate).
Step 5 - Install flashing/debug software
- Clone texane's st-link from https://github.com/texane/stlink
- Follow the “compiling” instructions to produce the
st-util
andst-flash
binaries
Step 6 - Build
A libopencm3 LED blink example is provided in firmware/src/main.c.
cd
to this directory and build the firmware with $ make
- this should produce the main.elf
file.
If you're having issues then use $ make V=1
for more verbose build output.
Step 7 - Flash the firmware
- Connect the board to the machine via the USB port
- Erase the device with
$ st-flash erase
- Make the .bin version of the binary with
$ make bin
- Flash the firmware to the device with
$ st-flash write main.bin 0x8000000
- 0x800000 is the start address of the flash memory in the device memory address space
On Linux, st-flash needs root privileges ( sudo ./st-flash …
) to access the USB system until you set up udev rules
Windows, Makefile, libopencm3
In theory you should be able to follow the linux instructions. You will need to have make installed, as well as python.
Windows, IDE
This guide will get a windows IDE based toolchain up and running. There is the option of either using ST or openlibcm3 libraries (see above). This guide uses 'coIDE,' however there are several available. This has the advantage that the ST libraries are 'built in', and so you just need to click on the ones you want and they are copied into the project. libopencm3 can still be used, but it requires a few more tweeks
Step 1 - Install
- Download compiler tools (the windows .exe) from: https://launchpad.net/gcc-arm-embedded
- Make sure the add to path .bat script (Launch gccvar.bat) is run at the end of the installation
- Install coIDE: direct links: http://www.coocox.org/Tools/ , current latest http://www.coocox.org/Tools/CoIDE-1.7.7.exe (they have an annoying autoupdater thing which these direct links avoid)
Step 2 - Install programmer drivers
These are the drivers and downloading program for ST-Link, which is found on the ST development boards
- Install the ST-Link/V2 driver: http://www.st.com/web/en/catalog/tools/PF258167 (XP-W7); http://www.st.com/web/en/catalog/tools/PF259459 (W8)
- Install the Link-Utility (this can be used as a stand-alone application to load a .hex onto a STM32) http://www.st.com/web/en/catalog/tools/PF258168
The STM32s also have a UART booloader, the tool to download is here: http://www.st.com/web/en/catalog/tools/PF257525 (you dont need this if you intend to use the SWD interface on the development boards)
Step 3 - Tell coIDE where the tools are (first time only)
- Open coIDE
- go Project → Select toolchain path
- Select toolchain install directory (eg C:\Program Files (x86)\GNU Tools ARM Embedded\4.8 2014q2\bin )
Step 4 - Create a new project
- Project → New project
- Type a project name, select a project path (you probably dont what the default one)
- Click Chip
- Select ST→…
- A blank main.c should be created
Step 5 (ST Libraries)
(skip to the next step if you want to use libopencm3)
This example will now get an LED flashing. After project creation the 'repository' window should be showing, which has a selection of libraries that can be copied to the project. (if not, go view→repository)
With the repository showing, click 'GPIO'. A whole load of files should have been copied into the project. Also click 'C library' (for printf/sprintf etc).
Open main.c, and copy in the sample code below
Step 5 (libopencm3 Libraries)
Firstly add the libopencm3 files to the project directory. This can be fetched from the libopencm3 repository and compiled as per above instructions, or run git submodule add https://github.com/libopencm3/libopencm3 .\firmware\libopencm3
if you want to add it to an existing repository. Since it is unlikely for all the tools (make, python and others) to be set up correctly. As a result, a precompiled version is available here. Unzip the contents into a separate libopencm3 folder along side your project
The final file needed is part of the linker script. Copy this file (f4) or this file (f0) along side your project. Note that this file needs editing depending on how much flash/RAM the target has
Now set up the IDE with these files:
- Right click on the project → Configuration
- Under compile, add STM32F0 (change as appropriate) to the defined symbols section; then remove USE_STDPERIPH_DRIVER (if it is there)
- Under compile, add libopencm3/include to the IncludePaths
- Under Link, add opencm3_stm32f0.a to the linked libraries (located in libopencm3/lib)
- Under Link, tick 'Discard unused sections' and 'Dont use the standard system startup files'
- Under Link, untick 'Use memory layout from memory window' and 'Enable LTO'
- Under Link, select the scatter file as stm32f0-discovery.ld
Step 6 - Download and run
To run the program:
- Click Project → Build
- Click Flash → Program Download (downloads and runs), OR
- Click Debug → Debug (to enter debug mode)
coIDE defaults to STLink to download programs, however if you are having issues, check 'Download' settings in the project configuration
Code Listings
ST Libraries (using API)
#include "stm32f0xx.h" #include "stm32f0xx_gpio.h" #include "stm32f0xx_rcc.h" //include further headers as more peripherals are used int main(void) { //turn on GPIOC //IMPORTANT: every peripheral must be turned on before use RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE); //init structure for GPIO GPIO_InitTypeDef GPIO_InitS; GPIO_InitS.GPIO_Pin = GPIO_Pin_9; //the pin we are configuring GPIO_InitS.GPIO_Mode = GPIO_Mode_OUT; //set to output mode GPIO_InitS.GPIO_OType = GPIO_OType_PP; //set to push/pull GPIO_InitS.GPIO_PuPd = GPIO_PuPd_NOPULL; //no pullup resistors GPIO_InitS.GPIO_Speed = GPIO_Speed_50MHz; //set to max speed GPIO_Init(GPIOC, &GPIO_InitS); //write this config to GPIOC while(1) //flash forever { GPIO_SetBits(GPIOC, GPIO_Pin_9); //set pin on int32_t i = 4800000; while(i) i--; //delay a bit GPIO_ResetBits(GPIOC, GPIO_Pin_9); //set pin off i = 4800000; while(i) i--; //delay a bit } }
libopencm3 (using API)
#include <libopencm3/stm32/rcc.h> #include <libopencm3/stm32/gpio.h> #define LED_PORT GPIOC #define LED_PIN GPIO9 int main(void) { // Set clock to 48MHz (max) rcc_clock_setup_in_hsi_out_48mhz(); // IMPORTANT: every peripheral must be clocked before use rcc_periph_clock_enable(RCC_GPIOC); // Configure GPIO C.9 as an output gpio_mode_setup(LED_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED_PIN); // Flash the pin forever while(1) { gpio_set(LED_PORT, LED_PIN); int32_t i = 4800000; while(i) i--; gpio_clear(LED_PORT, LED_PIN); i = 4800000; while(i) i--; } }
ST Libraries (direct register manipulation)
while(1) //flash forever { GPIOC->BSRR |= (1<<9); int32_t i = 4800000; while(i) i--; GPIOC->BRR |= (1<<9); i = 4800000; while(i) i--; }