⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uartser.c

📁 WinCE 3.0 BSP, 包含Inter SA1110, Intel_815E, Advantech_PCM9574 等
💻 C
📖 第 1 页 / 共 4 页
字号:
        // It will be clean when the data read out of FIFO.
        ) {
        interrupts = INTR_LINE;
    } else 
        // rid can not be used for detecting data in the FIFO. It may cause by hardware bug.
        // What I found even there is a character in the FIFO during xmit. The rid is not signaled.
        // It cause some problem at Xon/Xoff handshake protocol. 
        // So, I recommend do not use following condition to dectec data in receiving FIFO.
        //if ((pHWHead->pUART->utsr0.rfs) || (pHWHead->pUART->utsr0.rid)) {

        if (pHWHead->pUART->utsr1.rne) {
            interrupts = INTR_RX;
        //}
    } else if (pHWHead->pUART->utsr0.tfs){
        if (pHWHead->pUART->utcr3.tie) {
          interrupts = INTR_TX;
        }
    }
    else {//if ((pHWHead->UTSR0 & SERIAL_IIR_MS)) {
//RETAILMSG(1,(TEXT("HW_SA1100GetInterruptType Detected INTR_MODEM\r\n")));
        // We do not support Modem Interrupt, Because they will triger anoter shared interrupt
        // we may fix this later one.
        //interrupts = INTR_MODEM;
        HW_SA1100OtherIntr(pHead);                // Hardware Head
    }
    if (pHWHead->AddTXIntr) { 
        interrupts |= INTR_TX;
        pHWHead->AddTXIntr = FALSE;
    }
    if (interrupts==INTR_NONE) {
//RETAILMSG(1,(TEXT("HW_SA1100GetInterruptType Detected INTR_NONE\r\n")));
    }
    DEBUGMSG (ZONE_THREAD,(TEXT("-HW_SA1100GetInterruptType 0x%X, 0x%X\r\n"),pHead,interrupts));
//SA_DumpSerialRegisters(pHWHead);
    return interrupts;
}

