Hi everyone,
I am currently busy writing a CAN driver for the Atmel SAM7X. My setup is as follows:
2 Evaluation boards: Olimex SAM7-EX256 Rev. a. One for transmitting messages and the other for receiving them.
Controller : ATMEL AT91SAM7X256
Used toolchain: YAGARTO
Used debugger: Open OCD + Olimex ARM USB OCD
My code is based on an example for the IAR compiler: AT91SAM7X256-BasicCAN-IAR430A-1_2. Right now, my objective is to simply send a CAN message from one board to the other.
My init code:
// Enable CAN PIOs
AT91F_CAN_CfgPIO();
// Enable CAN Clock
AT91F_CAN_CfgPMC();
// Enable CAN Transceiver
AT91F_PIOA_CfgPMC();
// Init CAN Interrupt Source Level
AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, // CAN base address
AT91C_ID_CAN, // CAN ID
AT91C_AIC_PRIOR_HIGHEST, // Max priority
AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, // Level sensitive
AT91F_CAN_Handler); // C Handler
AT91F_AIC_EnableIt(AT91C_BASE_AIC,AT91C_ID_CAN);
// Cfg CAN Baudrate to 1Mbit/s => BRP = 5
// We choose 8 Time Quanta (tCSC = 125ns): 8tCSC = tSYNC + tPRS + tPHS1 + tPHS2
// Cfg PHASE1 PHASE2 PROPAG and SYNC segment
// Delay of busdriver + delay of receiver circuit = 200ns
// Delay of bus line considered negligible = 0ns
// tPRS = 2*(200+0) = 400ns < 4tCSC => PROPAG = 3
// tSYNC = 1tCSC => 8tCSC = 1tCSC + 4tCSC + tPHS1 + tPHS2
// tPHS1 + tPHS2 = 3tCSC => Phase Segment 2 = Max(IPT=2TQ,Phase Segment 1) = 2TQ => PHASE2 = 2-1 = 1 => PHASE1 = 0
// tSJW = Min(4 TQ, Phase Segment 1) = 1TQ => SJW = 1-1 = 0
AT91F_CAN_CfgBaudrateReg(AT91C_BASE_CAN,0x00050301);
enableIRQ(); //enable interrupts
// Enable CAN and Wait for WakeUp Interrupt
AT91F_CAN_EnableIt(AT91C_BASE_CAN,AT91C_CAN_WAKEUP);
AT91F_CAN_CfgModeReg(AT91C_BASE_CAN,AT91C_CAN_CANEN);
status = (AT91F_CAN_GetStatus(AT91C_BASE_CAN)&ERROR_MASK)>>16; //error active flag set in can status register! Not OK!
// Wait for WAKEUP flag raising <=> 11-recessive-bit were scanned by the transceiver
while( (testCAN != AT91C_TEST_OK) ) //the wake-up flag is set as expected in the CAN interrupt handler
{
}
// Configure Mailboxes
CANInitMailboxes();
//End of init.
#ifdef SENDER
// Ask Transmission on Mailbox 0
AT91F_CAN_InitTransferRequest(AT91C_BASE_CAN,AT91C_CAN_MB0);
// Enable Transmission Mailbox 0 interrupt
AT91F_CAN_EnableIt(AT91C_BASE_CAN,AT91C_CAN_MB0);
#else
// Enable Reception on Mailbox 1
AT91F_CAN_InitTransferRequest(AT91C_BASE_CAN,AT91C_CAN_MB1);
// Enable Mailbox 1 interrupt
AT91F_CAN_EnableIt(AT91C_BASE_CAN,AT91C_CAN_MB1);
#endif
/*
At this point the receiver should be waiting for a message in mailbox 1. The sender should send 1 message via mailbox 0 to the receiver.
*/
The CAN interrupt handler:
void AT91F_CAN_Handler(void)
{
volatile unsigned int status;
status = AT91F_CAN_GetStatus(AT91C_BASE_CAN) & AT91F_CAN_GetInterruptMaskStatus(AT91C_BASE_CAN);
AT91F_CAN_DisableIt(AT91C_BASE_CAN,status);
if(status & AT91C_CAN_WAKEUP) { //the wake-up interrupt is triggered, so thats ok.
testCAN = AT91C_TEST_OK;
D_TRACE_SIMPLE(“=>CAN WAKEUP”,1,BLUE);
}
if(status & AT91C_CAN_MB0) {
D_TRACE_SIMPLE(“=>CAN MB0 Int”,1,BLUE); //this interrupt is not triggered, so message sending fails
}
if(status & AT91C_CAN_MB1) {
D_TRACE_SIMPLE(“=>CAN MB1 Int”,1,BLUE); //this interrupt is not triggered, so message reception fails
}
}
The CAN wake-up flag is set as expected and handled by the ISR. However, as soon as I enable the CAN controller by setting CANEN in the mode register, the error active flag gets set in the status register.
Anyone an idea as to why this happens? When the transmitter is not attached to the bus (but with the 120 ohms terminator installed…), it keeps on sending frames. I assume these are error frames. The error
codes I read from the status register are:
-first only error active
-then warning limit & error passive & ack error
-then warning limit & error passive
-warning limit & error passive & ack error again
-and so on
When I then attach the receiver to the bus I get:
-warning limit & error passive & ack error & bit error
-and then warning limit & error passive
After that the communication dies down completely. So I assume the error frame sent by the transmitter is at least acknowledged by the receiver??
When the receiver is not connected to the bus I just get error active. when I then attach it to the bus it gives a form error & error active (after which the communication dies down, as said before).
Is there anybody who can point me in the right direction perhaps? Because right now I don’t have a clue. Or perhaps someone has already written a driver and is willing to share some code? Some help is much
appreciated.
regards,
Harm