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

RA8P1 Arm Ethos-U55 NPU foundation smoke – runs a checkable stand-in job. More...

#include <stdint.h>
#include "ra8_attributes.h"
#include "ra8_board_ra8p1.h"
#include "ra8_boot_entry.h"
#include "ra8_cgc.h"
#include "ra8_device.h"
#include "ra8_err.h"
#include "ra8_npu.h"
#include "ra8_npu_fake_cmd.h"
#include "ra8_npu_regs.h"
Include dependency graph for main.c:

Go to the source code of this file.

Enumerations

enum  npu_smoke_size_t : uint32_t {
  k_npu_smoke_baud = 115200U ,
  k_npu_smoke_arena_bytes = 64U ,
  k_npu_smoke_cmd_words = k_ra8_npu_fake_word_num ,
  k_npu_smoke_hex_digits = 8U ,
  k_npu_smoke_hex_shift = 4U ,
  k_npu_smoke_hex_mask = 0x0FU
}
 Command-stream / tensor-arena sizes and the console baud. More...
enum  npu_smoke_region_t : uint8_t {
  k_npu_smoke_region_weights = 0U ,
  k_npu_smoke_region_input = 1U ,
  k_npu_smoke_region_output = 2U ,
  k_npu_smoke_region_count = 3U
}
 Tensor-region indices the smoke job programs into BASEPn. More...
enum  npu_smoke_seed_t : uint8_t {
  k_npu_smoke_addk = 0x11U ,
  k_npu_smoke_seed_mul = 7U ,
  k_npu_smoke_seed_add = 3U ,
  k_npu_smoke_byte_mask = 0xFFU
}
 Deterministic input pattern + the add-constant the job applies. More...
enum  npu_smoke_fnv_t : uint32_t {
  k_npu_smoke_fnv_offset = 0x811C9DC5U ,
  k_npu_smoke_fnv_prime = 0x01000193U
}
 FNV-1a 32-bit constants for the displayed output checkword. More...

Functions

static void internal_npu_smoke_panic_halt (void)
 Park the CPU forever in WFI after a fatal init error (a real panic).
static void internal_npu_smoke_park (void)
 Park the CPU forever in WFI after the verdict banner (a clean stop).
static void internal_npu_smoke_setup_or_halt (void)
 Bring up CGC + the SCI8 console.
static void internal_npu_smoke_build_stream (void)
 Fill the command stream (add-constant op) per the stand-in convention.
static void internal_npu_smoke_seed_arenas (void)
 Seed the input arena with a deterministic pattern and zero the output.
static ra8_err_t internal_npu_smoke_run_job (void)
 Submit + run + wait for the NPU job.
static bool internal_npu_smoke_verify (uint32_t *out_check)
 Verify the output arena equals input+K and fold it into a checkword.
static void internal_npu_smoke_write (const uint8_t *data, size_t len)
static void internal_npu_smoke_write_hex32 (uint32_t value)
static void internal_npu_smoke_write_status (bool ok)
static void internal_npu_smoke_write_verdict (bool pass)
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.
void main (void)
 Application entry: bring up the NPU, run a checkable job, print verdict.

Variables

static uint32_t s_npu_cmd_stream [k_npu_smoke_cmd_words]
 Stand-in command stream in SRAM (ra8_npu_fake_cmd.h layout; add-constant op).
static uint8_t s_npu_weights [k_npu_smoke_arena_bytes]
 Region 0 weight arena (present by Vela convention; unused by this op).
static uint8_t s_npu_input [k_npu_smoke_arena_bytes]
 Region 1 input tensor: seeded with a deterministic byte pattern.
static uint8_t s_npu_output [k_npu_smoke_arena_bytes]
 Region 2 output tensor: zeroed pre-run, holds the NPU result post-run.
volatile uint32_t g_npu_smoke_id = 0U
 NPU_ID captured after init, for external (J-Link) inspection.
volatile uint32_t g_npu_smoke_status = 0U
 Raw NPU_STATUS captured after the run, for external inspection.
volatile uint32_t g_npu_smoke_check = 0U
 Output checkword captured after verify, for external inspection.
volatile uint32_t g_npu_smoke_pass = 0U
 Final verdict (1 = PASS, 0 = FAIL), for external inspection.

Detailed Description

RA8P1 Arm Ethos-U55 NPU foundation smoke – runs a checkable stand-in job.

Tag
[Ring 6 / APP] {World: S}

Companion to examples/ra8p1_foundation/blink_ra8p1 for the NPU. This app drives the FULL ra8_npu command/queue surface end-to-end and CHECKS the result: bring the Ethos-U55 out of module-stop (ra8_npu_init), read the NPU_ID probe, build a command stream + input tensor in SRAM, program them (ra8_npu_submit), kick the job (ra8_npu_run), wait for completion (ra8_npu_wait), then READ the output arena back and assert it holds the deterministic expected result. The verdict is printed over the SCI8 console:

npu: id=0x10060000 run=OK out=0x........ verdict=PASS

The SCI8 console is provided by the dedicated ra8_board_ra8p1 board layer (issue #226), whose LED/switch/console pins are provisional (mirrored from the pin-compatible EK-RA8D2) until an RA8P1 board is defined – see that layer's header for the TODO(EK-RA8P1 UM / ra8p1_kicad) rationale.

The command stream is NOT a real Vela program: it uses the tiny, documented ra8_emulator / host-test convention in ra8_npu_fake_cmd.h (an "SE55" magic word plus an add-constant opcode). Under tools/ra8_emulator --device ra8p1 the NPU model decodes it and applies the op to the tensor arenas, so this app is a DETERMINISTIC, emulator-runnable check of the driver protocol + BASEPn region programming – run it twice and the banner is identical. It is still a FOUNDATION app: there is no RA8P1 board yet, and real Vela-compiled inference is the follow-up on the RA8P1 NPU epic. On silicon the NPU reaches the arenas over AXI, so a real driver would add cache maintenance around the tensors; the cache-less emulator needs none, so this foundation omits it.

Architectural ring
See docs/RING_AND_WORLD.md for what [Ring 6 / APP] {World: S} means – application-layer code that runs in the Secure world.
Author
Brighton Sikarskie
Date
2026-07-10
Since
0.1.0

Definition in file main.c.

Enumeration Type Documentation

◆ npu_smoke_fnv_t

enum npu_smoke_fnv_t : uint32_t

FNV-1a 32-bit constants for the displayed output checkword.

Enumerator
k_npu_smoke_fnv_offset 

FNV-1a 32-bit offset basis.

k_npu_smoke_fnv_prime 

FNV-1a 32-bit prime.

Definition at line 109 of file main.c.

◆ npu_smoke_region_t

enum npu_smoke_region_t : uint8_t

Tensor-region indices the smoke job programs into BASEPn.

Enumerator
k_npu_smoke_region_weights 

Region 0: Vela weight arena (unused by op).

k_npu_smoke_region_input 

Region 1: op source (input tensor).

k_npu_smoke_region_output 

Region 2: op destination (output tensor).

k_npu_smoke_region_count 

Regions programmed (BASEP0..2).

Definition at line 87 of file main.c.

◆ npu_smoke_seed_t

enum npu_smoke_seed_t : uint8_t

Deterministic input pattern + the add-constant the job applies.

Enumerator
k_npu_smoke_addk 

Constant added to every input byte.

k_npu_smoke_seed_mul 

input[i] = (i * mul + add) & mask.

k_npu_smoke_seed_add 

Input pattern additive offset.

k_npu_smoke_byte_mask 

8-bit element wrap (matches the op).

Definition at line 98 of file main.c.

◆ npu_smoke_size_t

enum npu_smoke_size_t : uint32_t

Command-stream / tensor-arena sizes and the console baud.

Enumerator
k_npu_smoke_baud 

SCI8 J-Link OB console baud.

k_npu_smoke_arena_bytes 

Tensor-arena length (bytes).

k_npu_smoke_cmd_words 

Command-stream word count.

k_npu_smoke_hex_digits 

Fixed-width hex word digits.

k_npu_smoke_hex_shift 

Bits per hex nibble.

k_npu_smoke_hex_mask 

Mask for one hex nibble.

Definition at line 74 of file main.c.

Function Documentation

◆ internal_npu_smoke_build_stream()

void internal_npu_smoke_build_stream ( void )
static

Fill the command stream (add-constant op) per the stand-in convention.

Writes the five header words of ra8_npu_fake_cmd.h: magic|opcode, source region, destination region, byte count, constant addend.

Precondition
s_npu_cmd_stream has k_ra8_npu_fake_word_num words.
No active NPU job is reading the command stream.
Postcondition
s_npu_cmd_stream describes an add-constant of region 1 -> region 2.
Only the defined fake-command header words are modified.
Note
The stream exercises driver plumbing with a deterministic stand-in op.
Since
0.1.0

Definition at line 269 of file main.c.

References k_npu_smoke_addk, k_npu_smoke_arena_bytes, k_npu_smoke_region_input, k_npu_smoke_region_output, k_ra8_npu_fake_magic, k_ra8_npu_fake_op_addk, k_ra8_npu_fake_word_const, k_ra8_npu_fake_word_count, k_ra8_npu_fake_word_dst, k_ra8_npu_fake_word_op, k_ra8_npu_fake_word_src, RA8_INTERNAL, and s_npu_cmd_stream.

Referenced by main().

◆ internal_npu_smoke_emit()

void internal_npu_smoke_emit ( uint32_t id,
bool run_ok,
uint32_t check,
bool pass )
static

Print the one-line verdict banner over the SCI8 console.

Emits fixed text fragments and fixed-width hexadecimal fields directly, avoiding the libc snprintf implementation unavailable to the freestanding target.

Parameters
[in]idNPU_ID read after init.
[in]run_okWhether the submit/run/wait sequence returned k_ra8_ok.
[in]checkOutput checkword from internal_npu_smoke_verify().
[in]passFinal verdict (id valid AND run_ok AND output matched).
Precondition
The SCI8 console is initialised.
All supplied values are final snapshots for the completed run.
Postcondition
One banner line has been written and flushed to the console.
NPU arenas and published result globals remain unchanged.
Note
Individual diagnostic writes are best-effort; the final flush keeps the complete line observable by the HIL scraper.
Since
0.1.0

Definition at line 420 of file main.c.

References internal_npu_smoke_write(), internal_npu_smoke_write_hex32(), internal_npu_smoke_write_status(), internal_npu_smoke_write_verdict(), and ra8_board_uart_console_flush().

Referenced by main().

◆ internal_npu_smoke_panic_halt()

void internal_npu_smoke_panic_halt ( void )
static

Park the CPU forever in WFI after a fatal init error (a real panic).

Reserved for failures BEFORE a verdict can be emitted (CGC or the SCI8 console did not come up), so a ra8_emulator gate that scans for a *panic_halt terminal PC correctly reads this as a failed run. The normal post-verdict terminal is internal_npu_smoke_park, which is NOT a panic and must not be flagged as one.

Precondition
Called only after a fatal init error, before the verdict banner.
No initialized console path can publish a normal run verdict.
Postcondition
CPU is parked; only a debugger or reset wakes it.
No NPU or console access occurs after entry.
Note
The panic suffix is consumed by emulator failure classification.
Since
0.1.0

Definition at line 202 of file main.c.

References RA8_INTERNAL.

Referenced by internal_npu_smoke_setup_or_halt().

◆ internal_npu_smoke_park()

void internal_npu_smoke_park ( void )
static

Park the CPU forever in WFI after the verdict banner (a clean stop).

Distinct from internal_npu_smoke_panic_halt on purpose: a run that reached the verdict – PASS or FAIL – has done its job and parks here, whose name deliberately does NOT match the *panic_halt / *_halt_loop patterns a ra8_emulator gate treats as a give-up. The authoritative verdict is the emitted verdict=PASS / verdict=FAIL banner (and g_npu_smoke_pass for a memprobe), never the parked PC.

Precondition
The verdict banner has been emitted over the SCI8 console.
Run-result globals contain their final diagnostic values.
Postcondition
CPU is parked; only a debugger or reset wakes it.
The verdict remains stable for an attached memory probe.
Note
Reaching this clean terminal does not imply PASS; the banner is authoritative.
Since
0.1.0

Definition at line 226 of file main.c.

References RA8_INTERNAL.

Referenced by main().

◆ internal_npu_smoke_run_job()

ra8_err_t internal_npu_smoke_run_job ( void )
static

Submit + run + wait for the NPU job.

Builds a descriptor over the static regions, submits it, starts the NPU, and synchronously returns the completion wait result.

Returns
ra8_err_t from the first failing driver call, else k_ra8_ok.
Return values
k_ra8_okJob completed (command stream consumed).
Precondition
The command stream and arenas are populated.
The NPU is initialized and has no active job.
Postcondition
On k_ra8_ok the output arena holds the NPU result.
On failure no later driver stage is invoked by this helper.
Note
All referenced region storage remains owned by the application.
Since
0.1.0

Definition at line 316 of file main.c.

References ra8_npu_job_t::cmd_stream, ra8_npu_job_t::cmd_stream_bytes, k_npu_smoke_region_count, k_npu_smoke_region_input, k_npu_smoke_region_output, k_npu_smoke_region_weights, k_ra8_ok, RA8_INTERNAL, ra8_npu_run(), ra8_npu_submit(), ra8_npu_wait(), ra8_npu_job_t::region_base, ra8_npu_job_t::region_count, s_npu_cmd_stream, s_npu_input, s_npu_output, and s_npu_weights.

Referenced by main().

◆ internal_npu_smoke_seed_arenas()

void internal_npu_smoke_seed_arenas ( void )
static

Seed the input arena with a deterministic pattern and zero the output.

Generates the fixed affine byte sequence used by verification and clears every output byte so stale data cannot produce a false pass.

Precondition
The arenas are k_npu_smoke_arena_bytes long.
The current run exclusively owns both static arenas.
Postcondition
s_npu_input holds the pattern; s_npu_output is all zero.
The weights and command-stream regions remain unchanged.
Note
Deterministic seeding makes the emitted checkword reproducible.
Since
0.1.0

Definition at line 291 of file main.c.

References k_npu_smoke_arena_bytes, k_npu_smoke_byte_mask, k_npu_smoke_seed_add, k_npu_smoke_seed_mul, RA8_INTERNAL, s_npu_input, and s_npu_output.

Referenced by main().

◆ internal_npu_smoke_setup_or_halt()

void internal_npu_smoke_setup_or_halt ( void )
static

Bring up CGC + the SCI8 console.

Panic-halts on any failure.

The NPU needs no clock beyond the CGC default NPUCLK; only the console (PCLKA/SCICLK) is set up here so the verdict can be printed.

Precondition
Reset_Handler has initialised .data / .bss.
The application remains in single-threaded boot context.
Postcondition
On return CGC is up and the SCI8 console is ready for writes.
Any mandatory setup error transfers to the panic halt.
Note
NPU initialization is intentionally deferred until after diagnostics work.
Since
0.1.0

Definition at line 246 of file main.c.

References internal_npu_smoke_panic_halt(), k_npu_smoke_baud, k_ra8_ok, ra8_board_uart_console_init(), ra8_cgc_init(), and RA8_INTERNAL.

Referenced by main().

◆ internal_npu_smoke_verify()

bool internal_npu_smoke_verify ( uint32_t * out_check)
static

Verify the output arena equals input+K and fold it into a checkword.

Compares every output byte to the wrapped add-constant expectation while accumulating an FNV-1a digest independent of the verdict.

Parameters
[out]out_checkFNV-1a digest of the output bytes (for the banner).
Returns
true when every output byte matches the expected add-constant result.
Return values
trueEvery result byte matches its expected value.
falseOne or more result bytes differ.
Precondition
out_check is non-NULL; the job has completed.
Input and output arenas contain the same completed run.
Postcondition
*out_check holds the output digest regardless of the verdict.
Neither arena is modified during verification.
Note
The digest is diagnostic evidence, not a cryptographic authenticator.
Since
0.1.0

Definition at line 354 of file main.c.

References k_npu_smoke_addk, k_npu_smoke_arena_bytes, k_npu_smoke_byte_mask, k_npu_smoke_fnv_offset, k_npu_smoke_fnv_prime, RA8_INTERNAL, s_npu_input, and s_npu_output.

Referenced by main().

◆ internal_npu_smoke_write()

void internal_npu_smoke_write ( const uint8_t * data,
size_t len )
static

◆ internal_npu_smoke_write_hex32()

void internal_npu_smoke_write_hex32 ( uint32_t value)
static

◆ internal_npu_smoke_write_status()

void internal_npu_smoke_write_status ( bool ok)
static

Definition at line 387 of file main.c.

References internal_npu_smoke_write(), and RA8_INTERNAL.

Referenced by internal_npu_smoke_emit().

◆ internal_npu_smoke_write_verdict()

void internal_npu_smoke_write_verdict ( bool pass)
static

Definition at line 394 of file main.c.

References internal_npu_smoke_write(), and RA8_INTERNAL.

Referenced by internal_npu_smoke_emit().

◆ main()

void main ( void )

Application entry: bring up the NPU, run a checkable job, print verdict.

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler has copied .data and zeroed .bss.
Postcondition
The verdict banner is on the console; the CPU is parked in WFI.
Since
0.1.0

Definition at line 441 of file main.c.

References g_npu_smoke_check, g_npu_smoke_id, g_npu_smoke_pass, g_npu_smoke_status, internal_npu_smoke_build_stream(), internal_npu_smoke_emit(), internal_npu_smoke_park(), internal_npu_smoke_run_job(), internal_npu_smoke_seed_arenas(), internal_npu_smoke_setup_or_halt(), internal_npu_smoke_verify(), k_ra8_ok, ra8_npu_init(), ra8_npu_read_id(), ra8_npu_read_status(), and ra8_npu_status_t::raw.

Variable Documentation

◆ g_npu_smoke_check

volatile uint32_t g_npu_smoke_check = 0U

Output checkword captured after verify, for external inspection.

volatile + non-static so a debugger can read the result digest.

Note
Read externally only.
Since
0.1.0

Definition at line 175 of file main.c.

Referenced by main().

◆ g_npu_smoke_id

volatile uint32_t g_npu_smoke_id = 0U

NPU_ID captured after init, for external (J-Link) inspection.

volatile + non-static so a debugger can read it; firmware writes once.

Note
Read externally only.
Since
0.1.0

Definition at line 157 of file main.c.

Referenced by main().

◆ g_npu_smoke_pass

volatile uint32_t g_npu_smoke_pass = 0U

Final verdict (1 = PASS, 0 = FAIL), for external inspection.

volatile + non-static so a memprobe can read the verdict.

Note
Read externally only.
Since
0.1.0

Definition at line 184 of file main.c.

Referenced by main().

◆ g_npu_smoke_status

volatile uint32_t g_npu_smoke_status = 0U

Raw NPU_STATUS captured after the run, for external inspection.

volatile + non-static so a debugger can watch it.

Note
Read externally only.
Since
0.1.0

Definition at line 166 of file main.c.

Referenced by main().

◆ s_npu_cmd_stream

uint32_t s_npu_cmd_stream[k_npu_smoke_cmd_words]
static

Stand-in command stream in SRAM (ra8_npu_fake_cmd.h layout; add-constant op).

QBASE/QSIZE point the NPU at this; the fake model decodes it.

Note
Not a real Vela program – see the file header.
Since
0.1.0

Definition at line 121 of file main.c.

◆ s_npu_input

uint8_t s_npu_input[k_npu_smoke_arena_bytes]
static

Region 1 input tensor: seeded with a deterministic byte pattern.

The NPU (fake) reads this and writes input+K to the output arena.

Note
Seeded by internal_npu_smoke_seed_arenas().
Since
0.1.0

Definition at line 139 of file main.c.

◆ s_npu_output

uint8_t s_npu_output[k_npu_smoke_arena_bytes]
static

Region 2 output tensor: zeroed pre-run, holds the NPU result post-run.

Verified byte-for-byte against the expected input+K result.

Note
Written by the NPU (fake), read back by the app.
Since
0.1.0

Definition at line 148 of file main.c.

◆ s_npu_weights

uint8_t s_npu_weights[k_npu_smoke_arena_bytes]
static

Region 0 weight arena (present by Vela convention; unused by this op).

Programmed into BASEP0 so the region layout matches a real job.

Note
Contents irrelevant to the add-constant op.
Since
0.1.0

Definition at line 130 of file main.c.