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

📄 gpsdevicedriver.cpp

📁 一个基于windows mobile 的GPS 接受IC 驱动程序。
💻 CPP
📖 第 1 页 / 共 3 页
字号:
        {
            v_pSPIRegs->sscr0 = tmp;
            HW_SPI_WRITE(pSpi, cmd);
            SpiSR = pSpi->ssr;
            TRACE(TR_SPI_SR, SpiSR);
        }
#ifdef  SHORT_INTERRUPT_OFF_TIME
        INTERRUPTS_ON1();            // END CRITICAL REGION    )
#endif
        TRACE(TR_WR_CMD, cmd);
    }

    //-----------------------------------------------------------------
    //
    //  Check for SPI data read (already!)
    //  If there are data so soon, it could indicate the SPI cycle
    //  was terminated early.
    //
    //-----------------------------------------------------------------

    DWORD spiRxFifoCount = 0;
    if (SpiSR & XXLP_SSSP_RNE)
    {
        // The RX fifo is not empty so get the exact count.
        spiRxFifoCount = 1 + (0xF & (SpiSR >> 12));
        TRACE(TR_SW, spiRxFifoCount);

        // What to do now?  We already sent the data, so we
        // can't recover by resending the command!

        // Report the error with a proper timestamp for comparison
        // with GPS performance traces.
        GL_ERROR((TEXT("Spi_Exchange_Bytes(%d) SPI bus interrupted 0x%x %d\r\n")
                , sizeIn, SpiSR, spiRxFifoCount));
    }

    int recovery  = 3000;           // Assume ~3 seconds until "lockup".

#ifdef  FAST_POLL                   // {
    recovery  = 50000;              //    ~5 seconds until "lockup".
#endif                              // }

#ifdef  SPI_DONE_INTERRUPT          // { Use ISR to detect the SPI done

    //-----------------------------------------------------------------
    //
    //  Wait for SPI not busy by waiting for an interrupt.
    //  but if we're only waiting for 2 bytes, just poll.
    //  Remember:  sizeIn + 1 is the actual count because
    //             of the extra command/status byte.
    //
    //      Flags when using the SPI DONE interrupt:
    //
    // #define SPI_DONE_INTERRUPT
    // #undef  SHORT_INTERRUPT_OFF_TIME
    // #define SPI_DONE_POLL()
    // #define FAST_POLL
    //
    //-----------------------------------------------------------------

    if (sizeIn > 2)
    {
#define RFT_MASK (0xF << 10)

        DWORD cr1 = pSpi->sscr1 & ~RFT_MASK;

        //  RFT = Receive Fifo Threshold.
        //
        //  RFT is the number of bytes we want to be interrupted upon
        //  (minus one), so the one we add for the CMD byte is cancelled.
        //
        //  See Bulverde Developer's manual page 8-34 for RFT.
        // cr1 |= ((sizeIn + 1 - 1) << 10);

        cr1 |= (sizeIn << 10);

        // Enable the interrupt (Bulverde SPI hardware overhead)
		// RIE - receiver interrupt enable.
        // TINTE  - timeout interrupt enable (Consider later)
        pSpi->sscr1 = cr1 | XXLP_SSCR1_RIE; // | XLLP_SSCR1_TINTE;

        TRACE(TR_SPI_CMD, cr1 | XXLP_SSCR1_RIE);

#ifndef  SHORT_INTERRUPT_OFF_TIME
        INTERRUPTS_ON1();            // END CRITICAL REGION    )
#endif

        // Wait for the interrupt (or a 3.6 millisecond timeout)
        DWORD obj = WaitForSingleObject(ghRxDone, 2);

        // Disable the interrupt (Bulverde SPI hardware overhead)
        // Notice that RIE was never ORed into cr1, so no need to explicitly
        // remove it here.
        pSpi->sscr1 = cr1;

        // Finish the interrupt (OS overhead)
        InterruptDone(SYSINTR_SSP3);

        //  Get the status register.
        SpiSR = pSpi->ssr;
        TRACE(TR_SPI_SR, SpiSR);

        if (obj == WAIT_OBJECT_0)
        {
            TRACE(TR_SW,cr1);
            recovery = 0;           // All done, no polling needed.
        }
        else
        {
            GL_ERROR((TEXT
                ("SPI_Exchange_Bytes()/%d wait timeout cr1 0x%x sr 0x%x\n\r"),
                                __LINE__, cr1, SpiSR));

            // Interrupt error, so we still need to poll
            //
            // Note:  there will be an un-needed INTERRUPTS_ON1() below
            //        for this recovery case.

            TRACE(TR_SW,cr1);
        }

    }
    // else poll SPI device for done (45 microseconds or less at 400 KHz clock)
    // {
    //      Fall though to do a fast poll for done.
    // }

#endif                  // }

    //---------------------------------------------------------------------
    //  Wait for SPI not busy by polling
    //---------------------------------------------------------------------

    if (recovery)
    {
        while (true)
        {
            if (!HW_SPI_BUSY(SpiSR))
            {
                break;
            }
            if (--recovery < 0)
            {
                TRACE(TR_SW, timeGetTime());
                // Deinit the device??
                break;
            }
            SPI_DONE_POLL();
            SpiSR = pSpi->ssr;
            TRACE(TR_SPI_SR, SpiSR);
        }
#ifndef  SHORT_INTERRUPT_OFF_TIME
        INTERRUPTS_ON1();            // END CRITICAL REGION    )
#endif
    }

    //---------------------------------------------------------------------
    //  Compute the number of characters received and in the SPI hardware
    //---------------------------------------------------------------------

    spiRxFifoCount = 0;
    if (SpiSR & XXLP_SSSP_RNE)
    {
        // The RX fifo is not empty so get the exact count.
        spiRxFifoCount = 1 + (0xF & (SpiSR >> 12));
        TRACE(TR_SW, spiRxFifoCount);
    }

    //-----------------------------------------------------------------
    //  Read the GPS status word from the Bulverde SPI FIFO
    //-----------------------------------------------------------------

    UINT8 sr = 0x20;
    if (spiRxFifoCount)
    {
        sr = HW_SPI_READ(pSpi);
        TRACE(TR_RD_STATUS, sr);
        --spiRxFifoCount;
    }

    if (sizeIn != spiRxFifoCount)
    {
        TRACE(TR_SW, (spiRxFifoCount << 16) | sizeIn);
        if (spiRxFifoCount < sizeIn)
        {
            sizeIn = spiRxFifoCount;
        }
    }

    //-----------------------------------------------------------------
    //  Read all the data from the Bulverde SPI FIFO
    //-----------------------------------------------------------------

    UINT8* pOutOrig = pOut;
    UINT8* pOutEnd  = pOut + sizeIn;
    for (; pOut < pOutEnd; ++pOut)
    {
        *pOut = HW_SPI_READ(pSpi);
    }
#ifdef  ENABLE_TRACE        // {
    for (pOut = pOutOrig; pOut < pOutEnd; ++pOut)
    {
        TRACE(TR_RD_DATA, *pOut);
    }
#endif                      // }

    HW_CHIP_SELECT_OFF();
	TRACE(TR_SW, sizeIn);

    if (origSizeIn && (sizeIn == 0))
    {
        GL_ERROR((TEXT("SPI_Exchange_Bytes()/%d origSizeIn %d sizeIn %d\n\r"),
                            __LINE__, origSizeIn, sizeIn));
        traceDump(false);
    }
    return sr;
}

//-----------------------------------------------------------------------------
//
//      SPI_Write_Control()
//
//  Send one control code to the GL-20000.
//  This is a write(0x00) followed by write(control code).
//
//-----------------------------------------------------------------------------

static void
SPI_Write_Control(UINT8 ControlCode)
{
    if (spiDevClosed)
    {
        GL_ERROR((TEXT("SPI_Write_Control(%x)/%d closed\r\n"),
                                                    ControlCode, __LINE__));
        return;
    }
    UINT8 bytes[1];
    UINT8 dummy[1];
    bytes[0] = ControlCode;

    DWORD xfer = sizeof(bytes);
	UINT8 sr = SPI_Exchange_Bytes(GL_SPI_WRITE_CONTROL, bytes, dummy, xfer);
	GL_PRINT((MSG("SPI_Write_Control(0x%x) sr %x %d\r\n"),
                                                    ControlCode, sr, xfer));
    lastReadSR  = SET_SR(sr);
    lastWriteSR = lastReadSR;
}

//------------------------------------------------------------------------------
//
// Name:   SPI_ErrorCondition()
//    
// Input:
//
// Output:
//
//------------------------------------------------------------------------------

