| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794 |
- /*
- * Copyright (C) 2004 by Ole Reinhardt <ole.reinhardt@kernelconcepts.de>,
- * Kernelconcepts http://www.kernelconcepts.de
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holders nor the names of
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
- * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * For additional information see http://www.ethernut.de/
- *
- */
- /*!
- * \file arch/avr/dev/sja1000.c
- * \brief Driver for SJA1000 CAN-Bus controller
- *
- *
- * The SJA1000 controller is connected to the memory bus. It's base
- * address and interrupt is set by NutRegisterDevice.
- *
- * Have a look to our m-can board if you have questions.
- *
- * \verbatim
- * $Id: sja1000.c 5472 2013-12-06 00:16:28Z olereinhardt $
- * \endverbatim
- */
- /*!
- * \addtogroup xgCanSJA1000
- */
- /*@{*/
- /* Not ported. */
- #ifdef __GNUC__
- #include <string.h>
- #include <sys/heap.h>
- #include <sys/thread.h>
- #include <sys/event.h>
- #include <sys/atom.h>
- #include <sys/timer.h>
- #include <sys/semaphore.h>
- #include <sys/nutconfig.h>
- #include <dev/irqreg.h>
- #include <dev/can_dev.h>
- #include <dev/sja1000.h>
- #include <cfg/arch/avr.h>
- #ifndef SJA_SIGNAL
- #define SJA_SIGNAL sig_INTERRUPT7
- #endif
- #ifndef SJA_EICR
- #define SJA_EICR EICRB
- #endif
- #ifndef SJA_SIGNAL_BIT
- #define SJA_SIGNAL_BIT 7
- #endif
- #ifndef SJA_BASE
- #define SJA_BASE 0x8800
- #endif
- CANINFO dcb_sja1000;
- volatile uint16_t sja_base = 0x0000;
- struct _CANBuffer {
- CANFRAME *dataptr; // the physical memory address where the buffer is stored
- uint16_t size; // the allocated size of the buffer
- uint16_t datalength; // the length of the data currently in the buffer
- uint16_t dataindex; // the index into the buffer where the data starts
- SEM empty;
- SEM full;
- };
- typedef struct _CANBuffer CANBuffer;
- #ifndef CAN_BufSize
- #define CAN_BufSize 64
- #endif
- CANBuffer CAN_RX_BUF;
- CANBuffer CAN_TX_BUF;
- void CANBufferInit(CANBuffer * buffer,uint16_t size)
- {
- NutSemInit(&buffer->full, 0);
- NutSemInit(&buffer->empty, CAN_BufSize - 1);
- // set start pointer of the buffer
- buffer->dataptr = NutHeapAlloc(size * sizeof(CANFRAME));
- buffer->size = size;
- // initialize index and length
- buffer->dataindex = 0;
- buffer->datalength = 0;
- }
- // access routines
- CANFRAME CANBufferGetMutex(CANBuffer * buffer)
- {
- CANFRAME data;
- NutSemWait(&buffer->full);
- // NutSemWait(&buffer->mutex);
- // check to see if there's data in the buffer
- if (buffer->datalength) {
- // get the first frame from buffer
- data = buffer->dataptr[buffer->dataindex];
- // move index down and decrement length
- buffer->dataindex++;
- if (buffer->dataindex >= buffer->size) {
- buffer->dataindex %= buffer->size;
- }
- buffer->datalength--;
- }
- // NutSemPost(&buffer->mutex);
- NutSemPost(&buffer->empty);
- // return
- return data;
- }
- void CANBufferPutMutex(CANBuffer * buffer, CANFRAME * data)
- {
- NutSemWait(&buffer->empty);
- // NutSemWait(&buffer->mutex);
- // make sure the buffer has room
- if (buffer->datalength < buffer->size) {
- // save frame at end of buffer
- buffer->dataptr[(buffer->dataindex + buffer->datalength) % buffer->size] = *data;
- // increment the length
- buffer->datalength++;
- // return success
- }
- // NutSemPost(&buffer->mutex);
- NutSemPost(&buffer->full);
- }
- CANFRAME CANBufferGet(CANBuffer * buffer)
- {
- CANFRAME data;
- // check to see if there's data in the buffer
- if (buffer->datalength) {
- // get the first frame from buffer
- data = buffer->dataptr[buffer->dataindex];
- // move index down and decrement length
- buffer->dataindex++;
- if (buffer->dataindex >= buffer->size) {
- buffer->dataindex %= buffer->size;
- }
- buffer->datalength--;
- }
- // return
- return data;
- }
- void CANBufferPut(CANBuffer * buffer, CANFRAME * data)
- {
- // make sure the buffer has room
- if (buffer->datalength < buffer->size) {
- // save frame at end of buffer
- buffer->dataptr[(buffer->dataindex + buffer->datalength) % buffer->size] = *data;
- // increment the length
- buffer->datalength++;
- // return success
- }
- }
- uint16_t CANBufferFree(CANBuffer * buffer)
- {
- // check to see if the buffer has room
- // return true if there is room
- return (buffer->size - buffer->datalength);
- }
- /*!
- * \fn SJARxAvail(NUTDEVICE * dev)
- * \brief checks if data is available in input buffer
- *
- * \param dev Pointer to the device structure
- */
- inline uint8_t SJARxAvail(NUTDEVICE * dev)
- {
- return CAN_RX_BUF.datalength;
- }
- /*!
- * \fn SJATxFree(NUTDEVICE * dev)
- * \brief checks if there's still space in output buffer
- *
- * \param dev Pointer to the device structure
- */
- inline uint8_t SJATxFree(NUTDEVICE * dev)
- {
- return CANBufferFree(&CAN_TX_BUF);
- }
- /*!
- * \fn SJAOutput(NUTDEVICE * dev, CANFRAME * frame)
- * \brief Write a frame from to output buffer
- *
- * This function writes a frame to the output buffer. If the output buffer
- * is full the function will block until frames are send.
- *
- * \param dev Pointer to the device structure
- *
- * \param frame Pointer to the receive frame
- */
- void SJAOutput(NUTDEVICE * dev, CANFRAME * frame)
- {
- CANINFO *ci;
- ci = (CANINFO *) dev->dev_dcb;
- CANBufferPutMutex(&CAN_TX_BUF, frame);
- NutEventPostAsync(&ci->can_tx_rdy);
- }
- /*!
- * \fn SJAInput(NUTDEVICE * dev, CANFRAME * frame)
- * \brief Reads a frame from input buffer
- *
- * This function reads a frame from the input buffer. If the input buffer
- * is empty the function will block unitl new frames are received.
- *
- * \param dev Pointer to the device structure
- *
- * \param frame Pointer to the receive frame
- * \return 1 if timeout, 0 otherwise
- */
- uint8_t SJAInput(NUTDEVICE * dev, CANFRAME * frame)
- {
- uint8_t ready = 0;
- CANINFO *ci;
- ci = (CANINFO *) dev->dev_dcb;
- while (!ready)
- {
- if (CAN_RX_BUF.datalength==0)
- {
- uint32_t timeout = ((IFCAN *) (dev->dev_icb))->can_rtimeout;
- if (NutEventWait(&ci->can_rx_rdy, timeout))
- return 1;
- }
- NutEnterCritical();
- if (CAN_RX_BUF.datalength)
- {
- *frame = CANBufferGet(&CAN_RX_BUF);
- ready = 1;
- }
- NutExitCritical();
- }
- SJA1000_IEN |= (RIE_Bit); // enables IRQ since buffer has space
- return 0;
- }
- /*!
- * \fn SJASetAccCode(NUTDEVICE * dev, uint8_t * ac)
- * \brief Sets the acceptance code
- *
- *
- * \param dev Pointer to the device structure
- *
- * \param ac 4 byte char array with the acceptance code
- */
- void SJASetAccCode(NUTDEVICE * dev, uint8_t * ac)
- {
- memcpy(((IFCAN *) (dev->dev_icb))->can_acc_code, ac, 4);
- while ((SJA1000_MODECTRL & RM_RR_Bit) == 0x00) // enter reset state
- SJA1000_MODECTRL = (RM_RR_Bit | SJA1000_MODECTRL);
- SJA1000_AC0 = ac[0];
- SJA1000_AC1 = ac[1];
- SJA1000_AC2 = ac[2];
- SJA1000_AC3 = ac[3];
- SJA1000_MODECTRL = (AFM_Bit);
- //*** Note - if you change SJA1000_MODECTRL, change it in
- // functions CAN_Init and CAN_SetAccMask also.
- do {
- SJA1000_MODECTRL = 0x00;
- }
- while ((SJA1000_MODECTRL & RM_RR_Bit) != 0x00); // leave reset state
- }
- /*!
- * \fn SJASetAccMask(NUTDEVICE * dev, uint8_t * am)
- * \brief Sets the acceptance mask
- *
- *
- * \param dev Pointer to the device structure
- *
- * \param am 4 byte char array with the acceptance mask
- */
- void SJASetAccMask(NUTDEVICE * dev, uint8_t * am)
- {
- memcpy(((IFCAN *) (dev->dev_icb))->can_acc_mask, am, 4);
- while ((SJA1000_MODECTRL & RM_RR_Bit) == 0x00) // enter reset state
- SJA1000_MODECTRL = (RM_RR_Bit | SJA1000_MODECTRL);
- SJA1000_AM0 = am[0];
- SJA1000_AM1 = am[1]; // mask off lower nibble (SJA manual p44)
- SJA1000_AM2 = am[2];
- SJA1000_AM3 = am[3];
- SJA1000_MODECTRL = (AFM_Bit);
- //*** Note - if you change SJA1000_MODECTRL, change it in
- // functions CAN_Init and CAN_SetAccCode also.
- do {
- SJA1000_MODECTRL = 0x00;
- }
- while ((SJA1000_MODECTRL & RM_RR_Bit) != 0x00); // leave reset state
- }
- /*!
- * \fn SJASetBaudrate(NUTDEVICE * dev, uint32_t baudrate)
- * \brief Sets the baudrate
- *
- *
- * \param dev Pointer to the device structure
- *
- * \param baudrate Baudrate (One of the defined baudrates. See sja1000.h)
- */
- uint8_t SJASetBaudrate(NUTDEVICE * dev, uint32_t baudrate)
- {
- uint8_t result = 0;
- ((IFCAN *) (dev->dev_icb))->can_baudrate = baudrate;
- while ((SJA1000_MODECTRL & RM_RR_Bit) == 0x00) // enter reset state
- SJA1000_MODECTRL = (RM_RR_Bit | SJA1000_MODECTRL);
- switch (baudrate) // setting actual bustiming
- { // all @ 16 Mhz
- case CAN_SPEED_10K:
- SJA1000_BT0 = 113;
- SJA1000_BT1 = 28;
- break;
- case CAN_SPEED_20K:
- SJA1000_BT0 = 88;
- SJA1000_BT1 = 28;
- break;
- case CAN_SPEED_50K:
- SJA1000_BT0 = 73;
- SJA1000_BT1 = 28;
- break;
- case CAN_SPEED_100K:
- SJA1000_BT0 = 68;
- SJA1000_BT1 = 28;
- break;
- case CAN_SPEED_125K:
- SJA1000_BT0 = 67;
- SJA1000_BT1 = 28;
- break;
- case CAN_SPEED_250K:
- SJA1000_BT0 = 65;
- SJA1000_BT1 = 28;
- break;
- case CAN_SPEED_500K:
- SJA1000_BT0 = 64;
- SJA1000_BT1 = 28;
- break;
- case CAN_SPEED_800K:
- SJA1000_BT0 = 64;
- SJA1000_BT1 = 22;
- break;
- case CAN_SPEED_1M:
- SJA1000_BT0 = 64;
- SJA1000_BT1 = 20;
- break;
- default:
- result = 1;
- }
- do {
- SJA1000_MODECTRL = 0x00;
- }
- while ((SJA1000_MODECTRL & RM_RR_Bit) != 0x00); // leave reset state
- return result;
- }
- /*!
- * \fn SJATxFrame(CANFRAME * CAN_frame)
- * \brief Sends a CAN Frane
- *
- *
- * \param CAN_frame Pointer to the send frame
- */
- void SJATxFrame(CANFRAME * CAN_frame)
- {
- uint32_t temp_id;
- if (CAN_frame->ext) {
- temp_id = CAN_frame->id << 3;
- SJA1000_TxFrameInfo = CAN_frame->len | CAN_29 | (CAN_frame->rtr ? CAN_RTR : 0);
- SJA1000_Tx1 = (uint8_t) (temp_id >> 24); // load High Byte
- SJA1000_Tx2 = (uint8_t) (temp_id >> 16); // load High Byte
- SJA1000_Tx3 = (uint8_t) (temp_id >> 8); // load High Byte
- SJA1000_Tx4 = (uint8_t) (temp_id & 0x00F8); // Low Byte and ignore bit 0-2
- SJA1000_Tx5 = CAN_frame->byte[0];
- SJA1000_Tx6 = CAN_frame->byte[1];
- SJA1000_Tx7 = CAN_frame->byte[2];
- SJA1000_Tx8 = CAN_frame->byte[3];
- SJA1000_Tx9 = CAN_frame->byte[4];
- SJA1000_Tx10 = CAN_frame->byte[5];
- SJA1000_Tx11 = CAN_frame->byte[6];
- SJA1000_Tx12 = CAN_frame->byte[7];
- } else {
- temp_id = CAN_frame->id << 21;
- SJA1000_TxFrameInfo = CAN_frame->len | (CAN_frame->rtr ? CAN_RTR : 0);
- SJA1000_Tx1 = (uint8_t) (temp_id >> 24); // load High Byte
- SJA1000_Tx2 = (uint8_t) (temp_id >> 16) & 0xE0; // Low Byte and ignore bit 0-4
- SJA1000_Tx3 = CAN_frame->byte[0];
- SJA1000_Tx4 = CAN_frame->byte[1];
- SJA1000_Tx5 = CAN_frame->byte[2];
- SJA1000_Tx6 = CAN_frame->byte[3];
- SJA1000_Tx7 = CAN_frame->byte[4];
- SJA1000_Tx8 = CAN_frame->byte[5];
- SJA1000_Tx9 = CAN_frame->byte[6];
- SJA1000_Tx10 = CAN_frame->byte[7];
- }
- SJA1000_CMD = TR_Bit; // Start Transmission
- }
- /*!
- * \fn SJARxFrame(CANFRAME * CAN_frame)
- * \brief Receives a CAN Frane
- *
- *
- * \param CAN_frame Pointer to the receive frame
- */
- void SJARxFrame(CANFRAME * CAN_frame)
- {
- uint8_t FrameInfo = SJA1000_RxFrameInfo;
- CAN_frame->len = FrameInfo & 0x0F; // frame info mask off higher 4 bits
- CAN_frame->ext = FrameInfo & CAN_29 ? 1 : 0;
- CAN_frame->rtr = FrameInfo & CAN_RTR ? 1 : 0;
- if (CAN_frame->ext) {
- CAN_frame->id = (((uint32_t) SJA1000_Rx1 << 24) |
- ((uint32_t) SJA1000_Rx2 << 16) |
- ((uint32_t) SJA1000_Rx3 << 8) |
- ((uint32_t) SJA1000_Rx4 & 0xF8)) >> 3;
- CAN_frame->byte[0] = SJA1000_Rx5;
- CAN_frame->byte[1] = SJA1000_Rx6;
- CAN_frame->byte[2] = SJA1000_Rx7;
- CAN_frame->byte[3] = SJA1000_Rx8;
- CAN_frame->byte[4] = SJA1000_Rx9;
- CAN_frame->byte[5] = SJA1000_Rx10;
- CAN_frame->byte[6] = SJA1000_Rx11;
- CAN_frame->byte[7] = SJA1000_Rx12; // just fill the whole struct, less CPU cycles
- } else {
- CAN_frame->id = (((uint32_t) SJA1000_Rx1 << 24) |
- (uint32_t) SJA1000_Rx2 << 16) >> 21; // id_h and id_l
- CAN_frame->byte[0] = SJA1000_Rx3;
- CAN_frame->byte[1] = SJA1000_Rx4;
- CAN_frame->byte[2] = SJA1000_Rx5;
- CAN_frame->byte[3] = SJA1000_Rx6;
- CAN_frame->byte[4] = SJA1000_Rx7;
- CAN_frame->byte[5] = SJA1000_Rx8;
- CAN_frame->byte[6] = SJA1000_Rx9;
- CAN_frame->byte[7] = SJA1000_Rx10; // just fill the whole struct, less CPU cycles
- }
- SJA1000_CMD = RRB_Bit; // release the receive buffer
- }
- /*!
- * \fn CAN_Tx(void *arg)
- * \brief CAN transmitter thread.
- *
- *
- * This thread transmits data if there's some in the output buffer.
- * It runs with high priority.
- */
- THREAD(CAN_Tx, arg)
- {
- NUTDEVICE *dev;
- CANINFO *ci;
- CANFRAME out_frame;
- dev = arg;
- ci = (CANINFO *) dev->dev_dcb;
- NutThreadSetPriority(16);
- while (1) {
- NutEventWait(&ci->can_tx_rdy, NUT_WAIT_INFINITE);
- while ((SJA1000_STATUS & TBS_Bit) == TBS_Bit) // if transmit buffer released
- {
- out_frame = CANBufferGetMutex(&CAN_TX_BUF);
- SJATxFrame(&out_frame); // using SJA1000 TX buffer
- ci->can_tx_frames++;
- }
- }
- }
- /*!
- * \fn SJAInterrupt (void * arg)
- * \brief SJA interrupt entry.
- *
- * The interrupt handler posts events to the rx and tx thread wait queue.
- * receive interrupt will be disabled on reception and will be enabled by the
- * rx thread again. Otherwise interrupt would not stop (level triggered)
- */
- static void SJAInterrupt(void *arg)
- {
- CANINFO *ci;
- volatile uint8_t irq = SJA1000_INT;
- CANFRAME in_frame;
- ci = (CANINFO *) (((NUTDEVICE *) arg)->dev_dcb);
- ci->can_interrupts++;
- if (((irq & TI_Bit) == TI_Bit)) // transmit IRQ fired
- {
- NutEventPostFromIrq(&ci->can_tx_rdy);
- }
- if ((irq & RI_Bit) == RI_Bit) // Receive IRQ fired
- {
- if (CAN_RX_BUF.size-CAN_RX_BUF.datalength > 0)
- {
- SJARxFrame(&in_frame);
- CANBufferPut(&CAN_RX_BUF, &in_frame);
- if (CAN_RX_BUF.size==CAN_RX_BUF.datalength)
- SJA1000_IEN &= (~RIE_Bit); // Disable RX IRQ until data has been poped from input buffer
- NutEventPostFromIrq(&ci->can_rx_rdy);
- ci->can_rx_frames++;
- }
- }
- if ((irq & EI_Bit) == EI_Bit) //Error IRQ fired
- {
- ci->can_errors++;
- // TODO: Handle error
- } else if ((irq & DOI_Bit) == DOI_Bit) //Error IRQ fired
- {
- ci->can_overruns++;
- SJA1000_CMD = CDO_Bit; // Clear DO status;
- // TODO: Handle overrun
- }
- }
- /*!
- * \fn SJAInit(NUTDEVICE * dev)
- * \brief Initialize SJA1000 Canbus interface.
- *
- *
- * Applications typically do not use this function, but
- * call NutRegisterDevice().
- *
- * \param dev Identifies the device to initialize. The
- * structure must be properly set.
- */
- int SJAInit(NUTDEVICE * dev)
- {
- IFCAN *ifc;
- sja_base = dev->dev_base;
- if (sja_base == 0x0000) sja_base = SJA_BASE;
- ifc = dev->dev_icb;
- memset(dev->dev_dcb, 0, sizeof(CANINFO));
- CANBufferInit(&CAN_RX_BUF, CAN_BufSize);
- CANBufferInit(&CAN_TX_BUF, CAN_BufSize);
- while ((SJA1000_MODECTRL & RM_RR_Bit) == 0x00) // entering reset mode
- SJA1000_MODECTRL = (RM_RR_Bit | SJA1000_MODECTRL);
- SJA1000_CLK_DIV = (CANMode_Bit | CBP_Bit | DivBy2 | ClkOff_Bit); // sets clock divide register
- SJA1000_IEN = (ClrIntEnSJA); // Disables CAN IRQ
- SJA1000_AC0 = ifc->can_acc_code[0];
- SJA1000_AC1 = ifc->can_acc_code[1];
- SJA1000_AC2 = ifc->can_acc_code[2];
- SJA1000_AC3 = ifc->can_acc_code[3];
- SJA1000_AM0 = ifc->can_acc_mask[0];
- SJA1000_AM1 = ifc->can_acc_mask[1];
- SJA1000_AM2 = ifc->can_acc_mask[2];
- SJA1000_AM3 = ifc->can_acc_mask[3];
- switch (ifc->can_baudrate) // setting actual bustiming
- { // all @ 16 Mhz
- case CAN_SPEED_10K:
- SJA1000_BT0 = 113;
- SJA1000_BT1 = 28;
- break;
- case CAN_SPEED_20K:
- SJA1000_BT0 = 88;
- SJA1000_BT1 = 28;
- break;
- case CAN_SPEED_50K:
- SJA1000_BT0 = 73;
- SJA1000_BT1 = 28;
- break;
- case CAN_SPEED_100K:
- SJA1000_BT0 = 68;
- SJA1000_BT1 = 28;
- break;
- case CAN_SPEED_125K:
- SJA1000_BT0 = 67;
- SJA1000_BT1 = 28;
- break;
- case CAN_SPEED_250K:
- SJA1000_BT0 = 65;
- SJA1000_BT1 = 28;
- break;
- case CAN_SPEED_500K:
- SJA1000_BT0 = 64;
- SJA1000_BT1 = 28;
- break;
- case CAN_SPEED_800K:
- SJA1000_BT0 = 64;
- SJA1000_BT1 = 22;
- break;
- case CAN_SPEED_1M:
- SJA1000_BT0 = 64;
- SJA1000_BT1 = 20;
- break;
- default:
- return errCAN_INVALID_BAUD;
- }
- SJA1000_OUTCTRL = (Tx1Float | Tx0PshPull | NormalMode); // Set up Output Control Register
- SJA1000_IEN = (RIE_Bit | TIE_Bit | EIE_Bit | DOIE_Bit ); // Enables receive IRQ
- SJA1000_MODECTRL = (AFM_Bit); // set single filter mode + sleep
- // *** Note - if you change SJA1000_MODECTRL, change it in
- // functions SJASetAccMask and SJASetAccCode also.
- do {
- SJA1000_MODECTRL = 0x00;
- }
- while ((SJA1000_MODECTRL & RM_RR_Bit) != 0x00); // leaves reset mode
- NutEnterCritical();
- if (NutRegisterIrqHandler(&SJA_SIGNAL, SJAInterrupt, dev)) {
- NutExitCritical();
- return -1;
- }
- cbi(EIMSK, SJA_SIGNAL_BIT);
- if (SJA_SIGNAL_BIT < 4) // Set corresponding interrupt to low
- { // level interrupt
- #ifdef __AVR_ENHANCED__
- cbi(EICRA, (SJA_SIGNAL_BIT << 1));
- cbi(EICRA, (SJA_SIGNAL_BIT << 1) + 1);
- #endif /* __AVR_ENHANCED__ */
- } else {
- cbi(EICR, ((SJA_SIGNAL_BIT - 4) << 1));
- cbi(EICR, ((SJA_SIGNAL_BIT - 4) << 1) + 1);
- }
- SJA1000_INT; // Read interrupt register to clear pendin bits
- sbi(EIMSK, SJA_SIGNAL_BIT);
- sbi(PORTE, SJA_SIGNAL_BIT);
- NutThreadCreate("sjacantx", CAN_Tx, dev, 256);
- NutExitCritical();
- return 0;
- }
- /*!
- * \brief Interface information structure.
- *
- * This struct stores some interface parameters like bautdate and
- * acceptance mask / code. Beside this Callback handlers are registered.
- */
- IFCAN ifc_sja1000 = {
- CAN_IF_2B, /*!< \brief Interface type. */
- CAN_SPEED_500K, /*!< \brief Baudrate of device. */
- {0xFF, 0xFF, 0xFF, 0xFF}
- , /*!< \brief Acceptance mask */
- {0x00, 0x00, 0x00, 0x00}
- , /*!< \brief Acceptance code */
- NUT_WAIT_INFINITE, /*!< \brief Receive time-out */
- SJARxAvail, /*!< \brief Data in RxBuffer available? */
- SJATxFree, /*!< \brief TxBuffer free? */
- SJAInput, /*!< \brief CAN Input routine */
- SJAOutput, /*!< \brief CAN Output routine */
- SJASetAccCode, /*!< \brief Set acceptance code */
- SJASetAccMask, /*!< \brief Set acceptance mask */
- SJASetBaudrate /*!< \brief Set baudrate */
- };
- /*!
- * \brief Device information structure.
- *
- * Applications must pass this structure to NutRegisterDevice()
- * to bind this CAN device driver to the Nut/OS kernel.
- *
- * \note The interrupt handler of this driver uses a significant amount
- * of stack space, which may require to increase thread stacks of
- * all threads by at least 32 bytes. Furthermore, it requires quite
- * some time to execute and may degrade overall system performance.
- */
- NUTDEVICE devSJA1000 = {
- 0, /*!< Pointer to next device. */
- {'s', 'j', 'a', '1', '0', '0', '0', 0, 0}
- , /*!< Unique device name. */
- IFTYP_CAN, /*!< Type of device. */
- 0, /*!< Base address. */
- 0, /*!< First interrupt number. */
- &ifc_sja1000, /*!< Interface control block. */
- &dcb_sja1000, /*!< Driver control block. */
- SJAInit, /*!< Driver initialization routine. */
- 0, /*!< Driver specific control function. */
- 0, /*!< Read from device. */
- 0, /*!< Write to device. */
- 0, /*!< Write from program space data to device. */
- 0, /*!< Open a device or file. */
- 0, /*!< Close a device or file. */
- 0, /*!< Request file size. */
- 0, /*!< Select function, optional, not yet implemented */
- };
- #else
- void keep_icc_happy(void)
- {
- }
- #endif
- /*@}*/
|