If you follow the Hack-A-Day stream, you’ve probably seen the STM32F0Discovery board come up on occasion. I have two of these boards and I like them — they have what I need for basic stuff, but I wanted some more horse-power (and USB Host.) Quickly, to the STM32F4Discovery!
The target here is people who’ve outgrown the world of AVR and need something running faster; you should be capable and comfortable with diving into your PATH, mucking with environment variables and reading some pretty deep C.
I was given one of these for xmas a little while back (read: 8 months ago) and played with it, getting demo code to run on it. ST did something very painful and/or clever in that they produced this board, for hobbyists, but conveniently forgot to point to a clean, unadulterated compiler.
The options were Atollic, Keil or IAR. Atollic’s free version disables printf() on debugging, locks you out of your IDE on a regular basis and can’t export tarballs. Keil’s code size requirement is inane, keeping most debugging from ever happening, and IAR didn’t present free version for normal people (at the time I tried it). Eventually, I got CodeSourcery G++ working but I could never quite get it right. Linker scripts were not my best friend.
Until I went to DEF CON. Yes, that’s correct: I was pushed into learning STM32F4 (cortex M4) core setup by some (bastard|kind soul) who had done this a few times in the past while hacking upon the thing in the hallway. I’ll explain how to get it working on Windows, since that is currently my development platform. Linux follows the same, however you will need to install the CodeSourcery G++ Lite toolkit and the stlink-flash utility from source.
GCC will accept nicely written Assembly, but I won’t go into that. No, today we’ll be looking at how to get a very well timed LED to blink on… and off… and learn about RTOSs in the process.
Your first question might be: What’s an RTOS? Why do I need one of those?
What the hell is an RTOS?
An RTOS, or Real Time Operating System, abstracts your code (to some degree) from the actual board you’re working on. Even better, though, is that it lets you say “When this thing happens, I need control now. Not 2 clock cycles from now, now.” As a result, the RTOS world gets pretty slushy when it comes to differences: There’s FreeRTOS, my choice of ChibiOS, eCos, all of which are free/open source; In the “professional” world (read: money-driven) world there’s expensive ones like ThreadX and TASKING. At one point, Microsoft tried making Windows CE into a “real time operating system” and got some attention (oddly in the money and cellphone world)
RTOSs come in two flavors: Hard and Soft — much like chocolate. “Hard Real-Time” means you’re guaranteed that your events will be handled within a certain amount of time, no more (because that can be the difference between planes flying in the air or hitting the ground). ThreadX, TASKING and eCos all qualify as this; ports of Linux have been made so that you have a “hard” real time environment in-kernel. “Soft Real-Time” means you’re going to get handled — Eventually. Usually within 2-3 mS of the event happening. This can mean loosing your event. Linux, Windows CE, as well as a few others definitely qualify for this.
The difference really comes down to how responsive you need your system to be. Many systems such as flight-control decks, jet planes, automated robotic systems, etc, all use Hard Real Time because they need to be responsive when the event happens (or earlier!) and thus have tight control patterns, constantly acting and reacting to the world they are in. Others, such as fridges, cameras, cell-phones, thermostats (yes, thermostats) and even security systems run on a slower scale of time — seconds to minutes. Cell-phones (and even camera-phones) are known for running lightly interpreted systems like Java or Linux (or in the case of Android smart phones, both). There are plenty of security systems in this world which rely on Windows CE. ATM machines run various versions of Linux and Windows or even DOS, OS/2 and Minix. The farther you get away from the action or the slower the action happens, the less and less you need to be “hard” real time.
Why do I need one of these?
In our case, a hard-real time operating system like ChibiOS or ThreadX is overkill to an extreme — But working in that environment can be very helpful since you learn how your device reacts to the world. It pulls you away from the hardware itself just enough to focus on writing your application, letting you push into the hardware if you need. in our case, we’re going to make a very well timed LED blink every 500mS (give or take in our case; see below.)
First things first.
There’s a few things you’re going to need to procure first.
- STM32F4Discovery board (Didn’t I mention that earlier?)
- the ST-Link utility from ST and driver (this is mentioned nowhere on the page for the stm32f4discovery. I had to find it on ST’s website)
- USB A-Mini B cable (the middle size)
- A copy of the Yagarto tools and GNU toolchain from yagarto.de (or CodeSourcery G++ on Linux; get the ‘eabi’ version, not the ‘GNU/Linux’ version)
- A copy of ChibiOS (go read their howto’s, too!)
For this I’m going to assume the following:
- yagarto tools is installed to c:\bin\yagarto\tools
(not needed on Linux, but you should have binutils installed)
- yagarto toolchain is installd to c:\bin\yagarto\toolchain (Linux and CodeSourcery: try /opt/codesourcery/)
- ChibiOS is in c:\src\chibios\ (Linux: try ~/src/ or ~/work/, whatever you’re comfortable with)
The first thing you should do is make sure your toolchain is set up properly. At a command prompt, try to invoke GCC:
C:\Users\indrora>arm-none-eabi-gcc --version arm-none-eabi-gcc (GCC) 4.7.1 Copyright (C) 2012 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
If you get a message saying “arm-none-eabi-gcc is not recognized as an internal or external command” you haven’t added it to your PATH yet. You’ll want to add the paths for Yagarto tools and toolchain (in that order).
Once you have that working, try building the demo for the STM32F4 from chibios:
C:\src\chibios\demos\ARMCM4-STM32F407-DISCOVERY\> make Compiler Options arm-none-eabi-gcc -c -mcpu=cortex-m4 -O2 -ggdb -fomit-frame-pointer -falign-functions=16 -ffunction-s ections -fdata-sections -fno-common -Wall -Wextra -Wstrict-prototypes -Wa,-alms=build/lst/ -DCORTEX_U SE_FPU=FALSE -DTHUMB_PRESENT -mno-thumb-interwork -DTHUMB_NO_INTERWORKING -MD -MP -MF .dep/build.d -I . -I../../os/ports/common/ARMCMx/CMSIS/include -I../../os/ports/common/ARMCMx -I../../os/ports/GCC/AR MCMx -I../../os/ports/GCC/ARMCMx/STM32F4xx -I../../os/kernel/include -I../../test -I../../os/hal/incl ude -I../../os/hal/platforms/STM32F4xx -I../../os/hal/platforms/STM32 -I../../os/hal/platforms/STM32/ GPIOv2 -I../../os/hal/platforms/STM32/RTCv2 -I../../boards/ST_STM32F4_DISCOVERY -I../../os/various ma in.c -o main.o mkdir -p build/obj mkdir -p build/lst Compiling ../../os/ports/GCC/ARMCMx/crt0.c Compiling ../../os/ports/GCC/ARMCMx/STM32F4xx/vectors.c Compiling ../../os/ports/GCC/ARMCMx/chcore.c Compiling ../../os/ports/GCC/ARMCMx/chcore_v7m.c Compiling ../../os/ports/common/ARMCMx/nvic.c
(truncated for clarity)
Compiling ../../boards/ST_STM32F4_DISCOVERY/board.c Compiling ../../os/various/lis302dl.c Compiling ../../os/various/chprintf.c Compiling main.c main.c: In function 'Thread1': main.c:189:1: warning: no return statement in function returning non-void [-Wreturn-type] Linking build/ch.elf Creating build/ch.hex Creating build/ch.bin Creating build/ch.dmp Done
Congratulations, you have at least compiled the blinky demo (there’s also some other things that it does, but we’re focused on the blinky).
Placing it on the device requires you to use the ST-Link utility and an ST-Link (v2!). Luckily, STMicros was very kind and placed a full ST-link (in the form of an STM32F103 with some custom code) on the board. Make sure the headers between the ST-Link and the STM32F4 itself are set.
If all is right once the USB connection comes up, you can press the Connect button and you’ll get a nice output of what’s on the chip.
Open the file in build named ch.hex. The app will inform you that the code hasn’t been pushed to the device. Go ahead and press “Program” when prompted and let it go. Once it has done a verify of what’s on the device being the same as whats on your machine, Congratulations! You’ve just compiled the demo for this board and made sure that it was properly put on the device. Pat yourself on the back and get a glass of drink.
So now you’ve gotten the thing to compile and probably make things blink. Congratulations.
Go read the documentation. I can’t stress this enough: Read the documentation. You’ll be astounded how much the ChibiOS documentation contains for each of the boards it supports.
There’s quite a bit there, too: From details on what the basics of any part of the HAL device system does and can do all the way to how to fiddle with the OS itself. The website is helpful for learning the fundamentals of RTOSs, optimization for compilers, comparisons of devices, etc.
Here’s a list of pointers you may want to look at:
- Optimization is a double-edged sword in the ARM world. Sometimes GCC does a good job, sometimes you just want to do your job and not let GCC interfere.
- There’s a wonderful thing on timing where you need something done every X ms, on a solid clock, in the documentation. This has to do with how long operations take to complete.
- Git and SVN are updated every 10 minutes or so. Things like STM32F4’s usb cdc driver and RTC driver are in there.
- If you’re looking for a basic demo to make a particular thing work, look in the ‘haltest’ directory for your board, since each supported HAL feature must have an accompanying test to get into the tree.
Oh, and by the way: it supports the stm32f0-discovery as well, that fancy $10 dev board that people seem to like so much but only on the currently beta version — Just look in the ARMCM0-STM32F051-DISCOVERY directory under demos.