cancel
Showing results for 
Search instead for 
Did you mean: 

Is there another way?

luch
Associate III

I am a very patient man. I've spent the last 2 days (not hours! entire days!) studying this 'simple' example from Cube1 (HAL_TimeBase_RTC_ALARM). The example is irrelevant: I've experienced the same with other examples...

So, I'm looking at these files, started digging from main and the rabbit's hole took me very, very far... I found things that are not even mentioned in the (i.e.) Reference Manual... but I digress.

I've been fighting, trying to make some sense of it, with a wall of 38 files and 28064 lines, standing between me and the micro. And this is just a little example program! I am jumping thru this mountain of 'define's and going nowhere. There are people really determined to declare and name and rename and rename and rename things to death. What I don't see on these screen is 'action'. Or real C!

At the end of the day(s) one could gather all that blah-blah-blah (isn't HAL suppose to make our life easier?!) into a handful of instructions that would fit on a screen!

Are all of you, guys and girls, going thru the same? How do you deal with all this sh..oftware?

Is there another way? Or am I just stupid?

14 REPLIES 14

I learned many years ago that people all think and approach things differently.

HAL is a bit of a train-wreck, there are portions that are usable, and other portions and idea need to be taken to the middle of a field and burned. The original SPL abstraction was relatively clean and simple, whereas HAL tries to unify differences in architectures, and applies a paradigm that doesn't always fit will with other embedded solutions/methods. Races conditions, locking, thread safety and priority inversion touch the surface of some of the issues I don't think have been fully addressed.

I take HAL, use the pieces I can work with, and refactor or replace the pieces I can't. For example the USART implementation, only the initialization is worth touching. I'll let the compiler and linker do dead code elimination on the rest.

I can do register level programming, but this isn't an 8-bit micro, and I'm not going to fill my head with 10,000 manual pages.

I've got good static analysis tools, methods, and skills, and a clear understanding of what the underlying silicon is doing.

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 usually read the reference manual or ARM ARM for that architecture (if it's core peripheral).

Then I see how I can make HAL to do it for me. I'm more into register level programming, but I have to use CubeMX (policy at work). Also, HAL doesn't support everything the HW supports. I generate the code with CubeMX and change the set up with code in "user begin / user end" sections. There are usually also macros to flip the bits you need to flip.

With RTC (using stabdby mode) I had to generate the code, copy the code to another place and disable RTC from Cube and generate the stuff again and then add calls to initializations manually to prevent RTC initialization every time the board wakes up from stabdby.

So, to me, using CubeMX usually means a "layer" of extra work, but since I have to...

Thanks Clive,

yep, people do things differently (I don't know about the thinking part), that's why the diversity of tools around these micros. I don't have any preferences yet, as long as I am totally new to HAL, LL, CMSIS & co. What I'm trying to do is to avoid wasting time on things that are not worth it and I might not use in the long run and to focus on those that count: ARM architecture, programming, peripherals, etc. Yes, I'm coming from the 8 bits world (Atmel/Microchip), where one doesn't need to learn 'tools' that introduce an extra layer of abstraction to make things more 'universal', more 'portable', more fancy. Why should I write 200 lines of C, when I can use HAL and deal with 20000?! Maybe it's my lack of experience but I don't feel in control when I have to handle tens/hundreds of files with tens of thousands of lines and to generate an executable from which less than 5% is my contribution.

You, like you said, have the skills, the methods and the understanding not only of the silicon, but the entire environment. You can, therefore, make a determination as to what is the appropriate tool to use in a certain situation, because you already know them - their good and not so good parts. I'm not there yet. I'm just trying to find out how other people are doing things, what should I learn first and what not.

I know there is no easy way to master this. There is a lot to take in and nobody can do it for me - I'd just like to avoid the pollution...

Thanks turboscrew!

CubeMX seems to be a great help, although it is even more controversial than HAL. As a matter of fact I've just downgraded it a couple days ago, from 5.x to 4.27 because the UI of 5 *****.

So, from what I understand, I have to get accustomed with HAL & co. You are far more advanced: change the setup code generated by HAL with your own! How? How does that looks like? What language/library... With the next paragraph you lost me completely, but I understand there is no easy/strait way to write software with these tools. Just pain!

I here openly represent the extreme end of the spectrum, those who do not use any "library".

I started with spending days (not hours) reading the manuals; have written dozens of simple testing programs for the peripherals I intended to use and played with them around (and I still do); and that was it.

> Why should I write 200 lines of C, when I can use HAL and deal with 20000?!

The peripherals are very complicated, as transistor size is small so many of them fit to the chip, and the design process is very much like programming these days, far from stitching together circuits from transistors or gates, so creating that complexity is quite easy. However, most of the peripherals have a simple core where one can start - take for example a timer, you enable its clock in RCC, set some value into TIMx_ARR, set TIMx_CR1.CEN and that's it. Want interrupt? Enable in TIMx_DIER and enable in NVIC and write a handler. This is not much different from what we do in the 8-bitters.Want PWM output? Set some value into TIMx_CCRy, chose the appropriate mode in TIMx_CCMRy., enable in TIMx_CCER, and that's it. Oh wait, you also need to set the appropriate pin in GPIO as AF and set it's proper AF (and before that all enable GPIO's clock in RCC) - but you've already learned how to do all this when you played with the basic loopdelay-blinky.

So, handling the basic features of one peripheral is maybe a dozen of lines in C, not hundreds. And the rest offered by Cube - interrupt handlers, using circular buffers, moving data around, taking care of atomicity and other interrupt-related issues (or you can read it as thread-related or inter-process related, if you are into multitasking aka RTOS) is all basic programming skills, little to do with microcontrollers as such.

So, what a novice really needs are clear and well-described examples, which can be used as basis for the single most powerful and most underestimated programming method, copy-pasting. And he needs dozens if not hundreds of them for every single peripheral.

Now the problem is, that the basic documentation (DS/ES, RM, PM, ARM's material) is not very clear and examples for this sort of programming are scarce(ST started and then also promptly killed Snippets, available in sort of a beta state for F0 and L0 only). OTOH, the documentation for Cube/HAL/LL is also not the clearest (mostly doxygen-autovomited thus not very useful), and as you've said, the examples are also not exactly easy to understand (thus make them as a basis for further work). And, at the end of the day, there is not that many of those examples out there in Cube.

HAL (the "abstraction" part in it) promises portability. I freely admit I can't judge this - I never needed much of that - most of the peripherals in STM32 are the same or very similar across sub-families, and while there are exceptions - I2C, notably - I have no problem reading just one more chapter from the manual and write the software accordingly.

OTOH, "abstraction" inevitably means to find a least common denominator, and implement only a limited subset of what the hardware really allows (and it also inevitably means loss of efficiency of all kinds, but whether it's significant, well that's for another discussion). That's mostly OK as that subset obviously represents the most common usage modes. But once you want to depart from them, well, you're on your own, doing that drilldown and decomposition and figthing against the "native" HAL features - plus you'll have to learn *both* the Cube innards *and* the chip's exact workings, and remember not only the 1000 pages of manual and 1000 Cube-invented names for individual features, but also the mapping from one to the other.

Another promise of the "libraries" is instant access to the more complex peripherals - USB, ETH. Whether it's worth to use them, or to invest time to write your own or invest money into purchasing third-party, well, that's the question of having a deeper look at all those offerings...

Cube also promises easy setup through CubeMX, but that also means certain dependence on CubeMX and its quirks and its - as witnessed by threads in this forum, at times surprising - variablily through upgrades.

Then there of course are bugs, in CubeMX and in Cube/HAL/LL. This is not to blame the Cube/CubeMX authors, we all write bugs at a higher rate than we are willing to admit. I personally just prefer my own bugs to others'... :D

2 eurocents.

JW

Considering a company which want to release a product, they would have to fully own the software and be able to bug fix quickly and send upgrades. This means all used libraries shall be "understood and digested". Would this mean that the time to market is linked to the time to fully grasp a library? Defining learning curve time: Documentation pages, skill level of programmer, number of line of code involved in the project?

Pavel A.
Evangelist III

> but I understand there is no easy/strait way to write software with these tools. Just pain!

​There are different sorts of people. For example I often don't know how to fix my car or what's wrong with it at all. So I go to a garage and they fix it.

Like that, you can outsource all the "pain" of low-level coding to a professional who knows it, and skip straight to things you want to do.

So all the hairwire HAL and stuff become for you just platform_initialize() and that's it! No suffering.

Does it make sense?

If you prefer to do everything alone, bake your bread - there are other small platforms that come with complete software stack - Raspberry Pi's, Beaglebones etc.

-- pa

luch
Associate III

Thanks for the advice Pavel!

To put it simple, I just want to learn now... and I don't think I can 'outsource' that. I don't mind the pain. I'm just trying to avoid unnecessary pain. The 'platform_initialize()' part is already done pretty well by CubeMX, that is the main purpose of it, isn't it?

I am not doing everything alone (although, I wish could): I am here, right? asking for help/advice from people with experience, who have been thru this pain and confusion more or less, at some point. I am trying to gain from their/your experience, so I can avoid the pitfalls of wasting time by going in the wrong direction and focusing in unimportant things.

And I'm doing this as a hobby, I am not a business, I don't have a deadline, no 'time to market', not making money out of it. As most hobbyists, I am investing my time and money in this, with the gain of learning and making things on my own.

luch
Associate III

Thanks JW!

-Wow! I couldn't agree more with (most of) what you're saying!

Those "Libraries", from what I see, are for the most part just a huge collection of defines, typedefs, structures, macros, etc. They attempting to describe in a more human readable way the terse micro's components names/addresses. On a micro where before changing a bit in a GPIO you have to write 100 registers, it make sense to have such 'descriptions'. The problem I see with them is that I still have to learn a ton of (made up) 'names' that not all tools (HAL, LL, CMSIS...) might agree upon, or eventually decide to change them in the future. Plus, the flexibility they're offering has a high price, not only in terms of source code volume (tens of thousands of lines), but also in executable binary - the result being bloated and inefficient machine code. On a 32 bit micro with 100s of KB of flash and 10s of KB of SRAM, they can afford that waste. Time to market is more important! Like everywhere else nowadays, the MO is "Let's make it, sell the garbage before anybody else and maybe later, for a while, if people are complaining, we come up with (and eventually sell them) 'upgrades'."

I wouldn't want to rewrite the math library though, for example... that extreme am I not.

You are absolutely right about their (very few) 'examples'. The examples presented by Cube, or Keil's uVision look more like marketing material: "To run this example, just click on the project's name, to open it in your preferred tool, click 'Build', then click 'Load' and - done! Voila! Soooo simple!! I DON'T NEED/WANT THAT!

I - the novice - am just looking in awe at their blinking LED example and think: "Do they really need all those 50 files, containing 30K lines? What are all these files doing? Are all of them really necessary/used? I hope not! Am I unknowingly compiling a new Linux distribution? Why is the binary 7KB long? Really? To blink a LED? I could do that in 3 lines of C or even assembly on an 8 bitter...". They are not going to answer any of those questions. But anyways, thanks for your examples, guys!

Anyways, it looks like whether I'll use them or not, I'll have to get, at least, familiar with Cube(MX), HAL, LL and especially CMSIS. They have their place, are extensively used and seem to be here to stay... Tools of the trade! That besides the development tools and all the ARM documentation (which is a joke at times).

Thanks again JW!