kopia lustrzana https://github.com/espressif/esp-idf
Porównaj commity
103 Commity
ace5266e76
...
4b192ddb00
Autor | SHA1 | Data |
---|---|---|
mitchellcairns | 4b192ddb00 | |
morris | 9b3ae86417 | |
Marius Vikhammer | eb7c381761 | |
Jiang Jiang Jian | d82d7039fc | |
Jiang Jiang Jian | 3d56f1b1b9 | |
Wang Meng Yang | dc3e9531c0 | |
morris | 4cf7387e14 | |
morris | bc4c826ff1 | |
morris | 8374791fd4 | |
Michael (XIAO Xufeng) | 78b6d515bb | |
Darian Leung | 27e8db2ae9 | |
Omar Chebib | 70fc931dd2 | |
Wang Mengyang | 4d7f9c5d88 | |
Wang Mengyang | c136089f4e | |
Wang Mengyang | bb6cf16177 | |
Wang Mengyang | a06844d9b1 | |
Jiang Jiang Jian | 5ec51688a6 | |
Song Ruo Jing | 64984b7b71 | |
Song Ruo Jing | 15962a953a | |
Song Ruo Jing | 1ed2f223fb | |
Song Ruo Jing | 373e585bb7 | |
Karl Palsson | 52702cf886 | |
Island | 5fa34283c0 | |
xuxiao | 9897fd9c87 | |
Jiang Jiang Jian | 8b4177f148 | |
zwl | 275eab4f5d | |
zwl | 05521c918d | |
zwl | e99f45b4c6 | |
zwl | a64a528cb8 | |
Shu Chen | 66c164b90b | |
Jiang Jiang Jian | d4e32532df | |
Jiang Jiang Jian | 5aad8507cb | |
Jiang Jiang Jian | 1c09bc1675 | |
Jin Cheng | 89dbe5f6dc | |
Kapil Gupta | 5ce43f68f3 | |
Sarvesh Bodakhe | 3ba5cb9687 | |
Kapil Gupta | 280ec09b03 | |
Alexey Lapshin | d2e5b33e2c | |
liqigan | 98b744c85b | |
cjin | ca79a7d878 | |
Xu Si Yu | d4a361bb71 | |
Dávid Fehér | d574cea5e5 | |
Rahul Tank | 2ba5320112 | |
Jiang Jiang Jian | 85e5f0e546 | |
Roland Dobai | f0e5c92516 | |
Rahul Tank | 28157cf1e2 | |
jgujarathi | 0a13c60466 | |
Shu Chen | 1b9597f961 | |
Xu Si Yu | fd36f6fcac | |
Xu Si Yu | cea24c7137 | |
Xu Si Yu | c3398f3373 | |
Shu Chen | 85315941e3 | |
xiaqilin | 9e9aeb64be | |
xiaqilin | b89f08a615 | |
Jiang Jiang Jian | 470d5406ec | |
Frantisek Hrbata | 4bc2985aa3 | |
Wang Meng Yang | b0eef7f889 | |
Li Shuai | f20186fe02 | |
Li Shuai | 4066844908 | |
xiaqilin | ea3094a9a6 | |
Li Shuai | 71d37432da | |
Li Shuai | 8f9090b351 | |
Li Shuai | 0e28063291 | |
Li Shuai | 376b2f74ed | |
Li Shuai | 9f52809629 | |
Li Shuai | 9c8b54b886 | |
Li Shuai | 4faf042c21 | |
Li Shuai | 9a51752d4d | |
Li Shuai | e7d6748aec | |
Li Shuai | a2cbe3f0a3 | |
Li Shuai | f66e3f031d | |
Jiang Jiang Jian | 9efa26a23f | |
Jiang Jiang Jian | 3b9d5e120e | |
Marius Vikhammer | aaf3f4a7c3 | |
Mahavir Jain | 082c713069 | |
Li Shuai | f5c8cc2bef | |
Li Shuai | fd47ea34bb | |
Island | b19e27dd48 | |
Jiang Jiang Jian | 22fbaf65fd | |
Island | e362358ea3 | |
xiongweichao | 47d542acaa | |
zhanghaipeng | c079772799 | |
muhaidong | a07bce4fcc | |
muhaidong | 0e34a993d0 | |
muhaidong | 458ce7d4cf | |
Andy Lin | 6bcf47386d | |
zhangyanjiao | 830464eee7 | |
zhangyanjiao | 83f272ca4f | |
Omar Chebib | dcc7a41ad8 | |
zwl | 73f6ca8ebf | |
zwl | cc213b7c61 | |
harshal.patil | 42f244ae61 | |
Kapil Gupta | f9feb970b9 | |
Mitch Cairns | 45729f0897 | |
Mitch Cairns | 151ac2efbf | |
Mitch Cairns | db15af1aa8 | |
Mitch Cairns | 795edfdbf5 | |
mitchellcairns | 73616f8aab | |
mitchellcairns | 35021387d2 | |
mitchellcairns | 730919f274 | |
mitchellcairns | b86d322c3d | |
mitchellcairns | 3ccbb041e3 | |
mitchellcairns | 9a36745d25 |
|
@ -67,37 +67,40 @@ if(CONFIG_IDF_DOC_BUILD)
|
|||
${nimble_hci_include_dirs})
|
||||
endif()
|
||||
|
||||
|
||||
if(CONFIG_BT_ENABLED)
|
||||
|
||||
set(srcs "")
|
||||
set(include_dirs "")
|
||||
set(ldfragments "linker.lf")
|
||||
set(ldscripts "linker_common.lf")
|
||||
if(CONFIG_BT_CONTROLLER_ENABLED)
|
||||
if(CONFIG_IDF_TARGET_ESP32)
|
||||
list(APPEND srcs "controller/esp32/bt.c"
|
||||
"controller/esp32/hli_api.c"
|
||||
"controller/esp32/hli_vectors.S")
|
||||
list(APPEND ldscripts "linker_rw_bt_controller.lf")
|
||||
|
||||
elseif(CONFIG_IDF_TARGET_ESP32C3)
|
||||
list(APPEND srcs "controller/esp32c3/bt.c")
|
||||
list(APPEND ldscripts "linker_rw_bt_controller.lf")
|
||||
|
||||
elseif(CONFIG_IDF_TARGET_ESP32S3)
|
||||
list(APPEND srcs "controller/esp32c3/bt.c")
|
||||
list(APPEND ldscripts "linker_rw_bt_controller.lf")
|
||||
|
||||
elseif(CONFIG_IDF_TARGET_ESP32C2)
|
||||
set(ldfragments "linker.lf.esp32c2")
|
||||
list(APPEND srcs "controller/esp32c2/bt.c")
|
||||
set(ldscripts "linker_esp32c2.lf")
|
||||
|
||||
elseif(CONFIG_IDF_TARGET_ESP32C6)
|
||||
list(APPEND srcs "controller/esp32c6/bt.c")
|
||||
list(APPEND ldscripts "linker_esp_ble_controller.lf")
|
||||
|
||||
elseif(CONFIG_IDF_TARGET_ESP32H2)
|
||||
list(APPEND srcs "controller/esp32h2/bt.c")
|
||||
list(APPEND ldscripts "linker_esp_ble_controller.lf")
|
||||
endif()
|
||||
|
||||
list(APPEND include_dirs ${target_specific_include_dirs})
|
||||
|
||||
endif()
|
||||
|
||||
# Common
|
||||
|
@ -820,7 +823,7 @@ idf_component_register(SRCS "${srcs}"
|
|||
PRIV_INCLUDE_DIRS "${priv_include_dirs}"
|
||||
REQUIRES esp_timer esp_wifi
|
||||
PRIV_REQUIRES nvs_flash soc esp_pm esp_phy esp_coex mbedtls driver vfs
|
||||
LDFRAGMENTS "${ldfragments}")
|
||||
LDFRAGMENTS "${ldscripts}")
|
||||
|
||||
if(CONFIG_BT_ENABLED)
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-implicit-fallthrough -Wno-unused-const-variable)
|
||||
|
@ -837,14 +840,8 @@ if(CONFIG_BT_ENABLED)
|
|||
target_link_directories(${COMPONENT_LIB} INTERFACE
|
||||
"${CMAKE_CURRENT_LIST_DIR}/controller/lib_esp32c3_family/esp32s3")
|
||||
target_link_libraries(${COMPONENT_LIB} PUBLIC btdm_app)
|
||||
elseif(CONFIG_IDF_TARGET_ESP32C2)
|
||||
add_prebuilt_library(libble_app "controller/lib_esp32c2/esp32c2-bt-lib/libble_app.a")
|
||||
target_link_libraries(${COMPONENT_LIB} PRIVATE libble_app)
|
||||
elseif(CONFIG_IDF_TARGET_ESP32C6)
|
||||
add_prebuilt_library(libble_app "controller/lib_esp32c6/esp32c6-bt-lib/libble_app.a")
|
||||
target_link_libraries(${COMPONENT_LIB} PRIVATE libble_app)
|
||||
elseif(CONFIG_IDF_TARGET_ESP32H2)
|
||||
add_prebuilt_library(libble_app "controller/lib_esp32h2/esp32h2-bt-lib/libble_app.a")
|
||||
elseif(CONFIG_BT_CONTROLLER_ENABLED)
|
||||
add_prebuilt_library(libble_app "controller/lib_${target}/${target}-bt-lib/libble_app.a")
|
||||
target_link_libraries(${COMPONENT_LIB} PRIVATE libble_app)
|
||||
endif()
|
||||
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
@ -233,16 +233,12 @@ extern uint32_t _data_end_btdm_rom;
|
|||
|
||||
extern uint32_t _bt_bss_start;
|
||||
extern uint32_t _bt_bss_end;
|
||||
extern uint32_t _nimble_bss_start;
|
||||
extern uint32_t _nimble_bss_end;
|
||||
extern uint32_t _btdm_bss_start;
|
||||
extern uint32_t _btdm_bss_end;
|
||||
extern uint32_t _bt_controller_bss_start;
|
||||
extern uint32_t _bt_controller_bss_end;
|
||||
extern uint32_t _bt_data_start;
|
||||
extern uint32_t _bt_data_end;
|
||||
extern uint32_t _nimble_data_start;
|
||||
extern uint32_t _nimble_data_end;
|
||||
extern uint32_t _btdm_data_start;
|
||||
extern uint32_t _btdm_data_end;
|
||||
extern uint32_t _bt_controller_data_start;
|
||||
extern uint32_t _bt_controller_data_end;
|
||||
|
||||
extern void config_bt_funcs_reset(void);
|
||||
extern void config_ble_funcs_reset(void);
|
||||
|
@ -760,7 +756,7 @@ static int32_t queue_send_hlevel_wrapper(void *queue, void *item, uint32_t block
|
|||
* @param item The message which will be send
|
||||
* @param hptw need do task yield or not
|
||||
* @return send success or not
|
||||
* There is an issue here: When the queue is full, it may reture true but it send fail to the queue, sometimes.
|
||||
* There is an issue here: When the queue is full, it may return true but it send fail to the queue, sometimes.
|
||||
* But in Bluetooth controller's isr, We don't care about the return value.
|
||||
* It only required tp send success when the queue is empty all the time.
|
||||
* So, this function meets the requirement.
|
||||
|
@ -1281,7 +1277,45 @@ static esp_err_t try_heap_caps_add_region(intptr_t start, intptr_t end)
|
|||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_controller_mem_release(esp_bt_mode_t mode)
|
||||
typedef struct {
|
||||
intptr_t start;
|
||||
intptr_t end;
|
||||
const char* name;
|
||||
} bt_area_t;
|
||||
|
||||
|
||||
static esp_err_t esp_bt_mem_release_area(const bt_area_t *area)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
intptr_t mem_start = area->start;
|
||||
intptr_t mem_end = area->end;
|
||||
if (mem_start != mem_end) {
|
||||
ESP_LOGD(BTDM_LOG_TAG, "Release %s [0x%08x] - [0x%08x], len %d", area->name, mem_start, mem_end, mem_end - mem_start);
|
||||
ret = try_heap_caps_add_region(mem_start, mem_end);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t esp_bt_mem_release_areas(const bt_area_t *area1, const bt_area_t *area2)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
if (area1->end == area2->start) {
|
||||
bt_area_t merged_area = {
|
||||
.start = area1->start,
|
||||
.end = area2->end,
|
||||
.name = area1->name
|
||||
};
|
||||
ret = esp_bt_mem_release_area(&merged_area);
|
||||
} else {
|
||||
esp_bt_mem_release_area(area1);
|
||||
ret = esp_bt_mem_release_area(area2);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t esp_bt_controller_rom_mem_release(esp_bt_mode_t mode)
|
||||
{
|
||||
bool update = true;
|
||||
intptr_t mem_start=(intptr_t) NULL, mem_end=(intptr_t) NULL;
|
||||
|
@ -1332,61 +1366,86 @@ esp_err_t esp_bt_controller_mem_release(esp_bt_mode_t mode)
|
|||
}
|
||||
}
|
||||
|
||||
if (mode == ESP_BT_MODE_BTDM) {
|
||||
mem_start = (intptr_t)&_btdm_bss_start;
|
||||
mem_end = (intptr_t)&_btdm_bss_end;
|
||||
if (mem_start != mem_end) {
|
||||
ESP_LOGD(BTDM_LOG_TAG, "Release BTDM BSS [0x%08x] - [0x%08x]", mem_start, mem_end);
|
||||
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
|
||||
}
|
||||
mem_start = (intptr_t)&_btdm_data_start;
|
||||
mem_end = (intptr_t)&_btdm_data_end;
|
||||
if (mem_start != mem_end) {
|
||||
ESP_LOGD(BTDM_LOG_TAG, "Release BTDM Data [0x%08x] - [0x%08x]", mem_start, mem_end);
|
||||
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_controller_mem_release(esp_bt_mode_t mode)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_IDLE) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (mode == ESP_BT_MODE_BTDM) {
|
||||
bt_area_t cont_bss = {
|
||||
.start = (intptr_t)&_bt_controller_bss_start,
|
||||
.end = (intptr_t)&_bt_controller_bss_end,
|
||||
.name = "BT Controller BSS",
|
||||
};
|
||||
bt_area_t cont_data = {
|
||||
.start = (intptr_t)&_bt_controller_data_start,
|
||||
.end = (intptr_t)&_bt_controller_data_end,
|
||||
.name = "BT Controller Data"
|
||||
};
|
||||
|
||||
ret = esp_bt_mem_release_areas(&cont_data, &cont_bss);
|
||||
}
|
||||
|
||||
if (ret == ESP_OK) {
|
||||
ret = esp_bt_controller_rom_mem_release(mode);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_mem_release(esp_bt_mode_t mode)
|
||||
{
|
||||
int ret;
|
||||
intptr_t mem_start, mem_end;
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
ret = esp_bt_controller_mem_release(mode);
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_IDLE) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
bt_area_t bss = {
|
||||
.start = (intptr_t)&_bt_bss_start,
|
||||
.end = (intptr_t)&_bt_bss_end,
|
||||
.name = "BT BSS",
|
||||
};
|
||||
bt_area_t cont_bss = {
|
||||
.start = (intptr_t)&_bt_controller_bss_start,
|
||||
.end = (intptr_t)&_bt_controller_bss_end,
|
||||
.name = "BT Controller BSS",
|
||||
};
|
||||
bt_area_t data = {
|
||||
.start = (intptr_t)&_bt_data_start,
|
||||
.end = (intptr_t)&_bt_data_end,
|
||||
.name = "BT Data",
|
||||
};
|
||||
bt_area_t cont_data = {
|
||||
.start = (intptr_t)&_bt_controller_data_start,
|
||||
.end = (intptr_t)&_bt_controller_data_end,
|
||||
.name = "BT Controller Data"
|
||||
};
|
||||
|
||||
if (mode == ESP_BT_MODE_BTDM) {
|
||||
mem_start = (intptr_t)&_bt_bss_start;
|
||||
mem_end = (intptr_t)&_bt_bss_end;
|
||||
if (mem_start != mem_end) {
|
||||
ESP_LOGD(BTDM_LOG_TAG, "Release BT BSS [0x%08x] - [0x%08x]", mem_start, mem_end);
|
||||
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
|
||||
}
|
||||
mem_start = (intptr_t)&_bt_data_start;
|
||||
mem_end = (intptr_t)&_bt_data_end;
|
||||
if (mem_start != mem_end) {
|
||||
ESP_LOGD(BTDM_LOG_TAG, "Release BT Data [0x%08x] - [0x%08x]", mem_start, mem_end);
|
||||
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
|
||||
/* Start by freeing Bluetooth BSS section */
|
||||
if (ret == ESP_OK) {
|
||||
ret = esp_bt_mem_release_areas(&bss, &cont_bss);
|
||||
}
|
||||
|
||||
mem_start = (intptr_t)&_nimble_bss_start;
|
||||
mem_end = (intptr_t)&_nimble_bss_end;
|
||||
if (mem_start != mem_end) {
|
||||
ESP_LOGD(BTDM_LOG_TAG, "Release NimBLE BSS [0x%08x] - [0x%08x]", mem_start, mem_end);
|
||||
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
|
||||
}
|
||||
mem_start = (intptr_t)&_nimble_data_start;
|
||||
mem_end = (intptr_t)&_nimble_data_end;
|
||||
if (mem_start != mem_end) {
|
||||
ESP_LOGD(BTDM_LOG_TAG, "Release NimBLE Data [0x%08x] - [0x%08x]", mem_start, mem_end);
|
||||
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
|
||||
/* Do the same thing with the Bluetooth data section */
|
||||
if (ret == ESP_OK) {
|
||||
ret = esp_bt_mem_release_areas(&data, &cont_data);
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
|
||||
/* free data and BSS section for Bluetooth controller ROM code */
|
||||
if (ret == ESP_OK) {
|
||||
ret = esp_bt_controller_rom_mem_release(mode);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if CONFIG_BTDM_CTRL_HLI
|
||||
|
@ -1695,7 +1754,7 @@ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode)
|
|||
|
||||
sdk_config_set_bt_pll_track_enable(true);
|
||||
|
||||
// inititalize bluetooth baseband
|
||||
// initialize bluetooth baseband
|
||||
btdm_check_and_init_bb();
|
||||
|
||||
ret = btdm_controller_enable(mode);
|
||||
|
@ -1858,7 +1917,7 @@ esp_err_t esp_ble_scan_dupilcate_list_flush(void)
|
|||
|
||||
/**
|
||||
* This function re-write controller's function,
|
||||
* As coredump can not show paramerters in function which is in a .a file.
|
||||
* As coredump can not show parameters in function which is in a .a file.
|
||||
*
|
||||
* After coredump fixing this issue, just delete this function.
|
||||
*/
|
||||
|
|
|
@ -450,6 +450,7 @@ config BT_LE_USE_ESP_TIMER
|
|||
|
||||
config BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_SUPP
|
||||
bool "BLE adv report flow control supported"
|
||||
depends on BT_LE_ROLE_OBSERVER_ENABLE
|
||||
default y
|
||||
help
|
||||
The function is mainly used to enable flow control for advertising reports. When it is enabled,
|
||||
|
@ -498,3 +499,31 @@ config BT_LE_CCA_RSSI_THRESH
|
|||
default 20
|
||||
help
|
||||
Power threshold of CCA in unit of -1 dBm.
|
||||
|
||||
config BT_LE_ROLE_CENTROL_ENABLE
|
||||
bool "Enable BLE Centrol role function"
|
||||
depends on !BT_NIMBLE_ENABLED
|
||||
default y
|
||||
help
|
||||
Enable centrol role function.
|
||||
|
||||
config BT_LE_ROLE_PERIPHERAL_ENABLE
|
||||
bool "Enable BLE Peripheral role function"
|
||||
depends on !BT_NIMBLE_ENABLED
|
||||
default y
|
||||
help
|
||||
Enable Peripheral role function.
|
||||
|
||||
config BT_LE_ROLE_BROADCASTER_ENABLE
|
||||
bool "Enable BLE Broadcaster role function"
|
||||
depends on !BT_NIMBLE_ENABLED
|
||||
default y
|
||||
help
|
||||
Enable broadcaster role function.
|
||||
|
||||
config BT_LE_ROLE_OBSERVER_ENABLE
|
||||
bool "Enable BLE Observer role function"
|
||||
depends on !BT_NIMBLE_ENABLED
|
||||
default y
|
||||
help
|
||||
Enable observer role function.
|
||||
|
|
|
@ -168,11 +168,17 @@ extern const char *r_ble_controller_get_rom_compile_version(void);
|
|||
#if CONFIG_BT_RELEASE_IRAM
|
||||
extern uint32_t _iram_bt_text_start;
|
||||
extern uint32_t _bss_bt_end;
|
||||
#else
|
||||
extern uint32_t _bt_bss_end;
|
||||
extern uint32_t _bt_controller_data_start;
|
||||
#endif
|
||||
|
||||
extern uint32_t _bt_bss_start;
|
||||
extern uint32_t _bt_bss_end;
|
||||
extern uint32_t _bt_controller_bss_start;
|
||||
extern uint32_t _bt_controller_bss_end;
|
||||
extern uint32_t _bt_data_start;
|
||||
extern uint32_t _bt_data_end;
|
||||
extern uint32_t _bt_controller_data_start;
|
||||
extern uint32_t _bt_controller_data_end;
|
||||
|
||||
/* Local Function Declaration
|
||||
*********************************************************************
|
||||
*/
|
||||
|
@ -644,6 +650,15 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
|
|||
return ret;
|
||||
}
|
||||
|
||||
#if DEFAULT_BT_LE_50_FEATURE_SUPPORT || DEFAULT_BT_LE_ROLE_CENTROL || DEFAULT_BT_LE_ROLE_OBSERVER
|
||||
extern int esp_ble_rom_func_ptr_init_all(void);
|
||||
esp_ble_rom_func_ptr_init_all();
|
||||
#else
|
||||
ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Init only legacy adv and slave function");
|
||||
extern int esp_ble_rom_func_ptr_init_legacy_adv_and_slave(void);
|
||||
esp_ble_rom_func_ptr_init_legacy_adv_and_slave();
|
||||
#endif
|
||||
|
||||
/* Initialize the function pointers for OS porting */
|
||||
npl_freertos_funcs_init();
|
||||
struct npl_funcs_t *p_npl_funcs = npl_freertos_funcs_get();
|
||||
|
@ -891,9 +906,48 @@ static esp_err_t try_heap_caps_add_region(intptr_t start, intptr_t end)
|
|||
return ret;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
intptr_t start;
|
||||
intptr_t end;
|
||||
const char* name;
|
||||
} bt_area_t;
|
||||
|
||||
static esp_err_t esp_bt_mem_release_area(const bt_area_t *area)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
intptr_t mem_start = area->start;
|
||||
intptr_t mem_end = area->end;
|
||||
if (mem_start != mem_end) {
|
||||
ESP_LOGD(NIMBLE_PORT_LOG_TAG, "Release %s [0x%08x] - [0x%08x], len %d", area->name, mem_start, mem_end, mem_end - mem_start);
|
||||
ret = try_heap_caps_add_region(mem_start, mem_end);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_BT_RELEASE_IRAM
|
||||
static esp_err_t esp_bt_mem_release_areas(const bt_area_t *area1, const bt_area_t *area2)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
if(area1->end == area2->start) {
|
||||
bt_area_t merged_area = {
|
||||
.start = area1->start,
|
||||
.end = area2->end,
|
||||
.name = area1->name
|
||||
};
|
||||
ret = esp_bt_mem_release_area(&merged_area);
|
||||
} else {
|
||||
esp_bt_mem_release_area(area1);
|
||||
ret = esp_bt_mem_release_area(area2);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
esp_err_t esp_bt_mem_release(esp_bt_mode_t mode)
|
||||
{
|
||||
intptr_t mem_start, mem_end;
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
#if CONFIG_BT_RELEASE_IRAM && CONFIG_ESP_SYSTEM_PMP_IDRAM_SPLIT
|
||||
/* Release Bluetooth text section and merge Bluetooth data, bss & text into a large free heap
|
||||
|
@ -902,26 +956,58 @@ esp_err_t esp_bt_mem_release(esp_bt_mode_t mode)
|
|||
* memory into 3 different regions (IRAM, BLE-IRAM, DRAM). So `ESP_SYSTEM_PMP_IDRAM_SPLIT` needs
|
||||
* to be disabled.
|
||||
*/
|
||||
ESP_LOGE(NIMBLE_PORT_LOG_TAG, "`ESP_SYSTEM_PMP_IDRAM_SPLIT` should be disabled!");
|
||||
assert(0);
|
||||
#error "ESP_SYSTEM_PMP_IDRAM_SPLIT should be disabled to allow BT to be released"
|
||||
#endif // CONFIG_BT_RELEASE_IRAM && CONFIG_ESP_SYSTEM_PMP_IDRAM_SPLIT
|
||||
|
||||
if (mode & ESP_BT_MODE_BLE) {
|
||||
#if CONFIG_BT_RELEASE_IRAM
|
||||
mem_start = (intptr_t)MAP_IRAM_TO_DRAM((intptr_t)&_iram_bt_text_start);
|
||||
mem_end = (intptr_t)&_bss_bt_end;
|
||||
#else
|
||||
mem_start = (intptr_t)&_bt_controller_data_start;
|
||||
mem_end = (intptr_t)&_bt_bss_end;
|
||||
#endif // CONFIG_BT_RELEASE_IRAM
|
||||
if (mem_start != mem_end) {
|
||||
ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Release BLE [0x%08x] - [0x%08x], len %d", mem_start,
|
||||
mem_end, mem_end - mem_start);
|
||||
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
|
||||
}
|
||||
if (ble_controller_status != ESP_BT_CONTROLLER_STATUS_IDLE) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
if ((mode & ESP_BT_MODE_BLE) == 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if CONFIG_BT_RELEASE_IRAM
|
||||
bt_area_t merged_region = {
|
||||
.start = (intptr_t)MAP_IRAM_TO_DRAM((intptr_t)&_iram_bt_text_start),
|
||||
.end = (intptr_t)&_bss_bt_end,
|
||||
.name = "BT Text, BSS and Data"
|
||||
};
|
||||
ret = esp_bt_mem_release_area(&merged_region);
|
||||
#else
|
||||
bt_area_t bss = {
|
||||
.start = (intptr_t)&_bt_bss_start,
|
||||
.end = (intptr_t)&_bt_bss_end,
|
||||
.name = "BT BSS",
|
||||
};
|
||||
bt_area_t cont_bss = {
|
||||
.start = (intptr_t)&_bt_controller_bss_start,
|
||||
.end = (intptr_t)&_bt_controller_bss_end,
|
||||
.name = "BT Controller BSS",
|
||||
};
|
||||
bt_area_t data = {
|
||||
.start = (intptr_t)&_bt_data_start,
|
||||
.end = (intptr_t)&_bt_data_end,
|
||||
.name = "BT Data",
|
||||
};
|
||||
bt_area_t cont_data = {
|
||||
.start = (intptr_t)&_bt_controller_data_start,
|
||||
.end = (intptr_t)&_bt_controller_data_end,
|
||||
.name = "BT Controller Data"
|
||||
};
|
||||
|
||||
/* Start by freeing Bluetooth BSS section */
|
||||
if (ret == ESP_OK) {
|
||||
ret = esp_bt_mem_release_areas(&bss, &cont_bss);
|
||||
}
|
||||
|
||||
/* Do the same thing with the Bluetooth data section */
|
||||
if (ret == ESP_OK) {
|
||||
ret = esp_bt_mem_release_areas(&data, &cont_data);
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -46,6 +46,10 @@ extern "C" {
|
|||
#define DEFAULT_BT_LE_50_FEATURE_SUPPORT (0)
|
||||
#endif
|
||||
|
||||
#define DEFAULT_BT_LE_ROLE_OBSERVER MYNEWT_VAL(BLE_ROLE_OBSERVER)
|
||||
#define DEFAULT_BT_LE_ROLE_CENTROL MYNEWT_VAL(BLE_ROLE_CENTRAL)
|
||||
#define DEFAULT_BT_LE_ROLE_PERIPHERAL MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
|
||||
#define DEFAULT_BT_LE_ROLE_BROADCASTER MYNEWT_VAL(BLE_ROLE_BROADCASTER)
|
||||
#else
|
||||
|
||||
#if CONFIG_BT_LE_LL_CFG_FEAT_LE_CODED_PHY
|
||||
|
@ -57,13 +61,13 @@ extern "C" {
|
|||
#if defined(CONFIG_BT_LE_MAX_PERIODIC_ADVERTISER_LIST)
|
||||
#define DEFAULT_BT_LE_MAX_PERIODIC_ADVERTISER_LIST (CONFIG_BT_LE_MAX_PERIODIC_ADVERTISER_LIST)
|
||||
#else
|
||||
#define DEFAULT_BT_LE_MAX_PERIODIC_ADVERTISER_LIST (5)
|
||||
#define DEFAULT_BT_LE_MAX_PERIODIC_ADVERTISER_LIST (0)
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BT_LE_MAX_PERIODIC_SYNCS)
|
||||
#define DEFAULT_BT_LE_MAX_PERIODIC_SYNCS (CONFIG_BT_LE_MAX_PERIODIC_SYNCS)
|
||||
#else
|
||||
#define DEFAULT_BT_LE_MAX_PERIODIC_SYNCS (1)
|
||||
#define DEFAULT_BT_LE_MAX_PERIODIC_SYNCS (0)
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BT_LE_MAX_CONNECTIONS)
|
||||
|
@ -125,6 +129,29 @@ extern "C" {
|
|||
#define DEFAULT_BT_LE_50_FEATURE_SUPPORT (0)
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BT_LE_ROLE_CENTROL_ENABLE)
|
||||
#define DEFAULT_BT_LE_ROLE_CENTROL (1)
|
||||
#else
|
||||
#define DEFAULT_BT_LE_ROLE_CENTROL (0)
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BT_LE_ROLE_PERIPHERAL_ENABLE)
|
||||
#define DEFAULT_BT_LE_ROLE_PERIPHERAL (1)
|
||||
#else
|
||||
#define DEFAULT_BT_LE_ROLE_PERIPHERAL (0)
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BT_LE_ROLE_BROADCASTER_ENABLE)
|
||||
#define DEFAULT_BT_LE_ROLE_BROADCASTER (1)
|
||||
#else
|
||||
#define DEFAULT_BT_LE_ROLE_BROADCASTER (0)
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BT_LE_ROLE_OBSERVER_ENABLE)
|
||||
#define DEFAULT_BT_LE_ROLE_OBSERVER (1)
|
||||
#else
|
||||
#define DEFAULT_BT_LE_ROLE_OBSERVER (0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define DEFAULT_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF CONFIG_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF
|
||||
|
|
|
@ -263,16 +263,12 @@ extern void btdm_cca_feature_enable(void);
|
|||
|
||||
extern uint32_t _bt_bss_start;
|
||||
extern uint32_t _bt_bss_end;
|
||||
extern uint32_t _btdm_bss_start;
|
||||
extern uint32_t _btdm_bss_end;
|
||||
extern uint32_t _nimble_bss_start;
|
||||
extern uint32_t _nimble_bss_end;
|
||||
extern uint32_t _bt_controller_bss_start;
|
||||
extern uint32_t _bt_controller_bss_end;
|
||||
extern uint32_t _bt_data_start;
|
||||
extern uint32_t _bt_data_end;
|
||||
extern uint32_t _btdm_data_start;
|
||||
extern uint32_t _btdm_data_end;
|
||||
extern uint32_t _nimble_data_start;
|
||||
extern uint32_t _nimble_data_end;
|
||||
extern uint32_t _bt_controller_data_start;
|
||||
extern uint32_t _bt_controller_data_end;
|
||||
|
||||
/* Local Function Declare
|
||||
*********************************************************************
|
||||
|
@ -984,145 +980,175 @@ static void btdm_controller_mem_init(void)
|
|||
btdm_controller_rom_data_init();
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_controller_mem_release(esp_bt_mode_t mode)
|
||||
/**
|
||||
* Release two memory areas to the heap. If both areas are consecutive, they will be released as
|
||||
* a single area.
|
||||
*/
|
||||
typedef struct {
|
||||
intptr_t start;
|
||||
intptr_t end;
|
||||
const char* name;
|
||||
} bt_area_t;
|
||||
|
||||
static esp_err_t esp_bt_mem_release_area(const bt_area_t *area)
|
||||
{
|
||||
intptr_t mem_start=(intptr_t) NULL, mem_end=(intptr_t) NULL;
|
||||
esp_err_t ret = ESP_OK;
|
||||
intptr_t mem_start = area->start;
|
||||
intptr_t mem_end = area->end;
|
||||
if (mem_start != mem_end) {
|
||||
ESP_LOGD(BT_LOG_TAG, "Release %s [0x%08x] - [0x%08x], len %d", area->name, mem_start, mem_end, mem_end - mem_start);
|
||||
ret = try_heap_caps_add_region(mem_start, mem_end);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t esp_bt_mem_release_areas(const bt_area_t *area1, const bt_area_t *area2)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
if (area1->end == area2->start) {
|
||||
bt_area_t merged_area = {
|
||||
.start = area1->start,
|
||||
.end = area2->end,
|
||||
.name = area1->name
|
||||
};
|
||||
ret = esp_bt_mem_release_area(&merged_area);
|
||||
} else {
|
||||
esp_bt_mem_release_area(area1);
|
||||
ret = esp_bt_mem_release_area(area2);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_controller_rom_mem_release(esp_bt_mode_t mode)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_IDLE) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (mode & ESP_BT_MODE_BLE) {
|
||||
/* if the addresses of rom btdm .data and .bss are consecutive,
|
||||
they are registered in the system heap as a piece of memory
|
||||
*/
|
||||
if(ets_rom_layout_p->data_end_btdm == ets_rom_layout_p->bss_start_btdm) {
|
||||
mem_start = (intptr_t)ets_rom_layout_p->data_start_btdm;
|
||||
mem_end = (intptr_t)ets_rom_layout_p->bss_end_btdm;
|
||||
if (mem_start != mem_end) {
|
||||
ESP_LOGD(BT_LOG_TAG, "Release rom btdm [0x%08x] - [0x%08x], len %d", mem_start, mem_end, mem_end - mem_start);
|
||||
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
|
||||
}
|
||||
} else {
|
||||
mem_start = (intptr_t)ets_rom_layout_p->bss_start_btdm;
|
||||
mem_end = (intptr_t)ets_rom_layout_p->bss_end_btdm;
|
||||
if (mem_start != mem_end) {
|
||||
ESP_LOGD(BT_LOG_TAG, "Release rom btdm BSS [0x%08x] - [0x%08x], len %d", mem_start, mem_end, mem_end - mem_start);
|
||||
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
|
||||
}
|
||||
|
||||
mem_start = (intptr_t)ets_rom_layout_p->data_start_btdm;
|
||||
mem_end = (intptr_t)ets_rom_layout_p->data_end_btdm;
|
||||
if (mem_start != mem_end) {
|
||||
ESP_LOGD(BT_LOG_TAG, "Release rom btdm Data [0x%08x] - [0x%08x], len %d", mem_start, mem_end, mem_end - mem_start);
|
||||
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
|
||||
}
|
||||
}
|
||||
/* if the addresses of rom interface btdm .data and .bss are consecutive,
|
||||
they are registered in the system heap as a piece of memory
|
||||
*/
|
||||
if(ets_rom_layout_p->data_end_interface_btdm == ets_rom_layout_p->bss_start_interface_btdm) {
|
||||
mem_start = (intptr_t)ets_rom_layout_p->data_start_interface_btdm;
|
||||
mem_end = (intptr_t)ets_rom_layout_p->bss_end_interface_btdm;
|
||||
if (mem_start != mem_end) {
|
||||
ESP_LOGD(BT_LOG_TAG, "Release rom interface btdm [0x%08x] - [0x%08x], len %d", mem_start, mem_end, mem_end - mem_start);
|
||||
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
|
||||
}
|
||||
} else {
|
||||
mem_start = (intptr_t)ets_rom_layout_p->data_start_interface_btdm;
|
||||
mem_end = (intptr_t)ets_rom_layout_p->data_end_interface_btdm;
|
||||
if (mem_start != mem_end) {
|
||||
ESP_LOGD(BT_LOG_TAG, "Release rom interface btdm Data [0x%08x] - [0x%08x], len %d", mem_start, mem_end, mem_end - mem_start);
|
||||
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
|
||||
}
|
||||
|
||||
mem_start = (intptr_t)ets_rom_layout_p->bss_start_interface_btdm;
|
||||
mem_end = (intptr_t)ets_rom_layout_p->bss_end_interface_btdm;
|
||||
if (mem_start != mem_end) {
|
||||
ESP_LOGD(BT_LOG_TAG, "Release rom interface btdm BSS [0x%08x] - [0x%08x], len %d", mem_start, mem_end, mem_end - mem_start);
|
||||
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
|
||||
}
|
||||
}
|
||||
bt_area_t rom_btdm_data = {
|
||||
.start = (intptr_t) ets_rom_layout_p->data_start_btdm,
|
||||
.end = (intptr_t) ets_rom_layout_p->data_end_btdm,
|
||||
.name = "ROM btdm data",
|
||||
};
|
||||
bt_area_t rom_btdm_bss = {
|
||||
.start = (intptr_t)ets_rom_layout_p->bss_start_btdm,
|
||||
.end = (intptr_t)ets_rom_layout_p->bss_end_btdm,
|
||||
.name = "ROM btdm BSS",
|
||||
};
|
||||
bt_area_t rom_btdm_inter_data = {
|
||||
.start = (intptr_t) ets_rom_layout_p->data_start_interface_btdm,
|
||||
.end = (intptr_t) ets_rom_layout_p->data_end_interface_btdm,
|
||||
.name = "ROM interface btdm data",
|
||||
};
|
||||
bt_area_t rom_btdm_inter_bss = {
|
||||
.start = (intptr_t)ets_rom_layout_p->bss_start_interface_btdm,
|
||||
.end = (intptr_t)ets_rom_layout_p->bss_end_interface_btdm,
|
||||
.name = "ROM interface btdm BSS",
|
||||
};
|
||||
|
||||
if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_IDLE) {
|
||||
ret = ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
return ESP_OK;
|
||||
|
||||
if (mode & ESP_BT_MODE_BLE) {
|
||||
/* Free BTDM memory used by the ROM */
|
||||
if (ret == ESP_OK) {
|
||||
ret = esp_bt_mem_release_areas(&rom_btdm_data, &rom_btdm_bss);
|
||||
}
|
||||
|
||||
if (ret == ESP_OK) {
|
||||
ret = esp_bt_mem_release_areas(&rom_btdm_inter_data, &rom_btdm_inter_bss);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_controller_mem_release(esp_bt_mode_t mode)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_IDLE) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
bt_area_t cont_bss = {
|
||||
.start = (intptr_t)&_bt_controller_bss_start,
|
||||
.end = (intptr_t)&_bt_controller_bss_end,
|
||||
.name = "BT Controller BSS",
|
||||
};
|
||||
|
||||
bt_area_t cont_data = {
|
||||
.start = (intptr_t)&_bt_controller_data_start,
|
||||
.end = (intptr_t)&_bt_controller_data_end,
|
||||
.name = "BT Controller Data"
|
||||
};
|
||||
|
||||
if (mode & ESP_BT_MODE_BLE) {
|
||||
/* free data and BSS section for libbtdm_app.a */
|
||||
if (ret == ESP_OK) {
|
||||
ret = esp_bt_mem_release_areas(&cont_data, &cont_bss);
|
||||
}
|
||||
/* free data and BSS section for Bluetooth controller ROM code */
|
||||
if (ret == ESP_OK) {
|
||||
ret = esp_bt_controller_rom_mem_release(mode);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_mem_release(esp_bt_mode_t mode)
|
||||
{
|
||||
int ret;
|
||||
intptr_t mem_start, mem_end;
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
ret = esp_bt_controller_mem_release(mode);
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_IDLE) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
bt_area_t bss = {
|
||||
.start = (intptr_t)&_bt_bss_start,
|
||||
.end = (intptr_t)&_bt_bss_end,
|
||||
.name = "BT BSS",
|
||||
};
|
||||
bt_area_t cont_bss = {
|
||||
.start = (intptr_t)&_bt_controller_bss_start,
|
||||
.end = (intptr_t)&_bt_controller_bss_end,
|
||||
.name = "BT Controller BSS",
|
||||
};
|
||||
bt_area_t data = {
|
||||
.start = (intptr_t)&_bt_data_start,
|
||||
.end = (intptr_t)&_bt_data_end,
|
||||
.name = "BT Data",
|
||||
};
|
||||
bt_area_t cont_data = {
|
||||
.start = (intptr_t)&_bt_controller_data_start,
|
||||
.end = (intptr_t)&_bt_controller_data_end,
|
||||
.name = "BT Controller Data"
|
||||
};
|
||||
|
||||
if (mode & ESP_BT_MODE_BLE) {
|
||||
/* if the addresses of btdm .bss and bt .bss are consecutive,
|
||||
they are registered in the system heap as a piece of memory
|
||||
*/
|
||||
if(_bt_bss_end == _btdm_bss_start) {
|
||||
mem_start = (intptr_t)&_bt_bss_start;
|
||||
mem_end = (intptr_t)&_btdm_bss_end;
|
||||
if (mem_start != mem_end) {
|
||||
ESP_LOGD(BT_LOG_TAG, "Release BSS [0x%08x] - [0x%08x], len %d", mem_start, mem_end, mem_end - mem_start);
|
||||
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
|
||||
}
|
||||
} else {
|
||||
mem_start = (intptr_t)&_bt_bss_start;
|
||||
mem_end = (intptr_t)&_bt_bss_end;
|
||||
if (mem_start != mem_end) {
|
||||
ESP_LOGD(BT_LOG_TAG, "Release BT BSS [0x%08x] - [0x%08x], len %d", mem_start, mem_end, mem_end - mem_start);
|
||||
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
|
||||
}
|
||||
|
||||
mem_start = (intptr_t)&_btdm_bss_start;
|
||||
mem_end = (intptr_t)&_btdm_bss_end;
|
||||
if (mem_start != mem_end) {
|
||||
ESP_LOGD(BT_LOG_TAG, "Release BTDM BSS [0x%08x] - [0x%08x], len %d", mem_start, mem_end, mem_end - mem_start);
|
||||
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
|
||||
}
|
||||
}
|
||||
/* if the addresses of btdm .data and bt .data are consecutive,
|
||||
they are registered in the system heap as a piece of memory
|
||||
*/
|
||||
if(_bt_data_end == _btdm_data_start) {
|
||||
mem_start = (intptr_t)&_bt_data_start;
|
||||
mem_end = (intptr_t)&_btdm_data_end;
|
||||
if (mem_start != mem_end) {
|
||||
ESP_LOGD(BT_LOG_TAG, "Release data [0x%08x] - [0x%08x], len %d", mem_start, mem_end, mem_end - mem_start);
|
||||
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
|
||||
}
|
||||
} else {
|
||||
mem_start = (intptr_t)&_bt_data_start;
|
||||
mem_end = (intptr_t)&_bt_data_end;
|
||||
if (mem_start != mem_end) {
|
||||
ESP_LOGD(BT_LOG_TAG, "Release BT Data [0x%08x] - [0x%08x], len %d", mem_start, mem_end, mem_end - mem_start);
|
||||
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
|
||||
}
|
||||
|
||||
mem_start = (intptr_t)&_btdm_data_start;
|
||||
mem_end = (intptr_t)&_btdm_data_end;
|
||||
if (mem_start != mem_end) {
|
||||
ESP_LOGD(BT_LOG_TAG, "Release BTDM Data [0x%08x] - [0x%08x], len %d", mem_start, mem_end, mem_end - mem_start);
|
||||
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
|
||||
}
|
||||
/* Start by freeing Bluetooth BSS section */
|
||||
if (ret == ESP_OK) {
|
||||
ret = esp_bt_mem_release_areas(&bss, &cont_bss);
|
||||
}
|
||||
|
||||
mem_start = (intptr_t)&_nimble_bss_start;
|
||||
mem_end = (intptr_t)&_nimble_bss_end;
|
||||
if (mem_start != mem_end) {
|
||||
ESP_LOGD(BT_LOG_TAG, "Release NimBLE BSS [0x%08x] - [0x%08x], len %d", mem_start, mem_end, mem_end - mem_start);
|
||||
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
|
||||
/* Do the same thing with the Bluetooth data section */
|
||||
if (ret == ESP_OK) {
|
||||
ret = esp_bt_mem_release_areas(&data, &cont_data);
|
||||
}
|
||||
mem_start = (intptr_t)&_nimble_data_start;
|
||||
mem_end = (intptr_t)&_nimble_data_end;
|
||||
if (mem_start != mem_end) {
|
||||
ESP_LOGD(BT_LOG_TAG, "Release NimBLE Data [0x%08x] - [0x%08x], len %d", mem_start, mem_end, mem_end - mem_start);
|
||||
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
|
||||
|
||||
/* free data and BSS section for Bluetooth controller ROM code */
|
||||
if (ret == ESP_OK) {
|
||||
ret = esp_bt_controller_rom_mem_release(mode);
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t try_heap_caps_add_region(intptr_t start, intptr_t end)
|
||||
|
|
|
@ -512,9 +512,10 @@ IRAM_ATTR void controller_wakeup_cb(void *arg)
|
|||
}
|
||||
|
||||
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
|
||||
static esp_err_t sleep_modem_ble_mac_modem_state_init(uint8_t extra)
|
||||
static esp_err_t sleep_modem_ble_mac_retention_init(void *arg)
|
||||
{
|
||||
uint8_t size;
|
||||
int extra = *(int *)arg;
|
||||
const sleep_retention_entries_config_t *ble_mac_modem_config = esp_ble_mac_retention_link_get(&size, extra);
|
||||
esp_err_t err = sleep_retention_entries_create(ble_mac_modem_config, size, REGDMA_LINK_PRI_5, SLEEP_RETENTION_MODULE_BLE_MAC);
|
||||
if (err == ESP_OK) {
|
||||
|
@ -523,9 +524,27 @@ static esp_err_t sleep_modem_ble_mac_modem_state_init(uint8_t extra)
|
|||
return err;
|
||||
}
|
||||
|
||||
static esp_err_t sleep_modem_ble_mac_modem_state_init(uint8_t extra)
|
||||
{
|
||||
int retention_args = extra;
|
||||
sleep_retention_module_init_param_t init_param = {
|
||||
.cbs = { .create = { .handle = sleep_modem_ble_mac_retention_init, .arg = &retention_args } },
|
||||
.depends = BIT(SLEEP_RETENTION_MODULE_BT_BB)
|
||||
};
|
||||
esp_err_t err = sleep_retention_module_init(SLEEP_RETENTION_MODULE_BLE_MAC, &init_param);
|
||||
if (err == ESP_OK) {
|
||||
err = sleep_retention_module_allocate(SLEEP_RETENTION_MODULE_BLE_MAC);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static void sleep_modem_ble_mac_modem_state_deinit(void)
|
||||
{
|
||||
sleep_retention_entries_destroy(SLEEP_RETENTION_MODULE_BLE_MAC);
|
||||
esp_err_t err = sleep_retention_module_free(SLEEP_RETENTION_MODULE_BLE_MAC);
|
||||
if (err == ESP_OK) {
|
||||
err = sleep_retention_module_deinit(SLEEP_RETENTION_MODULE_BLE_MAC);
|
||||
assert(err == ESP_OK);
|
||||
}
|
||||
}
|
||||
|
||||
void sleep_modem_light_sleep_overhead_set(uint32_t overhead)
|
||||
|
@ -984,70 +1003,86 @@ static esp_err_t try_heap_caps_add_region(intptr_t start, intptr_t end)
|
|||
return ret;
|
||||
}
|
||||
|
||||
|
||||
typedef struct {
|
||||
intptr_t start;
|
||||
intptr_t end;
|
||||
const char* name;
|
||||
} bt_area_t;
|
||||
|
||||
static esp_err_t esp_bt_mem_release_area(const bt_area_t *area)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
intptr_t mem_start = area->start;
|
||||
intptr_t mem_end = area->end;
|
||||
if (mem_start != mem_end) {
|
||||
ESP_LOGD(NIMBLE_PORT_LOG_TAG, "Release %s [0x%08x] - [0x%08x], len %d", area->name, mem_start, mem_end, mem_end - mem_start);
|
||||
ret = try_heap_caps_add_region(mem_start, mem_end);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t esp_bt_mem_release_areas(const bt_area_t *area1, const bt_area_t *area2)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
if (area1->end == area2->start) {
|
||||
bt_area_t merged_area = {
|
||||
.start = area1->start,
|
||||
.end = area2->end,
|
||||
.name = area1->name
|
||||
};
|
||||
ret = esp_bt_mem_release_area(&merged_area);
|
||||
} else {
|
||||
esp_bt_mem_release_area(area1);
|
||||
ret = esp_bt_mem_release_area(area2);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_mem_release(esp_bt_mode_t mode)
|
||||
{
|
||||
intptr_t mem_start, mem_end;
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
if (ble_controller_status != ESP_BT_CONTROLLER_STATUS_IDLE) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
bt_area_t bss = {
|
||||
.start = (intptr_t)&_bt_bss_start,
|
||||
.end = (intptr_t)&_bt_bss_end,
|
||||
.name = "BT BSS",
|
||||
};
|
||||
bt_area_t cont_bss = {
|
||||
.start = (intptr_t)&_bt_controller_bss_start,
|
||||
.end = (intptr_t)&_bt_controller_bss_end,
|
||||
.name = "BT Controller BSS",
|
||||
};
|
||||
bt_area_t data = {
|
||||
.start = (intptr_t)&_bt_data_start,
|
||||
.end = (intptr_t)&_bt_data_end,
|
||||
.name = "BT Data",
|
||||
};
|
||||
bt_area_t cont_data = {
|
||||
.start = (intptr_t)&_bt_controller_data_start,
|
||||
.end = (intptr_t)&_bt_controller_data_end,
|
||||
.name = "BT Controller Data"
|
||||
};
|
||||
|
||||
if (mode & ESP_BT_MODE_BLE) {
|
||||
/* If the addresses of btdm .bss and bt .bss are consecutive,
|
||||
* they are registered in the system heap as a piece of memory
|
||||
*/
|
||||
if(_bt_bss_end == _bt_controller_bss_start) {
|
||||
mem_start = (intptr_t)&_bt_bss_start;
|
||||
mem_end = (intptr_t)&_bt_controller_bss_end;
|
||||
if (mem_start != mem_end) {
|
||||
ESP_LOGD(NIMBLE_PORT_LOG_TAG, "Release BSS [0x%08x] - [0x%08x], len %d",
|
||||
mem_start, mem_end, mem_end - mem_start);
|
||||
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
|
||||
}
|
||||
} else {
|
||||
mem_start = (intptr_t)&_bt_bss_start;
|
||||
mem_end = (intptr_t)&_bt_bss_end;
|
||||
if (mem_start != mem_end) {
|
||||
ESP_LOGD(NIMBLE_PORT_LOG_TAG, "Release BT BSS [0x%08x] - [0x%08x], len %d",
|
||||
mem_start, mem_end, mem_end - mem_start);
|
||||
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
|
||||
}
|
||||
|
||||
mem_start = (intptr_t)&_bt_controller_bss_start;
|
||||
mem_end = (intptr_t)&_bt_controller_bss_end;
|
||||
if (mem_start != mem_end) {
|
||||
ESP_LOGD(NIMBLE_PORT_LOG_TAG, "Release Controller BSS [0x%08x] - [0x%08x], len %d",
|
||||
mem_start, mem_end, mem_end - mem_start);
|
||||
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
|
||||
}
|
||||
/* Start by freeing Bluetooth BSS section */
|
||||
if (ret == ESP_OK) {
|
||||
ret = esp_bt_mem_release_areas(&bss, &cont_bss);
|
||||
}
|
||||
/* If the addresses of btdm .data and bt .data are consecutive,
|
||||
* they are registered in the system heap as a piece of memory
|
||||
*/
|
||||
if(_bt_data_end == _bt_controller_data_start) {
|
||||
mem_start = (intptr_t)&_bt_data_start;
|
||||
mem_end = (intptr_t)&_bt_controller_data_end;
|
||||
if (mem_start != mem_end) {
|
||||
ESP_LOGD(NIMBLE_PORT_LOG_TAG, "Release data [0x%08x] - [0x%08x], len %d",
|
||||
mem_start, mem_end, mem_end - mem_start);
|
||||
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
|
||||
}
|
||||
} else {
|
||||
mem_start = (intptr_t)&_bt_data_start;
|
||||
mem_end = (intptr_t)&_bt_data_end;
|
||||
if (mem_start != mem_end) {
|
||||
ESP_LOGD(NIMBLE_PORT_LOG_TAG, "Release BT Data [0x%08x] - [0x%08x], len %d",
|
||||
mem_start, mem_end, mem_end - mem_start);
|
||||
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
|
||||
}
|
||||
|
||||
mem_start = (intptr_t)&_bt_controller_data_start;
|
||||
mem_end = (intptr_t)&_bt_controller_data_end;
|
||||
if (mem_start != mem_end) {
|
||||
ESP_LOGD(NIMBLE_PORT_LOG_TAG, "Release Controller Data [0x%08x] - [0x%08x], len %d",
|
||||
mem_start, mem_end, mem_end - mem_start);
|
||||
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
|
||||
}
|
||||
/* Do the same thing with the Bluetooth data section */
|
||||
if (ret == ESP_OK) {
|
||||
ret = esp_bt_mem_release_areas(&data, &cont_data);
|
||||
}
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -501,9 +501,10 @@ IRAM_ATTR void controller_wakeup_cb(void *arg)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_FREERTOS_USE_TICKLESS_IDLE
|
||||
static esp_err_t sleep_modem_ble_mac_modem_state_init(uint8_t extra)
|
||||
static esp_err_t sleep_modem_ble_mac_retention_init(void *arg)
|
||||
{
|
||||
uint8_t size;
|
||||
int extra = *(int *)arg;
|
||||
const sleep_retention_entries_config_t *ble_mac_modem_config = esp_ble_mac_retention_link_get(&size, extra);
|
||||
esp_err_t err = sleep_retention_entries_create(ble_mac_modem_config, size, REGDMA_LINK_PRI_5, SLEEP_RETENTION_MODULE_BLE_MAC);
|
||||
if (err == ESP_OK) {
|
||||
|
@ -512,9 +513,27 @@ static esp_err_t sleep_modem_ble_mac_modem_state_init(uint8_t extra)
|
|||
return err;
|
||||
}
|
||||
|
||||
static esp_err_t sleep_modem_ble_mac_modem_state_init(uint8_t extra)
|
||||
{
|
||||
int retention_args = extra;
|
||||
sleep_retention_module_init_param_t init_param = {
|
||||
.cbs = { .create = { .handle = sleep_modem_ble_mac_retention_init, .arg = &retention_args } },
|
||||
.depends = BIT(SLEEP_RETENTION_MODULE_BT_BB)
|
||||
};
|
||||
esp_err_t err = sleep_retention_module_init(SLEEP_RETENTION_MODULE_BLE_MAC, &init_param);
|
||||
if (err == ESP_OK) {
|
||||
err = sleep_retention_module_allocate(SLEEP_RETENTION_MODULE_BLE_MAC);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static void sleep_modem_ble_mac_modem_state_deinit(void)
|
||||
{
|
||||
sleep_retention_entries_destroy(SLEEP_RETENTION_MODULE_BLE_MAC);
|
||||
esp_err_t err = sleep_retention_module_free(SLEEP_RETENTION_MODULE_BLE_MAC);
|
||||
if (err == ESP_OK) {
|
||||
err = sleep_retention_module_deinit(SLEEP_RETENTION_MODULE_BLE_MAC);
|
||||
assert(err == ESP_OK);
|
||||
}
|
||||
}
|
||||
|
||||
void sleep_modem_light_sleep_overhead_set(uint32_t overhead)
|
||||
|
@ -957,70 +976,86 @@ static esp_err_t try_heap_caps_add_region(intptr_t start, intptr_t end)
|
|||
return ret;
|
||||
}
|
||||
|
||||
|
||||
typedef struct {
|
||||
intptr_t start;
|
||||
intptr_t end;
|
||||
const char* name;
|
||||
} bt_area_t;
|
||||
|
||||
static esp_err_t esp_bt_mem_release_area(const bt_area_t *area)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
intptr_t mem_start = area->start;
|
||||
intptr_t mem_end = area->end;
|
||||
if (mem_start != mem_end) {
|
||||
ESP_LOGD(NIMBLE_PORT_LOG_TAG, "Release %s [0x%08x] - [0x%08x], len %d", area->name, mem_start, mem_end, mem_end - mem_start);
|
||||
ret = try_heap_caps_add_region(mem_start, mem_end);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t esp_bt_mem_release_areas(const bt_area_t *area1, const bt_area_t *area2)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
if (area1->end == area2->start) {
|
||||
bt_area_t merged_area = {
|
||||
.start = area1->start,
|
||||
.end = area2->end,
|
||||
.name = area1->name
|
||||
};
|
||||
ret = esp_bt_mem_release_area(&merged_area);
|
||||
} else {
|
||||
esp_bt_mem_release_area(area1);
|
||||
ret = esp_bt_mem_release_area(area2);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_mem_release(esp_bt_mode_t mode)
|
||||
{
|
||||
intptr_t mem_start, mem_end;
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
if (ble_controller_status != ESP_BT_CONTROLLER_STATUS_IDLE) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
bt_area_t bss = {
|
||||
.start = (intptr_t)&_bt_bss_start,
|
||||
.end = (intptr_t)&_bt_bss_end,
|
||||
.name = "BT BSS",
|
||||
};
|
||||
bt_area_t cont_bss = {
|
||||
.start = (intptr_t)&_bt_controller_bss_start,
|
||||
.end = (intptr_t)&_bt_controller_bss_end,
|
||||
.name = "BT Controller BSS",
|
||||
};
|
||||
bt_area_t data = {
|
||||
.start = (intptr_t)&_bt_data_start,
|
||||
.end = (intptr_t)&_bt_data_end,
|
||||
.name = "BT Data",
|
||||
};
|
||||
bt_area_t cont_data = {
|
||||
.start = (intptr_t)&_bt_controller_data_start,
|
||||
.end = (intptr_t)&_bt_controller_data_end,
|
||||
.name = "BT Controller Data"
|
||||
};
|
||||
|
||||
if (mode & ESP_BT_MODE_BLE) {
|
||||
/* If the addresses of btdm .bss and bt .bss are consecutive,
|
||||
* they are registered in the system heap as a piece of memory
|
||||
*/
|
||||
if(_bt_bss_end == _bt_controller_bss_start) {
|
||||
mem_start = (intptr_t)&_bt_bss_start;
|
||||
mem_end = (intptr_t)&_bt_controller_bss_end;
|
||||
if (mem_start != mem_end) {
|
||||
ESP_LOGD(NIMBLE_PORT_LOG_TAG, "Release BSS [0x%08x] - [0x%08x], len %d",
|
||||
mem_start, mem_end, mem_end - mem_start);
|
||||
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
|
||||
}
|
||||
} else {
|
||||
mem_start = (intptr_t)&_bt_bss_start;
|
||||
mem_end = (intptr_t)&_bt_bss_end;
|
||||
if (mem_start != mem_end) {
|
||||
ESP_LOGD(NIMBLE_PORT_LOG_TAG, "Release BT BSS [0x%08x] - [0x%08x], len %d",
|
||||
mem_start, mem_end, mem_end - mem_start);
|
||||
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
|
||||
}
|
||||
|
||||
mem_start = (intptr_t)&_bt_controller_bss_start;
|
||||
mem_end = (intptr_t)&_bt_controller_bss_end;
|
||||
if (mem_start != mem_end) {
|
||||
ESP_LOGD(NIMBLE_PORT_LOG_TAG, "Release Controller BSS [0x%08x] - [0x%08x], len %d",
|
||||
mem_start, mem_end, mem_end - mem_start);
|
||||
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
|
||||
}
|
||||
/* Start by freeing Bluetooth BSS section */
|
||||
if (ret == ESP_OK) {
|
||||
ret = esp_bt_mem_release_areas(&bss, &cont_bss);
|
||||
}
|
||||
/* If the addresses of btdm .data and bt .data are consecutive,
|
||||
* they are registered in the system heap as a piece of memory
|
||||
*/
|
||||
if(_bt_data_end == _bt_controller_data_start) {
|
||||
mem_start = (intptr_t)&_bt_data_start;
|
||||
mem_end = (intptr_t)&_bt_controller_data_end;
|
||||
if (mem_start != mem_end) {
|
||||
ESP_LOGD(NIMBLE_PORT_LOG_TAG, "Release data [0x%08x] - [0x%08x], len %d",
|
||||
mem_start, mem_end, mem_end - mem_start);
|
||||
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
|
||||
}
|
||||
} else {
|
||||
mem_start = (intptr_t)&_bt_data_start;
|
||||
mem_end = (intptr_t)&_bt_data_end;
|
||||
if (mem_start != mem_end) {
|
||||
ESP_LOGD(NIMBLE_PORT_LOG_TAG, "Release BT Data [0x%08x] - [0x%08x], len %d",
|
||||
mem_start, mem_end, mem_end - mem_start);
|
||||
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
|
||||
}
|
||||
|
||||
mem_start = (intptr_t)&_bt_controller_data_start;
|
||||
mem_end = (intptr_t)&_bt_controller_data_end;
|
||||
if (mem_start != mem_end) {
|
||||
ESP_LOGD(NIMBLE_PORT_LOG_TAG, "Release Controller Data [0x%08x] - [0x%08x], len %d",
|
||||
mem_start, mem_end, mem_end - mem_start);
|
||||
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
|
||||
}
|
||||
/* Do the same thing with the Bluetooth data section */
|
||||
if (ret == ESP_OK) {
|
||||
ret = esp_bt_mem_release_areas(&data, &cont_data);
|
||||
}
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 05fa7ad7edc0fda255e353880bbd38263bc08b9b
|
||||
Subproject commit b9a902c3551ef4a2032b6662a4cbb018125ddfda
|
|
@ -144,6 +144,13 @@ config BT_HID_DEVICE_ENABLED
|
|||
help
|
||||
This enables the BT HID Device
|
||||
|
||||
config BT_HID_DEVICE_TASK_SIZE
|
||||
int "Bluetooth HID event (callback to application) task stack size"
|
||||
depends on BT_HID_DEVICE_ENABLED
|
||||
default 4096
|
||||
help
|
||||
This selects the esp_hid task size
|
||||
|
||||
config BT_BLE_ENABLED
|
||||
bool "Bluetooth Low Energy"
|
||||
depends on BT_BLUEDROID_ENABLED
|
||||
|
|
|
@ -299,6 +299,7 @@ esp_err_t esp_ble_gap_config_local_icon (uint16_t icon)
|
|||
case ESP_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION_AND_NAV:
|
||||
case ESP_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION_POD:
|
||||
case ESP_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION_POD_AND_NAV:
|
||||
case ESP_BLE_APPEARANCE_STANDALONE_SPEAKER:
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GAP_BLE;
|
||||
msg.act = BTC_GAP_BLE_ACT_CONFIG_LOCAL_ICON;
|
||||
|
|
|
@ -104,6 +104,7 @@ typedef uint8_t esp_ble_auth_req_t; /*!< combination of the above bit
|
|||
#define ESP_BLE_APPEARANCE_CYCLING_CADENCE 0x0483 /*!< relate to BTM_BLE_APPEARANCE_CYCLING_CADENCE in stack/btm_ble_api.h */
|
||||
#define ESP_BLE_APPEARANCE_CYCLING_POWER 0x0484 /*!< relate to BTM_BLE_APPEARANCE_CYCLING_POWER in stack/btm_ble_api.h */
|
||||
#define ESP_BLE_APPEARANCE_CYCLING_SPEED_CADENCE 0x0485 /*!< relate to BTM_BLE_APPEARANCE_CYCLING_SPEED_CADENCE in stack/btm_ble_api.h */
|
||||
#define ESP_BLE_APPEARANCE_STANDALONE_SPEAKER 0x0841 /*!< relate to BTM_BLE_APPEARANCE_STANDALONE_SPEAKER in stack/btm_ble_api.h */
|
||||
#define ESP_BLE_APPEARANCE_GENERIC_PULSE_OXIMETER 0x0C40 /*!< relate to BTM_BLE_APPEARANCE_GENERIC_PULSE_OXIMETER in stack/btm_ble_api.h */
|
||||
#define ESP_BLE_APPEARANCE_PULSE_OXIMETER_FINGERTIP 0x0C41 /*!< relate to BTM_BLE_APPEARANCE_PULSE_OXIMETER_FINGERTIP in stack/btm_ble_api.h */
|
||||
#define ESP_BLE_APPEARANCE_PULSE_OXIMETER_WRIST 0x0C42 /*!< relate to BTM_BLE_APPEARANCE_PULSE_OXIMETER_WRIST in stack/btm_ble_api.h */
|
||||
|
|
|
@ -98,6 +98,12 @@ typedef struct {
|
|||
uint8_t subclass; /*!< HID device subclass */
|
||||
uint8_t *desc_list; /*!< HID descriptor list */
|
||||
int desc_list_len; /*!< size in bytes of HID descriptor list */
|
||||
|
||||
// DID Profile SDP
|
||||
uint16_t vendor_id; /*!< HID Vendor ID */
|
||||
uint16_t product_id; /*!< HID Product ID */
|
||||
uint16_t version; /*!< HID Product Version */
|
||||
uint8_t vendor_id_source; /*!< HID Country Code */
|
||||
} esp_hidd_app_param_t;
|
||||
|
||||
/**
|
||||
|
|
|
@ -175,6 +175,16 @@ void bta_hd_register_act(tBTA_HD_DATA *p_data)
|
|||
p_app_data->subclass, p_app_data->d_len, p_app_data->d_data);
|
||||
bta_sys_add_uuid(UUID_SERVCLASS_HUMAN_INTERFACE);
|
||||
|
||||
// Set DID Profile SDP Record
|
||||
tBTA_DI_RECORD bqb_device_info;
|
||||
bqb_device_info.vendor = p_app_data->vendor_id;
|
||||
bqb_device_info.vendor_id_source = p_app_data->vendor_id_source;
|
||||
bqb_device_info.product = p_app_data->product_id;
|
||||
bqb_device_info.version = p_app_data->version;
|
||||
bqb_device_info.primary_record = TRUE;
|
||||
|
||||
BTA_DmSetLocalDiRecord(&bqb_device_info, &bta_hd_cb.sdp_handle);
|
||||
|
||||
HID_DevSetIncomingQos(p_app_data->in_qos.service_type, p_app_data->in_qos.token_rate,
|
||||
p_app_data->in_qos.token_bucket_size, p_app_data->in_qos.peak_bandwidth,
|
||||
p_app_data->in_qos.access_latency, p_app_data->in_qos.delay_variation);
|
||||
|
|
|
@ -114,6 +114,13 @@ extern void BTA_HdRegisterApp(tBTA_HD_APP_INFO *p_app_info, tBTA_HD_QOS_INFO *p_
|
|||
p_buf->subclass = p_app_info->subclass;
|
||||
p_buf->d_len = p_app_info->descriptor.dl_len;
|
||||
memcpy(p_buf->d_data, p_app_info->descriptor.dsc_list, p_app_info->descriptor.dl_len);
|
||||
|
||||
// copy DID profile SDP info
|
||||
p_buf->vendor_id = p_app_info->vendor_id;
|
||||
p_buf->product_id = p_app_info->product_id;
|
||||
p_buf->version = p_app_info->version;
|
||||
p_buf->vendor_id_source = p_app_info->vendor_id_source;
|
||||
|
||||
// copy qos data as-is
|
||||
memcpy(&p_buf->in_qos, p_in_qos, sizeof(tBTA_HD_QOS_INFO));
|
||||
memcpy(&p_buf->out_qos, p_out_qos, sizeof(tBTA_HD_QOS_INFO));
|
||||
|
|
|
@ -75,6 +75,13 @@ typedef struct {
|
|||
uint8_t subclass;
|
||||
uint16_t d_len;
|
||||
uint8_t d_data[BTA_HD_APP_DESCRIPTOR_LEN];
|
||||
|
||||
// DID SDP Information (Device Information)
|
||||
uint16_t vendor_id;
|
||||
uint16_t product_id;
|
||||
uint16_t version;
|
||||
uint8_t vendor_id_source;
|
||||
|
||||
tBTA_HD_QOS_INFO in_qos;
|
||||
tBTA_HD_QOS_INFO out_qos;
|
||||
} tBTA_HD_REGISTER_APP;
|
||||
|
|
|
@ -276,7 +276,7 @@ static void bta_hh_di_sdp_cback(UINT16 result)
|
|||
bta_hh_update_di_info(p_cb, di_rec.rec.vendor, di_rec.rec.product, di_rec.rec.version, 0);
|
||||
}
|
||||
|
||||
} else { /* no DI recrod available */
|
||||
} else { /* no DI record available */
|
||||
bta_hh_update_di_info(p_cb, BTA_HH_VENDOR_ID_INVALID, 0, 0, 0);
|
||||
}
|
||||
|
||||
|
@ -358,7 +358,7 @@ void bta_hh_start_sdp(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
|
|||
|
||||
return;
|
||||
}
|
||||
/* GetSDPRecord. at one time only one SDP precedure can be active */
|
||||
/* GetSDPRecord. at one time only one SDP procedure can be active */
|
||||
else if (!bta_hh_cb.p_disc_db) {
|
||||
bta_hh_cb.p_disc_db = (tSDP_DISCOVERY_DB *) osi_malloc(p_bta_hh_cfg->sdp_db_size);
|
||||
|
||||
|
@ -429,6 +429,7 @@ void bta_hh_sdp_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
|
|||
APPL_TRACE_DEBUG ("bta_hh_sdp_cmpl: HID_HostOpenDev failed: \
|
||||
Status 0x%2X", ret);
|
||||
#endif
|
||||
conn_dat.is_orig = HID_HostConnectOrig(p_cb->hid_handle);
|
||||
/* open fail, remove device from management device list */
|
||||
HID_HostRemoveDev( p_cb->hid_handle);
|
||||
status = BTA_HH_ERR;
|
||||
|
@ -452,8 +453,6 @@ void bta_hh_sdp_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
|
|||
HID_HostRemoveDev( p_cb->incoming_hid_handle);
|
||||
}
|
||||
conn_dat.status = status;
|
||||
/* check if host initiate the connection*/
|
||||
conn_dat.is_orig = !p_cb->incoming_conn;
|
||||
(* bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH *)&conn_dat);
|
||||
|
||||
/* move state machine W4_CONN ->IDLE */
|
||||
|
@ -523,8 +522,7 @@ void bta_hh_open_cmpl_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
|
|||
|
||||
memset((void *)&conn, 0, sizeof (tBTA_HH_CONN));
|
||||
conn.handle = dev_handle;
|
||||
/* check if host initiate the connection*/
|
||||
conn.is_orig = !p_cb->incoming_conn;
|
||||
conn.is_orig = HID_HostConnectOrig(dev_handle);
|
||||
bdcpy(conn.bda, p_cb->addr);
|
||||
|
||||
/* increase connection number */
|
||||
|
@ -596,7 +594,7 @@ void bta_hh_open_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
|
|||
if (p_cb->app_id != 0) {
|
||||
bta_hh_sm_execute(p_cb, BTA_HH_OPEN_CMPL_EVT, p_data);
|
||||
} else
|
||||
/* app_id == 0 indicates an incoming conenction request arrives without SDP
|
||||
/* app_id == 0 indicates an incoming connection request arrives without SDP
|
||||
performed, do it first */
|
||||
{
|
||||
/* store the handle here in case sdp fails - need to disconnect */
|
||||
|
@ -637,7 +635,7 @@ void bta_hh_data_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
|
|||
**
|
||||
** Function bta_hh_handsk_act
|
||||
**
|
||||
** Description HID Host process a handshake acknoledgement.
|
||||
** Description HID Host process a handshake acknowledgement.
|
||||
**
|
||||
**
|
||||
** Returns void
|
||||
|
@ -674,7 +672,7 @@ void bta_hh_handsk_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
|
|||
p_cb->w4_evt = 0;
|
||||
break;
|
||||
|
||||
/* acknoledgement from HID device for SET_ transaction */
|
||||
/* acknowledgement from HID device for SET_ transaction */
|
||||
case BTA_HH_SET_RPT_EVT:
|
||||
case BTA_HH_SET_PROTO_EVT:
|
||||
case BTA_HH_SET_IDLE_EVT :
|
||||
|
@ -693,8 +691,7 @@ void bta_hh_handsk_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
|
|||
case BTA_HH_OPEN_EVT:
|
||||
conn.status = p_data->hid_cback.data ? BTA_HH_ERR_PROTO : BTA_HH_OK;
|
||||
conn.handle = p_cb->hid_handle;
|
||||
/* check if host initiate the connection*/
|
||||
conn.is_orig = !p_cb->incoming_conn;
|
||||
conn.is_orig = HID_HostConnectOrig(p_cb->hid_handle);
|
||||
bdcpy(conn.bda, p_cb->addr);
|
||||
(* bta_hh_cb.p_cback)(p_cb->w4_evt, (tBTA_HH *)&conn);
|
||||
#if BTA_HH_DEBUG
|
||||
|
@ -704,12 +701,12 @@ void bta_hh_handsk_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
|
|||
break;
|
||||
|
||||
default:
|
||||
/* unknow transaction handshake response */
|
||||
/* unknown transaction handshake response */
|
||||
APPL_TRACE_DEBUG("unknown transaction type");
|
||||
break;
|
||||
}
|
||||
|
||||
/* transaction achknoledgement received, inform PM for mode change */
|
||||
/* transaction acknowledgement received, inform PM for mode change */
|
||||
bta_sys_idle(BTA_ID_HH, p_cb->app_id, p_cb->addr);
|
||||
return;
|
||||
}
|
||||
|
@ -799,7 +796,7 @@ void bta_hh_open_failure(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
|
|||
conn_dat.status = (reason == HID_ERR_AUTH_FAILED) ?
|
||||
BTA_HH_ERR_AUTH_FAILED : BTA_HH_ERR;
|
||||
/* check if host initiate the connection*/
|
||||
conn_dat.is_orig = !p_cb->incoming_conn;
|
||||
conn_dat.is_orig = HID_HostConnectOrig(p_cb->hid_handle);
|
||||
bdcpy(conn_dat.bda, p_cb->addr);
|
||||
HID_HostCloseDev(p_cb->hid_handle);
|
||||
|
||||
|
@ -844,13 +841,13 @@ void bta_hh_close_act (tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
|
|||
|
||||
/* Check reason for closing */
|
||||
if ((reason & (HID_L2CAP_CONN_FAIL | HID_L2CAP_REQ_FAIL)) || /* Failure to initialize connection (page timeout or l2cap error) */
|
||||
(reason == HID_ERR_AUTH_FAILED) || /* Authenication error (while initiating) */
|
||||
(reason == HID_ERR_AUTH_FAILED) || /* Authentication error (while initiating) */
|
||||
(reason == HID_ERR_L2CAP_FAILED)) { /* Failure creating l2cap connection */
|
||||
/* Failure in opening connection */
|
||||
conn_dat.handle = p_cb->hid_handle;
|
||||
conn_dat.status = (reason == HID_ERR_AUTH_FAILED) ? BTA_HH_ERR_AUTH_FAILED : BTA_HH_ERR;
|
||||
/* check if host initiate the connection*/
|
||||
conn_dat.is_orig = !p_cb->incoming_conn;
|
||||
conn_dat.is_orig = HID_HostConnectOrig(p_cb->hid_handle);
|
||||
bdcpy(conn_dat.bda, p_cb->addr);
|
||||
HID_HostCloseDev(p_cb->hid_handle);
|
||||
|
||||
|
|
|
@ -293,7 +293,7 @@ void bta_hh_sm_execute(tBTA_HH_DEV_CB *p_cb, UINT16 event, tBTA_HH_DATA *p_data)
|
|||
cback_data.conn.status = BTA_HH_ERR_DB_FULL;
|
||||
cback_data.conn.handle = BTA_HH_INVALID_HANDLE;
|
||||
/* check if host initiate the connection*/
|
||||
cback_data.conn.is_orig = !p_cb->incoming_conn;
|
||||
cback_data.conn.is_orig = TRUE;
|
||||
break;
|
||||
/* DB full, BTA_HhAddDev */
|
||||
case BTA_HH_API_MAINT_DEV_EVT:
|
||||
|
|
|
@ -69,6 +69,13 @@ typedef struct {
|
|||
char *p_description;
|
||||
char *p_provider;
|
||||
uint8_t subclass;
|
||||
|
||||
// SDP Idenification info
|
||||
uint16_t vendor_id; // 0x0201
|
||||
uint16_t product_id; // 0x0202
|
||||
uint16_t version; // 0x0203
|
||||
uint8_t vendor_id_source; // 0x0205
|
||||
|
||||
tBTA_HD_DEV_DESCR descriptor;
|
||||
} tBTA_HD_APP_INFO;
|
||||
|
||||
|
|
|
@ -318,9 +318,19 @@ bt_status_t btc_hf_init(void)
|
|||
|
||||
BTC_TRACE_DEBUG("%s - max_hf_clients=%d", __func__, btc_max_hf_clients);
|
||||
|
||||
#if HFP_DYNAMIC_MEMORY == TRUE
|
||||
if (hf_local_param == NULL) {
|
||||
if ((hf_local_param = (hf_local_param_t *)osi_malloc(BTC_HF_NUM_CB * sizeof(hf_local_param_t))) == NULL) {
|
||||
BTC_TRACE_ERROR("%s malloc failed!", __func__);
|
||||
return BT_STATUS_NOMEM;
|
||||
}
|
||||
}
|
||||
memset((void *)hf_local_param, 0, BTC_HF_NUM_CB * sizeof(hf_local_param_t));
|
||||
#endif
|
||||
|
||||
/* Invoke the enable service API to the core to set the appropriate service_id
|
||||
* Internally, the HSP_SERVICE_ID shall also be enabled if HFP is enabled (phone)
|
||||
* othwerwise only HSP is enabled (tablet)*/
|
||||
* otherwise only HSP is enabled (tablet)*/
|
||||
#if (defined(BTC_HF_SERVICES) && (BTC_HF_SERVICES & BTA_HFP_SERVICE_MASK))
|
||||
btc_dm_enable_service(BTA_HFP_SERVICE_ID);
|
||||
#else
|
||||
|
@ -747,7 +757,7 @@ static bt_status_t btc_hf_phone_state_update(bt_bdaddr_t *bd_addr,int num_active
|
|||
}
|
||||
/* CIND response should have been updated. */
|
||||
BTA_AgResult(BTA_AG_HANDLE_ALL, res, &ag_res);
|
||||
/* Just open SCO conenction. */
|
||||
/* Just open SCO connection. */
|
||||
BTA_AgAudioOpen(ag_res.audio_handle);
|
||||
activeCallUpdated = TRUE;
|
||||
}
|
||||
|
@ -1560,7 +1570,7 @@ void btc_hf_cb_handler(btc_msg_t *msg)
|
|||
CHECK_HF_IDX(idx);
|
||||
BTC_TRACE_DEBUG("AG Bitmap of peer-codecs %d", p_data->val.num);
|
||||
#if (BTM_WBS_INCLUDED == TRUE)
|
||||
/* If the peer supports mSBC and the BTC prefferred codec is also mSBC, then
|
||||
/* If the peer supports mSBC and the BTC preferred codec is also mSBC, then
|
||||
** we should set the BTA AG Codec to mSBC. This would trigger a +BCS to mSBC at the time
|
||||
** of SCO connection establishment */
|
||||
if ((btc_conf_hf_force_wbs == TRUE) && (p_data->val.num & BTA_AG_CODEC_MSBC)) {
|
||||
|
@ -1596,7 +1606,7 @@ void btc_hf_cb_handler(btc_msg_t *msg)
|
|||
BTC_TRACE_DEBUG("AG final seleded codec is %d 1=CVSD 2=MSBC", p_data->val.num);
|
||||
memcpy(param.bcs_rep.remote_addr, &hf_local_param[idx].btc_hf_cb.connected_bda,sizeof(esp_bd_addr_t));
|
||||
param.bcs_rep.mode = p_data->val.num;
|
||||
/* No ESP_HF_WBS_NONE case, becuase HFP 1.6 supported device can send BCS */
|
||||
/* No ESP_HF_WBS_NONE case, because HFP 1.6 supported device can send BCS */
|
||||
btc_hf_cb_to_app(ESP_HF_BCS_RESPONSE_EVT, ¶m);
|
||||
} while (0);
|
||||
break;
|
||||
|
|
|
@ -341,6 +341,13 @@ static void btc_hd_register_app(esp_hidd_app_param_t *p_app_param, esp_hidd_qos_
|
|||
btc_hd_cb.out_qos.access_latency = p_out_qos->access_latency;
|
||||
btc_hd_cb.out_qos.delay_variation = p_out_qos->delay_variation;
|
||||
|
||||
// Copy SDP record information for DID (Device Identification Profile)
|
||||
btc_hd_cb.app_info.vendor_id = p_app_param->vendor_id;
|
||||
btc_hd_cb.app_info.product_id = p_app_param->product_id;
|
||||
btc_hd_cb.app_info.version = p_app_param->version;
|
||||
btc_hd_cb.app_info.vendor_id_source = p_app_param->vendor_id_source;
|
||||
|
||||
|
||||
BTA_HdRegisterApp(&btc_hd_cb.app_info, &btc_hd_cb.in_qos, &btc_hd_cb.out_qos);
|
||||
} while(0);
|
||||
|
||||
|
|
|
@ -189,7 +189,7 @@ static btc_hh_device_t *btc_hh_find_connected_dev_by_bda(BD_ADDR bd_addr)
|
|||
*
|
||||
* Function btc_hh_stop_vup_timer
|
||||
*
|
||||
* Description stop vitual unplug timer
|
||||
* Description stop virtual unplug timer
|
||||
*
|
||||
* Returns void
|
||||
******************************************************************************/
|
||||
|
@ -316,7 +316,7 @@ void btc_hh_remove_device(BD_ADDR bd_addr)
|
|||
|
||||
for (i = 0; i < BTC_HH_MAX_ADDED_DEV; i++) {
|
||||
p_added_dev = &btc_hh_cb.added_devices[i];
|
||||
if (p_added_dev->bd_addr == bd_addr) {
|
||||
if (memcmp(p_added_dev->bd_addr, bd_addr, BD_ADDR_LEN) == 0) {
|
||||
BTA_HhRemoveDev(p_added_dev->dev_handle);
|
||||
btc_storage_remove_hid_info((bt_bdaddr_t *)p_added_dev->bd_addr);
|
||||
memset(p_added_dev->bd_addr, 0, 6);
|
||||
|
@ -544,6 +544,11 @@ static void btc_hh_connect(btc_hidh_args_t *arg)
|
|||
BTC_TRACE_ERROR("%s exceeded the maximum supported HID device number %d!", __func__, BTC_HH_MAX_HID);
|
||||
ret = ESP_HIDH_ERR_NO_RES;
|
||||
break;
|
||||
} else if (dev && dev->dev_status == ESP_HIDH_CONN_STATE_CONNECTED) {
|
||||
BTC_TRACE_WARNING("%s Device[%s] already connected", __func__,
|
||||
bdaddr_to_string((const bt_bdaddr_t *)arg->connect.bd_addr, bdstr, sizeof(bdstr)));
|
||||
param.open.conn_status = ESP_HIDH_CONN_STATE_CONNECTED;
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i = 0; i < BTC_HH_MAX_ADDED_DEV; i++) {
|
||||
|
@ -662,7 +667,7 @@ static void btc_hh_virtual_unplug(btc_hidh_args_t *arg)
|
|||
param.unplug.conn_status = ESP_HIDH_CONN_STATE_DISCONNECTING;
|
||||
param.unplug.handle = p_dev->dev_handle;
|
||||
} else if ((p_dev != NULL) && (p_dev->dev_status == ESP_HIDH_CONN_STATE_CONNECTED)) {
|
||||
BTC_TRACE_WARNING("%s: Virtual unplug not suported, disconnecting device", __func__);
|
||||
BTC_TRACE_WARNING("%s: Virtual unplug not supported, disconnecting device", __func__);
|
||||
/* start the timer */
|
||||
btc_hh_start_vup_timer(arg->unplug.bd_addr);
|
||||
p_dev->local_vup = true;
|
||||
|
|
|
@ -144,6 +144,10 @@ void hci_shut_down(void)
|
|||
|
||||
bool hci_downstream_data_post(uint32_t timeout)
|
||||
{
|
||||
if (hci_host_env.downstream_data_ready == NULL) {
|
||||
HCI_TRACE_WARNING("%s downstream_data_ready event not created", __func__);
|
||||
return false;
|
||||
}
|
||||
return osi_thread_post_event(hci_host_env.downstream_data_ready, timeout);
|
||||
}
|
||||
|
||||
|
@ -263,7 +267,7 @@ static void transmit_command(
|
|||
// in case the upper layer didn't already
|
||||
command->event = MSG_STACK_TO_HC_HCI_CMD;
|
||||
|
||||
HCI_TRACE_DEBUG("HCI Enqueue Comamnd opcode=0x%x\n", metadata->opcode);
|
||||
HCI_TRACE_DEBUG("HCI Enqueue Command opcode=0x%x\n", metadata->opcode);
|
||||
BTTRC_DUMP_BUFFER(NULL, command->data + command->offset, command->len);
|
||||
|
||||
fixed_pkt_queue_enqueue(hci_host_env.command_queue, linked_pkt, FIXED_PKT_QUEUE_MAX_TIMEOUT);
|
||||
|
|
|
@ -3291,6 +3291,7 @@ static void btm_ble_appearance_to_cod(UINT16 appearance, UINT8 *dev_class)
|
|||
case BTM_BLE_APPEARANCE_CYCLING_CADENCE:
|
||||
case BTM_BLE_APPEARANCE_CYCLING_POWER:
|
||||
case BTM_BLE_APPEARANCE_CYCLING_SPEED_CADENCE:
|
||||
case BTM_BLE_APPEARANCE_STANDALONE_SPEAKER:
|
||||
case BTM_BLE_APPEARANCE_GENERIC_OUTDOOR_SPORTS:
|
||||
case BTM_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION:
|
||||
case BTM_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION_AND_NAV:
|
||||
|
|
|
@ -379,6 +379,7 @@ tHID_STATUS HID_HostAddDev ( BD_ADDR addr, UINT16 attr_mask, UINT8 *handle )
|
|||
if (!hh_cb.devices[i].in_use) {
|
||||
hh_cb.devices[i].in_use = TRUE;
|
||||
hh_cb.devices[i].delay_remove = FALSE;
|
||||
hh_cb.devices[i].is_orig = FALSE;
|
||||
memcpy( hh_cb.devices[i].addr, addr, sizeof( BD_ADDR ) ) ;
|
||||
hh_cb.devices[i].state = HID_DEV_NO_CONN;
|
||||
hh_cb.devices[i].conn_tries = 0 ;
|
||||
|
@ -486,6 +487,7 @@ tHID_STATUS HID_HostOpenDev ( UINT8 dev_handle )
|
|||
}
|
||||
|
||||
hh_cb.devices[dev_handle].conn_tries = 1;
|
||||
hh_cb.devices[dev_handle].is_orig = TRUE;
|
||||
return hidh_conn_initiate( dev_handle );
|
||||
}
|
||||
|
||||
|
@ -651,4 +653,23 @@ BOOLEAN hid_known_hid_device (BD_ADDR bd_addr)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
BOOLEAN HID_HostConnectOrig(UINT8 dev_handle)
|
||||
{
|
||||
BOOLEAN ret = FALSE;
|
||||
|
||||
do {
|
||||
if (!hh_cb.reg_flag) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ((dev_handle >= HID_HOST_MAX_DEVICES) || (!hh_cb.devices[dev_handle].in_use)) {
|
||||
break;
|
||||
}
|
||||
|
||||
ret = hh_cb.devices[dev_handle].is_orig;
|
||||
} while (0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif //HID_HOST_INCLUDED
|
||||
|
|
|
@ -35,11 +35,11 @@ enum { HID_DEV_NO_CONN, HID_DEV_CONNECTED };
|
|||
typedef struct per_device_ctb {
|
||||
BOOLEAN in_use;
|
||||
BOOLEAN delay_remove;
|
||||
BOOLEAN is_orig;
|
||||
BD_ADDR addr; /* BD-Addr of the host device */
|
||||
UINT16 attr_mask; /* 0x01- virtual_cable; 0x02- normally_connectable; 0x03- reconn_initiate;
|
||||
0x04- sdp_disable; */
|
||||
UINT8 state; /* Device state if in HOST-KNOWN mode */
|
||||
UINT8 conn_substate;
|
||||
UINT8 conn_tries; /* Remembers to the number of connection attempts while CONNECTING */
|
||||
|
||||
tHID_CONN conn; /* L2CAP channel info */
|
||||
|
|
|
@ -254,6 +254,7 @@ typedef UINT8 BLE_SIGNATURE[BTM_BLE_AUTH_SIGN_LEN]; /* Device address */
|
|||
#define BTM_BLE_APPEARANCE_CYCLING_CADENCE 0x0483
|
||||
#define BTM_BLE_APPEARANCE_CYCLING_POWER 0x0484
|
||||
#define BTM_BLE_APPEARANCE_CYCLING_SPEED_CADENCE 0x0485
|
||||
#define BTM_BLE_APPEARANCE_STANDALONE_SPEAKER 0x0841
|
||||
#define BTM_BLE_APPEARANCE_GENERIC_PULSE_OXIMETER 0x0C40
|
||||
#define BTM_BLE_APPEARANCE_PULSE_OXIMETER_FINGERTIP 0x0C41
|
||||
#define BTM_BLE_APPEARANCE_PULSE_OXIMETER_WRIST 0x0C42
|
||||
|
|
|
@ -249,6 +249,17 @@ BOOLEAN hid_known_hid_device (BD_ADDR bd_addr);
|
|||
*******************************************************************************/
|
||||
extern UINT8 HID_HostSetTraceLevel (UINT8 new_level);
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function HID_HostConnectOrig
|
||||
**
|
||||
** Description Check if the HID Host initiates the connection
|
||||
**
|
||||
** Returns TRUE if the HID Host initiates the connection else FALSE
|
||||
**
|
||||
*******************************************************************************/
|
||||
extern BOOLEAN HID_HostConnectOrig(UINT8 dev_handle);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit acbe4fe3219cb7ce677be1aa2c4142f308ea4958
|
||||
Subproject commit a2acac3e14bb7810783ac5089ccf8229a2dd2f70
|
|
@ -1,57 +0,0 @@
|
|||
[sections:bt_bss]
|
||||
entries:
|
||||
.bss+
|
||||
|
||||
[sections:bt_common]
|
||||
entries:
|
||||
COMMON
|
||||
|
||||
[scheme:bt_start_end]
|
||||
entries:
|
||||
bt_bss -> dram0_bss
|
||||
bt_common -> dram0_bss
|
||||
data -> dram0_data
|
||||
|
||||
# For the following fragments, order matters for
|
||||
# 'ALIGN(4) ALIGN(4, post) SURROUND(sym)', which generates:
|
||||
#
|
||||
# . = ALIGN(4)
|
||||
# _sym_start
|
||||
# ...
|
||||
# . = ALIGN(4)
|
||||
# _sym_end
|
||||
|
||||
[mapping:bt]
|
||||
archive: libbt.a
|
||||
entries:
|
||||
if ESP_ALLOW_BSS_SEG_EXTERNAL_MEMORY = y:
|
||||
* (extram_bss)
|
||||
else:
|
||||
* (bt_start_end);
|
||||
bt_bss -> dram0_bss ALIGN(4) ALIGN(4, post) SURROUND(bt_bss),
|
||||
bt_common -> dram0_bss ALIGN(4) ALIGN(4, post) SURROUND(bt_common),
|
||||
data -> dram0_data ALIGN(4) ALIGN(4, post) SURROUND(bt_data)
|
||||
|
||||
[mapping:btdm]
|
||||
archive: libbtdm_app.a
|
||||
entries:
|
||||
* (bt_start_end);
|
||||
bt_bss -> dram0_bss ALIGN(4) ALIGN(4, post) SURROUND(btdm_bss),
|
||||
bt_common -> dram0_bss ALIGN(4) ALIGN(4, post) SURROUND(btdm_common),
|
||||
data -> dram0_data ALIGN(4) ALIGN(4, post) SURROUND(btdm_data)
|
||||
|
||||
[mapping:bt_controller]
|
||||
archive: libble_app.a
|
||||
entries:
|
||||
* (bt_start_end);
|
||||
bt_bss -> dram0_bss ALIGN(4) ALIGN(4, post) SURROUND(bt_controller_bss),
|
||||
bt_common -> dram0_bss ALIGN(4) ALIGN(4, post) SURROUND(bt_controller_common),
|
||||
data -> dram0_data ALIGN(4) ALIGN(4, post) SURROUND(bt_controller_data)
|
||||
|
||||
[mapping:nimble]
|
||||
archive: libnimble.a
|
||||
entries:
|
||||
* (bt_start_end);
|
||||
bt_bss -> dram0_bss ALIGN(4) ALIGN(4, post) SURROUND(nimble_bss),
|
||||
bt_common -> dram0_bss ALIGN(4) ALIGN(4, post) SURROUND(nimble_common),
|
||||
data -> dram0_data ALIGN(4) ALIGN(4, post) SURROUND(nimble_data)
|
|
@ -0,0 +1,42 @@
|
|||
[sections:bt_bss]
|
||||
entries:
|
||||
.bss+
|
||||
|
||||
[sections:bt_common]
|
||||
entries:
|
||||
COMMON
|
||||
|
||||
[scheme:bt_default]
|
||||
entries:
|
||||
bt_bss -> dram0_bss
|
||||
bt_common -> dram0_bss
|
||||
data -> dram0_data
|
||||
|
||||
[scheme:bt_extram_bss]
|
||||
entries:
|
||||
bt_bss -> extern_ram
|
||||
bt_common -> extern_ram
|
||||
data -> dram0_data
|
||||
|
||||
# For the following fragments, order matters for
|
||||
# 'ALIGN(4) ALIGN(4, post) SURROUND(sym)', which generates:
|
||||
#
|
||||
# . = ALIGN(4)
|
||||
# _sym_start
|
||||
# ...
|
||||
# . = ALIGN(4)
|
||||
# _sym_end
|
||||
|
||||
[mapping:bt]
|
||||
archive: libbt.a
|
||||
entries:
|
||||
if ESP_ALLOW_BSS_SEG_EXTERNAL_MEMORY = y:
|
||||
* (bt_extram_bss);
|
||||
bt_bss -> extern_ram ALIGN(4) ALIGN(4, post) SURROUND(bt_bss),
|
||||
bt_common -> extern_ram ALIGN(4) ALIGN(4, post) SURROUND(bt_common),
|
||||
data -> dram0_data ALIGN(4) ALIGN(4, post) SURROUND(bt_data)
|
||||
else:
|
||||
* (bt_default);
|
||||
bt_bss -> dram0_bss ALIGN(4) ALIGN(4, post) SURROUND(bt_bss),
|
||||
bt_common -> dram0_bss ALIGN(4) ALIGN(4, post) SURROUND(bt_common),
|
||||
data -> dram0_data ALIGN(4) ALIGN(4, post) SURROUND(bt_data)
|
|
@ -1,4 +1,4 @@
|
|||
[sections:bt_text]
|
||||
[sections:bt_iram_text]
|
||||
entries:
|
||||
.iram1+
|
||||
|
||||
|
@ -17,9 +17,9 @@ entries:
|
|||
entries:
|
||||
COMMON
|
||||
|
||||
[scheme:bt_start_end]
|
||||
[scheme:bt_default]
|
||||
entries:
|
||||
bt_text -> iram0_bt_text
|
||||
bt_iram_text -> iram0_bt_text
|
||||
bt_bss -> dram0_bt_bss
|
||||
bt_common -> dram0_bt_bss
|
||||
bt_data -> dram0_bt_data
|
||||
|
@ -36,25 +36,15 @@ entries:
|
|||
[mapping:bt]
|
||||
archive: libbt.a
|
||||
entries:
|
||||
* (bt_start_end);
|
||||
* (bt_default);
|
||||
bt_bss -> dram0_bt_bss ALIGN(4) ALIGN(4, post) SURROUND(bt_bss),
|
||||
bt_common -> dram0_bt_bss ALIGN(4) ALIGN(4, post) SURROUND(bt_common),
|
||||
bt_data -> dram0_bt_data ALIGN(4) ALIGN(4, post) SURROUND(bt_data)
|
||||
if ESP_ALLOW_BSS_SEG_EXTERNAL_MEMORY = y:
|
||||
* (extram_bss)
|
||||
|
||||
[mapping:btdm]
|
||||
archive: libbtdm_app.a
|
||||
entries:
|
||||
* (bt_start_end);
|
||||
bt_bss -> dram0_bt_bss ALIGN(4) ALIGN(4, post) SURROUND(btdm_bss),
|
||||
bt_common -> dram0_bt_bss ALIGN(4) ALIGN(4, post) SURROUND(btdm_common),
|
||||
bt_data -> dram0_bt_data ALIGN(4) ALIGN(4, post) SURROUND(btdm_data)
|
||||
|
||||
[mapping:bt_controller]
|
||||
[mapping:ble_app]
|
||||
archive: libble_app.a
|
||||
entries:
|
||||
* (bt_start_end);
|
||||
* (bt_default);
|
||||
bt_bss -> dram0_bt_bss ALIGN(4) ALIGN(4, post) SURROUND(bt_controller_bss),
|
||||
bt_common -> dram0_bt_bss ALIGN(4) ALIGN(4, post) SURROUND(bt_controller_common),
|
||||
bt_data -> dram0_bt_data ALIGN(4) ALIGN(4, post) SURROUND(bt_controller_data)
|
|
@ -0,0 +1,7 @@
|
|||
[mapping:ble_app]
|
||||
archive: libble_app.a
|
||||
entries:
|
||||
* (bt_default);
|
||||
bt_bss -> dram0_bss ALIGN(4) ALIGN(4, post) SURROUND(bt_controller_bss),
|
||||
bt_common -> dram0_bss ALIGN(4) ALIGN(4, post) SURROUND(bt_controller_common),
|
||||
data -> dram0_data ALIGN(4) ALIGN(4, post) SURROUND(bt_controller_data)
|
|
@ -0,0 +1,7 @@
|
|||
[mapping:btdm]
|
||||
archive: libbtdm_app.a
|
||||
entries:
|
||||
* (bt_default);
|
||||
bt_bss -> dram0_bss ALIGN(4) ALIGN(4, post) SURROUND(bt_controller_bss),
|
||||
bt_common -> dram0_bss ALIGN(4) ALIGN(4, post) SURROUND(bt_controller_common),
|
||||
data -> dram0_data ALIGN(4) ALIGN(4, post) SURROUND(bt_controller_data)
|
|
@ -1,8 +1,17 @@
|
|||
# Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps
|
||||
|
||||
components/bt/test_apps:
|
||||
components/bt/test_apps/basic_unit_test:
|
||||
disable:
|
||||
- if: IDF_TARGET not in ["esp32", "esp32c3"]
|
||||
reason: Sufficient to run the tests on one chip of each architecture
|
||||
depends_components:
|
||||
- bt
|
||||
|
||||
components/bt/test_apps/memory_release:
|
||||
disable:
|
||||
- if: IDF_TARGET not in ["esp32", "esp32c2"]
|
||||
- if: CONFIG_NAME == "iram" and IDF_TARGET != "esp32c2"
|
||||
- if: CONFIG_NAME == "psram" and SOC_SPIRAM_SUPPORTED != 1
|
||||
reason: Sufficient to run the tests on one chip of each architecture
|
||||
depends_components:
|
||||
- bt
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
import pytest
|
||||
from pytest_embedded import Dut
|
||||
|
|
@ -1,3 +1,2 @@
|
|||
CONFIG_BT_ENABLED=y
|
||||
CONFIG_UNITY_FREERTOS_STACK_SIZE=12288
|
||||
CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=n
|
|
@ -0,0 +1,5 @@
|
|||
# This is the project CMakeLists.txt file for the test subproject
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(test_bt_memory_release)
|
|
@ -0,0 +1,4 @@
|
|||
| Supported Targets | ESP32 | ESP32-C2 |
|
||||
| ----------------- | ----- | -------- |
|
||||
|
||||
This test app is used to test esp_bt_memory_release function
|
|
@ -0,0 +1,3 @@
|
|||
idf_component_register(SRCS "test_app_main.c"
|
||||
INCLUDE_DIRS "."
|
||||
PRIV_REQUIRES bt nvs_flash)
|
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "nvs_flash.h"
|
||||
|
||||
#include "multi_heap.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
#include "esp_bt.h"
|
||||
#include "nimble/nimble_port.h"
|
||||
#include "nimble/nimble_port_freertos.h"
|
||||
#include "host/ble_hs.h"
|
||||
#include "host/util/util.h"
|
||||
#include "services/gap/ble_svc_gap.h"
|
||||
|
||||
#define FAIL() do { printf("FAILURE\n"); return; } while(0)
|
||||
|
||||
extern uint8_t _bt_bss_start;
|
||||
extern uint8_t _bt_bss_end;
|
||||
extern uint8_t _bt_controller_bss_start;
|
||||
extern uint8_t _bt_controller_bss_end;
|
||||
|
||||
extern void ble_store_config_init(void);
|
||||
|
||||
static const char *tag = "MEM_RELEASE_APP";
|
||||
|
||||
static void nimble_host_on_reset(int reason)
|
||||
{
|
||||
ESP_LOGI(tag, "Resetting state; reason=%d", reason);
|
||||
}
|
||||
|
||||
static void nimble_host_on_sync(void)
|
||||
{
|
||||
ESP_LOGI(tag, "NimBLE host synchronized");
|
||||
}
|
||||
|
||||
static void nimble_host_task_fn(void *param)
|
||||
{
|
||||
ESP_LOGI(tag, "BLE Host Task Started");
|
||||
/* This function will return only when nimble_port_stop() is executed */
|
||||
nimble_port_run();
|
||||
|
||||
nimble_port_freertos_deinit();
|
||||
}
|
||||
|
||||
static void bt_stack_init(void)
|
||||
{
|
||||
esp_err_t ret = nimble_port_init();
|
||||
ESP_ERROR_CHECK(ret);
|
||||
|
||||
/* Initialize the NimBLE host configuration. */
|
||||
ble_hs_cfg.reset_cb = nimble_host_on_reset;
|
||||
ble_hs_cfg.sync_cb = nimble_host_on_sync;
|
||||
ble_hs_cfg.store_status_cb = ble_store_util_status_rr;
|
||||
|
||||
/* Set the default device name. */
|
||||
int rc = ble_svc_gap_device_name_set(tag);
|
||||
assert(rc == 0);
|
||||
|
||||
/* XXX Need to have template for store */
|
||||
ble_store_config_init();
|
||||
|
||||
nimble_port_freertos_init(nimble_host_task_fn);
|
||||
}
|
||||
|
||||
static void bt_stack_deinit(void)
|
||||
{
|
||||
int rc = nimble_port_stop();
|
||||
assert(rc == 0);
|
||||
|
||||
nimble_port_deinit();
|
||||
ESP_LOGI(tag, "BLE Host Task Stopped");
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
/* Initialize NVS — it is used to store PHY calibration data */
|
||||
ret = nvs_flash_init();
|
||||
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||
ret = nvs_flash_init();
|
||||
}
|
||||
ESP_ERROR_CHECK(ret);
|
||||
|
||||
/* initialize and then deinitialize bluetooth stack */
|
||||
bt_stack_init();
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(200));
|
||||
|
||||
bt_stack_deinit();
|
||||
|
||||
/* Get the size of heap located in external RAM */
|
||||
const uint32_t free_before = heap_caps_get_free_size(MALLOC_CAP_DEFAULT);
|
||||
ESP_LOGI(tag, "Free size in external RAM heap: %"PRIu32, free_before);
|
||||
|
||||
/* Make sure at least one of the Bluetooth BSS section that can be used as a heap */
|
||||
const uint32_t heap_size = sizeof(multi_heap_info_t);
|
||||
const uint32_t bt_bss_size = &_bt_bss_end - &_bt_bss_start;
|
||||
const uint32_t bt_ctrl_bss_size = &_bt_controller_bss_end - &_bt_controller_bss_start;
|
||||
|
||||
ESP_LOGI(tag, "bt_bss_size %"PRIu32", bt_ctrl_bss_size %"PRIu32, bt_bss_size, bt_ctrl_bss_size);
|
||||
if (bt_bss_size < heap_size && bt_ctrl_bss_size < heap_size)
|
||||
{
|
||||
ESP_LOGW(tag, "Bluetooth BSS sections are too small!");
|
||||
FAIL();
|
||||
}
|
||||
|
||||
/* Release the BSS sections to use them as heap */
|
||||
ret = esp_bt_mem_release(ESP_BT_MODE_BTDM);
|
||||
ESP_ERROR_CHECK(ret);
|
||||
|
||||
/* Check that we have more available memory in the external RAM heap */
|
||||
const uint32_t free_after = heap_caps_get_free_size(MALLOC_CAP_DEFAULT);
|
||||
ESP_LOGI(tag, "Free size in external RAM after releasing: %"PRIu32, free_after);
|
||||
if (free_after <= free_before) {
|
||||
FAIL();
|
||||
}
|
||||
ESP_LOGI(tag, "Free heap size increased by %"PRIu32" bytes", free_after - free_before);
|
||||
|
||||
ESP_LOGI(tag, "SUCCESS");
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
import pytest
|
||||
from pytest_embedded import Dut
|
||||
|
||||
|
||||
@pytest.mark.parametrize('config', [
|
||||
pytest.param('default', marks=[pytest.mark.esp32, pytest.mark.esp32c2, pytest.mark.generic]),
|
||||
pytest.param('iram', marks=[pytest.mark.esp32c2, pytest.mark.generic]),
|
||||
pytest.param('psram', marks=[pytest.mark.esp32, pytest.mark.psram]),
|
||||
], indirect=True)
|
||||
def test_bt_memory_release(dut: Dut) -> None:
|
||||
dut.expect_exact('BLE Host Task Started', timeout=6)
|
||||
dut.expect_exact('BLE Host Task Stopped', timeout=8)
|
||||
dut.expect_exact('SUCCESS', timeout=10)
|
|
@ -0,0 +1,2 @@
|
|||
CONFIG_ESP_SYSTEM_PMP_IDRAM_SPLIT=n
|
||||
CONFIG_BT_RELEASE_IRAM=y
|
|
@ -0,0 +1,2 @@
|
|||
CONFIG_SPIRAM=y
|
||||
CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y
|
|
@ -0,0 +1,2 @@
|
|||
CONFIG_BT_ENABLED=y
|
||||
CONFIG_BT_NIMBLE_ENABLED=y
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -34,19 +34,23 @@ typedef struct gpio_etm_event_t gpio_etm_event_t;
|
|||
typedef struct gpio_etm_group_t {
|
||||
portMUX_TYPE spinlock;
|
||||
gpio_etm_dev_t *dev;
|
||||
gpio_etm_task_t *tasks[SOC_GPIO_ETM_TASKS_PER_GROUP];
|
||||
gpio_etm_event_t *events[SOC_GPIO_ETM_EVENTS_PER_GROUP];
|
||||
uint8_t tasks[GPIO_LL_ETM_TASK_CHANNELS_PER_GROUP]; // Array of the acquired action masks in each GPIO ETM task channel
|
||||
uint8_t events[GPIO_LL_ETM_EVENT_CHANNELS_PER_GROUP]; // Array of the acquired event masks in each GPIO ETM event channel
|
||||
uint8_t actions[SOC_GPIO_PIN_COUNT]; // Array of the masks of the added actions to each GPIO
|
||||
uint8_t edges[GPIO_LL_ETM_EVENT_CHANNELS_PER_GROUP]; // Array of the masks of the bound event edges in each GPIO ETM event channel
|
||||
} gpio_etm_group_t;
|
||||
|
||||
struct gpio_etm_event_t {
|
||||
esp_etm_event_t base;
|
||||
int chan_id;
|
||||
gpio_etm_event_edge_t edge_id;
|
||||
gpio_etm_group_t *group;
|
||||
};
|
||||
|
||||
struct gpio_etm_task_t {
|
||||
esp_etm_task_t base;
|
||||
int chan_id;
|
||||
gpio_etm_task_action_t action_id;
|
||||
gpio_etm_group_t *group;
|
||||
size_t num_of_gpios; // record the number of GPIOs that are bound to the etm task
|
||||
};
|
||||
|
@ -56,81 +60,65 @@ static gpio_etm_group_t s_gpio_etm_group = {
|
|||
.spinlock = portMUX_INITIALIZER_UNLOCKED,
|
||||
};
|
||||
|
||||
static esp_err_t gpio_etm_event_register_to_group(gpio_etm_event_t *event)
|
||||
static esp_err_t gpio_etm_acquire_event_channel(uint8_t event_mask, int *chan_id)
|
||||
{
|
||||
assert(chan_id);
|
||||
gpio_etm_group_t *group = &s_gpio_etm_group;
|
||||
int chan_id = -1;
|
||||
// loop to search free one in the group
|
||||
|
||||
int free_chan_id = -1;
|
||||
// loop to search free event channel in the group
|
||||
portENTER_CRITICAL(&group->spinlock);
|
||||
for (int j = 0; j < SOC_GPIO_ETM_EVENTS_PER_GROUP; j++) {
|
||||
for (int j = 0; j < GPIO_LL_ETM_EVENT_CHANNELS_PER_GROUP; j++) {
|
||||
if (!group->events[j]) {
|
||||
chan_id = j;
|
||||
group->events[j] = event;
|
||||
free_chan_id = j;
|
||||
group->events[j] = event_mask;
|
||||
break;
|
||||
}
|
||||
}
|
||||
portEXIT_CRITICAL(&group->spinlock);
|
||||
|
||||
ESP_RETURN_ON_FALSE(chan_id != -1, ESP_ERR_NOT_FOUND, TAG, "no free event channel");
|
||||
event->group = group;
|
||||
event->chan_id = chan_id;
|
||||
ESP_RETURN_ON_FALSE(free_chan_id != -1, ESP_ERR_NOT_FOUND, TAG, "no free event channel");
|
||||
*chan_id = free_chan_id;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t gpio_etm_task_register_to_group(gpio_etm_task_t *task)
|
||||
static esp_err_t gpio_etm_release_event_channel(int chan_id, uint8_t event_mask)
|
||||
{
|
||||
gpio_etm_group_t *group = &s_gpio_etm_group;
|
||||
int chan_id = -1;
|
||||
// loop to search free one in the group
|
||||
portENTER_CRITICAL(&group->spinlock);
|
||||
for (int j = 0; j < SOC_GPIO_ETM_TASKS_PER_GROUP; j++) {
|
||||
group->events[chan_id] &= ~event_mask;
|
||||
portEXIT_CRITICAL(&group->spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t gpio_etm_acquire_task_channel(uint8_t task_mask, int *chan_id)
|
||||
{
|
||||
assert(chan_id);
|
||||
gpio_etm_group_t *group = &s_gpio_etm_group;
|
||||
|
||||
int free_chan_id = -1;
|
||||
// loop to search free task channel in the group
|
||||
portENTER_CRITICAL(&group->spinlock);
|
||||
for (int j = 0; j < GPIO_LL_ETM_TASK_CHANNELS_PER_GROUP; j++) {
|
||||
if (!group->tasks[j]) {
|
||||
chan_id = j;
|
||||
group->tasks[j] = task;
|
||||
free_chan_id = j;
|
||||
group->tasks[j] = task_mask;
|
||||
break;
|
||||
}
|
||||
}
|
||||
portEXIT_CRITICAL(&group->spinlock);
|
||||
|
||||
ESP_RETURN_ON_FALSE(chan_id != -1, ESP_ERR_NOT_FOUND, TAG, "no free task channel");
|
||||
task->group = group;
|
||||
task->chan_id = chan_id;
|
||||
ESP_RETURN_ON_FALSE(free_chan_id != -1, ESP_ERR_NOT_FOUND, TAG, "no free task channel");
|
||||
*chan_id = free_chan_id;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void gpio_etm_event_unregister_from_group(gpio_etm_event_t *event)
|
||||
static esp_err_t gpio_etm_release_task_channel(int chan_id, uint8_t task_mask)
|
||||
{
|
||||
gpio_etm_group_t *group = event->group;
|
||||
int chan_id = event->chan_id;
|
||||
gpio_etm_group_t *group = &s_gpio_etm_group;
|
||||
portENTER_CRITICAL(&group->spinlock);
|
||||
group->events[chan_id] = NULL;
|
||||
group->tasks[chan_id] &= ~task_mask;
|
||||
portEXIT_CRITICAL(&group->spinlock);
|
||||
}
|
||||
|
||||
static void gpio_etm_task_unregister_from_group(gpio_etm_task_t *task)
|
||||
{
|
||||
gpio_etm_group_t *group = task->group;
|
||||
int chan_id = task->chan_id;
|
||||
portENTER_CRITICAL(&group->spinlock);
|
||||
group->tasks[chan_id] = NULL;
|
||||
portEXIT_CRITICAL(&group->spinlock);
|
||||
}
|
||||
|
||||
static esp_err_t gpio_etm_event_destroy(gpio_etm_event_t *event)
|
||||
{
|
||||
if (event->group) {
|
||||
gpio_etm_event_unregister_from_group(event);
|
||||
}
|
||||
free(event);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t gpio_etm_task_destroy(gpio_etm_task_t *task)
|
||||
{
|
||||
if (task->group) {
|
||||
gpio_etm_task_unregister_from_group(task);
|
||||
}
|
||||
free(task);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
@ -138,9 +126,16 @@ static esp_err_t gpio_del_etm_event(esp_etm_event_t *event)
|
|||
{
|
||||
gpio_etm_event_t *gpio_event = __containerof(event, gpio_etm_event_t, base);
|
||||
gpio_etm_group_t *group = gpio_event->group;
|
||||
// disable event channel
|
||||
gpio_ll_etm_enable_event_channel(group->dev, gpio_event->chan_id, false);
|
||||
gpio_etm_event_destroy(gpio_event);
|
||||
// unbind it from the GPIO and check if the GPIO ETM event channel can be disabled
|
||||
portENTER_CRITICAL(&group->spinlock);
|
||||
group->edges[gpio_event->chan_id] &= ~(1 << gpio_event->edge_id);
|
||||
if (!group->edges[gpio_event->chan_id]) {
|
||||
gpio_ll_etm_enable_event_channel(group->dev, gpio_event->chan_id, false);
|
||||
}
|
||||
portEXIT_CRITICAL(&group->spinlock);
|
||||
|
||||
gpio_etm_release_event_channel(gpio_event->chan_id, 1 << gpio_event->edge_id);
|
||||
free(gpio_event);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
@ -149,95 +144,192 @@ static esp_err_t gpio_del_etm_task(esp_etm_task_t *task)
|
|||
gpio_etm_task_t *gpio_task = __containerof(task, gpio_etm_task_t, base);
|
||||
// make sure user has called `gpio_etm_task_rm_gpio` to clean the etm task channel
|
||||
ESP_RETURN_ON_FALSE(gpio_task->num_of_gpios == 0, ESP_ERR_INVALID_STATE, TAG, "some GPIO till bounded to the etm task");
|
||||
gpio_etm_task_destroy(gpio_task);
|
||||
gpio_etm_release_task_channel(gpio_task->chan_id, 1 << gpio_task->action_id);
|
||||
free(gpio_task);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t gpio_new_etm_event(const gpio_etm_event_config_t *config, esp_etm_event_handle_t *ret_event)
|
||||
esp_err_t gpio_new_etm_event(const gpio_etm_event_config_t *config, esp_etm_event_handle_t *ret_event, ...)
|
||||
{
|
||||
#if CONFIG_ETM_ENABLE_DEBUG_LOG
|
||||
esp_log_level_set(TAG, ESP_LOG_DEBUG);
|
||||
#endif
|
||||
esp_err_t ret = ESP_OK;
|
||||
gpio_etm_event_t *event = NULL;
|
||||
ESP_GOTO_ON_FALSE(config && ret_event, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
|
||||
int chan_id = -1;
|
||||
uint8_t event_mask = 0;
|
||||
esp_etm_event_handle_t *ret_event_itor = ret_event;
|
||||
va_list args;
|
||||
ESP_RETURN_ON_FALSE(config && ret_event, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
for (int i = 0; i < GPIO_ETM_EVENT_EDGE_TYPES; i++) {
|
||||
if (config->edges[i]) {
|
||||
uint8_t msk = (1 << config->edges[i]);
|
||||
ESP_RETURN_ON_FALSE(!(msk & event_mask), ESP_ERR_INVALID_ARG, TAG, "no identical edge event allowed in one call");
|
||||
event_mask |= msk;
|
||||
}
|
||||
}
|
||||
ESP_RETURN_ON_FALSE(event_mask, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
uint32_t event_num = __builtin_popcount(event_mask);
|
||||
gpio_etm_event_t *events[event_num];
|
||||
|
||||
event = heap_caps_calloc(1, sizeof(gpio_etm_event_t), ETM_MEM_ALLOC_CAPS);
|
||||
ESP_GOTO_ON_FALSE(event, ESP_ERR_NO_MEM, err, TAG, "no mem for event channel");
|
||||
// register the event channel to the group
|
||||
ESP_GOTO_ON_ERROR(gpio_etm_event_register_to_group(event), err, TAG, "register event channel to group failed");
|
||||
int chan_id = event->chan_id;
|
||||
|
||||
uint32_t event_id = 0;
|
||||
switch (config->edge) {
|
||||
case GPIO_ETM_EVENT_EDGE_ANY:
|
||||
event_id = GPIO_LL_ETM_EVENT_ID_ANY_EDGE(chan_id);
|
||||
break;
|
||||
case GPIO_ETM_EVENT_EDGE_POS:
|
||||
event_id = GPIO_LL_ETM_EVENT_ID_POS_EDGE(chan_id);
|
||||
break;
|
||||
case GPIO_ETM_EVENT_EDGE_NEG:
|
||||
event_id = GPIO_LL_ETM_EVENT_ID_NEG_EDGE(chan_id);
|
||||
break;
|
||||
default:
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_INVALID_ARG, err, TAG, "invalid edge");
|
||||
for (int i = 0; i < event_num; i++) {
|
||||
events[i] = (gpio_etm_event_t *)heap_caps_calloc(1, sizeof(gpio_etm_event_t), ETM_MEM_ALLOC_CAPS);
|
||||
ESP_GOTO_ON_FALSE(events[i], ESP_ERR_NO_MEM, err, TAG, "no mem for event channel(s)");
|
||||
}
|
||||
|
||||
event->base.del = gpio_del_etm_event;
|
||||
event->base.event_id = event_id;
|
||||
event->base.trig_periph = ETM_TRIG_PERIPH_GPIO;
|
||||
ESP_LOGD(TAG, "new event @%p, event_id=%"PRIu32", chan_id=%d", event, event_id, chan_id);
|
||||
*ret_event = &event->base;
|
||||
// register the event channel to the group
|
||||
ESP_GOTO_ON_ERROR(gpio_etm_acquire_event_channel(event_mask, &chan_id), err, TAG, "register event channel to group failed");
|
||||
|
||||
bool no_avail_ret_arg = false;
|
||||
va_start(args, ret_event);
|
||||
for (int i = 0, j = 0; i < event_num; i++, j++) {
|
||||
if (!ret_event_itor) {
|
||||
no_avail_ret_arg = true;
|
||||
break;
|
||||
}
|
||||
// assign to the ret_event handles in the configuration order
|
||||
gpio_etm_event_edge_t event_edge;
|
||||
do {
|
||||
event_edge = config->edges[j];
|
||||
} while (!event_edge && ++j);
|
||||
uint32_t event_id = 0;
|
||||
switch (event_edge) {
|
||||
case GPIO_ETM_EVENT_EDGE_ANY:
|
||||
event_id = GPIO_LL_ETM_EVENT_ID_ANY_EDGE(chan_id);
|
||||
break;
|
||||
case GPIO_ETM_EVENT_EDGE_POS:
|
||||
event_id = GPIO_LL_ETM_EVENT_ID_POS_EDGE(chan_id);
|
||||
break;
|
||||
case GPIO_ETM_EVENT_EDGE_NEG:
|
||||
event_id = GPIO_LL_ETM_EVENT_ID_NEG_EDGE(chan_id);
|
||||
break;
|
||||
default:
|
||||
va_end(args);
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_INVALID_ARG, err, TAG, "invalid edge");
|
||||
}
|
||||
|
||||
gpio_etm_event_t *event = events[i];
|
||||
event->base.del = gpio_del_etm_event;
|
||||
event->base.event_id = event_id;
|
||||
event->base.trig_periph = ETM_TRIG_PERIPH_GPIO;
|
||||
event->group = &s_gpio_etm_group;
|
||||
event->chan_id = chan_id;
|
||||
event->edge_id = event_edge;
|
||||
ESP_LOGD(TAG, "new event @%p, event_id=%"PRIu32", chan_id=%d", event, event_id, chan_id);
|
||||
*ret_event_itor = &event->base;
|
||||
ret_event_itor = va_arg(args, esp_etm_event_handle_t *);
|
||||
}
|
||||
va_end(args);
|
||||
ESP_GOTO_ON_FALSE(!no_avail_ret_arg, ESP_ERR_INVALID_ARG, err, TAG, "mismatch number of events with number of pointers to store event handles");
|
||||
return ESP_OK;
|
||||
|
||||
err:
|
||||
if (event) {
|
||||
gpio_etm_event_destroy(event);
|
||||
if (chan_id != -1) {
|
||||
gpio_etm_release_event_channel(chan_id, event_mask);
|
||||
}
|
||||
for (int i = 0; i < event_num; i++) {
|
||||
if (events[i]) {
|
||||
free(events[i]);
|
||||
}
|
||||
}
|
||||
ret_event_itor = ret_event;
|
||||
va_start(args, ret_event);
|
||||
while (ret_event_itor) {
|
||||
*ret_event_itor = NULL;
|
||||
ret_event_itor = va_arg(args, esp_etm_event_handle_t *);
|
||||
}
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t gpio_new_etm_task(const gpio_etm_task_config_t *config, esp_etm_task_handle_t *ret_task)
|
||||
esp_err_t gpio_new_etm_task(const gpio_etm_task_config_t *config, esp_etm_task_handle_t *ret_task, ...)
|
||||
{
|
||||
#if CONFIG_ETM_ENABLE_DEBUG_LOG
|
||||
esp_log_level_set(TAG, ESP_LOG_DEBUG);
|
||||
#endif
|
||||
esp_err_t ret = ESP_OK;
|
||||
gpio_etm_task_t *task = NULL;
|
||||
ESP_GOTO_ON_FALSE(config && ret_task, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
|
||||
int chan_id = -1;
|
||||
uint8_t task_mask = 0;
|
||||
esp_etm_task_handle_t *ret_task_itor = ret_task;
|
||||
va_list args;
|
||||
ESP_RETURN_ON_FALSE(config && ret_task, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
for (int i = 0; i < GPIO_ETM_TASK_ACTION_TYPES; i++) {
|
||||
if (config->actions[i]) {
|
||||
uint8_t msk = (1 << config->actions[i]);
|
||||
ESP_RETURN_ON_FALSE(!(msk & task_mask), ESP_ERR_INVALID_ARG, TAG, "no identical action allowed in one call");
|
||||
task_mask |= msk;
|
||||
}
|
||||
}
|
||||
ESP_RETURN_ON_FALSE(task_mask, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
uint32_t task_num = __builtin_popcount(task_mask);
|
||||
gpio_etm_task_t *tasks[task_num];
|
||||
|
||||
task = heap_caps_calloc(1, sizeof(gpio_etm_task_t), ETM_MEM_ALLOC_CAPS);
|
||||
ESP_GOTO_ON_FALSE(task, ESP_ERR_NO_MEM, err, TAG, "no mem for task channel");
|
||||
// register the task channel to the group
|
||||
ESP_GOTO_ON_ERROR(gpio_etm_task_register_to_group(task), err, TAG, "register task channel to group failed");
|
||||
int chan_id = task->chan_id;
|
||||
|
||||
uint32_t task_id = 0;
|
||||
switch (config->action) {
|
||||
case GPIO_ETM_TASK_ACTION_SET:
|
||||
task_id = GPIO_LL_ETM_TASK_ID_SET(chan_id);
|
||||
break;
|
||||
case GPIO_ETM_TASK_ACTION_CLR:
|
||||
task_id = GPIO_LL_ETM_TASK_ID_CLR(chan_id);
|
||||
break;
|
||||
case GPIO_ETM_TASK_ACTION_TOG:
|
||||
task_id = GPIO_LL_ETM_TASK_ID_TOG(chan_id);
|
||||
break;
|
||||
default:
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_INVALID_ARG, err, TAG, "invalid action");
|
||||
for (int i = 0; i < task_num; i++) {
|
||||
tasks[i] = (gpio_etm_task_t *)heap_caps_calloc(1, sizeof(gpio_etm_task_t), ETM_MEM_ALLOC_CAPS);
|
||||
ESP_GOTO_ON_FALSE(tasks[i], ESP_ERR_NO_MEM, err, TAG, "no mem for task channel(s)");
|
||||
}
|
||||
|
||||
task->base.del = gpio_del_etm_task;
|
||||
task->base.task_id = task_id;
|
||||
task->base.trig_periph = ETM_TRIG_PERIPH_GPIO;
|
||||
ESP_LOGD(TAG, "new task @%p, task_id=%"PRIu32", chan_id=%d", task, task_id, chan_id);
|
||||
*ret_task = &task->base;
|
||||
// register the task channel to the group
|
||||
ESP_GOTO_ON_ERROR(gpio_etm_acquire_task_channel(task_mask, &chan_id), err, TAG, "register task channel to group failed");
|
||||
|
||||
bool no_avail_ret_arg = false;
|
||||
va_start(args, ret_task);
|
||||
for (int i = 0, j = 0; i < task_num; i++, j++) {
|
||||
if (!ret_task_itor) {
|
||||
no_avail_ret_arg = true;
|
||||
break;
|
||||
}
|
||||
// assign to the ret_task handles in the configuration order
|
||||
gpio_etm_task_action_t action;
|
||||
do {
|
||||
action = config->actions[i];
|
||||
} while (!action && ++j);
|
||||
uint32_t task_id = 0;
|
||||
switch (action) {
|
||||
case GPIO_ETM_TASK_ACTION_SET:
|
||||
task_id = GPIO_LL_ETM_TASK_ID_SET(chan_id);
|
||||
break;
|
||||
case GPIO_ETM_TASK_ACTION_CLR:
|
||||
task_id = GPIO_LL_ETM_TASK_ID_CLR(chan_id);
|
||||
break;
|
||||
case GPIO_ETM_TASK_ACTION_TOG:
|
||||
task_id = GPIO_LL_ETM_TASK_ID_TOG(chan_id);
|
||||
break;
|
||||
default:
|
||||
va_end(args);
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_INVALID_ARG, err, TAG, "invalid action");
|
||||
}
|
||||
|
||||
gpio_etm_task_t *task = tasks[i];
|
||||
task->base.del = gpio_del_etm_task;
|
||||
task->base.task_id = task_id;
|
||||
task->base.trig_periph = ETM_TRIG_PERIPH_GPIO;
|
||||
task->group = &s_gpio_etm_group;
|
||||
task->chan_id = chan_id;
|
||||
task->action_id = action;
|
||||
ESP_LOGD(TAG, "new task @%p, task_id=%"PRIu32", gpio_etm_task_chan_id=%d", task, task_id, chan_id);
|
||||
*ret_task_itor = &task->base;
|
||||
ret_task_itor = va_arg(args, esp_etm_task_handle_t *);
|
||||
}
|
||||
va_end(args);
|
||||
ESP_GOTO_ON_FALSE(!no_avail_ret_arg, ESP_ERR_INVALID_ARG, err, TAG, "mismatch number of tasks with number of pointers to store task handles");
|
||||
return ESP_OK;
|
||||
|
||||
err:
|
||||
if (task) {
|
||||
gpio_etm_task_destroy(task);
|
||||
if (chan_id != -1) {
|
||||
gpio_etm_release_task_channel(chan_id, task_mask);
|
||||
}
|
||||
for (int i = 0; i < task_num; i++) {
|
||||
if (tasks[i]) {
|
||||
free(tasks[i]);
|
||||
}
|
||||
}
|
||||
ret_task_itor = ret_task;
|
||||
va_start(args, ret_task);
|
||||
while (ret_task_itor) {
|
||||
*ret_task_itor = NULL;
|
||||
ret_task_itor = va_arg(args, esp_etm_task_handle_t *);
|
||||
}
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -248,12 +340,27 @@ esp_err_t gpio_etm_event_bind_gpio(esp_etm_event_handle_t event, int gpio_num)
|
|||
ESP_RETURN_ON_FALSE(GPIO_IS_VALID_GPIO(gpio_num), ESP_ERR_INVALID_ARG, TAG, "gpio is not input capable");
|
||||
gpio_etm_event_t *gpio_event = __containerof(event, gpio_etm_event_t, base);
|
||||
gpio_etm_group_t *group = gpio_event->group;
|
||||
// disable gpio etm event channel first
|
||||
gpio_ll_etm_enable_event_channel(group->dev, gpio_event->chan_id, false);
|
||||
// then set the gpio number
|
||||
gpio_ll_etm_event_channel_set_gpio(group->dev, gpio_event->chan_id, gpio_num);
|
||||
// enable gpio etm event channel again
|
||||
gpio_ll_etm_enable_event_channel(group->dev, gpio_event->chan_id, true);
|
||||
|
||||
bool allowed = true;
|
||||
portENTER_CRITICAL(&group->spinlock);
|
||||
// check if the GPIO ETM event channel where the new event belongs to has previously been bound to another GPIO
|
||||
// one GPIO ETM event channel can only be bound to one GPIO
|
||||
if (group->edges[gpio_event->chan_id]) {
|
||||
if (gpio_ll_etm_event_channel_get_gpio(group->dev, gpio_event->chan_id) != gpio_num) {
|
||||
allowed = false;
|
||||
}
|
||||
} else {
|
||||
// set the GPIO number
|
||||
gpio_ll_etm_event_channel_set_gpio(group->dev, gpio_event->chan_id, gpio_num);
|
||||
// enable GPIO ETM event channel
|
||||
gpio_ll_etm_enable_event_channel(group->dev, gpio_event->chan_id, true);
|
||||
}
|
||||
|
||||
if (allowed) {
|
||||
group->edges[gpio_event->chan_id] |= (1 << gpio_event->edge_id);
|
||||
}
|
||||
portEXIT_CRITICAL(&group->spinlock);
|
||||
ESP_RETURN_ON_FALSE(allowed, ESP_ERR_INVALID_ARG, TAG, "the GPIO ETM event channel where the event belongs to has already been bound to another GPIO");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
@ -264,19 +371,28 @@ esp_err_t gpio_etm_task_add_gpio(esp_etm_task_handle_t task, int gpio_num)
|
|||
ESP_RETURN_ON_FALSE(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), ESP_ERR_INVALID_ARG, TAG, "gpio is not output capable");
|
||||
gpio_etm_task_t *gpio_task = __containerof(task, gpio_etm_task_t, base);
|
||||
gpio_etm_group_t *group = gpio_task->group;
|
||||
bool gpio_not_enabled = true;
|
||||
|
||||
bool allowed = true;
|
||||
// use spinlock as this function may be called with different task object in different threads
|
||||
// and the gpio_num might reside in the same register
|
||||
portENTER_CRITICAL(&group->spinlock);
|
||||
// check if the gpio has been enabled
|
||||
if (!gpio_ll_etm_is_task_gpio_enabled(group->dev, gpio_num)) {
|
||||
// check if the new task is compatible with the tasks that has previously been added to the GPIO
|
||||
// the tasks have to be from the same GPIO ETM task channel
|
||||
if (group->actions[gpio_num]) {
|
||||
if (gpio_ll_etm_gpio_get_task_channel(group->dev, gpio_num) != gpio_task->chan_id) {
|
||||
allowed = false;
|
||||
}
|
||||
} else {
|
||||
// first action added to the GPIO
|
||||
gpio_ll_etm_gpio_set_task_channel(group->dev, gpio_num, gpio_task->chan_id);
|
||||
gpio_ll_etm_enable_task_gpio(group->dev, gpio_num, true);
|
||||
} else {
|
||||
gpio_not_enabled = false;
|
||||
}
|
||||
|
||||
if (allowed) {
|
||||
group->actions[gpio_num] |= (1 << gpio_task->action_id);
|
||||
}
|
||||
portEXIT_CRITICAL(&group->spinlock);
|
||||
ESP_RETURN_ON_FALSE(gpio_not_enabled, ESP_ERR_INVALID_STATE, TAG, "gpio already enabled by other task channel");
|
||||
ESP_RETURN_ON_FALSE(allowed, ESP_ERR_INVALID_ARG, TAG, "the task does not belong to the GPIO ETM task channel that the GPIO has already binded to");
|
||||
gpio_task->num_of_gpios++;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
@ -287,19 +403,24 @@ esp_err_t gpio_etm_task_rm_gpio(esp_etm_task_handle_t task, int gpio_num)
|
|||
ESP_RETURN_ON_FALSE(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), ESP_ERR_INVALID_ARG, TAG, "gpio is not output capable");
|
||||
gpio_etm_task_t *gpio_task = __containerof(task, gpio_etm_task_t, base);
|
||||
gpio_etm_group_t *group = gpio_task->group;
|
||||
bool gpio_enabled_by_this_task = true;
|
||||
|
||||
bool allowed = true;
|
||||
// use spinlock as this function may be called with different task object in different threads
|
||||
// and the gpio_num might reside in the same register
|
||||
portENTER_CRITICAL(&group->spinlock);
|
||||
// check if the gpio is managed by this etm task channel
|
||||
if (gpio_ll_etm_is_task_gpio_enabled(group->dev, gpio_num) &&
|
||||
if ((group->actions[gpio_num] & (1 << gpio_task->action_id)) &&
|
||||
gpio_ll_etm_is_task_gpio_enabled(group->dev, gpio_num) &&
|
||||
(gpio_ll_etm_gpio_get_task_channel(group->dev, gpio_num) == gpio_task->chan_id)) {
|
||||
gpio_ll_etm_enable_task_gpio(group->dev, gpio_num, false);
|
||||
group->actions[gpio_num] &= ~(1 << gpio_task->action_id);
|
||||
if (!group->actions[gpio_num]) {
|
||||
// all actions removed from the GPIO
|
||||
gpio_ll_etm_enable_task_gpio(group->dev, gpio_num, false);
|
||||
}
|
||||
} else {
|
||||
gpio_enabled_by_this_task = false;
|
||||
allowed = false;
|
||||
}
|
||||
portEXIT_CRITICAL(&group->spinlock);
|
||||
ESP_RETURN_ON_FALSE(gpio_enabled_by_this_task, ESP_ERR_INVALID_STATE, TAG, "gpio is not enabled by this task channel");
|
||||
ESP_RETURN_ON_FALSE(allowed, ESP_ERR_INVALID_ARG, TAG, "the task was not added to the GPIO");
|
||||
gpio_task->num_of_gpios--;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -13,20 +13,29 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define GPIO_ETM_EVENT_EDGE_TYPES 3 /*!< GPIO ETM edge events are POS/NEG/ANY */
|
||||
#define GPIO_ETM_TASK_ACTION_TYPES 3 /*!< GPIO ETM action tasks are SET/CLEAR/TOGGLE */
|
||||
|
||||
/**
|
||||
* @brief GPIO edges that can be used as ETM event
|
||||
*/
|
||||
typedef enum {
|
||||
GPIO_ETM_EVENT_EDGE_POS, /*!< A rising edge on the GPIO will generate an ETM event signal */
|
||||
GPIO_ETM_EVENT_EDGE_NEG, /*!< A falling edge on the GPIO will generate an ETM event signal */
|
||||
GPIO_ETM_EVENT_EDGE_ANY, /*!< Any edge on the GPIO can generate an ETM event signal */
|
||||
GPIO_ETM_EVENT_EDGE_POS = 1, /*!< A rising edge on the GPIO will generate an ETM event signal */
|
||||
GPIO_ETM_EVENT_EDGE_NEG, /*!< A falling edge on the GPIO will generate an ETM event signal */
|
||||
GPIO_ETM_EVENT_EDGE_ANY, /*!< Any edge on the GPIO can generate an ETM event signal */
|
||||
} gpio_etm_event_edge_t;
|
||||
|
||||
/**
|
||||
* @brief GPIO ETM event configuration
|
||||
*
|
||||
* If more than one kind of ETM edge event want to be triggered on the same GPIO pin, you can configure them together.
|
||||
* It helps to save GPIO ETM event channel resources for other GPIOs.
|
||||
*/
|
||||
typedef struct {
|
||||
gpio_etm_event_edge_t edge; /*!< Which kind of edge can trigger the ETM event module */
|
||||
union {
|
||||
gpio_etm_event_edge_t edge; /*!< Which kind of edge can trigger the ETM event module */
|
||||
gpio_etm_event_edge_t edges[GPIO_ETM_EVENT_EDGE_TYPES]; /*!< Array of kinds of edges to trigger the ETM event module on the same GPIO */
|
||||
};
|
||||
} gpio_etm_event_config_t;
|
||||
|
||||
/**
|
||||
|
@ -34,9 +43,11 @@ typedef struct {
|
|||
*
|
||||
* @note The created ETM event object can be deleted later by calling `esp_etm_del_event`
|
||||
* @note The newly created ETM event object is not bind to any GPIO, you need to call `gpio_etm_event_bind_gpio` to bind the wanted GPIO
|
||||
* @note Every success call to this function will acquire a free GPIO ETM event channel
|
||||
*
|
||||
* @param[in] config GPIO ETM event configuration
|
||||
* @param[out] ret_event Returned ETM event handle
|
||||
* @param[out] ... Other returned ETM event handles if any (the order of the returned event handles is aligned with the array order in field `edges` in `gpio_etm_event_config_t`)
|
||||
* @return
|
||||
* - ESP_OK: Create ETM event successfully
|
||||
* - ESP_ERR_INVALID_ARG: Create ETM event failed because of invalid argument
|
||||
|
@ -44,7 +55,7 @@ typedef struct {
|
|||
* - ESP_ERR_NOT_FOUND: Create ETM event failed because all events are used up and no more free one
|
||||
* - ESP_FAIL: Create ETM event failed because of other reasons
|
||||
*/
|
||||
esp_err_t gpio_new_etm_event(const gpio_etm_event_config_t *config, esp_etm_event_handle_t *ret_event);
|
||||
esp_err_t gpio_new_etm_event(const gpio_etm_event_config_t *config, esp_etm_event_handle_t *ret_event, ...);
|
||||
|
||||
/**
|
||||
* @brief Bind the GPIO with the ETM event
|
||||
|
@ -65,16 +76,21 @@ esp_err_t gpio_etm_event_bind_gpio(esp_etm_event_handle_t event, int gpio_num);
|
|||
* @brief GPIO actions that can be taken by the ETM task
|
||||
*/
|
||||
typedef enum {
|
||||
GPIO_ETM_TASK_ACTION_SET, /*!< Set the GPIO level to high */
|
||||
GPIO_ETM_TASK_ACTION_CLR, /*!< Clear the GPIO level to low */
|
||||
GPIO_ETM_TASK_ACTION_TOG, /*!< Toggle the GPIO level */
|
||||
GPIO_ETM_TASK_ACTION_SET = 1, /*!< Set the GPIO level to high */
|
||||
GPIO_ETM_TASK_ACTION_CLR, /*!< Clear the GPIO level to low */
|
||||
GPIO_ETM_TASK_ACTION_TOG, /*!< Toggle the GPIO level */
|
||||
} gpio_etm_task_action_t;
|
||||
|
||||
/**
|
||||
* @brief GPIO ETM task configuration
|
||||
*
|
||||
* If multiple actions wants to be added to the same GPIO pin, you have to configure all the GPIO ETM tasks together.
|
||||
*/
|
||||
typedef struct {
|
||||
gpio_etm_task_action_t action; /*!< Which action to take by the ETM task module */
|
||||
union {
|
||||
gpio_etm_task_action_t action; /*!< Action to take by the ETM task module */
|
||||
gpio_etm_task_action_t actions[GPIO_ETM_TASK_ACTION_TYPES]; /*!< Array of actions to take by the ETM task module on the same GPIO */
|
||||
};
|
||||
} gpio_etm_task_config_t;
|
||||
|
||||
/**
|
||||
|
@ -83,9 +99,11 @@ typedef struct {
|
|||
* @note The created ETM task object can be deleted later by calling `esp_etm_del_task`
|
||||
* @note The GPIO ETM task works like a container, a newly created ETM task object doesn't have GPIO members to be managed.
|
||||
* You need to call `gpio_etm_task_add_gpio` to put one or more GPIOs to the container.
|
||||
* @note Every success call to this function will acquire a free GPIO ETM task channel
|
||||
*
|
||||
* @param[in] config GPIO ETM task configuration
|
||||
* @param[out] ret_task Returned ETM task handle
|
||||
* @param[out] ... Other returned ETM task handles if any (the order of the returned task handles is aligned with the array order in field `actions` in `gpio_etm_task_config_t`)
|
||||
* @return
|
||||
* - ESP_OK: Create ETM task successfully
|
||||
* - ESP_ERR_INVALID_ARG: Create ETM task failed because of invalid argument
|
||||
|
@ -93,7 +111,7 @@ typedef struct {
|
|||
* - ESP_ERR_NOT_FOUND: Create ETM task failed because all tasks are used up and no more free one
|
||||
* - ESP_FAIL: Create ETM task failed because of other reasons
|
||||
*/
|
||||
esp_err_t gpio_new_etm_task(const gpio_etm_task_config_t *config, esp_etm_task_handle_t *ret_task);
|
||||
esp_err_t gpio_new_etm_task(const gpio_etm_task_config_t *config, esp_etm_task_handle_t *ret_task, ...);
|
||||
|
||||
/**
|
||||
* @brief Add GPIO to the ETM task.
|
||||
|
|
|
@ -1488,7 +1488,7 @@ esp_err_t i2c_master_cmd_begin(i2c_port_t i2c_num, i2c_cmd_handle_t cmd_handle,
|
|||
// Sometimes when the FSM get stuck, the ACK_ERR interrupt will occur endlessly until we reset the FSM and clear bus.
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
i2c_obj_t *p_i2c = p_i2c_obj[i2c_num];
|
||||
TickType_t ticks_start = xTaskGetTickCount();
|
||||
const TickType_t ticks_start = xTaskGetTickCount();
|
||||
BaseType_t res = xSemaphoreTake(p_i2c->cmd_mux, ticks_to_wait);
|
||||
if (res == pdFALSE) {
|
||||
return ESP_ERR_TIMEOUT;
|
||||
|
@ -1528,13 +1528,15 @@ esp_err_t i2c_master_cmd_begin(i2c_port_t i2c_num, i2c_cmd_handle_t cmd_handle,
|
|||
i2c_cmd_evt_t evt;
|
||||
while (1) {
|
||||
TickType_t wait_time = xTaskGetTickCount();
|
||||
if (wait_time - ticks_start > ticks_to_wait) { // out of time
|
||||
wait_time = I2C_CMD_ALIVE_INTERVAL_TICK;
|
||||
const TickType_t elapsed = wait_time - ticks_start;
|
||||
if (elapsed >= ticks_to_wait) { // out of time
|
||||
/* Before triggering a timeout, empty the queue by giving a wait_time of 0:
|
||||
* - if the queue is empty, `pdFALSE` will be returned and the loop will be exited
|
||||
* - if the queue is not empty, we will pop an element and come back here again
|
||||
*/
|
||||
wait_time = 0;
|
||||
} else {
|
||||
wait_time = ticks_to_wait - (wait_time - ticks_start);
|
||||
if (wait_time < I2C_CMD_ALIVE_INTERVAL_TICK) {
|
||||
wait_time = I2C_CMD_ALIVE_INTERVAL_TICK;
|
||||
}
|
||||
wait_time = MIN(ticks_to_wait - elapsed, I2C_CMD_ALIVE_INTERVAL_TICK);
|
||||
}
|
||||
// In master mode, since we don't have an interrupt to detective bus error or FSM state, what we do here is to make
|
||||
// sure the interrupt mechanism for master mode is still working.
|
||||
|
|
|
@ -1794,7 +1794,7 @@ esp_err_t uart_get_collision_flag(uart_port_t uart_num, bool *collision_flag)
|
|||
esp_err_t uart_set_wakeup_threshold(uart_port_t uart_num, int wakeup_threshold)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE((uart_num < UART_NUM_MAX), ESP_ERR_INVALID_ARG, UART_TAG, "uart_num error");
|
||||
ESP_RETURN_ON_FALSE((wakeup_threshold <= UART_THRESHOLD_NUM(uart_num, UART_ACTIVE_THRESHOLD_V) && wakeup_threshold > UART_MIN_WAKEUP_THRESH), ESP_ERR_INVALID_ARG, UART_TAG,
|
||||
ESP_RETURN_ON_FALSE((wakeup_threshold <= UART_THRESHOLD_NUM(uart_num, UART_ACTIVE_THRESHOLD_V) && wakeup_threshold >= UART_MIN_WAKEUP_THRESH), ESP_ERR_INVALID_ARG, UART_TAG,
|
||||
"wakeup_threshold out of bounds");
|
||||
UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock));
|
||||
uart_hal_set_wakeup_thrd(&(uart_context[uart_num].hal), wakeup_threshold);
|
||||
|
|
|
@ -77,13 +77,15 @@ static esp_err_t dp83848_update_link_duplex_speed(phy_dp83848_t *dp83848)
|
|||
uint32_t peer_pause_ability = false;
|
||||
anlpar_reg_t anlpar;
|
||||
physts_reg_t physts;
|
||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_ANLPAR_REG_ADDR, &(anlpar.val)), err, TAG, "read ANLPAR failed");
|
||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_STS_REG_ADDR, &(physts.val)), err, TAG, "read PHYSTS failed");
|
||||
eth_link_t link = physts.link_status ? ETH_LINK_UP : ETH_LINK_DOWN;
|
||||
bmsr_reg_t bmsr;
|
||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)), err, TAG, "read BMSR failed");
|
||||
eth_link_t link = bmsr.link_status ? ETH_LINK_UP : ETH_LINK_DOWN;
|
||||
/* check if link status changed */
|
||||
if (dp83848->phy_802_3.link_status != link) {
|
||||
/* when link up, read negotiation result */
|
||||
if (link == ETH_LINK_UP) {
|
||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_ANLPAR_REG_ADDR, &(anlpar.val)), err, TAG, "read ANLPAR failed");
|
||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_STS_REG_ADDR, &(physts.val)), err, TAG, "read PHYSTS failed");
|
||||
if (physts.speed_status) {
|
||||
speed = ETH_SPEED_10M;
|
||||
} else {
|
||||
|
|
|
@ -23,6 +23,11 @@ extern "C" {
|
|||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* HID BT Task Size Def */
|
||||
#ifndef BT_HID_DEVICE_TASK_SIZE
|
||||
#define BT_HID_DEVICE_TASK_SIZE 4096
|
||||
#endif
|
||||
|
||||
/* HID Report Map Values */
|
||||
#define HID_RM_INPUT 0x80
|
||||
#define HID_RM_OUTPUT 0x90
|
||||
|
|
|
@ -976,7 +976,7 @@ esp_err_t esp_ble_hidd_dev_init(esp_hidd_dev_t *dev_p, const esp_hid_device_conf
|
|||
.queue_size = 5,
|
||||
.task_name = "ble_hidd_events",
|
||||
.task_priority = uxTaskPriorityGet(NULL),
|
||||
.task_stack_size = 4096,
|
||||
.task_stack_size = BT_HID_DEVICE_TASK_SIZE,
|
||||
.task_core_id = tskNO_AFFINITY
|
||||
};
|
||||
ret = esp_event_loop_create(&event_task_args, &s_dev->event_loop_handle);
|
||||
|
|
|
@ -282,6 +282,12 @@ static void bt_hidd_init_app(void)
|
|||
s_hidd_param.app_param.subclass = get_subclass_by_appearance(s_hidd_param.dev->appearance);
|
||||
s_hidd_param.app_param.desc_list = (uint8_t *)s_hidd_param.dev->devices[0].reports_map.data;
|
||||
s_hidd_param.app_param.desc_list_len = s_hidd_param.dev->devices[0].reports_map.len;
|
||||
|
||||
// Information SDP
|
||||
s_hidd_param.app_param.vendor_id = p_config->vendor_id;
|
||||
s_hidd_param.app_param.product_id = p_config->product_id;
|
||||
s_hidd_param.app_param.version = p_config->version;
|
||||
s_hidd_param.app_param.vendor_id_source = s_hidd_param.app_param.vendor_id_source;
|
||||
}
|
||||
|
||||
static void bt_hidd_init_qos(void)
|
||||
|
@ -812,7 +818,7 @@ esp_err_t esp_bt_hidd_dev_init(esp_hidd_dev_t *dev_p, const esp_hid_device_confi
|
|||
.queue_size = 5,
|
||||
.task_name = "bt_hidd_events",
|
||||
.task_priority = uxTaskPriorityGet(NULL),
|
||||
.task_stack_size = 2048,
|
||||
.task_stack_size = BT_HID_DEVICE_TASK_SIZE,
|
||||
.task_core_id = tskNO_AFFINITY
|
||||
};
|
||||
ret = esp_event_loop_create(&event_task_args, &s_hidd_param.dev->event_loop_handle);
|
||||
|
|
|
@ -10,39 +10,75 @@
|
|||
#include "soc/soc_caps.h"
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "esp_check.h"
|
||||
#if CONFIG_GDMA_ENABLE_DEBUG_LOG
|
||||
// The local log level must be defined before including esp_log.h
|
||||
// Set the maximum log level for this source file
|
||||
#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
|
||||
#endif
|
||||
#include "esp_log.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_private/sleep_retention.h"
|
||||
#include "esp_private/esp_regdma.h"
|
||||
|
||||
#include "sleep_gdma_retention_context.inc"
|
||||
#include "hal/gdma_ll.h"
|
||||
|
||||
static const char *TAG = "gdma";
|
||||
|
||||
#define SLEEP_RETENTION_MODULE_GDMA_CH(group_id, pair_id) (SLEEP_RETENTION_MODULE_GDMA_CH0 << (SOC_GDMA_PAIRS_PER_GROUP_MAX * group_id) << pair_id)
|
||||
typedef struct {
|
||||
int group_id;
|
||||
int pair_id;
|
||||
} gdma_channel_retention_arg_t;
|
||||
|
||||
static esp_err_t sleep_modem_gdma_channel_retention_init(sleep_retention_module_bitmap_t module)
|
||||
typedef struct gdma_chx_reg_ctx_link {
|
||||
const sleep_retention_entries_config_t *link_list;
|
||||
uint32_t link_num;
|
||||
} gdma_chx_reg_ctx_link_t;
|
||||
|
||||
#include "sleep_gdma_retention_context.inc"
|
||||
|
||||
static esp_err_t sleep_gdma_channel_retention_init(void *arg)
|
||||
{
|
||||
uint32_t id = __builtin_ctz(module / SLEEP_RETENTION_MODULE_GDMA_CH0);
|
||||
esp_err_t err = sleep_retention_entries_create(gdma_chx_regs_retention[id].link_list, gdma_chx_regs_retention[id].link_num, REGDMA_LINK_PRI_7, module);
|
||||
gdma_channel_retention_arg_t *parg = (gdma_channel_retention_arg_t *)arg;
|
||||
int group_id = parg->group_id;
|
||||
int pair_id = parg->pair_id;
|
||||
|
||||
sleep_retention_module_bitmap_t module = GDMA_CH_RETENTION_GET_MODULE_ID(group_id, pair_id);
|
||||
esp_err_t err = sleep_retention_entries_create(gdma_chx_regs_retention[group_id][pair_id].link_list, gdma_chx_regs_retention[group_id][pair_id].link_num, REGDMA_LINK_PRI_7, module);
|
||||
if (err == ESP_OK) {
|
||||
int group_id = id / SOC_GDMA_PAIRS_PER_GROUP_MAX;
|
||||
int pair_id = id % SOC_GDMA_PAIRS_PER_GROUP_MAX;
|
||||
ESP_LOGI(TAG, "GDMA pair (%d, %d) retention initialization", group_id, pair_id);
|
||||
ESP_LOGD(TAG, "GDMA pair (%d, %d) retention initialization", group_id, pair_id);
|
||||
}
|
||||
|
||||
ESP_RETURN_ON_ERROR(err, TAG, "Failed to create sleep retention linked list for GDMA pair (%d, %d) retention", group_id, pair_id);
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t gdma_sleep_retention_init(int group_id, int pair_id)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
err = sleep_modem_gdma_channel_retention_init(SLEEP_RETENTION_MODULE_GDMA_CH(group_id, pair_id));
|
||||
ESP_RETURN_ON_ERROR(err, TAG, "Failed to create sleep retention linked list for GDMA pair (%d, %d) retention", group_id, pair_id);
|
||||
gdma_channel_retention_arg_t arg = { .group_id = group_id, .pair_id = pair_id };
|
||||
sleep_retention_module_init_param_t init_param = {
|
||||
.cbs = { .create = { .handle = sleep_gdma_channel_retention_init, .arg = &arg } },
|
||||
.depends = BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM)
|
||||
};
|
||||
sleep_retention_module_bitmap_t module = GDMA_CH_RETENTION_GET_MODULE_ID(group_id, pair_id);
|
||||
esp_err_t err = sleep_retention_module_init(module, &init_param);
|
||||
if (err == ESP_OK) {
|
||||
err = sleep_retention_module_allocate(module);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "Failed to allocate sleep retention linked list for GDMA retention");
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t gdma_sleep_retention_deinit(int group_id, int pair_id)
|
||||
{
|
||||
sleep_retention_entries_destroy(SLEEP_RETENTION_MODULE_GDMA_CH(group_id, pair_id));
|
||||
return ESP_OK;;
|
||||
esp_err_t err = sleep_retention_module_free(GDMA_CH_RETENTION_GET_MODULE_ID(group_id, pair_id));
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "GDMA pair (%d, %d) retention destroy failed", group_id, pair_id);
|
||||
}
|
||||
err = sleep_retention_module_deinit(GDMA_CH_RETENTION_GET_MODULE_ID(group_id, pair_id));
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "GDMA pair (%d, %d) retention deinit failed", group_id, pair_id);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -578,11 +578,11 @@ void regdma_link_stats(void *link, int entry);
|
|||
void regdma_link_set_write_wait_content(void *link, uint32_t value, uint32_t mask);
|
||||
|
||||
/**
|
||||
* @brief Print all node information of the REGDMA linked list indicated by the entry argument
|
||||
* @brief Dump all node information of the REGDMA linked list indicated by the entry argument
|
||||
* @param link The REGDMA linkded list head pointer
|
||||
* @param entry For nodes that support branching, use the branch specified by entry argument recursively
|
||||
*/
|
||||
void regdma_link_show_memories(void *link, int entry);
|
||||
void regdma_link_dump(FILE *out, void *link, int entry);
|
||||
|
||||
/**
|
||||
* @brief Update REGDMA linked list node next pointers
|
||||
|
@ -625,7 +625,7 @@ void *regdma_find_module_link_tail(void *link, void *tail, int entry, uint32_t m
|
|||
|
||||
/**
|
||||
* @brief Find the tail node of the previous module of the specified module in the REGDMA linked list
|
||||
* indicated by the entry argument starting from the link argment to the end of the tail argument
|
||||
* indicated by the entry argument starting from the link argument to the end of the tail argument
|
||||
* @param link The REGDMA linkded list head pointer
|
||||
* @param tail The REGDMA linkded list tail pointer
|
||||
* @param entry For nodes that support branching, use the branch specified by entry argument recursively
|
||||
|
@ -636,7 +636,7 @@ void *regdma_find_prev_module_link_tail(void *link, void *tail, int entry, uint3
|
|||
|
||||
/**
|
||||
* @brief Find the head node of the next module of the specified module in the REGDMA linked list
|
||||
* indicated by the entry argument starting from the link argment to the end of the tail argument
|
||||
* indicated by the entry argument starting from the link argument to the end of the tail argument
|
||||
* @param link The REGDMA linkded list head pointer
|
||||
* @param tail The REGDMA linkded list tail pointer
|
||||
* @param entry For nodes that support branching, use the branch specified by entry argument recursively
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -31,34 +31,6 @@ extern "C" {
|
|||
*/
|
||||
bool clock_domain_pd_allowed(void);
|
||||
|
||||
/**
|
||||
* @brief PCR module power down initialize
|
||||
*
|
||||
* @return ESP_OK on success
|
||||
* ESP_ERR_INVALID_ARG on invalid sleep_retention_entries_create args
|
||||
* No memory for the retention link
|
||||
*/
|
||||
esp_err_t sleep_clock_system_retention_init(void);
|
||||
|
||||
/**
|
||||
* @brief PCR module power down deinitialize
|
||||
*/
|
||||
void sleep_clock_system_retention_deinit(void);
|
||||
|
||||
/**
|
||||
* @brief Modem syscon module power down initialize
|
||||
*
|
||||
* @return ESP_OK on success
|
||||
* ESP_ERR_INVALID_ARG on invalid sleep_retention_entries_create args
|
||||
* No memory for the retention link
|
||||
*/
|
||||
esp_err_t sleep_clock_modem_retention_init(void);
|
||||
|
||||
/**
|
||||
* @brief Modem syscon module power down deinitialize
|
||||
*/
|
||||
void sleep_clock_modem_retention_deinit(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -23,34 +23,55 @@ extern "C" {
|
|||
* includes sleep retention list creation, destruction and debugging interfaces.
|
||||
*/
|
||||
|
||||
typedef enum sleep_retention_module_bitmap {
|
||||
typedef enum sleep_retention_module {
|
||||
SLEEP_RETENTION_MODULE_MIN = 0,
|
||||
/* clock module, which includes system and modem */
|
||||
SLEEP_RETENTION_MODULE_CLOCK_SYSTEM = BIT(1),
|
||||
SLEEP_RETENTION_MODULE_CLOCK_MODEM = BIT(2),
|
||||
SLEEP_RETENTION_MODULE_CLOCK_SYSTEM = 1,
|
||||
SLEEP_RETENTION_MODULE_CLOCK_MODEM = 2,
|
||||
|
||||
/* modem module, which includes WiFi, BLE and 802.15.4 */
|
||||
SLEEP_RETENTION_MODULE_WIFI_MAC = BIT(10),
|
||||
SLEEP_RETENTION_MODULE_WIFI_BB = BIT(11),
|
||||
SLEEP_RETENTION_MODULE_BLE_MAC = BIT(12),
|
||||
SLEEP_RETENTION_MODULE_BT_BB = BIT(13),
|
||||
SLEEP_RETENTION_MODULE_802154_MAC = BIT(14),
|
||||
SLEEP_RETENTION_MODULE_WIFI_MAC = 10,
|
||||
SLEEP_RETENTION_MODULE_WIFI_BB = 11,
|
||||
SLEEP_RETENTION_MODULE_BLE_MAC = 12,
|
||||
SLEEP_RETENTION_MODULE_BT_BB = 13,
|
||||
SLEEP_RETENTION_MODULE_802154_MAC = 14,
|
||||
|
||||
/* digital peripheral module, which includes Interrupt Matrix, HP_SYSTEM,
|
||||
* TEE, APM, UART, Timer Group, IOMUX, SPIMEM, SysTimer, etc.. */
|
||||
SLEEP_RETENTION_MODULE_INTR_MATRIX = BIT(16),
|
||||
SLEEP_RETENTION_MODULE_HP_SYSTEM = BIT(17),
|
||||
SLEEP_RETENTION_MODULE_TEE_APM = BIT(18),
|
||||
SLEEP_RETENTION_MODULE_UART0 = BIT(19),
|
||||
SLEEP_RETENTION_MODULE_TG0 = BIT(20),
|
||||
SLEEP_RETENTION_MODULE_IOMUX = BIT(21),
|
||||
SLEEP_RETENTION_MODULE_SPIMEM = BIT(22),
|
||||
SLEEP_RETENTION_MODULE_SYSTIMER = BIT(23),
|
||||
SLEEP_RETENTION_MODULE_GDMA_CH0 = BIT(24),
|
||||
SLEEP_RETENTION_MODULE_GDMA_CH1 = BIT(25),
|
||||
SLEEP_RETENTION_MODULE_GDMA_CH2 = BIT(26),
|
||||
SLEEP_RETENTION_MODULE_SYS_PERIPH = 16,
|
||||
|
||||
SLEEP_RETENTION_MODULE_ADC = 17,
|
||||
|
||||
SLEEP_RETENTION_MODULE_ALL = (uint32_t)-1
|
||||
SLEEP_RETENTION_MODULE_GDMA_CH0 = 24,
|
||||
SLEEP_RETENTION_MODULE_GDMA_CH1 = 25,
|
||||
SLEEP_RETENTION_MODULE_GDMA_CH2 = 26,
|
||||
|
||||
SLEEP_RETENTION_MODULE_MAX = 31
|
||||
} sleep_retention_module_t;
|
||||
|
||||
typedef enum sleep_retention_module_bitmap {
|
||||
/* clock module, which includes system and modem */
|
||||
SLEEP_RETENTION_MODULE_BM_CLOCK_SYSTEM = BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM),
|
||||
SLEEP_RETENTION_MODULE_BM_CLOCK_MODEM = BIT(SLEEP_RETENTION_MODULE_CLOCK_MODEM),
|
||||
|
||||
/* 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),
|
||||
SLEEP_RETENTION_MODULE_BM_BLE_MAC = BIT(SLEEP_RETENTION_MODULE_BLE_MAC),
|
||||
SLEEP_RETENTION_MODULE_BM_BT_BB = BIT(SLEEP_RETENTION_MODULE_BT_BB),
|
||||
SLEEP_RETENTION_MODULE_BM_802154_MAC = BIT(SLEEP_RETENTION_MODULE_802154_MAC),
|
||||
|
||||
/* digital peripheral module, which includes Interrupt Matrix, HP_SYSTEM,
|
||||
* TEE, APM, UART, Timer Group, IOMUX, SPIMEM, SysTimer, etc.. */
|
||||
SLEEP_RETENTION_MODULE_BM_SYS_PERIPH = BIT(SLEEP_RETENTION_MODULE_SYS_PERIPH),
|
||||
|
||||
SLEEP_RETENTION_MODULE_BM_ADC = BIT(SLEEP_RETENTION_MODULE_ADC),
|
||||
|
||||
SLEEP_RETENTION_MODULE_BM_GDMA_CH0 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH0),
|
||||
SLEEP_RETENTION_MODULE_BM_GDMA_CH1 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH1),
|
||||
SLEEP_RETENTION_MODULE_BM_GDMA_CH2 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH2),
|
||||
|
||||
SLEEP_RETENTION_MODULE_BM_ALL = (uint32_t)-1
|
||||
} sleep_retention_module_bitmap_t;
|
||||
|
||||
typedef regdma_entry_buf_t sleep_retention_entries_t;
|
||||
|
@ -60,6 +81,21 @@ typedef struct {
|
|||
uint32_t owner; /**< Indicates which regdma entries the current node will insert into */
|
||||
} sleep_retention_entries_config_t;
|
||||
|
||||
typedef esp_err_t (*sleep_retention_callback_t)(void *args);
|
||||
|
||||
typedef struct {
|
||||
sleep_retention_callback_t handle;
|
||||
void *arg;
|
||||
} sleep_retention_create_callback_t;
|
||||
|
||||
typedef struct {
|
||||
sleep_retention_create_callback_t create; /*!< A function handle is used to register the implementation of creating a sleep retention linked list and is executed when the corresponding module is created */
|
||||
} sleep_retention_module_callbacks_t;
|
||||
|
||||
typedef enum {
|
||||
SLEEP_RETENTION_MODULE_ATTR_PASSIVE = 0x1
|
||||
} sleep_retention_module_attribute_t;
|
||||
|
||||
/**
|
||||
* @brief Create a runtime sleep retention linked list
|
||||
*
|
||||
|
@ -67,26 +103,19 @@ typedef struct {
|
|||
* @param num the total number of sleep retention linked list configuration
|
||||
* items
|
||||
* @param priority the priority of the created sleep retention linked list
|
||||
* @param module the bitmap of the module to which the created sleep retention
|
||||
* @param module the number of the module to which the created sleep retention
|
||||
* linked list belongs
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_NO_MEM not enough memory for sleep retention
|
||||
* - ESP_ERR_INVALID_ARG if either of the arguments is out of range
|
||||
*/
|
||||
esp_err_t sleep_retention_entries_create(const sleep_retention_entries_config_t retent[], int num, regdma_link_priority_t priority, int module);
|
||||
esp_err_t sleep_retention_entries_create(const sleep_retention_entries_config_t retent[], int num, regdma_link_priority_t priority, sleep_retention_module_t module);
|
||||
|
||||
/**
|
||||
* @brief Destroy a runtime sleep retention linked list
|
||||
*
|
||||
* @param module the bitmap of the module to be destroyed
|
||||
* @brief Dump all runtime sleep retention linked lists
|
||||
*/
|
||||
void sleep_retention_entries_destroy(int module);
|
||||
|
||||
/**
|
||||
* @brief Print all runtime sleep retention linked lists
|
||||
*/
|
||||
void sleep_retention_entries_show_memories(void);
|
||||
void sleep_retention_dump_entries(FILE *out);
|
||||
|
||||
/**
|
||||
* @brief Find the linked list node with the unique id
|
||||
|
@ -104,6 +133,90 @@ void * sleep_retention_find_link_by_id(int id);
|
|||
*/
|
||||
void sleep_retention_entries_get(sleep_retention_entries_t *entries);
|
||||
|
||||
typedef struct sleep_retention_module_init_param {
|
||||
sleep_retention_module_callbacks_t cbs; /*!< The callbacks list of the initialize module */
|
||||
sleep_retention_module_attribute_t attribute; /*!< A bitmap indicating attribute of the initialize module */
|
||||
sleep_retention_module_bitmap_t depends; /*!< A bitmap identifying all modules that the current module depends on */
|
||||
} sleep_retention_module_init_param_t;
|
||||
|
||||
/**
|
||||
* @brief sleep retention initialization for the module
|
||||
*
|
||||
* @param module the module number that needs initialization
|
||||
* @param param the initialize parameters for module sleep retention initialization
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_NO_MEM not enough memory for sleep retention
|
||||
* - ESP_ERR_INVALID_ARG if either of the arguments is out of range
|
||||
* - ESP_ERR_INVALID_STATE if the retention context of module already been allocated
|
||||
*/
|
||||
esp_err_t sleep_retention_module_init(sleep_retention_module_t module, sleep_retention_module_init_param_t *param);
|
||||
|
||||
/**
|
||||
* @brief sleep retention de-initialization for the module
|
||||
*
|
||||
* @param module the module number that needs de-initialization
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_INVALID_ARG if either of the arguments is out of range
|
||||
* - ESP_ERR_INVALID_STATE if the retention context of module already been allocated
|
||||
*/
|
||||
esp_err_t sleep_retention_module_deinit(sleep_retention_module_t module);
|
||||
|
||||
/**
|
||||
* @brief Allocate the sleep retention context for the module
|
||||
*
|
||||
* @param module the module number that need to allocating sleep retention context
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_NO_MEM not enough memory for sleep retention
|
||||
* - ESP_ERR_INVALID_ARG if either of the arguments is out of range
|
||||
* - ESP_ERR_INVALID_STATE if the module is de-initialized
|
||||
* - ESP_ERR_NOT_ALLOWED if the attribute of module is set to SLEEP_RETENTION_MODULE_ATTR_PASSIVE
|
||||
*/
|
||||
esp_err_t sleep_retention_module_allocate(sleep_retention_module_t module);
|
||||
|
||||
/**
|
||||
* @brief Free the sleep retention context for the module
|
||||
*
|
||||
* @param module the module number that need to free sleep retention context
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_INVALID_ARG if either of the arguments is out of range
|
||||
* - ESP_ERR_INVALID_STATE if the module is de-initialized
|
||||
* - ESP_ERR_NOT_ALLOWED if the attribute of module is set to SLEEP_RETENTION_MODULE_ATTR_PASSIVE
|
||||
*/
|
||||
esp_err_t sleep_retention_module_free(sleep_retention_module_t module);
|
||||
|
||||
/**
|
||||
* @brief Get all initialized modules that require sleep retention
|
||||
*
|
||||
* This is an unprotected interface for getting a bitmap of all modules that
|
||||
* require sleep retention.
|
||||
*
|
||||
* It can only be called by the sleep procedure.
|
||||
*
|
||||
* @return the bitmap for all modules that require sleep retention
|
||||
*/
|
||||
uint32_t sleep_retention_get_inited_modules(void);
|
||||
|
||||
/**
|
||||
* @brief Get all created modules that require sleep retention
|
||||
*
|
||||
* This is an unprotected interface for getting a bitmap of all modules that
|
||||
* require sleep retention.
|
||||
*
|
||||
* It can only be called by the sleep procedure.
|
||||
*
|
||||
* @return the bitmap for all modules that have successfully created a sleep
|
||||
* retention context
|
||||
*/
|
||||
uint32_t sleep_retention_get_created_modules(void);
|
||||
|
||||
#if SOC_PM_RETENTION_HAS_CLOCK_BUG
|
||||
/**
|
||||
* @brief Software trigger REGDMA to do extra linked list retention
|
||||
|
@ -114,18 +227,6 @@ void sleep_retention_entries_get(sleep_retention_entries_t *entries);
|
|||
void sleep_retention_do_extra_retention(bool backup_or_restore);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Get all registered modules that require sleep retention
|
||||
*
|
||||
* This is an unprotected interface for getting a bitmap of all modules that
|
||||
* require sleep retention.
|
||||
*
|
||||
* It can only be called by the sleep procedure.
|
||||
*
|
||||
* @return the bitmap of all modules requiring sleep retention
|
||||
*/
|
||||
uint32_t sleep_retention_get_modules(void);
|
||||
|
||||
#if SOC_PM_RETENTION_SW_TRIGGER_REGDMA
|
||||
/**
|
||||
* @brief Software trigger REGDMA to do system linked list retention
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -29,15 +29,6 @@ extern "C" {
|
|||
*/
|
||||
bool peripheral_domain_pd_allowed(void);
|
||||
|
||||
/**
|
||||
* @brief Digital peripheral power down initialize
|
||||
*
|
||||
* @return ESP_OK on success
|
||||
* ESP_ERR_INVALID_ARG on invalid sleep_retention_entries_create args
|
||||
* No memory for the retention link
|
||||
*/
|
||||
void sleep_sys_periph_retention_init(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "esp_private/esp_pmu.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "hal/efuse_hal.h"
|
||||
#include "hal/clk_tree_ll.h"
|
||||
|
||||
// Please define the frequently called modules in the low bit,
|
||||
// which will improve the execution efficiency
|
||||
|
@ -354,10 +355,29 @@ void modem_clock_select_lp_clock_source(periph_module_t module, modem_clock_lpcl
|
|||
|
||||
#if SOC_BT_SUPPORTED
|
||||
case PERIPH_BT_MODULE:
|
||||
#if CONFIG_IDF_TARGET_ESP32H2
|
||||
bool rc_clk_en = true;
|
||||
bool selected = (src == MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL) ||
|
||||
(src == MODEM_CLOCK_LPCLK_SRC_RC_SLOW);
|
||||
if (selected) {
|
||||
rc_clk_en = clk_ll_rc32k_is_enabled();
|
||||
if (!rc_clk_en) {
|
||||
clk_ll_rc32k_enable();
|
||||
}
|
||||
modem_clock_hal_select_ble_rtc_timer_lpclk_source(MODEM_CLOCK_instance()->hal, MODEM_CLOCK_LPCLK_SRC_RC32K);
|
||||
}
|
||||
#endif // CONFIG_IDF_TARGET_ESP32H2
|
||||
modem_clock_hal_deselect_all_ble_rtc_timer_lpclk_source(MODEM_CLOCK_instance()->hal);
|
||||
modem_clock_hal_select_ble_rtc_timer_lpclk_source(MODEM_CLOCK_instance()->hal, src);
|
||||
modem_clock_hal_set_ble_rtc_timer_divisor_value(MODEM_CLOCK_instance()->hal, divider);
|
||||
modem_clock_hal_enable_ble_rtc_timer_clock(MODEM_CLOCK_instance()->hal, true);
|
||||
#if CONFIG_IDF_TARGET_ESP32H2
|
||||
if (!rc_clk_en) {
|
||||
extern void esp_ble_rtc_ticks_delay(uint32_t ticks);
|
||||
esp_ble_rtc_ticks_delay(2);
|
||||
clk_ll_rc32k_disable();
|
||||
}
|
||||
#endif // CONFIG_IDF_TARGET_ESP32H2
|
||||
#if SOC_BLE_USE_WIFI_PWR_CLK_WORKAROUND
|
||||
if (efuse_hal_chip_revision() != 0) {
|
||||
if (src == MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL) {
|
||||
|
|
|
@ -50,32 +50,31 @@ static const sleep_retention_entries_config_t gdma_g0p1_regs_retention[] = {
|
|||
GDMA_IN_CONF0_CH2_REG / GDMA_IN_CONF1_CH2_REG / GDMA_IN_LINK_CH2_REG / GDMA_IN_PRI_CH2_REG
|
||||
GDMA_OUT_CONF0_CH2_REG / GDMA_OUT_CONF1_CH2_REG / GDMA_OUT_LINK_CH2_REG /GDMA_OUT_PRI_CH2_REG
|
||||
*/
|
||||
#define G0P1_RETENTION_REGS_CNT_0 6
|
||||
#define G0P2_RETENTION_REGS_CNT_0 6
|
||||
#define G0P2_RETENTION_MAP_BASE_0 GDMA_IN_INT_ENA_CH2_REG
|
||||
#define G0P1_RETENTION_REGS_CNT_1 7
|
||||
#define G0P2_RETENTION_REGS_CNT_1 7
|
||||
#define G0P2_RETENTION_MAP_BASE_1 GDMA_IN_PRI_CH2_REG
|
||||
static const uint32_t g0p2_regs_map0[4] = {0x9001, 0, 0, 0x4C0000};
|
||||
static const uint32_t g0p2_regs_map1[4] = {0x3026003, 0, 0, 0};
|
||||
static const sleep_retention_entries_config_t gdma_g0p2_regs_retention[] = {
|
||||
[0] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_MODEM_GDMA_LINK(0x00), \
|
||||
G0P2_RETENTION_MAP_BASE_0, G0P2_RETENTION_MAP_BASE_0, \
|
||||
G0P1_RETENTION_REGS_CNT_0, 0, 0, \
|
||||
G0P2_RETENTION_REGS_CNT_0, 0, 0, \
|
||||
g0p2_regs_map0[0], g0p2_regs_map0[1], \
|
||||
g0p2_regs_map0[2], g0p2_regs_map0[3]), \
|
||||
.owner = ENTRY(0) | ENTRY(2) },
|
||||
[1] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_MODEM_GDMA_LINK(0x00), \
|
||||
G0P2_RETENTION_MAP_BASE_1, G0P2_RETENTION_MAP_BASE_1, \
|
||||
G0P1_RETENTION_REGS_CNT_1, 0, 0, \
|
||||
G0P2_RETENTION_REGS_CNT_1, 0, 0, \
|
||||
g0p2_regs_map1[0], g0p2_regs_map1[1], \
|
||||
g0p2_regs_map1[2], g0p2_regs_map1[3]), \
|
||||
.owner = ENTRY(0) | ENTRY(2) },
|
||||
};
|
||||
|
||||
static const struct {
|
||||
const sleep_retention_entries_config_t *link_list;
|
||||
uint32_t link_num;
|
||||
} gdma_chx_regs_retention[SOC_GDMA_PAIRS_PER_GROUP_MAX*SOC_GDMA_PAIRS_PER_GROUP_MAX] = {
|
||||
[0] = {gdma_g0p0_regs_retention, ARRAY_SIZE(gdma_g0p0_regs_retention)},
|
||||
[1] = {gdma_g0p1_regs_retention, ARRAY_SIZE(gdma_g0p1_regs_retention)},
|
||||
[2] = {gdma_g0p2_regs_retention, ARRAY_SIZE(gdma_g0p2_regs_retention)}
|
||||
const gdma_chx_reg_ctx_link_t gdma_chx_regs_retention[SOC_GDMA_NUM_GROUPS_MAX][SOC_GDMA_PAIRS_PER_GROUP_MAX] = {
|
||||
[0] = {
|
||||
[0] = {gdma_g0p0_regs_retention, ARRAY_SIZE(gdma_g0p0_regs_retention)},
|
||||
[1] = {gdma_g0p1_regs_retention, ARRAY_SIZE(gdma_g0p1_regs_retention)},
|
||||
[2] = {gdma_g0p2_regs_retention, ARRAY_SIZE(gdma_g0p2_regs_retention)}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -50,32 +50,31 @@ static const sleep_retention_entries_config_t gdma_g0p1_regs_retention[] = {
|
|||
GDMA_IN_CONF0_CH2_REG / GDMA_IN_CONF1_CH2_REG / GDMA_IN_LINK_CH2_REG / GDMA_IN_PRI_CH2_REG
|
||||
GDMA_OUT_CONF0_CH2_REG / GDMA_OUT_CONF1_CH2_REG / GDMA_OUT_LINK_CH2_REG /GDMA_OUT_PRI_CH2_REG
|
||||
*/
|
||||
#define G0P1_RETENTION_REGS_CNT_0 6
|
||||
#define G0P2_RETENTION_REGS_CNT_0 6
|
||||
#define G0P2_RETENTION_MAP_BASE_0 GDMA_IN_INT_ENA_CH2_REG
|
||||
#define G0P1_RETENTION_REGS_CNT_1 7
|
||||
#define G0P2_RETENTION_REGS_CNT_1 7
|
||||
#define G0P2_RETENTION_MAP_BASE_1 GDMA_IN_PRI_CH2_REG
|
||||
static const uint32_t g0p2_regs_map0[4] = {0x9001, 0, 0, 0x4C0000};
|
||||
static const uint32_t g0p2_regs_map1[4] = {0x3026003, 0, 0, 0};
|
||||
static const sleep_retention_entries_config_t gdma_g0p2_regs_retention[] = {
|
||||
[0] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_MODEM_GDMA_LINK(0x00), \
|
||||
G0P2_RETENTION_MAP_BASE_0, G0P2_RETENTION_MAP_BASE_0, \
|
||||
G0P1_RETENTION_REGS_CNT_0, 0, 0, \
|
||||
G0P2_RETENTION_REGS_CNT_0, 0, 0, \
|
||||
g0p2_regs_map0[0], g0p2_regs_map0[1], \
|
||||
g0p2_regs_map0[2], g0p2_regs_map0[3]), \
|
||||
.owner = ENTRY(0) | ENTRY(2) },
|
||||
[1] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_MODEM_GDMA_LINK(0x00), \
|
||||
G0P2_RETENTION_MAP_BASE_1, G0P2_RETENTION_MAP_BASE_1, \
|
||||
G0P1_RETENTION_REGS_CNT_1, 0, 0, \
|
||||
G0P2_RETENTION_REGS_CNT_1, 0, 0, \
|
||||
g0p2_regs_map1[0], g0p2_regs_map1[1], \
|
||||
g0p2_regs_map1[2], g0p2_regs_map1[3]), \
|
||||
.owner = ENTRY(0) | ENTRY(2) },
|
||||
};
|
||||
|
||||
static const struct {
|
||||
const sleep_retention_entries_config_t *link_list;
|
||||
uint32_t link_num;
|
||||
} gdma_chx_regs_retention[SOC_GDMA_PAIRS_PER_GROUP_MAX*SOC_GDMA_PAIRS_PER_GROUP_MAX] = {
|
||||
[0] = {gdma_g0p0_regs_retention, ARRAY_SIZE(gdma_g0p0_regs_retention)},
|
||||
[1] = {gdma_g0p1_regs_retention, ARRAY_SIZE(gdma_g0p1_regs_retention)},
|
||||
[2] = {gdma_g0p2_regs_retention, ARRAY_SIZE(gdma_g0p2_regs_retention)}
|
||||
const gdma_chx_reg_ctx_link_t gdma_chx_regs_retention[SOC_GDMA_NUM_GROUPS_MAX][SOC_GDMA_PAIRS_PER_GROUP_MAX] = {
|
||||
[0] = {
|
||||
[0] = {gdma_g0p0_regs_retention, ARRAY_SIZE(gdma_g0p0_regs_retention)},
|
||||
[1] = {gdma_g0p1_regs_retention, ARRAY_SIZE(gdma_g0p1_regs_retention)},
|
||||
[2] = {gdma_g0p2_regs_retention, ARRAY_SIZE(gdma_g0p2_regs_retention)}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -698,71 +698,81 @@ void * regdma_find_prev_module_link_tail(void *link, void *tail, int entry, uint
|
|||
}
|
||||
|
||||
#if REGDMA_LINK_DBG
|
||||
static const char *TAG = "regdma_link";
|
||||
static __attribute__((unused)) const char *TAG = "regdma_link";
|
||||
|
||||
static void print_info_continuous_wrapper(void *link)
|
||||
static void print_info_link_data(FILE *out, const uint32_t buf[], int len)
|
||||
{
|
||||
for (int i = 0; i < len; i++) {
|
||||
fprintf(out, ((i + 1) % 8) ? "%08lx " : "%08lx\n", buf[i]);
|
||||
}
|
||||
if (len % 8) {
|
||||
fprintf(out, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void print_info_continuous_wrapper(FILE *out, void *link)
|
||||
{
|
||||
regdma_link_head_t head = REGDMA_LINK_HEAD(link);
|
||||
regdma_link_continuous_t *cons = __containerof(link, regdma_link_continuous_t, head);
|
||||
ESP_EARLY_LOGI(TAG, "[%08x/%04x] link:%x, head:%x, next:%x, backup:%x, restore:%x, buff:%x",
|
||||
cons->stat.module, cons->stat.id, link, cons->head, cons->body.next,
|
||||
fprintf(out, "[%08lx/%04x] link:%p, head:%lx, next:%p, backup:%p, restore:%p, buff:%p\n",
|
||||
cons->stat.module, cons->stat.id, link, *(uint32_t *)&cons->head, cons->body.next,
|
||||
cons->body.backup, cons->body.restore, cons->body.mem);
|
||||
ESP_LOG_BUFFER_HEX(TAG, (const void *)cons->body.mem, head.length);
|
||||
print_info_link_data(out, (const uint32_t *)cons->body.mem, head.length);
|
||||
}
|
||||
|
||||
static void print_info_addr_map_wrapper(void *link)
|
||||
static void print_info_addr_map_wrapper(FILE *out, void *link)
|
||||
{
|
||||
regdma_link_head_t head = REGDMA_LINK_HEAD(link);
|
||||
regdma_link_addr_map_t *map = __containerof(link, regdma_link_addr_map_t, head);
|
||||
ESP_EARLY_LOGI(TAG, "[%08x/%04x] link:%x, head:%x, next:%x, backup:%x, restore:%x, buff:%x, map:{%x,%x,%x,%x}",
|
||||
map->stat.module, map->stat.id, link, map->head, map->body.next, map->body.backup,
|
||||
fprintf(out, "[%08lx/%04x] link:%p, head:%lx, next:%p, backup:%p, restore:%p, buff:%p, map:{%lx,%lx,%lx,%lx}\n",
|
||||
map->stat.module, map->stat.id, link, *(uint32_t *)&map->head, map->body.next, map->body.backup,
|
||||
map->body.restore, map->body.mem, map->body.map[0], map->body.map[1],
|
||||
map->body.map[2], map->body.map[3]);
|
||||
ESP_LOG_BUFFER_HEX(TAG, (const void *)map->body.mem, head.length);
|
||||
print_info_link_data(out, (const uint32_t *)map->body.mem, head.length);
|
||||
}
|
||||
|
||||
static void print_info_write_wait_wrapper(void *link)
|
||||
static void print_info_write_wait_wrapper(FILE *out, void *link)
|
||||
{
|
||||
regdma_link_write_wait_t *ww = __containerof(link, regdma_link_write_wait_t, head);
|
||||
ESP_EARLY_LOGI(TAG, "[%08x/%04x] link:%x, head:%x, next:%x, backup:%x, value:%x, mask:%x",
|
||||
ww->stat.module, ww->stat.id, link, ww->head, ww->body.next,
|
||||
fprintf(out, "[%08lx/%04x] link:%p, head:%lx, next:%p, backup:%p, value:%lx, mask:%lx\n",
|
||||
ww->stat.module, ww->stat.id, link, *(uint32_t *)&ww->head, ww->body.next,
|
||||
ww->body.backup, ww->body.value, ww->body.mask);
|
||||
}
|
||||
|
||||
static void print_info_branch_continuous_wrapper(void *link)
|
||||
static void print_info_branch_continuous_wrapper(FILE *out, void *link)
|
||||
{
|
||||
regdma_link_head_t head = REGDMA_LINK_HEAD(link);
|
||||
regdma_link_branch_continuous_t *cons = __containerof(link, regdma_link_branch_continuous_t, head);
|
||||
ESP_EARLY_LOGI(TAG, "[%08x/%04x] link:%x, head:%x, next:{%x,%x,%x,%x}, backup:%x, restore:%x, buff:%x",
|
||||
cons->stat.module, cons->stat.id, link, cons->head, cons->body.next[0], cons->body.next[1],
|
||||
fprintf(out, "[%08lx/%04x] link:%p, head:%lx, next:{%p,%p,%p,%p}, backup:%p, restore:%p, buff:%p\n",
|
||||
cons->stat.module, cons->stat.id, link, *(uint32_t *)&cons->head, cons->body.next[0], cons->body.next[1],
|
||||
cons->body.next[2], cons->body.next[3], cons->body.backup, cons->body.restore,
|
||||
cons->body.mem);
|
||||
ESP_LOG_BUFFER_HEX(TAG, (const void *)cons->body.mem, head.length);
|
||||
print_info_link_data(out, (const uint32_t *)cons->body.mem, head.length);
|
||||
}
|
||||
|
||||
static void print_info_branch_addr_map_wrapper(void *link)
|
||||
static void print_info_branch_addr_map_wrapper(FILE *out, void *link)
|
||||
{
|
||||
regdma_link_head_t head = REGDMA_LINK_HEAD(link);
|
||||
regdma_link_branch_addr_map_t *map = __containerof(link, regdma_link_branch_addr_map_t, head);
|
||||
ESP_EARLY_LOGI(TAG, "[%08x/%04x] link:%x, head:%x, next:{%x,%x,%x,%x}, backup:%x, restore:%x, buff:%x, map:{%x,%x,%x,%x}",
|
||||
map->stat.module, map->stat.id, link, map->head, map->body.next[0], map->body.next[1], map->body.next[2],
|
||||
fprintf(out, "[%08lx/%04x] link:%p, head:%lx, next:{%p,%p,%p,%p}, backup:%p, restore:%p, buff:%p, map:{%lx,%lx,%lx,%lx}\n",
|
||||
map->stat.module, map->stat.id, link, *(uint32_t *)&map->head, map->body.next[0], map->body.next[1], map->body.next[2],
|
||||
map->body.next[3], map->body.backup, map->body.restore, map->body.mem, map->body.map[0],
|
||||
map->body.map[1], map->body.map[2], map->body.map[3]);
|
||||
ESP_LOG_BUFFER_HEX(TAG, (const void *)map->body.mem, head.length);
|
||||
print_info_link_data(out, (const uint32_t *)map->body.mem, head.length);
|
||||
}
|
||||
|
||||
static void print_info_branch_write_wait_wrapper(void *link)
|
||||
static void print_info_branch_write_wait_wrapper(FILE *out, void *link)
|
||||
{
|
||||
regdma_link_branch_write_wait_t *ww = __containerof(link, regdma_link_branch_write_wait_t, head);
|
||||
ESP_EARLY_LOGI(TAG, "[%08x/%04x] link:%x, head:%x, next:{%x,%x,%x,%x}, backup:%x, value:%x, mask:%x",
|
||||
ww->stat.module, ww->stat.id, link, ww->head, ww->body.next[0], ww->body.next[1],
|
||||
fprintf(out, "[%08lx/%04x] link:%p, head:%lx, next:{%p,%p,%p,%p}, backup:%p, value:%lx, mask:%lx\n",
|
||||
ww->stat.module, ww->stat.id, link, *(uint32_t *)&ww->head, ww->body.next[0], ww->body.next[1],
|
||||
ww->body.next[2], ww->body.next[3], ww->body.backup, ww->body.value,
|
||||
ww->body.mask);
|
||||
}
|
||||
|
||||
static void print_link_info(void *args, int entry, int depth)
|
||||
static void print_link_info(FILE *out, void *args, int entry, int depth)
|
||||
{
|
||||
typedef void (*prinf_fn_t)(void *);
|
||||
typedef void (*prinf_fn_t)(FILE *, void *);
|
||||
|
||||
const static prinf_fn_t prinf_fn[] = {
|
||||
[0] = (prinf_fn_t)print_info_continuous_wrapper,
|
||||
|
@ -779,20 +789,20 @@ static void print_link_info(void *args, int entry, int depth)
|
|||
int it = (head.branch << 2) | head.mode;
|
||||
assert(it < ARRAY_SIZE(prinf_fn));
|
||||
|
||||
(*prinf_fn[it])(args);
|
||||
(*prinf_fn[it])(out, args);
|
||||
}
|
||||
|
||||
void regdma_link_show_memories(void *link, int entry)
|
||||
void regdma_link_dump(FILE *out, void *link, int entry)
|
||||
{
|
||||
assert(entry < REGDMA_LINK_ENTRY_NUM);
|
||||
|
||||
void *next = link;
|
||||
if (link) {
|
||||
do {
|
||||
print_link_info(next, entry, 0);
|
||||
print_link_info(out, next, entry, 0);
|
||||
} while ((next = regdma_link_get_next(next, entry)) != NULL);
|
||||
} else {
|
||||
ESP_EARLY_LOGW(TAG, "This REGDMA linked list is empty!\n");
|
||||
fprintf(out, "This REGDMA linked list is empty!\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -29,7 +29,7 @@
|
|||
|
||||
static __attribute__((unused)) const char *TAG = "sleep_clock";
|
||||
|
||||
esp_err_t sleep_clock_system_retention_init(void)
|
||||
static esp_err_t sleep_clock_system_retention_init(void *arg)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32C6
|
||||
#define N_REGS_PCR() (((PCR_SRAM_POWER_CONF_REG - DR_REG_PCR_BASE) / 4) + 1)
|
||||
|
@ -46,12 +46,8 @@ esp_err_t sleep_clock_system_retention_init(void)
|
|||
return ESP_OK;
|
||||
}
|
||||
|
||||
void sleep_clock_system_retention_deinit(void)
|
||||
{
|
||||
sleep_retention_entries_destroy(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM);
|
||||
}
|
||||
|
||||
esp_err_t sleep_clock_modem_retention_init(void)
|
||||
#if CONFIG_MAC_BB_PD || CONFIG_BT_LE_SLEEP_ENABLE || CONFIG_IEEE802154_SLEEP_ENABLE
|
||||
static esp_err_t sleep_clock_modem_retention_init(void *arg)
|
||||
{
|
||||
#define N_REGS_SYSCON() (((MODEM_SYSCON_MEM_CONF_REG - MODEM_SYSCON_TEST_CONF_REG) / 4) + 1)
|
||||
#if SOC_PM_RETENTION_SW_TRIGGER_REGDMA
|
||||
|
@ -70,34 +66,56 @@ esp_err_t sleep_clock_modem_retention_init(void)
|
|||
ESP_LOGI(TAG, "Modem Power, Clock and Reset sleep retention initialization");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void sleep_clock_modem_retention_deinit(void)
|
||||
{
|
||||
sleep_retention_entries_destroy(SLEEP_RETENTION_MODULE_CLOCK_MODEM);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool 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 || CONFIG_IEEE802154_SLEEP_ENABLE
|
||||
| SLEEP_RETENTION_MODULE_CLOCK_MODEM
|
||||
const uint32_t inited_modules = sleep_retention_get_inited_modules();
|
||||
const uint32_t created_modules = sleep_retention_get_created_modules();
|
||||
const uint32_t sys_clk_dep_modules = (const uint32_t) (BIT(SLEEP_RETENTION_MODULE_SYS_PERIPH));
|
||||
|
||||
/* The clock and reset of MODEM (WiFi, BLE and 15.4) modules are managed
|
||||
* through MODEM_SYSCON, when one or more MODEMs are initialized, it is
|
||||
* necessary to check the state of CLOCK_MODEM to determine MODEM domain on
|
||||
* or off. The clock and reset of digital peripherals are managed through
|
||||
* PCR, with TOP domain similar to MODEM domain. */
|
||||
uint32_t modem_clk_dep_modules = 0;
|
||||
#if SOC_WIFI_SUPPORTED
|
||||
modem_clk_dep_modules |= BIT(SLEEP_RETENTION_MODULE_WIFI_MAC) | BIT(SLEEP_RETENTION_MODULE_WIFI_BB);
|
||||
#endif
|
||||
);
|
||||
return ((modules & mask) == mask);
|
||||
#if SOC_BT_SUPPORTED
|
||||
modem_clk_dep_modules |= BIT(SLEEP_RETENTION_MODULE_BLE_MAC) | BIT(SLEEP_RETENTION_MODULE_BT_BB);
|
||||
#endif
|
||||
#if SOC_IEEE802154_SUPPORTED
|
||||
modem_clk_dep_modules |= BIT(SLEEP_RETENTION_MODULE_802154_MAC) | BIT(SLEEP_RETENTION_MODULE_BT_BB);
|
||||
#endif
|
||||
|
||||
uint32_t mask = 0;
|
||||
if (inited_modules & sys_clk_dep_modules) {
|
||||
mask |= BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM);
|
||||
}
|
||||
if (inited_modules & modem_clk_dep_modules) {
|
||||
#if SOC_WIFI_SUPPORTED || SOC_BT_SUPPORTED || SOC_IEEE802154_SUPPORTED
|
||||
mask |= BIT(SLEEP_RETENTION_MODULE_CLOCK_MODEM);
|
||||
#endif
|
||||
}
|
||||
return ((inited_modules & mask) == (created_modules & mask));
|
||||
}
|
||||
|
||||
#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
|
||||
sleep_retention_module_init_param_t init_param = {
|
||||
.cbs = { .create = { .handle = sleep_clock_system_retention_init, .arg = NULL } },
|
||||
.attribute = SLEEP_RETENTION_MODULE_ATTR_PASSIVE
|
||||
};
|
||||
sleep_retention_module_init(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM, &init_param);
|
||||
|
||||
#if CONFIG_MAC_BB_PD || CONFIG_BT_LE_SLEEP_ENABLE || CONFIG_IEEE802154_SLEEP_ENABLE
|
||||
sleep_clock_modem_retention_init();
|
||||
init_param = (sleep_retention_module_init_param_t) {
|
||||
.cbs = { .create = { .handle = sleep_clock_modem_retention_init, .arg = NULL } },
|
||||
.attribute = SLEEP_RETENTION_MODULE_ATTR_PASSIVE
|
||||
};
|
||||
sleep_retention_module_init(SLEEP_RETENTION_MODULE_CLOCK_MODEM, &init_param);
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
@ -285,16 +285,20 @@ inline __attribute__((always_inline)) bool sleep_modem_wifi_modem_link_done(void
|
|||
bool modem_domain_pd_allowed(void)
|
||||
{
|
||||
#if SOC_PM_MODEM_RETENTION_BY_REGDMA
|
||||
const uint32_t modules = sleep_retention_get_modules();
|
||||
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_BT_BB);
|
||||
const uint32_t mask_154 = (const uint32_t) (SLEEP_RETENTION_MODULE_802154_MAC |
|
||||
SLEEP_RETENTION_MODULE_BT_BB);
|
||||
return (((modules & mask_wifi) == mask_wifi) ||
|
||||
((modules & mask_ble) == mask_ble) ||
|
||||
((modules & mask_154) == mask_154));
|
||||
const uint32_t inited_modules = sleep_retention_get_inited_modules();
|
||||
const uint32_t created_modules = sleep_retention_get_created_modules();
|
||||
|
||||
uint32_t mask = 0;
|
||||
#if SOC_WIFI_SUPPORTED
|
||||
mask |= BIT(SLEEP_RETENTION_MODULE_WIFI_MAC) | BIT(SLEEP_RETENTION_MODULE_WIFI_BB);
|
||||
#endif
|
||||
#if SOC_BT_SUPPORTED
|
||||
mask |= BIT(SLEEP_RETENTION_MODULE_BLE_MAC) | BIT(SLEEP_RETENTION_MODULE_BT_BB);
|
||||
#endif
|
||||
#if SOC_IEEE802154_SUPPORTED
|
||||
mask |= BIT(SLEEP_RETENTION_MODULE_802154_MAC) | BIT(SLEEP_RETENTION_MODULE_BT_BB);
|
||||
#endif
|
||||
return ((inited_modules & mask) == (created_modules & mask));
|
||||
#else
|
||||
return false; /* MODEM power domain is controlled by each module (WiFi, Bluetooth or 15.4) of modem */
|
||||
#endif
|
||||
|
|
|
@ -2084,7 +2084,11 @@ static uint32_t get_power_down_flags(void)
|
|||
#endif
|
||||
|
||||
#if SOC_PM_SUPPORT_MODEM_PD
|
||||
if ((s_config.domain[ESP_PD_DOMAIN_MODEM].pd_option != ESP_PD_OPTION_ON) && modem_domain_pd_allowed()) {
|
||||
if ((s_config.domain[ESP_PD_DOMAIN_MODEM].pd_option != ESP_PD_OPTION_ON) && modem_domain_pd_allowed()
|
||||
#if SOC_PM_MODEM_RETENTION_BY_REGDMA
|
||||
&& clock_domain_pd_allowed()
|
||||
#endif
|
||||
) {
|
||||
pd_flags |= RTC_SLEEP_PD_MODEM;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -23,6 +23,92 @@
|
|||
|
||||
static __attribute__((unused)) const char *TAG = "sleep";
|
||||
|
||||
struct sleep_retention_module_object {
|
||||
sleep_retention_module_callbacks_t cbs; /* A callback list that can extend more sleep retention event callbacks */
|
||||
sleep_retention_module_bitmap_t dependents; /* A bitmap identifying all modules that the current module depends on */
|
||||
sleep_retention_module_bitmap_t references; /* A bitmap indicating all other modules that depend on (or reference) the current module,
|
||||
* It will update at runtime based on whether the module is referenced by other modules */
|
||||
sleep_retention_module_attribute_t attributes; /* A bitmap indicating attribute of the current module */
|
||||
};
|
||||
|
||||
static inline void sleep_retention_module_object_ctor(struct sleep_retention_module_object * const self, sleep_retention_module_callbacks_t *cbs)
|
||||
{
|
||||
self->cbs = *cbs;
|
||||
self->dependents = 0;
|
||||
self->references = 0;
|
||||
self->attributes = 0;
|
||||
}
|
||||
|
||||
static inline void sleep_retention_module_object_dtor(struct sleep_retention_module_object * const self)
|
||||
{
|
||||
self->cbs = (sleep_retention_module_callbacks_t) { .create = { .handle = NULL, .arg = NULL } };
|
||||
}
|
||||
|
||||
static inline void set_dependencies(struct sleep_retention_module_object * const self, sleep_retention_module_bitmap_t depends)
|
||||
{
|
||||
self->dependents = depends;
|
||||
}
|
||||
|
||||
static inline void clr_dependencies(struct sleep_retention_module_object * const self)
|
||||
{
|
||||
self->dependents = 0;
|
||||
}
|
||||
|
||||
static inline sleep_retention_module_bitmap_t get_dependencies(struct sleep_retention_module_object * const self)
|
||||
{
|
||||
return self->dependents;
|
||||
}
|
||||
|
||||
static inline void set_reference(struct sleep_retention_module_object * const self, sleep_retention_module_t module)
|
||||
{
|
||||
self->references |= BIT(module);
|
||||
}
|
||||
|
||||
static inline void clr_reference(struct sleep_retention_module_object * const self, sleep_retention_module_t module)
|
||||
{
|
||||
self->references &= ~BIT(module);
|
||||
}
|
||||
|
||||
static inline sleep_retention_module_bitmap_t get_references(struct sleep_retention_module_object * const self)
|
||||
{
|
||||
return self->references;
|
||||
}
|
||||
|
||||
static inline bool references_exist(struct sleep_retention_module_object * const self)
|
||||
{
|
||||
return (get_references(self) != 0);
|
||||
}
|
||||
|
||||
static inline void set_attributes(struct sleep_retention_module_object * const self, sleep_retention_module_attribute_t attributes)
|
||||
{
|
||||
self->attributes = attributes;
|
||||
}
|
||||
|
||||
static inline void clr_attributes(struct sleep_retention_module_object * const self)
|
||||
{
|
||||
self->attributes = 0;
|
||||
}
|
||||
|
||||
static inline sleep_retention_module_attribute_t get_attributes(struct sleep_retention_module_object * const self)
|
||||
{
|
||||
return self->attributes;
|
||||
}
|
||||
|
||||
static inline bool module_is_passive(struct sleep_retention_module_object * const self)
|
||||
{
|
||||
return (get_attributes(self) & SLEEP_RETENTION_MODULE_ATTR_PASSIVE) ? true : false;
|
||||
}
|
||||
|
||||
static inline bool module_is_inited(sleep_retention_module_t module)
|
||||
{
|
||||
return (sleep_retention_get_inited_modules() & BIT(module)) ? true : false;
|
||||
}
|
||||
|
||||
static inline bool module_is_created(sleep_retention_module_t module)
|
||||
{
|
||||
return (sleep_retention_get_created_modules() & BIT(module)) ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal structure which holds all requested sleep retention parameters
|
||||
*/
|
||||
|
@ -38,7 +124,7 @@ typedef struct {
|
|||
* information according to the configuration information of the linked list
|
||||
* nodes.
|
||||
* The PMU module triggers REGDMA to use the corresponding linked list when
|
||||
* swtiching between different power states. For example:
|
||||
* switching between different power states. For example:
|
||||
*
|
||||
* +---------------+---------------+-------------------+-----------+
|
||||
* | Current | The next | The entry will be | Retention |
|
||||
|
@ -82,6 +168,7 @@ typedef struct {
|
|||
#define SLEEP_RETENTION_REGDMA_LINK_NR_PRIORITIES (8u)
|
||||
#define SLEEP_RETENTION_REGDMA_LINK_HIGHEST_PRIORITY (0)
|
||||
#define SLEEP_RETENTION_REGDMA_LINK_LOWEST_PRIORITY (SLEEP_RETENTION_REGDMA_LINK_NR_PRIORITIES - 1)
|
||||
#define SLEEP_RETENTION_MODULE_INVALID ((sleep_retention_module_t)(-1)) /* the final node does not belong to any module */
|
||||
struct {
|
||||
sleep_retention_entries_t entries;
|
||||
uint32_t entries_bitmap: REGDMA_LINK_ENTRY_NUM,
|
||||
|
@ -91,22 +178,31 @@ typedef struct {
|
|||
} lists[SLEEP_RETENTION_REGDMA_LINK_NR_PRIORITIES];
|
||||
_lock_t lock;
|
||||
regdma_link_priority_t highpri;
|
||||
uint32_t modules;
|
||||
uint32_t inited_modules;
|
||||
uint32_t created_modules;
|
||||
|
||||
struct sleep_retention_module_object instance[32];
|
||||
|
||||
#if SOC_PM_RETENTION_HAS_CLOCK_BUG
|
||||
#define EXTRA_LINK_NUM (REGDMA_LINK_ENTRY_NUM - 1)
|
||||
#endif
|
||||
} sleep_retention_t;
|
||||
|
||||
static DRAM_ATTR __attribute__((unused)) sleep_retention_t s_retention = {
|
||||
.highpri = (uint8_t)-1, .modules = 0
|
||||
.highpri = (uint8_t)-1, .inited_modules = 0, .created_modules = 0
|
||||
};
|
||||
|
||||
#define SLEEP_RETENTION_ENTRY_BITMAP_MASK (BIT(REGDMA_LINK_ENTRY_NUM) - 1)
|
||||
#define SLEEP_RETENTION_ENTRY_BITMAP(bitmap) ((bitmap) & SLEEP_RETENTION_ENTRY_BITMAP_MASK)
|
||||
|
||||
static esp_err_t sleep_retention_entries_create_impl(const sleep_retention_entries_config_t retent[], int num, regdma_link_priority_t priority, int module);
|
||||
static esp_err_t sleep_retention_entries_create_impl(const sleep_retention_entries_config_t retent[], int num, regdma_link_priority_t priority, sleep_retention_module_t module);
|
||||
static void sleep_retention_entries_join(void);
|
||||
|
||||
static inline sleep_retention_module_bitmap_t module_num2map(sleep_retention_module_t module)
|
||||
{
|
||||
return (module == SLEEP_RETENTION_MODULE_INVALID) ? 0 : BIT(module);
|
||||
}
|
||||
|
||||
static inline bool sleep_retention_entries_require_branch(uint32_t owner, uint32_t runtime_bitmap)
|
||||
{
|
||||
bool use_new_entry = SLEEP_RETENTION_ENTRY_BITMAP(owner & ~runtime_bitmap) ? true : false;
|
||||
|
@ -114,7 +210,7 @@ static inline bool sleep_retention_entries_require_branch(uint32_t owner, uint32
|
|||
return use_new_entry && intersection_exist;
|
||||
}
|
||||
|
||||
static esp_err_t sleep_retention_entries_check_and_create_default(uint32_t owner, uint32_t runtime_bitmap, uint32_t entries_bitmap, regdma_link_priority_t priority, uint32_t module)
|
||||
static esp_err_t sleep_retention_entries_check_and_create_default(uint32_t owner, uint32_t runtime_bitmap, uint32_t entries_bitmap, regdma_link_priority_t priority, sleep_retention_module_t module)
|
||||
{
|
||||
assert(sleep_retention_entries_require_branch(owner, runtime_bitmap));
|
||||
|
||||
|
@ -133,7 +229,7 @@ static esp_err_t sleep_retention_entries_check_and_create_final_default(void)
|
|||
esp_err_t err = ESP_OK;
|
||||
_lock_acquire_recursive(&s_retention.lock);
|
||||
if (s_retention.lists[SLEEP_RETENTION_REGDMA_LINK_LOWEST_PRIORITY].entries_bitmap == 0) {
|
||||
err = sleep_retention_entries_create_impl(&final_dummy, 1, SLEEP_RETENTION_REGDMA_LINK_LOWEST_PRIORITY, 0);
|
||||
err = sleep_retention_entries_create_impl(&final_dummy, 1, SLEEP_RETENTION_REGDMA_LINK_LOWEST_PRIORITY, SLEEP_RETENTION_MODULE_INVALID);
|
||||
}
|
||||
_lock_release_recursive(&s_retention.lock);
|
||||
return err;
|
||||
|
@ -157,7 +253,7 @@ static void sleep_retention_entries_update(uint32_t owner, void *new_link, regdm
|
|||
_lock_release_recursive(&s_retention.lock);
|
||||
}
|
||||
|
||||
static void * sleep_retention_entries_try_create(const regdma_link_config_t *config, uint32_t owner, regdma_link_priority_t priority, uint32_t module)
|
||||
static void * sleep_retention_entries_try_create(const regdma_link_config_t *config, uint32_t owner, regdma_link_priority_t priority, sleep_retention_module_t module)
|
||||
{
|
||||
void *link = NULL;
|
||||
assert(owner > 0 && owner < BIT(REGDMA_LINK_ENTRY_NUM));
|
||||
|
@ -165,9 +261,9 @@ static void * sleep_retention_entries_try_create(const regdma_link_config_t *con
|
|||
_lock_acquire_recursive(&s_retention.lock);
|
||||
if (sleep_retention_entries_require_branch(owner, s_retention.lists[priority].runtime_bitmap)) {
|
||||
if (sleep_retention_entries_check_and_create_default(owner, s_retention.lists[priority].runtime_bitmap,
|
||||
s_retention.lists[priority].entries_bitmap, priority, module) == ESP_OK) { /* branch node can't as tail node */
|
||||
s_retention.lists[priority].entries_bitmap, priority, module_num2map(module)) == ESP_OK) { /* branch node can't as tail node */
|
||||
link = regdma_link_init_safe(
|
||||
config, true, module,
|
||||
config, true, module_num2map(module),
|
||||
(owner & BIT(0)) ? s_retention.lists[priority].entries[0] : NULL,
|
||||
(owner & BIT(1)) ? s_retention.lists[priority].entries[1] : NULL,
|
||||
(owner & BIT(2)) ? s_retention.lists[priority].entries[2] : NULL,
|
||||
|
@ -175,18 +271,18 @@ static void * sleep_retention_entries_try_create(const regdma_link_config_t *con
|
|||
);
|
||||
}
|
||||
} else {
|
||||
link = regdma_link_init_safe(config, false, module, s_retention.lists[priority].entries[__builtin_ffs(owner) - 1]);
|
||||
link = regdma_link_init_safe(config, false, module_num2map(module), s_retention.lists[priority].entries[__builtin_ffs(owner) - 1]);
|
||||
}
|
||||
_lock_release_recursive(&s_retention.lock);
|
||||
return link;
|
||||
}
|
||||
|
||||
static void * sleep_retention_entries_try_create_bonding(const regdma_link_config_t *config, uint32_t owner, regdma_link_priority_t priority, uint32_t module)
|
||||
static void * sleep_retention_entries_try_create_bonding(const regdma_link_config_t *config, uint32_t owner, regdma_link_priority_t priority, sleep_retention_module_t module)
|
||||
{
|
||||
assert(owner > 0 && owner < BIT(REGDMA_LINK_ENTRY_NUM));
|
||||
_lock_acquire_recursive(&s_retention.lock);
|
||||
void *link = regdma_link_init_safe(
|
||||
config, true, module,
|
||||
config, true, module_num2map(module),
|
||||
(owner & BIT(0)) ? s_retention.lists[priority].entries[0] : NULL,
|
||||
(owner & BIT(1)) ? s_retention.lists[priority].entries[1] : NULL,
|
||||
(owner & BIT(2)) ? s_retention.lists[priority].entries[2] : NULL,
|
||||
|
@ -208,13 +304,13 @@ static void sleep_retention_entries_stats(void)
|
|||
}
|
||||
|
||||
#if REGDMA_LINK_DBG
|
||||
void sleep_retention_entries_show_memories(void)
|
||||
void sleep_retention_dump_entries(FILE *out)
|
||||
{
|
||||
_lock_acquire_recursive(&s_retention.lock);
|
||||
if (s_retention.highpri >= SLEEP_RETENTION_REGDMA_LINK_HIGHEST_PRIORITY && s_retention.highpri <= SLEEP_RETENTION_REGDMA_LINK_LOWEST_PRIORITY) {
|
||||
for (int entry = 0; entry < ARRAY_SIZE(s_retention.lists[s_retention.highpri].entries); entry++) {
|
||||
ESP_LOGW(TAG, "Print sleep retention entries[%d] memories:", entry);
|
||||
regdma_link_show_memories(s_retention.lists[s_retention.highpri].entries[entry], entry);
|
||||
fprintf(out, "\nsleep retention entries[%d] context:\n", entry);
|
||||
regdma_link_dump(out, s_retention.lists[s_retention.highpri].entries[entry], entry);
|
||||
}
|
||||
}
|
||||
_lock_release_recursive(&s_retention.lock);
|
||||
|
@ -246,7 +342,7 @@ static uint32_t sleep_retention_entries_owner_bitmap(sleep_retention_entries_t *
|
|||
return owner;
|
||||
}
|
||||
|
||||
static bool sleep_retention_entries_get_destroy_context(regdma_link_priority_t priority, uint32_t module, sleep_retention_entries_t *destroy_entries, void **destroy_tail, sleep_retention_entries_t *next_entries, void **prev_tail)
|
||||
static bool sleep_retention_entries_get_destroy_context(regdma_link_priority_t priority, sleep_retention_module_t module, sleep_retention_entries_t *destroy_entries, void **destroy_tail, sleep_retention_entries_t *next_entries, void **prev_tail)
|
||||
{
|
||||
bool exist = false;
|
||||
sleep_retention_entries_t destroy_tails, prev_tails;
|
||||
|
@ -257,13 +353,13 @@ static bool sleep_retention_entries_get_destroy_context(regdma_link_priority_t p
|
|||
_lock_acquire_recursive(&s_retention.lock);
|
||||
for (int entry = 0; entry < ARRAY_SIZE(s_retention.lists[priority].entries); entry++) {
|
||||
(*destroy_entries)[entry] = regdma_find_module_link_head(
|
||||
s_retention.lists[priority].entries[entry], s_retention.lists[priority].entries_tail, entry, module);
|
||||
s_retention.lists[priority].entries[entry], s_retention.lists[priority].entries_tail, entry, module_num2map(module));
|
||||
destroy_tails [entry] = regdma_find_module_link_tail(
|
||||
s_retention.lists[priority].entries[entry], s_retention.lists[priority].entries_tail, entry, module);
|
||||
s_retention.lists[priority].entries[entry], s_retention.lists[priority].entries_tail, entry, module_num2map(module));
|
||||
(*next_entries) [entry] = regdma_find_next_module_link_head(
|
||||
s_retention.lists[priority].entries[entry], s_retention.lists[priority].entries_tail, entry, module);
|
||||
s_retention.lists[priority].entries[entry], s_retention.lists[priority].entries_tail, entry, module_num2map(module));
|
||||
prev_tails [entry] = regdma_find_prev_module_link_tail(
|
||||
s_retention.lists[priority].entries[entry], s_retention.lists[priority].entries_tail, entry, module);
|
||||
s_retention.lists[priority].entries[entry], s_retention.lists[priority].entries_tail, entry, module_num2map(module));
|
||||
if ((*destroy_entries)[entry] && destroy_tails[entry]) {
|
||||
exist = true;
|
||||
}
|
||||
|
@ -322,12 +418,12 @@ static void sleep_retention_entries_check_and_distroy_final_default(void)
|
|||
{
|
||||
_lock_acquire_recursive(&s_retention.lock);
|
||||
assert(s_retention.highpri == SLEEP_RETENTION_REGDMA_LINK_LOWEST_PRIORITY);
|
||||
assert(s_retention.modules == 0);
|
||||
assert(s_retention.created_modules == 0);
|
||||
sleep_retention_entries_destroy_wrapper(&s_retention.lists[SLEEP_RETENTION_REGDMA_LINK_LOWEST_PRIORITY].entries);
|
||||
_lock_release_recursive(&s_retention.lock);
|
||||
}
|
||||
|
||||
static void sleep_retention_entries_all_destroy_wrapper(uint32_t module)
|
||||
static void sleep_retention_entries_all_destroy_wrapper(sleep_retention_module_t module)
|
||||
{
|
||||
void *destroy_tail = NULL, *prev_tail = NULL;
|
||||
sleep_retention_entries_t destroy_entries, next_entries;
|
||||
|
@ -348,13 +444,13 @@ static void sleep_retention_entries_all_destroy_wrapper(uint32_t module)
|
|||
priority++;
|
||||
}
|
||||
} while (priority < SLEEP_RETENTION_REGDMA_LINK_NR_PRIORITIES);
|
||||
s_retention.modules &= ~module;
|
||||
s_retention.created_modules &= ~module_num2map(module);
|
||||
_lock_release_recursive(&s_retention.lock);
|
||||
}
|
||||
|
||||
static void sleep_retention_entries_do_destroy(int module)
|
||||
static void sleep_retention_entries_do_destroy(sleep_retention_module_t module)
|
||||
{
|
||||
assert(module != 0);
|
||||
assert(SLEEP_RETENTION_MODULE_MIN <= module && module <= SLEEP_RETENTION_MODULE_MAX);
|
||||
_lock_acquire_recursive(&s_retention.lock);
|
||||
sleep_retention_entries_join();
|
||||
sleep_retention_entries_stats();
|
||||
|
@ -362,25 +458,21 @@ static void sleep_retention_entries_do_destroy(int module)
|
|||
_lock_release_recursive(&s_retention.lock);
|
||||
}
|
||||
|
||||
void sleep_retention_entries_destroy(int module)
|
||||
static void sleep_retention_entries_destroy(sleep_retention_module_t module)
|
||||
{
|
||||
assert(module != 0);
|
||||
assert(SLEEP_RETENTION_MODULE_MIN <= module && module <= SLEEP_RETENTION_MODULE_MAX);
|
||||
_lock_acquire_recursive(&s_retention.lock);
|
||||
sleep_retention_entries_do_destroy(module);
|
||||
if (s_retention.modules == 0) {
|
||||
if (s_retention.created_modules == 0) {
|
||||
sleep_retention_entries_check_and_distroy_final_default();
|
||||
pmu_sleep_disable_regdma_backup();
|
||||
memset((void *)s_retention.lists, 0, sizeof(s_retention.lists));
|
||||
s_retention.highpri = (uint8_t)-1;
|
||||
_lock_release_recursive(&s_retention.lock);
|
||||
_lock_close_recursive(&s_retention.lock);
|
||||
s_retention.lock = NULL;
|
||||
return;
|
||||
}
|
||||
_lock_release_recursive(&s_retention.lock);
|
||||
}
|
||||
|
||||
static esp_err_t sleep_retention_entries_create_impl(const sleep_retention_entries_config_t retent[], int num, regdma_link_priority_t priority, int module)
|
||||
static esp_err_t sleep_retention_entries_create_impl(const sleep_retention_entries_config_t retent[], int num, regdma_link_priority_t priority, sleep_retention_module_t module)
|
||||
{
|
||||
_lock_acquire_recursive(&s_retention.lock);
|
||||
for (int i = num - 1; i >= 0; i--) {
|
||||
|
@ -403,7 +495,7 @@ static esp_err_t sleep_retention_entries_create_impl(const sleep_retention_entri
|
|||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t sleep_retention_entries_create_bonding(regdma_link_priority_t priority, uint32_t module)
|
||||
static esp_err_t sleep_retention_entries_create_bonding(regdma_link_priority_t priority, sleep_retention_module_t module)
|
||||
{
|
||||
static const sleep_retention_entries_config_t bonding_dummy = { REGDMA_LINK_WAIT_INIT(0xffff, 0, 0, 0, 1, 1), SLEEP_RETENTION_ENTRY_BITMAP_MASK };
|
||||
|
||||
|
@ -442,7 +534,7 @@ static void sleep_retention_entries_join(void)
|
|||
_lock_release_recursive(&s_retention.lock);
|
||||
}
|
||||
|
||||
static esp_err_t sleep_retention_entries_create_wrapper(const sleep_retention_entries_config_t retent[], int num, regdma_link_priority_t priority, uint32_t module)
|
||||
static esp_err_t sleep_retention_entries_create_wrapper(const sleep_retention_entries_config_t retent[], int num, regdma_link_priority_t priority, sleep_retention_module_t module)
|
||||
{
|
||||
_lock_acquire_recursive(&s_retention.lock);
|
||||
esp_err_t err = sleep_retention_entries_create_bonding(priority, module);
|
||||
|
@ -451,7 +543,7 @@ static esp_err_t sleep_retention_entries_create_wrapper(const sleep_retention_en
|
|||
if(err) goto error;
|
||||
err = sleep_retention_entries_create_bonding(priority, module);
|
||||
if(err) goto error;
|
||||
s_retention.modules |= module;
|
||||
s_retention.created_modules |= module_num2map(module);
|
||||
sleep_retention_entries_join();
|
||||
|
||||
error:
|
||||
|
@ -459,17 +551,16 @@ error:
|
|||
return err;
|
||||
}
|
||||
|
||||
esp_err_t sleep_retention_entries_create(const sleep_retention_entries_config_t retent[], int num, regdma_link_priority_t priority, int module)
|
||||
esp_err_t sleep_retention_entries_create(const sleep_retention_entries_config_t retent[], int num, regdma_link_priority_t priority, sleep_retention_module_t module)
|
||||
{
|
||||
if (!(retent && num > 0 && (priority < SLEEP_RETENTION_REGDMA_LINK_NR_PRIORITIES) && (module != 0))) {
|
||||
if (retent == NULL || num <= 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (s_retention.lock == NULL) {
|
||||
_lock_init_recursive(&s_retention.lock);
|
||||
if (s_retention.lock == NULL) {
|
||||
ESP_LOGE(TAG, "Create sleep retention lock failed");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
if (priority >= SLEEP_RETENTION_REGDMA_LINK_NR_PRIORITIES) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (module < SLEEP_RETENTION_MODULE_MIN || module > SLEEP_RETENTION_MODULE_MAX) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
esp_err_t err = sleep_retention_entries_check_and_create_final_default();
|
||||
if (err) goto error;
|
||||
|
@ -493,9 +584,192 @@ void sleep_retention_entries_get(sleep_retention_entries_t *entries)
|
|||
_lock_release_recursive(&s_retention.lock);
|
||||
}
|
||||
|
||||
uint32_t IRAM_ATTR sleep_retention_get_modules(void)
|
||||
uint32_t IRAM_ATTR sleep_retention_get_inited_modules(void)
|
||||
{
|
||||
return s_retention.modules;
|
||||
return s_retention.inited_modules;
|
||||
}
|
||||
|
||||
uint32_t IRAM_ATTR sleep_retention_get_created_modules(void)
|
||||
{
|
||||
return s_retention.created_modules;
|
||||
}
|
||||
|
||||
esp_err_t sleep_retention_module_init(sleep_retention_module_t module, sleep_retention_module_init_param_t *param)
|
||||
{
|
||||
if (module < SLEEP_RETENTION_MODULE_MIN || module > SLEEP_RETENTION_MODULE_MAX) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (param == NULL || param->cbs.create.handle == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (s_retention.lock == NULL) {
|
||||
/* Passive modules will be initialized during the system startup, with the
|
||||
* operating system scheduler not yet enabled. There is no risk of contention
|
||||
* for lock initialization here. */
|
||||
_lock_init_recursive(&s_retention.lock);
|
||||
if (s_retention.lock == NULL) {
|
||||
ESP_LOGE(TAG, "Create sleep retention lock failed");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t err = ESP_OK;
|
||||
_lock_acquire_recursive(&s_retention.lock);
|
||||
if (module_is_created(module) || module_is_inited(module)) {
|
||||
err = ESP_ERR_INVALID_STATE;
|
||||
} else {
|
||||
sleep_retention_module_object_ctor(&s_retention.instance[module], ¶m->cbs);
|
||||
set_dependencies(&s_retention.instance[module], param->depends);
|
||||
set_attributes(&s_retention.instance[module], param->attribute);
|
||||
s_retention.inited_modules |= module_num2map(module);
|
||||
}
|
||||
_lock_release_recursive(&s_retention.lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t sleep_retention_module_deinit(sleep_retention_module_t module)
|
||||
{
|
||||
if (module < SLEEP_RETENTION_MODULE_MIN || module > SLEEP_RETENTION_MODULE_MAX) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
esp_err_t err = ESP_OK;
|
||||
bool do_lock_release = false;
|
||||
_lock_acquire_recursive(&s_retention.lock);
|
||||
if (module_is_created(module) || !module_is_inited(module)) {
|
||||
err = ESP_ERR_INVALID_STATE;
|
||||
} else {
|
||||
clr_attributes(&s_retention.instance[module]);
|
||||
clr_dependencies(&s_retention.instance[module]);
|
||||
sleep_retention_module_object_dtor(&s_retention.instance[module]);
|
||||
s_retention.inited_modules &= ~module_num2map(module);
|
||||
do_lock_release = (sleep_retention_get_inited_modules() == 0);
|
||||
}
|
||||
_lock_release_recursive(&s_retention.lock);
|
||||
|
||||
if (do_lock_release) {
|
||||
_lock_close_recursive(&s_retention.lock);
|
||||
s_retention.lock = NULL;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static esp_err_t sleep_retention_passive_module_allocate(sleep_retention_module_t module)
|
||||
{
|
||||
assert(module >= SLEEP_RETENTION_MODULE_MIN && module <= SLEEP_RETENTION_MODULE_MAX);
|
||||
|
||||
esp_err_t err = ESP_OK;
|
||||
_lock_acquire_recursive(&s_retention.lock);
|
||||
assert(module_is_passive(&s_retention.instance[module]) && "Illegal dependency");
|
||||
assert(module_is_inited(module) && "All passive module must be inited first!");
|
||||
if (!module_is_created(module)) {
|
||||
sleep_retention_module_bitmap_t depends = get_dependencies(&s_retention.instance[module]);
|
||||
for (int i = 0; (err == ESP_OK) && depends; depends >>= 1, i++) {
|
||||
if (depends & BIT(0)) {
|
||||
set_reference(&s_retention.instance[i], module);
|
||||
err = sleep_retention_passive_module_allocate(i);
|
||||
}
|
||||
}
|
||||
if (err == ESP_OK) {
|
||||
sleep_retention_callback_t fn = s_retention.instance[module].cbs.create.handle;
|
||||
if (fn) {
|
||||
err = (*fn)(s_retention.instance[module].cbs.create.arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
_lock_release_recursive(&s_retention.lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t sleep_retention_module_allocate(sleep_retention_module_t module)
|
||||
{
|
||||
if (module < SLEEP_RETENTION_MODULE_MIN || module > SLEEP_RETENTION_MODULE_MAX) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
esp_err_t err = ESP_OK;
|
||||
_lock_acquire_recursive(&s_retention.lock);
|
||||
if (!module_is_passive(&s_retention.instance[module])) {
|
||||
if (module_is_inited(module) && !module_is_created(module)) {
|
||||
sleep_retention_module_bitmap_t depends = get_dependencies(&s_retention.instance[module]);
|
||||
for (int i = 0; (err == ESP_OK) && depends; depends >>= 1, i++) {
|
||||
if (depends & BIT(0)) {
|
||||
set_reference(&s_retention.instance[i], module);
|
||||
if (module_is_passive(&s_retention.instance[i])) { /* the callee ensures this module is inited */
|
||||
err = sleep_retention_passive_module_allocate(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (err == ESP_OK) {
|
||||
sleep_retention_callback_t fn = s_retention.instance[module].cbs.create.handle;
|
||||
if (fn) {
|
||||
err = (*fn)(s_retention.instance[module].cbs.create.arg);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err = ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
} else {
|
||||
err = ESP_ERR_NOT_ALLOWED;
|
||||
}
|
||||
_lock_release_recursive(&s_retention.lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
static esp_err_t sleep_retention_passive_module_free(sleep_retention_module_t module)
|
||||
{
|
||||
assert(module >= SLEEP_RETENTION_MODULE_MIN && module <= SLEEP_RETENTION_MODULE_MAX);
|
||||
|
||||
esp_err_t err = ESP_OK;
|
||||
_lock_acquire_recursive(&s_retention.lock);
|
||||
assert(module_is_passive(&s_retention.instance[module]) && "Illegal dependency");
|
||||
assert(module_is_inited(module) && "All passive module must be inited first!");
|
||||
if (module_is_created(module)) {
|
||||
if (!references_exist(&s_retention.instance[module])) {
|
||||
sleep_retention_entries_destroy(module);
|
||||
|
||||
sleep_retention_module_bitmap_t depends = get_dependencies(&s_retention.instance[module]);
|
||||
for (int i = 0; (err == ESP_OK) && depends; depends >>= 1, i++) {
|
||||
if (depends & BIT(0)) {
|
||||
clr_reference(&s_retention.instance[i], module);
|
||||
err = sleep_retention_passive_module_free(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_lock_release_recursive(&s_retention.lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t sleep_retention_module_free(sleep_retention_module_t module)
|
||||
{
|
||||
if (module < SLEEP_RETENTION_MODULE_MIN || module > SLEEP_RETENTION_MODULE_MAX) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
esp_err_t err = ESP_OK;
|
||||
_lock_acquire_recursive(&s_retention.lock);
|
||||
if (!module_is_passive(&s_retention.instance[module])) {
|
||||
if (module_is_inited(module) && module_is_created(module)) {
|
||||
sleep_retention_entries_destroy(module);
|
||||
|
||||
sleep_retention_module_bitmap_t depends = get_dependencies(&s_retention.instance[module]);
|
||||
for (int i = 0; (err == ESP_OK) && depends; depends >>= 1, i++) {
|
||||
if (depends & BIT(0)) {
|
||||
clr_reference(&s_retention.instance[i], module);
|
||||
if (module_is_passive(&s_retention.instance[i])) {
|
||||
err = sleep_retention_passive_module_free(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err = ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
} else {
|
||||
err = ESP_ERR_NOT_ALLOWED;
|
||||
}
|
||||
_lock_release_recursive(&s_retention.lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
#if SOC_PM_RETENTION_HAS_CLOCK_BUG
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -34,7 +34,7 @@ static __attribute__((unused)) const char *TAG = "sleep_sys_periph";
|
|||
|
||||
#define SLEEP_RETENTION_PERIPHERALS_PRIORITY_DEFAULT (REGDMA_LINK_PRI_6)
|
||||
|
||||
esp_err_t sleep_sys_periph_intr_matrix_retention_init(void)
|
||||
static __attribute__((unused)) esp_err_t sleep_sys_periph_intr_matrix_retention_init(void *arg)
|
||||
{
|
||||
#define N_REGS_INTR_MATRIX() (((INTMTX_CORE0_CLOCK_GATE_REG - DR_REG_INTERRUPT_MATRIX_BASE) / 4) + 1)
|
||||
|
||||
|
@ -42,13 +42,13 @@ esp_err_t sleep_sys_periph_intr_matrix_retention_init(void)
|
|||
[0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_INTMTX_LINK(0), DR_REG_INTERRUPT_MATRIX_BASE, DR_REG_INTERRUPT_MATRIX_BASE, N_REGS_INTR_MATRIX(), 0, 0), .owner = ENTRY(0) | ENTRY(2) } /* intr matrix */
|
||||
};
|
||||
|
||||
esp_err_t err = sleep_retention_entries_create(intr_matrix_regs_retention, ARRAY_SIZE(intr_matrix_regs_retention), REGDMA_LINK_PRI_5, SLEEP_RETENTION_MODULE_INTR_MATRIX);
|
||||
ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for digital peripherals (Interrupt matrix) retention");
|
||||
ESP_LOGI(TAG, "Interrupt Matrix sleep retention initialization");
|
||||
esp_err_t err = sleep_retention_entries_create(intr_matrix_regs_retention, ARRAY_SIZE(intr_matrix_regs_retention), REGDMA_LINK_PRI_5, SLEEP_RETENTION_MODULE_SYS_PERIPH);
|
||||
ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for digital peripherals (%s) retention", "Interrupt matrix");
|
||||
ESP_LOGD(TAG, "Interrupt Matrix sleep retention initialization");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t sleep_sys_periph_hp_system_retention_init(void)
|
||||
static __attribute__((unused)) esp_err_t sleep_sys_periph_hp_system_retention_init(void *arg)
|
||||
{
|
||||
#define N_REGS_HP_SYSTEM() (((HP_SYSTEM_MEM_TEST_CONF_REG - DR_REG_HP_SYSTEM_BASE) / 4) + 1)
|
||||
|
||||
|
@ -56,13 +56,13 @@ esp_err_t sleep_sys_periph_hp_system_retention_init(void)
|
|||
[0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_HPSYS_LINK(0), DR_REG_HP_SYSTEM_BASE, DR_REG_HP_SYSTEM_BASE, N_REGS_HP_SYSTEM(), 0, 0), .owner = ENTRY(0) | ENTRY(2) } /* hp system */
|
||||
};
|
||||
|
||||
esp_err_t err = sleep_retention_entries_create(hp_system_regs_retention, ARRAY_SIZE(hp_system_regs_retention), REGDMA_LINK_PRI_5, SLEEP_RETENTION_MODULE_HP_SYSTEM);
|
||||
ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for digital peripherals (HP system) retention");
|
||||
ESP_LOGI(TAG, "HP System sleep retention initialization");
|
||||
esp_err_t err = sleep_retention_entries_create(hp_system_regs_retention, ARRAY_SIZE(hp_system_regs_retention), REGDMA_LINK_PRI_5, SLEEP_RETENTION_MODULE_SYS_PERIPH);
|
||||
ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for digital peripherals (%s) retention", "HP system");
|
||||
ESP_LOGD(TAG, "HP System sleep retention initialization");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t sleep_sys_periph_tee_apm_retention_init(void)
|
||||
static __attribute__((unused)) esp_err_t sleep_sys_periph_tee_apm_retention_init(void *arg)
|
||||
{
|
||||
#define N_REGS_TEE() (((TEE_CLOCK_GATE_REG - DR_REG_TEE_BASE) / 4) + 1)
|
||||
#define N_REGS_APM() (((HP_APM_CLOCK_GATE_REG - DR_REG_HP_APM_BASE) / 4) + 1)
|
||||
|
@ -72,36 +72,36 @@ esp_err_t sleep_sys_periph_tee_apm_retention_init(void)
|
|||
[1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TEEAPM_LINK(1), DR_REG_TEE_BASE, DR_REG_TEE_BASE, N_REGS_TEE(), 0, 0), .owner = ENTRY(0) | ENTRY(2) } /* tee */
|
||||
};
|
||||
|
||||
esp_err_t err = sleep_retention_entries_create(tee_apm_regs_retention, ARRAY_SIZE(tee_apm_regs_retention), REGDMA_LINK_PRI_4, SLEEP_RETENTION_MODULE_TEE_APM);
|
||||
esp_err_t err = sleep_retention_entries_create(tee_apm_regs_retention, ARRAY_SIZE(tee_apm_regs_retention), REGDMA_LINK_PRI_4, SLEEP_RETENTION_MODULE_SYS_PERIPH);
|
||||
if (err == ESP_OK) {
|
||||
const static sleep_retention_entries_config_t regs_highpri_retention[] = {
|
||||
[0] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TEEAPM_LINK(2), TEE_M4_MODE_CTRL_REG, 0x0, 0xffffffff, 1, 0), .owner = ENTRY(2) }
|
||||
};
|
||||
err = sleep_retention_entries_create(regs_highpri_retention, ARRAY_SIZE(regs_highpri_retention), REGDMA_LINK_PRI_2, SLEEP_RETENTION_MODULE_TEE_APM);
|
||||
err = sleep_retention_entries_create(regs_highpri_retention, ARRAY_SIZE(regs_highpri_retention), REGDMA_LINK_PRI_2, SLEEP_RETENTION_MODULE_SYS_PERIPH);
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for digital peripherals (TEE/APM) retention");
|
||||
ESP_LOGI(TAG, "TEE/APM sleep retention initialization");
|
||||
ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for digital peripherals (%s) retention", "TEE/APM");
|
||||
ESP_LOGD(TAG, "TEE/APM sleep retention initialization");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t sleep_sys_periph_uart0_retention_init(void)
|
||||
static __attribute__((unused)) esp_err_t sleep_sys_periph_uart0_retention_init(void *arg)
|
||||
{
|
||||
#define N_REGS_UART() (((UART_ID_REG(0) - UART_INT_RAW_REG(0)) / 4) + 1)
|
||||
|
||||
const static sleep_retention_entries_config_t uart_regs_retention[] = {
|
||||
[0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_UART_LINK(0x00), UART_INT_RAW_REG(0), UART_INT_RAW_REG(0), N_REGS_UART(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, /* uart */
|
||||
[0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_UART_LINK(0x00), UART_INT_RAW_REG(0), UART_INT_RAW_REG(0), N_REGS_UART(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, /* uart */
|
||||
/* Note: uart register should set update reg to make the configuration take effect */
|
||||
[1] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_UART_LINK(0x01), UART_REG_UPDATE_REG(0), UART_REG_UPDATE, UART_REG_UPDATE_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) },
|
||||
[2] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_UART_LINK(0x02), UART_REG_UPDATE_REG(0), 0x0, UART_REG_UPDATE_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }
|
||||
};
|
||||
|
||||
esp_err_t err = sleep_retention_entries_create(uart_regs_retention, ARRAY_SIZE(uart_regs_retention), REGDMA_LINK_PRI_5, SLEEP_RETENTION_MODULE_UART0);
|
||||
ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for digital peripherals (UART) retention");
|
||||
ESP_LOGI(TAG, "UART sleep retention initialization");
|
||||
esp_err_t err = sleep_retention_entries_create(uart_regs_retention, ARRAY_SIZE(uart_regs_retention), REGDMA_LINK_PRI_5, SLEEP_RETENTION_MODULE_SYS_PERIPH);
|
||||
ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for digital peripherals (%s) retention", "UART");
|
||||
ESP_LOGD(TAG, "UART sleep retention initialization");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t sleep_sys_periph_tg0_retention_init(void)
|
||||
static __attribute__((unused)) esp_err_t sleep_sys_periph_tg0_retention_init(void *arg)
|
||||
{
|
||||
#define N_REGS_TG() (((TIMG_REGCLK_REG(0) - REG_TIMG_BASE(0)) / 4) + 1)
|
||||
|
||||
|
@ -117,13 +117,13 @@ esp_err_t sleep_sys_periph_tg0_retention_init(void)
|
|||
[7] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TIMG_LINK(0x07), TIMG_T0LOAD_REG(0), 0x1, TIMG_T0_LOAD_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }
|
||||
};
|
||||
|
||||
esp_err_t err = sleep_retention_entries_create(tg_regs_retention, ARRAY_SIZE(tg_regs_retention), SLEEP_RETENTION_PERIPHERALS_PRIORITY_DEFAULT, SLEEP_RETENTION_MODULE_TG0);
|
||||
ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for digital peripherals (Timer Group) retention");
|
||||
ESP_LOGI(TAG, "Timer Group sleep retention initialization");
|
||||
esp_err_t err = sleep_retention_entries_create(tg_regs_retention, ARRAY_SIZE(tg_regs_retention), SLEEP_RETENTION_PERIPHERALS_PRIORITY_DEFAULT, SLEEP_RETENTION_MODULE_SYS_PERIPH);
|
||||
ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for digital peripherals (%s) retention", "Timer Group");
|
||||
ESP_LOGD(TAG, "Timer Group sleep retention initialization");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t sleep_sys_periph_iomux_retention_init(void)
|
||||
static __attribute__((unused)) esp_err_t sleep_sys_periph_iomux_retention_init(void *arg)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32C6
|
||||
#define N_REGS_IOMUX_0() (((PERIPHS_IO_MUX_SPID_U - REG_IO_MUX_BASE) / 4) + 1)
|
||||
|
@ -143,13 +143,13 @@ esp_err_t sleep_sys_periph_iomux_retention_init(void)
|
|||
[3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x03), DR_REG_GPIO_BASE, DR_REG_GPIO_BASE, N_REGS_IOMUX_3(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }
|
||||
};
|
||||
|
||||
esp_err_t err = sleep_retention_entries_create(iomux_regs_retention, ARRAY_SIZE(iomux_regs_retention), SLEEP_RETENTION_PERIPHERALS_PRIORITY_DEFAULT, SLEEP_RETENTION_MODULE_IOMUX);
|
||||
ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for digital peripherals (IO Matrix) retention");
|
||||
ESP_LOGI(TAG, "IO Matrix sleep retention initialization");
|
||||
esp_err_t err = sleep_retention_entries_create(iomux_regs_retention, ARRAY_SIZE(iomux_regs_retention), SLEEP_RETENTION_PERIPHERALS_PRIORITY_DEFAULT, SLEEP_RETENTION_MODULE_SYS_PERIPH);
|
||||
ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for digital peripherals (%s) retention", "IO Matrix");
|
||||
ESP_LOGD(TAG, "IO Matrix sleep retention initialization");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t sleep_sys_periph_spimem_retention_init(void)
|
||||
static __attribute__((unused)) esp_err_t sleep_sys_periph_spimem_retention_init(void *arg)
|
||||
{
|
||||
#define N_REGS_SPI1_MEM_0() (((SPI_MEM_SPI_SMEM_DDR_REG(1) - REG_SPI_MEM_BASE(1)) / 4) + 1)
|
||||
#define N_REGS_SPI1_MEM_1() (((SPI_MEM_SPI_SMEM_AC_REG(1) - SPI_MEM_SPI_FMEM_PMS0_ATTR_REG(1)) / 4) + 1)
|
||||
|
@ -175,13 +175,13 @@ esp_err_t sleep_sys_periph_spimem_retention_init(void)
|
|||
[7] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x07), SPI_MEM_MMU_POWER_CTRL_REG(0), SPI_MEM_MMU_POWER_CTRL_REG(0), N_REGS_SPI0_MEM_3(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }
|
||||
};
|
||||
|
||||
esp_err_t err = sleep_retention_entries_create(spimem_regs_retention, ARRAY_SIZE(spimem_regs_retention), SLEEP_RETENTION_PERIPHERALS_PRIORITY_DEFAULT, SLEEP_RETENTION_MODULE_SPIMEM);
|
||||
ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for digital peripherals (SPI mem) retention");
|
||||
ESP_LOGI(TAG, "SPI Mem sleep retention initialization");
|
||||
esp_err_t err = sleep_retention_entries_create(spimem_regs_retention, ARRAY_SIZE(spimem_regs_retention), SLEEP_RETENTION_PERIPHERALS_PRIORITY_DEFAULT, SLEEP_RETENTION_MODULE_SYS_PERIPH);
|
||||
ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for digital peripherals (%s) retention", "SPI mem");
|
||||
ESP_LOGD(TAG, "SPI Mem sleep retention initialization");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t sleep_sys_periph_systimer_retention_init(void)
|
||||
static __attribute__((unused)) esp_err_t sleep_sys_periph_systimer_retention_init(void *arg)
|
||||
{
|
||||
#define N_REGS_SYSTIMER_0() (((SYSTIMER_TARGET2_CONF_REG - SYSTIMER_TARGET0_HI_REG) / 4) + 1)
|
||||
|
||||
|
@ -214,30 +214,30 @@ esp_err_t sleep_sys_periph_systimer_retention_init(void)
|
|||
[18] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SYSTIMER_LINK(0x12), SYSTIMER_INT_ENA_REG, SYSTIMER_INT_ENA_REG, 1, 0, 0), .owner = ENTRY(0) | ENTRY(2) } /* Systimer intr enable */
|
||||
};
|
||||
|
||||
esp_err_t err = sleep_retention_entries_create(systimer_regs_retention, ARRAY_SIZE(systimer_regs_retention), SLEEP_RETENTION_PERIPHERALS_PRIORITY_DEFAULT, SLEEP_RETENTION_MODULE_SYSTIMER);
|
||||
ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for digital peripherals (SysTimer) retention");
|
||||
ESP_LOGI(TAG, "SysTimer sleep retention initialization");
|
||||
esp_err_t err = sleep_retention_entries_create(systimer_regs_retention, ARRAY_SIZE(systimer_regs_retention), SLEEP_RETENTION_PERIPHERALS_PRIORITY_DEFAULT, SLEEP_RETENTION_MODULE_SYS_PERIPH);
|
||||
ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for digital peripherals (%s) retention", "SysTimer");
|
||||
ESP_LOGD(TAG, "SysTimer sleep retention initialization");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t sleep_sys_periph_retention_init(void)
|
||||
static __attribute__((unused)) esp_err_t sleep_sys_periph_retention_init(void *arg)
|
||||
{
|
||||
esp_err_t err;
|
||||
err = sleep_sys_periph_intr_matrix_retention_init();
|
||||
err = sleep_sys_periph_intr_matrix_retention_init(arg);
|
||||
if(err) goto error;
|
||||
err = sleep_sys_periph_hp_system_retention_init();
|
||||
err = sleep_sys_periph_hp_system_retention_init(arg);
|
||||
if(err) goto error;
|
||||
err = sleep_sys_periph_tee_apm_retention_init();
|
||||
err = sleep_sys_periph_tee_apm_retention_init(arg);
|
||||
if(err) goto error;
|
||||
err = sleep_sys_periph_uart0_retention_init();
|
||||
err = sleep_sys_periph_uart0_retention_init(arg);
|
||||
if(err) goto error;
|
||||
err = sleep_sys_periph_tg0_retention_init();
|
||||
err = sleep_sys_periph_tg0_retention_init(arg);
|
||||
if(err) goto error;
|
||||
err = sleep_sys_periph_iomux_retention_init();
|
||||
err = sleep_sys_periph_iomux_retention_init(arg);
|
||||
if(err) goto error;
|
||||
err = sleep_sys_periph_spimem_retention_init();
|
||||
err = sleep_sys_periph_spimem_retention_init(arg);
|
||||
if(err) goto error;
|
||||
err = sleep_sys_periph_systimer_retention_init();
|
||||
err = sleep_sys_periph_systimer_retention_init(arg);
|
||||
|
||||
error:
|
||||
return err;
|
||||
|
@ -245,23 +245,31 @@ error:
|
|||
|
||||
bool peripheral_domain_pd_allowed(void)
|
||||
{
|
||||
const uint32_t modules = sleep_retention_get_modules();
|
||||
const uint32_t mask = (const uint32_t) (
|
||||
SLEEP_RETENTION_MODULE_INTR_MATRIX | \
|
||||
SLEEP_RETENTION_MODULE_HP_SYSTEM | \
|
||||
SLEEP_RETENTION_MODULE_TEE_APM | \
|
||||
SLEEP_RETENTION_MODULE_UART0 | \
|
||||
SLEEP_RETENTION_MODULE_TG0 | \
|
||||
SLEEP_RETENTION_MODULE_IOMUX | \
|
||||
SLEEP_RETENTION_MODULE_SPIMEM | \
|
||||
SLEEP_RETENTION_MODULE_SYSTIMER);
|
||||
return ((modules & mask) == mask);
|
||||
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||
const uint32_t inited_modules = sleep_retention_get_inited_modules();
|
||||
const uint32_t created_modules = sleep_retention_get_created_modules();
|
||||
const uint32_t mask = (const uint32_t) (BIT(SLEEP_RETENTION_MODULE_SYS_PERIPH));
|
||||
|
||||
return ((inited_modules & mask) == (created_modules & mask));
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||
ESP_SYSTEM_INIT_FN(sleep_sys_periph_startup_init, BIT(0), 107)
|
||||
{
|
||||
sleep_sys_periph_retention_init();
|
||||
sleep_retention_module_init_param_t init_param = {
|
||||
.cbs = { .create = { .handle = sleep_sys_periph_retention_init, .arg = NULL } },
|
||||
.depends = BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM)
|
||||
};
|
||||
esp_err_t err = sleep_retention_module_init(SLEEP_RETENTION_MODULE_SYS_PERIPH, &init_param);
|
||||
if (err == ESP_OK) {
|
||||
err = sleep_retention_module_allocate(SLEEP_RETENTION_MODULE_SYS_PERIPH);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "failed to allocate sleep retention linked list for system peripherals retention");
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -81,7 +81,7 @@ TEST_CASE("gpio_etm_self_trigger", "[etm]")
|
|||
// delete gpio etm task without remove all bounded GPIOs should fail
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, esp_etm_del_task(gpio_task));
|
||||
// remove unrelated GPIO from the task should fail
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, gpio_etm_task_rm_gpio(gpio_task, 10));
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, gpio_etm_task_rm_gpio(gpio_task, 10));
|
||||
|
||||
// delete etm primitives
|
||||
TEST_ESP_OK(gpio_etm_task_rm_gpio(gpio_task, output_gpio));
|
||||
|
@ -90,3 +90,118 @@ TEST_CASE("gpio_etm_self_trigger", "[etm]")
|
|||
TEST_ESP_OK(esp_etm_del_event(gpio_event));
|
||||
TEST_ESP_OK(esp_etm_del_channel(etm_channel_a));
|
||||
}
|
||||
|
||||
TEST_CASE("gpio_etm_self_trigger_multi_action", "[etm]")
|
||||
{
|
||||
// GPIO 0 pos edge event ---> GPIO 1 set level task
|
||||
// GPIO 22 pos edge event ---> GPIO 1 clear level task
|
||||
|
||||
const uint32_t input_gpio1 = 0;
|
||||
const uint32_t input_gpio2 = 22;
|
||||
const uint32_t output_gpio = 1;
|
||||
printf("allocate etm channels\r\n");
|
||||
esp_etm_channel_config_t etm_config = {};
|
||||
esp_etm_channel_handle_t etm_channel_a = NULL;
|
||||
esp_etm_channel_handle_t etm_channel_b = NULL;
|
||||
TEST_ESP_OK(esp_etm_new_channel(&etm_config, &etm_channel_a));
|
||||
TEST_ESP_OK(esp_etm_new_channel(&etm_config, &etm_channel_b));
|
||||
|
||||
printf("allocate GPIO etm event and task\r\n");
|
||||
esp_etm_task_handle_t gpio_task_a = NULL;
|
||||
esp_etm_event_handle_t gpio_event_a = NULL;
|
||||
esp_etm_task_handle_t gpio_task_b = NULL;
|
||||
esp_etm_event_handle_t gpio_event_b = NULL;
|
||||
gpio_etm_event_config_t gpio_event_config = {};
|
||||
gpio_event_config.edges[0] = GPIO_ETM_EVENT_EDGE_POS;
|
||||
TEST_ESP_OK(gpio_new_etm_event(&gpio_event_config, &gpio_event_a));
|
||||
esp_etm_event_handle_t gpio_event_c = NULL; // an extra event only used for testing binding
|
||||
gpio_event_config.edges[1] = GPIO_ETM_EVENT_EDGE_ANY;
|
||||
TEST_ESP_OK(gpio_new_etm_event(&gpio_event_config, &gpio_event_b, &gpio_event_c));
|
||||
gpio_etm_task_config_t gpio_task_config = {};
|
||||
gpio_task_config.actions[0] = GPIO_ETM_TASK_ACTION_CLR;
|
||||
gpio_task_config.actions[1] = GPIO_ETM_TASK_ACTION_SET;
|
||||
TEST_ESP_OK(gpio_new_etm_task(&gpio_task_config, &gpio_task_b, &gpio_task_a));
|
||||
|
||||
// bind GPIO to the event and task
|
||||
TEST_ESP_OK(gpio_etm_event_bind_gpio(gpio_event_a, input_gpio1));
|
||||
TEST_ESP_OK(gpio_etm_event_bind_gpio(gpio_event_b, input_gpio2));
|
||||
TEST_ESP_OK(gpio_etm_task_add_gpio(gpio_task_a, output_gpio));
|
||||
TEST_ESP_OK(gpio_etm_task_add_gpio(gpio_task_b, output_gpio));
|
||||
|
||||
// try an infeasible bind of second event to a GPIO
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, gpio_etm_event_bind_gpio(gpio_event_c, input_gpio1));
|
||||
// try a feasible bind of second event to a GPIO
|
||||
TEST_ESP_OK(gpio_etm_event_bind_gpio(gpio_event_c, input_gpio2));
|
||||
// delete the event to unbind it from the GPIO
|
||||
TEST_ESP_OK(esp_etm_del_event(gpio_event_c));
|
||||
|
||||
printf("initialize gpio\r\n");
|
||||
gpio_config_t task_gpio_config = {
|
||||
.intr_type = GPIO_INTR_DISABLE,
|
||||
.mode = GPIO_MODE_INPUT_OUTPUT, // we want to read the GPIO value, so it should be input and output
|
||||
.pin_bit_mask = 1ULL << output_gpio,
|
||||
};
|
||||
TEST_ESP_OK(gpio_config(&task_gpio_config));
|
||||
// set the initial level
|
||||
TEST_ESP_OK(gpio_set_level(output_gpio, 0));
|
||||
|
||||
gpio_config_t event_gpio_config = {
|
||||
.intr_type = GPIO_INTR_DISABLE,
|
||||
.mode = GPIO_MODE_INPUT_OUTPUT, // we want to simulate the edge signal by software, so it should be input and output
|
||||
.pull_up_en = GPIO_PULLUP_ENABLE,
|
||||
.pull_down_en = GPIO_PULLDOWN_DISABLE,
|
||||
.pin_bit_mask = (1ULL << input_gpio1) | (1ULL << input_gpio2),
|
||||
};
|
||||
TEST_ESP_OK(gpio_config(&event_gpio_config));
|
||||
// set the initial level
|
||||
TEST_ESP_OK(gpio_set_level(input_gpio1, 0));
|
||||
TEST_ESP_OK(gpio_set_level(input_gpio2, 0));
|
||||
|
||||
printf("connect event and task to the channel\r\n");
|
||||
TEST_ESP_OK(esp_etm_channel_connect(etm_channel_a, gpio_event_a, gpio_task_a));
|
||||
TEST_ESP_OK(esp_etm_channel_connect(etm_channel_b, gpio_event_b, gpio_task_b));
|
||||
|
||||
TEST_ESP_OK(esp_etm_channel_enable(etm_channel_a));
|
||||
TEST_ESP_OK(esp_etm_channel_enable(etm_channel_b));
|
||||
|
||||
// input_gpio1 pos edge ---> output_gpio level being set
|
||||
TEST_ESP_OK(gpio_set_level(input_gpio1, 1));
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
TEST_ASSERT_EQUAL(1, gpio_get_level(output_gpio));
|
||||
|
||||
// input_gpio1 neg edge does not affect output_gpio level
|
||||
TEST_ESP_OK(gpio_set_level(input_gpio1, 0));
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
TEST_ASSERT_EQUAL(1, gpio_get_level(output_gpio));
|
||||
|
||||
// input_gpio2 pos edge ---> output_gpio level being cleared
|
||||
TEST_ESP_OK(gpio_set_level(input_gpio2, 1));
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
TEST_ASSERT_EQUAL(0, gpio_get_level(output_gpio));
|
||||
|
||||
// input_gpio2 neg edge does not affect output_gpio level
|
||||
TEST_ESP_OK(gpio_set_level(input_gpio2, 0));
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
TEST_ASSERT_EQUAL(0, gpio_get_level(output_gpio));
|
||||
|
||||
// Create a new gpio etm task separately, and add it to the output_gpio should fail (the task does not belong to the same GPIO ETM task channel as gpio_task_a and gpio_task_b)
|
||||
esp_etm_task_handle_t gpio_task_c = NULL;
|
||||
gpio_etm_task_config_t gpio_task_config_2 = {
|
||||
.action = GPIO_ETM_TASK_ACTION_TOG,
|
||||
};
|
||||
TEST_ESP_OK(gpio_new_etm_task(&gpio_task_config_2, &gpio_task_c));
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, gpio_etm_task_add_gpio(gpio_task_c, output_gpio));
|
||||
|
||||
// delete etm primitives
|
||||
TEST_ESP_OK(gpio_etm_task_rm_gpio(gpio_task_a, output_gpio));
|
||||
TEST_ESP_OK(gpio_etm_task_rm_gpio(gpio_task_b, output_gpio));
|
||||
TEST_ESP_OK(esp_etm_channel_disable(etm_channel_a));
|
||||
TEST_ESP_OK(esp_etm_channel_disable(etm_channel_b));
|
||||
TEST_ESP_OK(esp_etm_del_task(gpio_task_a));
|
||||
TEST_ESP_OK(esp_etm_del_task(gpio_task_b));
|
||||
TEST_ESP_OK(esp_etm_del_task(gpio_task_c));
|
||||
TEST_ESP_OK(esp_etm_del_event(gpio_event_a));
|
||||
TEST_ESP_OK(esp_etm_del_event(gpio_event_b));
|
||||
TEST_ESP_OK(esp_etm_del_channel(etm_channel_a));
|
||||
TEST_ESP_OK(esp_etm_del_channel(etm_channel_b));
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ static const char* TAG = "btbb_init";
|
|||
#define BTBB_LINK_OWNER ENTRY(0) | ENTRY(2)
|
||||
#endif // SOC_PM_RETENTION_HAS_CLOCK_BUG
|
||||
|
||||
static esp_err_t btbb_sleep_retention_init(void)
|
||||
static esp_err_t btbb_sleep_retention_init(void *arg)
|
||||
{
|
||||
const static sleep_retention_entries_config_t btbb_regs_retention[] = {
|
||||
[0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_MODEM_BT_BB_LINK(0x00), BB_PART_0_ADDR, BB_PART_0_ADDR, BB_PART_0_SIZE, 0, 0), .owner = BTBB_LINK_OWNER },
|
||||
|
@ -37,13 +37,20 @@ static esp_err_t btbb_sleep_retention_init(void)
|
|||
};
|
||||
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");
|
||||
ESP_LOGD(TAG, "btbb sleep retention initialization");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void btbb_sleep_retention_deinit(void)
|
||||
{
|
||||
sleep_retention_entries_destroy(SLEEP_RETENTION_MODULE_BT_BB);
|
||||
esp_err_t err = sleep_retention_module_free(SLEEP_RETENTION_MODULE_BT_BB);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "failed to destroy sleep retention linked list for btbb retention");
|
||||
}
|
||||
err = sleep_retention_module_deinit(SLEEP_RETENTION_MODULE_BT_BB);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "Modem BT BB retention callback unregister failed");
|
||||
}
|
||||
}
|
||||
#endif // SOC_PM_MODEM_RETENTION_BY_REGDMA && CONFIG_FREERTOS_USE_TICKLESS_IDLE
|
||||
|
||||
|
@ -54,7 +61,19 @@ void esp_btbb_enable(void)
|
|||
if (s_btbb_access_ref == 0) {
|
||||
bt_bb_v2_init_cmplx(BTBB_ENABLE_VERSION_PRINT);
|
||||
#if SOC_PM_MODEM_RETENTION_BY_REGDMA && CONFIG_FREERTOS_USE_TICKLESS_IDLE
|
||||
btbb_sleep_retention_init();
|
||||
sleep_retention_module_init_param_t init_param = {
|
||||
.cbs = { .create = { .handle = btbb_sleep_retention_init, .arg = NULL } },
|
||||
.depends = BIT(SLEEP_RETENTION_MODULE_CLOCK_MODEM)
|
||||
};
|
||||
esp_err_t err = sleep_retention_module_init(SLEEP_RETENTION_MODULE_BT_BB, &init_param);
|
||||
if (err == ESP_OK) {
|
||||
err = sleep_retention_module_allocate(SLEEP_RETENTION_MODULE_BT_BB);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "failed to allocate sleep retention linked list for btbb retention");
|
||||
}
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Modem BT BB retention callback register failed");
|
||||
}
|
||||
#endif // SOC_PM_MODEM_RETENTION_BY_REGDMA && CONFIG_FREERTOS_USE_TICKLESS_IDLE
|
||||
}
|
||||
s_btbb_access_ref++;
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "esp_efuse.h"
|
||||
#include "esp_timer.h"
|
||||
#include "esp_private/esp_sleep_internal.h"
|
||||
#include "esp_check.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/portmacro.h"
|
||||
|
@ -313,7 +314,7 @@ void esp_phy_disable(esp_phy_modem_t modem)
|
|||
#endif
|
||||
}
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
// Update WiFi MAC time before disalbe WiFi/BT common peripheral clock
|
||||
// Update WiFi MAC time before disable WiFi/BT common peripheral clock
|
||||
phy_update_wifi_mac_time(true, esp_timer_get_time());
|
||||
#endif
|
||||
// Disable WiFi/BT common peripheral clock. Do not disable clock for hardware RNG
|
||||
|
@ -412,7 +413,20 @@ static uint8_t s_macbb_backup_mem_ref = 0;
|
|||
/* Reference of powering down MAC and BB */
|
||||
static bool s_mac_bb_pu = true;
|
||||
#elif SOC_PM_MODEM_RETENTION_BY_REGDMA
|
||||
static void *s_mac_bb_tx_base = NULL;
|
||||
static esp_err_t sleep_retention_wifi_bb_init(void *arg)
|
||||
{
|
||||
const static sleep_retention_entries_config_t bb_regs_retention[] = {
|
||||
[0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b00, 0x600a7000, 0x600a7000, 121, 0, 0), .owner = BIT(0) | BIT(1) }, /* AGC */
|
||||
[1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b01, 0x600a7400, 0x600a7400, 14, 0, 0), .owner = BIT(0) | BIT(1) }, /* TX */
|
||||
[2] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b02, 0x600a7800, 0x600a7800, 136, 0, 0), .owner = BIT(0) | BIT(1) }, /* NRX */
|
||||
[3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b03, 0x600a7c00, 0x600a7c00, 53, 0, 0), .owner = BIT(0) | BIT(1) }, /* BB */
|
||||
[4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b05, 0x600a0000, 0x600a0000, 58, 0, 0), .owner = BIT(0) | BIT(1) } /* FE COEX */
|
||||
};
|
||||
esp_err_t err = sleep_retention_entries_create(bb_regs_retention, ARRAY_SIZE(bb_regs_retention), 3, SLEEP_RETENTION_MODULE_WIFI_BB);
|
||||
ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for modem (%s) retention", "WiFi BB");
|
||||
ESP_LOGD(TAG, "WiFi BB sleep retention initialization");
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif // SOC_PM_MODEM_RETENTION_BY_BACKUPDMA
|
||||
|
||||
void esp_mac_bb_pd_mem_init(void)
|
||||
|
@ -425,22 +439,18 @@ void esp_mac_bb_pd_mem_init(void)
|
|||
}
|
||||
_lock_release(&s_phy_access_lock);
|
||||
#elif SOC_PM_MODEM_RETENTION_BY_REGDMA
|
||||
const static sleep_retention_entries_config_t bb_regs_retention[] = {
|
||||
[0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b00, 0x600a7000, 0x600a7000, 121, 0, 0), .owner = BIT(0) | BIT(1) }, /* AGC */
|
||||
[1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b01, 0x600a7400, 0x600a7400, 14, 0, 0), .owner = BIT(0) | BIT(1) }, /* TX */
|
||||
[2] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b02, 0x600a7800, 0x600a7800, 136, 0, 0), .owner = BIT(0) | BIT(1) }, /* NRX */
|
||||
[3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b03, 0x600a7c00, 0x600a7c00, 53, 0, 0), .owner = BIT(0) | BIT(1) }, /* BB */
|
||||
[4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b05, 0x600a0000, 0x600a0000, 58, 0, 0), .owner = BIT(0) | BIT(1) } /* FE COEX */
|
||||
sleep_retention_module_init_param_t init_param = {
|
||||
.cbs = { .create = { .handle = sleep_retention_wifi_bb_init, .arg = NULL } },
|
||||
.depends = BIT(SLEEP_RETENTION_MODULE_CLOCK_MODEM)
|
||||
};
|
||||
esp_err_t err = ESP_OK;
|
||||
_lock_acquire(&s_phy_access_lock);
|
||||
s_mac_bb_tx_base = sleep_retention_find_link_by_id(0x0b01);
|
||||
if (s_mac_bb_tx_base == NULL) {
|
||||
err = sleep_retention_entries_create(bb_regs_retention, ARRAY_SIZE(bb_regs_retention), 3, SLEEP_RETENTION_MODULE_WIFI_BB);
|
||||
}
|
||||
_lock_release(&s_phy_access_lock);
|
||||
esp_err_t err = sleep_retention_module_init(SLEEP_RETENTION_MODULE_WIFI_BB, &init_param);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "failed to allocate memory for WiFi baseband retention");
|
||||
ESP_LOGW(TAG, "WiFi BB sleep retention init failed");
|
||||
return;
|
||||
}
|
||||
err = sleep_retention_module_allocate(SLEEP_RETENTION_MODULE_WIFI_BB);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "failed to allocate sleep retention linked list for wifi bb retention");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -456,10 +466,15 @@ void esp_mac_bb_pd_mem_deinit(void)
|
|||
}
|
||||
_lock_release(&s_phy_access_lock);
|
||||
#elif SOC_PM_MODEM_RETENTION_BY_REGDMA
|
||||
_lock_acquire(&s_phy_access_lock);
|
||||
sleep_retention_entries_destroy(SLEEP_RETENTION_MODULE_WIFI_BB);
|
||||
s_mac_bb_tx_base = NULL;
|
||||
_lock_release(&s_phy_access_lock);
|
||||
esp_err_t err = sleep_retention_module_free(SLEEP_RETENTION_MODULE_WIFI_BB);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "failed to free sleep retention linked list for wifi bb retention");
|
||||
return;
|
||||
}
|
||||
err = sleep_retention_module_deinit(SLEEP_RETENTION_MODULE_WIFI_BB);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "WiFi BB sleep retention deinit failed");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -903,7 +918,7 @@ static uint8_t phy_find_bin_type_according_country(const char* country)
|
|||
|
||||
if (i == sizeof(s_country_code_map_type_table)/sizeof(phy_country_to_bin_type_t)) {
|
||||
phy_init_data_type = ESP_PHY_INIT_DATA_TYPE_DEFAULT;
|
||||
ESP_LOGW(TAG, "Use the default certification code beacuse %c%c doesn't have a certificate", country[0], country[1]);
|
||||
ESP_LOGW(TAG, "Use the default certification code because %c%c doesn't have a certificate", country[0], country[1]);
|
||||
}
|
||||
|
||||
return phy_init_data_type;
|
||||
|
|
|
@ -1093,7 +1093,6 @@ r_ble_lll_conn_coex_dpc_update_on_event_scheduled = 0x400014e4;
|
|||
r_ble_lll_conn_coex_dpc_update_on_event_started = 0x400014e8;
|
||||
r_ble_lll_conn_cth_flow_alloc_credit = 0x400014ec;
|
||||
r_ble_lll_conn_current_sm_over = 0x400014f4;
|
||||
r_ble_lll_conn_event_end_timer_cb = 0x40001508;
|
||||
r_ble_lll_conn_event_is_over = 0x40001510;
|
||||
r_ble_lll_conn_event_start_cb = 0x40001514;
|
||||
r_ble_lll_conn_free_rx_mbuf = 0x40001518;
|
||||
|
@ -1483,7 +1482,7 @@ is_lmac_idle = 0x40001b0c;
|
|||
/*lmacAdjustTimestamp = 0x40001b10;*/
|
||||
lmacDiscardAgedMSDU = 0x40001b14;
|
||||
/*lmacDiscardMSDU = 0x40001b18;*/
|
||||
lmacEndFrameExchangeSequence = 0x40001b1c;
|
||||
/*lmacEndFrameExchangeSequence = 0x40001b1c;*/
|
||||
lmacIsIdle = 0x40001b20;
|
||||
lmacIsLongFrame = 0x40001b24;
|
||||
/*lmacMSDUAged = 0x40001b28;*/
|
||||
|
@ -1845,7 +1844,7 @@ ic_ebuf_recycle_rx = 0x40001fa0;
|
|||
ic_ebuf_recycle_tx = 0x40001fa4;
|
||||
ic_reset_rx_ba = 0x40001fa8;
|
||||
ieee80211_align_eb = 0x40001fac;
|
||||
ieee80211_ampdu_reorder = 0x40001fb0;
|
||||
/*ieee80211_ampdu_reorder = 0x40001fb0;*/
|
||||
ieee80211_ampdu_start_age_timer = 0x40001fb4;
|
||||
/*ieee80211_encap_esfbuf = 0x40001fb8;*/
|
||||
ieee80211_is_tx_allowed = 0x40001fbc;
|
||||
|
@ -1868,8 +1867,8 @@ ieee80211_decap = 0x40001ffc;
|
|||
ieee80211_set_tx_pti = 0x40002000;
|
||||
wifi_is_started = 0x40002004;
|
||||
ieee80211_gettid = 0x40002008;
|
||||
ieee80211_ccmp_decrypt = 0x4000200c;
|
||||
ieee80211_ccmp_encrypt = 0x40002010;
|
||||
/* ieee80211_ccmp_decrypt = 0x4000200c; */
|
||||
/* ieee80211_ccmp_encrypt = 0x40002010; */
|
||||
ccmp_encap = 0x40002014;
|
||||
ccmp_decap = 0x40002018;
|
||||
tkip_encap = 0x4000201c;
|
||||
|
@ -1923,7 +1922,7 @@ ieee80211_crypto_aes_128_cmac_encrypt = 0x40002100;
|
|||
ieee80211_alloc_tx_buf = 0x40002108;
|
||||
/* ieee80211_output_do = 0x4000210c; */
|
||||
/* ieee80211_send_nulldata = 0x40002110; */
|
||||
ieee80211_setup_robust_mgmtframe = 0x40002114;
|
||||
/* ieee80211_setup_robust_mgmtframe = 0x40002114; */
|
||||
ieee80211_encap_null_data = 0x4000211c;
|
||||
ieee80211_send_deauth = 0x40002120;
|
||||
ieee80211_alloc_deauth = 0x40002124;
|
||||
|
|
|
@ -1516,7 +1516,7 @@ is_lmac_idle = 0x400015e8;
|
|||
/*lmacAdjustTimestamp = 0x400015ec;*/
|
||||
lmacDiscardAgedMSDU = 0x400015f0;
|
||||
/*lmacDiscardMSDU = 0x400015f4;*/
|
||||
lmacEndFrameExchangeSequence = 0x400015f8;
|
||||
/*lmacEndFrameExchangeSequence = 0x400015f8;*/
|
||||
lmacIsIdle = 0x400015fc;
|
||||
lmacIsLongFrame = 0x40001600;
|
||||
/*lmacMSDUAged = 0x40001604;*/
|
||||
|
@ -1717,7 +1717,7 @@ ic_ebuf_recycle_rx = 0x40001844;
|
|||
ic_ebuf_recycle_tx = 0x40001848;
|
||||
ic_reset_rx_ba = 0x4000184c;
|
||||
ieee80211_align_eb = 0x40001850;
|
||||
ieee80211_ampdu_reorder = 0x40001854;
|
||||
/*ieee80211_ampdu_reorder = 0x40001854;*/
|
||||
ieee80211_ampdu_start_age_timer = 0x40001858;
|
||||
/*ieee80211_encap_esfbuf = 0x4000185c;*/
|
||||
ieee80211_is_tx_allowed = 0x40001860;
|
||||
|
|
|
@ -31,7 +31,7 @@ ic_ebuf_recycle_rx = 0x40000b70;
|
|||
ic_ebuf_recycle_tx = 0x40000b74;
|
||||
ic_reset_rx_ba = 0x40000b78;
|
||||
ieee80211_align_eb = 0x40000b7c;
|
||||
ieee80211_ampdu_reorder = 0x40000b80;
|
||||
/*ieee80211_ampdu_reorder = 0x40000b80;*/
|
||||
ieee80211_ampdu_start_age_timer = 0x40000b84;
|
||||
/*ieee80211_encap_esfbuf = 0x40000b88;*/
|
||||
ieee80211_is_tx_allowed = 0x40000b8c;
|
||||
|
|
|
@ -37,7 +37,7 @@ is_lmac_idle = 0x40000c14;
|
|||
/*lmacAdjustTimestamp = 0x40000c18;*/
|
||||
lmacDiscardAgedMSDU = 0x40000c1c;
|
||||
/*lmacDiscardMSDU = 0x40000c20;*/
|
||||
lmacEndFrameExchangeSequence = 0x40000c24;
|
||||
/*lmacEndFrameExchangeSequence = 0x40000c24;*/
|
||||
lmacIsIdle = 0x40000c28;
|
||||
lmacIsLongFrame = 0x40000c2c;
|
||||
/*lmacMSDUAged = 0x40000c30;*/
|
||||
|
@ -80,7 +80,7 @@ pm_on_data_rx = 0x40000ca8;
|
|||
pm_sleep_for = 0x40000cc4;
|
||||
//pm_tbtt_process = 0x40000cc8;
|
||||
ppAMPDU2Normal = 0x40000ccc;
|
||||
ppAssembleAMPDU = 0x40000cd0;
|
||||
/* ppAssembleAMPDU = 0x40000cd0; */
|
||||
ppCalFrameTimes = 0x40000cd4;
|
||||
ppCalSubFrameLength = 0x40000cd8;
|
||||
//ppCalTxAMPDULength = 0x40000cdc;
|
||||
|
|
|
@ -1816,7 +1816,7 @@ is_lmac_idle = 0x400052f8;
|
|||
/*lmacAdjustTimestamp = 0x40005304;*/
|
||||
lmacDiscardAgedMSDU = 0x40005310;
|
||||
/*lmacDiscardMSDU = 0x4000531c;*/
|
||||
lmacEndFrameExchangeSequence = 0x40005328;
|
||||
/*lmacEndFrameExchangeSequence = 0x40005328;*/
|
||||
lmacIsIdle = 0x40005334;
|
||||
lmacIsLongFrame = 0x40005340;
|
||||
/*lmacMSDUAged = 0x4000534c;*/
|
||||
|
@ -2024,7 +2024,7 @@ ic_ebuf_recycle_rx = 0x40005a24;
|
|||
ic_ebuf_recycle_tx = 0x40005a30;
|
||||
ic_reset_rx_ba = 0x40005a3c;
|
||||
ieee80211_align_eb = 0x40005a48;
|
||||
ieee80211_ampdu_reorder = 0x40005a54;
|
||||
/* ieee80211_ampdu_reorder = 0x40005a54; */
|
||||
ieee80211_ampdu_start_age_timer = 0x40005a60;
|
||||
/* ieee80211_encap_esfbuf = 0x40005a6c; */
|
||||
ieee80211_is_tx_allowed = 0x40005a78;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -535,6 +535,18 @@ static void esp_phy_disable_wrapper(void)
|
|||
esp_phy_disable(PHY_MODEM_WIFI);
|
||||
}
|
||||
|
||||
#if SOC_PM_MODEM_RETENTION_BY_REGDMA
|
||||
static void regdma_link_set_write_wait_content_wrapper(void *addr, uint32_t value, uint32_t mask)
|
||||
{
|
||||
regdma_link_set_write_wait_content(addr, value, mask);
|
||||
}
|
||||
|
||||
static void *sleep_retention_find_link_by_id_wrapper(int id)
|
||||
{
|
||||
return sleep_retention_find_link_by_id(id);
|
||||
}
|
||||
#endif
|
||||
|
||||
wifi_osi_funcs_t g_wifi_osi_funcs = {
|
||||
._version = ESP_WIFI_OS_ADAPTER_VERSION,
|
||||
._env_is_chip = esp_coex_common_env_is_chip_wrapper,
|
||||
|
@ -650,10 +662,8 @@ wifi_osi_funcs_t g_wifi_osi_funcs = {
|
|||
._coex_schm_curr_phase_get = coex_schm_curr_phase_get_wrapper,
|
||||
._coex_register_start_cb = coex_register_start_cb_wrapper,
|
||||
#if SOC_PM_MODEM_RETENTION_BY_REGDMA
|
||||
._regdma_link_set_write_wait_content = regdma_link_set_write_wait_content,
|
||||
._sleep_retention_find_link_by_id = sleep_retention_find_link_by_id,
|
||||
._sleep_retention_entries_create = (int (*)(const void *, int, int, int))sleep_retention_entries_create,
|
||||
._sleep_retention_entries_destroy = sleep_retention_entries_destroy,
|
||||
._regdma_link_set_write_wait_content = regdma_link_set_write_wait_content_wrapper,
|
||||
._sleep_retention_find_link_by_id = sleep_retention_find_link_by_id_wrapper,
|
||||
#endif
|
||||
._coex_schm_process_restart = coex_schm_process_restart_wrapper,
|
||||
._coex_schm_register_cb = coex_schm_register_cb_wrapper,
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
@ -72,7 +72,7 @@ typedef enum {
|
|||
#define WIFI_LOG_SUBMODULE_INIT (1) /*logs related to initialization*/
|
||||
#define WIFI_LOG_SUBMODULE_IOCTL (1<<1) /*logs related to API calling*/
|
||||
#define WIFI_LOG_SUBMODULE_CONN (1<<2) /*logs related to connecting*/
|
||||
#define WIFI_LOG_SUBMODULE_SCAN (1<<3) /*logs related to scaning*/
|
||||
#define WIFI_LOG_SUBMODULE_SCAN (1<<3) /*logs related to scanning*/
|
||||
|
||||
|
||||
/**
|
||||
|
@ -164,9 +164,9 @@ typedef void (*wifi_netstack_buf_free_cb_t)(void *netstack_buf);
|
|||
* supports reference counter.
|
||||
*
|
||||
* @param wifi_if : wifi interface id
|
||||
* @param buffer : the buffer to be tansmit
|
||||
* @param buffer : the buffer to be transmit
|
||||
* @param len : the length of buffer
|
||||
* @param netstack_buf : the netstack buffer related to bufffer
|
||||
* @param netstack_buf : the netstack buffer related to buffer
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK : Successfully transmit the buffer to wifi driver
|
||||
|
@ -539,6 +539,18 @@ void esp_wifi_power_domain_on(void);
|
|||
*/
|
||||
void esp_wifi_power_domain_off(void);
|
||||
|
||||
|
||||
#if (CONFIG_FREERTOS_USE_TICKLESS_IDLE && SOC_PM_MODEM_RETENTION_BY_REGDMA)
|
||||
/**
|
||||
* @brief Get wifi mac sleep retention hardware context configuration and size
|
||||
*
|
||||
* @param config_size: the wifi mac hardware context configuration size
|
||||
*
|
||||
* @return A pointer that point to wifi mac sleep renteiton hardware context configuration table
|
||||
*/
|
||||
void * esp_wifi_internal_mac_retention_context_get(int *config_size);
|
||||
#endif
|
||||
|
||||
#if CONFIG_MAC_BB_PD
|
||||
/**
|
||||
* @brief Enable or disable powering down MAC and baseband when Wi-Fi is sleeping.
|
||||
|
@ -562,12 +574,12 @@ void pm_mac_wakeup(void);
|
|||
#endif
|
||||
|
||||
/**
|
||||
* @breif TxDone callback function type. Should be registered using esp_wifi_set_tx_done_cb()
|
||||
* @brief TxDone callback function type. Should be registered using esp_wifi_set_tx_done_cb()
|
||||
*
|
||||
* @param ifidx The interface id that the tx callback has been triggered from
|
||||
* @param data Pointer to the data transmitted
|
||||
* @param data_len Length of the data transmitted
|
||||
* @param txStatus True:if the data was transmitted sucessfully False: if data transmission failed
|
||||
* @param txStatus True:if the data was transmitted successfully False: if data transmission failed
|
||||
*/
|
||||
typedef void (* wifi_tx_done_cb_t)(uint8_t ifidx, uint8_t *data, uint16_t *data_len, bool txStatus);
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2018-2021 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2018-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -152,8 +152,6 @@ typedef struct {
|
|||
#if CONFIG_IDF_TARGET_ESP32C6
|
||||
void (* _regdma_link_set_write_wait_content)(void *, uint32_t, uint32_t);
|
||||
void * (* _sleep_retention_find_link_by_id)(int);
|
||||
int (* _sleep_retention_entries_create)(const void *, int, int, int);
|
||||
void (* _sleep_retention_entries_destroy)(int);
|
||||
#endif
|
||||
int32_t _magic;
|
||||
} wifi_osi_funcs_t;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -240,6 +240,26 @@ typedef struct {
|
|||
uint32_t actual_suspend_time_ms[8]; /**< the actual suspend time for each flow id, unit: ms */
|
||||
} wifi_event_sta_itwt_suspend_t;
|
||||
|
||||
/**
|
||||
* @brief TWT types
|
||||
*/
|
||||
typedef enum {
|
||||
TWT_TYPE_INDIVIDUAL, /**< individual twt */
|
||||
TWT_TYPE_BROADCAST, /**< broadcast twt */
|
||||
TWT_TYPE_MAX, /**< the max value */
|
||||
} wifi_twt_type_t;
|
||||
|
||||
/** Argument structure for twt configuration */
|
||||
typedef struct {
|
||||
bool post_wakeup_event; /**< post twt wakeup event */
|
||||
} wifi_twt_config_t;
|
||||
|
||||
/** Argument structure for WIFI_EVENT_TWT_WAKEUP event */
|
||||
typedef struct {
|
||||
wifi_twt_type_t twt_type; /**< twt type */
|
||||
uint8_t flow_id; /**< flow id */
|
||||
} wifi_event_sta_twt_wakeup_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -583,6 +583,7 @@ typedef struct {
|
|||
uint8_t *hdr; /**< header of the wifi packet */
|
||||
uint8_t *payload; /**< payload of the wifi packet */
|
||||
uint16_t payload_len; /**< payload len of the wifi packet */
|
||||
uint16_t rx_seq; /**< rx sequence number of the wifi packet */
|
||||
} wifi_csi_info_t;
|
||||
|
||||
/**
|
||||
|
@ -895,6 +896,7 @@ typedef enum {
|
|||
WIFI_EVENT_ITWT_TEARDOWN, /**< iTWT teardown */
|
||||
WIFI_EVENT_ITWT_PROBE, /**< iTWT probe */
|
||||
WIFI_EVENT_ITWT_SUSPEND, /**< iTWT suspend */
|
||||
WIFI_EVENT_TWT_WAKEUP, /**< TWT wakeup */
|
||||
|
||||
WIFI_EVENT_NAN_STARTED, /**< NAN Discovery has started */
|
||||
WIFI_EVENT_NAN_STOPPED, /**< NAN Discovery has stopped */
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 39926ae1f56bd2de3d0c7fb875d5d301c4bf4467
|
||||
Subproject commit 4fba9c81baa3baf0996a8697127aca176a89e350
|
|
@ -12,6 +12,7 @@
|
|||
#include "esp_private/sleep_modem.h"
|
||||
#include "esp_pm.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_private/pm_impl.h"
|
||||
#include "esp_private/esp_clk.h"
|
||||
#include "esp_wpa.h"
|
||||
|
@ -29,6 +30,10 @@
|
|||
#include "esp_chip_info.h"
|
||||
#endif
|
||||
|
||||
#if SOC_PM_MODEM_RETENTION_BY_REGDMA
|
||||
#include "esp_private/sleep_retention.h"
|
||||
#endif
|
||||
|
||||
static bool s_wifi_inited = false;
|
||||
|
||||
#if (CONFIG_ESP_WIFI_RX_BA_WIN > CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM)
|
||||
|
@ -108,6 +113,41 @@ static void esp_wifi_set_log_level(void)
|
|||
esp_wifi_internal_set_log_level(wifi_log_level);
|
||||
}
|
||||
|
||||
#if (CONFIG_FREERTOS_USE_TICKLESS_IDLE && SOC_PM_MODEM_RETENTION_BY_REGDMA)
|
||||
static esp_err_t init_wifi_mac_sleep_retention(void *arg)
|
||||
{
|
||||
int config_size;
|
||||
sleep_retention_entries_config_t *config = esp_wifi_internal_mac_retention_context_get(&config_size);
|
||||
esp_err_t err = sleep_retention_entries_create(config, config_size, 3, SLEEP_RETENTION_MODULE_WIFI_MAC);
|
||||
ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for modem (%s) retention", "WiFi MAC");
|
||||
ESP_LOGD(TAG, "WiFi MAC sleep retention initialization");
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_MAC_BB_PD
|
||||
static void esp_wifi_mac_pd_mem_init(void)
|
||||
{
|
||||
#if SOC_PM_MODEM_RETENTION_BY_REGDMA
|
||||
esp_err_t err = sleep_retention_module_allocate(SLEEP_RETENTION_MODULE_WIFI_MAC);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "failed to allocate sleep retention linked list for wifi mac retention");
|
||||
}
|
||||
#endif
|
||||
esp_wifi_internal_set_mac_sleep(true);
|
||||
}
|
||||
static void esp_wifi_mac_pd_mem_deinit(void)
|
||||
{
|
||||
esp_wifi_internal_set_mac_sleep(false);
|
||||
#if SOC_PM_MODEM_RETENTION_BY_REGDMA
|
||||
esp_err_t err = sleep_retention_module_free(SLEEP_RETENTION_MODULE_WIFI_MAC);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "failed to free sleep retention linked list for wifi mac retention");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
static esp_err_t wifi_deinit_internal(void)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
|
@ -126,6 +166,11 @@ static esp_err_t wifi_deinit_internal(void)
|
|||
esp_nan_app_deinit();
|
||||
#endif
|
||||
|
||||
#if CONFIG_MAC_BB_PD
|
||||
esp_wifi_mac_pd_mem_deinit();
|
||||
esp_mac_bb_pd_mem_deinit();
|
||||
#endif
|
||||
|
||||
esp_supplicant_deinit();
|
||||
err = esp_wifi_deinit_internal();
|
||||
if (err != ESP_OK) {
|
||||
|
@ -157,15 +202,17 @@ static esp_err_t wifi_deinit_internal(void)
|
|||
esp_sleep_disable_wifi_beacon_wakeup();
|
||||
# endif
|
||||
#endif /* SOC_WIFI_HW_TSF */
|
||||
#if SOC_PM_MODEM_RETENTION_BY_REGDMA
|
||||
err = sleep_retention_module_deinit(SLEEP_RETENTION_MODULE_WIFI_MAC);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "WiFi MAC sleep retention deinit failed");
|
||||
}
|
||||
#endif /* SOC_PM_MODEM_RETENTION_BY_REGDMA */
|
||||
#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */
|
||||
#if CONFIG_MAC_BB_PD
|
||||
esp_unregister_mac_bb_pd_callback(pm_mac_sleep);
|
||||
esp_unregister_mac_bb_pu_callback(pm_mac_wakeup);
|
||||
#endif
|
||||
#if CONFIG_MAC_BB_PD
|
||||
esp_wifi_internal_set_mac_sleep(false);
|
||||
esp_mac_bb_pd_mem_deinit();
|
||||
#endif
|
||||
#if CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP
|
||||
esp_wifi_internal_modem_state_configure(false);
|
||||
esp_pm_unregister_skip_light_sleep_callback(sleep_modem_wifi_modem_state_skip_light_sleep);
|
||||
|
@ -281,6 +328,17 @@ esp_err_t esp_wifi_init(const wifi_init_config_t *config)
|
|||
#endif
|
||||
|
||||
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
|
||||
#if SOC_PM_MODEM_RETENTION_BY_REGDMA
|
||||
sleep_retention_module_init_param_t init_param = {
|
||||
.cbs = { .create = { .handle = init_wifi_mac_sleep_retention, .arg = NULL } },
|
||||
.depends = BIT(SLEEP_RETENTION_MODULE_WIFI_BB) | BIT(SLEEP_RETENTION_MODULE_CLOCK_MODEM)
|
||||
};
|
||||
esp_err_t err = sleep_retention_module_init(SLEEP_RETENTION_MODULE_WIFI_MAC, &init_param);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "WiFi MAC sleep retention init failed");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_MAC_BB_PD
|
||||
if (esp_register_mac_bb_pd_callback(pm_mac_sleep) != ESP_OK
|
||||
|| esp_register_mac_bb_pu_callback(pm_mac_wakeup) != ESP_OK) {
|
||||
|
@ -332,7 +390,7 @@ esp_err_t esp_wifi_init(const wifi_init_config_t *config)
|
|||
if (result == ESP_OK) {
|
||||
#if CONFIG_MAC_BB_PD
|
||||
esp_mac_bb_pd_mem_init();
|
||||
esp_wifi_internal_set_mac_sleep(true);
|
||||
esp_wifi_mac_pd_mem_init();
|
||||
#endif
|
||||
esp_phy_modem_init();
|
||||
#if CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP
|
||||
|
|
|
@ -142,7 +142,7 @@ typedef uint32_t TickType_t;
|
|||
UBaseType_t xPortSetInterruptMaskFromISR(void);
|
||||
|
||||
/**
|
||||
* @brief Reenable interrupts in a nested manner (meant to be called from ISRs)
|
||||
* @brief Re-enable interrupts in a nested manner (meant to be called from ISRs)
|
||||
*
|
||||
* @warning Only applies to current CPU.
|
||||
* @param prev_int_level Previous interrupt level
|
||||
|
@ -502,7 +502,7 @@ void vPortTCBPreDeleteHook( void *pxTCB );
|
|||
#define portENTER_CRITICAL_ISR(mux) vPortEnterCriticalMultiCore(mux)
|
||||
#define portEXIT_CRITICAL_ISR(mux) vPortExitCriticalMultiCore(mux)
|
||||
|
||||
#define portTRY_ENTER_CRITICAL_SAFE(mux, timeout) xPortEnterCriticalTimeoutSafe(mux)
|
||||
#define portTRY_ENTER_CRITICAL_SAFE(mux, timeout) xPortEnterCriticalTimeoutSafe(mux, timeout)
|
||||
#define portENTER_CRITICAL_SAFE(mux) vPortEnterCriticalSafe(mux)
|
||||
#define portEXIT_CRITICAL_SAFE(mux) vPortExitCriticalSafe(mux)
|
||||
#else
|
||||
|
@ -536,7 +536,12 @@ void vPortTCBPreDeleteHook( void *pxTCB );
|
|||
portEXIT_CRITICAL(mux); \
|
||||
} \
|
||||
})
|
||||
#define portTRY_ENTER_CRITICAL_SAFE(mux, timeout) portENTER_CRITICAL_SAFE(mux, timeout)
|
||||
#define portTRY_ENTER_CRITICAL_SAFE(mux, timeout) ({ \
|
||||
(void)timeout; \
|
||||
portENTER_CRITICAL_SAFE(mux); \
|
||||
BaseType_t ret = pdPASS; \
|
||||
ret; \
|
||||
})
|
||||
|
||||
#endif /* (configNUM_CORES > 1) */
|
||||
|
||||
|
|
|
@ -172,7 +172,7 @@ BaseType_t xPortInterruptedFromISRContext(void);
|
|||
static inline UBaseType_t xPortSetInterruptMaskFromISR(void);
|
||||
|
||||
/**
|
||||
* @brief Reenable interrupts in a nested manner (meant to be called from ISRs)
|
||||
* @brief Re-enable interrupts in a nested manner (meant to be called from ISRs)
|
||||
*
|
||||
* @warning Only applies to current CPU.
|
||||
* @param prev_level Previous interrupt level
|
||||
|
@ -460,7 +460,7 @@ void vPortTCBPreDeleteHook( void *pxTCB );
|
|||
#define portENTER_CRITICAL_ISR(mux) vPortEnterCritical(mux)
|
||||
#define portEXIT_CRITICAL_ISR(mux) vPortExitCritical(mux)
|
||||
|
||||
#define portTRY_ENTER_CRITICAL_SAFE(mux, timeout) xPortEnterCriticalTimeoutSafe(mux)
|
||||
#define portTRY_ENTER_CRITICAL_SAFE(mux, timeout) xPortEnterCriticalTimeoutSafe(mux, timeout)
|
||||
#define portENTER_CRITICAL_SAFE(mux) vPortEnterCriticalSafe(mux)
|
||||
#define portEXIT_CRITICAL_SAFE(mux) vPortExitCriticalSafe(mux)
|
||||
|
||||
|
|
|
@ -5440,7 +5440,8 @@ static void prvResetNextTaskUnblockTime( void )
|
|||
/* Write the rest of the string. */
|
||||
#if ( configTASKLIST_INCLUDE_COREID == 1 )
|
||||
{
|
||||
sprintf( pcWriteBuffer, "\t%c\t%u\t%d\t%u\t%u\r\n", cStatus, ( unsigned int ) pxTaskStatusArray[ x ].uxCurrentPriority, ( unsigned int ) pxTaskStatusArray[ x ].xCoreID, ( unsigned int ) pxTaskStatusArray[ x ].usStackHighWaterMark, ( unsigned int ) pxTaskStatusArray[ x ].xTaskNumber ); /*lint !e586 sprintf() allowed as this is compiled with many compilers and this is a utility function only - not part of the core kernel implementation. */
|
||||
const BaseType_t xCoreID = ( pxTaskStatusArray[ x ].xCoreID == tskNO_AFFINITY ) ? -1 : pxTaskStatusArray[ x ].xCoreID;
|
||||
sprintf( pcWriteBuffer, "\t%c\t%u\t%u\t%u\t%d\r\n", cStatus, ( unsigned int ) pxTaskStatusArray[ x ].uxCurrentPriority, ( unsigned int ) pxTaskStatusArray[ x ].usStackHighWaterMark, ( unsigned int ) pxTaskStatusArray[ x ].xTaskNumber, ( int ) xCoreID ); /*lint !e586 sprintf() allowed as this is compiled with many compilers and this is a utility function only - not part of the core kernel implementation. */
|
||||
}
|
||||
#else /* configTASKLIST_INCLUDE_COREID == 1 */
|
||||
{
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
@ -30,7 +30,7 @@ extern "C" {
|
|||
// The timeout calibration factor when using ref_tick
|
||||
#define UART_LL_TOUT_REF_FACTOR_DEFAULT (8)
|
||||
|
||||
#define UART_LL_MIN_WAKEUP_THRESH (2)
|
||||
#define UART_LL_MIN_WAKEUP_THRESH (3)
|
||||
#define UART_LL_INTR_MASK (0x7ffff) //All interrupt mask
|
||||
|
||||
// Define UART interrupts
|
||||
|
@ -692,7 +692,9 @@ FORCE_INLINE_ATTR void uart_ll_set_dtr_active_level(uart_dev_t *hw, int level)
|
|||
*/
|
||||
FORCE_INLINE_ATTR void uart_ll_set_wakeup_thrd(uart_dev_t *hw, uint32_t wakeup_thrd)
|
||||
{
|
||||
hw->sleep_conf.active_threshold = wakeup_thrd - UART_LL_MIN_WAKEUP_THRESH;
|
||||
// System would wakeup when the number of positive edges of RxD signal is larger than or equal to (UART_ACTIVE_THRESHOLD+2)
|
||||
// Note: On ESP32, the minimum UART wakeup threshold is 2 + 1 = 3 (UART_ACTIVE_THRESHOLD set to 0 leads to consecutive triggering wakeup)
|
||||
hw->sleep_conf.active_threshold = wakeup_thrd - (UART_LL_MIN_WAKEUP_THRESH - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -834,7 +836,7 @@ FORCE_INLINE_ATTR void uart_ll_get_at_cmd_char(uart_dev_t *hw, uint8_t *cmd_char
|
|||
*/
|
||||
FORCE_INLINE_ATTR uint32_t uart_ll_get_wakeup_thrd(uart_dev_t *hw)
|
||||
{
|
||||
return hw->sleep_conf.active_threshold + UART_LL_MIN_WAKEUP_THRESH;
|
||||
return hw->sleep_conf.active_threshold + (UART_LL_MIN_WAKEUP_THRESH - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -29,7 +29,7 @@ extern "C" {
|
|||
// Get UART hardware instance with giving uart num
|
||||
#define UART_LL_GET_HW(num) (((num) == UART_NUM_0) ? (&UART0) : (&UART1))
|
||||
|
||||
#define UART_LL_MIN_WAKEUP_THRESH (2)
|
||||
#define UART_LL_MIN_WAKEUP_THRESH (3)
|
||||
#define UART_LL_INTR_MASK (0x7ffff) //All interrupt mask
|
||||
|
||||
#define UART_LL_FSM_IDLE (0x0)
|
||||
|
@ -672,6 +672,7 @@ FORCE_INLINE_ATTR void uart_ll_set_dtr_active_level(uart_dev_t *hw, int level)
|
|||
*/
|
||||
FORCE_INLINE_ATTR void uart_ll_set_wakeup_thrd(uart_dev_t *hw, uint32_t wakeup_thrd)
|
||||
{
|
||||
// System would wakeup when the number of positive edges of RxD signal is larger than or equal to (UART_ACTIVE_THRESHOLD+3)
|
||||
hw->sleep_conf.active_threshold = wakeup_thrd - UART_LL_MIN_WAKEUP_THRESH;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -380,7 +380,12 @@ static inline void gpio_ll_wakeup_disable(gpio_dev_t *hw, uint32_t gpio_num)
|
|||
*/
|
||||
static inline void gpio_ll_set_drive_capability(gpio_dev_t *hw, uint32_t gpio_num, gpio_drive_cap_t strength)
|
||||
{
|
||||
SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[gpio_num], FUN_DRV_V, strength, FUN_DRV_S);
|
||||
uint32_t drv_cap = (uint32_t)strength;
|
||||
// DRV = 1 and DRV = 2 register bits are flipped for IO2, IO3, IO4, IO5, IO18, IO19 on the target
|
||||
if (gpio_num == 2 || gpio_num == 3 || gpio_num == 4 || gpio_num == 5 || gpio_num == 18 || gpio_num == 19) {
|
||||
drv_cap = ((drv_cap & 0x1) << 1) | ((drv_cap & 0x2) >> 1); // swap bit0 and bit1
|
||||
}
|
||||
SET_PERI_REG_BITS(IO_MUX_GPIO0_REG + (gpio_num * 4), FUN_DRV_V, drv_cap, FUN_DRV_S);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -392,7 +397,12 @@ static inline void gpio_ll_set_drive_capability(gpio_dev_t *hw, uint32_t gpio_nu
|
|||
*/
|
||||
static inline void gpio_ll_get_drive_capability(gpio_dev_t *hw, uint32_t gpio_num, gpio_drive_cap_t *strength)
|
||||
{
|
||||
*strength = (gpio_drive_cap_t)GET_PERI_REG_BITS2(GPIO_PIN_MUX_REG[gpio_num], FUN_DRV_V, FUN_DRV_S);
|
||||
uint32_t drv_cap = GET_PERI_REG_BITS2(IO_MUX_GPIO0_REG + (gpio_num * 4), FUN_DRV_V, FUN_DRV_S);
|
||||
// DRV = 1 and DRV = 2 register bits are flipped for IO2, IO3, IO4, IO5, IO18, IO19 on the target
|
||||
if (gpio_num == 2 || gpio_num == 3 || gpio_num == 4 || gpio_num == 5 || gpio_num == 18 || gpio_num == 19) {
|
||||
drv_cap = ((drv_cap & 0x1) << 1) | ((drv_cap & 0x2) >> 1); // swap bit0 and bit1
|
||||
}
|
||||
*strength = (gpio_drive_cap_t)drv_cap;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -29,7 +29,7 @@ extern "C" {
|
|||
// Get UART hardware instance with giving uart num
|
||||
#define UART_LL_GET_HW(num) (((num) == UART_NUM_0) ? (&UART0) : (&UART1))
|
||||
|
||||
#define UART_LL_MIN_WAKEUP_THRESH (2)
|
||||
#define UART_LL_MIN_WAKEUP_THRESH (3)
|
||||
#define UART_LL_INTR_MASK (0x7ffff) //All interrupt mask
|
||||
|
||||
#define UART_LL_FSM_IDLE (0x0)
|
||||
|
@ -675,6 +675,7 @@ FORCE_INLINE_ATTR void uart_ll_set_dtr_active_level(uart_dev_t *hw, int level)
|
|||
*/
|
||||
FORCE_INLINE_ATTR void uart_ll_set_wakeup_thrd(uart_dev_t *hw, uint32_t wakeup_thrd)
|
||||
{
|
||||
// System would wakeup when the number of positive edges of RxD signal is larger than or equal to (UART_ACTIVE_THRESHOLD+3)
|
||||
hw->sleep_conf.active_threshold = wakeup_thrd - UART_LL_MIN_WAKEUP_THRESH;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define GDMA_CH_RETENTION_GET_MODULE_ID(group_id, pair_id) (SLEEP_RETENTION_MODULE_GDMA_CH0 + (SOC_GDMA_PAIRS_PER_GROUP_MAX * group_id) + pair_id)
|
||||
|
||||
#define GDMA_LL_GET_HW(id) (((id) == 0) ? (&GDMA) : NULL)
|
||||
|
||||
#define GDMA_LL_CHANNEL_MAX_PRIORITY 5 // supported priority levels: [0,5]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -22,15 +22,20 @@
|
|||
#define GPIO_LL_ETM_TASK_ID_CLR(ch) (GPIO_TASK_CH0_CLEAR + (ch))
|
||||
#define GPIO_LL_ETM_TASK_ID_TOG(ch) (GPIO_TASK_CH0_TOGGLE + (ch))
|
||||
|
||||
#define GPIO_LL_ETM_EVENT_CHANNELS_PER_GROUP 8
|
||||
#define GPIO_LL_ETM_TASK_CHANNELS_PER_GROUP 8
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Set which GPIO to be bounded to the event channel
|
||||
* @brief Set which GPIO to be bound to the event channel
|
||||
*
|
||||
* @note Different channels can be bound to one GPIO
|
||||
*
|
||||
* @param dev Register base address
|
||||
* @param chan Channel number
|
||||
* @param chan GPIO ETM Event channel number
|
||||
* @param gpio_num GPIO number
|
||||
*/
|
||||
static inline void gpio_ll_etm_event_channel_set_gpio(gpio_etm_dev_t *dev, uint32_t chan, uint32_t gpio_num)
|
||||
|
@ -39,10 +44,10 @@ static inline void gpio_ll_etm_event_channel_set_gpio(gpio_etm_dev_t *dev, uint3
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Wether to enable the event channel
|
||||
* @brief Whether to enable the event channel
|
||||
*
|
||||
* @param dev Register base address
|
||||
* @param chan Channel number
|
||||
* @param chan GPIO ETM Event channel number
|
||||
* @param enable True to enable, false to disable
|
||||
*/
|
||||
static inline void gpio_ll_etm_enable_event_channel(gpio_etm_dev_t *dev, uint32_t chan, bool enable)
|
||||
|
@ -51,12 +56,24 @@ static inline void gpio_ll_etm_enable_event_channel(gpio_etm_dev_t *dev, uint32_
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Set which GPIO to be bounded to the task channel
|
||||
*
|
||||
* @note One channel can be bounded to multiple different GPIOs
|
||||
* @brief Get which GPIO is bound to the event channel
|
||||
*
|
||||
* @param dev Register base address
|
||||
* @param chan Channel number
|
||||
* @param chan GPIO ETM Event channel number
|
||||
* @return GPIO number
|
||||
*/
|
||||
static inline uint32_t gpio_ll_etm_event_channel_get_gpio(gpio_etm_dev_t *dev, uint32_t chan)
|
||||
{
|
||||
return dev->event_chn_cfg[chan].etm_chn_event_sel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set which GPIO to be bound to the task channel
|
||||
*
|
||||
* @note One channel can be bound to multiple different GPIOs
|
||||
*
|
||||
* @param dev Register base address
|
||||
* @param chan GPIO ETM Task channel number
|
||||
* @param gpio_num GPIO number
|
||||
*/
|
||||
static inline void gpio_ll_etm_gpio_set_task_channel(gpio_etm_dev_t *dev, uint32_t gpio_num, uint32_t chan)
|
||||
|
@ -70,7 +87,7 @@ static inline void gpio_ll_etm_gpio_set_task_channel(gpio_etm_dev_t *dev, uint32
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Wether to enable the GPIO to be managed by the task channel
|
||||
* @brief Whether to enable the GPIO to be managed by the task channel
|
||||
*
|
||||
* @param dev Register base address
|
||||
* @param gpio_num GPIO number
|
||||
|
@ -101,7 +118,7 @@ static inline bool gpio_ll_etm_is_task_gpio_enabled(gpio_etm_dev_t *dev, uint32_
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Get the channel number that the GPIO is bounded to
|
||||
* @brief Get the channel number that the GPIO is bound to
|
||||
*
|
||||
* @param dev Register base address
|
||||
* @param gpio_num GPIO number
|
||||
|
|
|
@ -33,7 +33,7 @@ extern "C" {
|
|||
|
||||
#define UART_LL_REG_FIELD_BIT_SHIFT(hw) (((hw) == &LP_UART) ? 3 : 0)
|
||||
|
||||
#define UART_LL_MIN_WAKEUP_THRESH (2)
|
||||
#define UART_LL_MIN_WAKEUP_THRESH (3)
|
||||
#define UART_LL_INTR_MASK (0x7ffff) //All interrupt mask
|
||||
|
||||
#define UART_LL_FSM_IDLE (0x0)
|
||||
|
@ -864,6 +864,7 @@ FORCE_INLINE_ATTR void uart_ll_set_dtr_active_level(uart_dev_t *hw, int level)
|
|||
*/
|
||||
FORCE_INLINE_ATTR void uart_ll_set_wakeup_thrd(uart_dev_t *hw, uint32_t wakeup_thrd)
|
||||
{
|
||||
// System would wakeup when the number of positive edges of RxD signal is larger than or equal to (UART_ACTIVE_THRESHOLD+3)
|
||||
hw->sleep_conf2.active_threshold = wakeup_thrd - UART_LL_MIN_WAKEUP_THRESH;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define GDMA_CH_RETENTION_GET_MODULE_ID(group_id, pair_id) (SLEEP_RETENTION_MODULE_GDMA_CH0 + (SOC_GDMA_PAIRS_PER_GROUP_MAX * group_id) + pair_id)
|
||||
|
||||
#define GDMA_LL_GET_HW(id) (((id) == 0) ? (&GDMA) : NULL)
|
||||
|
||||
#define GDMA_LL_CHANNEL_MAX_PRIORITY 5 // supported priority levels: [0,5]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -22,15 +22,20 @@
|
|||
#define GPIO_LL_ETM_TASK_ID_CLR(ch) (GPIO_TASK_CH0_CLEAR + (ch))
|
||||
#define GPIO_LL_ETM_TASK_ID_TOG(ch) (GPIO_TASK_CH0_TOGGLE + (ch))
|
||||
|
||||
#define GPIO_LL_ETM_EVENT_CHANNELS_PER_GROUP 8
|
||||
#define GPIO_LL_ETM_TASK_CHANNELS_PER_GROUP 8
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Set which GPIO to be bounded to the event channel
|
||||
* @brief Set which GPIO to be bound to the event channel
|
||||
*
|
||||
* @note Different channels can be bound to one GPIO
|
||||
*
|
||||
* @param dev Register base address
|
||||
* @param chan Channel number
|
||||
* @param chan GPIO ETM Event channel number
|
||||
* @param gpio_num GPIO number
|
||||
*/
|
||||
static inline void gpio_ll_etm_event_channel_set_gpio(gpio_etm_dev_t *dev, uint32_t chan, uint32_t gpio_num)
|
||||
|
@ -39,10 +44,10 @@ static inline void gpio_ll_etm_event_channel_set_gpio(gpio_etm_dev_t *dev, uint3
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Wether to enable the event channel
|
||||
* @brief Whether to enable the event channel
|
||||
*
|
||||
* @param dev Register base address
|
||||
* @param chan Channel number
|
||||
* @param chan GPIO ETM Event channel number
|
||||
* @param enable True to enable, false to disable
|
||||
*/
|
||||
static inline void gpio_ll_etm_enable_event_channel(gpio_etm_dev_t *dev, uint32_t chan, bool enable)
|
||||
|
@ -51,12 +56,24 @@ static inline void gpio_ll_etm_enable_event_channel(gpio_etm_dev_t *dev, uint32_
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Set which GPIO to be bounded to the task channel
|
||||
*
|
||||
* @note One channel can be bounded to multiple different GPIOs
|
||||
* @brief Get which GPIO is bound to the event channel
|
||||
*
|
||||
* @param dev Register base address
|
||||
* @param chan Channel number
|
||||
* @param chan GPIO ETM Event channel number
|
||||
* @return GPIO number
|
||||
*/
|
||||
static inline uint32_t gpio_ll_etm_event_channel_get_gpio(gpio_etm_dev_t *dev, uint32_t chan)
|
||||
{
|
||||
return dev->etm_event_chn_cfg[chan].etm_chn_event_sel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set which GPIO to be bound to the task channel
|
||||
*
|
||||
* @note One channel can be bound to multiple different GPIOs
|
||||
*
|
||||
* @param dev Register base address
|
||||
* @param chan GPIO ETM Task channel number
|
||||
* @param gpio_num GPIO number
|
||||
*/
|
||||
static inline void gpio_ll_etm_gpio_set_task_channel(gpio_etm_dev_t *dev, uint32_t gpio_num, uint32_t chan)
|
||||
|
@ -70,7 +87,7 @@ static inline void gpio_ll_etm_gpio_set_task_channel(gpio_etm_dev_t *dev, uint32
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Wether to enable the GPIO to be managed by the task channel
|
||||
* @brief Whether to enable the GPIO to be managed by the task channel
|
||||
*
|
||||
* @param dev Register base address
|
||||
* @param gpio_num GPIO number
|
||||
|
@ -101,7 +118,7 @@ static inline bool gpio_ll_etm_is_task_gpio_enabled(gpio_etm_dev_t *dev, uint32_
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Get the channel number that the GPIO is bounded to
|
||||
* @brief Get the channel number that the GPIO is bound to
|
||||
*
|
||||
* @param dev Register base address
|
||||
* @param gpio_num GPIO number
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Ładowanie…
Reference in New Issue