ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

ESP32 动态调频(DFS)实战:esp-iot-solution 电源管理测试指南

ESP32 动态调频(DFS)实战:esp-iot-solution 电源管理测试指南 ESP32 动态调频DFS实战esp-iot-solution 电源管理测试指南【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址: https://gitcode.com/GitHub_Trending/es/esp-iot-solution本文基于 esp-iot-solution 仓库中的 DFS 测试手册英文原版位于 docs/en/DFS_and_light_sleep/DFS_test_manual.rst整理而成。DFSDynamic Frequency Scaling动态频率调节是 ESP32 提供的另一类低功耗手段——通过动态调整 APB 与 CPU 频率来平衡性能与功耗。读完本文你将掌握从 menuconfig 开启电源管理、用esp_pm_configure()配置频率上下限、用电源管理锁PM Lock在关键时刻锁定高频以及如何用 LEDC 波形与电流实测验证降频行为最终学会在低功耗应用中安全、可控地使用 DFS。DFS 是什么另一种低功耗思路在 ESP32 的低功耗方案中除了让芯片整体休眠如 Light-sleep还有一类更温和的手段动态频率调节DFS。其核心思想是——在应用代码中动态调整 APB 总线与 CPU 的运行频率任务繁忙、需要算力时把频率提到最高如 240MHz任务全部挂起、系统空闲时自动把频率降到最低XTAL 频率典型 40MHz从而显著降低工作电流。与直接休眠不同DFS 不中断程序执行外设与 CPU 状态全程保留非常适合计算突发 空闲等待交替出现的物联网场景。下文将按照原手册的脉络从配置、锁机制、实测验证到功耗数据逐步展开。第一步在 menuconfig 中启用电源管理使用 DFS 的前提是打开 IDF 的电源管理功能。在项目根目录执行make menuconfig -- Component config -- Power Management勾选PM_ENABLE选项使电源管理子系统进入可配置状态。需要说明的是当前 IDF 新版本v5.x中电源管理相关配置集中在Component config → Power Management菜单下且通常与 FreeRTOS 的 tickless idle 配合使用。仓库中 button_power_save 示例的 sdkconfig.defaults 给出了完整的最小配置除CONFIG_PM_ENABLEy外还包括# Enable support for power management CONFIG_PM_ENABLEy # Enable tickless idle mode CONFIG_FREERTOS_USE_TICKLESS_IDLEy # Put related source code in IRAM CONFIG_PM_SLP_IRAM_OPTy CONFIG_PM_RTOS_IDLE_OPTy # Use 1000Hz freertos tick to lower sleep time threshold CONFIG_FREERTOS_HZ1000其中CONFIG_FREERTOS_USE_TICKLESS_IDLE允许空闲任务进入 tickless 模式是频率下调得以生效的底层支撑CONFIG_FREERTOS_HZ1000提高 tick 精度以降低睡眠时延。第二步调用 esp_pm_configure() 使能 DFS在应用代码中通过esp_pm_configure()配置频率范围即可开启 DFS。原手册以 ESP32 为例给出了经典写法esp_pm_config_esp32_t pm_config { .max_cpu_freq RTC_CPU_FREQ_240M, .min_cpu_freq RTC_CPU_FREQ_XTAL, }; esp_err_t ret; if((ret esp_pm_configure(pm_config)) ! ESP_OK) { printf(pm config error %s\n, \ ret ESP_ERR_INVALID_ARG ? \ ESP_ERR_INVALID_ARG:ESP_ERR_NOT_SUPPORTED); }两个关键字段含义如下字段含义本示例取值max_cpu_freqDFS 允许达到的最高 CPU 频率RTC_CPU_FREQ_240M240MHzmin_cpu_freqDFS 允许降到的最低 CPU 频率RTC_CPU_FREQ_XTAL即 XTAL 频率40MHz错误返回码ESP_ERR_INVALID_ARG表示参数非法如最大频率低于最小频率、频率取值不在支持列表内ESP_ERR_NOT_SUPPORTED表示当前芯片或配置不支持该频率组合。新版 IDF 的写法以仓库示例为准原手册面向早期 IDF使用按芯片区分的结构体如esp_pm_config_esp32_t。在 IDF 5.1 及以上版本API 已统一为esp_pm_config_t MHz 整数。仓库中的 button_power_save 示例 同时兼容两套 API可供参考#if ESP_IDF_VERSION ESP_IDF_VERSION_VAL(5, 1, 0) void power_save_init(void) { esp_pm_config_t pm_config { .max_freq_mhz CONFIG_EXAMPLE_MAX_CPU_FREQ_MHZ, .min_freq_mhz CONFIG_EXAMPLE_MIN_CPU_FREQ_MHZ, #if CONFIG_FREERTOS_USE_TICKLESS_IDLE .light_sleep_enable true #endif }; ESP_ERROR_CHECK(esp_pm_configure(pm_config)); } #else /* 旧版按目标芯片选择 esp_pm_config_esp32_t / esp_pm_config_esp32s2_t * / esp_pm_config_esp32c3_t / esp_pm_config_esp32s3_t 等结构体 */ #endif该示例把最大/最小频率做成 Kconfig 选项见 Kconfig.projbuild可选的max_cpu_freq为 80/96/120/160/240MHz视目标芯片而定如 ESP32H2 支持 96MHz、ESP32C2 支持 120MHzmin_cpu_freq可选 40/20/10MHz配合 40MHz XTAL或 26/13MHz配合 26MHz XTAL。配置项注释特别提醒最低频率应设置为 XTAL 频率或其整数分频这与原手册中RTC_CPU_FREQ_XTAL的语义一致。第三步创建电源管理锁PM LockDFS 使能后系统默认在空闲时把频率压到min_cpu_freq。但某些时刻如正在做运算、驱动时序敏感外设我们需要强制保持高频此时就要用到电源管理锁。调用esp_pm_lock_create创建锁句柄锁的类型对应不同的电源管理参数esp_err_t ret; if((ret esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 1, CPU_FREQ_MAX, pm_lock)) ! ESP_OK) { printf(pm config error %s\n, \ ret ESP_ERR_INVALID_ARG ? ESP_ERR_INVALID_ARG : \ (ret ESP_ERR_NOT_SUPPORTED ? ESP_ERR_NOT_SUPPORTED :\ ESP_ERR_NO_MEM)); }参数说明参数含义ESP_PM_APB_FREQ_MAX锁类型要求 APB 总线保持最高频率。原手册指出ESP_PM_APB_FREQ_MAX与ESP_PM_CPU_FREQ_MAX类型的锁效果相同——APB 保持 80MHz 时 CPU 自然运行在最高频1初始计数本示例为 1CPU_FREQ_MAX锁的名称调试用pm_lock返回的锁句柄错误返回码新增ESP_ERR_NO_MEM表示内存不足导致创建失败。第四步用 acquire / release 动态切换 CPU 频率创建锁之后在需要高频的临界区前后分别调用esp_pm_lock_acquire与esp_pm_lock_releaseif(esp_pm_lock_acquire(pm_lock) ESP_OK) { printf(lock acquire succeeded\n); vTaskDelay(2000 / portTICK_PERIOD_MS); esp_pm_lock_release(pm_lock); vTaskDelay(2000 / portTICK_PERIOD_MS); }锁是可重入递归的如果esp_pm_lock_acquire被调用 N 次就必须调用 N 次esp_pm_lock_release才能真正释放锁——在多层嵌套代码或回调中尤其要注意配对否则高频状态可能一直无法退出导致功耗白降。频率切换的时机原手册重点esp_pm_lock_acquire返回ESP_OK后CPU 频率立即切换到max_cpu_freq此后直到esp_pm_lock_release之前频率不会改变esp_pm_lock_release返回ESP_OK后CPU 频率不会立刻降到min_cpu_freq而是要等所有任务都进入挂起suspended状态后才会降频。为便于理解原手册假设只有一个任务并给出了完整时序代码/* max_cpu_freq RTC_CPU_FREQ_240M min_cpu_freq RTC_CPU_FREQ_XTAL */ void pm_test_task(void *param) { if(esp_pm_lock_acquire(pm_lock) ESP_OK) { // acquire a lock vTaskDelay(20 / portTICK_PERIOD_MS); // block task for(int i 0; i 100000; i); // do a loop vTaskDelay(20 / portTICK_PERIOD_MS); // block task esp_pm_lock_release(pm_lock); // release the lock for(int i 0; i 100000; i); // do a loop vTaskDelay(20 / portTICK_PERIOD_MS); // block task for(int i 0; i 100000; i); // do a loop vTaskDelay(20 / portTICK_PERIOD_MS); // block task } }按原手册的逐行分析以 240MHz / 40MHz 上下限为例第 4 行vTaskDelay挂起期间CPU 保持 240MHz锁尚未释放第 8、10 行循环运算在240MHz下执行第 9、11 行vTaskDelay期间锁已释放且任务挂起CPU 频率切换到 40MHzRTC_CPU_FREQ_XTAL。关键规律只有锁已释放 任务挂起同时满足频率才会下调只要任务还在 running/ready 态即便锁已释放频率也会按需保持。用 LEDC 实测验证5kHz → 2.5kHz 的降频证据理论之外原手册用 LEDC 外设做了直观验证。实验设计配置 LEDC 输出5kHzPWM 信号并选择APB 时钟作为定时器时钟源由于 LEDC 的计数时钟来自 APB当系统进入省电模式、APB 频率从 80MHz 降到 40MHz 时PWM 频率会减半为 2.5kHz——PWM 频率成为 APB 频率的晴雨表。锁持有期间频率稳定在 5kHz当pm_lock被 acquire 后LEDC 频率保持 5kHz 不变说明 APB 频率为 80MHz、CPU 频率为 240MHz在锁持有期间没有任何降频动作释放锁之后任务挂起时降为 2.5kHz释放锁后LEDC 频率在任务挂起期间变为 2.5kHz对应 APB 降至 40MHz而任务恢复执行do loop期间又回到 5kHz——波形上的疏密变化与上一节的时序分析完全吻合这一实验同时印证了原手册的两条结论一是锁能锁住APB/CPU 频率二是降频只发生在任务全部挂起时一旦有任务运行频率立即回到 5kHz 对应的档位。REF_TICK降频也不受影响的外设时钟源正常情况下 APB 频率为 80MHz进入低功耗模式后会切换到 40MHzRTC_CPU_FREQ_XTAL这会直接影响以 APB 为时钟源的外设。但部分外设可以选择REF_TICK作为时钟源即使 APB 频率在变化它们也能照常工作。原手册列出的三类外设UARTLEDCRMT原手册给出了一个 LEDC REF_TICK 的测试用例用 GPIO18 的电平标识测试区间锁持有期间拉高 GPIO18释放后延时再拉低if(esp_pm_lock_acquire(pm_lock) ESP_OK) { gpio_set_level(18,1); vTaskDelay(500 / portTICK_PERIOD_MS); esp_pm_lock_release(pm_lock); vTaskDelay(500 / portTICK_PERIOD_MS); gpio_set_level(18,0); vTaskDelay(20 / portTICK_PERIOD_MS); }将 LEDC 时钟源配置为 REF_TICK 后观察示波器在 GPIO18 保持高电平期间即执行到第 6 行vTaskDelay时CPU 时钟已切到 40M但LEDC 频率没有发生任何变化——实测中输出稳定保持在 62.50Hz标准差 0.000证明 REF_TICK 时钟源完全不受 DFS 降频影响工程建议如果你的外设时序不能随 APB 频率波动如精确的波特率、载波、PWM 周期优先选择支持 REF_TICK 的外设或为其分配独立的稳定时钟源这样即使系统 DFS 频繁降频功能也不会失真。实测功耗数据频率与电流的关系原手册创建了一个测试任务进行 DFS 实测得到不同 CPU 频率下的整机工作电流如下数据取自原手册测试具体数值与板卡、外设配置相关仅作趋势参考CPU 频率工作电流XTAL40MHz13.32mA80MHz22.85mA160MHz28.46mA240MHz39.95mA可以看到从 240MHz 降到 40MHz电流从约 40mA 降到约 13mA降幅超过 65%——这正是 DFS 的价值所在在不需要全速运行的空闲期把功耗压到接近最低档而一旦有任务需要算力频率又能瞬时拉满。与 Light-sleep 的配合DFS 降频只是第一步若进一步结合 Light-sleep轻睡眠功耗还能更低。仓库中的 light_sleep_performance.rst 记录了配套测试调用esp_light_sleep_start()后约 200µs 完全入睡EXT0 唤醒后约 566µs 恢复执行不同唤醒源下的睡眠电流为 ext0 约 1.15mA、ext1 约 1.14mA、timer 约 0.79mA。值得注意的是手册特别提醒进入 Light-sleep 前应将所有由 VDD3P3_CPU 供电的 GPIO 全部禁用否则 GPIO 漏电会使电流升高约 1.5mA。button_power_save示例main.c即演示了按钮触发 → 进入省电/轻睡眠 → 事件唤醒的完整链路可作为 DFS Light-sleep 组合落地的参考。总结DFS 使用要点清单先开总闸menuconfig 中启用PM_ENABLE配合CONFIG_FREERTOS_USE_TICKLESS_IDLE效果最佳配置区间用esp_pm_configure()设置max_cpu_freq/min_cpu_freq旧版 API或max_freq_mhz/min_freq_mhzIDF 5.1最低频率应取 XTAL 或其整数分频创建锁esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, ...)创建高频锁注意ESP_PM_APB_FREQ_MAX与ESP_PM_CPU_FREQ_MAX效果相同临界区保护acquire 后频率立即拉高release 后需等所有任务挂起才降频锁可重入acquire/release 必须严格配对外设考量时序敏感外设尽量使用 REF_TICKUART/LEDC/RMT等稳定时钟源避免受 APB 降频影响组合降功耗DFS 解决忙闲交替场景的工作电流Light-sleep 进一步降低空闲功耗二者可组合使用注意入睡前禁用 VDD3P3_CPU 供电的 GPIO。如需完整可运行示例可参考仓库 examples/get-started/button_power_save 与 examples/get-started/knob_power_save两者均已配置好电源管理相关 Kconfig 与 sdkconfig是快速上手 DFS 与低功耗开发的理想起点。【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址: https://gitcode.com/GitHub_Trending/es/esp-iot-solution创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表