One of the next tasks as I emerge from my marathon Hat designs is to wrap up an actual HAL (Hardware Abstraction Layer) in C++ for STM32F405. The Drivers from ST is named “HAL”, but they are low level drivers or merely C functions to interface to registers. They lack abstraction and normalized user interfaces. One good example is CAN. My MCU stop as I try to start the auto-generated CAN, so I went into CubeMX and get the following screen:
So where/how do I set bitrate? Answer: with some difficulty! This is just an excellent example of stuff I don’t want to see in a HAL Interface because this is low Level driver stuff. I expect that the developer who create the HAL class actually deal with this and leave the rest of us a straight forward, well documented and normalized interface!
A proper HAL would actually have a function that allow you to set standard bit-rates as per ISO11898-2 that is the standard for CAN. To be honest I think many of the older ST drivers was better than these new “HAL” ones. I like ST’s MCU series, but their software department need to shape up!
I have mentioned before that one of the better “HAL” interfaces I have seen is the Arduino “Wire” library. Not the code itself, but the actual interface. I can’t use that 1:1 because that library is blocking and I want asynchronous schemes, but it is a good start. CAN as an example should only contain a few control functions Send/Receive/Init and the Init parameter should be baud-rate in normalized form. I admit that I have yet to look into what Mbed have done, so I will do that as well.
The most important to get right is actually GPIO pin mapping. Then writing code you often need to wire your electronics in software, meaning you need to know which pin that has a given function. The way I decided to do this was to create a class “hGPIO” and allow the user to map it’s logical pins to actual physical pins. This means that I declare a hGPIO variable “can1GPIO” and map pin1 as Tx, pin2 as Rx, pin 3 as On/Off, pin 3 & 4 Special purpose etc. My SW will be given a GPIO variable and expect the pins to follow that standard.
I don’t use an On/Off function on my CAN port’s yet, but my software don’t need to know that. In fact the only place in my software I should need to worry about actual schematics and driver setup is in a single AppInit function.
I have used both C and C++ on STM32 in the past, and I will still need to use C on some MCU’s. The reason is that GCC for some reason bloat a bit as we start C++ so we use up the first 65Kb Flash faster than with C. This is because C++ drag in libraries and it probably can be optimized, but I do not care about C++ on a 16Kb Flash MCU. On these small MCU’s I just use bare metal because I can’t afford the abstraction layer.
This is not a new task as I did this before and created a C++ library EFC (Embedded Foundation Classes) to go with it. But, time has changed and it’s time to move on so I want to re-visit my old designs and re-fresh them before I start writing loads of new stuff for now 10 Hat different Hat’s + some, but don’t worry my list of Hat’s I want to make is very long so it will still be plenty of electronics, but I will start moving more and more into Software and end-user projects through this year.
Happy New Year!