LPCUSBLib Generic HID ROM Driver Bugs

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

LPCUSBLib Generic HID ROM Driver Bugs

968 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by neilt6 on Wed Jul 17 14:19:32 MST 2013
I've just spent an enraging 2 full days trying to get a generic HID device to work properly on an LPC11U35 using the on-chip ROM drivers with LPCUSBLib... In that time I've encountered so many bugs, and glitches, and "things that make you go hmm", it's not even funny. Before I start ranting, I should mention I'm doing the same thing on an ATmega32U4 running LUFA (Which LPCUSBLib is based on), and it works just fine. I'll start from the beginning:

First I created a new workspace and imported the LPC11U14 USB examples. Compiled the GenericHID example unmodified, 14KB later, surprise it works, so I move on to enabling the ROM drivers. This is where the fun starts... The first thing I did was change device symbol on all the projects to __LPC11U2X_3X__, then I changed the MCU selection to LPC11U35/401, and finally changed USE_USB_ROM_STACK to 1, crossed my fingers, and hit Build. CRASH, BOOM, BANG, undefined reference to `Generic_HID_Interface'! Hmm... So I tried building the other examples, most of them failed, but the CDC example built ok. Turns out, Generic_HID_Interface has been declared "static"... So I fixed that, and now it builds and runs. Hooray I thought, progress! So I opened up HIDClient.exe, and starting spamming things. Sigh... The button report won't work... I scratched my head over this one for a while, and ended up comparing the example to the older one that came with nxpUSBlib. Turns out GenericReport, DeviceDescriptor, and ConfigurationDescriptor are supposed to be "const"... So I changed those in Descriptors.c, and UsbRom.c, rebuilt, and tried it again. This time everything seemed to work, or so I thought. This is where things start getting really weird... The ATmega32U4 I'm replacing is using 64 byte reports, so I changed GENERIC_EPSIZE, and GENERIC_REPORT_SIZE to 64 in Descriptors.h, and rebuilt. Windows no longer receives the product string! Instead, HIDClient.exe lists it as "Device 1". Both reports still work though, so I rebuilt it using the software drivers. Windows now recognizes the product string, but the LED report no longer works, or at least, not all the time... And that's when I flipped the table over (figuratively speaking of course), and came here for help.

So the question is, what exactly am I doing wrong? Why have I had to make so many changes to the example just to get it to run properly, and how do I fix this new issue?
Labels (1)
0 Kudos
5 Replies

768 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by ray@photosonix.com on Sun Oct 12 20:47:18 MST 2014
Does anyone know of a case where the USB ROM for the LPC1347 was used successfully?

Is a description available of how INIT sets up buffer pointers and buffers in the RAM assigned to the USB stack? The USB handle points to some possible buffer addresses, and there are lots of values stored there, but what WriteEP does won't work no matter how I try to correct the values INIT has left there. Before wasting more time I would like to get convinced that it can be made to work.
0 Kudos

768 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by neilt6 on Tue Jul 23 09:38:37 MST 2013

Quote: Tsuneo

Quote:
Anyway, since I clearly can't rely on LPCUSBLib and nobody here seems eager to help me


Agree.
I never use LPCOpen for USB.
I look in LPCOpen, just when someone asks on it.


Quote:
1. The examples just set mem_base and mem_size to the upper 4KB of RamLoc8, isn't it possible that the linker could put something there that the ROM drivers would clobber?


It's possible. The space should be reserved for the ROM driver by linker script (or IDE setting).


Quote:
2. What's the 2KB of USB RAM at 0x20004000 used for? Is it used for endpoints only, or can I allocate memory for the drivers in there too?


Though it has name "USB RAM", it isn't actually bound to USB.
USB engine places endpoint status block on the RAM specified by EPLISTSTART register. The endpoint buffers are specified by DATABUFSTART (page address) and the offset field of endpoint status. These blocks are assigned to any RAM bank.

Here are examples on HID ROM driver.
a) usb_param.mem_base = 0x10001000;
EPLISTSTART     0x10001000
DATABUFSTART    0x10000000
EPBUFCFG        0x000003FC (BUF_SB = 0xFF: double buffer enabled)

USB EP Command/Status FIFO (at EPLISTSTART)
0x00 EP0OUT     0x00400048(0x0x10001200 - buffer address)
0x04 EP0SETUP   0x00400049(0x0x10001240)
0x08 EP0IN      0x00400048(0x0x10001200)
0x0C Reserved   0x40000000
0x10 EP1OUT_0   0x9004004C(0x0x10001300)
0x14 EP1OUT_1   0x8004004D(0x0x10001340)
0x18 EP1IN_0    0x0000004A(0x0x10001280)
0x1C EP1IN_1    0x0000004B(0x0x100012C0)

b) usb_param.mem_base = 0x20004000;
EPLISTSTART     0x20004000
DATABUFSTART    0x20000000
EPBUFCFG        0x000003FC (BUF_SB = 0xFF: double buffer enabled)

USB EP Command/Status FIFO (at EPLISTSTART)
0x00 EP0OUT     0x00400108(0x0x20004200 - buffer address)
0x04 EP0SETUP   0x00400109(0x0x20004240)
0x08 EP0IN      0x00400108(0x0x20004200)
0x0C Reserved   0x40000000
0x10 EP1OUT_0   0x9004010C(0x0x20004300)
0x14 EP1OUT_1   0x8004010D(0x0x20004340)
0x18 EP1IN_0    0x0000010A(0x0x20004280)
0x1C EP1IN_1    0x0000010B(0x0x200042C0)


Tsuneo


Cool, thanks for the clarification! Anyway, I just discovered USBPort by DZX Designs while I was searching this site for more info. It's awesome! Just include the files, edit the string descriptors, and it goes. They've got a secondary bootloader as well that makes programmatic firmware updates really easy. I figured for the amount of time I've wasted on USB, $499 per product is nothing to complain about. This is what I'm going to recommend to people who're just looking for driverless communication from now on.
0 Kudos

768 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Tsuneo on Fri Jul 19 15:14:35 MST 2013

Quote:
Anyway, since I clearly can't rely on LPCUSBLib and nobody here seems eager to help me


Agree.
I never use LPCOpen for USB.
I look in LPCOpen, just when someone asks on it.


Quote:
1. The examples just set mem_base and mem_size to the upper 4KB of RamLoc8, isn't it possible that the linker could put something there that the ROM drivers would clobber?


It's possible. The space should be reserved for the ROM driver by linker script (or IDE setting).


Quote:
2. What's the 2KB of USB RAM at 0x20004000 used for? Is it used for endpoints only, or can I allocate memory for the drivers in there too?


Though it has name "USB RAM", it isn't actually bound to USB.
USB engine places endpoint status block on the RAM specified by EPLISTSTART register. The endpoint buffers are specified by DATABUFSTART (page address) and the offset field of endpoint status. These blocks are assigned to any RAM bank.

Here are examples on HID ROM driver.
a) usb_param.mem_base = 0x10001000;
EPLISTSTART     0x10001000
DATABUFSTART    0x10000000
EPBUFCFG        0x000003FC (BUF_SB = 0xFF: double buffer enabled)

USB EP Command/Status FIFO (at EPLISTSTART)
0x00 EP0OUT     0x00400048(0x0x10001200 - buffer address)
0x04 EP0SETUP   0x00400049(0x0x10001240)
0x08 EP0IN      0x00400048(0x0x10001200)
0x0C Reserved   0x40000000
0x10 EP1OUT_0   0x9004004C(0x0x10001300)
0x14 EP1OUT_1   0x8004004D(0x0x10001340)
0x18 EP1IN_0    0x0000004A(0x0x10001280)
0x1C EP1IN_1    0x0000004B(0x0x100012C0)

b) usb_param.mem_base = 0x20004000;
EPLISTSTART     0x20004000
DATABUFSTART    0x20000000
EPBUFCFG        0x000003FC (BUF_SB = 0xFF: double buffer enabled)

USB EP Command/Status FIFO (at EPLISTSTART)
0x00 EP0OUT     0x00400108(0x0x20004200 - buffer address)
0x04 EP0SETUP   0x00400109(0x0x20004240)
0x08 EP0IN      0x00400108(0x0x20004200)
0x0C Reserved   0x40000000
0x10 EP1OUT_0   0x9004010C(0x0x20004300)
0x14 EP1OUT_1   0x8004010D(0x0x20004340)
0x18 EP1IN_0    0x0000010A(0x0x20004280)
0x1C EP1IN_1    0x0000010B(0x0x200042C0)


Tsuneo
0 Kudos

768 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by neilt6 on Fri Jul 19 07:59:51 MST 2013
Well, after stepping through the library code several times I'm still clueless as to why this is hard faulting on memcmp(). nxpUSBlib v0.98 doesn't appear to have the same problem, but when I step through it I don't notice any code differences. One thing that seemed odd is that both libraries only allocate 8 bytes for the HID driver, when a quick call to GetMemSize() specifies 56 bytes... Anyway, since I clearly can't rely on LPCUSBLib and nobody here seems eager to help me, I'm being forced to build my own library around the older ROM driver example code. Now I've just got a few questions about the ROM driver's memory model. For reference, I'm using an LPC11U35/401:

[list=1]
  [*]The examples just set mem_base and mem_size to the upper 4KB of RamLoc8, isn't it possible that the linker could put something there that the ROM drivers would clobber?
  [*]What's the 2KB of USB RAM at 0x20004000 used for? Is it used for endpoints only, or can I allocate memory for the drivers in there too?
[/list]
0 Kudos

768 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by neilt6 on Wed Jul 17 15:26:06 MST 2013

Quote: neilt6
I've just spent an enraging 2 full days trying to get a generic HID device to work properly on an LPC11U35 using the on-chip ROM drivers with LPCUSBLib... In that time I've encountered so many bugs, and glitches, and "things that make you go hmm", it's not even funny. Before I start ranting, I should mention I'm doing the same thing on an ATmega32U4 running LUFA (Which LPCUSBLib is based on), and it works just fine. I'll start from the beginning:

First I created a new workspace and imported the LPC11U14 USB examples. Compiled the GenericHID example unmodified, 14KB later, surprise it works, so I move on to enabling the ROM drivers. This is where the fun starts... The first thing I did was change device symbol on all the projects to __LPC11U2X_3X__, then I changed the MCU selection to LPC11U35/401, and finally changed USE_USB_ROM_STACK to 1, crossed my fingers, and hit Build. CRASH, BOOM, BANG, undefined reference to `Generic_HID_Interface'! Hmm... So I tried building the other examples, most of them failed, but the CDC example built ok. Turns out, Generic_HID_Interface has been declared "static"... So I fixed that, and now it builds and runs. Hooray I thought, progress! So I opened up HIDClient.exe, and starting spamming things. Sigh... The button report won't work... I scratched my head over this one for a while, and ended up comparing the example to the older one that came with nxpUSBlib. Turns out GenericReport, DeviceDescriptor, and ConfigurationDescriptor are supposed to be "const"... So I changed those in Descriptors.c, and UsbRom.c, rebuilt, and tried it again. This time everything seemed to work, or so I thought. This is where things start getting really weird... The ATmega32U4 I'm replacing is using 64 byte reports, so I changed GENERIC_EPSIZE, and GENERIC_REPORT_SIZE to 64 in Descriptors.h, and rebuilt. Windows no longer receives the product string! Instead, HIDClient.exe lists it as "Device 1". Both reports still work though, so I rebuilt it using the software drivers. Windows now recognizes the product string, but the LED report no longer works, or at least, not all the time... And that's when I flipped the table over (figuratively speaking of course), and came here for help.

So the question is, what exactly am I doing wrong? Why have I had to make so many changes to the example just to get it to run properly, and how do I fix this new issue?



It gets more interesting... I Just noticed that in the nxpUSBlib example, StringDescriptor was also "const", so I changed it in the LPCOpen example. Now the product string is received correctly, but the code hard faults as soon as it runs:

if (memcmp(&report, Generic_HID_Interface.Config.PrevReportINBuffer, Generic_HID_Interface.Config.PrevReportINBufferSize))


Interesting... So I dumped the "const" on StringDescriptor, and rebuilt with the whole "#if defined(USB_DEVICE_ROM_DRIVER)" block commented out of main. The product string now comes through...
0 Kudos