void SPI_ErrorCondition(UINT8 sr)
{
    if (sr & GL_SR_TERR)        // Transmitter underrun
    {
        SPI_Write_Control(GL_CR_TERR + GL_CR_TMASK);
        ++uiGpsSpiUnderRunErrors;
        GL_ERROR((TEXT("SpiGps: MR-->Bulverde underrun 0x%x (extra Bulverde read)\r\n"), sr));
    }  
    if (sr & GL_SR_RERR)	    //	Receiver overrun
    {
        SPI_Write_Control(GL_CR_RERR + GL_CR_TMASK);
        ++uiGpsSpiOverRunErrors;
        GL_ERROR((TEXT("SpiGps: Bulverde-->MR overrun 0x%x (extra Bulverde write)\r\n"), sr));
    }
    lastReadSR  = 0;
    lastWriteSR = 0;
    Sleep(10);
}

//------------------------------------------------------------------------------
//
// Name:   SPI_Write_Bytes
//    
//    Send bytes to the SPI.
//
// Input:
//       const UINT8* pcBuff   [in] Pointer to array to be written to 
//                                  the SPI.
//       sMaxSize              [in] Size of the array     
//
// Output:
//       On successful completion, Number of Bytes Written. 
//       0 - If the SPI_Write_Bytes call is not succesfull
//
//------------------------------------------------------------------------------

static DWORD
SPI_Write_Bytes(const UINT8 *pcBuff, DWORD sMaxSize)
{
    bool needDump = false;
    bool closeTrace = true;
    DWORD nWritten = 0;
	UINT8 sr;

    while (sMaxSize > 0)
	{ 
        int TimeOut_Count = 2;

        //  Wait for the SPI device to be ready.
        //  Toggle chip select between attempts.
        //
        //  Need to validate and possibly change these values.

        while (TRUE)
        {
            DWORD xfer = 0;

            if (lastWriteSR && (lastWriteSR & GL_SR_REMPTY))
            {
                // Use the last SR if we like it.
                sr = static_cast<UINT8> (lastWriteSR);
                lastWriteSR = 0;
            }
            else
            {
                sr = SPI_Exchange_Bytes(GL_SPI_READ_STATUS,  0, 0, xfer);   
                lastReadSR = SET_SR(sr);
            }

            if (sr & (GL_SR_TERR | GL_SR_RERR))
            {
                SPI_ErrorCondition(sr);
                needDump = true;
                GL_ERROR((TEXT("SPI_Write_Bytes()/%d sr 0x%x\n\r"),
                            __LINE__, sr));
                continue;
            }
            if (sr & GL_SR_REMPTY)
            {
                break;      // We can send now, so break
            }
			if (--TimeOut_Count < 0)
			{
                TRACE_TIME();
                goto exitWrite;
			}
			Sleep(1);
		}

        //  Send some bytes.  Send maximum of 18 at a time due to the 
        //  receive FIFO depth of the GL GPS chips.
        //
        //  Then loop to check for empty one more time.

        DWORD iWrite = sMaxSize;
        if (iWrite > GL_RX_FIFO_DEPTH)
        {
            iWrite = GL_RX_FIFO_DEPTH;
        }
        UINT8 dummyRead[GL_RX_FIFO_DEPTH];

        sr = SPI_Exchange_Bytes(GL_SPI_WRITE_DATA, pcBuff, dummyRead, iWrite);
        lastReadSR = SET_SR(sr);

        pcBuff   += iWrite;
        sMaxSize -= iWrite;
        nWritten += iWrite;
	}

exitWrite:

	GL_PRINT((MSG("SPI_Write_Bytes(%d) wrote %d\r\n"), sMaxSize, nWritten));

    if (needDump) traceDump(closeTrace);

	return nWritten;   
}

//------------------------------------------------------------------------------
//
// Name:   SPI_Read_Bytes
//    
//    Read up to 18 bytes from the SPI FIFO.
//    Toggle chip select appropriately.
//    Wait for <timeout> milliseconds for data.
//
// Input:
//       char* pcBuff -    [out] Pointer to array to be filled with data from 
//                               the SPI.
//       sMaxSize     -    [in] Size of the array     
//
// Returns:
//      > 0 - number of bytes read. 
//        0 - read nothing
//
//------------------------------------------------------------------------------

static DWORD
SPI_Read_Bytes(UINT8* pBuff, DWORD sMaxSize)
{
    DWORD xfer = 0;
    UINT8 sr;

    if (lastReadSR && (lastReadSR & GL_SR_TCNT))
    {
        // Use the last SR if we like it.
        sr = static_cast<UINT8> (lastReadSR);
        lastReadSR = 0;
    }
    else
    {

⌨️ 快捷键说明

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