|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
Dual-core (CPU0 / CPU1) lifecycle helper – public API. More...
Go to the source code of this file.
Enumerations | |
| enum | ra8_dual_core_addr_t : uintptr_t { k_ra8_dual_core_ctrl_base_addr = 0x4000F000UL } |
| Base address of the CPU control register window used for secondary-core lifecycle management. More... | |
| enum | ra8_dual_core_off_t : uint16_t { k_ra8_dual_core_off_cpu1_initvtor = 0x044U , k_ra8_dual_core_off_cpu1_waitcr = 0x054U , k_ra8_dual_core_off_cpu1_actcsr = 0x064U } |
| Offsets within the CPU_CTRL window for the CPU1 lifecycle registers (HUM Ch 2.9.1 p 128-130, section indices 2.9.1.7 / 2.9.1.8 / 2.9.1.9). More... | |
| enum | ra8_dual_core_field_t : uint16_t { k_ra8_dual_core_waitcr_cpuwait_mask = (1U << 0) , k_ra8_dual_core_actcsr_actreq_mask = (1U << 0) , k_ra8_dual_core_actcsr_act_mask = (1U << 7) , k_ra8_dual_core_actcsr_key_shift = 8U , k_ra8_dual_core_actcsr_key_value = 0xA5U } |
| Bit positions inside CPU1WAITCR / CPU1ACTCSR. More... | |
| enum | ra8_dual_core_const_t : uint32_t { k_ra8_dual_core_release_poll_max = 1000000U } |
| Tunable constants for the bounded poll loops. More... | |
Functions | |
| ra8_err_t | ra8_cpu1_release (void *entry, void *sp) |
| Release CPU1 (Cortex-M33) from reset and start it executing. | |
| ra8_err_t | ra8_cpu1_halt (void) |
| Park CPU1 by asserting CPU1WAITCR.CPUWAIT. | |
| bool | ra8_cpu1_is_running (void) |
| Return whether CPU1 is currently fetching instructions. | |
Dual-core (CPU0 / CPU1) lifecycle helper – public API.
The Renesas RA8D2 ships two Arm cores – a Cortex-M85 primary (CPU0) at 1 GHz and a Cortex-M33 secondary (CPU1) at 250 MHz. The secondary core boots held in a power-gated reset/wait state. CPU0 firmware is responsible for installing the CPU1 reset vector address and then issuing an activation request that takes CPU1 out of reset.
Register map (HUM Ch 2.9.1 "CPU control registers" p 128-130 and Ch 2.6.1.1 "Boot CPU Selection" p 117):
The earlier draft of this driver used Renesas-FSP-style names (LPCSR / VTORC1 / MSPC1 at SYSC base 0x4001_E000); those registers do not exist in the RA8D2 HUM and the hardware silently dropped every write, so CPU1 never came out of reset. The cpu1_pingpong HIL gate caught this when g_cpu1_pingpong_match stayed at zero for the entire 5 s probe window.
Definition in file ra8_dual_core.h.
| enum ra8_dual_core_addr_t : uintptr_t |
Base address of the CPU control register window used for secondary-core lifecycle management.
The HUM lists both a Secure (0x4000_F000) and Non-Secure (0x5000_F000) alias for this window; this driver uses the Secure alias because CPU1 lifecycle is owned by Secure firmware on this project (CPUSAR.CPUSA1 defaults Secure).
| Enumerator | |
|---|---|
| k_ra8_dual_core_ctrl_base_addr | CPU_CTRL Secure base. |
Definition at line 62 of file ra8_dual_core.h.
| enum ra8_dual_core_const_t : uint32_t |
Tunable constants for the bounded poll loops.
| Enumerator | |
|---|---|
| k_ra8_dual_core_release_poll_max | Bounded poll iterations. |
Definition at line 99 of file ra8_dual_core.h.
| enum ra8_dual_core_field_t : uint16_t |
Bit positions inside CPU1WAITCR / CPU1ACTCSR.
HUM Ch 2.9.1.8 p 129 – CPU1WAITCR.CPUWAIT @ bit 0. HUM Ch 2.9.1.9 p 129-130 – CPU1ACTCSR.ACTREQ @ bit 0 (W), ACT @ bit 7 (R). Writes to CPU1ACTCSR require KEY=0xA5 in bits 15:8.
Definition at line 87 of file ra8_dual_core.h.
| enum ra8_dual_core_off_t : uint16_t |
Offsets within the CPU_CTRL window for the CPU1 lifecycle registers (HUM Ch 2.9.1 p 128-130, section indices 2.9.1.7 / 2.9.1.8 / 2.9.1.9).
| Enumerator | |
|---|---|
| k_ra8_dual_core_off_cpu1_initvtor | CPU1INITVTOR (32-bit). |
| k_ra8_dual_core_off_cpu1_waitcr | CPU1WAITCR (8-bit). |
| k_ra8_dual_core_off_cpu1_actcsr | CPU1ACTCSR (16-bit). |
Definition at line 72 of file ra8_dual_core.h.
|
nodiscard |
Park CPU1 by asserting CPU1WAITCR.CPUWAIT.
RA8D2 does not document a clean deactivation path once CPU1ACTCSR.ACT has gone to 1, so this driver stalls CPU1 by writing CPUWAIT=1 instead. The ACT bit may still read 1 (CPU1 remains powered/clocked) but no instructions retire. ra8_cpu1_is_running() will return false after this call.
| k_ra8_ok | CPU1 stalled. |
| k_ra8_err_not_supported | Caller is not CPU0. |
See ra8_dual_core.h for the public contract. The RA8D2 HUM does not document a clean "go back to inactive" transition for the already-activated secondary core, so this driver stalls CPU1 by writing CPUWAIT=1. The chip remains powered/clocked but no instructions retire on the M33. ra8_cpu1_is_running() returns false while CPUWAIT is asserted.
| k_ra8_ok | CPU1 stalled. |
| k_ra8_err_not_supported | Caller is not CPU0. |
Definition at line 561 of file ra8_dual_core.c.
References internal_is_cpu0(), internal_waitcr_write(), k_ra8_dual_core_waitcr_cpuwait_mask, k_ra8_err_not_supported, k_ra8_ok, ra8_log_error, and s_tag.
| bool ra8_cpu1_is_running | ( | void | ) |
Return whether CPU1 is currently fetching instructions.
A truth-table of (ACT, CPUWAIT) -> running: (0, x) -> false (not yet activated / power-gated) (1, 0) -> true (out of reset, running) (1, 1) -> false (out of reset, stalled by CPUWAIT)
| true | CPU1 is fetching instructions. |
| false | CPU1 is in the stopped or stalled state. |
Combines two reads: CPU1ACTCSR.ACT tells us the core has been activated (out of power-gating), and CPU1WAITCR.CPUWAIT tells us whether the application has subsequently stalled it. CPU1 is "running" only when ACT=1 and CPUWAIT=0.
| true | CPU1 active and not stalled. |
| false | CPU1 inactive, or active but CPUWAIT=1. |
Definition at line 596 of file ra8_dual_core.c.
References internal_actcsr_read(), internal_waitcr_read(), k_ra8_dual_core_actcsr_act_mask, and k_ra8_dual_core_waitcr_cpuwait_mask.
|
nodiscard |
Release CPU1 (Cortex-M33) from reset and start it executing.
Writes the vector-table base into CPU1INITVTOR, clears CPU1WAITCR.CPUWAIT (so CPU1 starts immediately rather than stalling), then writes (KEY << 8 | ACTREQ) into CPU1ACTCSR and bounded-polls CPU1ACTCSR.ACT for the active transition. The Cortex-M33 fetches its initial MSP from the first word of the vector table at entry (Armv8-M reset behaviour), so sp is validated for alignment but does not drive a separate register write – the application is responsible for placing the stack-top value at entry[0].
| [in] | entry | CPU1 reset vector base (128-byte aligned). The first word at this address must be the initial MSP. |
| [in] | sp | CPU1 initial main stack pointer (8-byte aligned). Validated only; the M33 reads SP from entry[0]. |
| k_ra8_ok | Core released and confirmed active. |
| k_ra8_err_null_ptr | entry or sp was NULL. |
| k_ra8_err_invalid_arg | entry or sp mis-aligned. |
| k_ra8_err_not_supported | Caller is not CPU0. |
| k_ra8_err_timeout | ACTCSR.ACT did not assert within the bounded poll budget. |
See ra8_dual_core.h for the full public contract. This implementation validates entry and sp (non-NULL, alignment), confirms the caller is CPU0, programs CPU1INITVTOR, clears CPU1WAITCR.CPUWAIT so CPU1 runs immediately on activation, then issues a key-protected ACTREQ via CPU1ACTCSR and bounded-polls ACTCSR.ACT for the active transition. The Cortex-M33 reads its initial SP from the first word of the vector table at entry (Armv8-M reset behaviour), so the sp argument is validated for alignment only – ensuring the caller has actually populated entry[0] with the intended stack top is the application's responsibility.
| [in] | entry | CPU1 reset vector base, 128-byte aligned. |
| [in] | sp | CPU1 initial main stack pointer, 8-byte aligned. |
| k_ra8_ok | CPU1 released and observed active. |
| k_ra8_err_null_ptr | entry or sp was NULL. |
| k_ra8_err_invalid_arg | Alignment check failed. |
| k_ra8_err_not_supported | Caller is not CPU0. |
| k_ra8_err_timeout | ACTCSR.ACT did not assert within bound. |
Definition at line 494 of file ra8_dual_core.c.
References internal_actcsr_write(), internal_initvtor_write(), internal_is_cpu0(), internal_wait_act_set(), internal_waitcr_write(), k_ra8_dual_core_actcsr_actreq_mask, k_ra8_dual_core_actcsr_key_shift, k_ra8_dual_core_actcsr_key_value, k_ra8_dual_core_align_sp, k_ra8_dual_core_align_vtor, k_ra8_err_invalid_arg, k_ra8_err_not_supported, k_ra8_err_null_ptr, ra8_log_error, and s_tag.
Referenced by main().