drivers: clock_control: stm32: Add HSE CSS support

Add support for enabling the clock security system, which can detect
failures of the HSE clock.

Includes tests for nucleo_h743zi and nucleo_g474re.

Signed-off-by: Kevin ORourke <kevin.orourke@ferroamp.se>
This commit is contained in:
Kevin ORourke 2023-11-24 12:16:11 +01:00 committed by Carles Cufí
parent c758f1cc14
commit fbfd36e81e
11 changed files with 125 additions and 0 deletions

View file

@ -10,6 +10,8 @@ menuconfig CLOCK_CONTROL_STM32_CUBE
select USE_STM32_LL_UTILS
select USE_STM32_LL_RCC if (SOC_SERIES_STM32MP1X || SOC_SERIES_STM32H7X || \
SOC_SERIES_STM32F4X || SOC_SERIES_STM32F7X)
select RUNTIME_NMI if ($(dt_nodelabel_enabled,clk_hse) && \
$(dt_nodelabel_has_prop,clk_hse,css-enabled))
help
Enable driver for Reset & Clock Control subsystem found
in STM32 family of MCUs

View file

@ -567,6 +567,11 @@ static void set_up_fixed_clock_sources(void)
while (LL_RCC_HSE_IsReady() != 1) {
/* Wait for HSE ready */
}
/* Check if we need to enable HSE clock security system or not */
#if STM32_HSE_CSS
z_arm_nmi_set_handler(HAL_RCC_NMI_IRQHandler);
LL_RCC_HSE_EnableCSS();
#endif /* STM32_HSE_CSS */
}
if (IS_ENABLED(STM32_HSI_ENABLED)) {
@ -817,6 +822,16 @@ int stm32_clock_control_init(const struct device *dev)
return 0;
}
#if defined(STM32_HSE_CSS)
void __weak stm32_hse_css_callback(void) {}
/* Called by the HAL in response to an HSE CSS interrupt */
void HAL_RCC_CSSCallback(void)
{
stm32_hse_css_callback();
}
#endif
/**
* @brief RCC device, note that priority is intentionally set to 1 so
* that the device init runs just after SOC init

View file

@ -586,6 +586,11 @@ static void set_up_fixed_clock_sources(void)
LL_RCC_HSE_Enable();
while (LL_RCC_HSE_IsReady() != 1) {
}
/* Check if we need to enable HSE clock security system or not */
#if STM32_HSE_CSS
z_arm_nmi_set_handler(HAL_RCC_NMI_IRQHandler);
LL_RCC_HSE_EnableCSS();
#endif /* STM32_HSE_CSS */
}
if (IS_ENABLED(STM32_HSI_ENABLED)) {
@ -930,6 +935,16 @@ int stm32_clock_control_init(const struct device *dev)
}
#endif /* CONFIG_CPU_CORTEX_M7 */
#if defined(STM32_HSE_CSS)
void __weak stm32_hse_css_callback(void) {}
/* Called by the HAL in response to an HSE CSS interrupt */
void HAL_RCC_CSSCallback(void)
{
stm32_hse_css_callback();
}
#endif
/**
* @brief RCC device, note that priority is intentionally set to 1 so
* that the device init runs just after SOC init

View file

@ -13,3 +13,19 @@ properties:
description: |
HSE crystal oscillator bypass
Set to the property to by-pass the oscillator with an external clock.
css-enabled:
type: boolean
description: |
HSE clock security system enabled
Set the property to enable the clock security system (CSS) for the HSE clock.
If a failure is detected on the HSE clock, the HSE oscillator is automatically disabled,
a clock failure event is sent to timers, and a non-maskable interrupt is generated to
inform the software about the failure, allowing the MCU to perform rescue operations.
See the MCU reference manual for details.
The interaction of CSS and low-power modes is unclear from the documentation.
For at least some devices Zephyr will reconfigure the clocks on resuming from low-power
modes; this will include re-enabling CSS. However it is important that you verify
this for your own hardware.

View file

@ -369,6 +369,7 @@
#define STM32_HSE_ENABLED 1
#define STM32_HSE_BYPASS DT_PROP(DT_NODELABEL(clk_hse), hse_bypass)
#define STM32_HSE_FREQ DT_PROP(DT_NODELABEL(clk_hse), clock_frequency)
#define STM32_HSE_CSS DT_PROP(DT_NODELABEL(clk_hse), css_enabled)
#elif DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(clk_hse), st_stm32wl_hse_clock, okay)
#define STM32_HSE_ENABLED 1
#define STM32_HSE_TCXO DT_PROP(DT_NODELABEL(clk_hse), hse_tcxo)
@ -460,4 +461,16 @@ struct stm32_pclken {
#define STM32_CLOCK_VAL_GET(clock) \
(((clock) >> STM32_CLOCK_VAL_SHIFT) & STM32_CLOCK_VAL_MASK)
#if defined(STM32_HSE_CSS)
/**
* @brief Called if the HSE clock security system detects a clock fault.
*
* The function is called in interrupt context.
*
* The default (weakly-linked) implementation does nothing and should be
* overridden.
*/
void stm32_hse_css_callback(void);
#endif
#endif /* ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_STM32_CLOCK_CONTROL_H_ */

View file

@ -0,0 +1,14 @@
/*
* Copyright (c) 2023 Ferroamp AB (publ)
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
* Warning: This overlay assumes the HSE clock has already been enabled,
* for example by hse_24.overlay.
*/
&clk_hse {
css-enabled;
};

View file

@ -105,4 +105,17 @@ ZTEST(stm32_sysclck_config, test_pll_src)
#endif
}
#if STM32_HSE_ENABLED
ZTEST(stm32_sysclck_config, test_hse_css)
{
/* there is no function to read CSS status, so read directly from the register */
#if STM32_HSE_CSS
zassert_true(READ_BIT(RCC->CR, RCC_CR_CSSON), "HSE CSS is not enabled");
#else
zassert_false(READ_BIT(RCC->CR, RCC_CR_CSSON), "HSE CSS unexpectedly enabled");
#endif /* STM32_HSE_CSS */
}
#endif /* STM32_HSE_ENABLED */
ZTEST_SUITE(stm32_sysclck_config, NULL, NULL, NULL, NULL, NULL);

View file

@ -114,6 +114,10 @@ tests:
drivers.clock.stm32_clock_configuration.common_core.g4.sysclksrc_hse_24:
extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/hse_24.overlay"
platform_allow: nucleo_g474re
drivers.clock.stm32_clock_configuration.common_core.g4.sysclksrc_hse_24.css:
extra_args:
DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/hse_24.overlay;boards/hse_css.overlay"
platform_allow: nucleo_g474re
drivers.clock.stm32_clock_configuration.common_core.l0_l1.sysclksrc_hse_8:
extra_args:
DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/clear_msi.overlay;boards/hse_8.overlay"

View file

@ -0,0 +1,14 @@
/*
* Copyright (c) 2023 Ferroamp AB (publ)
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
* Warning: This overlay assumes the HSE clock has already been enabled,
* for example by hse_8.overlay.
*/
&clk_hse {
css-enabled;
};

View file

@ -76,4 +76,17 @@ ZTEST(stm32_syclck_config, test_pll_src)
#endif
}
#if STM32_HSE_ENABLED
ZTEST(stm32_syclck_config, test_hse_css)
{
/* there is no function to read CSS status, so read directly from the register */
#if STM32_HSE_CSS
zassert_true(READ_BIT(RCC->CR, RCC_CR_CSSHSEON), "HSE CSS is not enabled");
#else
zassert_false(READ_BIT(RCC->CR, RCC_CR_CSSHSEON), "HSE CSS unexpectedly enabled");
#endif /* STM32_HSE_CSS */
}
#endif /* STM32_HSE_ENABLED */
ZTEST_SUITE(stm32_syclck_config, NULL, NULL, NULL, NULL, NULL);

View file

@ -28,6 +28,12 @@ tests:
platform_allow: nucleo_h743zi
integration_platforms:
- nucleo_h743zi
drivers.clock.stm32_clock_configuration.h7_core.sysclksrc_hse_8_css:
extra_args:
DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/hse_8.overlay;boards/hse_css.overlay"
platform_allow: nucleo_h743zi
integration_platforms:
- nucleo_h743zi
drivers.clock.stm32_clock_configuration.h7_core.sysclksrc_pll_csi_96:
extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/pll_csi_96.overlay"
platform_allow: nucleo_h743zi