EmbeddedRelated.com
Forums

DMA update (works partly)

Started by oliverks1 August 15, 2006
This is a follow up to a message on DMA transfers on the LPC2148 I
wrote last month. Someone suggested trying the Keil example for the
usb audio. As this was tailored for the Keil eval board, I bought the
board and JTAG emulator to try their example.

First of all Keil is loaded with bugs. It took me a day to get any
example to build and run on their evaluation board, but eventually I
got that sorted out. I did try emailing Keil support but never got a
response. So I can't say I am overwhelmed.

The good news is I did get DMA working in their example. This got me
excited. They use a single isochronous end point to push data from
the "PC" to the eval board. I should note that my Windows XP SP2 did
not seem to contain the necessary driver, but it did work fine on my
Mac. The driver issue may not be a Keil issue, but my XP machine is
pretty stock.

I then found I could get my code to work in ISO mode as well doing DMA
transfers. In fact even when an EP is not realized, the DMA engine
tries to request DMA servicing. However, I can not get DMA to work
with Bulk end points automatically. What I can do, is enable a Bulk
end point in slave mode, and then mark the USBDMARSet register every
time I get an interrupt on the requested EP.

My guess is there are bugs in the Silicon right now. I have emailed
Tech support at Philips and they suggested the Keil example as well.
If anyone gets it working completely for bulk EPs let me know, but for
right now, I think the feature is more vaporware than real.

Oliver

An Engineer's Guide to the LPC2100 Series

--- In l..., "oliverks1" wrote:
>
> I then found I could get my code to work in ISO mode as well doing DMA
> transfers. In fact even when an EP is not realized, the DMA engine
> tries to request DMA servicing. However, I can not get DMA to work
> with Bulk end points automatically. What I can do, is enable a Bulk
> end point in slave mode, and then mark the USBDMARSet register every
> time I get an interrupt on the requested EP.

As I was trying to get a working DMA for USB on a 2148 myself and had
the same symptoms, your post gave me the idea to play with USBDMARSet.
After setting up the DDs, clearing the corresponding USBEpIntEn bit
and setting the USBEpDMAEn bit, I tried to add a set of the bit in
USBDMARSet. With that combination, the DMA fills my bulk IN endpoint
as expected! I had no need to trigger it in the ISR.

Thanks for the idea!
Jean-Marc
> As I was trying to get a working DMA for USB on a 2148 myself and had
> the same symptoms, your post gave me the idea to play with USBDMARSet.
> After setting up the DDs, clearing the corresponding USBEpIntEn bit
> and setting the USBEpDMAEn bit, I tried to add a set of the bit in
> USBDMARSet. With that combination, the DMA fills my bulk IN endpoint
> as expected! I had no need to trigger it in the ISR.
>
> Thanks for the idea!
>

Jean-Marc,

I am pretty sure I tried that combination, so assuming you can read
more than one packet length, their must be another pre-condition that
you have that I don't.

Oliver
Following is the reason Jean-Marc's solution works- in plain "black
and white".

>From page 216 of the current LPC2148 manual (which should be on page
215 in section 14.8.13)

"The DMA Request Set register is normally used for the test purpose.
It is also useful in the normal operation mode to avoid a "lock"
situation if the DMA is programmed after that the USB packets are
already received. Normally the arrival of a packet generates an
interrupt when it is completely received. This interrupt is used by
the DMA to start working. This works fine as long as the DMA is
programmed before the arrival of the packet (2 packets - if double
buffered). If the DMA is programmed "too late", the interrupts were
already generated in slave mode (but not handled because the
intention was to use the DMA) and when the DMA is programmed no
interrupts are generated to "activate" it. In this case the usage of
the DMA Request Set register is useful to manually start the DMA
transfer."

John Heenan

--- In l..., "oliverks1" wrote:
> > As I was trying to get a working DMA for USB on a 2148 myself and
had
> > the same symptoms, your post gave me the idea to play with
USBDMARSet.
> > After setting up the DDs, clearing the corresponding USBEpIntEn
bit
> > and setting the USBEpDMAEn bit, I tried to add a set of the bit in
> > USBDMARSet. With that combination, the DMA fills my bulk IN
endpoint
> > as expected! I had no need to trigger it in the ISR.
> >
> > Thanks for the idea!
> >
>
> Jean-Marc,
>
> I am pretty sure I tried that combination, so assuming you can read
> more than one packet length, their must be another pre-condition
that
> you have that I don't.
>
> Oliver
>
--- In l..., "oliverks1" wrote:
> > As I was trying to get a working DMA for USB on a 2148 myself
and had
> > the same symptoms, your post gave me the idea to play with
USBDMARSet.
> > After setting up the DDs, clearing the corresponding USBEpIntEn
bit
> > and setting the USBEpDMAEn bit, I tried to add a set of the bit
in
> > USBDMARSet. With that combination, the DMA fills my bulk IN
endpoint
>
> I am pretty sure I tried that combination, so assuming you can
read
> more than one packet length, their must be another pre-condition
that
> you have that I don't.

Here is a part of the function I use to trigger the transfer:
"
typedef u_long dma_dd_bulk_t[USBDMA_SIZEOF32DD_BULK];
struct dma_ram_s {
u_long* ep_dd[32];
dma_dd_bulk_t dd_bulk[];
};

[...]
int ep_lpcindex = ENDPOINT_LOGICAL2LPCINDEX( logical_endpoint );
LpcUSBEpIntClr = 1< LpcUSBEpIntEn &= ~(1< struct dma_ram_s* dma_ram = (struct dma_ram_s*)USB_DMA_RAM_START;
dma_ram->ep_dd[ep_lpcindex] = (u_long*)&dma_ram->dd_bulk[0];
[Filling the DDs required to transfer 2KB through a IN bulk
endpoint, resulting in 32 packets]
LpcUSBEpDMAEn = 1< LpcUSBDMARSet = 1< "
I'm using an endpoint serviced in slave mode, which receives
commands and triggers the emission (IN endpoint) of a buffer through
another endpoint, which is serviced by DMA.

The initialization isn't DMA related...

I'm pretty relieved, because it seems that the transfer speed is now
limited by libusb on the host side, and not anymore by the CPU seed
of LPC itself, like it was in slave mode...

Hope this helps,

Jean-Marc
--- In l..., "John Heenan" wrote:
>
> Following is the reason Jean-Marc's solution works- in plain "black
> and white".
>
> From page 216 of the current LPC2148 manual (which should be on page
> 215 in section 14.8.13)
>
> "The DMA Request Set register is normally used for the test purpose.
> It is also useful in the normal operation mode to avoid a "lock"
> situation if the DMA is programmed after that the USB packets are
> already received. Normally the arrival of a packet generates an

In my application, I send an OUT packet on endpoint 2 to initiate an
action, set-up the DMA transfer on IN endpoint 5 and send a short
reply in slave mode on endpoint 2. The application on the PC will only
perform a read on endpoint 5 if it received a response on endpoint 2.
So, the DMA has already been set-up at the point the first IN packet
on endpoint 5 is sent to the LPC! If I don't trigger the DMA
'manually', my LPC doesn't send any packet on endpoint 5!

It's true that during the initialization, I set-up the endpoint 5 in
slave mode, but it gets never used in this mode...
Jean-Marc
Jean-Marc,

I now have DMA working, but interestingly there does appear to be
another precondition, that you must have satisfied in your test run.

This is the procedure I use to get DMA working.

I setup the IN EP to be a regular endpoint. Then as soon as I get an
interrupt requesting data, I switch the Slave to DMA mode (as you did
in your snippet below) and set the USBDMARSet to start the transfer.

It then parses the DDs correctly moving as much data as you have
chained in the descriptors.

I think that in the time you were setting up your descriptors a
request must have arrived, hence priming the system. I am now
sustaining close to 1.2MB/s which is pretty good.

Oliver
> Here is a part of the function I use to trigger the transfer:
> "
> typedef u_long dma_dd_bulk_t[USBDMA_SIZEOF32DD_BULK];
> struct dma_ram_s {
> u_long* ep_dd[32];
> dma_dd_bulk_t dd_bulk[];
> };
>
> [...]
> int ep_lpcindex = ENDPOINT_LOGICAL2LPCINDEX( logical_endpoint );
> LpcUSBEpIntClr = 1< > LpcUSBEpIntEn &= ~(1< > struct dma_ram_s* dma_ram = (struct dma_ram_s*)USB_DMA_RAM_START;
> dma_ram->ep_dd[ep_lpcindex] = (u_long*)&dma_ram->dd_bulk[0];
> [Filling the DDs required to transfer 2KB through a IN bulk
> endpoint, resulting in 32 packets]
> LpcUSBEpDMAEn = 1< > LpcUSBDMARSet = 1< > "
> I'm using an endpoint serviced in slave mode, which receives
> commands and triggers the emission (IN endpoint) of a buffer through
> another endpoint, which is serviced by DMA.
>
> The initialization isn't DMA related...
>
> I'm pretty relieved, because it seems that the transfer speed is now
> limited by libusb on the host side, and not anymore by the CPU seed
> of LPC itself, like it was in slave mode...
>
> Hope this helps,
>
> Jean-Marc
>
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi Oliver,

I'm working on an open-source USB stack for the LPC2148 [1].
Currently this stack only support slave mode.
Eventually, I'd like to have DMA support in it, but without
disturbing the current slave mode code too much.

Would you like to help me getting DMA support in it?

Do you have any essential information on DMA that is not
in the user manual?

The user manual mentions double buffering in relation to
DMA, but this is not really explained any further. My guess
is that this means that for one endpoint two DMA descriptors
are set up to point to each other. Do you know more about this?

Kind regards,
Bertrik Sikken

[1] http://sourceforge.net/projects/lpcusb

oliverks1 wrote:
> This is a follow up to a message on DMA transfers on the LPC2148 I
> wrote last month. Someone suggested trying the Keil example for the
> usb audio. As this was tailored for the Keil eval board, I bought the
> board and JTAG emulator to try their example.
>
> First of all Keil is loaded with bugs. It took me a day to get any
> example to build and run on their evaluation board, but eventually I
> got that sorted out. I did try emailing Keil support but never got a
> response. So I can't say I am overwhelmed.
>
> The good news is I did get DMA working in their example. This got me
> excited. They use a single isochronous end point to push data from
> the "PC" to the eval board. I should note that my Windows XP SP2 did
> not seem to contain the necessary driver, but it did work fine on my
> Mac. The driver issue may not be a Keil issue, but my XP machine is
> pretty stock.
>
> I then found I could get my code to work in ISO mode as well doing DMA
> transfers. In fact even when an EP is not realized, the DMA engine
> tries to request DMA servicing. However, I can not get DMA to work
> with Bulk end points automatically. What I can do, is enable a Bulk
> end point in slave mode, and then mark the USBDMARSet register every
> time I get an interrupt on the requested EP.
>
> My guess is there are bugs in the Silicon right now. I have emailed
> Tech support at Philips and they suggested the Keil example as well.
> If anyone gets it working completely for bulk EPs let me know, but for
> right now, I think the feature is more vaporware than real.
>
> Oliver
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFE8AEdETD6mlrWxPURAtDhAJ95tk3HvIaryo40avDZQlajLGWJMQCgh2bq
dyZSono5NVdlrV9dJCDylYcUd
-----END PGP SIGNATURE-----
Bentrik,

I am sorry in the delay in responding but i have been busy with other
issues. Yes I can help. I will email you separately so let me know
if you don't get the email.

Oliver

--- In l..., Bertrik Sikken wrote:
>
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Hi Oliver,
>
> I'm working on an open-source USB stack for the LPC2148 [1].
> Currently this stack only support slave mode.
> Eventually, I'd like to have DMA support in it, but without
> disturbing the current slave mode code too much.
>
> Would you like to help me getting DMA support in it?
>
> Do you have any essential information on DMA that is not
> in the user manual?
>
> The user manual mentions double buffering in relation to
> DMA, but this is not really explained any further. My guess
> is that this means that for one endpoint two DMA descriptors
> are set up to point to each other. Do you know more about this?
>
> Kind regards,
> Bertrik Sikken
>
> [1] http://sourceforge.net/projects/lpcusb
>
> oliverks1 wrote:
> > This is a follow up to a message on DMA transfers on the LPC2148 I
> > wrote last month. Someone suggested trying the Keil example for the
> > usb audio. As this was tailored for the Keil eval board, I bought the
> > board and JTAG emulator to try their example.
> >
> > First of all Keil is loaded with bugs. It took me a day to get any
> > example to build and run on their evaluation board, but eventually I
> > got that sorted out. I did try emailing Keil support but never got a
> > response. So I can't say I am overwhelmed.
> >
> > The good news is I did get DMA working in their example. This got me
> > excited. They use a single isochronous end point to push data from
> > the "PC" to the eval board. I should note that my Windows XP SP2 did
> > not seem to contain the necessary driver, but it did work fine on my
> > Mac. The driver issue may not be a Keil issue, but my XP machine is
> > pretty stock.
> >
> > I then found I could get my code to work in ISO mode as well doing DMA
> > transfers. In fact even when an EP is not realized, the DMA engine
> > tries to request DMA servicing. However, I can not get DMA to work
> > with Bulk end points automatically. What I can do, is enable a Bulk
> > end point in slave mode, and then mark the USBDMARSet register every
> > time I get an interrupt on the requested EP.
> >
> > My guess is there are bugs in the Silicon right now. I have emailed
> > Tech support at Philips and they suggested the Keil example as well.
> > If anyone gets it working completely for bulk EPs let me know, but for
> > right now, I think the feature is more vaporware than real.
> >
> > Oliver
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.2 (MingW32)
> Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
>
> iD8DBQFE8AEdETD6mlrWxPURAtDhAJ95tk3HvIaryo40avDZQlajLGWJMQCgh2bq
> dyZSono5NVdlrV9dJCDylYc> Ud
> -----END PGP SIGNATURE-----
>