Merge branch 'feat/twai_sleep_retention' into 'master'

twai: sleep retention support

Closes IDF-8471, IDF-9772, and IDF-9743

See merge request espressif/esp-idf!34107
This commit is contained in:
Armando (Dou Yiwen)
2024-10-21 19:14:48 +08:00
23 changed files with 388 additions and 23 deletions

View File

@@ -12,6 +12,9 @@
#include "driver/twai.h"
#include "soc/soc_caps.h"
#include "esp_attr.h"
#include "esp_private/sleep_cpu.h"
#include "esp_private/esp_sleep_internal.h"
#include "esp_private/esp_pmu.h"
TEST_CASE("driver_life_cycle", "[twai-loop-back]")
{
@@ -130,3 +133,90 @@ TEST_CASE("twai_mode_ext_no_ack_250kbps", "[twai-loop-back]")
TEST_ESP_OK(twai_driver_uninstall_v2(twai_buses[i]));
}
}
static void s_test_sleep_retention(bool allow_pd)
{
// Prepare a TOP PD sleep
TEST_ESP_OK(esp_sleep_enable_timer_wakeup(1 * 1000 * 1000));
#if ESP_SLEEP_POWER_DOWN_CPU
TEST_ESP_OK(sleep_cpu_configure(true));
#endif
esp_sleep_context_t sleep_ctx;
esp_sleep_set_sleep_context(&sleep_ctx);
twai_handle_t twai_buses[SOC_TWAI_CONTROLLER_NUM] = {0};
twai_timing_config_t t_config = TWAI_TIMING_CONFIG_250KBITS();
twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL();
// bind the TX and RX to the same GPIO to act like a loopback
twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT(0, 0, TWAI_MODE_NO_ACK);
g_config.general_flags.sleep_allow_pd = allow_pd;
twai_message_t tx_msg = {
.identifier = 0x12345,
.data_length_code = 6,
.data = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66},
.self = true, // Transmitted message will also received by the same node
.extd = true, // Extended Frame Format (29bit ID)
};
for (int i = 0; i < SOC_TWAI_CONTROLLER_NUM; i++) {
g_config.controller_id = i;
g_config.tx_io = i;
g_config.rx_io = i;
printf("install twai driver %d\r\n", g_config.controller_id);
TEST_ESP_OK(twai_driver_install_v2(&g_config, &t_config, &f_config, &twai_buses[i]));
}
printf("Going into sleep...\n");
TEST_ESP_OK(esp_light_sleep_start());
printf("Waked up!\n");
// check if the sleep happened as expected
TEST_ASSERT_EQUAL(0, sleep_ctx.sleep_request_result);
#if SOC_TWAI_SUPPORT_SLEEP_RETENTION
// check if the power domain also is powered down
TEST_ASSERT_EQUAL(allow_pd ? PMU_SLEEP_PD_TOP : 0, (sleep_ctx.sleep_flags) & PMU_SLEEP_PD_TOP);
#endif
for (int i = 0; i < SOC_TWAI_CONTROLLER_NUM; i++) {
TEST_ESP_OK(twai_start_v2(twai_buses[i]));
}
for (int i = 0; i < SOC_TWAI_CONTROLLER_NUM; i++) {
printf("transmit message from %d\r\n", i);
tx_msg.data[5] = SOC_TWAI_CONTROLLER_NUM - i;
TEST_ESP_OK(twai_transmit_v2(twai_buses[i], &tx_msg, pdMS_TO_TICKS(1000)));
}
twai_message_t rx_msg;
for (int i = 0; i < SOC_TWAI_CONTROLLER_NUM; i++) {
printf("receive message from %d\r\n", i);
TEST_ESP_OK(twai_receive_v2(twai_buses[i], &rx_msg, pdMS_TO_TICKS(1000)));
TEST_ASSERT_TRUE(rx_msg.data_length_code == 6);
tx_msg.data[5] = SOC_TWAI_CONTROLLER_NUM - i;
for (int i = 0; i < 6; i++) {
TEST_ASSERT_EQUAL(tx_msg.data[i], rx_msg.data[i]);
}
}
for (int i = 0; i < SOC_TWAI_CONTROLLER_NUM; i++) {
TEST_ESP_OK(twai_stop_v2(twai_buses[i]));
TEST_ESP_OK(twai_driver_uninstall_v2(twai_buses[i]));
}
esp_sleep_set_sleep_context(NULL);
#if ESP_SLEEP_POWER_DOWN_CPU
TEST_ESP_OK(sleep_cpu_configure(false));
#endif
}
#if SOC_TWAI_SUPPORT_SLEEP_RETENTION
TEST_CASE("twai_mode_ext_no_ack_250kbps with sleep retention (allow pd)", "[twai-loop-back]")
{
s_test_sleep_retention(true);
}
#endif
TEST_CASE("twai_mode_ext_no_ack_250kbps with sleep retention (no pd)", "[twai-loop-back]")
{
s_test_sleep_retention(false);
}

View File

@@ -3,3 +3,5 @@ CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y
CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y

View File

@@ -1,2 +1,4 @@
CONFIG_FREERTOS_HZ=1000
CONFIG_ESP_TASK_WDT=n
# primitives for checking sleep internal state
CONFIG_ESP_SLEEP_DEBUG=y

View File

@@ -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
*/
@@ -114,6 +114,11 @@ typedef struct {
uint32_t alerts_enabled; /**< Bit field of alerts to enable (see documentation) */
uint32_t clkout_divider; /**< CLKOUT divider. Can be 1 or any even number from 2 to 14 (optional, set to 0 if unused) */
int intr_flags; /**< Interrupt flags to set the priority of the driver's ISR. Note that to use the ESP_INTR_FLAG_IRAM, the CONFIG_TWAI_ISR_IN_IRAM option should be enabled first. */
struct {
uint32_t sleep_allow_pd; /**< Set to allow power down. When this flag set, the driver will backup/restore the TWAI registers before/after entering/exist sleep mode.
By this approach, the system can power off TWAI's power domain.
This can save power, but at the expense of more RAM being consumed. */
} general_flags; /**< General flags */
} twai_general_config_t;
/**

View File

@@ -28,6 +28,9 @@
#include "soc/gpio_sig_map.h"
#include "hal/twai_hal.h"
#include "esp_rom_gpio.h"
#if SOC_TWAI_SUPPORT_SLEEP_RETENTION
#include "esp_private/sleep_retention.h"
#endif
/* ---------------------------- Definitions --------------------------------- */
//Internal Macros
@@ -64,6 +67,8 @@
#define TWAI_PERI_ATOMIC()
#endif
#define TWAI_USE_RETENTION_LINK (SOC_TWAI_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP)
/* ------------------ Typedefs, structures, and variables ------------------- */
//Control structure for TWAI driver
@@ -96,6 +101,11 @@ typedef struct twai_obj_t {
static twai_handle_t g_twai_objs[SOC_TWAI_CONTROLLER_NUM];
static portMUX_TYPE g_spinlock = portMUX_INITIALIZER_UNLOCKED;
/* -------------------- Sleep Retention ------------------------ */
#if TWAI_USE_RETENTION_LINK
static esp_err_t s_twai_create_sleep_retention_link_cb(void *obj);
#endif
/* -------------------- Interrupt and Alert Handlers ------------------------ */
static void twai_alert_handler(twai_obj_t *p_twai_obj, uint32_t alert_code, int *alert_req)
@@ -334,6 +344,19 @@ static void twai_free_driver_obj(twai_obj_t *p_obj)
if (p_obj->alert_semphr != NULL) {
vSemaphoreDeleteWithCaps(p_obj->alert_semphr);
}
#if TWAI_USE_RETENTION_LINK
const periph_retention_module_t retention_id = twai_reg_retention_info[p_obj->controller_id].module_id;
if (sleep_retention_get_created_modules() & BIT(retention_id)) {
assert(sleep_retention_get_inited_modules() & BIT(retention_id));
sleep_retention_module_free(retention_id);
}
if (sleep_retention_get_inited_modules() & BIT(retention_id)) {
sleep_retention_module_deinit(retention_id);
}
#endif
heap_caps_free(p_obj);
}
@@ -365,6 +388,9 @@ static esp_err_t twai_alloc_driver_obj(const twai_general_config_t *g_config, tw
if (ret != ESP_OK) {
goto err;
}
p_obj->controller_id = controller_id;
#if CONFIG_PM_ENABLE
#if SOC_TWAI_CLK_SUPPORT_APB
// DFS can change APB frequency. So add lock to prevent sleep and APB freq from changing
@@ -384,6 +410,28 @@ static esp_err_t twai_alloc_driver_obj(const twai_general_config_t *g_config, tw
#endif //SOC_TWAI_CLK_SUPPORT_APB
#endif //CONFIG_PM_ENABLE
#if TWAI_USE_RETENTION_LINK
sleep_retention_module_t module = twai_reg_retention_info[controller_id].module_id;
sleep_retention_module_init_param_t init_param = {
.cbs = {
.create = {
.handle = s_twai_create_sleep_retention_link_cb,
.arg = p_obj,
},
},
.depends = BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM)
};
if (sleep_retention_module_init(module, &init_param) != ESP_OK) {
ESP_LOGW(TWAI_TAG, "init sleep retention failed for TWAI%d, power domain may be turned off during sleep", controller_id);
}
if (g_config->general_flags.sleep_allow_pd) {
if (sleep_retention_module_allocate(module) != ESP_OK) {
ESP_LOGW(TWAI_TAG, "create retention module failed, power domain can't turn off");
}
}
#endif
*p_twai_obj_ret = p_obj;
return ESP_OK;
@@ -408,6 +456,9 @@ esp_err_t twai_driver_install_v2(const twai_general_config_t *g_config, const tw
#endif
int controller_id = g_config->controller_id;
TWAI_CHECK(g_twai_objs[controller_id] == NULL, ESP_ERR_INVALID_STATE);
#if !SOC_TWAI_SUPPORT_SLEEP_RETENTION
TWAI_CHECK(!g_config->general_flags.sleep_allow_pd, ESP_ERR_INVALID_ARG);
#endif
//Get clock source resolution
uint32_t clock_source_hz = 0;
@@ -437,7 +488,6 @@ esp_err_t twai_driver_install_v2(const twai_general_config_t *g_config, const tw
//Initialize flags and variables. All other members are already set to zero by twai_alloc_driver_obj()
portMUX_INITIALIZE(&p_twai_obj->spinlock);
p_twai_obj->controller_id = controller_id;
p_twai_obj->state = TWAI_STATE_STOPPED;
p_twai_obj->mode = g_config->mode;
p_twai_obj->alerts_enabled = g_config->alerts_enabled;
@@ -874,3 +924,14 @@ esp_err_t twai_clear_receive_queue(void)
// the handle-less driver API only support one TWAI controller, i.e. the g_twai_objs[0]
return twai_clear_receive_queue_v2(g_twai_objs[0]);
}
#if TWAI_USE_RETENTION_LINK
static esp_err_t s_twai_create_sleep_retention_link_cb(void *obj)
{
twai_obj_t *host = (twai_obj_t *)obj;
return sleep_retention_entries_create(twai_reg_retention_info[host->controller_id].entry_array,
twai_reg_retention_info[host->controller_id].array_size,
REGDMA_LINK_PRI_TWAI,
twai_reg_retention_info[host->controller_id].module_id);
}
#endif

View File

@@ -1175,6 +1175,10 @@ config SOC_TWAI_SUPPORTS_RX_STATUS
bool
default y
config SOC_TWAI_SUPPORT_SLEEP_RETENTION
bool
default y
config SOC_EFUSE_DIS_DOWNLOAD_ICACHE
bool
default y

View File

@@ -39,6 +39,8 @@ typedef enum periph_retention_module {
SLEEP_RETENTION_MODULE_I2S0 = 16,
SLEEP_RETENTION_MODULE_ETM0 = 17,
SLEEP_RETENTION_MODULE_TEMP_SENSOR = 18,
SLEEP_RETENTION_MODULE_TWAI0 = 19,
SLEEP_RETENTION_MODULE_TWAI1 = 20,
/* Modem module, which includes WiFi, BLE and 802.15.4 */
SLEEP_RETENTION_MODULE_WIFI_MAC = 26,
@@ -74,6 +76,8 @@ typedef enum periph_retention_module_bitmap {
SLEEP_RETENTION_MODULE_BM_I2S0 = BIT(SLEEP_RETENTION_MODULE_I2S0),
SLEEP_RETENTION_MODULE_BM_ETM0 = BIT(SLEEP_RETENTION_MODULE_ETM0),
SLEEP_RETENTION_MODULE_BM_TEMP_SENSOR = BIT(SLEEP_RETENTION_MODULE_TEMP_SENSOR),
SLEEP_RETENTION_MODULE_BM_TWAI0 = BIT(SLEEP_RETENTION_MODULE_TWAI0),
SLEEP_RETENTION_MODULE_BM_TWAI1 = BIT(SLEEP_RETENTION_MODULE_TWAI1),
/* modem module, which includes WiFi, BLE and 802.15.4 */
SLEEP_RETENTION_MODULE_BM_WIFI_MAC = BIT(SLEEP_RETENTION_MODULE_WIFI_MAC),
SLEEP_RETENTION_MODULE_BM_WIFI_BB = BIT(SLEEP_RETENTION_MODULE_WIFI_BB),
@@ -99,6 +103,8 @@ typedef enum periph_retention_module_bitmap {
| SLEEP_RETENTION_MODULE_BM_I2S0 \
| SLEEP_RETENTION_MODULE_BM_ETM0 \
| SLEEP_RETENTION_MODULE_BM_TEMP_SENSOR \
| SLEEP_RETENTION_MODULE_BM_TWAI0 \
| SLEEP_RETENTION_MODULE_BM_TWAI1 \
)
#ifdef __cplusplus

View File

@@ -456,11 +456,12 @@
#define SOC_MWDT_SUPPORT_SLEEP_RETENTION (1)
/*-------------------------- TWAI CAPS ---------------------------------------*/
#define SOC_TWAI_CONTROLLER_NUM 2
#define SOC_TWAI_CLK_SUPPORT_XTAL 1
#define SOC_TWAI_BRP_MIN 2
#define SOC_TWAI_BRP_MAX 32768
#define SOC_TWAI_SUPPORTS_RX_STATUS 1
#define SOC_TWAI_CONTROLLER_NUM 2
#define SOC_TWAI_CLK_SUPPORT_XTAL 1
#define SOC_TWAI_BRP_MIN 2
#define SOC_TWAI_BRP_MAX 32768
#define SOC_TWAI_SUPPORTS_RX_STATUS 1
#define SOC_TWAI_SUPPORT_SLEEP_RETENTION 1
/*-------------------------- eFuse CAPS----------------------------*/
#define SOC_EFUSE_DIS_DOWNLOAD_ICACHE 1

View File

@@ -1,10 +1,11 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/twai_periph.h"
#include "soc/twai_reg.h"
#include "soc/gpio_sig_map.h"
const twai_controller_signal_conn_t twai_controller_periph_signals = {
@@ -29,3 +30,49 @@ const twai_controller_signal_conn_t twai_controller_periph_signals = {
}
}
};
/**
* TWAI Registers to be saved during sleep retention
* - TWAI_MODE_REG
* - TWAI_INTERRUPT_ENABLE_REG
* - TWAI_BUS_TIMING_0_REG / TWAI_BUS_TIMING_1_REG
* - TWAI_ERR_WARNING_LIMIT_REG
* - TWAI_RX_ERR_CNT_REG
* - TWAI_TX_ERR_CNT_REG
* - TWAI_DATA_x_REG
* - TWAI_CLOCK_DIVIDER_REG
* - TWAI_SW_STANDBY_CFG_REG
* - TWAI_HW_CFG_REG
* - TWAI_HW_STANDBY_CNT_REG
* - TWAI_IDLE_INTR_CNT_REG
* - TWAI_ECO_CFG_REG
* - TWAI_TIMESTAMP_PRESCALER_REG
* - TWAI_TIMESTAMP_CFG_REG
*/
#define TWAI_RETENTION_REGS_CNT 28
#define TWAI_RETENTION_REGS_BASE(i) REG_TWAI_BASE(i)
static const uint32_t twai_regs_map[4] = {0x9fffe0d1, 0xdf, 0x0, 0x0};
#define TWAI_SLEEP_RETENTION_ENTRIES(id) { \
[0] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TWAI_LINK(0x00), \
TWAI_RETENTION_REGS_BASE(id), TWAI_RETENTION_REGS_BASE(id), \
TWAI_RETENTION_REGS_CNT, 0, 0, \
twai_regs_map[0], twai_regs_map[1], \
twai_regs_map[2], twai_regs_map[3]), \
.owner = ENTRY(0) | ENTRY(2) }, \
}
static const regdma_entries_config_t twai0_regs_retention[] = TWAI_SLEEP_RETENTION_ENTRIES(0);
static const regdma_entries_config_t twai1_regs_retention[] = TWAI_SLEEP_RETENTION_ENTRIES(1);
const twai_reg_retention_info_t twai_reg_retention_info[SOC_TWAI_CONTROLLER_NUM] = {
[0] = {
.module_id = SLEEP_RETENTION_MODULE_TWAI0,
.entry_array = twai0_regs_retention,
.array_size = ARRAY_SIZE(twai0_regs_retention)
},
[1] = {
.module_id = SLEEP_RETENTION_MODULE_TWAI1,
.entry_array = twai1_regs_retention,
.array_size = ARRAY_SIZE(twai1_regs_retention)
},
};

View File

@@ -1175,6 +1175,10 @@ config SOC_TWAI_SUPPORTS_RX_STATUS
bool
default y
config SOC_TWAI_SUPPORT_SLEEP_RETENTION
bool
default y
config SOC_EFUSE_DIS_PAD_JTAG
bool
default y

View File

@@ -40,6 +40,7 @@ typedef enum periph_retention_module {
SLEEP_RETENTION_MODULE_I2S0 = 17,
SLEEP_RETENTION_MODULE_ETM0 = 18,
SLEEP_RETENTION_MODULE_TEMP_SENSOR = 19,
SLEEP_RETENTION_MODULE_TWAI0 = 20,
/* Modem module, which includes BLE and 802.15.4 */
SLEEP_RETENTION_MODULE_BLE_MAC = 28,
@@ -74,6 +75,7 @@ typedef enum periph_retention_module_bitmap {
SLEEP_RETENTION_MODULE_BM_I2S0 = BIT(SLEEP_RETENTION_MODULE_I2S0),
SLEEP_RETENTION_MODULE_BM_ETM0 = BIT(SLEEP_RETENTION_MODULE_ETM0),
SLEEP_RETENTION_MODULE_BM_TEMP_SENSOR = BIT(SLEEP_RETENTION_MODULE_TEMP_SENSOR),
SLEEP_RETENTION_MODULE_BM_TWAI0 = BIT(SLEEP_RETENTION_MODULE_TWAI0),
/* modem module, which includes BLE and 802.15.4 */
SLEEP_RETENTION_MODULE_BM_BLE_MAC = BIT(SLEEP_RETENTION_MODULE_BLE_MAC),
SLEEP_RETENTION_MODULE_BM_BT_BB = BIT(SLEEP_RETENTION_MODULE_BT_BB),
@@ -98,6 +100,7 @@ typedef enum periph_retention_module_bitmap {
| SLEEP_RETENTION_MODULE_BM_I2S0 \
| SLEEP_RETENTION_MODULE_BM_ETM0 \
| SLEEP_RETENTION_MODULE_BM_TEMP_SENSOR \
| SLEEP_RETENTION_MODULE_BM_TWAI0 \
)
#ifdef __cplusplus

View File

@@ -453,11 +453,12 @@
#define SOC_MWDT_SUPPORT_SLEEP_RETENTION (1)
/*-------------------------- TWAI CAPS ---------------------------------------*/
#define SOC_TWAI_CONTROLLER_NUM 1UL
#define SOC_TWAI_CLK_SUPPORT_XTAL 1
#define SOC_TWAI_BRP_MIN 2
#define SOC_TWAI_BRP_MAX 32768
#define SOC_TWAI_SUPPORTS_RX_STATUS 1
#define SOC_TWAI_CONTROLLER_NUM 1UL
#define SOC_TWAI_CLK_SUPPORT_XTAL 1
#define SOC_TWAI_BRP_MIN 2
#define SOC_TWAI_BRP_MAX 32768
#define SOC_TWAI_SUPPORTS_RX_STATUS 1
#define SOC_TWAI_SUPPORT_SLEEP_RETENTION 1
/*-------------------------- eFuse CAPS----------------------------*/
#define SOC_EFUSE_DIS_PAD_JTAG 1

View File

@@ -1,10 +1,11 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/twai_periph.h"
#include "soc/twai_reg.h"
#include "soc/gpio_sig_map.h"
const twai_controller_signal_conn_t twai_controller_periph_signals = {
@@ -20,3 +21,42 @@ const twai_controller_signal_conn_t twai_controller_periph_signals = {
}
}
};
/**
* TWAI Registers to be saved during sleep retention
* - TWAI_MODE_REG
* - TWAI_INTERRUPT_ENABLE_REG
* - TWAI_BUS_TIMING_0_REG / TWAI_BUS_TIMING_1_REG
* - TWAI_ERR_WARNING_LIMIT_REG
* - TWAI_RX_ERR_CNT_REG
* - TWAI_TX_ERR_CNT_REG
* - TWAI_DATA_x_REG
* - TWAI_CLOCK_DIVIDER_REG
* - TWAI_SW_STANDBY_CFG_REG
* - TWAI_HW_CFG_REG
* - TWAI_HW_STANDBY_CNT_REG
* - TWAI_IDLE_INTR_CNT_REG
* - TWAI_ECO_CFG_REG
* - TWAI_TIMESTAMP_PRESCALER_REG
* - TWAI_TIMESTAMP_CFG_REG
*/
#define TWAI_RETENTION_REGS_CNT 28
#define TWAI_RETENTION_REGS_BASE(i) DR_REG_TWAI_BASE
static const uint32_t twai_regs_map[4] = {0x9fffe0d1, 0xdf, 0x0, 0x0};
#define TWAI_SLEEP_RETENTION_ENTRIES(id) { \
[0] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TWAI_LINK(0x00), \
TWAI_RETENTION_REGS_BASE(id), TWAI_RETENTION_REGS_BASE(id), \
TWAI_RETENTION_REGS_CNT, 0, 0, \
twai_regs_map[0], twai_regs_map[1], \
twai_regs_map[2], twai_regs_map[3]), \
.owner = ENTRY(0) | ENTRY(2) }, \
}
static const regdma_entries_config_t twai0_regs_retention[] = TWAI_SLEEP_RETENTION_ENTRIES(0);
const twai_reg_retention_info_t twai_reg_retention_info[SOC_TWAI_CONTROLLER_NUM] = {
[0] = {
.module_id = SLEEP_RETENTION_MODULE_TWAI0,
.entry_array = twai0_regs_retention,
.array_size = ARRAY_SIZE(twai0_regs_retention)
},
};

