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

📄 atcan.c

📁 含有完整TCP/IP PPP协议的嵌入式操作系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/*! * AtCan interrupt service routine */static void AtCanInterrupt(void *arg){    uint8_t savedCanPage;    CANINFO *ci = (CANINFO *) (((NUTDEVICE *) arg)->dev_dcb);    savedCanPage = CANPAGE; // Save the current CAN page    ci->can_interrupts++;    //    // Check for MOB interrupt    //    if ((CANHPMOB & 0xF0) != 0xF0)    {        CANPAGE = CANHPMOB; // Switch page        // RX interrupt ?        if (bit_is_set(CANSTMOB, RXOK))        {            // Space in buffer ?            if (canRxBuf.datalength < canRxBuf.size)            {                int8_t j;                CANFRAME * bufPtr = &canRxBuf.dataptr[(canRxBuf.dataindex + canRxBuf.datalength) % canRxBuf.size];                // Extended or standard ID?                bufPtr->ext = bit_is_set(CANCDMOB, IDE);                if (bufPtr->ext)                {                    ((uint8_t *) &(bufPtr->id))[3] = CANIDT1 >> 3;                    ((uint8_t *) &(bufPtr->id))[2] = (CANIDT2 >> 3) | (CANIDT1 << 5);                    ((uint8_t *) &(bufPtr->id))[1] = (CANIDT3 >> 3) | (CANIDT2 << 5);                    ((uint8_t *) &(bufPtr->id))[0] = (CANIDT4 >> 3) | (CANIDT3 << 5);                }                else                {                    ((uint8_t *) &(bufPtr->id))[3] = 0;                    ((uint8_t *) &(bufPtr->id))[2] = 0;                    ((uint8_t *) &(bufPtr->id))[1] = CANIDT1 >> 5;                    ((uint8_t *) &(bufPtr->id))[0] = (CANIDT1 << 3) | (CANIDT2 >> 5);                }                bufPtr->len = CANCDMOB & (_BV(DLC0) | _BV(DLC1) | _BV(DLC2) | _BV(DLC3));                bufPtr->rtr = bit_is_set(CANIDT4, RTRTAG);                for (j = 0; j < 8; j++)                    bufPtr->byte[j] = CANMSG;                // Increment buffer length                canRxBuf.datalength++;                NutEventPostFromIrq(&ci->can_rx_rdy);                CANSTMOB = CANSTMOB & ~_BV(RXOK); // Data sheet requires r/m/w cycle on whole register                // Re-enable MOB for reception                CANCDMOB |= _BV(CONMOB1);                // Stat houskeeping                ci->can_rx_frames++;            }            else            {                CANSTMOB = CANSTMOB & ~_BV(RXOK); // Data sheet requires r/m/w cycle on whole register                // Re-enable MOB for reception                CANCDMOB |= _BV(CONMOB1);                // Stat houskeeping                ci->can_overruns++;            }        }        // TX interrupt ?        else if (bit_is_set(CANSTMOB, TXOK))        {            NutEventPostFromIrq(&ci->can_tx_rdy);            CANSTMOB = CANSTMOB & ~_BV(TXOK); // Data sheet requires r/m/w cycle on whole register            // Re-claim MOB            CANCDMOB &= ~(_BV(CONMOB1) | _BV(CONMOB0));        }        else        {            CANSTMOB = CANSTMOB & 0x80; // Data sheet requires r/m/w cycle on whole register        }    }    else    {        // General CAN interrupt        // //ttt   TODO: Implement it!        //ci->can_errors++;        //ci->can_overruns++;    }    CANPAGE = savedCanPage; // Restore CAN page register}/***************************************************************************** * Function definitions *****************************************************************************//*! * Checks if data is available in input buffer * * \param dev Pointer to the device structure * \return Number of frames available */u_char AtCanRxAvail(NUTDEVICE * dev){    return canRxBuf.datalength;}/*! * Checks if there's still space in output buffer * * \param dev Pointer to the device structure * \return 1 if space is available */u_char AtCanTxFree(NUTDEVICE * dev){    return (AtCanGetFreeMob() >= 0);}/*! * 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 AtCanOutput(NUTDEVICE * dev, CANFRAME * frame){    CANINFO * ci = (CANINFO *) dev->dev_dcb;    while (AtCanSendMsg(frame) == CAN_TXBUF_FULL)    {        NutEventWait(&ci->can_tx_rdy, NUT_WAIT_INFINITE);    };    // Increment counter    ci->can_tx_frames++;}/*! * 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 AtCanInput(NUTDEVICE * dev, CANFRAME * frame){    CANINFO * ci = (CANINFO *) dev->dev_dcb;    while (canRxBuf.datalength == 0)    {        NutEventWait(&ci->can_rx_rdy, NUT_WAIT_INFINITE);    }    NutEnterCritical();    // Get the first frame from buffer    *frame = canRxBuf.dataptr[canRxBuf.dataindex];    // Move index down and decrement length    canRxBuf.dataindex++;    if (canRxBuf.dataindex >= canRxBuf.size)        canRxBuf.dataindex %= canRxBuf.size;    canRxBuf.datalength--;    NutExitCritical();}/*! * Sets the acceptance code * * \param dev Pointer to the device structure * \param ac 4 byte char array with the acceptance code */void AtCanSetAccCode(NUTDEVICE * dev, u_char * ac){    memcpy(((IFCAN *) (dev->dev_icb))->can_acc_code, ac, 4);    AtCanEnableRx(RX_MOB, 0, 0, 0, 0, 0, 0); //ttt   TODO: Implement it!}/*! * Sets the acceptance mask * * \param dev Pointer to the device structure * \param am 4 byte char array with the acceptance mask */void AtCanSetAccMask(NUTDEVICE * dev, u_char * am){    memcpy(((IFCAN *) (dev->dev_icb))->can_acc_mask, am, 4);    AtCanEnableRx(RX_MOB, 0, 0, 0, 0, 0, 0); //ttt   TODO: Implement it!}/*! * Sets the CAN baudrate * * \param dev Pointer to the device structure * \param baudrate Baudrate (One of the defined baudrates. See AtCan.h) * \return 0 for success */u_char AtCanSetBaudrate(NUTDEVICE * dev, u_long baudrate){    switch (baudrate)    {        case CAN_SPEED_10K:            CANBT1 = CAN_BT1_10K;            CANBT2 = CAN_BT2_10K;            CANBT3 = CAN_BT3_10K;        break;        case CAN_SPEED_20K:            CANBT1 = CAN_BT1_20K;            CANBT2 = CAN_BT2_20K;            CANBT3 = CAN_BT3_20K;        break;        case CAN_SPEED_50K:            CANBT1 = CAN_BT1_50K;            CANBT2 = CAN_BT2_50K;            CANBT3 = CAN_BT3_50K;        break;        case CAN_SPEED_100K:            CANBT1 = CAN_BT1_100K;            CANBT2 = CAN_BT2_100K;            CANBT3 = CAN_BT3_100K;        break;        case CAN_SPEED_125K:            CANBT1 = CAN_BT1_125K;            CANBT2 = CAN_BT2_125K;            CANBT3 = CAN_BT3_125K;        break;        case CAN_SPEED_250K:            CANBT1 = CAN_BT1_250K;            CANBT2 = CAN_BT2_250K;            CANBT3 = CAN_BT3_250K;        break;        case CAN_SPEED_500K:            CANBT1 = CAN_BT1_500K;            CANBT2 = CAN_BT2_500K;            CANBT3 = CAN_BT3_500K;        break;        case CAN_SPEED_800K:            CANBT1 = CAN_BT1_800K;            CANBT2 = CAN_BT2_800K;            CANBT3 = CAN_BT3_800K;        break;        case CAN_SPEED_1M:            CANBT1 = CAN_BT1_1M;            CANBT2 = CAN_BT2_1M;            CANBT3 = CAN_BT3_1M;        break;        case CAN_SPEED_CUSTOM:            // Do nothing, user sets baudrate directly but don't report an error        break;        default:        return 1;    }    ((IFCAN *) (dev->dev_icb))->can_baudrate = baudrate;    return 0;}/*! * Initialize CAN interface. * * Applications typically do not use this function, but * call NutRegisterDevice(). * * \param dev Identifies the device to initialize. The *            structure must be properly set. * \return 0 for successful initialisation or -1 in case init failed */int AtCanInit(NUTDEVICE * dev){    int8_t mob, i;    memset(dev->dev_dcb, 0, sizeof(CANINFO));    // Init receive buffer    canRxBuf.dataptr = NutHeapAlloc(CAN_BUF_SIZE * sizeof(CANFRAME));    canRxBuf.size = CAN_BUF_SIZE;    canRxBuf.dataindex = 0;    canRxBuf.datalength = 0;    // Disable AT90CAN128 CAN system    CANGCON &= ~_BV(ENASTB);    loop_until_bit_is_clear(CANGSTA, ENFG);    // Clear all MOBs    for (mob = 0; mob < MAX_NO_MOB; mob++)    {        CANPAGE = mob << 4;        CANSTMOB = 0; // Clear status register        CANCDMOB = 0; // Clear control register        CANHPMOB = 0; // Clear HP flags        // Clear identifier tag        CANIDT1 = 0;        CANIDT2 = 0;        CANIDT3 = 0;        CANIDT4 = 0;        // Clear identifier mask        CANIDM1 = 0;        CANIDM2 = 0;        CANIDM3 = 0;        CANIDM4 = 0;        for (i = 0; i < 8; i++)        {            CANMSG = 0;        }    }    // Set baudrate    AtCanSetBaudrate(dev, ifc_atcan.can_baudrate); // Errors silently ingnored here    // Install IRQ handler    if (NutRegisterIrqHandler(&sig_CAN_TRANSFER, AtCanInterrupt, dev))        return -1;    // Enable all MOB interrupts and RX, TX etc    CANIE1 = 0x7F;    CANIE2 = 0xFF;    CANGIE = _BV(ENIT)| _BV(ENRX) | _BV(ENTX) ;    // Enable receiving MOBs    AtCanEnableRx(RX_MOB, 0, 0, 0, 0, 0, 0);    // Enable AT90CAN128 CAN system    CANGCON |= _BV(ENASTB);    loop_until_bit_is_set(CANGSTA, ENFG);    return 0;}/*! * Interface information structure. * * This structure stores some interface parameters like bit rate, * acceptance mask, acceptance code and callback handlers. */IFCAN ifc_atcan = {    CAN_IF_2B,                 /*!< \brief Interface type. */    CAN_SPEED_125K,            /*!< \brief Baudrate of device. */    {0xFF, 0xFF, 0xFF, 0xFF},  /*!< \brief Acceptance mask */    {0x00, 0x00, 0x00, 0x00},  /*!< \brief Acceptance code */    AtCanRxAvail,              /*!< \brief Data in RxBuffer available? */    AtCanTxFree,               /*!< \brief TxBuffer free? */    AtCanInput,                /*!< \brief CAN Input routine */    AtCanOutput,               /*!< \brief CAN Output routine */    AtCanSetAccCode,           /*!< \brief Set acceptance code */    AtCanSetAccMask,           /*!< \brief Set acceptance mask */    AtCanSetBaudrate           /*!< \brief Set baudrate */};/*! * Device information structure. * * Applications must pass this structure to NutRegisterDevice() * to bind this CAN device driver to the Nut/OS kernel. */NUTDEVICE devAtCan = {    0,                          /*!< Pointer to next device. */    {'a', 't', 'c', 'a', 'n', '0', 0, 0, 0}, /*!< Unique device name. */    IFTYP_CAN,                  /*!< Type of device. */    0,                          /*!< Base address. */    0,                          /*!< First interrupt number. */    &ifc_atcan,                 /*!< Interface control block. */    &dcb_atcan,                 /*!< Driver control block. */    AtCanInit,                  /*!< 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. */};#elsestatic void keep_icc_happy(void){}#endif/*@}*/

⌨️ 快捷键说明

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