Skip to content

Commit 36dcf89

Browse files
simplify
1 parent dc47b3a commit 36dcf89

File tree

3 files changed

+30
-43
lines changed

3 files changed

+30
-43
lines changed

libcanard/canard.c

Lines changed: 26 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,14 @@ typedef unsigned char byte_t;
6363

6464
#define FOREACH_IFACE(i) for (size_t i = 0; (i) < CANARD_IFACE_COUNT; (i)++)
6565

66+
#if CANARD_IFACE_COUNT <= 4
67+
#define IFACE_INDEX_BIT_LENGTH 2U
68+
#elif CANARD_IFACE_COUNT <= 8
69+
#define IFACE_INDEX_BIT_LENGTH 3U
70+
#else
71+
#error "Too many interfaces"
72+
#endif
73+
6674
#define TREE_NULL (canard_tree_t){ NULL, { NULL, NULL }, 0 }
6775

6876
typedef enum format_t
@@ -1191,15 +1199,15 @@ static byte_t rx_transfer_id_forward_difference(const byte_t a, const byte_t b)
11911199
// Each state is only kept as long as the transfer reassembly is in progress; once it's completed, the slot is deleted.
11921200
typedef struct
11931201
{
1194-
canard_us_t start_ts;
1195-
size_t total_size; // The raw payload size before the implicit truncation and CRC removal.
1196-
canard_bytes_mut_t payload; // Dynamically allocated and handed off to the application when done.
1197-
uint16_t crc;
1198-
byte_t transfer_id : CANARD_TRANSFER_ID_BIT_LENGTH;
1199-
byte_t expected_toggle : 1;
1200-
byte_t iface_index;
1202+
canard_us_t start_ts;
1203+
size_t total_size; // The raw payload size before the implicit truncation and CRC removal.
1204+
uint16_t crc;
1205+
byte_t transfer_id : CANARD_TRANSFER_ID_BIT_LENGTH;
1206+
byte_t expected_toggle : 1;
1207+
byte_t iface_index : IFACE_INDEX_BIT_LENGTH;
1208+
byte_t payload[]; // Extent-sized.
12011209
} rx_slot_t;
1202-
static_assert((sizeof(void*) > 4) || (sizeof(rx_slot_t) <= 24), "too large");
1210+
#define RX_SLOT_OVERHEAD (offsetof(rx_slot_t, payload))
12031211

12041212
// Up to libcanard v4 we used a fixed-capacity array of pointers for per-remote sessions for constant-time lookup,
12051213
// but it was too costly on MCUs: with a 32-bit pointer it took 512 bytes for the array plus overheads,
@@ -1231,24 +1239,21 @@ static rx_slot_t* rx_slot_new(const canard_subscription_t* const sub,
12311239
const byte_t iface_index,
12321240
const bool v1)
12331241
{
1234-
rx_slot_t* const slot = mem_alloc_zero(sub->owner->mem.rx_slot, sizeof(rx_slot_t));
1242+
rx_slot_t* const slot = mem_alloc(sub->owner->mem.rx_payload, RX_SLOT_OVERHEAD + sub->extent);
12351243
if (slot != NULL) {
1244+
memset(slot, 0, RX_SLOT_OVERHEAD);
12361245
slot->start_ts = start_ts;
1237-
slot->payload.data = NULL;
12381246
slot->crc = sub->crc_seed;
12391247
slot->transfer_id = transfer_id & CANARD_TRANSFER_ID_MAX;
12401248
slot->expected_toggle = v1 ? 1 : 0;
1241-
slot->iface_index = iface_index;
1249+
slot->iface_index = iface_index & ((1U << IFACE_INDEX_BIT_LENGTH) - 1U);
12421250
}
12431251
return slot;
12441252
}
12451253

12461254
static void rx_slot_destroy(const canard_subscription_t* const sub, rx_slot_t* const slot)
12471255
{
1248-
if (slot != NULL) {
1249-
mem_free(sub->owner->mem.rx_payload, slot->payload.size, slot->payload.data);
1250-
mem_free(sub->owner->mem.rx_slot, sizeof(rx_slot_t), slot);
1251-
}
1256+
mem_free(sub->owner->mem.rx_payload, RX_SLOT_OVERHEAD + sub->extent, slot);
12521257
}
12531258

12541259
static int32_t rx_session_cavl_compare(const void* const user, const canard_tree_t* const node)
@@ -1314,29 +1319,13 @@ static size_t rx_session_scan(rx_session_t* const ses, const canard_us_t now)
13141319
return n_slots;
13151320
}
13161321

