cancel
Showing results for 
Search instead for 
Did you mean: 

I2S on STM32WB55

nikzin
Associate II

Hello,

I am trying to get I2S and DMA working on my stm32wb55 microcontroller. I want to read data from an INMP441 (or similar). I did try to use the STCube IDE (or MX) to configure I2S and DMA using tutorials from the internet but this also did not work. The tutorials are all made for other ST-microcontrollers though.

I either have a problem setting up the DMA, SAI (for I2S) or the DMA interrupt. I do not really have any idea where my problem lies. Just using the standard configurations from STCube do not seem to work.

Does anyone here have any experience with the STM32WB55 and the SAI of this Microcontroller in particular? I am using the WeAct STM32WB55CGU6 for testing.

Thanks a lot for helping me out here.

1 ACCEPTED SOLUTION

Accepted Solutions

Okay, so it's doing, what you set it to do: nothing.

First, set clock tree to something useful...

SAI clock 48M, maybe ok, but core to max, I don't know now, maybe also 48M.

Now it's at 4.... this cannot do anything useful.

Then start it, maybe HAL_SAI_DMA_START(), or so. To the data array you want the data to get then.

 

If you feel a post has answered your question, please click "Accept as Solution".

View solution in original post

5 REPLIES 5
AScha.3
Super User

Hi,

The SAI is working fine, just set it to the mode you need. Master receive, 16bit, two slots, ... maybe.

Then set a DMA Channel for circular mode, with 16b , half word, source and destination.

Enable callback in Cube project settings for the SAI, generate code.

In program then set an array int16_t , big enough, let's say 16KB .

Then start the SAI in DMA mode, once, that's it.

Now in callback half and full, you get the data, to copy and use it. That's it.

If you feel a post has answered your question, please click "Accept as Solution".

HI AScha.3,

 

I am not quite sure if I can recreate what you suggested.

So starting from the bare minimum, here are the settings I tried in the STMCube configurator to get the INMP441 to work on the STM32WB55:

Clocks.pngDMA.pngGPIOs.pngNVIC.pngSAI.png

And the generated code (without any own code or comments) was this:

 
#include "main.h"

SAI_HandleTypeDef hsai_BlockA1;
DMA_HandleTypeDef hdma_sai1_a;

void SystemClock_Config(void);
void PeriphCommonClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_SAI1_Init(void);

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  PeriphCommonClock_Config();
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_SAI1_Init();
  
  while (1)
  {
    
  }
}

void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  __HAL_RCC_PLL_PLLM_CONFIG(RCC_PLLM_DIV1);
  __HAL_RCC_PLL_PLLSOURCE_CONFIG(RCC_PLLSOURCE_MSI);
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_MSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.MSIState = RCC_MSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK4|RCC_CLOCKTYPE_HCLK2
                              |RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.AHBCLK2Divider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.AHBCLK4Divider = RCC_SYSCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
}
void PeriphCommonClock_Config(void)
{
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
  PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SMPS;
  PeriphClkInitStruct.SmpsClockSelection = RCC_SMPSCLKSOURCE_HSI;
  PeriphClkInitStruct.SmpsDivSelection = RCC_SMPSCLKDIV_RANGE1;

  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
}
static void MX_SAI1_Init(void)
{
  hsai_BlockA1.Instance = SAI1_Block_A;
  hsai_BlockA1.Init.AudioMode = SAI_MODEMASTER_RX;
  hsai_BlockA1.Init.Synchro = SAI_ASYNCHRONOUS;
  hsai_BlockA1.Init.OutputDrive = SAI_OUTPUTDRIVE_DISABLE;
  hsai_BlockA1.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE;
  hsai_BlockA1.Init.MckOverSampling = SAI_MCK_OVERSAMPLING_DISABLE;
  hsai_BlockA1.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_EMPTY;
  hsai_BlockA1.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_16K;
  hsai_BlockA1.Init.SynchroExt = SAI_SYNCEXT_DISABLE;
  hsai_BlockA1.Init.MonoStereoMode = SAI_MONOMODE;
  hsai_BlockA1.Init.CompandingMode = SAI_NOCOMPANDING;
  if (HAL_SAI_InitProtocol(&hsai_BlockA1, SAI_I2S_STANDARD, SAI_PROTOCOL_DATASIZE_24BIT, 2) != HAL_OK)
  {
    Error_Handler();
  }

}

static void MX_DMA_Init(void)
{
  __HAL_RCC_DMAMUX1_CLK_ENABLE();
  __HAL_RCC_DMA1_CLK_ENABLE();
  HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
  HAL_NVIC_SetPriority(DMAMUX1_OVR_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMAMUX1_OVR_IRQn);
}
static void MX_GPIO_Init(void)
{
  __HAL_RCC_GPIOB_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
}

void Error_Handler(void)
{
  __disable_irq();
  while (1)
  {
  }
}

 

Okay, so it's doing, what you set it to do: nothing.

First, set clock tree to something useful...

SAI clock 48M, maybe ok, but core to max, I don't know now, maybe also 48M.

Now it's at 4.... this cannot do anything useful.

Then start it, maybe HAL_SAI_DMA_START(), or so. To the data array you want the data to get then.

 

If you feel a post has answered your question, please click "Accept as Solution".

I overlooked the issue with the max clock, thanks I will try that.

I did let Cube auto set the clocks. Weird, for this simple setup I would trust Cube to be able to set usefull clocks....

The Core Clock was the issue. I got it working now with 64 MHz. Thanks for spotting it.