Skip to content

Commit

Permalink
Introduce CanardPayload etc (#235)
Browse files Browse the repository at this point in the history
- added `struct CanardPayload` to combine payload size and data.
- added `struct CanardMutablePayload` to combine payload size, data and
`allocated_size`.
  • Loading branch information
serges147 authored Nov 21, 2024
1 parent 5076702 commit dc19e93
Show file tree
Hide file tree
Showing 8 changed files with 596 additions and 582 deletions.
302 changes: 146 additions & 156 deletions libcanard/canard.c

Large diffs are not rendered by default.

50 changes: 32 additions & 18 deletions libcanard/canard.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,33 @@ struct CanardTreeNode
int8_t bf; ///< Do not access this field.
};

struct CanardPayload
{
/// Size of the payload data in bytes.
/// If the payload is empty (size = 0), the payload pointer may be NULL.
size_t size;

/// Pointer to the payload data buffer.
const void* data;
};

struct CanardMutablePayload
{
/// Size of the payload data in bytes.
/// The value is always less than or equal to the extent specified in the subscription.
/// If the payload is empty (`size` = 0), the `data` pointer may be NULL.
size_t size;

/// The application is required to deallocate the payload buffer after the transfer is processed.
/// Allocated buffer size (`allocated_size`, not `size`) should be used to deallocate the buffer.
void* data;

/// Size of the allocated data buffer in bytes.
/// Normally equal to the extent specified in the subscription, but could be less (equal to `size`)
/// in case of single frame transfer, or even zero if the `data` pointer is NULL.
size_t allocated_size;
};

/// CAN data frame with an extended 29-bit ID. RTR/Error frames are not used and therefore not modeled here.
/// CAN frames with 11-bit ID are not used by Cyphal/CAN and so they are not supported by the library.
typedef struct
Expand All @@ -179,14 +206,13 @@ typedef struct
uint32_t extended_can_id;

/// The useful data in the frame. The length value is not to be confused with DLC!
/// If the payload is empty (payload_size = 0), the payload pointer may be NULL.
/// If the payload is empty (payload.size = 0), the payload.data pointer may be NULL.
/// For RX frames: the library does not expect the lifetime of the pointee to extend beyond the point of return
/// from the API function. That is, the pointee can be invalidated immediately after the frame has been processed.
/// For TX frames: the frame and the payload are allocated within the same dynamic memory fragment, so their
/// lifetimes are identical; when the frame is freed, the payload is invalidated.
/// A more detailed overview of the dataflow and related resource management issues is provided in the API docs.
size_t payload_size;
const void* payload;
struct CanardPayload payload;
} CanardFrame;

/// Conversion look-up table from CAN DLC to data length.
Expand Down Expand Up @@ -384,19 +410,8 @@ typedef struct CanardRxTransfer
/// The time system may be arbitrary as long as the clock is monotonic (steady).
CanardMicrosecond timestamp_usec;

/// Size of the payload data in bytes.
/// The value is always less than or equal to the extent specified in the subscription.
/// If the payload is empty (payload_size = 0), the payload pointer may be NULL.
size_t payload_size;

/// The application is required to deallocate the payload buffer after the transfer is processed.
/// Allocated buffer size (`allocated_size`, not `payload_size`) should be used to deallocate the buffer.
void* payload;

/// Size of the allocated payload buffer in bytes.
/// Normally equal to the extent specified in the subscription, but could be less (equal to `payload_size`)
/// in case of single frame transfer, or even zero if the payload pointer is NULL.
size_t allocated_size;
/// The application is required to deallocate the payload after the transfer is processed.
struct CanardMutablePayload payload;
} CanardRxTransfer;

/// This is the core structure that keeps all of the states and allocated resources of the library instance.
Expand Down Expand Up @@ -509,8 +524,7 @@ int32_t canardTxPush(CanardTxQueue* const que,
const CanardInstance* const ins,
const CanardMicrosecond tx_deadline_usec,
const CanardTransferMetadata* const metadata,
const size_t payload_size,
const void* const payload);
const struct CanardPayload payload);

/// This function accesses the top element of the prioritized transmission queue. The queue itself is not modified
/// (i.e., the accessed element is not removed). The application should invoke this function to collect the transport
Expand Down
44 changes: 21 additions & 23 deletions tests/exposed.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,17 @@ struct TxItem final : CanardTxQueueItem
{
[[nodiscard]] auto getPayloadByte(const std::size_t offset) const -> std::uint8_t
{
return reinterpret_cast<const std::uint8_t*>(frame.payload)[offset];
return static_cast<const std::uint8_t*>(frame.payload.data)[offset];
}

[[nodiscard]] auto getTailByte() const
{
if (frame.payload_size < 1U)
if (frame.payload.size < 1U)
{
// Can't use REQUIRE because it is not thread-safe.
throw std::logic_error("Can't get the tail byte because the frame payload is empty.");
}
return getPayloadByte(frame.payload_size - 1U);
return getPayloadByte(frame.payload.size - 1U);
}

[[nodiscard]] auto isStartOfTransfer() const { return (getTailByte() & 128U) != 0; }
Expand All @@ -45,30 +45,28 @@ struct TxItem final : CanardTxQueueItem

struct RxSession
{
CanardMicrosecond transfer_timestamp_usec = std::numeric_limits<std::uint64_t>::max();
std::size_t total_payload_size = 0U;
std::size_t payload_size = 0U;
std::uint8_t* payload = nullptr;
TransferCRC calculated_crc = 0U;
CanardTransferID transfer_id = std::numeric_limits<std::uint8_t>::max();
std::uint8_t redundant_iface_index = std::numeric_limits<std::uint8_t>::max();
bool toggle = false;
CanardMicrosecond transfer_timestamp_usec = std::numeric_limits<std::uint64_t>::max();
std::size_t total_payload_size = 0U;
CanardMutablePayload payload = {0U, nullptr, 0U};
TransferCRC calculated_crc = 0U;
CanardTransferID transfer_id = std::numeric_limits<std::uint8_t>::max();
std::uint8_t redundant_iface_index = std::numeric_limits<std::uint8_t>::max();
bool toggle = false;
};

struct RxFrameModel
{
CanardMicrosecond timestamp_usec = std::numeric_limits<std::uint64_t>::max();
CanardPriority priority = CanardPriorityOptional;
CanardTransferKind transfer_kind = CanardTransferKindMessage;
CanardPortID port_id = std::numeric_limits<std::uint16_t>::max();
CanardNodeID source_node_id = CANARD_NODE_ID_UNSET;
CanardNodeID destination_node_id = CANARD_NODE_ID_UNSET;
CanardTransferID transfer_id = std::numeric_limits<std::uint8_t>::max();
bool start_of_transfer = false;
bool end_of_transfer = false;
bool toggle = false;
std::size_t payload_size = 0U;
const std::uint8_t* payload = nullptr;
CanardMicrosecond timestamp_usec = std::numeric_limits<std::uint64_t>::max();
CanardPriority priority = CanardPriorityOptional;
CanardTransferKind transfer_kind = CanardTransferKindMessage;
CanardPortID port_id = std::numeric_limits<std::uint16_t>::max();
CanardNodeID source_node_id = CANARD_NODE_ID_UNSET;
CanardNodeID destination_node_id = CANARD_NODE_ID_UNSET;
CanardTransferID transfer_id = std::numeric_limits<std::uint8_t>::max();
bool start_of_transfer = false;
bool end_of_transfer = false;
bool toggle = false;
CanardPayload payload = {0U, nullptr};
};

// Extern C effectively discards the outer namespaces.
Expand Down
5 changes: 2 additions & 3 deletions tests/helpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -288,12 +288,11 @@ class TxQueue
[[nodiscard]] auto push(CanardInstance* const ins,
const CanardMicrosecond transmission_deadline_usec,
const CanardTransferMetadata& metadata,
const std::size_t payload_size,
const void* const payload)
const struct CanardPayload payload)
{
checkInvariants();
const auto size_before = que_.size;
const auto ret = canardTxPush(&que_, ins, transmission_deadline_usec, &metadata, payload_size, payload);
const auto ret = canardTxPush(&que_, ins, transmission_deadline_usec, &metadata, payload);
const auto num_added = static_cast<std::size_t>(ret);
enforce((ret < 0) || ((size_before + num_added) == que_.size), "Unexpected size change after push");
checkInvariants();
Expand Down
Loading

0 comments on commit dc19e93

Please sign in to comment.