Building a CAN API for Arduino DUE

For a better understanding of the Atmel CAN controllers inside the SAM3X8E, I have dissected the initialization procedure required to let the

CAN controller interact (synchronize/listen) with the real world (CANH/CANL).

Document Sources:

  • Atmel doc 11057.pdf
  • Can Library from Atmel ASF.

System controllers used:

  • Power Management Controller (PMC)
  • Nested Vectored Interrupt Controller (NVIC)
  • CAN Controller (CAN)

CAN initialization procedure:

  1. CAN controller -> DISABLED after power-up reset.
  2. CAN controller clock -> ENABLED by PMC (via Low-Power Peripheral Bridge) for CAN peripheral IDs 43 (CAN0) and 44 (CAN1).
  3. CAN controller interrupt line -> ENABLED for mailbox X (API definition - CAN_IER_MBX) through CMSIS definitions (CANx_IRQn) in the embedded NVIC (NVIC_EnableIRQ).
  4. CAN controller initialized
    4.1. CAN_BR register (baudrate) -> SET. The following steps are performed:
    4.1.1 Check whether the baudrate prescale will be greater than the max divide value.
    4.1.2 Check whether the input MCK is too small.
    4.1.3 Initialize it as the minimum Time Quantum.
    4.1.4 Initialize the remainder as the max value. When the remainder is 0, get the right TQ number.
    4.1.5 Find out the approximate Time Quantum according to the baudrate.
    4.1.6 Calculate the baudrate prescale value.
    4.1.7 Get the right CAN BIT Timing group.
    4.1.8 Before modifying the CANBR register, disable the CAN controller.
    4.1.9 Write into the CAN baudrate register.

4.2. 8-CAN message mailboxes -> RESET. (CAN_MB_DISABLE_MODE) The following steps are performed:
4.2.1 Check the object type of the mailbox. If it's used to disable the mailbox, reset the whole mailbox.
4.2.2 Set the priority in Transmit mode.
4.2.3 Set the message ID and message acceptance mask for the mailbox in other modes.
4.2.4 Set up mailbox in one of the five different modes.
4.3. Configure a mailbox in reception (or consumer) mode
4.4. CAN autobaud listen mode -> SET in CAN_MR register (CAN_MR_ABM == 1)
4.5. CAN controller -> SET CANEN in CAN_MR register (CAN_MR_CANEN == 1)
At this stage, the internal CAN controller state machine is reset, error counters are reset to 0, error flags are reset to 0 and starts bus synchronization automatically by
scanning eleven recessive bits an then start listening to the network (real world).

I want to clarify that, even though the above initial procedure it might look over-elaborated, the nature of the CAN controller so requires. We, mortal thinkerers are used to a higher level language. My aim has been to bring here part of what's cooking regarding the CAN API, now in progress. But don't worry; at the end, a simpler solution to this whole approach will emerge.

Note: The CAN interruptions in SAM3X8E are implemented through CMSIS definitions in the embedded NVIC inside Cortex-M3 (Not from not existent AIC controller). I got confused because it would seem that some of the CAN controller sections in the SAM3X8E manual (doc11057) were from copy&paste sections of the SAM7X manual. The explanation could be that CORTEX-M3 inherited part of its functionality from the venerable ARM7.