drivers/AVR/can_AVR.c
changeset 375 03fb0bfccc1f
child 384 83793fc7ce48
equal deleted inserted replaced
374:b74f7ec412fc 375:03fb0bfccc1f
       
     1 /*
       
     2 This file is part of CanFestival, a library implementing CanOpen Stack.
       
     3 
       
     4 Copyright (C): Edouard TISSERANT and Francis DUPIN
       
     5 AVR Port: Andreas GLAUSER and Peter CHRISTEN
       
     6 
       
     7 See COPYING file for copyrights details.
       
     8 
       
     9 This library is free software; you can redistribute it and/or
       
    10 modify it under the terms of the GNU Lesser General Public
       
    11 License as published by the Free Software Foundation; either
       
    12 version 2.1 of the License, or (at your option) any later version.
       
    13 
       
    14 This library is distributed in the hope that it will be useful,
       
    15 but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    17 Lesser General Public License for more details.
       
    18 
       
    19 You should have received a copy of the GNU Lesser General Public
       
    20 License along with this library; if not, write to the Free Software
       
    21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    22 */
       
    23 
       
    24 //#define DEBUG_WAR_CONSOLE_ON
       
    25 //#define DEBUG_ERR_CONSOLE_ON
       
    26 
       
    27 #include "can_AVR.h"
       
    28 #include "canfestival.h"
       
    29 
       
    30 volatile unsigned char msg_received = 0;
       
    31 
       
    32 unsigned char canInit(unsigned int bitrate)
       
    33 /******************************************************************************
       
    34 Initialize the hardware to receive CAN messages and start the timer for the
       
    35 CANopen stack.
       
    36 INPUT	bitrate		bitrate in kilobit
       
    37 OUTPUT	1 if successful	
       
    38 ******************************************************************************/
       
    39 {
       
    40   unsigned char i,k;
       
    41     //- Pull-up on TxCAN & RxCAN one by one to use bit-addressing
       
    42   CAN_PORT_DIR &= ~(1<<CAN_INPUT_PIN );
       
    43   CAN_PORT_DIR &= ~(1<<CAN_OUTPUT_PIN);
       
    44   CAN_PORT_OUT |=  (1<<CAN_INPUT_PIN );
       
    45   CAN_PORT_OUT |=  (1<<CAN_OUTPUT_PIN);
       
    46 
       
    47   Can_reset();				// Reset the CAN controller
       
    48 
       
    49   if (bitrate <= 500)
       
    50   {
       
    51     // CANopen 10..500 kbit with 16 tq, sample point is at 14 tq
       
    52     // all values are added to 1 by hardware
       
    53     // Resynchronisation jump width (SJW)	= 1 tq 
       
    54     // Propagation Time Segment (PRS)		= 5 tq
       
    55     // Phase Segment 1 (PHS1)			= 8 tq 
       
    56     // Phase Segment 2 (PHS2)			= 2 tq
       
    57     // Total					= 16 tq
       
    58     CANBT1 = ((F_CPU/16/1000/bitrate-1) << BRP);	// set bitrate
       
    59     CANBT2 = ((1-1) << SJW) |((5-1) << PRS);	// set SJW, PRS
       
    60     CANBT3 = (((2-1) << PHS2) | ((8-1) << PHS1) | (1<<SMP)); // set PHS1, PHS2, 3 sample points
       
    61   }
       
    62   else 
       
    63     return 0;
       
    64 
       
    65   // Reset all mailsboxes (MObs), filters are zero (accept all) by clear all MOb
       
    66   // Set the lower MObs as rx buffer
       
    67   for (i = 0; i < NB_MOB; i++)
       
    68   {
       
    69     Can_set_mob(i);		// Change to MOb with the received message
       
    70     Can_clear_mob();		// All MOb Registers=0
       
    71     for (k = 0; k < NB_DATA_MAX; k++)
       
    72       CANMSG = 0;		// MOb data FIFO
       
    73     if (i < NB_RX_MOB)		// Is receive MOb
       
    74       Can_config_rx_buffer();	// configure as receive buffer
       
    75   }
       
    76   // The tx MOb is still disabled, it will be set to tx mode when the first message will be sent
       
    77   // Enable the general CAN interrupts
       
    78   CANGIE = (1 << ENIT) | (1 << ENRX) | (1 << ENTX) | (0 << ENERR) | (0 << ENERG) | (0 << ENOVRT);
       
    79   CANIE1 = 0x7F;	// Enable the interrupts of all MObs (0..14)
       
    80   CANIE2 = 0xFF;   
       
    81   Can_enable();                                 // Enable the CAN bus controller
       
    82   return 1;
       
    83 }
       
    84 
       
    85 unsigned char canSend(CAN_PORT notused, Message *m)
       
    86 /******************************************************************************
       
    87 The driver send a CAN message passed from the CANopen stack
       
    88 INPUT	CAN_PORT is not used (only 1 avaiable)
       
    89 	Message *m pointer to message to send
       
    90 OUTPUT	1 if  hardware -> CAN frame
       
    91 ******************************************************************************/
       
    92 {
       
    93   unsigned char i;
       
    94 
       
    95   for (i = START_TX_MOB; i < NB_MOB; i++)	// Search the first free MOb
       
    96   {
       
    97     Can_set_mob(i);			// Change to MOb
       
    98     if ((CANCDMOB & CONMOB_MSK) == 0)	// MOb disabled = free
       
    99     {
       
   100       break;
       
   101     }
       
   102   }
       
   103   if (i < NB_MOB)			// free MOb found
       
   104   {
       
   105     Can_set_mob(i);			// Switch to the sending messagebox
       
   106     Can_set_std_id(m->cob_id);		// Set cob id
       
   107     if (m->rtr)				// Set remote transmission request
       
   108       Can_set_rtr();
       
   109     Can_set_dlc(m->len);		// Set data lenght code
       
   110 
       
   111     for (i= 0; i < (m->len); i++)	// Add data bytes to the MOb
       
   112       CANMSG = m->data[i];
       
   113   // Start sending by writing the MB configuration register to transmit
       
   114     Can_config_tx();		// Set the last MOb to transmit mode
       
   115     return 1;	// succesful
       
   116   }
       
   117   else
       
   118     return 0;	// not succesful
       
   119 }
       
   120 
       
   121 unsigned char canReceive(Message *m)
       
   122 /******************************************************************************
       
   123 The driver pass a received CAN message to the stack
       
   124 INPUT	Message *m pointer to received CAN message
       
   125 OUTPUT	1 if a message received
       
   126 ******************************************************************************/
       
   127 {
       
   128   unsigned char i;
       
   129 
       
   130   if (msg_received == 0)
       
   131     return 0;		// Nothing received
       
   132 
       
   133   for (i = 0; i < NB_RX_MOB; i++)	// Search the first MOb received
       
   134   {
       
   135     Can_set_mob(i);			// Change to MOb
       
   136     if ((CANCDMOB & CONMOB_MSK) == 0)	// MOb disabled = received
       
   137     {
       
   138       msg_received--;
       
   139       break;
       
   140     }
       
   141   }
       
   142   if (i < NB_RX_MOB)			// message found
       
   143   {
       
   144     Can_get_std_id(m->cob_id);		// Get cob id
       
   145     m->rtr = Can_get_rtr();		// Get remote transmission request
       
   146     m->len = Can_get_dlc();		// Get data lenght code
       
   147     for (i= 0; i < (m->len); i++)	// get data bytes from the MOb
       
   148       m->data[i] = CANMSG;
       
   149     Can_config_rx_buffer();		// reset the MOb for receive
       
   150     return 1;                  		// message received
       
   151   }
       
   152   else					// no message found
       
   153   {
       
   154     msg_received = 0;			// reset counter
       
   155     return 0;                  		// no message received
       
   156   }
       
   157 }
       
   158 
       
   159 #ifdef  __IAR_SYSTEMS_ICC__
       
   160 #pragma type_attribute = __interrupt
       
   161 #pragma vector=CANIT_vect
       
   162 void CANIT_interrupt(void)
       
   163 #else	// GCC
       
   164 ISR(CANIT_vect)
       
   165 #endif	// GCC
       
   166 /******************************************************************************
       
   167 CAN Interrupt
       
   168 ******************************************************************************/
       
   169 {
       
   170   unsigned char i;
       
   171 
       
   172   if (CANGIT & (1 << CANIT))	// is a messagebox interrupt
       
   173   {
       
   174     if ((CANSIT1 & TX_INT_MSK) == 0)	// is a Rx interrupt
       
   175     {
       
   176       for (i = 0; (i < NB_RX_MOB) && (CANGIT & (1 << CANIT)); i++)	// Search the first MOb received
       
   177       {
       
   178         Can_set_mob(i);			// Change to MOb
       
   179         if (CANSTMOB & MOB_RX_COMPLETED)	// receive ok
       
   180         {
       
   181           Can_clear_status_mob();	// Clear status register
       
   182 	  Can_mob_abort();		// disable the MOb = received
       
   183 	  msg_received++;
       
   184         }
       
   185         else if (CANSTMOB & ~MOB_RX_COMPLETED)	// error
       
   186         {
       
   187           Can_clear_status_mob();	// Clear status register
       
   188 	  Can_config_rx_buffer();	// reconfigure as receive buffer
       
   189         }
       
   190       }
       
   191     }
       
   192     else				// is a Tx interrupt	 
       
   193     {
       
   194       for (i = NB_RX_MOB; i < NB_MOB; i++)	// Search the first MOb transmitted
       
   195       {
       
   196         Can_set_mob(i);			// change to MOb
       
   197         if (CANSTMOB)			// transmission ok or error
       
   198         {
       
   199           Can_clear_status_mob();	// clear status register
       
   200 	  CANCDMOB = 0;			// disable the MOb
       
   201 	  break;
       
   202         }
       
   203       }
       
   204     }
       
   205   }
       
   206 
       
   207   // Bus Off Interrupt Flag
       
   208   if (CANGIT & (1 << BOFFIT))    // Finaly clear the interrupt status register
       
   209   {
       
   210     CANGIT |= (1 << BOFFIT);                    // Clear the interrupt flag
       
   211   }
       
   212   else
       
   213     CANGIT |= (1 << BXOK) | (1 << SERG) | (1 << CERG) | (1 << FERG) | (1 << AERG);// Finaly clear other interrupts
       
   214 }
       
   215 
       
   216 #ifdef  __IAR_SYSTEMS_ICC__
       
   217 #pragma type_attribute = __interrupt
       
   218 #pragma vector=OVRIT_vect
       
   219 void OVRIT_interrupt(void)
       
   220 #else	// GCC
       
   221 ISR(OVRIT_vect)
       
   222 #endif	// GCC
       
   223 /******************************************************************************
       
   224 CAN Timer Interrupt
       
   225 ******************************************************************************/
       
   226 {
       
   227   CANGIT |= (1 << OVRTIM);
       
   228 }
       
   229