ICARUS OS (Intelligent Cooperative Architecture for Real-time Unified Systems) 0.1.0
Preemptive Real-Time Operating System for ARM Cortex-M7
Loading...
Searching...
No Matches
tables.c
Go to the documentation of this file.
1
35#include "icarus/icarus.h"
36#include <string.h>
37
38/* ---- Per-slot storage --------------------------------------------------- */
39
40typedef struct {
42
43 /* Staging side */
44 uint8_t staging[TBL_MAX_SIZE];
45 uint16_t staged_len;
47 uint16_t staged_data_crc;
50 /* Active side */
51 uint8_t active[TBL_MAX_SIZE];
52 uint16_t active_len;
54
57
58/* ---- Helper: find slot by id (priv mode only) -------------------------- */
59
61 for (uint8_t i = 0; i < reg_count; i++) {
62 if (registry[i].desc.id == id) {
63 return &registry[i];
64 }
65 }
66 return NULL;
67}
68
69/* ---- Privileged implementations ---------------------------------------- */
70
72 (void)memset(registry, 0, sizeof(registry));
73 reg_count = 0;
74}
75
77 if (!desc) {
78 return false;
79 }
80 if (reg_count >= (uint8_t)TBL_MAX_REGISTERED) {
81 return false;
82 }
83 if ((desc->size == 0u) || (desc->size > (uint16_t)TBL_MAX_SIZE)) {
84 return false;
85 }
86 /* Reject duplicate id */
87 for (uint8_t i = 0; i < reg_count; i++) {
88 if (registry[i].desc.id == desc->id) {
89 return false;
90 }
91 }
92 tbl_slot_t *slot = &registry[reg_count++];
93 (void)memset(slot, 0, sizeof(*slot));
94 (void)memcpy(&slot->desc, desc, sizeof(tbl_descriptor_t));
95 /* Ensure NUL termination of name */
96 slot->desc.name[TBL_NAME_LEN - 1] = '\0';
97 return true;
98}
99
100ITCM_FUNC bool __tbl_load(tbl_id_t id, const uint8_t *data, uint16_t len,
101 uint16_t schema_crc) {
102 if ((data == NULL) || (len == 0u)) {
103 return false;
104 }
105
106 tbl_slot_t *slot = find_slot(id);
107 if (slot == NULL) {
108 return false;
109 }
110
111 /* First chunk (or re-load after a completed/failed activation): reset
112 staging. We consider staging "ready for reset" when either it is
113 empty (staged_len == 0) or a previous full-size load has already been
114 validated (staged_valid == true). */
115 if ((slot->staged_len == 0u) || slot->staged_valid) {
116 (void)memset(slot->staging, 0, sizeof(slot->staging));
117 slot->staged_len = 0;
118 slot->staged_valid = false;
119 slot->staged_schema_crc = schema_crc;
120 }
121
122 /* Bounds check */
123 if (((uint32_t)slot->staged_len + (uint32_t)len) > (uint32_t)TBL_MAX_SIZE) {
124 return false;
125 }
126
127 (void)memcpy(&slot->staging[slot->staged_len], data, len);
128 slot->staged_len = (uint16_t)(slot->staged_len + len);
129
130 /* Mark valid and compute data CRC once we have a full descriptor-size load */
131 if (slot->staged_len == slot->desc.size) {
132 slot->staged_data_crc = crc16_ccitt(slot->staging, slot->staged_len);
133 slot->staged_valid = true;
134 }
135
136 return true;
137}
138
139ITCM_FUNC bool __tbl_activate_prepare(tbl_id_t id, uint8_t *out_data,
140 uint16_t *out_len,
141 tbl_activate_fn *out_activate) {
142 if ((out_data == NULL) || (out_len == NULL) || (out_activate == NULL)) {
143 return false;
144 }
145
146 tbl_slot_t *slot = find_slot(id);
147 if (slot == NULL) {
148 return false;
149 }
150
151 /* Step 1: size match */
152 if ((!slot->staged_valid) || (slot->staged_len != slot->desc.size)) {
153 return false;
154 }
155
156 /* Step 2: schema CRC */
157 if (slot->staged_schema_crc != slot->desc.schema_crc) {
158 return false;
159 }
160
161 /* Step 3: recompute data CRC for safety */
162 uint16_t computed = crc16_ccitt(slot->staging, slot->staged_len);
163 if (computed != slot->staged_data_crc) {
164 return false;
165 }
166
167 /* Step 4: copy into the caller-provided scratch buffer so the user
168 * activate callback can run from thread mode without touching
169 * DTCM_PRIV directly. */
170 (void)memcpy(out_data, slot->staging, slot->staged_len);
171 *out_len = slot->staged_len;
172 *out_activate = slot->desc.activate;
173 return true;
174}
175
176ITCM_FUNC bool __tbl_activate_commit(tbl_id_t id, const uint8_t *data,
177 uint16_t len) {
178 if ((data == NULL) || (len == 0u) || (len > (uint16_t)TBL_MAX_SIZE)) {
179 return false;
180 }
181 tbl_slot_t *slot = find_slot(id);
182 if (slot == NULL) {
183 return false;
184 }
185 (void)memcpy(slot->active, data, len);
186 slot->active_len = len;
187 return true;
188}
189
190ITCM_FUNC int16_t __tbl_dump(tbl_id_t id, uint8_t *out, uint16_t max) {
191 if ((out == NULL) || (max == 0u)) {
192 return -1;
193 }
194
195 tbl_slot_t *slot = find_slot(id);
196 if (slot == NULL) {
197 return -1;
198 }
199
200 uint16_t len = slot->active_len;
201 if (len == 0u) {
202 return -1;
203 }
204 if (len > max) {
205 len = max;
206 }
207 (void)memcpy(out, slot->active, len);
208 return (int16_t)len;
209}
210
212 tbl_slot_t *slot = find_slot(id);
213 return slot ? &slot->desc : NULL;
214}
215
216ITCM_FUNC uint8_t __tbl_count(void) {
217 return reg_count;
218}
uint16_t crc16_ccitt(const uint8_t *data, uint16_t len)
Compute CRC16-CCITT (poly 0x1021, init 0xFFFF) over a byte buffer.
Definition crc.c:66
#define DTCM_DATA_PRIV
Definition config.h:156
#define ITCM_FUNC
Definition config.h:155
ICARUS OS - Main API Header.
Static descriptor registered by a table producer.
Definition tables.h:59
uint16_t size
Expected table size in bytes
Definition tables.h:62
tbl_activate_fn activate
Callback on tbl_activate()
Definition tables.h:64
tbl_id_t id
Unique table identifier
Definition tables.h:60
char name[12]
Human-readable name
Definition tables.h:61
uint16_t schema_crc
Expected schema CRC
Definition tables.h:63
uint8_t active[512]
Definition tables.c:51
uint16_t staged_len
Bytes written to staging so far
Definition tables.c:45
uint16_t active_len
Bytes in active buffer (0 = none)
Definition tables.c:52
tbl_descriptor_t desc
Definition tables.c:41
uint16_t staged_schema_crc
schema_crc supplied with last tbl_load()
Definition tables.c:46
uint8_t staging[512]
Definition tables.c:44
uint16_t staged_data_crc
CRC16 computed over the full staged data.
Definition tables.c:47
bool staged_valid
True once a full-size load completed
Definition tables.c:48
bool __tbl_load(tbl_id_t id, const uint8_t *data, uint16_t len, uint16_t schema_crc)
Definition tables.c:100
static uint8_t reg_count
Definition tables.c:56
uint8_t __tbl_count(void)
Definition tables.c:216
bool __tbl_register(const tbl_descriptor_t *desc)
Definition tables.c:76
bool __tbl_activate_prepare(tbl_id_t id, uint8_t *out_data, uint16_t *out_len, tbl_activate_fn *out_activate)
Validate a staged table and copy it into a caller-provided scratch buffer for the activate callback.
Definition tables.c:139
int16_t __tbl_dump(tbl_id_t id, uint8_t *out, uint16_t max)
Definition tables.c:190
static tbl_slot_t registry[8]
Definition tables.c:55
bool __tbl_activate_commit(tbl_id_t id, const uint8_t *data, uint16_t len)
Commit a previously prepared table into the active buffer.
Definition tables.c:176
static tbl_slot_t * find_slot(tbl_id_t id)
Definition tables.c:60
const tbl_descriptor_t * __tbl_get_descriptor(tbl_id_t id)
Definition tables.c:211
void __tbl_init(void)
Definition tables.c:71
#define TBL_NAME_LEN
Maximum name length (incl.
Definition tables.h:34
uint8_t tbl_id_t
Generic table identifier.
Definition tables.h:43
#define TBL_MAX_REGISTERED
Maximum number of registered tables
Definition tables.h:32
#define TBL_MAX_SIZE
Maximum bytes per table buffer
Definition tables.h:33
bool(* tbl_activate_fn)(const void *data, uint16_t len)
Callback invoked when a staged table passes all CRC checks.
Definition tables.h:54