cancel
Showing results for 
Search instead for 
Did you mean: 

FULL DUPLEX SPI DMA RX from not firing interrupts

dauphin2
Associate II
Posted on June 20, 2016 at 11:24

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
4 REPLIES 4
Walid FTITI_O
Senior II
Posted on June 20, 2016 at 12:36

Hi,

In the ''stm32f4xxhal_msp.c'' file inside

HAL_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&currentviews=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=false
dauphin2
Associate II
Posted on June 20, 2016 at 13:45

Thanks for your pronpt reply.

But when i enable the SP2 Nvic interrupt, nothing changes.

The DMA interrupt  : void DMA1_Stream3_IRQHandler(void)  Is never called.

And the Tx dma works.

I check in the datasheet, and the I2S_rx  only works with DMA1 stream3 channel 0 .

0690X00000605PyQAI.png

I don't know what is wrong !

Also, something is realy strange , when i remplace SPI2 by SPI3. It's works.

I2S3_Ext_RX with DMA1_stream0 and SPI3_TX DMA1 stream 5, both generate DMA interrupts when the i2s flow is started with the function : ''HAL_DMAEx_MultiBufferStart_IT ''

(whitout SPi3 nvic interrupt enable)

The problem is, I can't change my hardware. I need to use I2S2_ext.

Does I2S2 doesn't support full duplex mode ?

The spi2 and sp3 are configured in the same way? I don't find any  differencies in the reference manual.

Do you have an idea ?

 Thanks

Walid FTITI_O
Senior II
Posted on June 20, 2016 at 16:11

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-
dauphin2
Associate II
Posted on June 20, 2016 at 17:28

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.