Skip to content

stm32: Add support for all STM32L43x/L44x/L45x/L462/L47x/L486/L4A6. #16523

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

chrismas9
Copy link
Contributor

@chrismas9 chrismas9 commented Jan 4, 2025

Summary

This adds support for all 80 MHz STM32L4 parts.
There are no code changes, only preprocessor directives, af, ld and mk file changes.
L431 and L433 are higher pincount versions of L432 with more peripherals.
All other variants are identical to existing parts except for USB, LCD and crypto.
The 256 kiB parts are short on Flash for File System and the FS size needs tuning depending on
enabled features (eg USB requires 14 KiB). The stm32l43x*.ld linker scripts simplify FS_SIZE tuning.

Testing

The L431, L432, L433, L442 and L443 have been tested on NUCLEO boards with and without USB. Only REPL, USB and FS have been tested. Other peripherals are the same as similar parts.
All parts have been compiled error free using modified board files from existing ports.
After these tests I consider the changes low risk.
I have been using many of these MCUs, including L433, commercially for 4 years based on #7123

Copy link

github-actions bot commented Jan 4, 2025

Code size report:

   bare-arm:    +0 +0.000% 
minimal x86:    +0 +0.000% 
   unix x64:    +0 +0.000% standard
      stm32:    +0 +0.000% PYBV10
     mimxrt:    +0 +0.000% TEENSY40
        rp2:    +0 +0.000% RPI_PICO_W
       samd:    +0 +0.000% ADAFRUIT_ITSYBITSY_M4_EXPRESS
  qemu rv32:    +0 +0.000% VIRT_RV32

Adds all STM32L4 80 MHz parts with at least 256 KiB Flash,
  including non-USB and crypto parts.
There are only preprocessor directive changes, no code changes.

Signed-off-by: Chris Mason <c.mason@inchipdesign.com.au>
@chrismas9 chrismas9 force-pushed the STM32_L43X_L45X_L47X_L49X branch from 2376c39 to a0943ed Compare January 4, 2025 10:27
stm32/boards/stm32l432_af.csv Fix errors and omission.
stm32/boards/stm32l452_af.csv Fix omission.
stm32/boards/stm32l433_af.csv Add.

Signed-off-by: Chris Mason <c.mason@inchipdesign.com.au>
stm32/boards/stm32l43x_12kFS.ld
stm32/boards/stm32l43x_26kFS.ld

Replace stm32l432.ld with tunable versions for all stm32l43x parts.
The LENGTH(FLASH_FS) needs to be tuned for each board port to squeeze in
  drivers (eg USB, CANbus).
These changes allow editing one number (FS_SIZE) and all regions are
  calculated automatically.
stm32l43x_26kFS.ld provides a 26 KiB file system for minimal ports,
  eg NUCLEO_L432KC.
stm32l43x_12kFS.ld provides a 12 KiB file system for ports with USB.

stm32/boards/NUCLEO_L432KC/mpconfigboard.mk Use new stm32l43x_26kFS.ld.

Signed-off-by: Chris Mason <c.mason@inchipdesign.com.au>
@chrismas9 chrismas9 force-pushed the STM32_L43X_L45X_L47X_L49X branch from a0943ed to 1665595 Compare January 4, 2025 10:37
@chrismas9
Copy link
Contributor Author

This is the first of three PRs to replace #7123
The next will add support for 120 MHz STM32L4 parts - L4P, L4Q, L4R and L4S.
The last one will add ST Microelectronics development board support for some of the new parts.

@chrismas9 chrismas9 changed the title stm32/boards/stm32l43*.ld Add tunable FS sizes for 256 kiB parts. stm32: Add support for all STM32L43x/L44x/L45x/L462/L47x/L486/L4A6. Jan 4, 2025
@projectgus projectgus self-requested a review January 6, 2025 23:55
Copy link
Contributor

@projectgus projectgus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for submitting this PR, @chrismas9!

