void CTR_HP(void) { uint8_t EPindex; int8_t epaddr; uint16_t wIstr; uint32_t wEPVal = 0; while (((wIstr = _GetISTR()) & ISTR_CTR) != 0) { _SetISTR((uint16_t)CLR_CTR); EPindex = (uint8_t)(wIstr & ISTR_EP_ID); epaddr = stm32_usbd_epaddr[EPindex]; wEPVal = _GetENDPOINT(EPindex); if ((wEPVal & EP_CTR_RX) != 0) { _ClearEP_CTR_RX(EPindex); if ((stm32_usbd_callback.on_out != NULL) && (epaddr >= 0)) { stm32_usbd_callback.on_out(stm32_usbd_callback.param, epaddr); } } else if ((wEPVal & EP_CTR_TX) != 0) { _ClearEP_CTR_TX(EPindex); if ((stm32_usbd_callback.on_in != NULL) && (epaddr >= 0)) { stm32_usbd_callback.on_in(stm32_usbd_callback.param, epaddr); } } } }
/******************************************************************************* * Function Name : CTR_HP. * Description : High Priority Endpoint Correct Transfer interrupt's service * routine. * Input : None. * Output : None. * Return : None. *******************************************************************************/ void CTR_HP(void) { uint32_t wEPVal = 0; while (((wIstr = _GetISTR()) & ISTR_CTR) != 0) { _SetISTR((uint16_t)CLR_CTR); /* clear CTR flag */ /* extract highest priority endpoint number */ EPindex = (uint8_t)(wIstr & ISTR_EP_ID); /* 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) */ else 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) */ }/* while(...) */ }
/******************************************************************************* * Function Name : CTR_HP. * Description : High Priority Endpoint Correct Transfer interrupt's service * routine. * Input : None. * Output : None. * Return : None. *******************************************************************************/ void CTR_HP(void) { u32 wEPVal = 0; while (((wIstr = ((u16) *(volatile unsigned *)(0x40005C44L))) & ISTR_CTR) != 0) { _SetISTR((u16)CLR_CTR); /* clear CTR flag */ /* extract highest priority endpoint number */ EPindex = (u8)(wIstr & ISTR_EP_ID); /* 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) */ else 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) */ }/* while(...) */ }
void USBglobalInterruptHandler() { uint16_t pending; pending = _GetCNTR() & _GetISTR(); if (pending & ISTR_CTR) { uint16_t EPindex, EPflags, EPnum; EPindex = _GetISTR() & ISTR_EP_ID; EPflags = _GetENDPOINT(EPindex); EPnum = EPflags & EPADDR_FIELD; /* The EP_SETUP bit implies the EP_CTR_RX bit. */ if (EPflags & EP_SETUP) { _ClearEP_CTR_RX(EPindex); USBDtransfer(EPnum, PID_SETUP); } else if (EPflags & EP_CTR_RX) { _ClearEP_CTR_RX(EPindex); USBDtransfer(EPnum, PID_OUT); } else if (EPflags & EP_CTR_TX) { _ClearEP_CTR_TX(EPindex); if (EPnum != 0) USBDcontinueInTransfer(EPnum); USBDtransfer(EPnum, PID_IN); } } if (pending & ISTR_DOVR) { _SetISTR(CLR_DOVR); } if (pending & ISTR_ERR) { _SetISTR(CLR_ERR); } if (pending & ISTR_SUSP) { USBDsuspend(); PWRreduce(); /* The ISTR_SUSP bit must be cleared after setting of the CNTR_FSUSP bit. */ _SetISTR(CLR_SUSP); } if (pending & ISTR_WKUP) { _SetISTR(CLR_WKUP); PWRresume(); USBDwakeup(); } if (pending & ISTR_RESET) { _SetISTR(CLR_RESET); USBDreset(FULL_SPEED); } if (pending & ISTR_SOF) { _SetISTR(CLR_SOF); USBDsof(_GetFNR() & FNR_FN); } if (pending & ISTR_ESOF) { _SetISTR(CLR_ESOF); } }
/******************************************************************************* * 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(...) */ }
void CTR_LP(void) { uint8_t EPindex; int8_t epaddr; uint16_t wIstr; volatile uint16_t wEPVal = 0; while (((wIstr = _GetISTR()) & ISTR_CTR) != 0) { EPindex = (uint8_t)(wIstr & ISTR_EP_ID); epaddr = stm32_usbd_epaddr[EPindex]; if (epaddr == 0) { if ((wIstr & ISTR_DIR) == 0) { _ClearEP_CTR_TX(ENDP0); if (stm32_usbd_callback.on_in != NULL) { stm32_usbd_callback.on_in(stm32_usbd_callback.param, epaddr); } return; } else { wEPVal = _GetENDPOINT(ENDP0); _ClearEP_CTR_RX(ENDP0); if ((wEPVal & EP_SETUP) != 0) { if (stm32_usbd_callback.on_setup != NULL) { stm32_usbd_callback.on_setup(stm32_usbd_callback.param); } } else if ((wEPVal & EP_CTR_RX) != 0) { if (stm32_usbd_callback.on_out != NULL) { stm32_usbd_callback.on_out(stm32_usbd_callback.param, epaddr); } } return; } } else { wEPVal = _GetENDPOINT(EPindex); if ((wEPVal & EP_CTR_RX) != 0) { _ClearEP_CTR_RX(EPindex); if ((stm32_usbd_callback.on_out != NULL) && (epaddr >= 0)) { stm32_usbd_callback.on_out(stm32_usbd_callback.param, epaddr); } } if ((wEPVal & EP_CTR_TX) != 0) { _ClearEP_CTR_TX(EPindex); if ((stm32_usbd_callback.on_in != NULL) && (epaddr >= 0)) { stm32_usbd_callback.on_in(stm32_usbd_callback.param, epaddr); } } } } }
/** * @brief Correct Transfer interrupt's service * @param None * @retval None */ void CTR(void) { USB_EP *ep; uint16_t count=0; uint8_t EPindex; __IO uint16_t wIstr; __IO 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 */ /* 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); ep = &((&USB_Device_dev)->dev.in_ep[0]); ep->xfer_count = GetEPTxCount(ep->num); ep->xfer_buff += ep->xfer_count; /* TX COMPLETE */ USBD_DCD_INT_fops->DataInStage(&USB_Device_dev, 0x00); } else { /* DIR = 1 */ /* DIR = 1 & CTR_RX => SETUP or OUT int */ /* DIR = 1 & (CTR_TX | CTR_RX) => 2 int pending */ ep = &((&USB_Device_dev)->dev.out_ep[0]); wEPVal = _GetENDPOINT(ENDP0); if ((wEPVal &EP_SETUP) != 0) { /* Get SETUP Packet*/ ep->xfer_count = GetEPRxCount(ep->num); PMAToUserBufferCopy(&((&USB_Device_dev)->dev.setup_packet[0]),ep->pmaadress , ep->xfer_count); /* SETUP bit kept frozen while CTR_RX = 1*/ _ClearEP_CTR_RX(ENDP0); /* Process SETUP Packet*/ USBD_DCD_INT_fops->SetupStage(&USB_Device_dev); } else if ((wEPVal & EP_CTR_RX) != 0) { _ClearEP_CTR_RX(ENDP0); /* Get Control Data OUT Packet*/ ep->xfer_count = GetEPRxCount(ep->num); if (ep->xfer_count != 0) { PMAToUserBufferCopy(ep->xfer_buff, ep->pmaadress, ep->xfer_count); ep->xfer_buff+=ep->xfer_count; } /* Process Control Data OUT Packet*/ USBD_DCD_INT_fops->DataOutStage(&USB_Device_dev, 0x00); _SetEPRxCount(ENDP0, ep->maxpacket); _SetEPRxStatus(ENDP0,EP_RX_VALID); } } }/* 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); ep = &((&USB_Device_dev)->dev.out_ep[EPindex]); /* OUT double Buffering*/ if (ep->doublebuffer == 0) { count = GetEPRxCount(ep->num); if (count != 0) { PMAToUserBufferCopy(ep->xfer_buff, ep->pmaadress, count); } } else { if (GetENDPOINT(ep->num) & EP_DTOG_RX) { /*read from endpoint BUF0Addr buffer*/ count = GetEPDblBuf0Count(ep->num); if (count != 0) { PMAToUserBufferCopy(ep->xfer_buff, ep->pmaaddr0, count); } } else { /*read from endpoint BUF1Addr buffer*/ count = GetEPDblBuf1Count(ep->num); if (count != 0) { PMAToUserBufferCopy(ep->xfer_buff, ep->pmaaddr1, count); } } FreeUserBuffer(ep->num, EP_DBUF_OUT); } /*multi-packet on the NON control OUT endpoint*/ ep->xfer_count+=count; ep->xfer_buff+=count; if ((ep->xfer_len == 0) || (count < ep->maxpacket)) { /* RX COMPLETE */ USBD_DCD_INT_fops->DataOutStage(&USB_Device_dev, ep->num); } else { DCD_EP_PrepareRx (&USB_Device_dev,ep->num, ep->xfer_buff, ep->xfer_len); } } /* if((wEPVal & EP_CTR_RX) */ if ((wEPVal & EP_CTR_TX) != 0) { ep = &((&USB_Device_dev)->dev.in_ep[EPindex]); /* clear int flag */ _ClearEP_CTR_TX(EPindex); /* IN double Buffering*/ if (ep->doublebuffer == 0) { ep->xfer_count = GetEPTxCount(ep->num); if (ep->xfer_count != 0) { UserToPMABufferCopy(ep->xfer_buff, ep->pmaadress, ep->xfer_count); } } else { if (GetENDPOINT(ep->num) & EP_DTOG_TX) { /*read from endpoint BUF0Addr buffer*/ ep->xfer_count = GetEPDblBuf0Count(ep->num); if (ep->xfer_count != 0) { UserToPMABufferCopy(ep->xfer_buff, ep->pmaaddr0, ep->xfer_count); } } else { /*read from endpoint BUF1Addr buffer*/ ep->xfer_count = GetEPDblBuf1Count(ep->num); if (ep->xfer_count != 0) { UserToPMABufferCopy(ep->xfer_buff, ep->pmaaddr1, ep->xfer_count); } } FreeUserBuffer(ep->num, EP_DBUF_IN); } /*multi-packet on the NON control IN endpoint*/ ep->xfer_count =GetEPTxCount(ep->num); ep->xfer_buff+=ep->xfer_count; /* Zero Length Packet? */ if (ep->xfer_len == 0) { /* TX COMPLETE */ USBD_DCD_INT_fops->DataInStage(&USB_Device_dev, ep->num); } else { DCD_EP_Tx (&USB_Device_dev,ep->num, ep->xfer_buff, ep->xfer_len); } } /* if((wEPVal & EP_CTR_TX) != 0) */ }/* if(EPindex == 0) else */ }/* while(...) */ }
/******************************************************************************* * 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(...) */ }