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