Skip to content

Commit

Permalink
fix(uart): Fix mismatch wakeup rising edges required with the thresho…
Browse files Browse the repository at this point in the history
…ld configured

Closes #12586
  • Loading branch information
songruo committed Mar 15, 2024
1 parent 3cd174a commit 90bf277
Show file tree
Hide file tree
Showing 14 changed files with 34 additions and 18 deletions.
2 changes: 1 addition & 1 deletion components/esp_driver_uart/src/uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -1792,7 +1792,7 @@ esp_err_t uart_get_collision_flag(uart_port_t uart_num, bool *collision_flag)
esp_err_t uart_set_wakeup_threshold(uart_port_t uart_num, int wakeup_threshold)
{
ESP_RETURN_ON_FALSE((uart_num < UART_NUM_MAX), ESP_ERR_INVALID_ARG, UART_TAG, "uart_num error");
ESP_RETURN_ON_FALSE((wakeup_threshold <= UART_THRESHOLD_NUM(uart_num, UART_ACTIVE_THRESHOLD_V) && wakeup_threshold > UART_MIN_WAKEUP_THRESH), ESP_ERR_INVALID_ARG, UART_TAG,
ESP_RETURN_ON_FALSE((wakeup_threshold <= UART_THRESHOLD_NUM(uart_num, UART_ACTIVE_THRESHOLD_V) && wakeup_threshold >= UART_MIN_WAKEUP_THRESH), ESP_ERR_INVALID_ARG, UART_TAG,
"wakeup_threshold out of bounds");
UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock));
uart_hal_set_wakeup_thrd(&(uart_context[uart_num].hal), wakeup_threshold);
Expand Down
10 changes: 6 additions & 4 deletions components/hal/esp32/include/hal/uart_ll.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand Down Expand Up @@ -30,7 +30,7 @@ extern "C" {
// The timeout calibration factor when using ref_tick
#define UART_LL_TOUT_REF_FACTOR_DEFAULT (8)

#define UART_LL_MIN_WAKEUP_THRESH (2)
#define UART_LL_MIN_WAKEUP_THRESH (3)
#define UART_LL_INTR_MASK (0x7ffff) //All interrupt mask

// Define UART interrupts
Expand Down Expand Up @@ -692,7 +692,9 @@ FORCE_INLINE_ATTR void uart_ll_set_dtr_active_level(uart_dev_t *hw, int level)
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_thrd(uart_dev_t *hw, uint32_t wakeup_thrd)
{
hw->sleep_conf.active_threshold = wakeup_thrd - UART_LL_MIN_WAKEUP_THRESH;
// System would wakeup when the number of positive edges of RxD signal is larger than or equal to (UART_ACTIVE_THRESHOLD+2)
// Note: On ESP32, the minimum UART wakeup threshold is 2 + 1 = 3 (UART_ACTIVE_THRESHOLD set to 0 leads to consecutive triggering wakeup)
hw->sleep_conf.active_threshold = wakeup_thrd - (UART_LL_MIN_WAKEUP_THRESH - 1);
}

/**
Expand Down Expand Up @@ -834,7 +836,7 @@ FORCE_INLINE_ATTR void uart_ll_get_at_cmd_char(uart_dev_t *hw, uint8_t *cmd_char
*/
FORCE_INLINE_ATTR uint32_t uart_ll_get_wakeup_thrd(uart_dev_t *hw)
{
return hw->sleep_conf.active_threshold + UART_LL_MIN_WAKEUP_THRESH;
return hw->sleep_conf.active_threshold + (UART_LL_MIN_WAKEUP_THRESH - 1);
}

/**
Expand Down
3 changes: 2 additions & 1 deletion components/hal/esp32c2/include/hal/uart_ll.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ extern "C" {
// Get UART hardware instance with giving uart num
#define UART_LL_GET_HW(num) (((num) == UART_NUM_0) ? (&UART0) : (&UART1))

#define UART_LL_MIN_WAKEUP_THRESH (2)
#define UART_LL_MIN_WAKEUP_THRESH (3)
#define UART_LL_INTR_MASK (0x7ffff) //All interrupt mask

#define UART_LL_FSM_IDLE (0x0)
Expand Down Expand Up @@ -675,6 +675,7 @@ FORCE_INLINE_ATTR void uart_ll_set_dtr_active_level(uart_dev_t *hw, int level)
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_thrd(uart_dev_t *hw, uint32_t wakeup_thrd)
{
// System would wakeup when the number of positive edges of RxD signal is larger than or equal to (UART_ACTIVE_THRESHOLD+3)
hw->sleep_conf.active_threshold = wakeup_thrd - UART_LL_MIN_WAKEUP_THRESH;
}

Expand Down
3 changes: 2 additions & 1 deletion components/hal/esp32c3/include/hal/uart_ll.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ extern "C" {
// Get UART hardware instance with giving uart num
#define UART_LL_GET_HW(num) (((num) == UART_NUM_0) ? (&UART0) : (&UART1))

#define UART_LL_MIN_WAKEUP_THRESH (2)
#define UART_LL_MIN_WAKEUP_THRESH (3)
#define UART_LL_INTR_MASK (0x7ffff) //All interrupt mask

#define UART_LL_FSM_IDLE (0x0)
Expand Down Expand Up @@ -678,6 +678,7 @@ FORCE_INLINE_ATTR void uart_ll_set_dtr_active_level(uart_dev_t *hw, int level)
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_thrd(uart_dev_t *hw, uint32_t wakeup_thrd)
{
// System would wakeup when the number of positive edges of RxD signal is larger than or equal to (UART_ACTIVE_THRESHOLD+3)
hw->sleep_conf.active_threshold = wakeup_thrd - UART_LL_MIN_WAKEUP_THRESH;
}

Expand Down
3 changes: 2 additions & 1 deletion components/hal/esp32c5/include/hal/uart_ll.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ extern "C" {

#define UART_LL_REG_FIELD_BIT_SHIFT(hw) (((hw) == &LP_UART) ? 3 : 0)

#define UART_LL_MIN_WAKEUP_THRESH (2)
#define UART_LL_MIN_WAKEUP_THRESH (3)
#define UART_LL_INTR_MASK (0x7ffff) //All interrupt mask

#define UART_LL_FSM_IDLE (0x0)
Expand Down Expand Up @@ -897,6 +897,7 @@ FORCE_INLINE_ATTR void uart_ll_set_dtr_active_level(uart_dev_t *hw, int level)
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_thrd(uart_dev_t *hw, uint32_t wakeup_thrd)
{
// System would wakeup when the number of positive edges of RxD signal is larger than or equal to (UART_ACTIVE_THRESHOLD+3)
hw->sleep_conf2.active_threshold = wakeup_thrd - UART_LL_MIN_WAKEUP_THRESH;
}

Expand Down
3 changes: 2 additions & 1 deletion components/hal/esp32c6/include/hal/uart_ll.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ extern "C" {

#define UART_LL_REG_FIELD_BIT_SHIFT(hw) (((hw) == &LP_UART) ? 3 : 0)

#define UART_LL_MIN_WAKEUP_THRESH (2)
#define UART_LL_MIN_WAKEUP_THRESH (3)
#define UART_LL_INTR_MASK (0x7ffff) //All interrupt mask

#define UART_LL_FSM_IDLE (0x0)
Expand Down Expand Up @@ -867,6 +867,7 @@ FORCE_INLINE_ATTR void uart_ll_set_dtr_active_level(uart_dev_t *hw, int level)
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_thrd(uart_dev_t *hw, uint32_t wakeup_thrd)
{
// System would wakeup when the number of positive edges of RxD signal is larger than or equal to (UART_ACTIVE_THRESHOLD+3)
hw->sleep_conf2.active_threshold = wakeup_thrd - UART_LL_MIN_WAKEUP_THRESH;
}

Expand Down
3 changes: 2 additions & 1 deletion components/hal/esp32h2/include/hal/uart_ll.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ extern "C" {
// Get UART hardware instance with giving uart num
#define UART_LL_GET_HW(num) (((num) == UART_NUM_0) ? (&UART0) : (&UART1))

#define UART_LL_MIN_WAKEUP_THRESH (2)
#define UART_LL_MIN_WAKEUP_THRESH (3)
#define UART_LL_INTR_MASK (0x7ffff) //All interrupt mask

#define UART_LL_FSM_IDLE (0x0)
Expand Down Expand Up @@ -717,6 +717,7 @@ FORCE_INLINE_ATTR void uart_ll_set_dtr_active_level(uart_dev_t *hw, int level)
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_thrd(uart_dev_t *hw, uint32_t wakeup_thrd)
{
// System would wakeup when the number of positive edges of RxD signal is larger than or equal to (UART_ACTIVE_THRESHOLD+3)
hw->sleep_conf2.active_threshold = wakeup_thrd - UART_LL_MIN_WAKEUP_THRESH;
}

Expand Down
3 changes: 2 additions & 1 deletion components/hal/esp32p4/include/hal/uart_ll.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ extern "C" {

#define UART_LL_REG_FIELD_BIT_SHIFT(hw) (((hw) == &LP_UART) ? 3 : 0)

#define UART_LL_MIN_WAKEUP_THRESH (2)
#define UART_LL_MIN_WAKEUP_THRESH (3)
#define UART_LL_INTR_MASK (0x7ffff) //All interrupt mask

#define UART_LL_FSM_IDLE (0x0)
Expand Down Expand Up @@ -980,6 +980,7 @@ FORCE_INLINE_ATTR void uart_ll_set_dtr_active_level(uart_dev_t *hw, int level)
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_thrd(uart_dev_t *hw, uint32_t wakeup_thrd)
{
// System would wakeup when the number of positive edges of RxD signal is larger than or equal to (UART_ACTIVE_THRESHOLD+3)
hw->sleep_conf2.active_threshold = wakeup_thrd - UART_LL_MIN_WAKEUP_THRESH;
}

Expand Down
3 changes: 2 additions & 1 deletion components/hal/esp32s2/include/hal/uart_ll.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ extern "C" {
// Get UART hardware instance with giving uart num
#define UART_LL_GET_HW(num) (((num) == UART_NUM_0) ? (&UART0) : (&UART1))

#define UART_LL_MIN_WAKEUP_THRESH (2)
#define UART_LL_MIN_WAKEUP_THRESH (3)
#define UART_LL_INTR_MASK (0x7ffff) //All interrupt mask

// Define UART interrupts
Expand Down Expand Up @@ -633,6 +633,7 @@ FORCE_INLINE_ATTR void uart_ll_set_dtr_active_level(uart_dev_t *hw, int level)
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_thrd(uart_dev_t *hw, uint32_t wakeup_thrd)
{
// System would wakeup when the number of positive edges of RxD signal is larger than or equal to (UART_ACTIVE_THRESHOLD+3)
hw->sleep_conf.active_threshold = wakeup_thrd - UART_LL_MIN_WAKEUP_THRESH;
}

Expand Down
3 changes: 2 additions & 1 deletion components/hal/esp32s3/include/hal/uart_ll.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ extern "C" {
// Get UART hardware instance with giving uart num
#define UART_LL_GET_HW(num) (((num) == UART_NUM_0) ? (&UART0) : (((num) == UART_NUM_1) ? (&UART1) : (&UART2)))

#define UART_LL_MIN_WAKEUP_THRESH (2)
#define UART_LL_MIN_WAKEUP_THRESH (3)
#define UART_LL_INTR_MASK (0x7ffff) //All interrupt mask

#define UART_LL_FSM_IDLE (0x0)
Expand Down Expand Up @@ -661,6 +661,7 @@ FORCE_INLINE_ATTR void uart_ll_set_dtr_active_level(uart_dev_t *hw, int level)
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_thrd(uart_dev_t *hw, uint32_t wakeup_thrd)
{
// System would wakeup when the number of positive edges of RxD signal is larger than or equal to (UART_ACTIVE_THRESHOLD+3)
hw->sleep_conf.active_threshold = wakeup_thrd - UART_LL_MIN_WAKEUP_THRESH;
}

Expand Down
2 changes: 2 additions & 0 deletions docs/en/api-reference/system/sleep_modes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,8 @@ When {IDF_TARGET_NAME} receives UART input from external devices, it is often ne

:cpp:func:`esp_sleep_enable_uart_wakeup` function can be used to enable this wakeup source.

After waking-up from UART, you should send some extra data through the UART port in Active mode, so that the internal wakeup indication signal can be cleared. Otherwises, the next UART wake-up would trigger with two less rising edges than the configured threshold value.

.. only:: esp32c6 or esp32h2

.. note::
Expand Down
2 changes: 2 additions & 0 deletions docs/zh_CN/api-reference/system/sleep_modes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,8 @@ UART 唤醒(仅适用于 Light-sleep 模式)

可调用 :cpp:func:`esp_sleep_enable_uart_wakeup` 函数来启用此唤醒源。

使用 UART 唤醒之后,在芯片 Active 模式下需要让 UART 接受一些数据用来清零内部的唤醒指示信号。不然的话,下一次 UART 唤醒的触发将只需要比配置的阈值少两个上升沿的数量。

.. only:: esp32c6 or esp32h2

.. note::
Expand Down
6 changes: 4 additions & 2 deletions examples/system/light_sleep/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ The example enables the following wakeup sources:

- Timer: wake up the chip in 2 seconds
- EXT0: wake up the chip if a button attached to GPIO0 is pressed (i.e. if GPIO0 goes low)
- UART0: wake up the chip when the uart rx pin (default GPIO6) receive more than 3 edges.
- UART0: wake up the chip when the uart rx pin receive more than or equal to 3 rising edges.

The example also prints time spent in light sleep mode to illustrate that timekeeping continues while the chip is in light sleep.

Expand Down Expand Up @@ -60,12 +60,14 @@ For this example, the wake-up GPIO is bound to the 'BOOT' button on the board, w

For this example, the wake-up UART is bound to the default console port (UART_NUM_0), we can wake-up the chip from light sleep by inputting some keys on the key board. We can see the wake-up reason is `uart` in this case.

Note #1: the UART wake-up threshould is set to 3 in this example, which means the ascii code of the input character should has at least 3 edges, for example, the ascii code of character `0` is `0011 0000` in binary, which only contains 2 edges, so the character `0` is not enough to wakeup the chip.
Note #1: the UART wake-up threshould is set to 3 in this example, which means the ascii code of the input character to wake-up the chip should has at least 3 rising edges (including the stop bit per character), for example, the ascii code of character `0` is `0011 0000` in binary, which only contains 2 rising edges, so the character `0` is not enough to wakeup the chip.

Note #2: only UART0 and UART1 (if has) are supported to be configured as wake up source. And for ESP32, we have to use iomux pin for RX signal (i.e. GPIO3 for UART0 & GPIO9 for UART1), otherwise it won't success.

Note #3: due to limitation of the HW, the bytes that received during light sleep is only used for waking up, and it will not be received by UART peripheral or passed to the driver.

Note #4: after waking-up from UART, you should send some extra data through the UART port, so that the internal wakeup indication signal can be cleared. Otherwises, the next UART wake-up would trigger with two less rising edges than the configured threshold value.

### Wake-up by Touch Pad

For this example, pressing any registered touch buttons can wake up the chip.
Expand Down
6 changes: 3 additions & 3 deletions examples/system/light_sleep/pytest_light_sleep.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import logging
import time
Expand Down Expand Up @@ -52,8 +52,8 @@ def test_light_sleep(dut: Dut) -> None:
dut.expect_exact(ENTERING_SLEEP_STR)
logging.info('Went to sleep again')

# Write 'U' to uart, 'U' in ascii is 0x55 which contains 8 edges in total
dut.write('U')
# Write 'a' to uart, 'a' in ascii is 0x61 which contains 3 rising edges in total (including the stop bit)
dut.write('a')
time.sleep(1)
match = dut.expect(EXIT_SLEEP_UART_REGEX)
logging.info('Got third sleep period, wakeup from {}, slept for {}'.format(match.group(1), match.group(3)))
Expand Down

0 comments on commit 90bf277

Please sign in to comment.