2016-06-20 02:24 AM
Hi everyone,
I'm trying to use I2S2 of a STM32F405RG custom board in full duplex. I generate my code with CubeMx: This is my I2S and DMA initialization :static
void
MX_I2S2_Init(
void
)
{
hi2s2.Instance = SPI2;
hi2s2.Init.Mode = I2S_MODE_MASTER_TX;
hi2s2.Init.Standard = I2S_STANDARD_PHILIPS;
hi2s2.Init.DataFormat = I2S_DATAFORMAT_16B;
hi2s2.Init.MCLKOutput = I2S_MCLKOUTPUT_ENABLE;
hi2s2.Init.AudioFreq = I2S_AUDIOFREQ_44K;
hi2s2.Init.CPOL = I2S_CPOL_LOW;
hi2s2.Init.ClockSource = I2S_CLOCK_PLL;
hi2s2.Init.FullDuplexMode = I2S_FULLDUPLEXMODE_ENABLE;
if
(HAL_I2S_Init(&hi2s2) != HAL_OK)
{
Error_Handler();
}
}
static
void
MX_DMA_Init(
void
)
{
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
/* DMA interrupt init */
/* DMA1_Stream3_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Stream3_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream3_IRQn);
/* DMA1_Stream4_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Stream4_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream4_IRQn);
}
and in the file stm32f4xxhal_msp.c
void
HAL_I2S_MspInit(I2S_HandleTypeDef* hi2s)
{
GPIO_InitTypeDef GPIO_InitStruct;
if
(hi2s->Instance==SPI2)
{
/* USER CODE BEGIN SPI2_MspInit 0 */
/* USER CODE END SPI2_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_SPI2_CLK_ENABLE();
/**I2S2 GPIO Configuration
PB12 ------> I2S2_WS
PB13 ------> I2S2_CK
PB14 ------> I2S2_ext_SD
PB15 ------> I2S2_SD
PC6 ------> I2S2_MCK
*/
GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_14;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF6_I2S2ext;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/* Peripheral DMA init*/
hdma_i2s2_ext_rx.Instance = DMA1_Stream3;
hdma_i2s2_ext_rx.Init.Channel = DMA_CHANNEL_0;
hdma_i2s2_ext_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_i2s2_ext_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_i2s2_ext_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_i2s2_ext_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_i2s2_ext_rx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_i2s2_ext_rx.Init.Mode = DMA_CIRCULAR;
hdma_i2s2_ext_rx.Init.Priority = DMA_PRIORITY_LOW;
hdma_i2s2_ext_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
hdma_i2s2_ext_rx.XferCpltCallback = Transfer_RX_I2S2_M0_Complete;
hdma_i2s2_ext_rx.XferM1CpltCallback = Transfer_RX_I2S2_M1_Complete;
hdma_i2s2_ext_rx.XferErrorCallback = Transfer_RX_I2S2_Error;
if
(HAL_DMA_Init(&hdma_i2s2_ext_rx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(hi2s,hdmarx,hdma_i2s2_ext_rx);
hdma_spi2_tx.Instance = DMA1_Stream4;
hdma_spi2_tx.Init.Channel = DMA_CHANNEL_0;
hdma_spi2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_spi2_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi2_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_spi2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_spi2_tx.Init.Mode = DMA_CIRCULAR;
hdma_spi2_tx.Init.Priority = DMA_PRIORITY_LOW;
hdma_spi2_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
hdma_spi2_tx.XferCpltCallback = Transfer_TX_I2S2_M0_Complete;
hdma_spi2_tx.XferM1CpltCallback = Transfer_TX_I2S2_M1_Complete;
hdma_spi2_tx.XferErrorCallback = Transfer_TX_I2S2_Error;
if
(HAL_DMA_Init(&hdma_spi2_tx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(hi2s,hdmatx,hdma_spi2_tx);
/* USER CODE BEGIN SPI2_MspInit 1 */
/* USER CODE END SPI2_MspInit 1 */
}
}
And my interrupt handler :
void
DMA1_Stream3_IRQHandler(
void
)
{
/* USER CODE BEGIN DMA1_Stream3_IRQn 0 */
/* USER CODE END DMA1_Stream3_IRQn 0 */
HAL_DMA_IRQHandler(&hdma_i2s2_ext_rx);
/* USER CODE BEGIN DMA1_Stream3_IRQn 1 */
/* USER CODE END DMA1_Stream3_IRQn 1 */
}
/**
* @brief This function handles DMA1 stream4 global interrupt.
*/
void
DMA1_Stream4_IRQHandler(
void
)
{
/* USER CODE BEGIN DMA1_Stream4_IRQn 0 */
/* USER CODE END DMA1_Stream4_IRQn 0 */
HAL_DMA_IRQHandler(&hdma_spi2_tx);
/* USER CODE BEGIN DMA1_Stream4_IRQn 1 */
/* USER CODE END DMA1_Stream4_IRQn 1 */
}
And my I2S with DMA are started with the following function :
volatile
uint32_t *I2S2_DR = &SPI2->DR;
// Address of the data register of the SPI2 : TX
volatile
uint32_t *I2S2ext_DR = &I2S2ext->DR;
// Address of the data register of the I2Sext : RX
if
(HAL_DMAEx_MultiBufferStart_IT(&hdma_i2s2_ext_rx,
(uint32_t) I2S2ext_DR, (uint32_t) &pingIN_I2S2[0],
(uint32_t) &pongIN_I2S2[0], BufferSize) != HAL_OK) {
Error_Handler();
}
I2S2ext->I2SCFGR |= SPI_I2SCFGR_I2SE;
// I2S Enable
I2S2ext->CR2 |= SPI_CR2_TXDMAEN;
// Tx buffer DMA interrupt enable
if
(HAL_DMAEx_MultiBufferStart_IT(&hdma_spi2_tx,
(uint32_t) &pingOUT_I2S2[0], (uint32_t) I2S2_DR,
(uint32_t) &pongOUT_I2S2[0], BufferSize) != HAL_OK) {
Error_Handler();
}
SPI2->I2SCFGR |= SPI_I2SCFGR_I2SE;
// I2S Enable
SPI2->CR2 |= SPI_CR2_TXDMAEN;
The problem is that the interrupt of the RX DMA is never generated.
There is no problems for the Tx interrupt. The interrupt is generated periodically when the transfert is complete.
I don't know where this problem could come from.
I used the same functions on a other target (stm32f411 ) and the I2S3 works well with DMA in full duplex mode.
thanks you for your help
#full-duplex #dma #i2s
2016-06-20 03:36 AM
Hi,
In the ''stm32f4xxhal_msp.c'' file insideHAL_I2S_MspInit
() function, it is missing the SPI2 peripheral interrupt like the follwoing :/* Peripheral interrupt init */
HAL_NVIC_SetPriority(SPI2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(SPI2_IRQn);
You should enable the SPI2 global interrupt in : ''Configuration''window -> I2S2 configuration -> Nvic setting. I have attached and .ico file to help you following my recommedation on STM32CubeMX Check this /public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=https%3a//my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/TIM%20triggered%20I2S%20DMA%20transfer&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B¤tviews=40
where you find a code similar to the yours. -Hannibal- ________________ Attachments : I2S_interrupt.ioc : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006Hznf&d=%2Fa%2F0X0000000bjv%2FII_6K2IWTT3CTuSKaqQ_uqIhkBYNtxEoGN7SlbZq54A&asPdf=false2016-06-20 04:45 AM
2016-06-20 07:11 AM
Hi alexandre.dauphi.001,
What do you mean exactly by replacing SPI2 by SPI3; have you changed the associated DMA configuration or you keep it and just the SPI name ? -Hannibal-2016-06-20 08:28 AM
Sorry for my basic English.
By remplacing SPI2 By SPI3 , i mean : In the cubeMx interface, I disable I2S2 . I enable I2S3 in full duplex master mode. And in the configuration tab > I2S3 > DMA Settings , I create two DMA request (Tx and Rx) with the default Dma/stream/channel/direction. and i choose Mode circular. increment memory only. And with the I2S3 in full duplex (SPI3_Tx & I2S3_ext_rx), when i start the DMA transfert with HAL_DMAEx_MultiBufferStart_IT( ... ) everything works. My callback : hdma_i2s3_ext_rx.XferCpltCallback hdma_i2s3_ext_rx.XferM1CpltCallback hdma_spi3_tx.XferCpltCallback hdma_spi3_tx.XferM1CpltCallback are called. I can set breakpoint in the two DMA_Stream_IRQHandler() and i can see the program stopped in the two. But when configure my code with I2S2(SPI2_tx and I2S2_ext_rx). I can not use the I2S2_ext_rx. I check my hardware, nothing looks strange on my I2S2_ext_rx pin. And i have this problem on my two boards. Thanks for your help.