Lately, I have been scratching my head to get the LPC2148 USB
device pass the USBCV test downloaded from "http://www.usb.org".
Using latest Keil's USB MSC sample, v1.04, the enumeration test
will fail from time to time, and program would spin in the
WrCmd() or WrCmdDat() routine forever.
While I was looking into the WrCmd(), WrCmdDat() and RdCmdDat()
routine and ISR carefully, Keil just found one problem that could
screw up the USB protocol engine.
In the USB device block, the registers are located in the VPB
clock domain, which requires minimum 18Mhz PCLK. in the original
MSC example, PCLK uses the default value 1/4 of CCLK = 15Mhz in
the startup.s. That has probably caused most of the intermitten
problems in these Wr/RdCmdDat() modules. The PCLK should be set
to >= 18Mhz.
I think that Keil will release a new version of these
example based on the fixes soon. I am just glad that I am
finally able to use the latest fixes to pass all the compliance
test. So, I pass around to those who had problems with the
LPC2148 USB driver:
Do the following steps:
(1) in startup.s, set:
VPBDIV_SETUP EQU 1
VPBDIV_Val EQU 0x00000001 ; PCLK is set to CCLK 60Mhz
(2) In usbhw.c, modify these modules, WrCmd(), WrCmdDat(),
and RdCmdDat() as below:
/*
* Write Command
* Parameters: cmd: Command
* Return Value: None
*/
void WrCmd (DWORD cmd) {
DEV_INT_CLR = CCEMTY_INT;
CMD_CODE = cmd;
while ((DEV_INT_STAT & CCEMTY_INT) == 0);
}
/*
* Write Command Data
* Parameters: cmd: Command
* val: Data
* Return Value: None
*/
void WrCmdDat (DWORD cmd, DWORD val) {
DEV_INT_CLR = CCEMTY_INT;
CMD_CODE = cmd;
while ((DEV_INT_STAT & CCEMTY_INT) == 0);
DEV_INT_CLR = CCEMTY_INT;
CMD_CODE = val;
while ((DEV_INT_STAT & CCEMTY_INT) == 0);
}
/*
* Read Command Data
* Parameters: cmd: Command
* Return Value: Data Value
*/
DWORD RdCmdDat (DWORD cmd) {
DEV_INT_CLR = CCEMTY_INT | CDFULL_INT;
CMD_CODE = cmd;
while ((DEV_INT_STAT & CDFULL_INT) == 0);
return (CMD_DATA);
}
(3) in usbhw.c, in the interrupt handler, USB_ISR(),
comment out "DEV_INT_CLR = CDFULL_INT;" as seen below:
...
EP_INT_CLR = 1 << n;
while ((DEV_INT_STAT & CDFULL_INT) == 0);
val = CMD_DATA;
// DEV_INT_CLR = CDFULL_INT;
if ((n & 1) == 0) { /* OUT Endpoint */
if (n == 0) { /* Control OUT Endpoint */
if (val & EP_SEL_STP) { /* Setup Packet */
if (USB_P_EP[0]) {
USB_P_EP[0](USB_EVT_SETUP);
continue;
}
}
}
That will probably address many intermitten problems seen in the
past. Meanwhile, we are working hard to improve our documentation
in the USB chapter.
Regards,
Tom
--- In lpc2000@yahoogroups.com, "gcopoix" <GCopoix@g...> wrote:
>
> Hi LPC group,
>
> I have an unnice problem regarding the LPC 214x USB communication:
>
> I've built a project based on the Keil MassStorage example.
> The only difference: I changed the descriptor to a non-class
device,
> setup 7in/7out pipes (I only use 2 BULK_IN and 1 BULK_OUT, needed
> this amount of declared pipes for descriptor compatibility
reasons).
> I've also added 1 timer interrupt, and 2 UART interrupts.
>
> 1 BULK_IN and 1 BULK_OUT are used as command bulk pipes which are
> used handshaked (means every command written is answered).
>
> In application level (non-interrupt driven, called by main loop) I
> check if I received some data e.g. over UART. The UART is buffered
by
> a ringbuffer (ISR -> ringbuffer) and the application sends the
> received data from ringbuffer->USB (calling USB_WriteEP()).
>
> Now the problem: This works OK for several hours, but then mostly
in
> WrCmd() after writing CMD_CODE the while-loop waiting for
CCEMTY_INT Show quoted textHide quoted text
> doesn't leave, resulting in a hanging USB communication.
>
> I've seen a hanging situation also in the USB ISR after setting
> EP_INT_CLR and waiting for CDFULL_INT.
>
> I tried to disable the USB interrupt while calling USB_WriteEP() -
> same result (may be a bit better, but can't say exactly).
> I also tried to send only within an USB interrupt (SOF irq), same
> result too.
>
> So my questions:
> - Does anybody else have this problem ?
> - What can be the reason for a non-accepted CMD_CODE or a
> non-accepted write to EP_INT_CLR ?
> - What to I need to take care of before calling USB_WriteEP() ?
> - Is it forbidden to send by application level ?
> - Is there a patch for the Keil USB stack ?
> - Is there some errata about this ?
> - What can I do to prevent this or what to resolve this situation ?
>
> Thank you for your help
>
> Gregor
>