Telink BLE 低功耗學習

低功耗管理(Low Power Management)也可以稱為功耗管理(Power Management),本?檔中會簡稱為PM。

Telink低功耗解惑

????????我查閱多連接SDK開發手冊時,低功耗管理章節看了兩三遍也沒太明白,有以下幾個問題一直沒得以解決,比較困惑,麻煩大神給點指
????????進入低功耗好像只有cpu_sleep_wakeup()這個API可以設置進入低功耗的時間,而且還只有200+秒鐘,而且只有timer和pad兩種喚醒方式;那么

  1. 等到有master發送連接請求了,再退出sleep,等上5秒之后,如果主機還沒發送需要的信號,slave又重新進入sleep,如果發送了就不進入sleep,又應該如何設置呢?
  2. 如果想設置更長的睡眠時間怎么設置呢?
  3. 如果用串口喚醒的話,怎么設置呢?
  4. 以及比如下面這情況,是通過cpu_sleep_wakeup()API設置的嗎?,通過這個API設置的tick和這里的sleep時間有關嗎?這情況和這個API有什么關系呢?

回答:

(1)(4) 在Telink BLE Multiple Connection SDK中,如果當前有BLE任務,廣播/掃描/連接,睡眠由BLE stack進行管控,用戶不需要介入,但是用戶可以在app_process_power_management()使用blc_pm_setSleepMask()配置當前是否暫時關閉sleep,比如當前正在按鍵或進行OTA。
(3) 如果用串口喚醒的話,建議配置UART_Rx_GPIO為低電平喚醒API cpu_set_gpio_wakeup(),在回調BLT_EV_FLAG_SLEEP_ENTER里將UART_Rx_GPIO配置為GPIO模式,在回調BLT_EV_FLAG_SUSPEND_EXIT里將UART_Rx_GPIO配置為UART模式。

當沒有BLE任務(廣播關閉/掃描關閉/連接斷開),BLE stack不進行睡眠管控,程序在main_loop()循環轉,這時用戶可以使用API cpu_sleep_wakeup()自行管理睡眠時間,

(2)當期望睡眠時間大于268秒可以使用API cpu_long_sleep_wakeup_32k_rc()自行管理睡眠時間。

如果只打開BLE_APP_PM_ENABLE,協議棧在任務空閑時只會進入suspend。如果同時打開BLE_APP_PM_ENABLE和PM_DEEPSLEEP_RETENTION_ENABLE,協議棧在任務空閑時會進入suspend或deepsleep retention,會根據任務空閑的時間來選擇進入哪個睡眠模式,空閑時間長進入deepsleep retention,空閑時間短進入suspend,空閑時間的門限是API blc_pm_setDeepsleepRetentionThreshold()設置的,默認配置為95ms。

注:

對于uart的接收GPIO作為串口喚醒;在回調BLT_EV_FLAG_SUSPEND_ENTER里將UART_Rx_GPIO配置為GPIO模式,在回調BLT_EV_FLAG_SUSPEND_EXIT里將UART_Rx_GPIO配置為UART模式。

bls_app_registerEventCallback(BLT_EV_FLAG_SUSPEND_EXIT, &task_suspend_exit);
bls_app_registerEventCallback(BLT_EV_FLAG_SUSPEND_ENTER, &task_suspend_enter);

在回調函數 task_suspend_exit中UART_Rx_GPIO配置為UART模式,task_suspend_enter中UART_Rx_GPIO配置為GPIO模式。

空閑時間的門限是API blc_pm_setDeepsleepRetentionThreshold()設置的,默認配置為95ms。

這個95ms的值,不是唯一固定的,你要看你的SDK中,power?management initialization中,是否有規定了adv和conn的門限值。

低功耗喚醒源

