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

📄 pdd.c

📁 Exar 公司 M1170 芯片 (i2c 转 串口)的 驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
//  Function:  HWRxIntr
//
//  This function 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.
//
static ULONG HWRxIntrHandler(VOID *pvContext, UCHAR *pRxBuffer, ULONG *pLength)
{
    UARTPDD *pPdd = (UARTPDD *)pvContext;
    ULONG ulCount = *pLength;
    UCHAR ucLineStat, ucRxChar;
    BOOL bRxFlag, bReplaceParityError;

    DEBUGMSG(ZONE_THREAD, (L"+HWRxIntrHandler(0x%08x, 0x%08x, %d)\r\n", pvContext, pRxBuffer,*pLength));

    *pLength = 0;
    bRxFlag = FALSE;
    bReplaceParityError = (pPdd->dcb.fErrorChar != '\0') && pPdd->dcb.fParity;

    EnterCriticalSection(&pPdd->hwCS);

    while (ulCount > 0) {

        // Get line status register
        ucLineStat = ReadLineStat(pPdd);

        // If there isn't more chars exit loop
        if ((ucLineStat & UART_LSR_RX_FIFO_E) == 0) break;

        // Get received char from RHR, need LCR[7] == 0
        ucRxChar = RegRead(pPdd, XR20M1170REG_RHR);

        // Ignore char in DSR is low and we care about it
        if (
            pPdd->dcb.fDsrSensitivity &&
            (ReadModemStat(pPdd) & UART_MSR_NDSR) == 0
        ) continue;

        // Ignore NUL char if requested
        if (ucRxChar == '\0' && pPdd->dcb.fNull) continue;

        // Replace char with parity error
        if (bReplaceParityError && (ucLineStat & UART_LSR_RX_PE) != 0) {
            ucRxChar = pPdd->dcb.ErrorChar;
        }

        // See if we need to generate an EV_RXFLAG
        if (ucRxChar == pPdd->dcb.EvtChar) bRxFlag = TRUE;

        // Store it to buffer
        *pRxBuffer++ = ucRxChar;
        (*pLength)++;
        ulCount--;
    }
    LeaveCriticalSection(&pPdd->hwCS);

    // Send event to MDD
    if (bRxFlag) EvaluateEventFlag(pPdd->pMdd, EV_RXFLAG);

    // Clear overrun counter and use this value as return code
    ulCount = pPdd->overrunCount;
    pPdd->overrunCount = 0;

//cleanUp:
    DEBUGMSG(ZONE_THREAD, (L"-HWRxIntrHandler(count = %d, length = %d)\r\n", ulCount, *pLength));
    return ulCount;
}


//------------------------------------------------------------------------------
//
//  Function:  HWTxIntr
//
//  This function is called from the MDD whenever INTR_TX is returned
//  by HWGetInterruptType which indicate empty place in transmitter FIFO.
//
static VOID HWTxIntrHandler(VOID *pvContext, UCHAR *pTxBuffer, ULONG *pLength)
{
    UARTPDD *pPdd = (UARTPDD *)pvContext;
    ULONG ulCount;
    UCHAR ucModemStat;
    UCHAR txlvl_reg;

    DEBUGMSG(ZONE_THREAD, (L"+HWTxIntr(0x%08x, 0x%08x, %d)\r\n", pvContext, pTxBuffer,*pLength));

    EnterCriticalSection(&pPdd->hwCS);

    // There can be nothing to send - then disable TX interrupt
    if (*pLength == 0) {
        pPdd->intrMask &= ~UART_IER_THR;
        RegWrite(pPdd, XR20M1170REG_IER, pPdd->intrMask);
        LeaveCriticalSection(&pPdd->hwCS);
        goto cleanUp;
    }

    // Set event to fire HWXmitComChar
    PulseEvent(pPdd->txEvent);

    // If CTS flow control is desired, check it. If deasserted, don't send,
    // but loop.  When CTS is asserted again, 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 (pPdd->dcb.fOutxCtsFlow) {
        ucModemStat = ReadModemStat(pPdd);
        if ((ucModemStat & UART_MSR_NCTS) == 0) {
            // Set flag
            pPdd->flowOffCTS = TRUE;
            // Disable TX interrupt
            pPdd->intrMask &= ~UART_IER_THR;
            RegWrite(pPdd, XR20M1170REG_IER, pPdd->intrMask);
            LeaveCriticalSection(&pPdd->hwCS);
            *pLength = 0;
            goto cleanUp;
        }
    }

    // Same thing applies for DSR
    if (pPdd->dcb.fOutxDsrFlow) {
        ucModemStat = ReadModemStat(pPdd);
        if ((ucModemStat & UART_MSR_NDSR) == 0) {
            // Set flag
            pPdd->flowOffDSR = TRUE;
            // Disable TX interrupt
            pPdd->intrMask &= ~UART_IER_THR;
            RegWrite(pPdd, XR20M1170REG_IER, pPdd->intrMask);
            LeaveCriticalSection(&pPdd->hwCS);
            *pLength = 0;
            goto cleanUp;
        }
    }

    LeaveCriticalSection(&pPdd->hwCS);

    // Give chance to HWXmitComChar there

    EnterCriticalSection(&pPdd->hwCS);

    // While there are data and there is room in TX FIFO
    ulCount = *pLength;
    *pLength = 0;

    while (ulCount > 0)
    {
        txlvl_reg = RegRead(pPdd, XR20M1170REG_TXLVL);
        if (txlvl_reg == 0) break;
        RegWrite(pPdd, XR20M1170REG_THR, *pTxBuffer++);
        (*pLength)++;
        ulCount--;
    }

    // Enable TX interrupt
    pPdd->intrMask |= UART_IER_THR;
    RegWrite(pPdd, XR20M1170REG_IER, pPdd->intrMask);

    LeaveCriticalSection(&pPdd->hwCS);

