Skip to content

Commit 599b721

Browse files
wip
1 parent fda9730 commit 599b721

File tree

3 files changed

+99
-62
lines changed

3 files changed

+99
-62
lines changed

libcanard/canard.c

Lines changed: 70 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -73,23 +73,20 @@ typedef unsigned char byte_t;
7373

7474
#define TREE_NULL (canard_tree_t){ NULL, { NULL, NULL }, 0 }
7575

76-
typedef enum format_t
76+
typedef enum kind_t
7777
{
78-
format_1v1_message = 0,
79-
format_1v0_message = 1,
80-
format_1v0_response = 2,
81-
format_1v0_request = 3,
78+
kind_1v1_message = 0,
79+
kind_1v0_message = 1,
80+
kind_1v0_response = 2,
81+
kind_1v0_request = 3,
8282
// v0.1
83-
format_0v1_message = 4,
84-
format_0v1_response = 5,
85-
format_0v1_request = 6,
86-
} format_t;
87-
static_assert(CANARD_FORMAT_COUNT == format_0v1_request + 1, "");
83+
kind_0v1_message = 4,
84+
kind_0v1_response = 5,
85+
kind_0v1_request = 6,
86+
} kind_t;
87+
static_assert(CANARD_KIND_COUNT == kind_0v1_request + 1, "");
8888

89-
static bool format_is_v0(const format_t kind)
90-
{
91-
return (kind == format_0v1_message) || (kind == format_0v1_request) || (kind == format_0v1_response);
92-
}
89+
static bool kind_is_v1(const kind_t kind) { return kind < kind_0v1_message; }
9390

9491
#define KILO 1000LL
9592
#define MEGA (KILO * KILO)
@@ -1055,7 +1052,7 @@ bool canard_0v1_respond(canard_t* const self,
10551052
typedef struct
10561053
{
10571054
canard_prio_t priority;
1058-
format_t format;
1055+
kind_t kind;
10591056

10601057
uint32_t port_id; // in v0 this stores the data type ID.
10611058

@@ -1125,17 +1122,17 @@ static byte_t rx_parse(const uint32_t can_id,
11251122
out_v1->dst = (byte_t)((can_id >> 7U) & CANARD_NODE_ID_MAX);
11261123
out_v1->port_id = (can_id >> 14U) & CANARD_SERVICE_ID_MAX;
11271124
const bool req = (can_id & (UINT32_C(1) << 24U)) != 0U;
1128-
out_v1->format = req ? format_1v0_request : format_1v0_response;
1125+
out_v1->kind = req ? kind_1v0_request : kind_1v0_response;
11291126
} else {
11301127
out_v1->dst = CANARD_NODE_ID_ANONYMOUS;
11311128
const bool is_1v1 = (can_id & (UINT32_C(1) << 7U)) != 0U;
11321129
if (is_1v1) {
11331130
out_v1->port_id = (can_id >> 8U) & CANARD_SUBJECT_ID_MAX;
1134-
out_v1->format = format_1v1_message;
1131+
out_v1->kind = kind_1v1_message;
11351132
} else {
11361133
is_v1 = is_v1 && !bit_23;
11371134
out_v1->port_id = (can_id >> 8U) & CANARD_SUBJECT_ID_MAX_1v0;
1138-
out_v1->format = format_1v0_message;
1135+
out_v1->kind = kind_1v0_message;
11391136
if ((can_id & (UINT32_C(1) << 24U)) != 0U) {
11401137
out_v1->src = CANARD_NODE_ID_ANONYMOUS;
11411138
is_v1 = is_v1 && start && end; // anonymous can only be single-frame
@@ -1158,11 +1155,11 @@ static byte_t rx_parse(const uint32_t can_id,
11581155
out_v0->dst = dst;
11591156
out_v0->port_id = (can_id >> 16U) & 0xFFU;
11601157
const bool req = (can_id & (UINT32_C(1) << 15U)) != 0U;
1161-
out_v0->format = req ? format_0v1_request : format_0v1_response;
1158+
out_v0->kind = req ? kind_0v1_request : kind_0v1_response;
11621159
} else {
11631160
out_v0->dst = CANARD_NODE_ID_ANONYMOUS;
11641161
out_v0->port_id = (can_id >> 8U) & 0xFFFFU;
1165-
out_v0->format = format_0v1_message;
1162+
out_v0->kind = kind_0v1_message;
11661163
if (src == 0) {
11671164
out_v0->src = CANARD_NODE_ID_ANONYMOUS;
11681165
is_v0 = is_v0 && start && end; // anonymous can only be single-frame
@@ -1243,16 +1240,15 @@ static_assert((sizeof(void*) > 4) || (sizeof(rx_session_t) <= 120), "too large")
12431240
static rx_slot_t* rx_slot_new(const canard_subscription_t* const sub,
12441241
const canard_us_t start_ts,
12451242
const byte_t transfer_id,
1246-
const byte_t iface_index,
1247-
const bool v1)
1243+
const byte_t iface_index)
12481244
{
12491245
rx_slot_t* const slot = mem_alloc(sub->owner->mem.rx_payload, RX_SLOT_OVERHEAD + sub->extent);
12501246
if (slot != NULL) {
12511247
memset(slot, 0, RX_SLOT_OVERHEAD);
12521248
slot->start_ts = start_ts;
12531249
slot->crc = sub->crc_seed;
12541250
slot->transfer_id = transfer_id & CANARD_TRANSFER_ID_MAX;
1255-
slot->expected_toggle = v1 ? 1 : 0;
1251+
slot->expected_toggle = kind_is_v1(sub->kind) ? 1 : 0;
12561252
slot->iface_index = iface_index & ((1U << IFACE_INDEX_BIT_LENGTH) - 1U);
12571253
}
12581254
return slot;
@@ -1281,13 +1277,12 @@ static canard_tree_t* rx_session_factory(void* const user)
12811277
if (ses == NULL) {
12821278
return NULL;
12831279
}
1284-
ses->index = TREE_NULL;
1285-
ses->list_animation = LIST_NULL;
12861280
FOREACH_SLOT (i) {
12871281
ses->slots[i] = NULL;
12881282
}
12891283
ses->owner = ctx->owner;
12901284
ses->node_id = ctx->node_id;
1285+
enlist_tail(&ctx->owner->owner->rx.list_session_by_animation, &ses->list_animation);
12911286
return &ses->index;
12921287
}
12931288

@@ -1336,21 +1331,63 @@ static void rx_slot_write_payload(const rx_session_t* const ses, rx_slot_t* cons
13361331
}
13371332

13381333
// Returns false on OOM, no other failure modes.
1339-
static bool rx_session_update(canard_subscription_t* const sub, const canard_us_t ts, const frame_t* const frame)
1334+
static bool rx_session_update(canard_subscription_t* const sub,
1335+
const canard_us_t ts,
1336+
const frame_t* const frame,
1337+
const byte_t iface_index)
13401338
{
13411339
CANARD_ASSERT((sub != NULL) && (frame != NULL) && (frame->payload.data != NULL) && (ts >= 0));
13421340
CANARD_ASSERT(frame->end || (frame->payload.size >= 7));
13431341

13441342
rx_session_factory_context_t factory_context = { .owner = sub, .node_id = frame->src };
1345-
rx_session_t* const ses = CAVL2_TO_OWNER(
1346-
cavl2_find_or_insert(&sub->sessions, &frame->src, rx_session_cavl_compare, &factory_context, rx_session_factory),
1347-
rx_session_t,
1348-
index);
1343+
rx_session_t* const ses =
1344+
CAVL2_TO_OWNER(frame->start ? cavl2_find_or_insert(&sub->sessions, //
1345+
&frame->src,
1346+
rx_session_cavl_compare,
1347+
&factory_context,
1348+
rx_session_factory)
1349+
: cavl2_find(sub->sessions, &frame->src, rx_session_cavl_compare),
1350+
rx_session_t,
1351+
index);
13491352
if (ses == NULL) {
1350-
return false;
1353+
sub->owner->err.oom += frame->start;
1354+
return !frame->start;
1355+
}
1356+
1357+
// Frame admittance state machine. A highly complex piece, redesigned after v4 to support priority preemption.
1358+
// TID forward difference illustration: f(2,3)==31, f(2,2)==0, f(2,1)==1
1359+
const bool tid_new = rx_transfer_id_forward_difference(ses->last_admitted_transfer_id, frame->transfer_id) > 1;
1360+
const canard_us_t timed_out = (ts - ses->last_admitted_start_ts) > ses->owner->transfer_id_timeout;
1361+
bool accept = false;
1362+
if (!frame->start) {
1363+
const rx_slot_t* const slot = ses->slots[frame->priority];
1364+
accept = (slot != NULL) && (slot->transfer_id == frame->transfer_id) && (slot->iface_index == iface_index) &&
1365+
(slot->expected_toggle == frame->toggle);
1366+
} else {
1367+
const rx_slot_t* const slot = ses->slots[frame->priority];
1368+
accept = (slot == NULL) || (slot->transfer_id != frame->transfer_id) || tid_new || timed_out; // --
13511369
}
1352-
ses->last_admitted_transfer_id++; // TODO stub
1353-
(void)ts;
1370+
if (!accept) {
1371+
return true; // Frame not needed; not a failure to accept.
1372+
}
1373+
1374+
// The frame must be accepted. If this is the start of a new transfer, we must update state.
1375+
enlist_tail(&sub->owner->rx.list_session_by_animation, &ses->list_animation);
1376+
if (frame->start) {
1377+
ses->last_admitted_start_ts = ts;
1378+
ses->last_admitted_transfer_id = frame->transfer_id;
1379+
rx_slot_destroy(sub, ses->slots[frame->priority]);
1380+
ses->slots[frame->priority] = NULL;
1381+
if (!frame->end) { // more frames to follow, must store in-progress state
1382+
ses->slots[frame->priority] = rx_slot_new(sub, ts, frame->transfer_id, iface_index);
1383+
if (ses->slots[frame->priority] == NULL) {
1384+
sub->owner->err.oom++;
1385+
return false;
1386+
}
1387+
}
1388+
}
1389+
1390+
// TODO acceptance
13541391

13551392
return false;
13561393
}

libcanard/canard.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ extern "C"
8080
#define CANARD_MTU_CAN_FD 64U
8181

8282
/// Exposed only for type completeness.
83-
#define CANARD_FORMAT_COUNT 7
83+
#define CANARD_KIND_COUNT 7
8484

8585
typedef struct canard_t canard_t;
8686

@@ -316,7 +316,7 @@ struct canard_t
316316

317317
struct
318318
{
319-
canard_tree_t* subscriptions[CANARD_FORMAT_COUNT];
319+
canard_tree_t* subscriptions[CANARD_KIND_COUNT];
320320
canard_list_t list_session_by_animation; ///< Oldest at the head.
321321

322322
size_t filter_count;

0 commit comments

Comments
 (0)