MCU 的suspend/deepsleep/deepsleep retention 在硬件上有2 個喚醒源:TIMER、GPIO PAD。

  • 喚醒源PM_WAKEUP_TIMER 來?硬件32k timer(32k RC timer or 32k Crystal timer)。32k timer 在SDK 中已經被正確初始化,user 在使?時不需要任何配置,只需要在cpu_sleep_wakeup() 中設置該喚醒源即可。
  • 喚醒源PM_WAKEUP_PAD 來?GPIO 模塊,除MSPI 4 個管腳外所有的GPIO(PAx/PBx/PCx/PDx)的?低電平都具有喚醒功能。

配置GPIO PAD 喚醒sleep mode 的API:
typedef enum{
Level_Low=0,
Level_High =1,
} GPIO_LevelTypeDef;


void cpu_set_gpio_wakeup (GPIO_PinTypeDef pin, GPIO_LevelTypeDef pol, int en);

  1. pin 為GPIO 定義。
  2. pol 為喚醒極性定義:Level_High 表??電平喚醒,Level_Low 表?低電平喚醒。
  3. en: 1 表?enable,0 表?disable。

舉例說明:
cpu_set_gpio_wakeup (GPIO_PC2, Level_High, 1); //GPIO_PC2 PAD 喚醒打開, ?電平喚醒
cpu_set_gpio_wakeup (GPIO_PC2, Level_High, 0); //GPIO_PC2 PAD 喚醒關閉
cpu_set_gpio_wakeup (GPIO_PB5, Level_Low, 1); //GPIO_PB5 PAD 喚醒打開, 低電平喚醒
cpu_set_gpio_wakeup (GPIO_PB5, Level_Low, 0); //GPIO_PB5 PAD 喚醒關閉

低功耗模式的進?和喚醒

設置MCU 進?睡眠和喚醒的API 為:

int cpu_sleep_wakeup (SleepMode_TypeDef sleep_mode, SleepWakeupSrc_TypeDef wakeup_src, unsigned int wakeup_tick);
  • 第?個參數sleep_mode:設置sleep mode,有以下4 個選擇,分別表?suspend mode、deepsleep mode、deepsleep retention 16K Sram、deepsleep retention 32K Sram。

typedef enum {
SUSPEND_MODE = 0,
DEEPSLEEP_MODE = 0x80,
DEEPSLEEP_MODE_RET_SRAM_LOW16K = 0x43,
DEEPSLEEP_MODE_RET_SRAM_LOW32K = 0x07,
}SleepMode_TypeDef;

  • 第?個參數wakeup_src:設置當前的suspend/deepsleep 的喚醒源,參數只能是PM_WAKEUP_PAD、PM_WAKEUP_TIMER 中的?個或者多個。如果wakeup_src 為0,那么進?低功耗sleep mode 后,?法被喚醒。
  • 第三個參數“wakeup_tick”:當wakeup_src 中設置了PM_WAKEUP_TIMER 時,需要設置wakeup_tick來決定timer 在何時將MCU 喚醒。如果沒有設置PM_WAKEUP_TIMER 喚醒,該參數?意義。

wakeup_tick 的值是?個絕對值,按照本?檔前?介紹的System Timer tick 來設置,當System Timer tick 的值達到這個設定的wakeup_tick 后,sleep mode 被喚醒。wakeup_tick 的值需要根據當前的System Timer tick的值,加上由需要睡眠的時間換算成的絕對時間,才可以有效地控制睡眠時間。如果沒有考慮當前的SystemTimer tick,直接對wakeup_tick 進?設置,喚醒的時間點就?法控制。
由于wakeup_tick 是絕對時間,必須在32bit 的System Timer tick 能表?的范圍之內,所以這個API 能表?的最?睡眠時間是有限的。?前的設計是最?睡眠時間為32bit 能表?的最?System Timer tick 對應時間的7/8。System Timer tick 最?能表??概268s,那么最?sleep 時間時間為268*7/8=234 s,即下?delta_Tick不能超過234 s, 若需要更?的睡眠時間,user 可以調??睡眠函數,具體可參考4.2.7 章節。

cpu_sleep_wakeup(SUSPEND_MODE, PM_WAKEUP_TIMER, clock_time() + delta_tick);
cpu_sleep_wakeup (SUSPEND_MODE , PM_WAKEUP_PAD, 0);
cpu_sleep_wakeup (SUSPEND_MODE , PM_WAKEUP_PAD | PM_WAKEUP_TIMER,
clock_time() + 50* CLOCK_16M_SYS_TIMER_CLK_1MS);

deepsleep mode

cpu_sleep_wakeup (DEEPSLEEP_MODE, PM_WAKEUP_PAD, 0);
cpu_sleep_wakeup (DEEPSLEEP_MODE_RET_SRAM_LOW32K , PM_WAKEUP_TIMER, clock_time() + 8*
? CLOCK_16M_SYS_TIMER_CLK_1S);
cpu_sleep_wakeup (DEEPSLEEP_MODE_RET_SRAM_LOW32K , PM_WAKEUP_PAD | PM_WAKEUP_TIMER,clock_time()
? + 10* CLOCK_16M_SYS_TIMER_CLK_1S);

低功耗運行流程

  1. no sleep?
    1. 如果沒有sleep mode,MCU 的運?流程為在while(1) 中循環,反復執?“Operation Set A” -????????>“Operation Set B”。
  2. suspend? ?
    1. 如果調?cpu_sleep_wakeup 函數進?suspend mode,當suspend 被喚醒后,相當于cpu_sleep_wakeup 函數的正常退出,MCU 運?到“Operation Set B”。
    2. suspend 是最?凈的sleep mode,在suspend 期間所有的Sram 數據能保持不變,所有的數字/模擬寄存器狀態也保持不變(只有?個特殊的例外);suspend 喚醒后,程序接著原來的位置運?,?乎不需要考慮任何sram和寄存器狀態的恢復。suspend 的缺點是功耗偏?。
  3. deepsleep
    1. 如果調?cpu_sleep_wakeup 函數進?deepsleep mode,當deepsleep 被喚醒后,MCU 會重新回到Runhardware bootloader。
    2. 可以看出,deepsleep wake_up 跟Power on 的流程是?乎?致的,所有的軟硬件初始化都得重新做。MCU 進?deepsleep 后,所有的Sram 和數字/模擬寄存器(只有?個模擬寄存器例外)都會掉電,所以功耗很低,MCU 電流?于1uA。
  4. deepsleep retention
    1. 如果調?cpu_sleep_wakeup 函數進?deepsleep retention mode,當deepsleep retention 被喚醒后,MCU會重新回到Run software bootloader。
    2. deepsleep retention 是介于suspend 和deepsleep 之間的?種sleep mode。
    3. suspend 因為要保存所有的sram 和寄存器狀態?導致電流偏?;deepsleep retention 不需要保存寄存器狀態,Sram 只保留前16K(或32K)不掉電,所以功耗?suspend 低很多,只有2uA 左右。
    4. deepsleep wake_up 后需要把所有的流程重新運??遍,?deepsleep retention 可以跳過“Run hardware bootloader”這?步,這是因為Sram 的前16K(32K)上數據是不丟的,不需要再從flash 上重新拷??次。但由于Sram 上retention area 有限,“run software bootloader”?法跳過,必須得執?;由于deepsleep retention ?法保存寄存器狀態,所以system initilization 必須執?,寄存器的初始化需要重新設置。deepsleep retention wake_up 后的user initilization 可以做?些優化改進,和MCU power on/deepsleep wake_up 后的user initilization 做區分處理,參考本?檔后?的介紹。

API

int pm_is_MCU_deepRetentionWakeup(void);

return 值為1,表?deepsleep retention wake_up;return 值為0,表?power on 或deepsleep wake_up。

void bls_pm_setSuspendMask (u8 mask);
u8 bls_pm_getSuspendMask (void);

mask可以有多個選擇

#define SUSPEND_DISABLE 0
#define SUSPEND_ADV BIT(0)
#define SUSPEND_CONN BIT(1)
#define DEEPSLEEP_RETENTION_ADV BIT(2)
#define DEEPSLEEP_RETENTION_CONN BIT(3)

