STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
emmc_log.h
Go to the documentation of this file.
1#ifndef STAR_EMMC_LOG_H
2#define STAR_EMMC_LOG_H
3
4/*
5 * The flight log on the eMMC (U9, THGBMTG5D1LBAIL, 4 GB).
6 *
7 * What it does
8 * Recording starts when the state machine enters ARMED and continues
9 * through LAUNCHED and RECOVERY; Un-arm closes the session. Self-test and
10 * Idle never touch the eMMC. (flight_state_logs_to_emmc.)
11 *
12 * How (see EMMC-ARCHITECTURE.md for why)
13 * - Raw blocks, no filesystem. An append-only run of self-checking 512 B
14 * blocks: each carries the volume epoch, its own position, its session
15 * and a CRC32. Nothing on the card is rewritten in place, so a power cut
16 * can only lose the tail that was in flight.
17 * - The end of the log is found at mount by binary search over "is this
18 * block valid and where it claims to be" (~23 reads for 4 GB), so there
19 * is no directory or pointer block to wear out or tear.
20 * - Two sides that never wait on each other. emmc_log_append() (sensor
21 * tasks) copies a record into a RAM chunk and returns. emmc_log_service()
22 * (one low-priority writer task) does every card transfer, one 16 KB
23 * chunk per call. If the card stalls and every chunk is full, records
24 * are dropped and counted, and a DROPPED record says how many.
25 * - All card I/O, including bring-up and mount, happens in
26 * emmc_log_service(), never in the caller of emmc_log_on_state().
27 *
28 * On-disk layout (little-endian)
29 * LBA 0 superblock: magic, layout version, epoch, data start,
30 * capacity, CRC32
31 * LBA data_start.. log blocks, block k at data_start + k:
32 * 0 u32 magic EMMC_LOG_BLOCK_MAGIC
33 * 4 u32 epoch changes on every format; older blocks are invalid
34 * 8 u32 seq = k (its own position)
35 * 12 u32 session numbered from 1 across power cycles
36 * 16 u8 kind EMMC_LOG_KIND_DATA or _PAD
37 * 17 u8 0
38 * 18 u16 used payload bytes in use
39 * 20 payload records, never split across blocks
40 * 508 u32 crc32 over bytes 0..507
41 * record: u8 type, u8 len, u32 t_ms, len bytes of data
42 */
43
44#include <stdbool.h>
45#include <stdint.h>
46
47#include "emmc_port.h"
48#include "flight_state.h"
49
50#ifdef __cplusplus
51extern "C" {
52#endif
53
54/* 16 KB: OPTIMAL_WRITE_SIZE (EXT_CSD[265] = 4, in 4 KB units). */
55#define EMMC_LOG_CHUNK_BLOCKS 32U
56#define EMMC_LOG_CHUNK_BYTES (EMMC_LOG_CHUNK_BLOCKS * EMMC_BLOCK_SIZE)
57#define EMMC_LOG_MAX_CHUNKS 16U
58
59#define EMMC_LOG_HEADER_BYTES 20U
60#define EMMC_LOG_PAYLOAD_BYTES (EMMC_BLOCK_SIZE - EMMC_LOG_HEADER_BYTES - 4U)
61#define EMMC_LOG_RECORD_HEADER_BYTES 6U
62
63#define EMMC_LOG_SUPER_MAGIC 0x31425353UL /* "SSB1" */
64#define EMMC_LOG_BLOCK_MAGIC 0x31474C53UL /* "SLG1" */
65#define EMMC_LOG_LAYOUT_VERSION 1U
66
67#define EMMC_LOG_KIND_DATA 1U
68#define EMMC_LOG_KIND_PAD 2U
69
70/* Record types below 0x10 belong to the log; sensors use 0x10 and up. */
71#define EMMC_REC_SESSION_START 0x01U /* data: u8 state entered */
72#define EMMC_REC_STATE 0x02U /* data: u8 from, u8 to */
73#define EMMC_REC_SESSION_END 0x03U /* data: u8 state entered */
74#define EMMC_REC_DROPPED 0x04U /* data: u32 records lost before this */
75#define EMMC_REC_USER_FIRST 0x10U
76
77/* Default data start: 8192 blocks = 4 MB = one HC erase group (EXT_CSD). */
78#define EMMC_LOG_DEFAULT_DATA_START 8192UL
79
80typedef struct {
83
84typedef struct {
85 uint32_t data_start_lba; /* first log block; > 0 (LBA 0 is super) */
86 uint32_t flush_interval_ms; /* max age of a partly filled chunk */
87 uint32_t read_budget_ms; /* per read() call */
88 uint32_t write_budget_ms; /* per write() call (one chunk) */
89 uint8_t write_attempts; /* tries per chunk before FAULT */
91
92typedef enum {
93 EMMC_DISK_UNMOUNTED = 0, /* not brought up yet (nothing armed so far) */
95 EMMC_DISK_FULL, /* no room for another chunk; recording stops */
96 EMMC_DISK_FAULT /* start, mount or writes failed; recording stops */
98
99typedef struct {
100 uint32_t records; /* records accepted into RAM */
101 uint32_t dropped; /* records refused while recording (no room) */
102 uint32_t chunks_written; /* chunks on the card */
103 uint32_t chunks_lost; /* sealed chunks discarded (FULL/FAULT) */
104 uint32_t write_errors; /* failed write() calls, retried or not */
105 uint32_t pad_blocks; /* blocks padded out by flushes */
107
113
114typedef struct {
115 /* Fixed at init. */
117 void* context;
120 uint8_t chunk_count;
121 uint8_t* scratch; /* one block, for mount reads */
122
123 /* Producer side (under lock). */
125 uint32_t arm_index; /* arms since power-up, from 1 */
127 uint8_t fill_chunk;
128 uint8_t fill_block;
129 uint16_t fill_offset;
130 bool fill_aged; /* the writer has seen this chunk filling */
131 uint32_t fill_started_ms; /* when it first saw it (writer's clock) */
135
136 /* Writer side. */
137 uint8_t write_chunk;
138 uint8_t write_tries;
140 uint32_t capacity; /* blocks, from start() */
141 uint32_t epoch;
142 uint32_t head; /* next LBA to write */
143 uint32_t base_session; /* last session on the card at mount */
144
146} emmc_log_t;
147
148/* Defaults: data start 4 MB, flush 1 s, read 100 ms, write 1 s, 3 tries. */
150
151/*
152 * No I/O. `chunks` (chunk_count of 2..EMMC_LOG_MAX_CHUNKS) and `scratch`
153 * (EMMC_BLOCK_SIZE bytes) must stay valid and be DMA-reachable and 32-byte
154 * aligned on the board. Returns EMMC_ERR_PARAM on a bad argument.
155 */
157 void* context, const emmc_log_config_t* config,
158 emmc_log_chunk_t* chunks, uint8_t chunk_count,
159 uint8_t* scratch);
160
161/*
162 * Tell the log about a state change. Entering a recording state from a
163 * non-recording one opens a session; leaving closes it and flushes; a change
164 * between recording states is logged as a STATE record. No I/O. Returns
165 * false if recording should have started but the disk is FULL or FAULT.
166 */
168 uint32_t now_ms);
169
170/*
171 * Copy one record into RAM. False when not recording (Self-test, Idle, a
172 * FULL/FAULT disk) or when no chunk is free (counted in stats.dropped).
173 * `type` >= EMMC_REC_USER_FIRST for sensor data. Never blocks on the card.
174 */
175bool emmc_log_append(emmc_log_t* log, uint8_t type, uint32_t t_ms,
176 const void* data, uint8_t len);
177
178/* Seal the partly filled chunk now (padding the rest) so it gets written. */
179void emmc_log_flush(emmc_log_t* log);
180
181/*
182 * The writer. Seals a chunk older than flush_interval_ms, brings the card up
183 * and mounts on first need, then writes at most one chunk. Call it in a loop
184 * from one task. Returns the result of the I/O it did (EMMC_OK if none).
185 */
186emmc_status_t emmc_log_service(emmc_log_t* log, uint32_t now_ms);
187
188/* Sealed chunks waiting for the card (0 = everything is on the card). */
189uint8_t emmc_log_backlog(const emmc_log_t* log);
190
191/* IEEE CRC-32 (reflected 0xEDB88320, init/xorout 0xFFFFFFFF). */
192uint32_t emmc_log_crc32(const void* data, uint32_t len);
193
194#ifdef __cplusplus
195}
196#endif
197#endif
flight_state_t
bool emmc_log_on_state(emmc_log_t *log, flight_state_t from, flight_state_t to, uint32_t now_ms)
Definition emmc_log.c:200
emmc_disk_state_t
Definition emmc_log.h:92
@ EMMC_DISK_FULL
Definition emmc_log.h:95
@ EMMC_DISK_FAULT
Definition emmc_log.h:96
@ EMMC_DISK_UNMOUNTED
Definition emmc_log.h:93
@ EMMC_DISK_MOUNTED
Definition emmc_log.h:94
uint32_t emmc_log_crc32(const void *data, uint32_t len)
Definition emmc_log.c:31
emmc_status_t emmc_log_service(emmc_log_t *log, uint32_t now_ms)
Definition emmc_log.c:424
#define EMMC_LOG_MAX_CHUNKS
Definition emmc_log.h:57
emmc_status_t emmc_log_init(emmc_log_t *log, const emmc_port_t *port, void *context, const emmc_log_config_t *config, emmc_log_chunk_t *chunks, uint8_t chunk_count, uint8_t *scratch)
Definition emmc_log.c:177
emmc_chunk_state_t
Definition emmc_log.h:108
@ EMMC_CHUNK_FREE
Definition emmc_log.h:109
@ EMMC_CHUNK_READY
Definition emmc_log.h:111
@ EMMC_CHUNK_FILLING
Definition emmc_log.h:110
uint8_t emmc_log_backlog(const emmc_log_t *log)
Definition emmc_log.c:252
bool emmc_log_append(emmc_log_t *log, uint8_t type, uint32_t t_ms, const void *data, uint8_t len)
Definition emmc_log.c:235
#define EMMC_LOG_CHUNK_BYTES
Definition emmc_log.h:56
void emmc_log_flush(emmc_log_t *log)
Definition emmc_log.c:246
emmc_log_config_t emmc_log_default_config(void)
Definition emmc_log.c:167
emmc_status_t
Definition emmc_port.h:22
static const emmc_port_t port
Definition emmc_stm32.c:210
std::vector< daq::SensorDataChunkCollection > chunks
Definition main.cpp:55
static const idle_config_t config
Definition idle_task.c:17
uint8_t bytes[EMMC_LOG_CHUNK_BYTES]
Definition emmc_log.h:81
uint32_t write_budget_ms
Definition emmc_log.h:88
uint32_t read_budget_ms
Definition emmc_log.h:87
uint8_t write_attempts
Definition emmc_log.h:89
uint32_t flush_interval_ms
Definition emmc_log.h:86
uint32_t data_start_lba
Definition emmc_log.h:85
uint32_t records
Definition emmc_log.h:100
uint32_t chunks_lost
Definition emmc_log.h:103
uint32_t write_errors
Definition emmc_log.h:104
uint32_t chunks_written
Definition emmc_log.h:102
uint32_t pad_blocks
Definition emmc_log.h:105
uint32_t dropped
Definition emmc_log.h:101
uint32_t arm_index
Definition emmc_log.h:125
uint32_t fill_started_ms
Definition emmc_log.h:131
bool recording
Definition emmc_log.h:124
emmc_log_stats_t stats
Definition emmc_log.h:145
uint32_t unreported_drops
Definition emmc_log.h:132
emmc_chunk_state_t chunk_state[EMMC_LOG_MAX_CHUNKS]
Definition emmc_log.h:133
emmc_log_config_t config
Definition emmc_log.h:118
emmc_disk_state_t disk
Definition emmc_log.h:139
uint32_t chunk_arm[EMMC_LOG_MAX_CHUNKS]
Definition emmc_log.h:134
uint32_t capacity
Definition emmc_log.h:140
uint32_t epoch
Definition emmc_log.h:141
bool has_fill
Definition emmc_log.h:126
uint8_t * scratch
Definition emmc_log.h:121
uint8_t chunk_count
Definition emmc_log.h:120
emmc_port_t port
Definition emmc_log.h:116
uint8_t write_chunk
Definition emmc_log.h:137
void * context
Definition emmc_log.h:117
bool fill_aged
Definition emmc_log.h:130
uint8_t fill_block
Definition emmc_log.h:128
uint8_t write_tries
Definition emmc_log.h:138
uint32_t base_session
Definition emmc_log.h:143
uint16_t fill_offset
Definition emmc_log.h:129
uint8_t fill_chunk
Definition emmc_log.h:127
uint32_t head
Definition emmc_log.h:142
emmc_log_chunk_t * chunks
Definition emmc_log.h:119
static uint8_t scratch[BS]