cancel
Showing results for 
Search instead for 
Did you mean: 

STR91x USB driver with DMA

yarivl
Associate
Posted on August 13, 2008 at 07:23

STR91x USB driver with DMA

1 REPLY 1
yarivl
Associate
Posted on August 13, 2008 at 07:23

Hello,

I implemented a driver for the USB slave STR91x micro controller. It works fine without the use of DMAC.

I'm trying to integrate the DMA controller for bulk transfers. The final goal is to use both Linked and Unlinked modes, but for the moment I'm working in Unlinked mode.

I managed to config the DMA channel to transfer data from a supplied buffer to the Tx EP FIFO, but I can't seem to get an interrupt for the completion of the DMA transaction.

I see the correct data issued on the bus only if I use a delay after configuring the DMA channel registers and before setting the Tx Status to valid and setting the Rx Count to the transfer size. Otherwise, I receive the same data from the previous Tx xfer (i.e. - the status stage from last transaction). in both cases no DMA interrupt is asserted.

I use the following API to register my DMA handler:

VIC_Config(DMA_ITLine, VIC_IRQ, USB_IRQ_PRIORITY, dma_callback);

(USB_IRQ_PRIORITY is defined as 5, dma_callback is the DMA interrupt handler I expect to be called when Terminal Count / Error interrupts occur).

This is the same API I use to register USB interrupt handler to USBLP_ITLine, which works fine. For the DMA I get no interrupts.

I tried polling the DMA_ISR register for a channel as well as the DMA_TCISR and the DMA_EISR. There was no change in those registers. I even tried checking the raw status (without masking) with the same result.

All that leads me to think there is something I missed in the DMAC initialization.

This is the sequence I use:

SCU_MCLKSourceConfig(SCU_MCLK_OSC);

/* configure PLL factors for 48MHz */

SCU_PLLFactorsConfig(0xC0,0x19,0x3);

/* Enable PLL */

SCU_PLLCmd(ENABLE);

/* PLL as MCLK clock */

SCU_MCLKSourceConfig(SCU_MCLK_PLL);

/* Enable VIC clock */

SCU_AHBPeriphClockConfig(__VIC,ENABLE);

SCU_AHBPeriphReset(__VIC,DISABLE);

/* USB clock = MCLK= 48MHz */

SCU_USBCLKConfig(SCU_USBCLK_MCLK);

/* Enable USB clock */

SCU_AHBPeriphClockConfig(__USB,ENABLE);

SCU_AHBPeriphReset(__USB,DISABLE);

REG_WRITE(USB_CNTR, uint16_t, 0x0000);

REG_WRITE(USB_ISTR, uint16_t, 0x0000);

SCU_AHBPeriphClockConfig(__USB48M,ENABLE);

SCU_AHBPeriphClockConfig(__DMA, ENABLE);

SCU_AHBPeriphReset(__DMA,DISABLE);

SCU_APBPeriphClockConfig(__GPIO6,ENABLE);

SCU_APBPeriphReset(__GPIO6,DISABLE);

SCU_AHBPeriphIdleConfig(__DMA, ENABLE);

/* Configure GPIO6 */

GPIO_DeInit(GPIO6);

GPIO_StructInit(&GPIO_InitStructure);

GPIO_InitStructure.GPIO_Direction = GPIO_PinInput;

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4;

GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull ;

GPIO_Init(GPIO6, &GPIO_InitStructure);

GPIO_StructInit(&GPIO_InitStructure);

GPIO_InitStructure.GPIO_Direction = GPIO_PinOutput;

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6;

GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull ;

GPIO_InitStructure.GPIO_Alternate = GPIO_OutputAlt1;

GPIO_Init(GPIO6, &GPIO_InitStructure);

/* Enable and configure the priority of the USB_LP IRQ Channel */

VIC_DeInit();

VIC_Config(USBLP_ITLine, VIC_IRQ, 0, str_generic_isr);

VIC_ITCmd(USBLP_ITLine, ENABLE);

What am I doing wrong?

Can anyone specify the initialization needed to activate the DMAC?

Yariv.