ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
cpu1_main.c
Go to the documentation of this file.
1
42
43#include <stdint.h>
44
45#include "lowpower_holdpage.h"
46
48extern uint32_t g_ra8_ls_cpu1_stack_top;
50extern uint32_t g_ra8_ls_cpu1_data_start;
52extern uint32_t g_ra8_ls_cpu1_data_end;
54extern uint32_t g_ra8_ls_cpu1_data_load;
56extern uint32_t g_ra8_ls_cpu1_bss_start;
58extern uint32_t g_ra8_ls_cpu1_bss_end;
59
60[[noreturn]] void cpu1_reset_handler(void);
61
71typedef enum : uintptr_t {
72 k_port6_pcntr1_addr = 0x404000C0U,
73 k_port0_pcntr2_addr = 0x40400004U,
75
86typedef enum : uint32_t {
87 k_led1_pdr_out = 0x00000001U,
88 k_led1_podr_on = 0x00010000U,
92 k_hold_spins = 3000000U,
94
115[[noreturn]] static void cpu1_hold_page(void)
116{
117 volatile lowpower_mailbox_t* mb = lowpower_mailbox();
118 volatile uint32_t* pcntr1 = (volatile uint32_t*)k_port6_pcntr1_addr;
119 volatile uint32_t* pcntr2 = (volatile uint32_t*)k_port0_pcntr2_addr;
120 uint32_t led = 0U;
121 uint32_t sw1_prev = (uint32_t)k_sw1_released;
122
123 while (1) {
124 for (volatile uint32_t d = 0U; d < (uint32_t)k_hold_spins; d++) {
125 __asm volatile("nop");
126 }
127 mb->m33_heartbeat = mb->m33_heartbeat + 1U;
128
129 /* HUM Ch 20.2 "PCNTR2 : Port Control Register 2" p 841 -- read PIDR; bit 9
130 * is SW1 (P009), active-low (pressed = 0). */
131 const uint32_t pidr = *pcntr2;
132 const uint32_t sw1_now = (pidr >> (uint32_t)k_sw1_pidr_bit) & 1U;
133 /* Detect a fresh press edge (was released, now pressed): a held-page turn
134 * the slow core handles without waking the M85. Split conditions to avoid a
135 * compound boolean decision. */
136 if (sw1_prev == (uint32_t)k_sw1_released) {
137 if (sw1_now == (uint32_t)k_sw1_pressed) {
138 mb->sw1_events = mb->sw1_events + 1U;
139 mb->page_num = mb->page_num + 1U;
140 }
141 }
142 sw1_prev = sw1_now;
143
144 /* Toggle LED1 as the "active core = M33" indicator. */
145 led ^= 1U;
146 uint32_t value = (uint32_t)k_led1_pdr_out;
147 if (led != 0U) {
148 value |= (uint32_t)k_led1_podr_on;
149 }
150 /* HUM Ch 20.2 "PCNTR1 : Port Control Register 1" p 840 -- write {PODR, PDR}:
151 * hold PORT6 pin 0 an output and drive LED1 (BLUE, P600) to the new level. */
152 *pcntr1 = value;
153 }
154}
155
174[[noreturn]] void cpu1_reset_handler(void)
175{
176 uint32_t* dst = &g_ra8_ls_cpu1_data_start;
177 uint32_t* src = &g_ra8_ls_cpu1_data_load;
178 while (dst < &g_ra8_ls_cpu1_data_end) {
179 *dst = *src;
180 dst++;
181 src++;
182 }
183
184 uint32_t* bss = &g_ra8_ls_cpu1_bss_start;
185 while (bss < &g_ra8_ls_cpu1_bss_end) {
186 *bss = 0U;
187 bss++;
188 }
189
191}
192
210[[noreturn]] static void cpu1_fault_handler(void)
211{
212 while (1) {
213 __asm volatile("nop");
214 }
215}
216
227#ifndef RA8_OFF_TARGET
228/* The vector table is only meaningful in the cross-compiled M33 image. The host
229 * unit-test build compile-checks this TU but never links it as an executable, so
230 * dropping the table there costs no coverage. */
231[[gnu::used, gnu::section(".cpu1_vectors")]] const uintptr_t g_cpu1_vector_table[] = {
232 (uintptr_t)&g_ra8_ls_cpu1_stack_top,
233 (uintptr_t)&cpu1_reset_handler,
234 (uintptr_t)&cpu1_fault_handler,
235 (uintptr_t)&cpu1_fault_handler,
236 (uintptr_t)&cpu1_fault_handler,
237 (uintptr_t)&cpu1_fault_handler,
238 (uintptr_t)&cpu1_fault_handler,
239 (uintptr_t)&cpu1_fault_handler,
240};
241#endif
void cpu1_reset_handler(void)
CPU1 reset handler.
Definition cpu1_main.c:266
uint32_t g_ra8_ls_cpu1_data_end
uint32_t g_ra8_ls_cpu1_bss_start
uint32_t g_ra8_ls_cpu1_data_load
uint32_t g_ra8_ls_cpu1_bss_end
const uintptr_t g_cpu1_vector_table[]
Minimal Armv8-M vector table for CPU1.
Definition cpu1_main.c:337
uint32_t g_ra8_ls_cpu1_stack_top
uint32_t g_ra8_ls_cpu1_data_start
m33_port_addr_t
MMIO addresses of the PORT registers the M33 hold loop drives.
Definition cpu1_main.c:71
@ k_port6_pcntr1_addr
PORT6 PCNTR1: {PODR[31:16], PDR[15:0]} (LED1).
Definition cpu1_main.c:72
@ k_port0_pcntr2_addr
PORT0 PCNTR2: {EIDR[31:16], PIDR[15:0]} (SW1).
Definition cpu1_main.c:73
static void cpu1_hold_page(void)
CPU1 application loop: hold the page, blink the active-core LED, poll SW1.
Definition cpu1_main.c:115
m33_hold_const_t
PCNTR field constants and the hold-loop delay bound.
Definition cpu1_main.c:86
@ k_led1_pdr_out
PCNTR1 PDR pin 0 = output direction.
Definition cpu1_main.c:87
@ k_hold_spins
Bounded busy-delay spins per hold pass.
Definition cpu1_main.c:92
@ k_sw1_pressed
SW1 active-low: 0 = pressed.
Definition cpu1_main.c:91
@ k_sw1_released
SW1 active-low: 1 = released (not pressed).
Definition cpu1_main.c:90
@ k_led1_podr_on
PCNTR1 PODR pin 0 = drive high (bit 16).
Definition cpu1_main.c:88
@ k_sw1_pidr_bit
SW1 = PORT0 pin 9 (PIDR bit 9).
Definition cpu1_main.c:89
Shared-SRAM contract for the low-power "hold the page" dual-core demo.
static volatile lowpower_mailbox_t * lowpower_mailbox(void)
Typed pointer to the fixed-address shared mailbox.
Cross-core handoff block backed by a fixed shared-SRAM address.
volatile uint32_t page_num
Held page; M85 sets 0, M33 bumps on turn.
volatile uint32_t m33_heartbeat
M33 increments each hold-loop iteration.
volatile uint32_t sw1_events
M33 counts SW1 (page-turn) press edges.