atcan.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2005-2007 proconX Pty Ltd <www.proconx.com>
00003  *
00004  * This driver has been closely modeled after the existing Nut/OS SJA1000
00005  * driver and the buffer management and some code snippets have been borrowed
00006  * from sja1000.c.
00007  *
00008  * Portions Copyright (C) 2004 by Ole Reinhardt <ole.reinhardt@kernelconcepts.de>,
00009  * Kernelconcepts http://www.kernelconcepts.de
00010  *
00011  * Redistribution and use in source and binary forms, with or without
00012  * modification, are permitted provided that the following conditions
00013  * are met:
00014  *
00015  * 1. Redistributions of source code must retain the above copyright
00016  *    notice, this list of conditions and the following disclaimer.
00017  * 2. Redistributions in binary form must reproduce the above copyright
00018  *    notice, this list of conditions and the following disclaimer in the
00019  *    documentation and/or other materials provided with the distribution.
00020  * 3. Neither the name of the copyright holders nor the names of
00021  *    contributors may be used to endorse or promote products derived
00022  *    from this software without specific prior written permission.
00023  *
00024  * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS
00025  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00026  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00027  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE
00028  * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00029  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00030  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00031  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00032  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00033  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00034  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00035  * SUCH DAMAGE.
00036  *
00037  * For additional information see http://www.ethernut.de/
00038  *
00039  */
00040 
00041 /*
00042  * $Log: atcan.c,v $
00043  * Revision 1.5  2007/09/08 03:00:52  hwmaier
00044  * Optional time-out for receiving added, more robust handling of error interrupts.
00045  *
00046  * Revision 1.3  2007/05/24 00:55:43  henrik
00047  * no message
00048  *
00049  * Revision 1.2  2007/03/11 08:59:47  henrik
00050  * no message
00051  *
00052  * Revision 1.1  2006/11/17 01:44:00  henrik
00053  * no message
00054  *
00055  * Revision 1.4  2006/03/01 02:15:29  hwmaier
00056  * Error check for NutHeapAlloc added
00057  *
00058  * Revision 1.3  2005/12/04 10:53:59  hwmaier
00059  * no message
00060  *
00061  * Revision 1.2  2005/10/07 22:02:33  hwmaier
00062  * no message
00063  *
00064  * Revision 1.1  2005/10/04 06:00:59  hwmaier
00065  * Added AT90CAN128 CAN driver
00066  *
00067  */
00068 
00073 
00074 #ifdef __GNUC__
00075 
00076 #include <cfg/os.h>
00077 #include <string.h>
00078 #include <sys/event.h>
00079 #include <sys/heap.h>
00080 #include <sys/atom.h>
00081 #include <dev/irqreg.h>
00082 #include <dev/can_dev.h>
00083 #include <avr/io.h>
00084 #include <dev/atcan.h>
00085 
00086 
00087 /*****************************************************************************
00088  * Definitions
00089  *****************************************************************************/
00090 
00091 #define RX_MOB 8
00092 
00093 #ifndef CAN_BUF_SIZE
00094 #  define CAN_BUF_SIZE 64
00095 #endif
00096 
00097 
00098 /*****************************************************************************
00099  * CAN baud rate table
00100  *
00101  * Sampling point is 75%, SJW = 1
00102  *****************************************************************************/
00103 
00104 //
00105 // 12.00 MHz
00106 //
00107 #if NUT_CPU_FREQ == 12000000
00108 // 10 kbit/s - brp=59 bits=20 Tprs=8 Tph1=6 Tph2=5 Tsjw=1
00109 #define CAN_BT1_10K  0x76
00110 #define CAN_BT2_10K  0x0E
00111 #define CAN_BT3_10K  0x4B
00112 // 20 kbit/s - brp=29 bits=20 Tprs=8 Tph1=6 Tph2=5 Tsjw=1
00113 #define CAN_BT1_20K  0x3A
00114 #define CAN_BT2_20K  0x0E
00115 #define CAN_BT3_20K  0x4B
00116 // 50 kbit/s - brp=19 bits=12 Tprs=5 Tph1=3 Tph2=3 Tsjw=1
00117 #define CAN_BT1_50K  0x26
00118 #define CAN_BT2_50K  0x08
00119 #define CAN_BT3_50K  0x25
00120 // 100 kbit/s - brp=9 bits=12 Tprs=5 Tph1=3 Tph2=3 Tsjw=1
00121 #define CAN_BT1_100K 0x12
00122 #define CAN_BT2_100K 0x08
00123 #define CAN_BT3_100K 0x25
00124 // 125 kbit/s - brp=5 bits=16 Tprs=7 Tph1=4 Tph2=4 Tsjw=1
00125 #define CAN_BT1_125K 0x0A
00126 #define CAN_BT2_125K 0x0C
00127 #define CAN_BT3_125K 0x37
00128 // 250 kbit/s - brp=2 bits=16 Tprs=7 Tph1=4 Tph2=4 Tsjw=1
00129 #define CAN_BT1_250K 0x04
00130 #define CAN_BT2_250K 0x0C
00131 #define CAN_BT3_250K 0x37
00132 // 500 kbit/s - brp=1 bits=12 Tprs=5 Tph1=3 Tph2=3 Tsjw=1
00133 #define CAN_BT1_500K 0x02
00134 #define CAN_BT2_500K 0x08
00135 #define CAN_BT3_500K 0x25
00136 // 800 kbit/s - brp=0 bits=15 Tprs=8 Tph1=3 Tph2=3 Tsjw=1
00137 #define CAN_BT1_800K 0x00
00138 #define CAN_BT2_800K 0x0E
00139 #define CAN_BT3_800K 0x25
00140 // 1000 kbit/s - brp=0 bits=12 Tprs=5 Tph1=3 Tph2=3 Tsjw=1
00141 #define CAN_BT1_1M   0x00
00142 #define CAN_BT2_1M   0x08
00143 #define CAN_BT3_1M   0x25
00144 
00145 //
00146 // 16.00 MHz
00147 //
00148 #elif NUT_CPU_FREQ == 16000000
00149 // 10 kbit/s - brp=63 bits=25 Tprs=8 Tph1=10 Tph2=6 Tsjw=1
00150 #define CAN_BT1_10K  0x7E
00151 #define CAN_BT2_10K  0x0E
00152 #define CAN_BT3_10K  0x53
00153 // 20 kbit/s - brp=39 bits=20 Tprs=8 Tph1=6 Tph2=5 Tsjw=1
00154 #define CAN_BT1_20K  0x4E
00155 #define CAN_BT2_20K  0x0E
00156 #define CAN_BT3_20K  0x4B
00157 // 50 kbit/s - brp=19 bits=16 Tprs=7 Tph1=4 Tph2=4 Tsjw=1
00158 #define CAN_BT1_50K  0x26
00159 #define CAN_BT2_50K  0x0C
00160 #define CAN_BT3_50K  0x37
00161 // 100 kbit/s - brp=9 bits=16 Tprs=7 Tph1=4 Tph2=4 Tsjw=1
00162 #define CAN_BT1_100K 0x12
00163 #define CAN_BT2_100K 0x0C
00164 #define CAN_BT3_100K 0x37
00165 // 125 kbit/s - brp=7 bits=16 Tprs=7 Tph1=4 Tph2=4 Tsjw=1
00166 #define CAN_BT1_125K 0x0E
00167 #define CAN_BT2_125K 0x0C
00168 #define CAN_BT3_125K 0x37
00169 // 250 kbit/s - brp=3 bits=16 Tprs=7 Tph1=4 Tph2=4 Tsjw=1
00170 #define CAN_BT1_250K 0x06
00171 #define CAN_BT2_250K 0x0C
00172 #define CAN_BT3_250K 0x37
00173 // 500 kbit/s - brp=1 bits=16 Tprs=7 Tph1=4 Tph2=4 Tsjw=1
00174 #define CAN_BT1_500K 0x02
00175 #define CAN_BT2_500K 0x0C
00176 #define CAN_BT3_500K 0x37
00177 // 800 kbit/s - brp=0 bits=20 Tprs=8 Tph1=6 Tph2=5 Tsjw=1
00178 #define CAN_BT1_800K 0x00
00179 #define CAN_BT2_800K 0x0E
00180 #define CAN_BT3_800K 0x4B
00181 // 1000 kbit/s - brp=0 bits=16 Tprs=7 Tph1=4 Tph2=4 Tsjw=1
00182 #define CAN_BT1_1M   0x00
00183 #define CAN_BT2_1M   0x0C
00184 #define CAN_BT3_1M   0x37
00185 #else
00186 #  error Frequency not supported or not set to a Fixed MCU clock!
00187 #endif
00188 
00189 
00190 /*****************************************************************************
00191  * Buffer management
00192  *
00193  * Note: Buffer concept borrowed from existing Nut/OS sja1000.c driver
00194  *****************************************************************************/
00195 
00196 struct _CANBuffer {
00197     CANFRAME *dataptr;    // the physical memory address where the buffer is stored
00198     uint8_t size;         // the allocated size of the buffer
00199     uint8_t datalength;   // the length of the data currently in the buffer
00200     uint8_t dataindex;    // the index into the buffer where the data starts
00201 };
00202 
00203 typedef struct _CANBuffer CANBuffer;
00204 
00205 
00206 /*****************************************************************************
00207  * Driver data
00208  *****************************************************************************/
00209 
00210 static CANBuffer canRxBuf;
00211 CANINFO dcb_atcan;
00212 IFCAN ifc_atcan;
00213 NUTDEVICE devAtCan;
00214 
00215 
00216 /*****************************************************************************
00217  * Low level functions
00218  *****************************************************************************/
00219 
00229 int8_t AtCanGetBusState(void)
00230 {
00231    if (CANGSTA & _BV(BOFF))
00232        return CAN_BUS_OFF;
00233    if (CANGSTA & _BV(ERRP))
00234        return CAN_PASSIVE;
00235    return CAN_SUCCESS;
00236 }
00237 
00238 
00244 int8_t AtCanGetFreeMob(void)
00245 {
00246    int8_t mob;
00247    uint8_t ctrlReg;
00248 
00249    for (mob = 0; mob < ATCAN_MAX_MOB; mob++)
00250    {
00251       CANPAGE = mob << 4;
00252       ctrlReg = CANCDMOB & (_BV(CONMOB1) | _BV(CONMOB0));
00253       if (ctrlReg == 0)
00254          return mob;
00255       if (ctrlReg == _BV(CONMOB0) && (bit_is_set(CANSTMOB, TXOK)))
00256       {
00257           // Free MOB
00258           CANCDMOB &= ~(_BV(CONMOB1) | _BV(CONMOB0));
00259           return mob;
00260       }
00261    }
00262    return -1;
00263 }
00264 
00265 
00278 int8_t AtCanEnableMsgObj(uint8_t mob,
00279                          uint32_t id, int8_t idIsExt, int8_t idRemTag,
00280                          uint32_t mask, int8_t maskIsExt, int8_t maskRemTag)
00281 {
00282     if (mob < ATCAN_MAX_MOB)
00283     {
00284         // Select MOb
00285         CANPAGE = mob << 4;
00286         // Abort MOb
00287         CANCDMOB = 0;
00288         // Set identifier and mask
00289         if (idIsExt)
00290         {
00291             CANCDMOB |= _BV(IDE);
00292             CANIDT1 = (((uint8_t *) &(id))[3] << 3) + (((uint8_t *) &(id))[2] >> 5);
00293             CANIDT2 = (((uint8_t *) &(id))[2] << 3) + (((uint8_t *) &(id))[1] >> 5);
00294             CANIDT3 = (((uint8_t *) &(id))[1] << 3) + (((uint8_t *) &(id))[0] >> 5);
00295             CANIDT4 = (((uint8_t *) &(id))[0] << 3);
00296             CANIDM1 = (((uint8_t *) &(mask))[3] << 3) + (((uint8_t *) &(mask))[2] >> 5);
00297             CANIDM2 = (((uint8_t *) &(mask))[2] << 3) + (((uint8_t *) &(mask))[1] >> 5);
00298             CANIDM3 = (((uint8_t *) &(mask))[1] << 3) + (((uint8_t *) &(mask))[0] >> 5);
00299             CANIDM4 = (((uint8_t *) &(mask))[0] << 3);
00300         }
00301         else
00302         {
00303             CANIDT1 = (((uint8_t *) &(id))[1] << 5) + (((uint8_t *) &(id))[0] >> 3);
00304             CANIDT2 = (((uint8_t *) &(id))[0] << 5);
00305             CANIDT3 = 0;
00306             CANIDT4 = 0;
00307             CANIDM1 = (((uint8_t *) &(mask))[1] << 5) + (((uint8_t *) &(mask))[0] >> 3);
00308             CANIDM2 = (((uint8_t *) &(mask))[0] << 5);
00309             CANIDM3 = 0;
00310             CANIDM4 = 0;
00311         }
00312         if (idRemTag)
00313             CANIDT4 |= _BV(RTRTAG);
00314         if (maskIsExt)
00315             CANIDM4 |= _BV(IDEMSK);
00316         if (maskRemTag)
00317             CANIDM4 |= _BV(RTRMSK);
00318         // Enable reception
00319         CANCDMOB |= _BV(CONMOB1);
00320         return CAN_SUCCESS;
00321     }
00322     else
00323         return CAN_ILLEGAL_MOB;
00324 }
00325 
00326 
00346 int8_t AtCanEnableRx(uint8_t noOfMsgObjs,
00347                      uint32_t id, int8_t idIsExt, int8_t idRemTag,
00348                      uint32_t mask, int8_t maskIsExt, int8_t maskRemTag)
00349 {
00350     int8_t i;
00351     int8_t result;
00352 
00353     for (i = 0; i < noOfMsgObjs; i++)
00354     {
00355         result = AtCanEnableMsgObj(i, id, idIsExt, idRemTag, mask, maskIsExt, maskRemTag);
00356         if (result != CAN_SUCCESS)
00357             return result;
00358     }
00359     return CAN_SUCCESS;
00360 }
00361 
00362 
00369 int8_t AtCanSendMsg(CANFRAME *frame)
00370 {
00371     signed char mob, j;
00372 
00373     mob = AtCanGetFreeMob();
00374     if (mob < 0)
00375         return CAN_TXBUF_FULL;
00376     // Select MOB
00377     CANPAGE = mob << 4;
00378     // Abort MOB and set length fields
00379     CANCDMOB = frame->len;
00380     // Check for ID type
00381     if (frame->ext)
00382     {
00383         CANIDT1 = (((uint8_t *) &(frame->id))[3] << 3) + (((uint8_t *) &(frame->id))[2] >> 5);
00384         CANIDT2 = (((uint8_t *) &(frame->id))[2] << 3) + (((uint8_t *) &(frame->id))[1] >> 5);
00385         CANIDT3 = (((uint8_t *) &(frame->id))[1] << 3) + (((uint8_t *) &(frame->id))[0] >> 5);
00386         CANIDT4 = (((uint8_t *) &(frame->id))[0] << 3);
00387         CANCDMOB |= _BV(IDE);
00388     }
00389     else
00390     {
00391         CANIDT1 = (((uint8_t *) &(frame->id))[1] << 5) + (((uint8_t *) &(frame->id))[0] >> 3);
00392         CANIDT2 = (((uint8_t *) &(frame->id))[0] << 5);
00393         CANIDT3 = 0;
00394         CANIDT4 = 0;
00395     }
00396     if (frame->rtr)
00397         CANIDT4 |= _BV(RTRTAG);
00398     for (j = 0; j < 8; j++)
00399         CANMSG = frame->byte[j];
00400     // Enable transmission
00401     CANCDMOB |= _BV(CONMOB0);
00402 
00403     return CAN_SUCCESS;
00404 }
00405 
00406 
00410 static void AtCanInterrupt(void *arg)
00411 {
00412     uint8_t savedCanPage;
00413     CANINFO *ci = (CANINFO *) (((NUTDEVICE *) arg)->dev_dcb);
00414 
00415     savedCanPage = CANPAGE; // Save the current CAN page
00416     ci->can_interrupts++;
00417 
00418     //
00419     // Check for MOb interrupt
00420     //
00421     if ((CANHPMOB & 0xF0) != 0xF0)
00422     {
00423         CANPAGE = CANHPMOB; // Switch page
00424         // RX interrupt ?
00425         if (bit_is_set(CANSTMOB, RXOK))
00426         {
00427             // Space in buffer ?
00428             if (canRxBuf.datalength < canRxBuf.size)
00429             {
00430                 int8_t j;
00431                 CANFRAME * bufPtr = &canRxBuf.dataptr[(canRxBuf.dataindex + canRxBuf.datalength) % canRxBuf.size];
00432 
00433                 // Extended or standard ID?
00434                 bufPtr->ext = bit_is_set(CANCDMOB, IDE);
00435                 if (bufPtr->ext)
00436                 {
00437                     ((uint8_t *) &(bufPtr->id))[3] = CANIDT1 >> 3;
00438                     ((uint8_t *) &(bufPtr->id))[2] = (CANIDT2 >> 3) | (CANIDT1 << 5);
00439                     ((uint8_t *) &(bufPtr->id))[1] = (CANIDT3 >> 3) | (CANIDT2 << 5);
00440                     ((uint8_t *) &(bufPtr->id))[0] = (CANIDT4 >> 3) | (CANIDT3 << 5);
00441                 }
00442                 else
00443                 {
00444                     ((uint8_t *) &(bufPtr->id))[3] = 0;
00445                     ((uint8_t *) &(bufPtr->id))[2] = 0;
00446                     ((uint8_t *) &(bufPtr->id))[1] = CANIDT1 >> 5;
00447                     ((uint8_t *) &(bufPtr->id))[0] = (CANIDT1 << 3) | (CANIDT2 >> 5);
00448                 }
00449                 bufPtr->len = CANCDMOB & (_BV(DLC0) | _BV(DLC1) | _BV(DLC2) | _BV(DLC3));
00450                 bufPtr->rtr = bit_is_set(CANIDT4, RTRTAG);
00451                 for (j = 0; j < 8; j++)
00452                     bufPtr->byte[j] = CANMSG;
00453                 // Increment buffer length
00454                 canRxBuf.datalength++;
00455                 NutEventPostFromIrq(&ci->can_rx_rdy);
00456                 // Stat houskeeping
00457                 ci->can_rx_frames++;
00458             }
00459             else
00460             {
00461                 // Stat houskeeping
00462                 ci->can_overruns++;
00463             }
00464         }
00465         // TX interrupt ?
00466         else if (bit_is_set(CANSTMOB, TXOK))
00467         {
00468             NutEventPostFromIrq(&ci->can_tx_rdy);
00469             ci->can_tx_frames++;
00470         }
00471         // Error interrupts ?
00472         else 
00473         {
00474            // Stat houskeeping
00475            ci->can_errors++;
00476         }
00477         
00478         //
00479         // Acknowledge all MOB interrupts and manage MObs
00480         //
00481         CANSTMOB = CANSTMOB & ~(_BV(TXOK) | _BV(RXOK) | _BV(BERR) | 
00482                                 _BV(SERR) | _BV(CERR) | _BV(FERR) | _BV(AERR));
00483         
00484         if (bit_is_set(CANCDMOB, CONMOB1))
00485            // Re-enable MOb for reception by re-writing CONMOB1 bit
00486            CANCDMOB |= _BV(CONMOB1);
00487         else
00488            // Re-claim MOb as send buffer
00489            CANCDMOB &= ~(_BV(CONMOB1) | _BV(CONMOB0));
00490 
00491     }
00492     else
00493     {
00494         // Acknowledge general CAN interrupt
00495         CANGIT = _BV(BOFFIT) | _BV(BXOK) | _BV(SERG) | _BV(CERG) | _BV(FERG) | _BV(AERG);
00496         // Stat houskeeping
00497         ci->can_errors++;
00498     }
00499     CANPAGE = savedCanPage; // Restore CAN page register
00500 }
00501 
00502 
00503 /*****************************************************************************
00504  * Function definitions
00505  *****************************************************************************/
00506 
00513 u_char AtCanRxAvail(NUTDEVICE * dev)
00514 {
00515     return canRxBuf.datalength;
00516 }
00517 
00518 
00525 u_char AtCanTxFree(NUTDEVICE * dev)
00526 {
00527     return (AtCanGetFreeMob() >= 0);
00528 }
00529 
00530 
00540 void AtCanOutput(NUTDEVICE * dev, CANFRAME * frame)
00541 {
00542     CANINFO * ci = (CANINFO *) dev->dev_dcb;
00543 
00544     while (AtCanSendMsg(frame) == CAN_TXBUF_FULL)
00545     {
00546         NutEventWait(&ci->can_tx_rdy, NUT_WAIT_INFINITE);
00547     };
00548 }
00549 
00550 
00562 u_char AtCanInput(NUTDEVICE * dev, CANFRAME * frame)
00563 {
00564     CANINFO * ci = (CANINFO *) dev->dev_dcb;
00565 
00566     while (canRxBuf.datalength == 0)
00567     {
00568         u_long timeout =  ((IFCAN *) (dev->dev_icb))->can_rtimeout;
00569         
00570         if (NutEventWait(&ci->can_rx_rdy, timeout)) 
00571             return 1;
00572     }
00573     NutEnterCritical();
00574     // Get the first frame from buffer
00575     *frame = canRxBuf.dataptr[canRxBuf.dataindex];
00576     // Move index down and decrement length
00577     canRxBuf.dataindex++;
00578     if (canRxBuf.dataindex >= canRxBuf.size)
00579         canRxBuf.dataindex %= canRxBuf.size;
00580     canRxBuf.datalength--;
00581     NutExitCritical();
00582     
00583     return 0;
00584 }
00585 
00586 
00593 void AtCanSetAccCode(NUTDEVICE * dev, u_char * ac)
00594 {
00595     memcpy(((IFCAN *) (dev->dev_icb))->can_acc_code, ac, 4);
00596     AtCanEnableRx(RX_MOB, 0, 0, 0, 0, 0, 0); //ttt   TODO: Implement it!
00597 }
00598 
00599 
00606 void AtCanSetAccMask(NUTDEVICE * dev, u_char * am)
00607 {
00608     memcpy(((IFCAN *) (dev->dev_icb))->can_acc_mask, am, 4);
00609     AtCanEnableRx(RX_MOB, 0, 0, 0, 0, 0, 0); //ttt   TODO: Implement it!
00610 }
00611 
00612 
00620 u_char AtCanSetBaudrate(NUTDEVICE * dev, u_long baudrate)
00621 {
00622     switch (baudrate)
00623     {
00624         case CAN_SPEED_10K:
00625             CANBT1 = CAN_BT1_10K;
00626             CANBT2 = CAN_BT2_10K;
00627             CANBT3 = CAN_BT3_10K;
00628         break;
00629         case CAN_SPEED_20K:
00630             CANBT1 = CAN_BT1_20K;
00631             CANBT2 = CAN_BT2_20K;
00632             CANBT3 = CAN_BT3_20K;
00633         break;
00634         case CAN_SPEED_50K:
00635             CANBT1 = CAN_BT1_50K;
00636             CANBT2 = CAN_BT2_50K;
00637             CANBT3 = CAN_BT3_50K;
00638         break;
00639         case CAN_SPEED_100K:
00640             CANBT1 = CAN_BT1_100K;
00641             CANBT2 = CAN_BT2_100K;
00642             CANBT3 = CAN_BT3_100K;
00643         break;
00644         case CAN_SPEED_125K:
00645             CANBT1 = CAN_BT1_125K;
00646             CANBT2 = CAN_BT2_125K;
00647             CANBT3 = CAN_BT3_125K;
00648         break;
00649         case CAN_SPEED_250K:
00650             CANBT1 = CAN_BT1_250K;
00651             CANBT2 = CAN_BT2_250K;
00652             CANBT3 = CAN_BT3_250K;
00653         break;
00654         case CAN_SPEED_500K:
00655             CANBT1 = CAN_BT1_500K;
00656             CANBT2 = CAN_BT2_500K;
00657             CANBT3 = CAN_BT3_500K;
00658         break;
00659         case CAN_SPEED_800K:
00660             CANBT1 = CAN_BT1_800K;
00661             CANBT2 = CAN_BT2_800K;
00662             CANBT3 = CAN_BT3_800K;
00663         break;
00664         case CAN_SPEED_1M:
00665             CANBT1 = CAN_BT1_1M;
00666             CANBT2 = CAN_BT2_1M;
00667             CANBT3 = CAN_BT3_1M;
00668         break;
00669         case CAN_SPEED_CUSTOM:
00670             // Do nothing, user sets baud rate directly but don't report an error
00671         break;
00672         default:
00673         return 1;
00674     }
00675     ((IFCAN *) (dev->dev_icb))->can_baudrate = baudrate;
00676     return 0;
00677 }
00678 
00679 
00690 int AtCanInit(NUTDEVICE * dev)
00691 {
00692     int8_t mob, i;
00693 
00694     memset(dev->dev_dcb, 0, sizeof(CANINFO));
00695 
00696     // Init receive buffer
00697     canRxBuf.dataptr = NutHeapAlloc(CAN_BUF_SIZE * sizeof(CANFRAME));
00698     if (canRxBuf.dataptr == 0)
00699         return -1;
00700     canRxBuf.size = CAN_BUF_SIZE;
00701     canRxBuf.dataindex = 0;
00702     canRxBuf.datalength = 0;
00703 
00704     // Disable AT90CAN128 CAN system
00705     CANGCON &= ~_BV(ENASTB);
00706     loop_until_bit_is_clear(CANGSTA, ENFG);
00707 
00708     // Clear all MObs
00709     for (mob = 0; mob < ATCAN_MAX_MOB; mob++)
00710     {
00711         CANPAGE = mob << 4;
00712         CANSTMOB = 0; // Clear status register
00713         CANCDMOB = 0; // Clear control register
00714         CANHPMOB = 0; // Clear HP flags
00715         // Clear identifier tag
00716         CANIDT1 = 0;
00717         CANIDT2 = 0;
00718         CANIDT3 = 0;
00719         CANIDT4 = 0;
00720         // Clear identifier mask
00721         CANIDM1 = 0;
00722         CANIDM2 = 0;
00723         CANIDM3 = 0;
00724         CANIDM4 = 0;
00725         for (i = 0; i < 8; i++)
00726         {
00727             CANMSG = 0;
00728         }
00729     }
00730     // Set baudrate
00731     AtCanSetBaudrate(dev, ifc_atcan.can_baudrate); // Errors silently ingnored here
00732     // Install IRQ handler
00733     if (NutRegisterIrqHandler(&sig_CAN_TRANSFER, AtCanInterrupt, dev))
00734         return -1;
00735     // Enable all interrupts
00736     CANIE1 = 0x7F;
00737     CANIE2 = 0xFF;
00738     CANGIE = 0xFE; // All interrupts except OVRTIM
00739     // Enable receiving MOBs
00740     AtCanEnableRx(RX_MOB, 0, 0, 0, 0, 0, 0);
00741 
00742     // Enable AT90CAN128 CAN system
00743     CANGCON |= _BV(ENASTB);
00744     loop_until_bit_is_set(CANGSTA, ENFG);
00745 
00746     return 0;
00747 }
00748 
00749 
00756 IFCAN ifc_atcan = {
00757     CAN_IF_2B,                 
00758     CAN_SPEED_125K,            
00759     {0xFF, 0xFF, 0xFF, 0xFF},  
00760     {0x00, 0x00, 0x00, 0x00},  
00761     NUT_WAIT_INFINITE,         
00762     AtCanRxAvail,              
00763     AtCanTxFree,               
00764     AtCanInput,                
00765     AtCanOutput,               
00766     AtCanSetAccCode,           
00767     AtCanSetAccMask,           
00768     AtCanSetBaudrate,          
00769 };
00770 
00771 
00778 NUTDEVICE devAtCan = {
00779     0,                          
00780     {'a', 't', 'c', 'a', 'n', '0', 0, 0, 0}, 
00781     IFTYP_CAN,                  
00782     0,                          
00783     0,                          
00784     &ifc_atcan,                 
00785     &dcb_atcan,                 
00786     AtCanInit,                  
00787     0,                          
00788     0,                          
00789     0,                          
00790     0,                          
00791     0,                          
00792     0,                          
00793     0                           
00794 };
00795 
00796 #else
00797 
00798 static void keep_icc_happy(void)
00799 {
00800 }
00801 
00802 #endif
00803 

© 2000-2007 by egnite Software GmbH - visit http://www.ethernut.de/