Electronic – How to leverage CAN bus Mailboxes in the embedded systems

caninterruptsmicrocontrollerperipheralprogramming

I don't understand how to leverage CAN bus Mailboxes in my embedded systems.
I think I don't use them properly because I don't understand the problem they are trying to solve.

Here's a simple example to illustrate my conundrum:

Requirements and assumptions

  • Transmit 10 different CAN messages with a period of 250ms.
  • Receive 10 different CAN messages with a period of 250ms.

Let's assume we can only use 1 CAN peripheral.
Let's assume the CAN bus has only those messages on it.
Let's assume we have more than 20 mailboxes.

Solution

To my understanding, to solve this problem, I could do

  • 1 mailbox for receiving (with a filter accepting all 10 CAN message's ID)
  • 1 mailbox for transmitting

I could also do

  • 10 mailbox for receiving; each mailbox only 1 message ID
  • 10 mailbox for transmitting; each mailbox only 1 message ID

or, of course, an in-between solution.

How can I evaluate what is the proper solution for my design?

As CAN bus can only receive 1 message at the time, why use multiple RX mailboxes? Is it to act as buffers you can pole, instead of using interrupts?

Why use multiple mailboxes to receive messages?

Why use multiple mailboxes to send messages?

Do you have examples of the kind of problems CAN mailboxes help to solves?

Thanks

Best Answer

Indeed, I don't think you are understanding the problem that mailboxes are trying to solve. An "old school" CAN controller only has FIFO buffers: one Rx FIFO and (at best) one Tx FIFO. Where the Tx "FIFO" may be as low level as "you get one data register to write to and meanwhile we use another register for shifting out the data". And the Rx FIFO might be restricted to just a few messages.

If you have a whole lot of different CAN identifiers on the bus and requirements saying that you should act each time you receive one particular identifier, then your receiver must be fast enough to always go through the Rx FIFO and process the messages before it hits the FIFO limit and you get overruns with data loss. That's pretty tough real-time requirements, down to microseconds depending on baudrate.

A CAN controller with the mailbox feature allows you to have that one particular message you are interested in ending up in its own private mailbox upon arrival, instead of going through the FIFO. You can then grab it when you need it, and buffer overrun might not even be an issue, because when that happens, it only means that you have gotten the latest data of the kind you are interested in.

Similarly when sending, you don't have to poll some flag to see when the Tx buffer is free - the hardware will grab the message from the mailbox when it got time to send it next. (Hopefully based on lowest CAN id = highest prio if the controller is any good, but some fishy CAN controllers have other oddball scheduling based on separate priority registers, as if the hardware designers failed to understand the whole idea with CAN message arbitration.)

This also means that you might be able to skip acceptance filters entirely - they are always a pain in the neck to get right and should be avoided when possible. They aren't particularly helpful either, when there is a whole lot of possible valid messages out there (think CANopen etc).


Regarding your specific example, 250ms intervals is an eternity, so it would be quite easy to implement a FIFO-based application for that. Even the slowest MCU on the market would have no problem keeping up either with polling or interrupt-based reception. So for that easy scenario, mailboxes would perhaps just add pointless complexity.

A more relevant example would be something like: there are 100 different messages possible on the bus. Every 10ms, a subset of these 100 are sent to all nodes, at 1Mbps. You are only interested in listening to messages 0x100, 0x200 and 0x300. Instead of coming up with some obscure acceptance masking scheme, or polling the Rx FIFO at mad pace, discarding almost everything you find, you could just set up 3 mailboxes for the messages you are interested in, then grab them when your program has time.

More sophisticated systems combine mailboxes with Rx FIFO as a defensive safety feature. For example I've designed systems where high integrity data (such as motion control commands) always uses mailboxes, while low priority data (such as error messages and diagnostics) uses the Rx FIFO. Suppose your program is only designed to work at the expected bus load of up to some 20-30% and you'll be able to poll the Rx FIFO at that pace. Then suddenly some node runs amok for an unexpected reason (a firmware bug) and starts sending out valid messages at 100% bus load. With the mailbox, you'd still be able to receive the important messages even if your Rx FIFO decoding isn't designed to keep up.