Open Source IDE and Toolchain for the STM32F4 Discovery on Mac OSX Lion

STM32F4-Discovery

ST Micro in the last few weeks was the first to market with the brand new ARM Cortex-M4 32-bit microcontroller core. The really interesting new feature is the ‘F’ in the name – this is the first low-cost, low-ish-power light duty microcontroller to include a built in, single cycle per instruction 32-bit floating point unit. In typical ST fashion, the development board is awesome – it’s got a built in ST-LINK/V2 programmer and in-circuit debugger on the top half. The bottom half contains the M4 and a host of fun peripherals to play with, including a 3-axis MEMS accelerometer, an audio DAC with class D output driver, a bunch of LEDs, and all GPIOs broken out to .1″ headers.

But alas, the software stinks. In fact, it doesn’t come with software. There are 4 proprietary (and EXPENSIVE) toolchains supported, Altium TASKING, Atollic TrueStudio, IAR Embedded Workbench for ARM, and Keil MDK-ARMT. Of those, only Atollic and IAR have free versions, where IAR is 32 KB limited (the M4 has 1MB flash), and where Atollic is neither time nor size limited, but doesn’t support C++. For some that will be fine, but I’m certain I’ll find that annoying.

So what do we do?! Luckily, the single most developed compiler out there is open source, GCC! We’re going to use a commercially-developed open source compiler, Mentor Graphics’ Sourcery CodeBench Lite edition. We’ll pair that with the open source IDE Eclipse (standard for most open source and commercial development toolchains alike), and then weave in ST’s tools like ST-LINK/V2 to fill in the gaps. I’m going to mash up a few different existing tutorials to do this, starting with this excellent tutorial for setting up this same toolchain, but for the original STM32VL Discovery and on Windows.

Prerequesites: you’ll need Apple’s developer tools (Xcode), a package manager for *nix programs (instructions given are for homebrew, you could probably use macports if you really want), and git.

Here’s what we’ll be using:

Indigo R Eclipse IDE for C/C++ Developers (Mac Cocoa 64-bit)
http://www.eclipse.org/downloads/packages/release/indigo/r

STM32F4 DSP and standard peripherals library
STM32F4 Discovery board firmware package
http://www.st.com/internet/mcu/product/252149.jsp#SOFTWARE_AND_DEVELOPMENT_TOOLSStart downloading these now, they can take a long time.

 

Sourcery G++ Lite 2011.03-42 for ARM EABI Source TAR – jsnyder package
https://github.com/jsnyder/arm-eabi-toolchain

1. Download and install Eclipse. From here, download the Mac Cocoa 64-bit version of Eclipse for C/C++ developers. Extract the .tar.gz, and copy the ‘eclipse’ folder to /Applications, as you would with any other Mac app. Launch Eclipse.app from that folder. When prompted for a workspace directory, add ‘stm32f4-discovery-projects’ to the path just before ‘/workspace’, as below:

Set your workspace path
Set your path
  1. Install Sourcery G++ lite. We’re going to use the arm-eabi-toolchain builder from James Snyder. Launch Terminal from /Applications/Terminal or spotlight and enter the following commands, preferably one at a time. Note that the compile commands (CC=clang make… and make cross-gdb take a LONG time, go grab coffee).

    cd
    git clone https://github.com/jsnyder/arm-eabi-toolchain.git
    cd arm-eabi-toolchain
    brew install mpfr gmp libmpc texinfo
    mkdir -p $HOME/arm-cs-tools/bin
    export PATH=$HOME/arm-cs-tools/bin:$PATH
    CC=clang make cross-binutils cross-gcc cross-g++ cross-newlib
    make cross-gdb
    export PATH=$HOME/arm-cs-tools/bin:$PATH
    make clean

  2. Configure Eclipse. Launch Eclipse that you started earlier. In the menu, go to ‘Help>Install New Software…’ then click on the ‘Available Software Sties’ link. Search for ‘cdt’ and select the one checkbox that pops up. Hit OK.

Search for ‘cdt’

In the ‘Available Software’ window, select the last entry in the ‘Work with:’ dropdown. Expand ‘CDT Optional Features’ and select ‘GCC Cross Compiler Support’. Click ‘Next’ until the wizard successfully installs and/or updates everything (in my case, all the software was already installed, so it just updated). Restart Eclipse when prompted.

