Building a CAN API for Arduino DUE

Ok. Change of plans. Henceforth I will stay working with the CAN code available through the Arduino IDE. At the end, a CAN library and a couple of sample sketches will be added to the Arduino IDE as tools to send and receive standard (ver.2.0A - 11 bit) and extended (ver.2.0B - 29 bits) messages, but before this, as I stated in previous posts, I have been running some tests of the sample CAN code provided by Atmel in AS6, SAM_BA 2.12 and my SAM3X-EK board. The purpose of these tests is to dissect and obtain a proven minimum CAN code for the SAM3X8E. Finally, once the necessary source code has been chosen (libraries, .h, .c), we will proceed to program the SAM3X8E in Arduino due through the Arduino IDE.

I know the majority of the CAN protocol fans in this forum look forward to have access to the code but for the moment let me show you a picture my SAM3X-EK and a CAN device (sorry for the wiring mess) and also a pseudo-code and an idealized sketch.

For understand a bit better the following pseudo –code, it is healthy to explain briefly about the CAN platform embedded inside the SAM3X8E core.
The SAM3X8H has two CAN Controllers. We will call these controllers CAN0 and CAN1. The SAM3X8H read/writes from/to them through the PIO A and PIO B respectively. Each of these controllers connects one respective bus. Each bus should comprehends only two transmission lines (CANTX/CANRX) but due to the energy efficiency design of the SAM3X8E, it is required the use of two CAN transceivers (one per bus) between the SAM3X8E and the outer world. Also, we will discuss latter about these transceiver and the future shield.
Here the pseudo-code:
Initialization code (setup)

  1. Define CAN0 and CAN1 transfer mailbox structure
  2. Enable the module clock for CAN0 and CAN1
  3. Initialize CAN0 and CAN1, baud rate (baud/s)
  4. Reset all CAN0 and CAN1 mailboxes
  5. Initialize CAN1 mailbox 0 as receiver, frame ID
  6. Initialize CAN0 mailbox 0 as transmitter, frame ID
  7. Prepare transmit ID, data and data length in CAN0 mailbox 0

Main code (loop)

  1. Send out data in CAN0 mailbox 0
  2. Wait for CAN1 mailbox 0 to receive the data
  3. Read the received data from CAN1 mailbox 0

For a user-friendly interface, I will encapsulate the initialization code in a couple of steps that only include baud rate, frame ID, priority, type of message frame (2.0A or 2.0B) and mailbox configuration(transmitter/receiver).

The main code will use the following functions: send, wait and read.
An idelized Arduino Due CAN sketch will look like:

// Idealized CAN sketch for Arduino Due board
// By Palliser 2012


// Required CAN library
#include <can.h>

// Initialize CAN Controllers (defines structure, enable clock)
CANInit CAN0;
CANInit CAN1;

// Mailboxes frame ID 7 and 8
int MB_ID7 = 7;
int MB_ID8 = 8;

// CAN message to turn on Arduino Due pin 13
int CAN_MSG_HIGH_PIN_13 = 0x11223344
// Arduino Due pin 13
int led13 = 13;

void setup()
{
  //CAN baud rate 1Mb/s
  Can.begin(1000000);
  //Reset all CAN0 and CAN1 mailboxes
  Can.MBReset(CAN0);
  Can.MBReset(CAN1);
  //Init CAN0 mailbox 7 as receiver
  Mailbox.mode(CAN0, MB_ID7, RX_Mode);
  // Init CAN1 mailbox 8 as transmitter
  Mailbox.mode(CAN1, MB_ID8, TX_Mode);
  // Prepare transmit information into CAN1 mailbox 8
  CAN_MB_WRITE(CAN1, MB_ID8, CAN_MSG_HIGH_PIN_13);
  // initialize the digital pin as an output.
  pinMode(led13, OUTPUT);
}

void loop()
{
  
  // Send out information in CAN1 mailbox 8
  CAN_MB_SEND(CAN1, MB_ID8);
  
  while(!recv_status){
  }
  if(CAN0_MB_DATA == CAN_MSG_HIGH_PIN_13){
  Serial.println("Test passed");
  digitalWrite(led13, HIGH);}
  else{
  Serial.println("Test ERROR");  
  }
}

Regards.