Skip to content

stm32: add GTZC and SAU drivers for TrustZone-capable families - #5915

Closed
leftger wants to merge 2 commits into
embassy-rs:mainfrom
leftger:feat/gtzc-driver
Closed

leftger wants to merge 2 commits into
embassy-rs:mainfrom
leftger:feat/gtzc-driver

Conversation

@leftger

@leftger leftger commented Apr 21, 2026

Copy link
Copy Markdown
Contributor

Adds initial support for the Global TrustZone Controller (GTZC) and Security Attribution Unit (SAU) on STM32 families with TrustZone:

  • WBA (gtzc_wba): TZSC + MPCBB + TZIC
  • U5/H5 (gtzc_v1): TZSC + MPCBB + TZIC + MPCWM (watermarks via PAC)
  • H503/L5: module stub, PAC sub-peripherals differ from wba/v1

embassy-stm32/src/gtzc/mod.rs:

  • Mpcbb: wraps pac::gtzc::Mpcbb; per-block and bulk secure/priv ops, raw bitmap read/write, global lock
  • Tzic: wraps pac::gtzc::Tzic; enable/clear/status per register group, convenience enable_all(n_regs)
  • lock() / is_locked(): lock TZSC config (cfg-gated per variant)

embassy-stm32/src/sau/mod.rs:

  • init(&[Region]): programs up to 8 SAU regions, enables SAU and SecureFault via the cortex-m peripheral API
  • disable(): clears SAU enable bit

examples/stm32wba6/src/bin/trustzone_setup.rs:

  • End-to-end example: SAU regions → MPCBB1/MPCBB2 → TZSC seccfgr → TZIC enable → lock

Both gtzc and sau modules compile cleanly for stm32wba65ri (gtzc_wba) and stm32u585ai (gtzc_v1).

Adds initial support for the Global TrustZone Controller (GTZC) and
Security Attribution Unit (SAU) on STM32 families with TrustZone:

- WBA  (gtzc_wba): TZSC + MPCBB + TZIC
- U5/H5 (gtzc_v1): TZSC + MPCBB + TZIC + MPCWM (watermarks via PAC)
- H503/L5: module stub, PAC sub-peripherals differ from wba/v1

embassy-stm32/src/gtzc/mod.rs:
  - `Mpcbb`: wraps pac::gtzc::Mpcbb; per-block and bulk secure/priv ops,
    raw bitmap read/write, global lock
  - `Tzic`: wraps pac::gtzc::Tzic; enable/clear/status per register group,
    convenience `enable_all(n_regs)`
  - `lock()` / `is_locked()`: lock TZSC config (cfg-gated per variant)

embassy-stm32/src/sau/mod.rs:
  - `init(&[Region])`: programs up to 8 SAU regions, enables SAU and
    SecureFault via the cortex-m peripheral API
  - `disable()`: clears SAU enable bit

examples/stm32wba6/src/bin/trustzone_setup.rs:
  - End-to-end example: SAU regions → MPCBB1/MPCBB2 → TZSC seccfgr →
    TZIC enable → lock

Both gtzc and sau modules compile cleanly for stm32wba65ri (gtzc_wba)
and stm32u585ai (gtzc_v1).
@leftger

leftger commented Apr 21, 2026

Copy link
Copy Markdown
Contributor Author

I'm going through the code and I realize it might be better to add some of these registers to cortex-m.

@leftger

leftger commented Apr 21, 2026

Copy link
Copy Markdown
Contributor Author

Two functions in the SAU driver — route_irq_to_nonsecure and enable_nonsecure_fpu — currently hardcode ARM register addresses directly (NVIC_ITNS_BASE = 0xE000_E380, SCB_NSACR = 0xE000_ED8C) with TODO comments in the source. These will be cleaned up to use typed cortex-m API methods once rust-embedded/cortex-m#647 lands, which adds NVIC::route_to_nonsecure() and SCB::enable_nonsecure_fpu() for ARMv8-M.

@leftger
leftger force-pushed the feat/gtzc-driver branch 3 times, most recently from 1b6ea29 to 555e80b Compare April 21, 2026 04:48
…S boot

- sau: add route_irq_to_nonsecure, enable_nonsecure_fpu, jump_to_nonsecure
  Raw register access used for NVIC ITNS (0xE000_E380) and SCB NSACR
  (0xE000_ED8C) pending cortex-m PR embassy-rs#647; TODO comments reference the PR.
  Fix disable() to set ALLNS=1 (was incorrectly writing 0).
  Fix doc example addresses to match WBA65RI memory map.
- gtzc: add enable_clock, MPCBB superblock locking, srwiladis, invsecstate
- trustzone_setup: rewrite example with correct WBA65RI addresses and all steps
- Cargo.toml: patch cortex-m to leftger/cortex-m feat/trustzone for FPU.fpccr
@Wassasin

Copy link
Copy Markdown
Contributor

The SAU and SCB stuff can partially already be achieved within cortex-m. I would remove it here. Any functionality missing in cortex-m should be added there.

I am not familiar with how STM does their own trustzone bus peripherals, but generally in MCUs they are very similar in diversity to how clock trees are arranged. Mostly they consist of a list of all memories (in sections) and peripherals, and you can configure bus access permissions for those. Hence for each SKU with a different set of peripherals, these bus-configuration blocks are unique.

If no one else has time or affinity with Trustzone I can take a look whether the arrangement makes sense.

@leftger

leftger commented Apr 21, 2026

Copy link
Copy Markdown
Contributor Author

I have PR#647 and PR#648 in the pipeline to address your comments @Wassasin. I'll give it a week for the maintainers to look over it. I'm not in a huge rush to get this through but I'd like to iterate on TrustZone by the end of the month. In the worst case I can have the manual register manipulation here as a placeholder and we can always remove it once cortex-m is able to address TrustZone.

@leftger leftger closed this Jun 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants