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

A/B OTA orchestration demo: stage -> verify -> commit / rollback over MRAM. More...

#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include "ra8_board_ek_ra8d2.h"
#include "ra8_boot_entry.h"
#include "ra8_cgc.h"
#include "ra8_check.h"
#include "ra8_err.h"
#include "ra8_flash.h"
#include "ra8_ota.h"
#include "ra8_rsip.h"
#include "ra8_secure.h"
Include dependency graph for main.c:

Go to the source code of this file.

Data Structures

struct  app_net_source_t
 In-RAM "download" cursor handed to the OTA net interface. More...

Enumerations

enum  app_const_t : uint32_t {
  k_app_uart_baud = 115200U ,
  k_app_image_bytes = 256U ,
  k_app_bank_size_bytes = 4096U ,
  k_app_report_delay = 4000000U ,
  k_app_bootsel_magic = 0xB007A8B1U ,
  k_app_demo_pubkey = 0x0A8D2C0DU
}
 Console, MRAM layout, and demo-image sizing constants. More...
enum  app_mram_addr_t : uintptr_t {
  k_app_bank_addr = k_ra8_flash_extra_start ,
  k_app_bootsel_addr
}
 Extra-MRAM option-setting addresses the demo owns (0x02E07600, 12 KiB). More...
enum  app_bank_t : uint8_t {
  k_app_bank_a = 0U ,
  k_app_bank_b = 1U
}
 A/B slot identifiers persisted in the boot-select record. More...
enum  app_size_t : uint8_t {
  k_app_mram_block_bytes = 32U ,
  k_app_sig_bytes = 32U ,
  k_app_rec_off_magic = 0U ,
  k_app_rec_off_bank = 4U ,
  k_app_rec_off_seq = 5U ,
  k_app_octet_bits = 8U
}
 Small byte-width and record-layout constants. More...
enum  app_flash_freq_t : uint16_t {
  k_app_mrcfreq_mhz = 200U ,
  k_app_mrefreq_mhz = 100U
}
 MRAM controller advertised clock rates for ra8_flash_init. More...
enum  app_pattern_t : uint8_t {
  k_app_img_seed_mul = 7U ,
  k_app_img_seed_add = 3U ,
  k_app_sig_tag_base = 0xA5U ,
  k_app_byte_all_ones = 0xFFU
}
 Deterministic demo-image byte-pattern + tag constants. More...
enum  app_outcome_t : uint8_t {
  k_app_outcome_committed = 0U ,
  k_app_outcome_rolled_back = 1U ,
  k_app_outcome_indeterminate = 2U
}
 Classified result of one A/B update attempt. More...

Functions

static size_t app_strlen (const char *text)
 Bounded length of a NUL-terminated ASCII string.
static void app_print (const char *text)
 Print a NUL-terminated ASCII string on the board VCOM console.
static ra8_err_t app_net_open (void *ctx, const char *url, uint32_t *out_content_len)
 Begin serving the staged image (OTA net.open).
static ra8_err_t app_net_read (void *ctx, uint8_t *dst, uint32_t cap, uint32_t *out_len)
 Copy up to cap bytes from the staged image (OTA net.read).
static ra8_err_t app_net_close (void *ctx)
 Tear down the local stream (OTA net.close); a no-op here.
static ra8_err_t app_sha_init (void *ctx)
 Begin a streaming SHA-256 (OTA crypto.sha256_init).
static ra8_err_t app_sha_update (void *ctx, const uint8_t *data, uint32_t len)
 Absorb bytes into the SHA-256 (OTA crypto.sha256_update).
static ra8_err_t app_sha_final (void *ctx, uint8_t out[k_ra8_ota_sha256_bytes])
 Finalise the SHA-256 digest (OTA crypto.sha256_final).
static ra8_err_t app_ecdsa_verify (void *ctx, uint32_t pubkey, const uint8_t bound[k_ra8_ota_sha256_bytes], const uint8_t *sig, uint32_t sig_len)
 DEMO authenticity check standing in for ECDSA-P256 (OTA crypto.ecdsa_verify).
static ra8_err_t app_flash_erase (void *ctx, uint32_t addr, uint32_t len)
 Erase the inactive bank region (OTA flash.erase).
static ra8_err_t app_flash_program (void *ctx, uint32_t addr, const uint8_t *src, uint32_t len)
 Program bytes into the inactive bank (OTA flash.program).
static ra8_err_t app_flash_readback (void *ctx, uint32_t addr, uint8_t *dst, uint32_t len)
 Read the inactive bank back for re-hash (OTA flash.readback).
static ra8_err_t app_write_bootsel (uint8_t bank)
 Persist the A/B boot-select record for bank.
static ra8_err_t app_flash_set_startup (void *ctx, uint8_t which_bank, bool persistent)
 Latch the inactive bank as the next boot bank (OTA flash.set_startup).
static ra8_err_t app_read_bootsel (uint8_t *out_bank, bool *out_valid)
 Read the persisted boot-select record.
static app_outcome_t app_ab_classify (ra8_err_t result, ra8_ota_state_t state)
 Classify one update attempt from its return code and final state.
static bool app_ab_ok (bool committed, bool rolled_back)
 Final demo verdict: both A/B paths behaved as designed.
static void app_make_cfg (ra8_ota_cfg_t *cfg)
 Assemble the OTA config wired to this app's backends.
static void app_make_manifest (ra8_ota_manifest_t *m)
 Build the demo manifest describing the good image.
static app_outcome_t app_run_attempt (const uint8_t *source, const ra8_ota_manifest_t *m, uint8_t *out_bank)
 Drive one full A/B attempt against source and classify it.
static ra8_err_t app_stage_images (void)
 Fill the golden/corrupt image blobs and precompute the manifest digest.
static ra8_err_t app_setup (void)
 Bring up CGC + the board VCOM console + the MRAM controller.
static void app_print_banner (bool staged, bool committed, bool rolled_back)
 Print the one-line A/B verdict banner over the console.
void main (void)
 Application entry: run both A/B paths once, then report forever.

Variables

static const char *const s_tag = "ota_ab"
 Module log/console tag.
static app_net_source_t s_net_source
 The staged image source (rebound per scenario).
static ra8_rsip_sha256_ctx_t s_sha_ctx
 Streaming SHA-256 context backing the OTA crypto interface.
static uint32_t s_bootsel_seq = 0U
 Monotonic sequence number stamped into each boot-select record.
static uint8_t s_image_good [k_app_image_bytes]
 Golden image bytes for the commit path (deterministic pattern).
static uint8_t s_image_bad [k_app_image_bytes]
 Corrupted image bytes for the rollback path (one flipped byte).
static uint8_t s_image_good_digest [k_ra8_ota_sha256_bytes]
 SHA-256 of s_image_good, published as the manifest digest.

Detailed Description

A/B OTA orchestration demo: stage -> verify -> commit / rollback over MRAM.

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

Exercises the libs/ra8_ota A/B slot state machine end to end on the EK-RA8D2, over the on-chip extra-MRAM (data-flash) bank model that tools/ra8_emulator already reproduces (board_periph_mram.c, the MACI program/erase sequencer). ra8_ota is Dependency-Inversion pure: it drives injected net / crypto / flash interfaces, so this app supplies concrete backends and runs BOTH outcomes of the A/B flow in a single boot:

  • COMMIT path – a good image is streamed into the inactive bank (ra8_ota_download_to_inactive_bank), the freshly programmed bank is re-hashed and its signature checked (ra8_ota_verify_signature), and the inactive bank is latched as the next boot bank (ra8_ota_commit_and_reboot -> flash.set_startup). The persisted boot-select record flips from bank A to bank B.
  • ROLLBACK path – a corrupted image is streamed into the inactive bank; the re-hash no longer matches the manifest digest, so verification fails (k_ra8_err_crc_mismatch), the machine parks in error, commit is never reached, and the boot-select record is left pointing at the still-good active bank A. This is the safe rollback a real bootloader relies on.
Backends (EIL==HIL):
  • flash routes to the real ra8_flash extra-MRAM driver (ra8_flash_extra_mram_write / _erase + direct read-back), so the stage / re-hash / boot-select persistence run the exact MACI register sequence ra8_emulator models – the same code path a bench run drives.
  • crypto routes SHA-256 to the real software SHA backend (ra8_rsip_sha256*); identical on host, emulator and silicon (there is no RSIP hash-hardware on this part). Image INTEGRITY (the digest match that triggers the rollback) is therefore verified for real.
  • net is a local in-RAM image source (no TLS stack is wired yet). The signature verifier is a DEMO authenticity stub, NOT real ECDSA-P256; a production build swaps in a tf-psa-crypto / ra8_tls backend. See the TODO markers at app_ecdsa_verify and s_net_source.

A successful run prints, once per report cycle, on the J-Link OB VCOM console: ota_ab: stage=ok commit=Y rollback=Y ok=Y.

Author
Brighton Sikarskie
Date
2026-07-16
Since
0.1.0

Definition in file main.c.

Enumeration Type Documentation

◆ app_bank_t

enum app_bank_t : uint8_t

A/B slot identifiers persisted in the boot-select record.

Enumerator
k_app_bank_a 

Slot A (the initially-active bank).

k_app_bank_b 

Slot B (the inactive/update target).

Definition at line 110 of file main.c.

◆ app_const_t

enum app_const_t : uint32_t

Console, MRAM layout, and demo-image sizing constants.

