What does this code to do at canardRxAccept in canard.c
while ((sub != NULL) && (sub->_port_id != model.port_id))
{
sub = sub->_next;
}
What does this code to do at canardRxAccept in canard.c
while ((sub != NULL) && (sub->_port_id != model.port_id))
{
sub = sub->_next;
}
Thank you very,very, very much!
// There are two possible reasons why the session may not exist: 1. OOM; 2. SOT-miss.
if (subscription->_sessions[frame->source_node_id] != NULL)
{
CANARD_ASSERT(out == 0);
out = rxSessionUpdate(ins,
subscription->_sessions[frame->source_node_id],
frame,
redundant_transport_index,
subscription->_transfer_id_timeout_usec,
subscription->_payload_size_max,
out_transfer);
}
What does “SOT-miss.” mean?
Start of transfer?
out->payload_size = frame->payload_size- 1U; // Cut off the tail byte.
I found that this line of code caused me to miss one byte of data that I received. Could you please give me some guidance?
You don’t need this byte because it contains the transport metadata that is consumed by the library.
When I continuously send the heartbeat node and the custom node information, after being processed by canardRxAccept, I can only receive each node once, from which canardRxAccept will not return 1. Why?
Is it because it’s the first frame of a transfer?
And. When i send 8 bytes,canardRxAccept return 0 , how to send multi frame ?
Re first question: you probably forgot to make the transfer-ID variable static. If that’s the case, then you’re sending multiple transfers under the same transfer-ID, which are then rejected by the receiving node as duplicates.
Re second question: sending a multi-frame transfer is no different from sending a single-frame transfer.
I’m confused about tranfer-ID.
I made "static uint8_t my_message_transfer_id;"And “+ + my_message_transfer_id;”
However, when I sent the transfer-ID, I did not send it to the receiver, but only transmitted the data(.payload) to the receiver. So how to set the tail byte of the data I sent?
uint8_t my_msg[10] = {0};
canardDSDLSetUxx(&my_msg[0], 0, 10, 8);
canardDSDLSetUxx(&my_msg[0], 8, 110, 8);
canardDSDLSetUxx(&my_msg[0], 16, 120, 8);
canardDSDLSetUxx(&my_msg[0], 24, 87, 8);
canardDSDLSetUxx(&my_msg[0], 32, 12, 8);
canardDSDLSetUxx(&my_msg[0], 40, 99, 8);
canardDSDLSetUxx(&my_msg[0], 48, 0xDEADAA, 24);
// ----------------------------------- how to set the tail byte ---------------------------------------------------------------------------------
canardDSDLSetUxx(&my_msg[0], 72, ?????, 8); // how to set the tail byte ?
static uint8_t mymsg_transfer_id;
const CanardTransfer mytransfer = {
.timestamp_usec = 0,
.priority = CanardPriorityNominal,
.transfer_kind = CanardTransferKindMessage,
.port_id = 32080, // 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 = 10,
.payload = &my_msg[0],
};
++mymsg_transfer_id;
int32_t myresult = canardTxPush(&ins, &mytransfer);
……………………(omit)
uint8_t fail_count;
FDCAN_TxHeaderTypeDef *txmsg = NULL;
for (const CanardFrame* txf = NULL; (txf = canardTxPeek(&ins)) != NULL;) // Look at the top of the TX queue.
{
printf("enter txmsg:\n");
uint8_t sendbuf[64] = {0};
txmsg->Identifier = txf->extended_can_id; //32085txf->extended_can_id
txmsg->DataLength = (txf->payload_size-1) << 16 & 0x000F0000U; //to set the stm32 FDCAN_TxHeaderTypeDef
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-1));
//-------------use stm32 fdcan send to the receiver ,only send buf, do not send transfer-id to receiver------------------------------
HAL_StatusTypeDef ret = HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, txmsg, sendbuf);
HAL_FDCAN_Start(&hfdcan1); /
Replace this:
txmsg->DataLength = (txf->payload_size-1) << 16 & 0x000F0000U;
With this:
txmsg->DataLength = convertDataLengthToFDCANDLC(txf->payload_size);
Where convertDataLengthToFDCANDLC
is defined as:
uint32_t convertDataLengthToFDCANDLC(const size_t length)
{
static const uint32_t Lookup[65] = { // TODO Please carefully check these.
// 0-8
FDCAN_DLC_BYTES_0,
FDCAN_DLC_BYTES_1,
FDCAN_DLC_BYTES_2,
FDCAN_DLC_BYTES_3,
FDCAN_DLC_BYTES_4,
FDCAN_DLC_BYTES_5,
FDCAN_DLC_BYTES_6,
FDCAN_DLC_BYTES_7,
FDCAN_DLC_BYTES_8,
// 9-12
FDCAN_DLC_BYTES_12,
FDCAN_DLC_BYTES_12,
FDCAN_DLC_BYTES_12,
FDCAN_DLC_BYTES_12,
// 13-16
FDCAN_DLC_BYTES_16,
FDCAN_DLC_BYTES_16,
FDCAN_DLC_BYTES_16,
FDCAN_DLC_BYTES_16,
// 17-20
FDCAN_DLC_BYTES_20,
FDCAN_DLC_BYTES_20,
FDCAN_DLC_BYTES_20,
FDCAN_DLC_BYTES_20,
// 21-24
FDCAN_DLC_BYTES_24,
FDCAN_DLC_BYTES_24,
FDCAN_DLC_BYTES_24,
FDCAN_DLC_BYTES_24,
// 25-32
FDCAN_DLC_BYTES_32,
FDCAN_DLC_BYTES_32,
FDCAN_DLC_BYTES_32,
FDCAN_DLC_BYTES_32,
FDCAN_DLC_BYTES_32,
FDCAN_DLC_BYTES_32,
FDCAN_DLC_BYTES_32,
FDCAN_DLC_BYTES_32,
// 33-48
FDCAN_DLC_BYTES_48,
FDCAN_DLC_BYTES_48,
FDCAN_DLC_BYTES_48,
FDCAN_DLC_BYTES_48,
FDCAN_DLC_BYTES_48,
FDCAN_DLC_BYTES_48,
FDCAN_DLC_BYTES_48,
FDCAN_DLC_BYTES_48,
FDCAN_DLC_BYTES_48,
FDCAN_DLC_BYTES_48,
FDCAN_DLC_BYTES_48,
FDCAN_DLC_BYTES_48,
FDCAN_DLC_BYTES_48,
FDCAN_DLC_BYTES_48,
FDCAN_DLC_BYTES_48,
FDCAN_DLC_BYTES_48,
// 49-64
FDCAN_DLC_BYTES_64,
FDCAN_DLC_BYTES_64,
FDCAN_DLC_BYTES_64,
FDCAN_DLC_BYTES_64,
FDCAN_DLC_BYTES_64,
FDCAN_DLC_BYTES_64,
FDCAN_DLC_BYTES_64,
FDCAN_DLC_BYTES_64,
FDCAN_DLC_BYTES_64,
FDCAN_DLC_BYTES_64,
FDCAN_DLC_BYTES_64,
FDCAN_DLC_BYTES_64,
FDCAN_DLC_BYTES_64,
FDCAN_DLC_BYTES_64,
FDCAN_DLC_BYTES_64,
FDCAN_DLC_BYTES_64,
};
// TODO Check the array bounds.
return Lookup[length];
}
You are not supposed to do anything with the tail byte yourself. The library does it automatically, just let it do its job.
Note that I did not test any of this.
Does that mean I can just write my data?Don’t I have to deliberately modify the last byte in the data?
uint8_t my_msg[10] = {0};
canardDSDLSetUxx(&my_msg[0], 0, 10, 8);
canardDSDLSetUxx(&my_msg[0], 8, 110, 8);
canardDSDLSetUxx(&my_msg[0], 16, 120, 8);
canardDSDLSetUxx(&my_msg[0], 24, 87, 8);
canardDSDLSetUxx(&my_msg[0], 32, 12, 8);
canardDSDLSetUxx(&my_msg[0], 40, 99, 8);
canardDSDLSetUxx(&my_msg[0], 48, 0xDEADAA, 24);
// ----------------------------------- how to set the tail byte ---------------------------------------------------------------------------------
canardDSDLSetUxx(&my_msg[0], 72, ?????, 8); // how to set the tail byte ?
Of course, that’s what the library is for.
But i found i do that , i can not receive anything .
When i send single frame, make the last data “0xff” , i can receive once . If do not do that ,i can not receive anything.
uint8_t my_msg[4] = {0};
canardDSDLSetUxx(&my_msg[0], 0, 10, 8); // msg1
canardDSDLSetUxx(&my_msg[0], 8, 110, 8); // msg2
canardDSDLSetUxx(&my_msg[0], 16, 120, 8); // msg1
canardDSDLSetUxx(&my_msg[0], 24, 0xff, 8); // msg2
This is because you are truncating the tail byte in your txmsg->DataLength = (txf->payload_size-1) << 16 & 0x000F0000U;
.
OK, thank you very much. I try it again.
When i receive data , the receive data length is set to "received_frame.payload_size = RxHeader.DataLength >> 16 ;
If the data i send is 10 bytes , it can not receive anything. How can i set the received_frame.payload_size correctly?
Thanks.
FDCAN_RxHeaderTypeDef RxHeader={0};
uint8_t recdata[64] = {0};
uint8_t payload_recdata[64] = {0};
CanardFrame received_frame = {0};
received_frame.payload = &payload_recdata;
if(HAL_FDCAN_GetRxMessage(&hfdcan1, FDCAN_RX_FIFO0, &RxHeader, recdata) == HAL_OK)
{
CanardTransfer receive={0};
received_frame.extended_can_id = RxHeader.Identifier ;
received_frame.payload_size = RxHeader.DataLength ;
memcpy(payload_recdata,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)
{
uint8_t final_data[64] = {0};
memcpy( final_data,receive.payload,receive.payload_size);
uint8_t mode = canardDSDLGetU8(final_data, receive.payload_size, 34, 3);
uint32_t uptime = canardDSDLGetU32(final_data, receive.payload_size, 0, 32);
uint32_t vssc = canardDSDLGetU32(final_data, receive.payload_size, 37, 19);
uint8_t health = canardDSDLGetU8(final_data, receive.payload_size, 32, 2);
printf("mode = %d\n",mode);
printf("health = %d\n",health);
printf("uptime = 0x%x\n",uptime);
printf("vssc = 0x%x\n",vssc);
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");
}