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

📄 gpsdevicedriver.cpp

📁 一个基于windows mobile 的GPS 接受IC 驱动程序。
💻 CPP
📖 第 1 页 / 共 3 页
字号:
        sr = SPI_Exchange_Bytes(GL_SPI_READ_STATUS,  0, 0, xfer);   
        lastWriteSR = SET_SR(sr);
    }

    bool needDump   = false;
    bool closeTrace = true;

	if (sr & (GL_SR_TERR | GL_SR_RERR))
    {
        SPI_ErrorCondition(sr);
        GL_ERROR((TEXT("SPI_Read_Bytes()/%d sr 0x%x\n\r"), __LINE__, sr));
        needDump = true;
    }

    //	Transmitter FIFO byte count can be 0..18 bytes ready to be read.
	DWORD txCount = (sr & GL_SR_TCNT);

    if (txCount)
    {
        if (txCount > sMaxSize)
        {
            txCount = sMaxSize;
        }
        static UINT8 dummyWrite[GL_RX_FIFO_DEPTH] = {0};
        sr = SPI_Exchange_Bytes(GL_SPI_READ_DATA, dummyWrite, pBuff, txCount);
        lastWriteSR = SET_SR(sr);
    }

    if (txCount)
    {
        GL_PRINT((MSG("SPI_Read_Bytes(%d) sr %x read %d "),
                                                    sMaxSize, sr, txCount));
        GL_DEBUG_PACKET(_T("SPI-->rb"), pBuff, txCount);
    }
    if (needDump)
    {
        traceDump(closeTrace);
    }
    return txCount;
}


//------------------------------------------------------------------------------
//
//  Dump a buffer.
//  of the SPI ring buffer driver.
//
//------------------------------------------------------------------------------

#ifdef DEBUG_GPS_DRIVER
void
gl_debug_dump(int line, const TCHAR* msg, const UINT8* pData, int iSize)
{
    int iShow = iSize;
    if (iShow > 64) iShow = 64;

    const UINT8* pEnd = pData + iShow;
    GL_PRINT((MSG("Line %d %s 0x%x[%d]:\n\r"), line, msg, pData, iSize));

    while (pData < pEnd)
    {
        const UINT8* pLineEnd = pData;
        int iDump = (pEnd - pData);
        if (iDump > 16) iDump = 16;
        
        for (pLineEnd += iDump; pData < pLineEnd; ++pData)
        {
            GL_PRINT((MSG("%02x  "), 0xFF & *pData));
        }
        GL_PRINT((MSG("\n\r")));
    }
    if (iShow != iSize) GL_PRINT((MSG("...\n\r")));
}
#endif


/*******************************************************************************
 *
 *          R i n g   B u f f e r     L a y e r
 *
 *  The next few procedures named "rb__<name>"
 *  use the ring buffers to manage the different data transfer rates and
 *  buffer sizes between the SPI hardware (usually 1 byte) and GL IC (18
 *  bytes) and what the GLL and HAL expects (arbitrary sizes, up to 700
 *  bytes).
 *
 *  Externally callable routines are:
 *
 *      rb__Enqueue() - send data to the GPS chip.
 *      rb__Dequeue() - read data from the GPS chip.
 *      rb__InterruptOperate() - allows an interrupt service routine
 *          to expedite transfer of data.  [optional]
 *      rb__RingBufferInit() - must be called once at the start.
 *
 ******************************************************************************/

//------------------------------------------------------------------------------
//
//          Read From Device
//
//  Reads bytes from the SPI device.
//  Write the bytes into a RingBuffer.
//  If we get a power fail, return ERROR_PWRINT to the GPSCT.
//
//------------------------------------------------------------------------------

unsigned int
rb__ReadFromDevice(void)
{
    RingBuffer* pThis = &Irb;

    int rSize;
    unsigned int result = 0;

    while (rSize = rb__writeByteCount(pThis))
    {
        //  Read data from SPI into the ring buffer
        unsigned long nBytes = SPI_Read_Bytes(pThis->pHead, rSize);
        if (!nBytes)
        {
            break;
        }
        rb__haveWrittenBytes(pThis, nBytes);
        result += nBytes;
    }
    return result;
}

