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.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

View File

@ -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;
}

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)
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;

View File

@ -26,6 +26,8 @@
#endif //CONFIG_BT_ENABLED
#include <sys/time.h>
#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

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();
}
#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

View File

@ -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(&reg);
}
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) {

View File

@ -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]();
}
}

View File

@ -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;

View File

@ -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();