ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_mpu.h File Reference

Cortex-M85 Memory Protection Unit (MPU) configuration helper. More...

#include <stddef.h>
#include <stdint.h>
#include "ra8_err.h"
Include dependency graph for ra8_mpu.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  ra8_mpu_region_t
 Static descriptor for one Armv8-M MPU region. More...
struct  ra8_mpu_cfg_t
 Whole-MPU static configuration block. More...

Enumerations

enum  ra8_mpu_perm_t : uint8_t {
  k_ra8_mpu_perm_none = 0U ,
  k_ra8_mpu_perm_ro = 1U ,
  k_ra8_mpu_perm_rw = 2U
}
 Per-world (priv / unpriv) access permission for an MPU region. More...
enum  ra8_mpu_share_t : uint8_t {
  k_ra8_mpu_share_non = 0U ,
  k_ra8_mpu_share_outer = 2U ,
  k_ra8_mpu_share_inner = 3U
}
 Shareability domain for an MPU region (Armv8-M SH[1:0]). More...
enum  ra8_mpu_attr_idx_t : uint8_t {
  k_ra8_mpu_attr_idx_0 = 0U ,
  k_ra8_mpu_attr_idx_1 = 1U ,
  k_ra8_mpu_attr_idx_2 = 2U ,
  k_ra8_mpu_attr_idx_3 = 3U ,
  k_ra8_mpu_attr_idx_4 = 4U ,
  k_ra8_mpu_attr_idx_5 = 5U ,
  k_ra8_mpu_attr_idx_6 = 6U ,
  k_ra8_mpu_attr_idx_7 = 7U
}
 Index into MAIR0/MAIR1 for the region's memory-attribute set. More...
enum  ra8_mpu_size_limits_t : uint32_t { k_ra8_mpu_min_region_size = 32U }
 Architectural size limits for an MPU region. More...
enum  ra8_mpu_boot_layout_t : uint8_t { k_ra8_mpu_boot_region_count = 5U }
 Fixed geometry of the canonical boot memory-attribute map. More...
enum  ra8_mpu_boot_mair_t : uint32_t {
  k_ra8_mpu_boot_mair0 = 0x000444FFUL ,
  k_ra8_mpu_boot_mair1 = 0x00000000UL
}
 MAIR0/MAIR1 attribute-indirection words for the canonical boot map. More...

Functions

ra8_err_t ra8_mpu_configure (const ra8_mpu_cfg_t *cfg)
 Program every MPU region from a static configuration.
ra8_err_t ra8_mpu_enable (void)
 Set MPU_CTRL.ENABLE.
ra8_err_t ra8_mpu_disable (void)
 Clear MPU_CTRL.ENABLE.
ra8_err_t ra8_mpu_set_region (uint8_t region, const ra8_mpu_region_t *region_cfg)
 Program a single region without disabling the MPU.
ra8_err_t ra8_mpu_apply_boot_map (void)
 Install the canonical 5-region boot memory-attribute map and enable the MPU.
const ra8_mpu_region_tra8_mpu_boot_map (uint8_t *out_count)
 Return the canonical boot memory-attribute map region table.
bool ra8_mpu_is_enabled (void)
 Report whether the core MPU is currently enabled.

Detailed Description

Cortex-M85 Memory Protection Unit (MPU) configuration helper.

Programs the Armv8-M MPU regions inside each TrustZone world from a static configuration. The MPU is independent of the SAU (which partitions S vs NS); the MPU partitions memory within a single world. The descriptor maps directly onto the Armv8-M RBAR / RLAR fields documented in ra8_mpu_regs.h; this layer adds power-of-two size validation, AP[1:0] encoding from human-readable RO/RW/None pairs, and bounds checking against MPU_TYPE.DREGION.

Definition in file ra8_mpu.h.

Enumeration Type Documentation

◆ ra8_mpu_attr_idx_t

enum ra8_mpu_attr_idx_t : uint8_t

Index into MAIR0/MAIR1 for the region's memory-attribute set.

Slot 0..7. Slots 0..3 live in MAIR0; 4..7 live in MAIR1.

Enumerator
k_ra8_mpu_attr_idx_0 

MAIR0 byte 0.

k_ra8_mpu_attr_idx_1 

MAIR0 byte 1.

k_ra8_mpu_attr_idx_2 

MAIR0 byte 2.

k_ra8_mpu_attr_idx_3 

MAIR0 byte 3.

k_ra8_mpu_attr_idx_4 

MAIR1 byte 0.

k_ra8_mpu_attr_idx_5 

MAIR1 byte 1.

k_ra8_mpu_attr_idx_6 

MAIR1 byte 2.

k_ra8_mpu_attr_idx_7 

MAIR1 byte 3.

Definition at line 65 of file ra8_mpu.h.

◆ ra8_mpu_boot_layout_t

enum ra8_mpu_boot_layout_t : uint8_t

Fixed geometry of the canonical boot memory-attribute map.

ra8_mpu_apply_boot_map() installs exactly this many regions. The count is a contract shared by the boot caller (SystemInit()) and the host tests, so it lives in the header rather than being buried in the implementation.

Enumerator
k_ra8_mpu_boot_region_count 

Regions in the canonical boot map.

Definition at line 95 of file ra8_mpu.h.

◆ ra8_mpu_boot_mair_t

enum ra8_mpu_boot_mair_t : uint32_t

MAIR0/MAIR1 attribute-indirection words for the canonical boot map.

Three memory-attribute sets are used by the boot map, packed into MAIR0:

  • byte 0 (AttrIdx 0) = 0xFF: Normal, inner+outer write-back / write-allocate.
  • byte 1 (AttrIdx 1) = 0x44: Normal, inner+outer non-cacheable.
  • byte 2 (AttrIdx 2) = 0x04: Device-nGnRE. MAIR1 is unused because the boot map has no region with AttrIdx >= 4. See the Armv8-M ARM "MAIR0/MAIR1, MPU Memory Attribute Indirection Registers".
See also
ra8_mpu_apply_boot_map()
Enumerator
k_ra8_mpu_boot_mair0 

Boot MAIR0: WB/WA, non-cacheable, Device.

k_ra8_mpu_boot_mair1 

Boot MAIR1: unused (no AttrIdx >= 4).

Definition at line 113 of file ra8_mpu.h.

◆ ra8_mpu_perm_t

enum ra8_mpu_perm_t : uint8_t

Per-world (priv / unpriv) access permission for an MPU region.

Armv8-M packs both privileged and unprivileged permissions into a single AP[1:0] field; this enum surfaces the underlying RO / RW / None levels so the caller specifies them independently. The Armv8-M AP table cannot represent "priv RO + unpriv RW", so configure() rejects that combination with k_ra8_err_invalid_arg.

Enumerator
k_ra8_mpu_perm_none 

No access at this privilege level.

k_ra8_mpu_perm_ro 

Read-only at this privilege level.

k_ra8_mpu_perm_rw 

Read-write at this privilege level.

Definition at line 41 of file ra8_mpu.h.

◆ ra8_mpu_share_t

enum ra8_mpu_share_t : uint8_t

Shareability domain for an MPU region (Armv8-M SH[1:0]).

Mirrors the SH field from the Cortex-M85 TRM "MPU_RBAR".

Enumerator
k_ra8_mpu_share_non 

Non-shareable.

k_ra8_mpu_share_outer 

Outer shareable.

k_ra8_mpu_share_inner 

Inner shareable.

Definition at line 53 of file ra8_mpu.h.

◆ ra8_mpu_size_limits_t

enum ra8_mpu_size_limits_t : uint32_t

Architectural size limits for an MPU region.

Armv8-M requires 32-byte alignment of base and limit.

Enumerator
k_ra8_mpu_min_region_size 

Minimum power-of-two size in bytes.

Definition at line 82 of file ra8_mpu.h.

Function Documentation

◆ ra8_mpu_apply_boot_map()

ra8_err_t ra8_mpu_apply_boot_map ( void )
nodiscard

Install the canonical 5-region boot memory-attribute map and enable the MPU.

