From 395519ac66d5625626cb06c3233467523be7744e Mon Sep 17 00:00:00 2001 From: David Sidrane Date: Thu, 18 Mar 2021 08:55:58 -0700 Subject: [PATCH] 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. --- .../driver/include/uavcan_stm32h7/can.hpp | 2 +- .../stm32h7/driver/src/uc_stm32h7_can.cpp | 22 +++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/drivers/uavcan/uavcan_drivers/stm32h7/driver/include/uavcan_stm32h7/can.hpp b/src/drivers/uavcan/uavcan_drivers/stm32h7/driver/include/uavcan_stm32h7/can.hpp index 023c642cc3..984245b505 100644 --- a/src/drivers/uavcan/uavcan_drivers/stm32h7/driver/include/uavcan_stm32h7/can.hpp +++ b/src/drivers/uavcan/uavcan_drivers/stm32h7/driver/include/uavcan_stm32h7/can.hpp @@ -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 diff --git a/src/drivers/uavcan/uavcan_drivers/stm32h7/driver/src/uc_stm32h7_can.cpp b/src/drivers/uavcan/uavcan_drivers/stm32h7/driver/src/uc_stm32h7_can.cpp index 06da5292ee..d3a7c25439 100644 --- a/src/drivers/uavcan/uavcan_drivers/stm32h7/driver/src/uc_stm32h7_can.cpp +++ b/src/drivers/uavcan/uavcan_drivers/stm32h7/driver/src/uc_stm32h7_can.cpp @@ -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;