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

📄 pl011api.c

📁 ARM9基于WINDOWSCE的BSP源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
            ulDR = ReadReg32(pPL011->pDR);
        else
            ulDR = 0;
    }
    except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
            EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
    {
        // Do nothing
        return FALSE;
    }

    // The low byte is the received data
    //
    if (pbData != NULL)
        *pbData = (UCHAR)ulDR;

    // Bits 8 - 11 are the receive status bits (for the byte just read from the data register)
    //
    if (pfStatus != NULL)
        *pfStatus = ulDR >> 8;

    return TRUE;
}


BOOL PL011XmitComChar(PL011_CONTEXT *pPL011, UCHAR ComChar, HANDLE hevTxReady)
{
    BOOL fTransmitted = FALSE;
    BOOL fInCritSection = FALSE;

    if ((pPL011 == NULL) || (hevTxReady == NULL))
        return FALSE;

    EnterCriticalSection(&pPL011->csXmit);

    try
    {
        while (!fTransmitted)
        {
            EnterCriticalSection(&pPL011->csRegs);

            fInCritSection = TRUE;

            DEBUGCHK(((ReadReg32(pPL011->pIBRD) != 0) &&
                     ((ReadReg32(pPL011->pCR) & PL011_CR_TXE) != 0) &&
                     ((ReadReg32(pPL011->pCR) & PL011_CR_UARTEN) != 0)));

            // If possible, write the character to the UART for transmission immediately, else enable
            //  the transmit interrupt (so that we can wait for room to become available).
            //
            if ((ReadReg32(pPL011->pFR) & PL011_FR_TXFF) == 0)
            {
                WriteReg32(pPL011->pDR, ComChar);
                fTransmitted = TRUE;
            }
            else
                VERIFY(PL011EnableTxInterrupts(pPL011));

            LeaveCriticalSection(&pPL011->csRegs);

            fInCritSection = FALSE;

            // If we wrote the character, we're finished. Otherwise, we'll wait for room to become
            //  avaiable by waiting on the event handle passed to us; it will get set when a transmit
            //  interrupt occurs, at which time the FIFO should no longer be full.
            //
            if (!fTransmitted)
                WaitForSingleObject(hevTxReady, 1000);
        }
    }
    except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
            EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
    {
        if (TRUE == fInCritSection)
        {
            LeaveCriticalSection(&pPL011->csRegs);
        }
    }

    LeaveCriticalSection(&pPL011->csXmit);

    return fTransmitted;
}


BOOL PL011PurgeComm(PL011_CONTEXT *pPL011, ULONG fdwAction)
{
    BOOL fPurgeRx, fPurgeTx;

    if (pPL011 == NULL)
        return FALSE;

    if (fdwAction == 0)
        return TRUE;

    fPurgeRx = ((fdwAction & (PURGE_RXCLEAR | PURGE_RXABORT)) != 0);
    fPurgeTx = ((fdwAction & (PURGE_TXCLEAR | PURGE_TXABORT)) != 0);

    if (!fPurgeRx && !fPurgeTx)
        return TRUE;

    if (fPurgeTx)
        EnterCriticalSection(&pPL011->csXmit);

    if (fPurgeRx)
        EnterCriticalSection(&pPL011->csRegs);

    // We won't disable interrupts since it might confuse and/or upset the MDD; we'll just keep
    //  emptying the receiver, if specified, until the transmitter is also empty, if specified.

    try
    {
        while (TRUE)
        {
            if (fPurgeRx)
                while ((ReadReg32(pPL011->pFR) & PL011_FR_RXFE) == 0)
                    ReadReg32(pPL011->pDR);

            if (fPurgeTx)
                if (PL011IsBusy(pPL011))
                    continue;

            break;
        }
    }
    except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
            EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
    {
        // Just get out of here.
        if (fPurgeRx)
            LeaveCriticalSection(&pPL011->csRegs);
        if (fPurgeTx)
            LeaveCriticalSection(&pPL011->csXmit);
        return FALSE;
    }

    if (fPurgeRx)
        LeaveCriticalSection(&pPL011->csRegs);

    if (fPurgeTx)
        LeaveCriticalSection(&pPL011->csXmit);

    return TRUE;
}


BOOL PL011GetModemStatus(PL011_CONTEXT *pPL011, ULONG *pfModemStatus)
{
    BOOL fDataReady;

    return PL011GetStatus(pPL011, &fDataReady, pfModemStatus);
}


BOOL PL011SendBytes(PL011_CONTEXT *pPL011, UCHAR const *pbBuffer, ULONG *pcbBuffLen)
{
    ULONG nBytesToSend;
    ULONG cbTargetRoom;
    ULONG nBytesSent = 0;

    if ((pPL011 == NULL) || (pcbBuffLen == NULL))
        return FALSE;

    // When there is no more to send, just disable the TX interrupts and return to the MDD.
    //
    if ((*pcbBuffLen == 0) || (pbBuffer == NULL))
        goto exit_point;

    // Save [in] parameter (number of bytes to send) and initialise [out] parameter (number of
    //  bytes actually sent)
    //
    nBytesToSend = *pcbBuffLen;
    *pcbBuffLen = 0;

    DEBUGCHK(((ReadReg32(pPL011->pIBRD) != 0) &&
             ((ReadReg32(pPL011->pCR) & PL011_CR_TXE) != 0) &&
             ((ReadReg32(pPL011->pCR) & PL011_CR_UARTEN) != 0)));

    if ((ReadReg32(pPL011->pFR) & PL011_FR_TXFE) == 0)
        goto exit_point;

    // The TX interrupt flag must always be set; we unmask it to generate a physical interrupt and
    //  mask it to clear the physical interrupt.
    //
    DEBUGCHK((ReadReg32(pPL011->pRIS) & PL011_RIS_TXRIS) != 0);

    EnterCriticalSection(&pPL011->csXmit);

    try
    {
        if ((ReadReg32(pPL011->pLCR_H) & PL011_LCR_H_FEN) != 0)
            cbTargetRoom = PL011_FIFO_DEPTH;
        else
            cbTargetRoom = 1;

        if (nBytesToSend > cbTargetRoom)
            nBytesToSend = cbTargetRoom;

        while (nBytesToSend > 0)
        {
            WriteReg32(pPL011->pDR, *pbBuffer);

            nBytesSent++;
            pbBuffer++;
            nBytesToSend--;
        }
    }
    except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
            EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
    {
        // Just get out of here.
        LeaveCriticalSection(&pPL011->csXmit);
        return FALSE;
    }

    LeaveCriticalSection(&pPL011->csXmit);

    *pcbBuffLen = nBytesSent;

exit_point:

    return TRUE;
}


BOOL PL011PowerOff(PL011_CONTEXT *pPL011)
{
    if (pPL011 == NULL)
        return FALSE;

    // Save settings
    //
    pPL011->ILPR  = ReadReg32(pPL011->pILPR);
    pPL011->IBRD  = ReadReg32(pPL011->pIBRD);
    pPL011->FBRD  = ReadReg32(pPL011->pFBRD);
    pPL011->LCR_H = ReadReg32(pPL011->pLCR_H);
    pPL011->CR    = ReadReg32(pPL011->pCR);
    pPL011->IFLS  = ReadReg32(pPL011->pIFLS);
    pPL011->IMSC  = ReadReg32(pPL011->pIMSC);
    pPL011->DMACR = ReadReg32(pPL011->pDMACR);

    // Disable UART
    //
    WriteReg32(pPL011->pCR, ReadReg32(pPL011->pCR) & ~PL011_CR_UARTEN);

    return TRUE;
}


BOOL PL011PowerOn(PL011_CONTEXT *pPL011)
{
    if (pPL011 == NULL)
        return FALSE;

    // Restore settings
    //
    WriteReg32(pPL011->pILPR,  pPL011->ILPR);
    WriteReg32(pPL011->pIBRD,  pPL011->IBRD);
    WriteReg32(pPL011->pFBRD,  pPL011->FBRD);
    WriteReg32(pPL011->pLCR_H, pPL011->LCR_H);
    WriteReg32(pPL011->pCR,    pPL011->CR);
    WriteReg32(pPL011->pIFLS,  pPL011->IFLS);
    WriteReg32(pPL011->pIMSC,  pPL011->IMSC);
    WriteReg32(pPL011->pDMACR, pPL011->DMACR);

    return TRUE;
}

