6.1. CubeIDE introduction

Since 2019, STM32 CubeIDE® has become the free, STMicroelectronics supported, integrated development environment for STM32 MCUs. Devices released past this date are not supported in Atollic® IDE anymore, therefore there is no way not changing and adopt CubeIDE®. Since CubeIDE® is basically a merging of Atollic TrueStudio® and CubeMX® device configurator, most of the above tutorials remains valid with only minor changes you can easily sort out.

STM32 CubeIDE is available for all major OS. I tried both Windows and Linux versions. It also works for Mac users.


1. CubeIDE install and first launch

You can download CubeIDE® from ST website: www.st.com/en/development-tools/stm32cubeide.html

At time of writing CubeIDE® is in 1.4.0 version. I'll use the Windows version in this tutorial.

Since most of the changes when moving from Atollic® to CubeIDE® concerns project creation. We'll cover this topic in two tutorials.

In the first one (this tutorial) I'll be using the ST-promoted way of doing this using HAL (Hardware Abstraction Layer) libraries and the graphical device configurator. I'm doing this against my will, to be honest, but beginners may find here an easy way to get started. I think that's a mistake to start with graphical code configuration tools because it hides many fundamental concepts that you need to understand first. IMHO, these tools should be used only by advanced users who know what they're doing, and with productivity and portability concerns (and not because of laziness). Besides, mastering HAL libraries requires its own level of expertise. It is another learning curve to climb that keeps you away from the STM32 hardware somehow, which I think is not good.

The one thing I trust: RTF(R)M! Read The F****** (Reference) Manual.

In the second tutorial, we use CubeIDE® to create a basic (HAL-free) template project just like we did in earlier Atollic® tutorials. I definitely recommend this approach first for beginners.

OK. Enough talking. Let us get started!


Start CubeIDE® using your OS launcher.

Since CubeIDE® is an Eclipse environment, the first thing you need at startup is to set the current workspace. The workspace is nothing more than a directory to store projects and settings.
Within Eclipse, various settings may be applied:
-    Globally (for all your eclipse tasks)
-    At workspace level (for all projects inside a given workspace)
-    At project level (for one project only)
For now, let us specify a workspace dedicated to tutorials, under C:\ST\tuto_workspace for instance, if you are on your own computer. You should point to a folder related to your network drive (P:\) if you are working on school computer (e.g. P:\STM32\tuto_workspace). Avoid spaces and special characters in the workspace path.

When you're done click Launch button.

Once started, into the CubeIDE® main window you may close the Information Center:


2. Create a new project

Open File → New → STM32 Project


It takes a little while for CubeIDE® to gather up-to-date device information from ST repositories. Wait until the process finishes.


Then you'll be asked to select the target for the project. We're using STM32F072RB device in these tutorials. Since there are more than 1500 STM32 devices available, you may use the Part Number field to help searching the desired part number:


When you're left with only few choices, pickup the device that corresponds to your package. Here, we're using the LQFP64 package. Select the corresponding line and then click Next.


Give a project name ‘blink’. Use STM32Cube for the targeted project type:

Click Finish.

You'll be prompted to open the Device Configuration Tool. Click Yes.


Again, it takes a little while for the project to get initialized. For new devices, you'll have to wait for the whole Cube Library to download first. Be patient, welcome to the HAL world!



When finished, you'll end up with your project environment ready. Take a look at the tree view in the Project Explorer frame. Expanding folders reveals a pretty big number of files and resources. At first start, the file blink.ioc is opened for edition in the main editor part. This file provides access to a graphical interface that offers visual way to setup the device configuration.


Double-click on the main.c file in the Project Explorer tree view. You'll be asked wether you want to open associated perspective. Answer Yes. You may also check the Remember my decision option to avoid further dialog boxes asking that same question.


A new tab opens in the main editor area and you're ready to start with some coding:


3. Configuring LED pin

Before going on to the LED pin configuration, take a look at the main.c file content. Removing comments leaves us with a pretty simple program that basically performs some initializations before entering en empty forever loop:

int main(void)
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */

  /* Configure the system clock */

  /* Infinite loop */
  while (1)


The SystemClock_Config() function is written below the main() function:

void SystemClock_Config(void)
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  /** Initializes the CPU, AHB and APB buses clocks
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)

And that's pretty much it.

Let us now make the Nucleo® LED blinking. First thing is to configure the corresponding pin (PA5) as a GPIO Output.

In the main editor, open the blink.ioc tab to bring back the graphical device configuration tool.

Locate and click the PA5 pin to select the behavior you want to associate with that pin. As we're going to use it to blink a LED, the corresponding function is GPIO_Output:

Then, right-click the PA5 pin and select the Enter User Label menu entry:

Provide a handy name to the pin such as "LED":

You should end-up with this:

Using the alphabetical view, explore Categories and select GPIO:


You may review all GPIO settings there. At this moment, only one pin (PA5) has been associated with a GPIO function. It is configured as a Push-Pull output, with no pull resistor and a low speed. If you like, you can change settings here (e.g. speed), but those settings are OK for the purpose of LED toggling, so I suggest not changing anything.

You may have observed that some other categories have been flagged with a warning sign. That's only to signal that corresponding peripheral has now limited options. For instance, all ADC channels are no more available since PA5 pin, corresponding to ADC channel input 5, has been used for another purpose (GPIO). There's nothing to worry about here.


4. Generating configuration code

When you are done with the device configuration, hit the code generation button  in the main toolbar.

Again, accept the perspective switching:

Wait until the process completes:

And here we are. New code has been automatically added to main.c.

First, in the main() function, a call to a new function MX_GPIO_Init() has appeared:

int main(void)
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */

  /* Configure the system clock */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();                              // <-- NEW ADDED LINE

  /* Infinite loop */
  while (1)
  /* USER CODE END 3 */


Then below, one can find the implementation of MX_GPIO_Init() function:

static void MX_GPIO_Init(void)
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */

  /*Configure GPIO pin Output Level */

  /*Configure GPIO pin : LED_Pin */
  GPIO_InitStruct.Pin = LED_Pin;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(LED_GPIO_Port, &GPIO_InitStruct);



You can finally note that new defines have been added to main.h:

/* Private defines -----------------------------------------------------------*/
#define LED_Pin GPIO_PIN_5
#define LED_GPIO_Port GPIOA



5. Get the LED blinking

As wonderful as it is, CubeIDE® still does not write application for you! Maybe one day, AI will do that... but that's not (fortunately) for now.

Edit the main() function this way:

int main(void)
   uint32_t	i;

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */

  /* Configure the system clock */

  /* Initialize all configured peripherals */

  /* Infinite loop */
  while (1)
	  // Toggle LED pin
	  HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);

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


Save all and hit the build button . Take a look at the build console. Make sure there are no error and no warnings.

As you can see, quite a lot source code has been built in the process. Most are HAL libraries you can see in the Project Explorer tree view by expanding the Drivers/STM32F0xx_HAL_Driver/src folder:


Also, take a look at the Build Analyzer to check for the amount of memory used by the program:


5. Run & Debug

In the main toolbar, click the dropdown arrow besides the debug button and select Debug Configurations...:


In the Debug Configuration dialog, select STM32 Cortes-M C/C++ Application, and then the New launch configuration button :


Make sure the new configuration has been created and review parameters in the Main tab:


Then move to the Debugger tab and make sure that Debug probe is ST-LINK with SWD Interface:

Then click the Debug button.


In some cases, depending on the previous life of your Nucleo® board, you will be prompted for a ST-LINK firmware update.


If this happens, click Yes. Then proceed to firmware update by using the subsequent dialog window. You'll need to click Open in update mode button before being able to perform the firmware  Upgrade:


When done, you can restart the debug session by simply clicking the debug button .

As usual,;accept the perspective switch if prompted for:


You should find yourself ready for debugging:


From there, you can control program execution using usual toolbar commands (, , , , , , ...), add variables or expressions to watch, etc.

Run the program full-speed by clicking the Resume button. You should get the blinking LED as expected:

Then, suspend the debugger and terminate image041.png the debug session and switch back to C/C++ perspective.