Ok so this bug was pretty interesting. Basically upon branching into the USB isr I call tclib_printf() to print a message to the serial port. tclib_printf would stall trying to retrieve a mutex lock held by the SysTick isr. A dump of the core registers indicated the USB interrupt was executing and SysTick was pending but it would never hand over. Deadlock.
Now I know that the Cortex-m3 core NVIC controller implements priority based preemption and I felt that leaving the default settings in place and since SysTick was at a lower position in the vector table than Usb it would automatically pre-empt.
Thats not the case. Some googling and a reread of the Cortex-m3 r1p1 manual cleared things up.
Basically only the first three interrupts (fault, nmi, reset) are automatically locked in with a priority that is non configurable. The other positions in the exception table (position <= 15) and external interrupts of peripherals(position >16) are configurable. And here the kicker:
In order for an Irq to preempt the currently executing Irq, its priority must be greater (smaller number) than that of the currently executing Irq. Meaning if they have identical priorities (as they did because I never bothered to change the default power up settings) then Systick will never preempt Usb.
Once I discovered this - I made a quick change to verify before putting in a permanent fix in both stm32_nvic_init() and stm32_nvic_install_isr(). Now I can see usb interaction while the SysTick handler' keep-alive-LED-blink continues to run.
before
/*set the priority low (high number) so as not to conflict with systick*/
wdByteIdx = (wdIrqNum / 4);
ptrTemp = PTR_STM32_NVIC_INTP_BASE;
ptrTemp += wdByteIdx;
(*ptrTemp)= 0xffffffff;
after
/*set the priority low (high number) so as not to conflict with systick*/
wdByteIdx = (wdIrqNum / 4);
wdBitIdx = (wdIrqNum % 4);
wdTemp = (wdIrqNum >> 4); /*build prio from irqnum*/
if(wdTemp == 0)
wdTemp++;
ptrTemp = PTR_STM32_NVIC_INTP_BASE;
ptrTemp += wdByteIdx;
(*ptrTemp)= ((wdTemp << 4) << (wdBitIdx << 8)); /*bits [7:4] of prio*/
Now to start debugging USB communication. I may need to fish out my USB sniffer.
+-++-++-++-+ +-++-++-++-++-++-++-++-+ +-++-++-++-++-++-++-++-++-+
|I||g||b||o| |E||m||b||e||d||d||e||d| |C||o||r||t||e||x||-||m||3|
+-++-++-++-+ +-++-++-++-++-++-++-++-+ +-++-++-++-++-++-++-++-++-+
-------user-usb-connect-request---------
--------RESET-----------
-------user-usb-disconnect-request------
-------user-usb-connect-request---------
--------RESET-----------
rombios@lenovo:~/FOR_NBOX$ dmesg
[59112.279114] usb 1-3.4: new full speed USB device number 60 using ehci_hcd
[59112.352119] usb 1-3.4: device descriptor read/64, error -32
[59112.526134] usb 1-3.4: device descriptor read/64, error -32
[59112.700189] usb 1-3.4: new full speed USB device number 61 using ehci_hcd
[59112.774164] usb 1-3.4: device descriptor read/64, error -32
[59112.949177] usb 1-3.4: device descriptor read/64, error -32
[59113.123905] usb 1-3.4: new full speed USB device number 62 using ehci_hcd
[59113.526020] usb 1-3.4: device not accepting address 62, error -32
[59113.599118] usb 1-3.4: new full speed USB device number 63 using ehci_hcd
[59114.001029] usb 1-3.4: device not accepting address 63, error -32
[59114.001150] hub 1-3:1.0: unable to enumerate USB device on port 4
No comments:
Post a Comment