cancel
Showing results for 
Search instead for 
Did you mean: 

Peripheral to memory DMA places data at bottom of buffer

solomonviveros
Associate II
Posted on October 21, 2013 at 20:07

I've DMA1 stream 3 channel 0 configured to handle the I2S2 data coming in from my UDA1380 codec and what I notice is that when configuring the Memory0BaseAddr to be the beginning of my circular buffer, the contents at the interrupt show the data being placed at the end of my buffer, moving toward the front[so in the case of four blocks, rather than placing the data at Block[0], I see the data being placed in Block[3], then decrementing to Block[2] the next interrupt]...I'm a little unclear as to what part of my code could be causing this...any insight would be much appreciated...

/* CODEC_I2S peripheral configuration */
SPI_I2S_DeInit(SPI2);
I2S_InitStructure.I2S_AudioFreq = AUDIO_FREQUENCY;
I2S_InitStructure.I2S_Standard = I2S_Standard_Phillips;
I2S_InitStructure.I2S_DataFormat = I2S_DataFormat_16b;
I2S_InitStructure.I2S_CPOL = I2S_CPOL_High;
I2S_InitStructure.I2S_Mode = I2S_Mode_SlaveRx;
I2S_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Disable;
I2S_Init(SPI2, &I2S_InitStructure);
I2S_Cmd(SPI2, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE); 
DMA_Cmd(DMA1_Stream3, DISABLE);
DMA_DeInit(DMA1_Stream3);
DMA_InitStruct.DMA_Channel = DMA_Channel_0; 
DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&(SPI2->DR); 
DMA_InitStruct.DMA_Memory0BaseAddr = (uint32_t)&Uda1380AdcAudio.Uda1380AdcBlock; 
DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralToMemory; 
DMA_InitStruct.DMA_BufferSize = DMA_TRANSFER_BLOCK_SIZE * 2; 
DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable; 
DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; 
DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; 
DMA_InitStruct.DMA_Mode = DMA_Mode_Normal; 
DMA_InitStruct.DMA_Priority = DMA_Priority_High; 
DMA_InitStruct.DMA_FIFOMode = DMA_FIFOMode_Disable; 
DMA_InitStruct.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull;
DMA_InitStruct.DMA_MemoryBurst = DMA_MemoryBurst_Single; 
DMA_InitStruct.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
while( DMA_GetCmdStatus( DMA1_Stream3 ) == ENABLE );
DMA_Init( DMA1_Stream3, &DMA_InitStruct );
DMA_ITConfig( DMA1_Stream3, DMA_IT_TC, ENABLE );
DMA_Cmd( DMA1_Stream3, ENABLE );
SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Rx, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

#dma #selective-cut-n-paste
4 REPLIES 4
Posted on October 21, 2013 at 20:41

Which interrupt, and where's the block definition?

The issue is not with the code presented. Have you filled the buffer with a known pattern and confirmed how the buffer fills, because it would be extremely odd of the DMA to fill backward.

Are you sure you don't have an Endian issue with the formatting of the data? Or the configuration of the Codec?
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
solomonviveros
Associate II
Posted on October 21, 2013 at 22:45

Here's my interrupt routine:

void DMA1_Stream3_IRQHandler(void)
{
static short unsigned int 
i = 0;
if(DMA_GetFlagStatus(DMA1_Stream3, DMA_FLAG_TCIF3) != RESET)
{ 
while (DMA_GetCmdStatus(DMA1_Stream3) != DISABLE)
{}
DMA_ClearFlag(DMA1_Stream3, DMA_FLAG_TCIF3); // Clear the Interrupt flag
DMA_InitStruct.DMA_Memory0BaseAddr = (uint32_t)&Uda1380AdcAudio.Uda1380AdcBlock[(SystemMaint.PcmInBufferingIndex + 1)% PCM_IN_BUFFER_BLOCKS];
DMA_Init(DMA1_Stream3, &DMA_InitStruct);//Configure the DMA Stream with the new parameters 
DMA_Cmd(DMA1_Stream3, ENABLE);// Enable the I2S DMA Stream
SystemMaint.PcmInDataIndex = SystemMaint.PcmInBufferingIndex;
for(i = 0; i < AUDIO_BLOCK_SIZE; i++)
AudioTransmitBuffer.Buffer[SystemMaint.PcmInDataIndex].Block[i] = Uda1380AdcAudio.Uda1380AdcBlock[SystemMaint.PcmInBufferingIndex].AdcSample[i].RxLeft; 
SystemMaint.PcmInBufferingIndex = (SystemMaint.PcmInBufferingIndex + 1)% PCM_IN_BUFFER_BLOCKS;
}
SystemMaint.DoTransmit = 1;
}

I've #pragma pack(1) before I define my structures that are as follows:

struct sUda1380AdcFrame
{ 
short int
RxLeft,
RxRight;
};
///////////////////////////////////////////////////////////////////////////////
struct sUda1380AdcSample
{
struct sUda1380AdcFrame
AdcSample[80];
};
///////////////////////////////////////////////////////////////////////////////
struct sUda1380AdcAudio
{
struct sUda1380AdcSample
Uda1380AdcBlock[5];
};

The data is coming from the codec to the STM32F4 and strangely enough I see after the first interrupt, data is placed at the last block[block 4 in this case]...if the dma configuration doesn't show any obvious goofs I'll continue debugging my code to see if I can't resolve the issue.
jpeacock2399
Associate II
Posted on October 22, 2013 at 01:01

Two things you might check:

DMA_InitStruct.DMA_Memory0BaseAddr = (uint32_t)&Uda1380AdcAudio.Uda1380AdcBlock[(SystemMaint.PcmInBufferingIndex + 1)% PCM_IN_BUFFER_BLOCKS];

Is your array packed? If not you may not be seeing the data where you expect it. And second, at the TC interrupt dump your DMA registers to see what it just did, especially the configuration. You may have errant code clobbering the DMA regs. Jack Peacock
Posted on October 22, 2013 at 01:12

DMA_TRANSFER_BLOCK_SIZE

is what? 400?
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..