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: render a held e-reader page. More...

#include <stdint.h>
#include "book.h"
#include "ereader_m33.h"
#include "ra8_attributes.h"
#include "ra8_gfx.h"
#include "ra8_ipc.h"
#include "rabook_fixture.h"
Include dependency graph for cpu1_main.c:

Go to the source code of this file.

Data Structures

struct  m33_walk_stack_t
 Explicit DOM-walk stack (NASA Rule 1: iteration, never recursion). More...

Enumerations

enum  m33_walk_bound_t : uint32_t {
  k_walk_iter_max = 4096U ,
  k_max_run_len = 1024U
}
 Static iteration bounds for the M33 DOM walk (NASA Rule 2). More...
enum  m33_walk_size_t : uint16_t {
  k_walk_stack_depth = 64U ,
  k_max_chapters = 32U ,
  k_max_nodes = 4096U ,
  k_magic_len = 7U
}
 Small table / validation sizes for the M33 reader. More...
enum  m33_render_t : uint32_t {
  k_erm33_glyph_h = 16U ,
  k_erm33_paper = 0xFFFFFFU ,
  k_erm33_ink = 0x000000U
}
 Glyph cell height and page colours for the ra8_gfx blit. More...
enum  m33_crc_t : uint32_t {
  k_crc32_init = 0xFFFFFFFFU ,
  k_crc32_poly = 0xEDB88320U
}
 Constants for the standard reflected CRC-32 over the rendered plane. More...
enum  m33_crc_bits_t : uint8_t { k_crc32_bits = 8U }
 Bit-fold count for the bitwise CRC-32 inner loop. More...
enum  cpu1_ipc_t : uint8_t { k_cpu1_ipc_wake_channel = 0U }
 IPC channel the M33 pokes to wake the parked M85 on a page turn. More...
enum  m33_cycle_bound_t : uint32_t { k_m33_ack_budget = 50000000UL }
 Static bound for the M33's wait-for-ack poll (NASA Rule 2). More...

Functions

void cpu1_reset_handler (void)
 CPU1 reset handler: minimal C-runtime init, then run the reader.
static void append_run (char *out, uint32_t *plen, uint32_t cap, const char *txt)
 Append one NUL-terminated text run into the page accumulator.
static void walk_push (m33_walk_stack_t *st, uint32_t node)
 Push a node index onto the DOM-walk stack if it fits.
static uint32_t collect_chapter_text (const void *base, uint32_t root, uint32_t node_count, char *out, uint32_t cap)
 Collect a chapter's opening text into the page accumulator.
static bool render_page (uint8_t *fb, const char *text, uint32_t len)
 Render the collected page text into the SDRAM framebuffer via ra8_gfx.
static uint32_t fb_crc32 (const uint8_t *fb, uint32_t len)
 Fold a reflected CRC-32 over the rendered framebuffer pixels.
static void publish_page (volatile erm33_mailbox_t *mb, uint32_t crc, uint32_t glyphs)
 Publish the rendered page's base, geometry, format and CRC.
static bool book_is_valid (const void *base, uint32_t size)
 Validate the baked RABOOK1 flat blob before walking it.
static bool render_held_page (const void *base, uint32_t *out_crc, uint32_t *out_glyphs)
 Re-render the held page from the validated book and fold its CRC.
static void notify_m85 (void)
 Poke the M85's IPC0 receive line to wake it from a page-turn park.
static void simulate_touch_dwell (void)
 Spin a bounded page-dwell that stands in for a touch-poll latency.
static bool wait_for_ack (volatile const erm33_mailbox_t *mb, uint32_t turn)
 Poll the mailbox until the M85 acks page turn turn (heavy work done).
static void run_page_turns (volatile erm33_mailbox_t *mb, const void *base)
 Hold the page and run the #150 page-turn handoff loop for the M85.
static void cpu1_park (void)
 Park the M33 forever once the held page has been published.
static void cpu1_fail (volatile erm33_mailbox_t *mb, uint32_t status)
 Mark a failure status, publish done, and park the M33.
static void cpu1_run_reader (void)
 CPU1 reader entry: validate the book, render the held page, publish.
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.
static uint8_t s_framebuffer [k_erm33_fb_bytes]
 The M33's RGB565 page framebuffer, resident in external SDRAM.
const uintptr_t g_cpu1_vector_table []

Detailed Description

CPU1 (Cortex-M33 secondary core) image: render a held e-reader page.

Tag
[Ring1/app] {World: NS}

This is the firmware that runs on the RA8D2's second core, the Cortex-M33, for the #150 power-saving 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 hands the reader to this core via ra8_cpu1_release (HUM Ch 2.9.1) and PARKS. From then on the M33 is the live core holding the page.

The M33 runs the reader's data path AND renders one page to real pixels through the production ra8_gfx text stack – the same scalar (no-Helium) renderer the M85 e-reader uses, here driving a framebuffer that lives in external SDRAM:

  1. Stamp k_erm33_m33_sig into the shared mailbox so the parked M85 can prove the M33 left reset and is executing user code.
  2. Validate the baked, already-inflated RABOOK1 flat blob (rabook_fixture.h) – magic, version, size, table counts – the same first step the real loader takes before walking a book.
  3. Walk chapter 0's DOM subtree iteratively (NASA Rule 1: an explicit stack, no recursion) with the pure inline book.h accessors, collecting the opening k_erm33_page_chars characters of extracted text.
  4. Bind the SDRAM RGB565 framebuffer (s_framebuffer, placed in .sdram_bss at 0x68000000) with ra8_gfx_init, clear it to paper white, and blit the collected text line by line with ra8_gfx_text_out.
  5. Fold a CRC-32 over the rendered pixels – reading them back out of SDRAM is itself the proof real pixels landed – and PUBLISH the framebuffer base, geometry, format, glyph count and CRC into the shared mailbox.
  6. Set status = ok, done = 1, then enter the #150 MODE-SWITCH hold loop: the M33 holds the page and polls a (fake) touch input. On each page turn it bumps turn_req, POKES the parked M85 over IPC0 (ra8_ipc_send_event, HUM Ch 3.2.11 p 215) to wake it, waits for the M85's heavy-work ack (turn_ack), RE-RENDERS the held page (re-folding the same deterministic CRC), and signals turn_done. After k_erm33_max_turns turns it holds forever. A bad blob or render sets a failure status, then done.
