1

I am programming an ESP32 with C (with the toolchain for ESP32) and I'm trying to change the clock frequency of my ESP32 but I'm quite unsure if I'm doing it right (I used the documenation https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/power_management.html#_CPPv418esp_pm_lock_type_t but I didn't find any code examples). I think I've done the program part right but I think it still doesn't work. Is there a way to figure out the the clock frequency that is set? I'm also unsure about this part in documentation: "ESP_PM_CPU_FREQ_MAX Require CPU frequency to be at the maximum value set via esp_pm_configure. Argument is unused and should be set to 0." Does the last part mean I shouldn't use this makro?

Last but not least I didnt't understand if I have to change my sdkconfig or is there a way to do everything in C?

I have to measure for a project times in region of ns hence I need maximum performance of esp32.

Code:

// ____________________________________________________________________________
esp_pm_config_esp32_t config_clock_struct;

// ____________________________________________________________________________
esp_pm_config_esp32_t* pointer_config_clock = &config_clock_struct;

// ____________________________________________________________________________
esp_pm_lock_handle_t handle;
void config_clock(int max_cpu_freq, int min_cpu_freq, bool light_sleep_enable,
                  esp_pm_config_esp32_t* pointer_config_clock) {
  pointer_config_clock->max_freq_mhz = max_cpu_freq;
  pointer_config_clock->min_freq_mhz = min_cpu_freq;
  pointer_config_clock->light_sleep_enable = light_sleep_enable;
  esp_err_t status = esp_pm_configure(pointer_config_clock);
  if (status == ESP_OK) {
    return;
  } else if (status == ESP_ERR_INVALID_ARG) {
    printf("Error %d: Configuration values aren't correct.", status);
    exit(1);
  } else if (status == ESP_ERR_NOT_SUPPORTED) {
    printf("Error %d: Combination of values aren't supported or CONFIG_PM_ENABLE isn't enabled in sdkconfig.",
           status);
    exit(1);
  }
}

// ____________________________________________________________________________
void init_clock(int max_cpu_freq, int min_cpu_freq, bool light_sleep_enable,
                esp_pm_lock_type_t lock_type, int arg, const char* name,
                esp_pm_config_esp32_t* pointer_config_clock, esp_pm_lock_handle_t* out_handle) {
  config_clock(max_cpu_freq, min_cpu_freq, light_sleep_enable, pointer_config_clock);
  esp_err_t status = esp_pm_lock_create(lock_type, arg, name, out_handle);
  if (status == ESP_OK) {
  return;
  } else if (status == ESP_ERR_NO_MEM) {
    printf("Error %d: Struct can't allocated.", status);
  } else if (status == ESP_ERR_INVALID_ARG) {
    printf("Error: %d: Invalid arguments.", status);
  } else if(ESP_ERR_NOT_SUPPORTED == status) {
    printf("Error %d: config pm is not enabled in sdkconfig.", status);
  }
}

And the relevant part of the main function:

#define MAX_FREQUENCY 240
#define MIN_FREQUENCY 40
#define DISABLE_SLEEP 0
  init_clock(MAX_FREQUENCY, MIN_FREQUENCY, DISABLE_SLEEP, ESP_PM_CPU_FREQ_MAX, ESP_PM_CPU_FREQ_MAX,
             "measure mode", pointer_config_clock, &handle);
  esp_err_t status_acquire = esp_pm_lock_acquire(handle);
5
  • 1
    Please edit your question and post your code. See: stackoverflow.com/help/minimal-reproducible-example Commented Oct 29, 2020 at 23:15
  • Sorry, I added it. Commented Oct 29, 2020 at 23:28
  • 1
    Just a guess: A websearch on an AND of: max_freq_mhz min_freq_mhz light_sleep_enable yielded amongst other things: programmersought.com/article/97514225639 and look at: ESP_PM_CPU_FREQ_MAX et. al. You're already using that, but what about: ESP_PM_APB_FREQ_MAX? That page also uses the esp_pm_configure function. In [your] main, how is pointer_config_clock set up. Does it point to the global (i.e. any uninited fields should be zeroed). Maybe, using memset(ptr,0,sizeof(esp_pm_config_esp32_t)); to be sure. Commented Oct 29, 2020 at 23:53
  • 1
    But, from the web search, a possible tutorial: git.card10.badge.events.ccc.de/card10/micropython/blob/… Note that it loops waiting for frequency to change. Commented Oct 29, 2020 at 23:54
  • Thank you very much! Now it works. And the gitlab example is very helpfully. The problem was only that I missed a while-loop to check if the new frequency is achieved (because I ignored that changing frequency needs a little bit time). Commented Oct 30, 2020 at 12:35

1 Answer 1

0

When one changes MCU clock frequency it alters all frequency dependent buses. For instance UART and I2C. Here's a neat hack to demonstrate how changing of clock frequency affects serial.print output. Mind you calculated Serial baud rates differ for each clock speed set.

//function takes the following frequencies as valid values:
//  240, 160, 80    <<< For all XTAL types
//  40, 20, 10      <<< For 40MHz XTAL
//  26, 13          <<< For 26MHz XTAL
//  24, 12          <<< For 24MHz XTAL


// 32Bit MCUs . change for 16bit 
    uint32_t Freq = 0;
    int MCU_FREQUENCY_SERIAL_SPEED=115200;
    int SERIAL_DEFAULT_SPEED = 115200;
    
    void changeMcuFreq(int Freq){
      delay(500);
      setCpuFrequencyMhz(Freq);
      changeSerialBaudRate(Freq);
      delay(500);
    } 
    
    void serialMcuFreq(){
      Freq = getCpuFrequencyMhz();
      Serial.print("CPU Freq = ");
      Serial.print(Freq);
      Serial.println(" MHz");
      Freq = getXtalFrequencyMhz();
      Serial.print("XTAL Freq = ");
      Serial.print(Freq);
      Serial.println(" MHz");
      Freq = getApbFrequency();
      Serial.print("APB Freq = ");
      Serial.print(Freq/1000000);
      Serial.println(" MHz");  
    }
    
    void changeSerialBaudRate(uint32_t Freq){
        if (Freq < 80) {
          MCU_FREQUENCY_SERIAL_SPEED = 80 / Freq * SERIAL_DEFAULT_SPEED;
        }
        else {
          MCU_FREQUENCY_SERIAL_SPEED = SERIAL_DEFAULT_SPEED;
        }
        // Dont do the 4 lines below or it will crash the ESP32 device
        // Serial.end();
        // delay(1000);
        // Serial.begin(MCU_FREQUENCY_SERIAL_SPEED);
        //delay(1000);
        
        Serial.print("\nSerial Baud Rate Speed is ");
        Serial.println(MCU_FREQUENCY_SERIAL_SPEED);
    }
    
    
    void setup()
    {
    
      Serial.begin(MCU_FREQUENCY_SERIAL_SPEED);
      
    }
     
    void loop()
    {
      changeMcuFreq(240);
      serialMcuFreq();    
      delay(2000);
      
      changeMcuFreq(160);
      serialMcuFreq();    
      delay(2000);
    
      changeMcuFreq(80);
      serialMcuFreq();    
      delay(2000);
    
      changeMcuFreq(40);
      serialMcuFreq();    
      delay(2000);
    
      changeMcuFreq(20);
      serialMcuFreq();    
      delay(2000);
    
      changeMcuFreq(10);
      serialMcuFreq();    
      delay(2000);
    
    }
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.