📄 sc2410_usb_hw.c
字号:
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 + -