📄 spi.cpp
字号:
// GPS_SPI_VERSION_MINOR 88
// Options: Enable stats; enable traces; disable debugs; long int-off
// Trace extra int_acks
// All time reporting uses glReportTime().
// Change spiFormatTime() to glFormatTime().
// Add "long int off" during SPI device driver operations.
//
// RESULTS:
//
// Performance is very good - 1-way latency is steady at 72 msec
// Read/Write times are 20 times faster.
// But interrupt off time is high: 251 usec to send 10 bytes.
//
// GPS_SPI_VERSION_MINOR 87
// Report extra int_acks in the stats.
// Fixed ISR time reporting.
// Fixed intack suppression flag bug, and:
// after 25 empty INT_ACKs, give an extra INT_ACK.
//
// RESULTS:
//
// See 2 intack timeouts over a long test period.
// Very efficient use of interrupt/event.
// Very good performance.
//
// GPS_SPI_VERSION_MINOR 86
// Use the last read/write SR if we like it.
// Change trace.cpp
// Suppress extra int_acks.
// Fixed ISR time reporting.
//
// RESULTS:
//
// Works with low latency, Interrupt effectiveness is very good.
// INT_ACK are suppressed
// ISR time results are confusing
// There seems to be a lot more effective timeouts than
// are accounted for in the statistics.
// The SPI_Write() time tracks the inter-write time too
// closely: this is because the inter-write time includes
// the write() time.
// Loses the INTERRUPT after a while.
// GPS_SPI_VERSION_MINOR 85
// Enable stats/disable traces/disable debugs
// Improve ISR reports.
//
// SPI_Write()
// - remove one check: IsBadReadPtr(pBuf, Count)
// - SetLastError(0);
// SPI_Write_Bytes() - change to Sleep(1) when getting size to send.
// SPI_Write_Bytes() use the most recent status if we have a
// status we like. Only read the status if we hate
// what we see (or if we didn't have a status).
// SPI_Read_Bytes() same thing aas SPI_Write_Bytes().
//
// RESULTS:
//
// Works with low latency, but interrupt effectiveness is low.
// Too many INT_ACK.
// ISR timing looks off.
// GPS_SPI_VERSION_MINOR 84
// Enable stats/disable traces/disable debugs
// Improve stats reports.
// Eliminate pause/resume IST.
// Remove retry from SPI_Read().
// Fix totalInterrupts stats
// WORKS!!! VERY WELLLLLLLL !!!!!
// Latency is very low
// Gets an autonomous fix indoors.
// GPS_SPI_VERSION_MINOR 83
// Enable stats/disable traces/disable debugs
// Minor spiFormatTime() changes.
// Major addition to the tracing - added statistics for read/write/intack
// Improve stats reports.
// Works.
// GPS_SPI_VERSION_MINOR 82
// Disable traces.
// Minor spiFormatTime() changes.
// Major addition to the tracing - added statistics for read/write/intack
// Untested
// GPS_SPI_VERSION_MINOR 81
// Traces off.
// Call INTERRUPTS_OFF1() once.
// Report time of a 60 status.
// See a SPI bus interruption problem every few seconds;
// but not all cause the underrun.
// GPS_SPI_VERSION_MINOR 80
// Move the CHIP_ON inside the protected region - for SEND_CMD, etc.
// Call INTERRUPTS_OFF1() twice.
// Unify the polling/interrupt done code.
// Added more interrupt enable commands.
// Appear to be a SPI bus disruption even if interrupts are off.
// GPS_SPI_VERSION_MINOR 79
// Move the CHIP_ON inside the protected region.
// Trace - don't disable upon error.
// Error messages - add more text.
// SPI_IST - use prio 100.
// SPI_XFER - use SPI_IST+2.
// Fewer 0x60 errors, but still have 1.
// More events processed.
// GPS_SPI_VERSION_MINOR 78
// Same as v1.77 except debugs are disabled.
// Works.
// GPS_SPI_VERSION_MINOR 77
// Revive gpsChipsetID.
// Suppress interrupt restore until after GPSCT has decided to start
// waiting (with a timeout) for more activity from the chipset.
// Split the GPS device ID to a separate function.
// Made the SPI done interrupt an option.
// Works.
// GPS_SPI_VERSION_MINOR 76
// Revert to Sleep(1) when waiting for SPI read completion.
// Change speed to 400 KHz (was 128 KHz)
// Works fine.
// GPS_SPI_VERSION_MINOR 75
// Sleep(0) when waiting for SPI read completion.
// Removed dead code.
// Results: sleep(0) made the SPI test very fast, but
// made the UI sluggish.
#define T_LABEL_MACRO(maj,min) _T("#@(#)GpsSpiBulverde ") \
_T(#maj) _T(".") \
_T(#min) _T(" built ") \
_T(__DATE__) _T(" ") \
_T(__TIME__) _T(" ") \
_T(OPT_DONE_MSG) \
_T(OPT_PRIO_MSG) _T(" ") \
_T(OPT_GPIO)
#define LABEL_MACRO(maj,min) "#@(#)GpsSpiBulverde " #maj "." #min \
" built " __DATE__ " " __TIME__ \
" " OPT_DONE_MSG " " OPT_PRIO_MSG " " OPT_GPIO
#define T_GPS_LABEL(maj,min) T_LABEL_MACRO(maj,min)
#define GPS_LABEL(maj,min) LABEL_MACRO(maj,min)
static const TCHAR t_driverLabel[] = {T_GPS_LABEL(GPS_SPI_VERSION_MAJOR,GPS_SPI_VERSION_MINOR)};
const char driverLabel[] = { GPS_LABEL(GPS_SPI_VERSION_MAJOR,GPS_SPI_VERSION_MINOR)};
const char* pDriverLabel = driverLabel;
//-----------------------------------------------------------------------------
// Globals.
//----------------------------------------------------------------------------
#define CACHED_TO_UNCACHED_OFFSET 0x20000000
#define GPIO_OFFSET 0x00E00000
#define SSP3_OFFSET 0x01900000
#define CLK_OFFSET 0x01300000 // Clock Manager
#define OST_OFFSET 0x00A00000 // OS Timer Manager
#define PERIF_BASE_C_VIRTUAL 0x8C000000
#define PERIF_BASE_U_VIRTUAL (PERIF_BASE_C_VIRTUAL + CACHED_TO_UNCACHED_OFFSET)
#define GPIO_BASE_U_VIRTUAL (PERIF_BASE_U_VIRTUAL + GPIO_OFFSET)
#define SSP3_BASE_U_VIRTUAL (PERIF_BASE_U_VIRTUAL + SSP3_OFFSET)
#define CLK_BASE_U_VIRTUAL (PERIF_BASE_U_VIRTUAL + CLK_OFFSET)
#define OST_BASE_U_VIRTUAL (PERIF_BASE_U_VIRTUAL + OST_OFFSET)
volatile XLLP_GPIO_T* v_pGPIORegs = (XLLP_GPIO_T *)GPIO_BASE_U_VIRTUAL;
volatile XLLP_SSP_REGS* v_pSPIRegs = (XLLP_SSP_REGS *)SSP3_BASE_U_VIRTUAL; //gpSsp3hw
volatile XLLP_CLKMGR_T* v_pClockRegs = (XLLP_CLKMGR_T *)CLK_BASE_U_VIRTUAL; //pSpiClock
//-----------------------------------------------------------------------------
// Forward declarations - provided by this device driver.
//-----------------------------------------------------------------------------
static BOOL SPI_AllocReg(SPI_DEVICE_CONTEXT* pDev);
SPI_EXPORT BOOL SPI_Deinit(DWORD hDeviceContext);
static DWORD SPI_Isr(PVOID pArg);
extern bool spiDevClosed;
static void sspConfig(void);
//-----------------------------------------------------------------------------
// Forward declarations - provided by the OS (ceddk.dll?)
//-----------------------------------------------------------------------------
//extern "C" BOOL InterruptInitialize(DWORD gpsIntr,
// HANDLE h, PVOID arg, DWORD param);
/*******************************************************************************
********************************************************************************
**
** Routines to be filled in by the customer
**
** Please fill in these routines.
** In cases where the routines are *not* required, the sample code
** will return the error case.
**
********************************************************************************
*******************************************************************************/
//------------------------------------------------------------------------------
//
// getMsisdn() - not required
//
// There are several possibilities to fill in the MSISDN
// See spiIoctl.h for all the choices.
//
// A BCD example is shown here.
//
// Nothing is needed for initial implementation, but this
// information is required for SUPL support.
//
//------------------------------------------------------------------------------
BOOL Customer_getMsisdnBcd(unsigned char* pBCD)
{
// memcpy(pBCD, Customer_MSISDN_BUFFER, 8);
return false; // fill in the real stuff, please.
}
//------------------------------------------------------------------------------
//
// getCellInfo() - not required
//
//------------------------------------------------------------------------------
BOOL Customer_getCellInfo(GLL_CID* cid)
{
static int CI = 0;
cid->MCC = 1; // fill in the real stuff, please.
cid->MNC = 2;
cid->LAC = 3;
cid->CI = ++CI;
return TRUE; // test purposes only.
}
//------------------------------------------------------------------------------
//
// reallyGoodTime() - not required
//
// For best operation, the customer should provide a seconds counter that:
// a) Is pretty accurate.
// b) Is not changed when the user changes the time.
// c) Is not changed when the user changes the time zone.
// d) Continues counting when the device is turned off.
// e) Starts over at zero when the device is "hard" reset.
//
// There are three choices:
//
// A) Do not provide Customer_reallyGoodTime(). Instead,
// provide time on the GPS device itself. This has hardware and
// system consequences to be discussed with the Global Locate FAE.
// << This is the best choice, and is assumed in this driver >>
//
// B) Do not provide Customer_reallyGoodTime(). Instead,
// allow use of the device time, but beware that time has changed,
// and accept the poor GPS performance. The GpsctService will detect
// the time change, and subsequent position fixes can have poor
// performance.
// << This is the worst choice, and is used only in demonstration
// integrations, not for production. >>
//
// C) Implement Customer_reallyGoodTime().
// << This is also a good choice as it simplifies the hardware and
// software, but can require additional software development by
// the customer. >>
//
//------------------------------------------------------------------------------
DWORD Customer_reallyGoodTime(void)
{
return 0;
}
/*******************************************************************************
********************************************************************************
**
** Device Driver Public Entry Points.
**
** These subroutines satisfy the requirements of the Microsoft
** device driver interface.
**
********************************************************************************
*******************************************************************************/
//-----------------------------------------------------------------------------
//
// SPI_Init()
//
// Init access to the hardware.
// Init access to the ISR.
// Init the ring buffers.
// Resume control of the GPIO.
//
//-----------------------------------------------------------------------------
#ifdef SPI_DONE_INTERRUPT // Use ISR to detect the SPI done
HANDLE ghRxDone = 0;
#endif
SPI_EXPORT DWORD
SPI_Init(LPCTSTR pContext, LPCVOID lpvBusContext)
{
GL_ERROR((TEXT("SPI_Init()/%d %s\n\r"), __LINE__,
t_driverLabel, driverLabel));
// allocate our device context
SPI_DEVICE_CONTEXT* pDev = (SPI_DEVICE_CONTEXT *)malloc(sizeof(SPI_DEVICE_CONTEXT));
pDev->ctor(DEBUG);
//-------------------------------------------------------------------------
// GPIO Configuration
//
// Set the Bulverde GPIO to drive the GPS_PWR_EN signal.
// Set the Bulverde GPIO to accept the GPS interrupt signal.
// Set the Bulverde clock to drive the SSP3 port for SPI.
// - all these things are done by the OS or other device drivers.
//
// You can see the Bulverde CPU Spec. 3-100 to learn about the GPIOs.
//
//-------------------------------------------------------------------------
#ifdef GPS_GPIO_RESET_EXISTS
v_pGPIORegs->GPSR_RESET = GPS_GPIO_RESET_EXISTS;
v_pGPIORegs->GPDR_RESET |= GPS_GPIO_RESET_EXISTS;
GL_PRINT((MSG("GPS Reset Enable!! 0x%x\r\n"),GPS_GPIO_RESET_EXISTS));
Sleep(1);
#endif
#ifdef GPS_GPIO_POWER_EXISTS
v_pGPIORegs->GPSR_POWER = GPS_GPIO_POWER_EXISTS;
v_pGPIORegs->GPDR_POWER |= GPS_GPIO_POWER_EXISTS;
GL_PRINT((MSG("GPS Power Enable!! 0x%x\r\n"),GPS_GPIO_POWER_EXISTS));
Sleep(1);
#endif
#ifdef GPS_GPIO_STANDBY_EXISTS
v_pGPIORegs->GPSR_STANDBY = GPS_GPIO_STANDBY_EXISTS;
v_pGPIORegs->GPDR_STANDBY |= GPS_GPIO_STANDBY_EXISTS;
GL_PRINT((MSG("GPS Power Enable!! 0x%x\r\n"),GPS_GPIO_STANDBY_EXISTS));
#endif
Sleep(10);
//-------------------------------------------------------------------------
// SSP Configuration
//-------------------------------------------------------------------------
sspConfig();
rb__RingBufferInit();
traceInit();
pDev->mbIsrAllow = false;
pDev->mIsrHandle = INVALID_HANDLE_VALUE;
#ifdef _ENABLE_TRACE_
XLLP_OST_T* pOST = (XLLP_OST_T *)OST_BASE_U_VIRTUAL;
pGpsTimer = (volatile DWORD*) &pOST->oscr0;
#endif
//-------------------------------------------------------------------------
//
// ISR Init
//
// 1) The interrupt from Mantaray/Hammerhead to Bulverde is used
// to shorten the HABI poll loop. It is enabled only just before
// the HABI will be sleeping for 100 ms.
//
//-------------------------------------------------------------------------
pDev->intackNeeded = false;
pDev->mIsrHandle = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) SPI_Isr,
(LPVOID)pDev, 0, &pDev->mIsrThreadID);
if (pDev->mIsrHandle == INVALID_HANDLE_VALUE)
{
GL_ERROR((TEXT("SPI_Init()/%d Cannot init gps ISR \n\r"), __LINE__));
SPI_Deinit((DWORD)pDev);
return 0;
}
#ifdef SPI_DONE_INTERRUPT
//-------------------------------------------------------------------------
//
// ISR Init
//
// The interrupt from the Bulverde SPI3 device to the CPU.
// It is used to signal the end of SPI transfers of 3 to 16 bytes.
// 1 or 2 byte transfers are polled directly.
//
//-------------------------------------------------------------------------
pDev->mhRxDone = CreateEvent(NULL, FALSE, FALSE, NULL);
ghRxDone = pDev->mhRxDone;
if (!InterruptInitialize(SYSINTR_SSP3, pDev->mhRxDone, 0, 0))
{
GL_ERROR((TEXT("SPI_Init()/%d Cannot init spi ISR %d\n\r"),
__LINE__, SYSINTR_SSP3));
SPI_Deinit((DWORD)pDev);
return 0;
}
#endif
//-------------------------------------------------------------------------
// GPS Device ID report
//-------------------------------------------------------------------------
// GetGpsDeviceID();
GL_PRINT((MSG("SPI_Init()/%d 0x%x int %d\n\r"),__LINE__, pDev, SYSINTR_GPS));
return (DWORD)pDev;
}
//-----------------------------------------------------------------------------
//
// sspConfig()
//
// Init SSP3 port.
//
//-----------------------------------------------------------------------------
static void
sspConfig(void)
{
v_pClockRegs->cken |= XLLP_CLKEN_SSP3;
v_pClockRegs->oscc |= XLLP_OSCC_TOUT_EN;
v_pSPIRegs->sscr0 = 0x00000000;
// Prior to 1.76:
//v_pSPIRegs->sscr0 = (XLLP_SSCR0_DSS_8BIT | XLLP_SSCR0_SCR_128K | XLLP_SSCR0_RIM | XLLP_SSCR0_TIM);
// Try this with v1.76:
v_pSPIRegs->sscr0 = (XLLP_SSCR0_DSS_8BIT | XLLP_SSCR0_SCR_400K | XLLP_SSCR0_RIM | XLLP_SSCR0_TIM);
v_pSPIRegs->sscr0 &= ~(XLLP_SSCR0_EDSS | XLLP_SSCR0_NCS | XLLP_SSCR0_ECS);
v_pSPIRegs->sscr1 = 0x00000000;
v_pSPIRegs->ssitr = 0x00000000;
v_pSPIRegs->ssto = 0x00001000;
GL_PRINT((MSG("sspConfig()/%d CR1 0x%x\n\r"),__LINE__, v_pSPIRegs->sscr1));
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -