mirror of
https://github.com/PX4/PX4-Autopilot.git
synced 2026-05-25 16:56:25 +08:00
uavcan_stm32h7:can driver preserve ordering
Refering to the refernece manual:
Tx queue operation is configured by programming FDCAN_TXBC.TFQM to 1. Messages
stored in the Tx queue are transmitted starting with the message with the lowest message
ID (highest priority). **In case that multiple queue buffers are configured with the same
message ID, the queue buffer with the lowest buffer number is transmitted first**
Tx FIFO operation is configured by programming FDCAN_TXBC.TFQM to 0. Messages
stored in the Tx FIFO are transmitted starting with the message referenced by the get index
FDCAN_TXFQS.TFGI. After each transmission the get index is incremented cyclically until
the Tx FIFO is empty. The Tx FIFO enables transmission of messages with the same
message ID from different Tx buffers in the order these messages have been written to the
Tx FIFO
The issue will be cancelation:
The FDCAN supports transmit cancellation. To cancel a requested transmission from a
dedicated Tx buffer or a Tx queue buffer the Host has to write a 1 to the corresponding bit
position (= number of Tx buffer) of register FDCAN_TXBCR. Transmit cancellation is not
intended for Tx FIFO operation.
But there is nothing preventing it. This seems to indicate it will
work. When a transmission request for the Tx buffer referenced by the get index is canceled, the
get index is incremented to the next Tx buffer with pending transmission request and the Tx
FIFO free level is recalculated. When transmission cancellation is applied to any other Tx
buffer, the get index and the FIFO free level remain unchanged.
This commit is contained in:
committed by
Lorenz Meier
parent
52a29ac6cf
commit
395519ac66
@@ -112,7 +112,7 @@ class CanIface : public uavcan::ICanIface, uavcan::Noncopyable
|
||||
uavcan::uint32_t ExtIdFilterSA;
|
||||
uavcan::uint32_t RxFIFO0SA;
|
||||
uavcan::uint32_t RxFIFO1SA;
|
||||
uavcan::uint32_t TxQueueSA;
|
||||
uavcan::uint32_t TxFIFOSA;
|
||||
} message_ram_;
|
||||
|
||||
enum { NumTxMailboxes = 32 }; // Should match the number of Tx FIFOs available in message RAM
|
||||
|
||||
@@ -405,24 +405,24 @@ uavcan::int16_t CanIface::send(const uavcan::CanFrame &frame, uavcan::MonotonicT
|
||||
* - Frames do not timeout on a properly functioning bus. Since frames do not timeout, the new
|
||||
* frame can only have higher priority, which doesn't break the logic.
|
||||
*
|
||||
* - If high-priority frames are timing out in the TX queue, there's probably a lot of other
|
||||
* - If high-priority frames are timing out in the TX FIFO, there's probably a lot of other
|
||||
* issues to take care of before this one becomes relevant.
|
||||
*
|
||||
* - It takes CPU time. Not just CPU time, but critical section time, which is expensive.
|
||||
*/
|
||||
CriticalSectionLocker lock;
|
||||
|
||||
// First, check if there are any slots available in the queue
|
||||
// First, check if there are any slots available in the FIFO
|
||||
if ((can_->TXFQS & FDCAN_TXFQS_TFQF) > 0) {
|
||||
// Tx FIFO / Queue is full
|
||||
// Tx FIFO is full
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Next, get the next available queue index from the controller
|
||||
// Next, get the next available FIFO index from the controller
|
||||
const uint8_t index = (can_->TXFQS & FDCAN_TXFQS_TFQPI) >> FDCAN_TXFQS_TFQPI_Pos;
|
||||
|
||||
// Now, we can copy the CAN frame to the queue (in message RAM)
|
||||
uint32_t *txbuf = (uint32_t *)(message_ram_.TxQueueSA + (index * FIFO_ELEMENT_SIZE * WORD_LENGTH));
|
||||
// Now, we can copy the CAN frame to the FIFO (in message RAM)
|
||||
uint32_t *txbuf = (uint32_t *)(message_ram_.TxFIFOSA + (index * FIFO_ELEMENT_SIZE * WORD_LENGTH));
|
||||
|
||||
// Copy the ID; special case for standard ID frames
|
||||
if (frame.isExtended()) {
|
||||
@@ -708,10 +708,10 @@ int CanIface::init(const uavcan::uint32_t bitrate, const OperatingMode mode)
|
||||
can_->RXF0C |= n_fifo0 << FDCAN_RXF0C_F0S_Pos;
|
||||
ram_offset += n_fifo0 * FIFO_ELEMENT_SIZE;
|
||||
|
||||
// Set Tx queue size (32 elements max)
|
||||
message_ram_.TxQueueSA = gl_ram_base + ram_offset * WORD_LENGTH;
|
||||
// Set Tx FIFO size (32 elements max)
|
||||
message_ram_.TxFIFOSA = gl_ram_base + ram_offset * WORD_LENGTH;
|
||||
can_->TXBC = 32U << FDCAN_TXBC_TFQS_Pos;
|
||||
can_->TXBC |= FDCAN_TXBC_TFQM; // Queue mode (vs. FIFO)
|
||||
can_->TXBC &= ~FDCAN_TXBC_TFQM; // Use FIFO
|
||||
can_->TXBC |= ram_offset << FDCAN_TXBC_TBSA_Pos;
|
||||
|
||||
/*
|
||||
@@ -882,11 +882,11 @@ bool CanIface::canAcceptNewTxFrame(const uavcan::CanFrame &frame) const
|
||||
{
|
||||
// Check that we even _have_ a Tx FIFO allocated
|
||||
if ((can_->TXBC & FDCAN_TXBC_TFQS) == 0) {
|
||||
// Your queue size is 0, you did something wrong
|
||||
// Your FIFO size is 0, you did something wrong
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the Tx queue is full
|
||||
// Check if the Tx FIFO is full
|
||||
if ((can_->TXFQS & FDCAN_TXFQS_TFQF) == FDCAN_TXFQS_TFQF) {
|
||||
// Sorry, out of room, try back later
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user