cleanUp:
    DEBUGMSG(ZONE_THREAD, (L"-HWTxIntr(*pLength = %d)\r\n", *pLength));
}

//------------------------------------------------------------------------------
//
//  Function:  HWModemIntr
//
//  This function is called from the MDD whenever INTR_MODEM is returned
//  by HWGetInterruptType which indicate change in modem registry.
//
static VOID HWModemIntrHandler(VOID *pvContext)
{
    UARTPDD *pPdd = (UARTPDD*)pvContext;
    UCHAR ucModemStat;

    DEBUGMSG(ZONE_THREAD, (L"+HWModemIntr(0x%08x)\r\n", pvContext));

    // Get actual modem status
    ucModemStat = ReadModemStat(pPdd);

    // If we are currently flowed off via CTS or DSR, then
    // we better signal the TX thread when one of them changes
    // so that TX can resume sending.

    EnterCriticalSection(&pPdd->hwCS);


    if (pPdd->flowOffDSR && (ucModemStat & UART_MSR_NDSR) != 0) {
        // Clear flag
        pPdd->flowOffDSR = FALSE;
        // DSR is set, so go ahead and resume sending
        pPdd->intrMask |= UART_IER_THR;
        RegWrite(pPdd, XR20M1170REG_IER,  pPdd->intrMask);
        // Then simulate a TX intr to get things moving
        pPdd->addTxIntr = TRUE;
    }

    if (pPdd->flowOffCTS && (ucModemStat & UART_MSR_NCTS) != 0) {
        pPdd->flowOffCTS = FALSE;
        // CTS is set, so go ahead and resume sending
        pPdd->intrMask |= UART_IER_THR;
        RegWrite(pPdd, XR20M1170REG_IER,  pPdd->intrMask);
        // Then simulate a TX intr to get things moving
        pPdd->addTxIntr = TRUE;
    }

    LeaveCriticalSection(&pPdd->hwCS);
    DEBUGMSG(ZONE_THREAD, (L"-HWModemIntr\r\n"));
}

//------------------------------------------------------------------------------
//
//  Function:  HWLineIntr
//
//  This function is called from the MDD whenever INTR_LINE is returned by
//  HWGetInterruptType which indicate change in line status registry.
//
static VOID HWLineIntrHandler(VOID *pvContext)
{
    UARTPDD *pPdd = (UARTPDD *)pvContext;
    UCHAR fcr_reg;

    DEBUGMSG(ZONE_THREAD, (L"+HWLineIntr(0x%08x)\r\n", pvContext));

    ReadLineStat(pPdd);

    EnterCriticalSection(&pPdd->hwCS);

    // Reset receiver
    fcr_reg = RegRead(pPdd, XR20M1170REG_FCR);
    RegSetBit(pPdd, XR20M1170REG_FCR, UART_FCR_RX_FIFO_CLEAR);
    // Read all character in fifo
    while ((ReadLineStat(pPdd) & UART_LSR_RX_FIFO_E) != 0) {
        RegRead(pPdd, XR20M1170REG_RHR);
    }
    LeaveCriticalSection(&pPdd->hwCS);
    DEBUGMSG(ZONE_THREAD, (L"-HWLineIntr\r\n"));
}

//------------------------------------------------------------------------------
//
//  Function:  HWGetRxBufferSize
//
//  This function returns the size of the hardware buffer passed to
//  the interrupt initialize function.
//
static ULONG HWGetRxBufferSize(VOID *pvContext)
{
    UARTPDD *pPdd = (UARTPDD *)pvContext;
    DEBUGMSG(ZONE_FUNCTION, (TEXT("+/-HWGetRxBufferSize()\r\n")));
    return pPdd->rxBufferSize;

}

//------------------------------------------------------------------------------
//
//  Function:  HWPowerOff
//
//  This function is called from COM_PowerOff. Implementation support power
//  management IOCTL, so there is nothing to do there.
//
static BOOL HWPowerOff(VOID *pvContext)
{
    return TRUE;
}

//------------------------------------------------------------------------------
//
//  Function:  HWPowerOn
//
//  This function is called from COM_PowerOff. Implementation support power
//  management IOCTL, so there is nothing to do there.
//
static BOOL HWPowerOn(VOID *pvContext)
{
    return TRUE;
}

//------------------------------------------------------------------------------
//
//  Function:  HWClearDTR
//
//  This function clears DTR.
//
static VOID HWClearDTR(VOID *pvContext)
{
    UARTPDD *pPdd = (UARTPDD*)pvContext;

    DEBUGMSG(ZONE_FUNCTION, (L"+HWClearDTR(0x%08x)\r\n", pvContext));

    EnterCriticalSection(&pPdd->hwCS);
    RegClrBit(pPdd, XR20M1170REG_MCR, UART_MCR_DTR);
    LeaveCriticalSection(&pPdd->hwCS);

    DEBUGMSG(ZONE_FUNCTION, (L"-HWClearDTR\r\n"));
}

//------------------------------------------------------------------------------
//
//  Function:  HWSetDTR
//
//  This function sets DTR.
//
static VOID HWSetDTR(VOID *pvContext)
{
    UARTPDD *pPdd = (UARTPDD*)pvContext;

    DEBUGMSG(ZONE_FUNCTION, (L"+HWClearDTR(0x%08x)\r\n", pvContext));

    EnterCriticalSection(&pPdd->hwCS);
    RegSetBit(pPdd, XR20M1170REG_MCR, UART_MCR_DTR);
    LeaveCriticalSection(&pPdd->hwCS);

    DEBUGMSG(ZONE_FUNCTION, (L"-HWSetDTR(0x%08x)\r\n", pvContext));
}

//------------------------------------------------------------------------------
//
//  Function:  HWClearRTS
//
//  This function clears RTS.
//
static VOID HWClearRTS(VOID *pvContext)
{
    UARTPDD *pPdd = (UARTPDD*)pvContext;

    DEBUGMSG(ZONE_FUNCTION, (L"+HWClearRTS(0x%08x)\r\n", pvContext));

    EnterCriticalSection(&pPdd->hwCS);
    RegClrBit(pPdd, XR20M1170REG_MCR, UART_MCR_RTS);
    LeaveCriticalSection(&pPdd->hwCS);
    DEBUGMSG(ZONE_FUNCTION, (L"-HWClearRTS\r\n"));
}

//------------------------------------------------------------------------------
//
//  Function:  HWSetRTS
//
//  This function sets RTS.
//
static VOID HWSetRTS(VOID *pvContext)
{
    UARTPDD *pPdd = (UARTPDD*)pvContext;

    DEBUGMSG(ZONE_FUNCTION, (L"+HWSetRTS(0x%08x)\r\n", pvContext));

    EnterCriticalSection(&pPdd->hwCS);
    RegSetBit(pPdd, XR20M1170REG_MCR, UART_MCR_RTS);
    LeaveCriticalSection(&pPdd->hwCS);

    DEBUGMSG(ZONE_FUNCTION, (L"-HWSetRTS(0x%08x)\r\n", pvContext));
}

//------------------------------------------------------------------------------

static BOOL HWEnableIR(VOID *pvContext, ULONG ulBaudRate)
{
    DEBUGMSG(ZONE_FUNCTION, (TEXT("+HWEnableIR()\r\n")));
    DEBUGMSG(ZONE_FUNCTION, (TEXT("-HWEnableIR()\r\n")));
    return TRUE;
}

//------------------------------------------------------------------------------

static BOOL HWDisableIR(VOID *pvContext)
{
    DEBUGMSG(ZONE_FUNCTION, (TEXT("+HWDisableIR()\r\n")));
    DEBUGMSG(ZONE_FUNCTION, (TEXT("-HWDisableIR()\r\n")));
    return TRUE;
}

//------------------------------------------------------------------------------
//
//  Function:  HWClearBreak
//
//  This function clears break.
//
static VOID HWClearBreak(VOID *pvContext)
{
    UARTPDD *pPdd = (UARTPDD*)pvContext;

    DEBUGMSG(ZONE_FUNCTION, (L"+HWClearBreak(0x%08x)\r\n", pvContext));

    EnterCriticalSection(&pPdd->hwCS);
    RegClrBit(pPdd, XR20M1170REG_LCR, UART_LCR_BREAK_EN);
    LeaveCriticalSection(&pPdd->hwCS);

    DEBUGMSG(ZONE_FUNCTION, (L"-HWClearBreak\r\n"));
}

//------------------------------------------------------------------------------
//
//  Function:  HWSetBreak
//
//  This function sets break.
//
static VOID HWSetBreak(VOID *pvContext)
{
    UARTPDD *pPdd = (UARTPDD*)pvContext;

    DEBUGMSG(ZONE_FUNCTION, (
        L"+HWSetBreak(0x%08x)\r\n", pvContext
    ));

    EnterCriticalSection(&pPdd->hwCS);
    RegSetBit(pPdd, XR20M1170REG_LCR, UART_LCR_BREAK_EN);
    LeaveCriticalSection(&pPdd->hwCS);

⌨️ 快捷键说明

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