📄 scidrv.c
字号:
if( periphBitTest( SCI_SCICR_TEIE, &pHandle->Base->StatusReg ) == true )
{
ReturnValue |= SCI_STATUS_WRITE_INPROGRESS;
}
return ReturnValue;
}
/*****************************************************************************
*
* Module: sciIoctlSCI_CMD_SEND_BREAK()
*
* Description: Send break symbol via SCI
*
* Returns: None
*
* Arguments: hndl - device descriptor
*
* Range Issues: None
*
* Test Method: sci.mcp
*
*****************************************************************************/
unsigned int sciIoctlSCI_CMD_SEND_BREAK( handle_t hndl, unsigned long params )
{
struct sSciDevice * pHandle = (struct sSciDevice *)hndl;
periphBitSet( SCI_SCICR_SBK, &pHandle->Base->ControlReg );
periphBitClear( SCI_SCICR_SBK, &pHandle->Base->ControlReg );
}
/*****************************************************************************
*
* Module: sciIoctlSCI_CMD_WAIT()
*
* Description: Put SCI device in wait state
*
* Returns: None
*
* Arguments: hndl - device descriptor
*
* Range Issues: None
*
* Test Method: sci.mcp
*
*****************************************************************************/
unsigned int sciIoctlSCI_CMD_WAIT( handle_t hndl, unsigned long params )
{
struct sSciDevice * pHandle = (struct sSciDevice *)hndl;
periphBitSet( SCI_SCICR_RWU, &pHandle->Base->ControlReg );
}
/*****************************************************************************
*
* Module: sciIoctlSCI_CMD_WAKEUP()
*
* Description: Wake up device from wait mode
*
* Returns: None
*
* Arguments: hndl - device descriptor
*
* Range Issues: None
*
* Test Method: sci.mcp
*
*****************************************************************************/
unsigned int sciIoctlSCI_CMD_WAKEUP( handle_t hndl, unsigned long params )
{
struct sSciDevice * pHandle = (struct sSciDevice *)hndl;
periphBitClear( SCI_SCICR_RWU, &pHandle->Base->ControlReg );
}
/*****************************************************************************
*
* Module: sciIoctlSCI_DEVICE_OFF()
*
* Description: Switch device off, disable device related interrupts
*
* Returns: None
*
* Arguments: hndl - device context
*
* Range Issues: None
*
* Test Method: sci.mcp
*
*****************************************************************************/
unsigned int sciIoctlSCI_DEVICE_OFF( handle_t hndl, unsigned long params )
{
struct sSciDevice * pHandle = (struct sSciDevice*)hndl;
scidrvHWDisableInterrupts( pHandle->Base );
/* Clear all receiver related interrupts */
periphMemRead( &pHandle->Base->StatusReg );
periphMemRead( &pHandle->Base->DataReg );
periphMemWrite( 0x0000, &pHandle->Base->StatusReg );
scidrvHWDisableDevice( pHandle->Base );
}
/*****************************************************************************
*
* Module: sciIoctlSCI_DEVICE_ON()
*
* Description: Switch device on, clear read and write buffers, enable
* receiver related interrupts
*
* Returns: None
*
* Arguments: hndl - device context
*
* Range Issues: None
*
* Test Method: sci.mcp
*
*****************************************************************************/
unsigned int sciIoctlSCI_DEVICE_ON( handle_t hndl , unsigned long params )
{
struct sSciDevice * pHandle = (struct sSciDevice *)hndl;
pHandle->qReceive.begin = pHandle->qReceive.end = 0;
pHandle->qSend.begin = pHandle->qSend.end = 0;
scidrvHWEnableDevice( pHandle->Base );
scidrvHWEnableRxInterrupts( pHandle->Base );
}
/*****************************************************************************/
/* ISRs */
/*****************************************************************************/
/*****************************************************************************
*
* Module: sciReceiverISR()
*
* Description: ISRs for SCI receivers
*
* Returns: None
*
* Arguments: None
*
* Range Issues: None
*
* Test Method: sci.mcp
*
*****************************************************************************/
/* ISR registers allocation:
R2 - arch
R3 - context
R4 - callback
*/
/*
user callback:
input: A0 - value(9 bits) which has been received, A1 - error status
output: A0 - value which will be placed into buffer
A1 - error state. If clear If A == -1 value will not be saved
*/
void sciReceiverISR( volatile register arch_sSCI * pArch , struct sSciDevice * pContext, tSciCallBackPtr callback )
{
/*save context*/
asm(adda #2 , SP );
asm(move.l R0 , X:(SP)+ );
asm(move.l X0 , X:(SP)+ );
asm(move.l Y , X:(SP)+ );
asm(move.l A2 , X:(SP)+ );
asm(move.l A10 , X:(SP) );
/* Clear SCI rx and errror related flags */
asm(move.w X:(R2 + #arch_sSCI_offset_StatusReg) , A1 );
asm(clr.w X:(R2 + #arch_sSCI_offset_StatusReg) );
asm(move.w #(SCI_SCISR_OR | SCI_SCISR_NF | SCI_SCISR_FE | SCI_SCISR_PF) , Y1 );
asm(move.w X:(R3 + #sSciDevice_offset_Mask) , Y0 ); /* load mask */
asm(move.w X:(R2 + #arch_sSCI_offset_DataReg) , A0 ); /* read Rx reg */
asm(and.l Y , A ); /* apply mask */
/* break symbol detecting */
asm(brclr #SCI_SCISR_FE , A1 , test_iterators );
asm(tst.w A0 );
asm(bne test_iterators );
asm(bfset #SCI_EXCEPTION_BREAK_SYMBOL , A1 );
test_iterators:
/* load queue descriptor */
asm(move.l X:(R3 + #(sSciDevice_offset_qReceive + sQueue_offset_begin)) , Y ); /* Y0 := begin. Y1 := end */
asm(move.w X:(R3 + #(sSciDevice_offset_qReceive + sQueue_offset_mask)) , X0 );
/* calculate free space in queue */
asm(sub Y0 , Y1 );
asm(add X0 , Y1 ); /* Y1 := mask - (begin - end) == free space - 1*/
asm(bge call_RxCallBack ); /* if X0 >= Y1, mask >= (begin-end) */
asm(bfset #SCI_EXCEPTION_BUFFER_OVERFLOW , A1 );
call_RxCallBack:
/* call callback */
asm(jsr (R4) );
asm(cmp.l #-1 , A ); /* if return "-1" in A */
asm(beq exit_handler );
asm(cmp.w Y1 , X0 );
asm(bcs exit_handler ); /* if overflow occured */
/* setup buffer pointer */
asm(and.w Y0 , X0); /* X0 := moduled begin */
asm(add.w X:(R3 + #(sSciDevice_offset_qReceive + sQueue_offset_bufferOffset)) , X0 );
asm(adda #BASE_CIRCULAR_BUFFER_ADDRESS , X0 , R0 );
asm(move.w A0 , X0 );
asm(move.w X0 , P:(R0)+ );
/* move begin iterator */
asm(inc.w Y0 ); /* Y0 == begin iterator*/
asm(move.w Y0 , X:(R3 + #(sSciDevice_offset_qReceive + sQueue_offset_begin)) );
exit_handler:
/*restore context*/
asm(move.l X:(SP)- , A );
asm(move.l X:(SP)- , A2 );
asm(move.l X:(SP)- , Y );
asm(move.l X:(SP)- , X0 );
asm(move.l X:(SP)- , R0 );
}
/*****************************************************************************
*
* Module: sciTransmitterISR()
*
* Description: ISRs for SCI transmitters
*
* Returns: None
*
* Arguments: None
*
* Range Issues: None
*
* Test Method: sci.mcp
*
*****************************************************************************/
/* ISR registers allocation:
R2 - arch
R3 - context
R4 - callback
*/
/*
user callback:
input: A0 - value which is going to sent. A = -1 if there is nothing to send
output: A0 - value which will be sent, A = "-1" if stop transmission
*/
void sciTransmitterISR( volatile register arch_sSCI * pArch , struct sSciDevice * pContext, tSciCallBackPtr callback )
{
/*save context*/
asm(adda #2 , SP );
asm(move.l R0 , X:(SP)+ );
asm(move.l X0 , X:(SP)+ );
asm(move.l Y , X:(SP)+ );
asm(move.l A2 , X:(SP)+ );
asm(move.l A10 , X:(SP) );
/*setup buffer pointer */
asm(move.l X:(R3 + #(sSciDevice_offset_qSend + sQueue_offset_begin)) , Y ); /* Y0 := begin, Y1 := end */
asm(move.w X:(R3 + #(sSciDevice_offset_qSend + sQueue_offset_mask)) , X0 );
asm(and.w Y1 , X0 );
asm(add.w X:(R3 + #(sSciDevice_offset_qSend + sQueue_offset_bufferOffset)) , X0 );
asm(adda #BASE_CIRCULAR_BUFFER_ADDRESS , X0 , R0 );
asm(clr A );
asm(move.w P:(R0)+ , X0 ); /* read from queue*/
asm(move.w X0 , A0 );
asm(cmp Y1 , Y0 );
asm(bne tx_callback );
asm(move.l #-1 , A ); /* set "-1" */
tx_callback:
/* call users callback */
asm(jsr ( R4 ) ); /* call transmit callback */
go_on:
asm(cmp.l #-1 , A );
asm(bne transmit_go_on );
asm(bfclr #SCI_SCICR_TEIE , X:(R2 + #arch_sSCI_offset_ControlReg) ); /* disable interrupt */
/* correct queue iterators after force stopping */
asm(move.w X:(R3 + #(sSciDevice_offset_qSend + sQueue_offset_end)) , X0);
asm(move.w X0 , X:(R3 + #(sSciDevice_offset_qSend + sQueue_offset_begin)) );
asm(bra exit_isr);
transmit_go_on:
asm(inc.w Y1); /* move end iterator */
asm(move.w Y1 , X:(R3 + #(sSciDevice_offset_qSend + sQueue_offset_end)) ); /* update queue descriptor*/
/* Clear SCI tx related flags */
asm(move.w X:(R2 + #arch_sSCI_offset_StatusReg) , X0 );
/* be performed before write to Data register to clear SCI Transmitter Ready & Idle flags */
asm(move.w X:(R3 + #sSciDevice_offset_Mask) , Y0 );
asm(and.l Y , A);
/* send byte */
asm(move.w A0 , X:(R2 + #arch_sSCI_offset_DataReg) );
exit_isr:
/*restore context*/
asm(move.l X:(SP)- , A );
asm(move.l X:(SP)- , A2 );
asm(move.l X:(SP)- , Y );
asm(move.l X:(SP)- , X0 );
asm(move.l X:(SP)- , R0 );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -