-
Notifications
You must be signed in to change notification settings - Fork 7.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CPU and APB Frequency support #2220
Conversation
cores/esp32/esp32-hal-i2c.c
Outdated
@@ -1611,7 +1612,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 = (rtc_clk_apb_freq_get()/clk_speed) / 2; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried this mod a couple of weeks ago, the returned value didn't change, it stayed at 80,000,000. But the actual hardware clock changed speed, I could see the i2c bus speed change on my oscilloscope.
Have you changed the code inside rtc_clk_apb_freq_get()
since Rc1 1.0.1 ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to me it changes now when you set the cpu frequency below 80MHz. I have not tested I2C, but tested other peripherals. Give it a go :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
see private glitter
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An upper bounds needs to be applied to I2C bus freq versus CPU freq:
#define MIN_I2C_CLKS 100
uint32_t period = (rtc_clk_apb_freq_get()/clk_speed) / 2;
if(period < (MIN_I2C_CLKS/2) ){
period = (MIN_I2C_CLKS/2);
log_w("APB Freq too slow, Reducing i2c Freq to %d Hz",rtc_clk_apb_freq_get()/(period*2));
}
This limits it to 1/100th APB frequency so a 5MHz APB has a max i2c of 50KHz down to 10KHz at 1MHz. I tried up to 1/80 APB, I2C did not function. In my newer code I have other places I need MIN_I2C_CLKS
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a good solution I think. Will also venture into dynamic cpu scaling and will see how we can manage that.
cores/esp32/esp32-hal-uart.c
Outdated
@@ -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 = ((rtc_clk_apb_freq_get()<<4)/baud_rate); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There needs to be some limits between APB
freq and baud_rate
. When I tested this at 4MHz, 3MHz (26MHz base clock) the serial monitor has garbage injected.
After change of clock to speed[7]=13
rtc_clk_cpu_freq_get=1073470388, cpuFreq=13
current apb freq =13000000, apbFreq=13
read 128 bytes
Error setting freq[8]=12MHZ
Error setting freq[9]=10MHZ
Error setting freq[10]=8MHZ
Error setting freq[11]=6MHZ
After change of clock to speed[12]=5
rtc_clk_cpu_freq_get=1073470388, cpuFreq=5
current apb freq =5000000, apbFreq=5
read 127 bytes
⸮P�W⸮Achange of clock to⸮.⸮⸮⸮m⸮3]=4
rtc_clk⸮,⸮}⸮ɕ⸮}⸮⸮⸮⸮1073470388,⸮,⸮�ɕ⸮⸮4
current apb⸮⸮⸮⸮A=4000000, apbFreq=4
read 128⸮⸮ѕ⸮) After change of clock to⸮.⸮⸮⸮m⸮4]=3
⸮.⸮}⸮⸮⸮}⸮⸮⸮}⸮ɕ⸮}⸮⸮⸮⸮1073470388, cpuFreq=3
current⸮X⸮Afreq =3000000, apbFreq=3
read⸮L&⸮bytes
After change of clock to speed[15]=2
rtc_clk_cpu_freq_get=4, cpuFreq=2
current apb freq =2000000, apbFreq=2
read 127 bytes
After change of clock to speed[16]=1
rtc_clk_cpu_freq_get=1073470388, cpuFreq=1
current apb freq =1000000, apbFreq=1
read 128 bytes
This is with Serial Monitor Baud set to 19200.
With Baud set to 115200 the ESP32 hangs when Frequency is changed to 1MHz.
After change of clock to speed[12]=5
rtc_clk_cpu_freq_get=1073470388, cpuFreq=5
current apb freq =5000000, apbFreq=5
read 127 bytes
⸮P�W⸮Achange⸮⸮Aclock to speed[13]=4
⸮.⸮}⸮⸮⸮}⸮⸮⸮}⸮ɕ⸮}⸮⸮⸮⸮1073470388,⸮,⸮�ɕ⸮⸮4
current apb freq⸮O�⸮⸮000, apbFreq=4
read 127⸮⸮ѕ⸮)⸮P�W⸮Achange⸮⸮Aclock⸮⸮�⸮⸮eed[14]=3
⸮.⸮}⸮⸮⸮}⸮⸮u⸮⸮⸮⸮}⸮⸮⸮⸮1073470388,⸮,⸮�ɕ⸮⸮3
⸮⸮⸮ɕ⸮⸮Aapb⸮⸮⸮⸮A=3000000,⸮X⸮�ɕ⸮⸮3
read⸮L⸮��⸮ѕ⸮) After change of clock to speed[15]=2
rtc_clk_cpu_freq_get=4, cpuFreq=2
current apb freq =2000000, apbFreq=2
read 128 bytes
Testing code:
uint8_t speeds[] ={240,160,80,40,26,24,20,13,12,10,8,6,5,4,3,2,1};
void loop() {
static int c=0;
c++;
if(c>=sizeof(speeds)) c = 0;
Serial.flush();
if(!setCpuFrequency(speeds[c])){
Serial.printf("\nError setting freq[%d]=%dMHZ\n\n",c,speeds[c]);
} else{
delay(100);
Serial.begin(BAUD);
Wire.begin(SDA,SCL,100000);
Serial.printf(" After change of clock to speed[%d]=%d\n",c,speeds[c]);
Serial.printf(" rtc_clk_cpu_freq_get=%d, cpuFreq=%d\n",rtc_clk_cpu_freq_get(),getCpuFrequency());
Serial.printf(" current apb freq =%d, apbFreq=%d\n",rtc_clk_apb_freq_get(),getApbFrequency());
runBlocks();
delay(5000);
}
}
Chuck.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tested with 40MHz crystal :) and uart works fine. Thanks for testing 26MHz!
_cpu_freq_mhz = conf.freq_mhz; | ||
_sys_time_multiplier = 80 / getApbFrequency(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will always set _sys_time_multiplier
to 0 all the time?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how did I miss this :D
This PR adds the ability to boot Arduino with CPU frequency other than the predefined 240MHz.
Beware when dropping below 80MHz. WiFi might not work and limits to what the peripherals can do also changes. The HAL has been updated, but you need to keep in mind that peripherals need to be reinitialised if frequency has been changed on the fly.