Canbus mailboxes

Is there a good reference somewhere about how the mailboxes work with the canbus? Accessing them, limitations, etc?

Well, as a 30k foot overview, mailboxes have nothing to do with the actual CAN bus itself. They’re a function of the hardware in the M2 not of the CAN bus. I’m saying that just to try to clarify things a bit. Now, the hardware in the M2 has 8 mailboxes per CAN bus. These are basically storage places where a frame that was either received or is being sent can be stored. For transmitting frames on the CAN bus you can put them into a mailbox and they’ll be scheduled to be sent when possible. Each mailbox is set either as a transmission or reception box.

If you want to send things then you need at least one mailbox for transmission but you are allowed to have more. If you have more than one TX mailbox then you can queue up frames and it’ll send the one with the highest priority first. Or you could use two TX mailboxes and it can be sending one while you load the other. But, you really only need one TX mailbox usually.

More important are the reception mailboxes. When a frame is sent on the wire and received at the M2 it will either be accepted or not. In order to accept a frame there must be at least one mailbox that accepts it. Each mailbox set for RX has an associated mask and filter that goes with it. When a frame comes in this is what happens:

  1. The ID of the frame is AND with the mask from the first RX mailbox.
  2. The resulting masked ID is compared to the filter value for that mailbox.
  3. If the two match then the frame is accepted and put into that mailbox
  4. If there was no match then try the next mailbox (steps 1-4)
  5. If no mailboxes matched then throw the frame away

So, transmission mailboxes are just kind of storage for frames you’re about to send. Reception mailboxes are mask/filter combos that accept only frames that match.

The limitation thus is that you can only accept frames via a mask/filter combo. That means that sometimes you might end up accepting more frames IDs through to a mailbox than you really wanted.

Here are some examples:
Let’s say you want to only accept ID 0x123. Then the mask / filter would be:
0x7FF / 0x123 - 0x7FF means that all 11 bits in a standard ID are required to match exactly. Then 0x123 is the exact ID to match.

0x7F0 / 0x120 - Now we mask 0x7F0 which means that the lowest 4 bits are masked away and don’t matter. So, 0x120 will match, 0x128 will match, 0x12F will match. There are 16 different IDs that will match.

But, let’s say you need to allow 9 IDs through. Say, 0x122 to 0x12A. You can’t create a mask/id combo that lets through those 9 IDs and no others. But, you can use the above combo that lets through 16 IDs and you can just ignore the other 7.

Let me know what else you’d like to know. Do you need specific examples in code? There are examples within the due_can library.

Thank you sir. This is some great info. This is what I kinda figured out by reading the code, but needed confirmation.

I do realize the mailbox is part of the hardware as opposed to the CAN bus, I just wanted to avoid confusions if there are mailboxes for the other bus lines the M2 can handle.

I’ve found the examples VERY helpful, but I have question more relating to performance and best practices. Nobody likes sloppy code :slight_smile:

How do the mailboxes affect performance? Is it better to only activate a mailbox when you are actually looking for a frame, or does it matter? What about just turning off the call back function with a call to detachCANInterrupt()? or is clearing the mask/filter considered better practice?

How many messages can the RX mailbox handle? If it’s only one, does it get overwritten immediately, or does it buffer? Is buffering a FIFO or LIFO? and what’s the best way to get the latest frame in the buffer if it is a FIFO stack?

Mailboxes essentially don’t affect performance. You have to use them so the use of them is basically free. The only performance related effect is that accepting more messages takes more time. It could cause your sketch to need to do more work which means fewer cycles for anything else. Deep down in the library all RX mailboxes dump into the same reception buffer. This is done automatically, once you set up a mailbox you don’t have to go get messages out of it. They’re automatically removed from the mailbox by the library. If you have a callback registered then you will immediately get a callback with the message. If you don’t then it gets stuck in a FIFO queue with all other RX messages that didn’t match a callback. So, you can limit the performance hit from CAN by turning off callbacks for any mailboxes you don’t need messages from at the moment. If you have mailboxes enabled but no callback the messages will be queued and the queue will just full up and quit saving messages at some point. But, if you aren’t caring about CAN traffic at that point then you can just ignore that - it doesn’t hurt anything.

If you need to disable a callback I’d use detachCANInterrupt instead of clearing the mask/filter but it’s up to you. Clearing the mask/filter totally quits accepting the traffic at all which is helpful for performance.

One curio I have noticed is that if you set MB0 as promiscuous(mid=mam=0)/standard(IDE=0) and MB1 as promiscuous/extended(IDE=1) …they are functionally identical, and ALL packets are caught by MB0 (assuming you acknowledge them quickly enough) …this feels like a bug in the silicon, but in section 40.9.15 (of the SAM datasheet) it explains why this happens