1317-
// Returns false on OOM, no other failure modes. Stores at most extent bytes. This is ONLY for multi-frame transfers.
1318-
static bool rx_slot_write_payload(rx_session_t* const ses, rx_slot_t* const slot, const canard_bytes_t payload)
1322+
static void rx_slot_write_payload(const rx_session_t* const ses, rx_slot_t* const slot, const canard_bytes_t payload)
13191323
{
1320-
CANARD_ASSERT(slot->payload.size <= ses->owner->extent); // enforced by the subscription logic
1321-
CANARD_ASSERT(slot->payload.size <= slot->total_size);
1322-
CANARD_ASSERT(payload.size > 0); // a multi-frame transfer cannot contain empty frames; enforced externally
1323-
const bool start = slot->total_size == 0;
1324-
slot->total_size += payload.size; // Before truncation.
1325-
if (ses->owner->extent == 0) {
1326-
return true;
1327-
}
1328-
if (start) {
1329-
CANARD_ASSERT((ses->owner->extent > 0) && (slot->payload.data == NULL));
1330-
slot->payload.data = mem_alloc(ses->owner->owner->mem.rx_payload, ses->owner->extent);
1331-
if (NULL == slot->payload.data) {
1332-
return false; // OOM. Must destroy the slot.
1333-
}
1324+
if (slot->total_size < ses->owner->extent) {
1325+
const size_t copy_size = smaller(payload.size, ses->owner->extent - slot->total_size);
1326+
(void)memcpy(&slot->payload[slot->total_size], payload.data, copy_size);
13341327
}
1335-
CANARD_ASSERT(slot->payload.data != NULL);
1336-
const size_t copy_size = smaller(payload.size, ses->owner->extent - slot->payload.size);
1337-
(void)memcpy(((byte_t*)slot->payload.data) + slot->payload.size, payload.data, copy_size);
1338-
slot->payload.size += copy_size;
1339-
return true;
1328+
slot->total_size += payload.size; // Before truncation.
13401329
}
13411330

13421331
// Returns false on OOM, no other failure modes.
@@ -1372,7 +1361,7 @@ bool canard_new(canard_t* const self,
13721361
{
13731362
bool ok = (self != NULL) && (vtable != NULL) && (vtable->now != NULL) && (vtable->tx != NULL) &&
13741363
(vtable->filter != NULL) && mem_valid(memory.tx_transfer) && mem_valid(memory.tx_frame) &&
1375-
mem_valid(memory.rx_session) && mem_valid(memory.rx_slot) && mem_valid(memory.rx_payload) &&
1364+
mem_valid(memory.rx_session) && mem_valid(memory.rx_payload) &&
13761365
((filter_count == 0U) || (filter_storage != NULL)) && (node_id <= CANARD_NODE_ID_MAX);
13771366
if (ok) {
13781367
(void)memset(self, 0, sizeof(*self));

libcanard/canard.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,8 +201,7 @@ typedef struct canard_mem_set_t
201201
canard_mem_t tx_transfer; ///< TX transfer objects, fixed-size, one per enqueued transfer.
202202
canard_mem_t tx_frame; ///< One per enqueued frame, at least one per TX transfer, size MTU+overhead.
203203
canard_mem_t rx_session; ///< Remote-associated sessions per subscriber, fixed-size.
204-
canard_mem_t rx_slot; ///< Reassembly slots per session, fixed-size.
205-
canard_mem_t rx_payload; ///< Variable-size, at most extent-sized.
204+
canard_mem_t rx_payload; ///< Variable-size, max size extent+sizeof(slot).
206205
} canard_mem_set_t;
207206

208207
typedef struct canard_subscription_t canard_subscription_t;

tests/src/test_api_tx.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ static const canard_vtable_t capture_vtable = {
100100
static canard_mem_set_t make_std_memory()
101101
{
102102
const canard_mem_t r = { .vtable = &std_mem_vtable, .context = nullptr };
103-
return canard_mem_set_t{ .tx_transfer = r, .tx_frame = r, .rx_session = r, .rx_slot = r, .rx_payload = r };
103+
return canard_mem_set_t{ .tx_transfer = r, .tx_frame = r, .rx_session = r, .rx_payload = r };
104104
}
105105

106106
static void init_with_capture_node_id(canard_t* const self, tx_capture_t* const capture, const uint_least8_t node_id)
@@ -126,9 +126,8 @@ static void test_canard_new_validation()
126126
const canard_mem_set_t mem = make_std_memory();
127127
const canard_mem_vtable_t bad_mv = { .free = std_free_mem, .alloc = nullptr };
128128
const canard_mem_t bad_mr = { .vtable = &bad_mv, .context = nullptr };
129-
const canard_mem_set_t bad_mem = canard_mem_set_t{
130-
.tx_transfer = bad_mr, .tx_frame = bad_mr, .rx_session = bad_mr, .rx_slot = bad_mr, .rx_payload = bad_mr
131-
};
129+
const canard_mem_set_t bad_mem =
130+
canard_mem_set_t{ .tx_transfer = bad_mr, .tx_frame = bad_mr, .rx_session = bad_mr, .rx_payload = bad_mr };
132131

133132
TEST_ASSERT_FALSE(canard_new(nullptr, &test_vtable, mem, 16, 1, 1234, 0, nullptr)); // Invalid self.
134133
TEST_ASSERT_FALSE(canard_new(&self, nullptr, mem, 16, 1, 1234, 0, nullptr)); // Invalid vtable.

0 commit comments

Comments
 (0)