cancel
Showing results for 
Search instead for 
Did you mean: 

IWDG with LSI on STM32L0

gerardo
Associate II
Posted on February 13, 2015 at 09:55

Hi all,

I´m trying to implement a Independent Watchdog functionality on my STM32L0.

In HAL description pdf I´ve read the following sentence that give me some doubts on me:

STM32L0xx devices provide the capability to measure the

LSI frequency (LSI clock connected internally to TIM5 CH4 input capture). The measured

value can be used to have an IWDG timeout with an acceptable accuracy.

1.- Has anyone the code example to do that?

2.- Can I use the LSI clock only to IWDG while I am using the HSE with my application?

Best regards
4 REPLIES 4
Posted on December 16, 2016 at 17:32

Hi,

a sample code you can find in ST examples (ex. STM32Cube_FW_F0_V1.7.0/Projects/STM32F042K6-Nucleo/Examples/IWDG/IWDG_Reset/). Basically, you need to configure the timer as input capture, then measure two rising edges and compute the frequency. In the example is it nicely shown. I use Cube generator for the basic code structure so here is generated output:

tim.c

void MX_TIM21_Init(void)
{
 TIM_MasterConfigTypeDef sMasterConfig;
 TIM_IC_InitTypeDef sConfigIC;
 htimInstance = TIM21;
 htimInit.Prescaler = 0;
 htimInit.CounterMode = TIM_COUNTERMODE_UP;
 htimInit.Period = 65535;
 htimInit.ClockDivision = TIM_CLOCKDIVISION_DIV1;
 if (HAL_TIM_IC_Init(&htim21) != HAL_OK)
 {
 Error_Handler();
 }
 sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
 sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
 if (HAL_TIMEx_MasterConfigSynchronization(&htim21, &sMasterConfig) != HAL_OK)
 {
 Error_Handler();
 }
 sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
 sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
 sConfigIC.ICPrescaler = TIM_ICPSC_DIV8;
 sConfigIC.ICFilter = 0;
 if (HAL_TIM_IC_ConfigChannel(&htim21, &sConfigIC, TIM_CHANNEL_1) != HAL_OK)
 {
 Error_Handler();
 }
 if (HAL_TIMEx_RemapConfig(&htim21, TIM21_TI1_MCO) != HAL_OK)
 {
 Error_Handler();
 }
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

The interrupt is in msp file.

Computation is done in TIM_IC_CaptureCallback like this

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
 uint32_t lsiperiod = 0;
 /* Get the Input Capture value */
 tmpCC4[uwCaptureNumber++] = HAL_TIM_ReadCapturedValue(&Input_Handle, TIM_CHANNEL_1);
 if (uwCaptureNumber >= 2)
 {
 /* Compute the period length */
 lsiperiod = (uint16_t)(0xFFFF - tmpCC4[0] + tmpCC4[1] + 1);
 /* Frequency computation */ 
 uwLsiFreq = (uint32_t) SystemCoreClock / lsiperiod;
 uwLsiFreq *= 8;
 }
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

Required variables for computation are defined as

uint16_t tmpCC4[2] = {0, 0};
__IO uint32_t uwLsiFreq = 0;
__IO uint32_t uwCaptureNumber = 0;�?�?�?

And finally start the timer to measure the frequency

HAL_TIM_IC_Start_IT(&Input_Handle, TIM_CHANNEL_1);
while(uwCaptureNumber < 2);
HAL_TIM_IC_Stop_IT(&Input_Handle, TIM_CHANNEL_1);�?�?�?

Jaroslav BECKA
ST Employee
Posted on December 20, 2016 at 16:09

Hi,

the LSI is the only clock source option for the IWDG, because it has to be independent on the core frequency and its source. Thus it will be working even if the main clock fails. With HSE and timer combination you will measure the LSI frequency very precisely.

Posted on December 20, 2016 at 16:26

Just a math tip here, but you can get better precision like this

uint16_t lsiperiod; // 16-bit

/* Compute the period length */

lsiperiod = tmpCC4[1] - tmpCC4[0]; // math wraps itself

/* Frequency computation */

uwLsiFreq = (SystemCoreClock * 😎 / (uint32_t)lsiperiod;
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on December 20, 2016 at 16:29

With HSE and timer combination you will measure the LSI frequency very precisely.

Agreed, however I seen several ST examples where doing the *8 at the end results in the loss of 3-bits of precision. They'll always be zeros.

For example this SPL code, the multiplication ideally needs to occur before the division when working with integers, though you should watch the scale of the source clock. This is an example where the use of doubles might be more appropriate.

STM32F4xx_DSP_StdPeriph_Lib_V1.6.1\Project\STM32F4xx_StdPeriph_Examples\RTC\RTC_LSI\main.c

 /* Get PCLK1 prescaler */
 if ((RCC->CFGR & RCC_CFGR_PPRE1) == 0)
 {
 /* PCLK1 prescaler equal to 1 => TIMCLK = PCLK1 */
 return ((RCC_ClockFreq.PCLK1_Frequency / uwPeriodValue) * 8);
 }
 else
 { /* PCLK1 prescaler different from 1 => TIMCLK = 2 * PCLK1 */
 return (((2 * RCC_ClockFreq.PCLK1_Frequency) / uwPeriodValue) * 8) ;
 }�?�?�?�?�?�?�?�?�?�?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..