atcan.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2005-2007 proconX Pty Ltd. All rights reserved. 
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.7  2008/08/11 06:59:14  haraldkipp
00044  * BSD types replaced by stdint types (feature request #1282721).
00045  *
00046  * Revision 1.6  2007/11/16 03:17:26  hwmaier
00047  * Updated bit timing values for a sample point of 87.5% and a SJW of 2. Required for maximum bus length as per CiA DS-102.
00048  *
00049  * Revision 1.5  2007/09/08 03:00:52  hwmaier
00050  * Optional time-out for receiving added, more robust handling of error interrupts.
00051  *
00052  * Revision 1.3  2007/05/24 00:55:43  henrik
00053  * no message
00054  *
00055  * Revision 1.2  2007/03/11 08:59:47  henrik
00056  * no message
00057  *
00058  * Revision 1.1  2006/11/17 01:44:00  henrik
00059  * no message
00060  *
00061  * Revision 1.4  2006/03/01 02:15:29  hwmaier
00062  * Error check for NutHeapAlloc added
00063  *
00064  * Revision 1.3  2005/12/04 10:53:59  hwmaier
00065  * no message
00066  *
00067  * Revision 1.2  2005/10/07 22:02:33  hwmaier
00068  * no message
00069  *
00070  * Revision 1.1  2005/10/04 06:00:59  hwmaier
00071  * Added AT90CAN128 CAN driver
00072  *
00073  */
00074 
00079 
00080 #ifdef __GNUC__
00081 
00082 #include <cfg/os.h>
00083 #include <string.h>
00084 #include <sys/event.h>
00085 #include <sys/heap.h>
00086 #include <sys/atom.h>
00087 #include <dev/irqreg.h>
00088 #include <dev/can_dev.h>
00089 #include <avr/io.h>
00090 #include <dev/atcan.h>
00091 
00092 
00093 /*****************************************************************************
00094  * Definitions
00095  *****************************************************************************/
00096 
00097 #define RX_MOB 8
00098 
00099 #ifndef CAN_BUF_SIZE
00100 #  define CAN_BUF_SIZE 64
00101 #endif
00102 
00103 
00104 /*****************************************************************************
00105  * CAN baud rate table
00106  *
00107  * Tried to match as closely as possible a sampling point of 87.5 %
00108  * which is recommended by CiA for CANOpen. DeviceNet specifies a 
00109  * sampling point > 80%. SQW is 2.
00110  *****************************************************************************/
00111 
00112 //
00113 // 12.00 MHz
00114 //
00115 #if NUT_CPU_FREQ == 12000000
00116 // 10 kbit/s 85.00% 20 quanta (BRP=59 Tprs=8 Tph1=8 Tph2=3 Tsjw=2)
00117 #define CAN_BT1_10K 0x76
00118 #define CAN_BT2_10K 0x2E
00119 #define CAN_BT3_10K 0x2E
00120 // 20 kbit/s 86.67% 15 quanta (BRP=39 Tprs=8 Tph1=4 Tph2=2 Tsjw=2)
00121 #define CAN_BT1_20K 0x4E
00122 #define CAN_BT2_20K 0x2E
00123 #define CAN_BT3_20K 0x16
00124 // 50 kbit/s 87.50% 16 quanta (BRP=14 Tprs=8 Tph1=5 Tph2=2 Tsjw=2)
00125 #define CAN_BT1_50K 0x1C
00126 #define CAN_BT2_50K 0x2E
00127 #define CAN_BT3_50K 0x18
00128 // 100 kbit/s 86.67% 15 quanta (BRP=7 Tprs=8 Tph1=4 Tph2=2 Tsjw=2)
00129 #define CAN_BT1_100K 0x0E
00130 #define CAN_BT2_100K 0x2E
00131 #define CAN_BT3_100K 0x16
00132 // 125 kbit/s 87.50% 16 quanta (BRP=5 Tprs=8 Tph1=5 Tph2=2 Tsjw=2)
00133 #define CAN_BT1_125K 0x0A
00134 #define CAN_BT2_125K 0x2E
00135 #define CAN_BT3_125K 0x18
00136 // 250 kbit/s 87.50% 16 quanta (BRP=2 Tprs=8 Tph1=5 Tph2=2 Tsjw=2)
00137 #define CAN_BT1_250K 0x04
00138 #define CAN_BT2_250K 0x2E
00139 #define CAN_BT3_250K 0x18
00140 // 500 kbit/s 83.33% 12 quanta (BRP=1 Tprs=7 Tph1=2 Tph2=2 Tsjw=2)
00141 #define CAN_BT1_500K 0x02
00142 #define CAN_BT2_500K 0x2C
00143 #define CAN_BT3_500K 0x12
00144 // 800 kbit/s 86.67% 15 quanta (BRP=0 Tprs=8 Tph1=4 Tph2=2 Tsjw=2)
00145 #define CAN_BT1_800K 0x00
00146 #define CAN_BT2_800K 0x2E
00147 #define CAN_BT3_800K 0x16
00148 // 1000 kbit/s 83.33% 12 quanta (BRP=0 Tprs=7 Tph1=2 Tph2=2 Tsjw=2)
00149 #define CAN_BT1_1M 0x00
00150 #define CAN_BT2_1M 0x2C
00151 #define CAN_BT3_1M 0x12
00152 
00153 //
00154 // 16.00 MHz
00155 //
00156 #elif NUT_CPU_FREQ == 16000000
00157 // 10 kbit/s 68.00% 25 quanta (BRP=63 Tprs=8 Tph1=8 Tph2=8 Tsjw=2)
00158 #define CAN_BT1_10K 0x7E
00159 #define CAN_BT2_10K 0x2E
00160 #define CAN_BT3_10K 0x7E
00161 // 20 kbit/s 87.50% 16 quanta (BRP=49 Tprs=8 Tph1=5 Tph2=2 Tsjw=2)
00162 #define CAN_BT1_20K 0x62
00163 #define CAN_BT2_20K 0x2E
00164 #define CAN_BT3_20K 0x18
00165 // 50 kbit/s 87.50% 16 quanta (BRP=19 Tprs=8 Tph1=5 Tph2=2 Tsjw=2)
00166 #define CAN_BT1_50K 0x26
00167 #define CAN_BT2_50K 0x2E
00168 #define CAN_BT3_50K 0x18
00169 // 100 kbit/s 87.50% 16 quanta (BRP=9 Tprs=8 Tph1=5 Tph2=2 Tsjw=2)
00170 #define CAN_BT1_100K 0x12
00171 #define CAN_BT2_100K 0x2E
00172 #define CAN_BT3_100K 0x18
00173 // 125 kbit/s 87.50% 16 quanta (BRP=7 Tprs=8 Tph1=5 Tph2=2 Tsjw=2)
00174 #define CAN_BT1_125K 0x0E
00175 #define CAN_BT2_125K 0x2E
00176 #define CAN_BT3_125K 0x18
00177 // 250 kbit/s 87.50% 16 quanta (BRP=3 Tprs=8 Tph1=5 Tph2=2 Tsjw=2)
00178 #define CAN_BT1_250K 0x06
00179 #define CAN_BT2_250K 0x2E
00180 #define CAN_BT3_250K 0x18
00181 // 500 kbit/s 87.50% 16 quanta (BRP=1 Tprs=8 Tph1=5 Tph2=2 Tsjw=2)
00182 #define CAN_BT1_500K 0x02
00183 #define CAN_BT2_500K 0x2E
00184 #define CAN_BT3_500K 0x18
00185 // 800 kbit/s 85.00% 20 quanta (BRP=0 Tprs=8 Tph1=8 Tph2=3 Tsjw=2)
00186 #define CAN_BT1_800K 0x00
00187 #define CAN_BT2_800K 0x2E
00188 #define CAN_BT3_800K 0x2E
00189 // 1000 kbit/s 87.50% 16 quanta (BRP=0 Tprs=8 Tph1=5 Tph2=2 Tsjw=2)
00190 #define CAN_BT1_1M 0x00
00191 #define CAN_BT2_1M 0x2E
00192 #define CAN_BT3_1M 0x18
00193 #else
00194 #  error Frequency not supported or not set to a Fixed MCU clock!
00195 #endif
00196 
00197 
00198 /*****************************************************************************
00199  * Buffer management
00200  *
00201  * Note: Buffer concept borrowed from existing Nut/OS sja1000.c driver
00202  *****************************************************************************/
00203 
00204 struct _CANBuffer {
00205     CANFRAME *dataptr;    // the physical memory address where the buffer is stored
00206     uint8_t size;         // the allocated size of the buffer
00207     uint8_t datalength;   // the length of the data currently in the buffer
00208     uint8_t dataindex;    // the index into the buffer where the data starts
00209 };
00210 
00211 typedef struct _CANBuffer CANBuffer;
00212 
00213 
00214 /*****************************************************************************
00215  * Driver data
00216  *****************************************************************************/
00217 
00218 static CANBuffer canRxBuf;
00219 CANINFO dcb_atcan;
00220 IFCAN ifc_atcan;
00221 NUTDEVICE devAtCan;
00222 
00223 
00224 /*****************************************************************************
00225  * Low level functions
00226  *****************************************************************************/
00227 
00237 int8_t AtCanGetBusState(void)
00238 {
00239    if (CANGSTA & _BV(BOFF))
00240        return CAN_BUS_OFF;
00241    if (CANGSTA & _BV(ERRP))
00242        return CAN_PASSIVE;
00243    return CAN_SUCCESS;
00244 }
00245 
00246 
00252 int8_t AtCanGetFreeMob(void)
00253 {
00254    int8_t mob;
00255    uint8_t ctrlReg;
00256 
00257    for (mob = 0; mob < ATCAN_MAX_MOB; mob++)
00258    {
00259       CANPAGE = mob << 4;
00260       ctrlReg = CANCDMOB & (_BV(CONMOB1) | _BV(CONMOB0));
00261       if (ctrlReg == 0)
00262          return mob;
00263       if (ctrlReg == _BV(CONMOB0) && (bit_is_set(CANSTMOB, TXOK)))
00264       {
00265           // Free MOB
00266           CANCDMOB &= ~(_BV(CONMOB1) | _BV(CONMOB0));
00267           return mob;
00268       }
00269    }
00270    return -1;
00271 }
00272 
00273 
00286 int8_t AtCanEnableMsgObj(uint8_t mob,
00287                          uint32_t id, int8_t idIsExt, int8_t idRemTag,
00288                          uint32_t mask, int8_t maskIsExt, int8_t maskRemTag)
00289 {
00290     if (mob < ATCAN_MAX_MOB)
00291     {
00292         // Select MOb
00293         CANPAGE = mob << 4;
00294         // Abort MOb
00295         CANCDMOB = 0;
00296         // Set identifier and mask
00297         if (idIsExt)
00298         {
00299             CANCDMOB |= _BV(IDE);
00300             CANIDT1 = (((uint8_t *) &(id))[3] << 3) + (((uint8_t *) &(id))[2] >> 5);
00301             CANIDT2 = (((uint8_t *) &(id))[2] << 3) + (((uint8_t *) &(id))[1] >> 5);
00302             CANIDT3 = (((uint8_t *) &(id))[1] << 3) + (((uint8_t *) &(id))[0] >> 5);
00303             CANIDT4 = (((uint8_t *) &(id))[0] << 3);
00304             CANIDM1 = (((uint8_t *) &(mask))[3] << 3) + (((uint8_t *) &(mask))[2] >> 5);
00305             CANIDM2 = (((uint8_t *) &(mask))[2] << 3) + (((uint8_t *) &(mask))[1] >> 5);
00306             CANIDM3 = (((uint8_t *) &(mask))[1] << 3) + (((uint8_t *) &(mask))[0] >> 5);
00307             CANIDM4 = (((uint8_t *) &(mask))[0] << 3);
00308         }
00309         else
00310         {
00311             CANIDT1 = (((uint8_t *) &(id))[1] << 5) + (((uint8_t *) &(id))[0] >> 3);
00312             CANIDT2 = (((uint8_t *) &(id))[0] << 5);
00313             CANIDT3 = 0;
00314             CANIDT4 = 0;
00315             CANIDM1 = (((uint8_t *) &(mask))[1] << 5) + (((uint8_t *) &(mask))[0] >> 3);
00316             CANIDM2 = (((uint8_t *) &(mask))[0] << 5);
00317             CANIDM3 = 0;
00318             CANIDM4 = 0;
00319         }
00320         if (idRemTag)
00321             CANIDT4 |= _BV(RTRTAG);
00322         if (maskIsExt)
00323             CANIDM4 |= _BV(IDEMSK);
00324         if (maskRemTag)
00325             CANIDM4 |= _BV(RTRMSK);
00326         // Enable reception
00327         CANCDMOB |= _BV(CONMOB1);
00328         return CAN_SUCCESS;
00329     }
00330     else
00331         return CAN_ILLEGAL_MOB;
00332 }
00333 
00334 
00354 int8_t AtCanEnableRx(uint8_t noOfMsgObjs,
00355                      uint32_t id, int8_t idIsExt, int8_t idRemTag,
00356                      uint32_t mask, int8_t maskIsExt, int8_t maskRemTag)
00357 {
00358     int8_t i;
00359     int8_t result;
00360 
00361     for (i = 0; i < noOfMsgObjs; i++)
00362     {
00363         result = AtCanEnableMsgObj(i, id, idIsExt, idRemTag, mask, maskIsExt, maskRemTag);
00364         if (result != CAN_SUCCESS)
00365             return result;
00366     }
00367     return CAN_SUCCESS;
00368 }
00369 
00370 
00377 int8_t AtCanSendMsg(CANFRAME *frame)
00378 {
00379     signed char mob, j;
00380 
00381     mob = AtCanGetFreeMob();
00382     if (mob < 0)
00383         return CAN_TXBUF_FULL;
00384     // Select MOB
00385     CANPAGE = mob << 4;
00386     // Abort MOB and set length fields
00387     CANCDMOB = frame->len;
00388     // Check for ID type
00389     if (frame->ext)
00390     {
00391         CANIDT1 = (((uint8_t *) &(frame->id))[3] << 3) + (((uint8_t *) &(frame->id))[2] >> 5);
00392         CANIDT2 = (((uint8_t *) &(frame->id))[2] << 3) + (((uint8_t *) &(frame->id))[1] >> 5);
00393         CANIDT3 = (((uint8_t *) &(frame->id))[1] << 3) + (((uint8_t *) &(frame->id))[0] >> 5);
00394         CANIDT4 = (((uint8_t *) &(frame->id))[0] << 3);
00395         CANCDMOB |= _BV(IDE);
00396     }
00397     else
00398     {
00399         CANIDT1 = (((uint8_t *) &(frame->id))[1] << 5) + (((uint8_t *) &(frame->id))[0] >> 3);
00400         CANIDT2 = (((uint8_t *) &(frame->id))[0] << 5);
00401         CANIDT3 = 0;
00402         CANIDT4 = 0;
00403     }
00404     if (frame->rtr)
00405         CANIDT4 |= _BV(RTRTAG);
00406     for (j = 0; j < 8; j++)
00407         CANMSG = frame->byte[j];
00408     // Enable transmission
00409     CANCDMOB |= _BV(CONMOB0);
00410 
00411     return CAN_SUCCESS;
00412 }
00413 
00414 
00418 static void AtCanInterrupt(void *arg)
00419 {
00420     uint8_t savedCanPage;
00421     CANINFO *ci = (CANINFO *) (((NUTDEVICE *) arg)->dev_dcb);
00422 
00423     savedCanPage = CANPAGE; // Save the current CAN page
00424     ci->can_interrupts++;
00425 
00426     //
00427     // Check for MOb interrupt
00428     //
00429     if ((CANHPMOB & 0xF0) != 0xF0)
00430     {
00431         CANPAGE = CANHPMOB; // Switch page
00432         // RX interrupt ?
00433         if (bit_is_set(CANSTMOB, RXOK))
00434         {
00435             // Space in buffer ?
00436             if (canRxBuf.datalength < canRxBuf.size)
00437             {
00438                 int8_t j;
00439                 CANFRAME * bufPtr = &canRxBuf.dataptr[(canRxBuf.dataindex + canRxBuf.datalength) % canRxBuf.size];
00440 
00441                 // Extended or standard ID?
00442                 bufPtr->ext = bit_is_set(CANCDMOB, IDE);
00443                 if (bufPtr->ext)
00444                 {
00445                     ((uint8_t *) &(bufPtr->id))[3] = CANIDT1 >> 3;
00446                     ((uint8_t *) &(bufPtr->id))[2] = (CANIDT2 >> 3) | (CANIDT1 << 5);
00447                     ((uint8_t *) &(bufPtr->id))[1] = (CANIDT3 >> 3) | (CANIDT2 << 5);
00448                     ((uint8_t *) &(bufPtr->id))[0] = (CANIDT4 >> 3) | (CANIDT3 << 5);
00449                 }
00450                 else
00451                 {
00452                     ((uint8_t *) &(bufPtr->id))[3] = 0;
00453                     ((uint8_t *) &(bufPtr->id))[2] = 0;
00454                     ((uint8_t *) &(bufPtr->id))[1] = CANIDT1 >> 5;
00455                     ((uint8_t *) &(bufPtr->id))[0] = (CANIDT1 << 3) | (CANIDT2 >> 5);
00456                 }
00457                 bufPtr->len = CANCDMOB & (_BV(DLC0) | _BV(DLC1) | _BV(DLC2) | _BV(DLC3));
00458                 bufPtr->rtr = bit_is_set(CANIDT4, RTRTAG);
00459                 for (j = 0; j < 8; j++)
00460                     bufPtr->byte[j] = CANMSG;
00461                 // Increment buffer length
00462                 canRxBuf.datalength++;
00463                 NutEventPostFromIrq(&ci->can_rx_rdy);
00464                 // Stat houskeeping
00465                 ci->can_rx_frames++;
00466             }
00467             else
00468             {
00469                 // Stat houskeeping
00470                 ci->can_overruns++;
00471             }
00472         }
00473         // TX interrupt ?
00474         else if (bit_is_set(CANSTMOB, TXOK))
00475         {
00476             NutEventPostFromIrq(&ci->can_tx_rdy);
00477             ci->can_tx_frames++;
00478         }
00479         // Error interrupts ?
00480         else 
00481         {
00482            // Stat houskeeping
00483            ci->can_errors++;
00484         }
00485         
00486         //
00487         // Acknowledge all MOB interrupts and manage MObs
00488         //
00489         CANSTMOB = CANSTMOB & ~(_BV(TXOK) | _BV(RXOK) | _BV(BERR) | 
00490                                 _BV(SERR) | _BV(CERR) | _BV(FERR) | _BV(AERR));
00491         
00492         if (bit_is_set(CANCDMOB, CONMOB1))
00493            // Re-enable MOb for reception by re-writing CONMOB1 bit
00494            CANCDMOB |= _BV(CONMOB1);
00495         else
00496            // Re-claim MOb as send buffer
00497            CANCDMOB &= ~(_BV(CONMOB1) | _BV(CONMOB0));
00498 
00499     }
00500     else
00501     {
00502         // Acknowledge general CAN interrupt
00503         CANGIT = _BV(BOFFIT) | _BV(BXOK) | _BV(SERG) | _BV(CERG) | _BV(FERG) | _BV(AERG);
00504         // Stat houskeeping
00505         ci->can_errors++;
00506     }
00507     CANPAGE = savedCanPage; // Restore CAN page register
00508 }
00509 
00510 
00511 /*****************************************************************************
00512  * Function definitions
00513  *****************************************************************************/
00514 
00521 uint8_t AtCanRxAvail(NUTDEVICE * dev)
00522 {
00523     return canRxBuf.datalength;
00524 }
00525 
00526 
00533 uint8_t AtCanTxFree(NUTDEVICE * dev)
00534 {
00535     return (AtCanGetFreeMob() >= 0);
00536 }
00537 
00538 
00548 void AtCanOutput(NUTDEVICE * dev, CANFRAME * frame)
00549 {
00550     CANINFO * ci = (CANINFO *) dev->dev_dcb;
00551 
00552     while (AtCanSendMsg(frame) == CAN_TXBUF_FULL)
00553     {
00554         NutEventWait(&ci->can_tx_rdy, NUT_WAIT_INFINITE);
00555     };
00556 }
00557 
00558 
00570 uint8_t AtCanInput(NUTDEVICE * dev, CANFRAME * frame)
00571 {
00572     CANINFO * ci = (CANINFO *) dev->dev_dcb;
00573 
00574     while (canRxBuf.datalength == 0)
00575     {
00576         uint32_t timeout =  ((IFCAN *) (dev->dev_icb))->can_rtimeout;
00577         
00578         if (NutEventWait(&ci->can_rx_rdy, timeout)) 
00579             return 1;
00580     }
00581     NutEnterCritical();
00582     // Get the first frame from buffer
00583     *frame = canRxBuf.dataptr[canRxBuf.dataindex];
00584     // Move index down and decrement length
00585     canRxBuf.dataindex++;
00586     if (canRxBuf.dataindex >= canRxBuf.size)
00587         canRxBuf.dataindex %= canRxBuf.size;
00588     canRxBuf.datalength--;
00589     NutExitCritical();
00590     
00591     return 0;
00592 }
00593 
00594 
00601 void AtCanSetAccCode(NUTDEVICE * dev, uint8_t * ac)
00602 {
00603     memcpy(((IFCAN *) (dev->dev_icb))->can_acc_code, ac, 4);
00604     AtCanEnableRx(RX_MOB, 0, 0, 0, 0, 0, 0); //ttt   TODO: Implement it!
00605 }
00606 
00607 
00614 void AtCanSetAccMask(NUTDEVICE * dev, uint8_t * am)
00615 {
00616     memcpy(((IFCAN *) (dev->dev_icb))->can_acc_mask, am, 4);
00617     AtCanEnableRx(RX_MOB, 0, 0, 0, 0, 0, 0); //ttt   TODO: Implement it!
00618 }
00619 
00620 
00628 uint8_t AtCanSetBaudrate(NUTDEVICE * dev, uint32_t baudrate)
00629 {
00630     switch (baudrate)
00631     {
00632         case CAN_SPEED_10K:
00633             CANBT1 = CAN_BT1_10K;
00634             CANBT2 = CAN_BT2_10K;
00635             CANBT3 = CAN_BT3_10K;
00636         break;
00637         case CAN_SPEED_20K:
00638             CANBT1 = CAN_BT1_20K;
00639             CANBT2 = CAN_BT2_20K;
00640             CANBT3 = CAN_BT3_20K;
00641         break;
00642         case CAN_SPEED_50K:
00643             CANBT1 = CAN_BT1_50K;
00644             CANBT2 = CAN_BT2_50K;
00645             CANBT3 = CAN_BT3_50K;
00646         break;
00647         case CAN_SPEED_100K:
00648             CANBT1 = CAN_BT1_100K;
00649             CANBT2 = CAN_BT2_100K;
00650             CANBT3 = CAN_BT3_100K;
00651         break;
00652         case CAN_SPEED_125K:
00653             CANBT1 = CAN_BT1_125K;
00654             CANBT2 = CAN_BT2_125K;
00655             CANBT3 = CAN_BT3_125K;
00656         break;
00657         case CAN_SPEED_250K:
00658             CANBT1 = CAN_BT1_250K;
00659             CANBT2 = CAN_BT2_250K;
00660             CANBT3 = CAN_BT3_250K;
00661         break;
00662         case CAN_SPEED_500K:
00663             CANBT1 = CAN_BT1_500K;
00664             CANBT2 = CAN_BT2_500K;
00665             CANBT3 = CAN_BT3_500K;
00666         break;
00667         case CAN_SPEED_800K:
00668             CANBT1 = CAN_BT1_800K;
00669             CANBT2 = CAN_BT2_800K;
00670             CANBT3 = CAN_BT3_800K;
00671         break;
00672         case CAN_SPEED_1M:
00673             CANBT1 = CAN_BT1_1M;
00674             CANBT2 = CAN_BT2_1M;
00675             CANBT3 = CAN_BT3_1M;
00676         break;
00677         case CAN_SPEED_CUSTOM:
00678             // Do nothing, user sets baud rate directly but don't report an error
00679         break;
00680         default:
00681         return 1;
00682     }
00683     ((IFCAN *) (dev->dev_icb))->can_baudrate = baudrate;
00684     return 0;
00685 }
00686 
00687 
00698 int AtCanInit(NUTDEVICE * dev)
00699 {
00700     int8_t mob, i;
00701 
00702     memset(dev->dev_dcb, 0, sizeof(CANINFO));
00703 
00704     // Init receive buffer
00705     canRxBuf.dataptr = NutHeapAlloc(CAN_BUF_SIZE * sizeof(CANFRAME));
00706     if (canRxBuf.dataptr == 0)
00707         return -1;
00708     canRxBuf.size = CAN_BUF_SIZE;
00709     canRxBuf.dataindex = 0;
00710     canRxBuf.datalength = 0;
00711 
00712     // Disable AT90CAN128 CAN system
00713     CANGCON &= ~_BV(ENASTB);
00714     loop_until_bit_is_clear(CANGSTA, ENFG);
00715 
00716     // Clear all MObs
00717     for (mob = 0; mob < ATCAN_MAX_MOB; mob++)
00718     {
00719         CANPAGE = mob << 4;
00720         CANSTMOB = 0; // Clear status register
00721         CANCDMOB = 0; // Clear control register
00722         CANHPMOB = 0; // Clear HP flags
00723         // Clear identifier tag
00724         CANIDT1 = 0;
00725         CANIDT2 = 0;
00726         CANIDT3 = 0;
00727         CANIDT4 = 0;
00728         // Clear identifier mask
00729         CANIDM1 = 0;
00730         CANIDM2 = 0;
00731         CANIDM3 = 0;
00732         CANIDM4 = 0;
00733         for (i = 0; i < 8; i++)
00734         {
00735             CANMSG = 0;
00736         }
00737     }
00738     // Set baudrate
00739     AtCanSetBaudrate(dev, ifc_atcan.can_baudrate); // Errors silently ingnored here
00740     // Install IRQ handler
00741     if (NutRegisterIrqHandler(&sig_CAN_TRANSFER, AtCanInterrupt, dev))
00742         return -1;
00743     // Enable all interrupts
00744     CANIE1 = 0x7F;
00745     CANIE2 = 0xFF;
00746     CANGIE = 0xFE; // All interrupts except OVRTIM
00747     // Enable receiving MOBs
00748     AtCanEnableRx(RX_MOB, 0, 0, 0, 0, 0, 0);
00749 
00750     // Enable AT90CAN128 CAN system
00751     CANGCON |= _BV(ENASTB);
00752     loop_until_bit_is_set(CANGSTA, ENFG);
00753 
00754     return 0;
00755 }
00756 
00757 
00764 IFCAN ifc_atcan = {
00765     CAN_IF_2B,                 
00766     CAN_SPEED_125K,            
00767     {0xFF, 0xFF, 0xFF, 0xFF},  
00768     {0x00, 0x00, 0x00, 0x00},  
00769     NUT_WAIT_INFINITE,         
00770     AtCanRxAvail,              
00771     AtCanTxFree,               
00772     AtCanInput,                
00773     AtCanOutput,               
00774     AtCanSetAccCode,           
00775     AtCanSetAccMask,           
00776     AtCanSetBaudrate,          
00777 };
00778 
00779 
00786 NUTDEVICE devAtCan = {
00787     0,                          
00788     {'a', 't', 'c', 'a', 'n', '0', 0, 0, 0}, 
00789     IFTYP_CAN,                  
00790     0,                          
00791     0,                          
00792     &ifc_atcan,                 
00793     &dcb_atcan,                 
00794     AtCanInit,                  
00795     0,                          
00796     0,                          
00797     0,                          
00798     0,                          
00799     0,                          
00800     0,                          
00801     0                           
00802 };
00803 
00804 #else
00805 
00806 static void keep_icc_happy(void)
00807 {
00808 }
00809 
00810 #endif
00811 

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