From 7b35715ee4c789afcae620e5c66390878038e19b Mon Sep 17 00:00:00 2001 From: Silvano Seva Date: Sat, 23 Nov 2024 17:25:20 +0100 Subject: [PATCH] STM32H7: driver for LPTIM peripheral --- platform/mcu/STM32H7xx/drivers/Lptim.hpp | 115 +++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 platform/mcu/STM32H7xx/drivers/Lptim.hpp diff --git a/platform/mcu/STM32H7xx/drivers/Lptim.hpp b/platform/mcu/STM32H7xx/drivers/Lptim.hpp new file mode 100644 index 00000000..b4bba392 --- /dev/null +++ b/platform/mcu/STM32H7xx/drivers/Lptim.hpp @@ -0,0 +1,115 @@ +/*************************************************************************** + * Copyright (C) 2024 by Federico Amedeo Izzo IU2NUO, * + * Niccolò Izzo IU2KIN * + * Frederik Saraci IU2NRO * + * Silvano Seva IU2KWO * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, see * + ***************************************************************************/ + +#ifndef LPTIM_H +#define LPTIM_H + +/** + * Handler class for STM32H7 LPTIM peripheral. + */ +class Lptim +{ +public: + + /** + * Constructor. + * + * @param tim: base address of timer peripheral to manage. + * @param baseFreq: timer base input frequency, in Hz. + */ + constexpr Lptim(const uint32_t tim, const uint32_t baseFreq) : tim(tim), + baseFreq(baseFreq) {} + + ~Lptim() = default; + + /** + * Configure timer prescaler and auto-reload registers for a given update + * frequency. + * + * @param updFreq: desidered update frequency, in Hz. + * @return effective timer update frequency, in Hz. + */ + uint32_t setUpdateFrequency(const uint32_t updFreq) const + { + /* + * Timer update frequency is given by: + * Fupd = (Fbus / prescaler) / autoreload + * + * In LPTIM the prescaler can only assume values being powers of two up + * to 128. To find the correct prescaler and autoreload values we start + * by setting the the prescaler to 1 and proceed iteratively until the + * autoreload value is less than the maximum allowed. + */ + uint32_t div; + uint32_t arr; + uint32_t psc; + for(div = 0; div < 8; div += 1) + { + psc = 1 << div; + arr = (baseFreq / psc) / updFreq; + if(arr < 0xFFFF) + break; + } + + // Timer needs to be enabled before configuring the other registers. + reinterpret_cast< LPTIM_TypeDef * >(tim)->CR = LPTIM_CR_ENABLE; + reinterpret_cast< LPTIM_TypeDef * >(tim)->CFGR = div << 9; + reinterpret_cast< LPTIM_TypeDef * >(tim)->ARR = arr - 1; + + return (baseFreq / psc) / arr; + } + + /** + * Clear and start the timer's counter. + */ + inline void start() const + { + reinterpret_cast< LPTIM_TypeDef * >(tim)->CNT = 0; + reinterpret_cast< LPTIM_TypeDef * >(tim)->CR |= LPTIM_CR_CNTSTRT; + } + + /** + * Stop the timer's counter. + */ + inline void stop() const + { + // It seems that the only way to stop the LPTIM is to turn it off. Then + // we have to turn it on again to allow writing the configuration registers. + reinterpret_cast< LPTIM_TypeDef * >(tim)->CR = 0; + reinterpret_cast< LPTIM_TypeDef * >(tim)->CR = LPTIM_CR_ENABLE; + } + + /** + * Get current value of timer's counter. + * + * @return value of timer's counter. + */ + inline uint16_t value() const + { + return reinterpret_cast< LPTIM_TypeDef * >(tim)->CNT = 0; + } + +private: + + const uint32_t tim; + const uint32_t baseFreq; +}; + +#endif /* LPTIM_H */