ACwing FC firmware
STM32WB55: attitude IEKF, altitude Kalman filter, flight core, protocol v2
Loading...
Searching...
No Matches
log_task.c
Go to the documentation of this file.
1
5#include "log_task.h"
6#include "log_queue.h"
7#include "usb_link.h"
8#include "proto_v2.h"
9#include "fc_core.h"
10#include "params.h"
11#include "spsc.h"
12#include "app_link.h"
13#include <string.h>
14
15/* where a command came from, and where its answer goes */
16enum { PORT_USB = 0, PORT_BLE = 1 };
17
18/* BLE: commands from the AppTask, answer frames back to it (it owns the BLE HI ring) */
19SPSC_DEFINE(s_blein, log_cmd_t, 4u);
20SPSC_DEFINE(s_bleout, log_msg_t, 8u);
21/* USB: the commands that are not the LogTask's, to the AppTask (ADR 0009) */
22SPSC_DEFINE(s_usbapp, appl_cmd_t, 8u);
23
25static uint8_t s_mounted;
26static volatile uint8_t s_pct = 0xFFu;
27static uint8_t s_was_armed;
28static uint32_t s_disarm_ms, s_cmd_ms;
29static uint8_t s_have_cmd;
30
31/* events seen while no log was open (e.g. ARMED just before the log opens) */
32#define PRE_EVENTS 8u
33#define PRE_EVENT_MS 2000u
35static uint8_t s_npre;
36
37/* wall clock, set by the app (SET_TIME); lost at reset */
38static struct {
39 uint8_t set;
40 uint32_t up_ms; /* uptime when it was set */
41 uint32_t unix_s;
42 uint16_t ms;
43 int16_t tz_min;
45
46/* LOG_READ in progress */
47static struct {
48 uint8_t on, seq, port;
49 uint16_t id;
50 uint32_t off, end;
52
54{
55 s_cfg = *cfg;
57 usbl_reset();
58 s_mounted = (uint8_t)(s_cfg.flash && log_mount(s_cfg.flash) == 0);
59 s_pct = s_mounted ? log_used_pct() : 0xFFu;
60 s_was_armed = 0u; s_disarm_ms = 0u; s_have_cmd = 0u; s_npre = 0u;
61 memset(&s_rd, 0, sizeof s_rd);
62 memset(&s_clk, 0, sizeof s_clk);
63 spsc_reset(&s_blein); spsc_reset(&s_bleout); spsc_reset(&s_usbapp);
64}
65
66int log_task_ble_cmd(const log_cmd_t *c) { return spsc_push(&s_blein, c); }
67int log_task_ble_take(log_msg_t *m) { return spsc_pop(&s_bleout, m); }
68int log_task_usb_app_take(appl_cmd_t *c) { return spsc_pop(&s_usbapp, c); }
69
70uint8_t log_task_pct(void) { return s_pct; }
71uint8_t log_task_busy(void) { return s_rd.on; }
72
73static void pump(void) { if (s_cfg.usb_pump) s_cfg.usb_pump(); }
74
75static int port_send(uint8_t port, uint8_t type, const void *p, uint8_t len)
76{
77 if (port == PORT_USB) return usbl_send(type, p, len);
78 log_msg_t m;
79 m.type = type; m.len = len;
80 memcpy(m.p, p, len);
81 return spsc_push(&s_bleout, &m);
82}
83
84/* room for one more LOG_DATA frame, keeping room for the final ACK */
85static int port_room(uint8_t port)
86{
87 if (port == PORT_USB) return usbl_tx_free() >= sizeof(pv2_log_data_hdr_t) + PV2_LOG_DATA_MAX + 6u + 16u;
88 return spsc_count(&s_bleout) < 7u;
89}
90
91static int port_room_ack(uint8_t port)
92{
93 if (port == PORT_USB) return usbl_tx_free() >= 16u;
94 return spsc_count(&s_bleout) < 8u;
95}
96
97static void ack(uint8_t port, uint8_t op, uint8_t seq, uint8_t res, uint8_t why)
98{
99 const pv2_ack_t a = { op, seq, res, why };
100 (void)port_send(port, PV2_FT_ACK, &a, sizeof a);
101 if (port == PORT_USB) pump();
102}
103
104/* ------------------------------------------------------------------ wall clock */
105int log_task_wallclock(uint32_t now, uint32_t *unix_s, uint16_t *ms)
106{
107 if (!s_clk.set) return -1;
108 const uint32_t el = now - s_clk.up_ms + s_clk.ms;
109 *unix_s = s_clk.unix_s + el / 1000u;
110 *ms = (uint16_t)(el % 1000u);
111 return 0;
112}
113
114static void append_time(uint32_t now)
115{
116 log_time_t t;
117 if (!log_is_open() || log_task_wallclock(now, &t.unix_s, &t.ms) != 0) return;
118 t.t_ms = now; t.tz_min = s_clk.tz_min;
119 (void)log_append(LR_TIME, &t, sizeof t);
120}
121
122/* ------------------------------------------------------------------ recording */
123static void close_log(void)
124{
125 if (!log_is_open()) return;
126 (void)log_close();
127}
128
129static void open_log(uint32_t now)
130{
131 if (log_open(now) != 0) return;
132 log_info_t in;
133 memset(&in, 0, sizeof in);
134 memcpy(in.fw, s_cfg.fw, 3);
135 in.hw_rev = s_cfg.hw_rev;
136 in.format = LOG_FORMAT;
137 in.t0_ms = now;
138 in.sensors = s_cfg.sensors ? s_cfg.sensors() : 0u;
139 (void)log_append(LR_INFO, &in, sizeof in);
140 append_time(now);
141 for (uint8_t i = 0; i < s_npre; ++i)
142 if ((now - s_pre[i].t_ms) < PRE_EVENT_MS) (void)log_append(LR_EVENT, &s_pre[i], sizeof s_pre[i]);
143 s_npre = 0;
144}
145
146static void drain(uint32_t now)
147{
148 uint8_t buf[LOG_REC_MAX], type;
149 for (uint8_t src = 0; src < LOG_SRC_COUNT; ++src) {
150 uint32_t r;
151 while ((r = log_q_get(src, &type, buf, sizeof buf)) != 0u) {
152 if (log_is_open()) (void)log_append(type, buf, (uint8_t)(r - 1u));
153 else if (type == LR_EVENT && r - 1u == sizeof(log_event_t)) {
154 if (s_npre == PRE_EVENTS) { memmove(&s_pre[0], &s_pre[1], sizeof s_pre - sizeof s_pre[0]); s_npre--; }
155 memcpy(&s_pre[s_npre++], buf, sizeof(log_event_t));
156 }
157 }
158 const uint16_t lost = log_q_take_drops(src);
159 if (lost && log_is_open()) {
160 const log_drop_t d = { now, lost, src };
161 (void)log_append(LR_DROP, &d, sizeof d);
162 }
163 }
164}
165
166static void recording(uint32_t now, uint8_t armed)
167{
168 if (!armed && s_was_armed) s_disarm_ms = now;
169 s_was_armed = armed;
170 const int mode = (int)(PARAM(P_LOG_MODE) + 0.5f);
171 const uint8_t usb = (uint8_t)(s_have_cmd && (now - s_cmd_ms) < LOG_USB_PAUSE_MS && !armed);
172 uint8_t want = 0u;
173 if (mode == PARAM_LOG_ALWAYS) want = 1u;
174 else if (mode == PARAM_LOG_ARMED) want = (uint8_t)(armed || (s_disarm_ms && (now - s_disarm_ms) < LOG_POSTROLL_MS));
175 if (usb) want = 0u;
176 /* producers queue whenever recording is possible: records that arrive
177 * before the log opens are dropped, except the events */
178 log_q_set_active((uint8_t)(mode != PARAM_LOG_OFF && !usb));
179
180 if (want && !log_is_open()) open_log(now);
181 drain(now);
182 if (!want && log_is_open()) close_log();
183}
184
185/* ------------------------------------------------------------------ log commands */
186static void entry_of(const log_entry_t *e, uint8_t index, uint8_t count, pv2_log_entry_t *m)
187{
188 m->id = e->id; m->index = index; m->count = count;
189 m->flags = (uint8_t)((e->truncated ? 1u : 0u) | (e->active ? 2u : 0u));
190 m->sectors = e->nsect; m->t0_ms = e->t0_ms;
191 m->bytes = (uint32_t)e->nsect * LOG_SECTOR;
192}
193
194/* the last flight: the newest log (closed first, so it can be read) */
195static const log_entry_t *last_log(void)
196{
197 close_log();
198 const uint8_t n = log_count();
199 return n ? log_entry((uint8_t)(n - 1u)) : NULL;
200}
201
202static void cmd_list(uint8_t port, uint8_t seq)
203{
205 if (port == PORT_BLE) {
206 /* BLE: only the last flight */
207 const log_entry_t *e = last_log();
208 if (e) { entry_of(e, 0u, 1u, &m); (void)port_send(port, PV2_FT_LOG_ENTRY, &m, sizeof m); }
209 } else {
210 const uint8_t n = log_count();
211 for (uint8_t i = 0; i < n; ++i) {
212 entry_of(log_entry(i), i, n, &m);
213 if (usbl_send(PV2_FT_LOG_ENTRY, &m, sizeof m) != 0) {
214 pump(); /* frees space if the host reads */
215 (void)usbl_send(PV2_FT_LOG_ENTRY, &m, sizeof m);
216 }
217 }
218 }
219 ack(port, PV2_OP_LOG_LIST, seq, PV2_ACK_OK, PV2_R_NONE); /* after the entries: the list is complete */
220}
221
222static void cmd(uint8_t port, const uint8_t *c, uint32_t n, uint8_t armed, uint32_t now)
223{
224 const uint8_t op = c[0], seq = c[1];
225 const uint8_t *p = &c[2];
226 const uint32_t pl = n - 2u;
227 if (op == PV2_OP_HEARTBEAT) return;
228 switch (op) {
229 case PV2_OP_LOG_LIST:
230 if (!s_mounted) { ack(port, op, seq, PV2_ACK_REJECTED, PV2_R_SENSOR_MISSING); return; }
231 if (armed && port == PORT_BLE) { ack(port, op, seq, PV2_ACK_REJECTED, PV2_R_ARMED); return; }
232 cmd_list(port, seq);
233 return;
234 case PV2_OP_LOG_READ: {
235 if (!s_mounted) { ack(port, op, seq, PV2_ACK_REJECTED, PV2_R_SENSOR_MISSING); return; }
236 if (armed) { ack(port, op, seq, PV2_ACK_REJECTED, PV2_R_ARMED); return; }
237 if (s_rd.on) { ack(port, op, seq, PV2_ACK_BUSY, PV2_R_NONE); return; }
238 if (pl < 10u) { ack(port, op, seq, PV2_ACK_INVALID, PV2_R_NONE); return; }
239 uint16_t id; uint32_t off, len;
240 memcpy(&id, p, 2); memcpy(&off, p + 2, 4); memcpy(&len, p + 6, 4);
241 close_log(); /* the newest log becomes readable */
242 if (port == PORT_BLE) {
243 /* BLE: the last flight only (the whole memory goes over USB) */
244 const log_entry_t *e = last_log();
245 if (!e || e->id != id) { ack(port, op, seq, PV2_ACK_REJECTED, PV2_R_OUT_OF_RANGE); return; }
246 }
247 const uint32_t size = log_size(id);
248 if (!size || off > size) { ack(port, op, seq, PV2_ACK_INVALID, PV2_R_OUT_OF_RANGE); return; }
249 if (len == 0u || len > size - off) len = size - off;
250 s_rd.on = 1u; s_rd.port = port; s_rd.seq = seq; s_rd.id = id; s_rd.off = off; s_rd.end = off + len;
251 return;
252 }
253 case PV2_OP_SET_TIME: {
254 /* any time, armed too: it only adds an LR_TIME record */
255 if (pl < 8u) { ack(port, op, seq, PV2_ACK_INVALID, PV2_R_NONE); return; }
256 uint32_t us; uint16_t ms; int16_t tz;
257 memcpy(&us, p, 4); memcpy(&ms, p + 4, 2); memcpy(&tz, p + 6, 2);
258 if (us < LOG_TIME_MIN_UNIX || ms > 999u || tz < -840 || tz > 840) {
260 }
261 s_clk.up_ms = now; s_clk.unix_s = us; s_clk.ms = ms; s_clk.tz_min = tz; s_clk.set = 1u;
262 append_time(now);
264 return;
265 }
266 case PV2_OP_LOG_ERASE:
267 if (port == PORT_BLE) { ack(port, op, seq, PV2_ACK_UNSUPPORTED, PV2_R_NONE); return; } /* USB only */
268 if (!s_mounted) { ack(port, op, seq, PV2_ACK_REJECTED, PV2_R_SENSOR_MISSING); return; }
269 if (armed) { ack(port, op, seq, PV2_ACK_REJECTED, PV2_R_ARMED); return; }
270 if (pl < 4u || memcmp(p, "WIPE", 4) != 0) { ack(port, op, seq, PV2_ACK_INVALID, PV2_R_NONE); return; }
271 close_log();
272 if (s_rd.on) { s_rd.on = 0u; ack(s_rd.port, PV2_OP_LOG_READ, s_rd.seq, PV2_ACK_REJECTED, PV2_R_NONE); }
274 {
275 int r;
276 if (s_cfg.erase_chip && log_count() > 0u) {
277 r = s_cfg.erase_chip();
278 if (r == 0) r = log_mount(s_cfg.flash); /* rebuild the (empty) list */
279 } else r = log_erase_all();
281 }
282 return;
283 default:
285 return;
286 }
287}
288
289static void read_stream(uint8_t armed)
290{
291 if (!s_rd.on) return;
292 const uint8_t port = s_rd.port;
293 if (armed) { /* armed during a download: stop it */
294 s_rd.on = 0u;
296 return;
297 }
298 uint8_t f[sizeof(pv2_log_data_hdr_t) + PV2_LOG_DATA_MAX];
299 while (s_rd.off < s_rd.end && port_room(port)) {
300 uint32_t k = s_rd.end - s_rd.off;
302 pv2_log_data_hdr_t h = { s_rd.id, s_rd.off };
303 memcpy(f, &h, sizeof h);
304 if (log_read(s_rd.id, s_rd.off, f + sizeof h, k) != 0) {
305 s_rd.on = 0u;
307 return;
308 }
309 (void)port_send(port, PV2_FT_LOG_DATA, f, (uint8_t)(sizeof h + k));
310 s_rd.off += k;
311 }
312 if (port == PORT_USB) pump();
313 if (s_rd.off >= s_rd.end && port_room_ack(port)) {
314 s_rd.on = 0u;
316 }
317}
318
319/* ------------------------------------------------------------------ step */
320/* a log command pauses the recording (LOG_USB_PAUSE_MS); SET_TIME, the
321 * heartbeat and the AppTask's commands do not */
322static int is_log_op(uint8_t op) { return op == PV2_OP_LOG_LIST || op == PV2_OP_LOG_READ || op == PV2_OP_LOG_ERASE; }
323static int pauses(uint8_t op) { return is_log_op(op); }
324
325/* a USB command for the AppTask (parameters, calibrations, requests ...) */
326static void to_app(const uint8_t *c, uint32_t n)
327{
328 appl_cmd_t a;
329 a.len = (uint8_t)(n > APPL_CMD_MAX ? APPL_CMD_MAX : n);
330 memcpy(a.b, c, a.len);
331 if (spsc_push(&s_usbapp, &a) != 0) ack(PORT_USB, c[0], c[1], PV2_ACK_BUSY, PV2_R_NONE);
332}
333
334void log_task_step(uint32_t now)
335{
336 fc_state_t f;
337 memset(&f, 0, sizeof f);
338 fc_snapshot(&f);
339
340 uint8_t c[USBL_CMD_MAX];
341 uint32_t n;
342 while ((n = usbl_poll(c, sizeof c, now)) != 0u) {
343 if (c[0] == PV2_OP_HEARTBEAT) continue; /* keeps the USB link open only */
344 if (!is_log_op(c[0]) && c[0] != PV2_OP_SET_TIME) { to_app(c, n); continue; }
345 if (pauses(c[0])) { s_cmd_ms = now; s_have_cmd = 1u; }
346 cmd(PORT_USB, c, n, f.armed, now);
347 }
348 log_cmd_t bc;
349 while (spsc_pop(&s_blein, &bc)) {
350 uint8_t b[2u + sizeof bc.p];
351 b[0] = bc.op; b[1] = bc.seq;
352 memcpy(&b[2], bc.p, sizeof bc.p);
353 if (pauses(bc.op)) { s_cmd_ms = now; s_have_cmd = 1u; }
354 cmd(PORT_BLE, b, 2u + (bc.len > sizeof bc.p ? sizeof bc.p : bc.len), f.armed, now);
355 }
357
358 if (s_mounted) {
359 recording(now, f.armed);
361 } else {
362 /* no log flash: empty the queues anyway */
363 uint8_t buf[LOG_REC_MAX], type;
364 for (uint8_t src = 0; src < LOG_SRC_COUNT; ++src) {
365 while (log_q_get(src, &type, buf, sizeof buf)) {}
366 (void)log_q_take_drops(src);
367 }
368 }
369 pump();
370}
371
372/* ------------------------------------------------------------------ RTOS shell */
373#ifndef HOST_TEST
374#include "cmsis_os2.h"
375
376static void LogTask(void *arg)
377{
378 (void)arg;
379 for (;;) {
380 log_task_step(osKernelGetTickCount());
381 osDelay(log_task_busy() ? 1u : (usbl_open(osKernelGetTickCount()) ? 2u : 10u)); /* USB open: drains the TX rings faster */
382 }
383}
384
386{
387 log_task_init(cfg);
388 /* lowest of the application tasks: erases and page programs may block it */
389 static const osThreadAttr_t a = { .name = "log", .priority = osPriorityLow,
390 .stack_size = 1536 };
391 (void)osThreadNew(LogTask, NULL, &a);
392}
393#endif
double b[6]
Definition calib_mgr.c:53
uint32_t n
Definition calib_mgr.c:35
void fc_snapshot(fc_state_t *out)
Definition fc_core.c:121
Flight core: arming, modes, automatic actions, failsafes, motor test (HANDOVER_FW....
#define LOG_REC_MAX
largest payload
Definition log_format.h:34
#define LOG_SECTOR
Definition log_format.h:30
@ LR_INFO
first record of a log
Definition log_format.h:51
@ LR_TIME
wall clock: after LR_INFO, and when it is set
Definition log_format.h:52
@ LR_EVENT
every EVENT of the flight core
Definition log_format.h:56
@ LR_DROP
records lost because a queue was full
Definition log_format.h:59
#define LOG_FORMAT
Definition log_format.h:28
uint32_t log_q_get(uint8_t src, uint8_t *type, void *p, uint8_t cap)
next record of 'src': returns payload length + 1, 0 if empty
Definition log_queue.c:52
void log_q_reset(void)
Definition log_queue.c:27
void log_q_set_active(uint8_t on)
Definition log_queue.c:25
uint16_t log_q_take_drops(uint8_t src)
Definition log_queue.c:73
Record queues from the producing tasks to the LogTask.
@ LOG_SRC_COUNT
Definition log_queue.h:18
uint8_t log_count(void)
Definition log_store.c:120
int log_append(uint8_t type, const void *payload, uint8_t len)
Definition log_store.c:193
int log_read(uint16_t id, uint32_t off, void *buf, uint32_t n)
bytes of a closed log 'id' from 'offset' (sectors concatenated, headers included)
Definition log_store.c:230
int log_close(void)
Definition log_store.c:214
int log_open(uint32_t t0)
0 = ok
Definition log_store.c:182
int log_mount(const log_flash_t *f)
0 = ok (empty flash is ok)
Definition log_store.c:82
const log_entry_t * log_entry(uint8_t i)
oldest first
Definition log_store.c:121
uint8_t log_used_pct(void)
Definition log_store.c:130
uint32_t log_size(uint16_t id)
nsect × LOG_SECTOR, 0 unknown
Definition log_store.c:224
uint8_t log_is_open(void)
Definition log_store.c:122
int log_erase_all(void)
erases every sector that holds data; logs restart from id 1
Definition log_store.c:246
static void open_log(uint32_t now)
Definition log_task.c:129
static int port_send(uint8_t port, uint8_t type, const void *p, uint8_t len)
Definition log_task.c:75
static void close_log(void)
Definition log_task.c:123
static void cmd_list(uint8_t port, uint8_t seq)
Definition log_task.c:202
static void entry_of(const log_entry_t *e, uint8_t index, uint8_t count, pv2_log_entry_t *m)
Definition log_task.c:186
uint32_t end
Definition log_task.c:50
uint8_t port
Definition log_task.c:48
int log_task_usb_app_take(appl_cmd_t *c)
1 if a command was taken
Definition log_task.c:68
static int is_log_op(uint8_t op)
Definition log_task.c:322
#define PRE_EVENTS
Definition log_task.c:32
static struct @3 s_clk
uint8_t seq
Definition log_task.c:48
static void drain(uint32_t now)
Definition log_task.c:146
uint8_t log_task_busy(void)
1 while a transfer is in progress (the task runs faster)
Definition log_task.c:71
static void ack(uint8_t port, uint8_t op, uint8_t seq, uint8_t res, uint8_t why)
Definition log_task.c:97
uint16_t id
Definition log_task.c:49
static uint32_t s_cmd_ms
Definition log_task.c:28
static void cmd(uint8_t port, const uint8_t *c, uint32_t n, uint8_t armed, uint32_t now)
Definition log_task.c:222
int log_task_wallclock(uint32_t now, uint32_t *unix_s, uint16_t *ms)
wall clock set by the app (PV2_OP_SET_TIME): 0 and UTC time at uptime 'now', -1 if not set since rese...
Definition log_task.c:105
static void pump(void)
Definition log_task.c:73
static uint8_t s_was_armed
Definition log_task.c:27
static int port_room_ack(uint8_t port)
Definition log_task.c:91
void log_task_init(const log_task_cfg_t *cfg)
Definition log_task.c:53
static uint8_t s_npre
Definition log_task.c:35
#define PRE_EVENT_MS
Definition log_task.c:33
uint8_t on
Definition log_task.c:48
uint8_t log_task_pct(void)
flash used %, 0xFF = no log flash (SYSTEM.log); any task
Definition log_task.c:70
static log_task_cfg_t s_cfg
Definition log_task.c:24
static void LogTask(void *arg)
Definition log_task.c:376
static volatile uint8_t s_pct
Definition log_task.c:26
uint32_t off
Definition log_task.c:50
static log_event_t s_pre[PRE_EVENTS]
Definition log_task.c:34
uint16_t ms
Definition log_task.c:42
static struct @4 s_rd
@ PORT_BLE
Definition log_task.c:16
@ PORT_USB
Definition log_task.c:16
int log_task_ble_cmd(const log_cmd_t *c)
0 = queued, -1 = full (answer BUSY)
Definition log_task.c:66
static void recording(uint32_t now, uint8_t armed)
Definition log_task.c:166
static int port_room(uint8_t port)
Definition log_task.c:85
void log_task_step(uint32_t now)
Definition log_task.c:334
int16_t tz_min
Definition log_task.c:43
static uint8_t s_have_cmd
Definition log_task.c:29
uint32_t unix_s
Definition log_task.c:41
uint8_t set
Definition log_task.c:39
uint32_t up_ms
Definition log_task.c:40
static int pauses(uint8_t op)
Definition log_task.c:323
void log_task_start(const log_task_cfg_t *cfg)
Definition log_task.c:385
static void to_app(const uint8_t *c, uint32_t n)
Definition log_task.c:326
static uint8_t s_mounted
Definition log_task.c:25
static const log_entry_t * last_log(void)
Definition log_task.c:195
static void append_time(uint32_t now)
Definition log_task.c:114
int log_task_ble_take(log_msg_t *m)
1 if a frame was taken
Definition log_task.c:67
static void read_stream(uint8_t armed)
Definition log_task.c:289
static uint32_t s_disarm_ms
Definition log_task.c:28
LogTask: owns the log flash, writes the flight log and serves the log download over USB.
#define LOG_POSTROLL_MS
keep logging after DISARM
Definition log_task.h:35
#define LOG_USB_PAUSE_MS
no recording after a log command (USB or BLE)
Definition log_task.h:37
Drone parameters of protocol v2 (HANDOVER_FW.md §8, ids.ts PARAMS).
#define PARAM(i)
Definition params.h:43
@ P_LOG_MODE
Definition params.h:28
@ PARAM_LOG_ARMED
Definition params.h:49
@ PARAM_LOG_ALWAYS
Definition params.h:49
@ PARAM_LOG_OFF
Definition params.h:49
ACwing Pilot app protocol v2: identifiers and frame layouts.
@ PV2_ACK_UNSUPPORTED
Definition proto_v2.h:88
@ PV2_ACK_BUSY
Definition proto_v2.h:87
@ PV2_ACK_OK
Definition proto_v2.h:87
@ PV2_ACK_IN_PROGRESS
Definition proto_v2.h:88
@ PV2_ACK_INVALID
Definition proto_v2.h:87
@ PV2_ACK_REJECTED
Definition proto_v2.h:87
@ PV2_R_NONE
Definition proto_v2.h:91
@ PV2_R_SENSOR_MISSING
Definition proto_v2.h:95
@ PV2_R_ARMED
Definition proto_v2.h:93
@ PV2_R_OUT_OF_RANGE
Definition proto_v2.h:94
#define PV2_FT_ACK
Definition proto_v2.h:39
#define PV2_FT_LOG_ENTRY
answer to LOG_LIST, one per log
Definition proto_v2.h:42
#define PV2_OP_HEARTBEAT
Definition proto_v2.h:49
#define PV2_FT_LOG_DATA
answer to LOG_READ
Definition proto_v2.h:43
#define PV2_OP_LOG_LIST
reserved in HANDOVER §16, USB link
Definition proto_v2.h:77
#define PV2_LOG_DATA_MAX
Definition proto_v2.h:265
#define PV2_OP_SET_TIME
unix_s u32, ms u16, tz_min i16: wall clock for the log
Definition proto_v2.h:76
#define PV2_OP_LOG_READ
id u16, offset u32, len u32
Definition proto_v2.h:78
#define PV2_OP_LOG_ERASE
"WIPE" (firmware extension)
Definition proto_v2.h:79
Lock-free single-producer single-consumer queue of fixed-size items.
#define SPSC_DEFINE(name, type, n)
Definition spsc.h:29
static int spsc_push(spsc_t *q, const void *it)
Definition spsc.h:35
static void spsc_reset(spsc_t *q)
Definition spsc.h:33
static uint32_t spsc_count(const spsc_t *q)
Definition spsc.h:56
static int spsc_pop(spsc_t *q, void *it)
Definition spsc.h:45
uint8_t b[APPL_CMD_MAX]
Definition app_link.h:33
uint8_t len
Definition app_link.h:32
published state (AppTask builds FLIGHT / MOTORS from it)
Definition fc_core.h:85
uint8_t armed
Definition fc_core.h:86
a log command received over BLE (op, seq, arguments as written by the app)
Definition log_task.h:51
uint8_t p[17]
Definition log_task.h:51
uint8_t seq
Definition log_task.h:51
uint8_t op
Definition log_task.h:51
uint8_t len
Definition log_task.h:51
Definition log_store.h:36
uint32_t t0_ms
Definition log_store.h:42
uint16_t id
Definition log_store.h:37
uint16_t nsect
Definition log_store.h:39
uint8_t active
being written now
Definition log_store.h:41
uint8_t truncated
seq 0 overwritten
Definition log_store.h:40
uint8_t format
Definition log_format.h:65
uint16_t sensors
CAPS bits
Definition log_format.h:67
uint32_t t0_ms
Definition log_format.h:66
uint8_t fw[3]
< LR_INFO
Definition log_format.h:63
char hw_rev
Definition log_format.h:64
an answer frame for BLE: type and payload (LOG_ENTRY, LOG_DATA, ACK)
Definition log_task.h:53
uint8_t type
Definition log_task.h:53
uint8_t len
Definition log_task.h:53
uint8_t p[sizeof(pv2_log_data_hdr_t)+PV2_LOG_DATA_MAX]
Definition log_task.h:53
const log_flash_t * flash
NULL: no log flash on this board
Definition log_task.h:40
void(* usb_pump)(void)
board binding: move queued USB TX bytes to the endpoint; may be NULL
Definition log_task.h:45
int(* erase_chip)(void)
optional whole-chip erase (faster than sector by sector); may be NULL
Definition log_task.h:47
uint8_t fw[3]
Definition log_task.h:42
uint16_t(* sensors)(void)
CAPS bits for LR_INFO; may be NULL
Definition log_task.h:43
uint32_t t_ms
< LR_TIME: wall clock at uptime t_ms (set by the app)
Definition log_format.h:72
uint32_t unix_s
UTC, seconds since 1970
Definition log_format.h:73
int16_t tz_min
local time offset of the phone, minutes
Definition log_format.h:75
uint16_t ms
Definition log_format.h:74
uint16_t id
< 0x11 LOG_DATA header (USB), then data
Definition proto_v2.h:262
Definition proto_v2.h:252
uint32_t bytes
sectors × 4096
Definition proto_v2.h:258
uint8_t index
Definition proto_v2.h:254
uint8_t flags
bit0 truncated (oldest, beginning overwritten), bit1 being written
Definition proto_v2.h:255
uint16_t sectors
Definition proto_v2.h:256
uint32_t t0_ms
uptime when the log started
Definition proto_v2.h:257
uint16_t id
< 0x10 LOG_ENTRY (USB)
Definition proto_v2.h:253
uint8_t count
position in the list, list size
Definition proto_v2.h:254