SUSPEND_DISABLE 表?sleep disable,不允許MCU 進?suspend 和deepsleep retention。

SUSPEND_ADV 和DEEPSLEEP_RETENTION_ADV 分別?于控制Advertising state 時MCU 進?suspend 和deepsleep retention。

SUSPEND_CONN 和DEEPSLEEP_RETENTION_CONN 分別?于控制Conn state Slave role 時MCU 進?suspend和deepsleep retention。

SDK 低功耗sleep mode 的設計上,deepsleep retention 是suspend 的替代模式,?的是降低sleep mode 的功耗。
以Conn state slave role 為例,SDK ?先得看到bltPm.suspend_mask 中SUSPEND_CONN 是否?效,才可以進?suspend。在可以進?suspend 的基礎上,根據實際情況再結合bltPm.suspend_mask 中DEEPSLEEP_RETENTION_CONN 是否?效,才能決定此時suspend mode 是否被切換為deepsleep retention mode。

所以如果user 希望MCU 進?suspend,打開SUSPEND_ADV/SUSPEND_CONN 即可;如果希望MCU 進?deepsleep retention mode,必須同時打開SUSPEND_CONN 和DEEPSLEEP_RETENTION_CONN。

該API 最常?的3 種情況如下:

bls_pm_setSuspendMask(SUSPEND_DISABLE);

MCU 不允許進?sleep mode。

bls_pm_setSuspendMask(SUSPEND_ADV | SUSPEND_CONN);

MCU 在Advertising state 和Conn state Slave role 只允許進?suspend,但是不允許進?deepsleep retention

bls_pm_setSuspendMask(SUSPEND_ADV | DEEPSLEEP_RETENTION_ADV
|SUSPEND_CONN | DEEPSLEEP_RETENTION_CONN);

MCU 在Advertising state 和Conn state Slave role 允許進?suspend 和deepsleep retention,具體進?哪種?sleep mode 由當前sleep 的時間?度決定。

閾值:

blc_pm_setDeepsleepRetentionThreshold(43, 43);

設置43ms

以?個10ms connection interval * (99 + 1) = 1s 的?連接為例進?說明:

在Conn state slave role 時,由于應?層的任務、?動latency 的設置等,會導致MCU suspend 時可能出現10ms、20ms、50ms、100ms、1s 等時間值。根據43ms 的閾值設置,MCU 會?動將50ms、100ms、1s 等suspend 切換為deepsleep retention,?10ms、20ms 等suspend 還是維持suspend,這樣的處理可以保證?個最優的功耗。

connection latency ?效時的Sleep 時序

if(conn_latency != 0)
{latency_use = bls_calculateLatency();T_wakeup = T_brx + (latency_use +1) * conn_interval;
}
else
{T_wakeup = T_brx + conn_interval;
}

當BLE slave 經過connection parameters update(連接參數更新)流程,conn_latency ?效后,sleep wake_up的時間為
T_wakeup = T_brx + (latency_use +1) * conn_interval;
下圖所?為?個conn_latency ?效時的sleep 時序,此時latency_use= 2。

conn_latency 沒有?效時,sleep 的時間最?不超過1 個connection interval (?般都?較?)。由于conn_latency的?效,sleep 的時間可能會出現?個?較?的值,如1s、2s 等,系統功耗可以變得?常低。?sleep 期間使?功耗更?的deepsleep retention mode 才變得有意義。

應?層定時喚醒

應?層定時喚醒API:
void bls_pm_setAppWakeupLowPower(u32 wakeup_tick, u8 enable);

  • wakeup_tick 為定時喚醒的System Timer tick 值;
  • enable 為1 時打開該喚醒功能,enable 為0 時關閉。

以Conn state Slave role 為例:
當user 使?bls_pm_setAppWakeupLowPower 設置了應?層定時喚醒的app_wakeup_tick,SDK 在進?sleep 前,會檢查app_wakeup_tick 是否在T_wakeup 之前。

  • 如果app_wakeup_tick 在T_wakeup 之前,如下圖所?,就會在app_wakeup_tick 觸發sleep 提前喚醒;
  • 如果app_wakeup_tick 在T_wakeup 之后,MCU 還是會在T_wakeup 喚醒。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/92136.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/92136.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/92136.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

設備管理系統(MMS)如何在工廠MOM功能設計和系統落地

一、核心系統功能模塊設備管理系統圍繞設備全生命周期管理設計,涵蓋基礎數據管理、設備運維全流程管控及統計分析功能,具體如下:基礎數據管理設備與備件臺賬:包含設備臺賬(設備編號、識別碼、型號、生產日期等&#xf…

低空經濟展 | 牧羽天航空攜飛行重卡AT1300亮相2025深圳eVTOL展

為深入推動低空經濟產業高質量發展,構建全球eVTOL(電動垂直起降飛行器)產業交流合作高端平臺,2025深圳eVTOL展定于2025年9月23日至25日在深圳坪山燕子湖國際會展中心隆重舉辦。本屆展會以“低空經濟?eVTOL?航空應急救援?商載大…

CS231n-2017 Lecture4神經網絡筆記

神經網絡:我們之前的線性分類器可以接受輸入,進而給出評分,這是一種線性變換,再此基礎上,我們對這種線性變換結果進行非線性變換,并輸入到下一層線性分類器中,這個過程就像是人類大腦神經的運作…

暑期算法訓練.5

目錄 20. 力扣 34.在排序數組中查找元素的第一個位置和最后一個位置 20.1 題目解析: 20.2 算法思路: 20.3 代碼演示: ?編輯 20.4 總結反思: 21.力扣 69.x的平方根 21.1 題目解析: 21.2 算法思路:…

【HDLBits習題詳解 2】Circuit - Sequential Logic(5)Finite State Machines 更新中...

1. Fsm1(Simple FSM 1 - asynchronous reset)狀態機可分為兩類:(1)Mealy狀態機:輸出由當前狀態和輸入共同決定。輸入變化可能立即改變輸出。(2)Moore狀態機:輸出僅由當前…

多級緩存(億級流量緩存)

傳統緩存方案問題 多級緩存方案 流程 1.客戶端瀏覽器緩存頁面靜態資源; 2. 客戶端請求到Nginx反向代理;[一級緩存_瀏覽器緩存] 3.Nginx反向代理將請求分發到Nginx集群(OpenResty); 4.先重Nginx集群OpenResty中獲取Nginx本地緩存數據;[二級緩存_Nginx本地緩存] 5.若Nginx本地緩存…

淺談Rust語言特性

如大家所了解的,Rust是一種由Mozilla開發的系統編程語言,專注于內存安全、并發性和高性能,旨在替代C/C等傳統系統編程語言。Rust 有著非常優秀的特性,例如:可重用模塊 內存安全和保證(安全的操作與不安全的…

React探索高性能Tree樹組件實現——react-window、react-vtree

🚀 簡介 在現代 Web 應用中,處理大量層級數據的樹形結構是一個常見挑戰。傳統的樹組件在面對成千上萬個節點時往往會出現性能瓶頸,導致頁面卡頓、內存占用過高等問題。本文將深入探討如何使用 react-window 和 react-vtree 構建高性能的虛擬…

C++ 中的默認構造函數:非必要,不提供

《More Effective C:35個改善編程與設計的有效方法》 讀書筆記:非必要不提供default constructor在 C 中,默認構造函數(即無需任何參數即可調用的構造函數)是對象“無中生有”的一種方式。它的核心作用是在沒有外部信息…

如何選擇低代碼開發平臺

選擇低代碼開發平臺需要考慮平臺的開發效率、靈活性和擴展能力、安全性和合規性、成本效益等關鍵因素。 具體來說,平臺的靈活性和擴展能力尤為重要,這決定了平臺是否能長期滿足企業日益增長的復雜需求。例如,企業在評估平臺時,應關…

電子數據取證領域的雙輪驅動——手工分析 vs 自動化分析

在你剛步入電子數據取證領域時,可能很快就注意到一個普遍現象:大多數取證分析師前期都花費大量時間在網上查閱博客、PDF、推文等信息,尋找證據線索的“藏身之處”——例如注冊表項、日志文件路徑、可疑文件命名模式或遠程登錄痕跡等。這種信息…

《Python 實時通信全解:掌握 WebSocket 技術與 HTTP 的本質區別》

??《Python 實時通信全解:掌握 WebSocket 技術與 HTTP 的本質區別》 引言:通信方式的演進與 Python 的角色 在數字化世界里,**“實時性”**已經成為構建高質量應用的核心訴求。從聊天工具到股票交易系統,再到物聯網設備管理——通信的即時響應能力直接決定用戶體驗。而…

GeoTools 自定義坐標系

前言在GIS開發中,坐標系統是重中之重,在接到任務時首先要確定的就是坐標系。大多數地圖庫或者互聯網地圖默認支持WGS84地理坐標系和Web墨卡托投影坐標系。而在我國要求使用自然資源數據使用2000國家大地坐標(CGCS2000)。1. 背景 經…

[特殊字符] Java反射從入門到飛升:手撕類結構,動態解析一切![特殊字符]

【🔍震撼揭秘】 你是否曾想窺探Java類的內部結構?🤔 是否好奇Spring框架如何實現"萬物皆可注入"?? 本文將帶你從反射小白晉升為反射高手,用一行代碼透視任意類的構造方法、成員變量和私有方法!&…

CMake與catkin_make的find_package()命令使用說明

在 CMake 中&#xff0c;find_package() 是一個核心函數&#xff0c;用于查找并加載外部依賴庫的配置。它的主要作用是定位頭文件、庫文件&#xff0c;并設置相關變量&#xff0c;以便后續編譯和鏈接。以下是詳細解析&#xff1a; 1. 基本語法 find_package(<PackageName&g…

Spring--BeanFactoryPostProcessor的用法

原文網址&#xff1a;Spring--BeanFactoryPostProcessor的用法_IT利刃出鞘的博客-CSDN博客 簡介 說明 本文介紹Spring的BeanFactoryPostProcessor的用法。 BeanPostProcessor和BeanFactoryPostProcessor的區別 項BeanPostProcessorBeanFactoryPostProcessor處理的對象處理…

了解類加載器嗎?類加載器的類型有哪些?

一、什么是類加載器&#xff08;ClassLoader&#xff09; 類加載器是 Java 虛擬機中的一部分&#xff0c;負責將 .class 文件加載到 JVM 內存中&#xff0c;生成對應的 Class 對象。 Java 程序中所有的類在使用前都必須通過類加載器加載進 JVM&#xff0c;才能被執行。二、類加…

PHP面向對象高級特性:魔術方法、對象迭代器與設計模式應用

引言 在前一篇文章中,我們探討了PHP的Traits、匿名類和對象比較機制。本文將深入PHP面向對象編程的更多高級特性,包括魔術方法、對象迭代器以及常用設計模式的實際應用,這些特性能夠幫助開發者構建更加靈活和強大的面向對象系統。 魔術方法深度解析 魔術方法是PHP中一組以…

【Java基礎】一個月教你輕松掌握Java——第三篇Git

一、Java概述&#xff08;之前的文章&#xff09;二、版本控制工具Git其實這個與Java基礎關系不大&#xff0c;但是這個工具還是很重要的&#xff0c;不管是團隊之間打比賽還是就業都應該學會它&#xff0c;秉持著學的早一些&#xff0c;用的時間長一點&#xff0c;會更熟練。&…

【C# in .NET】16. 探秘類成員-索引器:通過索引訪問對象

探秘類成員-索引器:通過索引訪問對象 在 C# 中,索引器(Indexer)是一種獨特的類成員,它允許類或結構的實例像數組一樣被索引訪問,為數據訪問提供了極大的靈活性。本文將從基礎概念出發,深入.NET 框架底層,剖析索引器的實現機制,并通過實戰案例展示其強大的應用價值。 …