6.2. Basic template project

In the previous tutorial, we have introduced CubeIDE® environment. The project was built using the graphical configuration tool, which heavily relies on HAL libraries. Let us now see how to get a very basic template project, without HAL libraries.


1. Create an empty STM32 project

Within CubeIDE®, close any open project and then go to File → New → STM32 Project

Follow the same steps as in previous tutorial until you reach that dialog window:

Provide a name to your project ('blink_nolib', for instance) and select Empty as targeted project type. Then click Finish.


You'll get the following starting project structure:


Let us create our own project file organization structure. For that, you can use the New → Source folder or New → Folder buttons, either using right-clicking in the Project Explorer, or from the main toolbar:

  • You must use source folders on the first hierarchical level, otherwise source files will not be included in the build process. Then you can use folders within source folders.
  • You can delete  unused folders.
  • You can drag n drop source files (*.c, *.h, *.s) from a folder to another.

Using these tools, construct the following folder structure in order to organize the project files:

  • /app folder will be used to put application level source files:
    • /app/inc for headers (.h)
    • /app/src for functions implementation (.c)
  • /bsp (board support package) folder will used to put source files used for peripherals initialization and board-related low-level functions:
    • /bsp/inc for headers (.h)
    • /bsp/src for functions implementation (.c)
  • /cmsis folder will be used to put STM32 device drivers:
    • /cmsis/core for CMSIS core headers
    • /cmsis/device/inc for device headers
    • /cmsis/device/src for device startup source code

Note that this folder structure is only a suggestion. If you know what you are doing, you can organize files the way you want and even put everything below root folder, although not recommended…

As your project grows, the number of source files can become really big. You need a clean file structure that you know and understand well to navigate comfortably between sources. The sooner you get familiar with your choice of folder structure, the better. Even for small projects.


When done building the folder hierarchy, you'll need to redefine the included paths. From the Project Explorer, right-click on the project name ('blink_nolib') and then select Properties.

Select the C/C++ Build category. Then, in the Tool Settings tab, select the MCU GCC Compiler→Include paths section.


Delete () any existing path, then add () paths to the header folders (use Workspace button to select folder and avoid mistakes entering paths):

Click Apply and Close when done.


2. Adding CMSIS source files

The default project already features a Linkerscript (.ld) file and a Startup (.s) file. In order to complete the template project, we need to collect few additional CMSIS files from the Cube Library provided by ST.

For that, you'll need a copy of the whole software package associated to our device family (STM32 F0 here). There are few options to get this archive:

  1. You can download the latest firmware package (Cube Library) for your device family directly from ST website :
  2. Yet, if you've completed the previous tutorial, chance is that CubeIDE® already downloaded that firmware package and that it is somewhere on your hard drive. From the main menu, select Window→Preferences. Then select the STM32Cube category and visit the Firmware Updater section. You'll see where the library might have been stored:

    Open that folder using Windows® file explorer to make sure that the library is there:


  3. If it is not there, then you can use the Embedded Software Package Manager from the Help→Manage Embedded Software Package menu within CubeIDE® to get it:


Note that FW package for STM32F0 version is 1.11.1 at time of writing. You may have a different one.


Then copy/paste (using Windows® file explorer) the following files, from library folders, into your project folders:

File(s)  Library folder Project folder
*.h  \Drivers\CMSIS\Include\ \cmsis\core\
stm32f0xx.h, stm32f072xb.h system_stm32f0xx.h \Drivers\CMSIS\Device\ST\STM32F0xx\Include \cmsis\device\inc
system_stm32f0xx.c \Projects\STM32F072RB-Nucleo\Templates\Src \cmsis\device\src
stm32f0xx_it.h \Projects\STM32F072RB-Nucleo\Templates\Inc \app\inc
stm32f0xx_it.c \Projects\STM32F072RB-Nucleo\Templates\Src \app\src

If you are working with a device other than STM32F0RB, just adapt the previous table to your needs… All ST Cube Libraries share the same file structure.


You should end-up with a project structure similar to this one (press F5 to refresh) :


3. Final settings

We need to perform some housecleaning before first build.

  • In the app/src folder, you can delete syscalls.c and sysmem.c files. We don't need those.
  • In stm32f0xx_it.c file:

    - delete or comment the #include "main.h" line. We don't have any main.h file yet.

    /* Includes */
    // #include "main.h"
    #include "stm32f0xx_it.h"

    - delete or comment the reference to HAL_IncTick() in the SystTick_Handler() function. We don't want to use HAL library.

    void SysTick_Handler(void)
      // HAL_IncTick();


  • Finally, in the project properties:
    - Remove all existing preprocessor symbols
    - Add "STM32F072xB"


4. Time to play

Then you can hit the build  button. There should be no error or warning:


Well done! Time to get the LED blinking. Edit the main.c file as follows:

#include "stm32f0xx.h"

int main(void)
	uint32_t	i;

	// Start GPIOA clock

	// Setup PA5 as output

    // Loop forever
		// Toggle LED

		// Wait using a counting delay
		for(i=0; i<100000; i++);


Build  the project again. Then configure and run the debug  session as explained in the previous tutorial. You should get the (famous) blinking LED working!