View File

@@ -1659,6 +1659,10 @@ config SOC_TWAI_SUPPORTS_RX_STATUS
bool
default y
config SOC_TWAI_SUPPORT_SLEEP_RETENTION
bool
default y
config SOC_EFUSE_DIS_PAD_JTAG
bool
default y

View File

@@ -47,6 +47,9 @@ typedef enum periph_retention_module {
SLEEP_RETENTION_MODULE_I2C0 = 22,
SLEEP_RETENTION_MODULE_I2C1 = 23,
SLEEP_RETENTION_MODULE_ETM0 = 24,
SLEEP_RETENTION_MODULE_TWAI0 = 25,
SLEEP_RETENTION_MODULE_TWAI1 = 26,
SLEEP_RETENTION_MODULE_TWAI2 = 27,
SLEEP_RETENTION_MODULE_MAX = 31
} periph_retention_module_t;
@@ -83,6 +86,9 @@ typedef enum periph_retention_module_bitmap {
SLEEP_RETENTION_MODULE_BM_ETM0 = BIT(SLEEP_RETENTION_MODULE_ETM0),
SLEEP_RETENTION_MODULE_BM_I2C0 = BIT(SLEEP_RETENTION_MODULE_I2C0),
SLEEP_RETENTION_MODULE_BM_I2C1 = BIT(SLEEP_RETENTION_MODULE_I2C1),
SLEEP_RETENTION_MODULE_BM_TWAI0 = BIT(SLEEP_RETENTION_MODULE_TWAI0),
SLEEP_RETENTION_MODULE_BM_TWAI1 = BIT(SLEEP_RETENTION_MODULE_TWAI1),
SLEEP_RETENTION_MODULE_BM_TWAI2 = BIT(SLEEP_RETENTION_MODULE_TWAI2),
SLEEP_RETENTION_MODULE_BM_ALL = (uint32_t)-1
} periph_retention_module_bitmap_t;
@@ -110,6 +116,9 @@ typedef enum periph_retention_module_bitmap {
| SLEEP_RETENTION_MODULE_BM_ETM0 \
| SLEEP_RETENTION_MODULE_BM_I2C0 \
| SLEEP_RETENTION_MODULE_BM_I2C1 \
| SLEEP_RETENTION_MODULE_BM_TWAI0 \
| SLEEP_RETENTION_MODULE_BM_TWAI1 \
| SLEEP_RETENTION_MODULE_BM_TWAI2 \
)
#ifdef __cplusplus

