📄 flexcan.c
字号:
asm( move.w # CANID_EMPTY, Y0 ); /* for case of interim code */
asm( bra end_status );
tx_case:
asm( move.w X:( BSP_PERIPH_BASE + archoff_FlexCAN_IntMask1Reg ), X0 );
asm( and.w X0, B ); /* check bit in flag register */
asm( beq end_status );
asm( move.w # CANID_FULL , Y0 );
end_status:
;
}
/*******************************************************************************
*
* NAME: ioctlCAN_RESET
*
* DESCRIPTION: Driver i/o control procedure - Reset CAN Driver
*
********************************************************************************
* PARAMETERS: file descriptor, parameters list
*
* SIDE EFFECTS: None Known
*
* DESIGNER NOTES:
*
* DEPENDENCIES: None
*******************************************************************************/
unsigned int ioctlCAN_RESET(handle_t FileDesc, unsigned long params )
{
register int i;
FC_Init();
for( i = nBottomRead; i < 16; i++ )
{
/* MB is active for receive data */
periphMemWrite( FC_MB_ACTIVE, &ArchIO.CAN.Buffer[i].CtlStatusReg );
}
return 0;
}
/*******************************************************************************
*
* NAME: ioctlCAN_SET_SLEEP
*
* DESCRIPTION: Driver i/o control - Sets CAN into SLEEP(power save) mode
*
********************************************************************************
* PARAMETERS: file descriptor, command and parameters list
*
* SIDE EFFECTS: None Known
*
* DESIGNER NOTES:
*
* DEPENDENCIES: None
*******************************************************************************/
unsigned int ioctlCAN_SET_SLEEP(handle_t FileDesc, unsigned long params )
{
periphBitSet(CAN_STOP, &ArchIO.CAN.ConfigReg ); /* goto low power sleep mode */
return (unsigned int)periphBitTest( CAN_STOP_ACK, &ArchIO.CAN.ConfigReg ) ;
}
/*******************************************************************************
*
* NAME: ioctlCAN_SET_WAKEUP
*
* DESCRIPTION: Driver i/o control procedure - Wakeups CAN
*
********************************************************************************
* PARAMETERS: file descriptor, command and parameters list
*
* SIDE EFFECTS: None Known
*
* DESIGNER NOTES:
*
* DEPENDENCIES: None
*******************************************************************************/
unsigned int ioctlCAN_SET_WAKEUP(handle_t FileDesc, unsigned long params )
{
periphBitSet(CAN_SELF_WAKE, &ArchIO.CAN.ConfigReg ); /* goto wake up mode */
return 0;
}
/*******************************************************************************
*
* NAME: ioctlCAN_GET_STATUS
*
* DESCRIPTION: Driver i/o control procedure - Gets status of CAN control registers
*
********************************************************************************
* PARAMETERS: file descriptor, command and parameters list
*
* SIDE EFFECTS: None Known
*
* DESIGNER NOTES: returned status value is composed of CANCTL0 + CANRFLG
*
* DEPENDENCIES: None
*******************************************************************************/
unsigned int ioctlCAN_GET_STATUS(handle_t FileDesc, unsigned long params )
{
unsigned int status;
status = periphMemRead( &ArchIO.CAN.StatusReg );
if( !(status & 0xFC00) )
status |= 0x0008;
return status;
}
/*******************************************************************************
*
* NAME: Close
*
* DESCRIPTION: Driver close procedure
*
********************************************************************************
* PARAMETERS: file descriptor
*
* SIDE EFFECTS: filters is staying open
*
* DESIGNER NOTES: close corresponding message buffer
*
* DEPENDENCIES: None
*******************************************************************************/
int flexcanClose(handle_t handle)
{
unsigned int i = ((can_sBuffer*)handle)->flags & 0x000F;
if ( ((can_sBuffer*)handle)->flags & CAN_BUF_READ_HANDLE )
{
if( i == nBottomRead )
{
nBottomRead++;
((can_sBuffer*)handle)->flags = 0;
}
else
{
return -1;
}
}
else
{
if( i == nTopWrite - 1 ) /* correct */
{
nTopWrite--;
((can_sBuffer*)handle)->flags = 0;
}
else
{
return -1;
}
}
periphMemWrite( 0, &ArchIO.CAN.Buffer[i].CtlStatusReg );
periphBitClear( (1 << i), &ArchIO.CAN.IntMask1Reg );
periphBitSet( (1 << i), &ArchIO.CAN.IntFlags1Reg );
return 0;
}
/*******************************************************************************
*
* NAME: ioctlCANID_SET_MSAK
*
* DESCRIPTION: update mask according to the buffer
*
********************************************************************************
* PARAMETERS: file descriptor, mask
*
* SIDE EFFECTS: None Known
*
* DESIGNER NOTES: only for 14 and 15 mask
*
* DEPENDENCIES: None
*******************************************************************************/
unsigned int ioctlCANID_SET_MASK(handle_t handle, unsigned long params )
{
unsigned int i;
unsigned long maskflag;
i = ((can_sBuffer*)handle)->flags & 0x000F;
maskflag = 0;
if( ((can_sBuffer*)handle)->flags & CAN_BUF_2B )
{
maskflag = CAN_LONG_IDE_MASK ;
}
if( i == 15 )
{
SetCANID( (unsigned short*)(BSP_PERIPH_BASE + archoff_FlexCAN_Rx15MaskHiReg ), params, maskflag );
}
else if( i == 14 )
{
SetCANID( (unsigned short*)(BSP_PERIPH_BASE + archoff_FlexCAN_Rx14MaskHiReg ), params, maskflag );
}
else
{
SetCANID( (unsigned short*)(BSP_PERIPH_BASE + archoff_FlexCAN_RxGlobalMaskHiReg ), params, maskflag );
}
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
*******************************************************************************/
#pragma interrupt called on
void CANReceiveISR(void)
{
register can_sData* pCrd;
pCrd = (*CANRcvPrepare)(
GetCANID(
((unsigned long)periphMemRead( &ArchIO.CAN.Buffer[15].IdRegHi)) << 16
| periphMemRead( &ArchIO.CAN.Buffer[15].IdRegLo)
)
); /* CANStdRcvPrepare */
if( pCrd )
{
pCrd->length = flexcanRead( (handle_t)&IOBuffer[15],
&pCrd->data[0], 8 );
}
else
{ /* just release */
flexcanRead( (handle_t)&IOBuffer[15], &pCrd->data[0], 0 );
}
}
#pragma interrupt called off
/*******************************************************************************
*
* NAME: FC_InitCallBack
*
* DESCRIPTION: Initialize CAN driver device for callback
*
********************************************************************************
* PARAMETERS:
*
* SIDE EFFECTS: None Known
*
* DESIGNER NOTES: only 15th buffer is used
*
* DEPENDENCIES: None
*******************************************************************************/
void FC_InitCallBack( CANADDRESSTYPE mask, CANADDRESSTYPE canID )
{
flexcanOpen( 0, O_RDONLY, canID ); /* use last buffer with own filter */
ioctlCANID_SET_MASK((handle_t)&IOBuffer[15], mask );
periphMemWrite( 0x8000, &ArchIO.CAN.IntMask1Reg ); /* 15th buffer */
IOBuffer[15].callback = CANReceiveISR;
}
/*******************************************************************************
*
* 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 CANBufferISR(void)
{
asm( alignsp ); /* saves needed registers only */
asm( move.l Y , x:(SP)+ );
asm( move.l X0, x:(SP)+ );
asm( move.l R2, x:(SP)+ );
asm( move.l N, x:(SP) );
asm( move.w X:( BSP_PERIPH_BASE + archoff_FlexCAN_IntMask1Reg ), Y0 );
asm( move.w X:( BSP_PERIPH_BASE + archoff_FlexCAN_IntFlags1Reg ), Y1 );
asm( and.w Y1, Y0 ); /* actual isr vector */
asm( clr.w Y1 );
asm( clb Y, X0 ); /* left buffer index (Y0) */
asm( move.w #0x1E, Y0 );
asm( sub X0, Y0 );
asm( blt end_bufisr );
asm( move.w #0x0001, X0 ); /* 0th mask (X0) */
asm( asll.w Y0, X0 ); /* actual buffer mask (X0) */
asm( move.w X:( BSP_PERIPH_BASE + archoff_FlexCAN_IntMask1Reg ), Y1 );
asm( not.w X0 ); /* to clear actual mask */
asm( and.w X0, Y1 ); /* only current ISR mask clear */
asm( move.w Y1, X:( BSP_PERIPH_BASE + archoff_FlexCAN_IntMask1Reg ) ); /* release mask */
asm( move.w #sFlexCAN_word_size, Y1 ); /* get status */
asm( impy.w Y1, Y0, X0 ); /* Y0*Y1 get contex offset */
asm( adda #IOBuffer, X0, R2 ); /* get context buffer address */
asm( tst.l X:(R2 + sFlexCAN_offset_callback) );
asm( beq end_bufisr );
asm( move.l X:(R2 + sFlexCAN_offset_callback), N ); /* get callback address */
asm( jsr (N) );
end_bufisr:
asm( move.l x:(SP)-, N );
asm( move.l x:(SP)-,R2 );
asm( move.l x:(SP)-,X0 );
asm( move.l x:(SP)-,Y );
asm( move.l x:(SP)-,SP );
asm( rti );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -