|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
CPU1 (Cortex-M33) lifecycle helper – implementation. More...
#include "ra8_dual_core.h"#include <stdint.h>#include "ra8_attributes.h"#include "ra8_check.h"#include "ra8_err.h"#include "ra8_hw_err.h"#include "ra8_log.h"Go to the source code of this file.
Enumerations | |
| enum | dc_mask_t : uint16_t { k_dc_byte_mask = 0xFFU } |
| Low-byte mask for ACTCSR field extraction. More... | |
| enum | ra8_dual_core_align_t : uint32_t { k_ra8_dual_core_align_vtor = 128U , k_ra8_dual_core_align_sp = 8U } |
Functions | |
| static volatile uint16_t * | internal_actcsr_ptr (void) |
| Address of CPU1ACTCSR on the live chip. | |
| static volatile uint8_t * | internal_waitcr_ptr (void) |
| Address of CPU1WAITCR on the live chip. | |
| static volatile uint32_t * | internal_initvtor_ptr (void) |
| Address of CPU1INITVTOR on the live chip. | |
| static uint16_t | internal_actcsr_read (void) |
| Read the live CPU1ACTCSR register on the chip. | |
| static void | internal_actcsr_write (uint16_t value) |
| Write the live CPU1ACTCSR register on the chip. | |
| static void | internal_waitcr_write (uint8_t value) |
| Write the live CPU1WAITCR register on the chip. | |
| static uint8_t | internal_waitcr_read (void) |
| Read the live CPU1WAITCR register on the chip. | |
| static void | internal_initvtor_write (uint32_t value) |
| Write the live CPU1INITVTOR register on the chip. | |
| static bool | internal_is_cpu0 (void) |
| Compile-time check that the caller is CPU0. | |
| static ra8_err_t | internal_wait_act_set (void) |
| Bounded poll for CPU1ACTCSR.ACT to assert after an ACTREQ. | |
| 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. | |
Variables | |
| static const char *const | s_tag = "ra8_dual_core" |
| Log tag for ra8_dual_core diagnostics. | |
CPU1 (Cortex-M33) lifecycle helper – implementation.
See ra8_dual_core.h for the public contract. This file implements the three lifecycle entry points (release / halt / is_running) on top of the CPU_CTRL register window's CPU1INITVTOR / CPU1WAITCR / CPU1ACTCSR registers (HUM Ch 2.9.1 p 128-130). Earlier drafts used SYSC.LPCSR / VTORC1 / MSPC1 register addresses that belong to a different RA family and do not exist on RA8D2; those silently dropped writes, which is what made cpu1_pingpong's CPU1 stay in reset forever.
Host (RA8_OFF_TARGET) builds back the registers with a small static state struct so unit tests can drive the API without a chip.
Definition in file ra8_dual_core.c.
| enum dc_mask_t : uint16_t |
Low-byte mask for ACTCSR field extraction.
| Enumerator | |
|---|---|
| k_dc_byte_mask | Dc byte mask. |
Definition at line 39 of file ra8_dual_core.c.
| enum ra8_dual_core_align_t : uint32_t |
| Enumerator | |
|---|---|
| k_ra8_dual_core_align_vtor | Armv8-M VTOR alignment requirement. |
| k_ra8_dual_core_align_sp | AAPCS main-stack alignment. |
Definition at line 43 of file ra8_dual_core.c.
|
inlinestatic |
Address of CPU1ACTCSR on the live chip.
Definition at line 223 of file ra8_dual_core.c.
References k_ra8_dual_core_ctrl_base_addr, k_ra8_dual_core_off_cpu1_actcsr, and RA8_INTERNAL.
Referenced by internal_actcsr_read(), and internal_actcsr_write().
|
inlinestatic |
Read the live CPU1ACTCSR register on the chip.
Single-volatile load via the typed accessor. Used by the ra8_cpu1_release ACT-poll and by ra8_cpu1_is_running; never mutates the register so reentrant reads are safe.
| 0..UINT16_MAX | Whatever the controller exposes; bit 7 latches once ACTREQ has been honored. |
Definition at line 281 of file ra8_dual_core.c.
References internal_actcsr_ptr(), and RA8_INTERNAL.
Referenced by internal_wait_act_set(), and ra8_cpu1_is_running().
|
inlinestatic |
Write the live CPU1ACTCSR register on the chip.
The hardware silently drops writes that do not present KEY[7:0] == 0xA5 in the upper byte (HUM Ch 2.9.1.9 p 130).
| [in] | value | New 16-bit ACTCSR value (KEY | ACTREQ). |
Definition at line 302 of file ra8_dual_core.c.
References internal_actcsr_ptr(), and RA8_INTERNAL.
Referenced by ra8_cpu1_release().
|
inlinestatic |
Address of CPU1INITVTOR on the live chip.
Definition at line 255 of file ra8_dual_core.c.
References k_ra8_dual_core_ctrl_base_addr, k_ra8_dual_core_off_cpu1_initvtor, and RA8_INTERNAL.
Referenced by internal_initvtor_write().
|
inlinestatic |
Write the live CPU1INITVTOR register on the chip.
Programs the CPU1 reset vector base. The Cortex-M33 latches INITVTOR into its VTOR on the next reset-release edge and fetches the initial MSP from offset 0 of the table.
| [in] | value | New 32-bit INITVTOR value (CPU1 vector table base). |
Definition at line 371 of file ra8_dual_core.c.
References internal_initvtor_ptr(), and RA8_INTERNAL.
Referenced by ra8_cpu1_release().
|
inlinestatic |
Compile-time check that the caller is CPU0.
On the M33 build (RA8_BUILD_FOR_CPU1) we refuse to touch the CPU1 lifecycle registers; CPU1 cannot release or stall itself through this API. On the M85 / host build there is no "other core" so we always return true.
| true | Caller is the M85 primary (or host build). |
| false | Caller is the M33 secondary (RA8_BUILD_FOR_CPU1). |
Definition at line 399 of file ra8_dual_core.c.
References RA8_INTERNAL.
Referenced by ra8_cpu1_halt(), and ra8_cpu1_release().
|
static |
Bounded poll for CPU1ACTCSR.ACT to assert after an ACTREQ.
Spins up to k_ra8_dual_core_release_poll_max reads of CPU1ACTCSR waiting for the ACT bit, extracted from ra8_cpu1_release to keep that function within the NASA Power of 10 Rule 4 line budget. On the host build nothing self-sets ACT, so the ra8_fake_mmio fault seam owns the loop-exit decision – first-poll success unless a test arms a fault on the ACTCSR key to drive the retry / timeout legs.
| k_ra8_ok | ACT observed set within the budget. |
| k_ra8_err_timeout | ACT stayed clear for the full budget. |
Definition at line 431 of file ra8_dual_core.c.
References internal_actcsr_read(), k_ra8_dual_core_actcsr_act_mask, k_ra8_dual_core_release_poll_max, k_ra8_err_timeout, k_ra8_ok, RA8_INTERNAL, ra8_log_error, and s_tag.
Referenced by ra8_cpu1_release().
|
inlinestatic |
Address of CPU1WAITCR on the live chip.
Definition at line 239 of file ra8_dual_core.c.
References k_ra8_dual_core_ctrl_base_addr, k_ra8_dual_core_off_cpu1_waitcr, and RA8_INTERNAL.
Referenced by internal_waitcr_read(), and internal_waitcr_write().
|
inlinestatic |
Read the live CPU1WAITCR register on the chip.
Single-volatile load. Drives the stalled-vs-running query in ra8_cpu1_is_running.
| 0..1 | Bit 0 reflects the CPUWAIT gate; other bits read as zero per HUM Ch 2.9.1.10 p 130. |
Definition at line 349 of file ra8_dual_core.c.
References internal_waitcr_ptr(), and RA8_INTERNAL.
Referenced by ra8_cpu1_is_running().
|
inlinestatic |
Write the live CPU1WAITCR register on the chip.
Single-volatile store via the typed accessor. CPU1 stays stalled while WAITCR.CPUWAIT == 1; clearing the bit lets the released core start fetching at CPU1INITVTOR.
| [in] | value | New 8-bit WAITCR value (bit 0 = CPUWAIT). |
Definition at line 325 of file ra8_dual_core.c.
References internal_waitcr_ptr(), and RA8_INTERNAL.
Referenced by ra8_cpu1_halt(), and ra8_cpu1_release().
|
nodiscard |
Park CPU1 by asserting CPU1WAITCR.CPUWAIT.
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.
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.
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().
|
static |
Log tag for ra8_dual_core diagnostics.
Definition at line 36 of file ra8_dual_core.c.