Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions cy_can/cy_can.c
Original file line number Diff line number Diff line change
Expand Up @@ -273,12 +273,11 @@ static bool v_canard_tx(canard_t* const self,
cy_can_t* const owner = (cy_can_t*)self->user_context;
const uint_least8_t len = (uint_least8_t)can_data.size;
(void)user_context;
(void)deadline;
assert(iface_index < owner->iface_count);
if (fd && (owner->vtable->tx_fd != NULL)) {
return owner->vtable->tx_fd(owner->user, iface_index, extended_can_id, can_data.data, len);
return owner->vtable->tx_fd(owner->user, deadline, iface_index, extended_can_id, can_data.data, len);
}
return owner->vtable->tx_classic(owner->user, iface_index, extended_can_id, can_data.data, len);
return owner->vtable->tx_classic(owner->user, deadline, iface_index, extended_can_id, can_data.data, len);
}

static bool v_canard_filter(canard_t* const self, const size_t filter_count, const canard_filter_t* const filters)
Expand Down
20 changes: 15 additions & 5 deletions cy_can/cy_can.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,26 @@ typedef struct cy_can_rx_t
/// All functions are non-blocking except rx(), which may block up to the specified deadline.
typedef struct
{
/// Transmit a classic CAN frame (up to 8 bytes) on the given interface.
/// Transmit a classic CAN frame (up to 8 bytes) on the given interface before the given deadline.
/// Returns true if the frame should be removed from the upstream TX queue (i.e., if the frame was accepted
/// for transmission or if it encountered a fatal failure and no further attempts are needed).
/// Returns false if the underlying CAN controller is not ready to accept a new frame (e.g., no free TX mailbox);
/// the caller will retry later.
bool (*tx_classic)(void* user, uint_least8_t iface_index, uint32_t can_id, const void* data, uint_least8_t len);

/// Transmit a CAN FD frame (up to 64 bytes) on the given interface.
bool (*tx_classic)(void* user,
canard_us_t deadline,
uint_least8_t iface_index,
uint32_t can_id,
const void* data,
uint_least8_t len);

/// Transmit a CAN FD frame (up to 64 bytes) on the given interface before the given deadline.
/// Set to NULL if the underlying driver does not support CAN FD; all interfaces share the same FD capability.
bool (*tx_fd)(void* user, uint_least8_t iface_index, uint32_t can_id, const void* data, uint_least8_t len);
bool (*tx_fd)(void* user,
canard_us_t deadline,
uint_least8_t iface_index,
uint32_t can_id,
const void* data,
uint_least8_t len);

/// Poll all redundant interfaces for a received frame. Returns true if a frame was received.
/// The implementation may block up to the given deadline; baremetal implementations may ignore the deadline
Expand Down
4 changes: 4 additions & 0 deletions cy_can/cy_can_socketcan.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,14 @@ static cy_us_t socketcan_now(void)
// VTABLE IMPLEMENTATION

static bool v_tx_classic(void* const user,
const canard_us_t deadline,
const uint_least8_t iface_index,
const uint32_t can_id,
const void* const data,
const uint_least8_t len)
{
const socketcan_t* const self = (const socketcan_t*)user;
(void)deadline;
assert(iface_index < self->iface_count);
struct can_frame frame = { .can_id = can_id | CAN_EFF_FLAG, .can_dlc = len };
if ((data != NULL) && (len > 0)) {
Expand All @@ -71,12 +73,14 @@ static bool v_tx_classic(void* const user,
}

static bool v_tx_fd(void* const user,
const canard_us_t deadline,
const uint_least8_t iface_index,
const uint32_t can_id,
const void* const data,
const uint_least8_t len)
{
const socketcan_t* const self = (const socketcan_t*)user;
(void)deadline;
assert(iface_index < self->iface_count);
struct canfd_frame frame = { .can_id = can_id | CAN_EFF_FLAG, .len = len, .flags = CANFD_FDF };
if ((data != NULL) && (len > 0)) {
Expand Down
10 changes: 6 additions & 4 deletions cy_can/tests/test_api_can_pubsub.c
Original file line number Diff line number Diff line change
Expand Up @@ -158,11 +158,12 @@ static void test_api_can_pubsub_fd_capable_uses_fd_frames(void)
TEST_ASSERT_NOT_NULL(pub);
can_test_spin_pair(&node, NULL, 4U, spin_slice_us);
can_test_node_reset_history(&node);
const cy_us_t deadline = cy_now(node.cy) + (40 * spin_slice_us);

TEST_ASSERT_EQUAL_INT(
CY_OK, cy_publish(pub, cy_now(node.cy) + (40 * spin_slice_us), (cy_bytes_t){ sizeof(payload), payload, NULL }));
TEST_ASSERT_EQUAL_INT(CY_OK, cy_publish(pub, deadline, (cy_bytes_t){ sizeof(payload), payload, NULL }));
spin_until_done(&node, sub);
TEST_ASSERT_TRUE(node.tx_fd_calls > 0U);
TEST_ASSERT_EQUAL_INT64(deadline, node.last_tx_fd_deadline);

{
uint8_t received[32];
Expand Down Expand Up @@ -200,12 +201,13 @@ static void test_api_can_pubsub_classic_only_emits_no_fd_frames(void)
TEST_ASSERT_NOT_NULL(pub);
can_test_spin_pair(&node, NULL, 4U, spin_slice_us);
can_test_node_reset_history(&node);
const cy_us_t deadline = cy_now(node.cy) + (40 * spin_slice_us);

TEST_ASSERT_EQUAL_INT(
CY_OK, cy_publish(pub, cy_now(node.cy) + (40 * spin_slice_us), (cy_bytes_t){ sizeof(payload), payload, NULL }));
TEST_ASSERT_EQUAL_INT(CY_OK, cy_publish(pub, deadline, (cy_bytes_t){ sizeof(payload), payload, NULL }));
spin_until_done(&node, sub);
TEST_ASSERT_EQUAL_size_t(0U, node.tx_fd_calls);
TEST_ASSERT_TRUE(node.tx_classic_calls > 0U);
TEST_ASSERT_EQUAL_INT64(deadline, node.last_tx_classic_deadline);

{
const cy_arrival_t arrival = cy_arrival_move(sub);
Expand Down
6 changes: 6 additions & 0 deletions cy_can/tests/test_support.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ static bool tx_common(void* const user,
}

static bool v_tx_classic(void* const user,
const canard_us_t deadline,
const uint_least8_t iface_index,
const uint32_t can_id,
const void* const data,
Expand All @@ -198,10 +199,12 @@ static bool v_tx_classic(void* const user,
TEST_ASSERT_NOT_NULL(self);
TEST_ASSERT_TRUE(len <= 8U);
self->tx_classic_calls++;
self->last_tx_classic_deadline = deadline;
return tx_common(user, iface_index, can_id, false, data, len);
}

static bool v_tx_fd(void* const user,
const canard_us_t deadline,
const uint_least8_t iface_index,
const uint32_t can_id,
const void* const data,
Expand All @@ -211,6 +214,7 @@ static bool v_tx_fd(void* const user,
TEST_ASSERT_NOT_NULL(self);
TEST_ASSERT_TRUE(len <= 64U);
self->tx_fd_calls++;
self->last_tx_fd_deadline = deadline;
return tx_common(user, iface_index, can_id, true, data, len);
}

Expand Down Expand Up @@ -454,6 +458,8 @@ void can_test_node_reset_history(can_test_node_t* const self)
self->tx_history_count = 0U;
self->tx_classic_calls = 0U;
self->tx_fd_calls = 0U;
self->last_tx_classic_deadline = 0;
self->last_tx_fd_deadline = 0;
self->last_tx_pending_iface_bitmap = 0U;
}

Expand Down
2 changes: 2 additions & 0 deletions cy_can/tests/test_support.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ struct can_test_node_t
size_t tx_blocked[CAN_TEST_MAX_IFACES];
size_t tx_classic_calls;
size_t tx_fd_calls;
canard_us_t last_tx_classic_deadline;
canard_us_t last_tx_fd_deadline;
size_t rx_calls;
uint_least8_t last_tx_pending_iface_bitmap;
size_t filter_calls;
Expand Down