ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
system_init.c
Go to the documentation of this file.
1
44
45#include <stdint.h>
46
48#include "ra8_boot_entry.h"
49#include "ra8_boot_intrinsics.h"
50#include "ra8_cache.h"
51#include "trustzone_init.h"
52
53extern const uint32_t g_ra8_vector_table_start[];
54
55/* =============================================================================
56 * Core / SCB / NVIC register addresses (direct, no CMSIS dep)
57 * =============================================================================
58 */
59
60typedef enum : uintptr_t {
61 k_ra8_scb_vtor_addr = 0xE000ED08UL,
62 k_ra8_scb_ccr_addr = 0xE000ED14UL,
63 k_ra8_scb_shcsr_addr = 0xE000ED24UL,
64 k_ra8_scb_cpacr_addr = 0xE000ED88UL,
65 k_ra8_scb_nsacr_addr = 0xE000ED8CUL,
66 k_ra8_scb_iciallu = 0xE000EF50UL,
67 k_ra8_scb_dciallu = 0xE000EF58UL,
68 k_ra8_scb_csselr = 0xE000ED84UL,
69 k_ra8_scb_ccsidr = 0xE000ED80UL,
70 k_ra8_scb_dcisw = 0xE000EF60UL,
71 k_ra8_fpu_fpccr_addr = 0xE000EF34UL,
72 k_ra8_nvic_aircr = 0xE000ED0CUL,
73 k_ra8_mpu_type_addr = 0xE000ED90UL,
74 k_ra8_mpu_ctrl_addr = 0xE000ED94UL,
75 k_ra8_mpu_rnr_addr = 0xE000ED98UL,
76 k_ra8_mpu_rbar_addr = 0xE000ED9CUL,
77 k_ra8_mpu_rlar_addr = 0xE000EDA0UL,
78 k_ra8_mpu_mair0_addr = 0xE000EDC0UL,
79 k_ra8_mpu_mair1_addr = 0xE000EDC4UL,
81
82extern uint32_t g_ra8_ls_stack_top; /* from vector_table.c / linker. */
83
84/* =============================================================================
85 * Core init steps
86 * =============================================================================
87 */
88
100static void internal_set_vtor(void)
101{
102 /* Vector table sits at the start of the .vectors section, which
103 * the linker pins to the start of MRAM (`0x02000000`). The SCB
104 * VTOR register stores the absolute address. */
106}
107
119static void internal_enable_fpu(void)
120{
121 enum : uint32_t {
122 k_ra8_cpacr_cp10_cp11_full_access = 0x00F00000UL,
123 };
124 uint32_t cpacr = ra8_boot_read32(k_ra8_scb_cpacr_addr);
125 cpacr |= k_ra8_cpacr_cp10_cp11_full_access;
127 ra8_boot_dsb();
128 ra8_boot_isb();
129}
130
143{
144 enum : uint32_t {
145 k_ra8_fpccr_lspen = 1UL << 30,
146 k_ra8_fpccr_aspen = 1UL << 31,
147 };
148 uint32_t fpccr = ra8_boot_read32(k_ra8_fpu_fpccr_addr);
149 fpccr |= k_ra8_fpccr_lspen | k_ra8_fpccr_aspen;
151}
152
164static void internal_enable_icache(void)
165{
166 /* Invalidate, then set CCR.IC. */
167 ra8_boot_dsb();
169 ra8_boot_dsb();
170 ra8_boot_isb();
171
172 enum : uint32_t { k_ra8_ccr_ic = 1UL << 17 };
173 uint32_t ccr = ra8_boot_read32(k_ra8_scb_ccr_addr);
174 ccr |= k_ra8_ccr_ic;
176 ra8_boot_dsb();
177 ra8_boot_isb();
178}
179
199static void internal_enable_dcache(void)
200{
201 /* Architectural ARMv8-M set/way invalidate of the whole D-cache,
202 * driven by CCSIDR (implemented in libs/ra8_hal ra8_cache). */
204 enum : uint32_t { k_ra8_ccr_dc = 1UL << 16 };
205 uint32_t ccr = ra8_boot_read32(k_ra8_scb_ccr_addr);
206 ccr |= k_ra8_ccr_dc;
208 ra8_boot_dsb();
209 ra8_boot_isb();
210}
211
224{
225 enum : uint32_t { k_ra8_ccr_bp = 1UL << 18 };
226 uint32_t ccr = ra8_boot_read32(k_ra8_scb_ccr_addr);
227 ccr |= k_ra8_ccr_bp;
229 ra8_boot_dsb();
230 ra8_boot_isb();
231}
232
268{
269 /* ARMv8-M SCB->SHCSR: MEMFAULTENA[16], BUSFAULTENA[17], USGFAULTENA[18],
270 * SECUREFAULTENA[19] take MemManage/BusFault/UsageFault/SecureFault to
271 * their own handlers instead of escalating to HardFault, so
272 * ra8_exception_report sees the real class. SECUREFAULTENA is a
273 * Secure-bank bit (RES0 from NS); this boot executes in the Secure
274 * state, see the function contract for the scoping rationale. */
275 enum : uint32_t {
276 k_ra8_shcsr_memfaultena = 1UL << 16,
277 k_ra8_shcsr_busfaultena = 1UL << 17,
278 k_ra8_shcsr_usgfaultena = 1UL << 18,
279 k_ra8_shcsr_securefaultena = 1UL << 19,
280 };
281 uint32_t shcsr = ra8_boot_read32(k_ra8_scb_shcsr_addr);
282 shcsr |= k_ra8_shcsr_memfaultena | k_ra8_shcsr_busfaultena | k_ra8_shcsr_usgfaultena |
283 k_ra8_shcsr_securefaultena;
285 ra8_boot_dsb();
286 ra8_boot_isb();
287}
288
319{
320 /* ARMv8-M SCB->CCR: DIV_0_TRP[4] promotes SDIV/UDIV-by-zero from
321 * "quotient reads as 0" to a UsageFault with CFSR.DIVBYZERO set.
322 * UNALIGN_TRP[3] stays 0 -- see the function contract for evidence. */
323 enum : uint32_t {
324 k_ra8_ccr_div_0_trp = 1UL << 4,
325 };
326 uint32_t ccr = ra8_boot_read32(k_ra8_scb_ccr_addr);
327 ccr |= k_ra8_ccr_div_0_trp;
329 ra8_boot_dsb();
330 ra8_boot_isb();
331}
332
345{
346 enum : uint32_t {
347 k_ra8_aircr_vectkey = 0x05FA0000UL,
348 k_ra8_aircr_prigroup_4 = 0x00000300UL,
349 };
350 ra8_boot_write32(k_ra8_nvic_aircr, k_ra8_aircr_vectkey | k_ra8_aircr_prigroup_4);
351}
352
387/* RBAR attribute bits[4:0] = { SH[4:3], AP[2:1], XN[0] }. AP: 0b01<<1 = RW
388 * any-privilege, 0b11<<1 = RO any-privilege. The memory TYPE is NOT here --
389 * it is the RLAR AttrIndx (see internal_mpu_set_region). */
390enum : uint32_t {
394};
395
396/* RLAR AttrIndx (bits[3:1]) selects which MAIR byte sets the region's memory
397 * type. The old code tried to encode "device" in RBAR (k_ra8_rbar_attr_device_rw
398 * = 0x23), which both spilled bit5 into the base address and left every RLAR at
399 * AttrIndx 0 = MAIR0[0] = Normal cacheable -- so peripheral MMIO was mapped
400 * cacheable. The type must be selected here instead. */
401enum : uint32_t {
407};
408
409/* Region base and limit addresses. RLAR limits are <region-end> minus
410 * the ARMv8-M 32-byte region quantum, OR-ed with the enable bit at write time. */
411enum : uint32_t {
412 k_ra8_mpu_mram_base = 0x02000000UL,
413 k_ra8_mpu_mram_limit = 0x020FFFE0UL,
414 k_ra8_mpu_sram_base = 0x22000000UL,
415 k_ra8_mpu_sram_limit = 0x220FFFE0UL,
421 k_ra8_mpu_sdram_base = 0x68000000UL,
422 k_ra8_mpu_sdram_limit = 0x6BFFFFE0UL,
423 k_ra8_mpu_peri_base = 0x40000000UL,
424 k_ra8_mpu_peri_limit = 0x47FFFFE0UL,
425};
426
444static void internal_mpu_set_region(uint32_t region,
445 uint32_t base_attr,
446 uint32_t limit_enable,
447 uint32_t attr_idx)
448{
452}
453
465static void internal_mpu_init(void)
466{
467 enum : uint32_t {
468 k_ra8_mpu_ctrl_enable = 1UL << 0,
469 k_ra8_mpu_ctrl_privdefena = 1UL << 2,
470 k_ra8_mair0_default = 0x000444FFUL,
471 };
472
473 /* MAIR0: idx0 = Normal WB/WA, idx1 = Normal non-cacheable, idx2 = Device-nGnRE. */
474 ra8_boot_write32(k_ra8_mpu_mair0_addr, k_ra8_mair0_default);
476
477 /* Code = RO + executable cacheable; RAM = RW/NX cacheable; peripherals =
478 * Device-nGnRE (NOT cacheable -- the AttrIndx selects the type). */
495 /* Shared M85<->M33 SRAM bank: Normal NON-cacheable so cross-core hand-offs
496 * (mailbox at 0x22100000, CPU1 RAM) stay coherent with the M85 D-cache on. */
501
502 /* Enable MPU with PRIVDEFENA so unclassified privileged accesses
503 * still succeed through the default system memory map. */
504 ra8_boot_dsb();
506 ra8_boot_dsb();
507 ra8_boot_isb();
508}
509
510/* =============================================================================
511 * Public entry point
512 * =============================================================================
513 *
514 * Called from `Reset_Handler` before the .data copy and .bss zero.
515 * Must therefore not touch any global variables -- everything here
516 * runs on the stack and writes to CPU / SCB memory only.
517 */
518
519void SystemInit(void)
520{
521 /* Mask global IRQs so the application gets a deterministic init
522 * window. main() must call ``ra8_isr_globals_enable`` once every
523 * driver / handler is wired up before any IRQ source can fire. */
525
529 /* Always-on fault diagnostics: take MemManage/BusFault/UsageFault/
530 * SecureFault to their own decoded handlers and trap divide-by-zero
531 * as a UsageFault (independent of the cache / MPU build flag). */
534#ifdef RA8_BOOT_ENABLE_CACHE_MPU
535 /* T4-06: MPU memory-attribute map FIRST (so the D-cache sees Device-nGnRE
536 * MMIO and the non-cacheable shared SRAM, not Normal cacheable), then the
537 * caches. Each *_enable does its own architectural invalidate before setting
538 * CCR. Region 4 (non-cacheable shared SRAM) keeps M85<->M33 hand-offs
539 * coherent with no software maintenance. */
541#ifdef RA8_BOOT_CACHE_VIA_HAL
542 /* Issue #577: bring the L1 caches up through the ra8_cache HAL instead of the
543 * hand-rolled internal_enable_icache / internal_enable_dcache pokes. The HAL
544 * primitives encode the identical ICIALLU + CCR.IC / CCR.DC sequence (each
545 * runs its architectural invalidate before setting the enable bit), so this is
546 * a drop-in with no behaviour change. The raw helpers stay compiled just above
547 * as the reference path; exactly the app that opts in takes the HAL route. */
552#else
555#endif
557#else
558 /* Default OFF: caches + MPU stay disabled -- no behaviour change. */
562 (void)internal_mpu_init;
563#endif
564 (void)ra8_trustzone_init; /* TrustZone has its own gate (RA8_TRUSTZONE_ENABLE). */
566}
static void internal_enable_fpu_lazy_stack(void)
Turn on FPU lazy stacking (FPCCR.LSPEN = 1, ASPEN = 1).
static void internal_enable_branch_predictor(void)
Enable branch-target prediction (CCR.BP on Cortex-M85).
static void internal_set_vtor(void)
Point VTOR at the physical vector table base.
static void internal_enable_dcache(void)
Invalidate and enable the Cortex-M85 D-cache.
static void internal_enable_icache(void)
Invalidate and enable the Cortex-M85 I-cache.
static void internal_mpu_init(void)
Programme and enable the Cortex-M85 core MPU.
void SystemInit(void)
Earliest C code the image runs: bring the core up before RAM init.
static void internal_mpu_set_region(uint32_t region, uint32_t base_attr, uint32_t limit_enable)
Program a single MPU region via RNR/RBAR/RLAR.
static void internal_set_priority_grouping(void)
Set NVIC priority grouping to 4 preempt bits / 0 sub-priority.
static void internal_enable_fpu(void)
Grant full access to CP10 / CP11 (the FPU coprocessors).
static void internal_enable_div0_trap(void)
Make integer divide-by-zero trap as a decoded UsageFault.
static void internal_enable_fault_handlers(void)
Enable the configurable-fault handlers so faults decode by class.
void ra8_trustzone_init(void)
Programme + enable the SAU per the partition.
@ k_ra8_mpu_rlar_attridx_shift
RA8 MPU rlar attridx shift.
@ k_ra8_mpu_attridx_normal_wbwa
MAIR0[0] 0xFF: Normal inner/outer WB/WA.
@ k_ra8_mpu_attridx_noncacheable
MAIR0[1] 0x44: Normal non-cacheable.
@ k_ra8_mpu_region_quantum
ARMv8-M PMSAv8 region granule, bytes.
@ k_ra8_mpu_attridx_device
MAIR0[2] 0x04: Device-nGnRE (MMIO).
static void internal_enable_branch_predictor(void)
Enable branch-target prediction (CCR.BP on Cortex-M85).
static void internal_enable_dcache(void)
Invalidate and enable the Cortex-M85 D-cache.
uint32_t g_ra8_ls_stack_top
static void internal_enable_icache(void)
Invalidate and enable the Cortex-M85 I-cache.
@ k_ra8_mpu_sdram_limit
RA8 MPU SDRAM limit.
@ k_ra8_mpu_mram_base
1 MiB MRAM code region.
@ k_ra8_mpu_sram_limit
RA8 MPU SRAM limit.
@ k_ra8_mpu_sram_base
M85 private SRAM0+1, 1 MiB, cacheable.
@ k_ra8_mpu_peri_base
Peripheral bus window base.
@ k_ra8_mpu_shram_base
Shared SRAM2+3: M33 mailbox + CPU1 RAM.
@ k_ra8_mpu_shram_limit
Non-cacheable -> M85<->M33 stays coherent.
@ k_ra8_mpu_mram_limit
RA8 MPU MRAM limit.
@ k_ra8_mpu_peri_limit
RA8 MPU peri limit.
@ k_ra8_mpu_sdram_base
64 MiB external SDRAM.
static void internal_mpu_init(void)
Programme and enable the Cortex-M85 core MPU.
@ k_ra8_rbar_attr_ro_x
AP=RO any-priv, SH=none, XN=0 (executable).
@ k_ra8_mpu_rlar_enable
RA8 MPU rlar enable.
@ k_ra8_rbar_attr_rw_xn
AP=RW any-priv, SH=none, XN=1 (no execute).
ra8_core_addr_t
Definition system_init.c:60
@ k_ra8_scb_iciallu
ICIALLU – invalidate I-cache.
Definition system_init.c:66
@ k_ra8_scb_dcisw
D-cache Invalidate by Set/Way.
Definition system_init.c:70
@ k_ra8_scb_csselr
Cache Size Selection Register.
Definition system_init.c:68
@ k_ra8_scb_dciallu
DCIALLU – invalidate D-cache (sets only).
Definition system_init.c:67
@ k_ra8_mpu_mair0_addr
MPU Attribute Indirection 0.
Definition system_init.c:78
@ k_ra8_scb_ccsidr
Cache Size ID Register.
Definition system_init.c:69
@ k_ra8_scb_cpacr_addr
Coprocessor Access Control.
Definition system_init.c:64
@ k_ra8_scb_shcsr_addr
System Handler Control and State.
Definition system_init.c:63
@ k_ra8_fpu_fpccr_addr
FPU Context Control Register.
Definition system_init.c:71
@ k_ra8_scb_ccr_addr
Configuration and Control Register.
Definition system_init.c:62
@ k_ra8_mpu_type_addr
MPU Type Register.
Definition system_init.c:73
@ k_ra8_mpu_rnr_addr
MPU Region Number.
Definition system_init.c:75
@ k_ra8_mpu_rbar_addr
MPU Region Base Address.
Definition system_init.c:76
@ k_ra8_mpu_mair1_addr
MPU Attribute Indirection 1.
Definition system_init.c:79
@ k_ra8_mpu_ctrl_addr
MPU Control Register.
Definition system_init.c:74
@ k_ra8_scb_vtor_addr
Vector Table Offset Register.
Definition system_init.c:61
@ k_ra8_scb_nsacr_addr
Non-secure Access Control.
Definition system_init.c:65
@ k_ra8_mpu_rlar_addr
MPU Region Limit Address.
Definition system_init.c:77
@ k_ra8_nvic_aircr
Application Interrupt and Reset Ctrl.
Definition system_init.c:72
const uint32_t g_ra8_vector_table_start[]
static uint32_t ra8_boot_read32(uintptr_t addr)
Volatile 32-bit MMIO read.
static void ra8_boot_write32(uintptr_t addr, uint32_t value)
Volatile 32-bit MMIO write.
static void ra8_boot_isb(void)
Instruction synchronisation barrier (no-op under RA8_OFF_TARGET).
static void ra8_boot_disable_irq(void)
Mask IRQs / set PRIMASK (no-op under RA8_OFF_TARGET).
static void ra8_boot_dsb(void)
Data synchronisation barrier (no-op under RA8_OFF_TARGET).
Where the EK-RA8D2's Cortex-M85 and Cortex-M33 meet, stated once.
@ k_ra8_board_cpu1_sram_size_bytes
64 KiB CPU1 private bank.
@ k_ra8_board_cpu1_sram_base
CPU1's private 64 KiB bank at the top of on-chip SRAM: .data, .bss and the M33 main stack.
@ k_ra8_board_shared_ram_base
Start of SRAM2: the CPU0 <-> CPU1 meeting window.
Boot entry points shared between a vector table and its startup code.
Cortex-M85 L1 cache maintenance, enable/disable, and I-cache invalidate.
void ra8_cache_icache_enable(void)
Invalidate then enable the Cortex-M85 L1 instruction cache (CCR.IC).
Definition ra8_cache.c:260
void ra8_cache_dcache_invalidate_all(void)
Invalidate the entire D-cache by set/way.
Definition ra8_cache.c:243
void ra8_cache_dcache_enable(void)
Invalidate then enable the Cortex-M85 L1 data cache (CCR.DC).
Definition ra8_cache.c:286
@ k_ra8_mpu_ctrl_enable
RA8 MPU control enable.
@ k_ra8_mpu_ctrl_privdefena
RA8 MPU control privdefena.