Phillip Kühne eb4859c31d Update power measurement examples
Update power measurement examples to the state in which they were used as test cases in thesis
2025-01-28 20:22:38 +01:00

136 lines
4.4 KiB
C++

#include "Dezibot.h"
#include "esp_pm.h"
#include "esp_task_wdt.h"
Dezibot dezibot;
const uint16_t cycleTime = 20e3;
esp_pm_lock_handle_t cpuFreqLock;
esp_pm_lock_handle_t apbFreqLock;
esp_pm_lock_handle_t lightSleepLock;
static bool pmLocksCreated = false;
void stress_task0(void *pvParameters) {
// Register ourselves with the task watchdog
if (esp_task_wdt_add(NULL) != ESP_OK) {
Serial.println("Failed to add task 0 to TWDT");
}
while (1) {
volatile uint32_t x = 0;
for (uint32_t i = 0; i < 10000; i++) {
x += i;
}
esp_task_wdt_reset();
}
}
void stress_task1(void *pvParameters) {
// Register ourselves with the task watchdog
if (esp_task_wdt_add(NULL) != ESP_OK) {
Serial.println("Failed to add task 0 to TWDT");
}
while (1) {
volatile uint32_t x = 0;
for (uint32_t i = 0; i < 10000; i++) {
x += i;
}
esp_task_wdt_reset();
}
}
void setup() {
Serial.begin(115200);
while (!Serial) {
;
}
uint32_t 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);
Serial.println(" Hz");
// Create lock handles for controlling power management features
// Parameter arg is always unused and should thus be set to 0
// Ref: https://docs.espressif.com/projects/esp-idf/en/v3.3.6/api-reference/system/power_management.html#enumerations
if (!pmLocksCreated) {
bool cpuFreqLockSuccess = esp_pm_lock_create(ESP_PM_CPU_FREQ_MAX, 0, "CPU_FREQ_MAX", &cpuFreqLock);
bool apbFreqLockSuccess = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "APB_FREQ_MAX", &apbFreqLock);
bool lightSleepLockSuccess = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "NO_LIGHT_SLEEP", &lightSleepLock);
if ((cpuFreqLockSuccess && apbFreqLockSuccess && lightSleepLockSuccess)) {
pmLocksCreated = true;
Serial.println("Sucessfully created handles to control power management features.");
} else {
Serial.println("Failed to create handles to control power management features!");
}
} else {
Serial.println("Powermanagement lock handles already created, skipping creation!");
}
// Configure Task Watchdog so it does not interfere
esp_task_wdt_config_t twdt_config = {
.timeout_ms = 30000,
.idle_core_mask = (1 << portNUM_PROCESSORS) - 1,
.trigger_panic = true
};
if (esp_task_wdt_reconfigure(&twdt_config) != ESP_OK) {
Serial.println("Failed to reconfigure task watchdog!");
}
delay(500);
Serial.flush();
Serial.end();
}
/*
* A function that prints to serial, setting up the serial peripheral beforehand, and shutting it down afterwards.
* Do not use this on a regular basis, as it is probably very slow. It is useful for not having the serial peripheral
* active at all times.
*
* @param str The text to print
*/
void setupAndCleanupSerialPrint(char *str) {
Serial.begin(115200);
while (!Serial) {
;
;
}
delay(10);
Serial.print(str);
delay(10);
Serial.flush();
delay(10);
Serial.end();
}
void loop() {
// Alternate between 20 Seconds at 100% CPU load, no artificial load but not sleeping, and normal behaviour (light sleep when there is nothing to do).
setupAndCleanupSerialPrint("Beginning stress phase\n");
TaskHandle_t core0StressTask = NULL;
TaskHandle_t core1StressTask = NULL;
xTaskCreatePinnedToCore(stress_task0, "CPU0Stress", 4096, NULL, 1, &core0StressTask, 0);
xTaskCreatePinnedToCore(stress_task1, "CPU1Stress", 4096, NULL, 1, &core1StressTask, 1);
vTaskDelay(pdMS_TO_TICKS(cycleTime));
setupAndCleanupSerialPrint("Still alive after waiting cycleTime after setting up stress tasks...\n");
esp_task_wdt_delete(core0StressTask);
esp_task_wdt_delete(core1StressTask);
vTaskDelete(core0StressTask);
vTaskDelete(core1StressTask);
// Now disable light sleep
setupAndCleanupSerialPrint("Beginning idle with power management disabled\n");
esp_pm_lock_acquire(cpuFreqLock);
esp_pm_lock_acquire(apbFreqLock);
esp_pm_lock_acquire(lightSleepLock);
vTaskDelay(pdMS_TO_TICKS(cycleTime));
// Restore auto light sleep and dynamic frequency scaling
setupAndCleanupSerialPrint("Beginning idle with power management reenabled\n");
esp_pm_lock_release(cpuFreqLock);
esp_pm_lock_release(apbFreqLock);
esp_pm_lock_release(lightSleepLock);
vTaskDelay(pdMS_TO_TICKS(cycleTime));
}