Skip to content
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

Merged
merged 6 commits into from
Dec 20, 2018
Merged

CPU and APB Frequency support #2220

merged 6 commits into from
Dec 20, 2018

Conversation

me-no-dev
Copy link
Member

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.

@@ -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;
Copy link
Contributor

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 ?

Copy link
Member Author

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

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see private glitter

Copy link
Contributor

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.

Copy link
Member Author

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.

@@ -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);
Copy link
Contributor

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.

Copy link
Member Author

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!

@me-no-dev me-no-dev merged commit c827bb4 into master Dec 20, 2018
@me-no-dev me-no-dev deleted the apb_freq_support branch December 20, 2018 00:57
_cpu_freq_mhz = conf.freq_mhz;
_sys_time_multiplier = 80 / getApbFrequency();
Copy link
Contributor

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?

Copy link
Member Author

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants