Note: This is a snapshot of the README.md file on the git repository for this project. Over the next few weeks, I plan on writing a series of blog posts dissecting the different parts of it and explaining how it all fits together.
You can find the repository here: https://github.com/tonyarkles/stm32f042-morse-example
If you’re looking at using an STM32F042K6 Nucleo board, this is a decent alternative to using mbed, if you feel like rolling up your sleeves a bit and getting dirty.
What is this?
This is a sample project for the STM32F042K6 Nucleo board that I’m happy with. It has the following features:
- CMake for builds
- crosstool-ng for building a toolchain
- Unity for unit testing on the host
- OpenOCD and gdb for running code on the target
How do I get started?
Toolchain
First, you need to have crosstool-ng
installed. I’m using version
1.22.0. The
instructions are
pretty straight-forward. Once you’ve got it installed, don’t worry
about the rest of their instructions (i.e. stop after the export
PATH
line).
Once it’s installed, you can use the configuration file in the
crosstool/
directory in this repository to build a compiler and
newlib (libc) for the microcontroller. To do this, you first tell
crosstool-ng to use the configuration provided, and then you tell it
to build it:
1 2 |
|
This will take a while. On my i7 desktop, it took about 16 minutes.
This will install the toolchain into ~/x-tools/arm-stm32f0-eabi
.
OpenOCD
The crosstool-ng toolchain comes with an ARM-compatible gdb, but without OpenOCD, there’s no way to connect to the target board.
I was lazy here and just installed it through apt: apt install -y openocd
To test that it’s working, plug your Nucleo board into a USB port and run this command. You should get similar output:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
CMake
CMake is a build system. The two-second intro is that instead of
having a Makefile, you have files called CMakeLists.txt
that are
used to generate Makefiles (and other things, in different
environments).
Here, too, I was lazy and just installed it via apt: sudo apt install -y cmake
Building and testing on the host
You should now have all the pieces in place necessary to do both host-unit-test builds and target-binary builds!
First, let’s do a host build. For CMake projects, you generally make a new directory to do the build in, which keeps all of the build objects out of your source tree (makes for really easy cleanup!)
To do a host build, make a directory called build/
in the source
directory. The .gitignore
file is already set up to ignore this
directory. In there, you run CMake to process the CMakeLists.txt
files and generate a Makefile. Then you run make
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
Once this has finished, there’s a unit test runner stored in
build/test/testrunner
. Executing this should result in output like
this:
1 2 3 4 5 6 7 |
|
Building and flashing onto the microcontroller
Now that you can see that the unit tests are passing, it’s time to try running the code on the microcontroller!
We’re going to make a new build directory for this; this one will contain all of the ARM-compiled pieces instead of the x86-compiled pieces from above. The process here is pretty similar, but we’re going to pass an additional parameter to CMake to tell it what to use for a cross-compilation toolchain. We’ll also tell CMake to do a Debug build, so that we can easily see what’s going on in GDB.
1 2 3 4 |
|
The output from this is going to be target/target.elf
. This file
contains all of the code that’s going to go onto the microcontroller,
plus additional things like debugging symbols.
To do these steps, make sure that you’ve got OpenOCD running (see
above). We’re going to use gdb
to connect to OpenOCD and upload the
firmware. I’ll talk about what is happening with each step as we go
along.
Start the ARM version of gdb:
1
|
|
Tell GDB to connect to OpenOCD. OpenOCD by defaults listens on port 4444 for general commands, and port 3333 for GDB commands:
1 2 3 |
|
Tell GDB which file has the firmware:
1 2 3 4 |
|
And tell GDB to tell OpenOCD to flash that firmware onto the chip:
1 2 3 4 5 6 7 |
|
Now tell GDB to tell OpenOCD to reset the chip and hold it in the halt state:
1 2 3 4 |
|
At this point, the firmware’s loaded on the chip. To get it to run, all we need to do is issue the continue command:
1
|
|
And if you look over at the board, the LED should now be blinking out “HELLO WORLD” in Morse Code.