Skip to content

Commit 8282c8b

Browse files
authored
Merge pull request #540 from facchinm/portenta_lse_as_lptimer
Portenta: use LSE as LPTIMER if possible
2 parents 0fadbde + f85b638 commit 8282c8b

5 files changed

+245
-4
lines changed

mbed-os-to-arduino

+9-3
Original file line numberDiff line numberDiff line change
@@ -198,15 +198,21 @@ generate_flags () {
198198
.pdm_section (NOLOAD) : {\n \
199199
. = ABSOLUTE(0x3800FC00);\n \
200200
*(.pdm_buffer)\n \
201-
} > RAM_D3"
201+
} > RAM_D3\n \
202+
_dtcm_lma = __etext + SIZEOF(.data);\n \
203+
.dtcm : AT(_dtcm_lma) {\n \
204+
_sdtcm = .;\n \
205+
*(.dtcm*)\n \
206+
_edtcm = .;\n \
207+
} > DTCMRAM"
202208
sed -i "s?.heap (COPY):?${OPENAMP_SECTION}\n .heap (COPY):?g" $ARDUINOVARIANT/linker_script.ld
203209
OPENAMP_REGIONS="__OPENAMP_region_start__ = 0x38000400;\n__OPENAMP_region_end__ = 0x38000400 + LENGTH(RAM_D3) - 1K;"
204210
sed -i "s?ENTRY(Reset_Handler)?${OPENAMP_REGIONS}\nENTRY(Reset_Handler)?g" $ARDUINOVARIANT/linker_script.ld
205211
fi
206212
echo "Patching linker scripts"
207213
sed -i 's/0x8100000/CM4_BINARY_START/g' "$ARDUINOVARIANT"/linker_script.ld
208-
sed -i 's/LENGTH = 0x100000/LENGTH = CM4_BINARY_END - CM4_BINARY_START/g' "$ARDUINOVARIANT"/linker_script.ld
209-
sed -i 's/LENGTH = 0xc0000/LENGTH = CM4_BINARY_START - 0x8040000/g' "$ARDUINOVARIANT"/linker_script.ld
214+
sed -i 's/LENGTH = 0x200000/LENGTH = CM4_BINARY_END - CM4_BINARY_START/g' "$ARDUINOVARIANT"/linker_script.ld
215+
sed -i 's/LENGTH = 0x1c0000/LENGTH = CM4_BINARY_START - 0x8040000/g' "$ARDUINOVARIANT"/linker_script.ld
210216
fi
211217
if [[ $ARDUINOVARIANT == *NANO_RP2040* ]]; then
212218
set +e
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
From ff38953e8e678c697b52ddbe62bc99fe445a1c74 Mon Sep 17 00:00:00 2001
2+
From: Martino Facchin <[email protected]>
3+
Date: Thu, 7 Oct 2021 17:00:27 +0200
4+
Subject: [PATCH 175/176] STM32: lpticker: allow dynamic configuration
5+
6+
Step1: allow automatic fallback to LSI if LSE is not functional
7+
Step2: expose two reconfiguration APIs, so the user can check if LSE is precise enough and eventually revert to LSI
8+
---
9+
targets/TARGET_STM/lp_ticker.c | 121 ++++++++++++++++++++++-----------
10+
1 file changed, 83 insertions(+), 38 deletions(-)
11+
12+
diff --git a/targets/TARGET_STM/lp_ticker.c b/targets/TARGET_STM/lp_ticker.c
13+
index d5292566e5..6dc806ccf6 100644
14+
--- a/targets/TARGET_STM/lp_ticker.c
15+
+++ b/targets/TARGET_STM/lp_ticker.c
16+
@@ -126,20 +126,35 @@
17+
18+
19+
LPTIM_HandleTypeDef LptimHandle;
20+
+static uint8_t using_lse = MBED_CONF_TARGET_LSE_AVAILABLE;
21+
22+
-const ticker_info_t *lp_ticker_get_info()
23+
+static const ticker_info_t *lp_ticker_get_info_lse()
24+
{
25+
- static const ticker_info_t info = {
26+
-#if MBED_CONF_TARGET_LSE_AVAILABLE
27+
+ const static ticker_info_t info = {
28+
LSE_VALUE / MBED_CONF_TARGET_LPTICKER_LPTIM_CLOCK,
29+
-#else
30+
+ 16
31+
+ };
32+
+ return &info;
33+
+}
34+
+
35+
+static const ticker_info_t *lp_ticker_get_info_lsi()
36+
+{
37+
+ const static ticker_info_t info = {
38+
LSI_VALUE / MBED_CONF_TARGET_LPTICKER_LPTIM_CLOCK,
39+
-#endif
40+
16
41+
};
42+
return &info;
43+
}
44+
45+
+const ticker_info_t *lp_ticker_get_info()
46+
+{
47+
+ if (using_lse) {
48+
+ return lp_ticker_get_info_lse();
49+
+ } else {
50+
+ return lp_ticker_get_info_lsi();
51+
+ }
52+
+}
53+
+
54+
volatile uint8_t lp_Fired = 0;
55+
/* Flag and stored counter to handle delayed programing at low level */
56+
volatile bool lp_delayed_prog = false;
57+
@@ -154,71 +169,101 @@ volatile bool sleep_manager_locked = false;
58+
static int LPTICKER_inited = 0;
59+
static void LPTIM_IRQHandler(void);
60+
61+
-void lp_ticker_init(void)
62+
-{
63+
- /* Check if LPTIM is already configured */
64+
- if (LPTICKER_inited) {
65+
- lp_ticker_disable_interrupt();
66+
- return;
67+
- }
68+
- LPTICKER_inited = 1;
69+
-
70+
- RCC_PeriphCLKInitTypeDef RCC_PeriphCLKInitStruct = {0};
71+
- RCC_OscInitTypeDef RCC_OscInitStruct = {0};
72+
-
73+
-#if MBED_CONF_TARGET_LSE_AVAILABLE
74+
+static void configureClocksLSE(RCC_PeriphCLKInitTypeDef* RCC_PeriphCLKInitStruct,
75+
+ RCC_OscInitTypeDef* RCC_OscInitStruct){
76+
77+
/* Enable LSE clock */
78+
- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE;
79+
+ RCC_OscInitStruct->OscillatorType = RCC_OSCILLATORTYPE_LSE;
80+
#if MBED_CONF_TARGET_LSE_BYPASS
81+
- RCC_OscInitStruct.LSEState = RCC_LSE_BYPASS;
82+
+ RCC_OscInitStruct->LSEState = RCC_LSE_BYPASS;
83+
#else
84+
- RCC_OscInitStruct.LSEState = RCC_LSE_ON;
85+
+ RCC_OscInitStruct->LSEState = RCC_LSE_ON;
86+
#endif
87+
- RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
88+
+ RCC_OscInitStruct->PLL.PLLState = RCC_PLL_NONE;
89+
90+
/* Select the LSE clock as LPTIM peripheral clock */
91+
- RCC_PeriphCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LPTIM;
92+
+ RCC_PeriphCLKInitStruct->PeriphClockSelection = RCC_PERIPHCLK_LPTIM;
93+
#if (TARGET_STM32L0)
94+
- RCC_PeriphCLKInitStruct.LptimClockSelection = RCC_LPTIMCLKSOURCE_LSE;
95+
+ RCC_PeriphCLKInitStruct->LptimClockSelection = RCC_LPTIMCLKSOURCE_LSE;
96+
#else
97+
#if (LPTIM_MST_BASE == LPTIM1_BASE)
98+
- RCC_PeriphCLKInitStruct.Lptim1ClockSelection = RCC_LPTIMCLKSOURCE_LSE;
99+
+ RCC_PeriphCLKInitStruct->Lptim1ClockSelection = RCC_LPTIMCLKSOURCE_LSE;
100+
#elif (LPTIM_MST_BASE == LPTIM3_BASE) || (LPTIM_MST_BASE == LPTIM4_BASE) || (LPTIM_MST_BASE == LPTIM5_BASE)
101+
- RCC_PeriphCLKInitStruct.Lptim345ClockSelection = RCC_LPTIMCLKSOURCE_LSE;
102+
+ RCC_PeriphCLKInitStruct->Lptim345ClockSelection = RCC_LPTIMCLKSOURCE_LSE;
103+
#endif /* LPTIM_MST_BASE == LPTIM1 */
104+
#endif /* TARGET_STM32L0 */
105+
-#else /* MBED_CONF_TARGET_LSE_AVAILABLE */
106+
+}
107+
+
108+
+static void configureClocksLSI(RCC_PeriphCLKInitTypeDef* RCC_PeriphCLKInitStruct,
109+
+ RCC_OscInitTypeDef* RCC_OscInitStruct){
110+
111+
/* Enable LSI clock */
112+
#if TARGET_STM32WB
113+
- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI1;
114+
+ RCC_OscInitStruct->OscillatorType = RCC_OSCILLATORTYPE_LSI1;
115+
#else
116+
- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI;
117+
+ RCC_OscInitStruct->OscillatorType = RCC_OSCILLATORTYPE_LSI;
118+
#endif
119+
- RCC_OscInitStruct.LSIState = RCC_LSI_ON;
120+
- RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
121+
+ RCC_OscInitStruct->LSIState = RCC_LSI_ON;
122+
+ RCC_OscInitStruct->PLL.PLLState = RCC_PLL_NONE;
123+
124+
/* Select the LSI clock as LPTIM peripheral clock */
125+
- RCC_PeriphCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LPTIM;
126+
+ RCC_PeriphCLKInitStruct->PeriphClockSelection = RCC_PERIPHCLK_LPTIM;
127+
#if (TARGET_STM32L0)
128+
- RCC_PeriphCLKInitStruct.LptimClockSelection = RCC_LPTIMCLKSOURCE_LSI;
129+
+ RCC_PeriphCLKInitStruct->LptimClockSelection = RCC_LPTIMCLKSOURCE_LSI;
130+
#else
131+
#if (LPTIM_MST_BASE == LPTIM1_BASE)
132+
- RCC_PeriphCLKInitStruct.Lptim1ClockSelection = RCC_LPTIMCLKSOURCE_LSI;
133+
+ RCC_PeriphCLKInitStruct->Lptim1ClockSelection = RCC_LPTIMCLKSOURCE_LSI;
134+
#elif (LPTIM_MST_BASE == LPTIM3_BASE) || (LPTIM_MST_BASE == LPTIM4_BASE) || (LPTIM_MST_BASE == LPTIM5_BASE)
135+
- RCC_PeriphCLKInitStruct.Lptim345ClockSelection = RCC_LPTIMCLKSOURCE_LSI;
136+
+ RCC_PeriphCLKInitStruct->Lptim345ClockSelection = RCC_LPTIMCLKSOURCE_LSI;
137+
#endif /* LPTIM_MST_BASE == LPTIM1 */
138+
#endif /* TARGET_STM32L0 */
139+
+}
140+
+
141+
+void lp_ticker_reconfigure_with_lsi() {
142+
+ lp_ticker_disable_interrupt();
143+
+ LPTICKER_inited = 0;
144+
+ using_lse = 0;
145+
+ lp_ticker_init();
146+
+}
147+
+
148+
+void lp_ticker_reconfigure_with_lse() {
149+
+ lp_ticker_disable_interrupt();
150+
+ LPTICKER_inited = 0;
151+
+ using_lse = 1;
152+
+ lp_ticker_init();
153+
+}
154+
+
155+
+void lp_ticker_init(void)
156+
+{
157+
+ /* Check if LPTIM is already configured */
158+
+ if (LPTICKER_inited) {
159+
+ lp_ticker_disable_interrupt();
160+
+ return;
161+
+ }
162+
+ LPTICKER_inited = 1;
163+
+
164+
+ RCC_PeriphCLKInitTypeDef RCC_PeriphCLKInitStruct = {0};
165+
+ RCC_OscInitTypeDef RCC_OscInitStruct = {0};
166+
+
167+
+ if (using_lse) {
168+
+ configureClocksLSE(&RCC_PeriphCLKInitStruct, &RCC_OscInitStruct);
169+
+ } else {
170+
+ configureClocksLSI(&RCC_PeriphCLKInitStruct, &RCC_OscInitStruct);
171+
+ }
172+
173+
-#endif /* MBED_CONF_TARGET_LSE_AVAILABLE */
174+
#if defined(DUAL_CORE) && (TARGET_STM32H7)
175+
while (LL_HSEM_1StepLock(HSEM, CFG_HW_RCC_SEMID)) {
176+
}
177+
#endif /* DUAL_CORE */
178+
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
179+
- error("HAL_RCC_OscConfig ERROR\n");
180+
- return;
181+
+
182+
+ // retry with LSI
183+
+ using_lse = 0;
184+
+ configureClocksLSI(&RCC_PeriphCLKInitStruct, &RCC_OscInitStruct);
185+
+ if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
186+
+ error("HAL_RCC_OscConfig ERROR\n");
187+
+ return;
188+
+ }
189+
}
190+
191+
if (HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphCLKInitStruct) != HAL_OK) {
192+
--
193+
2.37.1
194+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
From 0c7a86e2041971dc3d247c54e85870b6056c03fb Mon Sep 17 00:00:00 2001
2+
From: Martino Facchin <[email protected]>
3+
Date: Thu, 7 Oct 2021 17:02:45 +0200
4+
Subject: [PATCH 176/176] Portenta: use LSE for low power ticker
5+
6+
---
7+
targets/targets.json | 2 +-
8+
1 file changed, 1 insertion(+), 1 deletion(-)
9+
10+
diff --git a/targets/targets.json b/targets/targets.json
11+
index c998e1d8f0..7274f5d03e 100644
12+
--- a/targets/targets.json
13+
+++ b/targets/targets.json
14+
@@ -3483,7 +3483,7 @@
15+
"overrides": {
16+
"system_power_supply": "PWR_SMPS_1V8_SUPPLIES_LDO",
17+
"clock_source": "USE_PLL_HSE_EXTC",
18+
- "lse_available": 0,
19+
+ "lse_available": 1,
20+
"lpticker_delay_ticks": 0,
21+
"network-default-interface-type": "ETHERNET",
22+
"i2c_timing_value_algo": true
23+
--
24+
2.37.1
25+

variants/PORTENTA_H7_M7/conf/mbed_app.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
"VIRTIO_MASTER_ONLY",
2323
"NO_ATOMIC_64_SUPPORT",
2424
"METAL_MAX_DEVICE_REGIONS=2",
25-
"RPMSG_BUFFER_SIZE=2048"
25+
"RPMSG_BUFFER_SIZE=2048",
26+
"LSE_STARTUP_TIMEOUT=200"
2627
]
2728
}
2829
}

variants/PORTENTA_H7_M7/variant.cpp

+15
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,8 @@ void fixup3V1Rail() {
235235
i2c.write(8 << 1, data, sizeof(data));
236236
}
237237

238+
extern "C" void lp_ticker_reconfigure_with_lsi();
239+
238240
void initVariant() {
239241
RTCHandle.Instance = RTC;
240242
// Turn off LED from bootloader
@@ -244,6 +246,19 @@ void initVariant() {
244246
// Disable the FMC bank1 (enabled after reset)
245247
// See https://github.com/STMicroelectronics/STM32CubeH7/blob/beced99ac090fece04d1e0eb6648b8075e156c6c/Projects/STM32H747I-DISCO/Applications/OpenAMP/OpenAMP_RTOS_PingPong/Common/Src/system_stm32h7xx.c#L215
246248
FMC_Bank1_R->BTCR[0] = 0x000030D2;
249+
// Check that the selected lsi clock is ok
250+
if (__HAL_RCC_GET_LPTIM4_SOURCE() == RCC_LPTIM4CLKSOURCE_LSI) {
251+
// rtc is not mounted, no need to do other actions
252+
return;
253+
}
254+
// Use micros() to check the lptim precision
255+
// if the error is > 1% , reconfigure the clock using lsi
256+
uint32_t start_ms = millis();
257+
uint32_t start_us = micros();
258+
while (micros() - start_us < 100000);
259+
if (millis() - start_ms != 100) {
260+
lp_ticker_reconfigure_with_lsi();
261+
}
247262
}
248263

249264
#ifdef SERIAL_CDC

0 commit comments

Comments
 (0)