Skip to content

Commit

Permalink
eliminate struct/enum typedef-s #sonar
Browse files Browse the repository at this point in the history
  • Loading branch information
serges147 committed Nov 28, 2024
1 parent 3e70aa5 commit e58963c
Show file tree
Hide file tree
Showing 6 changed files with 243 additions and 237 deletions.
47 changes: 26 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,6 @@ reused in the target application to speed up the design of the media IO layer (d

## Example

## TODO: Update to show how to use the new sized de-allocations, and how not to confuse payload_size and allocated_size.
☝ todo will be addressed as soon as the new API is stable (tx, rx, and "zero copy" aspects).

The example augments the documentation but does not replace it.

The library requires a constant-complexity deterministic dynamic memory allocator.
Expand All @@ -68,39 +65,43 @@ so let's suppose that we're using [O1Heap](https://github.com/pavel-kirienko/o1h
We are going to need basic wrappers:

```c
static void* memAllocate(CanardInstance* const canard, const size_t amount)
static void* memAllocate(void* const user_reference, const size_t size)
{
(void) canard;
return o1heapAllocate(my_allocator, amount);
(void) user_reference;
return o1heapAllocate(my_allocator, size);
}

static void memFree(CanardInstance* const canard, void* const pointer, const size_t amount)
static void memFree(void* const user_reference, const size_t size, void* const pointer)
{
(void) canard;
(void) amount;
(void) user_reference;
(void) size;
o1heapFree(my_allocator, pointer);
}
```
Init a library instance:
```c
CanardInstance canard = canardInit(&memAllocate, &memFree);
const struct CanardMemoryResource memory{nullptr, &memAllocate, &memFree};
struct CanardInstance canard = canardInit(memory);
canard.node_id = 42; // Defaults to anonymous; can be set up later at any point.
```

In order to be able to send transfers over the network, we will need one transmission queue per redundant CAN interface:

```c
CanardTxQueue queue = canardTxInit(100, // Limit the size of the queue at 100 frames.
CANARD_MTU_CAN_FD); // Set MTU = 64 bytes. There is also CANARD_MTU_CAN_CLASSIC.
const struct CanardMemoryResource tx_memory{nullptr, memAllocate, memFree};
struct CanardTxQueue queue = canardTxInit(
100, // Limit the size of the queue at 100 frames.
CANARD_MTU_CAN_FD, // Set MTU = 64 bytes. There is also CANARD_MTU_CAN_CLASSIC.
tx_memory);
```
Publish a message (message serialization not shown):
```c
static uint8_t my_message_transfer_id; // Must be static or heap-allocated to retain state between calls.
const CanardTransferMetadata transfer_metadata = {
const struct CanardTransferMetadata transfer_metadata = {
.priority = CanardPriorityNominal,
.transfer_kind = CanardTransferKindMessage,
.port_id = 1234, // This is the subject-ID.
Expand Down Expand Up @@ -131,7 +132,7 @@ Normally, the following fragment should be invoked periodically to unload the CA
prioritized transmission queue (or several, if redundant network interfaces are used) into the CAN driver:

```c
for (const CanardTxQueueItem* ti = NULL; (ti = canardTxPeek(&queue)) != NULL;) // Peek at the top of the queue.
for (struct CanardTxQueueItem* ti = NULL; (ti = canardTxPeek(&queue)) != NULL;) // Peek at the top of the queue.
{
if ((0U == ti->tx_deadline_usec) || (ti->tx_deadline_usec > getCurrentMicroseconds())) // Check the deadline.
{
Expand All @@ -141,7 +142,7 @@ for (const CanardTxQueueItem* ti = NULL; (ti = canardTxPeek(&queue)) != NULL;)
}
}
// After the frame is transmitted or if it has timed out while waiting, pop it from the queue and deallocate:
canard.memory_free(&canard, canardTxPop(&queue, ti));
canardTxFree(&queue, &canard, canardTxPop(&queue, ti));
}
```

Expand All @@ -150,15 +151,15 @@ from any of the redundant interfaces.
But first, we need to subscribe:

```c
CanardRxSubscription heartbeat_subscription;
struct CanardRxSubscription heartbeat_subscription;
(void) canardRxSubscribe(&canard, // Subscribe to messages uavcan.node.Heartbeat.
CanardTransferKindMessage,
7509, // The fixed Subject-ID of the Heartbeat message type (see DSDL definition).
16, // The extent (the maximum possible payload size) provided by Nunavut.
CANARD_DEFAULT_TRANSFER_ID_TIMEOUT_USEC,
&heartbeat_subscription);

CanardRxSubscription my_service_subscription;
struct CanardRxSubscription my_service_subscription;
(void) canardRxSubscribe(&canard, // Subscribe to an arbitrary service response.
CanardTransferKindResponse, // Specify that we want service responses, not requests.
123, // The Service-ID whose responses we will receive.
Expand All @@ -183,7 +184,7 @@ Normally, however, an embedded application would subscribe once and roll with it
Okay, this is how we receive transfers:

```c
CanardRxTransfer transfer;
struct CanardRxTransfer transfer;
const int8_t result = canardRxAccept(&canard,
rx_timestamp_usec, // When the frame was received, in microseconds.
&received_frame, // The CAN frame received from the bus.
Expand Down Expand Up @@ -216,15 +217,15 @@ the number of irrelevant transfers processed in software.

```c
// Generate an acceptance filter to receive only uavcan.node.Heartbeat.1.0 messages (fixed port-ID 7509):
CanardFilter heartbeat_config = canardMakeFilterForSubject(7509);
struct CanardFilter heartbeat_config = canardMakeFilterForSubject(7509);
// And to receive only uavcan.register.Access.1.0 service transfers (fixed port-ID 384):
CanardFilter register_access_config = canardMakeFilterForService(384, ins.node_id);
struct CanardFilter register_access_config = canardMakeFilterForService(384, ins.node_id);

// You can also combine the two filter configurations into one (may also accept irrelevant messages).
// This allows consolidating a large set of configurations to fit the number of hardware filters.
// For more information on the optimal subset of configurations to consolidate to minimize wasted CPU,
// see the Cyphal specification.
CanardFilter combined_config =
struct CanardFilter combined_config =
canardConsolidateFilters(&heartbeat_config, &register_access_config);
configureHardwareFilters(combined_config.extended_can_id, combined_config.extended_mask);
```
Expand All @@ -234,6 +235,10 @@ If you find the examples to be unclear or incorrect, please, open a ticket.
## Revisions
### v4.0
#### TODO: Highlight the most important changes. Mention migration guide doc.
### v3.2
- Added new `canardRxGetSubscription`.
Expand Down
2 changes: 1 addition & 1 deletion libcanard/_canard_cavl.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ extern "C" {
// ---------------------------------------- PUBLIC API SECTION ----------------------------------------

/// Modified for use with Libcanard: expose the Cavl structure via public API as CanardTreeNode.
typedef CanardTreeNode Cavl;
typedef struct CanardTreeNode Cavl;

/// Returns POSITIVE if the search target is GREATER than the provided node, negative if smaller, zero on match (found).
/// Values other than {-1, 0, +1} are not recommended to avoid overflow during the narrowing conversion of the result.
Expand Down
Loading

0 comments on commit e58963c

Please sign in to comment.