mirror of
https://gitlab.dit.htwk-leipzig.de/phillip.kuehne/dezibot.git
synced 2025-05-19 02:51:47 +02:00
Update power measurement examples to the state in which they were used as test cases in thesis
136 lines
4.4 KiB
C++
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));
|
|
} |