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

📄 s3c2410_can.cpp

📁 ce下S3C2410的SPI口转CAN的驱动
💻 CPP
📖 第 1 页 / 共 5 页
字号:
//			    RETAILMSG (DEBUGMODE, (TEXT("GetInterruptType: INTR_MERRF\r\n")));
			    interrupts = INTR_MERRF;  // Error status
			    bit_cmd(CANINTE, INTR_MERRF, 0x00);//Disable MERRF interrupter
			}
			else if(IntPndVal & INTR_ERRIF)  
			{
//			    RETAILMSG (DEBUGMODE, (TEXT("GetInterruptType: INTR_ERRIF\r\n")));
			    interrupts = INTR_ERRIF;    // 
			    bit_cmd(CANINTE, INTR_ERRIF, 0x00);//Disable ERRIF interrupter
			}
		}
		else if(inter == 0x04)  
		{
//			RETAILMSG (DEBUGMODE, (TEXT("GetInterruptType: INTR_WAKIF\r\n")));
			interrupts = INTR_WAKIF;    // 
			bit_cmd(CANINTE, INTR_WAKIF, 0x00);//Disable WAKIF interrupter
		}
		else if((inter == 0x06) && pSpiHead->fSW_EnTxINT )  
		{
//			RETAILMSG (DEBUGMODE, (TEXT("GetInterruptType: INTR_TX0IF\r\n")));
			interrupts = INTR_TX0IF;
			bit_cmd(CANINTE, INTR_TX0IF, 0x00);//Disable TX0IF interrupter
		}
		else if((inter == 0x08) && pSpiHead->fSW_EnTxINT )  
		{
//			RETAILMSG (DEBUGMODE, (TEXT("GetInterruptType: INTR_TX1IF\r\n")));
			interrupts = INTR_TX1IF;
			bit_cmd(CANINTE, INTR_TX1IF, 0x00);//Disable TX1IF interrupter
		}
		else if((inter == 0x0a) && pSpiHead->fSW_EnTxINT )  
		{
//			RETAILMSG (DEBUGMODE, (TEXT("GetInterruptType: INTR_TX2IF\r\n")));
			interrupts = INTR_TX2IF;
			bit_cmd(CANINTE, INTR_TX2IF, 0x00);//Disable TX2IF interrupter
		}
		else if(inter == 0x0c)  
		{
//			RETAILMSG (DEBUGMODE, (TEXT("GetInterruptType: INTR_RX0IF\r\n")));
			interrupts = INTR_RX0IF;    // Received valid data.
			bit_cmd(CANINTE, INTR_RX0IF, 0x00);//Disable RX0IF interrupter
		}
		else if(inter == 0x0e)  
		{
//			RETAILMSG (DEBUGMODE, (TEXT("GetInterruptType: INTR_RX1IF\r\n")));
			interrupts = INTR_RX1IF;    // Received valid data.
			bit_cmd(CANINTE, INTR_RX1IF, 0x00);//Disable RX1IF interrupter
		}
		else 
		{
//			RETAILMSG (DEBUGMODE, (TEXT("GetInterruptType: INTR_NONE\r\n")));
			interrupts = INTR_NONE;  // No interrupts pending, vector is useless
		}
	}
	else 
	{
//		RETAILMSG (DEBUGMODE, (TEXT("INTR_NONE\r\n")));
		interrupts = INTR_NONE; // No interrupts pending, vector is useless
	}

	return(interrupts);
}
//
VOID EflgEventHandler(PHW_INDEP_INFO pSpiHead)
{
    ERRIF_TYPE   it = ERRIF_NONE;
    
//	RETAILMSG(1, (TEXT("EflgEventHandler, pHead 0x%X\r\n"), pSpiHead));
    DEBUGMSG (ZONE_THREAD, 
		      (TEXT("+EflgEventHandler, pHead 0x%X\r\n"), pSpiHead));

    try 
	{
		r_cmd(EFLG, (U8*)&it, 1);
	}
	except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
		EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) 
	{
//		RETAILMSG(DEBUGMODE, (TEXT("ACCESS VIOLATION ERROR \r\n")));
		it = ERRIF_NONE;
	}
      
//	RETAILMSG(1, (TEXT("EflgEventHandler, interrupts 0x%X\r\n"), it));
	DEBUGMSG (ZONE_THREAD, 
		      (TEXT("EflgEventHandler, interrupts 0x%X\r\n"), it));

    //接受缓冲器0溢出
    if(it & ERRIF_RX0OVR)
    {
//		RETAILMSG(1, (TEXT("RX0OVR Event\r\n")));
		DEBUGMSG (ZONE_THREAD, (TEXT("RX0OVR Event\r\n")));
		bit_cmd(CANINTF, RX0IF, 0x00);
        bit_cmd(EFLG, RX0OVR, 0x00);
    }
    //接受缓冲器1溢出
    if(it & ERRIF_RX1OVR)
    {
//		RETAILMSG(1, (TEXT("RX1OVR Event\r\n")));
		DEBUGMSG (ZONE_THREAD, (TEXT("RX1OVR Event\r\n")));
		bit_cmd(CANINTF, RX1IF, 0x00);
        bit_cmd(EFLG, RX1OVR, 0x00);
    }
    //TEC>=96 or REC>=96
    if(it & ERRIF_EWARN)
    {
//		RETAILMSG(1, (TEXT("EWARN Event\r\n")));
		DEBUGMSG (ZONE_THREAD, (TEXT("EWARN Event\r\n")));
    }
    //TEC>=96
    if(it & ERRIF_TXWAR)
    {
//		RETAILMSG(1, (TEXT("TXWAR Event\r\n")));
		DEBUGMSG (ZONE_THREAD, (TEXT("TXWAR Event\r\n")));
        w_cmd0(TEC, 0x00);
    }
    //REC>=96
    if(it & ERRIF_RXWAR)
    {
//		RETAILMSG(1, (TEXT("RXWAR Event\r\n")));
		DEBUGMSG (ZONE_THREAD, (TEXT("RXWAR Event\r\n")));
        w_cmd0(REC, 0x00);
    }
    //TEC>=128
    if(it & ERRIF_TXEP)
    {
//		RETAILMSG(1, (TEXT("RX0OVR Event\r\n")));
		DEBUGMSG (ZONE_THREAD, (TEXT("RX0OVR Event\r\n")));
        w_cmd0(TEC, 0x00);
    }
    //REC>=128
    if(it & ERRIF_RXEP)
    {
//		RETAILMSG(1, (TEXT("RXEP Event\r\n")));
		DEBUGMSG (ZONE_THREAD, (TEXT("RXEP Event\r\n")));
        w_cmd0(REC, 0x00);
    }
    //TEC>=255  
    if(it & ERRIF_TXB0)
    {
//		RETAILMSG(1, (TEXT("TXB0 Event\r\n")));
		DEBUGMSG (ZONE_THREAD, (TEXT("TXB0 Event\r\n")));
        w_cmd0(TEC, 0x00);
    }    

	return;
}
//
VOID SpiEventHandler(PHW_INDEP_INFO pSpiHead)
{
    INTERRUPT_TYPE      it = INTR_NONE;
    BOOL                RxDataAvail = FALSE;

//	RETAILMSG(1, (TEXT("+SpiEventHandler, pHead 0x%X\r\n"), pSpiHead));
	DEBUGMSG (ZONE_THREAD, 
		      (TEXT("+SpiEventHandler, pHead 0x%X\r\n"), pSpiHead));

	if ( pSpiHead->KillRxThread || !pSpiHead->hSpiEvent ) 
	{
//		RETAILMSG(1, (TEXT("Exitting thread\r\n")));
        DEBUGMSG (ZONE_THREAD, (TEXT("Exitting thread\r\n")));
        SetEvent(pSpiHead->hKillDispatchThread);
        ExitThread(0);
    }

	// NOTE - This one is a little tricky.  If the only owner is a monitoring task
    // then I don't have an owner for read/write, yet I might be in this routine
    // due to a change in line status.  Lets just do the best we can and increment
    // the count for the access owner if available.
    if ( pSpiHead->pAccessOwner )
        COM_INC_USAGE_CNT(pSpiHead->pAccessOwner);

	while ( 1 ) 
	{
		if( !(it = GetInterruptType(pSpiHead)) )
		{
//			RETAILMSG(1, (TEXT("SpiEventHandler, No Interrupt.\r\n")));
            DEBUGMSG (ZONE_THREAD, (TEXT("SpiEventHandler, No Interrupt.\r\n")));
			
            w_cmd0(CANINTF, 0x00); //清中断标志
			w_cmd0(CANINTE, 0xff); //中断使能

			ClearINTPnd(pSpiHead->bEINT);
	        EnINT(pSpiHead->bEINT); 
            break;
        }

//		RETAILMSG(1, (TEXT("SpiEventHandler, Interrupts 0x%X\r\n"), it));
        DEBUGMSG (ZONE_THREAD, (TEXT("SpiEventHandler, Interrupts 0x%X\r\n"), it));

		if ( it & INTR_RX0IF ) 
		{
//			RETAILMSG(1, (TEXT("RX0IF Event\r\n")));
            DEBUGMSG (ZONE_THREAD|ZONE_READ , (TEXT("RX0IF Event\r\n")));

			DoRxData(pSpiHead, &RxDataAvail, 0);

//			bit_cmd(CANINTF, INTR_RX0IF, 0x00);	
		}
		else if ( it & INTR_RX1IF ) 
		{
//			RETAILMSG(1, (TEXT("RX1IF Event\r\n")));
            DEBUGMSG (ZONE_THREAD|ZONE_READ , (TEXT("RX1IF Event\r\n")));

			DoRxData(pSpiHead, &RxDataAvail, 1);

//			bit_cmd(CANINTF, INTR_RX1IF, 0x00);	
		}
		else if ( it & INTR_TX0IF ) 
		{
//			RETAILMSG(1, (TEXT("TX0IF Event\r\n")));
            DEBUGMSG (ZONE_THREAD|ZONE_WRITE , (TEXT("TX0IF Event\r\n")));

            DoTxData(pSpiHead);

			//Clearing TX0IF interrupter
		    bit_cmd(CANINTF, INTR_TX0IF, 0x00);		
		}
		else if ( it & INTR_TX1IF ) 
		{
//			RETAILMSG(1, (TEXT("TX1IF Event\r\n")));
			DEBUGMSG (ZONE_THREAD|ZONE_WRITE , (TEXT("TX1IF Event\r\n")));

			DoTxData(pSpiHead);

            //Clearing ERRIF interrupter
			bit_cmd(CANINTF, INTR_TX1IF, 0x00);			
		}
		else if ( it & INTR_TX2IF ) 
		{
//			RETAILMSG(1, (TEXT("TX2IF Event\r\n")));
			DEBUGMSG (ZONE_THREAD|ZONE_WRITE , (TEXT("TX2IF Event\r\n")));

			DoTxData(pSpiHead);

            //Clearing ERRIF interrupter
			bit_cmd(CANINTF, INTR_TX2IF, 0x00);			
		}
		//错误中断
		else if ( it & INTR_ERRIF ) 
		{
            EflgEventHandler(pSpiHead);

			//Clearing ERRIF interrupter
			bit_cmd(CANINTF, INTR_ERRIF, 0x00);
			//Enable ERRIF interrupter
			bit_cmd(CANINTE, INTR_ERRIF, INTR_ERRIF);
		}
		//总线活动唤醒中断,从休眠模式中跳出
		else if ( it & INTR_WAKIF ) 
		{
			//do something here
			//......
            //Clearing WAKIF interrupter
			bit_cmd(CANINTF, INTR_WAKIF, 0x00);
			//Enable WAKIF interrupter
			bit_cmd(CANINTE, INTR_WAKIF, INTR_WAKIF);
		}
		//报文错误中断,
        //1.用于在只听模式下波特率的确定
        //2.总线上没有其他报文活动
		else if ( it & INTR_MERRF ) 
		{
			//do something here
			//......
			//Clearing MERRF interrupter
			bit_cmd(CANINTF, INTR_MERRF, 0x00);
			//Enable MERRF interrupter
			bit_cmd(CANINTE, INTR_MERRF, INTR_MERRF);

            Sleep(1000);
		}		
	}

    ClearINTPnd(pSpiHead->bEINT);
	EnINT(pSpiHead->bEINT); 

	// We kept this till the end to optimize the above loop
    if ( RxDataAvail ) 
	{
        // Signal SPI_Read that bytes are available.
        SetEvent(pSpiHead->hReadEvent);	
        EvaluateEventFlag(pSpiHead, EV_RXCHAR);
    }

//	RETAILMSG(1, (TEXT("-SpiEventHandler, Fifo(R=%d,W=%d,L=%d)\r\n"),
//               RxRead(pSpiHead), RxWrite(pSpiHead), RxLength(pSpiHead)));
    DEBUGMSG (ZONE_THREAD ,
              (TEXT("-SpiEventHandler, Fifo(R=%d,W=%d,L=%d)\r\n"),
               RxRead(pSpiHead), RxWrite(pSpiHead),
               RxLength(pSpiHead)));

	if ( pSpiHead->pAccessOwner )
        COM_DEC_USAGE_CNT(pSpiHead->pAccessOwner);

    return;
}
/*
 @doc INTERNAL
 @func	ULONG | SpiDispatchThread | Main spi event dispatch thread code.
 *	This is the reading and dispatching thread. It gets the
 *	event associated with the logical interrupt dwIntID and calls
 *	hardware specific routines to determine whether it's a receive event
 *	or a transmit event. If it's a transmit event, it calls the HW tx handler.
 *	If it's a receive event, it calls for the number of characters and calls
 *	atomic GetByte() to extract characters and put them into the drivers
 *	buffer represented by pSpiHead->pTargetBuffer, managing waiting
 *	for events and checking to see if those signals correspond to reading.
 *	It relies on NK masking the interrupts while it does it's thing, calling
 *	InterruptDone() to unmask them for each of the above cases.
 *
 *	Not exported to users.
 *
 @rdesc This thread technically returns a status, but in practice, doesn't return
 *		while the device is open.
 */
static DWORD WINAPI
SpiDispatchThread(
                    PVOID   pContext    /* @parm [IN] Pointer to main data structure. */
                    )
{
    PHW_INDEP_INFO      pSpiHead    = (PHW_INDEP_INFO)pContext;
    ULONG               WaitReturn;

//	RETAILMSG(1, (TEXT("Entered SpiDispatchThread %X\r\n"), pSpiHead));
    DEBUGMSG (ZONE_THREAD, (TEXT("Entered SpiDispatchThread %X\r\n"), pSpiHead));

    // It is possible for a PDD to use this routine in its private thread, so
    // don't just assume that the MDD synchronization mechanism is in place.
    DEBUGMSG(ZONE_INIT,  (TEXT("Spinning in dispatch thread %X\n\r"), pSpiHead));

    while ( !pSpiHead->pDispatchThread ) 
	{
         Sleep(20);
    }

    /* Wait for the event that any spi port action creates.
     */
    while ( !pSpiHead->KillRxThread ) 
	{
        DEBUGMSG (ZONE_THREAD, (TEXT("Event %X, %d\r\n"),
                                pSpiHead->hSpiEvent,
                                pSpiHead->dwIntID ));

        WaitReturn = WaitForSingleObject(pSpiHead->hSpiEvent, INFINITE);

        SpiEventHandler(pSpiHead);

        InterruptDone(pSpiHead->dwIntID);
    }

    DEBUGMSG (ZONE_THREAD, (TEXT("SpiDispatchThread %x exiting\r\n"), pSpiHead));

    return(0);
}
// ****************************************************************
//
//	@doc INTERNAL
//	@func		BOOL | StartDispatchThread | Start thread if requested by PDD.
//
//	@parm 		ULONG  | pspiHead
//
//	 @rdesc		TRUE if success, FALSE if failed.
//
BOOL
StartDispatchThread(
                   PHW_INDEP_INFO  pSpiHead
                   )
{
    // Initialize the interrupt to be associated with the hSpiEvent
    // event. GetByte waits on this event and acts as a second
    // level decoder determining the type of spi event. If this return
    // fails, then another process has registered for the interrupt, so
    // fail the init and set the hSpiEvent to NULL.
//	RETAILMSG(1, (TEXT("Initializing interrupt 0x%X, 0x%X\n\r"), 
//	          pSpiHead->dwIntID, pSpiHead->hSpiEvent));
    DEBUGMSG(ZONE_INIT,
             (TEXT("Initializing interrupt 0x%X, 0x%X\n\r"),
              pSpiHead->dwIntID, pSpiHead->hSpiEvent));

    if ( !InterruptInitialize(pSpiHead->dwIntID, pSpiHead->hSpiEvent, NULL, 0) ) 
	{
        DEBUGMSG(ZONE_INIT | ZONE_ERROR, (TEXT("Error initializing interrupt\n\r")));
        return(FALSE);
    }

    InterruptDone(pSpiHead->dwIntID);

    // Set up the dispatch thread and it's kill flag. Note that the thread
    // fills in its own handle in pspiHead.
    pSpiHead->KillRxThread = 0;
    pSpiHead->pDispatchThread = NULL;

    DEBUGMSG(ZONE_INIT, (TEXT("Spinning thread%X\n\r"), pSpiHead));

    pSpiHead->pDispatchThread = CreateThread(NULL,0, SpiDispatchThread, pSpiHead, 0,NULL);

    if ( pSpiHead->pDispatchThread == NULL ) 
	{
        DEBUGMSG(ZONE_INIT|ZONE_ERROR,
                 (TEXT("Error creating dispatch thread (%d)\n\r"),
                  GetLastError()));
        return(FALSE);
    }

//	RETAILMSG(1, (TEXT("Created receive thread %X\r\n"),  pSpiHead->pDispatchThread)); 
    DEBUGMSG (ZONE_INIT, (TEXT("Created receive thread %X\r\n"),
                          pSpiHead->pDispatchThread));     
    return(TRUE);
}
// ****************************************************************
//
//	@doc INTERNAL
//	@func		BOOL | StartDispatchThread | Stop thread, disable interrupt.
//
//	@parm 		ULONG  | pspiHead
//
//	 @rdesc		TRUE if success, FALSE if failed.
//
BOOL
StopDispatchThread(
                  PHW_INDEP_INFO  pSpiHead
                  )

{
    HANDLE              pThisThread = GetCurrentThread();
    ULONG               priority256;

⌨️ 快捷键说明

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