Skip to content

STM32 clock security system for LSE #11543

@maxgerhardt

Description

@maxgerhardt

Description

  • target: NUCLEO_L476RG
  • tools: mbed-cli
  • release: 5.13.3

Currently, the implementation of the 'Clock Security System' (for both LSE/LSI and HSE/HSI) for the STM32 MCUs is lacking in mbed-os. In fact the LSE/LSI CSS is even disabled in the MSI clock setup code and never re-enabled.

/* Enable the CSS interrupt in case LSE signal is corrupted or not present */
HAL_RCCEx_DisableLSECSS();

For hardening devices, the clock security system is important. However, the current mbed-os implementation makes it hard to implement CSS callbacks properly. As the reference manual for STM32L4x6 device says in chapter 6.2.11:

A Clock Security System on LSE can be activated by software writing the LSECSSON bit in
the Backup domain control register (RCC_BDCR). This bit can be disabled only by a
hardware reset or RTC software reset, or after a failure detection on LSE. LSECSSON must
be written after LSE and LSI are enabled (LSEON and LSION enabled) and ready (LSERDY
and LSIRDY set by hardware), and after the RTC clock has been selected by RTCSEL.
[..]
The software MUST then disable the LSECSSON bit, stop the defective 32 kHz oscillator
(disabling LSEON), and change the RTC clock source (no clock or LSI or HSE, with
RTCSEL), or take any required action to secure the application.

So even if I call HAL_RCCEx_EnableLSECSS() and implement the _WEAK callback HAL_RCCEx_LSECSS_Callback() in my app, I have to write my own RTC clock init routine because rtc_init() has hard-coded #ifdefs for whether the LSE is available on the system.

#if MBED_CONF_TARGET_LSE_AVAILABLE
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
RCC_OscInitStruct.LSEState = RCC_LSE_ON;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
error("Cannot initialize RTC with LSE\n");
}
__HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_LSE);
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC;
PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) {
error("PeriphClkInitStruct RTC failed with LSE\n");
}
#else /* MBED_CONF_TARGET_LSE_AVAILABLE */
#if TARGET_STM32WB
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI1;
#else
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI;
#endif
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
RCC_OscInitStruct.LSIState = RCC_LSI_ON;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
error("Cannot initialize RTC with LSI\n");
}

mbed-os is hardcoded to assume either LSE or LSI will be there forever and that their frequencies never change (you made sure to hardcode RTC_CLOCK as well, which will mess up all timebases if this changes). It would be nice if mbed-os integrates the CSS system and reinitializes peripherals (here: RTC and LP ticker, which you hardcoded as well) on clock failure to make the firmwares more resilient by default.

Similar for high-speed clock sources. Though SetSysClock() is called on bootup and on every wakeup from deepsleep, but what if during the "run" section of a firmware, we suddenly lose the external high-speed clock source (HSE)?

Issue request type

[] Question
[X] Enhancement
[ ] Bug

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions