It would be nice to start with a simple LED flashing, blinky type application. Well simple is a bit of an overstatement. The code to blink an LED is easy enough but those nice folk at ST have provided a special peripheral driver library. This library abstracts much of the hardware from the user and should make for more portable code. The library sources are all in standard C and are supposed to compile up just like anything. Even with the benefit if an IDE, this would be a bit tricky to set up. Without one, it means a lot of messing about with makefiles, linker scripts and startup code. This is how I set up mine on a Mac. Much the same arrangement will work just fine on a PC. Included is a project template to speed things up…
While most code examples out there use the ST Firmware Library Version 2, I thought I would base my stuff on the newer Peripheral Driver Library V3. It makes little difference to me since I have nothing invested in the earlier version and the programming interface is supposed to be the same in V3 as it was in V2. We shall see. You can download the library here:
When unpacked, the installation structure is a bit overwhelming. There are lots of folders.
Various essential parts of the library are in different places in this structure. The main driver code and header files live in the STM32F10x_StdPeriph_Driver folder and, apart from an unpleasant looking path name, are neatly arranged. To build a program with these files, you will also need to include in your project a few other files. These are mostly in the path
and comprise the following files:
system_stm32f10x.h stm32f10x.h core_cm3.h system_stm32f10x.c core_cm3.c
Like the actual driver files, they can be left where they are if you make sure that they can be found by your project makefile. There are two lines in stm32f10x.h that will want changing to set the processor type and to make use of the Peripheral Driver Library. If those settings are different from one project to the next, you will need to make a local copy of the file in your project folder and ensure that it is found first. As it will be the first #included file in main.c, that should not be a problem
In the startup/gcc folder, you will find three more C files which are the startup code for the three families of STM32 processor. My processor of choice is the STM32F103RBT6 which is a medium density device so I will be using the startup_stm32f10x_md.c file. You can make a local copy of that or you can make sure that the Makefile can find it during a build.
So that the Makefile can locate the C files needed by the project, I have added their location to the vpath variable in the file thus:
LIBSTM32 = /Applications/arm/stm32f10x_stdperiph_lib_v3.0.0/Libraries CM3 = $(LIBSTM32)/CMSIS/Core/CM3 STARTUP = $(CM3)/startup/gcc
DRIVERS = $(LIBSTM32)/STM32F10x_StdPeriph_Driver vpath %.c $(DRIVERS)/src $(CM3) $(STARTUP)
The penultimate piece we will need is a linker script so the linker can find out where all the bits of our program will go. The only one in the library is part of the Template project, intended for use with the Raisonance Ride7 IDE. You can find it here:
The settings are not quite what we want but it can be edited to sort out the small differences required later. These are mostly, I think, limited to the memory sizes and locations. I had some trouble with very large binary images being produced by objcopy. This seems to be a result of the LMA of sections not being generated correctly when the .data section was empty. Adding a KEEP() directive to those sections seems to have fixed it. The linker script (stm32f10x_flash_md.ld) is part of this archive:
The archive file contains a complete, blank template for a project set up with the information above in a folder.
This folder contains all the files needed for a project template when building a C project using the CodeSourcery GNU ARM compiler. It is based on the 2008q3 distribution although nothing in here should depend upon the exact version.
The Makefile is in two parts to make it easier to edit only that part needed by most projects. The Makefile itself simply defines the source files and the target name and then includes makefile.mk for all the actual work.
The project assumes you will be using the ST Peripheral Driver Library V3. The installation location for this library is defined in makefile.mk
The folder should contain at least the following files:
main.c Makefile makefile.mk README.TXT stm32f10x.h stm32f10x_conf.h stm32f10x_flash_md.ld stm32f10x_it.c stm32f10x_it.h
The template is a complete, but completely useless, program in its own right. It will build and produce output files so that you can test your toolchain setup.
To start a specific project, copy all this into a new folder with an appropriate name. Change to that folder and run make. If everything is set up correctly, you should get a bunch of object files, a couple of listings and, by default, a .bin file containing the image to be written to the processor. The settings in the linker script and makefile.mk assume the use of the STM32F103RBT6 processor. Note that the Makefile will create all the object files for the libraries in the project folder. At some point, I will try and bild the peripheral driver as a library but, for now, this will do.
A simple ‘make’ will build the project, ‘make clean’ will tidy out the objects, listings and binary, ‘make program’ will try and build the program if necessary and then load the binary to your target but you will need the stm32loader.py script for that. See this post for more details.
Assuming you want to use the Peripheral Driver Library, open stm32f10x_conf.h and uncomment the lines corresponding to the subsystems you wish to use.
The interrupt handlers are defined in the stm32f103x_it.c file. If you have a look in the startup code in startup_stm32f10x.c, you will see that al the interrupt handlers are defined there with the WEAK attribute and they all point to a default handler that just runs an endless loop. The WEAK attribute means that you are able to define another interrupt handler of the same name in another source file and it will override the one in the startup code. this is how the stm32f103x_it.c file is able to have apparently duplicate interrupt handlers to the startup code.
If it is more convenient, individual handlers could be placed in their own source files.
I think I now have all the pieces needed to start building applications for the STM32. the next step will be to translate some of the examples provided with the library for my development boards.
This Post Has 9 Comments
I have been closely following your blogs on STM32 and have a rather off topic query. You have been using PIC controllers for a long time for micromouse, what prompted you to shift to STM32 rather than PIC32? Or, in a different way, How STM32 is superior to PIC32?
I am being a bit lazy here and have not checked the STM32 datasheet.
Well, the PICs were a bit of a diversion because they had a free C compiler and reasonable tools. I wanted to be using REnesas processors because I quite like the architecture. They, however, had poor support for SPI and the dsPIC was next best.
then I discovered the STM32 Cortex-M3 devices at a trade show. these had everything I could want in a mouse controller. Every ‘can it … ‘ question I asked the sales chap was met with the answer ‘Yes!’
Crucially, that included the ability to handle at least two sets of quadrature encoders.
It was only after that I found out about the ‘MC804 dsPICs.
Now that I have the iMac, I am almost compelled to use different tools, even though I can run Windows in a virtual machine.
Other than that, I think that pretty well every aspect of the dsPIC is available on the Cortex but better.
I took your template a few weeks ago and now I came out with a version slightly modified to support the ST library v3.1.0 and some other modifications to compile C++ (makefile, linker…)
As your site is quite popular when we search for information for the Cortex-m3 from Google, I though maybe you’d like to put my version online so other could possibly use it.
Let me know.
That would be interesting. Email me direct and we will see whta we can do. I have no problem with a post written by you.
I tried to compile the example project using the new standard peripheral library v3.1.2 and codesourcery 2009q3-68, and found that it results in an empty binary file. Only by removing the option –gc-sections does the binary file end up with something in it.
Also had to remove
SRC += startup_stm32f10x_md.c
so that the example would compile, it doesn’t seem the startup .c file is included in the new downloads, there is an assembler source file, however I didn’t need to include that for the compile to work.
Is the gc-sections option important? From a little reading it seems to be a good idea, any ideas as to how to get it to work correctly?
Any help greatly appreciated.
thabks for the information. I must confess to not having looked at this for some months. I have been trying to get the Rowley stuff to work. Is it me or is all this just damned obtuse? I am tempted by the Rowley Crossworks just because I really don’t need to be tweaking my build environment and projects every time someone updates a library or compiler distribution. You might like to look at the post by Francois here: https://micromouseonline.com/sites/default/files/2009/10/19/another-stm32-project-template.
As far as I know, the -gc-sections option is to remove unused sections from the image. Not using it should just leave your object code larger. Perhaps the linker script is putting stuff in a place I have not anticipated.
Stupid beginner error! The fix was quite simple to get gc-sections working.
It would seem that the startup assembler file is required after all. Added:
ASRC += startup_stm32f10x_md.S
to makefile.mk, and also copied the file “startup_stm32f10x_md.S” into the project directory. Binary file generated by make is no longer empty! Still haven’t had a chance to load generated code onto a controller and run it though, but at least the binary is no longer zero bytes!
This doesn’t seem any worse than before (worse in terms of copying the startup code file to another location), as previously the startup code in a .c file was copied to the project directory (at least according to the makefile comments).
Hopefully someone finds this useful and can shave some time of their initial setup…
k i have read the post and now have an idea about building my LCD interface application.but is there any follow up link where i can find out this part
“I think I now have all the pieces needed to start building applications for the STM32. the next step will be to translate some of the examples provided with the library for my development boards”
I am afraid I have nothing to publish here at present.
There should be plenty of other information available on the web though.