View File

@@ -616,11 +616,12 @@
#define SOC_TOUCH_SAMPLE_CFG_NUM (3) /*!< The sample configurations number in total, each sampler can be used to sample on one frequency */
/*-------------------------- TWAI CAPS ---------------------------------------*/
#define SOC_TWAI_CONTROLLER_NUM 3
#define SOC_TWAI_CLK_SUPPORT_XTAL 1
#define SOC_TWAI_BRP_MIN 2
#define SOC_TWAI_BRP_MAX 32768
#define SOC_TWAI_SUPPORTS_RX_STATUS 1
#define SOC_TWAI_CONTROLLER_NUM 3
#define SOC_TWAI_CLK_SUPPORT_XTAL 1
#define SOC_TWAI_BRP_MIN 2
#define SOC_TWAI_BRP_MAX 32768
#define SOC_TWAI_SUPPORTS_RX_STATUS 1
#define SOC_TWAI_SUPPORT_SLEEP_RETENTION 1
/*-------------------------- eFuse CAPS----------------------------*/
#define SOC_EFUSE_DIS_PAD_JTAG 1

View File

@@ -1,10 +1,11 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/twai_periph.h"
#include "soc/twai_reg.h"
#include "soc/gpio_sig_map.h"
const twai_controller_signal_conn_t twai_controller_periph_signals = {
@@ -38,3 +39,55 @@ const twai_controller_signal_conn_t twai_controller_periph_signals = {
}
}
};
/**
* TWAI Registers to be saved during sleep retention
* - TWAI_MODE_REG
* - TWAI_INTERRUPT_ENABLE_REG
* - TWAI_BUS_TIMING_0_REG / TWAI_BUS_TIMING_1_REG
* - TWAI_ERR_WARNING_LIMIT_REG
* - TWAI_RX_ERR_CNT_REG
* - TWAI_TX_ERR_CNT_REG
* - TWAI_DATA_x_REG
* - TWAI_CLOCK_DIVIDER_REG
* - TWAI_SW_STANDBY_CFG_REG
* - TWAI_HW_CFG_REG
* - TWAI_HW_STANDBY_CNT_REG
* - TWAI_IDLE_INTR_CNT_REG
* - TWAI_ECO_CFG_REG
* - TWAI_TIMESTAMP_PRESCALER_REG
* - TWAI_TIMESTAMP_CFG_REG
*/
#define TWAI_RETENTION_REGS_CNT 28
#define TWAI_RETENTION_REGS_BASE(i) REG_TWAI_BASE(i)
static const uint32_t twai_regs_map[4] = {0x9fffe0d1, 0xdf, 0x0, 0x0};
#define TWAI_SLEEP_RETENTION_ENTRIES(id) { \
[0] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TWAI_LINK(0x00), \
TWAI_RETENTION_REGS_BASE(id), TWAI_RETENTION_REGS_BASE(id), \
TWAI_RETENTION_REGS_CNT, 0, 0, \
twai_regs_map[0], twai_regs_map[1], \
twai_regs_map[2], twai_regs_map[3]), \
.owner = ENTRY(0) }, \
}
static const regdma_entries_config_t twai0_regs_retention[] = TWAI_SLEEP_RETENTION_ENTRIES(0);
static const regdma_entries_config_t twai1_regs_retention[] = TWAI_SLEEP_RETENTION_ENTRIES(1);
static const regdma_entries_config_t twai2_regs_retention[] = TWAI_SLEEP_RETENTION_ENTRIES(2);
const twai_reg_retention_info_t twai_reg_retention_info[SOC_TWAI_CONTROLLER_NUM] = {
[0] = {
.module_id = SLEEP_RETENTION_MODULE_TWAI0,
.entry_array = twai0_regs_retention,
.array_size = ARRAY_SIZE(twai0_regs_retention)
},
[1] = {
.module_id = SLEEP_RETENTION_MODULE_TWAI1,
.entry_array = twai1_regs_retention,
.array_size = ARRAY_SIZE(twai1_regs_retention)
},
[2] = {
.module_id = SLEEP_RETENTION_MODULE_TWAI2,
.entry_array = twai2_regs_retention,
.array_size = ARRAY_SIZE(twai2_regs_retention)
},
};

