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

Cortex-M85 / RA8D2 core bring-up (called from Reset_Handler). More...

#include <stdint.h>
#include "ra8_boot_entry.h"
#include "ra8_cgc.h"
#include "trustzone_init.h"
Include dependency graph for system_init.c:

Go to the source code of this file.

Enumerations

enum  ra8_core_addr_t : uintptr_t {
  k_ra8_scb_vtor_addr = 0xE000ED08UL ,
  k_ra8_scb_ccr_addr = 0xE000ED14UL ,
  k_ra8_scb_shcsr_addr = 0xE000ED24UL ,
  k_ra8_scb_cpacr_addr = 0xE000ED88UL ,
  k_ra8_scb_nsacr_addr = 0xE000ED8CUL ,
  k_ra8_scb_iciallu = 0xE000EF50UL ,
  k_ra8_scb_dciallu = 0xE000EF58UL ,
  k_ra8_scb_csselr = 0xE000ED84UL ,
  k_ra8_scb_ccsidr = 0xE000ED80UL ,
  k_ra8_scb_dcisw = 0xE000EF60UL ,
  k_ra8_fpu_fpccr_addr = 0xE000EF34UL ,
  k_ra8_nvic_aircr = 0xE000ED0CUL ,
  k_ra8_mpu_type_addr = 0xE000ED90UL ,
  k_ra8_mpu_ctrl_addr = 0xE000ED94UL ,
  k_ra8_mpu_rnr_addr = 0xE000ED98UL ,
  k_ra8_mpu_rbar_addr = 0xE000ED9CUL ,
  k_ra8_mpu_rlar_addr = 0xE000EDA0UL ,
  k_ra8_mpu_mair0_addr = 0xE000EDC0UL ,
  k_ra8_mpu_mair1_addr = 0xE000EDC4UL
}
enum  : uint32_t {
  k_ra8_rbar_attr_ro_x = 0x02U ,
  k_ra8_rbar_attr_rw_xn = 0x03U ,
  k_ra8_rbar_attr_device_rw = 0x23U ,
  k_ra8_mpu_rlar_enable = 1UL << 0
}
 Programme and enable the Cortex-M85 core MPU. More...
enum  : uint32_t {
  k_ra8_mpu_mram_base = 0x02000000UL ,
  k_ra8_mpu_mram_limit = 0x020FFFE0UL ,
  k_ra8_mpu_sram_base = 0x22000000UL ,
  k_ra8_mpu_sram_limit = 0x221FFFE0UL ,
  k_ra8_mpu_sdram_base = 0x68000000UL ,
  k_ra8_mpu_sdram_limit = 0x6BFFFFE0UL ,
  k_ra8_mpu_peri_base = 0x40000000UL ,
  k_ra8_mpu_peri_limit = 0x47FFFFE0UL
}

Functions

static uint32_t internal_read32 (uintptr_t addr)
static void internal_write32 (uintptr_t addr, uint32_t value)
static void internal_dsb (void)
static void internal_isb (void)
static void internal_disable_irq (void)
static void internal_set_vtor (void)
 Point VTOR at the physical vector table base.
static void internal_enable_fpu (void)
 Grant full access to CP10 / CP11 (the FPU coprocessors).
static void internal_enable_fpu_lazy_stack (void)
 Turn on FPU lazy stacking (FPCCR.LSPEN = 1, ASPEN = 1).
static void internal_enable_icache (void)
 Invalidate and enable the Cortex-M85 I-cache.
static void internal_enable_dcache (void)
 Invalidate and enable the Cortex-M85 D-cache.
static void internal_enable_branch_predictor (void)
 Enable branch-target prediction (CCR.BP on Cortex-M85).
static void internal_set_priority_grouping (void)
 Set NVIC priority grouping to 4 preempt bits / 0 sub-priority.
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_mpu_init (void)
 Programme and enable the Cortex-M85 core MPU.
static void internal_halt_secure_clock_fault (void)
 Park forever after a Secure clock-tree bring-up failure.
void SystemInit (void)
 Earliest C code the image runs: bring the core up before RAM init.

Variables

