|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
Per-device configuration record – codec, two-copy resolver, commit. More...
#include "ra8_devcfg.h"#include <stddef.h>#include <stdint.h>#include <string.h>#include "ra8_attributes.h"#include "ra8_check.h"#include "ra8_err.h"#include "ra8_log.h"Go to the source code of this file.
Enumerations | |
| enum | ra8_devcfg_crc_t : uint32_t { k_ra8_devcfg_crc_init = 0xFFFFFFFFU , k_ra8_devcfg_crc_poly = 0xEDB88320U } |
| IEEE 802.3 CRC-32 parameters. More... | |
| enum | ra8_devcfg_bits_t : uint8_t { k_ra8_devcfg_bits_per_byte = 8U , k_ra8_devcfg_byte_shift = 8U , k_ra8_devcfg_byte_mask = 0xFFU , k_ra8_devcfg_off_b0 = 0U , k_ra8_devcfg_off_b1 = 1U , k_ra8_devcfg_off_b2 = 2U , k_ra8_devcfg_off_b3 = 3U } |
| Byte / word packing constants (no magic numbers). More... | |
| enum | ra8_devcfg_state_t : uint8_t { k_ra8_devcfg_state_unloaded = 0U , k_ra8_devcfg_state_loaded = 1U , k_ra8_devcfg_state_unprovisioned = 2U } |
| Module cache state established by ra8_devcfg_load. More... | |
Functions | |
| static uint32_t | internal_devcfg_crc32 (const uint8_t *data, uint32_t len) |
| Compute the IEEE 802.3 CRC-32 of a byte span. | |
| static void | internal_devcfg_pack_le16 (uint8_t *dst, uint16_t val) |
| Store a little-endian 16-bit value into a blob. | |
| static void | internal_devcfg_pack_le32 (uint8_t *dst, uint32_t val) |
| Store a little-endian 32-bit value into a blob. | |
| static uint16_t | internal_devcfg_unpack_le16 (const uint8_t *src) |
| Load a little-endian 16-bit value from a blob. | |
| static uint32_t | internal_devcfg_unpack_le32 (const uint8_t *src) |
| Load a little-endian 32-bit value from a blob. | |
| static void | internal_devcfg_serialize (const ra8_devcfg_record_t *rec, uint32_t seq, uint8_t *buf) |
| Serialise a record into a k_ra8_devcfg_record_len byte buffer. | |
| static void | internal_devcfg_deserialize (const uint8_t *buf, ra8_devcfg_record_t *out) |
| Decode a validated record buffer into a ra8_devcfg_record_t. | |
| static bool | internal_devcfg_copy_valid (const uint8_t *buf) |
| Report whether a serialised copy passes every integrity gate. | |
| static bool | internal_devcfg_probe (const ra8_devcfg_store_t *store, uint32_t offset, ra8_devcfg_record_t *out) |
| Read one copy through the store and validate it. | |
| static uint32_t | internal_devcfg_target (bool valid0, uint32_t seq0, bool valid1, uint32_t seq1) |
| Choose the copy offset a new record overwrites (the stale slot). | |
| static void | internal_devcfg_plan (const ra8_devcfg_store_t *store, uint32_t *out_target, uint32_t *out_seq) |
| Probe both copies and choose the commit target slot and next sequence. | |
| static ra8_err_t | internal_devcfg_write_record (const ra8_devcfg_store_t *store, uint32_t target, const uint8_t *buf) |
| Program a serialised record to a slot with the header page written last. | |
| 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. | |
Variables | |
| static const char *const | s_tag = "DEVCFG" |
| Logging tag used by every diagnostic path in this TU. | |
| static ra8_devcfg_state_t | s_state = k_ra8_devcfg_state_unloaded |
| Current cache state. | |
| static ra8_devcfg_record_t | s_record = {} |
| The resolved record cached by the last successful ra8_devcfg_load. | |
Per-device configuration record – codec, two-copy resolver, commit.
Implements the hardware-agnostic half of ra8_devcfg.h: a self-describing, CRC-protected record codec; a boot-time resolver that walks the two copies and picks the surviving / newest one or reports UNPROVISIONED; and a header-last commit. No HAL header is included – the durable medium is reached only through the injected ra8_devcfg_store_t seam, which is what lets every branch below run on the host. The extra-MRAM backing lives in the companion translation unit ra8_devcfg_store_extra_mram.c.
Definition in file ra8_devcfg.c.
| enum ra8_devcfg_bits_t : uint8_t |
Byte / word packing constants (no magic numbers).
Definition at line 60 of file ra8_devcfg.c.
| enum ra8_devcfg_crc_t : uint32_t |
IEEE 802.3 CRC-32 parameters.
Bit-banged rather than table-driven so the module carries no CRC table for a checksum it runs over 96 bytes a handful of times per boot. The polynomial matches ra8_epd_cal.c and ra8_touch_cal.c so every calibration record in the tree shares one CRC.
| Enumerator | |
|---|---|
| k_ra8_devcfg_crc_init | CRC seed / final XOR. |
| k_ra8_devcfg_crc_poly | Reversed IEEE 802.3 poly. |
Definition at line 51 of file ra8_devcfg.c.
| enum ra8_devcfg_state_t : uint8_t |
Module cache state established by ra8_devcfg_load.
| Enumerator | |
|---|---|
| k_ra8_devcfg_state_unloaded | No load attempted this boot. |
| k_ra8_devcfg_state_loaded | A valid record is cached. |
| k_ra8_devcfg_state_unprovisioned | Load ran; neither copy was valid. |
Definition at line 91 of file ra8_devcfg.c.
|
staticnodiscard |
Report whether a serialised copy passes every integrity gate.
Four sequential, independent gates – magic word, known schema, expected record_len, CRC-32 over the body. Any one failing rejects the copy; all four passing accepts it. Each gate is a single condition, so the copy is accepted only on the AND of all four.
| [in] | buf | k_ra8_devcfg_record_len byte buffer to test; non-NULL. |
| true | All four gates passed. |
| false | Magic, schema, record_len or CRC failed. |
Definition at line 376 of file ra8_devcfg.c.
References internal_devcfg_crc32(), internal_devcfg_unpack_le16(), internal_devcfg_unpack_le32(), k_ra8_devcfg_body_bytes, k_ra8_devcfg_hdr_bytes, k_ra8_devcfg_magic, k_ra8_devcfg_off_crc, k_ra8_devcfg_off_magic, k_ra8_devcfg_off_reclen, k_ra8_devcfg_off_schema, k_ra8_devcfg_record_len, and k_ra8_devcfg_schema_ver.
Referenced by internal_devcfg_probe().
|
staticnodiscard |
Compute the IEEE 802.3 CRC-32 of a byte span.
Bit-banged reflected-polynomial form; no lookup table. Used for the record body checksum stored in the header.
| [in] | data | Bytes to checksum; non-NULL. |
| [in] | len | Number of bytes. |
| 0xFFFFFFFF..0x00000000 | The reflected CRC-32 over the span. |
Definition at line 139 of file ra8_devcfg.c.
References k_ra8_devcfg_bits_per_byte, k_ra8_devcfg_crc_init, and k_ra8_devcfg_crc_poly.
Referenced by internal_devcfg_copy_valid(), and internal_devcfg_serialize().
|
static |
Decode a validated record buffer into a ra8_devcfg_record_t.
Inverse of internal_devcfg_serialize; unpacks each body field and the header discriminators. Assumes the buffer already passed validation, so no integrity check is repeated here.
| [in] | buf | Validated k_ra8_devcfg_record_len byte buffer; non-NULL. |
| [out] | out | Receives the decoded record; non-NULL. |
Definition at line 331 of file ra8_devcfg.c.
References ra8_devcfg_record_t::body, ra8_devcfg_record_t::flags, internal_devcfg_unpack_le16(), internal_devcfg_unpack_le32(), k_ra8_devcfg_off_fixture, k_ra8_devcfg_off_flags, k_ra8_devcfg_off_hw_rev, k_ra8_devcfg_off_key_id, k_ra8_devcfg_off_mfg_date, k_ra8_devcfg_off_panel_lut, k_ra8_devcfg_off_panel_serial, k_ra8_devcfg_off_schema, k_ra8_devcfg_off_seq, k_ra8_devcfg_off_serial, k_ra8_devcfg_off_touch_cal, k_ra8_devcfg_off_vcom, k_ra8_devcfg_panel_lut_len, k_ra8_devcfg_panel_serial_len, k_ra8_devcfg_serial_len, k_ra8_devcfg_touch_cal_len, memcpy(), ra8_devcfg_record_t::schema_version, and ra8_devcfg_record_t::seq.
Referenced by internal_devcfg_probe().
|
static |
Store a little-endian 16-bit value into a blob.
The record is serialised byte-at-a-time in an explicit byte order so a blob written on the host deserialises identically on the target.
| [out] | dst | Destination for two bytes; non-NULL. |
| [in] | val | Value to pack. |
Definition at line 170 of file ra8_devcfg.c.
References k_ra8_devcfg_byte_mask, k_ra8_devcfg_byte_shift, k_ra8_devcfg_off_b0, and k_ra8_devcfg_off_b1.
Referenced by internal_devcfg_serialize().
|
static |
Store a little-endian 32-bit value into a blob.
The 32-bit counterpart of internal_devcfg_pack_le16, used for the magic word, sequence, CRC and flags. Same explicit byte order.
| [out] | dst | Destination for four bytes; non-NULL. |
| [in] | val | Value to pack. |
Definition at line 195 of file ra8_devcfg.c.
References k_ra8_devcfg_byte_mask, k_ra8_devcfg_byte_shift, k_ra8_devcfg_off_b0, k_ra8_devcfg_off_b1, k_ra8_devcfg_off_b2, and k_ra8_devcfg_off_b3.
Referenced by internal_devcfg_serialize().
|
static |
Probe both copies and choose the commit target slot and next sequence.
Reads the two existing copies to find the newest valid sequence (0 when neither is valid), stamps the new record one past it, and selects the stale slot via internal_devcfg_target so the newest good copy is never the write target.
| [in] | store | Store seam; non-NULL with non-NULL read. |
| [out] | out_target | Receives the slot offset to program; non-NULL. |
| [out] | out_seq | Receives the sequence to stamp; non-NULL. |
Definition at line 494 of file ra8_devcfg.c.
References internal_devcfg_probe(), internal_devcfg_target(), k_ra8_devcfg_copy0_off, k_ra8_devcfg_copy1_off, and ra8_devcfg_record_t::seq.
Referenced by ra8_devcfg_commit().
|
staticnodiscard |
Read one copy through the store and validate it.
Reads k_ra8_devcfg_record_len bytes at offset through the store seam and runs the integrity gate. A read fault or blank window is treated as "copy absent" so the resolver falls through rather than failing the whole load.
| [in] | store | Store seam; non-NULL with non-NULL read. |
| [in] | offset | Copy offset in the devcfg region. |
| [out] | out | Receives the decoded record when valid; non-NULL. |
| true | out holds the decoded copy. |
| false | Read fault, blank window, or failed integrity gate. |
Definition at line 422 of file ra8_devcfg.c.
References internal_devcfg_copy_valid(), internal_devcfg_deserialize(), k_ra8_devcfg_record_len, k_ra8_ok, and ra8_devcfg_store_t::read.
Referenced by internal_devcfg_plan(), and ra8_devcfg_load().
|
static |
Serialise a record into a k_ra8_devcfg_record_len byte buffer.
Writes the body at its field offsets, then the header (magic, schema, record_len, seq, CRC over the body, flags). The CRC covers only the body span, matching the header-last commit discipline.
| [in] | rec | Record whose body and flags are serialised; non-NULL. |
| [in] | seq | Sequence number to stamp into the header. |
| [out] | buf | Destination of k_ra8_devcfg_record_len bytes; non-NULL. |
Definition at line 284 of file ra8_devcfg.c.
References ra8_devcfg_record_t::body, ra8_devcfg_record_t::flags, internal_devcfg_crc32(), internal_devcfg_pack_le16(), internal_devcfg_pack_le32(), k_ra8_devcfg_body_bytes, k_ra8_devcfg_hdr_bytes, k_ra8_devcfg_magic, k_ra8_devcfg_off_crc, k_ra8_devcfg_off_fixture, k_ra8_devcfg_off_flags, k_ra8_devcfg_off_hw_rev, k_ra8_devcfg_off_key_id, k_ra8_devcfg_off_magic, k_ra8_devcfg_off_mfg_date, k_ra8_devcfg_off_panel_lut, k_ra8_devcfg_off_panel_serial, k_ra8_devcfg_off_reclen, k_ra8_devcfg_off_schema, k_ra8_devcfg_off_seq, k_ra8_devcfg_off_serial, k_ra8_devcfg_off_touch_cal, k_ra8_devcfg_off_vcom, k_ra8_devcfg_panel_lut_len, k_ra8_devcfg_panel_serial_len, k_ra8_devcfg_record_len, k_ra8_devcfg_schema_ver, k_ra8_devcfg_serial_len, k_ra8_devcfg_touch_cal_len, memcpy(), and memset().
Referenced by ra8_devcfg_commit().
|
staticnodiscard |
Choose the copy offset a new record overwrites (the stale slot).
Prefers an invalid slot so a valid record is never clobbered; when both are valid, targets the lower seq so the newest survives the write window.
| [in] | valid0 | Copy-0 validity. |
| [in] | seq0 | Copy-0 sequence (meaningful only when valid0). |
| [in] | valid1 | Copy-1 validity. |
| [in] | seq1 | Copy-1 sequence (meaningful only when valid1). |
| k_ra8_devcfg_copy0_off | Copy 0 is the stale / free slot. |
| k_ra8_devcfg_copy1_off | Copy 1 is the stale / free slot. |
Definition at line 461 of file ra8_devcfg.c.
References k_ra8_devcfg_copy0_off, and k_ra8_devcfg_copy1_off.
Referenced by internal_devcfg_plan().
|
staticnodiscard |
Load a little-endian 16-bit value from a blob.
Inverse of internal_devcfg_pack_le16; reads the two bytes in the explicit record byte order.
| [in] | src | Two source bytes; non-NULL. |
| 0x0000..0xFFFF | The little-endian value at src. |
Definition at line 224 of file ra8_devcfg.c.
References k_ra8_devcfg_byte_shift, k_ra8_devcfg_off_b0, and k_ra8_devcfg_off_b1.
Referenced by internal_devcfg_copy_valid(), and internal_devcfg_deserialize().
|
staticnodiscard |
Load a little-endian 32-bit value from a blob.
Inverse of internal_devcfg_pack_le32; reads the four bytes in the explicit record byte order.
| [in] | src | Four source bytes; non-NULL. |
| 0x00000000..0xFFFFFFFF | The little-endian value at src. |
Definition at line 250 of file ra8_devcfg.c.
References k_ra8_devcfg_byte_shift, k_ra8_devcfg_off_b0, k_ra8_devcfg_off_b1, k_ra8_devcfg_off_b2, and k_ra8_devcfg_off_b3.
Referenced by internal_devcfg_copy_valid(), and internal_devcfg_deserialize().
|
staticnodiscard |
Program a serialised record to a slot with the header page written last.
Writes the body span first and the 32-byte header page last, so a power cut before the header lands leaves that slot header-invalid and the other copy the sole survivor – there is never a window with zero valid records.
| [in] | store | Store seam; non-NULL with non-NULL write. |
| [in] | target | Slot offset to program. |
| [in] | buf | Serialised k_ra8_devcfg_record_len byte record; non-NULL. |
| k_ra8_ok | Body and header both programmed. |
| other | Forwarded from the first failing store->write. |
Definition at line 533 of file ra8_devcfg.c.
References k_ra8_devcfg_body_bytes, k_ra8_devcfg_hdr_bytes, k_ra8_ok, RA8_RETURN_ON_ERROR, s_tag, and ra8_devcfg_store_t::write.
Referenced by ra8_devcfg_commit().
|
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.
|
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.
|
static |
The resolved record cached by the last successful ra8_devcfg_load.
Definition at line 111 of file ra8_devcfg.c.
Referenced by ra8_devcfg_get_body(), ra8_devcfg_get_vcom_mv(), ra8_devcfg_load(), and ra8_devcfg_reset().
|
static |
Current cache state.
Definition at line 103 of file ra8_devcfg.c.
|
static |
Logging tag used by every diagnostic path in this TU.
File-private component identifier for ra8_log_* / RA8_CHECK_*.
Definition at line 39 of file ra8_devcfg.c.