// @doc OEM
// @func ULONG | HW_SA1100RxIntr | This routine gets several characters from the hardware
//   receive buffer and puts them in a buffer provided via the second argument.
//   It returns the number of bytes lost to overrun.
// 
// @rdesc The return value indicates the number of overruns detected.
//   The actual number of dropped characters may be higher.
//
ULONG
HW_SA1100RxIntr(
    PVOID pHead,                // @parm Pointer to hardware head
    PUCHAR pRxBuffer,           // @parm Pointer to receive buffer
    ULONG *pBufflen             // @parm In = max bytes to read, out = bytes read
    )
{
    PSER_HW_INFO   pHWHead  = (PSER_HW_INFO)pHead;
    ULONG       TargetRoom  = *pBufflen;
    BOOL        fRXFlag = FALSE;
    BOOL        fReplaceparityErrors = FALSE;
    BOOL        fNull;
    UCHAR       cEvtChar, cRXChar;
    ULONG       RetVal;
    
//RETAILMSG(1,(TEXT("+GetBytes/HW_SA1100RxIntr - len %d.\r\n"),*pBufflen));
    DEBUGMSG (0,(TEXT("+GetBytes - len %d.\r\n"),*pBufflen));
    *pBufflen = 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
            SA_ReadSR1(pHWHead);
            if(pHWHead->pUART->utsr1.rne) {
                     // Read the byte
                  // cRXChar = (UCHAR)(pHWHead->pUART->utdr.data);
    IOW_REG_GET(struct utdrBits, &pHWHead->pUART->utdr, data, cRXChar);

//RETAILMSG(1,(TEXT("%c"),cRXChar));
//if (cRXChar == '\r')
//RETAILMSG(1,(TEXT("\n")));
                IOW_REG_BITSET (struct  utsr0Bits, &pHWHead->pUART->utsr0, rid, 1); // Clear interrupt
                 // But we may want to discard it
                if( !IsModemDsrOn(pHWHead)) {
                     // Do nothing - byte gets discarded
                    DEBUGMSG (ZONE_FLOW,
                              (TEXT("Dropping byte because DSR is low\r\n")));
                }
                else 
                if (!cRXChar && fNull) {
                         // Do nothing - byte gets discarded
                    DEBUGMSG (ZONE_FLOW| ZONE_WARN,
                              (TEXT("Dropping NULL byte due to fNull\r\n")));
                }
                else {
                        // Do character replacement if parity error detected.
                    if( fReplaceparityErrors && (pHWHead->pUART->utsr1.pre) ) {
                        cRXChar = pHWHead->dcb.ErrorChar;
                    }
                    else {    
                            // See if we need to generate an EV_RXFLAG for the received char.
                        if( cRXChar == cEvtChar )
                            fRXFlag = TRUE;
                    }
                    // Finally, we can get byte, update status and save.
                    *pRxBuffer++ = cRXChar;
                    (*pBufflen)++;
                    --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->pMddHead, EV_RXFLAG );
    if( pHWHead->DroppedBytes )
        DEBUGMSG (ZONE_WARN, (TEXT("Rx drop %d.\r\n"),pHWHead->DroppedBytes));
    DEBUGMSG (0,(TEXT("-GetBytes - rx'ed %d, dropped %d.\r\n"),*pBufflen,pHWHead->DroppedBytes));

    RetVal = pHWHead->DroppedBytes;
    pHWHead->DroppedBytes = 0;
//SA_DumpSerialRegisters(pHWHead);
    return RetVal;
}

// @doc OEM
// @func ULONG | HW_SA1100PutBytes | This routine is called from the MDD
//   in order to write a stream of data to the device.
// 
// @rdesc Always returns 0
//
ULONG
HW_SA1100PutBytes(
    PVOID   pHead,      // @parm    PVOID returned by HWInit.
    PUCHAR  pSrc,       // @parm    Pointer to bytes to be sent.
    ULONG   NumberOfBytes,  // @parm    Number of bytes to be sent.
    PULONG  pBytesSent      // @parm    Pointer to actual number of bytes put.
    )
{
    PSER_HW_INFO   pHWHead  = (PSER_HW_INFO)pHead;
    UCHAR       byteCount;
    unsigned    i;
    
//RETAILMSG(1, (TEXT("+PutBytes - Len %d.\r\n"),
//                           NumberOfBytes));
    DEBUGMSG (ZONE_WRITE, (TEXT("+PutBytes - Len %d.\r\n"),NumberOfBytes));
    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 (!IsModemCtsOn(pHWHead)) {
		DEBUGMSG (ZONE_WRITE|ZONE_FLOW,
			(TEXT("PutBytes, flowed off via CTS\n") ) );
		pHWHead->CTSFlowOff = TRUE;  // Record flowed off state
		//            byte = INB(pHWHead, pIER);
		//            OUTB(pHWHead, pIER, byte & ~SERIAL_IER_THR); // disable TX interrupts while flowed off
		IOW_REG_FIELD (struct  utcr3Bits, &pHWHead->pUART->utcr3, tie, 0);
		
		// 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.
		return 0;
    }

    // Same thing applies for DSR
	if (!IsModemDsrOn(pHWHead)) {
		DEBUGMSG (ZONE_WRITE|ZONE_FLOW,
			(TEXT("PutBytes, flowed off via DSR\n") ) );
		pHWHead->DSRFlowOff = TRUE;  // Record flowed off state
		//OUTB(pHWHead, pIER, IER_NORMAL_INTS); // disable TX interrupts while flowed off
		IOW_REG_FIELD (struct  utcr3Bits, &pHWHead->pUART->utcr3, tie, 0);
		
		// See the comment above above positive return codes.
		return 0;
    }

    DEBUGMSG (ZONE_WRITE, (TEXT("PutBytes wait for CritSec %x.\r\n"),
                           &(pHWHead->TransmitCritSec)));
    EnterCriticalSection(&(pHWHead->TransmitCritSec));
    DEBUGMSG (ZONE_WRITE, (TEXT("PutBytes got CritSec %x.\r\n"),
                           &(pHWHead->TransmitCritSec)));
    
    SA_ReadSR1(pHWHead);
    if(pHWHead->pUART->utsr1.tnf) {
        byteCount = 
#ifdef SA1100_USE_TX_FIFO
        (pHWHead->IIR && SERIAL_IIR_FIFOS_ENABLED) ? SERIAL_FIFO_DEPTH : 1;
#else
        1;
#endif
        DEBUGMSG (ZONE_WRITE | ZONE_THREAD,(TEXT("Put Bytes - Write max of %d bytes\r\n"),byteCount));
        try {
// --Can not do that It will cause data lose if NumberOfBytes is bigger enough
//          while(NumberOfBytes) { 
                DEBUGLED( ZONE_WRITE, (1, 0x10200000 | *pSrc) );
                for (i=byteCount;i>0;i--) {
//RETAILMSG(1,(TEXT("%c"),*pSrc));
                //pHWHead->pUART->utdr.data=*pSrc++;
                IOW_REG_FIELD (struct  utdrBits, &pHWHead->pUART->utdr, data, *pSrc++);

                }
                (*pBytesSent)+=byteCount;
                NumberOfBytes-=byteCount;
//          }
        }
        except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
                EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
            // Just ignore it, we'll eventually fall out of here
        }
    }
//RETAILMSG(1,(TEXT("\r\n")));
    // Enable xmit intr. We need to do this no matter what, 
    // since the MDD relies on one final interrupt before
    // returning to the application. 
    try {
        IOW_REG_FIELD (struct  utcr3Bits, &pHWHead->pUART->utcr3, tie, 1);
    }
    except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
            EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
    }
            
    LeaveCriticalSection(&(pHWHead->TransmitCritSec));
    DEBUGMSG (ZONE_WRITE, (TEXT("PutBytes released CritSec %x.\r\n"),
                           &(pHWHead->TransmitCritSec)));

    DEBUGMSG (ZONE_WRITE, (TEXT("-PutBytes - sent %d.\r\n"),*pBytesSent));
//SA_DumpSerialRegisters(pHWHead);
    return 0;
}

//
// @doc OEM
// @func ULONG | HW_SA1100TXIntr | This routine is called from the MDD
//   whenever INTR_TX is returned by HW_SA1100GetInterruptType
// 
// @rdesc None
//
VOID
HW_SA1100TxIntr(
    PVOID pHead                // Hardware Head
    )
{
    PSER_HW_INFO   pHWHead  = (PSER_HW_INFO)pHead;

//RETAILMSG(1,(TEXT("+HW_SA1100TxIntr 0x%X\r\n"), pHead));
    DEBUGMSG (0,(TEXT("+HW_SA1100TxIntr 0x%X\r\n"), pHead));
         // 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.
    try {
        IOW_REG_FIELD (struct  utcr3Bits, &pHWHead->pUART->utcr3, tie, 0);
    }
    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.
    }

    // Let the putbytes routine know he can continue
//RETAILMSG(1,(TEXT("+HW_SA1100TxIntr Pulsing FlushDone\r\n")));
    PulseEvent(pHWHead->FlushDone);
    DEBUGMSG (0,(TEXT("+HW_SA1100TxIntr 0x%X\r\n"), pHead));
//SA_DumpSerialRegisters(pHWHead);
}

//
// @doc OEM
// @func ULONG | HW_SA1100LineIntr | This routine is called from the MDD
//   whenever INTR_LINE is returned by HW_SA1100GetInterruptType.
// 
// @rdesc None
//
VOID
HW_SA1100LineIntr(
    PVOID pHead                // Hardware Head
    )
{
    PSER_HW_INFO   pHWHead  = (PSER_HW_INFO)pHead;
//RETAILMSG(1,(TEXT("+HW_SA1100LineIntr 0x%X\r\n"), pHead));
    DEBUGMSG (0,(TEXT("+HW_SA1100LineIntr 0x%X\r\n"), pHead));
    SA_ReadSR1(pHWHead);

    // We have to clean the Line Interrupt status register.
    // Otherwise, It will stay there forever.
    if (pHWHead->pUART->utsr0.rbb)
        IOW_REG_FIELD (struct utsr0Bits, &pHWHead->pUART->utsr0, rbb, 1);
    if (pHWHead->pUART->utsr0.reb)
        IOW_REG_FIELD (struct utsr0Bits, &pHWHead->pUART->utsr0, reb, 1);

    DEBUGMSG (0,(TEXT("-HW_SA1100LineIntr 0x%X\r\n"), pHead));
}


//  
// @doc OEM
// @func    ULONG | HW_SA1100GetStatus | This structure is called by the MDD
//   to retrieve the contents of a COMSTAT structure.
//
// @rdesc   The return is a ULONG, representing success (0) or failure (-1).
//
ULONG
HW_SA1100GetStatus(
    PVOID   pHead,  // @parm PVOID returned by HWInit.
    LPCOMSTAT   lpStat  // Pointer to LPCOMMSTAT to hold status.
    )
{
    PSER_HW_INFO pHWHead = (PSER_HW_INFO)pHead;
    ULONG RetVal = pHWHead->CommErrors;
    
//RETAILMSG(1,(TEXT("+HW_SA1100GetStatus 0x%X\r\n"), pHead));
          DEBUGMSG (ZONE_FUNCTION,(TEXT("+HW_SA1100GetStatus 0x%X\r\n"),pHead));

    pHWHead->CommErrors = 0; // Clear old errors each time
    if (lpStat) {
        try {
            if (pHWHead->CTSFlowOff)
                pHWHead->Status.fCtsHold = 1;
            else
                pHWHead->Status.fCtsHold = 0;
                    
            if (pHWHead->DSRFlowOff)
                pHWHead->Status.fDsrHold = 1;
            else
                pHWHead->Status.fDsrHold = 0;

             // NOTE - I think what they really want to know here is
             // the amount of data in the MDD buffer, not the amount

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -