00001 /* 00002 This file is part of CanFestival, a library implementing CanOpen Stack. 00003 00004 Copyright (C): Edouard TISSERANT and Francis DUPIN 00005 00006 See COPYING file for copyrights details. 00007 00008 This library is free software; you can redistribute it and/or 00009 modify it under the terms of the GNU Lesser General Public 00010 License as published by the Free Software Foundation; either 00011 version 2.1 of the License, or (at your option) any later version. 00012 00013 This library is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 Lesser General Public License for more details. 00017 00018 You should have received a copy of the GNU Lesser General Public 00019 License along with this library; if not, write to the Free Software 00020 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00021 */ 00022 00023 #ifndef __CANDRIVER__ 00024 #define __CANDRIVER__ 00025 00026 //#include DEBUG_CAN 00027 00028 #include <can.h> 00029 #include <objdictdef.h> 00030 00031 00032 /* 00033 The CAN message received are stored in a fifo stack 00034 We consider one stack for all the 5 can devices. It is a choice ! 00035 */ 00036 00037 /* Be free to change this value */ 00038 #define MAX_STACK_MSG_RCV 5 00039 00040 /* Number of incomings and outcomings CAN Line. The layer CanOpen must be 00041 used only for ONE line CAN. But you may used one or more CAN drivers, without 00042 a CanOpen layer. 00043 Only 2 lines are implemented. If more lines are needed, copy void __attribute__((interrupt)) can0HdlRcv (void) to void __attribute__((interrupt)) canXHdlRcv (void) and make 00044 changes : [0] to [x], CAN0 to CANX, etc 00045 */ 00046 #define NB_LINE_CAN 1 00047 00048 /* Whose hardware HCS12 CAN block is used for CanOpen ? Chose between CAN0, ..., CAN4 00049 If you use CANOPEN_LINE_NUMBER_USED = CANI, the value of NB_LINE_CAN must be 00050 more or equal to I + 1 00051 Value other than CAN0 not tested, but should work fine. 00052 */ 00053 #define CANOPEN_LINE_NUMBER_USED CAN0 00054 00055 /* Stack of received messages 00056 MSG received on CAN0 module is stored in stackMsgRcv[0], etc 00057 */ 00058 extern volatile Message stackMsgRcv[NB_LINE_CAN][MAX_STACK_MSG_RCV]; 00059 00060 00061 /* Copy from the stack of the message to treat */ 00062 extern Message msgRcv; 00063 00064 00065 /* To move on the stack of messages 00066 */ 00067 typedef struct { 00068 UNS8 w ; /* received */ 00069 UNS8 r ; /* To transmit */ 00070 } t_pointerStack; 00071 00072 00073 /* Pointer for write or read a message in/from the reception stack */ 00074 extern volatile t_pointerStack ptrMsgRcv[NB_LINE_CAN]; 00075 00076 /* 00077 Parameters to define the clock system for the CAN bus 00078 example : 00079 CAN_BUS_TIME clk = { 00080 1, // clksrc: Use the bus clock : 16 MHz, the freq. of the quartz's board 00081 0, // brp : chose btw 0 and 63 (6 bits). freq time quantum = 16MHz / (brp + 1) 00082 1, // sjw : chose btw 0 and 3 (2 bits). Sync on (sjw + 1 ) time quantum 00083 1, // samp : chose btw 0 and 3 (2 bits) (samp + 1 ) samples per bit 00084 4, // tseg2 : chose btw 0 and 7 (3 bits) Segment 2 width = (tseg2 + 1) tq 00085 9, // tseg1 : chose btw 0 and 15 (4 bits) Segment 1 width = (tseg1 + 1) tq 00086 00087 00088 With these values, 00089 - The width of the bit time is 16 time quantum : 00090 - 1 tq for the SYNC segment (could not be modified) 00091 - 10 tq for the TIME 1 segment (tseg1 = 9) 00092 - 5 tq for the TIME 2 segment (tseg2 = 4) 00093 - Because the bus clock of the MSCAN is 16 MHZ, and the 00094 freq of the time quantum is 16 MHZ (brp = 0), and there are 16 tq in the bit time, 00095 so the freq of the bit time is 1 MHz. 00096 00097 }; 00098 */ 00099 typedef struct { 00100 UNS8 clksrc; /* use of internal clock or clock bus */ 00101 UNS8 brp; /* define the bus speed */ 00102 UNS8 sjw; /* Number of time quantum for synchro - 1 */ 00103 UNS8 samp; /* Number of sample per bit (1 or 3) */ 00104 UNS8 tseg2; /* Width of the time segment 2 (in tq) - 1 */ 00105 UNS8 tseg1; /* Width of the time segment 1 (in tq) - 1 */ 00106 } canBusTime; 00107 00108 /* 00109 Parameters to init the filters for received messages 00110 */ 00111 typedef struct { 00112 UNS8 idam; /* Put 0x01 for 16 bits acceptance filter */ 00113 UNS8 canidar0; 00114 UNS8 canidmr0; 00115 UNS8 canidar1; 00116 UNS8 canidmr1; 00117 UNS8 canidar2; 00118 UNS8 canidmr2; 00119 UNS8 canidar3; 00120 UNS8 canidmr3; 00121 UNS8 canidar4; 00122 UNS8 canidmr4; 00123 UNS8 canidar5; 00124 UNS8 canidmr5; 00125 UNS8 canidar6; 00126 UNS8 canidmr6; 00127 UNS8 canidar7; 00128 UNS8 canidmr7; 00129 } canBusFilterInit; 00130 00131 /* 00132 Parameters to init MSCAN 00133 Example 00134 CAN_BUS_INIT bi = { 00135 0, no low power 00136 0, no time stamp 00137 1, enable MSCAN 00138 0, clock source : oscillator 00139 0, no loop back 00140 0, no listen only 00141 0, no low pass filter for wk up 00142 { 00143 1, Use the oscillator clock 00144 0, Quartz oscillator : freq time quantum = freq oscillator clock / (0 + 1) 00145 1, Sync on (1 + 1) time quantum 00146 1, 1 sample per bit 00147 4, time segment 2 width : (4 + 1) tq 00148 9, time segment 1 width : (9 + 1) tq 00149 } 00150 }; 00151 */ 00152 00153 typedef struct { 00154 UNS8 cswai; /* Low power/normal in wait mode (1/0) */ 00155 UNS8 time; /* Timer for time-stamp enable/disable (1/0) */ 00156 UNS8 cane; /* Enable MSCAN (yes=1) Do it ! */ 00157 UNS8 clksrc; /* clock source bus/oscillator (1/0) */ 00158 UNS8 loopb; /* loop back mode for test (yes=1/no=0) */ 00159 UNS8 listen; /* MSCAN is listen only (yes=1/no=0 ie normal)*/ 00160 UNS8 wupm; /* low pas filter for wake up (yes=1/no=0) */ 00161 canBusTime 00162 clk; /* Values for clock system init */ 00163 canBusFilterInit 00164 fi; /* Values for filter acceptance msg init */ 00165 00166 } canBusInit; 00167 00168 extern canBusInit bi; 00169 00170 00171 00172 /* 00173 For the received messsage, add a Identificator to 00174 the list of ID to accept. 00175 You can use several times this function to accept several messages. 00176 It configures registers on 16 bits. 00177 Automatically, it configure the filter to 00178 - not accepting the msg on 29 bits (ide=1 refused) 00179 - not filtering on rtr state (rtr = 1 and rtr = 0 are accepted) 00180 Algo : 00181 if CANIDARx = 0 then CANIDARx = id . else do nothing 00182 CANIDMRx = CANIDMRx OR (CANIDARx XOR id ) 00183 nFilter : 0 to 3 00184 Must be in init mode before. 00185 */ 00186 char canAddIdToFilter ( 00187 UNS16 adrCAN, 00188 UNS8 nFilter, 00189 UNS16 id /* 11 bits, the 5 msb not used */ 00190 ); 00191 00192 /* 00193 Use this function to change the CAN message acceptance filters and masks. 00194 */ 00195 char canChangeFilter (UNS16 adrCAN, canBusFilterInit fi); 00196 00197 00198 /* 00199 Enable one of the 5 MSCAN. 00200 Must be done only one time after a reset of the CPU. 00201 To do before any CAN initialisation 00202 */ 00203 char canEnable ( 00204 UNS16 adrCAN /* First address of MSCANx registers */ 00205 ); 00206 00207 00208 /* 00209 Initialize one of the 5 mscan 00210 can be done multiple times in your code 00211 Return 0 : OK 00212 When it return from the function, 00213 mscan is on sleep mode with wake up disabled. 00214 is not on init mode 00215 */ 00216 char canInit ( 00217 UNS16 adrCAN, /* First address of MSCANx registers */ 00218 canBusInit 00219 bi /* All the parameters to init the bus */ 00220 ); 00221 /* 00222 Initialize the parameters of the system clock for the MSCAN 00223 You must put the MSCAN in sleep mode before with canSleepMode() 00224 Return 0 : OK 00225 1 : Not in sleep mode. Unable to init MSCAN 00226 */ 00227 char canInitClock ( 00228 UNS16 adrCAN, /* First address of MSCANx registers */ 00229 canBusTime clk); 00230 00231 /* 00232 Initialize one filter for acceptance of received msg. 00233 Filters MUST be configured on 16 bits 00234 (See doc Motorola mscan bloc guide fig 4.3) 00235 Must be in init mode before. 00236 adrCAN : adress of the first register of the mscan module 00237 nFilter : the filter : 0 to 3. 00238 ar : Value to write in acceptance register 00239 Beware ! hight byte and low byte inverted. 00240 for example if nFilter = 0, hight byte of ar -> CANIDAR0 00241 low byte of ar -> CANIDAR1 00242 mr : Value to write in mask register 00243 Beware ! hight byte and low byte inverted. 00244 for example if nFilter = 2, hight byte of ar -> CANIDMR4 00245 low byte of ar -> CANIDMR5 00246 */ 00247 char canInit1Filter ( 00248 UNS16 adrCAN, 00249 UNS8 nFilter, 00250 UNS16 ar, 00251 UNS16 mr 00252 ); 00253 00254 /* 00255 Initialise the parameters for filtering the messages received. 00256 You must put the MSCAN in init mode before with canInitMode() 00257 Return 0 : OK 00258 1 : Not in init mode. Unable to init MSCAN 00259 */ 00260 00261 char canInitFilter ( 00262 UNS16 adrCAN, /* First address of MSCANx registers */ 00263 canBusFilterInit fi); 00264 /* 00265 Put one of the 5 mscan in Init mode 00266 Loop until init mode is reached. 00267 */ 00268 00269 char canInitMode ( 00270 UNS16 adrCAN /* First address of MSCANx registers */ 00271 ); 00272 00273 /* 00274 Leave the Init mode 00275 loop until init mode leaved. 00276 */ 00277 00278 char canInitModeQ ( 00279 UNS16 adrCAN /* First address of MSCANx registers */ 00280 ); 00281 00282 00283 00284 /* 00285 Transmit a msg on CAN "adrCan" 00286 Return : 0 No error 00287 other error : no buffer available to make the transmission 00288 */ 00289 00290 char canMsgTransmit ( 00291 UNS16 adrCAN, /* First address of MSCANx registers */ 00292 Message msg /* Message to transmit */ 00293 ); 00294 00295 /* 00296 Set the interruptions. Must be call just after having left the init mode. 00297 */ 00298 char canSetInterrupt (UNS16 adrCAN); 00299 00300 /* 00301 Put one of the 5 mscan in sleep mode 00302 Beware! If some messages are to be sent, 00303 or if it is receiving, going into sleep mode 00304 may take time. 00305 Wake up is disabled : stay in sleep mode even if 00306 bus traffic detected. 00307 return 0 if 0K, other if error : mscan is on init mode. 00308 Stay in this function until the sleep mode 00309 is reached. 00310 */ 00311 char canSleepMode ( 00312 UNS16 adrCAN /* First address of MSCANx registers */ 00313 ); 00314 00315 /* 00316 Leave the sleep mode 00317 loop until sleep mode leaved. 00318 return 0 : OK 00319 return 1 : error : in init mode 00320 */ 00321 char canSleepModeQ ( 00322 UNS16 adrCAN /* First address of MSCANx registers */ 00323 ); 00324 00325 /* 00326 Put one of the 5 mscan in sleep mode 00327 MSCAN must not be in init mode. 00328 wake up is enabled : wake up if traffic on CAN is detected 00329 Beware! If some messages are to be sent, 00330 or if it is receiving, going into sleep mode 00331 may take time. 00332 Loop until sleep mode reached. 00333 return 0 if 0K, other if error 00334 */ 00335 char canSleepWupMode ( 00336 UNS16 adrCAN /* First address of MSCANx registers */ 00337 ); 00338 00339 /* 00340 Test if one of the 5 mscan is in init mode. 00341 Return 00342 0 -> Not in init mode 00343 other -> In init mode 00344 */ 00345 char canTestInitMode ( 00346 UNS16 adrCAN /* First address of MSCANx registers */ 00347 ); 00348 00349 /* 00350 Test if one of the 5 mscan is in sleep mode. 00351 Return 00352 0 -> Not in sleep mode 00353 other -> In sleep mode 00354 */ 00355 char canTestSleepMode ( 00356 UNS16 adrCAN /* First address of MSCANx registers */ 00357 ); 00358 00359 00360 00361 #endif /*__CANDRIVER__*/ 00362