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

📄 pl011pdd.c

📁 ARM9基于WINDOWSCE的BSP源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
    pPDDContext->CommProp.dwServiceMask       = SP_SERIALCOMM;
    pPDDContext->CommProp.dwReserved1         = 0;
    pPDDContext->CommProp.dwMaxTxQueue        = 16;
    pPDDContext->CommProp.dwMaxRxQueue        = 16;
    pPDDContext->CommProp.dwMaxBaud           = BAUD_USER;
    pPDDContext->CommProp.dwProvSubType       = PST_RS232;
    pPDDContext->CommProp.dwProvCapabilities  = PCF_DTRDSR |
                                                PCF_INTTIMEOUTS |
                                                PCF_PARITY_CHECK |
                                                PCF_RLSD |
                                                PCF_RTSCTS |
                                                PCF_SETXCHAR |
                                                PCF_SPECIALCHARS |
                                                PCF_TOTALTIMEOUTS |
                                                PCF_XONXOFF;
    pPDDContext->CommProp.dwSettableParams    = SP_BAUD |
                                                SP_DATABITS |
                                                SP_HANDSHAKING |
                                                SP_PARITY |
                                                SP_PARITY_CHECK |
                                                SP_RLSD |
                                                SP_STOPBITS;
    pPDDContext->CommProp.dwSettableBaud      = BAUD_075 | BAUD_110 | BAUD_150 | BAUD_300 |
                                                BAUD_600 | BAUD_1200 | BAUD_1800 | BAUD_2400 |
                                                BAUD_4800 | BAUD_7200 | BAUD_9600 | BAUD_14400 |
                                                BAUD_19200 | BAUD_38400 | BAUD_56K | BAUD_128K |
                                                BAUD_115200 | BAUD_57600 | BAUD_USER;
    pPDDContext->CommProp.wSettableData       = DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8;
    pPDDContext->CommProp.wSettableStopParity = PARITY_NONE | PARITY_EVEN | PARITY_ODD |
                                                PARITY_MARK | PARITY_SPACE |
                                                STOPBITS_10 | STOPBITS_20;
    pPDDContext->CommProp.dwCurrentTxQueue    = 0;
    pPDDContext->CommProp.dwCurrentTxQueue    = 0;
    pPDDContext->CommProp.dwProvSpec1         = 0;
    pPDDContext->CommProp.dwProvSpec2         = 0;
    pPDDContext->CommProp.wcProvChar[0]       = 0;

    // We don't have to initialise the following members; the entire PDD context was initialised
    //  with zero by the allocation.
    //
    pPDDContext->dcb;               // MDD will call HWSetDCB() later
    pPDDContext->fCommErrors;       // 0x00000000

    pPDDContext->fInterrupts;       // 0x00000000
    pPDDContext->fModemStatus;      // 0x00000000
    pPDDContext->nDroppedBytes;     // 0
    pPDDContext->fCTSFlowOff;       // FALSE (not flowed-off yet)
    pPDDContext->fDSRFlowOff;       // FALSE (not flowed-off yet)
    pPDDContext->fAddTxIntr;        // FALSE

//UART DMA Init.
    if (pPDDContext->DMA_Enable){
        pPDDContext->No_DMA_timeout=FALSE; //by default, use DMA for Rx
        PL011DMACtrl(pPDDContext->pPL011, PL011_DMACR_TXDMAE|PL011_DMACR_RXDMAE); //Enable UART Rx & Tx DMA
    }

//End of DMA Init.
    

    // Don't allow any interrupts until PostInit
    //
    VERIFY(PL011DisableAllInterrupts(pPDDContext->pPL011));

    // Clear any pending interrupts (following a warm-start/soft-reset, for example)
    //
    VERIFY(PL011ClearPendingInterrupts(pPDDContext->pPL011));

    // Power-down PL011
    //
    DEBUGMSG(ZONE_INIT,
        (BODY_TEXT("PDD_Init: Powering-down UART")));
    VERIFY(PL011SetOutputMode(pPDDContext->pPL011, FALSE, FALSE));

    goto exit_point;

fail_point:

    // TODO: We can't use PDD_Deinit to cleanup here. The MDD will use the HW_VTBL in the HWOBJ
    //        that we returned from GetSerialObject to call HWDeinit; the HWOBJ and HW_VTBL will
    //        have to be cleaned-up last of all.
    //
    PDD_Deinit(pPDDContext);
    pPDDContext = NULL;

exit_point:

    DEBUGMSG(ZONE_INIT | ZONE_FUNCTION,
        (TAIL_TEXT("PDD_Init() %s"), SUCCEEDED_OR_FAILED(pPDDContext != NULL)));

    return pPDDContext;
}


BOOL PDD_PostInit(PDD_CONTEXT *pPDDContext)
{
    BOOL fRC = FALSE;

    DEBUGMSG(ZONE_INIT | ZONE_FUNCTION,
        (HEAD_TEXT("PDD_PostInit(%#08x)"), pPDDContext));

    if (pPDDContext == NULL)
        goto exit_point;

    // Since we are just a library which might get used for built-in ports which Init() at boot,
    //  or by PCMCIA ports which Init() at Open, we can't do anything too fancy. Let's just make
    //  sure we cancel any pending interrupts so that if we are being used with an edge triggered
    //  PIC, it will see an edge after the MDD hooks the interrupt.
    //
    VERIFY(fRC = PL011ClearPendingInterrupts(pPDDContext->pPL011));

exit_point:

    DEBUGMSG(ZONE_INIT | ZONE_FUNCTION,
        (TAIL_TEXT("PDD_PostInit() %s"), SUCCEEDED_OR_FAILED(fRC)));

    return fRC;
}


BOOL PDD_Deinit(PDD_CONTEXT *pPDDContext)
{
    DEBUGMSG(ZONE_INIT | ZONE_CLOSE | ZONE_FUNCTION,
        (HEAD_TEXT("PDD_Deinit(%#08x)"), pPDDContext));
	RETAILMSG( TRUE, (TEXT("PDD_Deinit ( )\r\n")) );
    if (pPDDContext == NULL)
        goto exit_point;

    // Make sure device is closed before doing DeInit
    //
    if (pPDDContext->nOpenCount != 0)
        PDD_Close(pPDDContext);

    // Free the PL011 context
    //
    pPDDContext->pPL011 = PL011Delete(pPDDContext->pPL011);
    DEBUGMSG((ZONE_INIT | ZONE_CLOSE | ZONE_ERROR) && (pPDDContext->pPL011 != NULL),
        (BODY_TEXT("PDD_Deinit: Failed to free PL011 context")));

    // Free the critical section
    //
    DeleteCriticalSection(&pPDDContext->cs);

    // Free the Win32 event object
    if ((pPDDContext->hevTxReady != NULL) && (CloseHandle(pPDDContext->hevTxReady)))
        pPDDContext->hevTxReady = NULL;

    DEBUGMSG((ZONE_INIT | ZONE_CLOSE | ZONE_ERROR) && (pPDDContext->hevTxReady != NULL),
        (BODY_TEXT("PDD_Deinit: Failed to free Win32 event object")));

    // Free the HWOBJ
    //
    if (pPDDContext->pHWObj != NULL)
        pPDDContext->pHWObj = LocalFree(pPDDContext->pHWObj);
 
    // Free the mapped memory
    if (pPDDContext->pBaseAddress)
    {
        VirtualFree (pPDDContext->pBaseAddress, 0, MEM_RELEASE);
    }    

    DEBUGMSG((ZONE_INIT | ZONE_CLOSE | ZONE_ERROR) && (pPDDContext->pHWObj != NULL),
        (BODY_TEXT("PDD_Deinit: Failed to free HWOBJ")));

    // Now, free the PDD context
    //
    pPDDContext = LocalFree(pPDDContext);
    DEBUGMSG((ZONE_INIT | ZONE_CLOSE | ZONE_ERROR) && (pPDDContext != NULL),
        (BODY_TEXT("PDD_Deinit: Failed to free PDD context")));

exit_point:

    DEBUGMSG(ZONE_INIT | ZONE_CLOSE | ZONE_FUNCTION,
        (TAIL_TEXT("PDD_Deinit() %s"), SUCCEEDED_OR_FAILED(pPDDContext == NULL)));

    return (pPDDContext == NULL);
}


BOOL PDD_Open(PDD_CONTEXT *pPDDContext)
{
    BOOL fRC = FALSE;

    DEBUGMSG(ZONE_OPEN | ZONE_FUNCTION,
        (HEAD_TEXT("PDD_Open(%#08x)"), pPDDContext));

    if (pPDDContext == NULL)
        goto exit_point;

    // Disallow multiple, simultaneous opens
    //
    if (pPDDContext->nOpenCount != 0)
    {
        DEBUGMSG(ZONE_OPEN | ZONE_ERROR,
            (BODY_TEXT("PDD_Open: Already open")));
        SetLastError(ERROR_OPEN_FAILED);
        goto exit_point;
    }

    pPDDContext->fCommErrors = 0;       // 0x00000000

    pPDDContext->fInterrupts = 0;       // 0x00000000
    pPDDContext->fModemStatus = 0;      // 0x00000000
    pPDDContext->nDroppedBytes = 0;     // 0
    pPDDContext->fCTSFlowOff = FALSE;       // FALSE (not flowed-off yet)
    pPDDContext->fDSRFlowOff = FALSE;       // FALSE (not flowed-off yet)
    pPDDContext->fAddTxIntr = FALSE;    

    EnterCriticalSection(&pPDDContext->cs);

    try
    {
//UART DMA - PDD_Open
        if (pPDDContext->DMA_Enable)
        {
        PUART_DMA_INFO pUDma = &(pPDDContext->uart_DMA_Info);
        ALLOCATE_DMA_PARAMS AllocateDMAParams;
        ALLOCATE_DMA_RESULT AllocateDMAResult;
        DWORD   dwRet;

        ++(pUDma->OpenCnt);
    
        // Allocate some virtual space (in page alignment) so we can do DMA transfer
        // between it and Rx/Tx. We can not use MDD buffer address to configure DMA because 
        // the buffer is allocated from heap, which we can not get physical address.
        pUDma->pvRxDestBuffer = (PUCHAR)VirtualAlloc
            (NULL, PAGE_SIZE, MEM_COMMIT, PAGE_READWRITE|PAGE_NOCACHE); 
        if(pUDma->pvRxDestBuffer == NULL)
        {
            RETAILMSG(1, (TEXT("Error - unable to allocate buffer\r\n")));
            return FALSE;
        }

        pUDma->pvTxSourceBuffer = (PUCHAR)VirtualAlloc
            (NULL, PAGE_SIZE, MEM_COMMIT, PAGE_READWRITE|PAGE_NOCACHE); 

        if(pUDma->pvTxSourceBuffer == NULL)
        {
            RETAILMSG(1, (TEXT("Error - unable to allocate buffer\r\n")));
            return FALSE;
        }



    //UART Rx Channel Alloc.

        if (pPDDContext->ComId)
            AllocateDMAParams.ucSourceDevice = UART1_Rx_ID; // UART1 Rx
        else
            AllocateDMAParams.ucSourceDevice = UART0_Rx_ID; // UART0 Rx
        AllocateDMAParams.ucDestDevice = 0;     // Memory, so could be any value
        AllocateDMAParams.ucPreferedPriority = 0xff;    // no preference
        if(!KernelIoControl(IOCTL_HAL_ALLOCATE_DMA_CHANNEL,
            &AllocateDMAParams, sizeof(AllocateDMAParams),
            &AllocateDMAResult, sizeof(AllocateDMAResult), &dwRet))
        {
            DEBUGMSG(ZONE_OPEN | ZONE_ERROR, 
                (TEXT("PDD_Open: Error - DMA channel(Rx) allocation failed\r\n")));
            // No channels available
            SetLastError(ERROR_ALREADY_ASSIGNED);
            DMA_Close(&(pPDDContext->uart_DMA_Info));
            return FALSE;
        }

        // Save the channel number and interrupt id
        pUDma->ucRxDMAChannel = AllocateDMAResult.ucChannelNumber;
        pUDma->dwRxDMASysIntr = AllocateDMAResult.dwInterruptID;

        // Create the DMA interrupt event for Rx
        pUDma->hRxUDmaISTEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
        if(pUDma->hRxUDmaISTEvent == NULL)
        {
            DEBUGMSG(ZONE_OPEN | ZONE_ERROR, 
                (TEXT("PDD_Open: Error creating Rx DMA Interrupt event\r\n")));
            DMA_Close(pUDma);
            return FALSE;
        }

    // Enable the DMA interrupt for Rx
        if(!InterruptInitialize(pUDma->dwRxDMASysIntr, pUDma->hRxUDmaISTEvent, NULL, 0))
        {
            DEBUGMSG(ZONE_OPEN | ZONE_ERROR, 
                (TEXT("PDD_Open: Error enabling Rx DMA interrupt (%d)\r\n"), 
                GetLastError()));
            DMA_Close(pUDma);
            return FALSE;
        }


    // UART Tx Channel Alloc.

        AllocateDMAParams.ucSourceDevice = 0;       // Memory
        if(pPDDContext->ComId)
            AllocateDMAParams.ucDestDevice = UART1_Tx_ID;   // UART1 Tx
        else
            AllocateDMAParams.ucDestDevice = UART0_Tx_ID;   // UART0 Tx
        AllocateDMAParams.ucPreferedPriority = 0xff;    // no preference
        if(!KernelIoControl(IOCTL_HAL_ALLOCATE_DMA_CHANNEL,
            &AllocateDMAParams, sizeof(AllocateDMAParams),
            &AllocateDMAResult, sizeof(AllocateDMAResult), &dwRet))
        {
            DEBUGMSG(ZONE_OPEN | ZONE_ERROR, 
                (TEXT("PDD_Open: Error - DMA channel(Tx) allocation failed\r\n")));
            // No channels available
            SetLastError(ERROR_ALREADY_ASSIGNED);
            DMA_Close(pUDma);
            return FALSE;
        }

        // Save the channel number and interrupt id
        pUDma->ucTxDMAChannel = AllocateDMAResult.ucChannelNumber;
        pUDma->dwTxDMASysIntr = AllocateDMAResult.dwInterruptID;

        // Create the DMA interrupt event for the Tx
        pUDma->hTxUDmaISTEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
        if(pUDma->hTxUDmaISTEvent == NULL)
        {
            DEBUGMSG(ZONE_OPEN | ZONE_ERROR, 
                (TEXT("PDD_Open: Error creating Tx DMA Interrupt event\r\n")));
            DMA_Close(pUDma);
            return FALSE;
        }

    // Enable the DMA interrupt for Tx
        if(!InterruptInitialize(pUDma->dwTxDMASysIntr, pUDma->hTxUDmaISTEvent, NULL, 0))
        {
            DEBUGMSG(ZONE_OPEN | ZONE_ERROR, 
                (TEXT("PDD_Open: Error enabling Tx DMA interrupt (%d)\r\n"), 
                GetLastError()));
            DMA_Close(pUDma);
            return FALSE;
        }
    }
//End of UART DMA - PDD_Open

    // Increment the open count
    //
    pPDDContext->nOpenCount++;
    DEBUGMSG(ZONE_OPEN,
        (BODY_TEXT("PDD_Open: Open count = %u"), pPDDContext->nOpenCount));

    // Set FIFO settings (enabled, Rx >= 3/4, Tx <= 1/4)
    //
    if (!PL011EnableFIFO(pPDDContext->pPL011, PL011_FLSEL_3_4, PL011_FLSEL_1_4))
    {
        fRC = FALSE;
        goto fail_point;
    }

    // Select wired by default
    //
    pPDDContext->fIRMode = FALSE;
    if (!PL011SetOutputMode(pPDDContext->pPL011, pPDDContext->fIRMode, !pPDDContext->fIRMode))
    {
        fRC = FALSE;
        goto fail_point;
    }

    DEBUGMSG(ZONE_OPEN,
        (BODY_TEXT("PDD_Open: %s"), (pPDDContext->fIRMode) ? TEXT("IR mode") :
                                                             TEXT("Non IR mode")));

    // Set baud rate, data size, parity and stop bits
    //
    fRC = PL011SetLineFormat(pPDDContext->pPL011, pPDDContext->dcb.BaudRate,
                                                  pPDDContext->dcb.ByteSize,
                                                  pPDDContext->dcb.Parity,
                                                  pPDDContext->dcb.StopBits);

    // Enable interrupts, for the first time
    //
    VERIFY(PL011EnableAllInterrupts(pPDDContext->pPL011));

#ifdef DEBUG
    if (ZONE_OPEN)
        PL011DumpRegisters(pPDDContext->pPL011);
#endif

⌨️ 快捷键说明

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