use libcanard v1
platform: stm32h743 baremetal platforms
runs results: No matching subscription.
void UavcanRun(void)
{
static uint8_t a = 0;
CanardInstance ins = canardInit(&memAllocate, &memFree);
ins.mtu_bytes = CANARD_MTU_CAN_FD; //Defaults to 64 (CAN FD); here we select Classic CAN.
ins.node_id = 42;
a++;
if(a == 1) //subcribe once
{
a++;
CanardRxSubscription heartbeat_subscription;
(void) canardRxSubscribe(&ins, // Subscribe to messages uavcan.node.Heartbeat.
CanardTransferKindMessage,
32085, // The fixed Subject-ID of the Heartbeat message type (see DSDL definition).
7, // The maximum payload size (max DSDL object size) from the DSDL definition.
CANARD_DEFAULT_TRANSFER_ID_TIMEOUT_USEC,
&heartbeat_subscription);
CanardRxSubscription mymsg_subscription;
(void) canardRxSubscribe(&ins, // Subscribe to messages uavcan.node.Heartbeat.
CanardTransferKindMessage,
4416, // The fixed Subject-ID of the Heartbeat message type (see DSDL definition).
2, // The maximum payload size (max DSDL object size) from the DSDL definition.
CANARD_DEFAULT_TRANSFER_ID_TIMEOUT_USEC,
&mymsg_subscription);
}
if(cnt %1000 == 0){ //excute per 1000ms
uint8_t buffer[7] = {0};
canardDSDLSetUxx(&buffer[0], 34, 2, 3); // mode
canardDSDLSetUxx(&buffer[0], 32, 2, 2); // health
canardDSDLSetUxx(&buffer[0], 0, 0xDEADBEEF, 32); // uptime
canardDSDLSetUxx(&buffer[0], 37, 0x7FFFF, 19); // vssc
static uint8_t heartbeat_transfer_id;
const CanardTransfer transfer = {
.timestamp_usec = HAL_GetTick(),
.priority = CanardPriorityNominal,
.transfer_kind = CanardTransferKindMessage,
.port_id = 32085, // This is the subject-ID.
.remote_node_id = CANARD_NODE_ID_UNSET, // Messages cannot be unicast, so use UNSET.
.transfer_id = heartbeat_transfer_id,
.payload_size = 7,
.payload = &buffer[0],
};
++heartbeat_transfer_id;
int32_t result = canardTxPush(&ins, &transfer);
printf("------------------send hearttransfer-------------------------\n");
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.
// abort();
printf("Illegal parameter or Memory Exhausted \n");
// return ;
}
}
if(cnt %200 == 0){//excute per 200ms
uint8_t my_msg[2] = {0};
canardDSDLSetUxx(&my_msg[0], 0, 120, 8);
canardDSDLSetUxx(&my_msg[0], 8, 110, 8);
static uint8_t mymsg_transfer_id;
const CanardTransfer mytransfer = {
.timestamp_usec = HAL_GetTick(),
.priority = CanardPriorityNominal,
.transfer_kind = CanardTransferKindMessage,
.port_id = 4416, // This is the subject-ID.
.remote_node_id = CANARD_NODE_ID_UNSET, // Messages cannot be unicast, so use UNSET.
.transfer_id = mymsg_transfer_id,
.payload_size = 2,
.payload = &my_msg[0],
};
++mymsg_transfer_id;
int32_t myresult = canardTxPush(&ins, &mytransfer);
printf("---------------------send mytransfer------------\n");
if (myresult < 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.
// abort();
printf("Illegal parameter or Memory Exhausted \n");
// return ;
}
}
static uint8_t fail_count;
FDCAN_TxHeaderTypeDef *txmsg = NULL;
uint8_t sendbuf[7] = {0};
for (const CanardFrame* txf = NULL; (txf = canardTxPeek(&ins)) != NULL;) // Look at the top of the TX queue.
{
printf("enter txmsg:\n");
static uint8_t i = 0;
txmsg->Identifier = txf->extended_can_id >> 8 & 0x00ffffU;
txmsg->DataLength = txf->payload_size << 16 & 0x000F0000U;
txmsg->IdType = FDCAN_EXTENDED_ID;
txmsg->FDFormat = FDCAN_FD_CAN;
txmsg->TxFrameType = FDCAN_DATA_FRAME;
txmsg->BitRateSwitch = FDCAN_BRS_OFF;
txmsg->TxEventFifoControl = FDCAN_STORE_TX_EVENTS;
txmsg->ErrorStateIndicator = FDCAN_ESI_ACTIVE;
txmsg->MessageMarker = 0x01;
memcpy(sendbuf,txf->payload,txf->payload_size);
HAL_StatusTypeDef ret = HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, txmsg, sendbuf); //stm32 hal library
HAL_FDCAN_Start(&hfdcan1);
HAL_FDCAN_EnableTxBufferRequest(&hfdcan1, FDCAN_TX_BUFFER0);
if(ret != HAL_OK)
{
// just exit and try again later. If we fail 8 times in a row
// then start discarding to prevent the pool filling up
if (fail_count < 8) {
fail_count++;
printf("send fail,fail_count:%d\n",fail_count);
} else {
canardTxPop(&ins);
printf("fail_count 8 times, exit send\n");
ins.memory_free(&ins, (CanardFrame*)txf); // Deallocate the dynamic memory afterwards.
}
return;
}
else{
canardTxPop(&ins);
fail_count = 0;
ins.memory_free(&ins, (CanardFrame*)txf); // Deallocate the dynamic memory afterwards.
}
}
////////////////////////// //receive serialized datat //////////////////////////
FDCAN_RxHeaderTypeDef RxHeader={0};
uint32_t RxLocation = 0;
uint8_t recdata[8] = {0};
CanardFrame received_frame;
received_frame.payload = &recdata;
if(HAL_FDCAN_GetRxMessage(&hfdcan1, FDCAN_RX_FIFO0, &RxHeader, recdata) == HAL_OK)
{
printf("RxHeader.Identifier = %d\n",RxHeader.Identifier);
CanardTransfer receive={0};
if(RxHeader.Identifier == 32085)
received_frame.payload_size = 7;
else
received_frame.payload_size = 2;
received_frame.extended_can_id = RxHeader.Identifier;
memcpy(received_frame.payload,recdata,received_frame.payload_size);
uint8_t result = canardRxAccept(&ins,
&received_frame, // The CAN frame received from the bus.
0, // If the transport is not redundant, use 0.
&receive);
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.
printf("RxAccept failure\n");
printf("An error has occurred: either an argument is invalid or we've ran out of memory.\n");
abort();
}
else if (result == 1)
{
printf("Receive Port ID :%d\n",receive.port_id);
//processReceivedTransfer(redundant_interface_index, &transfer); // A transfer has been received, process it.
ins.memory_free(&ins, (void*)receive.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.
printf("nothing to do \n");
}
}
Thanks for your reply.I run this code ,i found it return " No matching subscription. " at canardRxAccept.
Is UAVCAN subscribed, sent and received in my code correct?
–>use libcanard v1 ------https://github.com/UAVCAN/libcanard
–>platform: stm32h743 baremetal platforms
–>runs results: No matching subscription.