Atmel website | ARM Community | AVR freaks | Technical Support
Banner
 FAQ •  Search •  Register •  Login 

All times are UTC + 1 hour [ DST ]




Post new topic Reply to topic  [ 1 post ] 
Author Message
 Post subject: AT91SAM7X CAN driver problems
PostPosted: Tue Oct 02, 2007 9:46 am 
Offline

Joined: Thu Jul 12, 2007 12:10 pm
Posts: 1
Location: the Netherlands
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.

Code:
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
  }
}

My mailbox configuration:

void CANInitMailboxes(void)
{
  // Init CAN Mailbox 0
  //taskENTER_CRITICAL();
  AT91F_InitMailboxRegisters(AT91C_BASE_CAN_MB0,
                             AT91C_CAN_MOT_TX | AT91C_CAN_PRIOR,                    // Mailbox Mode Reg
                             0x00000000,                                            // Mailbox Acceptance Mask Reg
                             AT91C_CAN_MIDvA & (0x07<<18),                           // Mailbox ID Reg
                             0x11223344,                                            // Mailbox Data Low Reg
                             0x01234567,                                            // Mailbox Data High Reg
                             (AT91C_CAN_MDLC & (0x8<<16)) );                        // Mailbox Control Reg
  //taskEXIT_CRITICAL();
  //taskENTER_CRITICAL();
  // Init CANMailbox 1
  AT91F_InitMailboxRegisters(AT91C_BASE_CAN_MB1,
                             AT91C_CAN_MOT_RX | AT91C_CAN_PRIOR,                    // Mailbox Mode Reg
                             AT91C_CAN_MIDvA | AT91C_CAN_MIDvB | AT91C_CAN_MIDE,    // Mailbox Acceptance Mask Reg
                             AT91C_CAN_MIDvA & (0x07<<18),                           // Mailbox ID Reg
                             0x00000000,                                            // Mailbox Data Low Reg
                             0x00000000,                                            // Mailbox Data High Reg
                             0x00000000);                                           // Mailbox Control Reg
  //taskEXIT_CRITICAL();
}



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? Or perhaps someone has already written a driver and is willing to share some code? Some help is much appreciated.

regards,

Harm


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 1 post ] 

All times are UTC + 1 hour [ DST ]


Who is online

Users browsing this forum: No registered users and 8 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: