nico@215: nico@215: nico@215: CanFestival: drivers/hcs12/canOpenDriver.c Source File nico@215: nico@215: nico@215: nico@215: nico@215:
nico@215:
nico@215:
nico@215:
nico@215: nico@215:

canOpenDriver.c

Go to the documentation of this file.
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: 

Generated on Mon Jul 2 19:10:16 2007 for CanFestival by  nico@215: nico@215: doxygen 1.5.1
nico@215: nico@215: