In an upcoming project I need a micro controller that operates: 1x 16-bit DAC (SPI); 1x 24-bit ADC (SPI); 1x 8-bit parallel LCD; 1x rotary encoder; 1x PWM fan; 1x fan tachometer; 1x temperature sensor (DS18B20); 2x analog switches; 1x uplink UART; 4x push buttons, and some voltage monitoring for various power rails. To my estimation these peripherals require about 40 pins. Considering the additional clock, power and programming/debug lines, the minimal pin count I’m going for is 64. So I went to element 14 parametric search to look for a suitable chip.
While lacking of choice is not always a real engineering problem, having too many choices is usually more troublesome. My filtering for 64-100 pin devices resulted in 1638 devices from 17 manufactures… After much 1 second consideration I finally quickly made a decision. The winner is — STM32 ARM Cortex-M series. At the price point comparable to Microchip or Atmel’s 8-bit processor, I can jump onto 32-bit ARM development, how “IN” it is!
But the road that follows is not as smooth as I had imagined. STmicroelectronics has labelled themselves to be a “Hardware” manufacture so that they can excuse themselves from providing a usable compiler. While they do offer downloads of development tools from reputable vendors such as IAR or Keil, those tools are either “crippled” edition or time limited ware. I then spend several days looking for a guide to setup free or opensource ARM development tool-chain. There are quite a number of good resources online, for example, here, here and here. I’m not going to write “Yet Another …”, just document my approaches here, for note taking purposes.
Mini-TOC
- Development Platform
- Command Line Tools
- Project Folder
- Project Template
- Eclipse IDE
- Import STM32 Project
- Debugging in Eclipse
- Eclipse Plugins
- Downloads
Development Platform
My toolchain installation is on Windows 7. I have test it on both 32-bit and 64-bit editions. I have no plan to do development on Linux or Mac OSX yet, mainly because my other EDA tools are only available in Windows.
Command Line Tools
Compiling program from the command line is probably the best experience to understand the compiler tools and the interaction among them. Most online resources recommend Sourcery G++ Lite as the compiler. I did try this and it works great. However Sourcery is not fully open source and I do not like the fact that you have to signup at Mentor to download it. I use the GNU tools for ARM, because:
- It is fully open-source.
- It is actively maintained by ARM employees.
- It contains hardware float support (which is available on STM32F4) so more future-proof.
I download the Windows ZIP package and extract it to C:Appsarmgcc. (C:Apps is the folder where I usually keep programs that do not need to be installed). I also add C:Appsarmgccbin to the user PATH.
GNU make utilities are also required. I download the Yagarto Tools package from here. GNU make from here is also usable but I found the one inside Yagarto Tools has better compatibility with many “Linux only” Makefiles. GNU Make utility is required. Win32 version with supporting files is here. I extract all the files to C:Appsbin and add the same to user PATH.
To verify the installation, open a Command Prompt and try these two commands:
- arm-none-eabi-gcc -v
- make -v
I have heard some “make” utilities which maybe installed by other software such as the WinAVR or Delphi can conflict with the GNU make, so make sure “make -v” gives correct version information as “GNU make 3.81”. Otherwise just rename the make.exe to something else such as “gmake.exe”.
Project Folder
Many development tools, e.g., Arduino, MPLab, Atmel Studio, Altium Designer, etc, store user files in its own “workspace” or “project” folder. By default the folders are created under Windows user profile, but I prefer to move them to a central location to ease backup and sync. My central location is “D:workspace”. For STM32 I created a “D:workspaceSTM32” where I put all STM32 related files.
ST Standard Peripheral Library is required for development. I downloaded the STM32F10x flavour and put it under d:workspaceSTM32STM32F10x_StdPeriph_Lib_V3.5.0
Project Template
I tried several STM32 project templates available on the Internet, and finally I decided to make my own. The reason I do not like some templates are:
- Some templates copy files from ST peripheral library to their own folder. This is only good if ST frequently modify their library interface, or you want to modify ST source code. I would rather keep ST library files in their original location and reference them from my Makefile.
- Some templates compile all ST peripheral library files into one library archive (.a file). It is pretty wasteful if only part of the library are used. I choose to reference only the used ST library files.
- Some template organize the Makefile into separate sub-makefiles and include them in the final one. It is good for large project. At currently I would rather use a monolithic Makefile to make life easier.
As I have yet to learn how to create a GitHub account, my project template is attached below.
Explanation for some snippets of the Makefile:
[code firstline=”10″]
######################################
# building variables
######################################
# debug build?
DEBUG = 1
# build for debug in ram?
RAMBUILD = 0
# optimization
OPT = -O0
[/code]
Here I set the variables controlling the build process:
- DEBUG is a general debugging switch. If defined as 0, no debug symbol is generated in the final .elf file.
- RAMBUILD sets where the code is executed. If RAMBUILD = 0, the code is set to execute from Flash (starts from 0x08000000). Otherwise if RAMBUILD = 1, the code is executed from RAM (from 0x20000000). RAMBUILD selects the correct link script and interrupt vector table. It is always preferable to debug in RAM as the on-chip flash has a limited re-write cycle. The compiler will generate an error if RAM is not enough to host the complete program.
- OPT is the optimization switch. Sometimes if RAM is not enough for debugging, use -Os to reduce program size.
[code firstline=”20″]
#######################################
# paths
#######################################
# source path
VPATH = src startup
# firmware library path
PERIPHLIBPATH = ../../STM32F10x_StdPeriph_Lib_V3.5.0/Libraries
VPATH += $(PERIPHLIBPATH)/CMSIS/CM3/CoreSupport
VPATH += $(PERIPHLIBPATH)/CMSIS/CM3/DeviceSupport/ST/STM32F10x
VPATH += $(PERIPHLIBPATH)/STM32F10x_StdPeriph_Driver/src
# Build path
BUILD_DIR = build
[/code]
Here various paths are listed, including the project source code (src and startup), ST peripheral library path and building path (BUILD_DIR). Source codes are located using VPATH directive.
[code firstline=”33″]
# #####################################
# source
# #####################################
SRCS =
main.c
stm32f10x_it.c
system_stm32f10x.c
SRCSASM =
startup_stm32f10x_hd.s
# #####################################
# firmware library
# #####################################
PERIPHLIB_SOURCES =
core_cm3.c
stm32f10x_gpio.c
stm32f10x_rcc.c
[/code]
I list all the used source files here. system_stm32f10x.c and stm32f10x_it.c are copied from ST peripheral library. These two files always need modification to suit specific application. Startup code startup_stm32f10x_hd.s is from Attolic TrueStudio.
[code firstline=”87″]
#######################################
# LDFLAGS
#######################################
# link script
ifeq ($(RAMBUILD), 1)
LDSCRIPT = linker/STM32F103VE_ram.ld
else
LDSCRIPT = linker/STM32F103VE_flash.ld
endif
[/code]
These are the link scripts obtained from Atollic TrueStudio and ST peripheral library.
More startup files and link scripts for other STM32 devices are linked at the end of the article.
To compile the project simply type “make” within the project root folder. The Makefile features auto generated dependencies so I do not need to clean the project all the time. At the end of the building process the size of each section is displayed.
Eclipse IDE
Although building program from the command line is probably the best experience to understand the compiler, sticking to the command line only is definitely the stupidest idea (except for some “cool effect” in front of young players). Eclipse is one the the greatest free IDE so I decided to use it.
However Eclipse has become bloatware these days. The current binary package of “Eclipse IDE for C/C++ Developers” is about 130MB, which contains a lot of plugins, such as “Visual C++ support”, that I do not need at all. And you do not have an option to uninstall it! So I choose the bare metal way. Download the “Platform Runtime Binary” package from Eclipse archive (currently version 3.8.2 here). It weights 53MB. Extraction the package to C:Appseclipse-stm32, run eclipse.exe. When workspace location is asked, give “D:workspaceSTM32eclipse”
For the next step, choose “Help”->”Install New Software…”, click the “Add…” button and type in Eclipse CDT site as the picture below (The current settings is for Eclispe 3.8 “Juno”):
Then select “Work with:” CDT and check these packages:
Click “Next”, accept some license nags and a clean bare-metal Eclipse C/C++ development environment is up.
Import STM32 Project
Start Eclipse, choose “File”->”New”->”Makefile Project with Existing Code”, enter as follows:
The project “Blank” is created. A small red cross is displayed at the folder icon. This is because the Eclipse indexer is not able to find all the definitions and prototypes. To fix this, right click the project folder and select “Properties”, in the popup window, select “C/C++ Build->Discovery Options”, change “Complier invocation command” to “arm-none-eabi-gcc”.
Close the Properties window, do a rebuild inside Eclipse (which takes a while as compare to build from command line because Eclipse is scanning into building process). When finished, a “Includes” folder will appear in the project folder. The red cross should go away and all the symbols in the source code shall be able to resolve. (If not, right click project folder, “Index”->”Rebuild”)
Debugging in Eclipse
Programming and Debugging STM32 using UART is possible but clumsy. I’m lucky enough to have a SEGGER J-Link debugger so everything becomes easy. To start program and debug in Eclipse, right click the project, select “Debug As”->”Debug Configurations…”, select “GDB Hardware Debugging” and press “New Launch Configuration” button, set the parameters at “Main” tab as follows
The debug configuration name is “Debug Blank Flash”, meaning we’re debugging using on-board Dlash. Make sure “Using Standard GDB Hardware Debugging Launcher” is selected at the bottom. For the “Debugger” tab, the following settings are used
BTW I’ll be using SEGGER GDB Server so the “Port number” is 2331. There are other GDB servers such as OpenOCD, but since I’m developing under Windows I’d rather use original SEGGER software.
The “Startup” tab is below
Code inside the two editors are:
[code language=”text”]
monitor speed 30
monitor endian little
monitor reset
monitor speed auto
set remote memory-write-packet-size 1024
set remote memory-write-packet-size fixed
monitor flash download = 1
monitor flash device = STM32F103RC
[/code]
and
[code language=”text”]
tbreak main
monitor reset 0
continue
[/code]
For the “Initialize Command” part, my development board has a STM32F103RCT6 so the “flash device” is set to STM32F103RC.
For the “Run Commands” part, take note I’ve inserted a “monitor reset 0”. I found this is necessary to debug RTOSs such as Chibios (wonder why).
Most of the time it is more convenient to debug inside RAM, provided that the chip has enough RAM for the program. To build a program for RAM debugging, set “RAMBUILD=1” in the Makefile.
A separate debug configuration is necessary for RAM debugging. Simply duplicate a configuration from the previous Flash debugger and configure the “Startup” tab as follows
Similarly the codes are
[code language=”text”]
monitor speed 30
monitor endian little
monitor reset
monitor speed auto
monitor writeu32 0xE000ED08 = 0x20000000
[/code]
and
[code language=”text”]
tbreak main
monitor reset 0
monitor reg r13 = (0x20000000)
monitor reg pc = (0x20000004)
continue
[/code]
The debug configurations can be added to “Favourite” menu for easy launching. But before launching, start “SEGGER J-Link GDB Server”.
Make sure the “BOOT0” and “BOOT1” pin on STM32 are correctly configured when choosing debugging from RAM or Flash.
Eclipse Plugins
There’s a lot of STM32 Eclipse plugins that make life easier. The plugins I use:
- EmbSysRegView It shows ARM Cortex registers during debug section. Probably the most useful plugin.
- StateViewer It displays important information (Tasks, Queues, Timers) is the program uses FreeRTOS. It is a free plugin but the website asks for your information (which I don’t like). For simplicity the Eclipse software site is “http://www.highintegritysystems.com/StateViewer/“
Plugin I do not use:
- GNU ARM Eclipse Plug-in This plugin automates ARM development under Eclipse. It uses Eclipse managed build system so user do not need to write a Makefile. The reason I do not use this plugin is because it obscures the building process while I like to have everything in proper control.
- Zylin Embedded CDT This plugin provides easier settings for hardware GDB. However I do not feel the CDT build-in GDB integration is harder to configure.
- ST MicroXplorer MicroXplorer is a visual tool for planning and configure STM32 mcu pins. It also generates configuration code automatically. MicroXplorer is distributed as a standalone utility and a Eclipse plugin. The Eclipse plugin seems to slow down Eclipse startup significantly. I use the standalone version.
Downloads
[attachments size=small docid=”656,662,661″]
Another free development IDE is Code::Blocks and with Embedded plugin suite (EPS Debugger) supports some of discovery boards directly and most of STM32 devices. With free version you can utilize up to 25% of device flash memory capacity which could be enough also for medium sized project. Successfully compiled and debugged Chibi/OS and FreeRTOS with it. Includes also project wizard where with few clicks the basic project or example can be created. It has big advantage that you do not need to bother with complicated setup process.
Download here:
http://www.comsytec.eu/en/online-store/detail/flypage|eps/112-codeblocks-eps–embedded-plugin-suite?pop=0&sef=hfp
CodeBlocks has devided the developer chain and now called emBitz. It’s very eazy using this and a very good IDE for all around embedded development.
I had done some experiences using Eclipse and some others like Keils µVision and Atmels Atmel Studio. Eclipse is maybe able to extend in every way you ever wanna go, bot you pay this with a very long time to work with it, to know the handling of them; especialy with the embedded extension, who eclipse never had developed for.
CodeBlocks; especialy emBlocks supports the most boards, FreeRTS,Chibi/OS and a bunch more.
A second IDE i can limited recommend is coocox IDE. It’s very versatile and widely used.
Another free development IDE is Em::Blocks which comes with pre-installed GNU-arm tools and debugger plugin’s.
This one is really free!
This is also the only free IDE which is capable of live data (watch variables and memory while the target is running).
Works out of the box for STM32 and supports, besides openOCD and JLink also STlink out-of-the-box.
Web site:
http://www.emblocks.org
Features:
http://www.emblocks.org/web/features
I have also tried CooCox and it looks awesome too.
Thanks! I don’t know why, but just getting a build template ready seems to be the hardest part when starting with stm32. I modified this to work with stm32f0 parts – it’s on github here: https://github.com/synic/stm32f0_stdperiph_template
The linker files posted above have the following conditions:
** (c)Copyright Atollic AB.
** You may use this file as-is or modify it according to the needs of your
** project. Distribution of this file (unmodified or modified) is not
** permitted. Atollic AB permit registered Atollic TrueSTUDIO(R) users the
** rights to distribute the assembled, compiled & linked contents of this
** file as part of an application binary file, provided that it is built
** using the Atollic TrueSTUDIO(R) toolchain.
I’m not sure if this is in violation of these conditions?
Good catch. Thanks. I need to look around any free link scripts around, or I will write my own.
In my recent CubeMX2Makefile (https://github.com/baoshi/CubeMX2Makefile), I have replaced Atollic link script with the one from CooCox. Hope this can solve copyright issue. Thanks again.
I prefer qtcreator as my IDE
I just tried the new makefile generator w. a project for SW4STM32
My arm-gcc does NOT like the “weak” definiton in the makefile.
It builds if i remove the definition
My “launchpad” arm-none-eabi-gcc is
gcc version 4.8.4 20140526 (release) [ARM/embedded-4_8-branch revision 211358] (GNU Tools for ARM Embedded Processors)
$ make
arm-none-eabi-gcc -c -mthumb -mcpu=cortex-m3 -D__weak=”__attribute__((weak))” -D__packed=”__attribute__((__packed__))” -DUSE_HAL_DRIVER -DSTM32F103xB -IInc -IDrivers/STM32F1xx_HAL_Driver/Inc -IDrivers/STM32F1xx_HAL_Driver/Inc/Legacy -IMiddlewares/ST/STM32_USB_Device_Library/Core/Inc -IMiddlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc -IDrivers/CMSIS/Include -IDrivers/CMSIS/Device/ST/STM32F1xx/Include -O0 -Wall -fdata-sections -ffunction-sections -g -gdwarf-2 -MD -MP -MF .dep/stm32f1xx_hal.o.d -Wa,-a,-ad,-alms=build/stm32f1xx_hal.lst Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.c -o build/stm32f1xx_hal.o
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.c:215:1: error: stray ” in program
__weak void HAL_MspInit(void)
This is a bug I need to fix. It seems we don’t need to escape “(“, so remove the “” in front of “(” and “)” fixes the problem. But it only happens under certain terminal. I’m still trying to figure out why.
Hi! I’ve just trying out STM32 and found Your script. Also produces the same error, removed escape characters in makefile before ( and ), worked. Thanks!
I’m not that much of a internet reader to be honest but your blogs really nice, keep it up!
I’ll go ahead and bookmark your site to come back later on. Many
thanks