⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 s3c2410_can.cpp

📁 ce下S3C2410的SPI口转CAN的驱动
💻 CPP
📖 第 1 页 / 共 5 页
字号:

    /* 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 + -