STM32CubeMX
Last updated: 15-04-2026
On this page
- 1. What is CubeMX?
- 2. Before you start
- 3. Install & open a project
- 4. Typical RoboTeam workflow
- 5. Pinout & peripherals
- 6. Clock configuration
- 7. Middleware (FreeRTOS, USB, etc.)
- 8. Code generation rules (IMPORTANT)
- 9. Git best practices
- 10. Troubleshooting
- 11. Quick checklist
1) What is STM32CubeMX?
STM32CubeMX is STMicroelectronics’ configuration tool for STM32 microcontrollers. It helps you:
- select and configure peripherals (GPIO, UART, SPI, I2C, CAN, timers, ADC, DMA, etc.),
- set up the clock tree,
- generate initialization code (HAL/LL) and project files for your IDE/toolchain.
RoboTeam context: we use CubeMX primarily as a configuration source of truth for pins, clocks, and peripheral init. The generated code is then compiled as part of the firmware in our repositories (e.g. embedded projects).
2) Before you start
What you should have
- The correct board / STM32 part number (ask your lead if unsure).
- The firmware repository checked out and building at least once.
- Basic Git workflow (branch, commit, PR).
Things to clarify (ask in RoboTeam channels)
- Toolchain: Are we using STM32CubeIDE, Make/CMake, or another setup for this project?
- HAL vs LL: Most projects use HAL; some performance-critical code may use LL.
- RTOS: Does this firmware use FreeRTOS?
Important: CubeMX can overwrite files. Treat code generation as a controlled action, not something you click randomly.
3) Install & open a project
Install
- Install STM32CubeMX (standalone) or STM32CubeIDE (includes CubeMX functionality, but not recommended because VS Code is better).
- Install the correct STM32 device pack / firmware package when prompted.
Open an existing RoboTeam project
Most RoboTeam embedded repos store CubeMX configuration as an .ioc file.
- Find the
.iocfile in the repository (common names:*.ioc,board.ioc,project.ioc). - Open it in CubeMX (double click on Windows/macOS, or use File → Open Project).
- Confirm the MCU/board matches what you expect.
Tip: If you can’t find an .ioc file, the project may not be CubeMX-based or it’s stored elsewhere. Ask your team before creating a new one.
4) Typical RoboTeam workflow
When you need to add/change a peripheral (for example: “add UART for debug”):
- Pull latest and create a branch:
feature/cubemx-uart-debug - Open the
.iocin CubeMX. - Make minimal changes: pin assignment, peripheral settings, clocks, DMA, NVIC.
- Generate code (carefully, see Code generation rules).
- Build + run formatting/tests if your repo has them.
- Commit changes (both
.iocand generated code) and open a PR.
5) Pinout & peripherals
Pinout view
Use the Pinout & Configuration tab to assign functions to pins (GPIO, UART TX/RX, SPI SCK/MISO/MOSI, etc.).
- Click a pin and select the function (e.g.
USART2_TX). - Resolve conflicts (CubeMX will warn you if a pin is already used).
- Give GPIOs meaningful labels in CubeMX (helps readability).
Peripheral configuration
For each enabled peripheral (left-side tree), configure:
- Mode/settings: baud rate, polarity, prescalers, sample times, etc.
- DMA: if you need high throughput / low CPU usage.
- NVIC: interrupts and priorities, especially if using FreeRTOS.
RoboTeam convention (recommended): keep pin naming consistent with schematics.
6) Clock configuration
The Clock Configuration tab controls system frequency and peripheral clocks. Getting this right is critical for:
- accurate UART baud rates,
- correct timer frequencies (motor control / PWM),
- USB timing, and
- stable CPU operation.
What to watch for
- Clock source: HSI vs HSE (internal vs external crystal).
- PLL settings: CubeMX will highlight invalid ranges.
- Peripheral clock mux: some peripherals can pick different clock sources.
Common pitfall: “It compiles but communication is broken.” Often the root cause is a clock mismatch causing wrong baud rate or timing. Also, if you use windows, check out your c-compiler
7) Middleware (FreeRTOS, USB, etc.)
Middleware is configured in CubeMX under Middleware (varies by STM32 family / CubeMX version).
FreeRTOS
- Define tasks, priorities, stack sizes, and timers.
- Be consistent with interrupt priorities (especially if calling RTOS APIs from ISRs).
8) Code generation rules (IMPORTANT)
Do not hand-edit generated sections(Recommended). CubeMX regeneration can overwrite changes outside of “User Code” blocks.
User Code blocks
CubeMX-generated files typically contain protected regions like:
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
Only put custom code inside these regions if you must edit generated files.
Safer pattern: keep custom code outside generated files
If the project structure allows it, prefer:
- putting application logic in separate
src/files, - calling your init/setup from
main()inside a user code block, - keeping CubeMX-owned init in its generated location.
When you click “Generate Code”
- Scan the “Project Manager” settings first.
- Confirm the output location matches the repo layout.
- Generate, then immediately git diff to inspect what changed.
Golden rule: Always review the diff. If CubeMX touched hundreds of unrelated lines, stop and ask before committing.
Versioning
CubeMX, HAL packages, and codegen output can change between versions. If your team uses a specific CubeMX/Cube firmware version, write it down in the repo/wiki and try to match it.
9) Git best practices
- Commit the
.iocfile (it’s the source config). - Commit generated code if the repository expects it (most do).
- Keep commits focused: “CubeMX: enable UART2 + DMA RX”.
- Do not mix unrelated refactors with CubeMX regen commits.
Recommended commit flow
- Commit 1:
.iocchanges - Commit 2: generated code changes (if separate)
- Commit 3+: application code changes
10) Troubleshooting
“CubeMX overwrote my changes”
- Check if your edits were outside
/* USER CODE BEGIN */blocks. - Restore from Git history and move custom code into separate files or user regions.
“Pins conflict / can’t enable peripheral”
- Some pins have limited alternate functions; check the datasheet.
- Try remapping (different instance: USART1 vs USART2) if the board wiring allows it.
“UART/SPI/I2C is behaving weird”
- Verify clocks and prescalers.
- Confirm pull-ups/pull-downs and GPIO speed settings.
- Check DMA/interrupt configuration and priorities.
“Build fails after regeneration”
- Compare project settings in “Project Manager”.
- Check include paths / generated file locations.
- Inspect the diff for deleted/renamed files.
If stuck: attach your .ioc, a screenshot of the pinout/clock tabs, and the relevant git diff in your help message. That makes it much easier for others to debug.