# STM32CubeMX

***This page:** *the short, concrete workflow for using STM32CubeMX to configure an STM32 project and generate init code without accidentally nuking your work.**

<p class="callout info">**Download:**<span style="white-space: pre-wrap;"> </span>[https://www.st.com/en/development-tools/stm32cubemx.html](https://www.st.com/en/development-tools/stm32cubemx.html)</p>

## 1) What is it

> **STM32CubeMX** is a graphical tool that simplifies the configuration of STM32 products, and generates the corresponding initialization code through a guided step-by-step process.  
> <span style="white-space: pre-wrap;">&gt; </span>[st.com](https://www.st.com/en/development-tools/stm32cubemx.html)

In the embedded subteam, we use STM32 Nucleos to make our robot come to life. We use CubeMX to enable these boards to do what we want by **setting the pins**<span style="white-space: pre-wrap;"> on the physical board and </span>**generating code**<span style="white-space: pre-wrap;"> that we can use to drive those pins. </span>

---

## 2) Starting a (new) project

<span style="white-space: pre-wrap;">Once you have successfully installed CubeMX, you can either create or open a project. You will most likely be working with already existing CubeMX projects. </span>**You can open any project by finding the `<strong class="editor-theme-bold editor-theme-code">.ioc</strong>` file.**<span style="white-space: pre-wrap;"> This is the configuration file for any CubeMX project.</span>

However, there are some **important settings**<span style="white-space: pre-wrap;"> that any project needs.</span>

---

### a. New project

<p class="callout danger"><span style="white-space: pre-wrap;">When creating a NEW project make sure you use the </span>**board selector and NOT the MCU selector**<span style="white-space: pre-wrap;"> to start your project (given the fact that you will be working with a board). If you don't do this, it will cause problems down the line.</span></p>

### b. Project Settings

##### **Project Manager &gt; Project**

<span style="white-space: pre-wrap;">Once you have your project open, navigate to the project manager. </span>

- <span style="white-space: pre-wrap;">It is important that your </span>**project name is "firmware"**, since this is the name the folder is supposed to have in the embedded structure. (This is platformio configuration related.)
- **Do not generate main()**. You should only generate a main function to check what is in there and use it as an example, but when you want to build, you can not have a main function in your auto-generated code. It will conflict with your own main function.
- <span style="white-space: pre-wrap;">Set the toolchain to </span>**Makefile**. You should not use another toolchain, because the post code generation script uses information from the Makefile!

[![afbeelding.png](https://bookstack.roboteamtwente.nl/uploads/images/gallery/2026-04/scaled-1680-/G5rafbeelding.png)](https://bookstack.roboteamtwente.nl/uploads/images/gallery/2026-04/G5rafbeelding.png)

##### **Project Manager &gt; Code Generator**

- <span style="white-space: pre-wrap;">Click the box to generate </span>**separate files per peripheral**<span style="white-space: pre-wrap;">. Otherwise you will encounter errors surrounding missing libraries when building. </span>
- <span style="white-space: pre-wrap;">Set the after code generation script. It can be found in </span>`<span class="editor-theme-code">scripts/post_code_generation.bash</span>`<span style="white-space: pre-wrap;">. More information in </span>[Post-Generation Scripts](https://bookstack.roboteamtwente.nl/books/embedded-infastructure/page/post-generation-scripts "https://bookstack.roboteamtwente.nl/books/embedded-infastructure/page/post-generation-scripts").

<p class="callout info">**NOTE for Windows users:**<span style="white-space: pre-wrap;"> the post generation script will NOT automatically be ran for you. Instead, you will have to run the script by hand in the </span>**git bash**<span style="white-space: pre-wrap;"> terminal.</span></p>

[![afbeelding.png](https://bookstack.roboteamtwente.nl/uploads/images/gallery/2026-04/scaled-1680-/WV6afbeelding.png)](https://bookstack.roboteamtwente.nl/uploads/images/gallery/2026-04/WV6afbeelding.png)

---

## 3) Typical Workflow

### a. Configure pins &amp; peripherals

- <span style="white-space: pre-wrap;">In </span>**Pinout &amp; Configuration**: enable the peripherals you need (UART/SPI/I2C/CAN/Timers/ADC/etc.).
- Assign pins and resolve conflicts (CubeMX will warn you).
- Configure DMA + NVIC if needed (especially for high-rate IO or RTOS systems).

### b. Set up the clocks

- <span style="white-space: pre-wrap;">Go to </span>**Clock Configuration**<span style="white-space: pre-wrap;"> and set your clock source (HSI/HSE) and PLL to the target system frequency.</span>
- Verify peripheral clocks (UART baud rates and timer frequencies depend on this).
- If USB is used, make sure USB clock requirements are satisfied (CubeMX will usually flag invalid setups).

### c. Code generation

**Do not write custom code in CubeMX-generated files.**

<span style="white-space: pre-wrap;">CubeMX will overwrite generated files during regeneration. Any custom code placed there </span>**will be lost**, even if it appears to work temporarily.

**Rule:**

- <span style="white-space: pre-wrap;">Generated code is </span>**read-only**.
- <span style="white-space: pre-wrap;">Your code lives </span>**outside**<span style="white-space: pre-wrap;"> of it.</span>

**What to do instead:**

- Put all application logic in your own source files (`<span class="editor-theme-code">src/</span>`, modules, drivers, etc.).
- Only use generated code as initialization and hardware configuration.
- <span style="white-space: pre-wrap;">Call your own code from the appropriate entry points (e.g. after init in </span>`<span class="editor-theme-code">main()</span>`).

**Bottom line:**  
If your code depends on surviving a “Generate Code” click, it’s in the wrong place.

### d. Generate code, then build &amp; verify

- <span style="white-space: pre-wrap;">Open </span>**Project Manager**<span style="white-space: pre-wrap;"> and confirm the project type/toolchain and output path are correct.</span>
- <span style="white-space: pre-wrap;">Click </span>**Generate Code**.
- <span style="white-space: pre-wrap;">Immediately review changes (e.g. </span>`<span class="editor-theme-code">git diff</span>`). If CubeMX changed a lot more than expected, stop and investigate before committing.
- Build the firmware and run a basic smoke test (UART prints, LED blink, peripheral init success, etc.)