serialhw.c
来自「Microsoft WinCE 6.0 BSP FINAL release so」· C语言 代码 · 共 1,841 行 · 第 1/5 页
C
1,841 行
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))){
pHWHead->pUartReg->USR1=CSP_BITFVAL(UART_USR1_AGTIM, UART_USR1_AGTIM_SET);
interrupts = INTR_RX;
} else if ((pHWHead->pUartReg->USR1 & CSP_BITFVAL(UART_USR1_RTSD, UART_USR1_RTSD_SET))
&& (pHWHead->pUartReg->UCR1& CSP_BITFVAL(UART_UCR1_RTSDEN, UART_UCR1_RTSDEN_ENABLE))){
DEBUGMSG(ZONE_FUNCTION, (TEXT("RTS change state detected 0x%x\r\n"),pHWHead->pUartReg->USR1));
interrupts = INTR_MODEM; // 0x8
} else if (pHWHead->pUartReg->USR2 & CSP_BITFVAL(UART_USR2_IRINT, UART_USR2_IRINT_SET)){ //Infrared
pHWHead->pUartReg->USR2=CSP_BITFVAL(UART_USR2_IRINT, UART_USR2_IRINT_SET);
interrupts = INTR_MODEM; // 0x8
} else
interrupts = INTR_NONE; // 0x0 No interrupts pending, vector is useless
}
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;
ULONG RetVal = 0;
ULONG TargetRoom = *pByteNumber;
BOOL fRXFlag = FALSE;
BOOL fReplaceparityErrors = FALSE;
BOOL fNull;
UCHAR cEvtChar, cRXChar;
ULONG ulTemp=0;
ULONG LineEvents = 0;
DEBUGMSG(ZONE_FUNCTION, (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 {
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));
continue;
}
cRXChar = (UCHAR)ulTemp & UART_URXD_RX_DATA_MSK;
DEBUGMSG(ZONE_FUNCTION, (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_FUNCTION, (TEXT("Dropping byte because DSR is high\r\n")));
}
else if (!cRXChar && fNull) {
// Do nothing - byte gets discarded
DEBUGMSG(ZONE_FUNCTION, (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_FUNCTION, (TEXT("Evt Char x%x\r\n"), cEvtChar));
fRXFlag = TRUE;
}
}
// Finally, we can get byte, update status and save.
*pTargetBuffer++ = cRXChar;
DEBUGMSG(ZONE_FUNCTION,(TEXT("R%02x\r\n"),cRXChar));
(*pByteNumber)++;
--TargetRoom;
}
}
else {
// We read all chars, so we're done
break;
}
}
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
}
// if we saw one (or more) EVT chars, then generate an event
if (fRXFlag) {
pHWHead->EventCallback(pHWHead->pMDDContext, EV_RXFLAG);
DEBUGMSG(ZONE_FUNCTION, (TEXT("EV_RXFLAG set\r\n")));
}
else {
DEBUGMSG(ZONE_FUNCTION, (TEXT("EV_RXFLAG not set\r\n")));
}
if (pHWHead->DroppedBytes)
DEBUGMSG(ZONE_FUNCTION, (TEXT("Rx drop %d.\r\n"), pHWHead->DroppedBytes));
DEBUGMSG(ZONE_FUNCTION, (TEXT("SL_RxIntrHandler - rx'ed %d, dropped %d.\r\n"), *pByteNumber, pHWHead->DroppedBytes));
RetVal = pHWHead->DroppedBytes;
pHWHead->DroppedBytes = 0;
return(RetVal);
}
//-----------------------------------------------------------------------------
//
// Function: SL_TxIntrHandler
//
// This function is called when the driver
// detects a transmit interrupt (INTR_TX), as set by
// the SL_GetInterruptType function. It sends several
// characters to the hardware transmission buffer.
//
// Parameters:
// pContext
// [in] Pointer to device head.
// pSourceBuffer
// [in] Pointer to the source buffer that contains data to be sent.
// pByteNumber
// [in] When SL_TxIntrEx is called,
// pByteNumber points to the maximum number of bytes
// to send. When SL_TxIntrEx returns, pByteNumber
// points to the actual number of bytes sent..
//
// Returns:
// None.
//
//-----------------------------------------------------------------------------
VOID SL_TxIntrHandler( PVOID pContext, PUCHAR pSourceBuffer, ULONG *pByteNumber )
{
PUART_INFO pHWHead = (PUART_INFO)pContext;
UCHAR byteCount;
ULONG NumberOfBytes = *pByteNumber;
DEBUGMSG(ZONE_FUNCTION, (TEXT("SL_TxIntrHandler+\r\n")));
DEBUGMSG(ZONE_FUNCTION, (TEXT("Transmit Event 0x%X, Len %d\r\n"), pContext, *pByteNumber));
SL_ReadModemStatus(pHWHead);
// We may be done sending. If so, just disable the TX interrupts
// and return to the MDD.
if (! *pByteNumber) {
DEBUGMSG(ZONE_FUNCTION, (TEXT("SL_TxIntrHandler - Disable INTR_TX.\r\n")));
//Disable the TX interrupts
OUTREG32( &pHWHead->pUartReg->UCR4, INREG32(&pHWHead->pUartReg->UCR4)&~CSP_BITFMASK(UART_UCR4_TCEN) );
return;
}
*pByteNumber = 0; // In case we don't send anything below.
// Disable xmit intr. Most 16550s will keep hammering
// us with xmit interrupts if we don't turn them off
// Whoever gets the FlushDone will then need to turn
// TX Ints back on if needed.
EnterCriticalSection(&(pHWHead->RegCritSec));
try {
// Need to signal FlushDone for XmitComChar
PulseEvent(pHWHead->FlushDone);
pHWHead->CommErrors &= ~CE_TXFULL;
// If CTS flow control is desired, check cts. If clear, don't send,
// but loop. When CTS comes back on, the OtherInt routine will
// detect this and re-enable TX interrupts (causing Flushdone).
// For finest granularity, we would check this in the loop below,
// but for speed, I check it here (up to 8 xmit characters before
// we actually flow off.
if (pHWHead->dcb.fOutxCtsFlow) {
DEBUGMSG(ZONE_FUNCTION, (TEXT("SL_TxIntrHandler - fOutxCtsFlow true\r\n")));
// We don't need to explicitly read the MSR, since we always enable
// IER_MS, which ensures that we will get an interrupt and read
// the MSR whenever CTS, DSR, TERI, or DCD change.
//Check CTS (RTS), 1:low, 0:high;
if (!(pHWHead->sUSR1 & CSP_BITFVAL(UART_USR1_RTSS, UART_USR1_RTSS_SET))) {
DEBUGMSG(ZONE_FUNCTION, (TEXT("SL_TxIntrHandler - fOutxCtsFlow true 0x%x, 0x%x\r\n"),pHWHead->sUSR1,pHWHead->pUartReg->USR1));
DEBUGMSG(ZONE_FUNCTION, (TEXT("SL_TxIntrHandler, flowed off via CTS\n") ) );
pHWHead->CTSFlowOff = TRUE; // Record flowed off state
// disable TX interrupts while flowed off
OUTREG32( &pHWHead->pUartReg->UCR4, INREG32(&pHWHead->pUartReg->UCR4)&~CSP_BITFMASK(UART_UCR4_TCEN) );
// We could return a positive value here, which would
// cause the MDD to periodically check the flow control
// status. However, we don't need to since we know that
// the DCTS interrupt will cause the MDD to call us, and we
// will subsequently fake a TX interrupt to the MDD, causing
// him to call back into PutBytes.
LeaveCriticalSection(&(pHWHead->RegCritSec));
return;
}
}
// Same thing applies for DSR
if (pHWHead->dcb.fOutxDsrFlow) {
DEBUGMSG(ZONE_FUNCTION, (TEXT("SL_TxIntrHandler - fOutxDsrFlow true\r\n")));
// We don't need to explicitly read the register, since we always enable
// interrupt, which ensures that we will get an interrupt and read
// the register whenever CTS, DSR, TERI, or DCD change.
//Check shadow bDSR, 1:low, 0:high
if (!pHWHead->bDSR) {
pHWHead->DSRFlowOff = TRUE; // Record flowed off state
// disable TX interrupts while flowed off
OUTREG32( &pHWHead->pUartReg->UCR4, INREG32(&pHWHead->pUartReg->UCR4)&~CSP_BITFMASK(UART_UCR4_TCEN) );
// See the comment above above positive return codes.
LeaveCriticalSection(&(pHWHead->RegCritSec));
return;
}
}
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
// Do nothing. The worst case is that this was a fluke,
// and a TX Intr will come right back at us and we will
// resume transmission.
}
LeaveCriticalSection(&(pHWHead->RegCritSec));
// OK, now lets actually transmit some data.
EnterCriticalSection(&(pHWHead->TransmitCritSec));
EnterCriticalSection(&(pHWHead->RegCritSec));
try {
// Enable xmit intr. We need to do this no matter what,
// since the MDD relies on one final interrupt before
// returning to the application.
OUTREG32(&pHWHead->pUartReg->USR2,CSP_BITFVAL(UART_USR2_TXDC, UART_USR2_TXDC_SET));
SL_ReadLineStatus(pHWHead);
if (pHWHead->sUSR2 & CSP_BITFVAL(UART_USR2_TXFE, UART_USR2_TXFE_SET)) {
//always enable FIFO
byteCount = UART_TXFIFO_DEPTH-SER_FIFO_TXTL;
DEBUGMSG(ZONE_FUNCTION, (TEXT("SL_TxIntrHandler - Write max of %d bytes to 0x%x\r\n"), byteCount, &pHWHead->pUartReg->UTXD));
for (*pByteNumber=0; NumberOfBytes && byteCount; NumberOfBytes--, byteCount--) {
OUTREG32(&pHWHead->pUartReg->UTXD,*pSourceBuffer);
DEBUGMSG(ZONE_FUNCTION, (TEXT("Write x%x\r\n"), *pSourceBuffer));
//We need to discard the echo char for irda
if (pHWHead->UseIrDA)
pHWHead->ulDiscard++;
++pSourceBuffer;
(*pByteNumber)++;
}
}
DEBUGMSG(ZONE_FUNCTION, (TEXT("SL_TxIntrHandler: Enable INTR_TX.\r\n")));
INSREG32BF(&pHWHead->pUartReg->UCR4, UART_UCR4_TCEN, UART_UCR4_TCEN_ENABLE);
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
}
LeaveCriticalSection(&(pHWHead->RegCritSec));
LeaveCriticalSection(&(pHWHead->TransmitCritSec));
DEBUGMSG(ZONE_FUNCTION, (TEXT("SL_TxIntrHandler- sent %d.\r\n"), *pByteNumber));
return;
}
//-----------------------------------------------------------------------------
//
// Function: SL_ModemIntrHandler
//
// This function handles the modem interrupt. It
// collects the modem status of the serial port, and
// updates internal driver status information.
// In the new serial port upper layer implementation
// available in Microsoft Windows CE 3.0 and later,
// this function replaces the HWOtherIntrHandler
// function.
//
// Parameters:
// pContext
// [in] Pointer to device head.
//
// Returns:
// None.
//
//-----------------------------------------------------------------------------
VOID SL_ModemIntrHandler( PVOID pContext )
{
PUART_INFO pHWHead = (PUART_INFO)pContext;
DEBUGMSG(ZONE_FUNCTION, (TEXT("SL_ModemIntrHandler+\r\n")));
SL_ReadModemStatus( pHWHead );
if (!((PSER_INFO)pContext)->cOpenCount) {
// We want to indicate a cable event.
if (!pHWHead->UseIrDA) {
if ((pHWHead->sUSR1 & CSP_BITFVAL(UART_USR1_RTSS, UART_USR1_RTSS_SET)))
if (IsAPIReady(SH_WMGR)) {
DEBUGMSG(ZONE_FUNCTION, (TEXT("RS232 notification!!!\r\n")));
CeEventHasOccurred (NOTIFICATION_EVENT_RS232_DETECTED,NULL);
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?