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

📄 s3c2410_can.cpp

📁 ce下S3C2410的SPI口转CAN的驱动
💻 CPP
📖 第 1 页 / 共 5 页
字号:
              pOpenHead, pOpenHead->pSpiHead, pSpiHead->OpenCnt));

	if( !retval )
		goto OpenFail;

    return(pOpenHead);

OpenFail :
    DEBUGMSG (ZONE_OPEN|ZONE_FUNCTION, 
		      (TEXT("-SPI_Open handle x%X, x%X, Ref x%X\r\n"),
              NULL, pOpenHead->pSpiHead, pSpiHead->OpenCnt));

    SetLastError(ERROR_OPEN_FAILED);

    // If this was the handle with access permission, remove pointer
    if ( pOpenHead == pSpiHead->pAccessOwner )
        pSpiHead->pAccessOwner = NULL;

    // Remove the Open entry from the linked list
    RemoveEntryList(&pOpenHead->llist);

    // OK, everything is stable so release the critical section
    LeaveCriticalSection(&(pSpiHead->OpenCS));

    // Free all data allocated in open
    if ( pOpenHead->CommEvents.hCommEvent )
        CloseHandle(pOpenHead->CommEvents.hCommEvent);
	DeleteCriticalSection(&(pOpenHead->CommEvents.EventCS));
    LocalFree( pOpenHead );

	return(NULL);
}

// ****************************************************************
//
//	@doc EXTERNAL
//
//	@func BOOL	| SPI_Close | close the spi device.
//
//	@parm DWORD | pHead		| Context pointer returned from SPI_Open
//
//	@rdesc TRUE if success; FALSE if failure
//
//	@remark This routine is called by the device manager to close the device.
//			
//
//
BOOL
SPI_Close(PHW_OPEN_INFO pOpenHead)
{
	PHW_INDEP_INFO  pSpiHead = pOpenHead->pSpiHead;
    int             i;
    BOOL            RetCode = TRUE;

    DEBUGMSG (ZONE_CLOSE|ZONE_FUNCTION, (TEXT("+SPI_Close\r\n")));

    if ( !pSpiHead ) 
	{
        DEBUGMSG (ZONE_ERROR, (TEXT("!!SPI_Close: pSpiHead == NULL!!\r\n")));
        SetLastError(ERROR_INVALID_HANDLE);
        return(FALSE);
    }

    // Use the OpenCS to make sure we don't collide with an in-progress open.
    EnterCriticalSection(&(pSpiHead->OpenCS));

    if ( pSpiHead->OpenCnt ) 
	{
        --(pSpiHead->OpenCnt);

        DEBUGMSG (1,
                  (TEXT("SPI_Close: (%d handles) total RX %d, total TX %d, dropped %d\r\n"),
                   pSpiHead->OpenCnt, pSpiHead->RxBytes, pSpiHead->TxBytes, 
				   pSpiHead->DroppedBytes));

        // In multi open case, do we need to restore state later on or something????
        if ( pSpiHead->pDispatchThread ) 
		{
            SetThreadPriority(pSpiHead->pDispatchThread, THREAD_PRIORITY_NORMAL);
        }

        // Free up any threads which may be blocked waiting for events.
        // Monitor users count to make sure no one is still in one of
        // the COM_ functions before proceeding (wait up to 2 s). 
        for ( i=0; i<20 && pOpenHead->StructUsers; i++ ) 
		{
            DEBUGMSG(ZONE_INIT|ZONE_CLOSE,
                     (TEXT("SPI_Close: %d users in MDD functions\n\r"),
					 pOpenHead->StructUsers));

            // For any open handle, we must free pending waitcommevents
			EnterCriticalSection(&(pOpenHead->CommEvents.EventCS));
            pOpenHead->CommEvents.fEventMask = 0;
            pOpenHead->CommEvents.fAbort = 1;
            SetEvent(pOpenHead->CommEvents.hCommEvent);
			LeaveCriticalSection(&(pOpenHead->CommEvents.EventCS));

            // And only for the handle with access permissions do we
            // have to worry about read, write, etc being blocked.
            if ( pOpenHead->AccessCode & (GENERIC_READ | GENERIC_WRITE) ) 
			{
                SetEvent(pSpiHead->hReadEvent);
                SetEvent(pSpiHead->hTransmitEvent);
            }

            /* Sleep, let threads finish */
            Sleep(100);
        }
        if ( i==20 )
		{
            DEBUGMSG(ZONE_CLOSE|ZONE_INIT|ZONE_ERROR,
                     (TEXT("SPI_Close: Waited 2s for spi users to exit, %d left\n\r"),
                      pOpenHead->StructUsers));
		}

        // If we are closing the last open handle, then close PDD also
        if ( !pSpiHead->OpenCnt ) 
		{           
			// while we are still transmitting, sleep.
			//......

	        EnterCriticalSection(&(pSpiHead->RegCritSec));
			try 
			{	
				
		        // Disable all interrupts.
		        DisEnINT(pSpiHead->bEINT);
				//中断禁止
				w_cmd0(CANINTE, 0x00); 

		        pSpiHead->fSW_EnTxINT = FALSE;
			}
	        except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
		    EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) 
			{
		    // Just get out of here.
			}
	        LeaveCriticalSection(&(pSpiHead->RegCritSec));       
        }

        // If this was the handle with access permission, remove pointer
        if ( pOpenHead == pSpiHead->pAccessOwner ) 
		{
            DEBUGMSG(ZONE_INIT|ZONE_CLOSE,
                     (TEXT("SPI_Close: Closed access owner handle\n\r"),
                      pOpenHead));

            pSpiHead->pAccessOwner = NULL;
        }

        // Remove the entry from the linked list
        RemoveEntryList(&pOpenHead->llist);

        // Free all data allocated in open
		DeleteCriticalSection(&(pOpenHead->CommEvents.EventCS));
        if ( pOpenHead->CommEvents.hCommEvent )
            CloseHandle(pOpenHead->CommEvents.hCommEvent);
        LocalFree( pOpenHead );
    } 
	else 
	{
        DEBUGMSG (ZONE_ERROR, (TEXT("!!Close of non-open spi port\r\n")));
        SetLastError(ERROR_INVALID_HANDLE);        
        RetCode = FALSE;
    }

    // OK, other inits/opens can go ahead.
    LeaveCriticalSection(&(pSpiHead->OpenCS));

	RETAILMSG(1, (TEXT("SPI_Close\r\n")));
    DEBUGMSG (ZONE_CLOSE|ZONE_FUNCTION, (TEXT("-SPI_Close\r\n")));
    return(RetCode);
}

/*
 @doc EXTERNAL
 @func	BOOL | SPI_Deinit | De-initialize spi port.
 @parm DWORD | pSpiHead | Context pointer returned from SPI_Init
 *
 @rdesc None.
 */
BOOL
SPI_Deinit(PHW_INDEP_INFO pSpiHead)
{
//	RETAILMSG(1, (TEXT("+COM_Deinit\r\n")));
	DEBUGMSG (ZONE_INIT|ZONE_FUNCTION, (TEXT("+COM_Deinit\r\n")));

    if ( !pSpiHead ) 
	{
        /* Can't do much without this */
        DEBUGMSG (ZONE_INIT|ZONE_ERROR, (TEXT("SPI_Deinit can't find pspiHead\r\n")));
        SetLastError(ERROR_INVALID_HANDLE);
        return(FALSE);
    }

    // If we have an interrupt handler thread, kill it
    StopDispatchThread( pSpiHead );

    /*
    ** Call close, if we have a user.  Note that this call will ensure that
    ** all users are out of the spi routines before it returns, so we can
    ** go ahead and free our internal memory.
    */
    if ( pSpiHead->OpenCnt ) 
	{
        PLIST_ENTRY     pEntry;
        PHW_OPEN_INFO   pOpenHead;

        pEntry = pSpiHead->OpenList.Flink;
        while ( pEntry != &pSpiHead->OpenList ) 
		{
            pOpenHead = CONTAINING_RECORD( pEntry, HW_OPEN_INFO, llist);
            pEntry = pEntry->Flink;  // advance to next 

            DEBUGMSG (ZONE_INIT | ZONE_CLOSE, 
				      (TEXT(" Deinit - Closing Handle 0x%X\r\n"), pOpenHead ));

            SPI_Close(pOpenHead);
        }
    }

    /* Free our resources */
    if ( pSpiHead->hSpiEvent )
        CloseHandle(pSpiHead->hSpiEvent);
    if ( pSpiHead->hKillDispatchThread )
        CloseHandle(pSpiHead->hKillDispatchThread);
    if ( pSpiHead->hTransmitEvent )
        CloseHandle(pSpiHead->hTransmitEvent);
    if ( pSpiHead->hReadEvent )
        CloseHandle(pSpiHead->hReadEvent);

    DeleteCriticalSection(&(pSpiHead->ReceiveCritSec1));
    DeleteCriticalSection(&(pSpiHead->TransmitCritSec1));
    DeleteCriticalSection(&(pSpiHead->RxBufferInfo.CS));
    DeleteCriticalSection(&(pSpiHead->TxBufferInfo.CS));
    DeleteCriticalSection(&(pSpiHead->OpenCS));

	DeleteCriticalSection(&(pSpiHead->TransmitCritSec));
	DeleteCriticalSection(&(pSpiHead->RegCritSec));

    if ( pSpiHead->RxBufferInfo.RxCharBuffer )
        LocalFree(pSpiHead->RxBufferInfo.RxCharBuffer);

    SER_VirtualFree();
    LocalFree(pSpiHead);

//	RETAILMSG(1, (TEXT("-SPI_Deinit\r\n")));
    DEBUGMSG (ZONE_INIT|ZONE_FUNCTION, (TEXT("-SPI_Deinit\r\n")));

    return(TRUE);
}

/*
   @doc EXTERNAL
   @func	ULONG | SPI_Read | Allows application to receive characters from
   *	spi port. This routine sets the buffer and bufferlength to be used
   *	by the reading thread. It also enables reception and controlling when
   *	to return to the user. It writes to the referent of the fourth argument
   *	the number of bytes transacted. It returns the status of the call.
   *
   *	Exported to users.
   @rdesc This routine returns: -1 if error, or number of bytes read.
   */
ULONG
SPI_Read(
        HANDLE      pHead,          //@parm [IN]	 HANDLE returned by SPI_Open   
        PUCHAR      pTargetBuffer,  //@parm [IN,OUT] Pointer to valid memory.	  
        ULONG       BufferLength    //@parm [IN]	 Size in bytes of pTargetBuffer.
        )
{
	PHW_OPEN_INFO   pOpenHead = (PHW_OPEN_INFO)pHead;
    PHW_INDEP_INFO  pSpiHead = pOpenHead->pSpiHead;

    ULONG           Ticks;
    ULONG           Timeout;
    ULONG           BytesRead = 0;
    ULONG           IntervalTimeout;    // The interval timeout
	ULONG			AddIntervalTimeout;
    ULONG           TotalTimeout;       // The Total Timeout
    ULONG           TimeSpent = 0;      // How much time have we been waiting?
    ULONG           Len;

	PUCHAR pBuffer = pTargetBuffer;

//	RETAILMSG(1, (TEXT("+SPI_READ(0x%X,0x%X,%d)\r\n"), pHead, pTargetBuffer, BufferLength));
    DEBUGMSG (ZONE_USR_READ|ZONE_FUNCTION,
              (TEXT("+SPI_READ(0x%X,0x%X,%d)\r\n"),
               pHead, pTargetBuffer, BufferLength));

    // Check to see that the call is valid.
    if ( !pSpiHead || !pSpiHead->OpenCnt ) 
	{
        DEBUGMSG (ZONE_USR_READ|ZONE_ERROR,
                  (TEXT("SPI_READ, device not open\r\n") ));
        SetLastError (ERROR_INVALID_HANDLE);
        return(ULONG)-1;
    }

    // Make sure the caller has access permissions
    if ( !(pOpenHead->AccessCode & GENERIC_READ) ) 
	{
        DEBUGMSG(ZONE_USR_READ|ZONE_ERROR,
                 (TEXT("SPI_Read: Access permission failure x%X\n\r"),
                  pOpenHead->AccessCode));
        SetLastError (ERROR_INVALID_ACCESS);
        return(ULONG)-1;
    }

#ifdef DEBUG
    if ( IsBadWritePtr(pTargetBuffer, BufferLength) ) 
	{
        BytesRead = (ULONG)-1;
        SetLastError(ERROR_INVALID_PARAMETER);        
        return(ULONG)-1;
    }
#endif

    COM_INC_USAGE_CNT(pOpenHead);

    /* Practice safe threading.
     */
    EnterCriticalSection(&(pSpiHead->ReceiveCritSec1));

    /* Compute total time to wait. Take product and add constant.
     */
    if ( MAXDWORD != pSpiHead->CommTimeouts.ReadTotalTimeoutMultiplier ) 
	{
        TotalTimeout = pSpiHead->CommTimeouts.ReadTotalTimeoutMultiplier*BufferLength +
                       pSpiHead->CommTimeouts.ReadTotalTimeoutConstant;
		// Because we are using FIFO and water level is set to 8, we have to do following
		AddIntervalTimeout = pSpiHead->CommTimeouts.ReadTotalTimeoutMultiplier*8;
    } 
	else 
	{
        TotalTimeout = pSpiHead->CommTimeouts.ReadTotalTimeoutConstant;
		AddIntervalTimeout=0;
    }
    IntervalTimeout = pSpiHead->CommTimeouts.ReadIntervalTimeout;
	if (IntervalTimeout < MAXDWORD  - AddIntervalTimeout) 
	{
		IntervalTimeout +=AddIntervalTimeout;
	};

    DEBUGMSG (ZONE_USR_READ, (TEXT("TotalTimeout:%d\r\n"), TotalTimeout));

    while ( BufferLength ) 
	{
        DEBUGMSG (ZONE_USR_READ,
                  (TEXT("Top of Loop Fifo(R=%d,W=%d,L=%d,BA=%d)\r\n"),
                   RxRead(pSpiHead), RxWrite(pSpiHead),
                   RxLength(pSpiHead),
                   RxBytesAvail(pSpiHead)));

        if ( RxBytesAvail(pSpiHead) ) 
		{
            RxEnterCS(pSpiHead);
            // Copy the data over
            // This only copies the continous portion, This will cause a loop
            // if the receive data spans the end of the buffer.
            Len = MIN(RxBytesAvail(pSpiHead), RxLength(pSpiHead)-RxRead(pSpiHead));
            Len = MIN(Len, BufferLength);
//			RETAILMSG(1, (TEXT("About to copy %d bytes\r\n"), Len));
            DEBUGMSG (ZONE_USR_READ, (TEXT("About to copy %d bytes\r\n"), Len));
            memcpy (pTargetBuffer, RxBuffRead(pSpiHead), Len);
            // Update Fifo info
            RxRead(pSpiHead) += Len;
            RxRead(pSpiHead) %= RxLength(pSpiHead);

            // Update all the pointers.
            BufferLength -= Len;
            pTargetBuffer += Len;
            BytesRead += Len;
            RxLeaveCS(pSpiHead);
        } 
		else 
		{
            // Wait for a SPI event?
            if ( (IntervalTimeout == MAXDWORD) && (TotalTimeout == 0) ) 
			{
                // For some reason this means don't wait.
                break;
            }

            if ( (IntervalTimeout == 0) && (TotalTimeout == 0) ) 
			{
                // Not completely clear but this could mean wait
                // for ever
                Timeout = INFINITE;
            } 
			else if ( TotalTimeout == 0 ) 
			{
                if ( !BytesRead ) 
				{
                    // On first character we only use total timeout
                    Timeout = INFINITE;
                } 
				else 
				{
                    // No total timeout in use.	 Just use interval timer
                    Timeout = IntervalTimeout;
                }
            } 
			else 
			{
                // Total timeout is valid
                if ( TimeSpent >= TotalTimeout ) 
				{
                    // Timed out.
                    break;
                }
                Timeout = TotalTimeout - TimeSpent;
                // On first byte we only use interval timeout
                // on subsequent we use minimum of Interval and Timeout
                if ( BytesRead && (IntervalTimeout != 0) ) 
				{
                    Timeout = MIN(Timeout, IntervalTimeout);
                }

                // Yet another special case.
                if ( BytesRead &&
                   

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -