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

📄 s3c2410_can.cpp

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

		v_pINTregs = (volatile INTreg *)SER_RegAlloc((PVOID)INT_BASE, sizeof(INTreg));
		if (v_pINTregs == NULL) 
		{
	    	ERRORMSG(1,(TEXT("For INTregs: VirtualAlloc failed!\r\n")));
		    break;
		}

		v_pPWMregs = (volatile PWMreg *)SER_RegAlloc((PVOID)PWM_BASE, sizeof(PWMreg));
		if (v_pPWMregs == NULL) 
		{
	    	ERRORMSG(1,(TEXT("For PWMregs: VirtualAlloc failed!\r\n")));
		    break;
		}
		
		r = TRUE;

	} while (0);

	if (!r)
	{
		SER_VirtualFree();

//		RETAILMSG(DEBUGMODE,(TEXT("::: SPI_VirtualAlloc() - Fail\r\n")));
	}
	else
	{
//		RETAILMSG(DEBUGMODE,(TEXT("::: SPI_VirtualAlloc() - Success\r\n")));
	}

	return r;
}

PRIVATE void
SER_VirtualFree(VOID)
{
//    RETAILMSG(DEBUGMODE,(TEXT("::: SER_VirtualFree()\r\n")));

	if (v_pIOPregs)
    {
        VirtualFree((PVOID)v_pIOPregs, 0, MEM_RELEASE);
        v_pIOPregs = NULL;
    }
    if (v_pSPI0regs)
    {   
        VirtualFree((PVOID)v_pSPI0regs, 0, MEM_RELEASE);
        v_pSPI0regs = NULL;
    } 
    if (v_pINTregs)
    {   
        VirtualFree((PVOID)v_pINTregs, 0, MEM_RELEASE);
        v_pINTregs = NULL;
    } 
    if (v_pPWMregs)
    {   
        VirtualFree((PVOID)v_pPWMregs, 0, MEM_RELEASE);
        v_pPWMregs = NULL;
    } 
}
//
// @doc OEM
// @func ULONG | HWTxIntrHandler | This routine is called
//   whenever INTR_TX is returned by GetInterruptType
// 
// @rdesc None
//
VOID
HWTxIntrHandler(
                 PVOID  pHead,     // Hardware Head
                 PUCHAR pTxBuffer, // @parm Pointer to receive buffer
                 ULONG  *pBufflen  // @parm In = max bytes to transmit, out = bytes transmitted				 
               )
{
	PHW_INDEP_INFO pSpiHead = (PHW_INDEP_INFO)pHead;
	ULONG       NumberOfBytes = *pBufflen;
   
//	RETAILMSG(DEBUGMODE, (TEXT("HWTxIntrHandler \r\n")));

	// We may be done sending.  If so, just disable the TX interrupts and return.  
	if( ! *pBufflen ) 
	{		
		//Disable ERRIF interrupter
//		bit_cmd(CANINTE, INTR_TX0IF, 0x00);
		bit_cmd(CANINTE, 0x1c, 0x00);

		pSpiHead->fSW_EnTxINT = FALSE;
		
		return;
	}
    
	*pBufflen = 0;  //In case we don't send anything below.
	
	//  OK, now lets actually transmit some data.
	EnterCriticalSection(&(pSpiHead->TransmitCritSec));
	EnterCriticalSection(&(pSpiHead->RegCritSec));

	try {
		
        *pBufflen = CAN_Send(pTxBuffer, NumberOfBytes);

		// Enable xmit intr. We need to do this no matter what, 
		// since it relies on one final interrupt before
		// returning to the application. 	
		//Enable TX0IF/TX1IF/TX2IF interrupter
//		bit_cmd(CANINTE, INTR_TX0IF, INTR_TX0IF);
		bit_cmd(CANINTE, 0x1c, INTR_TX0IF|INTR_TX1IF|INTR_TX2IF);		

		pSpiHead->fSW_EnTxINT = TRUE;	                    		
	}
	except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
		EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) 
	{
		// Hmm, not sure what would cause this.  Lets just
		// go away until we get another TX interrupt.
	}

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

	return;
}
// @doc OEM
// @func ULONG | HWRxIntrHandler | This routine gets several characters from the hardware
//   receive buffer and puts them in a buffer provided via the second argument.
//   It returns the number of bytes lost to overrun.
// 
// @rdesc The return value indicates the number of overruns detected.
//   The actual number of dropped characters may be higher.
//
ULONG
HWRxIntrHandler(
                PVOID  pHead,      // @parm Pointer to hardware head
                PUCHAR pRxBuffer,  // @parm Pointer to receive buffer
                ULONG *pBufflen,   // @parm In = max bytes to read, out = bytes read
                U8     index
			   )
{
	PHW_INDEP_INFO pSpiHead = (PHW_INDEP_INFO)pHead;

    ULONG       RetVal=0, iCount=0;
	ULONG       TargetRoom = *pBufflen;
	BOOL        fRXFlag = FALSE;
	UCHAR       cEvtChar, cRXChar;
	ULONG       RxDataReady;

	*pBufflen = 0;
	cEvtChar = 0x0d;//EVENT_CHAR

//	RETAILMSG(DEBUGMODE, (TEXT("HWRxIntrHandler \r\n")));

	try 
	{	
		U8  length = 0;
		U8  dat0[20] = {0};
		U8  selrx[2] = {RX0IF, RX1IF};
		U8  selreg[2] = {RXB0SIDH, RXB1SIDH};

		CAN_State(&cRXChar);
		
		if(cRXChar & selrx[index])
			RxDataReady = 1;
		else
			RxDataReady = 0;

		while ( TargetRoom && RxDataReady ) 
		{
			// Read the byte
			r_cmd(selreg[index], dat0, 13);
			length = (dat0[4] & 0x0f) ;

//			RETAILMSG(DEBUGMODE, (TEXT("RxIntr : cRXChar = 0x%x \r\n"), cRXChar));
		   
			// Finally, we can get byte, update status and save.
			if (!pSpiHead->RxDiscard ) 
			{
				for(iCount=0; iCount<length; iCount++)
				{
				    *pRxBuffer++ = dat0[5+iCount];

					// Do character replacement if parity error detected.
			        // See if we need to generate an EV_RXFLAG for the received char.
					if(dat0[5+iCount] == cEvtChar)//0x0d
					{
//						RETAILMSG(1, (TEXT("RxIntr : EV_RXFLAG 0x%x\r\n"), cRXChar));
				        fRXFlag = TRUE;
					}
				}

				(*pBufflen) += length;
			} 
			else 
			{
//				RETAILMSG (1, (TEXT("RXIntr : Dropping byte because now Txing\r\n")));
			}

			TargetRoom -= length;
			
			RxDataReady = 0;
		}

		//Clear interrupt pending bit
		bit_cmd(CANINTF, selrx[index], 0x00);
		bit_cmd(CANINTE, selrx[index], selrx[index]);
	}
	except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
		EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) 
	{
		// just exit
	}

	// if we saw one (or more) EVT chars, then generate an event
	if ( fRXFlag )
	{		
		EvaluateEventFlag( pSpiHead, EV_RXFLAG );
	}

	if ( pSpiHead->DroppedBytes )
	{
//		RETAILMSG (DEBUGMODE, (TEXT("Rx drop %d.\r\n"), pSpiHead->DroppedBytes));
	}
    
	RetVal = pSpiHead->DroppedBytes;
	pSpiHead->DroppedBytes = 0;

	return(RetVal);
}
/*
 @doc INTERNAL
 @func	VOID | DoRxData | Reces next available chunk of RX data.
 *
 */
