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