Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Portenta: use LSE as LPTIMER if possible #540

Merged
merged 3 commits into from
Sep 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions mbed-os-to-arduino
Original file line number Diff line number Diff line change
Expand Up @@ -198,15 +198,21 @@ generate_flags () {
.pdm_section (NOLOAD) : {\n \
. = ABSOLUTE(0x3800FC00);\n \
*(.pdm_buffer)\n \
} > RAM_D3"
} > RAM_D3\n \
_dtcm_lma = __etext + SIZEOF(.data);\n \
.dtcm : AT(_dtcm_lma) {\n \
_sdtcm = .;\n \
*(.dtcm*)\n \
_edtcm = .;\n \
} > DTCMRAM"
sed -i "s?.heap (COPY):?${OPENAMP_SECTION}\n .heap (COPY):?g" $ARDUINOVARIANT/linker_script.ld
OPENAMP_REGIONS="__OPENAMP_region_start__ = 0x38000400;\n__OPENAMP_region_end__ = 0x38000400 + LENGTH(RAM_D3) - 1K;"
sed -i "s?ENTRY(Reset_Handler)?${OPENAMP_REGIONS}\nENTRY(Reset_Handler)?g" $ARDUINOVARIANT/linker_script.ld
fi
echo "Patching linker scripts"
sed -i 's/0x8100000/CM4_BINARY_START/g' "$ARDUINOVARIANT"/linker_script.ld
sed -i 's/LENGTH = 0x100000/LENGTH = CM4_BINARY_END - CM4_BINARY_START/g' "$ARDUINOVARIANT"/linker_script.ld
sed -i 's/LENGTH = 0xc0000/LENGTH = CM4_BINARY_START - 0x8040000/g' "$ARDUINOVARIANT"/linker_script.ld
sed -i 's/LENGTH = 0x200000/LENGTH = CM4_BINARY_END - CM4_BINARY_START/g' "$ARDUINOVARIANT"/linker_script.ld
sed -i 's/LENGTH = 0x1c0000/LENGTH = CM4_BINARY_START - 0x8040000/g' "$ARDUINOVARIANT"/linker_script.ld
fi
if [[ $ARDUINOVARIANT == *NANO_RP2040* ]]; then
set +e
Expand Down
194 changes: 194 additions & 0 deletions patches/0175-STM32-lpticker-allow-dynamic-configuration.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
From ff38953e8e678c697b52ddbe62bc99fe445a1c74 Mon Sep 17 00:00:00 2001
From: Martino Facchin <m.facchin@arduino.cc>
Date: Thu, 7 Oct 2021 17:00:27 +0200
Subject: [PATCH 175/176] STM32: lpticker: allow dynamic configuration

Step1: allow automatic fallback to LSI if LSE is not functional
Step2: expose two reconfiguration APIs, so the user can check if LSE is precise enough and eventually revert to LSI
---
targets/TARGET_STM/lp_ticker.c | 121 ++++++++++++++++++++++-----------
1 file changed, 83 insertions(+), 38 deletions(-)

diff --git a/targets/TARGET_STM/lp_ticker.c b/targets/TARGET_STM/lp_ticker.c
index d5292566e5..6dc806ccf6 100644
--- a/targets/TARGET_STM/lp_ticker.c
+++ b/targets/TARGET_STM/lp_ticker.c
@@ -126,20 +126,35 @@


LPTIM_HandleTypeDef LptimHandle;
+static uint8_t using_lse = MBED_CONF_TARGET_LSE_AVAILABLE;

-const ticker_info_t *lp_ticker_get_info()
+static const ticker_info_t *lp_ticker_get_info_lse()
{
- static const ticker_info_t info = {
-#if MBED_CONF_TARGET_LSE_AVAILABLE
+ const static ticker_info_t info = {
LSE_VALUE / MBED_CONF_TARGET_LPTICKER_LPTIM_CLOCK,
-#else
+ 16
+ };
+ return &info;
+}
+
+static const ticker_info_t *lp_ticker_get_info_lsi()
+{
+ const static ticker_info_t info = {
LSI_VALUE / MBED_CONF_TARGET_LPTICKER_LPTIM_CLOCK,
-#endif
16
};
return &info;
}

+const ticker_info_t *lp_ticker_get_info()
+{
+ if (using_lse) {
+ return lp_ticker_get_info_lse();
+ } else {
+ return lp_ticker_get_info_lsi();
+ }
+}
+
volatile uint8_t lp_Fired = 0;
/* Flag and stored counter to handle delayed programing at low level */
volatile bool lp_delayed_prog = false;
@@ -154,71 +169,101 @@ volatile bool sleep_manager_locked = false;
static int LPTICKER_inited = 0;
static void LPTIM_IRQHandler(void);

-void lp_ticker_init(void)
-{
- /* Check if LPTIM is already configured */
- if (LPTICKER_inited) {
- lp_ticker_disable_interrupt();
- return;
- }
- LPTICKER_inited = 1;
-
- RCC_PeriphCLKInitTypeDef RCC_PeriphCLKInitStruct = {0};
- RCC_OscInitTypeDef RCC_OscInitStruct = {0};
-
-#if MBED_CONF_TARGET_LSE_AVAILABLE
+static void configureClocksLSE(RCC_PeriphCLKInitTypeDef* RCC_PeriphCLKInitStruct,
+ RCC_OscInitTypeDef* RCC_OscInitStruct){

/* Enable LSE clock */
- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE;
+ RCC_OscInitStruct->OscillatorType = RCC_OSCILLATORTYPE_LSE;
#if MBED_CONF_TARGET_LSE_BYPASS
- RCC_OscInitStruct.LSEState = RCC_LSE_BYPASS;
+ RCC_OscInitStruct->LSEState = RCC_LSE_BYPASS;
#else
- RCC_OscInitStruct.LSEState = RCC_LSE_ON;
+ RCC_OscInitStruct->LSEState = RCC_LSE_ON;
#endif
- RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
+ RCC_OscInitStruct->PLL.PLLState = RCC_PLL_NONE;

/* Select the LSE clock as LPTIM peripheral clock */
- RCC_PeriphCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LPTIM;
+ RCC_PeriphCLKInitStruct->PeriphClockSelection = RCC_PERIPHCLK_LPTIM;
#if (TARGET_STM32L0)
- RCC_PeriphCLKInitStruct.LptimClockSelection = RCC_LPTIMCLKSOURCE_LSE;
+ RCC_PeriphCLKInitStruct->LptimClockSelection = RCC_LPTIMCLKSOURCE_LSE;
#else
#if (LPTIM_MST_BASE == LPTIM1_BASE)
- RCC_PeriphCLKInitStruct.Lptim1ClockSelection = RCC_LPTIMCLKSOURCE_LSE;
+ RCC_PeriphCLKInitStruct->Lptim1ClockSelection = RCC_LPTIMCLKSOURCE_LSE;
#elif (LPTIM_MST_BASE == LPTIM3_BASE) || (LPTIM_MST_BASE == LPTIM4_BASE) || (LPTIM_MST_BASE == LPTIM5_BASE)
- RCC_PeriphCLKInitStruct.Lptim345ClockSelection = RCC_LPTIMCLKSOURCE_LSE;
+ RCC_PeriphCLKInitStruct->Lptim345ClockSelection = RCC_LPTIMCLKSOURCE_LSE;
#endif /* LPTIM_MST_BASE == LPTIM1 */
#endif /* TARGET_STM32L0 */
-#else /* MBED_CONF_TARGET_LSE_AVAILABLE */
+}
+
+static void configureClocksLSI(RCC_PeriphCLKInitTypeDef* RCC_PeriphCLKInitStruct,
+ RCC_OscInitTypeDef* RCC_OscInitStruct){

/* Enable LSI clock */
#if TARGET_STM32WB
- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI1;
+ RCC_OscInitStruct->OscillatorType = RCC_OSCILLATORTYPE_LSI1;
#else
- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI;
+ RCC_OscInitStruct->OscillatorType = RCC_OSCILLATORTYPE_LSI;
#endif
- RCC_OscInitStruct.LSIState = RCC_LSI_ON;
- RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
+ RCC_OscInitStruct->LSIState = RCC_LSI_ON;
+ RCC_OscInitStruct->PLL.PLLState = RCC_PLL_NONE;

/* Select the LSI clock as LPTIM peripheral clock */
- RCC_PeriphCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LPTIM;
+ RCC_PeriphCLKInitStruct->PeriphClockSelection = RCC_PERIPHCLK_LPTIM;
#if (TARGET_STM32L0)
- RCC_PeriphCLKInitStruct.LptimClockSelection = RCC_LPTIMCLKSOURCE_LSI;
+ RCC_PeriphCLKInitStruct->LptimClockSelection = RCC_LPTIMCLKSOURCE_LSI;
#else
#if (LPTIM_MST_BASE == LPTIM1_BASE)
- RCC_PeriphCLKInitStruct.Lptim1ClockSelection = RCC_LPTIMCLKSOURCE_LSI;
+ RCC_PeriphCLKInitStruct->Lptim1ClockSelection = RCC_LPTIMCLKSOURCE_LSI;
#elif (LPTIM_MST_BASE == LPTIM3_BASE) || (LPTIM_MST_BASE == LPTIM4_BASE) || (LPTIM_MST_BASE == LPTIM5_BASE)
- RCC_PeriphCLKInitStruct.Lptim345ClockSelection = RCC_LPTIMCLKSOURCE_LSI;
+ RCC_PeriphCLKInitStruct->Lptim345ClockSelection = RCC_LPTIMCLKSOURCE_LSI;
#endif /* LPTIM_MST_BASE == LPTIM1 */
#endif /* TARGET_STM32L0 */
+}
+
+void lp_ticker_reconfigure_with_lsi() {
+ lp_ticker_disable_interrupt();
+ LPTICKER_inited = 0;
+ using_lse = 0;
+ lp_ticker_init();
+}
+
+void lp_ticker_reconfigure_with_lse() {
+ lp_ticker_disable_interrupt();
+ LPTICKER_inited = 0;
+ using_lse = 1;
+ lp_ticker_init();
+}
+
+void lp_ticker_init(void)
+{
+ /* Check if LPTIM is already configured */
+ if (LPTICKER_inited) {
+ lp_ticker_disable_interrupt();
+ return;
+ }
+ LPTICKER_inited = 1;
+
+ RCC_PeriphCLKInitTypeDef RCC_PeriphCLKInitStruct = {0};
+ RCC_OscInitTypeDef RCC_OscInitStruct = {0};
+
+ if (using_lse) {
+ configureClocksLSE(&RCC_PeriphCLKInitStruct, &RCC_OscInitStruct);
+ } else {
+ configureClocksLSI(&RCC_PeriphCLKInitStruct, &RCC_OscInitStruct);
+ }

-#endif /* MBED_CONF_TARGET_LSE_AVAILABLE */
#if defined(DUAL_CORE) && (TARGET_STM32H7)
while (LL_HSEM_1StepLock(HSEM, CFG_HW_RCC_SEMID)) {
}
#endif /* DUAL_CORE */
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
- error("HAL_RCC_OscConfig ERROR\n");
- return;
+
+ // retry with LSI
+ using_lse = 0;
+ configureClocksLSI(&RCC_PeriphCLKInitStruct, &RCC_OscInitStruct);
+ if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
+ error("HAL_RCC_OscConfig ERROR\n");
+ return;
+ }
}

if (HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphCLKInitStruct) != HAL_OK) {
--
2.37.1

25 changes: 25 additions & 0 deletions patches/0176-Portenta-use-LSE-for-low-power-ticker.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
From 0c7a86e2041971dc3d247c54e85870b6056c03fb Mon Sep 17 00:00:00 2001
From: Martino Facchin <m.facchin@arduino.cc>
Date: Thu, 7 Oct 2021 17:02:45 +0200
Subject: [PATCH 176/176] Portenta: use LSE for low power ticker

---
targets/targets.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/targets/targets.json b/targets/targets.json
index c998e1d8f0..7274f5d03e 100644
--- a/targets/targets.json
+++ b/targets/targets.json
@@ -3483,7 +3483,7 @@
"overrides": {
"system_power_supply": "PWR_SMPS_1V8_SUPPLIES_LDO",
"clock_source": "USE_PLL_HSE_EXTC",
- "lse_available": 0,
+ "lse_available": 1,
"lpticker_delay_ticks": 0,
"network-default-interface-type": "ETHERNET",
"i2c_timing_value_algo": true
--
2.37.1

3 changes: 2 additions & 1 deletion variants/PORTENTA_H7_M7/conf/mbed_app.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
"VIRTIO_MASTER_ONLY",
"NO_ATOMIC_64_SUPPORT",
"METAL_MAX_DEVICE_REGIONS=2",
"RPMSG_BUFFER_SIZE=2048"
"RPMSG_BUFFER_SIZE=2048",
"LSE_STARTUP_TIMEOUT=200"
]
}
}
Expand Down
15 changes: 15 additions & 0 deletions variants/PORTENTA_H7_M7/variant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,8 @@ void fixup3V1Rail() {
i2c.write(8 << 1, data, sizeof(data));
}

extern "C" void lp_ticker_reconfigure_with_lsi();

void initVariant() {
RTCHandle.Instance = RTC;
// Turn off LED from bootloader
Expand All @@ -244,6 +246,19 @@ void initVariant() {
// Disable the FMC bank1 (enabled after reset)
// See https://github.com/STMicroelectronics/STM32CubeH7/blob/beced99ac090fece04d1e0eb6648b8075e156c6c/Projects/STM32H747I-DISCO/Applications/OpenAMP/OpenAMP_RTOS_PingPong/Common/Src/system_stm32h7xx.c#L215
FMC_Bank1_R->BTCR[0] = 0x000030D2;
// Check that the selected lsi clock is ok
if (__HAL_RCC_GET_LPTIM4_SOURCE() == RCC_LPTIM4CLKSOURCE_LSI) {
// rtc is not mounted, no need to do other actions
return;
}
// Use micros() to check the lptim precision
// if the error is > 1% , reconfigure the clock using lsi
uint32_t start_ms = millis();
uint32_t start_us = micros();
while (micros() - start_us < 100000);
if (millis() - start_ms != 100) {
lp_ticker_reconfigure_with_lsi();
}
}

#ifdef SERIAL_CDC
Expand Down