STM32F4 (07VG) Discovery Toolchain for OSX
For those of you who know what you're doing - there is a "Speed Version." Have at it.
This has been tested on 10.6.8, 10.7.5 & 10.8.2
What is a Toolchain?
A collection of tools to build code. More to the point for us: it is a collection of tools to build code on one platform (your machine) to run on a different platform (your microcontroller). The CrossPack toolchain I have been using is made to build code on my machine that will run on the ATMega324P. Now, we need a toolchain for the Discovery board which is ARM-based. Arm is readily available but the proprietary tools can be a pain to use - and they generally charge and arm-and-a-leg for those tools. Pun intended. So, we need a compiler, linker, and libraries that will let us develop for ARM - and we want it for free using Open Source tools.
The 4 flavors of effort
Build Each Element Yourself
PRO: kind of a geek right-of-passage because it is typically NOT a good time and you end up doing it more than once before you get it right
CON: it is typically NOT a good time and you end up doing it more than once before you get it right
PRO: but hey, you'll probably learn ALOT and you'll get to claim that "cred"
PRO: Open Source!
Pre-built versions of each element
PRO: This is great middle ground, as it isn't all handed to you like the CrossPack package so you have more room to learn more about what you are doing.
Much of the time there just isn't a "CrossPack" like setup anyway
CON: It's not handed to you like CrossPack
PRO: Open Source!
Proprietary Packages
BIG CON: Expensive
*Usually* designed for Windows or Linux - but that is getting better
Other slick tools
PRO: It's all there for you - which is great. But sometimes learning to use what they hand you takes as much time as building or assembling your own version
CON: It might be doing so much for you that you don't really know what is going on behing the scenes - which makes it hard to fix things that break.
OpenSource Packages
Like CrossPack, these are great when you can find them.
PRO: They provide all the tools and libraries for you, pre-built, packaged and ready to use.
PRO: CrossPack provided the Makefiles for me so I didn't have to build one
PRO: Other slick tools.
PRO: Open Source!
We are going with a combo of Options A & B. We will gather the prebuilt tools - taking advantage of the wheels other people invented - and build a few others so we can start coding instead of fighting other people's tools.
What You'll Need
Installs & Dependencies
Homebrew and MacPorts.
I ended up using both. Homebrew handles some packages better than MacPorts from what I experienced. For instance, you wont be able to run the Macports version of OpenOCD because stlink wont work - but Homebrew's version works great. But MacPorts is more verbose - thus pointing out problems that Homebrew does not. (Like when you have the wrong version of XCode.)
XCode 4
If you were just using CrossPack - or developing code at all - you probably already have this.
Make sure you included the Command Line tools. On 10.7+ you do this by opening XCode -> Preferences -> Downloads -> select "Install" on the Command Line tools
However, while installing this toolchain on a second Mac, I didn't realize until later (while executing make cross-gcc ) that the machine I was on had XCode 3.2. Because of this I was able to start the build but it failed on the libgcc portion toward the end of the build. Which is annoying because those builds take so long as it is. I discovered the issue because I decided to try just installing arm-none-eabi-gcc with MacPorts. MacPorts pointed out I was using an older version - Note: Homebrew did not know this. It just didn't show me any options for the compiler I was looking for - I decided to keep both MacPorts and Homebrew on my machine for this reason.
Eclipse (optional).
This is optional but if you like IDEs I will show you how to get it working - or at least set up.
GCC Dependencies.
mpfr
gmp
libmpc
libelf
texinfo
Just Use Homebrew:
brew install mpfr gmp libmpc libelf texinfo
arm-eabi-toolchain ZIP File.
Download this from https://github.com/jsnyder/arm-eabi-toolchain
or, if you have git:
git clone https://github.com/jsnyder/arm-eabi-toolchain.git
Then unzip the file
cd into the directory
Open the README for instructions, which are essentially this:
make install-cross
CC=clang make cross-binutils cross-gcc cross-newlib
make cross-gdb
There are further tweaks available on the page link above if you need them, but I did not.
This process takes a while....go get coffee, read a book, take a nap....
arm-none-eabi-gcc
This is where I used Macports. This is because I am trying to keep my environment separated and I know Macports will install this at /opt/local/bin which I then put into my environment setup script as explained later. I am sure there are other ways to do this. Moving on...
sudo port install arm-none-eabi-gcc
OpenOCD.
You'll start OpenOCD when you want to connect to your board.
brew install openocd
wget
brew install wget
STM32F4 Discovery Firmware and Peripheral files.
wget http://www.st.com/internet/com/SOFTWARE_RESOURCES/SW_COMPONENT/FIRMWARE/stm32f4discovery_fw.zip
wget http://www.st.com/internet/com/SOFTWARE_RESOURCES/SW_COMPONENT/FIRMWARE/stm32f2xx_stdperiph_lib.zip
Unzip the files into your home directory:
unzip stm32f4discovery_fw.zip
unzip stm32f2xx_stdperiph_lib.zip
Makefiles!
THIS is a great example of pre-invented wheels for you. Thank You jthomson.towhee.org
wget http://jthomson.towhee.org/stm32f4discovery_files/STM32F4DISCOVERY_Makefiles.zip
Unzip this file in your home directory. (I have attached a Makefile from this which is edited specifically for use here. You will use my version for now. )
My Attached Files.
Download the attached example Makefile and main.c file.
Session-based Environments
When you need a couple different compilers and tools on your system, you don't want the key words and other idiosyncrasies that may be *called* the same but *implemented* differently between them to break your work. It can cause confusing problems as you switch between platforms. Instead, create a function in your .bashrc file you can call as you need it. NOTE: This means when you close out of your terminal or terminal session your environment will go back to the way it was before - so you'll need to re-execute the command when you want to develop on this board.
You can do this by putting something like this in your .bashrc file:
function stmenv () {
export PATH="/opt/local/bin:$PATH"
export STMSDKDIR="$HOME/STM32F4-Discovery_FW_V1.1.0"
}
*Don't forget to source the file with .~/.bashrc after you save and exit the file!
When you know you are going to be developing for the STM32F4 Discovery board, just open a terminal and type stmenv. If you close this terminal session, keep in mind the need to type this again when you want to develop for this board.
Just type stmenv in your terminal after you install the arm-none-eabi-gcc below. If you fail to do this (or have an error in the function), you'll probably end up using the compiler at /usr/bin/gcc instead of /opt/local/bin which will just fail when you use make flash. OR, as I ran into a couple times, you will get an error that the st32f4_discovery.h file can't be found.
The Makefile
Generally if you use an IDE you write some code, press a button, it does something, and then spits out your .bin .hex .elf or whatever file you need. We aren't using an IDE so, like using CrossPack, we use a makefile.
You need a makefile for each project, just like CrossPack. The difference being CrossPack would graciously create a template makefile for you whenever you started a new project. Here, you can just copy my example (and use it like a template) into your project directories and tweak it to your needs.
I have already made some tweaks for you:
For starters, when I pulled off an example Makefile from the .zip file off jthomson's site, it was configured for *his* file system. My system is not laid out the same - yours may be different too. So, after learning a little more Make-fu, I abstracted those parts of the Makefile to use my current environment (See the Session-based Environments section.) These changes will likely work great for your system by using your $PATH variable instead of hardcoded paths. Specifically:
I commented out this line and deleted any other references to this TOOLCHAIN_PATH variable:
TOOLCHAIN_PATH:=~/sat/bin
because without it, the path listed in my $PATH variable is used instead.
I commented out this line:
TOP:=$(shell readlink -f "../..")
and replaced "TOP" with "STMSDKDIR" which stands for the SDK file for the STM board. STMSDKDIR is defined in my .bashrc file by the line:
export STMSDKDIR="$HOME/STM32F4-Discovery_FW_V1.1.0"
Added this line at the top to use the shell I prefer:
SHELL := /bin/bash
(See the attached copy of my Makefile)
Another thing a makefile is REALLY good for, is automating commands that mess with address handling. For instance, a tutorial I was reading as I worked on this project had you retype the hex-address *every time* you wanted to flash code to the device. That is a VERY easy way to accidentally flash to the wrong address - resulting in potentially catastrophic (or at least confusing) results. So, after learning how to automate this process from a guru friend, I added these lines to my makefile:
flash: $(TARGET).bin
echo -ne "reset halt\nflash write_image erase $$(PWD)/$< 0x08000000 bin\nreset run\nexit\n" | nc localhost 4444
I explain the rest of the text later - but see that 0x08000...and-some-more-zeros number? That number is really easy to mistype. And frankly, who wants to remember that command anyway? So this will allow you to type make flash instead. make flash will first make sure you have the code compiled into a .bin, .hex, etc, push the file to your board with the correct address, then exit the session. Neat trick, eh? I thought so. Makefiles are great.
Talking to the STM32F4 board
Can your machine see the board?
Let's find out.
Plug in both the mini and the micro usb to your board and your machine. The board will power on and you'll see some Demo code making the LEDs between the buttons flash and rotate in their stock Demo sequence.
In your terminal session, enter:
system_profiler SPUSBDataType
You should see something like this in the list it presents you:
STM32 STLink:
Product ID: 0x3748
Vendor ID: 0x0483 (STMicroelectronics)
Version: 1.00
Serial Number: SÿpIUW
Speed: Up to 12 Mb/sec
Manufacturer: STMicroelectronics
Location ID: 0xfa130000 / 6
Current Available (mA): 500
Current Required (mA): 100
Great!
Starting OpenOCD
openocd -f /usr/local/share/openocd/scripts/stm32f4discovery.cfg &
The ampersand at the end is telling this to start "in the background".
If you want openocd to tell you what it's doing as it's doing it remove the ampersand and open another terminal/tab to execute this command as seen below.
Starting OpenOCD with an absolute path and running it in the fore-ground:
/usr/local/bin/openocd -f /usr/local/share/openocd/scripts/board/stm32f4discovery.cfg
See the which command-use below if you know you have openocd installed and these commands aren't working. It may just mean openocd is in a different directory.
If you are not running OpenOCD in the background, you should see a bunch of output like this:
...
libusb: 1.581668 info [op_handle_events] checking fd 8 with revents = 1
libusb: 1.581676 info [darwin_handle_callback] handling bulk completion with kernel status 0
libusb: 1.581686 info [ep_to_pipeRef] converting ep address 0x02 to pipeRef and interface
libusb: 1.581691 info [ep_to_pipeRef] pipe 2 on interface 0 matches
libusb: 1.581951 info [darwin_async_io_callback] an async io operation has completed
libusb: 1.581972 info [op_handle_events] checking fd 6 with revents = 0
libusb: 1.581980 info [op_handle_events] checking fd 8 with revents = 1
libusb: 1.581989 info [darwin_handle_callback] handling bulk completion with kernel status 0
libusb: 1.581998 info [ep_to_pipeRef] converting ep address 0x81 to pipeRef and interface
libusb: 1.582003 info [ep_to_pipeRef] pipe 1 on interface 0 matches
libusb: 1.582142 info [darwin_async_io_callback] an async io operation has completed
libusb: 1.582159 info [op_handle_events] checking fd 6 with revents = 0
libusb: 1.582167 info [op_handle_events] checking fd 8 with revents = 1
libusb: 1.582175 info [darwin_handle_callback] handling bulk completion with kernel status 0
Info : stm32f4x.cpu: hardware has 6 breakpoints, 4 watchpoints
Boss it around vs interactive mode
Start OpenOCD as above.
An interactive session with the board can be started with:
telnet localhost 4444
So far, the only time I have used the interactive session is to type "help" to get a list of the commands the board understands. Something VERY handy when I was referencing tutorials for older STM32 board revs that use slightly different commands.
But for just flashing the device using my makefile with make flash, I just want to boss the board around then get out - NOT use an interactive session. You do this with netcat like this:
echo -ne "flash probe 0\nexit\n" | nc localhost 4444
Don't have netcat? Use Homebrew.
Say "Hello!" with flash probe 0
Enter:
echo -ne "flash probe 0\nexit\n" | nc localhost 4444
You should see a few helpful pieces of info come back from the board, like its ID, Size, and start of the flash area:
????????Open On-Chip Debugger
> flash probe 0
device id = 0x10016413
flash size = 1024kbytes
device id = 0x10016413
flash size = 1024kbytes
flash 'stm32f2x' found at 0x08000000
> exit
Flash Your Hello World (LEDs)
Plug your board to your machine. Start a terminal session if you have not already. Don't forget to use the stmenv command I explain in "Session-based Environments."
Rename my Makefile and move it into this directory:
mv Jens_Makefile_Example_STM32F4_Discovery_With_OSX Makefile
mv Makefile /Users/jkniss/STM32F4-Discovery_FW_V1.1.0/Project/Demonstration
Save the original copy of main .c and copy mine to replace it:
mv /Users/jkniss/STM32F4-Discovery_FW_V1.1.0/Project/Demonstration/main.c /Users/jkniss/STM32F4-Discovery_FW_V1.1.0/Project/Demonstration/main.bak
mv main.c /Users/jkniss/STM32F4-Discovery_FW_V1.1.0/Project/Demonstration/
cd into the directory "STM32F4-Discovery_FW_V1.1.0/Project/Demonstration". For me:
cd /Users/jkniss/STM32F4-Discovery_FW_V1.1.0/Project/Demonstration
My main.c file is an edited version of the stock demo from the ST.com firmware files you extracted - the same Demo your board runs the first time you plug it in. I simply changed the LED behavior so you can tell your flash was successful just by looking at the board.
From the ../../STM32F4-Discovery_FW_V1.1.0/Project/Demonstration directory, type:
make clean
make flash
NOTE: You should always use make clean before make flash.
Instead of the four rotating and blinking lights you should see two.
The rest I will leave to your research on what to do with this board, where the peripherals are, how to connect things etc.
Commands You Should Know
which
Lets you see where the tool you are looking for has been put in your filesystem. It helps you when you're thinking "did that get put in /opt/local/share? Or /usr/local/share?"
It will also tell you if you even have the tool you are looking for on your machine.
Example:
which gcc
Gives me this:
/usr/bin/gcc
--version
Let's you figure out which version of that tool you have.
You'll care about this ALOT when you have tried 6 different tutorials that all recommended you instal different things and you can't keep them all straight while you are figuring out which one will actually work.
Example:
gcc --version
Gives me this:
i686-apple-darwin10-gcc-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5666) (dot 3)
Using Eclipse
If you prefer to use an IDE, go to the following website and start with Step 3 (once you download and open Eclipse). The link to the Eclipse version you want is include in the link below and in the Sites list at the end of this tutorial. JUST do the stuff for Eclipse.
http://www.alexwhittemore.com/open-source-ide-and-toolchain-for-the-stm32f4-discovery-on-mac-osx-lion/
I don't use IDEs so beyond getting it configured properly as in Alex's tutorial - I can't help you much.
REFERENCES
This tutorial is based on a smashed-together version of these and on my own experimentation of what worked on my own system:
Thank you Jeff Buttars, Dangerous Prototypes and Hack A Day
http://www.alexwhittemore.com/open-source-ide-and-toolchain-for-the-stm32f4-discovery-on-mac-osx-lion/
http://pulkomandy.tk/_/_Electronique/_Discovering%20the%20STM32F3%20Discovery
https://jethomson.wordpress.com/2011/11/17/getting-started-with-the-stm32f4discovery-in-linux/
Helpful Tutorials and pages:
Homebrew: http://mxcl.github.com/homebrew/
Setting up Eclipse for your Mac (optional): http://www.alexwhittemore.com/open-source-ide-and-toolchain-for-the-stm32f4-discovery-on-mac-osx-lion/
Github arm-eabi-toolchain repository: https://github.com/jsnyder/arm-eabi-toolchain
Eclipse Indigo zip-file page: http://www.eclipse.org/downloads/download.php?file=/technology/epp/downloads/release/indigo/R/eclipse-java-indigo-macosx-cocoa.tar.gz
Setting up your toolchain: http://pulkomandy.tk/_/_Electronique/_Discovering%20the%20STM32F3%20Discovery
STM32f4 Peripherals Library: http://www.microcodes.info/getting-st-perhipial-library-in-a-mikroc-arm-project-249245.html
Makefiles and STM32F4 firmware files: https://jethomson.wordpress.com/2011/11/17/getting-started-with-the-stm32f4discovery-in-linux/
More Examples and usage once you get it up and running: http://www.triplespark.net/elec/pdev/arm/stm32.html
Bus-Blaster, JTAG, and flashing with GDB use: http://www.nabiltewolde.com/programming-the-stm32f4-discovery-with/
The Speed Version
Get Xcode 4 w/ the Command Line Tools
Get Home Brew
Get MacPorts
Download my Makefile and main.c file to your home directory
mv Jens_Makefile_Example_STM32F4_Discovery_With_OSX Makefile
mv STM32F4-Discovery_FW_V1.1.0/Project/Demonstration/main.c STM32F4-Discovery_FW_V1.1.0/Project/Demonstration/main.bak
mv Makefile STM32F4-Discovery_FW_V1.1.0/Project/Demonstration
mv main.c STM32F4-Discovery_FW_V1.1.0/Project/Demonstration
From your HOME directory:
brew install mpfr gmp libmpc libelf texinfo wget openocd
sudo port install arm-none-eabi-gcc
wget http://www.st.com/internet/com/SOFTWARE_RESOURCES/SW_COMPONENT/FIRMWARE/stm32f4discovery_fw.zip
unzip stm32f4discovery_fw.zip
wget http://www.st.com/internet/com/SOFTWARE_RESOURCES/SW_COMPONENT/FIRMWARE/stm32f2xx_stdperiph_lib.zip
unzip stm32f2xx_stdperiph_lib.zip
wget http://jthomson.towhee.org/stm32f4discovery_files/STM32F4DISCOVERY_Makefiles.zip
unzip STM32F4DISCOVERY_Makefiles.zip
git clone https://github.com/jsnyder/arm-eabi-toolchain.git (you might have to unzip this, I can't remember...)
cd arm-eabi-toolchain
make install-cross
export PATH=/Users/<your user>/arm-cs-tools/bin:$PATH (or add this to your .bashrc or .profile)
CC=clang make cross-binutils cross-gcc cross-newlib (should work, if not try: CC=/usr/bin/gcc-4.2 make cross-binutils cross-gcc cross-newlib)
make cross-gdb
make clean
cd
vi .bashrc
Add this to the file:
function stmenv () {
export PATH="/opt/local/bin:$PATH"
export STMSDKDIR="$HOME/STM32F4-Discovery_FW_V1.1.0"
}
Save and Exit the file
source .bashrc
stmenv
cd STM32F4-Discovery_FW_V1.1.0/Project/Demonstration/
Plug in your board
system_profiler SPUSBDataType
Make sure you see the Board
openocd -f /usr/local/share/openocd/scripts/stm32f4discovery.cfg &
echo -ne "flash probe 0\nexit\n" | nc localhost 4444
Make sure you see the Device Info
make clean
make flash
You should see two instead of four LEDs flashing in the center of the board.
ERRATA and Troubleshooting
brew install openocd FAILS
While working on the 10.8.2 version of this, I was building the toolchain on a visiting French professor's machine. Aside from the novel - and speed-bump like - experience of using a French keyboard, I was having some strange issues with things not compiling. Specifically, openocd just wouldn't compile from homebrew. This worked finally:
brew install --use-llvm --fresh openocd
CC=clang make FAILS
This one was not fun. While working to ge the toolchain up on the 10.8.2 version I couldn't get the CC=clang make cross-binutils cross-gcc cross-newlib builds to work. The problem seems to be that I needed to restart the machine after getting the Command Line tools installed from XCode. When the machine rebooted I also needed to remove the cached versions of the previous build configs...these hang around and the build system will continue trying to use "bad" configurations in what I am guessing is an attempt to save processing time. I would get compiler errors of all kinds. This worked finally:
close the terminal
restart the machine
rm arm-eabi-toolchain/build/binutils/intl/config.cache
rm arm-eabi-toolchain/build/binutils/intl/config.h
make distclean
make clean
CC=clang make cross-binutils cross-gcc cross-newlib