From b1469780670cfdc665305bdd8b6cb21eaaae0823 Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Sat, 15 May 2021 19:49:51 +0000 Subject: [PATCH] Dynamic clock model for RP2040. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@14381 27425a3e-05d8-49a3-a47f-9c15f0e5edd8 --- os/hal/include/hal.h | 11 +--- os/hal/ports/RP/LLD/UARTv1/hal_sio_lld.c | 48 ++------------ os/hal/ports/RP/RP2040/hal_lld.h | 83 +++++++++++++++++++----- os/hal/ports/STM32/STM32G4xx/hal_lld.h | 5 ++ os/hal/templates/hal_lld.h | 5 ++ 5 files changed, 84 insertions(+), 68 deletions(-) diff --git a/os/hal/include/hal.h b/os/hal/include/hal.h index 08f92169d..41ea02454 100644 --- a/os/hal/include/hal.h +++ b/os/hal/include/hal.h @@ -29,6 +29,9 @@ #include "board.h" #include "halconf.h" +/* Low Level HAL support.*/ +#include "hal_lld.h" + /*===========================================================================*/ /* Driver constants. */ /*===========================================================================*/ @@ -192,11 +195,6 @@ /* Driver data structures and types. */ /*===========================================================================*/ -/** - * @brief Type of a clock point identifier. - */ -typedef unsigned halclkpt_t; - /*===========================================================================*/ /* Driver macros. */ /*===========================================================================*/ @@ -252,9 +250,6 @@ static inline halfreq_t halClockGetPointX(halclkpt_t clkpt) { /* Driver late inclusions. */ /*===========================================================================*/ -/* Low Level HAL support.*/ -#include "hal_lld.h" - /* Abstract interfaces.*/ #include "hal_objects.h" #include "hal_streams.h" diff --git a/os/hal/ports/RP/LLD/UARTv1/hal_sio_lld.c b/os/hal/ports/RP/LLD/UARTv1/hal_sio_lld.c index ecf970185..931d3f6c9 100644 --- a/os/hal/ports/RP/LLD/UARTv1/hal_sio_lld.c +++ b/os/hal/ports/RP/LLD/UARTv1/hal_sio_lld.c @@ -117,13 +117,14 @@ __STATIC_INLINE void uart_enable_tx_irq(SIODriver *siop) { * @param[in] siop pointer to a @p SIODriver object */ __STATIC_INLINE void uart_init(SIODriver *siop) { - uint32_t clock, div, idiv, fdiv; + uint32_t div, idiv, fdiv; + halfreq_t clock; - clock = hal_lld_get_clock(clk_peri); + clock = halClockGetPointX(clk_peri); osalDbgAssert(clock > 0U, "no clock"); - div = (8U * clock) / siop->config->baud; + div = (8U * (uint32_t)clock) / siop->config->baud; idiv = div >> 7; fdiv = ((div & 0x7FU) + 1U) / 2U; @@ -135,47 +136,6 @@ __STATIC_INLINE void uart_init(SIODriver *siop) { /* Registers settings, the LCR_H write also latches dividers values.*/ siop->uart->UARTLCR_H = siop->config->UARTLCR_H & ~UART_LCRH_CFG_FORBIDDEN; siop->uart->UARTCR = siop->config->UARTCR & ~UART_CR_CFG_FORBIDDEN; - -#if 0 - USART_TypeDef *u = siop->usart; - uint32_t presc, brr; - - /* Prescaler calculation.*/ - static const uint32_t prescvals[] = {1, 2, 4, 6, 8, 10, 12, 16, 32, 64, 128, 256}; - presc = prescvals[siop->config->presc]; - - /* Baud rate setting.*/ -#if RP_SIO_USE_LPUART1 - if (siop == &LPSIOD1) { - osalDbgAssert((siop->clock >= siop->config->baud * 3U) && - (siop->clock <= siop->config->baud * 4096U), - "invalid baud rate vs input clock"); - - brr = (uint32_t)(((uint64_t)(siop->clock / presc) * (uint64_t)256) / siop->config->baud); - - osalDbgAssert((brr >= 0x300) && (brr < 0x100000), "invalid BRR value"); - } - else -#endif - { - brr = (uint32_t)((siop->clock / presc) / siop->config->baud); - - /* Correcting BRR value when oversampling by 8 instead of 16. - Fraction is still 4 bits wide, but only lower 3 bits used. - Mantissa is doubled, but Fraction is left the same.*/ - if ((siop->config->cr1 & USART_CR1_OVER8) != 0U) { - brr = ((brr & ~7U) * 2U) | (brr & 7U); - } - - osalDbgAssert(brr < 0x10000, "invalid BRR value"); - } - - /* Setting up USART.*/ - u->BRR = brr; - u->CR1 = siop->config->cr1 & ~USART_CR1_CFG_FORBIDDEN; - u->CR2 = siop->config->cr2 & ~USART_CR2_CFG_FORBIDDEN; - u->CR3 = siop->config->cr3 & ~USART_CR3_CFG_FORBIDDEN; -#endif } /*===========================================================================*/ diff --git a/os/hal/ports/RP/RP2040/hal_lld.h b/os/hal/ports/RP/RP2040/hal_lld.h index 0626d3600..2fa9adb79 100644 --- a/os/hal/ports/RP/RP2040/hal_lld.h +++ b/os/hal/ports/RP/RP2040/hal_lld.h @@ -56,6 +56,10 @@ #define RP_ROSCCLK 6500000 /**< 6.5MHz internal clock. */ /** @} */ +/** + * @brief Dynamic clock supported. + */ +#define HAL_LLD_USE_CLOCK_MANAGEMENT /*===========================================================================*/ /* Driver pre-compile time settings. */ @@ -122,23 +126,40 @@ * @name Various clock points. * @{ */ -#define RP_GPOUT0_CLK hal_lld_get_clock(clk_gpout0) -#define RP_GPOUT1_CLK hal_lld_get_clock(clk_gpout1) -#define RP_GPOUT2_CLK hal_lld_get_clock(clk_gpout2) -#define RP_GPOUT3_CLK hal_lld_get_clock(clk_gpout3) -#define RP_REF_CLK hal_lld_get_clock(clk_ref) -#define RP_CORE_CLK hal_lld_get_clock(clk_sys) -#define RP_PERI_CLK hal_lld_get_clock(clk_peri) -#define RP_USB_CLK hal_lld_get_clock(clk_usb) -#define RP_ADC_CLK hal_lld_get_clock(clk_adc) -#define RP_RTC_CLK hal_lld_get_clock(clk_rtc) +#define RP_GPOUT0_CLK hal_lld_get_clock_point(clk_gpout0) +#define RP_GPOUT1_CLK hal_lld_get_clock_point(clk_gpout1) +#define RP_GPOUT2_CLK hal_lld_get_clock_point(clk_gpout2) +#define RP_GPOUT3_CLK hal_lld_get_clock_point(clk_gpout3) +#define RP_REF_CLK hal_lld_get_clock_point(clk_ref) +#define RP_CORE_CLK hal_lld_get_clock_point(clk_sys) +#define RP_PERI_CLK hal_lld_get_clock_point(clk_peri) +#define RP_USB_CLK hal_lld_get_clock_point(clk_usb) +#define RP_ADC_CLK hal_lld_get_clock_point(clk_adc) +#define RP_RTC_CLK hal_lld_get_clock_point(clk_rtc) /** @} */ /*===========================================================================*/ /* Driver data structures and types. */ /*===========================================================================*/ -typedef enum clock_index clock_index_t; +/** + * @brief Type of a clock point identifier. + */ +typedef enum clock_index halclkpt_t; + +#if defined(HAL_LLD_USE_CLOCK_MANAGEMENT) || defined(__DOXYGEN__) +/** + * @brief Type of a clock point frequency in Hz. + */ +typedef uint32_t halfreq_t; + +/** + * @brief Type of a clock configuration structure. + */ +typedef struct { + uint32_t dummy; +} halclkcfg_t; +#endif /* defined(HAL_LLD_USE_CLOCK_MANAGEMENT) */ /*===========================================================================*/ /* Driver macros. */ @@ -167,11 +188,6 @@ extern "C" { /* Driver inline functions. */ /*===========================================================================*/ -__STATIC_INLINE uint32_t hal_lld_get_clock(clock_index_t clk_index) { - - return clock_get_hz(clk_index); -} - __STATIC_INLINE void hal_lld_peripheral_reset(uint32_t mask) { RESETS->RESET |= mask; @@ -185,6 +201,41 @@ __STATIC_INLINE void hal_lld_peripheral_unreset(uint32_t mask) { } } +#if defined(HAL_LLD_USE_CLOCK_MANAGEMENT) || defined(__DOXYGEN__) +/** + * @brief Switches to a different clock configuration + * + * @param[in] ccp pointer to clock a @p halclkcfg_t structure + * @return The clock switch result. + * @retval false if the clock switch succeeded + * @retval true if the clock switch failed + * + * @notapi + */ +__STATIC_INLINE bool hal_lld_clock_switch_mode(const halclkcfg_t *ccp) { + + (void)ccp; + + return false; +} + +/** + * @brief Returns the frequency of a clock point in Hz. + * + * @param[in] clkpt clock point to be returned + * @return The clock point frequency in Hz or zero if the + * frequency is unknown. + * + * @notapi + */ +__STATIC_INLINE halfreq_t hal_lld_get_clock_point(halclkpt_t clkpt) { + + osalDbgAssert(clkpt < CLK_COUNT, "invalid clock point"); + + return clock_get_hz(clkpt); +} +#endif /* defined(HAL_LLD_USE_CLOCK_MANAGEMENT) */ + #endif /* HAL_LLD_H */ /** @} */ diff --git a/os/hal/ports/STM32/STM32G4xx/hal_lld.h b/os/hal/ports/STM32/STM32G4xx/hal_lld.h index 652d3de6a..19a9db32c 100644 --- a/os/hal/ports/STM32/STM32G4xx/hal_lld.h +++ b/os/hal/ports/STM32/STM32G4xx/hal_lld.h @@ -1542,6 +1542,11 @@ /* Driver data structures and types. */ /*===========================================================================*/ +/** + * @brief Type of a clock point identifier. + */ +typedef unsigned halclkpt_t; + #if defined(HAL_LLD_USE_CLOCK_MANAGEMENT) || defined(__DOXYGEN__) /** * @brief Type of a clock point frequency in Hz. diff --git a/os/hal/templates/hal_lld.h b/os/hal/templates/hal_lld.h index d68ac355b..8cb098ab6 100644 --- a/os/hal/templates/hal_lld.h +++ b/os/hal/templates/hal_lld.h @@ -66,6 +66,11 @@ /* Driver data structures and types. */ /*===========================================================================*/ +/** + * @brief Type of a clock point identifier. + */ +typedef unsigned halclkpt_t; + #if defined(HAL_LLD_USE_CLOCK_MANAGEMENT) || defined(__DOXYGEN__) /** * @brief Type of a clock point frequency in Hz.