Skip to content

Commit 6ddab6f

Browse files
committed
Fix for timing, timeout, and device switching issues
1 parent cb69f35 commit 6ddab6f

File tree

1 file changed

+127
-66
lines changed

1 file changed

+127
-66
lines changed

src/portable/wch/hcd_ch32_usbfs.c

Lines changed: 127 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -43,24 +43,26 @@
4343
__attribute__((aligned(4))) static uint8_t USBFS_RX_Buf[USBFS_RX_BUF_LEN];
4444
__attribute__((aligned(4))) static uint8_t USBFS_TX_Buf[USBFS_TX_BUF_LEN];
4545

46-
#define USB_XFER_TIMEOUT_MILLIS 500
46+
#define USB_XFER_TIMEOUT_MILLIS 100
47+
#define USB_INTERRUPT_XFER_TIMEOUT_MILLIS 1
4748

4849
#define PANIC(...) do { printf("\r\nPANIC: " __VA_ARGS__); while (true) { } } while (false)
4950

5051
#define LOG_CH32_USBFSH(...) TU_LOG3(__VA_ARGS__)
5152

5253
// Busywait for delay microseconds/nanoseconds
53-
// static void loopdelay(uint32_t count)
54-
// {
55-
// volatile uint32_t c = count / 3;
56-
// // while (c-- != 0);
57-
// asm volatile(
58-
// "1: \n" // loop label
59-
// " addi %0, %0, -1 \n" // c--
60-
// " bne %0, zero, 1b \n" // if (c != 0) goto loop
61-
// : "+r"(c) // c is input/output operand
62-
// );
63-
// }
54+
static void loopdelay(uint32_t count)
55+
{
56+
volatile uint32_t c = count / 3;
57+
if (c == 0) { return; }
58+
// while (c-- != 0);
59+
asm volatile(
60+
"1: \n" // loop label
61+
" addi %0, %0, -1 \n" // c--
62+
" bne %0, zero, 1b \n" // if (c != 0) goto loop
63+
: "+r"(c) // c is input/output operand
64+
);
65+
}
6466

6567

6668
// Endpoint status
@@ -71,21 +73,30 @@ typedef struct usb_edpt
7173

7274
uint8_t dev_addr;
7375
uint8_t ep_addr;
74-
uint16_t max_packet_size;
76+
uint8_t max_packet_size;
77+
78+
uint8_t xfer_type;
7579

7680
// Data toggle (0 or not 0) for DATA0/1
7781
uint8_t data_toggle;
82+
} usb_edpt_t;
83+
84+
85+
static usb_edpt_t usb_edpt_list[CFG_TUH_DEVICE_MAX * 6] = {};
86+
7887

88+
typedef struct usb_current_xfer_st {
89+
bool is_busy;
90+
uint8_t dev_addr;
91+
uint8_t ep_addr;
7992
// Xfer started time in millis for timeout
8093
uint32_t current_xfer_packet_start_millis;
8194
uint8_t* current_xfer_buffer;
8295
uint16_t current_xfer_bufferlen;
8396
uint16_t current_xfer_xferred_len;
97+
} usb_current_xfer_t;
8498

85-
} usb_edpt_t;
86-
87-
88-
static usb_edpt_t usb_edpt_list[8] = { };
99+
static volatile usb_current_xfer_t usb_current_xfer_info = {};
89100

90101

91102
static usb_edpt_t* get_edpt_record(uint8_t dev_addr, uint8_t ep_addr)
@@ -113,26 +124,26 @@ static usb_edpt_t* get_empty_record_slot(void)
113124
return NULL;
114125
}
115126

116-
static usb_edpt_t* add_edpt_record(uint8_t dev_addr, uint8_t ep_addr, uint16_t max_packet_size)
127+
static usb_edpt_t* add_edpt_record(uint8_t dev_addr, uint8_t ep_addr, uint16_t max_packet_size, uint8_t xfer_type)
117128
{
118129
usb_edpt_t* slot = get_empty_record_slot();
130+
if (slot == NULL) {
131+
PANIC("add_edpt_record(0x%02x, 0x%02x, ...) no slot for new record\r\n", dev_addr, ep_addr);
132+
}
119133
TU_ASSERT(slot != NULL, NULL);
120134

121135
slot->dev_addr = dev_addr;
122136
slot->ep_addr = ep_addr;
123137
slot->max_packet_size = max_packet_size;
138+
slot->xfer_type = xfer_type;
124139
slot->data_toggle = 0;
125-
slot->current_xfer_packet_start_millis = 0;
126-
slot->current_xfer_buffer = NULL;
127-
slot->current_xfer_bufferlen = 0;
128-
slot->current_xfer_xferred_len = 0;
129140

130141
slot->configured = true;
131142

132143
return slot;
133144
}
134145

135-
static usb_edpt_t* get_or_add_edpt_record(uint8_t dev_addr, uint8_t ep_addr, uint16_t max_packet_size)
146+
static usb_edpt_t* get_or_add_edpt_record(uint8_t dev_addr, uint8_t ep_addr, uint16_t max_packet_size, uint8_t xfer_type)
136147
{
137148
usb_edpt_t* ret = get_edpt_record(dev_addr, ep_addr);
138149
if (ret != NULL)
@@ -141,7 +152,7 @@ static usb_edpt_t* get_or_add_edpt_record(uint8_t dev_addr, uint8_t ep_addr, uin
141152
}
142153
else
143154
{
144-
return add_edpt_record(dev_addr, ep_addr, max_packet_size);
155+
return add_edpt_record(dev_addr, ep_addr, max_packet_size, xfer_type);
145156
}
146157
}
147158

@@ -157,6 +168,17 @@ static void remove_edpt_record_for_device(uint8_t dev_addr)
157168
}
158169
}
159170

171+
// static void dump_edpt_record_list() {
172+
// for (size_t i = 0; i < TU_ARRAY_SIZE(usb_edpt_list); i++) {
173+
// usb_edpt_t* cur = &usb_edpt_list[i];
174+
// if (cur->configured) {
175+
// printf("[%2d] Device 0x%02x Endpoint 0x%02x\r\n", i, cur->dev_addr, cur->ep_addr);
176+
// } else {
177+
// printf("[%2d] not configured\r\n", i);
178+
// }
179+
// }
180+
// }
181+
160182

161183
/** Enable or disable USBFS Host function */
162184
static void hardware_init_host(bool enabled)
@@ -180,7 +202,8 @@ static void hardware_init_host(bool enabled)
180202
USBOTG_H_FS->HOST_EP_MOD = USBFS_UH_EP_TX_EN | USBFS_UH_EP_RX_EN;
181203
USBOTG_H_FS->HOST_RX_DMA = (uint32_t)USBFS_RX_Buf;
182204
USBOTG_H_FS->HOST_TX_DMA = (uint32_t)USBFS_TX_Buf;
183-
USBOTG_H_FS->INT_EN = USBFS_UIE_TRANSFER | USBFS_UIE_DETECT;
205+
// USBOTG_H_FS->INT_EN = USBFS_UIE_TRANSFER | USBFS_UIE_DETECT;
206+
USBOTG_H_FS->INT_EN = USBFS_UIE_DETECT;
184207
}
185208
}
186209

@@ -199,6 +222,7 @@ static bool hardware_start_xfer(uint8_t pid, uint8_t ep_addr, uint8_t data_toggl
199222
USBOTG_H_FS->HOST_TX_CTRL = (data_toggle != 0) ? USBFS_UH_T_TOG : 0;
200223
USBOTG_H_FS->HOST_RX_CTRL = (data_toggle != 0) ? USBFS_UH_R_TOG : 0;
201224
USBOTG_H_FS->HOST_EP_PID = pid_edpt;
225+
USBOTG_H_FS->INT_EN |= USBFS_UIE_TRANSFER;
202226
USBOTG_H_FS->INT_FG = USBFS_UIF_TRANSFER;
203227
return true;
204228
}
@@ -371,19 +395,21 @@ void hcd_int_handler(uint8_t rhport, bool in_isr)
371395

372396
if (USBOTG_H_FS->INT_FG & USBFS_UIF_TRANSFER)
373397
{
398+
// Disable transfer interrupt
399+
USBOTG_H_FS->INT_EN &= ~USBFS_UIE_TRANSFER;
400+
// Clear the flag
401+
// USBOTG_H_FS->INT_FG = USBFS_UIF_TRANSFER;
374402
// Copy PID and Endpoint
375403
uint8_t pid_edpt = USBOTG_H_FS->HOST_EP_PID;
376404
uint8_t status = USBOTG_H_FS->INT_ST;
405+
uint8_t dev_addr = USBOTG_H_FS->DEV_ADDR & USBFS_USB_ADDR_MASK;
377406
// Clear register to stop transfer
378-
USBOTG_H_FS->HOST_EP_PID = 0;
379-
// Clear the flag
380-
USBOTG_H_FS->INT_FG = USBFS_UIF_TRANSFER;
407+
// USBOTG_H_FS->HOST_EP_PID = 0x00;
381408

382409
LOG_CH32_USBFSH("hcd_int_handler() pid_edpt=0x%02x\r\n", pid_edpt);
383410

384411
uint8_t request_pid = pid_edpt >> 4;
385-
uint8_t response_pid = USBOTG_H_FS->INT_ST & USBFS_UIS_H_RES_MASK;
386-
uint8_t dev_addr = USBOTG_H_FS->DEV_ADDR;
412+
uint8_t response_pid = status & USBFS_UIS_H_RES_MASK;
387413
uint8_t ep_addr = pid_edpt & 0x0f;
388414
if (request_pid == USB_PID_IN)
389415
{
@@ -393,7 +419,7 @@ void hcd_int_handler(uint8_t rhport, bool in_isr)
393419
usb_edpt_t* edpt_info = get_edpt_record(dev_addr, ep_addr);
394420
if (edpt_info == NULL)
395421
{
396-
PANIC("\r\nget_edpt_record() returned NULL in USBHD_IRQHandler\r\n");
422+
PANIC("\r\nget_edpt_record(0x%02x, 0x%02x) returned NULL in USBHD_IRQHandler\r\n", dev_addr, ep_addr);
397423
}
398424

399425
if (status & USBFS_UIS_TOG_OK)
@@ -406,43 +432,45 @@ void hcd_int_handler(uint8_t rhport, bool in_isr)
406432
case USB_PID_OUT:
407433
{
408434
uint16_t tx_len = USBOTG_H_FS->HOST_TX_LEN;
409-
edpt_info->current_xfer_bufferlen -= tx_len;
410-
edpt_info->current_xfer_xferred_len += tx_len;
411-
if (edpt_info->current_xfer_bufferlen == 0)
435+
usb_current_xfer_info.current_xfer_bufferlen -= tx_len;
436+
usb_current_xfer_info.current_xfer_xferred_len += tx_len;
437+
if (usb_current_xfer_info.current_xfer_bufferlen == 0)
412438
{
413-
LOG_CH32_USBFSH("USB_PID_OUT completed %d bytes\r\n", edpt_info->current_xfer_xferred_len);
414-
hcd_event_xfer_complete(dev_addr, ep_addr, edpt_info->current_xfer_xferred_len, XFER_RESULT_SUCCESS, true);
439+
LOG_CH32_USBFSH("USB_PID_%s completed %d bytes\r\n", request_pid == USB_PID_OUT ? "OUT" : "SETUP", usb_current_xfer_info.current_xfer_xferred_len);
440+
usb_current_xfer_info.is_busy = false;
441+
hcd_event_xfer_complete(dev_addr, ep_addr, usb_current_xfer_info.current_xfer_xferred_len, XFER_RESULT_SUCCESS, true);
415442
return;
416443
}
417444
else
418445
{
419446
LOG_CH32_USBFSH("USB_PID_OUT continue...\r\n");
420-
edpt_info->current_xfer_buffer += tx_len;
447+
usb_current_xfer_info.current_xfer_buffer += tx_len;
421448
uint16_t copylen = USBFS_TX_BUF_LEN;
422-
if (copylen > edpt_info->current_xfer_bufferlen)
449+
if (copylen > usb_current_xfer_info.current_xfer_bufferlen)
423450
{
424-
copylen = edpt_info->current_xfer_bufferlen;
451+
copylen = usb_current_xfer_info.current_xfer_bufferlen;
425452
}
426-
memcpy(USBFS_TX_Buf, edpt_info->current_xfer_buffer, copylen);
453+
memcpy(USBFS_TX_Buf, usb_current_xfer_info.current_xfer_buffer, copylen);
427454
hardware_start_xfer(USB_PID_OUT, ep_addr, edpt_info->data_toggle);
428455
return;
429456
}
430457
}
431458
case USB_PID_IN:
432459
{
433460
uint16_t received_len = USBOTG_H_FS->RX_LEN;
434-
edpt_info->current_xfer_xferred_len += received_len;
435-
uint16_t xferred_len = edpt_info->current_xfer_xferred_len;
461+
usb_current_xfer_info.current_xfer_xferred_len += received_len;
462+
uint16_t xferred_len = usb_current_xfer_info.current_xfer_xferred_len;
436463
LOG_CH32_USBFSH("Read %d bytes\r\n", received_len);
437-
// if (received_len > 0 && (edpt_info->current_xfer_buffer == NULL || edpt_info->current_xfer_bufferlen == 0)) {
464+
// if (received_len > 0 && (usb_current_xfer_info.current_xfer_buffer == NULL || usb_current_xfer_info.current_xfer_bufferlen == 0)) {
438465
// PANIC("Data received but buffer not set\r\n");
439466
// }
440-
memcpy(edpt_info->current_xfer_buffer, USBFS_RX_Buf, received_len);
441-
edpt_info->current_xfer_buffer += received_len;
442-
if ((received_len < edpt_info->max_packet_size) || (xferred_len == edpt_info->current_xfer_bufferlen))
467+
memcpy(usb_current_xfer_info.current_xfer_buffer, USBFS_RX_Buf, received_len);
468+
usb_current_xfer_info.current_xfer_buffer += received_len;
469+
if ((received_len < edpt_info->max_packet_size) || (xferred_len == usb_current_xfer_info.current_xfer_bufferlen))
443470
{
444471
// USB device sent all data.
445472
LOG_CH32_USBFSH("USB_PID_IN completed\r\n");
473+
usb_current_xfer_info.is_busy = false;
446474
hcd_event_xfer_complete(dev_addr, ep_addr, xferred_len, XFER_RESULT_SUCCESS, true);
447475
return;
448476
}
@@ -464,18 +492,24 @@ void hcd_int_handler(uint8_t rhport, bool in_isr)
464492
{
465493
if (response_pid == USB_PID_STALL)
466494
{
467-
LOG_CH32_USBFSH("Data toggle mismatched and STALL\r\n");
495+
LOG_CH32_USBFSH("STALL response\r\n");
468496
hcd_edpt_clear_stall(0, dev_addr, ep_addr);
469497
edpt_info->data_toggle = 0;
470498
hardware_start_xfer(request_pid, ep_addr, 0);
471499
return;
472500
}
473501
else if (response_pid == USB_PID_NAK)
474502
{
475-
LOG_CH32_USBFSH("Data toggle mismatched and NAK\r\n");
476-
uint32_t elapsed_time = board_millis() - edpt_info->current_xfer_packet_start_millis;
477-
if (elapsed_time > USB_XFER_TIMEOUT_MILLIS)
503+
LOG_CH32_USBFSH("NAK reposense\r\n");
504+
uint32_t elapsed_time = board_millis() - usb_current_xfer_info.current_xfer_packet_start_millis;
505+
if (edpt_info->xfer_type == TUSB_XFER_INTERRUPT && (elapsed_time > USB_INTERRUPT_XFER_TIMEOUT_MILLIS))
478506
{
507+
usb_current_xfer_info.is_busy = false;
508+
hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_SUCCESS, true);
509+
}
510+
else if (elapsed_time > USB_XFER_TIMEOUT_MILLIS)
511+
{
512+
usb_current_xfer_info.is_busy = false;
479513
hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_FAILED, true);
480514
}
481515
else
@@ -487,12 +521,14 @@ void hcd_int_handler(uint8_t rhport, bool in_isr)
487521
else if (response_pid == USB_PID_DATA0 || response_pid == USB_PID_DATA1)
488522
{
489523
LOG_CH32_USBFSH("Data toggle mismatched and DATA0/1 (not STALL). RX_LEN=%d\r\n", USBOTG_H_FS->RX_LEN);
524+
usb_current_xfer_info.is_busy = false;
490525
hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_FAILED, true);
491526
return;
492527
}
493528
else
494529
{
495530
LOG_CH32_USBFSH("In USBHD_IRQHandler, unexpected response PID: 0x%02x\r\n", response_pid);
531+
usb_current_xfer_info.is_busy = false;
496532
hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_FAILED, true);
497533
return;
498534
}
@@ -510,16 +546,17 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const
510546
uint8_t ep_addr = ep_desc->bEndpointAddress;
511547
uint8_t ep_num = tu_edpt_number(ep_addr);
512548
uint16_t max_packet_size = ep_desc->wMaxPacketSize;
513-
LOG_CH32_USBFSH("hcd_edpt_open(rhport=%d, dev_addr=0x%02x, %p) EndpointAdderss=0x%02x,maxPacketSize=%d\r\n", rhport, dev_addr, ep_desc, ep_addr, max_packet_size);
549+
uint8_t xfer_type = ep_desc->bmAttributes.xfer;
550+
LOG_CH32_USBFSH("hcd_edpt_open(rhport=%d, dev_addr=0x%02x, %p) EndpointAdderss=0x%02x,maxPacketSize=%d,xfer_type=%d\r\n", rhport, dev_addr, ep_desc, ep_addr, max_packet_size, xfer_type);
514551

515552
if (ep_num == 0x00)
516553
{
517-
TU_ASSERT(get_or_add_edpt_record(dev_addr, 0x00, max_packet_size) != NULL, false);
518-
TU_ASSERT(get_or_add_edpt_record(dev_addr, 0x80, max_packet_size) != NULL, false);
554+
TU_ASSERT(get_or_add_edpt_record(dev_addr, 0x00, max_packet_size, xfer_type) != NULL, false);
555+
TU_ASSERT(get_or_add_edpt_record(dev_addr, 0x80, max_packet_size, xfer_type) != NULL, false);
519556
}
520557
else
521558
{
522-
TU_ASSERT(get_or_add_edpt_record(dev_addr, ep_addr, max_packet_size) != NULL, false);
559+
TU_ASSERT(get_or_add_edpt_record(dev_addr, ep_addr, max_packet_size, xfer_type) != NULL, false);
523560
}
524561

525562
update_device_address(dev_addr);
@@ -540,26 +577,36 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *
540577
{
541578
(void)rhport;
542579

580+
while (usb_current_xfer_info.is_busy) {
581+
osal_task_delay(1);
582+
}
583+
usb_current_xfer_info.is_busy = true;
584+
543585
usb_edpt_t* edpt_info = get_edpt_record(dev_addr, ep_addr);
544586
if (edpt_info == NULL)
545587
{
546588
PANIC("get_edpt_record() returned NULL in hcd_edpt_xfer()\r\n");
547589
}
590+
591+
update_device_address(dev_addr);
592+
tusb_speed_t device_speed = hcd_port_speed_get(rhport);
593+
update_port_speed(device_speed);
548594

549-
edpt_info->current_xfer_buffer = buffer;
550-
edpt_info->current_xfer_bufferlen = buflen;
551-
552-
edpt_info->current_xfer_packet_start_millis = board_millis();
553-
edpt_info->current_xfer_xferred_len = 0;
595+
usb_current_xfer_info.dev_addr = dev_addr;
596+
usb_current_xfer_info.ep_addr = ep_addr;
597+
usb_current_xfer_info.current_xfer_buffer = buffer;
598+
usb_current_xfer_info.current_xfer_bufferlen = buflen;
599+
usb_current_xfer_info.current_xfer_packet_start_millis = board_millis();
600+
usb_current_xfer_info.current_xfer_xferred_len = 0;
554601

555602
if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN)
556603
{
557-
LOG_CH32_USBFSH("hcd_edpt_xfer(): READ, ep_addr=0x%02x, len=%d\r\n", ep_addr, buflen);
604+
LOG_CH32_USBFSH("hcd_edpt_xfer(): READ, dev_addr=0x%02x, ep_addr=0x%02x, len=%d\r\n", dev_addr, ep_addr, buflen);
558605
return hardware_start_xfer(USB_PID_IN, ep_addr, edpt_info->data_toggle);
559606
}
560607
else
561608
{
562-
LOG_CH32_USBFSH("hcd_edpt_xfer(): WRITE, ep_addr=0x%02x, len=%d\r\n", ep_addr, buflen);
609+
LOG_CH32_USBFSH("hcd_edpt_xfer(): WRITE, dev_addr=0x%02x, ep_addr=0x%02x, len=%d\r\n", dev_addr, ep_addr, buflen);
563610
uint16_t copylen = USBFS_TX_BUF_LEN;
564611
if (copylen > buflen)
565612
{
@@ -584,8 +631,20 @@ bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr)
584631
bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8])
585632
{
586633
(void)rhport;
634+
635+
if (usb_current_xfer_info.is_busy) {
636+
osal_task_delay(1);
637+
}
638+
usb_current_xfer_info.is_busy = true;
639+
587640
LOG_CH32_USBFSH("hcd_setup_send(rhport=%d, dev_addr=0x%02x, %p)\r\n", rhport, dev_addr, setup_packet);
588641

642+
// loopdelay(SystemCoreClock / 1000000 * 100);
643+
loopdelay(1);
644+
645+
update_device_address(dev_addr);
646+
tusb_speed_t device_speed = hcd_port_speed_get(rhport);
647+
update_port_speed(device_speed);
589648

590649
usb_edpt_t* edpt_info_tx = get_edpt_record(dev_addr, 0x00);
591650
usb_edpt_t* edpt_info_rx = get_edpt_record(dev_addr, 0x80);
@@ -600,11 +659,13 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet
600659
const uint16_t setup_packet_datalen = 8;
601660
memcpy(USBFS_TX_Buf, setup_packet, setup_packet_datalen);
602661
USBOTG_H_FS->HOST_TX_LEN = setup_packet_datalen;
603-
604-
edpt_info_tx->current_xfer_packet_start_millis = board_millis();
605-
edpt_info_tx->current_xfer_buffer = USBFS_TX_Buf;
606-
edpt_info_tx->current_xfer_bufferlen = setup_packet_datalen;
607-
edpt_info_tx->current_xfer_xferred_len = 0;
662+
uint8_t ep_addr = (setup_packet[0] & 0x80) ? 0x80 : 0x00;
663+
usb_current_xfer_info.dev_addr = dev_addr;
664+
usb_current_xfer_info.ep_addr = ep_addr;
665+
usb_current_xfer_info.current_xfer_packet_start_millis = board_millis();
666+
usb_current_xfer_info.current_xfer_buffer = USBFS_TX_Buf;
667+
usb_current_xfer_info.current_xfer_bufferlen = setup_packet_datalen;
668+
usb_current_xfer_info.current_xfer_xferred_len = 0;
608669

609670
hardware_start_xfer(USB_PID_SETUP, 0, 0);
610671

0 commit comments

Comments
 (0)