📄 serialhw.c
字号:
//Disable Transmiter & Receiver
OUTREG32( &pHWHead->pUartReg->UCR2, INREG32(&pHWHead->pUartReg->UCR2)&~CSP_BITFMASK(UART_UCR2_TXEN) );
OUTREG32( &pHWHead->pUartReg->UCR2, INREG32(&pHWHead->pUartReg->UCR2)&~CSP_BITFMASK(UART_UCR2_RXEN) );
if (pHWHead->UartType == DTE)
{
OUTREG32( &pHWHead->pUartReg->UCR3, INREG32(&pHWHead->pUartReg->UCR3)&~CSP_BITFMASK(UART_UCR3_DCD) );
OUTREG32( &pHWHead->pUartReg->UCR3, INREG32(&pHWHead->pUartReg->UCR3)&~CSP_BITFMASK(UART_UCR3_RI) );
}
if (((PSER_INFO)pHWHead)->useDMA)
{
DDKSdmaStopChan(((PSER_INFO)pHWHead)->SerialDmaChanRx, TRUE);
DDKSdmaStopChan(((PSER_INFO)pHWHead)->SerialDmaChanTx, TRUE);
INSREG32BF(&pHWHead->pUartReg->UCR1, UART_UCR1_RDMAEN, UART_UCR1_RXDMAEN_DISABLE);
INSREG32BF(&pHWHead->pUartReg->UCR1, UART_UCR1_TDMAEN, UART_UCR1_TXDMAEN_DISABLE);
BSPSerRestoreDMAReqGpr(((PSER_INFO)pHWHead)->dwIOBase);
}
SL_ClearPendingInts( pHWHead );
OUTREG32(&pHWHead->pUartReg->UCR1, CSP_BITFVAL(UART_UCR1_UARTEN, UART_UCR1_UARTEN_DISABLE));
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
}
LeaveCriticalSection(&(pHWHead->RegCritSec));
DEBUGMSG(ZONE_CLOSE,(TEXT("SL_Close- \r\n")));
return;
}
//-----------------------------------------------------------------------------
//
// Function: SL_PowerOff
//
// This routine performs powerdown sequence.
//
// Parameters:
// pContext
// [in] Pointer to device head.
//
// Returns:
// None.
//
//-----------------------------------------------------------------------------
VOID SL_PowerOff( PVOID pContext )
{
PUART_INFO pHWHead = (PUART_INFO)pContext;
DEBUGMSG(ZONE_FUNCTION,(TEXT("SL_PowerOff+ \r\n")));
// Disable UART
OUTREG32( &pHWHead->pUartReg->UCR1, INREG32(&pHWHead->pUartReg->UCR1)&~CSP_BITFMASK(UART_UCR1_UARTEN) );
DEBUGMSG(ZONE_FUNCTION,(TEXT("SL_PowerOff- \r\n")));
return;
}
//-----------------------------------------------------------------------------
//
// Function: SL_PowerOn
//
// This routine performs poweron sequence.
//
// Parameters:
// pContext
// [in] Pointer to device head.
//
// Returns:
// None.
//
//-----------------------------------------------------------------------------
VOID SL_PowerOn( PVOID pContext )
{
PUART_INFO pHWHead = (PUART_INFO)pContext;
DEBUGMSG(ZONE_FUNCTION,(TEXT("SL_PowerOn+ \r\n")));
pHWHead->ulDiscard = 0;
// Restore any registers that we need
// In power handler context, so don't try to do a critical section
// Enable UART
INSREG32BF(&pHWHead->pUartReg->UCR1, UART_UCR1_UARTEN, UART_UCR1_UARTEN_ENABLE);
DEBUGMSG(ZONE_FUNCTION,(TEXT("SL_PowerOn- \r\n")));
return;
}
//-----------------------------------------------------------------------------
//
// Function: SL_GetIntrType
//
// This function is called by the MDD whenever
// an interrupt occurs. The return code is then
// checked by the MDD to determine which of the four
// interrupt handling routines are to be called.
//
// Parameters:
// pContext
// [in] Pointer to device head.
//
// Returns:
// This routine returns a bitmask indicating
// which interrupts are currently pending. It returns
// one of the following interrupt types:
// INTR_NONE
// INTR_LINE
// INTR_RX
// INTR_TX
// INTR_MODEM
// These interrupt types are declared in Serhw.h.
//
//-----------------------------------------------------------------------------
INTERRUPT_TYPE SL_GetIntrType( PVOID pContext )
{
PUART_INFO pHWHead = (PUART_INFO)pContext;
PSER_INFO pSerHead = (PSER_INFO)pContext;
INTERRUPT_TYPE interrupts = INTR_NONE;
UINT64 intPndVal = 0;
UINT32 rxStatus = 0, txStatus = 0;
int i;
DEBUGMSG(ZONE_FUNCTION,(TEXT("SL_GetIntrType+ \r\n")));
if (pSerHead->useDMA)
{
DDKSdmaGetBufDescStatus(pSerHead->SerialDmaChanRx, 0, &rxStatus);
DEBUGMSG(ZONE_FLOW, (TEXT("DMA rx Buf %d status = 0x%08X\r\n"), 0, rxStatus));
DDKSdmaGetBufDescStatus(pSerHead->SerialDmaChanRx, 1, &rxStatus);
DEBUGMSG(ZONE_FLOW, (TEXT("DMA rx Buf %d status = 0x%08X\r\n"), 1, rxStatus));
DDKSdmaGetBufDescStatus(pSerHead->SerialDmaChanTx, 0, &txStatus);
DEBUGMSG(ZONE_FLOW, (TEXT("DMA tx Buf 0 status = 0x%08X\r\n"), txStatus));
DDKSdmaGetBufDescStatus(pSerHead->SerialDmaChanRx, pSerHead->currRxDmaBufId, &rxStatus);
}
EnterCriticalSection(&(pHWHead->RegCritSec));
try {
if ((pHWHead->pUartReg->USR1 & CSP_BITFVAL(UART_USR1_FRAMERR, UART_USR1_FRAMERR_SET))
|| (pHWHead->pUartReg->USR1 & CSP_BITFVAL(UART_USR1_PARITYERR, UART_USR1_PARITYERR_SET))
|| (pHWHead->pUartReg->USR2 & CSP_BITFVAL(UART_USR2_BRCD, UART_USR2_BRCD_SET))
|| (pHWHead->pUartReg->USR2 & CSP_BITFVAL(UART_USR2_ORE, UART_USR2_ORE_SET))){
interrupts = INTR_LINE; // 0x1
}
else if ((pHWHead->pUartReg->USR2 & CSP_BITFVAL(UART_USR2_TXDC,UART_USR2_TXDC_SET))
&& (pHWHead->pUartReg->UCR4 & CSP_BITFVAL(UART_UCR4_TCEN, UART_UCR4_TCEN_ENABLE))){
CSP_BITFCLR(pHWHead->pUartReg->UCR4, UART_UCR4_TCEN);
interrupts = INTR_TX; // 0x4
}
else if (((pHWHead->pUartReg->USR2 & CSP_BITFVAL(UART_USR2_RDR, UART_USR2_RDR_SET))
&& (pHWHead->pUartReg->UCR4 & CSP_BITFVAL(UART_UCR4_DREN, UART_UCR4_DREN_ENABLE)))
|| (pHWHead->pUartReg->USR1 & CSP_BITFVAL(UART_USR1_AGTIM, UART_USR1_AGTIM_SET))){
OUTREG32(&pHWHead->pUartReg->USR1, CSP_BITFVAL(UART_USR1_AGTIM, UART_USR1_AGTIM_SET));
interrupts = INTR_RX;
}
else if (((pHWHead->pUartReg->USR1 & CSP_BITFVAL(UART_USR1_DTRD, UART_USR1_DTRD_SET))
&& (pHWHead->pUartReg->UCR3 & CSP_BITFVAL(UART_UCR3_DTRDEN, UART_UCR3_DTRDEN_ENABLE)))
|| ((pHWHead->pUartReg->USR1 & CSP_BITFVAL(UART_USR1_RTSD, UART_USR1_RTSD_SET))
&& (pHWHead->pUartReg->UCR1& CSP_BITFVAL(UART_UCR1_RTSDEN, UART_UCR1_RTSDEN_ENABLE)))
|| ((pHWHead->pUartReg->USR2 & CSP_BITFVAL(UART_USR2_DCDDELT, UART_USR2_DCDDELT_SET))
&& (pHWHead->pUartReg->UCR3 & CSP_BITFVAL(UART_UCR3_DCD, UART_UCR3_DCD_ENABLE)))
|| ((pHWHead->pUartReg->USR2 & CSP_BITFVAL(UART_USR2_RIDELT, UART_USR2_RIDELT_SET)))
&& (pHWHead->pUartReg->UCR3 & CSP_BITFVAL(UART_UCR3_RI, UART_UCR3_RI_ENABLE))){
interrupts = INTR_MODEM; // 0x8
}
else if (pHWHead->pUartReg->USR2 & CSP_BITFVAL(UART_USR2_IRINT, UART_USR2_IRINT_SET)){ //Infrared
OUTREG32(&pHWHead->pUartReg->USR2, CSP_BITFVAL(UART_USR2_IRINT, UART_USR2_IRINT_SET));
interrupts = INTR_MODEM; // 0x8
}
else
{
if (pSerHead->useDMA)
{
if ((rxStatus & DDK_DMA_FLAGS_BUSY) == 0)
{
interrupts = INTR_RX;
DEBUGMSG(ZONE_FLOW, (TEXT("GetIntr: RX SDMA completion\r\n")));
}
else if (pSerHead->awaitingTxDMACompBmp)
{
DEBUGMSG(1, (TEXT("GetIntr: pSerHead->awaitingTxDMACompBmp: %d\r\n"), pSerHead->awaitingTxDMACompBmp));
for (i = 0; i < SERIAL_MAX_DESC_COUNT_TX; i++)
{
if ((1 << i) & pSerHead->awaitingTxDMACompBmp)
{
DDKSdmaGetBufDescStatus(pSerHead->SerialDmaChanTx, i, &txStatus);
DEBUGMSG(1, (TEXT("GetIntr: Status: 0x%x\r\n"), txStatus));
if ((txStatus & DDK_DMA_FLAGS_BUSY) == 0)
{
interrupts = INTR_TX;
pSerHead->awaitingTxDMACompBmp &= ~(1 << i);
DEBUGMSG(ZONE_FLOW, (TEXT("GetIntr: TX SDMA completion\r\n")));
}
}
}
}
else
{
interrupts = INTR_NONE;
}
}
else
interrupts = INTR_NONE;
}
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
intPndVal = INTR_NONE; // simulate no interrupt
}
LeaveCriticalSection(&(pHWHead->RegCritSec));
if (pHWHead->AddTXIntr) {
interrupts |= INTR_TX;
pHWHead->AddTXIntr = FALSE;
DEBUGMSG(ZONE_FUNCTION, (TEXT("SL_GetIntrType - AddTXIntr 0x%x\r\n"),pHWHead->pUartReg->USR1));
}
DEBUGMSG(ZONE_FUNCTION, (TEXT("UART_USR1: 0x%x | UART_USR2: 0x%x\r\n"), pHWHead->pUartReg->USR1, pHWHead->pUartReg->USR2));
DEBUGMSG(ZONE_FUNCTION, (TEXT("SL_GetIntrType- 0x%X\r\n"),interrupts));
return(interrupts);
}
//-----------------------------------------------------------------------------
//
// Function: SL_RxIntrHandler
//
// This function gets zero or more characters
// from the hardware receive buffer and puts them
// into the location pointed to by the pTargetBuffer
// parameter. If there are no characters available
// for reading, this function returns immediately.
// This function is called in response to a receive
// interrupt indication from the SL_GetInterruptType
// function.
//
// Parameters:
// pContext
// [in] Pointer to device head.
// pTargetBuffer
// [in] Pointer to the target buffer in which to put the data.
// pByteNumber
// [in] Pointer to, on entry, the maximum
// number of bytes to read. On exit, the number of
// bytes read.
//
// Returns:
// The return value indicates the number of overruns
// detected. The actual number of dropped characters
// may be higher.
//
//-----------------------------------------------------------------------------
ULONG SL_RxIntrHandler( PVOID pContext, PUCHAR pTargetBuffer, ULONG *pByteNumber )
{
PUART_INFO pHWHead = (PUART_INFO)pContext;
PSER_INFO pSerHead = (PSER_INFO)pContext;
ULONG RetVal = 0;
ULONG TargetRoom = *pByteNumber;
BOOL fRXFlag = FALSE;
BOOL fReplaceparityErrors = FALSE;
BOOL fNull;
UCHAR cEvtChar, cRXChar;
ULONG ulTemp=0;
ULONG LineEvents = 0;
// DMA related
UINT32 Status = 0;
UINT32 Mode = 0;
ULONG copyCount, discardCount;
DEBUGMSG(ZONE_READ, (TEXT("SL_RxIntrHandler+ : len %d. EvtChar 0x%x\r\n"), *pByteNumber,pHWHead->dcb.EvtChar));
*pByteNumber = 0;
cEvtChar = pHWHead->dcb.EvtChar;
fNull = pHWHead->dcb.fNull;
if (pHWHead->dcb.fErrorChar && pHWHead->dcb.fParity)
fReplaceparityErrors = TRUE;
try {
if (pSerHead->useDMA == FALSE)
{
while (TargetRoom) {
// See if there is another byte to be read
SL_ReadLineStatus(pHWHead);
if (pHWHead->sUSR2 & CSP_BITFVAL(UART_USR2_RDR, UART_USR2_RDR_SET)) {
// Read the RX register
ulTemp = INREG32(&pHWHead->pUartReg->URXD);
//Discard the echo char for irda
if (pHWHead->UseIrDA)
if (pHWHead->ulDiscard) {
pHWHead->ulDiscard--;
continue;
}
//Check if a valid char
if(ulTemp & CSP_BITFVAL(UART_URXD_ERR, UART_URXD_ERR_ERROR)) {
DEBUGMSG(ZONE_ERROR,(TEXT("READ ERROR!!! x%x\r\n"),ulTemp));
if (ulTemp & CSP_BITFVAL(UART_URXD_FRMERR, UART_URXD_FRMERR_ERROR)) {
DEBUGMSG(ZONE_ERROR, (TEXT("Error frame\r\n")));
pHWHead->CommErrors |= CE_FRAME;
LineEvents |= EV_ERR;
}
if (ulTemp & CSP_BITFVAL(UART_URXD_PRERR, UART_URXD_PRERR_ERROR)) {
DEBUGMSG(ZONE_ERROR, (TEXT("Error parity\r\n")));
pHWHead->CommErrors |= CE_RXPARITY;
LineEvents |= EV_ERR;
}
if (ulTemp & CSP_BITFVAL(UART_URXD_OVRRUN, UART_URXD_OVRRUN_LSH)) {
DEBUGMSG(ZONE_ERROR, (TEXT("Error Overrun\r\n")));
pHWHead->DroppedBytes++;
pHWHead->CommErrors |= CE_OVERRUN;
LineEvents |= EV_ERR;
}
if (ulTemp & CSP_BITFVAL(UART_URXD_BRK, UART_URXD_BRK_BREAK)) {
DEBUGMSG(ZONE_ERROR, (TEXT("Error Break detect!!!\r\n")));
LineEvents |= EV_BREAK;
}
// Let WaitCommEvent know about this error
if (LineEvents) {
pHWHead->EventCallback(pHWHead->pMDDContext, LineEvents);
} //It's not a valid byte or error;
}
cRXChar = (UCHAR)ulTemp & UART_URXD_RX_DATA_MSK;
DEBUGMSG(ZONE_READ, (TEXT("Read x%x\r\n"), cRXChar));
// But we may want to discard it
//Check DSR(DTR)
if (pHWHead->dcb.fDsrSensitivity && (!pHWHead->bDSR)) {
// Do nothing - byte gets discarded
DEBUGMSG(ZONE_READ, (TEXT("Dropping byte because DSR is high\r\n")));
}
else if (!cRXChar && fNull) {
// Do nothing - byte gets discarded
DEBUGMSG(ZONE_READ, (TEXT("Dropping NULL byte due to fNull\r\n")));
}
else {
// Do character replacement if parity error detected.
//if ( fReplaceparityErrors && (pHWHead->sUSR1 & CSP_BITFVAL(UART_USR1_PARITYERR, UART_USR1_PARITYERR_SET)) ) {
if (fReplaceparityErrors && (ulTemp & CSP_BITFVAL(UART_URXD_PRERR, UART_URXD_PRERR_ERROR))) {
cRXChar = pHWHead->dcb.ErrorChar;
}
else {
// See if we need to generate an EV_RXFLAG for the received char.
if (cRXChar == cEvtChar) {
DEBUGMSG(ZONE_READ, (TEXT("Evt Char x%x\r\n"), cEvtChar));
fRXFlag = TRUE;
}
}
// Finally, we can get byte, update status and save.
*pTargetBuffer++ = cRXChar;
DEBUGMSG(ZONE_READ,(TEXT("R%02x\r\n"),cRXChar));
(*pByteNumber)++;
--TargetRoom;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -