📄 mscan.c
字号:
#if defined(DSP56838EVM)
/*******************************************************************************
*
* Motorola Inc.
* (c) Copyright 2002 Motorola, Inc.
* ALL RIGHTS RESERVED.
*
********************************************************************************
*
* FILE NAME: mscan.c
*
*******************************************************************************/
#include "port.h"
#include "arch.h"
#include "periph.h"
#include "io.h"
#include "stdio.h"
#include "stdlib.h"
#include "stdarg.h"
#include "string.h"
#include "bsp.h"
#include "supconfig.h"
#include "config.h"
#include "mscan.h"
/* MSCAN property resolved table: 1 - free, 0 - busy */
const UWord16 CANDll [/* 8 */] = {
/* 000 */ 0x00 | CANM_TXISR | CANM_ALLBUSY,
/* 001 */ 0x01 | CANM_TXISR,
/* 010 */ 0x02 | CANM_TXISR | CANM_FREE1,
/* 011 */ 0x01,
/* 100 */ 0x04 | CANM_TXISR | CANM_FREE2,
/* 101 */ 0x01,
/* 110 */ 0x02 | CANM_FREE1,
/* 111 */ 0x01 | CANM_ALLFREE /* all free - reset priority */
};
extern const io_sMSCANInterface canInterfaceVT;
/* extern const io_sDriver interfaceCAN; */
static UWord16 CANInit();
static UWord16 CANEvlFlag( UWord16 flg );
static UWord16 CANSetFilter();
static can_sReadBuffer* CANGetFreeReadBuffer( );
static can_sWriteBuffer* CANGetFreeWriteBuffer( );
static int CANFilterWeight( CANADDRESSTYPE canID, CANADDRESSTYPE code, CANADDRESSTYPE mask );
static void CANTransmit( UWord16 idx, can_sWriteBuffer* pBuf, can_sData* pData );
static can_sWriteBuffer* TakeAway( can_sWriteBuffer* pBuf );
static int CheckCANID( CANADDRESSTYPE canID, UWord16 mode );
static CANADDRESSTYPE GetCANID( volatile UWord16* pAddr );
static void SetCANID( volatile UWord16* pAddr, CANADDRESSTYPE canID );
extern const can_sInitialState canInitialState;
/* the number of used buffers is defined statically */
/* to control of open devices */
static can_sWriteBuffer* pLastWrite;
static can_sReadBuffer* pLastRead;
/* CAN filters in CAN ID format */
static struct CANFilterMirror sCANFilterMirror[CANFILTERLIMIT];
extern can_pRawCallBack CANRcvPrepare; /* RAW CallBack pointer */
/* CAN driver context variables */
int CANErrno; /* last error code */
static UWord16 actFilterLimit ; /* free/busy filter index */
static can_sInitialState sIState; /* MSCAN initial state */
static UWord16 msprio; /* priority support counter */
/*******************************************************************************
*
* NAME: CANStdRcvPrepare
*
* DESCRIPTION: To find driver receive buffer by incoming CANID
*
********************************************************************************
* PARAMETERS: incoming CAN ID
*
* SIDE EFFECTS: None Known
*
* DESIGNER NOTES: Can be implemented by asm
*
* DEPENDENCIES: None
*******************************************************************************/
can_sData* CANStdRcvPrepare( CANADDRESSTYPE canID )
{
can_sReadBuffer* pBuf;
register can_sData* pData = 0;
for( pBuf = sIState.pRxBuffer;
pBuf < pLastRead;
pBuf = (can_sReadBuffer*)((char*)pBuf + sIState.RxSize))
{
if( pBuf->canID == canID )
{
pData = &pBuf->data[0];
if( pData->length != 0 )
pBuf->flags |= CAN_BUF_OVERFLOW;
else
pBuf->flags |= CAN_BUF_FULL;
}
}
return pData;
}
/*******************************************************************************
*
* NAME: CANEvlFlag
*
* DESCRIPTION: Evaluate CAN flags to obtain interrupt flags
*
********************************************************************************
* PARAMETERS: current flag set
*
* SIDE EFFECTS: None Known
*
* DESIGNER NOTES:
*
* DEPENDENCIES: None
*******************************************************************************/
UWord16 CANEvlFlag( UWord16 flg )
{
return( (CANWUPIE | CANRXFIE) | ~( flg | ~CANWATCHFLAG ) );
}
/*******************************************************************************
*
* NAME: GetCANID
*
* DESCRIPTION: Compose 11/29-bit CAN ID from the registers values
*
********************************************************************************
* PARAMETERS: Address of the registers
*
* SIDE EFFECTS: None Known
*
* DESIGNER NOTES:
*
* DEPENDENCIES: None
*******************************************************************************/
CANADDRESSTYPE GetCANID( volatile UWord16* pAddr )
{
#if defined( CAN20B )
/* 29-bit CAN ID is taken from four MSCAN registers in the following way:
xxxxxxxx IdReg0
xxx11xxx IdReg1
xxxxxxxx IdReg2
xxxxxxx0 IdReg3
xxxxxxxx xxxxxx xxxxxxxx xxxxxxx 29-bit CAN ID */
return ( (UWord32)periphMemRead(&pAddr[0]) << 21)
| (((UWord32)periphMemRead(&pAddr[1]) & 0xE0) << 13)
| (((UWord32)periphMemRead(&pAddr[1]) & 0x7) << 15)
| ( (UWord32)periphMemRead(&pAddr[2]) << 7)
| ( (UWord32)periphMemRead(&pAddr[3]) >> 1)
;
#else /* defined (CAN20B) */
return ( periphMemRead(&pAddr[0]) << 3 )
| ( periphMemRead(&pAddr[1]) >> 5 );
#endif /* defined (CAN20B) */
}
/*******************************************************************************
*
* NAME: SetCANID
*
* DESCRIPTION: Decompose 11/29-bit CAN ID into the registers
*
********************************************************************************
* PARAMETERS: Address of the registers, CAN ID
*
* SIDE EFFECTS: None Known
*
* DESIGNER NOTES:
*
* DEPENDENCIES: None
*******************************************************************************/
void SetCANID( volatile UWord16* pAddr, CANADDRESSTYPE canID )
{
#if defined( CAN20B )
/* if (canID>0x07FF) */
/* 29-bit CAN ID is placed into four MSCAN registers in the following way:
xxxxxxxx IdReg0
xxx11xxx IdReg1
xxxxxxxx IdReg2
xxxxxxx0 IdReg3
xxxxxxxx xxxxxx xxxxxxxx xxxxxxx 29-bit CAN ID */
periphMemWrite( (UWord16)(canID >> 21), &pAddr[0] );
/* check carefully ! */
periphMemWrite(
(UWord16)(( ((canID >> 15) & 0x7) | 0x18 | ((canID >> 13) & 0xE0))), &pAddr[1] );
periphMemWrite( (UWord16)(canID >> 7), &pAddr[2] );
periphMemWrite( (UWord16)(canID << 1), &pAddr[3] );
#else /* defined (CAN20B) */
periphMemWrite( canID >> 3, &pAddr[0]);
periphMemWrite( canID << 5, &pAddr[1]);
#endif /* defined (CAN20B) */
}
/*******************************************************************************
*
* NAME: CANSetFilter
*
* DESCRIPTION: Set CANCIDARs and CANCIDMRs
*
********************************************************************************
* PARAMETERS:
*
* SIDE EFFECTS: None Known
*
* DESIGNER NOTES:
*
* DEPENDENCIES: None
*******************************************************************************/
UWord16 CANSetFilter()
{
#if defined(CAN20B)
SetCANID( &ArchIO.CAN.IdAcceptReg0, sCANFilterMirror[0].code );
SetCANID( &ArchIO.CAN.IdAcceptReg4, sCANFilterMirror[1].code );
SetCANID( &ArchIO.CAN.IdMaskReg0, sCANFilterMirror[0].mask );
SetCANID( &ArchIO.CAN.IdMaskReg4, sCANFilterMirror[1].mask );
if( actFilterLimit > 0)
periphBitSet(0x1, &ArchIO.CAN.IdMaskReg3 );
if( actFilterLimit > 1)
periphBitSet(0x1, &ArchIO.CAN.IdMaskReg7);
#else /* defined (CAN20B) */
SetCANID( &ArchIO.CAN.IdAcceptReg0, sCANFilterMirror[0].code );
SetCANID( &ArchIO.CAN.IdAcceptReg2, sCANFilterMirror[1].code );
SetCANID( &ArchIO.CAN.IdAcceptReg4, sCANFilterMirror[2].code );
SetCANID( &ArchIO.CAN.IdAcceptReg6, sCANFilterMirror[3].code );
SetCANID( &ArchIO.CAN.IdMaskReg0, sCANFilterMirror[0].mask );
SetCANID( &ArchIO.CAN.IdMaskReg2, sCANFilterMirror[1].mask );
SetCANID( &ArchIO.CAN.IdMaskReg4, sCANFilterMirror[2].mask );
SetCANID( &ArchIO.CAN.IdMaskReg6, sCANFilterMirror[3].mask );
if( actFilterLimit > 0)
periphBitSet(0x7, &ArchIO.CAN.IdMaskReg1 );
if( actFilterLimit > 1)
periphBitSet(0x7, &ArchIO.CAN.IdMaskReg3 );
if( actFilterLimit > 2)
periphBitSet(0x7, &ArchIO.CAN.IdMaskReg5 );
if( actFilterLimit > 3)
periphBitSet(0x7, &ArchIO.CAN.IdMaskReg7);
#endif /* defined (CAN20B) */
return 0;
}
/*******************************************************************************
*
* NAME: CANInit
*
* DESCRIPTION: Initialize MSCAN device
*
********************************************************************************
* PARAMETERS:
*
* SIDE EFFECTS: None Known
*
* DESIGNER NOTES:
*
* DEPENDENCIES: None
*******************************************************************************/
static UWord16 CANInit()
{
UWord16 i;
can_sWriteBuffer* pWriteBuf;
can_sReadBuffer* pReadBuf;
periphBitSet(CANSFTRES, &ArchIO.CAN.Control0Reg); /* set soft reset bit */
for( pWriteBuf = sIState.pTxBuffer;
pWriteBuf < pLastWrite;
pWriteBuf++ )
{
if( pWriteBuf->flags & ( CAN_IDX_BUF0 | CAN_IDX_BUF1 | CAN_IDX_BUF2 | CAN_BUF_PENDING ) )
{
pWriteBuf->flags |= CAN_BUF_ERROR;
pWriteBuf->flags &= ~( CAN_IDX_BUF0 | CAN_IDX_BUF1 | CAN_IDX_BUF2 | CAN_BUF_PENDING );
}
}
for( pReadBuf = sIState.pRxBuffer;
pReadBuf < pLastRead;
pReadBuf++ )
{
pReadBuf->data[0].length = 0;
pReadBuf->flags &= ~( CAN_BUF_FULL | CAN_BUF_OVERFLOW );
}
msprio = CANLOWESTPRIO;
periphMemWrite( sIState.regCMCR1, &ArchIO.CAN.Control1Reg );
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 */
periphMemWrite( sIState.regCMCR0 & 0x28 , &ArchIO.CAN.Control0Reg );
periphMemWrite( 0, &ArchIO.CAN.TxControlReg );
/* no Tx interrupt, controling by handler */
periphMemWrite( CANWATCHFLAG, &ArchIO.CAN.RxFlagReg );
periphMemWrite( CANEvlFlag( periphMemRead(&ArchIO.CAN.RxFlagReg) ),
&ArchIO.CAN.RxIntEnableReg );
return 0;
}
/*******************************************************************************
*
* NAME: CANReceiveISR
*
* DESCRIPTION: receive ISR handler
*
********************************************************************************
* PARAMETERS:
*
* SIDE EFFECTS: Slowest handler in the driver, impacts to the interrupt lattency
*
* DESIGNER NOTES: copy is not effective on C, recomended to use asm
*
* DEPENDENCIES: None
*******************************************************************************/
void CANReceiveISR(void)
{
register can_sData* pCrd;
while( periphBitTest(CANRXF, &ArchIO.CAN.RxFlagReg) ) /* RX buffer ready */
{
pCrd = (*CANRcvPrepare)( GetCANID(&ArchIO.CAN.RxBuffer.IdReg0) ); /* CANStdRcvPrepare */
if( pCrd )
{
pCrd->length = ( periphMemRead(&ArchIO.CAN.RxBuffer.DataLengthReg) ) & 0x000F;
pCrd->data[0] = periphMemRead(&ArchIO.CAN.RxBuffer.DataSegReg[0]);
pCrd->data[1] = periphMemRead(&ArchIO.CAN.RxBuffer.DataSegReg[1]);
pCrd->data[2] = periphMemRead(&ArchIO.CAN.RxBuffer.DataSegReg[2]);
pCrd->data[3] = periphMemRead(&ArchIO.CAN.RxBuffer.DataSegReg[3]);
pCrd->data[4] = periphMemRead(&ArchIO.CAN.RxBuffer.DataSegReg[4]);
pCrd->data[5] = periphMemRead(&ArchIO.CAN.RxBuffer.DataSegReg[5]);
pCrd->data[6] = periphMemRead(&ArchIO.CAN.RxBuffer.DataSegReg[6]);
pCrd->data[7] = periphMemRead(&ArchIO.CAN.RxBuffer.DataSegReg[7]);
}
periphBitSet( CANRXF, &ArchIO.CAN.RxFlagReg ); /* free RX */
}
return;
}
/*******************************************************************************
*
* NAME: CANSendISR
*
* DESCRIPTION: send ISR handler
*
********************************************************************************
* PARAMETERS:
*
* SIDE EFFECTS: None Known
*
* DESIGNER NOTES:
*
* DEPENDENCIES: None
*******************************************************************************/
void CANSendISR(void)
{
register UWord16 idx;
can_sWriteBuffer* pBuf;
idx = periphMemRead(&ArchIO.CAN.TxControlReg) & periphMemRead(&ArchIO.CAN.TxFlagReg);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -