📄 sja1000.c
字号:
}
/************************************************************************
*
* SJA1000_SetIntMask - enable controller level interrupts on the CAN
* controller
*
* This function enables the specified list of controller level interrupts
* on the CAN controller. Interrupts are not enabled at the CAN board level
* or at the CPU level.
* The interrupt masks available are:
* WNCAN_INT_ERROR : enables interrupts due to errors on the CAN bus
* This may be implemented as a single or multiple
* interrupt sources on the CAN controller.
* WNCAN_INT_BUS_OFF: enables interrupt indicating bus off condition
* WNCAN_INT_WAKE_UP: enables interrupt on wake up
* All interrupt masks that need to be enabled must be specified in the list
* passed to the function, in order to be set, every time the function
* is called.
*
* RETURNS: OK or ERROR
*
* ERRNO: S_can_invalid_parameter
*
*/
static STATUS SJA1000_SetIntMask(struct WNCAN_Device *pDev, WNCAN_IntType intMask)
{
int oldLevel;
UCHAR value=0;
STATUS retCode = OK;
/*
return error if masks other than error, busoff and wakeup
are passed to the function
*/
if((intMask > (WNCAN_INT_ERROR | WNCAN_INT_BUS_OFF | WNCAN_INT_WAKE_UP)) &&
(intMask != WNCAN_INT_ALL))
{
errnoSet(S_can_invalid_parameter);
retCode = ERROR;
}
else
{
value = pDev->pBrd->canInByte(pDev, SJA1000_IER);
/*Enable all error interreupts. Bus error, data overrun*/
if(intMask & WNCAN_INT_ERROR)
value |= IER_BEIE;
else
value &= ~IER_BEIE;
if(intMask & WNCAN_INT_WAKE_UP)
value |= IER_WUIE;
else
value &= ~IER_WUIE;
/*
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 offf
*/
if(intMask & WNCAN_INT_BUS_OFF)
value |= IER_EIE;
else
value &= ~IER_EIE;
oldLevel = intLock();
pDev->pBrd->canOutByte(pDev, SJA1000_IER, value);
intUnlock(oldLevel);
}
return retCode;
}
/***************************************************************************
* SJA1000_EnableInt - enable interrupts from the CAN device to the CPU.
*
* This function enables interrupts from the CAN controller to reach the
* CPU. Typically, enables a global interrupt mask bit at the CPU level.
*
* RETURNS: N/A
*
* ERRNO: N/A
*
*/
static void SJA1000_EnableInt(struct WNCAN_Device *pDev)
{
int oldLevel;
UCHAR value=0;
value = pDev->pBrd->canInByte(pDev, SJA1000_IER);
/*Enable RxIE*/
value |= 0x01;
oldLevel = intLock();
pDev->pBrd->canOutByte(pDev, SJA1000_IER, value);
intUnlock(oldLevel);
return;
}
/************************************************************************
*
* SJA1000_DisableInt - disable interrupts from the CAN device to the CPU
*
* This function disables interrupts from the CAN controller from reaching the
* CPU. Typically, disables a global interrupt mask bit at the CPU level.
*
* RETURNS: N/A
*
* ERRNO: N/A
*
*/
static void SJA1000_DisableInt(struct WNCAN_Device *pDev)
{
int oldLevel;
oldLevel = intLock();
pDev->pBrd->canOutByte(pDev, SJA1000_IER, 0);
intUnlock(oldLevel);
return;
}
/************************************************************************
*
* SJA1000_GetBusError - get the bus error
*
* This function returns an ORed bit mask of all the bus errors that have
* occured during the last bus activity.
* Bus errors returned by this function can have the following values:
* WNCAN_ERR_NONE: No errors detected
* WNCAN_ERR_BIT: Bit error.
* WNCAN_ERR_ACK: Acknowledgement error.
* WNCAN_ERR_CRC: CRC error
* WNCAN_ERR_FORM: Form error
* WNCAN_ERR_STUFF: Stuff error
* WNCAN_ERR_UNKNOWN: this condition should not occur
* The five errors are not mutually exclusive.
* The occurence of an error will be indicated by an interrupt. Typically,
* this function will be called from the error interrupt handling case in the
* user's ISR callback function, to find out the kind of error that occured
* on the bus.
*
* RETURNS: the bus error
*
* ERRNO: N/A
*
*/
static WNCAN_BusError SJA1000_GetBusError(struct WNCAN_Device *pDev)
{
UCHAR value;
WNCAN_BusError error=0;
/* read the error code capture register */
value = pDev->pBrd->canInByte(pDev, SJA1000_ECC);
switch(value >> 6)
{
case 0:
error |= WNCAN_ERR_BIT;
break;
case 1:
error |= WNCAN_ERR_FORM;
break;
case 2:
error |= WNCAN_ERR_STUFF;
break;
case 3:
switch(value & 0x1F)
{
case 8:
error |= WNCAN_ERR_CRC;
break;
case 24:
error |= WNCAN_ERR_CRC;
break;
case 25:
error |= WNCAN_ERR_ACK;
break;
case 27:
error |= WNCAN_ERR_ACK;
break;
default:
error |= WNCAN_ERR_NONE;
break;
}
break;
}
return error;
}
/************************************************************************
*
* SJA1000_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 SJA1000_GetIntStatus
(
struct WNCAN_Device *pDev,
UCHAR *channelNum
)
{
UCHAR regInt;
WNCAN_IntType intStatus=WNCAN_INT_NONE;
UCHAR regStatus;
/* read the interrupt register */
regInt = pDev->pBrd->canInByte(pDev, SJA1000_IR);
/*logMsg("SJA1000_IR = 0x%x\n",regInt);*/
if(regInt & IR_RI) {
/*receive interrupt*/
intStatus = WNCAN_INT_RX;
*channelNum = 0;
}
if( regInt & IR_TI) {
/*transmit interrupt*/
intStatus = WNCAN_INT_TX;
*channelNum = 1;
}
if(regInt & IR_WUI)
{
intStatus = WNCAN_INT_WAKE_UP;
}
/*flag WNCAN_INT_ERROR, if data overrun error int, or
bus error int is detected */
if(regInt & IR_BEI) {
/*error interrupt*/
intStatus = WNCAN_INT_ERROR;
}
if(regInt & IR_EI) {
/*bus off interrupt*/
/* read the status register */
regStatus = pDev->pBrd->canInByte(pDev, SJA1000_SR);
if(regStatus & SJA1000_SR_BS)
intStatus = WNCAN_INT_BUS_OFF;
}
return intStatus;
}
/************************************************************************
*
* sja1000ISR - interrupt service routine
*
* RETURNS: N/A
*
* ERRNO: N/A
*
*/
void sja1000ISR(ULONG context)
{
WNCAN_DEVICE *pDev;
WNCAN_IntType intStatus=WNCAN_INT_NONE;
UCHAR chnNum;
pDev = (WNCAN_DEVICE *)context;
/* notify board that we're entering isr */
if(pDev->pBrd->onEnterISR)
pDev->pBrd->onEnterISR(pDev);
/* Get the interrupt status */
intStatus = SJA1000_GetIntStatus((void*)context, &chnNum);
if (intStatus != WNCAN_INT_NONE)
{
pDev->pISRCallback(pDev, intStatus, chnNum);
if (intStatus == WNCAN_INT_RX)
{
/*logMsg("WNCAN_INT_RX = 0x%x\n",WNCAN_INT_RX,0,0,0,0,0);*/
/* release the receive buffer */
/* this will temporarily cleat RI bit */
pDev->pBrd->canOutByte(pDev, SJA1000_CMR, CMR_RRB);
}
else if (intStatus == WNCAN_INT_ERROR)
{
/*logMsg("WNCAN_INT_ERROR = 0x%x\n",WNCAN_INT_ERROR,0,0,0,0,0);*/
/* clear bei interrupt flag */
pDev->pBrd->canInByte(pDev, SJA1000_ECC);
}
else if (intStatus == WNCAN_INT_TX)
{
/*logMsg("WNCAN_INT_TX = 0x%x\n",WNCAN_INT_TX,0,0,0,0,0);*/
/* notify channel available to TX again */
pDev->pISRCallback(pDev, WNCAN_INT_TXCLR, chnNum);
}
}
/* notify board that we're leaving isr */
if(pDev->pBrd->onLeaveISR)
pDev->pBrd->onLeaveISR(pDev);
return;
}
/************************************************************************
*
* SJA1000_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: LONG: the CAN Id; on error return -1
*
* ERRNO: S_can_illegal_channel_no,
* S_can_illegal_config
*
*/
static long SJA1000_ReadID(struct WNCAN_Device *pDev, UCHAR channelNum,
BOOL* ext)
{
UCHAR value;
struct TxMsg *pTxMsg;
ULONG msgID=0xffffffff;
if (channelNum >= SJA1000_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
{
/* Set up frame and ID registers based on channel mode */
if(pDev->pCtrl->chnMode[channelNum] == WNCAN_CHN_RECEIVE)
{
/* get the frame format */
value = pDev->pBrd->canInByte(pDev, SJA1000_SFF);
/* test if message ID is extended or standard */
if (value & 0x80)
{
*ext = 1;
value = pDev->pBrd->canInByte(pDev,SJA1000_RXID);
msgID = (value << (24-3));
value = pDev->pBrd->canInByte(pDev,SJA1000_RXID+1);
msgID |= (value << (16-3));
value = pDev->pBrd->canInByte(pDev,SJA1000_RXID+2);
msgID |= (value << (8-3));
value = pDev->pBrd->canInByte(pDev,SJA1000_RXID+3);
msgID |= (value >> 3);
}
else
{
*ext = 0;
value = pDev->pBrd->canInByte(pDev,SJA1000_RXID);
msgID = (value << (8-5));
value = pDev->pBrd->canInByte(pDev,SJA1000_RXID+1);
msgID |= (value >> 5);
}
}
else
{
pTxMsg = (struct TxMsg *)pDev->pCtrl->csData;
*ext = pTxMsg->ext;
msgID = pTxMsg->id;
}
}
return ((long) msgID);
}
/************************************************************************
*
* SJA1000_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
*
* If this function is called while the controller is online, receive errors
* may occur while the receive buffer id is being changed.
*
*
* RETURNS: OK, or ERROR
*
* ERRNO: S_can_illegal_channel_no,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -