/******************************************************************************* * Function Name : Suspend * Description : sets suspend mode operating conditions * Input : None. * Output : None. * Return : USB_SUCCESS. *******************************************************************************/ void Suspend(void) { #ifndef STM32F10X_CL uint16_t wCNTR; /* suspend preparation */ /* ... */ /* macrocell enters suspend mode */ wCNTR = _GetCNTR(); wCNTR |= CNTR_FSUSP; _SetCNTR(wCNTR); /* ------------------ ONLY WITH BUS-POWERED DEVICES ---------------------- */ /* power reduction */ /* ... on connected devices */ /* force low-power mode in the macrocell */ wCNTR = _GetCNTR(); wCNTR |= CNTR_LPMODE; _SetCNTR(wCNTR); #endif /* STM32F10X_CL */ #ifdef STM32F10X_CL /* Gate the PHY and AHB USB clocks */ _OTGD_FS_GATE_PHYCLK; #endif /* STM32F10X_CL */ /* switch-off the clocks */ /* ... */ Enter_LowPowerMode(); }
/** * @brief Sets suspend mode operating conditions * @param None. * @retval USB_SUCCESS. */ void Suspend(void) { uint16_t wCNTR; /* suspend preparation */ /* ... */ /* macrocell enters suspend mode */ wCNTR = _GetCNTR(); wCNTR |= CNTR_FSUSP; _SetCNTR(wCNTR); /* ------------------ ONLY WITH BUS-POWERED DEVICES ---------------------- */ /* power reduction */ /* ... on connected devices */ /* force low-power mode in the macrocell */ wCNTR = _GetCNTR(); wCNTR |= CNTR_LPMODE; _SetCNTR(wCNTR); /* switch-off the clocks */ /* ... */ Enter_LowPowerMode(); }
/******************************************************************************* * Function Name : Resume * Description : This is the state machine handling resume operations and * timing sequence. The control is based on the Resume structure * variables and on the ESOF interrupt calling this subroutine * without changing machine state. * Input : a state machine value (RESUME_STATE) * RESUME_ESOF doesn't change ResumeS.eState allowing * decrementing of the ESOF counter in different states. * Output : None. * Return : None. *******************************************************************************/ void Resume(RESUME_STATE eResumeSetVal) { GPIOB->ODR&=~GPIO_Pin_7; uint16_t wCNTR; if (eResumeSetVal != RESUME_ESOF) ResumeS.eState = eResumeSetVal; switch (ResumeS.eState) { case RESUME_EXTERNAL: if (remotewakeupon ==0) { Resume_Init(); ResumeS.eState = RESUME_OFF; } else /* RESUME detected during the RemoteWAkeup signalling => keep RemoteWakeup handling*/ { ResumeS.eState = RESUME_ON; } break; case RESUME_INTERNAL: Resume_Init(); ResumeS.eState = RESUME_START; remotewakeupon = 1; break; case RESUME_LATER: ResumeS.bESOFcnt = 2; ResumeS.eState = RESUME_WAIT; break; case RESUME_WAIT: ResumeS.bESOFcnt--; if (ResumeS.bESOFcnt == 0) ResumeS.eState = RESUME_START; break; case RESUME_START: wCNTR = _GetCNTR(); wCNTR |= CNTR_RESUME; _SetCNTR(wCNTR); ResumeS.eState = RESUME_ON; ResumeS.bESOFcnt = 10; break; case RESUME_ON: ResumeS.bESOFcnt--; if (ResumeS.bESOFcnt == 0) { wCNTR = _GetCNTR(); wCNTR &= (~CNTR_RESUME); _SetCNTR(wCNTR); ResumeS.eState = RESUME_OFF; remotewakeupon = 0; } break; case RESUME_OFF: case RESUME_ESOF: default: ResumeS.eState = RESUME_OFF; break; } }
/******************************************************************************* * Function Name : Suspend * Description : sets suspend mode operating conditions * Input : None. * Output : None. * Return : USB_SUCCESS. *******************************************************************************/ void Suspend(void) { uint32_t i =0; uint16_t wCNTR; uint32_t tmpreg = 0; /*Store CNTR value */ wCNTR = _GetCNTR(); /* This a sequence to apply a force RESET to handle a robustness case */ /*Store endpoints registers status */ for (i=0;i<8;i++) EP[i] = _GetENDPOINT(i); /* unmask RESET flag */ wCNTR|=CNTR_RESETM; _SetCNTR(wCNTR); /*apply FRES */ wCNTR|=CNTR_FRES; _SetCNTR(wCNTR); /*clear FRES*/ wCNTR&=~CNTR_FRES; _SetCNTR(wCNTR); /*poll for RESET flag in ISTR*/ while((_GetISTR()&ISTR_RESET) == 0); /* clear RESET flag in ISTR */ _SetISTR((uint16_t)CLR_RESET); /*restore Enpoints*/ for (i=0;i<8;i++) _SetENDPOINT(i, EP[i]); /* Now it is safe to enter macrocell in suspend mode */ wCNTR |= CNTR_FSUSP; _SetCNTR(wCNTR); /* force low-power mode in the macrocell */ wCNTR = _GetCNTR(); wCNTR |= CNTR_LPMODE; _SetCNTR(wCNTR); /* enter system in STOP mode, only when wakeup flag in not set */ if((_GetISTR()&ISTR_WKUP)==0) { } else { /* Clear Wakeup flag */ _SetISTR(CLR_WKUP); /* clear FSUSP to abort entry in suspend mode */ wCNTR = _GetCNTR(); wCNTR&=~CNTR_FSUSP; _SetCNTR(wCNTR); } }
/** * @brief This is the state machine handling resume operations and timing sequence. * The control is based on the Resume structure variables and on the ESOF * interrupt calling this subroutine without changing machine state. * @param eResumeSetVal: a state machine value (RESUME_STATE) RESUME_ESOF doesn't * change ResumeS.eState allowing decrementing of the ESOF * counter in different states. * @retval None. */ void Resume(RESUME_STATE eResumeSetVal) { uint16_t wCNTR; if (eResumeSetVal != RESUME_ESOF) ResumeS.eState = eResumeSetVal; switch (ResumeS.eState) { case RESUME_EXTERNAL: Resume_Init(); ResumeS.eState = RESUME_OFF; break; case RESUME_INTERNAL: Resume_Init(); ResumeS.eState = RESUME_START; break; case RESUME_LATER: ResumeS.bESOFcnt = 2; ResumeS.eState = RESUME_WAIT; break; case RESUME_WAIT: ResumeS.bESOFcnt--; if (ResumeS.bESOFcnt == 0) ResumeS.eState = RESUME_START; break; case RESUME_START: wCNTR = _GetCNTR(); wCNTR |= CNTR_RESUME; _SetCNTR(wCNTR); ResumeS.eState = RESUME_ON; ResumeS.bESOFcnt = 10; break; case RESUME_ON: ResumeS.bESOFcnt--; if (ResumeS.bESOFcnt == 0) { wCNTR = _GetCNTR(); wCNTR &= (~CNTR_RESUME); _SetCNTR(wCNTR); ResumeS.eState = RESUME_OFF; } break; case RESUME_OFF: case RESUME_ESOF: default: ResumeS.eState = RESUME_OFF; break; } }
/** * @brief Handles wake-up restoring normal operations * @param None. * @retval USB_SUCCESS. */ void Resume_Init(void) { uint16_t wCNTR; /* ------------------ ONLY WITH BUS-POWERED DEVICES ---------------------- */ /* restart the clocks */ /* ... */ /* CNTR_LPMODE = 0 */ wCNTR = _GetCNTR(); wCNTR &= (~CNTR_LPMODE); _SetCNTR(wCNTR); /* restore full power */ /* ... on connected devices */ Leave_LowPowerMode(); /* reset FSUSP bit */ _SetCNTR(IMR_MSK); /* reverse suspend preparation */ /* ... */ }
/******************************************************************************* * Function Name : Resume_Init * Description : Handles wake-up restoring normal operations * Input : None. * Output : None. * Return : USB_SUCCESS. *******************************************************************************/ void Resume_Init(void) { #ifndef STM32F10X_CL uint16_t wCNTR; #endif /* STM32F10X_CL */ /* ------------------ ONLY WITH BUS-POWERED DEVICES ---------------------- */ /* restart the clocks */ /* ... */ #ifndef STM32F10X_CL /* CNTR_LPMODE = 0 */ wCNTR = _GetCNTR(); wCNTR &= (~CNTR_LPMODE); _SetCNTR(wCNTR); #endif /* STM32F10X_CL */ #ifdef STM32F10X_CL /* Ungate the PHY and AHB USB clocks */ _OTGD_FS_UNGATE_PHYCLK; #endif /* STM32F10X_CL */ /* restore full power */ /* ... on connected devices */ Leave_LowPowerMode(); #ifndef STM32F10X_CL /* reset FSUSP bit */ _SetCNTR(IMR_MSK); #endif /* STM32F10X_CL */ /* reverse suspend preparation */ /* ... */ }
/******************************************************************************* * Function Name : Resume_Init * Description : Handles wake-up restoring normal operations * Input : None. * Output : None. * Return : USB_SUCCESS. *******************************************************************************/ void Resume_Init(void) { /* ------------------ ONLY WITH BUS-POWERED DEVICES ---------------------- */ /* restart the clocks */ /* ... */ #ifndef STM32F10X_CL uint16_t wCNTR; /* CNTR_LPMODE = 0 */ wCNTR = _GetCNTR(); wCNTR &= (~CNTR_LPMODE); _SetCNTR(wCNTR); #endif /* STM32F10X_CL */ /* restore full power */ /* ... on connected devices */ // dbg("Resume_Init CONFIGURED\n"); Leave_LowPowerMode(); #ifndef STM32F10X_CL /* reset FSUSP bit */ _SetCNTR(IMR_MSK); #endif /* STM32F10X_CL */ /* reverse suspend preparation */ /* ... */ }
void usbSuspend(void) { u16 wCNTR; wCNTR = _GetCNTR(); wCNTR |= CNTR_FSUSP | CNTR_LPMODE; _SetCNTR(wCNTR); /* run any power reduction handlers */ bDeviceState = SUSPENDED; }
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); } }
void usb_port_set(u8 enable) { uint16_t value; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); if(enable) { value = _GetCNTR()&(~(1<<1)); _SetCNTR(value); } else { value = _GetCNTR()|((1<<1)); _SetCNTR(value); GPIOA->CRH&=0XFFF00FFF; GPIOA->CRH|=0X00033000; PAout(12)=0; } }
void usbResumeInit(void) { u16 wCNTR; /* restart any clocks that had been stopped */ wCNTR = _GetCNTR(); wCNTR &= (~CNTR_LPMODE); _SetCNTR(wCNTR); /* undo power reduction handlers here */ _SetCNTR(ISR_MSK); }
/******************************************************************************* * Function Name : Resume_Init * Description : Handles wake-up restoring normal operations * Input : None * Return : None *******************************************************************************/ void Resume_Init(void) { u16 wCNTR; fCellSuspended= FALSE; /* CNTR_LPMODE = 0 */ wCNTR = _GetCNTR(); wCNTR &= (~CNTR_LPMODE); _SetCNTR(wCNTR); /* restore full power */ /* ... on connected devices */ Leave_LowPowerMode(); /* reset FSUSP bit */ _SetCNTR(IMR_MSK); /* reverse suspend preparation */ /* ... */ }/* Resume_Init() */
/******************************************************************************* * Function Name : Suspend * Description : sets suspend mode operating conditions * Input : None. * Output : None. * Return : USB_SUCCESS. *******************************************************************************/ void Suspend(void) { uint32_t i =0; uint16_t wCNTR; uint32_t tmpreg = 0; __IO uint32_t savePWR_CR=0; /* suspend preparation */ /* ... */ /*Store CNTR value */ wCNTR = _GetCNTR(); /* This a sequence to apply a force RESET to handle a robustness case */ /*Store endpoints registers status */ for (i=0;i<8;i++) EP[i] = _GetENDPOINT(i); /* unmask RESET flag */ wCNTR|=CNTR_RESETM; _SetCNTR(wCNTR); /*apply FRES */ wCNTR|=CNTR_FRES; _SetCNTR(wCNTR); /*clear FRES*/ wCNTR&=~CNTR_FRES; _SetCNTR(wCNTR); /*poll for RESET flag in ISTR*/ while((_GetISTR()&ISTR_RESET) == 0); /* clear RESET flag in ISTR */ _SetISTR((uint16_t)CLR_RESET); /*restore Enpoints*/ for (i=0;i<8;i++) _SetENDPOINT(i, EP[i]); /* Now it is safe to enter macrocell in suspend mode */ wCNTR |= CNTR_FSUSP; _SetCNTR(wCNTR); /* force low-power mode in the macrocell */ wCNTR = _GetCNTR(); wCNTR |= CNTR_LPMODE; _SetCNTR(wCNTR); /*prepare entry in low power mode (STOP mode)*/ /* Select the regulator state in STOP mode*/ savePWR_CR = PWR->CR; tmpreg = PWR->CR; /* Clear PDDS and LPDS bits */ tmpreg &= ((uint32_t)0xFFFFFFFC); /* Set LPDS bit according to PWR_Regulator value */ tmpreg |= PWR_Regulator_LowPower; /* Store the new value */ PWR->CR = tmpreg; /* Set SLEEPDEEP bit of Cortex System Control Register */ #if defined (STM32F30X) || defined (STM32F37X) SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; #else SCB->SCR |= SCB_SCR_SLEEPDEEP; #endif /* enter system in STOP mode, only when wakeup flag in not set */ if((_GetISTR()&ISTR_WKUP)==0) { __WFI(); /* Reset SLEEPDEEP bit of Cortex System Control Register */ #if defined (STM32F30X) || defined (STM32F37X) SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP_Msk); #else SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP); #endif } else { /* Clear Wakeup flag */ _SetISTR(CLR_WKUP); /* clear FSUSP to abort entry in suspend mode */ wCNTR = _GetCNTR(); wCNTR&=~CNTR_FSUSP; _SetCNTR(wCNTR); /*restore sleep mode configuration */ /* restore Power regulator config in sleep mode*/ PWR->CR = savePWR_CR; /* Reset SLEEPDEEP bit of Cortex System Control Register */ #if defined (STM32F30X) || defined (STM32F37X) SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP_Msk); #else SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP); #endif } }
/******************************************************************************* * Function Name : Resume * Description : This is the state machine handling resume operations and * timing sequence. The control is based on the Resume structure * variables and on the ESOF interrupt calling this subroutine * without changing machine state. * Input : a state machine value (RESUME_STATE) * RESUME_ESOF doesn't change ResumeS.eState allowing * decrementing of the ESOF counter in different states. * Output : None. * Return : None. *******************************************************************************/ void Resume(RESUME_STATE eResumeSetVal) { #ifndef STM32F10X_CL uint16_t wCNTR; #endif /* STM32F10X_CL */ if (eResumeSetVal != RESUME_ESOF) ResumeS.eState = eResumeSetVal; switch (ResumeS.eState) { case RESUME_EXTERNAL: Resume_Init(); ResumeS.eState = RESUME_OFF; break; case RESUME_INTERNAL: Resume_Init(); ResumeS.eState = RESUME_START; break; case RESUME_LATER: ResumeS.bESOFcnt = 2; ResumeS.eState = RESUME_WAIT; break; case RESUME_WAIT: ResumeS.bESOFcnt--; if (ResumeS.bESOFcnt == 0) ResumeS.eState = RESUME_START; break; case RESUME_START: #ifdef STM32F10X_CL OTGD_FS_SetRemoteWakeup(); #else wCNTR = _GetCNTR(); wCNTR |= CNTR_RESUME; _SetCNTR(wCNTR); #endif /* STM32F10X_CL */ ResumeS.eState = RESUME_ON; ResumeS.bESOFcnt = 10; break; case RESUME_ON: #ifndef STM32F10X_CL ResumeS.bESOFcnt--; if (ResumeS.bESOFcnt == 0) { #endif /* STM32F10X_CL */ #ifdef STM32F10X_CL OTGD_FS_ResetRemoteWakeup(); #else wCNTR = _GetCNTR(); wCNTR &= (~CNTR_RESUME); _SetCNTR(wCNTR); #endif /* STM32F10X_CL */ ResumeS.eState = RESUME_OFF; #ifndef STM32F10X_CL } #endif /* STM32F10X_CL */ break; case RESUME_OFF: case RESUME_ESOF: default: ResumeS.eState = RESUME_OFF; break; } }
/******************************************************************************* * Function Name : USB_Istr * Description : ISTR events interrupt service routine * Input : None. * Output : None. * Return : None. *******************************************************************************/ void USB_Istr(void) { uint32_t i=0; __IO uint32_t EP[8]; wIstr = _GetISTR(); #if (IMR_MSK & ISTR_SOF) if (wIstr & ISTR_SOF & wInterrupt_Mask) { _SetISTR((uint16_t)CLR_SOF); bIntPackSOF++; #ifdef SOF_CALLBACK SOF_Callback(); #endif } #endif /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ #if (IMR_MSK & ISTR_CTR) if (wIstr & ISTR_CTR & wInterrupt_Mask) { /* servicing of the endpoint correct transfer interrupt */ /* clear of the CTR flag into the sub */ CTR_LP(); #ifdef CTR_CALLBACK CTR_Callback(); #endif } #endif /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ #if (IMR_MSK & ISTR_RESET) if (wIstr & ISTR_RESET & wInterrupt_Mask) { _SetISTR((uint16_t)CLR_RESET); Device_Property.Reset(); #ifdef RESET_CALLBACK RESET_Callback(); #endif } #endif /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ #if (IMR_MSK & ISTR_DOVR) if (wIstr & ISTR_DOVR & wInterrupt_Mask) { _SetISTR((uint16_t)CLR_DOVR); #ifdef DOVR_CALLBACK DOVR_Callback(); #endif } #endif /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ #if (IMR_MSK & ISTR_ERR) if (wIstr & ISTR_ERR & wInterrupt_Mask) { _SetISTR((uint16_t)CLR_ERR); #ifdef ERR_CALLBACK ERR_Callback(); #endif } #endif /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ #if (IMR_MSK & ISTR_WKUP) if (wIstr & ISTR_WKUP & wInterrupt_Mask) { _SetISTR((uint16_t)CLR_WKUP); Resume(RESUME_EXTERNAL); #ifdef WKUP_CALLBACK WKUP_Callback(); #endif } #endif /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ #if (IMR_MSK & ISTR_SUSP) if (wIstr & ISTR_SUSP & wInterrupt_Mask) { /* check if SUSPEND is possible */ if (fSuspendEnabled) { Suspend(); } else { /* if not possible then resume after xx ms */ Resume(RESUME_LATER); } /* clear of the ISTR bit must be done after setting of CNTR_FSUSP */ _SetISTR((uint16_t)CLR_SUSP); #ifdef SUSP_CALLBACK SUSP_Callback(); #endif } #endif /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ #if (IMR_MSK & ISTR_ESOF) if (wIstr & ISTR_ESOF & wInterrupt_Mask) { /* clear ESOF flag in ISTR */ _SetISTR((uint16_t)CLR_ESOF); if ((_GetFNR()&FNR_RXDP)!=0) { /* increment ESOF counter */ esof_counter ++; /* test if we enter in ESOF more than 3 times with FSUSP =0 and RXDP =1=>> possible missing SUSP flag*/ if ((esof_counter >3)&&((_GetCNTR()&CNTR_FSUSP)==0)) { /* this a sequence to apply a force RESET*/ /*Store CNTR value */ wCNTR = _GetCNTR(); /*Store endpoints registers status */ for (i=0;i<8;i++) EP[i] = _GetENDPOINT(i); /*apply FRES */ wCNTR|=CNTR_FRES; _SetCNTR(wCNTR); /*clear FRES*/ wCNTR&=~CNTR_FRES; _SetCNTR(wCNTR); /*disable ESOF interrupt*/ //wCNTR &= ~CNTR_ESOFM; //_SetCNTR(wCNTR); /*poll for RESET flag in ISTR*/ while((_GetISTR()&ISTR_RESET) == 0); /* clear RESET flag in ISTR */ _SetISTR((uint16_t)CLR_RESET); /*restore Enpoints*/ for (i=0;i<8;i++) _SetENDPOINT(i, EP[i]); esof_counter = 0; } } else { esof_counter = 0; } /* resume handling timing is made with ESOFs */ Resume(RESUME_ESOF); /* request without change of the machine state */ #ifdef ESOF_CALLBACK ESOF_Callback(); #endif } #endif /*disable ESOF interrupt*/ wCNTR = _GetCNTR(); wCNTR &= ~CNTR_ESOFM; _SetCNTR(wCNTR); } /* USB_Istr */