cancel
Showing results for 
Search instead for 
Did you mean: 

Unable To Activate PLL64M on STM32WB05TZ/BlueNRG-LPS

DCMilla
Associate II

I'm building an application for a BlueNRG-LPS (332), now rebranded as STM32WB05TZ (WLCSP-36 Package) by starting with a simply Blinky project testing the clock signals of my device. I need to enable the PLL64M clock source to use the radio peripherals, and the generated configuration fails. Maybe I'm missing to add or properly set up something here?

Context:
I'm using STM32CubeIDE 1.16.0 with STM32Cube FW_WB0 V1.0.0 to generate some basic code.
Initially, all the Radio Peripherals are OFF, I'm using a 32MHz external crystal for the HSE, and do not have an LSE installed on my PCB (planning to have one, but for now, using the LSI). 
In my particular case, I added external 12pF capacitors to my HSE crystal, and set the chip's internal tuning capacitors to 0. (Ignore the inductor symbol, this is only a 0ohm resistor)

DCMilla_3-1725992152306.png

 


The PCB has the hardware to not work on SMPS mode (no Inductor), tried 2.4V and 3.3V as the VDD source with similar results.

My clock tree initially looked like following image, checking the MCO pin with an oscilloscope tells me that indeed the HSE signal looked proper. (1MHz as expected after the 32x division on the pin itself).

DCMilla_1-1725990045903.png


DCMilla_0-1725989851102.png

Using the exact same settings, but changing the RC64MPLL from using HSI RC to PLL64M input, fails with the following error:

DCMilla_2-1725990496445.png

 

// main.c

void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI|RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.LSIState = RCC_LSI_ON;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure the SYSCLKSource and SYSCLKDivider
  */
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_RC64MPLL;
  RCC_ClkInitStruct.SYSCLKDivider = RCC_RC64MPLL_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_WAIT_STATES_0) != HAL_OK)
  {
    Error_Handler(); // <-------------------------------------------------- FAILS HERE 
  }
  HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_SYSCLK, RCC_MCODIV_32);
  HAL_RCCEx_EnableLSCO(RCC_LSCO1, RCC_LSCOSOURCE_LSI);
}

 

Stepping further within "HAL_RCC_ClockConfig":

 

//stm32wb0x_hal_rcc.c

/* RC64MPLL is selected as System Clock Source */
  if (RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_RC64MPLL)
  {
    /* Check the HSI ready flag */
    if (LL_RCC_HSI_IsReady() == 0U)
    {
      return HAL_ERROR;
    }

    /* Check the HSE ready flag */
    if (LL_RCC_HSE_IsReady() == 0U)
    {
      return HAL_ERROR;
    }

    /* Enable the RC64MPLL*/
    __HAL_RCC_RC64MPLL_ENABLE();

    /* Get Start Tick*/
    tickstart = HAL_GetTick();

    /* Wait till RC64MPLL is ready */
    while (LL_RCC_RC64MPLL_IsReady() == 0)
    {
      if ((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE)
      {
        return HAL_TIMEOUT; // <---------------------------------------- FAILS HERE
      }
    }

    /* Configure the RC64MPLL multiplication factor */
    __HAL_RCC_RC64MPLL_PRESC_CONFIG(RCC_ClkInitStruct->SYSCLKDivider);
  }

 

Other notes: 
While loop only has GPIO toggle function and nothing else. 

Any hints as to why the LL_RCC_RC64MPLL_IsReady() would constantly fail? 

Thanks,
DC.

 

 

4 REPLIES 4
STTwo-32
ST Employee

Hello @DCMilla 

Could you share the error that you are having. For me, the only error I can see is that the "GPIO_InitStruct.Alternate = GPIO_AF3_SYS;" on the MCO pin Configuration should be changed to "GPIO_InitStruct.Alternate = GPIO_AF3_MCO;" and I've escalate it to the concerned team for correction (under internal ticket number 190852)

Best Regards.

STTwo-32

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

DCMilla
Associate II

Hi @STTwo-32 , 

Aside from what you mentioned I get no error while compiling the code. 
It's when executing it that the codes gets halted timing out for the PLL to respond on the line I showed above, which makes the generated code get into the error handler with a forever while loop (as it should when it fails).

I found in one of the application notes for the STM32WB series (AN5042) that the tunning capacitors can only be modulated between 12pF and 16pF, perhaps my problem is to have external capacitors in the chip, thinking that setting the HSE tunning capacitors to 0 meant "0pF" of load added. I see the STEVAL-IDB013V1 schematic does not have external capacitors.

DCMilla_0-1726074676136.png


This application note doesn't seem to be linked on neither the BlueNRG-LPS nor the STM32WB05 ST Pages, and could not find it between it's linked documents. Could you help me confirm if this applies to the STM32WB05TZ chip?

Best regards,
David C.

DCMilla
Associate II

Hi, 
An update here:

I have tested removing my external load capacitors for the HSE Resonator (C412 and C413 from my initial picture), and adjusting the Tuning Capacitor values under the "RCC" STM32Cube section. 
The resulting frequency of the clock is indeed closer to the expected value (checked using the MCO pin), but the PLL continues to not work. 

I saw on a different post that some chips such as the STM32L4 series often need mandatorily an LSE source to calibrate the PLL mode on some of the clocks, but could not find any comment about it in the reference manual. 

Can anyone confirm if this is the case for the STM32WB05/BlueNRG-LPS? 
 
Thanks,
David C.

STTwo-32
ST Employee

Hello @DCMilla 

If you are looking for the deployment of HSE (RC64MPLL), LSI with LSI, you may want to refer to the Configurations of the AN5977 or use the clock config code on following main.c attached code:

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

PKA_HandleTypeDef hpka;

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
void PeriphCommonClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_RADIO_Init(void);
static void MX_RADIO_TIMER_Init(void);
static void MX_PKA_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
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();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* Configure the peripherals common clocks */
  PeriphCommonClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_RADIO_Init();
  MX_RADIO_TIMER_Init();
  MX_PKA_Init();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Init code for STM32_BLE */
  MX_APPE_Init(NULL);

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
    MX_APPE_Process();

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE|RCC_OSCILLATORTYPE_LSI;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.LSIState = RCC_LSI_ON;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure the SYSCLKSource and SYSCLKDivider
  */
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_RC64MPLL;
  RCC_ClkInitStruct.SYSCLKDivider = RCC_RC64MPLL_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_WAIT_STATES_0) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief Peripherals Common Clock Configuration
  * @retval None
  */
void PeriphCommonClock_Config(void)
{
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};

  /** Initializes the peripherals clock
  */
  PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SMPS;
  PeriphClkInitStruct.SmpsDivSelection = RCC_SMPSCLK_DIV4;

  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief PKA Initialization Function
  * @param None
  * @retval None
  */
static void MX_PKA_Init(void)
{

  /* USER CODE BEGIN PKA_Init 0 */
  
  /* USER CODE END PKA_Init 0 */

  /* USER CODE BEGIN PKA_Init 1 */
  
  /* USER CODE END PKA_Init 1 */
  hpka.Instance = PKA;
  if (HAL_PKA_Init(&hpka) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN PKA_Init 2 */
  
  /* USER CODE END PKA_Init 2 */

}

/**
  * @brief RADIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_RADIO_Init(void)
{

  /* USER CODE BEGIN RADIO_Init 0 */

  /* USER CODE END RADIO_Init 0 */

  RADIO_HandleTypeDef hradio = {0};

  /* USER CODE BEGIN RADIO_Init 1 */

  /* USER CODE END RADIO_Init 1 */

  if (__HAL_RCC_RADIO_IS_CLK_DISABLED())
  {
    /* Radio Peripheral reset */
    __HAL_RCC_RADIO_FORCE_RESET();
    __HAL_RCC_RADIO_RELEASE_RESET();

    /* Enable Radio peripheral clock */
    __HAL_RCC_RADIO_CLK_ENABLE();
  }
  hradio.Instance = RADIO;
  HAL_RADIO_Init(&hradio);
  /* USER CODE BEGIN RADIO_Init 2 */

  /* USER CODE END RADIO_Init 2 */

}

/**
  * @brief RADIO_TIMER Initialization Function
  * @param None
  * @retval None
  */
static void MX_RADIO_TIMER_Init(void)
{

  /* USER CODE BEGIN RADIO_TIMER_Init 0 */
  
  /* USER CODE END RADIO_TIMER_Init 0 */

  RADIO_TIMER_InitTypeDef RADIO_TIMER_InitStruct = {0};

  /* USER CODE BEGIN RADIO_TIMER_Init 1 */
  
  /* USER CODE END RADIO_TIMER_Init 1 */

  if (__HAL_RCC_RADIO_IS_CLK_DISABLED())
  {
    /* Radio Peripheral reset */
    __HAL_RCC_RADIO_FORCE_RESET();
    __HAL_RCC_RADIO_RELEASE_RESET();

    /* Enable Radio peripheral clock */
    __HAL_RCC_RADIO_CLK_ENABLE();
  }
  /* Wait to be sure that the Radio Timer is active */
  while(LL_RADIO_TIMER_GetAbsoluteTime(WAKEUP) < 0x10);
  RADIO_TIMER_InitStruct.XTAL_StartupTime = 320;
  RADIO_TIMER_InitStruct.enableInitialCalibration = TRUE;
  RADIO_TIMER_InitStruct.periodicCalibrationInterval = 10000;
  HAL_RADIO_TIMER_Init(&RADIO_TIMER_InitStruct);
  /* USER CODE BEGIN RADIO_TIMER_Init 2 */

  /* USER CODE END RADIO_TIMER_Init 2 */

}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOB_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();

  /*RT DEBUG GPIO_Init */
  RT_DEBUG_GPIO_Init();

/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  Error_Handler();
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

 please try to follow the same config as here.

Best Regards.

STTwo-32

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.