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
This commit is contained in:
Me No Dev 2018-12-20 01:57:32 +01:00 committed by GitHub
parent 1628f533a1
commit c827bb4177
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 101 additions and 34 deletions

View File

@ -1,4 +1,5 @@
menu.UploadSpeed=Upload Speed menu.UploadSpeed=Upload Speed
menu.CPUFreq=CPU Frequency
menu.FlashFreq=Flash Frequency menu.FlashFreq=Flash Frequency
menu.FlashMode=Flash Mode menu.FlashMode=Flash Mode
menu.FlashSize=Flash Size 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=16M Fat
esp32.menu.PartitionScheme.fatflash.build.partitions=ffat 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=QIO
esp32.menu.FlashMode.qio.build.flash_mode=dio esp32.menu.FlashMode.qio.build.flash_mode=dio
esp32.menu.FlashMode.qio.build.boot=qio esp32.menu.FlashMode.qio.build.boot=qio

View File

@ -1611,7 +1611,7 @@ i2c_err_t i2cSetFrequency(i2c_t * i2c, uint32_t clk_speed)
} }
I2C_FIFO_CONF_t f; 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 halfPeriod = period/2;
uint32_t quarterPeriod = period/4; uint32_t quarterPeriod = period/4;
@ -1657,7 +1657,7 @@ uint32_t i2cGetFrequency(i2c_t * i2c)
uint32_t result = 0; uint32_t result = 0;
uint32_t old_count = (i2c->dev->scl_low_period.period+i2c->dev->scl_high_period.period); uint32_t old_count = (i2c->dev->scl_low_period.period+i2c->dev->scl_high_period.period);
if(old_count>0) { if(old_count>0) {
result = APB_CLK_FREQ / old_count; result = getApbFrequency() / old_count;
} else { } else {
result = 0; result = 0;
} }

View File

