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

📄 cspiclass.cpp

📁 Microsoft WinCE 6.0 BSP FINAL release source code for use with the i.MX27ADS TO2 WCE600_FINAL_MX27_S
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//------------------------------------------------------------------------------
//
// 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
    CLRREG32(&m_pCSPI->INT, 0x0003FE00);

    // Set client CSPI bus configuration based
    //  default EN = disabled
    //  default MODE = master
    //  default XCH = idle
    OUTREG32(&m_pCSPI->CONTROLREG, 
        CSP_BITFVAL(CSPI_CONTROLREG_SPIEN, CSPI_CONTROLREG_SPIEN_DISABLE) |
        CSP_BITFVAL(CSPI_CONTROLREG_MODE, CSPI_CONTROLREG_MODE_MASTER) |
        CSP_BITFVAL(CSPI_CONTROLREG_XCH, CSPI_CONTROLREG_XCH_IDLE) |
        CSP_BITFVAL(CSPI_CONTROLREG_CS, pBusCnfg->chipselect) |
        CSP_BITFVAL(CSPI_CONTROLREG_DATARATE, BSPCSPICalculateDivRate(pBusCnfg->freq)) |
        CSP_BITFVAL(CSPI_CONTROLREG_SSPOL, pBusCnfg->sspol) |
        CSP_BITFVAL(CSPI_CONTROLREG_SSCTL, pBusCnfg->ssctl) |
        CSP_BITFVAL(CSPI_CONTROLREG_POL, pBusCnfg->pol) |
        CSP_BITFVAL(CSPI_CONTROLREG_PHA, pBusCnfg->pha) |
        CSP_BITFVAL(CSPI_CONTROLREG_BITCOUNT, pBusCnfg->bitcount) |
        CSP_BITFVAL(CSPI_CONTROLREG_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_nIndex, TRUE);

    // Enable the CSPI
    INSREG32BF(&m_pCSPI->CONTROLREG, CSPI_CONTROLREG_SPIEN, CSPI_CONTROLREG_SPIEN_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->INT) & CSP_BITFMASK(CSPI_INT_TF)))
            && (xchTxCnt < pXchPkt->xchCnt)) {
            // 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
        INSREG32BF(&m_pCSPI->CONTROLREG, CSPI_CONTROLREG_XCH, CSPI_CONTROLREG_XCH_EN);

        if (xchTxCnt == pXchPkt->xchCnt) {
            // If we completed requested transfers, then polling or enable
            // interrupt for transfer completed
            if (m_bUsePolling) {
                // Wait until transaction is complete
                while (!(INREG32(&m_pCSPI->INT) & CSP_BITFMASK(CSPI_INT_TSHFE)));
            } else {
                INSREG32BF(&m_pCSPI->INT, CSPI_INT_TSHFEEN, CSPI_INT_TSHFEEN_ENABLE);
            }

            // Set flag to indicate requested exchange done
            bXchDone = TRUE;
        } else {
            // 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
            if (m_bUsePolling) {
                // Wait until RH
                while (!(INREG32(&m_pCSPI->INT) & CSP_BITFMASK(CSPI_INT_RH)));
            } else {
                INSREG32BF(&m_pCSPI->INT, CSPI_INT_RHEN, CSPI_INT_RHEN_ENABLE);            
            }
        }

        while (xchRxCnt < xchTxCnt) {
            // Wait for requested transfer interrupt
            WaitForSingleObject(m_hIntrEvent, INFINITE);

            // Disable all interrupts
            CLRREG32(&m_pCSPI->INT, 0x0003FE00);

            // Acknowledge transfer complete (w1c)
            OUTREG32(&m_pCSPI->INT, CSP_BITFMASK(CSPI_INT_TSHFEEN));

            // While there is data in Rx FIFO and we have buffer space
            while ((INREG32(&m_pCSPI->INT) & CSP_BITFMASK(CSPI_INT_RR))
                && (xchRxCnt < pXchPkt->xchCnt)) {
                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
                    CLRREG32(&m_pCSPI->INT, 0x0003FE00);
                } else {
                    // Enable Rx FIFO ready interrupt (RREN)
                    INSREG32BF(&m_pCSPI->INT, CSPI_INT_RREN, CSPI_INT_RREN_ENABLE);
                }
            } 
        } // while (xchRxCnt < xchTxCnt)
    } // while(!bXchDone)
    