BOOL PL011DMACtrl(PL011_CONTEXT *pPL011, DWORD value)
{
    if (pPL011 == NULL)
        return FALSE;

    WriteReg32(pPL011->pDMACR, value & 0x7);

    return TRUE;
}



#ifdef DEBUG
BOOL PL011DumpRegisters(PL011_CONTEXT *pPL011)
{
    // We don't read the data register or the received status register because doing so would
    //  effect the UART's state.

    ULONG ulFR, ulILPR, ulIBRD, ulFBRD, ulLCR_H, ulCR, ulIFLS, ulIMSC, ulRIS, ulMIS, ulDMACR;

    const TCHAR szFmtFR[]    = TEXT("PL011:FR   : %#4.4x [RI:%u TXFE:%u RXFF:%u TXFF:%u RXFE:%u BUSY:%u DCD:%u DSR:%u CTS:%u]\r\n");
    const TCHAR szFmtILPR[]  = TEXT("PL011:ILPR : %#4.2x [%u]\r\n");
    const TCHAR szFmtIBRD[]  = TEXT("PL011:IBRD : %#4.4x [%u]\r\n");
    const TCHAR szFmtFBRD[]  = TEXT("PL011:FBRD : %#4.2x [%u]\r\n");
    const TCHAR szFmtLCR_H[] = TEXT("PL011:LCR_H: %#4.2x [SPS:%u WLEN:%u%u FEN:%u STP2:%u EPS:%u PEN:%u BRK:%u]\r\n");
    const TCHAR szFmtCR[]    = TEXT("PL011:CR   : %#4.4x [CTSEN:%u RTSEN:%u OUT2:%u OUT1:%u RTS:%u DTR:%u RXE:%u TXE:%u LBE:%u [6:3]:%u%u%u%u SIRLP:%u SIREN:%u UARTEN:%u]\r\n");
    const TCHAR szFmtIFLS[]  = TEXT("PL011:IFLS : %#4.2x [RXIFLSEL:%u%u%u TXIFLSEL:%u%u%u]\r\n");
    const TCHAR szFmtIMSC[]  = TEXT("PL011:IMSC : %#4.4x [OEIM :%u BEIM :%u PEIM :%u FEIM :%u RTIM :%u TXIM :%u RXIM :%u DSRMIM :%u DCDMIM :%u CTSMIM :%u RIMIM :%u]\r\n");
    const TCHAR szFmtRIS[]   = TEXT("PL011:RIS  : %#4.4x [OERIS:%u BERIS:%u PERIS:%u FERIS:%u RTRIS:%u TXRIS:%u RXRIS:%u DSRRMIS:%u DCDRMIS:%u CTSRMIS:%u RIRMIS:%u]\r\n");
    const TCHAR szFmtMIS[]   = TEXT("PL011:MIS  : %#4.4x [OEMIS:%u BEMIS:%u PEMIS:%u FEMIS:%u RTMIS:%u TXMIS:%u RXMIS:%u DSRMMIS:%u DCDMMIS:%u CTSMMIS:%u RIMMIS:%u]\r\n");
    const TCHAR szFmtDMACR[] = TEXT("PL011:DMACR: %#4.2x [DMAONERR:%u TXDMAE:%u RXDMAE:%u]\r\n");

    if (pPL011 == NULL)
        return FALSE;


    // Read all of the following PL011 UART registers in quick succession and with the UART write-
    //  protected; the dump will be as close to a snapshot of the UART registers as we can get.
    //
    EnterCriticalSection(&pPL011->csRegs);

    try
    {
        ulFR    = ReadReg32(pPL011->pFR);                       // Flag
        ulILPR  = ReadReg32(pPL011->pILPR);                     // IrDA low-power counter
        ulIBRD  = ReadReg32(pPL011->pIBRD);                     // Integer baud rate divisor register
        ulFBRD  = ReadReg32(pPL011->pFBRD);                     // Fractional baud rate divisor register
        ulLCR_H = ReadReg32(pPL011->pLCR_H);                    // Line control (high byte)
        ulCR    = ReadReg32(pPL011->pCR);                       // Control
        ulIFLS  = ReadReg32(pPL011->pIFLS);                     // Interrupt FIFO level select
        ulIMSC  = ReadReg32(pPL011->pIMSC);                     // Interrupt mask set/clear
        ulRIS   = ReadReg32(pPL011->pRIS);                      // Raw interrupt status
        ulMIS   = ReadReg32(pPL011->pMIS);                      // Masked interrupt status
        ulDMACR = ReadReg32(pPL011->pDMACR);                    // DMA control
    }
    except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
            EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
    {
        // Just get out of here.
        LeaveCriticalSection(&pPL011->csRegs);
        return FALSE;
    }

    LeaveCriticalSection(&pPL011->csRegs);


    // Blank line
    //
    NKDbgPrintfW(TEXT("\r\n"));


    // Flag
    //
    NKDbgPrintfW(szFmtFR, ulFR, (ulFR & PL011_FR_RI)   ? 1 : 0,
                                (ulFR & PL011_FR_TXFE) ? 1 : 0,
                                (ulFR & PL011_FR_RXFF) ? 1 : 0,
                                (ulFR & PL011_FR_TXFF) ? 1 : 0,
                                (ulFR & PL011_FR_RXFE) ? 1 : 0,
                                (ulFR & PL011_FR_BUSY) ? 1 : 0,
                                (ulFR & PL011_FR_DCD)  ? 1 : 0,
                                (ulFR & PL011_FR_DSR)  ? 1 : 0,
                                (ulFR & PL011_FR_CTS)  ? 1 : 0);

    // IrDA low-power counter
    //
    NKDbgPrintfW(szFmtILPR, ulILPR, ulILPR);

    // Integer baud rate divisor register
    //
    NKDbgPrintfW(szFmtIBRD, ulIBRD, ulIBRD);

    // Fractional baud rate divisor
    //
    NKDbgPrintfW(szFmtFBRD, ulFBRD, ulFBRD);

    // Line control (high byte)
    //
    NKDbgPrintfW(szFmtLCR_H, ulLCR_H, (ulLCR_H & PL011_LCR_H_SPS)  ? 1 : 0,
                                      (ulLCR_H & 0x20)             ? 1 : 0,
                                      (ulLCR_H & 0x40)             ? 1 : 0,
                                      (ulLCR_H & PL011_LCR_H_FEN)  ? 1 : 0,
                                      (ulLCR_H & PL011_LCR_H_STP2) ? 1 : 0,
                                      (ulLCR_H & PL011_LCR_H_EPS)  ? 1 : 0,
                                      (ulLCR_H & PL011_LCR_H_PEN)  ? 1 : 0,
                                      (ulLCR_H & PL011_LCR_H_BRK)  ? 1 : 0);

    // Control
    //
    NKDbgPrintfW(szFmtCR, ulCR, (ulCR & PL011_CR_CTSEN)  ? 1 : 0,
                                (ulCR & PL011_CR_RTSEN)  ? 1 : 0,
                                (ulCR & PL011_CR_OUT2)   ? 1 : 0,
                                (ulCR & PL011_CR_OUT1)   ? 1 : 0,
                                (ulCR & PL011_CR_RTS)    ? 1 : 0,
                                (ulCR & PL011_CR_DTR)    ? 1 : 0,
                                (ulCR & PL011_CR_RXE)    ? 1 : 0,
                                (ulCR & PL011_CR_TXE)    ? 1 : 0,
                                (ulCR & PL011_CR_LBE)    ? 1 : 0,
                                (ulCR & 0x08)            ? 1 : 0,
                                (ulCR & 0x10)            ? 1 : 0,
                                (ulCR & 0x20)            ? 1 : 0,
                                (ulCR & 0x40)            ? 1 : 0,
                                (ulCR & PL011_CR_SIRLP)  ? 1 : 0,
                                (ulCR & PL011_CR_SIREN)  ? 1 : 0,
                                (ulCR & PL011_CR_UARTEN) ? 1 : 0);

    // Interrupt FIFO level select
    //
    NKDbgPrintfW(szFmtIFLS, ulIFLS, (ulIFLS & 0x20)  ? 1 : 0,
                                    (ulIFLS & 0x10)  ? 1 : 0,
                                    (ulIFLS & 0x08)  ? 1 : 0,
                                    (ulIFLS & 0x04)  ? 1 : 0,
                                    (ulIFLS & 0x02)  ? 1 : 0,
                                    (ulIFLS & 0x01)  ? 1 : 0);

    // Interrupt mask set/clear
    //
    NKDbgPrintfW(szFmtIMSC, ulIMSC, (ulIMSC & PL011_IMSC_OEIM)   ? 1 : 0,
                                    (ulIMSC & PL011_IMSC_BEIM)   ? 1 : 0,
                                    (ulIMSC & PL011_IMSC_PEIM)   ? 1 : 0,
                                    (ulIMSC & PL011_IMSC_FEIM)   ? 1 : 0,
                                    (ulIMSC & PL011_IMSC_RTIM)   ? 1 : 0,
                                    (ulIMSC & PL011_IMSC_TXIM)   ? 1 : 0,
                                    (ulIMSC & PL011_IMSC_RXIM)   ? 1 : 0,
                                    (ulIMSC & PL011_IMSC_DSRMIM) ? 1 : 0,
                                    (ulIMSC & PL011_IMSC_DCDMIM) ? 1 : 0,
                                    (ulIMSC & PL011_IMSC_CTSMIM) ? 1 : 0,
                                    (ulIMSC & PL011_IMSC_RIMIM)  ? 1 : 0);

    // Raw interrupt status
    //
    NKDbgPrintfW(szFmtRIS, ulRIS, (ulRIS & PL011_RIS_OERIS)   ? 1 : 0,
                                  (ulRIS & PL011_RIS_BERIS)   ? 1 : 0,
                                  (ulRIS & PL011_RIS_PERIS)   ? 1 : 0,
                                  (ulRIS & PL011_RIS_FERIS)   ? 1 : 0,
                                  (ulRIS & PL011_RIS_RTRIS)   ? 1 : 0,
                                  (ulRIS & PL011_RIS_TXRIS)   ? 1 : 0,
                                  (ulRIS & PL011_RIS_RXRIS)   ? 1 : 0,
                                  (ulRIS & PL011_RIS_DSRRMIS) ? 1 : 0,
                                  (ulRIS & PL011_RIS_DCDRMIS) ? 1 : 0,
                                  (ulRIS & PL011_RIS_CTSRMIS) ? 1 : 0,
                                  (ulRIS & PL011_RIS_RIRMIS)  ? 1 : 0);

    // Masked interrupt status
    //
    NKDbgPrintfW(szFmtMIS, ulMIS, (ulMIS & PL011_MIS_OEMIS)   ? 1 : 0,
                                  (ulMIS & PL011_MIS_BEMIS)   ? 1 : 0,
                                  (ulMIS & PL011_MIS_PEMIS)   ? 1 : 0,
                                  (ulMIS & PL011_MIS_FEMIS)   ? 1 : 0,
                                  (ulMIS & PL011_MIS_RTMIS)   ? 1 : 0,
                                  (ulMIS & PL011_MIS_TXMIS)   ? 1 : 0,
                                  (ulMIS & PL011_MIS_RXMIS)   ? 1 : 0,
                                  (ulMIS & PL011_MIS_DSRMMIS) ? 1 : 0,
                                  (ulMIS & PL011_MIS_DCDMMIS) ? 1 : 0,
                                  (ulMIS & PL011_MIS_CTSMMIS) ? 1 : 0,
                                  (ulMIS & PL011_MIS_RIMMIS)  ? 1 : 0);

    // DMA control
    //
    NKDbgPrintfW(szFmtDMACR, ulDMACR, (ulDMACR & PL011_DMACR_DMAONERR)  ? 1 : 0,
                                      (ulDMACR & PL011_DMACR_TXDMAE)    ? 1 : 0,
                                      (ulDMACR & PL011_DMACR_RXDMAE)    ? 1 : 0);

    // Blank line
    //
    NKDbgPrintfW(TEXT("\r\n"));


    return TRUE;
}
#endif // DEBUG

⌨️ 快捷键说明

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