Author Topic: Whats the most common way of programming STM32 series microcontrollers?  (Read 3414 times)

0 Members and 1 Guest are viewing this topic.

Offline EteslaTopic starter

  • Regular Contributor
  • *
  • Posts: 149
  • Country: us
I recently bought one of those stm32F0 discovery boards and am learning to use it. I come from a PIC microcontroller background, where writing to different registers was the name of the game. I see that you can program in a similar way with the STM32 series micros, but it seems like the difficulty of doing similar tasks is much higher. This is the datasheet I've been using:

https://www.st.com/content/ccc/resource/technical/document/reference_manual/cf/10/a8/c4/29/fb/4c/42/DM00091010.pdf/files/DM00091010.pdf/jcr:content/translations/en.DM00091010.pdf

I notice that most tutorials online, however, don't really reference this document at all, and instead utilize an array of different resources like STM32CubeMX, some libraries in keil, clock configurating excel files, etc, so that they don't have to do the register by register programming.

So my question is this. How should I spend my time learning to program these little beasts? Should I learn how to use some standard libraries (If so, recommendations would be great), or learn the cubeMx thing, or keep chugging with the low level way I have been trying to do things? Thanks in advance!
 

Offline lucazader

  • Regular Contributor
  • *
  • Posts: 221
  • Country: au
There are three main "supported" ways from ST:
- Direct register access. Compact, efficient and flexible. however can be a bit harder to get something up and running especially if you arent used to the cortex-M processors
- HAL LL api. basically small functions that do the manual register manipulation for you. relatively light weight, not quite as configurable
- CubeMX HAL. Mich higher level of abstraction. can be easier to get something working. but it may not function how you want without a lot of playing around. Much more bloated.

All of these approaches are equally valid and there are many proponents of each on these forums.

There are also some other 3rd party/ open source things that do similar things. I dont have a good list of them off the top of my head but im sure some of the community will list some of them below.

I personally use the Cubemx HAL. I find it, along with the CubeMX pin and peripheral setup gets me 80% of the way to most of my low level and driver functions for simpler peripherals, so i can spend more of my time on the business logic of the application.
This is however a personal preference.

Hope you enjoy your time learning the STM32!
 
The following users thanked this post: thm_w

Offline techman-001

  • Frequent Contributor
  • **
  • !
  • Posts: 748
  • Country: au
  • Electronics technician for the last 50 years
    • Mecrisp Stellaris Unofficial UserDoc
I recently bought one of those stm32F0 discovery boards and am learning to use it. I come from a PIC microcontroller background, where writing to different registers was the name of the game. I see that you can program in a similar way with the STM32 series micros, but it seems like the difficulty of doing similar tasks is much higher. This is the datasheet I've been using:

https://www.st.com/content/ccc/resource/technical/document/reference_manual/cf/10/a8/c4/29/fb/4c/42/DM00091010.pdf/files/DM00091010.pdf/jcr:content/translations/en.DM00091010.pdf

I notice that most tutorials online, however, don't really reference this document at all, and instead utilize an array of different resources like STM32CubeMX, some libraries in keil, clock configurating excel files, etc, so that they don't have to do the register by register programming.

So my question is this. How should I spend my time learning to program these little beasts? Should I learn how to use some standard libraries (If so, recommendations would be great), or learn the cubeMx thing, or keep chugging with the low level way I have been trying to do things? Thanks in advance!

You can work with the DM00091010.pdf interactively, and in near real time with the Forth programming language on STM32Fxx. This way you will get to know the STM32xx of your choice intimately.

Yes, it will take time, years even, because STM32F is incredibly feature-full and capable, but you will become a STM32Fxx expert.

My OSS document site has a ton of information on this and we also have a IRC channel on irc.freenode.net #mecrisp

Please see: https://mecrisp-stellaris-folkdoc.sourceforge.io/index.html
 

Offline jeremy

  • Super Contributor
  • ***
  • Posts: 1079
  • Country: au
I use cubemx to generate the setup code (in LL api) and then just use it as “inspiration” when writing my real code. Although most of the clock setup stuff just gets copy pasted.
 
The following users thanked this post: L1L1

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4199
  • Country: us
there is also Arduino, via "STM32duino", at least for some chips/boards:  https://github.com/stm32duino/Arduino_Core_STM32

 

Offline newbrain

  • Super Contributor
  • ***
  • Posts: 1719
  • Country: se
...
A good overview, but allow me to be an obnoxious nitpicker:
  • They are called HAL drivers and LL drivers
  • Both are part of the STM32 Cube (note: no MX), the driver (HAL, LL, BSPs) and tools (e.g. Programmer, RF monitor) suite
  • CubeMx is the name of the init code generator tool.

There are other, non official, libraries that might be of interest, e.g. opencm3, or, for a C++ approach, stm32plus
Nandemo wa shiranai wa yo, shitteru koto dake.
 

Offline emece67

  • Frequent Contributor
  • **
  • !
  • Posts: 614
  • Country: 00
« Last Edit: August 19, 2022, 02:21:24 pm by emece67 »
 

Offline Dubbie

  • Supporter
  • ****
  • Posts: 1115
  • Country: nz
I do the same with the cubeMX

Use what works and replace what doesn’t.

I’m usually interested in solving my problem at hand rather than reinventing wheels unnecessarily.
 

Offline exe

  • Supporter
  • ****
  • Posts: 2562
  • Country: nl
  • self-educated hobbyist
I used Chibios.
 
The following users thanked this post: skench

Offline Siwastaja

  • Super Contributor
  • ***
  • Posts: 8167
  • Country: fi
I recently bought one of those stm32F0 discovery boards and am learning to use it. I come from a PIC microcontroller background, where writing to different registers was the name of the game. I see that you can program in a similar way with the STM32 series micros, but it seems like the difficulty of doing similar tasks is much higher.

It really isn't. More features means thicker reference manual, more control registers and control bits, but usually you go with defaults or zero bits, and skip irrelevant documentation, when doing similar things you did on PIC.

For example, configuring and utilizing UART, SPI or ADC, or a similar complexity peripheral is:
On AVR or PIC: around 3-4 lines,
STM32, simple register access: around 5-6 lines (same as in AVR/PIC, but need to turn on the peripheral clock, plus configure IOs to Alternative Function mode, so about 2 lines more)
STM32 standard peripheral library way - still most prevalent on Google hits: around 30-50 lines of copy-paste or autogenerated code. No abstraction provided; you do the same as in "direct register" way, just with a lot more boilerplate code. Just some two years ago this was the preferred "forum" way and you was greeted with a lot of FUD bullshit if you disagreed; now it's officially deprecated, and people are starting to forget it, thank god. So generally, more and more people are using code autogeneration on larger degree.

Go on with your preferred "PIC way", you'll be just fine. It will never be completely out of fashion, unlike most other, typically inferior ways that come and go within the "scene".

The "modern" STM32 trend of autogenerating unmaintainable bullshit mess from a GUI is of course a lot better than copy-pasting the same unmaintainable bullshit mess from Stack Overflow, so it's getting better, but your chances of actually producing maintainable codebase is better if you keep your PIC C development style.
 

Offline Sal Ammoniac

  • Super Contributor
  • ***
  • Posts: 1668
  • Country: us
I've always preferred to write my own MCU startup and peripheral driver code at the register level. Sure, it's more work initially, but then I have something I'm intimately familiar with, meets my needs exactly, and is generally of much better quality than the typical vendor libraries that look like they were slapped together in a few weeks by a summer intern.
Complexity is the number-one enemy of high-quality code.
 
The following users thanked this post: Siwastaja

Online NorthGuy

  • Super Contributor
  • ***
  • Posts: 3139
  • Country: ca
I always use registers everywhere, for three reasons:

- No matter what you use, it uses registers anyway. Thus, using registers, you can do everything than higher layers can, and even more, but not vise versa.

- Registers are documented, but layers on top of them are not (or the documentation is not as good). Skipping high layers means less things to learn about. This makes things a lot faster.

- You get rid of unnecessary layers, which makes your product less bloated and less buggy.

Besides, if you write a lot for the same MCU, you figure something once, then you can just copy from your old projects and paste, or re-write if your old code doesn't fit. Since you have already figured it out once, it is easier for you to find the best course of action.
 
The following users thanked this post: Yansi, Siwastaja

Offline ralphrmartin

  • Frequent Contributor
  • **
  • Posts: 480
  • Country: gb
    • Me
Another alternative is to get an mbed board, and work at the level of mbed.
 
The following users thanked this post: vad

Offline techman-001

  • Frequent Contributor
  • **
  • !
  • Posts: 748
  • Country: au
  • Electronics technician for the last 50 years
    • Mecrisp Stellaris Unofficial UserDoc
I always use registers everywhere, for three reasons:

- No matter what you use, it uses registers anyway. Thus, using registers, you can do everything than higher layers can, and even more, but not vise versa.

- Registers are documented, but layers on top of them are not (or the documentation is not as good). Skipping high layers means less things to learn about. This makes things a lot faster.

- You get rid of unnecessary layers, which makes your product less bloated and less buggy.

Besides, if you write a lot for the same MCU, you figure something once, then you can just copy from your old projects and paste, or re-write if your old code doesn't fit. Since you have already figured it out once, it is easier for you to find the best course of action.

I guess there are two kinds of embedded designers, one type love registers and see them as the heart and soul of a mcu, the only place where one may master all the intricacies and extract the most out of the device. This kind spend endless time pouring over the data-sheets and murmuring words of joy and amazement, and the occasional "wtf!".

The other kind think that registers are why C and libraries exist, so they will never have to waste time 'reinventing the wheel again'. Often, this kind think that the options provided in a library represent the full capability of the device.

I'm in the former group, and a Forth programming language user.


 
 

Offline Dubbie

  • Supporter
  • ****
  • Posts: 1115
  • Country: nz
The other kind think that registers are why C and libraries exist, so they will never have to waste time 'reinventing the wheel again'. Often, this kind think that the options provided in a library represent the full capability of the device.

I think that’s a bit of an oversimplification. I too enjoy poking at registers and feeling like I fully understand a peripheral from the datasheet at a register level.

At the same time, that gets old after a bit and the
challenge of making an algorithm to do xxx or squeezing all the work I need to do into a reliable, tight loop becomes much more interesting than leafing through to page 1256 in the manual again because you need to check an address or something. And to be fair 95% of what you do on an mcu is pretty basic usually. It’s not an everyday occurrence where the HAL lets you down, although listening to people here, it sometimes can seem like the HAL can’t even blink a “hello world” LED without it blowing up.
 
The following users thanked this post: newbrain

Offline techman-001

  • Frequent Contributor
  • **
  • !
  • Posts: 748
  • Country: au
  • Electronics technician for the last 50 years
    • Mecrisp Stellaris Unofficial UserDoc
The other kind think that registers are why C and libraries exist, so they will never have to waste time 'reinventing the wheel again'. Often, this kind think that the options provided in a library represent the full capability of the device.

I think that’s a bit of an oversimplification. I too enjoy poking at registers and feeling like I fully understand a peripheral from the datasheet at a register level.

At the same time, that gets old after a bit and the
challenge of making an algorithm to do xxx or squeezing all the work I need to do into a reliable, tight loop becomes much more interesting than leafing through to page 1256 in the manual again because you need to check an address or something. And to be fair 95% of what you do on an mcu is pretty basic usually. It’s not an everyday occurrence where the HAL lets you down, although listening to people here, it sometimes can seem like the HAL can’t even blink a “hello world” LED without it blowing up.

This is a complex area so it's a given that everyone will have very varying expectations and experiences.

For instance if I want to enable SPI 1 on my target MCU, I can just do a search in my development system "Bitfields file" and I'll find this:

: RCC_APB2ENR_SPI1EN   %1 12 lshift RCC_APB2ENR bis! ;  \ RCC_APB2ENR_SPI1EN    SPI 1 clock enable

I don't need to go near the datasheet and the Word "RCC_APB2ENR_SPI1EN" when executed will enable SPI 1. It's also automatically memory mapped so there is no need to check any address.  The Bitfields file is automatically generated using CMSIS-SVD for the MCU chosen when I create a new project. I don't have a "HAl" and I don't want one.

Once one learns that all STM32F peripherals are enabled via its RCC clock, there isn't any need to revisit the manual on that score for me.

On the other hand, how long since you swapped the USART 1 TX/RX pins ? Once again, there is no need for me to consult the manual.
: USART1_CR2_SWAP   %1 15 lshift USART1_CR2 bis! ;  \ USART1_CR2_SWAP    Swap TX/RX pins

 :-+
 

Offline exe

  • Supporter
  • ****
  • Posts: 2562
  • Country: nl
  • self-educated hobbyist
Another alternative is to get an mbed board, and work at the level of mbed.

I have a bad experience with this approach. It was waaaay too slow and firmware files were huge. So, very powerful and expensive mcu were required to do basic stuff. It also had a limited support of stm32 mcus. I tried to backport to what I had, but didn't manage.
 

Offline ralphrmartin

  • Frequent Contributor
  • **
  • Posts: 480
  • Country: gb
    • Me
exe: I guess it depends on where you lie on the spectrum from designing something to be produced in large quantity, to working on a one-off project where the most expensive thing is your own time. And, of course, how many further projects you expect to use the same hardware on.
 

Online NorthGuy

  • Super Contributor
  • ***
  • Posts: 3139
  • Country: ca
one type love registers and see them as the heart and soul of a mcu, the only place where one may master all the intricacies and extract the most out of the device. This kind spend endless time pouring over the data-sheets and murmuring words of joy and amazement, and the occasional "wtf!".

MCU peripheral modules are usually fairly simple, even primitive, so I don't see why anyone would have to spend endless time sifting through the datasheets.

And to be fair 95% of what you do on an mcu is pretty basic usually. It’s not an everyday occurrence where the HAL lets you down, although listening to people here, it sometimes can seem like the HAL can’t even blink a “hello world” LED without it blowing up.

It is, of course, possile to blink LEDs with HAL, but even without HAL things are quite simple already. HAL cannot make things even simpler than they already are and thus doesn't provide any utility.

For example, you can enter a room, flip a wall switch and turn on lights. Or, you can use a special broom which you poke at the switch and it flips. The broom doesn't add anything to your ability to flip switches. It might or might not work, you just don't need it. Same with HAL.

Of course, if you live in a society where flipping switches without brooms is frown upon, you might get convinced that brooms are necessary, but this doesn't make brooms any more useful for flipping switches.
 

Offline Dubbie

  • Supporter
  • ****
  • Posts: 1115
  • Country: nz
Well, I will defer to your greater knowledge here. I am a long way from being an expert. I just thought I’d throw out my point of view and experience from a beginners perspective.

A lot of people from an Arduino style background would find the code snippets above completely unreadable. Of course once you make the effort to understand them, they are straightforward enough.
 

Offline pigrew

  • Frequent Contributor
  • **
  • Posts: 680
  • Country: us
Personally, I use STM32CubeMX to generate projects, and then use Atollic TrueStudio. I especially find the pin assignments and clock configuration helpful. I then will use HAL until I find that I can't figure out how to use it. At that point, I'll jump to the register-based programming style, but only for the peripherals where I wasn't satisfied with HAL. Up to now my projects are small enough that I've never worried about the HAL library sizes.

mbed seems like a nice c++ framework for microcontrollers, but I've find its support libraries to be a little bit disjoint (many of the peripherals supported in STM32Cube HAL don't have corresponding C++ mbed drivers). They did release a desktop version of their IDE, so it may be worth checking out again.

ST just released their STM32CubeIDE. I have not tried it, and have no clue how it is different than TrueStudio.
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4199
  • Country: us
ST chips are on their 3rd or 4th "vendor library mechanism"  (stlib, followed by several versions of cube, and the addition of the LL libraries?)  They're not alone - Atmel has equivalent churn on their ARM chips (libsam, ASF (several versions), and now "Start")
In general, I think the library code quality has improved over time, but it does make me wonder about whether the time investment in learning the vendor library is worthwhile.
 
The following users thanked this post: exe

Offline mikerj

  • Super Contributor
  • ***
  • Posts: 3237
  • Country: gb
You can work with the DM00091010.pdf interactively, and in near real time with the Forth programming language on STM32Fxx. This way you will get to know the STM32xx of your choice intimately.

Yes, it will take time, years even, because STM32F is incredibly feature-full and capable, but you will become a STM32Fxx expert.

My OSS document site has a ton of information on this and we also have a IRC channel on irc.freenode.net #mecrisp

Please see: https://mecrisp-stellaris-folkdoc.sourceforge.io/index.html

Just had a browse through your website and found this C example you use to demonstrate the complexity and information hiding of C; "I’m mystified where the WFI command is hiding in this C code."

There is no WFI command in that C code.  If you follow the link you provide to the ST forum, you'll find the person that posted that code was asking how to add the ability to sleep after 10 LED flashes to that bit of code, he was not claiming it already had that feature!
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf