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

📄 cspiclass.cpp

📁 freescale i.mx31 BSP CE5.0全部源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:

//-----------------------------------------------------------------------------
//
// Function: CspiProcessQueue
//
// This function is the entry point for a thread that will be created
// during CSPI driver initialization and remain resident to process
// packet exchange requests from client devices.
//
// Parameters:
//      lpParameter 
//          [in] Pointer to a single 32-bit parameter value passed to the 
//          thread during creation.  Currently not used.
//
// Returns:
//      Returns TRUE.
//
//-----------------------------------------------------------------------------
DWORD WINAPI cspiClass::CspiProcessQueue(LPVOID lpParameter)
{
    PCSPI_XCH_LIST_ENTRY_T pXchListEntry;
    cspiClass * pCspi = (cspiClass *)lpParameter;
    DEBUGMSG(ZONE_THREAD, (TEXT("CspiProcessQueue:  lpParameter=0x%x\r\n"),lpParameter));

    SetProcPermissions(0xFFFFFFFF);

    // until queue processing thread termination requested
    while (!pCspi->m_bTerminate)
    {
        // while our list of unprocessed queues has not been exhausted
        while (!IsListEmpty(&pCspi->m_ListHead)) 
        {
            // wrap linked list remove operation in critical section to 
            // serialize accesses with CSPI_IOCTL_EXCHANGE
            EnterCriticalSection(&pCspi->m_cspiCs);

            // get next list entry
            pXchListEntry = (PCSPI_XCH_LIST_ENTRY_T) RemoveHeadList(&pCspi->m_ListHead);
        
            LeaveCriticalSection(&pCspi->m_cspiCs);
        
            // check if mapping failed
            if (pXchListEntry == NULL)
            {
                DEBUGMSG(ZONE_ERROR, (TEXT("CspiProcessQueue:  MapCallerPtr failed!\r\n")));
            }
            // exchange packet mapped to our space
            else
            {
                // Wrap the exchange in critical section to 
                // serialize accesses with CSPI_IOCTL_EXCHANGE
                EnterCriticalSection(&pCspi->m_cspiDataXchCs);

                // do the exchange and update the exchange count
                pXchListEntry->xchPkt.xchCnt = pCspi->CspiDataExchange(&pXchListEntry->xchPkt);
                
                LeaveCriticalSection(&pCspi->m_cspiDataXchCs);

                // signal that new data available in Rx message queue
                if(!SetEvent(pXchListEntry->xchPkt.xchEvent))
                {
                    DEBUGMSG(ZONE_ERROR, (TEXT("CspiProcessQueue: SetEvent failed\r\n")));
                } 
            }

            // free memory allocated to list entry
            HeapFree(pCspi->m_hHeap, 0, pXchListEntry);

        } // while (!IsListEmpty(&m_ListHead))

        // wait for next list entry to arrive
        WaitForSingleObject(pCspi->m_hEnQEvent, INFINITE);

    }  // while (!m_bTerminate)

    pCspi->m_hThread = NULL;

    DEBUGMSG(ZONE_THREAD, (TEXT("CspiProcessQueue -\r\n")));
    
    return TRUE;
}


//-----------------------------------------------------------------------------
//
// Function: CspiDataExchange
//
// Exchanges CSPI data in Master mode.
//
// Parameters:
//      pXchPkt
//          [in] Points to exchange packet information.
//
// Returns:
//      Returns the number of data exchanges that completed successfully.
//   
//-----------------------------------------------------------------------------
UINT32 cspiClass::CspiDataExchange(PCSPI_XCH_PKT_T pXchPkt)
{
    PCSPI_BUSCONFIG_T pBusCnfg = pXchPkt->pBusCnfg;
    LPVOID pTxBuf = pXchPkt->pTxBuf;
    LPVOID pRxBuf = pXchPkt->pRxBuf;
    UINT32 xchTxCnt = 0;
    UINT32 xchRxCnt = 0;
    volatile UINT32 tmp;
    BOOL bXchDone = FALSE;
    UINT32 (*pfnTxBufRd)(LPVOID);
    void (*pfnRxBufWrt)(LPVOID, UINT32);
    UINT8 bufIncr;

    DEBUGMSG(ZONE_THREAD, (TEXT("CspiDataExchange: &m_pCSPI=0x%x\r\n"),&m_pCSPI));
    // check all translated pointers
    if ((pBusCnfg == NULL) || (pTxBuf == NULL) || (pRxBuf == NULL))
    {
        return 0;
    }

    // disable all interrupts
    OUTREG32(&m_pCSPI->INTREG, 0);

    // set client CSPI bus configuration based
    //  default EN = disabled
    //  default MODE = master
    //  default XCH = idle
    //  default SMC = XCH bit controls master start transfer
    OUTREG32(&m_pCSPI->CONREG, 
        CSP_BITFVAL(CSPI_CONREG_EN, CSPI_CONREG_EN_DISABLE) |
        CSP_BITFVAL(CSPI_CONREG_MODE, CSPI_CONREG_MODE_MASTER) |
        CSP_BITFVAL(CSPI_CONREG_XCH, CSPI_CONREG_XCH_IDLE) |
        CSP_BITFVAL(CSPI_CONREG_SMC, CSPI_CONREG_SMC_XCH) |
        CSP_BITFVAL(CSPI_CONREG_CHIPSELECT, pBusCnfg->chipselect) |
        CSP_BITFVAL(CSPI_CONREG_DATARATE, BSPCSPICalculateDivRate(pBusCnfg->freq)) |
        CSP_BITFVAL(CSPI_CONREG_SSPOL, pBusCnfg->sspol) |
        CSP_BITFVAL(CSPI_CONREG_SSCTL, pBusCnfg->ssctl) |
        CSP_BITFVAL(CSPI_CONREG_POL, pBusCnfg->pol) |
        CSP_BITFVAL(CSPI_CONREG_PHA, pBusCnfg->pha) |
        CSP_BITFVAL(CSPI_CONREG_BITCOUNT, pBusCnfg->bitcount) |
        CSP_BITFVAL(CSPI_CONREG_DRCTL, pBusCnfg->drctl));

    // select access funtions based on exchange bit width
    //
    // bitcount        Tx/Rx Buffer Access Width
    // --------        -------------------------
    //   1 - 8           UINT8 (unsigned 8-bit)
    //   9 - 16          UINT16 (unsigned 16-bit)
    //  17 - 32          UINT32 (unsigned 32-bit)
    //
    if ((pBusCnfg->bitcount >= 1) && (pBusCnfg->bitcount <= 8))
    {
        // 8-bit access width
        pfnTxBufRd = CspiBufRd8;
        pfnRxBufWrt = CspiBufWrt8;
        bufIncr = sizeof(UINT8);
    }
    else if ((pBusCnfg->bitcount >= 9) && (pBusCnfg->bitcount <= 16))
    {
        // 16-bit access width
        pfnTxBufRd = CspiBufRd16;
        pfnRxBufWrt = CspiBufWrt16;
        bufIncr = sizeof(UINT16);
    }
    else if ((pBusCnfg->bitcount >= 17) && (pBusCnfg->bitcount <= 32))
    {
        // 32-bit access width
        pfnTxBufRd = CspiBufRd32;
        pfnRxBufWrt = CspiBufWrt32;
        bufIncr = sizeof(UINT32);
    }
    else
    {
        // unsupported access width
        DEBUGMSG(ZONE_WARN, (TEXT("CspiMasterDataExchange:  unsupported bitcount!\r\n")));
        return 0;
    }

    // Enable the clock gating
    BSPCSPIEnableClock(m_Index,TRUE);

    // enable the CSPI
    INSREG32(&m_pCSPI->CONREG, CSP_BITFMASK(CSPI_CONREG_EN), 
        CSP_BITFVAL(CSPI_CONREG_EN, CSPI_CONREG_EN_ENABLE));

    if (m_bUseDMA)
    {
        UINT32 WordCount = pXchPkt->xchCnt / 4;

        if (WordCount)   // pXchPkt->xchCnt is more than 4
        {
            m_nondmaTransferCount = pXchPkt->xchCnt % 4;
            m_dmaTransferCount = WordCount * 4;
            m_isDMADone = FALSE;
        }
        else
        {
            m_nondmaTransferCount = pXchPkt->xchCnt;
            m_dmaTransferCount = 0;
        }
        // assert DMA request for half or empty
        // irrespective of the condition, 
        // we need to enable the transmitter
       // INSREG32(&m_pCSPI->DMAREG, CSP_BITFMASK(CSPI_DMAREG_THDEN), 
          //  CSP_BITFVAL(CSPI_DMAREG_THDEN, CSPI_DMAREG_THDEN_ENABLE));
        INSREG32(&m_pCSPI->DMAREG, CSP_BITFMASK(CSPI_DMAREG_TEDEN), 
            CSP_BITFVAL(CSPI_DMAREG_TEDEN, CSPI_DMAREG_TEDEN_ENABLE));
        if (m_dmaTransferCount)
        {
            INSREG32(&m_pCSPI->DMAREG, CSP_BITFMASK(CSPI_DMAREG_RHDEN), 
                CSP_BITFVAL(CSPI_DMAREG_RHDEN, CSPI_DMAREG_RHDEN_ENABLE));
            //INSREG32(&m_pCSPI->DMAREG, CSP_BITFMASK(CSPI_DMAREG_RFDEN), 
            //    CSP_BITFVAL(CSPI_DMAREG_RFDEN, CSPI_DMAREG_RFDEN_ENABLE));
        }
    }
    // until we are done with requested transfers
    while(!bXchDone)
    {
        // load Tx FIFO until full, or until we run out of data
        while ((!(INREG32(&m_pCSPI->STATREG) & CSP_BITFMASK(CSPI_STATREG_TF)))
            && (xchTxCnt < pXchPkt->xchCnt))
        {
            if (m_bUseDMA)
            {
                DDKSdmaClearBufDescStatus(m_dmaChanCspiTx,0);
                DDKSdmaSetBufDesc(m_dmaChanCspiTx, 0, 
                    DDK_DMA_FLAGS_INTR | DDK_DMA_FLAGS_WRAP,
                    PhysDMABufferAddr.LowPart + CSPI_TXMT_OFFSET,
                    0, DDK_DMA_ACCESS_32BIT, pXchPkt->xchCnt * 4); // set the count in bytes.
                MoveDMABuffer(pTxBuf, pXchPkt->xchCnt * 4, FALSE); // set the count in bytes.
                DDKSdmaStartChan(m_dmaChanCspiTx);

                UINT uiTxStatus = 0;
                do
                {
                   DDKSdmaGetBufDescStatus(m_dmaChanCspiTx, 0, &uiTxStatus); 
                }while (uiTxStatus & DDK_DMA_FLAGS_BUSY);

                DEBUGMSG(ZONE_FUNCTION, (TEXT(" uiTxStatus = 0x%X  xchTxCnt= 0x%X\r\n"), uiTxStatus, (uiTxStatus & CSP_BITFMASK(SDMA_MODE_COUNT)) / 4));
                xchTxCnt = (uiTxStatus & CSP_BITFMASK(SDMA_MODE_COUNT)) / 4; // division is to get the count in DWORD
            }
            else
            {
                // put next Tx data into CSPI FIFO
                OUTREG32(&m_pCSPI->TXDATA, pfnTxBufRd(pTxBuf));

                // increment Tx Buffer to next data point
                pTxBuf = (LPVOID) ((UINT) pTxBuf + bufIncr);

                // increment Tx exchange counter
                xchTxCnt++;
            }
        }
        
        // start exchange
        INSREG32(&m_pCSPI->CONREG, CSP_BITFMASK(CSPI_CONREG_XCH), 
            CSP_BITFVAL(CSPI_CONREG_XCH, CSPI_CONREG_XCH_EN));

        // if we completed requested transfers, then we enable
        // interrupt for transfer completed (TCEN)
        if (xchTxCnt == pXchPkt->xchCnt)
        {
            if(m_bUsePolling)
            {
                // wait until transaction is complete
                while (!(INREG32(&m_pCSPI->STATREG) & CSP_BITFMASK(CSPI_STATREG_TC)))
                    ;
            }
            else
            {
                INSREG32(&m_pCSPI->INTREG, CSP_BITFMASK(CSPI_INTREG_TCEN), 
                    CSP_BITFVAL(CSPI_INTREG_TCEN, CSPI_INTREG_TCEN_ENABLE));
            }
            
            // set flag to indicate requested exchange done
            bXchDone = TRUE;
        }
        // otherwise we need to wait until FIFO has more room, so
        // we enable interrupt for Rx FIFO half-full (RHEN) to
        // ensure we can read out data that arrived during exchange
        else
        {
            if(m_bUsePolling)
            {
                // wait until RH
                while (!(INREG32(&m_pCSPI->STATREG) & CSP_BITFMASK(CSPI_STATREG_RH)))
                    ;
            }
            else
            {
                if (m_bUseDMA && m_nondmaTransferCount)
                {
                    INSREG32(&m_pCSPI->INTREG, CSP_BITFMASK(CSPI_INTREG_RHEN), 
                        CSP_BITFVAL(CSPI_INTREG_RHEN, CSPI_INTREG_RHEN_ENABLE));
                }
                else
                {
                    INSREG32(&m_pCSPI->INTREG, CSP_BITFMASK(CSPI_INTREG_RHEN), 
                        CSP_BITFVAL(CSPI_INTREG_RHEN, CSPI_INTREG_RHEN_ENABLE));
                }
            }
        }   

        while (xchRxCnt < xchTxCnt)
        {

            // wait for requested transfer interrupt
            WaitForSingleObject(m_hIntrEvent, INFINITE);

            // disable all interrupts
            OUTREG32(&m_pCSPI->INTREG, 0);

            // acknowledge transfer complete (w1c)
            OUTREG32(&m_pCSPI->STATREG, CSP_BITFMASK(CSPI_STATREG_TC));

            // while there is data in Rx FIFO and we have buffer space
            while ((INREG32(&m_pCSPI->STATREG) & CSP_BITFMASK(CSPI_STATREG_RR))
                && (xchRxCnt < pXchPkt->xchCnt))
            {
                if (m_bUseDMA)
                {
                    if (m_dmaTransferCount && !m_isDMADone)
                    {
                        DDKSdmaClearBufDescStatus(m_dmaChanCspiRx,0);

                        DDKSdmaSetBufDesc(m_dmaChanCspiRx, 0, 
                            DDK_DMA_FLAGS_INTR | DDK_DMA_FLAGS_WRAP,
                            PhysDMABufferAddr.LowPart + CSPI_RECV_OFFSET,
                            0, DDK_DMA_ACCESS_32BIT, m_dmaTransferCount * 4); //Count should be in Bytes.
                        DDKSdmaStartChan(m_dmaChanCspiRx);
                        UINT uiRxStatus = 0;
                        do
                        {
                            DDKSdmaGetBufDescStatus(m_dmaChanCspiRx, 0, &uiRxStatus);
                        }while (uiRxStatus & DDK_DMA_FLAGS_BUSY);

                        DEBUGMSG(ZONE_FUNCTION, (TEXT(" uiRxStatus = 0x%X  xchRxCnt= 0x%X\r\n"), uiRxStatus, (uiRxStatus & CSP_BITFMASK(SDMA_MODE_COUNT)) / 4));
                        
                        xchRxCnt = (uiRxStatus & CSP_BITFMASK(SDMA_MODE_COUNT)) / 4;
                        MoveDMABuffer(pRxBuf, xchRxCnt * 4,TRUE);
                        m_isDMADone = TRUE;
                        
                        // advance the buffer
                        pRxBuf = (LPVOID) ((UINT) pRxBuf + (xchRxCnt * bufIncr));
                    }
                    if (m_nondmaTransferCount)
                    {
                        tmp = INREG32(&m_pCSPI->RXDATA);

                        // if receive data is not to be discarded
                        if (pRxBuf != NULL)
                        {
                            // get next Rx data from CSPI FIFO
                            pfnRxBufWrt(pRxBuf, tmp);

                            // increment Rx Buffer to next data point
                            pRxBuf = (LPVOID) ((UINT) pRxBuf + bufIncr);
                        }
                        // else receive data will be discarded

                        // increment Rx exchange counter
                        xchRxCnt++;
                    }
                }
                else
                {
                    tmp = INREG32(&m_pCSPI->RXDATA);

                    // if receive data is not to be discarded
                    if (pRxBuf != NULL)
                    {
                        // get next Rx data from CSPI FIFO
                        pfnRxBufWrt(pRxBuf, tmp);

                        // increment Rx Buffer to next data point
                        pRxBuf = (LPVOID) ((UINT) pRxBuf + bufIncr);
                    }
                    // else receive data will be discarded

                    // increment Rx exchange counter
                    xchRxCnt++;
                }
            }

            // signal that interrupt has been handled
            InterruptDone(m_dwSysIntr);

            // if Rx has not caught up to Tx, keep waiting until remaining 
            // data arrives
            if (xchRxCnt < xchTxCnt)
            {
                if (m_bUsePolling)
                {
                    // Disable all CSPI interrupts
                    OUTREG32(&m_pCSPI->INTREG, 0);
                }
                else
                {
                    // enable Rx FIFO ready interrupt (RREN)
                    
                    if (m_bUseDMA && m_nondmaTransferCount)
                    {
                        INSREG32(&m_pCSPI->INTREG, CSP_BITFMASK(CSPI_INTREG_RREN),
                           CSP_BITFVAL(CSPI_INTREG_RREN, CSPI_INTREG_RREN_ENABLE));
                    }
                    else
                    {
                        INSREG32(&m_pCSPI->INTREG, CSP_BITFMASK(CSPI_INTREG_RREN),
                            CSP_BITFVAL(CSPI_INTREG_RREN, CSPI_INTREG_RREN_ENABLE));
                    }
                }
            } 
        } // while (xchRxCnt < xchTxCnt)
    } // while(!bXchDone)
    
    // Disable the clock gating
    BSPCSPIEnableClock(m_Index,FALSE);
    DEBUGMSG(ZONE_THREAD, (TEXT("CspiDataExchange -\r\n")));

    return xchRxCnt;
}



//-----------------------------------------------------------------------------
//
// Function: CspiBufRd8
//
// This function is used to access a buffer as an array of 8-bit (UINT8) 
// values and read data from the specified location.
//
// Parameters:
//      pBuf

⌨️ 快捷键说明

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