cancel
Showing results for 
Search instead for 
Did you mean: 

Writing own drivers vs HAL for professional project

CDyer.1
Senior

Hi,

firstly i apologise if this is in the wrong section as I'm asking more for technical advice than an answer for a specific technical question.

First a bit of background:

I'm a PhD student that is the sole engineer on a three year project that includes hardware design and embedded firmware programming. For the embedded side I've elected to use the STM32H7 line for its fast clock speeds and DSP capabilities as I am going to be doing DSP related work further down the line. i have spent the past two months working with STM32F4 and getting to learn the fundamentals as it is a simpler device than the H7. My previous experience in embedded systems was 8 bit PIC as an undergraduate.

Issue:

The first month spent with the STM32F4 I played around with STM32CUBEMX for the clocks and UART and HAL for the ADC peripheral and got some fairly complicated system (read in to the ADC, do some stuff, output results over GPIO and over USART) up and running. Because I also want to learn the hardware itself, in the second month I spent writing my own drivers from scratch. I got GPIO with interrupts, and SPI up and running. Then I elected to move to the H7 as I want to do some fairly intensive DSP work later on, and in two months have only written GPIO drivers based on the previous work I did for the STM32F4. It is taking me ages to understand the peripherals present in the H7 as they seem to be orders of magnitude more complicated than the F4 (the SPI is a good example of this). If I want to go down the writing my own drivers route, I also have to write drivers for: The clock sources, the USART, the DMA, the ADC, timers and I may want to interface with a TFT display at some point (maybe TouchGFX?). My concern is that I won't have enough time before I get to the DSP part of the project if I write my own drivers as there is just too much work to do (for someone who has to understand how each of the peripherals work first). My other concern however is that if I use HAL to get the job done quicker, I'm not learning enough about the system. I would like to have deep knowledge of the STM32 when this project is done, but my fear is that HAL will abstract way too much. Worse case scenario for me is after the project attempting to get a job that requires register level knowledge and I only have HAL knowledge.

I'd also like to note that I have no professionals here that I can go to for advice. If I get stuck on something, the project halts until I can find the solution.

Can anyone give me any advice on how to make a decision with the project? Do i proceed to write my own drivers and get a better understanding of the chip and more performance out of the chip but at running the risk of running out of time or do I just proceed with HAL and get everything up and running nice and quickly and not worry about the details?

Any help or advice would be appreciated, I'm at the point in the project now where I need to make this decision before I proceed with continuing to write the drivers.

28 REPLIES 28
Ozone
Lead

I reckon the F7 device would be an alternative, and reasonable compromise in performance vs. complexity.

I suggest to have closer look at Cube and H7 related issues here before getting started.

> I would like to have deep knowledge of the STM32 when this project is done, but my fear is that HAL will abstract way too much. Worse case scenario for me is after the project attempting to get a job that requires ARM knowledge and I only have HAL knowledge.

I think most seasoned engineers would agree to your worries.

Work environments, architectures, MCU vendors and toolchains change quite often. No employer in my career ever cared about which IDEs I worked with.

Hi,

thanks for the response. I've actually struggled to determine what the differences are between the F7 and the H7 other than the H7 is newer and practically double the clock speeds. I'll have a look at some of the F7 nucleo board datasheets.

Yeah that's my concern. I like ST but what if the potential future employer is using completely different drivers or worse a completely different chip such as TI or NXP? I want to get as much out of this project personally as I can and HAL wouldn't help with that.

Personally I find MCU and peripheral knowledge is pretty transportable, but then I was doing ARM stuff in the mid 80's and did PASCAL, C and Assembler as an undergrad. Have a pragmatic understanding of the plumbing and function you'll be fine.

Workplaces tend to have MCU and Tool preferences, there may be historic/investment reasons for this, With foundational knowledge you can step into any role and interview well, chips/tools are very transitory.

Find a level that is comfortable, I can do register level coding, but it is a slog, I'm not a fan of HAL, much preferred the older SPL, but they provide for a quick means to pull everything together. You can then discard or refactor portions that you don't like or are just broken, but also tune things based on your own critical paths. ie mash out a working proof-of-concept, then focus time where it makes a difference. Initialization/configuration code is usually run once, its usually not worth spending hours on optimizing, let the compiler/linker optimize and remove dead code. Focus on user interface, it saves a lot of friction from end users/support.

It is easy to get lost in the minutia, focus on the details, and know where to find the specifics when you need them.

The H7 is much more complex than the F7 due to the busing for multi-core, and the dual porting of memory/peripherals and local memories. Check the bus matrix diagrams, be sure to balance where you use/hold resources. Have the CM4 deal with more mundane stuff.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
turboscrew
Senior III

I pretty much second what clive1 said, but note that the HAL is not complete nor efficient considering DSP-use.

The HW can usually do much more than what's supported by HAL, and HAL tends to be slow, because it's quite generic.

I'd vote for doing it yourself. Or maybe with some help from CMSIS.

I'm actually using the nucleo H743ZI which has just a single core M7 but for some reason the number of registers for even the basic peripherals (such as SPI) seems to be a lot more than what is required on the F4. I'm guessing ST offer performance above the usual standard on the peripherals for their H7 line and hence that increases the complexity? Looking at the reference manual for the F77xxx it looks a lot like the F4 reference manual (the basics look almost identical) but with additional features. I think moving down to an F7 is the right move to make.

