Skip to content
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

Update CAN drivers #242

Open
BlakeFreer opened this issue Oct 26, 2024 · 0 comments
Open

Update CAN drivers #242

BlakeFreer opened this issue Oct 26, 2024 · 0 comments
Assignees

Comments

@BlakeFreer
Copy link
Contributor

BlakeFreer commented Oct 26, 2024

Edit see #274


The current CAN peripheral and shared classes have three major drawbacks:

  1. Not interrupt based - messages are not handled upon arrival, rather upon manual request.

  2. Single message capacity at the bus level - old messages are lost and the latest message can be "read" multiple times. This prevents us from using CAN for one-off messages like button signals. Decided to stay with single message capacity as it simplifies the Bus. We will architect our systems to handle messages as they arrive. See discussion CAN Architecture Update #274.

  3. No filtering: the stm32 platform has a hardware CAN message filter which can ignore ranges of message IDs. Without filtering, our ECUs will be bogged down handling unrelated messages. Undecided how this will look, will implement filters later.

In particular, the current implementation freezes an ECU if it does not read all messages which arrive on the STM platform. This manifested in the TMS code freezing, and the root cause was the CAN_IT_RX_FIFO0_MSG_PENDING interrupt being triggered by BMS->FC CAN traffic (unrelated to the TMS). Since the TMS does not need to read these messages, it never called HAL_CAN_GetRxMessage(), so the interrupt continuously triggered preventing the program from continuing.

My initial idea is to enable filtering for ranges of messages (perhaps autogenerated from the DBC if possible) then trigger the HAL_CAN_GetRxMessage() in the CAN_IT_RX_FIFO0_MSG_PENDING interrupt. This will place the incoming message into a queue with all other messages of the same ID. The main program can pop elements from this queue when it wants to "read" that message. Using a queue ensures that no messages are missed, and we can intelligently raise an error if the queue becomes too full (i.e. a message is being sent to us but we aren't handling it). There isn't a great way to raise errors from an interrupt since the function has no caller (can't throw or return an error to anyone else). How would we decide whether to discard the oldest or incoming message? How big would the message queue be? Should it be FIFO or LIFO?

We will use a single message bucket for each RX message. It will always hold the latest message, so the old one will be discarded. This is ideal for measurement messages (like Accumulator Temp) since we only care about the value now. It is not ideal for event messages where the sender expects the receiver to respond to each and every message without dropping any. Instead of overcoming this issue with a queue at the CAN level, the application will decide how to handle it. They may choose to make an app-side queue for this message, or coordinate the nodes such that new events are not sent until the old one is acknowledged.

@BlakeFreer BlakeFreer self-assigned this Oct 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

When branches are created from issues, their pull requests are automatically linked.

1 participant