From c827bb4177702ce202ca3c966f3ce7564444df5b Mon Sep 17 00:00:00 2001 From: Me No Dev Date: Thu, 20 Dec 2018 01:57:32 +0100 Subject: [PATCH] CPU and APB Frequency support (#2220) * Add support to HAL for APB frequencies different than 80MHz * Add support for CPU frequencies in the IDE board menu * Switch to fast set_config * Add method to uart so debug can be reassigned after apb frequency switch * Return real APB frequency --- boards.txt | 30 +++++++++++++++++++++++++ cores/esp32/esp32-hal-i2c.c | 4 ++-- cores/esp32/esp32-hal-ledc.c | 4 ++-- cores/esp32/esp32-hal-misc.c | 35 ++++++++++++++++++++++++------ cores/esp32/esp32-hal-sigmadelta.c | 5 +++-- cores/esp32/esp32-hal-spi.c | 17 +++++++++------ cores/esp32/esp32-hal-timer.c | 2 +- cores/esp32/esp32-hal-uart.c | 28 ++++++++++++++---------- cores/esp32/esp32-hal.h | 10 +++++++-- 9 files changed, 101 insertions(+), 34 deletions(-) diff --git a/boards.txt b/boards.txt index ae64c91b8cd..17fed9f95f6 100644 --- a/boards.txt +++ b/boards.txt @@ -1,4 +1,5 @@ menu.UploadSpeed=Upload Speed +menu.CPUFreq=CPU Frequency menu.FlashFreq=Flash Frequency menu.FlashMode=Flash Mode menu.FlashSize=Flash Size @@ -49,6 +50,35 @@ esp32.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 esp32.menu.PartitionScheme.fatflash=16M Fat esp32.menu.PartitionScheme.fatflash.build.partitions=ffat +esp32.menu.CPUFreq.240=240MHz +esp32.menu.CPUFreq.240.build.f_cpu=240000000L +esp32.menu.CPUFreq.160=160MHz +esp32.menu.CPUFreq.160.build.f_cpu=160000000L +esp32.menu.CPUFreq.80=80MHz +esp32.menu.CPUFreq.80.build.f_cpu=80000000L +esp32.menu.CPUFreq.40=40MHz (40MHz XTAL) +esp32.menu.CPUFreq.40.build.f_cpu=40000000L +esp32.menu.CPUFreq.26=26MHz (26MHz XTAL) +esp32.menu.CPUFreq.26.build.f_cpu=26000000L +esp32.menu.CPUFreq.20=20MHz (40MHz XTAL) +esp32.menu.CPUFreq.20.build.f_cpu=20000000L +esp32.menu.CPUFreq.13=13MHz +esp32.menu.CPUFreq.13.build.f_cpu=13000000L +esp32.menu.CPUFreq.10=10MHz (40MHz XTAL) +esp32.menu.CPUFreq.10.build.f_cpu=10000000L +esp32.menu.CPUFreq.8=8MHz (40MHz XTAL) +esp32.menu.CPUFreq.8.build.f_cpu=8000000L +esp32.menu.CPUFreq.5=5MHz +esp32.menu.CPUFreq.5.build.f_cpu=5000000L +esp32.menu.CPUFreq.4=4MHz +esp32.menu.CPUFreq.4.build.f_cpu=4000000L +esp32.menu.CPUFreq.3=3MHz +esp32.menu.CPUFreq.3.build.f_cpu=3000000L +esp32.menu.CPUFreq.2=2MHz +esp32.menu.CPUFreq.2.build.f_cpu=2000000L +esp32.menu.CPUFreq.1=1MHz +esp32.menu.CPUFreq.1.build.f_cpu=1000000L + esp32.menu.FlashMode.qio=QIO esp32.menu.FlashMode.qio.build.flash_mode=dio esp32.menu.FlashMode.qio.build.boot=qio diff --git a/cores/esp32/esp32-hal-i2c.c b/cores/esp32/esp32-hal-i2c.c index 963e5d4996c..e95af3cf814 100644 --- a/cores/esp32/esp32-hal-i2c.c +++ b/cores/esp32/esp32-hal-i2c.c @@ -1611,7 +1611,7 @@ i2c_err_t i2cSetFrequency(i2c_t * i2c, uint32_t clk_speed) } I2C_FIFO_CONF_t f; - uint32_t period = (APB_CLK_FREQ/clk_speed) / 2; + uint32_t period = (getApbFrequency()/clk_speed) / 2; uint32_t halfPeriod = period/2; uint32_t quarterPeriod = period/4; @@ -1657,7 +1657,7 @@ uint32_t i2cGetFrequency(i2c_t * i2c) uint32_t result = 0; uint32_t old_count = (i2c->dev->scl_low_period.period+i2c->dev->scl_high_period.period); if(old_count>0) { - result = APB_CLK_FREQ / old_count; + result = getApbFrequency() / old_count; } else { result = 0; } diff --git a/cores/esp32/esp32-hal-ledc.c b/cores/esp32/esp32-hal-ledc.c index 64f4dc01fef..4d10d4eecdf 100644 --- a/cores/esp32/esp32-hal-ledc.c +++ b/cores/esp32/esp32-hal-ledc.c @@ -84,7 +84,7 @@ static void _ledcSetupTimer(uint8_t chan, uint32_t div_num, uint8_t bit_num, boo //max bit_num 0x1F (31) static double _ledcSetupTimerFreq(uint8_t chan, double freq, uint8_t bit_num) { - uint64_t clk_freq = APB_CLK_FREQ; + uint64_t clk_freq = getApbFrequency(); clk_freq <<= 8;//div_num is 8 bit decimal uint32_t div_num = (clk_freq >> bit_num) / freq; bool apb_clk = true; @@ -117,7 +117,7 @@ static double _ledcTimerRead(uint8_t chan) LEDC_MUTEX_UNLOCK(); uint64_t clk_freq = 1000000; if(apb_clk) { - clk_freq *= 80; + clk_freq = getApbFrequency(); } clk_freq <<= 8;//div_num is 8 bit decimal return (clk_freq >> bit_num) / (double)div_num; diff --git a/cores/esp32/esp32-hal-misc.c b/cores/esp32/esp32-hal-misc.c index 5a6e64b9540..dfe70e25b61 100644 --- a/cores/esp32/esp32-hal-misc.c +++ b/cores/esp32/esp32-hal-misc.c @@ -26,6 +26,8 @@ #endif //CONFIG_BT_ENABLED #include #include "soc/rtc.h" +#include "soc/rtc_cntl_reg.h" +#include "rom/rtc.h" #include "esp32-hal.h" //Undocumented!!! Get chip temperature in Farenheit @@ -42,31 +44,47 @@ void yield() vPortYield(); } -static uint32_t _cpu_freq_mhz = 240; +static uint32_t _cpu_freq_mhz = CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ; +static uint32_t _sys_time_multiplier = 1; -bool cpuFrequencySet(uint32_t cpu_freq_mhz){ - if(_cpu_freq_mhz == cpu_freq_mhz){ +bool setCpuFrequency(uint32_t cpu_freq_mhz){ + rtc_cpu_freq_config_t conf, cconf; + rtc_clk_cpu_freq_get_config(&cconf); + if(cconf.freq_mhz == cpu_freq_mhz && _cpu_freq_mhz == cpu_freq_mhz){ return true; } - rtc_cpu_freq_config_t conf; if(!rtc_clk_cpu_freq_mhz_to_config(cpu_freq_mhz, &conf)){ log_e("CPU clock could not be set to %u MHz", cpu_freq_mhz); return false; } - rtc_clk_cpu_freq_set_config(&conf); +#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO + log_i("%s: %u / %u = %u Mhz", (conf.source == RTC_CPU_FREQ_SRC_PLL)?"PLL":((conf.source == RTC_CPU_FREQ_SRC_APLL)?"APLL":((conf.source == RTC_CPU_FREQ_SRC_XTAL)?"XTAL":"8M")), conf.source_freq_mhz, conf.div, conf.freq_mhz); + delay(10); +#endif + rtc_clk_cpu_freq_set_config_fast(&conf); _cpu_freq_mhz = conf.freq_mhz; + _sys_time_multiplier = 80 / getApbFrequency(); return true; } -uint32_t cpuFrequencyGet(){ +uint32_t getCpuFrequency(){ rtc_cpu_freq_config_t conf; rtc_clk_cpu_freq_get_config(&conf); return conf.freq_mhz; } +uint32_t getApbFrequency(){ + rtc_cpu_freq_config_t conf; + rtc_clk_cpu_freq_get_config(&conf); + if(conf.freq_mhz >= 80){ + return 80000000; + } + return (conf.source_freq_mhz * 1000000) / conf.div; +} + unsigned long IRAM_ATTR micros() { - return (unsigned long) ((esp_timer_get_time() * 240) / _cpu_freq_mhz); + return (unsigned long) (esp_timer_get_time()) * _sys_time_multiplier; } unsigned long IRAM_ATTR millis() @@ -109,6 +127,9 @@ bool btInUse(){ return false; } void initArduino() { +#ifdef F_CPU + setCpuFrequency(F_CPU/1000000L); +#endif #if CONFIG_SPIRAM_SUPPORT psramInit(); #endif diff --git a/cores/esp32/esp32-hal-sigmadelta.c b/cores/esp32/esp32-hal-sigmadelta.c index 4c26adaa2dc..64355318abe 100644 --- a/cores/esp32/esp32-hal-sigmadelta.c +++ b/cores/esp32/esp32-hal-sigmadelta.c @@ -43,7 +43,8 @@ uint32_t sigmaDeltaSetup(uint8_t channel, uint32_t freq) //chan 0-7 freq 1220-31 _sd_sys_lock = xSemaphoreCreateMutex(); } #endif - uint32_t prescale = (10000000/(freq*32)) - 1; + uint32_t apb_freq = getApbFrequency(); + uint32_t prescale = (apb_freq/(freq*256)) - 1; if(prescale > 0xFF) { prescale = 0xFF; } @@ -52,7 +53,7 @@ uint32_t sigmaDeltaSetup(uint8_t channel, uint32_t freq) //chan 0-7 freq 1220-31 SIGMADELTA.cg.clk_en = 0; SIGMADELTA.cg.clk_en = 1; SD_MUTEX_UNLOCK(); - return 10000000/((prescale + 1) * 32); + return apb_freq/((prescale + 1) * 256); } void sigmaDeltaWrite(uint8_t channel, uint8_t duty) //chan 0-7 duty 8 bit diff --git a/cores/esp32/esp32-hal-spi.c b/cores/esp32/esp32-hal-spi.c index 52fa1175091..b262bdaaa0f 100644 --- a/cores/esp32/esp32-hal-spi.c +++ b/cores/esp32/esp32-hal-spi.c @@ -26,6 +26,7 @@ #include "soc/io_mux_reg.h" #include "soc/gpio_sig_map.h" #include "soc/dport_reg.h" +#include "soc/rtc.h" #define SPI_CLK_IDX(p) ((p==0)?SPICLK_OUT_IDX:((p==1)?SPICLK_OUT_IDX:((p==2)?HSPICLK_OUT_IDX:((p==3)?VSPICLK_OUT_IDX:0)))) #define SPI_MISO_IDX(p) ((p==0)?SPIQ_OUT_IDX:((p==1)?SPIQ_OUT_IDX:((p==2)?HSPIQ_OUT_IDX:((p==3)?VSPIQ_OUT_IDX:0)))) @@ -750,7 +751,7 @@ void spiEndTransaction(spi_t * spi) SPI_MUTEX_UNLOCK(); } -void spiWriteByteNL(spi_t * spi, uint8_t data) +void IRAM_ATTR spiWriteByteNL(spi_t * spi, uint8_t data) { if(!spi) { return; @@ -776,7 +777,7 @@ uint8_t spiTransferByteNL(spi_t * spi, uint8_t data) return data; } -void spiWriteShortNL(spi_t * spi, uint16_t data) +void IRAM_ATTR spiWriteShortNL(spi_t * spi, uint16_t data) { if(!spi) { return; @@ -811,7 +812,7 @@ uint16_t spiTransferShortNL(spi_t * spi, uint16_t data) return data; } -void spiWriteLongNL(spi_t * spi, uint32_t data) +void IRAM_ATTR spiWriteLongNL(spi_t * spi, uint32_t data) { if(!spi) { return; @@ -959,7 +960,7 @@ void spiTransferBitsNL(spi_t * spi, uint32_t data, uint32_t * out, uint8_t bits) } } -void spiWritePixelsNL(spi_t * spi, const void * data_in, size_t len){ +void IRAM_ATTR spiWritePixelsNL(spi_t * spi, const void * data_in, size_t len){ size_t longs = len >> 2; if(len & 3){ longs++; @@ -1017,18 +1018,20 @@ typedef union { }; } spiClk_t; -#define ClkRegToFreq(reg) (CPU_CLK_FREQ / (((reg)->regPre + 1) * ((reg)->regN + 1))) +#define ClkRegToFreq(reg) (apb_freq / (((reg)->regPre + 1) * ((reg)->regN + 1))) uint32_t spiClockDivToFrequency(uint32_t clockDiv) { + uint32_t apb_freq = getApbFrequency(); spiClk_t reg = { clockDiv }; return ClkRegToFreq(®); } uint32_t spiFrequencyToClockDiv(uint32_t freq) { + uint32_t apb_freq = getApbFrequency(); - if(freq >= CPU_CLK_FREQ) { + if(freq >= apb_freq) { return SPI_CLK_EQU_SYSCLK; } @@ -1051,7 +1054,7 @@ uint32_t spiFrequencyToClockDiv(uint32_t freq) reg.regN = calN; while(calPreVari++ <= 1) { - calPre = (((CPU_CLK_FREQ / (reg.regN + 1)) / freq) - 1) + calPreVari; + calPre = (((apb_freq / (reg.regN + 1)) / freq) - 1) + calPreVari; if(calPre > 0x1FFF) { reg.regPre = 0x1FFF; } else if(calPre <= 0) { diff --git a/cores/esp32/esp32-hal-timer.c b/cores/esp32/esp32-hal-timer.c index 17743a4f6d8..8fcee55f8e1 100644 --- a/cores/esp32/esp32-hal-timer.c +++ b/cores/esp32/esp32-hal-timer.c @@ -84,7 +84,7 @@ void IRAM_ATTR __timerISR(void * arg){ i = 4; //call callbacks while(i--){ - if(__timerInterruptHandlers[i] && status & (1 << i)){ + if(__timerInterruptHandlers[i] && (status & (1 << i))){ __timerInterruptHandlers[i](); } } diff --git a/cores/esp32/esp32-hal-uart.c b/cores/esp32/esp32-hal-uart.c index 11da14f6f85..56fe510a04c 100644 --- a/cores/esp32/esp32-hal-uart.c +++ b/cores/esp32/esp32-hal-uart.c @@ -27,6 +27,7 @@ #include "soc/io_mux_reg.h" #include "soc/gpio_sig_map.h" #include "soc/dport_reg.h" +#include "soc/rtc.h" #include "esp_intr_alloc.h" #define UART_REG_BASE(u) ((u==0)?DR_REG_UART_BASE:( (u==1)?DR_REG_UART1_BASE:( (u==2)?DR_REG_UART2_BASE:0))) @@ -352,7 +353,7 @@ void uartSetBaudRate(uart_t* uart, uint32_t baud_rate) return; } UART_MUTEX_LOCK(); - uint32_t clk_div = ((UART_CLK_FREQ<<4)/baud_rate); + uint32_t clk_div = ((getApbFrequency()<<4)/baud_rate); uart->dev->clk_div.div_int = clk_div>>4 ; uart->dev->clk_div.div_frag = clk_div & 0xf; UART_MUTEX_UNLOCK(); @@ -385,17 +386,8 @@ static void IRAM_ATTR uart2_write_char(char c) ESP_REG(DR_REG_UART2_BASE) = c; } -void uartSetDebug(uart_t* uart) +void uart_install_putc() { - if(uart == NULL || uart->num > 2) { - s_uart_debug_nr = -1; - ets_install_putc1(NULL); - return; - } - if(s_uart_debug_nr == uart->num) { - return; - } - s_uart_debug_nr = uart->num; switch(s_uart_debug_nr) { case 0: ets_install_putc1((void (*)(char)) &uart0_write_char); @@ -412,6 +404,20 @@ void uartSetDebug(uart_t* uart) } } +void uartSetDebug(uart_t* uart) +{ + if(uart == NULL || uart->num > 2) { + s_uart_debug_nr = -1; + //ets_install_putc1(NULL); + //return; + } else + if(s_uart_debug_nr == uart->num) { + return; + } else + s_uart_debug_nr = uart->num; + uart_install_putc(); +} + int uartGetDebug() { return s_uart_debug_nr; diff --git a/cores/esp32/esp32-hal.h b/cores/esp32/esp32-hal.h index ca4f95f81c7..60fbc6d57fd 100644 --- a/cores/esp32/esp32-hal.h +++ b/cores/esp32/esp32-hal.h @@ -72,8 +72,14 @@ void yield(void); //returns chip temperature in Celsius float temperatureRead(); -bool cpuFrequencySet(uint32_t cpu_freq_mhz); -uint32_t cpuFrequencyGet(); +//function takes the following frequencies as valid values: +// 240, 160, 80 <<< For all XTAL types +// 40, 20, 13, 10, 8, 5, 4, 3, 2, 1 <<< For 40MHz XTAL +// 26, 13, 5, 4, 3, 2, 1 <<< For 26MHz XTAL +// 24, 12, 8, 6, 4, 3, 2, 1 <<< For 24MHz XTAL +bool setCpuFrequency(uint32_t cpu_freq_mhz); +uint32_t getCpuFrequency(); +uint32_t getApbFrequency(); unsigned long micros(); unsigned long millis();