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

CPU1 (Cortex-M33 secondary core) image: hold the page in low power. More...

#include <stdint.h>
#include "lowpower_holdpage.h"
Include dependency graph for cpu1_main.c:

Go to the source code of this file.

Enumerations

enum  m33_port_addr_t : uintptr_t {
  k_port6_pcntr1_addr = 0x404000C0U ,
  k_port0_pcntr2_addr = 0x40400004U
}
 MMIO addresses of the PORT registers the M33 hold loop drives. More...
enum  m33_hold_const_t : uint32_t {
  k_led1_pdr_out = 0x00000001U ,
  k_led1_podr_on = 0x00010000U ,
  k_sw1_pidr_bit = 9U ,
  k_sw1_released = 1U ,
  k_sw1_pressed = 0U ,
  k_hold_spins = 3000000U
}
 PCNTR field constants and the hold-loop delay bound. More...

Functions

void cpu1_reset_handler (void)
 CPU1 reset handler: minimal C-runtime init, then enter the hold loop.
static void cpu1_hold_page (void)
 CPU1 application loop: hold the page, blink the active-core LED, poll SW1.
static void cpu1_fault_handler (void)
 CPU1 default fault handler: park the core.

Variables

uint32_t g_ra8_ls_cpu1_stack_top
 CPU1 stack top (slot 0 of the M33 vector table).
uint32_t g_ra8_ls_cpu1_data_start
 CPU1 .data run-region start (in SRAM_CPU1).
uint32_t g_ra8_ls_cpu1_data_end
 CPU1 .data run-region end.
uint32_t g_ra8_ls_cpu1_data_load
 CPU1 .data load image (in MRAM_CPU1).
uint32_t g_ra8_ls_cpu1_bss_start
 CPU1 .bss start (in SRAM_CPU1).
uint32_t g_ra8_ls_cpu1_bss_end
 CPU1 .bss end.
const uintptr_t g_cpu1_vector_table []

Detailed Description

CPU1 (Cortex-M33 secondary core) image: hold the page in low power.

Tag
[Ring 1 / app] {World: NS}

This is the firmware that runs on the RA8D2's second core, the Cortex-M33, for the #150 low-power-mode demo. It is compiled as a wholly separate ELF (-mcpu=cortex-m33) and embedded into the M85 ELF as a .cpu1_image blob; the M85 "renders" page 0, releases this core via ra8_cpu1_release (HUM Ch 2.9.1), and PARKS. From then on the M33 is the live core.

Its job is the e-reader's idle / hold loop – everything the device spends almost all its time doing – run on the slow core at a fraction of the power:

  1. Light board LED1 (BLUE, P600 = PORT6 pin 0) as the "active core = M33" indicator. The M85 never drives this pin, so a toggling LED is honest proof the M33 is the core holding the page – on silicon and in the ra8_emulator GPIO/LED view alike.
  2. Service the user switch SW1 (P009) as the page-turn input: on a press edge the M33 advances the held page_num and counts the event in the shared mailbox, without waking the M85.
  3. Bump the mailbox heartbeat each loop so the parked M85 can narrate that the M33 is alive.

Re-rendering a new page is M85-heavy work (ra8_gfx is Helium-tuned, 1 GHz- assuming); the M33 holds the existing page and advances the page number, and waking the M85 for the heavy re-render is the remaining piece tracked in #150.

Note
The M33 deliberately does NOT call ra8_log. ra8_emulator echoes only the primary core's ITM, so an M33 ra8_log line would be invisible; the proof-of-life is the LED + the mailbox heartbeat the M85 narrates.
Only PCNTR1/PCNTR2 are touched. The LED1 / SW1 pins power up routed to PORT, so no PmnPFS / PWPR pin-function setup is needed here.
Since
0.1.0

Definition in file cpu1_main.c.

Enumeration Type Documentation

◆ m33_hold_const_t

enum m33_hold_const_t : uint32_t

PCNTR field constants and the hold-loop delay bound.

PCNTR1 packs the direction latch PDR in its low half and the output latch PODR in its high half, so LED1 (pin 0) is held an output (PDR bit 0) while its level is set by PODR bit 0 (bit 16 of the word). SW1 (PORT0 pin 9) reads back in PIDR bit 9 of PCNTR2; it is active-low (pressed = 0).

Since
0.1.0
Enumerator
k_led1_pdr_out 

PCNTR1 PDR pin 0 = output direction.

k_led1_podr_on 

PCNTR1 PODR pin 0 = drive high (bit 16).

k_sw1_pidr_bit 

SW1 = PORT0 pin 9 (PIDR bit 9).

k_sw1_released 

SW1 active-low: 1 = released (not pressed).

k_sw1_pressed 

SW1 active-low: 0 = pressed.

k_hold_spins 

Bounded busy-delay spins per hold pass.

Definition at line 86 of file cpu1_main.c.

◆ m33_port_addr_t

enum m33_port_addr_t : uintptr_t

MMIO addresses of the PORT registers the M33 hold loop drives.

The PORT block base is 0x40400000 with a 0x20 per-port stride. LED1 (BLUE) is P600 = PORT6 pin 0, so PORT6 PCNTR1 is at 0x404000C0. SW1 is P009 = PORT0 pin 9, read via PORT0 PCNTR2 (the read-only register carrying PIDR) at 0x40400004. (HUM Ch 20 "I/O Ports".)

Since
0.1.0
Enumerator
k_port6_pcntr1_addr 

PORT6 PCNTR1: {PODR[31:16], PDR[15:0]} (LED1).

k_port0_pcntr2_addr 

PORT0 PCNTR2: {EIDR[31:16], PIDR[15:0]} (SW1).

Definition at line 71 of file cpu1_main.c.

Function Documentation

◆ cpu1_fault_handler()

void cpu1_fault_handler ( void )
static

CPU1 default fault handler: park the core.

Every M33 exception slot routes here. The core stops making forward progress; on hardware a watchdog (if enabled) eventually resets.

Returns
This function never returns.
Note
The core spins in place.
Precondition
A hardware fault or unhandled exception occurred.
Entered via the M33 exception entry path.
Postcondition
The M33 makes no further forward progress.
LED1 stops toggling and the heartbeat freezes, observable from the M85.
Note
Shared default for all CPU1 exception vectors.
Since
0.1.0

Definition at line 210 of file cpu1_main.c.

◆ cpu1_hold_page()

void cpu1_hold_page ( void )
static

CPU1 application loop: hold the page, blink the active-core LED, poll SW1.

Each pass: bump the shared mailbox heartbeat (so the parked M85 sees the M33 is alive), read SW1 (P009) and on a press edge advance the held page_num + count the event, then toggle LED1 (the "active core = M33" indicator). A bounded busy-delay paces the loop. The M85 never drives LED1 or page_num after handoff, so this loop's effects prove the M33 owns the page.

Returns
This function never returns.
Note
Control never leaves the hold loop.
Precondition
cpu1_reset_handler has initialised .data/.bss.
The PORT0/PORT6 blocks are reachable; the M85 published the mailbox.
Postcondition
LED1 (PORT6 pin 0) is configured as an output and toggles each pass.
The mailbox heartbeat advances and SW1 presses bump page_num.
Note
Single-threaded; runs in M33 thread mode with no RTOS.
Since
0.1.0

Definition at line 115 of file cpu1_main.c.

References k_hold_spins, k_led1_pdr_out, k_led1_podr_on, k_port0_pcntr2_addr, k_port6_pcntr1_addr, k_sw1_pidr_bit, k_sw1_pressed, k_sw1_released, lowpower_mailbox(), lowpower_mailbox_t::m33_heartbeat, lowpower_mailbox_t::page_num, and lowpower_mailbox_t::sw1_events.

Referenced by cpu1_reset_handler().

◆ cpu1_reset_handler()

void cpu1_reset_handler ( void )

CPU1 reset handler: minimal C-runtime init, then enter the hold loop.

The M33 boots with uninitialised RAM, so before any C code runs this copies .data from its MRAM_CPU1 load image into SRAM_CPU1 and zeroes .bss. The linker exports the region bounds as g_ra8_ls_cpu1_* symbols.

Returns
This function never returns.
Note
Control passes to cpu1_hold_page, which loops forever.
Precondition
Hardware loaded the initial SP from .cpu1_vectors[0].
The M85 released this core via the CPU1ACTCSR handshake.
Postcondition
.data mirrors its MRAM_CPU1 load image.
.bss is zero-filled.
Note
Entered only from the CPU1 vector table; runs in M33 thread mode.
Since
0.1.0

Definition at line 174 of file cpu1_main.c.

References cpu1_hold_page(), g_ra8_ls_cpu1_bss_end, g_ra8_ls_cpu1_bss_start, g_ra8_ls_cpu1_data_end, g_ra8_ls_cpu1_data_load, and g_ra8_ls_cpu1_data_start.

Variable Documentation

◆ g_cpu1_vector_table

const uintptr_t g_cpu1_vector_table[]
Initial value:
= {
(uintptr_t)&cpu1_reset_handler,
(uintptr_t)&cpu1_fault_handler,
(uintptr_t)&cpu1_fault_handler,
(uintptr_t)&cpu1_fault_handler,
(uintptr_t)&cpu1_fault_handler,
(uintptr_t)&cpu1_fault_handler,
(uintptr_t)&cpu1_fault_handler,
}
void cpu1_reset_handler(void)
CPU1 reset handler.
Definition cpu1_main.c:266
uint32_t g_ra8_ls_cpu1_stack_top

Definition at line 231 of file cpu1_main.c.

◆ g_ra8_ls_cpu1_bss_end

uint32_t g_ra8_ls_cpu1_bss_end
extern

CPU1 .bss end.

◆ g_ra8_ls_cpu1_bss_start

uint32_t g_ra8_ls_cpu1_bss_start
extern

CPU1 .bss start (in SRAM_CPU1).

◆ g_ra8_ls_cpu1_data_end

uint32_t g_ra8_ls_cpu1_data_end
extern

CPU1 .data run-region end.

◆ g_ra8_ls_cpu1_data_load

uint32_t g_ra8_ls_cpu1_data_load
extern

CPU1 .data load image (in MRAM_CPU1).

◆ g_ra8_ls_cpu1_data_start

uint32_t g_ra8_ls_cpu1_data_start
extern

CPU1 .data run-region start (in SRAM_CPU1).

◆ g_ra8_ls_cpu1_stack_top

uint32_t g_ra8_ls_cpu1_stack_top
extern

CPU1 stack top (slot 0 of the M33 vector table).