29
\$\begingroup\$

So I'm switching from PICs to ARM and I bought an STM32F4 discovery board. So far I understand that to program it you can either access all registers directly in memory (obvious way) and also there are 3 main libraries you can use to make your life easier. Now my question is, which one of those 3 (CMSIS, HAL, Std Peripherals Lib) is the most LOW level one? ie. the one with the less overhead. My goal is to learn the controller's inner workings and not make my life easier (only a little), so I would like to know which of these is closer to the core without resorting to use assembly.

\$\endgroup\$
  • 10
    \$\begingroup\$ [The STM32 side of] CMSIS is essentially just register definitions and no code, so CMSIS == direct register access. AFAIK ST doesn't have a separate download for only the CMSIS, but when you download StdPeriph Lib or STM32Cube, you can choose to just use only the CMSIS part. The STM32 register definitions are found in either Libraries/CMSIS/Device/ST/STM32F4xx/Include/stm32f4xx.h or Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f4xx.h respectively. \$\endgroup\$ – Aleksi Torhamo Mar 24 '16 at 11:53
27
\$\begingroup\$

Definitely the CMSIS. It is not exactly a library, it mostly contains definitions for the various registers.

It is exactly what one needs to access the microcontroller's registers easy, so as to implement his/her own HAL. It has no overhead, since you just access the registers.

Keep in mind that CMSIS, unlike the other two, is defined by ARM and not ST. This means that the various CMSIS libraries out there for the various microcontrollers are quite similar, which greatly aids in portability.

Furthermore, CMSIS is the simpler one so it is (IMO) the most versatile, and most reliable, with possibly fewer (or no) bugs. Some hal libraries for the various mcu's that I've used are quite infamous for their bugs.

On the other hand, CMSIS needs quite more work from you. It is however my personal choice, since I prefer to invest my time creating quality libraries, that suit my needs, and understanding how the chip works, that just spending time to learn just a new library.

\$\endgroup\$
  • \$\begingroup\$ I'm not sure that ST still supports the CMSIS library \$\endgroup\$ – Scott Seidman Mar 23 '16 at 23:41
  • 1
    \$\begingroup\$ Well... something like that. There is not direct link, they discourage it (seems like they want to bind users as much as possible to their code, discouraging them leaving for some other brand), but it is used in their other libraries. You can extract it from there. It is quite simple, does not include much of a code, and seems mature. Looks like its safe for production use, no matter whether they marketize it as supported or not. \$\endgroup\$ – Fotis Panagiotopoulos Mar 24 '16 at 20:24
  • \$\begingroup\$ Yeah, its a bummer that they stopped developing in that direction. The CMSIS compliance was one of the things that drew me to ST in the first place. I still use it, but I have a feeling the day will come when it won't be convenient. \$\endgroup\$ – Scott Seidman Mar 24 '16 at 21:20
  • 3
    \$\begingroup\$ @ScottSeidman, I think you confused CMSIS with StdPeriph. CMSIS is well supported and will be supported indefinitely. Its StdPeriph that is basically deprecated now, but CMSIS is as alive as 10 years ago. \$\endgroup\$ – ScienceSamovar Nov 22 '16 at 4:17
14
\$\begingroup\$

To learn how it works you want to use none of the above. Get an arm cross compiler and the documentation from st, done. Start coding. these chips are generally really easy to program. the documentation tells you what bits in what registers do what.

Any/all of these libraries are intended to remove that understanding/burden/work from you and make it feel like a just call an api like application programming experience. Which is what a lot of folks want. You can use all of the source for these libraries to help understand, but as you get better at it you find holes and problems in the libraries, sometimes very scary code. code tossed together, written generically and roughly ported from one chip to another, perhaps supporting features your chip doesnt have, etc. And they all have an excessive amount of overhead. 10 to 100 times too much code for the task, sure a lot of it may optimize away but why have it there in the first place?

Whether you go your own or use one of these libraries, you should still look at the source for the libraries you use to see if you are comfortable with what they are doing, if it makes sense, matches the chip documentation, etc. When something goes wrong you are likely having to dig through their stuff as much as yours to find out why.

Note the chip docs are not perfect either, that is part of the fun.

I dont understand why assembly comes up in a discussion about bare metal programming. You can get by with very little assembly. For these cortex-m chips, you technically only need this much asm to get booted:

.globl _start
_start:
.word 0x20001000
.word main

You cant rely on data nor bss and you cant return from main with that minimal of asm. But that is all the asm you NEED for the barest of bare metal. Now if you want to do interrupts you need more entries in the vector table. more .word lines. I recommend more asm, but maybe 10 or 20 lines more.

this is typically all the asm I use.

.cpu cortex-m0
.thumb
.thumb_func
.global _start
_start:
stacktop: .word 0x20001000
.word reset
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.thumb_func
reset:
    bl notmain
    b hang
.thumb_func
hang:   b .
.align
.thumb_func
.globl PUT16
PUT16:
    strh r1,[r0]
    bx lr
.thumb_func
.globl PUT32
PUT32:
    str r1,[r0]
    bx lr
.thumb_func
.globl GET32
GET32:
    ldr r0,[r0]
    bx lr
.thumb_func
.globl GET16
GET16:
    ldrh r0,[r0]
    bx lr
.thumb_func
.globl dummy
dummy:
    bx lr
.end

Yeah it says cortex-m0 but this is actual bootstrap for my m4 code. I prefer this to be thumb not thumb2. And I just reuse this code from one cortex-m to another, changing the stack pointer address as needed, so it works for m0, m3 and m4. I dont have an m7 yet nor have I researched it much.

Enabling the fpu might require a few more lines of asm as specific instructions are needed. But the point is dont confuse low level programming and asm. C has what you need to configure the chip, as well as write an application. The libraries you are talking about are written in C not asm, so obviously they dont need to use asm either.

If you want to learn the inner workings, write your own code. Dont use these libraries other than as a reference. Sometimes it is easier to just hack at it than try to read through their code. (not just ST but all of the vendors. One of the vendors had a line of code so alarming I use it as a interview question, nope not going to post it here).

ST definitely but other vendors as well, to save power, have clock enables for sections of the chip, so before you go in and try to blink an led, you need to find the enable bit for that gpio block and see if it comes out of reset enabled, if not then enable it, talking to that gpio logic without a clock enabling it simply hangs the processor as it is waiting for a response from logic that never will respond. They dont always tell you about these enables. Once enabled then they sometimes walk you through the init for some particular peripheral. ST docs are pretty good. Coming from microchip which gets a pretty bad grade for documentation, you shouldnt have a problem.

\$\endgroup\$
  • 2
    \$\begingroup\$ The OP didn't asked about the start-up procedure, or anything like that. Just which library is most suited for his/her use. \$\endgroup\$ – Fotis Panagiotopoulos Mar 24 '16 at 20:15
  • \$\begingroup\$ asm was mentioned and thus the comments on asm \$\endgroup\$ – old_timer Mar 24 '16 at 20:17
  • 2
    \$\begingroup\$ Also the CMSIS does not contain code, apart for some bare minimum. It does not include start-up code, linker scripts or anything like that. It only contains definitions for the registers. Why write cryptic code, or reinvent the wheel, instead of using nice name to access the registers directly? \$\endgroup\$ – Fotis Panagiotopoulos Mar 24 '16 at 20:18
  • 2
    \$\begingroup\$ @John You can easily start an ARM microcontroller with absolutelly no ASM, equally efficiently. If interested ask a new question, and comment a link here to show you some examples. \$\endgroup\$ – Fotis Panagiotopoulos Mar 24 '16 at 20:21
  • 1
    \$\begingroup\$ @user3634713 I'm actually very interested. Thanks electronics.stackexchange.com/questions/224618/… \$\endgroup\$ – John Mar 25 '16 at 11:38
2
\$\begingroup\$

I have used both, just bare metal register access and the std peripheral library. I find it easier just to deal with the registers. Also if you are using a debugger you can view the registers and confirm they contain what you programmed them to be. I think you do learn more about the operation of the chip in that way also.

\$\endgroup\$
2
\$\begingroup\$

Comming from the 8bit world I was always used to programming peripherals via registers. Microcontroller data sheets (i.e STM32 reference manuals) describe the peripherals exclusively in register notation. Since the programmer must read this very same documentation to know about the peripheral funtions and features before any attempt is made to use it then it seems natural to me to start programming the registers. With carful code layout and commenting I find the code can be pleasantly to read and modify even after coming back to it months later.

\$\endgroup\$
1
\$\begingroup\$

Until now I have used CMSIS definitions and enjoyed using registers directly. Meanwhile, I used HAL libraries in few projects. It had a considerable influence on code running time so I quit it. Although CMSIS serves my interest, these days I am going to be a fan of libopencm3. It is like LL libraries provided by ST. However, it covers more micro-controllers even in ST families:

The libopencm3 project (previously known as libopenstm32) aims to create a free/libre/open-source firmware library for various ARM Cortex-M3 microcontrollers, including ST STM32, Toshiba TX03, Atmel SAM3U, NXP LPC1000 and others.

please note that:

Despite the name, libopencm3 also supports other ARM Cortex "related" microcontrollers such as Cortex-M0 or Cortex-M4/Cortex-M4F ones, for example.

you can find the list of supported micro-controllers here.

\$\endgroup\$
  • \$\begingroup\$ The actual problem is that ST has the wrong idea of what a HAL is supposed to do. A proper HAL will have a function like adc_get_result() which wraps in the complete ADC peripheral driver including real-time aspects, interrupts etc. The ST one seems to rather be write_to_scary_register which is basically just a bloated wrapper around the register access. In all fairness, ST isn't the only vendor to provide such excess bloat, Atmel ASF and others are equally bad. \$\endgroup\$ – Lundin Sep 4 at 13:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.