Skip to content

stm32/can: Add support for a software based CAN message buffer. #6963

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

steven-michalske
Copy link

When using a CAN interface with many messages on the bus; the hardware
RX buffers can overflow. This is typically caused by a busy bus, at high
data rates, and permissive CAN filters. Our approach was to add
software FIFO buffers at the c level CAN ISR and drivers. This allowed
for fast reception, bulk python processing, and no dynamic allocations
after init.

In implementing the SW FIFOs two additional keyword arguments were
added to the constructor for HW FIFO configuration.

  • receive_fifo_locked_mode=True
  • transmit_fifo_priority=True
    And two keyword arguments for setting SW buffer sizes to be allocated.
  • sw_fifo_0_size = 0
  • sw_fifo_1_size = 0
    Defaulting to 0 messages for no SW FIFO.

The overall goals were:

  • Mimic the UART buffer initialization.
  • Implement RX buffers at the IRQ level.
  • Not change the python interface to access the data.
    • i.e. The same python calls are used in buffered or unbuffered modes.
  • Design decision was that both CAN FIFOs are either HW or SW per interface.
    • This was due to the desire to keep the ISR simpler.
    • The SW buffers can have different sizes for each CAN FIFO.
    • Each CAN interface may have HW or SW buffers.

Signed-off-by: Steven Michalske smichalske@apple.com

When using a CAN interface with many messages on the bus; the hardware
RX buffers can overflow. This is typically caused by a busy bus, at high
data rates, and permissive CAN filters. Our approach was to add
software FIFO buffers at the c level CAN ISR and drivers. This allowed
for fast reception, bulk python processing, and no dynamic allocations
after init.

In implementing the SW FIFOs two additional keyword arguments were
added to the constructor for HW FIFO configuration.
- receive_fifo_locked_mode=True
- transmit_fifo_priority=True
And two keyword arguments for setting SW buffer sizes to be allocated.
- sw_fifo_0_size = 0
- sw_fifo_1_size = 0
Defaulting to 0 messages for no SW FIFO.

The overall goals were:
- Mimic the UART buffer initialization.
- Implement RX buffers at the IRQ level.
- Not change the python interface to access the data.
    - i.e. The same python calls are used in buffered or unbuffered modes.
- Design decision was that both CAN FIFOs are either HW or SW per interface.
    - This was due to the desire to keep the ISR simpler.
    - The SW buffers can have different sizes for each CAN FIFO.
    - Each CAN interface may have HW or SW buffers.

Signed-off-by: Steven Michalske <smichalske@apple.com>
@steven-michalske steven-michalske marked this pull request as ready for review February 24, 2021 23:36
@steven-michalske
Copy link
Author

This pull request is based on v1.13, and will be updated to the new CAN baudrate updates introduced in v1.14

@projectgus
Copy link
Contributor

projectgus commented Aug 30, 2023

Thanks for submitting this, @steven-michalske! Linking this across to the machine.CAN plan in #12337.

It may be the case that we can implement software buffering in a port-agnostic way. Also the hardware FIFO mode feature additions (RX overwrite vs drop, TX priority) are potentially very useful to expose.

(EDIT: I should have worded this less optimistically, any initial version of machine.CAN probably won't support new features to avoid scope creep. However, having a design that can support these kind of additions is valuable.)

@steven-michalske
Copy link
Author

steven-michalske commented Sep 1, 2023

Hi @projectgus

I would say that going from no SW buffer to having a SW buffer is what was needed to truly support asyncio processing of more than trivial amounts of CAN messages. In terms of our internal testing having no SW buffer would allow 60% of 50 fast messages to be received. When adding a SW buffer of size 50 we could reliably receive 500 message bursts, and with a SW buffer of 200 we could receive 100% of a 50,000 message burst. Arguably these large message bursts take a substantial amount of wall clock time to transmit at 7 seconds; so this explains the capability of the 200 message buffer as it allowed the MCU to keep up with the messages.

In context of other ports SW buffering may not be an improvement, but for the STM32 port and asyncio it was mandatory to have any reasonable amount of bandwidth on the CAN bus. As this lives in the ISR of the STM32 port please consider it even if it is behind a C compile time constant, as it has a huge benefit on the performance of the CAN hardware.

@projectgus
Copy link
Contributor

@steven-michalske Makes sense, thanks for taking the time to relay those stats!

@projectgus
Copy link
Contributor

This is an automated heads-up that we've just merged a Pull Request
that removes the STATIC macro from MicroPython's C API.

See #13763

A search suggests this PR might apply the STATIC macro to some C code. If it
does, then next time you rebase the PR (or merge from master) then you should
please replace all the STATIC keywords with static.

Although this is an automated message, feel free to @-reply to me directly if
you have any questions about this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants