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

📄 sc2410_usb_hw.c

📁 SBC2410 WinCE 5.0 BSP.绝大多数驱动已经调通。
💻 C
📖 第 1 页 / 共 4 页
字号:
  call the interrupt mechanism will keep things going.
 
  We return the actual number of bytes we've queued to the UDC. Note that
  until the next interrupt we wont know if it has been transmitted. We'll
  deal with the failure by saving the original packet and retransmitting if
  we get an error. In that case we'll return 0 as the number of bytes sent
  since no new bytes have been consumed from the caller's buffer.
 
  When the packet is accepted we return the number of bytes and grab the 
  next packet (or portion thereof).
 
*************************************************************************/
//:-)
void SC2400_USB_TxIntHandler( PSER_INFO pHWHead,
			      PUCHAR pTxBuffer,
			      ULONG *pBuffLen ) 
{
	unsigned int i;
	UCHAR ucLen;
	BYTE saveIndex;
	
	DEBUGMSG(1, (TEXT("++SC2400_USB_TxIntHandler\r\n")));

	USBDMSG(1, (TEXT("<T:%d>"),*pBuffLen));
	
	usbdShMem->usbdEir&=~USBDEIR_EP1;

	// Endpoint 1 mode
	saveIndex=*(volatile BYTE *)&pHWHead->pUSBCtrlAddr->INDEX;
	UDC_REG_BITSET(struct INDEXBits, &pHWHead->pUSBCtrlAddr->INDEX, index, 0x1);
    //pHWHead->pUSBCtrlAddr->INDEX.index=0x1; //:-)
	
	pHWHead->CommErrors &= ~CE_TXFULL;

	// If nothing to send, just return after clearing interrupt.
	if (! *pBuffLen ) 
	{
		DEBUGMSG (1, (TEXT("[TX:nothing to send]")));    
		*(volatile BYTE *)&pHWHead->pUSBCtrlAddr->INDEX=saveIndex;
		return;
	}
    		      	
	// Don't try to send more than EP1 can handle.
	if( *pBuffLen > EP1Len )
    		ucLen = EP1Len;
	else {

		// If we end exactly on a packet boundary, the host doesn't
		// realize there is no more data.  So if we exactly fill the final 
		// packet, truncate it so we can send a short packet next frame
		// indicating end of the transmission
		if( *pBuffLen == EP1Len ) 
		{
			USBDMSG (1, (TEXT("Tx breaking packet\r\n")));            
			ucLen = EP1Len - 2;
		} else {
			ucLen = (UCHAR)*pBuffLen;
		}

	}

	if (!pHWHead->pUSBCtrlAddr->EP0ICSR1.opr_ipr)
	{
		// Write to the FIFO directly to send the bytes.
		for (i=0; i < ucLen; i++) 
		{
			IOW_REG_FIELD(struct EP1FBits, 
				&pHWHead->pUSBCtrlAddr->EP1F, fifo_data, *pTxBuffer++);
		}

		// Return number of bytes transmitted via pBuffLen.
		*pBuffLen = ucLen;
		UDC_REG_WRITE(struct EP0ICSR1Bits, &pHWHead->pUSBCtrlAddr->EP0ICSR1, opr_ipr, 1);
	} else {
		// Transmit already in progress.  Just return and wait for current
		// transmission to complete before sending more.
		USBDMSG(1, (TEXT("Write Pend !!!\r\n")));
		*pBuffLen = 0; 
	}

	DEBUGMSG(1, (TEXT("--SC2400_USB_TxIntHandler\r\n")));
	*(volatile BYTE *)&pHWHead->pUSBCtrlAddr->INDEX=saveIndex;
}



BOOL
HW_PowerOff(
    PSER_INFO pHWHead 
    )
{
	pHWHead->State = OFF;
	// cache the interrupt regs
	pHWHead->cIntStat_uir = *(BYTE *)&pHWHead->pUSBCtrlAddr->UIR;
	pHWHead->cIntStat_eir = *(BYTE *)&pHWHead->pUSBCtrlAddr->EIR;
    
	// disable the USB Clocks
	EnterCriticalSection(&pHWHead->HwRegCritSec);
	//DEBUGMSG(1, (TEXT("USB:HW_PowerOff()\r\n")));
	RETAILMSG(1, (TEXT("USB:HW_PowerOff()\r\n")));
	HW_USBClocks(pHWHead);
	LeaveCriticalSection(&pHWHead->HwRegCritSec);

    return TRUE;
}


BOOL 
HW_PowerOn(
    PSER_INFO pHWHead
    )
{
		
	pHWHead->State = RESUME;

	// enable the USB Clocks
	EnterCriticalSection(&pHWHead->HwRegCritSec);
	//DEBUGMSG(1, (TEXT("USB:HW_PowerOn()\r\n")));
	RETAILMSG(1, (TEXT("USB:HW_PowerOn()\r\n")));
	HW_USBClocks(pHWHead);
	LeaveCriticalSection(&pHWHead->HwRegCritSec);

	SetInterruptEvent(pHWHead->pHWObj->dwIntID); 		
    
    return TRUE;
}



VOID
HW_USBClocks(PSER_INFO pHWHead)
{
	if ((pHWHead->State == IDLE) || (pHWHead->State == RESUME))
	{
		DEBUGMSG(1, (TEXT("HW_USBClocks::IDLE\r\n")));
        //
        // Enable the USB Clocks
        //
        pHWHead->pCLKPWR->rCLKCON |= (1<<7);
        DEBUGMSG(ZONE_INIT, (TEXT("rCLKCON: 0x%X\r\n"), pHWHead->pCLKPWR->rCLKCON));
        
        // Fin=12MHz, Fout=48MHz
        //pHWHead->pCLKPWR->rUPLLCON = 0x48032;   // ((0x48 << 12) + (0x3 << 4) + 0x2)
        //DEBUGMSG(ZONE_INIT, (TEXT("rUPLLCON: 0x%X\r\n"), pHWHead->pCLKPWR->rUPLLCON));

        //
        // MISCCR: USBD Pads, Normal mode
        //
        pHWHead->pIrqCtrlAddr->rMISCCR &= ~((3 << 12) | (1 << 3));

        // TO DO :
        // Enable USB_PULLUP on GPIO PIN (tied to USB D+) & set high
        //
/*	(Example)
        pHWHead->pIrqCtrlAddr->rGPDCON &= ~(3 << 30);    // clear GPE15
        pHWHead->pIrqCtrlAddr->rGPDCON |=  (1 << 30);    // config as output
        pHWHead->pIrqCtrlAddr->rGPDUP  |=  (1 << 15);    // pullup disabled
        pHWHead->pIrqCtrlAddr->rGPDDAT |=  (1 << 15);    // set high
*/
        DEBUGMSG(ZONE_INIT, (TEXT("rGPDCON: 0x%X\r\n"), pHWHead->pIrqCtrlAddr->rGPDCON));
        DEBUGMSG(ZONE_INIT, (TEXT("rGPDUP: 0x%X\r\n"),  pHWHead->pIrqCtrlAddr->rGPDUP));
        DEBUGMSG(ZONE_INIT, (TEXT("rGPDDAT: 0x%X\r\n"), pHWHead->pIrqCtrlAddr->rGPDDAT));
	}
	else if (pHWHead->State == OFF) 
	{
		DEBUGMSG(1, (TEXT("HW_USBClocks::OFF\r\n")));
        //
        // Disable the USB Clocks
        //
        pHWHead->pCLKPWR->rCLKCON &= ~(1<<7);

        DEBUGMSG(ZONE_INIT, (TEXT("rCLKCON: 0x%X\r\n"), pHWHead->pCLKPWR->rCLKCON));
        
        // Fin=12MHz, Fout=48MHz
        //pHWHead->pCLKPWR->rUPLLCON = 0;
        // MISCCR: USBD Pads, Suspend mode
        pHWHead->pIrqCtrlAddr->rMISCCR |= (3 << 12);

        // TO DO :
        // Disable USB_PULLUP to remove us from the bus
        
/*	(Example)
        pHWHead->pIrqCtrlAddr->rGPDCON &= ~(3 << 30);    // clear GPE15
        pHWHead->pIrqCtrlAddr->rGPDCON |=  (1 << 30);    // config as output
        pHWHead->pIrqCtrlAddr->rGPDUP  |=  (1 << 15);    // pullup disabled
        pHWHead->pIrqCtrlAddr->rGPDDAT &= ~(1 << 15);    // set low
*/
		DEBUGMSG(ZONE_INIT, (TEXT("rUPLLCON: 0x%X\r\n"), pHWHead->pCLKPWR->rUPLLCON));
	}
}


