📄 usbrx.c
字号:
void Enable_EP(U8 ep_num){ U32 ep_state = 0; U32 mask = 1 << ep_num; ep_state = *(VP_U32)(OTG_FUNC_EP_EN); if (ep_state & mask){ /* $display("INFO: Enable_EP was called but EP %0x (%x) was already enabled!", ep_num, ep_state);*/ } else{ *(VP_U32)(OTG_FUNC_EP_EN) = ep_state | mask; /* enable the EP if it's not enabled*/ }}void WriteEPToggleBit(U8 ep, U8 dir, U8 toggle_val){ U8 ep_num = (ep * 2) + dir ; U32 temp; U32 toggle_mask; U32 mask; mask = 1 << ep_num; toggle_mask = toggle_val << ep_num; temp = *(VP_U32)(OTG_FUNC_EP_TOGGLE); if ( (temp & mask) == toggle_mask) { /* value in OTG_FUNC_EP_TOGGLE is already what is required, nothing is done */ } else { *(VP_U32)(OTG_FUNC_EP_TOGGLE) = toggle_mask; }}void Ready_EP_IN(U8 ep){ U8 ep_num = (ep * 2) + 1; U32 mask = 1 << ep_num; toggle_ready_ep(ep_num, 1); EP_active = EP_active | mask; /* set the EP active for DGC purpose */}void Ready_EP_OUT(U8 ep){ U8 ep_num = (ep * 2) + 0; U32 mask = 1 << ep_num; toggle_ready_ep(ep_num, 1); EP_active = EP_active | mask; /* set the EP active for DGC purpose */}void unready_ep_in(U8 ep){ U8 ep_num = (ep * 2) + 1; toggle_ready_ep(ep_num, 0); Clear_active_ep(ep_num);}void unready_ep_out(U8 ep){ U8 ep_num = (ep * 2) + 0; toggle_ready_ep(ep_num, 0); Clear_active_ep(ep_num);}void Clear_active_ep(U8 ep_num){ U32 mask = 1 << ep_num; if (EP_active & mask){ /* if "1", clear to "0" */ EP_active -= mask; }/*else, do nothing as the Ep is already inactive. */}void toggle_ready_ep(U8 ep_num, U8 ready){ U8 rAlreadyReady; U32 mask = 1 << ep_num; rAlreadyReady = check_ep_ready(ep_num); if (rAlreadyReady && ready){ /*$display("INFO: toggle_ready_ep was called but EP %0x (%x) was already ready! It will not be modified.", ep_num, ep_state);*/ } else{ if (!rAlreadyReady && !ready){ /*$display("INFO: toggle_ready_ep was called but EP %0x (%x) was already un-ready! It will not be modified.", ep_num, ep_state);*/ } else{ *(VP_U32)(OTG_FUNC_EP_RDY) = mask; /* write 1 to toggle current state */ } }}void OtgPort_PullUpEnabled(){ /* need to modify if Non-i2c mode is desired. See TDI's user_tasks.v */ if (r_i2cHwSw){ *(VP_U32)(OTG_CORE_HNP_CSTAT) = 0x00000800; } else{ i2cDpPullUp(); }}void i2cDpPullUp(){ i2cSingleRegWrite(OTG_CTRL_REG1_SET_ADD, (U8)I2C_MASK_DP_PULLUP); i2cSingleRegWrite(OTG_CTRL_REG1_CLR_ADD, (U8)I2C_MASK_DP_PULLDOWN);}void i2cSetSeqOpReg(U8 qWrData){ i2cCheckBusy(); *(VP_U8)(SEQ_OP_REG_ADD)= qWrData;}void i2cCheckBusy(){// U8 rRdData; U32 timeout = TIMEOUT_VALUE; // rRdData = *(VP_U8)(I2C_OP_CTRL_REG_ADD); // if (rRdData & 0x80){ while (*(VP_U8)(I2C_OP_CTRL_REG_ADD) & 0x80) /*busy waiting for bus to become unbusy */ { timeout--; if (!timeout) break; } // } }void i2cSetSeqRdStartAd(U8 qWrData){ i2cCheckBusy(); //wait until i2c not busy *(VP_U8)(SEQ_RD_STARTAD_ADD) = qWrData; //write the addr to be configured in i2c to 0x }/*------------------------------------------------------------------------------------*//*single i2c register write*//*write a byte only*//*wait for i2c Ready interrut event to know the register write is done*//*need to add timer watch dog later*//*need to add xcvr interrupt disable logic later*//*------------------------------------------------------------------------------------*/void i2cSingleRegWrite(U32 qRegAddr, U8 qWrData){ int timeout=TIMEOUT_VALUE; *(VP_U8)(qRegAddr) = qWrData; i2cSetSeqOpReg(1); i2cSetSeqRdStartAd(qRegAddr); *(VP_U8)(OTG_XCVR_DEVAD_ADD)=0x2d; /* Poll for i2c ready interrupt --- need to be removed if ISR is used */ /* while( !(*(VP_U8)(I2C_MASTER_INT_REG_ADD) & 0x02) ); i2cReadyIntHandler(); *///20030821 begin // Poll for i2c ready interruptd while( !(*(volatile p_uint8_t)(I2C_MASTER_INT_REG_ADD) & 0x02) ) { //pprintf("not ready.\n"); timeout--; if (!timeout) break; } //clear the RWREADY bit after it set if (*(volatile p_uint8_t)(I2C_MASTER_INT_REG_ADD) & 0x2) { //pprintf("yes, the flag is 1. should be cleared.\n"); *(volatile p_uint8_t)(I2C_MASTER_INT_REG_ADD) = 0x2; if (*(volatile p_uint8_t)(I2C_MASTER_INT_REG_ADD) & 0x2) { EchoMsg("clear is invalid.\n"); } } /* End of polling */ //20030821 end // while(!eINTI2CREADY);// eINTI2CREADY = 0; /* Clear the event */ //EchoMsg("i2cSingleRegWrite end.\n");}/*void ToggleNextBufferToService(U8 mask){ // 5) Toggle NextBufferToService // if (EpNextBufToService & mask) //"1"- set to "0" EpNextBufToService -= mask; else //"0" - set to "1" // EpNextBufToService = EpNextBufToService | mask;}*/void DefaultXBufferToService(U8 mask){ EpNextBufToService = EpNextBufToService | mask;}void SetClearFillStatus(U8 mask){ /* 4) Set/Clear FILL_STATUS */ if(EpNextBufToService & mask)/* X buffer */ *(VP_U32)(OTG_FUNC_XFILL_STAT) = mask; /*write to toggle the correct EP's X buffer status*/ else /* y buffer */ *(VP_U32)(OTG_FUNC_YFILL_STAT) = mask; /*write to toggle the correct EP's Y buffer status */}//due to teh MOT-ERRATA1;//Software must clear X and Y buffer interruptsvoid ClearXYBufferInt(void){ U32 temp=0; temp = *(VP_U32)OTG_FUNC_XINT_STAT; *(VP_U32)OTG_FUNC_XINT_STAT = temp; temp = *(VP_U32)OTG_FUNC_XINT_STAT; *(VP_U32)OTG_FUNC_YINT_STAT = temp; }void EP0OutForRequest(void){ /* Configure EP0 for CTRL SETUP (8 bytes) */ EPConfig(0, EP_OUT_DIR, EP_NO_STALL, EP_NO_SETUP, 8, CTL_TYPE, 0, 0, 8, 8); // Enable_EP(0); /* Enable EP0-OUT to accept CTRL SETUP */// Ready_EP_OUT(0); /* Ready EP0 */}void Return0x00(void){ int k=0; U32 EpStartAddress=0; EPConfig(EP0, EP_IN_DIR, 0, 0, 8, CTL_TYPE, (0*16), 0x200, 8, 1); // need to manually toggle because this is EP0 IN, previous transactions is EP0 SETUP (Out) // as this is the first transfer of EP0 IN, it suppose to DATA0 seq bit // but since this is a CTRL transfer, SETUP (EP0 OUT) follow by STATUS (EP0 IN) // thus although first transfer, it need to send DATA1, thus need to be manually toggle WriteEPToggleBit(EP0, EP_IN_DIR ,1); //Toggle Status Stage In PID from DATA0 to DATA1 //X Buffer Used EpStartAddress = ((*(VP_U32)(OTG_EP_BASE+(16*1)+4))&0x0000FFFF); //write the 8 bytes data to the XBuff for (k=0;k<2;k++) *(VP_U32)(OTG_DATA_BASE + EpStartAddress + (k*0x4)) = 0x00 ; ClearXYBufferInt(); //Ready EP0 IN Ready_EP_IN(EP0); //Set/Clear Fill Status SetClearFillStatus(EP0IN); //to complete the status stage of Setup EP0Out_StatusStageTransferDone();}void HandleSetupPacket(void){ uint32_t i = 0; uint32_t j=0; uint32_t EpStartAddress = 0; uint32_t TempPtr; for (i=0;i<8;i++) _gUsbOtgDevReq [i] = i+1; //===================== // Wait for Setup Done //===================== // clear EP0 OUT done *(VP_U32)OTG_FUNC_EP_DSTAT = EP0OUT; //read the Start Address (xbsa, ybsa) EpStartAddress = ((*(volatile p_uint32_t)(OTG_EP_BASE + 4))&0x0000FFFF); //read and decode the 8 byte Setup Packet with 32bit access for (i=0;i<2;i++) { TempPtr = *(p_uint32_t)(OTG_DATA_BASE + EpStartAddress + i*4); for (j=0;j<4;j++) _gUsbOtgDevReq[j+4*i] = (TempPtr >> (j*8)); } //Set/Clear Fill Status SetClearFillStatus(EP0OUT); // Set Address 00 05 02 00 00 00 00 00 if (_gUsbOtgDevReq[1] == 0x05) HandleSetAddress(); // Get Descriptor, Device Type 80 06 00 01 00 00 40 00 else if ((_gUsbOtgDevReq[0] == 0x80) && (_gUsbOtgDevReq[1] == 0x06)) HandleGetDescriptor(); // Set Configuration, 00 09 01 00 00 00 00 00 else if ((_gUsbOtgDevReq[0] == 0x00) && (_gUsbOtgDevReq[1] == 0x09) && (_gUsbOtgDevReq[2] == 0x01)) { HandleSetConfiguration(); _gSetConfigurationReceived = 1; } else if ((_gUsbOtgDevReq[0] == 0xA1) && (_gUsbOtgDevReq[1]==0xFE) && (_gUsbOtgDevReq[6] == 0x01)) { if (_gSetConfigurationReceived) { for (i=0;i<3;i++) { //wait for the 3 more EP0 Done status if ((*(VP_U32)OTG_FUNC_EP_DSTAT & EP0OUT)) { HandleSetupPacket(); // Configure EP0 for CTRL SETUP (8 bytes) EPConfig(EP0, EP_OUT_DIR, EP_NO_STALL, EP_NO_SETUP, 8, CTL_TYPE, 0, 0, 8, 8); // Enable EP0 OUT to accept CTRL SETUP, unless READY bit set, the device will keep NAK the host Enable_EP(EP0OUT); // Enable EP0 IN to complete the status stage Enable_EP(EP0IN); // Ready EP0 to ACK the host Ready_EP_OUT(EP0); } } } // return 0x00 only Return0x00(); }}//****************************// End of OTG related function//****************************//********************************************************************// usbotg_main.c//********************************************************************U32 Usbotg_main(){ U32 PC_change_Address = 0; //store the Address to be changed in PC //0 : no PC change // jump to the while loop, // this while loop is used to poll for the EP0 OUT status, for DEVREQ & // EP1 OUT done status, which is used to received the command from the PC // exit only when Change PC command received // Configure EP1 for BULK IN EPConfig(EP1, EP_IN_DIR, 0, 0, 32, BLK_TYPE, 0x100, 0x200, 32, 32); Enable_EP(3); // Configure EP2 for BULK OUT EPConfig(EP2,EP_OUT_DIR, EP_NO_STALL, EP_NO_SETUP, 32, BLK_TYPE, 0, 0, 32, 31); Enable_EP(4); Ready_EP_OUT(2); quit=0; while (!quit) { //===================== // Wait for Setup Done //===================== // wait for EP0 OUT done if (*(VP_U32)OTG_FUNC_EP_DSTAT & 0x1) { HandleSetupPacket(); } //========================== // Wait for Bulk OUT at EP1 // Command form PC host (16 bytes) //========================== if (*(VP_U32)OTG_FUNC_EP_DSTAT & 0x10) { // clear EP2 OUT done *(VP_U32)OTG_FUNC_EP_DSTAT = 0x10; ClearXYBufferInt(); unready_ep_out(EP2); processCommand(); // Configure EP2 for BULK OUT EPConfig(EP2, EP_OUT_DIR, EP_NO_STALL, EP_NO_SETUP, 32, BLK_TYPE, 0, 0, 32, 31); Ready_EP_OUT(2); } EPConfig(EP0, EP_OUT_DIR, EP_NO_STALL, EP_NO_SETUP, 8, CTL_TYPE, 0, 0, 8, 8); Enable_EP(EP0OUT); Enable_EP(EP0IN); Enable_EP(EP1IN); } //EchoMsg("Usbotg_main end...\n"); return PC_change_Address;}//*******************************************************************// usbotg.c//*******************************************************************void EP0Out_StatusStageTransferDone(void){ //EPConfig for EP0 OUT //DW0 = 0x00080000 configure EP0 for CTRL setup //DW1 = 0x00000000 //DW2 reserved //DW3 = 0x00E00000 TotalByteCnt = 0 bytes//void EPConfig(U32 ep, U32 dir, U32 stall, U32 setup, U32 MPS, U32 format, U32 xbsa, U32 ybsa, U32 Bufsize, U32 Tbyte){ /* Configure EP0 for CTRL SETUP (0 bytes) */ EPConfig(0, EP_OUT_DIR, EP_NO_STALL, EP_NO_SETUP, 8, CTL_TYPE, 0, 0, 7, 0); // Enable_EP(0); /* Enable EP0-OUT to accept CTRL SETUP */ Ready_EP_OUT(0); /* Ready EP0 */ //check for EP0 OUT transfer done while (!(*(VP_U32)OTG_FUNC_EP_DSTAT & 0x1)); //clear EP0 OUT transfer done
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -