/**
******************************************************************************
* @file usb_istr.c
* @author MCD Application Team
* @version V4.0.0
* @date 21-January-2013
* @brief ISTR events interrupt service routines
******************************************************************************
* @attention
*
*
© COPYRIGHT 2013 STMicroelectronics
*
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/software_license_agreement_liberty_v2
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
#include "usb_lib.h"
#include "usb_prop.h"
#include "usb_pwr.h"
#include "usb_istr.h"
// Private variables
__IO uint16_t wIstr; // ISTR register last read value
__IO uint8_t bIntPackSOF = 0; // SOFs received between 2 consecutive packets
__IO uint32_t esof_counter = 0; // expected SOF counter
// function pointers to non-control endpoints service routines
void (*pEpInt_IN[7])(void) = {
EP1_IN_Callback,
EP2_IN_Callback,
EP3_IN_Callback,
EP4_IN_Callback,
EP5_IN_Callback,
EP6_IN_Callback,
EP7_IN_Callback
};
void (*pEpInt_OUT[7])(void) = {
EP1_OUT_Callback,
EP2_OUT_Callback,
EP3_OUT_Callback,
EP4_OUT_Callback,
EP5_OUT_Callback,
EP6_OUT_Callback,
EP7_OUT_Callback
};
/*******************************************************************************
* 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 = *ISTR;
#if (IMR_MSK & ISTR_SOF)
if (wIstr & ISTR_SOF & wInterrupt_Mask) {
*ISTR = CLR_SOF;
bIntPackSOF++;
#ifdef SOF_CALLBACK
SOF_Callback();
#endif
}
#endif // IMR_MSK & ISTR_SOF
// -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
#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 // IMR_MSK & ISTR_CTR
// -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
#if (IMR_MSK & ISTR_RESET)
if (wIstr & ISTR_RESET & wInterrupt_Mask) {
*ISTR = CLR_RESET;
Device_Property.Reset();
#ifdef RESET_CALLBACK
RESET_Callback();
#endif
}
#endif // IMR_MSK & ISTR_RESET
// -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
#if (IMR_MSK & ISTR_DOVR)
if (wIstr & ISTR_DOVR & wInterrupt_Mask) {
*ISTR = CLR_DOVR;
#ifdef DOVR_CALLBACK
DOVR_Callback();
#endif
}
#endif // IMR_MSK & ISTR_DOVR
// -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
#if (IMR_MSK & ISTR_ERR)
if (wIstr & ISTR_ERR & wInterrupt_Mask) {
*ISTR = CLR_ERR;
#ifdef ERR_CALLBACK
ERR_Callback();
#endif
}
#endif // IMR_MSK & ISTR_ERR
// -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
#if (IMR_MSK & ISTR_WKUP)
if (wIstr & ISTR_WKUP & wInterrupt_Mask) {
*ISTR = CLR_WKUP;
Resume(RESUME_EXTERNAL);
#ifdef WKUP_CALLBACK
WKUP_Callback();
#endif
}
#endif // IMR_MSK & ISTR_WKUP
// -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
#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
*ISTR = CLR_SUSP;
#ifdef SUSP_CALLBACK
SUSP_Callback();
#endif
}
#endif // IMR_MSK & ISTR_SUSP
// -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
#if (IMR_MSK & ISTR_ESOF)
if (wIstr & ISTR_ESOF & wInterrupt_Mask) {
// clear ESOF flag in ISTR
*ISTR = CLR_ESOF;
if (*FNR & FNR_RXDP) {
// 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) && ((*CNTR & CNTR_FSUSP) == 0)) {
// this a sequence to apply a force RESET
// Store endpoints registers status
for (i = 0; i < 8; i++) EP[i] = _GetENDPOINT(i);
// apply FRES
*CNTR |= CNTR_FRES;
// clear FRES
*CNTR &= ~CNTR_FRES;
// poll for RESET flag in ISTR
while (!(*ISTR & ISTR_RESET));
// clear RESET flag in ISTR
*ISTR = CLR_RESET;
// restore endpoints
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 // IMR_MSK & ISTR_ESOF
} // USB_Istr