Hi,
I'm using uVision 4 with the MCB2300 development board. I'm developing a software that periodically transmits data (status information) from the device to the host (as first step, the data are sent without being explicitly requested by the host as soon as a connection has been established). Thereto I've modified the USBCDC example included with uVision. The software transmits 20 bytes periodically, using USB_WriteEP (in usbhw.c, which uses the register interface). This works fine so far. Now I would like to use the DMA engine to avoid copying the bytes word by word into the register. I've enabled DMA in the USB configuration for logical IN endpoint 2 (physical endpoint 5 which is called CDC_DEP_IN in the example), and I have managed to set up DMA descriptors. But how do I trigger a DMA transfer? I've tried several combinations of USB_DMA_Setup and USB_DMA_Enable. Manually setting the appropriate bit in DMA_REQ_SET to trigger the interrupt results in an error state. What am I doing wrong? Could anyone please give me some hints concerning USB DMA? Thanks a lot. I'll be back in January, after my Christmas vacation. I wish everybody a merry Christmas and a happy new year!
CC
sorry, I forgot to mention that I'm using a LPC2378.
To start transfer on a new DD for an IN endpoint, Enable DMA (USBEpDMAEn) and write to USBDMARSet register manually, to arm the endpoint buffer with the DD.
It was once discussed on this thread of LPC2000 tech.groups.yahoo.com/.../49934
Tsuneo
same problem here. Tsuneo could you give me some further steps???
I'v installed a separate function where I init a new dma packet transfer, if a packet is there to tx.
void SendDataToHost() { USB_DMA_DESCRIPTOR DD; DD.BufAdr = (unsigned int)DataBuf + DataIn; /* DMA Buffer Address */ DD.BufLen = 300; /* DMA Packet-size */ DD.MaxSize = 64; /* 64Byte for bulk-transfer */ DD.Cfg.Val = 0; /* Initial DMA Configuration */ USB_DMA_Setup (CDC_DEP_IN, &DD); /* Setup DMA */ USB_DMA_Enable(CDC_DEP_IN); /* Enable DMA */ LPC_USB->USBDMARSet |= 0x20; }
After that the host sends a pkt to the endpoint(CDC_DEP_IN).
void USB_EndPoint2 (unsigned int event) { if(event & USB_EVT_IN_DMA_EOT) { //??? what do I have to do here?? } if (event & (USB_EVT_IN_DMA_EOT) | (USB_EVT_IN_DMA_NDR)) { /* End of Transfer or New Descriptor Request */ DD.BufAdr = (unsigned int)DataBuf + DataIn; /* DMA Buffer Address */ DD.BufLen = 300; /* DMA Packet-size */ DD.MaxSize = 64; /* 64Byte for bulk-transfer */ DD.Cfg.Val = 0; /* Initial DMA Configuration */ USB_DMA_Setup (CDC_DEP_IN, &DD); /* Setup DMA */ USB_DMA_Enable(CDC_DEP_IN); /* Enable DMA */ LPC_USB->USBDMARSet |= 0x20; } }
This method will be called only once. But no data will be transfered to the host... :-(
Any help would be very appreciated!
Ola
Your code seems fine.
Did you set up usbcfg.h for the DMA Endpoint (USB_DMA_EP) ? USB_DMA_EP value is used to disable slave interrupt on the EP (EP_INT_EN) in USB_Reset() (usbhw.c) While slave interrupt is enabled on the EP (default), DMA doesn't fire.
Maybe, this line is fine LPC_USB->USBDMARSet |= 0x20;
But, in Keil style, DMA_REQ_SET = 1 << EPAdr(CDC_DEP_IN);
Hi Tsuneo,
yes I did the set up in the usbcfg.h file for the second endpoint(in/out).
#define USB_DMA_EP 0x00000030 LPC_USB->USBEpDMAEn = USB_DMA_EP;
Using LPC_USB->USBDMARSet = 1 << EPAdr(CDC_DEP_IN); didn't solve the problem. After calling the method SendDataToHost(), the endpoint(in) will be executed only once.
One further question: is it enough to set up the dma in the SendDataToHost() metho for each packet which has to be send to the host? Or did I also specify the dma setup in the endpoint ISR (as shown in the code above)? Or do I have to send a ZLP packet each time the endpoint isr will be called (with packet-size zero)?
I've not to deal with ZLP and so on - the dma will everything do for me?
here's the whole code from the usb_reset() - I didn't change anyhting in this function...
void USB_Reset (void) { #if USB_DMA uint32_t n; #endif LPC_USB->USBEpInd = 0; LPC_USB->USBMaxPSize = USB_MAX_PACKET0; LPC_USB->USBEpInd = 1; LPC_USB->USBMaxPSize = USB_MAX_PACKET0; while ((LPC_USB->USBDevIntSt & EP_RLZED_INT) == 0); LPC_USB->USBEpIntClr = 0xFFFFFFFF; LPC_USB->USBEpIntEn = 0xFFFFFFFF ^ USB_DMA_EP; LPC_USB->USBDevIntClr = 0xFFFFFFFF; LPC_USB->USBDevIntEn = DEV_STAT_INT | EP_SLOW_INT | (USB_SOF_EVENT ? FRAME_INT : 0) | (USB_ERROR_EVENT ? ERR_INT : 0); #if USB_DMA LPC_USB->USBUDCAH = USB_RAM_ADR; LPC_USB->USBDMARClr = 0xFFFFFFFF; LPC_USB->USBEpDMADis = 0xFFFFFFFF; LPC_USB->USBEpDMAEn = USB_DMA_EP; LPC_USB->USBEoTIntClr = 0xFFFFFFFF; LPC_USB->USBNDDRIntClr = 0xFFFFFFFF; LPC_USB->USBSysErrIntClr = 0xFFFFFFFF; LPC_USB->USBDMAIntEn = 0x00000007; DDMemMap[0] = 0x00000000; DDMemMap[1] = 0x00000000; for (n = 0; n < USB_EP_NUM; n++) { udca[n] = 0; UDCA[n] = 0; } #endif }
The interrupt which occured after setting up the dma descriptor in the SendDataToHost method, is a "New DD Request Interrupt"... but after that nothing happens.
if (LPC_USB->USBDMAIntSt & 0x00000002) { /* New DD Request Interrupt */ { }
I hope you could give me some hints to get in working...
View all questions in Keil forum