forked from espressif/esp-idf
uart: support light sleep on esp32s3
This commit is contained in:
@@ -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
|
||||
*/
|
||||
@@ -58,7 +58,7 @@ typedef enum {
|
||||
UART_PARITY_ERR, /*!< UART RX parity event*/
|
||||
UART_DATA_BREAK, /*!< UART TX data and break event*/
|
||||
UART_PATTERN_DET, /*!< UART pattern detected */
|
||||
#if SOC_UART_SUPPORT_WAKEUP
|
||||
#if SOC_UART_SUPPORT_WAKEUP_INT
|
||||
UART_WAKEUP, /*!< UART wakeup event */
|
||||
#endif
|
||||
UART_EVENT_MAX, /*!< UART event max index*/
|
||||
|
@@ -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
|
||||
*/
|
||||
@@ -59,7 +59,7 @@ static const char *UART_TAG = "uart";
|
||||
#define UART_PATTERN_DET_QLEN_DEFAULT (10)
|
||||
#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) \
|
||||
| (UART_INTR_RXFIFO_TOUT) \
|
||||
| (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);
|
||||
}
|
||||
}
|
||||
#if SOC_UART_SUPPORT_WAKEUP
|
||||
#if SOC_UART_SUPPORT_WAKEUP_INT
|
||||
else if (uart_intr_status & UART_INTR_WAKEUP) {
|
||||
uart_hal_clr_intsts_mask(&(uart_context[uart_num].hal), UART_INTR_WAKEUP);
|
||||
uart_event.type = UART_WAKEUP;
|
||||
|
@@ -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
|
||||
*/
|
||||
|
@@ -59,6 +59,7 @@ typedef enum {
|
||||
UART_INTR_RS485_FRM_ERR = (0x1 << 16),
|
||||
UART_INTR_RS485_CLASH = (0x1 << 17),
|
||||
UART_INTR_CMD_CHAR_DET = (0x1 << 18),
|
||||
UART_INTR_WAKEUP = (0x1 << 19),
|
||||
} uart_intr_t;
|
||||
|
||||
static inline void uart_ll_set_reset_core(uart_dev_t *hw, bool core_rst_en) {
|
||||
|
@@ -1,16 +1,8 @@
|
||||
// Copyright 2015-2019 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.
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
// The LL layer for UART register 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_CLASH = (0x1<<17),
|
||||
UART_INTR_CMD_CHAR_DET = (0x1<<18),
|
||||
UART_INTR_WAKEUP = (0x1 << 19),
|
||||
} uart_intr_t;
|
||||
|
||||
/**
|
||||
|
@@ -1,16 +1,8 @@
|
||||
// Copyright 2015-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.
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
// The LL layer for UART register 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_CLASH = (0x1 << 17),
|
||||
UART_INTR_CMD_CHAR_DET = (0x1 << 18),
|
||||
UART_INTR_WAKEUP = (0x1 << 19),
|
||||
} uart_intr_t;
|
||||
|
||||
/**
|
||||
|
@@ -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
|
||||
*/
|
||||
@@ -279,7 +279,7 @@
|
||||
|
||||
#define SOC_UART_SUPPORT_RTC_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)
|
||||
|
||||
// UART has an extra TX_WAIT_SEND state when the FIFO is not empty and XOFF is enabled
|
||||
|
@@ -260,7 +260,7 @@
|
||||
#define SOC_UART_NUM (2)
|
||||
#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_SUPPORT_WAKEUP_INT (1) /*!< Support UART wakeup interrupt */
|
||||
#define SOC_UART_SUPPORT_RTC_CLK (1)
|
||||
#define SOC_UART_SUPPORT_XTAL_CLK (1)
|
||||
|
||||
|
@@ -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
|
||||
*/
|
||||
@@ -262,6 +262,7 @@
|
||||
/*-------------------------- UART CAPS ---------------------------------------*/
|
||||
// ESP32-S2 has 2 UART.
|
||||
#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_FIFO_LEN (128) /*!< The UART hardware FIFO length */
|
||||
#define SOC_UART_BITRATE_MAX (5000000) /*!< Max bit rate supported by UART */
|
||||
|
@@ -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
|
||||
*/
|
||||
@@ -260,8 +260,13 @@
|
||||
#include "twai_caps.h"
|
||||
|
||||
/*-------------------------- 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_XTAL_CLK (1) /*!< Support XTAL clock as the clock source */
|
||||
#define SOC_UART_REQUIRE_CORE_RESET (1)
|
||||
|
@@ -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
|
@@ -1,5 +1,3 @@
|
||||
| Supported Targets | ESP32-C3 |
|
||||
| ----------------- | -------- |
|
||||
# Light Sleep Example
|
||||
|
||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||
|
@@ -1,10 +1,11 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
/* Light sleep example
|
||||
|
||||
/* 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 <string.h>
|
||||
@@ -18,130 +19,77 @@
|
||||
#include "driver/uart.h"
|
||||
#include "driver/gpio.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"
|
||||
#define TEST_UART_NUM 1
|
||||
#define TEST_BUF_SIZE 1024
|
||||
/* Most development boards have "boot" button attached to GPIO0.
|
||||
* You can also change this to another pin.
|
||||
*/
|
||||
#if CONFIG_IDF_TARGET_ESP32C3
|
||||
#define BUTTON_GPIO_NUM_DEFAULT 9
|
||||
#else
|
||||
#define BUTTON_GPIO_NUM_DEFAULT 0
|
||||
#endif
|
||||
|
||||
static QueueHandle_t uart0_queue;
|
||||
|
||||
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);
|
||||
}
|
||||
/* "Boot" button is active low */
|
||||
#define BUTTON_WAKEUP_LEVEL_DEFAULT 0
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
uart_config_t uart_config = {
|
||||
.baud_rate = 115200,
|
||||
.data_bits = UART_DATA_8_BITS,
|
||||
.parity = UART_PARITY_DISABLE,
|
||||
.stop_bits = UART_STOP_BITS_1,
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||
.source_clk = UART_SCLK_XTAL,
|
||||
/* Configure the button GPIO as input, enable wakeup */
|
||||
const int button_gpio_num = BUTTON_GPIO_NUM_DEFAULT;
|
||||
const int wakeup_level = BUTTON_WAKEUP_LEVEL_DEFAULT;
|
||||
gpio_config_t config = {
|
||||
.pin_bit_mask = BIT64(button_gpio_num),
|
||||
.mode = GPIO_MODE_INPUT
|
||||
};
|
||||
//Install UART driver, and get the queue.
|
||||
uart_driver_install(TEST_UART_NUM, TEST_BUF_SIZE * 2, TEST_BUF_SIZE * 2, 20, &uart0_queue, 0);
|
||||
uart_param_config(TEST_UART_NUM, &uart_config);
|
||||
uart_set_pin(TEST_UART_NUM, 7, 6, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
|
||||
light_sleep_wakeup_config();
|
||||
ESP_ERROR_CHECK(gpio_config(&config));
|
||||
gpio_wakeup_enable(button_gpio_num,
|
||||
wakeup_level == 0 ? GPIO_INTR_LOW_LEVEL : GPIO_INTR_HIGH_LEVEL);
|
||||
|
||||
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);
|
||||
}
|
||||
|
@@ -1,2 +1 @@
|
||||
CONFIG_PM_ENABLE=y
|
||||
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
|
||||
CONFIG_ESP32_DEFAULT_CPU_FREQ_80=y
|
||||
|
Reference in New Issue
Block a user