mirror of
https://github.com/hathach/tinyusb.git
synced 2025-03-28 16:20:26 +00:00
stm32: fix ISTR and CTR_RX/TX race conditions
This commit is contained in:
parent
8b2c822557
commit
020ad47bb0
@ -203,6 +203,11 @@ static inline void reg16_clear_bits(__IO uint16_t *reg, uint16_t mask) {
|
|||||||
*reg = (uint16_t)(*reg & ~mask);
|
*reg = (uint16_t)(*reg & ~mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Bits in ISTR are cleared upon writing 0
|
||||||
|
static inline void clear_istr_bits(uint16_t mask) {
|
||||||
|
USB->ISTR = ~mask;
|
||||||
|
}
|
||||||
|
|
||||||
void dcd_init (uint8_t rhport)
|
void dcd_init (uint8_t rhport)
|
||||||
{
|
{
|
||||||
/* Clocks should already be enabled */
|
/* Clocks should already be enabled */
|
||||||
@ -231,7 +236,7 @@ void dcd_init (uint8_t rhport)
|
|||||||
|
|
||||||
USB->BTABLE = DCD_STM32_BTABLE_BASE;
|
USB->BTABLE = DCD_STM32_BTABLE_BASE;
|
||||||
|
|
||||||
reg16_clear_bits(&USB->ISTR, USB_ISTR_ALL_EVENTS); // Clear pending interrupts
|
USB->ISTR = 0; // Clear pending interrupts
|
||||||
|
|
||||||
// Reset endpoints to disabled
|
// Reset endpoints to disabled
|
||||||
for(uint32_t i=0; i<STFSDEV_EP_COUNT; i++)
|
for(uint32_t i=0; i<STFSDEV_EP_COUNT; i++)
|
||||||
@ -512,7 +517,7 @@ void dcd_int_handler(uint8_t rhport) {
|
|||||||
|
|
||||||
if(int_status & USB_ISTR_RESET) {
|
if(int_status & USB_ISTR_RESET) {
|
||||||
// USBRST is start of reset.
|
// USBRST is start of reset.
|
||||||
reg16_clear_bits(&USB->ISTR, USB_ISTR_RESET);
|
clear_istr_bits(USB_ISTR_RESET);
|
||||||
dcd_handle_bus_reset();
|
dcd_handle_bus_reset();
|
||||||
dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true);
|
dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true);
|
||||||
return; // Don't do the rest of the things here; perhaps they've been cleared?
|
return; // Don't do the rest of the things here; perhaps they've been cleared?
|
||||||
@ -523,14 +528,13 @@ void dcd_int_handler(uint8_t rhport) {
|
|||||||
/* servicing of the endpoint correct transfer interrupt */
|
/* servicing of the endpoint correct transfer interrupt */
|
||||||
/* clear of the CTR flag into the sub */
|
/* clear of the CTR flag into the sub */
|
||||||
dcd_ep_ctr_handler();
|
dcd_ep_ctr_handler();
|
||||||
reg16_clear_bits(&USB->ISTR, USB_ISTR_CTR);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (int_status & USB_ISTR_WKUP)
|
if (int_status & USB_ISTR_WKUP)
|
||||||
{
|
{
|
||||||
reg16_clear_bits(&USB->CNTR, USB_CNTR_LPMODE);
|
reg16_clear_bits(&USB->CNTR, USB_CNTR_LPMODE);
|
||||||
reg16_clear_bits(&USB->CNTR, USB_CNTR_FSUSP);
|
reg16_clear_bits(&USB->CNTR, USB_CNTR_FSUSP);
|
||||||
reg16_clear_bits(&USB->ISTR, USB_ISTR_WKUP);
|
clear_istr_bits(USB_ISTR_WKUP);
|
||||||
dcd_event_bus_signal(0, DCD_EVENT_RESUME, true);
|
dcd_event_bus_signal(0, DCD_EVENT_RESUME, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -544,13 +548,13 @@ void dcd_int_handler(uint8_t rhport) {
|
|||||||
USB->CNTR |= USB_CNTR_LPMODE;
|
USB->CNTR |= USB_CNTR_LPMODE;
|
||||||
|
|
||||||
/* clear of the ISTR bit must be done after setting of CNTR_FSUSP */
|
/* clear of the ISTR bit must be done after setting of CNTR_FSUSP */
|
||||||
reg16_clear_bits(&USB->ISTR, USB_ISTR_SUSP);
|
clear_istr_bits(USB_ISTR_SUSP);
|
||||||
dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true);
|
dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if USE_SOF
|
#if USE_SOF
|
||||||
if(int_status & USB_ISTR_SOF) {
|
if(int_status & USB_ISTR_SOF) {
|
||||||
reg16_clear_bits(&USB->ISTR, USB_ISTR_SOF);
|
clear_istr_bits(USB_ISTR_SOF);
|
||||||
dcd_event_bus_signal(0, DCD_EVENT_SOF, true);
|
dcd_event_bus_signal(0, DCD_EVENT_SOF, true);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -564,7 +568,7 @@ void dcd_int_handler(uint8_t rhport) {
|
|||||||
{
|
{
|
||||||
remoteWakeCountdown--;
|
remoteWakeCountdown--;
|
||||||
}
|
}
|
||||||
reg16_clear_bits(&USB->ISTR, USB_ISTR_ESOF);
|
clear_istr_bits(USB_ISTR_ESOF);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,13 +143,17 @@ static inline uint32_t pcd_get_eptype(USB_TypeDef * USBx, uint32_t bEpNum)
|
|||||||
static inline void pcd_clear_rx_ep_ctr(USB_TypeDef * USBx, uint32_t bEpNum)
|
static inline void pcd_clear_rx_ep_ctr(USB_TypeDef * USBx, uint32_t bEpNum)
|
||||||
{
|
{
|
||||||
uint32_t regVal = pcd_get_endpoint(USBx, bEpNum);
|
uint32_t regVal = pcd_get_endpoint(USBx, bEpNum);
|
||||||
regVal &= 0x7FFFu & USB_EPREG_MASK;
|
regVal &= USB_EPREG_MASK;
|
||||||
|
regVal &= ~USB_EP_CTR_RX;
|
||||||
|
regVal |= USB_EP_CTR_TX; // preserve CTR_TX (clears on writing 0)
|
||||||
pcd_set_endpoint(USBx, bEpNum, regVal);
|
pcd_set_endpoint(USBx, bEpNum, regVal);
|
||||||
}
|
}
|
||||||
static inline void pcd_clear_tx_ep_ctr(USB_TypeDef * USBx, uint32_t bEpNum)
|
static inline void pcd_clear_tx_ep_ctr(USB_TypeDef * USBx, uint32_t bEpNum)
|
||||||
{
|
{
|
||||||
uint32_t regVal = pcd_get_endpoint(USBx, bEpNum);
|
uint32_t regVal = pcd_get_endpoint(USBx, bEpNum);
|
||||||
regVal &= regVal & 0xFF7FU & USB_EPREG_MASK;
|
regVal &= USB_EPREG_MASK;
|
||||||
|
regVal &= ~USB_EP_CTR_TX;
|
||||||
|
regVal |= USB_EP_CTR_RX; // preserve CTR_RX (clears on writing 0)
|
||||||
pcd_set_endpoint(USBx, bEpNum,regVal);
|
pcd_set_endpoint(USBx, bEpNum,regVal);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user