forked from espressif/esp-idf
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:
@@ -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);
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -1,2 +1,4 @@
|
||||
CONFIG_FREERTOS_HZ=1000
|
||||
CONFIG_ESP_TASK_WDT=n
|
||||
# primitives for checking sleep internal state
|
||||
CONFIG_ESP_SLEEP_DEBUG=y
|
||||
|
@@ -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;
|
||||
|
||||
/**
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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)
|
||||
},
|
||||
};
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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)
|
||||
},
|
||||
};
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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)
|
||||
},
|
||||
};
|
||||
|
@@ -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,
|
||||
|
@@ -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
|
||||
|
@@ -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 ----------------------------------
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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 ----------------------------------
|
||||
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user