@ -84,7 +84,7 @@ static void _ledcSetupTimer(uint8_t chan, uint32_t div_num, uint8_t bit_num, boo
//max bit_num 0x1F (31) //max bit_num 0x1F (31)
static double _ledcSetupTimerFreq(uint8_t chan, double freq, uint8_t bit_num) 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 clk_freq <<= 8;//div_num is 8 bit decimal
uint32_t div_num = (clk_freq >> bit_num) / freq; uint32_t div_num = (clk_freq >> bit_num) / freq;
bool apb_clk = true; bool apb_clk = true;
@ -117,7 +117,7 @@ static double _ledcTimerRead(uint8_t chan)
LEDC_MUTEX_UNLOCK(); LEDC_MUTEX_UNLOCK();
uint64_t clk_freq = 1000000; uint64_t clk_freq = 1000000;
if(apb_clk) { if(apb_clk) {
clk_freq *= 80; clk_freq = getApbFrequency();
} }
clk_freq <<= 8;//div_num is 8 bit decimal clk_freq <<= 8;//div_num is 8 bit decimal
return (clk_freq >> bit_num) / (double)div_num; return (clk_freq >> bit_num) / (double)div_num;

View File

@ -26,6 +26,8 @@
#endif //CONFIG_BT_ENABLED #endif //CONFIG_BT_ENABLED
#include <sys/time.h> #include <sys/time.h>
#include "soc/rtc.h" #include "soc/rtc.h"
#include "soc/rtc_cntl_reg.h"
#include "rom/rtc.h"
#include "esp32-hal.h" #include "esp32-hal.h"
//Undocumented!!! Get chip temperature in Farenheit //Undocumented!!! Get chip temperature in Farenheit
@ -42,31 +44,47 @@ void yield()
vPortYield(); 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){ bool setCpuFrequency(uint32_t cpu_freq_mhz){
if(_cpu_freq_mhz == 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; return true;
} }
rtc_cpu_freq_config_t conf;
if(!rtc_clk_cpu_freq_mhz_to_config(cpu_freq_mhz, &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); log_e("CPU clock could not be set to %u MHz", cpu_freq_mhz);
return false; 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; _cpu_freq_mhz = conf.freq_mhz;
_sys_time_multiplier = 80 / getApbFrequency();
return true; return true;
} }
uint32_t cpuFrequencyGet(){ uint32_t getCpuFrequency(){
rtc_cpu_freq_config_t conf; rtc_cpu_freq_config_t conf;
rtc_clk_cpu_freq_get_config(&conf); rtc_clk_cpu_freq_get_config(&conf);
return conf.freq_mhz; 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() 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() unsigned long IRAM_ATTR millis()
@ -109,6 +127,9 @@ bool btInUse(){ return false; }
void initArduino() void initArduino()
{ {
#ifdef F_CPU
setCpuFrequency(F_CPU/1000000L);
#endif
#if CONFIG_SPIRAM_SUPPORT #if CONFIG_SPIRAM_SUPPORT
psramInit(); psramInit();
#endif #endif

View File

@ -43,7 +43,8 @@ uint32_t sigmaDeltaSetup(uint8_t channel, uint32_t freq) //chan 0-7 freq 1220-31
_sd_sys_lock = xSemaphoreCreateMutex(); _sd_sys_lock = xSemaphoreCreateMutex();
} }
#endif #endif
uint32_t prescale = (10000000/(freq*32)) - 1; uint32_t apb_freq = getApbFrequency();
uint32_t prescale = (apb_freq/(freq*256)) - 1;
if(prescale > 0xFF) { if(prescale > 0xFF) {
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 = 0;
SIGMADELTA.cg.clk_en = 1; SIGMADELTA.cg.clk_en = 1;
SD_MUTEX_UNLOCK(); 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 void sigmaDeltaWrite(uint8_t channel, uint8_t duty) //chan 0-7 duty 8 bit

View File

@ -26,6 +26,7 @@
#include "soc/io_mux_reg.h" #include "soc/io_mux_reg.h"
#include "soc/gpio_sig_map.h" #include "soc/gpio_sig_map.h"
#include "soc/dport_reg.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_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)))) #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(); SPI_MUTEX_UNLOCK();
} }
void spiWriteByteNL(spi_t * spi, uint8_t data) void IRAM_ATTR spiWriteByteNL(spi_t * spi, uint8_t data)
{ {
if(!spi) { if(!spi) {
return; return;
@ -776,7 +777,7 @@ uint8_t spiTransferByteNL(spi_t * spi, uint8_t data)
return data; return data;
} }
void spiWriteShortNL(spi_t * spi, uint16_t data) void IRAM_ATTR spiWriteShortNL(spi_t * spi, uint16_t data)
{ {
if(!spi) { if(!spi) {
return; return;
@ -811,7 +812,7 @@ uint16_t spiTransferShortNL(spi_t * spi, uint16_t data)
return data; return data;
} }
void spiWriteLongNL(spi_t * spi, uint32_t data) void IRAM_ATTR spiWriteLongNL(spi_t * spi, uint32_t data)
{ {
if(!spi) { if(!spi) {
return; 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; size_t longs = len >> 2;
if(len & 3){ if(len & 3){
longs++; longs++;
@ -1017,18 +1018,20 @@ typedef union {
}; };
} spiClk_t; } 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 spiClockDivToFrequency(uint32_t clockDiv)
{ {
uint32_t apb_freq = getApbFrequency();
spiClk_t reg = { clockDiv }; spiClk_t reg = { clockDiv };
return ClkRegToFreq(&reg); return ClkRegToFreq(&reg);
} }
uint32_t spiFrequencyToClockDiv(uint32_t freq) 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; return SPI_CLK_EQU_SYSCLK;
} }
@ -1051,7 +1054,7 @@ uint32_t spiFrequencyToClockDiv(uint32_t freq)
reg.regN = calN; reg.regN = calN;
while(calPreVari++ <= 1) { 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) { if(calPre > 0x1FFF) {
reg.regPre = 0x1FFF; reg.regPre = 0x1FFF;
} else if(calPre <= 0) { } else if(calPre <= 0) {

View File

@ -84,7 +84,7 @@ void IRAM_ATTR __timerISR(void * arg){
i = 4; i = 4;
//call callbacks //call callbacks
while(i--){ while(i--){
if(__timerInterruptHandlers[i] && status & (1 << i)){ if(__timerInterruptHandlers[i] && (status & (1 << i))){
__timerInterruptHandlers[i](); __timerInterruptHandlers[i]();
} }
} }

View File

@ -27,6 +27,7 @@
#include "soc/io_mux_reg.h" #include "soc/io_mux_reg.h"
#include "soc/gpio_sig_map.h" #include "soc/gpio_sig_map.h"
#include "soc/dport_reg.h" #include "soc/dport_reg.h"
#include "soc/rtc.h"
#include "esp_intr_alloc.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))) #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; return;
} }
UART_MUTEX_LOCK(); 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_int = clk_div>>4 ;
uart->dev->clk_div.div_frag = clk_div & 0xf; uart->dev->clk_div.div_frag = clk_div & 0xf;
UART_MUTEX_UNLOCK(); UART_MUTEX_UNLOCK();
@ -385,17 +386,8 @@ static void IRAM_ATTR uart2_write_char(char c)
ESP_REG(DR_REG_UART2_BASE) = 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) { switch(s_uart_debug_nr) {
case 0: case 0:
ets_install_putc1((void (*)(char)) &uart0_write_char); 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() int uartGetDebug()
{ {
return s_uart_debug_nr; return s_uart_debug_nr;

View File

@ -72,8 +72,14 @@ void yield(void);
//returns chip temperature in Celsius //returns chip temperature in Celsius
float temperatureRead(); float temperatureRead();
bool cpuFrequencySet(uint32_t cpu_freq_mhz); //function takes the following frequencies as valid values:
uint32_t cpuFrequencyGet(); // 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 micros();
unsigned long millis(); unsigned long millis();