Skip to content

arch/arm/stm32h5: Add LPTIM support - #19959

Merged
xiaoxiang781216 merged 3 commits into
apache:masterfrom
liam-geotab:stm32h5-lptim
Aug 25, 2026
Merged

arch/arm/stm32h5: Add LPTIM support#19959
xiaoxiang781216 merged 3 commits into
apache:masterfrom
liam-geotab:stm32h5-lptim

Conversation

@liam-geotab

Copy link
Copy Markdown
Contributor

Summary

Add LPTIM support.

The implementation is based on STM32H7. setperiod and setcompare have been made to wait for the auto-reload value to apply before returning.

STM32H5 has 6 LPTIMs. LPTIM2 has an incomplete implementation. It is in a different RCC APBx register than the other LPTIMs. Without contact with the author, I decided not to assume it's trivial to add without thorough testing so I left it as-is. The build fails if LPTIM2 is enabled so it's not a silent gap. I can try to add it, if that is the maintainers' wish. Supporting LPTIM6 would require the common configs to have LPTIM6 added.

Some STM32H5 RCC definitions have been corrected. It's necessary for the clock source selection that a user would do before using the STM32 LPTIM API.

Also add a missing CMakeLists.txt change that should have been in #19914

Impact

The changes are only additive except for RCC definition corrections.

LPTIM2 complete implementation is missing. LPTIM6 needs a common config added for it.

Testing

Nothing in the nuttx tree calls stm32_lptim_init so here is how LPTIM has been sourced by the LSE (low speed external) clock to be used for the nuttx system tick on custom hardware. There is live adjustment of the timer period to deal with LSE modulo 100 Hz != 0.

nsh> uptime
00:00:03 up  0:00, load average: 0.00, 0.00, 0.00
nsh> uptime
00:00:05 up  0:00, load average: 0.00, 0.00, 0.00
nsh> uptime
00:26:33 up  0:26, load average: 0.00, 0.00, 0.00

Enable CONFIG_STM32_LPTIM1 and override arch/arm/src/stm32h5/stm32_timerisr.c or modify it to use LPTIM1 as the tick source:

#define SYSTICK_RELOAD_EXCESS_DIV	4	//Both CLK_TCK and EXCESS must be divisible by this value!
#define SYSTICK_RELOAD (STM32_LSE_FREQUENCY / CLK_TCK)
#define SYSTICK_RELOAD_EXCESS (((SYSTICK_RELOAD + 1) * CLK_TCK) - STM32_LSE_FREQUENCY)
#define SYSTICK_RELOAD_REDUCED (SYSTICK_RELOAD - (SYSTICK_RELOAD_EXCESS / SYSTICK_RELOAD_EXCESS_DIV))
#if ((CLK_TCK % SYSTICK_RELOAD_EXCESS_DIV) != 0)
#error "CLK_TCK not divisible by SYSTICK_RELOAD_EXCESS_DIV"
#endif
#if ((SYSTICK_RELOAD_EXCESS % SYSTICK_RELOAD_EXCESS_DIV) != 0)
#error "SYSTICK_RELOAD_EXCESS not divisible by SYSTICK_RELOAD_EXCESS_DIV"
#endif

int stm32_timerisr_counter = 0;
static int stm32_timerisr(int irq, void * regs, void * arg)
{
	struct stm32_lptim_dev_s * lptimer = arg;
	stm32_timerisr_counter++;

	/* Process timer interrupt */
	if (stm32_timerisr_counter >= (CLK_TCK / SYSTICK_RELOAD_EXCESS_DIV))
	{
		stm32_timerisr_counter = 0;
		lptimer->ops->setperiod(lptimer, SYSTICK_RELOAD_REDUCED);
	}
	else if (stm32_timerisr_counter == 1)
	{
		lptimer->ops->setperiod(lptimer, SYSTICK_RELOAD);
	}

	nxsched_process_timer();

	lptimer->ops->ackint(lptimer, LPTIM_ISR_ARRM | LPTIM_ISR_CMPM);
	return 0;
}

void up_timer_initialize(void)
{
	struct stm32_lptim_dev_s * lptimer;

	stm32_rcc_enablelse();	//Enable the LSE clock input

	// Enable LPTIM1 peripheral clock FIRST before configuring clock source
	modifyreg32(STM32_RCC_APB3ENR, 0, RCC_APB3ENR_LPTIM1EN);

	// Now configure clock source to LSE
	modifyreg32(STM32_RCC_CCIPR2, RCC_CCIPR2_LPTIM1SEL_MASK, RCC_CCIPR2_LPTIM1SEL_LSEKERCK);	//Set LPTIM1 clock source as LSE
	modifyreg32(STM32_RCC_APB3LPENR, 0, RCC_APB3LPENR_LPTIM1LPEN);	//Set LPTIM1 to remain enabled in STOP mode
	

	lptimer = stm32_lptim_init(1);	//Init LPTIMER1 (this also enables the clock, but it's safe to enable twice)

	// For STM32H5: Must enable timer BEFORE writing ARR in continuous mode
	lptimer->ops->setcfgr(lptimer, 0);
	lptimer->ops->enable(lptimer, true);  // Enable FIRST
	lptimer->ops->setperiod(lptimer, SYSTICK_RELOAD);  // Then set ARR (ARROK wait happens inside)

	lptimer->ops->setisr(lptimer, stm32_timerisr, lptimer, 0);
	lptimer->ops->enableint(lptimer, LPTIM_ISR_ARRM);
	lptimer->ops->start(lptimer, STM32_LPTIM_MODE_CONTINUOUS);
}

@github-actions github-actions Bot added Area: Documentation Improvements or additions to documentation Arch: arm Issues related to ARM (32-bit) architecture Size: L The size of the change in this PR is large Board: arm labels Aug 24, 2026
liam-geotab and others added 3 commits August 24, 2026 16:11
Add LPTIM 1, 3, 4, 5 support. Based on STM32H7. setperiod and
setcompare have been made to wait for the auto-reload value to
be applied before returning.

6 is absent since generic stm32 configs for a 6th LPTIM are not
present yet. 2 is absent for no good reason besides maybe
that it's in a different RCC APB register. I am not adding
support last-minute without more testing. The build fails
noisily when LPTIM2 is enabled so the shortcoming is clear.

Corrected some RCC definitions. They are needed for selecting the LPTIMx
clock source. This is not done in the LPTIM driver. It is done
outside and the definitions should ideally be correct for that.

Signed-off-by: Liam Howatt <liamhowatt@geotab.com>
Co-authored-by: Farzan Farhangian <farzanfarhangian@geotab.com>
Change to 'Yes' in the platform peripheral list and
give the file path in the porting guide/status.

Signed-off-by: Liam Howatt <liamhowatt@geotab.com>
SPI support was added to nucleo-h563zi without the CMakeLists.txt
SRCS list being updated to build stm32_spi.c. Add it.

Signed-off-by: Liam Howatt <liamhowatt@geotab.com>
@github-actions

Copy link
Copy Markdown

MemBrowse Memory Report

No memory changes detected for:

@xiaoxiang781216
xiaoxiang781216 merged commit 21a99f9 into apache:master Aug 25, 2026
39 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Arch: arm Issues related to ARM (32-bit) architecture Area: Documentation Improvements or additions to documentation Board: arm Size: L The size of the change in this PR is large

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants