📄 s3c2410_can.cpp
字号:
/* If we have an interrupt handler thread, kill it */
if ( pSpiHead->pDispatchThread )
{
DEBUGMSG (ZONE_INIT, (TEXT("\r\nTrying to close dispatch thread\r\n")));
/* Set the priority of the dispatch thread to be equal to this one,
* so that it shuts down before we free its memory. If this routine
* has been called from spiDllEntry then RxCharBuffer is set to
* NULL and the dispatch thread is already dead, so just skip the
* code which kills the thread.
*/
priority256 = CeGetThreadPriority(pThisThread);
CeSetThreadPriority(pSpiHead->pDispatchThread, priority256);
/* Signal the Dispatch thread to die.
*/
pSpiHead->KillRxThread = 1;
DEBUGMSG (ZONE_INIT, (TEXT("\r\nTrying to signal spi thread.\r\n")));
SetEvent(pSpiHead->hSpiEvent);
WaitForSingleObject(pSpiHead->hKillDispatchThread, 3000);
Sleep(10);
DEBUGMSG (ZONE_INIT, (TEXT("\r\nTrying to call CloseHandle\r\n")));
CloseHandle(pSpiHead->pDispatchThread);
pSpiHead->pDispatchThread = NULL;
DEBUGMSG (ZONE_INIT, (TEXT("\r\nReturned from CloseHandle\r\n")));
}
/* Ack any remaining interrupts and unregister the event from the
* logical interrupt.
*/
InterruptDone(pSpiHead->dwIntID);
InterruptDisable(pSpiHead->dwIntID);
return(TRUE);
}
/*
@doc INTERNAL
@func BOOL | DllEntry | Process attach/detach api.
*
@rdesc The return is a BOOL, representing success (TRUE) or failure (FALSE).
*/
BOOL
DllEntry(
HINSTANCE hinstDll, /*@parm Instance pointer. */
DWORD dwReason, /*@parm Reason routine is called. */
LPVOID lpReserved /*@parm system parameter. */
)
{
if ( dwReason == DLL_PROCESS_ATTACH )
{
DEBUGREGISTER(hinstDll);
// RETAILMSG(1, (TEXT("spi port process attach\r\n")));
DEBUGMSG (ZONE_INIT, (TEXT("spi port process attach\r\n")));
DisableThreadLibraryCalls((HMODULE) hinstDll);
}
if ( dwReason == DLL_PROCESS_DETACH )
{
// RETAILMSG(1, (TEXT("process detach called\r\n")));
DEBUGMSG (ZONE_INIT, (TEXT("process detach called\r\n")));
}
return(TRUE);
}
// ****************************************************************
//
// @doc EXTERNAL
// @func HANDLE | SPI_INIT | Spi device initialization.
//
// @parm ULONG | Identifier | Port identifier. The device loader
// passes in the registry key that contains information
// about the active device.
//
// @remark This routine is called at device load time in order
// to perform any initialization. Typically the init
// routine does as little as possible, postponing memory
// allocation and device power-on to Open time.
//
// @rdesc Returns a pointer to the spi head which is passed into
// the SPI_OPEN and SPI_DEINIT entry points as a device handle.
//
HANDLE
SPI_Init(
ULONG Identifier
)
{
PHW_INDEP_INFO pSpiHead = NULL;
DWORD DevIndex;
HKEY hKey;
ULONG kreserved = 0, kvaluetype;
ULONG datasize = sizeof(ULONG);
// RETAILMSG(DEBUGMODE, (TEXT("+SPI_Init\r\n")));
DEBUGMSG (ZONE_INIT | ZONE_FUNCTION, (TEXT("+SPI_Init\r\n")));
// Allocate our control structure.
pSpiHead = (PHW_INDEP_INFO)LocalAlloc(LPTR, sizeof(HW_INDEP_INFO));
// Check that LocalAlloc did stuff ok too.
if ( !pSpiHead )
{
DEBUGMSG(ZONE_INIT | ZONE_ERROR,
(TEXT("Error allocating memory for pSpiHead, SPI_Init failed\n\r")));
return(NULL);
}
// Initially, open list is empty.
InitializeListHead( &pSpiHead->OpenList );
InitializeCriticalSection(&(pSpiHead->OpenCS));
pSpiHead->pAccessOwner = NULL;
pSpiHead->fEventMask = 0;
pSpiHead->BaudRate = 125;
// Init CommTimeouts.
pSpiHead->CommTimeouts.ReadIntervalTimeout = READ_TIMEOUT;
pSpiHead->CommTimeouts.ReadTotalTimeoutMultiplier = READ_TIMEOUT_MULTIPLIER;
pSpiHead->CommTimeouts.ReadTotalTimeoutConstant = READ_TIMEOUT_CONSTANT;
pSpiHead->CommTimeouts.WriteTotalTimeoutMultiplier= 0;
pSpiHead->CommTimeouts.WriteTotalTimeoutConstant = 0;
/* Create tx and rx events and stash in global struct field. Check return.
*/
pSpiHead->hSpiEvent = CreateEvent(0, FALSE, FALSE, NULL);
pSpiHead->hKillDispatchThread = CreateEvent(0, FALSE, FALSE, NULL);
pSpiHead->hTransmitEvent = CreateEvent(0, FALSE, FALSE, NULL);
pSpiHead->hReadEvent = CreateEvent(0, FALSE, FALSE, NULL);
if ( !pSpiHead->hSpiEvent || !pSpiHead->hKillDispatchThread ||
!pSpiHead->hTransmitEvent || !pSpiHead->hReadEvent )
{
DEBUGMSG(ZONE_ERROR | ZONE_INIT,
(TEXT("Error creating event, COM_Init failed\n\r")));
LocalFree(pSpiHead);
return(NULL);
}
/* Initialize the critical sections that will guard the parts of
* the receive and transmit buffers.
*/
InitializeCriticalSection(&(pSpiHead->ReceiveCritSec1));
InitializeCriticalSection(&(pSpiHead->TransmitCritSec1));
InitializeCriticalSection(&(pSpiHead->TransmitCritSec));
InitializeCriticalSection(&(pSpiHead->RegCritSec));
/* Want to use the Identifier to do RegOpenKey and RegQueryValue (?)
* to get the index whether to start the
* listening thread or provide the callback.
*/
// RETAILMSG(DEBUGMODE, (TEXT("Try to open %s\r\n"), (LPCTSTR)Identifier));
DEBUGMSG (ZONE_INIT,(TEXT("Try to open %s\r\n"), (LPCTSTR)Identifier));
hKey = OpenDeviceKey((LPCTSTR)Identifier);
if ( !hKey )
{
DEBUGMSG (ZONE_INIT | ZONE_ERROR,
(TEXT("Failed to open devkeypath, SPI_Init failed\r\n")));
LocalFree(pSpiHead);
return(NULL);
}
datasize = sizeof(DWORD);
if ( RegQueryValueEx(hKey, L"DeviceArrayIndex", NULL, &kvaluetype,
(LPBYTE)&DevIndex, &datasize) )
{
DEBUGMSG (ZONE_INIT | ZONE_ERROR,
(TEXT("Failed to get DeviceArrayIndex value, SPI_Init failed\r\n")));
RegCloseKey (hKey);
LocalFree(pSpiHead);
return(NULL);
}
datasize = sizeof(DWORD);
if ( RegQueryValueEx(hKey, L"Priority256", NULL, &kvaluetype,
(LPBYTE)&pSpiHead->Priority256, &datasize) )
{
pSpiHead->Priority256 = DEFAULT_CE_THREAD_PRIORITY;
DEBUGMSG (ZONE_INIT | ZONE_WARN,
(TEXT("Failed to get Priority256 value, defaulting to %d\r\n"),
pSpiHead->Priority256));
}
if ( RegQueryValueEx(hKey, L"SysIntr", NULL, NULL,
(LPBYTE)(&pSpiHead->dwIntID), &datasize) )
{
DEBUGMSG (ZONE_INIT | ZONE_ERROR,
(TEXT("Failed to get SysIntr value, SPI_Init failed\r\n")));
RegCloseKey (hKey);
LocalFree(pSpiHead);
return(NULL);
}
RegCloseKey (hKey);
pSpiHead->dwDevIndex = DevIndex;
DEBUGMSG (ZONE_INIT, (TEXT("DevIndex %X\r\n"), DevIndex));
// RETAILMSG(DEBUGMODE, (TEXT("DevIndex %X Priority256 %d SysIntr %d\r\n"),
// DevIndex, pSpiHead->Priority256, pSpiHead->dwIntID));
if( !SPI_VirtualAlloc() )
{
DEBUGMSG (ZONE_INIT | ZONE_ERROR,
(TEXT("Failed to SPI_VirtualAlloc, SPI_Init failed\r\n")));
LocalFree(pSpiHead);
return(NULL);
}
// pSpiHead->OpenCount = 0;
pSpiHead->fSW_EnTxINT = FALSE;
pSpiHead->RxDiscard = FALSE;
// if(DevIndex == 0)
{
pSpiHead->bEINT = BIT_EINT0;
}
/* else
{
DEBUGMSG (ZONE_INIT | ZONE_ERROR,
(TEXT("Failed to get DeviceArrayIndex value, SPI_Init failed\r\n")));
SPI_Deinit(pSpiHead);
return(NULL);
}*/
DisEnINT(pSpiHead->bEINT);
ClearINTPnd(pSpiHead->bEINT);
// Init rx buffer and buffer length here.
pSpiHead->RxBufferInfo.Length = RX_BUFFER_SIZE;
PUCHAR RxCharBuffer = (PUCHAR)LocalAlloc(LPTR, pSpiHead->RxBufferInfo.Length);
if( !RxCharBuffer )
{
DEBUGMSG (ZONE_INIT | ZONE_ERROR,
(TEXT("Failed to LocalAlloc RxCharBuffer, SPI_Init failed\r\n")));
SPI_Deinit(pSpiHead);
return(NULL);
}
pSpiHead->RxBufferInfo.RxCharBuffer = RxCharBuffer;
InitializeCriticalSection(&(pSpiHead->RxBufferInfo.CS));
InitializeCriticalSection(&(pSpiHead->TxBufferInfo.CS));
DEBUGMSG (ZONE_INIT, (TEXT("RxBuffer init'ed with start at %x\r\n"),
pSpiHead->RxBufferInfo.RxCharBuffer));
if ( ! StartDispatchThread( pSpiHead ) )
{
// Failed on InterruptInitialize or CreateThread. Bail.
SPI_Deinit(pSpiHead);
return(NULL);
}
// RETAILMSG(DEBUGMODE, (TEXT("-SPI_Init 0x%X\r\n"), pSpiHead));
DEBUGMSG (ZONE_INIT | ZONE_FUNCTION, (TEXT("-SPI_Init\r\n")));
return (pSpiHead);
}
/*
@doc EXTERNAL
@func HANDLE | SPI_Open | Spi port driver initialization.
* Description: This routine must be called by the user to open the
* spi device. The HANDLE returned must be used by the application in
* all subsequent calls to the spi driver. This routine starts the thread
* which handles the spi events.
* Exported to users.
*
@rdesc This routine returns a HANDLE representing the device.
*/
HANDLE
SPI_Open(
HANDLE pHead, // @parm Handle returned by SPI_Init.
DWORD AccessCode, // @parm access code.
DWORD ShareMode // @parm share mode - Not used in this driver.
)
{
PHW_INDEP_INFO pSpiHead = (PHW_INDEP_INFO)pHead;
PHW_OPEN_INFO pOpenHead;
BOOL retval = TRUE;
// RETAILMSG(1, (TEXT("+SPI_Open handle x%X, access x%X, share x%X\r\n"),
// pHead, AccessCode, ShareMode));
DEBUGMSG (ZONE_OPEN|ZONE_FUNCTION,
(TEXT("+SPI_Open handle x%X, access x%X, share x%X\r\n"),
pHead, AccessCode, ShareMode));
// Return NULL if SpiInit failed.
if ( !pSpiHead )
{
// RETAILMSG(1, (TEXT("Open attempted on uninited device!\r\n")));
DEBUGMSG (ZONE_OPEN|ZONE_ERROR, (TEXT("Open attempted on uninited device!\r\n")));
SetLastError(ERROR_INVALID_HANDLE);
return(NULL);
}
// Return NULL if opening with access & someone else already has
if ( (AccessCode & (GENERIC_READ | GENERIC_WRITE)) && pSpiHead->pAccessOwner )
{
// RETAILMSG(1, (TEXT("Open requested access %x, handle x%X already has x%X!\r\n"),
// AccessCode, pSpiHead->pAccessOwner,
// pSpiHead->pAccessOwner->AccessCode));
DEBUGMSG (ZONE_OPEN|ZONE_ERROR,
(TEXT("Open requested access %x, handle x%X already has x%X!\r\n"),
AccessCode, pSpiHead->pAccessOwner,
pSpiHead->pAccessOwner->AccessCode));
SetLastError(ERROR_INVALID_ACCESS);
return(NULL);
}
// OK, lets allocate an open structure
pOpenHead = (PHW_OPEN_INFO)LocalAlloc(LPTR, sizeof(HW_OPEN_INFO));
if ( !pOpenHead )
{
DEBUGMSG(ZONE_INIT | ZONE_ERROR,
(TEXT("Error allocating memory for pOpenHead, COM_Open failed\n\r")));
return(NULL);
}
// Init the structure COMM_EVENTS
pOpenHead->pSpiHead = pSpiHead; // pointer back to our parent
pOpenHead->StructUsers = 0;
pOpenHead->AccessCode = AccessCode;
pOpenHead->ShareMode = ShareMode;
pOpenHead->CommEvents.hCommEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
pOpenHead->CommEvents.fEventMask = 0;
pOpenHead->CommEvents.fEventData = 0;
pOpenHead->CommEvents.fAbort = 0;
InitializeCriticalSection(&(pOpenHead->CommEvents.EventCS));
// if we have access permissions, note it in pSpihead
if ( AccessCode & (GENERIC_READ | GENERIC_WRITE) )
{
// RETAILMSG(1, (TEXT("SPI_Open: Access permission handle granted x%X\n\r"), pOpenHead));
DEBUGMSG(ZONE_INIT|ZONE_CLOSE,
(TEXT("SPI_Open: Access permission handle granted x%X\n\r"),
pOpenHead));
pSpiHead->pAccessOwner = pOpenHead;
}
// add this open entry to list of open entries.
// Note that we hold the open CS for the duration of the routine since
// all of our state info is in flux during this time. In particular,
// without the CS is would be possible for an open & close to be going on
// simultaneously and have bad things happen like spinning a new event
// thread before the old one was gone, etc.
EnterCriticalSection(&(pSpiHead->OpenCS));
InsertHeadList(&pSpiHead->OpenList, &pOpenHead->llist);
// If port not yet opened, we need to do some init
if ( !pSpiHead->OpenCnt )
{
// RETAILMSG(1, (TEXT("SPI_Open: First open : Do Init x%X\n\r"), pOpenHead));
DEBUGMSG(ZONE_INIT|ZONE_OPEN,
(TEXT("SPI_Open: First open : Do Init x%X\n\r"), pOpenHead));
pSpiHead->RxBytes = 0;
pSpiHead->TxBytes = 0;
pSpiHead->TxBytesPending = 0;
pSpiHead->DroppedBytes = 0;
// pSpiHead->CommErrors = 0;
EnterCriticalSection(&(pSpiHead->RegCritSec));
try
{
//SPI0 init SPICLK0 SPIMOSI0 SPIMISO0 nSS0
// RETAILMSG(1, (TEXT("I/0 init 0x%x\n\r"), v_pIOPregs));
v_pIOPregs->rGPEUP &= ~(0x07 << 11);
v_pIOPregs->rGPEUP |= (0x04 << 11);
v_pIOPregs->rGPGUP &= ~(0x1 << 2);
v_pIOPregs->rGPGUP |= (0x1 << 2);
v_pIOPregs->rGPECON &= ~(0x3f << 22);
v_pIOPregs->rGPECON |= (0x2a << 22);
v_pIOPregs->rGPGCON &= ~(0x03 << 4);
v_pIOPregs->rGPGCON |= (0x01 << 4);
CAN_CS_H();// Activate nSS high
// RETAILMSG(1, (TEXT("SPI0 init 0x%x\n\r"), v_pSPI0regs));
//if PCLK=(202800000/4)=50Mhz,SPICLK=2Mhz
v_pSPI0regs->rSPPRE0 = 0x0c;
//int,en-SCK,master,high,A,normal
v_pSPI0regs->rSPCON0 = (1<<5)|(1<<4)|(1<<3)|(0<<2)|(0<<1)|(0<<0);
//dis-ENMUL,SBO,release
v_pSPI0regs->rSPPIN0 = (0<<2)|(1<<1)|(0<<0);
//EINT0 init
// RETAILMSG(1, (TEXT("EINT0 init\n\r")));
v_pIOPregs->rGPFCON &= ~(0x03 << 0);
v_pIOPregs->rGPFCON |= (0x02 << 0);
v_pIOPregs->rEXTINT0 &= ~(0x07 << 0);
v_pIOPregs->rEXTINT0 |= (0x00 << 0);
ClearINTPnd(pSpiHead->bEINT);
EnINT(pSpiHead->bEINT);
//CAN init
// RETAILMSG(1, (TEXT("CAN Reset\n\r")));
CAN_Reset();
// RETAILMSG(1, (TEXT("CAN init\n\r")));
CAN_Init();
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
// Just get out of here.
// RETAILMSG(1, (TEXT("init except occur!\n\r")));
retval = FALSE;
}
LeaveCriticalSection(&(pSpiHead->RegCritSec));
}
++(pSpiHead->OpenCnt);
// OK, we are finally back in a stable state. Release the CS.
LeaveCriticalSection(&(pSpiHead->OpenCS));
// RETAILMSG(1, (TEXT("SPI_Open handle x%X, x%X, Ref x%X\r\n"),
// pOpenHead, pOpenHead->pSpiHead, pSpiHead->OpenCnt));
DEBUGMSG (ZONE_OPEN|ZONE_FUNCTION,
(TEXT("-SPI_Open handle x%X, x%X, Ref x%X\r\n"),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -