Skip to content

Commit 1b84618

Browse files
kamnxtjhedberg
authored andcommitted
drivers: timer: stm32_lptim: Support all LPTIM instances
The LPTIM timer driver previously had hardcoded assumptions about using LPTIM1 or LPTIM3, which prevented it from working with other LPTIM instances like LPTIM2, LPTIM4, LPTIM5, and LPTIM6. This change makes the driver work with any LPTIM instance by: 1. Adding lptim_enable_autonomous_mode() function that dynamically detects which LPTIM instance is in use and enables autonomous mode for instances that support it (LPTIM1, LPTIM3, LPTIM4). LPTIM2, LPTIM5, LPTIM6 do not support autonomous mode. 2. Adding lptim_freeze_during_debug() function that handles debug freeze configuration for all LPTIM instances across different APB buses: - LPTIM1: APB1_GRP1, APB3_GRP1, or APB7_GRP1 - LPTIM2: APB1_GRP1, APB1_GRP2, APB3_GRP1, or APB4_GRP1 - LPTIM3: APB1_GRP2, APB3_GRP1, or APB4_GRP1 - LPTIM4: APB3_GRP1 or APB4_GRP1 - LPTIM5: APB3_GRP1 - LPTIM6: APB3_GRP1 Both functions use DT_REG_ADDR() to compare the base address of the configured LPTIM instance at compile time, ensuring zero runtime overhead. Tested on STM32U5A5 with all four LPTIM instances (LPTIM1-4). Signed-off-by: Kamil Krzyżanowski <[email protected]>
1 parent 26ca2cf commit 1b84618

File tree

1 file changed

+121
-11
lines changed

1 file changed

+121
-11
lines changed

drivers/timer/stm32_lptim_timer.c

