From a76e0ccc2794686407840b11093d460a0ba29825 Mon Sep 17 00:00:00 2001 From: "Kate J. Temkin" Date: Tue, 18 Sep 2018 22:45:15 -0600 Subject: [PATCH] firmware: report timings for more oscillator events --- firmware/common/greatfet_core.c | 51 ++++++++++++++++++++++++++------- firmware/common/time.c | 6 ++-- firmware/common/time.h | 4 +-- 3 files changed, 45 insertions(+), 16 deletions(-) diff --git a/firmware/common/greatfet_core.c b/firmware/common/greatfet_core.c index 58a590c7..c9da04e1 100644 --- a/firmware/common/greatfet_core.c +++ b/firmware/common/greatfet_core.c @@ -210,6 +210,11 @@ Configure PLL1 to max speed (204MHz). Note: PLL1 clock is used by M4/M0 core, Peripheral, APB1. */ void cpu_clock_init(void) { + uint32_t time_base = 0, elapsed; + + debug_init(); + pr_info("GreatFET started!\n"); + /* If we've been asked to reset in order to switch to using an external * clock (e.g. for synchronization with other systems), use the GP_CLKIN * instead of the XTAL as the main system clock source. */ @@ -219,7 +224,6 @@ void cpu_clock_init(void) // And set our main clock source to the extclk. main_clock_source = CGU_SRC_GP_CLKIN; - } // TODO: Figure out a place to do this explicitly? @@ -227,6 +231,9 @@ void cpu_clock_init(void) // reason in the future. reset_reason = RESET_REASON_UNKNOWN; + /* For now, no matter what, start our "wall clock" timer. */ + set_up_microsecond_timer(12); // count microseconds from our 12MHz timer + /* use IRC as clock source for APB1 (including I2C0) */ CGU_BASE_APB1_CLK = CGU_BASE_APB1_CLK_CLK_SEL(CGU_SRC_IRC); @@ -237,18 +244,27 @@ void cpu_clock_init(void) /* set xtal oscillator to low frequency mode */ if(main_clock_source == CGU_SRC_XTAL) { - CGU_XTAL_OSC_CTRL &= ~CGU_XTAL_OSC_CTRL_HF_MASK; + pr_info("Bootstrapping the system clock off of the external 12MHz oscillator.\n"); + time_base = get_time(); + + CGU_XTAL_OSC_CTRL &= ~CGU_XTAL_OSC_CTRL_HF_MASK; - /* power on the oscillator and wait until stable */ - CGU_XTAL_OSC_CTRL &= ~CGU_XTAL_OSC_CTRL_ENABLE_MASK; + /* power on the oscillator and wait until stable */ + CGU_XTAL_OSC_CTRL &= ~CGU_XTAL_OSC_CTRL_ENABLE_MASK; - /* Wait about 100us after Crystal Power ON */ - delay(WAIT_CPU_CLOCK_INIT_DELAY); + /* Wait about 100us after Crystal Power ON */ + delay(WAIT_CPU_CLOCK_INIT_DELAY); } /* use XTAL_OSC as clock source for BASE_M4_CLK (CPU) */ CGU_BASE_M4_CLK = (CGU_BASE_M4_CLK_CLK_SEL(main_clock_source) | CGU_BASE_M4_CLK_AUTOBLOCK(1)); + /* if we've brought up the XTAL, report the time it took. */ + if (main_clock_source == CGU_SRC_XTAL) { + elapsed = get_time_since(time_base); + pr_info("External oscillator bringup complete (took %d uS).\n", elapsed); + } + /* use XTAL_OSC as clock source for APB1 */ CGU_BASE_APB1_CLK = CGU_BASE_APB1_CLK_AUTOBLOCK(1) | CGU_BASE_APB1_CLK_CLK_SEL(main_clock_source); @@ -323,10 +339,6 @@ void cpu_clock_init(void) CGU_BASE_SSP1_CLK = CGU_BASE_SSP1_CLK_AUTOBLOCK(1) | CGU_BASE_SSP1_CLK_CLK_SEL(CGU_SRC_PLL1); - - /* For now, no matter what, start our "wall clock" timer. */ - set_up_microsecond_timer(); - } @@ -339,6 +351,10 @@ This function is mainly used to lower power consumption. void cpu_clock_pll1_low_speed(void) { uint32_t pll_reg; + uint32_t time_base, elapsed; + + pr_info("Switching the system clock to PLL1 at 48MHz.\n"); + time_base = get_time(); /* Configure PLL1 Clock (48MHz) */ /* Integer mode: @@ -362,8 +378,13 @@ void cpu_clock_pll1_low_speed(void) /* wait until stable */ while (!(CGU_PLL1_STAT & CGU_PLL1_STAT_LOCK_MASK)); + set_up_microsecond_timer(48); // update the wall clock time to track our 48mhz timer + /* Wait a delay after switch to new frequency with Direct mode */ delay(WAIT_CPU_CLOCK_INIT_DELAY); + + elapsed = get_time_since(time_base); + pr_info("Clock switch complete (took %d uS).\n", elapsed); } /* @@ -374,6 +395,10 @@ This function shall be called after cpu_clock_init(). void cpu_clock_pll1_max_speed(void) { uint32_t pll_reg; + uint32_t time_base, elapsed; + + pr_info("Switching the system clock to PLL1 at 204MHz.\n"); + time_base = get_time(); /* Configure PLL1 to Intermediate Clock (between 90 MHz and 110 MHz) */ /* Integer mode: @@ -418,6 +443,10 @@ void cpu_clock_pll1_max_speed(void) /* wait until stable */ while (!(CGU_PLL1_STAT & CGU_PLL1_STAT_LOCK_MASK)); + set_up_microsecond_timer(204); // update the wall clock time to track our 204mhz main frequency + + elapsed = get_time_since(time_base); + pr_info("Clock switch complete (took %d uS).\n", elapsed); } bool validate_32khz_oscillator() @@ -469,7 +498,7 @@ void rtc_init(void) { RTC_CCR |= RTC_CCR_CLKEN(1); elapsed = get_time_since(time_base); - pr_info("RTC bringup complete (took %d mS).\n", elapsed / 1000); + pr_info("RTC bringup complete (took %d uS).\n", elapsed); } else { pr_warning("RTC oscillator did not come up in a reasonable time!\n"); } diff --git a/firmware/common/time.c b/firmware/common/time.c index 395aaf22..edd329f1 100644 --- a/firmware/common/time.c +++ b/firmware/common/time.c @@ -14,10 +14,10 @@ * * Currently must be called while on the faster clock speed. */ -void set_up_microsecond_timer(void) +void set_up_microsecond_timer(uint32_t m4_clk_mhz) { - // Set up TIMER3 to count microseconds. - timer_set_prescaler(TIMER3, 203); + // Set up TIMER3 to count microseconds. + timer_set_prescaler(TIMER3, m4_clk_mhz - 1); timer_enable_counter(TIMER3); } diff --git a/firmware/common/time.h b/firmware/common/time.h index c76fe9a9..de6a2740 100644 --- a/firmware/common/time.h +++ b/firmware/common/time.h @@ -15,9 +15,9 @@ * Initialization function for the GreatFET microsecond timer, which is used * to track total seconds while the GreatFET is running. * - * Currently must be called while on the faster clock speed. + * @param The frequency, in MHz, that the main M4 clock is running at. */ -void set_up_microsecond_timer(void); +void set_up_microsecond_timer(uint32_t m4_clk_mhz); /** * @returns the total number of microseconds since this timer was initialized.