Cannot set DMA transfersize

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Cannot set DMA transfersize

286 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by khorght on Mon Dec 02 11:53:50 MST 2013
Hello.

MCU - LPC2364
IDE - IAR 6.50.3
All seems fine,but... in debugger i see corretly set burst, src/dst, etc bits but transfersize field is always stays zero even if just write 0x01 to Control register for test purposes.
Tryed to enable DMA first, tryed to enable channel first, tryed to force channel configuration  register to zero for mem-to-mem transfer but transfersize can't be set.the strangest thing is that transfer occures one time, i see execution of the handler where TC status flag resets and TCCount variable increments by 1.  Here's the part of the code ( uses my own library - fully working with all other periphery, except DMA)
DMA_DeInit(DMACC1);
DMA_InitTypeDef DMA_InitStruct;
DMA_InitStruct.DMA_TransferSize = (uint16_t)((0x1000 / 4) & 0x0FFF); /* 0x1000 is DMA_SIZE */
DMA_InitStruct.DMA_SrcBaseAddr = 0x7FD00000;
DMA_InitStruct.DMA_DestBaseAddr = 0x7FD01000;
DMA_InitStruct.DMA_Flow = DMA_Flow_MemToMem_DMA;
DMA_InitStruct.DMA_SrcBurst = DMA_BurstSize32;
DMA_InitStruct.DMA_DestBurst = DMA_BurstSize32;
DMA_InitStruct.DMA_SrcDataSize = DMA_TransferWidth32bits;
DMA_InitStruct.DMA_DestDataSize = DMA_TransferWidth32bits;
DMA_InitStruct.DMA_SrcInc = DMA_InrementAddr;
DMA_InitStruct.DMA_DestInc = DMA_InrementAddr;
DMA_InitStruct.DMA_Protection = DMA_Protection_Default;
DMA_InitStruct.DMA_TerminalCountInt = DMA_TerminalCountIntEnable;
uint32_t i;
uint32_t *src_addr, *dest_addr;
src_addr = (uint32_t *)0x7FD00000;
dest_addr = (uint32_t *)0x7FD01000;
for ( i = 0; i < 0x1000 / 4; i ++ )
{
*src_addr = i;
*dest_addr = 0;
src_addr++;
dest_addr++;
}
/* Enable DMA */
DMA_Init(DMACC1, &DMA_InitStruct);
DMA_Endiannes(DMA_LittleEndian);
DMA_Cmd(ENABLE);
DMA_ChannelCmd(DMACC1, ENABLE);
...
...
...

void DMA_Init(DMACC_TypeDef *DMACCx, DMA_InitTypeDef* DMA_InitStruct)
{
/* Clear Any pending interrupts */
if (DMACCx == DMACC0)
{
DMAC->INTTCCLEAR = DMA_Channel0;
DMAC->INTERRCLR = DMA_Channel0;
}
else if (DMACCx == DMACC1)
{
DMAC->INTTCCLEAR = DMA_Channel1;
DMAC->INTERRCLR = DMA_Channel1;
}
/* Configure DMA Channel */
DMACCx->SRCADDR = DMA_InitStruct->DMA_SrcBaseAddr;
DMACCx->DESTADDR = DMA_InitStruct->DMA_DestBaseAddr;
/* Write the address of the next Linked List Item (LLI), or 0 if transfer - single packet */
DMACC0->LLI = 0;//DMA_LLI;
/* Flow Control */
DMACCx->CONTROL |= (((0x40 & 0xFFF) << 0));
DMACCx->CONFIGURATION |= DMA_InitStruct->DMA_Flow;
DMACCx->CONTROL = (((DMA_InitStruct->DMA_TransferSize & 0xFFF) << 0))
| (DMA_InitStruct->DMA_SrcBurst << 12)
| (DMA_InitStruct->DMA_DestBurst << 15)
| (DMA_InitStruct->DMA_SrcDataSize << 18)
| (DMA_InitStruct->DMA_DestDataSize << 21)
| (DMA_InitStruct->DMA_SrcInc << 26) //Source increment(src addr will be incremented after each transfer)
| (DMA_InitStruct->DMA_DestInc << 27) //Destination increment(dst addr will be incremented after each transfer)
| DMA_InitStruct->DMA_Protection /* Set DMA Channel Protection */
| DMA_InitStruct->DMA_TerminalCountInt;
}


what am i doing wrong?thanx.
Labels (1)
0 Kudos
1 Reply

255 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by triffid_hunter on Sun Dec 15 19:49:45 MST 2013
TransferSize is a magic dual-purpose register, like SSP->DR - that is, it performs a different function when written or read.

When written, it stores the TransferSize value in the DMA engine *somewhere*.

When read, it returns the number of transfers remaining for the active or halted channel.

As a result, it will always read zero after being written, but before the channel has begun transferring.

You should be extremely careful of read-modify-write operations on this register. TransferSize should be updated last.


I just went through this confusion myself :)
0 Kudos