📄 spi.cpp
字号:
//-----------------------------------------------------------------------------
//
// SPI_Deinit()
//
// Set the GPIO to the lowest GPS power level.
// Set the GPIO to the lowest GPIO power level.
// Set the SPI to the lowest SPI power level.
// Deinit the ring buffers.
// Deinit access to the ISR.
// Deinit access to the hardware.
//
//-----------------------------------------------------------------------------
SPI_EXPORT BOOL
SPI_Deinit(DWORD hDeviceContext)
{
GL_PRINT((MSG("SPI_Deinit(0x%x)/%d\n\r"),hDeviceContext,__LINE__));
SPI_DEVICE_CONTEXT* pDev = getSpiDeviceContext(hDeviceContext);
// Deinit the Isr
SuspendThread(pDev->mIsrHandle);
TerminateThread(pDev->mIsrHandle,0);
// TODO: do we need to CloseHandle() these???
pDev->mIsrHandle = INVALID_HANDLE_VALUE;
pDev->mhRxDone = INVALID_HANDLE_VALUE;
if (pDev->v_pGPIORegs)
{
pDev->v_pGPIORegs = NULL;
}
if (pDev->v_pSPIRegs)
{
pDev->v_pSPIRegs = NULL;
}
if (pDev->v_pClockRegs)
{
pDev->v_pClockRegs->cken &= ~XLLP_CLKEN_SSP3;
pDev->v_pClockRegs = NULL;
}
free(pDev);
GL_PRINT((MSG("SPI_Deinit()/%d\n\r"),__LINE__));
return TRUE;
}
//-----------------------------------------------------------------------------
//
// SPI_Open()
//
// Flush the ring buffers.
// Don't touch GPIO.
// Allow writing and reading.
// Enable the interrupt.
//
//-----------------------------------------------------------------------------
SPI_EXPORT DWORD
SPI_Open(DWORD hDeviceContext, DWORD AccessCode, DWORD ShareMode)
{
// GL_PRINT((TEXT("SPI_Open()/%d %s\n\r"), __LINE__, t_driverLabel));
GL_ERROR((TEXT("SPI_Open()/%d %s\n\r"),
__LINE__, t_driverLabel));
SPI_DEVICE_CONTEXT* pDev = getSpiDeviceContext(hDeviceContext);
pDev->mbSignaledPower = false;
pDev->mbClosed = false;
spiDevClosed = false;
// clockSsp3Enable(); // TODO - add protection.
ResumeThread(pDev->mIsrHandle);
traceResume();
pDev->closeTime_ = 0;
pDev->openTime_ = *pGpsTimer;
return (DWORD)pDev;
}
//-----------------------------------------------------------------------------
//
// SPI_Close()
//
// Flush the ring buffers.
//
//-----------------------------------------------------------------------------
SPI_EXPORT BOOL
SPI_Close(DWORD hOpenContext)
{
// Use GL_PRINT when testing with SPI_TEST.
GL_PRINT((TEXT("SPI_Close()/%d %s\n\r"), __LINE__, t_driverLabel));
// Use GL_ERROR normally.
GL_ERROR((TEXT("SPI_Close()/%d %s\n\r"),
__LINE__, t_driverLabel));
SPI_DEVICE_CONTEXT* pDev = getSpiDeviceContext(hOpenContext);
SuspendThread(pDev->mIsrHandle);
// clockSsp3Disable(); // TODO - add protection.
if (!pDev->closeTime_)
{
pDev->closeTime_ = *pGpsTimer;
}
traceStats(pDev->closeTime_ - pDev->openTime_);
return TRUE;
}
//-----------------------------------------------------------------------------
//
// SPI_PowerUp()
//
//-----------------------------------------------------------------------------
SPI_EXPORT void
SPI_PowerUp(DWORD hDeviceContext)
{
GL_ERROR((TEXT("SPI_PowerUp()/%d\n\r"),__LINE__));
sspConfig();
}
//-----------------------------------------------------------------------------
//
// SPI_PowerDown()
//
// Flush the ring buffers.
// Send the shut-down sequence to the GPS device.
// Ignore all subsequent write calls.
// Return error ERROR_PWR_INT upon reads.
// Disable the interrupt.
// Touch GPIO - set it to the lowest power consumption state.
//
//-----------------------------------------------------------------------------
SPI_EXPORT void
SPI_PowerDown(DWORD hDeviceContext)
{
SPI_DEVICE_CONTEXT* pDev = getSpiDeviceContext(hDeviceContext);
if (!pDev->closeTime_)
{
pDev->closeTime_ = *pGpsTimer;
}
GPS_GPIO_CONTROL control;
control.value = 0;
#ifdef GPS_GPIO_STANDBY_EXISTS // {
// Clear nSTANDBY/POWERON to cause Mantaray/Hammerhead to go into
// low power standby mode.
control.id = GPS_GPIO_STANDBY;
SPI_IOControl(hDeviceContext, GPS_IOCTL_CHIPSET_CONTROL,
reinterpret_cast<const PBYTE> (&control), sizeof(control),
0,0,0);
#endif // } GPS_GPIO_STANDBY_EXISTS
#ifdef GPS_GPIO_POWER_EXISTS // {
// Clear POWER to turn off Mantaray/Hammerhead VDD_CORE power supply.
control.id = GPS_GPIO_POWER;
SPI_IOControl(hDeviceContext, GPS_IOCTL_CHIPSET_CONTROL,
reinterpret_cast<const PBYTE> (&control), sizeof(control),
0,0,0);
#endif // } GPS_GPIO_POWER_EXISTS
rb__RingBufferInit();
pDev->mbClosed = true;
spiDevClosed = true;
GL_ERROR((TEXT("SPI_PowerDown()/%d\n\r"),__LINE__));
}
//-----------------------------------------------------------------------------
//
// SPI_Read()
//
// Read data from the queue.
// If we had a power-down/up, then return ERROR_PWR_INT.
//
//-----------------------------------------------------------------------------
SPI_EXPORT DWORD
SPI_Read(DWORD hOpenContext, LPVOID pBuf, DWORD Count)
{
DWORD startTime = *pGpsTimer;
SPI_DEVICE_CONTEXT* pSpi = getSpiDeviceContext(hOpenContext);
GL_PRINT((MSG("SPI_Read(%d)/%d %d %d {\n\r"),
Count,__LINE__,pSpi->mbClosed,pSpi->mbIsrAllow));
if (pSpi->mbClosed)
{
GL_ERROR((TEXT("SPI_Read()/%d Signal Power %d\n\r"),
__LINE__, pSpi->mbSignaledPower));
if (!pSpi->mbSignaledPower)
{
// This code to send the error result only once isn't needed:
pSpi->mbSignaledPower = true;
// For safety, always return the power interrupted error code
// until the next close/open cycle.
}
SetLastError(ERROR_PWRINT);
return -1;
}
if (!pBuf /*|| !IsBadWritePtr(pBuf, Count)*/)
{
SetLastError(ERROR_INVALID_PARAMETER);
return -1;
}
// SuspendThread(pSpi->mIsrHandle);
SetLastError(0);
#if 1
DWORD result = rb__Dequeue((UINT8 *)pBuf, Count);
#else
DWORD result = 0;
for (int tries = 2; tries > 0; --tries)
{
if (!rb_TestRead())
{
Sleep(10);
continue;
}
result = rb__Dequeue((UINT8 *)pBuf, Count);
if (result) break;
}
#endif
// ResumeThread(pSpi->mIsrHandle);
GL_PRINT((MSG("} SPI_Read()/%d %d\n\r"),__LINE__, result));
STATS_READ(static_cast<unsigned short> (result),*pGpsTimer - startTime);
return result;
}
//-----------------------------------------------------------------------------
//
// SPI_Write()
//
// Write data into the queue.
// If we had a power-down/up - ignore the write quietly.
//
//-----------------------------------------------------------------------------
SPI_EXPORT DWORD
SPI_Write(DWORD hOpenContext, LPCVOID pBuf, DWORD Count)
{
DWORD startTime = *pGpsTimer;
GL_PRINT((MSG("SPI_Write(%d)/%d {\n\r"), Count, __LINE__));
SPI_DEVICE_CONTEXT* pSpi = getSpiDeviceContext(hOpenContext);
SetLastError(0);
if (pSpi->mbClosed)
{
GL_PRINT((MSG("SPI_Write()/%d\n\r"),__LINE__));
return Count; // Quietly ignore all writes.
}
if (!pBuf) // || IsBadReadPtr(pBuf, Count))
{
SetLastError(ERROR_INVALID_PARAMETER);
return -1;
}
// SuspendThread(pSpi->mIsrHandle);
DWORD result = rb__Enqueue((const UINT8 *)pBuf, Count);
// if (!rb_TestRead())
// ResumeThread(pSpi->mIsrHandle);
STATS_WRITE(static_cast<unsigned short> (result),*pGpsTimer - startTime);
return result;
}
//-----------------------------------------------------------------------------
//
// SPI_Seek()
//
//-----------------------------------------------------------------------------
SPI_EXPORT DWORD
SPI_Seek(DWORD hOpenContext, long Amount, WORD Type)
{
GL_PRINT((MSG("SPI_Seek()/%d\n\r"),__LINE__));
SPI_DEVICE_CONTEXT* pSpi = getSpiDeviceContext(hOpenContext);
SetLastError(0);
return Amount;
}
//------------------------------------------------------------------------------
//
// Handy Macros for commonly repeated code.
//
// CASE(name) --> case IOCTL_SERIAL_name: ioctlName = "name"
// CHECK_IN(item) --> make sure pBufIn and lenIn are OK compared to
// sizeof(item)
// CHECK_OUT(item) --> make sure pBufIn, lenIn, and actualOut are OK
// compared to sizeof(item)
// COPY_IN(item) --> copy the pBufIn to item.
// COPY_OUT(item) --> copy the item to pBufIn.
//
//------------------------------------------------------------------------------
#define SET_ERR(e) err = (e); errLine = __LINE__
#define CASE(name) \
case GPS_IOCTL_##name: \
ioctlName = _T(#name)
#define CHECK_IN(item) \
if (sizeof(*item) != dwLenIn) \
{ \
GL_ERROR((TEXT("SPI_IOCTL(%d)/%d inLength. expect %d\n\r"), \
dwLenIn, __LINE__, sizeof(*item))); \
SET_ERR(ERROR_BAD_LENGTH); \
break; \
}
#define CHECK_OUT(item) \
if (dwLenOut < sizeof(*item)) \
{ \
GL_ERROR((TEXT("SPI_IOCTL(%d)/%d outLength. expect %d\n\r"), \
dwLenOut, __LINE__, sizeof(*item))); \
SET_ERR(ERROR_BAD_LENGTH); \
break; \
} \
*pdwActualOut = sizeof(*item)
//-----------------------------------------------------------------------------
//
// SPI_IOControl()
//
// REQUIRED - Set or get GPIO read/write.
// OPTIONAL - MSISDN
// OPTIONAL - CellID
// OPTIONAL - Accurate GPS time
// OPTIONAL - Radio status
// OPTIONAL - Set PowerDown data
//
//-----------------------------------------------------------------------------
SPI_EXPORT BOOL
SPI_IOControl(DWORD hOpenContext, DWORD dwCode,
PBYTE pBufIn, DWORD dwLenIn,
PBYTE pBufOut, DWORD dwLenOut,
PDWORD pdwActualOut)
{
bool printError = true;
int code = (dwCode - GPS_IOCTL_ZERO) >> 2;
if (code <= GPS_INDEX_ZERO || code >= GPS_INDEX_MAX)
{
GL_PRINT((MSG("SPI_IOControl(0x%x,%%x,%d,%%x,%d,%%x)/%d Bad code %d err %d\n 0x%x\r"),
dwCode,
/* pBufIn, */ dwLenIn,
/* pBufOut, */ dwLenOut,
/* pdwActualOut, */
__LINE__,
code, ERROR_INVALID_PARAMETER, GPS_IOCTL_ZERO));
SetLastError(ERROR_INVALID_PARAMETER);
GL_ERROR((TEXT("SPI_IOControl(%x[%d])/%d bad IO code\n\r"),
dwCode, code, __LINE__));
return FALSE;
}
#if 0
// Enable this debug when we start adding new commands.
GL_PRINT((MSG("SPI_IOControl(%d,%x[%d],%x[%d],%x)/%d\n\r"),
code,
pBufIn, dwLenIn,
pBufOut, dwLenOut,
pdwActualOut, __LINE__));
#endif
if (pBufIn && dwLenIn)
{
if (IsBadReadPtr(pBufIn, dwLenIn))
{
SetLastError(ERROR_INVALID_PARAMETER);
GL_ERROR((TEXT("SPI_IOControl(%x[%d])/%d bad pBufIn\n\r"),
pBufIn, dwLenIn, __LINE__));
return -1;
}
}
if (pBufOut && dwLenOut && pdwActualOut)
{
if (IsBadWritePtr(pBufOut, dwLenOut))
{
GL_ERROR((TEXT("SPI_IOControl(%x[%d])/%d bad pBufOut\n\r"),
pBufOut, dwLenOut, __LINE__));
SetLastError(ERROR_INVALID_PARAMETER);
return -1;
}
if (IsBadWritePtr(pdwActualOut, sizeof(DWORD)))
{
GL_ERROR((TEXT("SPI_IOControl(%x[%d])/%d bad pdwActualOut\n\r"),
pdwActualOut, __LINE__));
SetLastError(ERROR_INVALID_PARAMETER);
return -1;
}
}
else if (pBufOut || dwLenOut || pdwActualOut)
{
GL_ERROR((TEXT("SPI_IOControl(%x,%d,%x)/%d missing param\n\r"),
pBufOut, dwLenOut, pdwActualOut, __LINE__));
SetLastError(ERROR_INVALID_PARAMETER);
return -1;
}
SPI_DEVICE_CONTEXT* pSpi = getSpiDeviceContext(hOpenContext);
const TCHAR* ioctlName = _T("unknown");
const TCHAR* structureInName = (pBufIn ) ? _T("unknown") : _T("<null>");
const TCHAR* structureOutName = (pBufOut) ? _T("unknown") : _T("<null>");
DWORD err = 0;
int errLine = 0;
switch(dwCode)
{
CASE(CHIPSET_CONTROL);
{
const GPS_GPIO_CONTROL* gpioIn = (const GPS_GPIO_CONTROL *)pBufIn;
GPS_GPIO_CONTROL* gpioOut = (GPS_GPIO_CONTROL *)pBufOut;
if (pBufIn)
{
CHECK_IN(gpioIn);
structureInName = _T("GPS_GPIO_CONTROL<in>");
}
if (pBufOut)
{
CHECK_OUT(gpioOut);
structureOutName = _T("GPS_GPIO_CONTROL<out>");
}
printError = false;
//----------------------------------------------------------------------
// [required] Set the GPIO.
//----------------------------------------------------------------------
if (pBufIn) switch(gpioIn->id)
{
case GPS_NONE:
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -