uart: support light sleep on esp32s3

This commit is contained in:
laokaiyao
2022-01-12 11:03:38 +08:00
parent 1d31a493e4
commit ac67d5dd35
14 changed files with 106 additions and 199 deletions

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -58,7 +58,7 @@ typedef enum {
UART_PARITY_ERR, /*!< UART RX parity event*/ UART_PARITY_ERR, /*!< UART RX parity event*/
UART_DATA_BREAK, /*!< UART TX data and break event*/ UART_DATA_BREAK, /*!< UART TX data and break event*/
UART_PATTERN_DET, /*!< UART pattern detected */ UART_PATTERN_DET, /*!< UART pattern detected */
#if SOC_UART_SUPPORT_WAKEUP #if SOC_UART_SUPPORT_WAKEUP_INT
UART_WAKEUP, /*!< UART wakeup event */ UART_WAKEUP, /*!< UART wakeup event */
#endif #endif
UART_EVENT_MAX, /*!< UART event max index*/ UART_EVENT_MAX, /*!< UART event max index*/

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -59,7 +59,7 @@ static const char *UART_TAG = "uart";
#define UART_PATTERN_DET_QLEN_DEFAULT (10) #define UART_PATTERN_DET_QLEN_DEFAULT (10)
#define UART_MIN_WAKEUP_THRESH (UART_LL_MIN_WAKEUP_THRESH) #define UART_MIN_WAKEUP_THRESH (UART_LL_MIN_WAKEUP_THRESH)
#if SOC_UART_SUPPORT_WAKEUP #if SOC_UART_SUPPORT_WAKEUP_INT
#define UART_INTR_CONFIG_FLAG ((UART_INTR_RXFIFO_FULL) \ #define UART_INTR_CONFIG_FLAG ((UART_INTR_RXFIFO_FULL) \
| (UART_INTR_RXFIFO_TOUT) \ | (UART_INTR_RXFIFO_TOUT) \
| (UART_INTR_RXFIFO_OVF) \ | (UART_INTR_RXFIFO_OVF) \
@@ -1121,7 +1121,7 @@ static void UART_ISR_ATTR uart_rx_intr_handler_default(void *param)
xSemaphoreGiveFromISR(p_uart_obj[uart_num]->tx_done_sem, &HPTaskAwoken); xSemaphoreGiveFromISR(p_uart_obj[uart_num]->tx_done_sem, &HPTaskAwoken);
} }
} }
#if SOC_UART_SUPPORT_WAKEUP #if SOC_UART_SUPPORT_WAKEUP_INT
else if (uart_intr_status & UART_INTR_WAKEUP) { else if (uart_intr_status & UART_INTR_WAKEUP) {
uart_hal_clr_intsts_mask(&(uart_context[uart_num].hal), UART_INTR_WAKEUP); uart_hal_clr_intsts_mask(&(uart_context[uart_num].hal), UART_INTR_WAKEUP);
uart_event.type = UART_WAKEUP; uart_event.type = UART_WAKEUP;

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */

View File

@@ -59,6 +59,7 @@ typedef enum {
UART_INTR_RS485_FRM_ERR = (0x1 << 16), UART_INTR_RS485_FRM_ERR = (0x1 << 16),
UART_INTR_RS485_CLASH = (0x1 << 17), UART_INTR_RS485_CLASH = (0x1 << 17),
UART_INTR_CMD_CHAR_DET = (0x1 << 18), UART_INTR_CMD_CHAR_DET = (0x1 << 18),
UART_INTR_WAKEUP = (0x1 << 19),
} uart_intr_t; } uart_intr_t;
static inline void uart_ll_set_reset_core(uart_dev_t *hw, bool core_rst_en) { static inline void uart_ll_set_reset_core(uart_dev_t *hw, bool core_rst_en) {

View File

@@ -1,16 +1,8 @@
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD /*
// * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
// Licensed under the Apache License, Version 2.0 (the "License"); *
// you may not use this file except in compliance with the License. * SPDX-License-Identifier: Apache-2.0
// You may obtain a copy of the License at */
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// The LL layer for UART register operations. // The LL layer for UART register operations.
// Note that most of the register operations in this layer are non-atomic operations. // Note that most of the register operations in this layer are non-atomic operations.
@@ -57,6 +49,7 @@ typedef enum {
UART_INTR_RS485_FRM_ERR = (0x1<<16), UART_INTR_RS485_FRM_ERR = (0x1<<16),
UART_INTR_RS485_CLASH = (0x1<<17), UART_INTR_RS485_CLASH = (0x1<<17),
UART_INTR_CMD_CHAR_DET = (0x1<<18), UART_INTR_CMD_CHAR_DET = (0x1<<18),
UART_INTR_WAKEUP = (0x1 << 19),
} uart_intr_t; } uart_intr_t;
/** /**

View File

@@ -1,16 +1,8 @@
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD /*
// * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
// Licensed under the Apache License, Version 2.0 (the "License"); *
// you may not use this file except in compliance with the License. * SPDX-License-Identifier: Apache-2.0
// You may obtain a copy of the License at */
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// The LL layer for UART register operations. // The LL layer for UART register operations.
// Note that most of the register operations in this layer are non-atomic operations. // Note that most of the register operations in this layer are non-atomic operations.
@@ -60,6 +52,7 @@ typedef enum {
UART_INTR_RS485_FRM_ERR = (0x1 << 16), UART_INTR_RS485_FRM_ERR = (0x1 << 16),
UART_INTR_RS485_CLASH = (0x1 << 17), UART_INTR_RS485_CLASH = (0x1 << 17),
UART_INTR_CMD_CHAR_DET = (0x1 << 18), UART_INTR_CMD_CHAR_DET = (0x1 << 18),
UART_INTR_WAKEUP = (0x1 << 19),
} uart_intr_t; } uart_intr_t;
/** /**

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -279,7 +279,7 @@
#define SOC_UART_SUPPORT_RTC_CLK (1) #define SOC_UART_SUPPORT_RTC_CLK (1)
#define SOC_UART_SUPPORT_XTAL_CLK (1) #define SOC_UART_SUPPORT_XTAL_CLK (1)
#define SOC_UART_SUPPORT_WAKEUP (1) #define SOC_UART_SUPPORT_WAKEUP_INT (1) /*!< Support UART wakeup interrupt */
#define SOC_UART_REQUIRE_CORE_RESET (1) #define SOC_UART_REQUIRE_CORE_RESET (1)
// UART has an extra TX_WAIT_SEND state when the FIFO is not empty and XOFF is enabled // UART has an extra TX_WAIT_SEND state when the FIFO is not empty and XOFF is enabled

View File

@@ -260,7 +260,7 @@
#define SOC_UART_NUM (2) #define SOC_UART_NUM (2)
#define SOC_UART_FIFO_LEN (128) /*!< The UART hardware FIFO length */ #define SOC_UART_FIFO_LEN (128) /*!< The UART hardware FIFO length */
#define SOC_UART_BITRATE_MAX (5000000) /*!< Max bit rate supported by UART */ #define SOC_UART_BITRATE_MAX (5000000) /*!< Max bit rate supported by UART */
#define SOC_UART_SUPPORT_WAKEUP_INT (1) /*!< Support UART wakeup interrupt */
#define SOC_UART_SUPPORT_RTC_CLK (1) #define SOC_UART_SUPPORT_RTC_CLK (1)
#define SOC_UART_SUPPORT_XTAL_CLK (1) #define SOC_UART_SUPPORT_XTAL_CLK (1)

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -262,6 +262,7 @@
/*-------------------------- UART CAPS ---------------------------------------*/ /*-------------------------- UART CAPS ---------------------------------------*/
// ESP32-S2 has 2 UART. // ESP32-S2 has 2 UART.
#define SOC_UART_NUM (2) #define SOC_UART_NUM (2)
#define SOC_UART_SUPPORT_WAKEUP_INT (1) /*!< Support UART wakeup interrupt */
#define SOC_UART_SUPPORT_REF_TICK (1) /*!< Support REF_TICK as the clock source */ #define SOC_UART_SUPPORT_REF_TICK (1) /*!< Support REF_TICK as the clock source */
#define SOC_UART_FIFO_LEN (128) /*!< The UART hardware FIFO length */ #define SOC_UART_FIFO_LEN (128) /*!< The UART hardware FIFO length */
#define SOC_UART_BITRATE_MAX (5000000) /*!< Max bit rate supported by UART */ #define SOC_UART_BITRATE_MAX (5000000) /*!< Max bit rate supported by UART */

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -260,8 +260,13 @@
#include "twai_caps.h" #include "twai_caps.h"
/*-------------------------- UART CAPS ---------------------------------------*/ /*-------------------------- UART CAPS ---------------------------------------*/
#include "uart_caps.h" // ESP32-S3 has 3 UARTs
#define SOC_UART_NUM (3)
#define SOC_UART_FIFO_LEN (128) /*!< The UART hardware FIFO length */
#define SOC_UART_BITRATE_MAX (5000000) /*!< Max bit rate supported by UART */
// UART has an extra TX_WAIT_SEND state when the FIFO is not empty and XOFF is enabled
#define SOC_UART_SUPPORT_FSM_TX_WAIT_SEND (1)
#define SOC_UART_SUPPORT_WAKEUP_INT (1) /*!< Support UART wakeup interrupt */
#define SOC_UART_SUPPORT_RTC_CLK (1) /*!< Support RTC clock as the clock source */ #define SOC_UART_SUPPORT_RTC_CLK (1) /*!< Support RTC clock as the clock source */
#define SOC_UART_SUPPORT_XTAL_CLK (1) /*!< Support XTAL clock as the clock source */ #define SOC_UART_SUPPORT_XTAL_CLK (1) /*!< Support XTAL clock as the clock source */
#define SOC_UART_REQUIRE_CORE_RESET (1) #define SOC_UART_REQUIRE_CORE_RESET (1)

View File

@@ -1,31 +0,0 @@
// Copyright 2010-2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#define SOC_UART_FIFO_LEN (128) /*!< The UART hardware FIFO length */
#define SOC_UART_BITRATE_MAX (5000000) /*!< Max bit rate supported by UART */
#define SOC_UART_NUM (3)
// UART has an extra TX_WAIT_SEND state when the FIFO is not empty and XOFF is enabled
#define SOC_UART_SUPPORT_FSM_TX_WAIT_SEND (1)
#ifdef __cplusplus
}
#endif

View File

@@ -1,5 +1,3 @@
| Supported Targets | ESP32-C3 |
| ----------------- | -------- |
# Light Sleep Example # Light Sleep Example
(See the README.md file in the upper level 'examples' directory for more information about examples.) (See the README.md file in the upper level 'examples' directory for more information about examples.)

View File

@@ -1,10 +1,11 @@
/* /* Light sleep example
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
/* Light sleep example */ This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@@ -18,130 +19,77 @@
#include "driver/uart.h" #include "driver/uart.h"
#include "driver/gpio.h" #include "driver/gpio.h"
#include "esp_timer.h" #include "esp_timer.h"
#include "soc/uart_struct.h"
#include "soc/rtc.h"
#include "esp_pm.h"
#include "esp32c3/pm.h"
#define TAG "UART" /* Most development boards have "boot" button attached to GPIO0.
#define TEST_UART_NUM 1 * You can also change this to another pin.
#define TEST_BUF_SIZE 1024 */
#if CONFIG_IDF_TARGET_ESP32C3
#define BUTTON_GPIO_NUM_DEFAULT 9
#else
#define BUTTON_GPIO_NUM_DEFAULT 0
#endif
static QueueHandle_t uart0_queue; /* "Boot" button is active low */
#define BUTTON_WAKEUP_LEVEL_DEFAULT 0
void light_sleep_wakeup_config(void)
{
ESP_ERROR_CHECK(gpio_sleep_set_direction(6, GPIO_MODE_INPUT));
ESP_ERROR_CHECK(gpio_sleep_set_pull_mode(6, GPIO_PULLUP_ONLY));
if (uart_set_wakeup_threshold(TEST_UART_NUM, 3) != ESP_OK) {
ESP_LOGE(TAG, "set uart1 wakeup threshold failed");
}
if (esp_sleep_enable_uart_wakeup(TEST_UART_NUM) != ESP_OK) {
ESP_LOGE(TAG, "set uart1 wakeup failed");
}
ESP_LOGI(TAG, "set_light_sleep_wakeup ok");
}
void light_sleep_setup(void)
{
light_sleep_wakeup_config();
esp_pm_config_esp32c3_t pm_config = {
.max_freq_mhz = CONFIG_ESP32C3_DEFAULT_CPU_FREQ_MHZ,
.min_freq_mhz = (int) rtc_clk_xtal_freq_get(),
.light_sleep_enable = true
};
ESP_ERROR_CHECK(esp_pm_configure(&pm_config));
}
#define RD_BUF_SIZE 1024
static void uart_wakeup_task(void *arg)
{
uart_event_t event;
// esp_light_sleep_start();
esp_pm_lock_handle_t lock = ((struct { esp_pm_lock_handle_t lock; } *)arg)->lock;
light_sleep_setup();
uint8_t* dtmp = (uint8_t*) malloc(RD_BUF_SIZE);
for(;;) {
//Waiting for UART event.
if(xQueueReceive(uart0_queue, (void * )&event, (portTickType)portMAX_DELAY)) {
esp_pm_lock_acquire(lock);
ESP_LOGI(TAG, "uar%d recved event:%d (wk:%d)", TEST_UART_NUM, event.type, UART_WAKEUP);
switch(event.type) {
case UART_DATA:
ESP_LOGI(TAG, "[UART DATA]: %d", event.size);
uart_read_bytes(TEST_UART_NUM, dtmp, event.size, portMAX_DELAY);
ESP_LOGI(TAG, "[DATA EVT]:");
uart_write_bytes(TEST_UART_NUM, (const char *)dtmp, event.size);
break;
//Event of HW FIFO overflow detected
case UART_FIFO_OVF:
ESP_LOGI(TAG, "hw fifo overflow");
// If fifo overflow happened, you should consider adding flow control for your application.
// The ISR has already reset the rx FIFO,
// As an example, we directly flush the rx buffer here in order to read more data.
uart_flush_input(TEST_UART_NUM);
xQueueReset(uart0_queue);
break;
//Event of UART ring buffer full
case UART_BUFFER_FULL:
ESP_LOGI(TAG, "ring buffer full");
// If buffer full happened, you should consider encreasing your buffer size
// As an example, we directly flush the rx buffer here in order to read more data.
uart_flush_input(TEST_UART_NUM);
xQueueReset(uart0_queue);
break;
//Event of UART RX break detected
case UART_BREAK:
ESP_LOGI(TAG, "uart rx break");
break;
//Event of UART parity check error
case UART_PARITY_ERR:
ESP_LOGI(TAG, "uart parity error");
break;
//Event of UART frame error
case UART_FRAME_ERR:
ESP_LOGI(TAG, "uart frame error");
break;
case UART_WAKEUP:
ESP_LOGI(TAG, "uart uart wakeup");
break;
default:
ESP_LOGI(TAG, "uart event type: %d", event.type);
break;
}
ESP_LOGI(TAG, "uart[%d] esp_pm_lock_release()", TEST_UART_NUM);
esp_pm_lock_release(lock);
}
}
vTaskDelete(NULL);
}
void app_main(void) void app_main(void)
{ {
uart_config_t uart_config = { /* Configure the button GPIO as input, enable wakeup */
.baud_rate = 115200, const int button_gpio_num = BUTTON_GPIO_NUM_DEFAULT;
.data_bits = UART_DATA_8_BITS, const int wakeup_level = BUTTON_WAKEUP_LEVEL_DEFAULT;
.parity = UART_PARITY_DISABLE, gpio_config_t config = {
.stop_bits = UART_STOP_BITS_1, .pin_bit_mask = BIT64(button_gpio_num),
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE, .mode = GPIO_MODE_INPUT
.source_clk = UART_SCLK_XTAL,
}; };
//Install UART driver, and get the queue. ESP_ERROR_CHECK(gpio_config(&config));
uart_driver_install(TEST_UART_NUM, TEST_BUF_SIZE * 2, TEST_BUF_SIZE * 2, 20, &uart0_queue, 0); gpio_wakeup_enable(button_gpio_num,
uart_param_config(TEST_UART_NUM, &uart_config); wakeup_level == 0 ? GPIO_INTR_LOW_LEVEL : GPIO_INTR_HIGH_LEVEL);
uart_set_pin(TEST_UART_NUM, 7, 6, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
light_sleep_wakeup_config(); while (true) {
/* Wake up in 2 seconds, or when button is pressed */
esp_sleep_enable_timer_wakeup(2000000);
esp_sleep_enable_gpio_wakeup();
/* Wait until GPIO goes high */
if (gpio_get_level(button_gpio_num) == wakeup_level) {
printf("Waiting for GPIO%d to go high...\n", button_gpio_num);
do {
vTaskDelay(pdMS_TO_TICKS(10));
} while (gpio_get_level(button_gpio_num) == wakeup_level);
}
printf("Entering light sleep\n");
/* To make sure the complete line is printed before entering sleep mode,
* need to wait until UART TX FIFO is empty:
*/
uart_wait_tx_idle_polling(CONFIG_ESP_CONSOLE_UART_NUM);
/* Get timestamp before entering sleep */
int64_t t_before_us = esp_timer_get_time();
/* Enter sleep mode */
esp_light_sleep_start();
/* Execution continues here after wakeup */
/* Get timestamp after waking up from sleep */
int64_t t_after_us = esp_timer_get_time();
/* Determine wake up reason */
const char* wakeup_reason;
switch (esp_sleep_get_wakeup_cause()) {
case ESP_SLEEP_WAKEUP_TIMER:
wakeup_reason = "timer";
break;
case ESP_SLEEP_WAKEUP_GPIO:
wakeup_reason = "pin";
break;
default:
wakeup_reason = "other";
break;
}
printf("Returned from light sleep, reason: %s, t=%lld ms, slept for %lld ms\n",
wakeup_reason, t_after_us / 1000, (t_after_us - t_before_us) / 1000);
}
static esp_pm_lock_handle_t uart_event_lock;
ESP_ERROR_CHECK(esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "uart_evt", &uart_event_lock));
struct { esp_pm_lock_handle_t lock; } args = { .lock = uart_event_lock };
xTaskCreate(uart_wakeup_task, "uart_wakeup_task", 2048, &args, 12, NULL);
} }

View File

@@ -1,2 +1 @@
CONFIG_PM_ENABLE=y CONFIG_ESP32_DEFAULT_CPU_FREQ_80=y
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y