Author Topic: Migrating from AVR to STM32  (Read 9397 times)

0 Members and 2 Guests are viewing this topic.

Offline Sudo_apt-get_install_yumTopic starter

  • Regular Contributor
  • *
  • Posts: 165
  • Country: se
Migrating from AVR to STM32
« on: January 28, 2021, 01:39:41 pm »
Hi folks!

Like the title says, I’m moving away from AVR microcontroller series to the STM32 family.

I’m doing this because the STM32XX provides better performance, power use, cost and peripheral support over the old 8-bit AVR family.
I also see it as a big bonus, understanding the more modern processor cores.

I’m quite comfortable with the low level AVR things, written a lot of code in ASM and C/C++ but I’ve never used ASF. I always felt it to be unnecessary and add too much overhead for most things you could do on an 8-bit MCU.

I made a breakout board for the STM32L010K4 and have programmed it through STM32Cube-IDE and got a "blink" program up and running. The blink code i wrote was configured through CubeMX and uses HAL, their alternative to ASF.

The code uses 80.5% RAM(1.6 of 2K) and 54.5% FLASH(8.7 of 16K) and it makes me angry, so much waste. :'(
Is it normal to have this much memory overhead?

I’m used to configuring registers/ peripherals myself and seeing 32K FLASH as infinite storage and 2K RAM as more than enough.
Have some I/O input, use the T/C, sample something with the ADC and send it somewhere over a protocol.
This would result in a few percent of what this blink sketch is using.

Im aware that the STM32L010K4 (cortex M0+) is more complicated and requires more configuration but this is crazy.
Everyone on the web seems to use HAL. I would be more than happy to configure peripherals myself, maybe use HAL for more complicated things but I’m having a hard time starting out.

Does anybody have good appnotes, books or blogs with getting started with STM32 without the bloated abstraction layer.
 

Online Doctorandus_P

  • Super Contributor
  • ***
  • Posts: 3819
  • Country: nl
Re: Migrating from AVR to STM32
« Reply #1 on: January 28, 2021, 01:53:04 pm »
My first dip into STM32 was with the Pandafruits STM32 primer:
It's a very short introduction about the really low level stuff, such as fiddling a bit with linker scripts.
http://pandafruits.com/stm32_primer/stm32_primer_hardware.php

A book I like very much is:
STM32_Beginning_Developing_with_FreeRTOS_libopencm3_and_GCC

ISBN-13 (pbk): 978-1-4842-3623-9
ISBN-13 (electronic): 978-1-4842-3624-6

Hackaday has some recent articles about STM32.
(Avoid the "Blue Pills", the "Black Pills" are probably still good for as long as it lasts).

And of course, sites like github and gitlab have loads of "example" projects, working with different frameworks. (or none at all)

