📄 scidrv.c
字号:
/*******************************************************************************
*
* Motorola Inc.
* (c) Copyright 2002 Motorola, Inc.
* ALL RIGHTS RESERVED.
*
*
* Description: source file for the 56838 SCI device driver
*
* Notes:
*
******************************************************************************/
#include <stdarg.h>
#include "bsp.h"
#include "syslib.h"
#include "periph.h"
#include "scidrv.h"
#include "arch_off.h"
#include "gpioinline.h"
/*****************************************************************************/
/* Driver Function prototypes */
/*****************************************************************************/
#define scidrvHWDisableInterrupts(BaseAddress) (periphBitClear(SCI_SCICR_TEIE | SCI_SCICR_TIIE | SCI_SCICR_RIE | SCI_SCICR_REIE, &BaseAddress->ControlReg))
#define scidrvHWEnableRxInterrupts(BaseAddress) (periphBitSet(SCI_SCICR_RIE | SCI_SCICR_REIE, &BaseAddress->ControlReg))
#define scidrvHWDisableRxInterrupts(BaseAddress) (periphBitClear(SCI_SCICR_RIE | SCI_SCICR_REIE, &BaseAddress->ControlReg))
#define scidrvHWEnableTxCompleteInterrupt(BaseAddress) (periphBitSet(SCI_SCICR_TIIE, &BaseAddress->ControlReg))
#define scidrvHWEnableTxReadyInterrupt(BaseAddress) (periphBitSet(SCI_SCICR_TEIE, &BaseAddress->ControlReg))
#define scidrvHWDisableTxInterrupts(BaseAddress) (periphBitClear(SCI_SCICR_TEIE | SCI_SCICR_TIIE, &BaseAddress->ControlReg))
#define scidrvHWDisableTx(BaseAddress) (periphBitClear(SCI_SCICR_TE, &BaseAddress->ControlReg))
#define scidrvHWDisableRx(BaseAddress) (periphBitClear(SCI_SCICR_RE, &BaseAddress->ControlReg))
#define scidrvHWDisableDevice(BaseAddress) (periphBitClear(SCI_SCICR_TE | SCI_SCICR_RE, &BaseAddress->ControlReg))
#define scidrvHWEnableDevice(BaseAddress) (periphBitSet(SCI_SCICR_TE | SCI_SCICR_RE, &BaseAddress->ControlReg))
/*****************************************************************************/
/* API */
/*****************************************************************************/
handle_t sciPreOpen( const char * pName, struct io_sDevice* pDev, int OFlags , ... )
{
struct sSciDevice * pSciDevice;
unsigned long BaudRate;
unsigned long rawBaudRate;
va_list Args;
Args = (char *)&OFlags;
BaudRate = va_arg(Args, unsigned long);
va_end(Args);
switch ((int)pName)
{
case (int) BSP_DEVICE_NAME_SCI_0:
pSciDevice = &Sci0DeviceContext;
/* CONFIGURE SCI PINS TO BE PERIPHERAL */
gpioIoctlGPIO_SETAS_PERIPHERAL( SCI0_GPIO_BASE_ADDRESS, SCI0_GPIO_MASK );
break;
case (int) BSP_DEVICE_NAME_SCI_1:
pSciDevice = &Sci1DeviceContext;
/* CONFIGURE SCI PINS TO BE PERIPHERAL */
gpioIoctlGPIO_SETAS_PERIPHERAL( SCI1_GPIO_BASE_ADDRESS, SCI1_GPIO_MASK );
break;
default:
return (handle_t)-1;
}
scidrvHWDisableInterrupts( pSciDevice->Base );
scidrvHWDisableDevice( pSciDevice->Base );
if(OFlags & O_NONBLOCK)
{
extern const struct io_sSCIInterface scidrvIONonBlockInterfaceVT;
pSciDevice->drvInterface = (io_sInterface *)&scidrvIONonBlockInterfaceVT;
}
else
{
extern const struct io_sSCIInterface scidrvIOBlockInterfaceVT;
pSciDevice->drvInterface = (io_sInterface *)&scidrvIOBlockInterfaceVT;
}
rawBaudRate = sci_getBaudRate( BaudRate );
return sciOpen( (const char*)pSciDevice, OFlags, rawBaudRate );
}
/*****************************************************************************
*
* Module: sciOpen
*
* Description: Open SCI device.
* Initialize device context
*
* Returns: Device handle if successful,
* -1 if device name is not supported
*
* Arguments: pName - BSP SCI device name
* OFlags - open mode (for detail see sci.h file)
* O_NONBLOCK
* O_BLOCK
* O_SCI_DISABLE_IN_WAIT
* O_SCI_ENABLE_IN_WAIT
* O_SCI_WAKE_BY_ADDRESS
* O_SCI_WAKE_BY_IDLE
* O_SCI_WORD_9BIT
* O_SCI_WORD_8BIT
* O_SCI_PARITY_NONE
* O_SCI_PARITY_ODD
* O_SCI_PARITY_EVEN
* O_SCI_7_DATA_BITS_ODD_PARITY
* O_SCI_7_DATA_BITS_EVEN_PARITY
* O_SCI_8_DATA_BITS_NO_PARITY
* O_SCI_8_DATA_BITS_ODD_PARITY
* O_SCI_8_DATA_BITS_EVEN_PARITY
* O_SCI_9_DATA_BITS_NO_PARITY
* O_SCI_TX_INVERTED
* O_SCI_TX_NOT_INVERTED
* O_SCI_INVERT_ALL_BITS
* O_SCI_DONT_INVERT_ANY_BITS
* O_SCI_LOOPBACK_DISABLED
* O_SCI_LOOPBACK_ENABLED
* O_SCI_LOOPBACK_SINGLE_WIRE_ENABLED
*
*
* Range Issues: None
*
* Test Method: sci.mcp
*
*****************************************************************************/
handle_t sciOpen( const char * pName, int OFlags, unsigned long rawBaudRate )
{
struct sSciDevice* pSciDevice = (struct sSciDevice*)pName;
unsigned int ControlWord;
short Control = 0;
if(OFlags && 0xFFF0)
{
Control = OFlags & 0xFFF0;
}
if( OFlags & O_SCI_DATA_9BIT )
{
if( OFlags & (O_SCI_PARITY_ODD | O_SCI_PARITY_EVEN) )
pSciDevice->Mask = SCI_SCIDR_8BIT_MASK; /* 8 with parity */
else
pSciDevice->Mask = SCI_SCIDR_9BIT_MASK;
}
else /* O_SCI_DATA_8BIT */
{
if( OFlags & (O_SCI_PARITY_ODD | O_SCI_PARITY_EVEN) )
pSciDevice->Mask = SCI_SCIDR_7BIT_MASK;
else
pSciDevice->Mask = SCI_SCIDR_8BIT_MASK; /* 8 without parity */
}
periphMemWrite( rawBaudRate, &pSciDevice->Base->BaudRateReg );
periphMemWrite( Control & SCI_SCICR_USER_MASK, &pSciDevice->Base->ControlReg );
/* Clear all receiver related interrupts */
periphMemRead( &pSciDevice->Base->StatusReg );
periphMemRead( &pSciDevice->Base->DataReg );
periphMemWrite( 0x0000, &pSciDevice->Base->StatusReg );
scidrvHWEnableRxInterrupts( pSciDevice->Base );
scidrvHWEnableDevice( pSciDevice->Base );
pSciDevice->qReceive.begin = pSciDevice->qReceive.end = 0;
pSciDevice->qSend.begin = pSciDevice->qSend.end = 0;
return (handle_t)pSciDevice;
}
/*****************************************************************************
*
* Module: sciClose()
*
* Description: Close SCI device. Uninstall ISR vectors, if used.
*
* Returns: 0
*
* Arguments: hndl - device context
*
* Range Issues: None
*
* Test Method: sci.mcp
*
*****************************************************************************/
int sciClose( handle_t hndl )
{
struct sSciDevice * pHandle = (struct sSciDevice *)hndl;
volatile unsigned int status = 0;
scidrvHWDisableRx( pHandle->Base );
while(1)
{
status = periphMemRead( &pHandle->Base->StatusReg );
if( status & SCI_SCISR_TIDLE )
{
break;
}
}
scidrvHWDisableTx( pHandle->Base );
#if defined(BSP_DEVICE_NAME_SCI_0)
/* return GPIO pins in default state */
if( pHandle->Base == SCI0_BASE_ADDRESS )
{
gpioIoctlGPIO_SETAS_GPIO( SCI0_GPIO_BASE_ADDRESS, SCI0_GPIO_MASK );
}
#endif
#if defined(BSP_DEVICE_NAME_SCI_1)
if( pHandle->Base == SCI1_BASE_ADDRESS )
{
gpioIoctlGPIO_SETAS_GPIO( SCI1_GPIO_BASE_ADDRESS, SCI1_GPIO_MASK );
}
#endif /* defined(BSP_DEVICE_NAME_SCI_1) */
return 0;
}
/*****************************************************************************
*
* Module: sciNonBlockRead()
*
* Description: Read data from SCI driver into user buffer
*
* In NonBlocking mode, "read" returns the actual data that
* has already been received from the SCI device. It does not
* wait for more data, if NBytes is greater than data size
* already contained in the buffer.
*
* Returns: Actual read size
*
* Arguments: hndl - SCI Device descriptor returned by "sciOpen" call.
* pBuffer - Char pointer to user buffer.
* NBytes - NBytes (in 8-bit bytes) of the data to be read
* from SCI device;
*
* Range Issues: None
*
* Test Method: sci.mcp
*
*****************************************************************************/
ssize_t sciNonBlockRead( handle_t hndl, void * pBuffer, size_t NBytes )
{
asm(move.w M01, B ); /* save modulo context in B */
#if __m56800E_lmm__
asm(move.w A0,A);
asm(move.w A1,Y0);
#else
asm(nop);
asm(nop);
#endif
asm(move.w Y0,A); /* A := size */
/* load queue descriptor */
asm(move.l X:(R2 + #(sSciDevice_offset_qReceive + sQueue_offset_begin) ), Y); /* Y0 := begin, Y1 := end */
/* use space in queue */
asm(sub Y1,Y0); /* Y0 := begin - end */
asm(cmp.w Y0,A);
asm(tgt Y0,A); /* if ("buffer size" < "count of ready chars in queue") then copy only "buffer size" chars */
/* setup modulo */
asm(move.w X:(R2 + #(sSciDevice_offset_qReceive + sQueue_offset_mask) ) , X0);
asm(moveu.w X0,M01);
/* setup buffer pointer */
asm(and.w Y1,X0); /* X0 := moduled begin (Y0) */
asm(add.w X:(R2 + #(sSciDevice_offset_qReceive + sQueue_offset_bufferOffset) ) , X0);
asm(adda #BASE_CIRCULAR_BUFFER_ADDRESS,X0,R0);
asm(do A,end_reading_loop);
asm(move.w P:(R0)+,X0);
asm(nop);
asm(nop);
asm(move.bp X0,X:(R3)+);
asm(end_reading_loop:);
/* update queue descriptor */
asm(add A,Y1);
asm(move.w Y1,X:(R2 + #(sSciDevice_offset_qReceive + sQueue_offset_end) ) );
asm(move.w A,Y0);
#if __m56800E_lmm__
asm(move.w A1,A0);
asm(clr.w A1);
#else
asm(nop);
asm(nop);
#endif
asm(moveu.w B, M01 ); /* restore modulo context */
/* asm(rts); */
}
/*****************************************************************************
*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -