|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
Per-device (per-unit) configuration record – schema, storage seam, two-copy resolution. More...
Go to the source code of this file.
Data Structures | |
| struct | ra8_devcfg_body_t |
| Decoded per-unit payload (the 96-byte record body). More... | |
| struct | ra8_devcfg_record_t |
| Decoded record: the body plus the header discriminators. More... | |
| struct | ra8_devcfg_store_t |
| Dependency-injection vtable for the record backing store. More... | |
Typedefs | |
| typedef ra8_err_t(* | ra8_devcfg_read_fn_t) (uint32_t offset, uint8_t *dst, uint32_t len) |
| Backing-store read (dependency-injection seam). | |
| typedef ra8_err_t(* | ra8_devcfg_write_fn_t) (uint32_t offset, const uint8_t *src, uint32_t len) |
| Backing-store write (dependency-injection seam). | |
Functions | |
| ra8_err_t | ra8_devcfg_load (const ra8_devcfg_store_t *store) |
| Load and resolve the device configuration record from both copies. | |
| ra8_err_t | ra8_devcfg_get_vcom_mv (uint16_t *out_mv) |
| Fetch the validated panel VCOM magnitude in millivolts. | |
| ra8_err_t | ra8_devcfg_get_body (const ra8_devcfg_body_t **out_body) |
| Expose the decoded body of the loaded record. | |
| bool | ra8_devcfg_is_blank (void) |
| Report whether neither record copy is valid (the provisioning gate). | |
| ra8_err_t | ra8_devcfg_commit (const ra8_devcfg_store_t *store, const ra8_devcfg_record_t *rec) |
| Commit a new record to the stale copy slot with header-last ordering. | |
| void | ra8_devcfg_reset (void) |
| Drop the cached record so a later load re-resolves from scratch. | |
| const ra8_devcfg_store_t * | ra8_devcfg_default_store (void) |
| Return the production extra-MRAM-backed store binding. | |
Per-device (per-unit) configuration record – schema, storage seam, two-copy resolution.
A shipped product carries bytes that differ per unit and that a Root-of-Trust image signature structurally cannot cover: the e-paper panel VCOM printed on its flex tail, a serial number, the panel LUT id, touch calibration, a device-key identity. One signature covers one byte sequence; per-unit values differ per unit, so the config region needs its own integrity check and must live outside the A/B code banks so neither an update nor a rollback can erase it.
This module owns the record: a versioned, CRC-protected schema; a two-copy, header-last commit that survives a torn write; a boot-time resolver that picks the surviving copy or reports UNPROVISIONED; and a dependency-injection seam so the backing store is a RAM mock under host test and the extra-MRAM (data-flash) window on silicon.
The record lives in the extra-MRAM option-setting window at k_ra8_flash_extra_start (0x02E07600), which no DFU slot program or erase touches, so it survives an A/B firmware update and a rollback alike. Two k_ra8_devcfg_slot_bytes copies sit at k_ra8_devcfg_copy0_off and k_ra8_devcfg_copy1_off – the span 0x40 .. 0x1BF that ra8_epd_cal.h already reserves for exactly this record, clear of the DFU anti-rollback counter at offset 0 and the standalone VCOM blob at 0x200. The production binding is ra8_devcfg_default_store; host tests inject their own ra8_devcfg_store_t.
ra8_devcfg_load probes both copies and applies, in order:
There is deliberately no compile-time production fallback for VCOM – a build-time default is exactly the plausible-looking wrong value that damages panels cumulatively and irreversibly.
Definition in file ra8_devcfg.h.
| typedef ra8_err_t(* ra8_devcfg_read_fn_t) (uint32_t offset, uint8_t *dst, uint32_t len) |
Backing-store read (dependency-injection seam).
Reads len bytes at offset (relative to the devcfg region base) into dst. On silicon the base is k_ra8_flash_extra_start; the read must tolerate a blank (never-programmed) window, which reads back as 0xFF bytes. Any non-k_ra8_ok return makes the resolver treat that copy as absent and fall through – it never fabricates a record.
| [in] | offset | Byte offset into the devcfg region. |
| [out] | dst | Destination buffer; non-NULL, at least len bytes. |
| [in] | len | Bytes to read. |
| k_ra8_ok | dst holds len bytes. |
| k_ra8_err_null_ptr | dst was NULL. |
| other | Backing-store fault; the copy is treated absent. |
Definition at line 264 of file ra8_devcfg.h.
| typedef ra8_err_t(* ra8_devcfg_write_fn_t) (uint32_t offset, const uint8_t *src, uint32_t len) |
Backing-store write (dependency-injection seam).
Programs len bytes at offset. The caller (ra8_devcfg_commit) honours the header-last commit order – body bytes first, then the header page – so a torn write leaves the header invalid and the other copy wins. The implementation chunks len into k_ra8_devcfg_page_bytes program pages as its backing requires.
| [in] | offset | Byte offset into the devcfg region. |
| [in] | src | Source buffer; non-NULL, at least len bytes. |
| [in] | len | Bytes to write. |
| k_ra8_ok | len bytes committed durably. |
| k_ra8_err_null_ptr | src was NULL. |
| other | Program fault; the caller must not assume persistence. |
Definition at line 289 of file ra8_devcfg.h.
| enum ra8_devcfg_field_len_t : uint8_t |
Fixed byte lengths of the variable-width body fields.
| Enumerator | |
|---|---|
| k_ra8_devcfg_serial_len | Unit serial, NUL-padded. |
| k_ra8_devcfg_panel_serial_len | Panel identity, NUL-padded. |
| k_ra8_devcfg_panel_lut_len | Panel LUT id, e.g. "M641". |
| k_ra8_devcfg_touch_cal_len | ra8_touch_cal_save blob. |
| k_ra8_devcfg_hdr_rsvd_len | Header reserved padding. |
| k_ra8_devcfg_body_rsvd_len | Body reserved padding. |
Definition at line 109 of file ra8_devcfg.h.
| enum ra8_devcfg_flags_t : uint32_t |
Per-record status flags stored in the header flags word.
k_ra8_devcfg_flag_vcom_valid is an EXPLICIT validity bit rather than a sentinel value. "Zero means unset" is exactly how a plausible-looking wrong VCOM gets written, and a wrong VCOM degrades the panel cumulatively and irreversibly, so the validity of the VCOM field is stated, never inferred.
| Enumerator | |
|---|---|
| k_ra8_devcfg_flag_provisioned | Line self-test passed. |
| k_ra8_devcfg_flag_vcom_valid | panel_vcom_mv is real. |
| k_ra8_devcfg_flag_touch_valid | touch_cal blob is real. |
Definition at line 179 of file ra8_devcfg.h.
| enum ra8_devcfg_layout_t : uint32_t |
Record geometry, magic, schema version and extra-MRAM placement.
Placement offsets (copy0/copy1) are relative to k_ra8_flash_extra_start. The active record is k_ra8_devcfg_record_len bytes (header + body); each copy occupies a k_ra8_devcfg_slot_bytes slot, whose k_ra8_devcfg_sig_headroom tail is reserved for a future factory signature under Root-of-Trust.
Definition at line 92 of file ra8_devcfg.h.
| enum ra8_devcfg_off_t : uint8_t |
Byte offset of every field inside a serialised record.
The record is packed byte-at-a-time in an explicit little-endian order so a blob written on the host deserialises identically on the target – the on-storage format is a property of the record, not of the compiler. The header occupies [0, hdr_bytes) and is programmed LAST; the CRC-32 covers the body span [hdr_bytes, record_len) only.
| Enumerator | |
|---|---|
| k_ra8_devcfg_off_magic | u32 magic. |
| k_ra8_devcfg_off_schema | u16 schema_version. |
| k_ra8_devcfg_off_reclen | u16 record_len. |
| k_ra8_devcfg_off_seq | u32 monotonic sequence. |
| k_ra8_devcfg_off_crc | u32 CRC-32 of the body. |
| k_ra8_devcfg_off_flags | u32 ra8_devcfg_flags_t. |
| k_ra8_devcfg_off_hdr_rsvd | 12 reserved header bytes. |
| k_ra8_devcfg_off_serial | char[16] serial (body start). |
| k_ra8_devcfg_off_panel_serial | char[12] panel serial. |
| k_ra8_devcfg_off_panel_lut | char[8] panel LUT id. |
| k_ra8_devcfg_off_touch_cal | uint8[36] touch-cal blob. |
| k_ra8_devcfg_off_mfg_date | u32 packed YYYYMMDD. |
| k_ra8_devcfg_off_key_id | u32 device-key identifier. |
| k_ra8_devcfg_off_hw_rev | u16 board revision. |
| k_ra8_devcfg_off_fixture | u16 provisioning fixture id. |
| k_ra8_devcfg_off_vcom | u16 panel VCOM magnitude (mV). |
| k_ra8_devcfg_off_body_rsvd | 10 reserved body bytes. |
Definition at line 129 of file ra8_devcfg.h.
| enum ra8_devcfg_vcom_range_t : uint16_t |
Plausible-range guard for the stored VCOM magnitude, millivolts.
A secondary sanity guard behind the explicit k_ra8_devcfg_flag_vcom_valid bit: it rejects the two real-world poison values 0 (controller still booting) and 0xFFFF (blank / failed read) and any wildly out-of-band number. The window brackets the typical e-paper VCOM span (approximately -0.5 V to -4.0 V). These bounds are an extensible default, not a panel datasheet value; a panel-specific window belongs in the BSP descriptor.
| Enumerator | |
|---|---|
| k_ra8_devcfg_vcom_min_mv | Lowest accepted VCOM magnitude, mV. |
| k_ra8_devcfg_vcom_max_mv | Highest accepted VCOM magnitude, mV. |
Definition at line 164 of file ra8_devcfg.h.
|
nodiscard |
Commit a new record to the stale copy slot with header-last ordering.
The provisioning-writer primitive (consumed by #317). Serialises rec (its body, flags and a seq one past the newest existing copy), then programs the target slot – the older / invalid copy, so the newest good record is never overwritten – body bytes first and the header page LAST. A power cut before the header lands leaves that slot header-invalid, so the other copy still resolves; there is never a window with zero valid records. The caller must ra8_devcfg_load again to adopt the committed record.
| [in] | store | Backing-store vtable; non-NULL, both members non-NULL. |
| [in] | rec | Record to persist (rec->seq is ignored and recomputed); non-NULL. |
| k_ra8_ok | Body and header programmed to the target slot. |
| k_ra8_err_null_ptr | store, a member, or rec is NULL. |
| other | A backing write faulted; persistence is not assured. |
Definition at line 609 of file ra8_devcfg.c.
References internal_devcfg_plan(), internal_devcfg_serialize(), internal_devcfg_write_record(), k_ra8_devcfg_record_len, RA8_CHECK_NULL_PTR, ra8_devcfg_store_t::read, s_tag, and ra8_devcfg_store_t::write.
| const ra8_devcfg_store_t * ra8_devcfg_default_store | ( | void | ) |
Return the production extra-MRAM-backed store binding.
Wires ra8_devcfg_read_fn_t / ra8_devcfg_write_fn_t to the extra-MRAM (data-flash) window: reads dereference k_ra8_flash_extra_start + offset (a blank word reads back as 0xFF and does not fault – #315), writes go through ra8_flash_extra_mram_write in k_ra8_devcfg_page_bytes pages (HUM Ch 59.7.4.5 "Program Command" Table 59.15 p 3592). Under RA8_OFF_TARGET both members address a RAM shadow so host tests exercise the same control flow without MMIO. The returned pointer has static lifetime; the caller must not free it.
| non-NULL | The extra-MRAM (or, off-target, RAM-shadow) store. |
Definition at line 238 of file ra8_devcfg_store_extra_mram.c.
References s_default_store.
|
nodiscard |
Expose the decoded body of the loaded record.
Gives consumers read access to the per-unit fields (serial, touch calibration, panel identity) after a successful ra8_devcfg_load. The returned pointer aliases module-static cache storage and stays valid until the next ra8_devcfg_load / ra8_devcfg_reset; the caller must not modify or free it.
| [out] | out_body | Receives a pointer to the cached body; non-NULL. |
| k_ra8_ok | *out_body points at the cached body. |
| k_ra8_err_null_ptr | out_body is NULL. |
| k_ra8_err_not_initialized | No record is loaded (never loaded or UNPROVISIONED). |
Definition at line 594 of file ra8_devcfg.c.
References k_ra8_devcfg_state_loaded, k_ra8_err_not_initialized, k_ra8_ok, RA8_CHECK_NULL_PTR, s_record, s_state, and s_tag.
|
nodiscard |
Fetch the validated panel VCOM magnitude in millivolts.
The entry point the e-paper driver uses. It succeeds only when a record loaded cleanly, k_ra8_devcfg_flag_vcom_valid is set, and the stored value lies inside [k_ra8_devcfg_vcom_min_mv, k_ra8_devcfg_vcom_max_mv]. Any error means INV-VCOM-1 forbids driving the panel – leave the rail off and the controller in reset. Refusing to draw is recoverable; a wrong VCOM is not, because panel damage accumulates with time under bias.
| [out] | out_mv | Receives the magnitude (sign is implicitly negative). |
| k_ra8_ok | Value validated and safe to program. |
| k_ra8_err_null_ptr | out_mv is NULL. |
| k_ra8_err_not_initialized | ra8_devcfg_load has not succeeded. |
| k_ra8_err_validation_failed | No valid VCOM: unprovisioned, the valid flag is clear, or the value is out of range. Refuse the panel. |
Definition at line 575 of file ra8_devcfg.c.
References k_ra8_devcfg_flag_vcom_valid, k_ra8_devcfg_state_loaded, k_ra8_devcfg_vcom_max_mv, k_ra8_devcfg_vcom_min_mv, k_ra8_err_not_initialized, k_ra8_err_validation_failed, k_ra8_ok, RA8_CHECK_NULL_PTR, ra8_log_error, s_record, s_state, and s_tag.
|
nodiscard |
Report whether neither record copy is valid (the provisioning gate).
True exactly when the most recent ra8_devcfg_load found neither copy valid (UNPROVISIONED), and also before any load has run. One half of the provisioning-mode entry condition; the other half (a factory token) lives with the writer (#317). Blank-alone is not a sufficient gate while the debug port is open (#244).
| true | Both copies were invalid, or ra8_devcfg_load never ran. |
| false | A valid record is loaded. |
Definition at line 604 of file ra8_devcfg.c.
References k_ra8_devcfg_state_loaded, and s_state.
|
nodiscard |
Load and resolve the device configuration record from both copies.
Probes copy 0 and copy 1 through store; validates each (magic, schema known, record_len sane, CRC-32); selects the valid copy, or the higher seq when both are valid; and caches the winner for ra8_devcfg_get_vcom_mv / ra8_devcfg_get_body / ra8_devcfg_is_blank. A per-copy read fault or blank window marks that copy absent rather than failing the load, so a fresh unit resolves cleanly to UNPROVISIONED. This call is read-only: it never programs the backing.
| [in] | store | Backing-store vtable; non-NULL, both members non-NULL. |
| k_ra8_ok | A valid record is loaded and cached. |
| k_ra8_err_null_ptr | store or a member is NULL. |
| k_ra8_err_validation_failed | Neither copy is valid – the unit is UNPROVISIONED. Not a soft failure: the panel must not be driven and provisioning mode becomes reachable. |
Definition at line 549 of file ra8_devcfg.c.
References internal_devcfg_probe(), k_ra8_devcfg_copy0_off, k_ra8_devcfg_copy1_off, k_ra8_devcfg_state_loaded, k_ra8_devcfg_state_unprovisioned, k_ra8_err_validation_failed, k_ra8_ok, RA8_CHECK_NULL_PTR, ra8_log_warn, ra8_devcfg_store_t::read, s_record, s_state, s_tag, and ra8_devcfg_record_t::seq.
| void ra8_devcfg_reset | ( | void | ) |
Drop the cached record so a later load re-resolves from scratch.
Returns the module to the "never loaded" state. Used by the re-provisioning flow (write a new record, then reset and reload) and by host tests that need a pristine cache between cases. Touches no backing store.
Definition at line 626 of file ra8_devcfg.c.
References k_ra8_devcfg_state_unloaded, s_record, and s_state.