Select Cross Compiler Support
  1. Create a custom template. In Eclipse, go to ‘File>New C++ Project’. Name the project ‘Template’, and for ‘project type’, select ‘Cross-Compile Project’ under ‘Executable’. Click ‘Next’, NOT FINISH.
Template project settings

On the next screen, set the tool command prefix to ‘arm-none-eabi-‘ and the tool command path to ‘~/arm-cs-tools/bin’

Enter these values for tool prefix and path.

Click ‘Next’ then ‘Finish’. Click on the ‘Go to workbench’ icon. In the project explorer, right click ‘Template’ and click ‘Properties’. In the ‘Project Properties’ window, select ‘C/C++ Build>Settings’. Under ‘Cross GCC Assembler>General’ add -mthumb -mcpu=cortex-m4to ‘Assembler Flags’.

Add -mthumb -mcpu=cortex-m4 to assembler flags.

In the ‘Miscellaneous’ sections of both ‘Cross GCC Compiler’ and ‘Cross G++ Compiler’ set the ‘Other flags’ to -c -mthumb -mcpu=cortex-m4. Finally, go to ‘Cross G++ Linker>Miscellanoues’ and set the ‘Linker flags’ to -T "${ProjDirPath}\startup_src\stm32_flash.ld" -mthumb -mcpu=cortex-m4 -Wl,-Map=linker.map -Wl,-cref -Wl,--gc-sections. Click OK.

In the Project Explorer, right click ‘Template’ and select ‘New>Folder’ to create ‘src’ and ‘startup-src’

Create these folders
  1. Extract the earlier downloaded stm32f4_dsp_stdperiph_lib.zip inside the ~/Documents/stm32f4-discovery-projects/ directory.
Make sure your project directory looks like this

Copy the file ~/Documents/stm32f4-discovery-projects/STM32F4xx_DSP_StdPeriph_Lib_V1.0.0/Libraries/CMSIS/Device/ST/STM32F4xx/Source/Templates/TrueSTUDIO/startup_stm32f4xx.s to the startup_src directory you created in Eclipse above, then change the extension from .s to .S, capitalized. Note that you must drag/drop or copy/paste directly into the Eclipse interface or the file won’t show up in Eclipse.

This is as far as I’ve gotten. I’m currently hung up on how to replace ‘stm32_flash.ld‘ since the M4 isn’t nearly the same flash layout as the value line board used in that tutorial and I can’t seem to find a proper linker script. If you know where to go from here, PLEASE comment!

UPDATE 7/30/12 – I’ve got a toolchain set up and capable of compiling and loading to board, and I’m almost ready to integrate the GUI/toolchain halves. Hold tight, maybe a couple days and I’ll update with the complete tutorial.

14 Comments

  1. Dr. Klaus Schaefer
    November 22, 2011

    The sample LD file inside of the firmware package supplied by ST worked well
    in my GCC (Code Surcery) environment:

    Kind regards
    Klaus

    /*
    *****************************************************************************
    **
    ** File : stm32_flash.ld
    **
    ** Abstract : Linker script for STM32F207IG Device with
    ** 1024KByte FLASH, 112KByte RAM
    **
    ** Set heap size, stack size and stack location according
    ** to application requirements.
    **
    ** Set memory bank area and size if external memory is used.
    **
    ** Target : STMicroelectronics STM32
    **
    ** Environment : Atollic TrueSTUDIO(R)
    **
    ** Distribution: The file is distributed �as is,� without any warranty
    ** of any kind.
    **
    ** (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.
    **
    *****************************************************************************
    */

    /* Entry Point */
    ENTRY(Reset_Handler)

    /* Highest address of the user mode stack */
    _estack = 0x2001c000; /* end of 112K RAM */

    /* Generate a link error if heap and stack don’t fit into RAM */
    _Min_Heap_Size = 0; /* required amount of heap */
    _Min_Stack_Size = 0x400; /* required amount of stack */

    /* Specify the memory areas */
    MEMORY
    {
    FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
    RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 112K
    MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K
    }

    /* Define output sections */
    SECTIONS
    {
    /* The startup code goes first into FLASH */
    .isr_vector :
    {
    . = ALIGN(4);
    KEEP(*(.isr_vector)) /* Startup code */
    . = ALIGN(4);
    } >FLASH

    /* The program code and other data goes into FLASH */
    .text :
    {
    . = ALIGN(4);
    *(.text) /* .text sections (code) */
    *(.text*) /* .text* sections (code) */
    *(.rodata) /* .rodata sections (constants, strings, etc.) */
    *(.rodata*) /* .rodata* sections (constants, strings, etc.) */
    *(.glue_7) /* glue arm to thumb code */
    *(.glue_7t) /* glue thumb to arm code */
    *(.eh_frame)

    KEEP (*(.init))
    KEEP (*(.fini))

    . = ALIGN(4);
    _etext = .; /* define a global symbols at end of code */
    } >FLASH

    .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
    .ARM : {
    __exidx_start = .;
    *(.ARM.exidx*)
    __exidx_end = .;
    } >FLASH

    .preinit_array :
    {
    PROVIDE_HIDDEN (__preinit_array_start = .);
    KEEP (*(.preinit_array*))
    PROVIDE_HIDDEN (__preinit_array_end = .);
    } >FLASH
    .init_array :
    {
    PROVIDE_HIDDEN (__init_array_start = .);
    KEEP (*(SORT(.init_array.*)))
    KEEP (*(.init_array*))
    PROVIDE_HIDDEN (__init_array_end = .);
    } >FLASH
    .fini_array :
    {
    PROVIDE_HIDDEN (__fini_array_start = .);
    KEEP (*(.fini_array*))
    KEEP (*(SORT(.fini_array.*)))
    PROVIDE_HIDDEN (__fini_array_end = .);
    } >FLASH

    /* used by the startup to initialize data */
    _sidata = .;

    /* Initialized data sections goes into RAM, load LMA copy after code */
    .data : AT ( _sidata )
    {
    . = ALIGN(4);
    _sdata = .; /* create a global symbol at data start */
    *(.data) /* .data sections */
    *(.data*) /* .data* sections */

    . = ALIGN(4);
    _edata = .; /* define a global symbol at data end */
    } >RAM

    /* Uninitialized data section */
    . = ALIGN(4);
    .bss :
    {
    /* This is used by the startup in order to initialize the .bss secion */
    _sbss = .; /* define a global symbol at bss start */
    __bss_start__ = _sbss;
    *(.bss)
    *(.bss*)
    *(COMMON)

    . = ALIGN(4);
    _ebss = .; /* define a global symbol at bss end */
    __bss_end__ = _ebss;
    } >RAM

    /* User_heap_stack section, used to check that there is enough RAM left */
    ._user_heap_stack :
    {
    . = ALIGN(4);
    PROVIDE ( end = . );
    PROVIDE ( _end = . );
    . = . + _Min_Heap_Size;
    . = . + _Min_Stack_Size;
    . = ALIGN(4);
    } >RAM

    /* MEMORY_bank1 section, code must be located here explicitly */
    /* Example: extern int foo(void) __attribute__ ((section (“.mb1text”))); */
    .memory_b1_text :
    {
    *(.mb1text) /* .mb1text sections (code) */
    *(.mb1text*) /* .mb1text* sections (code) */
    *(.mb1rodata) /* read-only data (constants) */
    *(.mb1rodata*)
    } >MEMORY_B1

    /* Remove information from the standard libraries */
    /DISCARD/ :
    {
    libc.a ( * )
    libm.a ( * )
    libgcc.a ( * )
    }

    .ARM.attributes 0 : { *(.ARM.attributes) }
    }

  2. timo
    November 26, 2011

    I am currently trying to find out how to compile those libraries. Anybody done that?
    So far it seems that I have managed to create a GCC x-compiler version that supports Cortex-M4
    (right from sources, though bit tricky and still needs verification) so the toolchain creation part
    is “about” understood.
    Also I got the CMSIS/DSP lib compiling (with the above toolchain) but have no way of testing it before
    I get other parts compiling and working too. Currently wondering the 32F4 Peripheral Driver library
    and that (too) seems to have some oddities in terms of definitions etc – and does not compile easily.
    I could be missing something but the structure of the code and its “includes” seems a bit confusing.
    (Probably documented somewhere I have yet to find).

    I am working with Ubuntu11.10 + Hudson (for the toolchain) + Eclipse (with the created toolchain) + git.
    Any experience on getting the flashing & etc tools working from under Linux? (would not need to use
    Win7 at all)

    BR,

    Timo
    note: one can copy files “behind” Eclipse too, they just show after a “refresh” on the project.

  3. PittyJ
    December 3, 2011

    I’m hanging at step 2:
    2. Install Sourcery G++ lite.
    There are only 2 versions to download: Linux and Windows.
    But what do I install on the Mac? Where do get I get the Macos version?

  4. December 3, 2011

    You don’t actually need to download and install it yourself, the setup script included in the arm-eabi-toolchain project on github takes care of that for you automatically when you run the commands above for step two.

    But for reference, what’s going on in the background is that it’s downloading the SOURCE package for linux, and compiling it on Mac, which is similar enough that it should be compatible given the proper dependencies are installed first (which is also taken care of above).

  5. January 15, 2012

    Does this work with Mac OS X 10.7 (Lion) as well?

  6. oz
    January 23, 2012

    Hi, have you figured it out? Are you able to download a firmware into the Discovery board and debug it with Eclipse? Please share with us how to develop embedded SW under Mac OS-X.

  7. Vishal Sagar
    August 7, 2012

    How are you able to load the binary and debug? Are you using OpenOCD?

  8. CA Avizzano
    October 6, 2012

    You may download pkgs first converting them from ELF to bin or ihex (see objcopy) then using the ST link program

  9. Shannon
    December 6, 2012

    First, let me thank you for putting together this awesome tutorial – just the sort of thing I was looking for!

    I’m trying to install this on a 10.7.4 system and am hitting errors during the binutils build. Specifically I’m failing with:

    /bin/sh ./libtool –tag=CC –mode=compile clang -DHAVE_CONFIG_H -I. -I../../../binutils-2012.03/bfd -I. -I../../../binutils-2012.03/bfd -I../../../binutils-2012.03/bfd/../include -DHAVE_bfd_elf32_littlearm_vec -DHAVE_bfd_elf32_bigarm_vec -DHAVE_bfd_elf32_little_generic_vec -DHAVE_bfd_elf32_big_generic_vec -DBINDIR='”/Users/holland/arm-cs-tools/bin”‘ -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Wshadow -g -O2 -MT dwarf2.lo -MD -MP -MF .deps/dwarf2.Tpo -c -o dwarf2.lo -DDEBUGDIR=\”/Users/holland/arm-cs-tools/lib/debug\” ../../../binutils-2012.03/bfd/dwarf2.c
    ./libtool: line 519: CDPATH: command not found
    ./libtool: line 519: CDPATH: command not found
    ./libtool: line 519: CDPATH: command not found
    ./libtool: line 519: CDPATH: command not found
    libtool: Version mismatch error. This is libtool 2.2.7a, but the
    libtool: definition of this LT_INIT comes from an older release.
    libtool: You should recreate aclocal.m4 with macros from libtool 2.2.7a
    libtool: and run autoconf again.

    Any suggestions as to where I might look to fix this? Hoping I don’t have to figure out how to install an older version of libtool 🙂

    Thank you for your help!

  10. Josef van Niekerk
    February 15, 2013

    I’m getting the following when I run
    CC=clang make cross-binutils cross-gcc cross-g++ cross-newlib

    configure: error: Building GCC requires GMP 4.2+, MPFR 2.3.1+ and MPC 0.8.0+.
    Try the –with-gmp, –with-mpfr and/or –with-mpc options to specify
    their locations. Source code for these libraries can be found at
    their respective hosting sites as well as at
    ftp://gcc.gnu.org/pub/gcc/infrastructure/. See also
    http://gcc.gnu.org/install/prerequisites.html for additional info. If
    you obtained GMP, MPFR and/or MPC from a vendor distribution package,
    make sure that you have installed both the libraries and the header
    files. They may be located in separate packages.
    make: *** [cross-gcc-first] Error 1
    rm arm-2012.03-56-arm-none-eabi/binutils-2012.03-56.tar.bz2

    How can I check whether this step succeeded?

  11. Josef van Niekerk
    February 15, 2013

    Removed macports, reinstalled all the packages using homebrew, and now getting a different error on compile:

    make: *** No rule to make target `cross-g++’. Stop.

  12. Denis
    May 29, 2013

    Thanks. Is there a assembled toolchain? Cuz i can’t do it myself. I want to download completed IDE)))

Leave a Reply

Your email address will not be published. Required fields are marked *