2017-03-08 01:03 AM
Hi.
I'm trying to understand the I2S configuration in STMF469I-Discovery. I've got external MEMS microphone that's outputting 16khz mono output. I can see with oscilloscope that the output is OK however I cannot seem to get the I2S configured correctly.
I've connected the mic like this and generated code with cubemx as I2S2 as slave with microphone outputting the clock signal (1Mhz), so no as SAI I2S input:
/**I2S2 GPIO Configuration
PB13 ------> I2S2_CK PB12 ------> I2S2_WS PC1 ------> I2S2_SDI'm trying to read the output in task context like this:
status = HAL_I2S_Receive(&hi2s2, buf, time * hi2s2.Init.AudioFreq, time*1000);
However the I2S_WaitFlagStateUntilTimeout expires as the while(__HAL_I2S_GET_FLAG(hi2s, Flag) == RESET) stays in RESET.
The HAL init is not the _weak definition stmf4xx_hal_i2s.c, but one _i2s_ex.c. Is this the problem or is this clock related?
I'm really having a hard time understanding the clock configuration and the audio pipelines as general. Is there any documentation about this? Below is the simple intialization generated by CubeMX and read function added by me.
/* I2S2 init function */
void MX_I2S2_Init(void){hi2s2.Instance = SPI2;
hi2s2.Init.Mode = I2S_MODE_SLAVE_RX; hi2s2.Init.Standard = I2S_STANDARD_LSB; hi2s2.Init.DataFormat = I2S_DATAFORMAT_16B; hi2s2.Init.MCLKOutput = I2S_MCLKOUTPUT_DISABLE; //hi2s2.Init.AudioFreq = I2S_AUDIOFREQ_44K; hi2s2.Init.AudioFreq = I2S_FREQ; hi2s2.Init.CPOL = I2S_CPOL_LOW; hi2s2.Init.ClockSource = I2S_CLOCK_PLL; hi2s2.Init.FullDuplexMode = I2S_FULLDUPLEXMODE_DISABLE; if (HAL_I2S_Init(&hi2s2) != HAL_OK) { Error_Handler(); }}
void HAL_I2S_MspInit(I2S_HandleTypeDef* i2sHandle)
{GPIO_InitTypeDef GPIO_InitStruct;
if(i2sHandle->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 PB13 ------> I2S2_CK PB12 ------> I2S2_WS PC1 ------> I2S2_SD */ GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_12; 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_1;
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_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_BYTE; hdma_spi2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; hdma_spi2_rx.Init.Mode = DMA_NORMAL; hdma_spi2_rx.Init.Priority = DMA_PRIORITY_LOW; hdma_spi2_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; if (HAL_DMA_Init(&hdma_spi2_rx) != HAL_OK) { Error_Handler(); }__HAL_LINKDMA(i2sHandle,hdmarx,hdma_spi2_rx);
/* USER CODE BEGIN SPI2_MspInit 1 */
/* USER CODE END SPI2_MspInit 1 */
}}void HAL_I2S_MspDeInit(I2S_HandleTypeDef* i2sHandle)
{if(i2sHandle->Instance==SPI2)
{ /* USER CODE BEGIN SPI2_MspDeInit 0 *//* USER CODE END SPI2_MspDeInit 0 */
/* Peripheral clock disable */ __HAL_RCC_SPI2_CLK_DISABLE(); /**I2S2 GPIO Configuration PB13 ------> I2S2_CK PB12 ------> I2S2_WS PC1 ------> I2S2_SD */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_13|GPIO_PIN_12);HAL_GPIO_DeInit(GPIOC, GPIO_PIN_1);
/* Peripheral DMA DeInit*/
HAL_DMA_DeInit(i2sHandle->hdmarx); } /* USER CODE BEGIN SPI2_MspDeInit 1 *//* USER CODE END SPI2_MspDeInit 1 */
}/* USER CODE BEGIN 1 */
HAL_StatusTypeDef get_i2s_data(uint16_t *buf, uint16_t time) { HAL_StatusTypeDef status;HAL_I2S_MspDeInit(&hi2s2);
MX_I2S2_Init(); status = HAL_I2S_Receive(&hi2s2, buf, time * hi2s2.Init.AudioFreq, time*1000);return status;
}/* USER CODE END 1 */Solved! Go to Solution.
2017-03-08 04:09 AM
Then its clock in RCC is probably off.
I don't Cube (as you might have guessed).
JW
2017-03-08 02:07 AM
Hi,
I propose that you refer to the working I2S example within STM32CubeF4 firmware package. The provided example will help you to have more idea on how implementation is done:STM32Cube_FW_F4_V1.15.0\Projects\STM324xG_EVAL\Examples\I2S\I2S_Audio
Refer to your reference manual in 'I2S functional description' section this may help you on your setting and more understanding the clock configuration.
Imen
2017-03-08 02:17 AM
hi2s2.Init.Mode = I2S_MODE_SLAVE_RX;
So the mic is the source of clocks? Do you see both SCK and WS on PB13/PB12 with an oscilloscope/LA?
JW
2017-03-08 02:44 AM
And what is that flag Cube waits for? SPI_SR.RXNE? Do you observe the SPI/I2S registers in a debugger?
JW
2017-03-08 02:48 AM
I2S_FLAG_RXNE
From stm32f4xx_hal_i2s.c -> HAL_I2S_Receive
if (I2S_WaitFlagStateUntilTimeout(hi2s, I2S_FLAG_RXNE, RESET, Timeout) != HAL_OK)
{ return HAL_TIMEOUT; }My main confusion is the stm32f4xx_hal_i2sex -interface. Why the initialization is calling init there? What I understood from the code is that it's only for the full duplex stuff and not just for receiving.
2017-03-08 03:06 AM
All the SPI2 registers seem to be 0.
From debugger after timeout:
SPI2 SPI_TypeDef * 0x40003800
CR1 volatile uint32_t 0 CR2 volatile uint32_t 0 SR volatile uint32_t 0 DR volatile uint32_t 0 CRCPR volatile uint32_t 0 RXCRCR volatile uint32_t 0 TXCRCR volatile uint32_t 0 I2SCFGR volatile uint32_t 0 I2SPR volatile uint32_t 02017-03-08 03:20 AM
Thanks Imen!
The example is about playback. Is there anything about I2S slave input?
Also regarding the reference manual. Where do I get one that's applicable for 469i? I've found one that's for f43x.2017-03-08 03:24 AM
Yes, there's valid activity on all lines. And the mic is outputting the as long as it's on.
2017-03-08 03:27 AM
If I understood correctly the cube clock tree, the I2S gets I2S_APB1_CLK (160Mhz). And RCC registers say that the APB1ENR has value 4143892991 (0xf6fec9ff). From stm32f469xx.h:
#define RCC_APB1RSTR_SPI2RST_Pos (14U)
#define RCC_APB1RSTR_SPI2RST_Msk (0x1U << RCC_APB1RSTR_SPI2RST_Pos) /*!< 0x00004000 */#define RCC_APB1RSTR_SPI2RST RCC_APB1RSTR_SPI2RST_MskThe bit is 1. Dunno about the rest of the clock config.
RCC RCC_TypeDef * 0x40023800
CR volatile uint32_t 1057194115
PLLCFGR volatile uint32_t 624960527 CFGR volatile uint32_t 0 CIR volatile uint32_t 0 AHB1RSTR volatile uint32_t 0 AHB2RSTR volatile uint32_t 0 AHB3RSTR volatile uint32_t 0 RESERVED0 uint32_t 0 APB1RSTR volatile uint32_t 0 APB2RSTR volatile uint32_t 0 RESERVED1 uint32_t [2] 0x40023828 AHB1ENR volatile uint32_t 1050623 AHB2ENR volatile uint32_t 128 AHB3ENR volatile uint32_t 3 RESERVED2 uint32_t 0 APB1ENR volatile uint32_t 270532608 APB2ENR volatile uint32_t 134234113 RESERVED3 uint32_t [2] 0x40023848 AHB1LPENR volatile uint32_t 2129631231 AHB2LPENR volatile uint32_t 241 AHB3LPENR volatile uint32_t 3 RESERVED4 uint32_t 0 APB1LPENR volatile uint32_t 4143892991 APB2LPENR volatile uint32_t 209157939 RESERVED5 uint32_t [2] 0x40023868 BDCR volatile uint32_t 0 CSR volatile uint32_t 234881024 RESERVED6 uint32_t [2] 0x40023878 SSCGR volatile uint32_t 0 PLLI2SCFGR volatile uint32_t 536883200 PLLSAICFGR volatile uint32_t 570432768 DCKCFGR volatile uint32_t 0EDIT: The clock config in main.c seems to be OK from what I understood from other examples.
2017-03-08 03:57 AM
Do you observe the SPI/I2S registers in a debugger?