?? i82527.c
字號:
chipStuff->errorInt = FALSE; if(intMask & WNCAN_INT_WAKE_UP) chipStuff->wakeUpInt = TRUE; else chipStuff->wakeUpInt = FALSE; if((chipStuff->wakeUpInt == TRUE) || (chipStuff->errorInt == TRUE)) regCtrl |= I82527_B_SIE; else regCtrl &= ~I82527_B_SIE; /* The error warning interrupt is generated when errors on the bus exceed warning limits and if the controller becomes bus off. The interrupt is also raised when the controller goes into error active state from being bus off */ if(intMask & WNCAN_INT_BUS_OFF) { chipStuff->busOffInt = TRUE; regCtrl |= I82527_B_EIE; } else { chipStuff->busOffInt = FALSE; regCtrl &= ~I82527_B_EIE; } oldLevel = intLock(); pDev->pBrd->canOutByte(pDev, I82527_R_CTRL, regCtrl); intUnlock(oldLevel); } return retCode;}/************************************************************************** I82527_EnableInt - enable CAN interrupts** This routine enables CAN interrupts on the controller.** RETURNS: N/A* * ERRNO: N/A**/static void I82527_EnableInt ( struct WNCAN_Device *pDev ){ UCHAR regCtrl; int oldLevel; oldLevel = intLock(); /* read the control register */ regCtrl = pDev->pBrd->canInByte(pDev, I82527_R_CTRL); regCtrl |= I82527_B_IE; /* write control register */ pDev->pBrd->canOutByte(pDev, I82527_R_CTRL, regCtrl); intUnlock(oldLevel); return;}/************************************************************************** I82527_DisableInt - disable CAN interrupts** This routine disbles interrupts on the controller.** RETURNS: N/A* * ERRNO: N/A**/static void I82527_DisableInt ( struct WNCAN_Device *pDev ){ int oldLevel; UCHAR regCtrl; oldLevel = intLock(); regCtrl = pDev->pBrd->canInByte(pDev, I82527_R_CTRL); regCtrl &= ~I82527_B_IE; /* write control register */ pDev->pBrd->canOutByte(pDev, I82527_R_CTRL, regCtrl); intUnlock(oldLevel); return;}/************************************************************************** I82527_GetBusStatus - get the bus status** This routine returns the status of the CAN bus. The bus is either in a* WNCAN_BUS_OFF state resulting from an excessive number of errors, a * WNCAN_BUS_WARN state indicating that there is an abnormal rate of * occurances of errors. ** RETURNS: status of the CAN bus = WNCAN_BUS_OK, WNCAN_BUS_WARN, * or WNCAN_BUS_OFF* * ERRNO: N/A**/static WNCAN_BusStatus I82527_GetBusStatus ( struct WNCAN_Device *pDev ){ /* read the status register */ WNCAN_BusStatus regStatus = pDev->pBrd->canInByte(pDev, I82527_R_SR); if(regStatus & I82527_B_BOFF) return(WNCAN_BUS_OFF); else if (regStatus & I82527_B_WARN) return(WNCAN_BUS_WARN); else return(WNCAN_BUS_OK);}/************************************************************************** I82527_GetBusError - get the bus error** This routine returns the first bus error.** RETURNS: the first bus error* * ERRNO: N/A**/static WNCAN_BusError I82527_GetBusError ( struct WNCAN_Device *pDev ){ WNCAN_BusError error; UCHAR regStatus; /* read the status register */ regStatus = pDev->pBrd->canInByte(pDev, I82527_R_SR); switch(regStatus & 0x07) { case 1: error = WNCAN_ERR_STUFF; break; case 2: error = WNCAN_ERR_FORM; break; case 3: error = WNCAN_ERR_ACK; break; case 4: error = WNCAN_ERR_BIT; /* Bit1 error */ break; case 5: error = WNCAN_ERR_BIT; /* Bit0 error */ break; case 6: error = WNCAN_ERR_CRC; break; default: error = WNCAN_ERR_NONE; break; } return error;}/************************************************************************** I82527_GetIntStatus - get the interrupt status on the controller** This routine gets the interrupt status of the controller.* If the interrupt was caused by the transmission or reception of a * message, the channel number that generated the interrupt is set. * Otherwise, the channelNum value is set to an invalid channel number.** RETURNS: the interrupt status = WNCAN_INT_NONE, WNCAN_INT_ERROR,* WNCAN_INT_TX, or WNCAN_INT_RX* * ERRNO: N/A**/static WNCAN_IntType I82527_GetIntStatus( struct WNCAN_Device *pDev, UCHAR *channelNum ){ WNCAN_IntType intStatus=WNCAN_INT_NONE; UCHAR tmpCTRL0; UCHAR regInt; UCHAR regStatus = WNCAN_INT_NONE; struct i82527ChipSpecific *chipStuff; regInt = pDev->pBrd->canInByte(pDev, I82527_R_INT); if(regInt == 0) { intStatus = WNCAN_INT_NONE; } else if(regInt == 1) { /* Set default values in chip specific struct*/ chipStuff = (struct i82527ChipSpecific *)pDev->pCtrl->csData; /* read the status register */ regStatus = pDev->pBrd->canInByte(pDev, I82527_R_SR); /* A status change interrupt has occurred Unless the user is directly accessing the CAN controller's registers, this indicates that the user wants notification of a BUS OFF, WAKE UP or error interrupt. I82527 does not have separate interrupt sources for these conditions. Therefore, the status register must be checked and the correct cause of the status update returned. */ if((chipStuff->wakeUpInt == TRUE) && (regStatus & I82527_B_WAKE)) intStatus = WNCAN_INT_WAKE_UP; if((chipStuff->busOffInt == TRUE) && (regStatus & I82527_B_BOFF)) intStatus = WNCAN_INT_BUS_OFF; if((chipStuff->errorInt == TRUE) && (regStatus & 0x07)) intStatus = WNCAN_INT_ERROR; /* If neither of the above three conditions are true, the status change must have been due to a transmission or reception. We want this status change interrupt ignored. Tx / Rx interrupts should be flagged by channel interrupt pending bits, therefore the interrupt status is set to WNCAN_INT_SPURIOUS */ if(intStatus == WNCAN_INT_NONE) intStatus = WNCAN_INT_SPURIOUS; } else if(regInt == 2) { *channelNum = 14; intStatus = WNCAN_INT_RX; } else if(regInt <= 0x10) { *channelNum = regInt - 3; /* reading the control register 0 */ tmpCTRL0 = pDev->pBrd->canInByte(pDev, (I82527_R_XMT + (I82527_OFFS_MSG * (*channelNum)) + I82527_OFFS_CTRL0)); /* checking if this is an receive interrupt (on message object 1 to 14) */ if (tmpCTRL0 & 0x08) { intStatus = WNCAN_INT_RX; } else { intStatus = WNCAN_INT_TX; } } else { intStatus = WNCAN_INT_SPURIOUS; /* unallowed interrupt (should not happen) */ } return intStatus;}/************************************************************************** I82527_ReadID - read the CAN Id** This function reads the CAN Id corresponding to the channel number on* the controller. The standard or extended flag is set by the function.* The mode of the channel cannot be WNCAN_CHN_INACTIVE or WNCAN_CHN_INVALID** RETURNS: The CAN Id, or -1 if an input parameter is invalid** ERRNO: S_can_illegal_channel_no* S_can_illegal_config**/static long I82527_ReadID(struct WNCAN_Device *pDev, UCHAR channelNum, BOOL* ext){ UCHAR value; unsigned long msgID=0; /* invalid msg id */ if (channelNum >= I82527_MAX_MSG_OBJ) { errnoSet(S_can_illegal_channel_no); return(-1); } if((pDev->pCtrl->chnMode[channelNum] == WNCAN_CHN_INACTIVE) || (pDev->pCtrl->chnMode[channelNum] == WNCAN_CHN_INVALID)) { errnoSet(S_can_illegal_config); return(-1); } /* mark this message object as invalid */ pDev->pBrd->canOutByte(pDev, (I82527_R_XMT + (I82527_OFFS_MSG * channelNum) + I82527_OFFS_CTRL0), 0x7f); /* read the message configuration register to determine if the message is standard or extended */ value = pDev->pBrd->canInByte(pDev, (I82527_R_XMT + (I82527_OFFS_MSG * channelNum) + I82527_OFFS_MCR)); if (value & 0x4) { /* extended CAN message ID */ *ext = TRUE; value = pDev->pBrd->canInByte(pDev, (I82527_R_XMT + (I82527_OFFS_MSG * channelNum) + I82527_OFFS_ARBIT)); msgID = value << 24; value = pDev->pBrd->canInByte(pDev, (I82527_R_XMT + (I82527_OFFS_MSG * channelNum) + I82527_OFFS_ARBIT + 1)); msgID |= value << 16; value = pDev->pBrd->canInByte(pDev, (I82527_R_XMT + (I82527_OFFS_MSG * channelNum) + I82527_OFFS_ARBIT + 2)); msgID |= value << 8; value = pDev->pBrd->canInByte(pDev, (I82527_R_XMT + (I82527_OFFS_MSG * channelNum) + I82527_OFFS_ARBIT+ 3)); msgID |= value; msgID >>= 3; } else { /* standard CAN message ID */ *ext = FALSE; value = pDev->pBrd->canInByte(pDev, (I82527_R_XMT + (I82527_OFFS_MSG * channelNum) + I82527_OFFS_ARBIT)); msgID = value << 8; value = pDev->pBrd->canInByte(pDev, (I82527_R_XMT + (I82527_OFFS_MSG * channelNum) + I82527_OFFS_ARBIT + 1)); msgID |= value; msgID >>= 5; } /* mark this message object as valid */ pDev->pBrd->canOutByte(pDev, (I82527_R_XMT + (I82527_OFFS_MSG * channelNum) + I82527_OFFS_CTRL0), 0xbf); return(msgID);}/************************************************************************** I82527_WriteID - write the CAN Id to the channel number ** This function writes the CAN Id to the channel. The type of Id * (standard or extended) is specified. the behaviour of the function for* every channel mode is specified as follows:* WNCAN_CHN_INVALID: not allowed. ERROR is returned.* WNCAN_CHN_INACTIVE: not allowed. ERROR is returned.* WNCAN_CHN_RECEIVE: CAN messages with this Id will be received.* WNCAN_CHN_TRANSMIT: CAN meesage with the specified ID will be transmitted* when CAN_Tx is called* WNCAN_CHN_RTR_REQUESTER: CAN message with this id and RTR bit set will* be transmitted when CAN_TX is called* WNCAN_CHN_RTR_RESPONDER: CAN message with this id will be automatically* transmitted when a matching RTR request is received. CAN_WriteData should* be called to set up data for response.*** RETURNS: OK, or ERROR** ERRNO: S_can_illegal_channel_no,* S_can_illegal_config**/static STATUS I82527_WriteID ( struct WNCAN_Device *pDev, UCHAR channelNum, unsigned long canId, BOOL ext ){ STATUS retCode = ERROR; /* pessimistic */ UCHAR value; UCHAR prevState; if (channelNum >= I82527_MAX_MSG_OBJ) { errnoSet(S_can_illegal_channel_no); } else if((pDev->pCtrl->chnMode[channelNum] == WNCAN_CHN_INACTIVE) || (pDev->pCtrl->chnMode[channelNum] == WNCAN_CHN_INVALID)) { errnoSet(S_can_illegal_config); } else { /*Check if EnableChannel has been called earlier and channel marked as valid. If yes, store state to restore later */ prevState = pDev->pBrd->canInByte(pDev, (I82527_R_XMT + (I82527_OFFS_MSG * channelNum) + I82527_OFFS_CTRL0)); /* mark message object as invalid: MsgVal = 0 1 unchanged transmit interrupt enable: TXIE = 1 1 unchanged receive interrrupt enable: RXIE = 1 1 reset interrupt pending: IntPnd = 0 1 7 6 5 4 3 2 1 0 MsgVal TXIE RXIE IntPnd */ pDev->pBrd->canOutByte(pDev, (I82527_R_XMT + (I82527_OFFS_MSG * channelNum) + I82527_OFFS_CTRL0), 0x7d); /* remote transmission pending unchanged RmtPnd = 0 1 reset transmit request: TxRqst = 0 1 reset new data: NewDat = 0 1 set CPU update : CPUUpd = 1 0 7 6 5 4 3 2 1 0 RmtPnd TxRqst NewDat CPUUpd */ pDev->pBrd->canOutByte(pDev, (I82527_R_XMT + (I82527_OFFS_MSG * channelNum) + I82527_OFFS_CTRL1), 0x56); if (ext == FALSE) { /* standard message */ value = pDev->pBrd->canInByte(pDev, (I82527_R_XMT +
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -