cancel
Showing results for 
Search instead for 
Did you mean: 

Pulse Density Modulation Interface

polotomino
Associate II

Hi!

I'm trying to enable the PDM interface on a STM32WB55RGV with one microphone. Basically i followed the AN5027 application note, but I'm not able to start the clock on the proper GPIO.

The configuration from CUBE-MX seems ok, and I checked the registers value, so maybe I'm setting up the wrong API to start the streaming.

Any advice?

0690X00000AqXgJQAV.png

0690X00000AqXgOQAV.png

	MX_SAI1_Init();
 
	osDelay(10);
 
	//HAL_SAI_Receive_DMA(&hsai_BlockA1, (uint8_t *)mic_buff, MIC_BUFF_LEN);
	HAL_SAI_Receive(&hsai_BlockA1, (uint8_t *)mic_buff, MIC_BUFF_LEN, 100);
 
 
	/* start application */
	while (1){
		osDelay(1000);
	}

1 ACCEPTED SOLUTION

Accepted Solutions
polotomino
Associate II

Thanks waclawek.jan 

The issue comes from the RCC, selecting the PLLP clock source instead of PLLSAI1 the PDM peripheral works. It seems an CUBEMX bug generating the RCC config function.

View solution in original post

13 REPLIES 13

How is SAI clock set in RCC?

Read out and check/post content of relevant RCC, SAI and GPIO registers.

JW

polotomino
Associate II

0690X00000AqYalQAF.png

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
 
  /** Configure the main internal regulator output voltage 
  */
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  /** Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV1;
  RCC_OscInitStruct.PLL.PLLN = 8;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV31;
  RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure the SYSCLKSource, HCLK, PCLK1 and PCLK2 clocks dividers 
  */
  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_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.AHBCLK2Divider = RCC_SYSCLK_DIV2;
  RCC_ClkInitStruct.AHBCLK4Divider = RCC_SYSCLK_DIV1;
 
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the peripherals clocks 
  */
  PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SMPS|RCC_PERIPHCLK_SAI1
                              |RCC_PERIPHCLK_I2C1|RCC_PERIPHCLK_I2C3
                              |RCC_PERIPHCLK_ADC;
  PeriphClkInitStruct.PLLSAI1.PLLN = 6;
  PeriphClkInitStruct.PLLSAI1.PLLP = RCC_PLLP_DIV31;
  PeriphClkInitStruct.PLLSAI1.PLLQ = RCC_PLLQ_DIV2;
  PeriphClkInitStruct.PLLSAI1.PLLR = RCC_PLLR_DIV2;
  PeriphClkInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK;
  PeriphClkInitStruct.I2c1ClockSelection = RCC_I2C1CLKSOURCE_PCLK1;
  PeriphClkInitStruct.I2c3ClockSelection = RCC_I2C3CLKSOURCE_PCLK1;
  PeriphClkInitStruct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLLSAI1;
  PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_PLL;
  PeriphClkInitStruct.SmpsClockSelection = RCC_SMPSCLKSOURCE_HSI;
  PeriphClkInitStruct.SmpsDivSelection = RCC_SMPSCLKDIV_RANGE1;
 
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
}

I don't use Cube and don't understand its gibberish.

It appears you are using the SAI PLL's output - is that PLL running? Maybe there's no simple way to test that on your STM32 model, then use for SAI for testing a clock you are sure it's running.

Read out and check/post content of relevant RCC, SAI and GPIO registers.

JW

polotomino
Associate II

Thank you su much.

Here the SAI registers:

0690X00000AqYeOQAV.png

The RCC :

0690X00000AqYeiQAF.png

and lastly the GPIOs configuration:

0690X00000AqYfCQAV.png

PA10 is the SAI_D1 and PA8_SAI1_CK2

OK and GPIO_AFRx is set to the appropriate AF?

I have no experience with SAI with PDM, so you may want to check that yourself against the RM.

Did you make sure there is a valid clock input in RCC, maybe switching to a clock source which is known working (such as the main PLL)?

JW

polotomino
Associate II

Thanks waclawek.jan 

The issue comes from the RCC, selecting the PLLP clock source instead of PLLSAI1 the PDM peripheral works. It seems an CUBEMX bug generating the RCC config function.

OK so problem solved? Then please select your post as "Best" to mark the thread as solved.

JW

@Imen DAHMEN​  - so this appears that CubeMX does not generate code for initializing the PLLSAI for the 'WB55, can this please be checked?

Khouloud ZEMMELI
ST Employee

​Hello @Community member​  Did you mean by "  CubeMX does not generate code for initializing the PLLSAI for the 'WB55" that there's a missed  line of code ?

Thanks,

Khouloud

​and if yes which lignes of code ?

Thanks  @Community member​ 

Khouloud