Setting up the STM32F0DISCOVERY board under OS X Yosemite
I recently picked up an STM32F0 Discovery board from Digikey, and set about making it work on the Mac. Some documentation I found was slightly outdated for Yosemite and didn’t cover everything needed.
This is what I had to do:
Install libusb
libusb is a library that wraps common USB interactions so that application developers don’t have to tear their hair out dealing with the vagaries of dealing directly with USB. The STLink programming software will use it.
If you don’t already have it, you’ll need to install Homebrew, a package manager for Mac OS X that makes it easy to install popular open-source libraries.
Once Homebrew is installed, open a Terminal and type this:
brew install libusb-compat
After a short period of time, you will be returned to the bash prompt.
Clone, build and install the STLink programmer software
Originally intended for Linux, this open-source programmer knows how to speak the ST-Link v2 protocol that the Discovery board uses.
git clone git@github.com:texane/stlink.git
cd stlink
./autogen.sh
./configure
make
sudo make install
# enter your password here..
Once the install has completed, you should be able to type which st-flash
and have it return /usr/local/bin/st-flash
(or, if you changed the --prefix
setting in the configure script, wherever you ended up installing it to.)
Install the Mac OS X STLink driver
The driver is included in the stlink git repository so we’ll unpack and install it while we’re here.
cd stlinkv1_macosx_driver
tar -zxvf osx.tar.gz
Convince Yosemite to load unsigned kernel extensions
Added in recent versions of Yosemite, Apple has attempted to crack down on third-party kernel extensions (such as the STLink driver we’re trying to install) by forcing code signing. If you attempt to install the driver right now, you will end up with some error messages and nothing will happen.
Do this:
sudo nvram boot-args="kext-dev-mode=1"
Now restart your Mac. Don’t forget to come back here!
Modify the osx/install.sh file
Edit the osx/install.sh
file in your favorite text editor.
Change the case statement from 10.10)
to 10.10*)
.
Change the references to $KEXT
to osx/$KEXT
.
When you’re done the file should look something like this:
#!/bin/bash
ISOSXLION=$(sw_vers -productVersion)
case $ISOSXLION in
10.6*)
KEXT="stlink_shield10_6.kext"
;;
10.7*)
KEXT="stlink_shield10_7.kext"
;;
10.8*)
KEXT="stlink_shield10_8.kext"
;;
10.9*)
KEXT="stlink_shield10_9.kext"
;;
10.10*)
KEXT="stlink_shield10_10.kext"
;;
*)
echo "OS X version not supported."
exit 1
;;
esac
chown -R root:wheel osx/$KEXT/
cp -R osx/$KEXT /System/Library/Extensions/stlink_shield.kext
kextload -v /System/Library/Extensions/stlink_shield.kext
touch /System/Library/Extensions
Install the STLink driver
After all that we can finally install the STLink driver. Invoke the following from the stlinkv1_macosx_driver
directory:
sudo make osx_stlink_shield
If all goes well, you should see a message about the stlink_shield.kext
being successfully loaded.
Test it out
Run the following:
cd ../ # in the root of the git repository
./st-util
You should see something like the following:
2015-07-10T18:46:38 INFO src/stlink-usb.c: -- exit_dfu_mode
2015-07-10T18:46:38 INFO src/stlink-common.c: Loading device parameters....
2015-07-10T18:46:38 INFO src/stlink-common.c: Device connected is: F0 device, id 0x20006440
2015-07-10T18:46:38 INFO src/stlink-common.c: SRAM size: 0x2000 bytes (8 KiB), Flash: 0x10000 bytes (64 KiB) in pages of 1024 bytes
2015-07-10T18:46:38 INFO gdbserver/gdb-server.c: Chip ID is 00000440, Core ID is 0bb11477.
2015-07-10T18:46:38 INFO gdbserver/gdb-server.c: Target voltage is 2929 mV.
2015-07-10T18:46:38 INFO gdbserver/gdb-server.c: Listening at *:4242...
Install the GCC ARM tools
- Get the Mac installation tarball from here.
- Unpack the tarball with
tar jxvf
to a handy directory (I used$HOME/Code/cross-compilers
) - Add the
bin
directory from the unpacked tarball to your$PATH
. Edit your.bash_profile
or whatever other file launches for your shell.
Make sure the ARM tools are installed properly
Run the following from a new Terminal window:
arm-none-eabi-gdb
You should see this text, among other things:
GNU gdb (GNU Tools for ARM Embedded Processors) 7.8.0.20150304-cvs
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=x86_64-apple-darwin10 --target=arm-none-eabi".
Install OpenOCD
OpenOCD is a nice tool for pushing your code to the device.
If you clone the OpenOCD git repository and follow the directions in this readme you should be up and running with OpenOCD using stlink.
Now you can start building code and deploying it to the discovery board.
Download the basic template project
Mike Szczys has developed a template project that gets you started on the Discovery.
Clone it from Github and build it. It should succeed, if the ARM tools were installed properly. You should end up with a main.elf
file.
If you installed OpenOCD, running make program
will install and launch the program on the Discovery board. You can tweak the timing and reinstall it to make sure that it actually did something.
Stuff should be running, congratulations.
Note that I am unsure as to if the ST license allows redistributing the files from the StdPeriph lib. My template project references the ST files in the Makefile without directly including them in the repo. That said, Mike Szczys’ template project was a bona fide life saver on this one and provided missing chunks such as the startup code, OpenOCD configuration files and linker scripts that I copied.
New projects should use his template project if at all possible.
Download the ST standard peripherals library
These files will be important if you want to write code without checking in the StdPeriph lib files, or if you wish to target a different device.
You can go here to get them.
Some important directories:
Libraries/CMSIS/Include
: Core include filesProjects/STM32F0xx_StdPeriph_Templates
: Device conf headersLibraries/CMSIS/Device/ST/STM32F0xx/Include
: Device headersLibraries/CMSIS/Device/ST/STM32F0xx/Source/Templates
: Device library files (statically link against these)Libraries/STM32F0xx_StdPeriph_Driver/inc
: Peripheral headersLibraries/STM32F0xx_StdPeriph_Driver/src
: Peripheral library (statically link against these too)
Debugging
If you’re anything like me the first time you wrote some code the board didn’t seem to do anything. Don’t worry. The debugger is here.
Once you’ve started the gdb bridge from STLink (in a previous step), launch the ARM GDB and connect to the bridge.
(gdb) target extended-remote :4242
Remote debugging using :4242
Cannot access memory at address 0xffffffff
0x08000358 in ?? ()
You can restart the program from the beginning of execution using monitor reset
, and then step, set breakpoints, etc like you would normally in GDB.
If you have never used GDB before, the RMS tutorial is a handy guide.
Symbols can be loaded like this, prior to connecting to the remote:
(gdb) symbol-file blink.elf
Reading symbols from blink.elf...done.
(gdb) target extended-remote :4242
Remote debugging using :4242
0x080003d8 in WWDG_IRQHandler ()
Problems I encountered
Crashing in ____libc_init_array_from_thumb
I failed to provide -mcpu=cortex-m0
and -mthumb
to the linker even though I had provided it to the compiler. This apparently caused it to break trying to switch instruction sets.
OpenOCD push failed in ocd_bouncer
I had the gdb-server running at the same time. Killing it let me communicate with the device again and push code to it.
Complaining about missing _exit
There is no _exit
in the libc for this device, because where would you exit to on an embedded device?
Stripping sections during linking by passing --gc-sections
to the linker ended up taking care of this problem, as it removed the pieces of libc (such as exit
) that called these missing implementations.
Special Thanks
The following sources were helpful in figuring this one out:
- Huge portions of code lifted from Mike Szczys
- Tons of help from Scott Hilbert
- David Raphael
- David Rojas
- Harris’ Electronics