Dynamic clock model for RP2040.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@14381 27425a3e-05d8-49a3-a47f-9c15f0e5edd8
This commit is contained in:
Giovanni Di Sirio 2021-05-15 19:49:51 +00:00
parent 2d4e29da76
commit b146978067
5 changed files with 84 additions and 68 deletions

View File

@ -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"

View File

@ -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
}
/*===========================================================================*/

View File

@ -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 */
/** @} */

View File

@ -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.

View File

@ -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.