mirror of
https://github.com/hathach/tinyusb.git
synced 2025-03-23 04:20:47 +00:00
move walkaround to dcd_ep_ctr_rx_handler(), increase cycle_count from 10 to 20 (40 cycle)
This commit is contained in:
parent
27afa56844
commit
fc54ad43b1
4
.idea/runConfigurations/stlink.xml
generated
4
.idea/runConfigurations/stlink.xml
generated
@ -1,6 +1,6 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<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 "/opt/st/stm32cubeide_1.12.1/plugins/com.st.stm32cube.ide.mcu.externaltools.cubeprogrammer.linux64_2.1.100.202311100844/tools/bin" --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">
|
<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 "/opt/st/stm32cubeide_1.14.0/plugins/com.st.stm32cube.ide.mcu.externaltools.cubeprogrammer.linux64_2.1.100.202311100844/tools/bin" --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::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">
|
<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" />
|
<debugger kind="GDB" isBundled="true" />
|
||||||
</custom-gdb-server>
|
</custom-gdb-server>
|
||||||
<method v="2">
|
<method v="2">
|
||||||
|
@ -200,8 +200,7 @@ static bool dcd_read_packet_memory_ff(tu_fifo_t * ff, uint16_t src, uint16_t wNB
|
|||||||
// Inline helper
|
// 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 epnum = tu_edpt_number(ep_addr);
|
||||||
uint8_t dir = tu_edpt_dir(ep_addr);
|
uint8_t dir = tu_edpt_dir(ep_addr);
|
||||||
// Fix -Werror=null-dereference
|
// 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);
|
xfer_ctl_t * xfer = xfer_ctl_ptr(ep_addr);
|
||||||
if((xfer->total_len != xfer->queued_len)) /* TX not complete */
|
if((xfer->total_len != xfer->queued_len)) /* TX not complete */
|
||||||
{
|
{
|
||||||
dcd_transmit_packet(xfer, EPindex);
|
dcd_transmit_packet(xfer, EPindex);
|
||||||
}
|
}
|
||||||
else /* TX Complete */
|
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
|
// Handle CTR interrupt for the RX/OUT direction
|
||||||
//
|
|
||||||
// Upon call, (wIstr & USB_ISTR_DIR) == 0U
|
// 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 EPindex = wIstr & USB_ISTR_EP_ID;
|
||||||
uint32_t wEPRegVal = pcd_get_endpoint(USB, EPindex);
|
uint32_t wEPRegVal = pcd_get_endpoint(USB, EPindex);
|
||||||
uint8_t ep_addr = wEPRegVal & USB_EPADDR_FIELD;
|
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,
|
// Verify the CTR_RX bit is set. This was in the ST Micro code,
|
||||||
// but I'm not sure it's actually necessary?
|
// but I'm not sure it's actually necessary?
|
||||||
if((wEPRegVal & USB_EP_CTR_RX) == 0U)
|
if((wEPRegVal & USB_EP_CTR_RX) == 0U) {
|
||||||
{
|
|
||||||
return;
|
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)
|
// (Based on the docs, it seems SETUP will always be accepted after CTR is cleared)
|
||||||
if(ep_addr == 0u)
|
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_set_ep_rx_bufsize(USB, EPindex, CFG_TUD_ENDPOINT0_SIZE);
|
||||||
pcd_clear_rx_ep_ctr(USB, EPindex);
|
pcd_clear_rx_ep_ctr(USB, EPindex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dcd_ep_ctr_handler(void)
|
static void dcd_ep_ctr_handler(void) {
|
||||||
{
|
|
||||||
uint32_t wIstr;
|
uint32_t wIstr;
|
||||||
|
|
||||||
/* stay in loop while pending interrupts */
|
/* stay in loop while pending interrupts */
|
||||||
while (((wIstr = USB->ISTR) & USB_ISTR_CTR) != 0U)
|
while (((wIstr = USB->ISTR) & USB_ISTR_CTR) != 0U) {
|
||||||
{
|
if ((wIstr & USB_ISTR_DIR) == 0U) {
|
||||||
|
/* TX/IN */
|
||||||
if ((wIstr & USB_ISTR_DIR) == 0U) /* TX/IN */
|
|
||||||
{
|
|
||||||
dcd_ep_ctr_tx_handler(wIstr);
|
dcd_ep_ctr_tx_handler(wIstr);
|
||||||
}
|
} else {
|
||||||
else /* RX/OUT*/
|
/* RX/OUT*/
|
||||||
{
|
|
||||||
dcd_ep_ctr_rx_handler(wIstr);
|
dcd_ep_ctr_rx_handler(wIstr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx) {
|
||||||
#ifdef FSDEV_BUS_32BIT
|
#ifdef FSDEV_BUS_32BIT
|
||||||
(void) USBx;
|
(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;
|
return (pma32[2*bEpIdx + 1] & 0x03FF0000) >> 16;
|
||||||
#else
|
#else
|
||||||
__I uint16_t *regPtr = pcd_ep_rx_cnt_ptr(USBx, bEpIdx);
|
__I uint16_t *regPtr = pcd_ep_rx_cnt_ptr(USBx, bEpIdx);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user