I have a few comments, all about trying to avoid the "rightward creep" of needing to name the many subtly different variants of STM32L4! Sounds like you've used the STM32L4 family a lot, and I haven't, so please let me know if you think any of the proposed changes are too risky. (It's probably worth also waiting to see what @dpgeorge thinks about going in that direction before we commit to it.)

FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 230K /* sectors 0-114 */
FLASH_FS (r) : ORIGIN = 0x08039800, LENGTH = 26K /* sectors 115-127 */
ALL_FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 256K
FS_SIZE (r) : ORIGIN = 0, LENGTH = 12K /* Adjust the File System size here */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this trick... it'd be good to use it consistently across all the stm32 linker scripts, but there are 49 more of them...

I guess it's fine to have it just for these two, although @dpgeorge might have a different opinion.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can just use variables in ORIGIN and LENGTH? See how mimxrt does it, eg ports/mimxrt/boards/common.ld. @robert-hh has done a good job making that port quite configurable with the linker scripts.

#elif defined(STM32L0) || \
defined(STM32L432xx) || defined(STM32L442xx) || \
defined(STM32L433xx) || defined(STM32L443xx) || \
defined(STM32L452xx) || defined(STM32L462xx)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this one be defined(STM32L4)? If MICROPY_HW_USB_FS is unset, it won't include any code.

@@ -93,7 +93,8 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) {
const uint32_t otg_alt = GPIO_AF10_OTG1_FS;
#elif defined(STM32L0)
const uint32_t otg_alt = GPIO_AF0_USB;
#elif defined(STM32L432xx) || defined(STM32L452xx)
#elif defined(STM32L432xx) || defined(STM32L442xx) || defined(STM32L433xx) || defined(STM32L443xx) || \
defined(STM32L452xx) || defined(STM32L462xx)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confused about why we set otg_alt here anyway, if these are parts that only have USB device support?

But that's preexisting... How about using defined(STM32L4) here and same at line 160? We can always split it up again if a new STM32L4 board is added that behaves differently.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The STM32 HAL uses GPIO_AF0_USB, GPIO_AF10_USB_FS, GPIO_AF10_USB, GPIO_AF10_OTG_FS, GPIO_AF10_OTG1_FS, etc depending on the capabilities of each chip and which AF the USB is allocated to. The L432/L452 names differ to all other L4s because they don't support OTG. I think these need to stay as they are.

As for using otg_alt the pyboard hardware supports OTG, it has an OTG connector and provision for a power switch. I'm not sure what software support there is.

@@ -133,7 +133,7 @@ static void dac_deinit(uint32_t dac_channel) {

void dac_deinit_all(void) {
dac_deinit(DAC_CHANNEL_1);
#if !defined(STM32L452xx)
#if !defined(STM32L451xx) && !defined(STM32L452xx) && !defined(STM32L462xx)
Copy link
Contributor

@projectgus projectgus Jan 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think all of the clauses in this file can be #if !defined(DAC_CHANNEL2_SUPPORT) (another CMSIS header define).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, looking at CMSIS some more this macro might be inconsistently defined. 🙄

I think a safe (but ugly) variant will be #if !defined(STM32L4) || !defined(DAC_CHANNEL2_SUPPORT))

#if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32L0) || defined(STM32L1) || defined(STM32L432xx) || defined(STM32L452xx) || defined(STM32WB)
#if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32L0) || defined(STM32L1) || \
defined(STM32L432xx) || defined(STM32L442xx) || defined(STM32L433xx) || defined(STM32L443xx) || \
defined(STM32L452xx) || defined(STM32L462xx) || defined(STM32WB)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit of a deviation from how we've done this until now, but I think we can replace this increasingly long line of #if clauses with

#if defined(USB_OTG_FS)

This peripheral address is defined in the CMSIS headers for all the chips which contain an OTG peripheral, as far as I can tell...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The L332 and L452 families use USB_FS, so using USB_FS and USB_OTG_FS I can greatly simplify this.

@@ -90,7 +90,8 @@ void mp_hal_ticks_cpu_enable(void) {
#endif

void mp_hal_gpio_clock_enable(GPIO_TypeDef *gpio) {
#if defined(STM32L476xx) || defined(STM32L496xx)
#if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L486xx) || \
defined(STM32L496xx) || defined(STM32L4A6xx)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are too many datasheets to read them all, but it seems like all of the STM32L4s that have a GPIOG also have a VDDIO2:

❯ rg -c --include-zero "define PWR_CR2_IOSV" | sort
stm32l412xx.h:0
stm32l422xx.h:0
stm32l431xx.h:0
stm32l432xx.h:0
stm32l433xx.h:0
stm32l442xx.h:0
stm32l443xx.h:0
stm32l451xx.h:0
stm32l452xx.h:0
stm32l462xx.h:0
stm32l471xx.h:3
stm32l475xx.h:3
stm32l476xx.h:3
stm32l485xx.h:3
stm32l486xx.h:3
stm32l496xx.h:3
stm32l4a6xx.h:3
stm32l4p5xx.h:3
stm32l4q5xx.h:3
stm32l4r5xx.h:3
stm32l4r7xx.h:3
stm32l4r9xx.h:3
stm32l4s5xx.h:3
stm32l4s7xx.h:3
stm32l4s9xx.h:3
stm32l4xx.h:0
system_stm32l4xx.h:0

❯ rg -c --include-zero "define GPIOG" | sort
stm32l412xx.h:0
stm32l422xx.h:0
stm32l431xx.h:0
stm32l432xx.h:0
stm32l433xx.h:0
stm32l442xx.h:0
stm32l443xx.h:0
stm32l451xx.h:0
stm32l452xx.h:0
stm32l462xx.h:0
stm32l471xx.h:2
stm32l475xx.h:2
stm32l476xx.h:2
stm32l485xx.h:2
stm32l486xx.h:2
stm32l496xx.h:2
stm32l4a6xx.h:2
stm32l4p5xx.h:2
stm32l4q5xx.h:2
stm32l4r5xx.h:2
stm32l4r7xx.h:2
stm32l4r9xx.h:2
stm32l4s5xx.h:2
stm32l4s7xx.h:2
stm32l4s9xx.h:2
stm32l4xx.h:0
system_stm32l4xx.h:0

... Do you think it's safe to make this #if defined(STM32L4) && defined(GPIOG) ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have checked one datasheet from each family (L432/33/5/7/9/P/R) and this look safe. Only L47x and above have GPIOG and they also have VDDIO2

defined(STM32L476xx) || defined(STM32L496xx) || \
defined(STM32L462xx) || defined(STM32L471xx) || \
defined(STM32L475xx) || defined(STM32L476xx) || \
defined(STM32L486xx) || defined(STM32L496xx) || \
defined(STM32L4A6xx) || \
Copy link
Contributor

@projectgus projectgus Jan 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reference manual confirms this is true for all STM32L4s, so suggest collapsing it to be defined(STM32L4)

image

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's what I did in #7123

@chrismas9
Copy link
Contributor Author

@projectgus Thanks for the review and helpful comments.

I agree using STM32L4 in many places would simplify things and improve readability. I did that in my previous PR in some places. I looked for precedent from other commits and thought listing all parts was preferred . However with so many parts it is messy. When I first started I thought there might be newer parts coming with different features, but now I think that is unlikely. ST have moved on with newer families like G4 and I think L4 is stable. I will review your suggestions when I get a chance.

I also wanted to be careful not to touch anything that affects other families due to the amount of testing, especially for families I am not familiar with and don't have dev boards for. I will still consider your suggestions.

I'm happy to update all the linker scripts for parts with 2K sectors. It's a bit more complicated for parts with non uniform sectors sizes. I have another PR coming for them. It reduces the FS cache to 48K, moves the stack into CCRAM, increases the heap size and the FS by using more sectors. I would do the non uniform linker scripts in that PR. I have been using this for years, but it needs a bit of cleanup and a big rebase first.

@projectgus
Copy link
Contributor

Sounds good. Feel free to ignore any/all of the suggestions which might impact other chips, I will make a note to take a look at them later on. (I think I can write a script that builds all of the stm32 boards and verifies no differences in the binaries, and then get stuck in cleaning up macros without fear...)

I'm happy to update all the linker scripts for parts with 2K sectors. It's a bit more complicated for parts with non uniform sectors sizes. I have another PR coming for them. It reduces the FS cache to 48K, moves the stack into CCRAM, increases the heap size and the FS by using more sectors. I would do the non uniform linker scripts in that PR. I have been using this for years, but it needs a bit of cleanup and a big rebase first.

That sounds great to me, if you're up for it!

@projectgus
Copy link
Contributor

projectgus commented Jan 9, 2025

thought listing all parts was preferred

On this, @dpgeorge may disagree, but I think what's happened is most source files have gradually grown from only a few chips supported to a lot of chips now, without it necessarily being the intention to list them all out.

We've had good luck cleaning up the esp32 port to use capability-based macros rather than listing every chip, but that's an order of magnitude fewer chips with a lot less differences so I'm not sure how viable it will turn out to be on stm32.

(To be clear, this is not a problem I'm suggesting you should tackle in this PR - except for maybe the few places where the lines were growing by a large proportion.)

@chrismas9
Copy link
Contributor Author

Another possible way to simplify the long list of parts would be to define family sub groups in mpconfigboard_common.h, eg:

#if defined(STM32L431xx) || \
    defined(STM32L432xx) || defined(STM32L433xx) || \
    defined(STM32L442xx) || defined(STM32L443xx)
#define STM32L43
#endif

There are only six sub groups of STM32L4 compared with over twenty individual parts. The main differences between parts in a sub group are USB, LCD and crypto support.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy