This is an automated email from the ASF dual-hosted git repository. linguini1 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 10dea61e2320b0b1ddfb3ea386de1be205e71994 Author: Kerogit <[email protected]> AuthorDate: Thu Mar 5 11:04:36 2026 +0100 arch/avr/src/avrdx: add support for reading CPU clock from other sources This patch adds support for reading CPU clock frequency when the MCU is driven by clock source other than high frequency oscillator. Signed-off-by: Kerogit <[email protected]> --- arch/avr/src/avrdx/avrdx.h | 24 ++++++- arch/avr/src/avrdx/avrdx_peripherals.c | 111 +++++++++++++++++++++++++++------ arch/avr/src/avrdx/iodefs/avr128da28.h | 10 +++ arch/avr/src/avrdx/iodefs/avr128da64.h | 10 +++ arch/avr/src/avrdx/iodefs/avr128db64.h | 10 +++ 5 files changed, 143 insertions(+), 22 deletions(-) diff --git a/arch/avr/src/avrdx/avrdx.h b/arch/avr/src/avrdx/avrdx.h index 84efae45da9..88a2c413454 100644 --- a/arch/avr/src/avrdx/avrdx.h +++ b/arch/avr/src/avrdx/avrdx.h @@ -94,15 +94,33 @@ void up_clkinitialize(void); * Name: avrdx_current_freq_per * * Description: - * Calculate and return current f_per + * Calculate and return current f_per (peripheral clock frequency) * - * Assumptions: - * Main clock source is internal oscillator + * Returned Value: frequency in Hz. + * + * Assumptions/Limitations: + * Main clock must not be driven by external clock. * ****************************************************************************/ uint32_t avrdx_current_freq_per(void); +/**************************************************************************** + * Name: avrdx_current_freq_cpu + * + * Description: + * Calculate and return current f_cpu (CPU frequency). Returns value + * of avrdx_current_freq_per because both clocks are identical. + * + * Returned Value: frequency in Hz + * + * Assumptions/Limitations: + * Main clock must not be driven by external clock. + * + ****************************************************************************/ + +uint32_t avrdx_current_freq_cpu(void); + /**************************************************************************** * Name: up_consoleinit * diff --git a/arch/avr/src/avrdx/avrdx_peripherals.c b/arch/avr/src/avrdx/avrdx_peripherals.c index a7442280f39..7de37e38fd6 100644 --- a/arch/avr/src/avrdx/avrdx_peripherals.c +++ b/arch/avr/src/avrdx/avrdx_peripherals.c @@ -301,11 +301,36 @@ const IOBJ uint8_t avrdx_usart_portmux_masks[] = ****************************************************************************/ /**************************************************************************** - * Public Functions - ****************************************************************************/ + * Name: avrdx_current_freq_main_prescaler + * + * Description: + * Reduces given frequency by main clock prescaler. + * + * Input Parameters: + * frequency - input frequency + * + * Return value: output frequency in Hz + */ + +uint32_t avrdx_current_freq_main_prescaler(uint32_t frequency) +{ + uint8_t mclkctrlb; + uint8_t pdiv; + + /* Read this once, no point in re-reading */ + + mclkctrlb = CLKCTRL.MCLKCTRLB; + if (mclkctrlb & CLKCTRL_PEN_bm) + { + pdiv = (mclkctrlb & CLKCTRL_PDIV_GM) >> CLKCTRL_PDIV_GP; + frequency /= avrdx_main_pdiv[pdiv]; + } + + return frequency; +} /**************************************************************************** - * Name: avrdx_current_freq_per + * Name: avrdx_current_freq_per_oschf * * Description: * Calculate and return current f_per (peripheral clock frequency) @@ -315,15 +340,13 @@ const IOBJ uint8_t avrdx_usart_portmux_masks[] = * ****************************************************************************/ -uint32_t avrdx_current_freq_per() +uint32_t avrdx_current_freq_per_oschf(void) { uint32_t f_per; /* Shortcut variables */ uint8_t frqsel; - uint8_t pdiv; - uint8_t mclkctrlb; /* Calculate frequency in MHz, then divide it by main prescaler, * if set. @@ -332,23 +355,73 @@ uint32_t avrdx_current_freq_per() frqsel = (CLKCTRL.OSCHFCTRLA & CLKCTRL_FRQSEL_GM) >> CLKCTRL_FRQSEL_GP; f_per = 1000000UL * avrdx_frqsel_mhz[frqsel]; - /* Read this once, no point in re-reading */ + return avrdx_current_freq_main_prescaler(f_per); +} - mclkctrlb = CLKCTRL.MCLKCTRLB; - if (mclkctrlb & CLKCTRL_PEN_bm) +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: avrdx_current_freq_per + * + * Description: + * Calculate and return current f_per (peripheral clock frequency) + * + * Returned Value: frequency in Hz. + * + * Assumptions/Limitations: + * Main clock must not be driven by external clock. + * + ****************************************************************************/ + +uint32_t avrdx_current_freq_per(void) +{ + uint8_t mclkctrla; + + mclkctrla = CLKCTRL.MCLKCTRLA & CLKCTRL_CLKSEL_GM; + + /* Using if - else to deal with the most likely case first */ + + if (mclkctrla == CLKCTRL_CLKSEL_OSCHF_GC) { - pdiv = (mclkctrlb & CLKCTRL_PDIV_GM) >> CLKCTRL_PDIV_GP; - f_per /= avrdx_main_pdiv[pdiv]; + /* Internal high frequency oscillator */ + + return avrdx_current_freq_per_oschf(); + } + else if ((mclkctrla == CLKCTRL_CLKSEL_OSC32K_GC) || \ + (mclkctrla == CLKCTRL_CLKSEL_XOSC32K_GC)) + { + /* 32768 oscillator or external oscillator/crystal. + * Only apply the prescaler. + */ + + return avrdx_current_freq_main_prescaler(32768); } - /* Currently, rest of the code only supports internal oscillator - * and its frequency is pre-set using Kconfig. Nevertheless, that - * can change at some point and this function accounts for some - * of that. - * - * It doesn't account for the chip being clocked by external source - * though, that's to be done. + /* External clock. This is not supported and we can not determine + * the frequency. This will likely cause a failure (unless the caller + * has this case handled using other means.) */ - return f_per; + return 0; +} + +/**************************************************************************** + * Name: avrdx_current_freq_cpu + * + * Description: + * Calculate and return current f_cpu (CPU frequency). Returns value + * of avrdx_current_freq_per because both clocks are identical. + * + * Returned Value: frequency in Hz + * + * Assumptions/Limitations: + * Main clock must not be driven by external clock. + * + ****************************************************************************/ + +uint32_t avrdx_current_freq_cpu(void) +{ + return avrdx_current_freq_per(); } diff --git a/arch/avr/src/avrdx/iodefs/avr128da28.h b/arch/avr/src/avrdx/iodefs/avr128da28.h index 6dbc143bc35..abb16bcd5ce 100644 --- a/arch/avr/src/avrdx/iodefs/avr128da28.h +++ b/arch/avr/src/avrdx/iodefs/avr128da28.h @@ -64,6 +64,16 @@ #define PORT_ISC_BOTHEDGES_GC ( PORT_ISC_0_bm ) +/* CLKCTRL.MCLKCTRLA */ + +#define CLKCTRL_CLKSEL_GM ( CLKCTRL_CLKSEL_0_bm | CLKCTRL_CLKSEL_1_bm | \ + CLKCTRL_CLKSEL_2_bm ) + +#define CLKCTRL_CLKSEL_OSCHF_GC (0) +#define CLKCTRL_CLKSEL_OSC32K_GC ( CLKCTRL_CLKSEL_0_bm ) +#define CLKCTRL_CLKSEL_XOSC32K_GC ( CLKCTRL_CLKSEL_1_bm ) +#define CLKCTRL_CLKSEL_EXTCLK_GC ( CLKCTRL_CLKSEL_0_bm | CLKCTRL_CLKSEL_1_bm ) + /* CLKCTRL.MCLKCTRLB */ #define CLKCTRL_PDIV_GM ( CLKCTRL_PDIV_0_bm | CLKCTRL_PDIV_1_bm | \ diff --git a/arch/avr/src/avrdx/iodefs/avr128da64.h b/arch/avr/src/avrdx/iodefs/avr128da64.h index f00fef5bbce..8ce2e251e07 100644 --- a/arch/avr/src/avrdx/iodefs/avr128da64.h +++ b/arch/avr/src/avrdx/iodefs/avr128da64.h @@ -89,6 +89,16 @@ #define PORT_ISC_BOTHEDGES_GC ( PORT_ISC_0_bm ) +/* CLKCTRL.MCLKCTRLA */ + +#define CLKCTRL_CLKSEL_gm ( CLKCTRL_CLKSEL_0_bm | CLKCTRL_CLKSEL_1_bm | \ + CLKCTRL_CLKSEL_2_bm ) + +#define CLKCTRL_CLKSEL_OSCHF_GC (0) +#define CLKCTRL_CLKSEL_OSC32K_GC ( CLKCTRL_CLKSEL_0_bm ) +#define CLKCTRL_CLKSEL_XOSC32K_GC ( CLKCTRL_CLKSEL_1_bm ) +#define CLKCTRL_CLKSEL_EXTCLK_GC ( CLKCTRL_CLKSEL_0_bm | CLKCTRL_CLKSEL_1_bm ) + /* CLKCTRL.MCLKCTRLB */ #define CLKCTRL_PDIV_GM ( CLKCTRL_PDIV_0_bm | CLKCTRL_PDIV_1_bm | \ diff --git a/arch/avr/src/avrdx/iodefs/avr128db64.h b/arch/avr/src/avrdx/iodefs/avr128db64.h index 6bd0456f6ca..7fa48d80050 100644 --- a/arch/avr/src/avrdx/iodefs/avr128db64.h +++ b/arch/avr/src/avrdx/iodefs/avr128db64.h @@ -89,6 +89,16 @@ #define PORT_ISC_BOTHEDGES_GC ( PORT_ISC_0_bm ) +/* CLKCTRL.MCLKCTRLA */ + +#define CLKCTRL_CLKSEL_gm ( CLKCTRL_CLKSEL_0_bm | CLKCTRL_CLKSEL_1_bm | \ + CLKCTRL_CLKSEL_2_bm ) + +#define CLKCTRL_CLKSEL_OSCHF_GC (0) +#define CLKCTRL_CLKSEL_OSC32K_GC ( CLKCTRL_CLKSEL_0_bm ) +#define CLKCTRL_CLKSEL_XOSC32K_GC ( CLKCTRL_CLKSEL_1_bm ) +#define CLKCTRL_CLKSEL_EXTCLK_GC ( CLKCTRL_CLKSEL_0_bm | CLKCTRL_CLKSEL_1_bm ) + /* CLKCTRL.MCLKCTRLB */ #define CLKCTRL_PDIV_GM ( CLKCTRL_PDIV_0_bm | CLKCTRL_PDIV_1_bm | \
