Skip to content

Commit

Permalink
[stm32] Default FDCAN to FIFO mode instead of Queue Mode
Browse files Browse the repository at this point in the history
Queue Mode will send CAN frames in priority order according to their
arbitration ID. This is inconsistent with modm's software-managed queue
which is a strict FIFO. To make the behavior of the driver consistent
with an end-to-end FIFO order, we disable Queue Mode by default.

There is a new lbuild option, "tx_hw_queue_mode", which allows the user
to opt back into the old behavior if desired. This is mostly intended
for if they also set "buffer.tx" to zero and optionally increase
"message_ram.tx_fifo_elements".

Note that the fdcan unit test was implicitly assuming FIFO order. This
change also fixes that test for larger HW TX buffer sizes.
  • Loading branch information
WasabiFan committed Sep 17, 2024
1 parent 0716187 commit 69174c4
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 3 deletions.
2 changes: 2 additions & 0 deletions src/modm/platform/can/stm32-fdcan/can.cpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -256,8 +256,10 @@ modm::platform::Fdcan{{ id }}::initializeWithPrescaler(
{{ reg }}->RXGFC |= (MessageRam::Config.filterCountStandard << FDCAN_RXGFC_LSS_Pos) | (MessageRam::Config.filterCountExtended << FDCAN_RXGFC_LSE_Pos);
%%endif

%% if options["tx_hw_queue_mode"] == "Priority"
// Tx buffer: queue mode
{{ reg }}->TXBC |= FDCAN_TXBC_TFQM;
%% endif

// Enable bit rate switching and CANFD frame format
if(fdDataTimings) {
Expand Down
10 changes: 7 additions & 3 deletions src/modm/platform/can/stm32-fdcan/can.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ namespace modm::platform
* FDCAN instances.
*
* This driver supports SW-managed/in-memory FIFOs which augment the hardware TX
* and RX FIFOs. Note that the HW TX queue is set to "queue mode" (not "FIFO mode").
* This means CAN messages are popped from the in-memory FIFO in order of addition
* but arbitrated according to ID priority within the HW queue.
* and RX FIFOs. Note that the HW TX queue defaults to FIFO order but can be
* configured to transmit the highest priority (lowest arbitration ID) frames
* first.
*
* ## Filter
%% if target["family"] == "h7"
Expand All @@ -59,6 +59,10 @@ namespace modm::platform
* `buffer.rx` parameters. If set to 0, filling a HW FIFO will immediately drop
* frames.
*
* The `tx_hw_queue_mode` configures the order in which frames are transmitted
* from the hardware buffers. "FIFO" transmits in the order frames were enqueued.
* "Priority" transmits the message with the lowest arbitration ID first.
*
%% if target["family"] == "h7"
* You can configure the message RAM space allocation as follows:
* - `message_ram.standard_filter_count`: Maximum number of standard (11-bit ID) acceptance filters
Expand Down
16 changes: 16 additions & 0 deletions src/modm/platform/can/stm32-fdcan/module.lb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@ from collections import defaultdict

global_properties = {}

tx_hw_queue_mode_description = """
Controls the order in which frames are popped from the hardware TX queue (see
message_ram.tx_fifo_elements). Does not affect the optional software buffer
(buffer.tx), which is always popped in FIFO order.
FIFO: transmit frames in the order they were enqueued.
Priority: transmit the frame with the lowest arbitration ID first.
"""

def load_options(module, options):
module.add_option(
NumericOption(
Expand All @@ -31,6 +40,13 @@ def load_options(module, options):
minimum=0, maximum="64Ki-2",
default=32))

module.add_option(
EnumerationOption(
name="tx_hw_queue_mode",
description=tx_hw_queue_mode_description,
default="FIFO",
enumeration=["FIFO", "Priority"]))

supports_configurable_message_ram = options[":target"].identifier.family == "h7"

if supports_configurable_message_ram:
Expand Down

0 comments on commit 69174c4

Please sign in to comment.