Rob Laswick
May 10 2013
www.laswick.net
This project simply includes a set of easily customizable scripts that automatically download, configure, patch, build, and install the entire ARM toolchain (including binutils
, gcc
, newlib
, gdb
, and openocd
).
Currently the scripts only support the Cortex M3, Cortex M4, and Cortex M4F. However, support for other ARM cores can be added relatively easily.
build_toolchain
is the top level "master" script that calls all the other scripts, although the individual scripts can be run stand alone as well.
Before running build_toolchain
there are 2 parameters at the top of the file you'll want to edit:
WORKING_DIR
is the location where the toolchain will be built. Once it's built and you're happy with it, this directory can be deleted (it's actually quite large, ~2.6GB).
PREFIX
is the location where the final toolchain will be installed.
You can also specify the exact version of each of the tools you want your toolchain to use, which is pretty cool.
If your development host is setup correctly you can simply run ./build_toolchain
and walk away! A full build takes approximately 2 hours.
You get all the standard GNU tools and utilities with support for multilibs, a multilib and reentrant C library, the gdb debugger, and openocd (an awesome open source gdb server with support for a large number of hardware interfaces).
Like most non-commercial toolchains, you don't get any processor specific header files and start code, or any hardware specific linker scripts.
It's important to note, that as long as you know what you're doing, or have the drive and curiosity to find out, these key files are not impossible to write yourself (despite what your mother told you). In fact, I provide all of these files for all the projects on laswick.net (take that mom!).
The first thing you'll likely want to do is add the location of the tools to your PATH environment variable. This is typically done by adding a line similar to the following to your shell profile config file (i.e. .bash_profile
or .profile
depending on the distro you're running):
PATH="$PATH:$HOME/opt/arm-toolchain/bin:$HOME/opt/arm-toolchain/openocd/bin"
You'll need to run . ~/.profile
(or . ~/.bash_profile
) in each shell for this update to take effect (or log out and back in again).
There are Makefiles provided for all the projects on laswick.net, but a few key things to keep in mind when using Makefiles are:
-
I typically reserve the file
Makefile
(note the uppercase 'M') as a project template Makefile. -
I typically reserve the file
makefile
(note the lowercase 'm') to be used as asymlink
to the specific Makefile being used (i.e. flashLed.mak). Sincemake
searches formakefile
and thenMakefile
(in that order), yoursymlinked
Makefile will be used. This allows you to simply runmake
to build your project, rather than having to type outmake -f flashLed.mak
everytime. -
Ensure you pass the
-nostartfiles
flag when linking to prevent the tools from trying to include genericstart code
which you don't want. -
Do not link the core libraries (
libgcc
andlibc
) explicitly. Link usinggcc
instead ofld
to letgcc
determine which version of each library to pull in (you'll need to pass in yourCPU_FLAGS
(i.e. -mcpu=cortex-m4 -mthumb, etc) togcc
when linking for this to work correctly).
Also, for convenience, I highly recommend symlinking
the key files produced by a successful build as out.*
, i.e.:
out.s : disassembly listing
out.hex : hex record
out.elf : full image
out.map : map file
It's often a good idea to use a .gdbinit
script whenever you're using gdb
. The .gdbinit
script is simply a small text file, generally located in the directory you're working in, and typically used to automate a few tasks such as:
-
connecting to the gdb server (
openocd
). -
setting breakpoints on the standard default locations (i.e. the
assert()
stub, and yourdefault_interrupt_handler
). -
defining a
reset
command for your target.
A .gdbinit
script could look similar to:
target remote localhost:3333
b _deafult_fault_handler
b __assert_func
define reset
monitor reset init
end
gdb's load
command programs an image into memory on the target board.
In some cases when using gdb
with openocd
, gdb's load
command is unable to program the FLASH memory on the target. One way to work around this annoyance is to override the load
command by adding the following to the end of your .gdbinit
script:
define load
monitor flash write_image erase "out.axf" 0 elf
reset
end
This works quite well, but keep in mind this now binds the load
command to exclusively programming the FLASH. If this is an issue for you (i.e. you need support for RAM builds), don't redefine load
, simply use another name, like prog
, etc.