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