Okay, now that I've finally built the prototype hardware for my project and am getting underway with firmware development, I figured I might as well share what I settled on.
Essentially it is a combination of approaches 2 and 3.
I setup an isolated project with the IOC file and CubeMX-generated code on my machine, and use a local git repository (just in its directory) to track changes.
For the real project, I built an entirely custom (and sensible) directory structure that reorganizes all of the CubeMX-generated code into a layout that actually makes sense. I then took notes (and even wrote a script) to keep track of the mapping. For the build process, I'm still using an Eclipse/STM32CubeIDE managed build (based off the Cube-generated .project/.cproject files). I'm also keeping a copy of the latest IOC file in the "docs" directory of my project repo, simply as a shared reference.
On top of all this, the startup/framework code is logically divided into 3 categories:
- "external" - Everything that comprises the main HAL, CMSIS, anything put in "Middlewares", and anything needlessly put in a top-level project directory. Reorganized into a sensible structure
- "system" - Selected pieces that were dumped into "Core" and "Core/Startup" that aren't really project-code, but more like framework/platform glue. This is mostly files that still have the MCU part name in them, or implement various system calls. I may actually end up modifying some of this code, but it will be minimal.
- "src" - The actual project source code, including initialization routines. Some of this is based on snippets that CubeMX generated, but the general structure has been completely rewritten as code specific to the project.
Going forward, every time I want to change something on the CubeMX side, this will be my process:
- Make the change in the STM32CubeMX tool, and have it generate code
- Use "git diff" to see what changes actually happened to the output (this is where keeping it in a local repo helps)
- For simple things like peripheral configuration, manually apply equivalent changes in my own code. For more complex things like framework updates, semi-automatically copy the changed files.
If you're curious as to my specific layout, here is the quick-and-dirty script I wrote to implement it:
https://pastebin.com/7Nd1miGk(Its probably not ideal for ongoing maintenance, but it does get the basic idea across.)
All of this solves three huge "issues" I have with using the CubeMX code dump as-is:
- I hate being told to code between comment guardrails some committee decided to force upon me. I'm not hacking code onto some professor's framework for a college assignment. I don't need to be told "insert code here" or "insert static variables there".
- I really don't like STM's generated directory structure. It feels like something bestowed by a committee as a corporate policy, then they threw their hands in the air and got careless when adding additional components to it.
- I'm not a fan of ST slapping their "Ultimate Liberty License" in random places, and want a structure that makes it easier to keep such code at arm's length. This approach limits that to the bowels of the USB host library and portions of FATFS, and keeps it as far as possible from everything else.