September 21, 2016

STM32F103 command line development

For any number of excellent reasons, I am violently opposed to using the Arduino GUI. So these notes are about using vim and make to do code development.

First Demo (never worked)

As a starting point, I poked around in the ARM Cortex M3 projects link above and found an entry "LED Blink Example for STM32F103" and downloaded I unzip this, cd inside, and type make. It launches the first command:

arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -Wall -g -O0 -I . -I lib/inc   -c -o main.o main.c
This confronts me with the first issue. I have installed (and have been using for some time) the linux-gnu ARM compiler (installed on Fedora as gcc-arm-linux-gnu), whereas this makefile wants to use the code sourcery compiler (also available to install on fedora as arm-none-eabi-gcc-cs).

What do I do? Can these compilers both be installed? Can I just modify the makefile to use the compiler I have been using? Why are there two compilers for ARM anyway?

I actually try modifying the makefile. And it mostly works (at least the compiler doesn't blow up). It complains about a couple of odd constructions that I can easily clean up. Then it gets really upset at link time.

It is also worth noting that there is a lot of code here; over 16,000 lines of code just to blink an LED. Well it is a comprehensive library, not a simple demo. There are a lot of things that I may be glad to use in the future.

Pick your compiler

What about this compiler business? On my fedora system, there are two choices (and I chose the second).
arm-none-eabi-gcc-cs.x86_64              1:5.2.0-4.fc24                 fedora  
gcc-arm-linux-gnu.x86_64                 6.1.1-2.fc24                   updates 
Apparently the "code sourcery" compiler is the open source part of a commerical product from Mentor Graphics they call "Sourcery CodeBench". As I understand it, it may have bleeding edge support for new chips before the mainline gnu compiler assimilates their contributions. For me, working with the STM32F103, I don't particularly need it.

Compare however "none" and "linux" in the two names. In the gcc naming scheme "none" indicates that the compiler does not expect a C library and underlying operating system, where "linux" indicates the compiler is expecting to generate code to be linked in the usual way to run under the linux operating system. This is the party line anyway, although I have been using "gcc-arm-linux-gnu" for bare-metal embedded projects for quite some time. In other words, all that has been said so far in this paragraph is confusing rubbish.

The real trick is in the linker script. In the "linux" flavor compiler, the default path will expect to find main() and will try to get crt0, crt1.o (and similar things) from libc. Embedded projects will have none of this. An embedded project will have a special linker script, some assembler code to get things going after reset, and often will be wise to avoid having main() just to avoid confusion.

All this being said, I don't see any assembler code in the demo file I downloaded. There must be magic hidden in the code sourcery compiler.

Can we install them both safely? Who knows? Let's cross our fingers and give it a try:

dnf install arm-none-eabi-gcc-cs
(1/2): arm-none-eabi-binutils-cs-2.25-3.fc24.x86_64.rpm                                                                                                                                                                                                                                       840 kB/s | 2.0 MB     00:02    
(2/2): arm-none-eabi-gcc-cs-5.2.0-4.fc24.x86_64.rpm       
This doesn't work either:
arm-none-eabi-gcc -Wl,--gc-sections,,-cref,-u,Reset_Handler -I . -I lib/inc -L lib -T stm32.ld main.o stm32f10x_it.o lib/libstm32.a --output main.elf
/usr/lib/gcc/arm-none-eabi/5.2.0/../../../../arm-none-eabi/bin/ld: cannot find crt0.o: No such file or directory
/usr/lib/gcc/arm-none-eabi/5.2.0/../../../../arm-none-eabi/bin/ld: cannot find -lc
collect2: error: ld returned 1 exit status
Makefile:36: recipe for target 'main.elf' failed
make: *** [main.elf] Error 1

Second demo (sort of)

The following demos are much better, most are less than 100 lines of code. He is working with the STM32F4 on some kind of discovery board. He recommends looking at his mbed demos, which he says are even more instructive. In particular, he worked with the NXP LPC1768. You can buy these at Sparkfun for $55. The processor is made by NXP - 100 MHz ARM with 64 KB of SRAM, 512 KB of Flash.

  • Github - dwelch67 - stm32f4d
  • Github - dwelch67 - mbed samples
  • STM32 startup and linker script
    Feedback? Questions? Drop me a line!

    Tom's Computer Info /