Skip to content

Commit

Permalink
doc(sleep): add DFS and light-sleep test case and test result
Browse files Browse the repository at this point in the history
  • Loading branch information
koobest authored and costaud committed Nov 23, 2017
1 parent 3fcb37b commit 4aab0c5
Show file tree
Hide file tree
Showing 12 changed files with 422 additions and 0 deletions.
157 changes: 157 additions & 0 deletions documents/DFS_and_light_sleep/DFS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
## DFS testing report
Dynamic frequency scaling(DSF) is another low-power approach that ESP32 provides. in applications, we can adjust APB and CPU frequency.

This article shows how to set and use the DFS feature and how it performs. At the beginning of this article is how to configure DFS, and in the end is the test data.


### Configuration

1 Enable Power management
-

First of all, we should enable power management function by enalbing `PM_ENABLE` option in menuconfig.

`make menuconfig -->Componment config -->Power Management`

2 Enable DFS
-

In application codes, wen can call `esp_pm_configure()` to enable DFS.

For example:

```
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");
}
```

3 Initialize a lock handle
-

When DFS feature is enabled, call `esp_pm_lock_create` to initialize a lock handle with a certain power management parameter.

```
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"));
}
```

4 Switch CPU's frequency
-

If a lock handle was acquire by `esp_pm_lock_acquire`, CPU's frequency switched(ESP_PM_APB_FREQ_MAX and ESP_PM_CPU_FREQ_MAX type of lock have the same effect). Locks are recursive, so if `esp_pm_lock_acquire` is called a number of times, `esp_pm_lock_release` has to be called the same number of times in order to actually release the lock.

```
if(esp_pm_lock_acquire(pm_lock) == ESP_OK) {
printf("lock acquire successed\n");
vTaskDelay(2000 / portTICK_PERIOD_MS);
esp_pm_lock_release(pm_lock);
vTaskDelay(2000 / portTICK_PERIOD_MS);
}
```
---
### Attentions

If `esp_pm_lock_acquire` returns ESP_OK, the CPU's frequency will switch to the `max_cpu_freq`. Before `esp_pm_lock_release` is called, the frequency will not change. If `esp_pm_lock_release` returned ESP_OK, however, the CPU's freq will not immediately switched to `min_cpu_freq`, the CPU's frequency will switch to `min_cpu_freq` only after all task are suspended. Some examples bellow.

`For the sake of simplicity, we assume that there is only one task`

```
/*
max_cpu_freq = RTC_CPU_FREQ_240M
min_cpu_freq = RTC_CPU_FREQ_XTAL
*/
1. void pm_test_task(void *param)
2. {
3. if(esp_pm_lock_acquire(pm_lock) == ESP_OK) { // acquire a lock
4. vTaskDelay(20 / portTICK_PERIOD_MS); // block task
5. for(int i = 0; i <100000; i++); // do a loop
6. vTaskDelay(20 / portTICK_PERIOD_MS); // block task
7. esp_pm_lock_release(pm_lock); // release the lock
8. for(int i = 0; i <100000; i++); // do a loop
9. vTaskDelay(20 / portTICK_PERIOD_MS); // block task
10. for(int i = 0; i <100000; i++); // do a loop
11. vTaskDelay(20 / portTICK_PERIOD_MS); // block task
12. }
13. }
```

- during the delay time in line 4, the CPU's frequency will be 240MHz
- the code in line 8 and line 10 will be executed at 240MHz
- during the delay time in line 9 and line 11, the CPU's frequency will switch to 40MHz(RTC_CPU_FREQ_XTAL)


Here is a test to prove this. First, configure LEDC to output 5KHz PWM signal and chosse APB clock as timer clock. So, if chip enter power save mode, the APB clock will switch to 40MHz, and the LEDC's frequency will reduce to half of the original one(2.5kHz). The first picture shows the LEDC waveform when executing code line 3 to line 4, meanwhile, the second one shows the waveform when executing code from line 5 to line 6.

| | |
|--:|:--|
|<img src="../_static/testcase/DFS_and_light_sleep/pic4.svg.png" height=230, width=300, align=center>| When pm_lock are acquired, LEDC's frequency keeps 5kHz, this indicates that APB frequency is 80MHz, the CPU frequency is 240MHz and has not been changed during the hold of this pm_lock.|
|<img src="../_static/testcase/DFS_and_light_sleep/pic3.svg.png" height=230 width=360>| After pm_lock are released, when task is suspended, LEDC's frequency becomes to 2.5kHz. otherwise, LEDC's frequency is 5kHz.|










