电源管理

ESP-IDF中集成的电源管理算法可以根据应用程序组件的需求,调整外围总线 (APB) 频率、CPU 频率,并使芯片进入 Light-sleep 模式,尽可能减少运行应用程序的功耗

应用程序组件可以通过创建和获取电源管理锁来控制功耗

编译时可使用CONFIG_PM_ENABLE选项启用电源管理功能

电源管理配置

(摘自官网)启用电源管理功能将会增加中断延迟。额外延迟与多个因素有关,例如CPU频率、单/双核模式、是否需要进行频率切换等(CPU 频率为 240 MHz 且未启用频率调节时,最小额外延迟为 0.2 us;如果启用频率调节,且在中断入口将频率由 40 MHz 调节至 80 MHz,则最大额外延迟为 40 us)

应用程序可以通过调用esp_pm_configure()函数启用动态调频(DFS)功能和自动light-sleep模式。

通过esp_pm_config_esp32_t结构体来设置相关参数,如下所示

struct esp_pm_config_esp32_t//pm代表power management
{int max_freq_mhz;//最大CPU频率,也就是获取ESP_PM_CPU_FREQ_MAX锁后使用的频率,单位MHzint min_freq_mhz;//最小CPU频率,也就是获取ESP_PM_APB_FREQ_MAX锁后使用的频率,单位MHz,可设置为晶振频率值或晶振频率除以一个整数,但是需要注意10MHz是生成1MHz的REF_TICK默认时钟所需的最小频率bool light_sleep_enable;//当未获得任何管理锁时,决定系统是否需要自动进入light-sleep状态
}

电源管理锁与管理算法

应用程序可以通过获取或释放管理锁来控制电源管理算法

ESP32 支持下表中所述的三种电源管理锁。

电源管理锁 描述
ESP_PM_CPU_FREQ_MAX 请求使用esp_pm_configure将CPU频率设置为最大值。ESP32可以将该值设置为 80 MHz、160 MHz 或 240 MHz。
ESP_PM_APB_FREQ_MAX 请求将APB频率设置为最大值,ESP32支持的最大频率为80MHz
ESP_PM_NO_LIGHT_SLEEP 禁止自动切换至Light-sleep模式

如果没有获取任何管理锁,调用esp_pm_configure()将启动Light-sleep模式

Light-sleep模式持续时间由以下因素决定:1.处于阻塞状态的FreeRTOS任务书;2.高分辨率定时器API注册的计数器数量

动态调频和外设驱动

启用动态调频后,APB频率可在一个RTOS滴答周期内多次更改。有些外设不受APB频率变更的影响,但有些外设可能会出现问题

UART、LEDC、RMT不受APB频率变更的影响

SPI master、I2C、I2S、SDMMC可以感知动态调频并在调频期间使用ESP_PM_APB_FREQ_MAX锁

启用SPI slave、以太网、wifi、蓝牙、CAN时,将占用ESP_PM_APB_FREQ_MAX锁

MCPWM、PCNT、Sigma-delta、Timer Group无法感知动态调频,需要应用程序自行获取、释放管理锁

ESP32 在内置Deep-sleep低功耗模式RTC外设ULP协处理器的支持下,可以满足多种应用场景下的低功耗需求

(ULP协处理器见最后部分)

低功耗模式

ESP32可以进入light-sleep和deep-sleep模式,还能进入一个用于相对较低功耗运行的modem-sleep模式

注意:进入低功耗模式前,应用程序必须关闭wifi和蓝牙设备,如果需要维持wifi连接,应当使用modem-sleep模式,在这个模式下当需要wifi驱动执行时系统会自动唤醒来维持wifi连接

light-sleep

CPU暂停运行,wifi/蓝牙基带和射频关闭。RTC、ULP运行,任何唤醒事件都会唤醒芯片

在light-sleep模式下,数字外设、大部分内存和CPU都会被停用(停用时钟),电源功耗也会降低,从light-sleep模式下唤醒后外设和CPU会接回时钟源并继续工作,他们的外部状态会被保存

这个模式可以理解为电脑的挂起休眠

deep-sleep

CPU、大部分外设掉电,wifi/蓝牙基带和射频关闭,进有RTC、ULP运行,wifi和蓝牙连接数据被转移到RTC内存中。仅有一部分中断源会唤醒芯片

deep-sleep模式下,由APB_CLK时钟提供是时钟源的CPU、大部分内存和所有数字外设都会掉电;只有片上RTC控制器、RTC外设、ULP和RTC内存会被保留电源

这个模式可以理解为电脑的断电休眠

Deep-sleep模式下支持从以下唤醒源触发的设备唤醒

  • 定时器
  • touchpad
  • Ext(0):RTC IO中某个指定GPIO满足指定电平即唤醒
  • Ext(1):RTC IO中某些指定GPIO同时满足指定电平才能唤醒
  • ULP协处理器

睡眠唤醒源可以在进入light-sleep或deep-sleep之前的任何时间设置

特别地,应用程序可以调用esp_sleep_pd_config()函数来让RTC外设和RTC内存掉电

设置好中断源后可以使用esp_light_sleep_start()和esp_deep_sleep_start()来进入睡眠模式

中断源

使用esp_sleep_disable_wakeup_source()来停用某个已经设置的中断源

设置中断源的方法如下

定时器

RTC控制器自带一个能够在预定义时间后进行唤醒的定时器

这个换新模式不需要在睡眠期间为RTC外设或RTC内存上电

使用esp_sleep_enable_timer_wakeup()使能这个功能

触摸检测

RTC IO模块包括了一套触摸传感器中断触发唤醒的逻辑,需要在MCU进入睡眠之前配置好触摸中断唤醒

只有在RTC外设没有被强行上电的时候才能使用这个唤醒模式

使用esp_sleep_enable_touchpad_wakeup()函数来使能这个中断源

特定外部引脚

RTC IO模块包括了一套GPIO触发唤醒的逻辑。如果这个中断源被使能,RTC外设需要保持上电状态。因为RTC IO模组在这个模式中被使能,中断上拉或下拉电阻也会被使用到,它们需要通过rtc_gpio_pullup_en()和rtc_gpio_pulldown_en()函数设置

调用esp_sleep_enable_ext0_wakeup()函数来使能这个中断源

此外,也可以使用多个GPIO同时触发唤醒

配置API如下

esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);//开启特定GPIO唤醒
gpio_pullup_dis(gpio_num);//配置gpio_num为上拉
gpio_pulldown_en(gpio_num);//配置gpio_num为下拉
rtc_gpio_isolate(gpio_num);//配置gpio_num为高阻态rtc_gpio_deinit(gpio_num);//使用这个函数来取消配置引脚

rtc_gpio_isolate()可以用于防止进入休眠后由GPIO产生的额外功耗

ULP协处理器

可以使用esp_sleep_enable_ulp_wakeup()来启用ULP协处理器指令唤醒

GPIO

除了特定的外部引脚触发唤醒,还可以在light-sleep下使用gpio_wakeup_enable()来设定任意GPIO的高/低电平触发唤醒

在进入睡眠模式之前使用esp_sleep_enable_gio_wakeup()来使能该唤醒源

UART

在light-sleep下可以使用esp_sleep_enable_uart_wakeup()来启用UART触发唤醒

若开启该触发源,当睡眠状态的ESP32收到来自外部设备的UART输入的数个上升沿时,会自动唤醒,该上升沿数目可以用uart_set_wakeup_threshold()函数配置;在这个触发信号被接收之前,所有信息不会被接收——这就意味着外部设备需要发送额外的字符给ESP32来让它唤醒

modem-sleep

CPU运行、可配置时钟,wifi/蓝牙基带和射频关闭,但会维持wifi连接

RTC外设

RTC外设不仅包括RTC,还包括了片上温度传感器、ADC、RTC-GPIO和touchpad外设

ULP协处理器

ULP(Ultra Low Power超低功耗)协处理器是一种简单的有限状态机(FSM)。在主处理器处于Deep-sleep深度睡眠模式时,它可以使用ADC、温度传感器和外部IIC传感器执行测量操作。ULP协处理器可以访问RTC慢速内存区域(RTC_SLOW_MEM)及RTC_CNTL、RTC_IO、SARADC等外设寄存器。ULP协处理器使用32位固定宽度的指令32位内存寻址,配备4个16位通用寄存器

ULP协处理器编程

ULP协处理器代码是用汇编语言编写的,并使用binutils-esp32ulp工具链进行编译

开发环境被集成到ESP-IDF中

编译方法如下:

  1. ULP代码必须导入到一个或多个.S扩展文件中,源文件必须放在组件目录中一个独立的目录(如ulp/)

  2. 注册后从组件CMakeLists.txt中调用ulp_embed_binary,示例如下

    ...
    idf_component_register()set(ulp_app_name ulp_${COMPONENT_NAME})
    set(ulp_s_sources ulp/ulp_assembly_source_file.S)
    set(ulp_exp_dep_srcs "ulp_c_source_file.c") #二进制文件命名ulp_embed_binary(${ulp_app_name} "${ulp_s_sources}" "${ulp_exp_dep_srcs}") # 导入二进制文件
    
  3. 使用常规方法编译应用程序,ULP程序会被自动生成

    构建系统的内部编译步骤如下:

    1. 通过C预处理器运行每个.S文件,生成依赖文件和经过预处理的程序集文件
    2. 运行汇编器进行编译
    3. 通过C预处理器运行链接器脚本模板(位于components/ulp/ld目录)
    4. 将目标文件链接到.elf输出文件
    5. 将elf中的内容转储为.bin二进制文件
    6. 使用esp32ulp-elf-nm工具在elf文件中生成全局符号列表
    7. 创建LD导出脚本和头文件
    8. 将生成的二进制文件添加到要嵌入应用程序的二进制文件列表中

    总体过程和在mcu中嵌入二进制格式的其他文件类似,只是多出了编译的几步

使用ULP程序

在ULP程序中定义的全局符号也可以在主程序中使用

如果要从主程序访问ULP程序变量,应先使用include语句包含生成的头文件,这样就可以像访问常规变量一样访问ulp程序变量

注意:ULP程序在RTC内存中只能使用32位字的低16位,因为寄存器是16位的并且不具备从字的高位加载的指令

主应用程序需要调用ulp_load_binary函数将ULP程序加载到RTC内存中,然后调用ulp_run函数启动ULP程序。ULP协处理器由定时器启动,而调用ulp_run则可启动此定时器,定时器为RTC_SLOW_CLK的Tick事件计数(默认情况下,Tick由内部150 KHz晶振器生成)。一旦定时器为所选的SENS_ULP_CP_SLEEP_CYCx_REG寄存器的Tick事件计数,ULP协处理器就会启动,并调用ulp_run的入口点开始运行程序。程序保持运行,直到遇到halt指令或非法指令。一旦程序停止,ULP协处理器电源关闭,定时器再次启动。

使用 SENS_ULP_CP_SLEEP_CYCx_REG 寄存器 (x = 0…4) 设置 Tick 数值。第一次启动 ULP 时,使用 SENS_ULP_CP_SLEEP_CYC0_REG 设置定时器 Tick 数值,之后,ULP 程序可以使用 sleep 指令来另外选择 SENS_ULP_CP_SLEEP_CYCx_REG 寄存器

汇编指令集参考

ESP32与ESP32S2的汇编指令集并不相同,详情参考官网即可

ESP32指令集参考

ESP32S2指令集参考

汇编大同小异,下面给出几个常见的指令

指令 说明
NOP 空指令
SUB R1,R2,R3 R1=R2-R3
AND R1,R2,R3 R1=R2&R3
OR R1,R2,R3 R1=R2|R3
LSH R1,R2,R3 R1=R2<<R3
RSH R1,R2,R3 R1=R2>>R3
MOVE R1,R2 R1=R2
ST R1,R2,k MEM[R2+k]=R1
LD R1,R2,k R1=MEM[R2+k]
JUMP R1 跳转到R1所在地址
HALT 协处理器停机
WAKE 协处理器唤醒
SLEEP k 协处理器睡眠k个时间单位
REG_RD Addr,HIGH,LOW 读外设寄存器地址为Addr从LOW到HIGH的内容
REG_WR Addr,HIGH,LOW,Data 将Data写入外设寄存器地址为Addr从LOW到HIGH的内容

ESPIDF开发ESP32学习笔记【电源管理与低功耗模式】相关推荐

  1. stm32外部中断_STM32学习笔记 | 电源管理及低功耗设计要点

    一款好的电子产品,都需要认真考虑电源管理的问题,电池供电的产品更应该注意低功耗的实现. STM32电源介绍 嵌入式开发直播课 - STM32 USART串口的应用 - 创客学院直播室​www.make ...

  2. ESPIDF开发ESP32学习笔记【基本内容】

    学校老师留了个作业,让用剩下一半的寒假学学ESP32,做蓝牙透传+STA&AP模式下工作的http服务器,但是不准用Arduino 当场就傻了:ESP32我刚刚好就会一手Arduino:乐鑫那 ...

  3. ESPIDF开发ESP32学习笔记【SPI与片外FLASH基础】

    文章目录 SPI SPI Master SPI传输时序 Notes on Sending Mixed Transactions to the Same Device SPI传输模式 中断传输 轮询传输 ...

  4. ESPIDF开发ESP32学习笔记【WiFi实现】

    WiFi外设配置 ESP32/8266的Wi-Fi库支持配置及监控Wi-Fi连网功能 相关内容参考乐鑫的ESP32/8266文档https://docs.espressif.com/projects/ ...

  5. 1566_AURIX_TC275_电源管理_低功耗模式

    全部学习汇总:GreyZhang/g_TC275: happy hacking for TC275! (github.com) Idle模式每一个核都可以单独进入,但是standby.sleep模式是 ...

  6. ESP32学习笔记(27)——BLE GAP主机端扫描

    一.背景 1.1 低功耗蓝牙(BLE)协议栈 链路层(LL) 控制设备的射频状态,有五个设备状态:待机.广播.扫描.初始化和连接. 广播 为广播数据包,而 扫描 则是监听广播. GAP通信中角色,中心 ...

  7. ESP32学习笔记(20)——SPI(从机)接口使用

    一.SPI简介 SPI(Serial Peripheral Interface) 协议是由摩托罗拉公司提出的通讯协议,即串行外围设备接口,是一种高速全双工的通信总线.它被广泛地使用在 ADC.LCD ...

  8. ESP32学习笔记(19)——SPI(主机)接口使用

    一.SPI简介 SPI(Serial Peripheral Interface) 协议是由摩托罗拉公司提出的通讯协议,即串行外围设备接口,是一种高速全双工的通信总线.它被广泛地使用在 ADC.LCD ...

  9. ESP32学习笔记(14)——HTTP服务器

    一.HTTP简介 HTTP(Hyper Text Transfer Protocol) 超文本传输协议,是一种建立在 TCP 上的无状态连接,整个基本的工作流程是客户端发送一个 HTTP 请求,说明客 ...

最新文章

  1. 《lua程序设计(第二版)》学习笔记(五)-- 函数基础
  2. 请使用 WITH MOVE 选项来标识该文件的有效位置。
  3. jvm性能调优实战 -50修复Metaspace区域内存溢出问题
  4. asp自动生成html文件的方法
  5. zigbee zcl规范及其协议栈实现3 读取服务器端属性值
  6. jmeter修改redis_jmeter如何访问redis服务缓存
  7. 物联网智能家居项目---智能卧室
  8. 东北大学计算机学院宿舍环境,软件学院二舍A区308寝室
  9. 如何学好游戏编程 二
  10. 美国鲨鱼主机使用笔记
  11. 海康ISAPI透传ftp
  12. 使用pytorch搭建AlexNet网络模型
  13. 本题要求编写程序,输出整数152的个位数字、十位数字和百位数字的值。
  14. 【MySQL】创建数据表
  15. Python调用OpenAI API示例
  16. 微信小程序“插件未授权使用”问题解决
  17. vue3+vite+EChars LPL数据可视化项目总结
  18. 能在Windows CE上运行的的二维码识别系统,使用手机摄像头扫描二维码
  19. 自控实验——直流电机转速设计实验报告
  20. 局域网传输还在用飞鸽?还在用QQ,其实Python也可以实现类似的功能!Python基于scoket实现多路复用TCP局域网文件传输

热门文章

  1. Uniapp(H5)判断软键盘是否唤起、关闭事件
  2. 苹果电脑 MacOS 遭恶意软件针对,监控通信流量又很难发现
  3. CPU外频、FSB前端总线与内存频率的关系
  4. html 外部调用css文件路径,CSS编程的外部CSS文件引用方法是什么
  5. 《必备干货!程序员的自我修养高效学习方法》观后笔记
  6. CodeForces12D 树状数组降维
  7. Tomcat调优教程
  8. 使用PR实现图片推移对比视频的制作
  9. 个税申报系统显示服务器证书不合法,个税申报成功却显示未申报是什么原因?如何处理?...
  10. win7计算机如何调亮度,win7的电脑怎么调亮度