📄 usbrx.c
字号:
U8 mask = 1 <<qEpNumberDirection; //check whether the EP ready set or not //if ready, return 1 //else return 0; if (*(VP_U32)OTG_FUNC_EP_RDY & mask) return 1; //ready else return 0; //not ready }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{ if (!( temp & mask)){ /* original value in OTG_FUNC_EP_TOGGLE is a 0 */ *(VP_U32)(OTG_FUNC_EP_TOGGLE) = temp | toggle_mask; } else{/* original value in OTG_FUNC_EP_TOGGLE is a 1 */ *(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(); *///Jacky 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 */ //Jacky 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 */}//****************************// 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 int exit = 0; U32 m; U8 n; int i = 0; int j = 0; U32 ep_num = 0; //EP number U32 ep = 0; U8 dir = 0; // U32 mask = 0; U32 TempBuffer=0; U32 EpStartAddress = 0; //X/Y base address// EpNextBufToService = 0xFF; // 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) { //EchoMsg("EP0 OUT Done.\n"); // clear EP0 OUT done *(VP_U32)OTG_FUNC_EP_DSTAT = 0x1; ep = 0; dir = EP_OUT_DIR; ep_num = (ep*2) + dir; mask = 1 << ep_num; //read the Start Address (xbsa, ybsa) if (EpNextBufToService & (mask)) //X Buffer EpStartAddress = ((*(VP_U32)(OTG_EP_BASE+(16*ep_num)+4))&0x0000FFFF); else //Y Buffer EpStartAddress = (((*(VP_U32)(OTG_EP_BASE+(16*ep_num)+4))>>16)&0x0000FFFF); //read and decode the 8 byte Setup Packet 32bit access //for (i=0;i<8;i++) for (i=0;i<2;i++) { // _gUsbOtgDevReq[i] = *(VP_U8)(OTG_DATA_BASE + i); TempBuffer = *(VP_U32)(OTG_DATA_BASE + EpStartAddress + i*4); for (j=0;j<4;j++) _gUsbOtgDevReq[4*i+j] = ((TempBuffer >> 8*j) & 0xFF); } //Set/Clear Fill Status SetClearFillStatus(mask); // 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[1] == 0x09) && (_gUsbOtgDevReq[2] == 0x01)) HandleSetConfiguration(); } //========================== // 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 *(VP_U32)OTG_FUNC_EP_DSTAT = 0x1; //re-config the EP0OUT for status stage EP0OutForRequest();}// Set Address 00 05 02 00 00 00 00 00 void HandleSetAddress(void){ // Configure EP0 for CTRL IN (8 bytes) // EP0 for CTRL OUT configure at CommonInit (8 bytes) // endpt dir stall se MPS format xbsa ybsa bufsize totalbytes EPConfig(EP0, EP_IN_DIR, EP_NO_STALL, EP_NO_SETUP, 8, CTL_TYPE, 0, 0, 8, 0);// Enable_EP(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 ClearXYBufferInt(); //send IN with Empty packet to complete the status stage //set xfill to indicate data memory filled of EP0 IN *(VP_U32)OTG_FUNC_XFILL_STAT = EP0IN; Ready_EP_IN(0); //check for EP0 IN transfer done to send the Empty packet while (!(*(VP_U32)OTG_FUNC_EP_DSTAT & EP0IN)); //Write the Addr assiged by the host to OTG_FUNC_DEV_ADDR *(VP_U32)OTG_FUNC_DEV_ADDR = _gUsbOtgDevReq[2]; //clear EP0 IN transfer done
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -