Earlier this year, I wrote about the fun I had setting up the GCC ARM compiler to run under MAC OS X. This kept me occupied for a few days and, eventually, I got it all working. Francois Gervais read the post and kindly offered to share his recipe for building ARM Cortex M3 projects using the GCC compiler. Read on for his notes about the project template…

An STM32 Project Template by Francois Gervais.

This site has a post about using the ST Peripheral Driver Library with a custom toolchain. However. since the low cost microcontrollers are more and more powerful, some project could benefit of C++ OO language.

To modify the C project template to build C++ files a few things have to be done. But first, we’ll take a closer look at how I built my toolchain in order to use that template. This step is important since for some reason the popular CodeSourcery G++ Lite cannot build that template out of the box. Keep in mind that I didn’t debugged that issue since I was not planning on using the CodeSourcery toolchain anyway. There is pretty good chances that the problem that prevent the project to be built is a minor one.

There is a lot of information out there to build a custom toolchain but I built mine with the information of that website:

http://wyper.ca/news/2009/05/building-gcc-for-arm-cortex-m3/

In case the website goes down for some reason here a direct copy/paste of the build sequence:

Build and install Binutils

tar jxf binutils-2.19.tar.bz2
mkdir buildbinutils
cd buildbinutils
../binutils-2.19/configure
–build=i686-pc-linux-gnu
–host=i686-pc-linux-gnu
–target=arm-eabi
–enable-threads
–disable-libmudflap
–disable-libssp
–disable-libgomp
–disable-libstdcxx-pch
–with-gnu-as
–with-gnu-ld
–enable-languages=c,c++
–disable-shared
–with-newlib
–disable-nls
–prefix=/usr
–with-headers=yes
make -j8
make install

Build and install GCC (with Newlib)

tar jxf gcc-core-4.3.3.tar.bz2
tar jxf gcc-g++-4.3.3.tar.bz2
tar zxf newlib-1.17.0.tar.gz
mv newlib-1.17.0/newlib gcc-4.3.3
rm -rf newlib-1.17.0
mkdir gccbuild
cd gccbuild
CFLAGS=”$(CFLAGS) -Wl,-z,defs”
../gcc-4.3.3/configure –target=arm-eabi
–enable-languages=c,c++
–enable-thumb
–enable-interwork
–enable-multilib
–with-newlib
–prefix=/usr
–disable-libada
–disable-libssp

Build and install GDB

tar jxf gdb-6.8
mkdir buildgdb
cd buildgdb
../gdb-6.8/configure
–target=arm-eabi
–enable-languages=c,c++
–enable-thumb
–enable-interwork
–enable-multilib
–with-newlib
–prefix=/usr
–disable-libada
–disable-libssp

It is important to note that this template has been modified to build application for the STM32F103 which is a High Density device. This is different from the one in the original post which was a Medium Density one. Furthermore, the library version 3.1.0 is used instead of 3.0.0. Never the less, the C and the C++ template share a lot of similarities.

Let’s start with the startup file. Other than using the high density device, an assembly line needs to be added in order to call every static constructors of your application. This is added in the startup_stm32f10x_hd.S file (Just before the jump to main()) which is included in the archive.

/* Invoke all static constructors */
bl __libc_init_array
/* Call the application’s entry point.*/
bl main
bx lr

The original Makefile is pretty C++ ready, and most of it is kept as is. An important modification though is the addition of a define argument (-DSTM32F10X_HD) which is used in the stm32f10x.h file of the library.

Some warning has been removed such as -Wshadow since I use to shadow the member of my constructors all the time.

e.g.

Constructor(int member1) {
this->member1 = member1;
}

You might want to re-enable it.

I you take a closer look at the build process in the makefile you’ll see that G++ is used to build the C files as well. Since the ST library was C++ ready (extern “C”) this could avoid some problem in the future. However, it should build fine if you decide to build the C part with gcc and the C++ part with g++. If you do that, it is important that you still link it using g++.

The biggest modifications are in the linker script. I won’t list them here since the file is in the archive as well. Other than small changes to use the High Density devices, it is mostly a hybrid between the file included in the ST library and the generic.ld file included in the CodeSourcery G++ Lite package.

Well, this is mostly it. Code wise, every .cpp file you create in the root directory of the project should be built since the Makefile uses wildcard. The main() is in the Application.cpp file which is a class but wouldn’t need to.

I’ll finish with an example of how I handle interrupts. As the C++ faq lite suggest, I still use a C function to register in the interrupt vector. That function than call a static C++ function.

void USART1_IRQHandler(void)
{
// Data received?
STM32F103::getUart1()->receiveInterrupt();

// Data sent?
STM32F103::getUart1()->sendInterrupt();
}

This is a function added in the stm32f10x_it.c file. STM32F103 is my class which includes multiple static functions to return an instance for every concrete peripheral of the chip. I could provide a more complete example in another post if people are interested. Something like a C++ blink program maybe.

———————–

The project template is available as a zipped tar file:
stm-32-project-template-cpp.tar.gz

I have not yet been able to test this template but, if you have any problems, please leave a comment and I am sure Francois will be only too happy to help.


This Post Has 3 Comments

  1. steffen

    I read the article and i’m interested in programming a stm32 in c++, so i would be happy about a working example.

  2. Francois

    Hi Steffen,
    I’ve been working on a project with that chip all semester using C++ and you can get the code from there:
    svn checkout http://usbarm.googlecode.com/svn/trunk/ usbarm-read-only

    I just added a function in Application.cpp that simply blink a led. You have to make sure that the blinky() function is uncommented in the main() function and that any other function in the main() are commented. This should show you a simple led blinking using our framework. You could probably use this framework in your application as well. The UML of the whole project is in this directory : remote/Planning.

    I’ll try to explain a little more what it does but as I don’t know your domain of expertise it’s hard to know what are the parts that are going to be harder for you to understand. If you need more explanation on something let me know if you are more the software guy or the hardware guy.

    Basically, every time we need something from the chip we ask the STM32F103 class using static methods. This class takes care of creating the object if it doesn’t exist and configure it to be ready to use. Then when you receive the object you asked for, you can configure it using a configuration class. Every peripheral have its own configuration class. In the case of the blinking led example we use GpioPinConfiguration since we want to configure a GpioPin. After that the pin is ready to use.

    As I said I’ve been working all semester on that so everything seems easy for me but my explanations may be unclear. Don’t hesitate to ask for precision.

    If you want to see some video about this project you can go here:

    http://www.youtube.com/user/francoisgervais1

    Right now this one is the latest:

    Francois

  3. Pascal

    Hi François,

    I found this article is very interesting but what should I do to be able to compile with my Olimex P103 starter kit using a Medium Density STM32F103 device?

    Thanks,
    Pascal

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.