// :-)
/***************************************
  Added routines for USBD Rx:DMA Tx:ISR
 ***************************************/

BOOL InitUsbdDriverGlobals(void)
{
	BOOL	Ret;
	int i;

	if ( v_pDriverGlobals == NULL )
	{
		v_pDriverGlobals =(PDRIVER_GLOBALS)VirtualAlloc( 0,
						DRIVER_GLOBALS_PHYSICAL_MEMORY_SIZE,
						MEM_RESERVE,
						PAGE_NOACCESS);
		if ( v_pDriverGlobals == NULL )
		{
		    USBDMSG( 1, (TEXT( "InitUsbdDriverGlobals : VirtualAlloc failed!\r\n")) );
			return ( FALSE );
		}

		Ret = VirtualCopy( (LPVOID)v_pDriverGlobals,
						   (LPVOID)DRIVER_GLOBALS_PHYSICAL_MEMORY_START,
						   DRIVER_GLOBALS_PHYSICAL_MEMORY_SIZE,
						   PAGE_READWRITE | PAGE_NOCACHE
						   );

		if ( Ret == FALSE )
		{
			DEBUGMSG( ZONE_ERROR, (TEXT( "InitUsbdDriverGlobals: VirtualCopy failed!\r\n")) );
			if ( v_pDriverGlobals )
			{
				VirtualFree( v_pDriverGlobals,
							 DRIVER_GLOBALS_PHYSICAL_MEMORY_SIZE ,
							 MEM_RELEASE
							);
				v_pDriverGlobals = NULL;
			} 
			return ( FALSE );
		}
	}
	
	usbdShMem=&(v_pDriverGlobals->usbd);	

    for(i=0;i<USBD_GLOBALS_BUF_SIZE;i++)
    {
        usbdShMem->usbdRxBuf[i]=0x0;
		//usbdShMem->usbdTxBuf[i]=0x0;
    }
	usbdShMem->usbdRxRdPt=0;
	usbdShMem->usbdRxWrPt=0;
	usbdShMem->usbdRxCnt=0;
	//usbdShMem->usbdTxRdPt=0;
	//usbdShMem->usbdTxWrPt=0;
	//usbdShMem->usbdTxCnt=0;
	usbdShMem->usbdEir=0;
 	usbdShMem->usbdUir=0;
	usbdShMem->usbdDma3Int=0; 
	//usbdShMem->usbdMddRxCnt=0;
	USBDMSG( 1, (TEXT( "USBD:DRIVER_GLOBALS is initialized\r\n")) );
	return( TRUE ); 
}



BOOL UsbdAllocateVm(void)
{
	if(v_pDMAregs == NULL) 
	{
		v_pDMAregs = (volatile DMAreg *) 
			VirtualAlloc(0,sizeof(DMAreg),MEM_RESERVE, PAGE_NOACCESS);
		if(v_pDMAregs == NULL)
		{
			ERRORMSG(1,(TEXT("For DMAreg: VirtualAlloc failed!\r\n")));
			return (FALSE);
		}
		else 
		{
			if(!VirtualCopy((PVOID)v_pDMAregs,(PVOID)(DMA_BASE),sizeof(DMAreg),
				PAGE_READWRITE | PAGE_NOCACHE )) 
			{
				ERRORMSG(1,(TEXT("For pIOPregs: VirtualCopy failed!\r\n")));
				UsbdDeallocateVm();
				return (FALSE);
			}
		}
	}

	if(v_pINTregs == NULL)
	{
    	v_pINTregs = (volatile INTreg *) 
	    		VirtualAlloc(0,sizeof(INTreg),MEM_RESERVE, PAGE_NOACCESS);
   		if(v_pINTregs == NULL)
		{
	   		ERRORMSG(1,(TEXT("For INTreg: VirtualAlloc failed!\r\n")));
			return (FALSE);
	   	}
    	else 
		{
	    	if(!VirtualCopy((PVOID)v_pINTregs,(PVOID)(INT_BASE),sizeof(INTreg),
		    	   PAGE_READWRITE | PAGE_NOCACHE ))
		   	{
				ERRORMSG(1,(TEXT("For INTreg: VirtualCopy failed!\r\n")));
    				return (FALSE);
	    	}
	   	}
	}
	
	return TRUE;
}



void UsbdDeallocateVm(void)
{
	if(v_pDMAregs)
	{
		VirtualFree((void*)v_pDMAregs, sizeof(DMAreg), MEM_RELEASE);
		v_pDMAregs=NULL;
	}

	if(v_pINTregs)
	{
		VirtualFree((void*)v_pINTregs, sizeof(INTreg), MEM_RELEASE);
		v_pINTregs=NULL;
	}
}



void UsbdInitDma3(int bufIndex,int bufOffset)
{
	//ULONG usbdRxRdPt,usbdRxWrPt;

  	//If DMA3 is turned on, DMA3 should be turned off.
	if((v_pDMAregs->rDMASKTRIG3&(1<<1))!=0)
	{
		v_pDMAregs->rDMASKTRIG3=(1<<2);	//DMA3 stop
		while(v_pDMAregs->rDMASKTRIG3&(1<<1)); //wait until DMA3 stop
		usbdShMem->usbdRxRdPt=0;
		USBDMSG( 1, (TEXT("[DMA3 is stopped]\r\n")));
	}

	v_pDMAregs->rDISRCC3 = (1<<1)|(1<<0);		   //src=APB, srcAddr=fixed
	v_pDMAregs->rDISRC3 = REAL_PHYSICAL_ADDR_EP4_FIFO; //srcAddr=EP4_FIFO 
	v_pDMAregs->rDIDSTC3 = (0<<1)|(0<<0);		   //dst=AHB(memory),increase,

#if (DRIVER_GLOBALS_PHYSICAL_MEMORY_START<0xA0000000 || DMA_BUFFER_BASE<0xA0000000) 
	GENERATE_ERROR
		   	//The above two address should be non-cacheable area.
#endif  	

	realPhysicalAddr_UsbdRxBuf = \
		(ULONG)&((DRIVER_GLOBALS *)DRIVER_GLOBALS_PHYSICAL_MEMORY_START)->usbd.usbdRxBuf \
		- DMA_BUFFER_BASE + DMA_PHYSICAL_BASE;	
	//USBDMSG( 1, (TEXT( "[USBD:RPA_URxBuf=%x]"),realPhysicalAddr_UsbdRxBuf) );
	//Real physical address of usbdShMem->usbdRxBuf

	if(bufIndex==0)
	{
	   	v_pDMAregs->rDIDST3=realPhysicalAddr_UsbdRxBuf+0+bufOffset;
	}
	else
	{
		v_pDMAregs->rDIDST3=realPhysicalAddr_UsbdRxBuf+(USBD_GLOBALS_BUF_SIZE/2)+bufOffset;
	}

   	v_pDMAregs->rDCON3=(USBD_GLOBALS_BUF_SIZE-bufOffset)|(1<<31)|(0<<30)|(1<<29)|(0<<28)|(0<<27)|(4<<24)|(1<<23)|(1<<22)|(0<<20); 
	//handshake,requestor=APB,CURR_TC int enable,unit transfer,
	//single service,src=USBD,H/W request,no_autoreload,byte,CURR_TC

	v_pDMAregs->rDMASKTRIG3=(1<<1);	//DMA 3 on
	   

	USBDMSG( 1, (TEXT( "[USBD:rDIDST3=%x,rDCDST3=%x]\r\n"),v_pDMAregs->rDIDST3,v_pDMAregs->rDCDST3) );

}


⌨️ 快捷键说明

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