Libcanard and DSDL on Teensy4.1

Hello Everyone

I am working on Teensy 4.1 trying to send and receive UAVCAN packets, I use Libcanard, and referring to the documentation in GitHub - OpenCyphal/libcanard: A compact implementation of the Cyphal/CAN protocol in C for high-integrity real-time embedded systems I could generate can frames, actually I am still new with this protocol and I have some doubts regarding the output frames, as mentioned in the documentation the first two bytes of the first frame generated supposed to be the CRC but I do not see that, I am using canardTxPush, canardTxPeek, and canardTxPop to parse the packet and split it (if needed) to a set of frames.
Hint: I am using the “malloc()” and the “free()” functions to allocate and deallocate the memory because the o1heap library does not work on Teensy and I do not know why.
I print the input and output of my program as the following:

program start...
Input packet:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 
number of frames enqueued: 4

Generated frames>>>>
0 1 2 3 4 5 6 160 
7 8 9 10 11 12 13 0 
14 15 16 17 18 19 20 32 
221 10 64 134 169 14 0 0  
program finish......

the following is the simple code I use:


#include <Arduino.h>
#include <FlexCAN_T4.h>
#include "LIBCAN.h"

FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_16> can1;

CAN_message_t can_msg;

static void* my_all;
static void* mal(CanardInstance* const canard, const size_t amount){
  my_all = (void*)malloc(amount);
  return my_all;
}
static void fre(CanardInstance* const canard, void* const pointer){
  free(pointer);
}

void setup()
{
  Serial.begin(9600);
  can1.begin();
  Serial.println("program start...");

  CanardInstance canard2 = canardInit(&mal, &fre);
  canard2.node_id = 42; 
  CanardTxQueue queue = canardTxInit(10, CANARD_MTU_CAN_CLASSIC);
  
  uint64_t addr2 = (uint64_t)canard2.memory_allocate;
  
  static uint8_t my_message_transfer_id;
  
  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,
  };

  uint64_t tx_deadline_usec = 0xEE;

  uint8_t paylo[60];
  Serial.println("Input packet:");
  for(int y=0; y<21; y++){
    paylo[y] = y;
    Serial.print(y);
    Serial.print(" ");
  }
  Serial.println();

  ++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).
                                &canard2,
                                tx_deadline_usec,     // Zero if transmission deadline is not limited.
                                &transfer_metadata,
                                21,                   // Size of the message payload (see Nunavut transpiler).
                                paylo);
  
  if (result < 0)
  {
    Serial.println("Error!!!!!!");
  }

  Serial.print("number of frames enqueued: ");
  Serial.println(result);
  
  const CanardTxQueueItem* data;

  uint8_t* payload_array;

  Serial.println();
  Serial.println("Generated frames>>>>");

  for(int c=0; c<result; c++){
    delay(1000);
    data = canardTxPeek(&queue);
    payload_array = (uint8_t*)data->frame.payload;
    for(int i=0; i<CANARD_MTU_CAN_CLASSIC; i++){
      can_msg.buf[i] = payload_array[i]; 
      Serial.print(payload_array[i], HEX);
      Serial.print(" ");
    }
    Serial.println();
    canard2.memory_free(&canard2, canardTxPop(&queue, data));
  }

  CanardRxSubscription heartbeat_subscription;

}

void loop() 
{
  Serial.println("program finish......");
  while(true);
}

My questions are as the following:

  1. why I can not see the CRC bytes at the beginning of the first frame?
  2. As shown that there are some additional bytes at last frame generated, what do they mean and from where they come?
  3. where can I find the standard DSDL definition and how to use it?

Thanks in advance

The old layout with the CRC at the beginning was used by an experimental version of the protocol, which is now called DroneCAN. Cyphal/CAN appends the CRC at the end of the transfer. See Cyphal vs. DroneCAN.

The additional bytes are the transfer CRC.