In regards to the actual firmware side, I completely agree that HAL pulls everything together nice and quickly and you can discard or refine what is needed afterwards. My concern however is that as I've only been exposed to the ecosystem for a number of months relying on HAL will prevent me from having the ability to actually make the changes required unless it is again through HAL. i think that once you know what you're doing code-wise then it is easy enough to rely on HAL because you have the ability to make those changes. I'm not at that point yet, I'm still learning how to LL configure the SPI! Thanks for the advice

KnarfB
Principal III

> get a job that requires ARM knowledge and I only have HAL knowledge.

ARM is the MCU, not the peripherals you mentioned above. They will vary alot from vendor to vedor at register level.

If you abandon existing abstraction levels you have to read the data sheets, reference manuals errata sheets *very* carefully. And, you will have bugs in your code, so you re-read again and spend a lot of time with it. And documentaion? And re-usability? If I was your supervisor, I would not let you do this without a good reason. After you finish, the next person has to live with your project. Yes HAL will hurt you with annoyances and bugs, but nobody stops you digging deeper on demand. So I would go with a top-down approach and keep your target (PhD) in sight.

And, you will learn alot during that time. You will speak fluently I2C / SPI / ... and your favorite tools / IDE. I have hired ~100 engineers during my career and it rarely happend that the applicants uses exactly the same tools as we did. But, if you can demonstrate your knowledge in a nearby field, wouldn't that be great?

Jack Peacock_2
Senior III

Assuming this is not a commercial product being developed you are better off using the HAL and focusing on the core application code. You have a fixed deadline in a PhD program that can't be extended, so there's little margin for delays writing and debugging your own drivers. Yes, some risks are higher in that you have to trust the HAL will work reliably for what you want to do, but all projects have some degree of risk. Being non-commercial you can tolerate a less robust design. Like the Curate's Egg, some parts of the HAL are palatable....

On the other hand, if this IS a commercial product you have to consider long term reliability and maintainability. That's why I never use the HAL, LL or Cube software. If a critical design goal is reliability, especially if there's a safety factor involved, then spend the time to develop your own code library. I require tight control over code quality and functionality for what I work on (medical equipment) so I have an extensive and well-tested library of both code and hardware for STM32 across several families (no, don't ask, all proprietary and very expensive). That library represents quite a few years of work, more than would be justified in your project.

Jack Peacock

berendi
Principal

To make a proper decision, one should make a list of the pros and cons of each option. You have got some experience yourself, there are a couple of bullet points from me.

For HAL

  • Comes with a boatload of examples for most peripherals.
  • Works reasonably well in lots of use cases.
  • Offers somewhat more portability between series as the register interface on supported platforms.

Against HAL

  • Does not even try to cover the hardware capabilities. Lacks the interface for some very basic use cases.
  • Poor documentation. One-liner explanations of functionality that would sometimes require pages to properly explain. Invents its own terminology which is never defined properly. Limitations are not apparent.
  • Poor diagnose and error recovery capabilities. A function returns HAL_ERROR, then... what?
  • As a consequence of the points above, development time is unpredictable. Something might work at the first try, or require a lot more time to troubleshoot than writing a driver from scratch.
  • Another consequence is that there is little agreement on what the proper usage would be. Developers must make lots of assumptions themselves. It can lead to endless arguments and conflicts in a team of developers.
  • Demands lots of resources. Functions are too general, requiring lots of runtime decisions to make. Most apparent in time-critical code, in interrupt handler and elsewhere. Not really suited for real-time signal processing.
  • Poor code quality. Lots of improper volatile usage, and other assorted bugs.
  • Poor code readability. Definitions in the device headers are redefined without apparent reason, even basic C constructs are hidden behind defines.
  • The interface is not stable, sometimes there are incompatible changes between versions.
  • There are no guarantees that HAL will be maintained in the future. As far as we know it, ST might just abandon it next week, as they abandoned SPL.

For the register interface

  • Covers all capabilities of the hardware.
  • Extensively documented in the reference manual and the datasheet, down to the signaling level. Makes the required development effort more predictable.
  • Enables optimal use of resources.
  • The CMSIS naming convention enables writing readable code, and can be easily matched with the reference manual.
  • The interface is stable, it won't change in the lifetime of the product. (There are extremely rare exceptions, like the infamous rev. Y of the STM32H7 series).
  • Peripherals are compatible within one series, and more often than not across some series too.

Against the register interface.

  • Peripherals differ between low-end and high-end series, sometimes they are incompatible.
  • Actual code examples are missing for most series. There are however step-by-step instructions in the reference manual, ready to be implemented in code with little effort.
  • Interconnections and dependencies between peripherals are poorly documented. There is some improvement in the later series though.

There is a third option for the sake of completeness, the LL interface, but it just combines the disadvantages of HAL and the registers, so not really worth considering.

You can consider a mixed approach, prototyping using HAL, and using the register interface only when you hit an obstacle, then gradually converting your work to use less and less of HAL. There is no rule saying that you can only use one of them in a project, but of course once you touch a peripheral register, some assumptions in HAL might become invalid, so e.g. initializing UART with HAL, then doing the data transfer through the registers is fine, but it probably won't work the other way round.

An interesting read and plenty of points to consider, thanks. For the third option, I've yet to do anything with the LL interface but I was considering if this was the best middle ground to take as it isn't as bare metal as directly programming the registers but it isn't as abstract as HAL either. Perhaps combing LL with CMSIS? Would you be willing to explain why this may be a bad idea?