ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
main.c
Go to the documentation of this file.
1
47
48#include <stdint.h>
49
50#include "ra8_attributes.h"
51#include "ra8_board_ra8p1.h"
52#include "ra8_boot_entry.h"
53#include "ra8_cgc.h"
54#include "ra8_device.h"
55#include "ra8_err.h"
56#include "ra8_npu.h"
57#include "ra8_npu_fake_cmd.h"
58#include "ra8_npu_regs.h"
59
60/*
61 * Compile-time proof that the RA8P1 toolchain selection reached this TU: the NPU
62 * driver only exists when RA8_HAS_NPU is defined (RA8_DEVICE_RA8P1). Building this
63 * app with the RA8D2 toolchain fails loudly here instead of silently dropping
64 * the NPU.
65 */
66#ifndef RA8_HAS_NPU
67#error "npu_smoke must be built with cmake/toolchain-ra8p1.cmake (RA8_DEVICE_RA8P1)."
68#endif
69
82
93
104
109typedef enum : uint32_t {
111 k_npu_smoke_fnv_prime = 0x01000193U,
113
122
131
140
149
157volatile uint32_t g_npu_smoke_id = 0U;
158
166volatile uint32_t g_npu_smoke_status = 0U;
167
175volatile uint32_t g_npu_smoke_check = 0U;
176
184volatile uint32_t g_npu_smoke_pass = 0U;
185
203{
204 while (1) {
205 __asm__ volatile("wfi");
206 }
207}
208
227{
228 while (1) {
229 __asm__ volatile("wfi");
230 }
231}
232
255
278
292{
293 for (uint32_t i = 0U; i < (uint32_t)k_npu_smoke_arena_bytes; i++) {
294 s_npu_input[i] =
295 (uint8_t)(((i * (uint32_t)k_npu_smoke_seed_mul) + (uint32_t)k_npu_smoke_seed_add) &
296 (uint32_t)k_npu_smoke_byte_mask);
297 s_npu_output[i] = 0U;
298 }
299}
300
317{
318 ra8_npu_job_t job = {};
320 job.cmd_stream_bytes = (uint32_t)sizeof(s_npu_cmd_stream);
322 job.region_base[k_npu_smoke_region_weights] = (uint64_t)(uintptr_t)s_npu_weights;
323 job.region_base[k_npu_smoke_region_input] = (uint64_t)(uintptr_t)s_npu_input;
324 job.region_base[k_npu_smoke_region_output] = (uint64_t)(uintptr_t)s_npu_output;
325
326 const ra8_err_t sub = ra8_npu_submit(&job);
327 if (sub != k_ra8_ok) {
328 return sub;
329 }
330 const ra8_err_t run = ra8_npu_run();
331 if (run != k_ra8_ok) {
332 return run;
333 }
334 return ra8_npu_wait();
335}
336
354RA8_INTERNAL static bool internal_npu_smoke_verify(uint32_t* out_check)
355{
356 uint32_t check = (uint32_t)k_npu_smoke_fnv_offset;
357 bool ok = true;
358 for (uint32_t i = 0U; i < (uint32_t)k_npu_smoke_arena_bytes; i++) {
359 const uint8_t expected =
360 (uint8_t)((s_npu_input[i] + (uint32_t)k_npu_smoke_addk) & (uint32_t)k_npu_smoke_byte_mask);
361 if (s_npu_output[i] != expected) {
362 ok = false;
363 }
364 check = (check ^ (uint32_t)s_npu_output[i]) * (uint32_t)k_npu_smoke_fnv_prime;
365 }
366 *out_check = check;
367 return ok;
368}
369
370RA8_INTERNAL static void internal_npu_smoke_write(const uint8_t* data, size_t len)
371{
372 (void)ra8_board_uart_console_write(data, len);
373}
374
376{
377 static const uint8_t k_hex[] = "0123456789ABCDEF";
378 uint8_t digits[k_npu_smoke_hex_digits] = {};
379 for (uint8_t i = 0U; i < (uint8_t)k_npu_smoke_hex_digits; ++i) {
380 const uint8_t shift =
381 (uint8_t)(((uint8_t)k_npu_smoke_hex_digits - 1U - i) * (uint8_t)k_npu_smoke_hex_shift);
382 digits[i] = k_hex[(value >> shift) & (uint32_t)k_npu_smoke_hex_mask];
383 }
385}
386
388{
389 const uint8_t* text = ok ? (const uint8_t*)"OK" : (const uint8_t*)"FAIL";
390 const size_t len = ok ? 2U : 4U;
391 internal_npu_smoke_write(text, len);
392}
393
395{
396 const uint8_t* text = pass ? (const uint8_t*)"PASS" : (const uint8_t*)"FAIL";
397 internal_npu_smoke_write(text, 4U);
398}
399
419RA8_INTERNAL static void
420internal_npu_smoke_emit(uint32_t id, bool run_ok, uint32_t check, bool pass)
421{
422 internal_npu_smoke_write((const uint8_t*)"npu: id=0x", sizeof("npu: id=0x") - 1U);
424 internal_npu_smoke_write((const uint8_t*)" run=", sizeof(" run=") - 1U);
426 internal_npu_smoke_write((const uint8_t*)" out=0x", sizeof(" out=0x") - 1U);
428 internal_npu_smoke_write((const uint8_t*)" verdict=", sizeof(" verdict=") - 1U);
430 internal_npu_smoke_write((const uint8_t*)"\r\n", sizeof("\r\n") - 1U);
432}
433
441void main(void)
442{
444
445 bool run_ok = false;
446 uint32_t id = 0U;
447 uint32_t check = 0U;
448 bool pass = false;
449
450 if (ra8_npu_init() == k_ra8_ok) {
451 (void)ra8_npu_read_id(&id);
452 g_npu_smoke_id = id;
453
456 run_ok = (internal_npu_smoke_run_job() == k_ra8_ok);
457
458 ra8_npu_status_t st = {};
459 if (ra8_npu_read_status(&st) == k_ra8_ok) {
461 }
462 const bool matched = internal_npu_smoke_verify(&check);
464 pass = run_ok && matched && (id != 0U);
465 }
466
467 g_npu_smoke_pass = pass ? 1U : 0U;
468 internal_npu_smoke_emit(id, run_ok, check, pass);
469
471}
void main(void)
Secure fallback main entry point.
Definition main.c:37
static uint8_t s_npu_input[k_npu_infer_arena_bytes]
Region 1 UINT8 input tensor (quantized s_infer_input_f).
Definition main.c:169
static uint8_t s_npu_output[k_npu_infer_arena_bytes]
Region 2 UINT8 output tensor: zeroed pre-run, holds the NPU result.
Definition main.c:178
static uint32_t s_npu_cmd_stream[k_npu_infer_cmd_words]
Stand-in command stream in SRAM (ra8_npu_fake_cmd.h layout; add-constant op).
Definition main.c:142
static uint8_t s_npu_weights[k_npu_infer_arena_bytes]
Region 0 weight arena (present by Vela convention; unused by this op).
Definition main.c:151
npu_smoke_region_t
Tensor-region indices the smoke job programs into BASEPn.
Definition main.c:87
@ k_npu_smoke_region_count
Regions programmed (BASEP0..2).
Definition main.c:91
@ k_npu_smoke_region_weights
Region 0: Vela weight arena (unused by op).
Definition main.c:88
@ k_npu_smoke_region_output
Region 2: op destination (output tensor).
Definition main.c:90
@ k_npu_smoke_region_input
Region 1: op source (input tensor).
Definition main.c:89
npu_smoke_fnv_t
FNV-1a 32-bit constants for the displayed output checkword.
Definition main.c:109
@ k_npu_smoke_fnv_prime
FNV-1a 32-bit prime.
Definition main.c:111
@ k_npu_smoke_fnv_offset
FNV-1a 32-bit offset basis.
Definition main.c:110
volatile uint32_t g_npu_smoke_check
Output checkword captured after verify, for external inspection.
Definition main.c:175
static bool internal_npu_smoke_verify(uint32_t *out_check)
Verify the output arena equals input+K and fold it into a checkword.
Definition main.c:354
npu_smoke_size_t
Command-stream / tensor-arena sizes and the console baud.
Definition main.c:74
@ k_npu_smoke_hex_shift
Bits per hex nibble.
Definition main.c:79
@ k_npu_smoke_hex_mask
Mask for one hex nibble.
Definition main.c:80
@ k_npu_smoke_arena_bytes
Tensor-arena length (bytes).
Definition main.c:76
@ k_npu_smoke_hex_digits
Fixed-width hex word digits.
Definition main.c:78
@ k_npu_smoke_baud
SCI8 J-Link OB console baud.
Definition main.c:75
@ k_npu_smoke_cmd_words
Command-stream word count.
Definition main.c:77
static void internal_npu_smoke_build_stream(void)
Fill the command stream (add-constant op) per the stand-in convention.
Definition main.c:269
static void internal_npu_smoke_write_hex32(uint32_t value)
Definition main.c:375
npu_smoke_seed_t
Deterministic input pattern + the add-constant the job applies.
Definition main.c:98
@ k_npu_smoke_addk
Constant added to every input byte.
Definition main.c:99
@ k_npu_smoke_byte_mask
8-bit element wrap (matches the op).
Definition main.c:102
@ k_npu_smoke_seed_add
Input pattern additive offset.
Definition main.c:101
@ k_npu_smoke_seed_mul
input[i] = (i * mul + add) & mask.
Definition main.c:100
static void internal_npu_smoke_write(const uint8_t *data, size_t len)
Definition main.c:370
static ra8_err_t internal_npu_smoke_run_job(void)
Submit + run + wait for the NPU job.
Definition main.c:316
static void internal_npu_smoke_setup_or_halt(void)
Bring up CGC + the SCI8 console.
Definition main.c:246
static void internal_npu_smoke_emit(uint32_t id, bool run_ok, uint32_t check, bool pass)
Print the one-line verdict banner over the SCI8 console.
Definition main.c:420
static void internal_npu_smoke_write_verdict(bool pass)
Definition main.c:394
volatile uint32_t g_npu_smoke_id
NPU_ID captured after init, for external (J-Link) inspection.
Definition main.c:157
volatile uint32_t g_npu_smoke_pass
Final verdict (1 = PASS, 0 = FAIL), for external inspection.
Definition main.c:184
static void internal_npu_smoke_panic_halt(void)
Park the CPU forever in WFI after a fatal init error (a real panic).
Definition main.c:202
static void internal_npu_smoke_write_status(bool ok)
Definition main.c:387
volatile uint32_t g_npu_smoke_status
Raw NPU_STATUS captured after the run, for external inspection.
Definition main.c:166
static void internal_npu_smoke_seed_arenas(void)
Seed the input arena with a deterministic pattern and zero the output.
Definition main.c:291
static void internal_npu_smoke_park(void)
Park the CPU forever in WFI after the verdict banner (a clean stop).
Definition main.c:226
-copyright
Annotation-attribute framework macros for ra8-firmware.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
ra8_err_t ra8_board_uart_console_write(const uint8_t *data, size_t len)
Polled blocking write to the J-Link OB VCOM console.
ra8_err_t ra8_board_uart_console_init(uint32_t baud)
Configure SCI8 + PD02/PD03 as the debug-console UART.
ra8_err_t ra8_board_uart_console_flush(void)
Block until every byte queued on the J-Link OB VCOM console has finished clocking out on the wire.
Board-support layer for the Renesas RA8P1 (R7KA8P1KFLCAC) target board.
Boot entry points shared between a vector table and its startup code.
High-level Clock Generation Circuit driver.
ra8_err_t ra8_cgc_init(void)
Configure the clock tree to a safe default.
Definition ra8_cgc.c:727
Compile-time device selection for the RA8 multi-chip build (RA8D2 / RA8P1).
Error Code Definitions for ra8-firmware.
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
Arm Ethos-U55 NPU command/queue driver foundation (RA8P1-only).
ra8_err_t ra8_npu_read_status(ra8_npu_status_t *out)
Read and decode the NPU_STATUS register.
ra8_err_t ra8_npu_submit(const ra8_npu_job_t *job)
Program the command queue and tensor region base pointers for a job.
ra8_err_t ra8_npu_run(void)
Kick the currently-submitted job (transition the NPU to running).
ra8_err_t ra8_npu_read_id(uint32_t *out_id)
Read the Ethos-U55 NPU_ID (architecture / product revision) register.
ra8_err_t ra8_npu_init(void)
Bring the NPU out of module-stop and soft-reset it.
ra8_err_t ra8_npu_wait(void)
Bounded busy-wait until the running job completes or faults.
ra8_emulator / host-test command-stream convention for the Ethos-U55 model
@ k_ra8_npu_fake_op_addk
dst[i] = (src[i] + constant) & 0xFF.
@ k_ra8_npu_fake_word_dst
Destination region index (0 .
@ k_ra8_npu_fake_word_count
Byte count to process.
@ k_ra8_npu_fake_word_num
Header word count (populated words).
@ k_ra8_npu_fake_word_src
Source region index (0 .
@ k_ra8_npu_fake_word_op
magic | opcode.
@ k_ra8_npu_fake_word_const
Constant addend (add-constant op).
@ k_ra8_npu_fake_magic
Emu-Ethos-U55 marker in bits [31:16].
Arm Ethos-U55 NPU register window on the Renesas RA8P1 (RA8P1-only).
One Ethos-U55 inference job: a command stream plus its tensor arenas.
Definition ra8_npu.h:87
uint8_t region_count
Number of region_base[] entries in use.
Definition ra8_npu.h:90
uint32_t cmd_stream_bytes
Command stream length in bytes (> 0).
Definition ra8_npu.h:89
uint64_t region_base[k_ra8_npu_region_count]
AXI base of each BASEPn arena.
Definition ra8_npu.h:91
const void * cmd_stream
Vela command stream base in SRAM.
Definition ra8_npu.h:88
Decoded snapshot of the NPU_STATUS register.
Definition ra8_npu.h:106
uint32_t raw
Verbatim NPU_STATUS register value.
Definition ra8_npu.h:107