Skip to content

Commit 7f5ba1e

Browse files
committed
reorganize ctr_rx workaround
Signed-off-by: Zixun LI <[email protected]>
1 parent 37df71c commit 7f5ba1e

File tree

1 file changed

+48
-31
lines changed

1 file changed

+48
-31
lines changed

src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c

Lines changed: 48 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,51 @@ static inline void channel_write_status(uint8_t ch_id, uint32_t ch_reg, tusb_dir
139139
ch_write(ch_id, ch_reg, need_exclusive);
140140
}
141141

142+
static inline uint16_t channel_get_rx_count(uint8_t ch_id) {
143+
/* https://www.st.com/resource/en/errata_sheet/es0561-stm32h503cbebkbrb-device-errata-stmicroelectronics.pdf
144+
* https://www.st.com/resource/en/errata_sheet/es0587-stm32u535xx-and-stm32u545xx-device-errata-stmicroelectronics.pdf
145+
* From H503/U535 errata: Buffer description table update completes after CTR interrupt triggers
146+
* Description:
147+
* - During OUT transfers, the correct transfer interrupt (CTR) is triggered a little before the last USB SRAM accesses
148+
* have completed. If the software responds quickly to the interrupt, the full buffer contents may not be correct.
149+
* Workaround:
150+
* - Software should ensure that a small delay is included before accessing the SRAM contents. This delay
151+
* should be 800 ns in Full Speed mode and 6.4 μs in Low Speed mode
152+
*
153+
* We choose the delay count based on max CPU frequency (in MHz) to ensure the delay is at least the required time.
154+
*/
155+
156+
#if CFG_TUSB_MCU == OPT_MCU_STM32H5
157+
#define FREQUENCY_MHZ 250U
158+
#elif CFG_TUSB_MCU == OPT_MCU_STM32U5
159+
#define FREQUENCY_MHZ 160U
160+
#elif CFG_TUSB_MCU == OPT_MCU_STM32U3
161+
#define FREQUENCY_MHZ 96U
162+
#elif CFG_TUSB_MCU == OPT_MCU_STM32G0
163+
#define FREQUENCY_MHZ 64U
164+
#elif CFG_TUSB_MCU == OPT_MCU_STM32C0
165+
#define FREQUENCY_MHZ 48U
166+
#else
167+
#error "FREQUENCY_MHZ not defined for this STM32 MCU"
168+
#endif
169+
170+
uint32_t ch_reg = ch_read(ch_id);
171+
if (FSDEV_REG->ISTR & USB_ISTR_LS_DCONN || ch_reg & USB_CHEP_LSEP) {
172+
// Low speed mode: 6.4 us delay -> about 2 cycles per MHz
173+
volatile uint32_t cycle_count = FREQUENCY_MHZ * 2U;
174+
while (cycle_count > 0U) {
175+
cycle_count--; // each count take 3 cycles (1 for sub, jump, and compare)
176+
}
177+
} else {
178+
// Full speed mode: 800 ns delay -> about 0.25 cycles per MHz
179+
volatile uint32_t cycle_count = FREQUENCY_MHZ / 4U;
180+
while (cycle_count > 0U) {
181+
cycle_count--; // each count take 3 cycles (1 for sub, jump, and compare)
182+
}
183+
}
184+
185+
return btable_get_count(ch_id, BTABLE_BUF_RX);
186+
}
142187

143188
//--------------------------------------------------------------------+
144189
// Controller API
@@ -175,12 +220,6 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
175220
}
176221

177222
FSDEV_REG->CNTR = USB_CNTR_HOST; // Enable USB in Host mode
178-
179-
#if !defined(FSDEV_BUS_32BIT)
180-
// BTABLE register does not exist on 32-bit bus devices
181-
FSDEV_REG->BTABLE = FSDEV_BTABLE_BASE;
182-
#endif
183-
184223
FSDEV_REG->ISTR = 0; // Clear pending interrupts
185224

186225
// Reset channels to disabled
@@ -260,7 +299,7 @@ static void ch_handle_ack(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) {
260299
}
261300
} else {
262301
// IN/RX direction
263-
uint16_t const rx_count = btable_get_count(ch_id, BTABLE_BUF_RX);
302+
uint16_t const rx_count = channel_get_rx_count(ch_id);
264303
uint16_t pma_addr = (uint16_t) btable_get_addr(ch_id, BTABLE_BUF_RX);
265304

266305
fsdev_read_packet_memory(edpt->buffer + channel->queued_len[TUSB_DIR_IN], pma_addr, rx_count);
@@ -338,7 +377,7 @@ static void ch_handle_error(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) {
338377
}
339378

340379
// Handle CTR interrupt for the TX/OUT direction
341-
static void handle_ctr_tx(uint32_t ch_id) {
380+
static inline void handle_ctr_tx(uint32_t ch_id) {
342381
uint32_t ch_reg = ch_read(ch_id) | USB_EP_CTR_TX | USB_EP_CTR_RX;
343382
hcd_channel_t* channel = &_hcd_data.channel[ch_id];
344383
TU_VERIFY(channel->allocated[TUSB_DIR_OUT] == 1,);
@@ -358,7 +397,7 @@ static void handle_ctr_tx(uint32_t ch_id) {
358397
}
359398

360399
// Handle CTR interrupt for the RX/IN direction
361-
static void handle_ctr_rx(uint32_t ch_id) {
400+
static inline void handle_ctr_rx(uint32_t ch_id) {
362401
uint32_t ch_reg = ch_read(ch_id) | USB_EP_CTR_TX | USB_EP_CTR_RX;
363402
hcd_channel_t* channel = &_hcd_data.channel[ch_id];
364403
TU_VERIFY(channel->allocated[TUSB_DIR_IN] == 1,);
@@ -393,28 +432,6 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) {
393432
uint32_t const ch_reg = ch_read(ch_id);
394433

395434
if (ch_reg & USB_EP_CTR_RX) {
396-
#ifdef FSDEV_BUS_32BIT
397-
/* https://www.st.com/resource/en/errata_sheet/es0561-stm32h503cbebkbrb-device-errata-stmicroelectronics.pdf
398-
* https://www.st.com/resource/en/errata_sheet/es0587-stm32u535xx-and-stm32u545xx-device-errata-stmicroelectronics.pdf
399-
* From H503/U535 errata: Buffer description table update completes after CTR interrupt triggers
400-
* Description:
401-
* - During OUT transfers, the correct transfer interrupt (CTR) is triggered a little before the last USB SRAM accesses
402-
* have completed. If the software responds quickly to the interrupt, the full buffer contents may not be correct.
403-
* Workaround:
404-
* - Software should ensure that a small delay is included before accessing the SRAM contents. This delay
405-
* should be 800 ns in Full Speed mode and 6.4 μs in Low Speed mode
406-
* - Since H5 can run up to 250Mhz -> 1 cycle = 4ns. Per errata, we need to wait 200 cycles. Though executing code
407-
* also takes time, so we'll wait 60 cycles (count = 20).
408-
* - Since Low Speed mode is not supported/popular, we will ignore it for now.
409-
*
410-
* Note: this errata may also apply to G0, U5, H5 etc.
411-
*/
412-
volatile uint32_t cycle_count = 20; // defined as PCD_RX_PMA_CNT in stm32 hal_driver
413-
while (cycle_count > 0U) {
414-
cycle_count--; // each count take 3 cycles (1 for sub, jump, and compare)
415-
}
416-
#endif
417-
418435
ch_write_clear_ctr(ch_id, TUSB_DIR_IN);
419436
handle_ctr_rx(ch_id);
420437
}

0 commit comments

Comments
 (0)