#if 0
    // Dump out what we just transmitted and received
    pTxBuf = pXchPkt->pTxBuf;
    pRxBuf = pXchPkt->pRxBuf;
    for (xchTxCnt = 0; xchTxCnt < xchRxCnt; xchTxCnt++) {
        DEBUGMSG(ZONE_THREAD, (TEXT("TXDATA[%d] = 0x%x\r\n"), xchTxCnt, pfnTxBufRd(pTxBuf)));
        pTxBuf = (LPVOID) ((UINT) pTxBuf + bufIncr);
    }
    for (xchTxCnt = 0; xchTxCnt < xchRxCnt; xchTxCnt++) {
        DEBUGMSG(ZONE_THREAD, (TEXT("RXDATA[%d] = 0x%x\r\n"), xchTxCnt, pfnTxBufRd(pRxBuf)));
        pRxBuf = (LPVOID) ((UINT) pRxBuf + bufIncr);
    }
#endif

    // Disable the clock gating
    BSPCSPIEnableClock(m_nIndex, 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
//          [in] Pointer to buffer from which data will be read.
//
// Returns:
//      Returns data pointed to by specified buffer, promoted to UINT32.
//
//------------------------------------------------------------------------------
UINT32 cspiClass::CspiBufRd8(LPVOID pBuf)
{
    UINT8 *p;

    p = (UINT8 *) pBuf;

    return *p;
}

//------------------------------------------------------------------------------
//
// Function: CspiBufRd16
//
// This function is used to access a buffer as an array of 16-bit (UINT16) 
// values and read data from the specified location.
//
// Parameters:
//      pBuf
//          [in] Pointer to buffer from which data will be read.
//
// Returns:
//      Returns data pointed to by specified buffer, promoted to UINT32.
//
//------------------------------------------------------------------------------
UINT32 cspiClass::CspiBufRd16(LPVOID pBuf)
{
    UINT16 *p;

    p = (UINT16 *) pBuf;

    return *p;
}

//------------------------------------------------------------------------------
//
// Function: CspiBufRd32
//
// This function is used to access a buffer as an array of 32-bit (UINT32) 
// values and read data from the specified location.
//
// Parameters:
//      pBuf
//          [in] Pointer to buffer from which data will be read.
//
// Returns:
//      Returns data pointed to by specified buffer.
//
//------------------------------------------------------------------------------
UINT32 cspiClass::CspiBufRd32(LPVOID pBuf)
{
    UINT32 *p;

    p = (UINT32 *) pBuf;

    return *p;
}

//------------------------------------------------------------------------------
//
// Function: CspiBufWrt8
//
// This function is used to access a buffer as an array of 8-bit (UINT8) 
// values and writes data to the specified buffer location.
//
// Parameters:
//      pBuf
//          [in] Pointer to buffer to which data will be written.
//
//      data
//          [in] Data to be written demoted to UINT8.
//
// Returns:
//      None.
//
//------------------------------------------------------------------------------
void cspiClass::CspiBufWrt8(LPVOID pBuf, UINT32 data)
{
    UINT8 *p;

    p = (UINT8 *) pBuf;

   *p = (UINT8) data;
}

//------------------------------------------------------------------------------
//
// Function: CspiBufWrt16
//
// This function is used to access a buffer as an array of 16-bit (UINT16) 
// values and writes data to the specified buffer location.
//
// Parameters:
//      pBuf
//          [in] Pointer to buffer to which data will be written.
//
//      data
//          [in] Data to be written demoted to UINT16.
//
// Returns:
//      None.
//
//------------------------------------------------------------------------------
void cspiClass::CspiBufWrt16(LPVOID pBuf, UINT32 data)
{
    UINT16 *p;

    p = (UINT16 *) pBuf;

   *p = (UINT16) data;
}

//------------------------------------------------------------------------------
//
// Function: CspiBufWrt32
//
//      This function is used to access a buffer as an array of 32-bit (UINT32) 
//      values and writes data to the specified buffer location.
//
// Parameters:
//      pBuf
//          [in] Pointer to buffer to which data will be written.
//
//      data
//          [in] Data to be written.
//
// Returns:
//      None.
//
//------------------------------------------------------------------------------
void cspiClass::CspiBufWrt32(LPVOID pBuf, UINT32 data)
{
    UINT32 *p;

    p = (UINT32 *) pBuf;

   *p = data;
}

⌨️ 快捷键说明

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