📄 toucan.c
字号:
** 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 + -