I was inspired by this great post by Ross Wolin to make (yet) another blink tutorial for the stm32f4-discovery board on Linux. Ross Wolin did a great job writting makefiles for the peripheral library and reading his makefiles showed me how to actually work with the library, which is what I wanted because I like to write my own Makefiles and know what happens during the compilation process. IDEs like Eclipse are OK, but when learning, they stand in my way. Ross’s code however does not really use the peripheral library. This led me to adapt his code and Makefile and make a (almost) new one. His code can be found on Github. There is also a very cool GPIO tutorial by Elia for the stm32f4 here. Elia put his Makefile on Github, so I had one more case to study. Elia’s code is very obscure if you are just getting startet with C code, so his code made me want to write some clearer code.
In order to develop for the stm32f4-discovery board on Linux you need a few tools:
- GNU toolchain for the ARM Cortex-M. This toolchain contains the compiler (gcc), debugger (gdb) and other utilities used to generate machine code for the ARM-architecture. You can download it for free from Launchpad here:
After downloading, extract the archive somewhere. It does not matter where you extract it. I have put it under /opt/gcc-arm-embedded/ so the path to the gcc compiler is /opt/gcc-arm-embedded/gcc-arm-none-eabi-4_7-2013q1/bin/arm-none-eabi-gcc. Your download may have another version number.
- The stlink utility written by texane. The package contains two programs: st-util and st-flash.
st-util is a gdb server (that is a server taking commands from gdb over network) which on one side connects to the serial port of the discovery board and on the other side listens at TCP port 4242 on localhost, where gdb is also connecting and sending instructions. Such instructions are for instance loading the program into the flash memory, setting break points and so on. st-util converts the instructions from gdb into actual hardware signals which the board understands and sends them to the serial port of the board. This is how you debug on the chip the discovery board.st-flash is used to write or read the flash memory of the board. You can use this to just flash the executable without debugging. Note that after loading the programm with st-util and gdb, the program stays in memory so you don’t have to flash again.
You can download stlink here:
Installation and usage instructions are found in the downloaded archive (or cloned repository, if you use git). Don’t forget to copy the udev rules.
Archlinux users: you’re lucky, stlink is in the AUR.
- STMF4 Discovery board firmware package. This is a package of headers and source files which you can use to access the board peripherals by using symbolic names. Without this package, you have to know the exact memory mapping of the board and do a lot of initialization work before you actually write some useful code. You will compile the C source files and link them together with your own code.
You can download the peripheral library here:
After downloading, extract it somewhere in your workspace. Its exact location will be entered in the makefile. In my case, I have extracted the archive into
$HOME/workspace/stmso the location of the Utilities folder of the library is
- make. This should be preinstalled on all Linux machines.
This is actually all you need to develop for the stm32f4 discovery board on Linux (except the board itself).
Code sample, a makefile and usage instructions can be found here:
All files written by me are commented.
Writting the makefile
If you have no problems reading the makefile I wrote, you can skip this section because I will try to explain a basic strategy for writting a makefile when dealing with an external library like the standard peripherals library for the stm32f4 board.
Writting a makefile is more or less a matter of trial an error. After setting up the compiler’s flags like
-mcpu=cortex-m4 and so on, you try to compile your code. If you get errors about missing headers, you search for the missing header file and add its directory to the “include directories” option of gcc (that is to the “
-I” option). If you get link-errors about gcc not finding some reference or function, you search the library for the C-file implementing that function and add this file to the list of source files to compile. Then you try again to compile.
Thus, in the makefile I wrote, you find two variables:
SRCS. Every time I was missing a header file, I used my file manager to search the library’s folder for that file and added it’s directory to the variable
INC_DIRS. The variable
INCLUDE, defined later, is build by using the make-function
addprefix to add the prefix
-I to every directory in the variable
INC_DIRS. It contains a string like “
-Idirectory1 -Idirectory2 -Idirectory3“.
INCLUDE is then passed as argument to gcc, which will search those directories for the missing header files.
The second variable,
SRCS (for “sources”), holds a list of all source files to compile. Every time a got an
undefined reference error to some function, I used the file manager to search for the C-file implementing that function and added the file name to
SRCS (only the base name, without path). The next thing to do after adding a file name to the sources list, is to tell make where to look for that file, because it will not be in the current directory and make will not find it. You do this by using the make-function
vpath (for “virtual path”). Thus, the line
vpath %.c $(STM_SRC) tells make to look in the directory
$(STM_SRC) every time it does not find a .c file in the current directory.