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
15
16#include <stdint.h>
17
18#include "ra8_attributes.h"
19#include "ra8_err.h"
20#include "ra8_ipc.h"
21
22extern uint32_t g_ra8_ls_cpu1_stack_top;
23extern uint32_t g_ra8_ls_cpu1_data_start;
24extern uint32_t g_ra8_ls_cpu1_data_end;
25extern uint32_t g_ra8_ls_cpu1_data_load;
26extern uint32_t g_ra8_ls_cpu1_bss_start;
27extern uint32_t g_ra8_ls_cpu1_bss_end;
28
29[[noreturn]] void cpu1_reset_handler(void);
30
31typedef enum : uint32_t {
35
36typedef enum : uint8_t {
39
40/* Self-contained IPC for CPU1 -- avoid the M85 HAL whose accessors
41 * the M33 cannot all reach through its NS-controller view. Channel windows
42 * via the NS alias (bit 28 set) so the IPCSAR-attributed channels are
43 * reachable. HUM Ch 3.2 p 205. */
44typedef enum : uintptr_t {
45 k_cpu1_ipc_ch0_addr = 0x500200C0UL,
46 k_cpu1_ipc_ch2_addr = 0x50020100UL,
48
49typedef enum : uint8_t {
55
56typedef enum : uint32_t {
57 k_cpu1_ipc_sta_rdy = 0x00010000UL,
58 k_cpu1_ipc_clr_all = 0x030100FFUL,
60
73typedef enum : uintptr_t {
74 k_cpu1_sau_ctrl_addr = 0xE000EDD0UL,
75 k_cpu1_sau_rnr_addr = 0xE000EDD8UL,
76 k_cpu1_sau_rbar_addr = 0xE000EDDCUL,
77 k_cpu1_sau_rlar_addr = 0xE000EDE0UL,
79
89typedef enum : uint32_t {
92 k_cpu1_sau_periph_s_base = 0x40000000UL,
94 k_cpu1_sau_ns_sram_base = 0x22100000UL,
95 k_cpu1_sau_ns_sram_limit = 0x221FFFE1UL,
96 k_cpu1_sau_mram_base = 0x020C0000UL,
97 k_cpu1_sau_mram_limit = 0x020FFFE1UL,
99
110typedef enum : uintptr_t {
111 k_cpu1_probe_reset_addr = 0x32100200UL,
112 k_cpu1_probe_data_addr = 0x32100204UL,
113 k_cpu1_probe_bss_addr = 0x32100208UL,
114 k_cpu1_probe_main_addr = 0x3210020CUL,
115 k_cpu1_probe_sau_addr = 0x32100214UL,
116 k_cpu1_probe_iter_addr = 0x32100220UL,
117 k_cpu1_probe_rxd_addr = 0x32100224UL,
118 k_cpu1_probe_pong_addr = 0x32100228UL,
120 k_cpu1_probe_sta_addr = 0x32100234UL,
121 k_cpu1_probe_sem_addr = 0x32100238UL,
123 k_cpu1_ipcsem0_ns_addr = 0x50020000UL,
125
134typedef enum : uint32_t {
135 k_cpu1_probe_reset_val = 0xC0DEDEADUL,
136 k_cpu1_probe_data_val = 0xB055A55AUL,
137 k_cpu1_probe_bss_val = 0xBEEFCAFEUL,
138 k_cpu1_probe_main_val = 0x11111111UL,
139 k_cpu1_probe_sau_val = 0x33333333UL,
140 k_cpu1_probe_pre_val = 0xAAAAAAAAUL,
142
163{
164 /* Region 0: peripherals NS alias (0x50000000-0x5FFFFFE0). */
165 *(volatile uint32_t*)k_cpu1_sau_rnr_addr = 0x00000000UL; /* SAU_RNR */
166 *(volatile uint32_t*)k_cpu1_sau_rbar_addr = (uint32_t)k_cpu1_sau_periph_ns_base; /* SAU_RBAR */
167 *(volatile uint32_t*)k_cpu1_sau_rlar_addr =
168 (uint32_t)k_cpu1_sau_periph_ns_limit; /* SAU_RLAR limit | enable */
169 /* Region 1: peripherals S alias (0x40000000-0x4FFFFFE0). */
170 *(volatile uint32_t*)k_cpu1_sau_rnr_addr = 0x00000001UL;
171 *(volatile uint32_t*)k_cpu1_sau_rbar_addr = (uint32_t)k_cpu1_sau_periph_s_base;
172 *(volatile uint32_t*)k_cpu1_sau_rlar_addr = (uint32_t)k_cpu1_sau_periph_s_limit;
173 /* Region 2: NS SRAM range (0x22100000-0x221FFFE0). The CPU1 SRAM bank
174 * (0x22190000-0x2219FFE0) now lives inside this window, so one NS region
175 * covers both the shared markers and the bank -- a separate bank region
176 * would overlap this one, and overlapping SAU regions resolve to Secure,
177 * which the permanent-NS M33 cannot reach. */
178 *(volatile uint32_t*)k_cpu1_sau_rnr_addr = 0x00000002UL;
179 *(volatile uint32_t*)k_cpu1_sau_rbar_addr = (uint32_t)k_cpu1_sau_ns_sram_base;
180 *(volatile uint32_t*)k_cpu1_sau_rlar_addr = (uint32_t)k_cpu1_sau_ns_sram_limit;
181 /* Region 3: MRAM_CPU1 code (0x020C0000-0x020FFFE0). */
182 *(volatile uint32_t*)k_cpu1_sau_rnr_addr = 0x00000003UL;
183 *(volatile uint32_t*)k_cpu1_sau_rbar_addr = (uint32_t)k_cpu1_sau_mram_base;
184 *(volatile uint32_t*)k_cpu1_sau_rlar_addr = (uint32_t)k_cpu1_sau_mram_limit;
185 /* Enable SAU (no ALLNS, so unprogrammed defaults to IDAU). */
186 *(volatile uint32_t*)k_cpu1_sau_ctrl_addr = 0x00000001UL;
187 __asm__ volatile("dsb 0xf" ::: "memory");
188 __asm__ volatile("isb 0xf" ::: "memory");
189 *(volatile uint32_t*)k_cpu1_probe_sau_addr = (uint32_t)k_cpu1_probe_sau_val; /* SAU configured */
190}
191
204[[noreturn]] RA8_INTERNAL static void internal_cpu1_main(void)
205{
206 *(volatile uint32_t*)k_cpu1_probe_main_addr =
207 (uint32_t)k_cpu1_probe_main_val; /* internal_cpu1_main entry */
208
210
211 while (1) {
212 *(volatile uint32_t*)k_cpu1_probe_iter_addr += 1U; /* loop iter counter */
213 *(volatile uint32_t*)k_cpu1_probe_preread_addr =
214 (uint32_t)k_cpu1_probe_pre_val; /* pre-IPC-read marker */
215 /* TEST: read IPCSEM0 (the simplest IPC reg) first to isolate fault.
216 * IPCSEM0 is at 0x40020000 / NS alias 0x50020000.
217 * IPCSAR.SAIPCSEM0 (bit 0) was set NS too. */
218 const uint32_t sem = *(volatile uint32_t*)k_cpu1_ipcsem0_ns_addr;
219 *(volatile uint32_t*)k_cpu1_probe_sem_addr = sem; /* IPCSEM0 read survived */
220 /* Poll CH2 RX for ping. */
221 const uint32_t sta = *(volatile uint32_t*)(k_cpu1_ipc_ch2_addr + k_cpu1_ipc_off_sta);
222 *(volatile uint32_t*)k_cpu1_probe_sta_addr = sta; /* STA read survived */
223 if ((sta & (uint32_t)k_cpu1_ipc_sta_rdy) == 0U) {
224 continue;
225 }
226 const uint32_t got = *(volatile uint32_t*)(k_cpu1_ipc_ch2_addr + k_cpu1_ipc_off_rxd);
227 *(volatile uint32_t*)k_cpu1_probe_rxd_addr = got; /* most recent rxd */
228 if (got != (uint32_t)k_cpu1_pingpong_magic_ping) {
229 continue;
230 }
231 /* Push pong onto CH0 TX. */
232 *(volatile uint32_t*)(k_cpu1_ipc_ch0_addr + k_cpu1_ipc_off_txd) =
234 *(volatile uint32_t*)k_cpu1_probe_pong_addr += 1U; /* pong sent counter */
235 }
236}
237
266[[noreturn]] void cpu1_reset_handler(void)
267{
268 /* CPU1 NS-alias-side marker. The M33 here has SECEXT disabled, so it
269 * is hardware-locked to the NS controller state; the dedicated SRAM_CPU1
270 * bank at 0x22190000 is its physical alias for these BSS reads, but
271 * CPU0's J-Link memprobe sees the same bytes through the standard
272 * 0x22190000 view. Bench tail: confirm 0xC0DEDEAD before the data
273 * copy starts -- it tells us reset_handler actually ran and the
274 * MRAM_CPU1 fetch worked. */
275 /* Markers placed in NS_SRAM (CPU0 J-Link memprobe can read this view;
276 * CPU0's SAU NS_SRAM region 0x22100000-0x221FFFE0 maps NS, and CPU1
277 * as a permanent NS controller can write to the same physical bytes
278 * through the NS alias 0x32100200). The chip's two views of SRAM
279 * see the same backing store. */
280 *(volatile uint32_t*)k_cpu1_probe_reset_addr = (uint32_t)k_cpu1_probe_reset_val;
281 *(volatile uint32_t*)k_cpu1_probe_reset_s_addr = (uint32_t)k_cpu1_probe_reset_val;
282
283 /* Copy .data from MRAM_CPU1 load address into SRAM_CPU1. The linker
284 * defines ``g_ra8_ls_cpu1_data_load`` as LOADADDR(.data) so this
285 * works regardless of the absolute MRAM_CPU1 base. */
286 uint32_t* dst = &g_ra8_ls_cpu1_data_start;
287 uint32_t* src = &g_ra8_ls_cpu1_data_load;
288 while (dst < &g_ra8_ls_cpu1_data_end) {
289 *dst = *src;
290 dst++;
291 src++;
292 }
293 *(volatile uint32_t*)k_cpu1_probe_data_addr =
294 (uint32_t)k_cpu1_probe_data_val; /* survived .data copy */
295
296 /* Zero .bss in SRAM_CPU1. */
297 uint32_t* bss = &g_ra8_ls_cpu1_bss_start;
298 while (bss < &g_ra8_ls_cpu1_bss_end) {
299 *bss = 0U;
300 bss++;
301 }
302 *(volatile uint32_t*)k_cpu1_probe_bss_addr =
303 (uint32_t)k_cpu1_probe_bss_val; /* survived .bss zero */
304
306}
307
318[[noreturn]] RA8_INTERNAL static void internal_cpu1_fault_handler(void)
319{
320 while (1) {
321 __asm volatile("nop");
322 }
323}
324
333#ifndef RA8_OFF_TARGET
334/* Vector table only built for the cross-compiled M33 image. The host
335 * build does not link this TU as an executable -- it is compile-checked
336 * only -- so we can drop the table without losing test coverage. */
337[[gnu::used, gnu::section(".cpu1_vectors")]] const uintptr_t g_cpu1_vector_table[] = {
338 (uintptr_t)&g_ra8_ls_cpu1_stack_top,
339 (uintptr_t)&cpu1_reset_handler,
340 (uintptr_t)&internal_cpu1_fault_handler,
341 (uintptr_t)&internal_cpu1_fault_handler,
342 (uintptr_t)&internal_cpu1_fault_handler,
343 (uintptr_t)&internal_cpu1_fault_handler,
344 (uintptr_t)&internal_cpu1_fault_handler,
345 (uintptr_t)&internal_cpu1_fault_handler,
346};
347#endif
cpu1_ipc_off_t
Definition cpu1_main.c:49
@ k_cpu1_ipc_off_txd
Cpu1 ipc off txd.
Definition cpu1_main.c:51
@ k_cpu1_ipc_off_rxd
Cpu1 ipc off rxd.
Definition cpu1_main.c:52
@ k_cpu1_ipc_off_clr
Cpu1 ipc off clr.
Definition cpu1_main.c:53
@ k_cpu1_ipc_off_sta
Cpu1 ipc off sta.
Definition cpu1_main.c:50
void cpu1_reset_handler(void)
CPU1 reset handler.
Definition cpu1_main.c:266
cpu1_main_const_t
Definition cpu1_main.c:31
@ k_cpu1_pingpong_magic_ping
Cpu1 pingpong magic ping.
Definition cpu1_main.c:32
@ k_cpu1_pingpong_magic_pong
Cpu1 pingpong magic pong.
Definition cpu1_main.c:33
uint32_t g_ra8_ls_cpu1_data_end
cpu1_ipc_addr_t
Definition cpu1_main.c:44
@ k_cpu1_ipc_ch2_addr
CPU1 RX from CPU0 (NS alias).
Definition cpu1_main.c:46
@ k_cpu1_ipc_ch0_addr
CPU1 TX to CPU0 (NS alias).
Definition cpu1_main.c:45
static void internal_cpu1_sau_init(void)
Programme CPU1's SAU and enable it.
Definition cpu1_main.c:162
uint32_t g_ra8_ls_cpu1_bss_start
cpu1_sau_region_t
Base and limit words for the four SAU regions this image programmes.
Definition cpu1_main.c:89
@ k_cpu1_sau_ns_sram_limit
R2 limit.
Definition cpu1_main.c:95
@ k_cpu1_sau_periph_s_base
R1 S base.
Definition cpu1_main.c:92
@ k_cpu1_sau_periph_ns_base
R0 NS base.
Definition cpu1_main.c:90
@ k_cpu1_sau_periph_ns_limit
R0 limit.
Definition cpu1_main.c:91
@ k_cpu1_sau_mram_limit
R3 limit.
Definition cpu1_main.c:97
@ k_cpu1_sau_ns_sram_base
R2 SRAM base.
Definition cpu1_main.c:94
@ k_cpu1_sau_periph_s_limit
R1 limit.
Definition cpu1_main.c:93
@ k_cpu1_sau_mram_base
R3 MRAM base.
Definition cpu1_main.c:96
cpu1_probe_val_t
Sentinel values written to the cpu1_probe_addr_t probe words.
Definition cpu1_main.c:134
@ k_cpu1_probe_data_val
Data copied.
Definition cpu1_main.c:136
@ k_cpu1_probe_bss_val
BSS cleared.
Definition cpu1_main.c:137
@ k_cpu1_probe_reset_val
Reset entry.
Definition cpu1_main.c:135
@ k_cpu1_probe_main_val
Main entry.
Definition cpu1_main.c:138
@ k_cpu1_probe_pre_val
Pre-read.
Definition cpu1_main.c:140
@ k_cpu1_probe_sau_val
SAU ready.
Definition cpu1_main.c:139
cpu1_sau_reg_t
Armv8-M SAU programming registers, addressed directly.
Definition cpu1_main.c:73
@ k_cpu1_sau_rlar_addr
SAU_RLAR: region limit + enable.
Definition cpu1_main.c:77
@ k_cpu1_sau_ctrl_addr
SAU_CTRL: SAU enable bit.
Definition cpu1_main.c:74
@ k_cpu1_sau_rnr_addr
SAU_RNR: region number select.
Definition cpu1_main.c:75
@ k_cpu1_sau_rbar_addr
SAU_RBAR: region base address.
Definition cpu1_main.c:76
cpu1_ipc_mask_t
Definition cpu1_main.c:56
@ k_cpu1_ipc_clr_all
Cpu1 ipc clr all.
Definition cpu1_main.c:58
@ k_cpu1_ipc_sta_rdy
Cpu1 ipc sta rdy.
Definition cpu1_main.c:57
cpu1_main_pair_t
Definition cpu1_main.c:36
@ k_cpu1_pingpong_pair_zero
Cpu1 pingpong pair zero.
Definition cpu1_main.c:37
uint32_t g_ra8_ls_cpu1_data_load
static void internal_cpu1_fault_handler(void)
Default fault handler.
Definition cpu1_main.c:318
static void internal_cpu1_main(void)
Run the CPU1 side of the ping-pong exchange.
Definition cpu1_main.c:204
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
cpu1_probe_addr_t
Bench probe words this image writes for a J-Link post-mortem.
Definition cpu1_main.c:110
@ k_cpu1_probe_data_addr
Data copied.
Definition cpu1_main.c:112
@ k_cpu1_probe_rxd_addr
Last RX word.
Definition cpu1_main.c:117
@ k_cpu1_probe_pong_addr
Pong count.
Definition cpu1_main.c:118
@ k_cpu1_probe_reset_s_addr
SRAM reset mark.
Definition cpu1_main.c:122
@ k_cpu1_probe_reset_addr
Reset entry.
Definition cpu1_main.c:111
@ k_cpu1_probe_iter_addr
Loop count.
Definition cpu1_main.c:116
@ k_cpu1_probe_main_addr
Main entry.
Definition cpu1_main.c:114
@ k_cpu1_probe_preread_addr
Pre-read mark.
Definition cpu1_main.c:119
@ k_cpu1_probe_sta_addr
CH2 status.
Definition cpu1_main.c:120
@ k_cpu1_probe_sau_addr
SAU ready.
Definition cpu1_main.c:115
@ k_cpu1_ipcsem0_ns_addr
NS semaphore.
Definition cpu1_main.c:123
@ k_cpu1_probe_sem_addr
Semaphore.
Definition cpu1_main.c:121
@ k_cpu1_probe_bss_addr
BSS cleared.
Definition cpu1_main.c:113
uint32_t g_ra8_ls_cpu1_stack_top
uint32_t g_ra8_ls_cpu1_data_start
Annotation-attribute framework macros for ra8-firmware.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Error Code Definitions for ra8-firmware.
Inter-Processor Communication (IPC) HAL driver – public API.