/******************************************************************************* * Function Name : CTR_LP. * Description : Low priority Endpoint Correct Transfer interrupt's service * routine. * Input : None. * Output : None. * Return : None. *******************************************************************************/ void CTR_LP(void) { volatile uint16_t wEPVal = 0; /* stay in loop while pending interrupts */ while (((wIstr = _GetISTR()) & ISTR_CTR) != 0) { /* extract highest priority endpoint number */ EPindex = (uint8_t)(wIstr & ISTR_EP_ID); if (EPindex == 0) { /* Decode and service control endpoint interrupt */ /* calling related service routine */ /* (Setup0_Process, In0_Process, Out0_Process) */ /* save RX & TX status */ /* and set both to NAK */ SaveRState = _GetENDPOINT(ENDP0); SaveTState = SaveRState & EPTX_STAT; SaveRState &= EPRX_STAT; _SetEPRxTxStatus(ENDP0,EP_RX_NAK,EP_TX_NAK); /* DIR bit = origin of the interrupt */ if ((wIstr & ISTR_DIR) == 0) { /* DIR = 0 */ /* DIR = 0 => IN int */ /* DIR = 0 implies that (EP_CTR_TX = 1) always */ _ClearEP_CTR_TX(ENDP0); In0_Process(); /* before terminate set Tx & Rx status */ _SetEPRxTxStatus(ENDP0,SaveRState,SaveTState); return; } else { /* DIR = 1 */ /* DIR = 1 & CTR_RX => SETUP or OUT int */ /* DIR = 1 & (CTR_TX | CTR_RX) => 2 int pending */ wEPVal = _GetENDPOINT(ENDP0); if ((wEPVal &EP_SETUP) != 0) { _ClearEP_CTR_RX(ENDP0); /* SETUP bit kept frozen while CTR_RX = 1 */ Setup0_Process(); /* before terminate set Tx & Rx status */ _SetEPRxTxStatus(ENDP0,SaveRState,SaveTState); return; } else if ((wEPVal & EP_CTR_RX) != 0) { _ClearEP_CTR_RX(ENDP0); Out0_Process(); /* before terminate set Tx & Rx status */ _SetEPRxTxStatus(ENDP0,SaveRState,SaveTState); return; } } }/* if(EPindex == 0) */ else { /* Decode and service non control endpoints interrupt */ /* process related endpoint register */ wEPVal = _GetENDPOINT(EPindex); if ((wEPVal & EP_CTR_RX) != 0) { /* clear int flag */ _ClearEP_CTR_RX(EPindex); /* call OUT service function */ (*pEpInt_OUT[EPindex-1])(); } /* if((wEPVal & EP_CTR_RX) */ if ((wEPVal & EP_CTR_TX) != 0) { /* clear int flag */ _ClearEP_CTR_TX(EPindex); /* call IN service function */ (*pEpInt_IN[EPindex-1])(); } /* if((wEPVal & EP_CTR_TX) != 0) */ }/* if(EPindex == 0) else */ }/* while(...) */ }
/******************************************************************************* * Function Name : OTGD_FS_Handle_InEP_ISR * Description : Handles all IN endpoints interrupts. * Output : None * Return : status *******************************************************************************/ uint32_t OTGD_FS_Handle_InEP_ISR(void) { USB_OTG_DIEPINTx_TypeDef diepint; uint32_t ep_intr = 0; uint32_t epnum = 0; USB_OTG_EP *ep; uint32_t fifoemptymsk = 0; diepint.d32 = 0; ep_intr = OTGD_FS_ReadDevAllInEPItr(); while ( ep_intr ) { if (ep_intr&0x1) /* In ITR */ { ep = PCD_GetInEP(epnum); diepint.d32 = PCD_ReadDevInEP(ep); /* Get In ITR status */ if ( diepint.b.xfercompl ) { fifoemptymsk = 0x1 << ep->num; USB_OTG_MODIFY_REG32(&USB_OTG_FS_regs.DEV->DIEPEMPMSK, fifoemptymsk, 0); /* Clear the Interrupt flag */ CLEAR_IN_EP_INTR(epnum, xfercompl); if (epnum == 0) { /* Call the core IN process for EP0 */ In0_Process(); /* before terminate set Tx & Rx status */ OTG_DEV_SetEPRxStatus(epnum, SaveRState); OTG_DEV_SetEPTxStatus(epnum, SaveTState); } else { /* Call the relative IN endpoint callback */ (*pEpInt_IN[epnum -1])(); } } if ( diepint.b.timeout ) { CLEAR_IN_EP_INTR(epnum, timeout); } if (diepint.b.intktxfemp) { CLEAR_IN_EP_INTR(epnum, intktxfemp); } if (diepint.b.inepnakeff) { CLEAR_IN_EP_INTR(epnum, inepnakeff); } if (diepint.b.txfempty) { if ((epnum == 0) || (OTG_DEV_GetEPTxStatus(epnum) == DEV_EP_TX_VALID)) { PCD_WriteEmptyTxFifo(epnum); } CLEAR_IN_EP_INTR(epnum, txfempty); } if ( diepint.b.epdis) { /* Reset Endpoint Frame ID to 0 */ ep->even_odd_frame = 0; CLEAR_IN_EP_INTR(epnum, epdis); } } epnum++; ep_intr >>= 1; } /* Call user function */ INTR_INEPINTR_Callback(); return 1; }
static void handle_in0(void) { In0_Process(); }
/******************************************************************************* * Function Name : CTR_LP. * Description : Low priority Endpoint Correct Transfer interrupt's service * routine. * Input : None. * Output : None. * Return : None. *******************************************************************************/ void CTR_LP(void) { __IO uint16_t wEPVal = 0; // stay in loop while pending interrupts while ((wIstr = *ISTR) & ISTR_CTR) { // extract highest priority endpoint number EPindex = (uint8_t)(wIstr & ISTR_EP_ID); if (EPindex == 0) { // Decode and service control endpoint interrupt // calling related service routine // (Setup0_Process, In0_Process, Out0_Process) // save RX & TX status and set both to NAK SaveRState = _GetENDPOINT(ENDP0); SaveTState = SaveRState & EPTX_STAT; SaveRState &= EPRX_STAT; SetEPRxTxStatus(ENDP0,EP_RX_NAK,EP_TX_NAK); // DIR bit = origin of the interrupt if ((wIstr & ISTR_DIR) == 0) { // DIR = 0 => IN int // DIR = 0 implies that (EP_CTR_TX = 1) always ClearEP_CTR_TX(ENDP0); In0_Process(); // before terminate set Tx & Rx status SetEPRxTxStatus(ENDP0,SaveRState,SaveTState); return; } else { // DIR = 1 & CTR_RX => SETUP or OUT int // DIR = 1 & (CTR_TX | CTR_RX) => 2 int pending wEPVal = _GetENDPOINT(ENDP0); if ((wEPVal &EP_SETUP) != 0) { ClearEP_CTR_RX(ENDP0); // SETUP bit kept frozen while CTR_RX = 1 Setup0_Process(); // before terminate set Tx & Rx status SetEPRxTxStatus(ENDP0,SaveRState,SaveTState); return; } else if ((wEPVal & EP_CTR_RX) != 0) { ClearEP_CTR_RX(ENDP0); Out0_Process(); // before terminate set Tx & Rx status SetEPRxTxStatus(ENDP0,SaveRState,SaveTState); return; } } } else { // Decode and service non control endpoints interrupt // process related endpoint register wEPVal = _GetENDPOINT(EPindex); if ((wEPVal & EP_CTR_RX) != 0) { // clear int flag ClearEP_CTR_RX(EPindex); // call OUT service function (*pEpInt_OUT[EPindex-1])(); } if ((wEPVal & EP_CTR_TX) != 0) { // clear int flag ClearEP_CTR_TX(EPindex); // call IN service function (*pEpInt_IN[EPindex-1])(); } } } }
/******************************************************************************* * Function Name : CTR_LP. * Description : Low priority Endpoint Correct Transfer interrupt's service * routine. * Input : None. * Output : None. * Return : None. *******************************************************************************/ void CTR_LP(void) { u32 wEPVal = 0; // wIstr = *ISTR; /* stay in loop while pending ints */ while (((wIstr = (*ISTR)) & ISTR_CTR) != 0) //正确传输 { _SetISTR((u16)CLR_CTR); /* clear CTR flag 清正确传输中断*/ /* extract highest priority endpoint number */ EPindex = (u8)(wIstr & ISTR_EP_ID);//ISTR_EP_ID (0x000F) 这个只读,所以与0X000F& if (EPindex == 0) //如果是端点0 { /* Decode and service control endpoint interrupt */ /* calling related service routine */ /* (Setup0_Process, In0_Process, Out0_Process) */ /* save RX & TX status */ /* and set both to NAK */ SaveRState = _GetEPRxStatus(ENDP0); SaveTState = _GetEPTxStatus(ENDP0); _SetEPRxStatus(ENDP0, EP_RX_NAK); //当一次正确的OUT或SETUP数据传输完成后(CTR_RX=1), _SetEPTxStatus(ENDP0, EP_TX_NAK); //硬件会自动设置此位为NAK状态, //使应用程序有足够的时间在处理完当前传输的数据后, //响应下一个数据分组。 /* DIR bit = origin of the interrupt */ if ((wIstr & ISTR_DIR) == 0) //0x0010 如果是输入 { /* DIR = 0 */ /* DIR = 0 => IN int */ /* DIR = 0 implies that (EP_CTR_TX = 1) always */ _ClearEP_CTR_TX(ENDP0); In0_Process(); /* before terminate set Tx & Rx status */ _SetEPRxStatus(ENDP0, SaveRState); _SetEPTxStatus(ENDP0, SaveTState); return; } else //输出 { /* DIR = 1 */ /* DIR = 1 & CTR_RX => SETUP or OUT int */ /* DIR = 1 & (CTR_TX | CTR_RX) => 2 int pending */ //EP0的值 wEPVal =(u16)(*((volatile unsigned *)(0x40005C00L) + ENDP0)); if ((wEPVal & EP_CTR_TX) != 0) //硬件在一个正确的IN分组传输完成后置位 { _ClearEP_CTR_TX(ENDP0); In0_Process(); /* before terminate set Tx & Rx status */ _SetEPRxStatus(ENDP0, SaveRState); //SaveTState=EP_TX_STALL; 在In0_Process() _SetEPTxStatus(ENDP0, SaveTState); //SaveTState=EP_TX_STALL; 在In0_Process() return; } //控制传输由3个阶段组成,首先是主机发送SETUP分组的SETUP阶段, //然后是主机发送零个或多个数据的数据阶段,最后是状态阶段,由与数据阶段方向相反的数据分组构成 //据SETUP分组的相应字段决定后面的传输是IN还是OUT。 else if ((wEPVal &EP_SETUP) != 0) //在USB模块收到一个正确的SETUP分组后由硬件置位 { _ClearEP_CTR_RX(ENDP0); /* SETUP bit kept frozen while CTR_RX = 1 */ Setup0_Process(); /* before terminate set Tx & Rx status */ _SetEPRxStatus(ENDP0, SaveRState); _SetEPTxStatus(ENDP0, SaveTState); return; } else if ((wEPVal & EP_CTR_RX) != 0) { _ClearEP_CTR_RX(ENDP0); Out0_Process(); /* before terminate set Tx & Rx status */ _SetEPRxStatus(ENDP0, SaveRState); _SetEPTxStatus(ENDP0, SaveTState); return; } } }/* if(EPindex == 0) */ else { /* Decode and service non control endpoints interrupt */ /* process related endpoint register */ wEPVal = (u16)(*((volatile unsigned *)(0x40005C00L) + EPindex)); if ((wEPVal & EP_CTR_RX) != 0) { /* clear int flag */ _ClearEP_CTR_RX(EPindex); /* call OUT service function */ (*pEpInt_OUT[EPindex-1])(); } /* if((wEPVal & EP_CTR_RX) */ if ((wEPVal & EP_CTR_TX) != 0) { /* clear int flag */ _ClearEP_CTR_TX(EPindex); /* call IN service function */ // (*pEpInt_IN[EPindex-1])(); } /* if((wEPVal & EP_CTR_TX) != 0) */ }/* if(EPindex == 0) else */ }/* while(...) */ }