📄 sc2440_usb_hw.c
字号:
case SUSPEND:
// should never get here
//RETAILMSG(1, (TEXT("SUSPEND\r\n")));
ASSERT(0);
goto _done;
break;
case RESUME:
// Suspend disconnects us from the USB.
// When we Resume we re-enumerate on the USB.
//RETAILMSG(1, (TEXT("RESUME => ")));
default:
pHWHead->State = IDLE;
goto _re_enable;
break;
}
//
// Initialize the USBD Controller
//
index = pHWHead->pUSBCtrlAddr->INDEX.index;
// suspend mode disable
pHWHead->pUSBCtrlAddr->PMR.sus_en = 0x0;
ASSERT(pHWHead->pUSBCtrlAddr->PMR.sus_en == 0x0);
// setup endpoint 0
pHWHead->pUSBCtrlAddr->INDEX.index = 0;
ASSERT(pHWHead->pUSBCtrlAddr->INDEX.index == 0);
pHWHead->pUSBCtrlAddr->MAXP.maxp = 0x1; // 8 BYTE
ASSERT(pHWHead->pUSBCtrlAddr->MAXP.maxp == 0x1);
pHWHead->pUSBCtrlAddr->EP0ICSR1.sopr_cdt = 1; // OUT_PKT_RDY
//ASSERT(pHWHead->pUSBCtrlAddr->EP0ICSR1.sopr_cdt == 1); // W only
pHWHead->pUSBCtrlAddr->EP0ICSR1.sse_ = 1; // SETUP_END
//ASSERT(pHWHead->pUSBCtrlAddr->EP0ICSR1.sse_ == 1); // W only
// setup endpoint 1
pHWHead->pUSBCtrlAddr->INDEX.index = 1;
ASSERT(pHWHead->pUSBCtrlAddr->INDEX.index == 1);
pHWHead->pUSBCtrlAddr->MAXP.maxp = 0x8; // 64 BYTE
ASSERT(pHWHead->pUSBCtrlAddr->MAXP.maxp == 0x8);
pHWHead->pUSBCtrlAddr->ICSR2.mode_in = 1; // IN
ASSERT(pHWHead->pUSBCtrlAddr->ICSR2.mode_in == 1);
pHWHead->pUSBCtrlAddr->ICSR2.iso = 0; // BULK
ASSERT(pHWHead->pUSBCtrlAddr->ICSR2.iso == 0);
// setup endpoint 4
pHWHead->pUSBCtrlAddr->INDEX.index = 4;
ASSERT(pHWHead->pUSBCtrlAddr->INDEX.index == 4);
pHWHead->pUSBCtrlAddr->MAXP.maxp = 0x8; // 64 BYTE
ASSERT(pHWHead->pUSBCtrlAddr->MAXP.maxp == 0x8);
pHWHead->pUSBCtrlAddr->ICSR2.mode_in = 0; // OUT
ASSERT(pHWHead->pUSBCtrlAddr->ICSR2.mode_in == 0);
pHWHead->pUSBCtrlAddr->OCSR2.iso = 0; // BULK
ASSERT(pHWHead->pUSBCtrlAddr->OCSR2.iso == 0);
// clear all EP interrupts
pHWHead->pUSBCtrlAddr->EIR.ep0_int = 0x1;
ASSERT(pHWHead->pUSBCtrlAddr->EIR.ep0_int == 0);
pHWHead->pUSBCtrlAddr->EIR.ep1_int = 0x1;
ASSERT(pHWHead->pUSBCtrlAddr->EIR.ep1_int == 0);
pHWHead->pUSBCtrlAddr->EIR.ep2_int = 0x1;
ASSERT(pHWHead->pUSBCtrlAddr->EIR.ep2_int == 0);
pHWHead->pUSBCtrlAddr->EIR.ep3_int = 0x1;
ASSERT(pHWHead->pUSBCtrlAddr->EIR.ep3_int == 0);
pHWHead->pUSBCtrlAddr->EIR.ep4_int = 0x1;
ASSERT(pHWHead->pUSBCtrlAddr->EIR.ep4_int == 0);
// clear reset int
pHWHead->pUSBCtrlAddr->UIR.reset_int = 0x1;
ASSERT(pHWHead->pUSBCtrlAddr->UIR.reset_int == 0x0);
// EP0, 1, & 4 Enabled, EP2, 3 Disabled
pHWHead->pUSBCtrlAddr->EIER.ep2_int_en = 0x0;
ASSERT(pHWHead->pUSBCtrlAddr->EIER.ep2_int_en == 0x0);
pHWHead->pUSBCtrlAddr->EIER.ep3_int_en = 0x0;
ASSERT(pHWHead->pUSBCtrlAddr->EIER.ep3_int_en == 0x0);
pHWHead->pUSBCtrlAddr->EIER.ep0_int_en = 0x1;
ASSERT(pHWHead->pUSBCtrlAddr->EIER.ep0_int_en == 0x1);
pHWHead->pUSBCtrlAddr->EIER.ep1_int_en = 0x1;
ASSERT(pHWHead->pUSBCtrlAddr->EIER.ep1_int_en == 0x1);
pHWHead->pUSBCtrlAddr->EIER.ep4_int_en = 0x1;
ASSERT(pHWHead->pUSBCtrlAddr->EIER.ep4_int_en == 0x1);
// enable reset int
pHWHead->pUSBCtrlAddr->UIER.reset_int_en = 0x1;
ASSERT(pHWHead->pUSBCtrlAddr->UIER.reset_int_en == 0x1);
if(v_pDMAregs==NULL)
{
//RETAILMSG(1, (TEXT("ERROR: SC2440_usb_hw: v_pDMAregs=NULL\r\n")));
while(1);
}
pHWHead->pUSBCtrlAddr->INDEX.index = 0x4;
*(volatile BYTE *)&pHWHead->pUSBCtrlAddr->EP4DC=0x0;
//may not be needed, not to operate DMA during initialization.
UsbdInitDma3(0,0);
usbdShMem->usbdRxRdPt=0;
usbdShMem->usbdRxWrPt=0;
usbdShMem->usbdRxCnt=0;
usbdShMem->usbdEir=0;
usbdShMem->usbdUir=0;
usbdShMem->usbdDma3Int=0;
//rEP4_DMA_FIFO=0x40; //not needed for OUT operation.
*(volatile BYTE *)&pHWHead->pUSBCtrlAddr->EP4DTL=USBD_GLOBALS_BUF_SIZE&0xff;
*(volatile BYTE *)&pHWHead->pUSBCtrlAddr->EP4DTM=(USBD_GLOBALS_BUF_SIZE>>8)&0xff;
*(volatile BYTE *)&pHWHead->pUSBCtrlAddr->EP4DTH=(USBD_GLOBALS_BUF_SIZE>>16)&0x0f;
*(volatile BYTE *)&pHWHead->pUSBCtrlAddr->OCSR2=
*(BYTE *)&pHWHead->pUSBCtrlAddr->OCSR2 | (BYTE)EPO_AUTO_CLR /*| EPO_OUT_DMA_INT_MASK*/;
//AUTO_CLR(OUT_PKT_READY is cleared automatically), interrupt_masking.
*(volatile BYTE *)&pHWHead->pUSBCtrlAddr->EP4DU=0x01; //DMA transfer unit=1byte
*(volatile BYTE *)&pHWHead->pUSBCtrlAddr->EP4DC=UDMA_OUT_DMA_RUN|UDMA_DMA_MODE_EN;
//deamnd disable,out_dma_run=run,in_dma_run=stop,DMA mode enable
//wait until DMA_CON is effective.
*(volatile BYTE *)&pHWHead->pUSBCtrlAddr->EP4DC;
for(i=0;i<10;i++);
v_pINTregs->rINTMSK&=~(BIT_DMA3); //enable DMA3 interrupt
pHWHead->pUSBCtrlAddr->INDEX.index = 0x0; //del me
_done:
LeaveCriticalSection(&pHWHead->HwRegCritSec);
USBDMSG(1, (TEXT("--SC2440_USB_Init\r\n")));
//RETAILMSG(1, (TEXT("--SC2440_USB_Init\r\n")));
}
/*************************************************************************
Process Endpoint 0 interrupt. We are called here on every EIR interrupt.
We need to check the EP0 status and send the next packet, if any. We need
to handle errors as follows:
SE - This is set if we received a new command before we finished the last
one. This happens when the host does not wish to read all reply data
(it may only be interested in the first 8 bytes of a device descriptor
to get the max packet size, for example). We will simply discard the
next data to send and continue with the normal command handling. We
need to clear SE by asserting SSE before we continue.
SST - This is set when the UDC actually issues a stall. We just clear it
and continue.
Normal setup is as follows:
OPR - This indicates a receive command packet is ready to be read. Commands
are always 8 bytes in length and follow the form defined in chapter 9.
If OPR is not set and IPR is not set and SE is not set we must be here
because IPR transitioned from 1 -> 0. This means the last packet has been
sent (ACK'd). Send the next packet, if any.
We are emulating a serial line here. The state of the modem control lines
are sent in a command packet. Extract these and set the modem status bits
as for a normal serial line. This allows the upper levels to treat this
link just like a serial line with modem control (no flow control is
explicitly required and hence is not supported.
**************************************************************************/
void SC2440_USB_DoEndpoint0(PSER_INFO pHWHead, PDWORD pModemStatus)
{
BYTE dbuf[8];
WORD len, totLen;
PUCHAR p;
unsigned int cnt=0;
struct EP0ICSR1Bits EP0ICSR1=pHWHead->pUSBCtrlAddr->EP0ICSR1;
// Endpoint 0 mode
UDC_REG_BITSET(struct INDEXBits, &pHWHead->pUSBCtrlAddr->INDEX, index, 0x0);
DEBUGMSG(1, (TEXT("++SC2440_USB_DoEndpoint0\r\n")));
//RETAILMSG(1, (TEXT("++SC2440_USB_DoEndpoint0\r\n")));
/* If there is data to send and the transmitter is open go send
* the next packet. But, do not continue to send if the host has
* aborted the transfer or sent a new one. We'll clean up below.
*/
if ((EP0ICSR1.se_sds == 0) && (EP0ICSR1.ipr_ == 0) &&
(EP0ICSR1.opr_ipr == 0) && (sendPacket))
{
DEBUGMSG( 1, (TEXT("Send remaining data !!!\r\n")));
sendData(pHWHead, sendPacket, sendPacketLength, sendTotalLength);
}
// If setup end, the host has aborted the last transfer. Kill any
//remaining packets and continue;
if (EP0ICSR1.se_sds) {
sendPacketLength = 0;
sendPacket = NULL;
UDC_REG_BITSET(struct EP0ICSR1Bits, &pHWHead->pUSBCtrlAddr->EP0ICSR1, sse_, 1);
}
// If stall ack, not sure what needs to be done here.
if (EP0ICSR1.sts_ur)
{
DEBUGMSG( 1, (TEXT("Stall ACK set\r\n")));
UDC_REG_BITSET(struct EP0ICSR1Bits, &pHWHead->pUSBCtrlAddr->EP0ICSR1, sts_ur, 0); // 0 -> clear
}
// If new command received ...
DEBUGMSG(1, (TEXT("OUT_PKT_RDY = 0x%x\r\n"), EP0ICSR1.opr_ipr));
// if (EP0ICSR1.opr_ipr)
if (EP0ICSR1.opr_ipr)
{
// New command with existing data. Not sure how this can happen but if
// it does just clear the old data and continue.
if (sendPacket)
sendPacket = NULL;
cnt = pHWHead->pUSBCtrlAddr->OFCR1.out_cnt_low | pHWHead->pUSBCtrlAddr->OFCR2.out_cnt_high << 8;
DEBUGMSG(1,(TEXT("UDC received setup, EP0ICSR1 %x, len %d\n"),
EP0ICSR1, cnt));
// Read the command from the input FIFO
if (getCommand(pHWHead, (void*)&pHWHead->dReq) != 0)
{
sendDone(pHWHead,1);
}
DEBUGMSG(1,
(TEXT("bmRequest: %02x bRequest: %02x wValue: %04x wIndex: %04x wLength: %04x\n"),
pHWHead->dReq.bmRequest,
pHWHead->dReq.bRequest,
pHWHead->dReq.wValue,
pHWHead->dReq.wIndex,
pHWHead->dReq.wLength));
// Decode and execute the command. We support two sets of commands, vendor
// specific (modem control) and chapter 9 standard commands.
if (pHWHead->dReq.bmRequest & 0x60) // vendor or class command
{
DEBUGMSG(1, (TEXT("Vendor/Class Command !!\n")));
if (SET_CONTROL_LINE_STATE == pHWHead->dReq.bRequest)
{
// Host is notifying us of control line state.
// wValue contains bitmask
// 0 - DTR
// 1 - RTS
DEBUGMSG(1, (TEXT("SET_CONTROL_LINE_STATE %4.4X\r\n"),
pHWHead->dReq.wValue));
if (pHWHead->dReq.wValue & 0x01)
*pModemStatus |= (MS_DSR_ON|MS_RLSD_ON); // DTR active, set DSR/RLSD
else
*pModemStatus &= ~(MS_DSR_ON|MS_RLSD_ON); // DTR clear, clr DSR/RLSD
if (pHWHead->dReq.wValue & 0x02)
*pModemStatus |= MS_CTS_ON; // RTS active, set CTS
else
*pModemStatus &= ~MS_CTS_ON; // RTS clear, clear CTS
}
else {
// Unknown vendor/class request
DEBUGMSG(1,(TEXT("Unknown vendor/class request %2.2X\r\n"),
pHWHead->dReq.bRequest));
}
// Command is complete
sendDone(pHWHead,0);
return;
}
// standard chapter 9 commands
switch (pHWHead->dReq.bRequest) {
case GET_STATUS:
RETAILMSG(1, (TEXT("GET_STATUS\r\n")));
dbuf[0] = 0;
dbuf[1] = 0;
// If this is a request to the endpoint return the stalled status.
if (pHWHead->dReq.bmRequest == 0x82) {
dbuf[0] = 0;
switch (pHWHead->dReq.wIndex & 15) {
// Control endpoint can't stall (we wouldn't get this message).
case 0:
break;
// OUT endpoint. Return send_stall.
case 1:
UDC_REG_BITSET(struct INDEXBits, &pHWHead->pUSBCtrlAddr->INDEX, index, 0x4);
if (pHWHead->pUSBCtrlAddr->OCSR1.send_stall)
dbuf[0] = 1;
break;
// IN endpoint. Return send_stall.
case 2:
//case 3:
case 4:
UDC_REG_BITSET(struct INDEXBits, &pHWHead->pUSBCtrlAddr->INDEX, index, 0x1);
if (pHWHead->pUSBCtrlAddr->EP0ICSR1.se_sds)
dbuf[0] = 1;
break;
}
UDC_REG_BITSET(struct INDEXBits, &pHWHead->pUSBCtrlAddr->INDEX, index, 0);
}
// Clear the OPR bit and start the data phase
sendCommandDone(pHWHead);
// Send the reply data.
sendData(pHWHead, dbuf, 2, 2);
//RETAILMSG(1, (TEXT("GS[0x%X]\r\n"), pHWHead->dReq.wIndex & 0xFF));
break;
case CLEAR_FEATURE:
DEBUGMSG(1, (TEXT("CLEAR_FEATURE\r\n")));
if (pHWHead->dReq.bmRequest == 0x02) { // Halt
switch (pHWHead->dReq.wIndex & 15) {
// Control endpoint. Not suggested.
case 0:
break;
// OUT endpoint. Set and clear sendstall to reset DATA0/DATA1.
case 1:
UDC_REG_BITSET(struct INDEXBits, &pHWHead->pUSBCtrlAddr->INDEX, index, 0x4);
UDC_REG_BITSET(struct OCSR1Bits,
&pHWHead->pUSBCtrlAddr->OCSR1,send_stall,1); // STALL!!!
UDC_REG_BITSET(struct OCSR1Bits,
&pHWHead->pUSBCtrlAddr->OCSR1,send_stall,0);
UDC_REG_BITSET(struct OCSR1Bits,
&pHWHead->pUSBCtrlAddr->OCSR1,sent_stall,0); // CLEAR STALL
break;
// IN endpoint. Set and clear sendstall to reset DATA0/DATA1.
case 2:
//case 3:
case 4:
UDC_REG_WRITE(struct INDEXBits, &pHWHead->pUSBCtrlAddr->INDEX, index, 0x1);
UDC_REG_BITSET(struct EP0ICSR1Bits,
&pHWHead->pUSBCtrlAddr->EP0ICSR1,se_sds,1); // STALL!!!
UDC_REG_BITSET(struct EP0ICSR1Bits,
&pHWHead->pUSBCtrlAddr->EP0ICSR1,se_sds,0);
UDC_REG_BITSET(struct EP0ICSR1Bits,
&pHWHead->pUSBCtrlAddr->EP0ICSR1,sds_sts,0); // CLEAR STALL
break;
}
UDC_REG_BITSET(struct INDEXBits, &pHWHead->pUSBCtrlAddr->INDEX, index, 0);
}
// Command is complete
sendDone(pHWHead,0);
//RETAILMSG(1, (TEXT("CF[0x%X]\r\n"), pHWHead->dReq.wIndex & 0xFF));
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -