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.


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?


  • 1
    \$\begingroup\$ Does this answer help? Difference between buffer and mailbox \$\endgroup\$
    – Finbarr
    May 11, 2020 at 14:58
  • \$\begingroup\$ Hi @Finbarr. First of all, thanks for your help. I did review the related questions before asking this one. I think I have an ok understanding of what is a mailbox, but I don't understand the tradeoffs between mailboxes usages architecture. If that makes sense. \$\endgroup\$
    – gbt
    May 11, 2020 at 15:11

3 Answers 3


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.

  • \$\begingroup\$ Interesting. I was using mailboxes mainly as filters. Every time they receive a new message, they would trigger an ISR to put it in my own memory. I suppose that I could instead keep them in the mailbox and only poll them as needed. \$\endgroup\$
    – gbt
    May 14, 2020 at 12:23
  • \$\begingroup\$ What about the TX mailbox? As a CAN bus can only send a message 1 at the time, why have multiple TX mailbox? Again to not have TX FIFO? Or is there a better reason? \$\endgroup\$
    – gbt
    May 14, 2020 at 12:24
  • \$\begingroup\$ @gberth The TX mailbox means you can just drop a message there and then carry on doing other work. Whereas MCUs with the simpler CAN controllers will have to poll some status register, in worst case a busy-wait like while(CANSTATUS & TXBUSY) {/* do nothing */} CANDATA = data; \$\endgroup\$
    – Lundin
    May 14, 2020 at 12:53
  • \$\begingroup\$ That's such a good answer. I came back to it today. Thanks again @Lundin \$\endgroup\$
    – gbt
    Mar 17, 2023 at 14:46

CAN mailboxes solve problems for the CAN hardware designer: where to put a message when it arrives? And where to take messages from in order to send them?

Sophisticated systems like Ethernet tend to have queues. CAN microcontrollers usually don't. So each mailbox can hold only one message. If another message arrives for the same mailbox, it may not be received or it may overwrite the stored message.

On the transmit side, again you don't have queues. So in order to schedule multiple messages outgoing, you can designate multiple transmit mailboxes.

The inbound mailboxes usually have filters, so you can route mail of a particular type to a particular mailbox. This allows the code for handling messages of type X to be completely separate from the code handling type Y. In a system written by multiple developers, the chief architect can assign mailboxes to individual subsystems so the developers working on them don't have to coordinate.

  • \$\begingroup\$ Systems with multiple mailboxes often allow them to be configured either with separate filters or to queue (maybe FIFO, maybe round-robin) multiple messages matching the same filter. \$\endgroup\$
    – Ben Voigt
    May 11, 2020 at 15:51

CAN works with message objects instead of with a byte stream and thus mailbox is more accurate.

There are two ways to look at mailboxes, from controller perspective and software perspective.


This is a mailbox between the hardware and the software.
The controller requires a place to read messages from. Since it's more than one word, it is an object, and you can't put objects in single registers anymore. Hence the term "mailbox". It a collection of registers available to the hardware.

The opposite is also true, it needs a place to store the messages when received. Waiting for an irq to complete and read the data will result in missed frames. The mailbox provides an atomic way to immediately present received data to the rest of the system.

In the original Bosch CAN controller there are 20 mailboxes that also directly function as hardware filters. Since CAN can be very busy and not everything is important. Any match of those identifiers gets put in the mailbox, others are dropped. The drawback is that transmits also share these mailboxes, since registers aren't free.
It was done this way since an cpu's back then weren't very fast and copying >8 bytes of data around regularly is a waste. And the CAN controller was often a separate co-processor with a slow interface between them.

That some controllers today made mailbox/fifo hybrid solutions is something you should just ignore in this concept. (looking at you, bxCAN)

What does the mailbox solve?

It solves a data availability and overrun problems.


This is a mailbox between the can driver and the software.

An interface for such mailbox in a CAN driver could be:

class mailbox 
    flags (rx,tx,interval)

In the above prototype the events are often added in CAN driver software, and they scale well. Today it's cheap to get >100 MHz cpu's, so copying the data around isn't that much of a penalty anymore.
transmit_callback is called when it is ready to transmit a mailbox.
receive_callback is called when when mailbox has received data.
error_callback is called when when a mailbox receive interval expired or the mailbox was overwritten without being read.
Software using these mailbox interfaces is independent of the hardware.

What does the mailbox solve?

It solves the huge switch statement in your can.c file.

  • \$\begingroup\$ > "The mailbox provides an atomic way to immediately present received data to the rest of the system." Interesting. The TI's HAL recommend using while (!canIsRxMessageArrived(node, messageBox)) before using canGetData(). I always assume it was because the mailbox wasn't "atomic". \$\endgroup\$
    – gbt
    May 14, 2020 at 12:30
  • \$\begingroup\$ @gberth The mailbox is either shadowed or mutexed by hardware. \$\endgroup\$
    – Jeroen3
    May 14, 2020 at 12:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.