📄 mscan.c
字号:
idx = CANDll[ idx & 0x07 ] & 0x07;
periphBitClear(idx, &ArchIO.CAN.TxControlReg ); /* clear corresponded flag */
periphMemWrite( CANWATCHFLAG, &ArchIO.CAN.RxFlagReg ); /* clear error if possible */
periphMemWrite( CANEvlFlag( periphMemRead(&ArchIO.CAN.RxFlagReg) ),
&ArchIO.CAN.RxIntEnableReg );
}
/*******************************************************************************
*
* NAME: CANTransmit
*
* DESCRIPTION: CAN send buffer
*
********************************************************************************
* PARAMETERS:
*
* SIDE EFFECTS: None Known
*
* DESIGNER NOTES:
*
* DEPENDENCIES: None
*******************************************************************************/
void CANTransmit( UWord16 idx, can_sWriteBuffer* pBuf, can_sData* pData )
{
arch_sMSCANBuffer* pHBuf = &ArchIO.CAN.TxBuffer[ idx >> 1 ]; /* 1, 2, 4 -> 0, 1, 2 */
pBuf->flags &= ~( CAN_IDX_BUF0 | CAN_IDX_BUF1 | CAN_IDX_BUF2 | CAN_BUF_ERROR | CAN_BUF_PENDING );
pBuf->flags |= idx;
SetCANID( &pHBuf->IdReg0, pBuf->canID );
periphMemWrite( pData->length , &pHBuf->DataLengthReg );
periphMemWrite( pData->data[0], &pHBuf->DataSegReg[0] );
periphMemWrite( pData->data[1], &pHBuf->DataSegReg[1] );
periphMemWrite( pData->data[2], &pHBuf->DataSegReg[2] );
periphMemWrite( pData->data[3], &pHBuf->DataSegReg[3] );
periphMemWrite( pData->data[4], &pHBuf->DataSegReg[4] );
periphMemWrite( pData->data[5], &pHBuf->DataSegReg[5] );
periphMemWrite( pData->data[6], &pHBuf->DataSegReg[6] );
periphMemWrite( pData->data[7], &pHBuf->DataSegReg[7] );
periphMemWrite( pBuf->priority, &pHBuf->U.TxBufferPriorityReg );
/* hardware send */
periphMemWrite(idx, &ArchIO.CAN.TxFlagReg); /* send */
}
/*******************************************************************************
*
* NAME: CANErrorISR
*
* DESCRIPTION: error ISR handler
*
********************************************************************************
* PARAMETERS:
*
* SIDE EFFECTS: None Known
*
* DESIGNER NOTES:
*
* DEPENDENCIES: None
*******************************************************************************/
void CANErrorISR(void)
{
if( periphBitTest(CANBOFFIF, &ArchIO.CAN.RxFlagReg) ) /* bus-off ? */
{
CANInit();
}
/* try to clear all errors */
periphMemWrite( CANWATCHFLAG, &ArchIO.CAN.RxFlagReg );
periphMemWrite( CANEvlFlag( periphMemRead(&ArchIO.CAN.RxFlagReg) ),
&ArchIO.CAN.RxIntEnableReg );
}
/*******************************************************************************
*
* NAME: CANWakeUpISR
*
* DESCRIPTION: wakeup ISR handler
*
********************************************************************************
* PARAMETERS:
*
* SIDE EFFECTS: None Known
*
* DESIGNER NOTES:
*
* DEPENDENCIES: None
*******************************************************************************/
void CANWakeUpISR(void) /* CAN Wake up */
{
periphMemWrite( CANWUPIF, &ArchIO.CAN.RxFlagReg ); /* reset by 1 */
}
/*******************************************************************************
*
* NAME: CANFilterWeight
*
* DESCRIPTION: weight function to define optimal appropriate filter for
* incoming CAN ID
********************************************************************************
* PARAMETERS: CAN ID, current code and mask
*
* SIDE EFFECTS: None Known
*
* DESIGNER NOTES:
*
* DEPENDENCIES: None
*******************************************************************************/
int CANFilterWeight( CANADDRESSTYPE canID, CANADDRESSTYPE code, CANADDRESSTYPE mask )
{
CANADDRESSTYPE tmp;
CANADDRESSTYPE d;
int i = 0;
if( code == 0 && mask == 0 )
return 0; /* not used yet */
tmp = ( code ^ canID ) & ~mask; /* distance for the input filter */
while(1)
{
d = ~( ~tmp + 1);
if( (tmp & d) != 0 )
{
tmp &= d;
i++;
}
else return i;
}
}
/*******************************************************************************
*
* NAME: CheckCANID
*
* DESCRIPTION: check CAN ID to protect from reopen
*
********************************************************************************
* PARAMETERS: CAN ID, mode for loopback
*
* SIDE EFFECTS: None Known
*
* DESIGNER NOTES:
*
* DEPENDENCIES: None
*******************************************************************************/
int CheckCANID( CANADDRESSTYPE canID, UWord16 mode )
{
register void* pBuf;
if( !( mode & (CANLOOPB) >> 1 ) )
for( pBuf = sIState.pRxBuffer;
pBuf < pLastRead;
((char*)pBuf) += sIState.RxSize )
{
if( ((can_sReadBuffer*)pBuf)->canID == canID) /* checking receive buffers */
{
CANErrno = CAN_ERR_REOPEN;
return 0;
}
}
if( !( mode & (CANLOOPB) ) )
for( pBuf = sIState.pTxBuffer;
pBuf < pLastWrite;
((char*)pBuf) += sizeof(can_sWriteBuffer) )
{
if( ((can_sWriteBuffer*)pBuf)->canID == canID) /* checking send buffers */
{
CANErrno = CAN_ERR_REOPEN;
return 0; /* error: re-open is not possible */
}
}
return 1;
}
/*******************************************************************************
*
* NAME: Open
*
* DESCRIPTION: driver Open procedure: open CAN device, receive and send CAN ID
*
********************************************************************************
* PARAMETERS: device name, open flags, pointer to initialization structure
* of type can_sInitialState
*
* SIDE EFFECTS: None Known
*
* DESIGNER NOTES: following I/O flags accepted:
* O_RDONLY - Message buffer is opened for READ,
* O_WRONLY - Message buffer is opened for WRITE,
* transmission mode is synchronous,
* O_WRONLY | O_NON_BLOCK - Message buffer is opened for WRITE,
* transmission mode is asynchronous
* O_CAN_PRIORITY_SCHEDULE
*
* DEPENDENCIES: None
*******************************************************************************/
handle_t canOpen(const char * pName, int oFlags, ...)
{
int i;
va_list Args;
CANADDRESSTYPE canID;
Args = (char *)&oFlags;
canID = va_arg(Args, CANADDRESSTYPE);
va_end(Args);
if( pName != BSP_DEVICE_NAME_CAN_0 )
{
return (handle_t ) -1;
}
/*** open for read ( reception ) ***/
if( (UWord16)oFlags & O_RDONLY )
{
can_sReadBuffer* pRead;
long xi;
long xweight = 0xFF;
long weight;
if( !CheckCANID( canID, sIState.regCMCR1 & CANLOOPB ) )
{
CANErrno = CAN_ERR_REOPEN;
return (handle_t )-1; /* error: no more driver buffers */
}
if( pLastRead >= sIState.pLastRx )
{
CANErrno = CAN_ERR_NO_BUFFERS;
return (handle_t )-1; /* error: no more driver buffers */
}
pRead = pLastRead;
pLastRead = (can_sReadBuffer*)((char*) pLastRead + sIState.RxSize);
pRead->flags = CAN_BUF_READ_HANDLE;
pRead->drvInterface = (io_sInterface *)&canInterfaceVT; /* interfaceCAN_Rx; */
pRead->canID = canID;
if( !((UWord16)oFlags & O_NONBLOCK) )
pRead->flags |= CAN_BUF_SYNCHRONOUS;
if( actFilterLimit < CANFILTERLIMIT )/* CAN20B can be defines from canID*/
{
sCANFilterMirror[actFilterLimit].code = canID;
sCANFilterMirror[actFilterLimit].mask = 0;
actFilterLimit++;
}
else
{ /* filter limit is exhausted, looking for appropriate filter */
for( i = 0; i < CANFILTERLIMIT; i++ )
{
weight = CANFilterWeight( canID,
sCANFilterMirror[i].code,
sCANFilterMirror[i].mask
);
if( weight < xweight ) /* definition of optimal filter */
{
xweight = weight;
xi = i;
}
}
sCANFilterMirror[xi].mask |=
canID ^ sCANFilterMirror[xi].code;
}
periphBitSet( CANSFTRES, &ArchIO.CAN.Control0Reg ); /* set soft reset bit */
/* No need to disable interrupts since all MSCAN interrupts
are disabled now
*/
periphMemWrite( sIState.regCBTR0, &ArchIO.CAN.BusTiming0Reg );
periphMemWrite( sIState.regCBTR1, &ArchIO.CAN.BusTiming1Reg );
periphMemWrite( CANFILTERMODE, &ArchIO.CAN.IdControlReg );
CANSetFilter();
periphBitClear( CANSFTRES, &ArchIO.CAN.Control0Reg ); /* clear SFTRES bit, defined in common mask */
/* *** */
periphMemWrite( 0, &ArchIO.CAN.TxControlReg ); /* no Tx interrupt, controling by DLL handler */
periphMemWrite( CANWATCHFLAG, &ArchIO.CAN.RxFlagReg );
periphMemWrite( CANEvlFlag( periphMemRead(&ArchIO.CAN.RxFlagReg ) ),
&ArchIO.CAN.RxIntEnableReg );
return (handle_t )pRead;
}
/*** open for write ( transmission ) ***/
else if( (UWord16)oFlags & O_WRONLY )
{
UWord16 test = sizeof(can_sWriteBuffer);
can_sWriteBuffer* pWrite;
if( !CheckCANID( canID, (sIState.regCMCR1 & CANLOOPB) >> 1 ) )
{
CANErrno = CAN_ERR_REOPEN;
return (handle_t )-1; /* error: ID has been opened yet */
}
if( pLastWrite >= sIState.pLastTx )
{
CANErrno = CAN_ERR_NO_BUFFERS;
return (handle_t )-1; /* error: no more driver buffers */
}
pWrite = pLastWrite;
pLastWrite++; /* next buffer */
pWrite->drvInterface = (io_sInterface *)&canInterfaceVT; /* interfaceCAN_Tx; */
pWrite->flags = 0; /* CAN_BUF_WRITE_HANDLE */
pWrite->canID = canID;
if( !((UWord16)oFlags & O_NONBLOCK) )
pWrite->flags |= CAN_BUF_SYNCHRONOUS;
/* message schedule block */
if ((UWord16)oFlags & O_CAN_PRIORITY_SCHEDULE)
{
pWrite->flags |= CAN_BUF_PRIORITY_SCHEDULE;
/* work for restricted ranges */
pWrite->priority =
(UWord16)((pWrite->canID) >> (CANIDSIZE - 7));
}
return (handle_t )pWrite;
}
CANErrno = CAN_ERR_PARAMETER;
return (handle_t )-1; /* flag error */
}
/*******************************************************************************
*
* NAME: Read
*
* DESCRIPTION: Driver read procedure
*
********************************************************************************
* PARAMETERS: file descriptor, buffer and size
*
* SIDE EFFECTS: None Known
*
* DESIGNER NOTES: handler is pointer to the bufffer,
* truncation is possible when porting
* In case when CAN_8BIT data type is specified, data from one
* receiving register is considered to be of a single 8-bit
* char value.
* In case of CAN_16BIT data type the data from two receiving
* registers is composed to a single 16-bit value.
*
*
* DEPENDENCIES: None
*******************************************************************************/
ssize_t canRead(handle_t FileDesc,void *pBuffer, size_t size)
{
//can_sReadBuffer * pHandle = (can_sReadBuffer *)FileDesc;
can_sReadBuffer* pBuf = (can_sReadBuffer*) FileDesc;
register char* pSrc;
ssize_t len;
/* disable source isr */
periphBitClear( CANRXFIE, &ArchIO.CAN.RxIntEnableReg );
pSrc = (char *)(&pBuf->data[0]);
pBuf->flags &= ~(CAN_BUF_FULL | CAN_BUF_OVERFLOW);
len = ((can_sData*)pSrc)->length;
((can_sData*)pSrc)->length = 0; /* mark data as free */
pSrc = (char *)(((can_sData*)pSrc)->data);
if( len > size )
len = size;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -