📄 flexcan.c
字号:
* DESIGNER NOTES:
*
* DEPENDENCIES: None
*******************************************************************************/
handle_t flexcanOpen(const char * pName, int oFlags, CANADDRESSTYPE canID )
{
can_sBuffer* pbuf;
unsigned int cmd;
/*** open for read ( reception ) ***/
if( oFlags & O_RDONLY )
{
nBottomRead--;
pbuf = &IOBuffer[nBottomRead];
pbuf->flags = (unsigned int)nBottomRead | CAN_BUF_READ_HANDLE;
cmd = FC_MB_ACTIVE;
periphBitSet( (1 << nBottomRead), &ArchIO.CAN.IntMask1Reg );
}
/*** open for write ( transmission ) ***/
else if( oFlags & O_WRONLY )
{
pbuf = &IOBuffer[nTopWrite]; /* CAN_BUF_WRITE_HANDLE */
pbuf->flags = (unsigned int)nTopWrite;
cmd = FC_MB_NOTREADY;
nTopWrite++; /* next buffer */
}
if( !(oFlags & O_NONBLOCK) )
{
pbuf->flags |= CAN_BUF_SYNCHRONOUS;
}
pbuf->canID = canID;
if( FlexCANFlags /* oFlags*/ & O_CAN_2B )
{
pbuf->flags |= CAN_BUF_2B;
}
PrepareCANID( pbuf, cmd );
return (handle_t)pbuf;
}
/*******************************************************************************
*
* NAME: Write
*
* DESCRIPTION: Driver write procedure
*
********************************************************************************
* PARAMETERS: file descriptor, buffer and size
*
* SIDE EFFECTS: None Known
*
* DESIGNER NOTES: handler is pointer to the buffer,
* truncation is possible when porting
*
* DEPENDENCIES: None
*******************************************************************************/
ssize_t flexcanWrite( handle_t handle, const void *pBuffer, size_t size )
{
#if __m56800E_lmm__
asm(move.w A0,A);
asm(move.w A1,Y0);
#else
asm(nop);
asm(nop);
#endif
asm( move.w X:(R2 + #sFlexCAN_offset_flags), X0 );
asm( bfclr #0xFFF0, X0 ); /* clear flags */
asm( move.w #1, A );
asm( asll.w X0, A ); /* get mask for buffer */
asm( asll.w #0x3, X0 ); /* *8, convert to buffer index */
asm( adda #( BSP_PERIPH_BASE + archoff_FlexCAN_Buffer_0 ), X0, R4 );
/* R4 - message buffer */
asm( brclr #4, X:( BSP_PERIPH_BASE + archoff_FlexCAN_StatusReg ), continue_1 );
asm( bfset #4, X:( BSP_PERIPH_BASE + archoff_FlexCAN_StatusReg ) );
#if __m56800E_lmm__
asm(move.l #0xFFFFFFFF,A);
#else
asm( move.w #0xFFFF, Y0 );
#endif
asm( move.w # CAN_ERR_LOST, CANErrno );
asm( rts );
continue_1:
/* transmission finished ? */
asm( move.w X:( BSP_PERIPH_BASE + archoff_FlexCAN_IntMask1Reg ), X0 );
asm( and.w A, X0 ); /* compare with mask */
asm( beq continue_2 );
#if __m56800E_lmm__
asm(move.l #0xFFFFFFFF,A);
#else
asm( move.w #0xFFFF, Y0 );
#endif
asm( move.w #CAN_ERR_BUSY, CANErrno );
asm( rts );
continue_2:
asm( move.w # FC_MB_NOTREADY, X:(R4 + devoff_FlexCANBuffer_CtlStatusReg) );
asm(cmp.w #8, Y0);
asm(blt len_lt); /* change by received len only */
asm(move.w #8, Y0);
len_lt:
asm( move.w Y0, X0 );
asm( inc.w X0 );
asm( ror.w X0 ); /* words to copy */
asm( adda # devoff_FlexCANBuffer_DataSegReg_0, R4, R0 );
asm( do X0, enddo );
asm( move.bp X:(R3)+, Y1 ); /* copy from pBuffer */
asm( asll.w #8, Y1 );
asm( moveu.bp X:(R3)+, X0 ); /* copy from pBuffer */
asm( or.w X0, Y1 );
asm( move.w Y1, X:(R0)+ ); /* copy to hardware */
enddo:
asm( move.w X:( BSP_PERIPH_BASE + archoff_FlexCAN_IntFlags1Reg ), X0 );
asm( and.w A, X0 ); /* to clear isr flag */
asm( move.w X0, X:( BSP_PERIPH_BASE + archoff_FlexCAN_IntFlags1Reg ) );
asm( move.w X:( BSP_PERIPH_BASE + archoff_FlexCAN_IntMask1Reg ), X0 );
asm( or.w A, X0 ); /* to update isr mask */
asm( move.w X0, X:( BSP_PERIPH_BASE + archoff_FlexCAN_IntMask1Reg ) );
asm( bfset # FC_MB_SEND, Y0 );
asm( move.w Y0, X:(R4 + devoff_FlexCANBuffer_CtlStatusReg) );
asm( move.w X:( BSP_PERIPH_BASE + archoff_FlexCAN_TimerReg), X0 );
asm( brclr CAN_BUF_SYNCHRONOUS, X:(R2 + #sFlexCAN_offset_flags), endwrite );
wait_tx: /* wait in blocked mode only */
asm( move.w X:( BSP_PERIPH_BASE + archoff_FlexCAN_IntFlags1Reg ), X0 );
asm( and.w A, X0 );
asm( beq wait_tx );
endwrite:
asm( bfclr # 0xFFF0, Y0 ); /* return actual length */
#if __m56800E_lmm__
asm(move.w Y0,A0);
asm(clr.w A1);
#else
asm(nop);
asm(nop);
#endif
}
/*******************************************************************************
*
* NAME: Read
*
* DESCRIPTION: Driver read procedure
*
********************************************************************************
* PARAMETERS: file descriptor, buffer and size
*
* SIDE EFFECTS: None Known
*
* DESIGNER NOTES: handler is pointer to the CAN ID descriptor,
*
* DEPENDENCIES: None
*******************************************************************************/
ssize_t flexcanRead( handle_t handle, void *pBuffer, size_t size)
{
#if __m56800E_lmm__
asm(move.w A0,A);
asm(move.w A1,Y0);
#else
asm(nop);
asm(nop);
#endif
asm( move.w X:(R2 + #sFlexCAN_offset_flags), X0 );
asm( bfclr #0xFFF0, X0 ); /* clear flags */
asm( move.w #1, C );
asm( asll.w X0, C ); /* get mask for buffer */
asm( asll.w #0x3, X0 ); /* *8, convert to buffer index */
/* R3 - message buffer */
asm( adda #( BSP_PERIPH_BASE + archoff_FlexCAN_Buffer_0 ), X0, R4 );
asm( move.w X:(R4 + devoff_FlexCANBuffer_CtlStatusReg), X0 );
asm( move.w X0, Y1 );
asm( bfclr #0xFF0F, Y1 ); /* left only len */
asm( cmp.w # FC_MB_FULL, Y1 );
asm( beq continue_read );
asm( cmp.w # FC_MB_OVERRUN, Y1 );
asm( beq continue_read );
asm( clr.w Y0 );
#if __m56800E_lmm__
asm(clr.w A0);
asm(clr.w A1);
#else
asm(nop);
asm(nop);
#endif
asm( rts );
continue_read: /* mb full or overrun continue read */
asm( move.w X:(R4 + devoff_FlexCANBuffer_IdRegHi), A ); /* A - ID */
asm( move.w X:(R4 + devoff_FlexCANBuffer_IdRegLo), A0 );
asm( jsr GetCANID ); /* A - raw CAN ID -> CAN ID */
asm( cmp.w #(8 + 4), Y0 ); /* compare with ext buffer len, Y0 - 12 */
asm( blt IDcopy); /* change by received len only */
asm( adda #8, R3, R0 );
asm( asra R0 );
asm( move.w A0, X:(R0)+ ); /* copy ID to tail of long buffer */
asm( move.w A1, X:(R0)+ );
IDcopy:
asm( bfclr #0xFFF0, X0 ); /* left only len */
asm( cmp X0, Y0); /* Y0 - X0 */
asm( blt len_lt); /* change by received len only */
asm( move.w X0, Y0);
len_lt:
asm( adda # devoff_FlexCANBuffer_DataSegReg_0, R4, R0 );
asm( move.w Y0, X0 );
asm( asr X0 ); /* words to copy */
asm( do X0, enddo );
asm( move.w X:(R0)+, X0 );
asm( move.w X0, Y1 );
asm( asrr.w #8, X0 );
asm( move.bp X0, X:(R3)+ );
asm( move.bp Y1, X:(R3)+ );
enddo:
asm( brclr #0x0001, Y0, skip_odd_last );
asm( move.w X:(R0)+, X0 );
asm( asrr.w #8, X0 );
asm( move.bp X0, X:(R3)+ );
skip_odd_last:
asm( move.l X:( R2 + sFlexCAN_offset_canID), B );
asm( cmp.l A, B );
asm( beq id_compare );
asm( move.w X:(R2 + #sFlexCAN_offset_flags), X0 ); /* all flags */
asm( tfr B, A ); /* needed CAN ID -> A */
asm( clr B ); /* form flags on B register */
asm( brclr # CAN_BUF_2B, X:(R2 + #sFlexCAN_offset_flags), Bit_16 );
asm( bfset #CAN_SHORT_IDE_MASK, B1); /* only for long handles */
Bit_16:
asm( adda # devoff_FlexCANBuffer_IdRegHi, R4, R2 ); /* prepare addr for SetCANID */
asm( jsr SetCANID ); /* SetCANID(R2, A, B) & used X0 */
id_compare:
asm( move.w X:( BSP_PERIPH_BASE + archoff_FlexCAN_IntFlags1Reg ), X0 );
asm( and.w C, X0 ); /* to clear isr flag */
asm( move.w X0, X:( BSP_PERIPH_BASE + archoff_FlexCAN_IntFlags1Reg ) );
asm( move.w X:( BSP_PERIPH_BASE + archoff_FlexCAN_IntMask1Reg ), X0 );
asm( or.w C, X0 ); /* to update isr mask */
asm( move.w X0, X:( BSP_PERIPH_BASE + archoff_FlexCAN_IntMask1Reg ) );
asm( move.w #FC_MB_ACTIVE, X:(R4 + devoff_FlexCANBuffer_CtlStatusReg) );
asm( move.w X:( BSP_PERIPH_BASE + archoff_FlexCAN_TimerReg), X0 );
#if __m56800E_lmm__
asm(move.w Y0,A0);
asm(clr.w A1);
#else
asm(nop);
asm(nop);
#endif
}
/*******************************************************************************
*
* NAME: ioctlCANID_GET_STATUS
*
* DESCRIPTION: Driver i/o control procedure - Gets status of message buffer
*
********************************************************************************
* PARAMETERS: file descriptor, command and parameters list
*
* SIDE EFFECTS: None Known
*
* DESIGNER NOTES: returned status value can be one of the following:
* CANID_EMPTY - no messages in the message buffer
* CANID_FULL - a message is in the message buffer
* CANID_OVERFLOW - a message buffer is full
* but some received messages were lost
*
* DEPENDENCIES: None
*******************************************************************************/
unsigned int ioctlCANID_GET_STATUS(handle_t handle, unsigned long params )
{
asm( move.w X:(R2 + #sFlexCAN_offset_flags), X0 );
asm( bfclr #0xFFF0, X0 ); /* clear flags */
asm( move.w #1, B );
asm( asll.w X0, B ); /* get mask for buffer */
asm( move.w # CANID_EMPTY, Y0 ); /* default status */
asm( brclr CAN_BUF_READ_HANDLE, X:(R2 + #sFlexCAN_offset_flags), tx_case );
asm( asll.w #0x3, X0 ); /* x8, convert to buffer index */
asm( adda #( BSP_PERIPH_BASE + archoff_FlexCAN_Buffer_0 ), X0, R4 );
asm( move.w X:( BSP_PERIPH_BASE + archoff_FlexCAN_IntFlags1Reg ), X0 );
asm( and.w X0, B ); /* check bit in flag register */
asm( beq end_status ); /* empty buffer if was no reception */
asm( move.w X:(R4 + devoff_FlexCANBuffer_CtlStatusReg), Y1 );
asm( move.w X:( BSP_PERIPH_BASE + archoff_FlexCAN_TimerReg), X0 );
asm( bfclr #0xFF0F, Y1 ); /* left only raw status */
asm( move.w # CANID_FULL, Y0 );
asm( cmp.w # FC_MB_FULL, Y1 );
asm( beq end_status );
asm( move.w # CANID_OVERFLOW, Y0 );
asm( cmp.w # FC_MB_OVERRUN, Y1 );
asm( beq end_status );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -