STM32 Issues and CubeMX Workflow

STM32 tools include the CubeMX "Wizard" code-generator, the HAL and LL drivers, STM-provided stacks such as USB, and 3rd-party components such as FreeRTOS and the LWIP IP stack and tools. CubeMX generates a skeleton project including selected stacks, drivers, glue code, and hardware initialization. This is incredibly helpful for things like clock setup, peripheral initialization, using peripherals, except...

Unfortunately STM's CubeMX and provided code are extremely buggy. This page describes a project workflow to operate within the CubeMX constraints, using the Eclipse and GCC distributed by STM on Windows. Also included is an index of the most serious outstanding problems I've encountered.

Basic Setup

0) Install Tools
Install the complete CubeMX IDE and tool chain. Make sure to specify a "CubeMX repository" for the CubeMX supporting files as a top-level directory, for example c:\STM32CubeIDErepo (this directory contains all firmware and descriptive info needed by CubeMX). Because of numerous bugs in CubeMX, the repository directory name must not include any spaces. Don't create your repository directory under any location under a user-name that includes spaces,
for example not in c:\Users\Joe Smith\... .
1) Create Top-Level Directory
Create a top-level directory, for example c:\myRepo. Because of numerous bugs in CubeMX, the directory name must not include any spaces. Don't create your top-level directory under any location under a user-name that includes spaces, for example not in c:\Users\Joe Smith\... .
2) Create GIT Repository
Within the top-level directory, create a new GIT repository. Within this top-level directory, place project-wide files like .gitignore, IDE_dict.txt, engineering notes to be versioned, etc.
3) Create Shared Directory under Top-Level Directory
If your project includes multiple Eclipse/CubeMX projects (for example bootloaders, multiple processors, etc) and there's shared code, create a directory to house common code(c:\myRepo\Shared).
4) Create CubeMX Project directory under Top-Level Directory
Create a minimal project for your target and make sure the IOC file is placed in the directory you expect. It is critical that a project subdirectory is created under your top-level directory (for example c:\myRepo\437app)! This way when CubeMX goes off the rails and deletes the entire project directory contents, it does not also delete your repository. Specify major components you need (FreeRTOS, USB, LwIP) in CubeMX, but don't bother filling in all the hardware pin and component details yet.
5) Within CubeMX, Generate Code
Make sure the project compiles before proceeding.

Create A Basic Project

1) Download current versions of any 3rd party libraries
CubeMX currently includes FreeRTOS 10, but other libraries may be out-of-date. In particular, the distributed LwIP is an old buggy version. So,
- Exclude from all builds the obsolete version in the CubeMX-generated project
- Add git exclusion for the old version's tree, ie Middlewares/Third_Party/LwIP/.
- Using a different directory name from cube, place the up-to-date version (ie Middlewares/Third_Party/LwIP_2_1_2/)
- Update all relevant include paths to point to the new version
2) Verify everything still compiles
Hopefully no errors...
3) Commit first snapshot
Before next steps, which are a bit risky...
4) Change the project nature to C++
CubeMX doesn't support C++, so this must be done manually.
5) Correct include paths in the CubeMX-generated .cproject file
The project file has 4 sets of include paths for C/C++ x Debug/Release. When the C++ nature is added, the include paths are not copied from C. Clean, save, and exit Eclipse. Update the C/debug include set:
- edit the first set of include paths in .cproject such that they are sensibly ordered and grouped,
- replace any hard-wired paths with project-relative paths,
- ensure any paths to shared stuff look like
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/Shared/Src}&quot;"/>
6) Test modified include paths in Eclipse
Restart Eclipse. Verify debug project builds properly. Fix anything required, clean, and exit Eclipse.
7) Copy updated includes to all 4 variants
Edit the .cproject, and copy the C/Debug include paths to C/Release and both C++ variants.
8) Test modified include paths in Eclipse
Restart Eclipse. Verify both debug and release build properly. Fix anything required...
3) Commit and backup your work
Good time to take a snapshot before next steps.

Fill In The Project

1) Apply Nadler FreeRTOS-support Patches
STM ships a buggy integration of FreeRTOS and the supporting C runtime library (newlib). Follow the instructions here: newlibAndFreeRTOS.html
2) Blink an LED
Create a minimal task to blink an LED, and verify you can actually build and run the project.
3) Apply Patches...
Apply patches as required to USB stack, CubeMX glue code, and LL/HAL code. Finding all the required fixes is left as an exercise for the reader, as they are very hard to find on STM forum.
4) Fill in basic application
Add application code as required. At some point you will need to adjust settings in IOC with CubeMX, whether its IO pins, adding timers, changing subsystem options, etc. Don't do it before reading the next section!!

Project Regeneration after CubeMX Update

Each time you update the IOC with CubeMX, you'll need to regenerate code.

1) Commit
Never, ever, ever, ever, regenerate code without doing a commit and possibly a backup.
CubeMX will trash a few things!
2) Make IOC Changes, Generate Reports, and Regenerate Code
In CubeMX, make the required changes. Save the IOC, generate the reports detailing your settings, and regenerate code.
3) Review and Repair Damage by CubeMX
Use Meld or your favorite repository-enabled compare tool to survey and repair the damage. At a minimum:
- restore the .cproject file from GIT in its entirety, CubeMX will have trashed it
- restore any patches you've applied that were just overwritten by CubeMX
- restore any 'user code' erroneously deleted by CubeMX
- merge changes correctly applied by CubeMX (ie fixes from a later version of HAL/LL)
- revert anything you have not carefully reviewed!
4) Build, Fix, Retest
Retest everything, as something will have got broken in this process. Repair and retest as required...
5) Commit
Take a deep breath, commit, and maybe backup.

CubeMX and HAL/LL recommendations

ToDo: Add detail here.
Clock init OK except fails to support multiple clock settings (ie low-power and normal).
SPI and timer initialization OK except for Timer bugs (some PWM modes not supported).
Avoid STM's HAL/LL/ISR code for SPI, any DMA - write your own drivers as STM versions are buggy bloatware.
Simple timer code is OK, but for anything performance-sensitive or complicated (or using PWM) don't use the HAL/LL code except maybe for initialization.
Add notes on USB stack issues and patches for bugs and RTOS integration.
xx) Foo
xxx

Major Outstanding Problems

This is a quick summary of major unresolved issues. Unfortunately, STM does not give organized status updates nor provide a public view of outstanding problems. Apparently customers are expected to sort through thousands of unindexed forum posts to find relevant problems/solutions.
Not Good.

Summary

STM's toolchain, especially CubeMX, can be a bit of a trial.
Hopefully this helps ease the pain.
Enjoy!
Best Regards, Dave