Lines changed: 121 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,123 @@ static const struct device *stdby_timer = DEVICE_DT_GET(DT_CHOSEN(st_lptim_stdby
9898

9999
#endif /* CONFIG_STM32_LPTIM_STDBY_TIMER */
100100

101+
/**
102+
* @brief Enable autonomous clock for the LPTIM instance in use
103+
*
104+
* Enables autonomous mode (if supported) for whichever LPTIM instance
105+
* is configured as the system timer. This allows the LPTIM to continue
106+
* running in low power modes.
107+
*/
108+
static void lptim_enable_autonomous_mode(void)
109+
{
110+
const uint32_t lptim_base = (uint32_t)LPTIM;
111+
112+
switch (lptim_base) {
113+
#if DT_NODE_EXISTS(DT_NODELABEL(lptim1)) && defined(LL_SRDAMR_GRP1_PERIPH_LPTIM1AMEN)
114+
case DT_REG_ADDR(DT_NODELABEL(lptim1)):
115+
LL_SRDAMR_GRP1_EnableAutonomousClock(LL_SRDAMR_GRP1_PERIPH_LPTIM1AMEN);
116+
break;
117+
#endif
118+
#if DT_NODE_EXISTS(DT_NODELABEL(lptim3)) && defined(LL_SRDAMR_GRP1_PERIPH_LPTIM3AMEN)
119+
case DT_REG_ADDR(DT_NODELABEL(lptim3)):
120+
LL_SRDAMR_GRP1_EnableAutonomousClock(LL_SRDAMR_GRP1_PERIPH_LPTIM3AMEN);
121+
break;
122+
#endif
123+
#if DT_NODE_EXISTS(DT_NODELABEL(lptim4)) && defined(LL_SRDAMR_GRP1_PERIPH_LPTIM4AMEN)
124+
case DT_REG_ADDR(DT_NODELABEL(lptim4)):
125+
LL_SRDAMR_GRP1_EnableAutonomousClock(LL_SRDAMR_GRP1_PERIPH_LPTIM4AMEN);
126+
break;
127+
#endif
128+
default:
129+
/* Note: LPTIM2, LPTIM5, LPTIM6 do not support autonomous mode */
130+
break;
131+
}
132+
}
133+
134+
/**
135+
* @brief Freeze LPTIM during debug for the instance in use
136+
*
137+
* Configures the debug subsystem to freeze the LPTIM counter when the CPU
138+
* is halted in a debugger. Handles all LPTIM instances across different buses.
139+
*/
140+
static void lptim_freeze_during_debug(void)
141+
{
142+
#ifdef CONFIG_DEBUG
143+
const uint32_t lptim_base = (uint32_t)LPTIM;
144+
145+
switch (lptim_base) {
146+
/* LPTIM1 - can be on APB1_GRP1, APB3_GRP1, or APB7_GRP1 */
147+
#if DT_NODE_EXISTS(DT_NODELABEL(lptim1))
148+
case DT_REG_ADDR(DT_NODELABEL(lptim1)):
149+
#if defined(LL_DBGMCU_APB1_GRP1_LPTIM1_STOP)
150+
LL_DBGMCU_APB1_GRP1_FreezePeriph(LL_DBGMCU_APB1_GRP1_LPTIM1_STOP);
151+
#elif defined(LL_DBGMCU_APB3_GRP1_LPTIM1_STOP)
152+
LL_DBGMCU_APB3_GRP1_FreezePeriph(LL_DBGMCU_APB3_GRP1_LPTIM1_STOP);
153+
#elif defined(LL_DBGMCU_APB7_GRP1_LPTIM1_STOP)
154+
LL_DBGMCU_APB7_GRP1_FreezePeriph(LL_DBGMCU_APB7_GRP1_LPTIM1_STOP);
155+
#endif
156+
break;
157+
#endif
158+
/* LPTIM2 - can be on APB1_GRP1, APB1_GRP2, APB3_GRP1, or APB4_GRP1 */
159+
#if DT_NODE_EXISTS(DT_NODELABEL(lptim2))
160+
case DT_REG_ADDR(DT_NODELABEL(lptim2)):
161+
#if defined(LL_DBGMCU_APB1_GRP1_LPTIM2_STOP)
162+
LL_DBGMCU_APB1_GRP1_FreezePeriph(LL_DBGMCU_APB1_GRP1_LPTIM2_STOP);
163+
#elif defined(LL_DBGMCU_APB1_GRP2_LPTIM2_STOP)
164+
LL_DBGMCU_APB1_GRP2_FreezePeriph(LL_DBGMCU_APB1_GRP2_LPTIM2_STOP);
165+
#elif defined(LL_DBGMCU_APB3_GRP1_LPTIM2_STOP)
166+
LL_DBGMCU_APB3_GRP1_FreezePeriph(LL_DBGMCU_APB3_GRP1_LPTIM2_STOP);
167+
#elif defined(LL_DBGMCU_APB4_GRP1_LPTIM2_STOP)
168+
LL_DBGMCU_APB4_GRP1_FreezePeriph(LL_DBGMCU_APB4_GRP1_LPTIM2_STOP);
169+
#endif
170+
break;
171+
#endif
172+
/* LPTIM3 - can be on APB1_GRP2, APB3_GRP1, or APB4_GRP1 */
173+
#if DT_NODE_EXISTS(DT_NODELABEL(lptim3))
174+
case DT_REG_ADDR(DT_NODELABEL(lptim3)):
175+
#if defined(LL_DBGMCU_APB1_GRP2_LPTIM3_STOP)
176+
LL_DBGMCU_APB1_GRP2_FreezePeriph(LL_DBGMCU_APB1_GRP2_LPTIM3_STOP);
177+
#elif defined(LL_DBGMCU_APB3_GRP1_LPTIM3_STOP)
178+
LL_DBGMCU_APB3_GRP1_FreezePeriph(LL_DBGMCU_APB3_GRP1_LPTIM3_STOP);
179+
#elif defined(LL_DBGMCU_APB4_GRP1_LPTIM3_STOP)
180+
LL_DBGMCU_APB4_GRP1_FreezePeriph(LL_DBGMCU_APB4_GRP1_LPTIM3_STOP);
181+
#endif
182+
break;
183+
#endif
184+
/* LPTIM4 - can be on APB3_GRP1 or APB4_GRP1 */
185+
#if DT_NODE_EXISTS(DT_NODELABEL(lptim4))
186+
case DT_REG_ADDR(DT_NODELABEL(lptim4)):
187+
#if defined(LL_DBGMCU_APB3_GRP1_LPTIM4_STOP)
188+
LL_DBGMCU_APB3_GRP1_FreezePeriph(LL_DBGMCU_APB3_GRP1_LPTIM4_STOP);
189+
#elif defined(LL_DBGMCU_APB4_GRP1_LPTIM4_STOP)
190+
LL_DBGMCU_APB4_GRP1_FreezePeriph(LL_DBGMCU_APB4_GRP1_LPTIM4_STOP);
191+
#endif
192+
break;
193+
#endif
194+
/* LPTIM5 - can be on APB3_GRP1 or APB4_GRP1 */
195+
#if DT_NODE_EXISTS(DT_NODELABEL(lptim5))
196+
case DT_REG_ADDR(DT_NODELABEL(lptim5)): {
197+
#if defined(LL_DBGMCU_APB3_GRP1_LPTIM5_STOP)
198+
LL_DBGMCU_APB3_GRP1_FreezePeriph(LL_DBGMCU_APB3_GRP1_LPTIM5_STOP);
199+
#elif defined(LL_DBGMCU_APB4_GRP1_LPTIM5_STOP)
200+
LL_DBGMCU_APB4_GRP1_FreezePeriph(LL_DBGMCU_APB4_GRP1_LPTIM5_STOP);
201+
#endif
202+
}
203+
#endif
204+
/* LPTIM6 - on APB3_GRP1 */
205+
#if DT_NODE_EXISTS(DT_NODELABEL(lptim6))
206+
case DT_REG_ADDR(DT_NODELABEL(lptim6)):
207+
#if defined(LL_DBGMCU_APB3_GRP1_LPTIM6_STOP)
208+
LL_DBGMCU_APB3_GRP1_FreezePeriph(LL_DBGMCU_APB3_GRP1_LPTIM6_STOP);
209+
#endif
210+
break;
211+
#endif
212+
default:
213+
break;
214+
}
215+
#endif /* CONFIG_DEBUG */
216+
}
217+
101218
static inline bool arrm_state_get(void)
102219
{
103220
return (LL_LPTIM_IsActiveFlag_ARRM(LPTIM) && LL_LPTIM_IsEnabledIT_ARRM(LPTIM));
@@ -411,9 +528,8 @@ static int sys_clock_driver_init(void)
411528
return -EIO;
412529
}
413530

414-
#if defined(LL_SRDAMR_GRP1_PERIPH_LPTIM1AMEN)
415-
LL_SRDAMR_GRP1_EnableAutonomousClock(LL_SRDAMR_GRP1_PERIPH_LPTIM1AMEN);
416-
#endif
531+
/* Enable autonomous mode for the LPTIM instance in use */
532+
lptim_enable_autonomous_mode();
417533

418534
/* Enable LPTIM clock source */
419535
err = clock_control_configure(clk_ctrl,
@@ -564,15 +680,9 @@ static int sys_clock_driver_init(void)
564680
/* Start the LPTIM counter in continuous mode */
565681
LL_LPTIM_StartCounter(LPTIM, LL_LPTIM_OPERATING_MODE_CONTINUOUS);
566682

567-
#ifdef CONFIG_DEBUG
568-
/* stop LPTIM during DEBUG */
569-
#if defined(LL_DBGMCU_APB1_GRP1_LPTIM1_STOP)
570-
LL_DBGMCU_APB1_GRP1_FreezePeriph(LL_DBGMCU_APB1_GRP1_LPTIM1_STOP);
571-
#elif defined(LL_DBGMCU_APB3_GRP1_LPTIM1_STOP)
572-
LL_DBGMCU_APB3_GRP1_FreezePeriph(LL_DBGMCU_APB3_GRP1_LPTIM1_STOP);
573-
#endif
683+
/* Freeze LPTIM during debug */
684+
lptim_freeze_during_debug();
574685

575-
#endif
576686
return 0;
577687
}
578688

0 commit comments

Comments
 (0)