Updating STM32 C template with CMSIS V3

So far, we’ve been using an old template with CMSIS version 1.30. Since then, it was updated several times by adding new Cortex processor families, fixing several bugs, and adding new features. They also changed the folder structure of CMSIS to be more generic. And there is a CMSIS DSP library integrated. With it, you can do complex math tasks using only a few lines of code. So why not upgrading our software template for Sourcery Codebench G++ toolchain with new CMSIS. First of all, download the latest CMSIS package from arm.com/cmsis. You will have to register to access download files—package with CMSIS, DSP library, and documentation weights about 45MB. Since we are working with ST32 microcontrollers, you also need to download STM32F10x Standard Peripheral Library from STMicroelectronics.

Creating a project template

First of all, create an Eclipse project. Let’s name it STM32template. Again we are going to do this for the STM32F103ZET6 microcontroller board. For this, we create an empty project for the Sourcery G++ Lite toolchain. Then we can create a new .c file called main.c. Let’s write an empty loop in the main routine for testing purposes:

int main(void)
{
while(1) { }
return 0;
}

And yes, you can already try to build the project. It will compile, but you’ll get one specific warning telling that compiler can’t find entry symbol _start. And it will be defaulting to 00008000. In this situation, your program won’t work on the microcontroller just because the main should not start at the start of flash but after the interrupt table.

So now we have to take care of these things.

Startup and linker files

As you probably already know, before any ARM program is run, a special startup program needs to be run first. It takes care of loading interrupt vector table, initializing core, initializing variables if needed, and calling the main routine to run user functions. Startup code can be written in C or ASM language. Earlier, we were using the C startup file. Now let’s try ASM. You can find startup file named startup_ARMCM3.s in CMSIS archive in CMSIS-SP-00300-r3p1-00rel0\Device\ARM\ARMCM3\Source\G++ directory. Extension .s means that this is an ASM file. GCC compiler needs .s to be capitalized, so rename the file to be startup_ARMCM3.S. Let’s create a new folder named Device in Eclipse project explorer and import the startup file here. Note that you will have to edit it as it only has Only core interrupts listed correctly. You may need to edit the external interrupt list. In this template, we will use the corrected startup file with a Cortex-M3 HD line vector table. Rename it to startup_stm32f10x_hd.S, which is more obvious.

The linker file gcc_cs.ld is in the exact location as a startup. Import it to the Device folder as well. The only thing you will need to edit here is memory size.

Make sure that the MEMORY part matches the microcontroller memory sizes. For STM32F103ZET6 microcontroller it should be

MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 64K
}

Let’s continue including the necessary files. We need to add CMSIS core files that allow accessing Cortex core functions and registers. From CMSIS-SP-00300-r3p1-00rel0\CMSIS\Include, we will need three files only: core_cm3.h, core_cmFunc.h and core_cmInstr.h. Import those files to the Device folder in the project tree. The last thing we will be needing is the header files of the device. These we need to import from the STM32F10x Standard Peripheral Library that we downloaded. We will need stm32f10x.h, system_stm32f10x.c and system_stm32f10x.h. The first one describes all registers of the STM32 microcontroller, while the other two take care of initializing the system clock. Import these files into the Device folder as well. We should have the following project tree structure:

project tree structure

Changing project properties

Now, let’s adjust project settings to compile everything correctly. Click the right mouse button and select Properties. Go to the C/C++ Build section – this is where all settings need to be changed:

If you go to the C/C++ Build branch, you can see that most of the work is the ARM GCC Plugin. Builder already uses a built-in cs-make tool. It is already selected to generate Makefile automatically. Now go to the Settings branch. Here we will need to select the target processor to be cortex-m3. In additional tools, we can call Sourcery tools that do some actions after compile.

For instance, the Print size calls the arm-none-eab-size.exe tool generates the binary size of the compiled image.

Now go to ARM Sourcery Windows GCC Linker->General menu. Here we need to direct the linker to the linker file. Just Enter in Script file (-T) field following:

${workspace_loc:/${ProjName}/Device/gcc_cs.ld}

This means that it is located in the workspace->project directory->Device folder. Try to avoid using absolute paths as on project location change you will need to change settings again.

Before giving it a try, don’t forget to add locations of header files. For this, In ARM Sourcery Windows GCC Compiler->Directories, we need to add all areas where all project-related .h files are located. Again use workspace related paths:

Now we can try building and see if something is missing.

When trying to build a project, we get an error:

error: #error "Please select first the target STM32F10x device used in your application (in stm32f10x.h file)"

This means that we need to show that we are using the STM32 HD device. We can fix this by uncommenting

/* #define STM32F10X_HD *//*!< STM32F10X_HD: STM32 High density devices */

line in stm32f10x.h file. But better do this using project property. In C compiler preprocessor settings, add defined symbol STM32F10X_HD:

Now let us try to compile. Another error:

c:/codesourcery/bin/../lib/gcc/arm-none-eabi/4.7.2/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-init.o): In function `__libc_init_array':
init.c:(.text+0x3a): undefined reference to `_init'

This is because we left “Do not use standard start files” checked in Properties->C/C++ Build/ARM Sourcery Windows GCC C Linker->General also check “Remove unused sections”:

Now let us try:

text data bss dec hex filename
1192 24 32 1248 4e0 STM32template.elf
'Finished building: STM32template.siz'
' '
**** Build Finished ****

Now it is working. Since the template is ready, you can start building projects around it—download the template here:  STM32template. Also, you can download prepared startup files for other stm32 microcontrollers here: startup_files_for_codebench.

Leave a Reply