Question
I2S DMA Problems
Posted on May 28, 2013 at 10:31
Hi guys,
I'm in a bit of a crisis to get I2S working with DMA. I want to transfer Data from a TxBuffer array to the SPI3->DR Peripheral My setup is:- I2S3 Interface
- DMA Dir Mem2Peripheral
- DMA Interrupt on DMA_IT_TC
- DMA in Double Buffered Mode
- No Fifo
The Problem is, that the Interrupt is never called, so I guess the DMA isn't working and the DMACounter isn'T counting to zero (so no interrupt is called can be called)
Here is my Code: Defines:#define Audio_DMA_I2S3_Stream DMA1_Stream5
#define Audio_DMA_I2S3ext_Stream DMA1_Stream2
#define Audio_DMA_I2S3_Channel DMA_Channel_0
#define Audio_DMA_I2S3ext_Channel DMA_Channel_2
#define Audio_DMA_I2S3_IRQ DMA1_Stream5_IRQn
#define Audio_DMA_I2S3ext_IRQ DMA1_Stream2_IRQn
Initialization:
GPIO_Configuration();
I2S_Configuration();
DMA_Configuration();
GPIO_Coinfiguration:
GPIO_InitTypeDef GPIO_InitStructure;
// Enable peripheral clocks
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOC, ENABLE); // TODO: fix, enable alternate function clock
// Configure alternative functions for I2S3 pins
GPIO_PinAFConfig(GPIOA, GPIO_PinSource15, GPIO_AF_SPI3); // I2S3_WS
GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_SPI3); // I2S3_MCK
GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_SPI3); // I2S3_CK
GPIO_PinAFConfig(GPIOC, GPIO_PinSource11, GPIO_AF_SPI3); // I2S3_ext_SD
GPIO_PinAFConfig(GPIOC, GPIO_PinSource12, GPIO_AF_SPI3); // I2S3_SD
//GPIO_PinAFConfig(GPIOC, GPIO_PinSource9, GPIO_AF_SPI3); /* I2S_CKIN - needed?? */
// Configure pins as alternate function
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; // TODO: fix
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12;
GPIO_Init(GPIOC, &GPIO_InitStructure);
I2S_Configuration:
I2S_InitTypeDef I2S_InitStructure;
// Enable SPI3/I2S3
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE);
// I2S3 peripheral configuration
SPI_I2S_DeInit(SPI3);
I2S_InitStructure.I2S_Standard = I2S_Standard_Phillips;
I2S_InitStructure.I2S_DataFormat = I2S_DataFormat_16b;
I2S_InitStructure.I2S_AudioFreq = I2S_AudioFreq_8k;
I2S_InitStructure.I2S_CPOL = I2S_CPOL_Low;
I2S_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Enable;
I2S_InitStructure.I2S_Mode = I2S_Mode_MasterTx;
I2S_Init(SPI3, &I2S_InitStructure);
I2S_FullDuplexConfig(I2S3ext, &I2S_InitStructure);
// Hook up I2S3 to DMA buffers
SPI_I2S_DMACmd(SPI3, SPI_I2S_DMAReq_Tx, ENABLE);
SPI_I2S_DMACmd(I2S3ext, SPI_I2S_DMAReq_Rx, ENABLE);
DMA_Configuration:
DMA_InitTypeDef DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
// Enable DMA
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
// Common initialization
DMA_InitStructure.DMA_BufferSize = AUDIO_BUFFER_SIZE;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
/* DMA configuration for input & output if I2S data. Configure each DMA channel to use double-buffered mode
* in circular mode. This allows the software codec read/write operation form the one memory while the DMA
* is reading/writing to the other memory. */
// I2S3 - DMA configuration for sending data to the codec/speaker
DMA_Cmd(Audio_DMA_I2S3_Stream, DISABLE);
DMA_DeInit(Audio_DMA_I2S3_Stream);
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_InitStructure.DMA_Channel = Audio_DMA_I2S3_Channel;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) &SPI3->DR; // SPI data register for sending
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t) &audio_Tx_Buffer[AUDIO_BUFFER_0][0];
DMA_DoubleBufferModeConfig(Audio_DMA_I2S3_Stream, (uint32_t) &audio_Tx_Buffer[AUDIO_BUFFER_1][0], DMA_Memory_0);
DMA_DoubleBufferModeCmd(Audio_DMA_I2S3_Stream, ENABLE);
DMA_Init(Audio_DMA_I2S3_Stream, &DMA_InitStructure);
// I2S3ext - DMA configuration for reading data from the codec/microphone
DMA_Cmd(Audio_DMA_I2S3ext_Stream, DISABLE);
DMA_DeInit(Audio_DMA_I2S3ext_Stream);
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_Channel = Audio_DMA_I2S3ext_Channel;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) &I2S3ext->DR;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t) &audio_Rx_Buffer[AUDIO_BUFFER_0][0];
DMA_DoubleBufferModeConfig(Audio_DMA_I2S3ext_Stream, (uint32_t) &audio_Rx_Buffer[AUDIO_BUFFER_1][0], DMA_Memory_0);
DMA_DoubleBufferModeCmd(Audio_DMA_I2S3ext_Stream, ENABLE);
DMA_Init(Audio_DMA_I2S3ext_Stream, &DMA_InitStructure);
// NVIC: Configure the DMA interrupt priority
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3);
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
// DMA interrupt for sending data to speaker
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannel = Audio_DMA_I2S3_IRQ;
NVIC_Init(&NVIC_InitStructure);
// DMA interrupt for reading data from microphone
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannel = Audio_DMA_I2S3ext_IRQ;
NVIC_Init(&NVIC_InitStructure);
ISR: (It is never called)
extern ''C'' void DMA1_Stream5_IRQHandler(void) {
uint32_t memory = DMA_GetCurrentMemoryTarget(Audio_DMA_I2S3_Stream);
DMA_ClearITPendingBit(Audio_DMA_I2S3_Stream, DMA_FLAG_TCIF5);
}
To start the DMA transfer I call:
DMA_ITConfig(Audio_DMA_I2S3_Stream, DMA_IT_TC, ENABLE); // Enable/Disable DMA Interrupts
DMA_Cmd(Audio_DMA_I2S3_Stream, ENABLE); // Enable/Disable DMA
I2S_Cmd(SPI3, ENABLE); // Enable/Disable I2S
I really hope you guys can help me. I read the datasheet carefully and I thought I haven't made a mistake.
Unfortunately anythere must be one. I hope someone could find it.
Thanks a lot & Best Regards,
Manuel
#dma-i2s-spi-interrupts