📄 gpsdevicedriver.cpp
字号:
{
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 + -