26static volatile uint8_t
s_pct = 0xFFu;
33#define PRE_EVENT_MS 2000u
75static int port_send(uint8_t
port, uint8_t type,
const void *p, uint8_t len)
97static void ack(uint8_t
port, uint8_t op, uint8_t
seq, uint8_t res, uint8_t why)
107 if (!
s_clk.set)
return -1;
108 const uint32_t el = now -
s_clk.up_ms +
s_clk.ms;
110 *
ms = (uint16_t)(el % 1000u);
133 memset(&in, 0,
sizeof in);
141 for (uint8_t i = 0; i <
s_npre; ++i)
151 while ((r =
log_q_get(src, &type, buf,
sizeof buf)) != 0u) {
211 for (uint8_t i = 0; i <
n; ++i) {
222static void cmd(uint8_t
port,
const uint8_t *c, uint32_t
n, uint8_t armed, uint32_t now)
224 const uint8_t op = c[0],
seq = c[1];
225 const uint8_t *p = &c[2];
226 const uint32_t pl =
n - 2u;
239 uint16_t
id; uint32_t
off, len;
240 memcpy(&
id, p, 2); memcpy(&
off, p + 2, 4); memcpy(&len, p + 6, 4);
249 if (len == 0u || len > size -
off) len = size -
off;
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) {
291 if (!
s_rd.on)
return;
303 memcpy(f, &h,
sizeof h);
326static void to_app(
const uint8_t *c, uint32_t
n)
330 memcpy(a.
b, c, a.
len);
337 memset(&f, 0,
sizeof f);
342 while ((
n =
usbl_poll(c,
sizeof c, now)) != 0u) {
350 uint8_t
b[2u +
sizeof bc.
p];
352 memcpy(&
b[2], bc.
p,
sizeof bc.
p);
365 while (
log_q_get(src, &type, buf,
sizeof buf)) {}
374#include "cmsis_os2.h"
389 static const osThreadAttr_t a = { .name =
"log", .priority = osPriorityLow,
390 .stack_size = 1536 };
391 (void)osThreadNew(
LogTask, NULL, &a);
Receive side of the ACwing Pilot link (HANDOVER_FW.md §2 and §6).
void fc_snapshot(fc_state_t *out)
Flight core: arming, modes, automatic actions, failsafes, motor test (HANDOVER_FW....
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
void log_q_set_active(uint8_t on)
uint16_t log_q_take_drops(uint8_t src)
Record queues from the producing tasks to the LogTask.
int log_append(uint8_t type, const void *payload, uint8_t len)
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)
int log_open(uint32_t t0)
0 = ok
int log_mount(const log_flash_t *f)
0 = ok (empty flash is ok)
const log_entry_t * log_entry(uint8_t i)
oldest first
uint8_t log_used_pct(void)
uint32_t log_size(uint16_t id)
nsect × LOG_SECTOR, 0 unknown
uint8_t log_is_open(void)
int log_erase_all(void)
erases every sector that holds data; logs restart from id 1
static void open_log(uint32_t now)
static int port_send(uint8_t port, uint8_t type, const void *p, uint8_t len)
static void close_log(void)
static void cmd_list(uint8_t port, uint8_t seq)
static void entry_of(const log_entry_t *e, uint8_t index, uint8_t count, pv2_log_entry_t *m)
int log_task_usb_app_take(appl_cmd_t *c)
1 if a command was taken
static int is_log_op(uint8_t op)
static void drain(uint32_t now)
uint8_t log_task_busy(void)
1 while a transfer is in progress (the task runs faster)
static void ack(uint8_t port, uint8_t op, uint8_t seq, uint8_t res, uint8_t why)
static void cmd(uint8_t port, const uint8_t *c, uint32_t n, uint8_t armed, uint32_t now)
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...
static uint8_t s_was_armed
static int port_room_ack(uint8_t port)
void log_task_init(const log_task_cfg_t *cfg)
uint8_t log_task_pct(void)
flash used %, 0xFF = no log flash (SYSTEM.log); any task
static log_task_cfg_t s_cfg
static void LogTask(void *arg)
static volatile uint8_t s_pct
static log_event_t s_pre[PRE_EVENTS]
int log_task_ble_cmd(const log_cmd_t *c)
0 = queued, -1 = full (answer BUSY)
static void recording(uint32_t now, uint8_t armed)
static int port_room(uint8_t port)
void log_task_step(uint32_t now)
static uint8_t s_have_cmd
static int pauses(uint8_t op)
void log_task_start(const log_task_cfg_t *cfg)
static void to_app(const uint8_t *c, uint32_t n)
static const log_entry_t * last_log(void)
static void append_time(uint32_t now)
int log_task_ble_take(log_msg_t *m)
1 if a frame was taken
static void read_stream(uint8_t armed)
static uint32_t s_disarm_ms
LogTask: owns the log flash, writes the flight log and serves the log download over USB.
#define LOG_POSTROLL_MS
keep logging after DISARM
#define LOG_USB_PAUSE_MS
no recording after a log command (USB or BLE)
Drone parameters of protocol v2 (HANDOVER_FW.md §8, ids.ts PARAMS).
ACwing Pilot app protocol v2: identifiers and frame layouts.
#define PV2_FT_LOG_ENTRY
answer to LOG_LIST, one per log
#define PV2_FT_LOG_DATA
answer to LOG_READ
#define PV2_OP_LOG_LIST
reserved in HANDOVER §16, USB link
#define PV2_OP_SET_TIME
unix_s u32, ms u16, tz_min i16: wall clock for the log
#define PV2_OP_LOG_READ
id u16, offset u32, len u32
#define PV2_OP_LOG_ERASE
"WIPE" (firmware extension)
Lock-free single-producer single-consumer queue of fixed-size items.
#define SPSC_DEFINE(name, type, n)
static int spsc_push(spsc_t *q, const void *it)
static void spsc_reset(spsc_t *q)
static uint32_t spsc_count(const spsc_t *q)
static int spsc_pop(spsc_t *q, void *it)
published state (AppTask builds FLIGHT / MOTORS from it)
a log command received over BLE (op, seq, arguments as written by the app)
uint8_t active
being written now
uint8_t truncated
seq 0 overwritten
uint16_t sensors
CAPS bits
an answer frame for BLE: type and payload (LOG_ENTRY, LOG_DATA, ACK)
uint8_t p[sizeof(pv2_log_data_hdr_t)+PV2_LOG_DATA_MAX]
const log_flash_t * flash
NULL: no log flash on this board
void(* usb_pump)(void)
board binding: move queued USB TX bytes to the endpoint; may be NULL
int(* erase_chip)(void)
optional whole-chip erase (faster than sector by sector); may be NULL
uint16_t(* sensors)(void)
CAPS bits for LR_INFO; may be NULL
uint32_t t_ms
< LR_TIME: wall clock at uptime t_ms (set by the app)
uint32_t unix_s
UTC, seconds since 1970
int16_t tz_min
local time offset of the phone, minutes
uint16_t id
< 0x11 LOG_DATA header (USB), then data
uint32_t bytes
sectors × 4096
uint8_t flags
bit0 truncated (oldest, beginning overwritten), bit1 being written
uint32_t t0_ms
uptime when the log started
uint16_t id
< 0x10 LOG_ENTRY (USB)
uint8_t count
position in the list, list size
uint32_t usbl_poll(uint8_t *cmd, uint32_t cap, uint32_t now)
next CMD frame payload; returns its length (>= 2), 0 if none.
uint8_t usbl_open(uint32_t now)
a program has the port open: host and (DTR or a command in the last USBL_OPEN_MS)
Byte-stream link over USB CDC: protocol v2 frames in both directions (A5 5A | TYPE | LEN | PAYLOAD | ...
static uint32_t usbl_tx_free(void)
the LogTask's ring (log answers)
static int usbl_send(uint8_t type, const void *payload, uint8_t len)