cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F411 - HAL driver - I2S full duplex - ext_SD issue

leogarberoglio
Associate III
Posted on June 04, 2015 at 01:18

Hi, I'm continue fighting with full-duplex configuration of STM32F4

I have an audio codec with MIC input and speaker output. I connect DOUT pin from the CODEC to PC3 (I2S_Dat) line. So it will be my Rx pin. Then I connect DIN from de codec to PC2 (I2S_ext) line. So it will be my Tx pin. I configure (with Cube MX) the I2S and DMA stream as follow:

/* I2S2 init function */
void MX_I2S2_Init(void)
{
hi2s2.Instance = SPI2;
hi2s2.Init.Mode = I2S_MODE_MASTER_RX;
hi2s2.Init.Standard = I2S_STANDARD_PHILLIPS;
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;
HAL_I2S_Init(&hi2s2);
}
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 */
__SPI2_CLK_ENABLE();
/**I2S2 GPIO Configuration 
PC2 ------> I2S2_ext_SD
PC3 ------> I2S2_SD
PA6 ------> I2S2_MCK
PB10 ------> I2S2_CK
PB12 ------> I2S2_WS 
*/
GPIO_InitStruct.Pin = GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
GPIO_InitStruct.Alternate = GPIO_AF6_I2S2ext;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOC, &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_LOW;
GPIO_InitStruct.Alternate = GPIO_AF6_SPI2;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* Peripheral DMA init*/
hdma_spi2_rx.Instance = DMA1_Stream3;
hdma_spi2_rx.Init.Channel = DMA_CHANNEL_0;
hdma_spi2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_spi2_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi2_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_spi2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_spi2_rx.Init.Mode = DMA_NORMAL;
hdma_spi2_rx.Init.Priority = DMA_PRIORITY_LOW;
hdma_spi2_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
HAL_DMA_Init(&hdma_spi2_rx);
__HAL_LINKDMA(hi2s,hdmarx,hdma_spi2_rx);
hdma_i2s2_ext_tx.Instance = DMA1_Stream4;
hdma_i2s2_ext_tx.Init.Channel = DMA_CHANNEL_2;
hdma_i2s2_ext_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_i2s2_ext_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_i2s2_ext_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_i2s2_ext_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_i2s2_ext_tx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_i2s2_ext_tx.Init.Mode = DMA_NORMAL;
hdma_i2s2_ext_tx.Init.Priority = DMA_PRIORITY_LOW;
hdma_i2s2_ext_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
HAL_DMA_Init(&hdma_i2s2_ext_tx);
__HAL_LINKDMA(hi2s,hdmatx,hdma_i2s2_ext_tx);
/* USER CODE BEGIN SPI2_MspInit 1 */
/* USER CODE END SPI2_MspInit 1 */
}
}

first questions: what

hi2s2.Init.Mode = I2S_MODE_MASTER_RX;

means? how do I choos between MASTER_RX and MASTER_TX?

Then my code is something like this:

int main(void)
{
/* MCU Configuration----------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_I2S2_Init();
/* USER CODE BEGIN 2 */
uint16_t i;
for(i=0;i<BufferSize;i++)
{
InputBuffer[i]=0xFFFF;
OutputBuffer[i]=0x0000;
}
HAL_I2SEx_TransmitReceive_DMA(&hi2s2, OutputBuffer, InputBuffer, BufferSize);
while (1)
{
}
}

just initialize the buffers to see changes and then call the first DMA transmit_receive. Finally I have code for each IRQ:

void DMA1_Stream3_IRQHandler(void)
{
HAL_DMA_IRQHandler(&hdma_spi2_rx);
}
/**
* @brief This function handles DMA1 Stream4 global interrupt.
*/
void DMA1_Stream4_IRQHandler(void)
{
HAL_DMA_IRQHandler(&hdma_i2s2_ext_tx);
}
/* USER CODE BEGIN 1 */
void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s)
{
//Recivimos todos los datos del micrófono, enviémoslo a los parlantes
uint16_t i;
for(i=0;i<20000;i++)
{
OutputBuffer[i]=InputBuffer[i];
}
HAL_I2SEx_TransmitReceive_DMA(&hi2s2, OutputBuffer, InputBuffer, 20000);
// HAL_I2S_Receive_DMA(&hi2s2, InputBuffer, 10000);
}
void HAL_I2S_ext_TxCpltCallback(I2S_HandleTypeDef *hi2s)
{
// HAL_I2SEx_TransmitReceive_DMA(&hi2s2, OutputBuffer, InputBuffer, 10000);
}
void HAL_I2S_ErrorCallback(I2S_HandleTypeDef *hi2s)
{
}

I put a breack point on each ISR. When I run the project I see that there is just two interrupts and then stops, I mean, there is no new interrupts, just to of them. Input buffer is filled. So, how do I need to do to obtain a continous stream of data using this HAL library? BR!
1 REPLY 1
leogarberoglio
Associate III
Posted on June 05, 2015 at 01:41

I test blocking mode:

/* I2S2 init function */
void MX_I2S2_Init(void)
{
hi2s2.Instance = SPI2;
hi2s2.Init.Mode = I2S_MODE_MASTER_RX;
hi2s2.Init.Standard = I2S_STANDARD_PHILLIPS;
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;
HAL_I2S_Init(&hi2s2);
}
void HAL_I2S_MspInit(I2S_HandleTypeDef* hi2s)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(hi2s->Instance==SPI2)
{
/* Peripheral clock enable */
__SPI2_CLK_ENABLE();
/**I2S2 GPIO Configuration 
PC2 ------> I2S2_ext_SD
PC3 ------> I2S2_SD
PA6 ------> I2S2_MCK
PB10 ------> I2S2_CK
PB12 ------> I2S2_WS 
*/
GPIO_InitStruct.Pin = GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
GPIO_InitStruct.Alternate = GPIO_AF6_I2S2ext;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOC, &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_LOW;
GPIO_InitStruct.Alternate = GPIO_AF6_SPI2;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
}

/* USER CODE BEGIN 0 */
#define BufferSize 100*2*44100/500
int16_t InputBuffer[BufferSize];
int16_t OutputBuffer[BufferSize];
/* USER CODE END 0 */
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration----------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_I2S2_Init();
/* USER CODE BEGIN 2 */
uint16_t i;
for(i=0;i<BufferSize;i++)
{
InputBuffer[i]=0xFFFF;
}
for(i=0;i<BufferSize;i+=2){
OutputBuffer[i]=( sin(2*M_PI*(i/2)*500/44100) ) * 20000;
OutputBuffer[i+1]=( sin(2*M_PI*(i/2)*500/44100) ) * 20000;
}
// HAL_I2S_Receive_DMA(&hi2s2, InputBuffer, 20000);
while(__HAL_I2S_GET_FLAG(&hi2s2, I2S_FLAG_TXE) != 1);
HAL_I2SEx_TransmitReceive(&hi2s2, OutputBuffer, InputBuffer, BufferSize, 1000);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
while(__HAL_I2S_GET_FLAG(&hi2s2, I2S_FLAG_TXE) != 1);
for(i=0;i<BufferSize;i++)
{
OutputBuffer[i]=InputBuffer[i];
}
HAL_I2SEx_TransmitReceive(&hi2s2, OutputBuffer, InputBuffer, BufferSize, 1000);
}
/* USER CODE END 3 */
}

I have two buffer, one for input, one for output. I fill input buffer with 0xffff and outputbuffer with a 500Hz sine wave. Then wait for TXE flag and do a TransmitReceive. Then on the infinite loop just wait for TXE, copy Input to Output buffer and make another TransmitReceive. This way I can hear what I speak, with a litle delay So in blocking mode I2S_sd and I2Sext_sd works fine. But, just like hem (https://my.st.com/public/STe2ecommunities/mcu/Lists/STM32Java/Flat.aspx?RootFolder=%2Fpublic%2FSTe2ecommunities%2Fmcu%2FLists%2FSTM32Java%2FHAL%20STM32F427%20Full%20Duplex%20I2S%20problems%20communicating%20with%20Audio%20Codec&FolderCTID=0x01200200770978C69A1141439FE559EB459D758000F9A0E3A95BA69146A17C2E80209ADC21&currentviews=117) once I try _IT or DMA, extSD line seems to not work... Any idea?