//------------------------------------------------------------------------------
//
//          Write to Device
//
//  Writes bytes to the SPI device.
//  Read the bytes from a RingBuffer.
//
//------------------------------------------------------------------------------

static unsigned int
rb__WriteToDevice(void)
{
    RingBuffer*  pThis   = &Orb;
    unsigned int iTotal = 0;
    DWORD wSize;

    //  While we have data to read from the ring buffer
    while (wSize = rb__readByteCount(pThis))
    {
        DWORD nWritten = SPI_Write_Bytes(pThis->pTail, wSize);
        if (!nWritten)
        {
            break;      // Stop when the SPI can't take more.
        }
        GL_DEBUG_PACKET(_T("rb-->SPI"), pThis->pTail, nWritten);
        rb__haveReadBytes(pThis, nWritten);
        iTotal += nWritten;
    }
    return iTotal;
}

//------------------------------------------------------------------------------
//
//          RingBuffer Receive Interrupt Mask
//
//  If we have outgoing data that hasn't been sent, enable the RxInterrupt
//  of the GPS chip (the CPU will receive nINTR from the GPS chip
//  when the GPS chip can accept more SPI data).
//
//------------------------------------------------------------------------------

static void
rb__ReceiveInterruptMask(void)
{
    if (rb__readByteCount(&Orb))
    {
        desiredMask |=  GL_CR_RMASK;
    }
    else
    {
        desiredMask &= ~GL_CR_RMASK;
    }
    if (currentMask != desiredMask)
    {
        SPI_Write_Control(desiredMask);
        currentMask = desiredMask;
    }
}

//------------------------------------------------------------------------------
//
//          RingBuffer Operate
//
//  rb__Operate() reads data from the device driver into the
//  receive queue and sends data from the transmit queue to the device.
//
//  Continue reading and writing until there is no more work to do.
//
//  Return the number of bytes read from the GPS chip.
//
//------------------------------------------------------------------------------

unsigned long int
rb__Operate(void)
{
    unsigned int uRead;
    unsigned int uWrite;
    unsigned int uResult = 0;

    do
    {
        uRead    = rb__ReadFromDevice();
        uWrite   = rb__WriteToDevice ();
        uResult += uRead;
    } while (uRead + uWrite);

    rb__ReceiveInterruptMask();

    return uResult;
}

//------------------------------------------------------------------------------
//
//          Read From Input Ring Buffer.
//
//  This is a main invocation point from outside this file.c
//
//------------------------------------------------------------------------------

int
rb__Dequeue(UINT8* pBuf, int iReadMax)
{
#ifdef INCREASE_SPI_PRIORITY
    HANDLE me  = GetCurrentThread();
    int    pri = GetThreadPriority(me);
    CeSetThreadPriority(me, THREAD_PRIORITY_SPI_XFER);
#endif

    unsigned long iRead = 0;
    int copySize = 0;

    OS_SPI_INTR_OFF();
    rb__Operate();
    for (; iReadMax > 0; iReadMax -= copySize)
    {
        //  Compute the amount of data in contiguous part of the ring buffer
        int rSize = rb__readByteCount(&Irb);

        if (rSize <= 0)
        {
            break;
        }

        //  Read data from the ring buffer (if we have space)
        copySize = iReadMax;
        if (rSize < iReadMax)
        {
            copySize = rSize;
        }
        memcpy(pBuf, Irb.pTail, copySize);
        rb__haveReadBytes(&Irb, copySize);
        pBuf  += copySize;
        iRead += copySize;
    }
    OS_SPI_INTR_ON();
#ifdef INCREASE_SPI_PRIORITY
    CeSetThreadPriority(me, pri);
#endif
    return iRead;
}

//------------------------------------------------------------------------------
//
//      Write -- send data to the GPS device
//
//  Send data directly to the device.
//  Only needed when bypassing the queueing or at power-down.
//
//------------------------------------------------------------------------------

int
rb__WriteDirect(const unsigned char* pBuf, int nBytes)
{
	DWORD iTotal = 0;
    DWORD nWritten;
    for (; nBytes > 0; nBytes -= nWritten)
    {
        nWritten = SPI_Write_Bytes(pBuf, nBytes);
        if (!nWritten)
        {
            break;      // Stop when the device driver can't take more.
        }
        GL_DEBUG_PACKET(_T("buf-->SPI"), pBuf, nWritten);
        pBuf   += nWritten;
        iTotal += nWritten;
    }
	return iTotal;
}

//------------------------------------------------------------------------------
//
//      Enqueue -- send data to the ring buffer
//
//  If we're optimizing, then don't put the data into the RB if the RB is empty.
//  Instead send it to the device.
//  If the device can't take any more, then put the remaining bytes into the RB.
//  If the RB has any data, then just add the data to the RB.
//
//  When done, signal the main rb__Operate() to attempt to read and
//  write the SPI.  This signal is just a call, protected by the critical
//  section, but could be a true Windows event or some such.
//
//------------------------------------------------------------------------------

int
rb__Enqueue(const unsigned char* pBuf, int nBytes)
{
    int iTotal = 0;
    bool closeTrace = true;
    bool needDump   = false;

#ifdef INCREASE_SPI_PRIORITY
    HANDLE me  = GetCurrentThread();
    int    pri = GetThreadPriority(me);
    CeSetThreadPriority(me, THREAD_PRIORITY_SPI_XFER);
#endif

    OS_SPI_INTR_OFF();

    // If the outgoing queue is empty - write directly to the SPI port.
    if (!rb__readByteCount(&Orb))
    {
    	// NKDbgPrintfW(TEXT("rb_Enqueue is Empty!!\r\n"));
		iTotal  = rb__WriteDirect(pBuf, nBytes);
		pBuf   += iTotal;
		nBytes -= iTotal;
    }

    // If we didn't write everything directly to the SPI port, write
    // the remainder of our data to the queue to send later.
    if (nBytes)
    {
        int rSize;
        for (; nBytes > 0; nBytes -= rSize)
        {
            //  Compute the space remaining to the end of the rb.
            rSize = rb__writeByteCount(&Orb);

            if (rSize <= 0)
            {
				GL_ERROR((TEXT("spiGps: Enqueue: Ring Buffer full  rb full wrote %d   %d remaining\n\r"),
                        iTotal, nBytes));
                needDump = true;
                break;
            }
            if (nBytes < rSize)
            {
                rSize = nBytes;
            }
            memcpy(Orb.pHead, pBuf, rSize);
            rb__haveWrittenBytes(&Orb, rSize);
            pBuf   += rSize;
            iTotal += rSize;
        }
    }
    if ((desiredMask != currentMask) && iTotal)
    {
        rb__ReceiveInterruptMask();
    }
    rb__Operate();

    OS_SPI_INTR_ON();

#ifdef INCREASE_SPI_PRIORITY
    CeSetThreadPriority(me, pri);
#endif

    if (needDump)
    {
        traceDump(closeTrace);
    }
    return iTotal;
}

//------------------------------------------------------------------------------
//
//          RingBuffer Init
//
//------------------------------------------------------------------------------

void
rb__RingBufferInit(void)
{
    rb__RingBuffer(&Irb, "input" );
    rb__RingBuffer(&Orb, "output");
    uiGpsSpiUnderRunErrors = 0;
    uiGpsSpiOverRunErrors  = 0;
    desiredMask = GL_CR_TMASK;
    currentMask = 0;
}

int rb_TestRead(void)
{
    return rb__readTotalByteCount(&Irb);
}

void rb__InterruptEnable(void)
{
    SPI_Write_Control(desiredMask);
}

⌨️ 快捷键说明

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