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

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