Giter Site home page Giter Site logo

opencyphal / libcanard Goto Github PK

View Code? Open in Web Editor NEW
316.0 51.0 192.0 1.19 MB

A compact implementation of the Cyphal/CAN protocol in C for high-integrity real-time embedded systems

Home Page: http://opencyphal.org

License: MIT License

CMake 0.60% C++ 86.86% C 12.54%
uavcan canbus can-bus can robotics embedded embedded-systems protocol uav aerospace

libcanard's Introduction

Compact Cyphal/CAN in C

Main Workflow Quality Gate Status Reliability Rating Coverage Lines of Code Forum

Libcanard is a compact implementation of the Cyphal/CAN protocol stack in C99/C11 for high-integrity real-time embedded systems.

Cyphal is an open lightweight data bus standard designed for reliable intravehicular communication in aerospace and robotic applications via CAN bus, Ethernet, and other robust transports.

Read the docs in libcanard/canard.h.

Find examples, starters, tutorials on the Cyphal forum.

If you want to contribute, please read CONTRIBUTING.md.

Features

  • Full test coverage and extensive static analysis.
  • Compliance with automatically enforceable MISRA C rules (reach out to https://forum.opencyphal.org for details).
  • Detailed time complexity and memory requirement models for the benefit of real-time high-integrity applications.
  • Purely reactive API without the need for background servicing.
  • Support for the Classic CAN and CAN FD.
  • Support for redundant network interfaces.
  • Compatibility with 8/16/32/64-bit platforms.
  • Compatibility with extremely resource-constrained baremetal environments starting from 32K ROM and 32K RAM.
  • Implemented in ≈1000 lines of code.

Platforms

The library is designed to be usable out of the box with any conventional 8/16/32/64-bit platform, including deeply embedded baremetal platforms, as long as there is a standard-compliant compiler available. The platform-specific media IO layer (driver) is supposed to be provided by the application:

+---------------------------------+
|           Application           |
+-------+-----------------+-------+
        |                 |
+-------+-------+ +-------+-------+
|   Libcanard   | |  Media layer  |
+---------------+ +-------+-------+
                          |
                  +-------+-------+
                  |    Hardware   |
                  +---------------+

The OpenCyphal Development Team maintains a collection of various platform-specific components in a separate repository at https://github.com/OpenCyphal/platform_specific_components. Users are encouraged to search through that repository for drivers, examples, and other pieces that may be reused in the target application to speed up the design of the media IO layer (driver) for the application.

Example

The example augments the documentation but does not replace it.

The library requires a constant-complexity deterministic dynamic memory allocator. We could use the standard C heap, but most implementations are not constant-complexity, so let's suppose that we're using O1Heap instead. We are going to need basic wrappers:

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

static void memFree(CanardInstance* const canard, void* const pointer)
{
    (void) canard;
    o1heapFree(my_allocator, pointer);
}

Init a library instance:

CanardInstance canard = canardInit(&memAllocate, &memFree);
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:

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.

Publish a message (message serialization not shown):

static uint8_t my_message_transfer_id;  // Must be static or heap-allocated to retain state between calls.
const CanardTransferMetadata transfer_metadata = {
    .priority       = CanardPriorityNominal,
    .transfer_kind  = CanardTransferKindMessage,
    .port_id        = 1234,                       // This is the subject-ID.
    .remote_node_id = CANARD_NODE_ID_UNSET,       // Messages cannot be unicast, so use UNSET.
    .transfer_id    = my_message_transfer_id,
};
++my_message_transfer_id;  // The transfer-ID shall be incremented after every transmission on this subject.
int32_t result = canardTxPush(&queue,               // Call this once per redundant CAN interface (queue).
                              &canard,
                              tx_deadline_usec,     // Zero if transmission deadline is not limited.
                              &transfer_metadata,
                              47,                   // Size of the message payload (see Nunavut transpiler).
                              "\x2D\x00" "Sancho, it strikes me thou art in great fear.");
if (result < 0)
{
    // An error has occurred: either an argument is invalid, the TX queue is full, or we've run out of memory.
    // It is possible to statically prove that an out-of-memory will never occur for a given application if the
    // heap is sized correctly; for background, refer to the Robson's Proof and the documentation for O1Heap.
}

Use Nunavut to automatically generate (de)serialization code from DSDL definitions.

The CAN frames generated from the message transfer are now stored in the queue. We need to pick them out one by one and have them transmitted. Normally, the following fragment should be invoked periodically to unload the CAN frames from the prioritized transmission queue (or several, if redundant network interfaces are used) into the CAN driver:

for (const 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.
    {
        if (!pleaseTransmit(ti))               // Send the frame over this redundant CAN iface.
        {
            break;                             // If the driver is busy, break and retry later.
        }
    }
    // 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));
}

Transfer reception is done by feeding frames into the transfer reassembly state machine from any of the redundant interfaces. But first, we need to subscribe:

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;
(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.
                         1024,      // The extent (see above).
                         CANARD_DEFAULT_TRANSFER_ID_TIMEOUT_USEC,
                         &my_service_subscription);

The "extent" refers to the minimum amount of memory required to hold any serialized representation of any compatible version of the data type; or, in other words, it is the maximum possible size of received objects. This parameter is determined by the data type author at the data type definition time. It is typically larger than the maximum object size in order to allow the data type author to introduce more fields in the future versions of the type; for example, MyMessage.1.0 may have the maximum size of 100 bytes and the extent 200 bytes; a revised version MyMessage.1.1 may have the maximum size anywhere between 0 and 200 bytes. Extent values are provided per data type by DSDL transcompilers such as Nunavut.

In Libcanard we use the term "subscription" not only for subjects (messages), but also for services, for simplicity.

We can subscribe and unsubscribe at runtime as many times as we want. Normally, however, an embedded application would subscribe once and roll with it. Okay, this is how we receive transfers:

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.
                                     redundant_interface_index,  // If the transport is not redundant, use 0.
                                     &transfer,
                                     NULL);
if (result < 0)
{
    // An error has occurred: either an argument is invalid or we've ran out of memory.
    // It is possible to statically prove that an out-of-memory will never occur for a given application if
    // the heap is sized correctly; for background, refer to the Robson's Proof and the documentation for O1Heap.
    // Reception of an invalid frame is NOT an error.
}
else if (result == 1)
{
    processReceivedTransfer(redundant_interface_index, &transfer);  // A transfer has been received, process it.
    canard.memory_free(&canard, transfer.payload);                  // Deallocate the dynamic memory afterwards.
}
else
{
    // Nothing to do.
    // The received frame is either invalid or it's a non-last frame of a multi-frame transfer.
    // Reception of an invalid frame is NOT reported as an error because it is not an error.
}

A simple API for generating CAN hardware acceptance filter configurations is also provided. Acceptance filters are generated in an extended 29-bit ID + mask scheme and can be used to minimize the number of irrelevant transfers processed in software.

// Generate an acceptance filter to receive only uavcan.node.Heartbeat.1.0 messages (fixed port-ID 7509):
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);

// 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 =
        canardConsolidateFilters(&heartbeat_config, &register_access_config);
configureHardwareFilters(combined_config.extended_can_id, combined_config.extended_mask);

Full API specification is available in the documentation. If you find the examples to be unclear or incorrect, please, open a ticket.

Revisions

v3.2

  • Added new canardRxGetSubscription.

v3.1

v3.1.1

  • Refactor the transfer reassembly state machine to enhance its maintainability and robustness.

v3.1.2

  • Allow redefinition of CANARD_ASSERT via the config header; see #219.