5 REF_TICK
-
Normally, APB frequency is 80MHz, when system goes into lower power mode, APB frequency will switch to 40MHz(RTC_CPU_FREQ_XTAL). This will affect the peripheral who's clock source is APB clock. But some peripherals can use REF_TICK as clock source. these peripherals can work even when APB frequency is changing. These peripherals are listed below:

- UART
- LEDC
- RMT

Here's a case of LEDC.

```
1. if(esp_pm_lock_acquire(pm_lock) == ESP_OK)
2. {
3. gpio_set_level(18,1);
4. vTaskDelay(500 / portTICK_PERIOD_MS);
5. esp_pm_lock_release(pm_lock);
6. vTaskDelay(500 / portTICK_PERIOD_MS);
7. gpio_set_level(18,0);
8. vTaskDelay(20 / portTICK_PERIOD_MS);
9. }
```

| | |
|--:|:--|
|<img src="../_static/testcase/DFS_and_light_sleep/pic5.svg.png" height=230 width=360> |Configure REF_TICK as LEDC's clock source. during the high level of GPIO18 output, When the sixth line of `vTaskDelay` is executedthe, CPU clock will be cut to 40M, but LEDC frequency will not change. |






### Current Test

We created a task to test DFS, and result are as follows:

| CPU freq | current consumption |
| :---: | :---: |
|XTAL(40MHz)| 13.32mA |
| 80MHz | 22.85mA |
| 160MHz | 28.46mA |
| 240MHz | 39.95mA |

More informations about DFS, please Visit [Power Management](http://esp-idf.readthedocs.io/en/latest/api-reference/system/power_management.html)
23 changes: 23 additions & 0 deletions documents/DFS_and_light_sleep/light_sleep.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
## Current test report during force light-sleep mode

Light-sleep is another power saving mode. In Light-sleep mode, CPUs, digital peripherals and most of the RAM are clock-gated, and supply voltage is reduced. Upon exit from Light-sleep, peripherals and CPUs resume operation, their internal state is preserved. By calling `esp_err_t esp_light_sleep_start()`, application can enter light sleep mode.

This document gives a brief introduction of the ESP32's current consumption during Light-sleep mode and the results are as follows.


|Description|Waveform|TestCode|
|--|--|--|
| First we have a test about the time to sleep. We set a GPIO(GPIO18 in this case) from high to low level before we call `esp_light_sleep_start` to start the light-sleep mode. As shown below, after about **200us**, the chip completely goes to Light-sleep. | <img src="../_static/testcase/DFS_and_light_sleep/pic1.svg.png" height=250 width=350 align=center> | gpio_set_level(GPIO_NUM_18, 1);<br>vTaskDelay(2000 / portTICK_PERIOD_MS);<br>gpio_set_level(GPIO_NUM_18, 0);<br>esp_light_sleep_start(); |
| Second test is the time to resume from light_sleep. After chip was waked up, the program is executed from where it was last stopped, rather than restart. So We configure ext0 as wake up source, and about **566us** after ext0 source triggered, the chip resumed operation and GPIO18 output low. Figure shows this process.|<img src="../_static/testcase/DFS_and_light_sleep/pic2.svg.png" height=230 width=360>|esp_sleep_enable_ext0_wakeup(GPIO_NUM_34, 0);<br>gpio_set_level(GPIO_NUM_18, 0);<br>esp_light_sleep_start();<br>gpio_set_level(GPIO_NUM_18, 1);<br>|

---

Finally, the current during sleep was tested. We can wake the chip up from Light-sleep by different means, such as ext0, ext1 and timer. Different ways to take, the current consumption during Light-sleep will be different. the results are as follows.

| Wake source | current consumption during sleep |
| :---: | :---: |
| ext0 | 1.15mA |
| ext1 | 1.14mA |
| timer | 0.79mA |

Before enter Light-sleep, Those GPIO who powered by VDD3P3_CPU should be all disabled. otherwise, the current will be higher(about 1.5mA) due to GPIO leakage current.
70 changes: 70 additions & 0 deletions documents/DFS_and_light_sleep/light_sleep_current_test.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
## Ligth_sleep 电流测试步骤

这篇文档将介绍如何在 esp-iot-solution 平台下进行 Light_sleep 期间电流的测试. Light_sleep 测试代码在 esp-iot-solution 中可以找到[测试代码链接](/tools/unit-test-app/components/light_sleep).

- **1. 工具链的安装**

esp-iot-solution 使用 esp-idf 同一套工具链, 所以如果你的平台上能够编译 esp-idf 中的 example, 则工具链无须重复安装. 工具链的详细安装步骤可以在 [ESP-IDF Programming Guide](https://esp-idf.readthedocs.io/en/latest/get-started/index.html) 找到, 这里与不多加描述.

- **2. 测试代码下载**

你需要将完整的 esp-iot-solution 工程下载下来, 才能进行测试. 使用如下指令:

```
1. $ git clone ssh://[email protected]:27227/rd/esp-iot-solution.git
2. $ cd esp-iot-solution
3. $ git submodule update --init --recursive
```

更新 submodule 需要花费一点时间, 所以请耐心等待. 如果本地已经有 esp-iot-solution 仓库, 请更新到最新版本.

- **3. 测试代码编译及下载**

esp-iot-solution 里放置了很多测试代码和示例工程, 一般是放在 `esp-iot-solution/components``esp-iot-solution/tools/unit-test-app/components` 目录下. 所有测试代码编译方式都基本相同, 这里以 Light_sleep 为示例(Light_sleep测试代码放在了 `esp-iot-solution/tools/unit-test-app/components` 目录下).

* 1 工程配置

```
1. $ make menuconfig
```

在 menuconfig-->Serial flasher config 中修改串口号和波特率.

- 2 代码编译

```
1. $ cd esp-iot-solution/tools/unit-test-app
2. $ make TEST_COMPONENTS=light_sleep
```

- 3 固件烧写

代码编译通过后, 将编译生成的 .bin 文件烧写到开发板上. 首先将 GPIO0 拉低, 然后按下复位键让芯片进入下载模式. 执行指令:

```
1. $ make flash
```

`波特率太高, 可能会下载失败, 太低则烧写过程缓慢. 一般可以配置成 921600.`

(Light_sleep 测试代码可以直接在 ESP32_ULP_EB 测试板上进行测试. 如果使用其他开发板, 请修改测试代码后再进行测试).

- **4. Light_sleep 电流测试**

打开串口终端, 按下复位键后, 芯片启动, 你将看到如下打印信息:

```
...
Here's the test menu, pick your combo:
(1) "Light_sleep get wake_up cause test" [light_sleep][iot]
(2) "Light_sleep EXT0 wakeup test" [light_sleep][iot]
(3) "Light_sleep EXT1 wakeup test" [light_sleep][iot]
(4) "Light_sleep touch_pad wakeup test" [light_sleep][iot]
(5) "Light_sleep time wakeup test" [light_sleep][iot]
(6) "Time to enter light_sleep test" [light_sleep][iot]
```

log 上列举的就是我们可以进行的测试选项, 输入 5 则进行 Light_sleep time wakeup test. 在 Light_sleep 期间, 我们可以对电流进行测试.[接线图](/documents/low_power_solution/esp32_ulp_eb.md#53-%E7%BC%96%E8%AF%91%E4%B8%8E%E8%BF%90%E8%A1%8C). Light_sleep 期间, 电流是 800uA 左右.

`Note : 在 Light_sleep 期间, 会有部分 GPIO(GPIO18, GPIO19, GPIO21, GGPIO22) 漏电, 所以建议在调用 esp_light_sleep_start 之前, 可以调用gpio_set_direction(), 将这些 GPIO 的输入与输出关闭.`
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions tools/unit-test-app/components/light_sleep/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# light_sleep wake_up test

This test case provides the following tests:

- EXT0 wake up test, we use rtc_io 34 as trigger source. After entering light_sleep mode, set this io low will wake up system.

- EXT1 wake up test, we use rtc_io 34, 35, 36 and 39 as trigger source. After entering light_sleep mode, set them all low at the sametime will wake system up.

- Timer wakeup, 50 seconds later , system will waked up by timer after entering light_sleep mode.

- Touch_Pad wake_up, touch pad_7 will wake up system during light_sleep mode.

- After system waked up, you can run `Deep_sleep get wake_up cause test` to get what waked the system up.
5 changes: 5 additions & 0 deletions tools/unit-test-app/components/light_sleep/component.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#
# "main" pseudo-component makefile.
#
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)

5 changes: 5 additions & 0 deletions tools/unit-test-app/components/light_sleep/test/component.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#
#Component Makefile
#

COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive
Loading

0 comments on commit 4aab0c5

Please sign in to comment.