📄 pdds3c6410_ser.cpp
字号:
}
if ((dwData & S6410UART_INT_ERR)!=0)
{
interrupts |= INTR_LINE | INTR_RX;
}
if ((dwData & S6410UART_INT_MODEM)!=0)
{
interrupts |=INTR_MODEM;
}
NotifyPDDInterrupt( (INTERRUPT_TYPE)interrupts );
ClearInterrupt(dwData);
}
else
{
break;
}
}
m_HardwareLock.Unlock();
InterruptDone(m_dwSysIntr);
}
else
{
DEBUGMSG(ZONE_THREAD,(TEXT(" CPdd6410Uart::ThreadRun timeout INT=%x,MASK=%d\r\n"),m_pReg6410Uart->Read_UINTP()/*m_pReg6410Uart->Read_UINTSP()*/, m_pReg6410Uart->Read_UINTM()) );
ASSERT(FALSE);
}
}
return 1;
}
BOOL CPdd6410Uart::InitialEnableInterrupt(BOOL bEnable )
{
m_HardwareLock.Lock();
if (bEnable)
{
EnableInterrupt(S6410UART_INT_RXD | S6410UART_INT_ERR | S6410UART_INT_MODEM);
}
else
{
DisableInterrupt(S6410UART_INT_RXD | S6410UART_INT_ERR | S6410UART_INT_MODEM);
}
m_HardwareLock.Unlock();
return TRUE;
}
BOOL CPdd6410Uart::InitXmit(BOOL bInit)
{
DWORD dwTicks = 0;
DWORD dwUTRState;
if (bInit)
{
m_HardwareLock.Lock();
DWORD dwBit = m_pReg6410Uart->Read_UCON();
#if EPLL_CLK
// Set UART CLK.
dwBit &= ~(UART_CS_MASK);
dwBit |= (UART_CS_EPLLCLK);
#endif
if (m_ClockSelectValid) {
dwBit &= ~(UART_CS_MASK);
dwBit |= (m_ClockSelect);
}
// Set Tx Inerrupt Request Type, Tx Interrupt/Polling Mode.
dwBit &= ~(UART_TX_INT_TYPE_MASK|UART_TX_MODE_MASK);
dwBit |= (UART_TX_INT_TYPE_LEVEL|UART_TX_INT_POLL);
m_pReg6410Uart->Write_UCON(dwBit );
dwBit = m_pReg6410Uart->Read_UFCON();
// Reset Xmit Fifo.
dwBit |= (UART_FCR_TX_FIFO_RESET);
dwBit &= ~(UART_FCR_FIFO_ENABLE);
m_pReg6410Uart->Write_UFCON( dwBit);
// Set Trigger level to 16.
dwBit &= ~(UART_FCR_TX_FIFO_TRIG_MASK);
dwBit |= (UART_FCR_TX_FIFO_TRIG_16);//16
m_pReg6410Uart->Write_UFCON(dwBit);
// Enable Xmit FIFO.
dwBit &= ~(UART_FCR_TX_FIFO_RESET);
dwBit |= (UART_FCR_FIFO_ENABLE);
m_pReg6410Uart->Write_UFCON(dwBit); // Xmit Fifo Reset Done..
m_HardwareLock.Unlock();
#ifdef USE_DMA
if(m_dwTXDMAEnable)
{
InitXmitDMA();
}
#endif
}
else
{ // Make Sure data has been trasmit out.
// We have to make sure the xmit is complete because MDD will shut down the device after this return
while (dwTicks < TIMEOUT_TX_EMPTY && ((dwUTRState = m_pReg6410Uart->Read_UTRSTAT()) & (UART_TRANSMITTER_STATUS_MASK | UART_TX_BUFFER_STATUS_MASK))
!= (UART_TRANSMITTER_EMPTY | UART_TX_BUFFER_EMPTY))
{ // Transmitter empty is not true
DEBUGMSG(ZONE_THREAD|ZONE_WRITE, (TEXT("CPdd6410Uart::InitXmit! Wait for UTRSTAT=%x clear.\r\n"), dwUTRState));
Sleep(5);
dwTicks +=5;
}
}
return TRUE;
}
DWORD CPdd6410Uart::GetWriteableSize()
{
DWORD dwWriteSize = 0;
DWORD dwUfState = m_pReg6410Uart->Read_UFSTAT() ;
if ((dwUfState & UART_FSR_TX_FIFO_MASK)==UART_FSR_TX_FIFO_NOT_FULL)
{ // It is not full.
dwUfState = ((dwUfState & UART_FSR_TX_FIFO_COUNT_MASK) >> UART_FSR_TX_FIFO_COUNT_SHFIT); // It is fifo count.
if (dwUfState < S3C6410_UART_FIFO_DEPTH-1)
{
dwWriteSize = S3C6410_UART_FIFO_DEPTH-1 - dwUfState;
}
}
return dwWriteSize;
}
#ifdef USE_DMA
void CPdd6410Uart::XmitInterruptHandler(PUCHAR pTxBuffer, ULONG *pBuffLen)
{
BOOL bRet;
PREFAST_DEBUGCHK(pBuffLen!=NULL);
m_HardwareLock.Lock();
//wait until TX FIFO empty
// 6ms : 38400 baudrate/64Byte
// 85us : 3M baudrate/64Byte
// It affects when BT power on and off at low baudrate
if((m_dwTXDMAEnable==1) && (*pBuffLen < UART_TX_FIFO_LEN))
{
while(((m_pReg6410Uart->Read_UFSTAT()>>8) & 0x3f))
{
RETAILMSG(FALSE, (TEXT("[UART] Wait \r\n")));
}
}
if (*pBuffLen == 0)
{
EnableXmitInterrupt(FALSE);
}
else
{
DEBUGCHK(pTxBuffer);
PulseEvent(m_XmitFlushDone);
DWORD dwDataAvaiable = *pBuffLen;
*pBuffLen = 0;
DMA_ERROR dma_error_value = DMA_SUCCESS;
Rx_Pause(TRUE);
if ((m_DCB.fOutxCtsFlow && IsCTSOff()) ||(m_DCB.fOutxDsrFlow && IsDSROff()))
{ // We are in flow off
RETAILMSG(FALSE, (TEXT("CPddS3CXUart::XmitInterruptHandler! Flow Off, Data Discard.\r\n")));
EnableXmitInterrupt(FALSE);
}
else
{
if((m_dwTXDMAEnable==1)&&(dwDataAvaiable> UART_TX_FIFO_LEN/*UART_TX_FIFO_LEN*/))
{
DWORD dwDmaLen = (dwDataAvaiable > Buffer_Mem_Size)? Buffer_Mem_Size:dwDataAvaiable;
RETAILMSG(0,(TEXT("[UART] Thread for TX : USE DMA (TxCount : %d) \r\n"),dwDmaLen));
if(dwDmaLen > 0)
{
bRet = StartXmitDMA(pTxBuffer, dwDmaLen);
if(!bRet)
{
goto LEAVEWRITE;
}
dwDataAvaiable -= dwDmaLen;
pTxBuffer = (PUCHAR)(((PUINT) pTxBuffer) + dwDmaLen);
}
*pBuffLen = dwDmaLen;
EnableXmitInterrupt(TRUE);
}
else
{
DWORD dwWriteSize = GetWriteableSize();
RETAILMSG(0,(TEXT("[UART] XmitInterruptHandler! WriteableSize=%x to FIFO,dwDataAvaiable=%x\r\n"),
dwWriteSize,dwDataAvaiable));
for (DWORD dwByteWrite=0; dwByteWrite<dwWriteSize && dwDataAvaiable!=0;dwByteWrite++)
{
m_pReg6410Uart->Write_UTXH(*pTxBuffer);
pTxBuffer ++;
dwDataAvaiable--;
}
RETAILMSG(0,(TEXT("[UART] XmitInterruptHandler! Write %d byte to FIFO\r\n"),dwByteWrite));
*pBuffLen = dwByteWrite;
EnableXmitInterrupt(TRUE);
}
}
LEAVEWRITE:
ClearInterrupt(S6410UART_INT_TXD);
if (m_pReg6410Uart->Read_ULCON() & (1 << 6))
{
while((m_pReg6410Uart->Read_UFSTAT() & (0x3F << 8)) >> (8));
}
Rx_Pause(FALSE);
}
m_HardwareLock.Unlock();
}
#else//#ifdef USE_DMA
void CPdd6410Uart::XmitInterruptHandler(PUCHAR pTxBuffer, ULONG *pBuffLen)
{
PREFAST_DEBUGCHK(pBuffLen!=NULL);
m_HardwareLock.Lock();
if (*pBuffLen == 0)
{
EnableXmitInterrupt(FALSE);
}
else
{
DEBUGCHK(pTxBuffer);
PulseEvent(m_XmitFlushDone);
DWORD dwDataAvaiable = *pBuffLen;
*pBuffLen = 0;
Rx_Pause(TRUE);
if (!m_AutoFlowEnabled && ((m_DCB.fOutxCtsFlow && IsCTSOff()) ||(m_DCB.fOutxDsrFlow && IsDSROff())))
{ // We are in flow off
DEBUGMSG(ZONE_THREAD|ZONE_WRITE, (TEXT("CPdd6410Uart::XmitInterruptHandler! Flow Off, Data Discard.\r\n")));
EnableXmitInterrupt(FALSE);
}
else
{
DWORD dwWriteSize = GetWriteableSize();
DEBUGMSG(ZONE_THREAD|ZONE_WRITE,(TEXT("CPdd6410Uart::XmitInterruptHandler! WriteableSize=%x to FIFO,dwDataAvaiable=%x\r\n"),
dwWriteSize,dwDataAvaiable));
for (DWORD dwByteWrite=0; dwByteWrite<dwWriteSize && dwDataAvaiable!=0;dwByteWrite++)
{
m_pReg6410Uart->Write_UTXH(*pTxBuffer);
pTxBuffer ++;
dwDataAvaiable--;
}
DEBUGMSG(ZONE_THREAD|ZONE_WRITE,(TEXT("CPdd6410Uart::XmitInterruptHandler! Write %d byte to FIFO\r\n"),dwByteWrite));
*pBuffLen = dwByteWrite;
EnableXmitInterrupt(TRUE);
}
ClearInterrupt(S6410UART_INT_TXD);
if (m_pReg6410Uart->Read_ULCON() & UART_LCR_IR_MODE)
{
while((m_pReg6410Uart->Read_UFSTAT() & UART_FSR_TX_FIFO_COUNT_MASK) >> UART_FSR_TX_FIFO_COUNT_SHFIT);
}
Rx_Pause(FALSE);
}
m_HardwareLock.Unlock();
}
#endif //#ifdef USE_DMA
void CPdd6410Uart::XmitComChar(UCHAR ComChar)
{
// This function has to poll until the Data can be sent out.
BOOL bDone = FALSE;
do
{
m_HardwareLock.Lock();
if ( GetWriteableSize()!=0 )
{ // If not full
m_pReg6410Uart->Write_UTXH(ComChar);
bDone = TRUE;
}
else
{
EnableXmitInterrupt(TRUE);
}
m_HardwareLock.Unlock();
if (!bDone)
{
WaitForSingleObject(m_XmitFlushDone, (ULONG)1000);
}
}while (!bDone);
}
BOOL CPdd6410Uart::EnableXmitInterrupt(BOOL fEnable)
{
m_HardwareLock.Lock();
if (fEnable)
{
EnableInterrupt(S6410UART_INT_TXD);
}
else
{
DisableInterrupt(S6410UART_INT_TXD);
}
m_HardwareLock.Unlock();
return TRUE;
}
BOOL CPdd6410Uart::CancelXmit()
{
return InitXmit(TRUE);
}
static PAIRS s_HighWaterPairs[] =
{
{0, 1 },
{1, 8 },
{2, 16 },
{3, 32 }
};
BYTE CPdd6410Uart::GetWaterMarkBit()
{
BYTE bReturnKey = (BYTE)s_HighWaterPairs[0].Key;
for (DWORD dwIndex = dim(s_HighWaterPairs)-1 ; dwIndex != 0; dwIndex --)
{
if (m_dwWaterMark >= s_HighWaterPairs[dwIndex].AssociatedValue)
{
bReturnKey = (BYTE)s_HighWaterPairs[dwIndex].Key;
break;
}
}
return bReturnKey;
}
DWORD CPdd6410Uart::GetWaterMark()
{
BYTE bReturnValue = (BYTE)s_HighWaterPairs[0].AssociatedValue;
for (DWORD dwIndex = dim(s_HighWaterPairs)-1 ; dwIndex != 0; dwIndex --)
{
if (m_dwWaterMark >= s_HighWaterPairs[dwIndex].AssociatedValue)
{
bReturnValue = (BYTE)s_HighWaterPairs[dwIndex].AssociatedValue;
break;
}
}
return bReturnValue;
}
// Receive
BOOL CPdd6410Uart::InitReceive(BOOL bInit)
{
m_HardwareLock.Lock();
if (bInit)
{
BYTE uWarterMarkBit = GetWaterMarkBit();
if (uWarterMarkBit> 3)
{
uWarterMarkBit = 3;
}
// Setup Receive FIFO.
// Reset Receive Fifo.
DWORD dwBit = m_pReg6410Uart->Read_UFCON();
dwBit |= (UART_FCR_RX_FIFO_RESET);
dwBit &= ~(UART_FCR_FIFO_ENABLE);
m_pReg6410Uart->Write_UFCON( dwBit);
// Set Trigger level to WaterMark.
dwBit &= ~(UART_FCR_RX_FIFO_TRIG_MASK);
dwBit |= (uWarterMarkBit<<4);
m_pReg6410Uart->Write_UFCON(dwBit);
// Enable Receive FIFO.
dwBit &= ~(UART_FCR_RX_FIFO_RESET);
dwBit |= (UART_FCR_FIFO_ENABLE);
m_pReg6410Uart->Write_UFCON(dwBit); // Receive FIFO Reset Done..
m_pReg6410Uart->Read_UERSTAT(); // Clean Line Interrupt.
dwBit = m_pReg6410Uart->Read_UCON();
#if EPLL_CLK
// Set UART CLK.
dwBit &= ~(UART_CS_MASK);
dwBit |= (UART_CS_EPLLCLK);
#endif
if (m_ClockSelectValid) {
dwBit &= ~(UART_CS_MASK);
dwBit |= (m_ClockSelect);
}
// Set Rx Inerrupt Request Type, Rx Timeout, Rx Interrupt/Polling Mode.
dwBit &= ~(UART_RX_INT_TYPE_MASK|UART_RX_TIMEOUT_MASK|UART_RX_MODE_MASK);
dwBit |= (UART_RX_INT_TYPE_LEVEL|UART_RX_TIMEOUT_ENABLE|UART_RX_INT_POLL);
m_pReg6410Uart->Write_UCON(dwBit);
EnableInterrupt(S6410UART_INT_RXD | S6410UART_INT_ERR );
}
else
{
DisableInterrupt(S6410UART_INT_RXD | S6410UART_INT_ERR );
}
m_HardwareLock.Unlock();
return TRUE;
}
ULONG CPdd6410Uart::ReceiveInterruptHandler(PUCHAR pRxBuffer,ULONG *pBufflen)
{
DEBUGMSG(ZONE_THREAD|ZONE_READ,(TEXT("+CPdd6410Uart::ReceiveInterruptHandler pRxBuffer=%x,*pBufflen=%x\r\n"),
pRxBuffer,pBufflen!=NULL?*pBufflen:0));
DWORD dwBytesDropped = 0;
if (pRxBuffer && pBufflen )
{
DWORD dwBytesStored = 0 ;
DWORD dwRoomLeft = *pBufflen;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -