⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sja1000.c

📁 含有完整TCP/IP PPP协议的嵌入式操作系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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 EGNITE SOFTWARE GMBH 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 EGNITE * SOFTWARE GMBH 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 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. *//* * $Log: sja1000.c,v $ * Revision 1.2  2005/10/24 18:02:34  haraldkipp * Fixes for ATmega103. * * Revision 1.1  2005/07/26 18:02:40  haraldkipp * Moved from dev. * * Revision 1.8  2005/05/27 14:09:56  olereinhardt * Fixed a bug in irq initialisation * * Revision 1.7  2005/01/24 21:12:04  freckle * renamed NutEventPostFromIRQ into NutEventPostFromIrq * * Revision 1.6  2005/01/21 16:49:45  freckle * Seperated calls to NutEventPostAsync between Threads and IRQs * * Revision 1.5  2004/11/12 16:27:42  olereinhardt * Added critical section around NutEventPostAsync * * Revision 1.4  2004/09/17 14:31:37  olereinhardt * Compile only if __GNUC__ defined * * Revision 1.3  2004/06/08 14:50:25  olereinhardt * Removed receive thread and moved input data handling into irq handler. Much faster now on reception. * * Revision 1.1  2004/06/07 15:11:49  olereinhardt * Initial checkin * *//*! * \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>#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#endifCANINFO dcb_sja1000;volatile u_short sja_base = 0x0000;struct _CANBuffer {    CANFRAME *dataptr;          // the physical memory address where the buffer is stored    u_short size;               // the allocated size of the buffer    u_short datalength;         // the length of the data currently in the buffer    u_short 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#endifCANBuffer CAN_RX_BUF;CANBuffer CAN_TX_BUF;void CANBufferInit(CANBuffer * buffer,u_short 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 routinesCANFRAME 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    }}u_short 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 u_char SJARxAvail(NUTDEVICE * dev){    return CAN_RX_BUF.datalength;}/*! * \fn    SJATxAvail(NUTDEVICE * dev) * \brief checks if there's still space in output buffer * * \param dev Pointer to the device structure */inline u_char 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 */void SJAInput(NUTDEVICE * dev, CANFRAME * frame){    u_char ready = 0;    CANINFO *ci;        ci = (CANINFO *) dev->dev_dcb;    while (!ready)    {        if (CAN_RX_BUF.datalength==0)             NutEventWait(&ci->can_rx_rdy, NUT_WAIT_INFINITE);        NutEnterCritical();        if (CAN_RX_BUF.datalength)        {            *frame = CANBufferGet(&CAN_RX_BUF);            ready  = 1;        }        NutExitCritical();    }    SJA1000_IEN |= (RIE_Bit);       // enables IRQ since buffer has space}/*! * \fn    SJASetAccCode(NUTDEVICE * dev, u_char * 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, u_char * 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, u_char * 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, u_char * 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, u_long baudrate) * \brief Sets the baudrate  * * * \param dev Pointer to the device structure *  * \param baudrate Baudrate (One of the defined baudrates. See sja1000.h) */u_char SJASetBaudrate(NUTDEVICE * dev, u_long baudrate){    u_char 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:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -