Skip to content

Commit

Permalink
Merge branch 'backport/openthread_light_sleep' into 'release/v5.1'
Browse files Browse the repository at this point in the history
Backportv5.1/openthread light sleep

See merge request espressif/esp-idf!24736
  • Loading branch information
jack0c committed Jul 13, 2023
2 parents 9745b7f + 7f72271 commit a300e79
Show file tree
Hide file tree
Showing 27 changed files with 536 additions and 22 deletions.
1 change: 1 addition & 0 deletions components/esp_hw_support/include/esp_private/esp_regdma.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ extern "C" {
#define REGDMA_SYSTIMER_LINK(_pri) ((0x14 << 8) | _pri)
#define REGDMA_BLE_MAC_LINK(_pri) ((0x15 << 8) | _pri)
#define REGDMA_MODEM_BT_BB_LINK(_pri) ((0x16 << 8) | _pri)
#define REGDMA_MODEM_IEEE802154_LINK(_pri) ((0x17 << 8) | _pri)
#define REGDMA_MODEM_FE_LINK(_pri) ((0xFF << 8) | _pri)

typedef enum {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,8 @@ typedef enum sleep_retention_module_bitmap {
SLEEP_RETENTION_MODULE_WIFI_MAC = BIT(10),
SLEEP_RETENTION_MODULE_WIFI_BB = BIT(11),
SLEEP_RETENTION_MODULE_BLE_MAC = BIT(12),
SLEEP_RETENTION_MODULE_BLE_BB = BIT(13),
SLEEP_RETENTION_MODULE_BT_BB = BIT(13),
SLEEP_RETENTION_MODULE_802154_MAC = BIT(14),
SLEEP_RETENTION_MODULE_802154_BB = BIT(15),

/* digital peripheral module, which includes Interrupt Matrix, HP_SYSTEM,
* TEE, APM, UART, Timer Group, IOMUX, SPIMEM, SysTimer, etc.. */
Expand Down
6 changes: 3 additions & 3 deletions components/esp_hw_support/sleep_clock.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,21 +81,21 @@ bool IRAM_ATTR clock_domain_pd_allowed(void)
const uint32_t modules = sleep_retention_get_modules();
const uint32_t mask = (const uint32_t) (
SLEEP_RETENTION_MODULE_CLOCK_SYSTEM
#if CONFIG_MAC_BB_PD || CONFIG_BT_LE_SLEEP_ENABLE
#if CONFIG_MAC_BB_PD || CONFIG_BT_LE_SLEEP_ENABLE || CONFIG_IEEE802154_SLEEP_ENABLE
| SLEEP_RETENTION_MODULE_CLOCK_MODEM
#endif
);
return ((modules & mask) == mask);
}

#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP || CONFIG_MAC_BB_PD || CONFIG_BT_LE_SLEEP_ENABLE
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP || CONFIG_MAC_BB_PD || CONFIG_BT_LE_SLEEP_ENABLE || CONFIG_IEEE802154_SLEEP_ENABLE
ESP_SYSTEM_INIT_FN(sleep_clock_startup_init, BIT(0), 106)
{
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
sleep_clock_system_retention_init();
#endif

#if CONFIG_MAC_BB_PD || CONFIG_BT_LE_SLEEP_ENABLE
#if CONFIG_MAC_BB_PD || CONFIG_BT_LE_SLEEP_ENABLE || CONFIG_IEEE802154_SLEEP_ENABLE
sleep_clock_modem_retention_init();
#endif
return ESP_OK;
Expand Down
4 changes: 2 additions & 2 deletions components/esp_hw_support/sleep_modem.c
Original file line number Diff line number Diff line change
Expand Up @@ -279,9 +279,9 @@ bool IRAM_ATTR modem_domain_pd_allowed(void)
const uint32_t mask_wifi = (const uint32_t) (SLEEP_RETENTION_MODULE_WIFI_MAC |
SLEEP_RETENTION_MODULE_WIFI_BB);
const uint32_t mask_ble = (const uint32_t) (SLEEP_RETENTION_MODULE_BLE_MAC |
SLEEP_RETENTION_MODULE_BLE_BB);
SLEEP_RETENTION_MODULE_BT_BB);
const uint32_t mask_154 = (const uint32_t) (SLEEP_RETENTION_MODULE_802154_MAC |
SLEEP_RETENTION_MODULE_802154_BB);
SLEEP_RETENTION_MODULE_BT_BB);
return (((modules & mask_wifi) == mask_wifi) ||
((modules & mask_ble) == mask_ble) ||
((modules & mask_154) == mask_154));
Expand Down
1 change: 0 additions & 1 deletion components/esp_hw_support/sleep_retention.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
#include "sdkconfig.h"
#include "esp_pmu.h"


static __attribute__((unused)) const char *TAG = "sleep";

/**
Expand Down
4 changes: 2 additions & 2 deletions components/esp_phy/src/btbb_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,15 @@ static esp_err_t btbb_sleep_retention_init(void)
[1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_MODEM_BT_BB_LINK(0x01), BB_PART_1_ADDR, BB_PART_1_ADDR, BB_PART_1_SIZE, 0, 0), .owner = BTBB_LINK_OWNER },
[2] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_MODEM_BT_BB_LINK(0x02), BB_PART_2_ADDR, BB_PART_2_ADDR, BB_PART_2_SIZE, 0, 0), .owner = BTBB_LINK_OWNER }
};
esp_err_t err = sleep_retention_entries_create(btbb_regs_retention, ARRAY_SIZE(btbb_regs_retention), REGDMA_LINK_PRI_5, SLEEP_RETENTION_MODULE_BLE_BB);
esp_err_t err = sleep_retention_entries_create(btbb_regs_retention, ARRAY_SIZE(btbb_regs_retention), REGDMA_LINK_PRI_5, SLEEP_RETENTION_MODULE_BT_BB);
ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for btbb retention");
ESP_LOGI(TAG, "btbb sleep retention initialization");
return ESP_OK;
}

static void btbb_sleep_retention_deinit(void)
{
sleep_retention_entries_destroy(SLEEP_RETENTION_MODULE_BLE_BB);
sleep_retention_entries_destroy(SLEEP_RETENTION_MODULE_BT_BB);
}
#endif // SOC_PM_MODEM_RETENTION_BY_REGDMA && CONFIG_FREERTOS_USE_TICKLESS_IDLE

Expand Down
8 changes: 8 additions & 0 deletions components/ieee802154/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,12 @@ menu "IEEE 802.15.4"
Enabling this option increases throughput by ~5% at the expense of ~2.1k
IRAM code size increase.

config IEEE802154_SLEEP_ENABLE
# Todo: Remove when support safe power-down of the power domain (IDF-7317)
bool "Enable IEEE802154 light sleep"
depends on PM_ENABLE && PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
default n
help
Enabling this option allows the IEEE802.15.4 module to be powered down during automatic light sleep,
which reduces current consumption.
endmenu # IEEE 802.15.4
59 changes: 56 additions & 3 deletions components/ieee802154/driver/esp_ieee802154_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@
#include "esp_ieee802154_timer.h"
#include "hal/ieee802154_ll.h"
#include "esp_attr.h"
#include "esp_phy_init.h"

#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
#include "esp_pm.h"
#include "esp_private/esp_clk.h"
#include "esp_private/sleep_retention.h"
#endif

#define CCA_DETECTION_TIME 8

Expand All @@ -38,6 +45,8 @@ static uint8_t s_enh_ack_frame[128];
static uint8_t s_recent_rx_frame_info_index;
static portMUX_TYPE s_ieee802154_spinlock = portMUX_INITIALIZER_UNLOCKED;

static esp_err_t ieee802154_sleep_init(void);

static IRAM_ATTR void event_end_process(void)
{
ieee802154_etm_channel_clear(IEEE802154_ETM_CHANNEL0);
Expand Down Expand Up @@ -193,7 +202,11 @@ IEEE802154_STATIC bool stop_current_operation(void)
break;

case IEEE802154_STATE_IDLE:
// do nothing
ieee802154_ll_set_cmd(IEEE802154_CMD_STOP);
break;

case IEEE802154_STATE_SLEEP:
// Do nothing
break;

case IEEE802154_STATE_RX:
Expand Down Expand Up @@ -580,10 +593,12 @@ IEEE802154_STATIC IRAM_ATTR void ieee802154_exit_critical(void)
void ieee802154_enable(void)
{
modem_clock_module_enable(ieee802154_periph.module);
s_ieee802154_state = IEEE802154_STATE_IDLE;
}

void ieee802154_disable(void)
{
modem_clock_module_disable(ieee802154_periph.module);
s_ieee802154_state = IEEE802154_STATE_DISABLE;
}

Expand Down Expand Up @@ -616,12 +631,13 @@ esp_err_t ieee802154_mac_init(void)
#endif

memset(s_rx_frame, 0, sizeof(s_rx_frame));
s_ieee802154_state = IEEE802154_STATE_IDLE;

// TODO: Add flags for IEEE802154 ISR allocating. TZ-102
ret = esp_intr_alloc(ieee802154_periph.irq_id, 0, ieee802154_isr, NULL, NULL);
ESP_RETURN_ON_FALSE(ret == ESP_OK, ESP_FAIL, IEEE802154_TAG, "IEEE802154 MAC init failed");

ESP_RETURN_ON_FALSE(ieee802154_sleep_init() == ESP_OK, ESP_FAIL, IEEE802154_TAG, "IEEE802154 MAC sleep init failed");

return ret;
}

Expand Down Expand Up @@ -743,12 +759,49 @@ esp_err_t ieee802154_receive_at(uint32_t time)
return ESP_OK;
}

static esp_err_t ieee802154_sleep_init(void)
{
esp_err_t err = ESP_OK;
#if SOC_PM_MODEM_RETENTION_BY_REGDMA && CONFIG_FREERTOS_USE_TICKLESS_IDLE
#define N_REGS_IEEE802154() (((IEEE802154_MAC_DATE_REG - IEEE802154_REG_BASE) / 4) + 1)
const static sleep_retention_entries_config_t ieee802154_mac_regs_retention[] = {
[0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_MODEM_IEEE802154_LINK(0x00), IEEE802154_REG_BASE, IEEE802154_REG_BASE, N_REGS_IEEE802154(), 0, 0), .owner = ENTRY(3) },
};
err = sleep_retention_entries_create(ieee802154_mac_regs_retention, ARRAY_SIZE(ieee802154_mac_regs_retention), REGDMA_LINK_PRI_7, SLEEP_RETENTION_MODULE_802154_MAC);
ESP_RETURN_ON_ERROR(err, IEEE802154_TAG, "failed to allocate memory for ieee802154 mac retention");
ESP_LOGI(IEEE802154_TAG, "ieee802154 mac sleep retention initialization");
#endif
return err;
}

IRAM_ATTR void ieee802154_enter_sleep(void)
{
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
esp_phy_disable();
#if SOC_PM_RETENTION_HAS_CLOCK_BUG
sleep_retention_do_extra_retention(true);// backup
#endif
ieee802154_disable(); // IEEE802154 CLOCK Disable
#endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE
}

IRAM_ATTR void ieee802154_wakeup(void)
{
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
ieee802154_enable(); // IEEE802154 CLOCK Enable
#if SOC_PM_RETENTION_HAS_CLOCK_BUG
sleep_retention_do_extra_retention(false);// restore
#endif
esp_phy_enable();
#endif //CONFIG_FREERTOS_USE_TICKLESS_IDLE
}

esp_err_t ieee802154_sleep(void)
{
ieee802154_enter_critical();

stop_current_operation();
s_ieee802154_state = IEEE802154_STATE_IDLE;
s_ieee802154_state = IEEE802154_STATE_SLEEP;

ieee802154_exit_critical();
return ESP_OK;
Expand Down
13 changes: 13 additions & 0 deletions components/ieee802154/esp_ieee802154.c
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,9 @@ esp_ieee802154_state_t esp_ieee802154_get_state(void)
return ESP_IEEE802154_RADIO_DISABLE;

case IEEE802154_STATE_IDLE:
return ESP_IEEE802154_RADIO_IDLE;

case IEEE802154_STATE_SLEEP:
return ESP_IEEE802154_RADIO_SLEEP;

case IEEE802154_STATE_RX:
Expand Down Expand Up @@ -331,6 +334,16 @@ uint8_t esp_ieee802154_get_recent_lqi(void)
return ieee802154_get_recent_lqi();
}

void esp_ieee802154_enter_sleep(void)
{
ieee802154_enter_sleep();
}

void esp_ieee802154_wakeup(void)
{
ieee802154_wakeup();
}

__attribute__((weak)) void esp_ieee802154_receive_done(uint8_t *data, esp_ieee802154_frame_info_t *frame_info)
{

Expand Down
10 changes: 10 additions & 0 deletions components/ieee802154/include/esp_ieee802154.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,16 @@ esp_ieee802154_state_t esp_ieee802154_get_state(void);
*/
esp_err_t esp_ieee802154_sleep(void);

/**
* @brief The IEEE 802.15.4 enter sleep.
*/
void esp_ieee802154_enter_sleep(void);

/**
* @brief The IEEE 802.15.4 wakeup.
*/
void esp_ieee802154_wakeup(void);

/**
* @brief Set the IEEE 802.15.4 Radio to receive state.
*
Expand Down
1 change: 1 addition & 0 deletions components/ieee802154/include/esp_ieee802154_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ extern "C" {
*/
typedef enum {
ESP_IEEE802154_RADIO_DISABLE, /*!< Radio not up */
ESP_IEEE802154_RADIO_IDLE, /*!< Radio in the idle state */
ESP_IEEE802154_RADIO_SLEEP, /*!< Radio in the sleep state */
ESP_IEEE802154_RADIO_RECEIVE, /*!< Radio in the receive state */
ESP_IEEE802154_RADIO_TRANSMIT, /*!< Radio in the transmit state */
Expand Down
13 changes: 13 additions & 0 deletions components/ieee802154/private_include/esp_ieee802154_dev.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ extern "C" {
typedef enum {
IEEE802154_STATE_DISABLE, /*!< IEEE802154 radio state disable */
IEEE802154_STATE_IDLE, /*!< IEEE802154 radio state idle */
IEEE802154_STATE_SLEEP, /*!< IEEE802154 radio state sleep */
IEEE802154_STATE_RX, /*!< IEEE802154 radio state rx */
IEEE802154_STATE_TX_ACK, /*!< IEEE802154 radio state tx ack */
IEEE802154_STATE_TX_ENH_ACK, /*!< IEEE802154 radio state tx enh-ack */
Expand Down Expand Up @@ -177,6 +178,18 @@ uint8_t ieee802154_get_recent_lqi(void);
*/
ieee802154_state_t ieee802154_get_state(void);

/**
* @brief The IEEE 802.15.4 enter sleep.
*
*/
void ieee802154_enter_sleep(void);

/**
* @brief The IEEE 802.15.4 wakeup.
*
*/
void ieee802154_wakeup(void);

/** The following three functions are only used for internal test. **/
/**
* @brief The clear channel assessment done.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,17 +129,17 @@ def test_based_txrx(dut: Tuple[IdfDut, IdfDut]) -> None:
receive.expect('RX Start', timeout=10)
transmit.expect('ieee802154>', timeout=10)
transmit.write('tx -l 10')
transmit.expect('tx sfd done, Radio state: 3', timeout=10)
transmit.expect('tx sfd done, Radio state: 4', timeout=10)
transmit.expect('Tx Done 10 bytes', timeout=10)
transmit.expect('00 01 02 03 04 05 06 07', timeout=10)
transmit.expect('08 09 00 00 00 00 00 00', timeout=10)
receive.expect('rx sfd done, Radio state: 2', timeout=10)
receive.expect('rx sfd done, Radio state: 3', timeout=10)
receive.expect('Rx Done 10 bytes', timeout=10)
receive.expect('00 01 02 03 04 05 06 07', timeout=10)
receive.write('rx -r 0')
receive.expect('radio exit receive mode', timeout=10)
transmit.write('tx -l 10')
transmit.expect('tx sfd done, Radio state: 3', timeout=10)
transmit.expect('tx sfd done, Radio state: 4', timeout=10)
transmit.expect('Tx Done 10 bytes', timeout=10)
transmit.expect('00 01 02 03 04 05 06 07', timeout=10)
transmit.expect('08 09 00 00 00 00 00 00', timeout=10)
Expand Down Expand Up @@ -344,13 +344,13 @@ def test_based_autoack(dut: Tuple[IdfDut, IdfDut]) -> None:
receive.expect('RX Start', timeout=10)

transmit.write('tx 0x20 0x88 0x00 0x0A 0x28 0xDB 0x6F 0xBC 0x94 0x5A 0x43 0x68 0x02 0xaa 0x15 0x30 0x01 0x02')
transmit.expect('tx sfd done, Radio state: 3', timeout=10)
transmit.expect('rx sfd done, Radio state: 3', timeout=10)
transmit.expect('tx sfd done, Radio state: 4', timeout=10)
transmit.expect('rx sfd done, Radio state: 4', timeout=10)
transmit.expect('Tx Done 18 bytes', timeout=10)
transmit.expect('20 88 00 0a 28 db 6f bc', timeout=10)
transmit.expect('94 5a 43 68 02 aa 15 30', timeout=10)

receive.expect('rx sfd done, Radio state: 2', timeout=10)
receive.expect('rx sfd done, Radio state: 3', timeout=10)
receive.expect('Rx Done 18 bytes', timeout=10)
receive.expect('20 88 00 0a 28 db 6f bc', timeout=10)
receive.expect('94 5a 43 68 02 aa 15 30', timeout=10)
Expand Down Expand Up @@ -573,7 +573,7 @@ def test_based_transmit_failed(dut: IdfDut) -> None:
transmit.write('tx -l 10 -C')
transmit.expect('the Frame Transmission failed, Failure reason: 1', timeout=10)
transmit.write('tx -l 10')
transmit.expect('tx sfd done, Radio state: 3', timeout=10)
transmit.expect('tx sfd done, Radio state: 4', timeout=10)
transmit.expect('Tx Done 10 bytes', timeout=10)
transmit.expect('00 01 02 03 04 05 06 07', timeout=10)
transmit.expect('08 09 00 00 00 00 00 00', timeout=10)
Expand Down
5 changes: 5 additions & 0 deletions components/openthread/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,11 @@ if(CONFIG_OPENTHREAD_ENABLED)
"src/esp_openthread_dns64.c")
endif()

if(NOT CONFIG_FREERTOS_USE_TICKLESS_IDLE)
list(APPEND exclude_srcs
"src/port/esp_openthread_sleep.c")
endif()

if(CONFIG_OPENTHREAD_FTD)
set(device_type "OPENTHREAD_FTD=1")
elseif(CONFIG_OPENTHREAD_MTD)
Expand Down
42 changes: 42 additions & 0 deletions components/openthread/private_include/esp_openthread_sleep.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

#pragma once

#include "esp_err.h"
#include "sdkconfig.h"

#ifdef __cplusplus
extern "C" {
#endif

#ifdef CONFIG_FREERTOS_USE_TICKLESS_IDLE
/**
* @brief This function initializes the OpenThread sleep.
*
* @return
* - ESP_OK on success
* - ESP_FAIL on failure
*
*/
esp_err_t esp_openthread_sleep_init(void);

/**
* @brief This function performs the OpenThread sleep process.
*
*/
void esp_openthread_sleep_process(void);

/**
* @brief This function performs the OpenThread wakeup process.
*
*/
void esp_openthread_wakeup_process(void);
#endif

#ifdef __cplusplus
}
#endif
Loading

0 comments on commit a300e79

Please sign in to comment.