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

📄 pl011api.c

📁 ARM9基于WINDOWSCE的BSP源代码
💻 C
📖 第 1 页 / 共 3 页
字号:

    return TRUE;
}


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

    EnterCriticalSection(&pPL011->csRegs);

    try
    {
        WriteReg32(pPL011->pIMSC, ReadReg32(pPL011->pIMSC) | PL011_IMSC_TXIM);

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

    LeaveCriticalSection(&pPL011->csRegs);

    return TRUE;
}


BOOL PL011GetInterrupts(PL011_CONTEXT *pPL011, ULONG *pfInterrupts)
{
    ULONG ulMIS;

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

    // Initialise out parameter early
    //
    *pfInterrupts = 0;

    // Read the masked interrupt status register, save it, then clear those interrupts. We must
    //  only clear those interrupts that were flagged at the time of the read; if we were to clear
    //  all interrupts, we would lose those any that became flagged after the read.
    //

    try
    {
        ulMIS = ReadReg32(pPL011->pMIS);
        WriteReg32(pPL011->pICR, ulMIS & ~PL011_ICR_TXIC);
        WriteReg32(pPL011->pECR, 0x1); // Clear errors separately - value does not matter

    }
    except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
            EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
    {
        // Just get out of here.
        return FALSE;
    }

    // Copy the interrupt flags to the out parameter
    //
    *pfInterrupts = ulMIS;

    return TRUE;
}


BOOL PL011EnableFIFO(PL011_CONTEXT *pPL011, ULONG RxLevel, ULONG TxLevel)
{
    ULONG ulIFLS = 0;

    if (pPL011 == NULL)
        return FALSE;

    switch (RxLevel)
    {
    case PL011_FLSEL_1_8:
        ulIFLS |= PL011_IFLS_RXIFLSEL_1_8;
        break;

    case PL011_FLSEL_1_4:
        ulIFLS |= PL011_IFLS_RXIFLSEL_1_4;
        break;

    case PL011_FLSEL_1_2:
        ulIFLS |= PL011_IFLS_RXIFLSEL_1_2;
        break;

    case PL011_FLSEL_3_4:
        ulIFLS |= PL011_IFLS_RXIFLSEL_3_4;
        break;

    case PL011_FLSEL_7_8:
        ulIFLS |= PL011_IFLS_RXIFLSEL_7_8;
        break;

    default:
        return FALSE;
    }

    switch (TxLevel)
    {
    case PL011_FLSEL_1_8:
        ulIFLS |= PL011_IFLS_TXIFLSEL_1_8;
        break;

    case PL011_FLSEL_1_4:
        ulIFLS |= PL011_IFLS_TXIFLSEL_1_4;
        break;

    case PL011_FLSEL_1_2:
        ulIFLS |= PL011_IFLS_TXIFLSEL_1_2;
        break;

    case PL011_FLSEL_3_4:
        ulIFLS |= PL011_IFLS_TXIFLSEL_3_4;
        break;

    case PL011_FLSEL_7_8:
        ulIFLS |= PL011_IFLS_TXIFLSEL_7_8;
        break;

    default:
        return FALSE;
    }

    EnterCriticalSection(&pPL011->csRegs);

    try
    {
        WriteReg32(pPL011->pCR, ReadReg32(pPL011->pCR) & ~PL011_CR_UARTEN);
        WriteReg32(pPL011->pIFLS, ulIFLS);
        WriteReg32(pPL011->pLCR_H, ReadReg32(pPL011->pLCR_H) | PL011_LCR_H_FEN);
        WriteReg32(pPL011->pCR, ReadReg32(pPL011->pCR) | PL011_CR_UARTEN);  
    }
    except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
            EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
    {
        // Just get out of here.
        LeaveCriticalSection(&pPL011->csRegs);
        return FALSE;
    }

    LeaveCriticalSection(&pPL011->csRegs);

    return TRUE;
}


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

    EnterCriticalSection(&pPL011->csRegs);

    try
    {
        WriteReg32(pPL011->pLCR_H, ReadReg32(pPL011->pLCR_H) & ~PL011_LCR_H_FEN);
    }
    except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
            EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
    {
        // Just get out of here.
        LeaveCriticalSection(&pPL011->csRegs);
        return FALSE;
    }

    LeaveCriticalSection(&pPL011->csRegs);

    return TRUE;
}