I have used serial sathosimn (which exposes all 3 UARTS of an STM32F103C8T6 over USB as CDC (slightly tested on my linux box. It worked for me).
I've also put one of the GRBL ports for STM32 in such a chip and it also works :)


« Last Edit: January 28, 2021, 01:56:32 pm by Doctorandus_P »
 

Offline newbrain

  • Super Contributor
  • ***
  • Posts: 1765
  • Country: se
Re: Migrating from AVR to STM32
« Reply #2 on: January 28, 2021, 02:51:41 pm »
Something is not quite right with your project:
Code: [Select]
------------------- Memory utilization report -------------------
Used FLASH: 5576 bytes out of 16KB (34%)
Used SRAM: 44 bytes out of 2048 bytes (2%)

========== Project Build Summary ==========
    TestL0  built in 00:01
========== Build: 1 Succeeded, 0 Failed, 0 Skipped ==========

Yes, FLASH occupation is not trivial, but this is without any kind of optimization.
-O3 (speed):
Code: [Select]
------------------- Memory utilization report -------------------
Used FLASH: 3920 bytes out of 16KB (23%)
Used SRAM: 44 bytes out of 2048 bytes (2%)

Still a lot, but more tolerable.
Nandemo wa shiranai wa yo, shitteru koto dake.
 

Offline Siwastaja

  • Super Contributor
  • ***
  • Posts: 8748
  • Country: fi
Re: Migrating from AVR to STM32
« Reply #3 on: January 28, 2021, 02:56:00 pm »
Skip all the HAL and other crap. You'll thank yourself later for being able to actually do projects instead of debugging broken and limited libraries.

You'll have the advantage of knowing how to do it on AVR. The same methodology works for STM32.

Yes, porting between different chips is always some work. This is equally true when using the STM32 HAL, since it doesn't really completely abstract the hardware away (that would be impossible to do). Real projects tend to use significant part of the resources of the MCU, meaning there is the task of mapping your application to the resources, no one has automated it for you.
« Last Edit: January 28, 2021, 02:59:19 pm by Siwastaja »
 
The following users thanked this post: HB9EVI

Offline capt bullshot

  • Super Contributor
  • ***
  • Posts: 3033
  • Country: de
    • Mostly useless stuff, but nice to have: wunderkis.de
Re: Migrating from AVR to STM32
« Reply #4 on: January 28, 2021, 03:05:25 pm »
Like the title says, I’m moving away from AVR microcontroller series to the STM32 family.

...

Does anybody have good appnotes, books or blogs with getting started with STM32 without the bloated abstraction layer.

Welcome to another world.
One doesn't care too much about Flash / RAM use here, just don't use the smallest derivative. A reasonable starting point would be a derivative with 128k Flash and 20k RAM.
The modern STM HAL is bloated indeed,  old versions of the STM32 STDFW just did the GPIO and some basic peripheral initializations and that's it. Long time gone, and no useful way back. You might want to check the LL api instead of HAL. Or just switch over to something completely different, e.g. using the drivers etc. that come with ChibiOs, this is a real time OS that'll come in handy at some point anyway. Most of my projects use an RTOS today.
Safety devices hinder evolution
 
The following users thanked this post: Sudo_apt-get_install_yum

Offline Tagli

  • Contributor
  • Posts: 31
  • Country: tr
Re: Migrating from AVR to STM32
« Reply #5 on: January 28, 2021, 03:54:33 pm »
I prefer to avoid using HAL. You need to study reference manual anyways in order to use STM32 effectively. So, in reality, HAL can't abstract you from the hardware unlike its name suggests. Without the full knowledge of the reference manual, you just find yourself fighting with HAL, trying to understand the meaning of options & settings in CubeMX (or CubeIDE). The reference manual is all you need to know, so there is no point of learning the working details of some weird framework IMO.

It's true that there are some variations among the hardwares belonging to different families of STM32. But they are not many or hard to learn. They are the same more or less. For example, GPIO configuration was different in old F1 series, but then it remains same in other families. Or DMA configuration was a little bit different between F1 & F4. But you will get used to it, don't worry. You already have the experience of register level programming.

But I still recommend using CubeMX to see pin configurations and clock tree settings. Once you know which pins to use for hardware modules and the values needed for clock prescalers, you can easily use these settings in your register level code.

I have switched to C++ (from C) recently and started to create some thin hardware wrapper classes to make it easier to configure hardware modules. I think, after spending some time in register level programming, you will end up with your own libraries and everything will become easier.
Gokce Taglioglu
 
The following users thanked this post: Siwastaja, Sudo_apt-get_install_yum

Offline Sudo_apt-get_install_yumTopic starter

  • Regular Contributor
  • *
  • Posts: 165
  • Country: se
Re: Migrating from AVR to STM32
« Reply #6 on: January 28, 2021, 04:32:05 pm »
Skip all the HAL and other crap. You'll thank yourself later for being able to actually do projects instead of debugging broken and limited libraries.

You'll have the advantage of knowing how to do it on AVR. The same methodology works for STM32.

Yes, porting between different chips is always some work. This is equally true when using the STM32 HAL, since it doesn't really completely abstract the hardware away (that would be impossible to do). Real projects tend to use significant part of the resources of the MCU, meaning there is the task of mapping your application to the resources, no one has automated it for you.

I prefer to avoid using HAL. You need to study reference manual anyways in order to use STM32 effectively. So, in reality, HAL can't abstract you from the hardware unlike its name suggests. Without the full knowledge of the reference manual, you just find yourself fighting with HAL, trying to understand the meaning of options & settings in CubeMX (or CubeIDE). The reference manual is all you need to know, so there is no point of learning the working details of some weird framework IMO.

It's true that there are some variations among the hardwares belonging to different families of STM32. But they are not many or hard to learn. They are the same more or less. For example, GPIO configuration was different in old F1 series, but then it remains same in other families. Or DMA configuration was a little bit different between F1 & F4. But you will get used to it, don't worry. You already have the experience of register level programming.

But I still recommend using CubeMX to see pin configurations and clock tree settings. Once you know which pins to use for hardware modules and the values needed for clock prescalers, you can easily use these settings in your register level code.

I have switched to C++ (from C) recently and started to create some thin hardware wrapper classes to make it easier to configure hardware modules. I think, after spending some time in register level programming, you will end up with your own libraries and everything will become easier.

I’m lumping your post together since you have a similar outlook on this.

I’m not to concerned with the portability of the code between processors. Most of my projects are self-contained and I rarely switch processor mid project. I always write some sort of an abstraction layer when writing drivers and make them self-contained.

What would be a typical workflow? I don’t have any fancy environment like Keil or AIR so will be using CubeIDE combined with CubeMX.
Do i generate the base of the project in CubeMX or do I start from scratch, setting up the linker and all config files on my own?

Is there a way to split all the generated functions and add them in a separate file instead of having a huge main file?
Is there any way to prevent the generator from constantly removing my user code? I have checked the box "Keep User Code when re-generating" but it doesn’t seem to do anything.

Below is my simple but large code. I made a fresh project and removed the minimum heap & stack size.








 

Offline Tagli

  • Contributor
  • Posts: 31
  • Country: tr
Re: Migrating from AVR to STM32
« Reply #7 on: January 28, 2021, 04:50:59 pm »
I use STM32CubeIDE and create an empty C++ project. But it needs some work after that. I download CMSIS & ST's Cube package, (just for the up-to-date device headers), from their websites. After copying them into my project directory, I include them in the compiler settings by showing the folders as the include directories.

ST's Cube packages actually include a version of CMSIS, so you don't need to download it separately unless you want the latest version.

When creating the new project, STM32CubeIDE creates the linker script and startup files automatically. I'm not sure but IDE may skip creating some of them. But you can find them also in CMSIS and Cube packages.

Here are my example Blinky projects for STM32F103C8 in STM32CubeIDE, in C & C++:
https://bitbucket.org/tagli/blinky.cube/src/master/
https://bitbucket.org/tagli/blinkypp.cube/src/master/

Some of the header files in these example projects aren't necessary as they are related with other devices. But I didn't bother cleaning them. You will probably need to change the GPIO settings, because they are somewhat unique to old F1 series.
Gokce Taglioglu
 
The following users thanked this post: Sudo_apt-get_install_yum

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 14727
  • Country: de
Re: Migrating from AVR to STM32
« Reply #8 on: January 28, 2021, 05:17:48 pm »
One can use cubeMX and the graphical environment to create code for the initialization and can still decide of one wants to than use HAL, the less documented LL libs or direct register access. One can add the code directly to the main.c  file or use include to have moast of your own code in deparate files.

The register naming is a little different from the µC documentation. If in doubt look in the CMSIS include files for the register and constant names.
When using HAL one ideally does no longer needs the direct register access, but there are quite a few routines and constants for the settings one essentially has to look up everytime.
 
The following users thanked this post: newbrain

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 15244
  • Country: fr
Re: Migrating from AVR to STM32
« Reply #9 on: January 28, 2021, 06:34:35 pm »
For STM32, an alternative to the full HAL that is less bloated is the LL library. Lower level, but still makes portability to other STM32 MCUs easier.
 
The following users thanked this post: Jeroen3

Offline techman-001

  • Frequent Contributor
  • **
  • !
  • Posts: 748
  • Country: au
  • Electronics technician for the last 50 years
    • Mecrisp Stellaris Unofficial UserDoc
Re: Migrating from AVR to STM32
« Reply #10 on: January 30, 2021, 05:02:26 am »
Hi folks!

Like the title says, I’m moving away from AVR microcontroller series to the STM32 family.

I’m doing this because the STM32XX provides better performance, power use, cost and peripheral support over the old 8-bit AVR family.
I also see it as a big bonus, understanding the more modern processor cores.

I’m quite comfortable with the low level AVR things, written a lot of code in ASM and C/C++ but I’ve never used ASF. I always felt it to be unnecessary and add too much overhead for most things you could do on an 8-bit MCU.

I made a breakout board for the STM32L010K4 and have programmed it through STM32Cube-IDE and got a "blink" program up and running. The blink code i wrote was configured through CubeMX and uses HAL, their alternative to ASF.

The code uses 80.5% RAM(1.6 of 2K) and 54.5% FLASH(8.7 of 16K) and it makes me angry, so much waste. :'(
Is it normal to have this much memory overhead?

I’m used to configuring registers/ peripherals myself and seeing 32K FLASH as infinite storage and 2K RAM as more than enough.
Have some I/O input, use the T/C, sample something with the ADC and send it somewhere over a protocol.
This would result in a few percent of what this blink sketch is using.

Im aware that the STM32L010K4 (cortex M0+) is more complicated and requires more configuration but this is crazy.
Everyone on the web seems to use HAL. I would be more than happy to configure peripherals myself, maybe use HAL for more complicated things but I’m having a hard time starting out.

Does anybody have good appnotes, books or blogs with getting started with STM32 without the bloated abstraction layer.

How about a bootable blinky binary that  is only 76 bytes ?

Code: [Select]
@ blink.s
@ Assembly language Blinky example for stm32f051 mcu
@ Board: https://mecrisp-stellaris-folkdoc.sourceforge.io/stm32-boards.html?highlight=green%20pill#why-not-make-your-own-green-pill
@ led: PB-8 pin 32
@ Copyright 2020 <terry@tjporter.com.au> Released under BSD License, see COPYING.TXT

.cpu cortex-m0        @ Tell the assembler what model of Cortex-M this is for
.thumb        @ Cortex micros only understand thumb(1) code 
.include "gpio-equates.s"        @ GPIO action labels
.include "bitposn-equates.s"        @ A list of ".equ  BIT0, 0x00000001", " etc
.include "STM32F0xx-tp1.svd.equates.s" @ Every register and bitfield equate from Svd2Forth
.syntax unified        @ Use newer style instructions
.global main        @ Makes the symbol visible to ld
Vector_Table: .word     0x20000000   @ Atack pointer value when stack is empty 0x20000000
ResetVector:    .word     main + 1     @ Reset Handler
.text @ what follows is code      

main: ldr r1, = RCC_AHBENR        @ AHB Peripheral Clock enable register @ 0x40021014
ldr r2, = RCC_AHBENR_IOPBEN   @ I/O port B clock enable = 0x40000
str r2, [r1]

ldr r1, = GPIOB_MODER @ GPIOB port mode register @ 0x48000400
ldr r3, = OUTPUT << GPIOB_MODER_MODER8 @ Set PB-8 bit as output = 0x10000
str r3, [r1]

ldr r1, = GPIOB_BSRR        @ GPIOB bit set/reset register @ 0x48000418
ldr r4, = GPIOB_BSRR_BS8      @ PB-8 on = 0x100
ldr r5, = GPIOB_BSRR_BR8      @ PB-8 off = 0x1000000
   
led_on:        
  str r4, [r1]
  bl delay

led_off:
  str r5, [r1]
  bl delay
b led_on        

delay: lsls r0,r4, #12   @ r4 = 0x100 shifted left 12 times = 0x100000. Delay about 1 second @ 8MHz clock
loop: subs r0,r0,#1
bne loop
end: bx lr    @ return to caller

   @ binary = 76 bytes


I agree with Siwastaja and others who said words to this effect, "Skip all the HAL and other crap. You'll thank yourself later for being able to actually do projects instead of debugging broken and limited libraries."

They may not have been thinking of Assembly Language at the time, but really, how hard does the above source look ?

My code is very pedestrian (I'm an electronics tech), I always go for readability and maintainability over everything else, but I have a Blinky written by Matthias Koch that is only 28 bytes on the same STM32F051 MCU.
 

Offline Sudo_apt-get_install_yumTopic starter

  • Regular Contributor
  • *
  • Posts: 165
  • Country: se
Re: Migrating from AVR to STM32
« Reply #11 on: January 30, 2021, 03:06:45 pm »
Nice seeing a small binary for the STM32, not a common sight when scouring the internet!

Like i said in the post, id gladly skip HAL. I never liked ASF and feel the same with HAL from my limited experience with STM32 MCU's.
I’m comfortable with writing assembly for AVR, had a few collage courses in it and have written a few projects in it.
I’m not really interested in writing assembly for ARM processors, il probably continue writing ASM for simpler AVR projects but keep to C or C++ for the STM32’s.

I’m determined to learn the actual underlying architecture but I’m having a hard time getting started. There is a lot of recourses on the internet but most talk about HAL.

Can you recommend any books, blogs or papers?
How do I set up the environment in a proper way, without using the configuration tools?
 

Offline Siwastaja

  • Super Contributor
  • ***
  • Posts: 8748
  • Country: fi
Re: Migrating from AVR to STM32
« Reply #12 on: January 30, 2021, 03:24:45 pm »
There is not much "environment" to set up, that's the whole point, IMHO.

Get https://launchpad.net/gcc-arm-embedded

The hardest part, IMHO, is to come up with a linker script. On avr-gcc, that is autogenerated / included from somewhere behind your back. Try to google STM32 linker script, I'm sure you'll find examples.

Startup code is easier to understand, basically just get the addresses from the linker script and run simple loops to zero .bss and copy .data. I'm sure examples are available.

Then just start writing code, including the ARM/STM32 headers only so you have #defines and struct typedefs for accessing the peripheral registers with the names given in the reference manual.

I really haven't seen a proper tutorial. I've been thinking about writing one but have better things to do... Finding out everything by trial and error is time consuming, the bright side is it forces you to learn. When I come from AVR, I used a helpful tutorial made by some Swedish Ubuntu fan but can't find that from the 'net anymore. In any case, it had a few catastrophic small mistakes that made me lose a lot of time. Namely the stack pointer was initialized incorrectly, preventing a few opcodes and most library functions from working yet worked OK much of the time.

Using bare gnu tools and understanding the computer science basics has the significant advantage that it stays the same for decades to come, and also between different manufacturers!
« Last Edit: January 30, 2021, 03:26:48 pm by Siwastaja »
 

Offline Jeroen3

  • Super Contributor
  • ***
  • Posts: 4167
  • Country: nl
  • Embedded Engineer
    • jeroen3.nl
Re: Migrating from AVR to STM32
« Reply #13 on: January 30, 2021, 03:25:31 pm »
The code uses 80.5% RAM(1.6 of 2K) and 54.5% FLASH(8.7 of 16K) and it makes me angry, so much waste. :'(
Is it normal to have this much memory overhead?
How long did this blinky take you?

[...]

How about a bootable blinky binary that  is only 76 bytes ?

Code: [Select]
...
..
How long did that take you?

The code generation and hal can be quite useful. Not for a blinky, but other things. Being able to setup via a gui is nice.
Not having to worry about inter-chip differences, just spin up a new project, link to the application code that is somewhere else.
Eg: setup ADC with DMA and just call your data_frame_input(struct *, size_t samples) without worrying about any details in code, only gui, is very fast!
The HAL also doesn't block you from going to registers yourself. For example, I use TIM3 in a library, so just tick "enable" in the config and call the lib not the HAL_TIMx....

Learn to respect the abstraction it offers. It's useful. And it also tells your when you're doing it wrong with the asserts.
 

Offline Siwastaja

  • Super Contributor
  • ***
  • Posts: 8748
  • Country: fi
Re: Migrating from AVR to STM32
« Reply #14 on: January 30, 2021, 03:31:14 pm »
Abstraction is also a limitation.

Someone's else abstraction needs to be put under scrutiny; is it the right tool for the job?

Writing your own abstraction layer has the advantage of being very lean because you know what you need.

I think I have never used an ADC in such a way that I could just call a function to initialize a fixed-length transaction to a buffer, not even once. No; I may sync it to the timers, I generate interrupts, I utilize injected measurements, and so on.

If I want a computer, I use a computer, like a Raspberry Pi. Then I can run linux and have a standardized and fairly consistent and capable POSIX interface to high-level functionality.

But when I design in a microcontroller, I tend to do timing-critical control, something the software can't do alone, and something where the peripherals tend to be used beyond the "trivial" example use case. Most of my applications require at least some HW feature of some peripheral that simply can't be accessed or used through the STM32 HAL library (at least not easily / in a portable manner). Simple as that. I either don't use HAL at all, or create a strange mix of code where it is used in some places, and not used somewhere else, and where I need to write code twice (once with HAL, then without when I hit the limitations), or I could of course give up and not do the project at all.

Often the peripheral access itself is some 2-3 lines of code. I may abstract it behind my own function for easy maintainability or portability.

But I'm sure HAL is fine when you are mostly doing simple applications and are ready to call in an expert when you hit the wall.

And quite frankly, it tends to go in such a way that when others are starting the discussion about the merits of all the fine layers of abstraction (including STM32 HAL, code autogeneration, RTOS...) and how they should be used, I have already finished the project without. I have my own 71 lines-of-code long helper header to abstract the most widely used STM32 peripheral operations such as playing around with GPIO and DMA, makes code more readable.

When did it become a matter of pride to reveal you prefer a point-and-click interface instead of writing code? I mean, that's fine if it floats your boat, but really, if you want to work on actual projects and get some work done you should be confident writing code. If that feels difficult in comparison to point&click, you are writing the code wrong. And I don't blame you, many of the STM32 examples around the 'net need like 20 lines of code to toggle an IO. Really it should be an oneliner. If you struggle with code, my hint is, look for better ways to write that code (you can stay in C language, trust me, it's not the problem) instead of replacing it with a GUI autogenerating a horrible piece of spaghetti mess.
« Last Edit: January 30, 2021, 03:50:32 pm by Siwastaja »
 
The following users thanked this post: Sudo_apt-get_install_yum

Offline techman-001

  • Frequent Contributor
  • **
  • !
  • Posts: 748
  • Country: au
  • Electronics technician for the last 50 years
    • Mecrisp Stellaris Unofficial UserDoc
Re: Migrating from AVR to STM32
« Reply #15 on: January 30, 2021, 11:05:29 pm »
Nice seeing a small binary for the STM32, not a common sight when scouring the internet!

Like i said in the post, id gladly skip HAL. I never liked ASF and feel the same with HAL from my limited experience with STM32 MCU's.
I’m comfortable with writing assembly for AVR, had a few collage courses in it and have written a few projects in it.
I’m not really interested in writing assembly for ARM processors, il probably continue writing ASM for simpler AVR projects but keep to C or C++ for the STM32’s.

I’m determined to learn the actual underlying architecture but I’m having a hard time getting started. There is a lot of recourses on the internet but most talk about HAL.

Can you recommend any books, blogs or papers?
How do I set up the environment in a proper way, without using the configuration tools?

I recommend the Reference Manual "RM0451" and suggest that you read the 774 pages. Luckily for you this is a among the simpler STM32's, but not the simplest due to all the low power features of the STM32L010K4. Then I recommend that you make a project using one peripheral, then when you have a working knowledge of that peripheral, move on to the next.

As you plan to use C, look at the end of "RM0451" where you will find "Appendix A Code examples" for most peripherals.

https://www.st.com/resource/en/reference_manual/dm00443854-ultralowpower-stm32l0x0-advanced-armbased-32bit-mcus-stmicroelectronics.pdf

If you do this, then you will have the kind of knowledge to actually use the chip to it's capabilities.

Environment
------------------
The environment set up is entirely dependent on the programming language you plan to use and they all have their own peculiarities.

If you roll your own, you'll be swimming in linker scripts as Siwastaja said, and he's not kidding. Read the GNU Linker manual and you'll appreciate that this is a 16 headed monster.

You'll need a 'library' of some sort, perhaps https://libopencm3.org/ or the CMSIS library in the Keil packs ...

Happy building!
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4298
  • Country: us
Re: Migrating from AVR to STM32
« Reply #16 on: January 31, 2021, 01:39:40 am »
A few years ago, there was a big discussion here on "minimal ARM programming."
Some of the results, and discussion, and pointers to the discussion here, can be found at https://github.com/WestfW/Minimal-ARM

(programming an ARM in assembler is unpleasant, mostly because the peripheral definitions are not provided in a form that supports assembly.  It's also quite unnecessary.)

Additional "smaller than ASF" ARM experiments (for Atmel SAMD10 here:  https://github.com/WestfW/SAMD10-experiments )


I agree with the recommendations to ignore HAL/ASF/etc packages.  They'll typically take something like 1k of code just to initialize the clock :-(  (Note that for trivial programs, you probably don't NEED to "initialize the clock" at all.)
I keep hearing that newer replacements (Atmel Start, ST LL Library) are "better", but my initial experiences were so bad that I haven't looked.As for BlueSkull's recomendations FOR HAL...  You can do a better job writing abstracted and portable functions/macros on your own, for almost all common peripherals.

I keep getting facebook ads for a free https://stm32.embeddedexpert.io/stm32_ebook "Bare-Metal Embedded C Driver Cookbook", and eventually succumbed.  It's pretty sparse, but also useful, consisting of of cookbook-style short C programs with comments and references to the datasheet.  Their "toggle IO pin" example reads like:
Code: [Select]
/*1. Enable GPIOA clock */
/*2. Set PA5 to output mode */
/*3. Turn on bit */
/*4. Delay for some time*/
/*5. Turn off bit */
Which is nice, because it points out that important "enable clock" part, and provides the reference.
 
The following users thanked this post: Sudo_apt-get_install_yum

Offline techman-001

  • Frequent Contributor
  • **
  • !
  • Posts: 748
  • Country: au
  • Electronics technician for the last 50 years
    • Mecrisp Stellaris Unofficial UserDoc
Re: Migrating from AVR to STM32
« Reply #17 on: January 31, 2021, 03:54:47 am »
A few years ago, there was a big discussion here on "minimal ARM programming."
Some of the results, and discussion, and pointers to the discussion here, can be found at https://github.com/WestfW/Minimal-ARM

(programming an ARM in assembler is unpleasant, mostly because the peripheral definitions are not provided in a form that supports assembly.  It's also quite unnecessary.)

Additional "smaller than ASF" ARM experiments (for Atmel SAMD10 here:  https://github.com/WestfW/SAMD10-experiments )


I agree with the recommendations to ignore HAL/ASF/etc packages.  They'll typically take something like 1k of code just to initialize the clock :-(  (Note that for trivial programs, you probably don't NEED to "initialize the clock" at all.)
I keep hearing that newer replacements (Atmel Start, ST LL Library) are "better", but my initial experiences were so bad that I haven't looked.As for BlueSkull's recomendations FOR HAL...  You can do a better job writing abstracted and portable functions/macros on your own, for almost all common peripherals.

I keep getting facebook ads for a free https://stm32.embeddedexpert.io/stm32_ebook "Bare-Metal Embedded C Driver Cookbook", and eventually succumbed.  It's pretty sparse, but also useful, consisting of of cookbook-style short C programs with comments and references to the datasheet.  Their "toggle IO pin" example reads like:
Code: [Select]
/*1. Enable GPIOA clock */
/*2. Set PA5 to output mode */
/*3. Turn on bit */
/*4. Delay for some time*/
/*5. Turn off bit */
Which is nice, because it points out that important "enable clock" part, and provides the reference.


westfw, I'm devastated that you didn't read my code, does this look like the peripheral definitions are not supported, or not cmsis-svd compliant to you ?  :rant:

;-)

It's all automatic for me being transformed from the SVD. The hard work was the HEX in the comments which is only there as it's a teaching example.

Code: [Select]
        main: ldr r1, = RCC_AHBENR        @ AHB Peripheral Clock enable register @ 0x40021014
ldr r2, = RCC_AHBENR_IOPBEN   @ I/O port B clock enable = 0x40000
str r2, [r1]

ldr r1, = GPIOB_MODER @ GPIOB port mode register @ 0x48000400
ldr r3, = OUTPUT << GPIOB_MODER_MODER8 @ Set PB-8 bit as output = 0x10000
str r3, [r1]

ldr r1, = GPIOB_BSRR        @ GPIOB bit set/reset register @ 0x48000418
ldr r4, = GPIOB_BSRR_BS8      @ PB-8 on = 0x100
ldr r5, = GPIOB_BSRR_BR8      @ PB-8 off = 0x1000000

I also like their  "toggle IO pin" example as there is absolutely no reason to use C or any other programming language to explain a peripheral config.
« Last Edit: January 31, 2021, 05:34:14 am by techman-001 »
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4298
  • Country: us
Re: Migrating from AVR to STM32
« Reply #18 on: January 31, 2021, 11:01:23 am »
Quote
Code: [Select]
ldr r1, = GPIOB_BSRR        @ GPIOB bit set/reset register @ 0x48000418
ldr r3, = OUTPUT << GPIOB_MODER_MODER8 @ Set PB-8 bit as output = 0x10000
str r3, [r1]
does this look like the peripheral definitions are not supported
Yes.
Having a separate symbol for every register in the device is horribly bogus.
I want it to have offsets for fields and generic pointers; definitions which (AFAIK) are only provided hidden in C structure definitions (I suppose that they COULD be decoded from the .svd files...)

Code: [Select]
ldr r1, = GPIOB
ldr r3, = OUTPUT << GPIOB_MODER_MODER8 @ Set PB-8 bit as output = 0x10000
str r3, [r1, #BSRR]

 

Offline Sudo_apt-get_install_yumTopic starter

  • Regular Contributor
  • *
  • Posts: 165
  • Country: se
Re: Migrating from AVR to STM32
« Reply #19 on: January 31, 2021, 12:59:24 pm »
I just wanted to say thanks to all of you who wrote extensive replies. I’ve been reading through them and tried to get a bare metal version of my previous code working. So, my apologies for the slow replies!

I’ve setup a blank C/C++ project in STM32CubeIDE and used CMSIS, I’m not sure I actually need it since I’m directly writing to the registers of the processor. My understanding is that CMSIS is a small abstraction layer to keep some sort of standardization between different ARM manufacturers.

I’m able to build the project and get no errors or warnings but I’m not able to actually run the program. Se the image below for the error, I don’t really understand the error so any input would be appreciated!

The "Bare metal STM32 cookbook" was very helpful, it reminds me a lot of regular AVR programming and what steps i need to take in order to enable a peripheral and so on, so huge thanks!

Error when running.


Code


Memory


Project setup
 

Offline Yansi

  • Super Contributor
  • ***
  • Posts: 3893
  • Country: 00
  • STM32, STM8, AVR, 8051
Re: Migrating from AVR to STM32
« Reply #20 on: January 31, 2021, 01:04:52 pm »
Do not code directly on registers for 32-bit MCUs. This is generally not a good idea unless you have special needs (like you are making billions of copies and need to save every fraction of a penny, or like you need aerospace grade reliability).

Use the HAL, you will thank yourself later when you need to migrate from chip A to chip B of the same make (hence similar HAL naming convention).

And yes, they are a bit bloated, but your blinky consuming 8.7KB is absurd. Check if anywhere in your code it uses printf.

I just did a test on GD32F350 using arm-none-eabi-gcc, the blinky with HAL is 1.4KB, with printf is 9.1KB, with printf and float somewhere else (printf doesn't support float) is 10.5KB, with printf supporting float I didn't test, but I recalled it would considerably bloat up the size due to newlib's implementation on full featured printf.

As for RAM, since you only have 2KB, how much did you allocate for stack? Even if your HAL and user code use nothing, there could be easily a KB or so allocated to stack.

Its absurd use of resources is exactly why using the HAL shit should be avoided like a covid.

Especially with ultrasmall ST32 MCUs like the STM32L011, it makes absolutely 0.00 sense to use HAL on that. Use the registers, otherwise you won't fit anything inside, past the HAL initialization.

Same goes with for example STM32F042. Nice 20 pin ARM chip with a USB peripheral. Use the Cub/HAL with USB on that and you have barely any FLASH left to do the useful stuff.
 

Offline Yansi

  • Super Contributor
  • ***
  • Posts: 3893
  • Country: 00
  • STM32, STM8, AVR, 8051
Re: Migrating from AVR to STM32
« Reply #21 on: January 31, 2021, 01:09:23 pm »
Code


Do NOT use the magic numbers in your code. There is metric shit ton of human readable aliases for all that stuff.

instead of

Quote
RCC->IOPENR |= (1<<7) | (1<<1);

use for example:

Code: [Select]
RCC->IOPENR |= RCC_IOPENR_IOPBEN | RCC_IOPENR_IOPHEN ;
And btw, use of the double pipe || in your code is an error!
 

Offline Sudo_apt-get_install_yumTopic starter

  • Regular Contributor
  • *
  • Posts: 165
  • Country: se
Re: Migrating from AVR to STM32
« Reply #22 on: January 31, 2021, 01:22:06 pm »
You are completely right, should have used "single pipe" in this case!

Regarding the magic numbers, I hate it as much as anyone else. I could not find the correct alias names so just used the magic numbers for testing.
 

Offline Yansi

  • Super Contributor
  • ***
  • Posts: 3893
  • Country: 00
  • STM32, STM8, AVR, 8051
Re: Migrating from AVR to STM32
« Reply #23 on: January 31, 2021, 01:36:31 pm »
The aliases are really simple and consistent. It is a PERIPHERAL_REGISTER_BIT notation. Gives the exact bit set to 1.
There are also a bit position macros (add _Pos at the end) returning the bit number (0..31) and a bit mask macros (add _Msk at the end) when applicable.
 

Offline Siwastaja

  • Super Contributor
  • ***
  • Posts: 8748
  • Country: fi
Re: Migrating from AVR to STM32
« Reply #24 on: January 31, 2021, 01:51:34 pm »
I don't like copy-pasting or manually rewriting, or reading for that matter, things like

PERIPHERAL_X_CONFIG_REG = PERIPHERAL_X_CONFIG_REG_ASDFG | PERIPHERAL_X_CONFIG_REG_QWER | PERIPHERAL_X_CONFIG_REG_XYZ;

even if it's simple and logical.

First, it's a lot to read and write.

Second, because the SNR is so poor, a small one-letter mistake easily sneaks in and is hard to find.

Finally, it provides absolutely no documentation about what ASDFG, QWER or XYZ mean or do, so they are not any different from magic numbers. They are hard-to-understand abbreviations from the reference manual. You need to either look them up, or remember them by heart.

So the only way to write / read this is to open the relevant manual page describing those bits. Which is what you, realistically speaking, need to do anyway! So basically, at some point, I accepted this, and stopped playing those "let's pretend this has no magic numbers and is maintainable" games, removing one extra layer of nomenclature.

My assumption hence is, anyone who questions that line of the code (someone else, or me later), can't do that without opening the refman description anyway, they need to see the longer description than some ARPE to understand what a config bit actually does. Now, the reference manual documentation refers to the bits using bit numbers, directly, so why not use them.

Hence, ASDFG and 5 are similarly magical. Both require lookup. I prefer 5 to get rid of one layer of excess abstraction (that does not add anything). I replace the tedious WRITE_THIS_PART_TEN_TIMES_WITHOUT_ADDING_INFORMATION by adding a /* in-line comment */ describing what the configuration bit actually does.

An example:
Code: [Select]
TIM2->CR1 = 1UL<<3 /* one pulse mode */ | 1UL<<2 /*only overflow and underflow generate update interrupt*/;
is IMHO more descriptive than
Code: [Select]
TIM2->CR1 = TIM_CR1_OPM | TIM_CR1_URS;
But I won't be pushing this notation. Just saying there are options to do it differently.
« Last Edit: January 31, 2021, 01:54:50 pm by Siwastaja »
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf