This is an automated email from the ASF dual-hosted git repository. andk pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
commit 23e34b1c44d943cefd5b27a103fbef41b383e215 Author: Andrzej Kaczmarek <andrzej.kaczma...@codecoup.pl> AuthorDate: Tue Aug 1 12:51:51 2023 +0200 hw/mcu/dialog: Trim RC32K during calibration This updates RC32K calibration routine to also trim it to run close to target value of 32KHz. --- hw/mcu/dialog/da1469x/src/da1469x_clock.c | 75 ++++++++++++++++++++++++++++++- hw/mcu/dialog/da1469x/syscfg.yml | 6 +++ 2 files changed, 80 insertions(+), 1 deletion(-) diff --git a/hw/mcu/dialog/da1469x/src/da1469x_clock.c b/hw/mcu/dialog/da1469x/src/da1469x_clock.c index c40e05c82..bcd10d88a 100644 --- a/hw/mcu/dialog/da1469x/src/da1469x_clock.c +++ b/hw/mcu/dialog/da1469x/src/da1469x_clock.c @@ -208,10 +208,83 @@ da1469x_clock_lp_rcx_calibrate(void) da1469x_clock_calibrate(3, MYNEWT_VAL(MCU_CLOCK_RCX_CAL_REF_CNT)); } +#define RC32K_TARGET_FREQ 32000 +#define RC32K_TRIM_MIN 0 +#define RC32K_TRIM_MAX 15 + +static inline uint32_t +rc32k_trim_get(void) +{ + return (CRG_TOP->CLK_RC32K_REG & CRG_TOP_CLK_RC32K_REG_RC32K_TRIM_Msk) >> + CRG_TOP_CLK_RC32K_REG_RC32K_TRIM_Pos; +} + +static inline void +rc32k_trim_set(uint32_t trim) +{ + CRG_TOP->CLK_RC32K_REG = + (CRG_TOP->CLK_RC32K_REG & ~CRG_TOP_CLK_RC32K_REG_RC32K_TRIM_Msk) | + (trim << CRG_TOP_CLK_RC32K_REG_RC32K_TRIM_Pos); +} + void da1469x_clock_lp_rc32k_calibrate(void) { - g_mcu_clock_rc32k_freq = da1469x_clock_calibrate(0, 100); + uint32_t trim; + uint32_t trim_prev; + uint32_t freq; + uint32_t freq_prev; + uint32_t freq_delta; + uint32_t freq_delta_prev; + bool trim_ok; + + if (!(CRG_TOP->CLK_RC32K_REG & CRG_TOP_CLK_RC32K_REG_RC32K_ENABLE_Msk)) { + return; + } + + freq = 0; + freq_delta = INT32_MAX; + + trim = rc32k_trim_get(); + trim_prev = trim; + trim_ok = false; + + do { + freq_prev = freq; + freq_delta_prev = freq_delta; + + freq = da1469x_clock_calibrate(0, MYNEWT_VAL(MCU_CLOCK_RC32K_CAL_REF_CNT)); + + freq_delta = freq - RC32K_TARGET_FREQ; + freq_delta = (int32_t)freq_delta < 0 ? -freq_delta : freq_delta; + + if (freq_delta > freq_delta_prev) { + /* Previous trim value was closer to target frequency, use it */ + freq = freq_prev; + rc32k_trim_set(trim_prev); + trim_ok = true; + } else if (freq > RC32K_TARGET_FREQ) { + /* Decrease trim value if possible */ + if (trim > RC32K_TRIM_MIN) { + trim_prev = trim; + rc32k_trim_set(--trim); + } else { + trim_ok = true; + } + } else if (freq < RC32K_TARGET_FREQ) { + /* Increase trim value if possible */ + if (trim < RC32K_TRIM_MAX) { + trim_prev = trim; + rc32k_trim_set(++trim); + } else { + trim_ok = true; + } + } else { + trim_ok = true; + } + } while (!trim_ok); + + g_mcu_clock_rc32k_freq = freq; } void diff --git a/hw/mcu/dialog/da1469x/syscfg.yml b/hw/mcu/dialog/da1469x/syscfg.yml index eb2b642c7..5e808b69b 100644 --- a/hw/mcu/dialog/da1469x/syscfg.yml +++ b/hw/mcu/dialog/da1469x/syscfg.yml @@ -77,6 +77,12 @@ syscfg.defs: value: 100 restrictions: '!0' + MCU_CLOCK_RC32K_CAL_REF_CNT: + description: > + Reference count value for calibration of RC32K clock. + value: 1 + restrictions: '!0' + MCU_SYSCLK_SOURCE: description: > Specifies system clock source