📄 sc2440_usb_hw.c
字号:
When the packet is accepted we return the number of bytes and grab the
next packet (or portion thereof).
*************************************************************************/
//:-)
void SC2440_USB_TxIntHandler( PSER_INFO pHWHead,
PUCHAR pTxBuffer,
ULONG *pBuffLen )
{
unsigned int i;
UCHAR ucLen;
BYTE saveIndex;
//DEBUGMSG(1, (TEXT("++SC2440_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(0, (TEXT("Write Pend !!!\r\n")));
*pBuffLen = 0;
}
//DEBUGMSG(0, (TEXT("--SC2440_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
//
//pHWHead->pIrqCtrlAddr->rGPBCON &= ~(3 << 18); // clear GPE15
//pHWHead->pIrqCtrlAddr->rGPBCON |= (1 << 18); // config as output
//pHWHead->pIrqCtrlAddr->rGPBUP &= ~(1 << 9); // pullup disabled
//pHWHead->pIrqCtrlAddr->rGPBDAT |= (1 << 9); // set high
pHWHead->pIrqCtrlAddr->rGPGCON &= ~(3 << 24); // clear GPE15
pHWHead->pIrqCtrlAddr->rGPGCON |= (1 << 24); // config as output
pHWHead->pIrqCtrlAddr->rGPGUP &= ~(1 << 12); // pullup disabled
pHWHead->pIrqCtrlAddr->rGPGDAT |= (1 << 12); // 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
//pHWHead->pIrqCtrlAddr->rGPBCON &= ~(3 << 18); // clear GPE15
//pHWHead->pIrqCtrlAddr->rGPBCON |= (1 << 18); // config as output
//pHWHead->pIrqCtrlAddr->rGPBUP |= (1 << 9); // pullup disabled
//pHWHead->pIrqCtrlAddr->rGPBDAT &= ~(1 << 9); // set low
pHWHead->pIrqCtrlAddr->rGPGCON &= ~(3 << 24); // clear GPE15
pHWHead->pIrqCtrlAddr->rGPGCON |= (1 << 24); // config as output
pHWHead->pIrqCtrlAddr->rGPGUP |= (1 << 12); // pullup disabled
pHWHead->pIrqCtrlAddr->rGPGDAT &= ~(1 << 12); // 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 + -