Note
Only book.h (header-only inline accessors), ra8_gfx (three dependency-clean, zero-heap, scalar TUs) and the ra8_ipc send path (for the page-turn wake poke) are linked – no decompression, no logging backend (RA8_LOG_LEVEL=0 collapses ra8_ipc's log calls), no panel driver – so this freestanding M33 image keeps a clean link.
The M33 deliberately does NOT call ra8_log: ra8_emulator echoes only the primary core's ITM, so an M33 log line would be invisible. Its proof-of-life is the mailbox the M85 narrates and the CRC it publishes.
The touch is fake (a bounded page-dwell spin): on real hardware this is replaced by a GT911 touch-controller poll, a HIL follow-up.
The framebuffer is the M33's own RGB565 plane in external SDRAM, not yet the GLCDC scan-out plane; wiring the held plane to the live panel + the display-plane handoff is a later increment (#150).
Since
0.1.0

Definition in file cpu1_main.c.

Enumeration Type Documentation

◆ cpu1_ipc_t

enum cpu1_ipc_t : uint8_t

IPC channel the M33 pokes to wake the parked M85 on a page turn.

IPC0 channel 0 is the CPU1 -> CPU0 direction; writing its IPC0ISET0 raises the IPC0 receive interrupt the M85 armed before release, so the M85 leaves WFI as soon as a page-turn request is published.

Since
0.1.0
Enumerator
k_cpu1_ipc_wake_channel 

IPC0 channel 0 (CPU1 -> CPU0).

Definition at line 176 of file cpu1_main.c.

◆ m33_crc_bits_t

enum m33_crc_bits_t : uint8_t

Bit-fold count for the bitwise CRC-32 inner loop.

Since
0.1.0
Enumerator
k_crc32_bits 

Bits folded per input byte.

Definition at line 164 of file cpu1_main.c.

◆ m33_crc_t

enum m33_crc_t : uint32_t

Constants for the standard reflected CRC-32 over the rendered plane.

The M33 folds every byte of its SDRAM framebuffer through the IEEE 802.3 / zlib CRC-32 (reflected polynomial, pre/post-inverted), so the published value is a stable fingerprint of the exact pixels drawn.

Since
0.1.0
Enumerator
k_crc32_init 

Pre/post-inversion seed.

k_crc32_poly 

Reflected CRC-32 polynomial.

Definition at line 154 of file cpu1_main.c.

◆ m33_cycle_bound_t

enum m33_cycle_bound_t : uint32_t

Static bound for the M33's wait-for-ack poll (NASA Rule 2).

The M85 acknowledges a page turn within a few ra8_emulator interleaves; this bound is the backstop so a never-arriving ack still terminates the loop instead of hanging the held-page cycle.

Since
0.1.0
Enumerator
k_m33_ack_budget 

Max iters waiting for the M85's turn_ack.

Definition at line 188 of file cpu1_main.c.

◆ m33_render_t

enum m33_render_t : uint32_t

Glyph cell height and page colours for the ra8_gfx blit.

The bundled ra8_gfx font is 8x16, so glyph rows advance by 16 px. The page is rendered as black ink on a white paper background, the conventional e-reader palette.

Since
0.1.0
Enumerator
k_erm33_glyph_h 

ra8_gfx 8x16 font cell height, pixels.

k_erm33_paper 

Page background colour (white).

k_erm33_ink 

Glyph foreground colour (black).

Definition at line 140 of file cpu1_main.c.

◆ m33_walk_bound_t

enum m33_walk_bound_t : uint32_t

Static iteration bounds for the M33 DOM walk (NASA Rule 2).

Each loop in the reader is bounded by one of these compile-time constants so the M33 can never run unbounded on a corrupt blob.

Since
0.1.0
Enumerator
k_walk_iter_max 

Max DOM-walk pops in the chapter.

k_max_run_len 

Bounded text-run length cap, bytes.

Definition at line 113 of file cpu1_main.c.

◆ m33_walk_size_t

enum m33_walk_size_t : uint16_t

Small table / validation sizes for the M33 reader.

The DOM-walk stack depth and the validation caps that reject an implausible blob before the walk begins.

Since
0.1.0
Enumerator
k_walk_stack_depth 

Explicit DOM-walk stack depth.

k_max_chapters 

Validation cap on chapter_count.

k_max_nodes 

Validation cap on node_count.

k_magic_len 

"RABOOK1" magic length (no NUL).

Definition at line 125 of file cpu1_main.c.

Function Documentation

◆ append_run()

void append_run ( char * out,
uint32_t * plen,
uint32_t cap,
const char * txt )
static

Append one NUL-terminated text run into the page accumulator.

Scans txt up to its NUL or the static k_max_run_len cap, copying each character into out until out reaches cap. A run that would overflow the page is truncated, never wrapped past the buffer.

Parameters
[in,out]outPage accumulator (never NULL).
[in,out]plenIn/out count of characters already buffered (never NULL).
[in]capCapacity of out in characters.
[in]txtNUL-terminated run from the validated blob (may be NULL).
Returns
Nothing.
Precondition
out and plen are non-NULL; *plen <= cap.
txt, when non-NULL, points inside the validated blob's string pool.
Postcondition
*plen <= cap still holds.
Iteration bounded by k_max_run_len (NASA Rule 2).
Note
Single-threaded; runs in M33 thread mode with no RTOS.
Since
0.1.0

Definition at line 214 of file cpu1_main.c.

References k_max_run_len, and RA8_LOOP_BOUND.

Referenced by collect_chapter_text().

◆ book_is_valid()

bool book_is_valid ( const void * base,
uint32_t size )
static

Validate the baked RABOOK1 flat blob before walking it.

Checks the "RABOOK1" magic, the format version, that the header's total_size matches the baked length, and that the chapter / node counts are non-zero and within sane caps. Mirrors the real loader's gate so the M33 never walks a malformed blob (the inline accessors do no bounds checking).

Parameters
[in]baseCandidate blob base (never NULL in this app).
[in]sizeBaked blob length in bytes (k_rabook_fixture_len).
Returns
Whether the blob is well-formed enough to walk.
Return values
trueMagic, version, size and table counts are all plausible.
falseAny check failed; the caller must not walk the blob.
Precondition
base points at the baked fixture rodata.
size is the true baked length.
Postcondition
No field of the blob is modified.
On false, no accessor is subsequently called on base.
Note
Pure; reads only the immutable candidate blob.
Since
0.1.0

Definition at line 522 of file cpu1_main.c.

References book_header(), book_header_t::chapter_count, book_header_t::format_version, k_book_format_version, k_book_sizeof_header, k_magic_len, k_max_chapters, k_max_nodes, book_header_t::magic, book_header_t::node_count, RA8_LOOP_BOUND, and book_header_t::total_size.

Referenced by cpu1_run_reader().

◆ collect_chapter_text()

uint32_t collect_chapter_text ( const void * base,
uint32_t root,
uint32_t node_count,
char * out,
uint32_t cap )
static

Collect a chapter's opening text into the page accumulator.

Iterative pre-order walk (NASA Rule 1: an explicit index stack, no recursion) rooted at root. The root's own siblings are never followed, so the walk stays inside this chapter. Each text node's run is appended via append_run; the walk stops once cap characters are buffered. The pop loop is bounded by k_walk_iter_max.

Parameters
[in]baseValidated RABOOK1 blob base (never NULL).
[in]rootChapter root node index, or k_book_nil.
[in]node_countNode-table length (an out-of-range index is dropped).
[out]outPage accumulator (never NULL).
[in]capCapacity of out in characters.
Returns
Count of characters collected (<= cap).
Return values
0base or out was NULL, or the chapter held no text.
Precondition
base was accepted by book_is_valid.
out has room for cap characters.
Postcondition
The return value is <= cap.
Iteration is bounded by k_walk_iter_max (NASA Rule 2).
Note
Single-threaded; runs in M33 thread mode with no RTOS.
Since
0.1.0

Definition at line 309 of file cpu1_main.c.

References append_run(), book_node_text(), book_nodes(), book_node_t::first_child, m33_walk_stack_t::items, k_book_nil, k_book_node_text, k_walk_iter_max, book_node_t::kind, book_node_t::next_sibling, RA8_LOOP_BOUND, m33_walk_stack_t::sp, and walk_push().

Referenced by render_held_page().

◆ cpu1_fail()

void cpu1_fail ( volatile erm33_mailbox_t * mb,
uint32_t status )
static

Mark a failure status, publish done, and park the M33.

Parameters
[out]mbShared mailbox (never NULL).
[in]statusFailure status code (erm33_const_t).
Returns
This function never returns.
Note
Control ends in cpu1_park.
Precondition
mb is the fixed-address mailbox pointer.
A validation or render step failed.
Postcondition
mb->status == status and mb->done == 1, both behind a dsb.
The M33 makes no further forward progress.
Note
Single-threaded; runs in M33 thread mode with no RTOS.
Since
0.1.0

Definition at line 785 of file cpu1_main.c.

References cpu1_park(), erm33_mailbox_t::done, and erm33_mailbox_t::status.

Referenced by cpu1_run_reader().

◆ 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.
done stays at whatever value it held at fault time, so a fault before completion is visible to the M85 as a stalled, never-done reader.
Note
Shared default for all CPU1 exception vectors.
Since
0.1.0

Definition at line 905 of file cpu1_main.c.

◆ cpu1_park()

void cpu1_park ( void )
static

Park the M33 forever once the held page has been published.

Returns
This function never returns.
Note
The core spins in place.
Precondition
The mailbox already carries the final status / done.
Entered only after the render completes (or fails validation).
Postcondition
The M33 makes no further forward progress.
The published mailbox state is stable for the M85 to read.
Note
Mirrors the sibling dual-core park loops; this is the held-page idle.
Since
0.1.0

Definition at line 761 of file cpu1_main.c.

◆ cpu1_reset_handler()

void cpu1_reset_handler ( void )

CPU1 reset handler: minimal C-runtime init, then run the reader.

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. The SDRAM framebuffer is in a NOLOAD section and is painted by ra8_gfx_clear, so it is deliberately left out of this init.

Returns
This function never returns.
Note
Control passes to cpu1_run_reader, which holds 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 868 of file cpu1_main.c.

References cpu1_run_reader(), 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.

◆ cpu1_run_reader()

void cpu1_run_reader ( void )
static

CPU1 reader entry: validate the book, render the held page, publish.

Stamps the boot signature, validates the baked RABOOK1 blob, renders chapter 0's opening page into the SDRAM framebuffer (render_held_page), publishes the descriptor, and sets status = ok, done = 1. It then becomes the live core for the #150 mode-switch: it runs the page-turn hold loop (run_page_turns) – holding the page, waking the parked M85 on each scripted touch, and re-rendering – before holding for good. A failure at any step publishes the matching failure status and parks.

Returns
This function never returns.
Note
Control ends in cpu1_park.
Precondition
cpu1_reset_handler has initialised .data / .bss.
The M85 published k_erm33_magic and released this core.
Postcondition
mb->done == 1 with status, geometry and fb_crc reflecting the run.
On success the SDRAM framebuffer holds the (re-rendered) held page.
Note
Single-threaded; runs in M33 thread mode with no RTOS.
Since
0.1.0

Definition at line 818 of file cpu1_main.c.

References book_is_valid(), cpu1_fail(), cpu1_park(), erm33_mailbox_t::done, erm33_mailbox(), k_erm33_m33_sig, k_erm33_status_bad_book, k_erm33_status_ok, k_erm33_status_render_fail, k_rabook_fixture, k_rabook_fixture_len, erm33_mailbox_t::m33_sig, publish_page(), render_held_page(), run_page_turns(), and erm33_mailbox_t::status.

Referenced by cpu1_reset_handler().

◆ fb_crc32()

uint32_t fb_crc32 ( const uint8_t * fb,
uint32_t len )
static

Fold a reflected CRC-32 over the rendered framebuffer pixels.

Standard table-less reflected CRC-32: seed all-ones, fold each byte LSB-first through k_crc32_poly, post-invert. Reading every byte back out of SDRAM is what proves the M33's pixels actually landed; a blank plane hashes to one fixed value, so a different CRC demonstrates genuine rendering.

Parameters
[in]fbFramebuffer base (never NULL).
[in]lenBytes to hash; expected to equal k_erm33_fb_bytes.
Returns
CRC-32 of the len bytes at fb.
Return values
0fb is NULL or len is 0 (no pixels to hash).
Precondition
fb addresses the rendered SDRAM framebuffer.
The render completed and a dsb drained the pixels to SDRAM.
Postcondition
No framebuffer byte is modified.
Both loops are bounded (k_erm33_fb_bytes, k_crc32_bits; NASA Rule 2).
Note
Single-threaded; runs in M33 thread mode with no RTOS.
Since
0.1.0

Definition at line 439 of file cpu1_main.c.

References k_crc32_bits, k_crc32_init, k_crc32_poly, k_erm33_fb_bytes, and RA8_LOOP_BOUND.

Referenced by render_held_page().

◆ notify_m85()

void notify_m85 ( void )
static

Poke the M85's IPC0 receive line to wake it from a page-turn park.

Writes IPC0ISET0 for the wake channel (HUM Ch 3.2.11 "IPC0ISET0" p 215), asserting IRQ line 0 on the primary core. turn_req is already published and dsb-ordered ahead of this call, so the woken M85 observes a settled request. The HAL return value is intentionally discarded: a failed poke only costs the M85 a fall-through to its bounded poll, never correctness.

Returns
Nothing.
Precondition
turn_req is published behind a dsb.
The M85 armed the IPC0 receive IRQ before releasing this core.
Postcondition
IPC0 channel-0 IRQ line 0 is asserted toward the M85.
No shared mailbox field is modified.
Note
Single-threaded; runs in M33 thread mode with no RTOS.
Since
0.1.0

Definition at line 626 of file cpu1_main.c.

References k_cpu1_ipc_wake_channel, k_ra8_ipc_irq_event_0, and ra8_ipc_send_event().

◆ publish_page()

void publish_page ( volatile erm33_mailbox_t * mb,
uint32_t crc,
uint32_t glyphs )
static

Publish the rendered page's base, geometry, format and CRC.

Writes the SDRAM framebuffer address, the agreed RGB565 geometry, the glyph count and the freshly-folded CRC into the shared mailbox, each behind a dsb so the parked M85 observes a fully-formed descriptor.

Parameters
[out]mbShared mailbox (never NULL).
[in]crcCRC-32 the M33 folded over the framebuffer.
[in]glyphsCharacters laid onto the held page.
Returns
Nothing.
Precondition
mb is the fixed-address mailbox pointer.
The framebuffer at s_framebuffer holds the rendered page.
Postcondition
fb_base / geometry / fb_crc / glyph_count are published with a dsb.
No field the M85 owns (magic) is touched.
Note
Single-threaded; runs in M33 thread mode with no RTOS.
Since
0.1.0

Definition at line 484 of file cpu1_main.c.

References erm33_mailbox_t::fb_base, erm33_mailbox_t::fb_crc, erm33_mailbox_t::fb_format, erm33_mailbox_t::fb_height, erm33_mailbox_t::fb_stride, erm33_mailbox_t::fb_width, erm33_mailbox_t::glyph_count, k_erm33_fb_format_rgb565, k_erm33_fb_height, k_erm33_fb_stride, k_erm33_fb_width, and s_framebuffer.

Referenced by cpu1_run_reader(), and run_page_turns().

◆ render_held_page()

bool render_held_page ( const void * base,
uint32_t * out_crc,
uint32_t * out_glyphs )
static

Re-render the held page from the validated book and fold its CRC.

Re-collects chapter 0's opening text, renders it into the SDRAM framebuffer via ra8_gfx, drains the writes with a dsb, then folds the CRC-32 over the rendered pixels. Pure of the mailbox and fully deterministic – the same immutable blob renders the same bytes – so every call (the first render and each page-turn re-render) yields the identical CRC, keeping the ra8_emulator gate's golden stable.

Parameters
[in]baseValidated RABOOK1 blob base (never NULL).
[out]out_crcReceives the CRC-32 of the rendered framebuffer.
[out]out_glyphsReceives the count of characters laid onto the page.
Returns
Whether the render + CRC fold succeeded.
Return values
trueThe page rendered and out_crc / out_glyphs are set.
falsebase / out_crc / out_glyphs was NULL, or ra8_gfx failed.
Precondition
base was accepted by book_is_valid.
out_crc and out_glyphs are writable.
Postcondition
On true the SDRAM framebuffer holds the rendered held page.
On false no published mailbox field should be trusted.
Note
Single-threaded; runs in M33 thread mode with no RTOS.
Since
0.1.0

Definition at line 579 of file cpu1_main.c.

References book_chapters(), book_header(), collect_chapter_text(), fb_crc32(), k_erm33_fb_bytes, k_erm33_page_chars, book_header_t::node_count, render_page(), and s_framebuffer.

Referenced by cpu1_run_reader(), and run_page_turns().

◆ render_page()

bool render_page ( uint8_t * fb,
const char * text,
uint32_t len )
static

Render the collected page text into the SDRAM framebuffer via ra8_gfx.

Binds fb as an RGB565 canvas, clears it to paper white, then lays the len buffered characters out left-to-right, wrapping to the next glyph row every k_erm33_fb_cols cells, blitting each row string with one ra8_gfx_text_out. The row loop is bounded by k_erm33_fb_rows.

Parameters
[out]fbSDRAM framebuffer base (never NULL).
[in]textCollected page text (never NULL).
[in]lenCount of valid characters in text.
Returns
Whether every ra8_gfx call succeeded.
Return values
trueThe plane holds the page over a paper-white background.
falseA NULL argument or an ra8_gfx error; the plane is undefined.
Precondition
fb is k_erm33_fb_bytes bytes of SDRAM.
text holds at least len characters.
Postcondition
On true every framebuffer byte was written (paper or glyph pixels).
Iteration bounded by k_erm33_fb_rows (NASA Rule 2).
Note
Single-threaded; runs in M33 thread mode with no RTOS.
Since
0.1.0

Definition at line 370 of file cpu1_main.c.

References k_erm33_fb_cols, k_erm33_fb_height, k_erm33_fb_rows, k_erm33_fb_width, k_erm33_glyph_h, k_erm33_ink, k_erm33_paper, k_ra8_gfx_format_rgb565, k_ra8_ok, ra8_gfx_clear(), ra8_gfx_font_8x16, ra8_gfx_init(), ra8_gfx_text_out(), and RA8_LOOP_BOUND.

Referenced by render_held_page().

◆ run_page_turns()

void run_page_turns ( volatile erm33_mailbox_t * mb,
const void * base )
static

Hold the page and run the #150 page-turn handoff loop for the M85.

For each of k_erm33_max_turns turns the M33 dwells on the held page (simulate_touch_dwell), publishes the page-turn request (turn_req) behind a dsb, pokes the parked M85 (notify_m85), waits for the M85's heavy-work ack (wait_for_ack), RE-RENDERS the held page (render_held_page – same content, same CRC), republishes the descriptor, and sets turn_done. A missed ack ends the loop. The outer loop is bounded by k_erm33_max_turns (NASA Rule 2).

Parameters
[in,out]mbShared mailbox (never NULL).
[in]baseValidated RABOOK1 blob base (never NULL).
Returns
Nothing.
Precondition
mb is the fixed-address mailbox pointer with the first page published.
base was accepted by book_is_valid.
Postcondition
turn_done advances to the last completed turn (<= k_erm33_max_turns).
The SDRAM framebuffer holds the (re-rendered) held page on return.
Note
Single-threaded; runs in M33 thread mode with no RTOS.
Since
0.1.0

Definition at line 720 of file cpu1_main.c.

References k_erm33_max_turns, notify_m85(), publish_page(), RA8_LOOP_BOUND, render_held_page(), simulate_touch_dwell(), erm33_mailbox_t::turn_done, erm33_mailbox_t::turn_req, and wait_for_ack().

Referenced by cpu1_run_reader().

◆ simulate_touch_dwell()

void simulate_touch_dwell ( void )
static

Spin a bounded page-dwell that stands in for a touch-poll latency.

The real e-reader would poll the GT911 touch controller while holding the page; here the M33 spins k_erm33_touch_dwell times on a volatile counter so ra8_emulator interleaves the cores a few times before the synthetic page turn fires. Deterministic and bounded (NASA Rule 2); replaced by a real touch poll on hardware (a HIL follow-up).

Returns
Nothing.
Precondition
Runs in M33 thread mode while holding the rendered page.
k_erm33_touch_dwell is the agreed dwell bound.
Postcondition
No shared state is modified.
Iteration count bounded by k_erm33_touch_dwell (NASA Rule 2).
Note
Single-threaded; pure busy-wait with no side effects.
Since
0.1.0

Definition at line 650 of file cpu1_main.c.

References k_erm33_touch_dwell, and RA8_LOOP_BOUND.

Referenced by run_page_turns().

◆ wait_for_ack()

bool wait_for_ack ( volatile const erm33_mailbox_t * mb,
uint32_t turn )
static

Poll the mailbox until the M85 acks page turn turn (heavy work done).

After the M33 requests a page turn and pokes the M85, the woken M85 does its heavy next-page work and writes turn_ack. This bounded poll waits for that ack across ra8_emulator's core interleaves; the bound is the NASA Rule 2 backstop for an ack that never arrives.

Parameters
[in]mbShared mailbox (never NULL).
[in]turnThe page-turn number being acknowledged (1-based).
Returns
Whether turn_ack reached turn within budget.
Return values
trueturn_ack >= turn within k_m33_ack_budget iterations.
falsemb was NULL or the budget was exhausted first.
Precondition
mb is the fixed-address mailbox pointer; turn_req == turn published.
The M85 was poked via notify_m85.
Postcondition
No mailbox field is modified.
Iteration count bounded by k_m33_ack_budget (NASA Rule 2).
Note
Single-threaded; runs in M33 thread mode with no RTOS.
Since
0.1.0

Definition at line 683 of file cpu1_main.c.

References k_m33_ack_budget, RA8_LOOP_BOUND, and erm33_mailbox_t::turn_ack.

Referenced by run_page_turns().

◆ walk_push()

void walk_push ( m33_walk_stack_t * st,
uint32_t node )
static

Push a node index onto the DOM-walk stack if it fits.

Parameters
[in,out]stWalk stack (never NULL).
[in]nodeNode index to push, or k_book_nil to ignore.
Returns
Nothing.
Precondition
st is non-NULL with sp <= k_walk_stack_depth.
node is a node index or the nil sentinel.
Postcondition
A non-nil node is pushed unless the stack is full (then dropped).
st->sp <= k_walk_stack_depth still holds.
Note
Single-threaded; runs in M33 thread mode with no RTOS.
Since
0.1.0

Definition at line 268 of file cpu1_main.c.

References m33_walk_stack_t::items, k_book_nil, k_walk_stack_depth, and m33_walk_stack_t::sp.

Referenced by collect_chapter_text().

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 926 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).

◆ s_framebuffer

uint8_t s_framebuffer[k_erm33_fb_bytes]
static

The M33's RGB565 page framebuffer, resident in external SDRAM.

Placed in the .sdram_bss (NOLOAD) section the CPU1 linker script pins at the SDRAM base (0x68000000); ra8_gfx_clear paints every byte before the page is published, so it needs no startup zeroing. The M33 publishes its address (&s_framebuffer) in the mailbox's fb_base.

Warning
Written only through ra8_gfx; do not modify directly.
Since
0.1.0

Definition at line 104 of file cpu1_main.c.