move walkaround to dcd_ep_ctr_rx_handler(), increase cycle_count from 10 to 20 (40 cycle)

This commit is contained in:
hathach 2024-03-31 21:53:12 +07:00
parent 27afa56844
commit fc54ad43b1
No known key found for this signature in database
GPG Key ID: 26FAB84F615C3C52
3 changed files with 34 additions and 31 deletions

View File

@ -1,6 +1,6 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="stlink" type="com.jetbrains.cidr.embedded.customgdbserver.type" factoryName="com.jetbrains.cidr.embedded.customgdbserver.factory" folderName="stm32" PROGRAM_PARAMS="-p 28833 -cp &quot;/opt/st/stm32cubeide_1.12.1/plugins/com.st.stm32cube.ide.mcu.externaltools.cubeprogrammer.linux64_2.1.100.202311100844/tools/bin&quot; --frequency 8000 --swd" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="tinyusb_examples" TARGET_NAME="cdc_msc" CONFIG_NAME="stm32h563nucleo" version="1" RUN_TARGET_PROJECT_NAME="tinyusb_examples" RUN_TARGET_NAME="cdc_msc">
<custom-gdb-server version="1" gdb-connect="tcp::28833" executable="/opt/st/stm32cubeide_1.12.1/plugins/com.st.stm32cube.ide.mcu.externaltools.stlink-gdb-server.linux64_2.1.100.202310302101/tools/bin/ST-LINK_gdbserver" warmup-ms="0" download-type="ALWAYS" reset-cmd="monitor reset" reset-type="AFTER_DOWNLOAD">
<configuration default="false" name="stlink" type="com.jetbrains.cidr.embedded.customgdbserver.type" factoryName="com.jetbrains.cidr.embedded.customgdbserver.factory" folderName="stm32" PROGRAM_PARAMS="-p 10458 -cp &quot;/opt/st/stm32cubeide_1.14.0/plugins/com.st.stm32cube.ide.mcu.externaltools.cubeprogrammer.linux64_2.1.100.202311100844/tools/bin&quot; --frequency 8000 --swd" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="tinyusb_device_examples" TARGET_NAME="cdc_msc" CONFIG_NAME="stm32h563nucleo" version="1" RUN_TARGET_PROJECT_NAME="tinyusb_device_examples" RUN_TARGET_NAME="cdc_msc">
<custom-gdb-server version="1" gdb-connect="tcp::10458" executable="/opt/st/stm32cubeide_1.14.0/plugins/com.st.stm32cube.ide.mcu.externaltools.stlink-gdb-server.linux64_2.1.100.202310302101/tools/bin/ST-LINK_gdbserver" warmup-ms="0" download-type="ALWAYS" reset-cmd="monitor reset" reset-type="AFTER_DOWNLOAD">
<debugger kind="GDB" isBundled="true" />
</custom-gdb-server>
<method v="2">

View File

@ -200,8 +200,7 @@ static bool dcd_read_packet_memory_ff(tu_fifo_t * ff, uint16_t src, uint16_t wNB
// Inline helper
//--------------------------------------------------------------------+
TU_ATTR_ALWAYS_INLINE static inline xfer_ctl_t* xfer_ctl_ptr(uint32_t ep_addr)
{
TU_ATTR_ALWAYS_INLINE static inline xfer_ctl_t* xfer_ctl_ptr(uint32_t ep_addr) {
uint8_t epnum = tu_edpt_number(ep_addr);
uint8_t dir = tu_edpt_dir(ep_addr);
// Fix -Werror=null-dereference
@ -524,7 +523,7 @@ static void dcd_ep_ctr_tx_handler(uint32_t wIstr)
xfer_ctl_t * xfer = xfer_ctl_ptr(ep_addr);
if((xfer->total_len != xfer->queued_len)) /* TX not complete */
{
dcd_transmit_packet(xfer, EPindex);
dcd_transmit_packet(xfer, EPindex);
}
else /* TX Complete */
{
@ -533,10 +532,29 @@ static void dcd_ep_ctr_tx_handler(uint32_t wIstr)
}
// Handle CTR interrupt for the RX/OUT direction
//
// Upon call, (wIstr & USB_ISTR_DIR) == 0U
static void dcd_ep_ctr_rx_handler(uint32_t wIstr)
{
static void dcd_ep_ctr_rx_handler(uint32_t wIstr) {
#ifdef FSDEV_BUS_32BIT
/* https://www.st.com/resource/en/errata_sheet/es0561-stm32h503cbebkbrb-device-errata-stmicroelectronics.pdf
* From STM32H503 errata 2.15.1: Buffer description table update completes after CTR interrupt triggers
* Description:
* - During OUT transfers, the correct transfer interrupt (CTR) is triggered a little before the last USB SRAM accesses
* have completed. If the software responds quickly to the interrupt, the full buffer contents may not be correct.
* Workaround:
* - Software should ensure that a small delay is included before accessing the SRAM contents. This delay
* should be 800 ns in Full Speed mode and 6.4 μs in Low Speed mode
* - Since H5 can run up to 250Mhz -> 1 cycle = 4ns. Per errata, we need to wait 200 cycles. Though executing code
* also takes time, so we'll wait 40 cycles (count = 20).
* - Since Low Speed mode is not supported/popular, we will ignore it for now.
*
* Note: this errata also seems to apply to G0, U5, H5 etc.
*/
volatile uint32_t cycle_count = 20; // defined as PCD_RX_PMA_CNT in stm32 hal_driver
while (cycle_count > 0U) {
cycle_count--; // each count take 2 cycle (1 cycle for sub, 1 cycle for compare/jump)
}
#endif
uint32_t EPindex = wIstr & USB_ISTR_EP_ID;
uint32_t wEPRegVal = pcd_get_endpoint(USB, EPindex);
uint8_t ep_addr = wEPRegVal & USB_EPADDR_FIELD;
@ -545,8 +563,7 @@ static void dcd_ep_ctr_rx_handler(uint32_t wIstr)
// Verify the CTR_RX bit is set. This was in the ST Micro code,
// but I'm not sure it's actually necessary?
if((wEPRegVal & USB_EP_CTR_RX) == 0U)
{
if((wEPRegVal & USB_EP_CTR_RX) == 0U) {
return;
}
@ -633,26 +650,22 @@ static void dcd_ep_ctr_rx_handler(uint32_t wIstr)
// (Based on the docs, it seems SETUP will always be accepted after CTR is cleared)
if(ep_addr == 0u)
{
// Always be prepared for a status packet...
// Always be prepared for a status packet...
pcd_set_ep_rx_bufsize(USB, EPindex, CFG_TUD_ENDPOINT0_SIZE);
pcd_clear_rx_ep_ctr(USB, EPindex);
}
}
static void dcd_ep_ctr_handler(void)
{
static void dcd_ep_ctr_handler(void) {
uint32_t wIstr;
/* stay in loop while pending interrupts */
while (((wIstr = USB->ISTR) & USB_ISTR_CTR) != 0U)
{
if ((wIstr & USB_ISTR_DIR) == 0U) /* TX/IN */
{
while (((wIstr = USB->ISTR) & USB_ISTR_CTR) != 0U) {
if ((wIstr & USB_ISTR_DIR) == 0U) {
/* TX/IN */
dcd_ep_ctr_tx_handler(wIstr);
}
else /* RX/OUT*/
{
} else {
/* RX/OUT*/
dcd_ep_ctr_rx_handler(wIstr);
}
}

View File

@ -286,16 +286,6 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_tx_cnt(USB_TypeDef * USB
TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx) {
#ifdef FSDEV_BUS_32BIT
(void) USBx;
/* WA: few cycles for RX PMA descriptor to update, otherwise doesn't return the correct value.
Note: required for G0, U5, H5 etc.
This workaround is ported from stm32h5xx_hal_pcd.h and fixes the issue when calling this function fast enough.
Reproduced with GCC ast optimization(O2/O3) and stm32h573i_dk with an high frequency.
Observed on Windows 10 where tud_task() is scheduled by interrupt handler.
*/
volatile uint32_t count = 10; // defined as PCD_RX_PMA_CNT in stm32 hal_driver
while (count > 0U) {
count--;
}
return (pma32[2*bEpIdx + 1] & 0x03FF0000) >> 16;
#else
__I uint16_t *regPtr = pcd_ep_rx_cnt_ptr(USBx, bEpIdx);