VOID
DoRxData(PHW_INDEP_INFO pSpiHead, BOOL *RxDataAvail, U8 index)
{
    ULONG               CharIndex = 0;
    ULONG               RoomLeft = 0;	
    ULONG               TotalLeft = 0;

	// It's read data event.  Ack the receive,
    // unmask the interrupt, get the current data pointer
    // and see if data is available.

//	RETAILMSG(1, (TEXT("Rx Event\r\n")));
    DEBUGMSG (ZONE_THREAD|ZONE_READ , (TEXT("Rx Event\r\n")));

    if ( RxRead(pSpiHead) == 0 ) 
	{
        // have to leave one byte free.
        RoomLeft = RxLength(pSpiHead) - RxWrite(pSpiHead) - 1;
    } 
	else 
	{
        RoomLeft = RxLength(pSpiHead) - RxWrite(pSpiHead);
    }

    if ( RxRead(pSpiHead) > RxWrite(pSpiHead) ) 
	{
        RoomLeft = RxRead(pSpiHead) - RxWrite(pSpiHead) - 1;
    }

    if ( RoomLeft ) 
	{
        pSpiHead->DroppedBytes += HWRxIntrHandler(pSpiHead,
                                        RxBuffWrite(pSpiHead),
                                        &RoomLeft, index);          
    } 
	else 
	{
        BYTE    TempBuf[16];
        RoomLeft = 16;
        HWRxIntrHandler(pSpiHead, TempBuf, &RoomLeft, index);

        pSpiHead->DroppedBytes += RoomLeft;
//		RETAILMSG(1, (TEXT("Tossed %d bytes\r\n"), RoomLeft));
        DEBUGMSG (ZONE_WARN|ZONE_READ, (TEXT("Tossed %d bytes\r\n"), RoomLeft));
        RoomLeft = 0;
     }

//	 RETAILMSG(1, (TEXT("After HWGetBytes, Fifo(R=%d,W=%d,BA=%d,L=%d) ByteRead=%d\r\n"),
//               RxRead(pSpiHead), RxWrite(pSpiHead),
//               RxBytesAvail(pSpiHead), RxLength(pSpiHead), RoomLeft));
     DEBUGMSG (ZONE_READ, 
		       (TEXT("After HWGetBytes, Fifo(R=%d,W=%d,BA=%d,L=%d) ByteRead=%d\r\n"),
               RxRead(pSpiHead), RxWrite(pSpiHead),
               RxBytesAvail(pSpiHead), RxLength(pSpiHead), RoomLeft));

	 pSpiHead->RxBytes += RoomLeft;
     RxWrite(pSpiHead) += RoomLeft;
     RxWrite(pSpiHead) %= RxLength(pSpiHead);

     if ( RoomLeft ) 
	 {
         *RxDataAvail = TRUE;
     }
}
/*
 @doc INTERNAL
 @func	VOID | DoTxData | Sends next available chunk of TX data.
 *
 */
VOID
DoTxData(PHW_INDEP_INFO pSpiHead)
{
    ULONG               Len;

//	RETAILMSG(1, (TEXT("DoPutBytes wait for CritSec %x.\r\n"), &(pSpiHead->TxBufferInfo.CS)));
    DEBUGMSG (ZONE_WRITE, (TEXT("DoPutBytes wait for CritSec %x.\r\n"),
                           &(pSpiHead->TxBufferInfo.CS)));
    TxEnterCS(pSpiHead);

    DEBUGMSG (ZONE_WRITE, (TEXT("DoPutBytes got CritSec %x.\r\n"),
                           &(pSpiHead->TxBufferInfo.CS)));

    // If device was closed from under us, stop transmitting
    if ( !pSpiHead->OpenCnt ) 
	{
//		RETAILMSG(1, (TEXT("Device closed! Quit transmission!\r\n")));
        DEBUGMSG (ZONE_THREAD|ZONE_WRITE , (TEXT("Device closed! Quit transmission!\r\n")));
        DEBUGMSG (ZONE_WRITE,
                  (TEXT("SpiEventHandler: %d sent up-to-now.\n\r"),
				  pSpiHead->TxBytesSent));
        pSpiHead->TxBufferInfo.Permissions = 0;
        pSpiHead->TxBufferInfo.TxCharBuffer = NULL;
        pSpiHead->TxBufferInfo.Length = 0;
        TxRead(pSpiHead) = 0;
    }

    //call the hw TX routine to actually transmit some data.
    if ( pSpiHead->TxBufferInfo.TxCharBuffer && TxBytesAvail(pSpiHead) ) 
	{
        DWORD oldPerm = SetProcPermissions(pSpiHead->TxBufferInfo.Permissions);

//		RETAILMSG(1, (TEXT("TxRead = %d, TxLength = %d, TxBytesAvail = %d.\r\n"),
//                  TxRead(pSpiHead), TxLength(pSpiHead), TxBytesAvail(pSpiHead)));
        DEBUGMSG (ZONE_WRITE,
                  (TEXT("TxRead = %d, TxLength = %d, TxBytesAvail = %d.\r\n"),
                  TxRead(pSpiHead), TxLength(pSpiHead),
                  TxBytesAvail(pSpiHead)));

        Len = TxBytesAvail(pSpiHead);
//		RETAILMSG(1, (TEXT("About to copy %d bytes\r\n"), Len));
        DEBUGMSG (ZONE_WRITE, (TEXT("About to copy %d bytes\r\n"), Len));

        //
        HWTxIntrHandler(pSpiHead, TxBuffRead(pSpiHead), &Len);

//		RETAILMSG(1, (TEXT("%d bytes actually copied.\r\n"), Len));
        DEBUGMSG (ZONE_WRITE, (TEXT("%d bytes actually copied.\r\n"), Len));

        // Update Fifo info
        pSpiHead->TxBytes += Len;
        pSpiHead->TxBytesSent += Len;
        TxRead(pSpiHead) += Len;

        // Even if everything was Tx'ed, don't signal TX complete until
        // we get transmit interrupt indicating that the data has
        // actually been sent.  Since few/no UARTS have a way to tell
        // how much data remains, we don't bother trying to adjust the
        // return length to account for partially completed hardware buffer TX
        SetProcPermissions(oldPerm);
    } 
	else 
	{
        // Even if there is nothing left to send, we need to call
        // the interrupt handler so that it can clear the
        // transmit interrupt
        Len = 0;
        HWTxIntrHandler(pSpiHead, NULL, &Len);
		
//		RETAILMSG(1, (TEXT("Transmission complete, %d bytes sent\r\n"), Len));
        DEBUGMSG (ZONE_WRITE, (TEXT("Transmission complete, %d bytes sent\r\n"), Len));
        pSpiHead->TxBufferInfo.Permissions = 0;
        pSpiHead->TxBufferInfo.TxCharBuffer = NULL;
        pSpiHead->TxBufferInfo.Length = 0;
        TxRead(pSpiHead) = 0;

        SetEvent(pSpiHead->hTransmitEvent);
    }

    TxLeaveCS(pSpiHead);
//	RETAILMSG(1, (TEXT("DoPutBytes released CritSec: %x.\r\n"), &(pSpiHead->TxBufferInfo.CS)));
    DEBUGMSG (ZONE_WRITE|ZONE_FUNCTION,
              (TEXT("DoPutBytes released CritSec: %x.\r\n"),
               &(pSpiHead->TxBufferInfo.CS)));
}
//
// @doc OEM
// @func ULONG | GetInterruptType | This function is called
//   by the MDD whenever an interrupt occurs.  The return code
//   is then checked by the MDD to determine which of the four
//   interrupt handling routines are to be called.
// 
// @rdesc This routine returns a bitmask indicating which interrupts
//   are currently pending.
// 
INTERRUPT_TYPE
GetInterruptType(
                   PVOID pHead      // Pointer to hardware head
                   )
{
	PHW_INDEP_INFO    pSpiHead    = (PHW_INDEP_INFO)pHead;
	INTERRUPT_TYPE    interrupts;
	ULONG             IntPndVal = 0;
	U8                inter=0;

	try 
	{
//		r_cmd(CANINTF, (U8*)&IntPndVal, 1);
		r_cmd(CANSTAT, &inter, 1);
	}
	except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
		EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) 
	{
//		RETAILMSG(DEBUGMODE, (TEXT("ACCESS VIOLATION ERROR \r\n")));
		IntPndVal = INTR_NONE;
	}

	if ( inter )
	{
		if(inter == 0x02)
		{
            r_cmd(CANINTF, (U8*)&IntPndVal, 1);

		    if(IntPndVal & INTR_MERRF )  
			{

⌨️ 快捷键说明

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