Code Monkey home page Code Monkey logo

uc-usbh's People

Contributors

forg0ne avatar jamagasr avatar joetde avatar wes-fflores avatar wes-jmagasrevy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

uc-usbh's Issues

USBH_HID_DevLock() releases the mutex very early

USBH_HID_DevLock() should only acquire the hid mutex, but instead, it acquires it and then releases it. The release job should be done by USBH_HID_DevUnLock()

FIX
static USBH_ERR USBH_HID_DevLock (USBH_HID_DEV *p_hid_dev)
{
CPU_INT08U state;
CPU_SR_ALLOC();

CPU_CRITICAL_ENTER();
state = p_hid_dev->State;
CPU_CRITICAL_EXIT();

if (state != USBH_CLASS_DEV_STATE_CONN) {
return (USBH_ERR_DEV_NOT_READY);
}

(void)USBH_OS_MutexLock(p_hid_dev->HMutex);
if (p_hid_dev->State != USBH_CLASS_DEV_STATE_CONN) {
(void)USBH_OS_MutexUnlock(p_hid_dev->HMutex);
return (USBH_ERR_DEV_NOT_READY);
}
//(void)USBH_OS_MutexUnlock(p_hid_dev->HMutex); <<<NEEDS TO BE REMOVED

return (USBH_ERR_NONE);
}

[HCD/ATSAMx] Root hub RefCnt overflow triggered by reconnects causes infinite recursion

While integrating uC-USBH using the ATSAMx HCD for a client, I was running some tests where an external hub with devices on two ports was continuously disconnected from and reconnected to the root hub every few seconds. After a few hours (about 2000 disconnects/reconnects, give or take), I found that the system would crash and run into a reset.

So I turned on logging and got (again, after a few hours):

[2022-06-06 14:56:57.351658] I:usbh_hub.c:1065: Port 1 : Device Removed.
[2022-06-06 14:56:57.351697] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:57.351776] I:usbh_core.c:4116: URB is in ASYNC QUEUE
[2022-06-06 14:56:57.370743] I:usbh_core.c:4116: URB is in ASYNC QUEUE
[2022-06-06 14:56:58.536916] I:usbh_hub.c:1040: Port 1 : Device Connected.
[2022-06-06 14:56:58.743544] I:usbh_hub.c:1111: Port 1 : Port Reset complete, device speed is FULL Speed(12 Mb/Sec)
[2022-06-06 14:56:58.796466] I:usbh_core.c:985: Port 1: Device Address: 9.
[2022-06-06 14:56:58.796574] I:usbh_core.c:4992: Product      : USB 2.0 Hub
[2022-06-06 14:56:59.593510] I:usbh_hub.c:2242: Ext HUB (Addr# 9) connected
[2022-06-06 14:56:59.593609] I:usbh_hub.c:931: USBH_HUB_ISR() fails. Err=703 errcnt=0
[2022-06-06 14:56:59.593630] I:usbh_hub.c:1040: Port 1 : Device Connected.
[2022-06-06 14:56:59.593646] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.593662] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.593677] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.593692] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.593706] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.593727] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.604314] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.604426] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.604447] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.604462] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.604478] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.604500] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.604525] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.604554] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.604580] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.604609] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.614807] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.614851] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.614856] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.614860] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.614865] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.614869] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.614873] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.614880] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.614887] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.614893] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.625437] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.625529] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.625548] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.625565] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.625579] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.625593] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.625607] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.625626] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.625650] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.636332] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.636430] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.636448] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.636462] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.636478] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.636491] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.636505] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.636518] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.636537] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.636560] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.647280] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.647376] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.647394] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.647408] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.647424] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.647438] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.647452] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.647466] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.647480] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.647505] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.657996] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.658093] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.658111] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.658127] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.658141] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.658158] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.658182] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.658207] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.658234] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.658261] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.668679] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.668778] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.668796] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.668810] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.668825] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.668839] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.668853] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.668867] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.668886] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.679226] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.679318] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.679337] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.679351] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.679366] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.679380] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.679394] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.679407] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.679428] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.679453] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.690039] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.690138] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.690157] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.690172] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.690186] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.690200] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.690214] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.690228] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.690248] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.690273] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.700870] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.700980] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.701000] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.701015] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.701031] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.701049] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.701075] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.701101] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.701131] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.722719] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.722835] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.722855] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.722874] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.722896] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.722919] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.722944] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected
[2022-06-06 14:56:59.722962] I:usbh_hub.c:2248: Ext HUB (Addr# 9) disconnected

The USBH_HUB_ISR() fails was unique and seemed to be where things started to go wrong, so I set a breakpoint:

Breakpoint 1, USBH_HUB_ISR (p_ep=0x20006504 <USBH_HUB_Arr+1320>, p_buf=0x200065bc <USBH_HUB_Arr+1504>, buf_len=<optimized out>, xfer_len=<optimized out>, p_arg=0x20006504 <USBH_HUB_Arr+1320>, err=USBH_ERR_HC_IO) at uC-USBH/Source/usbh_hub.c:929
929	               USBH_PRINT_LOG("USBH_HUB_ISR() fails. Err=%d errcnt=%d\r\n",
(gdb) bt
#0  USBH_HUB_ISR (p_ep=0x20006504 <USBH_HUB_Arr+1320>, p_buf=0x200065bc <USBH_HUB_Arr+1504>, buf_len=<optimized out>, 
    xfer_len=<optimized out>, p_arg=0x20006504 <USBH_HUB_Arr+1320>, err=USBH_ERR_HC_IO)
    at uC-USBH/Source/usbh_hub.c:929
#1  0x000145fe in USBH_URB_Notify (p_urb=0x20003438 <hal::(anonymous namespace)::App_USBH_AsyncTaskStk+3964>)
    at uC-USBH/Source/usbh_core.c:4189
#2  USBH_URB_Complete (p_urb=p_urb@entry=0x20006520 <USBH_HUB_Arr+1348>)
    at uC-USBH/Source/usbh_core.c:3498
#3  0x000146f8 in USBH_AsyncTask (p_arg=<optimized out>)
    at uC-USBH/Source/usbh_core.c:5248
#4  0x00017834 in OSTaskQuery (prio=4 '\004', p_task_data=0x6060606)
    at uC-OS2/Source/os_task.c:1100
#5  0x00000000 in ?? ()

Then I stepped into USBH_HUB_Disconn:

Breakpoint 3, USBH_HUB_Disconn (p_class_dev=0x20006504 <USBH_HUB_Arr+1320>) at uC-USBH/Source/usbh_hub.c:642
642	{
(gdb) bt
#0  USBH_HUB_Disconn (p_class_dev=0x20006504 <USBH_HUB_Arr+1320>)
    at uC-USBH/Source/usbh_hub.c:642
#1  0x00013c96 in USBH_ClassDrvDisconn (p_dev=p_dev@entry=0x20005910 <USBH_Host+6308>)
    at uC-USBH/Source/usbh_class.c:504
#2  0x0001480c in USBH_DevDisconn (p_dev=p_dev@entry=0x20005910 <USBH_Host+6308>)
    at uC-USBH/Source/usbh_core.c:1041
#3  0x00015746 in USBH_HUB_EventProcess ()
    at uC-USBH/Source/usbh_hub.c:1046
#4  USBH_HUB_EventTask (p_arg=<optimized out>)
    at uC-USBH/Source/usbh_hub.c:293
#5  0x00017834 in OSTaskQuery (prio=4 '\004', p_task_data=0x20006508 <USBH_HUB_Arr+1324>)
    at uC-OS2/Source/os_task.c:1100
#6  0x00000000 in ?? ()

And this is where the code goes into infinite recursion:

#0  USBH_HUB_Disconn (p_class_dev=0x20006504 <USBH_HUB_Arr+1320>)
    at uC-USBH/Source/usbh_hub.c:642
#1  0x00013c96 in USBH_ClassDrvDisconn (p_dev=p_dev@entry=0x20005910 <USBH_Host+6308>)
    at uC-USBH/Source/usbh_class.c:504
#2  0x0001480c in USBH_DevDisconn (p_dev=p_dev@entry=0x20005910 <USBH_Host+6308>)
    at uC-USBH/Source/usbh_core.c:1041
#3  0x0001532c in USBH_HUB_Uninit (p_hub_dev=0x20006504 <USBH_HUB_Arr+1320>)
    at uC-USBH/Source/usbh_hub.c:756
#4  USBH_HUB_Disconn (p_class_dev=0x20006504 <USBH_HUB_Arr+1320>)
    at uC-USBH/Source/usbh_hub.c:649
#5  0x00013c96 in USBH_ClassDrvDisconn (p_dev=p_dev@entry=0x20005910 <USBH_Host+6308>)
    at uC-USBH/Source/usbh_class.c:504
#6  0x0001480c in USBH_DevDisconn (p_dev=p_dev@entry=0x20005910 <USBH_Host+6308>)
    at uC-USBH/Source/usbh_core.c:1041
#7  0x0001532c in USBH_HUB_Uninit (p_hub_dev=0x20006504 <USBH_HUB_Arr+1320>)
    at uC-USBH/Source/usbh_hub.c:756
#8  USBH_HUB_Disconn (p_class_dev=0x20006504 <USBH_HUB_Arr+1320>)
    at uC-USBH/Source/usbh_hub.c:649
#9  0x00013c96 in USBH_ClassDrvDisconn (p_dev=p_dev@entry=0x20005910 <USBH_Host+6308>)
    at uC-USBH/Source/usbh_class.c:504
#10 0x0001480c in USBH_DevDisconn (p_dev=p_dev@entry=0x20005910 <USBH_Host+6308>)
    at uC-USBH/Source/usbh_core.c:1041
#11 0x0001532c in USBH_HUB_Uninit (p_hub_dev=0x20006504 <USBH_HUB_Arr+1320>)
    at uC-USBH/Source/usbh_hub.c:756
#12 USBH_HUB_Disconn (p_class_dev=0x20006504 <USBH_HUB_Arr+1320>)
    at uC-USBH/Source/usbh_hub.c:649
#13 0x00013c96 in USBH_ClassDrvDisconn (p_dev=p_dev@entry=0x20005910 <USBH_Host+6308>)
    at uC-USBH/Source/usbh_class.c:504
#14 0x0001480c in USBH_DevDisconn (p_dev=p_dev@entry=0x20005910 <USBH_Host+6308>)
    at uC-USBH/Source/usbh_core.c:1041
#15 0x0001532c in USBH_HUB_Uninit (p_hub_dev=0x20006504 <USBH_HUB_Arr+1320>)
    at uC-USBH/Source/usbh_hub.c:756
#16 USBH_HUB_Disconn (p_class_dev=0x20006504 <USBH_HUB_Arr+1320>)
    at uC-USBH/Source/usbh_hub.c:649
#17 0x00013c96 in USBH_ClassDrvDisconn (p_dev=p_dev@entry=0x20005910 <USBH_Host+6308>)
    at uC-USBH/Source/usbh_class.c:504
#18 0x0001480c in USBH_DevDisconn (p_dev=p_dev@entry=0x20005910 <USBH_Host+6308>)
    at uC-USBH/Source/usbh_core.c:1041
#19 0x00015746 in USBH_HUB_EventProcess ()
    at uC-USBH/Source/usbh_hub.c:1046
#20 USBH_HUB_EventTask (p_arg=<optimized out>)
    at uC-USBH/Source/usbh_hub.c:293
#21 0x00017834 in OSTaskQuery (prio=4 '\004', p_task_data=0x20006508 <USBH_HUB_Arr+1324>)
    at uC-OS2/Source/os_task.c:1100
#22 0x00000000 in ?? ()

I've created gists for dumps of USBH_HUB_Arr and USBH_Host in case these are useful.

Basically, USBH_HUB_EventProcess calls USBH_DevDisconn, which calls USBH_ClassDrvDisconn, which for some reason recurses into USBH_HUB_Disconn while iterating the ports and ends up with the same hub pointer. In frame 19 (USBH_HUB_EventProcess), p_hub_dev is 0x20006504, which corresponds to USBH_HUB_Arr[5]. This hub's DevPtrList[0] is 0x20005910, which corresponds to USBH_Host.DevList[8]. This device has a ClassDevPtr that points back at USBH_HUB_Arr[5], which gets passed to USBH_HUB_Disconn and via USBH_HUB_Uninit back to USBH_DevDisconn, which then repeats the same cycle, recursing until it falls off the end of the stack frame.

This is already strange by itself and might point to a different bug than the one I'm about to describe.

What really made my me scratch my head was that the failure happened relatively reliably after a certain number of reconnects. So I incrementally instrumented the code with more logging and at some point saw that the root hub's reference counter field (RefCnt) was slowly incrementing. An increment happened on average every 8 reconnects. So it took some time until the RefCnt overflowed from 255 to 0, and the infinite recursion above seems to be a result of that. I don't fully understand what's going on, but I'm assuming that some part of the code is under the impression that the root hub is no longer in use and puts it back into the free list, whereas some other part of the code is still actively using it.

In any case, I was now looking further into these unexpected increments of the reference counter, and these are actually quite easy to explain. When a hardware interrupt occurs, an event is queued using USBH_HUB_RH_Event, and this event is later processed asynchronously. Now, USBH_HUB_RH_Event increments the associated hub's RefCnt field and then adds it to the event list formed by USBH_HUB_HeadPtr and USBH_HUB_TailPtr. However, it seems to assume that it won't be called more than once for the same hub before that hub has been removed from the event list again. So if USBH_HUB_RH_Event is called twice for the same hub, it'll increment the RefCnt for the hub twice and set USBH_HUB_TailPtr->NxtPtr to point to the hub; in case of just a single root hub, that means the hub is now linking to itself. Due to the way USBH_HUB_EventProcess checks the queue, this circular reference doesn't cause any immediate issues, though (at least not with a single root hub; things will likely go very wrong as soon as a second root hub is involved). USBH_HUB_EventProcess will only see a single event and it will consequently only decrement the RefCnt once.

The above happens when disconnect/connect hardware interrupts arrive in quick succession. It seems to me that USBH_HUB_RH_Event is probably even right to assume it can only be called once for the same hub as there is a call p_rh_drv_api->IntDis(p_hc_drv) right before the RefCnt increment. I'm assuming this is supposed to disable root hub hardware interrupts until the current event has been asynchronously processed. However, at least for the ATSAMx HCD, neither IntDis nor InEn do anything:

static  CPU_BOOLEAN  USBH_ATSAMX_HCD_RHSC_IntEn (USBH_HC_DRV  *p_hc_drv)
{
    (void)p_hc_drv;

    return (DEF_OK);
}

static  CPU_BOOLEAN  USBH_ATSAMX_HCD_RHSC_IntDis (USBH_HC_DRV  *p_hc_drv)
{
    (void)p_hc_drv;

    return (DEF_OK);
}

Instead, quite a bit of interrupt enabling/disabling is going on in USBH_ATSAMX_ISR_Handler.

At this point, while I seem to understand roughly what's going on, I'm unsure about how this should be fixed. I didn't find any documented rationale for why IntEn and IntDis are unimplemented. At least the implementation for Renesas_USBHS seems to also leave them empty.

From looking at the rest of the code, it seems most likely that a fix for this issue should prevent new interrupts from being queued while there are still pending events in the queue.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.