Centralises every numeric limit the demo references so the flow reads without bare literals (NASA Rule 8 + CLAUDE.md "C23 typed enums").

Enumerator
k_app_uart_baud 

J-Link OB VCOM console baud.

k_app_image_bytes 

Demo firmware image size (multiple of 32).

k_app_bank_size_bytes 

Advertised bank capacity for the OTA cfg.

k_app_report_delay 

Bounded busy-wait between banner prints.

k_app_bootsel_magic 

Boot-select record magic ("BOOT A/B").

k_app_demo_pubkey 

Opaque demo public-key handle.

Definition at line 78 of file main.c.

◆ app_flash_freq_t

enum app_flash_freq_t : uint16_t

MRAM controller advertised clock rates for ra8_flash_init.

Enumerator
k_app_mrcfreq_mhz 

Code-MRAM advertised clock (MHz).

k_app_mrefreq_mhz 

Extra-MRAM advertised clock (MHz).

Definition at line 132 of file main.c.

◆ app_mram_addr_t

enum app_mram_addr_t : uintptr_t

Extra-MRAM option-setting addresses the demo owns (0x02E07600, 12 KiB).

The inactive "bank" is staged at the region base; the persistent boot-select record lives in a separate 32-byte block clear of the image so an OTA bank erase never touches it (HUM Ch 59.7.4.5 Table 59.15 p 3592).

Warning
This window is one-time-programmable option-setting / OTP memory, not a rewritable data-flash bank: the erase + re-stage cycle an A/B updater needs does NOT work on real silicon. ra8_emulator maps the window so the demo passes here, but a real inactive-bank home (OSPI / SD) is tracked by #315.
Enumerator
k_app_bank_addr 

Inactive-bank base (extra-MRAM start).

k_app_bootsel_addr 

Persistent boot-select record (own block).

Definition at line 100 of file main.c.

◆ app_outcome_t

enum app_outcome_t : uint8_t

Classified result of one A/B update attempt.

Produced by app_ab_classify from the state-machine return code and final state; the demo checks that the good image yields committed and the corrupted image yields rolled_back.

Enumerator
k_app_outcome_committed 

Verify passed and the bank swap latched.

k_app_outcome_rolled_back 

Verify failed; no swap; active bank kept.

k_app_outcome_indeterminate 

Neither terminal shape matched.

Definition at line 160 of file main.c.

◆ app_pattern_t

enum app_pattern_t : uint8_t

Deterministic demo-image byte-pattern + tag constants.

The golden image is byte[i] = i*mul + add; the corrupt image flips byte 0 with an all-ones mask; the demo signature tag is a fixed base XOR-ed with its index.

Enumerator
k_app_img_seed_mul 

Golden-image pattern multiplier.

k_app_img_seed_add 

Golden-image pattern additive bias.

k_app_sig_tag_base 

Demo signature tag base byte.

k_app_byte_all_ones 

Corrupt-flip mask / erased MRAM byte.

Definition at line 145 of file main.c.

◆ app_size_t

enum app_size_t : uint8_t

Small byte-width and record-layout constants.

Enumerator
k_app_mram_block_bytes 

Extra-MRAM erase/program granularity.

k_app_sig_bytes 

Demo signature length.

k_app_rec_off_magic 

Boot-select record: magic byte offset.

k_app_rec_off_bank 

Boot-select record: bank byte offset.

k_app_rec_off_seq 

Boot-select record: seq byte offset.

k_app_octet_bits 

Bits per octet for LE spreads.

Definition at line 119 of file main.c.

Function Documentation

◆ app_ab_classify()

app_outcome_t app_ab_classify ( ra8_err_t result,
ra8_ota_state_t state )
static

Classify one update attempt from its return code and final state.

The A/B contract: a clean run ends (k_ra8_ok, done) = committed; a rejected image ends (!= k_ra8_ok, error) = rolled back; anything else is indeterminate (a bug or an aborted run).

Parameters
[in]resultReturn code from the driven OTA sequence.
[in]stateFinal ra8_ota_state_t reported by the machine.
Returns
app_outcome_t classification.
Return values
k_app_outcome_committedresult == ok and state == done.
k_app_outcome_rolled_backresult != ok and state == error.
k_app_outcome_indeterminateNeither terminal shape matched.
Precondition
None.
None.
Postcondition
No state changes.
Return solely determined by the two inputs.
Note
Pure function; test-mirrored for MC/DC.
Since
0.1.0

Definition at line 671 of file main.c.

References k_app_outcome_committed, k_app_outcome_indeterminate, k_app_outcome_rolled_back, k_ra8_ok, k_ra8_ota_state_done, and k_ra8_ota_state_error.

Referenced by app_run_attempt().

◆ app_ab_ok()

bool app_ab_ok ( bool committed,
bool rolled_back )
static

Final demo verdict: both A/B paths behaved as designed.

Parameters
[in]committedThe good-image attempt classified as committed.
[in]rolled_backThe corrupt-image attempt classified as rolled back.
Returns
Boolean verdict.
Return values
trueBoth paths matched their expected outcome.
falseEither path deviated.
Precondition
None.
None.
Postcondition
No state changes.
Return solely determined by the two inputs.
Note
Pure function; test-mirrored for MC/DC.
Since
0.1.0

Definition at line 697 of file main.c.

Referenced by app_print_banner().

◆ app_ecdsa_verify()

ra8_err_t app_ecdsa_verify ( void * ctx,
uint32_t pubkey,
const uint8_t bound[k_ra8_ota_sha256_bytes],
const uint8_t * sig,
uint32_t sig_len )
static

DEMO authenticity check standing in for ECDSA-P256 (OTA crypto.ecdsa_verify).

TODO(real ECDSA-P256): a production OTA verifies an asymmetric server signature over bound (the metadata-bound digest ra8_ota_verify_signature computes) through a tf-psa-crypto / ra8_psa_crypto backend, which is already proven in secure_boot_hil / psa_crypto_hil. This example is an orchestration demo, so it accepts iff the caller presented the configured demo key handle and a full-width tag – exercising the verify dispatch that GATES the commit without pulling a full PKI into the example. Update INTEGRITY (the digest match that drives the rollback path) is verified for real by the SHA re-hash upstream of this call, so the rollback demonstration is genuine.

Parameters
[in]ctxUnused opaque context.
[in]pubkeyPublic-key handle presented by the manifest.
[in]boundMetadata-bound digest (unused by the demo stub); non-NULL.
[in]sigSignature bytes; non-NULL.
[in]sig_lenSignature length in bytes.
Returns
ra8_err_t outcome.
Return values
k_ra8_okDemo key + tag width accepted.
k_ra8_err_hw_errorWrong key handle or tag width (verify rejects).
k_ra8_err_null_ptrA pointer argument was NULL.
Precondition
bound and sig are non-NULL.
pubkey is the handle set in the OTA config.
Postcondition
No state changes.
Return solely determined by the inputs.
Note
Not thread-safe; single OTA owner. Pure decision.
Since
0.1.0

Definition at line 436 of file main.c.

References k_app_demo_pubkey, k_app_sig_bytes, k_ra8_err_hw_error, k_ra8_ok, k_ra8_ota_sha256_bytes, RA8_CHECK_NULL_PTR, and s_tag.

Referenced by app_make_cfg().

◆ app_flash_erase()

ra8_err_t app_flash_erase ( void * ctx,
uint32_t addr,
uint32_t len )
static

Erase the inactive bank region (OTA flash.erase).

Walks len bytes from addr one k_app_mram_block_bytes block at a time through ra8_flash_extra_mram_erase (each block back to 0xFF).

Parameters
[in]ctxUnused opaque context.
[in]addrRegion base; 32-byte aligned.
[in]lenByte count; multiple of k_app_mram_block_bytes.
Returns
ra8_err_t outcome.
Return values
k_ra8_okThe whole region is erased.
otherThe first failing block erase's code.
Precondition
addr is block-aligned and len is a block multiple.
The MRAM controller was brought up (ra8_flash_init).
Postcondition
On success [addr, addr+len) reads back all-ones.
On failure the region may be partially erased.
Note
Not thread-safe; single OTA owner.
Since
0.1.0

Definition at line 474 of file main.c.

References k_app_mram_block_bytes, k_ra8_ok, and ra8_flash_extra_mram_erase().

Referenced by app_make_cfg().

◆ app_flash_program()

ra8_err_t app_flash_program ( void * ctx,
uint32_t addr,
const uint8_t * src,
uint32_t len )
static

Program bytes into the inactive bank (OTA flash.program).

Splits len into <= k_app_mram_block_bytes chunks, each a single ra8_flash_extra_mram_write (the MACI Program command ra8_emulator models). Callers stage 32-aligned offsets, so no write crosses a page.

Parameters
[in]ctxUnused opaque context.
[in]addrDestination base; 32-byte aligned.
[in]srcSource bytes; non-NULL.
[in]lenByte count.
Returns
ra8_err_t outcome.
Return values
k_ra8_okAll bytes programmed.
k_ra8_err_null_ptrsrc was NULL.
otherThe first failing block write's code.
Precondition
addr is 32-byte aligned and src is non-NULL.
[addr, addr+len) lies inside the extra-MRAM window.
Postcondition
On success the region holds src.
On failure the region is left partially programmed.
Note
Not thread-safe; single OTA owner.
Since
0.1.0

Definition at line 508 of file main.c.

References k_app_mram_block_bytes, k_ra8_ok, RA8_CHECK_NULL_PTR, ra8_flash_extra_mram_write(), and s_tag.

Referenced by app_make_cfg().

◆ app_flash_readback()

ra8_err_t app_flash_readback ( void * ctx,
uint32_t addr,
uint8_t * dst,
uint32_t len )
static

Read the inactive bank back for re-hash (OTA flash.readback).

Extra-MRAM is directly readable once programmed, so this is a plain copy from the mapped data-flash address – the same access a bench build makes.

Parameters
[in]ctxUnused opaque context.
[in]addrSource address in the extra-MRAM window.
[out]dstDestination buffer; non-NULL.
[in]lenByte count.
Returns
ra8_err_t outcome.
Return values
k_ra8_okBytes copied.
k_ra8_err_null_ptrdst was NULL.
Precondition
dst is non-NULL and addr is inside the extra-MRAM window.
[addr, addr+len) was programmed (no blank cells).
Postcondition
dst[0..len) mirrors the bank contents.
No MRAM state changes.
Note
Not thread-safe; single OTA owner.
Since
0.1.0

Definition at line 544 of file main.c.

References k_ra8_ok, memcpy(), RA8_CHECK_NULL_PTR, and s_tag.

Referenced by app_make_cfg().

◆ app_flash_set_startup()

ra8_err_t app_flash_set_startup ( void * ctx,
uint8_t which_bank,
bool persistent )
static

Latch the inactive bank as the next boot bank (OTA flash.set_startup).

Thin adapter: ra8_ota_commit_and_reboot calls this on a verified update, so it persists the boot-select record for which_bank.

Parameters
[in]ctxUnused opaque context.
[in]which_bankBank index the OTA config named as inactive.
[in]persistentWhether the swap should survive reset (always true here).
Returns
ra8_err_t from app_write_bootsel.
Return values
k_ra8_okThe boot-select record was written.
otherThe first failing erase/program code.
Precondition
The MRAM controller was brought up.
which_bank is a valid A/B index.
Postcondition
The boot-select record names which_bank.
s_bootsel_seq advanced by 1.
Note
Not thread-safe; single OTA owner.
Since
0.1.0

Definition at line 610 of file main.c.

References app_write_bootsel().

Referenced by app_make_cfg().

◆ app_make_cfg()

void app_make_cfg ( ra8_ota_cfg_t * cfg)
static

◆ app_make_manifest()

void app_make_manifest ( ra8_ota_manifest_t * m)
static

Build the demo manifest describing the good image.

Parameters
[out]mManifest to populate; non-NULL.
Returns
Nothing.
Precondition
m is non-NULL and s_image_good_digest is computed.
The demo signature width matches k_app_sig_bytes.
Postcondition
m->image_sha256 equals the golden image digest.
m->signature_len == k_app_sig_bytes.
Note
Single-threaded init only.
Since
0.1.0

Definition at line 759 of file main.c.

References app_strlen(), ra8_ota_manifest_t::image_sha256, ra8_ota_manifest_t::image_size_bytes, ra8_ota_manifest_t::image_url, k_app_image_bytes, k_app_sig_bytes, k_app_sig_tag_base, memcpy(), memset(), s_image_good_digest, ra8_ota_manifest_t::signature, ra8_ota_manifest_t::signature_len, and ra8_ota_manifest_t::version.

Referenced by main().

◆ app_net_close()

ra8_err_t app_net_close ( void * ctx)
static

Tear down the local stream (OTA net.close); a no-op here.

Parameters
[in]ctxapp_net_source_t handle; non-NULL.
Returns
ra8_err_t outcome.
Return values
k_ra8_okNothing to release.
k_ra8_err_null_ptrctx was NULL.
Precondition
ctx is non-NULL.
The stream was opened by app_net_open.
Postcondition
No state changes (RAM source needs no teardown).
Subsequent open calls remain valid.
Note
Not thread-safe; single OTA owner.
Since
0.1.0

Definition at line 336 of file main.c.

References k_ra8_ok, RA8_CHECK_NULL_PTR, and s_tag.

Referenced by app_make_cfg().

◆ app_net_open()

ra8_err_t app_net_open ( void * ctx,
const char * url,
uint32_t * out_content_len )
static

Begin serving the staged image (OTA net.open).

Parameters
[in]ctxapp_net_source_t handle; non-NULL.
[in]urlRequested URL (ignored – local source); unused.
[out]out_content_lenReceives the total image length; non-NULL.
Returns
ra8_err_t outcome.
Return values
k_ra8_okCursor reset; *out_content_len set.
k_ra8_err_null_ptrA required pointer was NULL.
Precondition
ctx and out_content_len are non-NULL.
The source blob was bound by ::app_bind_source.
Postcondition
ctx->pos == 0 and *out_content_len == ctx->len.
No image bytes are consumed yet.
Note
Not thread-safe; single OTA owner.
Since
0.1.0

Definition at line 276 of file main.c.

References k_ra8_ok, app_net_source_t::len, app_net_source_t::pos, RA8_CHECK_NULL_PTR, and s_tag.

Referenced by app_make_cfg().

◆ app_net_read()

ra8_err_t app_net_read ( void * ctx,
uint8_t * dst,
uint32_t cap,
uint32_t * out_len )
static

Copy up to cap bytes from the staged image (OTA net.read).

Parameters
[in]ctxapp_net_source_t handle; non-NULL.
[out]dstDestination buffer; non-NULL.
[in]capDestination capacity in bytes.
[out]out_lenBytes actually copied (0 == EOF); non-NULL.
Returns
ra8_err_t outcome.
Return values
k_ra8_okBytes copied (possibly 0 at EOF).
k_ra8_err_null_ptrA required pointer was NULL.
Precondition
ctx, dst and out_len are non-NULL.
ctx->pos <= ctx->len.
Postcondition
ctx->pos advanced by *out_len.
*out_len <= cap.
Note
Not thread-safe; single OTA owner.
Since
0.1.0

Definition at line 304 of file main.c.

References app_net_source_t::data, k_ra8_ok, app_net_source_t::len, memcpy(), app_net_source_t::pos, RA8_CHECK_NULL_PTR, and s_tag.

Referenced by app_make_cfg().

◆ app_print()

void app_print ( const char * text)
static

Print a NUL-terminated ASCII string on the board VCOM console.

Parameters
[in]textNUL-terminated string (CR/LF supplied by the caller); non-NULL.
Returns
Nothing.
Precondition
ra8_board_uart_console_init succeeded.
text is non-NULL.
Postcondition
The bytes of text are queued on SCI8.
No other state changes.
Note
Blocking polled TX; not interrupt-safe.
Since
0.1.0

Definition at line 248 of file main.c.

References app_strlen(), and ra8_board_uart_console_write().

Referenced by app_print_banner(), and main().

◆ app_print_banner()

void app_print_banner ( bool staged,
bool committed,
bool rolled_back )
static

Print the one-line A/B verdict banner over the console.

Parameters
[in]stagedWhether image staging + digest precompute succeeded.
[in]committedWhether the good-image attempt committed.
[in]rolled_backWhether the corrupt-image attempt rolled back.
Returns
Nothing.
Precondition
The console is initialised.
The three verdict flags are final.
Postcondition
One ota_ab: ... line is queued on SCI8.
No other state changes.
Note
Blocking polled TX.
Since
0.1.0

Definition at line 902 of file main.c.

References app_ab_ok(), and app_print().

Referenced by main().

◆ app_read_bootsel()

ra8_err_t app_read_bootsel ( uint8_t * out_bank,
bool * out_valid )
static

Read the persisted boot-select record.

Parameters
[out]out_bankReceives the recorded bank; non-NULL.
[out]out_validReceives whether the magic matched; non-NULL.
Returns
ra8_err_t outcome.
Return values
k_ra8_okRecord read (validity in *out_valid).
k_ra8_err_null_ptrA pointer argument was NULL.
Precondition
out_bank and out_valid are non-NULL.
The boot-select block was programmed by app_write_bootsel.
Postcondition
*out_valid is true iff the magic matched.
*out_bank holds the recorded bank when valid.
Note
Not thread-safe; single OTA owner.
Since
0.1.0

Definition at line 632 of file main.c.

References k_app_bootsel_addr, k_app_bootsel_magic, k_app_octet_bits, k_app_rec_off_bank, k_app_rec_off_magic, k_ra8_ok, RA8_CHECK_NULL_PTR, and s_tag.

Referenced by app_run_attempt().

◆ app_run_attempt()

app_outcome_t app_run_attempt ( const uint8_t * source,
const ra8_ota_manifest_t * m,
uint8_t * out_bank )
static

Drive one full A/B attempt against source and classify it.

Resets the boot-select record to bank A, (re)initialises ra8_ota, then runs download -> verify -> commit. Verify fails on a corrupted source, so commit is skipped and the machine parks in error.

Parameters
[in]sourceImage bytes to stream (good or corrupted); non-NULL.
[in]mManifest describing the expected (good) image; non-NULL.
[out]out_bankBank the boot-select record names afterwards; non-NULL.
Returns
app_outcome_t classification of the attempt.
Return values
k_app_outcome_committedGood image: verified and swap latched.
k_app_outcome_rolled_backCorrupt image: verify failed, no swap.
k_app_outcome_indeterminateSetup failure (reported via out_bank).
Precondition
Pointers are non-NULL and the MRAM controller is up.
m describes the good image.
Postcondition
*out_bank reflects the persisted boot-select record.
ra8_ota is left de-initialised.
Note
Not thread-safe; single OTA owner.
Since
0.1.0

Definition at line 796 of file main.c.

References app_ab_classify(), app_make_cfg(), app_read_bootsel(), app_write_bootsel(), k_app_bank_a, k_app_image_bytes, k_app_outcome_indeterminate, k_ra8_ok, ra8_ota_commit_and_reboot(), ra8_ota_deinit(), ra8_ota_download_to_inactive_bank(), ra8_ota_get_state(), ra8_ota_init(), ra8_ota_verify_signature(), and s_net_source.

Referenced by main().

◆ app_setup()

ra8_err_t app_setup ( void )
static

Bring up CGC + the board VCOM console + the MRAM controller.

Returns
ra8_err_t outcome.
Return values
k_ra8_okThe console and MRAM controller are live.
otherThe first failing bring-up step's code.
Precondition
SystemInit configured VTOR / FPU.
Runs single-threaded during early boot.
Postcondition
On success the console prints and extra-MRAM programs.
On failure the caller halts.
Note
Not thread-safe; boot-context only.
Since
0.1.0

Definition at line 870 of file main.c.

References k_app_mrcfreq_mhz, k_app_mrefreq_mhz, k_app_uart_baud, k_ra8_err_hw_error, k_ra8_ok, ra8_board_uart_console_init(), ra8_cgc_init(), and ra8_flash_init().

Referenced by main().

◆ app_sha_final()

ra8_err_t app_sha_final ( void * ctx,
uint8_t out[k_ra8_ota_sha256_bytes] )
static

Finalise the SHA-256 digest (OTA crypto.sha256_final).

Parameters
[in]ctxra8_rsip_sha256_ctx_t handle; non-NULL.
[out]out32-byte digest destination; non-NULL.
Returns
ra8_err_t from ra8_rsip_sha256_final.
Return values
k_ra8_okDigest written to out.
k_ra8_err_null_ptrA pointer argument was NULL.
Precondition
ctx is non-NULL and was init'd.
out addresses 32 writable bytes.
Postcondition
out[0..31] holds the digest on success.
ctx is consumed (must be re-init'd to reuse).
Note
Not thread-safe; single OTA owner.
Since
0.1.0

Definition at line 400 of file main.c.

References k_ra8_ota_sha256_bytes, RA8_CHECK_NULL_PTR, ra8_rsip_sha256_final(), and s_tag.

Referenced by app_make_cfg().

◆ app_sha_init()

ra8_err_t app_sha_init ( void * ctx)
static

Begin a streaming SHA-256 (OTA crypto.sha256_init).

Parameters
[in]ctxra8_rsip_sha256_ctx_t handle; non-NULL.
Returns
ra8_err_t from ra8_rsip_sha256_init.
Return values
k_ra8_okContext primed.
k_ra8_err_null_ptrctx was NULL.
Precondition
ctx is non-NULL.
The software SHA backend is linked (always, on this part).
Postcondition
ctx is ready for update.
No engine MMIO touched (software backend).
Note
Not thread-safe; single OTA owner.
Since
0.1.0

Definition at line 359 of file main.c.

References RA8_CHECK_NULL_PTR, ra8_rsip_sha256_init(), and s_tag.

Referenced by app_make_cfg().

◆ app_sha_update()

ra8_err_t app_sha_update ( void * ctx,
const uint8_t * data,
uint32_t len )
static

Absorb bytes into the SHA-256 (OTA crypto.sha256_update).

Parameters
[in]ctxra8_rsip_sha256_ctx_t handle; non-NULL.
[in]dataBytes to absorb; non-NULL when len > 0.
[in]lenByte count.
Returns
ra8_err_t from ra8_rsip_sha256_update.
Return values
k_ra8_okBytes accumulated.
k_ra8_err_null_ptrctx was NULL.
Precondition
ctx is non-NULL and was init'd.
Either len is 0 or data is non-NULL.
Postcondition
ctx->used grew by len on success.
No engine MMIO touched (software backend).
Note
Not thread-safe; single OTA owner.
Since
0.1.0

Definition at line 380 of file main.c.

References RA8_CHECK_NULL_PTR, ra8_rsip_sha256_update(), and s_tag.

Referenced by app_make_cfg().

◆ app_stage_images()

ra8_err_t app_stage_images ( void )
static

Fill the golden/corrupt image blobs and precompute the manifest digest.

Returns
ra8_err_t from the digest computation.
Return values
k_ra8_okBlobs staged and digest ready.
otherSHA backend error.
Precondition
The software SHA backend is linked.
s_image_good / s_image_bad are writable statics.
Postcondition
s_image_good_digest holds SHA-256 of s_image_good.
s_image_bad differs from s_image_good in exactly one byte.
Note
Single-threaded init only.
Since
0.1.0

Definition at line 845 of file main.c.

References k_app_byte_all_ones, k_app_image_bytes, k_app_img_seed_add, k_app_img_seed_mul, ra8_rsip_sha256(), s_image_bad, s_image_good, and s_image_good_digest.

Referenced by main().

◆ app_strlen()

size_t app_strlen ( const char * text)
static

Bounded length of a NUL-terminated ASCII string.

Parameters
[in]textNUL-terminated string; non-NULL.
Returns
Bytes before the NUL, capped at k_app_bank_size_bytes.
Return values
0Empty string.
Precondition
text is non-NULL and NUL-terminated.
text fits within the cap.
Postcondition
No state changes.
Return value never exceeds the cap.
Note
Pure bounded scan.
Since
0.1.0

Definition at line 224 of file main.c.

References k_app_bank_size_bytes.

Referenced by app_make_cfg(), app_make_manifest(), and app_print().

◆ app_write_bootsel()

ra8_err_t app_write_bootsel ( uint8_t bank)
static

Persist the A/B boot-select record for bank.

Erases the boot-select block and programs a 32-byte record [magic:4][bank:1][seq:4] into extra-MRAM through the real driver. Standing in for the BTFLG boot-area swap (HUM Ch 7.2 "BTFLG Boot-Area Swap" p 282), but on brick-safe data-flash: a demo never touches the option-setting anchors.

Parameters
[in]bankSlot to record as the next boot bank.
Returns
ra8_err_t outcome.
Return values
k_ra8_okThe record was persisted.
otherThe first failing erase/program code.
Precondition
The MRAM controller was brought up.
bank is k_app_bank_a or k_app_bank_b.
Postcondition
[k_app_bootsel_addr] holds a valid record naming bank.
s_bootsel_seq advanced by 1.
Note
Not thread-safe; single OTA owner.
Since
0.1.0

Definition at line 571 of file main.c.

References k_app_bootsel_addr, k_app_bootsel_magic, k_app_mram_block_bytes, k_app_octet_bits, k_app_rec_off_bank, k_app_rec_off_magic, k_app_rec_off_seq, k_ra8_ok, ra8_flash_extra_mram_erase(), ra8_flash_extra_mram_write(), and s_bootsel_seq.

Referenced by app_flash_set_startup(), and app_run_attempt().

◆ main()

void main ( void )

Application entry: run both A/B paths once, then report forever.

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler initialised the C runtime; SystemInit ran.
The EK-RA8D2 J-Link OB VCOM console is attached for the banner.
Postcondition
The commit + rollback attempts have executed against extra-MRAM.
The verdict banner is emitted once per report cycle.
Note
Single entry point; not re-entrant.
Since
0.1.0

Definition at line 925 of file main.c.

References app_make_manifest(), app_print(), app_print_banner(), app_run_attempt(), app_setup(), app_stage_images(), k_app_bank_a, k_app_bank_b, k_app_outcome_committed, k_app_outcome_rolled_back, k_app_report_delay, k_ra8_ok, s_image_bad, and s_image_good.

Variable Documentation

◆ s_bootsel_seq

uint32_t s_bootsel_seq = 0U
static

Monotonic sequence number stamped into each boot-select record.

Definition at line 196 of file main.c.

Referenced by app_write_bootsel().

◆ s_image_bad

uint8_t s_image_bad[k_app_image_bytes]
static

Corrupted image bytes for the rollback path (one flipped byte).

Definition at line 202 of file main.c.

Referenced by app_stage_images(), and main().

◆ s_image_good

uint8_t s_image_good[k_app_image_bytes]
static

Golden image bytes for the commit path (deterministic pattern).

Definition at line 199 of file main.c.

Referenced by app_stage_images(), and main().

◆ s_image_good_digest

uint8_t s_image_good_digest[k_ra8_ota_sha256_bytes]
static

SHA-256 of s_image_good, published as the manifest digest.

Definition at line 205 of file main.c.

Referenced by app_make_manifest(), and app_stage_images().

◆ s_net_source

app_net_source_t s_net_source
static

The staged image source (rebound per scenario).

Definition at line 190 of file main.c.

Referenced by app_make_cfg(), and app_run_attempt().

◆ s_sha_ctx

ra8_rsip_sha256_ctx_t s_sha_ctx
static

Streaming SHA-256 context backing the OTA crypto interface.

Definition at line 193 of file main.c.

Referenced by app_make_cfg().

◆ s_tag

const char* const s_tag = "ota_ab"
static

Module log/console tag.

Definition at line 167 of file main.c.