Programs the fixed attribute map every RA8D2 image needs out of reset – RO+executable cacheable MRAM code, RW/XN cacheable M85-private SRAM and SDRAM, RW/XN Device-nGnRE peripherals, and RW/XN Normal-non-cacheable shared M85<->M33 SRAM – then enables the MPU with PRIVDEFENA so anything the map does not cover keeps the privileged default memory map. This is the boot-usable entry point that replaces the hand-rolled MAIR/RBAR/RLAR/CTRL pokes each app's system_init.c used to duplicate: the boot path routes its attribute map through this one driver exactly as it already calls ra8_cache_dcache_invalidate_all().

Callable from SystemInit() before .data/.bss are initialised: it reads only the driver-owned const region table (in .rodata) and MMIO, writes no .data/.bss, and never logs. The shared M85<->M33 bank is 640 KiB, which is not a power of two and so cannot be expressed through the size-checked ra8_mpu_set_region(); this entry point encodes it by base+limit directly, which the Armv8-M PMSAv8 RBAR/RLAR pair supports natively.

Returns
ra8_err_t error code.
Return values
k_ra8_okMap installed; MPU enabled with PRIVDEFENA.
k_ra8_err_invalid_argMPU_TYPE.DREGION reports fewer than k_ra8_mpu_boot_region_count implemented regions; the MPU is left disabled.
Precondition
Caller is privileged (true out of reset in the Secure state).
The core MPU is idle (freshly reset or previously disabled).
Postcondition
On k_ra8_ok, MPU_CTRL.ENABLE == 1 and MPU_CTRL.PRIVDEFENA == 1.
On failure the MPU is left disabled; no partial map is enabled.
Note
Not thread-safe; single-threaded boot / init context only.
Does not touch SHCSR.MEMFAULTENA – the boot path enables the configurable-fault handlers separately; a runtime caller wanting MemManage delivery uses ra8_mpu_configure() instead.
See also
ra8_mpu_boot_map() Inspect the region table this installs.
ra8_mpu_configure() Full runtime configuration from a caller table.
Since
0.1.0

Definition at line 417 of file ra8_mpu.c.

References internal_clear_region(), internal_dregion_count(), internal_program_region(), internal_write_ctrl(), internal_write_mair(), k_ra8_err_invalid_arg, k_ra8_mpu_boot_mair0, k_ra8_mpu_boot_mair1, k_ra8_mpu_boot_region_count, k_ra8_mpu_ctrl_enable, k_ra8_mpu_ctrl_privdefena, k_ra8_ok, ra8_hw_dsb(), ra8_hw_isb(), and s_ra8_mpu_boot_regions.

Referenced by SystemInit().

◆ ra8_mpu_boot_map()

const ra8_mpu_region_t * ra8_mpu_boot_map ( uint8_t * out_count)

Return the canonical boot memory-attribute map region table.

Read-only view of the exact region descriptors ra8_mpu_apply_boot_map() installs, so callers (a boot self-test, the host unit tests) can inspect or cross-check the map without re-encoding it. The pointer targets a driver-owned static const table in .rodata; the entries are immutable.

Parameters
[out]out_countReceives the region count (k_ra8_mpu_boot_region_count). Must be non-NULL.
Returns
Pointer to the first of *out_count region descriptors, or NULL when out_count is NULL.
Return values
NULLout_count was NULL; *out_count is not written.
Precondition
out_count != NULL.
Postcondition
On non-NULL return, *out_count == k_ra8_mpu_boot_region_count.
The referenced table is not modified.
Note
Thread-safe: returns a pointer to immutable data.
See also
ra8_mpu_apply_boot_map()
Since
0.1.0

Definition at line 408 of file ra8_mpu.c.

References k_ra8_mpu_boot_region_count, and s_ra8_mpu_boot_regions.

Referenced by mpu_boot_test_map().

◆ ra8_mpu_configure()

ra8_err_t ra8_mpu_configure ( const ra8_mpu_cfg_t * cfg)
nodiscard

Program every MPU region from a static configuration.

Disables the MPU, writes MAIR0/MAIR1, walks the region table, clears any unused regions above region_count, then re-enables the MPU with the requested CTRL flags.

Parameters
[in]cfgConfiguration block.
Returns
ra8_err_t error code.
Return values
k_ra8_okRegion table programmed and MPU enabled.
k_ra8_err_null_ptrcfg == NULL or cfg->regions == NULL.
k_ra8_err_invalid_argregion_count > DREGION, or a region has non-power-of-two size, misaligned base, or unrepresentable AP pair.
Precondition
cfg != NULL.
Caller is in privileged mode.
Postcondition
On success MPU_CTRL.ENABLE == 1.
On failure no MPU state is changed.
Note
Not thread-safe.
See also
Arm Cortex-M85 TRM "MPU register summary".
Since
0.1.0

Definition at line 206 of file ra8_mpu.c.

References internal_build_ctrl(), internal_clear_region(), internal_dregion_count(), internal_program_region(), internal_validate_cfg(), internal_write_ctrl(), internal_write_mair(), k_ra8_mpu_shcsr_addr, k_ra8_mpu_shcsr_memfaultena, k_ra8_ok, ra8_mpu_cfg_t::mair0, ra8_mpu_cfg_t::mair1, RA8_CHECK_NULL_PTR, ra8_mpu_cfg_t::region_count, ra8_mpu_cfg_t::regions, and s_tag.

Referenced by main().

◆ ra8_mpu_disable()

ra8_err_t ra8_mpu_disable ( void )
nodiscard

Clear MPU_CTRL.ENABLE.

Returns
ra8_err_t error code.
Return values
k_ra8_okAlways.
Precondition
Caller is privileged.
Postcondition
MPU_CTRL.ENABLE == 0.
Note
Not thread-safe.
Since
0.1.0

Definition at line 251 of file ra8_mpu.c.

References r_mpu_regs_t::CTRL, k_ra8_mpu_ctrl_enable, k_ra8_ok, and ra8_mpu_regs().

◆ ra8_mpu_enable()

ra8_err_t ra8_mpu_enable ( void )
nodiscard

Set MPU_CTRL.ENABLE.

Returns
ra8_err_t error code.
Return values
k_ra8_okAlways.
Precondition
Caller is privileged.
Postcondition
MPU_CTRL.ENABLE == 1.
Note
Not thread-safe.
Since
0.1.0

Definition at line 243 of file ra8_mpu.c.

References r_mpu_regs_t::CTRL, k_ra8_mpu_ctrl_enable, k_ra8_ok, and ra8_mpu_regs().

◆ ra8_mpu_is_enabled()

bool ra8_mpu_is_enabled ( void )
nodiscard

Report whether the core MPU is currently enabled.

Reads MPU_CTRL.ENABLE (Armv8-M "MPU_CTRL"). Lets application code confirm the boot attribute map came up without poking the register block directly – the whole point of routing MPU access through this driver.

Returns
Whether MPU_CTRL.ENABLE is set.
Return values
trueThe MPU is enabled.
falseThe MPU is disabled.
Precondition
Caller is privileged (or RA8_OFF_TARGET, where the register is faked).
Postcondition
No MPU state is modified (pure read).
Note
Not thread-safe with respect to a concurrent enable/disable.
See also
ra8_mpu_enable()
ra8_mpu_apply_boot_map()
Since
0.1.0

Definition at line 450 of file ra8_mpu.c.

References k_ra8_mpu_ctrl_enable, and ra8_mpu_regs().

Referenced by mpu_boot_test_enabled().

◆ ra8_mpu_set_region()

ra8_err_t ra8_mpu_set_region ( uint8_t region,
const ra8_mpu_region_t * region_cfg )
nodiscard

Program a single region without disabling the MPU.

Parameters
[in]regionRegion index, 0..MPU_TYPE.DREGION - 1.
[in]region_cfgNew descriptor.
Returns
ra8_err_t error code.
Return values
k_ra8_okRegion updated.
k_ra8_err_null_ptrregion_cfg == NULL.
k_ra8_err_invalid_argregion >= DREGION, or region_cfg has non-power-of-two size, misaligned base, or unrepresentable AP pair.
Precondition
region_cfg != NULL.
Caller is privileged.
Postcondition
On success the addressed region holds the new descriptor.
Note
Not thread-safe.
Since
0.1.0

Definition at line 259 of file ra8_mpu.c.

References internal_dregion_count(), internal_program_region(), internal_validate_region(), k_ra8_err_invalid_arg, k_ra8_ok, RA8_CHECK_NULL_PTR, and s_tag.