Select one of the symbols to view example projects that use it.
 
Outline
#include <stddef.h>
#include <string.h>
#include <sys/lock.h>
#include <sys/param.h>
#include "esp_log.h"
#include "esp_attr.h"
#include "esp_sleep.h"
#include "esp_check.h"
#include "soc/soc_caps.h"
#include "esp_private/pm_impl.h"
#include "esp_private/sleep_modem.h"
#include "esp_private/sleep_retention.h"
#include "sdkconfig.h"
#include "esp_private/esp_pmu.h"
#include "esp_pau.h"
TAG
#define MAC_BB_POWER_DOWN_CB_NO
#define MAC_BB_POWER_UP_CB_NO
modem_domain_pd_allowed()
sleep_modem_reject_triggers()
sleep_modem_wifi_modem_state_skip_light_sleep()
sleep_modem_configure(int, int, bool)
#define PERIPH_INFORM_OUT_LIGHT_SLEEP_OVERHEAD_NO
s_periph_inform_out_light_sleep_overhead_cb
esp_pm_register_inform_out_light_sleep_overhead_callback(inform_out_light_sleep_overhead_cb_t)
esp_pm_unregister_inform_out_light_sleep_overhead_callback(inform_out_light_sleep_overhead_cb_t)
periph_inform_out_light_sleep_overhead(uint32_t)
s_light_sleep_default_params_config_cb
esp_pm_register_light_sleep_default_params_config_callback(update_light_sleep_default_params_config_cb_t)
esp_pm_unregister_light_sleep_default_params_config_callback()
Files
loading (2/5)...
SourceVuESP-IDF Framework and ExamplesESP-IDFcomponents/esp_hw_support/sleep_modem.c
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
/* * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 *//* ... */ #include <stddef.h> #include <string.h> #include <sys/lock.h> #include <sys/param.h> #include "esp_log.h" #include "esp_attr.h" #include "esp_sleep.h" #include "esp_check.h" #include "soc/soc_caps.h" #include "esp_private/pm_impl.h" #include "esp_private/sleep_modem.h" #include "esp_private/sleep_retention.h" #include "sdkconfig.h"13 includes #if SOC_PM_SUPPORT_PMU_MODEM_STATE #include "esp_private/esp_pmu.h" #endif #if SOC_PM_MODEM_RETENTION_BY_REGDMA #include "esp_pau.h" #endif static __attribute__((unused)) const char *TAG = "sleep_modem"; #if CONFIG_PM_SLP_DEFAULT_PARAMS_OPT static void esp_pm_light_sleep_default_params_config(int min_freq_mhz, int max_freq_mhz); #endif #if SOC_PM_RETENTION_HAS_CLOCK_BUG && CONFIG_MAC_BB_PD static bool s_modem_sleep = false; static uint8_t s_modem_prepare_ref = 0; static _lock_t s_modem_prepare_lock;/* ... */ #endif // SOC_PM_RETENTION_HAS_CLOCK_BUG && CONFIG_MAC_BB_PD #if CONFIG_MAC_BB_PD #define MAC_BB_POWER_DOWN_CB_NO (3) #define MAC_BB_POWER_UP_CB_NO (3) static DRAM_ATTR mac_bb_power_down_cb_t s_mac_bb_power_down_cb[MAC_BB_POWER_DOWN_CB_NO]; static DRAM_ATTR mac_bb_power_up_cb_t s_mac_bb_power_up_cb[MAC_BB_POWER_UP_CB_NO]; esp_err_t esp_register_mac_bb_pd_callback(mac_bb_power_down_cb_t cb) { int index = MAC_BB_POWER_DOWN_CB_NO; for (int i = MAC_BB_POWER_DOWN_CB_NO - 1; i >= 0; i--) { if (s_mac_bb_power_down_cb[i] == cb) { return ESP_OK; }{...} if (s_mac_bb_power_down_cb[i] == NULL) { index = i; }{...} }{...} if (index < MAC_BB_POWER_DOWN_CB_NO) { s_mac_bb_power_down_cb[index] = cb; return ESP_OK; }{...} return ESP_ERR_NO_MEM; }{...} esp_err_t esp_unregister_mac_bb_pd_callback(mac_bb_power_down_cb_t cb) { for (int i = MAC_BB_POWER_DOWN_CB_NO - 1; i >= 0; i--) { if (s_mac_bb_power_down_cb[i] == cb) { s_mac_bb_power_down_cb[i] = NULL; return ESP_OK; }{...} }{...} return ESP_ERR_INVALID_STATE; }{...} void IRAM_ATTR mac_bb_power_down_cb_execute(void) { for (int i = 0; i < MAC_BB_POWER_DOWN_CB_NO; i++) { if (s_mac_bb_power_down_cb[i]) { s_mac_bb_power_down_cb[i](); }{...} }{...} }{...} esp_err_t esp_register_mac_bb_pu_callback(mac_bb_power_up_cb_t cb) { int index = MAC_BB_POWER_UP_CB_NO; for (int i = MAC_BB_POWER_UP_CB_NO - 1; i >= 0; i--) { if (s_mac_bb_power_up_cb[i] == cb) { return ESP_OK; }{...} if (s_mac_bb_power_up_cb[i] == NULL) { index = i; }{...} }{...} if (index < MAC_BB_POWER_UP_CB_NO) { s_mac_bb_power_up_cb[index] = cb; return ESP_OK; }{...} return ESP_ERR_NO_MEM; }{...} esp_err_t esp_unregister_mac_bb_pu_callback(mac_bb_power_up_cb_t cb) { for (int i = MAC_BB_POWER_UP_CB_NO - 1; i >= 0; i--) { if (s_mac_bb_power_up_cb[i] == cb) { s_mac_bb_power_up_cb[i] = NULL; return ESP_OK; }{...} }{...} return ESP_ERR_INVALID_STATE; }{...} void IRAM_ATTR mac_bb_power_up_cb_execute(void) { for (int i = 0; i < MAC_BB_POWER_UP_CB_NO; i++) { if (s_mac_bb_power_up_cb[i]) { s_mac_bb_power_up_cb[i](); }{...} }{...} }{...} /* ... */ #endif ///CONFIG_MAC_BB_PD #if SOC_PM_SUPPORT_PMU_MODEM_STATE typedef struct sleep_modem_config { struct { void *phy_link; union { struct { uint32_t modem_state_phy_done: 1; uint32_t reserved: 31; }{...}; uint32_t flags; }{...}; }{...} wifi; }{...} sleep_modem_config_t; static sleep_modem_config_t s_sleep_modem = { .wifi.phy_link = NULL, .wifi.flags = 0 }; esp_err_t sleep_modem_wifi_modem_state_init(void) { esp_err_t err = ESP_OK; void *link = NULL; if (s_sleep_modem.wifi.phy_link == NULL) { err = sleep_modem_state_phy_link_init(&link); if (err == ESP_OK) { s_sleep_modem.wifi.phy_link = link; s_sleep_modem.wifi.flags = 0; }{...} }{...} return err; }{...} __attribute__((unused)) void sleep_modem_wifi_modem_state_deinit(void) { if (s_sleep_modem.wifi.phy_link) { sleep_modem_state_phy_link_deinit(s_sleep_modem.wifi.phy_link); s_sleep_modem.wifi.phy_link = NULL; s_sleep_modem.wifi.flags = 0; }{...} }{...} void IRAM_ATTR sleep_modem_wifi_do_phy_retention(bool restore) { if (restore) { pau_regdma_trigger_modem_link_restore(); }{...} else { pau_regdma_trigger_modem_link_backup(); s_sleep_modem.wifi.modem_state_phy_done = 1; }{...} }{...} inline __attribute__((always_inline)) bool sleep_modem_wifi_modem_state_enabled(void) { return (s_sleep_modem.wifi.phy_link != NULL); }{...} inline __attribute__((always_inline)) bool sleep_modem_wifi_modem_link_done(void) { return (s_sleep_modem.wifi.modem_state_phy_done == 1); }{...} /* ... */ #endif /* SOC_PM_SUPPORT_PMU_MODEM_STATE */ bool modem_domain_pd_allowed(void) { #if SOC_PM_MODEM_RETENTION_BY_REGDMA const sleep_retention_module_bitmap_t inited_modules = sleep_retention_get_inited_modules(); const sleep_retention_module_bitmap_t created_modules = sleep_retention_get_created_modules(); sleep_retention_module_bitmap_t mask = (sleep_retention_module_bitmap_t){ .bitmap = { 0 } }; #if SOC_WIFI_SUPPORTED mask.bitmap[SLEEP_RETENTION_MODULE_WIFI_MAC >> 5] |= BIT(SLEEP_RETENTION_MODULE_WIFI_MAC % 32); mask.bitmap[SLEEP_RETENTION_MODULE_WIFI_BB >> 5] |= BIT(SLEEP_RETENTION_MODULE_WIFI_BB % 32);/* ... */ #endif #if SOC_BT_SUPPORTED mask.bitmap[SLEEP_RETENTION_MODULE_BLE_MAC >> 5] |= BIT(SLEEP_RETENTION_MODULE_BLE_MAC % 32); mask.bitmap[SLEEP_RETENTION_MODULE_BT_BB >> 5] |= BIT(SLEEP_RETENTION_MODULE_BT_BB % 32);/* ... */ #endif #if SOC_IEEE802154_SUPPORTED mask.bitmap[SLEEP_RETENTION_MODULE_802154_MAC >> 5] |= BIT(SLEEP_RETENTION_MODULE_802154_MAC % 32); mask.bitmap[SLEEP_RETENTION_MODULE_BT_BB >> 5] |= BIT(SLEEP_RETENTION_MODULE_BT_BB % 32);/* ... */ #endif const sleep_retention_module_bitmap_t modem_domain_inited_modules = sleep_retention_module_bitmap_and(inited_modules, mask); const sleep_retention_module_bitmap_t modem_domain_created_modules = sleep_retention_module_bitmap_and(created_modules, mask); return sleep_retention_module_bitmap_eq(modem_domain_inited_modules, modem_domain_created_modules);/* ... */ #else return false; /* MODEM power domain is controlled by each module (WiFi, Bluetooth or 15.4) of modem */ #endif }{ ... } uint32_t IRAM_ATTR sleep_modem_reject_triggers(void) { uint32_t reject_triggers = 0; #if SOC_PM_SUPPORT_PMU_MODEM_STATE reject_triggers = (s_sleep_modem.wifi.phy_link != NULL) ? BIT(16) : 0; #endif return reject_triggers; }{ ... } bool IRAM_ATTR sleep_modem_wifi_modem_state_skip_light_sleep(void) { bool skip = false; #if SOC_PM_SUPPORT_PMU_MODEM_STATE /* To block the system from entering sleep before modem link done. In light * sleep mode, the system may switch to modem state, which will cause * hardware to fail to enable RF *//* ... */ skip = sleep_modem_wifi_modem_state_enabled() && !sleep_modem_wifi_modem_link_done();/* ... */ #endif return skip; }{ ... } esp_err_t sleep_modem_configure(int max_freq_mhz, int min_freq_mhz, bool light_sleep_enable) { #if CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP extern int esp_wifi_internal_light_sleep_configure(bool); esp_wifi_internal_light_sleep_configure(light_sleep_enable);/* ... */ #endif #if CONFIG_PM_SLP_DEFAULT_PARAMS_OPT if (light_sleep_enable) { esp_pm_light_sleep_default_params_config(min_freq_mhz, max_freq_mhz); }{...} #endif/* ... */ return ESP_OK; }{ ... } #define PERIPH_INFORM_OUT_LIGHT_SLEEP_OVERHEAD_NO 2 /* Inform peripherals of light sleep wakeup overhead time */ static inform_out_light_sleep_overhead_cb_t s_periph_inform_out_light_sleep_overhead_cb[PERIPH_INFORM_OUT_LIGHT_SLEEP_OVERHEAD_NO]; esp_err_t esp_pm_register_inform_out_light_sleep_overhead_callback(inform_out_light_sleep_overhead_cb_t cb) { for (int i = 0; i < PERIPH_INFORM_OUT_LIGHT_SLEEP_OVERHEAD_NO; i++) { if (s_periph_inform_out_light_sleep_overhead_cb[i] == cb) { return ESP_OK; }{...} else if (s_periph_inform_out_light_sleep_overhead_cb[i] == NULL) { s_periph_inform_out_light_sleep_overhead_cb[i] = cb; return ESP_OK; }{...} }{...} return ESP_ERR_NO_MEM; }{ ... } esp_err_t esp_pm_unregister_inform_out_light_sleep_overhead_callback(inform_out_light_sleep_overhead_cb_t cb) { for (int i = 0; i < PERIPH_INFORM_OUT_LIGHT_SLEEP_OVERHEAD_NO; i++) { if (s_periph_inform_out_light_sleep_overhead_cb[i] == cb) { s_periph_inform_out_light_sleep_overhead_cb[i] = NULL; return ESP_OK; }{...} }{...} return ESP_ERR_INVALID_STATE; }{ ... } void periph_inform_out_light_sleep_overhead(uint32_t out_light_sleep_time) { for (int i = 0; i < PERIPH_INFORM_OUT_LIGHT_SLEEP_OVERHEAD_NO; i++) { if (s_periph_inform_out_light_sleep_overhead_cb[i]) { s_periph_inform_out_light_sleep_overhead_cb[i](out_light_sleep_time); }{...} }{...} }{ ... } static update_light_sleep_default_params_config_cb_t s_light_sleep_default_params_config_cb = NULL; void esp_pm_register_light_sleep_default_params_config_callback(update_light_sleep_default_params_config_cb_t cb) { if (s_light_sleep_default_params_config_cb == NULL) { s_light_sleep_default_params_config_cb = cb; }{...} }{ ... } void esp_pm_unregister_light_sleep_default_params_config_callback(void) { if (s_light_sleep_default_params_config_cb) { s_light_sleep_default_params_config_cb = NULL; }{...} }{ ... } #if CONFIG_PM_SLP_DEFAULT_PARAMS_OPT static void esp_pm_light_sleep_default_params_config(int min_freq_mhz, int max_freq_mhz) { if (s_light_sleep_default_params_config_cb) { (*s_light_sleep_default_params_config_cb)(min_freq_mhz, max_freq_mhz); }{...} }{...} /* ... */#endif #if SOC_PM_RETENTION_HAS_CLOCK_BUG && CONFIG_MAC_BB_PD void sleep_modem_register_mac_bb_module_prepare_callback(mac_bb_power_down_cb_t pd_cb, mac_bb_power_up_cb_t pu_cb) { _lock_acquire(&s_modem_prepare_lock); if (s_modem_prepare_ref++ == 0) { esp_register_mac_bb_pd_callback(pd_cb); esp_register_mac_bb_pu_callback(pu_cb); }{...} _lock_release(&s_modem_prepare_lock); }{...} void sleep_modem_unregister_mac_bb_module_prepare_callback(mac_bb_power_down_cb_t pd_cb, mac_bb_power_up_cb_t pu_cb) { _lock_acquire(&s_modem_prepare_lock); assert(s_modem_prepare_ref); if (--s_modem_prepare_ref == 0) { esp_unregister_mac_bb_pd_callback(pd_cb); esp_unregister_mac_bb_pu_callback(pu_cb); }{...} _lock_release(&s_modem_prepare_lock); }{...} /** * @brief Switch root clock source to PLL do retention and switch back * * This function is used when Bluetooth/IEEE802154 module requires register backup/restore, this function * is called ONLY when SOC_PM_RETENTION_HAS_CLOCK_BUG is set. * @param backup true for backup, false for restore * @param cpu_freq_mhz cpu frequency to do retention * @param do_retention function for retention *//* ... */ static void IRAM_ATTR rtc_clk_cpu_freq_to_pll_mhz_and_do_retention(bool backup, int cpu_freq_mhz, void (*do_retention)(bool)) { #if SOC_PM_SUPPORT_PMU_MODEM_STATE if (pmu_sleep_pll_already_enabled()) { return; }{...} /* ... */#endif rtc_cpu_freq_config_t config, pll_config; rtc_clk_cpu_freq_get_config(&config); rtc_clk_cpu_freq_mhz_to_config(cpu_freq_mhz, &pll_config); rtc_clk_cpu_freq_set_config(&pll_config); if (do_retention) { (*do_retention)(backup); }{...} rtc_clk_cpu_freq_set_config(&config); }{...} void IRAM_ATTR sleep_modem_mac_bb_power_down_prepare(void) { if (s_modem_sleep == false) { rtc_clk_cpu_freq_to_pll_mhz_and_do_retention(true, CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ, sleep_retention_do_extra_retention); s_modem_sleep = true; }{...} }{...} void IRAM_ATTR sleep_modem_mac_bb_power_up_prepare(void) { if (s_modem_sleep) { rtc_clk_cpu_freq_to_pll_mhz_and_do_retention(false, CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ, sleep_retention_do_extra_retention); s_modem_sleep = false; }{...} }{...} /* ... */#endif /* SOC_PM_RETENTION_HAS_CLOCK_BUG && CONFIG_MAC_BB_PD */
Details