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 etisserant@240: 00023 #define DEBUG_WAR_CONSOLE_ON etisserant@240: 00024 #define DEBUG_ERR_CONSOLE_ON nico@215: 00025 nico@215: 00026 #include <stddef.h> /* for NULL */ nico@215: 00027 nico@215: 00028 #include "../include/hcs12/asm-m68hc12/portsaccess.h" nico@215: 00029 #include "../include/hcs12/asm-m68hc12/ports_def.h" nico@215: 00030 #include "../include/hcs12/asm-m68hc12/ports.h" nico@215: 00031 #include "../include/data.h" nico@215: 00032 #include "../include/hcs12/applicfg.h" nico@215: 00033 #include "../include/hcs12/candriver.h" nico@215: 00034 #include "../include/hcs12/interrupt.h" nico@215: 00035 #include "../include/hcs12/canOpenDriver.h" nico@215: 00036 #include "../include/can.h" nico@215: 00037 #include "../include/objdictdef.h" nico@215: 00038 #include "../include/timer.h" nico@215: 00039 nico@215: 00040 nico@215: 00041 nico@215: 00042 nico@215: 00043 nico@215: 00044 etisserant@240: 00045 volatile static Message stackMsgRcv[NB_LINE_CAN][MAX_STACK_MSG_RCV]; etisserant@240: 00046 volatile static t_pointerStack ptrMsgRcv[NB_LINE_CAN]; nico@215: 00047 etisserant@240: 00048 volatile static TIMEVAL last_time_set = TIMEVAL_MAX; etisserant@240: 00049 static UNS8 timer_is_set = 0; nico@215: 00050 nico@215: 00051 /* Prototypes */ etisserant@240: 00052 UNS8 f_can_receive(UNS8 notused, Message *m); etisserant@240: 00053 UNS8 canSend(UNS8 notused, Message *m); etisserant@240: 00054 void __attribute__((interrupt)) timer4Hdl (void); nico@215: 00055 nico@215: 00056 #define max(a,b) a>b?a:b nico@215: 00057 nico@215: 00058 /******************************************************************************/ etisserant@240: 00059 void setTimer(TIMEVAL value) nico@215: 00060 { etisserant@240: 00061 IO_PORTS_16(TC4H) += value; nico@215: 00062 timer_is_set = 1; nico@215: 00063 } nico@215: 00064 nico@215: 00065 /******************************************************************************/ etisserant@240: 00066 TIMEVAL getElapsedTime() nico@215: 00067 { etisserant@240: 00068 return (IO_PORTS_16(TC4H) > last_time_set ? IO_PORTS_16(TC4H) - last_time_set : last_time_set - IO_PORTS_16(TC4H)); nico@215: 00069 } nico@215: 00070 nico@215: 00071 nico@215: 00072 /******************************************************************************/ etisserant@240: 00073 void resetTimer(void) nico@215: 00074 { nico@215: 00075 nico@215: 00076 } nico@215: 00077 nico@215: 00078 /******************************************************************************/ etisserant@240: 00079 void initTimer(void) nico@215: 00080 { etisserant@240: 00081 lock(); // Inhibition of interruptions nico@215: 00082 nico@215: 00083 // Configure the timer channel 4 etisserant@240: 00084 IO_PORTS_8(TIOS) |= 0x10; // Canal 4 in output etisserant@240: 00085 IO_PORTS_8(TCTL1) &= ~(0x01 + 0x02); // Canal 4 unconnected to pin output etisserant@240: 00086 IO_PORTS_8(TIE) |= 0x10; // allow interruption channel 4 etisserant@240: 00087 IO_PORTS_8(TSCR2) |= 0X05; // Pre-scaler = 32 nico@215: 00088 // If this value is changed, change must be done also nico@215: 00089 // in void __attribute__((interrupt)) timer4Hdl (void) nico@215: 00090 etisserant@240: 00091 IO_PORTS_8(TSCR1) |= 0x80; // Start timer etisserant@240: 00092 unlock(); // Allow interruptions nico@215: 00093 } nico@215: 00094 nico@215: 00095 /******************************************************************************/ etisserant@240: 00096 void __attribute__((interrupt)) timer4Hdl (void) nico@215: 00097 { etisserant@240: 00098 lock(); etisserant@240: 00099 last_time_set = IO_PORTS_16(TC4H); etisserant@240: 00100 IO_PORTS_8(TFLG1) = 0x10; // RAZ flag interruption timer channel 4 nico@215: 00101 // Compute the next event : When the timer reach the value of TC4, an interrupt is nico@215: 00102 // started nico@215: 00103 //IO_PORTS_16(TC4H) += 250; // To have an interruption every 1 ms nico@215: 00104 //timerInterrupt(0); nico@215: 00105 //MSG_WAR(0xFFFF, "timer4 IT", 0); nico@215: 00106 { nico@215: 00107 //MSG_WAR(0xFFFF, "t4 ", IO_PORTS_16(TCNTH) - IO_PORTS_16(TC4H)); nico@215: 00108 } etisserant@240: 00109 TimeDispatch(); etisserant@240: 00110 unlock(); nico@215: 00111 } nico@215: 00112 nico@215: 00113 nico@215: 00114 /******************************************************************************/ etisserant@240: 00115 void initSCI_0(void) nico@215: 00116 { etisserant@240: 00117 IO_PORTS_16(SCI0 + SCIBDH) = etisserant@240: 00118 ((1000000 / SERIAL_SCI0_BAUD_RATE) * BUS_CLOCK) >> 4 ; etisserant@240: 00119 IO_PORTS_8(SCI0 + SCICR1) = 0; // format 8N1 etisserant@240: 00120 IO_PORTS_8(SCI0 + SCICR2) = 0x08; // Transmit enable only nico@215: 00121 } nico@215: 00122 nico@215: 00123 /******************************************************************************/ etisserant@240: 00124 void initSCI_1(void) nico@215: 00125 { etisserant@240: 00126 IO_PORTS_16(SCI1 + SCIBDH) = etisserant@240: 00127 ((1000000 / SERIAL_SCI1_BAUD_RATE) * BUS_CLOCK) >> 4 ; etisserant@240: 00128 IO_PORTS_8(SCI1 + SCICR1) = 0; // format 8N1 etisserant@240: 00129 IO_PORTS_8(SCI1 + SCICR2) = 0x08; // Transmit enable only nico@215: 00130 } nico@215: 00131 nico@215: 00132 nico@215: 00133 /******************************************************************************/ nico@215: 00134 char * etisserant@240: 00135 hex_convert (char *buf, unsigned long value, char lastCar) nico@215: 00136 { nico@215: 00137 //Thanks to Stéphane Carrez for this function nico@215: 00138 char num[32]; nico@215: 00139 int pos; nico@215: 00140 nico@215: 00141 *buf++ = '0'; nico@215: 00142 *buf++ = 'x'; nico@215: 00143 nico@215: 00144 pos = 0; nico@215: 00145 while (value != 0) { nico@215: 00146 char c = value & 0x0F; nico@215: 00147 num[pos++] = "0123456789ABCDEF"[(unsigned) c]; nico@215: 00148 value = (value >> 4) & (0x0fffffffL); nico@215: 00149 } nico@215: 00150 if (pos == 0) nico@215: 00151 num[pos++] = '0'; nico@215: 00152 nico@215: 00153 while (--pos >= 0) nico@215: 00154 *buf++ = num[pos]; nico@215: 00155 nico@215: 00156 *buf++ = lastCar; nico@215: 00157 *buf = 0; nico@215: 00158 return buf; nico@215: 00159 } nico@215: 00160 nico@215: 00161 /******************************************************************************/ etisserant@240: 00162 void printSCI_str(char sci, const char * str) nico@215: 00163 { nico@215: 00164 char i = 0; nico@215: 00165 nico@215: 00166 while ((*(str + i) != 0) && (i < 0xFF)) { nico@215: 00167 if (*(str + i) == '\n') nico@215: 00168 { etisserant@240: 00169 while ((IO_PORTS_8(sci + SCISR1) & 0X80) == 0); // wait if buffer not empty etisserant@240: 00170 IO_PORTS_8(sci + SCIDRL) = 13; // return to start of line nico@215: 00171 } etisserant@240: 00172 while ((IO_PORTS_8(sci + SCISR1) & 0X80) == 0); // wait if buffer not empty etisserant@240: 00173 IO_PORTS_8(sci + SCIDRL) = *(str + i++); nico@215: 00174 } nico@215: 00175 nico@215: 00176 } nico@215: 00177 nico@215: 00178 /******************************************************************************/ etisserant@240: 00179 void printSCI_nbr(char sci, unsigned long nbr, char lastCar) nico@215: 00180 { nico@215: 00181 char strNbr[12]; etisserant@240: 00182 hex_convert(strNbr, nbr, lastCar); etisserant@240: 00183 printSCI_str(sci, strNbr); nico@215: 00184 } nico@215: 00185 nico@215: 00186 /******************************************************************************/ nico@215: 00187 // PLL 24 MHZ if quartz on board is 16 MHZ etisserant@240: 00188 void initPLL(void) nico@215: 00189 { etisserant@240: 00190 IO_PORTS_8(CLKSEL) &= ~0x80; // unselect the PLL etisserant@240: 00191 IO_PORTS_8(PLLCTL) |= 0X60; // PLL ON and bandwidth auto etisserant@240: 00192 IO_PORTS_8(SYNR) = 0x02; etisserant@240: 00193 IO_PORTS_8(REFDV) = 0x01; etisserant@240: 00194 while ((IO_PORTS_8(CRGFLG) & 0x08) == 0); etisserant@240: 00195 IO_PORTS_8(CLKSEL) |= 0x80; nico@215: 00196 } nico@215: 00197 nico@215: 00198 /******************************************************************************/ etisserant@240: 00199 void initHCS12(void) nico@215: 00200 { nico@215: 00201 nico@215: 00202 # ifdef USE_PLL etisserant@240: 00203 MSG_WAR(0x3620, "Use the PLL ", 0); etisserant@240: 00204 initPLL(); nico@215: 00205 # endif nico@215: 00206 nico@215: 00207 } nico@215: 00208 nico@215: 00209 /***************************************************************************/ etisserant@240: 00210 char canAddIdToFilter(UNS16 adrCAN, UNS8 nFilter, UNS16 id) nico@215: 00211 { etisserant@240: 00212 UNS8 fiMsb; etisserant@240: 00213 UNS8 fiLsb; etisserant@240: 00214 UNS8 idMsb = (UNS8) (id >> 3); etisserant@240: 00215 UNS8 idLsb = (UNS8) (id << 5); nico@215: 00216 etisserant@240: 00217 if (! canTestInitMode(adrCAN)) { nico@215: 00218 /* Error because not init mode */ etisserant@240: 00219 MSG_WAR(0X2600, "Not in init mode ", 0); nico@215: 00220 return 1; nico@215: 00221 } nico@215: 00222 switch (nFilter) { nico@215: 00223 case 0: etisserant@240: 00224 nFilter = CANIDAR0; /* First bank */ nico@215: 00225 break; nico@215: 00226 case 1: etisserant@240: 00227 nFilter = CANIDAR2; /* First bank */ nico@215: 00228 break; nico@215: 00229 case 2: etisserant@240: 00230 nFilter = CANIDAR4; /* Second bank */ nico@215: 00231 break; nico@215: 00232 case 3: etisserant@240: 00233 nFilter = CANIDAR6; /* Second bank */ nico@215: 00234 } etisserant@240: 00235 if (! IO_PORTS_16(adrCAN + nFilter)) { nico@215: 00236 /* if CANIDARx = 0 */ etisserant@240: 00237 IO_PORTS_8(adrCAN + nFilter) = idMsb; etisserant@240: 00238 IO_PORTS_8(adrCAN + nFilter + 1) = idLsb; nico@215: 00239 } etisserant@240: 00240 fiMsb = IO_PORTS_8(adrCAN + nFilter) ^ idMsb; etisserant@240: 00241 fiLsb = IO_PORTS_8(adrCAN + nFilter + 1) ^ idLsb; nico@215: 00242 /* address of CANIDMRx */ etisserant@240: 00243 IO_PORTS_8(adrCAN + nFilter + 4) = IO_PORTS_8(adrCAN + nFilter + 4) | fiMsb; etisserant@240: 00244 IO_PORTS_8(adrCAN + nFilter + 5) = IO_PORTS_8(adrCAN + nFilter + 5) | fiLsb; etisserant@240: 00245 IO_PORTS_8(adrCAN + nFilter + 5) |= 0x10; /* Not filtering on rtr value */ nico@215: 00246 return 0; nico@215: 00247 } nico@215: 00248 nico@215: 00249 /***************************************************************************/ etisserant@240: 00250 char canChangeFilter(UNS16 adrCAN, canBusFilterInit fi) nico@215: 00251 { nico@215: 00252 /* If not in init mode, go to sleep before going in init mode*/ etisserant@240: 00253 if (! canTestInitMode(adrCAN)) { etisserant@240: 00254 canSleepMode(adrCAN); etisserant@240: 00255 canInitMode(adrCAN); nico@215: 00256 } nico@215: 00257 //update the filters configuration etisserant@240: 00258 canInitFilter(adrCAN, fi); etisserant@240: 00259 canInitModeQ(adrCAN); etisserant@240: 00260 canSleepModeQ(adrCAN); etisserant@240: 00261 canSetInterrupt(adrCAN); nico@215: 00262 return 0; nico@215: 00263 } nico@215: 00264 nico@215: 00265 /***************************************************************************/ etisserant@240: 00266 char canEnable(UNS16 adrCAN) nico@215: 00267 { nico@215: 00268 /* Register CANCTL1 nico@215: 00269 bit 7 : 1 MSCAN enabled nico@215: 00270 Other bits : default reset values nico@215: 00271 */ etisserant@240: 00272 IO_PORTS_8(adrCAN + CANCTL1) = 0X80; nico@215: 00273 return 0; nico@215: 00274 } nico@215: 00275 nico@215: 00276 /***************************************************************************/ etisserant@240: 00277 char canInit(UNS16 adrCAN, canBusInit bi) nico@215: 00278 { nico@215: 00279 /* If not in init mode, go to sleep before going in init mode*/ etisserant@240: 00280 if (! canTestInitMode(adrCAN)) { etisserant@240: 00281 canSleepMode(adrCAN); etisserant@240: 00282 canInitMode(adrCAN); nico@215: 00283 } nico@215: 00284 etisserant@240: 00285 canEnable(adrCAN); /* Does nothing if already enable */ nico@215: 00286 /* The most secure way to go in init mode : put before MSCAN in sleep mode */ nico@215: 00287 //canSleepMode(adrCAN); nico@215: 00288 /* Put MSCAN in Init mode */ nico@215: 00289 //canInitMode(adrCAN); etisserant@240: 00290 canInitClock(adrCAN, bi.clk); nico@215: 00291 /* Init CANCTL1 register. Must be in init mode */ etisserant@240: 00292 IO_PORTS_8(adrCAN + CANCTL1) &=0xC4;// 0xCB; /* Clr the bits that may be modified */ etisserant@240: 00293 IO_PORTS_8(adrCAN + CANCTL1) = (bi.cane << 7) | (bi.loopb << 5 ) | etisserant@240: 00294 (bi.listen << 4) | (bi.wupm << 2); nico@215: 00295 /* Initialize the filters for received msgs */ nico@215: 00296 /* We should decide to accept all the msgs */ etisserant@240: 00297 canInitFilter(adrCAN, bi.fi); nico@215: 00298 /* Before to modify CANCTL0, we must leave the init mode */ etisserant@240: 00299 canInitModeQ(adrCAN); nico@215: 00300 /* Init CANCTL0 register. MSCAN must not be in init mode */ nico@215: 00301 /* Do not change the value of wupe (should be 0) and slprq (should be 1) */ nico@215: 00302 /* Do not change the value of initrq (should be 0) */ nico@215: 00303 /* rxfrm is cleared, mupe also (should be before)*/ etisserant@240: 00304 IO_PORTS_8(adrCAN + CANCTL0) &= 0x53; /* Clr the bits that may be modified */ etisserant@240: 00305 IO_PORTS_8(adrCAN + CANCTL0) = (bi.cswai << 5) | (bi.time << 3); etisserant@240: 00306 canSetInterrupt(adrCAN); etisserant@240: 00307 canInitModeQ(adrCAN); /* Leave the init mode */ etisserant@240: 00308 canSleepModeQ(adrCAN); /* Leave the sleep mode */ nico@215: 00309 return 0; nico@215: 00310 } nico@215: 00311 nico@215: 00312 /***************************************************************************/ etisserant@240: 00313 char canInitClock(UNS16 adrCAN, canBusTime clk) nico@215: 00314 { etisserant@240: 00315 if (! canTestInitMode(adrCAN)) { nico@215: 00316 /* Not in Init mode */ etisserant@240: 00317 MSG_WAR(0X2601, "not in init mode ", 0); nico@215: 00318 return 1; nico@215: 00319 } nico@215: 00320 /* Set or reset CLKSRC (register CANCTL1). Does not change the other bits*/ etisserant@240: 00321 clk.clksrc = clk.clksrc << 6; etisserant@240: 00322 IO_PORTS_8(adrCAN + CANCTL1) &= 0xBF; etisserant@240: 00323 IO_PORTS_8(adrCAN + CANCTL1) |= clk.clksrc; nico@215: 00324 /* Build the CANBTR0 register */ etisserant@240: 00325 IO_PORTS_8(adrCAN + CANBTR0) = 0x00; /* Clear before changes */ etisserant@240: 00326 IO_PORTS_8(adrCAN + CANBTR0) = (clk.sjw << 6) | (clk.brp); nico@215: 00327 /* Build the CANBTR1 register */ etisserant@240: 00328 IO_PORTS_8(adrCAN + CANBTR1) = 0x00; /* Clear before changes */ etisserant@240: 00329 IO_PORTS_8(adrCAN + CANBTR1) = (clk.samp << 7) | (clk.tseg2 << 4) | etisserant@240: 00330 (clk.tseg1); nico@215: 00331 return 0; nico@215: 00332 } nico@215: 00333 nico@215: 00334 /***************************************************************************/ etisserant@240: 00335 char canInit1Filter(UNS16 adrCAN, UNS8 nFilter, UNS16 ar, UNS16 mr) nico@215: 00336 { etisserant@240: 00337 if (! canTestInitMode(adrCAN)) { nico@215: 00338 /* Error because not init mode */ etisserant@240: 00339 MSG_WAR(0X2602, "not in init mode ", 0); nico@215: 00340 return 1; nico@215: 00341 } nico@215: 00342 switch (nFilter) { nico@215: 00343 case 0: etisserant@240: 00344 nFilter = CANIDAR0; /* First bank */ nico@215: 00345 break; nico@215: 00346 case 1: etisserant@240: 00347 nFilter = CANIDAR2; /* First bank */ nico@215: 00348 break; nico@215: 00349 case 2: etisserant@240: 00350 nFilter = CANIDAR4; /* Second bank */ nico@215: 00351 break; nico@215: 00352 case 3: etisserant@240: 00353 nFilter = CANIDAR6; /* Second bank */ nico@215: 00354 } nico@215: 00355 /* address of CANIDARx */ etisserant@240: 00356 IO_PORTS_8(adrCAN + nFilter) = (UNS8) (ar >> 8); etisserant@240: 00357 IO_PORTS_8(adrCAN + nFilter + 1) = (UNS8) (ar); etisserant@240: 00358 IO_PORTS_8(adrCAN + nFilter + 4) = (UNS8) (mr >> 8); etisserant@240: 00359 IO_PORTS_8(adrCAN + nFilter + 5) = (UNS8) (mr); nico@215: 00360 return 0; nico@215: 00361 } nico@215: 00362 nico@215: 00363 /***************************************************************************/ etisserant@240: 00364 char canInitFilter(UNS16 adrCAN, canBusFilterInit fi) nico@215: 00365 { etisserant@240: 00366 if (! canTestInitMode(adrCAN)) { nico@215: 00367 /* Error because not init mode */ etisserant@240: 00368 MSG_WAR(0X2603, "not in init mode ", 0); nico@215: 00369 return 1; nico@215: 00370 } etisserant@240: 00371 IO_PORTS_8(adrCAN + CANIDAC) = fi.idam << 4; etisserant@240: 00372 IO_PORTS_8(adrCAN + CANIDAR0) = fi.canidar0; etisserant@240: 00373 IO_PORTS_8(adrCAN + CANIDMR0) = fi.canidmr0; etisserant@240: 00374 IO_PORTS_8(adrCAN + CANIDAR1) = fi.canidar1; etisserant@240: 00375 IO_PORTS_8(adrCAN + CANIDMR1) = fi.canidmr1; etisserant@240: 00376 IO_PORTS_8(adrCAN + CANIDAR2) = fi.canidar2; etisserant@240: 00377 IO_PORTS_8(adrCAN + CANIDMR2) = fi.canidmr2; etisserant@240: 00378 IO_PORTS_8(adrCAN + CANIDAR3) = fi.canidar3; etisserant@240: 00379 IO_PORTS_8(adrCAN + CANIDMR3) = fi.canidmr3; etisserant@240: 00380 IO_PORTS_8(adrCAN + CANIDAR4) = fi.canidar4; etisserant@240: 00381 IO_PORTS_8(adrCAN + CANIDMR4) = fi.canidmr4; etisserant@240: 00382 IO_PORTS_8(adrCAN + CANIDAR5) = fi.canidar5; etisserant@240: 00383 IO_PORTS_8(adrCAN + CANIDMR5) = fi.canidmr5; etisserant@240: 00384 IO_PORTS_8(adrCAN + CANIDAR6) = fi.canidar6; etisserant@240: 00385 IO_PORTS_8(adrCAN + CANIDMR6) = fi.canidmr6; etisserant@240: 00386 IO_PORTS_8(adrCAN + CANIDAR7) = fi.canidar7; etisserant@240: 00387 IO_PORTS_8(adrCAN + CANIDMR7) = fi.canidmr7; nico@215: 00388 return 0; nico@215: 00389 } nico@215: 00390 nico@215: 00391 /***************************************************************************/ etisserant@240: 00392 char canInitMode(UNS16 adrCAN) nico@215: 00393 { etisserant@240: 00394 IO_PORTS_8(adrCAN + CANCTL0) |= 0x01; /* Set the bit INITRQ */ etisserant@240: 00395 while (! canTestInitMode(adrCAN)) { nico@215: 00396 } nico@215: 00397 return 0; nico@215: 00398 } nico@215: 00399 nico@215: 00400 /***************************************************************************/ etisserant@240: 00401 char canInitModeQ(UNS16 adrCAN) nico@215: 00402 { etisserant@240: 00403 IO_PORTS_8(adrCAN + CANCTL0) &= 0xFE; /* Clear the bit INITRQ */ etisserant@240: 00404 while (canTestInitMode(adrCAN)) { nico@215: 00405 } nico@215: 00406 return 0; nico@215: 00407 } nico@215: 00408 nico@215: 00409 /***************************************************************************/ etisserant@240: 00410 char canMsgTransmit(UNS16 adrCAN, Message msg) nico@215: 00411 { nico@215: 00412 /* Remind : only CAN A msg implemented. ie id on 11 bits, not 29 */ etisserant@240: 00413 UNS8 cantflg; etisserant@240: 00414 UNS8 i; nico@215: 00415 /* Looking for a free buffer */ etisserant@240: 00416 cantflg = IO_PORTS_8(adrCAN + CANTFLG); nico@215: 00417 if ( cantflg == 0) { /* all the TXEx are set */ etisserant@240: 00418 MSG_WAR(0X2604, "No buffer free. Msg to transmit is losted ", 0); nico@215: 00419 return 1; /* No buffer free */ nico@215: 00420 } nico@215: 00421 else{ nico@215: 00422 /* Selecting a buffer */ etisserant@240: 00423 IO_PORTS_8(adrCAN + CANTBSEL) = cantflg; nico@215: 00424 /* We put ide = 0 because id is on 11 bits only */ etisserant@240: 00425 IO_PORTS_8(adrCAN + CANTRSID) = (UNS8)(msg.cob_id.w >> 3); etisserant@240: 00426 IO_PORTS_8(adrCAN + CANTRSID + 1) = (UNS8)((msg.cob_id.w << 5)| etisserant@240: 00427 (msg.rtr << 4)); nico@215: 00428 etisserant@240: 00429 IO_PORTS_8(adrCAN + CANTRSLEN) = msg.len & 0X0F; nico@215: 00430 /* For the priority, we put the highter bits of the cob_id */ etisserant@240: 00431 IO_PORTS_8(adrCAN + CANTRSPRI) = IO_PORTS_8(adrCAN + CANTRSID); etisserant@240: 00432 for (i = 0 ; i < msg.len ; i++) { etisserant@240: 00433 IO_PORTS_8(adrCAN + CANTRSDTA + i) = msg.data[i]; nico@215: 00434 } nico@215: 00435 /* Transmitting the message */ etisserant@240: 00436 cantflg = IO_PORTS_8(adrCAN + CANTBSEL);/* to know which buf is selected */ etisserant@240: 00437 IO_PORTS_8(adrCAN + CANTBSEL) = 0x00; etisserant@240: 00438 IO_PORTS_8(adrCAN + CANTFLG) = cantflg; /* Ready to transmit ! */ nico@215: 00439 nico@215: 00440 } nico@215: 00441 return 0; nico@215: 00442 } nico@215: 00443 nico@215: 00444 /***************************************************************************/ etisserant@240: 00445 char canSetInterrupt(UNS16 adrCAN) nico@215: 00446 { etisserant@240: 00447 IO_PORTS_8(adrCAN + CANRIER) = 0X01; /* Allow interruptions on receive */ etisserant@240: 00448 IO_PORTS_8(adrCAN + CANTIER) = 0X00; /* disallow interruptions on transmit */ nico@215: 00449 return 0; nico@215: 00450 } nico@215: 00451 /***************************************************************************/ etisserant@240: 00452 char canSleepMode(UNS16 adrCAN) nico@215: 00453 { etisserant@240: 00454 IO_PORTS_8(adrCAN + CANCTL0) &= 0xFB; /* clr the bit WUPE to avoid a wake-up*/ etisserant@240: 00455 IO_PORTS_8(adrCAN + CANCTL0) |= 0x02; /* Set the bit SLPRQ. go to Sleep !*/ nico@215: 00456 nico@215: 00457 // IO_PORTS_8(adrCAN + CANCTL1) |= 0x04; nico@215: 00458 // IO_PORTS_8(adrCAN + CANCTL0) |= 0x02; /* Set the bit SLPRQ */ etisserant@240: 00459 while ( ! canTestSleepMode(adrCAN)) { nico@215: 00460 } nico@215: 00461 nico@215: 00462 return 0; nico@215: 00463 } nico@215: 00464 nico@215: 00465 /***************************************************************************/ etisserant@240: 00466 char canSleepModeQ(UNS16 adrCAN) nico@215: 00467 { etisserant@240: 00468 if (canTestInitMode(adrCAN)) { nico@215: 00469 /* Error because in init mode */ etisserant@240: 00470 MSG_WAR(0X2606, "not in init mode ", 0); nico@215: 00471 return 1; nico@215: 00472 } etisserant@240: 00473 IO_PORTS_8(adrCAN + CANCTL0) &= 0xFD; /* clr the bit SLPRQ */ etisserant@240: 00474 while ( canTestSleepMode(adrCAN)) { nico@215: 00475 } nico@215: 00476 return 0; nico@215: 00477 } nico@215: 00478 nico@215: 00479 /***************************************************************************/ etisserant@240: 00480 char canSleepWupMode(UNS16 adrCAN) nico@215: 00481 { etisserant@240: 00482 if (canTestInitMode(adrCAN)) { etisserant@240: 00483 MSG_WAR(0X2607, "not in init mode ", 0); nico@215: 00484 return 1; nico@215: 00485 } etisserant@240: 00486 IO_PORTS_8(adrCAN + CANCTL0) |= 0x06; /* Set the bits WUPE & SLPRQ */ etisserant@240: 00487 while ( ! canTestSleepMode(adrCAN)) { nico@215: 00488 } nico@215: 00489 return 0; nico@215: 00490 } nico@215: 00491 nico@215: 00492 /***************************************************************************/ etisserant@240: 00493 char canTestInitMode(UNS16 adrCAN) nico@215: 00494 { etisserant@240: 00495 return IO_PORTS_8(adrCAN + CANCTL1) & 0x01; /* Test the bit INITAK */ nico@215: 00496 } nico@215: 00497 nico@215: 00498 /***************************************************************************/ etisserant@240: 00499 char canTestSleepMode(UNS16 adrCAN) nico@215: 00500 { etisserant@240: 00501 return IO_PORTS_8(adrCAN + CANCTL1) & 0x02; /* Test the bit SLPAK */ nico@215: 00502 } nico@215: 00503 nico@215: 00504 /***************************************************************************/ etisserant@240: 00505 UNS8 canSend(UNS8 notused, Message *m) nico@215: 00506 { etisserant@240: 00507 canMsgTransmit(CANOPEN_LINE_NUMBER_USED, *m); nico@215: 00508 return 0; nico@215: 00509 } nico@215: 00510 nico@215: 00511 nico@215: 00512 /**************************************************************************/ etisserant@240: 00513 UNS8 f_can_receive(UNS8 notused, Message *msgRcv) nico@215: 00514 { etisserant@240: 00515 UNS8 i, j; nico@215: 00516 etisserant@240: 00517 switch (CANOPEN_LINE_NUMBER_USED) { etisserant@240: 00518 case CAN0 : j = 0; break; etisserant@240: 00519 case CAN1 : j = 1; break; etisserant@240: 00520 case CAN2 : j = 2; break; etisserant@240: 00521 case CAN3 : j = 3; break; etisserant@240: 00522 case CAN4 : j = 4; break; nico@215: 00523 } nico@215: 00524 nico@215: 00525 /* See if a message is pending in the stack */ nico@215: 00526 if (ptrMsgRcv[j].r == ptrMsgRcv[j].w) nico@215: 00527 return 0x0; // No new message nico@215: 00528 nico@215: 00529 /* Increment the reading pointer of the stack */ etisserant@240: 00530 if (ptrMsgRcv[j].r == (MAX_STACK_MSG_RCV - 1)) etisserant@240: 00531 ptrMsgRcv[j].r = 0; nico@215: 00532 else etisserant@240: 00533 ptrMsgRcv[j].r ++; nico@215: 00534 nico@215: 00535 /* Store the message from the stack*/ etisserant@240: 00536 msgRcv->cob_id.w = stackMsgRcv[j][ptrMsgRcv[j].r].cob_id.w; etisserant@240: 00537 msgRcv->len = stackMsgRcv[j][ptrMsgRcv[j].r].len; etisserant@240: 00538 msgRcv->rtr = stackMsgRcv[j][ptrMsgRcv[j].r].rtr; etisserant@240: 00539 for (i = 0 ; i < stackMsgRcv[j][ptrMsgRcv[j].r].len ; i++) etisserant@240: 00540 msgRcv->data[i] = stackMsgRcv[j][ptrMsgRcv[j].r].data[i]; nico@215: 00541 return 0xFF; nico@215: 00542 } nico@215: 00543 nico@215: 00544 nico@215: 00545 /****************************************************************************** nico@215: 00546 ******************************* CAN INTERRUPT *******************************/ nico@215: 00547 etisserant@240: 00548 void __attribute__((interrupt)) can0HdlTra (void) nico@215: 00549 { nico@215: 00550 nico@215: 00551 } nico@215: 00552 etisserant@240: 00553 void __attribute__((interrupt)) can0HdlRcv (void) nico@215: 00554 { etisserant@240: 00555 UNS8 i; etisserant@240: 00556 lock(); etisserant@240: 00557 IO_PORTS_8(PORTB) &= ~ 0x40; // led 6 port B : ON etisserant@240: 00558 UNS8 NewPtrW; nico@215: 00559 /* We are obliged to save the message while the interruption is pending */ nico@215: 00560 /* Increment the writing stack pointer before writing the msg */ etisserant@240: 00561 if (ptrMsgRcv[0].w == (MAX_STACK_MSG_RCV - 1)) nico@215: 00562 NewPtrW = 0; nico@215: 00563 else etisserant@240: 00564 NewPtrW = ptrMsgRcv[0].w + 1; nico@215: 00565 nico@215: 00566 if (NewPtrW == ptrMsgRcv[0].r) { nico@215: 00567 /* The stack is full. The last msg received before this one is lost */ etisserant@240: 00568 MSG_WAR(0X1620, "Stack for received msg is full", 0); nico@215: 00569 //IO_PORTS_8(PORTB) &= ~0x40; // led 6 : ON (for debogue) nico@215: 00570 } nico@215: 00571 else etisserant@240: 00572 ptrMsgRcv[0].w = NewPtrW; nico@215: 00573 nico@215: 00574 /* Store the message */ etisserant@240: 00575 stackMsgRcv[0][ptrMsgRcv[0].w].cob_id.w = IO_PORTS_16(CAN0 + CANRCVID) >> 5; etisserant@240: 00576 stackMsgRcv[0][ptrMsgRcv[0].w].len = IO_PORTS_8(CAN0 + CANRCVLEN) & 0x0F; etisserant@240: 00577 stackMsgRcv[0][ptrMsgRcv[0].w].rtr = (IO_PORTS_8(CAN0 + CANRCVID + 1) >> 4) & 0x01; etisserant@240: 00578 for (i = 0 ; i < stackMsgRcv[0][ptrMsgRcv[0].w].len ; i++) etisserant@240: 00579 stackMsgRcv[0][ptrMsgRcv[0].w].data[i] = IO_PORTS_8(CAN0 + CANRCVDTA + i); nico@215: 00580 nico@215: 00581 // The message is stored , so nico@215: 00582 // we can now release the receive foreground buffer nico@215: 00583 // and acknowledge the interruption etisserant@240: 00584 IO_PORTS_8(CAN0 + CANRFLG) |= 0x01; nico@215: 00585 // Not very usefull etisserant@240: 00586 IO_PORTS_8(CAN0 + CANCTL0) |= 0x80; etisserant@240: 00587 IO_PORTS_8(PORTB) |= 0x40; // led 6 port B : OFF etisserant@240: 00588 unlock(); nico@215: 00589 } nico@215: 00590 etisserant@240: 00591 void __attribute__((interrupt)) can0HdlWup (void) nico@215: 00592 { nico@215: 00593 nico@215: 00594 } nico@215: 00595 etisserant@240: 00596 void __attribute__((interrupt)) can0HdlErr (void) nico@215: 00597 { nico@215: 00598 nico@215: 00599 } nico@215: 00600 etisserant@240: 00601 void __attribute__((interrupt)) can1HdlTra (void) nico@215: 00602 { nico@215: 00603 nico@215: 00604 } nico@215: 00605 etisserant@240: 00606 void __attribute__((interrupt)) can1HdlRcv (void) nico@215: 00607 { etisserant@240: 00608 UNS8 i; etisserant@240: 00609 lock(); etisserant@240: 00610 UNS8 NewPtrW; nico@215: 00611 /* We are obliged to save the message while the interruption is pending */ nico@215: 00612 /* Increment the writing stack pointer before writing the msg */ etisserant@240: 00613 if (ptrMsgRcv[1].w == (MAX_STACK_MSG_RCV - 1)) nico@215: 00614 NewPtrW = 0; nico@215: 00615 else etisserant@240: 00616 NewPtrW = ptrMsgRcv[1].w + 1; nico@215: 00617 nico@215: 00618 if (NewPtrW == ptrMsgRcv[1].r) { nico@215: 00619 /* The stack is full. The last msg received before this one is lost */ etisserant@240: 00620 MSG_WAR(0X2620, "Stack for received msg is full", 0); nico@215: 00621 } nico@215: 00622 else etisserant@240: 00623 ptrMsgRcv[1].w = NewPtrW; nico@215: 00624 nico@215: 00625 /* Store the message */ etisserant@240: 00626 stackMsgRcv[1][ptrMsgRcv[1].w].cob_id.w = IO_PORTS_16(CAN1 + CANRCVID) >> 5; etisserant@240: 00627 stackMsgRcv[1][ptrMsgRcv[1].w].len = IO_PORTS_8(CAN1 + CANRCVLEN) & 0x0F; etisserant@240: 00628 stackMsgRcv[0][ptrMsgRcv[0].w].rtr = (IO_PORTS_8(CAN1 + CANRCVID + 1) >> 4) & 0x01; etisserant@240: 00629 for (i = 0 ; i < stackMsgRcv[1][ptrMsgRcv[1].w].len ; i++) etisserant@240: 00630 stackMsgRcv[1][ptrMsgRcv[1].w].data[i] = IO_PORTS_8(CAN1 + CANRCVDTA + i); nico@215: 00631 nico@215: 00632 // The message is stored , so nico@215: 00633 // we can now release the receive foreground buffer nico@215: 00634 // and acknowledge the interruption etisserant@240: 00635 IO_PORTS_8(CAN1 + CANRFLG) |= 0x01; nico@215: 00636 // Not very usefull etisserant@240: 00637 IO_PORTS_8(CAN1 + CANCTL0) |= 0x80; etisserant@240: 00638 unlock(); nico@215: 00639 } nico@215: 00640 etisserant@240: 00641 void __attribute__((interrupt)) can1HdlWup (void) nico@215: 00642 { nico@215: 00643 nico@215: 00644 } nico@215: 00645 etisserant@240: 00646 void __attribute__((interrupt)) can1HdlErr (void) nico@215: 00647 { nico@215: 00648 nico@215: 00649 } nico@215: 00650 etisserant@240: 00651 void __attribute__((interrupt)) can2HdlTra (void) nico@215: 00652 { nico@215: 00653 nico@215: 00654 } nico@215: 00655 etisserant@240: 00656 void __attribute__((interrupt)) can2HdlRcv (void) nico@215: 00657 { nico@215: 00658 nico@215: 00659 } nico@215: 00660 etisserant@240: 00661 void __attribute__((interrupt)) can2HdlWup (void) nico@215: 00662 { nico@215: 00663 nico@215: 00664 } nico@215: 00665 etisserant@240: 00666 void __attribute__((interrupt)) can2HdlErr (void) nico@215: 00667 { nico@215: 00668 nico@215: 00669 } nico@215: 00670 etisserant@240: 00671 void __attribute__((interrupt)) can3HdlTra (void) nico@215: 00672 { nico@215: 00673 nico@215: 00674 } nico@215: 00675 etisserant@240: 00676 void __attribute__((interrupt)) can3HdlRcv (void) nico@215: 00677 { nico@215: 00678 nico@215: 00679 } nico@215: 00680 etisserant@240: 00681 void __attribute__((interrupt)) can3HdlWup (void) nico@215: 00682 { nico@215: 00683 nico@215: 00684 } nico@215: 00685 etisserant@240: 00686 void __attribute__((interrupt)) can3HdlErr (void) nico@215: 00687 { nico@215: 00688 nico@215: 00689 } nico@215: 00690 etisserant@240: 00691 void __attribute__((interrupt)) can4HdlTra (void) nico@215: 00692 { nico@215: 00693 nico@215: 00694 } nico@215: 00695 etisserant@240: 00696 void __attribute__((interrupt)) can4HdlRcv (void) nico@215: 00697 { nico@215: 00698 nico@215: 00699 } nico@215: 00700 etisserant@240: 00701 void __attribute__((interrupt)) can4HdlWup (void) nico@215: 00702 { nico@215: 00703 nico@215: 00704 } nico@215: 00705 etisserant@240: 00706 void __attribute__((interrupt)) can4HdlErr (void) nico@215: 00707 { nico@215: 00708 nico@215: 00709 } nico@215: 00710 nico@215: 00711 nico@215: 00712 etisserant@240: