etisserant@0: /* etisserant@0: This file is part of CanFestival, a library implementing CanOpen Stack. etisserant@0: etisserant@0: Copyright (C): Edouard TISSERANT and Francis DUPIN etisserant@0: etisserant@0: See COPYING file for copyrights details. etisserant@0: etisserant@0: This library is free software; you can redistribute it and/or etisserant@0: modify it under the terms of the GNU Lesser General Public etisserant@0: License as published by the Free Software Foundation; either etisserant@0: version 2.1 of the License, or (at your option) any later version. etisserant@0: etisserant@0: This library is distributed in the hope that it will be useful, etisserant@0: but WITHOUT ANY WARRANTY; without even the implied warranty of etisserant@0: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU etisserant@0: Lesser General Public License for more details. etisserant@0: etisserant@0: You should have received a copy of the GNU Lesser General Public etisserant@0: License along with this library; if not, write to the Free Software etisserant@0: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA etisserant@0: */ etisserant@0: etisserant@0: #define DEBUG_WAR_CONSOLE_ON etisserant@0: #define DEBUG_ERR_CONSOLE_ON etisserant@0: etisserant@0: #include /* for NULL */ etisserant@0: etisserant@0: #include "../include/hcs12/asm-m68hc12/portsaccess.h" etisserant@0: #include "../include/hcs12/asm-m68hc12/ports_def.h" etisserant@0: #include "../include/hcs12/asm-m68hc12/ports.h" etisserant@0: #include "../include/hcs12/applicfg.h" etisserant@0: #include "../include/hcs12/candriver.h" etisserant@0: #include "../include/hcs12/interrupt.h" etisserant@0: #include "../include/hcs12/canOpenDriver.h" etisserant@0: etisserant@0: #include "../include/can.h" etisserant@0: #include "../include/objdictdef.h" etisserant@0: #include "../include/timer.h" etisserant@0: etisserant@0: etisserant@0: etisserant@0: etisserant@0: etisserant@0: etisserant@0: volatile static Message stackMsgRcv[NB_LINE_CAN][MAX_STACK_MSG_RCV]; etisserant@0: volatile static t_pointerStack ptrMsgRcv[NB_LINE_CAN]; etisserant@0: etisserant@0: volatile static TIMEVAL last_time_set = TIMEVAL_MAX; etisserant@0: static UNS8 timer_is_set = 0; etisserant@0: etisserant@0: /* Prototypes */ etisserant@0: UNS8 f_can_receive(UNS8 notused, Message *m); etisserant@0: UNS8 canSend(UNS8 notused, Message *m); etisserant@0: void __attribute__((interrupt)) timer4Hdl (void); etisserant@0: etisserant@0: #define max(a,b) a>b?a:b etisserant@0: etisserant@0: /******************************************************************************/ etisserant@0: void setTimer(TIMEVAL value) etisserant@0: { etisserant@0: IO_PORTS_16(TC4H) += value; etisserant@0: timer_is_set = 1; etisserant@0: } etisserant@0: etisserant@0: /******************************************************************************/ etisserant@0: TIMEVAL getElapsedTime() etisserant@0: { etisserant@0: return (IO_PORTS_16(TC4H) > last_time_set ? IO_PORTS_16(TC4H) - last_time_set : last_time_set - IO_PORTS_16(TC4H)); etisserant@0: } etisserant@0: etisserant@0: etisserant@0: /******************************************************************************/ etisserant@0: void resetTimer(void) etisserant@0: { etisserant@0: etisserant@0: } etisserant@0: etisserant@0: /******************************************************************************/ etisserant@0: void initTimer(void) etisserant@0: { etisserant@0: lock(); // Inhibition of interruptions etisserant@0: etisserant@0: // Configure the timer channel 4 etisserant@0: IO_PORTS_8(TIOS) |= 0x10; // Canal 4 in output etisserant@0: IO_PORTS_8(TCTL1) &= ~(0x01 + 0x02); // Canal 4 unconnected to pin output etisserant@0: IO_PORTS_8(TIE) |= 0x10; // allow interruption channel 4 etisserant@0: IO_PORTS_8(TSCR2) |= 0X05; // Pre-scaler = 32 etisserant@0: // If this value is changed, change must be done also etisserant@0: // in void __attribute__((interrupt)) timer4Hdl (void) etisserant@0: etisserant@0: IO_PORTS_8(TSCR1) |= 0x80; // Start timer etisserant@0: unlock(); // Allow interruptions etisserant@0: } etisserant@0: etisserant@0: /******************************************************************************/ etisserant@0: void __attribute__((interrupt)) timer4Hdl (void) etisserant@0: { etisserant@0: lock(); etisserant@0: last_time_set = IO_PORTS_16(TC4H); etisserant@0: IO_PORTS_8(TFLG1) = 0x10; // RAZ flag interruption timer channel 4 etisserant@0: // Compute the next event : When the timer reach the value of TC4, an interrupt is etisserant@0: // started etisserant@0: //IO_PORTS_16(TC4H) += 250; // To have an interruption every 1 ms etisserant@0: //timerInterrupt(0); etisserant@0: //MSG_WAR(0xFFFF, "timer4 IT", 0); etisserant@0: { etisserant@0: //MSG_WAR(0xFFFF, "t4 ", IO_PORTS_16(TCNTH) - IO_PORTS_16(TC4H)); etisserant@0: } etisserant@0: TimeDispatch(); etisserant@0: unlock(); etisserant@0: } etisserant@0: etisserant@0: etisserant@0: /******************************************************************************/ etisserant@0: void initSCI_0(void) etisserant@0: { etisserant@0: IO_PORTS_16(SCI0 + SCIBDH) = etisserant@0: ((1000000 / SERIAL_SCI0_BAUD_RATE) * BUS_CLOCK) >> 4 ; etisserant@0: IO_PORTS_8(SCI0 + SCICR1) = 0; // format 8N1 etisserant@0: IO_PORTS_8(SCI0 + SCICR2) = 0x08; // Transmit enable only etisserant@0: } etisserant@0: etisserant@0: /******************************************************************************/ etisserant@0: void initSCI_1(void) etisserant@0: { etisserant@0: IO_PORTS_16(SCI1 + SCIBDH) = etisserant@0: ((1000000 / SERIAL_SCI1_BAUD_RATE) * BUS_CLOCK) >> 4 ; etisserant@0: IO_PORTS_8(SCI1 + SCICR1) = 0; // format 8N1 etisserant@0: IO_PORTS_8(SCI1 + SCICR2) = 0x08; // Transmit enable only etisserant@0: } etisserant@0: etisserant@0: etisserant@0: /******************************************************************************/ etisserant@0: char * etisserant@0: hex_convert (char *buf, unsigned long value, char lastCar) etisserant@0: { etisserant@0: //Thanks to Stéphane Carrez for this function etisserant@0: char num[32]; etisserant@0: int pos; etisserant@0: etisserant@0: *buf++ = '0'; etisserant@0: *buf++ = 'x'; etisserant@0: etisserant@0: pos = 0; etisserant@0: while (value != 0) { etisserant@0: char c = value & 0x0F; etisserant@0: num[pos++] = "0123456789ABCDEF"[(unsigned) c]; etisserant@0: value = (value >> 4) & (0x0fffffffL); etisserant@0: } etisserant@0: if (pos == 0) etisserant@0: num[pos++] = '0'; etisserant@0: etisserant@0: while (--pos >= 0) etisserant@0: *buf++ = num[pos]; etisserant@0: etisserant@0: *buf++ = lastCar; etisserant@0: *buf = 0; etisserant@0: return buf; etisserant@0: } etisserant@0: etisserant@0: /******************************************************************************/ etisserant@0: void printSCI_str(char sci, const char * str) etisserant@0: { etisserant@0: char i = 0; etisserant@0: etisserant@0: while ((*(str + i) != 0) && (i < 0xFF)) { etisserant@0: if (*(str + i) == '\n') etisserant@0: { etisserant@0: while ((IO_PORTS_8(sci + SCISR1) & 0X80) == 0); // wait if buffer not empty etisserant@0: IO_PORTS_8(sci + SCIDRL) = 13; // return to start of line etisserant@0: } etisserant@0: while ((IO_PORTS_8(sci + SCISR1) & 0X80) == 0); // wait if buffer not empty etisserant@0: IO_PORTS_8(sci + SCIDRL) = *(str + i++); etisserant@0: } etisserant@0: etisserant@0: } etisserant@0: etisserant@0: /******************************************************************************/ etisserant@0: void printSCI_nbr(char sci, unsigned long nbr, char lastCar) etisserant@0: { etisserant@0: char strNbr[12]; etisserant@0: hex_convert(strNbr, nbr, lastCar); etisserant@0: printSCI_str(sci, strNbr); etisserant@0: } etisserant@0: etisserant@0: /******************************************************************************/ etisserant@0: // PLL 24 MHZ if quartz on board is 16 MHZ etisserant@0: void initPLL(void) etisserant@0: { etisserant@0: IO_PORTS_8(CLKSEL) &= ~0x80; // unselect the PLL etisserant@0: IO_PORTS_8(PLLCTL) |= 0X60; // PLL ON and bandwidth auto etisserant@0: IO_PORTS_8(SYNR) = 0x02; etisserant@0: IO_PORTS_8(REFDV) = 0x01; etisserant@0: while ((IO_PORTS_8(CRGFLG) & 0x08) == 0); etisserant@0: IO_PORTS_8(CLKSEL) |= 0x80; etisserant@0: } etisserant@0: etisserant@0: /******************************************************************************/ etisserant@0: void initHCS12(void) etisserant@0: { etisserant@0: etisserant@0: # ifdef USE_PLL etisserant@0: MSG_WAR(0x3620, "Use the PLL ", 0); etisserant@0: initPLL(); etisserant@0: # endif etisserant@0: etisserant@0: } etisserant@0: etisserant@0: /***************************************************************************/ etisserant@0: char canAddIdToFilter(UNS16 adrCAN, UNS8 nFilter, UNS16 id) etisserant@0: { etisserant@0: UNS8 fiMsb; etisserant@0: UNS8 fiLsb; etisserant@0: UNS8 idMsb = (UNS8) (id >> 3); etisserant@0: UNS8 idLsb = (UNS8) (id << 5); etisserant@0: etisserant@0: if (! canTestInitMode(adrCAN)) { etisserant@0: /* Error because not init mode */ etisserant@0: MSG_WAR(0X2600, "Not in init mode ", 0); etisserant@0: return 1; etisserant@0: } etisserant@0: switch (nFilter) { etisserant@0: case 0: etisserant@0: nFilter = CANIDAR0; /* First bank */ etisserant@0: break; etisserant@0: case 1: etisserant@0: nFilter = CANIDAR2; /* First bank */ etisserant@0: break; etisserant@0: case 2: etisserant@0: nFilter = CANIDAR4; /* Second bank */ etisserant@0: break; etisserant@0: case 3: etisserant@0: nFilter = CANIDAR6; /* Second bank */ etisserant@0: } etisserant@0: if (! IO_PORTS_16(adrCAN + nFilter)) { etisserant@0: /* if CANIDARx = 0 */ etisserant@0: IO_PORTS_8(adrCAN + nFilter) = idMsb; etisserant@0: IO_PORTS_8(adrCAN + nFilter + 1) = idLsb; etisserant@0: } etisserant@0: fiMsb = IO_PORTS_8(adrCAN + nFilter) ^ idMsb; etisserant@0: fiLsb = IO_PORTS_8(adrCAN + nFilter + 1) ^ idLsb; etisserant@0: /* address of CANIDMRx */ etisserant@0: IO_PORTS_8(adrCAN + nFilter + 4) = IO_PORTS_8(adrCAN + nFilter + 4) | fiMsb; etisserant@0: IO_PORTS_8(adrCAN + nFilter + 5) = IO_PORTS_8(adrCAN + nFilter + 5) | fiLsb; etisserant@0: IO_PORTS_8(adrCAN + nFilter + 5) |= 0x10; /* Not filtering on rtr value */ etisserant@0: return 0; etisserant@0: } etisserant@0: etisserant@0: /***************************************************************************/ etisserant@0: char canEnable(UNS16 adrCAN) etisserant@0: { etisserant@0: /* Register CANCTL1 etisserant@0: bit 7 : 1 MSCAN enabled etisserant@0: Other bits : default reset values etisserant@0: */ etisserant@0: IO_PORTS_8(adrCAN + CANCTL1) = 0X80; etisserant@0: return 0; etisserant@0: } etisserant@0: etisserant@0: /***************************************************************************/ etisserant@0: char canInit(UNS16 adrCAN, canBusInit bi) etisserant@0: { etisserant@0: /* If not in init mode, go to sleep before going in init mode*/ etisserant@0: if (! canTestInitMode(adrCAN)) { etisserant@0: canSleepMode(adrCAN); etisserant@0: canInitMode(adrCAN); etisserant@0: } etisserant@0: etisserant@0: canEnable(adrCAN); /* Does nothing if already enable */ etisserant@0: /* The most secure way to go in init mode : put before MSCAN in sleep mode */ etisserant@0: //canSleepMode(adrCAN); etisserant@0: /* Put MSCAN in Init mode */ etisserant@0: //canInitMode(adrCAN); etisserant@0: canInitClock(adrCAN, bi.clk); etisserant@0: /* Init CANCTL1 register. Must be in init mode */ etisserant@0: IO_PORTS_8(adrCAN + CANCTL1) &=0xC4;// 0xCB; /* Clr the bits that may be modified */ etisserant@0: IO_PORTS_8(adrCAN + CANCTL1) = (bi.cane << 7) | (bi.loopb << 5 ) | etisserant@0: (bi.listen << 4) | (bi.wupm << 2); etisserant@0: /* Initialize the filters for received msgs */ etisserant@0: /* We should decide to accept all the msgs */ etisserant@0: canInitFilter(adrCAN, bi.fi); etisserant@0: /* Before to modify CANCTL0, we must leave the init mode */ etisserant@0: canInitModeQ(adrCAN); etisserant@0: /* Init CANCTL0 register. MSCAN must not be in init mode */ etisserant@0: /* Do not change the value of wupe (should be 0) and slprq (should be 1) */ etisserant@0: /* Do not change the value of initrq (should be 0) */ etisserant@0: /* rxfrm is cleared, mupe also (should be before)*/ etisserant@0: IO_PORTS_8(adrCAN + CANCTL0) &= 0x53; /* Clr the bits that may be modified */ etisserant@0: IO_PORTS_8(adrCAN + CANCTL0) = (bi.cswai << 5) | (bi.time << 3); etisserant@0: IO_PORTS_8(adrCAN + CANRIER) = 0X01; /* Allow interruptions on receive */ etisserant@0: IO_PORTS_8(adrCAN + CANTIER) = 0X00; /* disallow interruptions on transmit */ etisserant@0: canInitModeQ(adrCAN); /* Leave the init mode */ etisserant@0: canSleepModeQ(adrCAN); /* Leave the sleep mode */ etisserant@0: return 0; etisserant@0: } etisserant@0: etisserant@0: /***************************************************************************/ etisserant@0: char canInitClock(UNS16 adrCAN, canBusTime clk) etisserant@0: { etisserant@0: if (! canTestInitMode(adrCAN)) { etisserant@0: /* Not in Init mode */ etisserant@0: MSG_WAR(0X2601, "not in init mode ", 0); etisserant@0: return 1; etisserant@0: } etisserant@0: /* Set or reset CLKSRC (register CANCTL1). Does not change the other bits*/ etisserant@0: clk.clksrc = clk.clksrc << 6; etisserant@0: IO_PORTS_8(adrCAN + CANCTL1) &= 0xBF; etisserant@0: IO_PORTS_8(adrCAN + CANCTL1) |= clk.clksrc; etisserant@0: /* Build the CANBTR0 register */ etisserant@0: IO_PORTS_8(adrCAN + CANBTR0) = 0x00; /* Clear before changes */ etisserant@0: IO_PORTS_8(adrCAN + CANBTR0) = (clk.sjw << 6) | (clk.brp); etisserant@0: /* Build the CANBTR1 register */ etisserant@0: IO_PORTS_8(adrCAN + CANBTR1) = 0x00; /* Clear before changes */ etisserant@0: IO_PORTS_8(adrCAN + CANBTR1) = (clk.samp << 7) | (clk.tseg2 << 4) | etisserant@0: (clk.tseg1); etisserant@0: return 0; etisserant@0: } etisserant@0: etisserant@0: /***************************************************************************/ etisserant@0: char canInit1Filter(UNS16 adrCAN, UNS8 nFilter, UNS16 ar, UNS16 mr) etisserant@0: { etisserant@0: if (! canTestInitMode(adrCAN)) { etisserant@0: /* Error because not init mode */ etisserant@0: MSG_WAR(0X2602, "not in init mode ", 0); etisserant@0: return 1; etisserant@0: } etisserant@0: switch (nFilter) { etisserant@0: case 0: etisserant@0: nFilter = CANIDAR0; /* First bank */ etisserant@0: break; etisserant@0: case 1: etisserant@0: nFilter = CANIDAR2; /* First bank */ etisserant@0: break; etisserant@0: case 2: etisserant@0: nFilter = CANIDAR4; /* Second bank */ etisserant@0: break; etisserant@0: case 3: etisserant@0: nFilter = CANIDAR6; /* Second bank */ etisserant@0: } etisserant@0: /* address of CANIDARx */ etisserant@0: IO_PORTS_8(adrCAN + nFilter) = (UNS8) (ar >> 8); etisserant@0: IO_PORTS_8(adrCAN + nFilter + 1) = (UNS8) (ar); etisserant@0: IO_PORTS_8(adrCAN + nFilter + 4) = (UNS8) (mr >> 8); etisserant@0: IO_PORTS_8(adrCAN + nFilter + 5) = (UNS8) (mr); etisserant@0: return 0; etisserant@0: } etisserant@0: etisserant@0: /***************************************************************************/ etisserant@0: char canInitFilter(UNS16 adrCAN, canBusFilterInit fi) etisserant@0: { etisserant@0: if (! canTestInitMode(adrCAN)) { etisserant@0: /* Error because not init mode */ etisserant@0: MSG_WAR(0X2603, "not in init mode ", 0); etisserant@0: return 1; etisserant@0: } etisserant@0: IO_PORTS_8(adrCAN + CANIDAC) = fi.idam << 4; etisserant@0: IO_PORTS_8(adrCAN + CANIDAR0) = fi.canidar0; etisserant@0: IO_PORTS_8(adrCAN + CANIDMR0) = fi.canidmr0; etisserant@0: IO_PORTS_8(adrCAN + CANIDAR1) = fi.canidar1; etisserant@0: IO_PORTS_8(adrCAN + CANIDMR1) = fi.canidmr1; etisserant@0: IO_PORTS_8(adrCAN + CANIDAR2) = fi.canidar2; etisserant@0: IO_PORTS_8(adrCAN + CANIDMR2) = fi.canidmr2; etisserant@0: IO_PORTS_8(adrCAN + CANIDAR3) = fi.canidar3; etisserant@0: IO_PORTS_8(adrCAN + CANIDMR3) = fi.canidmr3; etisserant@0: IO_PORTS_8(adrCAN + CANIDAR4) = fi.canidar4; etisserant@0: IO_PORTS_8(adrCAN + CANIDMR4) = fi.canidmr4; etisserant@0: IO_PORTS_8(adrCAN + CANIDAR5) = fi.canidar5; etisserant@0: IO_PORTS_8(adrCAN + CANIDMR5) = fi.canidmr5; etisserant@0: IO_PORTS_8(adrCAN + CANIDAR6) = fi.canidar6; etisserant@0: IO_PORTS_8(adrCAN + CANIDMR6) = fi.canidmr6; etisserant@0: IO_PORTS_8(adrCAN + CANIDAR7) = fi.canidar7; etisserant@0: IO_PORTS_8(adrCAN + CANIDMR7) = fi.canidmr7; etisserant@0: return 0; etisserant@0: } etisserant@0: etisserant@0: /***************************************************************************/ etisserant@0: char canInitMode(UNS16 adrCAN) etisserant@0: { etisserant@0: IO_PORTS_8(adrCAN + CANCTL0) |= 0x01; /* Set the bit INITRQ */ etisserant@0: while (! canTestInitMode(adrCAN)) { etisserant@0: } etisserant@0: return 0; etisserant@0: } etisserant@0: etisserant@0: /***************************************************************************/ etisserant@0: char canInitModeQ(UNS16 adrCAN) etisserant@0: { etisserant@0: IO_PORTS_8(adrCAN + CANCTL0) &= 0xFE; /* Clear the bit INITRQ */ etisserant@0: while (canTestInitMode(adrCAN)) { etisserant@0: } etisserant@0: return 0; etisserant@0: } etisserant@0: etisserant@0: /***************************************************************************/ etisserant@0: char canMsgTransmit(UNS16 adrCAN, Message msg) etisserant@0: { etisserant@0: /* Remind : only CAN A msg implemented. ie id on 11 bits, not 29 */ etisserant@0: UNS8 cantflg; etisserant@0: UNS8 i; etisserant@0: /* Looking for a free buffer */ etisserant@0: cantflg = IO_PORTS_8(adrCAN + CANTFLG); etisserant@0: if ( cantflg == 0) { /* all the TXEx are set */ etisserant@0: MSG_WAR(0X2604, "No buffer free. Msg to transmit is losted ", 0); etisserant@0: return 1; /* No buffer free */ etisserant@0: } etisserant@0: else{ etisserant@0: /* Selecting a buffer */ etisserant@0: IO_PORTS_8(adrCAN + CANTBSEL) = cantflg; etisserant@0: /* We put ide = 0 because id is on 11 bits only */ etisserant@0: IO_PORTS_8(adrCAN + CANTRSID) = (UNS8)(msg.cob_id.w >> 3); etisserant@0: IO_PORTS_8(adrCAN + CANTRSID + 1) = (UNS8)((msg.cob_id.w << 5)| etisserant@0: (msg.rtr << 4)); etisserant@0: etisserant@0: IO_PORTS_8(adrCAN + CANTRSLEN) = msg.len & 0X0F; etisserant@0: /* For the priority, we put the highter bits of the cob_id */ etisserant@0: IO_PORTS_8(adrCAN + CANTRSPRI) = IO_PORTS_8(adrCAN + CANTRSID); etisserant@0: for (i = 0 ; i < msg.len ; i++) { etisserant@0: IO_PORTS_8(adrCAN + CANTRSDTA + i) = msg.data[i]; etisserant@0: } etisserant@0: /* Transmitting the message */ etisserant@0: cantflg = IO_PORTS_8(adrCAN + CANTBSEL);/* to know which buf is selected */ etisserant@0: IO_PORTS_8(adrCAN + CANTBSEL) = 0x00; etisserant@0: IO_PORTS_8(adrCAN + CANTFLG) = cantflg; /* Ready to transmit ! */ etisserant@0: etisserant@0: } etisserant@0: return 0; etisserant@0: } etisserant@0: etisserant@0: /***************************************************************************/ etisserant@0: char canSleepMode(UNS16 adrCAN) etisserant@0: { etisserant@0: IO_PORTS_8(adrCAN + CANCTL0) &= 0xFB; /* clr the bit WUPE to avoid a wake-up*/ etisserant@0: IO_PORTS_8(adrCAN + CANCTL0) |= 0x02; /* Set the bit SLPRQ. go to Sleep !*/ etisserant@0: etisserant@0: // IO_PORTS_8(adrCAN + CANCTL1) |= 0x04; etisserant@0: // IO_PORTS_8(adrCAN + CANCTL0) |= 0x02; /* Set the bit SLPRQ */ etisserant@0: while ( ! canTestSleepMode(adrCAN)) { etisserant@0: } etisserant@0: etisserant@0: return 0; etisserant@0: } etisserant@0: etisserant@0: /***************************************************************************/ etisserant@0: char canSleepModeQ(UNS16 adrCAN) etisserant@0: { etisserant@0: if (canTestInitMode(adrCAN)) { etisserant@0: /* Error because in init mode */ etisserant@0: MSG_WAR(0X2606, "not in init mode ", 0); etisserant@0: return 1; etisserant@0: } etisserant@0: IO_PORTS_8(adrCAN + CANCTL0) &= 0xFD; /* clr the bit SLPRQ */ etisserant@0: while ( canTestSleepMode(adrCAN)) { etisserant@0: } etisserant@0: return 0; etisserant@0: } etisserant@0: etisserant@0: /***************************************************************************/ etisserant@0: char canSleepWupMode(UNS16 adrCAN) etisserant@0: { etisserant@0: if (canTestInitMode(adrCAN)) { etisserant@0: MSG_WAR(0X2607, "not in init mode ", 0); etisserant@0: return 1; etisserant@0: } etisserant@0: IO_PORTS_8(adrCAN + CANCTL0) |= 0x06; /* Set the bits WUPE & SLPRQ */ etisserant@0: while ( ! canTestSleepMode(adrCAN)) { etisserant@0: } etisserant@0: return 0; etisserant@0: } etisserant@0: etisserant@0: /***************************************************************************/ etisserant@0: char canTestInitMode(UNS16 adrCAN) etisserant@0: { etisserant@0: return IO_PORTS_8(adrCAN + CANCTL1) & 0x01; /* Test the bit INITAK */ etisserant@0: } etisserant@0: etisserant@0: /***************************************************************************/ etisserant@0: char canTestSleepMode(UNS16 adrCAN) etisserant@0: { etisserant@0: return IO_PORTS_8(adrCAN + CANCTL1) & 0x02; /* Test the bit SLPAK */ etisserant@0: } etisserant@0: etisserant@0: /***************************************************************************/ etisserant@0: UNS8 canSend(UNS8 notused, Message *m) etisserant@0: { etisserant@0: canMsgTransmit(CANOPEN_LINE_NUMBER_USED, *m); etisserant@0: return 0; etisserant@0: } etisserant@0: etisserant@0: etisserant@0: /**************************************************************************/ etisserant@0: UNS8 f_can_receive(UNS8 notused, Message *msgRcv) etisserant@0: { etisserant@0: UNS8 i, j; etisserant@0: etisserant@0: switch (CANOPEN_LINE_NUMBER_USED) { etisserant@0: case CAN0 : j = 0; break; etisserant@0: case CAN1 : j = 1; break; etisserant@0: case CAN2 : j = 2; break; etisserant@0: case CAN3 : j = 3; break; etisserant@0: case CAN4 : j = 4; break; etisserant@0: } etisserant@0: etisserant@0: /* See if a message is pending in the stack */ etisserant@0: if (ptrMsgRcv[j].r == ptrMsgRcv[j].w) etisserant@0: return 0x0; // No new message etisserant@0: etisserant@0: /* Increment the reading pointer of the stack */ etisserant@0: if (ptrMsgRcv[j].r == (MAX_STACK_MSG_RCV - 1)) etisserant@0: ptrMsgRcv[j].r = 0; etisserant@0: else etisserant@0: ptrMsgRcv[j].r ++; etisserant@0: etisserant@0: /* Store the message from the stack*/ etisserant@0: msgRcv->cob_id.w = stackMsgRcv[j][ptrMsgRcv[j].r].cob_id.w; etisserant@0: msgRcv->len = stackMsgRcv[j][ptrMsgRcv[j].r].len; etisserant@0: msgRcv->rtr = stackMsgRcv[j][ptrMsgRcv[j].r].rtr; etisserant@0: for (i = 0 ; i < stackMsgRcv[j][ptrMsgRcv[j].r].len ; i++) etisserant@0: msgRcv->data[i] = stackMsgRcv[j][ptrMsgRcv[j].r].data[i]; etisserant@0: return 0xFF; etisserant@0: } etisserant@0: etisserant@0: etisserant@0: /****************************************************************************** etisserant@0: ******************************* CAN INTERRUPT *******************************/ etisserant@0: etisserant@0: void __attribute__((interrupt)) can0HdlTra (void) etisserant@0: { etisserant@0: etisserant@0: } etisserant@0: etisserant@0: void __attribute__((interrupt)) can0HdlRcv (void) etisserant@0: { etisserant@0: UNS8 i; etisserant@0: lock(); etisserant@0: IO_PORTS_8(PORTB) &= ~ 0x40; // led 6 port B : ON etisserant@0: UNS8 NewPtrW; etisserant@0: /* We are obliged to save the message while the interruption is pending */ etisserant@0: /* Increment the writing stack pointer before writing the msg */ etisserant@0: if (ptrMsgRcv[0].w == (MAX_STACK_MSG_RCV - 1)) etisserant@0: NewPtrW = 0; etisserant@0: else etisserant@0: NewPtrW = ptrMsgRcv[0].w + 1; etisserant@0: etisserant@0: if (NewPtrW == ptrMsgRcv[0].r) { etisserant@0: /* The stack is full. The last msg received before this one is lost */ etisserant@0: MSG_WAR(0X1620, "Stack for received msg is full", 0); etisserant@0: //IO_PORTS_8(PORTB) &= ~0x40; // led 6 : ON (for debogue) etisserant@0: } etisserant@0: else etisserant@0: ptrMsgRcv[0].w = NewPtrW; etisserant@0: etisserant@0: /* Store the message */ etisserant@0: stackMsgRcv[0][ptrMsgRcv[0].w].cob_id.w = IO_PORTS_16(CAN0 + CANRCVID) >> 5; etisserant@0: stackMsgRcv[0][ptrMsgRcv[0].w].len = IO_PORTS_8(CAN0 + CANRCVLEN) & 0x0F; etisserant@0: stackMsgRcv[0][ptrMsgRcv[0].w].rtr = (IO_PORTS_8(CAN0 + CANRCVID + 1) >> 4) & 0x01; etisserant@0: for (i = 0 ; i < stackMsgRcv[0][ptrMsgRcv[0].w].len ; i++) etisserant@0: stackMsgRcv[0][ptrMsgRcv[0].w].data[i] = IO_PORTS_8(CAN0 + CANRCVDTA + i); etisserant@0: etisserant@0: // The message is stored , so etisserant@0: // we can now release the receive foreground buffer etisserant@0: // and acknowledge the interruption etisserant@0: IO_PORTS_8(CAN0 + CANRFLG) |= 0x01; etisserant@0: // Not very usefull etisserant@0: IO_PORTS_8(CAN0 + CANCTL0) |= 0x80; etisserant@0: IO_PORTS_8(PORTB) |= 0x40; // led 6 port B : ON etisserant@0: unlock(); etisserant@0: } etisserant@0: etisserant@0: void __attribute__((interrupt)) can0HdlWup (void) etisserant@0: { etisserant@0: etisserant@0: } etisserant@0: etisserant@0: void __attribute__((interrupt)) can0HdlErr (void) etisserant@0: { etisserant@0: etisserant@0: } etisserant@0: etisserant@0: void __attribute__((interrupt)) can1HdlTra (void) etisserant@0: { etisserant@0: etisserant@0: } etisserant@0: etisserant@0: void __attribute__((interrupt)) can1HdlRcv (void) etisserant@0: { etisserant@0: UNS8 i; etisserant@0: lock(); etisserant@0: UNS8 NewPtrW; etisserant@0: /* We are obliged to save the message while the interruption is pending */ etisserant@0: /* Increment the writing stack pointer before writing the msg */ etisserant@0: if (ptrMsgRcv[1].w == (MAX_STACK_MSG_RCV - 1)) etisserant@0: NewPtrW = 0; etisserant@0: else etisserant@0: NewPtrW = ptrMsgRcv[1].w + 1; etisserant@0: etisserant@0: if (NewPtrW == ptrMsgRcv[1].r) { etisserant@0: /* The stack is full. The last msg received before this one is lost */ etisserant@0: MSG_WAR(0X2620, "Stack for received msg is full", 0); etisserant@0: } etisserant@0: else etisserant@0: ptrMsgRcv[1].w = NewPtrW; etisserant@0: etisserant@0: /* Store the message */ etisserant@0: stackMsgRcv[1][ptrMsgRcv[1].w].cob_id.w = IO_PORTS_16(CAN1 + CANRCVID) >> 5; etisserant@0: stackMsgRcv[1][ptrMsgRcv[1].w].len = IO_PORTS_8(CAN1 + CANRCVLEN) & 0x0F; etisserant@0: stackMsgRcv[0][ptrMsgRcv[0].w].rtr = (IO_PORTS_8(CAN1 + CANRCVID + 1) >> 4) & 0x01; etisserant@0: for (i = 0 ; i < stackMsgRcv[1][ptrMsgRcv[1].w].len ; i++) etisserant@0: stackMsgRcv[1][ptrMsgRcv[1].w].data[i] = IO_PORTS_8(CAN1 + CANRCVDTA + i); etisserant@0: etisserant@0: // The message is stored , so etisserant@0: // we can now release the receive foreground buffer etisserant@0: // and acknowledge the interruption etisserant@0: IO_PORTS_8(CAN1 + CANRFLG) |= 0x01; etisserant@0: // Not very usefull etisserant@0: IO_PORTS_8(CAN1 + CANCTL0) |= 0x80; etisserant@0: unlock(); etisserant@0: } etisserant@0: etisserant@0: void __attribute__((interrupt)) can1HdlWup (void) etisserant@0: { etisserant@0: etisserant@0: } etisserant@0: etisserant@0: void __attribute__((interrupt)) can1HdlErr (void) etisserant@0: { etisserant@0: etisserant@0: } etisserant@0: etisserant@0: void __attribute__((interrupt)) can2HdlTra (void) etisserant@0: { etisserant@0: etisserant@0: } etisserant@0: etisserant@0: void __attribute__((interrupt)) can2HdlRcv (void) etisserant@0: { etisserant@0: etisserant@0: } etisserant@0: etisserant@0: void __attribute__((interrupt)) can2HdlWup (void) etisserant@0: { etisserant@0: etisserant@0: } etisserant@0: etisserant@0: void __attribute__((interrupt)) can2HdlErr (void) etisserant@0: { etisserant@0: etisserant@0: } etisserant@0: etisserant@0: void __attribute__((interrupt)) can3HdlTra (void) etisserant@0: { etisserant@0: etisserant@0: } etisserant@0: etisserant@0: void __attribute__((interrupt)) can3HdlRcv (void) etisserant@0: { etisserant@0: etisserant@0: } etisserant@0: etisserant@0: void __attribute__((interrupt)) can3HdlWup (void) etisserant@0: { etisserant@0: etisserant@0: } etisserant@0: etisserant@0: void __attribute__((interrupt)) can3HdlErr (void) etisserant@0: { etisserant@0: etisserant@0: } etisserant@0: etisserant@0: void __attribute__((interrupt)) can4HdlTra (void) etisserant@0: { etisserant@0: etisserant@0: } etisserant@0: etisserant@0: void __attribute__((interrupt)) can4HdlRcv (void) etisserant@0: { etisserant@0: etisserant@0: } etisserant@0: etisserant@0: void __attribute__((interrupt)) can4HdlWup (void) etisserant@0: { etisserant@0: etisserant@0: } etisserant@0: etisserant@0: void __attribute__((interrupt)) can4HdlErr (void) etisserant@0: { etisserant@0: etisserant@0: } etisserant@0: etisserant@0: etisserant@0: