LPC11u24/301 Hard Fault in USB ROM Initialization

Discussion created by lpcware Employee on Jun 15, 2016
Latest reply on Jun 18, 2016 by lpcware
Content originally posted in LPCWare by crawford on Sun Mar 13 11:52:00 MST 2016
Hey everyone,

I'm running into a very bizarre issue while trying to use the builtin USB stack on my LPC11u24/301. I'm seeing a hard fault somewhere within the hardware initialization call (USBD_API->hw->Init), but only when I call it without USB connected to my host. I've set a breakpoint on that line of code. If I have USB connected when I continue, the code runs fine and I see my CDC device enumerate on my host. I can plug and unplug the device all day long and everything runs perfectly! If I don't have USB connected, the processor hard faults somewhere in the initialization call.

I'm not the best at debugging these things (closer to the worst), but from what I've gathered, the ROM appears to be jumping to whatever value I have set in USBD_API_INIT_PARAM_T.mem_size. Here is my declaration of usb_param:

USBD_API_INIT_PARAM_T usb_param = {
.usb_reg_base = LPC_USB0_BASE,
.max_num_ep   = USB_MAX_EP_NUM,
.mem_base     = USB_STACK_MEM_BASE,
.mem_size     = USB_STACK_MEM_SIZE,

...where USB_STACK_MEM_SIZE is 0x800 in this particular example. I have set it to other values and watched the ROM attempt to jump to that particular value, so they must be related. USB_STACK_MEM_BASE is 0x20004000 in this case (USB memory). I have tried placing this in the main bank with no change in behavior. Now for the interesting bit: the stacked registers from my hard-fault handler:

(gdb) print/x *stack
$1 = {R0 = 0x9b4, R1 = 0x9ec, R2 = 0x9b4, R3 = 0x10000000, R12 = 0xfffffe00, LR = 0x3ab, PC = 0x800,
  xPSR = {b = {ISR = 0x0, _reserved0 = 0x0, T = 0x0, IT = 0x0, Q = 0x0, V = 0x0, C = 0x0, Z = 0x0,
      N = 0x1}, w = 0x80000000}}

Here we see that the ROM attempted to jump to 0x800 (the value of USB_STACK_MEM_SIZE). Looking at the disassembly, we see that the link register's value points to the instruction after the call to init (which we would expect):

       /* USB Initialization */
        ret = USBD_API->hw->Init(&g_hUsb, &desc, &usb_param);
39a:   4b11            ldr     r3, [pc, #68]   ; (3e0 <main+0xc4>)
39c:   681b            ldr     r3, [r3, #0]
39e:   681b            ldr     r3, [r3, #0]
3a0:   685b            ldr     r3, [r3, #4]
3a2:   aa05            add     r2, sp, #20
3a4:   4669            mov     r1, sp
3a6:   4813            ldr     r0, [pc, #76]   ; (3f4 <main+0xd8>)
3a8:   4798            blx     r3
        if (ret == LPC_OK) {
3aa:   2800            cmp     r0, #0
3ac:   d113            bne.n   3d6 <main+0xba>

Of course, in the process of reproducing this issue while writing up this post, one time I did see it successfully initialize without USB connected. I was able to plug and unplug a bunch and the device enumerated properly. That would indicate to me that there is either a race condition in the initialization or some uninitialized memory being referenced. So, given all of this, I am quite confused as to what is going wrong. Any tips or guidance would be greatly appreciated.