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

📄 gpsdevicedriver.cpp

📁 一个基于windows mobile 的GPS 接受IC 驱动程序。
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/*******************************************************************************
 *------------------------------------------------------------------------------
 *      Global Locate Inc.
 *------------------------------------------------------------------------------
 *
 * Copyright 2004, 2005, 2006 by GlobalLocate Inc. All Rights Reserved.
 * This file contains company confidential and proprietary information.
 * This information may not be disclosed to any unauthorized individual.
 *
 *------------------------------------------------------------------------------
 *
 * NAME:            GpsDeviceDriver.cpp
 *
 * DESCRIPTION:     GpsDeviceDriver using SPI.
 *
 * NOTES:
 *------------------------------------------------------------------------------
 *
 ******************************************************************************/

#include "stdafx.h"
#include "trace.h"
#include <windows.h>
#include <ceddk.h>
#include "xllp_gpio.h"
#include "xllp_ssp.h"
#include "cust_debug.h"
#include "gpsDeviceDriver.h"
#include "spiDriver.h"
#include <pkfuncs.h>

//------------------------------------------------------------------------------
//
//      Types
//
//------------------------------------------------------------------------------

// typedef unsigned char     UINT8;
// typedef unsigned short    UINT16;
// typedef unsigned long int UINT32;
// typedef UINT32            DWORD;

extern volatile XLLP_GPIO_T *v_pGPIORegs;

#ifdef SPI_DONE_INTERRUPT          // Use ISR to detect the SPI done
extern HANDLE ghRxDone;
#endif

//  See below for a description of how this structure is used.

typedef struct RingBuffer
{
    unsigned char* pHead;
    unsigned char* pTail;
    unsigned char* pEnd;
    unsigned char  rb[2048];
    char* name;
} RingBuffer;

#define BIT(b)      (1L << (b))

static DWORD lastReadSR  = 0;
static DWORD lastWriteSR = 0;
#define SET_SR(sr)  (static_cast<DWORD> (sr) | BIT(31))

bool spiDevClosed;

//------------------------------------------------------------------------------
//
//          Customer Configuration.
//
//  The run-time environment must define three customer interfaces:
//  1)  SPI hardware
//  2)  Debug and logging
//  3)  OS interfaces
//
//------------------------------------------------------------------------------

#include "cust_debug.h"             // debug environment
#include "cust_os.h"                // OS environment
#include "cust_hw_spi.h"            // SPI hardware

//------------------------------------------------------------------------------
//
//          Data
//
//  Globals are:
//      uiGpsSpiUnderRunErrors - error count
//      uiGpsSpiOverRunErrors  - error count
//
//------------------------------------------------------------------------------

unsigned int uiGpsSpiUnderRunErrors;
unsigned int uiGpsSpiOverRunErrors;

static RingBuffer Orb;      // output ring buffer
static RingBuffer Irb;      // input  ring buffer
static UINT8 desiredMask;   // next  copy of the control register.
static UINT8 currentMask;   // local copy of the control register.

#include "gpsSerialControl.h"

/*******************************************************************************
 *
 *          Ring Buffer Procedures
 *
 *  Low-level details about the ring buffers.
 *
 ******************************************************************************/

//------------------------------------------------------------------------------
//
//          Ring Buffer Structure
//
//  We put data into the ring buffer at the HEAD and remove data from the TAIL.
//  Empty is when HEAD == TAIL.
//  The ring buffer is 4K.
//
//  Some illustrations of the HEAD and TAIL for various cases:
//  
//  Empty Ring Buffer:
//  +----------------------------------------------------------+
//  |          _                                               |
//  +----------------------------------------------------------+
//   ^         ^                                                ^
//   |         |                                                |
//   rb        rbTail                                       rbEnd
//             ^
//             |
//             rbHead
//
//  
//  Partially filled Ring Buffer:
//  +----------------------------------------------------------+
//  |          AXXXXXXXXXXXXXXXX_                              |
//  +----------------------------------------------------------+
//   ^         ^                ^                               ^
//   |         |                |                               |
//   rb        rbTail           rbHead                      rbEnd
//
//  
//  Another partially filled Ring Buffer:
//  +----------------------------------------------------------+
//  |XXXXXXXXXX_                AXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX|
//  +----------------------------------------------------------+
//   ^         ^                ^                               ^
//   |         |                |                               |
//   rb        rbHead           rbTail                      rbEnd
//
//  
//  Another partially filled Ring Buffer:
//  +----------------------------------------------------------+
//  |_                          AXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX|
//  +----------------------------------------------------------+
//   ^                          ^                               ^
//   | \                        |                               |
//   | rbHead                   rbTail                      rbEnd
//  rb
//
//  
//  Filled Ring Buffer:
//  +----------------------------------------------------------+
//  |XXXXXXXXXXXXXXXXX0AXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX|
//  +----------------------------------------------------------+
//   ^                ^^                                        ^
//   |                ||                                        |
//   rb         rbHead  rbTail                              rbEnd
//
//      A denotes the next byte to be removed from the ring buffer.
//      X denotes the other bytes in the ring buffer.
//      _ denotes the location of the next byte to be put into the ring buffer.
//      0 denotes a byte that won't ever be filled.
//
//------------------------------------------------------------------------------

static void
rb__RingBuffer(RingBuffer* pThis, char* pName)
{
    pThis->name  = pName;
    pThis->pHead = pThis->rb;
    pThis->pTail = pThis->rb;
    pThis->pEnd  = pThis->rb + sizeof(pThis->rb);
}

//------------------------------------------------------------------------------
//  Compute the count of contiguous bytes in the rb starting at
//  the tail.  This is not the total data bytes in the rb.
//------------------------------------------------------------------------------

static int
rb__readByteCount(RingBuffer* pThis)
{
    if (pThis->pHead >= pThis->pTail)
    {
        return pThis->pHead - pThis->pTail;
    }
    return pThis->pEnd - pThis->pTail;
}

//------------------------------------------------------------------------------
//  Compute the total count of all bytes in the rb.
//------------------------------------------------------------------------------

static int
rb__readTotalByteCount(RingBuffer* pThis)
{
    if (pThis->pTail <= pThis->pHead)
    {
        return pThis->pHead - pThis->pTail;
    }
    return (pThis->pEnd - pThis->pTail) + (pThis->pHead - pThis->rb);
}

//------------------------------------------------------------------------------
//  Compute the space remaining to the end of the rb.
//  This is not the total free space in the rb.
//------------------------------------------------------------------------------

static int
rb__writeByteCount(RingBuffer* pThis)
{
    if (pThis->pHead < pThis->pTail)
    {
        return pThis->pTail - pThis->pHead - 1;
    }
    int result = pThis->pEnd - pThis->pHead;
    if (pThis->pTail == pThis->rb)
    {
        --result;
    }
    return result;
}

//------------------------------------------------------------------------------
//  We have written some bytes into the RB,
//  so bump pointers & counters, etc.
//------------------------------------------------------------------------------

static void
rb__haveWrittenBytes(RingBuffer* pThis, int nBytes)
{
    pThis->pHead += nBytes;
    ASSERT(pThis->pHead <= pThis->pEnd);
    if (pThis->pHead == pThis->pEnd)
    {
        pThis->pHead = pThis->rb;
    }
}

//------------------------------------------------------------------------------
//  We have read some bytes from the RB,
//  so bump pointers & counters, etc.
//------------------------------------------------------------------------------

static void
rb__haveReadBytes(RingBuffer* pThis, int nBytes)
{
    pThis->pTail += nBytes;
    ASSERT(pThis->pTail <= pThis->pEnd);
    if (pThis->pTail == pThis->pEnd)
    {
        pThis->pTail = pThis->rb;
    }
}

/*******************************************************************************
 *
 *          S P I    L a y e r
 *
 *  The next few procedures with names "SPI_<name>" touch the SPI hardware.
 *
 *  The main algorithm to poll for data, send GL controls, write data,
 *  and handle errors is made clear here.
 *
 *  If your SPI hardware has DMA support, a deep FIFO, etc., then these
 *  routines will need extensive changes.
 *
 ******************************************************************************/

//  OAL/Nkintr.h and link with Nk.lib contains these assembly functions.
//  For GL, they are packaged into cpregXsc2.obj.

extern "C" void INTERRUPTS_ON1(void);
extern "C" void INTERRUPTS_OFF1(void);

#if 0       // { see interrupt.s for this:
asm_interrupt_off()
{
    LEAF_ENTRY INTERRUPTS_OFF

    mrs r0, cpsr
    bic r1,r0,#0x80
    msr cpsr, r1

    RETURN
}

asm_interrupt_on()
{
    LEAF_ENTRY INTERRUPTS_OFF

    mrs r0, cpsr
    orr r1,r0,#0x80
    msr cpsr, r1

    RETURN
}
#endif      // }

//----------------------------------------------------------------------------
//
//      SPI_Exchange_Bytes()
//
//  Send a command and N bytes of data to the SPI port.
//  Return the first byte read from the SPI port at the same time.
//  Fill the buffer with the data we read.
//
//  Set sizeIn to the amount of data actually transferred.
//  If the SPI bus transaction is prematurely terminated, then
//  sizeIn will be less than requested.
//
//  NOTE:  Tune this subroutine for maximum performance, as
//         it is the core of the SPI driver.  Specifically:
//  1)  Use register variables.
//  2)  Remove as many debugs as possible.
//  3)  Tune the OS_WAIT_US(10) value.
//
//----------------------------------------------------------------------------

UINT8
SPI_Exchange_Bytes(UINT8 cmd, const UINT8* pIn, UINT8* pOut, DWORD& sizeIn)
{
    DWORD origSizeIn = sizeIn;
    if (sizeIn > 15) sizeIn = 15;       // limit ourselves to 1 FIFO of data.
	TRACE(TR_SW, sizeIn);

    DWORD SpiSR;
    HW_SPI_TYPE pSpi = HW_SPI_PTR;

    //--------------------------------------------------------------
    //
    //      Send all the data.
    //
    //--------------------------------------------------------------

    bool sentCmd = false;
    if (sizeIn > 0)
    {
        SpiSR = pSpi->ssr;
        TRACE(TR_SPI_SR, SpiSR);

        if (!(SpiSR & XXLP_SSSP_TNF))
        {
            TRACE(TR_SW, SpiSR);            // Error!
        }
        else // transmit fifo NOT full
        {
            sentCmd = true;

            // Transmitter is not full - compute the number of bytes
            // we can send (plues one for the GPS command byte).
            DWORD txSpace = 16 - ((SpiSR >> 8) & 0xF);
            if (txSpace < (1+sizeIn))
            {
                sizeIn = txSpace-1;
            }
            // else if (sizeIn < txSpace) just xfer sizeIn

            const UINT8* pInOrig = pIn;
            const UINT8* pInEnd  = pIn  + sizeIn;

            //  This code is the same as HW_CHIP_SELECT_ON(), except
            //  that the interrupts are turned off before we do
            //  the write to the SPI register.
            //  The trace is done before the interrupts are off.

            DWORD tmp = v_pSPIRegs->sscr0 | XLLP_SSCR0_SSE;
            TRACE(TR_SPI_CMD, tmp);
            INTERRUPTS_OFF1();           // BEGIN CRITICAL REGION  (((
            {
                v_pSPIRegs->sscr0 = tmp;
                HW_SPI_WRITE(pSpi, cmd);
                for (; pIn < pInEnd; ++pIn)
                {
                    HW_SPI_WRITE(pSpi, *pIn);
                }
                SpiSR = pSpi->ssr;
            }
#ifdef  SHORT_INTERRUPT_OFF_TIME
            INTERRUPTS_ON1();            // END CRITICAL REGION    )
#endif

#ifdef  ENABLE_TRACE        // {
            TRACE(TR_WR_CMD, cmd);
            for (pIn = pInOrig; pIn < pInEnd; ++pIn)
            {
                TRACE(TR_WR_DATA, *pIn);
            }
            TRACE(TR_SPI_SR, SpiSR);
#endif                      // }
        }
    }

    if (!sentCmd)
    {
        sizeIn = 0;
        DWORD tmp = v_pSPIRegs->sscr0 | XLLP_SSCR0_SSE;
        TRACE(TR_SPI_CMD, tmp);
        INTERRUPTS_OFF1();           // BEGIN CRITICAL REGION  (

⌨️ 快捷键说明

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