ST32MVLDiscovery project template for GCC

In this tutorial, we will set up a simple template for programming ST32 -Discovery board. For this, we will use the latest Code Sourcery and Eclipse IDE. To make things simpler, we will use ARM-based 32-bit MCU STM32F10x Standard Peripheral Library v3.5.0, that can be downloaded from ST site. Also, we will use STM32VLDiscovery firmware package for example, files. And why write our linker, startup, and make scripts. For this, we will use Michael Fischer’s example project (STM32Test.zip) for yagarto. We only need slight modifications to fit our needs.

In this stage, we assume that you have set up Eclipse and Code Sourcery, and we can go further.

First of all, create new C project in Eclipse File->New:

Enter the project name, select the path where the project will be stored, and select Makefile project->Empty project in the Project type list. In Toolchain, list select Other Toolchain. This will create an empty project that will run make to compile the project.

Now we can start adding files. To avoid a significant mess in the project folder, it is good practice to create some logical folder structure. There are no particular rules how this can be done precisely, but you will find what works best for you. In my case, I create two root folders, Device and Libraries. Then in Device folder, create two subfolders – linker and startup.

After our folders are set we need to copy source and library files that will be needed for our project. First of all, we import linker scripts. Import stm32f103xb_flash.ld and stm32f103xb_ram.ld files to Device/linker folder from STM32Test/prj. Open each of them and edit memory configuration to fit your board like this

 

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

Discovery board has 128K of flash and 8K of RAM. There are two linker scripts for two cases – one to run code from flash and another from RAM. We will be using flash mode for now.

Next step is to import startup code. Now we import crt.c and vectors_stm32f10x_md.c files in to Device/startup directory from STM32Test/src. These are more general and well commented comparing to our earlier discussed. We don’t have edit anything here as startup files are ready for medium level arm cortex-m3 devices.

Now we have to import necessary libraries into our project. These will be CMSIS and STM32Discovery specific. Import latest CMSIS library from downloaded Standard Peripheral Library into the Libraries folder. This library includes a core support library and device support libraries. This is where register definitions are made, system level initializations and standardized access to processor features (Probably we will need to make a separate post about CMSIS). From same location import STM32F10x_StdPeriph_Driver package where all peripheral access drivers are stored. Then import STM32Discovery board specific library from downloaded STM32VLDiscovery firmware package. It lies in an3268\stm32vldiscovery_package\Utilities folder. So import whole Utilities folder into projects Library folder. We should have the following view in project explorer:

We have set up the base. Now all we need is a main program and makefile. stm32vldiscovery_package has a set of code examples. So we are going to use one. So import source files in to root project folder from an3268\stm32vldiscovery_package\Project\Examples\GPIOToggle:

import only files.

The last thing to do is to create a makefile. I used a makefile from STM32Test package and slightly modified to comply with project directories and also added size function to display memories used on the target. So Create new blank Makefile in the project root folder and copy the following contents to it:

 

#
#       !!!! Do NOT edit this makefile with an editor which replace tabs by spaces !!!!
#
##############################################################################################
#
# On command line:
#
# make all = Create project
#
# make clean = Clean project files.
#
# To rebuild project do "make clean" and "make all".
#

##############################################################################################
# Start of default section
#

TRGT = arm-none-eabi-
CC   = $(TRGT)gcc
CP   = $(TRGT)objcopy
AS   = $(TRGT)gcc -x assembler-with-cpp
BIN  = $(CP) -O ihex 

MCU  = cortex-m3

# List all default C defines here, like -D_DEBUG=1
DDEFS = -DSTM32F10X_MD_VL -DUSE_STDPERIPH_DRIVER
# List all default ASM defines here, like -D_DEBUG=1
DADEFS = 

# List all default directories to look for include files here
DINCDIR =

# List the default directory to look for the libraries here
DLIBDIR =

# List all default libraries here
DLIBS = 

#
# End of default section
##############################################################################################

##############################################################################################
# Start of user section
#

#
# Define project name and Ram/Flash mode here
PROJECT        = main
RUN_FROM_FLASH = 1

# List all user C define here, like -D_DEBUG=1
UDEFS =

# Define ASM defines here
UADEFS = 

# List C source files here
LIBSDIR    = ./Libraries
CORELIBDIR = $(LIBSDIR)/CMSIS/CM3/CoreSupport
DEVDIR  = $(LIBSDIR)/CMSIS/CM3/DeviceSupport/ST/STM32F10x
STMSPDDIR    = $(LIBSDIR)/STM32F10x_StdPeriph_Driver
STMSPSRCDDIR = $(STMSPDDIR)/src
STMSPINCDDIR = $(STMSPDDIR)/inc
DISCOVERY    = $(LIBSDIR)/Utilities
DEVICE       = ./Device
STARTUP      = $(DEVICE)/startup
LINKER       = $(DEVICE)/linker
SRC  = main.c
SRC += $(CORELIBDIR)/core_cm3.c
SRC += $(DEVDIR)/system_stm32f10x.c
SRC += $(STARTUP)/crt.c
SRC += $(STARTUP)/vectors_stm32f10x_md.c
SRC += $(DISCOVERY)/STM32vldiscovery.c
## used parts of the STM-Library
#SRC += $(STMSPSRCDDIR)/stm32f10x_usart.c
#SRC += $(STMSPSRCDDIR)/stm32f10x_flash.c
SRC  += $(STMSPSRCDDIR)/stm32f10x_gpio.c
SRC  += $(STMSPSRCDDIR)/stm32f10x_rcc.c
#SRC += $(STMSPSRCDDIR)/stm32f10x_spi.c
#SRC += $(STMSPSRCDDIR)/stm32f10x_rtc.c
#SRC += $(STMSPSRCDDIR)/stm32f10x_bkp.c
#SRC += $(STMSPSRCDDIR)/stm32f10x_pwr.c
#SRC += $(STMSPSRCDDIR)/stm32f10x_dma.c
#SRC += $(STMSPSRCDDIR)/stm32f10x_tim.c
SRC += $(STMSPSRCDDIR)/stm32f10x_exti.c
SRC += $(STMSPSRCDDIR)/misc.c

# List ASM source files here
ASRC =

# List all user directories here
UINCDIR = $(CORELIBDIR) \
          $(DEVDIR) \
          $(STMSPINCDDIR) \
          $(DISCOVERY)
# List the user directory to look for the libraries here
ULIBDIR =

# List all user libraries here
ULIBS = 

# Define optimisation level here
OPT = -Os

#
# End of user defines
##############################################################################################
#
# Define linker script file here
#
ifeq ($(RUN_FROM_FLASH), 0)
LDSCRIPT = $(LINKER)/stm32f103xb_ram.ld
FULL_PRJ = $(PROJECT)_ram
else
LDSCRIPT = $(LINKER)/stm32f103xb_flash.ld
FULL_PRJ = $(PROJECT)_rom
endif

INCDIR  = $(patsubst %,-I%,$(DINCDIR) $(UINCDIR))
LIBDIR  = $(patsubst %,-L%,$(DLIBDIR) $(ULIBDIR))

ifeq ($(RUN_FROM_FLASH), 0)
DEFS    = $(DDEFS) $(UDEFS) -DRUN_FROM_FLASH=0 -DVECT_TAB_SRAM
else
DEFS    = $(DDEFS) $(UDEFS) -DRUN_FROM_FLASH=1
endif

ADEFS   = $(DADEFS) $(UADEFS)
OBJS    = $(ASRC:.s=.o) $(SRC:.c=.o)
LIBS    = $(DLIBS) $(ULIBS)
MCFLAGS = -mcpu=$(MCU)

ASFLAGS = $(MCFLAGS) -g -gdwarf-2 -Wa,-amhls=$(<:.s=.lst) $(ADEFS)
CPFLAGS = $(MCFLAGS) $(OPT) -gdwarf-2 -mthumb -fomit-frame-pointer -Wall -Wstrict-prototypes -fverbose-asm -Wa,-ahlms=$(<:.c=.lst) $(DEFS)
LDFLAGS = $(MCFLAGS) -mthumb -nostartfiles -T$(LDSCRIPT) -Wl,-Map=$(FULL_PRJ).map,--cref,--no-warn-mismatch $(LIBDIR)

# Generate dependency information
CPFLAGS += -MD -MP -MF .dep/$(@F).d

#
# makefile rules
#

all: $(OBJS) $(FULL_PRJ).elf $(FULL_PRJ).hex
ifeq ($(RUN_FROM_FLASH), 0)
    $(TRGT)size $(PROJECT)_ram.elf
else
    $(TRGT)size $(PROJECT)_rom.elf
endif

%o : %c
    $(CC) -c $(CPFLAGS) -I . $(INCDIR)
lt; -o $@ %o : %s $(AS) -c $(ASFLAGS)
lt; -o $@ %elf: $(OBJS) $(CC) $(OBJS) $(LDFLAGS) $(LIBS) -o $@ %hex: %elf $(BIN)
lt; $@ clean: -rm -f $(OBJS) -rm -f $(FULL_PRJ).elf -rm -f $(FULL_PRJ).map -rm -f $(FULL_PRJ).hex -rm -f $(SRC:.c=.c.bak) -rm -f $(SRC:.c=.lst) -rm -f $(ASRC:.s=.s.bak) -rm -f $(ASRC:.s=.lst) -rm -fR .dep # # Include the dependency files, should be the last of the makefile # -include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*) # *** EOF ***

Now you’re all set. Build the project and upload .hex file to Discovery board. You should see blinking LEDs.

The same way other examples can be compiled and used.

Download project files here: STM32DiscoveryTemplate [~700KB]

5 Comments:

  1. Hello,
    I had problems while compiling your files with my toolchain on a linux sytem.
    The solution was to insert a . after the % in the Makefile. Line 154 157 160 163

    %o : %c –> %.o : %.c

    and so on.

    Nice project, thanks…

  2. Hello;
    I imported your template into Eclipse resulting in following errors. Any suggestions?

    **** Build of configuration Default for project STM32DiscoveryTemplate ****

    make all
    MAKE Version 5.4 Copyright (c) 1987, 2009 CodeGear
    Error makefile 115: Command syntax error
    Error makefile 118: Command syntax error
    Error makefile 121: Command syntax error
    Error makefile 129: Command syntax error
    Error makefile 131: Command syntax error
    Error makefile 133: Command syntax error
    Error makefile 152: Command syntax error
    Error makefile 153: Command syntax error
    Error makefile 154: Command syntax error
    Error makefile 155: Command syntax error
    Error makefile 156: Command syntax error
    Error makefile 163: Too many rules for target ‘%o’
    Error makefile 183: Command syntax error
    *** 13 errors during make ***

  3. 3 Error building this project on windows with Eclipse Juno:

    make: *** [Libraries/CMSIS/CM3/CoreSupport/core_cm3.o] Error 1
    registers may not be the same — `strexb r0,r0,[r1]’
    registers may not be the same — `strexh r0,r0,[r1]’

  4. Use newer CMSIS release. In this tutorial CMSIS version is 1.30. This error started popping after new release of courcery G Lite. Download newest CMSIS from http://www.arm.com/products/processors/cortex-m/cortex-microcontroller-software-interface-standard.php

    or modify core_cm3.c file as follows:

    replace:

    uint32_t __STREXH(uint16_t value, uint16_t *addr)
    {
    uint32_t result=0;
    __ASM volatile (“strexh %0, %2, [%1]” : “=r” (result) : “r” (addr), “r” (value) );
    return(result);
    }

    with

    uint32_t __STREXH(uint16_t value, uint16_t *addr)
    {
    //uint32_t result=0;
    register uint32_t result asm (“r2”);
    __ASM volatile (“strexh %0, %2, [%1]” : “=r” (result) : “r” (addr), “r” (value) );
    return(result);
    }

    and replace:

    uint32_t __STREXB(uint8_t value, uint8_t *addr)
    {
    uint32_t result=0;
    __ASM volatile (“strexb %0, %2, [%1]” : “=r” (result) : “r” (addr), “r” (value) );
    return(result);
    }

    with:

    uint32_t __STREXB(uint8_t value, uint8_t *addr)
    {
    //uint32_t result=0;
    register uint32_t result asm (“r2”);
    __ASM volatile (“strexb %0, %2, [%1]” : “=r” (result) : “r” (addr), “r” (value) );
    return(result);
    }

Comments are closed