v3.0

  • Update branding as UAVCAN v1 is renamed to Cyphal.

  • Improve MISRA compliance by removing use of flex array: (#192).

  • Fix dependency issues in docker toolchain.

    There are no API changes in this release aside from the rebranding/renaming: CANARD_UAVCAN_SPECIFICATION_VERSION_MAJOR -> CANARD_CYPHAL_SPECIFICATION_VERSION_MAJOR CANARD_UAVCAN_SPECIFICATION_VERSION_MINOR -> CANARD_CYPHAL_SPECIFICATION_VERSION_MINOR

v3.0.1

  • Remove UB as described in 203.

v3.0.2

  • Robustify the multi-frame transfer reassembler state machine (#189).
  • Eliminate the risk of a header file name collision by renaming the vendored Cavl header to _canard_cavl.h (#196).

v2.0

  • Dedicated transmission queues per redundant CAN interface with depth limits. The application is now expected to instantiate CanardTxQueue (or several in case of redundant transport) manually.

  • Replace O(n) linked lists with fast O(log n) AVL trees (Cavl library is distributed with libcanard). Traversing the list of RX subscriptions now requires recursive traversal of the tree.

  • Manual DSDL serialization helpers removed; use Nunavut instead.

  • Replace bitwise CRC computation with much faster static table by default (#185). This can be disabled by setting CANARD_CRC_TABLE=0, which is expected to save ca. 500 bytes of ROM.

  • Fixed issues with const-correctness in the API (#175).

  • canardRxAccept2() renamed to canardRxAccept().

  • Support build configuration headers via CANARD_CONFIG_HEADER.

  • Add API for generating CAN hardware acceptance filter configurations (#169).

v1.1

  • Add new API function canardRxAccept2(), deprecate canardRxAccept().
  • Provide user references in CanardRxSubscription.
  • Promote certain internal fields to the public API to allow introspection.

v1.0

The initial release.

libcanard's People

Contributors

aasmune avatar acassis avatar adolfogc avatar antoinealb avatar asfishman avatar coderkalyan avatar davidlenfesty avatar espitall avatar fvantienen avatar joshvazquez-amzn avatar jvishnefske avatar kjetilkjeka avatar linjieqiang avatar magshaw avatar mahibak avatar masierra avatar nacansino avatar papatience avatar pavel-kirienko avatar petervdperk-nxp avatar ponomarevda avatar rennerm avatar serges147 avatar storola avatar tridge avatar vvg77ripe avatar wesen avatar ycherniavskyi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

libcanard's Issues

I found a bug in libcanard dsdl compiler

Hi
Today I use libcanard dsdl compiler to generate code,
I fill below in my *.uavcan files:

uint8[<=6] command

and I found that in encode,
uavcan_xxx_encode_internal(source, msg_buf, offset, 1);
uavcan_xxx_encode_internal(uavcan_syrius_RobotCommand* source, void* msg_buf, uint32_t offset, uint8_t root_item)

Here is root_item = 1
and here inside uavcan_xxx_encode_internal
if (! root_item)
{
// - Add array length
canardEncodeScalar(msg_buf, offset, 3, (void*)&source->command.len);
offset += 3;
}

I think if (! root_item) need to be if (root_item).
this means that the first 3bits means length of my buffer.

because that in decode, this parameter need it.

Time-stamps for outgoing frames

According to http://uavcan.org/Specification/4._CAN_bus_transport_layer/#service-invocation

Service transfer transmission should be aborted if does not complete in 1 second.

As I understand, this means: if node determines it cannot send uavcan message within 1 second, it should stop trying for that particular message. If that true, then the following problem might have place.

Libcanard stores outgoing CAN frames in CanardTxQueueItem list which does not contain a time-stamp:

struct CanardTxQueueItem
{
    CanardTxQueueItem* next;
    CanardCANFrame frame;
};

Thus it seems impossible to determine whenever outgoing transfer item has reached a timeout.

addition 1

For multi-frame transfers it seems second and following frames may be stamped as first frame + 2 seconds, according to constant value in canard.c:

#define TRANSFER_TIMEOUT_USEC                       2000000

addition 2

If timestamp will exist, then it will be possible to implement function like canardCleanupStaleTransfers but for outgoing transfers. So application may decide if it wants to clean up outgoing stale frames of keep them going.

Implement drivers for LPC11C24

Libcanard should be a great fit for this MCU, unlike libuavcan, which takes almost all available ROM and RAM (32K/8K).

Boolean saturated to 0 length

Using DSDL definition dsdl/101.Bool.uavcan:

bool in
---
bool out

The following is generated:

uint32_t dsdl_BoolRequest_encode_internal(dsdl_BoolRequest* source,
  void* msg_buf,
  uint32_t offset,
  uint8_t CANARD_MAYBE_UNUSED(root_item))
{
    source->in = CANARD_INTERNAL_SATURATE_UNSIGNED(source->in, 0)
    canardEncodeScalar(msg_buf, offset, 1, (void*)&source->in); // 0
    offset += 1;

    return offset;
}

Saturation to length zero forces the saturated value to always be 0.

No longer applying saturation, and treating bool as an unsigned type for max size calculation seems to fix the issue, apply the diff:

diff --git a/dsdl_compiler/libcanard_dsdl_compiler/__init__.py b/dsdl_compiler/libcanard_dsdl_compiler/__init__.py
index 9b66128..474a8d3 100644
--- a/dsdl_compiler/libcanard_dsdl_compiler/__init__.py
+++ b/dsdl_compiler/libcanard_dsdl_compiler/__init__.py
@@ -217,9 +217,9 @@ def type_to_c_type(t):
                     'post_cpp_type':'',
                     'cpp_type_comment':'bit len %d' % (t.bitlen, ),
                     'bitlen':t.bitlen,
-                    'max_size':get_max_size(t.bitlen, False),
+                    'max_size':get_max_size(t.bitlen, True),
                     'signedness':signedness,
-                    'saturate':saturate}
+                    'saturate':False}
             else:
                 if saturate:
                     # Do not staturate if struct field length is equal bitlen

Generating:

uint32_t dsdl_BoolRequest_encode_internal(dsdl_BoolRequest* source,
  void* msg_buf,
  uint32_t offset,
  uint8_t CANARD_MAYBE_UNUSED(root_item))
{
    canardEncodeScalar(msg_buf, offset, 1, (void*)&source->in); // 1
    offset += 1;

    return offset;
}

Suggestions II

I've just seen the Suggestions by OlliW comit :)

I would also suggest this change in canard.h

...
#include <stdbool.h>
#ifndef CANARD_ASSERT
#  include <assert.h>
#endif

#ifdef __cplusplus
...

On my system at least (baremetal, STM32F103, CocCoox) linking to the assert.h causes a chain of issues

In canard_stm32.c I found usleep() troubling, and did this change

...
#include "canard_stm32.h"
#include "_internal_bxcan.h"
//#include <unistd.h>
extern void canardSTM32DelayUs(uint16_t);
...

...
        // Sleep 1 millisecond
//        usleep(1000);           // TODO: This function may be missing on some platforms
            canardSTM32DelayUs(1000);
    }
...

There is a Bug in libcanard dsdl,Please check –BeginFirmwareUpdateRequest

There‘s a Bug in uavcan_protocol_file_BeginFirmwareUpdateRequest_decode_internal(…)
This Bug lead to a wrong decode struct.
line 89

// Compound
offset = uavcan_protocol_file_Path_decode_internal(transfer, 0, &dest->image_file_remote_path, dyn_arr_buf, offset);

The second actual parameter should not be ‘0’, It should be ‘payload_len’;

fix:

// Compound
offset = uavcan_protocol_file_Path_decode_internal(transfer, payload_len, &dest->image_file_remote_path, dyn_arr_buf, offset);

Libcanard DSDL compiler fails when source paths ends with a trailing os separator in Windows

When generating C source code using the DSDL compiler in libcanard, it fails if the source paths provided from CLI ends with a trailing \\ or /.

$ python libcanard\dsdl_compiler\libcanard_dsdlc -O output dsdl/uavcan/                                                                                             
Internal error                                                                                                                                                      
Traceback (most recent call last):                                                                                                                                  
  File "C:\Python37-32\lib\site-packages\uavcan\dsdl\parser.py", line 708, in parse                                                                                 
    return self.parse_source(filename, source_text)                                                                                                                 
  File "C:\Python37-32\lib\site-packages\uavcan\dsdl\parser.py", line 700, in parse_source                                                                          
    raise ex                                                                                                                                                        
  File "C:\Python37-32\lib\site-packages\uavcan\dsdl\parser.py", line 632, in parse_source                                                                          
    full_typename, version, default_dtid = self._full_typename_version_and_dtid_from_filename(filename)                                                             
  File "C:\Python37-32\lib\site-packages\uavcan\dsdl\parser.py", line 455, in _full_typename_version_and_dtid_from_filename                                         
    full_name = self._namespace_from_filename(filename) + '.' + name                                                                                                
  File "C:\Python37-32\lib\site-packages\uavcan\dsdl\parser.py", line 426, in _namespace_from_filename                                                              
    validate_namespace_name(ns)                                                                                                                                     
  File "C:\Python37-32\lib\site-packages\uavcan\dsdl\parser.py", line 758, in validate_namespace_name                                                               
    enforce(re.match(r'[a-z][a-z0-9_]*$', component), 'Invalid namespace name [%s]', name)                                                                          
  File "C:\Python37-32\lib\site-packages\uavcan\dsdl\parser.py", line 722, in enforce                                                                               
    error(fmt, *args)                                                                                                                                               
  File "C:\Python37-32\lib\site-packages\uavcan\dsdl\parser.py", line 717, in error                                                                                 
    raise DsdlException(fmt % args)                                                                                                                                 
uavcan.dsdl.common.DsdlException: dsdl\uavcan\CoarseOrientation.uavcan: Invalid namespace name []                                                                   
Compiler failure                                                                                                                                                    
Traceback (most recent call last):                                                                                                                                  
  File "C:\Python37-32\lib\site-packages\uavcan\dsdl\parser.py", line 708, in parse                                                                                 
    return self.parse_source(filename, source_text)                                                                                                                 
  File "C:\Python37-32\lib\site-packages\uavcan\dsdl\parser.py", line 700, in parse_source                                                                          
    raise ex                                                                                                                                                        
  File "C:\Python37-32\lib\site-packages\uavcan\dsdl\parser.py", line 632, in parse_source                                                                          
    full_typename, version, default_dtid = self._full_typename_version_and_dtid_from_filename(filename)                                                             
  File "C:\Python37-32\lib\site-packages\uavcan\dsdl\parser.py", line 455, in _full_typename_version_and_dtid_from_filename                                         
    full_name = self._namespace_from_filename(filename) + '.' + name                                                                                                
  File "C:\Python37-32\lib\site-packages\uavcan\dsdl\parser.py", line 426, in _namespace_from_filename                                                              
    validate_namespace_name(ns)                                                                                                                                     
  File "C:\Python37-32\lib\site-packages\uavcan\dsdl\parser.py", line 758, in validate_namespace_name                                                               
    enforce(re.match(r'[a-z][a-z0-9_]*$', component), 'Invalid namespace name [%s]', name)                                                                          
  File "C:\Python37-32\lib\site-packages\uavcan\dsdl\parser.py", line 722, in enforce                                                                               
    error(fmt, *args)                                                                                                                                               
  File "C:\Python37-32\lib\site-packages\uavcan\dsdl\parser.py", line 717, in error                                                                                 
    raise DsdlException(fmt % args)                                                                                                                                 
uavcan.dsdl.common.DsdlException: dsdl\uavcan\CoarseOrientation.uavcan: Invalid namespace name []                                                                   
                                                                                                                                                                    
During handling of the above exception, another exception occurred:                                                                                                 
                                                                                                                                                                    
Traceback (most recent call last):                                                                                                                                  
  File "C:\Users\aasme\Documents\git\uavcan\libcanard\dsdl_compiler\libcanard_dsdl_compiler\__init__.py", line 111, in run_parser                                   
    types = dsdl.parse_namespaces(source_dirs, search_dirs)                                                                                                         
  File "C:\Python37-32\lib\site-packages\uavcan\dsdl\parser.py", line 860, in parse_namespaces                                                                      
    t = parser.parse(filename)                                                                                                                                      
  File "C:\Python37-32\lib\site-packages\uavcan\dsdl\parser.py", line 713, in parse                                                                                 
    raise DsdlException('Internal error: %s' % str(ex), file=filename)                                                                                              
uavcan.dsdl.common.DsdlException: dsdl\uavcan\CoarseOrientation.uavcan: Internal error: dsdl\uavcan\CoarseOrientation.uavcan: Invalid namespace name []             
                                                                                                                                                                    
During handling of the above exception, another exception occurred:                                                                                                 
                                                                                                                                                                    
Traceback (most recent call last):                                                                                                                                  
  File "libcanard\dsdl_compiler\libcanard_dsdlc", line 66, in <module>                                                                                              
    dsdlc_run(args.source_dir, args.incdir, args.outdir, args.header_only)                                                                                          
  File "C:\Users\aasme\Documents\git\uavcan\libcanard\dsdl_compiler\libcanard_dsdl_compiler\__init__.py", line 64, in run                                           
    types = run_parser(source_dirs, include_dirs + source_dirs)                                                                                                     
  File "C:\Users\aasme\Documents\git\uavcan\libcanard\dsdl_compiler\libcanard_dsdl_compiler\__init__.py", line 114, in run_parser                                   
    die(ex)                                                                                                                                                         
  File "C:\Users\aasme\Documents\git\uavcan\libcanard\dsdl_compiler\libcanard_dsdl_compiler\__init__.py", line 107, in die                                          
    raise DsdlCompilerException(str(text))                                                                                                                          
libcanard_dsdl_compiler.DsdlCompilerException: dsdl\uavcan\CoarseOrientation.uavcan: Internal error: dsdl\uavcan\CoarseOrientation.uavcan: Invalid namespace name []
dsdl\uavcan\CoarseOrientation.uavcan: Internal error: dsdl\uavcan\CoarseOrientation.uavcan: Invalid namespace name []                                               

and

$ python libcanard\dsdl_compiler\libcanard_dsdlc -O output dsdl\uavcan\
Internal error
Traceback (most recent call last):
  File "C:\Python37-32\lib\site-packages\uavcan\dsdl\parser.py", line 708, in parse
    return self.parse_source(filename, source_text)
  File "C:\Python37-32\lib\site-packages\uavcan\dsdl\parser.py", line 700, in parse_source
    raise ex
  File "C:\Python37-32\lib\site-packages\uavcan\dsdl\parser.py", line 632, in parse_source
    full_typename, version, default_dtid = self._full_typename_version_and_dtid_from_filename(filename)
  File "C:\Python37-32\lib\site-packages\uavcan\dsdl\parser.py", line 455, in _full_typename_version_and_dtid_from_filename
    full_name = self._namespace_from_filename(filename) + '.' + name
  File "C:\Python37-32\lib\site-packages\uavcan\dsdl\parser.py", line 426, in _namespace_from_filename
    validate_namespace_name(ns)
  File "C:\Python37-32\lib\site-packages\uavcan\dsdl\parser.py", line 758, in validate_namespace_name
    enforce(re.match(r'[a-z][a-z0-9_]*$', component), 'Invalid namespace name [%s]', name)
  File "C:\Python37-32\lib\site-packages\uavcan\dsdl\parser.py", line 722, in enforce
    error(fmt, *args)
  File "C:\Python37-32\lib\site-packages\uavcan\dsdl\parser.py", line 717, in error
    raise DsdlException(fmt % args)
uavcan.dsdl.common.DsdlException: dsdl\uavcan\CoarseOrientation.uavcan: Invalid namespace name []
Compiler failure
Traceback (most recent call last):
  File "C:\Python37-32\lib\site-packages\uavcan\dsdl\parser.py", line 708, in parse
    return self.parse_source(filename, source_text)
  File "C:\Python37-32\lib\site-packages\uavcan\dsdl\parser.py", line 700, in parse_source
    raise ex
  File "C:\Python37-32\lib\site-packages\uavcan\dsdl\parser.py", line 632, in parse_source
    full_typename, version, default_dtid = self._full_typename_version_and_dtid_from_filename(filename)
  File "C:\Python37-32\lib\site-packages\uavcan\dsdl\parser.py", line 455, in _full_typename_version_and_dtid_from_filename
    full_name = self._namespace_from_filename(filename) + '.' + name
  File "C:\Python37-32\lib\site-packages\uavcan\dsdl\parser.py", line 426, in _namespace_from_filename
    validate_namespace_name(ns)
  File "C:\Python37-32\lib\site-packages\uavcan\dsdl\parser.py", line 758, in validate_namespace_name
    enforce(re.match(r'[a-z][a-z0-9_]*$', component), 'Invalid namespace name [%s]', name)
  File "C:\Python37-32\lib\site-packages\uavcan\dsdl\parser.py", line 722, in enforce
    error(fmt, *args)
  File "C:\Python37-32\lib\site-packages\uavcan\dsdl\parser.py", line 717, in error
    raise DsdlException(fmt % args)
uavcan.dsdl.common.DsdlException: dsdl\uavcan\CoarseOrientation.uavcan: Invalid namespace name []

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\aasme\Documents\git\uavcan\libcanard\dsdl_compiler\libcanard_dsdl_compiler\__init__.py", line 111, in run_parser
    types = dsdl.parse_namespaces(source_dirs, search_dirs)
  File "C:\Python37-32\lib\site-packages\uavcan\dsdl\parser.py", line 860, in parse_namespaces
    t = parser.parse(filename)
  File "C:\Python37-32\lib\site-packages\uavcan\dsdl\parser.py", line 713, in parse
    raise DsdlException('Internal error: %s' % str(ex), file=filename)
uavcan.dsdl.common.DsdlException: dsdl\uavcan\CoarseOrientation.uavcan: Internal error: dsdl\uavcan\CoarseOrientation.uavcan: Invalid namespace name []

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "libcanard\dsdl_compiler\libcanard_dsdlc", line 66, in <module>
    dsdlc_run(args.source_dir, args.incdir, args.outdir, args.header_only)
  File "C:\Users\aasme\Documents\git\uavcan\libcanard\dsdl_compiler\libcanard_dsdl_compiler\__init__.py", line 64, in run
    types = run_parser(source_dirs, include_dirs + source_dirs)
  File "C:\Users\aasme\Documents\git\uavcan\libcanard\dsdl_compiler\libcanard_dsdl_compiler\__init__.py", line 114, in run_parser
    die(ex)
  File "C:\Users\aasme\Documents\git\uavcan\libcanard\dsdl_compiler\libcanard_dsdl_compiler\__init__.py", line 107, in die
    raise DsdlCompilerException(str(text))
libcanard_dsdl_compiler.DsdlCompilerException: dsdl\uavcan\CoarseOrientation.uavcan: Internal error: dsdl\uavcan\CoarseOrientation.uavcan: Invalid namespace name []
dsdl\uavcan\CoarseOrientation.uavcan: Internal error: dsdl\uavcan\CoarseOrientation.uavcan: Invalid namespace name []

The reason for this is that the search paths are splitted at the os separators in locate_namespace_directory, and that the last part therefore is empty. This can be fixed by explicitly removing any os separators at the end of the source paths. This can e.g be done in validate_search_directories() in pyuavcan.dsdl.Parser by changing it from

def validate_search_directories(dirnames):
    dirnames = set(dirnames)
    dirnames = list(map(os.path.abspath, dirnames))
    for d1 in dirnames:
        for d2 in dirnames:
            if d1 == d2:
                continue
            enforce(not d1.startswith(d2), 'Nested search directories are not allowed [%s] [%s]', d1, d2)
            enforce(d1.split(os.path.sep)[-1] != d2.split(os.path.sep)[-1],
                    'Namespace roots must be unique [%s] [%s]', d1, d2)
    return dirnames

to e.g

def validate_search_directories(dirnames):
    dirnames = set(dirnames)
    dirnames = list(map(os.path.abspath, dirnames))
    dirnames = list(map(lambda dir: dir.strip(os.sep), dirnames))
    for d1 in dirnames:
        for d2 in dirnames:
            if d1 == d2:
                continue
            enforce(not d1.startswith(d2), 'Nested search directories are not allowed [%s] [%s]', d1, d2)
            enforce(d1.split(os.path.sep)[-1] != d2.split(os.path.sep)[-1],
                    'Namespace roots must be unique [%s] [%s]', d1, d2)
    return dirnames

Missing support for DSDL generator for libcanard

Missing support for DSDL generator for libcanard

This would be useful because:

  • Easier way to use UAVCAN with libcanard
  • UAVCAN messages packed and un-packed systematic way
  • Allows UAVCAN usage with MCU's having smaller flash & memory size
  • ANSI C code library
  • Makes possible to write cross test generator between uavcan & libcanard pack and unpack functions

PR: coming in soon in near future

suggestions III

Hey Pavel
I'm relentless, I know ... some more suggestions

In canard.h I found it useful to change the CanardCANFrame structure to

#if CANARD_CAN_FRAME_MAX_DATA_LEN!=8
#  error CANARD_CAN_FRAME_MAX_DATA_LEN must be set to 8
#endif
typedef struct
{
    uint32_t id;
    union{
      uint8_t data[CANARD_CAN_FRAME_MAX_DATA_LEN];
      uint16_t data16[CANARD_CAN_FRAME_MAX_DATA_LEN/2];
      uint32_t data32[CANARD_CAN_FRAME_MAX_DATA_LEN/4];
      uint64_t data64[CANARD_CAN_FRAME_MAX_DATA_LEN/8];
    };
    uint8_t data_len;
} CanardCANFrame;

This also allows some code in the stm32 drivers to be cleaned up significantly. I've made a couple of changes in the stm32 driver. You can download my files here: www.olliw.eu/drop/canard_stm32_4pavel_20170410.zip. With a comparison/merge program, like WinMerge, it is very easy to see the changes:

  • renamed _internals_bxcan.h to canard_stm32_internals_bxcan.h
  • in struct CanardSTM32CANType; made RF0R,RF1R to RFxR,[2] similar as for other fields
  • added support for the iface mode CanardSTM32IfaceModeLoopBack (which I found very useful to get start with)
  • mailbox code in canardSTM32Transmit() and canardSTM32Receive() significantly cleaned up
  • in some places changed int etc to uint_t etc., and used 16-bit were it deemed appropriate to me

In canard.c allocateBlock() there should be probably an CANARD_ASSERT() to check that the available space is sufficient, i.e. something like allocator->statistics.current_usage_blocksstatistics.capacity_blocks, similar to the check in freeBlock(), but I was not totally sure what would be correct, hence just this comment.

Cheers, Olli

DSDL compiler: incorrect array serialization

A bug in the updated DSDL compiler has been found:

uavcan/equipment/actuator/actuator_ArrayCommand.c: In function ‘uavcan_equipment_actuator_ArrayCommand_encode_internal’:

uavcan/equipment/actuator/actuator_ArrayCommand.c:41:93: error: subscripted value is neither array nor pointer nor vector
offset += uavcan_equipment_actuator_Command_encode_internal((void*)&source->commands[c], msg_buf, offset, 0);

commands[c] is wrong ,that is commands.data[c] is right.

@aasmune could you look into this please?

Error in generated code (casting to void *)

In code generated by:

python3 libcanard_dsdlc --header_only --outdir <outdir> <dsdl-definition-uavcan-folder>

In GetTransportStats I get the following compile error:

/home/ton/Copter/MicroAvia/MicroAviaFramework/uavcan/generated/uavcan/protocol/GetTransportStats.h: In function 'uint32_t uavcan_protocol_GetTransportStatsResponse_encode_internal(uavcan_protocol_GetTransportStatsResponse*, void*, uint32_t, uint8_t)':
/home/ton/Copter/MicroAvia/MicroAviaFramework/uavcan/generated/uavcan/protocol/GetTransportStats.h:200:65: error: invalid conversion from 'void*' to 'uavcan_protocol_CANIfaceStats*' [-fpermissive]
         offset += uavcan_protocol_CANIfaceStats_encode_internal((void*)&source->can_iface_stats.data[c], msg_buf, offset, 0);
                                                                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /home/ton/Copter/MicroAvia/MicroAviaFramework/uavcan/generated/uavcan/protocol/GetTransportStats.h:20:0,
                 from /home/ton/Copter/MicroAvia/MicroAviaFramework/src/platforms/chibios/microavia/drivers/uavcan/UAVCANESC.cpp:7:
/home/ton/Copter/MicroAvia/MicroAviaFramework/uavcan/generated/uavcan/protocol/CANIfaceStats.h:98:10: note:   initializing argument 1 of 'uint32_t uavcan_protocol_CANIfaceStats_encode_internal(uavcan_protocol_CANIfaceStats*, void*, uint32_t, uint8_t)'
 uint32_t uavcan_protocol_CANIfaceStats_encode_internal(uavcan_protocol_CANIfaceStats* source,
          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

After fixing by hands it compiles, but gives wrong data in can_iface_stats, maybe is related problem.
Fixed this way:

-        offset += uavcan_protocol_CANIfaceStats_encode_internal((void*)&source->can_iface_stats.data[c], msg_buf, offset, 0);
+        offset += uavcan_protocol_CANIfaceStats_encode_internal(&source->can_iface_stats.data[c], msg_buf, offset, 0);
        offset += uavcan_protocol_CANIfaceStats_decode_internal(transfer,
                                                0,
-                                               (void*)&dest->can_iface_stats.data[c],
+                                               &dest->can_iface_stats.data[c],
                                                dyn_arr_buf,
                                                offset,
                                                tao);

/usr/include/c++/5/limits:42:28: fatal error: bits/c++config.h: No such file or directory

[ 41%] Building CXX object CMakeFiles/run_tests.dir/stm32/test_can_timings.cpp.o
In file included from /usr/include/gtest/gtest.h:54:0,
from /home/yangang/work/cortex_m7_proj/Bootloader/libcanard/tests/stm32/test_can_timings.cpp:25:
/usr/include/c++/5/limits:42:28: fatal error: bits/c++config.h: No such file or directory
compilation terminated.
CMakeFiles/run_tests.dir/build.make:62: recipe for target 'CMakeFiles/run_tests.dir/stm32/test_can_timings.cpp.o' failed
make[2]: *** [CMakeFiles/run_tests.dir/stm32/test_can_timings.cpp.o] Error 1
CMakeFiles/Makefile2:104: recipe for target 'CMakeFiles/run_tests.dir/all' failed
make[1]: *** [CMakeFiles/run_tests.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2

Should we consider switching to a more static architecture for the benefit of high-reliability applications?

The current implementation of the library uses a lot of indirection, which should be minimized in high-reliability settings (see MISRA, AUTOSAR, power of 10). Should we trade-off general utility for robustness?

The two prospects for improvement here are:

  1. Replacement of the instance pointers with a static private instance structure located inside canard.c. The downside is that it will no longer be possible to use more than one instance per application. The upside is the simplification of the API -- one argument will be removed from all API calls.
  2. Replacement of the callback pointers (which are generally dangerous) with statically bound external handlers (extern void canardOnTransferReception(CanardRxTransfer* transfer); instead of the dynamic callback pointer). Same downside.

The removal of the indirection will also reduce resource usage, which is important in the applications targeted by Libcanard. Also, removal of callbacks will improve its API compatibility with fully synchronous applications (e.g., sampling & queuing ports instead of asynchronous callbacks, see ARINC 653).

Porting Example???

Добрый день Павел,

У вас так и не появилось руководство как портировать код на другие платформы?
Какие функции и структуры нужно реализовать? Какую утилиту нужно использовать для преобразования словаря в ".c" и ".h"
Спасибо за совет.

Андрей.

https://github.com/karu2003/MotorWare_eCAN

Adding new constants for length of arrays in the DSDL compiler

Hi,
I am currently testing out the new DSDL compiler for Libcanard for use in a project which will be using UAVCAN. With the current DSDL serialization, constants are defined for the max size of all structs, but no constants are generated for the max size of single fields in a structure (arrays). The sizes are only added as a comment in the header file. For use in the application, it would be nice to have the size both of static arrays, and the max size of dynamic arrays defined.

Take HardwareVersion as an example:

Current version (Generated using the DSDL compiler)

// HardwareVersion.h
...

#define UAVCAN_PROTOCOL_HARDWAREVERSION_NAME               "uavcan.protocol.HardwareVersion"
#define UAVCAN_PROTOCOL_HARDWAREVERSION_SIGNATURE          (0xAD5C4C933F4A0C4ULL)

#define UAVCAN_PROTOCOL_HARDWAREVERSION_MAX_SIZE           ((2192 + 7)/8)

// Constants

typedef struct
{
    // FieldTypes
    uint8_t    major;                         // bit len 8
    uint8_t    minor;                         // bit len 8
    uint8_t    unique_id[16];                 // Static Array 8bit[16] max items
    struct
    {
        uint8_t    certificate_of_authenticity_len; // Dynamic array length
        uint8_t*   certificate_of_authenticity; // Dynamic Array 8bit[255] max items
    };

} uavcan_protocol_HardwareVersion;

....

New version with added constants for max size of arrays

// HardwareVersion.h
...

#define UAVCAN_PROTOCOL_HARDWAREVERSION_NAME               "uavcan.protocol.HardwareVersion"
#define UAVCAN_PROTOCOL_HARDWAREVERSION_SIGNATURE          (0xAD5C4C933F4A0C4ULL)

#define UAVCAN_PROTOCOL_HARDWAREVERSION_MAX_SIZE           ((2192 + 7)/8)

// Constants
#define UAVCAN_PROTOCOL_HARDWAREVERSION_UNIQUE_ID_LENGTH                            16
#define UAVCAN_PROTOCOL_HARDWAREVERSION_CERTIFICATE_OF_AUTHENTICITY_MAX_LENGTH      255

typedef struct
{
    // FieldTypes
    uint8_t    major;                         // bit len 8
    uint8_t    minor;                         // bit len 8
    uint8_t    unique_id[16];                 // Static Array 8bit[16] max items
    struct
    {
        uint8_t    certificate_of_authenticity_len; // Dynamic array length
        uint8_t*   certificate_of_authenticity; // Dynamic Array 8bit[255] max items
    };

} uavcan_protocol_HardwareVersion;

...

By adding these new constants, it will become easier for the user as they don't have to remember the max length of all arrays but can use predefined constants.

Missing constants in generated C files from DSDL

I have noticed that the generated C file doesn't contain any constants if the source DSDL file consists only of constants, without any other fields.

E.g. the following file will be created as Foo.1.0_no_constants.txt (converted from .h to .txt to be able to upload to Github and renamed)

uint8 BAR = 123

However, the following file will be created as Foo.1.0_with_constant.txt

uint8 BAR = 123
uint8 placeholder

I haven't looked deeply on the output from pydsdl during parsing, but is this expected behavior, or a bug? It should also be mentioned that this is with an "old" version of pydsdl (before v0.4)
@pavel-kirienko

Rename API entities to enhance compliance with the spec

  • canardEncodeScalar --> canardEncodePrimitive
  • canardDecodeScalar --> canardDecodePrimitive
  • CanardTransferTypeResponse --> CanardTransferTypeServiceResponse
  • CanardTransferTypeRequest --> CanardTransferTypeServiceRequest
  • CanardTransferTypeBroadcast --> CanardTransferTypeMessagePublication
  • canardBroadcast --> canardPublishMessage

Use a separate header file for assert macros

Hello,

I need to override the CANARD_ASSERT macro in a project in which I included Libcanard as a Git submodule. I don't want to make a separate copy of canard.h just to override this macro.
A convenient solution to this problem is to have a separate canard_assert.h header for the user to provide alternative macro definitions. This header would be included by canard.h. A default implementation would be provided, and the user could use a custom one if he/she wished to provide an alternative definition of the macros.

What do you think?

Best regards,
Adolfo

Include paths in generated sources contain backslashes

The source files which are generated by the dsdl compiler contain include paths with backslashes. This is a platform specific thing, but in general, we can always use forward slashes for include paths.

Problem is the function type_output_filename which uses forward slashes or backslashes depending on os. This is a problem if the generated files are generated in windows, then checked in into git, then compiled on linux. linux only supports forward slashes as path seperator. Windows supports both forward and backward slashes.

Remove TAO

The TAO (tail array optimization) logic needs to be removed.
See #106

DSDL compiler shall use a newer version of PyDSDL

When trying to compile the latest public_regulated_data_types using the dsdl_compiler in the uavcan-v1.0 branch (for both the data_types and libcanard) it will fail building with the following error:

pydsdl.regular_grammar_matcher.InvalidGrammarError: Invalid grammar: IOStatistics.0.1[<=MAX_PHYSICAL_INTERFACES] physical_interface_statistics

Compilation on 64 bit platforms fails

I tried to build an application with libcanard with a 64 bits compiler. Doing so will trigger static asserts, which is good, but is there any reason why we cannot use it on 64 bit? And, would it be possible to modify libcanard such that is can be compiled on 64 and 32 bit platforms?

Pack Structures

Structure padding on different compilers can result in CanardRxState being too large. May need to pack them in a portable way.

Inconsistency between design documentation and generated C definition for dynamic arrays

Reading through the design documentation of Libcanard, I see that the corresponding C definition of a dynamic array should be an array with the maximum number of elements which is allowed in the dynamic array. E.g Foo[<5] bars in DSDL should become Foo bars[4]; in C.

As of now, dynamic arrays are created as pointers, not as arrays. Is this the desired behavior, or should the pointers be replaced with the definition stated in the design documentation?

Unnamed structs gives error when compiling with -std=c99

When compiling using -std=c99 I get the following error related to how the structs for dynamic arrays are generated in the header files:

$ cmake . && make
running cd "/home/aasmune/Documents/git/UAVCAN-examples" && /usr/bin/python3 lib/libcanard/dsdl_compiler/libcanard_dsdlc --outdir dsdl lib/dsdl/uavcan/  2>&1
-- Configuring done
-- Generating done
-- Build files have been written to: /home/aasmune/Documents/git/UAVCAN-examples
Scanning dependencies of target example
[  1%] Building C object CMakeFiles/example.dir/src/example.c.o
In file included from /home/aasmune/Documents/git/UAVCAN-examples/dsdl/uavcan/protocol/GetNodeInfo.h:20:0,
                 from /home/aasmune/Documents/git/UAVCAN-examples/src/example.c:23:
/home/aasmune/Documents/git/UAVCAN-examples/dsdl/uavcan/protocol/HardwareVersion.h:71:6: error: ISO C99 doesn’t support unnamed structs/unions [-Werror=pedantic]
     };
      ^
In file included from /home/aasmune/Documents/git/UAVCAN-examples/src/example.c:23:0:
/home/aasmune/Documents/git/UAVCAN-examples/dsdl/uavcan/protocol/GetNodeInfo.h:99:6: error: ISO C99 doesn’t support unnamed structs/unions [-Werror=pedantic]
     };
      ^
/home/aasmune/Documents/git/UAVCAN-examples/src/example.c: In function ‘shouldAcceptTransfer’:
/home/aasmune/Documents/git/UAVCAN-examples/src/example.c:202:56: warning: unused parameter ‘ins’ [-Wunused-parameter]
 static bool shouldAcceptTransfer(const CanardInstance* ins,
                                                        ^~~
cc1: all warnings being treated as errors
CMakeFiles/example.dir/build.make:62: recipe for target 'CMakeFiles/example.dir/src/example.c.o' failed
make[2]: *** [CMakeFiles/example.dir/src/example.c.o] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/example.dir/all' failed
make[1]: *** [CMakeFiles/example.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2

The error is due to how dynamic arrays are created:

// GetNodeInfo.h
...

typedef struct
{
    // FieldTypes
    uavcan_protocol_NodeStatus status;                        //
    uavcan_protocol_SoftwareVersion software_version;              //
    uavcan_protocol_HardwareVersion hardware_version;              //
    struct
    {
        uint8_t    name_len;                  // Dynamic array length
        uint8_t*   name;                      // Dynamic Array 8bit[80] max items
    };

} uavcan_protocol_GetNodeInfoResponse;
...

It will compile using -std=c11, but I think it should be fixed as Libcanard uses the Zubax C++ coding conventions which states that C code should be written in standard c99.

Optional Tx queue

The tx queue is a bit of a pain point for carrying out integration - as there is no "push notification" to the queue it must be polled.

I have a branch which makes the TX queue optional via a build flag, CANARD_TX_NO_QUEUE, I wonder if a change like this would be acceptable to the project?

https://github.com/mike7c2/libcanard/tree/optional_tx_queue

I looked at other ways to resolve this and I think adding a "queue no longer empty" style notification could solve the issue - in our specific application though ignoring priority and pushing directly to an RTOS queue is the way we want to go.

Potential Bug in canardSTM32ConfigureAcceptanceFilters() !?

I'm chasing an issue, which I believe might be due to a potential bug in the function canardSTM32ConfigureAcceptanceFilters().

It's in this code part:
https://github.com/UAVCAN/libcanard/blob/master/drivers/stm32/canard_stm32.c#L482-L493

The if looks incorrect to me.
For instance, if in both the id and the mask the EFF flags are not set, corresponding to STD frames, then nevertheless the first branch is executed, and not the second as it would be correct. This effectively prevents STD frames to be used with this filter setter function.

There are some comments in the code, but it is not totally clear that the code is supposed to do. My guess would be that the second branch should be called only when in both the id and the mask the EFF flag is not set, i.e. a STD frame is clearly called, in which case line 482 probably should be

if ((cfg->id & CANARD_CAN_FRAME_EFF) || (cfg->mask & CANARD_CAN_FRAME_EFF))

Tx Buffer in the driver?

@pavel-kirienko Hi, this is more a generell architecture question.

I am wondering why you are added the TX and RX buffers inside the core of libcanard and not in the driver itself. For a similar proprietary can implementation where I also must support different controllers - I am not sure which way I should go.

Before I have looked into this implementation I taught i will use a TX and an RX Buffer inside the driver because I taught this way I could implement the send and receive with better performance and less memory consumption for the different controllers.

The Infineon XMC as an example hast several Buffers which can be combined to queues for TX and RX. Also some NXP controllers have suche features as i know. And for the other targets I could implement the buffers inside the driver - so that was my plan.

But now I am not sure if i should use a 2 stage buffering. ..

So why do you choose that design/architecture?

many thanks
mathias

Some issues with function "canardRequestOrRespond"

int16_t canardRequestOrRespond(CanardInstance* ins,             ///< Library instance
                               uint8_t destination_node_id,     ///< Node ID of the server/client
                               uint64_t data_type_signature,    ///< See above
                               uint8_t data_type_id,            ///< Refer to the specification
                               uint8_t* inout_transfer_id,      ///< Pointer to a persistent variable with transfer ID
                               uint8_t priority,                ///< Refer to definitions CANARD_TRANSFER_PRIORITY_*
                               CanardRequestResponse kind,      ///< Refer to CanardRequestResponse
                               const void* payload,             ///< Transfer payload
                               uint16_t payload_len);           ///< Length of the above, in bytes

Should the "data_type_id" be "uint16_t" not "uint8_t"?
I met some problems with canard library.

I want to use "1100.ArmingStatus.uavcan" with "service" so that I can use it with one button to change the FlightController armed status.

Teensy Drivers instead of AVR

in the Libcanuav GitHub library there is a driver for the Teensy boards (NXP). Can that be used in conjunction with this library?

Update demo application

The demo application should be updated to show usage of V1.0 with new v1.0 subjects/services instead of the old v0.1. It should also possibly show the usage of how to incorporate the DSDL compiler to generate C files to encode/decode messages.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.