Different CAN Implementations
1.) Basic CAN
The original CAN interfaces available were later called
"Basic" CAN interface. Basic CAN interfaces only offer a limited number of
receive buffers and filters (typically 1 to 3). If a node using such a controller needs to
listen to a number of different messages (different CAN message identifiers), the filters
usually have to be set "wide open" causing an interrupt with every single
message on the bus. Obviously, the microcontroller will get many CAN interrupts, as it has
to check in software if a message can be ignored or needs to be worked on.
2.) Full CAN
The next generation of CAN controllers was the so-called
"Full-CAN" implementation. Full CAN controllers use a number of message objects
(typically 15) with each being bi-directional (can be configured to either transmit or
receive), each having its own transmit/receive buffer for one message and each having one
filter match register. This allows setting a message object to only listen for exactly one
message (one identifier).
As long as the total number of messages a node needs to listen to is
smaller than the number of message objects available, these interfaces are very efficient.
They will only cause an interrupt to the MCU if a "wanted" message was received.
However, this mechanism does not offer any protection from a
back-to-back worst-case scenario. Each message object has a single buffer and a matching
incoming message will override the buffers' contents, so potentially messages can get
lost. As long as a buffer is configured for a single message identifier, this scenario is
not too bad, as it is unlikely that the producer of that message produces them
back-to-back. But as soon as any of the message objects is configured to receive multiple
CAN identifiers - the microcontroller needs to be prepared that these could come in
back-to-back. On a 1Mbit CAN network that means about 50 microseconds from receive
interrupt occurrence to a potential overwrite of that message by the next incoming
message.
3.) FIFOs
The only way to get around the back-to-back message problem and the
high performance and timing demands on the interrupt service routine is with a receive
FIFO buffer (First In - First Out). A typical implementation features a number of filters
that include both match and mask registers. Upon a filter match, the incoming message is
moved into the FIFO buffer. An interrupt request to the MCU is made depending on
configuration: either a certain fill-level is reached or a high priority filter received
the last incoming message.
Even if such a FIFO can only hold 64 bytes it is still big enough to
improve the back-to-back scenario mentioned earlier. If the FIFO is configured to cause an
interrupt with every single incoming (matched) message, the MCU has at least 500 bit times
until the FIFO will overflow. That is about 10 times more time available to the MCU than
with Basic CAN or Full CAN implementations.
On the downside, messages in the FIFO cannot overtake each other. So
if the FIFO already contains several messages and now an additional, but high priority
message comes in - the MCU first needs to process all messages previously stored in the
FIFO before it gets access to the high priority message. In a Full CAN interface it is up
to the interrupt service routine in which order the message objects are checked and it
would very well be possible that a higher priority message can "overtake"
previously received lower priority messages.
4.) Enhanced Full CAN with Receive
FIFO
The latest developments do not have standardized names as chip
manufacturers came up with their own customized improvements for the CAN interfaces.
Several chip manufacturers now offer devices that combine the benefits of Full CAN and a
FIFO.
The most powerful approach is a Full CAN implementation with a
dedicated FIFO for each single message object. Although powerful, these are also the most
complex controllers to configure, especially if each individual FIFO can be freely located
in RAM and can be of individual lengths.
Another alternative is to be able to take a Full CAN implementation
and be able to concatenate message objects to a FIFO. So instead of one message object
only having one buffer, a FIFO can be formed "borrowing" the buffers of other
message objects. Although fairly flexible, the disadvantage is obvious: with each buffer
added to a FIFO, one message object is lost. So the value of this feature increases with a
high number of message objects, but decreases if the number of message objects decreases,
too.
[ Introduction
| Performance | Implementations | Conclusions ] |