|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
Cortex-M85 Memory Protection Unit configuration helper. More...
#include "ra8_mpu.h"#include <stddef.h>#include <stdint.h>#include "ra8_attributes.h"#include "ra8_check.h"#include "ra8_err.h"#include "ra8_hw_intrinsics.h"#include "ra8_mpu_regs.h"Go to the source code of this file.
Enumerations | |
| enum | ra8_mpu_ap_t : uint8_t { k_ra8_mpu_ap_priv_rw_unpriv_none = 0U , k_ra8_mpu_ap_priv_rw_unpriv_rw = 1U , k_ra8_mpu_ap_priv_ro_unpriv_none = 2U , k_ra8_mpu_ap_priv_ro_unpriv_ro = 3U , k_ra8_mpu_ap_invalid = 0xFFU } |
| Encoded AP[1:0] values per the Cortex-M85 TRM. More... | |
| enum | ra8_mpu_shcsr_addr_t : uintptr_t { k_ra8_mpu_shcsr_addr = 0xE000ED24U } |
| SCB->SHCSR address + bits needed to dispatch MemManage faults. More... | |
| enum | ra8_mpu_shcsr_bits_t : uint32_t { k_ra8_mpu_shcsr_memfaultena = (1U << 16U) } |
| enum | ra8_mpu_boot_base_t : uintptr_t { k_ra8_mpu_boot_base_mram = 0x02000000UL , k_ra8_mpu_boot_base_sram = 0x22000000UL , k_ra8_mpu_boot_base_sdram = 0x68000000UL , k_ra8_mpu_boot_base_peri = 0x40000000UL , k_ra8_mpu_boot_base_shram = 0x22100000UL } |
| Region base addresses for the canonical boot map. More... | |
| enum | ra8_mpu_boot_size_t : uint32_t { k_ra8_mpu_boot_size_mram = 0x00100000UL , k_ra8_mpu_boot_size_sram = 0x00100000UL , k_ra8_mpu_boot_size_sdram = 0x04000000UL , k_ra8_mpu_boot_size_peri = 0x08000000UL , k_ra8_mpu_boot_size_shram = 0x000A0000UL } |
| Region byte sizes for the canonical boot map (base+size form). More... | |
Functions | |
| static bool | internal_is_pow2 (uint32_t value) |
| static uint8_t | internal_encode_ap (ra8_mpu_perm_t priv, ra8_mpu_perm_t unpriv) |
| static uint8_t | internal_dregion_count (void) |
| static ra8_err_t | internal_validate_region (const ra8_mpu_region_t *r) |
| static uint32_t | internal_build_rbar (const ra8_mpu_region_t *r) |
| static uint32_t | internal_build_rlar (const ra8_mpu_region_t *r) |
| static void | internal_program_region (uint8_t region, const ra8_mpu_region_t *r) |
| static void | internal_clear_region (uint8_t region) |
| static void | internal_write_ctrl (uint32_t ctrl) |
| static void | internal_write_mair (uint32_t mair0, uint32_t mair1) |
| static uint32_t | internal_build_ctrl (const ra8_mpu_cfg_t *cfg) |
| static ra8_err_t | internal_validate_cfg (const ra8_mpu_cfg_t *cfg) |
| 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. | |
| const ra8_mpu_region_t * | ra8_mpu_boot_map (uint8_t *out_count) |
| Return the canonical boot memory-attribute map region table. | |
| ra8_err_t | ra8_mpu_apply_boot_map (void) |
| Install the canonical 5-region boot memory-attribute map and enable the MPU. | |
| bool | ra8_mpu_is_enabled (void) |
| Report whether the core MPU is currently enabled. | |
Variables | |
| static const char * | s_tag = "MPU" |
| static const ra8_mpu_region_t | s_ra8_mpu_boot_regions [k_ra8_mpu_boot_region_count] |
| The canonical 5-region boot memory-attribute map. | |
Cortex-M85 Memory Protection Unit configuration helper.
Implementation of the public API in ra8_mpu.h. Programmes the Armv8-M MPU register block documented in ra8_mpu_regs.h from a static region table. The register-level shape (RBAR / RLAR / MAIR0 / MAIR1) follows the Arm Cortex-M85 TRM "MPU register summary"; the helper adds power-of-two validation, AP[1:0] encoding from RO/RW/None pairs, and bounds checking against the implemented region count reported by MPU_TYPE.DREGION.
It also owns the canonical 5-region boot memory-attribute map (ra8_mpu_apply_boot_map()), the single source of truth the reset path routes through instead of hand-rolling MAIR/RBAR/RLAR/CTRL pokes in each app's system_init.c (issue #576).
Definition in file ra8_mpu.c.
| enum ra8_mpu_ap_t : uint8_t |
Encoded AP[1:0] values per the Cortex-M85 TRM.
| enum ra8_mpu_boot_base_t : uintptr_t |
Region base addresses for the canonical boot map.
Each base is 32-byte aligned (the Armv8-M region quantum), asserted below. Addresses are 32-bit on the target; uintptr_t keeps the host build (64-bit) casts honest.
| enum ra8_mpu_boot_size_t : uint32_t |
Region byte sizes for the canonical boot map (base+size form).
Region 4 (the shared M85<->M33 bank) is 640 KiB – deliberately NOT a power of two, so the size-checked ra8_mpu_set_region() rejects it, but the Armv8-M base+limit RBAR/RLAR pair encodes it exactly. Every size is a 32-byte multiple (asserted below).
| enum ra8_mpu_shcsr_addr_t : uintptr_t |
SCB->SHCSR address + bits needed to dispatch MemManage faults.
Armv8-M ARM B3.2.10 "SHCSR, System Handler Control and State Register" / Cortex-M85 TRM SCB+0x24. Bit 16 MEMFAULTENA enables the MemManage exception; without it any MPU permission violation escalates to HardFault and the strong MemManage_Handler the application installed never runs.
| Enumerator | |
|---|---|
| k_ra8_mpu_shcsr_addr | SCB->SHCSR (Armv8-M B3.2.10). |
| enum ra8_mpu_shcsr_bits_t : uint32_t |
|
static |
Definition at line 175 of file ra8_mpu.c.
References ra8_mpu_cfg_t::hfnmiena, k_ra8_mpu_ctrl_enable, k_ra8_mpu_ctrl_hfnmiena, k_ra8_mpu_ctrl_privdefena, ra8_mpu_cfg_t::privdefena, and RA8_INTERNAL.
Referenced by ra8_mpu_configure().
|
static |
Definition at line 117 of file ra8_mpu.c.
References ra8_mpu_region_t::base, ra8_mpu_region_t::executable, internal_encode_ap(), k_ra8_mpu_rbar_ap_mask, k_ra8_mpu_rbar_ap_shift, k_ra8_mpu_rbar_base_mask, k_ra8_mpu_rbar_sh_mask, k_ra8_mpu_rbar_sh_shift, k_ra8_mpu_rbar_xn_mask, ra8_mpu_region_t::priv, RA8_INTERNAL, ra8_mpu_region_t::shareable, and ra8_mpu_region_t::unpriv.
Referenced by internal_program_region().
|
static |
Definition at line 131 of file ra8_mpu.c.
References ra8_mpu_region_t::attr_idx, ra8_mpu_region_t::base, k_ra8_mpu_rlar_attridx_mask, k_ra8_mpu_rlar_attridx_shift, k_ra8_mpu_rlar_en_mask, k_ra8_mpu_rlar_limit_mask, RA8_INTERNAL, and ra8_mpu_region_t::size.
Referenced by internal_program_region().
|
static |
Definition at line 151 of file ra8_mpu.c.
References RA8_INTERNAL, ra8_mpu_regs(), r_mpu_regs_t::RLAR, and r_mpu_regs_t::RNR.
Referenced by ra8_mpu_apply_boot_map(), and ra8_mpu_configure().
|
static |
Definition at line 93 of file ra8_mpu.c.
References k_ra8_mpu_type_dregion_mask, k_ra8_mpu_type_dregion_shift, RA8_INTERNAL, ra8_mpu_regs(), and r_mpu_regs_t::TYPE.
Referenced by internal_validate_cfg(), ra8_mpu_apply_boot_map(), ra8_mpu_configure(), and ra8_mpu_set_region().
|
static |
Definition at line 74 of file ra8_mpu.c.
References k_ra8_mpu_ap_invalid, k_ra8_mpu_ap_priv_ro_unpriv_none, k_ra8_mpu_ap_priv_ro_unpriv_ro, k_ra8_mpu_ap_priv_rw_unpriv_none, k_ra8_mpu_ap_priv_rw_unpriv_rw, k_ra8_mpu_perm_none, k_ra8_mpu_perm_ro, k_ra8_mpu_perm_rw, and RA8_INTERNAL.
Referenced by internal_build_rbar(), and internal_validate_region().
|
inlinestatic |
Definition at line 68 of file ra8_mpu.c.
References RA8_INTERNAL.
Referenced by internal_validate_region().
|
static |
Definition at line 142 of file ra8_mpu.c.
References internal_build_rbar(), internal_build_rlar(), RA8_INTERNAL, ra8_mpu_regs(), r_mpu_regs_t::RBAR, r_mpu_regs_t::RLAR, and r_mpu_regs_t::RNR.
Referenced by ra8_mpu_apply_boot_map(), ra8_mpu_configure(), and ra8_mpu_set_region().
|
static |
Definition at line 188 of file ra8_mpu.c.
References internal_dregion_count(), internal_validate_region(), k_ra8_err_invalid_arg, k_ra8_err_null_ptr, k_ra8_ok, RA8_INTERNAL, ra8_mpu_cfg_t::region_count, and ra8_mpu_cfg_t::regions.
Referenced by ra8_mpu_configure().
|
static |
Definition at line 102 of file ra8_mpu.c.
References ra8_mpu_region_t::base, internal_encode_ap(), internal_is_pow2(), k_ra8_err_invalid_arg, k_ra8_mpu_ap_invalid, k_ra8_mpu_min_region_size, k_ra8_ok, ra8_mpu_region_t::priv, RA8_INTERNAL, ra8_mpu_region_t::size, and ra8_mpu_region_t::unpriv.
Referenced by internal_validate_cfg(), and ra8_mpu_set_region().
|
static |
Definition at line 159 of file ra8_mpu.c.
References r_mpu_regs_t::CTRL, RA8_INTERNAL, and ra8_mpu_regs().
Referenced by ra8_mpu_apply_boot_map(), and ra8_mpu_configure().
|
static |
Definition at line 166 of file ra8_mpu.c.
References r_mpu_regs_t::MAIR0, r_mpu_regs_t::MAIR1, RA8_INTERNAL, and ra8_mpu_regs().
Referenced by ra8_mpu_apply_boot_map(), and ra8_mpu_configure().
|
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.
| k_ra8_ok | Map installed; MPU enabled with PRIVDEFENA. |
| k_ra8_err_invalid_arg | MPU_TYPE.DREGION reports fewer than k_ra8_mpu_boot_region_count implemented regions; the MPU is left disabled. |
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().
| 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.
| [out] | out_count | Receives the region count (k_ra8_mpu_boot_region_count). Must be non-NULL. |
out_count is NULL. | NULL | out_count was NULL; *out_count is not written. |
out_count != NULL. 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().
|
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.
| [in] | cfg | Configuration block. |
| k_ra8_ok | Region table programmed and MPU enabled. |
| k_ra8_err_null_ptr | cfg == NULL or cfg->regions == NULL. |
| k_ra8_err_invalid_arg | region_count > DREGION, or a region has non-power-of-two size, misaligned base, or unrepresentable AP pair. |
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().
|
nodiscard |
Clear MPU_CTRL.ENABLE.
| k_ra8_ok | Always. |
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().
|
nodiscard |
Set MPU_CTRL.ENABLE.
| k_ra8_ok | Always. |
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().
|
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.
| true | The MPU is enabled. |
| false | The MPU is disabled. |
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().
|
nodiscard |
Program a single region without disabling the MPU.
| [in] | region | Region index, 0..MPU_TYPE.DREGION - 1. |
| [in] | region_cfg | New descriptor. |
| k_ra8_ok | Region updated. |
| k_ra8_err_null_ptr | region_cfg == NULL. |
| k_ra8_err_invalid_arg | region >= DREGION, or region_cfg has non-power-of-two size, misaligned base, or unrepresentable AP pair. |
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.
|
static |
The canonical 5-region boot memory-attribute map.
Region 0 maps MRAM code RO+executable cacheable; regions 1-2 map the M85-private SRAM and SDRAM RW/XN cacheable; region 3 maps the peripheral window RW/XN Device-nGnRE; region 4 maps the shared M85<->M33 SRAM RW/XN Normal non-cacheable so cross-core hand-offs stay coherent with the M85 D-cache on. Lives in .rodata, so it is readable from SystemInit() before the .data copy.
Definition at line 325 of file ra8_mpu.c.
Referenced by ra8_mpu_apply_boot_map(), and ra8_mpu_boot_map().