Hi,
normally I wouldn't create a thread like this, but I am really stuck and cannot find the issue. Can you help me find it?
I have STM32F407 and using I2S2, trying to make a full duplex transmission with DMA. The I2S2 is in a Slave_Tx mode (the codec chip provides precise clock itself). The transmit side works fine, including the DMA in doublebuffer mode. But I am struggling to make it work full duplex. The RX side I2S_RX_Ext is not working, DMA is not triggered (CNTDR stuck, memory untouched).
Here is a summary of the settings and configurations:
+ I2S2 uses pins PB12, PB13, PB14, PB15. (Should be fine, TX already works)
+ I2S2 is in Slave_TX mode. (Codec generates clocks, already working).
+ DMA1 Stream4 Channel0 is used for transmit (SPI2_TX selected, working fine)
+ I2S2 is configured Full duplex. (Not working!)
+ DMA1 Stream3 Channel3 is used for the receive side (I2S2_RX_Ext selected, not triggered!).
I see both TXDMAEN and RXDMAEN set in the SPI2_CR2 register.
I see all registers from the DMA1 Stream3 configured, seem also to be properly. CNTDR is stuck at default, no request coming.
Can you pleas help me to trace the issue? What did I do wrong? What should I check? I just can't see my mistake.
Here is a dump of the init code:
void Init_I2S2(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
I2S_InitTypeDef I2S_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStruct;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource12, GPIO_AF_SPI2); /* WS */
GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_SPI2); /* CK */
GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_SPI2); /* DIN */
GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_SPI2); /* DOUT */
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_25MHz;
GPIO_Init(GPIOB, &GPIO_InitStruct);
I2S_StructInit(&I2S_InitStructure);
I2S_InitStructure.I2S_Mode = I2S_Mode_SlaveTx;
I2S_InitStructure.I2S_Standard = I2S_Standard_Phillips;
I2S_InitStructure.I2S_DataFormat = I2S_DataFormat_16bextended;
I2S_InitStructure.I2S_CPOL = I2S_CPOL_Low;
I2S_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Disable;
I2S_Init(SPI2, &I2S_InitStructure);
I2S_FullDuplexConfig(I2S2ext, &I2S_InitStructure);
/* Enable DMA request for TX & RX */
SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE);
SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Rx, ENABLE);
/* DMA1 Stream4 Channel0 for I2S2 TX side */
DMA_InitStructure.DMA_Channel = DMA_Channel_0;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&SPI2->DR;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)DAC_Buffer0;
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_InitStructure.DMA_BufferSize = BUFFER_DEPTH*2;
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_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA1_Stream4, &DMA_InitStructure);
DMA_DoubleBufferModeConfig(DMA1_Stream4, (uint32_t)DAC_Buffer1, DMA_Memory_0);
DMA_DoubleBufferModeCmd(DMA1_Stream4, ENABLE);
/* DMA1 Stream3 Channel3 for I2S2 RX side */
DMA_InitStructure.DMA_Channel = DMA_Channel_3;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&SPI2->DR;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)ADC_Buffer0;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = BUFFER_DEPTH*2;
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_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA1_Stream3, &DMA_InitStructure);
DMA_DoubleBufferModeConfig(DMA1_Stream3, (uint32_t)ADC_Buffer1, DMA_Memory_0);
DMA_DoubleBufferModeCmd(DMA1_Stream3, ENABLE);
DMA_ITConfig(DMA1_Stream4, DMA_IT_TC, ENABLE);
NVIC_InitStruct.NVIC_IRQChannel = DMA1_Stream4_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_Init(&NVIC_InitStruct);
/* Enable DMA, RX & TX */
DMA_Cmd(DMA1_Stream3, ENABLE);
DMA_Cmd(DMA1_Stream4, ENABLE);
}
Thx for help!
//EDIT: Calling I2S_Cmd() enable both for SPI2 and I2S2ext from main.