const uint32_t g_ra8_vector_table_start []
uint32_t g_ra8_ls_stack_top

Detailed Description

Cortex-M85 / RA8D2 core bring-up (called from Reset_Handler).

Tag
[Ring 1 / Boot] {World: S}
TrustZone:
Unlike the sibling usb_cdc_echo app, this variant calls ra8_trustzone_init so that the SAU is programmed before any NS code can run. The NS-side main() then crosses NS->S only via the cmse_nonsecure_entry veneers in libs/ra8_nsc/.

SystemInit() follows the CMSIS naming convention and runs as the first C function out of reset, before Reset_Handler copies .data or zeroes .bss. Its responsibilities are strictly CPU-core level – anything peripheral-bus-side belongs in ra8_infrastructure_init() called from main() after the C runtime is live.

Bring-up sequence

  1. Set VTOR to the physical address of the vector table (so that linker relocations and later TrustZone / bootloader hand-offs work).
  2. Enable CP10 / CP11 so the FPU is usable before any floating-point instruction runs.
  3. Enable FPU lazy stacking (FPCCR.LSPEN) so ISRs do not pay the full FP-state save cost unless they touch the FPU.
  4. Enable the I-cache and D-cache (Cortex-M85 has both). Without this the core runs at a small fraction of its rated speed.
  5. Enable the branch-target predictor (CCR.BP).
  6. Programme NVIC priority grouping to 4 bits preempt / 0 bits sub (the standard embedded pattern).
  7. Disable interrupts until the application is ready – this mirrors CMSIS convention. main() re-enables via __enable_irq() once all drivers are up.

The function is C, not naked asm, so stack, .data and .bss must already be usable. Reset_Handler loads SP from the vector table before calling SystemInit(), and now copies .data + zeroes .bss BEFORE the SystemInit() call, so any global state this function establishes survives into main(). This ordering is load-bearing: ra8_cgc_init() (called below) publishes the settled clock rates into a .data-resident cache in ra8_cgc; if the .data copy ran after SystemInit() it would clobber that cache back to the MOCO boot default and the SCI8 console would then read a stale ~8 MHz PCLKA and refuse to initialise.

Definition in file system_init.c.

Enumeration Type Documentation

◆ anonymous enum

anonymous enum : uint32_t

Programme and enable the Cortex-M85 core MPU.

Installs four regions and enables the MPU with PRIVDEFENA so privileged mode still sees the default memory map for anything not explicitly covered:

  • Region 0: MRAM (0x02000000, 1 MiB) – read + execute, inner/outer cacheable.
  • Region 1: SRAM (0x22000000, 2 MiB) – read + write, no execute.
  • Region 2: SDRAM (0x68000000, 64 MiB) – read + write, no execute.
  • Region 3: Peripherals (0x40000000, 128 MiB) – read + write, device memory, no execute.

Attribute indirection table:

  • MAIR0[0] = 0xFF (Normal inner + outer write-back / write-alloc).
  • MAIR0[1] = 0x44 (Normal non-cacheable).
  • MAIR0[2] = 0x04 (Device-nGnRE).

Region base + limit addresses are encoded per ARMv8-M main-profile PMSAv8 rules: low 5 bits of RBAR hold AP[2:0] / SH[4:3] / XN, and RLAR holds the upper bound OR the enable flag in bit 0.

Enumerator
k_ra8_rbar_attr_ro_x 

AP=RO, SH=none, XN=0.

k_ra8_rbar_attr_rw_xn 

AP=RW, SH=none, XN=1.

k_ra8_rbar_attr_device_rw 

AP=RW, SH=outer sh, XN=1, MAIR idx = device.

k_ra8_mpu_rlar_enable 

RA8 MPU rlar enable.

Definition at line 259 of file system_init.c.

◆ anonymous enum

anonymous enum : uint32_t
Enumerator
k_ra8_mpu_mram_base 

1 MiB MRAM code region.

k_ra8_mpu_mram_limit 

RA8 MPU MRAM limit.

k_ra8_mpu_sram_base 

2 MiB ECC SRAM region.

k_ra8_mpu_sram_limit 

RA8 MPU SRAM limit.

k_ra8_mpu_sdram_base 

64 MiB external SDRAM.

k_ra8_mpu_sdram_limit 

RA8 MPU SDRAM limit.

k_ra8_mpu_peri_base 

Peripheral bus window base.

k_ra8_mpu_peri_limit 

RA8 MPU peri limit.

Definition at line 268 of file system_init.c.

◆ ra8_core_addr_t

enum ra8_core_addr_t : uintptr_t
Enumerator
k_ra8_scb_vtor_addr 

Vector Table Offset Register.

k_ra8_scb_ccr_addr 

Configuration and Control Register.

k_ra8_scb_shcsr_addr 

System Handler Control and State.

k_ra8_scb_cpacr_addr 

Coprocessor Access Control.

k_ra8_scb_nsacr_addr 

Non-secure Access Control.

k_ra8_scb_iciallu 

ICIALLU – invalidate I-cache.

k_ra8_scb_dciallu 

DCIALLU – invalidate D-cache (sets only).

k_ra8_scb_csselr 

Cache Size Selection Register.

k_ra8_scb_ccsidr 

Cache Size ID Register.

k_ra8_scb_dcisw 

D-cache Invalidate by Set/Way.

k_ra8_fpu_fpccr_addr 

FPU Context Control Register.

k_ra8_nvic_aircr 

Application Interrupt and Reset Ctrl.

k_ra8_mpu_type_addr 

MPU Type Register.

k_ra8_mpu_ctrl_addr 

MPU Control Register.

k_ra8_mpu_rnr_addr 

MPU Region Number.

k_ra8_mpu_rbar_addr 

MPU Region Base Address.

k_ra8_mpu_rlar_addr 

MPU Region Limit Address.

k_ra8_mpu_mair0_addr 

MPU Attribute Indirection 0.

k_ra8_mpu_mair1_addr 

MPU Attribute Indirection 1.

Definition at line 67 of file system_init.c.

Function Documentation

◆ internal_disable_irq()

void internal_disable_irq ( void )
inlinestatic

Definition at line 120 of file system_init.c.

◆ internal_dsb()

void internal_dsb ( void )
inlinestatic

Definition at line 106 of file system_init.c.

◆ internal_enable_branch_predictor()

void internal_enable_branch_predictor ( void )
static

Enable branch-target prediction (CCR.BP on Cortex-M85).

< RA8 ccr bp.

Definition at line 213 of file system_init.c.

References internal_dsb(), internal_isb(), internal_read32(), internal_write32(), and k_ra8_scb_ccr_addr.

◆ internal_enable_dcache()

void internal_enable_dcache ( void )
static

Invalidate and enable the Cortex-M85 D-cache.

The invalidate-by-set/way loop is omitted here for brevity – on the RA8D2 the boot ROM leaves the D-cache with all lines marked invalid, so a bulk CCR.DC = 1 write is safe. A production build should add a real CCSIDR-driven loop.

< RA8 ccr dc.

Definition at line 200 of file system_init.c.

References internal_dsb(), internal_isb(), internal_read32(), internal_write32(), and k_ra8_scb_ccr_addr.

◆ internal_enable_fpu()

void internal_enable_fpu ( void )
static

Grant full access to CP10 / CP11 (the FPU coprocessors).

< RA8 cpacr cp10 cp11 full access.

Definition at line 146 of file system_init.c.

References internal_dsb(), internal_isb(), internal_read32(), internal_write32(), and k_ra8_scb_cpacr_addr.

◆ internal_enable_fpu_lazy_stack()

void internal_enable_fpu_lazy_stack ( void )
static

Turn on FPU lazy stacking (FPCCR.LSPEN = 1, ASPEN = 1).

< RA8 fpccr lspen.

< RA8 fpccr aspen.

Definition at line 161 of file system_init.c.

References internal_read32(), internal_write32(), and k_ra8_fpu_fpccr_addr.

◆ internal_enable_icache()

void internal_enable_icache ( void )
static

Invalidate and enable the Cortex-M85 I-cache.

< RA8 ccr ic.

Definition at line 175 of file system_init.c.

References internal_dsb(), internal_isb(), internal_read32(), internal_write32(), k_ra8_scb_ccr_addr, and k_ra8_scb_iciallu.

◆ internal_halt_secure_clock_fault()

void internal_halt_secure_clock_fault ( void )
static

Park forever after a Secure clock-tree bring-up failure.

Reached only when ra8_cgc_init fails inside SystemInit. The NS-side NSC CGC veneers require PLL1 locked, and ra8_trustzone_init BLXNS-es into the NS world without returning – so a failed clock bring-up must NOT proceed to the world switch, which would run NS code on a dead clock tree. Parks in a wfi loop at this named, non-inlined symbol so a debugger or HIL probe can pin the secure-boot clock failure; the only escape is a watchdog or debugger reset.

Returns
Does not return.
Precondition
Reached from SystemInit, before the SAU + BLXNS world switch.
Global interrupts are masked (ra8_boot_disable_irq ran first).
Postcondition
The CPU is parked with interrupts masked; no NS code runs.
No global state is touched (safe before .data/.bss init).
Note
Not thread-safe; single-threaded boot only.
Since
0.1.0

Definition at line 346 of file system_init.c.

◆ internal_isb()

void internal_isb ( void )
inlinestatic

Definition at line 113 of file system_init.c.

◆ internal_mpu_init()

◆ internal_mpu_set_region()

void internal_mpu_set_region ( uint32_t region,
uint32_t base_attr,
uint32_t limit_enable )
static

Program a single MPU region via RNR/RBAR/RLAR.

Definition at line 282 of file system_init.c.

References internal_write32(), k_ra8_mpu_rbar_addr, k_ra8_mpu_rlar_addr, and k_ra8_mpu_rnr_addr.

◆ internal_read32()

uint32_t internal_read32 ( uintptr_t addr)
inlinestatic

Definition at line 96 of file system_init.c.

◆ internal_set_priority_grouping()

void internal_set_priority_grouping ( void )
static

Set NVIC priority grouping to 4 preempt bits / 0 sub-priority.

< Required write key.

< PRIGROUP = 3 -> 4 bits.

Definition at line 226 of file system_init.c.

References internal_write32(), and k_ra8_nvic_aircr.

◆ internal_set_vtor()

void internal_set_vtor ( void )
static

Point VTOR at the physical vector table base.

Definition at line 135 of file system_init.c.

References g_ra8_vector_table_start, internal_write32(), and k_ra8_scb_vtor_addr.

◆ internal_write32()

void internal_write32 ( uintptr_t addr,
uint32_t value )
inlinestatic

Definition at line 101 of file system_init.c.

◆ SystemInit()

void SystemInit ( void )

Earliest C code the image runs: bring the core up before RAM init.

Called by Reset_Handler before .data is copied and .bss is zeroed, so it must not touch initialised or zero-initialised statics. Each image supplies its own definition – the shared board one under the board boot directories, or an application-local system_init.c where the clock tree or memory map diverges.

The name is the CMSIS convention; the startup code reaches it by that name, which is why it has external linkage.

Precondition
The CPU is at the reset vector with interrupts masked.
.data has not been copied and .bss has not been zeroed.
Postcondition
The clock tree, cache and memory controller are configured.
It is safe for Reset_Handler to initialise RAM and call main.
Note
Not thread-safe; single-threaded reset context only.
Warning
Must not read or write any static that startup has yet to initialise – at this point they hold whatever SRAM held.
See also
Default_Handler()
Since
0.1.0

Definition at line 362 of file system_init.c.

References internal_disable_irq(), internal_enable_branch_predictor(), internal_enable_dcache(), internal_enable_fpu(), internal_enable_fpu_lazy_stack(), internal_enable_icache(), internal_halt_secure_clock_fault(), internal_mpu_init(), internal_set_priority_grouping(), internal_set_vtor(), k_ra8_ok, ra8_cgc_init(), and ra8_trustzone_init().

Variable Documentation

◆ g_ra8_ls_stack_top

uint32_t g_ra8_ls_stack_top
extern

◆ g_ra8_vector_table_start

const uint32_t g_ra8_vector_table_start[]
extern

Definition at line 294 of file vector_table.c.