Hacker News new | ask | show | jobs
by dbolgheroni 2666 days ago
Hi, interesting article, but I would like to suggest you something. While it's OK to do bare metal just using the memory locations like you did:

    *(uint32_t *)0x40021018 = 0x00000004;
after a few days, it will become tiresome to read and to remember all those addresses. I suggest you to use the header [0] that the ST provides for STM32F1, which is included in packages such as STMCubeF1 [1], STMCubeF0, etc.

For instance, instead of using the memory address directly, you could just do

    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
so it's easier to remember what is what. STMCubeF1 is a big package, but you won't be using the API/drivers ST provides (such as HAL and LL), just the header. As I understand, the STM32 community kind of rejects this API as "bloated".

I have some examples here if you would like to take a look:

https://github.com/dbolgheroni/arm-makefile/blob/master/drv/...

Cheers,

[0] https://github.com/dbolgheroni/arm-makefile/blob/master/stm3... [1] https://www.st.com/en/embedded-software/stm32cubef1.html

4 comments

>but you won't be using the API/drivers ST provides (such as HAL and LL), just the header. As I understand, the STM32 community kind of rejects this API as "bloated".

If you're not making millions of something (cost sensitive), and not running into performance issues with the HAL, just pick a microcontroller with more than enough flash and use the HAL provided by ST. It's faster to develop with, relatively robust, good performance, and it will make your code more portable. Writing directly to registers is the perfect example of premature optimization.

I've spent the last ~7 years writing firmware on the NXP LPC8xx/18xx and the STM32 L0/L4/F7/H7. In that time I've only found a couple of errors in the HALs provided, and only once or twice needed to re-write some HAL code to increase performance. Using the HALs from the vendor saved me an immense amount of development time and made porting code between chips trivial.

    *(uint32_t *)0x40021018 = 0x00000004;

Actually that line is not ok. But for another reason. Without "volatile" in there, the compiler may reorder this access with others, or remove it, or combine it with others. None of that is good.
That's a very important call-out. This is the kind of tear-your-hair-out stuff that's going to be very difficult to track down unless you get it exactly right. I echo that using the definitions makes the code infinitely more readable and writeable, and makes zero difference in terms of performance.
Thanks, I updated the post.
To be fair, the last paragraph of the post mentions CMSIS, which provides proper headers with register names at least.

The HAL is very complete, but a bit hard to read because it supports all the (sometimes very subtle, possibly even undocumented) variations in the STM32 feature blocks. These variations have accumulated over the years.

Edit: also, the STMCube tool is a great help for configuring the chips of that family. It can configure IO pins, function blocks, the sometimes insanely flexible clock tree, generate project skeletons, estimate power consumption, etc... it is actually quite useful.

Curious if anyone has experience with ChibiOS/HAL instead of the ST provided HAL.

http://www.chibios.org/dokuwiki/doku.php?id=chibios:product:...