View File

@@ -56,6 +56,7 @@ extern "C" {
#define REGDMA_I2S_LINK(_pri) ((0x1E << 8) | _pri)
#define REGDMA_ETM_LINK(_pri) ((0x1F << 8) | _pri)
#define REGDMA_TSENS_LINK(_pri) ((0x20 << 8) | _pri)
#define REGDMA_TWAI_LINK(_pri) ((0x21 << 8) | _pri)
#define REGDMA_MODEM_FE_LINK(_pri) ((0xFF << 8) | _pri)
#define REGDMA_LINK_PRI_SYS_CLK REGDMA_LINK_PRI_0
@@ -76,6 +77,7 @@ extern "C" {
#define REGDMA_LINK_PRI_I2S REGDMA_LINK_PRI_GENERAL_PERIPH
#define REGDMA_LINK_PRI_UART REGDMA_LINK_PRI_GENERAL_PERIPH
#define REGDMA_LINK_PRI_TEMPERATURE_SENSOR REGDMA_LINK_PRI_GENERAL_PERIPH
#define REGDMA_LINK_PRI_TWAI REGDMA_LINK_PRI_GENERAL_PERIPH
typedef enum {
REGDMA_LINK_PRI_0 = 0,

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -9,6 +9,10 @@
#include <stdint.h>
#include "soc/soc_caps.h"
#include "soc/periph_defs.h"
#if SOC_PAU_SUPPORTED
#include "soc/regdma.h"
#include "soc/retention_periph_defs.h"
#endif
#ifdef __cplusplus
extern "C" {
@@ -30,6 +34,16 @@ typedef struct {
extern const twai_controller_signal_conn_t twai_controller_periph_signals;
#if SOC_PAU_SUPPORTED
typedef struct {
const periph_retention_module_t module_id;
const regdma_entries_config_t *entry_array;
uint32_t array_size;
} twai_reg_retention_info_t;
extern const twai_reg_retention_info_t twai_reg_retention_info[SOC_TWAI_CONTROLLER_NUM];
#endif // SOC_PAU_SUPPORTED
#endif // SOC_TWAI_SUPPORTED
#ifdef __cplusplus

View File

@@ -599,6 +599,14 @@ Application Examples
**Self-Test Example:** :example:`peripherals/twai/twai_self_test` demonstrates how a node can transmit TWAI messages to itself using the TWAI driver's "No Acknowledgement" mode and Self Reception Requests, testing the proper connection of a target to a working external transceiver.
.. only:: SOC_TWAI_SUPPORT_SLEEP_RETENTION
Sleep Retention
^^^^^^^^^^^^^^^
{IDF_TARGET_NAME} supports to retain the TWAI register context before entering **light sleep** and restore them after waking up. This means you don't have to re-init the TWAI driver after the light sleep.
This feature can be enabled by setting the flag :cpp:member:`twai_general_config_t::sleep_allow_pd`. It will allow the system to power down the TWAI in light sleep, meanwhile saving the register context. It can help save more power consumption with some extra cost of the memory.
.. ---------------------------- API Reference ----------------------------------

View File

@@ -157,6 +157,7 @@ The following peripheral drivers are not aware of DFS yet. Applications need to
:SOC_I2S_SUPPORT_SLEEP_RETENTION: - I2S
:SOC_UART_SUPPORT_SLEEP_RETENTION: - All UARTs
:SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION: - Temperature Sensor
:SOC_TWAI_SUPPORT_SLEEP_RETENTION: - All TWAIs
The following peripherals are not yet supported:
@@ -168,7 +169,6 @@ The following peripheral drivers are not aware of DFS yet. Applications need to
- SPI2
- PCNT
- USB-Serial-JTAG
- TWAI
- LEDC
- MCPWM
- SARADC

View File

@@ -599,6 +599,14 @@ TWAI 驱动程序通过 :cpp:type:`twai_message_t` 结构体的不同位字段
**自测示例:** :example:`peripherals/twai/twai_self_test` 演示了节点如何使用 TWAI 驱动程序的无应答模式和自接收请求,向自身传输 TWAI 消息。此示例可用于测试目标芯片与外部收发器之间的连接是否正常。
.. only:: SOC_TWAI_SUPPORT_SLEEP_RETENTION
睡眠保留
^^^^^^^^
{IDF_TARGET_NAME} 支持在进入 **Light Sleep** 之前保留 TWAI 寄存器中的内容,并在唤醒后恢复。即程序不需要在 **Light Sleep** 唤醒后重新配置 TWAI
该特性可以通过置位配置中的 :cpp:member:`twai_general_config_t::sleep_allow_pd` 标志位启用。启用后驱动允许系统在 Light Sleep 时对 TWAI 掉电,同时保存寄存器配置。它可以帮助降低轻度睡眠时的功耗,但需要花费一些额外的存储来保存寄存器的配置。
.. ---------------------------- API Reference ----------------------------------

View File

@@ -157,6 +157,7 @@ ESP-IDF 中集成的电源管理算法可以根据应用程序组件的需求,
:SOC_ETM_SUPPORT_SLEEP_RETENTION: - ETM
:SOC_UART_SUPPORT_SLEEP_RETENTION: - All UARTs
:SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION: - Temperature Sensor
:SOC_TWAI_SUPPORT_SLEEP_RETENTION: - All TWAIs
以下外设尚未支持:
@@ -168,7 +169,6 @@ ESP-IDF 中集成的电源管理算法可以根据应用程序组件的需求,
- SPI2
- PCNT
- USB-Serial-JTAG
- TWAI
- LEDC
- MCPWM
- SARADC