From 24ed48d93a71b0a7d6a27f3492efa80429dc1278 Mon Sep 17 00:00:00 2001 From: TitanMKD Date: Wed, 28 Aug 2013 22:01:57 +0200 Subject: [PATCH] Fix for "issues/62 fix PLL1 overclock bug" see hackrf_core.c -> cpu_clock_init() Fix for "issues/78 startup current too high" see hackrf_core.c -> New functions cpu_clock_pll1_low_speed()/cpu_clock_pll1_max_speed() & hackrf_usb.c to switch low_speed/max_speed. --- firmware/common/hackrf_core.c | 160 +++++++++++++++++++++++++++---- firmware/common/hackrf_core.h | 2 + firmware/hackrf_usb/hackrf_usb.c | 11 ++- 3 files changed, 151 insertions(+), 22 deletions(-) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index ef8d118d..e6d2aa24 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -31,6 +31,8 @@ #include #include +#define WAIT_CPU_CLOCK_INIT_DELAY (10000) + void delay(uint32_t duration) { uint32_t i; @@ -232,9 +234,13 @@ bool baseband_filter_bandwidth_set(const uint32_t bandwidth_hz) { return max2837_set_lpf_bandwidth(bandwidth_hz); } -/* clock startup for Jellybean with Lemondrop attached */ +/* clock startup for Jellybean with Lemondrop attached +Configure PLL1 to max speed (204MHz). +Note: PLL1 clock is used by M4/M0 core, Peripheral, APB1. */ void cpu_clock_init(void) { + uint32_t pll_reg; + /* use IRC as clock source for APB1 (including I2C0) */ CGU_BASE_APB1_CLK = CGU_BASE_APB1_CLK_CLK_SEL(CGU_SRC_IRC); @@ -328,36 +334,59 @@ void cpu_clock_init(void) /* power on the oscillator and wait until stable */ CGU_XTAL_OSC_CTRL &= ~CGU_XTAL_OSC_CTRL_ENABLE; + /* 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(CGU_SRC_XTAL); + CGU_BASE_M4_CLK = (CGU_BASE_M4_CLK_CLK_SEL(CGU_SRC_XTAL) | CGU_BASE_M4_CLK_AUTOBLOCK); /* use XTAL_OSC as clock source for APB1 */ CGU_BASE_APB1_CLK = CGU_BASE_APB1_CLK_AUTOBLOCK | CGU_BASE_APB1_CLK_CLK_SEL(CGU_SRC_XTAL); - /* use XTAL_OSC as clock source for PLL1 */ - /* Start PLL1 at 12MHz * 17 / (2+2) = 51MHz. */ - CGU_PLL1_CTRL = CGU_PLL1_CTRL_CLK_SEL(CGU_SRC_XTAL) - | CGU_PLL1_CTRL_PSEL(1) - | CGU_PLL1_CTRL_NSEL(0) - | CGU_PLL1_CTRL_MSEL(16) - | CGU_PLL1_CTRL_PD; - - /* power on PLL1 and wait until stable */ - CGU_PLL1_CTRL &= ~CGU_PLL1_CTRL_PD; + /* Configure PLL1 to Intermediate Clock (between 90 MHz and 110 MHz) */ + /* Integer mode: + FCLKOUT = M*(FCLKIN/N) + FCCO = 2*P*FCLKOUT = 2*P*M*(FCLKIN/N) + */ + pll_reg = CGU_PLL1_CTRL; + /* Clear PLL1 bits */ + pll_reg &= ~( CGU_PLL1_CTRL_CLK_SEL_MASK | CGU_PLL1_CTRL_PD | CGU_PLL1_CTRL_FBSEL | /* CLK SEL, PowerDown , FBSEL */ + CGU_PLL1_CTRL_BYPASS | /* BYPASS */ + CGU_PLL1_CTRL_DIRECT | /* DIRECT */ + CGU_PLL1_CTRL_PSEL_MASK | CGU_PLL1_CTRL_MSEL_MASK | CGU_PLL1_CTRL_NSEL_MASK ); /* PSEL, MSEL, NSEL- divider ratios */ + /* Set PLL1 up to 12MHz * 8 = 96MHz. */ + pll_reg |= CGU_PLL1_CTRL_CLK_SEL(CGU_SRC_XTAL) + | CGU_PLL1_CTRL_PSEL(0) + | CGU_PLL1_CTRL_NSEL(0) + | CGU_PLL1_CTRL_MSEL(7) + | CGU_PLL1_CTRL_FBSEL; + CGU_PLL1_CTRL = pll_reg; + /* wait until stable */ while (!(CGU_PLL1_STAT & CGU_PLL1_STAT_LOCK)); /* use PLL1 as clock source for BASE_M4_CLK (CPU) */ - CGU_BASE_M4_CLK = CGU_BASE_M4_CLK_CLK_SEL(CGU_SRC_PLL1); + CGU_BASE_M4_CLK = (CGU_BASE_M4_CLK_CLK_SEL(CGU_SRC_PLL1) | CGU_BASE_M4_CLK_AUTOBLOCK); - /* Move PLL1 up to 12MHz * 17 = 204MHz. */ - CGU_PLL1_CTRL = CGU_PLL1_CTRL_CLK_SEL(CGU_SRC_XTAL) - | CGU_PLL1_CTRL_PSEL(0) - | CGU_PLL1_CTRL_NSEL(0) + /* Wait before to switch to max speed */ + delay(WAIT_CPU_CLOCK_INIT_DELAY); + + /* Configure PLL1 Max Speed */ + /* Direct mode: FCLKOUT = FCCO = M*(FCLKIN/N) */ + pll_reg = CGU_PLL1_CTRL; + /* Clear PLL1 bits */ + pll_reg &= ~( CGU_PLL1_CTRL_CLK_SEL_MASK | CGU_PLL1_CTRL_PD | CGU_PLL1_CTRL_FBSEL | /* CLK SEL, PowerDown , FBSEL */ + CGU_PLL1_CTRL_BYPASS | /* BYPASS */ + CGU_PLL1_CTRL_DIRECT | /* DIRECT */ + CGU_PLL1_CTRL_PSEL_MASK | CGU_PLL1_CTRL_MSEL_MASK | CGU_PLL1_CTRL_NSEL_MASK ); /* PSEL, MSEL, NSEL- divider ratios */ + /* Set PLL1 up to 12MHz * 17 = 204MHz. */ + pll_reg |= CGU_PLL1_CTRL_CLK_SEL(CGU_SRC_XTAL) + | CGU_PLL1_CTRL_PSEL(0) + | CGU_PLL1_CTRL_NSEL(0) | CGU_PLL1_CTRL_MSEL(16) - | CGU_PLL1_CTRL_FBSEL; - //| CGU_PLL1_CTRL_DIRECT; - + | CGU_PLL1_CTRL_FBSEL + | CGU_PLL1_CTRL_DIRECT; + CGU_PLL1_CTRL = pll_reg; /* wait until stable */ while (!(CGU_PLL1_STAT & CGU_PLL1_STAT_LOCK)); @@ -393,6 +422,97 @@ void cpu_clock_init(void) | CGU_BASE_APB1_CLK_CLK_SEL(CGU_SRC_PLL1); } + +/* +Configure PLL1 to low speed (48MHz). +Note: PLL1 clock is used by M4/M0 core, Peripheral, APB1. +This function shall be called after cpu_clock_init(). +This function is mainly used to lower power consumption. +*/ +void cpu_clock_pll1_low_speed(void) +{ + uint32_t pll_reg; + + /* Configure PLL1 Clock (48MHz) */ + /* Integer mode: + FCLKOUT = M*(FCLKIN/N) + FCCO = 2*P*FCLKOUT = 2*P*M*(FCLKIN/N) + */ + pll_reg = CGU_PLL1_CTRL; + /* Clear PLL1 bits */ + pll_reg &= ~( CGU_PLL1_CTRL_CLK_SEL_MASK | CGU_PLL1_CTRL_PD | CGU_PLL1_CTRL_FBSEL | /* CLK SEL, PowerDown , FBSEL */ + CGU_PLL1_CTRL_BYPASS | /* BYPASS */ + CGU_PLL1_CTRL_DIRECT | /* DIRECT */ + CGU_PLL1_CTRL_PSEL_MASK | CGU_PLL1_CTRL_MSEL_MASK | CGU_PLL1_CTRL_NSEL_MASK ); /* PSEL, MSEL, NSEL- divider ratios */ + /* Set PLL1 up to 12MHz * 7 = 48MHz. */ + pll_reg |= CGU_PLL1_CTRL_CLK_SEL(CGU_SRC_XTAL) + | CGU_PLL1_CTRL_PSEL(0) + | CGU_PLL1_CTRL_NSEL(0) + | CGU_PLL1_CTRL_MSEL(6) + | CGU_PLL1_CTRL_FBSEL + | CGU_PLL1_CTRL_DIRECT; + CGU_PLL1_CTRL = pll_reg; + /* wait until stable */ + while (!(CGU_PLL1_STAT & CGU_PLL1_STAT_LOCK)); + + /* Wait a delay after switch to new frequency with Direct mode */ + delay(WAIT_CPU_CLOCK_INIT_DELAY); +} + +/* +Configure PLL1 (Main MCU Clock) to max speed (204MHz). +Note: PLL1 clock is used by M4/M0 core, Peripheral, APB1. +This function shall be called after cpu_clock_init(). +*/ +void cpu_clock_pll1_max_speed(void) +{ + uint32_t pll_reg; + + /* Configure PLL1 to Intermediate Clock (between 90 MHz and 110 MHz) */ + /* Integer mode: + FCLKOUT = M*(FCLKIN/N) + FCCO = 2*P*FCLKOUT = 2*P*M*(FCLKIN/N) + */ + pll_reg = CGU_PLL1_CTRL; + /* Clear PLL1 bits */ + pll_reg &= ~( CGU_PLL1_CTRL_CLK_SEL_MASK | CGU_PLL1_CTRL_PD | CGU_PLL1_CTRL_FBSEL | /* CLK SEL, PowerDown , FBSEL */ + CGU_PLL1_CTRL_BYPASS | /* BYPASS */ + CGU_PLL1_CTRL_DIRECT | /* DIRECT */ + CGU_PLL1_CTRL_PSEL_MASK | CGU_PLL1_CTRL_MSEL_MASK | CGU_PLL1_CTRL_NSEL_MASK ); /* PSEL, MSEL, NSEL- divider ratios */ + /* Set PLL1 up to 12MHz * 8 = 96MHz. */ + pll_reg |= CGU_PLL1_CTRL_CLK_SEL(CGU_SRC_XTAL) + | CGU_PLL1_CTRL_PSEL(0) + | CGU_PLL1_CTRL_NSEL(0) + | CGU_PLL1_CTRL_MSEL(7) + | CGU_PLL1_CTRL_FBSEL; + CGU_PLL1_CTRL = pll_reg; + /* wait until stable */ + while (!(CGU_PLL1_STAT & CGU_PLL1_STAT_LOCK)); + + /* Wait before to switch to max speed */ + delay(WAIT_CPU_CLOCK_INIT_DELAY); + + /* Configure PLL1 Max Speed */ + /* Direct mode: FCLKOUT = FCCO = M*(FCLKIN/N) */ + pll_reg = CGU_PLL1_CTRL; + /* Clear PLL1 bits */ + pll_reg &= ~( CGU_PLL1_CTRL_CLK_SEL_MASK | CGU_PLL1_CTRL_PD | CGU_PLL1_CTRL_FBSEL | /* CLK SEL, PowerDown , FBSEL */ + CGU_PLL1_CTRL_BYPASS | /* BYPASS */ + CGU_PLL1_CTRL_DIRECT | /* DIRECT */ + CGU_PLL1_CTRL_PSEL_MASK | CGU_PLL1_CTRL_MSEL_MASK | CGU_PLL1_CTRL_NSEL_MASK ); /* PSEL, MSEL, NSEL- divider ratios */ + /* Set PLL1 up to 12MHz * 17 = 204MHz. */ + pll_reg |= CGU_PLL1_CTRL_CLK_SEL(CGU_SRC_XTAL) + | CGU_PLL1_CTRL_PSEL(0) + | CGU_PLL1_CTRL_NSEL(0) + | CGU_PLL1_CTRL_MSEL(16) + | CGU_PLL1_CTRL_FBSEL + | CGU_PLL1_CTRL_DIRECT; + CGU_PLL1_CTRL = pll_reg; + /* wait until stable */ + while (!(CGU_PLL1_STAT & CGU_PLL1_STAT_LOCK)); + +} + void ssp1_init(void) { /* diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index 5752da00..cc772293 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -251,6 +251,8 @@ typedef enum { void delay(uint32_t duration); void cpu_clock_init(void); +void cpu_clock_pll1_low_speed(void); +void cpu_clock_pll1_max_speed(void); void ssp1_init(void); void ssp1_set_mode_max2837(void); void ssp1_set_mode_max5864(void); diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index e4cd3da3..986992dd 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -911,11 +911,17 @@ bool usb_set_configuration( if( new_configuration == 0 ) { return false; } - } + }else + { + /* Configuration number equal 0 means usb bus reset, + set MCU freq to low power consumption */ + cpu_clock_pll1_low_speed(); + } if( new_configuration != device->configuration ) { // Configuration changed. device->configuration = new_configuration; + cpu_clock_pll1_max_speed(); /* Switch MCU clock to max speed */ set_transceiver_mode(transceiver_mode); if( device->configuration ) { @@ -997,7 +1003,8 @@ int main(void) { pin_setup(); enable_1v8_power(); cpu_clock_init(); - + cpu_clock_pll1_low_speed(); + usb_peripheral_reset(); usb_device_init(0, &usb_device);