cancel
Showing results for 
Search instead for 
Did you mean: 

stm32l4 MSI PLL-mode (auto trimming with LSE ) stable only when VBAT supply present

siddiq.habib
Associate III

Hi All,

In our product we have to avoid HSE, so decided to use MSI in PLL mode.

The below code snippet works fine for MSI in PLL-mode , when auto-trimmed with LSE.

But if the battery is say removed (The battery can get depleted in the field), the accuracy of the

MSI detoriates.

If the VBAT is available, the MSI is very stable. Not sure what i am missing.

RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
   RCC_OscInitTypeDef RCC_OscInitStruct = {0};
   RCC_OscInitTypeDef LSE_OscInitStruct = {0};
 
   LSE_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE;
   LSE_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
   LSE_OscInitStruct.LSEState = RCC_LSE_ON;
   LSE_OscInitStruct.LSIState = RCC_LSI_OFF;
 
   // configure the oscillator
   if (HAL_RCC_OscConfig(&LSE_OscInitStruct) != HAL_OK)
   {
      Error_Handler();
   }
 
   // set drive level to maximum, to ensure RTC accuracy
   __HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_HIGH);
 
    HAL_RCCEx_DisableLSECSS();
 
     /* Set Oscillator to MSI*/
     RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI | 
                                                  RCC_OSCILLATORTYPE_HSI | RCC_OSCILLATORTYPE_HSE;
     RCC_OscInitStruct.MSIState       = RCC_MSI_ON;
     RCC_OscInitStruct.HSEState       = RCC_HSE_OFF;
     RCC_OscInitStruct.HSIState       = RCC_HSI_OFF;
     RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
     RCC_OscInitStruct.MSIClockRange       = RCC_CR_MSIRANGE_7;
 
     RCC_OscInitStruct.PLL.PLLState   = RCC_PLL_ON;
     RCC_OscInitStruct.PLL.PLLSource  = RCC_PLLSOURCE_MSI;
 
     RCC_OscInitStruct.PLL.PLLM       = 2;
     RCC_OscInitStruct.PLL.PLLN       = 40;
     RCC_OscInitStruct.PLL.PLLP       = 2;
     RCC_OscInitStruct.PLL.PLLQ       = 5;
     RCC_OscInitStruct.PLL.PLLR       = 2;
 
     if(HAL_RCC_OscConfig(&RCC_OscInitStruct) == HAL_OK)
     {
        // enable MSI auto-calibration through LSE
        _HAL_RCC_SET_MSIPLLEN();        
 
        /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers */
        RCC_ClkInitStruct.ClockType      = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
        RCC_ClkInitStruct.SYSCLKSource   = RCC_SYSCLKSOURCE_PLLCLK;
        RCC_ClkInitStruct.AHBCLKDivider  = RCC_SYSCLK_DIV2;
        RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
        RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
 
        if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) == HAL_OK)
        {
 
           __HAL_RCC_HSI_DISABLE();           
 
            //redo systick configuration
           HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
           HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
 
           __SYSCFG_CLK_ENABLE();
           __PWR_CLK_ENABLE();
 
           /* Enable GPIO Clocks */
       }
        else
        {
          Error_Handler();
        }
     }
    else
    {
        Error_Handler();
    }
 

 In the bootloader, there is no clock configuration apart from the call to default implementation in SystemInit().

One extra observation made was, When on VDD and no VBAT if the micro is reset (system reset) the System clock seems to be very stable.

But on Power on Reset with no VBAT, the system clock is not stable.

1 REPLY 1
siddiq.habib
Associate III

Looks like i have identified the problem.

in my code

After the above LSE, MSI and PLL related Oscillator and Clock related configuration.

I go for the RTC configuration,

with the call HAL_StatusTypeDef HAL_RTC_Init(RTC_HandleTypeDef *hrtc); to initialize the RTC peripheral

the above function makes a call to void HAL_RTC_MspInit(RTC_HandleTypeDef *hrtc)

which has the following implementation

void HAL_RTC_MspInit(RTC_HandleTypeDef *hrtc)
{
   RCC_PeriphCLKInitTypeDef  PeriphClkInitStruct = {0u};
 
   /*##-1- Enables the PWR Clock and Enables access to the backup domain ###################################*/
   /* To change the source clock of the RTC feature (LSE, LSI), You have to:
     - Enable the power clock using __HAL_RCC_PWR_CLK_ENABLE()
     - Enable write access using HAL_PWR_EnableBkUpAccess() function before to
       configure the RTC clock source (to be done once after reset).
     - Reset the Back up Domain using __HAL_RCC_BACKUPRESET_FORCE() and
       __HAL_RCC_BACKUPRESET_RELEASE().
     - Configure the needed RTC clock source */
   __HAL_RCC_PWR_CLK_ENABLE();
   HAL_PWR_EnableBkUpAccess();
 
   /*##-2- Configue LSE/LSI as RTC clock soucre ###############################*/
   //Configure_LSE_Oscillator(); // this has already been done so commented
 
   // configure the clock source
   PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC;
   PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
   if(HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
   {
     Error_Handler();
   }
 
   // Enable CSS for LSE over here
   HAL_RCCEx_EnableLSECSS();
 
   __HAL_RCC_RTC_ENABLE();
 
   HAL_NVIC_SetPriority(RTC_Alarm_IRQn, 0x0F, 0);
   HAL_NVIC_EnableIRQ(RTC_Alarm_IRQn);
   HAL_PWR_DisableBkUpAccess();
}

The problem happened with the call HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct); as inside this function

a Backup Domain Reset is done for the following condition

    /* Reset the Backup domain only if the RTC Clock source selction is modified */
    if((RCC->BDCR & RCC_BDCR_RTCSEL) != (PeriphClkInit->RTCClockSelection & RCC_BDCR_RTCSEL))
    {
      /* Store the content of BDCR register before the reset of Backup Domain */
      tmpreg = (RCC->BDCR & ~(RCC_BDCR_RTCSEL));
      /* RTC Clock selection can be changed only if the Backup Domain is reset */
      __HAL_RCC_BACKUPRESET_FORCE();
      __HAL_RCC_BACKUPRESET_RELEASE();
      /* Restore the Content of BDCR register */
      RCC->BDCR = tmpreg;
    }

If a Backup Domain Reset happens, as per the reference manual this can happen

"

Backup domain reset

The backup domain has two specific resets.

A backup domain reset is generated when one of the following events occurs:

1. Software reset, triggered by setting the BDRST bit in the Backup domain control

register (RCC_BDCR).

2. VDD or VBAT power on, if both supplies have previously been powered off.

"

The 2. condition in my case can happen due to "Battery being dead or removed" AND the product had power cycled due to "Power Reset (BOR)"

In all if the BDCR is reset by the HAL_RCCEx_PeriphCLKConfig call

What i found is my previous configuration of MSI being used in PLL mode is reset. I can see this from the value in RCC->CR register

I now just need to ensure the calls are made with the right checks, to avoid falling into MSI being in normal mode.