Skip to content
This repository was archived by the owner on Mar 7, 2026. It is now read-only.

AT32F4 flash handling #1542

@ALTracer

Description

@ALTracer

Summary

How should all these different parts be handled?

Description

#1150 actually #1151 introduced detection of ARTERY AT32F403A, F407 (and F407A) and F415 parts by listing their DBGMCU_IDCODE values, or part_id as referred in sources in src/target/stm32f1.c. I agree with the at32f41_detect() routine which assigns different flash sizes to F415 parts, but disagree with at32f40_detect() which makes them all appear as 256 KiB parts.

In the PR discussion and in the code comments there are concerns about "external memory" and "default layout".

  1. From my understanding of RM_AT32F403A_407_EN reference manual the MCUs have a "SPIM" external Quad I/O-like NOR Flash memory controller which can map into 0x0840_0000 base and perform transparent encryption. However, I'm now interested in internal flash only. 256 & 512 KiB flash parts have it all in a single bank in 2048-byte pages. 1 MiB parts employ two banks, the split address is at 0x0808_0000 (+512 KiB) and the second bank has individual FLASH_CTRL2 etc. registers.
  2. ZW & NZW split is a characteristic feature of most AT32F4 MCUs: first 128 KiB of Flash are always shadowed by 128 KiB of on-chip SRAM which cannot be reclaimed. Upwards from that, [by default] another (next) 128 KiB of Flash are shadowed/cached by 128 KiB of SRAM and this margin can be moved lower (or higher if there's more SRAM, like on F435). On F403A/F407, 96 leftover KiB of SRAM are by default available as work SRAM (but 96+128=224 max). This is controlled by option bytes. NZW flash runs at 72 MHz, for 240-288 MHz cores this incurs 4 wait states without caching (on jumps).
  • Is it possible to use all of 512..1024 KiB flash on AT32F403A, particularly on WeActStudio.BlackPill AT32F403ACGU7, by registering bigger sizes / page counts in stm32f1_add_flash()?
  • AT32F435/7 parts with 256 KiB are single-bank with 2048-byte pages, too; but parts with 1024 KiB flash are dual-bank, split equally, at 0x0808_0000 address (+512 KiB). These targets can be treated flash-wise like the F403A.
  • But AT32F435/7 parts with 4096-byte pages (also 448 KiB, single-bank -- simple, not considered here) of 4032 KiB dual-bank flash are split at 0x0820_0000 address (+2048 KiB) which is unusual.

stm32f1.c has branches on 0x430U XL-density in mass_erase, flash_erase & flash_write routines:

/* If there's anything to write left over and we're on a part with a second bank, write to bank 2 */
const size_t remainder = len - offset;
if (target->part_id == 0x430U && remainder) {

but it relies on macros for +0x40 control registers offset (which is suitable) and +512 KiB second bank offset
#define FLASH_BANK1_OFFSET 0x00U
#define FLASH_BANK2_OFFSET 0x40U
#define FLASH_BANK_SPLIT 0x08080000U

There are other targets already supporting dual-bank MCUs. Like stm32h7.c has a simple dual-bank support logic, or stm32f4.c has a rather convoluted one.
I am writing #1540 and I need recommendations on how to handle this situation. Maybe all of AT32F4 should be split out as a separate target, or a subset of functions (but stm32f1 flash API is not public), or just a set of distinct write/erase/mass_erase routines living in stm32f1.c will be enough (using its own macros for register manipulations)?

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugConfirmed bugHwIssue MitigationSolving or mitigating a Hardware issue in Software

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions