diff --git a/Libraries/PeriphDrivers/Include/MAX32657/mxc_sys.h b/Libraries/PeriphDrivers/Include/MAX32657/mxc_sys.h index d1c88f6dae..f30d7eea92 100644 --- a/Libraries/PeriphDrivers/Include/MAX32657/mxc_sys.h +++ b/Libraries/PeriphDrivers/Include/MAX32657/mxc_sys.h @@ -26,6 +26,7 @@ #include "mxc_device.h" #include "gcr_regs.h" +#include "fcr_regs.h" #ifdef __cplusplus extern "C" { @@ -115,6 +116,13 @@ typedef enum { MXC_SYS_CLOCK_DIV_128 = MXC_S_GCR_CLKCTRL_SYSCLK_DIV_DIV128 } mxc_sys_system_clock_div_t; +/** @brief Compare clock enumeration. Used in MXC_SYS_ClockMeasure function. */ +typedef enum { + MXC_SYS_COMPARE_CLOCK_RTC = MXC_S_FCR_FRQCNTCTRL_CMP_CLKSEL_RTC, + MXC_SYS_COMPARE_CLOCK_EXT_GPIO = MXC_S_FCR_FRQCNTCTRL_CMP_CLKSEL_EXT_GPIO, + MXC_SYS_COMPARE_CLOCK_INRO = MXC_S_FCR_FRQCNTCTRL_CMP_CLKSEL_INRO +} mxc_sys_compare_clock_t; + #define MXC_SYS_USN_CHECKSUM_LEN 16 // Length of the USN + padding for checksum compute #define MXC_SYS_USN_CSUM_FIELD_LEN 2 // Size of the checksum field in the USN #define MXC_SYS_USN_LEN 13 // Size of the USN including the checksum @@ -348,6 +356,18 @@ uint32_t MXC_SYS_RiscVClockRate(void); */ int MXC_SYS_LockDAP_Permanent(void); +/** + * @brief Measure the clock frequency. + * + * @details Assumes that measurement clock and ERFO are enabled. + * Increasing compareClockTicks will provide a more accurate measurement, + * but there are limits that could cause overflow. + * + * @param clock Enumeration for which clock to measure. + * @param compareClockTicks Number of ticks of the comparison clock to use for measurement. + */ +uint32_t MXC_SYS_ClockMeasure(mxc_sys_compare_clock_t clock, uint32_t compareClockTicks); + #ifdef __cplusplus } #endif diff --git a/Libraries/PeriphDrivers/Source/SYS/sys_me30.c b/Libraries/PeriphDrivers/Source/SYS/sys_me30.c index ee45aa55f6..bab9148853 100644 --- a/Libraries/PeriphDrivers/Source/SYS/sys_me30.c +++ b/Libraries/PeriphDrivers/Source/SYS/sys_me30.c @@ -543,4 +543,36 @@ int MXC_SYS_LockDAP_Permanent(void) } #endif +/* ************************************************************************** */ +uint32_t MXC_SYS_ClockMeasure(mxc_sys_compare_clock_t clock, uint32_t compareClockTicks) +{ + /* Assuming that both clocks are already enabled */ + + /* Setup the comparison clock */ + MXC_FCR->frqcntctrl = (MXC_FCR->frqcntctrl & ~(MXC_F_FCR_FRQCNTCTRL_CMP_CLKSEL)) | clock; + + /* Set ticks of the comparison clock */ + MXC_FCR->frqcntcmp = compareClockTicks; + + /* + * Enable interrupt, note that we don't see the flag if we leave + * this disabled. + */ + MXC_FCR->inten |= MXC_F_FCR_INTFL_FRQCNT; + + /* Clear the interrupt flag */ + MXC_FCR->intfl = MXC_F_FCR_INTFL_FRQCNT; + + /* Start the procedure */ + MXC_FCR->frqcntctrl |= MXC_F_FCR_FRQCNTCTRL_START; + + /* Wait for the procedure to finish */ + while (!(MXC_FCR->intfl & MXC_F_FCR_INTFL_FRQCNT)) {} + + /* Calculate the frequency */ + uint64_t freq = (uint64_t)ERFO_FREQ * (uint64_t)MXC_FCR->cmpclk / (uint64_t)MXC_FCR->refclk; + + return (uint32_t)freq; +} + /**@} end of mxc_sys */