Nut/OS  4.10.3
API Reference
sja1000.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004 by Ole Reinhardt <ole.reinhardt@kernelconcepts.de>,
00003  *                       Kernelconcepts http://www.kernelconcepts.de
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  * 3. Neither the name of the copyright holders nor the names of
00015  *    contributors may be used to endorse or promote products derived
00016  *    from this software without specific prior written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS
00019  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00020  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00021  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE
00022  * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00023  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00024  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00025  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00026  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00027  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00028  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00029  * SUCH DAMAGE.
00030  *
00031  * For additional information see http://www.ethernut.de/
00032  *
00033  */
00034 
00047 /*
00048  * $Log$
00049  * Revision 1.7  2008/08/11 06:59:17  haraldkipp
00050  * BSD types replaced by stdint types (feature request #1282721).
00051  *
00052  * Revision 1.6  2007/10/04 19:32:52  olereinhardt
00053  * SJA_BASE (base address for sja1000 driver) can now be set in configurator
00054  *
00055  * Revision 1.5  2007/09/08 03:00:17  hwmaier
00056  * Optional time-out for receiving added
00057  *
00058  * Revision 1.4  2007/09/06 19:02:48  olereinhardt
00059  * Corrected handling of 11bit standard IDs
00060  *
00061  * Revision 1.3  2006/10/08 16:48:08  haraldkipp
00062  * Documentation fixed
00063  *
00064  * Revision 1.2  2005/10/24 18:02:34  haraldkipp
00065  * Fixes for ATmega103.
00066  *
00067  * Revision 1.1  2005/07/26 18:02:40  haraldkipp
00068  * Moved from dev.
00069  *
00070  * Revision 1.8  2005/05/27 14:09:56  olereinhardt
00071  * Fixed a bug in irq initialisation
00072  *
00073  * Revision 1.7  2005/01/24 21:12:04  freckle
00074  * renamed NutEventPostFromIRQ into NutEventPostFromIrq
00075  *
00076  * Revision 1.6  2005/01/21 16:49:45  freckle
00077  * Seperated calls to NutEventPostAsync between Threads and IRQs
00078  *
00079  * Revision 1.5  2004/11/12 16:27:42  olereinhardt
00080  * Added critical section around NutEventPostAsync
00081  *
00082  * Revision 1.4  2004/09/17 14:31:37  olereinhardt
00083  * Compile only if __GNUC__ defined
00084  *
00085  * Revision 1.3  2004/06/08 14:50:25  olereinhardt
00086  * Removed receive thread and moved input data handling into irq handler. Much faster now on reception.
00087  *
00088  * Revision 1.1  2004/06/07 15:11:49  olereinhardt
00089  * Initial checkin
00090  *
00091  */
00092 
00097 
00098 /* Not ported. */
00099 #ifdef __GNUC__
00100 
00101 #include <string.h>
00102 #include <sys/heap.h>
00103 #include <sys/thread.h>
00104 #include <sys/event.h>
00105 #include <sys/atom.h>
00106 #include <sys/timer.h>
00107 #include <sys/semaphore.h>
00108 #include <sys/nutconfig.h>
00109 
00110 #include <dev/irqreg.h>
00111 #include <dev/can_dev.h>
00112 #include <dev/sja1000.h>
00113 #include <cfg/arch/avr.h>
00114 
00115 
00116 #ifndef SJA_SIGNAL
00117 #define SJA_SIGNAL     sig_INTERRUPT7
00118 #endif
00119 
00120 #ifndef SJA_EICR
00121 #define SJA_EICR       EICRB
00122 #endif
00123 
00124 #ifndef SJA_SIGNAL_BIT
00125 #define SJA_SIGNAL_BIT 7
00126 #endif
00127 
00128 #ifndef SJA_BASE
00129 #define SJA_BASE 0x8800
00130 #endif
00131 
00132 CANINFO dcb_sja1000;
00133 
00134 volatile uint16_t sja_base = 0x0000;
00135 
00136 
00137 struct _CANBuffer {
00138     CANFRAME *dataptr;          // the physical memory address where the buffer is stored
00139     uint16_t size;               // the allocated size of the buffer
00140     uint16_t datalength;         // the length of the data currently in the buffer
00141     uint16_t dataindex;          // the index into the buffer where the data starts
00142     SEM empty;
00143     SEM full;
00144 };
00145 
00146 typedef struct _CANBuffer CANBuffer;
00147 
00148 #ifndef CAN_BufSize
00149 #define CAN_BufSize 64
00150 #endif
00151 
00152 CANBuffer CAN_RX_BUF;
00153 CANBuffer CAN_TX_BUF;
00154 
00155 void CANBufferInit(CANBuffer * buffer,uint16_t size)
00156 {
00157     NutSemInit(&buffer->full, 0);
00158     NutSemInit(&buffer->empty, CAN_BufSize - 1);
00159     // set start pointer of the buffer
00160     buffer->dataptr = NutHeapAlloc(size * sizeof(CANFRAME));
00161     buffer->size = size;
00162     // initialize index and length
00163     buffer->dataindex = 0;
00164     buffer->datalength = 0;
00165 }
00166 
00167 // access routines
00168 
00169 CANFRAME CANBufferGetMutex(CANBuffer * buffer)
00170 {
00171     CANFRAME data;
00172 
00173     NutSemWait(&buffer->full);
00174 //    NutSemWait(&buffer->mutex);
00175     // check to see if there's data in the buffer
00176     if (buffer->datalength) {
00177         // get the first frame from buffer
00178         data = buffer->dataptr[buffer->dataindex];
00179         // move index down and decrement length
00180         buffer->dataindex++;
00181         if (buffer->dataindex >= buffer->size) {
00182             buffer->dataindex %= buffer->size;
00183         }
00184         buffer->datalength--;
00185     }
00186 //    NutSemPost(&buffer->mutex);
00187     NutSemPost(&buffer->empty);
00188     // return
00189     return data;
00190 }
00191 
00192 void CANBufferPutMutex(CANBuffer * buffer, CANFRAME * data)
00193 {
00194     NutSemWait(&buffer->empty);
00195 //    NutSemWait(&buffer->mutex);
00196 
00197     // make sure the buffer has room
00198     if (buffer->datalength < buffer->size) {
00199         // save frame at end of buffer
00200         buffer->dataptr[(buffer->dataindex + buffer->datalength) % buffer->size] = *data;
00201         // increment the length
00202         buffer->datalength++;
00203         // return success
00204     }
00205 
00206 //    NutSemPost(&buffer->mutex);
00207     NutSemPost(&buffer->full);
00208 }
00209 
00210 CANFRAME CANBufferGet(CANBuffer * buffer)
00211 {
00212     CANFRAME data;
00213 
00214     // check to see if there's data in the buffer
00215     if (buffer->datalength) {
00216         // get the first frame from buffer
00217         data = buffer->dataptr[buffer->dataindex];
00218         // move index down and decrement length
00219         buffer->dataindex++;
00220         if (buffer->dataindex >= buffer->size) {
00221             buffer->dataindex %= buffer->size;
00222         }
00223         buffer->datalength--;
00224     }
00225     // return
00226     return data;
00227 }
00228 
00229 void CANBufferPut(CANBuffer * buffer, CANFRAME * data)
00230 {
00231     // make sure the buffer has room
00232     if (buffer->datalength < buffer->size) {
00233         // save frame at end of buffer
00234         buffer->dataptr[(buffer->dataindex + buffer->datalength) % buffer->size] = *data;
00235         // increment the length
00236         buffer->datalength++;
00237         // return success
00238     }
00239 }
00240 
00241 uint16_t CANBufferFree(CANBuffer * buffer)
00242 {
00243     // check to see if the buffer has room
00244     // return true if there is room
00245     return (buffer->size - buffer->datalength);
00246 }
00247 
00255 inline uint8_t SJARxAvail(NUTDEVICE * dev)
00256 {
00257     return CAN_RX_BUF.datalength;
00258 }
00259 
00267 inline uint8_t SJATxFree(NUTDEVICE * dev)
00268 {
00269     return CANBufferFree(&CAN_TX_BUF);
00270 }
00271 
00284 void SJAOutput(NUTDEVICE * dev, CANFRAME * frame)
00285 {
00286     CANINFO *ci;
00287 
00288     ci = (CANINFO *) dev->dev_dcb;
00289 
00290     CANBufferPutMutex(&CAN_TX_BUF, frame);
00291     NutEventPostAsync(&ci->can_tx_rdy);
00292 }
00293 
00308 uint8_t SJAInput(NUTDEVICE * dev, CANFRAME * frame)
00309 {
00310     uint8_t ready = 0;
00311     CANINFO *ci;
00312     
00313     ci = (CANINFO *) dev->dev_dcb;
00314     while (!ready)
00315     {
00316         if (CAN_RX_BUF.datalength==0) 
00317         {
00318            uint32_t timeout =  ((IFCAN *) (dev->dev_icb))->can_rtimeout;
00319 
00320            if (NutEventWait(&ci->can_rx_rdy, timeout)) 
00321                return 1;
00322         }
00323         NutEnterCritical();
00324         if (CAN_RX_BUF.datalength)
00325         {
00326             *frame = CANBufferGet(&CAN_RX_BUF);
00327             ready  = 1;
00328         }
00329         NutExitCritical();
00330     }
00331     SJA1000_IEN |= (RIE_Bit);       // enables IRQ since buffer has space
00332     return 0;
00333 }
00334 
00347 void SJASetAccCode(NUTDEVICE * dev, uint8_t * ac)
00348 {
00349     memcpy(((IFCAN *) (dev->dev_icb))->can_acc_code, ac, 4);
00350 
00351     while ((SJA1000_MODECTRL & RM_RR_Bit) == 0x00)      // enter reset state
00352         SJA1000_MODECTRL = (RM_RR_Bit | SJA1000_MODECTRL);
00353 
00354     SJA1000_AC0 = ac[0];
00355     SJA1000_AC1 = ac[1];
00356     SJA1000_AC2 = ac[2];
00357     SJA1000_AC3 = ac[3];
00358     SJA1000_MODECTRL = (AFM_Bit);
00359     //*** Note - if you change SJA1000_MODECTRL, change it in
00360     // functions CAN_Init and CAN_SetAccMask also.
00361 
00362     do {
00363         SJA1000_MODECTRL = 0x00;
00364     }
00365     while ((SJA1000_MODECTRL & RM_RR_Bit) != 0x00);     // leave reset state
00366 }
00367 
00378 void SJASetAccMask(NUTDEVICE * dev, uint8_t * am)
00379 {
00380     memcpy(((IFCAN *) (dev->dev_icb))->can_acc_mask, am, 4);
00381 
00382     while ((SJA1000_MODECTRL & RM_RR_Bit) == 0x00)      // enter reset state
00383         SJA1000_MODECTRL = (RM_RR_Bit | SJA1000_MODECTRL);
00384 
00385     SJA1000_AM0 = am[0];
00386     SJA1000_AM1 = am[1];        // mask off lower nibble (SJA manual p44)
00387     SJA1000_AM2 = am[2];
00388     SJA1000_AM3 = am[3];
00389     SJA1000_MODECTRL = (AFM_Bit);
00390     //*** Note - if you change SJA1000_MODECTRL, change it in
00391     // functions CAN_Init and CAN_SetAccCode also.
00392 
00393     do {
00394         SJA1000_MODECTRL = 0x00;
00395     }
00396     while ((SJA1000_MODECTRL & RM_RR_Bit) != 0x00);     // leave reset state
00397 }
00398 
00410 uint8_t SJASetBaudrate(NUTDEVICE * dev, uint32_t baudrate)
00411 {
00412     uint8_t result = 0;
00413 
00414     ((IFCAN *) (dev->dev_icb))->can_baudrate = baudrate;
00415 
00416     while ((SJA1000_MODECTRL & RM_RR_Bit) == 0x00)      // enter reset state
00417         SJA1000_MODECTRL = (RM_RR_Bit | SJA1000_MODECTRL);
00418 
00419     switch (baudrate)           // setting actual bustiming
00420     {                           // all @ 16 Mhz
00421     case CAN_SPEED_10K:
00422         SJA1000_BT0 = 113;
00423         SJA1000_BT1 = 28;
00424         break;
00425     case CAN_SPEED_20K:
00426         SJA1000_BT0 = 88;
00427         SJA1000_BT1 = 28;
00428         break;
00429     case CAN_SPEED_50K:
00430         SJA1000_BT0 = 73;
00431         SJA1000_BT1 = 28;
00432         break;
00433     case CAN_SPEED_100K:
00434         SJA1000_BT0 = 68;
00435         SJA1000_BT1 = 28;
00436         break;
00437     case CAN_SPEED_125K:
00438         SJA1000_BT0 = 67;
00439         SJA1000_BT1 = 28;
00440         break;
00441     case CAN_SPEED_250K:
00442         SJA1000_BT0 = 65;
00443         SJA1000_BT1 = 28;
00444         break;
00445     case CAN_SPEED_500K:
00446         SJA1000_BT0 = 64;
00447         SJA1000_BT1 = 28;
00448         break;
00449     case CAN_SPEED_800K:
00450         SJA1000_BT0 = 64;
00451         SJA1000_BT1 = 22;
00452         break;
00453     case CAN_SPEED_1M:
00454         SJA1000_BT0 = 64;
00455         SJA1000_BT1 = 20;
00456         break;
00457     default:
00458         result = 1;
00459     }
00460 
00461     do {
00462         SJA1000_MODECTRL = 0x00;
00463     }
00464     while ((SJA1000_MODECTRL & RM_RR_Bit) != 0x00);     // leave reset state
00465 
00466     return result;
00467 }
00468 
00478 void SJATxFrame(CANFRAME * CAN_frame)
00479 {
00480     uint32_t temp_id;
00481 
00482 
00483     if (CAN_frame->ext) {
00484         temp_id = CAN_frame->id << 3;
00485         SJA1000_TxFrameInfo = CAN_frame->len | CAN_29 | (CAN_frame->rtr ? CAN_RTR : 0);
00486 
00487         SJA1000_Tx1 = (uint8_t) (temp_id >> 24);        // load High Byte
00488         SJA1000_Tx2 = (uint8_t) (temp_id >> 16);        // load High Byte
00489         SJA1000_Tx3 = (uint8_t) (temp_id >> 8);         // load High Byte
00490         SJA1000_Tx4 = (uint8_t) (temp_id & 0x00F8);     // Low Byte and ignore bit 0-2
00491 
00492         SJA1000_Tx5 = CAN_frame->byte[0];
00493         SJA1000_Tx6 = CAN_frame->byte[1];
00494         SJA1000_Tx7 = CAN_frame->byte[2];
00495         SJA1000_Tx8 = CAN_frame->byte[3];
00496         SJA1000_Tx9 = CAN_frame->byte[4];
00497         SJA1000_Tx10 = CAN_frame->byte[5];
00498         SJA1000_Tx11 = CAN_frame->byte[6];
00499         SJA1000_Tx12 = CAN_frame->byte[7];
00500 
00501     } else {
00502         temp_id = CAN_frame->id << 21;
00503         SJA1000_TxFrameInfo = CAN_frame->len | (CAN_frame->rtr ? CAN_RTR : 0);
00504 
00505         SJA1000_Tx1 = (uint8_t) (temp_id >> 24);        // load High Byte
00506         SJA1000_Tx2 = (uint8_t) (temp_id >> 16) & 0xE0; // Low Byte and ignore bit 0-4
00507 
00508         SJA1000_Tx3 = CAN_frame->byte[0];
00509         SJA1000_Tx4 = CAN_frame->byte[1];
00510         SJA1000_Tx5 = CAN_frame->byte[2];
00511         SJA1000_Tx6 = CAN_frame->byte[3];
00512         SJA1000_Tx7 = CAN_frame->byte[4];
00513         SJA1000_Tx8 = CAN_frame->byte[5];
00514         SJA1000_Tx9 = CAN_frame->byte[6];
00515         SJA1000_Tx10 = CAN_frame->byte[7];
00516     }
00517     SJA1000_CMD = TR_Bit;     // Start Transmission
00518 }
00519 
00528 void SJARxFrame(CANFRAME * CAN_frame)
00529 {
00530     uint8_t FrameInfo = SJA1000_RxFrameInfo;
00531     CAN_frame->len = FrameInfo & 0x0F;  // frame info mask off higher 4 bits
00532     CAN_frame->ext = FrameInfo & CAN_29 ? 1 : 0;
00533     CAN_frame->rtr = FrameInfo & CAN_RTR ? 1 : 0;
00534 
00535     if (CAN_frame->ext) {
00536         CAN_frame->id = (((uint32_t) SJA1000_Rx1 << 24) |
00537                          ((uint32_t) SJA1000_Rx2 << 16) | 
00538                          ((uint32_t) SJA1000_Rx3 << 8)  | 
00539                          ((uint32_t) SJA1000_Rx4 & 0xF8)) >> 3;
00540 
00541 
00542         CAN_frame->byte[0] = SJA1000_Rx5;
00543         CAN_frame->byte[1] = SJA1000_Rx6;
00544         CAN_frame->byte[2] = SJA1000_Rx7;
00545         CAN_frame->byte[3] = SJA1000_Rx8;
00546         CAN_frame->byte[4] = SJA1000_Rx9;
00547         CAN_frame->byte[5] = SJA1000_Rx10;
00548         CAN_frame->byte[6] = SJA1000_Rx11;
00549         CAN_frame->byte[7] = SJA1000_Rx12;      // just fill the whole struct, less CPU cycles
00550     } else {
00551         CAN_frame->id = (((uint32_t) SJA1000_Rx1 << 24) | 
00552                           (uint32_t) SJA1000_Rx2 << 16) >> 21;   // id_h and id_l
00553 
00554         CAN_frame->byte[0] = SJA1000_Rx3;
00555         CAN_frame->byte[1] = SJA1000_Rx4;
00556         CAN_frame->byte[2] = SJA1000_Rx5;
00557         CAN_frame->byte[3] = SJA1000_Rx6;
00558         CAN_frame->byte[4] = SJA1000_Rx7;
00559         CAN_frame->byte[5] = SJA1000_Rx8;
00560         CAN_frame->byte[6] = SJA1000_Rx9;
00561         CAN_frame->byte[7] = SJA1000_Rx10;      // just fill the whole struct, less CPU cycles
00562     }
00563     SJA1000_CMD = RRB_Bit;      // release the receive buffer
00564 }
00565 
00566 
00567 
00576 THREAD(CAN_Tx, arg)
00577 {
00578     NUTDEVICE *dev;
00579     CANINFO *ci;
00580     CANFRAME out_frame;
00581 
00582     dev = arg;
00583     ci = (CANINFO *) dev->dev_dcb;
00584 
00585     NutThreadSetPriority(16);
00586 
00587     while (1) {
00588         NutEventWait(&ci->can_tx_rdy, NUT_WAIT_INFINITE);
00589         while ((SJA1000_STATUS & TBS_Bit) == TBS_Bit)   // if transmit buffer released
00590         {
00591             out_frame = CANBufferGetMutex(&CAN_TX_BUF);
00592             SJATxFrame(&out_frame);     // using SJA1000 TX buffer
00593             ci->can_tx_frames++;
00594         }
00595     }
00596 }
00597 
00606 static void SJAInterrupt(void *arg)
00607 {
00608     CANINFO *ci;
00609     volatile uint8_t irq = SJA1000_INT;
00610     CANFRAME in_frame;
00611     
00612     ci = (CANINFO *) (((NUTDEVICE *) arg)->dev_dcb);
00613 
00614     ci->can_interrupts++;
00615 
00616     if (((irq & TI_Bit) == TI_Bit))     // transmit IRQ fired
00617     {
00618         NutEventPostFromIrq(&ci->can_tx_rdy);
00619     }
00620 
00621     if ((irq & RI_Bit) == RI_Bit)       // Receive IRQ fired
00622     {
00623         if (CAN_RX_BUF.size-CAN_RX_BUF.datalength > 0)
00624         {
00625             SJARxFrame(&in_frame);
00626             CANBufferPut(&CAN_RX_BUF, &in_frame);
00627             if (CAN_RX_BUF.size==CAN_RX_BUF.datalength)
00628                 SJA1000_IEN &= (~RIE_Bit);      // Disable RX IRQ until data has been poped from input buffer
00629             NutEventPostFromIrq(&ci->can_rx_rdy);
00630             ci->can_rx_frames++;
00631         }
00632     }
00633 
00634     if ((irq & EI_Bit) == EI_Bit)               //Error IRQ fired
00635     {
00636         ci->can_errors++;
00637         // TODO: Handle error
00638     } else if ((irq & DOI_Bit) == DOI_Bit)      //Error IRQ fired
00639     {
00640         ci->can_overruns++;
00641         SJA1000_CMD = CDO_Bit;                  // Clear DO status;
00642         // TODO: Handle overrun
00643     }
00644 }
00645 
00657 int SJAInit(NUTDEVICE * dev)
00658 {
00659     IFCAN *ifc;
00660     CANINFO *ci;
00661     volatile uint8_t temp;
00662 
00663     sja_base = dev->dev_base;
00664 
00665     if (sja_base == 0x0000) sja_base = SJA_BASE;
00666 
00667     ifc = dev->dev_icb;
00668 
00669     memset(dev->dev_dcb, 0, sizeof(CANINFO));
00670     ci = (CANINFO *) dev->dev_dcb;
00671 
00672     CANBufferInit(&CAN_RX_BUF, CAN_BufSize);
00673     CANBufferInit(&CAN_TX_BUF, CAN_BufSize);
00674 
00675     while ((SJA1000_MODECTRL & RM_RR_Bit) == 0x00)      // entering reset mode
00676         SJA1000_MODECTRL = (RM_RR_Bit | SJA1000_MODECTRL);
00677 
00678     SJA1000_CLK_DIV = (CANMode_Bit | CBP_Bit | DivBy2 | ClkOff_Bit);    // sets clock divide register
00679 
00680     SJA1000_IEN = (ClrIntEnSJA);        // Disables CAN IRQ
00681 
00682     SJA1000_AC0 = ifc->can_acc_code[0];
00683     SJA1000_AC1 = ifc->can_acc_code[1];
00684     SJA1000_AC2 = ifc->can_acc_code[2];
00685     SJA1000_AC3 = ifc->can_acc_code[3];
00686 
00687     SJA1000_AM0 = ifc->can_acc_mask[0];
00688     SJA1000_AM1 = ifc->can_acc_mask[1];
00689     SJA1000_AM2 = ifc->can_acc_mask[2];
00690     SJA1000_AM3 = ifc->can_acc_mask[3];
00691 
00692     switch (ifc->can_baudrate)  // setting actual bustiming
00693     {                           // all @ 16 Mhz
00694     case CAN_SPEED_10K:
00695         SJA1000_BT0 = 113;
00696         SJA1000_BT1 = 28;
00697         break;
00698     case CAN_SPEED_20K:
00699         SJA1000_BT0 = 88;
00700         SJA1000_BT1 = 28;
00701         break;
00702     case CAN_SPEED_50K:
00703         SJA1000_BT0 = 73;
00704         SJA1000_BT1 = 28;
00705         break;
00706     case CAN_SPEED_100K:
00707         SJA1000_BT0 = 68;
00708         SJA1000_BT1 = 28;
00709         break;
00710     case CAN_SPEED_125K:
00711         SJA1000_BT0 = 67;
00712         SJA1000_BT1 = 28;
00713         break;
00714     case CAN_SPEED_250K:
00715         SJA1000_BT0 = 65;
00716         SJA1000_BT1 = 28;
00717         break;
00718     case CAN_SPEED_500K:
00719         SJA1000_BT0 = 64;
00720         SJA1000_BT1 = 28;
00721         break;
00722     case CAN_SPEED_800K:
00723         SJA1000_BT0 = 64;
00724         SJA1000_BT1 = 22;
00725         break;
00726     case CAN_SPEED_1M:
00727         SJA1000_BT0 = 64;
00728         SJA1000_BT1 = 20;
00729         break;
00730     default:
00731         return errCAN_INVALID_BAUD;
00732     }
00733 
00734     SJA1000_OUTCTRL = (Tx1Float | Tx0PshPull | NormalMode);     // Set up Output Control Register
00735 
00736     SJA1000_IEN = (RIE_Bit | TIE_Bit | EIE_Bit | DOIE_Bit );       // Enables receive IRQ
00737 
00738     SJA1000_MODECTRL = (AFM_Bit);       // set single filter mode + sleep
00739     // *** Note - if you change SJA1000_MODECTRL, change it in
00740     // functions SJASetAccMask and SJASetAccCode also.
00741     
00742     do {
00743         SJA1000_MODECTRL = 0x00;
00744     }
00745     while ((SJA1000_MODECTRL & RM_RR_Bit) != 0x00);     // leaves reset mode
00746 
00747     NutEnterCritical();
00748 
00749     if (NutRegisterIrqHandler(&SJA_SIGNAL, SJAInterrupt, dev)) {
00750         NutExitCritical();
00751         return -1;
00752     }
00753 
00754     cbi(EIMSK, SJA_SIGNAL_BIT);
00755     if (SJA_SIGNAL_BIT < 4)     // Set corresponding interrupt to low
00756     {                           // level interrupt
00757 #ifdef __AVR_ENHANCED__
00758         cbi(EICRA, (SJA_SIGNAL_BIT << 1));
00759         cbi(EICRA, (SJA_SIGNAL_BIT << 1) + 1);
00760 #endif /* __AVR_ENHANCED__ */
00761     } else {
00762         cbi(EICR, ((SJA_SIGNAL_BIT - 4) << 1));
00763         cbi(EICR, ((SJA_SIGNAL_BIT - 4) << 1) + 1);
00764     }
00765     temp = SJA1000_INT;         // Read interrupt register to clear pendin bits    
00766     sbi(EIMSK, SJA_SIGNAL_BIT);
00767     sbi(PORTE, SJA_SIGNAL_BIT);
00768     NutThreadCreate("sjacantx", CAN_Tx, dev, 256);
00769 
00770     NutExitCritical();
00771 
00772     return 0;
00773 }
00774 
00775 
00784 IFCAN ifc_sja1000 = {
00785     CAN_IF_2B,                  
00786     CAN_SPEED_500K,             
00787     {0xFF, 0xFF, 0xFF, 0xFF}
00788     ,                           
00789     {0x00, 0x00, 0x00, 0x00}
00790     ,                           
00791     NUT_WAIT_INFINITE,         
00792     SJARxAvail,                 
00793     SJATxFree,                  
00794     SJAInput,                   
00795     SJAOutput,                  
00796     SJASetAccCode,              
00797     SJASetAccMask,              
00798     SJASetBaudrate              
00799 };
00800 
00808 NUTDEVICE devSJA1000 = {
00809     0,                          
00810     {'s', 'j', 'a', '1', '0', '0', '0', 0, 0}
00811     ,                           
00812     IFTYP_CAN,                  
00813     0,                          
00814     0,                          
00815     &ifc_sja1000,               
00816     &dcb_sja1000,               
00817     SJAInit,                    
00818     0,                          
00819     0,                          
00820     0,                          
00821     0,                          
00822     0,                          
00823     0,                          
00824     0                           
00825 };
00826 
00827 #else
00828 void keep_icc_happy(void)
00829 {
00830 }
00831 
00832 #endif
00833