BOOL PL011SetOutputMode(PL011_CONTEXT *pPL011, BOOL fUseIR, BOOL fUseCable)
{
    ULONG ulCR;

    if (pPL011 == NULL)
        return FALSE;

    // Either fUseIR or fUseCable can be TRUE, but not both
    //
    DEBUGCHK(!(fUseIR && fUseCable));

    EnterCriticalSection(&pPL011->csRegs);
    EnterCriticalSection(&pPL011->csFlow);

    try
    {
        ulCR = ReadReg32(pPL011->pCR) & ~(PL011_CR_UARTEN | PL011_CR_SIREN);
        WriteReg32(pPL011->pCR, ulCR);

        if (fUseCable)
        {
            ulCR |= (PL011_CR_RXE | PL011_CR_TXE | PL011_CR_UARTEN);
        }
        else if (fUseIR)
        {   
            ulCR |= (PL011_CR_RXE | PL011_CR_TXE | PL011_CR_UARTEN | PL011_CR_SIREN);
        }

        WriteReg32(pPL011->pCR, ulCR);
    }
    except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
            EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
    {
        // Just get out of here.
        LeaveCriticalSection(&pPL011->csFlow);
        LeaveCriticalSection(&pPL011->csRegs);
        return FALSE;
    }

    LeaveCriticalSection(&pPL011->csFlow);
    LeaveCriticalSection(&pPL011->csRegs);

    return TRUE;
}


BOOL PL011SetBaudRate(PL011_CONTEXT *pPL011, ULONG BaudRate)
{
    ULONG ulIBRD = 0, ulFBRD = 0;

    // Baud rate of zero would cause divide-by-zero exception
    //
    if ((pPL011 == NULL) || (BaudRate == 0))
        return FALSE;

    // Calculate integer and fractional parts of baud rate divisor for the required baud rate

    // Integer part of baud rate divisor must be within limits
    //
    ulIBRD = PL011_BAUD_DIVINT(BaudRate);
    if ((ulIBRD < PL011_IBRD_MIN) || (ulIBRD > PL011_IBRD_MAX))
        return FALSE;

    // Fractional part of baud rate divisor must be zero, if integer part is at maximum
    //
    ulFBRD = PL011_BAUD_DIVFRAC(BaudRate);
    if ((ulIBRD == PL011_IBRD_MAX) && (ulFBRD != 0))
        return FALSE;

    // The new settings for IBRD, FBRD are written to the internal, 29 bit, LCR register by a write
    //  to the LCR_H register. Since we don't want to modify the LCR_H register, we just read it
    //  then write it back out, unchanged.
    //
    EnterCriticalSection(&pPL011->csRegs);

    try
    {
        WriteReg32(pPL011->pCR, ReadReg32(pPL011->pCR) & ~PL011_CR_UARTEN);
        WriteReg32(pPL011->pIBRD,  ulIBRD);
        WriteReg32(pPL011->pFBRD,  ulFBRD);
        WriteReg32(pPL011->pLCR_H, ReadReg32(pPL011->pLCR_H));
        WriteReg32(pPL011->pCR, ReadReg32(pPL011->pCR) | PL011_CR_UARTEN);

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

    LeaveCriticalSection(&pPL011->csRegs);

    return TRUE;
}


BOOL PL011SetLineFormat(PL011_CONTEXT *pPL011,
                        ULONG BaudRate,
                        ULONG WordLength,
                        ULONG Parity,
                        ULONG StopBits)
{
    ULONG ulIBRD = 0, ulFBRD = 0, ulLCR_H = 0;

    // Baud rate of zero would cause divide-by-zero exception
    //
    if ((pPL011 == NULL) || (BaudRate == 0))
        return FALSE;

    // Calculate integer and fractional parts of baud rate divisor for the required baud rate

    // Integer part of baud rate divisor must be within limits
    //
    ulIBRD = PL011_BAUD_DIVINT(BaudRate);
    if ((ulIBRD < PL011_IBRD_MIN) || (ulIBRD > PL011_IBRD_MAX))
        return FALSE;

    // Fractional part of baud rate divisor must be zero, if integer part is at maximum
    //
    ulFBRD = PL011_BAUD_DIVFRAC(BaudRate);
    if ((ulIBRD == PL011_IBRD_MAX) && (ulFBRD != 0))
        return FALSE;

    // Prepare the new LCR_H register setting for the required data format

    // Prepare LCR_H bits for required word length (data length)
    //
    switch (WordLength)
    {
    case 5:
        ulLCR_H |= (PL011_LCR_H_WLEN_5);
        break;

    case 6:
        ulLCR_H |= (PL011_LCR_H_WLEN_6);
        break;

    case 7:
        ulLCR_H |= (PL011_LCR_H_WLEN_7);
        break;

    case 8:
        ulLCR_H |= (PL011_LCR_H_WLEN_8);
        break;

    default:
        return FALSE;
    }

    // Prepare LCR_H bits for required parity setting
    //
    switch (Parity)
    {
    case NOPARITY:
        break;

    case ODDPARITY:
        ulLCR_H |= (PL011_LCR_H_PEN);
        break;

    case EVENPARITY:
        ulLCR_H |= (PL011_LCR_H_PEN | PL011_LCR_H_EPS);
        break;

    case MARKPARITY:
        ulLCR_H |= (PL011_LCR_H_PEN | PL011_LCR_H_SPS);
    break;

    case SPACEPARITY:
        ulLCR_H |= (PL011_LCR_H_PEN | PL011_LCR_H_SPS | PL011_LCR_H_EPS);
        break;

    default:
        return FALSE;
    }

    // Prepare LCR_H bits for required stop bits setting
    //
    switch (StopBits)
    {
    case ONESTOPBIT:
        break;

    case ONE5STOPBITS:
        // ONE5STOPBITS is not supported so we'll fall through to TWOSTOPBITS
        DEBUGCHK(FALSE);

    case TWOSTOPBITS:
        ulLCR_H |= (PL011_LCR_H_STP2);
        break;

    default:
        return FALSE;
    }

    // Write the integer and fractional baud rate divisor settings, followed by the line control
    //  (high-byte) setting. The new settings for IBRD, FBRD and LCR_H are written to the internal,
    //  29 bit, LCR register by the write to the LCR_H register.
    //
    EnterCriticalSection(&pPL011->csRegs);

    try
    {
    // OR the existing LCR_H bits that we don't want to alter, into the new LCR_H register value
    //
        WriteReg32(pPL011->pCR, ReadReg32(pPL011->pCR) & ~PL011_CR_UARTEN);

        ulLCR_H |= (ReadReg32(pPL011->pLCR_H) & (PL011_LCR_H_FEN | PL011_LCR_H_BRK));

        WriteReg32(pPL011->pIBRD,  ulIBRD);
        WriteReg32(pPL011->pFBRD,  ulFBRD);
        WriteReg32(pPL011->pLCR_H, ulLCR_H);
        WriteReg32(pPL011->pCR, ReadReg32(pPL011->pCR) | PL011_CR_UARTEN);


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

    LeaveCriticalSection(&pPL011->csRegs);

    return TRUE;
}


BOOL PL011GetStatus(PL011_CONTEXT *pPL011, BOOL *pfDataReady, ULONG *pfModemStatus)
{
    ULONG ulFR;

    if ((pPL011 == NULL) || (pfDataReady == NULL) || (pfModemStatus == NULL))
        return FALSE;

    // Initialise out parameters early
    //
    *pfDataReady = FALSE;
    *pfModemStatus = 0;

    // Read the flag register, then set any appropriate flags in the out parameters
    //
    ulFR = ReadReg32(pPL011->pFR);
    if (ulFR == 0)
        goto exit_point;

    // If the receive FIFO is not empty, then there must be data ready to read
    //
    *pfDataReady = ((ulFR & PL011_FR_RXFE) == 0);

    // Now set the appropriate modem status flags
    //
    if ((ulFR & PL011_FR_RI) != 0)
        *pfModemStatus |= MS_RING_ON;

    if ((ulFR & PL011_FR_DCD) != 0)
        *pfModemStatus |= MS_RLSD_ON;

    if ((ulFR & PL011_FR_DSR) != 0)
        *pfModemStatus |= MS_DSR_ON;

    if ((ulFR & PL011_FR_CTS) != 0)
        *pfModemStatus |= MS_CTS_ON;

exit_point:

    return TRUE;
}


BOOL PL011ReadReceivedData(PL011_CONTEXT *pPL011, BOOL *pfReady, UCHAR *pbData, ULONG *pfStatus)
{
    ULONG ulDR;

    if ((pPL011 == NULL) || (pfReady == NULL))
        return FALSE;
    try
    {
        *pfReady = ((ReadReg32(pPL011->pFR) & PL011_FR_RXFE) == 0);
        if (*pfReady)

⌨️ 快捷键说明

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