@andy i just read what you wrote on the other post it's almost the same experience, i started to make a progress when i wrote directly to concerned register and not through supplied function.
I used Cube for schematics, when i generated the code same thing those HAL function are not compatible with IDE library am using (IAR) and again to trash i wrote my own code.
I share every single opinion you wrote there, concerning lack of documentation and how much supplied function and tools are
"I'll address the issue of portability between families if and when it becomes an issue, which I strongly suspect will be "never"."
My target uC is a F1 device but for now am using an F0 to test functionality of my prototype ( waiting for the F1 chip to be delivered ) if i understand your sentence right , i will have no issue of portability between both device. So my code can be almost the same. Did you make same test with different family ?
i think the answer to my question is there is no easy way to do it, i will eventually chose to either write directly registers or use the supplied function according to my project needs.
i like the way you wrote that example however it does not solve the main problem, of going through the configuration of all those registers and what is the best way to do it, your gpio file will be filled with those infinite line just to tell the damn compiler you need PA0 to be an output
i will remember this method when i write a code that need to be portable on many uC
So in general, since many ppl here had experience with multiple type of uC, when choosing a specific uC what family you prefer by putting in mind processing capability , cost , and time to market.