EmbeddedRelated.com
Forums
Memfault Beyond the Launch

LPC2xxx USB Writing data to endpoint

Started by Jan Thogersen December 11, 2006
Hi all,

I have tried the LPCUSB stack found on sourceforge and it works like a
charm! Only small changes had to be made for it to work on a LPC2368.

One thing troubles me a bit... How can I determine if an endpoint is
still filled with data that needs to be transferred? Because now if I
call USBHwEPWrite to often then the data in the endpoint's buffer gets
overwritten before the CPU has a chance of transmitting the data.

I have read the USB chapter of the manual in detail, however I didn't
find the solution to my problem.

What I'm trying to do is something like this:

while (EndPointStatus!=Empty); // Loop
USBHwEPWrite(....);

Thanks in advance!

Regards
Jan

An Engineer's Guide to the LPC2100 Series

Dnia 11-12-2006, pon o godzinie 17:59 +0100, Jan Thogersen napisał(a):
> Hi all,
>
> I have tried the LPCUSB stack found on sourceforge and it works like
> a
> charm! Only small changes had to be made for it to work on a LPC2368.
>
> One thing troubles me a bit... How can I determine if an endpoint is
> still filled with data that needs to be transferred? Because now if I
> call USBHwEPWrite to often then the data in the endpoint's buffer
> gets
> overwritten before the CPU has a chance of transmitting the data.
>
> I have read the USB chapter of the manual in detail, however I didn't
> find the solution to my problem.
>
> What I'm trying to do is something like this:
>
> while (EndPointStatus!=Empty); // Loop
> USBHwEPWrite(....);
>
Hmm, isn't EP interrupt for that?
And USBHwRegisterEPIntHandler for register function to handle it?

Albert
Albert Bartoszko wrote:
>
> Dnia 11-12-2006, pon o godzinie 17:59 +0100, Jan Thogersen napisał(a):
> > Hi all,
> >
> > I have tried the LPCUSB stack found on sourceforge and it works like
> > a
> > charm! Only small changes had to be made for it to work on a LPC2368.
> >
> > One thing troubles me a bit... How can I determine if an endpoint is
> > still filled with data that needs to be transferred? Because now if I
> > call USBHwEPWrite to often then the data in the endpoint's buffer
> > gets
> > overwritten before the CPU has a chance of transmitting the data.
> >
> > I have read the USB chapter of the manual in detail, however I didn't
> > find the solution to my problem.
> >
> > What I'm trying to do is something like this:
> >
> > while (EndPointStatus!=Empty); // Loop
> > USBHwEPWrite(....);
> >
> Hmm, isn't EP interrupt for that?
> And USBHwRegisterEPIntHandler for register function to handle it?
>
> Lets say that I have a button on my design. Each time the button gets
> pressed I want to send a USB package! So off cause before pushing data
> on the buffer, I want to know if the buffer is empty. Therefor I'm
> seeking a way of getting the buffer status. Maybe it's the wrong way
> I'm doing the implementation...
>
> Regards
> Jan
>
Jan Thogersen wrote:
[...]
>> Hmm, isn't EP interrupt for that?
>> And USBHwRegisterEPIntHandler for register function to handle it?
>>
>> Lets say that I have a button on my design. Each time the button gets
>> pressed I want to send a USB package! So off cause before pushing data
>> on the buffer, I want to know if the buffer is empty. Therefor I'm
>> seeking a way of getting the buffer status. Maybe it's the wrong way
>> I'm doing the implementation...

After write to EP buffer set global busy flag.
In Your EP IN handler clear the flag.

Next test flag before write

Albert
----------

Albert Bartoszko wrote:
>
> Dnia 11-12-2006, pon o godzinie 17:59 +0100, Jan Thogersen napisał(a):
> > Hi all,
> >
> > I have tried the LPCUSB stack found on sourceforge and it works like
> > a
> > charm! Only small changes had to be made for it to work on a LPC2368.
> >
> > One thing troubles me a bit... How can I determine if an endpoint is
> > still filled with data that needs to be transferred? Because now if I
> > call USBHwEPWrite to often then the data in the endpoint's buffer
> > gets
> > overwritten before the CPU has a chance of transmitting the data.
> >
> > I have read the USB chapter of the manual in detail, however I didn't
> > find the solution to my problem.
> >
> > What I'm trying to do is something like this:
> >
> > while (EndPointStatus!=Empty); // Loop
> > USBHwEPWrite(....);
> >
> Hmm, isn't EP interrupt for that?
> And USBHwRegisterEPIntHandler for register function to handle it?
>
> Lets say that I have a button on my design. Each time the button gets
> pressed I want to send a USB package! So off cause before pushing data
> on the buffer, I want to know if the buffer is empty. Therefor I'm
> seeking a way of getting the buffer status. Maybe it's the wrong way
> I'm doing the implementation...
>
> Regards
> Jan
>
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Jan Thogersen wrote:
> I have tried the LPCUSB stack found on sourceforge and it works like a
> charm! Only small changes had to be made for it to work on a LPC2368.

What changes did you have to make?

> One thing troubles me a bit... How can I determine if an endpoint is
> still filled with data that needs to be transferred? Because now if I
> call USBHwEPWrite to often then the data in the endpoint's buffer gets
> overwritten before the CPU has a chance of transmitting the data.
>
> I have read the USB chapter of the manual in detail, however I didn't
> find the solution to my problem.
>
> What I'm trying to do is something like this:
>
> while (EndPointStatus!=Empty); // Loop
> USBHwEPWrite(....);

USB is basically designed to always let the host (PC) take the
initiative to send or receive something. The device cannot send
anything unless the host is expecting to receive something, for
example.

It is quite easy to add a function to get the endpoint status from
the USB HW.
However, when using interrupts for USB, things can get tricky when
both the main task and the interrupt try to simultaneously access
the USB hardware. There is no protection against that in the stack.

The way that fits the USB model best (IMO) is to use handlers
that are called when there is some event on an endpoint. All access
to the actual USB hardware should be done from these handlers
(except things like HW initialisation, etc.). When using interrupts
to trigger the handlers, the interface between the main task and
the interrupt should be some kind of pre-emption safe mechanism,
like a FIFO or something else acting as a semaphore.

It is possible to configure the stack such that the handler is
also called when there was no actual transfer of data, but instead
the host sent a request to receive data that was NACKed by the
device. I think that in your case, you can use this mechanism
to let the endpoint handler "poll" a data buffer that is filled
by your button check routine. If it finds button data, it writes
it to the EP buffer. The handler knows that the buffer is empty
because the handler was either invoked because of successful
transmission of a packet from the EP buffer (ACK), or the handler
was invoked because the EP buffer was empty in the first place (NACK).

I hope this doesn't sound too complicated.

Kind regards,
Bertrik
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFFgEC7ETD6mlrWxPURAv9gAKCQokxeiLwMGgkMDGdoXSD86B9HxQCgvMRq
5969Ry/UCyq9nIKJSg/+sfU=7+Id
-----END PGP SIGNATURE-----
> Jan Thogersen wrote:
> > I have tried the LPCUSB stack found on sourceforge and it works like a
> > charm! Only small changes had to be made for it to work on a LPC2368.
>
> What changes did you have to make?
Of cause the routing of pins had to be changed. And to save power the
lpc23xx has no clock routed to the usb module at reset, so I had to
route the clock to get access to the registers in the module. Without
the clock I only get data access abort .

USBClkCtrl = USBClkCtrl_DEV_CLK_EN;
while (!( USBClkSt & USBClkSt_DEV_CLK_ON)); // Wait for USB clock to
come active

The LPC23xx also has errors in the USB module. The soft_connect and vbus
detection doesn't work. So I have to poll the vbus and set soft_connect
pins manually.

>
> > One thing troubles me a bit... How can I determine if an endpoint is
> > still filled with data that needs to be transferred? Because now if I
> > call USBHwEPWrite to often then the data in the endpoint's buffer gets
> > overwritten before the CPU has a chance of transmitting the data.
> >
> > I have read the USB chapter of the manual in detail, however I didn't
> > find the solution to my problem.
> >
> > What I'm trying to do is something like this:
> >
> > while (EndPointStatus!=Empty); // Loop
> > USBHwEPWrite(....);
>
> It is quite easy to add a function to get the endpoint status from
> the USB HW.
> However, when using interrupts for USB, things can get tricky when
> both the main task and the interrupt try to simultaneously access
> the USB hardware. There is no protection against that in the stack.
Okay, Please enlighten my in how to get the ep status. Because I can't
figure it out.

> The way that fits the USB model best (IMO) is to use handlers
> that are called when there is some event on an endpoint. All access
> to the actual USB hardware should be done from these handlers
> (except things like HW initialisation, etc.). When using interrupts
> to trigger the handlers, the interface between the main task and
> the interrupt should be some kind of pre-emption safe mechanism,
> like a FIFO or something else acting as a semaphore.
Yes. Your stack makes it very easy to make handlers for all the
different events on the bus, so of cause the most beautiful way of
implementing the usb communication is with the use of handlers. And
therefor I already did the communication this way, however I'm still
interested in knowing how it's possible to poll the ep status.

> It is possible to configure the stack such that the handler is
> also called when there was no actual transfer of data, but instead
> the host sent a request to receive data that was NACKed by the
> device. I think that in your case, you can use this mechanism
> to let the endpoint handler "poll" a data buffer that is filled
> by your button check routine. If it finds button data, it writes
> it to the EP buffer. The handler knows that the buffer is empty
> because the handler was either invoked because of successful
> transmission of a packet from the EP buffer (ACK), or the handler
> was invoked because the EP buffer was empty in the first place (NACK).
I hadn't figured out that this was possible to do, It sounds exactly as
what I need! I will try it out! Thanks a lot!
And thanks for the outstanding work you have done with the USBLPC stack!
Without you I think that most hobbyists would be in deep waters
regarding USB. IMO it's some of the most structured code I have seen...
Besides my own of cause :-)

> I hope this doesn't sound too complicated.
Not at all...

Regards
Jan
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Jan Thogersen wrote:
> > Jan Thogersen wrote:
> > > I have tried the LPCUSB stack found on sourceforge and it works like a
> > > charm! Only small changes had to be made for it to work on a LPC2368.
> >
> > What changes did you have to make?
> Of cause the routing of pins had to be changed. And to save power the
> lpc23xx has no clock routed to the usb module at reset, so I had to
> route the clock to get access to the registers in the module. Without
> the clock I only get data access abort .
>
> USBClkCtrl = USBClkCtrl_DEV_CLK_EN;
> while (!( USBClkSt & USBClkSt_DEV_CLK_ON)); // Wait for USB clock to
> come active
>
> The LPC23xx also has errors in the USB module. The soft_connect and vbus
> detection doesn't work. So I have to poll the vbus and set soft_connect
> pins manually.

Ok, thanks for the info.

> > > One thing troubles me a bit... How can I determine if an endpoint is
> > > still filled with data that needs to be transferred? Because now if I
> > > call USBHwEPWrite to often then the data in the endpoint's buffer gets
> > > overwritten before the CPU has a chance of transmitting the data.
> > >
> > > I have read the USB chapter of the manual in detail, however I didn't
> > > find the solution to my problem.
> > >
> > > What I'm trying to do is something like this:
> > >
> > > while (EndPointStatus!=Empty); // Loop
> > > USBHwEPWrite(....);
> >
> > It is quite easy to add a function to get the endpoint status from
> > the USB HW.
> > However, when using interrupts for USB, things can get tricky when
> > both the main task and the interrupt try to simultaneously access
> > the USB hardware. There is no protection against that in the stack.
> Okay, Please enlighten my in how to get the ep status. Because I can't
> figure it out.

I meant that it is easy to get the EP status from the USB hardware,
it's not something that can be done with the current lpcusb code.

It can be done by adding something like this to usbhw_lpc.c
U8 USBHwEPGetStatus(U8 bEP)
{
int idx = EP2IDX(bEP);

return USBHwCmdRead(CMD_EP_SELECT | idx);
}

This returns a byte where individual bits indicate specific status, like
EP_STATUS_DATA which means that the endpoint buffer is filled
EP_STATUS_STALLED means the endpoint is stalled
EP_STATUS_SETUP means the endpoint received a setup packet (EP 0 only)
EP_STATUS_ERROR means data was overwritten by setup packet
EP_STATUS_NACKED means that a NACK was sent to the host.

Initially I planned to use hardware independent status bit definitions,
so that's why there is some code in the USBHwISR function to convert
EPSTAT_xx (LPC214x specific) bits into EP_STATUS_xxx
(hardware-independent) bits, but that doesn't seem so important anymore.
Anyway, the two status bit definitions are currently identical.

Kind regards,
Bertrik
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFFgv2NETD6mlrWxPURAmTAAKC75tJOVDikTz94dA7PCORtTWZMcgCeLYaK
dU7AOxyR8h0SnnonF3FL6x8=Xjk8
-----END PGP SIGNATURE-----
Any chance of posting the files for the lpc23xx lpcusb port that was
done? maybe in the yahoo files area.

--- In l..., Bertrik Sikken wrote:
>
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Jan Thogersen wrote:
> > > Jan Thogersen wrote:
> > > > I have tried the LPCUSB stack found on sourceforge and it
works like a
> > > > charm! Only small changes had to be made for it to work on a
LPC2368.
> > >
> > > What changes did you have to make?
> > Of cause the routing of pins had to be changed. And to save power the
> > lpc23xx has no clock routed to the usb module at reset, so I had to
> > route the clock to get access to the registers in the module. Without
> > the clock I only get data access abort .
> >
> > USBClkCtrl = USBClkCtrl_DEV_CLK_EN;
> > while (!( USBClkSt & USBClkSt_DEV_CLK_ON)); // Wait for USB
clock to
> > come active
> >
> > The LPC23xx also has errors in the USB module. The soft_connect
and vbus
> > detection doesn't work. So I have to poll the vbus and set
soft_connect
> > pins manually.
>
> Ok, thanks for the info.
>
> > > > One thing troubles me a bit... How can I determine if an
endpoint is
> > > > still filled with data that needs to be transferred? Because
now if I
> > > > call USBHwEPWrite to often then the data in the endpoint's
buffer gets
> > > > overwritten before the CPU has a chance of transmitting the data.
> > > >
> > > > I have read the USB chapter of the manual in detail, however
I didn't
> > > > find the solution to my problem.
> > > >
> > > > What I'm trying to do is something like this:
> > > >
> > > > while (EndPointStatus!=Empty); // Loop
> > > > USBHwEPWrite(....);
> > >
> > > It is quite easy to add a function to get the endpoint status from
> > > the USB HW.
> > > However, when using interrupts for USB, things can get tricky when
> > > both the main task and the interrupt try to simultaneously access
> > > the USB hardware. There is no protection against that in the stack.
> > Okay, Please enlighten my in how to get the ep status. Because I
can't
> > figure it out.
>
> I meant that it is easy to get the EP status from the USB hardware,
> it's not something that can be done with the current lpcusb code.
>
> It can be done by adding something like this to usbhw_lpc.c
> U8 USBHwEPGetStatus(U8 bEP)
> {
> int idx = EP2IDX(bEP);
>
> return USBHwCmdRead(CMD_EP_SELECT | idx);
> }
>
> This returns a byte where individual bits indicate specific status, like
> EP_STATUS_DATA which means that the endpoint buffer is filled
> EP_STATUS_STALLED means the endpoint is stalled
> EP_STATUS_SETUP means the endpoint received a setup packet (EP 0 only)
> EP_STATUS_ERROR means data was overwritten by setup packet
> EP_STATUS_NACKED means that a NACK was sent to the host.
>
> Initially I planned to use hardware independent status bit definitions,
> so that's why there is some code in the USBHwISR function to convert
> EPSTAT_xx (LPC214x specific) bits into EP_STATUS_xxx
> (hardware-independent) bits, but that doesn't seem so important anymore.
> Anyway, the two status bit definitions are currently identical.
>
> Kind regards,
> Bertrik
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.2 (MingW32)
> Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
>
> iD8DBQFFgv2NETD6mlrWxPURAmTAAKC75tJOVDikTz94dA7PCORtTWZMcgCeLYaK
> dU7AOxyR8h0SnnonF3FL6x8> =Xjk8
> -----END PGP SIGNATURE-----
>

Memfault Beyond the Launch