Skip to content

Commit

Permalink
docs
Browse files Browse the repository at this point in the history
  • Loading branch information
serges147 committed Nov 26, 2024
1 parent ee70d86 commit 62451a0
Showing 1 changed file with 26 additions and 15 deletions.
41 changes: 26 additions & 15 deletions libcanard/canard.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,14 @@
/// Much like with dynamic memory, the time complexity of every API function is well-characterized, allowing the
/// application to guarantee predictable real-time performance.
///
/// The TX pipeline is managed with the help of four API functions. The first one -- canardTxInit() -- is used for
/// The TX pipeline is managed with the help of five API functions. The first one -- canardTxInit() -- is used for
/// constructing a new TX queue, of which there should be as many as there are redundant CAN interfaces;
/// each queue is managed independently. When the application needs to emit a transfer, it invokes canardTxPush()
/// on each queue separately. The function splits the transfer into CAN frames and stores them into the queue.
/// The application then picks the produced CAN frames from the queue one-by-one by calling canardTxPeek() followed
/// by canardTxPop() -- the former allows the application to look at the next frame scheduled for transmission,
/// and the latter tells the library that the frame shall be removed from the queue.
/// Popped frames need to be manually deallocated by the application upon transmission.
/// Popped frames need to be manually deallocated by the application upon transmission by calling canardTxFree().
///
/// The RX pipeline is managed with the help of three API functions; unlike the TX pipeline, there is one shared
/// state for all redundant interfaces that manages deduplication transparently. The main function canardRxAccept()
Expand Down Expand Up @@ -215,7 +215,8 @@ typedef struct
struct CanardPayload payload;
} CanardFrame;

/// TODO: docs!
/// Similar to the `CanardFrame` structure, but with a mutable payload (including `allocated_size` of the payload).
/// In use when payload memory ownership might be transferred.
struct CanardMutableFrame
{
uint32_t extended_can_id;
Expand Down Expand Up @@ -280,11 +281,11 @@ typedef struct
typedef void* (*CanardMemoryAllocate)(void* const user_reference, const size_t size);

/// The counterpart of the above -- this function is invoked to return previously allocated memory to the allocator.
/// The semantics are similar to free(), but with additional `amount` parameter:
/// The semantics are similar to free(), but with additional `size` parameter:
/// - The pointer was previously returned by the allocation function.
/// - The pointer may be NULL, in which case the function shall have no effect.
/// - The execution time should be constant (O(1)).
/// - The amount is the same as it was during allocation.
/// - The size is the same as it was during allocation.
///
/// The value of the user reference is taken from the corresponding field of the memory resource structure.
typedef void (*CanardMemoryDeallocate)(void* const user_reference, const size_t size, void* const pointer);
Expand All @@ -311,7 +312,9 @@ struct CanardMemoryResource
/// Prioritized transmission queue that keeps CAN frames destined for transmission via one CAN interface.
/// Applications with redundant interfaces are expected to have one instance of this type per interface.
/// Applications that are not interested in transmission may have zero queues.
/// All operations (push, peek, pop) are O(log n); there is exactly one heap allocation per element.
/// All operations (push, peek, pop) are O(log n); there are exactly two heap allocations per element:
/// - the first for bookkeeping purposes (CanardTxQueueItem)
/// - second for payload storage (the frame data)
/// API functions that work with this type are named "canardTx*()", find them below.
typedef struct CanardTxQueue
{
Expand All @@ -337,11 +340,16 @@ typedef struct CanardTxQueue
/// The root of the priority queue is NULL if the queue is empty. Do not modify this field!
CanardTreeNode* root;

/// The memory resource used by this queue for allocating the enqueued items (CAN frames).
/// There is exactly one allocation per enqueued item, each allocation contains both the CanardTxQueueItem
/// and its payload, hence the size is variable.
/// The memory resource used by this queue for allocating payload data (CAN frames).
/// There is exactly one allocation per enqueued item. Its size is equal to the MTU of the queue.
/// Memory for the queue item is allocated separately from the instance memory resource.
/// In a simple application, there would be just one memory resource shared by all parts of the library.
/// If the application knows its MTU, it can use block allocation to avoid extrinsic fragmentation.
/// If the application knows its MTU, it can use block allocation to avoid extrinsic fragmentation,
/// as well as a dedicated memory pool specifically for the TX queue payload for transmission.
/// Dedicated memory resources could be useful also for systems with special memory requirements for payload data.
/// For example, such a memory resource could be integrated with a peripheral DMA controller. So that
/// memory is allocated directly in the peripheral's memory space. Then it will be filled with payload data by
/// the Canard, and finally it will be ready to be directly transmitted by DMA HW (avoiding the need for copying).
struct CanardMemoryResource memory;

/// This field can be arbitrarily mutated by the user. It is never accessed by the library.
Expand Down Expand Up @@ -473,7 +481,7 @@ CanardInstance canardInit(const struct CanardMemoryResource memory);
/// Applications are expected to have one instance of this type per redundant interface.
///
/// The instance does not hold any resources itself except for the allocated memory.
/// To safely discard it, simply pop all items from the queue.
/// To safely discard it, simply pop all items from the queue and free them.
///
/// The time complexity is constant. This function does not invoke the dynamic memory manager.
CanardTxQueue canardTxInit(const size_t capacity, const size_t mtu_bytes, const struct CanardMemoryResource memory);
Expand Down Expand Up @@ -520,9 +528,12 @@ CanardTxQueue canardTxInit(const size_t capacity, const size_t mtu_bytes, const
/// The time complexity is O(p + log e), where p is the amount of payload in the transfer, and e is the number of
/// frames already enqueued in the transmission queue.
///
/// The memory allocation requirement is one allocation per transport frame. A single-frame transfer takes one
/// allocation; a multi-frame transfer of N frames takes N allocations. The size of each allocation is
/// (sizeof(CanardTxQueueItem) + MTU).
/// The memory allocation requirement is two allocations per transport frame. A single-frame transfer takes two
/// allocations; a multi-frame transfer of N frames takes N*2 allocations. In each pair of allocations:
/// - the first allocation is for CanardTxQueueItem; the size is `sizeof(CanardTxQueueItem)`;
/// the Canard instance memory resource is used for this allocation (and later for deallocation);
/// - the second allocation is for payload storage (the frame data) - size is normally MTU but could be less for
/// the last frame of the transfer; the TX queue memory resource is used for this allocation.
int32_t canardTxPush(CanardTxQueue* const que,
const CanardInstance* const ins,
const CanardMicrosecond tx_deadline_usec,
Expand Down Expand Up @@ -553,7 +564,7 @@ int32_t canardTxPush(CanardTxQueue* const que,
/// If these fields stay with their original values, the `canardTxFree` (after proper `canardTxPop of course) will
/// deallocate the payload buffer. In any case, the payload has to be eventually deallocated by the TX queue memory
/// resource. It will be automatically done by the `canardTxFree` (if the payload still stays in the item),
/// OR if moved, it is the responsibility of theapplication to eventually (f.e. at the end of transmission) deallocate
/// OR if moved, it is the responsibility of the application to eventually (f.e. at the end of transmission) deallocate
/// the memory with TX queue memory resource. Note that the mentioned above nullification of the payload fields is the
/// only reason why a returned TX item pointer is mutable. It was constant in the past (before v4),
/// but it was changed to be mutable to allow the payload ownership transfer.
Expand Down

0 comments on commit 62451a0

Please sign in to comment.