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

📄 toucan.c

📁 风河编写的摩托罗拉toucan模块的驱动代码
💻 C
📖 第 1 页 / 共 5 页
字号:
** This function clears data overrun flag for a particular channel* Valid only for channels with mode = WNCAN_CHN_RECEIVE or* WNCAN_CHN_RTR_REQUESTER** RETURNS:        Ok or ERROR** ERRNO:          S_can_illegal_channel_no, S_can_illegal_config**/static STATUS TouCAN_ClearMessageLost( struct WNCAN_Device *pDev, UCHAR channelNum ){        struct canAccess *pcanAccess;       TouCANBuf         pTouCanBufs;    TouCAN            pTouCanRegs;    volatile TouCAN_StandardMsgType *buffer;    volatile USHORT   len;    int               retCode = ERROR; /* pessimistic */        if (channelNum >= TOUCAN_MAX_MSG_OBJ)    {        errnoSet(S_can_illegal_channel_no);        goto exit;    }        if((pDev->pCtrl->chnMode[channelNum] != WNCAN_CHN_RECEIVE) &&        (pDev->pCtrl->chnMode[channelNum] != WNCAN_CHN_RTR_REQUESTER))    {        errnoSet(S_can_illegal_config);                goto exit;    }            /*    * Get pointer to TouCAN registers and channels.        */    pcanAccess = (struct canAccess *)pDev->pCtrl->csData;    pTouCanRegs = (TouCAN)pcanAccess->pTouCanRegs;        pTouCanBufs = (TouCANBuf)pcanAccess->pTouCanBufs;                   buffer = &pTouCanBufs->can_MSG[channelNum];                     /*Save and later restore data length*/    len = buffer->Control & 0x000f;        /*Clear overflow code, and replace with buffer full indicaition*/    buffer->Control = TOUCAN_BUFFER_FULL | len;        retCode = OK;    exit:    return retCode;}/************************************************************************** TouCAN_IsRTR - Tests if the message has the RTR bit set. * The RTR bit of an incoming remote request is not stored in the channel* registers on the TouCAN. CAN_IsRTR cannot be implemented directly. The* TouCAN has an automatic response feature, that must be used to respond * to incoming remote requests.* To do this:* 1. Select channel mode WNCAN_CHN_RTR_RESPONDER * 2. On this channel call CAN_WriteID and set up matching id for incoming*    remote request* 3. Set up response data by calling CAN_WriteData** RETURNS:        -1 *   * ERRNO:          S_can_use_auto_response_feature**/static int TouCAN_IsRTR( struct WNCAN_Device *pDev, UCHAR channelNum ){    errnoSet(S_can_use_auto_response_feature);    return -1;}/************************************************************************** TouCAN_SetRTR - Sets RTR bit** The TouCAN supports transmitting and receiving a message in the same * channel. The driver supports special channel modes namely * WNCAN_CHN_RTR_REQUESTER and WMCAN_CHN_RTR_RESPONDER to handle setting up* RTR messages easier. * ** RETURNS:        ERROR*   * ERRNO:          S_can_use_rtr_requester_channel_mode**/static STATUS TouCAN_SetRTR( struct WNCAN_Device *pDev, UCHAR channelNum, BOOL  rtr ){    errnoSet(S_can_use_rtr_requester_channel_mode);    return ERROR;}/************************************************************************** TouCAN_TxAbort - abort the current CAN transmission** This routine aborts any current CAN transmissions on the controller.** RETURNS:        N/A** ERRNO:          N/A**/static void TouCAN_TxAbort( struct WNCAN_Device *pDev ){    struct canAccess *pcanAccess;       TouCANBuf         pTouCanBufs;    volatile TouCAN_StandardMsgType *buffer;            UCHAR         i;              /*    * Get pointer to TouCAN registers and channels.        */    pcanAccess = (struct canAccess *)pDev->pCtrl->csData;    pTouCanBufs = (TouCANBuf)pcanAccess->pTouCanBufs;                           for(i=0;i<TOUCAN_MAX_MSG_OBJ;i++)    {        if((pDev->pCtrl->chnMode[i] == WNCAN_CHN_TRANSMIT) &&            ~(pDev->pCtrl->chnMode[i] & WNCAN_IS_CHN_RTR))        {                        buffer = &pTouCanBufs->can_MSG[i];                          /*Make the channel inactive*/                            /*            * A write access to the control field of the channel            * will make deactivate it, unless the message has been            * tranferred to the serial channel.            * However, no interrupt will be requested.            */            buffer->Control = 0x0080;        }    }        return;}/************************************************************************** TouCAN_Sleep - puts the CAN controller of the device into sleep mode* Auto awake feature is always enabled** RETURNS:        OK always*   * ERRNO:          N/A**/static STATUS TouCAN_Sleep( struct WNCAN_Device *pDev ){    struct canAccess *pcanAccess;       TouCAN            pTouCanRegs;            USHORT            temp;        /* Get pointer to TouCAN registers. */       pcanAccess = (struct canAccess *)pDev->pCtrl->csData;    pTouCanRegs = (TouCAN)pcanAccess->pTouCanRegs;        temp = pTouCanRegs->can_MCR;        /*Enable low power stop (sleep) mode*/    pTouCanRegs->can_MCR = (temp | TOUCAN_STOP | TOUCAN_SELFWAKE);        while((pTouCanRegs->can_MCR & TOUCAN_STOPACK) != TOUCAN_STOPACK)        ;            return OK;}/************************************************************************** TouCAN_WakeUp - gets the CAN controller out of sleep mode* Auto awake feature is always enabled** RETURNS:        OK always*   * ERRNO:          N/A**/static STATUS TouCAN_WakeUp( struct WNCAN_Device *pDev ){    struct canAccess *pcanAccess;       TouCAN            pTouCanRegs;            USHORT            temp;        /* Get pointer to TouCAN registers. */       pcanAccess = (struct canAccess *)pDev->pCtrl->csData;    pTouCanRegs = (TouCAN)pcanAccess->pTouCanRegs;        temp = pTouCanRegs->can_MCR;        temp &= ~(TOUCAN_STOP |TOUCAN_SELFWAKE);    /*Disable  sleep  mode*/    pTouCanRegs->can_MCR = temp;        while((pTouCanRegs->can_MCR & TOUCAN_STOPACK) == TOUCAN_STOPACK)        ;           return OK;}/************************************************************************** TouCAN_GetIntStatus - get the interrupt status on the controller** This function returns the interrupt status on the controller: **    WNCAN_INT_NONE     = no interrupt occurred*    WNCAN_INT_ERROR    = bus error*    WNCAN_INT_TX       = interrupt resuting from a CAN transmission*    WNCAN_INT_RX       = interrupt resulting form message reception*    WNCAN_INT_BUS_OFF  = interrupt resulting from bus off condition*    WNCAN_INT_WAKE_UP  = interrupt resulting from controller waking up*                         after being put in sleep mode*    WNCAN_INT_SPURIOUS = unknown interrupt** NOTE: If the interrupt was caused by the transmission or reception of a * message, the channel number that generated the interrupt is set; otherwise,* this value is undefined. * ERRNO: N/A **/static WNCAN_IntType TouCAN_GetIntStatus( struct WNCAN_Device *pDev, UCHAR *channelNum ){    WNCAN_IntType   intStatus = WNCAN_INT_NONE;    struct canAccess *pcanAccess;    TouCAN            pTouCanRegs;    TouCANBuf         pTouCanBufs;    volatile TouCAN_StandardMsgType *buffer;    volatile USHORT   regInt;    volatile USHORT   msgCode;    volatile USHORT   statusTemp;        /*    * Get pointer to TouCAN registers and channels.        */    pcanAccess = (struct canAccess *)pDev->pCtrl->csData;    pTouCanRegs = (TouCAN)pcanAccess->pTouCanRegs;                  pTouCanBufs = (TouCANBuf)pcanAccess->pTouCanBufs;        /*    * And the interrupt register and the interrupt mask register        */    regInt = pTouCanRegs->can_IFLAG & pTouCanRegs->can_IMASK;    statusTemp = pTouCanRegs->can_ESTAT;         if(regInt == 0)    {        if(pTouCanRegs->can_CR0 & TOUCAN_ERROR_MASK_ENABLE)        {            if( statusTemp & TOUCAN_ERRINT)            {                intStatus = WNCAN_INT_ERROR;            }                    }                if(pTouCanRegs->can_CR0 & TOUCAN_BOFF_MASK_ENABLE)        {            if( statusTemp & TOUCAN_BOFFINT)            {                intStatus = WNCAN_INT_ERROR;            }        }                if(pTouCanRegs->can_MCR & TOUCAN_WAKEUPINT_ENABLE)        {            if( statusTemp & TOUCAN_WAKEINT)            {                intStatus = WNCAN_INT_WAKE_UP;                            }                    }            }    else    {        for(*channelNum = 0; *channelNum < TOUCAN_MAX_MSG_OBJ ; ++*channelNum)        {            if( regInt & (1 << *channelNum))            {                buffer = &pTouCanBufs->can_MSG[*channelNum];                        msgCode = buffer->Control & 0x00f0;                                                /*                * Check in case busy bit is set. May be set if a                * response to remote request is being transferred from the                * serial buffer. Busy bit should not be set for a data rx,                * as we poll the IFLAG register before accessing the channel.                * If set, return error.                */                if(msgCode & TOUCAN_BUFFER_BUSY) {                    /*break as channel is busy*/                    break;                }                                                switch(msgCode) {                case TOUCAN_BUFFER_FULL:                    intStatus = WNCAN_INT_RX;                    break;                case TOUCAN_RESPONSE_TO_REMOTE:                                             intStatus = WNCAN_INT_RTR_RESPONSE;                    break;                                  case  TOUCAN_TX_NOT_READY:                    intStatus = WNCAN_INT_TX;                    break;                case TOUCAN_BUFFER_OVERRUN:                    intStatus = WNCAN_INT_ERROR;                    break;                case TOUCAN_BUFFER_READY_TO_RX:                    intStatus = WNCAN_INT_TX;                                            break;                default:                    /*To add errnoset to flag a fatal error*/                    intStatus = WNCAN_INT_NONE;                }                            }        }                /* Read the free running timer to unlock the controller */        timerRead = pTouCanRegs->can_TIMER;    }            return intStatus;}        /************************************************************************** TouCANISR - interrupt service routine ** RETURNS: N/A*   * ERRNO: N/A**/void TouCANISR( ULONG context ){    WNCAN_IntType      intStatus;    struct WNCAN_Device  *pDev;    struct canAccess     *pcanAccess;    TouCAN               pTouCanRegs;            TouCANBuf            pTouCanBufs;    volatile TouCAN_StandardMsgType *buffer;        volatile USHORT      regInt;    volatile USHORT      msgCode;    volatile USHORT      statusTemp;    UCHAR                chnNum=16;        /*    * Get pointer to TouCAN registers and channels.        */        if ((pDev = (struct WNCAN_Device *)context) == NULL) return;    pcanAccess  = (struct canAccess *)pDev->pCtrl->csData;    pTouCanRegs = (TouCAN)pcanAccess->pTouCanRegs;                  pTouCanBufs = (TouCANBuf)pcanAccess->pTouCanBufs;        while(1)    {        /* And the interrupt register and the interrupt mask register */          intStatus  = WNCAN_INT_NONE;        regInt     = pTouCanRegs->can_IFLAG & pTouCanRegs->can_IMASK;        statusTemp = pTouCanRegs->can_ESTAT;                 if(regInt == 0) {            if(pTouCanRegs->can_CR0 & TOUCAN_ERROR_MASK_ENABLE)            {                if( statusTemp & TOUCAN_ERRINT)                {                    intStatus = WNCAN_INT_ERROR;                                        /*                    * Clear the error interrupt bit in the ESTAT register                     * by reading it as a 1 and writing a 0                    */                    pTouCanRegs->can_ESTAT &= ~(TOUCAN_ERRINT);                }                            }                        if(pTouCanRegs->can_CR0 & TOUCAN_BOFF_MASK_ENABLE)            {                if( statusTemp & TOUCAN_BOFFINT)                {                    intStatus = WNCAN_INT_ERROR;                    /*                    * Clear the BUS OFF interrupt bit in the ESTAT register                     * by reading it as a 1 and writing a 0                    */                    pTouCanRegs->can_ESTAT &= ~(TOUCAN_BOFFINT);                                    }            }                        if(pTouCanRegs->can_MCR & TOUCAN_WAKEUPINT_ENABLE)            {                if( statusTemp & TOUCAN_WAKEINT)                {                    intStatus = WNCAN_INT_WAKE_UP;                                        /*                    * Clear the error interrupt bit in the ESTAT register                     * by reading it as a 1 and writing a 0                    */                    pTouCanRegs->can_ESTAT &= ~(TOUCAN_WAKEINT);                }                            }                    } else {            /* Find the channel with the highest pending interrupt */            for(chnNum = 0; chnNum < TO

⌨️ 快捷键说明

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