STM32 Project From Scratch on Eclipse

If you want to use the popular STM32 ARM series of microcontrollers but you don’t like using example projects or templates and want to create your development environment from scratch, you are at the correct page. I will explain step by step how to create a project on Eclipse.


Here I use my STM32VLdiscovery board, which is the most basic development kit for ST’s STM32F10x series ARM Cortex-M3 (STM32F100RB) chip. Then I create a project on Eclipse equipped with GNU MCU Eclipse environment.


Be sure that you have all the steps below in order to start creating the first project.

  1. Eclipse CDT (Oxygen) with GNU MCU Eclipse is installed. Follow the instructions on this post.
  2. GNU ARM Toolchain (gcc-arm-none-eabi-7-2017-q4-major) provided here.
  3. Download STM32F10x standard peripheral library (STM32F10x_StdPeriph_Lib_V3.5.0) here.
  4. STM32F10x board to debug (Optional).


Creating an empty project

Start Eclipse and go to Project Explorer, then right-click to create a project.

Now head to “C++ Project” under “C/C++” section and choose “Empty Project” under “Executable” and write the most creative name you can find for your first project.

Click “Next” and “Finish” with both “Debug” and “Release” configurations. Now you can start creating project folder structure.

We need “src”, “inc” and “lib” sections and finally the project will look like the following. Lib stands for MCU specific libraries; specifically stdperiph, CMSIS and linker script in this example project.

MCU Peripheral Libraries

Extract the contents of stdperiph archive and copy everything under “Libraries” folder (CMSIS and STM32F10x_StdPeriph_Driver) into “lib” folder of the project.

We will need a linker script to tell the linker to place everything to correct locations of RAM and Flash. Some sample linker scripts are hidden in the peripheral library archive. Luckily the script  stm32_flash.ld  given under Project/STM32F10x_StdPeriph_Template/TrueSTUDIO/STM32100B-EVAL can be used directly for STM32F100xB (128kB Flash, 8kB RAM). For other variants, you can either adjust the memory ranges in this script by modifying the following (here is a good tutorial)

or find another script for another development board that is closer to your needs.

Create Source Files

We need to create a main function somewhere and obviously the perfect location is a main.c file under src folder of the project. Now we can create a dummy file like the example below. We don’t need to include any headers for the time being.

The second mandatory file is a special header file called stm32f10x_conf.h and somebody has already provided one for us under Project/STM32F10x_StdPeriph_Examples/ADC/3ADCs_DMA. Now after we add these two mandatory files into the project structure, be sure that project explorer looks like this.

Startup File

Startup file is the most important file in my opinion. In contrast with most people’s misunderstanding, the first line of main function is obviously not the first code executed by the processor. There is a long way from the reset vector of the execution memory to the beginning of our application code. This covers;

  1. initialization of static values in .data  section.
  2. zero-filling of .bss  section.
  3. execution of initializer functions and/or static constructors in .init_array.
  4. calling main  function.
  5. execution of destructors in .fini_array  sections. (Refer to here)

Different compilers are supported in stdperiph and we need to exclude the unnecessary ones: arm, iar and TrueSTUDIO under lib/CMSIS/CM3/DeviceSupport/ST/STM32F10x/startup (for Debug and Release).

In gcc_ride7 folder, exclude all expect the startup file for your microcontroller. STM32F100RB is medium-density and value-line. So I excluded all expect startup_stm32f10x_md_vl.s. Finally, we need to rename the file to startup_stm32f10x_md_vl.S (uppercase .S or .asm extension) for Eclipse to see it as assembly file.

Project Settings

Once the project file structure is ok, we need to do some project settings. Simply go to Propertiesby right-clicking to the project in project explorer, then go to C/C++ Build  and Settings.

Chip and Board Definitions

Go to GNU ARM Cross Assembler/Preprocessor and add definitions for STM32F10x_MD_VL (can be different in your application), The crystal oscillator frequency (if any) HSE_VALUE=8000000 and USE_STDPERIPH_DRIVER to enable peripheral library.

Add the same definitions to GNU ARM Cross C Compiler  and GNU ARM Cross C++ Compiler sections too.

Include Paths

Add the library paths to  Includes section of  GNU ARM Cross Assembler, GNU ARM Cross C Compiler  and GNU ARM Cross C++ Compiler as shown below.

Finally it should look like below.

Linker Script Path

To show the linker the path of our script, add its path to GNU ARM Cross C++ Linker/General.


Now the project is ready to compile. But when you try to compile, see the following error in core_cm3.c which is a well-known bug of current version of CMSIS.

In core_cm3.c find the lines:

and change into:

Now you can see the code compiles.


Here is how to enable OpenOCD debugging in your project. Go to Debug Configurationsand create one.

Create a shared file for Debug and Run under Common  tab.

Finally, install STLink driver from here but this is not enough for OpenOCD to connect. Download Zadig tool and install libusb-win32 driver for STLink. If it is not visible on the list, go to Options, List All Devices.

After this step, you are ready for debugging ?

Demo Code

It’s time to see our project in action. Here s a sample main.c file for blinking an LED.

Here we can see that the peripheral library and CMSIS functions can be called from application code. Download link for the created project is also here in case if you have any trouble.


Since this project only works for STM32 micros, it is still a mystery to create a universal project that works with all ARM processors. Although there are many efforts made to achieve this on GitHub, still no general solution exists for all ARM family. Some while ago CoIDE from CooCox was a good alternative but looks like they are having some trouble and support is questionable. Currently it sounds reasonable to stick with KEIL MDK ARM since it supports the widest set of vendors, if this is what desired. Stay up to date ?