From e5dab5dc4bacb4e393591739a7c7aa3048b51f0d Mon Sep 17 00:00:00 2001 From: Rahul Tank Date: Thu, 25 Sep 2025 18:09:27 +0530 Subject: [PATCH 001/106] feat(nimble): Add support for HCI commands / events 1. Read all local supported feature 2. Read remote supported feature 3. Advertising monitor. --- components/bt/host/nimble/Kconfig.in | 6 +++++- components/bt/host/nimble/nimble | 2 +- components/bt/host/nimble/port/include/esp_nimble_cfg.h | 8 ++++++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/components/bt/host/nimble/Kconfig.in b/components/bt/host/nimble/Kconfig.in index f5f0b4541f4..62e4328d24c 100644 --- a/components/bt/host/nimble/Kconfig.in +++ b/components/bt/host/nimble/Kconfig.in @@ -721,11 +721,15 @@ menu "BLE 6.x Features" if BT_NIMBLE_60_FEATURE_SUPPORT config BT_NIMBLE_CHANNEL_SOUNDING bool "ble channel souding feature" - depends on BT_NIMBLE_ENABLED default n help Used to enable/disable the channel sounding feature + config BT_NIMBLE_MONITOR_ADV + bool "Enable Monitor Advertising" + default n + help + Enable support for Monitor Advertisers endif endmenu #BLE6.x diff --git a/components/bt/host/nimble/nimble b/components/bt/host/nimble/nimble index 9464ecd6e32..45387330100 160000 --- a/components/bt/host/nimble/nimble +++ b/components/bt/host/nimble/nimble @@ -1 +1 @@ -Subproject commit 9464ecd6e32ff80d09b0c1678805c0fa4e722821 +Subproject commit 45387330100ab0709a0d9e0510e764fdc91cfb83 diff --git a/components/bt/host/nimble/port/include/esp_nimble_cfg.h b/components/bt/host/nimble/port/include/esp_nimble_cfg.h index 1d6f8a4e7be..db2a4a1990b 100644 --- a/components/bt/host/nimble/port/include/esp_nimble_cfg.h +++ b/components/bt/host/nimble/port/include/esp_nimble_cfg.h @@ -2200,4 +2200,12 @@ #endif #endif +#ifndef MYNEWT_VAL_BLE_MONITOR_ADV +#ifdef CONFIG_BT_NIMBLE_MONITOR_ADV +#define MYNEWT_VAL_BLE_MONITOR_ADV CONFIG_BT_NIMBLE_MONITOR_ADV +#else +#define MYNEWT_VAL_BLE_MONITOR_ADV (0) +#endif +#endif + #endif From 2ac66d4020d620062b5464286752bb1767f2ef93 Mon Sep 17 00:00:00 2001 From: Xu Si Yu Date: Thu, 23 Oct 2025 17:57:29 +0800 Subject: [PATCH 002/106] feat(openthread): support custom netif config during initialization --- components/openthread/include/esp_openthread.h | 2 +- .../openthread/include/esp_openthread_types.h | 10 ++++++++++ components/openthread/src/esp_openthread.cpp | 16 ++++++++-------- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/components/openthread/include/esp_openthread.h b/components/openthread/include/esp_openthread.h index ce96d186569..7ce38a58844 100644 --- a/components/openthread/include/esp_openthread.h +++ b/components/openthread/include/esp_openthread.h @@ -102,7 +102,7 @@ esp_err_t esp_openthread_mainloop_exit(void); * - ESP_ERR_INVALID_STATE if already initialized * */ -esp_err_t esp_openthread_start(esp_openthread_platform_config_t *config); +esp_err_t esp_openthread_start(const esp_openthread_config_t *config); /** * @brief This function performs OpenThread stack and platform driver deinitialization and delete the handle task. diff --git a/components/openthread/include/esp_openthread_types.h b/components/openthread/include/esp_openthread_types.h index c5f4f4cba67..e384603b736 100644 --- a/components/openthread/include/esp_openthread_types.h +++ b/components/openthread/include/esp_openthread_types.h @@ -11,6 +11,7 @@ #include #include "esp_event_base.h" +#include "esp_netif_types.h" #include "driver/gpio.h" #include "driver/spi_master.h" #include "driver/spi_slave.h" @@ -199,6 +200,15 @@ typedef struct { esp_openthread_port_config_t port_config; /*!< The port configuration */ } esp_openthread_platform_config_t; +/** + * @brief The OpenThread configuration + * + */ +typedef struct { + esp_netif_config_t netif_config; /*!< The netif configuration */ + esp_openthread_platform_config_t platform_config; /*!< The platform configuration */ +} esp_openthread_config_t; + /** * @brief The OpenThread rcp failure handler * diff --git a/components/openthread/src/esp_openthread.cpp b/components/openthread/src/esp_openthread.cpp index e779959d25b..3379b318d4a 100644 --- a/components/openthread/src/esp_openthread.cpp +++ b/components/openthread/src/esp_openthread.cpp @@ -235,15 +235,14 @@ esp_err_t esp_openthread_deinit(void) static void ot_task_worker(void *aContext) { - esp_openthread_platform_config_t* config = (esp_openthread_platform_config_t *)aContext; + const esp_openthread_config_t* config = *(esp_openthread_config_t **)aContext; // Initialize the OpenThread stack - ESP_ERROR_CHECK(esp_openthread_init(config)); + ESP_ERROR_CHECK(esp_openthread_init(&(config->platform_config))); #if CONFIG_OPENTHREAD_FTD || CONFIG_OPENTHREAD_MTD - esp_netif_config_t cfg = ESP_NETIF_DEFAULT_OPENTHREAD(); - esp_netif_t *openthread_netif = esp_netif_new(&cfg); + esp_netif_t *openthread_netif = esp_netif_new(&(config->netif_config)); assert(openthread_netif != NULL); - ESP_ERROR_CHECK(esp_netif_attach(openthread_netif, esp_openthread_netif_glue_init(config))); + ESP_ERROR_CHECK(esp_netif_attach(openthread_netif, esp_openthread_netif_glue_init(&(config->platform_config)))); #endif #if CONFIG_OPENTHREAD_LOG_LEVEL_DYNAMIC @@ -256,10 +255,10 @@ static void ot_task_worker(void *aContext) esp_openthread_cli_console_command_register(); #endif // CONFIG_OPENTHREAD_CLI - xSemaphoreGive(s_ot_syn_semaphore); #if CONFIG_OPENTHREAD_RADIO otAppNcpInit(esp_openthread_get_instance()); #endif + xSemaphoreGive(s_ot_syn_semaphore); // Run the main loop esp_openthread_launch_mainloop(); @@ -284,12 +283,13 @@ static void ot_task_worker(void *aContext) vTaskDelay(portMAX_DELAY); } -esp_err_t esp_openthread_start(esp_openthread_platform_config_t *config) +esp_err_t esp_openthread_start(const esp_openthread_config_t *config) { + assert(config); ESP_RETURN_ON_FALSE(s_ot_syn_semaphore == NULL, ESP_ERR_INVALID_STATE, OT_PLAT_LOG_TAG, "OpenThread has been initialized"); s_ot_syn_semaphore = xSemaphoreCreateBinary(); ESP_RETURN_ON_FALSE(s_ot_syn_semaphore != NULL, ESP_ERR_INVALID_STATE, OT_PLAT_LOG_TAG, "Failed to create s_ot_syn_semaphore"); - assert(xTaskCreate(ot_task_worker, CONFIG_OPENTHREAD_TASK_NAME, CONFIG_OPENTHREAD_TASK_SIZE, config, CONFIG_OPENTHREAD_TASK_PRIORITY, &s_ot_task_handle) == pdPASS); + assert(xTaskCreate(ot_task_worker, CONFIG_OPENTHREAD_TASK_NAME, CONFIG_OPENTHREAD_TASK_SIZE, &config, CONFIG_OPENTHREAD_TASK_PRIORITY, &s_ot_task_handle) == pdPASS); xSemaphoreTake(s_ot_syn_semaphore, portMAX_DELAY); return ESP_OK; } From e24bb6f9ac455b5088c174c9599a70f122ea3692 Mon Sep 17 00:00:00 2001 From: Xu Si Yu Date: Fri, 24 Oct 2025 14:16:58 +0800 Subject: [PATCH 003/106] feat(openthread): update examples for API changes --- examples/openthread/ot_br/main/esp_ot_br.c | 11 +++++++---- examples/openthread/ot_cli/main/esp_ot_cli.c | 12 ++++++++---- examples/openthread/ot_rcp/main/esp_ot_rcp.c | 11 +++++++---- .../deep_sleep/main/esp_ot_sleepy_device.c | 11 +++++++---- .../light_sleep/main/esp_ot_sleepy_device.c | 11 +++++++---- examples/openthread/ot_trel/main/esp_ot_trel.c | 11 +++++++---- 6 files changed, 43 insertions(+), 24 deletions(-) diff --git a/examples/openthread/ot_br/main/esp_ot_br.c b/examples/openthread/ot_br/main/esp_ot_br.c index 10da75c855a..7cfcca642bb 100644 --- a/examples/openthread/ot_br/main/esp_ot_br.c +++ b/examples/openthread/ot_br/main/esp_ot_br.c @@ -103,10 +103,13 @@ void app_main(void) ot_external_coexist_init(); #endif - static esp_openthread_platform_config_t config = { - .radio_config = ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG(), - .host_config = ESP_OPENTHREAD_DEFAULT_HOST_CONFIG(), - .port_config = ESP_OPENTHREAD_DEFAULT_PORT_CONFIG(), + static esp_openthread_config_t config = { + .netif_config = ESP_NETIF_DEFAULT_OPENTHREAD(), + .platform_config = { + .radio_config = ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG(), + .host_config = ESP_OPENTHREAD_DEFAULT_HOST_CONFIG(), + .port_config = ESP_OPENTHREAD_DEFAULT_PORT_CONFIG(), + }, }; ESP_ERROR_CHECK(esp_openthread_start(&config)); diff --git a/examples/openthread/ot_cli/main/esp_ot_cli.c b/examples/openthread/ot_cli/main/esp_ot_cli.c index c2717a4c211..ee83bcc22de 100644 --- a/examples/openthread/ot_cli/main/esp_ot_cli.c +++ b/examples/openthread/ot_cli/main/esp_ot_cli.c @@ -24,6 +24,7 @@ #include "esp_netif_types.h" #include "esp_openthread.h" #include "esp_openthread_lock.h" +#include "esp_openthread_netif_glue.h" #include "esp_openthread_types.h" #include "esp_ot_config.h" #include "esp_vfs_eventfd.h" @@ -59,10 +60,13 @@ void app_main(void) ot_console_start(); #endif - esp_openthread_platform_config_t config = { - .radio_config = ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG(), - .host_config = ESP_OPENTHREAD_DEFAULT_HOST_CONFIG(), - .port_config = ESP_OPENTHREAD_DEFAULT_PORT_CONFIG(), + static esp_openthread_config_t config = { + .netif_config = ESP_NETIF_DEFAULT_OPENTHREAD(), + .platform_config = { + .radio_config = ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG(), + .host_config = ESP_OPENTHREAD_DEFAULT_HOST_CONFIG(), + .port_config = ESP_OPENTHREAD_DEFAULT_PORT_CONFIG(), + }, }; ESP_ERROR_CHECK(esp_openthread_start(&config)); diff --git a/examples/openthread/ot_rcp/main/esp_ot_rcp.c b/examples/openthread/ot_rcp/main/esp_ot_rcp.c index 765fef58a24..fddd7766846 100644 --- a/examples/openthread/ot_rcp/main/esp_ot_rcp.c +++ b/examples/openthread/ot_rcp/main/esp_ot_rcp.c @@ -50,10 +50,13 @@ void app_main(void) ot_external_coexist_init(); #endif - static esp_openthread_platform_config_t config = { - .radio_config = ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG(), - .host_config = ESP_OPENTHREAD_DEFAULT_HOST_CONFIG(), - .port_config = ESP_OPENTHREAD_DEFAULT_PORT_CONFIG(), + static esp_openthread_config_t config = { + .netif_config = {0}, + .platform_config = { + .radio_config = ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG(), + .host_config = ESP_OPENTHREAD_DEFAULT_HOST_CONFIG(), + .port_config = ESP_OPENTHREAD_DEFAULT_PORT_CONFIG(), + }, }; ESP_ERROR_CHECK(esp_openthread_start(&config)); diff --git a/examples/openthread/ot_sleepy_device/deep_sleep/main/esp_ot_sleepy_device.c b/examples/openthread/ot_sleepy_device/deep_sleep/main/esp_ot_sleepy_device.c index 5be8c610f42..7438715fa7a 100644 --- a/examples/openthread/ot_sleepy_device/deep_sleep/main/esp_ot_sleepy_device.c +++ b/examples/openthread/ot_sleepy_device/deep_sleep/main/esp_ot_sleepy_device.c @@ -163,10 +163,13 @@ void app_main(void) ESP_ERROR_CHECK(esp_vfs_eventfd_register(&eventfd_config)); ot_deep_sleep_init(); - esp_openthread_platform_config_t config = { - .radio_config = ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG(), - .host_config = ESP_OPENTHREAD_DEFAULT_HOST_CONFIG(), - .port_config = ESP_OPENTHREAD_DEFAULT_PORT_CONFIG(), + static esp_openthread_config_t config = { + .netif_config = ESP_NETIF_DEFAULT_OPENTHREAD(), + .platform_config = { + .radio_config = ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG(), + .host_config = ESP_OPENTHREAD_DEFAULT_HOST_CONFIG(), + .port_config = ESP_OPENTHREAD_DEFAULT_PORT_CONFIG(), + }, }; ESP_ERROR_CHECK(esp_openthread_start(&config)); esp_netif_set_default_netif(esp_openthread_get_netif()); diff --git a/examples/openthread/ot_sleepy_device/light_sleep/main/esp_ot_sleepy_device.c b/examples/openthread/ot_sleepy_device/light_sleep/main/esp_ot_sleepy_device.c index 633f40b094d..b54b2680424 100644 --- a/examples/openthread/ot_sleepy_device/light_sleep/main/esp_ot_sleepy_device.c +++ b/examples/openthread/ot_sleepy_device/light_sleep/main/esp_ot_sleepy_device.c @@ -163,10 +163,13 @@ void app_main(void) ot_console_start(); #endif - static esp_openthread_platform_config_t config = { - .radio_config = ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG(), - .host_config = ESP_OPENTHREAD_DEFAULT_HOST_CONFIG(), - .port_config = ESP_OPENTHREAD_DEFAULT_PORT_CONFIG(), + static esp_openthread_config_t config = { + .netif_config = ESP_NETIF_DEFAULT_OPENTHREAD(), + .platform_config = { + .radio_config = ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG(), + .host_config = ESP_OPENTHREAD_DEFAULT_HOST_CONFIG(), + .port_config = ESP_OPENTHREAD_DEFAULT_PORT_CONFIG(), + }, }; ESP_ERROR_CHECK(esp_openthread_start(&config)); esp_netif_set_default_netif(esp_openthread_get_netif()); diff --git a/examples/openthread/ot_trel/main/esp_ot_trel.c b/examples/openthread/ot_trel/main/esp_ot_trel.c index fc59497c2aa..d45b211b7b6 100644 --- a/examples/openthread/ot_trel/main/esp_ot_trel.c +++ b/examples/openthread/ot_trel/main/esp_ot_trel.c @@ -70,10 +70,13 @@ void app_main(void) ot_console_start(); #endif - static esp_openthread_platform_config_t config = { - .radio_config = ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG(), - .host_config = ESP_OPENTHREAD_DEFAULT_HOST_CONFIG(), - .port_config = ESP_OPENTHREAD_DEFAULT_PORT_CONFIG(), + static esp_openthread_config_t config = { + .netif_config = ESP_NETIF_DEFAULT_OPENTHREAD(), + .platform_config = { + .radio_config = ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG(), + .host_config = ESP_OPENTHREAD_DEFAULT_HOST_CONFIG(), + .port_config = ESP_OPENTHREAD_DEFAULT_PORT_CONFIG(), + }, }; ESP_ERROR_CHECK(esp_openthread_start(&config)); esp_netif_set_default_netif(esp_openthread_get_netif()); From 52ac615094b10180c2d66722e0196e53cf92adcb Mon Sep 17 00:00:00 2001 From: Tan Yan Quan Date: Wed, 22 Oct 2025 17:28:24 +0800 Subject: [PATCH 004/106] feat(openthread): update OT upstream to 36b14d3ef --- components/openthread/openthread | 2 +- components/openthread/sbom_openthread.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/components/openthread/openthread b/components/openthread/openthread index 3b3dd203be6..36b14d3ef74 160000 --- a/components/openthread/openthread +++ b/components/openthread/openthread @@ -1 +1 @@ -Subproject commit 3b3dd203be690995d1a89b110322e4eafafc3a3b +Subproject commit 36b14d3ef74f5e37e5be8902e1c1955a642fdfbf diff --git a/components/openthread/sbom_openthread.yml b/components/openthread/sbom_openthread.yml index 73b3caa70bf..74398658c69 100644 --- a/components/openthread/sbom_openthread.yml +++ b/components/openthread/sbom_openthread.yml @@ -5,4 +5,4 @@ supplier: 'Organization: Espressif Systems (Shanghai) CO LTD' originator: 'Organization: Google LLC' description: OpenThread released by Google is an open-source implementation of the Thread networking url: https://github.com/espressif/openthread -hash: 3b3dd203be690995d1a89b110322e4eafafc3a3b +hash: 36b14d3ef74f5e37e5be8902e1c1955a642fdfbf From de620d2e25c9656b9306989e67acf9e18fd985bf Mon Sep 17 00:00:00 2001 From: Tan Yan Quan Date: Wed, 22 Oct 2025 17:28:48 +0800 Subject: [PATCH 005/106] feat(openthread): support OT upstream dhcpv6 feature --- .../openthread-core-esp32x-ftd-config.h | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/components/openthread/private_include/openthread-core-esp32x-ftd-config.h b/components/openthread/private_include/openthread-core-esp32x-ftd-config.h index 6e62ee5f390..284c5493fe1 100644 --- a/components/openthread/private_include/openthread-core-esp32x-ftd-config.h +++ b/components/openthread/private_include/openthread-core-esp32x-ftd-config.h @@ -457,6 +457,36 @@ #define OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE 1 #endif +/** + * @def OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE + * + * Define to 1 to enable Border Routing DHCPv6 PD. + * + */ +#ifndef OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE +#define OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE 1 +#endif + +/** + * @def OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_CLIENT_ENABLE + * + * Define to 1 to enable Border Routing DHCPv6 client. + * + */ +#ifndef OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_CLIENT_ENABLE +#define OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_CLIENT_ENABLE 1 +#endif + +/** + * @def OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_CLIENT_MIN_LIFETIME + * + * This parameter sets the minimum preferred lifetime (in seconds) for the Border Router's built-in OpenThread + * DHCPv6 Prefix Delegation (PD) client feature. The default value is set to 30 to pass the certification case. + */ +#ifndef OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_CLIENT_MIN_LIFETIME +#define OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_CLIENT_MIN_LIFETIME 30 +#endif + /** * @def OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE * From 9a22339daa2499691fc7bc2e2f31d70958dd6826 Mon Sep 17 00:00:00 2001 From: Tan Yan Quan Date: Thu, 23 Oct 2025 04:21:24 +0000 Subject: [PATCH 006/106] feat(openthread): update thread-lib for new OT upstream 36b14d3ef * esp-openthread: thread_zigbee/esp-openthread@397da59b2 * openthread: espressif/openthread@36b14d3ef * esp-idf: espressif/esp-idf@49a872fc6 --- components/openthread/lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/openthread/lib b/components/openthread/lib index 984efc1578c..baa93a0cffc 160000 --- a/components/openthread/lib +++ b/components/openthread/lib @@ -1 +1 @@ -Subproject commit 984efc1578c856af215f33fcfeab645145949b46 +Subproject commit baa93a0cffc57c2f9cb0518d2e5ab3518ae5fa88 From f480be6d56c348e3ca95f7a8a22c75a3ef36fa65 Mon Sep 17 00:00:00 2001 From: Shu Chen Date: Thu, 23 Oct 2025 10:20:44 +0800 Subject: [PATCH 007/106] change(802.15.4): change the default cca threshold to -75dBm --- components/ieee802154/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/ieee802154/Kconfig b/components/ieee802154/Kconfig index 5d0b46666d2..54e7229affe 100644 --- a/components/ieee802154/Kconfig +++ b/components/ieee802154/Kconfig @@ -53,9 +53,9 @@ menu "IEEE 802.15.4" int "CCA detection threshold" depends on IEEE802154_ENABLED range -120 0 - default -60 + default -75 help - set the CCA threshold, in dB + set the CCA threshold, in dBm config IEEE802154_PENDING_TABLE_SIZE int "Pending table size" From 49ea34da8782ee5161c11c68432acf7e58c97c12 Mon Sep 17 00:00:00 2001 From: Tan Yan Quan Date: Thu, 23 Oct 2025 11:56:34 +0800 Subject: [PATCH 008/106] feat(openthread): add kconfig option for timing optimization --- components/openthread/Kconfig | 8 ++++++++ components/openthread/linker.lf | 10 ++++++---- examples/openthread/ot_rcp/sdkconfig.defaults | 2 ++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/components/openthread/Kconfig b/components/openthread/Kconfig index 99ed9fd364e..b113cfd1f4c 100644 --- a/components/openthread/Kconfig +++ b/components/openthread/Kconfig @@ -307,10 +307,17 @@ menu "OpenThread" Set the DNS server IPv4 address. endmenu + config OPENTHREAD_TIMING_OPTIMIZATION + bool "Enable timing optimization" + default n + help + Select this option to enable timing optimization for link metrics / CSL features. + config OPENTHREAD_LINK_METRICS bool "Enable link metrics feature" default n select IEEE802154_TIMING_OPTIMIZATION if IEEE802154_ENABLED + select OPENTHREAD_TIMING_OPTIMIZATION help Select this option to enable link metrics feature @@ -331,6 +338,7 @@ menu "OpenThread" bool "Enable CSL feature" default n select IEEE802154_TIMING_OPTIMIZATION if IEEE802154_ENABLED + select OPENTHREAD_TIMING_OPTIMIZATION help Select this option to enable CSL feature menu "CSL Configurations" diff --git a/components/openthread/linker.lf b/components/openthread/linker.lf index ffadcdff912..58c830c8e7a 100644 --- a/components/openthread/linker.lf +++ b/components/openthread/linker.lf @@ -1,15 +1,17 @@ [mapping:openthread] archive: libopenthread.a entries: - if OPENTHREAD_CSL_ENABLE = y || OPENTHREAD_LINK_METRICS = y: - csl_tx_scheduler (noflash) + if OPENTHREAD_TIMING_OPTIMIZATION = y: link_metrics (noflash) link_quality (noflash) - mac (noflash) mac_frame (noflash) - mesh_forwarder (noflash) radio (noflash) sub_mac (noflash) + if OPENTHREAD_TIMING_OPTIMIZATION = y && OPENTHREAD_RADIO = n: + mesh_forwarder (noflash) + csl_tx_scheduler (noflash) + mac (noflash) + if OPENTHREAD_RCP_SPI = y: ncp_spi (noflash) diff --git a/examples/openthread/ot_rcp/sdkconfig.defaults b/examples/openthread/ot_rcp/sdkconfig.defaults index 7a4583d9723..0419e6a33c7 100644 --- a/examples/openthread/ot_rcp/sdkconfig.defaults +++ b/examples/openthread/ot_rcp/sdkconfig.defaults @@ -50,3 +50,5 @@ CONFIG_LOG_DEFAULT_LEVEL_NONE=y CONFIG_LIBC_NEWLIB_NANO_FORMAT=y CONFIG_OPENTHREAD_LOG_LEVEL_DYNAMIC=n CONFIG_OPENTHREAD_LOG_LEVEL_NONE=y +CONFIG_OPENTHREAD_TIMING_OPTIMIZATION=y +CONFIG_FREERTOS_HZ=1000 From 269aa7252109ed0ee7550d88a0bb9ac183102bbf Mon Sep 17 00:00:00 2001 From: zhangyanjiao Date: Tue, 21 Oct 2025 14:23:42 +0800 Subject: [PATCH 009/106] fix(wifi/espnow): Remove doxygen groups as esp-docs is flat docs style --- components/esp_wifi/include/esp_now.h | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/components/esp_wifi/include/esp_now.h b/components/esp_wifi/include/esp_now.h index e5c2c020e39..587f015a824 100644 --- a/components/esp_wifi/include/esp_now.h +++ b/components/esp_wifi/include/esp_now.h @@ -15,23 +15,6 @@ extern "C" { #endif -/** \defgroup WiFi_APIs WiFi Related APIs - * @brief WiFi APIs - */ - -/** @addtogroup WiFi_APIs - * @{ - */ - -/** \defgroup ESPNOW_APIs ESPNOW APIs - * @brief ESP32 ESPNOW APIs - * - */ - -/** @addtogroup ESPNOW_APIs - * @{ - */ - #define ESP_ERR_ESPNOW_BASE (ESP_ERR_WIFI_BASE + 100) /*!< ESPNOW error number base. */ #define ESP_ERR_ESPNOW_NOT_INIT (ESP_ERR_ESPNOW_BASE + 1) /*!< ESPNOW is not initialized. */ #define ESP_ERR_ESPNOW_ARG (ESP_ERR_ESPNOW_BASE + 2) /*!< Invalid argument */ @@ -426,14 +409,6 @@ esp_err_t esp_now_switch_channel_tx(esp_now_switch_channel_t *config); */ esp_err_t esp_now_remain_on_channel(esp_now_remain_on_channel_t *config); -/** - * @} - */ - -/** - * @} - */ - #ifdef __cplusplus } #endif From f8fc421400e5c2ac26c6f70c22e5831821ebe7e3 Mon Sep 17 00:00:00 2001 From: Luo Xu Date: Thu, 30 Oct 2025 13:43:15 +0800 Subject: [PATCH 010/106] fix(ble_mesh): check data length before assigning adv data pointer (cherry picked from commit 6202aa89a6fd34137e4f52342bb5f5cdc8d8ae2b) Co-authored-by: luoxu --- components/bt/esp_ble_mesh/core/bluedroid_host/adapter.c | 2 +- components/bt/esp_ble_mesh/core/nimble_host/adapter.c | 2 +- components/bt/esp_ble_mesh/core/scan.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/components/bt/esp_ble_mesh/core/bluedroid_host/adapter.c b/components/bt/esp_ble_mesh/core/bluedroid_host/adapter.c index d6f51bfc9d7..fd42502fdaf 100644 --- a/components/bt/esp_ble_mesh/core/bluedroid_host/adapter.c +++ b/components/bt/esp_ble_mesh/core/bluedroid_host/adapter.c @@ -223,7 +223,7 @@ void bt_mesh_ble_ext_adv_report(tBTM_BLE_EXT_ADV_REPORT *ext_adv_report) memcpy(adv_rpt.dir_addr, ext_adv_report->dir_addr, BLE_MESH_ADDR_LEN); adv_rpt.addr_type = ext_adv_report->addr_type; - adv_rpt.data = ext_adv_report->adv_data; + adv_rpt.data = ext_adv_report->adv_data_len ? ext_adv_report->adv_data : NULL; adv_rpt.length = ext_adv_report->adv_data_len; adv_rpt.rssi = ext_adv_report->rssi; adv_rpt.event_type = ext_adv_report->event_type; diff --git a/components/bt/esp_ble_mesh/core/nimble_host/adapter.c b/components/bt/esp_ble_mesh/core/nimble_host/adapter.c index 60478e93e78..f5fd0279fc4 100644 --- a/components/bt/esp_ble_mesh/core/nimble_host/adapter.c +++ b/components/bt/esp_ble_mesh/core/nimble_host/adapter.c @@ -474,7 +474,7 @@ void bt_mesh_ble_ext_adv_report(struct ble_gap_ext_disc_desc *desc) /* Here, only a shallow copy needs to be implemented; * deep copying behavior occurs in btc_ble_mesh_ble_copy_req_data. */ - adv_rpt.data = desc->data; + adv_rpt.data = desc->length_data ? desc->data : NULL; adv_rpt.event_type = desc->props; adv_rpt.addr_type = desc->addr.type; diff --git a/components/bt/esp_ble_mesh/core/scan.c b/components/bt/esp_ble_mesh/core/scan.c index d161061ca74..df6f22e117e 100644 --- a/components/bt/esp_ble_mesh/core/scan.c +++ b/components/bt/esp_ble_mesh/core/scan.c @@ -380,7 +380,7 @@ static void inline callback_ble_adv_pkt(const bt_mesh_addr_t *addr, adv_rpt.addr_type = addr->type; adv_rpt.adv_type = adv_type; adv_rpt.length = length; - adv_rpt.data = data; + adv_rpt.data = length ? data : NULL; adv_rpt.rssi = rssi; bt_mesh_ble_scan_cb_evt_to_btc(&adv_rpt); } From 4cd460a3eb9f23bc8a454a3aebbf01e9ab44bc59 Mon Sep 17 00:00:00 2001 From: Shen Mengjing Date: Mon, 27 Oct 2025 14:21:11 +0800 Subject: [PATCH 011/106] docs: Update CN translation for several docs --- docs/en/api-reference/network/esp_netif_programming.rst | 2 -- docs/zh_CN/api-reference/system/system_time.rst | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/en/api-reference/network/esp_netif_programming.rst b/docs/en/api-reference/network/esp_netif_programming.rst index 18bebcd2ff8..9347a5b9e43 100644 --- a/docs/en/api-reference/network/esp_netif_programming.rst +++ b/docs/en/api-reference/network/esp_netif_programming.rst @@ -1,8 +1,6 @@ ESP-NETIF Programmers Manual ============================ -:link_to_translation:`zh_CN:[中文]` - .. _esp_netif_set_ip: Configure IP, Gateway, and DNS diff --git a/docs/zh_CN/api-reference/system/system_time.rst b/docs/zh_CN/api-reference/system/system_time.rst index 86a7ff08610..21b52671c5d 100644 --- a/docs/zh_CN/api-reference/system/system_time.rst +++ b/docs/zh_CN/api-reference/system/system_time.rst @@ -105,7 +105,7 @@ SNTP 时间同步 esp_sntp_config_t config = ESP_NETIF_SNTP_DEFAULT_CONFIG("pool.ntp.org"); esp_netif_sntp_init(&config); -一旦收到 SNTP 服务器的响应,此代码会自动执行时间同步。有时等待时间同步很有意义,调用 :cpp:func:`esp_netif_sntp_sync_wait()` 可实现此目的。应用也可以订阅时间同步事件(事件基座 ``NETIF_SNTP_EVENT``,事件 ID ``NETIF_SNTP_TIME_SYNC``): +一旦收到 SNTP 服务器的响应,此代码会自动执行时间同步。有时等待时间同步很有意义,调用 :cpp:func:`esp_netif_sntp_sync_wait()` 可实现此目的。应用也可以订阅时间同步完成时发布的事件(事件类型 ``NETIF_SNTP_EVENT``,事件 ID ``NETIF_SNTP_TIME_SYNC``)。事件数据是指向 :cpp:type:`esp_netif_sntp_time_sync_t` 的指针,其中包含已同步的 ``timeval``: .. code-block:: c From 82b08ef65184445edd59b2295631f95b88efec44 Mon Sep 17 00:00:00 2001 From: Shen Mengjing Date: Mon, 27 Oct 2025 15:48:37 +0800 Subject: [PATCH 012/106] docs: Sync EN and CN docs without 'needs translation' label --- .../esp-ble-mesh/ble-mesh-feature-list.rst | 2 +- docs/en/api-reference/network/esp_nan.rst | 4 ++-- docs/en/api-reference/peripherals/isp.rst | 1 + docs/en/api-reference/system/ulp-lp-core.rst | 2 +- .../release-6.x/6.0/build-system.rst | 2 +- .../en/migration-guides/release-6.x/6.0/tools.rst | 5 ++--- .../esp-ble-mesh/ble-mesh-feature-list.rst | 9 +++++++++ docs/zh_CN/api-reference/network/esp_nan.rst | 4 ++++ docs/zh_CN/api-reference/peripherals/isp.rst | 2 +- docs/zh_CN/api-reference/system/ulp-lp-core.rst | 3 +++ .../release-6.x/6.0/build-system.rst | 5 +++++ .../migration-guides/release-6.x/6.0/tools.rst | 15 ++++++++++++++- 12 files changed, 44 insertions(+), 10 deletions(-) diff --git a/docs/en/api-guides/esp-ble-mesh/ble-mesh-feature-list.rst b/docs/en/api-guides/esp-ble-mesh/ble-mesh-feature-list.rst index b83b6059ff5..feb37fd477a 100644 --- a/docs/en/api-guides/esp-ble-mesh/ble-mesh-feature-list.rst +++ b/docs/en/api-guides/esp-ble-mesh/ble-mesh-feature-list.rst @@ -136,11 +136,11 @@ Mesh Models * Device Firmware Update Client models * Firmware Update Client model (Preview) * Firmware Distribution Client model (coming soon) + * Device Firmware Update Server models * Firmware Update Server model (Preview) * Firmware Distribution Server model (coming soon) - Mesh Examples """"""""""""" diff --git a/docs/en/api-reference/network/esp_nan.rst b/docs/en/api-reference/network/esp_nan.rst index 42c7cdfd118..d490d0940d0 100644 --- a/docs/en/api-reference/network/esp_nan.rst +++ b/docs/en/api-reference/network/esp_nan.rst @@ -16,9 +16,9 @@ Application Examples - :example:`wifi/wifi_aware/nan_publisher` demonstrates how to use the NAN protocol to publish a service for advertising a service to other devices in the vicinity, and how to respond to the devices that subscribes to the service. -- :example:`wifi/wifi_aware/nan_subscriber` demonstrates how to use the NAN protocol to discover other devices that publishes the required service in the proximity, and communicate with them either by sending a message or initiating a datapath. +- :example:`wifi/wifi_aware/nan_subscriber` demonstrates how to use the NAN protocol to discover other devices that publish the required service in the proximity, and communicate with them either by sending a message or initiating a datapath. -- :example:`wifi/wifi_aware/usd_publisher` demonstrates how to use lightweight NAN Unsynchronized Service Discovery (NAN-USD) to advertise a service to nearby devices without forming NAN clusters. It walks through bringing up USD, publishing a service, responding to subscribers with follow-up messages, and returning to the idle state once discovery completes. +- :example:`wifi/wifi_aware/usd_publisher` demonstrates how to use lightweight NAN Unsynchronized Service Discovery (NAN-USD) protocol to advertise a service to nearby devices without forming NAN clusters. It walks through bringing up USD, publishing a service, responding to subscribers with follow-up messages, and returning to the idle state once discovery completes. - :example:`wifi/wifi_aware/usd_subscriber` demonstrates how to use the lightweight NAN Unsynchronized Service Discovery (NAN-USD) protocol to discover services advertised by nearby devices and interact with them. It covers enabling USD discovery, subscribing to services, handling follow-up exchanges, and terminating discovery after the session ends. diff --git a/docs/en/api-reference/peripherals/isp.rst b/docs/en/api-reference/peripherals/isp.rst index 21ef85af139..41c8381c325 100644 --- a/docs/en/api-reference/peripherals/isp.rst +++ b/docs/en/api-reference/peripherals/isp.rst @@ -518,6 +518,7 @@ After calling :cpp:func:`esp_isp_bf_configure`, you need to enable the ISP BF co Calling :cpp:func:`esp_isp_bf_disable` does the opposite, that is, put the driver back to the **init** state. + .. _isp-blc: ISP BLC Controller diff --git a/docs/en/api-reference/system/ulp-lp-core.rst b/docs/en/api-reference/system/ulp-lp-core.rst index a44c8d5bcfc..8dd8022b880 100644 --- a/docs/en/api-reference/system/ulp-lp-core.rst +++ b/docs/en/api-reference/system/ulp-lp-core.rst @@ -392,7 +392,7 @@ Application Examples - :example:`system/ulp/lp_core/lp_uart/lp_uart_echo` reads data written to a serial console and echoes it back. This example demonstrates the usage of the LP UART driver running on the LP core. - :example:`system/ulp/lp_core/lp_uart/lp_uart_print` shows how to print various statements from a program running on the LP core. - :example:`system/ulp/lp_core/lp_uart/lp_uart_char_seq_wakeup` shows how to trigger a wakeup using the LP UART specific character sequence wakeup mode. - - :example:`system/ulp/lp_core/lp_mailbox` shows how to use the mailbox for both synchronous and asynchronous communication between the HP and LP cores. Depending on the target, the implementation may use the hardware mailbox controller (if available) or a pure software implementation based on software interrupts. + - :example:`system/ulp/lp_core/lp_mailbox` shows how to use the mailbox for both synchronous and asynchronous communication between the HP and LP cores. Depending on the target, the implementation may use the hardware mailbox controller (if available) or a software-only implementation using interrupts. - :example:`system/ulp/lp_core/interrupt` shows how to register an interrupt handler on the LP core to receive an interrupt triggered by the main CPU. - :example:`system/ulp/lp_core/gpio_intr_pulse_counter` shows how to use GPIO interrupts to count pulses while the main CPU is in Deep-sleep mode. - :example:`system/ulp/lp_core/build_system/` demonstrates how to include custom ``CMakeLists.txt`` file for the ULP app. diff --git a/docs/en/migration-guides/release-6.x/6.0/build-system.rst b/docs/en/migration-guides/release-6.x/6.0/build-system.rst index 74a7b6571f8..467c4009e1d 100644 --- a/docs/en/migration-guides/release-6.x/6.0/build-system.rst +++ b/docs/en/migration-guides/release-6.x/6.0/build-system.rst @@ -78,7 +78,7 @@ Replace ``PRIO`` with an integer value. Lower values are executed earlier. This Changes in Configuration Files Syntax ------------------------------------- -ESP-IDF v6 uses esp-idf-kconfig v3, which introduces several changes in the configuration (``Kconfig``) files. For the full list of changes, please refer to the `esp-idf-kconfig migration guide from v2.x to v3.x `_. +ESP-IDF v6 uses esp-idf-kconfig v3, which introduces several changes in the configuration (``Kconfig``) files. For the full list of changes, please refer to the `Migration Guide From esp-idf-kconfig v2.x to v3.x `_. Compiler Options ---------------- diff --git a/docs/en/migration-guides/release-6.x/6.0/tools.rst b/docs/en/migration-guides/release-6.x/6.0/tools.rst index 723ed6bddec..618485a5636 100644 --- a/docs/en/migration-guides/release-6.x/6.0/tools.rst +++ b/docs/en/migration-guides/release-6.x/6.0/tools.rst @@ -57,7 +57,7 @@ This affects ESP-IDF users who use system-provided CMake and custom CMake. Unit-Test-App ------------- -The legacy unit-test-app has been moved out of ESP-IDF repository as no ESP-IDF component longer uses it for running tests. It is now available at the `component registry `_ and a test app can be created using the ``idf.py create-project-from-example`` command: +The legacy unit-test-app has been moved out of ESP-IDF repository as it is no longer used by any ESP-IDF component for running tests. It is now available at `The ESP Component Registry `__ and a test app can be created using the ``idf.py create-project-from-example`` command: .. code-block:: bash @@ -66,7 +66,7 @@ The legacy unit-test-app has been moved out of ESP-IDF repository as no ESP-IDF Catch ----- -The header-only copy of Catch2 unit testing library previously located in tools/catch directory has been removed. To continue using Catch2 in your project, migrate to Catch2 3.x, available from the `ESP component registry `_. For an example of migrating from Catch2 2.x to Catch2 3.x, see commit 79a2c15477dc327550ff46a64ee0f8b4679cc417. +The header-only copy of Catch2 unit testing library previously located in tools/catch directory has been removed. To continue using Catch2 in your project, migrate to Catch2 3.x, available from `The ESP Component Registry `__. For an example of migrating from Catch2 2.x to Catch2 3.x, see commit 79a2c15477dc327550ff46a64ee0f8b4679cc417. Dropped ``idf.py size --legacy`` option --------------------------------------- @@ -98,4 +98,3 @@ The ``--format json`` option has been replaced with ``--format json2``. The ``js } ] } - diff --git a/docs/zh_CN/api-guides/esp-ble-mesh/ble-mesh-feature-list.rst b/docs/zh_CN/api-guides/esp-ble-mesh/ble-mesh-feature-list.rst index edac2c0b2c1..503ddd80585 100644 --- a/docs/zh_CN/api-guides/esp-ble-mesh/ble-mesh-feature-list.rst +++ b/docs/zh_CN/api-guides/esp-ble-mesh/ble-mesh-feature-list.rst @@ -29,6 +29,7 @@ Mesh 核心 * 私有信标 * 子网桥 * 次要增强 + * 设备固件更新(预览) * 多个客户端模型同时运行 * 支持多个客户端模型同时向不同节点发送数据包 @@ -132,6 +133,14 @@ Mesh 模型 * 灯光 LC 服务器 * 灯光 LC 设置服务器 +* 设备固件更新客户端模型 + * 固件更新客户端模型(预览) + * 固件分发客户端模型(即将推出) + +* 设备固件更新服务器模型 + * 固件更新服务器模型(预览) + * 固件分发服务器模型(即将推出) + Mesh 示例 """"""""""" diff --git a/docs/zh_CN/api-reference/network/esp_nan.rst b/docs/zh_CN/api-reference/network/esp_nan.rst index 8dde70f378f..563ee325048 100644 --- a/docs/zh_CN/api-reference/network/esp_nan.rst +++ b/docs/zh_CN/api-reference/network/esp_nan.rst @@ -18,6 +18,10 @@ Wi-Fi Aware\ :sup:`TM`,也可称为 NAN (Neighbor Awareness Networking) 协议 - :example:`wifi/wifi_aware/nan_subscriber` 演示如何使用 NAN 协议发现附近发布所需服务的其他设备,并通过发送消息或启动数据路径与它们进行通信。 +- :example:`wifi/wifi_aware/usd_publisher` 演示了如何使用轻量级 NAN 非同步服务发现 (NAN-USD) 协议向附近设备发布服务而无需形成 NAN 集群。示例讲解了如何启动 USD、发布服务、通过后续消息响应订阅者,以及在发现完成后返回空闲状态。 + +- :example:`wifi/wifi_aware/usd_subscriber` 演示了如何使用轻量级 NAN 非同步服务发现 (NAN-USD) 协议发现附近设备发布的服务并与之交互。示例讲解了如何启用 USD 发现、订阅服务、处理后续消息交换,以及在会话结束后终止发现。 + API 参考 ------------- diff --git a/docs/zh_CN/api-reference/peripherals/isp.rst b/docs/zh_CN/api-reference/peripherals/isp.rst index aa08fb99c35..8bcaa3c1f02 100644 --- a/docs/zh_CN/api-reference/peripherals/isp.rst +++ b/docs/zh_CN/api-reference/peripherals/isp.rst @@ -399,7 +399,7 @@ ISP AE 控制器 .. code-block:: c - esp_isp_ae_config_t ae_config = { + esp_isp_ae_config_t ae_config = { .sample_point = ISP_AE_SAMPLE_POINT_AFTER_DEMOSAIC, }; isp_ae_ctlr_t ae_ctlr = NULL; diff --git a/docs/zh_CN/api-reference/system/ulp-lp-core.rst b/docs/zh_CN/api-reference/system/ulp-lp-core.rst index d88ccfd3cdc..2a51dd96188 100644 --- a/docs/zh_CN/api-reference/system/ulp-lp-core.rst +++ b/docs/zh_CN/api-reference/system/ulp-lp-core.rst @@ -237,6 +237,7 @@ ULP LP 内核支持的外设 * LP I2C * LP UART :SOC_LP_SPI_SUPPORTED: * LP SPI + :SOC_LP_MAILBOX_SUPPORTED: * LP 邮箱 .. only:: CONFIG_ESP_ROM_HAS_LP_ROM @@ -391,6 +392,7 @@ LP 内核调试特性 - :example:`system/ulp/lp_core/lp_uart/lp_uart_echo` 展示了低功耗内核上运行的 LP UART 驱动程序如何读取并回显写入串行控制台的数据。 - :example:`system/ulp/lp_core/lp_uart/lp_uart_print` 展示了如何在低功耗内核上使用串口打印功能。 - :example:`system/ulp/lp_core/lp_uart/lp_uart_char_seq_wakeup` 展示了如何使用 LP UART 特定字符序列唤醒模式触发唤醒。 + - :example:`system/ulp/lp_core/lp_mailbox` 展示了如何在 HP 内核和 LP 内核之间使用邮箱进行同步和异步通信。根据目标设备的不同,示例实现可能会使用硬件邮箱控制器(如果可用),或者使用基于中断的纯软件实现。 - :example:`system/ulp/lp_core/interrupt` 展示了如何在 LP 内核上注册中断处理程序,接收由主 CPU 触发的中断。 - :example:`system/ulp/lp_core/gpio_intr_pulse_counter` 展示了如何在主 CPU 处于 Deep-sleep 模式时,使用 GPIO 中断为脉冲计数。 - :example:`system/ulp/lp_core/build_system/` 演示了如何为 ULP 应用程序添加自定义的 ``CMakeLists.txt`` 文件。 @@ -423,6 +425,7 @@ LP 内核 API 参考 .. include-build-file:: inc/ulp_lp_core_gpio.inc .. include-build-file:: inc/ulp_lp_core_i2c.inc .. include-build-file:: inc/ulp_lp_core_uart.inc +.. include-build-file:: inc/ulp_lp_core_mailbox.inc .. include-build-file:: inc/ulp_lp_core_print.inc .. include-build-file:: inc/ulp_lp_core_interrupts.inc diff --git a/docs/zh_CN/migration-guides/release-6.x/6.0/build-system.rst b/docs/zh_CN/migration-guides/release-6.x/6.0/build-system.rst index 5456d5cadbb..2699ed54dc4 100644 --- a/docs/zh_CN/migration-guides/release-6.x/6.0/build-system.rst +++ b/docs/zh_CN/migration-guides/release-6.x/6.0/build-system.rst @@ -79,3 +79,8 @@ ------------------ ESP-IDF v6 使用了 esp-idf-kconfig v3,对配置文件 ``Kconfig`` 的语法进行了若干变更。完整变更列表请参阅 `Migration Guide From esp-idf-kconfig v2.x to v3.x `_。 + +编译器选项 +---------- + +默认的编译器警告将被视为报错。配置选项 :ref:`CONFIG_COMPILER_DISABLE_DEFAULT_ERRORS` 已被更改为 N。 diff --git a/docs/zh_CN/migration-guides/release-6.x/6.0/tools.rst b/docs/zh_CN/migration-guides/release-6.x/6.0/tools.rst index ac390d31bed..0a88b390858 100644 --- a/docs/zh_CN/migration-guides/release-6.x/6.0/tools.rst +++ b/docs/zh_CN/migration-guides/release-6.x/6.0/tools.rst @@ -54,6 +54,20 @@ CMake 版本升级 此变更影响所有使用系统自带 CMake 或自定义 CMake 的 ESP-IDF 用户。 +Unit-Test-App +------------- + +旧版的 unit-test-app 已经从 ESP-IDF 仓库中移出,目前已无 ESP-IDF 组件使用该组件进行测试。现在可通过 `乐鑫组件注册表 `__ 获取 unit-test-app,并且可以使用 ``idf.py create-project-from-example`` 命令创建测试应用: + +.. code-block:: bash + + idf.py create-project-from-example espressif/unit-test-app:unit-test-app + +Catch +----- + +之前位于 tools/catch 目录下的 Catch2 单元测试库(仅头文件)已被移除。若想在项目中继续使用 Catch2,请迁移至 Catch2 3.x,该版本可从 `乐鑫组件注册表 `__ 中获取。关于从 Catch2 2.x 迁移到 Catch2 3.x 的示例,请参见 79a2c15477dc327550ff46a64ee0f8b4679cc417 中的提交记录。 + 移除 ``idf.py size --legacy`` 选项 ------------------------------------- @@ -84,4 +98,3 @@ CMake 版本升级 } ] } - From 4c163700973ffd9da4c4cd46d98b111bf1a935dc Mon Sep 17 00:00:00 2001 From: Zhou Xiao Date: Thu, 30 Oct 2025 21:13:17 +0800 Subject: [PATCH 013/106] fix(ble): fixed hci event log when link layer logging is disabled (cherry picked from commit 777f21783b3cf003edda409d8716f562b26fb69c) Co-authored-by: Zhou Xiao --- components/bt/common/ble_log/ble_log_spi_out.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/components/bt/common/ble_log/ble_log_spi_out.c b/components/bt/common/ble_log/ble_log_spi_out.c index e6ca8d7a440..8c29265797f 100644 --- a/components/bt/common/ble_log/ble_log_spi_out.c +++ b/components/bt/common/ble_log/ble_log_spi_out.c @@ -1365,12 +1365,13 @@ int ble_log_spi_out_hci_write(uint8_t source, const uint8_t *addr, uint16_t len) return -1; } - if (source == BLE_LOG_SPI_OUT_SOURCE_HCI_UPSTREAM) { #if SPI_OUT_LL_ENABLED + if (source == BLE_LOG_SPI_OUT_SOURCE_HCI_UPSTREAM) { ble_log_spi_out_ll_write(len, addr, 0, NULL, BIT(LL_LOG_FLAG_HCI_UPSTREAM)); -#endif // SPI_OUT_LL_ENABLED } - if (source == BLE_LOG_SPI_OUT_SOURCE_HCI_DOWNSTREAM) { + if (source == BLE_LOG_SPI_OUT_SOURCE_HCI_DOWNSTREAM) +#endif /* SPI_OUT_LL_ENABLED */ + { spi_out_log_cb_t *log_cb; bool fallback = false; if (!spi_out_get_task_mapping(LOG_MODULE_TASK_MAP(hci), From e69c799b442b833798322d6e84c7c138baf08cde Mon Sep 17 00:00:00 2001 From: "nilesh.kale" Date: Wed, 3 Sep 2025 13:50:27 +0530 Subject: [PATCH 014/106] feat(hal): add support for ESP32-P4 ECO5 ECC peripheral This commit also enabled constant time mode for ECC. --- components/hal/esp32p4/include/hal/ecc_ll.h | 21 ++++++++++++------- .../esp32p4/include/soc/Kconfig.soc_caps.in | 4 ++++ components/soc/esp32p4/include/soc/soc_caps.h | 3 +++ 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/components/hal/esp32p4/include/hal/ecc_ll.h b/components/hal/esp32p4/include/hal/ecc_ll.h index d7977a83b81..4faf920ae30 100644 --- a/components/hal/esp32p4/include/hal/ecc_ll.h +++ b/components/hal/esp32p4/include/hal/ecc_ll.h @@ -9,8 +9,11 @@ #include #include "hal/assert.h" #include "hal/ecc_types.h" +#include "hal/efuse_hal.h" #include "soc/ecc_mult_reg.h" #include "soc/hp_sys_clkrst_struct.h" +#include "soc/chip_revision.h" +#include "hal/config.h" #ifdef __cplusplus extern "C" { @@ -124,16 +127,15 @@ static inline void ecc_ll_set_mode(ecc_mode_t mode) static inline void ecc_ll_set_curve(ecc_curve_t curve) { - switch(curve) { - case ECC_CURVE_SECP256R1: - REG_SET_BIT(ECC_MULT_CONF_REG, ECC_MULT_KEY_LENGTH); - break; + switch (curve) { case ECC_CURVE_SECP192R1: - REG_CLR_BIT(ECC_MULT_CONF_REG, ECC_MULT_KEY_LENGTH); + case ECC_CURVE_SECP256R1: + case ECC_CURVE_SECP384R1: + case ECC_CURVE_SM2: + REG_SET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_KEY_LENGTH, curve); break; default: HAL_ASSERT(false && "Unsupported curve"); - return; } } @@ -248,8 +250,11 @@ static inline void ecc_ll_read_param(ecc_ll_param_t param, uint8_t *buf, uint16_ static inline void ecc_ll_enable_constant_time_point_mul(bool enable) { - // Not supported for ESP32-P4 - (void) enable; //unused + if (enable) { + REG_SET_BIT(ECC_MULT_CONF_REG, ECC_MULT_SECURITY_MODE); + } else { + REG_CLR_BIT(ECC_MULT_CONF_REG, ECC_MULT_SECURITY_MODE); + } } #ifdef __cplusplus diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index ccb8d58c873..b00533d2c2f 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -1415,6 +1415,10 @@ config SOC_SHA_SUPPORT_SHA512_T bool default y +config SOC_ECC_CONSTANT_TIME_POINT_MUL + bool + default y + config SOC_ECDSA_SUPPORT_EXPORT_PUBKEY bool default y diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index 2a64a7ea718..cd73c71aa7b 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -528,6 +528,9 @@ #define SOC_SHA_SUPPORT_SHA512_256 (1) #define SOC_SHA_SUPPORT_SHA512_T (1) +/*--------------------------- ECC CAPS ---------------------------------------*/ +#define SOC_ECC_CONSTANT_TIME_POINT_MUL 1 + /*--------------------------- ECDSA CAPS ---------------------------------------*/ #define SOC_ECDSA_SUPPORT_EXPORT_PUBKEY (1) #define SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE (1) From 52b1f896cbdc821321ab8bd390b9a8f976777df5 Mon Sep 17 00:00:00 2001 From: "nilesh.kale" Date: Mon, 6 Oct 2025 12:19:15 +0530 Subject: [PATCH 015/106] feat: added test_cases for ECC P-384 curve operations --- components/hal/ecc_hal.c | 22 +- components/hal/esp32c5/include/hal/ecc_ll.h | 5 + components/hal/esp32p4/include/hal/ecc_ll.h | 9 + .../test_apps/crypto/main/ecc/ecc_params.h | 149 +++++- .../hal/test_apps/crypto/main/ecc/test_ecc.c | 468 ++++++++++++------ .../esp32c5/include/soc/Kconfig.soc_caps.in | 4 + components/soc/esp32c5/include/soc/soc_caps.h | 1 + .../esp32p4/include/soc/Kconfig.soc_caps.in | 4 + components/soc/esp32p4/include/soc/soc_caps.h | 1 + 9 files changed, 502 insertions(+), 161 deletions(-) diff --git a/components/hal/ecc_hal.c b/components/hal/ecc_hal.c index 79c28ce5019..47d068401c0 100644 --- a/components/hal/ecc_hal.c +++ b/components/hal/ecc_hal.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -7,6 +7,14 @@ #include "hal/ecc_ll.h" #include "soc/soc_caps.h" +/* ECC curve size constants in bytes */ +#define ECC_P192_SIZE_BYTES 24 +#define ECC_P256_SIZE_BYTES 32 +#define ECC_P384_SIZE_BYTES 48 + +/* Maximum ECC buffer size for all supported curves */ +#define ECC_MAX_BUFFER_SIZE 48 + void ecc_hal_set_mode(ecc_mode_t mode) { ecc_ll_set_mode(mode); @@ -30,7 +38,7 @@ int ecc_hal_is_calc_finished(void) static void clear_param_registers(void) { - uint8_t buf[32] = {0}; + uint8_t buf[ECC_MAX_BUFFER_SIZE] = {0}; ecc_ll_write_param(ECC_PARAM_PX, buf, sizeof(buf)); ecc_ll_write_param(ECC_PARAM_PY, buf, sizeof(buf)); @@ -44,7 +52,7 @@ static void clear_param_registers(void) void ecc_hal_write_mul_param(const uint8_t *k, const uint8_t *px, const uint8_t *py, uint16_t len) { - ecc_curve_t curve = len == 32 ? ECC_CURVE_SECP256R1 : ECC_CURVE_SECP192R1; + ecc_curve_t curve = len == ECC_P384_SIZE_BYTES ? ECC_CURVE_SECP384R1 : (len == ECC_P256_SIZE_BYTES ? ECC_CURVE_SECP256R1 : ECC_CURVE_SECP192R1); ecc_ll_set_curve(curve); clear_param_registers(); @@ -56,7 +64,7 @@ void ecc_hal_write_mul_param(const uint8_t *k, const uint8_t *px, const uint8_t void ecc_hal_write_verify_param(const uint8_t *px, const uint8_t *py, uint16_t len) { - ecc_curve_t curve = len == 32 ? ECC_CURVE_SECP256R1 : ECC_CURVE_SECP192R1; + ecc_curve_t curve = len == ECC_P384_SIZE_BYTES ? ECC_CURVE_SECP384R1 : (len == ECC_P256_SIZE_BYTES ? ECC_CURVE_SECP256R1 : ECC_CURVE_SECP192R1); ecc_ll_set_curve(curve); clear_param_registers(); @@ -96,7 +104,7 @@ void ecc_hal_set_mod_base(ecc_mod_base_t base) void ecc_hal_write_jacob_verify_param(const uint8_t *qx, const uint8_t *qy, const uint8_t *qz, uint16_t len) { - ecc_curve_t curve = len == 32 ? ECC_CURVE_SECP256R1 : ECC_CURVE_SECP192R1; + ecc_curve_t curve = len == ECC_P384_SIZE_BYTES ? ECC_CURVE_SECP384R1 : (len == ECC_P256_SIZE_BYTES ? ECC_CURVE_SECP256R1 : ECC_CURVE_SECP192R1); ecc_ll_set_curve(curve); clear_param_registers(); @@ -127,7 +135,7 @@ int ecc_hal_read_jacob_mul_result(uint8_t *rx, uint8_t *ry, uint8_t *rz, uint16_ void ecc_hal_write_point_add_param(const uint8_t *px, const uint8_t *py, const uint8_t *qx, const uint8_t *qy, const uint8_t *qz, uint16_t len) { - ecc_curve_t curve = len == 32 ? ECC_CURVE_SECP256R1 : ECC_CURVE_SECP192R1; + ecc_curve_t curve = len == ECC_P384_SIZE_BYTES ? ECC_CURVE_SECP384R1 : (len == ECC_P256_SIZE_BYTES ? ECC_CURVE_SECP256R1 : ECC_CURVE_SECP192R1); ecc_ll_set_curve(curve); clear_param_registers(); @@ -154,7 +162,7 @@ int ecc_hal_read_point_add_result(uint8_t *rx, uint8_t *ry, uint8_t *rz, uint16_ void ecc_hal_write_mod_op_param(const uint8_t *a, const uint8_t *b, uint16_t len) { - ecc_curve_t curve = len == 32 ? ECC_CURVE_SECP256R1 : ECC_CURVE_SECP192R1; + ecc_curve_t curve = len == ECC_P384_SIZE_BYTES ? ECC_CURVE_SECP384R1 : (len == ECC_P256_SIZE_BYTES ? ECC_CURVE_SECP256R1 : ECC_CURVE_SECP192R1); ecc_ll_set_curve(curve); clear_param_registers(); diff --git a/components/hal/esp32c5/include/hal/ecc_ll.h b/components/hal/esp32c5/include/hal/ecc_ll.h index 9060cdbf728..54c7b8bc2d9 100644 --- a/components/hal/esp32c5/include/hal/ecc_ll.h +++ b/components/hal/esp32c5/include/hal/ecc_ll.h @@ -148,6 +148,11 @@ static inline void ecc_ll_set_mod_base(ecc_mod_base_t base) } } +static inline bool ecc_ll_is_p384_curve_operations_supported(void) +{ + return true; +} + static inline void ecc_ll_enable_constant_time_point_mul(bool enable) { if (enable) { diff --git a/components/hal/esp32p4/include/hal/ecc_ll.h b/components/hal/esp32p4/include/hal/ecc_ll.h index 4faf920ae30..8e56f508cf8 100644 --- a/components/hal/esp32p4/include/hal/ecc_ll.h +++ b/components/hal/esp32p4/include/hal/ecc_ll.h @@ -248,6 +248,15 @@ static inline void ecc_ll_read_param(ecc_ll_param_t param, uint8_t *buf, uint16_ memcpy(buf, (void *)reg, len); } +static inline bool ecc_ll_is_p384_curve_operations_supported(void) +{ +#if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300 + return true; +#else + return false; +#endif +} + static inline void ecc_ll_enable_constant_time_point_mul(bool enable) { if (enable) { diff --git a/components/hal/test_apps/crypto/main/ecc/ecc_params.h b/components/hal/test_apps/crypto/main/ecc/ecc_params.h index 77aecedda9c..85fde9de38d 100644 --- a/components/hal/test_apps/crypto/main/ecc/ecc_params.h +++ b/components/hal/test_apps/crypto/main/ecc/ecc_params.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 * @@ -220,3 +220,150 @@ static const uint8_t ecc192_mul_res[] = { 0x8C, 0xFB, 0xA5, 0xCE, 0x1E, 0x7B, 0xE6, 0xF3, 0x8F, 0x79, 0x71, 0xCF, 0xD6, 0xF3, 0x41, 0xE6 }; + +#if SOC_ECC_SUPPORT_CURVE_P384 +static const uint8_t ecc_p384_point_x[] = { + 0xaa, 0x87, 0xca, 0x22, 0xbe, 0x8b, 0x05, 0x37, + 0x8e, 0xb1, 0xc7, 0x1e, 0xf3, 0x20, 0xad, 0x74, + 0x6e, 0x1d, 0x3b, 0x62, 0x8b, 0xa7, 0x9b, 0x98, + 0x59, 0xf7, 0x41, 0xe0, 0x82, 0x54, 0x2a, 0x38, + 0x55, 0x02, 0xf2, 0x5d, 0xbf, 0x55, 0x29, 0x6c, + 0x3a, 0x54, 0x5e, 0x38, 0x72, 0x76, 0x0a, 0xb7 +}; + +static const uint8_t ecc_p384_point_y[] = { + 0x36, 0x17, 0xde, 0x4a, 0x96, 0x26, 0x2c, 0x6f, + 0x5d, 0x9e, 0x98, 0xbf, 0x92, 0x92, 0xdc, 0x29, + 0xf8, 0xf4, 0x1d, 0xbd, 0x28, 0x9a, 0x14, 0x7c, + 0xe9, 0xda, 0x31, 0x13, 0xb5, 0xf0, 0xb8, 0xc0, + 0x0a, 0x60, 0xb1, 0xce, 0x1d, 0x7e, 0x81, 0x9d, + 0x7a, 0x43, 0x1d, 0x7c, 0x90, 0xea, 0x0e, 0x5f +}; + +static const uint8_t ecc_p384_scalar[] = { + 0x68, 0xd1, 0x09, 0xa7, 0xc7, 0x7e, 0xeb, 0xbd, + 0x43, 0x18, 0x7e, 0xdd, 0x69, 0x23, 0x7e, 0x0a, + 0xef, 0x07, 0xc2, 0x0e, 0xc5, 0x3d, 0xe7, 0xcb, + 0xd4, 0x36, 0xad, 0x9b, 0xdc, 0xf8, 0x6c, 0x5c, + 0x0c, 0x3d, 0xce, 0x45, 0xcd, 0x6f, 0x7f, 0x18, + 0x40, 0xc5, 0x29, 0xf3, 0xcd, 0x12, 0x1d, 0xc2 +}; + +static const uint8_t ecc_p384_mul_res_x[] = { + 0x74, 0x1d, 0xc3, 0xba, 0xac, 0x60, 0x37, 0xfc, + 0x57, 0x85, 0x90, 0x95, 0x64, 0xe6, 0xd1, 0xef, + 0x86, 0xdf, 0x42, 0xe0, 0xaf, 0x11, 0x24, 0x1f, + 0xe9, 0x97, 0x6e, 0x0c, 0xd9, 0xe5, 0xa0, 0x5d, + 0xd9, 0x91, 0x96, 0x71, 0xef, 0x96, 0xe9, 0x7e, + 0x90, 0xba, 0xa8, 0x33, 0xe2, 0x2e, 0xf0, 0x7b +}; + +static const uint8_t ecc_p384_mul_res_y[] = { + 0xc3, 0xe0, 0x66, 0x50, 0xd9, 0x1e, 0xa9, 0x42, + 0xcb, 0x0d, 0xec, 0xb6, 0x29, 0xe2, 0xae, 0x75, + 0xc6, 0xa2, 0xb9, 0xa6, 0xcf, 0x2c, 0x97, 0x01, + 0xcc, 0xff, 0x7c, 0x1c, 0xd1, 0x01, 0xde, 0xbc, + 0x40, 0x56, 0x8c, 0x18, 0x21, 0x9d, 0xbd, 0xc0, + 0x2d, 0x41, 0x5b, 0x92, 0x52, 0x5a, 0x40, 0x57 +}; + +static const uint8_t ecc_p384_jacob_mul_res_x_le[] = { + 0xE3, 0xFC, 0x92, 0x29, 0xCF, 0xCB, 0xF7, 0x90, + 0x04, 0xAD, 0xD2, 0x7C, 0xFD, 0x4B, 0xFB, 0x18, + 0xF1, 0x34, 0x93, 0x2C, 0xA3, 0x66, 0x02, 0xE8, + 0x54, 0xD3, 0x8C, 0xB6, 0x69, 0x75, 0x4E, 0xD2, + 0x80, 0xA3, 0x01, 0xC7, 0x78, 0x41, 0x9B, 0x2F, + 0x11, 0xEF, 0x79, 0x45, 0x8F, 0x31, 0x2A, 0x96 +}; + +static const uint8_t ecc_p384_jacob_mul_res_y_le[] = { + 0x42, 0xC0, 0x3B, 0xF0, 0x81, 0x86, 0xA0, 0xC9, + 0xA0, 0xC6, 0x59, 0x34, 0xF1, 0x2B, 0xDC, 0x02, + 0xE8, 0x92, 0x10, 0x1C, 0xBF, 0xAC, 0x5E, 0x17, + 0x5F, 0x53, 0xE2, 0x74, 0x3E, 0x46, 0xBA, 0xE9, + 0x83, 0x7B, 0xF3, 0x67, 0xD4, 0xF7, 0xA3, 0x4F, + 0x05, 0xB8, 0x62, 0xC0, 0x42, 0x1C, 0x0D, 0x77 +}; + +static const uint8_t ecc_p384_jacob_mul_res_z_le[] = { + 0xCB, 0x3B, 0xFB, 0x58, 0x85, 0x3A, 0xA5, 0x47, + 0x22, 0x9C, 0xF8, 0x0B, 0xDB, 0x08, 0xDD, 0x0D, + 0xA5, 0x7B, 0xE4, 0x2D, 0x1E, 0xEF, 0x8B, 0x88, + 0xE2, 0x73, 0x24, 0xCC, 0x74, 0xCA, 0xBA, 0x0A, + 0x69, 0x22, 0xEF, 0x7F, 0xCC, 0x92, 0x37, 0x24, + 0x8D, 0xF3, 0xAC, 0xCF, 0x76, 0xD7, 0x16, 0x4D +}; + +static const uint8_t ecc384_x[] = { + 0xaa, 0x87, 0xca, 0x22, 0xbe, 0x8b, 0x05, 0x37, + 0x8e, 0xb1, 0xc7, 0x1e, 0xf3, 0x20, 0xad, 0x74, + 0x6e, 0x1d, 0x3b, 0x62, 0x8b, 0xa7, 0x9b, 0x98, + 0x59, 0xf7, 0x41, 0xe0, 0x82, 0x54, 0x2a, 0x38, + 0x55, 0x02, 0xf2, 0x5d, 0xbf, 0x55, 0x29, 0x6c, + 0x3a, 0x54, 0x5e, 0x38, 0x72, 0x76, 0x0a, 0xb7 +}; + +static const uint8_t ecc384_y[] = { + 0x36, 0x17, 0xde, 0x4a, 0x96, 0x26, 0x2c, 0x6f, + 0x5d, 0x9e, 0x98, 0xbf, 0x92, 0x92, 0xdc, 0x29, + 0xf8, 0xf4, 0x1d, 0xbd, 0x28, 0x9a, 0x14, 0x7c, + 0xe9, 0xda, 0x31, 0x13, 0xb5, 0xf0, 0xb8, 0xc0, + 0x0a, 0x60, 0xb1, 0xce, 0x1d, 0x7e, 0x81, 0x9d, + 0x7a, 0x43, 0x1d, 0x7c, 0x90, 0xea, 0x0e, 0x5f +}; + +static const uint8_t ecc384_add_res[] = { + 0x6D, 0x75, 0xE3, 0xA0, 0xE9, 0x98, 0x45, 0xB9, + 0x70, 0xA8, 0xAF, 0x95, 0xD3, 0xA5, 0x6F, 0x46, + 0x87, 0xE4, 0x21, 0x2B, 0x32, 0xF4, 0x4C, 0x4D, + 0x43, 0xD2, 0x73, 0xF3, 0x37, 0x45, 0xE3, 0xF8, + 0x5F, 0x62, 0xA3, 0x2C, 0xDD, 0xD3, 0xAA, 0x09, + 0xB5, 0x97, 0x7B, 0xB4, 0x02, 0x61, 0x19, 0x16 +}; + +static const uint8_t ecc384_sub_res[] = { + 0x74, 0x70, 0xEC, 0xD7, 0x27, 0x65, 0xD9, 0xC7, + 0x30, 0x13, 0x2F, 0x5F, 0x60, 0x8E, 0xD0, 0x4A, + 0x76, 0x28, 0x1D, 0xA5, 0x62, 0x0D, 0x87, 0x1C, + 0x70, 0x1C, 0x10, 0xCD, 0xCD, 0x63, 0x71, 0x77, + 0x4A, 0xA2, 0x40, 0x8F, 0xA1, 0xD7, 0xA7, 0xCE, + 0xBF, 0x10, 0x41, 0xBC, 0xE1, 0x8B, 0xFB, 0x57 +}; + +static const uint8_t ecc384_mul_res[] = { + 0x63, 0x67, 0x7D, 0x8B, 0x32, 0x4C, 0x13, 0xE6, + 0x49, 0xAB, 0xDE, 0x9F, 0xDB, 0x68, 0x57, 0x49, + 0xDE, 0x88, 0x77, 0x56, 0x45, 0xB0, 0x7B, 0xD7, + 0xAB, 0xFB, 0xF4, 0x55, 0xC0, 0xD3, 0xD0, 0x2D, + 0x37, 0x14, 0x8F, 0x3A, 0x1E, 0x72, 0x7E, 0x49, + 0x77, 0xA0, 0xB9, 0xC8, 0xD0, 0x44, 0xDD, 0x16 +}; + +static const uint8_t ecc384_num[] = { + 0x68, 0xd1, 0x09, 0xa7, 0xc7, 0x7e, 0xeb, 0xbd, + 0x43, 0x18, 0x7e, 0xdd, 0x69, 0x23, 0x7e, 0x0a, + 0xef, 0x07, 0xc2, 0x0e, 0xc5, 0x3d, 0xe7, 0xcb, + 0xd4, 0x36, 0xad, 0x9b, 0xdc, 0xf8, 0x6c, 0x5c, + 0x0c, 0x3d, 0xce, 0x45, 0xcd, 0x6f, 0x7f, 0x18, + 0x40, 0xc5, 0x29, 0xf3, 0xcd, 0x12, 0x1d, 0xc2 +}; + +static const uint8_t ecc384_den[] = { + 0x68, 0xd1, 0x09, 0xa7, 0xc7, 0x7e, 0xeb, 0xbd, + 0x43, 0x18, 0x7e, 0xdd, 0x69, 0x23, 0x7e, 0x0a, + 0xef, 0x07, 0xc2, 0x0e, 0xc5, 0x3d, 0xe7, 0xcb, + 0xd4, 0x36, 0xad, 0x9b, 0xdc, 0xf8, 0x6c, 0x5c, + 0x0c, 0x3d, 0xce, 0x45, 0xcd, 0x6f, 0x7f, 0x18, + 0x40, 0xc5, 0x8c, 0x56, 0x68, 0xb7, 0xb8, 0x67 +}; + +static const uint8_t ecc384_inv_mul_res[] = { + 0x05, 0x35, 0xe1, 0x77, 0xd0, 0xd0, 0x47, 0x38, + 0x65, 0xe8, 0x4c, 0xeb, 0x31, 0x96, 0xd9, 0xfc, + 0x18, 0x0a, 0xe2, 0xd9, 0x5d, 0x40, 0xf4, 0x89, + 0x8a, 0xc6, 0xfc, 0x32, 0x5f, 0xd8, 0xc7, 0x74, + 0x15, 0x44, 0xa5, 0xd6, 0xca, 0x72, 0xc1, 0x2f, + 0xd7, 0xb3, 0x17, 0xda, 0x6f, 0x49, 0x17, 0xb7 +}; + +#endif /* SOC_ECC_SUPPORT_CURVE_P384 */ diff --git a/components/hal/test_apps/crypto/main/ecc/test_ecc.c b/components/hal/test_apps/crypto/main/ecc/test_ecc.c index 603771d081c..b8fe24a7e58 100644 --- a/components/hal/test_apps/crypto/main/ecc/test_ecc.c +++ b/components/hal/test_apps/crypto/main/ecc/test_ecc.c @@ -20,6 +20,15 @@ #include "unity_fixture.h" #include "ccomp_timer.h" +/* ECC curve size constants in bytes */ +#define ECC_P192_SIZE_BYTES 24 +#define ECC_P256_SIZE_BYTES 32 +#define ECC_P384_SIZE_BYTES 48 + +/* Maximum ECC buffer size for all supported curves */ +#define ECC_MAX_BUFFER_SIZE 48 + +/* ECC operation support flags */ #define SOC_ECC_SUPPORT_POINT_MULT 1 #define SOC_ECC_SUPPORT_POINT_VERIFY 1 @@ -36,7 +45,7 @@ static void ecc_be_to_le(const uint8_t* be_point, uint8_t *le_point, uint8_t len) { /* When the size is 24 bytes, it should be padded with 0 bytes*/ - memset(le_point, 0x0, 32); + memset(le_point, 0x0, ECC_MAX_BUFFER_SIZE); for (int i = 0; i < len; i++) { le_point[i] = be_point[len - i - 1]; @@ -82,61 +91,89 @@ static void ecc_point_mul(const uint8_t *k_le, const uint8_t *x_le, const uint8_ static void test_ecc_point_mul_inner(bool verify_first) { - uint8_t scalar_le[32]; - uint8_t x_le[32]; - uint8_t y_le[32]; + uint8_t scalar_le[ECC_MAX_BUFFER_SIZE]; + uint8_t x_le[ECC_MAX_BUFFER_SIZE]; + uint8_t y_le[ECC_MAX_BUFFER_SIZE]; /* P256 */ - ecc_be_to_le(ecc_p256_scalar, scalar_le, 32); - ecc_be_to_le(ecc_p256_point_x, x_le, 32); - ecc_be_to_le(ecc_p256_point_y, y_le, 32); + ecc_be_to_le(ecc_p256_scalar, scalar_le, ECC_P256_SIZE_BYTES); + ecc_be_to_le(ecc_p256_point_x, x_le, ECC_P256_SIZE_BYTES); + ecc_be_to_le(ecc_p256_point_y, y_le, ECC_P256_SIZE_BYTES); - uint8_t x_res_le[32]; - uint8_t y_res_le[32]; + uint8_t x_res_le[ECC_MAX_BUFFER_SIZE]; + uint8_t y_res_le[ECC_MAX_BUFFER_SIZE]; - ecc_point_mul(scalar_le, x_le, y_le, 32, verify_first, x_res_le, y_res_le); + ecc_point_mul(scalar_le, x_le, y_le, ECC_P256_SIZE_BYTES, verify_first, x_res_le, y_res_le); - uint8_t x_mul_le[32]; - uint8_t y_mul_le[32]; + uint8_t x_mul_le[ECC_MAX_BUFFER_SIZE]; + uint8_t y_mul_le[ECC_MAX_BUFFER_SIZE]; - ecc_be_to_le(ecc_p256_mul_res_x, x_mul_le, 32); - ecc_be_to_le(ecc_p256_mul_res_y, y_mul_le, 32); + ecc_be_to_le(ecc_p256_mul_res_x, x_mul_le, ECC_P256_SIZE_BYTES); + ecc_be_to_le(ecc_p256_mul_res_y, y_mul_le, ECC_P256_SIZE_BYTES); - ESP_LOG_BUFFER_HEXDUMP("Expected X:", x_mul_le, 32, ESP_LOG_DEBUG); - ESP_LOG_BUFFER_HEXDUMP("Got X:", x_res_le, 32, ESP_LOG_DEBUG); + ESP_LOG_BUFFER_HEXDUMP("Expected X:", x_mul_le, ECC_P256_SIZE_BYTES, ESP_LOG_DEBUG); + ESP_LOG_BUFFER_HEXDUMP("Got X:", x_res_le, ECC_P256_SIZE_BYTES, ESP_LOG_DEBUG); - ESP_LOG_BUFFER_HEXDUMP("Expected Y:", y_mul_le, 32, ESP_LOG_DEBUG); - ESP_LOG_BUFFER_HEXDUMP("Got Y:", y_res_le, 32, ESP_LOG_DEBUG); + ESP_LOG_BUFFER_HEXDUMP("Expected Y:", y_mul_le, ECC_P256_SIZE_BYTES, ESP_LOG_DEBUG); + ESP_LOG_BUFFER_HEXDUMP("Got Y:", y_res_le, ECC_P256_SIZE_BYTES, ESP_LOG_DEBUG); - TEST_ASSERT_EQUAL_MEMORY_MESSAGE(x_mul_le, x_res_le, 32, "X coordinate of P256 point multiplication "); - TEST_ASSERT_EQUAL_MEMORY_MESSAGE(y_mul_le, y_res_le, 32, "Y coordinate of P256 point multiplication "); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(x_mul_le, x_res_le, ECC_P256_SIZE_BYTES, "X coordinate of P256 point multiplication "); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(y_mul_le, y_res_le, ECC_P256_SIZE_BYTES, "Y coordinate of P256 point multiplication "); - memset(x_res_le, 0x0, 32); - memset(y_res_le, 0x0, 32); - memset(x_mul_le, 0x0, 32); - memset(y_mul_le, 0x0, 32); + memset(x_res_le, 0x0, ECC_MAX_BUFFER_SIZE); + memset(y_res_le, 0x0, ECC_MAX_BUFFER_SIZE); + memset(x_mul_le, 0x0, ECC_MAX_BUFFER_SIZE); + memset(y_mul_le, 0x0, ECC_MAX_BUFFER_SIZE); /* P192 */ - ecc_be_to_le(ecc_p192_scalar, scalar_le, 24); - ecc_be_to_le(ecc_p192_point_x, x_le, 24); - ecc_be_to_le(ecc_p192_point_y, y_le, 24); + ecc_be_to_le(ecc_p192_scalar, scalar_le, ECC_P192_SIZE_BYTES); + ecc_be_to_le(ecc_p192_point_x, x_le, ECC_P192_SIZE_BYTES); + ecc_be_to_le(ecc_p192_point_y, y_le, ECC_P192_SIZE_BYTES); - ecc_point_mul(scalar_le, x_le, y_le, 24, verify_first, x_res_le, y_res_le); + ecc_point_mul(scalar_le, x_le, y_le, ECC_P192_SIZE_BYTES, verify_first, x_res_le, y_res_le); - ecc_be_to_le(ecc_p192_mul_res_x, x_mul_le, 24); - ecc_be_to_le(ecc_p192_mul_res_y, y_mul_le, 24); + ecc_be_to_le(ecc_p192_mul_res_x, x_mul_le, ECC_P192_SIZE_BYTES); + ecc_be_to_le(ecc_p192_mul_res_y, y_mul_le, ECC_P192_SIZE_BYTES); - ESP_LOG_BUFFER_HEXDUMP("Expected X:", x_mul_le, 32, ESP_LOG_DEBUG); - ESP_LOG_BUFFER_HEXDUMP("Got X:", x_res_le, 32, ESP_LOG_DEBUG); + ESP_LOG_BUFFER_HEXDUMP("Expected X:", x_mul_le, ECC_P256_SIZE_BYTES, ESP_LOG_DEBUG); + ESP_LOG_BUFFER_HEXDUMP("Got X:", x_res_le, ECC_P256_SIZE_BYTES, ESP_LOG_DEBUG); - ESP_LOG_BUFFER_HEXDUMP("Expected Y:", y_mul_le, 32, ESP_LOG_DEBUG); - ESP_LOG_BUFFER_HEXDUMP("Got Y:", y_res_le, 32, ESP_LOG_DEBUG); + ESP_LOG_BUFFER_HEXDUMP("Expected Y:", y_mul_le, ECC_P256_SIZE_BYTES, ESP_LOG_DEBUG); + ESP_LOG_BUFFER_HEXDUMP("Got Y:", y_res_le, ECC_P256_SIZE_BYTES, ESP_LOG_DEBUG); - TEST_ASSERT_EQUAL_MEMORY_MESSAGE(x_mul_le, x_res_le, 24, "X coordinate of P192 point multiplication "); - TEST_ASSERT_EQUAL_MEMORY_MESSAGE(y_mul_le, y_res_le, 24, "Y coordinate of P192 point multiplication "); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(x_mul_le, x_res_le, ECC_P192_SIZE_BYTES, "X coordinate of P192 point multiplication "); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(y_mul_le, y_res_le, ECC_P192_SIZE_BYTES, "Y coordinate of P192 point multiplication "); + +#if SOC_ECC_SUPPORT_CURVE_P384 + if (ecc_ll_is_p384_curve_operations_supported()) { + memset(x_res_le, 0x0, ECC_MAX_BUFFER_SIZE); + memset(y_res_le, 0x0, ECC_MAX_BUFFER_SIZE); + memset(x_mul_le, 0x0, ECC_MAX_BUFFER_SIZE); + memset(y_mul_le, 0x0, ECC_MAX_BUFFER_SIZE); + + /* P384 */ + ecc_be_to_le(ecc_p384_scalar, scalar_le, ECC_P384_SIZE_BYTES); + ecc_be_to_le(ecc_p384_point_x, x_le, ECC_P384_SIZE_BYTES); + ecc_be_to_le(ecc_p384_point_y, y_le, ECC_P384_SIZE_BYTES); + + ecc_point_mul(scalar_le, x_le, y_le, ECC_P384_SIZE_BYTES, verify_first, x_res_le, y_res_le); + + ecc_be_to_le(ecc_p384_mul_res_x, x_mul_le, ECC_P384_SIZE_BYTES); + ecc_be_to_le(ecc_p384_mul_res_y, y_mul_le, ECC_P384_SIZE_BYTES); + + ESP_LOG_BUFFER_HEXDUMP("Expected Result X:", x_mul_le, ECC_P384_SIZE_BYTES, ESP_LOG_DEBUG); + ESP_LOG_BUFFER_HEXDUMP("Got Result X:", x_res_le, ECC_P384_SIZE_BYTES, ESP_LOG_DEBUG); + + ESP_LOG_BUFFER_HEXDUMP("Expected Result Y:", y_mul_le, ECC_P384_SIZE_BYTES, ESP_LOG_DEBUG); + ESP_LOG_BUFFER_HEXDUMP("Got Result Y:", y_res_le, ECC_P384_SIZE_BYTES, ESP_LOG_DEBUG); + + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(x_mul_le, x_res_le, ECC_P384_SIZE_BYTES, "X coordinate of P384 point multiplication "); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(y_mul_le, y_res_le, ECC_P384_SIZE_BYTES, "Y coordinate of P384 point multiplication "); + } +#endif /* SOC_ECC_SUPPORT_CURVE_P384 */ } -TEST(ecc, ecc_point_multiplication_on_SECP192R1_and_SECP256R1) +TEST(ecc, ecc_point_multiplication_on_SECP192R1_SECP256R1_SECP384R1) { test_ecc_point_mul_inner(false); } @@ -153,17 +190,17 @@ static void test_ecc_point_mul_inner_constant_time(void) return; } #endif - uint8_t scalar_le[32]; - uint8_t x_le[32]; - uint8_t y_le[32]; + uint8_t scalar_le[ECC_MAX_BUFFER_SIZE]; + uint8_t x_le[ECC_MAX_BUFFER_SIZE]; + uint8_t y_le[ECC_MAX_BUFFER_SIZE]; /* P256 */ - ecc_be_to_le(ecc_p256_scalar, scalar_le, 32); - ecc_be_to_le(ecc_p256_point_x, x_le, 32); - ecc_be_to_le(ecc_p256_point_y, y_le, 32); + ecc_be_to_le(ecc_p256_scalar, scalar_le, ECC_P256_SIZE_BYTES); + ecc_be_to_le(ecc_p256_point_x, x_le, ECC_P256_SIZE_BYTES); + ecc_be_to_le(ecc_p256_point_y, y_le, ECC_P256_SIZE_BYTES); - uint8_t x_res_le[32]; - uint8_t y_res_le[32]; + uint8_t x_res_le[ECC_MAX_BUFFER_SIZE]; + uint8_t y_res_le[ECC_MAX_BUFFER_SIZE]; double deviation = 0; uint32_t elapsed_time, mean_elapsed_time, total_elapsed_time = 0; @@ -172,7 +209,7 @@ static void test_ecc_point_mul_inner_constant_time(void) for (int i = 0; i < loop_count; i++) { ccomp_timer_start(); - ecc_point_mul(scalar_le, x_le, y_le, 32, 0, x_res_le, y_res_le); + ecc_point_mul(scalar_le, x_le, y_le, ECC_P256_SIZE_BYTES, 0, x_res_le, y_res_le); elapsed_time = ccomp_timer_stop(); max_time = MAX(elapsed_time, max_time); @@ -185,9 +222,9 @@ static void test_ecc_point_mul_inner_constant_time(void) TEST_ASSERT_LESS_THAN_DOUBLE(CONST_TIME_DEVIATION_PERCENT, deviation); /* P192 */ - ecc_be_to_le(ecc_p192_scalar, scalar_le, 24); - ecc_be_to_le(ecc_p192_point_x, x_le, 24); - ecc_be_to_le(ecc_p192_point_y, y_le, 24); + ecc_be_to_le(ecc_p192_scalar, scalar_le, ECC_P192_SIZE_BYTES); + ecc_be_to_le(ecc_p192_point_x, x_le, ECC_P192_SIZE_BYTES); + ecc_be_to_le(ecc_p192_point_y, y_le, ECC_P192_SIZE_BYTES); max_time = 0; min_time = UINT32_MAX; @@ -195,7 +232,7 @@ static void test_ecc_point_mul_inner_constant_time(void) for (int i = 0; i < loop_count; i++) { ccomp_timer_start(); - ecc_point_mul(scalar_le, x_le, y_le, 24, 0, x_res_le, y_res_le); + ecc_point_mul(scalar_le, x_le, y_le, ECC_P192_SIZE_BYTES, 0, x_res_le, y_res_le); elapsed_time = ccomp_timer_stop(); max_time = MAX(elapsed_time, max_time); @@ -206,9 +243,36 @@ static void test_ecc_point_mul_inner_constant_time(void) deviation = ((double)(max_time - mean_elapsed_time) / mean_elapsed_time); TEST_ASSERT_LESS_THAN_DOUBLE(CONST_TIME_DEVIATION_PERCENT, deviation); + +#if SOC_ECC_SUPPORT_CURVE_P384 + if (ecc_ll_is_p384_curve_operations_supported()) { + /* P384 */ + ecc_be_to_le(ecc_p384_scalar, scalar_le, ECC_P384_SIZE_BYTES); + ecc_be_to_le(ecc_p384_point_x, x_le, ECC_P384_SIZE_BYTES); + ecc_be_to_le(ecc_p384_point_y, y_le, ECC_P384_SIZE_BYTES); + + max_time = 0; + min_time = UINT32_MAX; + total_elapsed_time = 0; + + for (int i = 0; i < loop_count; i++) { + ccomp_timer_start(); + ecc_point_mul(scalar_le, x_le, y_le, ECC_P384_SIZE_BYTES, 0, x_res_le, y_res_le); + elapsed_time = ccomp_timer_stop(); + + max_time = MAX(elapsed_time, max_time); + min_time = MIN(elapsed_time, min_time); + total_elapsed_time += elapsed_time; + } + mean_elapsed_time = total_elapsed_time / loop_count; + deviation = ((double)(max_time - mean_elapsed_time) / mean_elapsed_time); + + TEST_ASSERT_LESS_THAN_DOUBLE(CONST_TIME_DEVIATION_PERCENT, deviation); + } +#endif /* SOC_ECC_SUPPORT_CURVE_P384 */ } -TEST(ecc, ecc_point_multiplication_const_time_check_on_SECP192R1_and_SECP256R1) +TEST(ecc, ecc_point_multiplication_const_time_check_on_SECP192R1_SECP256R1_SECP384R1) { test_ecc_point_mul_inner_constant_time(); } @@ -235,42 +299,59 @@ static int ecc_point_verify(const uint8_t *x_le, const uint8_t *y_le, uint8_t le return ret; } -TEST(ecc, ecc_point_verification_on_SECP192R1_and_SECP256R1) +TEST(ecc, ecc_point_verification_on_SECP192R1_SECP256R1_SECP384R1) { int res; - uint8_t x_le[32]; - uint8_t y_le[32]; + uint8_t x_le[ECC_MAX_BUFFER_SIZE]; + uint8_t y_le[ECC_MAX_BUFFER_SIZE]; /* P256 */ - ecc_be_to_le(ecc_p256_point_x, x_le, 32); - ecc_be_to_le(ecc_p256_point_y, y_le, 32); + ecc_be_to_le(ecc_p256_point_x, x_le, ECC_P256_SIZE_BYTES); + ecc_be_to_le(ecc_p256_point_y, y_le, ECC_P256_SIZE_BYTES); // Case 1: Correct point on curve - res = ecc_point_verify(x_le, y_le, 32); + res = ecc_point_verify(x_le, y_le, ECC_P256_SIZE_BYTES); TEST_ASSERT_EQUAL(1, res); // Case 2: Modify one byte from the point x_le[6] = x_le[6] ^ 0xFF; - res = ecc_point_verify(x_le, y_le, 32); + res = ecc_point_verify(x_le, y_le, ECC_P256_SIZE_BYTES); TEST_ASSERT_EQUAL(0, res); /* P192 */ - ecc_be_to_le(ecc_p192_point_x, x_le, 24); - ecc_be_to_le(ecc_p192_point_y, y_le, 24); + ecc_be_to_le(ecc_p192_point_x, x_le, ECC_P192_SIZE_BYTES); + ecc_be_to_le(ecc_p192_point_y, y_le, ECC_P192_SIZE_BYTES); // Case 1: Correct point on curve - res = ecc_point_verify(x_le, y_le, 24); + res = ecc_point_verify(x_le, y_le, ECC_P192_SIZE_BYTES); TEST_ASSERT_EQUAL(1, res); // Case 2: Modify one byte from the point x_le[6] = x_le[6] ^ 0xFF; - res = ecc_point_verify(x_le, y_le, 24); + res = ecc_point_verify(x_le, y_le, ECC_P192_SIZE_BYTES); TEST_ASSERT_EQUAL(0, res); + +#if SOC_ECC_SUPPORT_CURVE_P384 + if (ecc_ll_is_p384_curve_operations_supported()) { + /* P384 */ + ecc_be_to_le(ecc_p384_point_x, x_le, ECC_P384_SIZE_BYTES); + ecc_be_to_le(ecc_p384_point_y, y_le, ECC_P384_SIZE_BYTES); + + // Case 1: Correct point on curve + res = ecc_point_verify(x_le, y_le, ECC_P384_SIZE_BYTES); + TEST_ASSERT_EQUAL(1, res); + + // Case 2: Modify one byte from the point + x_le[6] = x_le[6] ^ 0xFF; + res = ecc_point_verify(x_le, y_le, ECC_P384_SIZE_BYTES); + TEST_ASSERT_EQUAL(0, res); + } +#endif /* SOC_ECC_SUPPORT_CURVE_P384 */ } #endif #if SOC_ECC_SUPPORT_POINT_MULT && SOC_ECC_SUPPORT_POINT_VERIFY && !defined(SOC_ECC_SUPPORT_POINT_VERIFY_QUIRK) -TEST(ecc, ecc_point_verification_and_multiplication_on_SECP192R1_and_SECP256R1) +TEST(ecc, ecc_point_verification_and_multiplication_on_SECP192R1_SECP256R1_SECP384R1) { test_ecc_point_mul_inner(true); } @@ -281,7 +362,7 @@ static void ecc_point_inv_mul(const uint8_t *num_le, const uint8_t *deno_le, uin { esp_crypto_ecc_enable_periph_clk(true); - uint8_t zero[32] = {0}; + uint8_t zero[ECC_MAX_BUFFER_SIZE] = {0}; ecc_hal_write_mul_param(zero, num_le, deno_le, len); ecc_hal_set_mode(ECC_MODE_INVERSE_MUL); @@ -296,14 +377,24 @@ static void ecc_point_inv_mul(const uint8_t *num_le, const uint8_t *deno_le, uin esp_crypto_ecc_enable_periph_clk(false); } -TEST(ecc, ecc_inverse_multiplication_or_mod_division_using_SECP192R1_and_SECP256R1_order_of_curve) +TEST(ecc, ecc_inverse_multiplication_or_mod_division_using_SECP192R1_SECP256R1_SECP384R1_order_of_curve) { - uint8_t res[32] = {0}; - ecc_point_inv_mul(ecc256_num, ecc256_den, 32, res); - TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc256_inv_mul_res, res, 32, "P256 Inverse multiplication (or Mod division)"); + uint8_t res[ECC_MAX_BUFFER_SIZE] = {0}; + ecc_point_inv_mul(ecc256_num, ecc256_den, ECC_P256_SIZE_BYTES, res); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc256_inv_mul_res, res, ECC_P256_SIZE_BYTES, "P256 Inverse multiplication (or Mod division)"); - ecc_point_inv_mul(ecc192_num, ecc192_den, 24, res); - TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc192_inv_mul_res, res, 24, "P192 Inverse multiplication (or Mod division)"); + ecc_point_inv_mul(ecc192_num, ecc192_den, ECC_P192_SIZE_BYTES, res); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc192_inv_mul_res, res, ECC_P192_SIZE_BYTES, "P192 Inverse multiplication (or Mod division)"); + +#if SOC_ECC_SUPPORT_CURVE_P384 + if (ecc_ll_is_p384_curve_operations_supported()) { + ecc_point_inv_mul(ecc384_num, ecc384_den, ECC_P384_SIZE_BYTES, res); + ESP_LOG_BUFFER_HEXDUMP("Expected Result X:", ecc384_inv_mul_res, ECC_P384_SIZE_BYTES, ESP_LOG_DEBUG); + ESP_LOG_BUFFER_HEXDUMP("Got Result X:", res, ECC_P384_SIZE_BYTES, ESP_LOG_DEBUG); + + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc384_inv_mul_res, res, ECC_P384_SIZE_BYTES, "P384 Inverse multiplication (or Mod division)"); + } +#endif /* SOC_ECC_SUPPORT_CURVE_P384 */ } #endif @@ -331,42 +422,61 @@ static void ecc_jacob_mul(uint8_t *k_le, uint8_t *x_le, uint8_t *y_le, uint8_t l static void test_ecc_jacob_mul_inner(bool verify_first) { - uint8_t scalar_le[32]; - uint8_t x_le[32]; - uint8_t y_le[32]; + uint8_t scalar_le[ECC_MAX_BUFFER_SIZE]; + uint8_t x_le[ECC_MAX_BUFFER_SIZE]; + uint8_t y_le[ECC_MAX_BUFFER_SIZE]; /* P256 */ - ecc_be_to_le(ecc_p256_scalar, scalar_le, 32); - ecc_be_to_le(ecc_p256_point_x, x_le, 32); - ecc_be_to_le(ecc_p256_point_y, y_le, 32); + ecc_be_to_le(ecc_p256_scalar, scalar_le, ECC_P256_SIZE_BYTES); + ecc_be_to_le(ecc_p256_point_x, x_le, ECC_P256_SIZE_BYTES); + ecc_be_to_le(ecc_p256_point_y, y_le, ECC_P256_SIZE_BYTES); - uint8_t x_res_le[32]; - uint8_t y_res_le[32]; - uint8_t z_res_le[32]; + uint8_t x_res_le[ECC_MAX_BUFFER_SIZE]; + uint8_t y_res_le[ECC_MAX_BUFFER_SIZE]; + uint8_t z_res_le[ECC_MAX_BUFFER_SIZE]; - ecc_jacob_mul(scalar_le, x_le, y_le, 32, verify_first, x_res_le, y_res_le, z_res_le); + ecc_jacob_mul(scalar_le, x_le, y_le, ECC_P256_SIZE_BYTES, verify_first, x_res_le, y_res_le, z_res_le); - TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc_p256_jacob_mul_res_x_le, x_res_le, 32, "X coordinate of P256 point jacobian multiplication "); - TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc_p256_jacob_mul_res_y_le, y_res_le, 32, "Y coordinate of P256 point jacobian multiplication "); - TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc_p256_jacob_mul_res_z_le, z_res_le, 32, "Z coordinate of P256 point jacobian multiplication "); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc_p256_jacob_mul_res_x_le, x_res_le, ECC_P256_SIZE_BYTES, "X coordinate of P256 point jacobian multiplication "); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc_p256_jacob_mul_res_y_le, y_res_le, ECC_P256_SIZE_BYTES, "Y coordinate of P256 point jacobian multiplication "); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc_p256_jacob_mul_res_z_le, z_res_le, ECC_P256_SIZE_BYTES, "Z coordinate of P256 point jacobian multiplication "); - memset(x_res_le, 0x0, 32); - memset(y_res_le, 0x0, 32); - memset(z_res_le, 0x0, 32); + memset(x_res_le, 0x0, ECC_MAX_BUFFER_SIZE); + memset(y_res_le, 0x0, ECC_MAX_BUFFER_SIZE); + memset(z_res_le, 0x0, ECC_MAX_BUFFER_SIZE); /* P192 */ - ecc_be_to_le(ecc_p192_scalar, scalar_le, 24); - ecc_be_to_le(ecc_p192_point_x, x_le, 24); - ecc_be_to_le(ecc_p192_point_y, y_le, 24); + ecc_be_to_le(ecc_p192_scalar, scalar_le, ECC_P192_SIZE_BYTES); + ecc_be_to_le(ecc_p192_point_x, x_le, ECC_P192_SIZE_BYTES); + ecc_be_to_le(ecc_p192_point_y, y_le, ECC_P192_SIZE_BYTES); - ecc_jacob_mul(scalar_le, x_le, y_le, 24, verify_first, x_res_le, y_res_le, z_res_le); + ecc_jacob_mul(scalar_le, x_le, y_le, ECC_P192_SIZE_BYTES, verify_first, x_res_le, y_res_le, z_res_le); - TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc_p192_jacob_mul_res_x_le, x_res_le, 24, "X coordinate of P192 point jacobian multiplication "); - TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc_p192_jacob_mul_res_y_le, y_res_le, 24, "Y coordinate of P192 point jacobian multiplication "); - TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc_p192_jacob_mul_res_z_le, z_res_le, 24, "Z coordinate of P192 point jacobian multiplication "); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc_p192_jacob_mul_res_x_le, x_res_le, ECC_P192_SIZE_BYTES, "X coordinate of P192 point jacobian multiplication "); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc_p192_jacob_mul_res_y_le, y_res_le, ECC_P192_SIZE_BYTES, "Y coordinate of P192 point jacobian multiplication "); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc_p192_jacob_mul_res_z_le, z_res_le, ECC_P192_SIZE_BYTES, "Z coordinate of P192 point jacobian multiplication "); + +#if SOC_ECC_SUPPORT_CURVE_P384 + if (ecc_ll_is_p384_curve_operations_supported()) { + memset(x_res_le, 0x0, ECC_MAX_BUFFER_SIZE); + memset(y_res_le, 0x0, ECC_MAX_BUFFER_SIZE); + memset(z_res_le, 0x0, ECC_MAX_BUFFER_SIZE); + + /* P384 */ + ecc_be_to_le(ecc_p384_scalar, scalar_le, ECC_P384_SIZE_BYTES); + ecc_be_to_le(ecc_p384_point_x, x_le, ECC_P384_SIZE_BYTES); + ecc_be_to_le(ecc_p384_point_y, y_le, ECC_P384_SIZE_BYTES); + + ecc_jacob_mul(scalar_le, x_le, y_le, ECC_P384_SIZE_BYTES, verify_first, x_res_le, y_res_le, z_res_le); + + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc_p384_jacob_mul_res_x_le, x_res_le, ECC_P384_SIZE_BYTES, "X coordinate of P384 point jacobian multiplication "); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc_p384_jacob_mul_res_y_le, y_res_le, ECC_P384_SIZE_BYTES, "Y coordinate of P384 point jacobian multiplication "); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc_p384_jacob_mul_res_z_le, z_res_le, ECC_P384_SIZE_BYTES, "Z coordinate of P384 point jacobian multiplication "); + } +#endif /* SOC_ECC_SUPPORT_CURVE_P384 */ } -TEST(ecc, ecc_jacobian_point_multiplication_on_SECP192R1_and_SECP256R1) +TEST(ecc, ecc_jacobian_point_multiplication_on_SECP192R1_SECP256R1_SECP384R1) { test_ecc_jacob_mul_inner(false); } @@ -393,21 +503,29 @@ static int ecc_jacob_verify(const uint8_t *x_le, const uint8_t *y_le, const uint return ret; } -TEST(ecc, ecc_jacobian_point_verification_on_SECP192R1_and_SECP256R1) +TEST(ecc, ecc_jacobian_point_verification_on_SECP192R1_SECP256R1_SECP384R1) { int res; /* P256 */ - res = ecc_jacob_verify(ecc_p256_jacob_mul_res_x_le, ecc_p256_jacob_mul_res_y_le, ecc_p256_jacob_mul_res_z_le, 32); + res = ecc_jacob_verify(ecc_p256_jacob_mul_res_x_le, ecc_p256_jacob_mul_res_y_le, ecc_p256_jacob_mul_res_z_le, ECC_P256_SIZE_BYTES); TEST_ASSERT_EQUAL(1, res); /* P192 */ - res = ecc_jacob_verify(ecc_p192_jacob_mul_res_x_le, ecc_p192_jacob_mul_res_y_le, ecc_p192_jacob_mul_res_z_le, 24); + res = ecc_jacob_verify(ecc_p192_jacob_mul_res_x_le, ecc_p192_jacob_mul_res_y_le, ecc_p192_jacob_mul_res_z_le, ECC_P192_SIZE_BYTES); TEST_ASSERT_EQUAL(1, res); + +#if SOC_ECC_SUPPORT_CURVE_P384 + if (ecc_ll_is_p384_curve_operations_supported()) { + /* P384 */ + res = ecc_jacob_verify(ecc_p384_jacob_mul_res_x_le, ecc_p384_jacob_mul_res_y_le, ecc_p384_jacob_mul_res_z_le, ECC_P384_SIZE_BYTES); + TEST_ASSERT_EQUAL(1, res); + } +#endif /* SOC_ECC_SUPPORT_CURVE_P384 */ } #endif #if SOC_ECC_SUPPORT_JACOB_POINT_MULT && SOC_ECC_SUPPORT_JACOB_POINT_VERIFY -TEST(ecc, ecc_point_verification_and_jacobian_point_multiplication_on_SECP192R1_and_SECP256R1) +TEST(ecc, ecc_point_verification_and_jacobian_point_multiplication_on_SECP192R1_SECP256R1_SECP384R1) { test_ecc_jacob_mul_inner(true); } @@ -434,56 +552,78 @@ static void ecc_point_addition(uint8_t *px_le, uint8_t *py_le, uint8_t *qx_le, u esp_crypto_ecc_enable_periph_clk(false); } -TEST(ecc, ecc_point_addition_on_SECP192R1_and_SECP256R1) +TEST(ecc, ecc_point_addition_on_SECP192R1_SECP256R1_SECP384R1) { - uint8_t scalar_le[32] = {0}; - uint8_t x_le[32] = {0}; - uint8_t y_le[32] = {0}; - uint8_t z_le[32] = {0}; + uint8_t scalar_le[ECC_MAX_BUFFER_SIZE] = {0}; + uint8_t x_le[ECC_MAX_BUFFER_SIZE] = {0}; + uint8_t y_le[ECC_MAX_BUFFER_SIZE] = {0}; + uint8_t z_le[ECC_MAX_BUFFER_SIZE] = {0}; /* P256 * R = 2 * P */ - ecc_be_to_le(ecc_p256_point_x, x_le, 32); - ecc_be_to_le(ecc_p256_point_y, y_le, 32); + ecc_be_to_le(ecc_p256_point_x, x_le, ECC_P256_SIZE_BYTES); + ecc_be_to_le(ecc_p256_point_y, y_le, ECC_P256_SIZE_BYTES); scalar_le[0] = 0x2; - uint8_t x_res_le[32]; - uint8_t y_res_le[32]; - uint8_t z_res_le[32]; + uint8_t x_res_le[ECC_MAX_BUFFER_SIZE]; + uint8_t y_res_le[ECC_MAX_BUFFER_SIZE]; + uint8_t z_res_le[ECC_MAX_BUFFER_SIZE]; - ecc_jacob_mul(scalar_le, x_le, y_le, 32, 0, x_res_le, y_res_le, z_res_le); + ecc_jacob_mul(scalar_le, x_le, y_le, ECC_P256_SIZE_BYTES, 0, x_res_le, y_res_le, z_res_le); - uint8_t x_add_le[32]; - uint8_t y_add_le[32]; - uint8_t z_add_le[32]; + uint8_t x_add_le[ECC_MAX_BUFFER_SIZE]; + uint8_t y_add_le[ECC_MAX_BUFFER_SIZE]; + uint8_t z_add_le[ECC_MAX_BUFFER_SIZE]; z_le[0] = 0x1; - ecc_point_addition(x_le, y_le, x_le, y_le, z_le, 32, 1, x_add_le, y_add_le, z_add_le); + ecc_point_addition(x_le, y_le, x_le, y_le, z_le, ECC_P256_SIZE_BYTES, 1, x_add_le, y_add_le, z_add_le); - TEST_ASSERT_EQUAL_MEMORY_MESSAGE(x_add_le, x_res_le, 32, "X coordinate of P256 point addition"); - TEST_ASSERT_EQUAL_MEMORY_MESSAGE(y_add_le, y_res_le, 32, "Y coordinate of P256 point addition"); - TEST_ASSERT_EQUAL_MEMORY_MESSAGE(z_add_le, z_res_le, 32, "Z coordinate of P256 point addition"); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(x_add_le, x_res_le, ECC_P256_SIZE_BYTES, "X coordinate of P256 point addition"); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(y_add_le, y_res_le, ECC_P256_SIZE_BYTES, "Y coordinate of P256 point addition"); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(z_add_le, z_res_le, ECC_P256_SIZE_BYTES, "Z coordinate of P256 point addition"); /* P192 * R = 2 * P */ - ecc_be_to_le(ecc_p192_point_x, x_le, 24); - ecc_be_to_le(ecc_p192_point_y, y_le, 24); + ecc_be_to_le(ecc_p192_point_x, x_le, ECC_P192_SIZE_BYTES); + ecc_be_to_le(ecc_p192_point_y, y_le, ECC_P192_SIZE_BYTES); scalar_le[0] = 0x2; - ecc_jacob_mul(scalar_le, x_le, y_le, 24, 0, x_res_le, y_res_le, z_res_le); + ecc_jacob_mul(scalar_le, x_le, y_le, ECC_P192_SIZE_BYTES, 0, x_res_le, y_res_le, z_res_le); z_le[0] = 0x1; - ecc_point_addition(x_le, y_le, x_le, y_le, z_le, 24, 1, x_add_le, y_add_le, z_add_le); + ecc_point_addition(x_le, y_le, x_le, y_le, z_le, ECC_P192_SIZE_BYTES, 1, x_add_le, y_add_le, z_add_le); - TEST_ASSERT_EQUAL_MEMORY_MESSAGE(x_add_le, x_res_le, 24, "X coordinate of P192 point addition"); - TEST_ASSERT_EQUAL_MEMORY_MESSAGE(y_add_le, y_res_le, 24, "Y coordinate of P192 point addition"); - TEST_ASSERT_EQUAL_MEMORY_MESSAGE(z_add_le, z_res_le, 24, "Z coordinate of P192 point addition"); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(x_add_le, x_res_le, ECC_P192_SIZE_BYTES, "X coordinate of P192 point addition"); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(y_add_le, y_res_le, ECC_P192_SIZE_BYTES, "Y coordinate of P192 point addition"); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(z_add_le, z_res_le, ECC_P192_SIZE_BYTES, "Z coordinate of P192 point addition"); + +#if SOC_ECC_SUPPORT_CURVE_P384 + if (ecc_ll_is_p384_curve_operations_supported()) { + /* P384 + * R = 2 * P + */ + ecc_be_to_le(ecc_p384_point_x, x_le, ECC_P384_SIZE_BYTES); + ecc_be_to_le(ecc_p384_point_y, y_le, ECC_P384_SIZE_BYTES); + + scalar_le[0] = 0x2; + + ecc_jacob_mul(scalar_le, x_le, y_le, ECC_P384_SIZE_BYTES, 0, x_res_le, y_res_le, z_res_le); + + z_le[0] = 0x1; + + ecc_point_addition(x_le, y_le, x_le, y_le, z_le, ECC_P384_SIZE_BYTES, 1, x_add_le, y_add_le, z_add_le); + + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(x_add_le, x_res_le, ECC_P384_SIZE_BYTES, "X coordinate of P384 point addition"); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(y_add_le, y_res_le, ECC_P384_SIZE_BYTES, "Y coordinate of P384 point addition"); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(z_add_le, z_res_le, ECC_P384_SIZE_BYTES, "Z coordinate of P384 point addition"); + } +#endif /* SOC_ECC_SUPPORT_CURVE_P384 */ } #endif @@ -508,87 +648,109 @@ static void ecc_mod_op(ecc_mode_t mode, const uint8_t *a, const uint8_t *b, uint #endif #if SOC_ECC_SUPPORT_MOD_ADD -TEST(ecc, ecc_mod_addition_using_SECP192R1_and_SECP256R1_order_of_curve) +TEST(ecc, ecc_mod_addition_using_SECP192R1_SECP256R1_SECP384R1_order_of_curve) { - uint8_t res[32] = {0}; - ecc_mod_op(ECC_MODE_MOD_ADD, ecc256_x, ecc256_y, 32, res); - TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc256_add_res, res, 32, "P256 mod addition"); + uint8_t res[ECC_MAX_BUFFER_SIZE] = {0}; + ecc_mod_op(ECC_MODE_MOD_ADD, ecc256_x, ecc256_y, ECC_P256_SIZE_BYTES, res); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc256_add_res, res, ECC_P256_SIZE_BYTES, "P256 mod addition"); - ecc_mod_op(ECC_MODE_MOD_ADD, ecc192_x, ecc192_y, 24, res); - TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc192_add_res, res, 24, "P192 mod addition"); + ecc_mod_op(ECC_MODE_MOD_ADD, ecc192_x, ecc192_y, ECC_P192_SIZE_BYTES, res); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc192_add_res, res, ECC_P192_SIZE_BYTES, "P192 mod addition"); + +#if SOC_ECC_SUPPORT_CURVE_P384 + if (ecc_ll_is_p384_curve_operations_supported()) { + ecc_mod_op(ECC_MODE_MOD_ADD, ecc384_x, ecc384_y, ECC_P384_SIZE_BYTES, res); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc384_add_res, res, ECC_P384_SIZE_BYTES, "P384 mod addition"); + } +#endif /* SOC_ECC_SUPPORT_CURVE_P384 */ } #endif #if SOC_ECC_SUPPORT_MOD_SUB -TEST(ecc, ecc_mod_subtraction_using_SECP192R1_and_SECP256R1_order_of_curve) +TEST(ecc, ecc_mod_subtraction_using_SECP192R1_SECP256R1_SECP384R1_order_of_curve) { - uint8_t res[32] = {0}; - ecc_mod_op(ECC_MODE_MOD_SUB, ecc256_x, ecc256_y, 32, res); - TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc256_sub_res, res, 32, "P256 mod subtraction"); + uint8_t res[ECC_MAX_BUFFER_SIZE] = {0}; + ecc_mod_op(ECC_MODE_MOD_SUB, ecc256_x, ecc256_y, ECC_P256_SIZE_BYTES, res); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc256_sub_res, res, ECC_P256_SIZE_BYTES, "P256 mod subtraction"); - ecc_mod_op(ECC_MODE_MOD_SUB, ecc192_x, ecc192_y, 24, res); - TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc192_sub_res, res, 24, "P192 mod subtraction"); + ecc_mod_op(ECC_MODE_MOD_SUB, ecc192_x, ecc192_y, ECC_P192_SIZE_BYTES, res); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc192_sub_res, res, ECC_P192_SIZE_BYTES, "P192 mod subtraction"); + +#if SOC_ECC_SUPPORT_CURVE_P384 + if (ecc_ll_is_p384_curve_operations_supported()) { + ecc_mod_op(ECC_MODE_MOD_SUB, ecc384_x, ecc384_y, ECC_P384_SIZE_BYTES, res); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc384_sub_res, res, ECC_P384_SIZE_BYTES, "P384 mod subtraction"); + } +#endif /* SOC_ECC_SUPPORT_CURVE_P384 */ } #endif #if SOC_ECC_SUPPORT_MOD_MUL -TEST(ecc, ecc_mod_multiplication_using_SECP192R1_and_SECP256R1_order_of_curve) +TEST(ecc, ecc_mod_multiplication_using_SECP192R1_SECP256R1_SECP384R1_order_of_curve) { - uint8_t res[32] = {0}; - ecc_mod_op(ECC_MODE_MOD_MUL, ecc256_x, ecc256_y, 32, res); - TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc256_mul_res, res, 32, "P256 mod multiplication"); + uint8_t res[ECC_MAX_BUFFER_SIZE] = {0}; + ecc_mod_op(ECC_MODE_MOD_MUL, ecc256_x, ecc256_y, ECC_P256_SIZE_BYTES, res); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc256_mul_res, res, ECC_P256_SIZE_BYTES, "P256 mod multiplication"); - ecc_mod_op(ECC_MODE_MOD_MUL, ecc192_x, ecc192_y, 24, res); - TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc192_mul_res, res, 24, "P192 mod multiplication"); + ecc_mod_op(ECC_MODE_MOD_MUL, ecc192_x, ecc192_y, ECC_P192_SIZE_BYTES, res); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc192_mul_res, res, ECC_P192_SIZE_BYTES, "P192 mod multiplication"); + +#if SOC_ECC_SUPPORT_CURVE_P384 + if (ecc_ll_is_p384_curve_operations_supported()) { + ecc_mod_op(ECC_MODE_MOD_MUL, ecc384_x, ecc384_y, ECC_P384_SIZE_BYTES, res); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc384_mul_res, res, ECC_P384_SIZE_BYTES, "P384 mod multiplication"); + } +#endif /* SOC_ECC_SUPPORT_CURVE_P384 */ } #endif + TEST_GROUP_RUNNER(ecc) { #if SOC_ECC_SUPPORT_POINT_MULT - RUN_TEST_CASE(ecc, ecc_point_multiplication_on_SECP192R1_and_SECP256R1); + RUN_TEST_CASE(ecc, ecc_point_multiplication_on_SECP192R1_SECP256R1_SECP384R1); #if SOC_ECC_CONSTANT_TIME_POINT_MUL - RUN_TEST_CASE(ecc, ecc_point_multiplication_const_time_check_on_SECP192R1_and_SECP256R1); + RUN_TEST_CASE(ecc, ecc_point_multiplication_const_time_check_on_SECP192R1_SECP256R1_SECP384R1); #endif #endif #if SOC_ECC_SUPPORT_POINT_VERIFY && !defined(SOC_ECC_SUPPORT_POINT_VERIFY_QUIRK) - RUN_TEST_CASE(ecc, ecc_point_verification_on_SECP192R1_and_SECP256R1); + RUN_TEST_CASE(ecc, ecc_point_verification_on_SECP192R1_SECP256R1_SECP384R1); #endif #if SOC_ECC_SUPPORT_POINT_MULT && SOC_ECC_SUPPORT_POINT_VERIFY && !defined(SOC_ECC_SUPPORT_POINT_VERIFY_QUIRK) - RUN_TEST_CASE(ecc, ecc_point_verification_and_multiplication_on_SECP192R1_and_SECP256R1); + RUN_TEST_CASE(ecc, ecc_point_verification_and_multiplication_on_SECP192R1_SECP256R1_SECP384R1); #endif #if SOC_ECC_SUPPORT_POINT_DIVISION - RUN_TEST_CASE(ecc, ecc_inverse_multiplication_or_mod_division_using_SECP192R1_and_SECP256R1_order_of_curve); + RUN_TEST_CASE(ecc, ecc_inverse_multiplication_or_mod_division_using_SECP192R1_SECP256R1_SECP384R1_order_of_curve); #endif #if SOC_ECC_SUPPORT_JACOB_POINT_MULT - RUN_TEST_CASE(ecc, ecc_jacobian_point_multiplication_on_SECP192R1_and_SECP256R1); + RUN_TEST_CASE(ecc, ecc_jacobian_point_multiplication_on_SECP192R1_SECP256R1_SECP384R1); #endif #if SOC_ECC_SUPPORT_JACOB_POINT_VERIFY - RUN_TEST_CASE(ecc, ecc_jacobian_point_verification_on_SECP192R1_and_SECP256R1); + RUN_TEST_CASE(ecc, ecc_jacobian_point_verification_on_SECP192R1_SECP256R1_SECP384R1); #endif #if SOC_ECC_SUPPORT_JACOB_POINT_MULT && SOC_ECC_SUPPORT_JACOB_POINT_VERIFY - RUN_TEST_CASE(ecc, ecc_point_verification_and_jacobian_point_multiplication_on_SECP192R1_and_SECP256R1); + RUN_TEST_CASE(ecc, ecc_point_verification_and_jacobian_point_multiplication_on_SECP192R1_SECP256R1_SECP384R1); #endif #if SOC_ECC_SUPPORT_POINT_ADDITION - RUN_TEST_CASE(ecc, ecc_point_addition_on_SECP192R1_and_SECP256R1); + RUN_TEST_CASE(ecc, ecc_point_addition_on_SECP192R1_SECP256R1_SECP384R1); #endif #if SOC_ECC_SUPPORT_MOD_ADD - RUN_TEST_CASE(ecc, ecc_mod_addition_using_SECP192R1_and_SECP256R1_order_of_curve); + RUN_TEST_CASE(ecc, ecc_mod_addition_using_SECP192R1_SECP256R1_SECP384R1_order_of_curve); #endif #if SOC_ECC_SUPPORT_MOD_SUB - RUN_TEST_CASE(ecc, ecc_mod_subtraction_using_SECP192R1_and_SECP256R1_order_of_curve); + RUN_TEST_CASE(ecc, ecc_mod_subtraction_using_SECP192R1_SECP256R1_SECP384R1_order_of_curve); #endif #if SOC_ECC_SUPPORT_MOD_MUL - RUN_TEST_CASE(ecc, ecc_mod_multiplication_using_SECP192R1_and_SECP256R1_order_of_curve); + RUN_TEST_CASE(ecc, ecc_mod_multiplication_using_SECP192R1_SECP256R1_SECP384R1_order_of_curve); #endif } diff --git a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in index 9a9cb551b68..7fb99af119f 100644 --- a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in @@ -1043,6 +1043,10 @@ config SOC_ECC_CONSTANT_TIME_POINT_MUL bool default y +config SOC_ECC_SUPPORT_CURVE_P384 + bool + default y + config SOC_ECDSA_SUPPORT_EXPORT_PUBKEY bool default y diff --git a/components/soc/esp32c5/include/soc/soc_caps.h b/components/soc/esp32c5/include/soc/soc_caps.h index fbed2753cb5..676c57fae31 100644 --- a/components/soc/esp32c5/include/soc/soc_caps.h +++ b/components/soc/esp32c5/include/soc/soc_caps.h @@ -420,6 +420,7 @@ /*--------------------------- ECC CAPS ---------------------------------------*/ #define SOC_ECC_CONSTANT_TIME_POINT_MUL 1 +#define SOC_ECC_SUPPORT_CURVE_P384 (1) /*--------------------------- ECDSA CAPS ---------------------------------------*/ #define SOC_ECDSA_SUPPORT_EXPORT_PUBKEY (1) diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index b00533d2c2f..75f7c1b8634 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -1419,6 +1419,10 @@ config SOC_ECC_CONSTANT_TIME_POINT_MUL bool default y +config SOC_ECC_SUPPORT_CURVE_P384 + bool + default y + config SOC_ECDSA_SUPPORT_EXPORT_PUBKEY bool default y diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index cd73c71aa7b..f680473e6ed 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -530,6 +530,7 @@ /*--------------------------- ECC CAPS ---------------------------------------*/ #define SOC_ECC_CONSTANT_TIME_POINT_MUL 1 +#define SOC_ECC_SUPPORT_CURVE_P384 (1) /*--------------------------- ECDSA CAPS ---------------------------------------*/ #define SOC_ECDSA_SUPPORT_EXPORT_PUBKEY (1) From 468ae71bd76075f677c046fa4a5c86c0497deef9 Mon Sep 17 00:00:00 2001 From: morris Date: Thu, 31 Jul 2025 23:51:14 +0800 Subject: [PATCH 016/106] fix(gdma): fixed the race conditon in of gdma resource allocation --- .../test_apps/i2s/main/test_app_main.c | 4 +- components/esp_driver_sdm/src/sdm.c | 6 +- .../test_apps/slave/main/test_app_main.c | 2 +- .../test_apps/slave_hd/main/test_app_main.c | 2 +- components/esp_hw_support/dma/gdma.c | 141 ++++++++++-------- components/esp_hw_support/dma/gdma_priv.h | 5 + .../esp_hw_support/dma/gdma_sleep_retention.c | 78 ++++++---- .../dma/include/esp_private/gdma.h | 44 +++--- .../esp_private/gdma_sleep_retention.h | 40 ----- .../include/esp_private/periph_ctrl.h | 18 +-- 10 files changed, 173 insertions(+), 167 deletions(-) delete mode 100644 components/esp_hw_support/include/esp_private/gdma_sleep_retention.h diff --git a/components/esp_driver_i2s/test_apps/i2s/main/test_app_main.c b/components/esp_driver_i2s/test_apps/i2s/main/test_app_main.c index b49226f5754..9e1f7b5a6ca 100644 --- a/components/esp_driver_i2s/test_apps/i2s/main/test_app_main.c +++ b/components/esp_driver_i2s/test_apps/i2s/main/test_app_main.c @@ -8,8 +8,8 @@ #include "unity_test_runner.h" #include "esp_heap_caps.h" -// Some resources are lazy allocated in I2S driver, the threadhold is left for that case -#define TEST_MEMORY_LEAK_THRESHOLD (-300) +// Some resources are lazy allocated in I2S driver, the threshold is left for that case +#define TEST_MEMORY_LEAK_THRESHOLD (-350) static size_t before_free_8bit; static size_t before_free_32bit; diff --git a/components/esp_driver_sdm/src/sdm.c b/components/esp_driver_sdm/src/sdm.c index 0a233bf100c..1a92e2a85df 100644 --- a/components/esp_driver_sdm/src/sdm.c +++ b/components/esp_driver_sdm/src/sdm.c @@ -162,11 +162,11 @@ static sdm_group_t *sdm_acquire_group_handle(int group_id, sdm_clock_source_t cl ESP_LOGD(TAG, "new group (%d) at %p", group_id, group); #if CONFIG_PM_ENABLE esp_pm_lock_type_t pm_type = ESP_PM_NO_LIGHT_SLEEP; -#if TIMER_LL_FUNC_CLOCK_SUPPORT_APB +#if SDM_LL_FUNC_CLOCK_SUPPORT_APB if (clk_src == SDM_CLK_SRC_APB) { pm_type = ESP_PM_APB_FREQ_MAX; } -#endif // TIMER_LL_FUNC_CLOCK_SUPPORT_APB +#endif // SDM_LL_FUNC_CLOCK_SUPPORT_APB if (esp_pm_lock_create(pm_type, 0, soc_sdm_signals[group_id].module_name, &group->pm_lock) != ESP_OK) { ESP_LOGE(TAG, "fail to create PM lock for group %d", group_id); } @@ -327,7 +327,7 @@ esp_err_t sdm_new_channel(const sdm_config_t *config, sdm_channel_handle_t *ret_ // preset the duty cycle to zero sdm_ll_set_pulse_density(group->hal.dev, chan_id, 0); - // initialize other members of timer + // initialize other members chan->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED; atomic_init(&chan->fsm, SDM_FSM_INIT); // set the initial state to INIT diff --git a/components/esp_driver_spi/test_apps/slave/main/test_app_main.c b/components/esp_driver_spi/test_apps/slave/main/test_app_main.c index 85c249ef105..9011f78d4d6 100644 --- a/components/esp_driver_spi/test_apps/slave/main/test_app_main.c +++ b/components/esp_driver_spi/test_apps/slave/main/test_app_main.c @@ -9,7 +9,7 @@ #include "esp_heap_caps.h" #include "esp_newlib.h" -#define TEST_MEMORY_LEAK_THRESHOLD (200) +#define TEST_MEMORY_LEAK_THRESHOLD (300) void setUp(void) { diff --git a/components/esp_driver_spi/test_apps/slave_hd/main/test_app_main.c b/components/esp_driver_spi/test_apps/slave_hd/main/test_app_main.c index ed90c0c9b69..a1b70e2a24f 100644 --- a/components/esp_driver_spi/test_apps/slave_hd/main/test_app_main.c +++ b/components/esp_driver_spi/test_apps/slave_hd/main/test_app_main.c @@ -9,7 +9,7 @@ #include "esp_heap_caps.h" #include "esp_newlib.h" -#define TEST_MEMORY_LEAK_THRESHOLD (200) +#define TEST_MEMORY_LEAK_THRESHOLD (300) void setUp(void) { diff --git a/components/esp_hw_support/dma/gdma.c b/components/esp_hw_support/dma/gdma.c index c8ac68e6914..1c2a6a0dfff 100644 --- a/components/esp_hw_support/dma/gdma.c +++ b/components/esp_hw_support/dma/gdma.c @@ -11,7 +11,7 @@ * +-----------------------------------+--+ +--+-----------------------------------+ * | GDMA-Group-X | | | | GDMA-Group-Y | * | +-------------+ +------------+ | | | | +-------------+ +------------+ | - * | | GDMA-Pair-0 |... |GDMA-Pair-N | | | | | | GDMA-Pair-0 |... |GDMA-Pair-N | | + * | | GDMA-Pair-0 |... |GDMA-Pair-N | | | | | | GDMA-Pair-0 |... |GDMA-Pair-M | | * | | | | | | | | | | | | | | * | | TX-Chan |... | TX-Chan | | | | | | TX-Chan |... | TX-Chan | | * | | RX-Chan | | RX-Chan | | | | | | RX-Chan | | RX-Chan | | @@ -29,25 +29,13 @@ #include "gdma_priv.h" #include "esp_memory_utils.h" #include "esp_flash_encrypt.h" -#include "esp_private/critical_section.h" - -#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP -#include "esp_private/gdma_sleep_retention.h" -#endif - -#if !SOC_RCC_IS_INDEPENDENT -// Reset and Clock Control registers are mixing with other peripherals, so we need to use a critical section -#define GDMA_RCC_ATOMIC() PERIPH_RCC_ATOMIC() -#else -#define GDMA_RCC_ATOMIC() -#endif #define GDMA_INVALID_PERIPH_TRIG (0x3F) #define SEARCH_REQUEST_RX_CHANNEL (1 << 0) #define SEARCH_REQUEST_TX_CHANNEL (1 << 1) typedef struct gdma_platform_t { - portMUX_TYPE spinlock; // platform level spinlock, protect the group handle slots and reference count of each group. + portMUX_TYPE spinlock; // platform level spinlock, protect the group handle slots and reference count of each group. gdma_group_t *groups[GDMA_LL_GET(INST_NUM)]; // array of GDMA group instances int group_ref_counts[GDMA_LL_GET(INST_NUM)]; // reference count used to protect group install/uninstall } gdma_platform_t; @@ -84,7 +72,23 @@ static esp_err_t do_allocate_gdma_channel(const gdma_channel_search_info_t *sear int search_code = 0; gdma_pair_t *pair = NULL; gdma_group_t *group = NULL; - ESP_RETURN_ON_FALSE(config && ret_chan, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + + // Validate input parameters + ESP_RETURN_ON_FALSE(search_info && config && ret_chan, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + ESP_RETURN_ON_FALSE(search_info->start_group_id < search_info->end_group_id, ESP_ERR_INVALID_ARG, TAG, "invalid group range"); + ESP_RETURN_ON_FALSE(search_info->pairs_per_group > 0, ESP_ERR_INVALID_ARG, TAG, "invalid pairs_per_group"); + if (config->sibling_chan) { + ESP_RETURN_ON_FALSE(config->sibling_chan->direction != config->direction, ESP_ERR_INVALID_ARG, TAG, + "sibling channel should have a different direction"); + ESP_RETURN_ON_FALSE(config->sibling_chan->pair, ESP_ERR_INVALID_ARG, TAG, "invalid sibling channel"); + } + +#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && SOC_GDMA_SUPPORT_SLEEP_RETENTION + // retention module is per GDMA pair, before we allocate the pair object, some common registers are already configured in "hal_init" + // if a light sleep happens and powers off the gdma module, those registers will get lost + // to work around it, we can acquire a power lock first, before any register configuration + sleep_retention_power_lock_acquire(); +#endif if (config->flags.reserve_sibling) { search_code = SEARCH_REQUEST_RX_CHANNEL | SEARCH_REQUEST_TX_CHANNEL; // search for a pair of channels @@ -101,13 +105,13 @@ static esp_err_t do_allocate_gdma_channel(const gdma_channel_search_info_t *sear if (config->sibling_chan) { pair = config->sibling_chan->pair; - ESP_GOTO_ON_FALSE(pair, ESP_ERR_INVALID_ARG, err, TAG, "invalid sibling channel"); - ESP_GOTO_ON_FALSE(config->sibling_chan->direction != config->direction, ESP_ERR_INVALID_ARG, err, TAG, "sibling channel should have a different direction"); group = pair->group; + // Acquire reference early, before any additional error checks esp_os_enter_critical(&group->spinlock); group->pair_ref_counts[pair->pair_id]++; // channel obtains a reference to pair esp_os_exit_critical(&group->spinlock); - goto search_done; // skip the search path below if user has specify a sibling channel + // skip the search path below if user has specify a sibling channel + goto search_done; } int start_group_id = search_info->start_group_id; @@ -129,17 +133,22 @@ static esp_err_t do_allocate_gdma_channel(const gdma_channel_search_info_t *sear esp_os_exit_critical(&pair->spinlock); // found a pair that satisfies the search condition if (search_code == 0) { - esp_os_enter_critical(&group->spinlock); - group->pair_ref_counts[pair->pair_id]++; // channel obtains a reference to pair - esp_os_exit_critical(&group->spinlock); + // gdma_acquire_pair_handle already increased pair ref count, no need to do it again + // pair is ready to use, don't release it + // however, we need to release the group reference acquired by gdma_acquire_group_handle + // because gdma_acquire_pair_handle already added its own group reference + gdma_release_group_handle(group); + break; // exit inner loop, will also exit outer loop due to search_code == 0 + } else { + // not suitable pair, release it + gdma_release_pair_handle(pair); + pair = NULL; } - gdma_release_pair_handle(pair); } // loop used to search pair - gdma_release_group_handle(group); - // restore to initial state if no suitable channel slot is found - if (search_code) { + // Only release group if we didn't find a suitable pair in this group + if (search_code != 0) { + gdma_release_group_handle(group); group = NULL; - pair = NULL; } } // loop used to search group ESP_GOTO_ON_FALSE(search_code == 0, ESP_ERR_NOT_FOUND, err, TAG, "no free gdma channel, search code=%d", search_code); @@ -170,6 +179,13 @@ search_done: // set 1 as default weight, can be overwritten by user gdma_set_weight(*ret_chan, 1); #endif + +#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && SOC_GDMA_SUPPORT_SLEEP_RETENTION + // set up the sleep retention link for the pair + gdma_acquire_sleep_retention(pair); + // release the helper power lock because we have finished setting up the sleep retention link + sleep_retention_power_lock_release(); +#endif (*ret_chan)->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED; ESP_LOGD(TAG, "new %s channel (%d,%d) at %p", (config->direction == GDMA_CHANNEL_DIRECTION_TX) ? "tx" : "rx", group->group_id, pair->pair_id, *ret_chan); @@ -184,10 +200,15 @@ err: } if (pair) { gdma_release_pair_handle(pair); - } - if (group) { + // pair release will also release group if it's the last reference + // so we don't need to release group separately to avoid double-release + } else if (group) { + // only release group if pair wasn't allocated/released gdma_release_group_handle(group); } +#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && SOC_GDMA_SUPPORT_SLEEP_RETENTION + sleep_retention_power_lock_release(); +#endif return ret; } @@ -219,14 +240,6 @@ esp_err_t gdma_new_axi_channel(const gdma_channel_alloc_config_t *config, gdma_c } #endif // SOC_HAS(AXI_GDMA) -#if SOC_HAS(AHB_GDMA) -esp_err_t gdma_new_channel(const gdma_channel_alloc_config_t *config, gdma_channel_handle_t *ret_chan) -__attribute__((alias("gdma_new_ahb_channel"))); -#elif SOC_HAS(AXI_GDMA) -esp_err_t gdma_new_channel(const gdma_channel_alloc_config_t *config, gdma_channel_handle_t *ret_chan) -__attribute__((alias("gdma_new_axi_channel"))); -#endif - esp_err_t gdma_del_channel(gdma_channel_handle_t dma_chan) { ESP_RETURN_ON_FALSE(dma_chan, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); @@ -613,14 +626,14 @@ static void gdma_release_group_handle(gdma_group_t *group) do_deinitialize = true; // deregister from the platform s_platform.groups[group_id] = NULL; + gdma_hal_deinit(&group->hal); + PERIPH_RCC_ATOMIC() { + gdma_ll_enable_bus_clock(group_id, false); + } } esp_os_exit_critical(&s_platform.spinlock); if (do_deinitialize) { - gdma_hal_deinit(&group->hal); - GDMA_RCC_ATOMIC() { - gdma_ll_enable_bus_clock(group_id, false); - } free(group); ESP_LOGD(TAG, "del group %d", group_id); } @@ -640,18 +653,11 @@ static gdma_group_t *gdma_acquire_group_handle(int group_id, void (*hal_init)(gd new_group = true; group = pre_alloc_group; s_platform.groups[group_id] = group; // register to platform - } else { - group = s_platform.groups[group_id]; - } - // someone acquired the group handle means we have a new object that refer to this group - s_platform.group_ref_counts[group_id]++; - esp_os_exit_critical(&s_platform.spinlock); - if (new_group) { group->group_id = group_id; group->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED; // enable APB to access GDMA registers - GDMA_RCC_ATOMIC() { + PERIPH_RCC_ATOMIC() { gdma_ll_enable_bus_clock(group_id, true); gdma_ll_reset_register(group_id); } @@ -662,6 +668,14 @@ static gdma_group_t *gdma_acquire_group_handle(int group_id, void (*hal_init)(gd #endif }; hal_init(&group->hal, &config); + } else { + group = s_platform.groups[group_id]; + } + // someone acquired the group handle means we have a new object that refer to this group + s_platform.group_ref_counts[group_id]++; + esp_os_exit_critical(&s_platform.spinlock); + + if (new_group) { ESP_LOGD(TAG, "new group (%d) at %p", group_id, group); } else { free(pre_alloc_group); @@ -687,9 +701,6 @@ static void gdma_release_pair_handle(gdma_pair_t *pair) if (do_deinitialize) { free(pair); -#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && SOC_GDMA_SUPPORT_SLEEP_RETENTION - gdma_sleep_retention_deinit(group->group_id, pair_id); -#endif ESP_LOGD(TAG, "del pair (%d,%d)", group->group_id, pair_id); gdma_release_group_handle(group); } @@ -708,6 +719,10 @@ static gdma_pair_t *gdma_acquire_pair_handle(gdma_group_t *group, int pair_id) if (!group->pairs[pair_id]) { new_pair = true; pair = pre_alloc_pair; + // initialize pair before registering to avoid accessing uninitialized pair + pair->group = group; + pair->pair_id = pair_id; + pair->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED; // register the pair to the group group->pairs[pair_id] = pair; } else { @@ -717,23 +732,18 @@ static gdma_pair_t *gdma_acquire_pair_handle(gdma_group_t *group, int pair_id) group->pair_ref_counts[pair_id]++; esp_os_exit_critical(&group->spinlock); + // Update group reference count outside of group->spinlock to avoid deadlock + // This must be done after pair registration to ensure group remains valid if (new_pair) { - pair->group = group; - pair->pair_id = pair_id; - pair->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED; - esp_os_enter_critical(&s_platform.spinlock); - // pair obtains a reference to group, so increase it s_platform.group_ref_counts[group->group_id]++; esp_os_exit_critical(&s_platform.spinlock); -#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && SOC_GDMA_SUPPORT_SLEEP_RETENTION - gdma_sleep_retention_init(group->group_id, pair_id); -#endif ESP_LOGD(TAG, "new pair (%d,%d) at %p", group->group_id, pair_id, pair); } else { free(pre_alloc_pair); } + out: return pair; } @@ -743,6 +753,7 @@ static esp_err_t gdma_del_tx_channel(gdma_channel_t *dma_channel) gdma_pair_t *pair = dma_channel->pair; gdma_group_t *group = pair->group; gdma_hal_context_t *hal = &group->hal; + // Store IDs early to avoid use-after-free int pair_id = pair->pair_id; int group_id = group->group_id; gdma_tx_channel_t *tx_chan = __containerof(dma_channel, gdma_tx_channel_t, base); @@ -762,6 +773,11 @@ static esp_err_t gdma_del_tx_channel(gdma_channel_t *dma_channel) free(tx_chan); ESP_LOGD(TAG, "del tx channel (%d,%d)", group_id, pair_id); + +#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && SOC_GDMA_SUPPORT_SLEEP_RETENTION + // release sleep retention lock + gdma_release_sleep_retention(pair); +#endif // channel has a reference on pair, release it now gdma_release_pair_handle(pair); return ESP_OK; @@ -772,6 +788,7 @@ static esp_err_t gdma_del_rx_channel(gdma_channel_t *dma_channel) gdma_pair_t *pair = dma_channel->pair; gdma_group_t *group = pair->group; gdma_hal_context_t *hal = &group->hal; + // Store IDs early to avoid use-after-free int pair_id = pair->pair_id; int group_id = group->group_id; gdma_rx_channel_t *rx_chan = __containerof(dma_channel, gdma_rx_channel_t, base); @@ -791,6 +808,12 @@ static esp_err_t gdma_del_rx_channel(gdma_channel_t *dma_channel) free(rx_chan); ESP_LOGD(TAG, "del rx channel (%d,%d)", group_id, pair_id); + +#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && SOC_GDMA_SUPPORT_SLEEP_RETENTION + // release sleep retention lock + gdma_release_sleep_retention(pair); +#endif + // channel has a reference on pair, release it now gdma_release_pair_handle(pair); return ESP_OK; } diff --git a/components/esp_hw_support/dma/gdma_priv.h b/components/esp_hw_support/dma/gdma_priv.h index ffa0e0bb893..a16305f58ff 100644 --- a/components/esp_hw_support/dma/gdma_priv.h +++ b/components/esp_hw_support/dma/gdma_priv.h @@ -33,6 +33,8 @@ #include "soc/periph_defs.h" #include "esp_private/gdma.h" #include "esp_private/periph_ctrl.h" +#include "esp_private/critical_section.h" +#include "esp_private/sleep_retention.h" #if CONFIG_GDMA_OBJ_DRAM_SAFE #define GDMA_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT) @@ -98,6 +100,9 @@ struct gdma_rx_channel_t { gdma_rx_event_callbacks_t cbs; // RX event callbacks }; +void gdma_acquire_sleep_retention(gdma_pair_t* pair); +void gdma_release_sleep_retention(gdma_pair_t* pair); + #ifdef __cplusplus } #endif diff --git a/components/esp_hw_support/dma/gdma_sleep_retention.c b/components/esp_hw_support/dma/gdma_sleep_retention.c index 6c8eeaf29c4..a5f27b365dd 100644 --- a/components/esp_hw_support/dma/gdma_sleep_retention.c +++ b/components/esp_hw_support/dma/gdma_sleep_retention.c @@ -4,61 +4,79 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include "gdma_priv.h" -#include "esp_private/sleep_retention.h" -#include "esp_private/esp_regdma.h" -typedef struct { - int group_id; - int pair_id; -} gdma_channel_retention_arg_t; +// Note!: the sleep retention APIs are using OS locks, so here we have to use a lock rather than a light-weight critical section +static _lock_t gdma_sleep_retention_lock; +static uint8_t pair_ref_counts[GDMA_LL_GET(INST_NUM)][GDMA_LL_GET(PAIRS_PER_INST)]; ESP_LOG_ATTR_TAG(TAG, "gdma"); static esp_err_t sleep_gdma_channel_retention_init(void *arg) { - gdma_channel_retention_arg_t *parg = (gdma_channel_retention_arg_t *)arg; - int group_id = parg->group_id; - int pair_id = parg->pair_id; + gdma_pair_t *pair = (gdma_pair_t *)arg; + int group_id = pair->group->group_id; + int pair_id = pair->pair_id; sleep_retention_module_t module = gdma_chx_regs_retention[group_id][pair_id].module_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_GDMA, module); + 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_GDMA, module); if (err == ESP_OK) { - ESP_LOGD(TAG, "GDMA pair (%d, %d) retention initialization", group_id, pair_id); + ESP_LOGD(TAG, "retention link created for pair (%d, %d)", group_id, pair_id); + } else { + ESP_LOGE(TAG, "failed to create retention link for pair (%d, %d)", 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) +void gdma_acquire_sleep_retention(gdma_pair_t* pair) { - gdma_channel_retention_arg_t arg = { .group_id = group_id, .pair_id = pair_id }; + int group_id = pair->group->group_id; + int pair_id = pair->pair_id; sleep_retention_module_init_param_t init_param = { - .cbs = { .create = { .handle = sleep_gdma_channel_retention_init, .arg = &arg } }, + .cbs = { .create = { .handle = sleep_gdma_channel_retention_init, .arg = pair } }, .depends = RETENTION_MODULE_BITMAP_INIT(CLOCK_SYSTEM) }; sleep_retention_module_t module = gdma_chx_regs_retention[group_id][pair_id].module_id; - esp_err_t err = sleep_retention_module_init(module, &init_param); - if (err == ESP_OK) { - err = sleep_retention_module_allocate(module); + + _lock_acquire(&gdma_sleep_retention_lock); + // First time acquiring this pair, initialize the module + if (pair_ref_counts[group_id][pair_id] == 0) { + esp_err_t err = sleep_retention_module_init(module, &init_param); if (err != ESP_OK) { - ESP_LOGW(TAG, "Failed to allocate sleep retention linked list for GDMA retention"); + ESP_LOGW(TAG, "init retention module failed for pair (%d, %d), power domain may be turned off during sleep", group_id, pair_id); + } else { + err = sleep_retention_module_allocate(module); + if (err != ESP_OK) { + ESP_LOGW(TAG, "fail to allocate retention link list for pair (%d, %d)", group_id, pair_id); + // don't call sleep_retention_module_deinit here, otherwise GDMA peripheral may be powered off during sleep + } } } - return err; + pair_ref_counts[group_id][pair_id]++; + _lock_release(&gdma_sleep_retention_lock); } -esp_err_t gdma_sleep_retention_deinit(int group_id, int pair_id) +void gdma_release_sleep_retention(gdma_pair_t* pair) { + int group_id = pair->group->group_id; + int pair_id = pair->pair_id; sleep_retention_module_t module = gdma_chx_regs_retention[group_id][pair_id].module_id; - esp_err_t err = sleep_retention_module_free(module); - if (err != ESP_OK) { - ESP_LOGW(TAG, "GDMA pair (%d, %d) retention destroy failed", group_id, pair_id); + + _lock_acquire(&gdma_sleep_retention_lock); + pair_ref_counts[group_id][pair_id]--; + // Last reference, free the module + if (pair_ref_counts[group_id][pair_id] == 0) { + esp_err_t err = sleep_retention_module_free(module); + if (err != ESP_OK) { + ESP_LOGW(TAG, "fail to free the retention link list for pair (%d, %d)", group_id, pair_id); + } + err = sleep_retention_module_deinit(module); + if (err != ESP_OK) { + ESP_LOGW(TAG, "fail to deinit the retention module for pair (%d, %d)", group_id, pair_id); + } } - err = sleep_retention_module_deinit(module); - if (err != ESP_OK) { - ESP_LOGW(TAG, "GDMA pair (%d, %d) retention deinit failed", group_id, pair_id); - } - return err; + _lock_release(&gdma_sleep_retention_lock); } diff --git a/components/esp_hw_support/dma/include/esp_private/gdma.h b/components/esp_hw_support/dma/include/esp_private/gdma.h index 1683b88076b..289b8e093d1 100644 --- a/components/esp_hw_support/dma/include/esp_private/gdma.h +++ b/components/esp_hw_support/dma/include/esp_private/gdma.h @@ -52,7 +52,7 @@ typedef struct { /** * @brief Type of GDMA event callback - * @param dma_chan GDMA channel handle, created from `gdma_new_channel` + * @param dma_chan GDMA channel handle, created from `gdma_new_ahb_channel/gdma_new_axi_channel` * @param event_data GDMA event data. Different event share the same data structure, but the caller may only use a few or none of the data members. * @param user_data User registered data from `gdma_register_tx_event_callbacks` or `gdma_register_rx_event_callbacks` * @@ -146,7 +146,7 @@ esp_err_t gdma_new_axi_channel(const gdma_channel_alloc_config_t *config, gdma_c * @note Suggest to use helper macro `GDMA_MAKE_TRIGGER` to construct parameter `trig_periph`. e.g. GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_SHA,0) * @note Connecting to a peripheral will also reset the DMA FIFO and FSM automatically * - * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel` + * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_ahb_channel/gdma_new_axi_channel` * @param[in] trig_periph GDMA trigger peripheral * @return * - ESP_OK: Connect GDMA channel successfully @@ -159,7 +159,7 @@ esp_err_t gdma_connect(gdma_channel_handle_t dma_chan, gdma_trigger_t trig_perip /** * @brief Disconnect GMA channel from peripheral * - * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel` + * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_ahb_channel/gdma_new_axi_channel` * @return * - ESP_OK: Disconnect GDMA channel successfully * - ESP_ERR_INVALID_ARG: Disconnect GDMA channel failed because of invalid argument @@ -184,7 +184,7 @@ typedef struct { * @note It's highly recommended to enable the burst mode and set proper burst size for the DMA channel, * which can improve the performance in accessing external memory by a lot. * - * @param[in] chan DMA channel handle, allocated by `gdma_new_channel` + * @param[in] chan DMA channel handle, allocated by `gdma_new_ahb_channel/gdma_new_axi_channel` * @param[in] config Transfer configurations * @return * - ESP_OK: Configure DMA transfer parameters successfully @@ -202,7 +202,7 @@ esp_err_t gdma_config_transfer(gdma_channel_handle_t dma_chan, const gdma_transf * @note The returned alignment doesn't take the cache line size into account, if you want to do aligned memory allocation, * you should align the buffer size to the cache line size by yourself if the DMA buffer is behind a cache. * - * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel` + * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_ahb_channel/gdma_new_axi_channel` * @param[out] int_mem_alignment Internal memory alignment * @param[out] ext_mem_alignment External memory alignment * @return @@ -215,7 +215,7 @@ esp_err_t gdma_get_alignment_constraints(gdma_channel_handle_t dma_chan, size_t /** * @brief Apply channel strategy for GDMA channel * - * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel` + * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_ahb_channel/gdma_new_axi_channel` * @param[in] config Configuration of GDMA channel strategy * - ESP_OK: Apply channel strategy successfully * - ESP_ERR_INVALID_ARG: Apply channel strategy failed because of invalid argument @@ -228,7 +228,7 @@ esp_err_t gdma_apply_strategy(gdma_channel_handle_t dma_chan, const gdma_strateg * * @note By default, all GDMA channels are with the same priority: 0. Channels with the same priority are served in round-robin manner. * - * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel` + * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_ahb_channel/gdma_new_axi_channel` * @param[in] priority Priority of GDMA channel, higher value means higher priority * @return * - ESP_OK: Set GDMA channel priority successfully @@ -239,9 +239,9 @@ esp_err_t gdma_set_priority(gdma_channel_handle_t dma_chan, uint32_t priority); /** * @brief Delete GDMA channel - * @note If you call `gdma_new_channel` several times for a same peripheral, make sure you call this API the same times. + * @note If you call `gdma_new_ahb_channel/gdma_new_axi_channel` several times for a same peripheral, make sure you call this API the same times. * - * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel` + * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_ahb_channel/gdma_new_axi_channel` * @return * - ESP_OK: Delete GDMA channel successfully * - ESP_ERR_INVALID_ARG: Delete GDMA channel failed because of invalid argument @@ -255,7 +255,7 @@ esp_err_t gdma_del_channel(gdma_channel_handle_t dma_chan); * @note This API breaks the encapsulation of GDMA Channel Object. * With the returned group/channel ID, you can even bypass all other GDMA driver API and access Low Level API directly. * - * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel` + * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_ahb_channel/gdma_new_axi_channel` * @param[out] group_id Returned group ID * @param[out] channel_id Returned channel ID * @return @@ -271,7 +271,7 @@ esp_err_t gdma_get_group_channel_id(gdma_channel_handle_t dma_chan, int *group_i * @brief Set GDMA event callbacks for TX channel * @note This API will install GDMA interrupt service for the channel internally * - * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel` + * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_ahb_channel/gdma_new_axi_channel` * @param[in] cbs Group of callback functions * @param[in] user_data User data, which will be passed to callback functions directly * @return @@ -285,7 +285,7 @@ esp_err_t gdma_register_tx_event_callbacks(gdma_channel_handle_t dma_chan, gdma_ * @brief Set GDMA event callbacks for RX channel * @note This API will install GDMA interrupt service for the channel internally * - * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel` + * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_ahb_channel/gdma_new_axi_channel` * @param[in] cbs Group of callback functions * @param[in] user_data User data, which will be passed to callback functions directly * @return @@ -301,7 +301,7 @@ esp_err_t gdma_register_rx_event_callbacks(gdma_channel_handle_t dma_chan, gdma_ * @note This function is allowed to run within ISR context * @note This function is also allowed to run when Cache is disabled, if `CONFIG_GDMA_CTRL_FUNC_IN_IRAM` is enabled * - * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel` + * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_ahb_channel/gdma_new_axi_channel` * @param[in] desc_base_addr Base address of descriptors (usually the descriptors are chained into a link or ring) * @return * - ESP_OK: Start DMA engine successfully @@ -317,7 +317,7 @@ esp_err_t gdma_start(gdma_channel_handle_t dma_chan, intptr_t desc_base_addr); * @note This function is allowed to run within ISR context * @note This function is also allowed to run when Cache is disabled, if `CONFIG_GDMA_CTRL_FUNC_IN_IRAM` is enabled * - * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel` + * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_ahb_channel/gdma_new_axi_channel` * @return * - ESP_OK: Stop DMA engine successfully * - ESP_ERR_INVALID_ARG: Stop DMA engine failed because of invalid argument @@ -333,7 +333,7 @@ esp_err_t gdma_stop(gdma_channel_handle_t dma_chan); * @note This function is also allowed to run when Cache is disabled, if `CONFIG_GDMA_CTRL_FUNC_IN_IRAM` is enabled * @note This API could also resume a paused DMA engine, make sure new descriptors have been appended to the descriptor chain before calling it. * - * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel` + * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_ahb_channel/gdma_new_axi_channel` * @return * - ESP_OK: Send append command to DMA engine successfully * - ESP_ERR_INVALID_ARG: Send append command to DMA engine failed because of invalid argument @@ -348,7 +348,7 @@ esp_err_t gdma_append(gdma_channel_handle_t dma_chan); * @note This function is also allowed to run when Cache is disabled, if `CONFIG_GDMA_CTRL_FUNC_IN_IRAM` is enabled * @note Resetting a DMA channel won't break the connection with the target peripheral * - * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel` + * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_ahb_channel/gdma_new_axi_channel` * @return * - ESP_OK: DMA channel reset successfully * - ESP_ERR_INVALID_ARG: DMA channel reset failed due to invalid arguments @@ -369,7 +369,7 @@ typedef struct { * * @note The created ETM event object can be deleted later by calling `esp_etm_del_event` * - * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel` + * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_ahb_channel/gdma_new_axi_channel` * @param[in] config GDMA ETM event configuration * @param[out] out_event Returned ETM event handle * @return @@ -393,7 +393,7 @@ typedef struct { * @note The created ETM task object can be deleted later by calling `esp_etm_del_task` * @note If the GDMA task (e.g. start/stop) is controlled by ETM, then you can't use `gdma_start`/`gdma_stop` to control it. * - * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel` + * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_ahb_channel/gdma_new_axi_channel` * @param[in] config GDMA ETM task configuration * @param[out] out_task Returned ETM task handle * @return @@ -412,7 +412,7 @@ esp_err_t gdma_new_etm_task(gdma_channel_handle_t dma_chan, const gdma_etm_task_ * which can bring conflict if the peripheral is also using the same trigger ID. This function can return the free IDs * for memory copy, at the runtime. * - * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel` + * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_ahb_channel/gdma_new_axi_channel` * @param[out] mask Returned mask of free M2M trigger IDs * @return * - ESP_OK: Get free M2M trigger IDs successfully @@ -438,7 +438,7 @@ typedef struct { * @note This function must be called before `gdma_start`. * @note The CRC Calculator will reset itself automatically if the DMA stops and starts again. * - * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel` + * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_ahb_channel/gdma_new_axi_channel` * @param[in] config CRC Calculator configuration * @return * - ESP_OK: Configure CRC Calculator successfully @@ -452,7 +452,7 @@ esp_err_t gdma_config_crc_calculator(gdma_channel_handle_t dma_chan, const gdma_ * * @note You need to call this function before a new DMA transaction starts, otherwise the CRC results may be overridden. * - * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel` + * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_ahb_channel/gdma_new_axi_channel` * @param[out] result Returned CRC result * @return * - ESP_OK: Get CRC result successfully @@ -474,7 +474,7 @@ esp_err_t gdma_crc_get_result(gdma_channel_handle_t dma_chan, uint32_t *result); * @note Weighted arbitration is different from priority arbitration. "Weight" is used after comparing "priority" * After the priority comparison, then arbitrator checks whether there are still unused tokens in the channel. * - * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel` + * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_ahb_channel/gdma_new_axi_channel` * @param[in] weight Weight of GDMA channel, higher value means higher priority in weighted arbitration. * @return * - ESP_OK: Set GDMA channel weight successfully diff --git a/components/esp_hw_support/include/esp_private/gdma_sleep_retention.h b/components/esp_hw_support/include/esp_private/gdma_sleep_retention.h deleted file mode 100644 index 19d649d79af..00000000000 --- a/components/esp_hw_support/include/esp_private/gdma_sleep_retention.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -// DO NOT USE THESE APIS IN ANY APPLICATIONS -// GDMA driver is not public for end users, but for ESP-IDF developers. - -#pragma once - -#include "esp_err.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Initialize GDMA channel retention link for powerdown the TOP powerdomain during lightsleep - * @param group_id Group id - * @param pair_id Pair id - * @return - * - ESP_OK: Create DMA retention link successfully - * - ESP_ERR_NO_MEM: Create DMA retention link failed because out of memory - */ -esp_err_t gdma_sleep_retention_init(int group_id, int pair_id); - -/** - * Destroy GDMA channel retention link - * @param group_id Group id - * @param pair_id Pair id - * @return - * - ESP_OK: GDMA channel retention link destrory successfully - * - ESP_ERR_INVALID_STATE: GDMA channel retention link not create yet - */ -esp_err_t gdma_sleep_retention_deinit(int group_id, int pair_id); - -#ifdef __cplusplus -} -#endif diff --git a/components/esp_hw_support/include/esp_private/periph_ctrl.h b/components/esp_hw_support/include/esp_private/periph_ctrl.h index cfbdc1fbe1c..005001e0354 100644 --- a/components/esp_hw_support/include/esp_private/periph_ctrl.h +++ b/components/esp_hw_support/include/esp_private/periph_ctrl.h @@ -25,9 +25,9 @@ extern "C" { * @note This macro will increase the reference lock of that peripheral. * You can get the value before the increment from the `rc_name` local variable */ -#define PERIPH_RCC_ACQUIRE_ATOMIC(rc_periph, rc_name) \ - for (uint8_t rc_name, _rc_cnt = 1, __DECLARE_RCC_RC_ATOMIC_ENV; \ - _rc_cnt ? (rc_name = periph_rcc_acquire_enter(rc_periph), 1) : 0; \ +#define PERIPH_RCC_ACQUIRE_ATOMIC(rc_periph, rc_name) \ + for (uint8_t rc_name, _rc_cnt = 1, __DECLARE_RCC_RC_ATOMIC_ENV __attribute__((unused)); \ + _rc_cnt ? (rc_name = periph_rcc_acquire_enter(rc_periph), 1) : 0; \ periph_rcc_acquire_exit(rc_periph, rc_name), _rc_cnt--) /** @@ -37,9 +37,9 @@ extern "C" { * @note This macro will decrease the reference lock of that peripheral. * You can get the value after the decrease from the `rc_name` local variable */ -#define PERIPH_RCC_RELEASE_ATOMIC(rc_periph, rc_name) \ - for (uint8_t rc_name, _rc_cnt = 1, __DECLARE_RCC_RC_ATOMIC_ENV; \ - _rc_cnt ? (rc_name = periph_rcc_release_enter(rc_periph), 1) : 0; \ +#define PERIPH_RCC_RELEASE_ATOMIC(rc_periph, rc_name) \ + for (uint8_t rc_name, _rc_cnt = 1, __DECLARE_RCC_RC_ATOMIC_ENV __attribute__((unused)); \ + _rc_cnt ? (rc_name = periph_rcc_release_enter(rc_periph), 1) : 0; \ periph_rcc_release_exit(rc_periph, rc_name), _rc_cnt--) /** @@ -47,9 +47,9 @@ extern "C" { * * @note User code protected by this macro should be as short as possible, because it's a critical section */ -#define PERIPH_RCC_ATOMIC() \ - for (int _rc_cnt = 1, __DECLARE_RCC_ATOMIC_ENV; \ - _rc_cnt ? (periph_rcc_enter(), 1) : 0; \ +#define PERIPH_RCC_ATOMIC() \ + for (int _rc_cnt = 1, __DECLARE_RCC_ATOMIC_ENV __attribute__((unused)); \ + _rc_cnt ? (periph_rcc_enter(), 1) : 0; \ periph_rcc_exit(), _rc_cnt--) /** @cond */ From 7338c5179bb456dd18f4eb7960ff6780968eb966 Mon Sep 17 00:00:00 2001 From: "harshal.patil" Date: Fri, 31 Oct 2025 14:06:37 +0530 Subject: [PATCH 017/106] fix(build_system): Add Bootloader and Partition Table as dependencies for encrypted-flash - If ESP-TEE is enabled, also add it as the dependency for the encrypted-flash target --- components/bootloader/CMakeLists.txt | 5 +++++ components/esp_tee/CMakeLists.txt | 4 ++++ components/partition_table/CMakeLists.txt | 6 ++++++ 3 files changed, 15 insertions(+) diff --git a/components/bootloader/CMakeLists.txt b/components/bootloader/CMakeLists.txt index 8ebd8e9051f..7fe8d380f6c 100644 --- a/components/bootloader/CMakeLists.txt +++ b/components/bootloader/CMakeLists.txt @@ -35,4 +35,9 @@ if(NOT CONFIG_SECURE_BOOT OR CONFIG_SECURE_BOOT_FLASH_BOOTLOADER_DEFAULT) # Add bootloader as a dependency to the flash target add_dependencies(flash bootloader) + + if(CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT) + # Also add bootloader as a dependency to the encrypted-flash target + add_dependencies(encrypted-flash bootloader) + endif() endif() diff --git a/components/esp_tee/CMakeLists.txt b/components/esp_tee/CMakeLists.txt index 320931b4a82..4de84941879 100644 --- a/components/esp_tee/CMakeLists.txt +++ b/components/esp_tee/CMakeLists.txt @@ -28,6 +28,10 @@ else() endif() add_dependencies(esp_tee partition_table_bin) add_dependencies(flash esp_tee) + if(CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT) + # Also add ESP-TEE binary as a dependency to the encrypted-flash target + add_dependencies(encrypted-flash esp_tee) + endif() set(image_file ${TEE_BUILD_DIR}/esp_tee.bin) partition_table_get_partition_info(offset "--partition-name ${partition}" "offset") esptool_py_flash_target_image(flash "${partition}" "${offset}" "${image_file}") diff --git a/components/partition_table/CMakeLists.txt b/components/partition_table/CMakeLists.txt index fca05efc855..53154d612fb 100644 --- a/components/partition_table/CMakeLists.txt +++ b/components/partition_table/CMakeLists.txt @@ -177,5 +177,11 @@ if(CONFIG_APP_BUILD_GENERATE_BINARIES AND CONFIG_APP_BUILD_TYPE_APP_2NDBOOT) # Add partition table as a dependency to the flash target add_dependencies(flash partition_table_bin) + + if(CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT) + # Also add partition table as a dependency to the encrypted-flash target + add_dependencies(encrypted-flash partition_table_bin) + endif() + add_deprecated_target_alias(partition_table-flash partition-table-flash) endif() From beb0303ad6b5a1b96e5c730702e1e784afc76ce4 Mon Sep 17 00:00:00 2001 From: "harshal.patil" Date: Mon, 27 Oct 2025 19:10:48 +0530 Subject: [PATCH 018/106] fix(hal): Fix MMU PSRAM anti-fi MMU target check In case of ESP32-C5 and ESP32-C61, mmu_ids for PSRAM and Flash MMU are the same due to their shared memory space. Thus, instead of mmu_id we should use mmu_target_t. --- components/hal/esp32c5/include/hal/mmu_ll.h | 2 +- components/hal/esp32c61/include/hal/mmu_ll.h | 2 +- components/hal/esp32p4/include/hal/mmu_ll.h | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/components/hal/esp32c5/include/hal/mmu_ll.h b/components/hal/esp32c5/include/hal/mmu_ll.h index 5dcc6e5fd18..79df1a70676 100644 --- a/components/hal/esp32c5/include/hal/mmu_ll.h +++ b/components/hal/esp32c5/include/hal/mmu_ll.h @@ -233,7 +233,7 @@ __attribute__((always_inline)) static inline void mmu_ll_write_entry(uint32_t mm if (mmu_ll_cache_encryption_enabled() && target == MMU_TARGET_PSRAM0 && efuse_hal_chip_revision() > 100) { ESP_FAULT_ASSERT(REG_READ(SPI_MEM_MMU_ITEM_CONTENT_REG(0)) & SOC_MMU_SENSITIVE); } else { - ESP_FAULT_ASSERT(!(mmu_ll_cache_encryption_enabled() && mmu_id == MMU_LL_PSRAM_MMU_ID && efuse_hal_chip_revision() > 100)); + ESP_FAULT_ASSERT(!(mmu_ll_cache_encryption_enabled() && target == MMU_TARGET_PSRAM0 && efuse_hal_chip_revision() > 100)); } } diff --git a/components/hal/esp32c61/include/hal/mmu_ll.h b/components/hal/esp32c61/include/hal/mmu_ll.h index 1e9da4aba83..b0dc2d03b7e 100644 --- a/components/hal/esp32c61/include/hal/mmu_ll.h +++ b/components/hal/esp32c61/include/hal/mmu_ll.h @@ -235,7 +235,7 @@ __attribute__((always_inline)) static inline void mmu_ll_write_entry(uint32_t mm if (mmu_ll_cache_encryption_enabled() && target == MMU_TARGET_PSRAM0 && efuse_hal_chip_revision() > 100) { ESP_FAULT_ASSERT(REG_READ(SPI_MEM_MMU_ITEM_CONTENT_REG(0)) & SOC_MMU_SENSITIVE); } else { - ESP_FAULT_ASSERT(!(mmu_ll_cache_encryption_enabled() && mmu_id == MMU_LL_PSRAM_MMU_ID && efuse_hal_chip_revision() > 100)); + ESP_FAULT_ASSERT(!(mmu_ll_cache_encryption_enabled() && target == MMU_TARGET_PSRAM0 && efuse_hal_chip_revision() > 100)); } } diff --git a/components/hal/esp32p4/include/hal/mmu_ll.h b/components/hal/esp32p4/include/hal/mmu_ll.h index 7120c30964b..e86d1a18fbd 100644 --- a/components/hal/esp32p4/include/hal/mmu_ll.h +++ b/components/hal/esp32p4/include/hal/mmu_ll.h @@ -294,10 +294,10 @@ __attribute__((always_inline)) static inline void mmu_ll_write_entry(uint32_t mm // Anti-FI check to confirm the encryption status for PSRAM entry. // This avoids a potential FI attacks to keep PSRAM unencrypted and // hence read out plaintext in execute from PSRAM model. - if (mmu_ll_cache_encryption_enabled() && mmu_id == MMU_LL_PSRAM_MMU_ID) { + if (mmu_ll_cache_encryption_enabled() && target == MMU_TARGET_PSRAM0) { ESP_FAULT_ASSERT(REG_READ(content_reg) & SOC_MMU_PSRAM_SENSITIVE); } else { - ESP_FAULT_ASSERT(!(mmu_ll_cache_encryption_enabled() && mmu_id == MMU_LL_PSRAM_MMU_ID)); + ESP_FAULT_ASSERT(!(mmu_ll_cache_encryption_enabled() && target == MMU_TARGET_PSRAM0)); } } From 7c1e5c8e76fe078ae967cfc80b47cbb35c96fd76 Mon Sep 17 00:00:00 2001 From: Ondrej Kosta Date: Mon, 27 Oct 2025 10:38:20 +0100 Subject: [PATCH 019/106] fix(examples): fixed bridge example test endnode to host send --- .../network/bridge/pytest_example_bridge.py | 54 ++++++++++--------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/examples/network/bridge/pytest_example_bridge.py b/examples/network/bridge/pytest_example_bridge.py index aa0108de7cb..aaffdb7ebc5 100644 --- a/examples/network/bridge/pytest_example_bridge.py +++ b/examples/network/bridge/pytest_example_bridge.py @@ -11,9 +11,6 @@ import subprocess import time from concurrent.futures import Future from concurrent.futures import ThreadPoolExecutor -from typing import List -from typing import Optional -from typing import Union import netifaces import paramiko # type: ignore @@ -34,7 +31,7 @@ MIN_TCP_THROUGHPUT = 4 class EndnodeSsh: - def __init__(self, host_ip: str, usr: str, passwd: Optional[str] = None): + def __init__(self, host_ip: str, usr: str, passwd: str | None = None): key_string = os.getenv('CI_ETHVM_KEY') key = None if key_string: @@ -55,7 +52,7 @@ class EndnodeSsh: error = stderr.read().decode().strip() if error: out = '' - logging.error('ssh_endnode_exec error: {}'.format(error)) + logging.error(f'ssh_endnode_exec error: {error}') return out # type: ignore @@ -91,7 +88,7 @@ class SwitchSsh: } self.ssh_client = ConnectHandler(**edgeSwitch) - def exec_cmd(self, cmd: Union[str, List[str]]) -> str: + def exec_cmd(self, cmd: str | list[str]) -> str: if self.type == self.EDGE_SWITCH_5XP: _, stdout, stderr = self.ssh_client.exec_command(cmd) @@ -99,7 +96,7 @@ class SwitchSsh: error = stderr.read().decode().strip() if error != 'TSW Init OK!': - raise Exception('switch_5xp exec_cmd error: {}'.format(error)) + raise Exception(f'switch_5xp exec_cmd error: {error}') else: out = self.ssh_client.send_config_set(cmd, cmd_verify=False, exit_config_mode=False) return out # type: ignore @@ -159,7 +156,7 @@ def get_host_interface_name_in_same_net(ip_addr: str) -> str: def get_host_mac_by_interface(interface_name: str, addr_type: int = netifaces.AF_LINK) -> str: for _addr in netifaces.ifaddresses(interface_name)[addr_type]: - host_mac = _addr['addr'].replace('%{}'.format(interface_name), '') + host_mac = _addr['addr'].replace(f'%{interface_name}', '') assert isinstance(host_mac, str) return host_mac return '' @@ -167,7 +164,7 @@ def get_host_mac_by_interface(interface_name: str, addr_type: int = netifaces.AF def get_host_brcast_ip_by_interface(interface_name: str, ip_type: int = netifaces.AF_INET) -> str: for _addr in netifaces.ifaddresses(interface_name)[ip_type]: - host_ip = _addr['broadcast'].replace('%{}'.format(interface_name), '') + host_ip = _addr['broadcast'].replace(f'%{interface_name}', '') assert isinstance(host_ip, str) return host_ip return '' @@ -190,7 +187,7 @@ def run_iperf( if ipaddress.ip_address(server_ip).is_multicast: # Configure Multicast Server server_proc = subprocess.Popen( - ['iperf', '-u', '-s', '-i', '1', '-t', '%i' % interval, '-B', '%s%%%s' % (server_ip, server_if)], + ['iperf', '-u', '-s', '-i', '1', '-t', str(interval), '-B', f'{server_ip}%{server_if}'], text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, @@ -200,20 +197,20 @@ def run_iperf( if endnode_ip == '': raise RuntimeError('End node IP address not found') client_res = endnode.exec_cmd( - 'iperf -u -c %s -t %i -i 1 -b %iM --ttl 5 -B %s' % (server_ip, interval, bandwidth_lim, endnode_ip) + f'iperf -u -c {server_ip} -t {interval} -i 1 -b {bandwidth_lim}M --ttl 5 -B {endnode_ip}' ) if server_proc.wait(10) is None: # Process did not finish. server_proc.terminate() else: # Configure Server server_proc = subprocess.Popen( - ['iperf', '%s' % proto, '-s', '-i', '1', '-t', '%i' % interval], + ['iperf', proto, '-s', '-i', '1', '-t', str(interval)], text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) # Configure Client - client_res = endnode.exec_cmd('iperf %s -c %s -t %i -i 1 -b %iM' % (proto, server_ip, interval, bandwidth_lim)) + client_res = endnode.exec_cmd(f'iperf {proto} -c {server_ip} -t {interval} -i 1 -b {bandwidth_lim}M') if server_proc.wait(10) is None: # Process did not finish. server_proc.terminate() @@ -243,8 +240,8 @@ def send_brcast_msg_host_to_endnode(endnode: EndnodeSsh, host_brcast_ip: str, te try: sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) sock.sendto(test_msg.encode('utf-8'), (host_brcast_ip, 5100)) - except socket.error as e: - raise Exception('Host brcast send failed %s' % e) + except OSError as e: + raise Exception(f'Host brcast send failed {e}') nc_endnode_out = endnode.get_async_res() sock.close() @@ -253,18 +250,24 @@ def send_brcast_msg_host_to_endnode(endnode: EndnodeSsh, host_brcast_ip: str, te def send_brcast_msg_endnode_to_host(endnode: EndnodeSsh, host_brcast_ip: str, test_msg: str) -> str: sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # Allow binding if port still in TIME_WAIT sock.settimeout(5) try: sock.bind(('', 5100)) - except socket.error as e: - raise Exception('Host bind failed %s' % e) + # Give socket time to be fully ready to receive before we tell endnode to send. + # Even with SSH latency, there's a small window where a fast-received packet could be dropped. + time.sleep(0.1) + except OSError as e: + raise Exception(f'Host bind failed {e}') - endnode.exec_cmd('echo -n "%s" | nc -b -w0 -u %s 5100' % (test_msg, host_brcast_ip)) + endnode.exec_cmd(f'echo -n "{test_msg}" | nc -b -w0 -u {host_brcast_ip} 5100') try: nc_host_out = sock.recv(1500).decode('utf-8') - except socket.error as e: - raise Exception('Host recv failed %s', e) + except TimeoutError: + raise Exception('Host recv timed out after 5 seconds') + except OSError as e: + raise Exception(f'Host recv failed {e}') sock.close() return nc_host_out @@ -430,16 +433,15 @@ def test_esp_eth_bridge(dut: Dut, dev_user: str, dev_password: str) -> None: if bandwidth_udp < MIN_UDP_THROUGHPUT: raise RuntimeError( - 'Unicast UDP throughput expected %.2f, actual %.2f' % (MIN_UDP_THROUGHPUT, bandwidth_udp) + ' Mbits/s' + f'Unicast UDP throughput expected {MIN_UDP_THROUGHPUT:.2f}, actual {bandwidth_udp:.2f} Mbits/s' ) if bandwidth_tcp < MIN_TCP_THROUGHPUT: raise RuntimeError( - 'Unicast TCP throughput expected %.2f, actual %.2f' % (MIN_TCP_THROUGHPUT, bandwidth_tcp) + ' Mbits/s' + f'Unicast TCP throughput expected {MIN_TCP_THROUGHPUT:.2f}, actual {bandwidth_tcp:.2f} Mbits/s' ) if bandwidth_mcast_udp < MIN_UDP_THROUGHPUT: raise RuntimeError( - 'Multicast UDP throughput expected %.2f, actual %.2f' % (MIN_UDP_THROUGHPUT, bandwidth_mcast_udp) - + ' Mbits/s' + f'Multicast UDP throughput expected {MIN_UDP_THROUGHPUT:.2f}, actual {bandwidth_mcast_udp:.2f} Mbits/s' ) # ------------------------------------------------ @@ -493,7 +495,7 @@ def test_esp_eth_bridge(dut: Dut, dev_user: str, dev_password: str) -> None: # try to add more FDB entries than configured max number for i in range(BR_PORTS_NUM + 1): - dut.write('add --addr=01:02:03:00:00:%02x' % i + ' -d') + dut.write(f'add --addr=01:02:03:00:00:{i:02x} -d') if i < BR_PORTS_NUM: dut.expect_exact('Bridge Config OK!') else: @@ -507,7 +509,7 @@ def test_esp_eth_bridge(dut: Dut, dev_user: str, dev_password: str) -> None: # remove dummy entries for i in range(BR_PORTS_NUM): - dut.write('remove --addr=01:02:03:00:00:%02x' % i) + dut.write(f'remove --addr=01:02:03:00:00:{i:02x}') dut.expect_exact('Bridge Config OK!') # valid multiple ports at once From eeadc96949d66b74cd4f267e6e0550eff235b74d Mon Sep 17 00:00:00 2001 From: Ondrej Kosta Date: Thu, 23 Oct 2025 15:30:15 +0200 Subject: [PATCH 020/106] fix(esp_eth): made LAN8720 test write register function more robust --- .../test_apps/main/esp_eth_test_apps.c | 108 +++++++++++++----- .../test_apps/main/esp_eth_test_common.c | 3 + .../esp_eth/test_apps/main/idf_component.yml | 3 + .../test_apps/sdkconfig.ci.default_lan8720 | 11 ++ 4 files changed, 96 insertions(+), 29 deletions(-) create mode 100644 components/esp_eth/test_apps/main/idf_component.yml create mode 100644 components/esp_eth/test_apps/sdkconfig.ci.default_lan8720 diff --git a/components/esp_eth/test_apps/main/esp_eth_test_apps.c b/components/esp_eth/test_apps/main/esp_eth_test_apps.c index 4b1346659ba..11a9721bb67 100644 --- a/components/esp_eth/test_apps/main/esp_eth_test_apps.c +++ b/components/esp_eth/test_apps/main/esp_eth_test_apps.c @@ -94,6 +94,82 @@ TEST_CASE("ethernet io test", "[ethernet]") extra_cleanup(); } +#ifdef CONFIG_TARGET_ETH_PHY_DEVICE_LAN8720 +esp_err_t set_phy_reg_bits(esp_eth_handle_t eth_handle, uint32_t reg_addr, uint32_t bitmask, uint32_t max_attempts) +{ + esp_eth_phy_reg_rw_data_t reg = { + .reg_addr = reg_addr, + .reg_value_p = NULL + }; + uint32_t reg_value, reg_value_rb; + + for (uint32_t i = 0; i < max_attempts; i++) { + reg.reg_value_p = ®_value; + esp_err_t ret = esp_eth_ioctl(eth_handle, ETH_CMD_READ_PHY_REG, ®); + if (ret != ESP_OK) { + return ret; + } + reg_value |= bitmask; + ret = esp_eth_ioctl(eth_handle, ETH_CMD_WRITE_PHY_REG, ®); + if (ret != ESP_OK) { + return ret; + } + reg.reg_value_p = ®_value_rb; + ret = esp_eth_ioctl(eth_handle, ETH_CMD_READ_PHY_REG, ®); + if (ret != ESP_OK) { + return ret; + } + // Check if the write was successful + if ((reg_value_rb & bitmask) == bitmask) { + return ESP_OK; + } + // Add delay only if not the last attempt + if (i < max_attempts - 1) { + ESP_LOGW(TAG, "Setting PHY register %04"PRIx32" failed, retrying... (attempt %"PRIu32" of %"PRIu32")", reg_addr, i + 1, max_attempts); + vTaskDelay(pdMS_TO_TICKS(10)); + } + } + return ESP_ERR_TIMEOUT; +} + +esp_err_t clear_phy_reg_bits(esp_eth_handle_t eth_handle, uint32_t reg_addr, uint32_t bitmask, uint32_t max_attempts) +{ + esp_eth_phy_reg_rw_data_t reg = { + .reg_addr = reg_addr, + .reg_value_p = NULL + }; + uint32_t reg_value, reg_value_rb; + + for (uint32_t i = 0; i < max_attempts; i++) { + reg.reg_value_p = ®_value; + esp_err_t ret = esp_eth_ioctl(eth_handle, ETH_CMD_READ_PHY_REG, ®); + if (ret != ESP_OK) { + return ret; + } + reg_value &= ~bitmask; + ret = esp_eth_ioctl(eth_handle, ETH_CMD_WRITE_PHY_REG, ®); + if (ret != ESP_OK) { + return ret; + } + reg.reg_value_p = ®_value_rb; + ret = esp_eth_ioctl(eth_handle, ETH_CMD_READ_PHY_REG, ®); + if (ret != ESP_OK) { + return ret; + } + // Check if the write was successful + if ((reg_value_rb & bitmask) == 0) { + return ESP_OK; + } + // Add delay only if not the last attempt + if (i < max_attempts - 1) { + ESP_LOGW(TAG, "Clearing PHY register %04"PRIx32" failed, retrying... (attempt %"PRIu32" of %"PRIu32")", reg_addr, i + 1, max_attempts); + vTaskDelay(pdMS_TO_TICKS(10)); + } + } + return ESP_ERR_TIMEOUT; +} +#endif // CONFIG_TARGET_ETH_PHY_DEVICE_LAN8720 + // This test expects autonegotiation to be enabled on the other node. TEST_CASE("ethernet io speed/duplex/autonegotiation", "[ethernet]") { @@ -168,17 +244,7 @@ TEST_CASE("ethernet io speed/duplex/autonegotiation", "[ethernet]") // Rationale: When the device is in manual 100BASE-TX or 10BASE-T modes with Auto-MDIX enabled, the PHY does not link to a // link partner that is configured for auto-negotiation. See LAN8720 errata for more details. #ifdef CONFIG_TARGET_ETH_PHY_DEVICE_LAN8720 - esp_eth_phy_reg_rw_data_t reg; - uint32_t reg_val; - reg.reg_addr = 27; - reg.reg_value_p = ®_val; - TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_READ_PHY_REG, ®)); - reg_val |= 0x8000; - TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_WRITE_PHY_REG, ®)); - uint32_t reg_val_act; - reg.reg_value_p = ®_val_act; - TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_READ_PHY_REG, ®)); - TEST_ASSERT_EQUAL(reg_val, reg_val_act); + TEST_ESP_OK(set_phy_reg_bits(eth_handle, 27, 0x8000, 3)); #endif // start the driver and wait for connection establish @@ -263,13 +329,7 @@ TEST_CASE("ethernet io speed/duplex/autonegotiation", "[ethernet]") // *** LAN8720 deviation *** // Rationale: See above #ifdef CONFIG_TARGET_ETH_PHY_DEVICE_LAN8720 - reg.reg_value_p = ®_val; - TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_READ_PHY_REG, ®)); - reg_val &= ~0x8000; - TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_WRITE_PHY_REG, ®)); - reg.reg_value_p = ®_val_act; - TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_READ_PHY_REG, ®)); - TEST_ASSERT_EQUAL(reg_val, reg_val_act); + TEST_ESP_OK(clear_phy_reg_bits(eth_handle, 27, 0x8000, 3)); #endif esp_eth_start(eth_handle); @@ -568,17 +628,7 @@ TEST_CASE("ethernet start/stop stress test with IP stack", "[ethernet]") // Rationale: When the device is in manual 100BASE-TX or 10BASE-T modes with Auto-MDIX enabled, the PHY does not link to a // link partner that is configured for auto-negotiation. See LAN8720 errata for more details. #ifdef CONFIG_TARGET_ETH_PHY_DEVICE_LAN8720 - esp_eth_phy_reg_rw_data_t reg; - uint32_t reg_val; - reg.reg_addr = 27; - reg.reg_value_p = ®_val; - TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_READ_PHY_REG, ®)); - reg_val |= 0x8000; - TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_WRITE_PHY_REG, ®)); - uint32_t reg_val_act; - reg.reg_value_p = ®_val_act; - TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_READ_PHY_REG, ®)); - TEST_ASSERT_EQUAL(reg_val, reg_val_act); + TEST_ESP_OK(set_phy_reg_bits(eth_handle, 27, 0x8000, 3)); #endif } for (int i = 0; i < 10; i++) { diff --git a/components/esp_eth/test_apps/main/esp_eth_test_common.c b/components/esp_eth/test_apps/main/esp_eth_test_common.c index 2e695c1fa7a..edfb7480b0d 100644 --- a/components/esp_eth/test_apps/main/esp_eth_test_common.c +++ b/components/esp_eth/test_apps/main/esp_eth_test_common.c @@ -14,6 +14,9 @@ #endif // CONFIG_TARGET_USE_SPI_ETHERNET #include "sdkconfig.h" #include "esp_eth_test_common.h" +#if CONFIG_TARGET_ETH_PHY_DEVICE_LAN8720 +#include "esp_eth_phy_lan87xx.h" +#endif // CONFIG_TARGET_ETH_PHY_DEVICE_LAN8720 #if CONFIG_TARGET_USE_SPI_ETHERNET #define DEFAULT_TARGET_SPI_HOST 1 diff --git a/components/esp_eth/test_apps/main/idf_component.yml b/components/esp_eth/test_apps/main/idf_component.yml new file mode 100644 index 00000000000..4644e55803d --- /dev/null +++ b/components/esp_eth/test_apps/main/idf_component.yml @@ -0,0 +1,3 @@ +## IDF Component Manager Manifest File +dependencies: + espressif/lan87xx: ^1.0.0 diff --git a/components/esp_eth/test_apps/sdkconfig.ci.default_lan8720 b/components/esp_eth/test_apps/sdkconfig.ci.default_lan8720 new file mode 100644 index 00000000000..195e3d514e0 --- /dev/null +++ b/components/esp_eth/test_apps/sdkconfig.ci.default_lan8720 @@ -0,0 +1,11 @@ +CONFIG_IDF_TARGET="esp32" + +CONFIG_UNITY_ENABLE_FIXTURE=y +CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y +CONFIG_ETH_USE_ESP32_EMAC=y +CONFIG_ESP_TASK_WDT_EN=n + +CONFIG_TARGET_USE_INTERNAL_ETHERNET=y +CONFIG_TARGET_ETH_PHY_DEVICE_LAN8720=y +CONFIG_TARGET_RMII_CLK_OUT=y +CONFIG_TARGET_RMII_CLK_OUT_GPIO=17 From fea4723a113ff9d6bc60f98b66db0fa13de72311 Mon Sep 17 00:00:00 2001 From: "hrushikesh.bhosale" Date: Mon, 3 Nov 2025 14:43:04 +0530 Subject: [PATCH 021/106] fix(http_server): Fixed response status code for temporary redirect Closes https://github.com/espressif/esp-idf/issues/17791 --- examples/protocols/http_server/captive_portal/main/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/protocols/http_server/captive_portal/main/main.c b/examples/protocols/http_server/captive_portal/main/main.c index 787003c4ea7..b52040e1dde 100644 --- a/examples/protocols/http_server/captive_portal/main/main.c +++ b/examples/protocols/http_server/captive_portal/main/main.c @@ -127,7 +127,7 @@ static const httpd_uri_t root = { esp_err_t http_404_error_handler(httpd_req_t *req, httpd_err_code_t err) { // Set status - httpd_resp_set_status(req, "302 Temporary Redirect"); + httpd_resp_set_status(req, "303 See Other"); // Redirect to the "/" root directory httpd_resp_set_hdr(req, "Location", "/"); // iOS requires content in the response to detect a captive portal, simply redirecting is not sufficient. From bc7161e9645baba4ff855549e6b677564daff74a Mon Sep 17 00:00:00 2001 From: Chen Jian Hua Date: Wed, 5 Nov 2025 13:33:25 +0800 Subject: [PATCH 022/106] feat(bt): Update bt lib for ESP32-C3 and ESP32-S3(0871069) - Added more log for BLE - Support BLE log filter and simeple output - Support BLE log compression (cherry picked from commit 03758ba550d1eec11b3f00ecc00341e2f53cd2e3) Co-authored-by: chenjianhua --- components/bt/controller/esp32c3/Kconfig.in | 8 +-- components/bt/controller/esp32c3/bt.c | 62 ++++++++++--------- components/bt/controller/lib_esp32c3_family | 2 +- .../bt/include/esp32c3/include/esp_bt.h | 6 +- 4 files changed, 38 insertions(+), 40 deletions(-) diff --git a/components/bt/controller/esp32c3/Kconfig.in b/components/bt/controller/esp32c3/Kconfig.in index d9f1bcc05d7..6a7b9107171 100644 --- a/components/bt/controller/esp32c3/Kconfig.in +++ b/components/bt/controller/esp32c3/Kconfig.in @@ -616,15 +616,15 @@ menu "Controller debug log Options (Experimental)" config BT_CTRL_LE_LOG_MODE_EN depends on BT_CTRL_LE_LOG_EN - int "Enable log for specified BLE mode" - range 0 4095 - default 4093 + hex "Enable log for specified BLE mode" + range 0 0xFFFF + default 0xDB7F config BT_CTRL_LE_LOG_LEVEL depends on BT_CTRL_LE_LOG_EN int "The level of BLE log" range 0 5 - default 2 + default 1 config BT_CTRL_LE_LOG_BUF1_SIZE depends on BT_CTRL_LE_LOG_EN diff --git a/components/bt/controller/esp32c3/bt.c b/components/bt/controller/esp32c3/bt.c index ea2bffaec66..b3aa8def98b 100644 --- a/components/bt/controller/esp32c3/bt.c +++ b/components/bt/controller/esp32c3/bt.c @@ -241,7 +241,12 @@ struct osi_funcs_t { }; #if CONFIG_BT_CTRL_LE_LOG_EN -typedef void (*interface_func_t) (uint32_t len, const uint8_t*addr, bool end); +typedef void (*interface_func_t) (uint32_t len, const uint8_t *addr, uint32_t len_append, const uint8_t *addr_append, uint32_t flag); + +enum { + BLE_LOG_INTERFACE_FLAG_CONTINUE = 0, + BLE_LOG_INTERFACE_FLAG_END, +}; #endif // CONFIG_BT_CTRL_LE_LOG_EN /* External functions or values @@ -304,11 +309,14 @@ extern void btdm_aa_check_enhance_enable(void); /* BLE Log module */ #if CONFIG_BT_CTRL_LE_LOG_EN +extern int r_ble_log_init_simple(interface_func_t interface, void *handler); +extern void r_ble_log_deinit_simple(void); extern int r_ble_log_init_async(interface_func_t bt_controller_log_interface, bool task_create, uint8_t buffers, uint32_t *bufs_size); extern int r_ble_log_deinit_async(void); extern void r_ble_log_async_select_dump_buffers(uint8_t buffers); extern void r_ble_log_async_output_dump_all(bool output); extern void esp_panic_handler_feed_wdts(void); +extern int r_ble_log_ctrl_level_and_mod(uint8_t level, uint32_t mod_en); #endif // CONFIG_BT_CTRL_LE_LOG_EN #if (CONFIG_BT_BLUEDROID_ENABLED || CONFIG_BT_NIMBLE_ENABLED) extern void scan_stack_enableAdvFlowCtrlVsCmd(bool en); @@ -399,12 +407,13 @@ static esp_err_t try_heap_caps_add_region(intptr_t start, intptr_t end); static void bt_controller_deinit_internal(void); #if CONFIG_BT_CTRL_LE_LOG_EN -static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, bool end); +#if !CONFIG_BT_CTRL_LE_LOG_MODE_BLE_LOG_V2 #if CONFIG_BT_CTRL_LE_LOG_STORAGE_EN void esp_bt_read_ctrl_log_from_flash(bool output); static int esp_bt_controller_log_storage(uint32_t len, const uint8_t *addr, bool end); static void esp_bt_ctrl_log_partition_get_and_erase_first_block(void); -#endif // #if CONFIG_BT_CTRL_LE_LOG_STORAGE_EN +#endif // CONFIG_BT_CTRL_LE_LOG_STORAGE_EN +#endif // !CONFIG_BT_CTRL_LE_LOG_MODE_BLE_LOG_V2 #endif // CONFIG_BT_CTRL_LE_LOG_EN /* Local variable definition @@ -538,18 +547,14 @@ static bool is_filled = false; #endif // CONFIG_BT_CTRL_LE_LOG_STORAGE_EN #if CONFIG_BT_CTRL_LE_LOG_MODE_BLE_LOG_V2 -static IRAM_ATTR void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, bool end) -{ - ble_log_write_hex_ll(len, addr, 0, NULL, 0); -} - void esp_ble_controller_log_dump_all(bool output) { ble_log_dump_to_console(); } #else /* !CONFIG_BT_CTRL_LE_LOG_MODE_BLE_LOG_V2 */ -static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, bool end) +static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, uint32_t len_append, const uint8_t *addr_append, uint32_t flag) { + bool end = (flag & BIT(BLE_LOG_INTERFACE_FLAG_END)); if (log_output_mode == LOG_STORAGE_TO_FLASH) { #if CONFIG_BT_CTRL_LE_LOG_STORAGE_EN esp_bt_controller_log_storage(len, addr, end); @@ -558,24 +563,19 @@ static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, b portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; portENTER_CRITICAL_SAFE(&spinlock); esp_panic_handler_feed_wdts(); - for (int i = 0; i < len; i++) { - esp_rom_printf("%02x ", addr[i]); - } - if (end) { - esp_rom_printf("\n"); + if (len && addr) { + for (int i = 0; i < len; i++) { esp_rom_printf("%02x ", addr[i]); } } + if (len_append && addr_append) { + for (int i = 0; i < len_append; i++) { esp_rom_printf("%02x ", addr_append[i]); } + } + if (end) { esp_rom_printf("\n"); } + portEXIT_CRITICAL_SAFE(&spinlock); } } -#if CONFIG_BT_CTRL_LE_LOG_SPI_OUT_EN -static IRAM_ATTR void esp_bt_controller_spi_log_interface(uint32_t len, const uint8_t *addr, bool end) -{ - ble_log_spi_out_ll_write(len, addr, 0, NULL, 0); -} -#endif // CONFIG_BT_CTRL_LE_LOG_SPI_OUT_EN - void esp_ble_controller_log_dump_all(bool output) { if (log_output_mode == LOG_STORAGE_TO_FLASH) { @@ -612,16 +612,13 @@ esp_err_t esp_bt_controller_log_init(uint8_t log_output_mode) } esp_err_t ret = ESP_OK; - uint8_t buffers = 0; -#if CONFIG_BT_CTRL_LE_LOG_EN - buffers |= ESP_BLE_LOG_BUF_CONTROLLER; -#endif // CONFIG_BT_CTRL_LE_LOG_EN -#if CONFIG_BT_CTRL_LE_HCI_LOG_EN - buffers |= ESP_BLE_LOG_BUF_HCI; -#endif // CONFIG_BT_CTRL_LE_HCI_LOG_EN + ret = r_ble_log_init_simple(ble_log_write_hex_ll, NULL); + if (ret != ESP_OK) { + return ret; + } - ret = r_ble_log_init_async(esp_bt_controller_log_interface, true, buffers, (uint32_t *)log_bufs_size); + ret = r_ble_log_ctrl_level_and_mod(BLE_LOG_LEVEL, BLE_LOG_MODE_EN); if (ret == ESP_OK) { log_is_inited = true; } @@ -664,7 +661,7 @@ esp_err_t esp_bt_controller_log_init(uint8_t log_output_mode) case LOG_SPI_OUT: task_create = true; #if CONFIG_BT_CTRL_LE_LOG_SPI_OUT_EN - bt_controller_log_interface = esp_bt_controller_spi_log_interface; + bt_controller_log_interface = ble_log_spi_out_ll_write; #endif // CONFIG_BT_CTRL_LE_LOG_SPI_OUT_EN break; default: @@ -672,6 +669,11 @@ esp_err_t esp_bt_controller_log_init(uint8_t log_output_mode) } ret = r_ble_log_init_async(bt_controller_log_interface, task_create, buffers, (uint32_t *)log_bufs_size); + if (ret != ESP_OK) { + return ret; + } + + ret = r_ble_log_ctrl_level_and_mod(BLE_LOG_LEVEL, BLE_LOG_MODE_EN); if (ret == ESP_OK) { log_is_inited = true; } diff --git a/components/bt/controller/lib_esp32c3_family b/components/bt/controller/lib_esp32c3_family index 42c965137ec..099a7e1ab87 160000 --- a/components/bt/controller/lib_esp32c3_family +++ b/components/bt/controller/lib_esp32c3_family @@ -1 +1 @@ -Subproject commit 42c965137ecc3c6cf3d38ecece7ce71ffc461353 +Subproject commit 099a7e1ab87dd977754fc4ad35678ab7ebf2f2a2 diff --git a/components/bt/include/esp32c3/include/esp_bt.h b/components/bt/include/esp32c3/include/esp_bt.h index 86c902fc9bb..78daf08428e 100644 --- a/components/bt/include/esp32c3/include/esp_bt.h +++ b/components/bt/include/esp32c3/include/esp_bt.h @@ -30,7 +30,7 @@ extern "C" { * * @note Please do not modify this value */ -#define ESP_BT_CTRL_CONFIG_VERSION 0x02505080 +#define ESP_BT_CTRL_CONFIG_VERSION 0x02509280 /** * @brief Internal use only @@ -376,8 +376,6 @@ typedef void (* esp_bt_hci_tl_callback_t) (void *arg, uint8_t status); .connect_en = BT_CTRL_BLE_MASTER, \ .scan_en = BT_CTRL_BLE_SCAN, \ .ble_aa_check = BLE_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS_ENABLED, \ - .ble_log_mode_en = BLE_LOG_MODE_EN, \ - .ble_log_level = BLE_LOG_LEVEL, \ .adv_en = BT_CTRL_BLE_ADV, \ } @@ -504,8 +502,6 @@ typedef struct { bool connect_en; /*!< True if the connection feature is enabled (default); false otherwise. Configurable in menuconfig.*/ bool scan_en; /*!< True if the scan feature is enabled (default); false otherwise. Configurable in menuconfig.*/ bool ble_aa_check; /*!< True if adds a verification step for the Access Address within the CONNECT_IND PDU; false otherwise. Configurable in menuconfig */ - uint32_t ble_log_mode_en; /*!< BLE log mode enable */ - uint8_t ble_log_level; /*!< BLE log level */ bool adv_en; /*!< True if the ADV feature is enabled (default); false otherwise. Configurable in menuconfig.*/ } esp_bt_controller_config_t; From 6133fb671f3b66aee19abaf7559325f659aea07b Mon Sep 17 00:00:00 2001 From: Chen Jian Hua Date: Wed, 5 Nov 2025 13:33:25 +0800 Subject: [PATCH 023/106] feat(ble): Enable get bt ts for ESP32-C3 and ESP32-S3 (cherry picked from commit b870a8fb5afb278ea29bbf70744589e41cdfe26a) Co-authored-by: chenjianhua --- components/bt/common/ble_log/ble_log_spi_out.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/components/bt/common/ble_log/ble_log_spi_out.c b/components/bt/common/ble_log/ble_log_spi_out.c index e6ca8d7a440..c59455c2ffc 100644 --- a/components/bt/common/ble_log/ble_log_spi_out.c +++ b/components/bt/common/ble_log/ble_log_spi_out.c @@ -247,9 +247,9 @@ extern uint32_t r_ble_lll_timer_current_tick_get(void); #elif defined(CONFIG_IDF_TARGET_ESP32C2) extern uint32_t r_os_cputime_get32(void); #define SPI_OUT_GET_LC_TIME r_os_cputime_get32() -// #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S3) -// extern uint32_t lld_read_clock_us(void); -// #define SPI_OUT_GET_LC_TIME lld_read_clock_us() +#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S3) +extern uint32_t lld_read_clock_us(void); +#define SPI_OUT_GET_LC_TIME lld_read_clock_us() #else #define SPI_OUT_GET_LC_TIME esp_timer_get_time() #endif From 7a828d8914eceb4360c3a0e914ad766b8e9348c7 Mon Sep 17 00:00:00 2001 From: Chen Jian Hua Date: Wed, 5 Nov 2025 13:33:25 +0800 Subject: [PATCH 024/106] feat(ble): make ble log task stack size configurable (cherry picked from commit b525e6555b153deff11d9dc5365036eee3a5f9ee) Co-authored-by: Zhou Xiao --- components/bt/common/ble_log/Kconfig.in | 6 ++++++ .../bt/common/ble_log/src/internal_include/ble_log_rt.h | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/components/bt/common/ble_log/Kconfig.in b/components/bt/common/ble_log/Kconfig.in index dfbd4711783..f3a5e5348a7 100644 --- a/components/bt/common/ble_log/Kconfig.in +++ b/components/bt/common/ble_log/Kconfig.in @@ -5,6 +5,12 @@ config BLE_LOG_ENABLED Enable BLE Log Module if BLE_LOG_ENABLED + config BLE_LOG_TASK_STACK_SIZE + int "Stack size for BLE Log Task" + default 1024 + help + Stack size for BLE Log Task + config BLE_LOG_LBM_TRANS_SIZE int "Buffer size for each peripheral transport" default 512 diff --git a/components/bt/common/ble_log/src/internal_include/ble_log_rt.h b/components/bt/common/ble_log/src/internal_include/ble_log_rt.h index f053049339f..ae8b4b05a37 100644 --- a/components/bt/common/ble_log/src/internal_include/ble_log_rt.h +++ b/components/bt/common/ble_log/src/internal_include/ble_log_rt.h @@ -21,7 +21,7 @@ /* MACRO */ #define BLE_LOG_TASK_PRIO (ESP_TASK_PRIO_MAX - 1) -#define BLE_LOG_TASK_STACK_SIZE (1024) +#define BLE_LOG_TASK_STACK_SIZE CONFIG_BLE_LOG_TASK_STACK_SIZE #define BLE_LOG_TASK_HOOK_TIMEOUT_MS (1000) /* INTERFACE */ From 8b91bf577a4e6f28c0db791343fff779de3b9a77 Mon Sep 17 00:00:00 2001 From: Rasmus Buurman Date: Wed, 5 Nov 2025 00:18:03 +0100 Subject: [PATCH 025/106] fix(examples): Fix typos in NimBLE example comments --- .../ble_get_started/nimble/NimBLE_Beacon/main/src/gap.c | 4 ++-- .../ble_get_started/nimble/NimBLE_Connection/main/src/gap.c | 4 ++-- .../ble_get_started/nimble/NimBLE_GATT_Server/main/src/gap.c | 4 ++-- .../ble_get_started/nimble/NimBLE_Security/main/src/gap.c | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/bluetooth/ble_get_started/nimble/NimBLE_Beacon/main/src/gap.c b/examples/bluetooth/ble_get_started/nimble/NimBLE_Beacon/main/src/gap.c index 71e03ba7c2a..8243ecf3341 100644 --- a/examples/bluetooth/ble_get_started/nimble/NimBLE_Beacon/main/src/gap.c +++ b/examples/bluetooth/ble_get_started/nimble/NimBLE_Beacon/main/src/gap.c @@ -51,7 +51,7 @@ static void start_advertising(void) { adv_fields.le_role = BLE_GAP_LE_ROLE_PERIPHERAL; adv_fields.le_role_is_present = 1; - /* Set advertiement fields */ + /* Set advertisement fields */ rc = ble_gap_adv_set_fields(&adv_fields); if (rc != 0) { ESP_LOGE(TAG, "failed to set advertising data, error code: %d", rc); @@ -74,7 +74,7 @@ static void start_advertising(void) { return; } - /* Set non-connetable and general discoverable mode to be a beacon */ + /* Set non-connectable and general discoverable mode to be a beacon */ adv_params.conn_mode = BLE_GAP_CONN_MODE_NON; adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN; diff --git a/examples/bluetooth/ble_get_started/nimble/NimBLE_Connection/main/src/gap.c b/examples/bluetooth/ble_get_started/nimble/NimBLE_Connection/main/src/gap.c index 8788b66f267..68fffcaafba 100644 --- a/examples/bluetooth/ble_get_started/nimble/NimBLE_Connection/main/src/gap.c +++ b/examples/bluetooth/ble_get_started/nimble/NimBLE_Connection/main/src/gap.c @@ -80,7 +80,7 @@ static void start_advertising(void) { adv_fields.le_role = BLE_GAP_LE_ROLE_PERIPHERAL; adv_fields.le_role_is_present = 1; - /* Set advertiement fields */ + /* Set advertisement fields */ rc = ble_gap_adv_set_fields(&adv_fields); if (rc != 0) { ESP_LOGE(TAG, "failed to set advertising data, error code: %d", rc); @@ -107,7 +107,7 @@ static void start_advertising(void) { return; } - /* Set non-connetable and general discoverable mode to be a beacon */ + /* Set undirected connectable and general discoverable mode */ adv_params.conn_mode = BLE_GAP_CONN_MODE_UND; adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN; diff --git a/examples/bluetooth/ble_get_started/nimble/NimBLE_GATT_Server/main/src/gap.c b/examples/bluetooth/ble_get_started/nimble/NimBLE_GATT_Server/main/src/gap.c index 8519028a5d0..7c7b3dde2ad 100644 --- a/examples/bluetooth/ble_get_started/nimble/NimBLE_GATT_Server/main/src/gap.c +++ b/examples/bluetooth/ble_get_started/nimble/NimBLE_GATT_Server/main/src/gap.c @@ -80,7 +80,7 @@ static void start_advertising(void) { adv_fields.le_role = BLE_GAP_LE_ROLE_PERIPHERAL; adv_fields.le_role_is_present = 1; - /* Set advertiement fields */ + /* Set advertisement fields */ rc = ble_gap_adv_set_fields(&adv_fields); if (rc != 0) { ESP_LOGE(TAG, "failed to set advertising data, error code: %d", rc); @@ -107,7 +107,7 @@ static void start_advertising(void) { return; } - /* Set non-connetable and general discoverable mode to be a beacon */ + /* Set undirected connectable and general discoverable mode */ adv_params.conn_mode = BLE_GAP_CONN_MODE_UND; adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN; diff --git a/examples/bluetooth/ble_get_started/nimble/NimBLE_Security/main/src/gap.c b/examples/bluetooth/ble_get_started/nimble/NimBLE_Security/main/src/gap.c index d4e7c249b68..55c34487eb9 100644 --- a/examples/bluetooth/ble_get_started/nimble/NimBLE_Security/main/src/gap.c +++ b/examples/bluetooth/ble_get_started/nimble/NimBLE_Security/main/src/gap.c @@ -95,7 +95,7 @@ static void start_advertising(void) { adv_fields.le_role = BLE_GAP_LE_ROLE_PERIPHERAL; adv_fields.le_role_is_present = 1; - /* Set advertiement fields */ + /* Set advertisement fields */ rc = ble_gap_adv_set_fields(&adv_fields); if (rc != 0) { ESP_LOGE(TAG, "failed to set advertising data, error code: %d", rc); @@ -122,7 +122,7 @@ static void start_advertising(void) { return; } - /* Set non-connetable and general discoverable mode to be a beacon */ + /* Set undirected connectable and general discoverable mode */ adv_params.conn_mode = BLE_GAP_CONN_MODE_UND; adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN; From f67e76d641b0b5fbe0d70b7c07f323e4b99dd4b7 Mon Sep 17 00:00:00 2001 From: Sudeep Mohanty Date: Mon, 3 Nov 2025 11:24:45 +0800 Subject: [PATCH 026/106] test(freertos): Added miscellaneous stability fixes to unit tests This commit adds fixes for freertos unit tests for a more deterministic run and avoid occational failures. --- .../kernel/tasks/test_freertos_psram.c | 3 ++ .../test_vTaskSuspendAll_xTaskResumeAll.c | 1 + .../freertos/kernel/tasks/test_yielding.c | 33 +++++++++++++------ .../freertos/misc/test_tickless_idle.c | 7 ++-- 4 files changed, 32 insertions(+), 12 deletions(-) diff --git a/components/freertos/test_apps/freertos/kernel/tasks/test_freertos_psram.c b/components/freertos/test_apps/freertos/kernel/tasks/test_freertos_psram.c index 866b4e4bba4..ea6413883e3 100644 --- a/components/freertos/test_apps/freertos/kernel/tasks/test_freertos_psram.c +++ b/components/freertos/test_apps/freertos/kernel/tasks/test_freertos_psram.c @@ -140,6 +140,9 @@ TEST_CASE("Task on specific core works", "[freertos][psram]") TEST_ASSERT_EQUAL((size_t) corenum, corenum_info.recorded_core_num); vTaskDelete(task_handle); + + // Add a short delay to allow the idle task to free any remaining task memory + vTaskDelay(10); } } #endif // !CONFIG_FREERTOS_UNICORE diff --git a/components/freertos/test_apps/freertos/kernel/tasks/test_vTaskSuspendAll_xTaskResumeAll.c b/components/freertos/test_apps/freertos/kernel/tasks/test_vTaskSuspendAll_xTaskResumeAll.c index e6dd88c7aa6..746540bc020 100644 --- a/components/freertos/test_apps/freertos/kernel/tasks/test_vTaskSuspendAll_xTaskResumeAll.c +++ b/components/freertos/test_apps/freertos/kernel/tasks/test_vTaskSuspendAll_xTaskResumeAll.c @@ -394,6 +394,7 @@ TEST_CASE("Test vTaskSuspendAll allows scheduling on other cores", "[freertos]") // Cleanup tasks vTaskDelete(a1_task_hdl); vTaskDelete(b1_task_hdl); + vTaskDelay(10); } vSemaphoreDelete(test_unblk_done_sem); diff --git a/components/freertos/test_apps/freertos/kernel/tasks/test_yielding.c b/components/freertos/test_apps/freertos/kernel/tasks/test_yielding.c index 6da218976f7..9d5d7b2c5e6 100644 --- a/components/freertos/test_apps/freertos/kernel/tasks/test_yielding.c +++ b/components/freertos/test_apps/freertos/kernel/tasks/test_yielding.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -34,6 +34,9 @@ static volatile uint32_t count; // Lock variable to create a blocked task scenario static volatile SemaphoreHandle_t task_mutex; +// Semaphore to synchronize yield test tasks +static SemaphoreHandle_t yield_sync_sem; + // This helper macro is used to store the task id atomically #define STORE_TASK_ID(task_id) ({ \ portENTER_CRITICAL(&idx_lock); \ @@ -56,10 +59,11 @@ static void yield_task1(void *arg) /* Store task_id in the sequence array */ STORE_TASK_ID(task_id); - /* Notify the yield_task2 to run */ - task_sequence_ready = true; + /* Give semaphore to unblock yield_task2, making it READY (not just setting a flag). + * This ensures task2 is in the ready queue when we yield. */ + xSemaphoreGive(yield_sync_sem); - /* Yield */ + /* Yield - now task2 is guaranteed to be READY and should run next */ taskYIELD(); /* Increment task count to notify unity task */ @@ -73,10 +77,9 @@ static void yield_task2(void *arg) { uint32_t task_id = (uint32_t)arg; - /* Wait for the other task to run for the test to begin */ - while (!task_sequence_ready) { - vTaskDelay(10); - }; + /* Block on semaphore - this ensures task1 runs first and we don't poll. + * When task1 gives the semaphore, we transition directly to READY state. */ + xSemaphoreTake(yield_sync_sem, portMAX_DELAY); /* Store task_id in the sequence array */ STORE_TASK_ID(task_id); @@ -108,9 +111,16 @@ TEST_CASE("Task yield must run the next ready task of the same priority", "[free /* Reset task sequence flag */ task_sequence_ready = false; - /* Create test tasks */ - xTaskCreatePinnedToCore(yield_task1, "yield_task1", 2048, (void *)1, UNITY_FREERTOS_PRIORITY - 1, NULL, UNITY_FREERTOS_CPU); + /* Create semaphore for synchronization - start empty so task2 blocks */ + yield_sync_sem = xSemaphoreCreateBinary(); + TEST_ASSERT_NOT_NULL(yield_sync_sem); + + /* Create test tasks - order matters! + * Task2 is created first and will immediately block on the semaphore. + * Task1 is created second and will run first since task2 is blocked. */ xTaskCreatePinnedToCore(yield_task2, "yield_task2", 2048, (void *)2, UNITY_FREERTOS_PRIORITY - 1, NULL, UNITY_FREERTOS_CPU); + vTaskDelay(1); /* Ensure task2 has blocked on semaphore before creating task1 */ + xTaskCreatePinnedToCore(yield_task1, "yield_task1", 2048, (void *)1, UNITY_FREERTOS_PRIORITY - 1, NULL, UNITY_FREERTOS_CPU); /* Wait for the tasks to finish up */ while (count != 2) { @@ -122,6 +132,9 @@ TEST_CASE("Task yield must run the next ready task of the same priority", "[free /* Verify that the yield is successful and the next ready task is run */ TEST_ASSERT_EQUAL(1, task_yield_sequence[idx++]); TEST_ASSERT_EQUAL(2, task_yield_sequence[idx++]); + + /* Clean up semaphore */ + vSemaphoreDelete(yield_sync_sem); } /* diff --git a/components/freertos/test_apps/freertos/misc/test_tickless_idle.c b/components/freertos/test_apps/freertos/misc/test_tickless_idle.c index 7ed64ddf354..aa73b5346c5 100644 --- a/components/freertos/test_apps/freertos/misc/test_tickless_idle.c +++ b/components/freertos/test_apps/freertos/misc/test_tickless_idle.c @@ -10,6 +10,7 @@ #include "freertos/semphr.h" #include "esp_pm.h" #include "esp_private/esp_clk.h" +#include "esp_clk_tree.h" #include "sdkconfig.h" @@ -66,9 +67,11 @@ static void consumer_task(void *arg) TEST_CASE("Test semaphore timeout during tickless idle", "[freertos]") { // Configure tickless idle + uint32_t xtal_hz = 0; + esp_clk_tree_src_get_freq_hz(SOC_MOD_CLK_XTAL, ESP_CLK_TREE_SRC_FREQ_PRECISION_EXACT, &xtal_hz); esp_pm_config_t pm_config = { - .max_freq_mhz = esp_clk_cpu_freq() / MHZ, - .min_freq_mhz = esp_clk_cpu_freq() / MHZ, + .max_freq_mhz = CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ, + .min_freq_mhz = xtal_hz / MHZ, .light_sleep_enable = true, }; TEST_ESP_OK(esp_pm_configure(&pm_config)); From 37e2aad5294442cab4ea2eacf260f513d6c2705f Mon Sep 17 00:00:00 2001 From: yiwenxiu Date: Wed, 22 Oct 2025 19:04:48 +0800 Subject: [PATCH 027/106] feat(openthread): optimize fail cases in CI test --- examples/openthread/ot_ci_function.py | 101 +++++++++++++++++--------- examples/openthread/pytest_otbr.py | 99 +++++++++++++------------ 2 files changed, 119 insertions(+), 81 deletions(-) diff --git a/examples/openthread/ot_ci_function.py b/examples/openthread/ot_ci_function.py index 9c594894c3c..3a5339d3415 100644 --- a/examples/openthread/ot_ci_function.py +++ b/examples/openthread/ot_ci_function.py @@ -19,19 +19,31 @@ from pytest_embedded_idf.dut import IdfDut def extract_address( - command: str, pattern: str, default_return: str = '' + command: str, + pattern: str, + default_return: str = '', + retries: int = 3, + delay: int = 2, ) -> Callable[[Callable[[str], str]], Callable[[IdfDut], str]]: def decorator(func: Callable[[str], str]) -> Callable[[IdfDut], str]: @wraps(func) def wrapper(dut: IdfDut) -> str: - clean_buffer(dut) - execute_command(dut, command) - try: - result = dut.expect(pattern, timeout=5)[1].decode() - except Exception as e: - logging.error(f'Error: {e}') - return default_return - return func(result) + last_exception: Exception | None = None + for attempt in range(1, retries + 1): + try: + clean_buffer(dut) + execute_command(dut, command) + result = dut.expect(pattern, timeout=5)[1].decode() + return func(result) + except Exception as e: + logging.exception(f'[{command}] Attempt {attempt}/{retries} failed: {e}') + last_exception = e + if attempt < retries: + time.sleep(delay) + + if last_exception: + logging.exception(f'[{command}] Giving up after {retries} retries.') + return default_return return wrapper @@ -173,6 +185,12 @@ def init_thread(dut: IdfDut) -> None: reset_thread(dut) +def stop_thread(dut: IdfDut) -> None: + execute_command(dut, 'thread stop') + dut.expect('disabled', timeout=20) + reset_thread(dut) + + def reset_thread(dut: IdfDut) -> None: execute_command(dut, 'factoryreset') dut.expect('OpenThread attached to netif', timeout=20) @@ -180,28 +198,28 @@ def reset_thread(dut: IdfDut) -> None: clean_buffer(dut) +def hardreset_dut(dut: IdfDut) -> None: + dut.serial.hard_reset() + time.sleep(5) + execute_command(dut, 'factoryreset') + + # get the mleid address of the thread -def get_mleid_addr(dut: IdfDut) -> str: - dut_adress = '' - execute_command(dut, 'ipaddr mleid') - dut_adress = dut.expect(r'\n((?:\w+:){7}\w+)\r', timeout=5)[1].decode() - return str(dut_adress) +@extract_address('ipaddr mleid', r'\n((?:\w+:){7}\w+)\r') +def get_mleid_addr(addr: str) -> str: + return addr # get the rloc address of the thread -def get_rloc_addr(dut: IdfDut) -> str: - dut_adress = '' - execute_command(dut, 'ipaddr rloc') - dut_adress = dut.expect(r'\n((?:\w+:){7}\w+)\r', timeout=5)[1].decode() - return str(dut_adress) +@extract_address('ipaddr rloc', r'\n((?:\w+:){7}\w+)\r') +def get_rloc_addr(addr: str) -> str: + return addr # get the linklocal address of the thread -def get_linklocal_addr(dut: IdfDut) -> str: - dut_adress = '' - execute_command(dut, 'ipaddr linklocal') - dut_adress = dut.expect(r'\n((?:\w+:){7}\w+)\r', timeout=5)[1].decode() - return str(dut_adress) +@extract_address('ipaddr linklocal', r'\n((?:\w+:){7}\w+)\r') +def get_linklocal_addr(addr: str) -> str: + return addr # get the global unicast address of the thread: @@ -619,22 +637,19 @@ def decimal_to_hex(decimal_str: str) -> str: return hex_str -def get_omrprefix(br: IdfDut) -> str: - execute_command(br, 'br omrprefix') - omrprefix = br.expect(r'Local: ((?:\w+:){4}):/\d+\r', timeout=5)[1].decode() - return str(omrprefix) +@extract_address('br omrprefix', r'Local: ((?:\w+:){4}):/\d+\r') +def get_omrprefix(addr: str) -> str: + return addr -def get_onlinkprefix(br: IdfDut) -> str: - execute_command(br, 'br onlinkprefix') - onlinkprefix = br.expect(r'Local: ((?:\w+:){4}):/\d+\r', timeout=5)[1].decode() - return str(onlinkprefix) +@extract_address('br onlinkprefix', r'Local: ((?:\w+:){4}):/\d+\r') +def get_onlinkprefix(addr: str) -> str: + return addr -def get_nat64prefix(br: IdfDut) -> str: - execute_command(br, 'br nat64prefix') - nat64prefix = br.expect(r'Local: ((?:\w+:){6}):/\d+', timeout=5)[1].decode() - return str(nat64prefix) +@extract_address('br nat64prefix', r'Local: ((?:\w+:){6}):/\d+') +def get_nat64prefix(addr: str) -> str: + return addr def execute_command(dut: IdfDut, command: str, prefix: str = 'ot ') -> None: @@ -647,3 +662,17 @@ def get_ouput_string(dut: IdfDut, command: str, wait_time: int) -> str: tmp = dut.expect(pexpect.TIMEOUT, timeout=wait_time) clean_buffer(dut) return str(tmp) + + +def wait_for_host_network(host: str = '8.8.8.8', retries: int = 6, interval: int = 10) -> None: + for attempt in range(1, retries + 1): + try: + subprocess.run(['ping', '-c', '1', '-W', '2', host], check=True) + logging.info(f'Host network reachable on attempt {attempt}') + return + except subprocess.CalledProcessError: + logging.info(f'Ping attempt {attempt} failed, retrying in {interval} seconds...') + if attempt < retries: + time.sleep(interval) + else: + raise RuntimeError(f'Host network is not reachable after {retries} attempts.') diff --git a/examples/openthread/pytest_otbr.py b/examples/openthread/pytest_otbr.py index 1e06b4b3156..8642f47ea6a 100644 --- a/examples/openthread/pytest_otbr.py +++ b/examples/openthread/pytest_otbr.py @@ -106,7 +106,7 @@ PORT_MAPPING = {'ESPPORT1': 'esp32h2', 'ESPPORT2': 'esp32s3', 'ESPPORT3': 'esp32 # Case 1: Thread network formation and attaching @pytest.mark.openthread_br -@pytest.mark.flaky(reruns=1, reruns_delay=1) +@pytest.mark.flaky(reruns=1, reruns_delay=5) @pytest.mark.parametrize( 'config, count, app_path, target, port', [ @@ -161,9 +161,9 @@ def test_thread_connect(dut: tuple[IdfDut, IdfDut, IdfDut]) -> None: rx_nums = ocf.ot_ping(br, cli_mleid_addr, count=5)[1] assert rx_nums == 5 finally: - ocf.execute_command(br, 'factoryreset') for cli in cli_list: - ocf.execute_command(cli, 'factoryreset') + ocf.stop_thread(cli) + ocf.stop_thread(br) time.sleep(3) @@ -189,7 +189,7 @@ def formBasicWiFiThreadNetwork(br: IdfDut, cli: IdfDut) -> None: # Case 2: Bidirectional IPv6 connectivity @pytest.mark.openthread_br -@pytest.mark.flaky(reruns=1, reruns_delay=1) +@pytest.mark.flaky(reruns=1, reruns_delay=5) @pytest.mark.parametrize( 'config, count, app_path, target, port', [ @@ -231,18 +231,19 @@ def test_Bidirectional_IPv6_connectivity(Init_interface: bool, dut: tuple[IdfDut host_global_unicast_addr = re.findall(pattern, out_str) rx_nums = 0 for ip_addr in host_global_unicast_addr: - txrx_nums = ocf.ot_ping(cli, str(ip_addr), count=5) + txrx_nums = ocf.ot_ping(cli, str(ip_addr), count=10) rx_nums = rx_nums + int(txrx_nums[1]) + logging.debug(f'rx_nums: {rx_nums}') assert rx_nums != 0 finally: - ocf.execute_command(br, 'factoryreset') - ocf.execute_command(cli, 'factoryreset') + ocf.stop_thread(cli) + ocf.stop_thread(br) time.sleep(3) # Case 3: Multicast forwarding from Wi-Fi to Thread network @pytest.mark.openthread_br -@pytest.mark.flaky(reruns=1, reruns_delay=1) +@pytest.mark.flaky(reruns=1, reruns_delay=5) @pytest.mark.parametrize( 'config, count, app_path, target, port', [ @@ -288,14 +289,14 @@ def test_multicast_forwarding_A(Init_interface: bool, dut: tuple[IdfDut, IdfDut, ocf.execute_command(cli, 'udp close') cli.expect('Done', timeout=5) finally: - ocf.execute_command(br, 'factoryreset') - ocf.execute_command(cli, 'factoryreset') + ocf.stop_thread(cli) + ocf.stop_thread(br) time.sleep(3) # Case 4: Multicast forwarding from Thread to Wi-Fi network @pytest.mark.openthread_br -@pytest.mark.flaky(reruns=1, reruns_delay=1) +@pytest.mark.flaky(reruns=1, reruns_delay=5) @pytest.mark.parametrize( 'config, count, app_path, target, port', [ @@ -341,15 +342,15 @@ def test_multicast_forwarding_B(Init_interface: bool, dut: tuple[IdfDut, IdfDut, while udp_mission.is_alive(): time.sleep(1) finally: - ocf.execute_command(br, 'factoryreset') - ocf.execute_command(cli, 'factoryreset') + ocf.stop_thread(cli) + ocf.stop_thread(br) time.sleep(3) assert b'hello' in myudp.udp_bytes # Case 5: discover dervice published by Thread device @pytest.mark.openthread_br -@pytest.mark.flaky(reruns=1, reruns_delay=1) +@pytest.mark.flaky(reruns=1, reruns_delay=5) @pytest.mark.parametrize( 'config, count, app_path, target, port', [ @@ -403,14 +404,14 @@ def test_service_discovery_of_Thread_device( logging.info(f'avahi-browse:\n {out_str}') assert 'myTest' in str(out_str) finally: - ocf.execute_command(br, 'factoryreset') - ocf.execute_command(cli, 'factoryreset') + ocf.stop_thread(cli) + ocf.stop_thread(br) time.sleep(3) # Case 6: discover dervice published by Wi-Fi device @pytest.mark.openthread_br -@pytest.mark.flaky(reruns=1, reruns_delay=1) +@pytest.mark.flaky(reruns=1, reruns_delay=5) @pytest.mark.parametrize( 'config, count, app_path, target, port', [ @@ -473,14 +474,14 @@ def test_service_discovery_of_WiFi_device( finally: ocf.host_close_service() sp.terminate() - ocf.execute_command(br, 'factoryreset') - ocf.execute_command(cli, 'factoryreset') + ocf.stop_thread(cli) + ocf.stop_thread(br) time.sleep(3) # Case 7: ICMP communication via NAT64 @pytest.mark.openthread_br -@pytest.mark.flaky(reruns=1, reruns_delay=1) +@pytest.mark.flaky(reruns=1, reruns_delay=5) @pytest.mark.parametrize( 'config, count, app_path, target, port', [ @@ -511,14 +512,14 @@ def test_ICMP_NAT64(Init_interface: bool, dut: tuple[IdfDut, IdfDut, IdfDut]) -> rx_nums = ocf.ot_ping(cli, str(host_ipv4_address), count=5)[1] assert rx_nums != 0 finally: - ocf.execute_command(br, 'factoryreset') - ocf.execute_command(cli, 'factoryreset') + ocf.stop_thread(cli) + ocf.stop_thread(br) time.sleep(3) # Case 8: UDP communication via NAT64 @pytest.mark.openthread_br -@pytest.mark.flaky(reruns=1, reruns_delay=1) +@pytest.mark.flaky(reruns=1, reruns_delay=5) @pytest.mark.parametrize( 'config, count, app_path, target, port', [ @@ -566,15 +567,15 @@ def test_UDP_NAT64(Init_interface: bool, dut: tuple[IdfDut, IdfDut, IdfDut]) -> while udp_mission.is_alive(): time.sleep(1) finally: - ocf.execute_command(br, 'factoryreset') - ocf.execute_command(cli, 'factoryreset') + ocf.stop_thread(cli) + ocf.stop_thread(br) time.sleep(3) assert b'hello' in myudp.udp_bytes # Case 9: TCP communication via NAT64 @pytest.mark.openthread_br -@pytest.mark.flaky(reruns=1, reruns_delay=1) +@pytest.mark.flaky(reruns=1, reruns_delay=5) @pytest.mark.parametrize( 'config, count, app_path, target, port', [ @@ -628,14 +629,15 @@ def test_TCP_NAT64(Init_interface: bool, dut: tuple[IdfDut, IdfDut, IdfDut]) -> while tcp_mission.is_alive(): time.sleep(1) finally: - ocf.execute_command(br, 'factoryreset') - ocf.execute_command(cli, 'factoryreset') + ocf.stop_thread(cli) + ocf.stop_thread(br) time.sleep(3) assert b'hello' in mytcp.tcp_bytes # Case 10: Sleepy device test @pytest.mark.openthread_sleep +@pytest.mark.flaky(reruns=1, reruns_delay=5) @pytest.mark.parametrize( 'config, count, app_path, target, port', [ @@ -663,6 +665,7 @@ def test_TCP_NAT64(Init_interface: bool, dut: tuple[IdfDut, IdfDut, IdfDut]) -> def test_ot_sleepy_device(dut: tuple[IdfDut, IdfDut]) -> None: leader = dut[0] sleepy_device = dut[1] + ocf.hardreset_dut(sleepy_device) fail_info = re.compile(r'Core\W*?\d\W*?register dump') try: ocf.init_thread(leader) @@ -689,12 +692,13 @@ def test_ot_sleepy_device(dut: tuple[IdfDut, IdfDut]) -> None: assert not bool(fail_info.search(str(output))) finally: ocf.execute_command(leader, 'factoryreset') + ocf.hardreset_dut(sleepy_device) time.sleep(3) # Case 11: Basic startup Test of BR @pytest.mark.openthread_br -@pytest.mark.flaky(reruns=1, reruns_delay=1) +@pytest.mark.flaky(reruns=1, reruns_delay=5) @pytest.mark.parametrize( 'config, count, app_path, target, port', [ @@ -728,13 +732,13 @@ def test_basic_startup(dut: tuple[IdfDut, IdfDut]) -> None: br.expect('Done', timeout=5) assert ocf.wait_for_join(br, 'leader') finally: - ocf.execute_command(br, 'factoryreset') + ocf.stop_thread(br) time.sleep(3) # Case 12: Curl a website via DNS and NAT64 @pytest.mark.openthread_bbr -@pytest.mark.flaky(reruns=1, reruns_delay=1) +@pytest.mark.flaky(reruns=1, reruns_delay=5) @pytest.mark.parametrize( 'config, count, app_path, target, port', [ @@ -759,23 +763,24 @@ def test_NAT64_DNS(Init_interface: bool, dut: tuple[IdfDut, IdfDut, IdfDut]) -> formBasicWiFiThreadNetwork(br, cli) try: + ocf.wait_for_host_network() ocf.execute_command(br, 'bbr') br.expect('server16', timeout=5) ocf.execute_command(cli, 'dns64server 8.8.8.8') cli.expect('Done', timeout=5) command = 'curl http://www.espressif.com' message = ocf.get_ouput_string(cli, command, 10) - assert '' in str(message) + assert 'html' in str(message) assert '301 Moved Permanently' in str(message) finally: - ocf.execute_command(br, 'factoryreset') - ocf.execute_command(cli, 'factoryreset') + ocf.stop_thread(cli) + ocf.stop_thread(br) time.sleep(3) # Case 13: Meshcop discovery of Border Router @pytest.mark.openthread_br -@pytest.mark.flaky(reruns=1, reruns_delay=1) +@pytest.mark.flaky(reruns=1, reruns_delay=5) @pytest.mark.parametrize( 'config, count, app_path, target, port', [ @@ -829,13 +834,13 @@ def test_br_meshcop(Init_interface: bool, Init_avahi: bool, dut: tuple[IdfDut, I assert 'vn=OpenThread' in str(output_str) assert 'rv=1' in str(output_str) finally: - ocf.execute_command(br, 'factoryreset') + ocf.stop_thread(br) time.sleep(3) # Case 14: Curl a website over HTTPS via DNS and NAT64 @pytest.mark.openthread_bbr -@pytest.mark.flaky(reruns=1, reruns_delay=1) +@pytest.mark.flaky(reruns=1, reruns_delay=5) @pytest.mark.parametrize( 'config, count, app_path, target, port', [ @@ -860,21 +865,22 @@ def test_https_NAT64_DNS(Init_interface: bool, dut: tuple[IdfDut, IdfDut, IdfDut formBasicWiFiThreadNetwork(br, cli) try: + ocf.wait_for_host_network() ocf.execute_command(cli, 'dns64server 8.8.8.8') cli.expect('Done', timeout=5) command = 'curl https://www.example.com/' message = ocf.get_ouput_string(cli, command, 20) - assert '' in str(message) - assert 'This domain is for use in illustrative examples in documents' in str(message) + assert 'html' in str(message) + assert 'This domain is for use in' in str(message) finally: - ocf.execute_command(br, 'factoryreset') - ocf.execute_command(cli, 'factoryreset') + ocf.stop_thread(cli) + ocf.stop_thread(br) time.sleep(3) # Case 15: Thread network formation and attaching with TREL @pytest.mark.openthread_br -@pytest.mark.flaky(reruns=1, reruns_delay=1) +@pytest.mark.flaky(reruns=1, reruns_delay=5) @pytest.mark.parametrize( 'config, count, app_path, target, port', [ @@ -920,15 +926,15 @@ def test_trel_connect(dut: tuple[IdfDut, IdfDut]) -> None: rx_nums = ocf.ot_ping(trel_s3, trel_mleid_addr, count=10)[1] assert rx_nums > 5 finally: - ocf.execute_command(trel_s3, 'factoryreset') for trel in trel_list: - ocf.execute_command(trel, 'factoryreset') + ocf.stop_thread(trel) + ocf.stop_thread(trel_s3) time.sleep(3) # Case 16: Thread network BR lib check @pytest.mark.openthread_br -@pytest.mark.flaky(reruns=1, reruns_delay=1) +@pytest.mark.flaky(reruns=1, reruns_delay=5) @pytest.mark.parametrize( 'config, count, app_path, target, port', [ @@ -957,6 +963,7 @@ def test_br_lib_check(dut: tuple[IdfDut, IdfDut]) -> None: # Case 17: SSED test @pytest.mark.openthread_sleep +@pytest.mark.flaky(reruns=1, reruns_delay=5) @pytest.mark.parametrize( 'config, count, app_path, target, port', [ @@ -985,6 +992,7 @@ def test_ot_ssed_device(dut: tuple[IdfDut, IdfDut]) -> None: leader = dut[0] ssed_device = dut[1] try: + ocf.hardreset_dut(ssed_device) # CI device must have external XTAL to run SSED case, we will check this here first ssed_device.expect('32k XTAL in use', timeout=10) ocf.init_thread(leader) @@ -1024,4 +1032,5 @@ def test_ot_ssed_device(dut: tuple[IdfDut, IdfDut]) -> None: ocf.ping_and_check(dut=leader, target=ssed_address, tx_total=10, timeout=6) finally: ocf.execute_command(leader, 'factoryreset') + ocf.hardreset_dut(ssed_device) time.sleep(3) From 2b82146902c2329b38f6b28f1c932a13088ed5f3 Mon Sep 17 00:00:00 2001 From: Mahavir Jain Date: Fri, 24 Oct 2025 14:17:06 +0530 Subject: [PATCH 028/106] fix(esp_psram): make SPIRAM_USE_MEMMAP available for all targets This reverts earlier commit d2858847 and thereby making SPIRAM_USE_MEMMAP available for all targets. This config option has no direct usage but just avoids adding the PSRAM to heap but still keeps it memory mapped. Closes https://github.com/espressif/esp-idf/issues/17764 --- components/esp_psram/Kconfig.spiram.common | 1 - 1 file changed, 1 deletion(-) diff --git a/components/esp_psram/Kconfig.spiram.common b/components/esp_psram/Kconfig.spiram.common index b04cacbd929..ea16849a521 100644 --- a/components/esp_psram/Kconfig.spiram.common +++ b/components/esp_psram/Kconfig.spiram.common @@ -69,7 +69,6 @@ choice SPIRAM_USE return SPI RAM pointers. config SPIRAM_USE_MEMMAP - depends on IDF_TARGET_ESP32 bool "Integrate RAM into memory map" config SPIRAM_USE_CAPS_ALLOC bool "Make RAM allocatable using heap_caps_malloc(..., MALLOC_CAP_SPIRAM)" From dcde633acd84c9b9a5a61e89270ab78c89da6244 Mon Sep 17 00:00:00 2001 From: Erhan Kurubas Date: Thu, 25 Sep 2025 08:58:59 +0200 Subject: [PATCH 029/106] feat(tracing): add new component for tracing --- components/app_trace/CMakeLists.txt | 8 +- components/app_trace/Kconfig | 330 --------------- components/app_trace/Kconfig.apptrace | 144 +++++++ components/app_trace/app_trace.c | 10 +- components/app_trace/heap_trace_tohost.c | 16 +- components/app_trace/include/esp_app_trace.h | 26 +- .../app_trace/include/esp_app_trace_config.h | 18 +- .../app_trace/include/esp_app_trace_types.h | 7 +- .../app_trace/include/esp_sysview_trace.h | 29 +- components/app_trace/linker.lf | 24 +- components/app_trace/port/port_uart.c | 7 +- components/app_trace/sdkconfig.rename | 39 +- components/app_trace/sys_view/Kconfig.sysview | 113 ++++++ .../app_trace/sys_view/SEGGER/SEGGER_RTT.h | 4 +- .../esp/SEGGER_SYSVIEW_Config_FreeRTOS.c | 135 ++---- .../FreeRTOSV10.4/SEGGER_SYSVIEW_FreeRTOS.h | 2 +- .../app_trace/sys_view/esp/SEGGER_RTT_esp.c | 176 +++++--- .../sys_view/ext/heap_trace_module.c | 2 +- .../app_trace/test_apps/main/CMakeLists.txt | 2 +- .../app_trace/test_apps/main/test_trace.c | 6 +- .../test_apps/sdkconfig.ci.app_trace | 4 +- .../app_trace/test_apps/sdkconfig.ci.sysview | 4 +- .../app_trace/test_apps/sdkconfig.defaults | 3 +- components/esp_hw_support/intr_alloc.c | 8 +- components/esp_system/CMakeLists.txt | 4 +- components/esp_system/panic.c | 38 +- components/esp_system/system_init_fn.txt | 6 +- components/esp_trace/CMakeLists.txt | 38 ++ components/esp_trace/Kconfig | 90 ++++ components/esp_trace/README.md | 383 ++++++++++++++++++ .../encoder/adapter_encoder_sysview.c | 148 +++++++ .../transport/adapter_transport_apptrace.c | 268 ++++++++++++ .../adapters/adapter_encoder_sysview.h | 46 +++ components/esp_trace/include/esp_trace.h | 140 +++++++ .../esp_trace/include/esp_trace_freertos.h | 27 ++ .../include/esp_trace_port_encoder.h | 80 ++++ .../include/esp_trace_port_transport.h | 137 +++++++ .../esp_trace/include/esp_trace_registry.h | 69 ++++ .../esp_trace/include/esp_trace_types.h | 28 ++ components/esp_trace/include/esp_trace_util.h | 123 ++++++ components/esp_trace/linker.lf | 50 +++ .../esp_trace/src/core/esp_trace_core.c | 207 ++++++++++ .../esp_trace/src/core/esp_trace_registry.c | 59 +++ components/esp_trace/src/ports/port_utils.c | 154 +++++++ components/freertos/CMakeLists.txt | 9 +- .../riscv/include/freertos/portmacro.h | 2 +- .../xtensa/include/freertos/portmacro.h | 2 +- .../riscv/include/freertos/portmacro.h | 2 +- .../xtensa/include/freertos/portmacro.h | 2 +- .../config/include/freertos/FreeRTOSConfig.h | 9 +- components/xtensa/xtensa_intr.c | 2 +- docs/en/api-guides/app_trace.rst | 85 +++- docs/en/api-reference/system/heap_debug.rst | 4 +- .../release-6.x/6.0/system.rst | 73 ++-- docs/zh_CN/api-guides/app_trace.rst | 108 +++-- .../zh_CN/api-reference/system/heap_debug.rst | 4 +- .../release-6.x/6.0/system.rst | 73 ++-- .../app_trace_basic/main/CMakeLists.txt | 2 +- .../main/app_trace_basic_example_main.c | 6 +- .../sdkconfig.ci.apptrace_uart | 4 +- .../system/app_trace_basic/sdkconfig.defaults | 4 +- .../app_trace_to_plot/main/CMakeLists.txt | 2 +- .../main/app_trace_to_plot.c | 1 + .../app_trace_to_plot/sdkconfig.defaults | 4 +- examples/system/gcov/sdkconfig.defaults | 4 +- .../sysview_tracing/main/CMakeLists.txt | 2 +- .../sysview_tracing/main/sysview_tracing.c | 8 +- .../system/sysview_tracing/sdkconfig.defaults | 33 +- .../main/CMakeLists.txt | 2 +- .../main/sysview_heap_log.c | 2 +- .../sdkconfig.defaults | 33 +- tools/ci/check_copyright_config.yaml | 13 + 72 files changed, 2897 insertions(+), 810 deletions(-) delete mode 100644 components/app_trace/Kconfig create mode 100644 components/app_trace/Kconfig.apptrace create mode 100644 components/app_trace/sys_view/Kconfig.sysview create mode 100644 components/esp_trace/CMakeLists.txt create mode 100644 components/esp_trace/Kconfig create mode 100644 components/esp_trace/README.md create mode 100644 components/esp_trace/adapters/encoder/adapter_encoder_sysview.c create mode 100644 components/esp_trace/adapters/transport/adapter_transport_apptrace.c create mode 100644 components/esp_trace/include/adapters/adapter_encoder_sysview.h create mode 100644 components/esp_trace/include/esp_trace.h create mode 100644 components/esp_trace/include/esp_trace_freertos.h create mode 100644 components/esp_trace/include/esp_trace_port_encoder.h create mode 100644 components/esp_trace/include/esp_trace_port_transport.h create mode 100644 components/esp_trace/include/esp_trace_registry.h create mode 100644 components/esp_trace/include/esp_trace_types.h create mode 100644 components/esp_trace/include/esp_trace_util.h create mode 100644 components/esp_trace/linker.lf create mode 100644 components/esp_trace/src/core/esp_trace_core.c create mode 100644 components/esp_trace/src/core/esp_trace_registry.c create mode 100644 components/esp_trace/src/ports/port_utils.c diff --git a/components/app_trace/CMakeLists.txt b/components/app_trace/CMakeLists.txt index 716d83bfab7..8b711b9ee86 100644 --- a/components/app_trace/CMakeLists.txt +++ b/components/app_trace/CMakeLists.txt @@ -4,14 +4,14 @@ if(${target} STREQUAL "linux") return() # This component is not supported by the POSIX/Linux simulator endif() -if(CONFIG_APPTRACE_ENABLE) +if(CONFIG_ESP_TRACE_TRANSPORT_APPTRACE) set(srcs "app_trace.c" "app_trace_util.c" "host_file_io.c" ) - if(NOT CONFIG_APPTRACE_DEST_UART) # JTAG or ALL + if(NOT CONFIG_APPTRACE_DEST_UART) # JTAG or None if(CONFIG_IDF_TARGET_ARCH_XTENSA) list(APPEND srcs "port/xtensa/port_jtag.c") elseif(CONFIG_IDF_TARGET_ARCH_RISCV) @@ -20,7 +20,7 @@ if(CONFIG_APPTRACE_ENABLE) list(APPEND srcs "app_trace_membufs_proto.c") endif() - if(NOT CONFIG_APPTRACE_DEST_JTAG) # UART or ALL + if(NOT CONFIG_APPTRACE_DEST_JTAG) # UART or None list(APPEND srcs "port/port_uart.c") endif() endif() @@ -33,7 +33,7 @@ set(include_dirs "include") set(priv_include_dirs "private_include" "port/include") -if(CONFIG_APPTRACE_SV_ENABLE) +if(CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW) list(APPEND include_dirs sys_view/Config sys_view/SEGGER diff --git a/components/app_trace/Kconfig b/components/app_trace/Kconfig deleted file mode 100644 index 3bf90245003..00000000000 --- a/components/app_trace/Kconfig +++ /dev/null @@ -1,330 +0,0 @@ -menu "Application Level Tracing" - - config APPTRACE_ENABLE - bool "Enable Application Level Tracing" - default n - help - Enables/disable application tracing module. - This must be enabled to use any tracing library. - - choice APPTRACE_DESTINATION - prompt "Data Destination" - default APPTRACE_DEST_JTAG if !PM_ENABLE - default APPTRACE_DEST_UART if PM_ENABLE - depends on APPTRACE_ENABLE - help - Select destination for application trace: JTAG or UART. - When SystemView is enabled, this also controls the SystemView destination. - - config APPTRACE_DEST_JTAG - bool "JTAG" - select APPTRACE_TRAX_ENABLE if IDF_TARGET_ARCH_XTENSA - depends on !PM_ENABLE - - config APPTRACE_DEST_UART - bool "UART" - - config APPTRACE_DEST_NONE - bool "None (runtime selection)" - help - Compile both JTAG and UART interfaces. Increases IRAM usage. - Allows runtime selection via esp_apptrace_get_user_params(). - - With this option, destination and configuration must be provided - at runtime. Default JTAG and UART settings are defined in - components/app_trace/include/esp_app_trace_config.h. - - Override these by implementing esp_apptrace_get_user_params() - in your application. - endchoice - - config APPTRACE_BUF_SIZE - int "Size of the apptrace buffer" - depends on APPTRACE_DEST_JTAG && !APPTRACE_TRAX_ENABLE - default 16384 - help - Size of the memory buffer for trace data in bytes. - - config APPTRACE_DEST_UART_NUM - int "UART port number" - depends on APPTRACE_DEST_UART - range 0 1 if (SOC_UART_NUM <= 2) - range 0 2 if (SOC_UART_NUM <= 3) - range 0 5 if (SOC_UART_NUM <= 6) - default 1 - help - UART communication port number for the apptrace destination. - See UART documentation for available port numbers. - - config APPTRACE_UART_TX_GPIO - int "UART TX on GPIO" - depends on APPTRACE_DEST_UART - range 0 46 - default 12 - help - This GPIO is used for UART TX pin. - - config APPTRACE_UART_RX_GPIO - int "UART RX on GPIO" - depends on APPTRACE_DEST_UART - range 0 46 - default 13 - help - This GPIO is used for UART RX pin. - - config APPTRACE_UART_BAUDRATE - int - prompt "UART baud rate" if APPTRACE_DEST_UART - depends on APPTRACE_DEST_UART - default 1000000 - range 1200 8000000 - range 1200 1000000 - help - This baud rate is used for UART. - - The app's maximum baud rate depends on the UART clock source. If Power Management is disabled, - the UART clock source is the APB clock and all baud rates in the available range will be sufficiently - accurate. If Power Management is enabled, REF_TICK clock source is used so the baud rate is divided - from 1MHz. Baud rates above 1Mbps are not possible and values between 500Kbps and 1Mbps may not be - accurate. - - config APPTRACE_UART_RX_BUFF_SIZE - int - prompt "UART RX ring buffer size" if APPTRACE_DEST_UART - depends on APPTRACE_DEST_UART - default 128 - range 64 32768 - help - Size of the UART input ring buffer. - This size related to the baudrate, system tick frequency and amount of data to transfer. - The data placed to this buffer before sent out to the interface. - - config APPTRACE_UART_TX_BUFF_SIZE - int - prompt "UART TX ring buffer size" if APPTRACE_DEST_UART - depends on APPTRACE_DEST_UART - default 4096 - range 2048 32768 - help - Size of the UART output ring buffer. - This size related to the baudrate, system tick frequency and amount of data to transfer. - - config APPTRACE_UART_TX_MSG_SIZE - int - prompt "UART TX message size" if APPTRACE_DEST_UART - depends on APPTRACE_DEST_UART - default 128 - range 64 32768 - help - Maximum size of the single message to transfer. - - config APPTRACE_UART_TASK_PRIO - int - prompt "UART Task Priority" if APPTRACE_DEST_UART - depends on APPTRACE_DEST_UART - default 1 - range 1 32 - help - UART task priority. In case of high events rate, - this parameter could be changed up to (configMAX_PRIORITIES-1). - - config APPTRACE_TRAX_ENABLE - bool - depends on IDF_TARGET_ARCH_XTENSA && !ESP32_TRAX && !ESP32S2_TRAX && !ESP32S3_TRAX - select ESP32_MEMMAP_TRACEMEM - select ESP32S2_MEMMAP_TRACEMEM - select ESP32S3_MEMMAP_TRACEMEM - select ESP32_MEMMAP_TRACEMEM_TWOBANKS - select ESP32S2_MEMMAP_TRACEMEM_TWOBANKS - select ESP32S3_MEMMAP_TRACEMEM_TWOBANKS - default n - help - Enables/disable TRAX tracing HW. - - config APPTRACE_LOCK_ENABLE - bool "Internal Sync Lock Enable" - depends on APPTRACE_ENABLE - default n - help - Enables/disable application tracing module internal sync lock. - Keep in mind this will slow down the trace data transfer to the host. - - config APPTRACE_ONPANIC_HOST_FLUSH_TMO - int "Timeout for flushing last trace data to host on panic" - depends on APPTRACE_ENABLE - range -1 5000 - default -1 - help - Timeout for flushing last trace data to host in case of panic. In ms. - Use -1 to disable timeout and wait forever. - - config APPTRACE_POSTMORTEM_FLUSH_THRESH - int "Threshold for flushing last trace data to host on panic" - depends on APPTRACE_ENABLE - range 0 16384 - default 0 - help - Threshold for flushing last trace data to host on panic in post-mortem mode. - This is minimal amount of data needed to perform flush. In bytes. - - menu "FreeRTOS SystemView Tracing" - depends on APPTRACE_ENABLE - config APPTRACE_SV_ENABLE - bool "SystemView Tracing Enable" - depends on APPTRACE_ENABLE - default n - help - Enables support for SEGGER SystemView tracing functionality. - - choice APPTRACE_SV_CPU - prompt "CPU to trace" - depends on APPTRACE_SV_ENABLE && APPTRACE_DEST_UART && !ESP_SYSTEM_SINGLE_CORE_MODE - default APPTRACE_SV_DEST_CPU_0 - help - Define the CPU to trace by SystemView. - - config APPTRACE_SV_DEST_CPU_0 - bool "CPU0" - help - Send SEGGER SystemView events for Pro CPU. - - config APPTRACE_SV_DEST_CPU_1 - bool "CPU1" - help - Send SEGGER SystemView events for App CPU. - - endchoice - - choice APPTRACE_SV_TS_SOURCE - prompt "Timer to use as timestamp source" - depends on APPTRACE_SV_ENABLE - default APPTRACE_SV_TS_SOURCE_CCOUNT if ESP_SYSTEM_SINGLE_CORE_MODE && !PM_ENABLE && !IDF_TARGET_ESP32C3 - default APPTRACE_SV_TS_SOURCE_GPTIMER if !ESP_SYSTEM_SINGLE_CORE_MODE && !PM_ENABLE && !IDF_TARGET_ESP32C3 - default APPTRACE_SV_TS_SOURCE_ESP_TIMER if PM_ENABLE || IDF_TARGET_ESP32C3 - help - SystemView needs to use a hardware timer as the source of timestamps - when tracing. This option selects the timer for it. - - config APPTRACE_SV_TS_SOURCE_CCOUNT - bool "CPU cycle counter (CCOUNT)" - depends on ESP_SYSTEM_SINGLE_CORE_MODE && !PM_ENABLE && !IDF_TARGET_ESP32C3 - - config APPTRACE_SV_TS_SOURCE_GPTIMER - bool "General Purpose Timer (Timer Group)" - depends on !PM_ENABLE && !IDF_TARGET_ESP32C3 - - config APPTRACE_SV_TS_SOURCE_ESP_TIMER - bool "esp_timer high resolution timer" - - endchoice - - config APPTRACE_SV_MAX_TASKS - int "Maximum supported tasks" - depends on APPTRACE_SV_ENABLE - range 1 64 - default 16 - help - Configures maximum supported tasks in sysview debug - - config APPTRACE_SV_BUF_WAIT_TMO - int "Trace buffer wait timeout" - depends on APPTRACE_SV_ENABLE - default 500 - help - Configures timeout (in us) to wait for free space in trace buffer. - Set to -1 to wait forever and avoid lost events. - - config APPTRACE_SV_EVT_OVERFLOW_ENABLE - bool "Trace Buffer Overflow Event" - depends on APPTRACE_SV_ENABLE - default y - help - Enables "Trace Buffer Overflow" event. - - config APPTRACE_SV_EVT_ISR_ENTER_ENABLE - bool "ISR Enter Event" - depends on APPTRACE_SV_ENABLE - default y - help - Enables "ISR Enter" event. - - config APPTRACE_SV_EVT_ISR_EXIT_ENABLE - bool "ISR Exit Event" - depends on APPTRACE_SV_ENABLE - default y - help - Enables "ISR Exit" event. - - config APPTRACE_SV_EVT_ISR_TO_SCHED_ENABLE - bool "ISR Exit to Scheduler Event" - depends on APPTRACE_SV_ENABLE - default y - help - Enables "ISR to Scheduler" event. - - config APPTRACE_SV_EVT_TASK_START_EXEC_ENABLE - bool "Task Start Execution Event" - depends on APPTRACE_SV_ENABLE - default y - help - Enables "Task Start Execution" event. - - config APPTRACE_SV_EVT_TASK_STOP_EXEC_ENABLE - bool "Task Stop Execution Event" - depends on APPTRACE_SV_ENABLE - default y - help - Enables "Task Stop Execution" event. - - config APPTRACE_SV_EVT_TASK_START_READY_ENABLE - bool "Task Start Ready State Event" - depends on APPTRACE_SV_ENABLE - default y - help - Enables "Task Start Ready State" event. - - config APPTRACE_SV_EVT_TASK_STOP_READY_ENABLE - bool "Task Stop Ready State Event" - depends on APPTRACE_SV_ENABLE - default y - help - Enables "Task Stop Ready State" event. - - config APPTRACE_SV_EVT_TASK_CREATE_ENABLE - bool "Task Create Event" - depends on APPTRACE_SV_ENABLE - default y - help - Enables "Task Create" event. - - config APPTRACE_SV_EVT_TASK_TERMINATE_ENABLE - bool "Task Terminate Event" - depends on APPTRACE_SV_ENABLE - default y - help - Enables "Task Terminate" event. - - config APPTRACE_SV_EVT_IDLE_ENABLE - bool "System Idle Event" - depends on APPTRACE_SV_ENABLE - default y - help - Enables "System Idle" event. - - config APPTRACE_SV_EVT_TIMER_ENTER_ENABLE - bool "Timer Enter Event" - depends on APPTRACE_SV_ENABLE - default y - help - Enables "Timer Enter" event. - - config APPTRACE_SV_EVT_TIMER_EXIT_ENABLE - bool "Timer Exit Event" - depends on APPTRACE_SV_ENABLE - default y - help - Enables "Timer Exit" event. - - endmenu - -endmenu diff --git a/components/app_trace/Kconfig.apptrace b/components/app_trace/Kconfig.apptrace new file mode 100644 index 00000000000..ca609cfb72f --- /dev/null +++ b/components/app_trace/Kconfig.apptrace @@ -0,0 +1,144 @@ +menu "Application Level Tracing" + depends on ESP_TRACE_TRANSPORT_APPTRACE + choice APPTRACE_DESTINATION + prompt "Data Destination" + default APPTRACE_DEST_JTAG if !PM_ENABLE + default APPTRACE_DEST_UART if PM_ENABLE + help + Select destination for application trace: JTAG, UART, or both. + + config APPTRACE_DEST_JTAG + bool "JTAG" + select APPTRACE_TRAX_ENABLE if IDF_TARGET_ARCH_XTENSA + depends on !PM_ENABLE + + config APPTRACE_DEST_UART + bool "UART" + + config APPTRACE_DEST_ALL + bool "All (runtime selection)" + help + Compile both JTAG and UART interfaces in advance (higher IRAM usage). + Allows runtime switching between JTAG and UART via esp_apptrace_get_user_params(). + + If esp_apptrace_get_user_params() is not provided by the + application, JTAG is used by default with the default + configuration defined in components/app_trace/include/esp_app_trace_config.h. + endchoice + + config APPTRACE_BUF_SIZE + int "Size of the apptrace buffer" + depends on APPTRACE_DEST_JTAG && !APPTRACE_TRAX_ENABLE + default 16384 + help + Size of the memory buffer for trace data in bytes. + + config APPTRACE_DEST_UART_NUM + int "UART port number" + depends on APPTRACE_DEST_UART + range 0 1 if (SOC_UART_NUM <= 2) + range 0 2 if (SOC_UART_NUM <= 3) + range 0 5 if (SOC_UART_NUM <= 6) + default 1 + help + UART communication port number for the apptrace destination. + See UART documentation for available port numbers. + + config APPTRACE_UART_TX_GPIO + int "UART TX on GPIO" + depends on APPTRACE_DEST_UART + range 0 46 + default 12 + help + This GPIO is used for UART TX pin. + + config APPTRACE_UART_RX_GPIO + int "UART RX on GPIO" + depends on APPTRACE_DEST_UART + range 0 46 + default 13 + help + This GPIO is used for UART RX pin. + + config APPTRACE_UART_BAUDRATE + int + prompt "UART baud rate" if APPTRACE_DEST_UART + depends on APPTRACE_DEST_UART + default 1000000 + range 1200 8000000 + range 1200 1000000 + help + This baud rate is used for UART. + + The app's maximum baud rate depends on the UART clock source. If Power Management is disabled, + the UART clock source is the APB clock and all baud rates in the available range will be sufficiently + accurate. If Power Management is enabled, REF_TICK clock source is used so the baud rate is divided + from 1MHz. Baud rates above 1Mbps are not possible and values between 500Kbps and 1Mbps may not be + accurate. + + config APPTRACE_UART_TX_BUFF_SIZE + int + prompt "UART TX ring buffer size" if APPTRACE_DEST_UART + depends on APPTRACE_DEST_UART + default 4096 + range 2048 32768 + help + Size of the UART output ring buffer. + This size related to the baudrate, system tick frequency and amount of data to transfer. + + config APPTRACE_UART_TX_MSG_SIZE + int + prompt "UART TX message size" if APPTRACE_DEST_UART + depends on APPTRACE_DEST_UART + default 128 + range 64 32768 + help + Maximum size of the single message to transfer. + + config APPTRACE_UART_TASK_PRIO + int + prompt "UART Task Priority" if APPTRACE_DEST_UART + depends on APPTRACE_DEST_UART + default 1 + range 1 32 + help + UART task priority. In case of high events rate, + this parameter could be changed up to (configMAX_PRIORITIES-1). + + config APPTRACE_TRAX_ENABLE + bool + depends on IDF_TARGET_ARCH_XTENSA && !ESP32_TRAX && !ESP32S2_TRAX && !ESP32S3_TRAX + select ESP32_MEMMAP_TRACEMEM + select ESP32S2_MEMMAP_TRACEMEM + select ESP32S3_MEMMAP_TRACEMEM + select ESP32_MEMMAP_TRACEMEM_TWOBANKS + select ESP32S2_MEMMAP_TRACEMEM_TWOBANKS + select ESP32S3_MEMMAP_TRACEMEM_TWOBANKS + default n + help + Enables/disable TRAX tracing HW. + + config APPTRACE_LOCK_ENABLE + bool "Internal Sync Lock Enable" + default n + help + Enables/disable application tracing module internal sync lock to prevent data corruption + when multiple tasks are writing to the same trace buffer. + Keep in mind this will slow down the trace data transfer to the host. + + config APPTRACE_ONPANIC_HOST_FLUSH_TMO + int "Timeout for flushing last trace data to host on panic" + range -1 5000 + default -1 + help + Timeout for flushing last trace data to host in case of panic. In ms. + Use -1 to disable timeout and wait forever. + + config APPTRACE_POSTMORTEM_FLUSH_THRESH + int "Threshold for flushing last trace data to host on panic" + range 0 16384 + default 0 + help + Threshold for flushing last trace data to host on panic in post-mortem mode. + This is minimal amount of data needed to perform flush. In bytes. +endmenu diff --git a/components/app_trace/app_trace.c b/components/app_trace/app_trace.c index cb8bb2b49df..4a2ff63dbd9 100644 --- a/components/app_trace/app_trace.c +++ b/components/app_trace/app_trace.c @@ -32,7 +32,7 @@ typedef struct { static esp_apptrace_channel_t s_trace_ch; static volatile int s_trace_ch_hw_initialized = 0; -static esp_err_t esp_apptrace_init(const esp_apptrace_config_t *config) +esp_err_t esp_apptrace_init(const esp_apptrace_config_t *config) { __attribute__((unused)) void *hw_data = NULL; @@ -44,7 +44,7 @@ static esp_err_t esp_apptrace_init(const esp_apptrace_config_t *config) const esp_apptrace_uart_config_t *uart_config = &config->dest_cfg.uart; s_trace_ch.hw = esp_apptrace_uart_hw_get(uart_config->uart_num, &hw_data); s_trace_ch.hw_data = hw_data; -#else // CONFIG_APPTRACE_DEST_NONE allows runtime selection +#else // CONFIG_APPTRACE_DEST_ALL allows runtime selection between destinations if (config->dest == ESP_APPTRACE_DEST_JTAG) { s_trace_ch.hw = esp_apptrace_jtag_hw_get(&hw_data); s_trace_ch.hw_data = hw_data; @@ -363,6 +363,11 @@ esp_err_t esp_apptrace_set_header_size(esp_apptrace_header_size_t header_size) return ESP_OK; } +/* If any trace library (sysview or external) is selected with the apptrace transport, + * initialization will be handled by the esp_trace component + */ +#if CONFIG_ESP_TRACE_LIB_NONE && CONFIG_ESP_TRACE_TRANSPORT_APPTRACE + esp_apptrace_config_t __attribute__((weak)) esp_apptrace_get_user_params(void) { esp_apptrace_config_t default_config = APPTRACE_CONFIG_DEFAULT(); @@ -374,3 +379,4 @@ ESP_SYSTEM_INIT_FN(apptrace_early_init, SECONDARY, ESP_SYSTEM_INIT_ALL_CORES, 11 esp_apptrace_config_t config = esp_apptrace_get_user_params(); return esp_apptrace_init(&config); } +#endif diff --git a/components/app_trace/heap_trace_tohost.c b/components/app_trace/heap_trace_tohost.c index 8ee093b31b2..7ee0bd893e0 100644 --- a/components/app_trace/heap_trace_tohost.c +++ b/components/app_trace/heap_trace_tohost.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -7,8 +7,10 @@ #include "freertos/FreeRTOS.h" #include "esp_heap_trace.h" #include "esp_heap_caps.h" -#if CONFIG_APPTRACE_SV_ENABLE +#if CONFIG_ESP_TRACE_TRANSPORT_APPTRACE #include "esp_app_trace.h" +#endif +#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW #include "esp_sysview_trace.h" #endif @@ -16,7 +18,7 @@ #if CONFIG_HEAP_TRACING_TOHOST -#if !CONFIG_APPTRACE_SV_ENABLE +#if !CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW #error None of the heap tracing backends is enabled! You must enable SystemView compatible tracing to use this feature. #endif @@ -32,7 +34,7 @@ esp_err_t heap_trace_init_tohost(void) esp_err_t heap_trace_start(heap_trace_mode_t mode_param) { -#if CONFIG_APPTRACE_SV_ENABLE +#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW esp_err_t ret = esp_sysview_heap_trace_start((uint32_t) -1); if (ret != ESP_OK) { return ret; @@ -45,7 +47,7 @@ esp_err_t heap_trace_start(heap_trace_mode_t mode_param) esp_err_t heap_trace_stop(void) { esp_err_t ret = ESP_ERR_NOT_SUPPORTED; -#if CONFIG_APPTRACE_SV_ENABLE +#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW ret = esp_sysview_heap_trace_stop(); #endif s_tracing = false; @@ -88,7 +90,7 @@ static HEAP_IRAM_ATTR void record_allocation(const heap_trace_record_t *record) if (!s_tracing) { return; } -#if CONFIG_APPTRACE_SV_ENABLE +#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW esp_sysview_heap_trace_alloc(record->address, record->size, record->alloced_by); #endif } @@ -103,7 +105,7 @@ static HEAP_IRAM_ATTR void record_free(void *p, void **callers) if (!s_tracing) { return; } -#if CONFIG_APPTRACE_SV_ENABLE +#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW esp_sysview_heap_trace_free(p, callers); #endif } diff --git a/components/app_trace/include/esp_app_trace.h b/components/app_trace/include/esp_app_trace.h index ea84866ee01..45cac0526a1 100644 --- a/components/app_trace/include/esp_app_trace.h +++ b/components/app_trace/include/esp_app_trace.h @@ -16,22 +16,19 @@ extern "C" { #endif /** - * @brief Get custom trace initialization parameters (optional callback) + * @brief Initializes application tracing module for the selected destination and configuration. * - * This is an optional callback function that user applications can implement to provide - * custom trace configuration. A weak default implementation exists in the app_trace component - * that returns menuconfig defaults (APPTRACE_CONFIG_DEFAULT()). User applications can override - * this by providing their own implementation. - * - * This function is called during early system initialization (before app_main) on all cores. + * @note Should be called before any esp_apptrace_xxx call. * + * @return ESP_OK on success, otherwise see esp_err_t */ -esp_apptrace_config_t esp_apptrace_get_user_params(void); +esp_err_t esp_apptrace_init(const esp_apptrace_config_t *config); /** * @brief Configures down buffer. - * @note Needs to be called before attempting to receive any data using esp_apptrace_down_buffer_get and esp_apptrace_read. - * This function does not protect internal data by lock. + * + * @note Needs to be called before attempting to receive any data using esp_apptrace_down_buffer_get and + * esp_apptrace_read. This function does not protect internal data by lock. * * @param buf Address of buffer to use for down channel (host to target) data. * @param size Size of the buffer. @@ -262,8 +259,8 @@ int esp_apptrace_feof(void *stream); #define APPTRACE_JTAG_CONFIG_DEFAULT() { \ .dest = ESP_APPTRACE_DEST_JTAG, \ .dest_cfg.jtag = {0}, \ - .panic_flush_tmo = CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO, \ - .panic_flush_thresh = CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH, \ + .flush_tmo = CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO, \ + .flush_thresh = CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH, \ } #endif @@ -275,13 +272,12 @@ int esp_apptrace_feof(void *stream); .tx_pin_num = CONFIG_APPTRACE_UART_TX_GPIO, \ .rx_pin_num = CONFIG_APPTRACE_UART_RX_GPIO, \ .baud_rate = CONFIG_APPTRACE_UART_BAUDRATE, \ - .rx_buff_size = CONFIG_APPTRACE_UART_RX_BUFF_SIZE, \ .tx_buff_size = CONFIG_APPTRACE_UART_TX_BUFF_SIZE, \ .tx_msg_size = CONFIG_APPTRACE_UART_TX_MSG_SIZE, \ .task_prio = CONFIG_APPTRACE_UART_TASK_PRIO, \ }, \ - .panic_flush_tmo = CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO, \ - .panic_flush_thresh = CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH, \ + .flush_tmo = CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO, \ + .flush_thresh = CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH, \ } #endif diff --git a/components/app_trace/include/esp_app_trace_config.h b/components/app_trace/include/esp_app_trace_config.h index 0f827da97f4..027868d2cb4 100644 --- a/components/app_trace/include/esp_app_trace_config.h +++ b/components/app_trace/include/esp_app_trace_config.h @@ -8,10 +8,12 @@ #include "sdkconfig.h" -/* Default configurations for runtime selection (CONFIG_APPTRACE_DEST_NONE) - * These values are used when CONFIG_APPTRACE_DEST_NONE is selected in menuconfig. - * To customize at runtime, implement esp_apptrace_get_user_params() - * in your application. See esp_app_trace.h for details. +/* Default configurations for runtime selection (APPTRACE_DEST_ALL) + * These values are used when building with both JTAG and UART enabled + * to allow runtime selection. You can switch between destinations + * via esp_apptrace_get_user_params(). If this function is + * not provided by the application, JTAG is used by default with the + * configuration defined below. See esp_app_trace.h for details. */ #if !defined(CONFIG_APPTRACE_UART_TX_GPIO) || !defined(CONFIG_APPTRACE_UART_RX_GPIO) @@ -22,10 +24,6 @@ #define CONFIG_APPTRACE_BUF_SIZE 16384 #endif -#ifndef CONFIG_APPTRACE_UART_RX_BUFF_SIZE -#define CONFIG_APPTRACE_UART_RX_BUFF_SIZE 128 -#endif - #ifndef CONFIG_APPTRACE_UART_TX_BUFF_SIZE #define CONFIG_APPTRACE_UART_TX_BUFF_SIZE 4096 #endif @@ -54,8 +52,4 @@ #define CONFIG_APPTRACE_DEST_UART_NUM 1 #endif -#ifndef CONFIG_APPTRACE_SV_DEST_CPU_0 -#define CONFIG_APPTRACE_SV_DEST_CPU_0 1 -#endif - #endif /* ESP_APP_TRACE_CONFIG_H_ */ diff --git a/components/app_trace/include/esp_app_trace_types.h b/components/app_trace/include/esp_app_trace_types.h index ed48376bca6..cd4b2dee6fe 100644 --- a/components/app_trace/include/esp_app_trace_types.h +++ b/components/app_trace/include/esp_app_trace_types.h @@ -27,7 +27,7 @@ typedef struct { /** Tracing module synchronization lock */ typedef struct { spinlock_t mux; - unsigned int_state; + unsigned int int_state; } esp_apptrace_lock_t; /** Ring buffer control structure. @@ -59,7 +59,6 @@ typedef struct { int tx_pin_num; ///< TX pin number int rx_pin_num; ///< RX pin number int baud_rate; ///< Baud rate - uint32_t rx_buff_size; ///< RX ring buffer size uint32_t tx_buff_size; ///< TX ring buffer size uint32_t tx_msg_size; ///< Maximum size of the single message to transfer. int task_prio; ///< Task priority @@ -86,8 +85,8 @@ typedef struct { } jtag; } dest_cfg; ///< Destination-specific configuration - uint32_t panic_flush_tmo; ///< Panic flush timeout in milliseconds - uint32_t panic_flush_thresh; ///< Panic flush threshold in bytes + uint32_t flush_tmo; ///< Flush timeout in milliseconds + uint32_t flush_thresh; ///< Flush threshold in bytes } esp_apptrace_config_t; #ifdef __cplusplus diff --git a/components/app_trace/include/esp_sysview_trace.h b/components/app_trace/include/esp_sysview_trace.h index 98e2a9c908b..3f6ea49b35f 100644 --- a/components/app_trace/include/esp_sysview_trace.h +++ b/components/app_trace/include/esp_sysview_trace.h @@ -15,16 +15,37 @@ extern "C" { #include "SEGGER_RTT.h" // SEGGER_RTT_ESP_Flush #include "esp_app_trace_util.h" // ESP_APPTRACE_TMO_INFINITE +/* Forward declaration for esp_trace integration */ +typedef struct esp_trace_encoder esp_trace_encoder_t; + +/** + * @brief Inject encoder handle to SEGGER RTT layer. + * + * This maintains proper architectural layering. SEGGER RTT can accesses it's transport + * + * @param encoder Pointer to encoder instance from esp_trace + * + * @return 0 if successful, -1 if encoder is not initialized or missing required functions. + */ +int SEGGER_RTT_ESP_SetEncoder(esp_trace_encoder_t *encoder); + +/** + * @brief Get the encoder handle for accessing transport functions. + * + * This is used by SEGGER_SYSVIEW_Config_FreeRTOS.c to access transport lock functions. + * + * @return Pointer to encoder instance, or NULL if not initialized. + */ +esp_trace_encoder_t* SEGGER_SYSVIEW_GetEncoder(void); + /** * @brief Flushes remaining data in SystemView trace buffer to host. * - * @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinitely. - * * @return ESP_OK. */ -static inline esp_err_t esp_sysview_flush(uint32_t tmo) +static inline esp_err_t esp_sysview_flush(void) { - SEGGER_RTT_ESP_Flush(0, tmo); + SEGGER_RTT_ESP_Flush(); return ESP_OK; } diff --git a/components/app_trace/linker.lf b/components/app_trace/linker.lf index 4223e486dea..51473c671c7 100644 --- a/components/app_trace/linker.lf +++ b/components/app_trace/linker.lf @@ -1,24 +1,16 @@ [mapping:app_trace] archive: libapp_trace.a entries: - if APPTRACE_ENABLE = y: + if ESP_TRACE_TRANSPORT_APPTRACE = y: app_trace (noflash) app_trace_util (noflash) - if APPTRACE_DEST_JTAG = y || APPTRACE_DEST_NONE = y: + if APPTRACE_DEST_JTAG = y || APPTRACE_DEST_ALL = y: port_jtag (noflash) app_trace_membufs_proto (noflash) - if APPTRACE_DEST_UART = y || APPTRACE_DEST_NONE = y: + if APPTRACE_DEST_UART = y || APPTRACE_DEST_ALL = y: port_uart (noflash) - if APPTRACE_SV_ENABLE = y: - SEGGER_SYSVIEW (noflash) - SEGGER_RTT_esp (noflash) - SEGGER_SYSVIEW_Config_FreeRTOS (noflash) - SEGGER_SYSVIEW_FreeRTOS (noflash) - -[mapping:app_trace_driver] -archive: libesp_driver_gptimer.a -entries: - if APPTRACE_SV_TS_SOURCE_GPTIMER = y: - gptimer: gptimer_get_raw_count (noflash) - else: - * (default) + if ESP_TRACE_LIB_SEGGER_SYSVIEW = y: + SEGGER_SYSVIEW (noflash) + SEGGER_RTT_esp (noflash) + SEGGER_SYSVIEW_Config_FreeRTOS (noflash) + SEGGER_SYSVIEW_FreeRTOS (noflash) diff --git a/components/app_trace/port/port_uart.c b/components/app_trace/port/port_uart.c index f76edc51f02..c7b7920f800 100644 --- a/components/app_trace/port/port_uart.c +++ b/components/app_trace/port/port_uart.c @@ -286,10 +286,9 @@ static void esp_apptrace_uart_down_buffer_config(void *hw_data, uint8_t *buf, ui { esp_apptrace_uart_data_t *uart_data = hw_data; - uart_data->down_buffer = (uint8_t *)malloc(size); - if (uart_data->down_buffer == NULL) { - assert(false && "Failed to allocate apptrace uart down buffer!"); - } + assert(buf != NULL && "Down buffer cannot be NULL"); + + uart_data->down_buffer = buf; uart_data->down_buffer_size = size; } diff --git a/components/app_trace/sdkconfig.rename b/components/app_trace/sdkconfig.rename index 6b61ac0c221..59216fb3ff1 100644 --- a/components/app_trace/sdkconfig.rename +++ b/components/app_trace/sdkconfig.rename @@ -3,27 +3,26 @@ CONFIG_ESP32_APPTRACE_DESTINATION CONFIG_APPTRACE_DESTINATION CONFIG_ESP32_APPTRACE_DEST_TRAX CONFIG_APPTRACE_DEST_JTAG -CONFIG_ESP32_APPTRACE_ENABLE CONFIG_APPTRACE_ENABLE +CONFIG_ESP32_APPTRACE_ENABLE CONFIG_ESP_TRACE_TRANSPORT_APPTRACE CONFIG_ESP32_APPTRACE_LOCK_ENABLE CONFIG_APPTRACE_LOCK_ENABLE CONFIG_ESP32_APPTRACE_ONPANIC_HOST_FLUSH_TMO CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO CONFIG_ESP32_APPTRACE_POSTMORTEM_FLUSH_TRAX_THRESH CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH -CONFIG_SYSVIEW_ENABLE CONFIG_APPTRACE_SV_ENABLE -CONFIG_SYSVIEW_TS_SOURCE CONFIG_APPTRACE_SV_TS_SOURCE -CONFIG_SYSVIEW_TS_SOURCE_CCOUNT CONFIG_APPTRACE_SV_TS_SOURCE_CCOUNT -CONFIG_SYSVIEW_TS_SOURCE_ESP_TIMER CONFIG_APPTRACE_SV_TS_SOURCE_ESP_TIMER -CONFIG_SYSVIEW_MAX_TASKS CONFIG_APPTRACE_SV_MAX_TASKS -CONFIG_SYSVIEW_BUF_WAIT_TMO CONFIG_APPTRACE_SV_BUF_WAIT_TMO -CONFIG_SYSVIEW_EVT_OVERFLOW_ENABLE CONFIG_APPTRACE_SV_EVT_OVERFLOW_ENABLE -CONFIG_SYSVIEW_EVT_ISR_ENTER_ENABLE CONFIG_APPTRACE_SV_EVT_ISR_ENTER_ENABLE -CONFIG_SYSVIEW_EVT_ISR_EXIT_ENABLE CONFIG_APPTRACE_SV_EVT_ISR_EXIT_ENABLE -CONFIG_SYSVIEW_EVT_ISR_TO_SCHEDULER_ENABLE CONFIG_APPTRACE_SV_EVT_ISR_TO_SCHED_ENABLE -CONFIG_SYSVIEW_EVT_TASK_START_EXEC_ENABLE CONFIG_APPTRACE_SV_EVT_TASK_START_EXEC_ENABLE -CONFIG_SYSVIEW_EVT_TASK_STOP_EXEC_ENABLE CONFIG_APPTRACE_SV_EVT_TASK_STOP_EXEC_ENABLE -CONFIG_SYSVIEW_EVT_TASK_START_READY_ENABLE CONFIG_APPTRACE_SV_EVT_TASK_START_READY_ENABLE -CONFIG_SYSVIEW_EVT_TASK_STOP_READY_ENABLE CONFIG_APPTRACE_SV_EVT_TASK_STOP_READY_ENABLE -CONFIG_SYSVIEW_EVT_TASK_CREATE_ENABLE CONFIG_APPTRACE_SV_EVT_TASK_CREATE_ENABLE -CONFIG_SYSVIEW_EVT_TASK_TERMINATE_ENABLE CONFIG_APPTRACE_SV_EVT_TASK_TERMINATE_ENABLE -CONFIG_SYSVIEW_EVT_IDLE_ENABLE CONFIG_APPTRACE_SV_EVT_IDLE_ENABLE -CONFIG_SYSVIEW_EVT_TIMER_ENTER_ENABLE CONFIG_APPTRACE_SV_EVT_TIMER_ENTER_ENABLE -CONFIG_SYSVIEW_EVT_TIMER_EXIT_ENABLE CONFIG_APPTRACE_SV_EVT_TIMER_EXIT_ENABLE +CONFIG_SYSVIEW_ENABLE CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW +CONFIG_SYSVIEW_TS_SOURCE_CCOUNT CONFIG_ESP_TRACE_TS_SOURCE_CCOUNT +CONFIG_SYSVIEW_TS_SOURCE_ESP_TIMER CONFIG_ESP_TRACE_TS_SOURCE_ESP_TIMER +CONFIG_SYSVIEW_MAX_TASKS CONFIG_SEGGER_SYSVIEW_MAX_TASKS +CONFIG_SYSVIEW_BUF_WAIT_TMO CONFIG_SEGGER_SYSVIEW_BUF_WAIT_TMO +CONFIG_SYSVIEW_EVT_OVERFLOW_ENABLE CONFIG_SEGGER_SYSVIEW_EVT_OVERFLOW_ENABLE +CONFIG_SYSVIEW_EVT_ISR_ENTER_ENABLE CONFIG_SEGGER_SYSVIEW_EVT_ISR_ENTER_ENABLE +CONFIG_SYSVIEW_EVT_ISR_EXIT_ENABLE CONFIG_SEGGER_SYSVIEW_EVT_ISR_EXIT_ENABLE +CONFIG_SYSVIEW_EVT_ISR_TO_SCHEDULER_ENABLE CONFIG_SEGGER_SYSVIEW_EVT_ISR_TO_SCHED_ENABLE +CONFIG_SYSVIEW_EVT_TASK_START_EXEC_ENABLE CONFIG_SEGGER_SYSVIEW_EVT_TASK_START_EXEC_ENABLE +CONFIG_SYSVIEW_EVT_TASK_STOP_EXEC_ENABLE CONFIG_SEGGER_SYSVIEW_EVT_TASK_STOP_EXEC_ENABLE +CONFIG_SYSVIEW_EVT_TASK_START_READY_ENABLE CONFIG_SEGGER_SYSVIEW_EVT_TASK_START_READY_ENABLE +CONFIG_SYSVIEW_EVT_TASK_STOP_READY_ENABLE CONFIG_SEGGER_SYSVIEW_EVT_TASK_STOP_READY_ENABLE +CONFIG_SYSVIEW_EVT_TASK_CREATE_ENABLE CONFIG_SEGGER_SYSVIEW_EVT_TASK_CREATE_ENABLE +CONFIG_SYSVIEW_EVT_TASK_TERMINATE_ENABLE CONFIG_SEGGER_SYSVIEW_EVT_TASK_TERMINATE_ENABLE +CONFIG_SYSVIEW_EVT_IDLE_ENABLE CONFIG_SEGGER_SYSVIEW_EVT_IDLE_ENABLE +CONFIG_SYSVIEW_EVT_TIMER_ENTER_ENABLE CONFIG_SEGGER_SYSVIEW_EVT_TIMER_ENTER_ENABLE +CONFIG_SYSVIEW_EVT_TIMER_EXIT_ENABLE CONFIG_SEGGER_SYSVIEW_EVT_TIMER_EXIT_ENABLE diff --git a/components/app_trace/sys_view/Kconfig.sysview b/components/app_trace/sys_view/Kconfig.sysview new file mode 100644 index 00000000000..f9366bb49c1 --- /dev/null +++ b/components/app_trace/sys_view/Kconfig.sysview @@ -0,0 +1,113 @@ +menu "SEGGER SystemView" + depends on ESP_TRACE_LIB_SEGGER_SYSVIEW + choice SEGGER_SYSVIEW_DEST_CPU + prompt "CPU to trace" + depends on ESP_TRACE_TRANSPORT_APPTRACE && APPTRACE_DEST_UART && !ESP_SYSTEM_SINGLE_CORE_MODE + default SEGGER_SYSVIEW_DEST_CPU_0 + help + Define the CPU to trace. + + config SEGGER_SYSVIEW_DEST_CPU_0 + bool "CPU0" + help + Send tracing data for Pro CPU. + + config SEGGER_SYSVIEW_DEST_CPU_1 + bool "CPU1" + help + Send tracing data for App CPU. + + endchoice + + config SEGGER_SYSVIEW_MAX_TASKS + int "Maximum supported tasks" + range 1 64 + default 16 + help + Configures maximum supported tasks in sysview debug + + config SEGGER_SYSVIEW_BUF_WAIT_TMO + int "Trace buffer wait timeout" + default 500 + help + Configures timeout (in us) to wait for free space in trace buffer. + Set to -1 to wait forever and avoid lost events. + + config SEGGER_SYSVIEW_EVT_OVERFLOW_ENABLE + bool "Trace Buffer Overflow Event" + default y + help + Enables "Trace Buffer Overflow" event. + + config SEGGER_SYSVIEW_EVT_ISR_ENTER_ENABLE + bool "ISR Enter Event" + default y + help + Enables "ISR Enter" event. + + config SEGGER_SYSVIEW_EVT_ISR_EXIT_ENABLE + bool "ISR Exit Event" + default y + help + Enables "ISR Exit" event. + + config SEGGER_SYSVIEW_EVT_ISR_TO_SCHED_ENABLE + bool "ISR Exit to Scheduler Event" + default y + help + Enables "ISR to Scheduler" event. + + config SEGGER_SYSVIEW_EVT_TASK_START_EXEC_ENABLE + bool "Task Start Execution Event" + default y + help + Enables "Task Start Execution" event. + + config SEGGER_SYSVIEW_EVT_TASK_STOP_EXEC_ENABLE + bool "Task Stop Execution Event" + default y + help + Enables "Task Stop Execution" event. + + config SEGGER_SYSVIEW_EVT_TASK_START_READY_ENABLE + bool "Task Start Ready State Event" + default y + help + Enables "Task Start Ready State" event. + + config SEGGER_SYSVIEW_EVT_TASK_STOP_READY_ENABLE + bool "Task Stop Ready State Event" + default y + help + Enables "Task Stop Ready State" event. + + config SEGGER_SYSVIEW_EVT_TASK_CREATE_ENABLE + bool "Task Create Event" + default y + help + Enables "Task Create" event. + + config SEGGER_SYSVIEW_EVT_TASK_TERMINATE_ENABLE + bool "Task Terminate Event" + default y + help + Enables "Task Terminate" event. + + config SEGGER_SYSVIEW_EVT_IDLE_ENABLE + bool "System Idle Event" + default y + help + Enables "System Idle" event. + + config SEGGER_SYSVIEW_EVT_TIMER_ENTER_ENABLE + bool "Timer Enter Event" + default y + help + Enables "Timer Enter" event. + + config SEGGER_SYSVIEW_EVT_TIMER_EXIT_ENABLE + bool "Timer Exit Event" + default y + help + Enables "Timer Exit" event. +endmenu diff --git a/components/app_trace/sys_view/SEGGER/SEGGER_RTT.h b/components/app_trace/sys_view/SEGGER/SEGGER_RTT.h index 6e1c758f0d5..15d31ea411a 100644 --- a/components/app_trace/sys_view/SEGGER/SEGGER_RTT.h +++ b/components/app_trace/sys_view/SEGGER/SEGGER_RTT.h @@ -401,8 +401,8 @@ unsigned SEGGER_RTT_PutCharSkipNoLock (unsigned BufferIndex, char c); unsigned SEGGER_RTT_GetAvailWriteSpace (unsigned BufferIndex); unsigned SEGGER_RTT_GetBytesInBuffer (unsigned BufferIndex); -void SEGGER_RTT_ESP_FlushNoLock (unsigned long min_sz, unsigned long tmo); -void SEGGER_RTT_ESP_Flush (unsigned long min_sz, unsigned long tmo); +void SEGGER_RTT_ESP_FlushNoLock (void); +void SEGGER_RTT_ESP_Flush (void); // // Function macro for performance optimization // diff --git a/components/app_trace/sys_view/Sample/FreeRTOSV10.4/Config/esp/SEGGER_SYSVIEW_Config_FreeRTOS.c b/components/app_trace/sys_view/Sample/FreeRTOSV10.4/Config/esp/SEGGER_SYSVIEW_Config_FreeRTOS.c index 9761960d75e..eb40b843ab4 100644 --- a/components/app_trace/sys_view/Sample/FreeRTOSV10.4/Config/esp/SEGGER_SYSVIEW_Config_FreeRTOS.c +++ b/components/app_trace/sys_view/Sample/FreeRTOSV10.4/Config/esp/SEGGER_SYSVIEW_Config_FreeRTOS.c @@ -62,17 +62,20 @@ Revision: $Rev: 7745 $ #include "sdkconfig.h" #include "freertos/FreeRTOS.h" #include "SEGGER_SYSVIEW.h" -#include "esp_app_trace.h" -#include "esp_app_trace_util.h" #include "esp_intr_alloc.h" -#include "esp_clk_tree.h" -#include "esp_cpu.h" #include "soc/soc.h" #include "soc/interrupts.h" -#include "esp_private/esp_clk.h" +#include "esp_sysview_trace.h" +#include "esp_trace_port_encoder.h" +#include "esp_trace_port_transport.h" +#include "esp_trace_util.h" extern const SEGGER_SYSVIEW_OS_API SYSVIEW_X_OS_TraceAPI; +/* Encoder reference for accessing lock functions + * This is set by SEGGER_RTT_ESP_SetEncoder() during encoder initialization */ +extern esp_trace_encoder_t* SEGGER_SYSVIEW_GetEncoder(void); + /********************************************************************* * * Defines, configurable @@ -87,39 +90,6 @@ extern const SEGGER_SYSVIEW_OS_API SYSVIEW_X_OS_TraceAPI; // The target core name #define SYSVIEW_CORE_NAME "core0" // In dual core, this will be renamed by OpenOCD as core1 -// Determine which timer to use as timestamp source -#if CONFIG_APPTRACE_SV_TS_SOURCE_CCOUNT -#define TS_USE_CCOUNT 1 -#elif CONFIG_APPTRACE_SV_TS_SOURCE_ESP_TIMER -#define TS_USE_ESP_TIMER 1 -#else -#define TS_USE_TIMERGROUP 1 -#endif - -#if TS_USE_TIMERGROUP -#include "driver/gptimer.h" - -// Timer group timer divisor -#define SYSVIEW_TIMER_DIV 2 - -// GPTimer handle -gptimer_handle_t s_sv_gptimer; - -#endif // TS_USE_TIMERGROUP - -#if TS_USE_ESP_TIMER -// esp_timer provides 1us resolution -#define SYSVIEW_TIMESTAMP_FREQ (1000000) -#endif // TS_USE_ESP_TIMER - -#if TS_USE_CCOUNT -// CCOUNT is incremented at CPU frequency -#define SYSVIEW_TIMESTAMP_FREQ (CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ * 1000000) -#endif // TS_USE_CCOUNT - -// System Frequency. -#define SYSVIEW_CPU_FREQ (esp_clk_cpu_freq()) - // The lowest RAM address used for IDs (pointers) #define SYSVIEW_RAM_BASE (SOC_DROM_LOW) @@ -139,9 +109,7 @@ gptimer_handle_t s_sv_gptimer; // disables IRQs (disables rescheduling globally). So we can not use finite timeouts for locks and return error // in case of expiration, because error will not be handled and SEGGER's code will go further implying that // everything is fine, so for multi-core env we have to wait on underlying lock forever -#define SEGGER_LOCK_WAIT_TMO ESP_APPTRACE_TMO_INFINITE - -static esp_apptrace_lock_t s_sys_view_lock = {.mux = portMUX_INITIALIZER_UNLOCKED, .int_state = 0}; +#define SEGGER_LOCK_WAIT_TMO ESP_TRACE_TMO_INFINITE /********************************************************************* * @@ -171,78 +139,51 @@ static void _cbSendSystemDesc(void) { * ********************************************************************** */ -static int SEGGER_SYSVIEW_TS_Init(void) -{ - /* We only need to initialize something if we use Timer Group. - * esp_timer and ccount can be used as is. - */ -#if TS_USE_TIMERGROUP - // get clock source frequency - uint32_t counter_src_hz = 0; - ESP_ERROR_CHECK(esp_clk_tree_src_get_freq_hz( - (soc_module_clk_t)GPTIMER_CLK_SRC_DEFAULT, - ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &counter_src_hz)); - gptimer_config_t config = { - .clk_src = GPTIMER_CLK_SRC_DEFAULT, - .direction = GPTIMER_COUNT_UP, - .resolution_hz = counter_src_hz / SYSVIEW_TIMER_DIV, - }; - // pick any free GPTimer instance - ESP_ERROR_CHECK(gptimer_new_timer(&config, &s_sv_gptimer)); - /* Start counting */ - gptimer_enable(s_sv_gptimer); - gptimer_start(s_sv_gptimer); - return config.resolution_hz; -#else - return SYSVIEW_TIMESTAMP_FREQ; -#endif // TS_USE_TIMERGROUP -} - void SEGGER_SYSVIEW_Conf(void) { U32 disable_evts = 0; - int timestamp_freq = SEGGER_SYSVIEW_TS_Init(); - SEGGER_SYSVIEW_Init(timestamp_freq, SYSVIEW_CPU_FREQ, + int timestamp_freq = esp_trace_timestamp_init(); + SEGGER_SYSVIEW_Init(timestamp_freq, esp_trace_cpu_freq_get(), &SYSVIEW_X_OS_TraceAPI, _cbSendSystemDesc); SEGGER_SYSVIEW_SetRAMBase(SYSVIEW_RAM_BASE); -#if !CONFIG_APPTRACE_SV_EVT_OVERFLOW_ENABLE +#if !CONFIG_SEGGER_SYSVIEW_EVT_OVERFLOW_ENABLE disable_evts |= SYSVIEW_EVTMASK_OVERFLOW; #endif -#if !CONFIG_APPTRACE_SV_EVT_ISR_ENTER_ENABLE +#if !CONFIG_SEGGER_SYSVIEW_EVT_ISR_ENTER_ENABLE disable_evts |= SYSVIEW_EVTMASK_ISR_ENTER; #endif -#if !CONFIG_APPTRACE_SV_EVT_ISR_EXIT_ENABLE +#if !CONFIG_SEGGER_SYSVIEW_EVT_ISR_EXIT_ENABLE disable_evts |= SYSVIEW_EVTMASK_ISR_EXIT; #endif -#if !CONFIG_APPTRACE_SV_EVT_TASK_START_EXEC_ENABLE +#if !CONFIG_SEGGER_SYSVIEW_EVT_TASK_START_EXEC_ENABLE disable_evts |= SYSVIEW_EVTMASK_TASK_START_EXEC; #endif -#if !CONFIG_APPTRACE_SV_EVT_TASK_STOP_EXEC_ENABLE +#if !CONFIG_SEGGER_SYSVIEW_EVT_TASK_STOP_EXEC_ENABLE disable_evts |= SYSVIEW_EVTMASK_TASK_STOP_EXEC; #endif -#if !CONFIG_APPTRACE_SV_EVT_TASK_START_READY_ENABLE +#if !CONFIG_SEGGER_SYSVIEW_EVT_TASK_START_READY_ENABLE disable_evts |= SYSVIEW_EVTMASK_TASK_START_READY; #endif -#if !CONFIG_APPTRACE_SV_EVT_TASK_STOP_READY_ENABLE +#if !CONFIG_SEGGER_SYSVIEW_EVT_TASK_STOP_READY_ENABLE disable_evts |= SYSVIEW_EVTMASK_TASK_STOP_READY; #endif -#if !CONFIG_APPTRACE_SV_EVT_TASK_CREATE_ENABLE +#if !CONFIG_SEGGER_SYSVIEW_EVT_TASK_CREATE_ENABLE disable_evts |= SYSVIEW_EVTMASK_TASK_CREATE; #endif -#if !CONFIG_APPTRACE_SV_EVT_TASK_TERMINATE_ENABLE +#if !CONFIG_SEGGER_SYSVIEW_EVT_TASK_TERMINATE_ENABLE disable_evts |= SYSVIEW_EVTMASK_TASK_TERMINATE; #endif -#if !CONFIG_APPTRACE_SV_EVT_IDLE_ENABLE +#if !CONFIG_SEGGER_SYSVIEW_EVT_IDLE_ENABLE disable_evts |= SYSVIEW_EVTMASK_IDLE; #endif -#if !CONFIG_APPTRACE_SV_EVT_ISR_TO_SCHED_ENABLE +#if !CONFIG_SEGGER_SYSVIEW_EVT_ISR_TO_SCHED_ENABLE disable_evts |= SYSVIEW_EVTMASK_ISR_TO_SCHEDULER; #endif -#if !CONFIG_APPTRACE_SV_EVT_TIMER_ENTER_ENABLE +#if !CONFIG_SEGGER_SYSVIEW_EVT_TIMER_ENTER_ENABLE disable_evts |= SYSVIEW_EVTMASK_TIMER_ENTER; #endif -#if !CONFIG_APPTRACE_SV_EVT_TIMER_EXIT_ENABLE +#if !CONFIG_SEGGER_SYSVIEW_EVT_TIMER_EXIT_ENABLE disable_evts |= SYSVIEW_EVTMASK_TIMER_EXIT; #endif SEGGER_SYSVIEW_DisableEvents(disable_evts); @@ -250,15 +191,7 @@ void SEGGER_SYSVIEW_Conf(void) { U32 SEGGER_SYSVIEW_X_GetTimestamp(void) { -#if TS_USE_TIMERGROUP - uint64_t ts = 0; - gptimer_get_raw_count(s_sv_gptimer, &ts); - return (U32) ts; // return lower part of counter value -#elif TS_USE_CCOUNT - return esp_cpu_get_cycle_count(); -#elif TS_USE_ESP_TIMER - return (U32) esp_timer_get_time(); // return lower part of counter value -#endif + return esp_trace_timestamp_get(); } void SEGGER_SYSVIEW_X_RTT_Lock(void) @@ -271,17 +204,21 @@ void SEGGER_SYSVIEW_X_RTT_Unlock(void) unsigned SEGGER_SYSVIEW_X_SysView_Lock(void) { - esp_apptrace_tmo_t tmo; - esp_apptrace_tmo_init(&tmo, SEGGER_LOCK_WAIT_TMO); - esp_apptrace_lock_take(&s_sys_view_lock, &tmo); - // to be recursive save IRQ status on the stack of the caller to keep it from overwriting - return s_sys_view_lock.int_state; + esp_trace_encoder_t *encoder = SEGGER_SYSVIEW_GetEncoder(); + if (encoder) { + // Use encoder-level lock + return encoder->vt->take_lock(encoder, SEGGER_LOCK_WAIT_TMO); + } + return 0; } void SEGGER_SYSVIEW_X_SysView_Unlock(unsigned int_state) { - s_sys_view_lock.int_state = int_state; - esp_apptrace_lock_give(&s_sys_view_lock); + esp_trace_encoder_t *encoder = SEGGER_SYSVIEW_GetEncoder(); + if (encoder) { + // Use encoder-level unlock + encoder->vt->give_lock(encoder, int_state); + } } /*************************** End of file ****************************/ diff --git a/components/app_trace/sys_view/Sample/FreeRTOSV10.4/SEGGER_SYSVIEW_FreeRTOS.h b/components/app_trace/sys_view/Sample/FreeRTOSV10.4/SEGGER_SYSVIEW_FreeRTOS.h index 9bfa9b0a92a..5d67e93e043 100644 --- a/components/app_trace/sys_view/Sample/FreeRTOSV10.4/SEGGER_SYSVIEW_FreeRTOS.h +++ b/components/app_trace/sys_view/Sample/FreeRTOSV10.4/SEGGER_SYSVIEW_FreeRTOS.h @@ -75,7 +75,7 @@ Notes: ********************************************************************** */ -#define SYSVIEW_FREERTOS_MAX_NOF_TASKS CONFIG_APPTRACE_SV_MAX_TASKS +#define SYSVIEW_FREERTOS_MAX_NOF_TASKS CONFIG_SEGGER_SYSVIEW_MAX_TASKS /********************************************************************* * diff --git a/components/app_trace/sys_view/esp/SEGGER_RTT_esp.c b/components/app_trace/sys_view/esp/SEGGER_RTT_esp.c index e6ab35f13d5..fa93f452aa8 100644 --- a/components/app_trace/sys_view/esp/SEGGER_RTT_esp.c +++ b/components/app_trace/sys_view/esp/SEGGER_RTT_esp.c @@ -10,10 +10,13 @@ #include "SEGGER_SYSVIEW.h" #include "SEGGER_SYSVIEW_Conf.h" -#include "esp_app_trace.h" #include "esp_log.h" #include "esp_cpu.h" +#include "esp_trace_port_transport.h" +#include "esp_trace_port_encoder.h" +#include "esp_trace_types.h" #include "esp_private/startup_internal.h" +#include "adapters/adapter_encoder_sysview.h" const static char *TAG = "segger_rtt"; @@ -21,22 +24,27 @@ const static char *TAG = "segger_rtt"; // size of down channel data buf #define SYSVIEW_DOWN_BUF_SIZE 32 -#define SEGGER_STOP_WAIT_TMO 1000000 //us -#if CONFIG_APPTRACE_SV_BUF_WAIT_TMO == -1 -#define SEGGER_HOST_WAIT_TMO ESP_APPTRACE_TMO_INFINITE +#if CONFIG_SEGGER_SYSVIEW_BUF_WAIT_TMO == -1 +#define SEGGER_HOST_WAIT_TMO ESP_TRACE_TMO_INFINITE #else -#define SEGGER_HOST_WAIT_TMO CONFIG_APPTRACE_SV_BUF_WAIT_TMO +#define SEGGER_HOST_WAIT_TMO CONFIG_SEGGER_SYSVIEW_BUF_WAIT_TMO #endif static uint8_t s_events_buf[SYSVIEW_EVENTS_BUF_SZ]; static uint16_t s_events_buf_filled; static uint8_t s_down_buf[SYSVIEW_DOWN_BUF_SIZE]; -#if CONFIG_APPTRACE_SV_DEST_CPU_0 || CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE -#define APPTRACE_SV_DEST_CPU 0 -#else -#define APPTRACE_SV_DEST_CPU 1 -#endif // CONFIG_APPTRACE_SV_DEST_CPU_0 +/** + * @brief Encoder reference for SEGGER RTT layer + * + * This maintains proper architectural layering: + * - SEGGER RTT is part of the SystemView encoder implementation + * - It accesses transport through the encoder's transport reference (s_encoder->tp) + * - NOT through global singleton (that would be a layer violation) + * + * Set by SEGGER_RTT_ESP_SetEncoder() during encoder init. + */ +static esp_trace_encoder_t *s_encoder = NULL; /********************************************************************* * @@ -45,6 +53,80 @@ static uint8_t s_down_buf[SYSVIEW_DOWN_BUF_SIZE]; ********************************************************************** */ +/********************************************************************* +* +* SEGGER_RTT_ESP_SetEncoder() +* +* Function description +* Inject encoder handle from esp_trace adapter. +* This allows SEGGER RTT to access transport through the encoder's +* transport reference, maintaining proper architectural layering. +* +* Parameters +* encoder Pointer to encoder instance from esp_trace +* +* Return value +* 0 if successful, -1 if encoder is not initialized or missing required functions in transport. +*/ +int SEGGER_RTT_ESP_SetEncoder(esp_trace_encoder_t *encoder) +{ + /* Check if adapters have all required functions */ + if (!encoder || !encoder->ctx || + !encoder->vt->give_lock || + !encoder->vt->take_lock || + !encoder->tp->vt->down_buffer_config || + !encoder->tp->vt->write || + !encoder->tp->vt->flush_nolock || + !encoder->tp->vt->read || + !encoder->tp->vt->get_link_type) { + ESP_LOGE(TAG, "Encoder not initialized or missing required functions in transport"); + return -1; + } + + s_encoder = encoder; + + return 0; +} + +/********************************************************************* +* +* SEGGER_SYSVIEW_GetEncoder() +* +* Function description +* Returns the encoder handle for accessing transport functions. +* This is used by SEGGER_SYSVIEW_Config_FreeRTOS.c to access +* transport lock functions. +* +* Parameters +* None +* +* Return value +* Pointer to encoder instance, or NULL if not initialized. +*/ +esp_trace_encoder_t* SEGGER_SYSVIEW_GetEncoder(void) +{ + return s_encoder; +} + +/********************************************************************* +* +* SEGGER_RTT_ESP_GetDestCpu() +* +* Function description +* Gets the destination CPU from the encoder context. +* +* Parameters +* None +* +* Return value +* CPU ID (0 or 1) to trace +*/ +static int SEGGER_RTT_ESP_GetDestCpu(void) +{ + sysview_encoder_ctx_t *ctx = s_encoder->ctx; + return ctx->dest_cpu; +} + /********************************************************************* * * SEGGER_RTT_ESP_FlushNoLock() @@ -59,20 +141,29 @@ static uint8_t s_down_buf[SYSVIEW_DOWN_BUF_SIZE]; * Return value * None. */ -void SEGGER_RTT_ESP_FlushNoLock(unsigned long min_sz, unsigned long tmo) +void SEGGER_RTT_ESP_FlushNoLock(void) { esp_err_t res; + + if (!s_encoder) { + ESP_LOGE(TAG, "Encoder not initialized"); + return; + } + + esp_trace_transport_t *tp = s_encoder->tp; + if (s_events_buf_filled > 0) { - res = esp_apptrace_write(s_events_buf, s_events_buf_filled, tmo); + res = tp->vt->write(tp, s_events_buf, s_events_buf_filled, SEGGER_HOST_WAIT_TMO); if (res != ESP_OK) { - ESP_LOGE(TAG, "Failed to flush buffered events (%d)!", res); + ESP_LOGE(TAG, "Failed to write buffered events (%d)!", res); } } // flush even if we failed to write buffered events, because no new events will be sent after STOP - res = esp_apptrace_flush_nolock(min_sz, tmo); + res = tp->vt->flush_nolock(tp); if (res != ESP_OK) { - ESP_LOGE(TAG, "Failed to flush apptrace data (%d)!", res); + ESP_LOGE(TAG, "Failed to flush buffered events (%d)!", res); } + s_events_buf_filled = 0; } @@ -83,17 +174,14 @@ void SEGGER_RTT_ESP_FlushNoLock(unsigned long min_sz, unsigned long tmo) * Function description * Flushes buffered events. * -* Parameters -* min_sz Threshold for flushing data. If current filling level is above this value, data will be flushed. JTAG destinations only. -* tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinitely. * * Return value * None. */ -void SEGGER_RTT_ESP_Flush(unsigned long min_sz, unsigned long tmo) +void SEGGER_RTT_ESP_Flush(void) { SEGGER_SYSVIEW_LOCK(); - SEGGER_RTT_ESP_FlushNoLock(min_sz, tmo); + SEGGER_RTT_ESP_FlushNoLock(); SEGGER_SYSVIEW_UNLOCK(); } @@ -116,12 +204,12 @@ void SEGGER_RTT_ESP_Flush(unsigned long min_sz, unsigned long tmo) */ unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) { - uint32_t size = BufferSize; - esp_err_t res = esp_apptrace_read(pData, &size, 0); - if (res != ESP_OK) { + if (!s_encoder) { return 0; } - return size; + size_t size = BufferSize; + esp_err_t res = s_encoder->tp->vt->read(s_encoder->tp, pData, &size, 0); + return res != ESP_OK ? 0 : size; } /********************************************************************* @@ -150,12 +238,18 @@ unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void* pData, unsigned Buffe */ unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { + if (!s_encoder) { + return 0; // Encoder is not initialized + } + + esp_trace_transport_t *tp = s_encoder->tp; uint8_t *pbuf = (uint8_t *)pBuffer; uint8_t event_id = *pbuf; - if (esp_apptrace_get_destination() == ESP_APPTRACE_DEST_UART) { + if (tp->vt->get_link_type(tp) == ESP_TRACE_LINK_UART) { + int dest_cpu = SEGGER_RTT_ESP_GetDestCpu(); if ( - (APPTRACE_SV_DEST_CPU != esp_cpu_get_core_id()) && + (dest_cpu != esp_cpu_get_core_id()) && ( (event_id == SYSVIEW_EVTID_ISR_ENTER) || (event_id == SYSVIEW_EVTID_ISR_EXIT) || @@ -185,7 +279,7 @@ unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, u ESP_LOGE(TAG, "Too large event %u bytes!", NumBytes); return 0; } - if (esp_apptrace_get_destination() == ESP_APPTRACE_DEST_JTAG) { + if (tp->vt->get_link_type(tp) == ESP_TRACE_LINK_DEBUG_PROBE) { if (esp_cpu_get_core_id()) { // dual core specific code // use the highest - 1 bit of event ID to indicate core ID // the highest bit can not be used due to event ID encoding method @@ -199,7 +293,7 @@ unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, u if (s_events_buf_filled + NumBytes > SYSVIEW_EVENTS_BUF_SZ) { - esp_err_t res = esp_apptrace_write(s_events_buf, s_events_buf_filled, SEGGER_HOST_WAIT_TMO); + esp_err_t res = tp->vt->write(tp, s_events_buf, s_events_buf_filled, SEGGER_HOST_WAIT_TMO); if (res != ESP_OK) { return 0; // skip current data buffer only, accumulated events are kept } @@ -209,8 +303,8 @@ unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, u memcpy(&s_events_buf[s_events_buf_filled], pBuffer, NumBytes); s_events_buf_filled += NumBytes; - if (esp_apptrace_get_destination() == ESP_APPTRACE_DEST_UART) { - esp_err_t res = esp_apptrace_write(pBuffer, NumBytes, SEGGER_HOST_WAIT_TMO); + if (tp->vt->get_link_type(tp) == ESP_TRACE_LINK_UART) { + esp_err_t res = tp->vt->write(tp, pBuffer, NumBytes, SEGGER_HOST_WAIT_TMO); if (res != ESP_OK) { return 0; // skip current data buffer only, accumulated events are kept } @@ -218,7 +312,7 @@ unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, u } if (event_id == SYSVIEW_EVTID_TRACE_STOP) { - SEGGER_RTT_ESP_FlushNoLock(0, SEGGER_STOP_WAIT_TMO); + SEGGER_RTT_ESP_FlushNoLock(); } return NumBytes; } @@ -281,20 +375,8 @@ int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBu */ int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { - return esp_apptrace_down_buffer_config(s_down_buf, sizeof(s_down_buf)); + if (!s_encoder) { + return -1; + } + return s_encoder->tp->vt->down_buffer_config(s_encoder->tp, s_down_buf, sizeof(s_down_buf)); } - -/*************************** Init hook **************************** - * - * This init function is placed here because this port file will be linked whenever SystemView is used. - * It is used to initialize SystemView and app trace configuration by the init hook function. - * Otherwise, SystemView and app trace initialization needs to be done later in the app_main. - */ -ESP_SYSTEM_INIT_FN(sysview_early_init, SECONDARY, BIT(0), 120) -{ - esp_apptrace_set_header_size(ESP_APPTRACE_HEADER_SIZE_16); - SEGGER_SYSVIEW_Conf(); - - return ESP_OK; -} -/*************************** End of file ****************************/ diff --git a/components/app_trace/sys_view/ext/heap_trace_module.c b/components/app_trace/sys_view/ext/heap_trace_module.c index cbe81723d80..fc149c2e491 100644 --- a/components/app_trace/sys_view/ext/heap_trace_module.c +++ b/components/app_trace/sys_view/ext/heap_trace_module.c @@ -51,7 +51,7 @@ esp_err_t esp_sysview_heap_trace_start(uint32_t tmo) esp_err_t esp_sysview_heap_trace_stop(void) { ESP_EARLY_LOGV(TAG, "%s", __func__); - SEGGER_RTT_ESP_Flush(0, ESP_APPTRACE_TMO_INFINITE); + SEGGER_RTT_ESP_Flush(); return ESP_OK; } diff --git a/components/app_trace/test_apps/main/CMakeLists.txt b/components/app_trace/test_apps/main/CMakeLists.txt index 45781494003..ea49d3b9045 100644 --- a/components/app_trace/test_apps/main/CMakeLists.txt +++ b/components/app_trace/test_apps/main/CMakeLists.txt @@ -1,4 +1,4 @@ idf_component_register(SRCS "test_app_trace_main.c" "test_trace.c" INCLUDE_DIRS "." - PRIV_REQUIRES app_trace unity esp_driver_gptimer + PRIV_REQUIRES esp_trace unity esp_driver_gptimer WHOLE_ARCHIVE) diff --git a/components/app_trace/test_apps/main/test_trace.c b/components/app_trace/test_apps/main/test_trace.c index c4d4fcf2004..17488215225 100644 --- a/components/app_trace/test_apps/main/test_trace.c +++ b/components/app_trace/test_apps/main/test_trace.c @@ -65,7 +65,7 @@ const static char *TAG = "esp_apptrace_test"; #define ESP_APPTRACE_TEST_LOGV( format, ... ) ESP_APPTRACE_TEST_LOG_LEVEL(V, ESP_LOG_VERBOSE, format, ##__VA_ARGS__) #define ESP_APPTRACE_TEST_LOGO( format, ... ) ESP_APPTRACE_TEST_LOG_LEVEL(E, ESP_LOG_NONE, format, ##__VA_ARGS__) -#if CONFIG_APPTRACE_SV_ENABLE == 0 +#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW == 0 #define ESP_APPTRACE_TEST_WRITE(_b_, _s_) esp_apptrace_write(_b_, _s_, ESP_APPTRACE_TMO_INFINITE) #define ESP_APPTRACE_TEST_WRITE_FROM_ISR(_b_, _s_) esp_apptrace_write(_b_, _s_, 0UL) #define ESP_APPTRACE_TEST_WRITE_NOWAIT(_b_, _s_) esp_apptrace_write(_b_, _s_, 0) @@ -694,7 +694,7 @@ TEST_CASE("Log trace test (2 tasks)", "[trace][ignore]") vSemaphoreDelete(arg2.done); } -#else // #if CONFIG_APPTRACE_SV_ENABLE == 0 +#else // #if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW == 0 typedef struct { gptimer_handle_t gptimer; @@ -922,4 +922,4 @@ TEST_CASE("SysView trace test 2", "[trace][ignore]") TEST_ESP_OK(gptimer_disable(tim_arg2.gptimer)); TEST_ESP_OK(gptimer_del_timer(tim_arg2.gptimer)); } -#endif // #if CONFIG_APPTRACE_SV_ENABLE == 0 +#endif // CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW == 0 diff --git a/components/app_trace/test_apps/sdkconfig.ci.app_trace b/components/app_trace/test_apps/sdkconfig.ci.app_trace index ce6deb86769..c2a35aea831 100644 --- a/components/app_trace/test_apps/sdkconfig.ci.app_trace +++ b/components/app_trace/test_apps/sdkconfig.ci.app_trace @@ -1 +1,3 @@ -# app_trace is already enabled by sdkconfig.defaults, so no options are needed here +CONFIG_ESP_TRACE_LIB_NONE=y +CONFIG_ESP_TRACE_TRANSPORT_APPTRACE=y +CONFIG_APPTRACE_DEST_JTAG=y diff --git a/components/app_trace/test_apps/sdkconfig.ci.sysview b/components/app_trace/test_apps/sdkconfig.ci.sysview index 0308ac377b0..73ca998c6cd 100644 --- a/components/app_trace/test_apps/sdkconfig.ci.sysview +++ b/components/app_trace/test_apps/sdkconfig.ci.sysview @@ -1 +1,3 @@ -CONFIG_APPTRACE_SV_ENABLE=y +CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW=y +CONFIG_ESP_TRACE_TRANSPORT_APPTRACE=y +CONFIG_APPTRACE_DEST_JTAG=y diff --git a/components/app_trace/test_apps/sdkconfig.defaults b/components/app_trace/test_apps/sdkconfig.defaults index 2931bc40520..4b6639bbc19 100644 --- a/components/app_trace/test_apps/sdkconfig.defaults +++ b/components/app_trace/test_apps/sdkconfig.defaults @@ -1,3 +1,2 @@ CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=n -CONFIG_APPTRACE_ENABLE=y -CONFIG_APPTRACE_DEST_JTAG=y +CONFIG_ESP_TRACE_ENABLE=y diff --git a/components/esp_hw_support/intr_alloc.c b/components/esp_hw_support/intr_alloc.c index f55c35b632b..942e681c4fe 100644 --- a/components/esp_hw_support/intr_alloc.c +++ b/components/esp_hw_support/intr_alloc.c @@ -481,7 +481,7 @@ static void ESP_INTR_IRAM_ATTR shared_intr_isr(void *arg) esp_os_exit_critical_isr(&spinlock); } -#if CONFIG_APPTRACE_SV_ENABLE +#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW //Common non-shared isr handler wrapper. static void ESP_INTR_IRAM_ATTR non_shared_intr_isr(void *arg) { @@ -489,7 +489,7 @@ static void ESP_INTR_IRAM_ATTR non_shared_intr_isr(void *arg) esp_os_enter_critical_isr(&spinlock); traceISR_ENTER(ns_isr_arg->source + ETS_INTERNAL_INTR_SOURCE_OFF); // FIXME: can we call ISR and check os_task_switch_is_pended() after releasing spinlock? - // when CONFIG_APPTRACE_SV_ENABLE = 0 ISRs for non-shared IRQs are called without spinlock + // when CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW = 0 ISRs for non-shared IRQs are called without spinlock ns_isr_arg->isr(ns_isr_arg->isr_arg); // check if we will return to scheduler or to interrupted task after ISR if (!os_task_switch_is_pended(esp_cpu_get_core_id())) { @@ -631,7 +631,7 @@ esp_err_t esp_intr_alloc_intrstatus_bind(int source, int flags, uint32_t intrsta //Mark as unusable for other interrupt sources. This is ours now! vd->flags = VECDESC_FL_NONSHARED; if (handler) { -#if CONFIG_APPTRACE_SV_ENABLE +#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW non_shared_isr_arg_t *ns_isr_arg = heap_caps_malloc(sizeof(non_shared_isr_arg_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); if (!ns_isr_arg) { esp_os_exit_critical(&spinlock); @@ -831,7 +831,7 @@ static esp_err_t intr_free_for_current_cpu(intr_handle_t handle) if ((handle->vector_desc->flags & VECDESC_FL_NONSHARED) || free_shared_vector) { ESP_EARLY_LOGV(TAG, "esp_intr_free: Disabling int, killing handler"); -#if CONFIG_APPTRACE_SV_ENABLE +#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW if (!free_shared_vector) { void *isr_arg = esp_cpu_intr_get_handler_arg(handle->vector_desc->intno); if (isr_arg) { diff --git a/components/esp_system/CMakeLists.txt b/components/esp_system/CMakeLists.txt index 6aafeabb96a..73af8599a8d 100644 --- a/components/esp_system/CMakeLists.txt +++ b/components/esp_system/CMakeLists.txt @@ -129,8 +129,8 @@ target_link_libraries(${COMPONENT_LIB} INTERFACE "-u esp_system_include_startup_ # [refactor-todo] requirements due to init code, should be removable # once link-time registration of component init functions is used. -if(CONFIG_APPTRACE_ENABLE) - idf_component_optional_requires(PRIVATE app_trace) +if(CONFIG_ESP_TRACE_ENABLE) + idf_component_optional_requires(PRIVATE esp_trace) endif() if(CONFIG_ESP_COREDUMP_ENABLE) diff --git a/components/esp_system/panic.c b/components/esp_system/panic.c index 660459b5eb5..d269dd9c744 100644 --- a/components/esp_system/panic.c +++ b/components/esp_system/panic.c @@ -37,19 +37,10 @@ #include "esp_core_dump.h" #endif -#if CONFIG_APPTRACE_ENABLE -#include "esp_app_trace.h" -#if CONFIG_APPTRACE_SV_ENABLE -#include "SEGGER_RTT.h" +#if CONFIG_ESP_TRACE_ENABLE +#include "esp_trace.h" #endif -#if CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO == -1 -#define APPTRACE_ONPANIC_HOST_FLUSH_TMO ESP_APPTRACE_TMO_INFINITE -#else -#define APPTRACE_ONPANIC_HOST_FLUSH_TMO (1000*CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO) -#endif -#endif // CONFIG_APPTRACE_ENABLE - #if !CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT #include "hal/uart_hal.h" #endif @@ -367,12 +358,9 @@ void esp_panic_handler(panic_info_t *info) panic_print_str("Setting breakpoint at 0x"); panic_print_hex((uint32_t)info->addr); panic_print_str(" and returning...\r\n"); -#if CONFIG_APPTRACE_ENABLE -#if CONFIG_APPTRACE_SV_ENABLE - SEGGER_RTT_ESP_FlushNoLock(CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH, APPTRACE_ONPANIC_HOST_FLUSH_TMO); -#else - esp_apptrace_flush_nolock(CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH, APPTRACE_ONPANIC_HOST_FLUSH_TMO); -#endif + +#if CONFIG_ESP_TRACE_ENABLE + esp_trace_panic_handler(info); #endif disable_all_wdts(); @@ -408,14 +396,10 @@ void esp_panic_handler(panic_info_t *info) panic_print_str("\r\n"); -#if CONFIG_APPTRACE_ENABLE +#if CONFIG_ESP_TRACE_ENABLE esp_panic_handler_feed_wdts(); -#if CONFIG_APPTRACE_SV_ENABLE - SEGGER_RTT_ESP_FlushNoLock(CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH, APPTRACE_ONPANIC_HOST_FLUSH_TMO); -#else - esp_apptrace_flush_nolock(CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH, APPTRACE_ONPANIC_HOST_FLUSH_TMO); + esp_trace_panic_handler(info); #endif -#endif // CONFIG_APPTRACE_ENABLE #if CONFIG_ESP_COREDUMP_ENABLE esp_panic_handler_feed_wdts(); @@ -479,12 +463,8 @@ void __attribute__((noreturn, no_sanitize_undefined)) panic_abort(const char *de g_panic_abort = true; g_panic_abort_details = (char *) details; -#if CONFIG_APPTRACE_ENABLE -#if CONFIG_APPTRACE_SV_ENABLE - SEGGER_RTT_ESP_FlushNoLock(CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH, APPTRACE_ONPANIC_HOST_FLUSH_TMO); -#else - esp_apptrace_flush_nolock(CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH, APPTRACE_ONPANIC_HOST_FLUSH_TMO); -#endif +#if CONFIG_ESP_TRACE_ENABLE + esp_trace_panic_handler(NULL); #endif #ifdef __XTENSA__ diff --git a/components/esp_system/system_init_fn.txt b/components/esp_system/system_init_fn.txt index fd665d90d4c..5e048324b94 100644 --- a/components/esp_system/system_init_fn.txt +++ b/components/esp_system/system_init_fn.txt @@ -91,9 +91,11 @@ SECONDARY: 106: sleep_clock_startup_init in components/esp_hw_support/lowpower/p SECONDARY: 107: sleep_sys_periph_startup_init in components/esp_hw_support/sleep_system_peripheral.c on BIT(0) SECONDARY: 108: sleep_mmu_startup_init in components/esp_hw_support/lowpower/port/esp32c5/sleep_mmu.c on BIT(0) -# app_trace has to be initialized before systemview +# app_trace doesn't have init dependencies SECONDARY: 115: apptrace_early_init in components/app_trace/app_trace.c on ESP_SYSTEM_INIT_ALL_CORES -SECONDARY: 120: sysview_early_init in components/app_trace/sys_view/esp/SEGGER_RTT_esp.c on BIT(0) + +# esp_trace doesn't have init dependencies +SECONDARY: 120: esp_trace_early_init in components/esp_trace/src/core/esp_trace_core.c on ESP_SYSTEM_INIT_ALL_CORES # coredump doesn't have init dependencies SECONDARY: 130: init_coredump in components/espcoredump/src/core_dump_init.c on BIT(0) diff --git a/components/esp_trace/CMakeLists.txt b/components/esp_trace/CMakeLists.txt new file mode 100644 index 00000000000..f32c0d6d8d4 --- /dev/null +++ b/components/esp_trace/CMakeLists.txt @@ -0,0 +1,38 @@ +idf_build_get_property(target IDF_TARGET) + +if(${target} STREQUAL "linux") + return() +endif() + +if(CONFIG_ESP_TRACE_ENABLE) + set(srcs + "src/core/esp_trace_core.c" + "src/core/esp_trace_registry.c" + "src/ports/port_utils.c" + ) + + if(CONFIG_ESP_TRACE_TRANSPORT_APPTRACE) + list(APPEND srcs "adapters/transport/adapter_transport_apptrace.c") + endif() + + if(CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW) + list(APPEND srcs "adapters/encoder/adapter_encoder_sysview.c") + endif() + +endif() + +set(includes + "include" +) + +set(priv_requires "esp_driver_gptimer") +set(priv_includes "") +set(requires "app_trace") + +idf_component_register(SRCS ${srcs} + INCLUDE_DIRS ${includes} + PRIV_INCLUDE_DIRS ${priv_includes} + PRIV_REQUIRES ${priv_requires} + REQUIRES ${requires} + WHOLE_ARCHIVE TRUE + LDFRAGMENTS linker.lf) diff --git a/components/esp_trace/Kconfig b/components/esp_trace/Kconfig new file mode 100644 index 00000000000..b6f7ec9a9bc --- /dev/null +++ b/components/esp_trace/Kconfig @@ -0,0 +1,90 @@ +menu "ESP Trace Configuration" + + choice ESP_TRACE_LIBRARY + prompt "Trace library" + default ESP_TRACE_LIB_NONE + help + Select the trace library to use. + + config ESP_TRACE_LIB_SEGGER_SYSVIEW + bool "SEGGER SystemView" + + config ESP_TRACE_LIB_EXTERNAL + bool "External library from component registry" + help + Use a custom encoder provided by an external component. + The trace core system will be enabled but no built-in encoder is included. + + The external component MUST provide a header file named + "esp_trace_freertos_impl.h" in its include directories that + defines all required FreeRTOS trace macros. + + config ESP_TRACE_LIB_NONE + bool "Disabled" + endchoice + + config ESP_TRACE_LIB_NAME + string + default "sysview" if ESP_TRACE_LIB_SEGGER_SYSVIEW + default "ext" if ESP_TRACE_LIB_EXTERNAL + default "none" if ESP_TRACE_LIB_NONE + + rsource "$IDF_PATH/components/app_trace/sys_view/Kconfig.sysview" + + choice ESP_TRACE_TRANSPORT + prompt "Trace transport" + default ESP_TRACE_TRANSPORT_NONE + help + Select the trace backend to use. + + config ESP_TRACE_TRANSPORT_APPTRACE + bool "ESP-IDF apptrace" + + config ESP_TRACE_TRANSPORT_EXTERNAL + bool "External transport from component registry" + depends on !ESP_TRACE_LIB_NONE + help + Use a transport registered by an external component. + The trace core system will be enabled but no built-in transport is included. + + config ESP_TRACE_TRANSPORT_NONE + bool "None" + endchoice + + config ESP_TRACE_TRANSPORT_NAME + string + default "apptrace" if ESP_TRACE_TRANSPORT_APPTRACE + default "ext" if ESP_TRACE_TRANSPORT_EXTERNAL + default "none" if ESP_TRACE_TRANSPORT_NONE + + config ESP_TRACE_ENABLE + bool + default !ESP_TRACE_LIB_NONE + help + Internal config to enable tracing dependency around components. + + rsource "$IDF_PATH/components/app_trace/Kconfig.apptrace" + + choice ESP_TRACE_TIMESTAMP_SOURCE + depends on ESP_TRACE_ENABLE + prompt "Trace timestamp source" + default ESP_TRACE_TS_SOURCE_CCOUNT if ESP_SYSTEM_SINGLE_CORE_MODE && !PM_ENABLE && !IDF_TARGET_ESP32C3 + default ESP_TRACE_TS_SOURCE_GPTIMER if !ESP_SYSTEM_SINGLE_CORE_MODE && !PM_ENABLE && !IDF_TARGET_ESP32C3 + default ESP_TRACE_TS_SOURCE_ESP_TIMER if PM_ENABLE || IDF_TARGET_ESP32C3 + help + Select the timestamp source for tracing. + + config ESP_TRACE_TS_SOURCE_CCOUNT + bool "CPU cycle counter (CCOUNT)" + depends on ESP_SYSTEM_SINGLE_CORE_MODE && !PM_ENABLE && !IDF_TARGET_ESP32C3 + + config ESP_TRACE_TS_SOURCE_GPTIMER + bool "General Purpose Timer (Timer Group)" + depends on !PM_ENABLE && !IDF_TARGET_ESP32C3 + + config ESP_TRACE_TS_SOURCE_ESP_TIMER + bool "esp_timer high resolution timer" + + endchoice + +endmenu diff --git a/components/esp_trace/README.md b/components/esp_trace/README.md new file mode 100644 index 00000000000..3c6ca01c42b --- /dev/null +++ b/components/esp_trace/README.md @@ -0,0 +1,383 @@ +# ESP Trace Component + +The `esp_trace` component provides a unified tracing infrastructure for ESP-IDF. It acts as a central hub that coordinates different trace libraries (like SEGGER SystemView) and trace transports (like apptrace over JTAG/UART). + +## Overview + +The `esp_trace` component enables: +- Integration of multiple trace libraries through a common interface +- Flexible transport layer selection (JTAG, UART, or custom) +- Centralized trace configuration and management +- Support for both built-in and external trace libraries + +## Architecture + +The `esp_trace` component uses a **Port & Adapter** design pattern (also known as Hexagonal Architecture) to provide flexibility and extensibility: + +```mermaid +flowchart TB + +%% ======================= +%% Application Layer +%% ======================= +subgraph APP["📱 APPLICATION"] + app_main["app_main()"] + sysview_tracing["sysview_tracing.c"] + examples["tracing_heap_log.c"] + freertos_events["FreeRTOS Events"] +end + + +%% ======================= +%% Primary Port (Driver Port) +%% ======================= +subgraph PRIMARY["🔌 PUBLIC INTERFACE"] + api["- esp_trace.h + - esp_trace_init() + - esp_trace_record() + - esp_trace_write() + - esp_trace_flush() + - esp_trace_print()"] +end + +%% wiring: App uses API (labels land on the short pre-edges to api_in) +app_main -->|esp_trace.h| api +sysview_tracing -->|esp_trace.h| api +examples -->|esp_trace.h| api +freertos_events -->|trace macros| api +%% ======================= +%% Core Domain +%% ======================= +subgraph CORE["⚙️ CORE DOMAIN"] + corec["- esp_trace_core.c + - Creates encoder + transport instances + - Thread safe multi-core init + - Adapter coordination"] + regc["esp_trace_registry.c + - Runtime adapter discovery + - Maps names to vtables"] +end + +api --> corec +corec --- regc + +%% ======================= +%% Ports (Outbound) +%% ======================= +subgraph PORT_ENC["🔌 PORT Encoder"] + enc_port["esp_trace_port_encoder.h + Interface: + - init() + - print_event() + - write() + - flush()"] +end + +subgraph PORT_TR["🔌 PORT Transport"] + tr_port["esp_trace_port_transport.h + Interface: + - init() + - write() + - flush() + - is_host_connected()"] +end + +corec --> enc_port +corec --> tr_port + +%% ======================= +%% Adapters +%% ======================= +subgraph ADAPTERS["🔶 ADAPTERS"] + %% Encoders + enc_sysview["encoder_sysview.c implements sysview vtable"] + enc_ctf["encoder_ctf.c implements ctf vtable"] + enc_percepio["encoder_percepio.c implements percepio vtable"] + + %% Transports + tr_apptrace["transport_apptrace.c implements apptrace vtable"] +end + +enc_port --> enc_sysview +enc_port --> enc_ctf +enc_port --> enc_percepio +tr_port --> tr_apptrace + +%% ======================= +%% Host tools +%% ======================= +subgraph HOST_TOOLS["💻 TOOLS"] + direction LR + view_openocd["OpenOCD"] + view_sysview["SEGGER SystemView"] + view_ctf["Trace Compass"] + view_perfetto["Perfetto"] + view_babeltrace["Babeltrace2"] + view_percepio["TraceAlyzer"] +end + +%% invisible hub to center align +hub(("HOST")) + +%% Adapters feed into the hub (not directly into subgraph) +enc_sysview --> hub +enc_ctf --> hub +tr_apptrace --> hub + +%% hub connects downward to host tools +hub --> view_openocd & view_sysview & view_ctf & view_perfetto & view_babeltrace & view_percepio + +%% Styling +classDef appStyle fill:#e3f2fd,stroke:#1976d2,stroke-width:2px,color:#000 +classDef primaryStyle fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px,color:#000 +classDef coreStyle fill:#fff3e0,stroke:#f57c00,stroke-width:2px,color:#000 +classDef portStyle fill:#e1f5fe,stroke:#0277bd,stroke-width:3px,color:#000 +classDef adapterStyle fill:#fff9c4,stroke:#f9a825,stroke-width:2px,color:#000 +classDef hostStyle fill:#e8f5e9,stroke:#388e3c,stroke-width:2px,color:#000 +classDef hubStyle fill:#ffebee,stroke:#c62828,stroke-width:3px,color:#000 + +class APP appStyle +class PRIMARY,api primaryStyle +class CORE,corec,regc coreStyle +class PORT_ENC,PORT_TR,enc_port,tr_port portStyle +class ADAPTERS,enc_sysview,enc_ctf,enc_percepio,tr_apptrace adapterStyle +class HOST_TOOLS,view_openocd,view_sysview,view_ctf,view_perfetto,view_babeltrace,view_percepio hostStyle +class hub hubStyle + +``` + +The architecture follows a layered Port & Adapter pattern where the core manages trace sessions and coordinates adapters through well-defined interfaces (ports). Applications interact with a public API that forwards calls to the core, which then delegates work to encoder adapters (for trace formatting) and transport adapters (for data transmission). The registry enables runtime discovery of adapters that register themselves at link time using `ESP_TRACE_REGISTER_ENCODER()` and `ESP_TRACE_REGISTER_TRANSPORT()` macros. Encoders use transport ports to send formatted trace data, allowing any encoder to work with any transport. This separation means you can, for example, use SystemView with JTAG, other library with UART, or any other combination without modifying the core or adapters themselves. + +## How to Enable + +### Using Menuconfig + +1. Go to `Component config` → `ESP Trace Configuration` +2. Select your desired trace transport under `Trace transport`: + - **ESP-IDF apptrace** - Use built-in apptrace for custom tracing + - **None** - Disable tracing transport +3. Select your trace library under `Trace library`: + - **SEGGER SystemView** - Enable SystemView tracing + - **None** - Use standalone apptrace without a library + +### Using sdkconfig + +For standalone apptrace (without a trace library): + +``` +CONFIG_ESP_TRACE_ENABLE=y +CONFIG_ESP_TRACE_LIB_NONE=y +CONFIG_ESP_TRACE_TRANSPORT_APPTRACE=y +``` + +For SystemView tracing over JTAG: + +``` +CONFIG_ESP_TRACE_ENABLE=y +CONFIG_ESP_TRACE_LIB_SYSVIEW=y +CONFIG_ESP_TRACE_TRANSPORT_APPTRACE=y +CONFIG_APPTRACE_DEST_JTAG=y +``` + +## Component Dependencies + +To use tracing in your application, add `esp_trace` to your component's dependencies in `CMakeLists.txt`: + +```cmake +idf_component_register( + SRCS "main.c" + INCLUDE_DIRS "." + REQUIRES esp_trace +) +``` + +The `esp_trace` component will automatically include necessary sub-components (like `app_trace`) based on your configuration. + +## Adding External Trace Libraries + +The `esp_trace` component supports integration of external trace libraries through two types of adapters: + +- **Transport Adapters**: Handle the physical transport layer (e.g., JTAG, UART) +- **Encoder Adapters**: Handle the trace encoding/formatting (e.g., SystemView, custom formats) + +### Creating a Transport Adapter + +Transport adapters provide the physical communication layer for trace data. + +**Example: Creating a custom transport adapter** + +```c +#include "esp_trace_registry.h" +#include "esp_trace_port_transport.h" + +static esp_err_t my_transport_init(esp_trace_transport_t *tp, const void *cfg) +{ + // Initialize your transport + return ESP_OK; +} + +static esp_err_t my_transport_write(esp_trace_transport_t *tp, const void *data, size_t size, uint32_t tmo) +{ + // Write data to your transport + return ESP_OK; +} + +static esp_err_t my_transport_flush(esp_trace_transport_t *tp, uint32_t tmo) +{ + // Flush transport buffers + return ESP_OK; +} + +// Create the vtable with your functions +static const esp_trace_transport_vtable_t s_my_transport_vt = { + .init = my_transport_init, + .write = my_transport_write, + .flush = my_transport_flush, + // Add other required function pointers as needed +}; + +// Register the transport adapter +ESP_TRACE_REGISTER_TRANSPORT("my_transport", &s_my_transport_vt); +``` + +See `components/esp_trace/adapters/transport/adapter_transport_apptrace.c` for a complete reference implementation. + +### Creating an Encoder Adapter + +Encoder adapters handle trace data formatting and encoding for specific trace libraries. + +**Example: Creating a custom encoder adapter** + +```c +#include "esp_trace_registry.h" +#include "esp_trace_port_encoder.h" + +static esp_err_t my_encoder_init(esp_trace_encoder_t *enc, const void *cfg) +{ + // Initialize your encoder + // Configure transport if needed: + // enc->tp->vt->set_config(enc->tp, ESP_TRACE_TRANSPORT_CFG_HEADER_SIZE, &value); + return ESP_OK; +} + +static esp_err_t my_encoder_print_event(esp_trace_encoder_t *enc, + const char *event_name, + const char *formatted_str) +{ + // Format and send trace event + return ESP_OK; +} + +static esp_err_t my_encoder_flush(esp_trace_encoder_t *enc, uint32_t tmo) +{ + // Flush encoder buffers + return ESP_OK; +} + +// Create the vtable with your functions +static const esp_trace_encoder_vtable_t s_my_encoder_vt = { + .init = my_encoder_init, + .print_event = my_encoder_print_event, + .flush = my_encoder_flush, + // Add other required function pointers as needed +}; + +// Register the encoder adapter +ESP_TRACE_REGISTER_ENCODER("my_encoder", &s_my_encoder_vt); +``` + +**Key Points:** +- Use `ESP_TRACE_REGISTER_ENCODER(name, vtable)` to register your encoder +- Use `ESP_TRACE_REGISTER_TRANSPORT(name, vtable)` if you're implementing a custom transport +- Registration happens automatically at link time (no manual initialization needed) + +See `components/esp_trace/adapters/encoder/adapter_encoder_sysview.c` for a complete reference implementation. + +### FreeRTOS Trace Integration + +If your external trace library needs to capture FreeRTOS events, you must provide an `esp_trace_freertos_impl.h` header in your component's include directory. This header should define FreeRTOS trace macros (like `traceTASK_SWITCHED_IN()`, `traceISR_ENTER()`, etc.) that will be called by FreeRTOS. + +The `esp_trace` component includes this header when `CONFIG_ESP_TRACE_LIB_EXTERNAL=y` is set: + +```c +// In esp_trace_freertos.h +#if CONFIG_ESP_TRACE_LIB_EXTERNAL +#include "esp_trace_freertos_impl.h" +#endif +``` + +**Example esp_trace_freertos_impl.h:** +```c +#pragma once + +#include "your_trace_library.h" + +#define traceTASK_SWITCHED_IN() your_lib_task_switched_in(xTaskGetCurrentTaskHandle()) +#define traceISR_ENTER(irq_num) your_lib_isr_enter(irq_num) +#define traceISR_EXIT() your_lib_isr_exit() +// ... define other FreeRTOS trace macros as needed +``` + +### Component CMakeLists.txt Setup + +For external adapters to work properly, your component's CMakeLists.txt needs two important settings: + +**Example CMakeLists.txt:** +```cmake +idf_component_register( + SRCS "src/adapter_encoder_ctf.c" + INCLUDE_DIRS "include" + REQUIRES esp_trace + WHOLE_ARCHIVE TRUE # Important: ensures adapter registration is linked +) + +# Auto-register this component with esp_trace +# This allows esp_trace to find your esp_trace_freertos_impl.h +idf_component_get_property(esp_trace_lib esp_trace COMPONENT_LIB) +target_link_libraries(${esp_trace_lib} INTERFACE $) +``` + +**Important:** +- `WHOLE_ARCHIVE TRUE` ensures your adapter registration code is linked +- The `target_link_libraries` trick makes your headers visible to esp_trace component + +### Using an External Adapter + +1. **Add the component to your project dependencies** in your main component's `CMakeLists.txt`: + ```cmake + idf_component_register( + SRCS "main.c" + INCLUDE_DIRS "." + REQUIRES my_trace_component esp_trace + ) + ``` + +2. **Configure trace settings** in your project's `sdkconfig.defaults`: + ```ini + # Enable esp_trace + CONFIG_ESP_TRACE_ENABLE=y + + # Use external trace library + CONFIG_ESP_TRACE_LIB_EXTERNAL=y + + # Select transport (e.g., apptrace over UART) + CONFIG_ESP_TRACE_TRANSPORT_APPTRACE=y + CONFIG_APPTRACE_DEST_UART=y + CONFIG_APPTRACE_DEST_UART_NUM=0 + ``` + +3. **Build and run** - The adapter will be automatically registered and used when the component is linked. + +**Note:** External trace libraries should use `CONFIG_ESP_TRACE_LIB_EXTERNAL=y` instead of defining their own Kconfig option in the esp_trace menu. This keeps the external component independent from the esp_trace component. + +## Documentation + +For detailed usage instructions, see: +- [Application Tracing Guide](../../docs/en/api-guides/app_trace.rst) +- [Migration Guide](../../docs/en/migration-guides/release-6.x/6.0/system.rst) + +## Examples + +Examples demonstrating trace usage can be found in: +- `examples/system/app_trace_basic/` - Basic application tracing +- `examples/system/sysview_tracing/` - SystemView tracing example diff --git a/components/esp_trace/adapters/encoder/adapter_encoder_sysview.c b/components/esp_trace/adapters/encoder/adapter_encoder_sysview.c new file mode 100644 index 00000000000..6061c4110d6 --- /dev/null +++ b/components/esp_trace/adapters/encoder/adapter_encoder_sysview.c @@ -0,0 +1,148 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include + +#include "esp_err.h" +#include "esp_heap_caps.h" +#include "esp_trace_types.h" +#include "esp_trace_registry.h" +#include "esp_trace_port_encoder.h" +#include "esp_trace_port_transport.h" +#include "adapters/adapter_encoder_sysview.h" +#include "esp_trace_util.h" +#include "esp_sysview_trace.h" +#include "SEGGER_SYSVIEW.h" +#include "SEGGER_RTT.h" + +/* + * This adapter is used to create a public system-wide APIs for SystemView. + * All encoding and transport operations are done by SystemView component. (SEGGER_RTT_esp.c) + */ + +#define SYSVIEW_FLUSH_TMO_US (1000 * 1000) /* 1second */ +#define SYSVIEW_FLUSH_THRESH 0 + +/** + * @brief Initializes sysview encoder. + * This function is called for each core. + * Adapter implementations do NOT need their own multi-core protection. Core does it for them. + * + * @param enc Pointer to the encoder structure. Must not be NULL. + * @param enc_cfg Pointer to the encoder configuration. Can be NULL for defaults. + * + * @return ESP_OK on success, otherwise \see esp_err_t + */ +static esp_err_t init(esp_trace_encoder_t *enc, const void *enc_cfg) +{ + static bool initialized = false; + + if (!enc) { + return ESP_ERR_INVALID_ARG; + } + + if (initialized) { + return ESP_OK; + } + + const esp_trace_sysview_config_t *cfg = enc_cfg; + int dest_cpu = 0; // Default to CPU0 + + if (cfg) { + dest_cpu = cfg->dest_cpu; + } + + // Allocate and initialize encoder context + sysview_encoder_ctx_t *ctx = heap_caps_calloc(1, sizeof(*ctx), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); + if (!ctx) { + return ESP_ERR_NO_MEM; + } + + /* Segger Sysview needs locking mechanism. */ + esp_trace_lock_init(&ctx->lock); + ctx->dest_cpu = dest_cpu; + enc->ctx = ctx; + + if (SEGGER_RTT_ESP_SetEncoder(enc) != 0) { + heap_caps_free(ctx); + enc->ctx = NULL; + return ESP_ERR_NOT_SUPPORTED; + } + + /* Configure transport for SystemView requirements */ + if (enc->tp->vt->set_config) { + uint32_t flush_tmo = SYSVIEW_FLUSH_TMO_US; + uint32_t flush_thresh = SYSVIEW_FLUSH_THRESH; + uint32_t header_size = 2; /* SystemView uses 2-byte (16-bit) trace headers */ + enc->tp->vt->set_config(enc->tp, ESP_TRACE_TRANSPORT_CFG_FLUSH_TMO, &flush_tmo); + enc->tp->vt->set_config(enc->tp, ESP_TRACE_TRANSPORT_CFG_FLUSH_THRESH, &flush_thresh); + enc->tp->vt->set_config(enc->tp, ESP_TRACE_TRANSPORT_CFG_HEADER_SIZE, &header_size); + } + + SEGGER_SYSVIEW_Conf(); + + initialized = true; + + return ESP_OK; +} + +/** + * @brief Panic handler + * + * Called during system panic to finalize encoder state. + * + * @param enc Pointer to the encoder structure. Must not be NULL. + * @param info Panic information + */ +static void panic_handler(esp_trace_encoder_t *enc, const void *info) +{ + (void)enc; + (void)info; + + SEGGER_RTT_ESP_Flush(); +} + +/** + * @brief Takes the lock of sysview encoder. + * + * @param enc Pointer to the encoder structure. Must not be NULL. + * @param tmo Timeout for the operation (in us). + */ +static unsigned int take_lock(esp_trace_encoder_t *enc, uint32_t tmo_us) +{ + sysview_encoder_ctx_t *ctx = enc->ctx; + esp_trace_lock_take(&ctx->lock, tmo_us); + + return ctx->lock.int_state; +} + +/** + * @brief Gives the lock of sysview encoder. + * + * @param enc Pointer to the encoder structure. Must not be NULL. + * @param int_state The interrupt state. + */ +static void give_lock(esp_trace_encoder_t *enc, unsigned int_state) +{ + sysview_encoder_ctx_t *ctx = enc->ctx; + + // Restore interrupt state before releasing lock + ctx->lock.int_state = int_state; + esp_trace_lock_give(&ctx->lock); +} + +/** + * @brief Sysview encoder vtable. + */ +static const esp_trace_encoder_vtable_t s_sysview_vt = { + .init = init, + .panic_handler = panic_handler, + .take_lock = take_lock, + .give_lock = give_lock, +}; + +ESP_TRACE_REGISTER_ENCODER("sysview", &s_sysview_vt); diff --git a/components/esp_trace/adapters/transport/adapter_transport_apptrace.c b/components/esp_trace/adapters/transport/adapter_transport_apptrace.c new file mode 100644 index 00000000000..c7ecda0af70 --- /dev/null +++ b/components/esp_trace/adapters/transport/adapter_transport_apptrace.c @@ -0,0 +1,268 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include "esp_err.h" +#include "esp_log.h" +#include "esp_heap_caps.h" +#include "esp_trace_registry.h" +#include "esp_trace_port_transport.h" +#include "esp_trace_types.h" +#include "esp_app_trace.h" + +static const char *TAG = "adapter_transport_apptrace"; + +typedef struct { + uint32_t flush_tmo; + uint32_t flush_thresh; +} apptrace_ctx_t; + +/** + * @brief Initializes apptrace transport. + * This function is called for each core at system init time. + * Allocated context will not be freed and kept alive until the end of the program. + * Adapter implementations do NOT need their own multi-core protection. Core does it for them. + * + * @param tp Pointer to the transport structure. Must not be NULL. + * @param tp_cfg Pointer to the transport configuration. NULL means use default configuration. + * + * @return ESP_OK on success, otherwise \see esp_err_t + */ +static esp_err_t apptrace_init(esp_trace_transport_t *tp, const void *tp_cfg) +{ + if (!tp) { + return ESP_ERR_INVALID_ARG; + } + + /* Create context if not already done */ + if (!tp->ctx) { + apptrace_ctx_t *ctx = heap_caps_calloc(1, sizeof(*ctx), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); + if (!ctx) { + return ESP_ERR_NO_MEM; + } + tp->ctx = ctx; + } + + const esp_apptrace_config_t *cfg = (esp_apptrace_config_t *)tp_cfg; + esp_apptrace_config_t default_cfg = APPTRACE_CONFIG_DEFAULT(); + + if (!cfg) { + cfg = &default_cfg; + } + + /* Initialize context */ + apptrace_ctx_t *ctx = (apptrace_ctx_t *)tp->ctx; + ctx->flush_tmo = cfg->flush_tmo; + ctx->flush_thresh = cfg->flush_thresh; + + // Initialize underlying apptrace + esp_err_t err = esp_apptrace_init(cfg); + if (err != ESP_OK) { + heap_caps_free(ctx); + tp->ctx = NULL; + return err; + } + + return ESP_OK; +} + +/** + * @brief Reads data from apptrace transport. + * + * @param tp Pointer to the transport structure. Ignored. + * @param data Pointer to the data buffer. + * @param size Pointer to the size of the data buffer. + * @param tmo Timeout for the operation (in us). + * + * @return ESP_OK on success, otherwise \see esp_err_t + */ +static esp_err_t apptrace_read(esp_trace_transport_t *tp, void *data, size_t *size, uint32_t tmo) +{ + (void)tp; + return esp_apptrace_read(data, (uint32_t *)size, tmo); +} + +/** + * @brief Writes data to apptrace transport. + * + * @param tp Pointer to the transport structure. Ignored. + * @param data Pointer to the data buffer. + * @param size Size of the data buffer. + * @param tmo Timeout for the operation (in us). + * + * @return ESP_OK on success, otherwise \see esp_err_t + */ +static esp_err_t apptrace_write(esp_trace_transport_t *tp, const void *data, size_t size, uint32_t tmo) +{ + (void)tp; + return esp_apptrace_write(data, (uint32_t)size, tmo); +} + +/** + * @brief Configures down buffer for apptrace transport. + * + * @param tp Pointer to the transport structure. Ignored. + * @param buf Pointer to the data buffer. + * @param size Size of the data buffer. + * + * @return ESP_OK on success, otherwise \see esp_err_t + */ +static esp_err_t apptrace_down_buffer_config(esp_trace_transport_t *tp, uint8_t *buf, uint32_t size) +{ + (void)tp; + return esp_apptrace_down_buffer_config(buf, size); +} + +/** + * @brief Flushes data from apptrace transport without locking. + * + * Uses the panic configuration stored during initialization. + * + * @param tp Pointer to the transport structure. + * + * @return ESP_OK on success, otherwise \see esp_err_t + */ +static esp_err_t apptrace_flush_nolock(esp_trace_transport_t *tp) +{ + apptrace_ctx_t *ctx = (apptrace_ctx_t *)tp->ctx; + if (!ctx) { + return ESP_ERR_INVALID_STATE; + } + return esp_apptrace_flush_nolock(ctx->flush_thresh, ctx->flush_tmo); +} + +/** + * @brief Checks if the host is connected to apptrace transport. + * + * @param tp Pointer to the transport structure. Ignored. + * + * @return True if the host is connected, otherwise false. + */ +static bool apptrace_is_host_connected(esp_trace_transport_t *tp) +{ + (void)tp; + return esp_apptrace_host_is_connected(); +} + +/** + * @brief Gets the link type of apptrace transport. + * + * @param tp Pointer to the transport structure. Ignored. + * + * @return The link type of apptrace transport. + */ +static esp_trace_link_types_t apptrace_get_link_type(esp_trace_transport_t *tp) +{ + (void)tp; + + switch (esp_apptrace_get_destination()) { + case ESP_APPTRACE_DEST_JTAG: + return ESP_TRACE_LINK_DEBUG_PROBE; + case ESP_APPTRACE_DEST_UART: + return ESP_TRACE_LINK_UART; + default: + return ESP_TRACE_LINK_UNKNOWN; + } +} + +/** + * @brief Sets configuration for apptrace transport. + * + * @param tp Pointer to the transport structure. Must not be NULL. + * @param key The key of the configuration. + * @param value The value of the configuration. + */ +static esp_err_t apptrace_set_config(esp_trace_transport_t *tp, esp_trace_transport_cfg_key_t key, const void *value) +{ + if (!value) { + return ESP_ERR_INVALID_ARG; + } + + apptrace_ctx_t *ctx = (apptrace_ctx_t *)tp->ctx; + if (!ctx) { + return ESP_ERR_INVALID_STATE; + } + + switch (key) { + case ESP_TRACE_TRANSPORT_CFG_HEADER_SIZE: { + esp_apptrace_header_size_t header_size = *(const esp_apptrace_header_size_t *)value; + return esp_apptrace_set_header_size(header_size); + } + case ESP_TRACE_TRANSPORT_CFG_FLUSH_TMO: + ctx->flush_tmo = *(const uint32_t *)value; + return ESP_OK; + case ESP_TRACE_TRANSPORT_CFG_FLUSH_THRESH: + ctx->flush_thresh = *(const uint32_t *)value; + return ESP_OK; + default: + ESP_EARLY_LOGE(TAG, "Key %d is not supported", key); + return ESP_ERR_NOT_SUPPORTED; + } +} + +/** + * @brief Gets configuration from apptrace transport. + * + * @param tp Pointer to the transport structure. Must not be NULL. + * @param key Configuration key. + * @param value Pointer to store the configuration value. + * @return ESP_OK on success, ESP_ERR_INVALID_ARG if parameters are invalid, + * ESP_ERR_NOT_SUPPORTED if key is not supported. + */ +static esp_err_t apptrace_get_config(esp_trace_transport_t *tp, esp_trace_transport_cfg_key_t key, void *value) +{ + apptrace_ctx_t *ctx = (apptrace_ctx_t *)tp->ctx; + + if (!value) { + return ESP_ERR_INVALID_ARG; + } + + switch (key) { + case ESP_TRACE_TRANSPORT_CFG_FLUSH_TMO: + *(uint32_t *)value = ctx->flush_tmo; + return ESP_OK; + case ESP_TRACE_TRANSPORT_CFG_FLUSH_THRESH: + *(uint32_t *)value = ctx->flush_thresh; + return ESP_OK; + default: + ESP_EARLY_LOGE(TAG, "Key %d is not supported", key); + return ESP_ERR_NOT_SUPPORTED; + } +} + +void apptrace_panic_handler(esp_trace_transport_t *tp, const void *info) +{ + (void)info; + + apptrace_ctx_t *ctx = (apptrace_ctx_t *)tp->ctx; + if (!ctx) { + return; + } + + esp_apptrace_flush_nolock(ctx->flush_thresh, ctx->flush_tmo); +} + +/** + * @brief Apptrace transport vtable. + */ +static const esp_trace_transport_vtable_t s_apptrace_vt = { + .init = apptrace_init, + .set_config = apptrace_set_config, + .get_config = apptrace_get_config, + .read = apptrace_read, + .write = apptrace_write, + .flush_nolock = apptrace_flush_nolock, + .down_buffer_config = apptrace_down_buffer_config, + .is_host_connected = apptrace_is_host_connected, + .get_link_type = apptrace_get_link_type, + .panic_handler = apptrace_panic_handler, +}; + +ESP_TRACE_REGISTER_TRANSPORT("apptrace", &s_apptrace_vt); diff --git a/components/esp_trace/include/adapters/adapter_encoder_sysview.h b/components/esp_trace/include/adapters/adapter_encoder_sysview.h new file mode 100644 index 00000000000..cd367324ccd --- /dev/null +++ b/components/esp_trace/include/adapters/adapter_encoder_sysview.h @@ -0,0 +1,46 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include "esp_trace_util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief SystemView encoder configuration + */ +typedef struct { + /** + * @brief CPU to trace (0 or 1) + * + * Determines which CPU's events are captured by SystemView. + * Only relevant when using UART apptrace transport. + * + * - 0: Capture events from CPU0 (Pro CPU) + * - 1: Capture events from CPU1 (App CPU) + * + * @note This parameter is ignored for single-core systems + * @note This parameter is ignored when using JTAG transport + */ + int dest_cpu; +} esp_trace_sysview_config_t; + +/** + * @brief SystemView encoder context structure + * + * This structure is shared between the sysview adapter and the SEGGER RTT layer + * to allow proper access to encoder-specific configuration. + */ +typedef struct { + int dest_cpu; ///< CPU to trace (0 or 1) + esp_trace_lock_t lock; ///< Encoder lock +} sysview_encoder_ctx_t; + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_trace/include/esp_trace.h b/components/esp_trace/include/esp_trace.h new file mode 100644 index 00000000000..bbc96fa646e --- /dev/null +++ b/components/esp_trace/include/esp_trace.h @@ -0,0 +1,140 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "esp_err.h" +#include "esp_trace_types.h" + +/** + * @brief Trace session handle + * + * Opaque handle representing an active trace session. + */ +typedef struct esp_trace_handle *esp_trace_handle_t; + +/** + * @brief Parameters for opening a trace session + * + * This structure configures all aspects of a trace session, including the core behavior, + * encoder (trace library), and transport (communication channel). + */ +typedef struct { + /** + * @brief Core trace system configuration (optional) + * + * Currently reserved for future use. + */ + const esp_trace_config_t *core_cfg; + + /** + * @brief Encoder name (required) + * + * Must match a registered encoder name. Built-in encoders: + * - "sysview" - SEGGER SystemView protocol for FreeRTOS tracing + * - "raw" - Pass-through for raw binary data + */ + const char *encoder_name; + + /** + * @brief Encoder-specific configuration (optional) + * + * If NULL, encoder uses its default configuration. The structure type + * depends on the encoder being used. See encoder-specific documentation. + */ + const void *encoder_cfg; + + /** + * @brief Transport name (required) + * + * Must match a registered transport name. Built-in transports: + * - "apptrace" - Uses app_trace for JTAG or UART communication + * + */ + const char *transport_name; + + /** + * @brief Transport-specific configuration (optional) + * + * If NULL, transport uses its default configuration. The structure type + * depends on the transport being used: + * - For "apptrace": `esp_apptrace_config_t*` + * + * See transport-specific documentation for details. + */ + const void *transport_cfg; +} esp_trace_open_params_t; + +/** + * @brief Get trace initialization parameters for early system initialization + * + * User applications need to implement this function to provide a custom trace configuration. + * This function is called during system initialization before any other trace functions are called. + * + * @return Configuration + */ +esp_trace_open_params_t esp_trace_get_user_params(void); + +/** + * @brief Get the active trace handle + * + * @return The active trace handle + */ +esp_trace_handle_t esp_trace_get_active_handle(void); + +/** + * @brief Write data to the trace handle + * + * @param handle The trace handle + * @param data The data to write + * @param size The size of the data + * @param tmo The timeout in us + * + * @return ESP_OK on success, otherwise see esp_err_t + */ +esp_err_t esp_trace_write(esp_trace_handle_t handle, const void *data, size_t size, unsigned long tmo); + +/** + * @brief Flush the trace handle + * + * @param handle The trace handle + * @param tmo The timeout in us + * + * @return ESP_OK on success, otherwise see esp_err_t + */ +esp_err_t esp_trace_flush(esp_trace_handle_t handle, unsigned long tmo); + +/** + * @brief Check if the host is connected + * + * @param handle The trace handle + * + * @return true if the host is connected, otherwise false + */ +bool esp_trace_is_host_connected(esp_trace_handle_t handle); + +/** + * @brief Get the link type + * + * @param handle The trace handle + * + * @return The link type @see esp_trace_link_types_t + */ +esp_trace_link_types_t esp_trace_get_link_type(esp_trace_handle_t handle); + +/** + * @brief Panic flush the trace handle. This function is called from panic handler. + * + * @param handle The trace handle + */ +void esp_trace_panic_handler(const void *info); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_trace/include/esp_trace_freertos.h b/components/esp_trace/include/esp_trace_freertos.h new file mode 100644 index 00000000000..fc8d75c89db --- /dev/null +++ b/components/esp_trace/include/esp_trace_freertos.h @@ -0,0 +1,27 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "sdkconfig.h" + +/** + * @brief FreeRTOS trace macros dispatcher + * + * This header provides a unified interface for FreeRTOS tracing. + * It dispatches to the appropriate implementation based on configuration: + * + * - CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW: Uses SEGGER SystemView + * - CONFIG_ESP_TRACE_LIB_EXTERNAL: Uses external component's implementation + * (external component must provide esp_trace_freertos_impl.h see components/esp_trace/README.md for more details) + */ + +#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW +#include "SEGGER_SYSVIEW_FreeRTOS.h" +#undef INLINE /* to avoid redefinition */ +#elif CONFIG_ESP_TRACE_LIB_EXTERNAL +#include "esp_trace_freertos_impl.h" +#endif diff --git a/components/esp_trace/include/esp_trace_port_encoder.h b/components/esp_trace/include/esp_trace_port_encoder.h new file mode 100644 index 00000000000..2aa7bd8b9f6 --- /dev/null +++ b/components/esp_trace/include/esp_trace_port_encoder.h @@ -0,0 +1,80 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "esp_err.h" +#include "esp_trace_types.h" + +/* forward declarations */ +typedef struct esp_trace_encoder esp_trace_encoder_t; +typedef struct esp_trace_transport esp_trace_transport_t; + +/** + * @brief Encoder Virtual Table + * + * Defines the interface for trace encoders (libraries) + */ +typedef struct { + /** + * @brief Initialize encoder + * @param enc Encoder instance + * @param enc_cfg Encoder-specific configuration + * @return ESP_OK on success, error code otherwise + */ + esp_err_t (*init)(esp_trace_encoder_t *enc, const void *enc_cfg); + + /** + * @brief Write trace data + * @param enc Encoder instance + * @param data Data buffer to write + * @param size Size of data in bytes + * @param tmo Timeout in microseconds + * @return ESP_OK on success, error code otherwise + */ + esp_err_t (*write)(esp_trace_encoder_t *enc, const void *data, size_t size, uint32_t tmo); + + /** + * @brief Panic handler + * @param enc Encoder instance + * @param info Panic information + */ + void (*panic_handler)(esp_trace_encoder_t *enc, const void *info); + + /** + * @brief Take encoder lock + * @param enc Encoder instance + * @param tmo Timeout in microseconds + * @return Lock state (for recursive locking) or 0 on failure + */ + unsigned int (*take_lock)(esp_trace_encoder_t *enc, uint32_t tmo_us); + + /** + * @brief Give encoder lock + * @param enc Encoder instance + * @param int_state The interrupt state + */ + void (*give_lock)(esp_trace_encoder_t *enc, unsigned int_state); + +} esp_trace_encoder_vtable_t; + +/** + * @brief Encoder structure, represents an active trace library instance. + */ +struct esp_trace_encoder { + const esp_trace_encoder_vtable_t *vt; ///< Pointer to encoder vtable + esp_trace_transport_t *tp; ///< Pointer to transport instance + void *ctx; ///< Encoder specific context +}; + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_trace/include/esp_trace_port_transport.h b/components/esp_trace/include/esp_trace_port_transport.h new file mode 100644 index 00000000000..39d435e9242 --- /dev/null +++ b/components/esp_trace/include/esp_trace_port_transport.h @@ -0,0 +1,137 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include "esp_err.h" +#include "esp_trace_types.h" // esp_trace_link_types_t + +/* forward declarations */ +typedef struct esp_trace_transport esp_trace_transport_t; + +/** + * @brief Transport configuration keys + * + * Standard configuration keys that encoders can use to configure transport behavior. + */ +typedef enum { + ESP_TRACE_TRANSPORT_CFG_HEADER_SIZE, ///< (uint32_t*) Trace header size in bytes + ESP_TRACE_TRANSPORT_CFG_FLUSH_TMO, ///< (uint32_t*) Flush timeout in microseconds + ESP_TRACE_TRANSPORT_CFG_FLUSH_THRESH, ///< (uint32_t*) Flush threshold in bytes +} esp_trace_transport_cfg_key_t; + +/** + * @brief Transport Virtual Table + * + * Defines the interface for trace transports. + * + */ +typedef struct { + /** + * @brief Initialize transport + * @param tp Transport instance + * @param tp_cfg Transport-specific configuration + * @return ESP_OK on success, error code otherwise + */ + esp_err_t (*init)(esp_trace_transport_t *tp, const void *tp_cfg); + + /** + * @brief Set transport configuration + * @param tp Transport instance + * @param key Configuration key + * @param value Configuration value + * @return ESP_OK on success, error code otherwise + */ + esp_err_t (*set_config)(esp_trace_transport_t *tp, esp_trace_transport_cfg_key_t key, const void *value); + + /** + * @brief Get transport configuration + * @param tp Transport instance + * @param key Configuration key + * @param value Pointer to store configuration value + * @return ESP_OK on success, error code otherwise + */ + esp_err_t (*get_config)(esp_trace_transport_t *tp, esp_trace_transport_cfg_key_t key, void *value); + + /** + * @brief Read trace data + * @param tp Transport instance + * @param data Buffer to read data into + * @param size Pointer to size (in: buffer size, out: bytes read) + * @param tmo Timeout in microseconds + * @return ESP_OK on success, error code otherwise + */ + esp_err_t (*read)(esp_trace_transport_t *tp, void *data, size_t *size, uint32_t tmo); + + /** + * @brief Write trace data + * @param tp Transport instance + * @param data Data buffer to write + * @param size Size of data in bytes + * @param tmo Timeout in microseconds + * @return ESP_OK on success, error code otherwise + */ + esp_err_t (*write)(esp_trace_transport_t *tp, const void *data, size_t size, uint32_t tmo); + + /** + * @brief Flush without lock + * + * The transport should use its internally stored flush configuration (timeout, threshold) that was + * set during initialization. + * + * @param tp Transport instance + * @return ESP_OK on success, error code otherwise + */ + esp_err_t (*flush_nolock)(esp_trace_transport_t *tp); + + /** + * @brief Configure down buffer + * @param tp Transport instance + * @param buf Buffer pointer + * @param size Buffer size in bytes + * @return ESP_OK on success, error code otherwise + */ + esp_err_t (*down_buffer_config)(esp_trace_transport_t *tp, uint8_t *buf, uint32_t size); + + /** + * @brief Check if host is connected + * @param tp Transport instance + * @return true if host is connected, false otherwise + */ + bool (*is_host_connected)(esp_trace_transport_t *tp); + + /** + * @brief Get link type @see esp_trace_link_types_t + * @param tp Transport instance + * @return Link type + */ + esp_trace_link_types_t (*get_link_type)(esp_trace_transport_t *tp); + + /** + * @brief Panic handler + * @param tp Transport instance + * @param info Panic information + */ + void (*panic_handler)(esp_trace_transport_t *tp, const void *info); +} esp_trace_transport_vtable_t; + +/** + * @brief Transport structure representing an active transport instance. + */ +struct esp_trace_transport { + const esp_trace_transport_vtable_t *vt; ///< Pointer to transport vtable + void *ctx; ///< Transport-specific context +}; + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_trace/include/esp_trace_registry.h b/components/esp_trace/include/esp_trace_registry.h new file mode 100644 index 00000000000..d1ae8fa2864 --- /dev/null +++ b/components/esp_trace/include/esp_trace_registry.h @@ -0,0 +1,69 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once +#ifdef __cplusplus +extern "C" { +#endif + +#include "esp_err.h" +#include "esp_trace_port_encoder.h" +#include "esp_trace_port_transport.h" + +typedef struct { + const char *name; ///< Encoder name for lookup (e.g., "sysview") + const esp_trace_encoder_vtable_t *vtable; ///< Pointer to function table +} esp_trace_encoder_desc_t; + +typedef struct { + const char *name; ///< Transport name for lookup (e.g., "apptrace") + const esp_trace_transport_vtable_t *vtable; ///< Pointer to function table +} esp_trace_transport_desc_t; + +#define ESP_TRACE_SECTION(name) __attribute__((used, section(name))) + +/** + * @brief Register an encoder at compile time + * + * Place this macro in your encoder implementation file after defining the vtable. + * The encoder will be automatically discovered by the trace system at runtime. + * + * @note This creates a static descriptor in the .esp_trace_encoder_desc section + * @note The linker collects all descriptors and creates esp_trace_encoder_array + * @note Only use once per file (one encoder per implementation file) + * + * @param name_str Encoder name string (e.g., "sysview") + * @param vt_ptr Pointer to the encoder vtable structure + * + */ +#define ESP_TRACE_REGISTER_ENCODER(name_str, vt_ptr) \ + static const esp_trace_encoder_desc_t _esp_trace_encoder_desc \ + ESP_TRACE_SECTION(".esp_trace_encoder_desc") = { (name_str), (vt_ptr) } + +/** + * @brief Register a transport at compile time + * + * Place this macro in your transport implementation file after defining the vtable. + * The transport will be automatically discovered by the trace system at runtime. + * + * @note This creates a static descriptor in the .esp_trace_transport_desc section + * @note The linker collects all descriptors and creates esp_trace_transport_array + * @note Only use once per file (one transport per implementation file) + * + * @param name_str Transport name string (e.g., "apptrace") + * @param vt_ptr Pointer to the transport vtable structure + * + */ +#define ESP_TRACE_REGISTER_TRANSPORT(name_str, vt_ptr) \ + static const esp_trace_transport_desc_t _esp_trace_transport_desc \ + ESP_TRACE_SECTION(".esp_trace_transport_desc") = { (name_str), (vt_ptr) } + +/* Lookup functions */ +const esp_trace_encoder_vtable_t *esp_trace_find_encoder(const char *name); +const esp_trace_transport_vtable_t *esp_trace_find_transport(const char *name); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_trace/include/esp_trace_types.h b/components/esp_trace/include/esp_trace_types.h new file mode 100644 index 00000000000..5b1efae25ac --- /dev/null +++ b/components/esp_trace/include/esp_trace_types.h @@ -0,0 +1,28 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct esp_trace_config { + // Reserved for future use + int reserved; +} esp_trace_config_t; + +typedef enum { + ESP_TRACE_LINK_UNKNOWN = 0, + ESP_TRACE_LINK_DEBUG_PROBE, + ESP_TRACE_LINK_UART, +} esp_trace_link_types_t; + +/* Timeout constants for trace operations */ +#define ESP_TRACE_TMO_INFINITE (UINT32_MAX) + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_trace/include/esp_trace_util.h b/components/esp_trace/include/esp_trace_util.h new file mode 100644 index 00000000000..a2c158b6c84 --- /dev/null +++ b/components/esp_trace/include/esp_trace_util.h @@ -0,0 +1,123 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "esp_err.h" + +/////////////////////////////////////////////////////////////////////////////// +///////////////////////////////// TIMESTAMP /////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +/** + * @brief Initialize the trace timestamp source. + * + * This function initializes the trace timestamp source based on the configured + * source. The timestamp source can be the CPU cycle counter, esp_timer, or + * Timer Group, depending on configuration. + * + * @return The timestamp frequency in Hz. + */ +uint32_t esp_trace_timestamp_init(void); + +/** + * @brief Get the current timestamp value from the configured source for ESP trace. + * + * This function returns the current timestamp value, which can be sourced from + * the CPU cycle counter, esp_timer, or Timer Group, depending on configuration. + * + * @return The current timestamp value as a 32-bit unsigned integer. + */ +uint32_t esp_trace_timestamp_get(void); + +/** + * @brief Get the current CPU frequency in Hz. + * + * This function returns the current CPU frequency as reported by esp_clk_cpu_freq(). + * + * @return The CPU frequency in Hz. + */ +uint32_t esp_trace_cpu_freq_get(void); + +/////////////////////////////////////////////////////////////////////////////// +///////////////////////////////// TIMEOUT ///////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +/** + * @brief Timeout structure for trace operations + * + * This structure holds data necessary for measuring time intervals. + * After initialization via esp_trace_tmo_init(), user needs to call esp_trace_tmo_check() + * periodically to check timeout for expiration. + */ +typedef struct { + int64_t start; ///< Time interval start (in us) + int64_t tmo; ///< Timeout value (in us) + int64_t elapsed; ///< Elapsed time (in us) +} esp_trace_tmo_t; + +/** + * @brief Initialize timeout structure + * + * @param tmo Pointer to timeout structure to be initialized + * @param user_tmo Timeout value (in us). Use ESP_TRACE_TMO_INFINITE to wait indefinitely + */ +void esp_trace_tmo_init(esp_trace_tmo_t *tmo, uint32_t user_tmo); + +/** + * @brief Check timeout for expiration + * + * @param tmo Pointer to timeout structure + * @return ESP_OK if not expired, ESP_ERR_TIMEOUT if expired + */ +esp_err_t esp_trace_tmo_check(esp_trace_tmo_t *tmo); + +/////////////////////////////////////////////////////////////////////////////// +///////////////////////////////// LOCKS /////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +#include "spinlock.h" + +/** + * @brief Trace component lock structure + * + * Similar to esp_apptrace_lock_t but for trace component locking. + * This structure provides spinlock-based synchronization for trace components + * (encoders, transports, and other trace components). + */ +typedef struct { + spinlock_t mux; ///< Spinlock for synchronization + unsigned int int_state; ///< Interrupt state for recursive locking +} esp_trace_lock_t; + +/** + * @brief Initialize trace component lock + * @param lock Pointer to lock structure to be initialized + */ +void esp_trace_lock_init(esp_trace_lock_t *lock); + +/** + * @brief Take trace component lock + * @param lock Pointer to lock structure + * @param tmo Timeout in microseconds + * @return ESP_OK on success, ESP_ERR_TIMEOUT on timeout + */ +esp_err_t esp_trace_lock_take(esp_trace_lock_t *lock, uint32_t tmo_us); + +/** + * @brief Give trace component lock + * @param lock Pointer to lock structure + * @return ESP_OK on success + */ +esp_err_t esp_trace_lock_give(esp_trace_lock_t *lock); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_trace/linker.lf b/components/esp_trace/linker.lf new file mode 100644 index 00000000000..ba230f2034f --- /dev/null +++ b/components/esp_trace/linker.lf @@ -0,0 +1,50 @@ +# ESP Trace Component Linker Fragment +[mapping:esp_trace] +archive: libesp_trace.a +entries: + if ESP_TRACE_ENABLE = y: + esp_trace_core (noflash) + esp_trace_registry (noflash) + port_utils (noflash) + if ESP_TRACE_LIB_SEGGER_SYSVIEW: + adapter_encoder_sysview (noflash) + if ESP_TRACE_TRANSPORT_APPTRACE: + adapter_transport_apptrace (noflash) + +[mapping:esp_trace_driver] +archive: libesp_driver_gptimer.a +entries: + if ESP_TRACE_TS_SOURCE_GPTIMER = y: + gptimer: gptimer_get_raw_count (noflash) + else: + * (default) + +# Static registration of encoders and transports at link time + +[sections:esp_trace_encoder_desc] +entries: + .esp_trace_encoder_desc + +[sections:esp_trace_transport_desc] +entries: + .esp_trace_transport_desc + +[scheme:esp_trace_encoder_desc_default] +entries: + esp_trace_encoder_desc -> flash_rodata + +[scheme:esp_trace_transport_desc_default] +entries: + esp_trace_transport_desc -> flash_rodata + +[mapping:esp_trace_encoder_desc] +archive: * +entries: + * (esp_trace_encoder_desc_default); + esp_trace_encoder_desc -> flash_rodata KEEP() SORT(name) SURROUND(esp_trace_encoder_array) + +[mapping:esp_trace_transport_desc] +archive: * +entries: + * (esp_trace_transport_desc_default); + esp_trace_transport_desc -> flash_rodata KEEP() SORT(name) SURROUND(esp_trace_transport_array) diff --git a/components/esp_trace/src/core/esp_trace_core.c b/components/esp_trace/src/core/esp_trace_core.c new file mode 100644 index 00000000000..13fd193e8cb --- /dev/null +++ b/components/esp_trace/src/core/esp_trace_core.c @@ -0,0 +1,207 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * ESP Trace Core - Central trace session management + * + * This module manages trace sessions, coordinating encoders (trace libraries like SystemView) + * and transports (communication channels like JTAG, UART). + * + */ + +#include +#include "esp_cpu.h" +#include "esp_log.h" +#include "esp_err.h" +#include "esp_rom_sys.h" +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" +#include "esp_trace_registry.h" +#include "esp_trace.h" +#include "esp_trace_port_transport.h" +#include "esp_private/startup_internal.h" + +static const char *TAG = "esp_trace_core"; + +struct esp_trace_handle { + esp_trace_encoder_t encoder; + esp_trace_transport_t transport; +}; + +/** + * Singleton session management + * Only one trace session can be active at a time. + */ +static esp_trace_handle_t s_active_handle = NULL; +static portMUX_TYPE s_init_lock = portMUX_INITIALIZER_UNLOCKED; +static volatile int s_trace_handle_created = 0; + +static esp_err_t esp_trace_create(const esp_trace_open_params_t *params) +{ + if (!params || !params->encoder_name || !params->transport_name) { + return ESP_ERR_INVALID_ARG; + } + + if (s_active_handle) { + ESP_EARLY_LOGE(TAG, "Trace handle already created"); + return ESP_ERR_INVALID_STATE; + } + + const esp_trace_encoder_vtable_t *enc_vt = esp_trace_find_encoder(params->encoder_name); + const esp_trace_transport_vtable_t *tp_vt = esp_trace_find_transport(params->transport_name); + + if (!enc_vt || !tp_vt) { + ESP_EARLY_LOGE(TAG, "Encoder '%s' or transport '%s' not found", params->encoder_name, params->transport_name); + return ESP_ERR_NOT_FOUND; + } + + esp_trace_handle_t h = heap_caps_calloc(1, sizeof(*h), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); + if (!h) { + ESP_EARLY_LOGE(TAG, "Failed to allocate trace handle"); + return ESP_ERR_NO_MEM; + } + + h->encoder.vt = enc_vt; + h->transport.vt = tp_vt; + h->encoder.tp = &h->transport; + + s_active_handle = h; + + return ESP_OK; +} + +/* This function is called during early system initialization (before app_main) on all cores */ +static esp_err_t esp_trace_init(const esp_trace_open_params_t *params) +{ + esp_err_t err = ESP_OK; + esp_trace_handle_t h = NULL; + int core_id = esp_cpu_get_core_id(); + + /* Core 0 creates the handle if it doesn't exist yet */ + if (core_id == 0) { + if (!s_trace_handle_created) { + err = esp_trace_create(params); + if (err != ESP_OK) { + return err; + } + s_trace_handle_created = 1; + } + } else { + // There is NO guarantee that system init functions will execute on core 0 first + // So we need to wait for core 0 to create the handle + while (!s_trace_handle_created) { + esp_rom_delay_us(10); + } + } + + /* Handle is guaranteed to be created by now */ + h = s_active_handle; + + portENTER_CRITICAL(&s_init_lock); + + /* Setup transport first (encoder depends on it) */ + if (h->transport.vt->init) { + err = h->transport.vt->init(&h->transport, params->transport_cfg); + if (err != ESP_OK) { + ESP_EARLY_LOGE(TAG, "Transport open failed: %d", err); + goto cleanup; + } + } + + /* Setup encoder */ + if (h->encoder.vt->init) { + err = h->encoder.vt->init(&h->encoder, params->encoder_cfg); + if (err != ESP_OK) { + ESP_EARLY_LOGE(TAG, "Encoder init failed: %d", err); + goto cleanup; + } + } + + ESP_EARLY_LOGI(TAG, "Trace initialized on core %d: encoder='%s', transport='%s'", + core_id, params->encoder_name, params->transport_name); + + portEXIT_CRITICAL(&s_init_lock); + return ESP_OK; + +cleanup: + if (s_active_handle) { + /* Will not create a heap trace event. Returning error will cause an abort. */ + heap_caps_free(s_active_handle); + s_active_handle = NULL; + s_trace_handle_created = 0; + } + portEXIT_CRITICAL(&s_init_lock); + return err; +} + +esp_err_t esp_trace_write(esp_trace_handle_t h, const void *data, size_t size, unsigned long tmo) +{ + if (!h || !data || size == 0) { + return ESP_ERR_INVALID_ARG; + } + + if (!h->encoder.vt->write) { + return ESP_ERR_NOT_SUPPORTED; + } + + return h->encoder.vt->write(&h->encoder, data, size, tmo); +} + +bool esp_trace_is_host_connected(esp_trace_handle_t h) +{ + if (!h || !h->transport.vt->is_host_connected) { + return false; + } + + return h->transport.vt->is_host_connected(&h->transport); +} + +esp_trace_link_types_t esp_trace_get_link_type(esp_trace_handle_t h) +{ + if (!h || !h->transport.vt->get_link_type) { + return ESP_TRACE_LINK_UNKNOWN; + } + + return h->transport.vt->get_link_type(&h->transport); +} + +esp_trace_handle_t esp_trace_get_active_handle(void) +{ + return s_active_handle; +} + +void esp_trace_panic_handler(const void *info) +{ + esp_trace_handle_t h = s_active_handle; + if (!h) { + return; + } + if (h->encoder.vt->panic_handler) { + h->encoder.vt->panic_handler(&h->encoder, info); + } + + if (h->transport.vt->panic_handler) { + h->transport.vt->panic_handler(&h->transport, info); + } +} + +esp_trace_open_params_t __attribute__((weak)) esp_trace_get_user_params(void) +{ + esp_trace_open_params_t trace_params = { + .core_cfg = NULL, + .encoder_name = CONFIG_ESP_TRACE_LIB_NAME, + .encoder_cfg = NULL, /* Not used for now */ + .transport_name = CONFIG_ESP_TRACE_TRANSPORT_NAME, + .transport_cfg = NULL, /* Null means configure with the default parameters */ + }; + return trace_params; +} + +ESP_SYSTEM_INIT_FN(esp_trace_early_init, SECONDARY, ESP_SYSTEM_INIT_ALL_CORES, 120) +{ + esp_trace_open_params_t trace_params = esp_trace_get_user_params(); + return esp_trace_init(&trace_params); +} diff --git a/components/esp_trace/src/core/esp_trace_registry.c b/components/esp_trace/src/core/esp_trace_registry.c new file mode 100644 index 00000000000..c2b259cac97 --- /dev/null +++ b/components/esp_trace/src/core/esp_trace_registry.c @@ -0,0 +1,59 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include "esp_log.h" +#include "esp_err.h" +#include "esp_trace_registry.h" + +/** + * @file esp_trace_registry.c + * @brief Linker-time registration implementation + * + * The linker collects all ESP_TRACE_REGISTER_ENCODER() and ESP_TRACE_REGISTER_TRANSPORT() + * registrations into arrays with SURROUND symbols that mark the start and end: + * + * - _esp_trace_encoder_array_start ... _esp_trace_encoder_array_end + * - _esp_trace_transport_array_start ... _esp_trace_transport_array_end + * + * These are populated automatically by the linker script (linker.lf). + */ + +extern esp_trace_encoder_desc_t _esp_trace_encoder_array_start; +extern esp_trace_encoder_desc_t _esp_trace_encoder_array_end; +extern esp_trace_transport_desc_t _esp_trace_transport_array_start; +extern esp_trace_transport_desc_t _esp_trace_transport_array_end; + +const esp_trace_encoder_vtable_t *esp_trace_find_encoder(const char *name) +{ + if (!name) { + return NULL; + } + + for (const esp_trace_encoder_desc_t *it = &_esp_trace_encoder_array_start; + it < &_esp_trace_encoder_array_end; ++it) { + if (it->name && strcmp(it->name, name) == 0) { + return it->vtable; + } + } + + return NULL; +} + +const esp_trace_transport_vtable_t *esp_trace_find_transport(const char *name) +{ + if (!name) { + return NULL; + } + + for (const esp_trace_transport_desc_t *it = &_esp_trace_transport_array_start; + it < &_esp_trace_transport_array_end; ++it) { + if (it->name && strcmp(it->name, name) == 0) { + return it->vtable; + } + } + + return NULL; +} diff --git a/components/esp_trace/src/ports/port_utils.c b/components/esp_trace/src/ports/port_utils.c new file mode 100644 index 00000000000..30cad3d97c6 --- /dev/null +++ b/components/esp_trace/src/ports/port_utils.c @@ -0,0 +1,154 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include "sdkconfig.h" +#include "esp_timer.h" +#include "esp_clk_tree.h" +#include "esp_cpu.h" +#include "esp_private/esp_clk.h" +#include "esp_err.h" +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" + +#include "esp_trace_util.h" +#include "esp_trace_types.h" + +/////////////////////////////////////////////////////////////////////////////// +///////////////////////////////// TIMESTAMP /////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +// Determine which timer to use as timestamp source +#if CONFIG_ESP_TRACE_TS_SOURCE_CCOUNT +#define TS_USE_CCOUNT 1 +#elif CONFIG_ESP_TRACE_TS_SOURCE_ESP_TIMER +#define TS_USE_ESP_TIMER 1 +#else +#define TS_USE_TIMERGROUP 1 +#endif + +#if TS_USE_TIMERGROUP +#include "driver/gptimer.h" + +// Timer group timer divisor +#define ESP_TRACE_TIMER_DIV 2 + +// GPTimer handle +static gptimer_handle_t s_trace_gptimer; + +#endif // TS_USE_TIMERGROUP + +#if TS_USE_ESP_TIMER +// esp_timer provides 1us resolution +#define ESP_TRACE_TIMESTAMP_FREQ (1000000) +#endif // TS_USE_ESP_TIMER + +#if TS_USE_CCOUNT +// CCOUNT is incremented at CPU frequency +#define ESP_TRACE_TIMESTAMP_FREQ (CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ * 1000000) +#endif // TS_USE_CCOUNT + +// System Frequency. +#define ESP_TRACE_CPU_FREQ (esp_clk_cpu_freq()) + +uint32_t esp_trace_timestamp_init(void) +{ + /* We only need to initialize something if we use Timer Group. + * esp_timer and ccount can be used as is. + */ +#if TS_USE_TIMERGROUP + // get clock source frequency + uint32_t counter_src_hz = 0; + ESP_ERROR_CHECK(esp_clk_tree_src_get_freq_hz((soc_module_clk_t)GPTIMER_CLK_SRC_DEFAULT, + ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &counter_src_hz)); + gptimer_config_t config = { + .clk_src = GPTIMER_CLK_SRC_DEFAULT, + .direction = GPTIMER_COUNT_UP, + .resolution_hz = counter_src_hz / ESP_TRACE_TIMER_DIV, + }; + // pick any free GPTimer instance + ESP_ERROR_CHECK(gptimer_new_timer(&config, &s_trace_gptimer)); + /* Start counting */ + gptimer_enable(s_trace_gptimer); + gptimer_start(s_trace_gptimer); + return config.resolution_hz; +#else + return ESP_TRACE_TIMESTAMP_FREQ; +#endif // TS_USE_TIMERGROUP +} + +uint32_t esp_trace_timestamp_get(void) +{ +#if TS_USE_TIMERGROUP + uint64_t ts = 0; + gptimer_get_raw_count(s_trace_gptimer, &ts); + return (uint32_t)ts; // return lower part of counter value +#elif TS_USE_CCOUNT + return esp_cpu_get_cycle_count(); +#elif TS_USE_ESP_TIMER + return (uint32_t) esp_timer_get_time(); // return lower part of counter value +#endif +} + +uint32_t esp_trace_cpu_freq_get(void) +{ + return esp_clk_cpu_freq(); +} + +/////////////////////////////////////////////////////////////////////////////// +///////////////////////////////// TIMEOUT ///////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +void esp_trace_tmo_init(esp_trace_tmo_t *tmo, uint32_t user_tmo) +{ + tmo->start = esp_timer_get_time(); + tmo->tmo = user_tmo == ESP_TRACE_TMO_INFINITE ? (int64_t) -1 : (int64_t)user_tmo; + tmo->elapsed = 0; +} + +esp_err_t esp_trace_tmo_check(esp_trace_tmo_t *tmo) +{ + if (tmo->tmo != (int64_t) -1) { + tmo->elapsed = esp_timer_get_time() - tmo->start; + if (tmo->elapsed >= tmo->tmo) { + return ESP_ERR_TIMEOUT; + } + } + return ESP_OK; +} + +/////////////////////////////////////////////////////////////////////////////// +///////////////////////////////// LOCKS /////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +void esp_trace_lock_init(esp_trace_lock_t *lock) +{ + portMUX_INITIALIZE(&lock->mux); + lock->int_state = 0; +} + +esp_err_t esp_trace_lock_take(esp_trace_lock_t *lock, uint32_t tmo_us) +{ + esp_trace_tmo_t tmo; + esp_trace_tmo_init(&tmo, tmo_us); + + while (1) { + // Try to enter critical section (take the spinlock) with 0 timeout + if (portTRY_ENTER_CRITICAL(&lock->mux, 0) == pdTRUE) { + return ESP_OK; + } + + // Failed to enter critical section, check timeout + if (esp_trace_tmo_check(&tmo) != ESP_OK) { + return ESP_ERR_TIMEOUT; + } + } +} + +esp_err_t esp_trace_lock_give(esp_trace_lock_t *lock) +{ + portEXIT_CRITICAL(&lock->mux); + return ESP_OK; +} diff --git a/components/freertos/CMakeLists.txt b/components/freertos/CMakeLists.txt index 9f9db5fdef8..1401601f715 100644 --- a/components/freertos/CMakeLists.txt +++ b/components/freertos/CMakeLists.txt @@ -220,13 +220,8 @@ else() # linker to not drop this symbol. target_link_libraries(${COMPONENT_LIB} INTERFACE "-u app_main") - if(CONFIG_APPTRACE_SV_ENABLE) - # FreeRTOS headers have a dependency on app_trace when SystemView tracing is enabled - idf_component_optional_requires(PUBLIC app_trace) - elseif(CONFIG_APPTRACE_ENABLE) - # [refactor-todo]: app_startup.c esp_startup_start_app_other_cores() has a dependency on esp_apptrace_init() - # (called on CPU1). This should be resolved when link-time registration of startup functions is added. - idf_component_optional_requires(PRIVATE app_trace) + if(CONFIG_ESP_TRACE_ENABLE) + idf_component_optional_requires(PUBLIC esp_trace) endif() if(CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME) diff --git a/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/include/freertos/portmacro.h b/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/include/freertos/portmacro.h index d66b6df762e..b017c5105da 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/include/freertos/portmacro.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/include/freertos/portmacro.h @@ -401,7 +401,7 @@ bool xPortcheckValidStackMem(const void *ptr); // --------------------- App-Trace ------------------------- -#if CONFIG_APPTRACE_SV_ENABLE +#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW extern volatile BaseType_t xPortSwitchFlag; #define os_task_switch_is_pended(_cpu_) (xPortSwitchFlag) #else diff --git a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/portmacro.h b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/portmacro.h index 59ae3548ebe..a460e179ca4 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/portmacro.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/portmacro.h @@ -421,7 +421,7 @@ bool xPortcheckValidStackMem(const void *ptr); // --------------------- App-Trace ------------------------- -#if CONFIG_APPTRACE_SV_ENABLE +#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW extern volatile BaseType_t xPortSwitchFlag; #define os_task_switch_is_pended(_cpu_) (xPortSwitchFlag) #else diff --git a/components/freertos/FreeRTOS-Kernel/portable/riscv/include/freertos/portmacro.h b/components/freertos/FreeRTOS-Kernel/portable/riscv/include/freertos/portmacro.h index 2280f54d46e..a5b7b1b914d 100644 --- a/components/freertos/FreeRTOS-Kernel/portable/riscv/include/freertos/portmacro.h +++ b/components/freertos/FreeRTOS-Kernel/portable/riscv/include/freertos/portmacro.h @@ -740,7 +740,7 @@ bool xPortcheckValidStackMem(const void *ptr); // --------------------- App-Trace ------------------------- -#if CONFIG_APPTRACE_SV_ENABLE +#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW extern volatile UBaseType_t xPortSwitchFlag[portNUM_PROCESSORS]; #define os_task_switch_is_pended(_cpu_) (xPortSwitchFlag[_cpu_]) #else diff --git a/components/freertos/FreeRTOS-Kernel/portable/xtensa/include/freertos/portmacro.h b/components/freertos/FreeRTOS-Kernel/portable/xtensa/include/freertos/portmacro.h index ce0b2064193..b8200604142 100644 --- a/components/freertos/FreeRTOS-Kernel/portable/xtensa/include/freertos/portmacro.h +++ b/components/freertos/FreeRTOS-Kernel/portable/xtensa/include/freertos/portmacro.h @@ -658,7 +658,7 @@ bool xPortcheckValidStackMem(const void *ptr); // --------------------- App-Trace ------------------------- -#if CONFIG_APPTRACE_SV_ENABLE +#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW extern volatile uint32_t port_switch_flag[portNUM_PROCESSORS]; #define os_task_switch_is_pended(_cpu_) (port_switch_flag[_cpu_]) #else diff --git a/components/freertos/config/include/freertos/FreeRTOSConfig.h b/components/freertos/config/include/freertos/FreeRTOSConfig.h index 8a505d5bc26..1e3db20e98e 100644 --- a/components/freertos/config/include/freertos/FreeRTOSConfig.h +++ b/components/freertos/config/include/freertos/FreeRTOSConfig.h @@ -35,7 +35,7 @@ #endif /* apptrace module increases minimum stack usage */ -#if CONFIG_APPTRACE_ENABLE +#if CONFIG_ESP_TRACE_TRANSPORT_APPTRACE #define STACK_OVERHEAD_APPTRACE 1280 #else #define STACK_OVERHEAD_APPTRACE 0 @@ -232,10 +232,9 @@ * Note: Include trace macros here and not above as trace macros are dependent on some of the FreeRTOS configs */ #ifndef __ASSEMBLER__ - #if CONFIG_SYSVIEW_ENABLE - #include "SEGGER_SYSVIEW_FreeRTOS.h" - #undef INLINE /* to avoid redefinition */ - #endif /* CONFIG_SYSVIEW_ENABLE */ + #if CONFIG_ESP_TRACE_ENABLE + #include "esp_trace_freertos.h" + #endif #if CONFIG_FREERTOS_SMP diff --git a/components/xtensa/xtensa_intr.c b/components/xtensa/xtensa_intr.c index 4d374aad50e..a2f9bfc69b3 100644 --- a/components/xtensa/xtensa_intr.c +++ b/components/xtensa/xtensa_intr.c @@ -156,7 +156,7 @@ xt_handler xt_set_interrupt_handler(int n, xt_handler f, void * arg) return ((old == &xt_unhandled_interrupt) ? 0 : old); } -#if CONFIG_APPTRACE_SV_ENABLE +#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW void * xt_get_interrupt_handler_arg(int n) { xt_handler_table_entry * entry; diff --git a/docs/en/api-guides/app_trace.rst b/docs/en/api-guides/app_trace.rst index 1733f0952e8..dcc88f7410b 100644 --- a/docs/en/api-guides/app_trace.rst +++ b/docs/en/api-guides/app_trace.rst @@ -41,7 +41,7 @@ Using of this feature depends on two components: 1. **Host side:** Application tracing is done over JTAG, so it needs OpenOCD to be set up and running on host machine. For instructions on how to set it up, please see :doc:`JTAG Debugging <../api-guides/jtag-debugging/index>` for details. -2. **Target side:** Application tracing functionality can be enabled in menuconfig. **Important:** You must first enable application tracing by going to ``Component config`` > ``Application Level Tracing`` > ``Enable Application Level Tracing`` (:ref:`CONFIG_APPTRACE_ENABLE`). After enabling this option, you can configure the destination for the trace data. For UART interfaces, users have to define port number, baud rate, TX and RX pins numbers, and additional UART-related parameters. When FreeRTOS SystemView Tracing is enabled, selected destination will be used for systemview tracing as well. +2. **Target side:** Application tracing functionality can be enabled in menuconfig. **Important:** You must first enable application tracing by going to ``Component config`` > ``ESP Trace Configuration`` > ``Trace transport`` and selecting ``ESP-IDF apptrace``. After that, configuration can be done at ``Component config`` > ``ESP Trace Configuration`` > ``Application Level Tracing``. Here you can configure the destination for the trace data. For UART interfaces, users have to define port number, baud rate, TX and RX pins numbers, and additional UART-related parameters. When any trace library is selected (for example SEGGER SystemView), these settings will be used for the library as well. .. note:: @@ -65,7 +65,40 @@ How to Use This Library This library provides APIs for transferring arbitrary data between the host and {IDF_TARGET_NAME}. When enabled in menuconfig, the application tracing module is automatically initialized during system startup using configuration from menuconfig. Users can then call corresponding APIs to send, receive, or flush the data. -Optionally, users can override the default configuration by implementing the weak callback function :cpp:func:`esp_apptrace_get_user_params()`. +Optionally, users can override the default configuration by implementing the weak callback function :cpp:func:`esp_apptrace_get_user_params()`. This callback will be active when there is no selected trace library, meaning the Application Level Tracing library (``app_trace`` component) will be working standalone. Otherwise, :cpp:func:`esp_trace_get_user_params()` will be used for overriding the configuration. + +Quick Start Summary +------------------- + +1. Standalone usage with Application Level Tracing APIs + + In menuconfig, disable the trace library and enable the Application Level Tracing transport: + + - ``Component config`` > ``ESP Trace Configuration`` > ``Trace library``: select ``None`` + - ``Component config`` > ``ESP Trace Configuration`` > ``Trace transport``: select ``ESP-IDF apptrace`` + + Alternatively, set these options in ``sdkconfig.defaults`` to enforce standalone mode: + + .. code-block:: none + + CONFIG_ESP_TRACE_ENABLE=y + CONFIG_ESP_TRACE_LIB_NONE=y + CONFIG_ESP_TRACE_TRANSPORT_APPTRACE=y + + Configure the destination in ``Component config`` > ``ESP Trace Configuration`` > ``Application Level Tracing``. + +2. Runtime configuration via ``esp_apptrace_get_user_params()`` + + - If you select ``All (runtime selection)`` in Kconfig (``APPTRACE_DEST_ALL``), the callback can switch between JTAG and UART at runtime and adjust their parameters. + - If you select a single destination (JTAG or UART) in Kconfig, the callback can override that destination's parameters at runtime, but it cannot switch the destination type. + +.. note:: + + Application tracing can also work as a transport adapter to the esp_trace library. In this case, the Application Level Tracing library will not be used directly, but rather through the selected esp_trace library with new APIs. + +.. note:: + + The code examples below are valid when the Application Level Tracing library is used standalone without a trace library. .. _app_trace-application-specific-tracing: @@ -110,7 +143,7 @@ In general, users should decide what type of data should be transferred in every return res; } - ``esp_apptrace_write()`` function uses memcpy to copy user data to the internal buffer. In some cases, it can be more optimal to use ``esp_apptrace_buffer_get()`` and ``esp_apptrace_buffer_put()`` functions. They allow developers to allocate buffer and fill it themselves. The following piece of code shows how to do this. + The :cpp:func:`esp_apptrace_write()` function uses memcpy to copy user data to the internal buffer. In some cases, it can be more optimal to use :cpp:func:`esp_apptrace_buffer_get()` and :cpp:func:`esp_apptrace_buffer_put()` functions. They allow developers to allocate buffer and fill it themselves. The following piece of code shows how to do this. .. code-block:: c @@ -157,7 +190,7 @@ In general, users should decide what type of data should be transferred in every ... } - ``esp_apptrace_read()`` function uses memcpy to copy host data to user buffer. In some casesm it can be more optimal to use ``esp_apptrace_down_buffer_get()`` and ``esp_apptrace_down_buffer_put()`` functions. They allow developers to occupy chunk of read buffer and process it in-place. The following piece of code shows how to do this. + The :cpp:func:`esp_apptrace_read()` function uses memcpy to copy host data to user buffer. In some cases, it can be more optimal to use :cpp:func:`esp_apptrace_down_buffer_get()` and :cpp:func:`esp_apptrace_down_buffer_put()` functions. They allow developers to occupy chunk of read buffer and process it in-place. The following piece of code shows how to do this. .. code-block:: c @@ -197,7 +230,7 @@ In general, users should decide what type of data should be transferred in every 5. Connect to OpenOCD telnet server. It can be done using the following command in terminal ``telnet 4444``. If telnet session is opened on the same machine which runs OpenOCD, you can use ``localhost`` as ```` in the command above. -6. Start trace data collection using special OpenOCD command. This command will transfer tracing data and redirect them to the specified file or socket (currently only files are supported as trace data destination). For description of the corresponding commands, see `OpenOCD Application Level Tracing Commands`_. +6. Start trace data collection using special OpenOCD command. This command will transfer tracing data and redirect them to the specified file or socket. For description of the corresponding commands, see `OpenOCD Application Level Tracing Commands`_. 7. The final step is to process received data. Since the format of data is defined by users, the processing stage is out of the scope of this document. Good starting points for data processor are python scripts in ``$IDF_PATH/tools/esp_app_trace``: ``apptrace_proc.py`` (used for feature tests) and ``logtrace_proc.py`` (see more details in section `Logging to Host`_). @@ -255,7 +288,7 @@ Command usage examples: .. highlight:: none -1. Collect 2048 bytes of tracing data to the file ``trace.log``. The file will be saved in the ``openocd-esp32`` directory. +1. Collect 2048 bytes of tracing data to the file ``trace.log``. The file will be saved in the ``openocd-esp32`` directory. :: @@ -328,7 +361,7 @@ How To Use It In order to use logging via trace module, users need to perform the following steps: -1. Enable application tracing in menuconfig (``Component config`` > ``Application Level Tracing`` > ``Enable Application Level Tracing``). +1. Enable application tracing in menuconfig by going to ``Component config`` > ``ESP Trace Configuration`` > ``Trace transport`` and selecting ``ESP-IDF apptrace``. After that, configuration can be done at ``Component config`` > ``ESP Trace Configuration`` > ``Application Level Tracing``. 2. On the target side, the special vprintf-like function :cpp:func:`esp_apptrace_vprintf` needs to be installed. It sends log data to the host. An example is ``esp_log_set_vprintf(esp_apptrace_vprintf);``. To send log data to UART again, use ``esp_log_set_vprintf(vprintf);``. 3. Follow instructions in items 4-6 in `Application Specific Tracing`_ (OpenOCD setup and trace collection). 4. To print out collected log records, run the following command in terminal: ``$IDF_PATH/tools/esp_app_trace/logtrace_proc.py /path/to/trace/file /path/to/program/elf/file``. @@ -367,11 +400,11 @@ Another useful ESP-IDF feature built on top of application tracing library is th How To Use It """"""""""""" -Support for this feature is enabled by ``Component config`` > ``Application Level Tracing`` > ``FreeRTOS SystemView Tracing`` (:ref:`CONFIG_APPTRACE_SV_ENABLE`) menuconfig option. There are several other options enabled under the same menu: +Support for this feature is enabled by ``Component config`` > ``ESP Trace Configuration`` > ``Trace library`` > ``SEGGER SystemView`` menuconfig option. There are several other options enabled under the same menu: -1. {IDF_TARGET_NAME} timer to use as SystemView timestamp source: (:ref:`CONFIG_APPTRACE_SV_TS_SOURCE`) selects the source of timestamps for SystemView events. In the single core mode, timestamps are generated using {IDF_TARGET_NAME} internal cycle counter running at maximum frequency. (:ref:`CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ`) In the dual-core mode, external timer is used to generate timestamps. It's frequency is 1/2 of the CPU frequency. +1. {IDF_TARGET_NAME} timer to use as SystemView timestamp source: (:ref:`CONFIG_ESP_TRACE_TIMESTAMP_SOURCE`) selects the source of timestamps for SystemView events. In the single core mode, timestamps are generated using {IDF_TARGET_NAME} internal cycle counter running at maximum frequency. (:ref:`CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ`) In the dual-core mode, external timer is used to generate timestamps. It's frequency is 1/2 of the CPU frequency. -2. Individually enabled or disabled collection of SystemView events (``CONFIG_APPTRACE_SV_EVT_XXX``): +2. Individually enabled or disabled collection of SystemView events (``CONFIG_SEGGER_SYSVIEW_EVT_XXX``): - Trace Buffer Overflow Event - ISR Enter Event @@ -389,7 +422,7 @@ Support for this feature is enabled by ``Component config`` > ``Application Leve ESP-IDF has all the code required to produce SystemView compatible traces. -3. Select Pro or App CPU in menuconfig options ``Component config`` > ``Application Level Tracing`` > ``FreeRTOS SystemView Tracing`` to trace over the UART interface in real-time. +3. To trace over the UART interface in real-time, first select UART as the destination in ``Component config`` > ``ESP Trace Configuration`` > ``Application Level Tracing``. Then select Pro or App CPU in ``Component config`` > ``ESP Trace Configuration`` > ``SEGGER SystemView``. OpenOCD SystemView Tracing Command Options """""""""""""""""""""""""""""""""""""""""" @@ -447,6 +480,22 @@ Command usage examples: OpenOCD telnet command line prompt will not be available until tracing is stopped. To stop tracing, press Ctrl+C in the OpenOCD window. +Multi-Core SystemView Tracing Command +"""""""""""""""""""""""""""""""""""""" + +For SystemView version 3.60 and later, which supports multi-core tracing, use the ``esp sysview_mcore`` command. This command is identical to ``esp sysview`` but uses the official SEGGER SystemView multi-core format. Tracing data from all cores are saved in the same file, which can be opened in SEGGER SystemView v3.60 or later. + +Command usage example: + +.. highlight:: none + +:: + + esp sysview_mcore start file://heap_log_mcore.SVDat + +For detailed command syntax and options, refer to the ``esp sysview`` command above, as ``esp sysview_mcore`` accepts the same parameters. + + Data Visualization """""""""""""""""" @@ -454,9 +503,19 @@ After trace data are collected, users can use a special tool to visualize the re .. only:: SOC_HP_CPU_HAS_MULTIPLE_CORES - Unfortunately, SystemView does not support tracing from multiple cores. So when tracing from {IDF_TARGET_NAME} with JTAG interfaces in the dual-core mode, two files are generated: one for PRO CPU and another for APP CPU. Users can load each file into separate instances of the tool. For tracing over UART, users can select ``Component config`` > ``Application Level Tracing`` > ``FreeRTOS SystemView Tracing`` in menuconfig Pro or App to choose which CPU has to be traced. + **Multi-Core Tracing** -It is uneasy and awkward to analyze data for every core in separate instance of the tool. Fortunately, there is an Eclipse plugin called *Impulse* which can load several trace files, thus making it possible to inspect events from both cores in one view. Also, this plugin has no limitation of 1,000,000 events as compared to the free version of SystemView. + SystemView version 3.60 and later supports tracing from multiple cores. For multi-core tracing, use the ``esp sysview_mcore`` command to generate a single file compatible with SystemView multi-core format: + + :: + + esp sysview_mcore start file://heap_log_mcore.SVDat + + This command will create a single trace file that can be loaded directly into SystemView 3.60+ for multi-core visualization. + + **Note:** SystemView versions before 3.60 do not support multi-core tracing. For older versions, when tracing from {IDF_TARGET_NAME} with JTAG interfaces in the dual-core mode, two separate files are generated: one for PRO CPU and another for APP CPU. Users can load each file into separate instances of the tool. For tracing over UART, users can select ``Component config`` > ``ESP Trace Configuration`` > ``SEGGER SystemView`` in menuconfig to choose which CPU (Pro or App) has to be traced. + + For older SystemView versions, analyzing data for every core in separate instances can be awkward. An alternative is to use the Eclipse plugin called *Impulse*, which can load several trace files, making it possible to inspect events from both cores in one view. This plugin also has no limitation of 1,000,000 events as compared to the free version of SystemView. Good instructions on how to install, configure, and visualize data in Impulse from one core can be found `here `_. diff --git a/docs/en/api-reference/system/heap_debug.rst b/docs/en/api-reference/system/heap_debug.rst index 069a7245da1..287dda1979c 100644 --- a/docs/en/api-reference/system/heap_debug.rst +++ b/docs/en/api-reference/system/heap_debug.rst @@ -571,8 +571,8 @@ Host-Based Mode Once you have identified the code which you think is leaking: - In the project configuration menu, navigate to ``Component config`` > ``Heap Memory Debugging`` > :ref:`CONFIG_HEAP_TRACING_DEST` and select ``Host-Based``. -- In the project configuration menu, navigate to ``Component config`` > ``Application Level Tracing`` > ``Enable Application Level Tracing`` > ``Data Destination`` :ref:`CONFIG_APPTRACE_DESTINATION` and select ``JTAG``. -- In the project configuration menu, navigate to ``Component config`` > ``Application Level Tracing`` > ``FreeRTOS SystemView Tracing`` and enable :ref:`CONFIG_APPTRACE_SV_ENABLE`. +- In the project configuration menu, navigate to ``Component config`` > ``ESP Trace Configuration`` > ``Application Level Tracing`` > ``Data Destination`` :ref:`CONFIG_APPTRACE_DESTINATION` and select ``JTAG``. +- In the project configuration menu, navigate to ``Component config`` > ``ESP Trace Configuration`` > ``Trace library`` and select ``SEGGER SystemView``. - Call the function :cpp:func:`heap_trace_init_tohost` early in the program, to initialize the JTAG heap tracing module. - Call the function :cpp:func:`heap_trace_start` to begin recording all memory allocation and free calls in the system. Call this immediately before the piece of code which you suspect is leaking memory. diff --git a/docs/en/migration-guides/release-6.x/6.0/system.rst b/docs/en/migration-guides/release-6.x/6.0/system.rst index bbf3652aacd..97337b3d52c 100644 --- a/docs/en/migration-guides/release-6.x/6.0/system.rst +++ b/docs/en/migration-guides/release-6.x/6.0/system.rst @@ -73,61 +73,44 @@ App Trace Configuration Changes ^^^^^^^^^^^^^^^^^^^^^ -Previously, application tracing was automatically enabled when a destination was configured. Now you must explicitly enable application tracing through ``CONFIG_APPTRACE_ENABLE``` option before configuring any destination. +The application tracing configuration menu has been moved. Previously located at ``Component config`` > ``Application Level Tracing``, it is now under ``Component config`` > ``ESP Trace Configuration``. -To enable application tracing, go to "Component config" → "Application Level Tracing" → "Enable Application Level Tracing" in menuconfig. +Previously, application tracing was automatically enabled when a destination was configured. Now you must explicitly enable application tracing by selecting the trace transport before configuring any destination. + +To enable application tracing, go to ``Component config`` > ``ESP Trace Configuration`` > ``Trace transport`` and select ``ESP-IDF apptrace`` in menuconfig. After that, configuration can be done at ``Component config`` > ``ESP Trace Configuration`` > ``Application Level Tracing``. + +If apptrace will be used without a library (for example when SEGGER SystemView is disabled) in standalone mode, the following configurations need to be set in your sdkconfig file: + +.. code-block:: none + + CONFIG_ESP_TRACE_ENABLE=y + CONFIG_ESP_TRACE_LIB_NONE=y + CONFIG_ESP_TRACE_TRANSPORT_APPTRACE=y + +These can also be configured through menuconfig as described above. Removed extra data buffering option. ``CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX`` is no longer supported. Removed deprecated ``ESP_APPTRACE_DEST_TRAX`` enum value. Use ``ESP_APPTRACE_DEST_JTAG`` instead. +Component Dependency Changes +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Applications now require the ``esp_trace`` component instead of ``app_trace``. Update your component's ``CMakeLists.txt`` file to reflect this change. + +The ``app_trace`` component is now a sub-component of ``esp_trace`` and will be included automatically when needed. + Initialization Flow Changes ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -If you need to override the default configuration at runtime, you can implement the ``esp_apptrace_get_user_params()`` callback function. A weak default implementation exists that returns menuconfig defaults (``APPTRACE_CONFIG_DEFAULT()``). Your application can override this by providing its own configuration. - - .. code-block:: c - - esp_apptrace_config_t esp_apptrace_get_user_params(void) - { - esp_apptrace_config_t config = APPTRACE_CONFIG_DEFAULT(); - - // Override with custom values (example for UART) - config.dest_cfg.uart.uart_num = UART_NUM_0; - config.dest_cfg.uart.baud_rate = 921600; - config.dest_cfg.uart.tx_pin_num = GPIO_NUM_17; - config.dest_cfg.uart.rx_pin_num = GPIO_NUM_16; - - return config; - } - - **Important:** - - - Do **not** add ``__attribute__((weak))`` to your implementation - - You can also use destination-specific macros: ``APPTRACE_JTAG_CONFIG_DEFAULT()`` or ``APPTRACE_UART_CONFIG_DEFAULT()`` +For runtime configuration override, a new callback system is available. See the :doc:`Application Tracing documentation <../../../api-guides/app_trace>` for details on ``esp_apptrace_get_user_params()`` and ``esp_trace_get_user_params()``. API Changes ^^^^^^^^^^^ The destination parameter has been removed from all apptrace APIs. -Old Version: - -.. code-block:: c - - esp_apptrace_write(ESP_APPTRACE_DEST_JTAG, data, size, timeout); - esp_apptrace_read(ESP_APPTRACE_DEST_UART, buffer, &size, timeout); - esp_apptrace_flush(ESP_APPTRACE_DEST_JTAG, min_sz, timeout); - -Update to: - -.. code-block:: c - - esp_apptrace_write(data, size, timeout); - esp_apptrace_read(buffer, &size, timeout); - esp_apptrace_flush(min_sz, timeout); - -The destination is now configured in menuconfig under "Application Level Tracing" → "Data Destination". +Default destination is now configured in menuconfig under ``Component config`` > ``ESP Trace Configuration`` > ``Application Level Tracing`` and can be altered at runtime by providing callback with custom tracing configuration. The UART destination configuration has been simplified: @@ -151,12 +134,12 @@ New configuration: CONFIG_APPTRACE_DEST_UART=y CONFIG_APPTRACE_DEST_UART_NUM=0 # or 1, 2 depending on target -SystemView Destination -^^^^^^^^^^^^^^^^^^^^^^ +SystemView Configuration +^^^^^^^^^^^^^^^^^^^^^^^^ -The SystemView destination is now controlled by the same configuration as the application trace destination. When SystemView is enabled, it will use the destination configured under "Application Level Tracing" → "Data Destination". +The SystemView configuration has been moved to a new location in the menuconfig: ``Component config`` > ``ESP Trace Configuration`` > ``Trace library`` > ``SEGGER SystemView``. -This means that if you have both application tracing and SystemView enabled, they will share the same destination (JTAG or UART) as configured in the menuconfig. SystemView will not have its own destination configuration. +The SystemView no longer has its own separate destination configuration. It shares the configuration with the application tracing transport (JTAG or UART). FreeRTOS -------- @@ -249,7 +232,7 @@ OTA Updates The partial download functionality in ESP HTTPS OTA has been moved under a configuration option in order to reduce the memory footprint if partial download is not used. -To use partial download features in your OTA applications, you need to enable the component-level configuration :ref:`CONFIG_ESP_HTTPS_OTA_ENABLE_PARTIAL_DOWNLOAD` in menuconfig (``Component config`` → ``ESP HTTPS OTA`` → ``Enable partial HTTP download for OTA``). +To use partial download features in your OTA applications, you need to enable the component-level configuration :ref:`CONFIG_ESP_HTTPS_OTA_ENABLE_PARTIAL_DOWNLOAD` in menuconfig (``Component config`` > ``ESP HTTPS OTA`` > ``Enable partial HTTP download for OTA``). Removed Deprecated APIs ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/docs/zh_CN/api-guides/app_trace.rst b/docs/zh_CN/api-guides/app_trace.rst index 48b763d0d7c..8ea25142c02 100644 --- a/docs/zh_CN/api-guides/app_trace.rst +++ b/docs/zh_CN/api-guides/app_trace.rst @@ -41,7 +41,7 @@ ESP-IDF 中提供了应用层跟踪功能,用于分析应用程序的行为。 1. **主机端:** 应用程序跟踪通过 JTAG 来完成,因此需要在主机上安装并运行 OpenOCD。详细信息请参阅 :doc:`JTAG 调试 <../api-guides/jtag-debugging/index>`。 -2. **目标端:** 在 menuconfig 中开启应用程序跟踪功能。**重要提示:** 您必须首先通过 ``Component config`` > ``Application Level Tracing`` > ``Enable Application Level Tracing`` (:ref:`CONFIG_APPTRACE_ENABLE`) 启用应用程序跟踪。启用此选项后,您可以配置跟踪数据的传输目标。对于 UART 接口,用户需要定义端口号、波特率、TX 和 RX 管脚及其他相关参数。当启用 FreeRTOS SystemView 跟踪功能时,所选目标也将被用于 SystemView 跟踪。 +2. **目标端:** 在 menuconfig 中开启应用程序跟踪功能。**重要提示:** 须首先通过 ``Component config`` > ``ESP Trace Configuration`` > ``Trace transport`` 并选择 ``ESP-IDF apptrace`` 启用应用程序跟踪。之后,可以在 ``Component config`` > ``ESP Trace Configuration`` > ``Application Level Tracing`` 中进行详细配置,例如配置跟踪数据的传输目标。对于 UART 接口,需定义端口号、波特率、TX 和 RX 管脚及其他相关参数。当选择任何跟踪库(例如 SEGGER SystemView)时,这些配置也将同步用于该库。 .. note:: @@ -53,7 +53,7 @@ ESP-IDF 中提供了应用层跟踪功能,用于分析应用程序的行为。 2. *Timeout for flushing last trace data to host on panic* (:ref:`CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO`)。该选项仅在流模式下才可发挥作用,它可用于控制跟踪模块在发生 Panic 时等待主机读取最新数据的最长时间。 -3. *Internal Sync Lock* (:ref:`CONFIG_APPTRACE_LOCK_ENABLE`)。启用此选项可使用锁保护跟踪缓冲区写入操作,防止多个任务并发生成跟踪数据时发生数据损坏。 +3. *Internal Sync Lock* (:ref:`CONFIG_APPTRACE_LOCK_ENABLE`)。启用此选项可使用锁保护跟踪缓冲区的写入操作,防止多个任务并发生成跟踪数据时发生数据损坏。 4. *UART RX/TX ring buffer size* (:ref:`CONFIG_APPTRACE_UART_TX_BUFF_SIZE`)。缓冲区的大小取决于通过 UART 传输的数据量。 @@ -63,9 +63,42 @@ ESP-IDF 中提供了应用层跟踪功能,用于分析应用程序的行为。 如何使用此库 -------------- -该库提供了用于在主机和 {IDF_TARGET_NAME} 之间传输任意数据的 API。在 menuconfig 中启用该库后,应用程序跟踪模块会在系统启动期间使用 menuconfig 配置自动初始化。然后用户可以调用相应的 API 来发送、接收或者刷新数据。 +该库提供了用于在主机和 {IDF_TARGET_NAME} 之间传输任意数据的 API。在 menuconfig 中启用该库后,应用程序跟踪模块会在系统启动期间使用 menuconfig 配置自动初始化。随后用户可以调用相应的 API 来发送、接收或者刷新数据。 -用户可以通过实现弱回调函数 :cpp:func:`esp_apptrace_get_user_params()` 来覆盖默认配置(可选)。 +用户可选择通过实现弱回调函数 :cpp:func:`esp_apptrace_get_user_params()` 来覆盖默认配置。该函数仅在未选择任何跟踪库时生效,此时,仅应用层跟踪库(``app_trace`` 组件)独立运行。否则,系统将调用 :cpp:func:`esp_trace_get_user_params()` 来覆盖默认配置。 + +快速入门 +--------- + +1. 独立使用应用层跟踪 API + + 在 menuconfig 中禁用跟踪库并启用应用层跟踪传输: + + - ``Component config`` > ``ESP Trace Configuration`` > ``Trace library``:选择 ``None`` + - ``Component config`` > ``ESP Trace Configuration`` > ``Trace transport``:选择 ``ESP-IDF apptrace`` + + 也可在 ``sdkconfig.defaults`` 中设置以下选项以强制启用独立模式: + + .. code-block:: none + + CONFIG_ESP_TRACE_ENABLE=y + CONFIG_ESP_TRACE_LIB_NONE=y + CONFIG_ESP_TRACE_TRANSPORT_APPTRACE=y + + 通过上述任一方式启用独立应用层跟踪传输后,即可在 ``Component config`` > ``ESP Trace Configuration`` > ``Application Level Tracing`` 中配置目标传输。 + +2. 通过 ``esp_apptrace_get_user_params()`` 进行运行时配置 + + - 如果在 Kconfig 中选择 ``All (runtime selection)`` (即 ``APPTRACE_DEST_ALL``),可通过回调函数在运行时切换 JTAG 和 UART 并调整其参数。 + - 如果在 Kconfig 中选定单一目标(JTAG 或 UART),回调函数可在运行时覆盖该目标的参数,但无法切换目标类型。 + +.. note:: + + 应用程序跟踪也可作为 esp_trace 库的传输适配器。在这种情况下,应用层跟踪库不会被直接使用,而是通过已选择的 esp_trace 库及其 API 间接使用。 + +.. note:: + + 以下代码示例适用于应用层跟踪库独立运行(未绑定任何跟踪库)的场景。 .. _app_trace-application-specific-tracing: @@ -85,8 +118,8 @@ ESP-IDF 中提供了应用层跟踪功能,用于分析应用程序的行为。 { esp_apptrace_config_t config = APPTRACE_CONFIG_DEFAULT(); - // Customize configuration if needed - // For example, to use different UART pins: + // 根据需要自定义配置 + // 例如,使用不同的 UART 引脚: config.dest_cfg.uart.tx_pin_num = GPIO_NUM_17; config.dest_cfg.uart.rx_pin_num = GPIO_NUM_16; @@ -110,7 +143,7 @@ ESP-IDF 中提供了应用层跟踪功能,用于分析应用程序的行为。 return res; } - ``esp_apptrace_write()`` 函数使用 memcpy 把用户数据复制到内部缓存中。在某些情况下,使用 ``esp_apptrace_buffer_get()`` 和 ``esp_apptrace_buffer_put()`` 函数会更加理想,它们允许开发人员自行分配缓冲区并填充。下面的代码片段展示了如何执行此操作。 + 函数 :cpp:func:`esp_apptrace_write()` 通过 memcpy 将用户数据复制到内部缓冲区。在某些情况下,使用 :cpp:func:`esp_apptrace_buffer_get()` 和 :cpp:func:`esp_apptrace_buffer_put()` 函数可能是更优的选择。这两个函数允许开发者自行分配缓冲区并填充数据。以下代码片段展示了具体实现方法。 .. code-block:: c @@ -157,7 +190,7 @@ ESP-IDF 中提供了应用层跟踪功能,用于分析应用程序的行为。 ... } - ``esp_apptrace_read()`` 函数使用 memcpy 把主机端的数据复制到用户缓存区。在某些情况下,使用 ``esp_apptrace_down_buffer_get()`` 和 ``esp_apptrace_down_buffer_put()`` 函数可能更为理想。它们允许开发人员占用一块读缓冲区并就地进行有关处理操作。下面的代码片段展示了如何执行此操作。 + 函数 :cpp:func:`esp_apptrace_read()` 通过 memcpy 将主机数据复制到用户缓冲区。在某些情况下,使用 :cpp:func:`esp_apptrace_down_buffer_get()` 和 :cpp:func:`esp_apptrace_down_buffer_put()` 函数可能是更优的选择。这两个函数允许开发者直接占用读取缓冲区的数据块并进行原地处理。以下代码片段展示了具体实现方法。 .. code-block:: c @@ -197,7 +230,7 @@ ESP-IDF 中提供了应用层跟踪功能,用于分析应用程序的行为。 5. 连接到 OpenOCD 的 telnet 服务器。用户可在终端执行命令 ``telnet 4444``。如果用户是在运行 OpenOCD 的同一台机器上打开 telnet 会话,可以使用 ``localhost`` 替换上面命令中的 ````。 -6. 使用特殊的 OpenOCD 命令开始收集待跟踪的命令。此命令将传输跟踪数据并将其重定向到指定的文件或套接字(当前仅支持文件作为跟踪数据目标)。相关命令的说明,请参阅 :ref:`jtag-debugging-launching-debugger`。 +6. 使用特殊的 OpenOCD 命令开始收集待跟踪的命令。此命令将传输跟踪数据并将其重定向到指定的文件或套接字。相关命令的说明,请参阅 `OpenOCD 应用程序跟踪命令`_。 7. 最后,处理接收到的数据。由于数据格式由用户自己定义,本文档中省略数据处理的具体流程。数据处理的范例可以参考位于 ``$IDF_PATH/tools/esp_app_trace`` 下的 Python 脚本 ``apptrace_proc.py`` (用于功能测试)和 ``logtrace_proc.py`` (请参阅 :ref:`app_trace-logging-to-host` 章节中的详细信息)。 @@ -232,7 +265,7 @@ OpenOCD 应用程序跟踪命令 Start 子命令的语法: - ``start [poll_period [trace_size [stop_tmo [wait4halt [skip_size]]]]`` + ``start [poll_period [trace_size [stop_tmo [wait4halt [skip_size]]]]`` ``outfile`` 用于保存来自两个 CPU 的数据文件的路径,该参数需要具有以下格式: ``file://path/to/file``。 @@ -261,11 +294,11 @@ Start 子命令的语法: esp apptrace start file://trace.log 1 2048 5 0 0 - 跟踪数据会被检索并以非阻塞的模式保存到文件中,如果收集满 2048 字节的数据或者在 5 秒内都没有新的数据,那么该过程就会停止。 + 跟踪数据会被检索并以非阻塞的模式保存到文件中,如果收集满 2048 字节的数据或者在 5 秒内都没有新的数据,那么该过程就会停止。 - .. note:: + .. note:: - 在将数据提供给 OpenOCD 之前,会对其进行缓冲。如果看到 “Data timeout!” 的消息,则表示目标可能在超时之前没有向 OpenOCD 发送足够的数据以清空缓冲区。要解决这个问题,可以增加超时时间或者使用函数 ``esp_apptrace_flush()`` 以特定间隔刷新数据。 + 在将数据提供给 OpenOCD 之前,会对其进行缓冲。如果看到 “Data timeout!” 的消息,则表示目标可能在超时之前没有向 OpenOCD 发送足够的数据以清空缓冲区。要解决这个问题,可以增加超时时间或者使用函数 ``esp_apptrace_flush()`` 以特定间隔刷新数据。 2. 在非阻塞模式下无限地检索跟踪数据。 @@ -273,7 +306,7 @@ Start 子命令的语法: esp apptrace start file://trace.log 1 -1 -1 0 0 - 对收集数据的大小没有限制,也不设置超时时间。要停止此过程,可以在 OpenOCD 的 telnet 会话窗口中发送 ``esp apptrace stop`` 命令,或者在 OpenOCD 窗口中使用快捷键 Ctrl+C。 + 对收集数据的大小没有限制,也不设置超时时间。要停止此过程,可以在 OpenOCD 的 telnet 会话窗口中发送 ``esp apptrace stop`` 命令,或者在 OpenOCD 窗口中使用快捷键 Ctrl+C。 3. 检索跟踪数据并无限期保存。 @@ -281,7 +314,7 @@ Start 子命令的语法: esp apptrace start file://trace.log 0 -1 -1 0 0 - 在跟踪停止之前,OpenOCD 的 telnet 会话窗口将不可用。要停止跟踪,请在 OpenOCD 的窗口中使用快捷键 Ctrl+C。 + 在跟踪停止之前,OpenOCD 的 telnet 会话窗口将不可用。要停止跟踪,请在 OpenOCD 的窗口中使用快捷键 Ctrl+C。 4. 等待目标停止,然后恢复目标的操作并开始检索数据。当收集满 2048 字节的数据后就停止: @@ -289,7 +322,7 @@ Start 子命令的语法: esp apptrace start file://trace.log 0 2048 -1 1 0 - 想要复位后立即开始跟踪,请使用 OpenOCD 的 ``reset halt`` 命令。 + 想要复位后立即开始跟踪,请使用 OpenOCD 的 ``reset halt`` 命令。 .. _app_trace-logging-to-host: @@ -328,9 +361,9 @@ ESP-IDF 的日志库会默认使用类 vprintf 的函数将格式化的字符串 为了使用跟踪模块来记录日志,用户需要执行以下步骤: -1. 在 menuconfig 中启用应用程序跟踪功能(路径为 ``Component config`` > ``Application Level Tracing`` > ``Enable Application Level Tracing``)。 +1. 在 menuconfig 中开启应用程序跟踪功能。须首先通过 ``Component config`` > ``ESP Trace Configuration`` > ``Trace transport`` 并选择 ``ESP-IDF apptrace`` 启用应用程序跟踪。之后,可以在 ``Component config`` > ``ESP Trace Configuration`` > ``Application Level Tracing`` 中进行详细配置。 2. 在目标端,需要安装特殊的类 vprintf 函数 :cpp:func:`esp_apptrace_vprintf`,该函数负责将日志数据发送给主机,使用方法为 ``esp_log_set_vprintf(esp_apptrace_vprintf);``。如需将日志数据再次重定向给 UART,请使用 ``esp_log_set_vprintf(vprintf);``。 -3. 按照 :ref:`app_trace-application-specific-tracing` 章节中的第 1-5 步进行操作。 +3. 按照 :ref:`app_trace-application-specific-tracing` 章节中的第 4-6 步进行操作(OpenOCD 设置和跟踪数据收集)。 4. 打印接收到的日志记录,请在终端运行以下命令:``$IDF_PATH/tools/esp_app_trace/logtrace_proc.py /path/to/trace/file /path/to/program/elf/file``。 @@ -367,11 +400,11 @@ ESP-IDF 中另一个基于应用层跟踪库的实用功能是系统级跟踪, 如何使用 """""""" -若需使用这个功能,需要在 menuconfig 中开启 :ref:`CONFIG_APPTRACE_SV_ENABLE` 选项,具体路径为 ``Component config`` > ``Application Level Tracing`` > ``FreeRTOS SystemView Tracing``。同一菜单栏下还开启了其它几个选项: +若需使用这个功能,需要在 menuconfig 中通过 ``Component config`` > ``ESP Trace Configuration`` > ``Trace library`` > ``SEGGER SystemView`` 选项启用此功能。同一菜单栏下还有其它几个选项: -1. {IDF_TARGET_NAME} 用作 SystemView 时间戳源的定时器选择:(:ref:`CONFIG_APPTRACE_SV_TS_SOURCE`)用于选择 SystemView 事件的时间戳源。在单核模式下,时间戳由以最大频率运行的 {IDF_TARGET_NAME} 内部周期计数器生成。(:ref:`CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ`)在双核模式下,使用外部定时器生成时间戳,其频率为 CPU 频率的 1/2。 +1. {IDF_TARGET_NAME} 用作 SystemView 时间戳源的定时器选择:(:ref:`CONFIG_ESP_TRACE_TIMESTAMP_SOURCE`)用于选择 SystemView 事件的时间戳源。在单核模式下,时间戳由以最大频率运行的 {IDF_TARGET_NAME} 内部周期计数器生成。(:ref:`CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ`)在双核模式下,使用外部定时器生成时间戳,其频率为 CPU 频率的 1/2。 -2. 可以单独启用或禁用的 SystemView 事件集合 (``CONFIG_APPTRACE_SV_EVT_XXX``): +2. 可以单独启用或禁用的 SystemView 事件集合 (``CONFIG_SEGGER_SYSVIEW_EVT_XXX``): - Trace Buffer Overflow Event - ISR Enter Event @@ -389,7 +422,7 @@ ESP-IDF 中另一个基于应用层跟踪库的实用功能是系统级跟踪, ESP-IDF 中已经包含了所有用于生成兼容 SystemView 跟踪信息的代码。 -3. 想要通过 UART 接口进行实时跟踪,请在菜单配置选项 ``Component config`` > ``Application Level Tracing`` > ``FreeRTOS SystemView Tracing`` 中选择 Pro 或 App CPU。 +3. 想要通过 UART 接口进行实时跟踪,请首先在 ``Component config`` > ``ESP Trace Configuration`` > ``Application Level Tracing`` 中选择 UART 作为目标传输方式。然后在 ``Component config`` > ``ESP Trace Configuration`` > ``SEGGER SystemView`` 中选择 Pro 或 App CPU。 OpenOCD SystemView 跟踪命令选项 """"""""""""""""""""""""""""""" @@ -447,6 +480,22 @@ Start 子命令语法: OpenOCD 的 telnet 命令行在跟踪停止前会无法使用,要停止跟踪,请在 OpenOCD 窗口使用 Ctrl+C 快捷键。 +多核 SystemView 跟踪命令 +"""""""""""""""""""""""""" + +对于支持多核跟踪的 SystemView 3.60 及更高版本,请使用 ``esp sysview_mcore`` 命令。此命令与 ``esp sysview`` 相同,但使用官方 SEGGER SystemView 多核格式。所有核心的跟踪数据都保存在同一文件中,可在 SEGGER SystemView v3.60 或更高版本中打开。 + +命令使用示例: + +.. highlight:: none + +:: + + esp sysview_mcore start file://heap_log_mcore.SVDat + +有关详细的命令语法和选项,请参考前文所述的 ``esp sysview`` 命令,因为 ``esp sysview_mcore`` 支持相同的参数。 + + 数据可视化 """""""""" @@ -454,9 +503,19 @@ Start 子命令语法: .. only:: SOC_HP_CPU_HAS_MULTIPLE_CORES - 遗憾的是,SystemView 不支持从多个核心进行跟踪。所以当使用 JTAG 跟踪双核模式下的 {IDF_TARGET_NAME} 时会生成两个文件:一个用于 PRO CPU,另一个用于 APP CPU。用户可以将每个文件加载到工具中单独分析。使用 UART 进行跟踪时,用户可以在 menuconfig Pro 或 App 中点击 ``Component config`` > ``Application Level Tracing`` > ``FreeRTOS SystemView Tracing`` 并选择要跟踪的 CPU。 + **多核跟踪** -在工具中单独分析每个核的跟踪数据是比较棘手的,但是 Eclipse 提供了 *Impulse* 插件,该插件可以加载多个跟踪文件,并且可以在同一视图中检查来自两个内核的事件。此外,与免费版的 SystemView 相比,此插件没有 1,000,000 个事件的限制。 + SystemView 3.60 及更高版本支持多核心进行跟踪。对于多核跟踪,使用 ``esp sysview_mcore`` 命令可以生成与 SystemView 多核格式兼容的单个文件: + + :: + + esp sysview_mcore start file://heap_log_mcore.SVDat + + 此命令将创建一个单独的跟踪文件,可以直接加载到 SystemView 3.60+ 中进行多核可视化。 + + **注意:** SystemView 3.60 之前的版本不支持多核跟踪。对于旧版本,当使用 JTAG 接口跟踪双核模式下的 {IDF_TARGET_NAME} 时会生成两个文件:一个用于 PRO CPU,另一个用于 APP CPU。用户可将每个文件载入不同的工具实例。使用 UART 进行跟踪时,用户可以在 menuconfig 中选择 ``Component config`` > ``ESP Trace Configuration`` > ``SEGGER SystemView`` 来指定需要跟踪的 CPU(Pro 或 App)。 + + 对于旧版本的 SystemView,在不同的实例中分别分析每个核的数据可能较为不便。另一个选择是使用名为 *Impulse* 的 Eclipse 插件,该插件可同时加载多个跟踪文件,实现在同一视图中检查来自两个核心的事件。与 SystemView 免费版相比,此插件还不受 100 万事件数量的限制。 关于如何安装、配置 Impulse 并使用它来可视化来自单个核心的跟踪数据,请参阅 `官方教程 `_ 。 @@ -485,7 +544,6 @@ Start 子命令语法: 如果你在可视化方面遇到了问题(未显示数据或者缩放操作异常),可以尝试删除当前的信号层次结构,再双击必要的文件或端口。Eclipse 会请求创建新的信号层次结构。 - .. _app_trace-gcov-source-code-coverage: Gcov(源代码覆盖率) diff --git a/docs/zh_CN/api-reference/system/heap_debug.rst b/docs/zh_CN/api-reference/system/heap_debug.rst index c932b8049f2..370cc13751a 100644 --- a/docs/zh_CN/api-reference/system/heap_debug.rst +++ b/docs/zh_CN/api-reference/system/heap_debug.rst @@ -571,8 +571,8 @@ ESP-IDF 集成了用于请求 :ref:`堆内存信息 `、:ref:` 确定存在泄漏的代码后,请执行以下步骤: - 在项目配置菜单中,前往 ``Component config`` > ``Heap Memory Debugging`` > :ref:`CONFIG_HEAP_TRACING_DEST` 并选择 ``Host-Based``。 -- 在项目配置菜单中,前往 ``Component config`` > ``Application Level Tracing`` > ``Enable Application Level Tracing`` > ``Data Destination`` :ref:`CONFIG_APPTRACE_DESTINATION` 并选择 ``JTAG``。 -- 在项目配置菜单中,前往 ``Component config`` > ``Application Level Tracing`` > ``FreeRTOS SystemView Tracing`` 并启用 :ref:`CONFIG_APPTRACE_SV_ENABLE`。 +- 在项目配置菜单中,前往 ``Component config`` > ``ESP Trace Configuration`` > ``Application Level Tracing`` > ``Data Destination`` :ref:`CONFIG_APPTRACE_DESTINATION` 并选择 ``JTAG``。 +- 在项目配置菜单中,前往 ``Component config`` > ``ESP Trace Configuration`` > ``Trace library`` 并选择 ``SEGGER SystemView``。 - 在程序早期,调用函数 :cpp:func:`heap_trace_init_tohost`,初始化 JTAG 堆内存跟踪模块。 - 在有内存泄漏之嫌的代码块前,调用函数 :cpp:func:`heap_trace_start` 开始记录系统中的内存分配和释放操作。 diff --git a/docs/zh_CN/migration-guides/release-6.x/6.0/system.rst b/docs/zh_CN/migration-guides/release-6.x/6.0/system.rst index 8678610fa16..b9cdd4b055e 100644 --- a/docs/zh_CN/migration-guides/release-6.x/6.0/system.rst +++ b/docs/zh_CN/migration-guides/release-6.x/6.0/system.rst @@ -73,61 +73,44 @@ App 追踪 配置更改 ^^^^^^^^^^ -此前,当配置传输目标时,应用程序跟踪会自动启用。现在必须在配置任何目标前,通过 ``CONFIG_APPTRACE_ENABLE`` 选项显式启用应用程序跟踪功能。 +应用程序跟踪配置菜单已移动。之前位于 ``Component config`` > ``Application Level Tracing``,现在位于 ``Component config`` > ``ESP Trace Configuration``。 -如需启用应用程序跟踪,请在 menuconfig 中依次进入 "Component config" → "Application Level Tracing" → "Enable Application Level Tracing" 进行设置。 +此前,应用程序跟踪功能会在配置目标传输方式时自动启用。现在必须在配置任何目标传输方式前,通过选择跟踪传输方式显式启用应用程序跟踪功能。 + +如需启用应用程序跟踪,请在 menuconfig 中依次进入 ``Component config`` > ``ESP Trace Configuration`` > ``Trace transport`` 并选择 ``ESP-IDF apptrace``。之后,可以在 ``Component config`` > ``ESP Trace Configuration`` > ``Application Level Tracing`` 中进行配置。 + +如果要在独立模式下使用 apptrace 而不使用库(例如禁用 SEGGER SystemView 时),需要在 sdkconfig 文件中设置以下配置: + +.. code-block:: none + + CONFIG_ESP_TRACE_ENABLE=y + CONFIG_ESP_TRACE_LIB_NONE=y + CONFIG_ESP_TRACE_TRANSPORT_APPTRACE=y + +这些配置也可以按上述说明通过 menuconfig 进行设置。 已移除额外数据缓冲选项。不再支持 ``CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX`` 配置项。 已移除弃用的 ``ESP_APPTRACE_DEST_TRAX`` 枚举值。请改用 ``ESP_APPTRACE_DEST_JTAG``。 +组件依赖更改 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +应用程序现在需要 ``esp_trace`` 组件,而不是 ``app_trace``。请更新组件的 ``CMakeLists.txt`` 文件以反映此更改。 + +``app_trace`` 组件现在是 ``esp_trace`` 的子组件,将在需要时自动包含。 + 初始化流程更改 ^^^^^^^^^^^^^^^^^^^ -如需在运行时覆盖默认配置,可以实现 ``esp_apptrace_get_user_params()`` 回调函数。系统提供了一个弱默认实现,返回 menuconfig 的默认配置(``APPTRACE_CONFIG_DEFAULT()``)。您的应用程序可以通过提供自己的配置来覆盖此默认实现。 - - .. code-block:: c - - esp_apptrace_config_t esp_apptrace_get_user_params(void) - { - esp_apptrace_config_t config = APPTRACE_CONFIG_DEFAULT(); - - // 使用自定义值覆盖(UART 示例) - config.dest_cfg.uart.uart_num = UART_NUM_0; - config.dest_cfg.uart.baud_rate = 921600; - config.dest_cfg.uart.tx_pin_num = GPIO_NUM_17; - config.dest_cfg.uart.rx_pin_num = GPIO_NUM_16; - - return config; - } - - **重要提示:** - - - 请 **勿** 在您的实现中添加 ``__attribute__((weak))`` - - 您也可以使用特定目标的宏:``APPTRACE_JTAG_CONFIG_DEFAULT()`` 或 ``APPTRACE_UART_CONFIG_DEFAULT()`` +对于运行时配置覆盖,提供了新的回调系统。详细信息请参见 :doc:`应用程序跟踪文档 <../../../api-guides/app_trace>` 中关于 ``esp_apptrace_get_user_params()`` 和 ``esp_trace_get_user_params()`` 的说明。 API 更改 ^^^^^^^^^^^ 所有 apptrace API 中的目标参数已被移除。 -旧版本: - -.. code-block:: c - - esp_apptrace_write(ESP_APPTRACE_DEST_JTAG, data, size, timeout); - esp_apptrace_read(ESP_APPTRACE_DEST_UART, buffer, &size, timeout); - esp_apptrace_flush(ESP_APPTRACE_DEST_JTAG, min_sz, timeout); - -更新为: - -.. code-block:: c - - esp_apptrace_write(data, size, timeout); - esp_apptrace_read(buffer, &size, timeout); - esp_apptrace_flush(min_sz, timeout); - -目标现在在 menuconfig 中的 "Application Level Tracing" → "Data Destination" 下全局配置。 +默认目标现在在 menuconfig 中的 ``Component config`` > ``ESP Trace Configuration`` > ``Application Level Tracing`` 下配置,并且可以在运行时通过提供带有自定义跟踪配置的回调来更改。 UART 目标配置已简化: @@ -151,12 +134,12 @@ UART 目标配置已简化: CONFIG_APPTRACE_DEST_UART=y CONFIG_APPTRACE_DEST_UART_NUM=0 # 或 1、2,具体取决于目标芯片 -SystemView 的传输目标 -^^^^^^^^^^^^^^^^^^^^^^^ +SystemView 配置 +^^^^^^^^^^^^^^^^^^^^^^^^ -SystemView 的传输目标现在由与应用程序跟踪目标相同的配置控制。启用 SystemView 后,它将使用在 "Application Level Tracing" → "Data Destination" 下配置的目标传输方式。 +SystemView 配置已移至 menuconfig 中的新位置:``Component config`` > ``ESP Trace Configuration`` > ``Trace library`` > ``SEGGER SystemView``。 -这意味着如果同时启用了应用程序跟踪和 SystemView,它们将共享在 menuconfig 中配置的相同目标传输方式(JTAG 或 UART)。SystemView 将不再拥有独立的传输目标配置。 +SystemView 不再拥有独立的传输目标配置。它与应用程序跟踪传输方式(JTAG 或 UART)共享配置。 FreeRTOS -------- @@ -249,7 +232,7 @@ OTA 更新 ESP HTTPS OTA 的分段下载功能已移至配置选项下,以便在未使用分段下载时减少内存占用。 -如果要在 OTA 应用中使用分段下载功能,需要在 menuconfig 中启用组件级配置 :ref:`CONFIG_ESP_HTTPS_OTA_ENABLE_PARTIAL_DOWNLOAD` (``Component config`` → ``ESP HTTPS OTA`` → ``Enable partial HTTP download for OTA``)。 +如果要在 OTA 应用中使用分段下载功能,需要在 menuconfig 中启用组件级配置 :ref:`CONFIG_ESP_HTTPS_OTA_ENABLE_PARTIAL_DOWNLOAD` (``Component config`` > ``ESP HTTPS OTA`` > ``Enable partial HTTP download for OTA``)。 已移除的废弃 API ^^^^^^^^^^^^^^^^^^^^ diff --git a/examples/system/app_trace_basic/main/CMakeLists.txt b/examples/system/app_trace_basic/main/CMakeLists.txt index 0558d62cba0..0664fdf7a4f 100644 --- a/examples/system/app_trace_basic/main/CMakeLists.txt +++ b/examples/system/app_trace_basic/main/CMakeLists.txt @@ -1,3 +1,3 @@ idf_component_register(SRCS "app_trace_basic_example_main.c" - PRIV_REQUIRES app_trace + PRIV_REQUIRES esp_trace INCLUDE_DIRS ".") diff --git a/examples/system/app_trace_basic/main/app_trace_basic_example_main.c b/examples/system/app_trace_basic/main/app_trace_basic_example_main.c index de89536b582..cdd5812c080 100644 --- a/examples/system/app_trace_basic/main/app_trace_basic_example_main.c +++ b/examples/system/app_trace_basic/main/app_trace_basic_example_main.c @@ -16,14 +16,14 @@ #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "esp_app_trace.h" #include "soc/uart_pins.h" #include "esp_log.h" +#include "esp_app_trace.h" static const char *TAG = "example"; #if !CONFIG_APPTRACE_DEST_JTAG -/* Override default config to use console pins as a uart channel */ +/* Override default uart config to use console pins as a uart channel */ esp_apptrace_config_t esp_apptrace_get_user_params(void) { esp_apptrace_config_t config = APPTRACE_UART_CONFIG_DEFAULT(); @@ -56,7 +56,7 @@ void app_main(void) if (res != ESP_OK) { ESP_LOGE(TAG, "Failed to write data to host [0x%x] (%s)", res, esp_err_to_name(res)); } - esp_apptrace_flush(1000); + esp_apptrace_flush( 1000); vTaskDelay(50 / portTICK_PERIOD_MS); } diff --git a/examples/system/app_trace_basic/sdkconfig.ci.apptrace_uart b/examples/system/app_trace_basic/sdkconfig.ci.apptrace_uart index e2a7c255a3b..d96128e892a 100644 --- a/examples/system/app_trace_basic/sdkconfig.ci.apptrace_uart +++ b/examples/system/app_trace_basic/sdkconfig.ci.apptrace_uart @@ -1,3 +1,3 @@ CONFIG_ESP_CONSOLE_NONE=y -# Destination selection on runtime -CONFIG_APPTRACE_DEST_NONE=y +# Destination can be selectable on runtime +CONFIG_APPTRACE_DEST_ALL=y diff --git a/examples/system/app_trace_basic/sdkconfig.defaults b/examples/system/app_trace_basic/sdkconfig.defaults index 376f789f619..0bf0d89da21 100644 --- a/examples/system/app_trace_basic/sdkconfig.defaults +++ b/examples/system/app_trace_basic/sdkconfig.defaults @@ -1,2 +1,4 @@ # Enable application tracing by default -CONFIG_APPTRACE_ENABLE=y +CONFIG_ESP_TRACE_ENABLE=y +CONFIG_ESP_TRACE_LIB_NONE=y +CONFIG_ESP_TRACE_TRANSPORT_APPTRACE=y diff --git a/examples/system/app_trace_to_plot/main/CMakeLists.txt b/examples/system/app_trace_to_plot/main/CMakeLists.txt index d96666ff74b..ce5523dc831 100644 --- a/examples/system/app_trace_to_plot/main/CMakeLists.txt +++ b/examples/system/app_trace_to_plot/main/CMakeLists.txt @@ -1,3 +1,3 @@ idf_component_register(SRCS "app_trace_to_plot.c" - PRIV_REQUIRES app_trace + PRIV_REQUIRES esp_trace INCLUDE_DIRS ".") diff --git a/examples/system/app_trace_to_plot/main/app_trace_to_plot.c b/examples/system/app_trace_to_plot/main/app_trace_to_plot.c index db686a10859..ce872916abe 100644 --- a/examples/system/app_trace_to_plot/main/app_trace_to_plot.c +++ b/examples/system/app_trace_to_plot/main/app_trace_to_plot.c @@ -17,6 +17,7 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_app_trace.h" +#include "esp_trace.h" #include "esp_log.h" #include #include diff --git a/examples/system/app_trace_to_plot/sdkconfig.defaults b/examples/system/app_trace_to_plot/sdkconfig.defaults index bcec5bd2f04..fbbd10861bf 100644 --- a/examples/system/app_trace_to_plot/sdkconfig.defaults +++ b/examples/system/app_trace_to_plot/sdkconfig.defaults @@ -1,3 +1,5 @@ # Enable application tracing by default -CONFIG_APPTRACE_ENABLE=y +CONFIG_ESP_TRACE_ENABLE=y +CONFIG_ESP_TRACE_LIB_NONE=y +CONFIG_ESP_TRACE_TRANSPORT_APPTRACE=y CONFIG_APPTRACE_DEST_JTAG=y diff --git a/examples/system/gcov/sdkconfig.defaults b/examples/system/gcov/sdkconfig.defaults index 4d64a379004..bd9ffe56cac 100644 --- a/examples/system/gcov/sdkconfig.defaults +++ b/examples/system/gcov/sdkconfig.defaults @@ -1,5 +1,7 @@ +CONFIG_ESP_TRACE_ENABLE=y +CONFIG_ESP_TRACE_LIB_NONE=y +CONFIG_ESP_TRACE_TRANSPORT_APPTRACE=y CONFIG_APPTRACE_DEST_JTAG=y -CONFIG_APPTRACE_ENABLE=y CONFIG_APPTRACE_LOCK_ENABLE=y CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO=-1 CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH=0 diff --git a/examples/system/sysview_tracing/main/CMakeLists.txt b/examples/system/sysview_tracing/main/CMakeLists.txt index 55b846e1da2..ff0df4c7b76 100644 --- a/examples/system/sysview_tracing/main/CMakeLists.txt +++ b/examples/system/sysview_tracing/main/CMakeLists.txt @@ -1,3 +1,3 @@ idf_component_register(SRCS "sysview_tracing.c" - PRIV_REQUIRES esp_driver_gptimer app_trace + PRIV_REQUIRES esp_driver_gptimer esp_trace INCLUDE_DIRS ".") diff --git a/examples/system/sysview_tracing/main/sysview_tracing.c b/examples/system/sysview_tracing/main/sysview_tracing.c index 0d62a122177..498e29fb146 100644 --- a/examples/system/sysview_tracing/main/sysview_tracing.c +++ b/examples/system/sysview_tracing/main/sysview_tracing.c @@ -9,6 +9,7 @@ #include "esp_err.h" #include "sdkconfig.h" +#include #include #include #include @@ -18,10 +19,11 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "driver/gptimer.h" +#include "esp_trace.h" static const char *TAG = "example"; -#if CONFIG_APPTRACE_SV_ENABLE +#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW #if !CONFIG_USE_CUSTOM_EVENT_ID #define SYSVIEW_EXAMPLE_SEND_EVENT_ID 0 @@ -76,7 +78,7 @@ static void example_sysview_event_send(uint32_t id, uint32_t val) #define SYSVIEW_EXAMPLE_WAIT_EVENT_START() #define SYSVIEW_EXAMPLE_WAIT_EVENT_END(_val_) -#endif // CONFIG_APPTRACE_SV_ENABLE +#endif // CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW typedef struct { gptimer_handle_t gptimer; @@ -140,7 +142,7 @@ void app_main(void) static example_event_data_t event_data[CONFIG_FREERTOS_NUMBER_OF_CORES]; -#if CONFIG_APPTRACE_SV_ENABLE && CONFIG_USE_CUSTOM_EVENT_ID +#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW && CONFIG_USE_CUSTOM_EVENT_ID // Currently OpenOCD does not support requesting module info from target. So do the following... // Wait until SystemView module receives START command from host, // after that data can be sent to the host using onboard API, diff --git a/examples/system/sysview_tracing/sdkconfig.defaults b/examples/system/sysview_tracing/sdkconfig.defaults index 0593357a289..a555ba97272 100644 --- a/examples/system/sysview_tracing/sdkconfig.defaults +++ b/examples/system/sysview_tracing/sdkconfig.defaults @@ -1,19 +1,20 @@ # 1ms tick period CONFIG_FREERTOS_HZ=1000 # Enable FreeRTOS SystemView Tracing by default -CONFIG_APPTRACE_ENABLE=y -CONFIG_APPTRACE_SV_ENABLE=y -CONFIG_APPTRACE_SV_TS_SOURCE_ESP_TIMER=y -CONFIG_APPTRACE_SV_EVT_OVERFLOW_ENABLE=y -CONFIG_APPTRACE_SV_EVT_ISR_ENTER_ENABLE=y -CONFIG_APPTRACE_SV_EVT_ISR_EXIT_ENABLE=y -CONFIG_APPTRACE_SV_EVT_ISR_TO_SCHED_ENABLE=y -CONFIG_APPTRACE_SV_EVT_TASK_START_EXEC_ENABLE=y -CONFIG_APPTRACE_SV_EVT_TASK_STOP_EXEC_ENABLE=y -CONFIG_APPTRACE_SV_EVT_TASK_START_READY_ENABLE=y -CONFIG_APPTRACE_SV_EVT_TASK_STOP_READY_ENABLE=y -CONFIG_APPTRACE_SV_EVT_TASK_CREATE_ENABLE=y -CONFIG_APPTRACE_SV_EVT_TASK_TERMINATE_ENABLE=y -CONFIG_APPTRACE_SV_EVT_IDLE_ENABLE=y -CONFIG_APPTRACE_SV_EVT_TIMER_ENTER_ENABLE=y -CONFIG_APPTRACE_SV_EVT_TIMER_EXIT_ENABLE=y +CONFIG_ESP_TRACE_ENABLE=y +CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW=y +CONFIG_ESP_TRACE_TRANSPORT_APPTRACE=y +CONFIG_ESP_TRACE_TS_SOURCE_ESP_TIMER=y +CONFIG_SEGGER_SYSVIEW_EVT_OVERFLOW_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_ISR_ENTER_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_ISR_EXIT_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_ISR_TO_SCHED_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_TASK_START_EXEC_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_TASK_STOP_EXEC_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_TASK_START_READY_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_TASK_STOP_READY_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_TASK_CREATE_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_TASK_TERMINATE_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_IDLE_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_TIMER_ENTER_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_TIMER_EXIT_ENABLE=y diff --git a/examples/system/sysview_tracing_heap_log/main/CMakeLists.txt b/examples/system/sysview_tracing_heap_log/main/CMakeLists.txt index 25730750989..f4f7b0740de 100644 --- a/examples/system/sysview_tracing_heap_log/main/CMakeLists.txt +++ b/examples/system/sysview_tracing_heap_log/main/CMakeLists.txt @@ -1,3 +1,3 @@ idf_component_register(SRCS "sysview_heap_log.c" - PRIV_REQUIRES app_trace + PRIV_REQUIRES esp_trace INCLUDE_DIRS ".") diff --git a/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c b/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c index 455d013ad2e..339083a4b7d 100644 --- a/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c +++ b/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c @@ -17,7 +17,7 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/queue.h" - +#include "esp_trace.h" static const char *TAG = "example"; diff --git a/examples/system/sysview_tracing_heap_log/sdkconfig.defaults b/examples/system/sysview_tracing_heap_log/sdkconfig.defaults index 97521d048e8..a709f86cbae 100644 --- a/examples/system/sysview_tracing_heap_log/sdkconfig.defaults +++ b/examples/system/sysview_tracing_heap_log/sdkconfig.defaults @@ -1,24 +1,25 @@ # 1ms tick period CONFIG_FREERTOS_HZ=1000 # Enable application tracing by default +CONFIG_ESP_TRACE_ENABLE=y +CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW=y +CONFIG_ESP_TRACE_TRANSPORT_APPTRACE=y +CONFIG_ESP_TRACE_TS_SOURCE_GPTIMER=y CONFIG_APPTRACE_DEST_JTAG=y -CONFIG_APPTRACE_ENABLE=y # Enable FreeRTOS SystemView Tracing by default -CONFIG_APPTRACE_SV_ENABLE=y -CONFIG_APPTRACE_SV_TS_SOURCE_GPTIMER=y -CONFIG_APPTRACE_SV_EVT_OVERFLOW_ENABLE=y -CONFIG_APPTRACE_SV_EVT_ISR_ENTER_ENABLE=y -CONFIG_APPTRACE_SV_EVT_ISR_EXIT_ENABLE=y -CONFIG_APPTRACE_SV_EVT_ISR_TO_SCHED_ENABLE=y -CONFIG_APPTRACE_SV_EVT_TASK_START_EXEC_ENABLE=y -CONFIG_APPTRACE_SV_EVT_TASK_STOP_EXEC_ENABLE=y -CONFIG_APPTRACE_SV_EVT_TASK_START_READY_ENABLE=y -CONFIG_APPTRACE_SV_EVT_TASK_STOP_READY_ENABLE=y -CONFIG_APPTRACE_SV_EVT_TASK_CREATE_ENABLE=y -CONFIG_APPTRACE_SV_EVT_TASK_TERMINATE_ENABLE=y -CONFIG_APPTRACE_SV_EVT_IDLE_ENABLE=y -CONFIG_APPTRACE_SV_EVT_TIMER_ENTER_ENABLE=y -CONFIG_APPTRACE_SV_EVT_TIMER_EXIT_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_OVERFLOW_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_ISR_ENTER_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_ISR_EXIT_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_ISR_TO_SCHED_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_TASK_START_EXEC_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_TASK_STOP_EXEC_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_TASK_START_READY_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_TASK_STOP_READY_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_TASK_CREATE_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_TASK_TERMINATE_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_IDLE_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_TIMER_ENTER_ENABLE=y +CONFIG_SEGGER_SYSVIEW_EVT_TIMER_EXIT_ENABLE=y # Disable color output in logs CONFIG_LOG_COLORS=n # Enable heap tracing to host diff --git a/tools/ci/check_copyright_config.yaml b/tools/ci/check_copyright_config.yaml index 82486806220..1df236acf8c 100644 --- a/tools/ci/check_copyright_config.yaml +++ b/tools/ci/check_copyright_config.yaml @@ -223,6 +223,19 @@ zigbee: - Apache-2.0 - LicenseRef-Included +esp_trace: + include: + - components/esp_trace/include/ + - components/esp_trace/adapters/transport/ + - components/esp_trace/adapters/encoder/ + - components/esp_trace/src/core/ + - components/esp_trace/src/ports/ + allowed_licenses: + - Apache-2.0 + - MIT + - CC0-1.0 + + # files matching this section do not perform the check # file patterns starting with ! are negated, meaning files matching them won't match the section. ignore: From 1f7b1f3615de63b35e18c144c7bdc37995692d80 Mon Sep 17 00:00:00 2001 From: armando Date: Sat, 11 Oct 2025 11:35:00 +0800 Subject: [PATCH 030/106] feat(mspi): supported psram & flash 120MHz timing tuning --- .../src/bootloader_flash_config_esp32c5.c | 6 +++ .../esp32c5/include/hal/mspi_ll.h | 12 ++++++ .../port/esp32c5/mspi_timing_tuning_configs.h | 43 +++++++++++++------ .../mspi_timing_by_flash_delay.c | 4 +- .../mspi_timing_by_mspi_delay.c | 9 +++- components/esp_psram/esp32c5/Kconfig.spiram | 3 ++ components/spi_flash/Kconfig | 2 +- .../spi_flash/esp32c5/Kconfig.flash_freq | 2 + 8 files changed, 63 insertions(+), 18 deletions(-) diff --git a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c5.c b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c5.c index c9273bd08c6..6563eef671d 100644 --- a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c5.c +++ b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c5.c @@ -237,6 +237,12 @@ esp_err_t bootloader_init_spi_flash(void) bootloader_init_mspi_clock(); bootloader_init_flash_configure(); + +#if CONFIG_BOOTLOADER_FLASH_DC_AWARE + // Reset flash, clear volatile bits DC[0:1]. Make it work under default mode to boot. + bootloader_spi_flash_reset(); +#endif + bootloader_spi_flash_resume(); if ((void*)bootloader_flash_unlock != (void*)bootloader_flash_unlock_default) { ESP_EARLY_LOGD(TAG, "Using overridden bootloader_flash_unlock"); diff --git a/components/esp_hal_mspi/esp32c5/include/hal/mspi_ll.h b/components/esp_hal_mspi/esp32c5/include/hal/mspi_ll.h index 4258d8efe2a..c05190d42bb 100644 --- a/components/esp_hal_mspi/esp32c5/include/hal/mspi_ll.h +++ b/components/esp_hal_mspi/esp32c5/include/hal/mspi_ll.h @@ -230,6 +230,18 @@ static inline void mspi_timing_ll_set_flash_extra_dummy(uint8_t mspi_id, uint8_t REG_SET_BIT(SPI_MEM_TIMING_CALI_REG(MSPI_TIMING_LL_MSPI_ID_0), SPI_MEM_TIMING_CALI_UPDATE); } +/** + * Set MSPI Flash user dummy + * + * @param mspi_id SPI0 / SPI1 + * @param user_dummy user dummy + */ +__attribute__((always_inline)) +static inline void mspi_timing_ll_set_flash_user_dummy(uint8_t mspi_id, uint8_t user_dummy) +{ + REG_SET_FIELD(SPI_MEM_USER1_REG(mspi_id), SPI_MEM_USR_DUMMY_CYCLELEN, user_dummy); +} + /** * Get MSPI flash dummy info * diff --git a/components/esp_hw_support/mspi_timing_tuning/port/esp32c5/mspi_timing_tuning_configs.h b/components/esp_hw_support/mspi_timing_tuning/port/esp32c5/mspi_timing_tuning_configs.h index 82558dbb9eb..92262108aa5 100644 --- a/components/esp_hw_support/mspi_timing_tuning/port/esp32c5/mspi_timing_tuning_configs.h +++ b/components/esp_hw_support/mspi_timing_tuning/port/esp32c5/mspi_timing_tuning_configs.h @@ -43,6 +43,8 @@ #define MSPI_TIMING_PSRAM_MODULE_CLOCK 40 #elif CONFIG_SPIRAM_SPEED_80M #define MSPI_TIMING_PSRAM_MODULE_CLOCK 80 +#else //CONFIG_SPIRAM_SPEED_120M +#define MSPI_TIMING_PSRAM_MODULE_CLOCK 120 #endif #else //Disable PSRAM #define MSPI_TIMING_PSRAM_MODULE_CLOCK 10 //Define this to 10MHz @@ -53,17 +55,30 @@ #define MSPI_TIMING_PSRAM_NEEDS_TUNING (MSPI_TIMING_PSRAM_MODULE_CLOCK > 40) #endif -///////////////////////////////////// FLASH/PSRAM CORE CLOCK ///////////////////////////////////// -#if ((CONFIG_ESPTOOLPY_FLASHFREQ_80M && !CONFIG_SPIRAM) || (CONFIG_ESPTOOLPY_FLASHFREQ_80M && CONFIG_SPIRAM_SPEED_80M)) +///////////////////////////////////// FLASH CORE CLOCK ///////////////////////////////////// +//FLASH 80M +#if CONFIG_ESPTOOLPY_FLASHFREQ_80M #define MSPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ 80 -#define MSPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ 80 #define MSPI_TIMING_FLASH_CONSECUTIVE_LEN_MAX 6 -#else -#define MSPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ 240 -#define MSPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ 240 +#endif + +//FLASH 120M +#if CONFIG_ESPTOOLPY_FLASHFREQ_120M +#define MSPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ 120 #define MSPI_TIMING_FLASH_CONSECUTIVE_LEN_MAX 4 #endif +///////////////////////////////////// PSRAM CORE CLOCK ///////////////////////////////////// +//PSRAM 80M +#if CONFIG_SPIRAM_SPEED_80M +#define MSPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ 80 +#endif + +//PSRAM 120M +#if CONFIG_SPIRAM_SPEED_120M +#define MSPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ 120 +#endif //PSRAM 120M DTR + //------------------------------------------Determine the Core Clock-----------------------------------------------// /** * @note @@ -105,10 +120,10 @@ ESP_STATIC_ASSERT(MSPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ % MSPI_TIMING_FLASH_MO /** * Timing Tuning Parameters */ -//FLASH: core clock 240M, module clock 120M, STR mode -#define MSPI_TIMING_FLASH_CONFIG_TABLE_CORE_CLK_240M_MODULE_CLK_120M_STR_MODE {{2, 0, 1}, {0, 0, 0}, {2, 2, 2}, {2, 1, 2}, {2, 0, 2}, {0, 0, 1}, {2, 2, 3}, {2, 1, 3}, {2, 0, 3}, {0, 0, 2}, {2, 2, 4}, {2, 1, 4}} -#define MSPI_TIMING_FLASH_CONFIG_NUM_CORE_CLK_240M_MODULE_CLK_120M_STR_MODE 12 -#define MSPI_TIMING_FLASH_DEFAULT_CONFIG_ID_CORE_CLK_240M_MODULE_CLK_120M_STR_MODE 4 +//FLASH: core clock 120M, module clock 120M, STR mode +#define MSPI_TIMING_FLASH_CONFIG_TABLE_CORE_CLK_120M_MODULE_CLK_120M_STR_MODE {{2, 0, 1}, {0, 0, 0}, {2, 2, 2}, {2, 1, 2}, {2, 0, 2}, {0, 0, 1}, {2, 2, 3}, {2, 1, 3}, {2, 0, 3}, {0, 0, 2}, {2, 2, 4}, {2, 1, 4}} +#define MSPI_TIMING_FLASH_CONFIG_NUM_CORE_CLK_120M_MODULE_CLK_120M_STR_MODE 12 +#define MSPI_TIMING_FLASH_DEFAULT_CONFIG_ID_CORE_CLK_120M_MODULE_CLK_120M_STR_MODE 4 //FLASH: core clock 240M, module clock 80M, STR mode #define MSPI_TIMING_FLASH_CONFIG_TABLE_CORE_CLK_240M_MODULE_CLK_80M_STR_MODE {{2, 2, 1}, {2, 1, 1}, {2, 0, 1}, {0, 0, 0}, {3, 1, 2}, {2, 3, 2}, {2, 2, 2}, {2, 1, 2}, {2, 0, 2}, {0, 0, 1}, {3, 1, 3}, {2, 3, 3}, {2, 2, 3}, {2, 1, 3}} @@ -120,10 +135,10 @@ ESP_STATIC_ASSERT(MSPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ % MSPI_TIMING_FLASH_MO #define MSPI_TIMING_FLASH_CONFIG_NUM_CORE_CLK_80M_MODULE_CLK_80M_STR_MODE 14 #define MSPI_TIMING_FLASH_DEFAULT_CONFIG_ID_CORE_CLK_80M_MODULE_CLK_80M_STR_MODE 4 -//PSRAM: core clock 240M, module clock 120M, STR mode -#define MSPI_TIMING_PSRAM_CONFIG_TABLE_CORE_CLK_240M_MODULE_CLK_120M_STR_MODE {{2, 0, 1}, {0, 0, 0}, {2, 2, 2}, {2, 1, 2}, {2, 0, 2}, {0, 0, 1}, {2, 2, 3}, {2, 1, 3}, {2, 0, 3}, {0, 0, 2}, {2, 2, 4}, {2, 1, 4}} -#define MSPI_TIMING_PSRAM_CONFIG_NUM_CORE_CLK_240M_MODULE_CLK_120M_STR_MODE 12 -#define MSPI_TIMING_PSRAM_DEFAULT_CONFIG_ID_CORE_CLK_240M_MODULE_CLK_120M_STR_MODE 4 +//PSRAM: core clock 120M, module clock 120M, STR mode +#define MSPI_TIMING_PSRAM_CONFIG_TABLE_CORE_CLK_120M_MODULE_CLK_120M_STR_MODE {{2, 0, 1}, {0, 0, 0}, {2, 2, 2}, {2, 1, 2}, {2, 0, 2}, {0, 0, 1}, {2, 2, 3}, {2, 1, 3}, {2, 0, 3}, {0, 0, 2}, {2, 2, 4}, {2, 1, 4}} +#define MSPI_TIMING_PSRAM_CONFIG_NUM_CORE_CLK_120M_MODULE_CLK_120M_STR_MODE 12 +#define MSPI_TIMING_PSRAM_DEFAULT_CONFIG_ID_CORE_CLK_120M_MODULE_CLK_120M_STR_MODE 4 //PSRAM: core clock 240M, module clock 80M, STR mode #define MSPI_TIMING_PSRAM_CONFIG_TABLE_CORE_CLK_240M_MODULE_CLK_80M_STR_MODE {{2, 2, 1}, {2, 1, 1}, {2, 0, 1}, {0, 0, 0}, {3, 1, 2}, {2, 3, 2}, {2, 2, 2}, {2, 1, 2}, {2, 0, 2}, {0, 0, 1}, {3, 1, 3}, {2, 3, 3}, {2, 2, 3}, {2, 1, 3}} diff --git a/components/esp_hw_support/mspi_timing_tuning/tuning_scheme_impl/mspi_timing_by_flash_delay.c b/components/esp_hw_support/mspi_timing_tuning/tuning_scheme_impl/mspi_timing_by_flash_delay.c index 805aeda0a73..3e8aa83afce 100644 --- a/components/esp_hw_support/mspi_timing_tuning/tuning_scheme_impl/mspi_timing_by_flash_delay.c +++ b/components/esp_hw_support/mspi_timing_tuning/tuning_scheme_impl/mspi_timing_by_flash_delay.c @@ -73,7 +73,7 @@ void mspi_timing_config_flash_set_tuning_regs(const void *configs, uint8_t id) //-------------------------------------------FLASH Read/Write------------------------------------------// void mspi_timing_config_flash_read_data(uint8_t *buf, uint32_t addr, uint32_t len) { -#if CONFIG_ESPTOOLPY_FLASHMODE_QIO +#if CONFIG_ESPTOOLPY_FLASHMODE_QIO && CONFIG_SPI_FLASH_HPM_ON g_rom_spiflash_dummy_len_plus[1] = 4; #endif esp_rom_spiflash_read(addr, (uint32_t *)buf, len); @@ -164,7 +164,7 @@ void mspi_timing_flash_config_set_tuning_regs(bool control_both_mspi) //Won't touch SPI1 registers } -#if MSPI_TIMING_FLASH_NEEDS_TUNING && CONFIG_ESPTOOLPY_FLASHMODE_QIO +#if MSPI_TIMING_FLASH_NEEDS_TUNING && CONFIG_ESPTOOLPY_FLASHMODE_QIO && CONFIG_SPI_FLASH_HPM_ON mspi_timing_ll_set_flash_user_dummy(MSPI_TIMING_LL_MSPI_ID_0, 7); #endif diff --git a/components/esp_hw_support/mspi_timing_tuning/tuning_scheme_impl/mspi_timing_by_mspi_delay.c b/components/esp_hw_support/mspi_timing_tuning/tuning_scheme_impl/mspi_timing_by_mspi_delay.c index 38c20923038..b1ba7201771 100644 --- a/components/esp_hw_support/mspi_timing_tuning/tuning_scheme_impl/mspi_timing_by_mspi_delay.c +++ b/components/esp_hw_support/mspi_timing_tuning/tuning_scheme_impl/mspi_timing_by_mspi_delay.c @@ -87,6 +87,9 @@ void mspi_timing_config_flash_set_tuning_regs(const void *configs, uint8_t id) //-------------------------------------------FLASH Read/Write------------------------------------------// void mspi_timing_config_flash_read_data(uint8_t *buf, uint32_t addr, uint32_t len) { +#if CONFIG_ESPTOOLPY_FLASHMODE_QIO && CONFIG_SPI_FLASH_HPM_ON + g_rom_spiflash_dummy_len_plus[1] = 4; +#endif if (bootloader_flash_is_octal_mode_enabled()) { // note that in spi_flash_read API, there is a wait-idle stage, since flash can only be read in idle state. // but after we change the timing settings, we might not read correct idle status via RDSR. @@ -353,6 +356,10 @@ void mspi_timing_flash_config_set_tuning_regs(bool control_both_mspi) //Won't touch SPI1 registers } +#if MSPI_TIMING_FLASH_NEEDS_TUNING && CONFIG_ESPTOOLPY_FLASHMODE_QIO && CONFIG_SPI_FLASH_HPM_ON + mspi_timing_ll_set_flash_user_dummy(MSPI_TIMING_LL_MSPI_ID_0, 7); +#endif + int spi1_usr_dummy = 0; int spi1_extra_dummy = 0; int spi0_usr_dummy = 0; @@ -382,7 +389,7 @@ void mspi_timing_psram_config_set_tuning_regs(bool control_both_mspi) } /*------------------------------------------------------------------------------------------------- - * To let upper lay (spi_flash_timing_tuning.c) to know the necessary timing registers + * To let upper layer (spi_flash_timing_tuning.c) to know the necessary timing registers *-------------------------------------------------------------------------------------------------*/ /** * Get the SPI1 Flash CS timing setting. The setup time and hold time are both realistic cycles. diff --git a/components/esp_psram/esp32c5/Kconfig.spiram b/components/esp_psram/esp32c5/Kconfig.spiram index a27b718f9c5..3b5b8ef65bc 100644 --- a/components/esp_psram/esp32c5/Kconfig.spiram +++ b/components/esp_psram/esp32c5/Kconfig.spiram @@ -23,6 +23,8 @@ menu "SPI RAM config" help Select the speed for the SPI RAM chip. + config SPIRAM_SPEED_120M + bool "120MHz clock speed" config SPIRAM_SPEED_80M bool "80MHz clock speed" config SPIRAM_SPEED_40M @@ -31,6 +33,7 @@ menu "SPI RAM config" config SPIRAM_SPEED int + default 120 if SPIRAM_SPEED_120M default 80 if SPIRAM_SPEED_80M default 40 if SPIRAM_SPEED_40M diff --git a/components/spi_flash/Kconfig b/components/spi_flash/Kconfig index f96bfab0456..81d6feef399 100644 --- a/components/spi_flash/Kconfig +++ b/components/spi_flash/Kconfig @@ -36,7 +36,7 @@ menu "Main Flash configuration" choice SPI_FLASH_HPM prompt "High Performance Mode (READ DOCS FIRST, > 80MHz)" # Currently, only esp32s3 allows high performance mode. - depends on (IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4) && !ESPTOOLPY_OCT_FLASH + depends on (IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4 || IDF_TARGET_ESP32C5) && !ESPTOOLPY_OCT_FLASH default SPI_FLASH_HPM_AUTO help Whether the High Performance Mode of Flash is enabled. As an optional feature, user needs to manually diff --git a/components/spi_flash/esp32c5/Kconfig.flash_freq b/components/spi_flash/esp32c5/Kconfig.flash_freq index 2eac2e2f958..ac9875af5af 100644 --- a/components/spi_flash/esp32c5/Kconfig.flash_freq +++ b/components/spi_flash/esp32c5/Kconfig.flash_freq @@ -1,6 +1,8 @@ choice ESPTOOLPY_FLASHFREQ prompt "Flash SPI speed" default ESPTOOLPY_FLASHFREQ_80M + config ESPTOOLPY_FLASHFREQ_120M + bool "120 MHz" config ESPTOOLPY_FLASHFREQ_80M bool "80 MHz" config ESPTOOLPY_FLASHFREQ_40M From 73b6e718f290730a4d6e07119b581167fa75b07b Mon Sep 17 00:00:00 2001 From: Laukik Hase Date: Wed, 5 Nov 2025 16:21:28 +0530 Subject: [PATCH 031/106] ci(esp_tee): Remove incorrect error checks for TEE flash protection tests - Also fixed coverity issue from TEE secure storage --- .../tee_sec_storage/tee_sec_storage.c | 5 ++-- .../main/test_esp_tee_flash_prot.c | 24 +++++-------------- 2 files changed, 9 insertions(+), 20 deletions(-) diff --git a/components/esp_tee/subproject/components/tee_sec_storage/tee_sec_storage.c b/components/esp_tee/subproject/components/tee_sec_storage/tee_sec_storage.c index ff6ef16cfd3..0868e386066 100644 --- a/components/esp_tee/subproject/components/tee_sec_storage/tee_sec_storage.c +++ b/components/esp_tee/subproject/components/tee_sec_storage/tee_sec_storage.c @@ -643,11 +643,12 @@ esp_err_t esp_tee_sec_storage_ecdsa_sign_pbkdf2(const esp_tee_sec_storage_pbkdf2 return ESP_ERR_INVALID_ARG; } - hmac_key_id_t key_id = (hmac_key_id_t)(CONFIG_SECURE_TEE_PBKDF2_EFUSE_HMAC_KEY_ID); - if (key_id < 0 || key_id >= HMAC_KEY_MAX) { + int cfg_key_id = (int)CONFIG_SECURE_TEE_PBKDF2_EFUSE_HMAC_KEY_ID; + if (cfg_key_id < 0 || cfg_key_id >= HMAC_KEY_MAX) { return ESP_ERR_INVALID_ARG; } + hmac_key_id_t key_id = (hmac_key_id_t)cfg_key_id; esp_efuse_block_t blk = (esp_efuse_block_t)(EFUSE_BLK_KEY0 + key_id); if (esp_efuse_get_key_purpose(blk) != ESP_EFUSE_KEY_PURPOSE_HMAC_UP) { ESP_LOGE(TAG, "HMAC key is not burnt in the specified eFuse block ID"); diff --git a/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_flash_prot.c b/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_flash_prot.c index 9a7e68afc49..030e6ff1c8c 100644 --- a/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_flash_prot.c +++ b/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_flash_prot.c @@ -48,12 +48,6 @@ __attribute__((unused)) static const uint32_t mmu_op_fail_seq[8] = {[0 ... 7] = } while (0) #endif -#if SOC_TEE_FLASH_OP_FAIL_FAULT -#define CHECK_FLASH_OP_FAIL(err) TEST_ESP_ERR(ESP_FAIL, err) -#else -#define CHECK_FLASH_OP_FAIL(err) do { (void)(err); esp_restart(); } while (0) -#endif - static const char *TAG = "test_esp_tee_flash_prot"; static void set_boot_count_in_nvs(uint8_t boot_count) @@ -146,8 +140,7 @@ static void test_esp_partition_api_r(const esp_partition_t *part) TEST_ASSERT_NOT_NULL(part); uint8_t buf_r[128]; memset(buf_r, 0x00, sizeof(buf_r)); - esp_err_t err = esp_partition_read(part, 0x00, buf_r, sizeof(buf_r)); - CHECK_FLASH_OP_FAIL(err); + esp_partition_read(part, 0x00, buf_r, sizeof(buf_r)); } static void test_esp_partition_api_w(const esp_partition_t *part) @@ -155,15 +148,13 @@ static void test_esp_partition_api_w(const esp_partition_t *part) TEST_ASSERT_NOT_NULL(part); uint8_t buf_w[128]; memset(buf_w, 0xA5, sizeof(buf_w)); - esp_err_t err = esp_partition_write(part, 0x00, buf_w, sizeof(buf_w)); - CHECK_FLASH_OP_FAIL(err); + esp_partition_write(part, 0x00, buf_w, sizeof(buf_w)); } static void test_esp_partition_api_e(const esp_partition_t *part) { TEST_ASSERT_NOT_NULL(part); - esp_err_t err = esp_partition_erase_range(part, 0x00, SPI_FLASH_SEC_SIZE); - CHECK_FLASH_OP_FAIL(err); + esp_partition_erase_range(part, 0x00, SPI_FLASH_SEC_SIZE); } static void test_esp_partition_api(void) @@ -267,22 +258,19 @@ static void test_esp_flash_api_r(uint32_t paddr) { uint8_t buf_r[128]; memset(buf_r, 0x00, sizeof(buf_r)); - esp_err_t err = esp_flash_read(NULL, buf_r, paddr, sizeof(buf_r)); - CHECK_FLASH_OP_FAIL(err); + esp_flash_read(NULL, buf_r, paddr, sizeof(buf_r)); } static void test_esp_flash_api_w(uint32_t paddr) { uint8_t buf_w[128]; memset(buf_w, 0xA5, sizeof(buf_w)); - esp_err_t err = esp_flash_write(NULL, buf_w, paddr, sizeof(buf_w)); - CHECK_FLASH_OP_FAIL(err); + esp_flash_write(NULL, buf_w, paddr, sizeof(buf_w)); } static void test_esp_flash_api_e(uint32_t paddr) { - esp_err_t err = esp_flash_erase_region(NULL, paddr, SPI_FLASH_SEC_SIZE); - CHECK_FLASH_OP_FAIL(err); + esp_flash_erase_region(NULL, paddr, SPI_FLASH_SEC_SIZE); } static void test_esp_flash_api(void) From 5b3185168dae83d42aa0852689422fffd931f16c Mon Sep 17 00:00:00 2001 From: Jin Cheng Date: Tue, 28 Oct 2025 10:47:55 +0800 Subject: [PATCH 032/106] fix(bt/blurdoird): fixed an OOB write in bta_dm_sdp_result --- components/bt/common/include/bt_common.h | 1 + .../bt/host/bluedroid/bta/dm/bta_dm_act.c | 19 ++++++++++++++----- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/components/bt/common/include/bt_common.h b/components/bt/common/include/bt_common.h index 1ebd5b14383..f687e3afe7a 100644 --- a/components/bt/common/include/bt_common.h +++ b/components/bt/common/include/bt_common.h @@ -240,6 +240,7 @@ typedef uint64_t UINT64; typedef bool BOOLEAN; /* Maximum UUID size - 16 bytes, and structure to hold any type of UUID. */ #define MAX_UUID_SIZE 16 +#define MAX_UUID_NUM 32 typedef struct { #define LEN_UUID_16 2 diff --git a/components/bt/host/bluedroid/bta/dm/bta_dm_act.c b/components/bt/host/bluedroid/bta/dm/bta_dm_act.c index 3ec7ae2aff5..c0383286a20 100644 --- a/components/bt/host/bluedroid/bta/dm/bta_dm_act.c +++ b/components/bt/host/bluedroid/bta/dm/bta_dm_act.c @@ -2056,7 +2056,7 @@ void bta_dm_sdp_result (tBTA_DM_MSG *p_data) #endif UINT32 num_uuids = 0; - UINT8 uuid_list[32][MAX_UUID_SIZE]; // assuming a max of 32 services + UINT8 uuid_list[MAX_UUID_NUM][MAX_UUID_SIZE]; // assuming a max of MAX_UUID_NUM services if ((p_data->sdp_event.sdp_result == SDP_SUCCESS) || (p_data->sdp_event.sdp_result == SDP_NO_RECS_MATCH) @@ -2119,8 +2119,12 @@ void bta_dm_sdp_result (tBTA_DM_MSG *p_data) (tBTA_SERVICE_MASK)(BTA_SERVICE_ID_TO_SERVICE_MASK(bta_dm_search_cb.service_index - 1)); tmp_svc = bta_service_id_to_uuid_lkup_tbl[bta_dm_search_cb.service_index - 1]; /* Add to the list of UUIDs */ - sdpu_uuid16_to_uuid128(tmp_svc, uuid_list[num_uuids]); - num_uuids++; + if (num_uuids < MAX_UUID_NUM) { + sdpu_uuid16_to_uuid128(tmp_svc, uuid_list[num_uuids]); + num_uuids++; + } else { + APPL_TRACE_WARNING("only process the first %d records\n", MAX_UUID_NUM); + } } } } @@ -2154,8 +2158,13 @@ void bta_dm_sdp_result (tBTA_DM_MSG *p_data) p_sdp_rec = SDP_FindServiceInDb_128bit(bta_dm_search_cb.p_sdp_db, p_sdp_rec); if (p_sdp_rec) { if (SDP_FindServiceUUIDInRec_128bit(p_sdp_rec, &temp_uuid)) { - memcpy(uuid_list[num_uuids], temp_uuid.uu.uuid128, MAX_UUID_SIZE); - num_uuids++; + if (num_uuids < MAX_UUID_NUM) { + memcpy(uuid_list[num_uuids], temp_uuid.uu.uuid128, MAX_UUID_SIZE); + num_uuids++; + } else { + APPL_TRACE_WARNING("only process the first %d records\n", MAX_UUID_NUM); + break; + } } } } while (p_sdp_rec); From 981e271b9466993a8b522c9039cd75bd8df08a95 Mon Sep 17 00:00:00 2001 From: "igor.masar" Date: Sun, 19 Oct 2025 19:10:38 +0200 Subject: [PATCH 033/106] docs(usb): add ESP32-H4 support notes and pin map - usb_device: add esp32h4 DP/DM defaults (GPIO22/21) and "only:: esp32h4"; add H4 PHY considerations; add H4 MSC write-speed table; generalize MSC SD note to {IDF_TARGET_NAME}; exclude tusb_ncm on H4 - usb_host: include esp32h4 in feature gates; add H4 PHY considerations - usb_host_notes_dwc_otg: enable H4 by extending "only::" selector - examples/usb: add ESP32-H4 row to DP/DM pin map - docs_not_updated: drop H4 entries for usb_device, usb_host, and related usb_host notes now covered - soc(esp32h4): set internal PHY mapping to DP=22, DM=21 (cherry picked from commit 7492f9b9cd74740ce23d1ba377856754c99efe88) --- components/soc/esp32h4/usb_dwc_periph.c | 4 +-- docs/docs_not_updated/esp32h4.txt | 10 ------ .../api-reference/peripherals/usb_device.rst | 33 +++++++++++++++---- .../en/api-reference/peripherals/usb_host.rst | 2 +- .../usb_host/usb_host_notes_dwc_otg.rst | 2 +- examples/peripherals/usb/README.md | 1 + 6 files changed, 32 insertions(+), 20 deletions(-) diff --git a/components/soc/esp32h4/usb_dwc_periph.c b/components/soc/esp32h4/usb_dwc_periph.c index 0b5c4e43dc7..fe2b5acdee1 100644 --- a/components/soc/esp32h4/usb_dwc_periph.c +++ b/components/soc/esp32h4/usb_dwc_periph.c @@ -28,8 +28,8 @@ static const usb_otg_signal_conn_t otg_signals = { }; static const usb_internal_phy_io_t internal_phy_io = { - .dp = 21, - .dm = 22, + .dp = 22, + .dm = 21, }; /* --------------------------------- Public --------------------------------- */ diff --git a/docs/docs_not_updated/esp32h4.txt b/docs/docs_not_updated/esp32h4.txt index d75bf21a37b..b16afa94618 100644 --- a/docs/docs_not_updated/esp32h4.txt +++ b/docs/docs_not_updated/esp32h4.txt @@ -125,10 +125,8 @@ api-reference/peripherals/gptimer.rst api-reference/peripherals/sdio_slave.rst api-reference/peripherals/bitscrambler.rst api-reference/peripherals/temp_sensor.rst -api-reference/peripherals/usb_device.rst api-reference/peripherals/jpeg.rst api-reference/peripherals/mcpwm.rst -api-reference/peripherals/usb_host.rst api-reference/peripherals/camera_driver.rst api-reference/peripherals/adc_oneshot.rst api-reference/peripherals/sdspi_share.rst @@ -139,14 +137,6 @@ api-reference/peripherals/sdspi_host.rst api-reference/peripherals/vad.rst api-reference/peripherals/i2s.rst api-reference/peripherals/isp.rst -api-reference/peripherals/usb_host/usb_host_notes_usbh.rst -api-reference/peripherals/usb_host/usb_host_notes_ext_hub.rst -api-reference/peripherals/usb_host/usb_host_notes_arch.rst -api-reference/peripherals/usb_host/usb_host_notes_index.rst -api-reference/peripherals/usb_host/usb_host_notes_ext_port.rst -api-reference/peripherals/usb_host/usb_host_notes_design.rst -api-reference/peripherals/usb_host/usb_host_notes_enum.rst -api-reference/peripherals/usb_host/usb_host_notes_dwc_otg.rst api-reference/peripherals/dedic_gpio.rst api-reference/peripherals/sd_pullup_requirements.rst api-reference/peripherals/parlio.rst diff --git a/docs/en/api-reference/peripherals/usb_device.rst b/docs/en/api-reference/peripherals/usb_device.rst index 8fcb8b2c8ac..df58ee34728 100644 --- a/docs/en/api-reference/peripherals/usb_device.rst +++ b/docs/en/api-reference/peripherals/usb_device.rst @@ -3,8 +3,8 @@ USB Device Stack :link_to_translation:`zh_CN:[中文]` -{IDF_TARGET_USB_DP_GPIO_NUM:default="20"} -{IDF_TARGET_USB_DM_GPIO_NUM:default="19"} +{IDF_TARGET_USB_DP_GPIO_NUM:default="20", esp32h4="22"} +{IDF_TARGET_USB_DM_GPIO_NUM:default="19", esp32h4="21"} {IDF_TARGET_USB_EP_NUM: default="6", esp32p4="15"} {IDF_TARGET_USB_EP_NUM_INOUT:default="5", esp32p4="8"} {IDF_TARGET_USB_EP_NUM_IN:default="1", esp32p4="7"} @@ -34,7 +34,7 @@ Features Hardware Connection ------------------- -.. only:: esp32s2 or esp32s3 +.. only:: esp32s2 or esp32s3 or esp32h4 The {IDF_TARGET_NAME} routes the USB D+ and D- signals to GPIOs {IDF_TARGET_USB_DP_GPIO_NUM} and {IDF_TARGET_USB_DM_GPIO_NUM} respectively. For USB device functionality, these GPIOs should be connected to the bus in some way (e.g., via a Micro-B port, USB-C port, or directly to standard-A plug). @@ -47,7 +47,7 @@ Hardware Connection :alt: Connection of an USB GPIOs directly to a USB standard-A plug :figclass: align-center -.. only:: esp32s2 or esp32s3 +.. only:: esp32s2 or esp32s3 or esp32h4 .. note:: @@ -406,7 +406,7 @@ This approach ensures that USB transactions remain fast while avoiding potential .. note:: - SD card support is not available for ESP32-S2 in MSC device mode. + SD card support is not available for {IDF_TARGET_NAME} in MSC device mode. **SPI Flash Performance:** @@ -423,6 +423,27 @@ This approach ensures that USB transactions remain fast while avoiding potential * - 8192 B - 21.54 KB/s +.. only:: esp32h4 + + .. note:: + + SD card support is not available for {IDF_TARGET_NAME} in MSC device mode. + + **SPI Flash Performance:** + + .. list-table:: + :header-rows: 1 + :widths: 20 20 + + * - FIFO Size + - Write Speed + + * - 512 B + - 4.48 KB/s + + * - 8192 B + - 22.33 KB/s + Performance Limitations: - **Internal SPI Flash performance** is constrained by architectural limitations where program execution and storage access share the same flash chip. This results in program execution being **suspended during flash writes**, significantly impacting performance. @@ -444,6 +465,6 @@ The examples can be found in the directory :example:`peripherals/usb/device`. - :example:`peripherals/usb/device/tusb_msc` demonstrates how to use the USB capabilities to create a Mass Storage Device that can be recognized by USB-hosts, allowing access to its internal data storage, with support for SPI Flash and SD MMC Card storage media. - :example:`peripherals/usb/device/tusb_composite_msc_serialdevice` demonstrates how to set up {IDF_TARGET_NAME} to function simultaneously as both a USB Serial Device and an MSC device (SPI-Flash as the storage media) using the TinyUSB component. -.. only:: not esp32p4 +.. only:: not esp32p4 and not esp32h4 - :example:`peripherals/usb/device/tusb_ncm` demonstrates how to transmit Wi-Fi data to a Linux or Windows host via USB using the Network Control Model (NCM), a sub-class of Communication Device Class (CDC) USB Device for Ethernet-over-USB applications, with the help of a TinyUSB component. diff --git a/docs/en/api-reference/peripherals/usb_host.rst b/docs/en/api-reference/peripherals/usb_host.rst index c318c06eb6f..38184cfbe64 100644 --- a/docs/en/api-reference/peripherals/usb_host.rst +++ b/docs/en/api-reference/peripherals/usb_host.rst @@ -29,7 +29,7 @@ The Host Library has the following features: .. list:: - :esp32s2 or esp32s3: - Supports Full Speed (FS) and Low Speed (LS) Devices. + :esp32s2 or esp32s3 or esp32h4: - Supports Full Speed (FS) and Low Speed (LS) Devices. :esp32p4: - Supports High Speed (HS), Full Speed (FS) and Low Speed (LS) Devices. - Supports all four transfer types: Control, Bulk, Interrupt, and Isochronous. :esp32p4: - Supports High-Bandwidth Isochronous endpoints. diff --git a/docs/en/api-reference/peripherals/usb_host/usb_host_notes_dwc_otg.rst b/docs/en/api-reference/peripherals/usb_host/usb_host_notes_dwc_otg.rst index e9cab825284..1885b7d0884 100644 --- a/docs/en/api-reference/peripherals/usb_host/usb_host_notes_dwc_otg.rst +++ b/docs/en/api-reference/peripherals/usb_host/usb_host_notes_dwc_otg.rst @@ -116,7 +116,7 @@ The DWC_OTG IP is configurable. The notable host related configurations of the { * - Only 4 periodic and 4 non-periodic transactions per microframe - ``OTG_NPERIO_TX_QUEUE_DEPTH = 4``, ``OTG_PERIO_TX_QUEUE_DEPTH = 4`` -.. only:: esp32s2 or esp32s3 +.. only:: esp32s2 or esp32s3 or esp32h4 .. list-table:: {IDF_TARGET_NAME}'s DWC_OTG Configuration :widths: 70 30 diff --git a/examples/peripherals/usb/README.md b/examples/peripherals/usb/README.md index 30a6320fe71..b3000ffbb89 100644 --- a/examples/peripherals/usb/README.md +++ b/examples/peripherals/usb/README.md @@ -24,5 +24,6 @@ ESP BOARD USB CONNECTOR (type A) | ESP32-S2/S3 | GPIO20 | GPIO19 | | ESP32-P4 2.0 | pin 50 | pin 49 | | ESP32-P4 1.1 | GPIO27 | GPIO26 | +| ESP32-H4 | GPIO22 | GPIO21 | > Note: On the ESP32-P4, the USB 2.0 PHY pins are dedicated to USB-OTG functionality and cannot be used as general-purpose GPIOs. From c88d8ed378e3864dc5f4e9538f87a9280d4e3b25 Mon Sep 17 00:00:00 2001 From: renpeiying Date: Tue, 4 Nov 2025 15:07:36 +0800 Subject: [PATCH 034/106] docs: Update CN translation (cherry picked from commit bcef36325b41b93df9851c87940697b9653cd039) --- .../api-reference/peripherals/usb_device.rst | 33 +++++++++++++++---- .../api-reference/peripherals/usb_host.rst | 2 +- .../usb_host/usb_host_notes_dwc_otg.rst | 2 +- 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/docs/zh_CN/api-reference/peripherals/usb_device.rst b/docs/zh_CN/api-reference/peripherals/usb_device.rst index 205649f9d12..7486c26c0d7 100644 --- a/docs/zh_CN/api-reference/peripherals/usb_device.rst +++ b/docs/zh_CN/api-reference/peripherals/usb_device.rst @@ -3,8 +3,8 @@ USB 设备栈 :link_to_translation:`en:[English]` -{IDF_TARGET_USB_DP_GPIO_NUM:default="20"} -{IDF_TARGET_USB_DM_GPIO_NUM:default="19"} +{IDF_TARGET_USB_DP_GPIO_NUM:default="20", esp32h4="22"} +{IDF_TARGET_USB_DM_GPIO_NUM:default="19", esp32h4="21"} {IDF_TARGET_USB_EP_NUM: default="6", esp32p4="15"} {IDF_TARGET_USB_EP_NUM_INOUT:default="5", esp32p4="8"} {IDF_TARGET_USB_EP_NUM_IN:default="1", esp32p4="7"} @@ -34,7 +34,7 @@ USB 设备栈(以下简称设备栈)支持在 {IDF_TARGET_NAME} 上启用 US 硬件连接 -------- -.. only:: esp32s2 or esp32s3 +.. only:: esp32s2 or esp32s3 or esp32h4 {IDF_TARGET_NAME} 将 USB D+ 和 D- 信号分别路由到 GPIO {IDF_TARGET_USB_DP_GPIO_NUM} 和 {IDF_TARGET_USB_DM_GPIO_NUM}。为了实现 USB 设备功能,这些 GPIO 应通过某种方式连接到总线(例如,通过 Micro-B 端口、USB-C 端口或直接连接到标准-A 插头)。 @@ -47,7 +47,7 @@ USB 设备栈(以下简称设备栈)支持在 {IDF_TARGET_NAME} 上启用 US :alt: 将 USB GPIO 直接接连至 USB 标准-A 插头 :figclass: align-center -.. only:: esp32s2 or esp32s3 +.. only:: esp32s2 or esp32s3 or esp32h4 .. note:: @@ -406,7 +406,7 @@ single-buffer 方案通过使用专用 buffer 临时存储接收到的写入数 .. note:: - ESP32-S2 在 MSC 设备模式下不支持 SD 卡功能。 + {IDF_TARGET_NAME} 在 MSC 设备模式下不支持 SD 卡功能。 **SPI flash 性能:** @@ -423,6 +423,27 @@ single-buffer 方案通过使用专用 buffer 临时存储接收到的写入数 * - 8192 B - 21.54 KB/s +.. only:: esp32h4 + + .. note:: + + {IDF_TARGET_NAME} 不支持在 MSC 设备模式下使用 SD 卡。 + + **SPI Flash 性能:** + + .. list-table:: + :header-rows: 1 + :widths: 20 20 + + * - FIFO 大小 + - 写入速度 + + * - 512 B + - 4.48 KB/s + + * - 8192 B + - 22.33 KB/s + 性能限制: - **内部 SPI flash 性能** 受架构限制影响。程序执行和存储访问共享同一 flash 芯片,导致写入 flash 时必须暂停程序执行,会显著影响性能。 @@ -444,6 +465,6 @@ single-buffer 方案通过使用专用 buffer 临时存储接收到的写入数 - :example:`peripherals/usb/device/tusb_msc` 演示了如何使用 USB 功能创建一个可以被 USB 主机识别的大容量存储设备,允许访问其内部数据存储,支持 SPI Flash 和 SD MMC 卡存储介质。 - :example:`peripherals/usb/device/tusb_composite_msc_serialdevice` 演示了如何使用 TinyUSB 组件将 {IDF_TARGET_NAME} 同时配置为 USB 串行设备和 MSC 设备(存储介质为 SPI-Flash)运行。 -.. only:: not esp32p4 +.. only:: not esp32p4 and not esp32h4 - :example:`peripherals/usb/device/tusb_ncm` 演示了使用 TinyUSB 组件,借助网络控制模型 (NCM) 将 Wi-Fi 数据通过 USB 传输到 Linux 或 Windows 主机。NCM 是通信设备类 (CDC) USB 设备的一个子类,专用于 Ethernet-over-USB 应用。 diff --git a/docs/zh_CN/api-reference/peripherals/usb_host.rst b/docs/zh_CN/api-reference/peripherals/usb_host.rst index f83000d2c0e..40a192b4afc 100644 --- a/docs/zh_CN/api-reference/peripherals/usb_host.rst +++ b/docs/zh_CN/api-reference/peripherals/usb_host.rst @@ -29,7 +29,7 @@ USB 主机库(以下简称主机库)是 USB 主机栈的最底层,提供 .. list:: - :esp32s2 or esp32s3: - 支持全速 (FS) 和低速 (LS) 设备。 + :esp32s2 or esp32s3 or esp32h4: - 支持全速 (FS) 和低速 (LS) 设备。 :esp32p4: - 支持高速 (HS)、全速 (FS) 和低速 (LS) 设备。 - 支持四种传输类型,即控制传输、块传输、中断传输和同步传输。 :esp32p4: - 支持高带宽等时性端点。 diff --git a/docs/zh_CN/api-reference/peripherals/usb_host/usb_host_notes_dwc_otg.rst b/docs/zh_CN/api-reference/peripherals/usb_host/usb_host_notes_dwc_otg.rst index a3f5d922786..63d2b3d272f 100644 --- a/docs/zh_CN/api-reference/peripherals/usb_host/usb_host_notes_dwc_otg.rst +++ b/docs/zh_CN/api-reference/peripherals/usb_host/usb_host_notes_dwc_otg.rst @@ -116,7 +116,7 @@ DWC_OTG IP 是可配置的。有关 {IDF_TARGET_NAME} 的 DWC_OTG 的重要主 * - 每个微帧仅支持 4 个周期性和 4 个非周期性事务 - ``OTG_NPERIO_TX_QUEUE_DEPTH = 4``、``OTG_PERIO_TX_QUEUE_DEPTH = 4`` -.. only:: esp32s2 or esp32s3 +.. only:: esp32s2 or esp32s3 or esp32h4 .. list-table:: {IDF_TARGET_NAME} 的 DWC_OTG 配置 :widths: 70 30 From 666098804ac6d74dc10671ee425d528c56bc2e67 Mon Sep 17 00:00:00 2001 From: armando Date: Mon, 27 Oct 2025 11:01:35 +0800 Subject: [PATCH 035/106] change(isp): make wbg standalone --- components/esp_driver_isp/CMakeLists.txt | 4 + .../esp_driver_isp/include/driver/isp.h | 1 + .../esp_driver_isp/include/driver/isp_awb.h | 12 --- .../esp_driver_isp/include/driver/isp_wbg.h | 81 +++++++++++++++++++ .../include/esp_private/isp_private.h | 1 + components/esp_driver_isp/src/isp_awb.c | 18 ----- components/esp_driver_isp/src/isp_wbg.c | 79 ++++++++++++++++++ components/hal/esp32p4/include/hal/isp_ll.h | 19 ++++- components/hal/include/hal/isp_types.h | 12 +++ .../esp32p4/include/soc/Kconfig.soc_caps.in | 4 + components/soc/esp32p4/include/soc/soc_caps.h | 1 + 11 files changed, 200 insertions(+), 32 deletions(-) create mode 100644 components/esp_driver_isp/include/driver/isp_wbg.h create mode 100644 components/esp_driver_isp/src/isp_wbg.c diff --git a/components/esp_driver_isp/CMakeLists.txt b/components/esp_driver_isp/CMakeLists.txt index 57728bf667f..f20d5847b73 100644 --- a/components/esp_driver_isp/CMakeLists.txt +++ b/components/esp_driver_isp/CMakeLists.txt @@ -42,6 +42,10 @@ if(CONFIG_SOC_ISP_LSC_SUPPORTED) list(APPEND srcs "src/isp_lsc.c") endif() +if(CONFIG_SOC_ISP_WBG_SUPPORTED) + list(APPEND srcs "src/isp_wbg.c") +endif() + if(NOT ${target} STREQUAL "linux") list(APPEND requires esp_mm) endif() diff --git a/components/esp_driver_isp/include/driver/isp.h b/components/esp_driver_isp/include/driver/isp.h index 73f6fbd4659..0bdd11d8db0 100644 --- a/components/esp_driver_isp/include/driver/isp.h +++ b/components/esp_driver_isp/include/driver/isp.h @@ -24,3 +24,4 @@ #include "driver/isp_hist.h" #include "driver/isp_lsc.h" #include "driver/isp_sharpen.h" +#include "driver/isp_wbg.h" diff --git a/components/esp_driver_isp/include/driver/isp_awb.h b/components/esp_driver_isp/include/driver/isp_awb.h index 10883e2c664..4cd508cd100 100644 --- a/components/esp_driver_isp/include/driver/isp_awb.h +++ b/components/esp_driver_isp/include/driver/isp_awb.h @@ -164,18 +164,6 @@ esp_err_t esp_isp_awb_controller_start_continuous_statistics(isp_awb_ctlr_t awb_ */ esp_err_t esp_isp_awb_controller_stop_continuous_statistics(isp_awb_ctlr_t awb_ctlr); -/** - * @brief Set AWB white balance gain - * - * @param[in] awb_ctlr AWB controller handle - * @param[in] gain AWB white balance gain - * @return - * - ESP_OK On success - * - ESP_ERR_INVALID_ARG Null pointer - * - ESP_ERR_INVALID_STATE Driver state is invalid. - */ -esp_err_t esp_isp_awb_controller_set_wb_gain(isp_awb_ctlr_t awb_ctlr, isp_awb_gain_t gain); - /** * @brief Event data of callbacks */ diff --git a/components/esp_driver_isp/include/driver/isp_wbg.h b/components/esp_driver_isp/include/driver/isp_wbg.h new file mode 100644 index 00000000000..b8add5cd50f --- /dev/null +++ b/components/esp_driver_isp/include/driver/isp_wbg.h @@ -0,0 +1,81 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "esp_err.h" +#include "driver/isp_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*--------------------------------------------------------------- + WBG (White Balance Gain) +---------------------------------------------------------------*/ +/** + * @brief ISP BLC configurations + */ +typedef struct { + //for future proof +} esp_isp_wbg_config_t; + +/** + * @brief ISP WBG configuration + * + * @note After calling this API, WBG doesn't take into effect until `esp_isp_wbg_enable` is called + * + * @param[in] isp_proc Processor handle + * @param[in] config WBG configurations + * + * @return + * - ESP_OK On success + * - ESP_ERR_INVALID_STATE Not allowed to be called under current state + * - ESP_ERR_INVALID_ARG If the combination of arguments is invalid + * - ESP_ERR_NOT_SUPPORTED Not supported + */ +esp_err_t esp_isp_wbg_configure(isp_proc_handle_t isp_proc, const esp_isp_wbg_config_t *config); + +/** + * @brief Enable ISP WBG function + * + * @param[in] isp_proc Processor handle + * + * @return + * - ESP_OK On success + * - ESP_ERR_INVALID_ARG If the combination of arguments is invalid. + * - ESP_ERR_INVALID_STATE Driver state is invalid. + */ +esp_err_t esp_isp_wbg_enable(isp_proc_handle_t isp_proc); + +/** + * @brief Set AWB white balance gain + * + * @param[in] isp_proc Processor handle + * @param[in] gain WBG white balance gain + * @return + * - ESP_OK On success + * - ESP_ERR_INVALID_ARG Null pointer + * - ESP_ERR_INVALID_STATE Driver state is invalid. + */ +esp_err_t esp_isp_wbg_set_wb_gain(isp_proc_handle_t isp_proc, isp_wbg_gain_t gain); + +/** + * @brief Disable ISP WBG function + * + * @param[in] isp_proc Processor handle + * + * @return + * - ESP_OK On success + * - ESP_ERR_INVALID_ARG If the combination of arguments is invalid. + * - ESP_ERR_INVALID_STATE Driver state is invalid. + */ +esp_err_t esp_isp_wbg_disable(isp_proc_handle_t isp_proc); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_driver_isp/include/esp_private/isp_private.h b/components/esp_driver_isp/include/esp_private/isp_private.h index 452d3c23237..98ccafe5a2b 100644 --- a/components/esp_driver_isp/include/esp_private/isp_private.h +++ b/components/esp_driver_isp/include/esp_private/isp_private.h @@ -78,6 +78,7 @@ typedef struct isp_processor_t { isp_fsm_t color_fsm; isp_fsm_t lsc_fsm; isp_fsm_t blc_fsm; + isp_fsm_t wbg_fsm; esp_isp_evt_cbs_t cbs; void *user_data; diff --git a/components/esp_driver_isp/src/isp_awb.c b/components/esp_driver_isp/src/isp_awb.c index e734985bcd4..28ab0393bb8 100644 --- a/components/esp_driver_isp/src/isp_awb.c +++ b/components/esp_driver_isp/src/isp_awb.c @@ -111,10 +111,6 @@ esp_err_t esp_isp_new_awb_controller(isp_proc_handle_t isp_proc, const esp_isp_a isp_ll_awb_enable(isp_proc->hal.hw, false); isp_ll_awb_set_clk_ctrl_mode(isp_proc->hal.hw, ISP_LL_PIPELINE_CLK_CTRL_AUTO); isp_ll_awb_enable_algorithm_mode(isp_proc->hal.hw, true); -#if !CONFIG_ESP32P4_SELECTS_REV_LESS_V3 - isp_ll_awb_set_wb_gain_clk_ctrl_mode(isp_proc->hal.hw, ISP_LL_PIPELINE_CLK_CTRL_AUTO); - isp_ll_awb_enable_wb_gain(isp_proc->hal.hw, true); -#endif ESP_GOTO_ON_ERROR(s_esp_isp_awb_config_hardware(isp_proc, awb_cfg), err2, TAG, "configure awb hardware failed"); *ret_hdl = awb_ctlr; @@ -139,9 +135,6 @@ esp_err_t esp_isp_del_awb_controller(isp_awb_ctlr_t awb_ctlr) s_isp_declaim_awb_controller(awb_ctlr); isp_ll_awb_enable_algorithm_mode(awb_ctlr->isp_proc->hal.hw, false); -#if !CONFIG_ESP32P4_SELECTS_REV_LESS_V3 - isp_ll_awb_enable_wb_gain(awb_ctlr->isp_proc->hal.hw, false); -#endif s_isp_awb_free_controller(awb_ctlr); return ESP_OK; @@ -228,17 +221,6 @@ esp_err_t esp_isp_awb_controller_stop_continuous_statistics(isp_awb_ctlr_t awb_c return ESP_OK; } -#if !CONFIG_ESP32P4_SELECTS_REV_LESS_V3 -esp_err_t esp_isp_awb_controller_set_wb_gain(isp_awb_ctlr_t awb_ctlr, isp_awb_gain_t gain) -{ - ESP_RETURN_ON_FALSE(awb_ctlr, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); - ESP_RETURN_ON_FALSE(atomic_load(&awb_ctlr->fsm) != ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "controller not in init state"); - isp_ll_awb_set_wb_gain(awb_ctlr->isp_proc->hal.hw, gain); - - return ESP_OK; -} -#endif //#if !CONFIG_ESP32P4_SELECTS_REV_LESS_V3 - /*--------------------------------------------------------------- INTR ---------------------------------------------------------------*/ diff --git a/components/esp_driver_isp/src/isp_wbg.c b/components/esp_driver_isp/src/isp_wbg.c new file mode 100644 index 00000000000..a80a59be4ad --- /dev/null +++ b/components/esp_driver_isp/src/isp_wbg.c @@ -0,0 +1,79 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +#include +#include "sdkconfig.h" +#include "esp_log.h" +#include "esp_check.h" +#include "freertos/FreeRTOS.h" +#include "driver/isp_core.h" +#include "driver/isp_wbg.h" +#include "esp_private/isp_private.h" +#include "hal/efuse_hal.h" +#include "soc/chip_revision.h" + +/*--------------------------------------------------------------- + WBG +---------------------------------------------------------------*/ + +static const char *TAG = "ISP_WBG"; + +esp_err_t esp_isp_wbg_configure(isp_proc_handle_t isp_proc, const esp_isp_wbg_config_t *config) +{ +#if CONFIG_IDF_TARGET_ESP32P4 + unsigned chip_version = efuse_hal_chip_revision(); + if (!ESP_CHIP_REV_ABOVE(chip_version, 300)) { + ESP_RETURN_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, TAG, "WBG is not supported on ESP32P4 chips prior than v3.0"); + } +#endif + + ESP_RETURN_ON_FALSE(isp_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); + ESP_RETURN_ON_FALSE(isp_proc->wbg_fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "wbg is enabled already"); + + // Configure clock control mode + isp_ll_awb_set_wb_gain_clk_ctrl_mode(isp_proc->hal.hw, ISP_LL_PIPELINE_CLK_CTRL_AUTO); + + return ESP_OK; +} + +esp_err_t esp_isp_wbg_enable(isp_proc_handle_t isp_proc) +{ + ESP_RETURN_ON_FALSE(isp_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); + ESP_RETURN_ON_FALSE(isp_proc->wbg_fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "wbg is enabled already"); + + // Enable WBG module + isp_ll_awb_enable_wb_gain(isp_proc->hal.hw, true); + isp_proc->wbg_fsm = ISP_FSM_ENABLE; + + ESP_LOGD(TAG, "WBG enabled"); + return ESP_OK; +} + +esp_err_t esp_isp_wbg_set_wb_gain(isp_proc_handle_t isp_proc, isp_wbg_gain_t gain) +{ + ESP_RETURN_ON_FALSE(isp_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); + ESP_RETURN_ON_FALSE(isp_proc->wbg_fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "wbg isn't enabled yet"); + + // Set WBG gain + isp_ll_awb_set_wb_gain(isp_proc->hal.hw, gain); + + return ESP_OK; +} + +esp_err_t esp_isp_wbg_disable(isp_proc_handle_t isp_proc) +{ + ESP_RETURN_ON_FALSE(isp_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); + ESP_RETURN_ON_FALSE(isp_proc->wbg_fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "wbg isn't enabled yet"); + + // Disable WBG module + isp_ll_awb_enable_wb_gain(isp_proc->hal.hw, false); + isp_proc->wbg_fsm = ISP_FSM_INIT; + + ESP_LOGD(TAG, "WBG disabled"); + return ESP_OK; +} diff --git a/components/hal/esp32p4/include/hal/isp_ll.h b/components/hal/esp32p4/include/hal/isp_ll.h index 288cb3ab903..2fec895ab4b 100644 --- a/components/hal/esp32p4/include/hal/isp_ll.h +++ b/components/hal/esp32p4/include/hal/isp_ll.h @@ -1742,14 +1742,29 @@ static inline void isp_ll_awb_set_wb_gain_clk_ctrl_mode(isp_dev_t *hw, isp_ll_pi * @brief Set AWB white balance gain * * @param[in] hw Hardware instance address - * @param[in] gain AWB white balance gain + * @param[in] gain WBG white balance gain */ -static inline void isp_ll_awb_set_wb_gain(isp_dev_t *hw, isp_awb_gain_t gain) +static inline void isp_ll_awb_set_wb_gain(isp_dev_t *hw, isp_wbg_gain_t gain) { hw->wbg_coef_r.wbg_r = gain.gain_r; hw->wbg_coef_g.wbg_g = gain.gain_g; hw->wbg_coef_b.wbg_b = gain.gain_b; } +#else +static inline void isp_ll_awb_enable_wb_gain(isp_dev_t *hw, bool enable) +{ + //for compatibility +} + +static inline void isp_ll_awb_set_wb_gain_clk_ctrl_mode(isp_dev_t *hw, isp_ll_pipeline_clk_ctrl_t mode) +{ + //for compatibility +} + +static inline void isp_ll_awb_set_wb_gain(isp_dev_t *hw, isp_wbg_gain_t gain) +{ + //for compatibility +} #endif //#if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300 /*--------------------------------------------------------------- diff --git a/components/hal/include/hal/isp_types.h b/components/hal/include/hal/isp_types.h index 29ecffe1b0f..dc72142c192 100644 --- a/components/hal/include/hal/isp_types.h +++ b/components/hal/include/hal/isp_types.h @@ -435,6 +435,18 @@ typedef union { uint32_t val; ///< 32-bit gradient ratio value } isp_lsc_gain_t; +/*--------------------------------------------------------------- + WBG (White Balance Gain) +---------------------------------------------------------------*/ +/** + * @brief ISP White Balance Gain + */ +typedef struct { + uint32_t gain_r; ///< White balance gain for R channel + uint32_t gain_g; ///< White balance gain for G channel + uint32_t gain_b; ///< White balance gain for B channel +} isp_wbg_gain_t; + #ifdef __cplusplus } #endif diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index ccb8d58c873..75f7ac6453e 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -919,6 +919,10 @@ config SOC_ISP_SHARPEN_SUPPORTED bool default y +config SOC_ISP_WBG_SUPPORTED + bool + default y + config SOC_ISP_SHARE_CSI_BRG bool default y diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index 2a64a7ea718..5de9bdb1494 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -353,6 +353,7 @@ #define SOC_ISP_DVP_SUPPORTED 1 #define SOC_ISP_LSC_SUPPORTED 1 #define SOC_ISP_SHARPEN_SUPPORTED 1 +#define SOC_ISP_WBG_SUPPORTED 1 #define SOC_ISP_SHARE_CSI_BRG 1 #define SOC_ISP_NUMS 1U From 06b35ab86be8fbc150517f30c8ba2f5dc1b6f0a4 Mon Sep 17 00:00:00 2001 From: armando Date: Mon, 27 Oct 2025 15:12:30 +0800 Subject: [PATCH 036/106] fix(isp): use atomic fsm check --- .../include/esp_private/isp_private.h | 31 +++++++++++++------ components/esp_driver_isp/src/isp_bf.c | 10 +++--- components/esp_driver_isp/src/isp_blc.c | 10 +++--- components/esp_driver_isp/src/isp_ccm.c | 4 +++ components/esp_driver_isp/src/isp_color.c | 10 +++--- components/esp_driver_isp/src/isp_core.c | 23 +++++++++----- components/esp_driver_isp/src/isp_demosaic.c | 10 +++--- components/esp_driver_isp/src/isp_gamma.c | 4 +++ components/esp_driver_isp/src/isp_lsc.c | 10 +++--- components/esp_driver_isp/src/isp_sharpen.c | 10 +++--- components/esp_driver_isp/src/isp_wbg.c | 11 +++---- 11 files changed, 80 insertions(+), 53 deletions(-) diff --git a/components/esp_driver_isp/include/esp_private/isp_private.h b/components/esp_driver_isp/include/esp_private/isp_private.h index 98ccafe5a2b..e94fe16e64d 100644 --- a/components/esp_driver_isp/include/esp_private/isp_private.h +++ b/components/esp_driver_isp/include/esp_private/isp_private.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -9,6 +9,7 @@ #include #include #include +#include #include "sdkconfig.h" #include "esp_attr.h" #include "esp_log.h" @@ -27,8 +28,12 @@ #include "soc/isp_periph.h" #endif +// Helper macros for atomic operations to ensure Clang compatibility #ifdef __cplusplus -extern "C" { +#include +#define ISP_ATOMIC_TYPE(T) std::atomic +#else +#define ISP_ATOMIC_TYPE(T) _Atomic T #endif #if CONFIG_ISP_ISR_IRAM_SAFE || CONFIG_ISP_CTRL_FUNC_IN_IRAM @@ -39,6 +44,10 @@ extern "C" { #define ISP_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT #endif +#ifdef __cplusplus +extern "C" { +#endif + typedef enum { ISP_FSM_INIT, // Controller is initialized, but not enabled ISP_FSM_ENABLE, // Controller is enabled, but is not running @@ -59,7 +68,7 @@ typedef struct isp_processor_t { int csi_brg_id; void *csi_brg_hw; #endif - isp_fsm_t isp_fsm; + ISP_ATOMIC_TYPE(isp_fsm_t) isp_fsm; portMUX_TYPE spinlock; color_space_pixel_format_t in_color_format; color_space_pixel_format_t out_color_format; @@ -72,13 +81,15 @@ typedef struct isp_processor_t { isp_awb_ctlr_t awb_ctlr; isp_ae_ctlr_t ae_ctlr; isp_hist_ctlr_t hist_ctlr; - isp_fsm_t bf_fsm; - isp_fsm_t demosaic_fsm; - isp_fsm_t sharpen_fsm; - isp_fsm_t color_fsm; - isp_fsm_t lsc_fsm; - isp_fsm_t blc_fsm; - isp_fsm_t wbg_fsm; + ISP_ATOMIC_TYPE(isp_fsm_t) bf_fsm; + ISP_ATOMIC_TYPE(isp_fsm_t) blc_fsm; + ISP_ATOMIC_TYPE(isp_fsm_t) ccm_fsm; + ISP_ATOMIC_TYPE(isp_fsm_t) color_fsm; + ISP_ATOMIC_TYPE(isp_fsm_t) demosaic_fsm; + ISP_ATOMIC_TYPE(isp_fsm_t) gamma_fsm; + ISP_ATOMIC_TYPE(isp_fsm_t) lsc_fsm; + ISP_ATOMIC_TYPE(isp_fsm_t) sharpen_fsm; + ISP_ATOMIC_TYPE(isp_fsm_t) wbg_fsm; esp_isp_evt_cbs_t cbs; void *user_data; diff --git a/components/esp_driver_isp/src/isp_bf.c b/components/esp_driver_isp/src/isp_bf.c index f6f0befc2f0..066076624f0 100644 --- a/components/esp_driver_isp/src/isp_bf.c +++ b/components/esp_driver_isp/src/isp_bf.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -49,10 +49,10 @@ esp_err_t esp_isp_bf_configure(isp_proc_handle_t proc, const esp_isp_bf_config_t esp_err_t esp_isp_bf_enable(isp_proc_handle_t proc) { ESP_RETURN_ON_FALSE(proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); - ESP_RETURN_ON_FALSE(proc->bf_fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "bf is enabled already"); + isp_fsm_t expected_fsm = ISP_FSM_INIT; + ESP_RETURN_ON_FALSE(atomic_compare_exchange_strong(&proc->bf_fsm, &expected_fsm, ISP_FSM_ENABLE), ESP_ERR_INVALID_STATE, TAG, "bf is enabled already"); isp_ll_bf_enable(proc->hal.hw, true); - proc->bf_fsm = ISP_FSM_ENABLE; return ESP_OK; } @@ -60,10 +60,10 @@ esp_err_t esp_isp_bf_enable(isp_proc_handle_t proc) esp_err_t esp_isp_bf_disable(isp_proc_handle_t proc) { ESP_RETURN_ON_FALSE(proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); - ESP_RETURN_ON_FALSE(proc->bf_fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "bf isn't enabled yet"); + isp_fsm_t expected_fsm = ISP_FSM_ENABLE; + ESP_RETURN_ON_FALSE(atomic_compare_exchange_strong(&proc->bf_fsm, &expected_fsm, ISP_FSM_INIT), ESP_ERR_INVALID_STATE, TAG, "bf isn't enabled yet"); isp_ll_bf_enable(proc->hal.hw, false); - proc->bf_fsm = ISP_FSM_INIT; return ESP_OK; } diff --git a/components/esp_driver_isp/src/isp_blc.c b/components/esp_driver_isp/src/isp_blc.c index bad515da5ef..c808e66d04d 100644 --- a/components/esp_driver_isp/src/isp_blc.c +++ b/components/esp_driver_isp/src/isp_blc.c @@ -64,11 +64,11 @@ esp_err_t esp_isp_blc_configure(isp_proc_handle_t isp_proc, const esp_isp_blc_co esp_err_t esp_isp_blc_enable(isp_proc_handle_t isp_proc) { ESP_RETURN_ON_FALSE(isp_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); - ESP_RETURN_ON_FALSE(isp_proc->blc_fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "blc is enabled already"); + isp_fsm_t expected_fsm = ISP_FSM_INIT; + ESP_RETURN_ON_FALSE(atomic_compare_exchange_strong(&isp_proc->blc_fsm, &expected_fsm, ISP_FSM_ENABLE), ESP_ERR_INVALID_STATE, TAG, "blc is enabled already"); // Enable BLC module isp_ll_blc_enable(isp_proc->hal.hw, true); - isp_proc->blc_fsm = ISP_FSM_ENABLE; ESP_LOGD(TAG, "BLC enabled"); return ESP_OK; @@ -77,7 +77,7 @@ esp_err_t esp_isp_blc_enable(isp_proc_handle_t isp_proc) esp_err_t esp_isp_blc_set_correction_offset(isp_proc_handle_t isp_proc, esp_isp_blc_offset_t *offset) { ESP_RETURN_ON_FALSE(isp_proc && offset, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); - ESP_RETURN_ON_FALSE(isp_proc->blc_fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "blc isn't enabled yet"); + ESP_RETURN_ON_FALSE(atomic_load(&isp_proc->blc_fsm) == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "blc isn't enabled yet"); // Set correction offset for each channel isp_ll_blc_set_correction_offset(isp_proc->hal.hw, offset->top_left_chan_offset, offset->top_right_chan_offset, offset->bottom_left_chan_offset, offset->bottom_right_chan_offset); @@ -92,11 +92,11 @@ esp_err_t esp_isp_blc_set_correction_offset(isp_proc_handle_t isp_proc, esp_isp_ esp_err_t esp_isp_blc_disable(isp_proc_handle_t isp_proc) { ESP_RETURN_ON_FALSE(isp_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); - ESP_RETURN_ON_FALSE(isp_proc->blc_fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "blc isn't enabled yet"); + isp_fsm_t expected_fsm = ISP_FSM_ENABLE; + ESP_RETURN_ON_FALSE(atomic_compare_exchange_strong(&isp_proc->blc_fsm, &expected_fsm, ISP_FSM_INIT), ESP_ERR_INVALID_STATE, TAG, "blc isn't enabled yet"); // Disable BLC module isp_ll_blc_enable(isp_proc->hal.hw, false); - isp_proc->blc_fsm = ISP_FSM_INIT; ESP_LOGD(TAG, "BLC disabled"); return ESP_OK; diff --git a/components/esp_driver_isp/src/isp_ccm.c b/components/esp_driver_isp/src/isp_ccm.c index e47af370250..b8b28bad44b 100644 --- a/components/esp_driver_isp/src/isp_ccm.c +++ b/components/esp_driver_isp/src/isp_ccm.c @@ -45,6 +45,8 @@ esp_err_t esp_isp_ccm_configure(isp_proc_handle_t proc, const esp_isp_ccm_config esp_err_t esp_isp_ccm_enable(isp_proc_handle_t proc) { ESP_RETURN_ON_FALSE(proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); + isp_fsm_t expected_fsm = ISP_FSM_INIT; + ESP_RETURN_ON_FALSE(atomic_compare_exchange_strong(&proc->ccm_fsm, &expected_fsm, ISP_FSM_ENABLE), ESP_ERR_INVALID_STATE, TAG, "ccm is enabled already"); portENTER_CRITICAL(&proc->spinlock); isp_ll_ccm_enable(proc->hal.hw, true); @@ -56,6 +58,8 @@ esp_err_t esp_isp_ccm_enable(isp_proc_handle_t proc) esp_err_t esp_isp_ccm_disable(isp_proc_handle_t proc) { ESP_RETURN_ON_FALSE(proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); + isp_fsm_t expected_fsm = ISP_FSM_ENABLE; + ESP_RETURN_ON_FALSE(atomic_compare_exchange_strong(&proc->ccm_fsm, &expected_fsm, ISP_FSM_INIT), ESP_ERR_INVALID_STATE, TAG, "ccm isn't enabled yet"); portENTER_CRITICAL(&proc->spinlock); isp_ll_ccm_enable(proc->hal.hw, false); diff --git a/components/esp_driver_isp/src/isp_color.c b/components/esp_driver_isp/src/isp_color.c index cfd8227c89e..d10504e3f2f 100644 --- a/components/esp_driver_isp/src/isp_color.c +++ b/components/esp_driver_isp/src/isp_color.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -49,10 +49,10 @@ esp_err_t esp_isp_color_configure(isp_proc_handle_t proc, const esp_isp_color_co esp_err_t esp_isp_color_enable(isp_proc_handle_t proc) { ESP_RETURN_ON_FALSE(proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); - ESP_RETURN_ON_FALSE(proc->color_fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "color is enabled already"); + isp_fsm_t expected_fsm = ISP_FSM_INIT; + ESP_RETURN_ON_FALSE(atomic_compare_exchange_strong(&proc->color_fsm, &expected_fsm, ISP_FSM_ENABLE), ESP_ERR_INVALID_STATE, TAG, "color is enabled already"); isp_ll_color_enable(proc->hal.hw, true); - proc->color_fsm = ISP_FSM_ENABLE; return ESP_OK; } @@ -60,10 +60,10 @@ esp_err_t esp_isp_color_enable(isp_proc_handle_t proc) esp_err_t esp_isp_color_disable(isp_proc_handle_t proc) { ESP_RETURN_ON_FALSE(proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); - ESP_RETURN_ON_FALSE(proc->color_fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "color isn't enabled yet"); + isp_fsm_t expected_fsm = ISP_FSM_ENABLE; + ESP_RETURN_ON_FALSE(atomic_compare_exchange_strong(&proc->color_fsm, &expected_fsm, ISP_FSM_INIT), ESP_ERR_INVALID_STATE, TAG, "color isn't enabled yet"); isp_ll_color_enable(proc->hal.hw, false); - proc->color_fsm = ISP_FSM_INIT; return ESP_OK; } diff --git a/components/esp_driver_isp/src/isp_core.c b/components/esp_driver_isp/src/isp_core.c index d6dd2bbeae1..b1d1b45e147 100644 --- a/components/esp_driver_isp/src/isp_core.c +++ b/components/esp_driver_isp/src/isp_core.c @@ -119,7 +119,16 @@ esp_err_t esp_isp_new_processor(const esp_isp_processor_cfg_t *proc_config, isp_ isp_ll_set_clock_div(proc->hal.hw, &clk_div); } proc->clk_src = clk_src; - proc->isp_fsm = ISP_FSM_INIT; + atomic_init(&proc->isp_fsm, ISP_FSM_INIT); + atomic_init(&proc->bf_fsm, ISP_FSM_INIT); + atomic_init(&proc->blc_fsm, ISP_FSM_INIT); + atomic_init(&proc->ccm_fsm, ISP_FSM_INIT); + atomic_init(&proc->color_fsm, ISP_FSM_INIT); + atomic_init(&proc->demosaic_fsm, ISP_FSM_INIT); + atomic_init(&proc->gamma_fsm, ISP_FSM_INIT); + atomic_init(&proc->lsc_fsm, ISP_FSM_INIT); + atomic_init(&proc->sharpen_fsm, ISP_FSM_INIT); + atomic_init(&proc->wbg_fsm, ISP_FSM_INIT); proc->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED; //Input & Output color format @@ -189,7 +198,7 @@ err: esp_err_t esp_isp_del_processor(isp_proc_handle_t proc) { ESP_RETURN_ON_FALSE(proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); - ESP_RETURN_ON_FALSE(proc->isp_fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "processor isn't in init state"); + ESP_RETURN_ON_FALSE(atomic_load(&proc->isp_fsm) == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "processor isn't in init state"); //declaim first, then do free ESP_RETURN_ON_ERROR(s_isp_declaim_processor(proc), TAG, "declaim processor fail"); @@ -205,7 +214,7 @@ esp_err_t esp_isp_del_processor(isp_proc_handle_t proc) esp_err_t esp_isp_register_event_callbacks(isp_proc_handle_t proc, const esp_isp_evt_cbs_t *cbs, void *user_data) { ESP_RETURN_ON_FALSE(proc && cbs, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); - ESP_RETURN_ON_FALSE(proc->isp_fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "processor isn't in the init state"); + ESP_RETURN_ON_FALSE(atomic_load(&proc->isp_fsm) == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "processor isn't in the init state"); #if CONFIG_ISP_ISR_IRAM_SAFE if (cbs->on_sharpen_frame_done) { @@ -230,11 +239,11 @@ esp_err_t esp_isp_register_event_callbacks(isp_proc_handle_t proc, const esp_isp esp_err_t esp_isp_enable(isp_proc_handle_t proc) { ESP_RETURN_ON_FALSE(proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); - ESP_RETURN_ON_FALSE(proc->isp_fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "processor isn't in init state"); + isp_fsm_t expected_fsm = ISP_FSM_INIT; + ESP_RETURN_ON_FALSE(atomic_compare_exchange_strong(&proc->isp_fsm, &expected_fsm, ISP_FSM_ENABLE), ESP_ERR_INVALID_STATE, TAG, "processor isn't in init state"); ESP_RETURN_ON_FALSE(proc->bypass_isp == false, ESP_ERR_INVALID_STATE, TAG, "processor is configured to be bypassed"); isp_ll_enable(proc->hal.hw, true); - proc->isp_fsm = ISP_FSM_ENABLE; return ESP_OK; } @@ -242,10 +251,10 @@ esp_err_t esp_isp_enable(isp_proc_handle_t proc) esp_err_t esp_isp_disable(isp_proc_handle_t proc) { ESP_RETURN_ON_FALSE(proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); - ESP_RETURN_ON_FALSE(proc->isp_fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "processor isn't in enable state"); + isp_fsm_t expected_fsm = ISP_FSM_ENABLE; + ESP_RETURN_ON_FALSE(atomic_compare_exchange_strong(&proc->isp_fsm, &expected_fsm, ISP_FSM_INIT), ESP_ERR_INVALID_STATE, TAG, "processor isn't in enable state"); isp_ll_enable(proc->hal.hw, false); - proc->isp_fsm = ISP_FSM_INIT; return ESP_OK; } diff --git a/components/esp_driver_isp/src/isp_demosaic.c b/components/esp_driver_isp/src/isp_demosaic.c index 92a224caae0..37f299bd71b 100644 --- a/components/esp_driver_isp/src/isp_demosaic.c +++ b/components/esp_driver_isp/src/isp_demosaic.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -46,10 +46,10 @@ esp_err_t esp_isp_demosaic_configure(isp_proc_handle_t proc, const esp_isp_demos esp_err_t esp_isp_demosaic_enable(isp_proc_handle_t proc) { ESP_RETURN_ON_FALSE(proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); - ESP_RETURN_ON_FALSE(proc->demosaic_fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "demosaic is enabled already"); + isp_fsm_t expected_fsm = ISP_FSM_INIT; + ESP_RETURN_ON_FALSE(atomic_compare_exchange_strong(&proc->demosaic_fsm, &expected_fsm, ISP_FSM_ENABLE), ESP_ERR_INVALID_STATE, TAG, "demosaic is enabled already"); isp_ll_demosaic_enable(proc->hal.hw, true); - proc->demosaic_fsm = ISP_FSM_ENABLE; return ESP_OK; } @@ -57,13 +57,13 @@ esp_err_t esp_isp_demosaic_enable(isp_proc_handle_t proc) esp_err_t esp_isp_demosaic_disable(isp_proc_handle_t proc) { ESP_RETURN_ON_FALSE(proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); - ESP_RETURN_ON_FALSE(proc->demosaic_fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "demosaic isn't enabled yet"); + isp_fsm_t expected_fsm = ISP_FSM_ENABLE; + ESP_RETURN_ON_FALSE(atomic_compare_exchange_strong(&proc->demosaic_fsm, &expected_fsm, ISP_FSM_INIT), ESP_ERR_INVALID_STATE, TAG, "demosaic isn't enabled yet"); if (proc->out_color_format.color_space == (uint32_t)COLOR_SPACE_RAW) { // for other out_color_format, demosaic module is needed for rgb interpolation algorithm isp_ll_demosaic_enable(proc->hal.hw, false); } - proc->demosaic_fsm = ISP_FSM_INIT; return ESP_OK; } diff --git a/components/esp_driver_isp/src/isp_gamma.c b/components/esp_driver_isp/src/isp_gamma.c index c8d323f4169..52b77ba9d60 100644 --- a/components/esp_driver_isp/src/isp_gamma.c +++ b/components/esp_driver_isp/src/isp_gamma.c @@ -58,6 +58,8 @@ esp_err_t esp_isp_gamma_configure(isp_proc_handle_t proc, color_component_t comp esp_err_t esp_isp_gamma_enable(isp_proc_handle_t proc) { ESP_RETURN_ON_FALSE(proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); + isp_fsm_t expected_fsm = ISP_FSM_INIT; + ESP_RETURN_ON_FALSE(atomic_compare_exchange_strong(&proc->gamma_fsm, &expected_fsm, ISP_FSM_ENABLE), ESP_ERR_INVALID_STATE, TAG, "gamma is enabled already"); portENTER_CRITICAL(&proc->spinlock); isp_ll_gamma_enable(proc->hal.hw, true); @@ -69,6 +71,8 @@ esp_err_t esp_isp_gamma_enable(isp_proc_handle_t proc) esp_err_t esp_isp_gamma_disable(isp_proc_handle_t proc) { ESP_RETURN_ON_FALSE(proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); + isp_fsm_t expected_fsm = ISP_FSM_ENABLE; + ESP_RETURN_ON_FALSE(atomic_compare_exchange_strong(&proc->gamma_fsm, &expected_fsm, ISP_FSM_INIT), ESP_ERR_INVALID_STATE, TAG, "gamma is disabled already"); portENTER_CRITICAL(&proc->spinlock); isp_ll_gamma_enable(proc->hal.hw, false); diff --git a/components/esp_driver_isp/src/isp_lsc.c b/components/esp_driver_isp/src/isp_lsc.c index 758d780758d..8ddf94126d1 100644 --- a/components/esp_driver_isp/src/isp_lsc.c +++ b/components/esp_driver_isp/src/isp_lsc.c @@ -28,7 +28,7 @@ static const char *TAG = "ISP_LSC"; esp_err_t esp_isp_lsc_allocate_gain_array(isp_proc_handle_t isp_proc, esp_isp_lsc_gain_array_t *gain_array, size_t *out_array_size_per_channel) { ESP_RETURN_ON_FALSE(isp_proc && gain_array && out_array_size_per_channel, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); - ESP_RETURN_ON_FALSE(isp_proc->lsc_fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "lsc is enabled already"); + ESP_RETURN_ON_FALSE(atomic_load(&isp_proc->lsc_fsm) == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "lsc is enabled already"); int num_grids_x_max = ISP_LSC_GET_GRIDS(ISP_LL_HSIZE_MAX); int num_grids_y_max = ISP_LSC_GET_GRIDS(ISP_LL_VSIZE_MAX); @@ -89,10 +89,10 @@ esp_err_t esp_isp_lsc_configure(isp_proc_handle_t isp_proc, const esp_isp_lsc_co esp_err_t esp_isp_lsc_enable(isp_proc_handle_t isp_proc) { ESP_RETURN_ON_FALSE(isp_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); - ESP_RETURN_ON_FALSE(isp_proc->lsc_fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "lsc is enabled already"); + isp_fsm_t expected_fsm = ISP_FSM_INIT; + ESP_RETURN_ON_FALSE(atomic_compare_exchange_strong(&isp_proc->lsc_fsm, &expected_fsm, ISP_FSM_ENABLE), ESP_ERR_INVALID_STATE, TAG, "lsc is enabled already"); isp_ll_lsc_enable(isp_proc->hal.hw, true); - isp_proc->lsc_fsm = ISP_FSM_ENABLE; return ESP_OK; } @@ -100,10 +100,10 @@ esp_err_t esp_isp_lsc_enable(isp_proc_handle_t isp_proc) esp_err_t esp_isp_lsc_disable(isp_proc_handle_t isp_proc) { ESP_RETURN_ON_FALSE(isp_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); - ESP_RETURN_ON_FALSE(isp_proc->lsc_fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "lsc isn't enabled yet"); + isp_fsm_t expected_fsm = ISP_FSM_ENABLE; + ESP_RETURN_ON_FALSE(atomic_compare_exchange_strong(&isp_proc->lsc_fsm, &expected_fsm, ISP_FSM_INIT), ESP_ERR_INVALID_STATE, TAG, "lsc isn't enabled yet"); isp_ll_lsc_enable(isp_proc->hal.hw, false); - isp_proc->lsc_fsm = ISP_FSM_INIT; return ESP_OK; } diff --git a/components/esp_driver_isp/src/isp_sharpen.c b/components/esp_driver_isp/src/isp_sharpen.c index 750a5adb13d..b8ac88abeb9 100644 --- a/components/esp_driver_isp/src/isp_sharpen.c +++ b/components/esp_driver_isp/src/isp_sharpen.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -51,11 +51,11 @@ esp_err_t esp_isp_sharpen_configure(isp_proc_handle_t proc, const esp_isp_sharpe esp_err_t esp_isp_sharpen_enable(isp_proc_handle_t proc) { ESP_RETURN_ON_FALSE(proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); - ESP_RETURN_ON_FALSE(proc->sharpen_fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "sharpen is enabled already"); + isp_fsm_t expected_fsm = ISP_FSM_INIT; + ESP_RETURN_ON_FALSE(atomic_compare_exchange_strong(&proc->sharpen_fsm, &expected_fsm, ISP_FSM_ENABLE), ESP_ERR_INVALID_STATE, TAG, "sharpen is enabled already"); isp_ll_enable_intr(proc->hal.hw, ISP_LL_EVENT_SHARP_FRAME, true); isp_ll_sharp_enable(proc->hal.hw, true); - proc->sharpen_fsm = ISP_FSM_ENABLE; return ESP_OK; } @@ -63,11 +63,11 @@ esp_err_t esp_isp_sharpen_enable(isp_proc_handle_t proc) esp_err_t esp_isp_sharpen_disable(isp_proc_handle_t proc) { ESP_RETURN_ON_FALSE(proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); - ESP_RETURN_ON_FALSE(proc->sharpen_fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "sharpen isn't enabled yet"); + isp_fsm_t expected_fsm = ISP_FSM_ENABLE; + ESP_RETURN_ON_FALSE(atomic_compare_exchange_strong(&proc->sharpen_fsm, &expected_fsm, ISP_FSM_INIT), ESP_ERR_INVALID_STATE, TAG, "sharpen isn't enabled yet"); isp_ll_sharp_enable(proc->hal.hw, false); isp_ll_enable_intr(proc->hal.hw, ISP_LL_EVENT_SHARP_FRAME, false); - proc->sharpen_fsm = ISP_FSM_INIT; return ESP_OK; } diff --git a/components/esp_driver_isp/src/isp_wbg.c b/components/esp_driver_isp/src/isp_wbg.c index a80a59be4ad..e03d0eda52c 100644 --- a/components/esp_driver_isp/src/isp_wbg.c +++ b/components/esp_driver_isp/src/isp_wbg.c @@ -33,7 +33,6 @@ esp_err_t esp_isp_wbg_configure(isp_proc_handle_t isp_proc, const esp_isp_wbg_co #endif ESP_RETURN_ON_FALSE(isp_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); - ESP_RETURN_ON_FALSE(isp_proc->wbg_fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "wbg is enabled already"); // Configure clock control mode isp_ll_awb_set_wb_gain_clk_ctrl_mode(isp_proc->hal.hw, ISP_LL_PIPELINE_CLK_CTRL_AUTO); @@ -44,11 +43,11 @@ esp_err_t esp_isp_wbg_configure(isp_proc_handle_t isp_proc, const esp_isp_wbg_co esp_err_t esp_isp_wbg_enable(isp_proc_handle_t isp_proc) { ESP_RETURN_ON_FALSE(isp_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); - ESP_RETURN_ON_FALSE(isp_proc->wbg_fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "wbg is enabled already"); + isp_fsm_t expected_fsm = ISP_FSM_INIT; + ESP_RETURN_ON_FALSE(atomic_compare_exchange_strong(&isp_proc->wbg_fsm, &expected_fsm, ISP_FSM_ENABLE), ESP_ERR_INVALID_STATE, TAG, "wbg is enabled already"); // Enable WBG module isp_ll_awb_enable_wb_gain(isp_proc->hal.hw, true); - isp_proc->wbg_fsm = ISP_FSM_ENABLE; ESP_LOGD(TAG, "WBG enabled"); return ESP_OK; @@ -57,7 +56,7 @@ esp_err_t esp_isp_wbg_enable(isp_proc_handle_t isp_proc) esp_err_t esp_isp_wbg_set_wb_gain(isp_proc_handle_t isp_proc, isp_wbg_gain_t gain) { ESP_RETURN_ON_FALSE(isp_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); - ESP_RETURN_ON_FALSE(isp_proc->wbg_fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "wbg isn't enabled yet"); + ESP_RETURN_ON_FALSE(atomic_load(&isp_proc->wbg_fsm) == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "wbg isn't enabled yet"); // Set WBG gain isp_ll_awb_set_wb_gain(isp_proc->hal.hw, gain); @@ -68,11 +67,11 @@ esp_err_t esp_isp_wbg_set_wb_gain(isp_proc_handle_t isp_proc, isp_wbg_gain_t gai esp_err_t esp_isp_wbg_disable(isp_proc_handle_t isp_proc) { ESP_RETURN_ON_FALSE(isp_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); - ESP_RETURN_ON_FALSE(isp_proc->wbg_fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "wbg isn't enabled yet"); + isp_fsm_t expected_fsm = ISP_FSM_ENABLE; + ESP_RETURN_ON_FALSE(atomic_compare_exchange_strong(&isp_proc->wbg_fsm, &expected_fsm, ISP_FSM_INIT), ESP_ERR_INVALID_STATE, TAG, "wbg isn't enabled yet"); // Disable WBG module isp_ll_awb_enable_wb_gain(isp_proc->hal.hw, false); - isp_proc->wbg_fsm = ISP_FSM_INIT; ESP_LOGD(TAG, "WBG disabled"); return ESP_OK; From f9f0be690e0bb74ee2671c444370ae933d2ee110 Mon Sep 17 00:00:00 2001 From: zhuanghang Date: Mon, 10 Nov 2025 15:28:45 +0800 Subject: [PATCH 037/106] fix(802.15.4): fix line save in 154 debug --- components/ieee802154/driver/esp_ieee802154_debug.c | 8 ++++---- .../ieee802154/private_include/esp_ieee802154_util.h | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/components/ieee802154/driver/esp_ieee802154_debug.c b/components/ieee802154/driver/esp_ieee802154_debug.c index 21c315c4b9b..8aa30f26cc3 100644 --- a/components/ieee802154/driver/esp_ieee802154_debug.c +++ b/components/ieee802154/driver/esp_ieee802154_debug.c @@ -210,8 +210,8 @@ void ieee802154_record_print(void) #if CONFIG_IEEE802154_RECORD_STATE ESP_EARLY_LOGW(IEEE802154_TAG, "Print the record state, current state index: %d", g_ieee802154_probe.state_index); for (uint8_t i = 0; i < IEEE802154_ASSERT_RECORD_STATE_SIZE; i++) { - ESP_EARLY_LOGW(IEEE802154_TAG, "index %2d: line:%5s, state:%10s, timestamp: %lld", - i, g_ieee802154_probe.state[i].line_str, + ESP_EARLY_LOGW(IEEE802154_TAG, "index %2d: line:%5lu, state:%10s, timestamp: %lld", + i, g_ieee802154_probe.state[i].line, ieee802154_state_string[g_ieee802154_probe.state[i].state], g_ieee802154_probe.state[i].timestamp); } @@ -221,8 +221,8 @@ void ieee802154_record_print(void) #if CONFIG_IEEE802154_RECORD_CMD ESP_EARLY_LOGW(IEEE802154_TAG, "Print the record cmd, current cmd index: %d", g_ieee802154_probe.cmd_index); for (uint8_t i = 0; i < IEEE802154_ASSERT_RECORD_CMD_SIZE; i++) { - ESP_EARLY_LOGW(IEEE802154_TAG, "index %2d: line:%5s, cmd:%10s, timestamp: %lld", - i, g_ieee802154_probe.cmd[i].line_str, + ESP_EARLY_LOGW(IEEE802154_TAG, "index %2d: line:%5lu, cmd:%10s, timestamp: %lld", + i, g_ieee802154_probe.cmd[i].line, ieee802154_get_cmd_string(g_ieee802154_probe.cmd[i].cmd), g_ieee802154_probe.cmd[i].timestamp); } diff --git a/components/ieee802154/private_include/esp_ieee802154_util.h b/components/ieee802154/private_include/esp_ieee802154_util.h index b323367b9ce..5efdac1c26e 100644 --- a/components/ieee802154/private_include/esp_ieee802154_util.h +++ b/components/ieee802154/private_include/esp_ieee802154_util.h @@ -78,7 +78,7 @@ typedef struct { #if CONFIG_IEEE802154_RECORD_STATE #define IEEE802154_ASSERT_RECORD_STATE_SIZE CONFIG_IEEE802154_RECORD_STATE_SIZE #define ieee802154_set_state(a) do { s_ieee802154_state = a; \ - sprintf(g_ieee802154_probe.state[g_ieee802154_probe.state_index].line_str, "%d", __LINE__); \ + g_ieee802154_probe.state[g_ieee802154_probe.state_index].line = __LINE__; \ g_ieee802154_probe.state[g_ieee802154_probe.state_index].timestamp = esp_timer_get_time(); \ g_ieee802154_probe.state[g_ieee802154_probe.state_index++].state = a; \ g_ieee802154_probe.state_index = \ @@ -89,7 +89,7 @@ typedef struct { * @brief The table of recording IEEE802154 state command. */ typedef struct { - char line_str[5]; /*!< record which line in esp_ieee802154_dev.c changes the state */ + uint32_t line; /*!< record which line in esp_ieee802154_dev.c changes the state */ ieee802154_state_t state; /*!< record current radio state */ uint64_t timestamp; /*!< record timestamp */ } ieee802154_state_info_t; @@ -100,7 +100,7 @@ typedef struct { #if CONFIG_IEEE802154_RECORD_CMD #define IEEE802154_ASSERT_RECORD_CMD_SIZE CONFIG_IEEE802154_RECORD_CMD_SIZE #define ieee802154_set_cmd(a) do { ieee802154_ll_set_cmd(a); \ - sprintf(g_ieee802154_probe.cmd[g_ieee802154_probe.cmd_index].line_str, "%d", __LINE__); \ + g_ieee802154_probe.cmd[g_ieee802154_probe.cmd_index].line = __LINE__; \ g_ieee802154_probe.cmd[g_ieee802154_probe.cmd_index].timestamp = esp_timer_get_time(); \ g_ieee802154_probe.cmd[g_ieee802154_probe.cmd_index++].cmd = a; \ g_ieee802154_probe.cmd_index = \ @@ -111,7 +111,7 @@ typedef struct { * @brief The table of recording IEEE802154 radio command. */ typedef struct { - char line_str[5]; /*!< record which line in esp_ieee802154_dev.c set the command */ + uint32_t line; /*!< record which line in esp_ieee802154_dev.c set the command */ ieee802154_ll_cmd_t cmd; /*!< record current command */ uint64_t timestamp; /*!< record timestamp */ } ieee802154_cmd_info_t; From 7fa65f4cff4c5b9a317cefaa11b8006a8cf05dad Mon Sep 17 00:00:00 2001 From: wanckl Date: Wed, 22 Oct 2025 17:25:25 +0800 Subject: [PATCH 038/106] refactor(driver_twai): remove errata config selection 1 --- components/driver/twai/Kconfig.twai | 12 ------------ components/hal/esp32/include/hal/twai_ll.h | 9 ++++++++- components/hal/twai_hal_v1.c | 2 +- 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/components/driver/twai/Kconfig.twai b/components/driver/twai/Kconfig.twai index 11ff4187296..64e60d7c61e 100644 --- a/components/driver/twai/Kconfig.twai +++ b/components/driver/twai/Kconfig.twai @@ -21,18 +21,6 @@ menu "Legacy TWAI Driver Configurations" (driver/twai.h). If you want to continue using the legacy driver, and don't want to see related deprecation warnings, you can enable this option. - config TWAI_ERRATA_FIX_BUS_OFF_REC - bool "Add SW workaround for REC change during bus-off" - depends on IDF_TARGET_ESP32 - default y - help - When the bus-off condition is reached, the REC should be reset to 0 and frozen (via LOM) by the - driver's ISR. However on the ESP32, there is an edge case where the REC will increase before the - driver's ISR can respond in time (e.g., due to the rapid occurrence of bus errors), thus causing the - REC to be non-zero after bus-off. A non-zero REC can prevent bus-off recovery as the bus-off recovery - condition is that both TEC and REC become 0. Enabling this option will add a workaround in the driver - to forcibly reset REC to zero on reaching bus-off. - config TWAI_ERRATA_FIX_TX_INTR_LOST bool "Add SW workaround for TX interrupt lost errata" depends on IDF_TARGET_ESP32 diff --git a/components/hal/esp32/include/hal/twai_ll.h b/components/hal/esp32/include/hal/twai_ll.h index 59a0513d7e9..d38a5049ecf 100644 --- a/components/hal/esp32/include/hal/twai_ll.h +++ b/components/hal/esp32/include/hal/twai_ll.h @@ -28,7 +28,13 @@ #include "soc/dport_reg.h" #define TWAI_LL_GET_HW(controller_id) ((controller_id == 0) ? (&TWAI) : NULL) -#define TWAI_LL_BRP_DIV_THRESH 128 + +// When the bus-off condition is reached, the REC should be reset to 0 and frozen (via LOM) by the +// driver's ISR. However on the ESP32, there is an edge case where the REC will increase before the +// driver's ISR can respond in time (e.g., due to the rapid occurrence of bus errors), thus causing the +// REC to be non-zero after bus-off. A non-zero REC can prevent bus-off recovery as the bus-off recovery +// condition is that both TEC and REC become 0. +#define TWAI_LL_HAS_BUSOFF_REC_ISSUE 1 #ifdef __cplusplus extern "C" { @@ -38,6 +44,7 @@ static uint32_t twai_ll_get_brp_max(void); /* ------------------------- Defines and Typedefs --------------------------- */ #define TWAI_LL_BRP_MIN 2 #define TWAI_LL_BRP_MAX twai_ll_get_brp_max() // max brp of esp32 is depends on chip version +#define TWAI_LL_BRP_DIV_THRESH 128 #define TWAI_LL_TSEG1_MIN 1 #define TWAI_LL_TSEG2_MIN 1 #define TWAI_LL_TSEG1_MAX 16 //the max register value diff --git a/components/hal/twai_hal_v1.c b/components/hal/twai_hal_v1.c index e063bdffa93..c8f8a731636 100644 --- a/components/hal/twai_hal_v1.c +++ b/components/hal/twai_hal_v1.c @@ -270,7 +270,7 @@ uint32_t twai_hal_get_events(twai_hal_context_t *hal_ctx) //Handle low latency events if (events & TWAI_HAL_EVENT_BUS_OFF) { -#ifdef CONFIG_TWAI_ERRATA_FIX_BUS_OFF_REC +#if TWAI_LL_HAS_BUSOFF_REC_ISSUE //Errata workaround: Force REC to 0 by re-triggering bus-off (by setting TEC to 0 then 255) twai_ll_set_tec(hal_ctx->dev, 0); twai_ll_set_tec(hal_ctx->dev, 255); From 08de38ae62aee8814e7a5b4746bfe5fc856ef98a Mon Sep 17 00:00:00 2001 From: wanckl Date: Wed, 22 Oct 2025 17:36:59 +0800 Subject: [PATCH 039/106] refactor(driver_twai): remove errata config selection 2 --- components/driver/twai/Kconfig.twai | 17 ++++------------- components/hal/esp32/include/hal/twai_ll.h | 4 ++++ components/hal/twai_hal_v1.c | 3 ++- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/components/driver/twai/Kconfig.twai b/components/driver/twai/Kconfig.twai index 64e60d7c61e..b6de8caa443 100644 --- a/components/driver/twai/Kconfig.twai +++ b/components/driver/twai/Kconfig.twai @@ -7,12 +7,6 @@ menu "Legacy TWAI Driver Configurations" help Place the TWAI ISR in to IRAM to reduce latency and increase performance - config TWAI_SKIP_LEGACY_CONFLICT_CHECK - bool "Skip legacy driver conflict check" - default n - help - This configuration option used to bypass the conflict check mechanism with legacy code. - config TWAI_SUPPRESS_DEPRECATE_WARN bool "Suppress legacy driver deprecated warning" default n @@ -21,14 +15,11 @@ menu "Legacy TWAI Driver Configurations" (driver/twai.h). If you want to continue using the legacy driver, and don't want to see related deprecation warnings, you can enable this option. - config TWAI_ERRATA_FIX_TX_INTR_LOST - bool "Add SW workaround for TX interrupt lost errata" - depends on IDF_TARGET_ESP32 - default y + config TWAI_SKIP_LEGACY_CONFLICT_CHECK + bool "Skip legacy driver conflict check" + default n help - On the ESP32, when a transmit interrupt occurs, and interrupt register is read on the same APB clock - cycle, the transmit interrupt could be lost. Enabling this option will add a workaround that checks the - transmit buffer status bit to recover any lost transmit interrupt. + This configuration option used to bypass the conflict check mechanism with legacy code. config TWAI_ERRATA_FIX_RX_FRAME_INVALID bool "Add SW workaround for invalid RX frame errata" diff --git a/components/hal/esp32/include/hal/twai_ll.h b/components/hal/esp32/include/hal/twai_ll.h index d38a5049ecf..ba5e6556d1c 100644 --- a/components/hal/esp32/include/hal/twai_ll.h +++ b/components/hal/esp32/include/hal/twai_ll.h @@ -36,6 +36,10 @@ // condition is that both TEC and REC become 0. #define TWAI_LL_HAS_BUSOFF_REC_ISSUE 1 +// On the ESP32, when a transmit interrupt occurs, and interrupt register is read on the same APB clock +// cycle, the transmit interrupt could be lost. +#define TWAI_LL_HAS_INTR_LOST_ISSUE 1 + #ifdef __cplusplus extern "C" { #endif diff --git a/components/hal/twai_hal_v1.c b/components/hal/twai_hal_v1.c index c8f8a731636..8f677fb99a0 100644 --- a/components/hal/twai_hal_v1.c +++ b/components/hal/twai_hal_v1.c @@ -231,7 +231,8 @@ static inline uint32_t twai_hal_decode_interrupt(twai_hal_context_t *hal_ctx) TWAI_HAL_SET_BITS(events, TWAI_HAL_EVENT_RX_BUFF_FRAME); } //Transmit interrupt set whenever TX buffer becomes free -#ifdef CONFIG_TWAI_ERRATA_FIX_TX_INTR_LOST +#if TWAI_LL_HAS_INTR_LOST_ISSUE + // Errata workaround: Check the transmit buffer status bit to recover any lost transmit interrupt. if ((interrupts & TWAI_LL_INTR_TI || hal_ctx->state_flags & TWAI_HAL_STATE_FLAG_TX_BUFF_OCCUPIED) && status & TWAI_LL_STATUS_TBS) { #else if (interrupts & TWAI_LL_INTR_TI) { From 425f7f8053b01f6cd0199a24c2341c1dccf1fc24 Mon Sep 17 00:00:00 2001 From: wanckl Date: Wed, 22 Oct 2025 17:51:02 +0800 Subject: [PATCH 040/106] refactor(driver_twai): remove errata config selection 3 --- components/driver/twai/Kconfig.twai | 11 ----------- components/hal/esp32/include/hal/twai_ll.h | 5 +++++ components/hal/esp32c3/include/hal/twai_ll.h | 5 +++++ components/hal/esp32s2/include/hal/twai_ll.h | 5 +++++ components/hal/esp32s3/include/hal/twai_ll.h | 5 +++++ components/hal/twai_hal_v1.c | 10 ++++------ 6 files changed, 24 insertions(+), 17 deletions(-) diff --git a/components/driver/twai/Kconfig.twai b/components/driver/twai/Kconfig.twai index b6de8caa443..6e98a87ef4b 100644 --- a/components/driver/twai/Kconfig.twai +++ b/components/driver/twai/Kconfig.twai @@ -42,15 +42,4 @@ menu "Legacy TWAI Driver Configurations" on detection of this errata condition. Note that if a frame is being sent on the bus during the reset bus during the reset, the message will be lost. - config TWAI_ERRATA_FIX_LISTEN_ONLY_DOM - bool "Add SW workaround for listen only transmits dominant bit errata" - depends on IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32C3 - default y - help - When in the listen only mode, the TWAI controller must not influence the TWAI bus (i.e., must not send - any dominant bits). However, while in listen only mode on the ESP32/ESP32-S2/ESP32-S3/ESP32-C3, the - TWAI controller will still transmit dominant bits when it detects an error (i.e., as part of an active - error frame). Enabling this option will add a workaround that forces the TWAI controller into an error - passive state on initialization, thus preventing any dominant bits from being sent. - endmenu # TWAI Configuration diff --git a/components/hal/esp32/include/hal/twai_ll.h b/components/hal/esp32/include/hal/twai_ll.h index ba5e6556d1c..2f8d0a75cb3 100644 --- a/components/hal/esp32/include/hal/twai_ll.h +++ b/components/hal/esp32/include/hal/twai_ll.h @@ -40,6 +40,11 @@ // cycle, the transmit interrupt could be lost. #define TWAI_LL_HAS_INTR_LOST_ISSUE 1 +// When in the listen only mode, the TWAI controller must not influence the TWAI bus (i.e., must not send +// any dominant bits). However, while in listen only mode, the TWAI controller will still transmit dominant +// bits when it detects an error (i.e., as part of an active error frame). +#define TWAI_LL_HAS_LOM_DOM_ISSUE 1 + #ifdef __cplusplus extern "C" { #endif diff --git a/components/hal/esp32c3/include/hal/twai_ll.h b/components/hal/esp32c3/include/hal/twai_ll.h index a1a7c3d0596..c1a19c68c2d 100644 --- a/components/hal/esp32c3/include/hal/twai_ll.h +++ b/components/hal/esp32c3/include/hal/twai_ll.h @@ -27,6 +27,11 @@ #define TWAI_LL_GET_HW(controller_id) ((controller_id == 0) ? (&TWAI) : NULL) +// When in the listen only mode, the TWAI controller must not influence the TWAI bus (i.e., must not send +// any dominant bits). However, while in listen only mode, the TWAI controller will still transmit dominant +// bits when it detects an error (i.e., as part of an active error frame). +#define TWAI_LL_HAS_LOM_DOM_ISSUE 1 + #ifdef __cplusplus extern "C" { #endif diff --git a/components/hal/esp32s2/include/hal/twai_ll.h b/components/hal/esp32s2/include/hal/twai_ll.h index a46717c2c52..a224b9523f9 100644 --- a/components/hal/esp32s2/include/hal/twai_ll.h +++ b/components/hal/esp32s2/include/hal/twai_ll.h @@ -27,6 +27,11 @@ #define TWAI_LL_GET_HW(controller_id) ((controller_id == 0) ? (&TWAI) : NULL) +// When in the listen only mode, the TWAI controller must not influence the TWAI bus (i.e., must not send +// any dominant bits). However, while in listen only mode, the TWAI controller will still transmit dominant +// bits when it detects an error (i.e., as part of an active error frame). +#define TWAI_LL_HAS_LOM_DOM_ISSUE 1 + #ifdef __cplusplus extern "C" { #endif diff --git a/components/hal/esp32s3/include/hal/twai_ll.h b/components/hal/esp32s3/include/hal/twai_ll.h index 965f162859e..538a40e1292 100644 --- a/components/hal/esp32s3/include/hal/twai_ll.h +++ b/components/hal/esp32s3/include/hal/twai_ll.h @@ -27,6 +27,11 @@ #define TWAI_LL_GET_HW(controller_id) ((controller_id == 0) ? (&TWAI) : NULL) +// When in the listen only mode, the TWAI controller must not influence the TWAI bus (i.e., must not send +// any dominant bits). However, while in listen only mode, the TWAI controller will still transmit dominant +// bits when it detects an error (i.e., as part of an active error frame). +#define TWAI_LL_HAS_LOM_DOM_ISSUE 1 + #ifdef __cplusplus extern "C" { #endif diff --git a/components/hal/twai_hal_v1.c b/components/hal/twai_hal_v1.c index 8f677fb99a0..3224c2d1bf8 100644 --- a/components/hal/twai_hal_v1.c +++ b/components/hal/twai_hal_v1.c @@ -143,12 +143,10 @@ void twai_hal_start(twai_hal_context_t *hal_ctx) twai_ll_set_mode(hal_ctx->dev, hal_ctx->enable_listen_only, hal_ctx->enable_self_test, hal_ctx->enable_loopback); //Clear the TEC and REC twai_ll_set_tec(hal_ctx->dev, 0); -#ifdef CONFIG_TWAI_ERRATA_FIX_LISTEN_ONLY_DOM - /* - Errata workaround: Prevent transmission of dominant error frame while in listen only mode by setting REC to 128 - before exiting reset mode. This forces the controller to be error passive (thus only transmits recessive bits). - The TEC/REC remain frozen in listen only mode thus ensuring we remain error passive. - */ +#if TWAI_LL_HAS_LOM_DOM_ISSUE + // Errata workaround: Prevent transmission of dominant error frame while in listen only mode by setting REC to 128 + // before exiting reset mode. This forces the controller to be error passive (thus only transmits recessive bits). + // The TEC/REC remain frozen in listen only mode thus ensuring we remain error passive. if (hal_ctx->enable_listen_only) { twai_ll_set_rec(hal_ctx->dev, 128); } else From 334a0d2747b92e71477dd01e3eab9a47cea39018 Mon Sep 17 00:00:00 2001 From: wanckl Date: Thu, 23 Oct 2025 15:58:26 +0800 Subject: [PATCH 041/106] refactor(driver_twai): remove errata config selection 4 --- components/driver/twai/Kconfig.twai | 10 ---------- components/driver/twai/linker.lf | 2 +- components/driver/twai/twai.c | 5 ++++- components/esp_driver_twai/Kconfig | 2 +- components/hal/esp32/include/hal/twai_ll.h | 4 ++++ components/hal/twai_hal_v1.c | 12 +++++++----- 6 files changed, 17 insertions(+), 18 deletions(-) diff --git a/components/driver/twai/Kconfig.twai b/components/driver/twai/Kconfig.twai index 6e98a87ef4b..35a535771d4 100644 --- a/components/driver/twai/Kconfig.twai +++ b/components/driver/twai/Kconfig.twai @@ -32,14 +32,4 @@ menu "Legacy TWAI Driver Configurations" the bus whilst the reset is ongoing, the message will not be receive by the peripheral sent on the bus during the reset, the message will be lost. - config TWAI_ERRATA_FIX_RX_FIFO_CORRUPT - bool "Add SW workaround for RX FIFO corruption errata" - depends on IDF_TARGET_ESP32 - default y - help - On the ESP32, when the RX FIFO overruns and the RX message counter maxes out at 64 messages, the entire - RX FIFO is no longer recoverable. Enabling this option will add a workaround that resets the peripheral - on detection of this errata condition. Note that if a frame is being sent on the bus during the reset - bus during the reset, the message will be lost. - endmenu # TWAI Configuration diff --git a/components/driver/twai/linker.lf b/components/driver/twai/linker.lf index 2d0c47b0b95..67b93ecd9c2 100644 --- a/components/driver/twai/linker.lf +++ b/components/driver/twai/linker.lf @@ -23,7 +23,7 @@ entries: twai_hal_v1: twai_hal_check_state_flags (noflash) twai_hal_v1: twai_hal_clear_rx_fifo_overrun (noflash) - if TWAI_ERRATA_FIX_RX_FRAME_INVALID = y || TWAI_ERRATA_FIX_RX_FIFO_CORRUPT = y: + if TWAI_ERRATA_FIX_RX_FRAME_INVALID = y || IDF_TARGET_ESP32 = y: twai_hal_v1: twai_hal_prepare_for_reset (noflash) twai_hal_v1: twai_hal_recover_from_reset (noflash) twai_hal_v1: twai_hal_backup_config (noflash) diff --git a/components/driver/twai/twai.c b/components/driver/twai/twai.c index 5a42e178171..bb47982bb91 100644 --- a/components/driver/twai/twai.c +++ b/components/driver/twai/twai.c @@ -226,8 +226,11 @@ static void twai_intr_handler_main(void *arg) portENTER_CRITICAL_ISR(&p_twai_obj->spinlock); events = twai_hal_get_events(p_twai_obj->hal); //Get the events that triggered the interrupt -#if defined(CONFIG_TWAI_ERRATA_FIX_RX_FRAME_INVALID) || defined(CONFIG_TWAI_ERRATA_FIX_RX_FIFO_CORRUPT) +#if defined(CONFIG_TWAI_ERRATA_FIX_RX_FRAME_INVALID) || TWAI_LL_HAS_RX_FIFO_ISSUE + // Errata workaround: Reset the peripheral on detection of this errata condition. + // Note that if a frame is being sent on the bus during the reset, the message will be lost. if (events & TWAI_HAL_EVENT_NEED_PERIPH_RESET) { + ESP_EARLY_LOGD(TWAI_TAG, "Triggered peripheral reset"); twai_hal_prepare_for_reset(p_twai_obj->hal); TWAI_RCC_ATOMIC() { twai_ll_reset_register(p_twai_obj->controller_id); diff --git a/components/esp_driver_twai/Kconfig b/components/esp_driver_twai/Kconfig index e9ace179f15..6b657a8521a 100644 --- a/components/esp_driver_twai/Kconfig +++ b/components/esp_driver_twai/Kconfig @@ -18,7 +18,7 @@ menu "ESP-Driver:TWAI Configurations" config TWAI_ISR_CACHE_SAFE bool "Allow TWAI ISR execute when cache disabled" if !SPI_FLASH_AUTO_SUSPEND select TWAI_ISR_IN_IRAM - select ESP_PERIPH_CTRL_FUNC_IN_IRAM if TWAI_ERRATA_FIX_RX_FRAME_INVALID || TWAI_ERRATA_FIX_RX_FIFO_CORRUPT + select ESP_PERIPH_CTRL_FUNC_IN_IRAM if TWAI_ERRATA_FIX_RX_FRAME_INVALID || IDF_TARGET_ESP32 default n help Allow TWAI works under Cache disabled (such as when writing to SPI Flash), diff --git a/components/hal/esp32/include/hal/twai_ll.h b/components/hal/esp32/include/hal/twai_ll.h index 2f8d0a75cb3..4a3654446b5 100644 --- a/components/hal/esp32/include/hal/twai_ll.h +++ b/components/hal/esp32/include/hal/twai_ll.h @@ -45,6 +45,10 @@ // bits when it detects an error (i.e., as part of an active error frame). #define TWAI_LL_HAS_LOM_DOM_ISSUE 1 +// On the ESP32, when the RX FIFO overruns and the RX message counter maxes out at 64 messages, the entire +// RX FIFO is no longer recoverable. +#define TWAI_LL_HAS_RX_FIFO_ISSUE 1 + #ifdef __cplusplus extern "C" { #endif diff --git a/components/hal/twai_hal_v1.c b/components/hal/twai_hal_v1.c index 3224c2d1bf8..f03016d325e 100644 --- a/components/hal/twai_hal_v1.c +++ b/components/hal/twai_hal_v1.c @@ -7,6 +7,7 @@ #include #include "sdkconfig.h" #include "esp_compiler.h" +#include "hal/log.h" #include "hal/twai_hal.h" #include "hal/twai_ll.h" #include "soc/soc_caps.h" @@ -177,7 +178,7 @@ void twai_hal_start_bus_recovery(twai_hal_context_t *hal_ctx) /* ------------------------------------ IRAM Content ------------------------------------ */ -#ifdef CONFIG_TWAI_ERRATA_FIX_RX_FIFO_CORRUPT +#if TWAI_LL_HAS_RX_FIFO_ISSUE //Errata condition occurs at 64 messages. Threshold set to 62 to prevent the chance of failing to detect errata condition. #define TWAI_RX_FIFO_CORRUPT_THRESH 62 #endif @@ -300,13 +301,14 @@ uint32_t twai_hal_get_events(twai_hal_context_t *hal_ctx) if (events & TWAI_HAL_EVENT_ARB_LOST) { twai_ll_clear_arb_lost_cap(hal_ctx->dev); } -#ifdef CONFIG_TWAI_ERRATA_FIX_RX_FIFO_CORRUPT +#if TWAI_LL_HAS_RX_FIFO_ISSUE //Check for errata condition (rx_msg_count >= corruption_threshold) if (events & TWAI_HAL_EVENT_RX_BUFF_FRAME && twai_ll_get_rx_msg_count(hal_ctx->dev) >= TWAI_RX_FIFO_CORRUPT_THRESH) { TWAI_HAL_SET_BITS(events, TWAI_HAL_EVENT_NEED_PERIPH_RESET); + HAL_LOGD("TWAI_HAL", "RX FIFO corruption detected"); } #endif -#if defined(CONFIG_TWAI_ERRATA_FIX_RX_FRAME_INVALID) || defined(CONFIG_TWAI_ERRATA_FIX_RX_FIFO_CORRUPT) +#if defined(CONFIG_TWAI_ERRATA_FIX_RX_FRAME_INVALID) || TWAI_LL_HAS_RX_FIFO_ISSUE if (events & TWAI_HAL_EVENT_NEED_PERIPH_RESET) { //A peripheral reset will invalidate an RX event; TWAI_HAL_CLEAR_BITS(events, (TWAI_HAL_EVENT_RX_BUFF_FRAME)); @@ -404,7 +406,7 @@ void twai_hal_set_tx_buffer_and_transmit(twai_hal_context_t *hal_ctx, twai_hal_f twai_ll_set_cmd_tx(hal_ctx->dev); } TWAI_HAL_SET_BITS(hal_ctx->state_flags, TWAI_HAL_STATE_FLAG_TX_BUFF_OCCUPIED); -#if defined(CONFIG_TWAI_ERRATA_FIX_RX_FRAME_INVALID) || defined(CONFIG_TWAI_ERRATA_FIX_RX_FIFO_CORRUPT) +#if defined(CONFIG_TWAI_ERRATA_FIX_RX_FRAME_INVALID) || TWAI_LL_HAS_RX_FIFO_ISSUE if (&hal_ctx->errata_ctx->tx_frame_save == tx_frame) { return; } @@ -412,7 +414,7 @@ void twai_hal_set_tx_buffer_and_transmit(twai_hal_context_t *hal_ctx, twai_hal_f ESP_COMPILER_DIAGNOSTIC_PUSH_IGNORE("-Wanalyzer-overlapping-buffers") // TODO IDF-11085 memcpy(&hal_ctx->errata_ctx->tx_frame_save, tx_frame, sizeof(twai_hal_frame_t)); ESP_COMPILER_DIAGNOSTIC_POP("-Wanalyzer-overlapping-buffers") -#endif //defined(CONFIG_TWAI_ERRATA_FIX_RX_FRAME_INVALID) || defined(CONFIG_TWAI_ERRATA_FIX_RX_FIFO_CORRUPT) +#endif //defined(CONFIG_TWAI_ERRATA_FIX_RX_FRAME_INVALID) || TWAI_LL_HAS_RX_FIFO_ISSUE } uint32_t twai_hal_get_rx_msg_count(twai_hal_context_t *hal_ctx) From 3e361a559f8fc2291f5d62a446f538b44bcdaaf9 Mon Sep 17 00:00:00 2001 From: wanckl Date: Thu, 23 Oct 2025 16:36:58 +0800 Subject: [PATCH 042/106] refactor(driver_twai): remove errata config selection 5 --- components/driver/twai/Kconfig.twai | 11 ----------- components/driver/twai/linker.lf | 2 +- components/driver/twai/twai.c | 2 +- components/esp_driver_twai/Kconfig | 2 +- components/esp_driver_twai/esp_twai_onchip.c | 7 +++++-- components/hal/esp32/include/hal/twai_ll.h | 4 ++++ components/hal/twai_hal_v1.c | 20 +++++++++++--------- 7 files changed, 23 insertions(+), 25 deletions(-) diff --git a/components/driver/twai/Kconfig.twai b/components/driver/twai/Kconfig.twai index 35a535771d4..7ed12e03f17 100644 --- a/components/driver/twai/Kconfig.twai +++ b/components/driver/twai/Kconfig.twai @@ -21,15 +21,4 @@ menu "Legacy TWAI Driver Configurations" help This configuration option used to bypass the conflict check mechanism with legacy code. - config TWAI_ERRATA_FIX_RX_FRAME_INVALID - bool "Add SW workaround for invalid RX frame errata" - depends on IDF_TARGET_ESP32 - default y - help - On the ESP32, when receiving a data or remote frame, if a bus error occurs in the data or CRC field, - the data of the next received frame could be invalid. Enabling this option will add a workaround that - will reset the peripheral on detection of this errata condition. Note that if a frame is transmitted on - the bus whilst the reset is ongoing, the message will not be receive by the peripheral sent on the bus - during the reset, the message will be lost. - endmenu # TWAI Configuration diff --git a/components/driver/twai/linker.lf b/components/driver/twai/linker.lf index 67b93ecd9c2..968506ed339 100644 --- a/components/driver/twai/linker.lf +++ b/components/driver/twai/linker.lf @@ -23,7 +23,7 @@ entries: twai_hal_v1: twai_hal_check_state_flags (noflash) twai_hal_v1: twai_hal_clear_rx_fifo_overrun (noflash) - if TWAI_ERRATA_FIX_RX_FRAME_INVALID = y || IDF_TARGET_ESP32 = y: + if IDF_TARGET_ESP32 = y: #For errata workarounds twai_hal_v1: twai_hal_prepare_for_reset (noflash) twai_hal_v1: twai_hal_recover_from_reset (noflash) twai_hal_v1: twai_hal_backup_config (noflash) diff --git a/components/driver/twai/twai.c b/components/driver/twai/twai.c index bb47982bb91..3b107c7b718 100644 --- a/components/driver/twai/twai.c +++ b/components/driver/twai/twai.c @@ -226,7 +226,7 @@ static void twai_intr_handler_main(void *arg) portENTER_CRITICAL_ISR(&p_twai_obj->spinlock); events = twai_hal_get_events(p_twai_obj->hal); //Get the events that triggered the interrupt -#if defined(CONFIG_TWAI_ERRATA_FIX_RX_FRAME_INVALID) || TWAI_LL_HAS_RX_FIFO_ISSUE +#if TWAI_LL_HAS_RX_FRAME_ISSUE || TWAI_LL_HAS_RX_FIFO_ISSUE // Errata workaround: Reset the peripheral on detection of this errata condition. // Note that if a frame is being sent on the bus during the reset, the message will be lost. if (events & TWAI_HAL_EVENT_NEED_PERIPH_RESET) { diff --git a/components/esp_driver_twai/Kconfig b/components/esp_driver_twai/Kconfig index 6b657a8521a..1b979310563 100644 --- a/components/esp_driver_twai/Kconfig +++ b/components/esp_driver_twai/Kconfig @@ -18,7 +18,7 @@ menu "ESP-Driver:TWAI Configurations" config TWAI_ISR_CACHE_SAFE bool "Allow TWAI ISR execute when cache disabled" if !SPI_FLASH_AUTO_SUSPEND select TWAI_ISR_IN_IRAM - select ESP_PERIPH_CTRL_FUNC_IN_IRAM if TWAI_ERRATA_FIX_RX_FRAME_INVALID || IDF_TARGET_ESP32 + select ESP_PERIPH_CTRL_FUNC_IN_IRAM if IDF_TARGET_ESP32 #For errata workarounds default n help Allow TWAI works under Cache disabled (such as when writing to SPI Flash), diff --git a/components/esp_driver_twai/esp_twai_onchip.c b/components/esp_driver_twai/esp_twai_onchip.c index f83b76dc31f..7a8440842ed 100644 --- a/components/esp_driver_twai/esp_twai_onchip.c +++ b/components/esp_driver_twai/esp_twai_onchip.c @@ -201,8 +201,11 @@ static void _node_isr_main(void *arg) twai_onchip_ctx_t *twai_ctx = arg; uint32_t events = twai_hal_get_events(twai_ctx->hal); //Get the events that triggered the interrupt -#if CONFIG_IDF_TARGET_ESP32 // only esp32 have this errata, TODO: IDF-13002 check errata runtime +#if TWAI_LL_HAS_RX_FRAME_ISSUE || TWAI_LL_HAS_RX_FIFO_ISSUE + // Errata workaround: Reset the peripheral on detection of this errata condition. + // Note that if a frame is being sent on the bus during the reset, the message will be lost. if (events & TWAI_HAL_EVENT_NEED_PERIPH_RESET) { + ESP_EARLY_LOGD(TAG, "Triggered peripheral reset"); twai_hal_prepare_for_reset(twai_ctx->hal); TWAI_RCC_ATOMIC() { twai_ll_reset_register(twai_ctx->ctrlr_id); @@ -498,7 +501,7 @@ static esp_err_t _node_disable(twai_node_handle_t node) ESP_RETURN_ON_ERROR(esp_intr_disable(twai_ctx->intr_hdl), TAG, "disable interrupt failed"); atomic_store(&twai_ctx->state, TWAI_ERROR_BUS_OFF); twai_hal_stop(twai_ctx->hal); -#if CONFIG_IDF_TARGET_ESP32 // only esp32 have this errata, TODO: IDF-13002 check errata runtime +#if TWAI_LL_HAS_RX_FRAME_ISSUE // when `disable` happens during hardware busy, the next RX frame is corrupted, a HW reset can fix it if (twai_hal_is_hw_busy(twai_ctx->hal)) { twai_hal_backup_config(twai_ctx->hal); diff --git a/components/hal/esp32/include/hal/twai_ll.h b/components/hal/esp32/include/hal/twai_ll.h index 4a3654446b5..036a8e6c610 100644 --- a/components/hal/esp32/include/hal/twai_ll.h +++ b/components/hal/esp32/include/hal/twai_ll.h @@ -49,6 +49,10 @@ // RX FIFO is no longer recoverable. #define TWAI_LL_HAS_RX_FIFO_ISSUE 1 +// On the ESP32, when receiving a data or remote frame, if a bus error occurs in the data or CRC field, +// the data field of the NEXT received frame could be invalid. +#define TWAI_LL_HAS_RX_FRAME_ISSUE 1 + #ifdef __cplusplus extern "C" { #endif diff --git a/components/hal/twai_hal_v1.c b/components/hal/twai_hal_v1.c index f03016d325e..570db8be366 100644 --- a/components/hal/twai_hal_v1.c +++ b/components/hal/twai_hal_v1.c @@ -17,7 +17,8 @@ #define TWAI_HAL_INIT_REC 0 #define TWAI_HAL_INIT_EWL 96 -#if CONFIG_IDF_TARGET_ESP32 // only esp32 have this errata, TODO: IDF-13002 check errata runtime +#if TWAI_LL_HAS_RX_FRAME_ISSUE || TWAI_LL_HAS_RX_FIFO_ISSUE +// context for errata workarounds typedef struct twai_hal_errata_ctx_t { twai_hal_frame_t tx_frame_save; twai_ll_reg_save_t reg_save; @@ -26,7 +27,7 @@ typedef struct twai_hal_errata_ctx_t { #endif size_t twai_hal_get_mem_requirment(void) { -#if CONFIG_IDF_TARGET_ESP32 // only esp32 have this errata, TODO: IDF-13002 check errata runtime +#if TWAI_LL_HAS_RX_FRAME_ISSUE || TWAI_LL_HAS_RX_FIFO_ISSUE return sizeof(twai_hal_context_t) + sizeof(twai_hal_errata_ctx_t); #else return sizeof(twai_hal_context_t); @@ -49,7 +50,7 @@ bool twai_hal_init(twai_hal_context_t *hal_ctx, const twai_hal_config_t *config) if (!twai_ll_is_in_reset_mode(hal_ctx->dev)) { //Must enter reset mode to write to config registers return false; } -#if CONFIG_IDF_TARGET_ESP32 // only esp32 have this errata, TODO: IDF-13002 check errata runtime +#if TWAI_LL_HAS_RX_FRAME_ISSUE || TWAI_LL_HAS_RX_FIFO_ISSUE hal_ctx->errata_ctx = (twai_hal_errata_ctx_t *)(hal_ctx + 1); //errata context is place at end of hal_ctx #endif #if SOC_TWAI_SUPPORT_MULTI_ADDRESS_LAYOUT @@ -289,12 +290,13 @@ uint32_t twai_hal_get_events(twai_hal_context_t *hal_ctx) .ack_err = (type == TWAI_LL_ERR_OTHER) && (seg == TWAI_LL_ERR_SEG_ACK_SLOT), }; hal_ctx->errors = errors; -#ifdef CONFIG_TWAI_ERRATA_FIX_RX_FRAME_INVALID +#if TWAI_LL_HAS_RX_FRAME_ISSUE //Check for errata condition (RX message has bus error at particular segments) if (dir == TWAI_LL_ERR_DIR_RX && ((seg == TWAI_LL_ERR_SEG_DATA || seg == TWAI_LL_ERR_SEG_CRC_SEQ) || (seg == TWAI_LL_ERR_SEG_ACK_DELIM && type == TWAI_LL_ERR_OTHER))) { TWAI_HAL_SET_BITS(events, TWAI_HAL_EVENT_NEED_PERIPH_RESET); + HAL_LOGD("TWAI_HAL", "RX frame invalid detected"); } #endif } @@ -308,7 +310,7 @@ uint32_t twai_hal_get_events(twai_hal_context_t *hal_ctx) HAL_LOGD("TWAI_HAL", "RX FIFO corruption detected"); } #endif -#if defined(CONFIG_TWAI_ERRATA_FIX_RX_FRAME_INVALID) || TWAI_LL_HAS_RX_FIFO_ISSUE +#if TWAI_LL_HAS_RX_FRAME_ISSUE || TWAI_LL_HAS_RX_FIFO_ISSUE if (events & TWAI_HAL_EVENT_NEED_PERIPH_RESET) { //A peripheral reset will invalidate an RX event; TWAI_HAL_CLEAR_BITS(events, (TWAI_HAL_EVENT_RX_BUFF_FRAME)); @@ -317,7 +319,7 @@ uint32_t twai_hal_get_events(twai_hal_context_t *hal_ctx) return events; } -#if CONFIG_IDF_TARGET_ESP32 // only esp32 have this errata, TODO: IDF-13002 check errata runtime +#if TWAI_LL_HAS_RX_FRAME_ISSUE || TWAI_LL_HAS_RX_FIFO_ISSUE bool twai_hal_is_hw_busy(twai_hal_context_t *hal_ctx) { return (TWAI_LL_STATUS_TS | TWAI_LL_STATUS_RS) & twai_ll_get_status(hal_ctx->dev); @@ -366,7 +368,7 @@ void twai_hal_recover_from_reset(twai_hal_context_t *hal_ctx) TWAI_HAL_CLEAR_BITS(hal_ctx->state_flags, TWAI_HAL_STATE_FLAG_TX_NEED_RETRY); } } -#endif // CONFIG_IDF_TARGET_ESP32 +#endif // TWAI_LL_HAS_RX_FRAME_ISSUE || TWAI_LL_HAS_RX_FIFO_ISSUE void twai_hal_format_frame(const twai_hal_trans_desc_t *trans_desc, twai_hal_frame_t *frame) { @@ -406,7 +408,7 @@ void twai_hal_set_tx_buffer_and_transmit(twai_hal_context_t *hal_ctx, twai_hal_f twai_ll_set_cmd_tx(hal_ctx->dev); } TWAI_HAL_SET_BITS(hal_ctx->state_flags, TWAI_HAL_STATE_FLAG_TX_BUFF_OCCUPIED); -#if defined(CONFIG_TWAI_ERRATA_FIX_RX_FRAME_INVALID) || TWAI_LL_HAS_RX_FIFO_ISSUE +#if TWAI_LL_HAS_RX_FRAME_ISSUE || TWAI_LL_HAS_RX_FIFO_ISSUE if (&hal_ctx->errata_ctx->tx_frame_save == tx_frame) { return; } @@ -414,7 +416,7 @@ void twai_hal_set_tx_buffer_and_transmit(twai_hal_context_t *hal_ctx, twai_hal_f ESP_COMPILER_DIAGNOSTIC_PUSH_IGNORE("-Wanalyzer-overlapping-buffers") // TODO IDF-11085 memcpy(&hal_ctx->errata_ctx->tx_frame_save, tx_frame, sizeof(twai_hal_frame_t)); ESP_COMPILER_DIAGNOSTIC_POP("-Wanalyzer-overlapping-buffers") -#endif //defined(CONFIG_TWAI_ERRATA_FIX_RX_FRAME_INVALID) || TWAI_LL_HAS_RX_FIFO_ISSUE +#endif //TWAI_LL_HAS_RX_FRAME_ISSUE || TWAI_LL_HAS_RX_FIFO_ISSUE } uint32_t twai_hal_get_rx_msg_count(twai_hal_context_t *hal_ctx) From 9176ef32a40bbe83d24a9492190e2cc51316a3ff Mon Sep 17 00:00:00 2001 From: wanckl Date: Thu, 23 Oct 2025 19:21:49 +0800 Subject: [PATCH 043/106] refactor(driver_twai): using hal/config in hal layer --- components/hal/include/hal/twai_types_deprecated.h | 8 ++++---- components/hal/twai_hal_v1.c | 1 - tools/ci/sg_rules/no_kconfig_in_hal_component.yml | 7 ------- 3 files changed, 4 insertions(+), 12 deletions(-) diff --git a/components/hal/include/hal/twai_types_deprecated.h b/components/hal/include/hal/twai_types_deprecated.h index 3dfe57d5225..1752c786665 100644 --- a/components/hal/include/hal/twai_types_deprecated.h +++ b/components/hal/include/hal/twai_types_deprecated.h @@ -8,9 +8,9 @@ #include #include -#include "sdkconfig.h" #include "soc/soc_caps.h" #include "soc/clk_tree_defs.h" +#include "hal/config.h" #ifdef __cplusplus extern "C" { @@ -56,11 +56,11 @@ extern "C" { #define TWAI_TIMING_CONFIG_10KBITS() {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 200000, .brp = 0, .prop_seg = 0, .tseg_1 = 15, .tseg_2 = 4, .sjw = 3, .ssp_offset = 0, .triple_sampling = false} #endif // SOC_TWAI_BRP_MAX > 256 -#if (SOC_TWAI_BRP_MAX > 128) || (CONFIG_ESP32_REV_MIN_FULL >= 200) +#if (SOC_TWAI_BRP_MAX > 128) || (SOC_IS(ESP32) && (HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 200)) #define TWAI_TIMING_CONFIG_12_5KBITS() {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 312500, .brp = 0, .prop_seg = 0, .tseg_1 = 16, .tseg_2 = 8, .sjw = 3, .ssp_offset = 0, .triple_sampling = false} #define TWAI_TIMING_CONFIG_16KBITS() {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 400000, .brp = 0, .prop_seg = 0, .tseg_1 = 16, .tseg_2 = 8, .sjw = 3, .ssp_offset = 0, .triple_sampling = false} #define TWAI_TIMING_CONFIG_20KBITS() {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 400000, .brp = 0, .prop_seg = 0, .tseg_1 = 15, .tseg_2 = 4, .sjw = 3, .ssp_offset = 0, .triple_sampling = false} -#endif // (SOC_TWAI_BRP_MAX > 128) || (CONFIG_ESP32_REV_MIN_FULL >= 200) +#endif #if SOC_TWAI_CLK_SUPPORT_XTAL #define TWAI_TIMING_CONFIG_25KBITS() {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 500000, .brp = 0, .prop_seg = 0, .tseg_1 = 15, .tseg_2 = 4, .sjw = 3, .ssp_offset = 0, .triple_sampling = false} @@ -71,7 +71,7 @@ extern "C" { #define TWAI_TIMING_CONFIG_100KBITS() {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 2000000, .brp = 0, .prop_seg = 0, .tseg_1 = 15, .tseg_2 = 4, .sjw = 3, .ssp_offset = 0, .triple_sampling = false} #define TWAI_TIMING_CONFIG_125KBITS() {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 2000000, .brp = 0, .prop_seg = 0, .tseg_1 = 11, .tseg_2 = 4, .sjw = 3, .ssp_offset = 0, .triple_sampling = false} #define TWAI_TIMING_CONFIG_250KBITS() {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 4000000, .brp = 0, .prop_seg = 0, .tseg_1 = 11, .tseg_2 = 4, .sjw = 2, .ssp_offset = 0, .triple_sampling = false} -#if SOC_TWAI_CLK_SUPPORT_XTAL && CONFIG_XTAL_FREQ == 40 // TWAI_CLK_SRC_XTAL = 40M +#if SOC_TWAI_CLK_SUPPORT_XTAL && HAL_CONFIG(XTAL_HINT_FREQ_MHZ) == 40 // TWAI_CLK_SRC_XTAL = 40M #define TWAI_TIMING_CONFIG_500KBITS() {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 10000000, .brp = 0, .prop_seg = 0, .tseg_1 = 15, .tseg_2 = 4, .sjw = 3, .ssp_offset = 0, .triple_sampling = false} #define TWAI_TIMING_CONFIG_800KBITS() {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 20000000, .brp = 0, .prop_seg = 0, .tseg_1 = 16, .tseg_2 = 8, .sjw = 3, .ssp_offset = 0, .triple_sampling = false} #define TWAI_TIMING_CONFIG_1MBITS() {.clk_src = TWAI_CLK_SRC_DEFAULT, .quanta_resolution_hz = 20000000, .brp = 0, .prop_seg = 0, .tseg_1 = 15, .tseg_2 = 4, .sjw = 3, .ssp_offset = 0, .triple_sampling = false} diff --git a/components/hal/twai_hal_v1.c b/components/hal/twai_hal_v1.c index 570db8be366..a3590816eb9 100644 --- a/components/hal/twai_hal_v1.c +++ b/components/hal/twai_hal_v1.c @@ -5,7 +5,6 @@ */ #include -#include "sdkconfig.h" #include "esp_compiler.h" #include "hal/log.h" #include "hal/twai_hal.h" diff --git a/tools/ci/sg_rules/no_kconfig_in_hal_component.yml b/tools/ci/sg_rules/no_kconfig_in_hal_component.yml index b505efbf435..87ed8167825 100644 --- a/tools/ci/sg_rules/no_kconfig_in_hal_component.yml +++ b/tools/ci/sg_rules/no_kconfig_in_hal_component.yml @@ -12,10 +12,6 @@ ignores: - "components/hal/platform_port/**/*" - "components/hal/test_apps/**/*" - "components/esp_hal*/test_apps/**/*" - # the following files should be refactored to remove Kconfig macros - - "components/hal/twai_hal_v1.c" - - "components/hal/esp32/include/hal/twai_ll.h" - - "components/hal/include/hal/twai_types_deprecated.h" rule: any: - kind: argument_list @@ -47,9 +43,6 @@ ignores: - "components/hal/platform_port/**/*" - "components/hal/test_apps/**/*" - "components/esp_hal*/test_apps/**/*" - # the following files should be refactored to remove sdkconfig.h - - "components/hal/twai_hal_v1.c" - - "components/hal/include/hal/twai_types_deprecated.h" rule: kind: preproc_include has: From 2f50cb27274a5a3d30c7d29b1cd83cb3ebfee03b Mon Sep 17 00:00:00 2001 From: JinCheng Date: Mon, 25 Aug 2025 15:53:48 +0800 Subject: [PATCH 044/106] fix(bt/bluedroid): update the COD before enabling inquiry scan --- components/bt/host/bluedroid/stack/btm/btm_inq.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/components/bt/host/bluedroid/stack/btm/btm_inq.c b/components/bt/host/bluedroid/stack/btm/btm_inq.c index 4456140df93..41a47300e72 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_inq.c +++ b/components/bt/host/bluedroid/stack/btm/btm_inq.c @@ -240,13 +240,6 @@ tBTM_STATUS BTM_SetDiscoverability (UINT16 inq_mode, UINT16 window, UINT16 inter scan_mode |= HCI_PAGE_SCAN_ENABLED; } - if (btsnd_hcic_write_scan_enable (scan_mode)) { - btm_cb.btm_inq_vars.discoverable_mode &= (~BTM_DISCOVERABLE_MASK); - btm_cb.btm_inq_vars.discoverable_mode |= inq_mode; - } else { - return (BTM_NO_RESOURCES); - } - /* Change the service class bit if mode has changed */ p_cod = BTM_ReadDeviceClass(); BTM_COD_SERVICE_CLASS(service_class, p_cod); @@ -266,6 +259,13 @@ tBTM_STATUS BTM_SetDiscoverability (UINT16 inq_mode, UINT16 window, UINT16 inter (void) BTM_SetDeviceClass (cod); } + if (btsnd_hcic_write_scan_enable (scan_mode)) { + btm_cb.btm_inq_vars.discoverable_mode &= (~BTM_DISCOVERABLE_MASK); + btm_cb.btm_inq_vars.discoverable_mode |= inq_mode; + } else { + return (BTM_NO_RESOURCES); + } + return (BTM_SUCCESS); } From efd24c27db26afe7c4d8560d1cc6422ce9adb352 Mon Sep 17 00:00:00 2001 From: Ashish Sharma Date: Thu, 16 Oct 2025 13:18:49 +0800 Subject: [PATCH 045/106] feat(mbedtls): update to version 3.6.5 --- components/esp-tls/Kconfig | 2 +- components/idf_test/include/esp32/idf_performance_target.h | 4 ++-- components/idf_test/include/esp32s2/idf_performance_target.h | 4 ++-- components/idf_test/include/esp32s3/idf_performance_target.h | 4 ++-- components/mbedtls/mbedtls | 2 +- docs/en/api-reference/protocols/mbedtls.rst | 2 +- docs/zh_CN/api-reference/protocols/mbedtls.rst | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/components/esp-tls/Kconfig b/components/esp-tls/Kconfig index 3420ebd6981..99ccfb07777 100644 --- a/components/esp-tls/Kconfig +++ b/components/esp-tls/Kconfig @@ -26,7 +26,7 @@ menu "ESP-TLS" config ESP_TLS_USE_DS_PERIPHERAL bool "Use Digital Signature (DS) Peripheral with ESP-TLS" - depends on ESP_TLS_USING_MBEDTLS && SOC_DIG_SIGN_SUPPORTED + depends on ESP_TLS_USING_MBEDTLS && SOC_DIG_SIGN_SUPPORTED && MBEDTLS_PK_RSA_ALT_SUPPORT default y help Enable use of the Digital Signature Peripheral for ESP-TLS.The DS peripheral diff --git a/components/idf_test/include/esp32/idf_performance_target.h b/components/idf_test/include/esp32/idf_performance_target.h index ca772c685f7..9f39fefe9c8 100644 --- a/components/idf_test/include/esp32/idf_performance_target.h +++ b/components/idf_test/include/esp32/idf_performance_target.h @@ -22,11 +22,11 @@ #define IDF_PERFORMANCE_MAX_TIME_SHA512_32KB 4500 #define IDF_PERFORMANCE_MAX_RSA_2048KEY_PUBLIC_OP 19000 -#define IDF_PERFORMANCE_MAX_RSA_2048KEY_PRIVATE_OP 450000 +#define IDF_PERFORMANCE_MAX_RSA_2048KEY_PRIVATE_OP 750000 #define IDF_PERFORMANCE_MAX_RSA_3072KEY_PUBLIC_OP 33000 #define IDF_PERFORMANCE_MAX_RSA_3072KEY_PRIVATE_OP 950000 #define IDF_PERFORMANCE_MAX_RSA_4096KEY_PUBLIC_OP 90000 -#define IDF_PERFORMANCE_MAX_RSA_4096KEY_PRIVATE_OP 1900000 +#define IDF_PERFORMANCE_MAX_RSA_4096KEY_PRIVATE_OP 3000000 // floating point instructions per divide and per sqrt (configured for worst-case with PSRAM workaround) #define IDF_PERFORMANCE_MAX_CYCLES_PER_DIV 70 diff --git a/components/idf_test/include/esp32s2/idf_performance_target.h b/components/idf_test/include/esp32s2/idf_performance_target.h index 07baf2ca51d..0d2b6f0dd36 100644 --- a/components/idf_test/include/esp32s2/idf_performance_target.h +++ b/components/idf_test/include/esp32s2/idf_performance_target.h @@ -17,11 +17,11 @@ #define IDF_PERFORMANCE_MAX_TIME_SHA512_32KB 900 #define IDF_PERFORMANCE_MAX_RSA_2048KEY_PUBLIC_OP 13500 -#define IDF_PERFORMANCE_MAX_RSA_2048KEY_PRIVATE_OP 420000 +#define IDF_PERFORMANCE_MAX_RSA_2048KEY_PRIVATE_OP 650000 #define IDF_PERFORMANCE_MAX_RSA_3072KEY_PUBLIC_OP 36000 #define IDF_PERFORMANCE_MAX_RSA_3072KEY_PRIVATE_OP 960000 #define IDF_PERFORMANCE_MAX_RSA_4096KEY_PUBLIC_OP 62000 -#define IDF_PERFORMANCE_MAX_RSA_4096KEY_PRIVATE_OP 1850000 +#define IDF_PERFORMANCE_MAX_RSA_4096KEY_PRIVATE_OP 2850000 #define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_NO_FILTER 3 #define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_FILTER_2 3 diff --git a/components/idf_test/include/esp32s3/idf_performance_target.h b/components/idf_test/include/esp32s3/idf_performance_target.h index 9f485b382c2..3b2bbe3b42f 100644 --- a/components/idf_test/include/esp32s3/idf_performance_target.h +++ b/components/idf_test/include/esp32s3/idf_performance_target.h @@ -15,11 +15,11 @@ #define IDF_PERFORMANCE_MAX_TIME_SHA512_32KB 900 #define IDF_PERFORMANCE_MAX_RSA_2048KEY_PUBLIC_OP 18000 -#define IDF_PERFORMANCE_MAX_RSA_2048KEY_PRIVATE_OP 490000 +#define IDF_PERFORMANCE_MAX_RSA_2048KEY_PRIVATE_OP 700000 #define IDF_PERFORMANCE_MAX_RSA_3072KEY_PUBLIC_OP 45000 #define IDF_PERFORMANCE_MAX_RSA_3072KEY_PRIVATE_OP 1300000 #define IDF_PERFORMANCE_MAX_RSA_4096KEY_PUBLIC_OP 80000 -#define IDF_PERFORMANCE_MAX_RSA_4096KEY_PRIVATE_OP 2500000 +#define IDF_PERFORMANCE_MAX_RSA_4096KEY_PRIVATE_OP 3500000 // floating point instructions per divide and per sqrt (configured for worst-case with PSRAM workaround) #define IDF_PERFORMANCE_MAX_CYCLES_PER_DIV 70 diff --git a/components/mbedtls/mbedtls b/components/mbedtls/mbedtls index 05556725a28..ffb280bb63c 160000 --- a/components/mbedtls/mbedtls +++ b/components/mbedtls/mbedtls @@ -1 +1 @@ -Subproject commit 05556725a2816aecbf87623c959a4a80ee7eb6de +Subproject commit ffb280bb63c78bfec1e1ab55040671768c85c923 diff --git a/docs/en/api-reference/protocols/mbedtls.rst b/docs/en/api-reference/protocols/mbedtls.rst index cd33f9b82f3..1565bcce696 100644 --- a/docs/en/api-reference/protocols/mbedtls.rst +++ b/docs/en/api-reference/protocols/mbedtls.rst @@ -311,5 +311,5 @@ Reducing Binary Size Under ``Component Config`` > ``mbedTLS``, several Mbed TLS features are enabled by default. These can be disabled if not needed to save code size. More information is available in the :ref:`Minimizing Binary Size ` documentation. -.. _`API Reference`: https://mbed-tls.readthedocs.io/projects/api/en/v3.6.4/ +.. _`API Reference`: https://mbed-tls.readthedocs.io/projects/api/en/v3.6.5/ .. _`Knowledge Base`: https://mbed-tls.readthedocs.io/en/latest/kb/ diff --git a/docs/zh_CN/api-reference/protocols/mbedtls.rst b/docs/zh_CN/api-reference/protocols/mbedtls.rst index 3f06d882844..0e7122185d8 100644 --- a/docs/zh_CN/api-reference/protocols/mbedtls.rst +++ b/docs/zh_CN/api-reference/protocols/mbedtls.rst @@ -311,5 +311,5 @@ Mbed TLS 配置系统支持预设配置。``Component Config`` > ``mbedTLS`` 中 在 ``Component Config`` > ``mbedTLS`` 配置中,多个 Mbed TLS 功能已默认启用。如无需使用,可以禁用以减小固件大小。详情请参阅 :ref:`最小化固件大小 `。 -.. _`API Reference`: https://mbed-tls.readthedocs.io/projects/api/en/v3.6.4/ +.. _`API Reference`: https://mbed-tls.readthedocs.io/projects/api/en/v3.6.5/ .. _`Knowledge Base`: https://mbed-tls.readthedocs.io/en/latest/kb/ From d44f7e92b5e38055ab0ae3b823c4f27f231771b0 Mon Sep 17 00:00:00 2001 From: Tomas Rezucha Date: Thu, 6 Nov 2025 18:13:05 +0800 Subject: [PATCH 046/106] refactor(usb): Make usb hal layer independent --- components/esp_hal_usb/CMakeLists.txt | 23 +++++++ components/esp_hal_usb/README.md | 55 ++++++++++++++++ .../esp32h4/include/hal/usb_dwc_ll.h | 25 ++++---- .../esp32h4/include/hal/usb_wrap_ll.h | 7 +-- .../esp32h4/usb_dwc_periph.c | 0 .../esp32p4/include/hal/usb_dwc_ll.h | 63 +++++++++---------- .../esp32p4/include/hal/usb_utmi_ll.h | 0 .../esp32p4/include/hal/usb_wrap_ll.h | 1 - .../esp32p4/usb_dwc_periph.c | 0 .../esp32s2/include/hal/usb_dwc_ll.h | 25 ++++---- .../esp32s2/include/hal/usb_wrap_ll.h | 1 - .../esp32s2/usb_dwc_periph.c | 0 .../esp32s3/include/hal/usb_dwc_ll.h | 25 ++++---- .../esp32s3/include/hal/usb_wrap_ll.h | 1 - .../esp32s3/usb_dwc_periph.c | 0 .../include/hal/usb_dwc_hal.h | 13 ++-- .../include/hal/usb_dwc_types.h | 0 .../include/hal/usb_phy_types.h | 0 .../include/hal/usb_utmi_hal.h | 0 .../include/hal/usb_wrap_hal.h | 0 .../include/hal/usb_wrap_types.h | 0 .../include/soc/usb_periph.h | 0 components/{hal => esp_hal_usb}/usb_dwc_hal.c | 15 +++-- .../{hal => esp_hal_usb}/usb_utmi_hal.c | 0 .../{hal => esp_hal_usb}/usb_wrap_hal.c | 0 components/esp_hw_support/CMakeLists.txt | 2 +- components/hal/CMakeLists.txt | 10 --- components/soc/CMakeLists.txt | 4 -- examples/peripherals/.build-test-rules.yml | 12 ++-- 29 files changed, 167 insertions(+), 115 deletions(-) create mode 100644 components/esp_hal_usb/CMakeLists.txt create mode 100644 components/esp_hal_usb/README.md rename components/{hal => esp_hal_usb}/esp32h4/include/hal/usb_dwc_ll.h (98%) rename components/{hal => esp_hal_usb}/esp32h4/include/hal/usb_wrap_ll.h (97%) rename components/{soc => esp_hal_usb}/esp32h4/usb_dwc_periph.c (100%) rename components/{hal => esp_hal_usb}/esp32p4/include/hal/usb_dwc_ll.h (97%) rename components/{hal => esp_hal_usb}/esp32p4/include/hal/usb_utmi_ll.h (100%) rename components/{hal => esp_hal_usb}/esp32p4/include/hal/usb_wrap_ll.h (99%) rename components/{soc => esp_hal_usb}/esp32p4/usb_dwc_periph.c (100%) rename components/{hal => esp_hal_usb}/esp32s2/include/hal/usb_dwc_ll.h (98%) rename components/{hal => esp_hal_usb}/esp32s2/include/hal/usb_wrap_ll.h (99%) rename components/{soc => esp_hal_usb}/esp32s2/usb_dwc_periph.c (100%) rename components/{hal => esp_hal_usb}/esp32s3/include/hal/usb_dwc_ll.h (98%) rename components/{hal => esp_hal_usb}/esp32s3/include/hal/usb_wrap_ll.h (99%) rename components/{soc => esp_hal_usb}/esp32s3/usb_dwc_periph.c (100%) rename components/{hal => esp_hal_usb}/include/hal/usb_dwc_hal.h (98%) rename components/{hal => esp_hal_usb}/include/hal/usb_dwc_types.h (100%) rename components/{hal => esp_hal_usb}/include/hal/usb_phy_types.h (100%) rename components/{hal => esp_hal_usb}/include/hal/usb_utmi_hal.h (100%) rename components/{hal => esp_hal_usb}/include/hal/usb_wrap_hal.h (100%) rename components/{hal => esp_hal_usb}/include/hal/usb_wrap_types.h (100%) rename components/{soc => esp_hal_usb}/include/soc/usb_periph.h (100%) rename components/{hal => esp_hal_usb}/usb_dwc_hal.c (98%) rename components/{hal => esp_hal_usb}/usb_utmi_hal.c (100%) rename components/{hal => esp_hal_usb}/usb_wrap_hal.c (100%) diff --git a/components/esp_hal_usb/CMakeLists.txt b/components/esp_hal_usb/CMakeLists.txt new file mode 100644 index 00000000000..c069c78e435 --- /dev/null +++ b/components/esp_hal_usb/CMakeLists.txt @@ -0,0 +1,23 @@ +idf_build_get_property(target IDF_TARGET) + +if(${target} STREQUAL "linux") + return() # This component is not supported by the POSIX/Linux simulator +endif() + +set(includes "include") +set(srcs) + +# USB-DWC related source files and USB FSLS PHY wrapper +if(CONFIG_SOC_USB_OTG_SUPPORTED) + list(APPEND srcs "usb_dwc_hal.c" "usb_wrap_hal.c" "${target}/usb_dwc_periph.c") + list(APPEND includes "${target}/include") +endif() + +# USB UTMI PHY +if(CONFIG_SOC_USB_UTMI_PHY_NUM GREATER 0) + list(APPEND srcs "usb_utmi_hal.c") +endif() + +idf_component_register(SRCS ${srcs} + INCLUDE_DIRS ${includes} + REQUIRES soc hal) diff --git a/components/esp_hal_usb/README.md b/components/esp_hal_usb/README.md new file mode 100644 index 00000000000..0efd2c37f32 --- /dev/null +++ b/components/esp_hal_usb/README.md @@ -0,0 +1,55 @@ +# ESP Hardware Abstraction Layer for USB Peripheral(s) + +> [!NOTE] +> This component is currently in beta. Its API, behavior, and compatibility may change at any time and without notice; backward compatibility is not guaranteed. Use caution when integrating into production systems. + +## Overview + +The `esp_hal_usb` component provides a **Hardware Abstraction Layer** for USB controllers and PHYs across all ESP-IDF supported targets. USB (Universal Serial Bus) enables communication between the ESP device and USB hosts or devices, supporting various USB speeds and transfer types for data exchange. + +## Architecture + +The USB HAL is structured in two main sub-layers: + +1. **HAL Layer (Upper)**: Defines the operational steps and data structures required to control USB peripherals (e.g., initialization, endpoint configuration, transfer management, PHY control). + +2. **Low-Level Layer (Bottom)**: Serves as a translation layer between the HAL and the register files defined in the `soc` component, handling target-specific register configurations. + +## Supported USB Controllers and PHYs + +This HAL supports various USB controller and PHY types depending on the ESP chip: + +- **USB-DWC (DesignWare USB Controller)**: The main USB OTG controller available on: + - ESP32-S2 + - ESP32-S3 + - ESP32-H4 + - ESP32-P4 + +- **USB WRAP**: A wrapper/peripheral controller that provides additional USB functionality and GPIO matrix integration + +- **USB PHY Types**: + - **FSLS (Full Speed/Low Speed) Internal PHY**: Built-in PHY supporting USB Full Speed and Low Speed operation + - **FSLS External PHY**: Support for external FSLS PHY via GPIO matrix + - **UTMI PHY**: UTMI+ compliant PHY interface (available on ESP32-P4) + +## Features + +- USB controller initialization and configuration +- Endpoint management (IN/OUT endpoints) +- Transfer type support (Control, Bulk, Interrupt, Isochronous) +- USB speed detection and configuration (High Speed, Full Speed, Low Speed) +- FIFO configuration and management +- PHY initialization and control (FSLS and UTMI) +- GPIO matrix signal routing for USB PHY interfaces +- OTG (On-The-Go) signal handling +- Interrupt management and event handling +- Multi-controller support (on chips with multiple USB controllers) + +## Usage + +The HAL functions primarily serve ESP-IDF USB drivers, primarily the [USB Host stack](https://components.espressif.com/components/espressif/usb). + +## Dependencies + +- `soc`: Provides chip-specific register definitions +- `hal`: Core hardware abstraction utilities and macros diff --git a/components/hal/esp32h4/include/hal/usb_dwc_ll.h b/components/esp_hal_usb/esp32h4/include/hal/usb_dwc_ll.h similarity index 98% rename from components/hal/esp32h4/include/hal/usb_dwc_ll.h rename to components/esp_hal_usb/esp32h4/include/hal/usb_dwc_ll.h index 7488affb70e..ef85560faf1 100644 --- a/components/hal/esp32h4/include/hal/usb_dwc_ll.h +++ b/components/esp_hal_usb/esp32h4/include/hal/usb_dwc_ll.h @@ -164,7 +164,6 @@ typedef struct { uint8_t *buffer; } usb_dwc_ll_dma_qtd_t; - /* ----------------------------------------------------------------------------- ------------------------------- Global Registers ------------------------------- ----------------------------------------------------------------------------- */ @@ -400,18 +399,18 @@ static inline void usb_dwc_ll_hcfg_set_num_frame_list_entries(usb_dwc_dev_t *hw, { uint32_t frlisten; switch (num_entries) { - case USB_HAL_FRAME_LIST_LEN_8: - frlisten = 0; - break; - case USB_HAL_FRAME_LIST_LEN_16: - frlisten = 1; - break; - case USB_HAL_FRAME_LIST_LEN_32: - frlisten = 2; - break; - default: //USB_HAL_FRAME_LIST_LEN_64 - frlisten = 3; - break; + case USB_HAL_FRAME_LIST_LEN_8: + frlisten = 0; + break; + case USB_HAL_FRAME_LIST_LEN_16: + frlisten = 1; + break; + case USB_HAL_FRAME_LIST_LEN_32: + frlisten = 2; + break; + default: //USB_HAL_FRAME_LIST_LEN_64 + frlisten = 3; + break; } hw->hcfg_reg.frlisten = frlisten; } diff --git a/components/hal/esp32h4/include/hal/usb_wrap_ll.h b/components/esp_hal_usb/esp32h4/include/hal/usb_wrap_ll.h similarity index 97% rename from components/hal/esp32h4/include/hal/usb_wrap_ll.h rename to components/esp_hal_usb/esp32h4/include/hal/usb_wrap_ll.h index ff4a08c1d50..d233ed52ffd 100644 --- a/components/hal/esp32h4/include/hal/usb_wrap_ll.h +++ b/components/esp_hal_usb/esp32h4/include/hal/usb_wrap_ll.h @@ -17,7 +17,6 @@ #define USB_WRAP_LL_EXT_PHY_SUPPORTED 0 // Cannot route to an external FSLS PHY - #ifdef __cplusplus extern "C" { #endif @@ -70,11 +69,11 @@ FORCE_INLINE_ATTR void usb_wrap_ll_phy_disable_srp_sessend_override(usb_wrap_dev FORCE_INLINE_ATTR void usb_wrap_ll_phy_enable_pin_exchg(usb_wrap_dev_t *hw, bool enable) { if (enable) { - hw->wrap_otg_conf.wrap_exchg_pins = 1; + hw->wrap_otg_conf.wrap_exchg_pins = 1; hw->wrap_otg_conf.wrap_exchg_pins_override = 1; } else { - hw->wrap_otg_conf.wrap_exchg_pins_override = 0; - hw->wrap_otg_conf.wrap_exchg_pins = 0; + hw->wrap_otg_conf.wrap_exchg_pins_override = 0; + hw->wrap_otg_conf.wrap_exchg_pins = 0; } } diff --git a/components/soc/esp32h4/usb_dwc_periph.c b/components/esp_hal_usb/esp32h4/usb_dwc_periph.c similarity index 100% rename from components/soc/esp32h4/usb_dwc_periph.c rename to components/esp_hal_usb/esp32h4/usb_dwc_periph.c diff --git a/components/hal/esp32p4/include/hal/usb_dwc_ll.h b/components/esp_hal_usb/esp32p4/include/hal/usb_dwc_ll.h similarity index 97% rename from components/hal/esp32p4/include/hal/usb_dwc_ll.h rename to components/esp_hal_usb/esp32p4/include/hal/usb_dwc_ll.h index 1ee7334a749..7fb3bcbfb29 100644 --- a/components/hal/esp32p4/include/hal/usb_dwc_ll.h +++ b/components/esp_hal_usb/esp32p4/include/hal/usb_dwc_ll.h @@ -166,7 +166,6 @@ typedef struct { uint8_t *buffer; } usb_dwc_ll_dma_qtd_t; - /* ----------------------------------------------------------------------------- ------------------------------- Global Registers ------------------------------- ----------------------------------------------------------------------------- */ @@ -423,18 +422,18 @@ static inline void usb_dwc_ll_hcfg_set_num_frame_list_entries(usb_dwc_dev_t *hw, { uint32_t frlisten; switch (num_entries) { - case USB_HAL_FRAME_LIST_LEN_8: - frlisten = 0; - break; - case USB_HAL_FRAME_LIST_LEN_16: - frlisten = 1; - break; - case USB_HAL_FRAME_LIST_LEN_32: - frlisten = 2; - break; - default: //USB_HAL_FRAME_LIST_LEN_64 - frlisten = 3; - break; + case USB_HAL_FRAME_LIST_LEN_8: + frlisten = 0; + break; + case USB_HAL_FRAME_LIST_LEN_16: + frlisten = 1; + break; + case USB_HAL_FRAME_LIST_LEN_32: + frlisten = 2; + break; + default: //USB_HAL_FRAME_LIST_LEN_64 + frlisten = 3; + break; } hw->hcfg_reg.frlisten = frlisten; } @@ -862,25 +861,25 @@ static inline void usb_dwc_ll_hctsiz_set_sched_info(volatile usb_dwc_host_chan_r hctsiz.val = chan->hctsiz_reg.val; uint8_t sched_info_val; switch (tokens_per_frame) { - case 1: - offset %= 8; // If the required offset > 8, we must wrap around to SCHED_INFO size = 8 - sched_info_val = 0b00000001; - break; - case 2: - offset %= 4; - sched_info_val = 0b00010001; - break; - case 4: - offset %= 2; - sched_info_val = 0b01010101; - break; - case 8: - offset = 0; - sched_info_val = 0b11111111; - break; - default: - abort(); - break; + case 1: + offset %= 8; // If the required offset > 8, we must wrap around to SCHED_INFO size = 8 + sched_info_val = 0b00000001; + break; + case 2: + offset %= 4; + sched_info_val = 0b00010001; + break; + case 4: + offset %= 2; + sched_info_val = 0b01010101; + break; + case 8: + offset = 0; + sched_info_val = 0b11111111; + break; + default: + abort(); + break; } sched_info_val <<= offset; hctsiz.xfersize &= ~(0xFF); diff --git a/components/hal/esp32p4/include/hal/usb_utmi_ll.h b/components/esp_hal_usb/esp32p4/include/hal/usb_utmi_ll.h similarity index 100% rename from components/hal/esp32p4/include/hal/usb_utmi_ll.h rename to components/esp_hal_usb/esp32p4/include/hal/usb_utmi_ll.h diff --git a/components/hal/esp32p4/include/hal/usb_wrap_ll.h b/components/esp_hal_usb/esp32p4/include/hal/usb_wrap_ll.h similarity index 99% rename from components/hal/esp32p4/include/hal/usb_wrap_ll.h rename to components/esp_hal_usb/esp32p4/include/hal/usb_wrap_ll.h index 212a7f9dae8..30d164bea6c 100644 --- a/components/hal/esp32p4/include/hal/usb_wrap_ll.h +++ b/components/esp_hal_usb/esp32p4/include/hal/usb_wrap_ll.h @@ -19,7 +19,6 @@ #define USB_WRAP_LL_SELECT_PHY_SUPPORTED 1 // Can swap to another internal FSLS PHY - #ifdef __cplusplus extern "C" { #endif diff --git a/components/soc/esp32p4/usb_dwc_periph.c b/components/esp_hal_usb/esp32p4/usb_dwc_periph.c similarity index 100% rename from components/soc/esp32p4/usb_dwc_periph.c rename to components/esp_hal_usb/esp32p4/usb_dwc_periph.c diff --git a/components/hal/esp32s2/include/hal/usb_dwc_ll.h b/components/esp_hal_usb/esp32s2/include/hal/usb_dwc_ll.h similarity index 98% rename from components/hal/esp32s2/include/hal/usb_dwc_ll.h rename to components/esp_hal_usb/esp32s2/include/hal/usb_dwc_ll.h index d3eef71367b..aaa8cc64681 100644 --- a/components/hal/esp32s2/include/hal/usb_dwc_ll.h +++ b/components/esp_hal_usb/esp32s2/include/hal/usb_dwc_ll.h @@ -164,7 +164,6 @@ typedef struct { uint8_t *buffer; } usb_dwc_ll_dma_qtd_t; - /* ----------------------------------------------------------------------------- ------------------------------- Global Registers ------------------------------- ----------------------------------------------------------------------------- */ @@ -398,18 +397,18 @@ static inline void usb_dwc_ll_hcfg_set_num_frame_list_entries(usb_dwc_dev_t *hw, { uint32_t frlisten; switch (num_entries) { - case USB_HAL_FRAME_LIST_LEN_8: - frlisten = 0; - break; - case USB_HAL_FRAME_LIST_LEN_16: - frlisten = 1; - break; - case USB_HAL_FRAME_LIST_LEN_32: - frlisten = 2; - break; - default: //USB_HAL_FRAME_LIST_LEN_64 - frlisten = 3; - break; + case USB_HAL_FRAME_LIST_LEN_8: + frlisten = 0; + break; + case USB_HAL_FRAME_LIST_LEN_16: + frlisten = 1; + break; + case USB_HAL_FRAME_LIST_LEN_32: + frlisten = 2; + break; + default: //USB_HAL_FRAME_LIST_LEN_64 + frlisten = 3; + break; } hw->hcfg_reg.frlisten = frlisten; } diff --git a/components/hal/esp32s2/include/hal/usb_wrap_ll.h b/components/esp_hal_usb/esp32s2/include/hal/usb_wrap_ll.h similarity index 99% rename from components/hal/esp32s2/include/hal/usb_wrap_ll.h rename to components/esp_hal_usb/esp32s2/include/hal/usb_wrap_ll.h index d8dae2a747b..a9619fcaa51 100644 --- a/components/hal/esp32s2/include/hal/usb_wrap_ll.h +++ b/components/esp_hal_usb/esp32s2/include/hal/usb_wrap_ll.h @@ -17,7 +17,6 @@ #define USB_WRAP_LL_EXT_PHY_SUPPORTED 1 // Can route to an external FSLS PHY - #ifdef __cplusplus extern "C" { #endif diff --git a/components/soc/esp32s2/usb_dwc_periph.c b/components/esp_hal_usb/esp32s2/usb_dwc_periph.c similarity index 100% rename from components/soc/esp32s2/usb_dwc_periph.c rename to components/esp_hal_usb/esp32s2/usb_dwc_periph.c diff --git a/components/hal/esp32s3/include/hal/usb_dwc_ll.h b/components/esp_hal_usb/esp32s3/include/hal/usb_dwc_ll.h similarity index 98% rename from components/hal/esp32s3/include/hal/usb_dwc_ll.h rename to components/esp_hal_usb/esp32s3/include/hal/usb_dwc_ll.h index 32f7469a3e3..da560893636 100644 --- a/components/hal/esp32s3/include/hal/usb_dwc_ll.h +++ b/components/esp_hal_usb/esp32s3/include/hal/usb_dwc_ll.h @@ -164,7 +164,6 @@ typedef struct { uint8_t *buffer; } usb_dwc_ll_dma_qtd_t; - /* ----------------------------------------------------------------------------- ------------------------------- Global Registers ------------------------------- ----------------------------------------------------------------------------- */ @@ -398,18 +397,18 @@ static inline void usb_dwc_ll_hcfg_set_num_frame_list_entries(usb_dwc_dev_t *hw, { uint32_t frlisten; switch (num_entries) { - case USB_HAL_FRAME_LIST_LEN_8: - frlisten = 0; - break; - case USB_HAL_FRAME_LIST_LEN_16: - frlisten = 1; - break; - case USB_HAL_FRAME_LIST_LEN_32: - frlisten = 2; - break; - default: //USB_HAL_FRAME_LIST_LEN_64 - frlisten = 3; - break; + case USB_HAL_FRAME_LIST_LEN_8: + frlisten = 0; + break; + case USB_HAL_FRAME_LIST_LEN_16: + frlisten = 1; + break; + case USB_HAL_FRAME_LIST_LEN_32: + frlisten = 2; + break; + default: //USB_HAL_FRAME_LIST_LEN_64 + frlisten = 3; + break; } hw->hcfg_reg.frlisten = frlisten; } diff --git a/components/hal/esp32s3/include/hal/usb_wrap_ll.h b/components/esp_hal_usb/esp32s3/include/hal/usb_wrap_ll.h similarity index 99% rename from components/hal/esp32s3/include/hal/usb_wrap_ll.h rename to components/esp_hal_usb/esp32s3/include/hal/usb_wrap_ll.h index 409e751ca2d..42a557b2a22 100644 --- a/components/hal/esp32s3/include/hal/usb_wrap_ll.h +++ b/components/esp_hal_usb/esp32s3/include/hal/usb_wrap_ll.h @@ -18,7 +18,6 @@ #define USB_WRAP_LL_EXT_PHY_SUPPORTED 1 // Can route to an external FSLS PHY - #ifdef __cplusplus extern "C" { #endif diff --git a/components/soc/esp32s3/usb_dwc_periph.c b/components/esp_hal_usb/esp32s3/usb_dwc_periph.c similarity index 100% rename from components/soc/esp32s3/usb_dwc_periph.c rename to components/esp_hal_usb/esp32s3/usb_dwc_periph.c diff --git a/components/hal/include/hal/usb_dwc_hal.h b/components/esp_hal_usb/include/hal/usb_dwc_hal.h similarity index 98% rename from components/hal/include/hal/usb_dwc_hal.h rename to components/esp_hal_usb/include/hal/usb_dwc_hal.h index d6eab592221..e703f20cfc9 100644 --- a/components/hal/include/hal/usb_dwc_hal.h +++ b/components/esp_hal_usb/include/hal/usb_dwc_hal.h @@ -263,7 +263,6 @@ void usb_dwc_hal_core_soft_reset(usb_dwc_hal_context_t *hal); */ bool usb_dwc_hal_fifo_config_is_valid(const usb_dwc_hal_context_t *hal, const usb_dwc_hal_fifo_config_t *config); - /** * @brief Set the FIFO sizes of the USB-DWC core * @@ -759,14 +758,14 @@ static inline void usb_dwc_hal_xfer_desc_fill(void *desc_list, uint32_t desc_idx usb_dwc_ll_dma_qtd_t *qtd_list = (usb_dwc_ll_dma_qtd_t *)desc_list; if (flags & USB_DWC_HAL_XFER_DESC_FLAG_IN) { usb_dwc_ll_qtd_set_in(&qtd_list[desc_idx], - xfer_data_buff, xfer_len, - flags & USB_DWC_HAL_XFER_DESC_FLAG_HOC); + xfer_data_buff, xfer_len, + flags & USB_DWC_HAL_XFER_DESC_FLAG_HOC); } else { usb_dwc_ll_qtd_set_out(&qtd_list[desc_idx], - xfer_data_buff, - xfer_len, - flags & USB_DWC_HAL_XFER_DESC_FLAG_HOC, - flags & USB_DWC_HAL_XFER_DESC_FLAG_SETUP); + xfer_data_buff, + xfer_len, + flags & USB_DWC_HAL_XFER_DESC_FLAG_HOC, + flags & USB_DWC_HAL_XFER_DESC_FLAG_SETUP); } } diff --git a/components/hal/include/hal/usb_dwc_types.h b/components/esp_hal_usb/include/hal/usb_dwc_types.h similarity index 100% rename from components/hal/include/hal/usb_dwc_types.h rename to components/esp_hal_usb/include/hal/usb_dwc_types.h diff --git a/components/hal/include/hal/usb_phy_types.h b/components/esp_hal_usb/include/hal/usb_phy_types.h similarity index 100% rename from components/hal/include/hal/usb_phy_types.h rename to components/esp_hal_usb/include/hal/usb_phy_types.h diff --git a/components/hal/include/hal/usb_utmi_hal.h b/components/esp_hal_usb/include/hal/usb_utmi_hal.h similarity index 100% rename from components/hal/include/hal/usb_utmi_hal.h rename to components/esp_hal_usb/include/hal/usb_utmi_hal.h diff --git a/components/hal/include/hal/usb_wrap_hal.h b/components/esp_hal_usb/include/hal/usb_wrap_hal.h similarity index 100% rename from components/hal/include/hal/usb_wrap_hal.h rename to components/esp_hal_usb/include/hal/usb_wrap_hal.h diff --git a/components/hal/include/hal/usb_wrap_types.h b/components/esp_hal_usb/include/hal/usb_wrap_types.h similarity index 100% rename from components/hal/include/hal/usb_wrap_types.h rename to components/esp_hal_usb/include/hal/usb_wrap_types.h diff --git a/components/soc/include/soc/usb_periph.h b/components/esp_hal_usb/include/soc/usb_periph.h similarity index 100% rename from components/soc/include/soc/usb_periph.h rename to components/esp_hal_usb/include/soc/usb_periph.h diff --git a/components/hal/usb_dwc_hal.c b/components/esp_hal_usb/usb_dwc_hal.c similarity index 98% rename from components/hal/usb_dwc_hal.c rename to components/esp_hal_usb/usb_dwc_hal.c index fa46d8228cb..db889e61218 100644 --- a/components/hal/usb_dwc_hal.c +++ b/components/esp_hal_usb/usb_dwc_hal.c @@ -193,7 +193,6 @@ bool usb_dwc_hal_fifo_config_is_valid(const usb_dwc_hal_context_t *hal, const us return (used_lines <= hal->constant_config.fifo_size); } - void usb_dwc_hal_set_fifo_config(usb_dwc_hal_context_t *hal, const usb_dwc_hal_fifo_config_t *config) { // Check internal HAL state @@ -330,12 +329,12 @@ void usb_dwc_hal_chan_set_ep_char(usb_dwc_hal_context_t *hal, usb_dwc_hal_chan_t HAL_ASSERT(!chan_obj->flags.active); //Set the endpoint characteristics of the pipe usb_dwc_ll_hcchar_init(chan_obj->regs, - ep_char->dev_addr, - ep_char->bEndpointAddress & BENDPOINTADDRESS_NUM_MSK, - ep_char->mps, - ep_char->type, - ep_char->bEndpointAddress & BENDPOINTADDRESS_DIR_MSK, - ep_char->ls_via_fs_hub); + ep_char->dev_addr, + ep_char->bEndpointAddress & BENDPOINTADDRESS_NUM_MSK, + ep_char->mps, + ep_char->type, + ep_char->bEndpointAddress & BENDPOINTADDRESS_DIR_MSK, + ep_char->ls_via_fs_hub); //Save channel type chan_obj->type = ep_char->type; //If this is a periodic endpoint/channel, set its schedule in the frame list @@ -365,7 +364,7 @@ void usb_dwc_hal_chan_set_ep_char(usb_dwc_hal_context_t *hal, usb_dwc_hal_chan_t interval_frame_list = 1; } // Schedule the channel in the frame list - for (int i = 0; i < hal->frame_list_len; i+= interval_frame_list) { + for (int i = 0; i < hal->frame_list_len; i += interval_frame_list) { int index = (offset_frame_list + i) % hal->frame_list_len; hal->periodic_frame_list[index] |= 1 << chan_obj->flags.chan_idx; } diff --git a/components/hal/usb_utmi_hal.c b/components/esp_hal_usb/usb_utmi_hal.c similarity index 100% rename from components/hal/usb_utmi_hal.c rename to components/esp_hal_usb/usb_utmi_hal.c diff --git a/components/hal/usb_wrap_hal.c b/components/esp_hal_usb/usb_wrap_hal.c similarity index 100% rename from components/hal/usb_wrap_hal.c rename to components/esp_hal_usb/usb_wrap_hal.c diff --git a/components/esp_hw_support/CMakeLists.txt b/components/esp_hw_support/CMakeLists.txt index 9005a47f248..9399a8c92c5 100644 --- a/components/esp_hw_support/CMakeLists.txt +++ b/components/esp_hw_support/CMakeLists.txt @@ -9,7 +9,7 @@ if(${target} STREQUAL "linux") return() endif() -set(requires esp_hal_dma) +set(requires esp_hal_dma esp_hal_usb) # only esp_hw_support/adc_share_hw_ctrl.c requires efuse component set(priv_requires efuse spi_flash bootloader_support esp_hal_wdt) diff --git a/components/hal/CMakeLists.txt b/components/hal/CMakeLists.txt index 561d2820c3d..b581f7adbc7 100644 --- a/components/hal/CMakeLists.txt +++ b/components/hal/CMakeLists.txt @@ -239,16 +239,6 @@ elseif(NOT BOOTLOADER_BUILD) list(APPEND srcs "usb_serial_jtag_hal.c") endif() - if(CONFIG_SOC_USB_UTMI_PHY_NUM GREATER 0) - list(APPEND srcs "usb_utmi_hal.c") - endif() - - if(CONFIG_SOC_USB_OTG_SUPPORTED) - list(APPEND srcs - "usb_dwc_hal.c" - "usb_wrap_hal.c") - endif() - if(CONFIG_SOC_TOUCH_SENSOR_SUPPORTED) # Source files for the legacy touch hal driver if(CONFIG_SOC_TOUCH_SENSOR_VERSION LESS 3) diff --git a/components/soc/CMakeLists.txt b/components/soc/CMakeLists.txt index a00a3671ff6..e9d45a4f327 100644 --- a/components/soc/CMakeLists.txt +++ b/components/soc/CMakeLists.txt @@ -158,10 +158,6 @@ if(CONFIG_SOC_IEEE802154_SUPPORTED) endif() endif() -if(CONFIG_SOC_USB_OTG_SUPPORTED) - list(APPEND srcs "${target_folder}/usb_dwc_periph.c") -endif() - if(CONFIG_SOC_DAC_SUPPORTED) list(APPEND srcs "${target_folder}/dac_periph.c") endif() diff --git a/examples/peripherals/.build-test-rules.yml b/examples/peripherals/.build-test-rules.yml index 4e2b89da403..e113f93d374 100644 --- a/examples/peripherals/.build-test-rules.yml +++ b/examples/peripherals/.build-test-rules.yml @@ -560,6 +560,9 @@ examples/peripherals/usb/device: depends_components: - fatfs depends_filepatterns: + - components/soc/esp32*/include/soc/usb_dwc_struct.h + - components/esp_hw_support/usb_phy/usb_phy.c + - components/esp_hw_support/include/esp_private/usb_phy.h - examples/peripherals/usb/device/**/* examples/peripherals/usb/device/cherryusb_serial_device: @@ -589,14 +592,9 @@ examples/peripherals/usb/host: reason: lack of runners with usb_host_flash_disk tag depends_components: - fatfs + - esp_hal_usb depends_filepatterns: - - components/hal/usb*.c - - components/hal/include/hal/usb*.h - - components/hal/esp32*/include/hal/usb*.h - - components/soc/esp32*/usb*.c - - components/soc/include/soc/usb*.h - - components/soc/esp32*/include/soc/usb_dwc_*.h - - components/soc/esp32*/include/soc/usb_wrap_*.h + - components/soc/esp32*/include/soc/usb_dwc_struct.h - components/esp_hw_support/usb_phy/usb_phy.c - components/esp_hw_support/include/esp_private/usb_phy.h - examples/peripherals/usb/host/**/* From 10cefdd975efa422293c873746dae94e42d9a25e Mon Sep 17 00:00:00 2001 From: "harshal.patil" Date: Thu, 30 Oct 2025 17:27:25 +0530 Subject: [PATCH 047/106] fix(mbedtls/port): Align AES and SHA DMA buffers to 16 when SPIRAM encryption is enabled - Targets that support GDMA and MSPI encryption module need data and addresses aligned to 16 --- components/mbedtls/CMakeLists.txt | 3 -- .../mbedtls/port/aes/dma/esp_aes_dma_core.c | 48 +++++++++++++------ .../esp_crypto_shared_gdma.c | 44 +++++++++++------ components/mbedtls/port/sha/core/sha.c | 46 ++++++++++-------- .../esp32c5/include/soc/Kconfig.soc_caps.in | 4 ++ components/soc/esp32c5/include/soc/soc_caps.h | 1 + .../esp32c61/include/soc/Kconfig.soc_caps.in | 4 ++ .../soc/esp32c61/include/soc/soc_caps.h | 1 + .../esp32p4/include/soc/Kconfig.soc_caps.in | 2 +- components/soc/esp32p4/include/soc/soc_caps.h | 2 +- 10 files changed, 100 insertions(+), 55 deletions(-) diff --git a/components/mbedtls/CMakeLists.txt b/components/mbedtls/CMakeLists.txt index 30845c211f5..bcda4d69ae9 100644 --- a/components/mbedtls/CMakeLists.txt +++ b/components/mbedtls/CMakeLists.txt @@ -242,9 +242,6 @@ endif() if((SHA_PERIPHERAL_TYPE STREQUAL "core" AND CONFIG_SOC_SHA_SUPPORT_DMA) OR CONFIG_SOC_AES_SUPPORT_DMA) target_link_libraries(mbedcrypto PRIVATE idf::esp_mm) if(CONFIG_SOC_SHA_GDMA OR CONFIG_SOC_AES_GDMA) - if(CONFIG_SOC_AXI_DMA_EXT_MEM_ENC_ALIGNMENT) - target_link_libraries(mbedcrypto PRIVATE idf::bootloader_support) - endif() target_sources(mbedcrypto PRIVATE "${COMPONENT_DIR}/port/crypto_shared_gdma/esp_crypto_shared_gdma.c") endif() endif() diff --git a/components/mbedtls/port/aes/dma/esp_aes_dma_core.c b/components/mbedtls/port/aes/dma/esp_aes_dma_core.c index a4a3d7c43bf..4cb5cd4429c 100644 --- a/components/mbedtls/port/aes/dma/esp_aes_dma_core.c +++ b/components/mbedtls/port/aes/dma/esp_aes_dma_core.c @@ -41,9 +41,9 @@ #include "aes/esp_aes_gcm.h" #endif -#ifdef SOC_AXI_DMA_EXT_MEM_ENC_ALIGNMENT -#include "esp_flash_encrypt.h" -#endif /* SOC_AXI_DMA_EXT_MEM_ENC_ALIGNMENT */ +#ifdef SOC_GDMA_EXT_MEM_ENC_ALIGNMENT +#include "hal/efuse_hal.h" +#endif /* SOC_GDMA_EXT_MEM_ENC_ALIGNMENT */ /* Max size of each chunk to process when output buffer is in unaligned external ram must be a multiple of block size @@ -241,17 +241,17 @@ static int esp_aes_process_dma_ext_ram(esp_aes_context *ctx, const unsigned char /* When AES-DMA operations are carried out using external memory with external memory encryption enabled, we need to make sure that the addresses and the sizes of the buffers on which the DMA operates are 16 byte-aligned. */ -#ifdef SOC_AXI_DMA_EXT_MEM_ENC_ALIGNMENT - if (esp_flash_encryption_enabled()) { +#ifdef SOC_GDMA_EXT_MEM_ENC_ALIGNMENT + if (efuse_hal_flash_encryption_enabled()) { if (esp_ptr_external_ram(input) || esp_ptr_external_ram(output) || esp_ptr_in_drom(input) || esp_ptr_in_drom(output)) { - input_alignment = MAX(get_cache_line_size(input), SOC_AXI_DMA_EXT_MEM_ENC_ALIGNMENT); - output_alignment = MAX(get_cache_line_size(output), SOC_AXI_DMA_EXT_MEM_ENC_ALIGNMENT); + input_alignment = MAX(get_cache_line_size(input), SOC_GDMA_EXT_MEM_ENC_ALIGNMENT); + output_alignment = MAX(get_cache_line_size(output), SOC_GDMA_EXT_MEM_ENC_ALIGNMENT); input_heap_caps = MALLOC_CAP_8BIT | (esp_ptr_external_ram(input) ? MALLOC_CAP_SPIRAM : MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL); output_heap_caps = MALLOC_CAP_8BIT | (esp_ptr_external_ram(output) ? MALLOC_CAP_SPIRAM : MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL); } } -#endif /* SOC_AXI_DMA_EXT_MEM_ENC_ALIGNMENT */ +#endif /* SOC_GDMA_EXT_MEM_ENC_ALIGNMENT */ if (realloc_input) { input_buf = heap_caps_aligned_alloc(input_alignment, chunk_len, input_heap_caps); @@ -537,19 +537,19 @@ int esp_aes_process_dma(esp_aes_context *ctx, const unsigned char *input, unsign return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; } -#ifdef SOC_AXI_DMA_EXT_MEM_ENC_ALIGNMENT - if (esp_flash_encryption_enabled()) { +#ifdef SOC_GDMA_EXT_MEM_ENC_ALIGNMENT + if (efuse_hal_flash_encryption_enabled()) { if (esp_ptr_external_ram(input) || esp_ptr_external_ram(output) || esp_ptr_in_drom(input) || esp_ptr_in_drom(output)) { - if (((intptr_t)(input) & (SOC_AXI_DMA_EXT_MEM_ENC_ALIGNMENT - 1)) != 0) { + if (((intptr_t)(input) & (SOC_GDMA_EXT_MEM_ENC_ALIGNMENT - 1)) != 0) { input_needs_realloc = true; } - if (((intptr_t)(output) & (SOC_AXI_DMA_EXT_MEM_ENC_ALIGNMENT - 1)) != 0) { + if (((intptr_t)(output) & (SOC_GDMA_EXT_MEM_ENC_ALIGNMENT - 1)) != 0) { output_needs_realloc = true; } } } -#endif /* SOC_AXI_DMA_EXT_MEM_ENC_ALIGNMENT */ +#endif /* SOC_GDMA_EXT_MEM_ENC_ALIGNMENT */ /* DMA cannot access memory in the iCache range, copy input to internal ram */ if (!s_check_dma_capable(input)) { @@ -1002,6 +1002,20 @@ int esp_aes_process_dma(esp_aes_context *ctx, const unsigned char *input, unsign if (block_bytes > 0) { /* Flush cache if input in external ram */ #if (CONFIG_SPIRAM && SOC_PSRAM_DMA_CAPABLE) +#ifdef SOC_GDMA_EXT_MEM_ENC_ALIGNMENT + if (efuse_hal_flash_encryption_enabled()) { + if (esp_ptr_external_ram(input) || esp_ptr_external_ram(output) || esp_ptr_in_drom(input) || esp_ptr_in_drom(output)) { + if (((intptr_t)(input) & (SOC_GDMA_EXT_MEM_ENC_ALIGNMENT - 1)) != 0) { + input_needs_realloc = true; + } + + if (((intptr_t)(output) & (SOC_GDMA_EXT_MEM_ENC_ALIGNMENT - 1)) != 0) { + output_needs_realloc = true; + } + } + } +#endif /* SOC_GDMA_EXT_MEM_ENC_ALIGNMENT */ + if (esp_ptr_external_ram(input)) { if (esp_cache_msync((void *)input, len, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED) != ESP_OK) { mbedtls_platform_zeroize(output, len); @@ -1049,12 +1063,18 @@ int esp_aes_process_dma(esp_aes_context *ctx, const unsigned char *input, unsign block_in_desc = block_desc; block_out_desc = block_desc + crypto_dma_desc_num; +#if SOC_AHB_GDMA_VERSION == 2 + // Limit max inlink descriptor length to be 16 byte aligned, as buffer sizes need to be 16 byte aligned + // when Flash Encryption is enabled. + dma_desc_setup_link(block_in_desc, input, block_bytes, DMA_DESCRIPTOR_BUFFER_MAX_SIZE_16B_ALIGNED, 0); +#else // the size field has 12 bits, but 0 not for 4096. // to avoid possible problem when the size is not word-aligned, we only use 4096-4 per desc. // Maximum size of data in the buffer that a DMA descriptor can hold. dma_desc_setup_link(block_in_desc, input, block_bytes, DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED, 0); +#endif - //Limit max inlink descriptor length to be 16 byte aligned, require for EDMA + //Limit max outlink descriptor length to be 16 byte aligned, require for EDMA dma_desc_setup_link(block_out_desc, output, block_bytes, DMA_DESCRIPTOR_BUFFER_MAX_SIZE_16B_ALIGNED, 0); /* Setup in/out start descriptors */ diff --git a/components/mbedtls/port/crypto_shared_gdma/esp_crypto_shared_gdma.c b/components/mbedtls/port/crypto_shared_gdma/esp_crypto_shared_gdma.c index fb0d538e38d..05fb8fe0506 100644 --- a/components/mbedtls/port/crypto_shared_gdma/esp_crypto_shared_gdma.c +++ b/components/mbedtls/port/crypto_shared_gdma/esp_crypto_shared_gdma.c @@ -17,14 +17,16 @@ #include "soc/soc_caps.h" #include "sdkconfig.h" -#ifdef SOC_AXI_DMA_EXT_MEM_ENC_ALIGNMENT -#include "esp_flash_encrypt.h" -#endif /* SOC_AXI_DMA_EXT_MEM_ENC_ALIGNMENT */ +#ifdef SOC_GDMA_EXT_MEM_ENC_ALIGNMENT +#include "hal/efuse_hal.h" +#endif /* SOC_GDMA_EXT_MEM_ENC_ALIGNMENT */ -#if SOC_AHB_GDMA_VERSION == 1 -#include "hal/gdma_ll.h" -#elif SOC_AXI_GDMA_SUPPORTED +#if SOC_AXI_GDMA_SUPPORTED #include "hal/axi_dma_ll.h" +#elif SOC_AHB_GDMA_VERSION == 1 +#include "hal/gdma_ll.h" +#elif SOC_AHB_GDMA_VERSION == 2 +#include "hal/ahb_dma_ll.h" #endif /* SOC_AHB_GDMA_VERSION */ #define NEW_CHANNEL_TIMEOUT_MS 1000 @@ -89,7 +91,16 @@ static esp_err_t crypto_shared_gdma_init(void) .access_ext_mem = true, // crypto peripheral may want to access PSRAM }; gdma_config_transfer(tx_channel, &transfer_cfg); + + /* When using AHB-GDMA version 1, the max data burst size must be 0, otherwise buffers need to be aligned as well. + * Whereas, in case of the other GDMA versions, the RX max burst size is default enabled, but with default burst size of 4, + * but it case of Flash Encryption, the buffers can be allocated from the external memory, which requires 16 byte alignment. + * Thus, we set the max data burst size to 16, similar to the TX channel. + */ +#if SOC_AHB_GDMA_VERSION == 1 || SOC_AXI_GDMA_SUPPORTED // IDF-14335: SOC_AXI_GDMA_SUPPORTED might not be needed here transfer_cfg.max_data_burst_size = 0; +#endif + gdma_config_transfer(rx_channel, &transfer_cfg); #ifdef SOC_AES_SUPPORTED @@ -112,7 +123,7 @@ err: /* The external memory ecc-aes access must be enabled when there exists at least one buffer in the DMA descriptors that resides in external memory. */ -#ifdef SOC_AXI_DMA_EXT_MEM_ENC_ALIGNMENT +#if (SOC_GDMA_EXT_MEM_ENC_ALIGNMENT && SOC_AXI_GDMA_SUPPORTED) static bool check_dma_descs_need_ext_mem_ecc_aes_access(const crypto_dma_desc_t *dmadesc) { crypto_dma_desc_t* desc = (crypto_dma_desc_t*) dmadesc; @@ -124,7 +135,7 @@ static bool check_dma_descs_need_ext_mem_ecc_aes_access(const crypto_dma_desc_t } return false; } -#endif /* SOC_AXI_DMA_EXT_MEM_ENC_ALIGNMENT */ +#endif /* (SOC_GDMA_EXT_MEM_ENC_ALIGNMENT && SOC_AXI_GDMA_SUPPORTED) */ esp_err_t esp_crypto_shared_gdma_start_axi_ahb(const crypto_dma_desc_t *input, const crypto_dma_desc_t *output, gdma_trigger_peripheral_t peripheral) { @@ -159,16 +170,19 @@ esp_err_t esp_crypto_shared_gdma_start_axi_ahb(const crypto_dma_desc_t *input, c /* tx channel is reset by gdma_connect(), also reset rx to ensure a known state */ gdma_get_channel_id(rx_channel, &rx_ch_id); -#if SOC_AHB_GDMA_VERSION == 1 - gdma_ll_rx_reset_channel(&GDMA, rx_ch_id); -#elif SOC_AXI_GDMA_SUPPORTED + // IDF-14335: Use gdma_reset() instead +#if SOC_AXI_GDMA_SUPPORTED axi_dma_ll_rx_reset_channel(&AXI_DMA, rx_ch_id); -#endif /* SOC_AHB_GDMA_VERSION */ +#elif SOC_AHB_GDMA_VERSION == 1 + gdma_ll_rx_reset_channel(&GDMA, rx_ch_id); +#elif SOC_AHB_GDMA_VERSION == 2 + ahb_dma_ll_rx_reset_channel(&AHB_DMA, rx_ch_id); +#endif /* SOC_AXI_GDMA_SUPPORTED */ /* When GDMA operations are carried out using external memory with external memory encryption enabled, we need to enable AXI-DMA's AES-ECC mean access bit. */ -#if (SOC_AXI_DMA_EXT_MEM_ENC_ALIGNMENT) - if (esp_flash_encryption_enabled()) { +#if (SOC_GDMA_EXT_MEM_ENC_ALIGNMENT && SOC_AXI_GDMA_SUPPORTED) + if (efuse_hal_flash_encryption_enabled()) { int tx_ch_id = 0; gdma_get_channel_id(tx_channel, &tx_ch_id); @@ -180,7 +194,7 @@ esp_err_t esp_crypto_shared_gdma_start_axi_ahb(const crypto_dma_desc_t *input, c axi_dma_ll_tx_enable_ext_mem_ecc_aes_access(&AXI_DMA, tx_ch_id, false); } } -#endif /* SOC_AXI_DMA_EXT_MEM_ENC_ALIGNMENT */ +#endif /* SOC_GDMA_EXT_MEM_ENC_ALIGNMENT */ gdma_start(tx_channel, (intptr_t)input); gdma_start(rx_channel, (intptr_t)output); diff --git a/components/mbedtls/port/sha/core/sha.c b/components/mbedtls/port/sha/core/sha.c index 8aa2f1e0e11..eb905d4bb50 100644 --- a/components/mbedtls/port/sha/core/sha.c +++ b/components/mbedtls/port/sha/core/sha.c @@ -43,9 +43,9 @@ #include "esp_sha_dma_priv.h" #include "sdkconfig.h" -#ifdef SOC_AXI_DMA_EXT_MEM_ENC_ALIGNMENT -#include "esp_flash_encrypt.h" -#endif /* SOC_AXI_DMA_EXT_MEM_ENC_ALIGNMENT */ +#ifdef SOC_GDMA_EXT_MEM_ENC_ALIGNMENT +#include "hal/efuse_hal.h" +#endif /* SOC_GDMA_EXT_MEM_ENC_ALIGNMENT */ #if SOC_SHA_CRYPTO_DMA #include "hal/crypto_dma_ll.h" @@ -154,7 +154,7 @@ static DRAM_ATTR crypto_dma_desc_t s_dma_descr_buf; static esp_err_t esp_sha_dma_process(esp_sha_type sha_type, const void *input, uint32_t ilen, const void *buf, uint32_t buf_len, bool is_first_block); -#ifdef SOC_AXI_DMA_EXT_MEM_ENC_ALIGNMENT +#ifdef SOC_GDMA_EXT_MEM_ENC_ALIGNMENT static esp_err_t esp_sha_dma_process_ext(esp_sha_type sha_type, const void *input, uint32_t ilen, const void *buf, uint32_t buf_len, bool is_first_block, bool realloc_input, bool realloc_buf) @@ -170,7 +170,7 @@ static esp_err_t esp_sha_dma_process_ext(esp_sha_type sha_type, const void *inpu if (realloc_input) { heap_caps = MALLOC_CAP_8BIT | (esp_ptr_external_ram(input) ? MALLOC_CAP_SPIRAM : MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL); - input_copy = heap_caps_aligned_alloc(SOC_AXI_DMA_EXT_MEM_ENC_ALIGNMENT, ilen, heap_caps); + input_copy = heap_caps_aligned_alloc(SOC_GDMA_EXT_MEM_ENC_ALIGNMENT, ilen, heap_caps); if (input_copy == NULL) { ESP_LOGE(TAG, "Failed to allocate aligned SPIRAM memory"); return ret; @@ -183,7 +183,7 @@ static esp_err_t esp_sha_dma_process_ext(esp_sha_type sha_type, const void *inpu if (realloc_buf) { heap_caps = MALLOC_CAP_8BIT | (esp_ptr_external_ram(buf) ? MALLOC_CAP_SPIRAM : MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL); - buf_copy = heap_caps_aligned_alloc(SOC_AXI_DMA_EXT_MEM_ENC_ALIGNMENT, buf_len, heap_caps); + buf_copy = heap_caps_aligned_alloc(SOC_GDMA_EXT_MEM_ENC_ALIGNMENT, buf_len, heap_caps); if (buf_copy == NULL) { ESP_LOGE(TAG, "Failed to allocate aligned internal memory"); return ret; @@ -206,7 +206,7 @@ static esp_err_t esp_sha_dma_process_ext(esp_sha_type sha_type, const void *inpu return ret; } -#endif /* SOC_AXI_DMA_EXT_MEM_ENC_ALIGNMENT */ +#endif /* SOC_GDMA_EXT_MEM_ENC_ALIGNMENT */ /* Performs SHA on multiple blocks at a time */ static esp_err_t esp_sha_dma_process(esp_sha_type sha_type, const void *input, uint32_t ilen, @@ -227,17 +227,17 @@ static esp_err_t esp_sha_dma_process(esp_sha_type sha_type, const void *input, u /* When SHA-DMA operations are carried out using external memory with external memory encryption enabled, we need to make sure that the addresses and the sizes of the buffers on which the DMA operates are 16 byte-aligned. */ -#ifdef SOC_AXI_DMA_EXT_MEM_ENC_ALIGNMENT - if (esp_flash_encryption_enabled()) { +#ifdef SOC_GDMA_EXT_MEM_ENC_ALIGNMENT + if (efuse_hal_flash_encryption_enabled()) { if (esp_ptr_external_ram(input) || esp_ptr_external_ram(buf) || esp_ptr_in_drom(input) || esp_ptr_in_drom(buf)) { bool input_needs_realloc = false; bool buf_needs_realloc = false; - if (ilen && ((intptr_t)(input) & (SOC_AXI_DMA_EXT_MEM_ENC_ALIGNMENT - 1)) != 0) { + if (ilen && ((intptr_t)(input) & (SOC_GDMA_EXT_MEM_ENC_ALIGNMENT - 1)) != 0) { input_needs_realloc = true; } - if (buf_len && ((intptr_t)(buf) & (SOC_AXI_DMA_EXT_MEM_ENC_ALIGNMENT - 1)) != 0) { + if (buf_len && ((intptr_t)(buf) & (SOC_GDMA_EXT_MEM_ENC_ALIGNMENT - 1)) != 0) { buf_needs_realloc = true; } @@ -246,7 +246,7 @@ static esp_err_t esp_sha_dma_process(esp_sha_type sha_type, const void *input, u } } } -#endif /* SOC_AXI_DMA_EXT_MEM_ENC_ALIGNMENT */ +#endif /* SOC_GDMA_EXT_MEM_ENC_ALIGNMENT */ /* DMA descriptor for Memory to DMA-SHA transfer */ if (ilen) { @@ -273,6 +273,19 @@ static esp_err_t esp_sha_dma_process(esp_sha_type sha_type, const void *input, u s_dma_descr_buf.next = (&s_dma_descr_input); } + /* Write back buffers to memory if they are in external RAM + * The writeback needs to be performed in esp_sha_dma_process() instead of esp_sha_dma() to make + * sure that if the buffers are reallocated, then the writeback is performed on the new buffers. + */ +#if (CONFIG_SPIRAM && SOC_PSRAM_DMA_CAPABLE) + if (esp_ptr_external_ram(input)) { + esp_cache_msync((void *)input, ilen, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED); + } + if (esp_ptr_external_ram(buf)) { + esp_cache_msync((void *)buf, buf_len, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED); + } +#endif + #if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE if (ilen) { ESP_ERROR_CHECK(esp_cache_msync(&s_dma_descr_input, sizeof(crypto_dma_desc_t), ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED)); @@ -317,15 +330,6 @@ int esp_sha_dma(esp_sha_type sha_type, const void *input, uint32_t ilen, return 0; } -#if (CONFIG_SPIRAM && SOC_PSRAM_DMA_CAPABLE) - if (esp_ptr_external_ram(input)) { - esp_cache_msync((void *)input, ilen, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED); - } - if (esp_ptr_external_ram(buf)) { - esp_cache_msync((void *)buf, buf_len, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED); - } -#endif - /* Copy to internal buf if buf is in non DMA capable memory */ if (!s_check_dma_capable(buf) && (buf_len != 0)) { dma_cap_buf = heap_caps_malloc(sizeof(unsigned char) * buf_len, MALLOC_CAP_8BIT|MALLOC_CAP_DMA|MALLOC_CAP_INTERNAL); diff --git a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in index 6c7cac4940f..76a9513994d 100644 --- a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in @@ -519,6 +519,10 @@ config SOC_GDMA_SUPPORT_WEIGHTED_ARBITRATION bool default y +config SOC_GDMA_EXT_MEM_ENC_ALIGNMENT + int + default 16 + config SOC_GPIO_PORT int default 1 diff --git a/components/soc/esp32c5/include/soc/soc_caps.h b/components/soc/esp32c5/include/soc/soc_caps.h index 6ae6518c4cf..d81ab6e5e44 100644 --- a/components/soc/esp32c5/include/soc/soc_caps.h +++ b/components/soc/esp32c5/include/soc/soc_caps.h @@ -203,6 +203,7 @@ #define SOC_GDMA_SUPPORT_ETM 1 #define SOC_GDMA_SUPPORT_SLEEP_RETENTION 1 #define SOC_GDMA_SUPPORT_WEIGHTED_ARBITRATION 1 +#define SOC_GDMA_EXT_MEM_ENC_ALIGNMENT (16) /*-------------------------- GPIO CAPS ---------------------------------------*/ // ESP32-C5 has 1 GPIO peripheral diff --git a/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in index 7c3e574238d..7ab8a3c1a2a 100644 --- a/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in @@ -395,6 +395,10 @@ config SOC_GDMA_SUPPORT_WEIGHTED_ARBITRATION bool default y +config SOC_GDMA_EXT_MEM_ENC_ALIGNMENT + int + default 16 + config SOC_ETM_SUPPORT_SLEEP_RETENTION bool default y diff --git a/components/soc/esp32c61/include/soc/soc_caps.h b/components/soc/esp32c61/include/soc/soc_caps.h index e156c5daefd..bd5bf8a0b32 100644 --- a/components/soc/esp32c61/include/soc/soc_caps.h +++ b/components/soc/esp32c61/include/soc/soc_caps.h @@ -159,6 +159,7 @@ #define SOC_GDMA_SUPPORT_ETM 1 // Support ETM submodule #define SOC_GDMA_SUPPORT_SLEEP_RETENTION 1 #define SOC_GDMA_SUPPORT_WEIGHTED_ARBITRATION 1 +#define SOC_GDMA_EXT_MEM_ENC_ALIGNMENT (16) /*-------------------------- ETM CAPS -----------------------------------*/ #define SOC_ETM_SUPPORT_SLEEP_RETENTION 1 diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index 5e0fada7cd5..77ec2cd371c 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -627,7 +627,7 @@ config SOC_GDMA_SUPPORT_SLEEP_RETENTION bool default y -config SOC_AXI_DMA_EXT_MEM_ENC_ALIGNMENT +config SOC_GDMA_EXT_MEM_ENC_ALIGNMENT int default 16 diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index 60bc9e17f60..d946f4a3d3e 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -230,7 +230,7 @@ #define SOC_GDMA_SUPPORT_CRC 1 #define SOC_GDMA_SUPPORT_ETM 1 #define SOC_GDMA_SUPPORT_SLEEP_RETENTION 1 -#define SOC_AXI_DMA_EXT_MEM_ENC_ALIGNMENT (16) +#define SOC_GDMA_EXT_MEM_ENC_ALIGNMENT (16) /*-------------------------- GPIO CAPS ---------------------------------------*/ // ESP32-P4 has 1 GPIO peripheral From 488dcb58e1069419c8c24d2241cf1c47d7cf70d7 Mon Sep 17 00:00:00 2001 From: "harshal.patil" Date: Tue, 4 Nov 2025 15:05:30 +0530 Subject: [PATCH 048/106] fix(esp_security): Fix undefined efuse build failure in case of ESP32-P4 - The `wr_dis` efuse bit corresponding to `SECURE_BOOT_SHA384_EN` is absent in P4 --- components/esp_security/src/init.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/components/esp_security/src/init.c b/components/esp_security/src/init.c index 17196935f30..e886d46d1e5 100644 --- a/components/esp_security/src/init.c +++ b/components/esp_security/src/init.c @@ -106,10 +106,13 @@ ESP_SYSTEM_INIT_FN(esp_security_init, SECONDARY, BIT(0), 103) #if !CONFIG_SECURE_BOOT_SKIP_WRITE_PROTECTION_SCA // C5 -#if SOC_ECDSA_SUPPORT_CURVE_P384 && !CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS +#if SOC_ECDSA_SUPPORT_CURVE_P384 && !CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS && !CONFIG_IDF_TARGET_ESP32P4 // Since SECURE_BOOT_SHA384_EN, XTS_DPA_PSEUDO_LEVEL, and ECC_FORCE_CONST_TIME share the // same write-protection bit, these efuses should only be write-protected after all of // them have been programmed. + // Note: ESP32-P4 lacks WR_DIS_SECURE_BOOT_SHA384_EN bit, so it relies on software protection + // in the efuse write APIs (see esp_efuse_api.c) to prevent unauthorized programming of + // SECURE_BOOT_SHA384_EN when Secure Boot using SHA-256 is enabled. err = esp_efuse_write_field_bit(ESP_EFUSE_WR_DIS_SECURE_BOOT_SHA384_EN); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to write protect the SECURE_BOOT_SHA384_EN efuse bit."); From 54c5c760ba7d1bc3322550a3ec126318acc9c047 Mon Sep 17 00:00:00 2001 From: "harshal.patil" Date: Sun, 26 Oct 2025 15:27:52 +0530 Subject: [PATCH 049/106] fix(esp_security): Set WR_DIS_SECURE_BOOT_SHA384_EN by default when Flash Encryption Release mode is enabled and Secure Boot P384 scheme not is enabled. --- components/bootloader/Kconfig.projbuild | 2 +- components/esp_security/src/init.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/components/bootloader/Kconfig.projbuild b/components/bootloader/Kconfig.projbuild index e2e45a895f4..4878a4d8b22 100644 --- a/components/bootloader/Kconfig.projbuild +++ b/components/bootloader/Kconfig.projbuild @@ -974,7 +974,7 @@ menu "Security features" config SECURE_BOOT_SKIP_WRITE_PROTECTION_SCA bool "Skip write-protection of SECURE_FLASH_PSEUDO_ROUND_FUNC_STRENGTH" - default y if SECURE_FLASH_PSEUDO_ROUND_FUNC + default y if SECURE_FLASH_PSEUDO_ROUND_FUNC && !SECURE_FLASH_ENCRYPTION_MODE_RELEASE default n depends on SOC_ECDSA_SUPPORT_CURVE_P384 && SOC_FLASH_ENCRYPTION_XTS_AES_SUPPORT_PSEUDO_ROUND help diff --git a/components/esp_security/src/init.c b/components/esp_security/src/init.c index e886d46d1e5..9189f90bf3c 100644 --- a/components/esp_security/src/init.c +++ b/components/esp_security/src/init.c @@ -94,7 +94,7 @@ ESP_SYSTEM_INIT_FN(esp_security_init, SECONDARY, BIT(0), 103) #if CONFIG_SECURE_BOOT_V2_ENABLED // H2, H21 #if SOC_ECDSA_P192_CURVE_DEFAULT_DISABLED - // Also write protects the ECDSA_CURVE_MODE efuse bit. + // Also write protects the ECC_FORCE_CONST_TIME efuse bit. if (ecdsa_ll_is_configurable_curve_supported()) { err = esp_efuse_write_field_bit(ESP_EFUSE_WR_DIS_ECDSA_CURVE_MODE); if (err != ESP_OK) { From 3e7602a2e453223205d6b0dbecd8a498554b7f45 Mon Sep 17 00:00:00 2001 From: "harshal.patil" Date: Tue, 7 Oct 2025 14:18:37 +0530 Subject: [PATCH 050/106] feat(cpu_region_protect): Extend PMP memprot for ESP32-P4 V3 --- .../port/esp32p4/cpu_region_protect.c | 273 ++++++++++++++---- components/riscv/include/riscv/csr.h | 20 +- .../system/panic/main/include/test_memprot.h | 26 +- .../system/panic/main/test_app_main.c | 25 ++ .../system/panic/main/test_memprot.c | 114 ++++++++ tools/test_apps/system/panic/pytest_panic.py | 226 ++++++++++++--- .../system/panic/test_panic_util/panic_dut.py | 86 +++--- 7 files changed, 618 insertions(+), 152 deletions(-) diff --git a/components/esp_hw_support/port/esp32p4/cpu_region_protect.c b/components/esp_hw_support/port/esp32p4/cpu_region_protect.c index 52037adba0a..1d7e804a4d8 100644 --- a/components/esp_hw_support/port/esp32p4/cpu_region_protect.c +++ b/components/esp_hw_support/port/esp32p4/cpu_region_protect.c @@ -15,6 +15,9 @@ #include "esp_private/esp_psram_extram.h" #endif /* CONFIG_SPIRAM */ +#include "soc/chip_revision.h" +#include "hal/config.h" + #ifdef BOOTLOADER_BUILD // Without L bit set #define CONDITIONAL_NONE 0x0 @@ -82,70 +85,160 @@ static void esp_cpu_configure_invalid_regions(void) PMA_RESET_AND_ENTRY_SET_TOR(15, UINT32_MAX, PMA_TOR | PMA_NONE); } -void esp_cpu_configure_region_protection(void) -{ - /* Notes on implementation: - * - * 1) Note: ESP32-P4 CPU support overlapping PMP regions, configuration is based on static priority - * feature (lowest numbered entry has highest priority). - * - * 2) ESP32-P4 supports 16 PMA regions so we use this feature to block the invalid address ranges. - * However the entries are not sufficient to block all reserved memory ranges and the excluded sections are: - * a. Region between LP ROM and LP SRAM - * b. Region between LP peripherals and External flash (direct access) - * c. Region between External flash (direct access) and External RAM (direct access) - * d. Region between External RAM (direct access) and HP ROM (direct access) - * e. Region between HP ROM (direct access) and HP L2MEM (direct access) - * - * 3) We use combination of NAPOT (Naturally Aligned Power Of Two) and TOR (top of range) - * entries to map all the valid address space, bottom to top. This leaves us with some extra PMP entries - * which can be used to provide more granular access - * - * 4) Entries are grouped in order with some static asserts to try and verify everything is - * correct. - * - * 5) No explicit permission specified in PMP (default all permissions) for following regions due to - * limited entries: - * a. External RAM - * b. LP ROM, LP Peripherals, LP SRAM - * c. External flash, External RAM, HP ROM, HP L2MEM (direct access) - */ +#if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300 +// Helper macro to set both cached and non-cached PMP entries with the same permissions +#define PMP_ENTRY_SET_CACHED_AND_UNCACHED(cached_entry, non_cached_entry, addr, perm) \ + do { \ + PMP_RESET_AND_ENTRY_SET(cached_entry, addr, perm); \ + PMP_RESET_AND_ENTRY_SET(non_cached_entry, CACHE_LL_L2MEM_NON_CACHE_ADDR(addr), perm); \ + } while(0) - /* There are 4 configuration scenarios for SRAM - * - * 1. Bootloader build: - * - We cannot set the lock bit as we need to reconfigure it again for the application. - * We configure PMP to cover entire valid IRAM and DRAM range. - * - * 2. Application build with CONFIG_ESP_SYSTEM_MEMPROT enabled - * - We split the SRAM into IRAM and DRAM such that IRAM region cannot be written to - * and DRAM region cannot be executed. We use _iram_text_end and _data_start markers to set the boundaries. - * We also lock these entries so the R/W/X permissions are enforced even for machine mode - * - * 3. Application build with CONFIG_ESP_SYSTEM_MEMPROT disabled - * - The IRAM-DRAM split is not enabled so we just need to ensure that access to only valid address ranges are successful - * so for that we set PMP to cover entire valid IRAM and DRAM region. - * We also lock these entries so the R/W/X permissions are enforced even for machine mode - * - * 4. CPU is in OCD debug mode - * - The IRAM-DRAM split is not enabled so that OpenOCD can write and execute from IRAM. - * We set PMP to cover entire valid IRAM and DRAM region. - * We also lock these entries so the R/W/X permissions are enforced even for machine mode - */ +static void esp_cpu_configure_region_protection_rev_v3(void) +{ const unsigned NONE = PMP_L; __attribute__((unused)) const unsigned R = PMP_L | PMP_R; const unsigned RW = PMP_L | PMP_R | PMP_W; const unsigned RX = PMP_L | PMP_R | PMP_X; const unsigned RWX = PMP_L | PMP_R | PMP_W | PMP_X; - // - // Configure all the invalid address regions using PMA - // - esp_cpu_configure_invalid_regions(); + // 1. CPU Subsystem region - contains debug mode code and interrupt config registers + const uint32_t pmpaddr0 = PMPADDR_NAPOT(SOC_CPU_SUBSYSTEM_LOW, SOC_CPU_SUBSYSTEM_HIGH); + PMP_RESET_AND_ENTRY_SET(0, pmpaddr0, PMP_NAPOT | RW); + _Static_assert(SOC_CPU_SUBSYSTEM_LOW < SOC_CPU_SUBSYSTEM_HIGH, "Invalid CPU subsystem region"); - // - // Configure all the valid address regions using PMP - // + // 2. HP-CPU TCM + // The default memory permissions are RWX and TCM should be RWX, so we can skip configuring it + + // 3. CPU Peripherals + const uint32_t pmpaddr1 = PMPADDR_NAPOT(CPU_PERIPH_LOW, CPU_PERIPH_HIGH); + PMP_RESET_AND_ENTRY_SET(1, pmpaddr1, PMP_NAPOT | RW); + _Static_assert(CPU_PERIPH_LOW < CPU_PERIPH_HIGH, "Invalid CPU peripheral region"); + + // 4. I/D-ROM + const uint32_t pmpaddr2 = PMPADDR_NAPOT(SOC_IROM_MASK_LOW, SOC_IROM_MASK_HIGH); + PMP_RESET_AND_ENTRY_SET(2, pmpaddr2, PMP_NAPOT | RX); + + const uint32_t pmpaddr3 = PMPADDR_NAPOT(CACHE_LL_L2MEM_NON_CACHE_ADDR(SOC_IROM_MASK_LOW), CACHE_LL_L2MEM_NON_CACHE_ADDR(SOC_IROM_MASK_HIGH)); + PMP_RESET_AND_ENTRY_SET(3, pmpaddr3, PMP_NAPOT | RX); + + _Static_assert(SOC_IROM_MASK_LOW < SOC_IROM_MASK_HIGH, "Invalid I/D-ROM region"); + + // 5. IRAM and DRAM + if (esp_cpu_dbgr_is_attached()) { + // Anti-FI check that cpu is really in ocd mode + ESP_FAULT_ASSERT(esp_cpu_dbgr_is_attached()); + + PMP_ENTRY_SET_CACHED_AND_UNCACHED(4, 6, SOC_IRAM_LOW, NONE); + PMP_ENTRY_SET_CACHED_AND_UNCACHED(5, 7, SOC_IRAM_HIGH, PMP_TOR | RWX); + + _Static_assert(SOC_IRAM_LOW < SOC_IRAM_HIGH, "Invalid RAM region"); + } else { +#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMP && !BOOTLOADER_BUILD + extern int _iram_text_end; + + PMP_ENTRY_SET_CACHED_AND_UNCACHED(4, 7, SOC_IRAM_LOW, NONE); + PMP_ENTRY_SET_CACHED_AND_UNCACHED(5, 8, (int)&_iram_text_end, PMP_TOR | RX); + PMP_ENTRY_SET_CACHED_AND_UNCACHED(6, 9, SOC_DRAM_HIGH, PMP_TOR | RW); +#else + PMP_ENTRY_SET_CACHED_AND_UNCACHED(4, 6, SOC_IRAM_LOW, CONDITIONAL_NONE); + PMP_ENTRY_SET_CACHED_AND_UNCACHED(5, 7, SOC_IRAM_HIGH, PMP_TOR | CONDITIONAL_RWX); + _Static_assert(SOC_IRAM_LOW < SOC_IRAM_HIGH, "Invalid RAM region"); +#endif + } + +#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMP && !BOOTLOADER_BUILD + extern int _instruction_reserved_end; + extern int _rodata_reserved_end; + + const uint32_t page_aligned_irom_resv_end = ALIGN_UP_TO_MMU_PAGE_SIZE((uint32_t)(&_instruction_reserved_end)); + __attribute__((unused)) const uint32_t page_aligned_drom_resv_end = ALIGN_UP_TO_MMU_PAGE_SIZE((uint32_t)(&_rodata_reserved_end)); + + // 6. I_EXTRAM / D_EXTRAM (SPIRAM) +#if CONFIG_SPIRAM && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION + + const size_t available_psram_heap = esp_psram_get_heap_size_to_protect(); + + PMP_ENTRY_SET_CACHED_AND_UNCACHED(10, 15, SOC_EXTRAM_LOW, NONE); + +#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS && CONFIG_SPIRAM_RODATA + PMP_ENTRY_SET_CACHED_AND_UNCACHED(11, 16, (uint32_t)(&_instruction_reserved_end), PMP_TOR | RX); + PMP_ENTRY_SET_CACHED_AND_UNCACHED(12, 17, page_aligned_irom_resv_end, PMP_TOR | RW); + PMP_ENTRY_SET_CACHED_AND_UNCACHED(13, 18, (uint32_t)(&_rodata_reserved_end), PMP_TOR | R); + PMP_ENTRY_SET_CACHED_AND_UNCACHED(14, 19, ALIGN_UP((uint32_t)(&_rodata_reserved_end) + available_psram_heap, SOC_CPU_PMP_REGION_GRANULARITY), PMP_TOR | RW); + +#elif CONFIG_SPIRAM_FETCH_INSTRUCTIONS + PMP_ENTRY_SET_CACHED_AND_UNCACHED(11, 16, (uint32_t)(&_instruction_reserved_end), PMP_TOR | RX); + PMP_ENTRY_SET_CACHED_AND_UNCACHED(12, 17, page_aligned_irom_resv_end, PMP_TOR | RW); + PMP_ENTRY_SET_CACHED_AND_UNCACHED(13, 18, ALIGN_UP(page_aligned_irom_resv_end + available_psram_heap, SOC_CPU_PMP_REGION_GRANULARITY), PMP_TOR | RW); + +#elif CONFIG_SPIRAM_RODATA + PMP_ENTRY_SET_CACHED_AND_UNCACHED(11, 16, (uint32_t)(&_rodata_reserved_end), PMP_TOR | R); + PMP_ENTRY_SET_CACHED_AND_UNCACHED(12, 17, ALIGN_UP((uint32_t)(&_rodata_reserved_end) + available_psram_heap, SOC_CPU_PMP_REGION_GRANULARITY), PMP_TOR | RW); + +#else + PMP_ENTRY_SET_CACHED_AND_UNCACHED(11, 16, ALIGN_UP(SOC_EXTRAM_LOW + available_psram_heap, SOC_CPU_PMP_REGION_GRANULARITY), PMP_TOR | RW); +#endif +#endif /* CONFIG_SPIRAM && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION */ + + // ESP32-P4 V3's 24th PMP entry cannot be used as a TOR entry // DIG-752 + // 7. I_Cache / D_Cache (flash) + PMP_ENTRY_SET_CACHED_AND_UNCACHED(20, 24, SOC_IROM_LOW, NONE); + PMP_ENTRY_SET_CACHED_AND_UNCACHED(21, 25, page_aligned_irom_resv_end, PMP_TOR | RX); + PMP_ENTRY_SET_CACHED_AND_UNCACHED(22, 26, page_aligned_drom_resv_end, PMP_TOR | R); + +#else +#if CONFIG_SPIRAM + const uint32_t pmpaddr10 = PMPADDR_NAPOT(SOC_EXTRAM_LOW, SOC_EXTRAM_HIGH); + PMP_RESET_AND_ENTRY_SET(10, pmpaddr10, PMP_NAPOT | CONDITIONAL_RWX); + + const uint32_t pmpaddr11 = PMPADDR_NAPOT(CACHE_LL_L2MEM_NON_CACHE_ADDR(SOC_EXTRAM_LOW), CACHE_LL_L2MEM_NON_CACHE_ADDR(SOC_EXTRAM_HIGH)); + PMP_RESET_AND_ENTRY_SET(11, pmpaddr11, PMP_NAPOT | CONDITIONAL_RWX); + _Static_assert(SOC_EXTRAM_LOW < SOC_EXTRAM_HIGH, "Invalid I/D_EXTRAM region"); +#endif /* CONFIG_SPIRAM */ + + const uint32_t pmpaddr12 = PMPADDR_NAPOT(SOC_IROM_LOW, SOC_IROM_HIGH); + PMP_RESET_AND_ENTRY_SET(12, pmpaddr12, PMP_NAPOT | CONDITIONAL_RX); + + const uint32_t pmpaddr13 = PMPADDR_NAPOT(CACHE_LL_L2MEM_NON_CACHE_ADDR(SOC_IROM_LOW), CACHE_LL_L2MEM_NON_CACHE_ADDR(SOC_IROM_HIGH)); + PMP_RESET_AND_ENTRY_SET(13, pmpaddr13, PMP_NAPOT | CONDITIONAL_RX); + _Static_assert(SOC_IROM_LOW < SOC_IROM_HIGH, "Invalid I/D_Cache region"); +#endif + + // 8. Peripheral addresses + const uint32_t pmpaddr27 = PMPADDR_NAPOT(SOC_PERIPHERAL_LOW, SOC_PERIPHERAL_HIGH); + PMP_RESET_AND_ENTRY_SET(27, pmpaddr27, PMP_NAPOT | RW); + _Static_assert(SOC_PERIPHERAL_LOW < SOC_PERIPHERAL_HIGH, "Invalid peripheral region"); + + // 9. LP memory +#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMP && !BOOTLOADER_BUILD + extern int _rtc_text_start; + extern int _rtc_text_end; + + // ESP32-P4 V3's 28th PMP entry cannot be used as a TOR entry // DIG-752 + PMP_RESET_AND_ENTRY_SET(28, SOC_RTC_IRAM_LOW, NONE); + // First part of LP mem is reserved for RTC reserved mem (shared between bootloader and app) + // as well as memory for ULP coprocessor +#if CONFIG_ESP_SYSTEM_MEMPROT_PMP_LP_CORE_RESERVE_MEM_EXEC + PMP_RESET_AND_ENTRY_SET(29, (int)&_rtc_text_start, PMP_TOR | RWX); +#else + PMP_RESET_AND_ENTRY_SET(29, (int)&_rtc_text_start, PMP_TOR | RW); +#endif + PMP_RESET_AND_ENTRY_SET(30, (int)&_rtc_text_end, PMP_TOR | RX); + PMP_RESET_AND_ENTRY_SET(31, SOC_RTC_IRAM_HIGH, PMP_TOR | RW); +#else + const uint32_t pmpaddr28 = PMPADDR_NAPOT(SOC_RTC_IRAM_LOW, SOC_RTC_IRAM_HIGH); + PMP_RESET_AND_ENTRY_SET(28, pmpaddr28, PMP_NAPOT | CONDITIONAL_RWX); + _Static_assert(SOC_RTC_IRAM_LOW < SOC_RTC_IRAM_HIGH, "Invalid RTC IRAM region"); +#endif +} +#else +static void esp_cpu_configure_region_protection_rev_less_than_v3(void) +{ + const unsigned NONE = PMP_L; + __attribute__((unused)) const unsigned R = PMP_L | PMP_R; + const unsigned RW = PMP_L | PMP_R | PMP_W; + const unsigned RX = PMP_L | PMP_R | PMP_X; + const unsigned RWX = PMP_L | PMP_R | PMP_W | PMP_X; // 1. CPU Subsystem region - contains debug mode code and interrupt config registers const uint32_t pmpaddr0 = PMPADDR_NAPOT(SOC_CPU_SUBSYSTEM_LOW, SOC_CPU_SUBSYSTEM_HIGH); @@ -262,3 +355,71 @@ void esp_cpu_configure_region_protection(void) PMP_ENTRY_SET(15, pmpaddr15, PMP_NAPOT | RW); _Static_assert(SOC_PERIPHERAL_LOW < SOC_PERIPHERAL_HIGH, "Invalid peripheral region"); } +#endif + +void esp_cpu_configure_region_protection(void) +{ + /* Notes on implementation: + * + * 1) Note: ESP32-P4 CPU support overlapping PMP regions, configuration is based on static priority + * feature (lowest numbered entry has highest priority). + * + * 2) ESP32-P4 supports 16 PMA regions so we use this feature to block the invalid address ranges. + * However the entries are not sufficient to block all reserved memory ranges and the excluded sections are: + * a. Region between LP ROM and LP SRAM + * b. Region between LP peripherals and External flash (direct access) + * c. Region between External flash (direct access) and External RAM (direct access) + * d. Region between External RAM (direct access) and HP ROM (direct access) + * e. Region between HP ROM (direct access) and HP L2MEM (direct access) + * + * 3) We use combination of NAPOT (Naturally Aligned Power Of Two) and TOR (top of range) + * entries to map all the valid address space, bottom to top. This leaves us with some extra PMP entries + * which can be used to provide more granular access + * + * 4) Entries are grouped in order with some static asserts to try and verify everything is + * correct. + * + * 5) For ESP32-P4's versions less than v3, no explicit permissions are specified in PMP (default all permissions) for following regions: + * limited entries: + * a. External RAM + * b. LP ROM, LP Peripherals, LP SRAM + * c. External flash, External RAM, HP ROM, HP L2MEM (direct access) + */ + + /* There are 4 configuration scenarios for SRAM + * + * 1. Bootloader build: + * - We cannot set the lock bit as we need to reconfigure it again for the application. + * We configure PMP to cover entire valid IRAM and DRAM range. + * + * 2. Application build with CONFIG_ESP_SYSTEM_MEMPROT enabled + * - We split the SRAM into IRAM and DRAM such that IRAM region cannot be written to + * and DRAM region cannot be executed. We use _iram_text_end and _data_start markers to set the boundaries. + * We also lock these entries so the R/W/X permissions are enforced even for machine mode + * + * 3. Application build with CONFIG_ESP_SYSTEM_MEMPROT disabled + * - The IRAM-DRAM split is not enabled so we just need to ensure that access to only valid address ranges are successful + * so for that we set PMP to cover entire valid IRAM and DRAM region. + * We also lock these entries so the R/W/X permissions are enforced even for machine mode + * + * 4. CPU is in OCD debug mode + * - The IRAM-DRAM split is not enabled so that OpenOCD can write and execute from IRAM. + * We set PMP to cover entire valid IRAM and DRAM region. + * We also lock these entries so the R/W/X permissions are enforced even for machine mode + */ + // + // Configure all the invalid address regions using PMA + // + esp_cpu_configure_invalid_regions(); + + // + // Configure all the valid address regions using PMP + // + +#if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300 + esp_cpu_configure_region_protection_rev_v3(); +#else + esp_cpu_configure_region_protection_rev_less_than_v3(); +#endif + +} diff --git a/components/riscv/include/riscv/csr.h b/components/riscv/include/riscv/csr.h index 1eb2c3fe11b..cbb8773da14 100644 --- a/components/riscv/include/riscv/csr.h +++ b/components/riscv/include/riscv/csr.h @@ -126,19 +126,31 @@ extern "C" { */ #define PMP_ENTRY_SET(ENTRY, ADDR, CFG) do { \ RV_WRITE_CSR((CSR_PMPADDR0) + (ENTRY), (ADDR) >> (PMP_SHIFT)); \ - RV_SET_CSR((CSR_PMPCFG0) + (ENTRY)/4, ((CFG)&0xFF) << (ENTRY%4)*8); \ + PMP_ENTRY_CFG_SET(ENTRY, CFG); \ } while(0) /*Only set PMPCFG entries*/ -#define PMP_ENTRY_CFG_SET(ENTRY, CFG) do {\ - RV_SET_CSR((CSR_PMPCFG0) + (ENTRY)/4, ((CFG)&0xFF) << (ENTRY%4)*8); \ - } while(0) +#define PMP_ENTRY_CFG_SET(ENTRY, CFG) \ + RV_SET_CSR((CSR_PMPCFG0) + (ENTRY)/4, ((CFG)&0xFF) << (ENTRY%4)*8) /*Reset all permissions of a particular PMPCFG entry*/ #define PMP_ENTRY_CFG_RESET(ENTRY) do {\ + RV_WRITE_CSR((CSR_PMPADDR0) + (ENTRY), 0); \ RV_CLEAR_CSR((CSR_PMPCFG0) + (ENTRY)/4, (0xFF) << (ENTRY%4)*8); \ } while(0) +/*Read configuration of a particular PMPCFG entry*/ +#define PMP_ENTRY_CFG_READ(ENTRY) \ + ((RV_READ_CSR((CSR_PMPCFG0) + (ENTRY)/4) >> ((ENTRY%4)*8)) & 0xFF) + +#define PMP_ENTRY_ADDR_READ(ENTRY) \ + (RV_READ_CSR((CSR_PMPADDR0) + (ENTRY)) << (PMP_SHIFT)) + +#define PMP_RESET_AND_ENTRY_SET(ENTRY, ADDR, CFG) do {\ + PMP_ENTRY_CFG_RESET(ENTRY); \ + PMP_ENTRY_SET(ENTRY, ADDR, CFG); \ + } while(0) + /*Reset all permissions of a particular PMACFG entry*/ #define PMA_ENTRY_CFG_RESET(ENTRY) do {\ RV_WRITE_CSR((CSR_PMACFG0) + (ENTRY) , 0); \ diff --git a/tools/test_apps/system/panic/main/include/test_memprot.h b/tools/test_apps/system/panic/main/include/test_memprot.h index 5dde7fc83c5..e3e0dc40af6 100644 --- a/tools/test_apps/system/panic/main/include/test_memprot.h +++ b/tools/test_apps/system/panic/main/include/test_memprot.h @@ -1,10 +1,12 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #pragma once +#include "sdkconfig.h" +#include "soc/soc_caps.h" #ifdef __cplusplus extern "C" { @@ -26,12 +28,25 @@ void test_iram_reg2_write_violation(void); void test_iram_reg3_write_violation(void); + +#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE +void test_non_cache_iram_reg1_write_violation(void); +void test_non_cache_iram_reg2_write_violation(void); +void test_non_cache_iram_reg3_write_violation(void); +void test_non_cache_iram_reg4_write_violation(void); +#endif + void test_iram_reg4_write_violation(void); void test_dram_reg1_execute_violation(void); void test_dram_reg2_execute_violation(void); +#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE +void test_non_cache_dram_reg1_execute_violation(void); +void test_non_cache_dram_reg2_execute_violation(void); +#endif + void test_rtc_fast_reg1_execute_violation(void); void test_rtc_fast_reg2_execute_violation(void); @@ -52,6 +67,15 @@ void test_drom_reg_write_violation(void); void test_drom_reg_execute_violation(void); +#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE +void test_non_cache_irom_reg_write_violation(void); +void test_non_cache_drom_reg_write_violation(void); +void test_non_cache_drom_reg_execute_violation(void); + +void test_non_cache_spiram_xip_irom_alignment_reg_execute_violation(void); +void test_non_cache_spiram_xip_drom_alignment_reg_execute_violation(void); +#endif + void test_invalid_memory_region_write_violation(void); void test_invalid_memory_region_execute_violation(void); diff --git a/tools/test_apps/system/panic/main/test_app_main.c b/tools/test_apps/system/panic/main/test_app_main.c index 34e637483ce..8413507b16b 100644 --- a/tools/test_apps/system/panic/main/test_app_main.c +++ b/tools/test_apps/system/panic/main/test_app_main.c @@ -146,6 +146,13 @@ void app_main(void) HANDLE_TEST(test_name, test_iram_reg2_write_violation); HANDLE_TEST(test_name, test_iram_reg3_write_violation); +#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE + HANDLE_TEST(test_name, test_non_cache_iram_reg1_write_violation); + HANDLE_TEST(test_name, test_non_cache_iram_reg2_write_violation); + HANDLE_TEST(test_name, test_non_cache_iram_reg3_write_violation); + HANDLE_TEST(test_name, test_non_cache_iram_reg4_write_violation); +#endif + /* TODO: IDF-6820: ESP32-S2 -> Fix incorrect panic reason: Unhandled debug exception */ HANDLE_TEST(test_name, test_iram_reg4_write_violation); @@ -154,6 +161,11 @@ void app_main(void) HANDLE_TEST(test_name, test_dram_reg2_execute_violation); +#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE + HANDLE_TEST(test_name, test_non_cache_dram_reg1_execute_violation); + HANDLE_TEST(test_name, test_non_cache_dram_reg2_execute_violation); +#endif + #if CONFIG_SOC_RTC_FAST_MEM_SUPPORTED HANDLE_TEST(test_name, test_rtc_fast_reg1_execute_violation); HANDLE_TEST(test_name, test_rtc_fast_reg2_execute_violation); @@ -178,13 +190,26 @@ void app_main(void) HANDLE_TEST(test_name, test_irom_reg_write_violation); HANDLE_TEST(test_name, test_drom_reg_write_violation); HANDLE_TEST(test_name, test_drom_reg_execute_violation); + +#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE + HANDLE_TEST(test_name, test_non_cache_irom_reg_write_violation); + HANDLE_TEST(test_name, test_non_cache_drom_reg_write_violation); + HANDLE_TEST(test_name, test_non_cache_drom_reg_execute_violation); +#endif + #if CONFIG_SPIRAM_FETCH_INSTRUCTIONS && SOC_MMU_DI_VADDR_SHARED HANDLE_TEST(test_name, test_spiram_xip_irom_alignment_reg_execute_violation); +#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE + HANDLE_TEST(test_name, test_non_cache_spiram_xip_irom_alignment_reg_execute_violation); +#endif #endif #endif #if CONFIG_SPIRAM_RODATA && !CONFIG_IDF_TARGET_ESP32S2 HANDLE_TEST(test_name, test_spiram_xip_drom_alignment_reg_execute_violation); +#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE + HANDLE_TEST(test_name, test_non_cache_spiram_xip_drom_alignment_reg_execute_violation); +#endif #endif #ifdef CONFIG_SOC_CPU_HAS_PMA diff --git a/tools/test_apps/system/panic/main/test_memprot.c b/tools/test_apps/system/panic/main/test_memprot.c index 15cd3476266..209809127a2 100644 --- a/tools/test_apps/system/panic/main/test_memprot.c +++ b/tools/test_apps/system/panic/main/test_memprot.c @@ -18,6 +18,10 @@ #include "test_memprot.h" #include "sdkconfig.h" +#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE +#include "hal/cache_ll.h" +#endif + #define RND_VAL (0xA5A5A5A5) #define SPIN_ITER (16) @@ -112,6 +116,40 @@ void test_iram_reg4_write_violation(void) *test_addr = RND_VAL; } +#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE +/* IRAM: I/DCACHE boundary region */ +void test_non_cache_iram_reg1_write_violation(void) +{ + uint32_t *test_addr = (uint32_t *)(CACHE_LL_L2MEM_NON_CACHE_ADDR((uint32_t)(&_iram_start) - 0x04)); + printf("IRAM: Non-cacheable Write operation | Address: %p\n", test_addr); + *test_addr = RND_VAL; +} + +/* IRAM: Interrupt vector table region */ +void test_non_cache_iram_reg2_write_violation(void) +{ + uint32_t *test_addr = (uint32_t *)(CACHE_LL_L2MEM_NON_CACHE_ADDR((uint32_t)(&_iram_text_start) - 0x04)); + printf("IRAM: Non-cacheable Write operation | Address: %p\n", test_addr); + *test_addr = RND_VAL; +} + +/* IRAM: Text (and data) region */ +void test_non_cache_iram_reg3_write_violation(void) +{ + uint32_t *test_addr = (uint32_t *)(CACHE_LL_L2MEM_NON_CACHE_ADDR((uint32_t)(&_iram_text_end) - 0x04)); + printf("IRAM: Non-cacheable Write operation | Address: %p\n", test_addr); + *test_addr = RND_VAL; +} + +/* IRAM: Through the data bus */ +void test_non_cache_iram_reg4_write_violation(void) +{ + uint32_t *test_addr = (uint32_t *)MAP_IRAM_TO_DRAM((uint32_t)&_iram_text_end - 0x04); + printf("IRAM: Write operation | Address: %p\n", test_addr); + *test_addr = RND_VAL; +} +#endif /* SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE */ + /* ---------------------------------------------------- DRAM Violation Checks ---------------------------------------------------- */ static void foo_d(void) @@ -144,6 +182,30 @@ void test_dram_reg2_execute_violation(void) run_function(test_addr); } +#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE +/* DRAM: Data region (DRAM_ATTR tagged) */ +void test_non_cache_dram_reg1_execute_violation(void) +{ + memcpy(&s_dram_buf, &foo_d, sizeof(s_dram_buf)); + void *test_addr = (void *)(CACHE_LL_L2MEM_NON_CACHE_ADDR(&s_dram_buf)); + printf("DRAM: Non-cacheable Execute operation | Address: %p\n", &s_dram_buf); + run_function(test_addr); +} + +/* DRAM: Heap region */ +void test_non_cache_dram_reg2_execute_violation(void) +{ + uint8_t *instr = calloc(1024, sizeof(uint8_t)); + assert(instr != NULL); + + printf("DRAM: Non-cacheable Execute operation | Address: %p\n", instr); + + memcpy(instr, &foo_d, 1024); + void *test_addr = (void *)(CACHE_LL_L2MEM_NON_CACHE_ADDR(instr)); + run_function(test_addr); +} +#endif /* SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE */ + /* ---------------------------------------------------- RTC Violation Checks ---------------------------------------------------- */ #if CONFIG_SOC_RTC_FAST_MEM_SUPPORTED @@ -251,6 +313,30 @@ void test_drom_reg_execute_violation(void) run_function(test_addr); } +#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE +void test_non_cache_irom_reg_write_violation(void) +{ + extern int _instruction_reserved_end; + uint32_t *test_addr = (uint32_t *)(CACHE_LL_L2MEM_NON_CACHE_ADDR((uint32_t)(&_instruction_reserved_end - 0x100))); + printf("Flash (IROM): Non-cacheable Write operation | Address: %p\n", test_addr); + *test_addr = RND_VAL; +} + +void test_non_cache_drom_reg_write_violation(void) +{ + uint32_t *test_addr = (uint32_t *)CACHE_LL_L2MEM_NON_CACHE_ADDR(((uint32_t)(foo_buf))); + printf("Flash (DROM): Non-cacheable Write operation | Address: %p\n", test_addr); + *test_addr = RND_VAL; +} + +void test_non_cache_drom_reg_execute_violation(void) +{ + void *test_addr = (void *)CACHE_LL_L2MEM_NON_CACHE_ADDR((void *)foo_buf); + printf("Flash (DROM): Non-cacheable Execute operation | Address: %p\n", test_addr); + run_function(test_addr); +} +#endif + // Check if the memory alignment gaps added to the heap are correctly configured #if CONFIG_SPIRAM_FETCH_INSTRUCTIONS && SOC_MMU_DI_VADDR_SHARED void test_spiram_xip_irom_alignment_reg_execute_violation(void) @@ -264,6 +350,20 @@ void test_spiram_xip_irom_alignment_reg_execute_violation(void) printf("SPIRAM (IROM): IROM alignment gap not added into heap\n"); } } + +#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE +void test_non_cache_spiram_xip_irom_alignment_reg_execute_violation(void) +{ + extern int _instruction_reserved_end; + if (ALIGN_UP_TO_MMU_PAGE_SIZE((uint32_t)(&_instruction_reserved_end)) - (uint32_t)(&_instruction_reserved_end) >= 4) { + void *test_addr = (void *)CACHE_LL_L2MEM_NON_CACHE_ADDR(&_instruction_reserved_end + 1); + printf("SPIRAM (IROM): Non-cacheable Execute operation | Address: %p\n", test_addr); + run_function(test_addr); + } else { + printf("SPIRAM (IROM): Non-cacheable IROM alignment gap not added into heap\n"); + } +} +#endif #endif /* CONFIG_SPIRAM_FETCH_INSTRUCTIONS && SOC_MMU_DI_VADDR_SHARED */ #endif @@ -279,6 +379,20 @@ void test_spiram_xip_drom_alignment_reg_execute_violation(void) printf("SPIRAM (DROM): DROM alignment gap not added into heap\n"); } } + +#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE +void test_non_cache_spiram_xip_drom_alignment_reg_execute_violation(void) +{ + extern int _rodata_reserved_end; + if (ALIGN_UP_TO_MMU_PAGE_SIZE((uint32_t)(&_rodata_reserved_end)) - (uint32_t)(&_rodata_reserved_end) >= 4) { + void *test_addr = (void *)CACHE_LL_L2MEM_NON_CACHE_ADDR(&_rodata_reserved_end + 0x4); + printf("SPIRAM (DROM): Non-cacheable Execute operation | Address: %p\n", test_addr); + run_function(test_addr); + } else { + printf("SPIRAM (DROM): Non-cacheable DROM alignment gap not added into heap\n"); + } +} +#endif #endif /* CONFIG_SPIRAM_RODATA && !CONFIG_IDF_TARGET_ESP32S2 */ #ifdef CONFIG_SOC_CPU_HAS_PMA diff --git a/tools/test_apps/system/panic/pytest_panic.py b/tools/test_apps/system/panic/pytest_panic.py index 1df2f495833..7cb7c3d5e50 100644 --- a/tools/test_apps/system/panic/pytest_panic.py +++ b/tools/test_apps/system/panic/pytest_panic.py @@ -681,6 +681,8 @@ CONFIGS_MEMPROT_IDRAM = list( ) ) +CONFIGS_MEMPROT_IDRAM_L2_MEM_NON_CACHE = list(zip(['memprot_esp32p4'], ['esp32p4'])) + CONFIGS_MEMPROT_DCACHE = list(zip(['memprot_esp32s2'], ['esp32s2'])) CONFIGS_MEMPROT_RTC_FAST_MEM = list( @@ -714,6 +716,8 @@ CONFIGS_MEMPROT_FLASH_IDROM = list( ) ) +CONFIGS_MEMPROT_FLASH_IDROM_L2_NON_CACHE = list(zip(['memprot_esp32p4'], ['esp32p4'])) + CONFIGS_MEMPROT_SPIRAM_XIP_IROM_ALIGNMENT_HEAP = list( zip( ['memprot_spiram_xip_esp32c5', 'memprot_spiram_xip_esp32c61', 'memprot_spiram_xip_esp32p4'], @@ -721,6 +725,14 @@ CONFIGS_MEMPROT_SPIRAM_XIP_IROM_ALIGNMENT_HEAP = list( ) ) +CONFIGS_MEMPROT_SPIRAM_XIP_IROM_ALIGNMENT_HEAP_L2_NON_CACHE = list( + zip( + ['memprot_spiram_xip_esp32p4'], + ['esp32p4'], + ) +) + + CONFIGS_MEMPROT_SPIRAM_XIP_DROM_ALIGNMENT_HEAP = list( zip( [ @@ -733,6 +745,13 @@ CONFIGS_MEMPROT_SPIRAM_XIP_DROM_ALIGNMENT_HEAP = list( ) ) +CONFIGS_MEMPROT_SPIRAM_XIP_DROM_ALIGNMENT_HEAP_L2_NON_CACHE = list( + zip( + ['memprot_spiram_xip_esp32p4'], + ['esp32p4'], + ) +) + CONFIGS_MEMPROT_INVALID_REGION_PROTECTION_USING_PMA = list( zip( [ @@ -769,10 +788,7 @@ def test_dcache_write_violation(dut: PanicTestDut, test_func_name: str) -> None: dut.expect_cpu_reset() -@pytest.mark.generic -@pytest.mark.temp_skip_ci(targets=['esp32h21'], reason='lack of runners') -@idf_parametrize('config, target', CONFIGS_MEMPROT_IDRAM, indirect=['config', 'target']) -def test_iram_reg1_write_violation(dut: PanicTestDut, test_func_name: str) -> None: +def iram_reg1_write_violation(dut: PanicTestDut, test_func_name: str) -> None: dut.run_test_func(test_func_name) if dut.target == 'esp32s2': @@ -790,10 +806,58 @@ def test_iram_reg1_write_violation(dut: PanicTestDut, test_func_name: str) -> No dut.expect_cpu_reset() +@pytest.mark.generic +@pytest.mark.temp_skip_ci(targets=['esp32h21'], reason='lack of runners') +@idf_parametrize('config, target', CONFIGS_MEMPROT_IDRAM, indirect=['config', 'target']) +def test_iram_reg1_write_violation(dut: PanicTestDut, test_func_name: str) -> None: + iram_reg1_write_violation(dut, test_func_name) + + +@pytest.mark.generic +@idf_parametrize('config, target', CONFIGS_MEMPROT_IDRAM_L2_MEM_NON_CACHE, indirect=['config', 'target']) +def test_non_cache_iram_reg1_write_violation(dut: PanicTestDut, test_func_name: str) -> None: + if dut.target == 'esp32p4' and not dut.app.sdkconfig.get('ESP32P4_SELECTS_REV_LESS_V3'): + iram_reg1_write_violation(dut, test_func_name) + + +def iram_reg_write_violation(dut: PanicTestDut, test_func_name: str) -> None: + dut.run_test_func(test_func_name) + + if dut.target == 'esp32s2': + dut.expect_gme('Memory protection fault') + dut.expect(r'Write operation at address [0-9xa-f]+ not permitted \((\S+)\)') + dut.expect_reg_dump(0) + dut.expect_backtrace() + elif dut.target == 'esp32c3': + dut.expect_gme('Memory protection fault') + dut.expect(r' memory type: (\S+)') + dut.expect(r' faulting address: [0-9xa-f]+') + dut.expect(r' operation type: (\S+)') + dut.expect_reg_dump(0) + dut.expect_stack_dump() + else: + dut.expect_gme('Store access fault') + dut.expect_reg_dump(0) + dut.expect_stack_dump() + + dut.expect_cpu_reset() + + @pytest.mark.generic @pytest.mark.temp_skip_ci(targets=['esp32h21'], reason='lack of runners') @idf_parametrize('config, target', CONFIGS_MEMPROT_IDRAM, indirect=['config', 'target']) def test_iram_reg2_write_violation(dut: PanicTestDut, test_func_name: str) -> None: + iram_reg_write_violation(dut, test_func_name) + + +@pytest.mark.generic +@idf_parametrize('config, target', CONFIGS_MEMPROT_IDRAM_L2_MEM_NON_CACHE, indirect=['config', 'target']) +def test_non_cache_iram_reg2_write_violation(dut: PanicTestDut, test_func_name: str) -> None: + if dut.target == 'esp32p4' and not dut.app.sdkconfig.get('ESP32P4_SELECTS_REV_LESS_V3'): + iram_reg_write_violation(dut, test_func_name) + + +def iram_reg3_write_violation(dut: PanicTestDut, test_func_name: str) -> None: dut.run_test_func(test_func_name) if dut.target == 'esp32s2': @@ -820,6 +884,17 @@ def test_iram_reg2_write_violation(dut: PanicTestDut, test_func_name: str) -> No @pytest.mark.temp_skip_ci(targets=['esp32h21'], reason='lack of runners') @idf_parametrize('config, target', CONFIGS_MEMPROT_IDRAM, indirect=['config', 'target']) def test_iram_reg3_write_violation(dut: PanicTestDut, test_func_name: str) -> None: + iram_reg_write_violation(dut, test_func_name) + + +@pytest.mark.generic +@idf_parametrize('config, target', CONFIGS_MEMPROT_IDRAM_L2_MEM_NON_CACHE, indirect=['config', 'target']) +def test_non_cache_iram_reg3_write_violation(dut: PanicTestDut, test_func_name: str) -> None: + if dut.target == 'esp32p4' and not dut.app.sdkconfig.get('ESP32P4_SELECTS_REV_LESS_V3'): + iram_reg_write_violation(dut, test_func_name) + + +def iram_reg4_write_violation(dut: PanicTestDut, test_func_name: str) -> None: dut.run_test_func(test_func_name) if dut.target == 'esp32s2': @@ -848,36 +923,17 @@ def test_iram_reg3_write_violation(dut: PanicTestDut, test_func_name: str) -> No @pytest.mark.temp_skip_ci(targets=['esp32h21'], reason='lack of runners') @idf_parametrize('config, target', CONFIGS_MEMPROT_IDRAM, indirect=['config', 'target']) def test_iram_reg4_write_violation(dut: PanicTestDut, test_func_name: str) -> None: - dut.run_test_func(test_func_name) - - if dut.target == 'esp32s2': - dut.expect_gme('Memory protection fault') - dut.expect(r'Write operation at address [0-9xa-f]+ not permitted \((\S+)\)') - dut.expect_reg_dump(0) - dut.expect_backtrace() - elif dut.target == 'esp32c3': - dut.expect_gme('Memory protection fault') - dut.expect(r' memory type: (\S+)') - dut.expect(r' faulting address: [0-9xa-f]+') - dut.expect(r' operation type: (\S+)') - dut.expect_reg_dump(0) - dut.expect_stack_dump() - else: - dut.expect_gme('Store access fault') - dut.expect_reg_dump(0) - dut.expect_stack_dump() - - dut.expect_cpu_reset() + iram_reg_write_violation(dut, test_func_name) -# TODO: IDF-6820: ESP32-S2 -> Fix multiple panic reasons in different runs @pytest.mark.generic -@pytest.mark.xfail( - 'config.getvalue("target") == "esp32s2"', reason='Multiple panic reasons for the same test may surface', run=False -) -@pytest.mark.temp_skip_ci(targets=['esp32h21'], reason='lack of runners') -@idf_parametrize('config, target', CONFIGS_MEMPROT_IDRAM, indirect=['config', 'target']) -def test_dram_reg1_execute_violation(dut: PanicTestDut, test_func_name: str) -> None: +@idf_parametrize('config, target', CONFIGS_MEMPROT_IDRAM_L2_MEM_NON_CACHE, indirect=['config', 'target']) +def test_non_cache_iram_reg4_write_violation(dut: PanicTestDut, test_func_name: str) -> None: + if dut.target == 'esp32p4' and not dut.app.sdkconfig.get('ESP32P4_SELECTS_REV_LESS_V3'): + iram_reg_write_violation(dut, test_func_name) + + +def dram_reg1_execute_violation(dut: PanicTestDut, test_func_name: str) -> None: dut.run_test_func(test_func_name) if dut.target == 'esp32s2': @@ -900,7 +956,18 @@ def test_dram_reg1_execute_violation(dut: PanicTestDut, test_func_name: str) -> ) @pytest.mark.temp_skip_ci(targets=['esp32h21'], reason='lack of runners') @idf_parametrize('config, target', CONFIGS_MEMPROT_IDRAM, indirect=['config', 'target']) -def test_dram_reg2_execute_violation(dut: PanicTestDut, test_func_name: str) -> None: +def test_dram_reg1_execute_violation(dut: PanicTestDut, test_func_name: str) -> None: + dram_reg1_execute_violation(dut, test_func_name) + + +@pytest.mark.generic +@idf_parametrize('config, target', CONFIGS_MEMPROT_IDRAM_L2_MEM_NON_CACHE, indirect=['config', 'target']) +def test_non_cache_dram_reg1_execute_violation(dut: PanicTestDut, test_func_name: str) -> None: + if dut.target == 'esp32p4' and not dut.app.sdkconfig.get('ESP32P4_SELECTS_REV_LESS_V3'): + dram_reg1_execute_violation(dut, test_func_name) + + +def dram_reg2_execute_violation(dut: PanicTestDut, test_func_name: str) -> None: dut.run_test_func(test_func_name) if dut.target == 'esp32s2': @@ -915,6 +982,24 @@ def test_dram_reg2_execute_violation(dut: PanicTestDut, test_func_name: str) -> dut.expect_cpu_reset() +# TODO: IDF-6820: ESP32-S2 -> Fix multiple panic reasons in different runs +@pytest.mark.generic +@pytest.mark.xfail( + 'config.getvalue("target") == "esp32s2"', reason='Multiple panic reasons for the same test may surface', run=False +) +@pytest.mark.temp_skip_ci(targets=['esp32h21'], reason='lack of runners') +@idf_parametrize('config, target', CONFIGS_MEMPROT_IDRAM, indirect=['config', 'target']) +def test_dram_reg2_execute_violation(dut: PanicTestDut, test_func_name: str) -> None: + dram_reg2_execute_violation(dut, test_func_name) + + +@pytest.mark.generic +@idf_parametrize('config, target', CONFIGS_MEMPROT_IDRAM_L2_MEM_NON_CACHE, indirect=['config', 'target']) +def test_non_cache_dram_reg2_execute_violation(dut: PanicTestDut, test_func_name: str) -> None: + if dut.target == 'esp32p4' and not dut.app.sdkconfig.get('ESP32P4_SELECTS_REV_LESS_V3'): + dram_reg2_execute_violation(dut, test_func_name) + + @pytest.mark.generic @pytest.mark.temp_skip_ci(targets=['esp32h21'], reason='lack of runners') @idf_parametrize('config, target', CONFIGS_MEMPROT_RTC_FAST_MEM, indirect=['config', 'target']) @@ -1000,10 +1085,28 @@ def test_rtc_slow_reg2_execute_violation(dut: PanicTestDut, test_func_name: str) dut.expect_cpu_reset() +def irom_reg_write_violation(dut: PanicTestDut, test_func_name: str) -> None: + dut.run_test_func(test_func_name) + dut.expect_gme('Store access fault') + dut.expect_reg_dump(0) + dut.expect_cpu_reset() + + @pytest.mark.generic @pytest.mark.temp_skip_ci(targets=['esp32h21'], reason='lack of runners') @idf_parametrize('config, target', CONFIGS_MEMPROT_FLASH_IDROM, indirect=['config', 'target']) def test_irom_reg_write_violation(dut: PanicTestDut, test_func_name: str) -> None: + irom_reg_write_violation(dut, test_func_name) + + +@pytest.mark.generic +@idf_parametrize('config, target', CONFIGS_MEMPROT_FLASH_IDROM_L2_NON_CACHE, indirect=['config', 'target']) +def test_non_cache_irom_reg_write_violation(dut: PanicTestDut, test_func_name: str) -> None: + if dut.target == 'esp32p4' and not dut.app.sdkconfig.get('ESP32P4_SELECTS_REV_LESS_V3'): + irom_reg_write_violation(dut, test_func_name) + + +def drom_reg_write_violation(dut: PanicTestDut, test_func_name: str) -> None: dut.run_test_func(test_func_name) dut.expect_gme('Store access fault') dut.expect_reg_dump(0) @@ -1014,8 +1117,19 @@ def test_irom_reg_write_violation(dut: PanicTestDut, test_func_name: str) -> Non @pytest.mark.temp_skip_ci(targets=['esp32h21'], reason='lack of runners') @idf_parametrize('config, target', CONFIGS_MEMPROT_FLASH_IDROM, indirect=['config', 'target']) def test_drom_reg_write_violation(dut: PanicTestDut, test_func_name: str) -> None: + drom_reg_write_violation(dut, test_func_name) + + +@pytest.mark.generic +@idf_parametrize('config, target', CONFIGS_MEMPROT_FLASH_IDROM_L2_NON_CACHE, indirect=['config', 'target']) +def test_non_cache_drom_reg_write_violation(dut: PanicTestDut, test_func_name: str) -> None: + if dut.target == 'esp32p4' and not dut.app.sdkconfig.get('ESP32P4_SELECTS_REV_LESS_V3'): + drom_reg_write_violation(dut, test_func_name) + + +def drom_reg_execute_violation(dut: PanicTestDut, test_func_name: str) -> None: dut.run_test_func(test_func_name) - dut.expect_gme('Store access fault') + dut.expect_gme('Instruction access fault') dut.expect_reg_dump(0) dut.expect_cpu_reset() @@ -1024,15 +1138,17 @@ def test_drom_reg_write_violation(dut: PanicTestDut, test_func_name: str) -> Non @pytest.mark.temp_skip_ci(targets=['esp32h21'], reason='lack of runners') @idf_parametrize('config, target', CONFIGS_MEMPROT_FLASH_IDROM, indirect=['config', 'target']) def test_drom_reg_execute_violation(dut: PanicTestDut, test_func_name: str) -> None: - dut.run_test_func(test_func_name) - dut.expect_gme('Instruction access fault') - dut.expect_reg_dump(0) - dut.expect_cpu_reset() + drom_reg_execute_violation(dut, test_func_name) @pytest.mark.generic -@idf_parametrize('config, target', CONFIGS_MEMPROT_SPIRAM_XIP_IROM_ALIGNMENT_HEAP, indirect=['config', 'target']) -def test_spiram_xip_irom_alignment_reg_execute_violation(dut: PanicTestDut, test_func_name: str) -> None: +@idf_parametrize('config, target', CONFIGS_MEMPROT_FLASH_IDROM_L2_NON_CACHE, indirect=['config', 'target']) +def test_non_cache_drom_reg_execute_violation(dut: PanicTestDut, test_func_name: str) -> None: + if dut.target == 'esp32p4' and not dut.app.sdkconfig.get('ESP32P4_SELECTS_REV_LESS_V3'): + drom_reg_execute_violation(dut, test_func_name) + + +def spiram_xip_irom_alignment_reg_execute_violation(dut: PanicTestDut, test_func_name: str) -> None: dut.run_test_func(test_func_name) try: dut.expect_gme('Instruction access fault') @@ -1043,8 +1159,21 @@ def test_spiram_xip_irom_alignment_reg_execute_violation(dut: PanicTestDut, test @pytest.mark.generic -@idf_parametrize('config, target', CONFIGS_MEMPROT_SPIRAM_XIP_DROM_ALIGNMENT_HEAP, indirect=['config', 'target']) -def test_spiram_xip_drom_alignment_reg_execute_violation(dut: PanicTestDut, test_func_name: str) -> None: +@idf_parametrize('config, target', CONFIGS_MEMPROT_SPIRAM_XIP_IROM_ALIGNMENT_HEAP, indirect=['config', 'target']) +def test_spiram_xip_irom_alignment_reg_execute_violation(dut: PanicTestDut, test_func_name: str) -> None: + spiram_xip_irom_alignment_reg_execute_violation(dut, test_func_name) + + +@pytest.mark.generic +@idf_parametrize( + 'config, target', CONFIGS_MEMPROT_SPIRAM_XIP_IROM_ALIGNMENT_HEAP_L2_NON_CACHE, indirect=['config', 'target'] +) +def test_non_cache_spiram_xip_irom_alignment_reg_execute_violation(dut: PanicTestDut, test_func_name: str) -> None: + if dut.target == 'esp32p4' and not dut.app.sdkconfig.get('ESP32P4_SELECTS_REV_LESS_V3'): + spiram_xip_irom_alignment_reg_execute_violation(dut, test_func_name) + + +def spiram_xip_drom_alignment_reg_execute_violation(dut: PanicTestDut, test_func_name: str) -> None: dut.run_test_func(test_func_name) try: if dut.target == 'esp32s3': @@ -1057,6 +1186,21 @@ def test_spiram_xip_drom_alignment_reg_execute_violation(dut: PanicTestDut, test dut.expect_cpu_reset() +@pytest.mark.generic +@idf_parametrize('config, target', CONFIGS_MEMPROT_SPIRAM_XIP_DROM_ALIGNMENT_HEAP, indirect=['config', 'target']) +def test_spiram_xip_drom_alignment_reg_execute_violation(dut: PanicTestDut, test_func_name: str) -> None: + spiram_xip_drom_alignment_reg_execute_violation(dut, test_func_name) + + +@pytest.mark.generic +@idf_parametrize( + 'config, target', CONFIGS_MEMPROT_SPIRAM_XIP_DROM_ALIGNMENT_HEAP_L2_NON_CACHE, indirect=['config', 'target'] +) +def test_non_cache_spiram_xip_drom_alignment_reg_execute_violation(dut: PanicTestDut, test_func_name: str) -> None: + if dut.target == 'esp32p4' and not dut.app.sdkconfig.get('ESP32P4_SELECTS_REV_LESS_V3'): + spiram_xip_drom_alignment_reg_execute_violation(dut, test_func_name) + + @pytest.mark.generic @pytest.mark.temp_skip_ci(targets=['esp32h21'], reason='lack of runners') @idf_parametrize('config, target', CONFIGS_MEMPROT_INVALID_REGION_PROTECTION_USING_PMA, indirect=['config', 'target']) diff --git a/tools/test_apps/system/panic/test_panic_util/panic_dut.py b/tools/test_apps/system/panic/test_panic_util/panic_dut.py index 0e03d201ae8..db425883044 100644 --- a/tools/test_apps/system/panic/test_panic_util/panic_dut.py +++ b/tools/test_apps/system/panic/test_panic_util/panic_dut.py @@ -6,15 +6,11 @@ import re import subprocess import sys from typing import Any -from typing import Dict -from typing import List -from typing import Optional from typing import TextIO -from typing import Union import pexpect -from panic_utils import attach_logger from panic_utils import NoGdbProcessError +from panic_utils import attach_logger from panic_utils import quote_string from panic_utils import sha256 from panic_utils import verify_valid_gdb_subprocess @@ -32,7 +28,10 @@ class PanicTestDut(IdfDut): COREDUMP_UART_END = r'================= CORE DUMP END =================' COREDUMP_CHECKSUM = r"Coredump checksum='([a-fA-F0-9]+)'" REBOOT = r'.*Rebooting\.\.\.' - CPU_RESET = r'.*rst:.*(RTC_SW_CPU_RST|SW_CPU_RESET|SW_CPU|RTCWDT_RTC_RESET|LP_WDT_SYS|RTCWDT_RTC_RST|CHIP_LP_WDT_RESET|RTC_WDT_SYS)\b' + CPU_RESET = ( + r'.*rst:.*(RTC_SW_CPU_RST|SW_CPU_RESET|SW_CPU|RTCWDT_RTC_RESET|LP_WDT_SYS|' + r'RTCWDT_RTC_RST|CHIP_LP_WDT_RESET|RTC_WDT_SYS)\b' + ) app: IdfApp serial: IdfSerial @@ -40,14 +39,14 @@ class PanicTestDut(IdfDut): def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) - self.gdbmi: Optional[GdbController] = None + self.gdbmi: GdbController | None = None # record this since pygdbmi is using logging.debug to generate some single character mess self.log_level = logging.getLogger().level # pygdbmi is using logging.debug to generate some single character mess if self.log_level <= logging.DEBUG: logging.getLogger().setLevel(logging.INFO) - self.coredump_output: Optional[TextIO] = None + self.coredump_output: TextIO | None = None def close(self) -> None: if self.gdbmi: @@ -68,6 +67,8 @@ class PanicTestDut(IdfDut): return self.target in ['esp32', 'esp32s3', 'esp32p4'] def run_test_func(self, test_func_name: str) -> None: + if self.target == 'esp32p4' and not self.app.sdkconfig.get('ESP32P4_SELECTS_REV_LESS_V3'): + self.write('\n') self.expect_exact('Enter test name:') self.write(test_func_name) self.expect_exact('Got test name: ' + test_func_name) @@ -98,13 +99,13 @@ class PanicTestDut(IdfDut): """Expect method for Guru Meditation Errors""" self.expect_exact(f"Guru Meditation Error: Core 0 panic'ed ({reason})") - def expect_reg_dump(self, core: Optional[int] = None) -> None: + def expect_reg_dump(self, core: int | None = None) -> None: if core is None: # Match any core num self.expect(r'Core\s+\d+\s+register dump:') else: # Match the exact core num provided - self.expect(r'Core\s+%d\s+register dump:' % core) + self.expect(rf'Core\s+{core}\s+register dump:') def expect_cpu_reset(self) -> None: # no digital system reset for panic handling restarts (see IDF-7255) @@ -113,13 +114,11 @@ class PanicTestDut(IdfDut): def expect_elf_sha256(self, caption: str = 'ELF file SHA256: ') -> None: """Expect method for ELF SHA256 line""" elf_sha256 = sha256(self.app.elf_file) - elf_sha256_len = int( - self.app.sdkconfig.get('CONFIG_APP_RETRIEVE_LEN_ELF_SHA', '9') - ) + elf_sha256_len = int(self.app.sdkconfig.get('CONFIG_APP_RETRIEVE_LEN_ELF_SHA', '9')) self.expect_exact(caption + elf_sha256[0:elf_sha256_len]) - def expect_coredump(self, output_file_name: str, patterns: List[Union[str, re.Pattern]]) -> None: - with open(output_file_name, 'r') as file: + def expect_coredump(self, output_file_name: str, patterns: list[str | re.Pattern]) -> None: + with open(output_file_name) as file: coredump = file.read() for pattern in patterns: if isinstance(pattern, str): @@ -131,16 +130,12 @@ class PanicTestDut(IdfDut): else: raise ValueError(f'Unsupported input type: {type(pattern).__name__}') - def _call_espcoredump( - self, extra_args: List[str], output_file_name: str - ) -> None: + def _call_espcoredump(self, extra_args: list[str], output_file_name: str) -> None: # no "with" here, since we need the file to be open for later inspection by the test case if not self.coredump_output: self.coredump_output = open(output_file_name, 'w') - espcoredump_script = os.path.join( - os.environ['IDF_PATH'], 'components', 'espcoredump', 'espcoredump.py' - ) + espcoredump_script = os.path.join(os.environ['IDF_PATH'], 'components', 'espcoredump', 'espcoredump.py') espcoredump_args = [ sys.executable, espcoredump_script, @@ -157,14 +152,16 @@ class PanicTestDut(IdfDut): subprocess.check_call(espcoredump_args, stdout=self.coredump_output, stderr=self.coredump_output) except subprocess.CalledProcessError: self.coredump_output.flush() - with open(output_file_name, 'r') as file: + with open(output_file_name) as file: logging.error('espcoredump failed with output: %s', file.read()) raise finally: self.coredump_output.seek(0) def process_coredump_uart( - self, coredump_base64: Any, expected: Optional[List[Union[str, re.Pattern]]] = None, + self, + coredump_base64: Any, + expected: list[str | re.Pattern] | None = None, ) -> Any: with open(os.path.join(self.logdir, 'coredump_data.b64'), 'w') as coredump_file: logging.info('Writing UART base64 core dump to %s', coredump_file.name) @@ -179,13 +176,11 @@ class PanicTestDut(IdfDut): self.expect_coredump(output_file_name, expected) return coredump_elf_file - def process_coredump_flash(self, expected: Optional[List[Union[str, re.Pattern]]] = None) -> Any: + def process_coredump_flash(self, expected: list[str | re.Pattern] | None = None) -> Any: coredump_file_name = os.path.join(self.logdir, 'coredump_data.bin') logging.info('Writing flash binary core dump to %s', coredump_file_name) output_file_name = os.path.join(self.logdir, 'coredump_flash_result.txt') - self._call_espcoredump( - ['--core-format', 'raw', '--save-core', coredump_file_name], output_file_name - ) + self._call_espcoredump(['--core-format', 'raw', '--save-core', coredump_file_name], output_file_name) if expected: self.expect_coredump(output_file_name, expected) return coredump_file_name @@ -210,12 +205,14 @@ class PanicTestDut(IdfDut): gdb_path = 'riscv32-esp-elf-gdb' try: from pygdbmi.constants import GdbTimeoutError + gdb_command = [gdb_path] + gdb_args self.gdbmi = GdbController(command=gdb_command) pygdbmi_logger = attach_logger() except ImportError: # fallback for pygdbmi<0.10.0.0. from pygdbmi.gdbcontroller import GdbTimeoutError + self.gdbmi = GdbController(gdb_path=gdb_path, gdb_args=gdb_args) pygdbmi_logger = self.gdbmi.logger @@ -225,9 +222,7 @@ class PanicTestDut(IdfDut): while pygdbmi_logger.hasHandlers(): pygdbmi_logger.removeHandler(pygdbmi_logger.handlers[0]) log_handler = logging.FileHandler(pygdbmi_log_file_name) - log_handler.setFormatter( - logging.Formatter('%(asctime)s %(levelname)s: %(message)s') - ) + log_handler.setFormatter(logging.Formatter('%(asctime)s %(levelname)s: %(message)s')) logging.info(f'Saving pygdbmi logs to {pygdbmi_log_file_name}') pygdbmi_logger.addHandler(log_handler) try: @@ -251,27 +246,22 @@ class PanicTestDut(IdfDut): logging.info('GDB response: %s', resp) break # success except GdbTimeoutError: - logging.warning( - 'GDB internal error: cannot get response from the subprocess' - ) + logging.warning('GDB internal error: cannot get response from the subprocess') except NoGdbProcessError: logging.error('GDB internal error: process is not running') break # failure - TODO: create another GdbController except ValueError: - logging.error( - 'GDB internal error: select() returned an unexpected file number' - ) + logging.error('GDB internal error: select() returned an unexpected file number') # Set up logging for GDB remote protocol gdb_remotelog_file_name = os.path.join(self.logdir, 'gdb_remote_log.txt') self.gdb_write('-gdb-set remotelogfile ' + gdb_remotelog_file_name) # Load the ELF file - self.gdb_write('-file-exec-and-symbols {}'.format(self.app.elf_file)) + self.gdb_write(f'-file-exec-and-symbols {self.app.elf_file}') # Prepare gdb for the gdb stub def start_gdb_for_gdbstub(self) -> None: - self.run_gdb() # Connect GDB to UART @@ -280,8 +270,9 @@ class PanicTestDut(IdfDut): self.gdb_write('-gdb-set serial baud 115200') if sys.platform == 'darwin': - assert '/dev/tty.' not in self.serial.port, \ - '/dev/tty.* ports can\'t be used with GDB on macOS. Use with /dev/cu.* instead.' + assert '/dev/tty.' not in self.serial.port, ( + "/dev/tty.* ports can't be used with GDB on macOS. Use with /dev/cu.* instead." + ) # Make sure we get the 'stopped' notification responses = self.gdb_write('-target-select remote ' + self.serial.port) @@ -307,9 +298,8 @@ class PanicTestDut(IdfDut): # Prepare gdb to debug coredump file def start_gdb_for_coredump(self, elf_file: str) -> None: - self.run_gdb() - self.gdb_write('core {}'.format(elf_file)) + self.gdb_write(f'core {elf_file}') def gdb_backtrace(self) -> Any: """ @@ -322,13 +312,11 @@ class PanicTestDut(IdfDut): return self.find_gdb_response('done', 'result', responses)['payload']['stack'] def gdb_data_eval_expr(self, expr: str) -> Any: - responses = self.gdb_write('-data-evaluate-expression "%s"' % expr) + responses = self.gdb_write(f'-data-evaluate-expression "{expr}"') return self.find_gdb_response('done', 'result', responses)['payload']['value'] @staticmethod - def verify_gdb_backtrace( - gdb_backtrace: List[Any], expected_functions_list: List[Any] - ) -> None: + def verify_gdb_backtrace(gdb_backtrace: list[Any], expected_functions_list: list[Any]) -> None: """ Raises an assert if the function names listed in expected_functions_list do not match the backtrace given by gdb_backtrace argument. The latter is in the same format as returned by gdb_backtrace() @@ -341,15 +329,13 @@ class PanicTestDut(IdfDut): assert False, 'Got unexpected backtrace' @staticmethod - def find_gdb_response( - message: str, response_type: str, responses: List[Any] - ) -> Any: + def find_gdb_response(message: str, response_type: str, responses: list[Any]) -> Any: """ Helper function which extracts one response from an array of GDB responses, filtering by message and type. Returned message is a dictionary, refer to pygdbmi docs for the format. """ - def match_response(response: Dict[str, Any]) -> bool: + def match_response(response: dict[str, Any]) -> bool: return response['message'] == message and response['type'] == response_type # type: ignore filtered_responses = [r for r in responses if match_response(r)] From 468376642a36df005639f5f40fdb06f2a9e0af70 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Thu, 16 Oct 2025 14:00:57 +0800 Subject: [PATCH 051/106] fix(esp_hw_support): fix esp32p4 v3 cache error false alarm after PD_TOP wakeup --- .../include/soc/system_periph_retention.h | 2 +- .../soc/esp32p4/system_retention_periph.c | 30 +++++++++++-------- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/components/soc/esp32p4/include/soc/system_periph_retention.h b/components/soc/esp32p4/include/soc/system_periph_retention.h index 590c7ed3aaf..805c5a8de5e 100644 --- a/components/soc/esp32p4/include/soc/system_periph_retention.h +++ b/components/soc/esp32p4/include/soc/system_periph_retention.h @@ -32,7 +32,7 @@ extern const regdma_entries_config_t intr_matrix_regs_retention[INT_MTX_RETENTIO * This is an internal function of the sleep retention driver, and is not * useful for external use. */ -#define CACHE_RETENTION_LINK_LEN 10 +#define CACHE_RETENTION_LINK_LEN 12 extern const regdma_entries_config_t cache_regs_retention[CACHE_RETENTION_LINK_LEN]; /** diff --git a/components/soc/esp32p4/system_retention_periph.c b/components/soc/esp32p4/system_retention_periph.c index 01f300e7370..86501a18c89 100644 --- a/components/soc/esp32p4/system_retention_periph.c +++ b/components/soc/esp32p4/system_retention_periph.c @@ -45,17 +45,23 @@ static const uint32_t l1_cache_regs_map[4] = {0x7, 0x0, 0xc000000, 0x0}; CACHE_L2_CACHE_ACS_FAIL_CTRL_REG & CACHE_L2_CACHE_ACS_FAIL_INT_ENA_REG */ #define L2_CACHE_RETENTION_REGS_CNT (6) #define L2_CACHE_RETENTION_REGS_BASE (CACHE_L2_CACHE_CTRL_REG) +#define L1_CACHE_ACS_FAIL_INR_CLR (CACHE_L1_ICACHE0_FAIL_INT_CLR | CACHE_L1_ICACHE1_FAIL_INT_CLR | CACHE_L1_ICACHE2_FAIL_INT_CLR | CACHE_L1_ICACHE3_FAIL_INT_CLR |CACHE_L1_DCACHE_FAIL_INT_CLR) +#define L1_CACHE_ACS_FAIL_INR_CLR_M (CACHE_L1_ICACHE0_FAIL_INT_CLR_M | CACHE_L1_ICACHE1_FAIL_INT_CLR_M | CACHE_L1_ICACHE2_FAIL_INT_CLR_M | CACHE_L1_ICACHE3_FAIL_INT_CLR_M |CACHE_L1_DCACHE_FAIL_INT_CLR_M) + static const uint32_t l2_cache_regs_map[4] = {0xc000000f, 0x0, 0x0, 0x0}; const regdma_entries_config_t cache_regs_retention[] = { - [0] = { - .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_CACHE_LINK(0x00), L1_CACHE_RETENTION_REGS_BASE, L1_CACHE_RETENTION_REGS_BASE, \ + // Clear the cache error status, since the auto clock gating added to the cache after version v3, it may falsely report cache acs fail when the module is reset. + [0] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_CACHE_LINK(0x00), CACHE_L1_CACHE_ACS_FAIL_INT_CLR_REG, L1_CACHE_ACS_FAIL_INR_CLR, L1_CACHE_ACS_FAIL_INR_CLR_M, 1, 0), .owner = ENTRY(0) }, + [1] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_CACHE_LINK(0x01), CACHE_L2_CACHE_ACS_FAIL_INT_CLR_REG, CACHE_L2_CACHE_FAIL_INT_CLR, CACHE_L2_CACHE_FAIL_INT_CLR_M, 1, 0), .owner = ENTRY(0) }, + [2] = { + .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_CACHE_LINK(0x02), L1_CACHE_RETENTION_REGS_BASE, L1_CACHE_RETENTION_REGS_BASE, \ L1_CACHE_RETENTION_REGS_CNT, 0, 0, \ l1_cache_regs_map[0], l1_cache_regs_map[1], \ l1_cache_regs_map[2], l1_cache_regs_map[3]), \ .owner = ENTRY(0) }, - [1] = { - .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_CACHE_LINK(0x01), \ + [3] = { + .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_CACHE_LINK(0x03), \ L2_CACHE_RETENTION_REGS_BASE, L2_CACHE_RETENTION_REGS_BASE, \ L2_CACHE_RETENTION_REGS_CNT, 0, 0, \ l2_cache_regs_map[0], l2_cache_regs_map[1], \ @@ -63,15 +69,15 @@ const regdma_entries_config_t cache_regs_retention[] = { .owner = ENTRY(0) }, // Invalidate L1 Cache - [2] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_CACHE_LINK(0x02), CACHE_SYNC_ADDR_REG, 0, CACHE_SYNC_ADDR_M, 1, 0), .owner = ENTRY(0) }, - [3] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_CACHE_LINK(0x03), CACHE_SYNC_SIZE_REG, 0, CACHE_SYNC_SIZE_M, 1, 0), .owner = ENTRY(0) }, - [4] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_CACHE_LINK(0x04), CACHE_SYNC_MAP_REG, CACHE_MAP_L1_CACHE_MASK, CACHE_SYNC_MAP_M, 1, 0), .owner = ENTRY(0) }, - [5] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_CACHE_LINK(0x05), CACHE_SYNC_CTRL_REG, 0, CACHE_SYNC_RGID_M, 1, 0), .owner = ENTRY(0) }, - [6] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_CACHE_LINK(0x06), CACHE_SYNC_CTRL_REG, CACHE_INVALIDATE_ENA, CACHE_INVALIDATE_ENA_M, 1, 0), .owner = ENTRY(0) }, - [7] = { .config = REGDMA_LINK_WAIT_INIT(REGDMA_CACHE_LINK(0x07), CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE, CACHE_SYNC_DONE_M, 1, 0), .owner = ENTRY(0) }, + [4] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_CACHE_LINK(0x04), CACHE_SYNC_ADDR_REG, 0, CACHE_SYNC_ADDR_M, 1, 0), .owner = ENTRY(0) }, + [5] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_CACHE_LINK(0x05), CACHE_SYNC_SIZE_REG, 0, CACHE_SYNC_SIZE_M, 1, 0), .owner = ENTRY(0) }, + [6] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_CACHE_LINK(0x06), CACHE_SYNC_MAP_REG, CACHE_MAP_L1_CACHE_MASK, CACHE_SYNC_MAP_M, 1, 0), .owner = ENTRY(0) }, + [7] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_CACHE_LINK(0x07), CACHE_SYNC_CTRL_REG, 0, CACHE_SYNC_RGID_M, 1, 0), .owner = ENTRY(0) }, + [8] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_CACHE_LINK(0x08), CACHE_SYNC_CTRL_REG, CACHE_INVALIDATE_ENA, CACHE_INVALIDATE_ENA_M, 1, 0), .owner = ENTRY(0) }, + [9] = { .config = REGDMA_LINK_WAIT_INIT(REGDMA_CACHE_LINK(0x09), CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE, CACHE_SYNC_DONE_M, 1, 0), .owner = ENTRY(0) }, // Reset L2 CACHE SYNC - [8] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_CACHE_LINK(0x08), CACHE_L2_CACHE_SYNC_RST_CTRL_REG, CACHE_L2_CACHE_SYNC_RST, CACHE_L2_CACHE_SYNC_RST_M, 1, 0), .owner = ENTRY(0) }, - [9] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_CACHE_LINK(0x09), CACHE_L2_CACHE_SYNC_RST_CTRL_REG, 0, CACHE_L2_CACHE_SYNC_RST_M, 1, 0), .owner = ENTRY(0) }, + [10] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_CACHE_LINK(0x10), CACHE_L2_CACHE_SYNC_RST_CTRL_REG, CACHE_L2_CACHE_SYNC_RST, CACHE_L2_CACHE_SYNC_RST_M, 1, 0), .owner = ENTRY(0) }, + [11] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_CACHE_LINK(0x11), CACHE_L2_CACHE_SYNC_RST_CTRL_REG, 0, CACHE_L2_CACHE_SYNC_RST_M, 1, 0), .owner = ENTRY(0) }, }; _Static_assert(ARRAY_SIZE(cache_regs_retention) == CACHE_RETENTION_LINK_LEN, "Inconsistent L2 CACHE retention link length definitions"); From 9d865e22a6e36bd8a8c8d581ab03eef1eb1711ca Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Fri, 17 Oct 2025 19:51:38 +0800 Subject: [PATCH 052/106] fix(esp_hw_support): add PD_TOP lightsleep mspi failure workaround for p4 rev3 --- .../esp32p4/include/hal/mspi_ll.h | 14 +++++++++ components/esp_hw_support/CMakeLists.txt | 1 + .../include/esp_private/esp_pau.h | 4 ++- .../include/esp_private/sleep_flash.h | 25 ++++++++++++++++ components/esp_hw_support/linker.lf | 1 + .../esp_hw_support/port/esp32p4/pmu_sleep.c | 6 ++++ components/esp_hw_support/port/pau_regdma.c | 4 ++- components/esp_hw_support/sleep_modes.c | 17 +++++++++-- components/esp_hw_support/sleep_mspi.c | 29 +++++++++++++++++++ components/esp_hw_support/sleep_retention.c | 5 +++- .../hal/esp32p4/include/hal/lp_sys_ll.h | 7 ++++- .../soc/esp32p4/system_retention_periph.c | 22 ++++++++------ 12 files changed, 120 insertions(+), 15 deletions(-) create mode 100644 components/esp_hw_support/include/esp_private/sleep_flash.h create mode 100644 components/esp_hw_support/sleep_mspi.c diff --git a/components/esp_hal_mspi/esp32p4/include/hal/mspi_ll.h b/components/esp_hal_mspi/esp32p4/include/hal/mspi_ll.h index 5978b568e49..4c0069fd9f4 100644 --- a/components/esp_hal_mspi/esp32p4/include/hal/mspi_ll.h +++ b/components/esp_hal_mspi/esp32p4/include/hal/mspi_ll.h @@ -139,6 +139,20 @@ static inline void _mspi_timing_ll_reset_mspi(void) _mspi_timing_ll_reset_mspi(__VA_ARGS__); \ } while(0) +__attribute__((always_inline)) +static inline void _mspi_timing_ll_reset_mspi_apb(void) +{ + REG_SET_BIT(HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_MSPI_APB); + REG_CLR_BIT(HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_MSPI_APB); +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance +#define mspi_timing_ll_reset_mspi_apb(...) do { \ + (void)__DECLARE_RCC_RC_ATOMIC_ENV; \ + _mspi_timing_ll_reset_mspi_apb(__VA_ARGS__); \ + } while(0) + /*--------------------------------------------------------------- PSRAM tuning ---------------------------------------------------------------*/ diff --git a/components/esp_hw_support/CMakeLists.txt b/components/esp_hw_support/CMakeLists.txt index 9005a47f248..86085d3e9fa 100644 --- a/components/esp_hw_support/CMakeLists.txt +++ b/components/esp_hw_support/CMakeLists.txt @@ -64,6 +64,7 @@ if(NOT non_os_build) list(APPEND srcs "sleep_modem.c" "sleep_modes.c" "sleep_console.c" + "sleep_mspi.c" "sleep_usb.c" "sleep_gpio.c" "sleep_event.c" diff --git a/components/esp_hw_support/include/esp_private/esp_pau.h b/components/esp_hw_support/include/esp_private/esp_pau.h index ba975b7b8dd..f82d0f7dbbe 100644 --- a/components/esp_hw_support/include/esp_private/esp_pau.h +++ b/components/esp_hw_support/include/esp_private/esp_pau.h @@ -83,8 +83,10 @@ void pau_regdma_trigger_extra_link_restore(void); * link entry configuration in always-on domain * * @param enable Set true to use always-on domain link configuration instead + * + * @return The origin aon link bypass enable status */ -void pau_regdma_enable_aon_link_entry(bool enable); +bool pau_regdma_enable_aon_link_entry(bool enable); #endif #ifdef __cplusplus diff --git a/components/esp_hw_support/include/esp_private/sleep_flash.h b/components/esp_hw_support/include/esp_private/sleep_flash.h new file mode 100644 index 00000000000..ab8c95e0986 --- /dev/null +++ b/components/esp_hw_support/include/esp_private/sleep_flash.h @@ -0,0 +1,25 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once +#include +#include "sdkconfig.h" +#include "soc/soc_caps.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if CONFIG_IDF_TARGET_ESP32P4 && (CONFIG_ESP_REV_MIN_FULL == 300) +/** + * Workaround for esp32p4 v3 MPSI access failure after power up. + */ +void sleep_flash_p4_rev3_workaround(void); +#endif + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hw_support/linker.lf b/components/esp_hw_support/linker.lf index c37057f2c00..6a0de4b82d6 100644 --- a/components/esp_hw_support/linker.lf +++ b/components/esp_hw_support/linker.lf @@ -40,6 +40,7 @@ entries: rtc_sleep:rtc_sleep_pu (noflash) if SOC_PMU_SUPPORTED = y && SOC_LIGHT_SLEEP_SUPPORTED = y: pmu_sleep (noflash) + sleep_mspi (noflash) if SPIRAM_FLASH_LOAD_TO_PSRAM = y: pmu_init (noflash) pmu_param (noflash) diff --git a/components/esp_hw_support/port/esp32p4/pmu_sleep.c b/components/esp_hw_support/port/esp32p4/pmu_sleep.c index 0064785ae66..a0ccf7947c3 100644 --- a/components/esp_hw_support/port/esp32p4/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32p4/pmu_sleep.c @@ -39,6 +39,12 @@ #include "hal/ldo_ll.h" #endif +#if (CONFIG_ESP_REV_MIN_FULL == 300) +#include "soc/hp_system_reg.h" +#include "hal/mmu_ll.h" +#include "hal/mspi_ll.h" +#endif + #define HP(state) (PMU_MODE_HP_ ## state) #define LP(state) (PMU_MODE_LP_ ## state) diff --git a/components/esp_hw_support/port/pau_regdma.c b/components/esp_hw_support/port/pau_regdma.c index a66d78b10b1..03281ce7b76 100644 --- a/components/esp_hw_support/port/pau_regdma.c +++ b/components/esp_hw_support/port/pau_regdma.c @@ -137,8 +137,10 @@ void IRAM_ATTR pau_regdma_trigger_extra_link_restore(void) } #if SOC_PAU_IN_TOP_DOMAIN -void pau_regdma_enable_aon_link_entry(bool enable) +bool IRAM_ATTR pau_regdma_enable_aon_link_entry(bool enable) { + bool origin_bypass_en = lp_sys_ll_get_pau_aon_bypass(); lp_sys_ll_set_pau_aon_bypass(enable); + return origin_bypass_en; } #endif diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 6730ae3838f..ade972a6110 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -23,6 +23,7 @@ #include "soc/rtc.h" #include "esp_private/sleep_event.h" #include "esp_private/system_internal.h" +#include "esp_private/sleep_retention.h" #include "esp_private/io_mux.h" #include "esp_private/critical_section.h" #include "esp_log.h" @@ -78,6 +79,7 @@ #include "esp_private/sleep_console.h" #include "esp_private/sleep_cpu.h" #include "esp_private/sleep_modem.h" +#include "esp_private/sleep_flash.h" #include "esp_private/sleep_usb.h" #include "esp_private/esp_clk.h" #include "esp_private/esp_task_wdt.h" @@ -959,9 +961,14 @@ static esp_err_t FORCE_IRAM_ATTR esp_sleep_start_safe(uint32_t sleep_flags, uint } #endif -#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && SOC_PM_MMU_TABLE_RETENTION_WHEN_TOP_PD +#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP if (sleep_flags & PMU_SLEEP_PD_TOP) { +#if SOC_PM_MMU_TABLE_RETENTION_WHEN_TOP_PD esp_sleep_mmu_retention(true); +#endif +#if CONFIG_IDF_TARGET_ESP32P4 && (CONFIG_ESP_REV_MIN_FULL == 300) + sleep_retention_do_extra_retention(true); +#endif } #endif @@ -984,9 +991,15 @@ static esp_err_t FORCE_IRAM_ATTR esp_sleep_start_safe(uint32_t sleep_flags, uint result = call_rtc_sleep_start(reject_triggers, config->lslp_mem_inf_fpu, deep_sleep); #endif -#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && SOC_PM_MMU_TABLE_RETENTION_WHEN_TOP_PD +#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP if (sleep_flags & PMU_SLEEP_PD_TOP) { +#if SOC_PM_MMU_TABLE_RETENTION_WHEN_TOP_PD esp_sleep_mmu_retention(false); +#endif +#if CONFIG_IDF_TARGET_ESP32P4 && (CONFIG_ESP_REV_MIN_FULL == 300) + sleep_flash_p4_rev3_workaround(); + sleep_retention_do_extra_retention(false); +#endif } #endif diff --git a/components/esp_hw_support/sleep_mspi.c b/components/esp_hw_support/sleep_mspi.c new file mode 100644 index 00000000000..9f198262864 --- /dev/null +++ b/components/esp_hw_support/sleep_mspi.c @@ -0,0 +1,29 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "sdkconfig.h" + +#if CONFIG_IDF_TARGET_ESP32P4 && (CONFIG_ESP_REV_MIN_FULL == 300) +#include "soc/hp_system_reg.h" +#include "hal/mmu_ll.h" +#include "hal/mspi_ll.h" + +void sleep_flash_p4_rev3_workaround(void) +{ + REG_CLR_BIT(SPI_MEM_C_CACHE_FCTRL_REG, SPI_MEM_C_CLOSE_AXI_INF_EN); + REG_SET_BIT(SPI_MEM_C_CACHE_FCTRL_REG, SPI_MEM_C_AXI_REQ_EN); + REG_SET_FIELD(HP_SYSTEM_CORE_ERR_RESP_DIS_REG, HP_SYSTEM_CORE_ERR_RESP_DIS, 0x7); + REG_WRITE(SPI_MEM_C_MMU_ITEM_INDEX_REG, 0); + uint32_t mmu_backup = mmu_ll_read_entry(MMU_LL_FLASH_MMU_ID, 0); + mmu_ll_write_entry(MMU_LL_FLASH_MMU_ID, 0, 0, MMU_TARGET_FLASH0); + __attribute__((unused)) volatile uint32_t val = 0; + val = REG_READ(0x80000000); + val = REG_READ(0x80000080); + mmu_ll_write_entry(MMU_LL_FLASH_MMU_ID, 0, mmu_backup, MMU_TARGET_FLASH0); + _mspi_timing_ll_reset_mspi(); + _mspi_timing_ll_reset_mspi_apb(); + REG_SET_FIELD(HP_SYSTEM_CORE_ERR_RESP_DIS_REG, HP_SYSTEM_CORE_ERR_RESP_DIS, 0); +} +#endif diff --git a/components/esp_hw_support/sleep_retention.c b/components/esp_hw_support/sleep_retention.c index 724ce38bbc1..01fbdb2c774 100644 --- a/components/esp_hw_support/sleep_retention.c +++ b/components/esp_hw_support/sleep_retention.c @@ -968,7 +968,7 @@ void IRAM_ATTR sleep_retention_do_extra_retention(bool backup_or_restore) return; } #if SOC_PAU_IN_TOP_DOMAIN - pau_regdma_enable_aon_link_entry(false); + bool origin_bypass_en = pau_regdma_enable_aon_link_entry(false); #endif // Set extra linked list head pointer to hardware pau_regdma_set_extra_link_addr(s_retention.lists[s_retention.highpri].entries[EXTRA_LINK_NUM]); @@ -982,6 +982,9 @@ void IRAM_ATTR sleep_retention_do_extra_retention(bool backup_or_restore) } else { pau_regdma_trigger_extra_link_restore(); } +#if SOC_PAU_IN_TOP_DOMAIN + pau_regdma_enable_aon_link_entry(origin_bypass_en); +#endif } #if SOC_PM_RETENTION_SW_TRIGGER_REGDMA diff --git a/components/hal/esp32p4/include/hal/lp_sys_ll.h b/components/hal/esp32p4/include/hal/lp_sys_ll.h index e28a69a6783..510e1158b1e 100644 --- a/components/hal/esp32p4/include/hal/lp_sys_ll.h +++ b/components/hal/esp32p4/include/hal/lp_sys_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -40,6 +40,11 @@ FORCE_INLINE_ATTR void lp_sys_ll_set_pau_aon_bypass(bool bypass) LP_SYS.backup_dma_cfg1.aon_bypass = bypass ? 1 : 0; } +FORCE_INLINE_ATTR bool lp_sys_ll_get_pau_aon_bypass(void) +{ + return LP_SYS.backup_dma_cfg1.aon_bypass; +} + FORCE_INLINE_ATTR void lp_sys_ll_set_pau_link_tout_thres(uint32_t tout) { LP_SYS.backup_dma_cfg0.link_tout_thres_aon = tout; diff --git a/components/soc/esp32p4/system_retention_periph.c b/components/soc/esp32p4/system_retention_periph.c index 86501a18c89..0bcff04f94f 100644 --- a/components/soc/esp32p4/system_retention_periph.c +++ b/components/soc/esp32p4/system_retention_periph.c @@ -133,19 +133,23 @@ _Static_assert(ARRAY_SIZE(iomux_regs_retention) == IOMUX_RETENTION_LINK_LEN, "In #define N_REGS_SPI0_C_MEM_1() (((SPI_MEM_C_SMEM_AC_REG - SPI_MEM_C_FMEM__PMS0_ATTR_REG) / 4) + 1) #define N_REGS_SPI0_C_MEM_2() (1) #define N_REGS_SPI0_C_MEM_3() (((SPI_MEM_C_DPA_CTRL_REG - SPI_MEM_C_MMU_POWER_CTRL_REG) / 4) + 1) - +#if !CONFIG_ESP32P4_SELECTS_REV_LESS_V3 +#define FLASH_SPIMEM_RETENTION_ENTRY (ENTRY(0) | REGDMA_SW_TRIGGER_ENTRY) +#else +#define FLASH_SPIMEM_RETENTION_ENTRY ENTRY(0) +#endif const regdma_entries_config_t flash_spimem_regs_retention[] = { /* Note: SPI mem should not to write mmu SPI_MEM_MMU_ITEM_CONTENT_REG and SPI_MEM_MMU_ITEM_INDEX_REG */ - [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x00), DR_REG_FLASH_SPI1_BASE, DR_REG_FLASH_SPI1_BASE, N_REGS_SPI1_C_MEM_0(), 0, 0), .owner = ENTRY(0) }, /* spi1_mem */ - [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x01), SPI1_MEM_C_INT_ENA_REG, SPI1_MEM_C_INT_ENA_REG, N_REGS_SPI1_C_MEM_1(), 0, 0), .owner = ENTRY(0) }, - [2] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x02), SPI1_MEM_C_TIMING_CALI_REG, SPI1_MEM_C_TIMING_CALI_REG, N_REGS_SPI1_C_MEM_2(), 0, 0), .owner = ENTRY(0) }, + [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x00), DR_REG_FLASH_SPI1_BASE, DR_REG_FLASH_SPI1_BASE, N_REGS_SPI1_C_MEM_0(), 0, 0), .owner = FLASH_SPIMEM_RETENTION_ENTRY }, /* spi1_mem */ + [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x01), SPI1_MEM_C_INT_ENA_REG, SPI1_MEM_C_INT_ENA_REG, N_REGS_SPI1_C_MEM_1(), 0, 0), .owner = FLASH_SPIMEM_RETENTION_ENTRY }, + [2] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x02), SPI1_MEM_C_TIMING_CALI_REG, SPI1_MEM_C_TIMING_CALI_REG, N_REGS_SPI1_C_MEM_2(), 0, 0), .owner = FLASH_SPIMEM_RETENTION_ENTRY }, /* Note: SPI mem should not to write mmu SPI_MEM_MMU_ITEM_CONTENT_REG and SPI_MEM_MMU_ITEM_INDEX_REG */ - [3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x04), DR_REG_FLASH_SPI0_BASE, DR_REG_FLASH_SPI0_BASE, N_REGS_SPI0_C_MEM_0(), 0, 0), .owner = ENTRY(0) }, /* spi0_mem */ - [4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x05), SPI_MEM_C_FMEM__PMS0_ATTR_REG, SPI_MEM_C_FMEM__PMS0_ATTR_REG, N_REGS_SPI0_C_MEM_1(), 0, 0), .owner = ENTRY(0) }, - [5] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x06), SPI_MEM_C_CLOCK_GATE_REG, SPI_MEM_C_CLOCK_GATE_REG, N_REGS_SPI0_C_MEM_2(), 0, 0), .owner = ENTRY(0) }, - [6] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x07), SPI_MEM_C_MMU_POWER_CTRL_REG, SPI_MEM_C_MMU_POWER_CTRL_REG, N_REGS_SPI0_C_MEM_3(), 0, 0), .owner = ENTRY(0) }, - [7] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_SPIMEM_LINK(0x08), SPI_MEM_C_TIMING_CALI_REG, SPI_MEM_C_TIMING_CALI_UPDATE, SPI_MEM_C_TIMING_CALI_UPDATE_M, 1, 0), .owner = ENTRY(0) }, + [3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x04), DR_REG_FLASH_SPI0_BASE, DR_REG_FLASH_SPI0_BASE, N_REGS_SPI0_C_MEM_0(), 0, 0), .owner = FLASH_SPIMEM_RETENTION_ENTRY }, /* spi0_mem */ + [4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x05), SPI_MEM_C_FMEM__PMS0_ATTR_REG, SPI_MEM_C_FMEM__PMS0_ATTR_REG, N_REGS_SPI0_C_MEM_1(), 0, 0), .owner = FLASH_SPIMEM_RETENTION_ENTRY }, + [5] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x06), SPI_MEM_C_CLOCK_GATE_REG, SPI_MEM_C_CLOCK_GATE_REG, N_REGS_SPI0_C_MEM_2(), 0, 0), .owner = FLASH_SPIMEM_RETENTION_ENTRY }, + [6] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x07), SPI_MEM_C_MMU_POWER_CTRL_REG, SPI_MEM_C_MMU_POWER_CTRL_REG, N_REGS_SPI0_C_MEM_3(), 0, 0), .owner = FLASH_SPIMEM_RETENTION_ENTRY }, + [7] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_SPIMEM_LINK(0x08), SPI_MEM_C_TIMING_CALI_REG, SPI_MEM_C_TIMING_CALI_UPDATE, SPI_MEM_C_TIMING_CALI_UPDATE_M, 1, 0), .owner = FLASH_SPIMEM_RETENTION_ENTRY }, }; _Static_assert(ARRAY_SIZE(flash_spimem_regs_retention) == SPIMEM_FLASH_RETENTION_LINK_LEN, "Inconsistent Flash SPI Mem retention link length definitions"); From 5c10e4b7198be32017408f63109494cbba7688b4 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Fri, 17 Oct 2025 20:06:13 +0800 Subject: [PATCH 053/106] change(esp_hw_support): update TOP pd sleep dependency Disable peripheral powerdown lightsleep if PSRAM if enabled on P4 v3 Force powerdown Flash if peripheral power down lightsleep is enabled --- components/esp_pm/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/components/esp_pm/Kconfig b/components/esp_pm/Kconfig index fca3fae5b60..71573bbb149 100644 --- a/components/esp_pm/Kconfig +++ b/components/esp_pm/Kconfig @@ -178,7 +178,9 @@ menu "Power Management" config PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP bool "Power down Digital Peripheral in light sleep (EXPERIMENTAL)" depends on SOC_PM_SUPPORT_TOP_PD && SOC_PAU_SUPPORTED + depends on !(IDF_TARGET_ESP32P4 && (ESP_REV_MIN_FULL = 300) && SPIRAM) select PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP if !ESP32P4_SELECTS_REV_LESS_V3 + select ESP_SLEEP_POWER_DOWN_FLASH if (IDF_TARGET_ESP32P4 && (ESP_REV_MIN_FULL = 300)) default n #TODO: enable by default if periph init/deinit management supported (WIFI-5252) help If enabled, digital peripherals will try to powered down in light sleep, then all related peripherals will From a4ceeec72c8c29a67b32c5586c3b2f06d711df39 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Fri, 17 Oct 2025 20:20:40 +0800 Subject: [PATCH 054/106] change(esp_hw_support): set HP/LP mem in retention mode in sleep --- .../esp_hw_support/port/esp32p4/pmu_init.c | 8 ++++++++ .../hal/esp32p4/include/hal/lp_sys_ll.h | 15 +++++++++++++++ .../register/hw_ver3/soc/lp_system_reg.h | 19 +++++++++++++++++-- .../register/hw_ver3/soc/lp_system_struct.h | 16 ++++++++++++---- 4 files changed, 52 insertions(+), 6 deletions(-) diff --git a/components/esp_hw_support/port/esp32p4/pmu_init.c b/components/esp_hw_support/port/esp32p4/pmu_init.c index 64aa1880fab..2910f22dd30 100644 --- a/components/esp_hw_support/port/esp32p4/pmu_init.c +++ b/components/esp_hw_support/port/esp32p4/pmu_init.c @@ -14,9 +14,11 @@ #include "soc/pmu_struct.h" #include "hal/efuse_hal.h" #include "hal/pmu_hal.h" +#include "hal/lp_sys_ll.h" #include "pmu_param.h" #include "esp_private/esp_pmu.h" #include "soc/regi2c_dig_reg.h" +#include "soc/lp_system_reg.h" #include "regi2c_ctrl.h" #include "esp_rom_sys.h" #include "soc/rtc.h" @@ -175,6 +177,9 @@ static void pmu_hp_system_init_default(pmu_context_t *ctx) pmu_hp_system_param_default(mode, ¶m); pmu_hp_system_init(ctx, mode, ¶m); } +#if CONFIG_ESP32P4_REV_MIN_FULL >= 300 + lp_sys_ll_set_hp_mem_lowpower_mode(MEM_AUX_DEEPSLEEP); +#endif } static inline void pmu_lp_system_param_default(pmu_lp_mode_t mode, pmu_lp_system_param_t *param) @@ -191,6 +196,9 @@ static void pmu_lp_system_init_default(pmu_context_t *ctx) pmu_lp_system_param_default(mode, ¶m); pmu_lp_system_init(ctx, mode, ¶m); } +#if CONFIG_ESP32P4_REV_MIN_FULL >= 300 + lp_sys_ll_set_lp_mem_lowpower_mode(MEM_AUX_DEEPSLEEP); +#endif } void pmu_init(void) diff --git a/components/hal/esp32p4/include/hal/lp_sys_ll.h b/components/hal/esp32p4/include/hal/lp_sys_ll.h index 510e1158b1e..945e379da45 100644 --- a/components/hal/esp32p4/include/hal/lp_sys_ll.h +++ b/components/hal/esp32p4/include/hal/lp_sys_ll.h @@ -20,6 +20,10 @@ extern "C" { #endif +#define MEM_AUX_SHUTDOWN BIT(0) +#define MEM_AUX_LIGHTSLEEP BIT(1) +#define MEM_AUX_DEEPSLEEP BIT(2) + /** * @brief ROM obtains the wake-up type through LP_SYS_STORE9_REG[0]. * Set the flag to inform @@ -65,6 +69,17 @@ FORCE_INLINE_ATTR void lp_sys_ll_set_pau_link_addr(uint32_t addr) LP_SYS.backup_dma_cfg2.link_addr_aon = addr; } +#if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300 +FORCE_INLINE_ATTR void lp_sys_ll_set_hp_mem_lowpower_mode(uint32_t mode) +{ + LP_SYS.hp_mem_aux_ctrl.hp_mem_lowpower_mode = mode; +} + +FORCE_INLINE_ATTR void lp_sys_ll_set_lp_mem_lowpower_mode(uint32_t mode) +{ + LP_SYS.lp_mem_aux_ctrl.lp_mem_lowpower_mode = mode; +} +#endif #ifdef __cplusplus } #endif diff --git a/components/soc/esp32p4/register/hw_ver3/soc/lp_system_reg.h b/components/soc/esp32p4/register/hw_ver3/soc/lp_system_reg.h index 3719697ee9c..c137a567750 100644 --- a/components/soc/esp32p4/register/hw_ver3/soc/lp_system_reg.h +++ b/components/soc/esp32p4/register/hw_ver3/soc/lp_system_reg.h @@ -1083,7 +1083,15 @@ extern "C" { * need_des */ #define LP_SYSTEM_REG_HP_MEM_AUX_CTRL_REG (DR_REG_LP_SYS_BASE + 0x180) -/** LP_SYSTEM_REG_HP_MEM_AUX_CTRL : R/W; bitpos: [31:0]; default: 8304; +/** LP_SYSTEM_REG_HP_MEM_LOWPOWER_MODE : R/W; bitpos: [2:0]; default: 0; + * need_des + */ +#define LP_SYSTEM_REG_HP_MEM_LOWPOWER_MODE 0x7U +#define LP_SYSTEM_REG_HP_MEM_LOWPOWER_MODE_M (LP_SYSTEM_REG_HP_MEM_LOWPOWER_MODE_V << LP_SYSTEM_REG_HP_MEM_LOWPOWER_MODE_S) +#define LP_SYSTEM_REG_HP_MEM_LOWPOWER_MODE_V 0x7U +#define LP_SYSTEM_REG_HP_MEM_LOWPOWER_MODE_S 0 + +/** LP_SYSTEM_REG_HP_MEM_AUX_CTRL : R/W; bitpos: [31:3]; default: 1038; * need_des */ #define LP_SYSTEM_REG_HP_MEM_AUX_CTRL 0xFFFFFFFFU @@ -1095,7 +1103,14 @@ extern "C" { * need_des */ #define LP_SYSTEM_REG_LP_MEM_AUX_CTRL_REG (DR_REG_LP_SYS_BASE + 0x184) -/** LP_SYSTEM_REG_LP_MEM_AUX_CTRL : R/W; bitpos: [31:0]; default: 8304; +/** LP_SYSTEM_REG_LP_MEM_LOWPOWER_MODE : R/W; bitpos: [2:0]; default: 0; + * need_des + */ +#define LP_SYSTEM_REG_LP_MEM_LOWPOWER_MODE 0x7U +#define LP_SYSTEM_REG_LP_MEM_LOWPOWER_MODE_M (LP_SYSTEM_REG_LP_MEM_LOWPOWER_MODE_V << LP_SYSTEM_REG_LP_MEM_LOWPOWER_MODE_S) +#define LP_SYSTEM_REG_LP_MEM_LOWPOWER_MODE_V 0x7U +#define LP_SYSTEM_REG_LP_MEM_LOWPOWER_MODE_S 0 +/** LP_SYSTEM_REG_LP_MEM_AUX_CTRL : R/W; bitpos: [31:3]; default: 1038; * need_des */ #define LP_SYSTEM_REG_LP_MEM_AUX_CTRL 0xFFFFFFFFU diff --git a/components/soc/esp32p4/register/hw_ver3/soc/lp_system_struct.h b/components/soc/esp32p4/register/hw_ver3/soc/lp_system_struct.h index 1b63f5af864..5d674d89d47 100644 --- a/components/soc/esp32p4/register/hw_ver3/soc/lp_system_struct.h +++ b/components/soc/esp32p4/register/hw_ver3/soc/lp_system_struct.h @@ -768,10 +768,14 @@ typedef union { */ typedef union { struct { - /** hp_mem_aux_ctrl : R/W; bitpos: [31:0]; default: 8304; + /** hp_mem_lowpower_mode : R/W; bitpos: [2:0]; default: 0; * need_des */ - uint32_t hp_mem_aux_ctrl:32; + uint32_t hp_mem_lowpower_mode:3; + /** hp_mem_aux_ctrl : R/W; bitpos: [31:3]; default: 1038; + * need_des + */ + uint32_t hp_mem_aux_ctrl:29; }; uint32_t val; } lp_system_reg_hp_mem_aux_ctrl_reg_t; @@ -781,10 +785,14 @@ typedef union { */ typedef union { struct { - /** lp_mem_aux_ctrl : R/W; bitpos: [31:0]; default: 8304; + /** lp_mem_lowpower_mode : R/W; bitpos: [2:0]; default: 0; * need_des */ - uint32_t lp_mem_aux_ctrl:32; + uint32_t lp_mem_lowpower_mode:3; + /** lp_mem_aux_ctrl : R/W; bitpos: [31:3]; default: 1038; + * need_des + */ + uint32_t lp_mem_aux_ctrl:29; }; uint32_t val; } lp_system_reg_lp_mem_aux_ctrl_reg_t; From 123f7d71d205cdec5999fa3beb99f822920d2ee0 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Mon, 20 Oct 2025 15:50:23 +0800 Subject: [PATCH 055/106] change(esp_hw_support): set HP LDO powerdown in sleep by default --- components/esp_hw_support/port/esp32p4/pmu_sleep.c | 1 - .../esp_hw_support/port/esp32p4/private_include/pmu_param.h | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/components/esp_hw_support/port/esp32p4/pmu_sleep.c b/components/esp_hw_support/port/esp32p4/pmu_sleep.c index a0ccf7947c3..ffa8d0e5ee0 100644 --- a/components/esp_hw_support/port/esp32p4/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32p4/pmu_sleep.c @@ -211,7 +211,6 @@ const pmu_sleep_config_t* pmu_sleep_config_default( } power_default.hp_sys.dig_power.dcdc_switch_pd_en = 0; analog_default.hp_sys.analog.dcm_vset = CONFIG_ESP_SLEEP_DCM_VSET_VAL_IN_SLEEP; - analog_default.hp_sys.analog.xpd = 0; if (sleep_flags & PMU_SLEEP_PD_VDDSDIO) { analog_default.hp_sys.analog.xpd_0p1a = 0; } else { diff --git a/components/esp_hw_support/port/esp32p4/private_include/pmu_param.h b/components/esp_hw_support/port/esp32p4/private_include/pmu_param.h index c7f61b07232..295c3f81807 100644 --- a/components/esp_hw_support/port/esp32p4/private_include/pmu_param.h +++ b/components/esp_hw_support/port/esp32p4/private_include/pmu_param.h @@ -34,7 +34,7 @@ extern "C" { // FOR LIGHTSLEEP #define PMU_HP_DRVB_LIGHTSLEEP 0 #define PMU_LP_DRVB_LIGHTSLEEP 0 -#define PMU_HP_XPD_LIGHTSLEEP 1 +#define PMU_HP_XPD_LIGHTSLEEP 0 // Always use DCDC power supply in lightsleep #define PMU_DBG_ATTEN_LIGHTSLEEP_DEFAULT 0 #define PMU_HP_DBIAS_LIGHTSLEEP_0V6 1 From 5e03aa88787e3eb5ff697fc52e4fa9101ce4cf26 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Fri, 24 Oct 2025 17:31:03 +0800 Subject: [PATCH 056/106] fix(esp_hw_support): fix mie lost after pd_cpu sleep request reject --- components/esp_hw_support/lowpower/port/esp32p4/sleep_cpu.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/components/esp_hw_support/lowpower/port/esp32p4/sleep_cpu.c b/components/esp_hw_support/lowpower/port/esp32p4/sleep_cpu.c index 7cb3d1f40e8..02ea0f6c5f5 100644 --- a/components/esp_hw_support/lowpower/port/esp32p4/sleep_cpu.c +++ b/components/esp_hw_support/lowpower/port/esp32p4/sleep_cpu.c @@ -276,7 +276,11 @@ static TCM_IRAM_ATTR esp_err_t do_cpu_retention(sleep_cpu_entry_cb_t goto_sleep, } #endif - return (*goto_sleep)(wakeup_opt, reject_opt, lslp_mem_inf_fpu, dslp); + uint32_t reject = (*goto_sleep)(wakeup_opt, reject_opt, lslp_mem_inf_fpu, dslp); + if (reject) { + restore_mstatus(mstatus); + return reject; + } } #if CONFIG_PM_CHECK_SLEEP_RETENTION_FRAME else { From 5eff18eec28d7c5526dafeaf45e16ff824b48203 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Mon, 27 Oct 2025 20:06:09 +0800 Subject: [PATCH 057/106] fix(esp_hw_support): add p4 rev3.0 MSPI workaround for deepsleep --- .../src/bootloader_common_loader.c | 4 + components/esp_hw_support/Kconfig | 1 + .../esp_hw_support/lowpower/CMakeLists.txt | 6 + .../esp32p4/Kconfig.p4_rev3_mspi_workaround | 10 ++ .../port/esp32p4/p4_rev3_mspi_workaround.S | 110 ++++++++++++++++++ .../esp_hw_support/port/esp32p4/pmu_sleep.c | 15 ++- components/esp_system/ld/esp32p4/memory.ld.in | 15 ++- .../esp_system/ld/esp32p4/sections.rev3.ld.in | 9 ++ .../hal/esp32p4/include/hal/lp_clkrst_ll.h | 35 ++++++ .../hal/esp32p4/include/hal/lp_sys_ll.h | 1 + components/heap/port/esp32p4/memory_layout.c | 7 +- .../system/deep_sleep/main/CMakeLists.txt | 2 +- examples/system/deep_sleep/sdkconfig.ci.basic | 2 - .../deep_sleep/sdkconfig.ci.esp32_singlecore | 2 - examples/system/deep_sleep/sdkconfig.defaults | 2 - 15 files changed, 207 insertions(+), 14 deletions(-) create mode 100644 components/esp_hw_support/lowpower/port/esp32p4/Kconfig.p4_rev3_mspi_workaround create mode 100644 components/esp_hw_support/lowpower/port/esp32p4/p4_rev3_mspi_workaround.S create mode 100644 components/hal/esp32p4/include/hal/lp_clkrst_ll.h diff --git a/components/bootloader_support/src/bootloader_common_loader.c b/components/bootloader_support/src/bootloader_common_loader.c index ecc96cafca6..1ca7b4c0695 100644 --- a/components/bootloader_support/src/bootloader_common_loader.c +++ b/components/bootloader_support/src/bootloader_common_loader.c @@ -263,7 +263,11 @@ rtc_retain_mem_t* bootloader_common_get_rtc_retain_mem(void) #ifdef BOOTLOADER_BUILD #if ESP_ROM_HAS_LP_ROM +#if CONFIG_IDF_TARGET_ESP32P4 + #define RTC_RETAIN_MEM_ADDR (SOC_RTC_DRAM_LOW + CONFIG_P4_REV3_MSPI_WORKAROUND_SIZE) +#else #define RTC_RETAIN_MEM_ADDR (SOC_RTC_DRAM_LOW) +#endif #else /* Since the structure containing the retain_mem_t is aligned on 8 by the linker, make sure we align this * structure size here too */ diff --git a/components/esp_hw_support/Kconfig b/components/esp_hw_support/Kconfig index a1e06c95db1..010d5e422b1 100644 --- a/components/esp_hw_support/Kconfig +++ b/components/esp_hw_support/Kconfig @@ -299,4 +299,5 @@ menu "Hardware Settings" bool "Place esp_intr_alloc functions in IRAM" if SPI_FLASH_AUTO_SUSPEND default y + orsource "./lowpower/port/esp32p4/Kconfig.p4_rev3_mspi_workaround" endmenu diff --git a/components/esp_hw_support/lowpower/CMakeLists.txt b/components/esp_hw_support/lowpower/CMakeLists.txt index cc05b16c05c..7e110d605cb 100644 --- a/components/esp_hw_support/lowpower/CMakeLists.txt +++ b/components/esp_hw_support/lowpower/CMakeLists.txt @@ -23,6 +23,12 @@ if(CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP OR endif() endif() +if(CONFIG_P4_REV3_MSPI_CRASH_AFTER_POWER_UP_WORKAROUND) + list(APPEND srcs "port/esp32p4/p4_rev3_mspi_workaround.S") + set_property(TARGET ${COMPONENT_LIB} + APPEND PROPERTY INTERFACE_LINK_LIBRARIES "-u p4_rev3_mspi_workaround") +endif() + if(CONFIG_SOC_PM_MMU_TABLE_RETENTION_WHEN_TOP_PD AND CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP) list(APPEND srcs "port/${target}/sleep_mmu.c") endif() diff --git a/components/esp_hw_support/lowpower/port/esp32p4/Kconfig.p4_rev3_mspi_workaround b/components/esp_hw_support/lowpower/port/esp32p4/Kconfig.p4_rev3_mspi_workaround new file mode 100644 index 00000000000..5810818f799 --- /dev/null +++ b/components/esp_hw_support/lowpower/port/esp32p4/Kconfig.p4_rev3_mspi_workaround @@ -0,0 +1,10 @@ +config P4_REV3_MSPI_CRASH_AFTER_POWER_UP_WORKAROUND + bool + depends on IDF_TARGET_ESP32P4 + default y if ESP32P4_REV_MIN_300 + +config P4_REV3_MSPI_WORKAROUND_SIZE + hex + depends on IDF_TARGET_ESP32P4 + default 0x100 if ESP32P4_REV_MIN_300 + default 0 diff --git a/components/esp_hw_support/lowpower/port/esp32p4/p4_rev3_mspi_workaround.S b/components/esp_hw_support/lowpower/port/esp32p4/p4_rev3_mspi_workaround.S new file mode 100644 index 00000000000..64a105929d2 --- /dev/null +++ b/components/esp_hw_support/lowpower/port/esp32p4/p4_rev3_mspi_workaround.S @@ -0,0 +1,110 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "soc/reg_base.h" + +#define HP_SYSTEM_CORE_ERR_RESP_DIS_REG (DR_REG_HP_SYS_BASE + 0x1a4) + +/* Clock related */ +#define DR_REG_LP_CLKRST_BASE (DR_REG_LPAON_BASE + 0x1000) +#define LP_CLKRST_HPCPU_RESET_CTRL0_REG (DR_REG_LP_CLKRST_BASE + 0x14) +#define LP_CLKRST_HPCORE0_STAT_VECTOR_SEL (1 << 15) + +#define HP_SYS_CLKRST_HP_RST_EN0_REG (DR_REG_HP_SYS_CLKRST_BASE + 0xc0) +#define HP_SYS_CLKRST_REG_RST_EN_MSPI_AXI (1 << 22) +#define HP_SYS_CLKRST_REG_RST_EN_MSPI_APB (1 << 24) + + +/* SPIMEM related */ +#define DR_REG_FLASH_SPI0_BASE (DR_REG_HPPERIPH0_BASE + 0x8C000) +#define SPI_MEM_C_CACHE_FCTRL_REG (DR_REG_FLASH_SPI0_BASE + 0x3c) +#define SPI_MEM_C_CLOSE_AXI_INF_EN (1 << 31) +#define SPI_MEM_C_AXI_REQ_EN (1 << 0) + +#define SPI_MEM_C_MMU_ITEM_INDEX_REG (DR_REG_FLASH_SPI0_BASE + 0x380) +#define SPI_MEM_C_MMU_ITEM_CONTENT_REG (DR_REG_FLASH_SPI0_BASE + 0x37c) + +.macro REG_SET_BIT addr, value + li a0, \addr + li a1, \value + lw a2, (a0) + or a2, a2, a1 + sw a2, (a0) +.endm + +.macro REG_CLR_BIT addr, value + li a0, \addr + /* Since all our parameters will be constants, we can pre-calculate it at assemble time */ + li a1, ~\value + lw a2, (a0) + and a2, a2, a1 + sw a2, (a0) +.endm + +.macro REG_WRITE addr, value + li a0, \addr + li a1, \value + sw a1, (a0) +.endm + +.macro REG_READ addr + li a0, \addr + lw a1, (a0) +.endm + +.macro DELAY_US us + li t3, (40 * \us) /* CPU @40MHz after reset */ + csrr t0, cycle + add t1, t0, t3 +1: csrr t2, cycle + blt t2, t1, 1b +.endm + +/** + * @brief Workaround for MSPI issues on ESP32-P4 revision 3 + * + * This function implements a workaround for MSPI-related issues on ESP32-P4 revision 3. + * It performs 2 flash dummy reads to stabilize the MSPI functionality before jumping to + * ROM code after deepsleep wakeup. + */ +.global p4_rev3_mspi_workaround +.section .p4_rev3_mspi_workaround.rtc_text,"ax" + +p4_rev3_mspi_workaround: + # Recover the reset vector to HP ROM + REG_SET_BIT LP_CLKRST_HPCPU_RESET_CTRL0_REG, LP_CLKRST_HPCORE0_STAT_VECTOR_SEL + + # Clear the bit to close AXI interface and then set the AXI request enable bit + REG_CLR_BIT SPI_MEM_C_CACHE_FCTRL_REG, SPI_MEM_C_CLOSE_AXI_INF_EN + REG_SET_BIT SPI_MEM_C_CACHE_FCTRL_REG, SPI_MEM_C_AXI_REQ_EN + + # Set 1 mspi mmu entry for axi addr to flash addr + REG_WRITE SPI_MEM_C_MMU_ITEM_INDEX_REG, 0 + REG_WRITE SPI_MEM_C_MMU_ITEM_CONTENT_REG, 0x1000 + + # Disable cpu get error response + REG_WRITE HP_SYSTEM_CORE_ERR_RESP_DIS_REG, 0x7 + + # Perform dummy reads + REG_READ 0x80000000 + # Perform dummy reads again + REG_READ 0x80000080 + + # Delay 1us to wait MSPI read transmission done + DELAY_US 1 + + # Enable cpu get error response + REG_WRITE HP_SYSTEM_CORE_ERR_RESP_DIS_REG, 0 + + # Reset MSPI AXI and APB interfaces + REG_SET_BIT HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_MSPI_AXI + REG_SET_BIT HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_MSPI_APB + REG_CLR_BIT HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_MSPI_AXI + REG_CLR_BIT HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_MSPI_APB + + # Jump to HP ROM first stage boot code + li a5, 0x4fc00000 + jr a5 diff --git a/components/esp_hw_support/port/esp32p4/pmu_sleep.c b/components/esp_hw_support/port/esp32p4/pmu_sleep.c index ffa8d0e5ee0..7f2a2c012b8 100644 --- a/components/esp_hw_support/port/esp32p4/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32p4/pmu_sleep.c @@ -30,6 +30,7 @@ #include "hal/pmu_hal.h" #include "hal/psram_ctrlr_ll.h" #include "hal/lp_sys_ll.h" +#include "hal/lp_clkrst_ll.h" #include "esp_private/esp_pmu.h" #include "pmu_param.h" #include "esp_rom_sys.h" @@ -420,6 +421,10 @@ TCM_IRAM_ATTR uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, #endif rtc_clk_mpll_disable(); } + } else { +#if CONFIG_P4_REV3_MSPI_CRASH_AFTER_POWER_UP_WORKAROUND + lp_clkrst_ll_boot_from_lp_ram(true); +#endif } @@ -443,12 +448,16 @@ TCM_IRAM_ATTR uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, ; } -#if CONFIG_SPIRAM && CONFIG_ESP_LDO_RESERVE_PSRAM - // Enable PSRAM chip power supply after deepsleep request rejected if (dslp) { +#if CONFIG_SPIRAM && CONFIG_ESP_LDO_RESERVE_PSRAM + // Enable PSRAM chip power supply after deepsleep request rejected ldo_ll_enable(LDO_ID2UNIT(CONFIG_ESP_LDO_CHAN_PSRAM_DOMAIN), true); - } #endif +#if CONFIG_P4_REV3_MSPI_CRASH_AFTER_POWER_UP_WORKAROUND + // Set reset vector back to HP ROM after deepsleep request rejected + lp_clkrst_ll_boot_from_lp_ram(false); +#endif + } return pmu_sleep_finish(dslp); } diff --git a/components/esp_system/ld/esp32p4/memory.ld.in b/components/esp_system/ld/esp32p4/memory.ld.in index b5e42cfad1f..107b00d98b7 100644 --- a/components/esp_system/ld/esp32p4/memory.ld.in +++ b/components/esp_system/ld/esp32p4/memory.ld.in @@ -32,6 +32,12 @@ #define SRAM_HIGH_END SRAM_HIGH_START + SRAM_HIGH_SIZE #endif +#if CONFIG_P4_REV3_MSPI_CRASH_AFTER_POWER_UP_WORKAROUND +#define MSPI_WORKAROUND_SIZE CONFIG_P4_REV3_MSPI_WORKAROUND_SIZE +#else +#define MSPI_WORKAROUND_SIZE 0x0 +#endif + #define IDROM_SEG_SIZE (CONFIG_MMU_PAGE_SIZE << 10) #define LP_ROM_DRAM_START 0x5010fa80 // Value taken from ROM elf, includes LP ROM stack @@ -90,14 +96,17 @@ MEMORY /* (See irom_seg for meaning of 0x20 offset in the above.) */ #endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS + /* Used to store the deep sleep workaround code of P4 rev3.0. The reset vector will be set here before the chip enters sleep. */ + rev3_mspi_workaround_seg(RWX) : org = 0x50108000, len = MSPI_WORKAROUND_SIZE + /** * lp ram memory (RWX). Persists over deep sleep. // TODO: IDF-5667 */ #if CONFIG_ULP_COPROC_ENABLED - lp_ram_seg(RW) : org = 0x50108000 + RESERVE_RTC_MEM + CONFIG_ULP_COPROC_RESERVE_MEM, + lp_ram_seg(RW) : org = 0x50108000 + MSPI_WORKAROUND_SIZE + RESERVE_RTC_MEM + CONFIG_ULP_COPROC_RESERVE_MEM, len = 0x8000 - CONFIG_ULP_COPROC_RESERVE_MEM - RESERVE_RTC_MEM - LP_ROM_DRAM_SIZE #else - lp_ram_seg(RW) : org = 0x50108000 + RESERVE_RTC_MEM, len = 0x8000 - RESERVE_RTC_MEM + lp_ram_seg(RW) : org = 0x50108000 + MSPI_WORKAROUND_SIZE + RESERVE_RTC_MEM, len = 0x8000 - RESERVE_RTC_MEM - MSPI_WORKAROUND_SIZE #endif // CONFIG_ULP_COPROC_ENABLED /* We reduced the size of lp_ram_seg by RESERVE_RTC_MEM value. @@ -108,7 +117,7 @@ MEMORY The aim of this is to keep data that will not be moved around and have a fixed address. This segment is placed at the beginning of LP RAM, as the end of LP RAM is occupied by LP ROM stack/data */ - lp_reserved_seg(RW) : org = 0x50108000, len = RESERVE_RTC_MEM + lp_reserved_seg(RW) : org = 0x50108000 + MSPI_WORKAROUND_SIZE, len = RESERVE_RTC_MEM /* PSRAM seg */ extern_ram_seg(RWX) : org = 0x48000000, len = IDROM_SEG_SIZE diff --git a/components/esp_system/ld/esp32p4/sections.rev3.ld.in b/components/esp_system/ld/esp32p4/sections.rev3.ld.in index cc4c34afb22..e370942abf4 100644 --- a/components/esp_system/ld/esp32p4/sections.rev3.ld.in +++ b/components/esp_system/ld/esp32p4/sections.rev3.ld.in @@ -115,6 +115,15 @@ SECTIONS ALIGNED_SYMBOL(4, _rtc_force_slow_end) } > lp_ram_seg +#if CONFIG_P4_REV3_MSPI_CRASH_AFTER_POWER_UP_WORKAROUND + .rtc.p4_rev3_mspi_workaround : + { + ALIGNED_SYMBOL(4, _rtc_p4_rev3_mspi_workaround_start) + KEEP (*(.p4_rev3_mspi_workaround.rtc_text .p4_rev3_mspi_workaround.rtc_text.*)) + ALIGNED_SYMBOL(4, _rtc_p4_rev3_mspi_workaround_end) + } > rev3_mspi_workaround_seg +#endif + /** * This section holds RTC data that should have fixed addresses. * The data are not initialized at power-up and are retained during deep diff --git a/components/hal/esp32p4/include/hal/lp_clkrst_ll.h b/components/hal/esp32p4/include/hal/lp_clkrst_ll.h new file mode 100644 index 00000000000..68f4b424f2c --- /dev/null +++ b/components/hal/esp32p4/include/hal/lp_clkrst_ll.h @@ -0,0 +1,35 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +// The LL layer for ESP32-P4 LP_CLKRST register operations + +#pragma once + +#include +#include +#include "soc/soc.h" +#include "soc/lp_clkrst_struct.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Select CPU reset vector + * @param boot_from_lp_ram + * true: boot from LP TCM RAM: 0x50108000 + * false: boot from HP TCM ROM: 0x4FC00000 + */ +__attribute__((always_inline)) +static inline void lp_clkrst_ll_boot_from_lp_ram(bool boot_from_lp_ram) +{ + LP_AON_CLKRST.hpcpu_reset_ctrl0.hpcore0_stat_vector_sel = !boot_from_lp_ram; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32p4/include/hal/lp_sys_ll.h b/components/hal/esp32p4/include/hal/lp_sys_ll.h index 945e379da45..366edbd4d52 100644 --- a/components/hal/esp32p4/include/hal/lp_sys_ll.h +++ b/components/hal/esp32p4/include/hal/lp_sys_ll.h @@ -13,6 +13,7 @@ #include "soc/soc.h" #include "soc/lp_system_struct.h" #include "hal/misc.h" +#include "hal/config.h" #include "esp32p4/rom/rtc.h" diff --git a/components/heap/port/esp32p4/memory_layout.c b/components/heap/port/esp32p4/memory_layout.c index a495363432a..d26238bc975 100644 --- a/components/heap/port/esp32p4/memory_layout.c +++ b/components/heap/port/esp32p4/memory_layout.c @@ -121,6 +121,9 @@ const size_t soc_memory_region_count = sizeof(soc_memory_regions) / sizeof(soc_m extern int _data_start_low, _data_start_high, _heap_start_low, _heap_start_high, _iram_start, _iram_end, _rtc_force_slow_end; #else extern int _data_start, _heap_start, _iram_start, _iram_end, _rtc_force_slow_end; +#if CONFIG_P4_REV3_MSPI_CRASH_AFTER_POWER_UP_WORKAROUND +extern int _rtc_p4_rev3_mspi_workaround_start, _rtc_p4_rev3_mspi_workaround_end; +#endif #endif extern int _tcm_text_start, _tcm_data_end; extern int _rtc_reserved_start, _rtc_reserved_end; @@ -154,5 +157,7 @@ SOC_RESERVE_MEMORY_REGION( SOC_EXTRAM_LOW, SOC_EXTRAM_HIGH, extram_region); SOC_RESERVE_MEMORY_REGION((intptr_t)&_rtc_reserved_start, (intptr_t)&_rtc_reserved_end, rtc_reserved_data); /* This includes any memory reserved for ULP RAM */ SOC_RESERVE_MEMORY_REGION((intptr_t)&_rtc_reserved_end, (intptr_t)&_rtc_force_slow_end, rtcram_data); - +#if CONFIG_P4_REV3_MSPI_CRASH_AFTER_POWER_UP_WORKAROUND +SOC_RESERVE_MEMORY_REGION((intptr_t)&_rtc_p4_rev3_mspi_workaround_start, (intptr_t)&_rtc_p4_rev3_mspi_workaround_end, p4_rev3_mspi_workaround); +#endif #endif diff --git a/examples/system/deep_sleep/main/CMakeLists.txt b/examples/system/deep_sleep/main/CMakeLists.txt index 73604b48a39..bc399df70f9 100644 --- a/examples/system/deep_sleep/main/CMakeLists.txt +++ b/examples/system/deep_sleep/main/CMakeLists.txt @@ -4,5 +4,5 @@ set(srcs "deep_sleep_example_main.c" set(includes ".") idf_component_register(SRCS ${srcs} - PRIV_REQUIRES nvs_flash ulp esp_driver_gpio + PRIV_REQUIRES nvs_flash esp_driver_gpio INCLUDE_DIRS ${includes}) diff --git a/examples/system/deep_sleep/sdkconfig.ci.basic b/examples/system/deep_sleep/sdkconfig.ci.basic index 1e9cf53a7ea..ffd95a3d156 100644 --- a/examples/system/deep_sleep/sdkconfig.ci.basic +++ b/examples/system/deep_sleep/sdkconfig.ci.basic @@ -2,8 +2,6 @@ CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP=y CONFIG_EXAMPLE_EXT1_WAKEUP=n -CONFIG_ULP_COPROC_ENABLED=y -CONFIG_ULP_COPROC_RESERVE_MEM=512 CONFIG_LIBC_TIME_SYSCALL_USE_RTC_HRT=y CONFIG_RTC_CLK_SRC_INT_RC=y CONFIG_PARTITION_TABLE_CUSTOM=y diff --git a/examples/system/deep_sleep/sdkconfig.ci.esp32_singlecore b/examples/system/deep_sleep/sdkconfig.ci.esp32_singlecore index bc9053c45f3..23f627840f0 100644 --- a/examples/system/deep_sleep/sdkconfig.ci.esp32_singlecore +++ b/examples/system/deep_sleep/sdkconfig.ci.esp32_singlecore @@ -9,8 +9,6 @@ CONFIG_EXAMPLE_EXT1_WAKEUP=n CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_80=y CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ=80 -CONFIG_ULP_COPROC_ENABLED=y -CONFIG_ULP_COPROC_RESERVE_MEM=512 CONFIG_LIBC_TIME_SYSCALL_USE_RTC_HRT=y CONFIG_RTC_CLK_SRC_INT_RC=y CONFIG_PARTITION_TABLE_CUSTOM=y diff --git a/examples/system/deep_sleep/sdkconfig.defaults b/examples/system/deep_sleep/sdkconfig.defaults index 1a61739cba0..b3ef018be4f 100644 --- a/examples/system/deep_sleep/sdkconfig.defaults +++ b/examples/system/deep_sleep/sdkconfig.defaults @@ -1,5 +1,3 @@ -CONFIG_ULP_COPROC_ENABLED=y -CONFIG_ULP_COPROC_RESERVE_MEM=512 CONFIG_LIBC_TIME_SYSCALL_USE_RTC_HRT=y CONFIG_RTC_CLK_SRC_INT_RC=y CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP=y From a7063c98849bfd32836a11bb6dde7aaeba9e819e Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Mon, 10 Nov 2025 17:40:49 +0800 Subject: [PATCH 058/106] fix(esp_system): fix XTAL32K power breaks ADC function on 32k XTAL clock pin --- components/esp_system/port/soc/esp32c5/clk.c | 9 +++++++++ components/esp_system/port/soc/esp32c6/clk.c | 8 ++++++++ components/esp_system/port/soc/esp32c61/clk.c | 9 +++++++++ components/esp_system/port/soc/esp32h2/clk.c | 8 ++++++++ components/esp_system/port/soc/esp32h21/clk.c | 8 ++++++++ components/esp_system/port/soc/esp32h4/clk.c | 8 ++++++++ components/esp_system/port/soc/esp32p4/clk.c | 8 ++++++++ 7 files changed, 58 insertions(+) diff --git a/components/esp_system/port/soc/esp32c5/clk.c b/components/esp_system/port/soc/esp32c5/clk.c index d9be5716c1b..458b44cd69d 100644 --- a/components/esp_system/port/soc/esp32c5/clk.c +++ b/components/esp_system/port/soc/esp32c5/clk.c @@ -209,6 +209,15 @@ static void select_rtc_slow_clk(soc_rtc_slow_clk_src_t rtc_slow_clk_src) rtc_clk_32k_enable(false); rtc_clk_32k_disable_external(); } + // We have enabled all LP clock power in pmu_init, re-initialize the LP clock power based on the slow clock source after selection. + pmu_lp_power_t lp_clk_power = { + .xpd_xtal32k = (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) || (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_OSC_SLOW), + .xpd_rc32k = 0, + .xpd_fosc = 1, + .pd_osc = 0 + }; + pmu_ll_lp_set_clk_power(&PMU, PMU_MODE_LP_ACTIVE, lp_clk_power.val); + if (SLOW_CLK_CAL_CYCLES > 0) { /* TODO: 32k XTAL oscillator has some frequency drift at startup. * Improve calibration routine to wait until the frequency is stable. diff --git a/components/esp_system/port/soc/esp32c6/clk.c b/components/esp_system/port/soc/esp32c6/clk.c index 91c4ddf772d..50a2ccd5720 100644 --- a/components/esp_system/port/soc/esp32c6/clk.c +++ b/components/esp_system/port/soc/esp32c6/clk.c @@ -193,6 +193,14 @@ static void select_rtc_slow_clk(soc_rtc_slow_clk_src_t rtc_slow_clk_src) if (rtc_slow_clk_src != SOC_RTC_SLOW_CLK_SRC_RC32K) { rtc_clk_rc32k_enable(false); } + // We have enabled all LP clock power in pmu_init, re-initialize the LP clock power based on the slow clock source after selection. + pmu_lp_power_t lp_clk_power = { + .xpd_xtal32k = (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) || (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_OSC_SLOW), + .xpd_rc32k = (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC32K), + .xpd_fosc = 1, + .pd_osc = 0 + }; + pmu_ll_lp_set_clk_power(&PMU, PMU_MODE_LP_ACTIVE, lp_clk_power.val); if (SLOW_CLK_CAL_CYCLES > 0) { /* TODO: 32k XTAL oscillator has some frequency drift at startup. diff --git a/components/esp_system/port/soc/esp32c61/clk.c b/components/esp_system/port/soc/esp32c61/clk.c index 32d252b5704..e0fb0de7d97 100644 --- a/components/esp_system/port/soc/esp32c61/clk.c +++ b/components/esp_system/port/soc/esp32c61/clk.c @@ -159,6 +159,15 @@ static void select_rtc_slow_clk(soc_rtc_slow_clk_src_t rtc_slow_clk_src) rtc_clk_32k_enable(false); rtc_clk_32k_disable_external(); } + // We have enabled all LP clock power in pmu_init, re-initialize the LP clock power based on the slow clock source after selection. + pmu_lp_power_t lp_clk_power = { + .xpd_xtal32k = (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) || (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_OSC_SLOW), + .xpd_rc32k = 0, + .xpd_fosc = 1, + .pd_osc = 0 + }; + pmu_ll_lp_set_clk_power(&PMU, PMU_MODE_LP_ACTIVE, lp_clk_power.val); + if (SLOW_CLK_CAL_CYCLES > 0) { /* TODO: 32k XTAL oscillator has some frequency drift at startup. * Improve calibration routine to wait until the frequency is stable. diff --git a/components/esp_system/port/soc/esp32h2/clk.c b/components/esp_system/port/soc/esp32h2/clk.c index c96a05df287..cd61d1e23e2 100644 --- a/components/esp_system/port/soc/esp32h2/clk.c +++ b/components/esp_system/port/soc/esp32h2/clk.c @@ -197,6 +197,14 @@ static void select_rtc_slow_clk(soc_rtc_slow_clk_src_t rtc_slow_clk_src) if (rtc_slow_clk_src != SOC_RTC_SLOW_CLK_SRC_RC32K) { rtc_clk_rc32k_enable(false); } + // We have enabled all LP clock power in pmu_init, re-initialize the LP clock power based on the slow clock source after selection. + pmu_lp_power_t lp_clk_power = { + .xpd_xtal32k = (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) || (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_OSC_SLOW), + .xpd_rc32k = (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC32K), + .xpd_fosc = 1, + .pd_osc = 0 + }; + pmu_ll_lp_set_clk_power(&PMU, PMU_MODE_LP_ACTIVE, lp_clk_power.val); if (SLOW_CLK_CAL_CYCLES > 0) { /* TODO: 32k XTAL oscillator has some frequency drift at startup. diff --git a/components/esp_system/port/soc/esp32h21/clk.c b/components/esp_system/port/soc/esp32h21/clk.c index 5395cc4f113..a00424eaf8d 100644 --- a/components/esp_system/port/soc/esp32h21/clk.c +++ b/components/esp_system/port/soc/esp32h21/clk.c @@ -161,6 +161,14 @@ static void select_rtc_slow_clk(soc_rtc_slow_clk_src_t rtc_slow_clk_src) rtc_clk_32k_enable(false); rtc_clk_32k_disable_external(); } + // We have enabled all LP clock power in pmu_init, re-initialize the LP clock power based on the slow clock source after selection. + pmu_lp_power_t lp_clk_power = { + .xpd_xtal32k = (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) || (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_OSC_SLOW), + .xpd_rc32k = 0, + .xpd_fosc = 1, + .pd_osc = 0 + }; + pmu_ll_lp_set_clk_power(&PMU, PMU_MODE_LP_ACTIVE, lp_clk_power.val); if (SLOW_CLK_CAL_CYCLES > 0) { /* TODO: 32k XTAL oscillator has some frequency drift at startup. diff --git a/components/esp_system/port/soc/esp32h4/clk.c b/components/esp_system/port/soc/esp32h4/clk.c index 74ba4461b56..f24d6ce8328 100644 --- a/components/esp_system/port/soc/esp32h4/clk.c +++ b/components/esp_system/port/soc/esp32h4/clk.c @@ -159,6 +159,14 @@ static void select_rtc_slow_clk(soc_rtc_slow_clk_src_t rtc_slow_clk_src) rtc_clk_32k_enable(false); rtc_clk_32k_disable_external(); } + // We have enabled all LP clock power in pmu_init, re-initialize the LP clock power based on the slow clock source after selection. + pmu_lp_power_t lp_clk_power = { + .xpd_xtal32k = (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) || (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_OSC_SLOW), + .xpd_rc32k = 0, + .xpd_fosc = 1, + .pd_osc = 0 + }; + pmu_ll_lp_set_clk_power(&PMU, PMU_MODE_LP_ACTIVE, lp_clk_power.val); if (SLOW_CLK_CAL_CYCLES > 0) { /* TODO: 32k XTAL oscillator has some frequency drift at startup. diff --git a/components/esp_system/port/soc/esp32p4/clk.c b/components/esp_system/port/soc/esp32p4/clk.c index 0119d26157e..79e296bae0a 100644 --- a/components/esp_system/port/soc/esp32p4/clk.c +++ b/components/esp_system/port/soc/esp32p4/clk.c @@ -205,6 +205,14 @@ static void select_rtc_slow_clk(soc_rtc_slow_clk_src_t rtc_slow_clk_src) if (rtc_slow_clk_src != SOC_RTC_SLOW_CLK_SRC_RC32K) { rtc_clk_rc32k_enable(false); } + // We have enabled all LP clock power in pmu_init, re-initialize the LP clock power based on the slow clock source after selection. + pmu_lp_power_t lp_clk_power = { + .xpd_xtal32k = (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K), + .xpd_rc32k = (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC32K), + .xpd_fosc = 1, + .pd_osc = 0 + }; + pmu_ll_lp_set_clk_power(&PMU, PMU_MODE_LP_ACTIVE, lp_clk_power.val); if (SLOW_CLK_CAL_CYCLES > 0) { /* TODO: 32k XTAL oscillator has some frequency drift at startup. From e28ff721542b1baec2aa24a036ce9248bf8da784 Mon Sep 17 00:00:00 2001 From: Song Ruo Jing Date: Wed, 5 Nov 2025 16:18:16 +0800 Subject: [PATCH 059/106] feat(gpio): add IO hold support for Deep-sleep for ESP32-P4 ECO5 --- .../esp_driver_gpio/include/driver/gpio.h | 16 +++++---- components/esp_driver_gpio/src/gpio.c | 6 ++-- .../test_apps/gpio/main/test_gpio.c | 35 +++++++++++++++---- .../test_apps/gpio/main/test_gpio.h | 1 + .../test_apps/gpio/main/test_rtcio.c | 6 ++-- .../test_apps/gpio/main/test_rtcio.h | 1 + .../include/esp_private/esp_sleep_internal.h | 2 +- .../port/esp32p4/private_include/pmu_param.h | 15 ++++++++ components/esp_hw_support/sleep_gpio.c | 4 +-- components/esp_hw_support/sleep_modes.c | 2 +- components/hal/esp32p4/include/hal/gpio_ll.h | 25 +++++++++++++ .../hal/esp32p4/include/hal/rtc_io_ll.h | 10 ++++++ components/hal/include/hal/gpio_hal.h | 4 +-- .../soc/esp32/include/soc/Kconfig.soc_caps.in | 4 --- components/soc/esp32/include/soc/soc_caps.h | 3 -- .../esp32c2/include/soc/Kconfig.soc_caps.in | 4 --- components/soc/esp32c2/include/soc/soc_caps.h | 3 -- .../esp32c3/include/soc/Kconfig.soc_caps.in | 4 --- components/soc/esp32c3/include/soc/soc_caps.h | 3 -- .../esp32c5/include/soc/Kconfig.soc_caps.in | 4 --- components/soc/esp32c5/include/soc/soc_caps.h | 2 -- .../esp32c6/include/soc/Kconfig.soc_caps.in | 4 --- components/soc/esp32c6/include/soc/soc_caps.h | 2 -- .../esp32c61/include/soc/Kconfig.soc_caps.in | 4 --- .../soc/esp32c61/include/soc/soc_caps.h | 2 -- .../esp32h2/include/soc/Kconfig.soc_caps.in | 4 --- components/soc/esp32h2/include/soc/soc_caps.h | 2 -- .../esp32h21/include/soc/Kconfig.soc_caps.in | 4 --- .../soc/esp32h21/include/soc/soc_caps.h | 2 -- .../esp32p4/include/soc/Kconfig.soc_caps.in | 12 ++++--- components/soc/esp32p4/include/soc/soc_caps.h | 8 +++-- .../register/hw_ver3/soc/hp_system_struct.h | 34 +----------------- .../register/hw_ver3/soc/lp_iomux_struct.h | 18 +--------- .../esp32s2/include/soc/Kconfig.soc_caps.in | 4 --- components/soc/esp32s2/include/soc/soc_caps.h | 3 -- .../esp32s3/include/soc/Kconfig.soc_caps.in | 4 --- components/soc/esp32s3/include/soc/soc_caps.h | 3 -- 37 files changed, 117 insertions(+), 147 deletions(-) diff --git a/components/esp_driver_gpio/include/driver/gpio.h b/components/esp_driver_gpio/include/driver/gpio.h index 7e375e2cb15..7cbb8b01424 100644 --- a/components/esp_driver_gpio/include/driver/gpio.h +++ b/components/esp_driver_gpio/include/driver/gpio.h @@ -416,23 +416,25 @@ esp_err_t gpio_get_drive_capability(gpio_num_t gpio_num, gpio_drive_cap_t *stren * signal or the IO MUX/GPIO configuration is modified (including input enable, output enable, output value, * function, and drive strength values). This function can be used to retain the state of GPIOs when the power * domain of where GPIO/IOMUX belongs to becomes off. For example, chip or system is reset (e.g. watchdog - * time-out, deep-sleep events are triggered), or peripheral power-down in light-sleep. + * time-out, Deep-sleep events are triggered), or peripheral power-down in Light-sleep. * * This function works in both input and output modes, and only applicable to output-capable GPIOs. * If this function is enabled: * in output mode: the output level of the GPIO will be locked and can not be changed. * in input mode: the input read value can still reflect the changes of the input signal. * + * Power down or call `gpio_hold_dis` will disable this function. + * * Please be aware that, * - * On ESP32P4, the states of IOs can not be hold after waking up from Deep-sleep. + * 1. USB pads cannot hold at low level after waking up from Deep-sleep. The USB related registers are reset, so the USB pull-up is back. * - * Additionally, on ESP32/S2/C3/S3/C2, this function cannot be used to hold the state of a digital GPIO during Deep-sleep. + * 2. For ESP32-P4 rev < 3.0, the states of IOs can not be hold after waking up from Deep-sleep. + * + * 3. For ESP32/S2/C3/S3/C2, this function cannot be used to hold the state of a digital GPIO during Deep-sleep. * Even if this function is enabled, the digital GPIO will be reset to its default state when the chip wakes up from * Deep-sleep. If you want to hold the state of a digital GPIO during Deep-sleep, please call `gpio_deep_sleep_hold_en`. * - * Power down or call `gpio_hold_dis` will disable this function. - * * @param gpio_num GPIO number, only support output-capable GPIOs * * @return @@ -460,7 +462,7 @@ esp_err_t gpio_hold_en(gpio_num_t gpio_num); */ esp_err_t gpio_hold_dis(gpio_num_t gpio_num); -#if SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP && !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP +#if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP /** * @brief Enable all digital gpio pads hold function during Deep-sleep. * @@ -484,7 +486,7 @@ void gpio_deep_sleep_hold_en(void); * @brief Disable all digital gpio pads hold function during Deep-sleep. */ void gpio_deep_sleep_hold_dis(void); -#endif //SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP && !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP +#endif //!SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP #if SOC_GPIO_SUPPORT_FORCE_HOLD /** diff --git a/components/esp_driver_gpio/src/gpio.c b/components/esp_driver_gpio/src/gpio.c index 9c494a2631f..df11fb96a99 100644 --- a/components/esp_driver_gpio/src/gpio.c +++ b/components/esp_driver_gpio/src/gpio.c @@ -8,13 +8,13 @@ #include "esp_err.h" #include "freertos/FreeRTOS.h" #include "esp_heap_caps.h" +#include "sdkconfig.h" #include "driver/gpio.h" #include "driver/rtc_io.h" #include "soc/interrupts.h" #if !CONFIG_FREERTOS_UNICORE #include "esp_ipc.h" #endif - #include "soc/soc_caps.h" #include "soc/gpio_periph.h" #include "esp_log.h" @@ -775,7 +775,7 @@ esp_err_t gpio_hold_dis(gpio_num_t gpio_num) return ret; } -#if SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP && !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP +#if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP void gpio_deep_sleep_hold_en(void) { portENTER_CRITICAL(&gpio_context.gpio_spinlock); @@ -789,7 +789,7 @@ void gpio_deep_sleep_hold_dis(void) gpio_hal_deep_sleep_hold_dis(gpio_context.gpio_hal); portEXIT_CRITICAL(&gpio_context.gpio_spinlock); } -#endif //SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP && !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP +#endif //!SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP #if SOC_GPIO_SUPPORT_FORCE_HOLD esp_err_t IRAM_ATTR gpio_force_hold_all() diff --git a/components/esp_driver_gpio/test_apps/gpio/main/test_gpio.c b/components/esp_driver_gpio/test_apps/gpio/main/test_gpio.c index f4e249a25eb..286720482de 100644 --- a/components/esp_driver_gpio/test_apps/gpio/main/test_gpio.c +++ b/components/esp_driver_gpio/test_apps/gpio/main/test_gpio.c @@ -884,7 +884,7 @@ TEST_CASE("GPIO_light_sleep_wake_up_test", "[gpio][ignore]") } #endif -#if SOC_DEEP_SLEEP_SUPPORTED && SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP +#if SOC_DEEP_SLEEP_SUPPORTED // Pick one digital IO for each target to test is enough static void gpio_deep_sleep_hold_test_first_stage(void) { @@ -902,7 +902,9 @@ static void gpio_deep_sleep_hold_test_first_stage(void) .pull_up_en = GPIO_PULLUP_DISABLE, }; TEST_ESP_OK(gpio_config(&io_conf)); - TEST_ESP_OK(gpio_set_level(io_num, 0)); + + const bool initial_level = gpio_get_level(io_num); + TEST_ESP_OK(gpio_set_level(io_num, !initial_level)); // Enable global persistence TEST_ESP_OK(gpio_hold_en(io_num)); @@ -911,6 +913,10 @@ static void gpio_deep_sleep_hold_test_first_stage(void) // Extra step is required, so that all digital IOs can automatically get held when entering Deep-sleep gpio_deep_sleep_hold_en(); #endif + vTaskDelay(pdMS_TO_TICKS(200)); + TEST_ESP_OK(gpio_set_level(io_num, initial_level)); + TEST_ASSERT_EQUAL_INT(!initial_level, gpio_get_level(io_num)); + vTaskDelay(pdMS_TO_TICKS(200)); esp_deep_sleep_start(); } @@ -921,16 +927,31 @@ static void gpio_deep_sleep_hold_test_second_stage(void) // Check reset reason is waking up from deepsleep TEST_ASSERT_EQUAL(ESP_RST_DEEPSLEEP, esp_reset_reason()); - // Pin should stay at low level after the deep sleep - TEST_ASSERT_EQUAL_INT(0, gpio_get_level(io_num)); +#if !CONFIG_ESP32P4_SELECTS_REV_LESS_V3 // DIG-399 + bool level = gpio_get_level(io_num); // Set level should not take effect since hold is still active (and the INPUT_OUTPUT mode should still be held) - TEST_ESP_OK(gpio_set_level(io_num, 1)); - TEST_ASSERT_EQUAL_INT(0, gpio_get_level(io_num)); + TEST_ESP_OK(gpio_set_level(io_num, !level)); + TEST_ASSERT_EQUAL_INT(level, gpio_get_level(io_num)); +#endif #if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP gpio_deep_sleep_hold_dis(); #endif TEST_ESP_OK(gpio_hold_dis(io_num)); + + gpio_config_t io_conf = { + .intr_type = GPIO_INTR_DISABLE, + .mode = GPIO_MODE_INPUT_OUTPUT, + .pin_bit_mask = (1ULL << io_num), + .pull_down_en = GPIO_PULLDOWN_DISABLE, + .pull_up_en = GPIO_PULLUP_DISABLE, + }; + TEST_ESP_OK(gpio_config(&io_conf)); + +#if !CONFIG_ESP32P4_SELECTS_REV_LESS_V3 // DIG-399 + // Check that the hold level after wakeup is the level before entering deep sleep + TEST_ASSERT_EQUAL_INT(!level, gpio_get_level(io_num)); +#endif } /* @@ -942,4 +963,4 @@ static void gpio_deep_sleep_hold_test_second_stage(void) TEST_CASE_MULTIPLE_STAGES("GPIO_deep_sleep_output_hold_test", "[gpio]", gpio_deep_sleep_hold_test_first_stage, gpio_deep_sleep_hold_test_second_stage) -#endif // SOC_DEEP_SLEEP_SUPPORTED && SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP +#endif // SOC_DEEP_SLEEP_SUPPORTED diff --git a/components/esp_driver_gpio/test_apps/gpio/main/test_gpio.h b/components/esp_driver_gpio/test_apps/gpio/main/test_gpio.h index 2000b19520d..3caa9c2001f 100644 --- a/components/esp_driver_gpio/test_apps/gpio/main/test_gpio.h +++ b/components/esp_driver_gpio/test_apps/gpio/main/test_gpio.h @@ -39,6 +39,7 @@ extern "C" { #define TEST_GPIO_EXT_IN_IO (3) #define TEST_GPIO_INPUT_LEVEL_LOW_PIN (1) #define TEST_GPIO_SIGNAL_IDX (SIG_IN_FUNC250_IDX) +#define TEST_GPIO_DEEP_SLEEP_HOLD_PIN (28) #elif CONFIG_IDF_TARGET_ESP32H2 #define TEST_GPIO_EXT_OUT_IO (2) #define TEST_GPIO_EXT_IN_IO (3) diff --git a/components/esp_driver_gpio/test_apps/gpio/main/test_rtcio.c b/components/esp_driver_gpio/test_apps/gpio/main/test_rtcio.c index 3a8e2697c87..fd0735b3e88 100644 --- a/components/esp_driver_gpio/test_apps/gpio/main/test_rtcio.c +++ b/components/esp_driver_gpio/test_apps/gpio/main/test_rtcio.c @@ -278,7 +278,7 @@ TEST_CASE("RTCIO_interrupt_test", "[rtcio]") #endif //SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP && (SOC_RTCIO_PIN_COUNT > 0) #endif //SOC_RTCIO_INPUT_OUTPUT_SUPPORTED -#if SOC_DEEP_SLEEP_SUPPORTED && SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP +#if SOC_DEEP_SLEEP_SUPPORTED // It is not necessary to test every rtcio pin, it will take too much ci testing time for deep sleep // Only tests on s_test_map[TEST_RTCIO_DEEP_SLEEP_PIN_INDEX] pin // The default configuration of these pads is low level @@ -311,8 +311,10 @@ static void rtcio_deep_sleep_hold_test_second_stage(void) int io_num = s_test_map[TEST_RTCIO_DEEP_SLEEP_PIN_INDEX]; // Check reset reason is waking up from deepsleep TEST_ASSERT_EQUAL(ESP_RST_DEEPSLEEP, esp_reset_reason()); +#if !CONFIG_ESP32P4_SELECTS_REV_LESS_V3 // DIG-399 // Pin should stay at high level after the deep sleep TEST_ASSERT_EQUAL_INT(1, gpio_get_level(io_num)); +#endif gpio_hold_dis(io_num); } @@ -326,4 +328,4 @@ static void rtcio_deep_sleep_hold_test_second_stage(void) TEST_CASE_MULTIPLE_STAGES("RTCIO_deep_sleep_output_hold_test", "[rtcio]", rtcio_deep_sleep_hold_test_first_stage, rtcio_deep_sleep_hold_test_second_stage) -#endif // SOC_DEEP_SLEEP_SUPPORTED && SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP +#endif // SOC_DEEP_SLEEP_SUPPORTED diff --git a/components/esp_driver_gpio/test_apps/gpio/main/test_rtcio.h b/components/esp_driver_gpio/test_apps/gpio/main/test_rtcio.h index e72580f8976..5b07231356a 100644 --- a/components/esp_driver_gpio/test_apps/gpio/main/test_rtcio.h +++ b/components/esp_driver_gpio/test_apps/gpio/main/test_rtcio.h @@ -162,6 +162,7 @@ const int s_test_map[TEST_GPIO_PIN_COUNT] = { GPIO_NUM_15, //GPIO15 }; #define TEST_RTCIO_INTR_PIN_INDEX 2 // IO2 +#define TEST_RTCIO_DEEP_SLEEP_PIN_INDEX 5 // IO5 #elif CONFIG_IDF_TARGET_ESP32C61 || CONFIG_IDF_TARGET_ESP32C5 // Has no input-only rtcio pins, all pins support pull-up/down #define RTCIO_SUPPORT_PU_PD(num) 1 diff --git a/components/esp_hw_support/include/esp_private/esp_sleep_internal.h b/components/esp_hw_support/include/esp_private/esp_sleep_internal.h index e9c5a569fea..f424f7d903a 100644 --- a/components/esp_hw_support/include/esp_private/esp_sleep_internal.h +++ b/components/esp_hw_support/include/esp_private/esp_sleep_internal.h @@ -97,7 +97,7 @@ esp_err_t esp_sleep_acquire_lp_use_xtal(void); esp_err_t esp_sleep_release_lp_use_xtal(void); #endif -#if SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP && !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP +#if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP /** * @brief Isolate all digital IOs except those that are held during deep sleep * diff --git a/components/esp_hw_support/port/esp32p4/private_include/pmu_param.h b/components/esp_hw_support/port/esp32p4/private_include/pmu_param.h index c7f61b07232..ca28b67104f 100644 --- a/components/esp_hw_support/port/esp32p4/private_include/pmu_param.h +++ b/components/esp_hw_support/port/esp32p4/private_include/pmu_param.h @@ -11,6 +11,7 @@ #include #include "soc/pmu_struct.h" #include "hal/pmu_hal.h" +#include "sdkconfig.h" #ifdef __cplusplus extern "C" { @@ -330,6 +331,7 @@ typedef struct { } pmu_sleep_digital_config_t; +#if CONFIG_ESP32P4_SELECTS_REV_LESS_V3 #define PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags) { \ .syscntl = { \ .dig_pad_slp_sel = 0, \ @@ -343,6 +345,19 @@ typedef struct { .lp_pad_hold_all = (sleep_flags & PMU_SLEEP_PD_LP_PERIPH) ? 1 : 0, \ } \ } +#else // !CONFIG_ESP32P4_SELECTS_REV_LESS_V3 +#define PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags) { \ + .syscntl = { \ + .dig_pad_slp_sel = 0, \ + } \ +} + +#define PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags) { \ + .syscntl = { \ + .dig_pad_slp_sel = 0, \ + } \ +} +#endif typedef struct { struct { diff --git a/components/esp_hw_support/sleep_gpio.c b/components/esp_hw_support/sleep_gpio.c index 78d6b652419..0ac1dd67cfe 100644 --- a/components/esp_hw_support/sleep_gpio.c +++ b/components/esp_hw_support/sleep_gpio.c @@ -170,7 +170,7 @@ void esp_sleep_enable_gpio_switch(bool enable) } } -#if SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP && !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP +#if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP IRAM_ATTR void esp_sleep_isolate_digital_gpio(void) { gpio_hal_context_t gpio_hal = { @@ -225,7 +225,7 @@ IRAM_ATTR void esp_sleep_isolate_digital_gpio(void) } } } -#endif //SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP && !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP +#endif //!SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP #if SOC_DEEP_SLEEP_SUPPORTED void esp_deep_sleep_wakeup_io_reset(void) diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 6730ae3838f..e4a36e8b57f 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -905,7 +905,7 @@ static esp_err_t FORCE_IRAM_ATTR esp_sleep_start_safe(uint32_t sleep_flags, uint } #endif if (deep_sleep) { -#if SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP && !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP +#if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP esp_sleep_isolate_digital_gpio(); #endif diff --git a/components/hal/esp32p4/include/hal/gpio_ll.h b/components/hal/esp32p4/include/hal/gpio_ll.h index e5508f6f8b5..57402074854 100644 --- a/components/hal/esp32p4/include/hal/gpio_ll.h +++ b/components/hal/esp32p4/include/hal/gpio_ll.h @@ -22,6 +22,7 @@ #include "soc/io_mux_reg.h" #include "soc/io_mux_struct.h" #include "soc/hp_system_struct.h" +#include "soc/lp_system_struct.h" #include "soc/lp_iomux_struct.h" #include "soc/hp_sys_clkrst_struct.h" #include "soc/pmu_struct.h" @@ -489,6 +490,13 @@ static inline void gpio_ll_get_drive_capability(gpio_dev_t *hw, uint32_t gpio_nu __attribute__((always_inline)) static inline void gpio_ll_hold_en(gpio_dev_t *hw, uint32_t gpio_num) { +#if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300 + if (gpio_num < 32) { + LP_SYS.pad_rtc_hold_ctrl0.pad_rtc_hold_ctrl0 |= (1 << gpio_num); + } else { + LP_SYS.pad_rtc_hold_ctrl1.pad_rtc_hold_ctrl1 |= (1 << (gpio_num - 32)); + } +#else uint64_t bit_mask = 1ULL << gpio_num; if (!(bit_mask & SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK)) { // GPIO 0-15 @@ -504,6 +512,7 @@ static inline void gpio_ll_hold_en(gpio_dev_t *hw, uint32_t gpio_num) HP_SYSTEM.gpio_o_hold_ctrl1.reg_gpio_0_hold_high |= (bit_mask >> (32 + SOC_RTCIO_PIN_COUNT)); } } +#endif } /** @@ -515,6 +524,13 @@ static inline void gpio_ll_hold_en(gpio_dev_t *hw, uint32_t gpio_num) __attribute__((always_inline)) static inline void gpio_ll_hold_dis(gpio_dev_t *hw, uint32_t gpio_num) { +#if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300 + if (gpio_num < 32) { + LP_SYS.pad_rtc_hold_ctrl0.pad_rtc_hold_ctrl0 &= ~(1 << gpio_num); + } else { + LP_SYS.pad_rtc_hold_ctrl1.pad_rtc_hold_ctrl1 &= ~(1 << (gpio_num - 32)); + } +#else uint64_t bit_mask = 1ULL << gpio_num; if (!(bit_mask & SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK)) { // GPIO 0-15 @@ -530,6 +546,7 @@ static inline void gpio_ll_hold_dis(gpio_dev_t *hw, uint32_t gpio_num) HP_SYSTEM.gpio_o_hold_ctrl1.reg_gpio_0_hold_high &= ~(bit_mask >> (32 + SOC_RTCIO_PIN_COUNT)); } } +#endif } /** @@ -552,6 +569,13 @@ static inline bool gpio_ll_is_digital_io_hold(gpio_dev_t *hw, uint32_t gpio_num) // GPIO 0-15 abort(); } else { +#if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300 + if (gpio_num < 32) { + return !!(LP_SYS.pad_rtc_hold_ctrl0.pad_rtc_hold_ctrl0 & (1 << gpio_num)); + } else { + return !!(LP_SYS.pad_rtc_hold_ctrl1.pad_rtc_hold_ctrl1 & (1 << (gpio_num - 32))); + } +#else if (gpio_num < 32 + SOC_RTCIO_PIN_COUNT) { // GPIO 16-47 return !!(HP_SYSTEM.gpio_o_hold_ctrl0.reg_gpio_0_hold_low & (bit_mask >> SOC_RTCIO_PIN_COUNT)); @@ -559,6 +583,7 @@ static inline bool gpio_ll_is_digital_io_hold(gpio_dev_t *hw, uint32_t gpio_num) // GPIO 48-54 return !!(HP_SYSTEM.gpio_o_hold_ctrl1.reg_gpio_0_hold_high & (bit_mask >> (32 + SOC_RTCIO_PIN_COUNT))); } +#endif } } diff --git a/components/hal/esp32p4/include/hal/rtc_io_ll.h b/components/hal/esp32p4/include/hal/rtc_io_ll.h index a46be6823d1..2424fe20e77 100644 --- a/components/hal/esp32p4/include/hal/rtc_io_ll.h +++ b/components/hal/esp32p4/include/hal/rtc_io_ll.h @@ -18,10 +18,12 @@ #include "soc/lp_gpio_struct.h" #include "soc/lp_iomux_struct.h" #include "soc/lp_gpio_sig_map.h" +#include "soc/lp_system_struct.h" #include "soc/pmu_struct.h" #include "hal/gpio_types.h" #include "hal/misc.h" #include "hal/assert.h" +#include "hal/config.h" #ifdef __cplusplus extern "C" { @@ -312,9 +314,13 @@ static inline bool rtcio_ll_is_pulldown_enabled(int rtcio_num) */ static inline void rtcio_ll_force_hold_enable(int rtcio_num) { +#if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300 + LP_SYS.pad_rtc_hold_ctrl0.pad_rtc_hold_ctrl0 |= BIT(rtcio_num); +#else uint32_t hold_mask = HAL_FORCE_READ_U32_REG_FIELD(LP_IOMUX.lp_pad_hold, reg_lp_gpio_hold); hold_mask |= BIT(rtcio_num); HAL_FORCE_MODIFY_U32_REG_FIELD(LP_IOMUX.lp_pad_hold, reg_lp_gpio_hold, hold_mask); +#endif } /** @@ -325,9 +331,13 @@ static inline void rtcio_ll_force_hold_enable(int rtcio_num) */ static inline void rtcio_ll_force_hold_disable(int rtcio_num) { +#if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300 + LP_SYS.pad_rtc_hold_ctrl0.pad_rtc_hold_ctrl0 &= ~BIT(rtcio_num); +#else uint32_t hold_mask = HAL_FORCE_READ_U32_REG_FIELD(LP_IOMUX.lp_pad_hold, reg_lp_gpio_hold); hold_mask &= ~BIT(rtcio_num); HAL_FORCE_MODIFY_U32_REG_FIELD(LP_IOMUX.lp_pad_hold, reg_lp_gpio_hold, hold_mask); +#endif } /** diff --git a/components/hal/include/hal/gpio_hal.h b/components/hal/include/hal/gpio_hal.h index e3adeb43268..f9e949ca019 100644 --- a/components/hal/include/hal/gpio_hal.h +++ b/components/hal/include/hal/gpio_hal.h @@ -323,7 +323,7 @@ void gpio_hal_intr_disable(gpio_hal_context_t *hal, uint32_t gpio_num); */ #define gpio_hal_is_digital_io_hold(hal, gpio_num) gpio_ll_is_digital_io_hold((hal)->dev, gpio_num) -#if SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP && !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP +#if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP /** * @brief Enable all digital gpio pad hold function during Deep-sleep. * @@ -354,7 +354,7 @@ void gpio_hal_intr_disable(gpio_hal_context_t *hal, uint32_t gpio_num); * - false deep sleep hold is disabled */ #define gpio_hal_deep_sleep_hold_is_en(hal) gpio_ll_deep_sleep_hold_is_en((hal)->dev) -#endif //SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP && !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP +#endif //!SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP /** * @brief Set pad input to a peripheral signal through the IOMUX. diff --git a/components/soc/esp32/include/soc/Kconfig.soc_caps.in b/components/soc/esp32/include/soc/Kconfig.soc_caps.in index fd0d76b0992..21355136a4f 100644 --- a/components/soc/esp32/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32/include/soc/Kconfig.soc_caps.in @@ -355,10 +355,6 @@ config SOC_GPIO_CLOCKOUT_CHANNEL_NUM int default 3 -config SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP - bool - default y - config SOC_I2C_NUM int default 2 diff --git a/components/soc/esp32/include/soc/soc_caps.h b/components/soc/esp32/include/soc/soc_caps.h index 8040f364fb7..5d9b02f4d9f 100644 --- a/components/soc/esp32/include/soc/soc_caps.h +++ b/components/soc/esp32/include/soc/soc_caps.h @@ -199,9 +199,6 @@ #define SOC_GPIO_CLOCKOUT_BY_IO_MUX (1) #define SOC_GPIO_CLOCKOUT_CHANNEL_NUM (3) -// RTC_IOs and DIG_IOs can be hold during deep sleep and after waking up -#define SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP (1) - /*-------------------------- I2C CAPS ----------------------------------------*/ // ESP32 has 2 I2C #define SOC_I2C_NUM (2U) diff --git a/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in index 39812894908..a79fd8fa486 100644 --- a/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in @@ -323,10 +323,6 @@ config SOC_GPIO_CLOCKOUT_CHANNEL_NUM int default 3 -config SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP - bool - default y - config SOC_I2C_NUM int default 1 diff --git a/components/soc/esp32c2/include/soc/soc_caps.h b/components/soc/esp32c2/include/soc/soc_caps.h index f8b7b24cf5d..701ee2c5ea0 100644 --- a/components/soc/esp32c2/include/soc/soc_caps.h +++ b/components/soc/esp32c2/include/soc/soc_caps.h @@ -149,9 +149,6 @@ #define SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX (1) #define SOC_GPIO_CLOCKOUT_CHANNEL_NUM (3) -// "RTC"_IOs and DIG_IOs can be hold during deep sleep and after waking up -#define SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP (1) - /*-------------------------- I2C CAPS ----------------------------------------*/ // ESP32-C2 has 1 I2C #define SOC_I2C_NUM (1U) diff --git a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in index 7d6b01b69c8..4472fc985b0 100644 --- a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in @@ -419,10 +419,6 @@ config SOC_GPIO_CLOCKOUT_CHANNEL_NUM int default 3 -config SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP - bool - default y - config SOC_I2C_NUM int default 1 diff --git a/components/soc/esp32c3/include/soc/soc_caps.h b/components/soc/esp32c3/include/soc/soc_caps.h index 9dcbeae032b..d25c7c661ea 100644 --- a/components/soc/esp32c3/include/soc/soc_caps.h +++ b/components/soc/esp32c3/include/soc/soc_caps.h @@ -188,9 +188,6 @@ #define SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX (1) #define SOC_GPIO_CLOCKOUT_CHANNEL_NUM (3) -// "RTC"_IOs and DIG_IOs can be hold during deep sleep and after waking up -#define SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP (1) - /*-------------------------- I2C CAPS ----------------------------------------*/ // ESP32-C3 has 1 I2C #define SOC_I2C_NUM (1U) diff --git a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in index 494f4098938..0c36c652073 100644 --- a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in @@ -579,10 +579,6 @@ config SOC_GPIO_SUPPORT_FORCE_HOLD bool default y -config SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP - bool - default y - config SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP bool default y diff --git a/components/soc/esp32c5/include/soc/soc_caps.h b/components/soc/esp32c5/include/soc/soc_caps.h index 16209316e63..1b8bdd4b4bf 100644 --- a/components/soc/esp32c5/include/soc/soc_caps.h +++ b/components/soc/esp32c5/include/soc/soc_caps.h @@ -237,8 +237,6 @@ // Support to force hold all IOs #define SOC_GPIO_SUPPORT_FORCE_HOLD (1) -// LP_IOs and DIG_IOs can be hold during deep sleep and after waking up -#define SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP (1) // Support to hold a single digital I/O when the digital domain is powered off #define SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP (1) diff --git a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in index 4e58fe0b164..f393b198d6c 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -511,10 +511,6 @@ config SOC_GPIO_SUPPORT_FORCE_HOLD bool default y -config SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP - bool - default y - config SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP bool default y diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index 89768a54e5e..a64d07dfdb1 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -215,8 +215,6 @@ // Support to force hold all IOs #define SOC_GPIO_SUPPORT_FORCE_HOLD (1) -// LP_IOs and DIG_IOs can be hold during deep sleep and after waking up -#define SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP (1) // Support to hold a single digital I/O when the digital domain is powered off #define SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP (1) diff --git a/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in index 7c3e574238d..55a0f500c52 100644 --- a/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in @@ -455,10 +455,6 @@ config SOC_GPIO_SUPPORT_FORCE_HOLD bool default y -config SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP - bool - default y - config SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP bool default y diff --git a/components/soc/esp32c61/include/soc/soc_caps.h b/components/soc/esp32c61/include/soc/soc_caps.h index e156c5daefd..41ea7882d0c 100644 --- a/components/soc/esp32c61/include/soc/soc_caps.h +++ b/components/soc/esp32c61/include/soc/soc_caps.h @@ -196,8 +196,6 @@ // Support to force hold all IOs #define SOC_GPIO_SUPPORT_FORCE_HOLD (1) -// "LP"_IOs and DIG_IOs can be hold during deep sleep and after waking up -#define SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP (1) // Support to hold a single digital I/O when the digital domain is powered off #define SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP (1) diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index bc81eaf985f..2bec2242c6d 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -531,10 +531,6 @@ config SOC_GPIO_SUPPORT_FORCE_HOLD bool default y -config SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP - bool - default y - config SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP bool default y diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index d46bef6e2da..1c00ce0f0cf 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -240,8 +240,6 @@ // Support to force hold all IOs #define SOC_GPIO_SUPPORT_FORCE_HOLD (1) -// LP_IOs and DIG_IOs can be hold during deep sleep and after waking up -#define SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP (1) // Support to hold a single digital I/O when the digital domain is powered off #define SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP (1) diff --git a/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in index 6bdcec69a75..1878f56aec7 100644 --- a/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in @@ -387,10 +387,6 @@ config SOC_GPIO_SUPPORT_FORCE_HOLD bool default y -config SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP - bool - default y - config SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP bool default y diff --git a/components/soc/esp32h21/include/soc/soc_caps.h b/components/soc/esp32h21/include/soc/soc_caps.h index 1475416a83b..471f8c01c81 100644 --- a/components/soc/esp32h21/include/soc/soc_caps.h +++ b/components/soc/esp32h21/include/soc/soc_caps.h @@ -220,8 +220,6 @@ // Support to force hold all IOs #define SOC_GPIO_SUPPORT_FORCE_HOLD (1) -// LP_IOs and DIG_IOs can be hold during deep sleep and after waking up -#define SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP (1) // Support to hold a single digital I/O when the digital domain is powered off #define SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP (1) diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index 62949459747..ad552e26714 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -695,6 +695,14 @@ config SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK hex default 0x007FFFFFFFFF0000 +config SOC_GPIO_SUPPORT_FORCE_HOLD + bool + default y + +config SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP + bool + default y + config SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX bool default y @@ -715,10 +723,6 @@ config SOC_DEBUG_PROBE_MAX_OUTPUT_WIDTH int default 16 -config SOC_GPIO_SUPPORT_FORCE_HOLD - bool - default y - config SOC_RTCIO_PIN_COUNT int default 16 diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index 6913444bc8f..cee0a5c85d2 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -265,6 +265,11 @@ // digital I/O pad powered by VDD3P3_CPU or VDD_SPI(GPIO_NUM_16~GPIO_NUM_54) #define SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK 0x007FFFFFFFFF0000ULL +// Support to force hold all IOs +#define SOC_GPIO_SUPPORT_FORCE_HOLD (1) +// Support to hold a single digital I/O when the digital domain is powered off +#define SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP (1) // Supported only on ESP32P4 rev >= 3.0 (see DIG-399) + // The Clock Out signal is route to the pin by GPIO matrix #define SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX (1) #define SOC_GPIO_CLOCKOUT_CHANNEL_NUM (2) @@ -273,9 +278,6 @@ #define SOC_DEBUG_PROBE_NUM_UNIT (1U) // Number of debug probe units #define SOC_DEBUG_PROBE_MAX_OUTPUT_WIDTH (16) // Maximum width of the debug probe output in each unit -// Support to force hold all IOs -#define SOC_GPIO_SUPPORT_FORCE_HOLD (1) - /*-------------------------- RTCIO CAPS --------------------------------------*/ #define SOC_RTCIO_PIN_COUNT 16 #define SOC_RTCIO_INPUT_OUTPUT_SUPPORTED 1 /* This macro indicates that the target has separate RTC IOMUX hardware feature, diff --git a/components/soc/esp32p4/register/hw_ver3/soc/hp_system_struct.h b/components/soc/esp32p4/register/hw_ver3/soc/hp_system_struct.h index 86a980f8e0e..8e62f2bec84 100644 --- a/components/soc/esp32p4/register/hw_ver3/soc/hp_system_struct.h +++ b/components/soc/esp32p4/register/hw_ver3/soc/hp_system_struct.h @@ -413,37 +413,6 @@ typedef union { } hp_crypto_ctrl_reg_t; -/** Group: HP GPIO O HOLD CTRL0 REG */ -/** Type of gpio_o_hold_ctrl0 register - * NA - */ -typedef union { - struct { - /** reg_gpio_0_hold_low : R/W; bitpos: [31:0]; default: 0; - * hold control for gpio47~16 - */ - uint32_t reg_gpio_0_hold_low:32; - }; - uint32_t val; -} hp_gpio_o_hold_ctrl0_reg_t; - - -/** Group: HP GPIO O HOLD CTRL1 REG */ -/** Type of gpio_o_hold_ctrl1 register - * NA - */ -typedef union { - struct { - /** reg_gpio_0_hold_high : R/W; bitpos: [8:0]; default: 0; - * hold control for gpio56~48 - */ - uint32_t reg_gpio_0_hold_high:9; - uint32_t reserved_9:23; - }; - uint32_t val; -} hp_gpio_o_hold_ctrl1_reg_t; - - /** Group: HP SYS RDN ECO CS REG */ /** Type of sys_rdn_eco_cs register * NA @@ -2149,8 +2118,7 @@ typedef struct hp_system_dev_t { volatile hp_cpu_corestalled_st_reg_t cpu_corestalled_st; uint32_t reserved_068[2]; volatile hp_crypto_ctrl_reg_t crypto_ctrl; - volatile hp_gpio_o_hold_ctrl0_reg_t gpio_o_hold_ctrl0; - volatile hp_gpio_o_hold_ctrl1_reg_t gpio_o_hold_ctrl1; + uint32_t reserved_074[2]; volatile hp_sys_rdn_eco_cs_reg_t sys_rdn_eco_cs; volatile hp_cache_apb_postw_en_reg_t cache_apb_postw_en; volatile hp_l2_mem_subsize_reg_t l2_mem_subsize; diff --git a/components/soc/esp32p4/register/hw_ver3/soc/lp_iomux_struct.h b/components/soc/esp32p4/register/hw_ver3/soc/lp_iomux_struct.h index 740839aecdc..c445ffbd166 100644 --- a/components/soc/esp32p4/register/hw_ver3/soc/lp_iomux_struct.h +++ b/components/soc/esp32p4/register/hw_ver3/soc/lp_iomux_struct.h @@ -114,22 +114,6 @@ typedef union { } lp_iomux_ext_wakeup0_sel_reg_t; -/** Group: lp_pad_hold */ -/** Type of lp_pad_hold register - * Reserved - */ -typedef union { - struct { - /** reg_lp_gpio_hold : R/W; bitpos: [15:0]; default: 0; - * Reserved - */ - uint32_t reg_lp_gpio_hold:16; - uint32_t reserved_16:16; - }; - uint32_t val; -} lp_iomux_lp_pad_hold_reg_t; - - /** Group: lp_pad_hys */ /** Type of lp_pad_hys register * Reserved @@ -151,7 +135,7 @@ typedef struct lp_iomux_dev_t { volatile lp_iomux_ver_date_reg_t ver_date; volatile lp_iomux_pad_reg_t pad[16]; volatile lp_iomux_ext_wakeup0_sel_reg_t ext_wakeup0_sel; - volatile lp_iomux_lp_pad_hold_reg_t lp_pad_hold; + uint32_t reserved_04c; volatile lp_iomux_lp_pad_hys_reg_t lp_pad_hys; } lp_iomux_dev_t; diff --git a/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in index 30ed2429973..186d2ae2b65 100644 --- a/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in @@ -415,10 +415,6 @@ config SOC_GPIO_CLOCKOUT_CHANNEL_NUM int default 3 -config SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP - bool - default y - config SOC_DEDIC_GPIO_HAS_INTERRUPT bool default y diff --git a/components/soc/esp32s2/include/soc/soc_caps.h b/components/soc/esp32s2/include/soc/soc_caps.h index dbacc847a0c..6376fe2a58b 100644 --- a/components/soc/esp32s2/include/soc/soc_caps.h +++ b/components/soc/esp32s2/include/soc/soc_caps.h @@ -190,9 +190,6 @@ #define SOC_GPIO_CLOCKOUT_BY_IO_MUX (1) #define SOC_GPIO_CLOCKOUT_CHANNEL_NUM (3) -// RTC_IOs and DIG_IOs can be hold during deep sleep and after waking up -#define SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP (1) - /*-------------------------- Dedicated GPIO CAPS ---------------------------------------*/ #define SOC_DEDIC_GPIO_HAS_INTERRUPT (1) /*!< Dedicated GPIO has its own interrupt source */ diff --git a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in index 805a2dfc88c..1af3e5af9ac 100644 --- a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in @@ -479,10 +479,6 @@ config SOC_GPIO_CLOCKOUT_CHANNEL_NUM int default 3 -config SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP - bool - default y - config SOC_I2C_NUM int default 2 diff --git a/components/soc/esp32s3/include/soc/soc_caps.h b/components/soc/esp32s3/include/soc/soc_caps.h index dd2ed30876c..bb599f03817 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -201,9 +201,6 @@ #define SOC_GPIO_CLOCKOUT_BY_IO_MUX (1) #define SOC_GPIO_CLOCKOUT_CHANNEL_NUM (3) -// RTC_IOs and DIG_IOs can be hold during deep sleep and after waking up -#define SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP (1) - /*-------------------------- I2C CAPS ----------------------------------------*/ // ESP32-S3 has 2 I2C #define SOC_I2C_NUM (2U) From 05c2486d8b48e3c4d6350c241bc2d9083ebdfb4a Mon Sep 17 00:00:00 2001 From: Song Ruo Jing Date: Tue, 11 Nov 2025 17:02:32 +0800 Subject: [PATCH 060/106] fix(clk): 400MHz CPU should still be selectable on ESP32-P4 less than rev3 --- components/esp_system/port/CMakeLists.txt | 4 ++++ components/esp_system/port/soc/esp32p4/Kconfig.cpu | 1 - 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/components/esp_system/port/CMakeLists.txt b/components/esp_system/port/CMakeLists.txt index d3adc03954a..0aa682d0561 100644 --- a/components/esp_system/port/CMakeLists.txt +++ b/components/esp_system/port/CMakeLists.txt @@ -6,6 +6,10 @@ endif() target_include_directories(${COMPONENT_LIB} PRIVATE ${INCLUDE_FILES} include/private) +if(CONFIG_ESP32P4_SELECTS_REV_LESS_V3 AND CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_400) + message(WARNING "400 MHz CPU frequency is not guaranteed to work on all chips with revision prior to rev 3!") +endif() + set(srcs "cpu_start.c" "panic_handler.c" "esp_system_chip.c") if(NOT CONFIG_APP_BUILD_TYPE_PURE_RAM_APP) diff --git a/components/esp_system/port/soc/esp32p4/Kconfig.cpu b/components/esp_system/port/soc/esp32p4/Kconfig.cpu index 47064a383ac..d88464cc994 100644 --- a/components/esp_system/port/soc/esp32p4/Kconfig.cpu +++ b/components/esp_system/port/soc/esp32p4/Kconfig.cpu @@ -14,7 +14,6 @@ choice ESP_DEFAULT_CPU_FREQ_MHZ depends on ESP32P4_SELECTS_REV_LESS_V3 config ESP_DEFAULT_CPU_FREQ_MHZ_400 bool "400 MHz" - depends on !ESP32P4_SELECTS_REV_LESS_V3 endchoice config ESP_DEFAULT_CPU_FREQ_MHZ From b4ce71b7460780527a1b488f1653bf4fbeb5ce8c Mon Sep 17 00:00:00 2001 From: zwx Date: Mon, 3 Nov 2025 19:31:21 +0800 Subject: [PATCH 061/106] feat(esp_coex): set the pull mode of the external coex input pin --- components/esp_coex/src/coexist.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/components/esp_coex/src/coexist.c b/components/esp_coex/src/coexist.c index 3d916c69dce..8a276cea8a8 100644 --- a/components/esp_coex/src/coexist.c +++ b/components/esp_coex/src/coexist.c @@ -189,6 +189,7 @@ esp_err_t esp_enable_extern_coex_gpio_pin(external_coex_wire_t wire_type, esp_ex { gpio_func_sel(gpio_pin.priority, PIN_FUNC_GPIO); gpio_set_direction(gpio_pin.priority, GPIO_MODE_INPUT); + gpio_set_pull_mode(gpio_pin.priority, GPIO_PULLDOWN_ONLY); esp_rom_gpio_connect_in_signal(gpio_pin.priority, EXTERNAL_COEX_SIGNAL_I1_IDX, false); REG_SET_FIELD(GPIO_PIN_REG(gpio_pin.priority), GPIO_PIN1_SYNC1_BYPASS, 2); REG_SET_FIELD(GPIO_PIN_REG(gpio_pin.priority), GPIO_PIN1_SYNC2_BYPASS, 2); @@ -206,6 +207,7 @@ esp_err_t esp_enable_extern_coex_gpio_pin(external_coex_wire_t wire_type, esp_ex { gpio_func_sel(gpio_pin.request, PIN_FUNC_GPIO); gpio_set_direction(gpio_pin.request, GPIO_MODE_INPUT); + gpio_set_pull_mode(gpio_pin.request, GPIO_PULLDOWN_ONLY); esp_rom_gpio_connect_in_signal(gpio_pin.request, EXTERNAL_COEX_SIGNAL_I0_IDX, false); REG_SET_FIELD(GPIO_PIN_REG(gpio_pin.request), GPIO_PIN1_SYNC1_BYPASS, 2); REG_SET_FIELD(GPIO_PIN_REG(gpio_pin.request), GPIO_PIN1_SYNC2_BYPASS, 2); @@ -224,6 +226,7 @@ esp_err_t esp_enable_extern_coex_gpio_pin(external_coex_wire_t wire_type, esp_ex { gpio_func_sel(gpio_pin.tx_line, PIN_FUNC_GPIO); gpio_set_direction(gpio_pin.tx_line, GPIO_MODE_INPUT); + gpio_set_pull_mode(gpio_pin.tx_line, GPIO_PULLDOWN_ONLY); esp_rom_gpio_connect_in_signal(gpio_pin.tx_line, EXTERNAL_COEX_SIGNAL_I1_IDX, false); REG_SET_FIELD(GPIO_PIN_REG(gpio_pin.tx_line), GPIO_PIN1_SYNC1_BYPASS, 2); REG_SET_FIELD(GPIO_PIN_REG(gpio_pin.tx_line), GPIO_PIN1_SYNC2_BYPASS, 2); @@ -241,6 +244,7 @@ esp_err_t esp_enable_extern_coex_gpio_pin(external_coex_wire_t wire_type, esp_ex { gpio_func_sel(gpio_pin.grant, PIN_FUNC_GPIO); gpio_set_direction(gpio_pin.grant, GPIO_MODE_INPUT); + gpio_set_pull_mode(gpio_pin.grant, GPIO_PULLUP_ONLY); esp_rom_gpio_connect_in_signal(gpio_pin.grant, EXTERNAL_COEX_SIGNAL_I0_IDX, false); REG_SET_FIELD(GPIO_PIN_REG(gpio_pin.grant), GPIO_PIN1_SYNC1_BYPASS, 2); REG_SET_FIELD(GPIO_PIN_REG(gpio_pin.grant), GPIO_PIN1_SYNC2_BYPASS, 2); From 2206242fc8d9020d7fc397b59608609399a53bb4 Mon Sep 17 00:00:00 2001 From: Mahavir Jain Date: Wed, 5 Nov 2025 13:03:21 +0530 Subject: [PATCH 062/106] fix(lwip): allow task stack from SPIRAM except for ESP32 ECO2 and below Closes https://github.com/espressif/esp-idf/issues/17827 --- components/lwip/port/hooks/tcp_isn_default.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/components/lwip/port/hooks/tcp_isn_default.c b/components/lwip/port/hooks/tcp_isn_default.c index 71020cee515..7996b2f3d90 100644 --- a/components/lwip/port/hooks/tcp_isn_default.c +++ b/components/lwip/port/hooks/tcp_isn_default.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -82,6 +82,10 @@ #include "esp_rom_md5.h" #ifdef CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY #include "esp_memory_utils.h" +#if CONFIG_IDF_TARGET_ESP32 +#include "hal/efuse_hal.h" +#include "soc/chip_revision.h" +#endif #endif #ifdef CONFIG_LWIP_HOOK_TCP_ISN_DEFAULT @@ -169,13 +173,13 @@ lwip_hook_tcp_isn(const ip_addr_t *local_ip, u16_t local_port, /* * Generate the hash using ROM MD5 APIs - * This hook is invoked in the context of TCP/IP (tiT) task and - * it is unlikely that its stack would be placed in SPIRAM. Hence - * even with SPIRAM enabled case and ESP32 revision < 3, using ROM - * APIs should not create any issues. + * For ESP32 chips prior to ECO3, the stack pointer must not point to external RAM + * to use the ROM MD5 functions. + * Other chips (ESP32-S2, ESP32-S3, ESP32-C3, etc.) don't have this limitation. */ -#if CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY - assert(!esp_ptr_external_ram(esp_cpu_get_sp())); +#if CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY && CONFIG_IDF_TARGET_ESP32 + /* Only assert for ESP32 revision < ECO3 (revision 300) */ + assert(ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 300) || !esp_ptr_external_ram(esp_cpu_get_sp())); #endif md5_context_t ctx; From 0f7737474673f9c6269f4a622f76a52e86fa5563 Mon Sep 17 00:00:00 2001 From: Mahavir Jain Date: Wed, 12 Nov 2025 17:50:18 +0530 Subject: [PATCH 063/106] fix(esp_system): limit CPU clock to 160MHz in ESP32-C5 for flash encryption Encrypted flash write operation sometimes result in random corruption in certain bytes. Root cause points to sudden current surge due to involvement of encryption block overwhelming LDO supply. More details will be provided in the ESP32-C5 SoC Errata document. This fix limits the CPU clock to 160MHz for flash encryption enabled case. Failing encrypted flash write tests could successfully pass in this configuration. Going ahead, a dynamic clock adjustment in flash driver will be considered to mitigate this issue. --- components/esp_security/src/init.c | 10 ++++++++++ components/esp_system/port/soc/esp32c5/Kconfig.cpu | 8 +++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/components/esp_security/src/init.c b/components/esp_security/src/init.c index 17196935f30..00d094ad3a6 100644 --- a/components/esp_security/src/init.c +++ b/components/esp_security/src/init.c @@ -55,6 +55,16 @@ static void esp_key_mgr_init(void) ESP_SYSTEM_INIT_FN(esp_security_init, SECONDARY, BIT(0), 103) { +#if CONFIG_IDF_TARGET_ESP32C5 + // Check for unsupported configuration: flash encryption with CPU frequency > 160MHz + // Manual encrypted flash writes are not stable at higher CPU clock. + // Please refer to the ESP32-C5 SoC Errata document for more details. + if (efuse_hal_flash_encryption_enabled() && CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ > 160) { + ESP_EARLY_LOGE(TAG, "Flash encryption with CPU frequency > 160MHz is not supported. Please reconfigure the CPU frequency."); + return ESP_ERR_NOT_SUPPORTED; + } +#endif + esp_crypto_clk_init(); #if SOC_KEY_MANAGER_SUPPORT_KEY_DEPLOYMENT diff --git a/components/esp_system/port/soc/esp32c5/Kconfig.cpu b/components/esp_system/port/soc/esp32c5/Kconfig.cpu index 0ce4f03b2bb..cf422222294 100644 --- a/components/esp_system/port/soc/esp32c5/Kconfig.cpu +++ b/components/esp_system/port/soc/esp32c5/Kconfig.cpu @@ -1,9 +1,12 @@ choice ESP_DEFAULT_CPU_FREQ_MHZ prompt "CPU frequency" default ESP_DEFAULT_CPU_FREQ_MHZ_40 if IDF_ENV_FPGA + default ESP_DEFAULT_CPU_FREQ_MHZ_160 if SECURE_FLASH_ENC_ENABLED default ESP_DEFAULT_CPU_FREQ_MHZ_240 help - CPU frequency to be set on application startup. + CPU frequency to be set on application startup. For flash encryption enabled case, + the default CPU frequency is 160MHz as the encrypted flash writes are not stable at + higher CPU clock. Please see SoC Errata document for details. config ESP_DEFAULT_CPU_FREQ_MHZ_40 bool "40 MHz" @@ -13,6 +16,9 @@ choice ESP_DEFAULT_CPU_FREQ_MHZ config ESP_DEFAULT_CPU_FREQ_MHZ_160 bool "160 MHz" config ESP_DEFAULT_CPU_FREQ_MHZ_240 + # Encrypted flash writes aren't supported at 240 MHz. + # Please see SoC Errata document for details. + depends on !SECURE_FLASH_ENC_ENABLED bool "240 MHz" endchoice From 6c55efc2e09c1b17ef56b33829c07cff05ee7d88 Mon Sep 17 00:00:00 2001 From: Zhou Xiao Date: Tue, 11 Nov 2025 17:07:42 +0800 Subject: [PATCH 064/106] fix(ble): increase default ble log stack size for xtensa chips --- components/bt/common/ble_log/Kconfig.in | 2 ++ components/bt/common/ble_log/ble_log_spi_out.c | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/components/bt/common/ble_log/Kconfig.in b/components/bt/common/ble_log/Kconfig.in index f3a5e5348a7..2bb05ede5af 100644 --- a/components/bt/common/ble_log/Kconfig.in +++ b/components/bt/common/ble_log/Kconfig.in @@ -7,6 +7,8 @@ config BLE_LOG_ENABLED if BLE_LOG_ENABLED config BLE_LOG_TASK_STACK_SIZE int "Stack size for BLE Log Task" + default 1024 if IDF_TARGET_ARCH_RISCV + default 2048 if IDF_TARGET_ARCH_XTENSA default 1024 help Stack size for BLE Log Task diff --git a/components/bt/common/ble_log/ble_log_spi_out.c b/components/bt/common/ble_log/ble_log_spi_out.c index ac5022054e6..a9c77abfffd 100644 --- a/components/bt/common/ble_log/ble_log_spi_out.c +++ b/components/bt/common/ble_log/ble_log_spi_out.c @@ -41,7 +41,14 @@ #define SPI_OUT_LOG_STR_BUF_SIZE (100) #define SPI_OUT_MALLOC(size) heap_caps_malloc(size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT) #define SPI_OUT_TASK_PRIORITY (ESP_TASK_PRIO_MAX - 1) + +#if CONFIG_IDF_TARGET_ARCH_RISCV #define SPI_OUT_TASK_STACK_SIZE (1024) +#elif CONFIG_IDF_TARGET_ARCH_XTENSA +#define SPI_OUT_TASK_STACK_SIZE (2048) +#else +static_assert(false, "BLE Log SPI Out: Unsupported target architecture"); +#endif /* CONFIG_IDF_TARGET_ARCH_RISCV */ #if SPI_OUT_TS_SYNC_ENABLED #define SPI_OUT_TS_SYNC_TIMEOUT_MS (1000) From fbf0e15694fe5ece291bad45de2c13f5e8051c44 Mon Sep 17 00:00:00 2001 From: Linyan Liu Date: Wed, 27 Aug 2025 16:11:56 +0800 Subject: [PATCH 065/106] feat(ble_mesh): Miscellaneous update for BLE Mesh --- components/bt/CMakeLists.txt | 13 +- components/bt/esp_ble_mesh/core/access.c | 70 ++++++- components/bt/esp_ble_mesh/core/adv.c | 86 +++----- components/bt/esp_ble_mesh/core/adv.h | 4 - components/bt/esp_ble_mesh/core/adv_common.c | 196 +++++++++--------- components/bt/esp_ble_mesh/core/adv_common.h | 54 +++-- components/bt/esp_ble_mesh/core/ble_adv.c | 33 +-- .../core/bluedroid_host/adapter.c | 8 +- components/bt/esp_ble_mesh/core/ext_adv.c | 129 +++++------- components/bt/esp_ble_mesh/core/ext_adv.h | 7 - components/bt/esp_ble_mesh/core/friend.c | 2 +- .../esp_ble_mesh/core/include/mesh/adapter.h | 10 +- components/bt/esp_ble_mesh/core/net.c | 14 +- .../esp_ble_mesh/core/nimble_host/adapter.c | 25 ++- .../bt/esp_ble_mesh/core/proxy_server.c | 10 + components/bt/esp_ble_mesh/core/scan.c | 40 ++-- components/bt/esp_ble_mesh/core/transport.c | 83 +------- .../bt/esp_ble_mesh/core/transport.enh.c | 68 ------ .../models/client/client_common.c | 51 ++--- 19 files changed, 392 insertions(+), 511 deletions(-) diff --git a/components/bt/CMakeLists.txt b/components/bt/CMakeLists.txt index d6d30e650ff..77f4919d025 100644 --- a/components/bt/CMakeLists.txt +++ b/components/bt/CMakeLists.txt @@ -562,7 +562,6 @@ if(CONFIG_BT_ENABLED) "esp_ble_mesh/core/storage/settings.c" "esp_ble_mesh/core/access.c" "esp_ble_mesh/core/adv_common.c" - "esp_ble_mesh/core/ble_adv.c" "esp_ble_mesh/core/beacon.c" "esp_ble_mesh/core/cfg_cli.c" "esp_ble_mesh/core/cfg_srv.c" @@ -619,6 +618,7 @@ if(CONFIG_BT_ENABLED) "esp_ble_mesh/common/tinycrypt/src/sha256.c" "esp_ble_mesh/common/tinycrypt/src/utils.c") endif() + if(CONFIG_BLE_MESH_V11_SUPPORT) list(APPEND include_dirs ${ble_mesh_v11_include_dirs}) @@ -655,24 +655,27 @@ if(CONFIG_BT_ENABLED) "esp_ble_mesh/v1.1/dfu/dfu_slot.c" "esp_ble_mesh/v1.1/dfu/dfu_metadata.c" "esp_ble_mesh/lib/ext.c") + if(CONFIG_BLE_MESH_SAR_ENHANCEMENT) list(APPEND srcs "esp_ble_mesh/core/transport.enh.c") else() list(APPEND srcs "esp_ble_mesh/core/transport.c") endif() else() - list(APPEND srcs - "esp_ble_mesh/core/transport.c") + list(APPEND srcs "esp_ble_mesh/core/transport.c") endif() + if(CONFIG_BLE_MESH_SUPPORT_MULTI_ADV) list(APPEND srcs "esp_ble_mesh/core/ext_adv.c") else() list(APPEND srcs "esp_ble_mesh/core/adv.c") endif() + + if(CONFIG_BLE_MESH_SUPPORT_BLE_ADV) + list(APPEND srcs "esp_ble_mesh/core/ble_adv.c") + endif() endif() - - if(CONFIG_BT_LE_CONTROLLER_NPL_OS_PORTING_SUPPORT) list(APPEND srcs "porting/npl/freertos/src/npl_os_freertos.c" diff --git a/components/bt/esp_ble_mesh/core/access.c b/components/bt/esp_ble_mesh/core/access.c index 73363c2f993..5aad6a0a848 100644 --- a/components/bt/esp_ble_mesh/core/access.c +++ b/components/bt/esp_ble_mesh/core/access.c @@ -117,7 +117,7 @@ static int32_t next_period(struct bt_mesh_model *mod) if (!pub) { BT_ERR("Model has no publication support"); - return -ENOTSUP; + return 0; } period = bt_mesh_model_pub_period_get(mod); @@ -1404,3 +1404,71 @@ struct bt_mesh_app_key *bt_mesh_rx_appkey_get(size_t index) return key; } + +struct bt_mesh_app_key *bt_mesh_app_key_get(uint16_t app_idx) +{ + if (bt_mesh_is_provisioned()) { +#if CONFIG_BLE_MESH_NODE + if (!IS_ENABLED(CONFIG_BLE_MESH_FAST_PROV)) { + for (int i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) { + if (bt_mesh.app_keys[i].net_idx != BLE_MESH_KEY_UNUSED && + bt_mesh.app_keys[i].app_idx == app_idx) { + return &bt_mesh.app_keys[i]; + } + } + } else { + return bt_mesh_fast_prov_app_key_find(app_idx); + } +#endif + } else if (bt_mesh_is_provisioner_en()) { +#if CONFIG_BLE_MESH_PROVISIONER + for (int i = 0; i < ARRAY_SIZE(bt_mesh.p_app_keys); i++) { + if (bt_mesh.p_app_keys[i] && + bt_mesh.p_app_keys[i]->net_idx != BLE_MESH_KEY_UNUSED && + bt_mesh.p_app_keys[i]->app_idx == app_idx) { + return bt_mesh.p_app_keys[i]; + } + } +#endif + } + + return NULL; +} + +int bt_mesh_upper_key_get(const struct bt_mesh_subnet *subnet, uint16_t app_idx, + const uint8_t **key, uint8_t *aid, uint16_t dst) +{ + struct bt_mesh_app_key *app_key = NULL; + + if (app_idx == BLE_MESH_KEY_DEV) { + *key = bt_mesh_dev_key_get(dst); + if (!*key) { + BT_ERR("DevKey of 0x%04x not found", dst); + return -EINVAL; + } + + *aid = 0U; + return 0; + } + + if (!subnet) { + BT_ERR("Invalid subnet"); + return -EINVAL; + } + + app_key = bt_mesh_app_key_get(app_idx); + if (!app_key) { + BT_ERR("AppKey 0x%04x not found", app_idx); + return -ENOENT; + } + + if (subnet->kr_phase == BLE_MESH_KR_PHASE_2 && app_key->updated) { + *key = app_key->keys[1].val; + *aid = app_key->keys[1].id; + } else { + *key = app_key->keys[0].val; + *aid = app_key->keys[0].id; + } + + return 0; +} diff --git a/components/bt/esp_ble_mesh/core/adv.c b/components/bt/esp_ble_mesh/core/adv.c index fa4249c1875..d9096caa136 100644 --- a/components/bt/esp_ble_mesh/core/adv.c +++ b/components/bt/esp_ble_mesh/core/adv.c @@ -37,24 +37,7 @@ static QueueSetHandle_t mesh_queue_set; #endif /* CONFIG_BLE_MESH_RELAY_ADV_BUF */ -static inline void adv_send_start(uint16_t duration, int err, - const struct bt_mesh_send_cb *cb, - void *cb_data) -{ - if (cb && cb->start) { - cb->start(duration, err, cb_data); - } -} - -static inline void adv_send_end(int err, const struct bt_mesh_send_cb *cb, - void *cb_data) -{ - if (cb && cb->end) { - cb->end(err, cb_data); - } -} - -static inline int adv_send(struct net_buf *buf) +static int adv_send(struct net_buf *buf) { const struct bt_mesh_send_cb *cb = BLE_MESH_ADV(buf)->cb; void *cb_data = BLE_MESH_ADV(buf)->cb_data; @@ -201,17 +184,15 @@ static inline int adv_send(struct net_buf *buf) BT_DBG("Advertising started. Sleeping %u ms", duration); #if CONFIG_BLE_MESH_USE_BLE_50 - if (!ble_mesh_adv_task_wait(UINT32_MAX, K_FOREVER, NULL)) { + if (!bt_mesh_adv_task_wait(UINT32_MAX, K_FOREVER, NULL)) { BT_WARN("Advertising didn't finish on time"); bt_le_ext_adv_stop(CONFIG_BLE_MESH_ADV_INST_ID); } #else /* CONFIG_BLE_MESH_USE_BLE_50 */ - ble_mesh_adv_task_wait(K_MSEC(duration)); -#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ + bt_mesh_adv_task_wait(K_MSEC(duration)); -#if !CONFIG_BLE_MESH_USE_BLE_50 err = bt_le_adv_stop(); -#endif +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ adv_send_end(err, cb, cb_data); if (err) { @@ -223,15 +204,34 @@ static inline int adv_send(struct net_buf *buf) return 0; } +#if CONFIG_BLE_MESH_RELAY_ADV_BUF +static QueueHandle_t relay_adv_handle_get(void) +{ + struct bt_mesh_adv_type_manager *adv_type = NULL; + + adv_type = bt_mesh_adv_types_mgmt_get(BLE_MESH_ADV_RELAY_DATA); + + if (adv_type->adv_q == NULL) { + return NULL; + } + + return adv_type->adv_q->q.handle; +} +#endif /* CONFIG_BLE_MESH_RELAY_ADV_BUF */ + static void adv_thread(void *p) { #if CONFIG_BLE_MESH_RELAY_ADV_BUF + QueueHandle_t relay_adv_handle = NULL; QueueSetMemberHandle_t handle = NULL; - QueueHandle_t relay_adv_handle = - bt_mesh_adv_types_mgnt_get(BLE_MESH_ADV_RELAY_DATA)->adv_q->q.handle; #endif - bt_mesh_msg_t msg = {0}; struct net_buf **buf = NULL; + bt_mesh_msg_t msg = {0}; + +#if CONFIG_BLE_MESH_RELAY_ADV_BUF + relay_adv_handle = relay_adv_handle_get(); + assert(relay_adv_handle); +#endif /* CONFIG_BLE_MESH_RELAY_ADV_BUF */ buf = (struct net_buf **)(&msg.arg); @@ -328,28 +328,6 @@ static void adv_thread(void *p) } } -void bt_mesh_adv_send(struct net_buf *buf, uint8_t xmit, - const struct bt_mesh_send_cb *cb, - void *cb_data) -{ - bt_mesh_msg_t msg = { - .relay = false, - }; - - BT_DBG("type 0x%02x len %u: %s", BLE_MESH_ADV(buf)->type, buf->len, - bt_hex(buf->data, buf->len)); - - BLE_MESH_ADV(buf)->cb = cb; - BLE_MESH_ADV(buf)->cb_data = cb_data; - bt_mesh_atomic_set(&BLE_MESH_ADV_BUSY(buf), 1); - BLE_MESH_ADV(buf)->xmit = xmit; - - bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL); - - msg.arg = (void *)net_buf_ref(buf); - bt_mesh_task_post(&msg, portMAX_DELAY, false); -} - void bt_mesh_adv_update(void) { bt_mesh_msg_t msg = { @@ -375,11 +353,11 @@ void bt_mesh_adv_init(void) bt_mesh_ble_adv_init(); #endif -#if CONFIG_BLE_MESH_RELAY_ADV_BUF && !CONFIG_BLE_MESH_SUPPORT_MULTI_ADV - QueueHandle_t relay_adv_handle = - bt_mesh_adv_types_mgnt_get(BLE_MESH_ADV_RELAY_DATA)->adv_q->q.handle; +#if CONFIG_BLE_MESH_RELAY_ADV_BUF + QueueHandle_t relay_adv_handle = relay_adv_handle_get(); + assert(relay_adv_handle); mesh_queue_set = xQueueCreateSet(BLE_MESH_QUEUE_SET_SIZE); - __ASSERT(mesh_queue_set, "Failed to create queue set"); + assert(mesh_queue_set); xQueueAddToSet(adv_queue->q.handle, mesh_queue_set); xQueueAddToSet(relay_adv_handle, mesh_queue_set); #endif @@ -394,8 +372,8 @@ void bt_mesh_adv_deinit(void) bt_mesh_adv_task_deinit(); #if CONFIG_BLE_MESH_RELAY_ADV_BUF - QueueHandle_t relay_adv_handle = - bt_mesh_adv_types_mgnt_get(BLE_MESH_ADV_RELAY_DATA)->adv_q->q.handle; + QueueHandle_t relay_adv_handle = relay_adv_handle_get(); + assert(relay_adv_handle); xQueueRemoveFromSet(adv_queue->q.handle, mesh_queue_set); xQueueRemoveFromSet(relay_adv_handle, mesh_queue_set); diff --git a/components/bt/esp_ble_mesh/core/adv.h b/components/bt/esp_ble_mesh/core/adv.h index 5770364a2e3..a2c8dd03301 100644 --- a/components/bt/esp_ble_mesh/core/adv.h +++ b/components/bt/esp_ble_mesh/core/adv.h @@ -23,10 +23,6 @@ extern "C" { #endif -void bt_mesh_adv_send(struct net_buf *buf, uint8_t xmit, - const struct bt_mesh_send_cb *cb, - void *cb_data); - void bt_mesh_adv_update(void); void bt_mesh_adv_init(void); diff --git a/components/bt/esp_ble_mesh/core/adv_common.c b/components/bt/esp_ble_mesh/core/adv_common.c index 96b4ac773ae..ec1e3b68dbc 100644 --- a/components/bt/esp_ble_mesh/core/adv_common.c +++ b/components/bt/esp_ble_mesh/core/adv_common.c @@ -76,15 +76,7 @@ static inline void init_adv_with_defaults(struct bt_mesh_adv *adv, NET_BUF_POOL_FIXED_DEFINE(friend_buf_pool, FRIEND_BUF_COUNT, BLE_MESH_ADV_DATA_SIZE, NULL); -bt_mesh_friend_adv_t frnd_adv_pool[FRIEND_BUF_COUNT]; - -struct bt_mesh_adv *bt_mesh_frnd_adv_buf_get(int idx, enum bt_mesh_adv_type type) -{ - memset(&frnd_adv_pool[idx].adv, 0, sizeof(struct bt_mesh_adv)); - init_adv_with_defaults(&frnd_adv_pool[idx].adv, type); - frnd_adv_pool[idx].app_idx = BLE_MESH_KEY_UNUSED; - return &frnd_adv_pool[idx].adv; -} +static bt_mesh_friend_adv_t frnd_adv_pool[FRIEND_BUF_COUNT]; #endif struct bt_mesh_adv_task { @@ -102,7 +94,7 @@ static struct bt_mesh_adv_type_manager adv_types[BLE_MESH_ADV_TYPES_NUM]; #if CONFIG_BLE_MESH_USE_BLE_50 static struct bt_mesh_adv_inst adv_insts[] = { - [BLE_MESH_ADV_INS] = { + [BLE_MESH_ADV_INST] = { .id = CONFIG_BLE_MESH_ADV_INST_ID, #if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV .busy = false, @@ -111,19 +103,19 @@ static struct bt_mesh_adv_inst adv_insts[] = { #if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV #if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ CONFIG_BLE_MESH_GATT_PROXY_SERVER - [BLE_MESH_ADV_PROXY_INS] = { + [BLE_MESH_ADV_PROXY_INST] = { .id = CONFIG_BLE_MESH_PROXY_ADV_INST_ID, .busy = false, }, #endif #if CONFIG_BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE - [BLE_MESH_RELAY_ADV_INS] = { + [BLE_MESH_RELAY_ADV_INST] = { .id = CONFIG_BLE_MESH_RELAY_ADV_INST_ID, .busy = false, }, #endif #if CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE - [BLE_MESH_BLE_ADV_INS] = { + [BLE_MESH_BLE_ADV_INST] = { .id = CONFIG_BLE_MESH_BLE_ADV_INST_ID, .busy = false, }, @@ -154,7 +146,7 @@ bool bt_mesh_is_adv_inst_used(uint8_t adv_inst_id) int bt_mesh_adv_inst_init(enum bt_mesh_adv_inst_type inst_type, uint8_t inst_id) { - if (inst_type >= BLE_MESH_ADV_INS_TYPES_NUM) { + if (inst_type >= BLE_MESH_ADV_INST_TYPES_NUM) { BT_ERR("Invalid instance type %d", inst_type); return -EINVAL; } @@ -170,7 +162,7 @@ int bt_mesh_adv_inst_init(enum bt_mesh_adv_inst_type inst_type, uint8_t inst_id) int bt_mesh_adv_inst_deinit(enum bt_mesh_adv_inst_type inst_type) { - if (inst_type >= BLE_MESH_ADV_INS_TYPES_NUM) { + if (inst_type >= BLE_MESH_ADV_INST_TYPES_NUM) { BT_ERR("Invalid instance type %d", inst_type); return -EINVAL; } @@ -186,7 +178,7 @@ int bt_mesh_adv_inst_deinit(enum bt_mesh_adv_inst_type inst_type) #endif /* CONFIG_BLE_MESH_USE_BLE_50 */ -struct bt_mesh_adv *adv_alloc(int id, enum bt_mesh_adv_type type) +static struct bt_mesh_adv *adv_alloc(int id, enum bt_mesh_adv_type type) { init_adv_with_defaults(&adv_pool[id], type); return &adv_pool[id]; @@ -268,10 +260,10 @@ void bt_mesh_adv_buf_ref_debug(const char *func, struct net_buf *buf, } #if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV -void bt_mesh_adv_inst_supported_adv_type_add(enum bt_mesh_adv_inst_type inst_type, - enum bt_mesh_adv_type adv_type) +void bt_mesh_adv_inst_type_add(enum bt_mesh_adv_inst_type inst_type, + enum bt_mesh_adv_type adv_type) { - if (inst_type >= BLE_MESH_ADV_INS_TYPES_NUM) { + if (inst_type >= BLE_MESH_ADV_INST_TYPES_NUM) { BT_ERR("Invalid instance type %d", inst_type); return; } @@ -284,10 +276,10 @@ void bt_mesh_adv_inst_supported_adv_type_add(enum bt_mesh_adv_inst_type inst_typ adv_insts[inst_type].spt_mask |= BIT(adv_type); } -void bt_mesh_adv_inst_supported_adv_type_rm(enum bt_mesh_adv_inst_type inst_type, - enum bt_mesh_adv_type adv_type) +void bt_mesh_adv_inst_type_rm(enum bt_mesh_adv_inst_type inst_type, + enum bt_mesh_adv_type adv_type) { - if (inst_type >= BLE_MESH_ADV_INS_TYPES_NUM) { + if (inst_type >= BLE_MESH_ADV_INST_TYPES_NUM) { BT_ERR("Invalid instance type %d", inst_type); return; } @@ -303,7 +295,7 @@ void bt_mesh_adv_inst_supported_adv_type_rm(enum bt_mesh_adv_inst_type inst_type void bt_mesh_adv_inst_supported_adv_type_clear(enum bt_mesh_adv_inst_type inst_type, enum bt_mesh_adv_type adv_type) { - if (inst_type >= BLE_MESH_ADV_INS_TYPES_NUM) { + if (inst_type >= BLE_MESH_ADV_INST_TYPES_NUM) { BT_ERR("Invalid instance type %d", inst_type); return; } @@ -379,18 +371,18 @@ void bt_mesh_adv_type_deinit(enum bt_mesh_adv_type adv_type) } #if CONFIG_BLE_MESH_USE_BLE_50 -int ble_mesh_adv_task_wakeup(uint32_t evt) +int bt_mesh_adv_task_wakeup(uint32_t evt) { xTaskNotify(adv_task.handle, evt, eSetBits); return 0; } -bool ble_mesh_adv_task_wait(uint32_t wait_bits, uint32_t timeout, uint32_t *notify) +bool bt_mesh_adv_task_wait(uint32_t wait_bits, uint32_t timeout, uint32_t *notify) { return (xTaskNotifyWait(wait_bits, UINT32_MAX, notify, K_WAIT(timeout)) == pdTRUE); } #else /* CONFIG_BLE_MESH_USE_BLE_50 */ -bool ble_mesh_adv_task_wait(uint32_t timeout) +bool bt_mesh_adv_task_wait(uint32_t timeout) { vTaskDelay(K_WAIT(timeout)); return true; @@ -408,25 +400,29 @@ uint16_t bt_mesh_pdu_duration(uint8_t xmit) return duration; } -struct net_buf *bt_mesh_adv_create_from_pool(enum bt_mesh_adv_type type, - int32_t timeout) +struct net_buf *bt_mesh_adv_create_from_pool(enum bt_mesh_adv_type type, int32_t timeout) { struct bt_mesh_adv *adv = NULL; struct net_buf *buf = NULL; - struct net_buf_pool *pool = adv_types[type].pool; if (bt_mesh_atomic_test_bit(bt_mesh.flags, BLE_MESH_SUSPENDED)) { BT_WARN("Refusing to allocate buffer while suspended"); return NULL; } - if (!pool || !adv_types[type].pool_allocator) { + if (type >= BLE_MESH_ADV_TYPES_NUM) { + BT_ERR("%s, Invalid adv type %u", __func__, type); + return NULL; + } + + if (adv_types[type].pool == NULL || adv_types[type].pool_allocator == NULL) { BT_ERR("Uninitialized adv type %d", type); return NULL; } bt_mesh_r_mutex_lock(&adv_buf_alloc_lock); - buf = net_buf_alloc(pool, timeout); + + buf = net_buf_alloc(adv_types[type].pool, timeout); if (!buf) { bt_mesh_r_mutex_unlock(&adv_buf_alloc_lock); BT_WARN("Buf alloc failed"); @@ -434,7 +430,8 @@ struct net_buf *bt_mesh_adv_create_from_pool(enum bt_mesh_adv_type type, } BT_DBG("pool %p, buf_count %d, uinit_count %d, ref %d", - buf->pool, pool->buf_count, pool->uninit_count, buf->ref); + adv_types[type].pool, adv_types[type].pool->buf_count, + adv_types[type].pool->uninit_count, buf->ref); adv = adv_types[type].pool_allocator(net_buf_id(buf), type); BLE_MESH_ADV(buf) = adv; @@ -460,10 +457,9 @@ void bt_mesh_unref_buf_from_pool(struct net_buf_pool *pool) void bt_mesh_unref_buf(bt_mesh_msg_t *msg) { - struct net_buf *buf = NULL; + struct net_buf *buf = msg->arg; - if (msg->arg) { - buf = (struct net_buf *)msg->arg; + if (buf) { bt_mesh_atomic_set(&BLE_MESH_ADV_BUSY(buf), 0); if (buf->ref > 1U) { buf->ref = 1U; @@ -502,12 +498,13 @@ void bt_mesh_generic_adv_send(struct net_buf *buf, uint8_t xmit, } #endif - assert(adv_types[BLE_MESH_ADV(buf)->type].adv_q && adv_types[BLE_MESH_ADV(buf)->type].adv_q->send); + assert(adv_types[BLE_MESH_ADV(buf)->type].adv_q); + assert(adv_types[BLE_MESH_ADV(buf)->type].adv_q->send); adv_types[BLE_MESH_ADV(buf)->type].adv_q->send(&msg, portMAX_DELAY, front); #if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV - ble_mesh_adv_task_wakeup(ADV_TASK_PKT_SEND_EVT); + bt_mesh_adv_task_wakeup(ADV_TASK_PKT_SEND_EVT); #endif } @@ -558,12 +555,7 @@ static struct bt_mesh_adv *relay_adv_alloc(int id, enum bt_mesh_adv_type type) return &relay_adv_pool[id]; } -struct net_buf *bt_mesh_relay_adv_create(enum bt_mesh_adv_type type, int32_t timeout) -{ - return bt_mesh_adv_create_from_pool(type, timeout); -} - -static void ble_mesh_relay_task_post(bt_mesh_msg_t *msg, uint32_t timeout, bool front) +static void bt_mesh_relay_task_post(bt_mesh_msg_t *msg, uint32_t timeout, bool front) { bt_mesh_msg_t old_msg = {0}; @@ -609,7 +601,7 @@ uint16_t bt_mesh_get_stored_relay_count(void) } static ALWAYS_INLINE -uint16_t ble_mesh_relay_adv_buf_count_get(void) +uint16_t bt_mesh_relay_adv_buf_count_get(void) { uint16_t relay_adv_count = 2 + CONFIG_BLE_MESH_RELAY_ADV_BUF_COUNT; @@ -625,8 +617,8 @@ uint16_t ble_mesh_relay_adv_buf_count_get(void) void bt_mesh_relay_adv_init(void) { - bt_mesh_adv_queue_init(&relay_adv_queue, ble_mesh_relay_adv_buf_count_get(), - ble_mesh_relay_task_post); + bt_mesh_adv_queue_init(&relay_adv_queue, bt_mesh_relay_adv_buf_count_get(), + bt_mesh_relay_task_post); bt_mesh_adv_type_init(BLE_MESH_ADV_RELAY_DATA, &relay_adv_queue, &relay_adv_buf_pool, &relay_adv_alloc); #if CONFIG_BLE_MESH_EXT_ADV @@ -634,29 +626,29 @@ void bt_mesh_relay_adv_init(void) &ext_adv_buf_pool, &ext_relay_adv_alloc); #if CONFIG_BLE_MESH_LONG_PACKET && CONFIG_BLE_MESH_LONG_PACKET_RELAY_ADV_BUF_COUNT bt_mesh_adv_type_init(BLE_MESH_ADV_EXT_LONG_RELAY_DATA, &relay_adv_queue, - &ext_long_relay_adv_buf_pool, ext_long_relay_adv_alloc); -#endif /* CONFIG_BLE_MESH_LONG_PACKET */ + &ext_long_relay_adv_buf_pool, ext_long_relay_adv_alloc); +#endif /* CONFIG_BLE_MESH_LONG_PACKET && CONFIG_BLE_MESH_LONG_PACKET_RELAY_ADV_BUF_COUNT */ #endif /* CONFIG_BLE_MESH_EXT_ADV */ #if CONFIG_BLE_MESH_USE_BLE_50 #if CONFIG_BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE - bt_mesh_adv_inst_init(BLE_MESH_RELAY_ADV_INS, + bt_mesh_adv_inst_init(BLE_MESH_RELAY_ADV_INST, CONFIG_BLE_MESH_RELAY_ADV_INST_ID); - bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_RELAY_ADV_INS, BLE_MESH_ADV_RELAY_DATA); + bt_mesh_adv_inst_type_add(BLE_MESH_RELAY_ADV_INST, BLE_MESH_ADV_RELAY_DATA); #if CONFIG_BLE_MESH_EXT_ADV - bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_RELAY_ADV_INS, BLE_MESH_ADV_EXT_RELAY_DATA); + bt_mesh_adv_inst_type_add(BLE_MESH_RELAY_ADV_INST, BLE_MESH_ADV_EXT_RELAY_DATA); #if CONFIG_BLE_MESH_LONG_PACKET - bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_RELAY_ADV_INS, BLE_MESH_ADV_EXT_LONG_RELAY_DATA); + bt_mesh_adv_inst_type_add(BLE_MESH_RELAY_ADV_INST, BLE_MESH_ADV_EXT_LONG_RELAY_DATA); #endif /* CONFIG_BLE_MESH_LONG_PACKET */ #endif /* CONFIG_BLE_MESH_EXT_ADV */ -#else +#else /* CONFIG_BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE */ #if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV - bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_RELAY_DATA); + bt_mesh_adv_inst_type_add(BLE_MESH_ADV_INST, BLE_MESH_ADV_RELAY_DATA); #if CONFIG_BLE_MESH_EXT_ADV - bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_EXT_RELAY_DATA); + bt_mesh_adv_inst_type_add(BLE_MESH_ADV_INST, BLE_MESH_ADV_EXT_RELAY_DATA); #if CONFIG_BLE_MESH_LONG_PACKET - bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_EXT_LONG_RELAY_DATA); + bt_mesh_adv_inst_type_add(BLE_MESH_ADV_INST, BLE_MESH_ADV_EXT_LONG_RELAY_DATA); #endif /* CONFIG_BLE_MESH_LONG_PACKET */ #endif /* CONFIG_BLE_MESH_EXT_ADV */ #endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ @@ -673,25 +665,25 @@ void bt_mesh_relay_adv_deinit(void) #if CONFIG_BLE_MESH_LONG_PACKET bt_mesh_adv_type_deinit(BLE_MESH_ADV_EXT_LONG_RELAY_DATA); #endif /* CONFIG_BLE_MESH_LONG_PACKET */ -#endif +#endif /* CONFIG_BLE_MESH_EXT_ADV */ #if CONFIG_BLE_MESH_USE_BLE_50 #if CONFIG_BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE - bt_mesh_adv_inst_supported_adv_type_rm(BLE_MESH_RELAY_ADV_INS, BLE_MESH_ADV_RELAY_DATA); + bt_mesh_adv_inst_type_rm(BLE_MESH_RELAY_ADV_INST, BLE_MESH_ADV_RELAY_DATA); #if CONFIG_BLE_MESH_EXT_ADV - bt_mesh_adv_inst_supported_adv_type_rm(BLE_MESH_RELAY_ADV_INS, BLE_MESH_ADV_EXT_RELAY_DATA); + bt_mesh_adv_inst_type_rm(BLE_MESH_RELAY_ADV_INST, BLE_MESH_ADV_EXT_RELAY_DATA); #if CONFIG_BLE_MESH_LONG_PACKET - bt_mesh_adv_inst_supported_adv_type_rm(BLE_MESH_RELAY_ADV_INS, BLE_MESH_ADV_EXT_LONG_RELAY_DATA); + bt_mesh_adv_inst_type_rm(BLE_MESH_RELAY_ADV_INST, BLE_MESH_ADV_EXT_LONG_RELAY_DATA); #endif /* CONFIG_BLE_MESH_LONG_PACKET */ #endif /* CONFIG_BLE_MESH_EXT_ADV */ - bt_mesh_adv_inst_deinit(BLE_MESH_RELAY_ADV_INS); -#else + bt_mesh_adv_inst_deinit(BLE_MESH_RELAY_ADV_INST); +#else /* CONFIG_BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE */ #if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV - bt_mesh_adv_inst_supported_adv_type_rm(BLE_MESH_ADV_INS, BLE_MESH_ADV_RELAY_DATA); + bt_mesh_adv_inst_type_rm(BLE_MESH_ADV_INST, BLE_MESH_ADV_RELAY_DATA); #if CONFIG_BLE_MESH_EXT_ADV - bt_mesh_adv_inst_supported_adv_type_rm(BLE_MESH_ADV_INS, BLE_MESH_ADV_EXT_RELAY_DATA); + bt_mesh_adv_inst_type_rm(BLE_MESH_ADV_INST, BLE_MESH_ADV_EXT_RELAY_DATA); #if CONFIG_BLE_MESH_LONG_PACKET - bt_mesh_adv_inst_supported_adv_type_rm(BLE_MESH_ADV_INS, BLE_MESH_ADV_EXT_LONG_RELAY_DATA); + bt_mesh_adv_inst_type_rm(BLE_MESH_ADV_INST, BLE_MESH_ADV_EXT_LONG_RELAY_DATA); #endif /* CONFIG_BLE_MESH_LONG_PACKET */ #endif /* CONFIG_BLE_MESH_EXT_ADV */ #endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ @@ -704,16 +696,19 @@ void bt_mesh_relay_adv_deinit(void) #endif /* CONFIG_BLE_MESH_RELAY_ADV_BUF */ #if CONFIG_BLE_MESH_FRIEND -struct net_buf_pool *bt_mesh_frnd_adv_pool_get(void) +static struct bt_mesh_adv *bt_mesh_frnd_adv_buf_get(int idx, enum bt_mesh_adv_type type) { - return &friend_buf_pool; + memset(&frnd_adv_pool[idx].adv, 0, sizeof(struct bt_mesh_adv)); + init_adv_with_defaults(&frnd_adv_pool[idx].adv, type); + frnd_adv_pool[idx].app_idx = BLE_MESH_KEY_UNUSED; + return &frnd_adv_pool[idx].adv; } void bt_mesh_frnd_adv_init(void) { bt_mesh_adv_type_init(BLE_MESH_ADV_FRIEND, &adv_queue, &friend_buf_pool, bt_mesh_frnd_adv_buf_get); #if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV - bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_FRIEND); + bt_mesh_adv_inst_type_add(BLE_MESH_ADV_INST, BLE_MESH_ADV_FRIEND); #endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ } @@ -722,7 +717,7 @@ void bt_mesh_frnd_adv_deinit(void) bt_mesh_adv_type_deinit(BLE_MESH_ADV_FRIEND); #if CONFIG_BLE_MESH_FRIEND && CONFIG_BLE_MESH_SUPPORT_MULTI_ADV - bt_mesh_adv_inst_supported_adv_type_rm(BLE_MESH_ADV_INS, BLE_MESH_ADV_FRIEND); + bt_mesh_adv_inst_type_rm(BLE_MESH_ADV_INST, BLE_MESH_ADV_FRIEND); #endif /* CONFIG_BLE_MESH_FRIEND */ bt_mesh_unref_buf_from_pool(&friend_buf_pool); @@ -731,7 +726,7 @@ void bt_mesh_frnd_adv_deinit(void) #endif /* CONFIG_BLE_MESH_FRIEND */ static ALWAYS_INLINE -uint16_t ble_mesh_adv_buf_count_get(void) +uint16_t bt_mesh_adv_buf_count_get(void) { uint16_t adv_count = 2 + CONFIG_BLE_MESH_ADV_BUF_COUNT; @@ -739,15 +734,15 @@ uint16_t ble_mesh_adv_buf_count_get(void) adv_count += CONFIG_BLE_MESH_EXT_ADV_BUF_COUNT; #if !CONFIG_BLE_MESH_RELAY_ADV_BUF && CONFIG_BLE_MESH_RELAY adv_count += CONFIG_BLE_MESH_EXT_RELAY_ADV_BUF_COUNT; -#endif -#endif +#endif /* !CONFIG_BLE_MESH_RELAY_ADV_BUF && CONFIG_BLE_MESH_RELAY */ +#endif /* CONFIG_BLE_MESH_EXT_ADV */ #if CONFIG_BLE_MESH_LONG_PACKET adv_count += CONFIG_BLE_MESH_LONG_PACKET_ADV_BUF_COUNT; #if !CONFIG_BLE_MESH_RELAY_ADV_BUF && CONFIG_BLE_MESH_RELAY adv_count += CONFIG_BLE_MESH_LONG_PACKET_RELAY_ADV_BUF_COUNT; -#endif -#endif +#endif /* !CONFIG_BLE_MESH_RELAY_ADV_BUF && CONFIG_BLE_MESH_RELAY */ +#endif /* CONFIG_BLE_MESH_LONG_PACKET */ #if (CONFIG_BLE_MESH_SUPPORT_BLE_ADV && \ !(CONFIG_BLE_MESH_USE_BLE_50 && CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE)) @@ -768,24 +763,29 @@ void bt_mesh_adv_task_init(void adv_thread(void *p)) (CONFIG_SPIRAM_CACHE_WORKAROUND || !CONFIG_IDF_TARGET_ESP32) && \ CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY) adv_task.task = heap_caps_calloc(1, sizeof(StaticTask_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); - __ASSERT(adv_task.task, "Failed to create adv thread task"); - adv_task.stack = heap_caps_calloc_prefer(1, BLE_MESH_ADV_TASK_STACK_SIZE * sizeof(StackType_t), 2, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); - __ASSERT(adv_task.stack, "Failed to create adv thread stack"); - adv_task.handle = xTaskCreateStaticPinnedToCore(adv_thread, BLE_MESH_ADV_TASK_NAME, BLE_MESH_ADV_TASK_STACK_SIZE, NULL, - BLE_MESH_ADV_TASK_PRIO, adv_task.stack, adv_task.task, BLE_MESH_ADV_TASK_CORE); - __ASSERT(adv_task.handle, "Failed to create static adv thread"); + assert(adv_task.task); + + adv_task.stack = heap_caps_calloc_prefer(1, BLE_MESH_ADV_TASK_STACK_SIZE * sizeof(StackType_t), + 2, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT, + MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); + assert(adv_task.stack); + + adv_task.handle = xTaskCreateStaticPinnedToCore(adv_thread, BLE_MESH_ADV_TASK_NAME, + BLE_MESH_ADV_TASK_STACK_SIZE, NULL, + BLE_MESH_ADV_TASK_PRIO, adv_task.stack, + adv_task.task, BLE_MESH_ADV_TASK_CORE); + assert(adv_task.handle); #else /* CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL && (CONFIG_SPIRAM_CACHE_WORKAROUND || !CONFIG_IDF_TARGET_ESP32) && CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY */ int ret = xTaskCreatePinnedToCore(adv_thread, BLE_MESH_ADV_TASK_NAME, BLE_MESH_ADV_TASK_STACK_SIZE, NULL, BLE_MESH_ADV_TASK_PRIO, &adv_task.handle, BLE_MESH_ADV_TASK_CORE); - __ASSERT(ret == pdTRUE, "Failed to create adv thread"); - (void)ret; + assert(ret == pdTRUE); #endif /* CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL && (CONFIG_SPIRAM_CACHE_WORKAROUND || !CONFIG_IDF_TARGET_ESP32) && CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY */ } void bt_mesh_adv_common_init(void) { bt_mesh_r_mutex_create(&adv_buf_alloc_lock); - bt_mesh_adv_queue_init(&adv_queue, ble_mesh_adv_buf_count_get(), bt_mesh_task_post); + bt_mesh_adv_queue_init(&adv_queue, bt_mesh_adv_buf_count_get(), bt_mesh_task_post); bt_mesh_adv_type_init(BLE_MESH_ADV_PROV, &adv_queue, &adv_buf_pool, adv_alloc); bt_mesh_adv_type_init(BLE_MESH_ADV_DATA, &adv_queue, &adv_buf_pool, adv_alloc); bt_mesh_adv_type_init(BLE_MESH_ADV_BEACON, &adv_queue, &adv_buf_pool, adv_alloc); @@ -795,7 +795,7 @@ void bt_mesh_adv_common_init(void) #endif #if CONFIG_BLE_MESH_USE_BLE_50 - bt_mesh_adv_inst_init(BLE_MESH_ADV_INS, CONFIG_BLE_MESH_ADV_INST_ID); + bt_mesh_adv_inst_init(BLE_MESH_ADV_INST, CONFIG_BLE_MESH_ADV_INST_ID); #if CONFIG_BLE_MESH_EXT_ADV bt_mesh_adv_type_init(BLE_MESH_ADV_EXT_PROV, &adv_queue, &ext_adv_buf_pool, ext_adv_alloc); bt_mesh_adv_type_init(BLE_MESH_ADV_EXT_DATA, &adv_queue, &ext_adv_buf_pool, ext_adv_alloc); @@ -818,24 +818,24 @@ void bt_mesh_adv_common_init(void) * it is not possible to use multiple advertising instances to process * data from the same message queue when sending mesh packets. * - * Therefore, shall to check whether there are - * duplicates in the queue buffer corresponding to each advertising instance. - */ - bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_PROV); - bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_DATA); - bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_BEACON); - bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_URI); + * Therefore, shall to check whether there are duplicates in the queue + * buffer corresponding to each advertising instance. + */ + bt_mesh_adv_inst_type_add(BLE_MESH_ADV_INST, BLE_MESH_ADV_PROV); + bt_mesh_adv_inst_type_add(BLE_MESH_ADV_INST, BLE_MESH_ADV_DATA); + bt_mesh_adv_inst_type_add(BLE_MESH_ADV_INST, BLE_MESH_ADV_BEACON); + bt_mesh_adv_inst_type_add(BLE_MESH_ADV_INST, BLE_MESH_ADV_URI); #if CONFIG_BLE_MESH_EXT_ADV - bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_EXT_PROV); - bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_EXT_DATA); + bt_mesh_adv_inst_type_add(BLE_MESH_ADV_INST, BLE_MESH_ADV_EXT_PROV); + bt_mesh_adv_inst_type_add(BLE_MESH_ADV_INST, BLE_MESH_ADV_EXT_DATA); #if CONFIG_BLE_MESH_RELAY && !CONFIG_BLE_MESH_RELAY_ADV_BUF - bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_EXT_RELAY_DATA); + bt_mesh_adv_inst_type_add(BLE_MESH_ADV_INST, BLE_MESH_ADV_EXT_RELAY_DATA); #endif #if CONFIG_BLE_MESH_LONG_PACKET - bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_EXT_LONG_PROV); - bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_EXT_LONG_DATA); + bt_mesh_adv_inst_type_add(BLE_MESH_ADV_INST, BLE_MESH_ADV_EXT_LONG_PROV); + bt_mesh_adv_inst_type_add(BLE_MESH_ADV_INST, BLE_MESH_ADV_EXT_LONG_DATA); #if CONFIG_BLE_MESH_RELAY && !CONFIG_BLE_MESH_RELAY_ADV_BUF - bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_EXT_LONG_RELAY_DATA); + bt_mesh_adv_inst_type_add(BLE_MESH_ADV_INST, BLE_MESH_ADV_EXT_LONG_RELAY_DATA); #endif /* !CONFIG_BLE_MESH_RELAY_ADV_BUF */ #endif /* CONFIG_BLE_MESH_LONG_PACKET */ #endif /* CONFIG_BLE_MESH_EXT_ADV */ @@ -886,7 +886,7 @@ void bt_mesh_adv_common_deinit(void) bt_mesh_adv_queue_deinit(&adv_queue); #if CONFIG_BLE_MESH_USE_BLE_50 - bt_mesh_adv_inst_deinit(BLE_MESH_ADV_INS); + bt_mesh_adv_inst_deinit(BLE_MESH_ADV_INST); #endif bt_mesh_unref_buf_from_pool(&adv_buf_pool); diff --git a/components/bt/esp_ble_mesh/core/adv_common.h b/components/bt/esp_ble_mesh/core/adv_common.h index 23372d404cf..d5172a676af 100644 --- a/components/bt/esp_ble_mesh/core/adv_common.h +++ b/components/bt/esp_ble_mesh/core/adv_common.h @@ -46,7 +46,7 @@ extern "C" { #define BLE_MESH_MSG_NET_BUF(msg) ((struct net_buf *)(msg->arg)) -#define BLE_MESH_ADV_INS_UNUSED 0xFF +#define BLE_MESH_ADV_INST_UNUSED 0xFF struct bt_mesh_adv { const struct bt_mesh_send_cb *cb; @@ -128,7 +128,7 @@ struct bt_mesh_adv_inst { bool busy; struct net_buf *sending_buf; - /* indicates that which adv_type is supported by this instance */ + /* Indicate which adv_type is supported by this instance */ uint32_t spt_mask; #endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ }; @@ -212,10 +212,26 @@ static inline TickType_t K_WAIT(int32_t val) return (val == K_FOREVER) ? portMAX_DELAY : (val / portTICK_PERIOD_MS); } +static inline void adv_send_start(uint16_t duration, int err, + const struct bt_mesh_send_cb *cb, + void *cb_data) +{ + if (cb && cb->start) { + cb->start(duration, err, cb_data); + } +} + +static inline void adv_send_end(int err, const struct bt_mesh_send_cb *cb, + void *cb_data) +{ + if (cb && cb->end) { + cb->end(err, cb_data); + } +} + struct bt_mesh_adv_queue *bt_mesh_adv_queue_get(void); -struct net_buf *bt_mesh_adv_create_from_pool(enum bt_mesh_adv_type type, - int32_t timeout); +struct net_buf *bt_mesh_adv_create_from_pool(enum bt_mesh_adv_type type, int32_t timeout); static inline struct net_buf *bt_mesh_adv_create(enum bt_mesh_adv_type type, int32_t timeout) { @@ -225,13 +241,20 @@ static inline struct net_buf *bt_mesh_adv_create(enum bt_mesh_adv_type type, int void bt_mesh_adv_buf_ref_debug(const char *func, struct net_buf *buf, uint8_t ref_cmp, bt_mesh_buf_ref_flag_t flag); -struct bt_mesh_adv_type_manager *bt_mesh_adv_types_mgnt_get(enum bt_mesh_adv_type adv_type); +struct bt_mesh_adv_type_manager *bt_mesh_adv_types_mgmt_get(enum bt_mesh_adv_type adv_type); void bt_mesh_generic_adv_send(struct net_buf *buf, uint8_t xmit, const struct bt_mesh_send_cb *cb, void *cb_data, uint16_t src, uint16_t dst, bool front); +static inline void bt_mesh_adv_send(struct net_buf *buf, uint8_t xmit, + const struct bt_mesh_send_cb *cb, + void *cb_data) +{ + bt_mesh_generic_adv_send(buf, xmit, cb, cb_data, BLE_MESH_ADDR_UNASSIGNED, BLE_MESH_ADDR_UNASSIGNED, false); +} + void bt_mesh_unref_buf_from_pool(struct net_buf_pool *pool); void bt_mesh_unref_buf(bt_mesh_msg_t *msg); @@ -252,15 +275,16 @@ void bt_mesh_task_post(bt_mesh_msg_t *msg, uint32_t timeout, bool front); #if CONFIG_BLE_MESH_USE_BLE_50 struct bt_mesh_adv_inst * bt_mesh_get_adv_insts_set(void); +bool bt_mesh_is_adv_inst_used(uint8_t adv_inst_id); int bt_mesh_adv_inst_init(enum bt_mesh_adv_inst_type inst_type, uint8_t inst_id); int bt_mesh_adv_inst_deinit(enum bt_mesh_adv_inst_type inst_type); #endif /* CONFIG_BLE_MESH_USE_BLE_50 */ #if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV -void bt_mesh_adv_inst_supported_adv_type_add(enum bt_mesh_adv_inst_type inst_type, +void bt_mesh_adv_inst_type_add(enum bt_mesh_adv_inst_type inst_type, enum bt_mesh_adv_type adv_type); -void bt_mesh_adv_inst_supported_adv_type_rm(enum bt_mesh_adv_inst_type inst_type, +void bt_mesh_adv_inst_type_rm(enum bt_mesh_adv_inst_type inst_type, enum bt_mesh_adv_type adv_type); void bt_mesh_adv_inst_supported_adv_type_clear(enum bt_mesh_adv_inst_type inst_type, @@ -270,7 +294,6 @@ void bt_mesh_adv_inst_supported_adv_type_clear(enum bt_mesh_adv_inst_type inst_t #if CONFIG_BLE_MESH_RELAY_ADV_BUF void bt_mesh_relay_adv_init(void); bool bt_mesh_ignore_relay_packet(uint32_t timestamp); -struct net_buf *bt_mesh_relay_adv_create(enum bt_mesh_adv_type type, int32_t timeout); static inline void bt_mesh_relay_adv_send(struct net_buf *buf, uint8_t xmit, uint16_t src, uint16_t dst, @@ -288,8 +311,6 @@ void bt_mesh_relay_adv_deinit(void); #endif /* CONFIG_BLE_MESH_RELAY_ADV_BUF */ #if CONFIG_BLE_MESH_FRIEND -struct bt_mesh_adv *bt_mesh_frnd_adv_buf_get(int id, enum bt_mesh_adv_type type); -struct net_buf_pool *bt_mesh_frnd_adv_pool_get(void); void bt_mesh_frnd_adv_init(void); #if CONFIG_BLE_MESH_DEINIT void bt_mesh_frnd_adv_deinit(void); @@ -305,14 +326,19 @@ void bt_mesh_adv_common_deinit(void); #endif #if CONFIG_BLE_MESH_USE_BLE_50 -bool bt_mesh_is_adv_inst_used(uint8_t adv_inst_id); -bool ble_mesh_adv_task_wait(uint32_t wait_bits, TickType_t timeout, uint32_t *notify); -int ble_mesh_adv_task_wakeup(uint32_t evt); +int bt_mesh_adv_task_wakeup(uint32_t evt); +bool bt_mesh_adv_task_wait(uint32_t wait_bits, TickType_t timeout, uint32_t *notify); #else -bool ble_mesh_adv_task_wait(uint32_t timeout); +bool bt_mesh_adv_task_wait(uint32_t timeout); #endif #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV +static inline void bt_mesh_ble_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb, + void *cb_data, bool front) +{ + bt_mesh_generic_adv_send(buf, 0, cb, cb_data, BLE_MESH_ADDR_UNASSIGNED, BLE_MESH_ADDR_UNASSIGNED, front); +} + int bt_mesh_start_ble_advertising(const struct bt_mesh_ble_adv_param *param, const struct bt_mesh_ble_adv_data *data, uint8_t *index); diff --git a/components/bt/esp_ble_mesh/core/ble_adv.c b/components/bt/esp_ble_mesh/core/ble_adv.c index 110e52e2204..e27109c0471 100644 --- a/components/bt/esp_ble_mesh/core/ble_adv.c +++ b/components/bt/esp_ble_mesh/core/ble_adv.c @@ -14,14 +14,14 @@ #include "mesh/common.h" #include "mesh/buf.h" -#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV #if CONFIG_BLE_MESH_USE_BLE_50 && CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE /* Use independent ble adv queue only if multi adv instance is used */ static struct bt_mesh_adv_queue ble_adv_queue; static void bt_mesh_ble_task_post(bt_mesh_msg_t *msg, uint32_t timeout, bool front); #endif + static struct bt_mesh_adv_queue *p_ble_adv_queue; -#define BLE_MESH_BLE_ADV_QUEUE_SIZE (CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT + 1) + /* length + advertising data + length + scan response data */ NET_BUF_POOL_DEFINE(ble_adv_buf_pool, CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT, ((BLE_MESH_ADV_DATA_SIZE + 3) << 1), BLE_MESH_ADV_USER_DATA_SIZE, NULL); @@ -64,17 +64,6 @@ static void bt_mesh_ble_task_post(bt_mesh_msg_t *msg, uint32_t timeout, bool fro } #endif -static struct net_buf *bt_mesh_ble_adv_create(enum bt_mesh_adv_type type, int32_t timeout) -{ - return bt_mesh_adv_create_from_pool(type, timeout); -} - -inline void bt_mesh_ble_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb, - void *cb_data, bool front) -{ - bt_mesh_generic_adv_send(buf, 0, cb, cb_data, BLE_MESH_ADDR_UNASSIGNED, BLE_MESH_ADDR_UNASSIGNED, front); -} - static void ble_adv_tx_reset(struct bt_mesh_ble_adv_tx *tx, bool unref) { if (tx->buf == NULL) { @@ -211,7 +200,7 @@ int bt_mesh_start_ble_advertising(const struct bt_mesh_ble_adv_param *param, return -EINVAL; } - buf = bt_mesh_ble_adv_create(BLE_MESH_ADV_BLE, K_NO_WAIT); + buf = bt_mesh_adv_create(BLE_MESH_ADV_BLE, K_NO_WAIT); if (!buf) { BT_ERR("No empty ble adv buffer"); return -ENOBUFS; @@ -303,11 +292,11 @@ void bt_mesh_ble_adv_init(void) bt_mesh_adv_type_init(BLE_MESH_ADV_BLE, p_ble_adv_queue, &ble_adv_buf_pool, ble_adv_alloc); #if CONFIG_BLE_MESH_USE_BLE_50 #if CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE - bt_mesh_adv_inst_init(BLE_MESH_BLE_ADV_INS, CONFIG_BLE_MESH_BLE_ADV_INST_ID); - bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_BLE_ADV_INS, BLE_MESH_ADV_BLE); + bt_mesh_adv_inst_init(BLE_MESH_BLE_ADV_INST, CONFIG_BLE_MESH_BLE_ADV_INST_ID); + bt_mesh_adv_inst_type_add(BLE_MESH_BLE_ADV_INST, BLE_MESH_ADV_BLE); #else #if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV - bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_BLE); + bt_mesh_adv_inst_type_add(BLE_MESH_ADV_INST, BLE_MESH_ADV_BLE); #endif #endif /* CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE */ #endif /* CONFIG_BLE_MESH_USE_BLE_50 */ @@ -317,8 +306,7 @@ void bt_mesh_ble_adv_init(void) void bt_mesh_ble_adv_deinit(void) { for (int i = 0; i < ARRAY_SIZE(ble_adv_tx); i++) { - struct bt_mesh_ble_adv_tx *tx = &ble_adv_tx[i]; - ble_adv_tx_reset(tx, false); + ble_adv_tx_reset(&ble_adv_tx[i], false); } bt_mesh_unref_buf_from_pool(&ble_adv_buf_pool); memset(ble_adv_pool, 0, sizeof(ble_adv_pool)); @@ -331,14 +319,13 @@ void bt_mesh_ble_adv_deinit(void) bt_mesh_adv_type_deinit(BLE_MESH_ADV_BLE); #if CONFIG_BLE_MESH_USE_BLE_50 #if CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE - bt_mesh_adv_inst_deinit(BLE_MESH_BLE_ADV_INS); - bt_mesh_adv_inst_supported_adv_type_rm(BLE_MESH_BLE_ADV_INS, BLE_MESH_ADV_BLE); + bt_mesh_adv_inst_deinit(BLE_MESH_BLE_ADV_INST); + bt_mesh_adv_inst_type_rm(BLE_MESH_BLE_ADV_INST, BLE_MESH_ADV_BLE); #else #if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV - bt_mesh_adv_inst_supported_adv_type_rm(BLE_MESH_ADV_INS, BLE_MESH_ADV_BLE); + bt_mesh_adv_inst_type_rm(BLE_MESH_ADV_INST, BLE_MESH_ADV_BLE); #endif #endif /* CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE */ #endif /* CONFIG_BLE_MESH_USE_BLE_50 */ } #endif /* CONFIG_BLE_MESH_DEINIT */ -#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ diff --git a/components/bt/esp_ble_mesh/core/bluedroid_host/adapter.c b/components/bt/esp_ble_mesh/core/bluedroid_host/adapter.c index fd42502fdaf..0520ca7a114 100644 --- a/components/bt/esp_ble_mesh/core/bluedroid_host/adapter.c +++ b/components/bt/esp_ble_mesh/core/bluedroid_host/adapter.c @@ -396,11 +396,11 @@ void ble_mesh_5_gap_callback(tBTA_DM_BLE_5_GAP_EVENT event, goto transfer_to_user; } #if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV - ble_mesh_adv_task_wakeup(ADV_TASK_ADV_INST_EVT(params->adv_term.adv_handle)); + bt_mesh_adv_task_wakeup(ADV_TASK_ADV_INST_EVT(params->adv_term.adv_handle)); #else /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ if (params->adv_term.status == 0x43 || /* Limit reached */ params->adv_term.status == 0x3C) { /* Advertising timeout */ - ble_mesh_adv_task_wakeup(ADV_TASK_MESH_ADV_INST_EVT); + bt_mesh_adv_task_wakeup(ADV_TASK_MESH_ADV_INST_EVT); } #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV /** @@ -423,7 +423,7 @@ void ble_mesh_5_gap_callback(tBTA_DM_BLE_5_GAP_EVENT event, * could lead to resource contention issues. */ bt_mesh_unset_ble_adv_running(); - ble_mesh_adv_task_wakeup(ADV_TASK_MESH_ADV_INST_EVT); + bt_mesh_adv_task_wakeup(ADV_TASK_MESH_ADV_INST_EVT); } #endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ #endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ @@ -655,7 +655,7 @@ static void bt_mesh_scan_result_callback(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARC static struct { bool set; tBTA_DM_BLE_GAP_EXT_ADV_PARAMS param; -} last_param[BLE_MESH_ADV_INS_TYPES_NUM]; +} last_param[BLE_MESH_ADV_INST_TYPES_NUM]; int bt_le_ext_adv_start(const uint8_t inst_id, const struct bt_mesh_adv_param *param, diff --git a/components/bt/esp_ble_mesh/core/ext_adv.c b/components/bt/esp_ble_mesh/core/ext_adv.c index ebc28517779..4958e5686db 100644 --- a/components/bt/esp_ble_mesh/core/ext_adv.c +++ b/components/bt/esp_ble_mesh/core/ext_adv.c @@ -28,28 +28,9 @@ #include "adv_common.h" #include "ble_adv.h" -static struct bt_mesh_adv_queue *adv_queue; - static struct bt_mesh_adv_inst *adv_insts; -static inline void adv_send_start(uint16_t duration, int err, - const struct bt_mesh_send_cb *cb, - void *cb_data) -{ - if (cb && cb->start) { - cb->start(duration, err, cb_data); - } -} - -static inline void adv_send_end(int err, const struct bt_mesh_send_cb *cb, - void *cb_data) -{ - if (cb && cb->end) { - cb->end(err, cb_data); - } -} - -static inline int adv_send(struct bt_mesh_adv_inst *inst, uint16_t *adv_duration) +static int adv_send(struct bt_mesh_adv_inst *inst, uint16_t *adv_duration) { struct net_buf *buf = inst->sending_buf; const struct bt_mesh_send_cb *cb = BLE_MESH_ADV(buf)->cb; @@ -205,40 +186,40 @@ static inline int adv_send(struct bt_mesh_adv_inst *inst, uint16_t *adv_duration return 0; } -static inline int find_valid_msg_from_queue(bt_mesh_queue_t *msg_queue, bt_mesh_msg_t *msg) +static int find_valid_msg_from_queue(bt_mesh_queue_t *msg_queue, bt_mesh_msg_t *msg) { while(uxQueueMessagesWaiting(msg_queue->handle)) { xQueueReceive(msg_queue->handle, msg, K_WAIT(K_FOREVER)); - /* In the previous adv task design, only - * the *buf of messages pushed to the queue - * by adv_update would be empty, but in the - * new design, there is a new processing method - * for adv_update's messages, - * so *buf here cannot be empty. */ + /* In the previous adv task design, only the *buf of messages pushed to the queue + * by adv_update would be empty, but in the new design, there is a new processing + * method for adv_update's messages, so *buf here cannot be empty. + */ assert(msg->arg); - /* If the message is canceled for advertising, - * then continue to retrieve the next message - * from that queue. */ + /* If the message is cancelled for advertising, then continue to retrieve the next + * message from that queue. + */ if (!bt_mesh_atomic_cas(&BLE_MESH_ADV_BUSY(BLE_MESH_MSG_NET_BUF(msg)), 1, 0)) { bt_mesh_adv_buf_ref_debug(__func__, BLE_MESH_MSG_NET_BUF(msg), 1U, BLE_MESH_BUF_REF_EQUAL); /* Cancel the adv task's reference to this data packet. - * tips: The reference of buffer by adv_task occurs - * when the buffer is pushed into the queue. + * Tips: + * The reference of buffer by adv_task occurs when the buffer is pushed into + * the queue. */ net_buf_unref(BLE_MESH_MSG_NET_BUF(msg)); - /* Avoid reading the last message in the queue, which could lead - * to pointing to an invalid buffer due to the absence of other - * messages in the queue. */ + + /* Avoid reading the last message in the queue, which could lead to pointing + * to an invalid buffer due to the absence of other messages in the queue. + */ msg->arg = NULL; continue; } #if CONFIG_BLE_MESH_RELAY_ADV_BUF - /* If the relay message should be ignored, - * then continue to retrieve the next message - * from that queue. */ + /* If the relay message should be ignored, then continue to retrieve the next message + * from that queue. + */ if (msg->relay && bt_mesh_ignore_relay_packet(msg->timestamp)) { /* If the interval between "current time - msg.timestamp" is bigger than * BLE_MESH_RELAY_TIME_INTERVAL, this relay packet will not be sent. @@ -259,32 +240,32 @@ static inline int find_valid_msg_from_queue(bt_mesh_queue_t *msg_queue, bt_mesh_ return 0; } -static inline int active_idle_adv_instance(uint32_t *update_evts, uint16_t *min_duration) +static int activate_idle_adv_instance(uint32_t *update_evts, uint16_t *min_duration) { - uint32_t evts = 0; - uint16_t duration = K_FOREVER; uint16_t cur_min_duration = K_FOREVER; enum bt_mesh_adv_type adv_type = 0; - struct bt_mesh_adv_inst *instance = NULL; bt_mesh_queue_t *msg_queue = NULL; + uint16_t duration = K_FOREVER; bt_mesh_msg_t msg = {0}; uint32_t spt_mask = 0; + uint32_t evts = 0; #if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ CONFIG_BLE_MESH_GATT_PROXY_SERVER - if (!adv_insts[BLE_MESH_ADV_PROXY_INS].busy) { + if (!adv_insts[BLE_MESH_ADV_PROXY_INST].busy) { BT_DBG("Mesh Proxy Advertising start"); duration = bt_mesh_proxy_server_adv_start(); if (duration < cur_min_duration) { cur_min_duration = duration; } - adv_insts[BLE_MESH_ADV_PROXY_INS].busy = true; - evts |= ADV_TASK_ADV_INST_EVT(adv_insts[BLE_MESH_ADV_PROXY_INS].id); + adv_insts[BLE_MESH_ADV_PROXY_INST].busy = true; + evts |= ADV_TASK_ADV_INST_EVT(adv_insts[BLE_MESH_ADV_PROXY_INST].id); } #endif - for (int i = BLE_MESH_ADV_INS; i < BLE_MESH_ADV_INS_TYPES_NUM; i++) { - instance = &adv_insts[i]; + for (int i = BLE_MESH_ADV_INST; i < BLE_MESH_ADV_INST_TYPES_NUM; i++) { + struct bt_mesh_adv_inst *instance = &adv_insts[i]; + if (instance->busy #if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ CONFIG_BLE_MESH_GATT_PROXY_SERVER @@ -300,10 +281,9 @@ static inline int active_idle_adv_instance(uint32_t *update_evts, uint16_t *min_ while(spt_mask) { adv_type = find_lsb_set(spt_mask) - 1; spt_mask &= ~BIT(adv_type); - msg_queue = &(bt_mesh_adv_types_mgnt_get(adv_type)->adv_q->q); + msg_queue = &(bt_mesh_adv_types_mgmt_get(adv_type)->adv_q->q); - /* When there is no new message in the queue, *buf (aka: msg.arg) - * will be empty. */ + /* If no new message in the queue, the *buf (aka: msg.arg) will be empty */ if (find_valid_msg_from_queue(msg_queue, &msg)) { BT_DBG("no valid message for instance %d", instance->id); continue; @@ -312,15 +292,17 @@ static inline int active_idle_adv_instance(uint32_t *update_evts, uint16_t *min_ instance->sending_buf = (struct net_buf *)msg.arg; if (adv_send(instance, &duration)) { BT_ERR("adv start failed"); + /* When this adv instance fails to broadcast, it could be due to some + * persistent issues, such as incorrect adv parameter settings, or it + * could be due to some temporary issues, such as memory allocation + * failure. + * + * Therefore, it is advisable to skip subsequent queue reads for this + * instance and attempt to broadcast subsequent data again next time, + * rather than disabling the adv instance. + */ net_buf_unref(instance->sending_buf); instance->sending_buf = NULL; - /* When this adv instance fails to broadcast, it could be - * due to some persistent issues, such as incorrect adv - * parameter settings, or it could be due to some temporary - * issues, such as memory allocation failure. Therefore, it - * is advisable to skip subsequent queue reads for this instance - * and attempt to broadcast subsequent data again next time, - * rather than disabling the adv instance. */ break; } @@ -331,9 +313,9 @@ static inline int active_idle_adv_instance(uint32_t *update_evts, uint16_t *min_ instance->busy = true; evts |= ADV_TASK_ADV_INST_EVT(adv_insts[i].id); - /* Must be nullified to avoid affecting the next adv - * instance's judgment on whether the message queue - * is empty. */ + /* Must be nullified to avoid affecting the next adv instance's judgment + * on whether the message queue is empty. + */ msg.arg = NULL; break; } @@ -347,19 +329,18 @@ static inline int active_idle_adv_instance(uint32_t *update_evts, uint16_t *min_ static uint32_t received_adv_evts_handle(uint32_t recv_evts) { - uint32_t evt = 0; - if (!recv_evts) { return 0; } - for (int i = 0; recv_evts && i < BLE_MESH_ADV_INS_TYPES_NUM; i++) { - evt = ADV_TASK_ADV_INST_EVT(adv_insts[i].id); + for (int i = 0; recv_evts && i < BLE_MESH_ADV_INST_TYPES_NUM; i++) { + uint32_t evt = ADV_TASK_ADV_INST_EVT(adv_insts[i].id); + if (recv_evts & evt) { recv_evts &= ~evt; #if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ CONFIG_BLE_MESH_GATT_PROXY_SERVER - if (unlikely(i == BLE_MESH_ADV_PROXY_INS)) { + if (unlikely(i == BLE_MESH_ADV_PROXY_INST)) { BT_DBG("Mesh Proxy Advertising auto stop"); bt_mesh_proxy_server_adv_flag_set(false); } else @@ -390,24 +371,23 @@ static void adv_thread(void *p) adv_duration = K_FOREVER; wait_evts |= ADV_TASK_PKT_SEND_EVT; - active_idle_adv_instance(&wait_evts, &adv_duration); + activate_idle_adv_instance(&wait_evts, &adv_duration); - ble_mesh_adv_task_wait(wait_evts, adv_duration, &recv_evts); + bt_mesh_adv_task_wait(wait_evts, adv_duration, &recv_evts); wait_evts &= ~recv_evts; #if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ CONFIG_BLE_MESH_GATT_PROXY_SERVER if (recv_evts & ADV_TASK_PROXY_ADV_UPD_EVT) { - adv_insts[BLE_MESH_ADV_PROXY_INS].busy = false; + adv_insts[BLE_MESH_ADV_PROXY_INST].busy = false; recv_evts &= ~ADV_TASK_PROXY_ADV_UPD_EVT; } #endif - /** - * `recv_evts == ADV_TASK_PKT_SEND_EVT` indicates that new packets - * have been placed into the queue, and the advertising instances started - * previous have not yet stopped. + /* The `recv_evts == ADV_TASK_PKT_SEND_EVT` indicates that new packets + * have been put into the queue, and the advertising instances started + * previously have not yet been stopped. */ if (recv_evts == ADV_TASK_PKT_SEND_EVT) { continue; @@ -431,8 +411,8 @@ void bt_mesh_adv_update(void) CONFIG_BLE_MESH_GATT_PROXY_SERVER BT_DBG("Mesh Proxy Advertising stopped manually"); bt_mesh_proxy_server_adv_stop(); - if (adv_insts[BLE_MESH_ADV_PROXY_INS].busy) { - ble_mesh_adv_task_wakeup(ADV_TASK_PROXY_ADV_UPD_EVT); + if (adv_insts[BLE_MESH_ADV_PROXY_INST].busy) { + bt_mesh_adv_task_wakeup(ADV_TASK_PROXY_ADV_UPD_EVT); } #endif } @@ -442,7 +422,6 @@ void bt_mesh_adv_init(void) bt_mesh_adv_common_init(); adv_insts = bt_mesh_get_adv_insts_set(); - adv_queue = bt_mesh_adv_queue_get(); #if CONFIG_BLE_MESH_RELAY_ADV_BUF bt_mesh_relay_adv_init(); diff --git a/components/bt/esp_ble_mesh/core/ext_adv.h b/components/bt/esp_ble_mesh/core/ext_adv.h index 3004db27cdf..536b0aa4fd1 100644 --- a/components/bt/esp_ble_mesh/core/ext_adv.h +++ b/components/bt/esp_ble_mesh/core/ext_adv.h @@ -20,13 +20,6 @@ extern "C" { #endif -static inline void bt_mesh_adv_send(struct net_buf *buf, uint8_t xmit, - const struct bt_mesh_send_cb *cb, - void *cb_data) -{ - bt_mesh_generic_adv_send(buf, xmit, cb, cb_data, BLE_MESH_ADDR_UNASSIGNED, BLE_MESH_ADDR_UNASSIGNED, false); -} - void bt_mesh_adv_update(void); void bt_mesh_adv_init(void); diff --git a/components/bt/esp_ble_mesh/core/friend.c b/components/bt/esp_ble_mesh/core/friend.c index 99e41cd099d..eae9f9471d0 100644 --- a/components/bt/esp_ble_mesh/core/friend.c +++ b/components/bt/esp_ble_mesh/core/friend.c @@ -346,7 +346,7 @@ static struct net_buf *create_friend_pdu(struct bt_mesh_friend *frnd, { struct net_buf *buf = NULL; - buf = bt_mesh_adv_create_from_pool(BLE_MESH_ADV_FRIEND, K_NO_WAIT); + buf = bt_mesh_adv_create(BLE_MESH_ADV_FRIEND, K_NO_WAIT); if (!buf) { return NULL; } diff --git a/components/bt/esp_ble_mesh/core/include/mesh/adapter.h b/components/bt/esp_ble_mesh/core/include/mesh/adapter.h index de8b01c95f1..39c359d695c 100644 --- a/components/bt/esp_ble_mesh/core/include/mesh/adapter.h +++ b/components/bt/esp_ble_mesh/core/include/mesh/adapter.h @@ -512,20 +512,20 @@ struct bt_mesh_adv_param { #define ADV_TASK_ADV_INST_EVT(inst_id) BIT(inst_id) enum bt_mesh_adv_inst_type { - BLE_MESH_ADV_INS, + BLE_MESH_ADV_INST, #if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV #if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ CONFIG_BLE_MESH_GATT_PROXY_SERVER - BLE_MESH_ADV_PROXY_INS, + BLE_MESH_ADV_PROXY_INST, #endif #if CONFIG_BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE - BLE_MESH_RELAY_ADV_INS, + BLE_MESH_RELAY_ADV_INST, #endif #if CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE - BLE_MESH_BLE_ADV_INS, + BLE_MESH_BLE_ADV_INST, #endif #endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ - BLE_MESH_ADV_INS_TYPES_NUM, + BLE_MESH_ADV_INST_TYPES_NUM, }; #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV diff --git a/components/bt/esp_ble_mesh/core/net.c b/components/bt/esp_ble_mesh/core/net.c index c81b15d37df..3d140927040 100644 --- a/components/bt/esp_ble_mesh/core/net.c +++ b/components/bt/esp_ble_mesh/core/net.c @@ -1679,7 +1679,7 @@ static void bt_mesh_net_relay(struct net_buf_simple *sbuf, if (rx->ctx.enh.long_pkt_cfg) { buf = bt_mesh_adv_create(BLE_MESH_ADV_EXT_LONG_RELAY_DATA, K_NO_WAIT); } else -#endif +#endif /* CONFIG_BLE_MESH_LONG_PACKET */ { buf = bt_mesh_adv_create(BLE_MESH_ADV_EXT_DATA, K_NO_WAIT); } @@ -1690,11 +1690,11 @@ static void bt_mesh_net_relay(struct net_buf_simple *sbuf, EXT_ADV(buf)->tx_power = rx->ctx.enh.ext_adv_cfg.tx_power; } } else -#endif +#endif /* CONFIG_BLE_MESH_EXT_ADV */ { buf = bt_mesh_adv_create(BLE_MESH_ADV_DATA, K_NO_WAIT); } -#else +#else /* !CONFIG_BLE_MESH_RELAY_ADV_BUF */ /* Check if the number of relay packets in queue is too large, if so * use minimum relay retransmit value for later relay packets. */ @@ -1707,7 +1707,7 @@ static void bt_mesh_net_relay(struct net_buf_simple *sbuf, if (rx->ctx.enh.long_pkt_cfg) { buf = bt_mesh_adv_create(BLE_MESH_ADV_EXT_LONG_RELAY_DATA, K_NO_WAIT); } else -#endif +#endif /* CONFIG_BLE_MESH_LONG_PACKET */ { buf = bt_mesh_adv_create(BLE_MESH_ADV_EXT_DATA, K_NO_WAIT); } @@ -1718,11 +1718,11 @@ static void bt_mesh_net_relay(struct net_buf_simple *sbuf, EXT_ADV(buf)->tx_power = rx->ctx.enh.ext_adv_cfg.tx_power; } } else -#endif +#endif /* CONFIG_BLE_MESH_EXT_ADV */ { - buf = bt_mesh_relay_adv_create(BLE_MESH_ADV_RELAY_DATA, K_NO_WAIT); + buf = bt_mesh_adv_create(BLE_MESH_ADV_RELAY_DATA, K_NO_WAIT); } -#endif +#endif /* !CONFIG_BLE_MESH_RELAY_ADV_BUF */ if (!buf) { BT_INFO("Out of relay buffers"); diff --git a/components/bt/esp_ble_mesh/core/nimble_host/adapter.c b/components/bt/esp_ble_mesh/core/nimble_host/adapter.c index f5fd0279fc4..d89c63b3492 100644 --- a/components/bt/esp_ble_mesh/core/nimble_host/adapter.c +++ b/components/bt/esp_ble_mesh/core/nimble_host/adapter.c @@ -997,12 +997,12 @@ static int gap_event_cb(struct ble_gap_event *event, void *arg) event->adv_complete.reason); #if CONFIG_BLE_MESH_USE_BLE_50 #if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV - ble_mesh_adv_task_wakeup(ADV_TASK_ADV_INST_EVT(event->adv_complete.instance)); + bt_mesh_adv_task_wakeup(ADV_TASK_ADV_INST_EVT(event->adv_complete.instance)); #else /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ assert(CONFIG_BLE_MESH_ADV_INST_ID == event->adv_complete.instance); /* Limit Reached (0x43) and Advertising Timeout (0x3C) will cause BLE_HS_ETIMEOUT to be set. */ if (event->adv_complete.reason == BLE_HS_ETIMEOUT) { - ble_mesh_adv_task_wakeup(ADV_TASK_ADV_INST_EVT(event->adv_complete.instance)); + bt_mesh_adv_task_wakeup(ADV_TASK_ADV_INST_EVT(event->adv_complete.instance)); } #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV /** @@ -1020,12 +1020,12 @@ static int gap_event_cb(struct ble_gap_event *event, void *arg) */ if (bt_mesh_is_ble_adv_running() && event->adv_complete.reason == 0) { - /* The unset operation must be performed before waking up the - * adv task; performing the unset after waking up the adv task - * could lead to resource contention issues. - */ + /* The unset operation must be performed before waking up the + * adv task; performing the unset after waking up the adv task + * could lead to resource contention issues. + */ bt_mesh_unset_ble_adv_running(); - ble_mesh_adv_task_wakeup(ADV_TASK_ADV_INST_EVT(event->adv_complete.instance)); + bt_mesh_adv_task_wakeup(ADV_TASK_ADV_INST_EVT(event->adv_complete.instance)); } #endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ #endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ @@ -1124,12 +1124,12 @@ static int gap_event_cb(struct ble_gap_event *event, void *arg) BT_DBG("Provisioner advertise complete; reason=%d", event->adv_complete.reason); #if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV - ble_mesh_adv_task_wakeup(ADV_TASK_ADV_INST_EVT(event->adv_complete.instance)); + bt_mesh_adv_task_wakeup(ADV_TASK_ADV_INST_EVT(event->adv_complete.instance)); #else /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ assert(CONFIG_BLE_MESH_ADV_INST_ID == event->adv_complete.instance); /* Limit Reached (0x43) and Advertising Timeout (0x3C) will cause BLE_HS_ETIMEOUT to be set. */ if (event->adv_complete.reason == BLE_HS_ETIMEOUT) { - ble_mesh_adv_task_wakeup(ADV_TASK_ADV_INST_EVT(CONFIG_BLE_MESH_ADV_INST_ID)); + bt_mesh_adv_task_wakeup(ADV_TASK_ADV_INST_EVT(CONFIG_BLE_MESH_ADV_INST_ID)); } #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV /** @@ -1152,7 +1152,7 @@ static int gap_event_cb(struct ble_gap_event *event, void *arg) * could lead to resource contention issues. */ bt_mesh_unset_ble_adv_running(); - ble_mesh_adv_task_wakeup(ADV_TASK_ADV_INST_EVT(CONFIG_BLE_MESH_ADV_INST_ID)); + bt_mesh_adv_task_wakeup(ADV_TASK_ADV_INST_EVT(CONFIG_BLE_MESH_ADV_INST_ID)); } #endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ #endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ @@ -1167,7 +1167,7 @@ static int gap_event_cb(struct ble_gap_event *event, void *arg) static struct { bool set; struct ble_gap_ext_adv_params param; -} last_param[BLE_MESH_ADV_INS_TYPES_NUM]; +} last_param[BLE_MESH_ADV_INST_TYPES_NUM]; int bt_le_ext_adv_start(const uint8_t inst_id, const struct bt_mesh_adv_param *param, @@ -2516,8 +2516,7 @@ void bt_mesh_gatt_init(void) static bool init = false; if (init == false) { - - __ASSERT(g_gatts_svcs_add, "func bt_mesh_gatts_svcs_add should be called before mesh init"); + assert(g_gatts_svcs_add); ble_gatts_svc_set_visibility(prov_svc_start_handle, 1); ble_gatts_svc_set_visibility(proxy_svc_start_handle, 0); diff --git a/components/bt/esp_ble_mesh/core/proxy_server.c b/components/bt/esp_ble_mesh/core/proxy_server.c index 062bb9b247f..c6cc15cab6e 100644 --- a/components/bt/esp_ble_mesh/core/proxy_server.c +++ b/components/bt/esp_ble_mesh/core/proxy_server.c @@ -1598,8 +1598,13 @@ static int private_node_id_adv(struct bt_mesh_subnet *sub) memcpy(proxy_svc_data + 3, tmp + 8, 8); proxy_sd_len = gatt_proxy_adv_create(&proxy_sd); +#if CONFIG_BLE_MESH_USE_BLE_50 + err = bt_le_ext_adv_start(proxy_adv_inst, &fast_adv_param, private_node_id_ad, + ARRAY_SIZE(private_node_id_ad), &proxy_sd, proxy_sd_len); +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ err = bt_le_adv_start(&fast_adv_param, private_node_id_ad, ARRAY_SIZE(private_node_id_ad), &proxy_sd, proxy_sd_len); +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ if (err) { BT_WARN("Failed to advertise with Private Node ID (err %d)", err); return err; @@ -1642,8 +1647,13 @@ static int private_net_id_adv(struct bt_mesh_subnet *sub) proxy_sd_len = gatt_proxy_adv_create(&proxy_sd); +#if CONFIG_BLE_MESH_USE_BLE_50 + err = bt_le_ext_adv_start(proxy_adv_inst, &fast_adv_param, private_net_id_ad, + ARRAY_SIZE(private_net_id_ad), &proxy_sd, proxy_sd_len); +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ err = bt_le_adv_start(&fast_adv_param, private_net_id_ad, ARRAY_SIZE(private_net_id_ad), &proxy_sd, proxy_sd_len); +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ if (err) { BT_WARN("Failed to advertise with Private Net ID (err %d)", err); return err; diff --git a/components/bt/esp_ble_mesh/core/scan.c b/components/bt/esp_ble_mesh/core/scan.c index df6f22e117e..c298f184566 100644 --- a/components/bt/esp_ble_mesh/core/scan.c +++ b/components/bt/esp_ble_mesh/core/scan.c @@ -43,18 +43,18 @@ static struct bt_mesh_scan_param scan_param = { #if CONFIG_BLE_MESH_RPR_SRV_ACTIVE_SCAN - .type = BLE_MESH_SCAN_ACTIVE, + .type = BLE_MESH_SCAN_ACTIVE, #else - .type = BLE_MESH_SCAN_PASSIVE, + .type = BLE_MESH_SCAN_PASSIVE, #endif #if CONFIG_BLE_MESH_USE_DUPLICATE_SCAN - .filter_dup = BLE_MESH_SCAN_FILTER_DUP_ENABLE, + .filter_dup = BLE_MESH_SCAN_FILTER_DUP_ENABLE, #else - .filter_dup = BLE_MESH_SCAN_FILTER_DUP_DISABLE, + .filter_dup = BLE_MESH_SCAN_FILTER_DUP_DISABLE, #endif - .interval = SCAN_INTERVAL, - .window = SCAN_WINDOW, - .scan_fil_policy = BLE_MESH_SP_ADV_ALL, + .interval = SCAN_INTERVAL, + .window = SCAN_WINDOW, + .scan_fil_policy = BLE_MESH_SP_ADV_ALL, }; #if (CONFIG_BLE_MESH_PROVISIONER || CONFIG_BLE_MESH_RPR_SRV) @@ -115,21 +115,21 @@ int bt_mesh_unprov_dev_info_query(uint8_t uuid[16], uint8_t addr[6], if (!memcmp(unprov_dev_info_fifo.info[idx].addr, addr, 6)) { if (query_type & BLE_MESH_STORE_UNPROV_INFO_QUERY_TYPE_EXISTS) { return 0; - } else { - memcpy(uuid, unprov_dev_info_fifo.info[idx].uuid, 16); - *adv_type = unprov_dev_info_fifo.info[idx].adv_type; - break; } + + memcpy(uuid, unprov_dev_info_fifo.info[idx].uuid, 16); + *adv_type = unprov_dev_info_fifo.info[idx].adv_type; + break; } } else { if (!memcmp(unprov_dev_info_fifo.info[idx].uuid, uuid, 16)) { if (query_type & BLE_MESH_STORE_UNPROV_INFO_QUERY_TYPE_EXISTS) { return 0; - } else { - memcpy(addr, unprov_dev_info_fifo.info[idx].addr, 6); - *adv_type = unprov_dev_info_fifo.info[idx].adv_type; - break; } + + memcpy(addr, unprov_dev_info_fifo.info[idx].addr, 6); + *adv_type = unprov_dev_info_fifo.info[idx].adv_type; + break; } } cnt++; @@ -458,12 +458,12 @@ static void bt_mesh_scan_cb(struct bt_mesh_adv_report *adv_rpt) */ if (rpr_ext_scan_handle_adv_pkt(&adv_rpt->addr, adv_data, adv_len)) { return; - } else { -#if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN - callback_ble_adv_pkt(&adv_rpt->addr, adv_rpt->adv_type, adv_data, adv_len, adv_rpt->rssi); -#endif - net_buf_simple_restore(buf, &buf_state); } + +#if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN + callback_ble_adv_pkt(&adv_rpt->addr, adv_rpt->adv_type, adv_data, adv_len, adv_rpt->rssi); +#endif + net_buf_simple_restore(buf, &buf_state); } #endif /* CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_RPR_SRV_ACTIVE_SCAN */ diff --git a/components/bt/esp_ble_mesh/core/transport.c b/components/bt/esp_ble_mesh/core/transport.c index 88a6158b89e..797ff2a1ad3 100644 --- a/components/bt/esp_ble_mesh/core/transport.c +++ b/components/bt/esp_ble_mesh/core/transport.c @@ -177,74 +177,6 @@ int32_t bt_mesh_get_seg_rtx_timeout(uint16_t dst, uint8_t ttl) return SEG_RETRANSMIT_TIMEOUT_UNICAST(&tx); } -struct bt_mesh_app_key *bt_mesh_app_key_get(uint16_t app_idx) -{ - if (bt_mesh_is_provisioned()) { -#if CONFIG_BLE_MESH_NODE - if (!IS_ENABLED(CONFIG_BLE_MESH_FAST_PROV)) { - for (int i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) { - if (bt_mesh.app_keys[i].net_idx != BLE_MESH_KEY_UNUSED && - bt_mesh.app_keys[i].app_idx == app_idx) { - return &bt_mesh.app_keys[i]; - } - } - } else { - return bt_mesh_fast_prov_app_key_find(app_idx); - } -#endif - } else if (bt_mesh_is_provisioner_en()) { -#if CONFIG_BLE_MESH_PROVISIONER - for (int i = 0; i < ARRAY_SIZE(bt_mesh.p_app_keys); i++) { - if (bt_mesh.p_app_keys[i] && - bt_mesh.p_app_keys[i]->net_idx != BLE_MESH_KEY_UNUSED && - bt_mesh.p_app_keys[i]->app_idx == app_idx) { - return bt_mesh.p_app_keys[i]; - } - } -#endif - } - - return NULL; -} - -int bt_mesh_upper_key_get(const struct bt_mesh_subnet *subnet, uint16_t app_idx, - const uint8_t **key, uint8_t *aid, uint16_t dst) -{ - struct bt_mesh_app_key *app_key = NULL; - - if (app_idx == BLE_MESH_KEY_DEV) { - *key = bt_mesh_dev_key_get(dst); - if (!*key) { - BT_ERR("DevKey of 0x%04x not found", dst); - return -EINVAL; - } - - *aid = 0U; - return 0; - } - - if (!subnet) { - BT_ERR("Invalid subnet"); - return -EINVAL; - } - - app_key = bt_mesh_app_key_get(app_idx); - if (!app_key) { - BT_ERR("AppKey 0x%04x not found", app_idx); - return -ENOENT; - } - - if (subnet->kr_phase == BLE_MESH_KR_PHASE_2 && app_key->updated) { - *key = app_key->keys[1].val; - *aid = app_key->keys[1].id; - } else { - *key = app_key->keys[0].val; - *aid = app_key->keys[0].id; - } - - return 0; -} - static int send_unseg(struct bt_mesh_net_tx *tx, struct net_buf_simple *sdu, const struct bt_mesh_send_cb *cb, void *cb_data, const uint8_t *ctl_op) @@ -442,7 +374,6 @@ static inline void seg_tx_complete(struct seg_tx *tx, int err) static void schedule_retransmit(struct seg_tx *tx) { - bt_mesh_seg_tx_lock(tx); /* It's possible that a segment broadcast hasn't finished, * but the tx are already released. Only the seg_pending * of this segment remains unprocessed. So, here, we @@ -450,27 +381,29 @@ static void schedule_retransmit(struct seg_tx *tx) * destination (dst) is unassigned, and then process * the seg_pending of this segment. * See BLEMESH25-92 for details */ + + bt_mesh_seg_tx_lock(tx); + if (tx->dst == BLE_MESH_ADDR_UNASSIGNED) { if (tx->seg_pending) { tx->seg_pending--; } - bt_mesh_seg_tx_unlock(tx); - return; + goto end; } if (--tx->seg_pending) { - bt_mesh_seg_tx_unlock(tx); - return; + goto end; } if (!BLE_MESH_ADDR_IS_UNICAST(tx->dst) && !tx->attempts) { BT_INFO("Complete tx sdu to group"); seg_tx_complete(tx, 0); - bt_mesh_seg_tx_unlock(tx); - return; + goto end; } k_delayed_work_submit(&tx->rtx_timer, SEG_RETRANSMIT_TIMEOUT(tx)); + +end: bt_mesh_seg_tx_unlock(tx); } diff --git a/components/bt/esp_ble_mesh/core/transport.enh.c b/components/bt/esp_ble_mesh/core/transport.enh.c index 318b21bb099..583f83e6a30 100644 --- a/components/bt/esp_ble_mesh/core/transport.enh.c +++ b/components/bt/esp_ble_mesh/core/transport.enh.c @@ -209,74 +209,6 @@ uint32_t bt_mesh_seg_ack_period(void) return (uint32_t)(val * bt_mesh_seg_rx_interval()); } -struct bt_mesh_app_key *bt_mesh_app_key_get(uint16_t app_idx) -{ - if (bt_mesh_is_provisioned()) { -#if CONFIG_BLE_MESH_NODE - if (!IS_ENABLED(CONFIG_BLE_MESH_FAST_PROV)) { - for (int i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) { - if (bt_mesh.app_keys[i].net_idx != BLE_MESH_KEY_UNUSED && - bt_mesh.app_keys[i].app_idx == app_idx) { - return &bt_mesh.app_keys[i]; - } - } - } else { - return bt_mesh_fast_prov_app_key_find(app_idx); - } -#endif - } else if (bt_mesh_is_provisioner_en()) { -#if CONFIG_BLE_MESH_PROVISIONER - for (int i = 0; i < ARRAY_SIZE(bt_mesh.p_app_keys); i++) { - if (bt_mesh.p_app_keys[i] && - bt_mesh.p_app_keys[i]->net_idx != BLE_MESH_KEY_UNUSED && - bt_mesh.p_app_keys[i]->app_idx == app_idx) { - return bt_mesh.p_app_keys[i]; - } - } -#endif - } - - return NULL; -} - -int bt_mesh_upper_key_get(const struct bt_mesh_subnet *subnet, uint16_t app_idx, - const uint8_t **key, uint8_t *aid, uint16_t dst) -{ - struct bt_mesh_app_key *app_key = NULL; - - if (app_idx == BLE_MESH_KEY_DEV) { - *key = bt_mesh_dev_key_get(dst); - if (!*key) { - BT_ERR("DevKey of 0x%04x not found", dst); - return -EINVAL; - } - - *aid = 0U; - return 0; - } - - if (!subnet) { - BT_ERR("Invalid subnet"); - return -EINVAL; - } - - app_key = bt_mesh_app_key_get(app_idx); - if (!app_key) { - BT_ERR("AppKey 0x%04x not found", app_idx); - return -ENOENT; - } - - if (subnet->kr_phase == BLE_MESH_KR_PHASE_2 && app_key->updated) { - *key = app_key->keys[1].val; - *aid = app_key->keys[1].id; - } else { - *key = app_key->keys[0].val; - *aid = app_key->keys[0].id; - } - - return 0; -} - static int send_unseg(struct bt_mesh_net_tx *tx, struct net_buf_simple *sdu, const struct bt_mesh_send_cb *cb, void *cb_data, const uint8_t *ctl_op) diff --git a/components/bt/esp_ble_mesh/models/client/client_common.c b/components/bt/esp_ble_mesh/models/client/client_common.c index 5917b69cdf7..8c8afdd563f 100644 --- a/components/bt/esp_ble_mesh/models/client/client_common.c +++ b/components/bt/esp_ble_mesh/models/client/client_common.c @@ -20,7 +20,7 @@ #define HCI_TIME_FOR_START_ADV K_MSEC(5) /* Three adv related hci commands may take 4 ~ 5ms */ -static bt_mesh_client_node_t *bt_mesh_client_pick_node(sys_slist_t *list, uint16_t tx_dst) +static bt_mesh_client_node_t *client_pick_node(sys_slist_t *list, uint16_t tx_dst) { bt_mesh_client_node_t *node = NULL; sys_snode_t *cur = NULL; @@ -86,7 +86,7 @@ bt_mesh_client_node_t *bt_mesh_is_client_recv_publish_msg(struct bt_mesh_model * return NULL; } - if ((node = bt_mesh_client_pick_node(&data->queue, ctx->addr)) == NULL) { + if ((node = client_pick_node(&data->queue, ctx->addr)) == NULL) { BT_DBG("Unexpected status message 0x%08x", ctx->recv_op); if (cli->publish_status && need_pub) { cli->publish_status(ctx->recv_op, model, ctx, buf); @@ -113,32 +113,8 @@ bt_mesh_client_node_t *bt_mesh_is_client_recv_publish_msg(struct bt_mesh_model * return node; } -static bool bt_mesh_client_check_node_in_list(sys_slist_t *list, uint16_t tx_dst) -{ - bt_mesh_client_node_t *node = NULL; - sys_snode_t *cur = NULL; - - bt_mesh_list_lock(); - if (sys_slist_is_empty(list)) { - bt_mesh_list_unlock(); - return false; - } - - for (cur = sys_slist_peek_head(list); - cur != NULL; cur = sys_slist_peek_next(cur)) { - node = (bt_mesh_client_node_t *)cur; - if (node->ctx.addr == tx_dst) { - bt_mesh_list_unlock(); - return true; - } - } - - bt_mesh_list_unlock(); - return false; -} - -static uint32_t bt_mesh_client_get_status_op(const bt_mesh_client_op_pair_t *op_pair, - int size, uint32_t opcode) +static uint32_t client_get_status_op(const bt_mesh_client_op_pair_t *op_pair, + int size, uint32_t opcode) { if (!op_pair || size == 0) { return 0; @@ -155,7 +131,7 @@ static uint32_t bt_mesh_client_get_status_op(const bt_mesh_client_op_pair_t *op_ return 0; } -static int32_t bt_mesh_get_adv_duration(struct bt_mesh_msg_ctx *ctx) +static int32_t client_get_adv_duration(struct bt_mesh_msg_ctx *ctx) { uint16_t duration = 0, adv_int = 0; uint8_t xmit = 0; @@ -177,9 +153,9 @@ static int32_t bt_mesh_get_adv_duration(struct bt_mesh_msg_ctx *ctx) return (int32_t)duration; } -static int32_t bt_mesh_client_calc_timeout(struct bt_mesh_msg_ctx *ctx, - struct net_buf_simple *msg, - uint32_t opcode, int32_t timeout) +static int32_t client_calc_timeout(struct bt_mesh_msg_ctx *ctx, + struct net_buf_simple *msg, + uint32_t opcode, int32_t timeout) { int32_t seg_rtx_to = 0, duration = 0, time = 0; uint8_t seg_count = 0, seg_rtx_num = 0; @@ -228,7 +204,7 @@ static int32_t bt_mesh_client_calc_timeout(struct bt_mesh_msg_ctx *ctx, seg_count = (msg->len + mic_size - 1) / 12U + 1U; } - duration = bt_mesh_get_adv_duration(ctx); + duration = client_get_adv_duration(ctx); /* Currently only consider the time consumption of the same segmented * messages, but if there are other messages between any two retrans- @@ -334,7 +310,7 @@ int bt_mesh_client_send_msg(bt_mesh_client_common_param_t *param, return -EINVAL; } - if (bt_mesh_client_check_node_in_list(&internal->queue, param->ctx.addr)) { + if (client_pick_node(&internal->queue, param->ctx.addr)) { BT_ERR("Busy sending message to DST 0x%04x", param->ctx.addr); return -EBUSY; } @@ -349,14 +325,15 @@ int bt_mesh_client_send_msg(bt_mesh_client_common_param_t *param, memcpy(&node->ctx, ¶m->ctx, sizeof(struct bt_mesh_msg_ctx)); node->model = param->model; node->opcode = param->opcode; - node->op_pending = bt_mesh_client_get_status_op(client->op_pair, client->op_pair_size, param->opcode); + node->op_pending = client_get_status_op(client->op_pair, client->op_pair_size, param->opcode); if (node->op_pending == 0U) { BT_ERR("Status opcode not found in op_pair list, opcode 0x%08x", param->opcode); bt_mesh_free(node); return -EINVAL; } - node->timeout = bt_mesh_client_calc_timeout(¶m->ctx, msg, param->opcode, - param->msg_timeout ? param->msg_timeout : CONFIG_BLE_MESH_CLIENT_MSG_TIMEOUT); + node->timeout = client_calc_timeout(¶m->ctx, msg, param->opcode, + (param->msg_timeout ? param->msg_timeout : + CONFIG_BLE_MESH_CLIENT_MSG_TIMEOUT)); if (k_delayed_work_init(&node->timer, timer_handler)) { BT_ERR("Failed to create a timer"); From b73eb03d8873788cef1fdb34d16501cb2a6d92ab Mon Sep 17 00:00:00 2001 From: Liu Linyan Date: Tue, 26 Aug 2025 18:18:42 +0800 Subject: [PATCH 066/106] feat(ble_mesh): Miscellaneous log enhancement for BLE Mesh --- components/bt/esp_ble_mesh/core/access.c | 234 +++++-- components/bt/esp_ble_mesh/core/adv.c | 54 +- components/bt/esp_ble_mesh/core/adv.h | 3 + components/bt/esp_ble_mesh/core/adv_common.c | 192 ++++-- components/bt/esp_ble_mesh/core/adv_common.h | 53 +- components/bt/esp_ble_mesh/core/beacon.c | 113 ++- components/bt/esp_ble_mesh/core/ble_adv.c | 56 +- .../core/bluedroid_host/adapter.c | 18 +- components/bt/esp_ble_mesh/core/cfg_cli.c | 292 ++++++-- components/bt/esp_ble_mesh/core/cfg_srv.c | 642 ++++++++++++------ components/bt/esp_ble_mesh/core/crypto.c | 53 +- components/bt/esp_ble_mesh/core/ext_adv.c | 101 ++- components/bt/esp_ble_mesh/core/ext_adv.h | 1 + components/bt/esp_ble_mesh/core/fast_prov.c | 36 + components/bt/esp_ble_mesh/core/foundation.h | 1 + components/bt/esp_ble_mesh/core/friend.c | 314 ++++++--- components/bt/esp_ble_mesh/core/health_cli.c | 50 +- components/bt/esp_ble_mesh/core/health_srv.c | 77 ++- components/bt/esp_ble_mesh/core/heartbeat.c | 44 +- components/bt/esp_ble_mesh/core/local.c | 97 +-- components/bt/esp_ble_mesh/core/lpn.c | 156 +++-- components/bt/esp_ble_mesh/core/main.c | 98 ++- components/bt/esp_ble_mesh/core/net.c | 374 ++++++---- components/bt/esp_ble_mesh/core/net.h | 28 +- .../esp_ble_mesh/core/nimble_host/adapter.c | 4 +- components/bt/esp_ble_mesh/core/prov_common.c | 6 + .../bt/esp_ble_mesh/core/proxy_client.c | 161 +++-- .../bt/esp_ble_mesh/core/proxy_server.c | 353 +++++++--- .../bt/esp_ble_mesh/core/proxy_server.h | 2 +- components/bt/esp_ble_mesh/core/rpl.c | 29 +- components/bt/esp_ble_mesh/core/scan.c | 218 ++++-- .../bt/esp_ble_mesh/core/storage/settings.c | 330 +++++++-- .../esp_ble_mesh/core/storage/settings_nvs.c | 123 +++- .../esp_ble_mesh/core/storage/settings_uid.c | 72 +- components/bt/esp_ble_mesh/core/test.c | 10 +- components/bt/esp_ble_mesh/core/transport.c | 313 ++++++--- .../bt/esp_ble_mesh/core/transport.enh.c | 433 +++++++++--- .../models/client/client_common.c | 70 +- 38 files changed, 3815 insertions(+), 1396 deletions(-) diff --git a/components/bt/esp_ble_mesh/core/access.c b/components/bt/esp_ble_mesh/core/access.c index 5aad6a0a848..2f70e64eeae 100644 --- a/components/bt/esp_ble_mesh/core/access.c +++ b/components/bt/esp_ble_mesh/core/access.c @@ -25,7 +25,7 @@ #if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" -#endif +#endif /* CONFIG_BLE_MESH_V11_SUPPORT */ #define BLE_MESH_SDU_MAX_LEN 384 @@ -50,6 +50,8 @@ void bt_mesh_model_foreach(void (*func)(struct bt_mesh_model *mod, { int i, j; + BT_DBG("ModelForeach"); + if (comp_0 == NULL) { BT_ERR("Invalid device composition"); return; @@ -58,15 +60,21 @@ void bt_mesh_model_foreach(void (*func)(struct bt_mesh_model *mod, for (i = 0; i < comp_0->elem_count; i++) { struct bt_mesh_elem *elem = &comp_0->elem[i]; + BT_DBG("Element %u", i); + for (j = 0; j < elem->model_count; j++) { struct bt_mesh_model *model = &elem->models[j]; + BT_DBG("ID 0x%04x", model->id); + func(model, elem, false, i == 0, user_data); } for (j = 0; j < elem->vnd_model_count; j++) { struct bt_mesh_model *model = &elem->vnd_models[j]; + BT_DBG("ID 0x%04x CID 0x%04x", model->vnd.id, model->vnd.company); + func(model, elem, true, i == 0, user_data); } } @@ -76,6 +84,8 @@ int32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod) { int period = 0; + BT_DBG("ModelPubPeriodGet"); + if (!mod->pub) { BT_ERR("Model has no publication support"); return 0; @@ -103,6 +113,9 @@ int32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod) return 0; } + BT_DBG("Period %ld FastPeriod %u PeriodDiv %u", + period, mod->pub->fast_period, mod->pub->period_div); + if (mod->pub->fast_period) { return period >> mod->pub->period_div; } @@ -115,6 +128,8 @@ static int32_t next_period(struct bt_mesh_model *mod) struct bt_mesh_model_pub *pub = mod->pub; uint32_t elapsed = 0U, period = 0U; + BT_DBG("NextPeriod"); + if (!pub) { BT_ERR("Model has no publication support"); return 0; @@ -122,12 +137,13 @@ static int32_t next_period(struct bt_mesh_model *mod) period = bt_mesh_model_pub_period_get(mod); if (!period) { + BT_DBG("PeriodZero"); return 0; } elapsed = k_uptime_get_32() - pub->period_start; - BT_INFO("Publishing took %ums", elapsed); + BT_INFO("Elapsed %u Period %u", elapsed, period); if (elapsed >= period) { BT_WARN("Publication sending took longer than the period"); @@ -143,7 +159,7 @@ static void publish_sent(int err, void *user_data) struct bt_mesh_model *mod = user_data; int32_t delay = 0; - BT_DBG("err %d", err); + BT_DBG("PublishSent, Err %d", err); if (!mod->pub) { BT_ERR("Model has no publication support"); @@ -156,8 +172,9 @@ static void publish_sent(int err, void *user_data) delay = next_period(mod); } + BT_DBG("PubCount %u PubDelay %ld", mod->pub->count, delay); + if (delay) { - BT_INFO("Publishing next time in %dms", delay); k_delayed_work_submit(&mod->pub->timer, delay); } } @@ -167,6 +184,8 @@ static void publish_start(uint16_t duration, int err, void *user_data) struct bt_mesh_model *mod = user_data; struct bt_mesh_model_pub *pub = mod->pub; + BT_DBG("PublishStart, Err %d", err); + if (err) { BT_ERR("Failed to publish: err %d", err); return; @@ -196,6 +215,8 @@ static int publish_retransmit(struct bt_mesh_model *mod) }; int err = 0; + BT_DBG("PublishRetransmit"); + if (!pub || !pub->msg) { BT_ERR("Model has no publication support"); return -ENOTSUP; @@ -224,9 +245,14 @@ static int publish_retransmit(struct bt_mesh_model *mod) ctx.send_tag |= BLE_MESH_TAG_SEND_SEGMENTED; } + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Dst 0x%04x", + ctx.net_idx, ctx.app_idx, ctx.addr); + BT_DBG("TTL %u SendCred %u SendRel %u PubCount %u", + ctx.send_ttl, ctx.send_cred, pub->send_rel, pub->count); + #if CONFIG_BLE_MESH_DF_SRV bt_mesh_model_pub_use_directed(&tx, pub->directed_pub_policy); -#endif +#endif /* CONFIG_BLE_MESH_DF_SRV */ sdu = bt_mesh_alloc_buf(pub->msg->len + BLE_MESH_MIC_LONG); if (!sdu) { @@ -246,8 +272,11 @@ static int publish_retransmit(struct bt_mesh_model *mod) static void publish_retransmit_end(int err, struct bt_mesh_model_pub *pub) { + BT_DBG("PublishRetransmitEnd, Err %d", err); + /* Cancel all retransmits for this publish attempt */ pub->count = 0U; + /* Make sure the publish timer gets reset */ publish_sent(err, pub->mod); } @@ -261,7 +290,8 @@ static void mod_publish(struct k_work *work) int err = 0; period_ms = bt_mesh_model_pub_period_get(pub->mod); - BT_INFO("Publish period %u ms", period_ms); + + BT_INFO("ModPublish, Period %u", period_ms); if (pub->count) { err = publish_retransmit(pub->mod); @@ -289,6 +319,7 @@ static void mod_publish(struct k_work *work) if (pub->update && pub->update(pub->mod)) { /* Cancel this publish attempt. */ BT_ERR("Update failed, skipping publish (err %d)", err); + pub->period_start = k_uptime_get_32(); publish_retransmit_end(err, pub); return; @@ -302,6 +333,8 @@ static void mod_publish(struct k_work *work) struct bt_mesh_elem *bt_mesh_model_elem(const struct bt_mesh_model *mod) { + BT_DBG("ModelElem, ElemIdx %u", mod->elem_idx); + return &comp_0->elem[mod->elem_idx]; } @@ -309,6 +342,8 @@ struct bt_mesh_model *bt_mesh_model_get(bool vnd, uint8_t elem_idx, uint8_t mod_ { struct bt_mesh_elem *elem = NULL; + BT_DBG("ModelGet, ElemIdx %u ModIdx %u Vnd %u", elem_idx, mod_idx, vnd); + if (!comp_0) { BT_ERR("comp_0 not initialized"); return NULL; @@ -344,6 +379,8 @@ static void mod_init(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, int *err = user_data; int i; + BT_DBG("ModInit, Vnd %u Primary %u", vnd, primary); + if (!user_data) { BT_ERR("Invalid model init user data"); return; @@ -373,6 +410,8 @@ static void mod_init(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, mod->model_idx = mod - elem->models; } + BT_DBG("ElemIdx %u ModelIdx %u", mod->elem_idx, mod->model_idx); + if (vnd) { return; } @@ -386,6 +425,8 @@ int bt_mesh_comp_register(const struct bt_mesh_comp *comp) { int err = 0; + BT_DBG("CompRegister, ElemCount %u", comp->elem_count); + /* There must be at least one element */ if (!comp->elem_count) { return -EINVAL; @@ -405,6 +446,8 @@ static void mod_deinit(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, int *err = user_data; int i; + BT_DBG("ModDeinit, Vnd %u Primary %u", vnd, primary); + if (!user_data) { BT_ERR("Invalid model deinit user data"); return; @@ -443,6 +486,8 @@ int bt_mesh_comp_deregister(void) { int err = 0; + BT_DBG("CompDeregister"); + if (comp_0 == NULL) { return -EINVAL; } @@ -461,25 +506,29 @@ void bt_mesh_comp_provision(uint16_t addr) dev_primary_addr = addr; - BT_INFO("Primary address 0x%04x, element count %u", addr, comp_0->elem_count); + BT_INFO("CompProvision, PrimaryAddr 0x%04x ElemCount %u", addr, comp_0->elem_count); for (i = 0; i < comp_0->elem_count; i++) { struct bt_mesh_elem *elem = &comp_0->elem[i]; elem->addr = addr++; - BT_DBG("addr 0x%04x mod_count %u vnd_mod_count %u", + BT_DBG("ElemAddr 0x%04x ModCount %u VndModCount %u", elem->addr, elem->model_count, elem->vnd_model_count); } } void bt_mesh_comp_unprovision(void) { + BT_DBG("CompUnprovision"); + dev_primary_addr = BLE_MESH_ADDR_UNASSIGNED; } uint16_t bt_mesh_primary_addr(void) { + BT_DBG("PrimaryAddr 0x%04x", dev_primary_addr); + return dev_primary_addr; } @@ -487,12 +536,16 @@ uint16_t *bt_mesh_model_find_group(struct bt_mesh_model *mod, uint16_t addr) { int i; + BT_DBG("ModelFindGroup, Addr 0x%04x", addr); + for (i = 0; i < ARRAY_SIZE(mod->groups); i++) { if (mod->groups[i] == addr) { + BT_DBG("ModGroupFound"); return &mod->groups[i]; } } + BT_DBG("ModGroupNotFound"); return NULL; } @@ -503,6 +556,8 @@ static struct bt_mesh_model *bt_mesh_elem_find_group(struct bt_mesh_elem *elem, uint16_t *match = NULL; int i; + BT_DBG("ElemFindGroup, Addr 0x%04x", group_addr); + for (i = 0; i < elem->model_count; i++) { model = &elem->models[i]; @@ -528,6 +583,8 @@ struct bt_mesh_elem *bt_mesh_elem_find(uint16_t addr) { uint16_t index = 0U; + BT_DBG("ElemFind, Addr 0x%04x", addr); + if (BLE_MESH_ADDR_IS_UNICAST(addr)) { index = (addr - comp_0->elem[0].addr); if (index < comp_0->elem_count) { @@ -569,6 +626,8 @@ bool bt_mesh_has_addr(uint16_t addr) uint8_t bt_mesh_elem_count(void) { + BT_DBG("ElemCount %u", comp_0->elem_count); + return comp_0->elem_count; } @@ -576,6 +635,8 @@ static bool model_has_key(const struct bt_mesh_model *mod, uint16_t key) { int i; + BT_DBG("ModelHasKey, AppIdx 0x%04x", key); + for (i = 0; i < ARRAY_SIZE(mod->keys); i++) { if (mod->keys[i] == key) { return true; @@ -589,6 +650,8 @@ static bool model_has_dst(struct bt_mesh_model *model, struct bt_mesh_subnet *sub, uint16_t dst) { + BT_DBG("ModelHasDst, Dst 0x%04x", dst); + if (BLE_MESH_ADDR_IS_UNICAST(dst)) { return (comp_0->elem[model->elem_idx].addr == dst); } @@ -607,6 +670,8 @@ static const struct bt_mesh_model_op *find_op(struct bt_mesh_model *models, { int i; + BT_DBG("FindOp, ModelCount %u Opcode 0x%08lx", model_count, opcode); + for (i = 0; i < model_count; i++) { const struct bt_mesh_model_op *op; @@ -625,6 +690,8 @@ static const struct bt_mesh_model_op *find_op(struct bt_mesh_model *models, static int get_opcode(struct net_buf_simple *buf, uint32_t *opcode, bool pull_buf) { + BT_DBG("GetOpCode, PullBuf %u", pull_buf); + switch (buf->data[0] >> 6) { case 0x00: case 0x01: @@ -670,6 +737,8 @@ static int get_opcode(struct net_buf_simple *buf, uint32_t *opcode, bool pull_bu int bt_mesh_get_opcode(struct net_buf_simple *buf, uint32_t *opcode, bool pull_buf) { + BT_DBG("GetOpCode"); + if (buf == NULL || buf->len == 0 || opcode == NULL) { BT_ERR("%s, Invalid parameter", __func__); return -EINVAL; @@ -680,6 +749,8 @@ int bt_mesh_get_opcode(struct net_buf_simple *buf, bool bt_mesh_fixed_group_match(uint16_t addr) { + BT_DBG("FixedGroupMatch, Addr 0x%04x", addr); + /* Check for fixed group addresses */ switch (addr) { case BLE_MESH_ADDR_ALL_NODES: @@ -701,12 +772,14 @@ bool bt_mesh_fixed_direct_match(struct bt_mesh_subnet *sub, uint16_t addr) * shall be processed by the primary element of all nodes that * have directed forwarding functionality enabled. */ + BT_DBG("FixedDirectMatch, Addr 0x%04x", addr); + #if CONFIG_BLE_MESH_DF_SRV if (addr == BLE_MESH_ADDR_DIRECTS && sub && sub->directed_forwarding == BLE_MESH_DIRECTED_FORWARDING_ENABLED) { return true; } -#endif +#endif /* CONFIG_BLE_MESH_DF_SRV */ return false; } @@ -719,16 +792,17 @@ void bt_mesh_model_recv(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf) uint8_t count = 0U; int i; - BT_INFO("recv, app_idx 0x%04x src 0x%04x dst 0x%04x", rx->ctx.app_idx, - rx->ctx.addr, rx->ctx.recv_dst); - BT_INFO("recv, len %u: %s", buf->len, bt_hex(buf->data, buf->len)); + BT_INFO("ModelRecv"); + BT_INFO("AppIdx 0x%04x Src 0x%04x Dst 0x%04x", + rx->ctx.app_idx, rx->ctx.addr, rx->ctx.recv_dst); + BT_INFO("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); if (get_opcode(buf, &opcode, true) < 0) { BT_WARN("Unable to decode OpCode"); return; } - BT_DBG("OpCode 0x%08x", opcode); + BT_DBG("OpCode 0x%08lx RecvCred %u", opcode, rx->ctx.recv_cred); for (i = 0; i < comp_0->elem_count; i++) { struct bt_mesh_elem *elem = &comp_0->elem[i]; @@ -753,10 +827,12 @@ void bt_mesh_model_recv(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf) } if (!model_has_key(model, rx->ctx.app_idx)) { + BT_DBG("ModelNotHasKey"); continue; } if (!model_has_dst(model, rx->sub, rx->ctx.recv_dst)) { + BT_DBG("ModelNotHasDst"); continue; } @@ -800,6 +876,8 @@ void bt_mesh_model_recv(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf) void bt_mesh_model_msg_init(struct net_buf_simple *msg, uint32_t opcode) { + BT_DBG("ModelMsgInit, OpCode 0x%08lx", opcode); + net_buf_simple_init(msg, 0); switch (BLE_MESH_MODEL_OP_LEN(opcode)) { @@ -825,6 +903,8 @@ void bt_mesh_model_msg_init(struct net_buf_simple *msg, uint32_t opcode) static bool ready_to_send(uint16_t dst) { + BT_DBG("IsReadyToSend, Dst 0x%04x", dst); + if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) { return true; } @@ -832,7 +912,7 @@ static bool ready_to_send(uint16_t dst) if (IS_ENABLED(CONFIG_BLE_MESH_PROVISIONER) && bt_mesh_is_provisioner_en()) { if (bt_mesh_provisioner_check_msg_dst(dst) == false && bt_mesh_elem_find(dst) == false) { - BT_ERR("Failed to find DST 0x%04x", dst); + BT_ERR("Failed to find Dst 0x%04x", dst); return false; } return true; @@ -844,15 +924,19 @@ static bool ready_to_send(uint16_t dst) #if !CONFIG_BLE_MESH_V11_SUPPORT static bool use_friend_cred(uint16_t net_idx, uint16_t dst) { + BT_DBG("IsFrndCredUsed, NetIdx 0x%04x Dst 0x%04x", net_idx, dst); + /* Currently LPN only supports using NetKey in bt_mesh.sub[0] */ if (IS_ENABLED(CONFIG_BLE_MESH_LOW_POWER) && net_idx == 0 && bt_mesh_lpn_match(dst)) { + BT_DBG("LPNMatch"); return true; } if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && bt_mesh_friend_match(net_idx, dst)) { + BT_DBG("FrndMatch"); return true; } @@ -867,6 +951,9 @@ bool bt_mesh_valid_security_cred(struct bt_mesh_net_tx *tx) * If not, later a better security credentials could be * chosen for the message. */ + BT_DBG("IsValidSecCred, NetIdx 0x%04x Tag 0x%02x Cred %u", + tx->ctx->net_idx, tx->ctx->send_tag, tx->ctx->send_cred); + if (!bt_mesh_tag_immutable_cred(tx->ctx->send_tag)) { return true; } @@ -895,22 +982,27 @@ void bt_mesh_choose_better_security_cred(struct bt_mesh_net_tx *tx) net_idx = tx->ctx->net_idx; addr = tx->ctx->addr; + BT_DBG("ChooseBetterSecCred"); + BT_DBG("NetIdx 0x%04x Dst 0x%04x Tag 0x%02x Cred %u", + net_idx, addr, send_tag, send_cred); + /* If the message is tagged with immutable-credentials, * then the security credentials shall not be changed. */ if (bt_mesh_tag_immutable_cred(send_tag)) { + BT_DBG("ImmutableCred"); return; } if (send_cred > BLE_MESH_FRIENDSHIP_CRED) { - BT_INFO("Use managed flooding security credentials"); + BT_INFO("UseFloodingSecCred"); tx->ctx->send_cred = BLE_MESH_FLOODING_CRED; return; } if (send_cred == BLE_MESH_FRIENDSHIP_CRED) { if (!use_friend_cred(net_idx, addr)) { - BT_INFO("Use managed flooding security credentials"); + BT_INFO("UseFloodingSecCred"); tx->ctx->send_cred = BLE_MESH_FLOODING_CRED; tx->ctx->send_tag = send_tag | BLE_MESH_TAG_IMMUTABLE_CRED; } else { @@ -935,14 +1027,13 @@ void bt_mesh_choose_better_security_cred(struct bt_mesh_net_tx *tx) if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && BLE_MESH_ADDR_IS_UNICAST(addr) && bt_mesh_friend_match(net_idx, addr)) { - BT_INFO("Use friendship security credentials"); + BT_INFO("UseFrndSecCred"); tx->ctx->send_cred = BLE_MESH_FRIENDSHIP_CRED; tx->ctx->send_tag = send_tag | BLE_MESH_TAG_IMMUTABLE_CRED; return; } - /** - * Spec 3.7.3.1 + /* Spec 3.7.3.1 * The Low power node in friendship should use friendship security * material. * @@ -962,11 +1053,12 @@ void bt_mesh_choose_better_security_cred(struct bt_mesh_net_tx *tx) if (BLE_MESH_ADDR_IS_UNICAST(addr) && bt_mesh.lpn.frnd == addr && !bt_mesh_tag_immutable_cred(send_tag)) { + BT_INFO("UseFrndSecCred"); tx->ctx->send_cred = BLE_MESH_FRIENDSHIP_CRED; tx->ctx->send_tag = send_tag | BLE_MESH_TAG_IMMUTABLE_CRED; return; } -#endif +#endif /* CONFIG_BLE_MESH_LOW_POWER */ } #endif /* !CONFIG_BLE_MESH_V11_SUPPORT */ @@ -977,9 +1069,10 @@ static int model_send(const struct bt_mesh_model *model, { int err = 0; - BT_INFO("send, app_idx 0x%04x src 0x%04x dst 0x%04x", - tx->ctx->app_idx, tx->src, tx->ctx->addr); - BT_INFO("send, len %u: %s", msg->len, bt_hex(msg->data, msg->len)); + BT_INFO("ModelSend"); + BT_INFO("AppIdx 0x%04x Src 0x%04x Dst 0x%04x TTL %u", + tx->ctx->app_idx, tx->src, tx->ctx->addr, tx->ctx->send_ttl); + BT_INFO("Len %u: %s", msg->len, bt_hex(msg->data, msg->len)); if (ready_to_send(tx->ctx->addr) == false) { BT_ERR("Not ready to send"); @@ -1032,7 +1125,7 @@ static int model_send(const struct bt_mesh_model *model, #if CONFIG_BLE_MESH_DF_SRV bt_mesh_is_directed_path_needed(tx); -#endif +#endif /* CONFIG_BLE_MESH_DF_SRV */ return err; } @@ -1044,9 +1137,11 @@ int bt_mesh_model_send_implicit(struct bt_mesh_model *model, { struct bt_mesh_subnet *sub = NULL; + BT_DBG("ModelSendImplicit"); + sub = bt_mesh_subnet_get(ctx->net_idx); if (!sub) { - BT_ERR("Send, NetKey 0x%04x not found", ctx->net_idx); + BT_ERR("NetIdx 0x%04x not found", ctx->net_idx); return -EADDRNOTAVAIL; } @@ -1067,9 +1162,11 @@ int bt_mesh_model_send(const struct bt_mesh_model *model, { struct bt_mesh_subnet *sub = NULL; + BT_DBG("ModelSend, NetIdx 0x%04x", ctx->net_idx); + sub = bt_mesh_subnet_get(ctx->net_idx); if (!sub) { - BT_ERR("Send, NetKey 0x%04x not found", ctx->net_idx); + BT_ERR("NetIdx 0x%04x not found", ctx->net_idx); return -EADDRNOTAVAIL; } @@ -1096,6 +1193,8 @@ int bt_mesh_model_publish(struct bt_mesh_model *model) }; int err = 0; + BT_DBG("ModelPublish"); + if (!pub || !pub->msg) { BT_ERR("Model has no publication support"); return -ENOTSUP; @@ -1144,12 +1243,12 @@ int bt_mesh_model_publish(struct bt_mesh_model *model) #if CONFIG_BLE_MESH_DF_SRV bt_mesh_model_pub_use_directed(&tx, pub->directed_pub_policy); -#endif +#endif /* CONFIG_BLE_MESH_DF_SRV */ pub->count = BLE_MESH_PUB_TRANSMIT_COUNT(pub->retransmit); - BT_INFO("Publish Retransmit Count %u Interval %ums", pub->count, - BLE_MESH_PUB_TRANSMIT_INT(pub->retransmit)); + BT_INFO("PubCount %u PubInterval %u", + pub->count, BLE_MESH_PUB_TRANSMIT_INT(pub->retransmit)); sdu = bt_mesh_alloc_buf(pub->msg->len + BLE_MESH_MIC_LONG); if (!sdu) { @@ -1173,6 +1272,8 @@ struct bt_mesh_model *bt_mesh_model_find_vnd(struct bt_mesh_elem *elem, { int i; + BT_DBG("ModelFindVnd, ID 0x%04x CID 0x%04x", id, company); + for (i = 0; i < elem->vnd_model_count; i++) { if (elem->vnd_models[i].vnd.company == company && elem->vnd_models[i].vnd.id == id) { @@ -1187,6 +1288,8 @@ struct bt_mesh_model *bt_mesh_model_find(struct bt_mesh_elem *elem, uint16_t id) { int i; + BT_DBG("ModelFind, ID 0x%04x", id); + for (i = 0; i < elem->model_count; i++) { if (elem->models[i].id == id) { return &elem->models[i]; @@ -1198,6 +1301,8 @@ struct bt_mesh_model *bt_mesh_model_find(struct bt_mesh_elem *elem, uint16_t id) const struct bt_mesh_comp *bt_mesh_comp_get(void) { + BT_DBG("CompGet %p", comp_0); + return comp_0; } @@ -1215,6 +1320,8 @@ const uint8_t *bt_mesh_dev_key_get(uint16_t dst) key = bt_mesh_provisioner_dev_key_get(dst); } + BT_DBG("Dst 0x%04x DevKey %s", dst, key ? bt_hex(key, 16) : ""); + return key; } @@ -1226,20 +1333,22 @@ size_t bt_mesh_rx_netkey_size(void) if (bt_mesh_is_provisioned()) { size = ARRAY_SIZE(bt_mesh.sub); } -#endif +#endif /* CONFIG_BLE_MESH_NODE && !CONFIG_BLE_MESH_PROVISIONER */ #if !CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PROVISIONER if (bt_mesh_is_provisioner_en()) { size = ARRAY_SIZE(bt_mesh.p_sub); } -#endif +#endif /* !CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PROVISIONER */ #if CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PROVISIONER size = ARRAY_SIZE(bt_mesh.sub); if (bt_mesh_is_provisioner_en()) { size += ARRAY_SIZE(bt_mesh.p_sub); } -#endif +#endif /* CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PROVISIONER */ + + BT_DBG("RxNetKeySize %u", size); return size; } @@ -1252,13 +1361,13 @@ struct bt_mesh_subnet *bt_mesh_rx_netkey_get(size_t index) if (bt_mesh_is_provisioned()) { sub = &bt_mesh.sub[index]; } -#endif +#endif /* CONFIG_BLE_MESH_NODE && !CONFIG_BLE_MESH_PROVISIONER */ #if !CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PROVISIONER if (bt_mesh_is_provisioner_en()) { sub = bt_mesh.p_sub[index]; } -#endif +#endif /* !CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PROVISIONER */ #if CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PROVISIONER if (index < ARRAY_SIZE(bt_mesh.sub)) { @@ -1266,7 +1375,10 @@ struct bt_mesh_subnet *bt_mesh_rx_netkey_get(size_t index) } else { sub = bt_mesh.p_sub[index - ARRAY_SIZE(bt_mesh.sub)]; } -#endif +#endif /* CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PROVISIONER */ + + BT_DBG("RxNetKeyGet, Index %u NetIdx 0x%04x", + index, sub ? sub->net_idx : BLE_MESH_KEY_ANY); return sub; } @@ -1290,7 +1402,7 @@ size_t bt_mesh_rx_devkey_size(void) if (bt_mesh_is_provisioner_en()) { size = 1; } -#endif +#endif /* !CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PROVISIONER */ #if CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PROVISIONER size = 1; @@ -1302,7 +1414,9 @@ size_t bt_mesh_rx_devkey_size(void) if (bt_mesh_is_provisioner_en()) { size += 1; } -#endif +#endif /* CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PROVISIONER */ + + BT_DBG("RxDevKeySize %u", size); return size; } @@ -1319,13 +1433,13 @@ const uint8_t *bt_mesh_rx_devkey_get(size_t index, uint16_t src) key = bt_mesh.dev_key_ca; } } -#endif +#endif /* CONFIG_BLE_MESH_NODE && !CONFIG_BLE_MESH_PROVISIONER */ #if !CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PROVISIONER if (bt_mesh_is_provisioner_en()) { key = bt_mesh_provisioner_dev_key_get(src); } -#endif +#endif /* !CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PROVISIONER */ #if CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PROVISIONER if (index == 0) { @@ -1343,11 +1457,13 @@ const uint8_t *bt_mesh_rx_devkey_get(size_t index, uint16_t src) */ key = bt_mesh.dev_key_ca; } else -#endif +#endif /* CONFIG_BLE_MESH_RPR_SRV */ { key = bt_mesh_provisioner_dev_key_get(src); } -#endif +#endif /* CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PROVISIONER */ + + BT_DBG("RxDevKeyGet, Index %u Src 0x%04x", index, src); return key; } @@ -1360,20 +1476,22 @@ size_t bt_mesh_rx_appkey_size(void) if (bt_mesh_is_provisioned()) { size = ARRAY_SIZE(bt_mesh.app_keys); } -#endif +#endif /* CONFIG_BLE_MESH_NODE && !CONFIG_BLE_MESH_PROVISIONER */ #if !CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PROVISIONER if (bt_mesh_is_provisioner_en()) { size = ARRAY_SIZE(bt_mesh.p_app_keys); } -#endif +#endif /* !CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PROVISIONER */ #if CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PROVISIONER size = ARRAY_SIZE(bt_mesh.app_keys); if (bt_mesh_is_provisioner_en()) { size += ARRAY_SIZE(bt_mesh.p_app_keys); } -#endif +#endif /* CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PROVISIONER */ + + BT_DBG("RxAppKeySize %u", size); return size; } @@ -1386,13 +1504,13 @@ struct bt_mesh_app_key *bt_mesh_rx_appkey_get(size_t index) if (bt_mesh_is_provisioned()) { key = &bt_mesh.app_keys[index]; } -#endif +#endif /* CONFIG_BLE_MESH_NODE && !CONFIG_BLE_MESH_PROVISIONER */ #if !CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PROVISIONER if (bt_mesh_is_provisioner_en()) { key = bt_mesh.p_app_keys[index]; } -#endif +#endif /* !CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PROVISIONER */ #if CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PROVISIONER if (index < ARRAY_SIZE(bt_mesh.app_keys)) { @@ -1400,36 +1518,44 @@ struct bt_mesh_app_key *bt_mesh_rx_appkey_get(size_t index) } else { key = bt_mesh.p_app_keys[index - ARRAY_SIZE(bt_mesh.app_keys)]; } -#endif +#endif /* CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PROVISIONER */ + + BT_DBG("RxAppKeyGet, Index %u AppIdx 0x%04x", + index, key ? key->app_idx : BLE_MESH_KEY_ANY); return key; } struct bt_mesh_app_key *bt_mesh_app_key_get(uint16_t app_idx) { + BT_DBG("AppKeyGet, AppIdx 0x%04x", app_idx); + if (bt_mesh_is_provisioned()) { #if CONFIG_BLE_MESH_NODE if (!IS_ENABLED(CONFIG_BLE_MESH_FAST_PROV)) { for (int i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) { if (bt_mesh.app_keys[i].net_idx != BLE_MESH_KEY_UNUSED && bt_mesh.app_keys[i].app_idx == app_idx) { + BT_DBG("NodeAppKey"); return &bt_mesh.app_keys[i]; } } } else { + BT_DBG("FastProvAppKey"); return bt_mesh_fast_prov_app_key_find(app_idx); } -#endif +#endif /* CONFIG_BLE_MESH_NODE */ } else if (bt_mesh_is_provisioner_en()) { #if CONFIG_BLE_MESH_PROVISIONER for (int i = 0; i < ARRAY_SIZE(bt_mesh.p_app_keys); i++) { if (bt_mesh.p_app_keys[i] && bt_mesh.p_app_keys[i]->net_idx != BLE_MESH_KEY_UNUSED && bt_mesh.p_app_keys[i]->app_idx == app_idx) { + BT_DBG("PvnrAppKey"); return bt_mesh.p_app_keys[i]; } } -#endif +#endif /* CONFIG_BLE_MESH_PROVISIONER */ } return NULL; @@ -1440,10 +1566,12 @@ int bt_mesh_upper_key_get(const struct bt_mesh_subnet *subnet, uint16_t app_idx, { struct bt_mesh_app_key *app_key = NULL; + BT_DBG("UpperKeyGet, AppIdx 0x%04x Dst 0x%04x", app_idx, dst); + if (app_idx == BLE_MESH_KEY_DEV) { *key = bt_mesh_dev_key_get(dst); if (!*key) { - BT_ERR("DevKey of 0x%04x not found", dst); + BT_ERR("DevKeyNotFound 0x%04x", dst); return -EINVAL; } @@ -1452,20 +1580,22 @@ int bt_mesh_upper_key_get(const struct bt_mesh_subnet *subnet, uint16_t app_idx, } if (!subnet) { - BT_ERR("Invalid subnet"); + BT_ERR("InvalidSubnet"); return -EINVAL; } app_key = bt_mesh_app_key_get(app_idx); if (!app_key) { - BT_ERR("AppKey 0x%04x not found", app_idx); + BT_ERR("AppKeyNotFound 0x%04x", app_idx); return -ENOENT; } if (subnet->kr_phase == BLE_MESH_KR_PHASE_2 && app_key->updated) { + BT_DBG("NewAppKey"); *key = app_key->keys[1].val; *aid = app_key->keys[1].id; } else { + BT_DBG("OldAppKey"); *key = app_key->keys[0].val; *aid = app_key->keys[0].id; } diff --git a/components/bt/esp_ble_mesh/core/adv.c b/components/bt/esp_ble_mesh/core/adv.c index d9096caa136..bb7b9771ca1 100644 --- a/components/bt/esp_ble_mesh/core/adv.c +++ b/components/bt/esp_ble_mesh/core/adv.c @@ -29,12 +29,10 @@ static struct bt_mesh_adv_queue *adv_queue; #if CONFIG_BLE_MESH_RELAY_ADV_BUF - #define BLE_MESH_RELAY_QUEUE_SIZE CONFIG_BLE_MESH_RELAY_ADV_BUF_COUNT static QueueSetHandle_t mesh_queue_set; #define BLE_MESH_QUEUE_SET_SIZE (BLE_MESH_ADV_QUEUE_SIZE + BLE_MESH_RELAY_QUEUE_SIZE) - #endif /* CONFIG_BLE_MESH_RELAY_ADV_BUF */ static int adv_send(struct net_buf *buf) @@ -47,8 +45,8 @@ static int adv_send(struct net_buf *buf) struct bt_mesh_adv_data ad = {0}; int err = 0; - BT_DBG("type %u len %u: %s", BLE_MESH_ADV(buf)->type, - buf->len, bt_hex(buf->data, buf->len)); + BT_DBG("LegacyAdvSend, Type %u", BLE_MESH_ADV(buf)->type); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV if (BLE_MESH_ADV(buf)->type != BLE_MESH_ADV_BLE) { @@ -116,10 +114,12 @@ static int adv_send(struct net_buf *buf) #if CONFIG_BLE_MESH_PROXY_SOLIC_PDU_TX if (BLE_MESH_ADV(buf)->type == BLE_MESH_ADV_PROXY_SOLIC) { bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL); + struct bt_mesh_adv_data solic_ad[2] = { BLE_MESH_ADV_DATA_BYTES(BLE_MESH_DATA_UUID16_ALL, 0x59, 0x18), BLE_MESH_ADV_DATA(BLE_MESH_DATA_SVC_DATA16, buf->data, buf->len), }; + #if CONFIG_BLE_MESH_USE_BLE_50 param.primary_phy = BLE_MESH_ADV_PHY_1M; param.secondary_phy = BLE_MESH_ADV_PHY_1M; @@ -128,9 +128,10 @@ static int adv_send(struct net_buf *buf) err = bt_le_adv_start(¶m, solic_ad, ARRAY_SIZE(solic_ad), NULL, 0); #endif /* CONFIG_BLE_MESH_USE_BLE_50 */ } else -#endif +#endif /* CONFIG_BLE_MESH_PROXY_SOLIC_PDU_TX */ { bt_mesh_adv_buf_ref_debug(__func__, buf, 4U, BLE_MESH_BUF_REF_SMALL); + #if CONFIG_BLE_MESH_USE_BLE_50 param.primary_phy = BLE_MESH_ADV_PHY_1M; param.secondary_phy = BLE_MESH_ADV_PHY_1M; @@ -151,8 +152,8 @@ static int adv_send(struct net_buf *buf) } BT_DBG("interval %dms, duration %dms, period %dms, count %d", - ADV_SCAN_INT(tx->param.interval), tx->param.duration, - tx->param.period, tx->param.count); + ADV_SCAN_INT(tx->param.interval), tx->param.duration, + tx->param.period, tx->param.count); data.adv_data_len = tx->buf->data[0]; if (data.adv_data_len) { @@ -175,6 +176,7 @@ static int adv_send(struct net_buf *buf) #endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ net_buf_unref(buf); + adv_send_start(duration, err, cb, cb_data); if (err) { BT_ERR("Start advertising failed: err %d", err); @@ -209,9 +211,12 @@ static QueueHandle_t relay_adv_handle_get(void) { struct bt_mesh_adv_type_manager *adv_type = NULL; + BT_DBG("RelayAdvHandleGet"); + adv_type = bt_mesh_adv_types_mgmt_get(BLE_MESH_ADV_RELAY_DATA); if (adv_type->adv_q == NULL) { + BT_DBG("HandleNotFound"); return NULL; } @@ -224,7 +229,7 @@ static void adv_thread(void *p) #if CONFIG_BLE_MESH_RELAY_ADV_BUF QueueHandle_t relay_adv_handle = NULL; QueueSetMemberHandle_t handle = NULL; -#endif +#endif /* CONFIG_BLE_MESH_RELAY_ADV_BUF */ struct net_buf **buf = NULL; bt_mesh_msg_t msg = {0}; @@ -235,24 +240,29 @@ static void adv_thread(void *p) buf = (struct net_buf **)(&msg.arg); - BT_DBG("%s, starts", __func__); + BT_DBG("LegacyAdvThread"); while (1) { *buf = NULL; + #if !CONFIG_BLE_MESH_RELAY_ADV_BUF #if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ CONFIG_BLE_MESH_GATT_PROXY_SERVER xQueueReceive(adv_queue->q.handle, &msg, K_NO_WAIT); while (!(*buf)) { int32_t timeout = 0; + BT_DBG("Mesh Proxy Advertising start"); + timeout = bt_mesh_proxy_server_adv_start(); BT_DBG("Mesh Proxy Advertising up to %d ms", timeout); + xQueueReceive(adv_queue->q.handle, &msg, K_WAIT(timeout)); + BT_DBG("Mesh Proxy Advertising stop"); bt_mesh_proxy_server_adv_stop(); } -#else +#else /* (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || CONFIG_BLE_MESH_GATT_PROXY_SERVER */ xQueueReceive(adv_queue->q.handle, &msg, portMAX_DELAY); #endif /* (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || CONFIG_BLE_MESH_GATT_PROXY_SERVER */ #else /* !CONFIG_BLE_MESH_RELAY_ADV_BUF */ @@ -268,12 +278,17 @@ static void adv_thread(void *p) } else { while (!(*buf)) { int32_t timeout = 0; + BT_DBG("Mesh Proxy Advertising start"); + timeout = bt_mesh_proxy_server_adv_start(); BT_DBG("Mesh Proxy Advertising up to %d ms", timeout); + handle = xQueueSelectFromSet(mesh_queue_set, K_WAIT(timeout)); + BT_DBG("Mesh Proxy Advertising stop"); bt_mesh_proxy_server_adv_stop(); + if (handle) { if (uxQueueMessagesWaiting(adv_queue->q.handle)) { xQueueReceive(adv_queue->q.handle, &msg, K_NO_WAIT); @@ -283,7 +298,7 @@ static void adv_thread(void *p) } } } -#else +#else /* (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || CONFIG_BLE_MESH_GATT_PROXY_SERVER */ handle = xQueueSelectFromSet(mesh_queue_set, portMAX_DELAY); if (handle) { if (uxQueueMessagesWaiting(adv_queue->q.handle)) { @@ -311,6 +326,7 @@ static void adv_thread(void *p) * BLE_MESH_RELAY_TIME_INTERVAL, this relay packet will not be sent. */ BT_INFO("Ignore relay packet"); + net_buf_unref(*buf); } else { if (adv_send(*buf)) { @@ -323,6 +339,8 @@ static void adv_thread(void *p) net_buf_unref(*buf); } + BT_DBG("Yield"); + /* Give other threads a chance to run */ taskYIELD(); } @@ -335,11 +353,14 @@ void bt_mesh_adv_update(void) .arg = NULL, }; + BT_DBG("LegacyAdvUpdate"); + bt_mesh_task_post(&msg, K_NO_WAIT, false); } void bt_mesh_adv_init(void) { + BT_DBG("LegacyAdvInit"); bt_mesh_adv_common_init(); adv_queue = bt_mesh_adv_queue_get(); @@ -347,20 +368,22 @@ void bt_mesh_adv_init(void) #if CONFIG_BLE_MESH_RELAY_ADV_BUF bt_mesh_relay_adv_init(); -#endif +#endif /* CONFIG_BLE_MESH_RELAY_ADV_BUF */ #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV bt_mesh_ble_adv_init(); -#endif +#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ #if CONFIG_BLE_MESH_RELAY_ADV_BUF QueueHandle_t relay_adv_handle = relay_adv_handle_get(); assert(relay_adv_handle); + mesh_queue_set = xQueueCreateSet(BLE_MESH_QUEUE_SET_SIZE); assert(mesh_queue_set); + xQueueAddToSet(adv_queue->q.handle, mesh_queue_set); xQueueAddToSet(relay_adv_handle, mesh_queue_set); -#endif +#endif /* CONFIG_BLE_MESH_RELAY_ADV_BUF */ bt_mesh_adv_task_init(adv_thread); } @@ -368,6 +391,8 @@ void bt_mesh_adv_init(void) #if CONFIG_BLE_MESH_DEINIT void bt_mesh_adv_deinit(void) { + BT_DBG("LegacyAdvDeinit"); + /* Adv task must be deinit first */ bt_mesh_adv_task_deinit(); @@ -377,6 +402,7 @@ void bt_mesh_adv_deinit(void) xQueueRemoveFromSet(adv_queue->q.handle, mesh_queue_set); xQueueRemoveFromSet(relay_adv_handle, mesh_queue_set); + vQueueDelete(mesh_queue_set); mesh_queue_set = NULL; diff --git a/components/bt/esp_ble_mesh/core/adv.h b/components/bt/esp_ble_mesh/core/adv.h index a2c8dd03301..79f8ca2991b 100644 --- a/components/bt/esp_ble_mesh/core/adv.h +++ b/components/bt/esp_ble_mesh/core/adv.h @@ -26,10 +26,13 @@ extern "C" { void bt_mesh_adv_update(void); void bt_mesh_adv_init(void); + void bt_mesh_adv_deinit(void); #ifdef __cplusplus } #endif + #endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ + #endif /* _ADV_H_ */ diff --git a/components/bt/esp_ble_mesh/core/adv_common.c b/components/bt/esp_ble_mesh/core/adv_common.c index ec1e3b68dbc..193dcf4c43b 100644 --- a/components/bt/esp_ble_mesh/core/adv_common.c +++ b/components/bt/esp_ble_mesh/core/adv_common.c @@ -31,8 +31,7 @@ struct bt_mesh_adv_queue relay_adv_queue; #define BLE_MESH_RELAY_TIME_INTERVAL K_SECONDS(6) #define BLE_MESH_MAX_TIME_INTERVAL 0xFFFFFFFF - -#endif +#endif /* CONFIG_BLE_MESH_RELAY_ADV_BUF */ static bt_mesh_mutex_t adv_buf_alloc_lock; #if CONFIG_BLE_MESH_EXT_ADV @@ -77,7 +76,7 @@ NET_BUF_POOL_FIXED_DEFINE(friend_buf_pool, FRIEND_BUF_COUNT, BLE_MESH_ADV_DATA_SIZE, NULL); static bt_mesh_friend_adv_t frnd_adv_pool[FRIEND_BUF_COUNT]; -#endif +#endif /* CONFIG_BLE_MESH_FRIEND */ struct bt_mesh_adv_task { TaskHandle_t handle; @@ -90,6 +89,7 @@ struct bt_mesh_adv_task { }; static struct bt_mesh_adv_task adv_task; + static struct bt_mesh_adv_type_manager adv_types[BLE_MESH_ADV_TYPES_NUM]; #if CONFIG_BLE_MESH_USE_BLE_50 @@ -98,7 +98,7 @@ static struct bt_mesh_adv_inst adv_insts[] = { .id = CONFIG_BLE_MESH_ADV_INST_ID, #if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV .busy = false, -#endif +#endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ }, #if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV #if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ @@ -113,24 +113,27 @@ static struct bt_mesh_adv_inst adv_insts[] = { .id = CONFIG_BLE_MESH_RELAY_ADV_INST_ID, .busy = false, }, -#endif +#endif /* CONFIG_BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE */ #if CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE [BLE_MESH_BLE_ADV_INST] = { .id = CONFIG_BLE_MESH_BLE_ADV_INST_ID, .busy = false, }, -#endif +#endif /* CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE */ #endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ }; static struct bt_mesh_adv_inst *find_adv_inst_with_inst_id(uint8_t id) { + BT_DBG("FindAdvInstWithID, InstID %u", id); + for (int i = 0; i < ARRAY_SIZE(adv_insts); i++) { if (adv_insts[i].id == id) { return &adv_insts[i]; } } + BT_WARN("NotFoundAdvInst, InstID %u", id); return NULL; } @@ -139,47 +142,57 @@ struct bt_mesh_adv_inst *bt_mesh_get_adv_insts_set(void) return adv_insts; } -bool bt_mesh_is_adv_inst_used(uint8_t adv_inst_id) +bool bt_mesh_is_adv_inst_used(uint8_t inst_id) { - return (find_adv_inst_with_inst_id(adv_inst_id) != NULL); + BT_DBG("IsAdvInstUsed, InstID %u", inst_id); + + return (find_adv_inst_with_inst_id(inst_id) != NULL); } int bt_mesh_adv_inst_init(enum bt_mesh_adv_inst_type inst_type, uint8_t inst_id) { + BT_DBG("AdvInstInit, InstType %u InstID %u", inst_type, inst_id); + if (inst_type >= BLE_MESH_ADV_INST_TYPES_NUM) { - BT_ERR("Invalid instance type %d", inst_type); + BT_ERR("InvalidAdvInstType %u", inst_type); return -EINVAL; } if (inst_id == BLE_MESH_ADV_INS_UNUSED) { - BT_ERR("Invalid instance id %d", inst_id); + BT_ERR("UnusedAdvInstID"); return -EINVAL; } adv_insts[inst_type].id = inst_id; + return 0; } int bt_mesh_adv_inst_deinit(enum bt_mesh_adv_inst_type inst_type) { + BT_DBG("AdvInstDeinit, InstType %u", inst_type); + if (inst_type >= BLE_MESH_ADV_INST_TYPES_NUM) { - BT_ERR("Invalid instance type %d", inst_type); + BT_ERR("Invalid adv inst type %d", inst_type); return -EINVAL; } + BT_DBG("InstID %u", adv_insts[inst_type].id); + bt_le_ext_adv_stop(adv_insts[inst_type].id); adv_insts[inst_type].id = BLE_MESH_ADV_INS_UNUSED; #if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV adv_insts[inst_type].spt_mask = 0; -#endif +#endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ + return 0; } - #endif /* CONFIG_BLE_MESH_USE_BLE_50 */ static struct bt_mesh_adv *adv_alloc(int id, enum bt_mesh_adv_type type) { + BT_DBG("AdvAlloc, ID %d", id); init_adv_with_defaults(&adv_pool[id], type); return &adv_pool[id]; } @@ -232,6 +245,8 @@ struct bt_mesh_adv *ext_long_relay_adv_alloc(int id, enum bt_mesh_adv_type type) struct bt_mesh_adv_type_manager *bt_mesh_adv_types_mgnt_get(enum bt_mesh_adv_type adv_type) { + BT_DBG("AdvTypeMgmtGet, AdvType %u", adv_type); + return &adv_types[adv_type]; } @@ -243,6 +258,8 @@ void bt_mesh_adv_buf_ref_debug(const char *func, struct net_buf *buf, return; } + BT_DBG("AdvBufRefDebug, BufRef %u RefCmp %u", buf->ref, ref_cmp); + switch (flag) { case BLE_MESH_BUF_REF_EQUAL: if (buf->ref != ref_cmp) { @@ -263,8 +280,10 @@ void bt_mesh_adv_buf_ref_debug(const char *func, struct net_buf *buf, void bt_mesh_adv_inst_type_add(enum bt_mesh_adv_inst_type inst_type, enum bt_mesh_adv_type adv_type) { + BT_DBG("AdvInstTypeAdd, InstType %u AdvType %u", inst_type, adv_type); + if (inst_type >= BLE_MESH_ADV_INST_TYPES_NUM) { - BT_ERR("Invalid instance type %d", inst_type); + BT_ERR("Invalid adv inst type %d", inst_type); return; } @@ -276,11 +295,13 @@ void bt_mesh_adv_inst_type_add(enum bt_mesh_adv_inst_type inst_type, adv_insts[inst_type].spt_mask |= BIT(adv_type); } -void bt_mesh_adv_inst_type_rm(enum bt_mesh_adv_inst_type inst_type, - enum bt_mesh_adv_type adv_type) +void bt_mesh_adv_inst_type_rem(enum bt_mesh_adv_inst_type inst_type, + enum bt_mesh_adv_type adv_type) { + BT_DBG("AdvInstTypeRem, InstType %u AdvType %u", inst_type, adv_type); + if (inst_type >= BLE_MESH_ADV_INST_TYPES_NUM) { - BT_ERR("Invalid instance type %d", inst_type); + BT_ERR("Invalid adv inst type %d", inst_type); return; } @@ -292,11 +313,13 @@ void bt_mesh_adv_inst_type_rm(enum bt_mesh_adv_inst_type inst_type, adv_insts[inst_type].spt_mask &= ~BIT(adv_type); } -void bt_mesh_adv_inst_supported_adv_type_clear(enum bt_mesh_adv_inst_type inst_type, - enum bt_mesh_adv_type adv_type) +void bt_mesh_adv_inst_type_clear(enum bt_mesh_adv_inst_type inst_type, + enum bt_mesh_adv_type adv_type) { + BT_DBG("AdvInstTypeClear, InstType %u AdvType %u", inst_type, adv_type); + if (inst_type >= BLE_MESH_ADV_INST_TYPES_NUM) { - BT_ERR("Invalid instance type %d", inst_type); + BT_ERR("Invalid adv inst type %d", inst_type); return; } @@ -307,18 +330,19 @@ void bt_mesh_adv_inst_supported_adv_type_clear(enum bt_mesh_adv_inst_type inst_t adv_insts[inst_type].spt_mask = 0; } -#endif +#endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ int bt_mesh_adv_queue_init(struct bt_mesh_adv_queue *adv_queue, uint16_t queue_size, bt_mesh_adv_queue_send_cb_t cb) { + BT_DBG("AdvQueueInit, QueueSize %u", queue_size); + if (!adv_queue || !queue_size || !cb) { - BT_ERR("Invalid param %s", __func__); + BT_ERR("%s, Invalid parameter", __func__); return -EINVAL; } bt_mesh_queue_init(&adv_queue->q, queue_size, sizeof(bt_mesh_msg_t)); - adv_queue->send = cb; return 0; @@ -326,13 +350,14 @@ int bt_mesh_adv_queue_init(struct bt_mesh_adv_queue *adv_queue, uint16_t queue_s int bt_mesh_adv_queue_deinit(struct bt_mesh_adv_queue *adv_queue) { + BT_DBG("AdvQueueDeinit"); + if (!adv_queue) { - BT_ERR("Invalid param %s", __func__); + BT_ERR("%s, Invalid parameter", __func__); return -EINVAL; } bt_mesh_queue_deinit(&adv_queue->q); - adv_queue->send = NULL; return 0; @@ -343,13 +368,15 @@ void bt_mesh_adv_type_init(enum bt_mesh_adv_type adv_type, struct net_buf_pool *buf_pool, bt_mesh_pool_allocator_t adv_alloc) { + BT_DBG("AdvTypeInit, AdvType %u", adv_type); + if (adv_type >= BLE_MESH_ADV_TYPES_NUM) { - BT_ERR("%s Invalid adv type %d",__func__, adv_type); + BT_ERR("%s, Invalid adv type %d", __func__, adv_type); return; } if (!adv_queue || !buf_pool || !adv_alloc) { - BT_ERR("Invalid parameters %s", __func__); + BT_ERR("%s, Invalid parameter", __func__); return; } @@ -360,8 +387,10 @@ void bt_mesh_adv_type_init(enum bt_mesh_adv_type adv_type, void bt_mesh_adv_type_deinit(enum bt_mesh_adv_type adv_type) { + BT_DBG("AdvTypeDeinit, AdvType %u", adv_type); + if (adv_type >= BLE_MESH_ADV_TYPES_NUM) { - BT_ERR("%s Invalid adv type %d",__func__, adv_type); + BT_ERR("%s, Invalid adv type %d", __func__, adv_type); return; } @@ -373,17 +402,23 @@ void bt_mesh_adv_type_deinit(enum bt_mesh_adv_type adv_type) #if CONFIG_BLE_MESH_USE_BLE_50 int bt_mesh_adv_task_wakeup(uint32_t evt) { + BT_DBG("AdvTypeWakeup, Evt 0x%08lx", evt); + xTaskNotify(adv_task.handle, evt, eSetBits); return 0; } bool bt_mesh_adv_task_wait(uint32_t wait_bits, uint32_t timeout, uint32_t *notify) { + BT_DBG("AdvTypeWait, WaitBits 0x%08lx Timeout %lu", wait_bits, timeout); + return (xTaskNotifyWait(wait_bits, UINT32_MAX, notify, K_WAIT(timeout)) == pdTRUE); } #else /* CONFIG_BLE_MESH_USE_BLE_50 */ bool bt_mesh_adv_task_wait(uint32_t timeout) { + BT_DBG("AdvTypeWait, Timeout %lu", timeout); + vTaskDelay(K_WAIT(timeout)); return true; } @@ -397,6 +432,8 @@ uint16_t bt_mesh_pdu_duration(uint8_t xmit) adv_int = MAX(ADV_ITVL_MIN, BLE_MESH_TRANSMIT_INT(xmit)); duration = (BLE_MESH_TRANSMIT_COUNT(xmit) + 1) * (adv_int + 10); + BT_DBG("PDUDuration %u", duration); + return duration; } @@ -405,6 +442,8 @@ struct net_buf *bt_mesh_adv_create_from_pool(enum bt_mesh_adv_type type, int32_t struct bt_mesh_adv *adv = NULL; struct net_buf *buf = NULL; + BT_DBG("AdvCreateFromPool, Type %u", type); + if (bt_mesh_atomic_test_bit(bt_mesh.flags, BLE_MESH_SUSPENDED)) { BT_WARN("Refusing to allocate buffer while suspended"); return NULL; @@ -424,23 +463,27 @@ struct net_buf *bt_mesh_adv_create_from_pool(enum bt_mesh_adv_type type, int32_t buf = net_buf_alloc(adv_types[type].pool, timeout); if (!buf) { + BT_WARN("net buf alloc failed"); bt_mesh_r_mutex_unlock(&adv_buf_alloc_lock); - BT_WARN("Buf alloc failed"); return NULL; } - BT_DBG("pool %p, buf_count %d, uinit_count %d, ref %d", - adv_types[type].pool, adv_types[type].pool->buf_count, - adv_types[type].pool->uninit_count, buf->ref); + BT_DBG("Pool %p BufCount %u UinitCount %u BufID %d Ref %u", + adv_types[type].pool, adv_types[type].pool->buf_count, + adv_types[type].pool->uninit_count, net_buf_id(buf), + buf->ref); adv = adv_types[type].pool_allocator(net_buf_id(buf), type); BLE_MESH_ADV(buf) = adv; bt_mesh_r_mutex_unlock(&adv_buf_alloc_lock); + return buf; } void bt_mesh_unref_buf_from_pool(struct net_buf_pool *pool) { + BT_DBG("UnrefBufFromPool"); + if (pool == NULL) { BT_ERR("%s, Invalid parameter", __func__); return; @@ -448,6 +491,9 @@ void bt_mesh_unref_buf_from_pool(struct net_buf_pool *pool) for (int i = 0; i < pool->buf_count; i++) { struct net_buf *buf = &pool->__bufs[i]; + + BT_DBG("%u: Buf %p Ref %u", i, buf, buf->ref); + if (buf->ref > 1U) { buf->ref = 1U; } @@ -459,8 +505,13 @@ void bt_mesh_unref_buf(bt_mesh_msg_t *msg) { struct net_buf *buf = msg->arg; + BT_DBG("UnRefBuf %p", buf); + if (buf) { + BT_DBG("Ref %u", buf->ref); + bt_mesh_atomic_set(&BLE_MESH_ADV_BUSY(buf), 0); + if (buf->ref > 1U) { buf->ref = 1U; } @@ -477,8 +528,10 @@ void bt_mesh_generic_adv_send(struct net_buf *buf, uint8_t xmit, .relay = false, /* useless flag in multi-instance mode */ }; - BT_DBG("type 0x%02x len %u: %s", BLE_MESH_ADV(buf)->type, buf->len, - bt_hex(buf->data, buf->len)); + BT_DBG("GenericAdvSend"); + BT_DBG("Src 0x%04x Dst 0x%04x Type 0x%02x", + src, dst, BLE_MESH_ADV(buf)->type); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); BLE_MESH_ADV(buf)->cb = cb; BLE_MESH_ADV(buf)->cb_data = cb_data; @@ -495,8 +548,10 @@ void bt_mesh_generic_adv_send(struct net_buf *buf, uint8_t xmit, msg.src = src; msg.dst = dst; msg.timestamp = k_uptime_get_32(); + + BT_DBG("RelayAdvData, Timestamp %lu", msg.timestamp); } -#endif +#endif /* CONFIG_BLE_MESH_RELAY_ADV_BUF */ assert(adv_types[BLE_MESH_ADV(buf)->type].adv_q); assert(adv_types[BLE_MESH_ADV(buf)->type].adv_q->send); @@ -505,7 +560,7 @@ void bt_mesh_generic_adv_send(struct net_buf *buf, uint8_t xmit, #if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV bt_mesh_adv_task_wakeup(ADV_TASK_PKT_SEND_EVT); -#endif +#endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ } struct bt_mesh_adv_queue *bt_mesh_adv_queue_get(void) @@ -515,6 +570,8 @@ struct bt_mesh_adv_queue *bt_mesh_adv_queue_get(void) void bt_mesh_task_post(bt_mesh_msg_t *msg, uint32_t timeout, bool front) { + BT_DBG("TaskPost, Front %u", front); + if (adv_queue.q.handle == NULL) { BT_ERR("Invalid adv queue"); return; @@ -545,11 +602,15 @@ bool bt_mesh_ignore_relay_packet(uint32_t timestamp) interval = BLE_MESH_MAX_TIME_INTERVAL - (timestamp - now) + 1; } + BT_DBG("IgnoreRelayPacket"); + BT_DBG("Now %lu Timestamp %lu Interval %lu", now, timestamp, interval); + return ((interval >= BLE_MESH_RELAY_TIME_INTERVAL) ? true : false); } static struct bt_mesh_adv *relay_adv_alloc(int id, enum bt_mesh_adv_type type) { + BT_DBG("RelayAdvAlloc, ID %d", id); memset(&relay_adv_pool[id], 0, sizeof(struct bt_mesh_adv)); init_adv_with_defaults(&relay_adv_pool[id], type); return &relay_adv_pool[id]; @@ -559,7 +620,7 @@ static void bt_mesh_relay_task_post(bt_mesh_msg_t *msg, uint32_t timeout, bool f { bt_mesh_msg_t old_msg = {0}; - ARG_UNUSED(front); + BT_DBG("RelayTaskPost, Front %u", front); if (relay_adv_queue.q.handle == NULL) { BT_ERR("Invalid relay queue"); @@ -575,14 +636,17 @@ static void bt_mesh_relay_task_post(bt_mesh_msg_t *msg, uint32_t timeout, bool f */ if (uxQueueMessagesWaiting(relay_adv_queue.q.handle)) { BT_INFO("Full queue, remove the oldest relay packet"); + /* Remove the oldest relay packet from queue */ if (xQueueReceive(relay_adv_queue.q.handle, &old_msg, K_NO_WAIT) != pdTRUE) { BT_ERR("Failed to remove item from relay queue"); bt_mesh_unref_buf(msg); return; } + /* Unref buf used for the oldest relay packet */ bt_mesh_unref_buf(&old_msg); + /* Send the latest relay packet to queue */ if (xQueueSend(relay_adv_queue.q.handle, msg, K_NO_WAIT) != pdTRUE) { BT_ERR("Failed to send item to relay queue"); @@ -597,7 +661,11 @@ static void bt_mesh_relay_task_post(bt_mesh_msg_t *msg, uint32_t timeout, bool f uint16_t bt_mesh_get_stored_relay_count(void) { - return (uint16_t)uxQueueMessagesWaiting(relay_adv_queue.q.handle); + uint16_t count = (uint16_t)uxQueueMessagesWaiting(relay_adv_queue.q.handle); + + BT_DBG("StoredRelayCount %u", count); + + return count; } static ALWAYS_INLINE @@ -617,6 +685,7 @@ uint16_t bt_mesh_relay_adv_buf_count_get(void) void bt_mesh_relay_adv_init(void) { + BT_DBG("RelayAdvInit"); bt_mesh_adv_queue_init(&relay_adv_queue, bt_mesh_relay_adv_buf_count_get(), bt_mesh_relay_task_post); bt_mesh_adv_type_init(BLE_MESH_ADV_RELAY_DATA, &relay_adv_queue, @@ -655,10 +724,14 @@ void bt_mesh_relay_adv_init(void) #endif /* CONFIG_BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE */ #endif /* CONFIG_BLE_MESH_USE_BLE_50 */ } + #if CONFIG_BLE_MESH_DEINIT void bt_mesh_relay_adv_deinit(void) { + BT_DBG("RelayAdvDeinit"); + bt_mesh_adv_queue_deinit(&relay_adv_queue); + bt_mesh_adv_type_deinit(BLE_MESH_ADV_RELAY_DATA); #if CONFIG_BLE_MESH_EXT_ADV bt_mesh_adv_type_deinit(BLE_MESH_ADV_EXT_RELAY_DATA); @@ -669,26 +742,27 @@ void bt_mesh_relay_adv_deinit(void) #if CONFIG_BLE_MESH_USE_BLE_50 #if CONFIG_BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE - bt_mesh_adv_inst_type_rm(BLE_MESH_RELAY_ADV_INST, BLE_MESH_ADV_RELAY_DATA); + bt_mesh_adv_inst_type_rem(BLE_MESH_RELAY_ADV_INST, BLE_MESH_ADV_RELAY_DATA); #if CONFIG_BLE_MESH_EXT_ADV - bt_mesh_adv_inst_type_rm(BLE_MESH_RELAY_ADV_INST, BLE_MESH_ADV_EXT_RELAY_DATA); + bt_mesh_adv_inst_type_rem(BLE_MESH_RELAY_ADV_INST, BLE_MESH_ADV_EXT_RELAY_DATA); #if CONFIG_BLE_MESH_LONG_PACKET - bt_mesh_adv_inst_type_rm(BLE_MESH_RELAY_ADV_INST, BLE_MESH_ADV_EXT_LONG_RELAY_DATA); + bt_mesh_adv_inst_type_rem(BLE_MESH_RELAY_ADV_INST, BLE_MESH_ADV_EXT_LONG_RELAY_DATA); #endif /* CONFIG_BLE_MESH_LONG_PACKET */ #endif /* CONFIG_BLE_MESH_EXT_ADV */ bt_mesh_adv_inst_deinit(BLE_MESH_RELAY_ADV_INST); #else /* CONFIG_BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE */ #if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV - bt_mesh_adv_inst_type_rm(BLE_MESH_ADV_INST, BLE_MESH_ADV_RELAY_DATA); + bt_mesh_adv_inst_type_rem(BLE_MESH_ADV_INST, BLE_MESH_ADV_RELAY_DATA); #if CONFIG_BLE_MESH_EXT_ADV - bt_mesh_adv_inst_type_rm(BLE_MESH_ADV_INST, BLE_MESH_ADV_EXT_RELAY_DATA); + bt_mesh_adv_inst_type_rem(BLE_MESH_ADV_INST, BLE_MESH_ADV_EXT_RELAY_DATA); #if CONFIG_BLE_MESH_LONG_PACKET - bt_mesh_adv_inst_type_rm(BLE_MESH_ADV_INST, BLE_MESH_ADV_EXT_LONG_RELAY_DATA); + bt_mesh_adv_inst_type_rem(BLE_MESH_ADV_INST, BLE_MESH_ADV_EXT_LONG_RELAY_DATA); #endif /* CONFIG_BLE_MESH_LONG_PACKET */ #endif /* CONFIG_BLE_MESH_EXT_ADV */ #endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ #endif /* CONFIG_BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE */ #endif /* CONFIG_BLE_MESH_USE_BLE_50 */ + bt_mesh_unref_buf_from_pool(&relay_adv_buf_pool); memset(relay_adv_pool, 0, sizeof(relay_adv_pool)); } @@ -698,6 +772,8 @@ void bt_mesh_relay_adv_deinit(void) #if CONFIG_BLE_MESH_FRIEND static struct bt_mesh_adv *bt_mesh_frnd_adv_buf_get(int idx, enum bt_mesh_adv_type type) { + BT_DBG("FrndAdvBufGet, Idx %d", idx); + memset(&frnd_adv_pool[idx].adv, 0, sizeof(struct bt_mesh_adv)); init_adv_with_defaults(&frnd_adv_pool[idx].adv, type); frnd_adv_pool[idx].app_idx = BLE_MESH_KEY_UNUSED; @@ -706,7 +782,10 @@ static struct bt_mesh_adv *bt_mesh_frnd_adv_buf_get(int idx, enum bt_mesh_adv_ty void bt_mesh_frnd_adv_init(void) { + BT_DBG("FrndAdvInit"); + bt_mesh_adv_type_init(BLE_MESH_ADV_FRIEND, &adv_queue, &friend_buf_pool, bt_mesh_frnd_adv_buf_get); + #if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV bt_mesh_adv_inst_type_add(BLE_MESH_ADV_INST, BLE_MESH_ADV_FRIEND); #endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ @@ -714,10 +793,12 @@ void bt_mesh_frnd_adv_init(void) void bt_mesh_frnd_adv_deinit(void) { + BT_DBG("FrndAdvDeinit"); + bt_mesh_adv_type_deinit(BLE_MESH_ADV_FRIEND); #if CONFIG_BLE_MESH_FRIEND && CONFIG_BLE_MESH_SUPPORT_MULTI_ADV - bt_mesh_adv_inst_type_rm(BLE_MESH_ADV_INST, BLE_MESH_ADV_FRIEND); + bt_mesh_adv_inst_type_rem(BLE_MESH_ADV_INST, BLE_MESH_ADV_FRIEND); #endif /* CONFIG_BLE_MESH_FRIEND */ bt_mesh_unref_buf_from_pool(&friend_buf_pool); @@ -754,13 +835,15 @@ uint16_t bt_mesh_adv_buf_count_get(void) void bt_mesh_adv_task_init(void adv_thread(void *p)) { + BT_DBG("AdvTaskInit"); + if (!adv_thread) { - BT_ERR("Invalid param %s", __func__); + BT_ERR("%s, Invalid parameter", __func__); return; } #if (CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL && \ - (CONFIG_SPIRAM_CACHE_WORKAROUND || !CONFIG_IDF_TARGET_ESP32) && \ + (CONFIG_SPIRAM_CACHE_WORKAROUND || !CONFIG_IDF_TARGET_ESP32) && \ CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY) adv_task.task = heap_caps_calloc(1, sizeof(StaticTask_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); assert(adv_task.task); @@ -784,6 +867,8 @@ void bt_mesh_adv_task_init(void adv_thread(void *p)) void bt_mesh_adv_common_init(void) { + BT_DBG("AdvCommonInit"); + bt_mesh_r_mutex_create(&adv_buf_alloc_lock); bt_mesh_adv_queue_init(&adv_queue, bt_mesh_adv_buf_count_get(), bt_mesh_task_post); bt_mesh_adv_type_init(BLE_MESH_ADV_PROV, &adv_queue, &adv_buf_pool, adv_alloc); @@ -792,7 +877,7 @@ void bt_mesh_adv_common_init(void) bt_mesh_adv_type_init(BLE_MESH_ADV_URI, &adv_queue, &adv_buf_pool, adv_alloc); #if CONFIG_BLE_MESH_PROXY_SOLIC_PDU_TX bt_mesh_adv_type_init(BLE_MESH_ADV_PROXY_SOLIC, &adv_queue, &adv_buf_pool, adv_alloc); -#endif +#endif /* CONFIG_BLE_MESH_PROXY_SOLIC_PDU_TX */ #if CONFIG_BLE_MESH_USE_BLE_50 bt_mesh_adv_inst_init(BLE_MESH_ADV_INST, CONFIG_BLE_MESH_ADV_INST_ID); @@ -813,8 +898,7 @@ void bt_mesh_adv_common_init(void) #endif /* CONFIG_BLE_MESH_USE_BLE_50 */ #if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV - /** - * Due to the limitation of the sequence number in the network layer, + /* Due to the limitation of the sequence number in the network layer, * it is not possible to use multiple advertising instances to process * data from the same message queue when sending mesh packets. * @@ -845,6 +929,8 @@ void bt_mesh_adv_common_init(void) #if CONFIG_BLE_MESH_DEINIT void bt_mesh_adv_task_deinit(void) { + BT_DBG("AdvTaskDeinit"); + vTaskDelete(adv_task.handle); adv_task.handle = NULL; @@ -860,6 +946,8 @@ void bt_mesh_adv_task_deinit(void) void bt_mesh_adv_common_deinit(void) { + BT_DBG("AdvCommonDeinit"); + bt_mesh_adv_type_deinit(BLE_MESH_ADV_PROV); bt_mesh_adv_type_deinit(BLE_MESH_ADV_DATA); bt_mesh_adv_type_deinit(BLE_MESH_ADV_BEACON); @@ -885,12 +973,14 @@ void bt_mesh_adv_common_deinit(void) #endif /* CONFIG_BLE_MESH_EXT_ADV */ bt_mesh_adv_queue_deinit(&adv_queue); + #if CONFIG_BLE_MESH_USE_BLE_50 bt_mesh_adv_inst_deinit(BLE_MESH_ADV_INST); -#endif +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ bt_mesh_unref_buf_from_pool(&adv_buf_pool); memset(adv_pool, 0, sizeof(adv_pool)); + bt_mesh_r_mutex_free(&adv_buf_alloc_lock); } #endif /* CONFIG_BLE_MESH_DEINIT */ diff --git a/components/bt/esp_ble_mesh/core/adv_common.h b/components/bt/esp_ble_mesh/core/adv_common.h index d5172a676af..f77079a648e 100644 --- a/components/bt/esp_ble_mesh/core/adv_common.h +++ b/components/bt/esp_ble_mesh/core/adv_common.h @@ -31,9 +31,9 @@ extern "C" { #endif /* Convert from ms to 0.625ms units */ -#define ADV_SCAN_UNIT(_ms) ((_ms) * 8 / 5) +#define ADV_SCAN_UNIT(_ms) ((_ms) * 8 / 5) /* Convert from 0.625ms units to interval(ms) */ -#define ADV_SCAN_INT(val) ((val) * 5 / 8) +#define ADV_SCAN_INT(val) ((val) * 5 / 8) /* Maximum advertising data payload for a single data type */ #define BLE_MESH_ADV_DATA_SIZE 29 @@ -75,15 +75,13 @@ typedef struct { #endif #if CONFIG_BLE_MESH_FRIEND - #define FRIEND_ADV(buf) CONTAINER_OF(BLE_MESH_ADV(buf), bt_mesh_friend_adv_t, adv) typedef struct { struct bt_mesh_adv adv; uint16_t app_idx; } bt_mesh_friend_adv_t; - -#endif +#endif /* CONFIG_BLE_MESH_FRIEND */ enum { #if CONFIG_BLE_MESH_USE_BLE_50 @@ -103,12 +101,15 @@ enum { ADV_TASK_BLE_ADV_INST_EVT = BIT(CONFIG_BLE_MESH_BLE_ADV_INST_ID), #endif #endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ + #if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ CONFIG_BLE_MESH_GATT_PROXY_SERVER ADV_TASK_PROXY_ADV_UPD_EVT = BIT(30), #endif #endif /* CONFIG_BLE_MESH_USE_BLE_50 */ + ADV_TASK_PKT_SEND_EVT = BIT(31), + ADV_TASK_EVT_MAX, }; @@ -124,6 +125,7 @@ typedef struct bt_mesh_msg { struct bt_mesh_adv_inst { uint8_t id; + #if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV bool busy; struct net_buf *sending_buf; @@ -184,13 +186,13 @@ static const uint8_t adv_type[] = { #endif /* CONFIG_BLE_MESH_LONG_PACKET */ #endif /* CONFIG_BLE_MESH_EXT_ADV */ #if CONFIG_BLE_MESH_FRIEND - [BLE_MESH_ADV_FRIEND] = BLE_MESH_DATA_MESH_MESSAGE, + [BLE_MESH_ADV_FRIEND] = BLE_MESH_DATA_MESH_MESSAGE, #endif #if CONFIG_BLE_MESH_RELAY_ADV_BUF [BLE_MESH_ADV_RELAY_DATA] = BLE_MESH_DATA_MESH_MESSAGE, #endif - [BLE_MESH_ADV_BEACON] = BLE_MESH_DATA_MESH_BEACON, - [BLE_MESH_ADV_URI] = BLE_MESH_DATA_URI, + [BLE_MESH_ADV_BEACON] = BLE_MESH_DATA_MESH_BEACON, + [BLE_MESH_ADV_URI] = BLE_MESH_DATA_URI, }; typedef struct bt_mesh_adv *(*bt_mesh_pool_allocator_t)(int id, enum bt_mesh_adv_type type); @@ -256,6 +258,7 @@ static inline void bt_mesh_adv_send(struct net_buf *buf, uint8_t xmit, } void bt_mesh_unref_buf_from_pool(struct net_buf_pool *pool); + void bt_mesh_unref_buf(bt_mesh_msg_t *msg); int bt_mesh_adv_queue_init(struct bt_mesh_adv_queue *adv_queue, @@ -265,34 +268,38 @@ int bt_mesh_adv_queue_init(struct bt_mesh_adv_queue *adv_queue, int bt_mesh_adv_queue_deinit(struct bt_mesh_adv_queue *adv_queue); void bt_mesh_adv_type_init(enum bt_mesh_adv_type adv_type, - struct bt_mesh_adv_queue *adv_queue, - struct net_buf_pool *buf_pool, - bt_mesh_pool_allocator_t adv_alloc); + struct bt_mesh_adv_queue *adv_queue, + struct net_buf_pool *buf_pool, + bt_mesh_pool_allocator_t adv_alloc); void bt_mesh_adv_type_deinit(enum bt_mesh_adv_type adv_type); void bt_mesh_task_post(bt_mesh_msg_t *msg, uint32_t timeout, bool front); #if CONFIG_BLE_MESH_USE_BLE_50 -struct bt_mesh_adv_inst * bt_mesh_get_adv_insts_set(void); -bool bt_mesh_is_adv_inst_used(uint8_t adv_inst_id); +struct bt_mesh_adv_inst *bt_mesh_get_adv_insts_set(void); + +bool bt_mesh_is_adv_inst_used(uint8_t inst_id); + int bt_mesh_adv_inst_init(enum bt_mesh_adv_inst_type inst_type, uint8_t inst_id); + int bt_mesh_adv_inst_deinit(enum bt_mesh_adv_inst_type inst_type); #endif /* CONFIG_BLE_MESH_USE_BLE_50 */ #if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV void bt_mesh_adv_inst_type_add(enum bt_mesh_adv_inst_type inst_type, - enum bt_mesh_adv_type adv_type); + enum bt_mesh_adv_type adv_type); -void bt_mesh_adv_inst_type_rm(enum bt_mesh_adv_inst_type inst_type, - enum bt_mesh_adv_type adv_type); +void bt_mesh_adv_inst_type_rem(enum bt_mesh_adv_inst_type inst_type, + enum bt_mesh_adv_type adv_type); -void bt_mesh_adv_inst_supported_adv_type_clear(enum bt_mesh_adv_inst_type inst_type, - enum bt_mesh_adv_type adv_type); -#endif +void bt_mesh_adv_inst_type_clear(enum bt_mesh_adv_inst_type inst_type, + enum bt_mesh_adv_type adv_type); +#endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ #if CONFIG_BLE_MESH_RELAY_ADV_BUF void bt_mesh_relay_adv_init(void); + bool bt_mesh_ignore_relay_packet(uint32_t timestamp); static inline void bt_mesh_relay_adv_send(struct net_buf *buf, uint8_t xmit, @@ -312,25 +319,29 @@ void bt_mesh_relay_adv_deinit(void); #if CONFIG_BLE_MESH_FRIEND void bt_mesh_frnd_adv_init(void); + #if CONFIG_BLE_MESH_DEINIT void bt_mesh_frnd_adv_deinit(void); #endif /* CONFIG_BLE_MESH_DEINIT */ #endif /* CONFIG_BLE_MESH_FRIEND */ void bt_mesh_adv_task_init(void adv_thread(void *p)); + void bt_mesh_adv_common_init(void); #if CONFIG_BLE_MESH_DEINIT void bt_mesh_adv_task_deinit(void); + void bt_mesh_adv_common_deinit(void); #endif #if CONFIG_BLE_MESH_USE_BLE_50 int bt_mesh_adv_task_wakeup(uint32_t evt); + bool bt_mesh_adv_task_wait(uint32_t wait_bits, TickType_t timeout, uint32_t *notify); -#else +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ bool bt_mesh_adv_task_wait(uint32_t timeout); -#endif +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV static inline void bt_mesh_ble_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb, diff --git a/components/bt/esp_ble_mesh/core/beacon.c b/components/bt/esp_ble_mesh/core/beacon.c index 97ec6ebd823..32e31f10a97 100644 --- a/components/bt/esp_ble_mesh/core/beacon.c +++ b/components/bt/esp_ble_mesh/core/beacon.c @@ -27,19 +27,19 @@ #if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" -#endif +#endif /* CONFIG_BLE_MESH_V11_SUPPORT */ -#if defined(CONFIG_BLE_MESH_UNPROVISIONED_BEACON_INTERVAL) +#if CONFIG_BLE_MESH_UNPROVISIONED_BEACON_INTERVAL #define UNPROV_BEACON_INTERVAL K_SECONDS(CONFIG_BLE_MESH_UNPROVISIONED_BEACON_INTERVAL) -#else +#else /* CONFIG_BLE_MESH_UNPROVISIONED_BEACON_INTERVAL */ #define UNPROV_BEACON_INTERVAL K_SECONDS(5) -#endif +#endif /* CONFIG_BLE_MESH_UNPROVISIONED_BEACON_INTERVAL */ #if CONFIG_BLE_MESH_BQB_TEST #define SECURE_BEACON_INTERVAL K_SECONDS(3) -#else +#else /* CONFIG_BLE_MESH_BQB_TEST */ #define SECURE_BEACON_INTERVAL K_SECONDS(10) -#endif +#endif /* CONFIG_BLE_MESH_BQB_TEST */ /* 3 transmissions, 20ms interval */ #define UNPROV_XMIT BLE_MESH_TRANSMIT(2, 20) @@ -58,6 +58,8 @@ struct bt_mesh_subnet *cache_check(uint8_t data[21], bool private_beacon) uint8_t *cache = NULL; int i = 0; + BT_DBG("CacheCheck, PrivateBeacon %u", private_beacon); + subnet_size = bt_mesh_rx_netkey_size(); for (i = 0; i < subnet_size; i++) { @@ -69,11 +71,12 @@ struct bt_mesh_subnet *cache_check(uint8_t data[21], bool private_beacon) #if CONFIG_BLE_MESH_PRIVATE_BEACON cache = private_beacon ? sub->mpb_cache : sub->snb_cache; -#else +#else /* CONFIG_BLE_MESH_PRIVATE_BEACON */ cache = sub->snb_cache; -#endif +#endif /* CONFIG_BLE_MESH_PRIVATE_BEACON */ if (!memcmp(cache, data, 21)) { + BT_DBG("BeaconSubFound, NetIdx 0x%04x", sub->net_idx); return sub; } } @@ -83,11 +86,13 @@ struct bt_mesh_subnet *cache_check(uint8_t data[21], bool private_beacon) void cache_add(uint8_t data[21], struct bt_mesh_subnet *sub, bool private_beacon) { + BT_DBG("CacheAdd, NetIdx 0x%04x PrivateBeacon %u", sub->net_idx, private_beacon); + #if CONFIG_BLE_MESH_PRIVATE_BEACON if (private_beacon) { memcpy(sub->mpb_cache, data, 21); } else -#endif +#endif /* CONFIG_BLE_MESH_PRIVATE_BEACON */ { memcpy(sub->snb_cache, data, 21); } @@ -98,10 +103,10 @@ static void secure_beacon_complete(int err, void *user_data) struct bt_mesh_subnet *sub = NULL; uint16_t net_idx = BLE_MESH_KEY_UNUSED; - BT_DBG("err %d", err); - net_idx = (uint16_t)NET_IDX_GET(user_data); + BT_DBG("SecureBeaconComplete, NetIdx 0x%04x Err %d", net_idx, err); + /* For node, directly updating the "beacon_sent" timestamp is fine, * since the subnet is pre-allocated. * For Provisioner, before updating the "beacon_sent" timestamp, we @@ -112,6 +117,8 @@ static void secure_beacon_complete(int err, void *user_data) sub = bt_mesh_subnet_get(net_idx); if (sub) { sub->snb_sent = k_uptime_get_32(); + + BT_DBG("SnbSent %lu", sub->snb_sent); } } @@ -121,6 +128,8 @@ void bt_mesh_secure_beacon_create(struct bt_mesh_subnet *sub, uint8_t flags = bt_mesh_net_flags(sub); struct bt_mesh_subnet_keys *keys = NULL; + BT_DBG("SecureBeaconCreate"); + net_buf_simple_add_u8(buf, BEACON_TYPE_SECURE); if (sub->kr_flag) { @@ -139,10 +148,10 @@ void bt_mesh_secure_beacon_create(struct bt_mesh_subnet *sub, net_buf_simple_add_mem(buf, sub->auth, 8); - BT_DBG("SNB: net_idx 0x%03x iv_index 0x%08x flags 0x%02x", - sub->net_idx, bt_mesh.iv_index, flags); - BT_DBG("SNB: NetID %s Auth %s", bt_hex(keys->net_id, 8), - bt_hex(sub->auth, 8)); + BT_DBG("NetIdx 0x%04x IVIndex 0x%08x Flags 0x%02x", + sub->net_idx, bt_mesh.iv_index, flags); + BT_DBG("NetID %s Auth %s", bt_hex(keys->net_id, 8), + bt_hex(sub->auth, 8)); } static int secure_beacon_send(void) @@ -154,6 +163,8 @@ static int secure_beacon_send(void) size_t subnet_size = 0U; int i = 0; + BT_DBG("SecureBeaconSend"); + subnet_size = bt_mesh_rx_netkey_size(); for (i = 0; i < subnet_size; i++) { @@ -165,6 +176,8 @@ static int secure_beacon_send(void) continue; } + BT_DBG("Now %lu SnbSent %lu SnbLast %u", now, sub->snb_sent, sub->snb_last); + time_diff = now - sub->snb_sent; if (time_diff < K_SECONDS(600) && time_diff < BEACON_THRESHOLD(sub->snb_last)) { @@ -178,9 +191,10 @@ static int secure_beacon_send(void) */ #if CONFIG_BLE_MESH_GATT_PROXY_CLIENT if (bt_mesh_proxy_client_beacon_send(sub, false)) { + BT_DBG("ProxyClientBeaconSend"); continue; } -#endif +#endif /* CONFIG_BLE_MESH_GATT_PROXY_CLIENT */ buf = bt_mesh_adv_create(BLE_MESH_ADV_BEACON, K_NO_WAIT); if (!buf) { @@ -201,6 +215,7 @@ static int secure_beacon_send(void) * updating its "snb_sent" timestamp. */ bt_mesh_adv_send(buf, SNB_XMIT, &send_cb, NET_IDX_SET(sub->net_idx)); + net_buf_unref(buf); } @@ -214,6 +229,8 @@ static int unprovisioned_beacon_send(void) struct net_buf *buf = NULL; uint16_t oob_info = 0U; + BT_DBG("UnprovisionedBeaconSend"); + if (bt_mesh_prov_get() == NULL) { BT_ERR("No provisioning context provided"); return -EINVAL; @@ -252,6 +269,8 @@ static int unprovisioned_beacon_send(void) len = strlen(bt_mesh_prov_get()->uri); + BT_DBG("URI %u: %s", len, bt_mesh_prov_get()->uri); + if (net_buf_tailroom(buf) < len) { BT_WARN("Too long URI to fit advertising data"); } else { @@ -277,6 +296,8 @@ void update_beacon_observation(bool private_beacon) size_t subnet_size = 0U; int i = 0; + BT_DBG("UpdateBeaconObservation, PrivateBeacon %u", private_beacon); + /* Observation period is 20 seconds, whereas the beacon timer * runs every 10 seconds. We process what's happened during * the window only after the second half. @@ -287,13 +308,15 @@ void update_beacon_observation(bool private_beacon) if (private_beacon) { mpb_first_half = !mpb_first_half; if (mpb_first_half) { + BT_DBG("MpbFirstHalf"); return; } } else -#endif +#endif /* CONFIG_BLE_MESH_PRB_SRV */ { snb_first_half = !snb_first_half; if (snb_first_half) { + BT_DBG("SnbFirstHalf"); return; } } @@ -309,11 +332,15 @@ void update_beacon_observation(bool private_beacon) #if CONFIG_BLE_MESH_PRB_SRV if (private_beacon) { + BT_DBG("NetIdx 0x%04x MpbCur %u", sub->net_idx, sub->mpb_cur); + sub->mpb_last = sub->mpb_cur; sub->mpb_cur = 0U; } else -#endif +#endif /* CONFIG_BLE_MESH_PRB_SRV */ { + BT_DBG("NetIdx 0x%04x SnbCur %u", sub->net_idx, sub->snb_cur); + sub->snb_last = sub->snb_cur; sub->snb_cur = 0U; } @@ -330,9 +357,12 @@ static bool ready_to_send(void) static void secure_beacon_send_timeout(struct k_work *work) { + BT_DBG("SecureBeaconSendTimeout"); + /* Don't send anything if we have an active provisioning link */ if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_node() && IS_ENABLED(CONFIG_BLE_MESH_PROV) && bt_mesh_prov_active()) { + BT_DBG("ProvActive"); k_delayed_work_submit(&snb_timer, UNPROV_BEACON_INTERVAL); return; } @@ -345,11 +375,14 @@ static void secure_beacon_send_timeout(struct k_work *work) /* Only resubmit if beaconing is still enabled */ if (bt_mesh_secure_beacon_get() == BLE_MESH_SECURE_BEACON_ENABLED || bt_mesh_atomic_test_bit(bt_mesh.flags, BLE_MESH_IVU_INITIATOR)) { + BT_DBG("Resubmit, SecureBeacon %u", bt_mesh_secure_beacon_get()); + k_delayed_work_submit(&snb_timer, SECURE_BEACON_INTERVAL); } } else { if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_node()) { unprovisioned_beacon_send(); + k_delayed_work_submit(&snb_timer, UNPROV_BEACON_INTERVAL); } } @@ -365,6 +398,8 @@ static void secure_beacon_recv(struct net_buf_simple *buf) bool new_key = false; uint8_t flags = 0U; + BT_DBG("SecureBeaconRecv"); + if (buf->len != 21) { BT_ERR("Malformed secure beacon (len %u)", buf->len); return; @@ -384,7 +419,7 @@ static void secure_beacon_recv(struct net_buf_simple *buf) iv_index = net_buf_simple_pull_be32(buf); auth = buf->data; - BT_DBG("flags 0x%02x id %s iv_index 0x%08x", + BT_DBG("Flags 0x%02x NetID %s IVIndex 0x%08x", flags, bt_hex(net_id, 8), iv_index); sub = bt_mesh_subnet_find_with_snb(net_id, flags, iv_index, auth, &new_key); @@ -393,6 +428,9 @@ static void secure_beacon_recv(struct net_buf_simple *buf) return; } + BT_DBG("NetIdx 0x%04x KrPhase %u NewKey %u", + sub->net_idx, sub->kr_phase, new_key); + if (sub->kr_phase == BLE_MESH_KR_PHASE_2 && !new_key) { BT_WARN("Ignoring Phase 2 KR Update secured using old key"); return; @@ -417,8 +455,7 @@ static void secure_beacon_recv(struct net_buf_simple *buf) goto update_stats; } - BT_DBG("SNB: net_idx 0x%03x iv_index 0x%08x current iv_index 0x%08x", - sub->net_idx, iv_index, bt_mesh.iv_index); + BT_DBG("IVIndex 0x%08lx CurIVIndex 0x%08lx", iv_index, bt_mesh.iv_index); if (bt_mesh_atomic_test_bit(bt_mesh.flags, BLE_MESH_IVU_INITIATOR) && (bt_mesh_atomic_test_bit(bt_mesh.flags, BLE_MESH_IVU_IN_PROGRESS) == @@ -452,6 +489,7 @@ static void secure_beacon_recv(struct net_buf_simple *buf) update_stats: if (bt_mesh_secure_beacon_get() == BLE_MESH_SECURE_BEACON_ENABLED && sub->snb_cur < 0xff) { + BT_DBG("SnbCurInc %u", sub->snb_cur); sub->snb_cur++; } } @@ -460,7 +498,8 @@ void bt_mesh_beacon_recv(struct net_buf_simple *buf, int8_t rssi) { uint8_t type = 0U; - BT_DBG("%u bytes: %s", buf->len, bt_hex(buf->data, buf->len)); + BT_DBG("BeaconRecv"); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); if (buf->len < 1) { BT_ERR("Too short beacon"); @@ -470,7 +509,7 @@ void bt_mesh_beacon_recv(struct net_buf_simple *buf, int8_t rssi) type = net_buf_simple_pull_u8(buf); switch (type) { case BEACON_TYPE_UNPROVISIONED: - BT_DBG("Unprovisioned device beacon received"); + BT_DBG("UnprovDevBeaconRecv, Rssi %d", rssi); if (IS_ENABLED(CONFIG_BLE_MESH_PROVISIONER) && IS_ENABLED(CONFIG_BLE_MESH_PB_ADV) && @@ -480,11 +519,16 @@ void bt_mesh_beacon_recv(struct net_buf_simple *buf, int8_t rssi) #if CONFIG_BLE_MESH_RPR_SRV if (bt_mesh_is_provisioned()) { - const bt_mesh_addr_t *addr = bt_mesh_get_unprov_dev_addr(); + const bt_mesh_addr_t *addr = NULL; + + addr = bt_mesh_get_unprov_dev_addr(); + assert(addr); + bt_mesh_unprov_dev_fifo_enqueue(buf->data, addr->val, bt_mesh_get_adv_type()); + bt_mesh_rpr_srv_unprov_beacon_recv(buf, bt_mesh_get_adv_type(), addr, rssi); } -#endif +#endif /* CONFIG_BLE_MESH_RPR_SRV */ break; case BEACON_TYPE_SECURE: secure_beacon_recv(buf); @@ -493,7 +537,7 @@ void bt_mesh_beacon_recv(struct net_buf_simple *buf, int8_t rssi) case BEACON_TYPE_PRIVATE: bt_mesh_private_beacon_recv(buf); break; -#endif +#endif /* CONFIG_BLE_MESH_PRIVATE_BEACON */ default: BT_DBG("Unknown beacon type 0x%02x", type); break; @@ -514,7 +558,7 @@ void bt_mesh_beacon_init(void) BT_ERR("Failed to create a mpb_timer"); return; } -#endif +#endif /* CONFIG_BLE_MESH_PRB_SRV */ } #if CONFIG_BLE_MESH_DEINIT @@ -532,24 +576,28 @@ void bt_mesh_beacon_deinit(void) void bt_mesh_beacon_ivu_initiator(bool enable) { + BT_DBG("BeaconIVUInitiator, IVUInitiator %u", enable); + bt_mesh_atomic_set_bit_to(bt_mesh.flags, BLE_MESH_IVU_INITIATOR, enable); if (enable) { k_delayed_work_submit(&snb_timer, K_NO_WAIT); + #if CONFIG_BLE_MESH_PRB_SRV if (bt_mesh_private_beacon_state_get() == BLE_MESH_PRIVATE_BEACON_ENABLED) { bt_mesh_private_beacon_timer_submit(K_NO_WAIT); } -#endif +#endif /* CONFIG_BLE_MESH_PRB_SRV */ } else { if (bt_mesh_secure_beacon_get() == BLE_MESH_SECURE_BEACON_DISABLED) { k_delayed_work_cancel(&snb_timer); } + #if CONFIG_BLE_MESH_PRB_SRV if (bt_mesh_private_beacon_state_get() == BLE_MESH_PRIVATE_BEACON_DISABLED) { bt_mesh_private_beacon_timer_cancel(); } -#endif +#endif /* CONFIG_BLE_MESH_PRB_SRV */ } } @@ -558,8 +606,12 @@ void bt_mesh_secure_beacon_enable(void) size_t subnet_size = 0U; int i = 0; + BT_DBG("SecureBeaconEnable"); + if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_node() && !bt_mesh_is_provisioned()) { + BT_DBG("NodeNotProvisioned"); + k_delayed_work_submit(&snb_timer, K_NO_WAIT); return; } @@ -584,6 +636,9 @@ void bt_mesh_secure_beacon_enable(void) void bt_mesh_secure_beacon_disable(void) { + BT_DBG("SecureBeaconDisable, IVUInitiator %u", + bt_mesh_atomic_test_bit(bt_mesh.flags, BLE_MESH_IVU_INITIATOR)); + if (!bt_mesh_atomic_test_bit(bt_mesh.flags, BLE_MESH_IVU_INITIATOR)) { k_delayed_work_cancel(&snb_timer); } diff --git a/components/bt/esp_ble_mesh/core/ble_adv.c b/components/bt/esp_ble_mesh/core/ble_adv.c index e27109c0471..aaaa4b42906 100644 --- a/components/bt/esp_ble_mesh/core/ble_adv.c +++ b/components/bt/esp_ble_mesh/core/ble_adv.c @@ -30,10 +30,11 @@ static struct bt_mesh_adv ble_adv_pool[CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT]; static struct bt_mesh_ble_adv_tx ble_adv_tx[CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT]; -#define SEND_BLE_ADV_INFINITE 0xFFFF +#define SEND_BLE_ADV_INFINITE 0xFFFF static struct bt_mesh_adv *ble_adv_alloc(int id, enum bt_mesh_adv_type type) { + BT_DBG("BLEAdvAlloc, ID %d", id); memset(&ble_adv_pool[id], 0, sizeof(struct bt_mesh_adv)); ble_adv_pool[id].type = type; return &ble_adv_pool[id]; @@ -43,7 +44,7 @@ static struct bt_mesh_adv *ble_adv_alloc(int id, enum bt_mesh_adv_type type) /* A separate post function is required only when using a separate queue */ static void bt_mesh_ble_task_post(bt_mesh_msg_t *msg, uint32_t timeout, bool front) { - BT_DBG("%s", __func__); + BT_DBG("BLETaskPost, Front %u", front); if (p_ble_adv_queue->q.handle == NULL) { BT_ERR("Invalid adv queue"); @@ -66,7 +67,10 @@ static void bt_mesh_ble_task_post(bt_mesh_msg_t *msg, uint32_t timeout, bool fro static void ble_adv_tx_reset(struct bt_mesh_ble_adv_tx *tx, bool unref) { + BT_DBG("BLEAdvTxReset, Unref %u", unref); + if (tx->buf == NULL) { + BT_DBG("NullTxBuf"); return; } @@ -74,7 +78,13 @@ static void ble_adv_tx_reset(struct bt_mesh_ble_adv_tx *tx, bool unref) k_delayed_work_free(&tx->resend); } bt_mesh_atomic_set(tx->flags, 0); + memset(&tx->param, 0, sizeof(tx->param)); + + BT_DBG("Buf %p Ref %u Busy %u", + tx->buf, tx->buf->ref, + !!bt_mesh_atomic_get(&BLE_MESH_ADV_BUSY(tx->buf))); + bt_mesh_atomic_set(&BLE_MESH_ADV_BUSY(tx->buf), 0); if (unref) { net_buf_unref(tx->buf); @@ -86,7 +96,7 @@ static void ble_adv_send_start(uint16_t duration, int err, void *cb_data) { struct bt_mesh_ble_adv_tx *tx = cb_data; - BT_DBG("%s, duration %d, err %d", __func__, duration, err); + BT_DBG("BLEAdvSendStart, Duration %u Err %d", duration, err); /* If failed to send BLE adv packet, and param->count is not 0 * which means the timer has been initialized, here we need to @@ -101,13 +111,15 @@ static void ble_adv_send_end(int err, void *cb_data) { struct bt_mesh_ble_adv_tx *tx = cb_data; - BT_DBG("%s, err %d", __func__, err); + BT_DBG("BLEAdvSendEnd, Err %d", err); if (err) { ble_adv_tx_reset(tx, true); return; } + BT_DBG("Count %u Period %u", tx->param.count, tx->param.period); + if (tx->param.count) { if (tx->param.period) { k_delayed_work_submit(&tx->resend, tx->param.period); @@ -129,12 +141,18 @@ static void ble_adv_resend(struct k_work *work) struct bt_mesh_ble_adv_tx *tx = CONTAINER_OF(work, struct bt_mesh_ble_adv_tx, resend.work); bool front = false; + BT_DBG("BLEAdvResend"); + if (tx->buf == NULL) { /* The advertising has been cancelled */ + BT_INFO("%s, cancelled", __func__); return; } + BT_DBG("Priority %u Count %u Buf %p", tx->param.priority, tx->param.count, tx->buf); + front = (tx->param.priority == BLE_MESH_BLE_ADV_PRIO_HIGH) ? true : false; + bt_mesh_ble_adv_send(tx->buf, &ble_adv_send_cb, tx, front); if (tx->param.count == SEND_BLE_ADV_INFINITE) { @@ -154,6 +172,8 @@ int bt_mesh_start_ble_advertising(const struct bt_mesh_ble_adv_param *param, struct net_buf *buf = NULL; bool front = false; + BT_DBG("StartBLEAdv"); + if (param == NULL || index == NULL) { BT_ERR("%s, Invalid parameter", __func__); return -EINVAL; @@ -206,6 +226,12 @@ int bt_mesh_start_ble_advertising(const struct bt_mesh_ble_adv_param *param, return -ENOBUFS; } + BT_DBG("AdvType 0x%02x Interval 0x%04x AddrType 0x%02x/0x%02x", + param->adv_type, param->interval, param->own_addr_type, param->peer_addr_type); + BT_DBG("DataLen %u/%u Priority %u Count %u Duration %u", + (data ? data->adv_data_len : 0), (data ? data->scan_rsp_data_len : 0), + param->priority, param->count, param->duration); + /* Set advertising data and scan response data */ memset(buf->data, 0, buf->size); if (data) { @@ -226,6 +252,7 @@ int bt_mesh_start_ble_advertising(const struct bt_mesh_ble_adv_param *param, front = (tx->param.priority == BLE_MESH_BLE_ADV_PRIO_HIGH) ? true : false; bt_mesh_ble_adv_send(buf, &ble_adv_send_cb, tx, front); + if (param->count) { if (k_delayed_work_init(&tx->resend, ble_adv_resend)) { /* If failed to create a timer, the BLE adv packet will be @@ -233,10 +260,12 @@ int bt_mesh_start_ble_advertising(const struct bt_mesh_ble_adv_param *param, * BLE adv packet can be sent, return 0 here. */ BT_WARN("Send BLE adv packet only once"); + tx->param.count = 0; net_buf_unref(buf); return 0; } + bt_mesh_atomic_set_bit(tx->flags, TIMER_INIT); } else { /* Send the BLE advertising packet only once */ @@ -251,6 +280,8 @@ int bt_mesh_stop_ble_advertising(uint8_t index) struct bt_mesh_ble_adv_tx *tx = NULL; bool unref = true; + BT_DBG("StopBLEAdv, Index %u", index); + if (index >= ARRAY_SIZE(ble_adv_tx)) { BT_ERR("Invalid adv index %d", index); return -EINVAL; @@ -263,6 +294,10 @@ int bt_mesh_stop_ble_advertising(uint8_t index) return 0; } + BT_DBG("Busy %u Ref %u", + !!bt_mesh_atomic_get(&BLE_MESH_ADV_BUSY(tx->buf)), + tx->buf->ref); + /* busy 1, ref 1; busy 1, ref 2; * busy 0, ref 0; busy 0, ref 1; */ @@ -288,16 +323,17 @@ struct bt_mesh_adv_queue *bt_mesh_ble_adv_queue_get(void) void bt_mesh_ble_adv_init(void) { + BT_DBG("BLEAdvInit"); p_ble_adv_queue = bt_mesh_ble_adv_queue_get(); bt_mesh_adv_type_init(BLE_MESH_ADV_BLE, p_ble_adv_queue, &ble_adv_buf_pool, ble_adv_alloc); #if CONFIG_BLE_MESH_USE_BLE_50 #if CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE bt_mesh_adv_inst_init(BLE_MESH_BLE_ADV_INST, CONFIG_BLE_MESH_BLE_ADV_INST_ID); bt_mesh_adv_inst_type_add(BLE_MESH_BLE_ADV_INST, BLE_MESH_ADV_BLE); -#else +#else /* CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE */ #if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV bt_mesh_adv_inst_type_add(BLE_MESH_ADV_INST, BLE_MESH_ADV_BLE); -#endif +#endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ #endif /* CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE */ #endif /* CONFIG_BLE_MESH_USE_BLE_50 */ } @@ -305,9 +341,12 @@ void bt_mesh_ble_adv_init(void) #if CONFIG_BLE_MESH_DEINIT void bt_mesh_ble_adv_deinit(void) { + BT_DBG("BLEAdvDeinit"); + for (int i = 0; i < ARRAY_SIZE(ble_adv_tx); i++) { ble_adv_tx_reset(&ble_adv_tx[i], false); } + bt_mesh_unref_buf_from_pool(&ble_adv_buf_pool); memset(ble_adv_pool, 0, sizeof(ble_adv_pool)); @@ -317,13 +356,14 @@ void bt_mesh_ble_adv_deinit(void) bt_mesh_adv_queue_deinit(p_ble_adv_queue); #endif bt_mesh_adv_type_deinit(BLE_MESH_ADV_BLE); + #if CONFIG_BLE_MESH_USE_BLE_50 #if CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE bt_mesh_adv_inst_deinit(BLE_MESH_BLE_ADV_INST); - bt_mesh_adv_inst_type_rm(BLE_MESH_BLE_ADV_INST, BLE_MESH_ADV_BLE); + bt_mesh_adv_inst_type_rem(BLE_MESH_BLE_ADV_INST, BLE_MESH_ADV_BLE); #else #if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV - bt_mesh_adv_inst_type_rm(BLE_MESH_ADV_INST, BLE_MESH_ADV_BLE); + bt_mesh_adv_inst_type_rem(BLE_MESH_ADV_INST, BLE_MESH_ADV_BLE); #endif #endif /* CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE */ #endif /* CONFIG_BLE_MESH_USE_BLE_50 */ diff --git a/components/bt/esp_ble_mesh/core/bluedroid_host/adapter.c b/components/bt/esp_ble_mesh/core/bluedroid_host/adapter.c index 0520ca7a114..e31d4186e70 100644 --- a/components/bt/esp_ble_mesh/core/bluedroid_host/adapter.c +++ b/components/bt/esp_ble_mesh/core/bluedroid_host/adapter.c @@ -1615,7 +1615,7 @@ int bt_mesh_gatts_service_register(struct bt_mesh_gatt_service *svc) svc->attrs[i].handle = char_handle - 1; svc->attrs[i + 1].handle = char_handle; BT_DBG("Add characteristic, uuid 0x%04x, handle %d, perm %d, properties %d", - BLE_MESH_UUID_16(gatts_chrc->uuid)->val, char_handle, svc->attrs[i + 1].perm, gatts_chrc->properties); + BLE_MESH_UUID_16(gatts_chrc->uuid)->val, char_handle, svc->attrs[i + 1].perm, gatts_chrc->properties); break; } case BLE_MESH_UUID_GATT_CEP_VAL: @@ -1803,7 +1803,7 @@ uint16_t bt_mesh_gattc_get_service_uuid(struct bt_mesh_conn *conn) int bt_mesh_gattc_conn_create(const bt_mesh_addr_t *addr, uint16_t service_uuid) { - tBTA_BLE_CONN_PARAMS conn_1m_param = {0}; + tBTA_BLE_CONN_PARAMS conn_1m_param = {0}; uint8_t zero[6] = {0}; int i; @@ -1872,9 +1872,10 @@ int bt_mesh_gattc_conn_create(const bt_mesh_addr_t *addr, uint16_t service_uuid) conn_1m_param.max_ce_len = 0; BTA_GATTC_Enh_Open(bt_mesh_gattc_if, bt_mesh_gattc_info[i].addr.val, - bt_mesh_gattc_info[i].addr.type, true, BTA_GATT_TRANSPORT_LE, TRUE, BLE_ADDR_UNKNOWN_TYPE, - BTA_BLE_PHY_1M_MASK, &conn_1m_param, NULL, NULL); -#else + bt_mesh_gattc_info[i].addr.type, true, + BTA_GATT_TRANSPORT_LE, TRUE, BLE_ADDR_UNKNOWN_TYPE, + BTA_BLE_PHY_1M_MASK, &conn_1m_param, NULL, NULL); +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ /* Min_interval: 15ms * Max_interval: 15ms * Slave_latency: 0x0 @@ -1886,9 +1887,10 @@ int bt_mesh_gattc_conn_create(const bt_mesh_addr_t *addr, uint16_t service_uuid) conn_1m_param.supervision_timeout = 0x64; BTA_GATTC_Enh_Open(bt_mesh_gattc_if, bt_mesh_gattc_info[i].addr.val, - bt_mesh_gattc_info[i].addr.type, true, BTA_GATT_TRANSPORT_LE, FALSE, BLE_ADDR_UNKNOWN_TYPE, - BTA_BLE_PHY_1M_MASK, &conn_1m_param, NULL, NULL); -#endif + bt_mesh_gattc_info[i].addr.type, true, + BTA_GATT_TRANSPORT_LE, FALSE, BLE_ADDR_UNKNOWN_TYPE, + BTA_BLE_PHY_1M_MASK, &conn_1m_param, NULL, NULL); +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ return 0; } diff --git a/components/bt/esp_ble_mesh/core/cfg_cli.c b/components/bt/esp_ble_mesh/core/cfg_cli.c index 3aedd3644b8..e04588fab71 100644 --- a/components/bt/esp_ble_mesh/core/cfg_cli.c +++ b/components/bt/esp_ble_mesh/core/cfg_cli.c @@ -110,6 +110,8 @@ static void cfg_client_recv_status(struct bt_mesh_model *model, struct net_buf_simple buf = {0}; uint8_t evt_type = 0xFF; + BT_DBG("CfgClientRecvStatus"); + if (!model || !ctx) { BT_ERR("%s, Invalid parameter", __func__); return; @@ -125,6 +127,8 @@ static void cfg_client_recv_status(struct bt_mesh_model *model, if (!node) { BT_DBG("Unexpected Config Status 0x%04x", ctx->recv_op); } else { + BT_DBG("OpCode 0x%08lx RecvOp 0x%08lx", node->opcode, ctx->recv_op); + switch (node->opcode) { case OP_BEACON_GET: case OP_COMP_DATA_GET: @@ -230,9 +234,10 @@ static void comp_data_status(struct bt_mesh_model *model, { struct bt_mesh_cfg_comp_data_status status = {0}; - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, - bt_hex(buf->data, buf->len)); + BT_DBG("CompDataStatus"); + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", + ctx->net_idx, ctx->app_idx, ctx->addr); + BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); status.page = net_buf_simple_pull_u8(buf); status.comp_data = bt_mesh_alloc_buf(buf->len); @@ -252,9 +257,10 @@ static void state_status_u8(struct bt_mesh_model *model, { uint8_t status = 0U; - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, - bt_hex(buf->data, buf->len)); + BT_DBG("StateStatusU8"); + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", + ctx->net_idx, ctx->app_idx, ctx->addr); + BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); status = net_buf_simple_pull_u8(buf); @@ -265,6 +271,8 @@ static void beacon_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { + BT_DBG("BeaconStatus"); + state_status_u8(model, ctx, buf); } @@ -272,6 +280,8 @@ static void ttl_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { + BT_DBG("TTLStatus"); + state_status_u8(model, ctx, buf); } @@ -279,6 +289,8 @@ static void friend_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { + BT_DBG("FrndStatus"); + state_status_u8(model, ctx, buf); } @@ -286,6 +298,8 @@ static void gatt_proxy_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { + BT_DBG("GattProxyStatus"); + state_status_u8(model, ctx, buf); } @@ -295,9 +309,10 @@ static void relay_status(struct bt_mesh_model *model, { struct bt_mesh_cfg_relay_status status = {0}; - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, - bt_hex(buf->data, buf->len)); + BT_DBG("RelayStatus"); + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", + ctx->net_idx, ctx->app_idx, ctx->addr); + BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); status.relay = net_buf_simple_pull_u8(buf); status.retransmit = net_buf_simple_pull_u8(buf); @@ -311,9 +326,10 @@ static void net_key_status(struct bt_mesh_model *model, { struct bt_mesh_cfg_netkey_status status = {0}; - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, - bt_hex(buf->data, buf->len)); + BT_DBG("NetKeyStatus"); + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", + ctx->net_idx, ctx->app_idx, ctx->addr); + BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); status.status = net_buf_simple_pull_u8(buf); status.net_idx = net_buf_simple_pull_le16(buf) & 0xfff; @@ -327,9 +343,10 @@ static void app_key_status(struct bt_mesh_model *model, { struct bt_mesh_cfg_appkey_status status = {0}; - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, - bt_hex(buf->data, buf->len)); + BT_DBG("AppKeyStatus"); + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", + ctx->net_idx, ctx->app_idx, ctx->addr); + BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); status.status = net_buf_simple_pull_u8(buf); key_idx_unpack(buf, &status.net_idx, &status.app_idx); @@ -343,9 +360,10 @@ static void mod_app_status(struct bt_mesh_model *model, { struct bt_mesh_cfg_mod_app_status status = {0}; - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, - bt_hex(buf->data, buf->len)); + BT_DBG("ModAppStatus"); + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", + ctx->net_idx, ctx->app_idx, ctx->addr); + BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); status.status = net_buf_simple_pull_u8(buf); status.elem_addr = net_buf_simple_pull_le16(buf); @@ -366,9 +384,10 @@ static void mod_pub_status(struct bt_mesh_model *model, { struct bt_mesh_cfg_mod_pub_status status = {0}; - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, - bt_hex(buf->data, buf->len)); + BT_DBG("ModPubStatus"); + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", + ctx->net_idx, ctx->app_idx, ctx->addr); + BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); status.status = net_buf_simple_pull_u8(buf); status.elem_addr = net_buf_simple_pull_le16(buf); @@ -395,9 +414,10 @@ static void mod_sub_status(struct bt_mesh_model *model, { struct bt_mesh_cfg_mod_sub_status status = {0}; - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, - bt_hex(buf->data, buf->len)); + BT_DBG("ModSubStatus"); + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", + ctx->net_idx, ctx->app_idx, ctx->addr); + BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); status.status = net_buf_simple_pull_u8(buf); status.elem_addr = net_buf_simple_pull_le16(buf); @@ -418,9 +438,10 @@ static void hb_sub_status(struct bt_mesh_model *model, { struct bt_mesh_cfg_hb_sub_status status = {0}; - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, - bt_hex(buf->data, buf->len)); + BT_DBG("HbSubStatus"); + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", + ctx->net_idx, ctx->app_idx, ctx->addr); + BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); status.status = net_buf_simple_pull_u8(buf); status.src = net_buf_simple_pull_le16(buf); @@ -439,9 +460,10 @@ static void hb_pub_status(struct bt_mesh_model *model, { struct bt_mesh_cfg_hb_pub_status status = {0}; - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, - bt_hex(buf->data, buf->len)); + BT_DBG("HbPubStatus"); + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", + ctx->net_idx, ctx->app_idx, ctx->addr); + BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); status.status = net_buf_simple_pull_u8(buf); status.dst = net_buf_simple_pull_le16(buf); @@ -458,9 +480,10 @@ static void node_reset_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, - bt_hex(buf->data, buf->len)); + BT_DBG("NodeResetStatus"); + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", + ctx->net_idx, ctx->app_idx, ctx->addr); + BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); cfg_client_recv_status(model, ctx, NULL, 0); } @@ -471,9 +494,10 @@ static void mod_sub_list(struct bt_mesh_model *model, { struct bt_mesh_cfg_mod_sub_list list = {0}; - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, - bt_hex(buf->data, buf->len)); + BT_DBG("ModSubList"); + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", + ctx->net_idx, ctx->app_idx, ctx->addr); + BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); list.status = net_buf_simple_pull_u8(buf); list.elem_addr = net_buf_simple_pull_le16(buf); @@ -500,9 +524,10 @@ static void net_key_list(struct bt_mesh_model *model, { struct bt_mesh_cfg_net_key_list list = {0}; - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, - bt_hex(buf->data, buf->len)); + BT_DBG("NetKeyList"); + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", + ctx->net_idx, ctx->app_idx, ctx->addr); + BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); list.net_idx = bt_mesh_alloc_buf(buf->len); if (!list.net_idx) { @@ -520,9 +545,10 @@ static void app_key_list(struct bt_mesh_model *model, { struct bt_mesh_cfg_app_key_list list = {0}; - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, - bt_hex(buf->data, buf->len)); + BT_DBG("AppKeyList"); + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", + ctx->net_idx, ctx->app_idx, ctx->addr); + BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); list.status = net_buf_simple_pull_u8(buf); list.net_idx = net_buf_simple_pull_le16(buf); @@ -542,9 +568,10 @@ static void node_id_status(struct bt_mesh_model *model, { struct bt_mesh_cfg_node_id_status status = {0}; - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, - bt_hex(buf->data, buf->len)); + BT_DBG("NodeIDStatus"); + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", + ctx->net_idx, ctx->app_idx, ctx->addr); + BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); status.status = net_buf_simple_pull_u8(buf); status.net_idx = net_buf_simple_pull_le16(buf); @@ -559,9 +586,10 @@ static void mod_app_list(struct bt_mesh_model *model, { struct bt_mesh_cfg_mod_app_list list = {0}; - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, - bt_hex(buf->data, buf->len)); + BT_DBG("ModAppList"); + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", + ctx->net_idx, ctx->app_idx, ctx->addr); + BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); list.status = net_buf_simple_pull_u8(buf); list.elem_addr = net_buf_simple_pull_le16(buf); @@ -588,9 +616,10 @@ static void kr_phase_status(struct bt_mesh_model *model, { struct bt_mesh_cfg_key_refresh_status status = {0}; - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, - bt_hex(buf->data, buf->len)); + BT_DBG("KrPhaseStatus"); + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", + ctx->net_idx, ctx->app_idx, ctx->addr); + BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); status.status = net_buf_simple_pull_u8(buf); status.net_idx = net_buf_simple_pull_le16(buf); @@ -605,9 +634,10 @@ static void lpn_pollto_status(struct bt_mesh_model *model, { struct bt_mesh_cfg_lpn_pollto_status status = {0}; - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, - bt_hex(buf->data, buf->len)); + BT_DBG("LPNPollToStatus"); + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", + ctx->net_idx, ctx->app_idx, ctx->addr); + BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); status.lpn_addr = net_buf_simple_pull_le16(buf); status.timeout = net_buf_simple_pull_u8(buf); @@ -621,6 +651,8 @@ static void net_trans_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { + BT_DBG("NetTransStatus"); + state_status_u8(model, ctx, buf); } @@ -656,6 +688,9 @@ static int send_msg_with_none(bt_mesh_client_common_param_t *param, uint32_t op) { BLE_MESH_MODEL_BUF_DEFINE(msg, op, 0); + BT_DBG("SendMsgWithNone"); + BT_DBG("Dst 0x%04x Op 0x%08lx", param->ctx.addr, op); + bt_mesh_model_msg_init(&msg, op); return bt_mesh_client_send_msg(param, &msg, true, timeout_handler); @@ -665,6 +700,9 @@ static int send_msg_with_u8(bt_mesh_client_common_param_t *param, uint32_t op, u { BLE_MESH_MODEL_BUF_DEFINE(msg, op, 1); + BT_DBG("SendMsgWithU8"); + BT_DBG("Dst 0x%04x Op 0x%08lx Val 0x%02x", param->ctx.addr, op, val); + bt_mesh_model_msg_init(&msg, op); net_buf_simple_add_u8(&msg, val); @@ -675,6 +713,9 @@ static int send_msg_with_le16(bt_mesh_client_common_param_t *param, uint32_t op, { BLE_MESH_MODEL_BUF_DEFINE(msg, op, 2); + BT_DBG("SendMsgWithLE16"); + BT_DBG("Dst 0x%04x Op 0x%08lx Val 0x%04x", param->ctx.addr, op, val); + bt_mesh_model_msg_init(&msg, op); net_buf_simple_add_le16(&msg, val); @@ -683,55 +724,76 @@ static int send_msg_with_le16(bt_mesh_client_common_param_t *param, uint32_t op, int bt_mesh_cfg_comp_data_get(bt_mesh_client_common_param_t *param, uint8_t page) { + BT_DBG("CompDataGet, Page %u", page); + return send_msg_with_u8(param, OP_COMP_DATA_GET, page); } int bt_mesh_cfg_beacon_get(bt_mesh_client_common_param_t *param) { + BT_DBG("BeaconGet"); + return send_msg_with_none(param, OP_BEACON_GET); } int bt_mesh_cfg_beacon_set(bt_mesh_client_common_param_t *param, uint8_t val) { + BT_DBG("BeaconSet, Val 0x%02x", val); + if (val > 0x01) { BT_ERR("Invalid beacon state 0x%02x", val); return -EINVAL; } + return send_msg_with_u8(param, OP_BEACON_SET, val); } int bt_mesh_cfg_ttl_get(bt_mesh_client_common_param_t *param) { + BT_DBG("TTLGet"); + return send_msg_with_none(param, OP_DEFAULT_TTL_GET); } int bt_mesh_cfg_ttl_set(bt_mesh_client_common_param_t *param, uint8_t val) { + BT_DBG("TTLSet, Val 0x%02x", val); + return send_msg_with_u8(param, OP_DEFAULT_TTL_SET, val); } int bt_mesh_cfg_friend_get(bt_mesh_client_common_param_t *param) { + BT_DBG("FrndGet"); + return send_msg_with_none(param, OP_FRIEND_GET); } int bt_mesh_cfg_friend_set(bt_mesh_client_common_param_t *param, uint8_t val) { + BT_DBG("FrndSet, Val 0x%02x", val); + return send_msg_with_u8(param, OP_FRIEND_SET, val); } int bt_mesh_cfg_gatt_proxy_get(bt_mesh_client_common_param_t *param) { + BT_DBG("GattProxyGet"); + return send_msg_with_none(param, OP_GATT_PROXY_GET); } int bt_mesh_cfg_gatt_proxy_set(bt_mesh_client_common_param_t *param, uint8_t val) { + BT_DBG("GattProxySet, Val 0x%02x", val); + return send_msg_with_u8(param, OP_GATT_PROXY_SET, val); } int bt_mesh_cfg_relay_get(bt_mesh_client_common_param_t *param) { + BT_DBG("RelayGet"); + return send_msg_with_none(param, OP_RELAY_GET); } @@ -740,6 +802,8 @@ int bt_mesh_cfg_relay_set(bt_mesh_client_common_param_t *param, { BLE_MESH_MODEL_BUF_DEFINE(msg, OP_RELAY_SET, 2); + BT_DBG("RelaySet, Relay 0x%02x Retransmit 0x%02x", relay, retransmit); + bt_mesh_model_msg_init(&msg, OP_RELAY_SET); net_buf_simple_add_u8(&msg, relay); net_buf_simple_add_u8(&msg, retransmit); @@ -752,11 +816,15 @@ int bt_mesh_cfg_net_key_add(bt_mesh_client_common_param_t *param, { BLE_MESH_MODEL_BUF_DEFINE(msg, OP_NET_KEY_ADD, 18); + BT_DBG("NetKeyAdd"); + if (!net_key) { BT_ERR("Invalid NetKey"); return -EINVAL; } + BT_DBG("NetIdx 0x%04x NetKey %s", net_idx, bt_hex(net_key, 16)); + bt_mesh_model_msg_init(&msg, OP_NET_KEY_ADD); net_buf_simple_add_le16(&msg, net_idx); net_buf_simple_add_mem(&msg, net_key, 16); @@ -770,11 +838,16 @@ int bt_mesh_cfg_app_key_add(bt_mesh_client_common_param_t *param, { BLE_MESH_MODEL_BUF_DEFINE(msg, OP_APP_KEY_ADD, 19); + BT_DBG("AppKeyAdd"); + if (!app_key) { BT_ERR("Invalid AppKey"); return -EINVAL; } + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x AppKey %s", + net_idx, app_idx, bt_hex(app_key, 16)); + bt_mesh_model_msg_init(&msg, OP_APP_KEY_ADD); key_idx_pack(&msg, net_idx, app_idx); net_buf_simple_add_mem(&msg, app_key, 16); @@ -788,6 +861,10 @@ int bt_mesh_cfg_mod_app_bind(bt_mesh_client_common_param_t *param, { BLE_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_APP_BIND, 8); + BT_DBG("ModAppBind"); + BT_DBG("ElemAddr 0x%04x AppIdx 0x%04x ModID 0x%04x CID 0x%04x", + elem_addr, app_idx, mod_id, cid); + bt_mesh_model_msg_init(&msg, OP_MOD_APP_BIND); net_buf_simple_add_le16(&msg, elem_addr); net_buf_simple_add_le16(&msg, app_idx); @@ -805,6 +882,10 @@ static int mod_sub(bt_mesh_client_common_param_t *param, uint32_t op, { BLE_MESH_MODEL_BUF_DEFINE(msg, op, 8); + BT_DBG("ModSub"); + BT_DBG("ElemAddr 0x%04x SubAddr 0x%04x ModID 0x%04x CID 0x%04x", + elem_addr, sub_addr, mod_id, cid); + bt_mesh_model_msg_init(&msg, op); net_buf_simple_add_le16(&msg, elem_addr); net_buf_simple_add_le16(&msg, sub_addr); @@ -820,6 +901,8 @@ int bt_mesh_cfg_mod_sub_add(bt_mesh_client_common_param_t *param, uint16_t elem_addr, uint16_t sub_addr, uint16_t mod_id, uint16_t cid) { + BT_DBG("ModSubAdd"); + return mod_sub(param, OP_MOD_SUB_ADD, elem_addr, sub_addr, mod_id, cid); } @@ -827,6 +910,8 @@ int bt_mesh_cfg_mod_sub_del(bt_mesh_client_common_param_t *param, uint16_t elem_addr, uint16_t sub_addr, uint16_t mod_id, uint16_t cid) { + BT_DBG("ModSubDel"); + return mod_sub(param, OP_MOD_SUB_DEL, elem_addr, sub_addr, mod_id, cid); } @@ -834,6 +919,8 @@ int bt_mesh_cfg_mod_sub_overwrite(bt_mesh_client_common_param_t *param, uint16_t elem_addr, uint16_t sub_addr, uint16_t mod_id, uint16_t cid) { + BT_DBG("ModSubOverwrite"); + return mod_sub(param, OP_MOD_SUB_OVERWRITE, elem_addr, sub_addr, mod_id, cid); } @@ -843,13 +930,15 @@ static int mod_sub_va(bt_mesh_client_common_param_t *param, uint32_t op, { BLE_MESH_MODEL_BUF_DEFINE(msg, op, 22); + BT_DBG("ModSubVa"); + if (!label) { BT_ERR("Invalid label uuid"); return -EINVAL; } - BT_DBG("elem_addr 0x%04x label %s", elem_addr, bt_hex(label, 16)); - BT_DBG("mod_id 0x%04x cid 0x%04x", mod_id, cid); + BT_DBG("ElemAddr 0x%04x ModID 0x%04x CID 0x%04x", elem_addr, mod_id, cid); + BT_DBG("Label %s", bt_hex(label, 16)); bt_mesh_model_msg_init(&msg, op); net_buf_simple_add_le16(&msg, elem_addr); @@ -866,6 +955,8 @@ int bt_mesh_cfg_mod_sub_va_add(bt_mesh_client_common_param_t *param, uint16_t elem_addr, const uint8_t label[16], uint16_t mod_id, uint16_t cid) { + BT_DBG("ModSubVaAdd"); + return mod_sub_va(param, OP_MOD_SUB_VA_ADD, elem_addr, label, mod_id, cid); } @@ -873,6 +964,8 @@ int bt_mesh_cfg_mod_sub_va_del(bt_mesh_client_common_param_t *param, uint16_t elem_addr, const uint8_t label[16], uint16_t mod_id, uint16_t cid) { + BT_DBG("ModSubVaDel"); + return mod_sub_va(param, OP_MOD_SUB_VA_DEL, elem_addr, label, mod_id, cid); } @@ -880,6 +973,8 @@ int bt_mesh_cfg_mod_sub_va_overwrite(bt_mesh_client_common_param_t *param, uint16_t elem_addr, const uint8_t label[16], uint16_t mod_id, uint16_t cid) { + BT_DBG("ModSubVaOverwrite"); + return mod_sub_va(param, OP_MOD_SUB_VA_OVERWRITE, elem_addr, label, mod_id, cid); } @@ -888,6 +983,9 @@ int bt_mesh_cfg_mod_pub_get(bt_mesh_client_common_param_t *param, { BLE_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_PUB_GET, 6); + BT_DBG("ModPubGet"); + BT_DBG("ElemAddr 0x%04x ModID 0x%04x CID 0x%04x", elem_addr, mod_id, cid); + bt_mesh_model_msg_init(&msg, OP_MOD_PUB_GET); net_buf_simple_add_le16(&msg, elem_addr); if (cid != BLE_MESH_CID_NVAL) { @@ -904,11 +1002,17 @@ int bt_mesh_cfg_mod_pub_set(bt_mesh_client_common_param_t *param, { BLE_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_PUB_SET, 13); + BT_DBG("ModPubSet"); + BT_DBG("ElemAddr 0x%04x ModID 0x%04x CID 0x%04x", elem_addr, mod_id, cid); + if (!pub) { BT_ERR("Invalid model pub set"); return -EINVAL; } + BT_DBG("Addr 0x%04x AppIdx 0x%04x TTL %u Period 0x%02x Transmit 0x%02x", + pub->addr, pub->app_idx, pub->ttl, pub->period, pub->transmit); + bt_mesh_model_msg_init(&msg, OP_MOD_PUB_SET); net_buf_simple_add_le16(&msg, elem_addr); net_buf_simple_add_le16(&msg, pub->addr); @@ -929,11 +1033,15 @@ int bt_mesh_cfg_hb_sub_set(bt_mesh_client_common_param_t *param, { BLE_MESH_MODEL_BUF_DEFINE(msg, OP_HEARTBEAT_SUB_SET, 5); + BT_DBG("HbSubSet"); + if (!sub) { BT_ERR("Invalid heartbeat sub set"); return -EINVAL; } + BT_DBG("Src 0x%04x Dst 0x%04x Period 0x%02x", sub->src, sub->dst, sub->period); + bt_mesh_model_msg_init(&msg, OP_HEARTBEAT_SUB_SET); net_buf_simple_add_le16(&msg, sub->src); net_buf_simple_add_le16(&msg, sub->dst); @@ -944,6 +1052,8 @@ int bt_mesh_cfg_hb_sub_set(bt_mesh_client_common_param_t *param, int bt_mesh_cfg_hb_sub_get(bt_mesh_client_common_param_t *param) { + BT_DBG("HbSubGet"); + return send_msg_with_none(param, OP_HEARTBEAT_SUB_GET); } @@ -952,11 +1062,16 @@ int bt_mesh_cfg_hb_pub_set(bt_mesh_client_common_param_t *param, { BLE_MESH_MODEL_BUF_DEFINE(msg, OP_HEARTBEAT_PUB_SET, 9); + BT_DBG("HbPubSet"); + if (!pub) { BT_ERR("Invalid heartbeat pub set"); return -EINVAL; } + BT_DBG("Dst 0x%04x Count 0x%02x Period 0x%02x TTL %u Feat 0x%04x NetIdx 0x%04x", + pub->dst, pub->count, pub->period, pub->ttl, pub->feat, pub->net_idx); + bt_mesh_model_msg_init(&msg, OP_HEARTBEAT_PUB_SET); net_buf_simple_add_le16(&msg, pub->dst); net_buf_simple_add_u8(&msg, pub->count); @@ -970,11 +1085,15 @@ int bt_mesh_cfg_hb_pub_set(bt_mesh_client_common_param_t *param, int bt_mesh_cfg_hb_pub_get(bt_mesh_client_common_param_t *param) { + BT_DBG("HbPubGet"); + return send_msg_with_none(param, OP_HEARTBEAT_PUB_GET); } int bt_mesh_cfg_node_reset(bt_mesh_client_common_param_t *param) { + BT_DBG("NodeReset"); + return send_msg_with_none(param, OP_NODE_RESET); } @@ -985,11 +1104,18 @@ int bt_mesh_cfg_mod_pub_va_set(bt_mesh_client_common_param_t *param, { BLE_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_PUB_VA_SET, 27); + BT_DBG("ModPubVaSet"); + BT_DBG("ElemAddr 0x%04x ModID 0x%04x CID 0x%04x", elem_addr, mod_id, cid); + if (!label || !pub) { BT_ERR("%s, Invalid parameter", __func__); return -EINVAL; } + BT_DBG("Label %s", bt_hex(label, 16)); + BT_DBG("AppIdx 0x%04x TTL %u Period 0x%02x Transmit 0x%02x", + pub->app_idx, pub->ttl, pub->period, pub->transmit); + bt_mesh_model_msg_init(&msg, OP_MOD_PUB_VA_SET); net_buf_simple_add_le16(&msg, elem_addr); net_buf_simple_add_mem(&msg, label, 16); @@ -1010,6 +1136,9 @@ int bt_mesh_cfg_mod_sub_del_all(bt_mesh_client_common_param_t *param, { BLE_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_SUB_DEL_ALL, 6); + BT_DBG("ModSubDelAll"); + BT_DBG("ElemAddr 0x%04x ModID 0x%04x CID 0x%04x", elem_addr, mod_id, cid); + bt_mesh_model_msg_init(&msg, OP_MOD_SUB_DEL_ALL); net_buf_simple_add_le16(&msg, elem_addr); if (cid != BLE_MESH_CID_NVAL) { @@ -1038,12 +1167,18 @@ static int mod_sub_get(bt_mesh_client_common_param_t *param, uint32_t op, int bt_mesh_cfg_mod_sub_get(bt_mesh_client_common_param_t *param, uint16_t elem_addr, uint16_t mod_id) { + BT_DBG("ModSubGet"); + BT_DBG("ElemAddr 0x%04x ModID 0x%04x", elem_addr, mod_id); + return mod_sub_get(param, OP_MOD_SUB_GET, elem_addr, mod_id, BLE_MESH_CID_NVAL); } int bt_mesh_cfg_mod_sub_get_vnd(bt_mesh_client_common_param_t *param, uint16_t elem_addr, uint16_t mod_id, uint16_t cid) { + BT_DBG("ModSubGetVnd"); + BT_DBG("ElemAddr 0x%04x ModID 0x%04x CID 0x%04x", elem_addr, mod_id, cid); + if (cid == BLE_MESH_CID_NVAL) { BT_ERR("Invalid company id"); return -EINVAL; @@ -1056,11 +1191,15 @@ int bt_mesh_cfg_net_key_update(bt_mesh_client_common_param_t *param, { BLE_MESH_MODEL_BUF_DEFINE(msg, OP_NET_KEY_UPDATE, 18); + BT_DBG("NetKeyUpdate"); + if (!net_key) { BT_ERR("Invalid NetKey"); return -EINVAL; } + BT_DBG("NetIdx 0x%04x NetKey %s", net_idx, bt_hex(net_key, 16)); + bt_mesh_model_msg_init(&msg, OP_NET_KEY_UPDATE); net_buf_simple_add_le16(&msg, net_idx); net_buf_simple_add_mem(&msg, net_key, 16); @@ -1070,11 +1209,15 @@ int bt_mesh_cfg_net_key_update(bt_mesh_client_common_param_t *param, int bt_mesh_cfg_net_key_delete(bt_mesh_client_common_param_t *param, uint16_t net_idx) { + BT_DBG("NetKeyDelete, NetIdx 0x%04x", net_idx); + return send_msg_with_le16(param, OP_NET_KEY_DEL, net_idx); } int bt_mesh_cfg_net_key_get(bt_mesh_client_common_param_t *param) { + BT_DBG("NetKeyGet"); + return send_msg_with_none(param, OP_NET_KEY_GET); } @@ -1084,11 +1227,16 @@ int bt_mesh_cfg_app_key_update(bt_mesh_client_common_param_t *param, { BLE_MESH_MODEL_BUF_DEFINE(msg, OP_APP_KEY_UPDATE, 19); + BT_DBG("AppKeyUpdate"); + if (!app_key) { BT_ERR("Invalid AppKey"); return -EINVAL; } + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x AppKey %s", + net_idx, app_idx, bt_hex(app_key, 16)); + bt_mesh_model_msg_init(&msg, OP_APP_KEY_UPDATE); key_idx_pack(&msg, net_idx, app_idx); net_buf_simple_add_mem(&msg, app_key, 16); @@ -1101,6 +1249,8 @@ int bt_mesh_cfg_app_key_delete(bt_mesh_client_common_param_t *param, { BLE_MESH_MODEL_BUF_DEFINE(msg, OP_APP_KEY_DEL, 3); + BT_DBG("AppKeyDelete, NetIdx 0x%04x AppIdx 0x%04x", net_idx, app_idx); + bt_mesh_model_msg_init(&msg, OP_APP_KEY_DEL); key_idx_pack(&msg, net_idx, app_idx); @@ -1109,11 +1259,15 @@ int bt_mesh_cfg_app_key_delete(bt_mesh_client_common_param_t *param, int bt_mesh_cfg_app_key_get(bt_mesh_client_common_param_t *param, uint16_t net_idx) { + BT_DBG("AppKeyGet, NetIdx 0x%04x", net_idx); + return send_msg_with_le16(param, OP_APP_KEY_GET, net_idx); } int bt_mesh_cfg_node_identity_get(bt_mesh_client_common_param_t *param, uint16_t net_idx) { + BT_DBG("NodeIdentityGet, NetIdx 0x%04x", net_idx); + return send_msg_with_le16(param, OP_NODE_IDENTITY_GET, net_idx); } @@ -1122,6 +1276,8 @@ int bt_mesh_cfg_node_identity_set(bt_mesh_client_common_param_t *param, { BLE_MESH_MODEL_BUF_DEFINE(msg, OP_NODE_IDENTITY_SET, 3); + BT_DBG("NodeIdentitySet, NetIdx 0x%04x Identity 0x%02x", net_idx, identity); + if (identity > 0x02) { BT_ERR("Invalid node identity 0x%02x", identity); return -EINVAL; @@ -1140,6 +1296,10 @@ int bt_mesh_cfg_mod_app_unbind(bt_mesh_client_common_param_t *param, { BLE_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_APP_UNBIND, 8); + BT_DBG("ModAppUnbind"); + BT_DBG("ElemAddr 0x%04x AppIdx 0x%04x ModID 0x%04x CID 0x%04x", + elem_addr, app_idx, mod_id, cid); + bt_mesh_model_msg_init(&msg, OP_MOD_APP_UNBIND); net_buf_simple_add_le16(&msg, elem_addr); net_buf_simple_add_le16(&msg, app_idx); @@ -1169,21 +1329,29 @@ static int mod_app_get(bt_mesh_client_common_param_t *param, uint32_t op, int bt_mesh_cfg_mod_app_get(bt_mesh_client_common_param_t *param, uint16_t elem_addr, uint16_t mod_id) { + BT_DBG("ModAppGet, ElemAddr 0x%04x ModID 0x%04x", elem_addr, mod_id); + return mod_app_get(param, OP_SIG_MOD_APP_GET, elem_addr, mod_id, BLE_MESH_CID_NVAL); } int bt_mesh_cfg_mod_app_get_vnd(bt_mesh_client_common_param_t *param, uint16_t elem_addr, uint16_t mod_id, uint16_t cid) { + BT_DBG("ModAppGetVnd"); + BT_DBG("ElemAddr 0x%04x ModID 0x%04x CID 0x%04x", elem_addr, mod_id, cid); + if (cid == BLE_MESH_CID_NVAL) { BT_ERR("Invalid company id"); return -EINVAL; } + return mod_app_get(param, OP_VND_MOD_APP_GET, elem_addr, mod_id, cid); } int bt_mesh_cfg_kr_phase_get(bt_mesh_client_common_param_t *param, uint16_t net_idx) { + BT_DBG("KrPhaseGet, NetIdx 0x%04x", net_idx); + return send_msg_with_le16(param, OP_KRP_GET, net_idx); } @@ -1192,6 +1360,8 @@ int bt_mesh_cfg_kr_phase_set(bt_mesh_client_common_param_t *param, { BLE_MESH_MODEL_BUF_DEFINE(msg, OP_KRP_SET, 3); + BT_DBG("KrPhaseSet, NetIdx 0x%04x Transition 0x%02x", net_idx, transition); + if (transition > 0x03) { BT_ERR("Invalid kr phase transition 0x%02x", transition); return -EINVAL; @@ -1206,16 +1376,22 @@ int bt_mesh_cfg_kr_phase_set(bt_mesh_client_common_param_t *param, int bt_mesh_cfg_lpn_timeout_get(bt_mesh_client_common_param_t *param, uint16_t lpn_addr) { + BT_DBG("LPNTimeoutGet, LPN 0x%04x", lpn_addr); + return send_msg_with_le16(param, OP_LPN_TIMEOUT_GET, lpn_addr); } int bt_mesh_cfg_net_transmit_get(bt_mesh_client_common_param_t *param) { + BT_DBG("NetTransmitGet"); + return send_msg_with_none(param, OP_NET_TRANSMIT_GET); } int bt_mesh_cfg_net_transmit_set(bt_mesh_client_common_param_t *param, uint8_t transmit) { + BT_DBG("NetTransmitSet, Transmit 0x%02x", transmit); + return send_msg_with_u8(param, OP_NET_TRANSMIT_SET, transmit); } @@ -1224,6 +1400,8 @@ static int cfg_cli_init(struct bt_mesh_model *model) config_internal_data_t *internal = NULL; bt_mesh_config_client_t *client = NULL; + BT_DBG("CfgCliInit"); + if (!model) { BT_ERR("Invalid Configuration Client model"); return -EINVAL; @@ -1271,6 +1449,8 @@ static int cfg_cli_deinit(struct bt_mesh_model *model) { bt_mesh_config_client_t *client = NULL; + BT_DBG("CfgCliDeinit"); + if (!model) { BT_ERR("Invalid Configuration Client model"); return -EINVAL; diff --git a/components/bt/esp_ble_mesh/core/cfg_srv.c b/components/bt/esp_ble_mesh/core/cfg_srv.c index fe605939a54..84cdb59b3aa 100644 --- a/components/bt/esp_ble_mesh/core/cfg_srv.c +++ b/components/bt/esp_ble_mesh/core/cfg_srv.c @@ -32,7 +32,7 @@ #if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" -#endif +#endif /* CONFIG_BLE_MESH_V11_SUPPORT */ #define DEFAULT_TTL 7 @@ -66,6 +66,9 @@ static uint8_t bt_mesh_comp_page_check(uint8_t page, bool largest) static inline uint16_t get_comp_elem_size(struct bt_mesh_elem *elem) { + BT_DBG("GetCompElemSize, ModelCount %u VndModelCount %u", + elem->model_count, elem->vnd_model_count); + return (4 + elem->model_count * 2 + elem->vnd_model_count * 4); } @@ -77,6 +80,8 @@ static uint16_t get_comp_data_size(const struct bt_mesh_comp *comp) size += get_comp_elem_size(&(comp->elem[i])); } + BT_DBG("GetCompDataSize, Size %u", size); + return size; } @@ -119,6 +124,7 @@ static void get_comp_data(struct net_buf_simple *buf, */ if (full_element && net_buf_simple_tailroom(buf) < get_comp_elem_size(elem)) { + BT_WARN("NoRoomForElementModelList"); return; } @@ -137,6 +143,8 @@ static void get_comp_data(struct net_buf_simple *buf, net_buf_simple_add_le16(buf, model->vnd.id); } } + + BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); } static int fetch_comp_data(struct net_buf_simple *buf, @@ -155,7 +163,7 @@ static int fetch_comp_data(struct net_buf_simple *buf, if (net_buf_simple_tailroom(buf) < 10 || size - offset > net_buf_simple_tailroom(buf)) { BT_ERR("Too small buffer for comp data %d, %d, expected %d", - page, buf->size, size - offset); + page, buf->size, size - offset); return -EINVAL; } @@ -183,6 +191,9 @@ static int bt_mesh_get_comp_data(struct net_buf_simple *buf, uint8_t page, uint16_t offset, bool full_element) { + BT_DBG("FetchCompData, Page %u Offset %u FullElement %u", + page, offset, full_element); + if (page == 0) { return fetch_comp_data(buf, comp_0, page, offset, full_element); } @@ -199,9 +210,10 @@ static void comp_data_get(struct bt_mesh_model *model, struct net_buf_simple *sdu = NULL; uint8_t page = 0U; - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, - bt_hex(buf->data, buf->len)); + BT_DBG("CompDataGet"); + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", + ctx->net_idx, ctx->app_idx, ctx->addr); + BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); /* TODO: * @@ -268,14 +280,17 @@ static void comp_data_get(struct bt_mesh_model *model, } static struct bt_mesh_model *get_model(struct bt_mesh_elem *elem, - struct net_buf_simple *buf, bool *vnd) + struct net_buf_simple *buf, + bool *vnd) { uint16_t company = 0U, id = 0U; + BT_DBG("GetModel, Len %u", buf->len); + if (buf->len < 4) { id = net_buf_simple_pull_le16(buf); - BT_DBG("ID 0x%04x addr 0x%04x", id, elem->addr); + BT_DBG("ID 0x%04x ElemAddr 0x%04x", id, elem->addr); *vnd = false; @@ -285,42 +300,49 @@ static struct bt_mesh_model *get_model(struct bt_mesh_elem *elem, company = net_buf_simple_pull_le16(buf); id = net_buf_simple_pull_le16(buf); - BT_DBG("Company 0x%04x ID 0x%04x addr 0x%04x", company, id, - elem->addr); + BT_DBG("CID 0x%04x ID 0x%04x Addr 0x%04x", company, id, elem->addr); *vnd = true; return bt_mesh_model_find_vnd(elem, company, id); } -static bool mod_pub_app_key_bound(struct bt_mesh_model *model, - uint16_t app_idx) +static bool mod_pub_app_key_bound(struct bt_mesh_model *model, uint16_t app_idx) { int i; + BT_DBG("ModPubAppKeyBound, AppIdx 0x%04x", app_idx); + for (i = 0; i < ARRAY_SIZE(model->keys); i++) { if (model->keys[i] == app_idx) { return true; } } - BT_ERR("AppKey(0x%02x) not bound to this model", app_idx); + BT_ERR("AppKeyNotBound, AppIdx 0x%04x", app_idx); return false; } static uint8_t _mod_pub_set(struct bt_mesh_model *model, uint16_t pub_addr, - uint16_t app_idx, uint8_t cred_flag, uint8_t ttl, uint8_t period, - uint8_t retransmit, bool store) + uint16_t app_idx, uint8_t cred_flag, uint8_t ttl, + uint8_t period, uint8_t retransmit, bool store) { + BT_DBG("_ModPubSet"); + BT_DBG("Addr 0x%04x AppIdx 0x%04x TTL %u Period 0x%02x Retransmit 0x%02x Store %u", + pub_addr, app_idx, ttl, period, retransmit, store); + if (!model->pub) { + BT_DBG("StatusNvalPubParam"); return STATUS_NVAL_PUB_PARAM; } if (!IS_ENABLED(CONFIG_BLE_MESH_LOW_POWER) && cred_flag) { + BT_DBG("StatusFeatNotSupp"); return STATUS_FEAT_NOT_SUPP; } if (!model->pub->update && period) { + BT_DBG("StatusNvalPubParam"); return STATUS_NVAL_PUB_PARAM; } @@ -353,6 +375,7 @@ static uint8_t _mod_pub_set(struct bt_mesh_model *model, uint16_t pub_addr, */ if (!bt_mesh_app_key_get(app_idx) || !mod_pub_app_key_bound(model, app_idx)) { + BT_DBG("StatusInvalidAppKey"); return STATUS_INVALID_APPKEY; } @@ -367,7 +390,8 @@ static uint8_t _mod_pub_set(struct bt_mesh_model *model, uint16_t pub_addr, int32_t period_ms; period_ms = bt_mesh_model_pub_period_get(model); - BT_DBG("period %u ms", period_ms); + + BT_DBG("PubPeriod %ld", period_ms); if (period_ms) { k_delayed_work_submit(&model->pub->timer, period_ms); @@ -387,9 +411,10 @@ static uint8_t mod_bind(struct bt_mesh_model *model, uint16_t key_idx) { int i; - BT_DBG("model %p key_idx 0x%03x", model, key_idx); + BT_DBG("ModBind, KeyIdx 0x%04x", key_idx); if (!bt_mesh_app_key_get(key_idx)) { + BT_DBG("StatusInvalidAppKey"); return STATUS_INVALID_APPKEY; } @@ -412,6 +437,7 @@ static uint8_t mod_bind(struct bt_mesh_model *model, uint16_t key_idx) } } + BT_DBG("StatusInsuffResources"); return STATUS_INSUFF_RESOURCES; } @@ -419,9 +445,10 @@ static uint8_t mod_unbind(struct bt_mesh_model *model, uint16_t key_idx, bool st { int i; - BT_DBG("model %p key_idx 0x%03x store %u", model, key_idx, store); + BT_DBG("ModUnbind, KeyIdx 0x%04x Store %u", key_idx, store); if (!bt_mesh_app_key_get(key_idx)) { + BT_DBG("StatusInvalidAppKey"); return STATUS_INVALID_APPKEY; } @@ -449,6 +476,8 @@ struct bt_mesh_app_key *bt_mesh_app_key_alloc(uint16_t app_idx) { int i; + BT_DBG("AppKeyAlloc, AppIdx 0x%04x", app_idx); + for (i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) { struct bt_mesh_app_key *key = &bt_mesh.app_keys[i]; @@ -457,31 +486,36 @@ struct bt_mesh_app_key *bt_mesh_app_key_alloc(uint16_t app_idx) } } + BT_ERR("AppKeyFull"); return NULL; } -static uint8_t app_key_set(uint16_t net_idx, uint16_t app_idx, const uint8_t val[16], - bool update) +static uint8_t app_key_set(uint16_t net_idx, uint16_t app_idx, + const uint8_t val[16], bool update) { struct bt_mesh_app_keys *keys = NULL; struct bt_mesh_app_key *key = NULL; struct bt_mesh_subnet *sub = NULL; - BT_DBG("net_idx 0x%04x app_idx %04x update %u val %s", + BT_DBG("AppKeySet"); + BT_DBG("NetIdx 0x%04x AppIdx %04x Update %u Val %s", net_idx, app_idx, update, bt_hex(val, 16)); sub = bt_mesh_subnet_get(net_idx); if (!sub) { + BT_DBG("StatusInvalidNetKey"); return STATUS_INVALID_NETKEY; } key = bt_mesh_app_key_get(app_idx); if (update) { if (!key) { + BT_DBG("StatusInvalidAppKey"); return STATUS_INVALID_APPKEY; } if (key->net_idx != net_idx) { + BT_DBG("StatusInvalidBinding"); return STATUS_INVALID_BINDING; } @@ -493,11 +527,13 @@ static uint8_t app_key_set(uint16_t net_idx, uint16_t app_idx, const uint8_t val * the AppKey value is different. */ if (sub->kr_phase != BLE_MESH_KR_PHASE_1) { + BT_DBG("StatusCannotUpdate"); return STATUS_CANNOT_UPDATE; } if (key->updated) { if (memcmp(keys->val, val, 16)) { + BT_DBG("StatusCannotUpdate"); return STATUS_CANNOT_UPDATE; } @@ -513,14 +549,17 @@ static uint8_t app_key_set(uint16_t net_idx, uint16_t app_idx, const uint8_t val } if (key->net_idx == net_idx) { + BT_DBG("StatusIdxAlreadyStored"); return STATUS_IDX_ALREADY_STORED; } + BT_DBG("StatusInvalidNetKey"); return STATUS_INVALID_NETKEY; } key = bt_mesh_app_key_alloc(app_idx); if (!key) { + BT_DBG("StatusInsuffResources"); return STATUS_INSUFF_RESOURCES; } @@ -532,17 +571,15 @@ static uint8_t app_key_set(uint16_t net_idx, uint16_t app_idx, const uint8_t val key->updated = false; } + BT_DBG("StatusStorageFail"); return STATUS_STORAGE_FAIL; } - BT_DBG("app_idx 0x%04x AID 0x%02x", app_idx, keys->id); - key->net_idx = net_idx; key->app_idx = app_idx; memcpy(keys->val, val, 16); if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) { - BT_DBG("Storing AppKey persistently"); bt_mesh_store_app_key(key); } @@ -559,14 +596,13 @@ static void app_key_add(struct bt_mesh_model *model, key_idx_unpack(buf, &key_net_idx, &key_app_idx); - BT_DBG("AppIdx 0x%04x NetIdx 0x%04x", key_app_idx, key_net_idx); + BT_DBG("AppKeyAdd, NetIdx 0x%04x AppIdx 0x%04x", key_net_idx, key_app_idx); bt_mesh_model_msg_init(&msg, OP_APP_KEY_STATUS); status = app_key_set(key_net_idx, key_app_idx, buf->data, false); - BT_DBG("status 0x%02x", status); - net_buf_simple_add_u8(&msg, status); + net_buf_simple_add_u8(&msg, status); key_idx_pack(&msg, key_net_idx, key_app_idx); if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) { @@ -594,14 +630,13 @@ static void app_key_update(struct bt_mesh_model *model, key_idx_unpack(buf, &key_net_idx, &key_app_idx); - BT_DBG("AppIdx 0x%04x NetIdx 0x%04x", key_app_idx, key_net_idx); + BT_DBG("AppKeyUpdate, NetIdx 0x%04x AppIdx 0x%04x", key_net_idx, key_app_idx); bt_mesh_model_msg_init(&msg, OP_APP_KEY_STATUS); status = app_key_set(key_net_idx, key_app_idx, buf->data, true); - BT_DBG("status 0x%02x", status); - net_buf_simple_add_u8(&msg, status); + net_buf_simple_add_u8(&msg, status); key_idx_pack(&msg, key_net_idx, key_app_idx); if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) { @@ -628,6 +663,8 @@ static void _mod_unbind(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, { struct unbind_data *data = user_data; + BT_DBG("_ModUnbind, Vnd %u Primary %u", vnd, primary); + mod_unbind(mod, data->app_idx, data->store); } @@ -635,7 +672,7 @@ void bt_mesh_app_key_del(struct bt_mesh_app_key *key, bool store) { struct unbind_data data = { .app_idx = key->app_idx, .store = store }; - BT_DBG("AppIdx 0x%03x store %u", key->app_idx, store); + BT_DBG("AppKeyDel, AppIdx 0x%04x Store %u", key->app_idx, store); bt_mesh_model_foreach(_mod_unbind, &data); @@ -658,9 +695,10 @@ static void app_key_del(struct bt_mesh_model *model, key_idx_unpack(buf, &key_net_idx, &key_app_idx); - BT_DBG("AppIdx 0x%04x NetIdx 0x%04x", key_app_idx, key_net_idx); + BT_DBG("AppkeyDel, NetIdx 0x%04x AppIdx 0x%04x", key_net_idx, key_app_idx); if (!bt_mesh_subnet_get(key_net_idx)) { + BT_DBG("StatusInvalidNetKey"); status = STATUS_INVALID_NETKEY; goto send_status; } @@ -675,11 +713,13 @@ static void app_key_del(struct bt_mesh_model *model, } if (key->net_idx != key_net_idx) { + BT_DBG("StatusInvalidBinding"); status = STATUS_INVALID_BINDING; goto send_status; } bt_mesh_app_key_del(key, true); + status = STATUS_SUCCESS; send_status: @@ -703,7 +743,7 @@ send_status: } /* Index list length: 3 bytes for every pair and 2 bytes for an odd idx */ -#define IDX_LEN(num) (((num) / 2) * 3 + ((num) % 2) * 2) +#define IDX_LEN(num) (((num) / 2) * 3 + ((num) % 2) * 2) static void app_key_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, @@ -714,17 +754,20 @@ static void app_key_get(struct bt_mesh_model *model, uint16_t get_idx = 0U, i = 0U, prev = 0U; uint8_t status = 0U; + BT_DBG("AppkeyGet"); + get_idx = net_buf_simple_pull_le16(buf); if (get_idx > 0xfff) { BT_ERR("Invalid NetKeyIndex 0x%04x", get_idx); return; } - BT_DBG("idx 0x%04x", get_idx); + BT_DBG("GetIdx 0x%04x", get_idx); bt_mesh_model_msg_init(&msg, OP_APP_KEY_LIST); if (!bt_mesh_subnet_get(get_idx)) { + BT_DBG("StatusInvalidNetKey"); status = STATUS_INVALID_NETKEY; } else { status = STATUS_SUCCESS; @@ -738,6 +781,7 @@ static void app_key_get(struct bt_mesh_model *model, } prev = BLE_MESH_KEY_UNUSED; + for (i = 0U; i < ARRAY_SIZE(bt_mesh.app_keys); i++) { struct bt_mesh_app_key *key = &bt_mesh.app_keys[i]; @@ -770,9 +814,10 @@ static void beacon_get(struct bt_mesh_model *model, { BLE_MESH_MODEL_BUF_DEFINE(msg, OP_BEACON_STATUS, 1); - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, - bt_hex(buf->data, buf->len)); + BT_DBG("BeaconGet"); + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", + ctx->net_idx, ctx->app_idx, ctx->addr); + BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); bt_mesh_model_msg_init(&msg, OP_BEACON_STATUS); net_buf_simple_add_u8(&msg, bt_mesh_secure_beacon_get()); @@ -789,9 +834,10 @@ static void beacon_set(struct bt_mesh_model *model, BLE_MESH_MODEL_BUF_DEFINE(msg, OP_BEACON_STATUS, 1); struct bt_mesh_cfg_srv *cfg = model->user_data; - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, - bt_hex(buf->data, buf->len)); + BT_DBG("BeaconSet"); + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", + ctx->net_idx, ctx->app_idx, ctx->addr); + BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); if (!cfg) { BT_WARN("No Configuration Server context available"); @@ -828,9 +874,10 @@ static void default_ttl_get(struct bt_mesh_model *model, { BLE_MESH_MODEL_BUF_DEFINE(msg, OP_DEFAULT_TTL_STATUS, 1); - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, - bt_hex(buf->data, buf->len)); + BT_DBG("DefaultTTLGet"); + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", + ctx->net_idx, ctx->app_idx, ctx->addr); + BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); bt_mesh_model_msg_init(&msg, OP_DEFAULT_TTL_STATUS); net_buf_simple_add_u8(&msg, bt_mesh_default_ttl_get()); @@ -847,9 +894,10 @@ static void default_ttl_set(struct bt_mesh_model *model, BLE_MESH_MODEL_BUF_DEFINE(msg, OP_DEFAULT_TTL_STATUS, 1); struct bt_mesh_cfg_srv *cfg = model->user_data; - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, - bt_hex(buf->data, buf->len)); + BT_DBG("DefaultTTLSet"); + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", + ctx->net_idx, ctx->app_idx, ctx->addr); + BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); if (!cfg) { BT_WARN("No Configuration Server context available"); @@ -879,6 +927,8 @@ static void send_gatt_proxy_status(struct bt_mesh_model *model, { BLE_MESH_MODEL_BUF_DEFINE(msg, OP_GATT_PROXY_STATUS, 1); + BT_DBG("SendGattProxyStatus"); + bt_mesh_model_msg_init(&msg, OP_GATT_PROXY_STATUS); net_buf_simple_add_u8(&msg, bt_mesh_gatt_proxy_get()); @@ -891,9 +941,10 @@ static void gatt_proxy_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, - bt_hex(buf->data, buf->len)); + BT_DBG("GattProxyGet"); + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", + ctx->net_idx, ctx->app_idx, ctx->addr); + BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); send_gatt_proxy_status(model, ctx); } @@ -904,9 +955,10 @@ static void gatt_proxy_set(struct bt_mesh_model *model, { struct bt_mesh_cfg_srv *cfg = model->user_data; - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, - bt_hex(buf->data, buf->len)); + BT_DBG("GattProxySet"); + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", + ctx->net_idx, ctx->app_idx, ctx->addr); + BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); if (buf->data[0] != 0x00 && buf->data[0] != 0x01) { BT_WARN("Invalid GATT Proxy value 0x%02x", buf->data[0]); @@ -923,7 +975,7 @@ static void gatt_proxy_set(struct bt_mesh_model *model, goto send_status; } - BT_DBG("GATT Proxy 0x%02x -> 0x%02x", cfg->gatt_proxy, buf->data[0]); + BT_DBG("GattProxy 0x%02x -> 0x%02x", cfg->gatt_proxy, buf->data[0]); if (cfg->gatt_proxy == buf->data[0]) { goto send_status; @@ -934,11 +986,11 @@ static void gatt_proxy_set(struct bt_mesh_model *model, #if CONFIG_BLE_MESH_PRB_SRV /* If the value of the GATT Proxy state of the node is 0x01 (see Table 4.21), * then the value of the Private GATT Proxy state shall be Disable (0x00). - */ + */ if (buf->data[0] == BLE_MESH_GATT_PROXY_ENABLED) { bt_mesh_disable_private_gatt_proxy(); } -#endif +#endif /* CONFIG_BLE_MESH_PRB_SRV */ #if CONFIG_BLE_MESH_DF_SRV /* If the value of the GATT Proxy state of the node is 0x00, @@ -946,7 +998,7 @@ static void gatt_proxy_set(struct bt_mesh_model *model, * directed proxy use directed default shall be 0x02. */ bt_mesh_disable_directed_proxy_state(ctx->net_idx); -#endif +#endif /* CONFIG_BLE_MESH_DF_SRV */ if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) { bt_mesh_store_cfg(); @@ -966,9 +1018,10 @@ static void net_transmit_get(struct bt_mesh_model *model, { BLE_MESH_MODEL_BUF_DEFINE(msg, OP_NET_TRANSMIT_STATUS, 1); - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, - bt_hex(buf->data, buf->len)); + BT_DBG("NetTransmitGet"); + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", + ctx->net_idx, ctx->app_idx, ctx->addr); + BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); bt_mesh_model_msg_init(&msg, OP_NET_TRANSMIT_STATUS); net_buf_simple_add_u8(&msg, bt_mesh_net_transmit_get()); @@ -985,11 +1038,13 @@ static void net_transmit_set(struct bt_mesh_model *model, BLE_MESH_MODEL_BUF_DEFINE(msg, OP_NET_TRANSMIT_STATUS, 1); struct bt_mesh_cfg_srv *cfg = model->user_data; - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, - bt_hex(buf->data, buf->len)); + BT_DBG("NetTransmitSet"); + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", + ctx->net_idx, ctx->app_idx, ctx->addr); + BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); - BT_DBG("Transmit 0x%02x (count %u interval %ums)", buf->data[0], + BT_DBG("Transmit 0x%02x Count %u Interval %u", + buf->data[0], BLE_MESH_TRANSMIT_COUNT(buf->data[0]), BLE_MESH_TRANSMIT_INT(buf->data[0])); @@ -1017,9 +1072,10 @@ static void relay_get(struct bt_mesh_model *model, { BLE_MESH_MODEL_BUF_DEFINE(msg, OP_RELAY_STATUS, 2); - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, - bt_hex(buf->data, buf->len)); + BT_DBG("RelayGet"); + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", + ctx->net_idx, ctx->app_idx, ctx->addr); + BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); bt_mesh_model_msg_init(&msg, OP_RELAY_STATUS); net_buf_simple_add_u8(&msg, bt_mesh_relay_get()); @@ -1037,9 +1093,10 @@ static void relay_set(struct bt_mesh_model *model, BLE_MESH_MODEL_BUF_DEFINE(msg, OP_RELAY_STATUS, 2); struct bt_mesh_cfg_srv *cfg = model->user_data; - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, - bt_hex(buf->data, buf->len)); + BT_DBG("RelaySet"); + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", + ctx->net_idx, ctx->app_idx, ctx->addr); + BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); if (!cfg) { BT_WARN("No Configuration Server context available"); @@ -1050,6 +1107,7 @@ static void relay_set(struct bt_mesh_model *model, change = false; } else { change = (cfg->relay != buf->data[0]); + cfg->relay = buf->data[0]; cfg->relay_retransmit = buf->data[1]; @@ -1058,9 +1116,8 @@ static void relay_set(struct bt_mesh_model *model, } } - BT_DBG("Relay 0x%02x (%s) xmit 0x%02x (count %u interval %u)", - cfg->relay, change ? "changed" : "not changed", - cfg->relay_retransmit, + BT_DBG("Relay 0x%02x Change %u Xmit 0x%02x Count %u Interval %u", + cfg->relay, change, cfg->relay_retransmit, BLE_MESH_TRANSMIT_COUNT(cfg->relay_retransmit), BLE_MESH_TRANSMIT_INT(cfg->relay_retransmit)); @@ -1089,6 +1146,10 @@ static void send_mod_pub_status(struct bt_mesh_model *cfg_mod, { BLE_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_PUB_STATUS, 14); + BT_DBG("SendModPubStatus"); + BT_DBG("ElemAddr 0x%04x PubAddr 0x%04x Vnd %u Status 0x%02x", + elem_addr, pub_addr, vnd, status); + bt_mesh_model_msg_init(&msg, OP_MOD_PUB_STATUS); net_buf_simple_add_u8(&msg, status); @@ -1129,6 +1190,8 @@ static void mod_pub_get(struct bt_mesh_model *model, uint8_t *mod_id = NULL, status = 0U; bool vnd = false; + BT_DBG("ModPubGet"); + elem_addr = net_buf_simple_pull_le16(buf); if (!BLE_MESH_ADDR_IS_UNICAST(elem_addr)) { BT_ERR("Prohibited element address 0x%04x", elem_addr); @@ -1137,10 +1200,11 @@ static void mod_pub_get(struct bt_mesh_model *model, mod_id = buf->data; - BT_DBG("elem_addr 0x%04x", elem_addr); + BT_DBG("ElemAddr 0x%04x", elem_addr); elem = bt_mesh_elem_find(elem_addr); if (!elem) { + BT_DBG("StatusInvalidAddress"); mod = NULL; vnd = (buf->len == 4U); status = STATUS_INVALID_ADDRESS; @@ -1149,11 +1213,13 @@ static void mod_pub_get(struct bt_mesh_model *model, mod = get_model(elem, buf, &vnd); if (!mod) { + BT_DBG("StatusInvalidModel"); status = STATUS_INVALID_MODEL; goto send_status; } if (!mod->pub) { + BT_DBG("StatusNvalPubParam"); status = STATUS_NVAL_PUB_PARAM; goto send_status; } @@ -1162,8 +1228,7 @@ static void mod_pub_get(struct bt_mesh_model *model, status = STATUS_SUCCESS; send_status: - send_mod_pub_status(model, ctx, elem_addr, pub_addr, vnd, mod, - status, mod_id); + send_mod_pub_status(model, ctx, elem_addr, pub_addr, vnd, mod, status, mod_id); } static void mod_pub_set(struct bt_mesh_model *model, @@ -1177,6 +1242,8 @@ static void mod_pub_set(struct bt_mesh_model *model, uint8_t *mod_id = NULL; bool vnd = false; + BT_DBG("ModPubSet"); + elem_addr = net_buf_simple_pull_le16(buf); if (!BLE_MESH_ADDR_IS_UNICAST(elem_addr)) { BT_ERR("Prohibited element address 0x%04x", elem_addr); @@ -1198,16 +1265,18 @@ static void mod_pub_set(struct bt_mesh_model *model, retransmit = net_buf_simple_pull_u8(buf); mod_id = buf->data; - BT_DBG("elem_addr 0x%04x pub_addr 0x%04x cred_flag %u", + BT_DBG("ElemAddr 0x%04x PubAddr 0x%04x CredFlag %u", elem_addr, pub_addr, cred_flag); - BT_DBG("pub_app_idx 0x%03x, pub_ttl %u pub_period 0x%02x", + BT_DBG("PubAppIdx 0x%04x PubTTL %u PubPeriod 0x%02x", pub_app_idx, pub_ttl, pub_period); - BT_DBG("retransmit 0x%02x (count %u interval %ums)", retransmit, + BT_DBG("Retransmit 0x%02x Count %u Interval %u", + retransmit, BLE_MESH_PUB_TRANSMIT_COUNT(retransmit), BLE_MESH_PUB_TRANSMIT_INT(retransmit)); elem = bt_mesh_elem_find(elem_addr); if (!elem) { + BT_DBG("StatusInvalidAddress"); mod = NULL; vnd = (buf->len == 4U); status = STATUS_INVALID_ADDRESS; @@ -1216,6 +1285,7 @@ static void mod_pub_set(struct bt_mesh_model *model, mod = get_model(elem, buf, &vnd); if (!mod) { + BT_DBG("StatusInvalidModel"); status = STATUS_INVALID_MODEL; goto send_status; } @@ -1224,8 +1294,7 @@ static void mod_pub_set(struct bt_mesh_model *model, pub_period, retransmit, true); send_status: - send_mod_pub_status(model, ctx, elem_addr, pub_addr, vnd, mod, - status, mod_id); + send_mod_pub_status(model, ctx, elem_addr, pub_addr, vnd, mod, status, mod_id); if (status == STATUS_SUCCESS && mod->pub) { bt_mesh_cfg_server_state_change_t change = {0}; @@ -1245,6 +1314,8 @@ send_status: struct label *get_label(uint16_t index) { + BT_DBG("GetLabel, Index %u", index); + if (index >= ARRAY_SIZE(labels)) { return NULL; } @@ -1255,7 +1326,10 @@ struct label *get_label(uint16_t index) #if CONFIG_BLE_MESH_LABEL_COUNT > 0 static inline void va_store(struct label *store) { + BT_DBG("VaStore"); + bt_mesh_atomic_set_bit(store->flags, BLE_MESH_VA_CHANGED); + if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) { bt_mesh_store_label(); } @@ -1267,6 +1341,8 @@ static struct label *va_find(const uint8_t *label_uuid, struct label *match = NULL; int i; + BT_DBG("VaFind"); + if (free_slot != NULL) { *free_slot = NULL; } @@ -1291,10 +1367,14 @@ uint8_t va_add(uint8_t *label_uuid, uint16_t *addr) { struct label *update = NULL, *free_slot = NULL; + BT_DBG("VaAdd"); + update = va_find(label_uuid, &free_slot); if (update) { update->ref++; + va_store(update); + if (addr) { *addr = update->addr; } @@ -1302,10 +1382,12 @@ uint8_t va_add(uint8_t *label_uuid, uint16_t *addr) } if (!free_slot) { + BT_DBG("StatusInsuffResources"); return STATUS_INSUFF_RESOURCES; } if (bt_mesh_virtual_addr(label_uuid, addr) < 0) { + BT_DBG("StatusUnspecified"); return STATUS_UNSPECIFIED; } @@ -1321,6 +1403,8 @@ uint8_t va_del(uint8_t *label_uuid, uint16_t *addr) { struct label *update = NULL; + BT_DBG("VaDel"); + update = va_find(label_uuid, NULL); if (update) { update->ref--; @@ -1337,6 +1421,7 @@ uint8_t va_del(uint8_t *label_uuid, uint16_t *addr) *addr = BLE_MESH_ADDR_UNASSIGNED; } + BT_DBG("StatusCannotRemove"); return STATUS_CANNOT_REMOVE; } @@ -1346,6 +1431,8 @@ static size_t mod_sub_list_clear(struct bt_mesh_model *mod) size_t clear_count = 0U; int i; + BT_DBG("ModSubListClear"); + /* Unref stored labels related to this model */ for (i = 0, clear_count = 0; i < ARRAY_SIZE(mod->groups); i++) { if (!BLE_MESH_ADDR_IS_VIRTUAL(mod->groups[i])) { @@ -1365,10 +1452,12 @@ static size_t mod_sub_list_clear(struct bt_mesh_model *mod) if (label_uuid) { va_del(label_uuid, NULL); } else { - BT_ERR("Label UUID not found"); + BT_ERR("LabelUUIDNotFound"); } } + BT_DBG("ClearCount %u", clear_count); + return clear_count; } @@ -1384,6 +1473,8 @@ static void mod_pub_va_set(struct bt_mesh_model *model, uint8_t *mod_id = NULL; bool vnd = false; + BT_DBG("ModPubVaSet"); + elem_addr = net_buf_simple_pull_le16(buf); if (!BLE_MESH_ADDR_IS_UNICAST(elem_addr)) { BT_ERR("Prohibited element address 0x%04x", elem_addr); @@ -1404,15 +1495,17 @@ static void mod_pub_va_set(struct bt_mesh_model *model, retransmit = net_buf_simple_pull_u8(buf); mod_id = buf->data; - BT_DBG("elem_addr 0x%04x cred_flag %u", elem_addr, cred_flag); - BT_DBG("pub_app_idx 0x%03x, pub_ttl %u pub_period 0x%02x", + BT_DBG("ElemAddr 0x%04x CredFlag %u", elem_addr, cred_flag); + BT_DBG("PubAppIdx 0x%04x PubTTL %u PubPeriod 0x%02x", pub_app_idx, pub_ttl, pub_period); - BT_DBG("retransmit 0x%02x (count %u interval %ums)", retransmit, + BT_DBG("Retransmit 0x%02x Count %u Interval %u", + retransmit, BLE_MESH_PUB_TRANSMIT_COUNT(retransmit), BLE_MESH_PUB_TRANSMIT_INT(retransmit)); elem = bt_mesh_elem_find(elem_addr); if (!elem) { + BT_DBG("StatusInvalidAddress"); mod = NULL; vnd = (buf->len == 4U); pub_addr = 0U; @@ -1422,6 +1515,7 @@ static void mod_pub_va_set(struct bt_mesh_model *model, mod = get_model(elem, buf, &vnd); if (!mod) { + BT_DBG("StatusInvalidModel"); pub_addr = 0U; status = STATUS_INVALID_MODEL; goto send_status; @@ -1434,15 +1528,16 @@ static void mod_pub_va_set(struct bt_mesh_model *model, } send_status: - send_mod_pub_status(model, ctx, elem_addr, pub_addr, vnd, mod, - status, mod_id); + send_mod_pub_status(model, ctx, elem_addr, pub_addr, vnd, mod, status, mod_id); } -#else +#else /* CONFIG_BLE_MESH_LABEL_COUNT > 0 */ static size_t mod_sub_list_clear(struct bt_mesh_model *mod) { size_t clear_count = 0U; int i; + BT_DBG("ModSubListClear"); + /* Unref stored labels related to this model */ for (i = 0, clear_count = 0; i < ARRAY_SIZE(mod->groups); i++) { if (mod->groups[i] != BLE_MESH_ADDR_UNASSIGNED) { @@ -1451,6 +1546,8 @@ static size_t mod_sub_list_clear(struct bt_mesh_model *mod) } } + BT_DBG("ClearCount %u", clear_count); + return clear_count; } @@ -1458,12 +1555,14 @@ static void mod_pub_va_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { + uint16_t elem_addr = 0U, pub_addr = 0U; uint8_t *mod_id = NULL, status = 0U; struct bt_mesh_model *mod = NULL; struct bt_mesh_elem *elem = NULL; - uint16_t elem_addr = 0U, pub_addr = 0U; bool vnd = false; + BT_DBG("ModPubVaSet"); + elem_addr = net_buf_simple_pull_le16(buf); if (!BLE_MESH_ADDR_IS_UNICAST(elem_addr)) { BT_ERR("Prohibited element address 0x%04x", elem_addr); @@ -1473,10 +1572,11 @@ static void mod_pub_va_set(struct bt_mesh_model *model, net_buf_simple_pull(buf, 16); mod_id = net_buf_simple_pull(buf, 4); - BT_DBG("elem_addr 0x%04x", elem_addr); + BT_DBG("ElemAddr 0x%04x", elem_addr); elem = bt_mesh_elem_find(elem_addr); if (!elem) { + BT_DBG("StatusInvalidAddress"); mod = NULL; vnd = (buf->len == 4U); status = STATUS_INVALID_ADDRESS; @@ -1485,33 +1585,37 @@ static void mod_pub_va_set(struct bt_mesh_model *model, mod = get_model(elem, buf, &vnd); if (!mod) { + BT_DBG("StatusInvalidModel"); status = STATUS_INVALID_MODEL; goto send_status; } if (!mod->pub) { + BT_DBG("StatusNvalPubParam"); status = STATUS_NVAL_PUB_PARAM; goto send_status; } pub_addr = mod->pub->addr; + + BT_DBG("StatusInsuffResources"); status = STATUS_INSUFF_RESOURCES; send_status: - send_mod_pub_status(model, ctx, elem_addr, pub_addr, vnd, mod, - status, mod_id); + send_mod_pub_status(model, ctx, elem_addr, pub_addr, vnd, mod, status, mod_id); } #endif /* CONFIG_BLE_MESH_LABEL_COUNT > 0 */ static void send_mod_sub_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, uint8_t status, - uint16_t elem_addr, uint16_t sub_addr, uint8_t *mod_id, - bool vnd) + uint16_t elem_addr, uint16_t sub_addr, + uint8_t *mod_id, bool vnd) { BLE_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_SUB_STATUS, 9); - BT_DBG("status 0x%02x elem_addr 0x%04x sub_addr 0x%04x", status, - elem_addr, sub_addr); + BT_DBG("SendModSubStatus"); + BT_DBG("Status 0x%02x ElemAddr 0x%04x SubAddr 0x%04x Vnd %u", + status, elem_addr, sub_addr, vnd); bt_mesh_model_msg_init(&msg, OP_MOD_SUB_STATUS); @@ -1542,6 +1646,8 @@ static void mod_sub_add(struct bt_mesh_model *model, bool vnd = false; int i; + BT_DBG("ModSubAdd"); + elem_addr = net_buf_simple_pull_le16(buf); if (!BLE_MESH_ADDR_IS_UNICAST(elem_addr)) { BT_ERR("Prohibited element address 0x%04x", elem_addr); @@ -1550,12 +1656,13 @@ static void mod_sub_add(struct bt_mesh_model *model, sub_addr = net_buf_simple_pull_le16(buf); - BT_DBG("elem_addr 0x%04x, sub_addr 0x%04x", elem_addr, sub_addr); + BT_DBG("ElemAddr 0x%04x SubAddr 0x%04x", elem_addr, sub_addr); mod_id = buf->data; elem = bt_mesh_elem_find(elem_addr); if (!elem) { + BT_DBG("StatusInvalidAddress"); mod = NULL; vnd = (buf->len == 4U); status = STATUS_INVALID_ADDRESS; @@ -1564,18 +1671,19 @@ static void mod_sub_add(struct bt_mesh_model *model, mod = get_model(elem, buf, &vnd); if (!mod) { + BT_DBG("StatusInvalidModel"); status = STATUS_INVALID_MODEL; goto send_status; } if (!BLE_MESH_ADDR_IS_GROUP(sub_addr)) { + BT_DBG("StatusInvalidAddress"); status = STATUS_INVALID_ADDRESS; goto send_status; } if (bt_mesh_model_find_group(mod, sub_addr)) { /* Tried to add existing subscription */ - BT_DBG("found existing subscription"); status = STATUS_SUCCESS; goto send_status; } @@ -1592,6 +1700,7 @@ static void mod_sub_add(struct bt_mesh_model *model, } if (i == ARRAY_SIZE(mod->groups)) { + BT_DBG("StatusInsuffResources"); status = STATUS_INSUFF_RESOURCES; } else { status = STATUS_SUCCESS; @@ -1606,12 +1715,11 @@ static void mod_sub_add(struct bt_mesh_model *model, } send_status: - send_mod_sub_status(model, ctx, status, elem_addr, sub_addr, - mod_id, vnd); + send_mod_sub_status(model, ctx, status, elem_addr, sub_addr, mod_id, vnd); #if CONFIG_BLE_MESH_DF_SRV bt_mesh_directed_forwarding_node_solicitation(mod, bt_mesh_subnet_get(ctx->net_idx)); -#endif +#endif /* CONFIG_BLE_MESH_DF_SRV */ if (status == STATUS_SUCCESS) { bt_mesh_cfg_server_state_change_t change = {0}; @@ -1636,6 +1744,8 @@ static void mod_sub_del(struct bt_mesh_model *model, uint8_t status = 0U; bool vnd = false; + BT_DBG("ModSubDel"); + elem_addr = net_buf_simple_pull_le16(buf); if (!BLE_MESH_ADDR_IS_UNICAST(elem_addr)) { BT_ERR("Prohibited element address 0x%04x", elem_addr); @@ -1644,12 +1754,13 @@ static void mod_sub_del(struct bt_mesh_model *model, sub_addr = net_buf_simple_pull_le16(buf); - BT_DBG("elem_addr 0x%04x sub_addr 0x%04x", elem_addr, sub_addr); + BT_DBG("ElemAddr 0x%04x SubAddr 0x%04x", elem_addr, sub_addr); mod_id = buf->data; elem = bt_mesh_elem_find(elem_addr); if (!elem) { + BT_DBG("StatusInvalidAddress"); mod = NULL; vnd = (buf->len == 4U); status = STATUS_INVALID_ADDRESS; @@ -1658,11 +1769,13 @@ static void mod_sub_del(struct bt_mesh_model *model, mod = get_model(elem, buf, &vnd); if (!mod) { + BT_DBG("StatusInvalidModel"); status = STATUS_INVALID_MODEL; goto send_status; } if (!BLE_MESH_ADDR_IS_GROUP(sub_addr)) { + BT_DBG("StatusInvalidAddress"); status = STATUS_INVALID_ADDRESS; goto send_status; } @@ -1686,8 +1799,7 @@ static void mod_sub_del(struct bt_mesh_model *model, } send_status: - send_mod_sub_status(model, ctx, status, elem_addr, sub_addr, - mod_id, vnd); + send_mod_sub_status(model, ctx, status, elem_addr, sub_addr, mod_id, vnd); if (status == STATUS_SUCCESS) { bt_mesh_cfg_server_state_change_t change = {0}; @@ -1711,6 +1823,8 @@ static void mod_sub_overwrite(struct bt_mesh_model *model, uint8_t status = 0U; bool vnd = false; + BT_DBG("ModSubOverwrite"); + elem_addr = net_buf_simple_pull_le16(buf); if (!BLE_MESH_ADDR_IS_UNICAST(elem_addr)) { BT_ERR("Prohibited element address 0x%04x", elem_addr); @@ -1719,12 +1833,13 @@ static void mod_sub_overwrite(struct bt_mesh_model *model, sub_addr = net_buf_simple_pull_le16(buf); - BT_DBG("elem_addr 0x%04x sub_addr 0x%04x", elem_addr, sub_addr); + BT_DBG("ElemAddr 0x%04x SubAddr 0x%04x", elem_addr, sub_addr); mod_id = buf->data; elem = bt_mesh_elem_find(elem_addr); if (!elem) { + BT_DBG("StatusInvalidAddress"); mod = NULL; vnd = (buf->len == 4U); status = STATUS_INVALID_ADDRESS; @@ -1733,11 +1848,13 @@ static void mod_sub_overwrite(struct bt_mesh_model *model, mod = get_model(elem, buf, &vnd); if (!mod) { + BT_DBG("StatusInvalidModel"); status = STATUS_INVALID_MODEL; goto send_status; } if (!BLE_MESH_ADDR_IS_GROUP(sub_addr)) { + BT_DBG("StatusInvalidAddress"); status = STATUS_INVALID_ADDRESS; goto send_status; } @@ -1760,13 +1877,13 @@ static void mod_sub_overwrite(struct bt_mesh_model *model, bt_mesh_lpn_group_add(sub_addr); } } else { + BT_DBG("StatusInsuffResources"); status = STATUS_INSUFF_RESOURCES; } send_status: - send_mod_sub_status(model, ctx, status, elem_addr, sub_addr, - mod_id, vnd); + send_mod_sub_status(model, ctx, status, elem_addr, sub_addr, mod_id, vnd); } static void mod_sub_del_all(struct bt_mesh_model *model, @@ -1780,18 +1897,21 @@ static void mod_sub_del_all(struct bt_mesh_model *model, uint8_t status = 0U; bool vnd = false; + BT_DBG("ModSubDelAll"); + elem_addr = net_buf_simple_pull_le16(buf); if (!BLE_MESH_ADDR_IS_UNICAST(elem_addr)) { BT_ERR("Prohibited element address 0x%04x", elem_addr); return; } - BT_DBG("elem_addr 0x%04x", elem_addr); + BT_DBG("ElemAddr 0x%04x", elem_addr); mod_id = buf->data; elem = bt_mesh_elem_find(elem_addr); if (!elem) { + BT_DBG("StatusInvalidAddress"); mod = NULL; vnd = (buf->len == 4U); status = STATUS_INVALID_ADDRESS; @@ -1800,6 +1920,7 @@ static void mod_sub_del_all(struct bt_mesh_model *model, mod = get_model(elem, buf, &vnd); if (!mod) { + BT_DBG("StatusInvalidModel"); status = STATUS_INVALID_MODEL; goto send_status; } @@ -1832,6 +1953,8 @@ static void mod_sub_get(struct bt_mesh_model *model, uint16_t addr = 0U, id = 0U; int i; + BT_DBG("ModSubGet"); + addr = net_buf_simple_pull_le16(buf); if (!BLE_MESH_ADDR_IS_UNICAST(addr)) { BT_ERR("Prohibited element address 0x%04x", addr); @@ -1840,12 +1963,13 @@ static void mod_sub_get(struct bt_mesh_model *model, id = net_buf_simple_pull_le16(buf); - BT_DBG("addr 0x%04x id 0x%04x", addr, id); + BT_DBG("ElemAddr 0x%04x ID 0x%04x", addr, id); bt_mesh_model_msg_init(&msg, OP_MOD_SUB_LIST); elem = bt_mesh_elem_find(addr); if (!elem) { + BT_DBG("StatusInvalidAddress"); net_buf_simple_add_u8(&msg, STATUS_INVALID_ADDRESS); net_buf_simple_add_le16(&msg, addr); net_buf_simple_add_le16(&msg, id); @@ -1854,6 +1978,7 @@ static void mod_sub_get(struct bt_mesh_model *model, mod = bt_mesh_model_find(elem, id); if (!mod) { + BT_DBG("StatusInvalidModel"); net_buf_simple_add_u8(&msg, STATUS_INVALID_MODEL); net_buf_simple_add_le16(&msg, addr); net_buf_simple_add_le16(&msg, id); @@ -1888,6 +2013,8 @@ static void mod_sub_get_vnd(struct bt_mesh_model *model, uint16_t company = 0U, addr = 0U, id = 0U; int i; + BT_DBG("ModSubGetVnd"); + addr = net_buf_simple_pull_le16(buf); if (!BLE_MESH_ADDR_IS_UNICAST(addr)) { BT_ERR("Prohibited element address 0x%04x", addr); @@ -1897,12 +2024,13 @@ static void mod_sub_get_vnd(struct bt_mesh_model *model, company = net_buf_simple_pull_le16(buf); id = net_buf_simple_pull_le16(buf); - BT_DBG("addr 0x%04x company 0x%04x id 0x%04x", addr, company, id); + BT_DBG("ElemAddr 0x%04x CID 0x%04x ID 0x%04x", addr, company, id); bt_mesh_model_msg_init(&msg, OP_MOD_SUB_LIST_VND); elem = bt_mesh_elem_find(addr); if (!elem) { + BT_DBG("StatusInvalidAddress"); net_buf_simple_add_u8(&msg, STATUS_INVALID_ADDRESS); net_buf_simple_add_le16(&msg, addr); net_buf_simple_add_le16(&msg, company); @@ -1912,6 +2040,7 @@ static void mod_sub_get_vnd(struct bt_mesh_model *model, mod = bt_mesh_model_find_vnd(elem, company, id); if (!mod) { + BT_DBG("StatusInvalidModel"); net_buf_simple_add_u8(&msg, STATUS_INVALID_MODEL); net_buf_simple_add_le16(&msg, addr); net_buf_simple_add_le16(&msg, company); @@ -1951,6 +2080,8 @@ static void mod_sub_va_add(struct bt_mesh_model *model, bool vnd = false; int i; + BT_DBG("ModSubVaAdd"); + elem_addr = net_buf_simple_pull_le16(buf); if (!BLE_MESH_ADDR_IS_UNICAST(elem_addr)) { BT_ERR("Prohibited element address 0x%04x", elem_addr); @@ -1959,11 +2090,12 @@ static void mod_sub_va_add(struct bt_mesh_model *model, label_uuid = net_buf_simple_pull_mem(buf, 16); - BT_DBG("elem_addr 0x%04x", elem_addr); + BT_DBG("ElemAddr 0x%04x", elem_addr); mod_id = buf->data; elem = bt_mesh_elem_find(elem_addr); if (!elem) { + BT_DBG("StatusInvalidAddress"); mod = NULL; vnd = (buf->len == 4U); sub_addr = BLE_MESH_ADDR_UNASSIGNED; @@ -1973,6 +2105,7 @@ static void mod_sub_va_add(struct bt_mesh_model *model, mod = get_model(elem, buf, &vnd); if (!mod) { + BT_DBG("StatusInvalidModel"); sub_addr = BLE_MESH_ADDR_UNASSIGNED; status = STATUS_INVALID_MODEL; goto send_status; @@ -2001,6 +2134,7 @@ static void mod_sub_va_add(struct bt_mesh_model *model, } if (i == ARRAY_SIZE(mod->groups)) { + BT_DBG("StatusInsuffResources"); status = STATUS_INSUFF_RESOURCES; } else { if (IS_ENABLED(CONFIG_BLE_MESH_LOW_POWER)) { @@ -2015,8 +2149,7 @@ static void mod_sub_va_add(struct bt_mesh_model *model, } send_status: - send_mod_sub_status(model, ctx, status, elem_addr, sub_addr, - mod_id, vnd); + send_mod_sub_status(model, ctx, status, elem_addr, sub_addr, mod_id, vnd); } static void mod_sub_va_del(struct bt_mesh_model *model, @@ -2032,6 +2165,8 @@ static void mod_sub_va_del(struct bt_mesh_model *model, uint8_t status = 0U; bool vnd = false; + BT_DBG("ModSubVaDel"); + elem_addr = net_buf_simple_pull_le16(buf); if (!BLE_MESH_ADDR_IS_UNICAST(elem_addr)) { BT_ERR("Prohibited element address 0x%04x", elem_addr); @@ -2040,12 +2175,13 @@ static void mod_sub_va_del(struct bt_mesh_model *model, label_uuid = net_buf_simple_pull_mem(buf, 16); - BT_DBG("elem_addr 0x%04x", elem_addr); + BT_DBG("ElemAddr 0x%04x", elem_addr); mod_id = buf->data; elem = bt_mesh_elem_find(elem_addr); if (!elem) { + BT_DBG("StatusInvalidAddress"); mod = NULL; vnd = (buf->len == 4U); sub_addr = BLE_MESH_ADDR_UNASSIGNED; @@ -2055,6 +2191,7 @@ static void mod_sub_va_del(struct bt_mesh_model *model, mod = get_model(elem, buf, &vnd); if (!mod) { + BT_DBG("StatusInvalidModel"); sub_addr = BLE_MESH_ADDR_UNASSIGNED; status = STATUS_INVALID_MODEL; goto send_status; @@ -2079,12 +2216,12 @@ static void mod_sub_va_del(struct bt_mesh_model *model, status = STATUS_SUCCESS; } else { + BT_DBG("StatusCannotRemove"); status = STATUS_CANNOT_REMOVE; } send_status: - send_mod_sub_status(model, ctx, status, elem_addr, sub_addr, - mod_id, vnd); + send_mod_sub_status(model, ctx, status, elem_addr, sub_addr, mod_id, vnd); } static void mod_sub_va_overwrite(struct bt_mesh_model *model, @@ -2099,6 +2236,8 @@ static void mod_sub_va_overwrite(struct bt_mesh_model *model, uint8_t status = 0U; bool vnd = false; + BT_DBG("ModSubVaOverwrite"); + elem_addr = net_buf_simple_pull_le16(buf); if (!BLE_MESH_ADDR_IS_UNICAST(elem_addr)) { BT_ERR("Prohibited element address 0x%04x", elem_addr); @@ -2107,12 +2246,13 @@ static void mod_sub_va_overwrite(struct bt_mesh_model *model, label_uuid = net_buf_simple_pull_mem(buf, 16); - BT_DBG("elem_addr 0x%04x", elem_addr); + BT_DBG("ElemAddr 0x%04x", elem_addr); mod_id = buf->data; elem = bt_mesh_elem_find(elem_addr); if (!elem) { + BT_DBG("StatusInvalidAddress"); mod = NULL; vnd = (buf->len == 4U); status = STATUS_INVALID_ADDRESS; @@ -2121,6 +2261,7 @@ static void mod_sub_va_overwrite(struct bt_mesh_model *model, mod = get_model(elem, buf, &vnd); if (!mod) { + BT_DBG("StatusInvalidModel"); status = STATUS_INVALID_MODEL; goto send_status; } @@ -2145,14 +2286,14 @@ static void mod_sub_va_overwrite(struct bt_mesh_model *model, } } } else { + BT_DBG("StatusInsuffResources"); status = STATUS_INSUFF_RESOURCES; } send_status: - send_mod_sub_status(model, ctx, status, elem_addr, sub_addr, - mod_id, vnd); + send_mod_sub_status(model, ctx, status, elem_addr, sub_addr, mod_id, vnd); } -#else +#else /* CONFIG_BLE_MESH_LABEL_COUNT > 0 */ static void mod_sub_va_add(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) @@ -2164,6 +2305,8 @@ static void mod_sub_va_add(struct bt_mesh_model *model, uint8_t status = 0U; bool vnd = false; + BT_DBG("ModSubVaAdd"); + elem_addr = net_buf_simple_pull_le16(buf); if (!BLE_MESH_ADDR_IS_UNICAST(elem_addr)) { BT_ERR("Prohibited element address 0x%04x", elem_addr); @@ -2176,6 +2319,7 @@ static void mod_sub_va_add(struct bt_mesh_model *model, elem = bt_mesh_elem_find(elem_addr); if (!elem) { + BT_DBG("StatusInvalidAddress"); mod = NULL; vnd = (buf->len == 4U); status = STATUS_INVALID_ADDRESS; @@ -2184,10 +2328,12 @@ static void mod_sub_va_add(struct bt_mesh_model *model, mod = get_model(elem, buf, &vnd); if (!mod) { + BT_DBG("StatusInvalidModel"); status = STATUS_INVALID_MODEL; goto send_status; } + BT_DBG("StatusInsuffResources"); status = STATUS_INSUFF_RESOURCES; send_status: @@ -2205,6 +2351,8 @@ static void mod_sub_va_del(struct bt_mesh_model *model, uint8_t status = 0U; bool vnd = false; + BT_DBG("ModSubVaDel"); + elem_addr = net_buf_simple_pull_le16(buf); if (!BLE_MESH_ADDR_IS_UNICAST(elem_addr)) { BT_ERR("Prohibited element address 0x%04x", elem_addr); @@ -2217,16 +2365,19 @@ static void mod_sub_va_del(struct bt_mesh_model *model, elem = bt_mesh_elem_find(elem_addr); if (!elem) { + BT_DBG("StatusInvalidAddress"); vnd = (buf->len == 4U); status = STATUS_INVALID_ADDRESS; goto send_status; } if (!get_model(elem, buf, &vnd)) { + BT_DBG("StatusInvalidModel"); status = STATUS_INVALID_MODEL; goto send_status; } + BT_DBG("StatusInsuffResources"); status = STATUS_INSUFF_RESOURCES; send_status: @@ -2244,6 +2395,8 @@ static void mod_sub_va_overwrite(struct bt_mesh_model *model, uint8_t status = 0U; bool vnd = false; + BT_DBG("ModSubVaOverwrite"); + elem_addr = net_buf_simple_pull_le16(buf); if (!BLE_MESH_ADDR_IS_UNICAST(elem_addr)) { BT_ERR("Prohibited element address 0x%04x", elem_addr); @@ -2256,16 +2409,19 @@ static void mod_sub_va_overwrite(struct bt_mesh_model *model, elem = bt_mesh_elem_find(elem_addr); if (!elem) { + BT_DBG("StatusInvalidAddress"); vnd = (buf->len == 4U); status = STATUS_INVALID_ADDRESS; goto send_status; } if (!get_model(elem, buf, &vnd)) { + BT_DBG("StatusInvalidModel"); status = STATUS_INVALID_MODEL; goto send_status; } + BT_DBG("StatusInsuffResources"); status = STATUS_INSUFF_RESOURCES; send_status: @@ -2280,6 +2436,8 @@ static void send_net_key_status(struct bt_mesh_model *model, { BLE_MESH_MODEL_BUF_DEFINE(msg, OP_NET_KEY_STATUS, 3); + BT_DBG("SendNetKeyStatus"); + bt_mesh_model_msg_init(&msg, OP_NET_KEY_STATUS); net_buf_simple_add_u8(&msg, status); @@ -2298,13 +2456,15 @@ static void net_key_add(struct bt_mesh_model *model, uint16_t idx = 0U; int err = 0; + BT_DBG("NetKeyAdd"); + idx = net_buf_simple_pull_le16(buf); if (idx > 0xfff) { BT_ERR("Invalid NetKeyIndex 0x%04x", idx); return; } - BT_DBG("idx 0x%04x", idx); + BT_DBG("NetIdx 0x%04x", idx); sub = bt_mesh_subnet_get(idx); if (!sub) { @@ -2318,8 +2478,8 @@ static void net_key_add(struct bt_mesh_model *model, } if (!sub) { - send_net_key_status(model, ctx, idx, - STATUS_INSUFF_RESOURCES); + BT_DBG("StatusInsuffResources"); + send_net_key_status(model, ctx, idx, STATUS_INSUFF_RESOURCES); return; } } @@ -2329,6 +2489,7 @@ static void net_key_add(struct bt_mesh_model *model, uint8_t status = 0U; if (memcmp(buf->data, sub->keys[0].net, 16)) { + BT_DBG("StatusIdxAlreadyStored"); status = STATUS_IDX_ALREADY_STORED; } else { status = STATUS_SUCCESS; @@ -2340,6 +2501,7 @@ static void net_key_add(struct bt_mesh_model *model, err = bt_mesh_net_keys_create(&sub->keys[0], buf->data); if (err) { + BT_DBG("StatusUnspecified"); send_net_key_status(model, ctx, idx, STATUS_UNSPECIFIED); return; } @@ -2347,7 +2509,6 @@ static void net_key_add(struct bt_mesh_model *model, sub->net_idx = idx; if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) { - BT_DBG("Storing NetKey persistently"); bt_mesh_store_subnet(sub); } @@ -2368,7 +2529,7 @@ static void net_key_add(struct bt_mesh_model *model, if (sub->directed_proxy != BLE_MESH_DIRECTED_PROXY_NOT_SUPPORTED) { bt_mesh_directed_proxy_server_directed_proxy_caps_send(sub, false); } -#endif +#endif /* CONFIG_BLE_MESH_DF_SRV && CONFIG_BLE_MESH_SUPPORT_DIRECTED_PROXY */ bt_mesh_adv_update(); } else { @@ -2381,7 +2542,7 @@ static void net_key_add(struct bt_mesh_model *model, if (bt_mesh_directed_forwarding_sub_init(sub)) { BT_ERR("Failed to init subnet for directed forward"); } -#endif +#endif /* CONFIG_BLE_MESH_DF_SRV */ bt_mesh_cfg_server_state_change_t change = {0}; change.cfg_netkey_add.net_idx = sub->net_idx; @@ -2398,16 +2559,19 @@ static void net_key_update(struct bt_mesh_model *model, uint16_t idx = 0U; int err = 0; + BT_DBG("NetKeyUpdate"); + idx = net_buf_simple_pull_le16(buf); if (idx > 0xfff) { BT_ERR("Invalid NetKeyIndex 0x%04x", idx); return; } - BT_DBG("idx 0x%04x", idx); + BT_DBG("NetIdx 0x%04x", idx); sub = bt_mesh_subnet_get(idx); if (!sub) { + BT_DBG("StatusInvalidNetKey"); send_net_key_status(model, ctx, idx, STATUS_INVALID_NETKEY); return; } @@ -2432,6 +2596,7 @@ static void net_key_update(struct bt_mesh_model *model, /* fall through */ case BLE_MESH_KR_PHASE_2: case BLE_MESH_KR_PHASE_3: + BT_DBG("StatusCannotUpdate"); send_net_key_status(model, ctx, idx, STATUS_CANNOT_UPDATE); return; } @@ -2443,6 +2608,7 @@ static void net_key_update(struct bt_mesh_model *model, } if (err) { + BT_DBG("StatusUnspecified"); send_net_key_status(model, ctx, idx, STATUS_UNSPECIFIED); return; } @@ -2450,7 +2616,6 @@ static void net_key_update(struct bt_mesh_model *model, sub->kr_phase = BLE_MESH_KR_PHASE_1; if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) { - BT_DBG("Storing NetKey persistently"); bt_mesh_store_subnet(sub); } @@ -2467,6 +2632,8 @@ static void net_key_update(struct bt_mesh_model *model, static void hb_pub_disable(struct bt_mesh_cfg_srv *cfg) { + BT_DBG("HbPubDisable"); + cfg->hb_pub.dst = BLE_MESH_ADDR_UNASSIGNED; cfg->hb_pub.count = 0U; cfg->hb_pub.ttl = 0U; @@ -2483,13 +2650,15 @@ static void net_key_del(struct bt_mesh_model *model, uint16_t del_idx = 0U; uint8_t status = 0U; + BT_DBG("NetKeyDel"); + del_idx = net_buf_simple_pull_le16(buf); if (del_idx > 0xfff) { BT_ERR("Invalid NetKeyIndex 0x%04x", del_idx); return; } - BT_DBG("idx 0x%04x", del_idx); + BT_DBG("NetIdx 0x%04x", del_idx); sub = bt_mesh_subnet_get(del_idx); if (!sub) { @@ -2504,6 +2673,7 @@ static void net_key_del(struct bt_mesh_model *model, * The NetKey List must contain a minimum of one NetKey. */ if (ctx->net_idx == del_idx) { + BT_DBG("StatusCannotRemove"); status = STATUS_CANNOT_REMOVE; goto send_status; } @@ -2525,8 +2695,8 @@ static void net_key_del(struct bt_mesh_model *model, #if CONFIG_BLE_MESH_SETTINGS bt_mesh_clear_directed_forwarding_table_data(del_idx); -#endif -#endif +#endif /* CONFIG_BLE_MESH_SETTINGS */ +#endif /* CONFIG_BLE_MESH_DF_SRV && CONFIG_BLE_MESH_SUPPORT_DIRECTED_PROXY */ bt_mesh_subnet_del(sub, true); status = STATUS_SUCCESS; @@ -2540,11 +2710,11 @@ static void net_key_del(struct bt_mesh_model *model, * Index of the deleted NetKey are removed. */ bt_mesh_delete_netkey_in_bridge_table(del_idx); -#endif /* CONFIG_BLE_MESH_BRC_SRV */ +#endif /* CONFIG_BLE_MESH_BRC_SRV */ #if CONFIG_BLE_MESH_RPR_SRV bt_mesh_rpr_srv_netkey_del(del_idx); -#endif +#endif /* CONFIG_BLE_MESH_RPR_SRV */ send_status: send_net_key_status(model, ctx, del_idx, status); @@ -2565,6 +2735,8 @@ static void net_key_get(struct bt_mesh_model *model, IDX_LEN(CONFIG_BLE_MESH_SUBNET_COUNT)); uint16_t prev = 0U, i = 0U; + BT_DBG("NetKeyGet"); + bt_mesh_model_msg_init(&msg, OP_NET_KEY_LIST); prev = BLE_MESH_KEY_UNUSED; @@ -2602,9 +2774,10 @@ static void node_identity_get(struct bt_mesh_model *model, uint8_t node_id = 0U; uint16_t idx = 0U; - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, - bt_hex(buf->data, buf->len)); + BT_DBG("NodeIdentityGet"); + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", + ctx->net_idx, ctx->app_idx, ctx->addr); + BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); idx = net_buf_simple_pull_le16(buf); if (idx > 0xfff) { @@ -2616,6 +2789,7 @@ static void node_identity_get(struct bt_mesh_model *model, sub = bt_mesh_subnet_get(idx); if (!sub) { + BT_DBG("StatusInvalidNetKey"); net_buf_simple_add_u8(&msg, STATUS_INVALID_NETKEY); node_id = 0x00; } else { @@ -2640,9 +2814,10 @@ static void node_identity_set(struct bt_mesh_model *model, uint8_t node_id = 0U; uint16_t idx = 0U; - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, - bt_hex(buf->data, buf->len)); + BT_DBG("NodeIdentitySet"); + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", + ctx->net_idx, ctx->app_idx, ctx->addr); + BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); idx = net_buf_simple_pull_le16(buf); if (idx > 0xfff) { @@ -2660,6 +2835,7 @@ static void node_identity_set(struct bt_mesh_model *model, sub = bt_mesh_subnet_get(idx); if (!sub) { + BT_DBG("StatusInvalidNetKey"); net_buf_simple_add_u8(&msg, STATUS_INVALID_NETKEY); net_buf_simple_add_le16(&msg, idx); net_buf_simple_add_u8(&msg, node_id); @@ -2672,7 +2848,8 @@ static void node_identity_set(struct bt_mesh_model *model, * Identity state shall be Disable (0x00). */ bt_mesh_proxy_private_identity_disable(); -#endif +#endif /* CONFIG_BLE_MESH_PRB_SRV */ + bt_mesh_proxy_server_identity_start(sub); } else { bt_mesh_proxy_server_identity_stop(sub); @@ -2697,6 +2874,10 @@ static void create_mod_app_status(struct net_buf_simple *msg, { bt_mesh_model_msg_init(msg, OP_MOD_APP_STATUS); + BT_DBG("CreateModAppStatus"); + BT_DBG("ElemAddr 0x%04x AppIdx 0x%04x Status 0x%02x Vnd %u", + elem_addr, app_idx, status, vnd); + net_buf_simple_add_u8(msg, status); net_buf_simple_add_le16(msg, elem_addr); net_buf_simple_add_le16(msg, app_idx); @@ -2719,6 +2900,8 @@ static void mod_app_bind(struct bt_mesh_model *model, uint8_t *mod_id = NULL, status = 0U; bool vnd = false; + BT_DBG("ModAppBind"); + elem_addr = net_buf_simple_pull_le16(buf); if (!BLE_MESH_ADDR_IS_UNICAST(elem_addr)) { BT_ERR("Prohibited element address 0x%04x", elem_addr); @@ -2730,6 +2913,7 @@ static void mod_app_bind(struct bt_mesh_model *model, elem = bt_mesh_elem_find(elem_addr); if (!elem) { + BT_DBG("StatusInvalidAddress"); mod = NULL; vnd = (buf->len == 4U); status = STATUS_INVALID_ADDRESS; @@ -2738,24 +2922,24 @@ static void mod_app_bind(struct bt_mesh_model *model, mod = get_model(elem, buf, &vnd); if (!mod) { + BT_DBG("StatusInvalidModel"); status = STATUS_INVALID_MODEL; goto send_status; } /* Configuration Server only allows device key based access */ if (model == mod) { - BT_ERR("Client tried to bind AppKey to Configuration Model"); + BT_ERR("StatusCannotBind"); status = STATUS_CANNOT_BIND; goto send_status; } status = mod_bind(mod, key_app_idx); - BT_INFO("bind app key %#x on mode %#x", key_app_idx, mod->id); + BT_INFO("AppIdx 0x%04x ID 0x%04x", key_app_idx, mod->id); + send_status: - BT_DBG("status 0x%02x", status); - create_mod_app_status(&msg, mod, vnd, elem_addr, key_app_idx, status, - mod_id); + create_mod_app_status(&msg, mod, vnd, elem_addr, key_app_idx, status, mod_id); if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) { BT_ERR("Unable to send Config Model App Bind Status"); @@ -2783,6 +2967,8 @@ static void mod_app_unbind(struct bt_mesh_model *model, uint8_t *mod_id = NULL, status = 0U; bool vnd = false; + BT_DBG("ModAppUnbind"); + elem_addr = net_buf_simple_pull_le16(buf); if (!BLE_MESH_ADDR_IS_UNICAST(elem_addr)) { BT_ERR("Prohibited element address 0x%04x", elem_addr); @@ -2794,6 +2980,7 @@ static void mod_app_unbind(struct bt_mesh_model *model, elem = bt_mesh_elem_find(elem_addr); if (!elem) { + BT_DBG("StatusInvalidAddress"); mod = NULL; vnd = (buf->len == 4U); status = STATUS_INVALID_ADDRESS; @@ -2802,6 +2989,7 @@ static void mod_app_unbind(struct bt_mesh_model *model, mod = get_model(elem, buf, &vnd); if (!mod) { + BT_DBG("StatusInvalidModel"); status = STATUS_INVALID_MODEL; goto send_status; } @@ -2809,9 +2997,7 @@ static void mod_app_unbind(struct bt_mesh_model *model, status = mod_unbind(mod, key_app_idx, true); send_status: - BT_DBG("status 0x%02x", status); - create_mod_app_status(&msg, mod, vnd, elem_addr, key_app_idx, status, - mod_id); + create_mod_app_status(&msg, mod, vnd, elem_addr, key_app_idx, status, mod_id); if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) { BT_ERR("Unable to send Config Model App Unbind Status"); @@ -2828,23 +3014,22 @@ send_status: } } -#define KEY_LIST_LEN (CONFIG_BLE_MESH_MODEL_KEY_COUNT * 2) +#define KEY_LIST_LEN (CONFIG_BLE_MESH_MODEL_KEY_COUNT * 2) static void mod_app_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - NET_BUF_SIMPLE_DEFINE(msg, - MAX(BLE_MESH_MODEL_BUF_LEN(OP_VND_MOD_APP_LIST, - 9 + KEY_LIST_LEN), - BLE_MESH_MODEL_BUF_LEN(OP_SIG_MOD_APP_LIST, - 9 + KEY_LIST_LEN))); + NET_BUF_SIMPLE_DEFINE(msg, MAX(BLE_MESH_MODEL_BUF_LEN(OP_VND_MOD_APP_LIST, 9 + KEY_LIST_LEN), + BLE_MESH_MODEL_BUF_LEN(OP_SIG_MOD_APP_LIST, 9 + KEY_LIST_LEN))); struct bt_mesh_model *mod = NULL; struct bt_mesh_elem *elem = NULL; uint8_t *mod_id = NULL, status = 0U; uint16_t elem_addr = 0U; bool vnd = false; + BT_DBG("ModAppGet"); + elem_addr = net_buf_simple_pull_le16(buf); if (!BLE_MESH_ADDR_IS_UNICAST(elem_addr)) { BT_ERR("Prohibited element address 0x%04x", elem_addr); @@ -2853,10 +3038,11 @@ static void mod_app_get(struct bt_mesh_model *model, mod_id = buf->data; - BT_DBG("elem_addr 0x%04x", elem_addr); + BT_DBG("ElemAddr 0x%04x", elem_addr); elem = bt_mesh_elem_find(elem_addr); if (!elem) { + BT_DBG("StatusInvalidAddress"); mod = NULL; vnd = (buf->len == 4U); status = STATUS_INVALID_ADDRESS; @@ -2865,6 +3051,7 @@ static void mod_app_get(struct bt_mesh_model *model, mod = get_model(elem, buf, &vnd); if (!mod) { + BT_DBG("StatusInvalidModel"); status = STATUS_INVALID_MODEL; goto send_list; } @@ -2908,15 +3095,15 @@ static void node_reset(struct bt_mesh_model *model, { BLE_MESH_MODEL_BUF_DEFINE(msg, OP_NODE_RESET_STATUS, 0); - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, - bt_hex(buf->data, buf->len)); - + BT_DBG("NodeReset"); + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", + ctx->net_idx, ctx->app_idx, ctx->addr); + BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); bt_mesh_model_msg_init(&msg, OP_NODE_RESET_STATUS); - /* Send the response first since we won't have any keys left to - * send it later. + /* Send the response first since we won't have any keys + * left to send it later. */ if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) { BT_ERR("Unable to send Config Node Reset Status"); @@ -2933,6 +3120,8 @@ static void send_friend_status(struct bt_mesh_model *model, BLE_MESH_MODEL_BUF_DEFINE(msg, OP_FRIEND_STATUS, 1); struct bt_mesh_cfg_srv *cfg = model->user_data; + BT_DBG("SendFrndStatus"); + bt_mesh_model_msg_init(&msg, OP_FRIEND_STATUS); net_buf_simple_add_u8(&msg, cfg->frnd); @@ -2945,9 +3134,10 @@ static void friend_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, - bt_hex(buf->data, buf->len)); + BT_DBG("FrndGet"); + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", + ctx->net_idx, ctx->app_idx, ctx->addr); + BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); send_friend_status(model, ctx); } @@ -2958,9 +3148,10 @@ static void friend_set(struct bt_mesh_model *model, { struct bt_mesh_cfg_srv *cfg = model->user_data; - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, - bt_hex(buf->data, buf->len)); + BT_DBG("FrndSet"); + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", + ctx->net_idx, ctx->app_idx, ctx->addr); + BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); if (buf->data[0] != 0x00 && buf->data[0] != 0x01) { BT_WARN("Invalid Friend value 0x%02x", buf->data[0]); @@ -2972,7 +3163,7 @@ static void friend_set(struct bt_mesh_model *model, goto send_status; } - BT_DBG("Friend 0x%02x -> 0x%02x", cfg->frnd, buf->data[0]); + BT_DBG("Frnd 0x%02x -> 0x%02x", cfg->frnd, buf->data[0]); if (cfg->frnd == buf->data[0]) { goto send_status; @@ -2993,7 +3184,7 @@ static void friend_set(struct bt_mesh_model *model, * then the value of the directed friend state shall be 0x00. */ bt_mesh_disable_directed_friend_state(ctx->net_idx); -#endif +#endif /* CONFIG_BLE_MESH_DF_SRV && CONFIG_BLE_MESH_FRIEND */ } } @@ -3016,7 +3207,8 @@ static void lpn_timeout_get(struct bt_mesh_model *model, lpn_addr = net_buf_simple_pull_le16(buf); - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x lpn_addr 0x%02x", + BT_DBG("LPNTimeoutGet"); + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x LPN 0x%04x", ctx->net_idx, ctx->app_idx, ctx->addr, lpn_addr); if (!BLE_MESH_ADDR_IS_UNICAST(lpn_addr)) { @@ -3054,6 +3246,8 @@ static void send_krp_status(struct bt_mesh_model *model, { BLE_MESH_MODEL_BUF_DEFINE(msg, OP_KRP_STATUS, 4); + BT_DBG("SendKrpStatus"); + bt_mesh_model_msg_init(&msg, OP_KRP_STATUS); net_buf_simple_add_u8(&msg, status); @@ -3071,20 +3265,22 @@ static void krp_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct bt_mesh_subnet *sub = NULL; uint16_t idx = 0U; + BT_DBG("KrpGet"); + idx = net_buf_simple_pull_le16(buf); if (idx > 0xfff) { BT_ERR("Invalid NetKeyIndex 0x%04x", idx); return; } - BT_DBG("idx 0x%04x", idx); + BT_DBG("NetIdx 0x%04x", idx); sub = bt_mesh_subnet_get(idx); if (!sub) { + BT_DBG("StatusInvalidNetKey"); send_krp_status(model, ctx, idx, 0x00, STATUS_INVALID_NETKEY); } else { - send_krp_status(model, ctx, idx, sub->kr_phase, - STATUS_SUCCESS); + send_krp_status(model, ctx, idx, sub->kr_phase, STATUS_SUCCESS); } } @@ -3095,6 +3291,8 @@ static void krp_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, uint8_t phase = 0U; uint16_t idx = 0U; + BT_DBG("KrpSet"); + idx = net_buf_simple_pull_le16(buf); phase = net_buf_simple_pull_u8(buf); @@ -3103,15 +3301,16 @@ static void krp_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, return; } - BT_DBG("idx 0x%04x transition 0x%02x", idx, phase); + BT_DBG("NetIdx 0x%04x Phase 0x%02x", idx, phase); sub = bt_mesh_subnet_get(idx); if (!sub) { + BT_DBG("StatusInvalidNetKey"); send_krp_status(model, ctx, idx, 0x00, STATUS_INVALID_NETKEY); return; } - BT_DBG("%u -> %u", sub->kr_phase, phase); + BT_DBG("KrPhase %u -> %u", sub->kr_phase, phase); if (phase < BLE_MESH_KR_PHASE_2 || phase > BLE_MESH_KR_PHASE_3 || (sub->kr_phase == BLE_MESH_KR_NORMAL && @@ -3126,7 +3325,6 @@ static void krp_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, sub->kr_flag = 1; if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) { - BT_DBG("Storing kr phase persistently"); bt_mesh_store_subnet(sub); } @@ -3157,6 +3355,8 @@ static void krp_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, static uint8_t hb_log(uint16_t val) { + BT_DBG("HbLog, Val 0x%04x", val); + switch (val) { case 0x0000: return 0x00; @@ -3169,6 +3369,8 @@ static uint8_t hb_log(uint16_t val) static uint8_t hb_pub_count_log(uint16_t val) { + BT_DBG("HbPubCountLog, Val 0x%04x", val); + switch (val) { case 0x0000: return 0x00; @@ -3183,6 +3385,8 @@ static uint8_t hb_pub_count_log(uint16_t val) static uint16_t hb_pwr2(uint8_t val, uint8_t sub) { + BT_DBG("HbPwr2, Val 0x%02x Sub 0x%02x", val, sub); + switch (val) { case 0x00: return 0x0000; @@ -3210,7 +3414,7 @@ static void hb_pub_send_status(struct bt_mesh_model *model, BLE_MESH_MODEL_BUF_DEFINE(msg, OP_HEARTBEAT_PUB_STATUS, 10); struct bt_mesh_cfg_srv *cfg = model->user_data; - BT_DBG("src 0x%04x status 0x%02x", ctx->addr, status); + BT_DBG("HbPubSendStatus, Src 0x%04x Status 0x%02x", ctx->addr, status); bt_mesh_model_msg_init(&msg, OP_HEARTBEAT_PUB_STATUS); @@ -3239,7 +3443,7 @@ static void heartbeat_pub_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - BT_DBG("src 0x%04x", ctx->addr); + BT_DBG("HeartbeatPubGet, Src 0x%04x", ctx->addr); hb_pub_send_status(model, ctx, STATUS_SUCCESS, NULL); } @@ -3253,27 +3457,30 @@ static void heartbeat_pub_set(struct bt_mesh_model *model, uint16_t dst = 0U, feat = 0U, idx = 0U; uint8_t status = 0U; - BT_DBG("src 0x%04x", ctx->addr); + BT_DBG("HeartbeatPubSet, Src 0x%04x", ctx->addr); dst = sys_le16_to_cpu(param->dst); /* All other address types but virtual are valid */ if (BLE_MESH_ADDR_IS_VIRTUAL(dst)) { + BT_DBG("StatusInvalidAddress"); status = STATUS_INVALID_ADDRESS; goto failed; } if (param->count_log > 0x11 && param->count_log != 0xff) { + BT_DBG("StatusCannotSet"); status = STATUS_CANNOT_SET; goto failed; } if (param->period_log > 0x11) { + BT_DBG("StatusCannotSet"); status = STATUS_CANNOT_SET; goto failed; } if (param->ttl > BLE_MESH_TTL_MAX && param->ttl != BLE_MESH_TTL_DEFAULT) { - BT_ERR("Invalid TTL value 0x%02x", param->ttl); + BT_ERR("InvalidTTL %u", param->ttl); return; } @@ -3281,11 +3488,12 @@ static void heartbeat_pub_set(struct bt_mesh_model *model, idx = sys_le16_to_cpu(param->net_idx); if (idx > 0xfff) { - BT_ERR("Invalid NetKeyIndex 0x%04x", idx); + BT_ERR("InvalidNetIdx 0x%04x", idx); return; } if (!bt_mesh_subnet_get(idx)) { + BT_DBG("StatusInvalidNetKey"); status = STATUS_INVALID_NETKEY; goto failed; } @@ -3302,7 +3510,7 @@ static void heartbeat_pub_set(struct bt_mesh_model *model, cfg->hb_pub.count = hb_pwr2(param->count_log, 1); cfg->hb_pub.ttl = param->ttl; - BT_DBG("period %u ms", hb_pwr2(param->period_log, 1) * 1000U); + BT_DBG("Period %u", hb_pwr2(param->period_log, 1) * 1000U); /* Note: Send heartbeat message here will cause wrong heartbeat status message */ #if 0 @@ -3343,14 +3551,15 @@ failed: } static void hb_sub_send_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, uint8_t status) + struct bt_mesh_msg_ctx *ctx, + uint8_t status) { BLE_MESH_MODEL_BUF_DEFINE(msg, OP_HEARTBEAT_SUB_STATUS, 9); struct bt_mesh_cfg_srv *cfg = model->user_data; uint16_t period = 0U; int64_t uptime = 0; - BT_DBG("src 0x%04x status 0x%02x", ctx->addr, status); + BT_DBG("HbSubSendStatus, Src 0x%04x Status 0x%02x", ctx->addr, status); uptime = k_uptime_get(); if (uptime > cfg->hb_sub.expiry) { @@ -3378,7 +3587,7 @@ static void heartbeat_sub_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { - BT_DBG("src 0x%04x", ctx->addr); + BT_DBG("HeartbeatSubGet, Src 0x%04x", ctx->addr); hb_sub_send_status(model, ctx, STATUS_SUCCESS); } @@ -3392,13 +3601,13 @@ static void heartbeat_sub_set(struct bt_mesh_model *model, uint8_t sub_period = 0U; int32_t period_ms = 0; - BT_DBG("src 0x%04x", ctx->addr); + BT_DBG("HeartbeatSubSet, Src 0x%04x", ctx->addr); sub_src = net_buf_simple_pull_le16(buf); sub_dst = net_buf_simple_pull_le16(buf); sub_period = net_buf_simple_pull_u8(buf); - BT_DBG("sub_src 0x%04x sub_dst 0x%04x period 0x%02x", + BT_DBG("SubSrc 0x%04x SubDst 0x%04x SubPeriod 0x%02x", sub_src, sub_dst, sub_period); if (sub_src != BLE_MESH_ADDR_UNASSIGNED && @@ -3447,7 +3656,7 @@ static void heartbeat_sub_set(struct bt_mesh_model *model, /* Let the transport layer know it needs to handle this address */ bt_mesh_set_hb_sub_dst(cfg->hb_sub.dst); - BT_DBG("period_ms %u", period_ms); + BT_DBG("Period %ld", period_ms); if (period_ms) { cfg->hb_sub.expiry = k_uptime_get() + period_ms; @@ -3529,7 +3738,8 @@ static void hb_publish(struct k_work *work) struct bt_mesh_subnet *sub = NULL; uint16_t period_ms = 0U; - BT_DBG("hb_pub.count: %u", cfg->hb_pub.count); + BT_DBG("HbPublish, NetIdx 0x%04x Count %u", + cfg->hb_pub.net_idx, cfg->hb_pub.count); sub = bt_mesh_subnet_get(cfg->hb_pub.net_idx); if (!sub) { @@ -3557,15 +3767,20 @@ static void hb_publish(struct k_work *work) static bool conf_is_valid(struct bt_mesh_cfg_srv *cfg) { + BT_DBG("ConfIsValid"); + if (cfg->relay > 0x02) { + BT_ERR("InvalidRelay 0x%02x", cfg->relay); return false; } if (cfg->beacon > 0x01) { + BT_ERR("InvalidBeacon 0x%02x", cfg->beacon); return false; } if (cfg->default_ttl > BLE_MESH_TTL_MAX) { + BT_ERR("InvalidDefaultTTL 0x%02x", cfg->default_ttl); return false; } @@ -3591,6 +3806,8 @@ static int cfg_srv_init(struct bt_mesh_model *model) { struct bt_mesh_cfg_srv *cfg = model->user_data; + BT_DBG("CfgSrvInit"); + if (!bt_mesh_model_in_primary(model)) { BT_ERR("Configuration Server only allowed in primary element"); return -EINVAL; @@ -3602,7 +3819,6 @@ static int cfg_srv_init(struct bt_mesh_model *model) } if (!conf_is_valid(cfg)) { - BT_ERR("Invalid values in configuration"); return -EINVAL; } @@ -3637,6 +3853,8 @@ static int cfg_srv_deinit(struct bt_mesh_model *model) { struct bt_mesh_cfg_srv *cfg = model->user_data; + BT_DBG("CfgSrvDeinit"); + if (!bt_mesh_model_in_primary(model)) { BT_ERR("Configuration Server only allowed in primary element"); return -EINVAL; @@ -3682,6 +3900,9 @@ static void mod_reset(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, clear_count = mod_sub_list_clear(mod); + BT_DBG("ModReset, ClearCount %lu Vnd %u Primary %u", + clear_count, vnd, primary); + if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS) && clear_count && store) { bt_mesh_store_mod_sub(mod); } @@ -3689,6 +3910,8 @@ static void mod_reset(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, void bt_mesh_mod_sub_reset(bool store) { + BT_DBG("ModSubReset, Store %u", store); + bt_mesh_model_foreach(mod_reset, &store); } @@ -3697,6 +3920,8 @@ void bt_mesh_cfg_reset(bool store) struct bt_mesh_cfg_srv *cfg = conf; int i; + BT_DBG("CfgReset, Store %u", store); + if (!cfg) { return; } @@ -3725,7 +3950,11 @@ void bt_mesh_cfg_reset(bool store) uint8_t bt_mesh_net_transmit_get(void) { + BT_DBG("NetTransmitGet"); + if (conf) { + BT_DBG("Val 0x%02x", conf->net_transmit); + return conf->net_transmit; } @@ -3734,6 +3963,8 @@ uint8_t bt_mesh_net_transmit_get(void) void bt_mesh_relay_local_set(bool enable) { + BT_DBG("RelayLocalSet, Enable %u", enable); + if (conf && conf->relay != BLE_MESH_RELAY_NOT_SUPPORTED) { if (enable) { conf->relay = BLE_MESH_RELAY_ENABLED; @@ -3745,7 +3976,11 @@ void bt_mesh_relay_local_set(bool enable) uint8_t bt_mesh_relay_get(void) { + BT_DBG("RelayGet"); + if (conf) { + BT_DBG("Val 0x%02x", conf->relay); + return conf->relay; } @@ -3754,8 +3989,11 @@ uint8_t bt_mesh_relay_get(void) uint8_t bt_mesh_friend_get(void) { + BT_DBG("FrndGet"); + if (conf) { - BT_DBG("conf %p conf->frnd 0x%02x", conf, conf->frnd); + BT_DBG("Val 0x%02x", conf->frnd); + return conf->frnd; } @@ -3764,7 +4002,11 @@ uint8_t bt_mesh_friend_get(void) uint8_t bt_mesh_relay_retransmit_get(void) { + BT_DBG("RelayRetransmitGet"); + if (conf) { + BT_DBG("Val 0x%02x", conf->relay_retransmit); + return conf->relay_retransmit; } @@ -3773,7 +4015,11 @@ uint8_t bt_mesh_relay_retransmit_get(void) uint8_t bt_mesh_secure_beacon_get(void) { + BT_DBG("SecureBeaconGet"); + if (conf) { + BT_DBG("Val 0x%02x", conf->beacon); + return conf->beacon; } @@ -3782,7 +4028,11 @@ uint8_t bt_mesh_secure_beacon_get(void) uint8_t bt_mesh_gatt_proxy_get(void) { + BT_DBG("GattProxyGet"); + if (conf) { + BT_DBG("Val 0x%02x", conf->gatt_proxy); + return conf->gatt_proxy; } @@ -3791,7 +4041,11 @@ uint8_t bt_mesh_gatt_proxy_get(void) uint8_t bt_mesh_default_ttl_get(void) { + BT_DBG("DefaultTTLGet"); + if (conf) { + BT_DBG("Val 0x%02x", conf->default_ttl); + return conf->default_ttl; } @@ -3802,7 +4056,7 @@ uint8_t *bt_mesh_label_uuid_get(uint16_t addr) { int i; - BT_DBG("addr 0x%04x", addr); + BT_DBG("LabelUUIDGet, Addr 0x%04x", addr); for (i = 0; i < ARRAY_SIZE(labels); i++) { if (labels[i].addr == addr) { @@ -3819,6 +4073,8 @@ uint8_t *bt_mesh_label_uuid_get(uint16_t addr) struct bt_mesh_hb_pub *bt_mesh_hb_pub_get(void) { + BT_DBG("HbPubGet"); + if (!conf) { return NULL; } @@ -3828,6 +4084,8 @@ struct bt_mesh_hb_pub *bt_mesh_hb_pub_get(void) void bt_mesh_hb_pub_disable(void) { + BT_DBG("HbPubDisable"); + if (conf) { hb_pub_disable(conf); } @@ -3835,6 +4093,8 @@ void bt_mesh_hb_pub_disable(void) struct bt_mesh_cfg_srv *bt_mesh_cfg_get(void) { + BT_DBG("CfgGet, Conf %p", conf); + return conf; } @@ -3842,7 +4102,7 @@ void bt_mesh_subnet_del(struct bt_mesh_subnet *sub, bool store) { int i; - BT_DBG("NetIdx 0x%03x store %u", sub->net_idx, store); + BT_DBG("SubnetDel, NetIdx 0x%04x Store %u", sub->net_idx, store); if (conf && conf->hb_pub.net_idx == sub->net_idx) { hb_pub_disable(conf); diff --git a/components/bt/esp_ble_mesh/core/crypto.c b/components/bt/esp_ble_mesh/core/crypto.c index 2577c65efba..3adba0be1fc 100644 --- a/components/bt/esp_ble_mesh/core/crypto.c +++ b/components/bt/esp_ble_mesh/core/crypto.c @@ -24,9 +24,9 @@ #if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" -#endif +#endif /* CONFIG_BLE_MESH_V11_SUPPORT */ -#define NET_MIC_LEN(pdu) (((pdu)[1] & 0x80) ? 8 : 4) +#define NET_MIC_LEN(pdu) (((pdu)[1] & 0x80) ? 8 : 4) #define APP_MIC_LEN(aszmic) ((aszmic) ? 8 : 4) int bt_mesh_aes_cmac(const uint8_t key[16], struct bt_mesh_sg *sg, @@ -369,10 +369,11 @@ static int bt_mesh_ccm_encrypt(const uint8_t key[16], uint8_t nonce[13], size_t i = 0U, j = 0U; int err = 0; - BT_DBG("key %s", bt_hex(key, 16)); - BT_DBG("nonce %s", bt_hex(nonce, 13)); - BT_DBG("msg (len %u) %s", msg_len, bt_hex(msg, msg_len)); - BT_DBG("aad_len %u mic_size %u", aad_len, mic_size); + BT_DBG("CCMEncrypt"); + BT_DBG("Key %s", bt_hex(key, 16)); + BT_DBG("Nonce %s", bt_hex(nonce, 13)); + BT_DBG("Len %u: %s", msg_len, bt_hex(msg, msg_len)); + BT_DBG("AADLen %u MicSize %u", aad_len, mic_size); /* Unsupported AAD size */ if (aad_len >= 0xff00) { @@ -580,7 +581,7 @@ int bt_mesh_net_obfuscate(uint8_t *pdu, uint32_t iv_index, uint8_t tmp[16] = {0}; int err = 0, i; - BT_DBG("IVIndex %u, PrivacyKey %s", iv_index, bt_hex(privacy_key, 16)); + BT_DBG("IVIndex %lu PrivacyKey %s", iv_index, bt_hex(privacy_key, 16)); sys_put_be32(iv_index, &priv_rand[5]); memcpy(&priv_rand[9], &pdu[7], 7); @@ -589,6 +590,7 @@ int bt_mesh_net_obfuscate(uint8_t *pdu, uint32_t iv_index, err = bt_mesh_encrypt_be(privacy_key, priv_rand, tmp); if (err) { + BT_ERR("NetObfuscateFailed (%d)", err); return err; } @@ -606,9 +608,9 @@ int bt_mesh_net_encrypt(const uint8_t key[16], struct net_buf_simple *buf, uint8_t nonce[13] = {0}; int err = 0; - BT_DBG("IVIndex %u EncKey %s mic_len %u", iv_index, bt_hex(key, 16), - mic_len); - BT_DBG("PDU (len %u) %s", buf->len, bt_hex(buf->data, buf->len)); + BT_DBG("IVIndex %u EncKey %s MicLen %u proxy %u/%u", + iv_index, bt_hex(key, 16), mic_len, proxy, proxy_solic); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); #if CONFIG_BLE_MESH_PROXY if (proxy) { @@ -633,6 +635,8 @@ int bt_mesh_net_encrypt(const uint8_t key[16], struct net_buf_simple *buf, NULL, 0, &buf->data[7], mic_len); if (!err) { net_buf_simple_add(buf, mic_len); + } else { + BT_ERR("NetEncryptFailed (%d)", err); } return err; @@ -643,10 +647,11 @@ int bt_mesh_net_decrypt(const uint8_t key[16], struct net_buf_simple *buf, { uint8_t mic_len = NET_MIC_LEN(buf->data); uint8_t nonce[13] = {0}; + int err; - BT_DBG("PDU (%u bytes) %s", buf->len, bt_hex(buf->data, buf->len)); - BT_DBG("iv_index %u, key %s mic_len %u", iv_index, bt_hex(key, 16), - mic_len); + BT_DBG("IVIndex %u EncKey %s MicLen %u proxy %u/%u", + iv_index, bt_hex(key, 16), mic_len, proxy, proxy_solic); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); #if CONFIG_BLE_MESH_PROXY if (proxy) { @@ -669,8 +674,13 @@ int bt_mesh_net_decrypt(const uint8_t key[16], struct net_buf_simple *buf, buf->len -= mic_len; - return bt_mesh_ccm_decrypt(key, nonce, &buf->data[7], buf->len - 7, - NULL, 0, &buf->data[7], mic_len); + err = bt_mesh_ccm_decrypt(key, nonce, &buf->data[7], buf->len - 7, + NULL, 0, &buf->data[7], mic_len); + if (err) { + BT_ERR("NetDecrypt failed (%d)", err); + } + + return err; } static void create_app_nonce(uint8_t nonce[13], bool dev_key, uint8_t aszmic, @@ -698,14 +708,15 @@ int bt_mesh_app_encrypt(const uint8_t key[16], bool dev_key, uint8_t aszmic, uint8_t nonce[13] = {0}; int err = 0; + BT_DBG("AppEncrypt"); BT_DBG("AppKey %s", bt_hex(key, 16)); - BT_DBG("dev_key %u src 0x%04x dst 0x%04x", dev_key, src, dst); - BT_DBG("seq_num 0x%08x iv_index 0x%08x", seq_num, iv_index); - BT_DBG("Clear: %s", bt_hex(buf->data, buf->len)); + BT_DBG("DevKey %u Src 0x%04x Dst 0x%04x", dev_key, src, dst); + BT_DBG("SeqNum 0x%08lx IVIndex 0x%08lx", seq_num, iv_index); + BT_DBG("Data %u %s", buf->len, bt_hex(buf->data, buf->len)); create_app_nonce(nonce, dev_key, aszmic, src, dst, seq_num, iv_index); - BT_DBG("Nonce %s", bt_hex(nonce, 13)); + BT_DBG("Nonce %s", bt_hex(nonce, 13)); err = bt_mesh_ccm_encrypt(key, nonce, buf->data, buf->len, ad, ad ? 16 : 0, buf->data, APP_MIC_LEN(aszmic)); @@ -725,12 +736,12 @@ int bt_mesh_app_decrypt(const uint8_t key[16], bool dev_key, uint8_t aszmic, uint8_t nonce[13] = {0}; int err = 0; - BT_DBG("EncData (len %u) %s", buf->len, bt_hex(buf->data, buf->len)); + BT_DBG("EncData %u %s", buf->len, bt_hex(buf->data, buf->len)); create_app_nonce(nonce, dev_key, aszmic, src, dst, seq_num, iv_index); BT_DBG("AppKey %s", bt_hex(key, 16)); - BT_DBG("Nonce %s", bt_hex(nonce, 13)); + BT_DBG("Nonce %s", bt_hex(nonce, 13)); err = bt_mesh_ccm_decrypt(key, nonce, buf->data, buf->len, ad, ad ? 16 : 0, out->data, APP_MIC_LEN(aszmic)); diff --git a/components/bt/esp_ble_mesh/core/ext_adv.c b/components/bt/esp_ble_mesh/core/ext_adv.c index 4958e5686db..37000ce73ef 100644 --- a/components/bt/esp_ble_mesh/core/ext_adv.c +++ b/components/bt/esp_ble_mesh/core/ext_adv.c @@ -44,8 +44,8 @@ static int adv_send(struct bt_mesh_adv_inst *inst, uint16_t *adv_duration) uint8_t is_ext_adv = false; #endif - BT_DBG("type %u len %u: %s", BLE_MESH_ADV(buf)->type, - buf->len, bt_hex(buf->data, buf->len)); + BT_DBG("ExtAdvSend, Type %u", BLE_MESH_ADV(buf)->type); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); switch (BLE_MESH_ADV(buf)->type) { #if CONFIG_BLE_MESH_EXT_ADV @@ -65,13 +65,13 @@ static int adv_send(struct bt_mesh_adv_inst *inst, uint16_t *adv_duration) case BLE_MESH_ADV_DATA: #if CONFIG_BLE_MESH_FRIEND case BLE_MESH_ADV_FRIEND: -#endif +#endif /* CONFIG_BLE_MESH_FRIEND */ #if CONFIG_BLE_MESH_RELAY_ADV_BUF case BLE_MESH_ADV_RELAY_DATA: -#endif +#endif /* CONFIG_BLE_MESH_RELAY_ADV_BUF */ #if CONFIG_BLE_MESH_PROXY_SOLIC_PDU_TX case BLE_MESH_ADV_PROXY_SOLIC: -#endif +#endif /* CONFIG_BLE_MESH_PROXY_SOLIC_PDU_TX */ case BLE_MESH_ADV_BEACON: case BLE_MESH_ADV_URI: { #if CONFIG_BLE_MESH_EXT_ADV @@ -127,19 +127,23 @@ static int adv_send(struct bt_mesh_adv_inst *inst, uint16_t *adv_duration) #if CONFIG_BLE_MESH_PROXY_SOLIC_PDU_TX if (BLE_MESH_ADV(buf)->type == BLE_MESH_ADV_PROXY_SOLIC) { bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL); + struct bt_mesh_adv_data solic_ad[2] = { BLE_MESH_ADV_DATA_BYTES(BLE_MESH_DATA_UUID16_ALL, 0x59, 0x18), BLE_MESH_ADV_DATA(BLE_MESH_DATA_SVC_DATA16, buf->data, buf->len), }; - err = bt_le_ext_adv_start(CONFIG_BLE_MESH_ADV_INST_ID, ¶m, solic_ad, ARRAY_SIZE(solic_ad), NULL, 0); + + err = bt_le_ext_adv_start(CONFIG_BLE_MESH_ADV_INST_ID, ¶m, + solic_ad, ARRAY_SIZE(solic_ad), NULL, 0); } else -#endif +#endif /* CONFIG_BLE_MESH_PROXY_SOLIC_PDU_TX */ { bt_mesh_adv_buf_ref_debug(__func__, buf, 4U, BLE_MESH_BUF_REF_SMALL); + err = bt_le_ext_adv_start(inst->id, ¶m, &ad, 1, NULL, 0); } - } break; + #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV case BLE_MESH_ADV_BLE: struct bt_mesh_ble_adv_data data = {0}; @@ -152,8 +156,8 @@ static int adv_send(struct bt_mesh_adv_inst *inst, uint16_t *adv_duration) } BT_DBG("interval %dms, duration %dms, period %dms, count %d", - ADV_SCAN_INT(tx->param.interval), tx->param.duration, - tx->param.period, tx->param.count); + ADV_SCAN_INT(tx->param.interval), tx->param.duration, + tx->param.period, tx->param.count); data.adv_data_len = tx->buf->data[0]; if (data.adv_data_len) { @@ -169,9 +173,10 @@ static int adv_send(struct bt_mesh_adv_inst *inst, uint16_t *adv_duration) err = bt_mesh_ble_ext_adv_start(inst->id, &tx->param, &data); break; -#endif +#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ + default: - BT_ERR("Error Type"); + BT_ERR("InvalidAdvType %u", BLE_MESH_ADV(buf)->type); break; } @@ -182,12 +187,15 @@ static int adv_send(struct bt_mesh_adv_inst *inst, uint16_t *adv_duration) } *adv_duration = duration; + BT_DBG("Advertising started. %u ms", duration); return 0; } static int find_valid_msg_from_queue(bt_mesh_queue_t *msg_queue, bt_mesh_msg_t *msg) { + BT_DBG("FindValidMsgFromQueue"); + while(uxQueueMessagesWaiting(msg_queue->handle)) { xQueueReceive(msg_queue->handle, msg, K_WAIT(K_FOREVER)); @@ -197,11 +205,16 @@ static int find_valid_msg_from_queue(bt_mesh_queue_t *msg_queue, bt_mesh_msg_t * */ assert(msg->arg); + BT_DBG("Buf %p Relay %u Busy %u", + BLE_MESH_MSG_NET_BUF(msg), msg->relay, + !!bt_mesh_atomic_get(&BLE_MESH_ADV_BUSY(BLE_MESH_MSG_NET_BUF(msg)))); + /* If the message is cancelled for advertising, then continue to retrieve the next * message from that queue. */ if (!bt_mesh_atomic_cas(&BLE_MESH_ADV_BUSY(BLE_MESH_MSG_NET_BUF(msg)), 1, 0)) { bt_mesh_adv_buf_ref_debug(__func__, BLE_MESH_MSG_NET_BUF(msg), 1U, BLE_MESH_BUF_REF_EQUAL); + /* Cancel the adv task's reference to this data packet. * Tips: * The reference of buffer by adv_task occurs when the buffer is pushed into @@ -225,11 +238,13 @@ static int find_valid_msg_from_queue(bt_mesh_queue_t *msg_queue, bt_mesh_msg_t * * BLE_MESH_RELAY_TIME_INTERVAL, this relay packet will not be sent. */ BT_DBG("Ignore relay packet"); + net_buf_unref(BLE_MESH_MSG_NET_BUF(msg)); msg->arg = NULL; continue; } -#endif +#endif /* CONFIG_BLE_MESH_RELAY_ADV_BUF */ + break; } @@ -250,14 +265,18 @@ static int activate_idle_adv_instance(uint32_t *update_evts, uint16_t *min_durat uint32_t spt_mask = 0; uint32_t evts = 0; + BT_DBG("ActivateIdleAdvInst"); + #if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ CONFIG_BLE_MESH_GATT_PROXY_SERVER if (!adv_insts[BLE_MESH_ADV_PROXY_INST].busy) { BT_DBG("Mesh Proxy Advertising start"); + duration = bt_mesh_proxy_server_adv_start(); if (duration < cur_min_duration) { cur_min_duration = duration; } + adv_insts[BLE_MESH_ADV_PROXY_INST].busy = true; evts |= ADV_TASK_ADV_INST_EVT(adv_insts[BLE_MESH_ADV_PROXY_INST].id); } @@ -268,10 +287,11 @@ static int activate_idle_adv_instance(uint32_t *update_evts, uint16_t *min_durat if (instance->busy #if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ - CONFIG_BLE_MESH_GATT_PROXY_SERVER - || unlikely(instance->id == CONFIG_BLE_MESH_PROXY_ADV_INST_ID) + CONFIG_BLE_MESH_GATT_PROXY_SERVER + || unlikely(instance->id == CONFIG_BLE_MESH_PROXY_ADV_INST_ID) #endif - ) { + ) { + BT_DBG("AdvInstSkipped, InstID %u Busy %u", instance->id, instance->busy); continue; } @@ -285,13 +305,13 @@ static int activate_idle_adv_instance(uint32_t *update_evts, uint16_t *min_durat /* If no new message in the queue, the *buf (aka: msg.arg) will be empty */ if (find_valid_msg_from_queue(msg_queue, &msg)) { - BT_DBG("no valid message for instance %d", instance->id); + BT_DBG("NoMsgForAdvInst, InstID %u", instance->id); continue; } instance->sending_buf = (struct net_buf *)msg.arg; + if (adv_send(instance, &duration)) { - BT_ERR("adv start failed"); /* When this adv instance fails to broadcast, it could be due to some * persistent issues, such as incorrect adv parameter settings, or it * could be due to some temporary issues, such as memory allocation @@ -301,11 +321,18 @@ static int activate_idle_adv_instance(uint32_t *update_evts, uint16_t *min_durat * instance and attempt to broadcast subsequent data again next time, * rather than disabling the adv instance. */ + BT_ERR("AdvSendFailed, InstID %u AdvType %u SptMask %08lx Buf %p", + instance->id, adv_type, instance->spt_mask, instance->sending_buf); + net_buf_unref(instance->sending_buf); instance->sending_buf = NULL; break; } + BT_DBG("Activate, InstID %u AdvType %u SptMask %08lx Buf %p Duration %u/%u", + instance->id, adv_type, instance->spt_mask, + instance->sending_buf, duration, cur_min_duration); + if (duration < cur_min_duration) { cur_min_duration = duration; } @@ -321,6 +348,9 @@ static int activate_idle_adv_instance(uint32_t *update_evts, uint16_t *min_durat } } + BT_DBG("ActivateEnd, Duration %u UpdateEvts %08lx Evts%08lx", + cur_min_duration, *update_evts, evts); + *min_duration = cur_min_duration; *update_evts |= evts; @@ -329,6 +359,8 @@ static int activate_idle_adv_instance(uint32_t *update_evts, uint16_t *min_durat static uint32_t received_adv_evts_handle(uint32_t recv_evts) { + BT_DBG("RecvAdvEvtsHandle, RecvEvts 0x%08lx", recv_evts); + if (!recv_evts) { return 0; } @@ -338,20 +370,25 @@ static uint32_t received_adv_evts_handle(uint32_t recv_evts) if (recv_evts & evt) { recv_evts &= ~evt; + #if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ -CONFIG_BLE_MESH_GATT_PROXY_SERVER + CONFIG_BLE_MESH_GATT_PROXY_SERVER if (unlikely(i == BLE_MESH_ADV_PROXY_INST)) { BT_DBG("Mesh Proxy Advertising auto stop"); + bt_mesh_proxy_server_adv_flag_set(false); } else #endif { - /* adv_send_end maybe*/ - adv_send_end(0, BLE_MESH_ADV(adv_insts[i].sending_buf)->cb, BLE_MESH_ADV(adv_insts[i].sending_buf)->cb_data); + adv_send_end(0, BLE_MESH_ADV(adv_insts[i].sending_buf)->cb, + BLE_MESH_ADV(adv_insts[i].sending_buf)->cb_data); + bt_mesh_adv_buf_ref_debug(__func__, adv_insts[i].sending_buf, 4U, BLE_MESH_BUF_REF_SMALL); + net_buf_unref(adv_insts[i].sending_buf); adv_insts[i].sending_buf = NULL; } + adv_insts[i].busy = false; } } @@ -365,7 +402,7 @@ static void adv_thread(void *p) uint32_t recv_evts = 0; uint32_t wait_evts = 0; - BT_DBG("%s, starts", __func__); + BT_DBG("ExtAdvThread"); while (1) { adv_duration = K_FOREVER; @@ -375,6 +412,8 @@ static void adv_thread(void *p) bt_mesh_adv_task_wait(wait_evts, adv_duration, &recv_evts); + BT_DBG("WaitEvts %08lx RecvEvts %08lx", wait_evts, recv_evts); + wait_evts &= ~recv_evts; #if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ @@ -400,17 +439,21 @@ static void adv_thread(void *p) recv_evts = received_adv_evts_handle(recv_evts); if (recv_evts) { - BT_ERR("Remain evts %08x to handle", recv_evts); + BT_ERR("RecvEvts %08lx", recv_evts); } } } void bt_mesh_adv_update(void) { + BT_DBG("ExtAdvUpdate"); + #if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ CONFIG_BLE_MESH_GATT_PROXY_SERVER BT_DBG("Mesh Proxy Advertising stopped manually"); + bt_mesh_proxy_server_adv_stop(); + if (adv_insts[BLE_MESH_ADV_PROXY_INST].busy) { bt_mesh_adv_task_wakeup(ADV_TASK_PROXY_ADV_UPD_EVT); } @@ -419,17 +462,19 @@ void bt_mesh_adv_update(void) void bt_mesh_adv_init(void) { + BT_DBG("ExtAdvInit"); + bt_mesh_adv_common_init(); adv_insts = bt_mesh_get_adv_insts_set(); #if CONFIG_BLE_MESH_RELAY_ADV_BUF bt_mesh_relay_adv_init(); -#endif +#endif /* CONFIG_BLE_MESH_RELAY_ADV_BUF */ #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV bt_mesh_ble_adv_init(); -#endif +#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ bt_mesh_adv_task_init(adv_thread); } @@ -437,6 +482,8 @@ void bt_mesh_adv_init(void) #if CONFIG_BLE_MESH_DEINIT void bt_mesh_adv_deinit(void) { + BT_DBG("ExtAdvDeinit"); + bt_mesh_adv_task_deinit(); bt_mesh_adv_common_deinit(); @@ -445,10 +492,10 @@ void bt_mesh_adv_deinit(void) #if CONFIG_BLE_MESH_RELAY_ADV_BUF bt_mesh_relay_adv_deinit(); -#endif +#endif /* CONFIG_BLE_MESH_RELAY_ADV_BUF */ #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV bt_mesh_ble_adv_deinit(); -#endif +#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ } #endif /* CONFIG_BLE_MESH_DEINIT */ diff --git a/components/bt/esp_ble_mesh/core/ext_adv.h b/components/bt/esp_ble_mesh/core/ext_adv.h index 536b0aa4fd1..51118fb5d62 100644 --- a/components/bt/esp_ble_mesh/core/ext_adv.h +++ b/components/bt/esp_ble_mesh/core/ext_adv.h @@ -23,6 +23,7 @@ extern "C" { void bt_mesh_adv_update(void); void bt_mesh_adv_init(void); + void bt_mesh_adv_deinit(void); #ifdef __cplusplus diff --git a/components/bt/esp_ble_mesh/core/fast_prov.c b/components/bt/esp_ble_mesh/core/fast_prov.c index 049a12bb438..5d34db8a091 100644 --- a/components/bt/esp_ble_mesh/core/fast_prov.c +++ b/components/bt/esp_ble_mesh/core/fast_prov.c @@ -27,12 +27,15 @@ const uint8_t *bt_mesh_fast_prov_dev_key_get(uint16_t dst) { const uint8_t *key = NULL; + BT_DBG("FastProvDevKeyGet, Dst 0x%04x", dst); + if (!BLE_MESH_ADDR_IS_UNICAST(dst)) { BT_ERR("Invalid unicast address 0x%04x", dst); return NULL; } if (bt_mesh_is_provisioner_en() == false) { + BT_DBG("NodeDevKey"); return bt_mesh.dev_key; } @@ -42,9 +45,11 @@ const uint8_t *bt_mesh_fast_prov_dev_key_get(uint16_t dst) */ key = bt_mesh_provisioner_dev_key_get(dst); if (key) { + BT_DBG("PvnrDevKey"); return key; } + BT_DBG("NodeDevKeyFinal"); return bt_mesh.dev_key; } @@ -53,9 +58,12 @@ struct bt_mesh_subnet *bt_mesh_fast_prov_subnet_get(uint16_t net_idx) struct bt_mesh_subnet *sub = NULL; int i; + BT_DBG("FastProvSubnetGet, NetIdx 0x%04x", net_idx); + for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) { sub = &bt_mesh.sub[i]; if (sub->net_idx == net_idx) { + BT_DBG("NodeSub"); return sub; } } @@ -63,10 +71,12 @@ struct bt_mesh_subnet *bt_mesh_fast_prov_subnet_get(uint16_t net_idx) for (i = 0; i < ARRAY_SIZE(bt_mesh.p_sub); i++) { sub = bt_mesh.p_sub[i]; if (sub && sub->net_idx == net_idx) { + BT_DBG("PvnrSub"); return sub; } } + BT_DBG("NoSub"); return NULL; } @@ -75,10 +85,13 @@ struct bt_mesh_app_key *bt_mesh_fast_prov_app_key_find(uint16_t app_idx) struct bt_mesh_app_key *key = NULL; int i; + BT_DBG("FastProvAppKeyFind, AppIdx 0x%04x", app_idx); + for (i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) { key = &bt_mesh.app_keys[i]; if (key->net_idx != BLE_MESH_KEY_UNUSED && key->app_idx == app_idx) { + BT_DBG("NodeAppKey"); return key; } } @@ -87,15 +100,19 @@ struct bt_mesh_app_key *bt_mesh_fast_prov_app_key_find(uint16_t app_idx) key = bt_mesh.p_app_keys[i]; if (key && key->net_idx != BLE_MESH_KEY_UNUSED && key->app_idx == app_idx) { + BT_DBG("PvnrAppKey"); return key; } } + BT_DBG("NoAppKey"); return NULL; } uint8_t bt_mesh_set_fast_prov_net_idx(uint16_t net_idx) { + BT_DBG("SetFastProvNetIdx, NetIdx 0x%04x", net_idx); + /* Set net_idx for fast provisioning */ bt_mesh_provisioner_set_fast_prov_net_idx(net_idx); @@ -116,6 +133,8 @@ uint8_t bt_mesh_fast_prov_net_key_add(const uint8_t net_key[16]) net_idx = bt_mesh_provisioner_get_fast_prov_net_idx(); bt_mesh.p_net_idx_next = net_idx; + BT_DBG("FastProvNetKeyAdd, NetIdx 0x%04x", net_idx); + err = bt_mesh_provisioner_local_net_key_add(net_key, &net_idx); if (err) { BT_ERR("Invalid NetKeyIndex 0x%04x", net_idx); @@ -130,12 +149,16 @@ const uint8_t *bt_mesh_fast_prov_net_key_get(uint16_t net_idx) { struct bt_mesh_subnet *sub = NULL; + BT_DBG("FastProvNetKeyGet, NetIdx 0x%04x", net_idx); + sub = bt_mesh_fast_prov_subnet_get(net_idx); if (!sub) { BT_ERR("Invalid NetKeyIndex 0x%04x", net_idx); return NULL; } + BT_DBG("KrFlag %u", sub->kr_flag); + return (sub->kr_flag ? sub->keys[1].net : sub->keys[0].net); } @@ -143,17 +166,23 @@ const uint8_t *bt_mesh_get_fast_prov_app_key(uint16_t net_idx, uint16_t app_idx) { struct bt_mesh_app_key *key = NULL; + BT_DBG("GetFastProvAppKey, NetIdx 0x%04x AppIdx 0x%04x", net_idx, app_idx); + key = bt_mesh_fast_prov_app_key_find(app_idx); if (!key) { BT_ERR("Invalid AppKeyIndex 0x%04x", app_idx); return NULL; } + BT_DBG("KeyUpdated %u", key->updated); + return (key->updated ? key->keys[1].val : key->keys[0].val); } uint8_t bt_mesh_set_fast_prov_action(uint8_t action) { + BT_DBG("SetFastProvAction, Action %u", action); + if (!action || action > ACTION_EXIT) { return 0x01; } @@ -168,9 +197,11 @@ uint8_t bt_mesh_set_fast_prov_action(uint8_t action) if (bt_mesh_secure_beacon_get() == BLE_MESH_SECURE_BEACON_ENABLED) { bt_mesh_secure_beacon_disable(); } + if (IS_ENABLED(CONFIG_BLE_MESH_PB_GATT)) { bt_mesh_proxy_client_prov_enable(); } + bt_mesh_provisioner_set_primary_elem_addr(bt_mesh_primary_addr()); bt_mesh_provisioner_set_prov_bearer(BLE_MESH_PROV_ADV, false); bt_mesh_provisioner_fast_prov_enable(true); @@ -179,11 +210,15 @@ uint8_t bt_mesh_set_fast_prov_action(uint8_t action) if (IS_ENABLED(CONFIG_BLE_MESH_PB_GATT)) { bt_mesh_proxy_client_prov_disable(); } + if (bt_mesh_secure_beacon_get() == BLE_MESH_SECURE_BEACON_ENABLED) { bt_mesh_secure_beacon_enable(); } + bt_mesh_atomic_and(bt_mesh.flags, ~(BIT(BLE_MESH_PROVISIONER) | BIT(BLE_MESH_VALID_PROV))); + bt_mesh_provisioner_fast_prov_enable(false); + if (action == ACTION_EXIT) { bt_mesh_provisioner_remove_node(NULL); } @@ -191,4 +226,5 @@ uint8_t bt_mesh_set_fast_prov_action(uint8_t action) return 0x0; } + #endif /* CONFIG_BLE_MESH_FAST_PROV */ diff --git a/components/bt/esp_ble_mesh/core/foundation.h b/components/bt/esp_ble_mesh/core/foundation.h index 4f3aa79ad11..66f8c5ea2b8 100644 --- a/components/bt/esp_ble_mesh/core/foundation.h +++ b/components/bt/esp_ble_mesh/core/foundation.h @@ -287,6 +287,7 @@ uint8_t bt_mesh_default_ttl_get(void); void bt_mesh_subnet_del(struct bt_mesh_subnet *sub, bool store); struct bt_mesh_app_key *bt_mesh_app_key_alloc(uint16_t app_idx); + void bt_mesh_app_key_del(struct bt_mesh_app_key *key, bool store); static inline void key_idx_pack(struct net_buf_simple *buf, diff --git a/components/bt/esp_ble_mesh/core/friend.c b/components/bt/esp_ble_mesh/core/friend.c index eae9f9471d0..07de4b7d3c8 100644 --- a/components/bt/esp_ble_mesh/core/friend.c +++ b/components/bt/esp_ble_mesh/core/friend.c @@ -69,6 +69,9 @@ static struct bt_mesh_subnet *friend_subnet_get(uint16_t net_idx) static bool is_lpn_unicast(struct bt_mesh_friend *frnd, uint16_t addr) { + BT_INFO("IsLPNUnicast, LPN 0x%04x NumElem %u Addr 0x%04x", + frnd->lpn, frnd->num_elem, addr); + if (frnd->lpn == BLE_MESH_ADDR_UNASSIGNED) { return false; } @@ -81,11 +84,16 @@ struct bt_mesh_friend *bt_mesh_friend_find(uint16_t net_idx, uint16_t lpn_addr, { int i; - BT_DBG("net_idx 0x%04x lpn_addr 0x%04x", net_idx, lpn_addr); + BT_DBG("FrndFind"); + BT_DBG("NetIdx 0x%04x LPN 0x%04x Valid %u Established %u", + net_idx, lpn_addr, valid, established); for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) { struct bt_mesh_friend *frnd = &bt_mesh.frnd[i]; + BT_DBG("%u: LPN 0x%04x NetIdx 0x%04x Valid %u Established %u", + i, frnd->lpn, frnd->net_idx, frnd->valid, frnd->established); + if (valid && !frnd->valid) { continue; } @@ -108,11 +116,15 @@ struct bt_mesh_friend *bt_mesh_friend_find(uint16_t net_idx, uint16_t lpn_addr, static void purge_buffers(sys_slist_t *list) { + BT_DBG("PurgeBuffers"); + while (!sys_slist_is_empty(list)) { struct net_buf *buf = NULL; buf = (void *)sys_slist_get_not_empty(list); + BT_DBG("Buf %p Ref %u", buf, buf->ref); + buf->frags = NULL; buf->flags &= ~NET_BUF_FRAGS; @@ -127,18 +139,21 @@ static void purge_buffers(sys_slist_t *list) */ static int32_t recv_delay(struct bt_mesh_friend *frnd) { + BT_DBG("RecvDelay, LPN 0x%04x RecvWin %u RecvDelay %u", + frnd->lpn, CONFIG_BLE_MESH_FRIEND_RECV_WIN, frnd->recv_delay); + #if CONFIG_BLE_MESH_FRIEND_RECV_WIN > 50 return (int32_t)frnd->recv_delay + (CONFIG_BLE_MESH_FRIEND_RECV_WIN / 5); -#else +#else /* CONFIG_BLE_MESH_FRIEND_RECV_WIN > 50 */ return frnd->recv_delay; -#endif +#endif /* CONFIG_BLE_MESH_FRIEND_RECV_WIN > 50 */ } static void friend_clear(struct bt_mesh_friend *frnd, uint8_t reason) { int i; - BT_DBG("LPN 0x%04x", frnd->lpn); + BT_DBG("FrndClear, LPN 0x%04x Reason 0x%02x", frnd->lpn, reason); k_delayed_work_cancel(&frnd->timer); @@ -160,9 +175,13 @@ static void friend_clear(struct bt_mesh_friend *frnd, uint8_t reason) friend_cred_del(frnd->net_idx, frnd->lpn); if (frnd->last) { + BT_DBG("FrndLast, Buf %p Ref %u PendingBuf %u", + frnd->last, frnd->last->ref, frnd->pending_buf); + /* Cancel the sending if necessary */ if (frnd->pending_buf) { bt_mesh_adv_buf_ref_debug(__func__, frnd->last, 2U, BLE_MESH_BUF_REF_EQUAL); + bt_mesh_atomic_set(&BLE_MESH_ADV_BUSY(frnd->last), 0); } else { bt_mesh_adv_buf_ref_debug(__func__, frnd->last, 1U, BLE_MESH_BUF_REF_EQUAL); @@ -177,6 +196,8 @@ static void friend_clear(struct bt_mesh_friend *frnd, uint8_t reason) for (i = 0; i < ARRAY_SIZE(frnd->seg); i++) { struct bt_mesh_friend_seg *seg = &frnd->seg[i]; + BT_DBG("%u: SegCount %u", i, seg->seg_count); + purge_buffers(&seg->queue); seg->seg_count = 0U; } @@ -194,11 +215,13 @@ void bt_mesh_friend_clear_net_idx(uint16_t net_idx) { int i; - BT_DBG("net_idx 0x%04x", net_idx); + BT_DBG("FrndClearNetIdx, NetIdx 0x%04x", net_idx); for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) { struct bt_mesh_friend *frnd = &bt_mesh.frnd[i]; + BT_DBG("%u: LPN 0x%04x NetIdx 0x%04x", i, frnd->lpn, frnd->net_idx); + if (frnd->net_idx == BLE_MESH_KEY_UNUSED) { continue; } @@ -213,11 +236,13 @@ void bt_mesh_friend_sec_update(uint16_t net_idx) { int i; - BT_DBG("net_idx 0x%04x", net_idx); + BT_DBG("FrndSecUpdate, NetIdx 0x%04x", net_idx); for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) { struct bt_mesh_friend *frnd = &bt_mesh.frnd[i]; + BT_DBG("%u: NetIdx 0x%04x", i, frnd->net_idx); + if (frnd->net_idx == BLE_MESH_KEY_UNUSED) { continue; } @@ -257,19 +282,21 @@ int bt_mesh_friend_clear(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf) }; struct bt_mesh_ctl_friend_clear_confirm cfm = {0}; + BT_DBG("FrndClear, NetIdx 0x%04x", rx->sub->net_idx); + if (buf->len < sizeof(*msg)) { - BT_WARN("Too short Friend Clear (len %d)", buf->len); + BT_WARN("Too short FriendClear (len %d)", buf->len); return -EINVAL; } lpn_addr = sys_be16_to_cpu(msg->lpn_addr); lpn_counter = sys_be16_to_cpu(msg->lpn_counter); - BT_DBG("LPN addr 0x%04x counter 0x%04x", lpn_addr, lpn_counter); + BT_DBG("LPN 0x%04x Counter %u", lpn_addr, lpn_counter); frnd = bt_mesh_friend_find(rx->sub->net_idx, lpn_addr, false, false); if (!frnd) { - BT_WARN("No matching LPN addr 0x%04x", lpn_addr); + BT_WARN("NoMatchLPN, Addr 0x%04x", lpn_addr); return 0; } @@ -305,6 +332,8 @@ static bool friend_sub_exist(struct bt_mesh_friend *frnd, uint16_t addr) { int i; + BT_DBG("IsFrndSubExist, Addr 0x%04x"); + for (i = 0; i < ARRAY_SIZE(frnd->sub_list); i++) { if (frnd->sub_list[i] == addr) { return true; @@ -318,6 +347,8 @@ static void friend_sub_add(struct bt_mesh_friend *frnd, uint16_t addr) { int i; + BT_DBG("FrndSubAdd, Addr 0x%04x"); + for (i = 0; i < ARRAY_SIZE(frnd->sub_list); i++) { if (frnd->sub_list[i] == BLE_MESH_ADDR_UNASSIGNED) { frnd->sub_list[i] = addr; @@ -332,6 +363,8 @@ static void friend_sub_rem(struct bt_mesh_friend *frnd, uint16_t addr) { int i; + BT_DBG("FrndSubRem, Addr 0x%04x"); + for (i = 0; i < ARRAY_SIZE(frnd->sub_list); i++) { if (frnd->sub_list[i] == addr) { frnd->sub_list[i] = BLE_MESH_ADDR_UNASSIGNED; @@ -346,6 +379,8 @@ static struct net_buf *create_friend_pdu(struct bt_mesh_friend *frnd, { struct net_buf *buf = NULL; + BT_DBG("CreatFrndPDU"); + buf = bt_mesh_adv_create(BLE_MESH_ADV_FRIEND, K_NO_WAIT); if (!buf) { return NULL; @@ -385,6 +420,10 @@ static int unseg_app_sdu_unpack(struct bt_mesh_friend *frnd, uint16_t app_idx = FRIEND_ADV(buf)->app_idx; int err = 0; + BT_DBG("UnsegAppSduUnpack"); + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x RecvDst 0x%04x", + frnd->net_idx, app_idx, meta->net.ctx.recv_dst); + meta->subnet = friend_subnet_get(frnd->net_idx); if (!meta->subnet) { BT_ERR("Invalid subnet for unseg app sdu"); @@ -393,6 +432,7 @@ static int unseg_app_sdu_unpack(struct bt_mesh_friend *frnd, meta->is_dev_key = (app_idx == BLE_MESH_KEY_DEV); bt_mesh_net_header_parse(&buf->b, &meta->net); + err = bt_mesh_upper_key_get(meta->subnet, app_idx, &meta->key, &meta->aid, meta->net.ctx.addr); if (err) { @@ -423,6 +463,8 @@ static int unseg_app_sdu_decrypt(struct bt_mesh_friend *frnd, net_buf_simple_pull(&sdu, 10); sdu.len -= 4; + BT_DBG("UnsegAppSduDecrypt, SduLen %u", sdu.len); + return bt_mesh_app_decrypt(meta->key, meta->is_dev_key, 0, &sdu, &sdu, meta->ad, meta->net.ctx.addr, meta->net.ctx.recv_dst, meta->net.seq, @@ -439,6 +481,8 @@ static int unseg_app_sdu_encrypt(struct bt_mesh_friend *frnd, net_buf_simple_pull(&sdu, 10); sdu.len -= 4; + BT_DBG("UnsegAppSduEncrypt, SduLen %u", sdu.len); + return bt_mesh_app_encrypt(meta->key, meta->is_dev_key, 0, &sdu, meta->ad, meta->net.ctx.addr, meta->net.ctx.recv_dst, bt_mesh.seq, @@ -451,6 +495,10 @@ static int unseg_app_sdu_prepare(struct bt_mesh_friend *frnd, struct unseg_app_sdu_meta meta = {0}; int err = 0; + BT_DBG("UnsegAppSduPrepare"); + BT_DBG("LPN 0x%04x AppIdx 0x%04x Buf %p", + frnd->lpn, FRIEND_ADV(buf)->app_idx, buf); + if (FRIEND_ADV(buf)->app_idx == BLE_MESH_KEY_UNUSED) { return 0; } @@ -464,6 +512,7 @@ static int unseg_app_sdu_prepare(struct bt_mesh_friend *frnd, * unchanged. */ if (meta.net.seq == bt_mesh.seq) { + BT_DBG("Seq 0x%06x", bt_mesh.seq); return 0; } @@ -491,8 +540,11 @@ static int encrypt_friend_pdu(struct bt_mesh_friend *frnd, struct net_buf *buf, uint8_t nid = 0U; int err = 0; + BT_DBG("EncryptFrndPDU, LPN 0x%04x NetIdx 0x%04x Cred %u", + frnd->lpn, frnd->net_idx, master_cred); + if (!sub) { - BT_ERR("Invalid subnet to encrypt friend pdu"); + BT_ERR("NoSubToEncryptFrndPDU"); return -EINVAL; } @@ -502,7 +554,7 @@ static int encrypt_friend_pdu(struct bt_mesh_friend *frnd, struct net_buf *buf, nid = sub->keys[sub->kr_flag].nid; } else { if (friend_cred_get(sub, frnd->lpn, &nid, &enc, &priv)) { - BT_ERR("friend_cred_get failed"); + BT_ERR("FrndCredNotFound"); return -ENOENT; } } @@ -515,6 +567,7 @@ static int encrypt_friend_pdu(struct bt_mesh_friend *frnd, struct net_buf *buf, if (FRIEND_ADV(buf)->app_idx != BLE_MESH_KEY_UNUSED) { err = unseg_app_sdu_prepare(frnd, buf); if (err) { + BT_DBG("UnsegAppSduPrepareFailed, Err %d", err); return err; } } @@ -529,15 +582,15 @@ static int encrypt_friend_pdu(struct bt_mesh_friend *frnd, struct net_buf *buf, iv_index = (bt_mesh.iv_index - ((bt_mesh.iv_index & 1) != ivi)); } + BT_DBG("Src 0x%04x NID 0x%02x IVIndex 0x%08lx", src, nid, iv_index); + buf->data[0] = (nid | (iv_index & 1) << 7); if (bt_mesh_net_encrypt(enc, &buf->b, iv_index, false, false)) { - BT_ERR("Encrypting failed"); return -EINVAL; } if (bt_mesh_net_obfuscate(buf->data, iv_index, priv)) { - BT_ERR("Obfuscating failed"); return -EINVAL; } @@ -550,7 +603,7 @@ static struct net_buf *encode_friend_ctl(struct bt_mesh_friend *frnd, { struct friend_pdu_info info = {0}; - BT_DBG("LPN 0x%04x", frnd->lpn); + BT_DBG("EncodeFrndCTL"); net_buf_simple_push_u8(sdu, TRANS_CTL_HDR(ctl_op, 0)); @@ -564,21 +617,25 @@ static struct net_buf *encode_friend_ctl(struct bt_mesh_friend *frnd, info.iv_index = BLE_MESH_NET_IVI_TX; + BT_DBG("CTLOp 0x%02x IVIndex 0x%08lx", ctl_op, info.iv_index); + return create_friend_pdu(frnd, &info, sdu); } static struct net_buf *encode_update(struct bt_mesh_friend *frnd, uint8_t md) { + struct bt_mesh_subnet *sub = friend_subnet_get(frnd->net_idx); struct bt_mesh_ctl_friend_update *upd = NULL; NET_BUF_SIMPLE_DEFINE(sdu, 1 + sizeof(*upd)); - struct bt_mesh_subnet *sub = friend_subnet_get(frnd->net_idx); + + BT_DBG("EncodeUpdate, NetIdx 0x%04x", frnd->net_idx); if (!sub) { BT_ERR("Friend subnet 0x%04x not found", frnd->net_idx); return NULL; } - BT_DBG("lpn 0x%04x md 0x%02x", frnd->lpn, md); + BT_DBG("LPN 0x%04x MD %u", frnd->lpn, md); net_buf_simple_reserve(&sdu, 1); @@ -596,7 +653,7 @@ static void enqueue_sub_cfm(struct bt_mesh_friend *frnd, uint8_t xact) NET_BUF_SIMPLE_DEFINE(sdu, 1 + sizeof(*cfm)); struct net_buf *buf = NULL; - BT_DBG("lpn 0x%04x xact 0x%02x", frnd->lpn, xact); + BT_DBG("EnqueueSubCFM, LPN 0x%04x Xact 0x%02x", frnd->lpn, xact); net_buf_simple_reserve(&sdu, 1); @@ -614,7 +671,7 @@ static void enqueue_sub_cfm(struct bt_mesh_friend *frnd, uint8_t xact) } if (frnd->last) { - BT_DBG("Discarding last PDU"); + BT_DBG("DiscardFrndLast, Buf %p Ref %u", frnd->last, frnd->last->ref); net_buf_unref(frnd->last); } @@ -624,9 +681,12 @@ static void enqueue_sub_cfm(struct bt_mesh_friend *frnd, uint8_t xact) static void friend_recv_delay(struct bt_mesh_friend *frnd) { + int32_t delay = recv_delay(frnd); + + BT_INFO("FrndRecvDelay, Delay %ld", delay); + frnd->pending_req = 1U; - k_delayed_work_submit(&frnd->timer, recv_delay(frnd)); - BT_INFO("Waiting RecvDelay of %d ms", recv_delay(frnd)); + k_delayed_work_submit(&frnd->timer, delay); } int bt_mesh_friend_sub_add(struct bt_mesh_net_rx *rx, @@ -635,6 +695,8 @@ int bt_mesh_friend_sub_add(struct bt_mesh_net_rx *rx, struct bt_mesh_friend *frnd = NULL; uint8_t xact = 0U; + BT_DBG("FrndSubAdd"); + if (buf->len < BLE_MESH_FRIEND_SUB_MIN_LEN) { BT_WARN("Too short Friend Subscription Add (len %d)", buf->len); return -EINVAL; @@ -642,7 +704,7 @@ int bt_mesh_friend_sub_add(struct bt_mesh_net_rx *rx, frnd = bt_mesh_friend_find(rx->sub->net_idx, rx->ctx.addr, true, true); if (!frnd) { - BT_WARN("No matching LPN addr 0x%04x", rx->ctx.addr); + BT_WARN("NoMatchLPN, Addr 0x%04x", rx->ctx.addr); return 0; } @@ -666,6 +728,7 @@ int bt_mesh_friend_sub_add(struct bt_mesh_net_rx *rx, } if (friend_sub_exist(frnd, addr)) { + BT_DBG("FrndSubExist, Addr 0x%04x", addr); continue; } @@ -676,9 +739,9 @@ int bt_mesh_friend_sub_add(struct bt_mesh_net_rx *rx, #if CONFIG_BLE_MESH_DF_SRV return bt_mesh_directed_friend_solicitation(frnd, rx->sub); -#else +#else /* CONFIG_BLE_MESH_DF_SRV */ return 0; -#endif +#endif /* CONFIG_BLE_MESH_DF_SRV */ } int bt_mesh_friend_sub_rem(struct bt_mesh_net_rx *rx, @@ -687,6 +750,8 @@ int bt_mesh_friend_sub_rem(struct bt_mesh_net_rx *rx, struct bt_mesh_friend *frnd = NULL; uint8_t xact = 0U; + BT_DBG("FrndSubRem"); + if (buf->len < BLE_MESH_FRIEND_SUB_MIN_LEN) { BT_WARN("Too short Friend Subscription Remove (len %d)", buf->len); return -EINVAL; @@ -694,7 +759,7 @@ int bt_mesh_friend_sub_rem(struct bt_mesh_net_rx *rx, frnd = bt_mesh_friend_find(rx->sub->net_idx, rx->ctx.addr, true, true); if (!frnd) { - BT_WARN("No matching LPN addr 0x%04x", rx->ctx.addr); + BT_WARN("NoMatchLPN, Addr 0x%04x", rx->ctx.addr); return 0; } @@ -713,7 +778,7 @@ int bt_mesh_friend_sub_rem(struct bt_mesh_net_rx *rx, if (!BLE_MESH_ADDR_IS_GROUP(addr) && !BLE_MESH_ADDR_IS_VIRTUAL(addr) && !BLE_MESH_ADDR_IS_FIXED_GROUP(addr)) { - BT_WARN("Invalid friend sub addr 0x%04x to remove", addr); + BT_WARN("InvalidFrndSub, Addr 0x%04x", addr); continue; } @@ -727,6 +792,8 @@ int bt_mesh_friend_sub_rem(struct bt_mesh_net_rx *rx, static void enqueue_buf(struct bt_mesh_friend *frnd, struct net_buf *buf) { + BT_DBG("EnqueueBuf, Buf %p QueueSize %u", __func__, buf, frnd->queue_size); + net_buf_slist_put(&frnd->queue, buf); frnd->queue_size++; } @@ -735,6 +802,8 @@ static void enqueue_update(struct bt_mesh_friend *frnd, uint8_t md) { struct net_buf *buf = NULL; + BT_DBG("EnqueueUpdate, LPN 0x%04x MD %u", __func__, frnd->lpn, md); + buf = encode_update(frnd, md); if (!buf) { BT_ERR("Unable to encode Friend Update"); @@ -749,6 +818,8 @@ int bt_mesh_friend_poll(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf) struct bt_mesh_ctl_friend_poll *msg = (void *)buf->data; struct bt_mesh_friend *frnd = NULL; + BT_DBG("FrndPoll"); + if (buf->len < sizeof(*msg)) { BT_WARN("Too short Friend Poll (len %d)", buf->len); return -EINVAL; @@ -756,7 +827,7 @@ int bt_mesh_friend_poll(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf) frnd = bt_mesh_friend_find(rx->sub->net_idx, rx->ctx.addr, true, false); if (!frnd) { - BT_WARN("No matching LPN addr 0x%04x", rx->ctx.addr); + BT_WARN("NoMatchLPN, Addr 0x%04x", rx->ctx.addr); return 0; } @@ -770,12 +841,13 @@ int bt_mesh_friend_poll(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf) return 0; } - BT_DBG("msg->fsn %u frnd->fsn %u", (msg->fsn & 1), frnd->fsn); + BT_DBG("MsgFSN %u FrndFSN %u", (msg->fsn & 1), frnd->fsn); friend_recv_delay(frnd); if (!frnd->established) { - BT_INFO("Friendship established with 0x%04x", frnd->lpn); + BT_INFO("Friendship established with LPN 0x%04x", frnd->lpn); + frnd->established = 1U; if (friend_cb) { friend_cb(true, frnd->lpn, 0); @@ -783,7 +855,8 @@ int bt_mesh_friend_poll(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf) } if (msg->fsn == frnd->fsn && frnd->last) { - BT_DBG("Re-sending last PDU"); + BT_DBG("ResendFrndLast"); + frnd->send_last = 1U; } else { if (frnd->last) { @@ -794,8 +867,8 @@ int bt_mesh_friend_poll(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf) frnd->fsn = msg->fsn; if (sys_slist_is_empty(&frnd->queue)) { + BT_DBG("EnqueueFrndUpdate"); enqueue_update(frnd, 0); - BT_DBG("Enqueued Friend Update to empty queue"); } } @@ -806,6 +879,8 @@ static struct bt_mesh_friend *find_clear(uint16_t prev_friend) { int i; + BT_DBG("FindClear, PrevFrnd 0x%04x", prev_friend); + for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) { struct bt_mesh_friend *frnd = &bt_mesh.frnd[i]; @@ -821,6 +896,8 @@ static void friend_clear_sent(int err, void *user_data) { struct bt_mesh_friend *frnd = user_data; + BT_DBG("FrndClearSent, RepeatSec %u Err %d", frnd->clear.repeat_sec, err); + k_delayed_work_submit(&frnd->clear.timer, K_SECONDS(frnd->clear.repeat_sec)); frnd->clear.repeat_sec *= 2U; @@ -852,6 +929,8 @@ static void send_friend_clear(struct bt_mesh_friend *frnd) .lpn_counter = sys_cpu_to_be16(frnd->lpn_counter), }; + BT_DBG("SendFrndClear, Addr 0x%04x", frnd->clear.frnd); + if (!tx.sub) { BT_ERR("Invalid subnet for Friend Clear"); return; @@ -863,13 +942,15 @@ static void send_friend_clear(struct bt_mesh_friend *frnd) static void clear_timeout(struct k_work *work) { - struct bt_mesh_friend *frnd = CONTAINER_OF(work, struct bt_mesh_friend, - clear.timer.work); + struct bt_mesh_friend *frnd = CONTAINER_OF(work, struct bt_mesh_friend, clear.timer.work); uint32_t duration = 0U; - BT_DBG("LPN 0x%04x (old) Friend 0x%04x", frnd->lpn, frnd->clear.frnd); - duration = k_uptime_get_32() - frnd->clear.start; + + BT_DBG("ClearTimeout"); + BT_DBG("LPN 0x%04x Frnd 0x%04x Duration %lu PollTo %ld", + frnd->lpn, frnd->clear.frnd, duration, frnd->poll_to); + if (duration > 2 * frnd->poll_to) { BT_DBG("Clear Procedure timer expired"); frnd->clear.frnd = BLE_MESH_ADDR_UNASSIGNED; @@ -881,11 +962,13 @@ static void clear_timeout(struct k_work *work) static void clear_procedure_start(struct bt_mesh_friend *frnd) { - BT_DBG("LPN 0x%04x (old) Friend 0x%04x", frnd->lpn, frnd->clear.frnd); - frnd->clear.start = k_uptime_get_32(); frnd->clear.repeat_sec = 1U; + BT_DBG("ClearProcedureStart"); + BT_DBG("LPN 0x%04x Frnd 0x%04x ClearStart %lu", + frnd->lpn, frnd->clear.frnd, frnd->clear.start); + send_friend_clear(frnd); } @@ -896,6 +979,8 @@ int bt_mesh_friend_clear_cfm(struct bt_mesh_net_rx *rx, struct bt_mesh_friend *frnd = NULL; uint16_t lpn_addr = 0U, lpn_counter = 0U; + BT_DBG("FrndClearCFM"); + if (buf->len < sizeof(*msg)) { BT_WARN("Too short Friend Clear Confirm (len %d)", buf->len); return -EINVAL; @@ -933,6 +1018,9 @@ static void enqueue_offer(struct bt_mesh_friend *frnd, int8_t rssi) NET_BUF_SIMPLE_DEFINE(sdu, 1 + sizeof(*off)); struct net_buf *buf = NULL; + BT_DBG("EnqueueOffset"); + BT_DBG("LPN 0x%04x Counter %u Rssi %d", frnd->lpn, frnd->counter, rssi); + net_buf_simple_reserve(&sdu, 1); off = net_buf_simple_add(&sdu, sizeof(*off)); @@ -977,7 +1065,7 @@ static int32_t offer_delay(struct bt_mesh_friend *frnd, int8_t rssi, uint8_t cri static const uint8_t fact[] = { 10, 15, 20, 25 }; int32_t delay = 0; - BT_INFO("ReceiveWindowFactor %u ReceiveWindow %u RSSIFactor %u RSSI %d", + BT_INFO("RecvWinFactor %u RecvWin %u RssiFactor %u Rssi %d", fact[RECV_WIN_FACT(crit)], RECV_WIN, fact[RSSI_FACT(crit)], rssi); @@ -986,7 +1074,7 @@ static int32_t offer_delay(struct bt_mesh_friend *frnd, int8_t rssi, uint8_t cri delay -= (int32_t)fact[RSSI_FACT(crit)] * rssi; delay /= 10; - BT_DBG("Local Delay calculated as %d ms", delay); + BT_DBG("OfferDelay %d", delay); if (delay < 100) { return K_MSEC(100); @@ -1002,13 +1090,15 @@ int bt_mesh_friend_req(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf) uint32_t poll_to = 0U; int i; + BT_DBG("FrndReq"); + if (buf->len < sizeof(*msg)) { BT_WARN("Too short Friend Request (len %d)", buf->len); return -EINVAL; } if (msg->recv_delay <= 0x09) { - BT_WARN("Prohibited ReceiveDelay (0x%02x)", msg->recv_delay); + BT_WARN("Prohibited RecvDelay (0x%02x)", msg->recv_delay); return -EINVAL; } @@ -1035,7 +1125,7 @@ int bt_mesh_friend_req(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf) } if (CONFIG_BLE_MESH_FRIEND_QUEUE_SIZE < MIN_QUEUE_SIZE(msg->criteria)) { - BT_WARN("We have a too small Friend Queue size (%u < %u)", + BT_WARN("Too small Friend Queue size (%u < %u)", CONFIG_BLE_MESH_FRIEND_QUEUE_SIZE, MIN_QUEUE_SIZE(msg->criteria)); return 0; @@ -1070,11 +1160,10 @@ init_friend: frnd->lpn_counter = sys_be16_to_cpu(msg->lpn_counter); frnd->clear.frnd = sys_be16_to_cpu(msg->prev_addr); - BT_INFO("LPN 0x%04x rssi %d recv_delay %u poll_to %ums", - frnd->lpn, rx->ctx.recv_rssi, frnd->recv_delay, frnd->poll_to); + BT_INFO("LPN 0x%04x Rssi %d RecvDelay %u PollTo %u", + frnd->lpn, rx->ctx.recv_rssi, frnd->recv_delay, frnd->poll_to); - /** - * Spec says: + /* Spec says: * After a friendship has been established, if the PreviousAddress field * of the Friend Request message contains a valid unicast address that is * not the Friend node’s own unicast address, then the Friend node shall @@ -1086,11 +1175,9 @@ init_friend: } k_delayed_work_submit(&frnd->timer, - offer_delay(frnd, rx->ctx.recv_rssi, - msg->criteria)); + offer_delay(frnd, rx->ctx.recv_rssi, msg->criteria)); - friend_cred_create(rx->sub, frnd->lpn, frnd->lpn_counter, - frnd->counter); + friend_cred_create(rx->sub, frnd->lpn, frnd->lpn_counter, frnd->counter); enqueue_offer(frnd, rx->ctx.recv_rssi); @@ -1104,6 +1191,8 @@ static bool is_seg(struct bt_mesh_friend_seg *seg, uint16_t src, uint16_t seq_ze uint16_t buf_seq_zero = 0U; uint16_t buf_src = 0U; + BT_DBG("IsSeg, Buf %p", buf); + if (!buf) { return false; } @@ -1125,6 +1214,9 @@ static struct bt_mesh_friend_seg *get_seg(struct bt_mesh_friend *frnd, struct bt_mesh_friend_seg *unassigned = NULL; int i; + BT_DBG("GetSeg, Src 0x%04x SeqZero 0x%04x SegCount %u", + src, seq_zero, seg_count); + for (i = 0; i < ARRAY_SIZE(frnd->seg); i++) { struct bt_mesh_friend_seg *seg = &frnd->seg[i]; @@ -1150,15 +1242,18 @@ static void enqueue_friend_pdu(struct bt_mesh_friend *frnd, struct net_buf *buf) { struct bt_mesh_friend_seg *seg = NULL; + uint16_t seq_zero = 0; - BT_DBG("type %u", type); + BT_DBG("EnqueueFrndPDU, Type %u", type); if (type == BLE_MESH_FRIEND_PDU_SINGLE) { enqueue_buf(frnd, buf); return; } - uint16_t seq_zero = (((buf->data[10] << 8 | buf->data[11]) >> 2) & TRANS_SEQ_ZERO_MASK); + seq_zero = (((buf->data[10] << 8 | buf->data[11]) >> 2) & TRANS_SEQ_ZERO_MASK); + + BT_DBG("Src 0x%04x SegCount %u SegZero 0x%04x", src, seg_count, seq_zero); seg = get_seg(frnd, src, seq_zero, seg_count); if (!seg) { @@ -1184,7 +1279,7 @@ static void buf_send_start(uint16_t duration, int err, void *user_data) { struct bt_mesh_friend *frnd = user_data; - BT_DBG("err %d", err); + BT_DBG("BufSendStart, Err %d", err); frnd->pending_buf = 0U; @@ -1199,7 +1294,7 @@ static void buf_send_end(int err, void *user_data) { struct bt_mesh_friend *frnd = user_data; - BT_DBG("err %d", err); + BT_DBG("BufSendEnd, Err %d", err); if (frnd->pending_req) { BT_WARN("Another request before previous completed sending"); @@ -1207,47 +1302,48 @@ static void buf_send_end(int err, void *user_data) } if (frnd->established) { + BT_DBG("WaitForNextPoll %u", frnd->poll_to); + k_delayed_work_submit(&frnd->timer, frnd->poll_to); - BT_DBG("Waiting %u ms for next poll", frnd->poll_to); } else { /* Friend offer timeout is 1 second */ + BT_DBG("WaitForFirstPoll"); + k_delayed_work_submit(&frnd->timer, K_SECONDS(1)); - BT_DBG("Waiting for first poll"); } } static void friend_timeout(struct k_work *work) { - struct bt_mesh_friend *frnd = CONTAINER_OF(work, struct bt_mesh_friend, - timer.work); + struct bt_mesh_friend *frnd = CONTAINER_OF(work, struct bt_mesh_friend, timer.work); static const struct bt_mesh_send_cb buf_sent_cb = { .start = buf_send_start, .end = buf_send_end, }; + BT_DBG("FrndTimeout"); + if (frnd->pending_buf != 0U) { BT_ERR("Previous buffer not yet sent!"); return; } - BT_DBG("lpn 0x%04x send_last %u last %p", frnd->lpn, - frnd->send_last, frnd->last); + BT_DBG("LPN 0x%04x SendLast %u FrndLast %p", frnd->lpn, frnd->send_last, frnd->last); if (frnd->send_last && frnd->last) { - BT_DBG("Sending frnd->last %p", frnd->last); frnd->send_last = 0U; goto send_last; } if (frnd->established && !frnd->pending_req) { - BT_WARN("Friendship lost with 0x%04x", frnd->lpn); + BT_WARN("FriendshipLost, LPN 0x%04x", frnd->lpn); friend_clear(frnd, BLE_MESH_FRIENDSHIP_TERMINATE_POLL_TIMEOUT); return; } frnd->last = (void *)sys_slist_get(&frnd->queue); if (!frnd->last) { - BT_WARN("Friendship not established with 0x%04x", frnd->lpn); + BT_WARN("FriendshipNotEstablished, LPN 0x%04x", frnd->lpn); friend_clear(frnd, BLE_MESH_FRIENDSHIP_TERMINATE_ESTABLISH_FAIL); return; } @@ -1260,8 +1356,9 @@ static void friend_timeout(struct k_work *work) frnd->last->flags &= ~NET_BUF_FRAGS; frnd->last->frags = NULL; - BT_DBG("Sending buf %p from Friend Queue of LPN 0x%04x", - frnd->last, frnd->lpn); + BT_DBG("SendBufFromFrndQueue, Last %p QueueSize %u LPN 0x%04x", + frnd->last, frnd->queue_size, frnd->lpn); + frnd->queue_size--; send_last: @@ -1279,6 +1376,8 @@ int bt_mesh_friend_init(void) { int i; + BT_DBG("FrndInit"); + if (friend_init == true) { BT_WARN("%s, Already", __func__); return -EALREADY; @@ -1312,6 +1411,8 @@ int bt_mesh_friend_deinit(void) { int i; + BT_DBG("FrndDeinit"); + if (friend_init == false) { BT_WARN("%s, Already", __func__); return -EALREADY; @@ -1341,6 +1442,8 @@ static bool is_segack(struct net_buf *buf, const uint64_t *seqauth, uint16_t src struct net_buf_simple_state state = {0}; bool found = false; + BT_DBG("IsSegAck, Len %u", buf->len); + if (buf->len != 16) { return false; } @@ -1350,23 +1453,27 @@ static bool is_segack(struct net_buf *buf, const uint64_t *seqauth, uint16_t src net_buf_skip(buf, 1); /* skip IVI, NID */ if (!(net_buf_pull_u8(buf) >> 7)) { + BT_DBG("Not SegAck"); goto end; } net_buf_pull(buf, 3); /* skip SEQNUM */ if (src != net_buf_pull_be16(buf)) { + BT_DBG("SrcNotSegAck"); goto end; } net_buf_skip(buf, 2); /* skip dst */ - if (TRANS_CTL_OP((uint8_t *) net_buf_pull_mem(buf, 1)) != TRANS_CTL_OP_ACK) { + if (TRANS_CTL_OP((uint8_t *)net_buf_pull_mem(buf, 1)) != TRANS_CTL_OP_ACK) { + BT_DBG("OpNotSegAck"); goto end; } - found = ((net_buf_pull_be16(buf) >> 2) & TRANS_SEQ_ZERO_MASK) == - (*seqauth & TRANS_SEQ_ZERO_MASK); + found = (((net_buf_pull_be16(buf) >> 2) & TRANS_SEQ_ZERO_MASK) == + (*seqauth & TRANS_SEQ_ZERO_MASK)); + end: net_buf_simple_restore(&buf->b, &state); return found; @@ -1377,17 +1484,18 @@ static void friend_purge_old_ack(struct bt_mesh_friend *frnd, { sys_snode_t *cur = NULL, *prev = NULL; - BT_DBG("SeqAuth %llx src 0x%04x", *seq_auth, src); + BT_DBG("FrndPurgeOldAck, SeqAuth %llx Src 0x%04x", *seq_auth, src); for (cur = sys_slist_peek_head(&frnd->queue); - cur != NULL; prev = cur, cur = sys_slist_peek_next(cur)) { + cur != NULL; prev = cur, cur = sys_slist_peek_next(cur)) { struct net_buf *buf = (void *)cur; if (is_segack(buf, seq_auth, src)) { - BT_DBG("Removing old ack from Friend Queue"); + BT_DBG("RemoveOldAckFromFrndQueue, QueueSize %u", frnd->queue_size); sys_slist_remove(&frnd->queue, prev, cur); frnd->queue_size--; + /* Make sure old slist entry state doesn't remain */ buf->frags = NULL; @@ -1406,6 +1514,9 @@ static void friend_lpn_enqueue_rx(struct bt_mesh_friend *frnd, struct friend_pdu_info info = {0}; struct net_buf *buf = NULL; + BT_DBG("FrndLPNEnqueueRx, LPN 0x%04x QueueSize %u Type 0x%02x", + frnd->lpn, frnd->queue_size, type); + /* Because of network loopback, tx packets will also be passed into * this rx function. These packets have already been added to the * queue, and should be ignored. @@ -1414,8 +1525,6 @@ static void friend_lpn_enqueue_rx(struct bt_mesh_friend *frnd, return; } - BT_DBG("LPN 0x%04x queue_size %u", frnd->lpn, frnd->queue_size); - if (type == BLE_MESH_FRIEND_PDU_SINGLE && seq_auth) { friend_purge_old_ack(frnd, seq_auth, rx->ctx.addr); } @@ -1443,7 +1552,7 @@ static void friend_lpn_enqueue_rx(struct bt_mesh_friend *frnd, enqueue_friend_pdu(frnd, type, info.src, seg_count, buf); - BT_DBG("Queued message for LPN 0x%04x, queue_size %u", + BT_DBG("QueuedMsg, LPN 0x%04x QueueSize %u", frnd->lpn, frnd->queue_size); } @@ -1456,7 +1565,7 @@ static void friend_lpn_enqueue_tx(struct bt_mesh_friend *frnd, struct friend_pdu_info info = {0}; struct net_buf *buf = NULL; - BT_DBG("LPN 0x%04x", frnd->lpn); + BT_DBG("FrndLPNEnqueueTx, LPN 0x%04x Type 0x%02x", frnd->lpn, type); if (type == BLE_MESH_FRIEND_PDU_SINGLE && seq_auth) { friend_purge_old_ack(frnd, seq_auth, tx->src); @@ -1488,7 +1597,7 @@ static void friend_lpn_enqueue_tx(struct bt_mesh_friend *frnd, enqueue_friend_pdu(frnd, type, info.src, seg_count, buf); - BT_DBG("Queued message for LPN 0x%04x", frnd->lpn); + BT_DBG("QueuedMsg, LPN 0x%04x", frnd->lpn); } static bool friend_lpn_matches(struct bt_mesh_friend *frnd, uint16_t net_idx, @@ -1496,6 +1605,10 @@ static bool friend_lpn_matches(struct bt_mesh_friend *frnd, uint16_t net_idx, { int i; + BT_DBG("IsFrndLPNMatch"); + BT_DBG("LPN 0x%04x NetIdx 0x%04x/0x%04x Addr 0x%04x Established %u", + frnd->lpn, net_idx, frnd->net_idx, addr, frnd->established); + if (!frnd->established) { return false; } @@ -1521,12 +1634,13 @@ bool bt_mesh_friend_match(uint16_t net_idx, uint16_t addr) { int i; + BT_DBG("FrndMatch, NetIdx 0x%04x Addr 0x%04x", net_idx, addr); + for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) { struct bt_mesh_friend *frnd = &bt_mesh.frnd[i]; if (friend_lpn_matches(frnd, net_idx, addr)) { - BT_DBG("LPN 0x%04x matched address 0x%04x", - frnd->lpn, addr); + BT_DBG("LPNMatch, LPN 0x%04x Addr 0x%04x", frnd->lpn, addr); return true; } } @@ -1540,6 +1654,8 @@ bool bt_mesh_friend_unicast_match(uint16_t net_idx, uint16_t addr, uint8_t *sele { int i; + BT_DBG("FrndUnicastMatch, NetIdx 0x%04x addr 0x%04x", net_idx, addr); + if (!BLE_MESH_ADDR_IS_UNICAST(addr) || selem == NULL) { BT_ERR("%s, Invalid parameter", __func__); return false; @@ -1565,6 +1681,10 @@ static bool friend_queue_has_space(struct bt_mesh_friend *frnd, uint16_t addr, uint32_t total = 0U; int i; + BT_DBG("IsFrndQueueHasSpace"); + BT_DBG("LPN 0x%04x SegCount %u QueueSize %u Addr 0x%04x", + frnd->lpn, seg_count, CONFIG_BLE_MESH_FRIEND_QUEUE_SIZE, addr); + if (seg_count > CONFIG_BLE_MESH_FRIEND_QUEUE_SIZE) { return false; } @@ -1573,8 +1693,8 @@ static bool friend_queue_has_space(struct bt_mesh_friend *frnd, uint16_t addr, struct bt_mesh_friend_seg *seg = &frnd->seg[i]; if (seq_auth && is_seg(seg, addr, *seq_auth & TRANS_SEQ_ZERO_MASK)) { - /* If there's a segment queue for this message then the - * space verification has already happened. + /* If there's a segment queue for this message then the space + * verification has already happened. */ return true; } @@ -1582,6 +1702,8 @@ static bool friend_queue_has_space(struct bt_mesh_friend *frnd, uint16_t addr, total += seg->seg_count; } + BT_DBG("TotalCount %u", total); + /* If currently pending segments combined with this segmented message * are more than the Friend Queue Size, then there's no space. This * is because we don't have a mechanism of aborting already pending @@ -1596,6 +1718,10 @@ bool bt_mesh_friend_queue_has_space(uint16_t net_idx, uint16_t src, uint16_t dst bool someone_has_space = false, friend_match = false; int i; + BT_DBG("FrndQueueHasSpace"); + BT_DBG("NetIdx 0x%04x Src 0x%04x Dst 0x%04x SegCount %u", + net_idx, src, dst, seg_count); + for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) { struct bt_mesh_friend *frnd = &bt_mesh.frnd[i]; @@ -1614,6 +1740,7 @@ bool bt_mesh_friend_queue_has_space(uint16_t net_idx, uint16_t src, uint16_t dst * transport layer can continue its work. */ if (!friend_match) { + BT_DBG("NoMatchLPN"); return true; } @@ -1631,6 +1758,9 @@ static bool friend_queue_prepare_space(struct bt_mesh_friend *frnd, uint16_t add bool pending_segments = false; uint8_t avail_space = 0U; + BT_DBG("FrndQueuePrepareSpace"); + BT_DBG("LPN 0x%04x Addr 0x%04x SegCount %u", frnd->lpn, addr, seg_count); + if (!friend_queue_has_space(frnd, addr, seq_auth, seg_count)) { return false; } @@ -1646,6 +1776,9 @@ static bool friend_queue_prepare_space(struct bt_mesh_friend *frnd, uint16_t add return false; } + BT_DBG("PendingSeg %u AvailSpace %u QueueSize %u", + pending_segments, avail_space, frnd->queue_size); + frnd->queue_size--; avail_space++; @@ -1668,15 +1801,19 @@ void bt_mesh_friend_enqueue_rx(struct bt_mesh_net_rx *rx, { int i; + BT_DBG("FrndEnqueueRx"); + BT_DBG("FrndMatch %u RecvTTL %u NetIf %u FrndGet %u", + rx->friend_match, rx->ctx.recv_ttl, rx->net_if, + bt_mesh_friend_get()); + if (!rx->friend_match || (rx->ctx.recv_ttl <= 1U && rx->net_if != BLE_MESH_NET_IF_LOCAL) || bt_mesh_friend_get() != BLE_MESH_FRIEND_ENABLED) { return; } - BT_DBG("recv_ttl %u net_idx 0x%04x src 0x%04x dst 0x%04x", - rx->ctx.recv_ttl, rx->sub->net_idx, rx->ctx.addr, - rx->ctx.recv_dst); + BT_DBG("NetIdx 0x%04x Src 0x%04x Dst 0x%04x", + rx->sub->net_idx, rx->ctx.addr, rx->ctx.recv_dst); for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) { struct bt_mesh_friend *frnd = &bt_mesh.frnd[i]; @@ -1691,8 +1828,7 @@ void bt_mesh_friend_enqueue_rx(struct bt_mesh_net_rx *rx, continue; } - friend_lpn_enqueue_rx(frnd, rx, type, seq_auth, seg_count, - sbuf); + friend_lpn_enqueue_rx(frnd, rx, type, seq_auth, seg_count, sbuf); } } @@ -1704,14 +1840,15 @@ bool bt_mesh_friend_enqueue_tx(struct bt_mesh_net_tx *tx, bool matched = false; int i; + BT_DBG("FrndEnqueueTx"); + BT_DBG("NetIdx 0x%04x Dst 0x%04x Src 0x%04x FrndState %u", + tx->sub->net_idx, tx->ctx->addr, tx->src, bt_mesh_friend_get()); + if (!bt_mesh_friend_match(tx->sub->net_idx, tx->ctx->addr) || bt_mesh_friend_get() != BLE_MESH_FRIEND_ENABLED) { return matched; } - BT_DBG("net_idx 0x%04x dst 0x%04x src 0x%04x", tx->sub->net_idx, - tx->ctx->addr, tx->src); - for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) { struct bt_mesh_friend *frnd = &bt_mesh.frnd[i]; @@ -1738,6 +1875,9 @@ void bt_mesh_friend_clear_incomplete(struct bt_mesh_subnet *sub, uint16_t src, { int i; + BT_DBG("FrndClearComplete"); + BT_DBG("NetIdx 0x%04x Src 0x%04x Dst 0x%04x", sub->net_idx, src, dst); + for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) { struct bt_mesh_friend *frnd = &bt_mesh.frnd[i]; int j; @@ -1766,6 +1906,8 @@ void bt_mesh_friend_remove_lpn(uint16_t lpn_addr) { struct bt_mesh_friend *frnd = NULL; + BT_DBG("FrndRemoveLPN, Addr 0x%04x", lpn_addr); + frnd = bt_mesh_friend_find(BLE_MESH_KEY_ANY, lpn_addr, false, false); if (frnd) { friend_clear(frnd, BLE_MESH_FRIENDSHIP_TERMINATE_DISABLE); diff --git a/components/bt/esp_ble_mesh/core/health_cli.c b/components/bt/esp_ble_mesh/core/health_cli.c index 1e03d93513c..829ae336932 100644 --- a/components/bt/esp_ble_mesh/core/health_cli.c +++ b/components/bt/esp_ble_mesh/core/health_cli.c @@ -68,6 +68,8 @@ static void health_client_recv_status(struct bt_mesh_model *model, struct net_buf_simple buf = {0}; uint8_t evt_type = 0xFF; + BT_DBG("HealthClientRecvStatus"); + if (!model || !ctx || !status || !len) { BT_ERR("%s, Invalid parameter", __func__); return; @@ -83,6 +85,8 @@ static void health_client_recv_status(struct bt_mesh_model *model, if (!node) { BT_DBG("Unexpected Health Status 0x%04x", ctx->recv_op); } else { + BT_DBG("OpCode 0x%08lx RecvOp 0x%08lx", node->opcode, ctx->recv_op); + switch (node->opcode) { case OP_HEALTH_FAULT_GET: case OP_HEALTH_PERIOD_GET: @@ -131,9 +135,10 @@ static void health_fault_status(struct bt_mesh_model *model, { struct bt_mesh_health_fault_status status = {0}; - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, - bt_hex(buf->data, buf->len)); + BT_DBG("HealthFaultStatus"); + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", + ctx->net_idx, ctx->app_idx, ctx->addr); + BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); status.test_id = net_buf_simple_pull_u8(buf); status.cid = net_buf_simple_pull_le16(buf); @@ -154,9 +159,10 @@ static void health_current_status(struct bt_mesh_model *model, { struct bt_mesh_health_current_status status = {0}; - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, - bt_hex(buf->data, buf->len)); + BT_DBG("HealthCurrentStatus"); + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", + ctx->net_idx, ctx->app_idx, ctx->addr); + BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); status.test_id = net_buf_simple_pull_u8(buf); status.cid = net_buf_simple_pull_le16(buf); @@ -177,9 +183,10 @@ static void health_period_status(struct bt_mesh_model *model, { uint8_t status = 0U; - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, - bt_hex(buf->data, buf->len)); + BT_DBG("HealthPeriodStatus"); + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", + ctx->net_idx, ctx->app_idx, ctx->addr); + BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); status = net_buf_simple_pull_u8(buf); @@ -192,9 +199,10 @@ static void health_attention_status(struct bt_mesh_model *model, { uint8_t status = 0U; - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->len, - bt_hex(buf->data, buf->len)); + BT_DBG("HealthAttentionStatus"); + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", + ctx->net_idx, ctx->app_idx, ctx->addr); + BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); status = net_buf_simple_pull_u8(buf); @@ -213,6 +221,8 @@ int bt_mesh_health_attention_get(bt_mesh_client_common_param_t *param) { BLE_MESH_MODEL_BUF_DEFINE(msg, OP_ATTENTION_GET, 0); + BT_DBG("HealthAttentionGet"); + bt_mesh_model_msg_init(&msg, OP_ATTENTION_GET); return bt_mesh_client_send_msg(param, &msg, true, timeout_handler); @@ -223,6 +233,8 @@ int bt_mesh_health_attention_set(bt_mesh_client_common_param_t *param, { BLE_MESH_MODEL_BUF_DEFINE(msg, OP_ATTENTION_SET, 1); + BT_DBG("HealthAttentionSet, Attention 0x%02x NeedAck %u", attention, need_ack); + bt_mesh_model_msg_init(&msg, need_ack ? OP_ATTENTION_SET : OP_ATTENTION_SET_UNREL); net_buf_simple_add_u8(&msg, attention); @@ -233,6 +245,8 @@ int bt_mesh_health_period_get(bt_mesh_client_common_param_t *param) { BLE_MESH_MODEL_BUF_DEFINE(msg, OP_HEALTH_PERIOD_GET, 0); + BT_DBG("HealthPeriodGet"); + bt_mesh_model_msg_init(&msg, OP_HEALTH_PERIOD_GET); return bt_mesh_client_send_msg(param, &msg, true, timeout_handler); @@ -243,6 +257,8 @@ int bt_mesh_health_period_set(bt_mesh_client_common_param_t *param, { BLE_MESH_MODEL_BUF_DEFINE(msg, OP_HEALTH_PERIOD_SET, 1); + BT_DBG("HealthPeriodSet, Divisor 0x%02x NeedAck %u", divisor, need_ack); + bt_mesh_model_msg_init(&msg, need_ack ? OP_HEALTH_PERIOD_SET : OP_HEALTH_PERIOD_SET_UNREL); net_buf_simple_add_u8(&msg, divisor); @@ -254,6 +270,8 @@ int bt_mesh_health_fault_test(bt_mesh_client_common_param_t *param, { BLE_MESH_MODEL_BUF_DEFINE(msg, OP_HEALTH_FAULT_TEST, 3); + BT_DBG("HealthFaultTest, CID 0x%04x TestID 0x%04x NeedAck %u", cid, test_id, need_ack); + bt_mesh_model_msg_init(&msg, need_ack ? OP_HEALTH_FAULT_TEST : OP_HEALTH_FAULT_TEST_UNREL); net_buf_simple_add_u8(&msg, test_id); net_buf_simple_add_le16(&msg, cid); @@ -266,6 +284,8 @@ int bt_mesh_health_fault_clear(bt_mesh_client_common_param_t *param, { BLE_MESH_MODEL_BUF_DEFINE(msg, OP_HEALTH_FAULT_CLEAR, 2); + BT_DBG("HealthFaultClear, CID 0x%04x NeedAck %u", cid, need_ack); + bt_mesh_model_msg_init(&msg, need_ack ? OP_HEALTH_FAULT_CLEAR : OP_HEALTH_FAULT_CLEAR_UNREL); net_buf_simple_add_le16(&msg, cid); @@ -276,6 +296,8 @@ int bt_mesh_health_fault_get(bt_mesh_client_common_param_t *param, uint16_t cid) { BLE_MESH_MODEL_BUF_DEFINE(msg, OP_HEALTH_FAULT_GET, 2); + BT_DBG("HealthFaultGet, CID 0x%04x", cid); + bt_mesh_model_msg_init(&msg, OP_HEALTH_FAULT_GET); net_buf_simple_add_le16(&msg, cid); @@ -287,6 +309,8 @@ static int health_cli_init(struct bt_mesh_model *model) health_internal_data_t *internal = NULL; bt_mesh_health_client_t *client = NULL; + BT_DBG("HealthCliInit"); + if (!model) { BT_ERR("Invalid Health Client model"); return -EINVAL; @@ -328,6 +352,8 @@ static int health_cli_deinit(struct bt_mesh_model *model) { bt_mesh_health_client_t *client = NULL; + BT_DBG("HealthCliDeinit"); + if (!model) { BT_ERR("Invalid Health Client model"); return -EINVAL; diff --git a/components/bt/esp_ble_mesh/core/health_srv.c b/components/bt/esp_ble_mesh/core/health_srv.c index a27e4547b21..f7db34babb3 100644 --- a/components/bt/esp_ble_mesh/core/health_srv.c +++ b/components/bt/esp_ble_mesh/core/health_srv.c @@ -26,8 +26,7 @@ /* Health Server context of the primary element */ struct bt_mesh_health_srv *health_srv; -/** - * When an Element receives a Health Fault Get, or a Health Fault Test, or +/* When an Element receives a Health Fault Get, or a Health Fault Test, or * a Health Fault Test Unacknowledged, or a Health Fault Clear, or a Health * Fault Clear Unacknowledged message that is not successfully processed * (i.e. the Company ID field that does not identify any Health Fault state @@ -48,6 +47,8 @@ static uint8_t health_get_curr_fault_count(struct bt_mesh_model *model) } } + BT_DBG("HealthGetCurrFaultCount, Count %u", count); + return count; } @@ -61,6 +62,8 @@ static void health_get_fault_value(struct bt_mesh_model *model, array_size = current ? ARRAY_SIZE(srv->test.curr_faults) : ARRAY_SIZE(srv->test.reg_faults); + BT_DBG("HealthGetFaultValue, Current %u Size %lu", current, array_size); + for (i = 0U; i < array_size; i++) { if (net_buf_simple_tailroom(msg) == 0) { return; @@ -70,6 +73,8 @@ static void health_get_fault_value(struct bt_mesh_model *model, if (fault != HEALTH_NO_FAULT) { net_buf_simple_add_u8(msg, fault); } + + BT_DBG("%u: Fault 0x%02x", i, fault); } } @@ -78,12 +83,16 @@ static bool health_is_test_id_exist(struct bt_mesh_model *model, uint8_t test_id struct bt_mesh_health_srv *srv = model->user_data; int i; + BT_DBG("HealthIsTestIDExist, TestID 0x%02x", test_id); + for (i = 0; i < srv->test.id_count; i++) { if (srv->test.test_ids[i] == test_id) { + BT_DBG("TestIDExist"); return true; } } + BT_DBG("TestIDNotExist"); return false; } @@ -94,19 +103,23 @@ static int health_send_fault_status(struct bt_mesh_model *model, struct net_buf_simple *msg = NULL; int err = 0; + BT_DBG("HealthSendFaultStatus"); + msg = bt_mesh_alloc_buf(4 + ARRAY_SIZE(srv->test.reg_faults) + 4); if (!msg) { BT_ERR("%s, Out of memory", __func__); return -ENOMEM; } + BT_DBG("TestID 0x%02x CID 0x%04x", + srv->test.prev_test_id, srv->test.company_id); + bt_mesh_model_msg_init(msg, OP_HEALTH_FAULT_STATUS); net_buf_simple_add_u8(msg, srv->test.prev_test_id); net_buf_simple_add_le16(msg, srv->test.company_id); if (ctx->recv_op != OP_HEALTH_FAULT_CLEAR) { - /** - * For Health Fault Clear, the FaultArray field in Health Fault Status - * shall be empty. + /* For Health Fault Clear, the FaultArray field + * in Health Fault Status shall be empty. */ health_get_fault_value(model, msg, false); } @@ -127,6 +140,8 @@ static void health_fault_get(struct bt_mesh_model *model, struct bt_mesh_health_srv *srv = model->user_data; uint16_t company_id = 0U; + BT_DBG("HealthFaultGet"); + if (!srv) { BT_ERR("No Health Server context provided"); return; @@ -138,7 +153,7 @@ static void health_fault_get(struct bt_mesh_model *model, return; } - BT_DBG("company_id 0x%04x", company_id); + BT_DBG("CID 0x%04x", company_id); health_send_fault_status(model, ctx); } @@ -150,6 +165,8 @@ static void health_fault_clear(struct bt_mesh_model *model, struct bt_mesh_health_srv *srv = model->user_data; uint16_t company_id = 0U; + BT_DBG("HealthFaultClear"); + if (!srv) { BT_ERR("No Health Server context provided"); return; @@ -161,7 +178,7 @@ static void health_fault_clear(struct bt_mesh_model *model, return; } - BT_DBG("company_id 0x%04x", company_id); + BT_DBG("CID 0x%04x", company_id); memset(srv->test.reg_faults, HEALTH_NO_FAULT, ARRAY_SIZE(srv->test.reg_faults)); @@ -182,6 +199,8 @@ static void health_fault_test(struct bt_mesh_model *model, uint16_t company_id = 0U; uint8_t test_id = 0U; + BT_DBG("HealthFaultTest"); + if (!srv) { BT_ERR("No Health Server context provided"); return; @@ -199,7 +218,7 @@ static void health_fault_test(struct bt_mesh_model *model, return; } - BT_DBG("test 0x%02x company 0x%04x", test_id, company_id); + BT_DBG("TestID 0x%02x CID 0x%04x", test_id, company_id); srv->test.prev_test_id = test_id; @@ -219,13 +238,16 @@ static void send_attention_status(struct bt_mesh_model *model, struct bt_mesh_health_srv *srv = model->user_data; uint8_t time = 0U; + BT_DBG("SendAttentionStatus"); + if (!srv) { BT_ERR("No Health Server context provided"); return; } time = k_delayed_work_remaining_get(&srv->attn_timer) / 1000; - BT_DBG("%u second%s", time, (time == 1U) ? "" : "s"); + + BT_DBG("Time %u", time); bt_mesh_model_msg_init(&msg, OP_ATTENTION_STATUS); net_buf_simple_add_u8(&msg, time); @@ -239,6 +261,8 @@ static void attention_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { + BT_DBG("AttentionGet"); + send_attention_status(model, ctx); } @@ -250,7 +274,7 @@ static void health_set_attention(struct bt_mesh_model *model, time = net_buf_simple_pull_u8(buf); - BT_DBG("%u second%s", time, (time == 1U) ? "" : "s"); + BT_DBG("HealthSetAttention, Time %u", time); bt_mesh_attention(model, time); } @@ -259,6 +283,8 @@ static void attention_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { + BT_DBG("AttentionSet"); + health_set_attention(model, ctx, buf); if (ctx->recv_op == OP_ATTENTION_SET) { @@ -271,6 +297,8 @@ static void send_health_period_status(struct bt_mesh_model *model, { BLE_MESH_MODEL_BUF_DEFINE(msg, OP_HEALTH_PERIOD_STATUS, 1); + BT_DBG("SendHealthPeriodStatus"); + bt_mesh_model_msg_init(&msg, OP_HEALTH_PERIOD_STATUS); net_buf_simple_add_u8(&msg, model->pub->period_div); @@ -283,6 +311,8 @@ static void health_period_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { + BT_DBG("HealthPeriodGet"); + send_health_period_status(model, ctx); } @@ -292,13 +322,15 @@ static void health_set_period(struct bt_mesh_model *model, { uint8_t period = 0U; + BT_DBG("HealthSetPeriod"); + period = net_buf_simple_pull_u8(buf); if (period > 15) { BT_WARN("Prohibited period value %u", period); return; } - BT_DBG("period %u", period); + BT_DBG("Period %u", period); model->pub->period_div = period; } @@ -307,6 +339,8 @@ static void health_period_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) { + BT_DBG("HealthPeriodSet"); + health_set_period(model, ctx, buf); if (ctx->recv_op == OP_HEALTH_PERIOD_SET) { @@ -334,6 +368,8 @@ static size_t health_get_current(struct bt_mesh_model *model, { struct bt_mesh_health_srv *srv = model->user_data; + BT_DBG("HealthGetCurrent"); + if (!srv) { BT_ERR("No Health Server context provided"); return 0; @@ -344,6 +380,9 @@ static size_t health_get_current(struct bt_mesh_model *model, return 0; } + BT_DBG("TestID 0x%02x CID 0x%04x", + srv->test.prev_test_id, srv->test.company_id); + bt_mesh_model_msg_init(msg, OP_HEALTH_CURRENT_STATUS); net_buf_simple_add_u8(msg, srv->test.prev_test_id); net_buf_simple_add_le16(msg, srv->test.company_id); @@ -357,6 +396,8 @@ static int health_pub_update(struct bt_mesh_model *model) struct bt_mesh_model_pub *pub = model->pub; size_t count = 0U; + BT_DBG("HealthPubUpdate"); + if (!pub || !pub->msg) { BT_ERR("Invalid health publication context"); return -EINVAL; @@ -369,6 +410,8 @@ static int health_pub_update(struct bt_mesh_model *model) pub->fast_period = 0U; } + BT_DBG("Count %lu", count); + return 0; } @@ -376,6 +419,8 @@ int bt_mesh_fault_update(struct bt_mesh_elem *elem) { struct bt_mesh_model *model = NULL; + BT_DBG("FaultUpdate"); + model = bt_mesh_model_find(elem, BLE_MESH_MODEL_ID_HEALTH_SRV); if (!model) { BT_ERR("Health Server not exists"); @@ -409,6 +454,8 @@ static void attention_off(struct k_work *work) return; } + BT_DBG("AttentionOff"); + if (srv->cb.attn_off) { srv->cb.attn_off(srv->model); } @@ -423,6 +470,8 @@ static int health_srv_init(struct bt_mesh_model *model) * supported by any secondary elements. */ + BT_DBG("HealthSrvInit"); + if (!srv) { BT_ERR("No Health Server context provided"); return -EINVAL; @@ -433,6 +482,8 @@ static int health_srv_init(struct bt_mesh_model *model) return -EINVAL; } + BT_DBG("TestIDCount %u", srv->test.id_count); + if (!model->pub) { BT_ERR("Health Server has no publication support"); return -EINVAL; @@ -460,6 +511,8 @@ static int health_srv_deinit(struct bt_mesh_model *model) { struct bt_mesh_health_srv *srv = model->user_data; + BT_DBG("HealthSrvDeinit"); + if (!srv) { BT_ERR("No Health Server context provided"); return -EINVAL; @@ -499,6 +552,8 @@ void bt_mesh_attention(struct bt_mesh_model *model, uint8_t time) { struct bt_mesh_health_srv *srv = NULL; + BT_DBG("Attention, Time %u", time); + if (!model) { srv = health_srv; if (!srv) { diff --git a/components/bt/esp_ble_mesh/core/heartbeat.c b/components/bt/esp_ble_mesh/core/heartbeat.c index 4ff63a13abe..4324da32234 100644 --- a/components/bt/esp_ble_mesh/core/heartbeat.c +++ b/components/bt/esp_ble_mesh/core/heartbeat.c @@ -21,11 +21,15 @@ static uint16_t hb_sub_dst = BLE_MESH_ADDR_UNASSIGNED; void bt_mesh_set_hb_sub_dst(uint16_t addr) { + BT_DBG("SetHbSubDst 0x%04x", addr); + hb_sub_dst = addr; } uint16_t bt_mesh_get_hb_sub_dst(void) { + BT_DBG("GetHbSubDst 0x%04x", hb_sub_dst); + return hb_sub_dst; } @@ -33,6 +37,9 @@ void bt_mesh_heartbeat_recv(uint16_t src, uint16_t dst, uint8_t hops, uint16_t f { struct bt_mesh_cfg_srv *cfg = bt_mesh_cfg_get(); + BT_DBG("HeartbeatRecv"); + BT_DBG("Src 0x%04x Dst 0x%04x Hops %u Feat 0x%04x", src, dst, hops, feat); + if (cfg == NULL) { BT_WARN("No configuration server context available"); return; @@ -55,9 +62,8 @@ void bt_mesh_heartbeat_recv(uint16_t src, uint16_t dst, uint8_t hops, uint16_t f cfg->hb_sub.count++; } - BT_DBG("src 0x%04x dst 0x%04x hops %u min %u max %u count %u", src, - dst, hops, cfg->hb_sub.min_hops, cfg->hb_sub.max_hops, - cfg->hb_sub.count); + BT_DBG("MinHops %u MaxHops %u Count %u", + cfg->hb_sub.min_hops, cfg->hb_sub.max_hops, cfg->hb_sub.count); if (cfg->hb_sub.func) { cfg->hb_sub.func(hops, feat); @@ -67,7 +73,6 @@ void bt_mesh_heartbeat_recv(uint16_t src, uint16_t dst, uint8_t hops, uint16_t f void bt_mesh_heartbeat_send(void) { struct bt_mesh_cfg_srv *cfg = bt_mesh_cfg_get(); - uint16_t feat = 0U; struct __attribute__((packed)) { uint8_t init_ttl; uint16_t feat; @@ -85,6 +90,9 @@ void bt_mesh_heartbeat_send(void) .src = bt_mesh_model_elem(cfg->model)->addr, .xmit = bt_mesh_net_transmit_get(), }; + uint16_t feat = 0U; + + BT_DBG("HeartbeatSend, Dst 0x%04x", cfg->hb_pub.dst); /* Do nothing if heartbeat publication is not enabled */ if (cfg->hb_pub.dst == BLE_MESH_ADDR_UNASSIGNED) { @@ -111,7 +119,7 @@ void bt_mesh_heartbeat_send(void) hb.feat = sys_cpu_to_be16(feat); - BT_INFO("InitTTL %u feat 0x%04x", cfg->hb_pub.ttl, feat); + BT_INFO("InitTTL %u Feat 0x%04x", cfg->hb_pub.ttl, feat); bt_mesh_ctl_send(&tx, TRANS_CTL_OP_HEARTBEAT, &hb, sizeof(hb), NULL, NULL); @@ -149,6 +157,8 @@ int bt_mesh_pvnr_register_hb_recv_cb(bt_mesh_pvnr_hb_recv_cb_t cb) int bt_mesh_pvnr_set_hb_recv_filter_type(uint8_t type) { + BT_DBG("PvnrSetHbRecvFilterType"); + if (type > HEARTBEAT_FILTER_REJECTLIST) { BT_ERR("Invalid heartbeat filter type 0x%02x", type); return -EINVAL; @@ -158,6 +168,8 @@ int bt_mesh_pvnr_set_hb_recv_filter_type(uint8_t type) * clear the existing filter entries. */ if (hb_rx.type != type) { + BT_DBG("OldType %u NewType %u", hb_rx.type, type); + memset(&hb_rx, 0, offsetof(struct heartbeat_recv, cb)); hb_rx.type = type; } @@ -169,6 +181,8 @@ static int hb_filter_alloc(uint16_t src, uint16_t dst) { int i; + BT_DBG("HbFilterAlloc, Src 0x%04x Dst 0x%04x", src, dst); + for (i = 0; i < ARRAY_SIZE(hb_rx.filter); i++) { struct heartbeat_filter *filter = &hb_rx.filter[i]; @@ -180,7 +194,7 @@ static int hb_filter_alloc(uint16_t src, uint16_t dst) } } - BT_ERR("Heartbeat filter is full!"); + BT_ERR("HbFilterFull"); return -ENOMEM; } @@ -188,6 +202,8 @@ static int hb_filter_add(uint16_t src, uint16_t dst) { int i; + BT_DBG("HbFilterAdd, Src 0x%04x Dst 0x%04x", src, dst); + if (!(BLE_MESH_ADDR_IS_UNICAST(src) && (BLE_MESH_ADDR_IS_UNICAST(dst) || BLE_MESH_ADDR_IS_GROUP(dst)))) { BT_ERR("Invalid filter address, src 0x%04x, dst 0x%04x", src, dst); @@ -199,7 +215,7 @@ static int hb_filter_add(uint16_t src, uint16_t dst) struct heartbeat_filter *filter = &hb_rx.filter[i]; if (filter->src == src && filter->dst == dst) { - BT_WARN("Filter already exists, src 0x%04x dst 0x%04x", filter->src, filter->dst); + BT_DBG("FilterIndex %u", i); return 0; } } @@ -211,6 +227,8 @@ static int hb_filter_remove(uint16_t src, uint16_t dst) { int i; + BT_DBG("HbFilterRemove, Src 0x%04x Dst 0x%04x", src, dst); + if (!(BLE_MESH_ADDR_IS_UNICAST(src) && (BLE_MESH_ADDR_IS_UNICAST(dst) || BLE_MESH_ADDR_IS_GROUP(dst)))) { BT_ERR("Invalid filter address, src 0x%04x, dst 0x%04x", src, dst); @@ -221,6 +239,7 @@ static int hb_filter_remove(uint16_t src, uint16_t dst) struct heartbeat_filter *filter = &hb_rx.filter[i]; if (filter->src == src && filter->dst == dst) { + BT_DBG("FilterIndex %u", i); memset(filter, 0, sizeof(struct heartbeat_filter)); } } @@ -236,7 +255,7 @@ int bt_mesh_pvnr_set_hb_recv_filter_info(uint8_t op, uint16_t src, uint16_t dst) case HEARTBEAT_FILTER_REMOVE: return hb_filter_remove(src, dst); default: - BT_ERR("Invalid heartbeat filter opcode 0x%02x", op); + BT_ERR("Invalid HbFilterOpCode 0x%02x", op); return -EINVAL; } } @@ -248,6 +267,7 @@ static bool filter_with_rejectlist(uint16_t hb_src, uint16_t hb_dst) for (i = 0; i < ARRAY_SIZE(hb_rx.filter); i++) { struct heartbeat_filter *filter = &hb_rx.filter[i]; if (hb_src == filter->src && hb_dst == filter->dst) { + BT_DBG("InRejectList, Src 0x%04x Dst 0x%04x", hb_src, hb_dst); return true; } } @@ -262,6 +282,7 @@ static bool filter_with_acceptlist(uint16_t hb_src, uint16_t hb_dst) for (i = 0; i < ARRAY_SIZE(hb_rx.filter); i++) { struct heartbeat_filter *filter = &hb_rx.filter[i]; if (hb_src == filter->src && hb_dst == filter->dst) { + BT_DBG("InAcceptList, Src 0x%04x Dst 0x%04x", hb_src, hb_dst); return false; } } @@ -273,6 +294,8 @@ void bt_mesh_pvnr_heartbeat_recv(uint16_t hb_src, uint16_t hb_dst, uint8_t init_ttl, uint8_t rx_ttl, uint8_t hops, uint16_t feat, int8_t rssi) { + BT_DBG("PvnrHeartbeatRecv"); + if (hb_rx.cb == NULL) { BT_DBG("Receiving heartbeat is not enabled"); return; @@ -280,16 +303,17 @@ void bt_mesh_pvnr_heartbeat_recv(uint16_t hb_src, uint16_t hb_dst, if (hb_rx.type == HEARTBEAT_FILTER_REJECTLIST) { if (filter_with_rejectlist(hb_src, hb_dst)) { - BT_INFO("Filtered by rejectlist, src 0x%04x, dst 0x%04x", hb_src, hb_dst); return; } } else { if (filter_with_acceptlist(hb_src, hb_dst)) { - BT_INFO("Filtered by acceptlist, src 0x%04x, dst 0x%04x", hb_src, hb_dst); return; } } + BT_DBG("Src 0x%04x Dst 0x%04x InitTTL %u RxTTL %u Hops %u Feat 0x%04x Rssi %d", + hb_src, hb_dst, init_ttl, rx_ttl, hops, feat, rssi); + if (hb_rx.cb) { hb_rx.cb(hb_src, hb_dst, init_ttl, rx_ttl, hops, feat, rssi); } diff --git a/components/bt/esp_ble_mesh/core/local.c b/components/bt/esp_ble_mesh/core/local.c index 4451e0d7b26..fb933cc804a 100644 --- a/components/bt/esp_ble_mesh/core/local.c +++ b/components/bt/esp_ble_mesh/core/local.c @@ -22,14 +22,17 @@ static struct bt_mesh_model *find_model(uint16_t elem_addr, uint16_t cid, uint16 { struct bt_mesh_elem *elem = NULL; + BT_DBG("FindModelLocal"); + BT_DBG("ElemAddr 0x%04x CID 0x%04x ID 0x%04x", elem_addr, cid, mod_id); + if (!BLE_MESH_ADDR_IS_UNICAST(elem_addr)) { - BT_ERR("Invalid unicast address 0x%04x", elem_addr); + BT_ERR("InvalidUnicastAddr 0x%04x", elem_addr); return NULL; } elem = bt_mesh_elem_find(elem_addr); if (elem == NULL) { - BT_ERR("No element found, addr 0x%04x", elem_addr); + BT_ERR("NoElemFound 0x%04x", elem_addr); return NULL; } @@ -46,19 +49,23 @@ int bt_mesh_model_subscribe_group_addr(uint16_t elem_addr, uint16_t cid, struct bt_mesh_model *model = NULL; int i; + BT_DBG("ModelSubGroupAddrLocal"); + BT_DBG("ElemAddr 0x%04x CID 0x%04x ID 0x%04x GroupAddr 0x%04x", + elem_addr, cid, mod_id, group_addr); + model = find_model(elem_addr, cid, mod_id); if (model == NULL) { - BT_ERR("Subscribe, model not found, cid 0x%04x, mod_id 0x%04x", cid, mod_id); + BT_ERR("ModelNotFound, CID 0x%04x ID 0x%04x", cid, mod_id); return -ENODEV; } if (!BLE_MESH_ADDR_IS_GROUP(group_addr)) { - BT_ERR("Subscribe, not a group address 0x%04x", group_addr); + BT_ERR("NotGroupAddr 0x%04x", group_addr); return -EINVAL; } if (bt_mesh_model_find_group(model, group_addr)) { - BT_INFO("Group address 0x%04x already exists", group_addr); + BT_INFO("GroupAddrExist 0x%04x", group_addr); return 0; } @@ -74,12 +81,11 @@ int bt_mesh_model_subscribe_group_addr(uint16_t elem_addr, uint16_t cid, bt_mesh_lpn_group_add(group_addr); } - BT_INFO("Subscribe group address 0x%04x", group_addr); return 0; } } - BT_ERR("Subscribe, model sub is full!"); + BT_ERR("ModelSubFull"); return -ENOMEM; } @@ -89,20 +95,24 @@ int bt_mesh_model_unsubscribe_group_addr(uint16_t elem_addr, uint16_t cid, struct bt_mesh_model *model = NULL; uint16_t *match = NULL; + BT_DBG("ModelUnsubGroupAddrLocal"); + BT_DBG("ElemAddr 0x%04x CID 0x%04x ID 0x%04x GroupAddr 0x%04x", + elem_addr, cid, mod_id, group_addr); + model = find_model(elem_addr, cid, mod_id); if (model == NULL) { - BT_ERR("Unsubscribe, model not found, cid 0x%04x, mod_id 0x%04x", cid, mod_id); + BT_ERR("ModelNotFound, CID 0x%04x ID 0x%04x", cid, mod_id); return -ENODEV; } if (!BLE_MESH_ADDR_IS_GROUP(group_addr)) { - BT_ERR("Unsubscribe, not a group address 0x%04x", group_addr); + BT_ERR("NotGroupAddr 0x%04x", group_addr); return -EINVAL; } match = bt_mesh_model_find_group(model, group_addr); if (match == NULL) { - BT_WARN("Group address 0x%04x not exists", group_addr); + BT_WARN("GroupAddrExist 0x%04x", group_addr); return -EEXIST; } @@ -116,7 +126,6 @@ int bt_mesh_model_unsubscribe_group_addr(uint16_t elem_addr, uint16_t cid, bt_mesh_lpn_group_del(&group_addr, 1); } - BT_INFO("Unsubscribe group address 0x%04x", group_addr); return 0; } @@ -126,20 +135,24 @@ int bt_mesh_enable_directed_forwarding(uint16_t net_idx, bool directed_forwardin { struct bt_mesh_subnet *sub = NULL; + BT_DBG("EnableDFLocal, NetIdx 0x%04x DF %u DFRelay %u", + net_idx, directed_forwarding, directed_forwarding_relay); + if (net_idx > 0xFFF) { - BT_ERR("Invalid NetKeyIndex 0x%04x", net_idx); + BT_ERR("InvalidNetIdx 0x%04x", net_idx); return -EINVAL; } sub = bt_mesh_subnet_get(net_idx); if (!sub) { - BT_ERR("NetKey 0x%04x not exists", net_idx); + BT_ERR("NetIdxNotExist 0x%04x", net_idx); return -EINVAL; } if (directed_forwarding == BLE_MESH_DIRECTED_FORWARDING_DISABLED && directed_forwarding_relay == BLE_MESH_DIRECTED_RELAY_ENABLED) { - BT_ERR("Invalid Config directed forwarding: %d, directed forwarding relay: %d", directed_forwarding, directed_forwarding_relay); + BT_ERR("InvalidDFConfig %u/%u", + directed_forwarding, directed_forwarding_relay); return -EINVAL; } @@ -155,14 +168,16 @@ const uint8_t *bt_mesh_node_get_local_net_key(uint16_t net_idx) { struct bt_mesh_subnet *sub = NULL; + BT_DBG("NodeGetNetKeyLocal, NetIdx 0x%04x", net_idx); + if (net_idx > 0xFFF) { - BT_ERR("Invalid NetKeyIndex 0x%04x", net_idx); + BT_ERR("InvalidNetIdx 0x%04x", net_idx); return NULL; } sub = bt_mesh_subnet_get(net_idx); if (!sub) { - BT_ERR("NetKey 0x%04x not exists", net_idx); + BT_ERR("NetIdxNotExist 0x%04x", net_idx); return NULL; } @@ -173,14 +188,16 @@ const uint8_t *bt_mesh_node_get_local_app_key(uint16_t app_idx) { struct bt_mesh_app_key *key = NULL; + BT_DBG("NodeGetAppKeyLocal, AppIdx 0x%04x", app_idx); + if (app_idx > 0xFFF) { - BT_ERR("Invalid AppKeyIndex 0x%04x", app_idx); + BT_ERR("InvalidAppIdx 0x%04x", app_idx); return NULL; } key = bt_mesh_app_key_get(app_idx); if (!key) { - BT_ERR("AppKey 0x%04x not exists", app_idx); + BT_ERR("AppIdxNotExist 0x%04x", app_idx); return NULL; } @@ -193,19 +210,21 @@ int bt_mesh_node_local_net_key_add(uint16_t net_idx, const uint8_t net_key[16]) int err = 0; int i; + BT_DBG("NodeAddNetKeyLocal, NetIdx 0x%04x", net_idx); + if (net_idx > 0xFFF || net_key == NULL) { BT_ERR("%s, Invalid parameter", __func__); return -EINVAL; } if (!bt_mesh_is_provisioned()) { - BT_ERR("Not provisioned, failed to add NetKey"); + BT_ERR("NotProvisioned"); return -EIO; } sub = bt_mesh_subnet_get(net_idx); if (sub) { - BT_WARN("NetKey 0x%04x already exists", net_idx); + BT_WARN("NetIdxExist 0x%04x", net_idx); return -EEXIST; } @@ -215,7 +234,7 @@ int bt_mesh_node_local_net_key_add(uint16_t net_idx, const uint8_t net_key[16]) memcmp(bt_mesh.sub[i].keys[0].net, net_key, 16) == 0) || (bt_mesh.sub[i].kr_flag == true && memcmp(bt_mesh.sub[i].keys[1].net, net_key, 16) == 0)) { - BT_WARN("Key value %s already exists", bt_hex(net_key, 16)); + BT_WARN("NetKeyValExist %s", bt_hex(net_key, 16)); return -EEXIST; } } @@ -229,13 +248,13 @@ int bt_mesh_node_local_net_key_add(uint16_t net_idx, const uint8_t net_key[16]) } if (sub == NULL) { - BT_ERR("NetKey is full!"); + BT_ERR("NetKeyFull"); return -ENOMEM; } err = bt_mesh_net_keys_create(&sub->keys[0], net_key); if (err) { - BT_ERR("Failed to create keys for NetKey 0x%04x", net_idx); + BT_ERR("NetKeyCreateFail 0x%04x", net_idx); return -EIO; } @@ -249,7 +268,6 @@ int bt_mesh_node_local_net_key_add(uint16_t net_idx, const uint8_t net_key[16]) } if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) { - BT_DBG("Storing NetKey persistently"); bt_mesh_store_subnet(sub); } @@ -264,24 +282,26 @@ int bt_mesh_node_local_app_key_add(uint16_t net_idx, uint16_t app_idx, { struct bt_mesh_app_key *key = NULL; + BT_DBG("NodeAddAppKeyLocal, NetIdx 0x%04x AppIdx 0x%04x", net_idx, app_idx); + if (net_idx > 0xFFF || app_idx > 0xFFF || app_key == NULL) { BT_ERR("%s, Invalid parameter", __func__); return -EINVAL; } if (!bt_mesh_is_provisioned()) { - BT_ERR("Not provisioned, failed to add AppKey"); + BT_ERR("NotProvisioned"); return -EIO; } if (bt_mesh_subnet_get(net_idx) == NULL) { - BT_ERR("Subnet 0x%04x not exists", net_idx); + BT_ERR("NetIdxNotExist 0x%04x", net_idx); return -EIO; } key = bt_mesh_app_key_get(app_idx); if (key) { - BT_WARN("AppKey 0x%04x already exists", app_idx); + BT_WARN("AppIdxExist 0x%04x", app_idx); return -EEXIST; } @@ -291,7 +311,7 @@ int bt_mesh_node_local_app_key_add(uint16_t net_idx, uint16_t app_idx, memcmp(bt_mesh.app_keys[i].keys[0].val, app_key, 16) == 0) || (bt_mesh.app_keys[i].updated == true && memcmp(bt_mesh.app_keys[i].keys[1].val, app_key, 16) == 0)) { - BT_WARN("Key value %s already exists", bt_hex(app_key, 16)); + BT_WARN("AppKeyValExist %s", bt_hex(app_key, 16)); return -EEXIST; } } @@ -302,7 +322,7 @@ int bt_mesh_node_local_app_key_add(uint16_t net_idx, uint16_t app_idx, struct bt_mesh_app_keys *keys = &key->keys[0]; if (bt_mesh_app_id(app_key, &keys->id)) { - BT_ERR("Failed to generate AID"); + BT_ERR("GenAIDFail"); return -EIO; } @@ -312,15 +332,12 @@ int bt_mesh_node_local_app_key_add(uint16_t net_idx, uint16_t app_idx, memcpy(keys->val, app_key, 16); if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) { - BT_DBG("Storing AppKey persistently"); bt_mesh_store_app_key(key); } - BT_INFO("Add AppKey 0x%04x, NetKeyIndex 0x%04x", app_idx, net_idx); return 0; } - BT_ERR("AppKey is full!"); return -ENOMEM; } @@ -330,25 +347,29 @@ int bt_mesh_node_bind_app_key_to_model(uint16_t elem_addr, uint16_t mod_id, struct bt_mesh_model *model = NULL; int i; + BT_DBG("NodeBindAppKeyLocal"); + BT_DBG("ElemAddr 0x%04x CID 0x%04x ID 0x%04x AppIdx 0x%04x", + elem_addr, cid, mod_id, app_idx); + if (!bt_mesh_is_provisioned()) { - BT_ERR("Not provisioned, failed to bind AppKey"); + BT_ERR("NotProvisioned"); return -EIO; } model = find_model(elem_addr, cid, mod_id); if (model == NULL) { - BT_ERR("Bind, model(id 0x%04x, cid 0x%04x) not found", mod_id, cid); + BT_ERR("ModelNotFound, ID 0x%04x CID 0x%04x", mod_id, cid); return -ENODEV; } if (bt_mesh_app_key_get(app_idx) == NULL) { - BT_ERR("Bind, AppKey 0x%03x not exists", app_idx); + BT_ERR("AppIdxNotExist 0x%04x", app_idx); return -ENODEV; } for (i = 0; i < ARRAY_SIZE(model->keys); i++) { if (model->keys[i] == app_idx) { - BT_WARN("Already bound to AppKey 0x%04x", app_idx); + BT_WARN("AppIdxBound 0x%04x", app_idx); return -EALREADY; } } @@ -356,16 +377,16 @@ int bt_mesh_node_bind_app_key_to_model(uint16_t elem_addr, uint16_t mod_id, for (i = 0; i < ARRAY_SIZE(model->keys); i++) { if (model->keys[i] == BLE_MESH_KEY_UNUSED) { model->keys[i] = app_idx; + if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) { bt_mesh_store_mod_bind(model); } - BT_INFO("Model(id 0x%04x, cid 0x%04x) bound to AppKey 0x%04x", mod_id, cid, app_idx); return 0; } } - BT_ERR("Model bound is full!"); + BT_ERR("ModelBindFull"); return -ENOMEM; } #endif /* CONFIG_BLE_MESH_NODE */ diff --git a/components/bt/esp_ble_mesh/core/lpn.c b/components/bt/esp_ble_mesh/core/lpn.c index 80f5b4321af..a38b0944e4d 100644 --- a/components/bt/esp_ble_mesh/core/lpn.c +++ b/components/bt/esp_ble_mesh/core/lpn.c @@ -81,30 +81,30 @@ static const char *state2str(int state) { switch (state) { case BLE_MESH_LPN_DISABLED: - return "disabled"; + return "Disabled"; case BLE_MESH_LPN_CLEAR: - return "clear"; + return "Clear"; case BLE_MESH_LPN_TIMER: - return "timer"; + return "Timer"; case BLE_MESH_LPN_ENABLED: - return "enabled"; + return "Enabled"; case BLE_MESH_LPN_REQ_WAIT: - return "req wait"; + return "ReqWait"; case BLE_MESH_LPN_WAIT_OFFER: - return "wait offer"; + return "WaitOffer"; case BLE_MESH_LPN_ESTABLISHED: - return "established"; + return "Established"; case BLE_MESH_LPN_RECV_DELAY: - return "recv delay"; + return "RecvDelay"; case BLE_MESH_LPN_WAIT_UPDATE: - return "wait update"; + return "WaitUpdate"; case BLE_MESH_LPN_OFFER_RECV: - return "offer recv"; + return "OfferRecv"; default: - return "(unknown)"; + return "(Unknown)"; } } -#endif +#endif /* !CONFIG_BLE_MESH_NO_LOG */ static inline void lpn_set_state(int state) { @@ -120,9 +120,9 @@ static inline void group_zero(bt_mesh_atomic_t *target) for (i = 0; i < ARRAY_SIZE(bt_mesh.lpn.added); i++) { bt_mesh_atomic_set(&target[i], 0); } -#else +#else /* CONFIG_BLE_MESH_LPN_GROUPS > 32 */ bt_mesh_atomic_set(target, 0); -#endif +#endif /* CONFIG_BLE_MESH_LPN_GROUPS > 32 */ } static inline void group_set(bt_mesh_atomic_t *target, bt_mesh_atomic_t *source) @@ -133,9 +133,9 @@ static inline void group_set(bt_mesh_atomic_t *target, bt_mesh_atomic_t *source) for (i = 0; i < ARRAY_SIZE(bt_mesh.lpn.added); i++) { (void)bt_mesh_atomic_or(&target[i], bt_mesh_atomic_get(&source[i])); } -#else +#else /* CONFIG_BLE_MESH_LPN_GROUPS > 32 */ (void)bt_mesh_atomic_or(target, bt_mesh_atomic_get(source)); -#endif +#endif /* CONFIG_BLE_MESH_LPN_GROUPS > 32 */ } static inline void group_clear(bt_mesh_atomic_t *target, bt_mesh_atomic_t *source) @@ -146,9 +146,9 @@ static inline void group_clear(bt_mesh_atomic_t *target, bt_mesh_atomic_t *sourc for (i = 0; i < ARRAY_SIZE(bt_mesh.lpn.added); i++) { (void)bt_mesh_atomic_and(&target[i], ~bt_mesh_atomic_get(&source[i])); } -#else +#else /* CONFIG_BLE_MESH_LPN_GROUPS > 32 */ (void)bt_mesh_atomic_and(target, ~bt_mesh_atomic_get(source)); -#endif +#endif /* CONFIG_BLE_MESH_LPN_GROUPS > 32 */ } static void clear_friendship(bool force, bool disable); @@ -159,6 +159,8 @@ static void friend_clear_sent(int err, void *user_data) { struct bt_mesh_lpn *lpn = &bt_mesh.lpn; + BT_DBG("FrndClearSent, Err %d", err); + /* We're switching away from Low Power behavior, so permanently * enable scanning. */ @@ -169,6 +171,8 @@ static void friend_clear_sent(int err, void *user_data) lpn->req_attempts++; + BT_DBG("ReqAttempts %u", lpn->req_attempts); + if (err) { BT_ERR("Sending Friend Clear failed (err %d)", err); lpn_set_state(BLE_MESH_LPN_ENABLED); @@ -206,6 +210,8 @@ static int send_friend_clear(void) .lpn_counter = sys_cpu_to_be16(bt_mesh.lpn.counter), }; + BT_DBG("SendFrndClear"); + return bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_CLEAR, &req, sizeof(req), &clear_sent_cb, NULL); } @@ -215,10 +221,12 @@ static void clear_friendship(bool force, bool disable) struct bt_mesh_cfg_srv *cfg = bt_mesh_cfg_get(); struct bt_mesh_lpn *lpn = &bt_mesh.lpn; - BT_DBG("force %u disable %u", force, disable); + BT_DBG("ClearFriendship, Force %u Disable %u", force, disable); if (!force && lpn->established && !lpn->clear_success && lpn->req_attempts < CLEAR_ATTEMPTS) { + BT_DBG("SendFrndClear, ReqAttempts %u", lpn->req_attempts); + send_friend_clear(); lpn->disable = disable; return; @@ -253,7 +261,7 @@ static void clear_friendship(bool force, bool disable) bt_mesh_restore_directed_forwarding_state(bt_mesh.sub[0].net_idx, lpn->old_directed_forwarding); } -#endif +#endif /* CONFIG_BLE_MESH_DF_SRV */ lpn->frnd = BLE_MESH_ADDR_UNASSIGNED; lpn->fsn = 0U; @@ -306,6 +314,8 @@ static void friend_req_sent(uint16_t duration, int err, void *user_data) return; } + BT_DBG("FrndReqSent, duration %u", duration); + lpn->adv_duration = duration; if (IS_ENABLED(CONFIG_BLE_MESH_LPN_ESTABLISHMENT)) { @@ -349,6 +359,8 @@ static int send_friend_req(struct bt_mesh_lpn *lpn) .lpn_counter = sys_cpu_to_be16(lpn->counter), }; + BT_DBG("SendFrndReq, NetIdx 0x%04x", ctx.net_idx); + return bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_REQ, &req, sizeof(req), &friend_req_sent_cb, NULL); } @@ -357,7 +369,7 @@ static void req_sent(uint16_t duration, int err, void *user_data) { struct bt_mesh_lpn *lpn = &bt_mesh.lpn; - BT_DBG("req 0x%02x duration %u err %d state %s", + BT_DBG("ReqSent, Req 0x%02x Duration %u Err %d State %s", lpn->sent_req, duration, err, state2str(lpn->state)); if (err) { @@ -372,6 +384,9 @@ static void req_sent(uint16_t duration, int err, void *user_data) if (lpn->established || IS_ENABLED(CONFIG_BLE_MESH_LPN_ESTABLISHMENT)) { lpn_set_state(BLE_MESH_LPN_RECV_DELAY); + + BT_DBG("RecvDelay %u ScanLatency %u", LPN_RECV_DELAY, SCAN_LATENCY); + /* We start scanning a bit early to eliminate risk of missing * response data due to HCI and other latencies. */ @@ -379,6 +394,9 @@ static void req_sent(uint16_t duration, int err, void *user_data) LPN_RECV_DELAY - SCAN_LATENCY); } else { lpn_set_state(BLE_MESH_LPN_OFFER_RECV); + + BT_DBG("RecvDelay %u RecvWin %u", LPN_RECV_DELAY, lpn->recv_win); + /** * Friend Update is replied by Friend Node with TTL set to 0 and Network * Transmit set to 30ms which will cause the packet easy to be missed. @@ -416,7 +434,7 @@ static int send_friend_poll(void) uint8_t fsn = lpn->fsn; int err = 0; - BT_DBG("lpn->sent_req 0x%02x", lpn->sent_req); + BT_DBG("SendFrndPoll, Req 0x%02x ", lpn->sent_req); if (lpn->sent_req) { if (lpn->sent_req != TRANS_CTL_OP_FRIEND_POLL) { @@ -438,6 +456,8 @@ static int send_friend_poll(void) void bt_mesh_lpn_disable(bool force) { + BT_DBG("LPNDisable, Force %u State 0x%02x", force, bt_mesh.lpn.state); + if (bt_mesh.lpn.state == BLE_MESH_LPN_DISABLED) { return; } @@ -449,6 +469,8 @@ int bt_mesh_lpn_set(bool enable, bool force) { struct bt_mesh_lpn *lpn = &bt_mesh.lpn; + BT_DBG("LPNSet, Enable %u Force %u State 0x%02x", enable, force, lpn->state); + if (enable) { if (lpn->state != BLE_MESH_LPN_DISABLED) { return 0; @@ -479,7 +501,7 @@ int bt_mesh_lpn_set(bool enable, bool force) send_friend_req(lpn); } else { if (IS_ENABLED(CONFIG_BLE_MESH_LPN_AUTO) && - lpn->state == BLE_MESH_LPN_TIMER) { + lpn->state == BLE_MESH_LPN_TIMER) { k_delayed_work_cancel(&lpn->timer); lpn_set_state(BLE_MESH_LPN_DISABLED); } else { @@ -492,7 +514,7 @@ int bt_mesh_lpn_set(bool enable, bool force) static void friend_response_received(struct bt_mesh_lpn *lpn) { - BT_DBG("lpn->sent_req 0x%02x", lpn->sent_req); + BT_DBG("FrndRspRecv, Req 0x%02x Fsn %u", lpn->sent_req, lpn->fsn); if (lpn->sent_req == TRANS_CTL_OP_FRIEND_POLL) { lpn->fsn++; @@ -509,6 +531,8 @@ void bt_mesh_lpn_msg_received(struct bt_mesh_net_rx *rx) { struct bt_mesh_lpn *lpn = &bt_mesh.lpn; + BT_DBG("LPNMsgRecv, Req 0x%02x State 0x%02x", lpn->sent_req, lpn->state); + if (lpn->state == BLE_MESH_LPN_TIMER) { BT_DBG("Restarting establishment timer"); k_delayed_work_submit(&lpn->timer, LPN_AUTO_TIMEOUT); @@ -522,8 +546,6 @@ void bt_mesh_lpn_msg_received(struct bt_mesh_net_rx *rx) friend_response_received(lpn); - BT_DBG("Requesting more messages from Friend"); - send_friend_poll(); } @@ -537,6 +559,8 @@ int bt_mesh_lpn_friend_offer(struct bt_mesh_net_rx *rx, uint16_t frnd_counter = 0U; int err = 0; + BT_DBG("LPNFrndOffer"); + if (buf->len < sizeof(*msg)) { BT_WARN("Too short Friend Offer"); return -EINVAL; @@ -554,9 +578,9 @@ int bt_mesh_lpn_friend_offer(struct bt_mesh_net_rx *rx, frnd_counter = sys_be16_to_cpu(msg->frnd_counter); - BT_INFO("recv_win %u queue_size %u sub_list_size %u rssi %d counter %u", - msg->recv_win, msg->queue_size, msg->sub_list_size, msg->rssi, - frnd_counter); + BT_INFO("Frnd 0x%04x RecvWin %u QueueSize %u SubListSize %u FrndCounter %u Rssi %d", + rx->ctx.addr, msg->recv_win, msg->queue_size, + msg->sub_list_size, frnd_counter, msg->rssi); lpn->frnd = rx->ctx.addr; @@ -575,6 +599,8 @@ int bt_mesh_lpn_friend_offer(struct bt_mesh_net_rx *rx, err = send_friend_poll(); if (err) { + BT_ERR("SendFrndPollFailed, Err %d", err); + friend_cred_clear(cred); lpn->frnd = BLE_MESH_ADDR_UNASSIGNED; lpn->recv_win = 0U; @@ -598,6 +624,8 @@ int bt_mesh_lpn_friend_clear_cfm(struct bt_mesh_net_rx *rx, struct bt_mesh_lpn *lpn = &bt_mesh.lpn; uint16_t addr = 0U, counter = 0U; + BT_DBG("LPNFrndClearCFM"); + if (buf->len < sizeof(*msg)) { BT_WARN("Too short Friend Clear Confirm"); return -EINVAL; @@ -611,7 +639,7 @@ int bt_mesh_lpn_friend_clear_cfm(struct bt_mesh_net_rx *rx, addr = sys_be16_to_cpu(msg->lpn_addr); counter = sys_be16_to_cpu(msg->lpn_counter); - BT_DBG("LPNAddress 0x%04x LPNCounter 0x%04x", addr, counter); + BT_DBG("LPN 0x%04x Counter 0x%04x", addr, counter); if (addr != bt_mesh_primary_addr() || counter != lpn->counter) { BT_WARN("Invalid parameters in Friend Clear Confirm"); @@ -630,8 +658,11 @@ static void lpn_group_add(uint16_t group) uint16_t *free_slot = NULL; int i; + BT_DBG("LPNGroupAdd, Addr 0x%04x", group); + for (i = 0; i < ARRAY_SIZE(lpn->groups); i++) { if (lpn->groups[i] == group) { + BT_DBG("ClearLPNToRemove"); bt_mesh_atomic_clear_bit(lpn->to_remove, i); return; } @@ -655,10 +686,13 @@ static void lpn_group_del(uint16_t group) struct bt_mesh_lpn *lpn = &bt_mesh.lpn; int i; + BT_DBG("LPNGroupDel, Addr 0x%04x", group); + for (i = 0; i < ARRAY_SIZE(lpn->groups); i++) { if (lpn->groups[i] == group) { if (bt_mesh_atomic_test_bit(lpn->added, i) || bt_mesh_atomic_test_bit(lpn->pending, i)) { + BT_DBG("Set LPNToRemove"); bt_mesh_atomic_set_bit(lpn->to_remove, i); lpn->groups_changed = 1U; } else { @@ -676,9 +710,9 @@ static inline int group_popcount(bt_mesh_atomic_t *target) for (i = 0; i < ARRAY_SIZE(bt_mesh.lpn.added); i++) { count += popcount(bt_mesh_atomic_get(&target[i])); } -#else +#else /* CONFIG_BLE_MESH_LPN_GROUPS > 32 */ return popcount(bt_mesh_atomic_get(target)); -#endif +#endif /* CONFIG_BLE_MESH_LPN_GROUPS > 32 */ } static bool sub_update(uint8_t op) @@ -703,7 +737,7 @@ static bool sub_update(uint8_t op) struct bt_mesh_ctl_friend_sub req = {0}; size_t i = 0U, g = 0U; - BT_DBG("op 0x%02x sent_req 0x%02x", op, lpn->sent_req); + BT_DBG("SubUpdate, OP 0x%02x Req 0x%02x ", op, lpn->sent_req); if (lpn->sent_req) { return false; @@ -725,7 +759,8 @@ static bool sub_update(uint8_t op) } if (added_count + g >= lpn->queue_size) { - BT_WARN("Friend Queue Size exceeded"); + BT_WARN("FrndQueueExceeded, Added %u G %u Size %u", + added_count, g, lpn->queue_size); break; } @@ -744,6 +779,8 @@ static bool sub_update(uint8_t op) req.xact = lpn->xact_next++; + BT_DBG("Xact %u G %u", req.xact, g); + if (bt_mesh_ctl_send(&tx, op, &req, 1 + g * 2, &req_sent_cb, NULL) < 0) { group_zero(lpn->pending); @@ -752,14 +789,19 @@ static bool sub_update(uint8_t op) lpn->xact_pending = req.xact; lpn->sent_req = op; + return true; } static void update_timeout(struct bt_mesh_lpn *lpn) { + BT_DBG("UpdateTimeout"); + if (lpn->established) { BT_WARN("No response from Friend during ReceiveWindow"); + bt_mesh_scan_disable(); + lpn_set_state(BLE_MESH_LPN_ESTABLISHED); k_delayed_work_submit(&lpn->timer, POLL_RETRY_TIMEOUT); } else { @@ -767,6 +809,8 @@ static void update_timeout(struct bt_mesh_lpn *lpn) bt_mesh_scan_disable(); } + BT_DBG("ReqAttempts %u", lpn->req_attempts); + if (lpn->req_attempts < FIRST_POLL_ATTEMPTS) { BT_WARN("Retrying first Friend Poll"); lpn->sent_req = 0U; @@ -784,7 +828,7 @@ static void lpn_timeout(struct k_work *work) { struct bt_mesh_lpn *lpn = &bt_mesh.lpn; - BT_DBG("state: %s", state2str(lpn->state)); + BT_DBG("LPNTimeout, State: %s", state2str(lpn->state)); switch (lpn->state) { case BLE_MESH_LPN_DISABLED: @@ -830,6 +874,8 @@ static void lpn_timeout(struct k_work *work) clear_friendship(true, false); break; case BLE_MESH_LPN_ESTABLISHED: + BT_DBG("ReqAttempts %u vs. %u", lpn->req_attempts, REQ_ATTEMPTS(lpn)); + if (lpn->req_attempts < REQ_ATTEMPTS(lpn)) { uint8_t req = lpn->sent_req; @@ -867,11 +913,13 @@ static void lpn_timeout(struct k_work *work) void bt_mesh_lpn_group_add(uint16_t group) { - BT_DBG("group 0x%04x", group); + BT_DBG("LPNGroupAdd, Addr 0x%04x", group); lpn_group_add(group); if (!bt_mesh_lpn_established() || bt_mesh.lpn.sent_req) { + BT_INFO("Established %u Req 0x%02x", + bt_mesh_lpn_established(), bt_mesh.lpn.sent_req); return; } @@ -882,6 +930,8 @@ void bt_mesh_lpn_group_del(uint16_t *groups, size_t group_count) { int i; + BT_DBG("LPNGroupDel, GroupCount %u", group_count); + for (i = 0; i < group_count; i++) { if (groups[i] != BLE_MESH_ADDR_UNASSIGNED) { BT_DBG("group 0x%04x", groups[i]); @@ -890,6 +940,8 @@ void bt_mesh_lpn_group_del(uint16_t *groups, size_t group_count) } if (!bt_mesh_lpn_established() || bt_mesh.lpn.sent_req) { + BT_INFO("Established %u Req 0x%02x", + bt_mesh_lpn_established(), bt_mesh.lpn.sent_req); return; } @@ -900,6 +952,7 @@ static int32_t poll_timeout(struct bt_mesh_lpn *lpn) { /* If we're waiting for segment acks keep polling at high freq */ if (bt_mesh_tx_in_progress()) { + BT_DBG("PollTimeout, Max %u", POLL_TIMEOUT_MAX(lpn)); return MIN(POLL_TIMEOUT_MAX(lpn), K_SECONDS(1)); } @@ -909,7 +962,7 @@ static int32_t poll_timeout(struct bt_mesh_lpn *lpn) POLL_TIMEOUT_MAX(lpn)); } - BT_DBG("Poll Timeout is %ums", lpn->poll_timeout); + BT_DBG("PollTimeout %u", lpn->poll_timeout); return lpn->poll_timeout; } @@ -920,12 +973,15 @@ int bt_mesh_lpn_friend_sub_cfm(struct bt_mesh_net_rx *rx, struct bt_mesh_ctl_friend_sub_confirm *msg = (void *)buf->data; struct bt_mesh_lpn *lpn = &bt_mesh.lpn; + BT_DBG("LPNFrndSubCFM"); + if (buf->len < sizeof(*msg)) { BT_WARN("Too short Friend Subscription Confirm"); return -EINVAL; } - BT_DBG("xact 0x%02x", msg->xact); + BT_DBG("Xact %u Req 0x%02x GroupsChanged %u PendingPoll %u", + msg->xact, lpn->sent_req, lpn->groups_changed, lpn->pending_poll); if (!lpn->sent_req) { BT_WARN("No pending subscription list message"); @@ -987,11 +1043,16 @@ int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx, struct bt_mesh_subnet *sub = rx->sub; uint32_t iv_index = 0U; + BT_DBG("LPNFrndUpdate"); + if (buf->len < sizeof(*msg)) { BT_WARN("Too short Friend Update"); return -EINVAL; } + BT_DBG("Req 0x%02x KrPhase %u Established %u", + lpn->sent_req, sub->kr_phase, lpn->established); + if (lpn->sent_req != TRANS_CTL_OP_FRIEND_POLL) { BT_WARN("Unexpected friend update"); return 0; @@ -1034,8 +1095,7 @@ int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx, } /* Set initial poll timeout */ - lpn->poll_timeout = MIN(POLL_TIMEOUT_MAX(lpn), - POLL_TIMEOUT_INIT); + lpn->poll_timeout = MIN(POLL_TIMEOUT_MAX(lpn), POLL_TIMEOUT_INIT); /* If the Low Power node supports directed forwarding functionality when * the friendship is established in a subnet, the Low Power node shall @@ -1046,18 +1106,16 @@ int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx, */ #if CONFIG_BLE_MESH_DF_SRV lpn->old_directed_forwarding = bt_mesh_get_and_disable_directed_forwarding_state(sub); -#endif +#endif /* CONFIG_BLE_MESH_DF_SRV */ } friend_response_received(lpn); iv_index = sys_be32_to_cpu(msg->iv_index); - BT_INFO("flags 0x%02x iv_index 0x%08x md %u", msg->flags, iv_index, - msg->md); + BT_INFO("Flags 0x%02x IVIndex 0x%08lx MD %u", msg->flags, iv_index, msg->md); - if (bt_mesh_kr_update(sub, BLE_MESH_KEY_REFRESH(msg->flags), - rx->new_key)) { + if (bt_mesh_kr_update(sub, BLE_MESH_KEY_REFRESH(msg->flags), rx->new_key)) { bt_mesh_net_secure_beacon_update(sub); } @@ -1086,12 +1144,12 @@ int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx, int bt_mesh_lpn_poll(void) { + BT_DBG("LPNPoll, Established %u", bt_mesh.lpn.established); + if (!bt_mesh.lpn.established) { return -EAGAIN; } - BT_DBG("Requesting more messages"); - return send_friend_poll(); } @@ -1104,6 +1162,8 @@ int bt_mesh_lpn_init(void) { struct bt_mesh_lpn *lpn = &bt_mesh.lpn; + BT_DBG("LPNInit"); + k_delayed_work_init(&lpn->timer, lpn_timeout); if (lpn->state == BLE_MESH_LPN_ENABLED) { @@ -1130,6 +1190,8 @@ int bt_mesh_lpn_deinit(void) { struct bt_mesh_lpn *lpn = &bt_mesh.lpn; + BT_DBG("LPNDeinit"); + bt_mesh_lpn_disable(true); k_delayed_work_free(&lpn->timer); diff --git a/components/bt/esp_ble_mesh/core/main.c b/components/bt/esp_ble_mesh/core/main.c index 957234e312e..3b6dcb14022 100644 --- a/components/bt/esp_ble_mesh/core/main.c +++ b/components/bt/esp_ble_mesh/core/main.c @@ -32,12 +32,14 @@ #if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" -#endif +#endif /* CONFIG_BLE_MESH_V11_SUPPORT */ static bool mesh_init = false; bool bt_mesh_is_initialized(void) { + BT_DBG("IsInitialized %u", mesh_init); + return mesh_init; } @@ -48,9 +50,10 @@ int bt_mesh_provision(const uint8_t net_key[16], uint16_t net_idx, bool pb_gatt_enabled = false; int err = 0; - BT_INFO("Primary Element: 0x%04x", addr); - BT_INFO("net_idx 0x%04x flags 0x%02x iv_index 0x%04x", - net_idx, flags, iv_index); + BT_INFO("NodeProvisioned"); + BT_INFO("PrimaryAddr 0x%04x", addr); + BT_INFO("NetIdx 0x%04x Flags 0x%02x IVIndex 0x%08lx", + net_idx, flags, iv_index); BT_INFO("DevKey %s", bt_hex(dev_key, 16)); BT_INFO("NetKey %s", bt_hex(net_key, 16)); @@ -69,9 +72,12 @@ int bt_mesh_provision(const uint8_t net_key[16], uint16_t net_idx, pb_gatt_enabled = false; } + BT_DBG("PbGattEnabled %u", pb_gatt_enabled); + err = bt_mesh_net_create(net_idx, flags, net_key, iv_index); if (err) { BT_ERR("Create network for node failed"); + bt_mesh_atomic_clear_bit(bt_mesh.flags, BLE_MESH_VALID); if (IS_ENABLED(CONFIG_BLE_MESH_PB_GATT) && pb_gatt_enabled) { @@ -89,11 +95,11 @@ int bt_mesh_provision(const uint8_t net_key[16], uint16_t net_idx, if (IS_ENABLED(CONFIG_BLE_MESH_LOW_POWER) && IS_ENABLED(CONFIG_BLE_MESH_LPN_SUB_ALL_NODES_ADDR)) { + BT_DBG("LPNAllNodesAdded"); bt_mesh_lpn_group_add(BLE_MESH_ADDR_ALL_NODES); } if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) { - BT_DBG("Storing network information persistently"); bt_mesh_store_net(); bt_mesh_store_subnet(&bt_mesh.sub[0]); bt_mesh_store_iv(false); @@ -106,6 +112,8 @@ int bt_mesh_provision(const uint8_t net_key[16], uint16_t net_idx, void bt_mesh_node_reset(void) { + BT_DBG("NodeLocalReset"); + if (!bt_mesh_is_provisioned()) { BT_WARN("%s, Not provisioned", __func__); return; @@ -154,7 +162,7 @@ void bt_mesh_node_reset(void) #if CONFIG_BLE_MESH_PRB_SRV bt_mesh_private_beacon_disable(); -#endif +#endif /* CONFIG_BLE_MESH_PRB_SRV */ bt_mesh_comp_unprovision(); @@ -165,7 +173,7 @@ void bt_mesh_node_reset(void) bt_mesh_clear_role(); #if CONFIG_BLE_MESH_DF_SRV bt_mesh_clear_all_directed_forwarding_table_data(); -#endif +#endif /* CONFIG_BLE_MESH_DF_SRV */ } memset(bt_mesh.flags, 0, sizeof(bt_mesh.flags)); @@ -177,34 +185,52 @@ void bt_mesh_node_reset(void) bool bt_mesh_is_node(void) { - return bt_mesh_atomic_test_bit(bt_mesh.flags, BLE_MESH_NODE); + bool is_node = bt_mesh_atomic_test_bit(bt_mesh.flags, BLE_MESH_NODE); + + BT_DBG("IsNode %u", is_node); + + return is_node; } bool bt_mesh_is_provisioned(void) { + bool is_provisioned = false; + if (bt_mesh_is_node()) { - return bt_mesh_atomic_test_bit(bt_mesh.flags, BLE_MESH_VALID); - } else { - return false; + is_provisioned = bt_mesh_atomic_test_bit(bt_mesh.flags, BLE_MESH_VALID); } + + BT_DBG("IsProvisioned %u", is_provisioned); + + return is_provisioned; } bool bt_mesh_is_provisioner(void) { - return bt_mesh_atomic_test_bit(bt_mesh.flags, BLE_MESH_PROVISIONER); + bool is_pvnr = bt_mesh_atomic_test_bit(bt_mesh.flags, BLE_MESH_PROVISIONER); + + BT_DBG("IsPvnr %u", is_pvnr); + + return is_pvnr; } bool bt_mesh_is_provisioner_en(void) { + bool is_pvnr_en = false; + if (bt_mesh_is_provisioner()) { - return bt_mesh_atomic_test_bit(bt_mesh.flags, BLE_MESH_VALID_PROV); + is_pvnr_en = bt_mesh_atomic_test_bit(bt_mesh.flags, BLE_MESH_VALID_PROV); } - return false; + BT_DBG("IsPvnrEn %u", is_pvnr_en); + + return is_pvnr_en; } static bool prov_bearers_valid(bt_mesh_prov_bearer_t bearers) { + BT_DBG("ProvBearersValid, Bearers 0x%02x", bearers); + if ((!(bearers & (BLE_MESH_PROV_ADV | BLE_MESH_PROV_GATT))) || (IS_ENABLED(CONFIG_BLE_MESH_PB_ADV) && !IS_ENABLED(CONFIG_BLE_MESH_PB_GATT) && @@ -215,6 +241,7 @@ static bool prov_bearers_valid(bt_mesh_prov_bearer_t bearers) BT_ERR("Invalid bearers 0x%02x", bearers); return false; } + return true; } @@ -222,6 +249,8 @@ int bt_mesh_prov_enable(bt_mesh_prov_bearer_t bearers) { int err = 0; + BT_DBG("ProvEnable, Bearers 0x%02x", bearers); + if (bt_mesh_is_provisioned()) { BT_WARN("%s, Already", __func__); return -EALREADY; @@ -247,6 +276,7 @@ int bt_mesh_prov_enable(bt_mesh_prov_bearer_t bearers) if (role == BLE_MESH_SETTINGS_ROLE_NONE) { bt_mesh_atomic_set_bit(bt_mesh.flags, BLE_MESH_NODE); } + if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS_BACKWARD_COMPATIBILITY) || role == BLE_MESH_SETTINGS_ROLE_NONE) { if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) { @@ -277,6 +307,8 @@ int bt_mesh_prov_enable(bt_mesh_prov_bearer_t bearers) int bt_mesh_prov_disable(bt_mesh_prov_bearer_t bearers) { + BT_DBG("ProvDisable, Bearers 0x%02x", bearers); + if (bt_mesh_is_provisioned()) { BT_WARN("%s, Already provisioned", __func__); return -EALREADY; @@ -309,6 +341,8 @@ int bt_mesh_prov_disable(bt_mesh_prov_bearer_t bearers) static void model_suspend(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, bool vnd, bool primary, void *user_data) { + BT_DBG("ModelSuspend, Vnd %u Primary %u", vnd, primary); + if (mod->pub && mod->pub->update) { mod->pub->count = 0U; k_delayed_work_cancel(&mod->pub->timer); @@ -319,6 +353,8 @@ int bt_mesh_suspend(void) { int err = 0; + BT_DBG("Suspend"); + if (!bt_mesh_atomic_test_bit(bt_mesh.flags, BLE_MESH_VALID)) { return -EINVAL; } @@ -344,7 +380,7 @@ int bt_mesh_suspend(void) if (bt_mesh_private_beacon_state_get() == BLE_MESH_PRIVATE_BEACON_ENABLED) { bt_mesh_private_beacon_disable(); } -#endif +#endif /* CONFIG_BLE_MESH_PRB_SRV */ bt_mesh_model_foreach(model_suspend, NULL); @@ -354,6 +390,8 @@ int bt_mesh_suspend(void) static void model_resume(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, bool vnd, bool primary, void *user_data) { + BT_DBG("ModelResume, Vnd %u Primary %u", vnd, primary); + if (mod->pub && mod->pub->update) { int32_t period_ms = bt_mesh_model_pub_period_get(mod); @@ -367,6 +405,8 @@ int bt_mesh_resume(void) { int err = 0; + BT_DBG("Resume"); + if (!bt_mesh_atomic_test_bit(bt_mesh.flags, BLE_MESH_VALID)) { return -EINVAL; } @@ -390,7 +430,7 @@ int bt_mesh_resume(void) if (bt_mesh_private_beacon_state_get() == BLE_MESH_PRIVATE_BEACON_ENABLED) { bt_mesh_private_beacon_enable(); } -#endif +#endif /* CONFIG_BLE_MESH_PRB_SRV */ bt_mesh_model_foreach(model_resume, NULL); @@ -402,6 +442,8 @@ int bt_mesh_init(const struct bt_mesh_prov *prov, { int err = 0; + BT_DBG("Init"); + if (mesh_init == true) { BT_WARN("%s, Already", __func__); return -EALREADY; @@ -414,7 +456,7 @@ int bt_mesh_init(const struct bt_mesh_prov *prov, BT_ERR("Bluetooth Mesh v1.1 init failed"); return err; } -#endif +#endif /* CONFIG_BLE_MESH_V11_SUPPORT */ bt_mesh_mutex_init(); @@ -452,7 +494,7 @@ int bt_mesh_init(const struct bt_mesh_prov *prov, if (err) { return err; } -#endif +#endif /* CONFIG_BLE_MESH_PROXY_SOLIC */ if (IS_ENABLED(CONFIG_BLE_MESH_PROV)) { err = bt_mesh_prov_set(prov); @@ -507,6 +549,8 @@ int bt_mesh_deinit(struct bt_mesh_deinit_param *param) { int err = 0; + BT_DBG("Deinit"); + if (param == NULL) { BT_ERR("%s, Invalid parameter", __func__); return -EINVAL; @@ -522,7 +566,7 @@ int bt_mesh_deinit(struct bt_mesh_deinit_param *param) #if CONFIG_BLE_MESH_PRB_SRV bt_mesh_private_beacon_disable(); -#endif +#endif /* CONFIG_BLE_MESH_PRB_SRV */ if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_node()) { if (IS_ENABLED(CONFIG_BLE_MESH_PB_GATT) && @@ -583,7 +627,7 @@ int bt_mesh_deinit(struct bt_mesh_deinit_param *param) #if CONFIG_BLE_MESH_PROXY_SOLIC bt_mesh_proxy_solic_deinit(); -#endif +#endif /* CONFIG_BLE_MESH_PROXY_SOLIC */ if ((IS_ENABLED(CONFIG_BLE_MESH_NODE) && IS_ENABLED(CONFIG_BLE_MESH_PB_GATT)) || @@ -638,6 +682,8 @@ int bt_mesh_provisioner_enable(bt_mesh_prov_bearer_t bearers) { int err = 0; + BT_DBG("PvnrEnable, Bearers 0x%02x", bearers); + if (bt_mesh_is_provisioner_en()) { BT_WARN("%s, Already", __func__); return -EALREADY; @@ -703,7 +749,7 @@ int bt_mesh_provisioner_enable(bt_mesh_prov_bearer_t bearers) BLE_MESH_EXCEP_LIST_TYPE_MESH_PROV_ADV, NULL); } -#endif +#endif /* CONFIG_BLE_MESH_USE_DUPLICATE_SCAN */ if (IS_ENABLED(CONFIG_BLE_MESH_PB_GATT) && (bearers & BLE_MESH_PROV_GATT)) { @@ -722,7 +768,7 @@ int bt_mesh_provisioner_enable(bt_mesh_prov_bearer_t bearers) if (bt_mesh_private_beacon_state_get() == BLE_MESH_PRIVATE_BEACON_ENABLED) { bt_mesh_private_beacon_enable(); } -#endif +#endif /* CONFIG_BLE_MESH_PRB_SRV */ err = bt_mesh_scan_enable(); if (err) { @@ -736,6 +782,8 @@ int bt_mesh_provisioner_disable(bt_mesh_prov_bearer_t bearers) { bt_mesh_prov_bearer_t enable = 0U; + BT_DBG("PvnrDisable, Bearers 0x%02x", bearers); + if (!bt_mesh_is_provisioner_en()) { BT_WARN("%s, Already", __func__); return -EALREADY; @@ -762,7 +810,7 @@ int bt_mesh_provisioner_disable(bt_mesh_prov_bearer_t bearers) bt_mesh_update_exceptional_list(BLE_MESH_EXCEP_LIST_SUB_CODE_REMOVE, BLE_MESH_EXCEP_LIST_TYPE_MESH_PROV_ADV, NULL); -#endif +#endif /* CONFIG_BLE_MESH_USE_DUPLICATE_SCAN */ } if (!(enable & (~bearers))) { @@ -776,7 +824,7 @@ int bt_mesh_provisioner_disable(bt_mesh_prov_bearer_t bearers) BLE_MESH_EXCEP_LIST_TYPE_MESH_BEACON, NULL); } -#endif +#endif /* CONFIG_BLE_MESH_USE_DUPLICATE_SCAN */ /* Clear corresponding flags */ bt_mesh_atomic_and(bt_mesh.flags, ~(BIT(BLE_MESH_PROVISIONER) | BIT(BLE_MESH_VALID_PROV))); @@ -794,7 +842,7 @@ int bt_mesh_provisioner_disable(bt_mesh_prov_bearer_t bearers) if (bt_mesh_private_beacon_state_get() == BLE_MESH_PRIVATE_BEACON_ENABLED) { bt_mesh_private_beacon_disable(); } -#endif +#endif /* CONFIG_BLE_MESH_PRB_SRV */ if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND)) { bt_mesh_friend_clear_net_idx(BLE_MESH_KEY_ANY); diff --git a/components/bt/esp_ble_mesh/core/net.c b/components/bt/esp_ble_mesh/core/net.c index 3d140927040..5ddbb46ca03 100644 --- a/components/bt/esp_ble_mesh/core/net.c +++ b/components/bt/esp_ble_mesh/core/net.c @@ -33,7 +33,7 @@ #if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" -#endif +#endif /* CONFIG_BLE_MESH_V11_SUPPORT */ /* Minimum valid Mesh Network PDU length. The Network headers * themselves take up 9 bytes. After that there is a minimum of 1 byte @@ -41,23 +41,27 @@ * PDUs must use a 64-bit (8 byte) NetMIC, whereas CTL=0 PDUs have at least * a 32-bit (4 byte) NetMIC and AppMIC giving again a total of 8 bytes. */ -#define BLE_MESH_NET_MIN_PDU_LEN (BLE_MESH_NET_HDR_LEN + 1 + 8) +#define BLE_MESH_NET_MIN_PDU_LEN (BLE_MESH_NET_HDR_LEN + 1 + 8) /* Seq limit after IV Update is triggered */ -#define IV_UPDATE_SEQ_LIMIT 8000000 +#define IV_UPDATE_SEQ_LIMIT 8000000 /* Determine how many friendship credentials we need */ #if CONFIG_BLE_MESH_FRIEND -#define FRIEND_CRED_COUNT CONFIG_BLE_MESH_FRIEND_LPN_COUNT +#define FRIEND_CRED_COUNT CONFIG_BLE_MESH_FRIEND_LPN_COUNT #elif CONFIG_BLE_MESH_LOW_POWER -#define FRIEND_CRED_COUNT CONFIG_BLE_MESH_SUBNET_COUNT +#define FRIEND_CRED_COUNT CONFIG_BLE_MESH_SUBNET_COUNT #else -#define FRIEND_CRED_COUNT 0 +#define FRIEND_CRED_COUNT 0 #endif +#if CONFIG_BLE_MESH_RELAY_ADV_BUF +#define MAX_STORED_RELAY_COUNT (CONFIG_BLE_MESH_RELAY_ADV_BUF_COUNT / 2) +#endif /* CONFIG_BLE_MESH_RELAY_ADV_BUF */ + #if FRIEND_CRED_COUNT > 0 static struct friend_cred friend_cred[FRIEND_CRED_COUNT]; -#endif +#endif /* FRIEND_CRED_COUNT > 0 */ static struct { uint32_t src:15, /* MSB of source address is always 0 */ @@ -83,10 +87,6 @@ struct bt_mesh_net bt_mesh = { static uint32_t dup_cache[4]; static int dup_cache_next; -#if CONFIG_BLE_MESH_RELAY_ADV_BUF -#define BLE_MESH_MAX_STORED_RELAY_COUNT (CONFIG_BLE_MESH_RELAY_ADV_BUF_COUNT / 2) -#endif - static bool check_dup(struct net_buf_simple *data) { const uint8_t *tail = net_buf_simple_tail(data); @@ -95,12 +95,17 @@ static bool check_dup(struct net_buf_simple *data) val = sys_get_be32(tail - 4) ^ sys_get_be32(tail - 8); + BT_DBG("CheckDup, Val 0x%08lx", val); + for (i = 0; i < ARRAY_SIZE(dup_cache); i++) { if (dup_cache[i] == val) { + BT_DBG("DupCacheFound"); return true; } } + BT_DBG("DupCacheAdd, CacheNext %ld", val, dup_cache_next); + dup_cache[dup_cache_next++] = val; dup_cache_next %= ARRAY_SIZE(dup_cache); @@ -112,9 +117,13 @@ static bool msg_cache_match(struct bt_mesh_net_rx *rx, { int i; + BT_DBG("MsgCacheMatch"); + for (i = 0; i < ARRAY_SIZE(msg_cache); i++) { if (msg_cache[i].src == BLE_MESH_NET_HDR_SRC(pdu->data) && msg_cache[i].seq == (BLE_MESH_NET_HDR_SEQ(pdu->data) & BIT_MASK(17))) { + BT_DBG("CacheFound, Src 0x%04x Seq 0x%06x", + msg_cache[i].src, msg_cache[i].seq); return true; } } @@ -124,6 +133,9 @@ static bool msg_cache_match(struct bt_mesh_net_rx *rx, static void msg_cache_add(struct bt_mesh_net_rx *rx) { + BT_DBG("MsgCacheAdd, Src 0x%04x Seq 0x%06x CacheNext %u", + rx->ctx.addr, rx->seq, msg_cache_next); + rx->msg_cache_idx = msg_cache_next++; msg_cache[rx->msg_cache_idx].src = rx->ctx.addr; msg_cache[rx->msg_cache_idx].seq = rx->seq; @@ -135,6 +147,8 @@ void bt_mesh_msg_cache_clear(uint16_t unicast_addr, uint8_t elem_num) { int i; + BT_DBG("MsgCacheClear, Addr 0x%04x ElemNum %u", unicast_addr, elem_num); + for (i = 0; i < ARRAY_SIZE(msg_cache); i++) { if (msg_cache[i].src >= unicast_addr && msg_cache[i].src < unicast_addr + elem_num) { @@ -146,6 +160,8 @@ void bt_mesh_msg_cache_clear(uint16_t unicast_addr, uint8_t elem_num) struct bt_mesh_subnet *bt_mesh_subnet_get(uint16_t net_idx) { + BT_DBG("SubnetGet, NetIdx 0x%04x", net_idx); + if (bt_mesh_is_provisioned()) { #if CONFIG_BLE_MESH_NODE if (!IS_ENABLED(CONFIG_BLE_MESH_FAST_PROV)) { @@ -161,7 +177,7 @@ struct bt_mesh_subnet *bt_mesh_subnet_get(uint16_t net_idx) } else { return bt_mesh_fast_prov_subnet_get(net_idx); } -#endif +#endif /* CONFIG_BLE_MESH_NODE */ } else if (bt_mesh_is_provisioner_en()) { #if CONFIG_BLE_MESH_PROVISIONER if (net_idx == BLE_MESH_KEY_ANY) { @@ -174,7 +190,7 @@ struct bt_mesh_subnet *bt_mesh_subnet_get(uint16_t net_idx) return bt_mesh.p_sub[i]; } } -#endif +#endif /* CONFIG_BLE_MESH_PROVISIONER */ } return NULL; @@ -187,6 +203,8 @@ int bt_mesh_net_keys_create(struct bt_mesh_subnet_keys *keys, uint8_t nid = 0U; int err = 0; + BT_DBG("NetKeysCreate"); + err = bt_mesh_k2(key, p, sizeof(p), &nid, keys->enc, keys->privacy); if (err) { BT_ERR("Unable to generate NID, EncKey & PrivacyKey"); @@ -258,6 +276,9 @@ int friend_cred_set(struct friend_cred *cred, uint8_t idx, const uint8_t net_key uint8_t p[9] = {0}; int err = 0; + BT_DBG("FrndCredSet, NetIdx 0x%04x Addr 0x%04x Idx %u", + cred->net_idx, cred->addr, idx); + #if CONFIG_BLE_MESH_LOW_POWER if (cred->addr == bt_mesh.lpn.frnd) { lpn_addr = bt_mesh_primary_addr(); @@ -266,14 +287,13 @@ int friend_cred_set(struct friend_cred *cred, uint8_t idx, const uint8_t net_key lpn_addr = cred->addr; frnd_addr = bt_mesh_primary_addr(); } -#else +#else /* CONFIG_BLE_MESH_LOW_POWER */ lpn_addr = cred->addr; frnd_addr = bt_mesh_primary_addr(); -#endif +#endif /* CONFIG_BLE_MESH_LOW_POWER */ - BT_DBG("LPNAddress 0x%04x FriendAddress 0x%04x", lpn_addr, frnd_addr); - BT_DBG("LPNCounter 0x%04x FriendCounter 0x%04x", cred->lpn_counter, - cred->frnd_counter); + BT_DBG("LPN 0x%04x Frnd 0x%04x LPNCounter %u FrndCounter %u", + lpn_addr, frnd_addr, cred->lpn_counter, cred->frnd_counter); p[0] = 0x01; sys_put_be16(lpn_addr, p + 1); @@ -288,9 +308,9 @@ int friend_cred_set(struct friend_cred *cred, uint8_t idx, const uint8_t net_key return err; } - BT_DBG("Friend NID 0x%02x EncKey %s", cred->cred[idx].nid, - bt_hex(cred->cred[idx].enc, 16)); - BT_DBG("Friend PrivacyKey %s", bt_hex(cred->cred[idx].privacy, 16)); + BT_DBG("FrndNID 0x%02x EncKey %s", + cred->cred[idx].nid, bt_hex(cred->cred[idx].enc, 16)); + BT_DBG("FrndPrivacyKey %s", bt_hex(cred->cred[idx].privacy, 16)); return 0; } @@ -299,11 +319,14 @@ void friend_cred_refresh(uint16_t net_idx) { int i; + BT_DBG("FrndCredRefresh, NetIdx 0x%04x", net_idx); + for (i = 0; i < ARRAY_SIZE(friend_cred); i++) { struct friend_cred *cred = &friend_cred[i]; if (cred->addr != BLE_MESH_ADDR_UNASSIGNED && cred->net_idx == net_idx) { + BT_DBG("Refreshed, Addr 0x%04x", cred->addr); memcpy(&cred->cred[0], &cred->cred[1], sizeof(cred->cred[0])); } @@ -314,7 +337,7 @@ int friend_cred_update(struct bt_mesh_subnet *sub) { int err = 0, i; - BT_DBG("net_idx 0x%04x", sub->net_idx); + BT_DBG("FrndCredUpdate, NetIdx 0x%04x", sub->net_idx); for (i = 0; i < ARRAY_SIZE(friend_cred); i++) { struct friend_cred *cred = &friend_cred[i]; @@ -324,6 +347,8 @@ int friend_cred_update(struct bt_mesh_subnet *sub) continue; } + BT_DBG("UpdateFound, Addr 0x%04x", cred->addr); + err = friend_cred_set(cred, 1, sub->keys[1].net); if (err) { return err; @@ -339,7 +364,8 @@ struct friend_cred *friend_cred_create(struct bt_mesh_subnet *sub, uint16_t addr struct friend_cred *cred = NULL; int i, err = 0; - BT_DBG("net_idx 0x%04x addr 0x%04x", sub->net_idx, addr); + BT_DBG("FrndCredCreate, NetIdx 0x%04x KrFlag %u Addr 0x%04x", + sub->net_idx, sub->kr_flag, addr); for (cred = NULL, i = 0; i < ARRAY_SIZE(friend_cred); i++) { if ((friend_cred[i].addr == BLE_MESH_ADDR_UNASSIGNED) || @@ -379,6 +405,8 @@ struct friend_cred *friend_cred_create(struct bt_mesh_subnet *sub, uint16_t addr void friend_cred_clear(struct friend_cred *cred) { + BT_DBG("FrndCredClear, NetIdx 0x%04x Addr 0x%04x", cred->net_idx, cred->addr); + cred->net_idx = BLE_MESH_KEY_UNUSED; cred->addr = BLE_MESH_ADDR_UNASSIGNED; cred->lpn_counter = 0U; @@ -390,9 +418,13 @@ int friend_cred_del(uint16_t net_idx, uint16_t addr) { int i; + BT_DBG("FrndCredDel, NetIdx 0x%04x Addr 0x%04x", net_idx, addr); + for (i = 0; i < ARRAY_SIZE(friend_cred); i++) { struct friend_cred *cred = &friend_cred[i]; + BT_DBG("%u: NetIdx 0x%04x Addr 0x%04x", i, cred->net_idx, cred->addr); + if (cred->addr == addr && cred->net_idx == net_idx) { friend_cred_clear(cred); return 0; @@ -407,7 +439,8 @@ int friend_cred_get(struct bt_mesh_subnet *sub, uint16_t addr, uint8_t *nid, { int i; - BT_DBG("net_idx 0x%04x addr 0x%04x", sub->net_idx, addr); + BT_DBG("FrndCredGet, NetIdx 0x%04x KrFlag %u Addr 0x%04x", + sub->net_idx, sub->kr_flag, addr); for (i = 0; i < ARRAY_SIZE(friend_cred); i++) { struct friend_cred *cred = &friend_cred[i]; @@ -437,13 +470,15 @@ int friend_cred_get(struct bt_mesh_subnet *sub, uint16_t addr, uint8_t *nid, return -ENOENT; } -#else +#else /* (CONFIG_BLE_MESH_LOW_POWER || CONFIG_BLE_MESH_FRIEND) */ int friend_cred_get(struct bt_mesh_subnet *sub, uint16_t addr, uint8_t *nid, const uint8_t **enc, const uint8_t **priv) { + BT_DBG("FrndCredGetNoEnt"); + return -ENOENT; } -#endif /* FRIEND || LOW_POWER */ +#endif /* (CONFIG_BLE_MESH_LOW_POWER || CONFIG_BLE_MESH_FRIEND) */ uint8_t bt_mesh_net_flags(struct bt_mesh_subnet *sub) { @@ -457,36 +492,40 @@ uint8_t bt_mesh_net_flags(struct bt_mesh_subnet *sub) flags |= BLE_MESH_NET_FLAG_IVU; } + BT_DBG("NetFlags 0x%02x", flags); + return flags; } int bt_mesh_net_secure_beacon_update(struct bt_mesh_subnet *sub) { - uint8_t flags = bt_mesh_net_flags(sub); struct bt_mesh_subnet_keys *keys = NULL; + uint8_t flags = 0; + + BT_DBG("SecureBeaconUpdate, NetIdx 0x%04x KrFlag %u IVIndex %lu", + sub->net_idx, sub->kr_flag, bt_mesh.iv_index); if (sub->kr_flag) { - BT_DBG("NetIndex %u Using new key", sub->net_idx); keys = &sub->keys[1]; } else { - BT_DBG("NetIndex %u Using current key", sub->net_idx); keys = &sub->keys[0]; } - BT_DBG("flags 0x%02x, IVI 0x%08x", flags, bt_mesh.iv_index); + flags = bt_mesh_net_flags(sub); return bt_mesh_secure_beacon_auth(keys->beacon, flags, keys->net_id, bt_mesh.iv_index, sub->auth); } -int bt_mesh_net_create(uint16_t idx, uint8_t flags, const uint8_t key[16], +int bt_mesh_net_create(uint16_t net_idx, uint8_t flags, const uint8_t key[16], uint32_t iv_index) { struct bt_mesh_subnet *sub = NULL; int err = 0; - BT_DBG("idx %u flags 0x%02x iv_index %u", idx, flags, iv_index); - + BT_DBG("NetCreate"); + BT_DBG("NetIdx 0x%04x Flags 0x%02x IVIndex %lu Hours %u", + net_idx, flags, iv_index, BLE_MESH_IVU_HOURS); BT_DBG("NetKey %s", bt_hex(key, 16)); (void)memset(msg_cache, 0, sizeof(msg_cache)); @@ -509,7 +548,7 @@ int bt_mesh_net_create(uint16_t idx, uint8_t flags, const uint8_t key[16], } } - sub->net_idx = idx; + sub->net_idx = net_idx; if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER)) { sub->node_id = BLE_MESH_NODE_IDENTITY_STOPPED; @@ -517,7 +556,7 @@ int bt_mesh_net_create(uint16_t idx, uint8_t flags, const uint8_t key[16], sub->node_id = BLE_MESH_NODE_IDENTITY_NOT_SUPPORTED; #if CONFIG_BLE_MESH_PRB_SRV sub->private_node_id = BLE_MESH_PRIVATE_NODE_IDENTITY_NOT_SUPPORTED; -#endif +#endif /* CONFIG_BLE_MESH_PRB_SRV */ } bt_mesh.iv_index = iv_index; @@ -535,27 +574,29 @@ int bt_mesh_net_create(uint16_t idx, uint8_t flags, const uint8_t key[16], #if CONFIG_BLE_MESH_DF_SRV return bt_mesh_directed_forwarding_sub_init(sub); -#endif - +#else /* CONFIG_BLE_MESH_DF_SRV */ return 0; +#endif /* CONFIG_BLE_MESH_DF_SRV */ } void bt_mesh_net_revoke_keys(struct bt_mesh_subnet *sub) { int i; - BT_DBG("idx 0x%04x", sub->net_idx); + BT_DBG("RevokeKeys, NetIdx 0x%04x", sub->net_idx); memcpy(&sub->keys[0], &sub->keys[1], sizeof(sub->keys[0])); if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) { - BT_DBG("Store updated NetKey persistently"); bt_mesh_store_subnet(sub); } for (i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) { struct bt_mesh_app_key *key = &bt_mesh.app_keys[i]; + BT_DBG("Revoke, NetIdx 0x%04x AppIdx 0x%04x KeyUpdated %u", + key->net_idx, key->app_idx, key->updated); + if (key->net_idx != sub->net_idx || !key->updated) { continue; } @@ -564,7 +605,6 @@ void bt_mesh_net_revoke_keys(struct bt_mesh_subnet *sub) key->updated = false; if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) { - BT_DBG("Store updated AppKey persistently"); bt_mesh_store_app_key(key); } } @@ -572,6 +612,9 @@ void bt_mesh_net_revoke_keys(struct bt_mesh_subnet *sub) bool bt_mesh_kr_update(struct bt_mesh_subnet *sub, uint8_t new_kr, bool new_key) { + BT_DBG("KrUpdate, NewKr %u NewKey %u KrFlag %u KrPhase %u", + new_kr, new_key, sub->kr_flag, sub->kr_phase); + if (new_kr != sub->kr_flag && sub->kr_phase == BLE_MESH_KR_NORMAL) { BT_WARN("KR change in normal operation. Are we blacklisted?"); return false; @@ -582,10 +625,10 @@ bool bt_mesh_kr_update(struct bt_mesh_subnet *sub, uint8_t new_kr, bool new_key) if (sub->kr_flag) { if (sub->kr_phase == BLE_MESH_KR_PHASE_1) { BT_INFO("Phase 1 -> Phase 2"); + sub->kr_phase = BLE_MESH_KR_PHASE_2; if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) { - BT_DBG("Storing kr phase persistently"); bt_mesh_store_subnet(sub); } @@ -606,14 +649,14 @@ bool bt_mesh_kr_update(struct bt_mesh_subnet *sub, uint8_t new_kr, bool new_key) * Intentional fall-through. */ case BLE_MESH_KR_PHASE_2: - BT_INFO("KR Phase 0x%02x -> Normal", sub->kr_phase); + BT_INFO("KrPhase 0x%02x -> Normal", sub->kr_phase); #if CONFIG_BLE_MESH_PRB_SRV /* In this case, consider that kr_flag has changed, so * need to modify the content of the random field. */ bt_mesh_private_beacon_update_random(sub); -#endif +#endif /* CONFIG_BLE_MESH_PRB_SRV */ sub->kr_phase = BLE_MESH_KR_NORMAL; bt_mesh_net_revoke_keys(sub); @@ -633,15 +676,21 @@ bool bt_mesh_kr_update(struct bt_mesh_subnet *sub, uint8_t new_kr, bool new_key) #if CONFIG_BLE_MESH_IV_UPDATE_TEST void bt_mesh_iv_update_test(bool enable) { + BT_DBG("IVUpdateTest, Enable %u", enable); + bt_mesh_atomic_set_bit_to(bt_mesh.flags, BLE_MESH_IVU_TEST, enable); + /* Reset the duration variable - needed for some PTS tests */ bt_mesh.ivu_duration = 0U; } bool bt_mesh_iv_update(void) { + BT_DBG("IVUpdate, IVIndex %lu InProgress %u", bt_mesh.iv_index, + bt_mesh_atomic_test_bit(bt_mesh.flags, BLE_MESH_IVU_IN_PROGRESS)); + if (!bt_mesh_is_provisioned()) { - BT_ERR("Not yet provisioned"); + BT_ERR("NotProvisioned"); return false; } @@ -660,6 +709,8 @@ bool bt_mesh_iv_update(void) /* Used for sending immediate beacons to Friend queues and GATT clients */ void bt_mesh_net_sec_update(struct bt_mesh_subnet *sub) { + BT_DBG("NetSecUpdate, NetIdx 0x%04x", sub ? sub->net_idx : BLE_MESH_KEY_ANY); + if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND)) { bt_mesh_friend_sec_update(sub ? sub->net_idx : BLE_MESH_KEY_ANY); } @@ -667,8 +718,8 @@ void bt_mesh_net_sec_update(struct bt_mesh_subnet *sub) if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) && (bt_mesh_gatt_proxy_get() == BLE_MESH_GATT_PROXY_ENABLED #if CONFIG_BLE_MESH_PRB_SRV - || bt_mesh_private_gatt_proxy_state_get() == BLE_MESH_PRIVATE_GATT_PROXY_ENABLED -#endif + || bt_mesh_private_gatt_proxy_state_get() == BLE_MESH_PRIVATE_GATT_PROXY_ENABLED +#endif /* CONFIG_BLE_MESH_PRB_SRV */ )) { bt_mesh_proxy_server_beacon_send(sub); } @@ -678,6 +729,11 @@ bool bt_mesh_net_iv_update(uint32_t iv_index, bool iv_update) { int i; + BT_DBG("NetIVUpdate"); + BT_DBG("IVIndex %lu/%lu IVU %u InProgress %u", + iv_index, bt_mesh.iv_index, iv_update, + bt_mesh_atomic_test_bit(bt_mesh.flags, BLE_MESH_IVU_IN_PROGRESS)); + /* If a node in Normal Operation receives a Secure Network beacon or * a Mesh Private beacon with an IV index less than the last known * IV Index or greater than the last known IV Index + 42, the Secure @@ -685,7 +741,7 @@ bool bt_mesh_net_iv_update(uint32_t iv_index, bool iv_update) */ if (iv_index < bt_mesh.iv_index || iv_index > bt_mesh.iv_index + 42) { - BT_ERR("IV Index out of sync: 0x%08x != 0x%08x", + BT_ERR("IVIndex out of sync: 0x%08x != 0x%08x", iv_index, bt_mesh.iv_index); return false; } @@ -721,7 +777,7 @@ bool bt_mesh_net_iv_update(uint32_t iv_index, bool iv_update) if ((iv_index > bt_mesh.iv_index + 1) #if CONFIG_BLE_MESH_IVU_RECOVERY_IVI || (iv_index == bt_mesh.iv_index + 1 && !iv_update) -#endif +#endif /* CONFIG_BLE_MESH_IVU_RECOVERY_IVI */ ) { BT_WARN("Performing IV Index Recovery"); (void)memset(bt_mesh.rpl, 0, sizeof(bt_mesh.rpl)); @@ -742,7 +798,7 @@ bool bt_mesh_net_iv_update(uint32_t iv_index, bool iv_update) BT_WARN("Ignoring new index in normal mode"); return false; } -#endif +#endif /* !CONFIG_BLE_MESH_IVU_RECOVERY_IVI */ if (!iv_update) { /* Nothing to do */ @@ -802,9 +858,11 @@ do_update: bool bt_mesh_primary_subnet_exist(void) { if (bt_mesh_subnet_get(BLE_MESH_KEY_PRIMARY)) { + BT_DBG("PrimarySubnetExist"); return true; } + BT_DBG("PrimarySubnetNotExist"); return false; } @@ -812,6 +870,8 @@ uint32_t bt_mesh_next_seq(void) { uint32_t seq = bt_mesh.seq++; + BT_DBG("NextSeq %lu", seq); + if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) { bt_mesh_store_seq(); } @@ -839,8 +899,9 @@ int bt_mesh_net_resend(struct bt_mesh_subnet *sub, struct net_buf *buf, /* The variable is not used when proxy server or proxy client is disabled. */ ARG_UNUSED(dst); - BT_DBG("net_idx 0x%04x new_key %u len %u", sub->net_idx, new_key, - buf->len); + BT_DBG("NetResend"); + BT_DBG("NetIdx 0x%04x NewKey %u Len %u Tag 0x%02x", + sub->net_idx, new_key, buf->len, tx_tag); /* Previously when resending the segments, only managed flooding * security credentials will be used. @@ -887,13 +948,11 @@ int bt_mesh_net_resend(struct bt_mesh_subnet *sub, struct net_buf *buf, err = bt_mesh_net_obfuscate(buf->data, BLE_MESH_NET_IVI_TX, priv); if (err) { - BT_ERR("De-obfuscate failed (err %d)", err); return err; } err = bt_mesh_net_decrypt(enc, &buf->b, BLE_MESH_NET_IVI_TX, false, false); if (err) { - BT_ERR("Decrypt failed (err %d)", err); return err; } @@ -906,20 +965,18 @@ int bt_mesh_net_resend(struct bt_mesh_subnet *sub, struct net_buf *buf, err = bt_mesh_net_encrypt(enc, &buf->b, BLE_MESH_NET_IVI_TX, false, false); if (err) { - BT_ERR("Encrypt failed (err %d)", err); return err; } err = bt_mesh_net_obfuscate(buf->data, BLE_MESH_NET_IVI_TX, priv); if (err) { - BT_ERR("Obfuscate failed (err %d)", err); return err; } - /** - * TODO: Find a way to determine how the message was sent previously + /* TODO: + * Find a way to determine how the message was sent previously * during a retransmission, to avoid ineffective advertising. - */ + */ #if CONFIG_BLE_MESH_GATT_PROXY_SERVER if (bt_mesh_proxy_server_relay(&buf->b, dst) && BLE_MESH_ADDR_IS_UNICAST(dst) && @@ -927,13 +984,14 @@ int bt_mesh_net_resend(struct bt_mesh_subnet *sub, struct net_buf *buf, send_cb_finalize(cb, cb_data); return 0; } -#endif +#endif /* CONFIG_BLE_MESH_GATT_PROXY_SERVER */ #if CONFIG_BLE_MESH_GATT_PROXY_CLIENT bt_mesh_proxy_client_relay(&buf->b, dst); -#endif +#endif /* CONFIG_BLE_MESH_GATT_PROXY_CLIENT */ bt_mesh_adv_send(buf, BLE_MESH_ADV(buf)->xmit, cb, cb_data); + return 0; } @@ -941,8 +999,10 @@ static void bt_mesh_net_local(void) { struct net_buf *buf = NULL; + BT_DBG("NetLocal"); + while ((buf = net_buf_slist_get(&bt_mesh.local_queue))) { - BT_DBG("len %u: %s", buf->len, bt_hex(buf->data, buf->len)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); bt_mesh_net_recv(&buf->b, 0, BLE_MESH_NET_IF_LOCAL); net_buf_unref(buf); } @@ -956,6 +1016,10 @@ int bt_mesh_net_encode(struct bt_mesh_net_tx *tx, struct net_buf_simple *buf, uint8_t nid = 0U; int err = 0; + BT_DBG("NetEncode"); + BT_DBG("Src 0x%04x Dst 0x%04x Cred 0x%02x CTL %u Proxy %u", + tx->src, tx->ctx->addr, tx->ctx->send_cred, ctl, proxy); + if (ctl && net_buf_simple_tailroom(buf) < BLE_MESH_MIC_LONG) { BT_ERR("Insufficient MIC space for CTL PDU"); return -EINVAL; @@ -966,9 +1030,6 @@ int bt_mesh_net_encode(struct bt_mesh_net_tx *tx, struct net_buf_simple *buf, return -EINVAL; } - BT_DBG("src 0x%04x dst 0x%04x ctl %u seq 0x%06x", - tx->src, tx->ctx->addr, ctl, bt_mesh.seq); - net_buf_simple_push_be16(buf, tx->ctx->addr); net_buf_simple_push_be16(buf, tx->src); @@ -980,8 +1041,6 @@ int bt_mesh_net_encode(struct bt_mesh_net_tx *tx, struct net_buf_simple *buf, net_buf_simple_push_u8(buf, tx->ctx->send_ttl); } - BT_INFO("Use security credentials 0x%02x, proxy %d", tx->ctx->send_cred, proxy); - if (IS_ENABLED(CONFIG_BLE_MESH_LOW_POWER) && tx->ctx->send_cred == BLE_MESH_FRIENDSHIP_CRED) { err = friend_cred_get(tx->sub, BLE_MESH_ADDR_UNASSIGNED, @@ -1042,16 +1101,13 @@ static void bt_mesh_net_adv_xmit_update(struct bt_mesh_net_tx *tx) */ if (bt_mesh_tag_friendship(tx->ctx->send_tag)) { tx->xmit = BLE_MESH_TRANSMIT(0, BLE_MESH_TRANSMIT_INT(bt_mesh_net_transmit_get())); - return; - } - - if (bt_mesh_tag_relay(tx->ctx->send_tag)) { + } else if (bt_mesh_tag_relay(tx->ctx->send_tag)) { tx->xmit = bt_mesh_relay_retransmit_get(); } else { tx->xmit = bt_mesh_net_transmit_get(); } - return; + BT_INFO("NetAdvXmitUpdate, Tag 0x%02x Xmit 0x%02x", tx->ctx->send_tag, tx->xmit); } #endif /* !CONFIG_BLE_MESH_V11_SUPPORT */ @@ -1062,11 +1118,11 @@ int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct net_buf *buf, uint8_t bearer = BLE_MESH_ALL_BEARERS; int err = 0; - BT_DBG("src 0x%04x dst 0x%04x len %u headroom %u tailroom %u", - tx->src, tx->ctx->addr, buf->len, net_buf_headroom(buf), - net_buf_tailroom(buf)); - BT_DBG("Payload len %u: %s", buf->len, bt_hex(buf->data, buf->len)); - BT_DBG("Seq 0x%06x", bt_mesh.seq); + BT_DBG("NetSend"); + BT_DBG("Src 0x%04x Dst 0x%04x TTL %u Cred %u Tag 0x%02x Seq 0x%06x Room %u/%u", + tx->src, tx->ctx->addr, tx->ctx->send_ttl, tx->ctx->send_cred, + tx->ctx->send_tag, bt_mesh.seq, net_buf_headroom(buf), net_buf_tailroom(buf)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); if (tx->ctx->send_ttl == BLE_MESH_TTL_DEFAULT) { tx->ctx->send_ttl = bt_mesh_default_ttl_get(); @@ -1100,6 +1156,8 @@ int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct net_buf *buf, #if CONFIG_BLE_MESH_DF_SRV bt_mesh_update_net_send_cred(tx, &bearer); + + BT_DBG("TxBearer 0x%02x", bearer); #endif /* CONFIG_BLE_MESH_DF_SRV */ err = bt_mesh_net_encode(tx, &buf->b, false); @@ -1140,9 +1198,10 @@ int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct net_buf *buf, * a advertising method. */ if (bt_mesh_proxy_server_find_client_by_addr(tx->ctx->addr)) { + BT_DBG("ProxyClientFound"); + send_cb_finalize(send_cb, cb_data); send_cb = NULL; - goto done; } @@ -1154,6 +1213,7 @@ int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct net_buf *buf, #if CONFIG_BLE_MESH_GATT_PROXY_CLIENT /* This message will not be transmitted by proxy client */ if (!bt_mesh_proxy_client_get_conn_count()) { + BT_DBG("ProxyClientNoConn"); goto done; } #endif /* CONFIG_BLE_MESH_GATT_PROXY_CLIENT */ @@ -1167,6 +1227,8 @@ int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct net_buf *buf, (tx->ctx->send_ttl != 1U || bt_mesh_tag_relay(tx->ctx->send_tag)) && tx->ctx->send_cred != BLE_MESH_FRIENDSHIP_CRED) { if (bt_mesh_proxy_client_relay(&buf->b, tx->ctx->addr)) { + BT_DBG("ProxyClientRelay"); + /* If Proxy Client succeeds to send messages with GATT bearer, * we can directly finish here. And if not, which means no * connection has been created with Proxy Client, here we will @@ -1175,7 +1237,6 @@ int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct net_buf *buf, if ((bearer & (~BLE_MESH_GATT_BEARER)) == 0) { send_cb_finalize(send_cb, cb_data); send_cb = NULL; - goto done; } } @@ -1203,11 +1264,11 @@ int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct net_buf *buf, } bt_mesh_net_local(); - goto done; } net_buf_slist_put(&bt_mesh.local_queue, net_buf_ref(buf)); + bt_mesh_net_local(); } @@ -1226,16 +1287,12 @@ int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct net_buf *buf, */ bt_mesh_net_adv_xmit_update(tx); - BT_INFO("Network PDU, count %d, interval %d", - BLE_MESH_TRANSMIT_COUNT(tx->xmit), BLE_MESH_TRANSMIT_INT(tx->xmit)); bt_mesh_adv_send(buf, tx->xmit, cb, cb_data); - goto done; } - BT_WARN("Not sent, src 0x%04x, dst 0x%04x, ttl %d, cred 0x%02x, tag 0x%02x", - tx->src, tx->ctx->addr, tx->ctx->send_ttl, tx->ctx->send_cred, - tx->ctx->send_tag); + BT_WARN("NetNotSend"); + err = -EIO; done: @@ -1249,7 +1306,10 @@ static bool auth_match(struct bt_mesh_subnet_keys *keys, { uint8_t net_auth[8] = {0}; + BT_DBG("AuthMatch"); + if (memcmp(net_id, keys->net_id, 8)) { + BT_DBG("NetID %s != %s", bt_hex(net_id, 8), bt_hex(keys->net_id, 8)); return false; } @@ -1257,8 +1317,7 @@ static bool auth_match(struct bt_mesh_subnet_keys *keys, net_auth); if (memcmp(auth, net_auth, 8)) { - BT_WARN("Authentication Value %s != %s", - bt_hex(auth, 8), bt_hex(net_auth, 8)); + BT_WARN("NetAuth %s != %s", bt_hex(auth, 8), bt_hex(net_auth, 8)); return false; } @@ -1274,6 +1333,8 @@ struct bt_mesh_subnet *bt_mesh_subnet_find_with_snb(const uint8_t net_id[8], uin subnet_size = bt_mesh_rx_netkey_size(); + BT_DBG("SubnetFindWithSnb, Size %lu", subnet_size); + for (i = 0; i < subnet_size; i++) { struct bt_mesh_subnet *sub = bt_mesh_rx_netkey_get(i); @@ -1304,8 +1365,10 @@ int net_decrypt(struct bt_mesh_subnet *sub, const uint8_t *enc, size_t data_len, struct bt_mesh_net_rx *rx, struct net_buf_simple *buf) { - BT_DBG("NID 0x%02x net_idx 0x%04x", BLE_MESH_NET_HDR_NID(data), sub->net_idx); - BT_DBG("IVI %u net->iv_index 0x%08x", BLE_MESH_NET_HDR_IVI(data), bt_mesh.iv_index); + BT_DBG("NetDecrypt"); + BT_DBG("IVI %u NID 0x%02x NetIdx 0x%04x IVIndex %lu NetIf %u", + BLE_MESH_NET_HDR_IVI(data), BLE_MESH_NET_HDR_NID(data), + sub->net_idx, bt_mesh.iv_index, rx->net_if); rx->old_iv = (BLE_MESH_NET_HDR_IVI(data) != (bt_mesh.iv_index & 0x01)); @@ -1327,12 +1390,11 @@ int net_decrypt(struct bt_mesh_subnet *sub, const uint8_t *enc, return -EALREADY; } - BT_DBG("src 0x%04x", rx->ctx.addr); + BT_DBG("Src 0x%04x", rx->ctx.addr); if (IS_ENABLED(CONFIG_BLE_MESH_PROXY) && rx->net_if == BLE_MESH_NET_IF_PROXY_CFG) { - return bt_mesh_net_decrypt(enc, buf, BLE_MESH_NET_IVI_RX(rx), - true, false); + return bt_mesh_net_decrypt(enc, buf, BLE_MESH_NET_IVI_RX(rx), true, false); } return bt_mesh_net_decrypt(enc, buf, BLE_MESH_NET_IVI_RX(rx), false, false); @@ -1345,7 +1407,9 @@ static int friend_decrypt(struct bt_mesh_subnet *sub, const uint8_t *data, { int i; - BT_DBG("NID 0x%02x net_idx 0x%04x", BLE_MESH_NET_HDR_NID(data), sub->net_idx); + BT_DBG("FrndDecrypt"); + BT_DBG("NID 0x%02x NetIdx 0x%04x KrPhase %u", + BLE_MESH_NET_HDR_NID(data), sub->net_idx, sub->kr_phase); for (i = 0; i < ARRAY_SIZE(friend_cred); i++) { struct friend_cred *cred = &friend_cred[i]; @@ -1357,6 +1421,7 @@ static int friend_decrypt(struct bt_mesh_subnet *sub, const uint8_t *data, if (BLE_MESH_NET_HDR_NID(data) == cred->cred[0].nid && !net_decrypt(sub, cred->cred[0].enc, cred->cred[0].privacy, data, data_len, rx, buf)) { + BT_DBG("UseOldKey"); return 0; } @@ -1367,6 +1432,7 @@ static int friend_decrypt(struct bt_mesh_subnet *sub, const uint8_t *data, if (BLE_MESH_NET_HDR_NID(data) == cred->cred[1].nid && !net_decrypt(sub, cred->cred[1].enc, cred->cred[1].privacy, data, data_len, rx, buf)) { + BT_DBG("UseNewKey"); rx->new_key = 1U; return 0; } @@ -1380,11 +1446,14 @@ static int flooding_decrypt(struct bt_mesh_subnet *sub, const uint8_t *data, size_t data_len, struct bt_mesh_net_rx *rx, struct net_buf_simple *buf) { - BT_DBG("NID 0x%02x net_idx 0x%04x", BLE_MESH_NET_HDR_NID(data), sub->net_idx); + BT_DBG("FloodingDecrypt"); + BT_DBG("NID 0x%02x NetIdx 0x%04x KrPhase %u", + BLE_MESH_NET_HDR_NID(data), sub->net_idx, sub->kr_phase); if (BLE_MESH_NET_HDR_NID(data) == sub->keys[0].nid && !net_decrypt(sub, sub->keys[0].enc, sub->keys[0].privacy, data, data_len, rx, buf)) { + BT_DBG("UseOldKey"); return 0; } @@ -1395,6 +1464,7 @@ static int flooding_decrypt(struct bt_mesh_subnet *sub, const uint8_t *data, if (BLE_MESH_NET_HDR_NID(data) == sub->keys[1].nid && !net_decrypt(sub, sub->keys[1].enc, sub->keys[1].privacy, data, data_len, rx, buf)) { + BT_DBG("UseNewKey"); rx->new_key = 1U; return 0; } @@ -1412,10 +1482,12 @@ static bool net_find_and_decrypt(const uint8_t *data, size_t data_len, array_size = bt_mesh_rx_netkey_size(); + BT_DBG("NetFindAndDecrypt, Size %u", array_size); + for (i = 0; i < array_size; i++) { sub = bt_mesh_rx_netkey_get(i); if (!sub) { - BT_DBG("Subnet not found"); + BT_DBG("SubNotFound"); continue; } @@ -1425,7 +1497,7 @@ static bool net_find_and_decrypt(const uint8_t *data, size_t data_len, #if CONFIG_BLE_MESH_BRC_SRV sub->sbr_net_idx = BLE_MESH_KEY_UNUSED; -#endif +#endif /* CONFIG_BLE_MESH_BRC_SRV */ #if (CONFIG_BLE_MESH_LOW_POWER || CONFIG_BLE_MESH_FRIEND) if (!friend_decrypt(sub, data, data_len, rx, buf)) { @@ -1434,7 +1506,7 @@ static bool net_find_and_decrypt(const uint8_t *data, size_t data_len, rx->sub = sub; return true; } -#endif +#endif /* (CONFIG_BLE_MESH_LOW_POWER || CONFIG_BLE_MESH_FRIEND) */ #if CONFIG_BLE_MESH_DF_SRV if (!bt_mesh_directed_decrypt(sub, data, data_len, rx, buf)) { @@ -1463,6 +1535,8 @@ static bool net_find_and_decrypt(const uint8_t *data, size_t data_len, */ static bool relay_to_adv(enum bt_mesh_net_if net_if) { + BT_DBG("RelayToAdv, NetIf %u", net_if); + switch (net_if) { case BLE_MESH_NET_IF_LOCAL: return true; @@ -1472,7 +1546,7 @@ static bool relay_to_adv(enum bt_mesh_net_if net_if) return (bt_mesh_gatt_proxy_get() == BLE_MESH_GATT_PROXY_ENABLED #if CONFIG_BLE_MESH_PRB_SRV || bt_mesh_private_gatt_proxy_state_get() == BLE_MESH_PRIVATE_GATT_PROXY_ENABLED -#endif +#endif /* CONFIG_BLE_MESH_PRB_SRV */ ); default: return false; @@ -1483,6 +1557,8 @@ static bool relay_to_adv(enum bt_mesh_net_if net_if) static uint8_t net_retransmission_adv(struct bt_mesh_net_rx *rx, uint8_t *cred, uint8_t *tag) { + BT_DBG("NetRetransmissionAdv"); + if (rx->ctx.recv_cred == BLE_MESH_FLOODING_CRED) { uint8_t bearer = BLE_MESH_NONE_BEARER; @@ -1506,6 +1582,8 @@ static uint8_t net_retransmission_adv(struct bt_mesh_net_rx *rx, *cred = BLE_MESH_FLOODING_CRED; } + BT_DBG("FloodingBearer 0x%02x", bearer); + return bearer; } @@ -1515,6 +1593,9 @@ static uint8_t net_retransmission_adv(struct bt_mesh_net_rx *rx, /* Condition: Directed friend is disabled. */ *cred = BLE_MESH_FLOODING_CRED; + + BT_DBG("FrndBearerAll"); + return BLE_MESH_ALL_BEARERS; } @@ -1524,6 +1605,8 @@ static uint8_t net_retransmission_adv(struct bt_mesh_net_rx *rx, static uint8_t net_retransmission_gatt(struct bt_mesh_net_rx *rx, uint8_t *cred, uint8_t *tag) { + BT_DBG("NetRetransmissionGatt"); + if (rx->ctx.recv_cred == BLE_MESH_FLOODING_CRED) { /* Inbound bearer: GATT; * Inbound Security Material: managed flooding; @@ -1533,6 +1616,9 @@ static uint8_t net_retransmission_gatt(struct bt_mesh_net_rx *rx, bt_mesh_gatt_proxy_get() == BLE_MESH_GATT_PROXY_ENABLED) { /* Condition: Directed proxy is disabled. */ *cred = BLE_MESH_FLOODING_CRED; + + BT_DBG("FloodingBearerAll"); + return BLE_MESH_ALL_BEARERS; } @@ -1561,14 +1647,19 @@ static void bt_mesh_net_relay(struct net_buf_simple *sbuf, struct bt_mesh_net_rx *rx) { const uint8_t *enc = NULL, *priv = NULL; + bool netkey_changed = false; struct net_buf *buf = NULL; uint8_t bearer = 0; uint8_t xmit = 0U; uint8_t cred = 0; uint8_t nid = 0U; - bool netkey_changed = false; uint8_t tag = 0; + BT_DBG("NetRelay"); + BT_DBG("TTL %u CTL %u Dst 0x%04x RecvCred %u NetIf %u", + rx->ctx.recv_ttl, rx->ctl, rx->ctx.recv_dst, + rx->ctx.recv_cred, rx->net_if); + if (rx->net_if == BLE_MESH_NET_IF_LOCAL) { /* Locally originated PDUs with TTL=1 will only be delivered * to local elements as per Mesh Profile 1.0 section 3.4.5.2: @@ -1624,12 +1715,12 @@ static void bt_mesh_net_relay(struct net_buf_simple *sbuf, BT_ERR("Bridge RPL attack"); goto done; } -#endif +#endif /* CONFIG_BLE_MESH_BRC_SRV */ if (cred != BLE_MESH_FLOODING_CRED #if CONFIG_BLE_MESH_DF_SRV - && cred != BLE_MESH_DIRECTED_CRED -#endif + && cred != BLE_MESH_DIRECTED_CRED +#endif /* CONFIG_BLE_MESH_DF_SRV */ ) { BT_WARN("No outbound security cred found, inbound cred %d", rx->ctx.recv_cred); return; @@ -1645,8 +1736,6 @@ static void bt_mesh_net_relay(struct net_buf_simple *sbuf, return; } - BT_DBG("TTL %u CTL %u dst 0x%04x", rx->ctx.recv_ttl, rx->ctl, rx->ctx.recv_dst); - /* The Relay Retransmit state is only applied to adv-adv relaying. * Anything else (like GATT to adv, or locally originated packets) * use the Network Transmit state. @@ -1698,7 +1787,7 @@ static void bt_mesh_net_relay(struct net_buf_simple *sbuf, /* Check if the number of relay packets in queue is too large, if so * use minimum relay retransmit value for later relay packets. */ - if (bt_mesh_get_stored_relay_count() >= BLE_MESH_MAX_STORED_RELAY_COUNT) { + if (bt_mesh_get_stored_relay_count() >= MAX_STORED_RELAY_COUNT) { xmit = BLE_MESH_TRANSMIT(0, 20); } #if CONFIG_BLE_MESH_EXT_ADV @@ -1754,10 +1843,12 @@ static void bt_mesh_net_relay(struct net_buf_simple *sbuf, /* Check if subnet bridge is supported & decide which NetKey is used */ if (bt_mesh_subnet_bridge_state_get() == BLE_MESH_SUBNET_BRIDGE_ENABLED) { netkey_changed = bt_mesh_bridge_change_net_key(rx, &enc, &priv, &nid, cred); - } -#endif - BT_DBG("Relaying packet. TTL is now %u", BLE_MESH_NET_HDR_TTL(buf->data)); + BT_DBG("NetKeyChanged %u", netkey_changed); + } +#endif /* CONFIG_BLE_MESH_BRC_SRV */ + + BT_DBG("Relaying, NewTTL %u", BLE_MESH_NET_HDR_TTL(buf->data)); /* 1. Update NID if RX or RX was with friend credentials(included by case 3). * 2. Update NID if the net_key has changed. @@ -1773,12 +1864,10 @@ static void bt_mesh_net_relay(struct net_buf_simple *sbuf, * layer nonce includes the IVI. */ if (bt_mesh_net_encrypt(enc, &buf->b, BLE_MESH_NET_IVI_RX(rx), false, false)) { - BT_ERR("Re-encrypting failed"); goto done; } if (bt_mesh_net_obfuscate(buf->data, BLE_MESH_NET_IVI_RX(rx), priv)) { - BT_ERR("Re-obfuscating failed"); goto done; } @@ -1795,14 +1884,15 @@ static void bt_mesh_net_relay(struct net_buf_simple *sbuf, cred != BLE_MESH_FRIENDSHIP_CRED) || #if CONFIG_BLE_MESH_PRB_SRV bt_mesh_private_gatt_proxy_state_get() == BLE_MESH_PRIVATE_GATT_PROXY_ENABLED || -#endif +#endif /* CONFIG_BLE_MESH_PRB_SRV */ rx->net_if == BLE_MESH_NET_IF_LOCAL || rx->ctx.recv_cred == BLE_MESH_FRIENDSHIP_CRED)) { if (bt_mesh_proxy_server_relay(&buf->b, rx->ctx.recv_dst) && BLE_MESH_ADDR_IS_UNICAST(rx->ctx.recv_dst)) { - + /* Not relay if only GATT bearer is chosen or found Proxy Client */ if (((bearer & (~BLE_MESH_GATT_BEARER)) == 0) || bt_mesh_proxy_server_find_client_by_addr(rx->ctx.recv_dst)) { + BT_DBG("ProxyNotRelay"); goto done; } } @@ -1814,9 +1904,9 @@ static void bt_mesh_net_relay(struct net_buf_simple *sbuf, rx->ctx.recv_cred == BLE_MESH_FRIENDSHIP_CRED) { #if !CONFIG_BLE_MESH_RELAY_ADV_BUF bt_mesh_adv_send(buf, xmit, NULL, NULL); -#else +#else /* !CONFIG_BLE_MESH_RELAY_ADV_BUF */ bt_mesh_relay_adv_send(buf, xmit, rx->ctx.addr, rx->ctx.recv_dst, NULL, NULL); -#endif +#endif /* !CONFIG_BLE_MESH_RELAY_ADV_BUF */ } done: @@ -1826,6 +1916,8 @@ done: void bt_mesh_net_header_parse(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx) { + BT_DBG("NetHeaderParse"); + rx->old_iv = (BLE_MESH_NET_HDR_IVI(buf->data) != (bt_mesh.iv_index & 0x01)); rx->ctl = BLE_MESH_NET_HDR_CTL(buf->data); rx->ctx.recv_ttl = BLE_MESH_NET_HDR_TTL(buf->data); @@ -1837,9 +1929,10 @@ void bt_mesh_net_header_parse(struct net_buf_simple *buf, int bt_mesh_net_decode(struct net_buf_simple *data, enum bt_mesh_net_if net_if, struct bt_mesh_net_rx *rx, struct net_buf_simple *buf) { + BT_DBG("NetDecode, NetIf %u", net_if); + if (data->len < BLE_MESH_NET_MIN_PDU_LEN) { BT_WARN("Dropping too short mesh packet (len %u)", data->len); - BT_WARN("%s", bt_hex(data->data, data->len)); return -EINVAL; } @@ -1847,7 +1940,7 @@ int bt_mesh_net_decode(struct net_buf_simple *data, enum bt_mesh_net_if net_if, return -EINVAL; } - BT_DBG("%u bytes: %s", data->len, bt_hex(data->data, data->len)); + BT_DBG("Len %u: %s", data->len, bt_hex(data->data, data->len)); rx->net_if = net_if; @@ -1883,8 +1976,6 @@ int bt_mesh_net_decode(struct net_buf_simple *data, enum bt_mesh_net_if net_if, rx->seq = BLE_MESH_NET_HDR_SEQ(buf->data); rx->ctx.recv_dst = BLE_MESH_NET_HDR_DST(buf->data); - BT_DBG("Decryption successful. Payload len %u", buf->len); - if (net_if != BLE_MESH_NET_IF_PROXY_CFG && rx->ctx.recv_dst == BLE_MESH_ADDR_UNASSIGNED) { BT_ERR("Destination address is unassigned; dropping packet"); @@ -1897,16 +1988,15 @@ int bt_mesh_net_decode(struct net_buf_simple *data, enum bt_mesh_net_if net_if, BT_ERR("Destination address is RFU; dropping packet 0x%02x", rx->ctx.recv_dst); return -EBADMSG; } -#endif +#endif /* !CONFIG_BLE_MESH_BQB_TEST */ if (net_if != BLE_MESH_NET_IF_LOCAL && bt_mesh_elem_find(rx->ctx.addr)) { BT_DBG("Dropping locally originated packet"); return -EBADMSG; } - BT_DBG("src 0x%04x dst 0x%04x ttl %u", rx->ctx.addr, rx->ctx.recv_dst, - rx->ctx.recv_ttl); - BT_DBG("PDU: %s", bt_hex(buf->data, buf->len)); + BT_DBG("Src 0x%04x Dst 0x%04x TTL %u", rx->ctx.addr, rx->ctx.recv_dst, rx->ctx.recv_ttl); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); msg_cache_add(rx); @@ -1916,25 +2006,31 @@ int bt_mesh_net_decode(struct net_buf_simple *data, enum bt_mesh_net_if net_if, static bool ready_to_recv(void) { if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) { + BT_DBG("NodeReadyToRecv"); return true; } if (IS_ENABLED(CONFIG_BLE_MESH_PROVISIONER) && bt_mesh_is_provisioner_en()) { if (bt_mesh_provisioner_get_node_count()) { + BT_DBG("PvnrReadyToRecv"); return true; } } + BT_DBG("NotReadyToRecv"); return false; } static bool ignore_net_msg(uint16_t src, uint16_t dst) { + BT_DBG("IgnoreNetMsg, Src 0x%04x Dst 0x%04x", src, dst); + if (IS_ENABLED(CONFIG_BLE_MESH_FAST_PROV)) { /* When fast provisioning is enabled, the node addr * message will be sent to the Primary Provisioner, * which shall not be ignored here. */ + BT_DBG("FastProvNotIgnoreNetMsg"); return false; } @@ -1949,11 +2045,12 @@ static bool ignore_net_msg(uint16_t src, uint16_t dst) */ if (!bt_mesh_provisioner_get_node_with_addr(src) && !bt_mesh_elem_find(src)) { - BT_INFO("Not found node address 0x%04x", src); + BT_INFO("PvnrIgnoreNetMsg"); return true; } } + BT_DBG("NotIgnoreNetMsg"); return false; } @@ -1982,10 +2079,15 @@ void bt_mesh_generic_net_recv(struct net_buf_simple *data, BT_DBG("rssi %d net_if %u", rx->ctx.recv_rssi, net_if); if (bt_mesh_net_decode(data, net_if, rx, buf)) { + BT_DBG("DecodeFailed"); goto free_net_msg_buf; } + BT_DBG("NetRecv, Src 0x%04x Dst 0x%04x Rssi %d NetIf %u", + rx->ctx.addr, rx->ctx.recv_dst, rx->ctx.recv_rssi, net_if); + if (ignore_net_msg(rx->ctx.addr, rx->ctx.recv_dst)) { + BT_DBG("IgnoreNetMsg"); goto free_net_msg_buf; } @@ -2003,8 +2105,8 @@ void bt_mesh_generic_net_recv(struct net_buf_simple *data, * corresponding subnet. */ rx->local_match = (bt_mesh_fixed_group_match(rx->ctx.recv_dst) || - bt_mesh_fixed_direct_match(rx->sub, rx->ctx.recv_dst) || - bt_mesh_elem_find(rx->ctx.recv_dst)); + bt_mesh_fixed_direct_match(rx->sub, rx->ctx.recv_dst) || + bt_mesh_elem_find(rx->ctx.recv_dst)); #if CONFIG_BLE_MESH_LONG_PACKET /* It should be noted that if the length of buf @@ -2018,8 +2120,10 @@ void bt_mesh_generic_net_recv(struct net_buf_simple *data, if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) && #if CONFIG_BLE_MESH_PRB_SRV bt_mesh_private_gatt_proxy_state_get() != BLE_MESH_PRIVATE_GATT_PROXY_ENABLED && -#endif +#endif /* CONFIG_BLE_MESH_PRB_SRV */ net_if == BLE_MESH_NET_IF_PROXY) { + BT_DBG("ProxyServerAddrAdd"); + bt_mesh_proxy_server_addr_add(data, rx->ctx.addr); if (bt_mesh_gatt_proxy_get() == BLE_MESH_GATT_PROXY_DISABLED && @@ -2040,6 +2144,7 @@ void bt_mesh_generic_net_recv(struct net_buf_simple *data, rx->sub->use_directed == BLE_MESH_PROXY_USE_DIRECTED_ENABLED && !bt_mesh_addr_in_uar(&rx->sub->proxy_client_uar, rx->ctx.addr) && !bt_mesh_proxy_server_find_client_by_addr(rx->ctx.addr)) { + BT_DBG("ImmutableCredTag"); rx->ctx.recv_tag |= BLE_MESH_TAG_IMMUTABLE_CRED; } #endif /* CONFIG_BLE_MESH_DF_SRV */ @@ -2080,7 +2185,7 @@ static void ivu_refresh(struct k_work *work) { bt_mesh.ivu_duration += BLE_MESH_IVU_HOURS; - BT_INFO("%s for %u hour%s", + BT_INFO("IVURefresh, %s for %u hour%s", bt_mesh_atomic_test_bit(bt_mesh.flags, BLE_MESH_IVU_IN_PROGRESS) ? "IVU in Progress" : "IVU Normal mode", bt_mesh.ivu_duration, bt_mesh.ivu_duration == 1U ? "" : "s"); @@ -2104,6 +2209,8 @@ static void ivu_refresh(struct k_work *work) void bt_mesh_net_start(void) { + BT_DBG("NetStart"); + if (bt_mesh_secure_beacon_get() == BLE_MESH_SECURE_BEACON_ENABLED) { bt_mesh_secure_beacon_enable(); } else { @@ -2116,7 +2223,7 @@ void bt_mesh_net_start(void) } else { bt_mesh_private_beacon_disable(); } -#endif +#endif /* CONFIG_BLE_MESH_PRB_SRV */ if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) && bt_mesh_gatt_proxy_get() != BLE_MESH_GATT_PROXY_NOT_SUPPORTED) { @@ -2129,7 +2236,7 @@ void bt_mesh_net_start(void) bt_mesh_update_exceptional_list(BLE_MESH_EXCEP_LIST_SUB_CODE_ADD, BLE_MESH_EXCEP_LIST_TYPE_MESH_BEACON, NULL); -#endif +#endif /* CONFIG_BLE_MESH_USE_DUPLICATE_SCAN */ if (IS_ENABLED(CONFIG_BLE_MESH_LOW_POWER)) { /* TODO: Enable duplicate scan in Low Power Mode */ @@ -2148,6 +2255,7 @@ void bt_mesh_net_start(void) uint32_t iv_index = bt_mesh.iv_index; uint8_t flags = (uint8_t)bt_mesh.sub[0].kr_flag; const uint8_t *net_key = bt_mesh.sub[0].keys[flags].net; + if (bt_mesh_atomic_test_bit(bt_mesh.flags, BLE_MESH_IVU_IN_PROGRESS)) { flags |= BLE_MESH_NET_FLAG_IVU; } @@ -2158,16 +2266,20 @@ void bt_mesh_net_start(void) void bt_mesh_net_init(void) { + BT_DBG("NetInit"); + k_delayed_work_init(&bt_mesh.ivu_timer, ivu_refresh); } void bt_mesh_net_reset(void) { + BT_DBG("NetReset"); + k_delayed_work_cancel(&bt_mesh.ivu_timer); #if FRIEND_CRED_COUNT > 0 memset(friend_cred, 0, sizeof(friend_cred)); -#endif +#endif /* FRIEND_CRED_COUNT > 0 */ memset(msg_cache, 0, sizeof(msg_cache)); msg_cache_next = 0U; @@ -2182,6 +2294,8 @@ void bt_mesh_net_reset(void) #if CONFIG_BLE_MESH_DEINIT void bt_mesh_net_deinit(void) { + BT_DBG("NetDeinit"); + bt_mesh_net_reset(); k_delayed_work_free(&bt_mesh.ivu_timer); diff --git a/components/bt/esp_ble_mesh/core/net.h b/components/bt/esp_ble_mesh/core/net.h index e946daef0f2..1141bd2bd95 100644 --- a/components/bt/esp_ble_mesh/core/net.h +++ b/components/bt/esp_ble_mesh/core/net.h @@ -66,7 +66,7 @@ struct bt_mesh_subnet { #if CONFIG_BLE_MESH_BRC_SRV uint16_t sbr_net_idx; /* NetKeyIndex of bridged subnet */ -#endif +#endif /* CONFIG_BLE_MESH_BRC_SRV */ bool kr_flag; /* Key Refresh Flag */ uint8_t kr_phase; /* Key Refresh Phase */ @@ -163,17 +163,17 @@ struct bt_mesh_rpl { bool old_iv; #if CONFIG_BLE_MESH_SETTINGS bool store; -#endif +#endif /* CONFIG_BLE_MESH_SETTINGS */ uint32_t seq; }; #if CONFIG_BLE_MESH_FRIEND #define FRIEND_SEG_RX CONFIG_BLE_MESH_FRIEND_SEG_RX #define FRIEND_SUB_LIST_SIZE CONFIG_BLE_MESH_FRIEND_SUB_LIST_SIZE -#else +#else /* CONFIG_BLE_MESH_FRIEND */ #define FRIEND_SEG_RX 0 #define FRIEND_SUB_LIST_SIZE 0 -#endif +#endif /* CONFIG_BLE_MESH_FRIEND */ struct bt_mesh_friend { uint16_t lpn; @@ -220,10 +220,10 @@ struct bt_mesh_friend { }; #if CONFIG_BLE_MESH_LOW_POWER -#define LPN_GROUPS CONFIG_BLE_MESH_LPN_GROUPS -#else -#define LPN_GROUPS 0 -#endif +#define LPN_GROUPS CONFIG_BLE_MESH_LPN_GROUPS +#else /* CONFIG_BLE_MESH_LOW_POWER */ +#define LPN_GROUPS 0 +#endif /* CONFIG_BLE_MESH_LOW_POWER */ /* Low Power Node state */ struct bt_mesh_lpn { @@ -275,7 +275,7 @@ struct bt_mesh_lpn { #if CONFIG_BLE_MESH_DF_SRV uint8_t old_directed_forwarding; -#endif +#endif /* CONFIG_BLE_MESH_DF_SRV */ /* Duration reported for last advertising packet */ uint16_t adv_duration; @@ -331,11 +331,11 @@ struct bt_mesh_net { #if CONFIG_BLE_MESH_FRIEND /* Friend state, unique for each LPN that we're Friends for */ struct bt_mesh_friend frnd[CONFIG_BLE_MESH_FRIEND_LPN_COUNT]; -#endif +#endif /* CONFIG_BLE_MESH_FRIEND */ #if CONFIG_BLE_MESH_LOW_POWER struct bt_mesh_lpn lpn; /* Low Power Node state */ -#endif +#endif /* CONFIG_BLE_MESH_LOW_POWER */ /* Number of hours in current IV Update state */ uint8_t ivu_duration; @@ -362,7 +362,7 @@ struct bt_mesh_net { struct bt_mesh_subnet *p_sub[CONFIG_BLE_MESH_PROVISIONER_SUBNET_COUNT]; /* Next net_idx can be assigned */ uint16_t p_net_idx_next; -#endif +#endif /* CONFIG_BLE_MESH_PROVISIONER */ }; /* Network interface */ @@ -393,7 +393,7 @@ struct bt_mesh_net_rx { friend_match:1, /* Matched an LPN we're friends for */ #if CONFIG_BLE_MESH_NOT_RELAY_REPLAY_MSG replay_msg:1, /* Replayed messages */ -#endif +#endif /* CONFIG_BLE_MESH_NOT_RELAY_REPLAY_MSG */ sbr_rpl:1; /* Bridge RPL attacker */ uint16_t msg_cache_idx; /* Index of entry in message cache */ }; @@ -431,7 +431,7 @@ void bt_mesh_msg_cache_clear(uint16_t unicast_addr, uint8_t elem_num); int bt_mesh_net_keys_create(struct bt_mesh_subnet_keys *keys, const uint8_t key[16]); -int bt_mesh_net_create(uint16_t idx, uint8_t flags, const uint8_t key[16], +int bt_mesh_net_create(uint16_t net_idx, uint8_t flags, const uint8_t key[16], uint32_t iv_index); uint8_t bt_mesh_net_flags(struct bt_mesh_subnet *sub); diff --git a/components/bt/esp_ble_mesh/core/nimble_host/adapter.c b/components/bt/esp_ble_mesh/core/nimble_host/adapter.c index d89c63b3492..4d598a333e2 100644 --- a/components/bt/esp_ble_mesh/core/nimble_host/adapter.c +++ b/components/bt/esp_ble_mesh/core/nimble_host/adapter.c @@ -993,8 +993,8 @@ static int gap_event_cb(struct ble_gap_event *event, void *arg) return 0; case BLE_GAP_EVENT_ADV_COMPLETE: - BT_DBG("advertise complete; reason=%d", - event->adv_complete.reason); + BT_DBG("advertise complete; reason=%d", event->adv_complete.reason); + #if CONFIG_BLE_MESH_USE_BLE_50 #if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV bt_mesh_adv_task_wakeup(ADV_TASK_ADV_INST_EVT(event->adv_complete.instance)); diff --git a/components/bt/esp_ble_mesh/core/prov_common.c b/components/bt/esp_ble_mesh/core/prov_common.c index 6f9e1dfa417..a29ba8fb4fe 100644 --- a/components/bt/esp_ble_mesh/core/prov_common.c +++ b/components/bt/esp_ble_mesh/core/prov_common.c @@ -419,6 +419,9 @@ static void prov_retransmit(struct k_work *work) } #if CONFIG_BLE_MESH_FAST_PROV + BT_DBG("FastProv, TxPDUType %u LastTxPDU %u", + link->tx_pdu_type, link->last_tx_pdu); + if (link->tx_pdu_type >= link->last_tx_pdu) { timeout = K_SECONDS(30); } @@ -651,6 +654,9 @@ int bt_mesh_prov_send_adv(struct bt_mesh_prov_link *link, struct net_buf_simple send_reliable(link, PROV_XMIT); #if CONFIG_BLE_MESH_FAST_PROV + BT_DBG("FastProv, TxPDUType %u LastTxPDU %u", + link->tx_pdu_type, link->last_tx_pdu); + if (link->tx_pdu_type >= link->last_tx_pdu) { timeout = K_SECONDS(60); } diff --git a/components/bt/esp_ble_mesh/core/proxy_client.c b/components/bt/esp_ble_mesh/core/proxy_client.c index ac05f92ffee..710159fd252 100644 --- a/components/bt/esp_ble_mesh/core/proxy_client.c +++ b/components/bt/esp_ble_mesh/core/proxy_client.c @@ -23,11 +23,11 @@ #if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" -#endif +#endif /* CONFIG_BLE_MESH_V11_SUPPORT */ #if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \ - (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) + (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) static struct bt_mesh_proxy_server { struct bt_mesh_conn *conn; @@ -40,7 +40,8 @@ static struct bt_mesh_proxy_server { #if CONFIG_BLE_MESH_GATT_PROXY_CLIENT uint16_t net_idx; -#endif +#endif /* CONFIG_BLE_MESH_GATT_PROXY_CLIENT */ + uint8_t msg_type; struct k_delayed_work sar_timer; @@ -53,7 +54,7 @@ static struct { struct bt_mesh_prov_link *link; bt_mesh_addr_t addr; } waiting_conn_link[BLE_MESH_MAX_CONN]; -#endif +#endif /* CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT */ static uint8_t server_buf_data[BLE_MESH_PROXY_BUF_SIZE * BLE_MESH_MAX_CONN]; @@ -61,6 +62,8 @@ static struct bt_mesh_proxy_server *find_server(struct bt_mesh_conn *conn) { int i; + BT_DBG("FindServer, ConnHandle 0x%04x", conn->handle); + for (i = 0; i < ARRAY_SIZE(servers); i++) { if (servers[i].conn == conn) { return &servers[i]; @@ -74,15 +77,16 @@ static void proxy_sar_timeout(struct k_work *work) { struct bt_mesh_proxy_server *server = NULL; - BT_WARN("%s", __func__); + BT_WARN("ProxySARTimeout"); server = CONTAINER_OF(work, struct bt_mesh_proxy_server, sar_timer.work); if (!server || !server->conn) { - BT_ERR("Invalid proxy server parameter"); + BT_ERR("InvalidProxyServerParam"); return; } net_buf_simple_reset(&server->buf); + bt_mesh_gattc_disconnect(server->conn); } @@ -90,6 +94,8 @@ static void proxy_sar_timeout(struct k_work *work) int bt_mesh_rpr_srv_set_waiting_prov_link(struct bt_mesh_prov_link *link, bt_mesh_addr_t *addr) { + BT_DBG("RPRSrvSetWaitingProvLink"); + for (size_t i = 0; i < ARRAY_SIZE(waiting_conn_link);i++) { if (waiting_conn_link[i].link == NULL) { waiting_conn_link[i].link = link; @@ -103,8 +109,7 @@ int bt_mesh_rpr_srv_set_waiting_prov_link(struct bt_mesh_prov_link *link, #endif /* CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT */ #if CONFIG_BLE_MESH_GATT_PROXY_CLIENT -/** - * The following callbacks are used to notify proper information +/* The following callbacks are used to notify proper information * to the application layer. */ static proxy_client_recv_adv_cb_t proxy_client_adv_recv_cb; @@ -139,6 +144,8 @@ static void filter_status(struct bt_mesh_proxy_server *server, uint8_t filter_type = 0U; uint16_t list_size = 0U; + BT_DBG("FilterStatus"); + if (buf->len != 3) { BT_ERR("Invalid Proxy Filter Status length %d", buf->len); return; @@ -152,10 +159,11 @@ static void filter_status(struct bt_mesh_proxy_server *server, list_size = net_buf_simple_pull_be16(buf); - BT_INFO("filter_type 0x%02x, list_size %d", filter_type, list_size); + BT_INFO("FilterType %u ListSize %u", filter_type, list_size); if (proxy_client_filter_status_recv_cb) { - proxy_client_filter_status_recv_cb(server - servers, rx->ctx.addr, server->net_idx, filter_type, list_size); + proxy_client_filter_status_recv_cb(server - servers, rx->ctx.addr, + server->net_idx, filter_type, list_size); } } @@ -167,7 +175,7 @@ static void recv_directed_proxy_caps_status(struct bt_mesh_proxy_server *server, uint8_t directed_proxy = net_buf_simple_pull_u8(buf); uint8_t use_directed = net_buf_simple_pull_u8(buf); - BT_INFO("Directed Proxy 0x%02x, Use Directed 0x%02x", directed_proxy, use_directed); + BT_INFO("DirectedProxy %u UseDirected %u", directed_proxy, use_directed); ARG_UNUSED(directed_proxy); ARG_UNUSED(use_directed); @@ -181,13 +189,14 @@ static void proxy_cfg(struct bt_mesh_proxy_server *server) uint8_t opcode = 0U; int err = 0; + BT_DBG("ProxyCfg"); + if (server->buf.len > 29) { BT_ERR("Too large proxy cfg pdu (len %d)", server->buf.len); return; } - err = bt_mesh_net_decode(&server->buf, BLE_MESH_NET_IF_PROXY_CFG, - &rx, &buf); + err = bt_mesh_net_decode(&server->buf, BLE_MESH_NET_IF_PROXY_CFG, &rx, &buf); if (err) { BT_ERR("Failed to decode Proxy Configuration (err %d)", err); return; @@ -201,7 +210,7 @@ static void proxy_cfg(struct bt_mesh_proxy_server *server) rx.local_match = 1U; if (bt_mesh_rpl_check(&rx, NULL)) { - BT_WARN("Replay: src 0x%04x dst 0x%04x seq 0x%06x", + BT_WARN("Replay, Src 0x%04x Dst 0x%04x Seq 0x%06x", rx.ctx.addr, rx.ctx.recv_dst, rx.seq); return; } @@ -209,7 +218,7 @@ static void proxy_cfg(struct bt_mesh_proxy_server *server) /* Remove network headers */ net_buf_simple_pull(&buf, BLE_MESH_NET_HDR_LEN); - BT_DBG("%u bytes: %s", buf.len, bt_hex(buf.data, buf.len)); + BT_DBG("Len %u: %s", buf.len, bt_hex(buf.data, buf.len)); if (buf.len < 3) { BT_WARN("Too short proxy configuration PDU"); @@ -243,6 +252,8 @@ static void proxy_cfg(struct bt_mesh_proxy_server *server) static void proxy_complete_pdu(struct bt_mesh_proxy_server *server) { + BT_DBG("ProxyCompletePDU"); + switch (server->msg_type) { #if CONFIG_BLE_MESH_GATT_PROXY_CLIENT case BLE_MESH_PROXY_NET_PDU: @@ -265,14 +276,14 @@ static void proxy_complete_pdu(struct bt_mesh_proxy_server *server) if (server->conn == bt_mesh_prov_node_get_link()->conn) { bt_mesh_pb_gatt_recv(server->conn, &server->buf); } else -#endif +#endif /* CONFIG_BLE_MESH_RPR_SRV */ { #if CONFIG_BLE_MESH_PROVISIONER bt_mesh_provisioner_pb_gatt_recv(server->conn, &server->buf); -#endif +#endif /* CONFIG_BLE_MESH_PROVISIONER */ } break; -#endif +#endif /* CONFIG_BLE_MESH_PB_GATT && (CONFIG_BLE_MESH_PROVISIONER || CONFIG_BLE_MESH_RPR_SRV) */ default: BT_WARN("Unhandled Message Type 0x%02x", server->msg_type); break; @@ -291,6 +302,8 @@ static ssize_t proxy_recv(struct bt_mesh_conn *conn, const uint8_t *data = buf; uint16_t srvc_uuid = 0U; + BT_DBG("ProxyRecv, ConnHandle 0x%04x", conn->handle); + if (!server) { BT_ERR("No Proxy Server object found"); return -ENOTCONN; @@ -377,7 +390,8 @@ static ssize_t proxy_recv(struct bt_mesh_conn *conn, static int proxy_send(struct bt_mesh_conn *conn, const void *data, uint16_t len) { - BT_DBG("%u bytes: %s", len, bt_hex(data, len)); + BT_DBG("ProxySend"); + BT_DBG("Len %u: %s", len, bt_hex(data, len)); return bt_mesh_gattc_write_no_rsp(conn, NULL, data, len); } @@ -388,13 +402,15 @@ int bt_mesh_proxy_client_segment_send(struct bt_mesh_conn *conn, uint8_t type, uint16_t mtu = 0U; int err = 0; + BT_DBG("ProxyClientSegSend"); + if (conn == NULL) { BT_ERR("%s, Invalid parameter", __func__); return -EINVAL; } - BT_DBG("conn %p type 0x%02x len %u: %s", conn, type, msg->len, - bt_hex(msg->data, msg->len)); + BT_DBG("ConnHandle 0x%04x Type %u", conn->handle, type); + BT_DBG("Len %u: %s", msg->len, bt_hex(msg->data, msg->len)); mtu = bt_mesh_gattc_get_mtu_info(conn); if (!mtu) { @@ -402,6 +418,8 @@ int bt_mesh_proxy_client_segment_send(struct bt_mesh_conn *conn, uint8_t type, return -ENOTCONN; } + BT_DBG("MTU %u", mtu); + /* ATT_MTU - OpCode (1 byte) - Handle (2 bytes) */ mtu -= 3; if (mtu > msg->len) { @@ -433,6 +451,8 @@ int bt_mesh_proxy_client_send(struct bt_mesh_conn *conn, uint8_t type, { struct bt_mesh_proxy_server *server = find_server(conn); + BT_DBG("ProxyClientSend, ConnHandle 0x%04x Type %u", conn->handle, type); + if (!server) { BT_ERR("No Proxy Server object found"); return -ENOTCONN; @@ -450,6 +470,8 @@ static void proxy_connected(bt_mesh_addr_t *addr, struct bt_mesh_conn *conn, int { struct bt_mesh_proxy_server *server = NULL; + BT_DBG("ProxyConnected, ConnHandle 0x%04x ID %d", conn->handle, id); + if (!servers[id].conn) { server = &servers[id]; } @@ -475,7 +497,7 @@ static void proxy_connected(bt_mesh_addr_t *addr, struct bt_mesh_conn *conn, int break; } } -#endif +#endif /* CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT */ bt_mesh_gattc_exchange_mtu(id); } @@ -484,7 +506,7 @@ static void proxy_disconnected(bt_mesh_addr_t *addr, struct bt_mesh_conn *conn, { struct bt_mesh_proxy_server *server = find_server(conn); - BT_DBG("conn %p, handle is %d, reason 0x%02x", conn, conn->handle, reason); + BT_DBG("ProxyDisconnected, ConnHandle 0x%04x Reason 0x%02x", conn->handle, reason); if (!server) { BT_ERR("No Proxy Server object found"); @@ -521,14 +543,15 @@ static void proxy_disconnected(bt_mesh_addr_t *addr, struct bt_mesh_conn *conn, proxy_client_disconnect_cb(addr, server - servers, server->net_idx, reason); } } -#endif +#endif /* CONFIG_BLE_MESH_GATT_PROXY_CLIENT */ k_delayed_work_cancel(&server->sar_timer); + server->conn = NULL; server->conn_type = CLI_NONE; #if CONFIG_BLE_MESH_GATT_PROXY_CLIENT server->net_idx = BLE_MESH_KEY_UNUSED; -#endif +#endif /* CONFIG_BLE_MESH_GATT_PROXY_CLIENT */ } #if CONFIG_BLE_MESH_PB_GATT && \ @@ -537,6 +560,8 @@ static ssize_t prov_write_ccc(bt_mesh_addr_t *addr, struct bt_mesh_conn *conn) { struct bt_mesh_proxy_server *server = find_server(conn); + BT_DBG("ProvWriteCCC, ConnHandle 0x%04x", conn->handle); + if (!server) { BT_ERR("No Proxy Server object found"); return -ENOTCONN; @@ -555,11 +580,11 @@ static ssize_t prov_write_ccc(bt_mesh_addr_t *addr, struct bt_mesh_conn *conn) return bt_mesh_rpr_srv_recv_link_ack(addr->val, false); } -#endif +#endif /* CONFIG_BLE_MESH_RPR_SRV */ #if CONFIG_BLE_MESH_PROVISIONER return bt_mesh_provisioner_pb_gatt_open(conn, addr->val); -#endif +#endif /* CONFIG_BLE_MESH_PROVISIONER */ } return -ENOMEM; @@ -569,6 +594,8 @@ static ssize_t prov_recv_ntf(struct bt_mesh_conn *conn, uint8_t *data, uint16_t { struct bt_mesh_proxy_server *server = find_server(conn); + BT_DBG("ProvRecvNtf, ConnHandle 0x%04x", conn->handle); + if (!server) { BT_ERR("No Proxy Server object found"); return -ENOTCONN; @@ -585,6 +612,8 @@ int bt_mesh_proxy_client_prov_enable(void) { int i; + BT_DBG("ProxyClientProvEnable"); + for (i = 0; i < ARRAY_SIZE(servers); i++) { if (servers[i].conn) { servers[i].conn_type = CLI_PROV; @@ -598,6 +627,8 @@ int bt_mesh_proxy_client_prov_disable(void) { int i; + BT_DBG("ProxyClientProvDisable"); + for (i = 0; i < ARRAY_SIZE(servers); i++) { struct bt_mesh_proxy_server *server = &servers[i]; @@ -616,6 +647,8 @@ static ssize_t proxy_write_ccc(bt_mesh_addr_t *addr, struct bt_mesh_conn *conn) { struct bt_mesh_proxy_server *server = find_server(conn); + BT_DBG("ProxyWriteCCC, ConnHandle 0x%04x", conn->handle); + if (!server) { BT_ERR("No Proxy Server object found"); return -ENOTCONN; @@ -631,11 +664,12 @@ static ssize_t proxy_write_ccc(bt_mesh_addr_t *addr, struct bt_mesh_conn *conn) } #if CONFIG_BLE_MESH_BQB_TEST - /* notify maybe received first */ + /* Notification maybe received firstly */ if (server->conn_type == CLI_PROXY) { return 0; } -#endif +#endif /* CONFIG_BLE_MESH_BQB_TEST */ + return -EINVAL; } @@ -643,20 +677,23 @@ static ssize_t proxy_recv_ntf(struct bt_mesh_conn *conn, uint8_t *data, uint16_t { struct bt_mesh_proxy_server *server = find_server(conn); + BT_DBG("ProxyRecvNtf, ConnHandle 0x%04x", conn->handle); + if (!server) { BT_ERR("No Proxy Server object found"); return -ENOTCONN; } #if CONFIG_BLE_MESH_BQB_TEST - /* update conn type if notify received before write ccc */ + /* Update conn type if notification received before writing ccc */ if (server->conn_type == CLI_NONE) { server->conn_type = CLI_PROXY; + if (proxy_client_connect_cb) { proxy_client_connect_cb(&server->addr, server - servers, server->net_idx); } } -#endif +#endif /* CONFIG_BLE_MESH_BQB_TEST */ if (server->conn_type == CLI_PROXY) { return proxy_recv(conn, NULL, data, len, 0, 0); @@ -665,8 +702,7 @@ static ssize_t proxy_recv_ntf(struct bt_mesh_conn *conn, uint8_t *data, uint16_t return -EINVAL; } -/** - * Currently proxy client doesn't need bt_mesh_proxy_client_gatt_enable() +/* Currently proxy client doesn't need bt_mesh_proxy_client_gatt_enable() * and bt_mesh_proxy_client_gatt_disable() functions, and once they are * used, proxy client can be enabled to parse node_id_adv and net_id_adv * in order to support proxy client role. @@ -677,6 +713,8 @@ int bt_mesh_proxy_client_gatt_enable(void) { int i; + BT_DBG("ProxyClientGattEnable"); + for (i = 0; i < ARRAY_SIZE(servers); i++) { if (servers[i].conn) { servers[i].conn_type = CLI_PROXY; @@ -696,8 +734,9 @@ int bt_mesh_proxy_client_gatt_disable(void) { int i; - /** - * TODO: + BT_DBG("ProxyClientGattDisable"); + + /* TODO: * Once this function is invoked, proxy client shall stop handling * node_id & net_id adv packets, and if proxy connection exists, * it should be disconnected. @@ -739,6 +778,8 @@ static struct bt_mesh_subnet *bt_mesh_is_net_id_exist(const uint8_t net_id[8]) size = bt_mesh_rx_netkey_size(); + BT_DBG("IsNetIDExist, Size %u", size); + for (i = 0U; i < size; i++) { sub = bt_mesh_rx_netkey_get(i); if (sub && !memcmp(sub->keys[sub->kr_flag].net_id, net_id, 8)) { @@ -753,8 +794,11 @@ void bt_mesh_proxy_client_gatt_adv_recv(struct net_buf_simple *buf, const bt_mesh_addr_t *addr, int8_t rssi) { bt_mesh_proxy_adv_ctx_t ctx = {0}; + struct bt_mesh_subnet *sub = NULL; uint8_t type = 0U; + BT_DBG("ProxyClientGattAdvRecv, Rssi %d", rssi); + /* Check if connection reaches the maximum limitation */ if (bt_mesh_gattc_get_free_conn_count() == 0) { BT_INFO("BLE connections for mesh reach max limit"); @@ -763,14 +807,15 @@ void bt_mesh_proxy_client_gatt_adv_recv(struct net_buf_simple *buf, type = net_buf_simple_pull_u8(buf); + BT_DBG("Type %u", type); + switch (type) { - case BLE_MESH_PROXY_ADV_NET_ID: { + case BLE_MESH_PROXY_ADV_NET_ID: if (buf->len != sizeof(ctx.net_id.net_id)) { BT_WARN("Malformed Network ID"); return; } - struct bt_mesh_subnet *sub = NULL; sub = bt_mesh_is_net_id_exist(buf->data); if (!sub) { return; @@ -779,7 +824,6 @@ void bt_mesh_proxy_client_gatt_adv_recv(struct net_buf_simple *buf, memcpy(ctx.net_id.net_id, buf->data, buf->len); ctx.net_id.net_idx = sub->net_idx; break; - } case BLE_MESH_PROXY_ADV_NODE_ID: /* Gets node identity information. * hash = aes-ecb(identity key, 16 octets(padding + random + src)) mod 2^64, @@ -808,6 +852,8 @@ int bt_mesh_proxy_client_connect(const uint8_t addr[6], uint8_t addr_type, uint1 bt_mesh_addr_t remote_addr = {0}; int result = 0; + BT_DBG("ProxyClientConnect, NetIdx 0x%04x", net_idx); + if (!addr || addr_type > BLE_MESH_ADDR_RANDOM) { BT_ERR("%s, Invalid parameter", __func__); return -EINVAL; @@ -830,13 +876,13 @@ int bt_mesh_proxy_client_disconnect(uint8_t conn_handle) { struct bt_mesh_conn *conn = NULL; + BT_DBG("ProxyClientDisconnect, ConnHandle 0x%04x", conn_handle); + if (conn_handle >= BLE_MESH_MAX_CONN) { BT_ERR("%s, Invalid parameter", __func__); return -EINVAL; } - BT_DBG("conn_handle %d", conn_handle); - conn = servers[conn_handle].conn; if (!conn) { BT_ERR("Not connected, conn handle %d", conn_handle); @@ -861,6 +907,8 @@ uint16_t bt_mesh_proxy_client_get_conn_count(void) count++; } + BT_DBG("ProxyClientGetConnCount, Count %u", count); + return count; } @@ -870,6 +918,8 @@ bool bt_mesh_proxy_client_relay(struct net_buf_simple *buf, uint16_t dst) int err = 0; int i; + BT_DBG("ProxyClientRelay, Dst 0x%04x", dst); + for (i = 0; i < ARRAY_SIZE(servers); i++) { struct bt_mesh_proxy_server *server = &servers[i]; NET_BUF_SIMPLE_DEFINE(msg, 32); @@ -900,12 +950,15 @@ static int beacon_send(struct bt_mesh_conn *conn, struct bt_mesh_subnet *sub, bo { NET_BUF_SIMPLE_DEFINE(buf, 28); + BT_DBG("BeaconSend, ConnHandle 0x%04x Private %u", conn->handle, private); + net_buf_simple_reserve(&buf, 1); + #if CONFIG_BLE_MESH_PRB_SRV if (private) { bt_mesh_private_beacon_create(sub, &buf); } else -#endif +#endif /* CONFIG_BLE_MESH_PRB_SRV */ { bt_mesh_secure_beacon_create(sub, &buf); } @@ -919,6 +972,8 @@ bool bt_mesh_proxy_client_beacon_send(struct bt_mesh_subnet *sub, bool private) int err = 0; int i; + BT_DBG("ProxyClientBeaconSend, Private %u", private); + /* NULL means we send Secure Network Beacon or Mesh Private Beacon on all subnets */ if (!sub) { #if CONFIG_BLE_MESH_NODE @@ -975,6 +1030,8 @@ static int send_proxy_cfg(struct bt_mesh_conn *conn, uint16_t net_idx, struct bt uint16_t alloc_len = 0U; int err = 0; + BT_DBG("SendProxyCfg, ConnHandle 0x%04x NetIdx 0x%04x", conn->handle, net_idx); + tx.sub = bt_mesh_subnet_get(net_idx); if (!tx.sub) { BT_ERR("NetKey 0x%04x not found", net_idx); @@ -1038,6 +1095,7 @@ static int send_proxy_cfg(struct bt_mesh_conn *conn, uint16_t net_idx, struct bt */ buf = bt_mesh_alloc_buf(1 + BLE_MESH_NET_HDR_LEN + alloc_len + 8); if (!buf) { + BT_ERR("Out of memory"); return -ENOMEM; } @@ -1072,11 +1130,10 @@ static int send_proxy_cfg(struct bt_mesh_conn *conn, uint16_t net_idx, struct bt #endif /* CONFIG_BLE_MESH_DF_SRV */ } - BT_DBG("len %u bytes: %s", buf->len, bt_hex(buf->data, buf->len)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); err = bt_mesh_net_encode(&tx, buf, true); if (err) { - BT_ERR("Encoding proxy cfg message failed (err %d)", err); goto end; } @@ -1095,13 +1152,14 @@ int bt_mesh_proxy_client_cfg_send(uint8_t conn_handle, uint16_t net_idx, { struct bt_mesh_conn *conn = NULL; - if (conn_handle >= BLE_MESH_MAX_CONN || !pdu || pdu->opcode > BLE_MESH_PROXY_CFG_DIRECTED_PROXY_CONTROL) { + BT_DBG("ProxyClientCfgSend, ConnHandle 0x%04x NetIdx 0x%04x", conn_handle, net_idx); + + if (conn_handle >= BLE_MESH_MAX_CONN || !pdu || + pdu->opcode > BLE_MESH_PROXY_CFG_DIRECTED_PROXY_CONTROL) { BT_ERR("%s, Invalid parameter", __func__); return -EINVAL; } - BT_DBG("conn_handle %d, net_idx 0x%04x", conn_handle, net_idx); - conn = servers[conn_handle].conn; if (!conn) { BT_ERR("Not connected, conn handle %d", conn_handle); @@ -1113,7 +1171,7 @@ int bt_mesh_proxy_client_cfg_send(uint8_t conn_handle, uint16_t net_idx, */ if (servers[conn_handle].net_idx != net_idx) { BT_ERR("NetKeyIndex 0x%04x mismatch, expect 0x%04x", - net_idx, servers[conn_handle].net_idx); + net_idx, servers[conn_handle].net_idx); return -EIO; } @@ -1125,16 +1183,19 @@ int bt_mesh_proxy_client_init(void) { int i; + BT_DBG("ProxyClientInit"); + /* Initialize the server receive buffers */ for (i = 0; i < ARRAY_SIZE(servers); i++) { struct bt_mesh_proxy_server *server = &servers[i]; k_delayed_work_init(&server->sar_timer, proxy_sar_timeout); + server->buf.size = BLE_MESH_PROXY_BUF_SIZE; server->buf.__buf = server_buf_data + (i * BLE_MESH_PROXY_BUF_SIZE); #if CONFIG_BLE_MESH_GATT_PROXY_CLIENT server->net_idx = BLE_MESH_KEY_UNUSED; -#endif +#endif /* CONFIG_BLE_MESH_GATT_PROXY_CLIENT */ } bt_mesh_gattc_conn_cb_register(&conn_callbacks); @@ -1143,7 +1204,7 @@ int bt_mesh_proxy_client_init(void) bt_mesh_update_exceptional_list(BLE_MESH_EXCEP_LIST_SUB_CODE_ADD, BLE_MESH_EXCEP_LIST_TYPE_MESH_PROXY_ADV, NULL); -#endif +#endif /* CONFIG_BLE_MESH_USE_DUPLICATE_SCAN && CONFIG_BLE_MESH_GATT_PROXY_CLIENT */ return 0; } @@ -1153,6 +1214,8 @@ int bt_mesh_proxy_client_deinit(void) { int i; + BT_DBG("ProxyClientDeinit"); + /* Initialize the server receive buffers */ for (i = 0; i < ARRAY_SIZE(servers); i++) { struct bt_mesh_proxy_server *server = &servers[i]; diff --git a/components/bt/esp_ble_mesh/core/proxy_server.c b/components/bt/esp_ble_mesh/core/proxy_server.c index c6cc15cab6e..6a498f75086 100644 --- a/components/bt/esp_ble_mesh/core/proxy_server.c +++ b/components/bt/esp_ble_mesh/core/proxy_server.c @@ -24,7 +24,7 @@ #if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" -#endif +#endif /* CONFIG_BLE_MESH_V11_SUPPORT */ #if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ CONFIG_BLE_MESH_GATT_PROXY_SERVER @@ -37,7 +37,7 @@ _Static_assert(!(IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) && IS_ENABLED(CON #if CONFIG_BLE_MESH_USE_BLE_50 static uint8_t proxy_adv_inst = BLE_MESH_ADV_INS_UNUSED; -#endif +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ #define ADV_OPT (BLE_MESH_ADV_OPT_CONNECTABLE | BLE_MESH_ADV_OPT_ONE_TIME) @@ -58,7 +58,7 @@ static const struct bt_mesh_adv_param slow_adv_param = { .interval_max = BLE_MESH_GAP_ADV_SLOW_INT_MAX, .channel_map = BLE_MESH_ADV_CHAN_DEFAULT, #if CONFIG_BLE_MESH_USE_BLE_50 - .primary_phy = BLE_MESH_ADV_PHY_1M, + .primary_phy = BLE_MESH_ADV_PHY_1M, .secondary_phy = BLE_MESH_ADV_PHY_1M, .adv_duration = 0, .adv_count = 0, @@ -73,7 +73,7 @@ static const struct bt_mesh_adv_param fast_adv_param = { .interval_max = BLE_MESH_GAP_ADV_FAST_INT_MAX_0, .channel_map = BLE_MESH_ADV_CHAN_DEFAULT, #if CONFIG_BLE_MESH_USE_BLE_50 - .primary_phy = BLE_MESH_ADV_PHY_1M, + .primary_phy = BLE_MESH_ADV_PHY_1M, .secondary_phy = BLE_MESH_ADV_PHY_1M, .adv_duration = 0, .adv_count = 0, @@ -87,19 +87,19 @@ static bool proxy_adv_enabled; #if CONFIG_BLE_MESH_GATT_PROXY_SERVER static void proxy_send_beacons(struct k_work *work); static uint16_t proxy_ccc_val; -#endif +#endif /* CONFIG_BLE_MESH_GATT_PROXY_SERVER */ #if CONFIG_BLE_MESH_PB_GATT static uint16_t prov_ccc_val; static bool prov_fast_adv; static uint32_t prov_start_time; -#endif +#endif /* CONFIG_BLE_MESH_PB_GATT */ static struct bt_mesh_proxy_client clients[BLE_MESH_MAX_CONN] = { [0 ... (BLE_MESH_MAX_CONN - 1)] = { #if CONFIG_BLE_MESH_PROXY_PRIVACY .proxy_privacy = BLE_MESH_PROXY_PRIVACY_DISABLED, -#endif +#endif /* CONFIG_BLE_MESH_PROXY_PRIVACY */ }, }; @@ -116,6 +116,8 @@ static char device_name[DEVICE_NAME_SIZE + 1]; struct bt_mesh_proxy_client *bt_mesh_proxy_server_get_client(uint8_t index) { + BT_DBG("ProxyServerGetClient, Index %u", index); + return &clients[0]; } @@ -126,11 +128,15 @@ uint8_t bt_mesh_proxy_server_get_client_count(void) int bt_mesh_set_device_name(const char *name) { + BT_DBG("SetDeviceName"); + if (!name) { BT_ERR("%s, Invalid parameter", __func__); return -EINVAL; } + BT_DBG("Name %s", name); + if (strlen(name) > DEVICE_NAME_SIZE) { BT_ERR("Too long device name (len %d)", strlen(name)); return -EINVAL; @@ -144,6 +150,8 @@ int bt_mesh_set_device_name(const char *name) const char *bt_mesh_get_device_name(void) { + BT_DBG("GetDeviceName %s", device_name); + return device_name; } @@ -151,6 +159,8 @@ static struct bt_mesh_proxy_client *find_client(struct bt_mesh_conn *conn) { int i; + BT_DBG("FindClient, ConnHandle 0x%04x", conn->handle); + for (i = 0; i < ARRAY_SIZE(clients); i++) { if (clients[i].conn == conn) { return &clients[i]; @@ -164,7 +174,7 @@ static void proxy_sar_timeout(struct k_work *work) { struct bt_mesh_proxy_client *client = NULL; - BT_WARN("Proxy SAR timeout"); + BT_WARN("ProxySARTimeout"); client = CONTAINER_OF(work, struct bt_mesh_proxy_client, sar_timer.work); if (!client || !client->conn) { @@ -178,12 +188,13 @@ static void proxy_sar_timeout(struct k_work *work) void bt_mesh_proxy_server_adv_flag_set(bool enable) { + BT_DBG("ProxyServerAdvFlagSet, Enable %u/%u", proxy_adv_enabled, enable); + proxy_adv_enabled = enable; } #if CONFIG_BLE_MESH_GATT_PROXY_SERVER -/** - * The following callbacks are used to notify proper information +/* The following callbacks are used to notify proper information * to the application layer. */ static proxy_server_connect_cb_t proxy_server_connect_cb; @@ -204,6 +215,8 @@ static int next_idx; bool bt_mesh_proxy_server_find_client_by_addr(uint16_t addr) { + BT_DBG("ProxyServerFindClient, Addr 0x%04x", addr); + for (size_t i = 0; i < ARRAY_SIZE(clients); i++) { if (clients[i].conn) { for (size_t j = 0; j < ARRAY_SIZE(clients[i].filter); j++) { @@ -231,6 +244,8 @@ uint8_t bt_mesh_proxy_server_get_all_client_type(void) } } + BT_DBG("ProxyServerGetAllClientType, type 0x%02x", client_type); + return client_type; } @@ -239,13 +254,16 @@ static int filter_set(struct bt_mesh_proxy_client *client, { uint8_t type = 0U; + BT_INFO("FilterSet"); + if (buf->len < 1) { BT_WARN("Too short Filter Set message"); return -EINVAL; } type = net_buf_simple_pull_u8(buf); - BT_INFO("Set filter type 0x%02x", type); + + BT_INFO("Type 0x%02x", type); switch (type) { case 0x00: @@ -276,7 +294,7 @@ static void filter_add(struct bt_mesh_proxy_client *client, * is the element address of Proxy Client. */ - BT_DBG("addr 0x%04x", addr); + BT_DBG("FilterAdd, Addr 0x%04x ProxyClient %u", addr, proxy_client); if (addr == BLE_MESH_ADDR_UNASSIGNED) { return; @@ -306,14 +324,14 @@ static void filter_add(struct bt_mesh_proxy_client *client, } } - BT_WARN("Proxy filter is full!"); + BT_WARN("ProxyFilterFull"); } static void filter_remove(struct bt_mesh_proxy_client *client, uint16_t addr) { int i; - BT_DBG("addr 0x%04x", addr); + BT_DBG("FilterRemove, Addr 0x%04x", addr); if (addr == BLE_MESH_ADDR_UNASSIGNED) { return; @@ -341,6 +359,8 @@ static void send_filter_status(struct bt_mesh_proxy_client *client, uint16_t filter_size = 0U; int i, err = 0; + BT_DBG("SetFilterStatus"); + /* Configuration messages always have dst unassigned */ tx.ctx->addr = BLE_MESH_ADDR_UNASSIGNED; tx.ctx->send_cred = BLE_MESH_FLOODING_CRED, @@ -364,11 +384,10 @@ static void send_filter_status(struct bt_mesh_proxy_client *client, net_buf_simple_add_be16(buf, filter_size); - BT_DBG("%u bytes: %s", buf->len, bt_hex(buf->data, buf->len)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); err = bt_mesh_net_encode(&tx, buf, true); if (err) { - BT_ERR("Encoding proxy filter status failed (err %d)", err); return; } @@ -385,13 +404,14 @@ static void proxy_cfg(struct bt_mesh_proxy_client *client) uint8_t opcode = 0U; int err = 0; + BT_DBG("ProxyCfg"); + if (client->buf.len > 29) { BT_ERR("Too large proxy cfg pdu (len %d)", client->buf.len); return; } - err = bt_mesh_net_decode(&client->buf, BLE_MESH_NET_IF_PROXY_CFG, - &rx, &buf); + err = bt_mesh_net_decode(&client->buf, BLE_MESH_NET_IF_PROXY_CFG, &rx, &buf); if (err) { BT_ERR("Failed to decode Proxy Configuration (err %d)", err); return; @@ -400,7 +420,7 @@ static void proxy_cfg(struct bt_mesh_proxy_client *client) rx.local_match = 1U; if (bt_mesh_rpl_check(&rx, NULL)) { - BT_WARN("Replay: src 0x%04x dst 0x%04x seq 0x%06x", + BT_WARN("Replay, Src 0x%04x Dst 0x%04x Seq 0x%06x", rx.ctx.addr, rx.ctx.recv_dst, rx.seq); return; } @@ -408,7 +428,7 @@ static void proxy_cfg(struct bt_mesh_proxy_client *client) /* Remove network headers */ net_buf_simple_pull(&buf, BLE_MESH_NET_HDR_LEN); - BT_DBG("%u bytes: %s", buf.len, bt_hex(buf.data, buf.len)); + BT_DBG("Len %u: %s", buf.len, bt_hex(buf.data, buf.len)); if (buf.len < 1) { BT_WARN("Too short proxy configuration PDU"); @@ -464,6 +484,8 @@ static int beacon_send(struct bt_mesh_proxy_client *client, struct bt_mesh_subne { NET_BUF_SIMPLE_DEFINE(buf, 28); + BT_DBG("BeaconSend"); + net_buf_simple_reserve(&buf, 1); #if CONFIG_BLE_MESH_PROXY_PRIVACY @@ -475,7 +497,7 @@ static int beacon_send(struct bt_mesh_proxy_client *client, struct bt_mesh_subne bt_mesh_private_beacon_create(sub, &buf); } else -#endif +#endif /* CONFIG_BLE_MESH_PROXY_PRIVACY */ { bt_mesh_secure_beacon_create(sub, &buf); } @@ -485,10 +507,12 @@ static int beacon_send(struct bt_mesh_proxy_client *client, struct bt_mesh_subne static void proxy_send_beacons(struct k_work *work) { - struct bt_mesh_proxy_client *client = NULL; + struct bt_mesh_proxy_client *client = CONTAINER_OF(work, + struct bt_mesh_proxy_client, + send_beacons);; int i; - client = CONTAINER_OF(work, struct bt_mesh_proxy_client, send_beacons); + BT_DBG("ProxySendBeacons"); /* Upon connection, the Proxy Server shall evaluate Proxy Privacy parameter * for the connection and the Proxy Server shall retain the value of the @@ -523,7 +547,7 @@ static void proxy_send_beacons(struct k_work *work) } else if (sub->proxy_privacy == BLE_MESH_PROXY_PRIVACY_ENABLED) { #if CONFIG_BLE_MESH_PRB_SRV /* TODO: Send Mesh Private Beacon */ -#endif +#endif /* CONFIG_BLE_MESH_PRB_SRV */ } } #endif @@ -534,6 +558,8 @@ void bt_mesh_proxy_server_beacon_send(struct bt_mesh_subnet *sub) { int i; + BT_DBG("ProxyServerBeaconSend, Sub %p", sub); + if (!sub) { /* NULL means we send on all subnets */ for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) { @@ -559,10 +585,14 @@ void bt_mesh_proxy_server_identity_start(struct bt_mesh_subnet *sub) /* Prioritize the recently enabled subnet */ next_idx = sub - bt_mesh.sub; + + BT_DBG("ProxyServerIdentityStart, NextIdx %d", next_idx); } void bt_mesh_proxy_server_identity_stop(struct bt_mesh_subnet *sub) { + BT_DBG("ProxyServerIdentityStop"); + sub->node_id = BLE_MESH_NODE_IDENTITY_STOPPED; sub->node_id_start = 0U; } @@ -571,7 +601,10 @@ int bt_mesh_proxy_identity_enable(void) { int i, count = 0; + BT_DBG("ProxyIdentityEnable"); + if (!bt_mesh_is_provisioned()) { + BT_DBG("NotProvisioned"); return -EAGAIN; } @@ -587,9 +620,12 @@ int bt_mesh_proxy_identity_enable(void) } bt_mesh_proxy_server_identity_start(sub); + count++; } + BT_DBG("SubCount %u", count); + if (count) { bt_mesh_adv_update(); } @@ -605,16 +641,22 @@ void bt_mesh_proxy_server_private_identity_start(struct bt_mesh_subnet *sub) /* Prioritize the recently enabled subnet */ next_idx = sub - bt_mesh.sub; + + BT_DBG("ProxyServerPrivateIdentityStart, NextIdx %d", next_idx); } void bt_mesh_proxy_server_private_identity_stop(struct bt_mesh_subnet *sub) { + BT_DBG("ProxyServerPrivateIdentityStop"); + sub->private_node_id = BLE_MESH_PRIVATE_NODE_IDENTITY_STOPPED; sub->node_id_start = 0U; } bool bt_mesh_proxy_server_is_node_id_enable(void) { + BT_DBG("ProxyServerIsNodeIDEnable"); + for (size_t i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) { /* If the Node Identity state of the node for any subnet * is 0x01 (i.e. running), return true. @@ -634,22 +676,27 @@ static bool is_exist_private_node_id_enable(void) { for (size_t i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) { /* If the value of the Node Identity state of the node - * for any subnet is 0x01,If exist return true. + * for any subnet is 0x01, if exist return true. */ struct bt_mesh_subnet *sub = &bt_mesh.sub[i]; if (sub->net_idx != BLE_MESH_KEY_UNUSED && sub->private_node_id == BLE_MESH_PRIVATE_NODE_IDENTITY_RUNNING) { + BT_DBG("PrivateNodeIDExist, NetIdx 0x%04x", sub->net_idx); return true; } } + BT_DBG("PrivateNodeIDNotExist"); return false; } int bt_mesh_proxy_private_identity_disable(void) { + BT_DBG("ProxyPrivateIdentityDisable"); + if (!bt_mesh_is_provisioned()) { + BT_DBG("NotProvisioned"); return -EAGAIN; } @@ -675,7 +722,10 @@ int bt_mesh_proxy_private_identity_enable(void) { int count = 0; + BT_DBG("ProxyPrivateIdentityEnable"); + if (!bt_mesh_is_provisioned()) { + BT_DBG("NotProvisioned"); return -EAGAIN; } @@ -691,9 +741,12 @@ int bt_mesh_proxy_private_identity_enable(void) } bt_mesh_proxy_server_private_identity_start(sub); + count++; } + BT_DBG("SubCount %u", count); + if (count) { bt_mesh_adv_update(); } @@ -701,10 +754,12 @@ int bt_mesh_proxy_private_identity_enable(void) return 0; } #endif /* CONFIG_BLE_MESH_PRB_SRV */ -#endif /* GATT_PROXY */ +#endif /* CONFIG_BLE_MESH_GATT_PROXY_SERVER */ static void proxy_complete_pdu(struct bt_mesh_proxy_client *client) { + BT_DBG("ProxyCompletePDU"); + switch (client->msg_type) { #if CONFIG_BLE_MESH_GATT_PROXY_SERVER case BLE_MESH_PROXY_NET_PDU: @@ -719,13 +774,13 @@ static void proxy_complete_pdu(struct bt_mesh_proxy_client *client) BT_DBG("Mesh Configuration PDU"); proxy_cfg(client); break; -#endif +#endif /* CONFIG_BLE_MESH_GATT_PROXY_SERVER */ #if CONFIG_BLE_MESH_PB_GATT case BLE_MESH_PROXY_PROV: BT_DBG("Mesh Provisioning PDU"); bt_mesh_pb_gatt_recv(client->conn, &client->buf); break; -#endif +#endif /* CONFIG_BLE_MESH_PB_GATT */ default: BT_WARN("Unhandled Message Type 0x%02x", client->msg_type); break; @@ -736,27 +791,35 @@ static void proxy_complete_pdu(struct bt_mesh_proxy_client *client) #if CONFIG_BLE_MESH_GATT_PROXY_SERVER if (client->msg_type < BLE_MESH_PROXY_PROV && client->proxy_msg_recv == false) { - client->proxy_msg_recv = true; - /** - * @Spec: P626 - * When a new connection is established between a Proxy Client and the Directed Proxy Server, and the - * first message received from the Proxy Client is a successfully processed DIRECTED_PROXY_CONTROL - * message, then the Directed Proxy Server shall set the Proxy_Client_Type parameter to Directed Proxy Client, - * shall set the Use_Directed parameter to Disable for all subnets known to the Directed Proxy Server - * except the subnet identified by the received message; - * otherwise, the Directed Proxy Server shall set the Proxy_Client_Type parameter to Proxy Client. + /* @Spec: P626 + * When a new connection is established between a Proxy Client and + * the Directed Proxy Server, and the first message received from + * the Proxy Client is a successfully processed DIRECTED_PROXY_CONTROL + * message, then the Directed Proxy Server shall set the Proxy_Client_Type + * parameter to Directed Proxy Client, shall set the Use_Directed + * parameter to Disable for all subnets known to the Directed Proxy + * Server except the subnet identified by the received message; + * otherwise, the Directed Proxy Server shall set the Proxy_Client_Type + * parameter to Proxy Client. * - * If the first message received is DIRECTED_PROXY_CONTROL, proxy_client_type will be set to Directed Proxy Client, - * But if device didn't receive DIRECTED_PROXY_CONTROL message and all received is normal proxy message, That - * client type will be always in UNSET state, because we set client type in handle function of DIRECTED_PROXY_CONTROL. + * If the first message received is DIRECTED_PROXY_CONTROL, proxy_client_type + * will be set to Directed Proxy Client. + * But if device didn't receive DIRECTED_PROXY_CONTROL message and all + * received is normal proxy message, That client type will be always in + * UNSET state, because we set client type in handle function of + * DIRECTED_PROXY_CONTROL. * * So the flowing code was used to avoid that situation. - */ + */ + client->proxy_msg_recv = true; + + BT_DBG("ProxyClientTypeUpdate"); + if (client->proxy_client_type == BLE_MESH_PROXY_CLI_TYPE_UNSET) { client->proxy_client_type = BLE_MESH_PROXY_CLI_TYPE_PROXY_CLIENT; } } -#endif +#endif /* CONFIG_BLE_MESH_GATT_PROXY_SERVER */ } #define ATTR_IS_PROV(attr) (attr->user_data != NULL) @@ -768,6 +831,8 @@ static ssize_t proxy_recv(struct bt_mesh_conn *conn, struct bt_mesh_proxy_client *client = find_client(conn); const uint8_t *data = buf; + BT_DBG("ProxyRecv"); + if (!client) { BT_ERR("No Proxy Client found"); return -ENOTCONN; @@ -853,7 +918,7 @@ static void proxy_connected(struct bt_mesh_conn *conn, uint8_t err) struct bt_mesh_proxy_client *client = NULL; int i; - BT_DBG("conn %p err 0x%02x", conn, err); + BT_DBG("ProxyConnected, ConnHandle 0x%04x Err 0x%02x", conn->handle, err); if (gatt_svc == MESH_GATT_PROV && conn_count == 1) { BT_WARN("Only one prov connection could exists"); @@ -866,7 +931,7 @@ static void proxy_connected(struct bt_mesh_conn *conn, uint8_t err) /* Since we use ADV_OPT_ONE_TIME */ #if !CONFIG_BLE_MESH_USE_BLE_50 bt_mesh_proxy_server_adv_flag_set(false); -#endif +#endif /* !CONFIG_BLE_MESH_USE_BLE_50 */ #if CONFIG_BLE_MESH_PROXY_SOLIC_PDU_RX /* Before re-enabling advertising, stop advertising @@ -874,7 +939,9 @@ static void proxy_connected(struct bt_mesh_conn *conn, uint8_t err) * Network Identity type. */ bt_mesh_proxy_server_stop_solic_adv_priv_net_id(); -#endif +#endif /* CONFIG_BLE_MESH_PROXY_SOLIC_PDU_RX */ + + BT_DBG("ConnCount %u vs. %u", conn_count, BLE_MESH_MAX_CONN); /* Try to re-enable advertising in case it's possible */ if (conn_count < BLE_MESH_MAX_CONN) { @@ -895,13 +962,15 @@ static void proxy_connected(struct bt_mesh_conn *conn, uint8_t err) client->conn = bt_mesh_conn_ref(conn); client->filter_type = SRV_NONE; + #if CONFIG_BLE_MESH_GATT_PROXY_SERVER (void)memset(client->filter, 0, sizeof(client->filter)); if (proxy_server_connect_cb) { proxy_server_connect_cb(conn->handle); } -#endif +#endif /* CONFIG_BLE_MESH_GATT_PROXY_SERVER */ + net_buf_simple_reset(&client->buf); } @@ -909,7 +978,8 @@ static void proxy_disconnected(struct bt_mesh_conn *conn, uint8_t reason) { int i; - BT_DBG("conn %p reason 0x%02x", conn, reason); + BT_DBG("ProxyDisconnected, ConnHandle 0x%04x Count %u Reason 0x%02x", + conn->handle, conn_count, reason); conn_count--; @@ -921,7 +991,8 @@ static void proxy_disconnected(struct bt_mesh_conn *conn, uint8_t reason) if (proxy_server_disconnect_cb) { proxy_server_disconnect_cb(conn->handle, reason); } -#endif +#endif /* CONFIG_BLE_MESH_GATT_PROXY_SERVER */ + if (IS_ENABLED(CONFIG_BLE_MESH_PB_GATT) && client->filter_type == SRV_PROV) { bt_mesh_pb_gatt_close(conn, reason); @@ -929,11 +1000,11 @@ static void proxy_disconnected(struct bt_mesh_conn *conn, uint8_t reason) #if CONFIG_BLE_MESH_PROXY_PRIVACY client->proxy_privacy = BLE_MESH_PROXY_PRIVACY_DISABLED; -#endif +#endif /* CONFIG_BLE_MESH_PROXY_PRIVACY */ #if CONFIG_BLE_MESH_GATT_PROXY_SERVER && CONFIG_BLE_MESH_PRB_SRV k_delayed_work_cancel(&rand_upd_timer); -#endif +#endif /* CONFIG_BLE_MESH_GATT_PROXY_SERVER && CONFIG_BLE_MESH_PRB_SRV */ k_delayed_work_cancel(&client->sar_timer); bt_mesh_conn_unref(client->conn); @@ -953,13 +1024,15 @@ static void proxy_disconnected(struct bt_mesh_conn *conn, uint8_t reason) if (bt_mesh_directed_proxy_server_update_dep_node(NULL, &clients[i], 0)) { BT_ERR("Proxy disconnected, failed to update dependent node"); } -#endif /* CONFIG_BLE_MESH_DF_SRV */ +#endif /* CONFIG_BLE_MESH_GATT_PROXY_SERVER && CONFIG_BLE_MESH_DF_SRV */ } struct net_buf_simple *bt_mesh_proxy_server_get_buf(void) { struct net_buf_simple *buf = &clients[0].buf; + BT_DBG("ProxyServerGetBuf"); + net_buf_simple_reset(buf); return buf; @@ -974,9 +1047,11 @@ static ssize_t prov_ccc_write(struct bt_mesh_conn *conn, struct bt_mesh_proxy_client *client = NULL; uint16_t *value = attr->user_data; - BT_DBG("len %u: %s", len, bt_hex(buf, len)); + BT_DBG("ProvCCCWrite"); + BT_DBG("Len %u: %s", len, bt_hex(buf, len)); if (len != sizeof(*value)) { + BT_WARN("MismatchLen %u != %u", len, sizeof(*value)); return BLE_MESH_GATT_ERR(BLE_MESH_ATT_ERR_INVALID_ATTRIBUTE_LEN); } @@ -1007,6 +1082,8 @@ static ssize_t prov_ccc_read(struct bt_mesh_conn *conn, { uint16_t *value = attr->user_data; + BT_DBG("ProvCCCRead, Len %u", len); + return bt_mesh_gatts_attr_read(conn, attr, buf, len, offset, value, sizeof(*value)); } @@ -1036,6 +1113,8 @@ int bt_mesh_proxy_server_prov_enable(void) { int i; + BT_DBG("ProxyServerProvEnable"); + if (gatt_svc == MESH_GATT_PROV) { BT_WARN("%s, Already", __func__); return -EALREADY; @@ -1063,6 +1142,8 @@ int bt_mesh_proxy_server_prov_disable(bool disconnect) { int i; + BT_DBG("ProxyServerProvDisable, Disconnect %u", disconnect); + if (gatt_svc == MESH_GATT_NONE) { BT_WARN("%s, Already", __func__); return -EALREADY; @@ -1106,9 +1187,11 @@ static ssize_t proxy_ccc_write(struct bt_mesh_conn *conn, struct bt_mesh_proxy_client *client = NULL; uint16_t value = 0U; - BT_DBG("len %u: %s", len, bt_hex(buf, len)); + BT_DBG("ProxyCCCWrite"); + BT_DBG("Len %u: %s", len, bt_hex(buf, len)); if (len != sizeof(value)) { + BT_WARN("MismatchLen %u != %u", len, sizeof(value)); return BLE_MESH_GATT_ERR(BLE_MESH_ATT_ERR_INVALID_ATTRIBUTE_LEN); } @@ -1163,6 +1246,8 @@ static ssize_t proxy_ccc_read(struct bt_mesh_conn *conn, { uint16_t *value = attr->user_data; + BT_DBG("ProxyCCCRead, Len %u", len); + return bt_mesh_gatts_attr_read(conn, attr, buf, len, offset, value, sizeof(*value)); } @@ -1192,6 +1277,8 @@ int bt_mesh_proxy_server_gatt_enable(void) { int i; + BT_DBG("ProxyServerGattEnable"); + if (gatt_svc == MESH_GATT_PROXY) { BT_WARN("%s, Already", __func__); return -EALREADY; @@ -1218,6 +1305,8 @@ void bt_mesh_proxy_server_gatt_disconnect(void) { int i; + BT_DBG("ProxyServerGattDisconnect"); + for (i = 0; i < ARRAY_SIZE(clients); i++) { struct bt_mesh_proxy_client *client = &clients[i]; @@ -1231,6 +1320,8 @@ void bt_mesh_proxy_server_gatt_disconnect(void) int bt_mesh_proxy_server_gatt_disable(void) { + BT_DBG("ProxyServerGattDisable"); + if (gatt_svc == MESH_GATT_NONE) { BT_WARN("%s, Already", __func__); return -EALREADY; @@ -1255,7 +1346,7 @@ void bt_mesh_proxy_server_addr_add(struct net_buf_simple *buf, uint16_t addr) struct bt_mesh_proxy_client, buf); - BT_DBG("filter_type %u addr 0x%04x", client->filter_type, addr); + BT_DBG("ProxyServerAddrAdd, Type %u Addr 0x%04x", client->filter_type, addr); if (client->filter_type == SRV_WHITELIST) { filter_add(client, addr, true); @@ -1264,16 +1355,16 @@ void bt_mesh_proxy_server_addr_add(struct net_buf_simple *buf, uint16_t addr) } } -static bool client_filter_match(struct bt_mesh_proxy_client *client, - uint16_t addr) +static bool client_filter_match(struct bt_mesh_proxy_client *client, uint16_t addr) { int i; - BT_DBG("filter_type %u addr 0x%04x", client->filter_type, addr); + BT_DBG("ClientFilterMatch, Type %u Addr 0x%04x", client->filter_type, addr); if (client->filter_type == SRV_BLACKLIST) { for (i = 0; i < ARRAY_SIZE(client->filter); i++) { if (client->filter[i].addr == addr) { + BT_DBG("InBlackList"); return false; } } @@ -1282,12 +1373,14 @@ static bool client_filter_match(struct bt_mesh_proxy_client *client, } if (addr == BLE_MESH_ADDR_ALL_NODES) { + BT_DBG("AllNodes"); return true; } if (client->filter_type == SRV_WHITELIST) { for (i = 0; i < ARRAY_SIZE(client->filter); i++) { if (client->filter[i].addr == addr) { + BT_DBG("InWhiteList"); return true; } } @@ -1301,7 +1394,7 @@ bool bt_mesh_proxy_server_relay(struct net_buf_simple *buf, uint16_t dst) bool relayed = false; int i; - BT_DBG("%u bytes to dst 0x%04x", buf->len, dst); + BT_DBG("ProxyServerRelay, Len %u Dst 0x%04x", buf->len, dst); for (i = 0; i < ARRAY_SIZE(clients); i++) { struct bt_mesh_proxy_client *client = &clients[i]; @@ -1327,24 +1420,24 @@ bool bt_mesh_proxy_server_relay(struct net_buf_simple *buf, uint16_t dst) return relayed; } - #endif /* CONFIG_BLE_MESH_GATT_PROXY_SERVER */ static int proxy_send(struct bt_mesh_conn *conn, const void *data, uint16_t len) { - BT_DBG("%u bytes: %s", len, bt_hex(data, len)); + BT_DBG("ProxySend"); + BT_DBG("Len %u: %s", len, bt_hex(data, len)); #if CONFIG_BLE_MESH_GATT_PROXY_SERVER if (gatt_svc == MESH_GATT_PROXY) { return bt_mesh_gatts_notify(conn, &proxy_attrs[4], data, len); } -#endif +#endif /* CONFIG_BLE_MESH_GATT_PROXY_SERVER */ #if CONFIG_BLE_MESH_PB_GATT if (gatt_svc == MESH_GATT_PROV) { return bt_mesh_gatts_notify(conn, &prov_attrs[4], data, len); } -#endif +#endif /* CONFIG_BLE_MESH_PB_GATT */ return 0; } @@ -1354,11 +1447,15 @@ int bt_mesh_proxy_server_segment_send(struct bt_mesh_conn *conn, uint8_t type, { uint16_t mtu = 0U; - BT_DBG("conn %p type 0x%02x len %u: %s", conn, type, msg->len, - bt_hex(msg->data, msg->len)); + BT_DBG("ProxyServerSegSend"); + BT_DBG("ConnHandle 0x%04x Type %u", conn->handle, type); + BT_DBG("Len %u: %s", msg->len, bt_hex(msg->data, msg->len)); /* ATT_MTU - OpCode (1 byte) - Handle (2 bytes) */ mtu = bt_mesh_gatt_get_mtu(conn) - 3; + + BT_DBG("MTU %u", mtu); + if (mtu > msg->len) { net_buf_simple_push_u8(msg, BLE_MESH_PROXY_PDU_HDR(BLE_MESH_PROXY_SAR_COMP, type)); return proxy_send(conn, msg->data, msg->len); @@ -1388,6 +1485,8 @@ int bt_mesh_proxy_server_send(struct bt_mesh_conn *conn, uint8_t type, { struct bt_mesh_proxy_client *client = find_client(conn); + BT_DBG("ProxyServerSend, Type 0x%02x", type); + if (!client) { BT_ERR("No Proxy Client found"); return -ENOTCONN; @@ -1409,10 +1508,9 @@ static const struct bt_mesh_adv_data prov_ad[] = { BLE_MESH_ADV_DATA_BYTES(BLE_MESH_DATA_UUID16_ALL, 0x27, 0x18), BLE_MESH_ADV_DATA(BLE_MESH_DATA_SVC_DATA16, prov_svc_data, sizeof(prov_svc_data)), }; -#endif /* PB_GATT */ +#endif /* CONFIG_BLE_MESH_PB_GATT */ #if CONFIG_BLE_MESH_GATT_PROXY_SERVER - #define NET_ID_LEN 11 #define NODE_ID_LEN 19 #define PRIVATE_NET_ID_LEN 19 @@ -1460,6 +1558,9 @@ static size_t gatt_proxy_adv_create(struct bt_mesh_adv_data *proxy_sd) /* One octet for Length, and another octet for AD type */ size_t sd_space = 29; + BT_DBG("GattProxyAdvCreate"); + BT_DBG("Name %u: %s", name_len, name); + if (name_len > sd_space) { proxy_sd->type = BLE_MESH_DATA_NAME_SHORTENED; proxy_sd->data_len = sd_space; @@ -1480,6 +1581,8 @@ static int node_id_adv(struct bt_mesh_subnet *sub) uint8_t tmp[16] = {0}; int err = 0; + BT_DBG("NodeIDAdv, NetIdx 0x%04x", sub->net_idx); + proxy_svc_data[2] = BLE_MESH_PROXY_ADV_NODE_ID; err = bt_mesh_rand(proxy_svc_data + 11, 8); @@ -1502,10 +1605,10 @@ static int node_id_adv(struct bt_mesh_subnet *sub) #if CONFIG_BLE_MESH_USE_BLE_50 err = bt_le_ext_adv_start(proxy_adv_inst, &fast_adv_param, node_id_ad, ARRAY_SIZE(node_id_ad), &proxy_sd, proxy_sd_len); -#else +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ err = bt_le_adv_start(&fast_adv_param, node_id_ad, ARRAY_SIZE(node_id_ad), &proxy_sd, proxy_sd_len); -#endif +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ if (err) { BT_WARN("Failed to advertise using Node ID (err %d)", err); return err; @@ -1522,10 +1625,10 @@ static int net_id_adv(struct bt_mesh_subnet *sub) size_t proxy_sd_len = 0U; int err = 0; - proxy_svc_data[2] = BLE_MESH_PROXY_ADV_NET_ID; + BT_DBG("NetIDAdv, NetIdx 0x%04x", sub->net_idx); + BT_DBG("NetId %s", bt_hex(sub->keys[sub->kr_flag].net_id, 8)); - BT_DBG("Advertising with NetId %s", - bt_hex(sub->keys[sub->kr_flag].net_id, 8)); + proxy_svc_data[2] = BLE_MESH_PROXY_ADV_NET_ID; memcpy(proxy_svc_data + 3, sub->keys[sub->kr_flag].net_id, 8); proxy_sd_len = gatt_proxy_adv_create(&proxy_sd); @@ -1533,10 +1636,10 @@ static int net_id_adv(struct bt_mesh_subnet *sub) #if CONFIG_BLE_MESH_USE_BLE_50 err = bt_le_ext_adv_start(proxy_adv_inst, &slow_adv_param, net_id_ad, ARRAY_SIZE(net_id_ad), &proxy_sd, proxy_sd_len); -#else +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ err = bt_le_adv_start(&slow_adv_param, net_id_ad, ARRAY_SIZE(net_id_ad), &proxy_sd, proxy_sd_len); -#endif +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ if (err) { BT_WARN("Failed to advertise using Network ID (err %d)", err); return err; @@ -1550,11 +1653,15 @@ static int net_id_adv(struct bt_mesh_subnet *sub) #if CONFIG_BLE_MESH_PRB_SRV void bt_mesh_proxy_server_update_net_id_rand(void) { + BT_DBG("ProxyServerUpdateNetIDRand"); + k_delayed_work_submit(&rand_upd_timer, RAND_UPDATE_INTERVAL); } void bt_mesh_proxy_server_update_net_id_rand_stop(void) { + BT_DBG("ProxyServerUpdateNetIDRandStop"); + k_delayed_work_cancel(&rand_upd_timer); } @@ -1562,6 +1669,8 @@ static void random_update_timeout(struct k_work *work) { int err = 0; + BT_DBG("RandomUpdateTimeout"); + err = bt_mesh_rand(net_id_random, 8); if (err) { BT_ERR("Generate random value failed"); @@ -1578,6 +1687,8 @@ static int private_node_id_adv(struct bt_mesh_subnet *sub) uint8_t tmp[16] = {0}; int err = 0; + BT_DBG("PrivateNodeIDAdv, NetIdx 0x%04x", sub->net_idx); + proxy_svc_data[2] = BLE_MESH_PROXY_ADV_PRIVATE_NODE_ID; err = bt_mesh_rand(proxy_svc_data + 11, 8); @@ -1616,8 +1727,7 @@ static int private_node_id_adv(struct bt_mesh_subnet *sub) } #endif /* CONFIG_BLE_MESH_PRB_SRV */ -#if (CONFIG_BLE_MESH_PRB_SRV || \ - CONFIG_BLE_MESH_PROXY_SOLIC_PDU_RX) +#if (CONFIG_BLE_MESH_PRB_SRV || CONFIG_BLE_MESH_PROXY_SOLIC_PDU_RX) static int private_net_id_adv(struct bt_mesh_subnet *sub) { struct bt_mesh_adv_data proxy_sd = {0}; @@ -1625,6 +1735,8 @@ static int private_net_id_adv(struct bt_mesh_subnet *sub) uint8_t tmp[16] = {0}; int err = 0; + BT_DBG("PrivateNetIDAdv, NetIdx 0x%04x", sub->net_idx); + proxy_svc_data[2] = BLE_MESH_PROXY_ADV_PRIVATE_NET_ID; /* TODO: @@ -1663,11 +1775,12 @@ static int private_net_id_adv(struct bt_mesh_subnet *sub) return 0; } -#endif /* (CONFIG_BLE_MESH_PRB_SRV || \ - CONFIG_BLE_MESH_PROXY_SOLIC_PDU_RX) */ +#endif /* (CONFIG_BLE_MESH_PRB_SRV || CONFIG_BLE_MESH_PROXY_SOLIC_PDU_RX) */ static bool advertise_subnet(struct bt_mesh_subnet *sub) { + BT_DBG("AdvSubnet, NetIdx 0x%04x", sub->net_idx); + if (sub->net_idx == BLE_MESH_KEY_UNUSED) { return false; } @@ -1677,7 +1790,7 @@ static bool advertise_subnet(struct bt_mesh_subnet *sub) #if CONFIG_BLE_MESH_PRB_SRV || sub->private_node_id == BLE_MESH_PRIVATE_NODE_IDENTITY_RUNNING || bt_mesh_private_gatt_proxy_state_get() == BLE_MESH_PRIVATE_GATT_PROXY_ENABLED -#endif +#endif /* CONFIG_BLE_MESH_PRB_SRV */ ); } @@ -1686,10 +1799,13 @@ static struct bt_mesh_subnet *next_sub(void) struct bt_mesh_subnet *sub = NULL; int i; + BT_DBG("NextSub"); + for (i = next_idx; i < ARRAY_SIZE(bt_mesh.sub); i++) { sub = &bt_mesh.sub[i]; if (advertise_subnet(sub)) { next_idx = (i + 1) % ARRAY_SIZE(bt_mesh.sub); + BT_DBG("NextIdx %d", next_idx); return sub; } } @@ -1701,6 +1817,7 @@ static struct bt_mesh_subnet *next_sub(void) sub = &bt_mesh.sub[i]; if (advertise_subnet(sub)) { next_idx = (i + 1) % ARRAY_SIZE(bt_mesh.sub); + BT_DBG("NextIdx %d", next_idx); return sub; } } @@ -1720,6 +1837,8 @@ static int sub_count(void) } } + BT_DBG("SubCount %ld", count); + return count; } @@ -1729,6 +1848,8 @@ static int32_t gatt_proxy_advertise(struct bt_mesh_subnet *sub) int subnet_count = 0; uint32_t active = 0U; + BT_DBG("GattProxyAdvertise"); + if (conn_count == BLE_MESH_MAX_CONN) { BT_WARN("Connectable advertising deferred (max connections %d)", conn_count); return remaining; @@ -1739,6 +1860,8 @@ static int32_t gatt_proxy_advertise(struct bt_mesh_subnet *sub) return remaining; } + BT_DBG("NetIdx 0x%04x NodeID %u", sub->net_idx, sub->node_id); + if (sub->node_id == BLE_MESH_NODE_IDENTITY_RUNNING) { active = k_uptime_get_32() - sub->node_id_start; @@ -1751,6 +1874,7 @@ static int32_t gatt_proxy_advertise(struct bt_mesh_subnet *sub) BT_DBG("Node ID stopped"); } } + #if CONFIG_BLE_MESH_PRB_SRV else if (sub->private_node_id == BLE_MESH_PRIVATE_NODE_IDENTITY_RUNNING) { active = k_uptime_get_32() - sub->node_id_start; @@ -1769,7 +1893,7 @@ static int32_t gatt_proxy_advertise(struct bt_mesh_subnet *sub) if (sub->node_id == BLE_MESH_NODE_IDENTITY_STOPPED #if CONFIG_BLE_MESH_PRB_SRV && sub->private_node_id == BLE_MESH_PRIVATE_NODE_IDENTITY_STOPPED -#endif +#endif /* CONFIG_BLE_MESH_PRB_SRV */ ) { /* advertising node identity forever */ if (bt_mesh_gatt_proxy_get() == BLE_MESH_GATT_PROXY_ENABLED) { @@ -1779,11 +1903,10 @@ static int32_t gatt_proxy_advertise(struct bt_mesh_subnet *sub) else if (bt_mesh_private_gatt_proxy_state_get() == BLE_MESH_PRIVATE_GATT_PROXY_ENABLED) { private_net_id_adv(sub); } -#endif +#endif /* CONFIG_BLE_MESH_PRB_SRV */ } subnet_count = sub_count(); - BT_DBG("sub_count %u", subnet_count); if (subnet_count > 1) { int32_t max_timeout = 0; @@ -1796,16 +1919,18 @@ static int32_t gatt_proxy_advertise(struct bt_mesh_subnet *sub) max_timeout = NODE_ID_TIMEOUT / MAX(subnet_count, 6); max_timeout = MAX(max_timeout, K_SECONDS(1)); + BT_DBG("Remaining %d MaxTimeout %d", remaining, max_timeout); + if (remaining > max_timeout || remaining < 0) { remaining = max_timeout; } } - BT_DBG("Advertising %d ms for net_idx 0x%04x", remaining, sub->net_idx); + BT_DBG("Remaining %d NetIdx 0x%04x", remaining, sub->net_idx); return remaining; } -#endif /* GATT_PROXY */ +#endif /* CONFIG_BLE_MESH_GATT_PROXY_SERVER */ #if CONFIG_BLE_MESH_PB_GATT static size_t gatt_prov_adv_create(struct bt_mesh_adv_data prov_sd[2]) @@ -1815,6 +1940,8 @@ static size_t gatt_prov_adv_create(struct bt_mesh_adv_data prov_sd[2]) size_t prov_sd_len = 0U; size_t sd_space = 31U; + BT_DBG("GattProvAdvCreate"); + if (bt_mesh_prov_get() == NULL) { BT_ERR("No provisioning context provided"); return 0; @@ -1865,41 +1992,51 @@ static int32_t solic_adv_private_net_id(void) struct bt_mesh_subnet *sub = NULL; int32_t remaining = 0; + BT_DBG("SolicAdvPrivateNetID"); + remaining = bt_mesh_proxy_server_get_solic_adv_remaining(); if (remaining == 0) { + BT_DBG("RemainingZero"); return 0; } net_idx = bt_mesh_proxy_server_get_solic_adv_net_idx(); if (net_idx == BLE_MESH_KEY_UNUSED) { + BT_DBG("UnusedNetIdx"); return 0; } sub = bt_mesh_subnet_get(net_idx); if (sub == NULL) { + BT_DBG("NoSub"); return 0; } private_net_id_adv(sub); + return remaining; } #endif /* CONFIG_BLE_MESH_PROXY_SOLIC_PDU_RX */ int32_t bt_mesh_proxy_server_adv_start(void) { - BT_DBG("proxy server start"); + BT_DBG("ProxyServerAdvStart"); if (gatt_svc == MESH_GATT_NONE) { + BT_DBG("GattSvcNone"); return K_FOREVER; } #if CONFIG_BLE_MESH_USE_BLE_50 if (proxy_adv_inst == BLE_MESH_ADV_INS_UNUSED) { + BT_DBG("ProxyAdvInstUnused"); return K_FOREVER; } -#endif +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ #if CONFIG_BLE_MESH_PB_GATT + BT_DBG("ProvFastAdv %u", prov_fast_adv); + if (prov_fast_adv) { prov_start_time = k_uptime_get_32(); } @@ -1909,6 +2046,8 @@ int32_t bt_mesh_proxy_server_adv_start(void) struct bt_mesh_adv_data prov_sd[2]; size_t prov_sd_len; + BT_DBG("NotProvisioned"); + if (k_uptime_get_32() - prov_start_time < K_SECONDS(60)) { param = &fast_adv_param; } else { @@ -1924,7 +2063,6 @@ int32_t bt_mesh_proxy_server_adv_start(void) if (bt_le_adv_start(param, prov_ad, ARRAY_SIZE(prov_ad), prov_sd, prov_sd_len) == 0) { #endif /* CONFIG_BLE_MESH_USE_BLE_50 */ - bt_mesh_proxy_server_adv_flag_set(true); /* Advertise 60 seconds using fast interval */ @@ -1934,7 +2072,7 @@ int32_t bt_mesh_proxy_server_adv_start(void) } } } -#endif /* PB_GATT */ +#endif /* CONFIG_BLE_MESH_PB_GATT */ #if CONFIG_BLE_MESH_GATT_PROXY_SERVER if (bt_mesh_is_provisioned()) { @@ -1963,6 +2101,8 @@ int bt_mesh_proxy_server_adv_stop(void) { int err = 0; + BT_DBG("ProxyServerAdvStop, Enabled %u", proxy_adv_enabled); + if (!proxy_adv_enabled) { return -EALREADY; } @@ -1974,15 +2114,16 @@ int bt_mesh_proxy_server_adv_stop(void) } err = bt_le_ext_adv_stop(proxy_adv_inst); -#else +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ err = bt_le_adv_stop(); -#endif +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ if (err) { BT_ERR("Failed to stop advertising (err %d)", err); return -EINVAL; } bt_mesh_proxy_server_adv_flag_set(false); + return 0; } @@ -1995,21 +2136,23 @@ int bt_mesh_proxy_server_init(void) { int i; + BT_DBG("ProxyServerInit"); + #if CONFIG_BLE_MESH_USE_BLE_50 #if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV proxy_adv_inst = CONFIG_BLE_MESH_PROXY_ADV_INST_ID; #else /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ proxy_adv_inst = CONFIG_BLE_MESH_ADV_INST_ID; -#endif -#endif +#endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ #if CONFIG_BLE_MESH_GATT_PROXY_SERVER bt_mesh_gatts_service_register(&proxy_svc); -#endif +#endif /* CONFIG_BLE_MESH_GATT_PROXY_SERVER */ #if CONFIG_BLE_MESH_PB_GATT bt_mesh_gatts_service_register(&prov_svc); -#endif +#endif /* CONFIG_BLE_MESH_PB_GATT */ /* Initialize the client receive buffers */ for (i = 0; i < ARRAY_SIZE(clients); i++) { @@ -2017,9 +2160,10 @@ int bt_mesh_proxy_server_init(void) client->buf.size = BLE_MESH_PROXY_BUF_SIZE; client->buf.__buf = client_buf_data + (i * BLE_MESH_PROXY_BUF_SIZE); -#if defined(CONFIG_BLE_MESH_GATT_PROXY_SERVER) + +#if CONFIG_BLE_MESH_GATT_PROXY_SERVER k_delayed_work_init(&client->send_beacons, proxy_send_beacons); -#endif +#endif /* CONFIG_BLE_MESH_GATT_PROXY_SERVER */ k_delayed_work_init(&client->sar_timer, proxy_sar_timeout); } @@ -2028,11 +2172,12 @@ int bt_mesh_proxy_server_init(void) BT_ERR("Failed to create a random update timer"); return -EIO; } -#endif +#endif /* CONFIG_BLE_MESH_GATT_PROXY_SERVER && CONFIG_BLE_MESH_PRB_SRV */ bt_mesh_gatts_conn_cb_register(&conn_callbacks); strncpy(device_name, "ESP-BLE-MESH", DEVICE_NAME_SIZE); + return bt_mesh_gatts_set_local_device_name(device_name); } @@ -2041,9 +2186,11 @@ int bt_mesh_proxy_server_deinit(void) { int i; + BT_DBG("ProxyServerDeinit"); + #if CONFIG_BLE_MESH_USE_BLE_50 proxy_adv_inst = BLE_MESH_ADV_INS_UNUSED; -#endif +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ bt_mesh_proxy_server_adv_flag_set(false); gatt_svc = MESH_GATT_NONE; @@ -2051,24 +2198,26 @@ int bt_mesh_proxy_server_deinit(void) #if CONFIG_BLE_MESH_GATT_PROXY_SERVER bt_mesh_gatts_service_deregister(&proxy_svc); next_idx = 0; -#endif +#endif /* CONFIG_BLE_MESH_GATT_PROXY_SERVER */ #if CONFIG_BLE_MESH_PB_GATT bt_mesh_gatts_service_deregister(&prov_svc); -#endif +#endif /* CONFIG_BLE_MESH_PB_GATT */ for (i = 0; i < ARRAY_SIZE(clients); i++) { struct bt_mesh_proxy_client *client = &clients[i]; -#if defined(CONFIG_BLE_MESH_GATT_PROXY_SERVER) + +#if CONFIG_BLE_MESH_GATT_PROXY_SERVER k_delayed_work_free(&client->send_beacons); -#endif +#endif /* CONFIG_BLE_MESH_GATT_PROXY_SERVER */ k_delayed_work_free(&client->sar_timer); + memset(client, 0, sizeof(struct bt_mesh_proxy_client)); } #if CONFIG_BLE_MESH_GATT_PROXY_SERVER && CONFIG_BLE_MESH_PRB_SRV k_delayed_work_free(&rand_upd_timer); -#endif +#endif /* CONFIG_BLE_MESH_GATT_PROXY_SERVER && CONFIG_BLE_MESH_PRB_SRV */ memset(client_buf_data, 0, sizeof(client_buf_data)); memset(device_name, 0, sizeof(device_name)); diff --git a/components/bt/esp_ble_mesh/core/proxy_server.h b/components/bt/esp_ble_mesh/core/proxy_server.h index fc4041f8774..d16d0d390f0 100644 --- a/components/bt/esp_ble_mesh/core/proxy_server.h +++ b/components/bt/esp_ble_mesh/core/proxy_server.h @@ -58,7 +58,7 @@ struct bt_mesh_proxy_client { #if CONFIG_BLE_MESH_PROXY_PRIVACY uint8_t proxy_privacy; -#endif +#endif /* CONFIG_BLE_MESH_PROXY_PRIVACY */ #endif /* CONFIG_BLE_MESH_GATT_PROXY_SERVER */ struct k_delayed_work sar_timer; diff --git a/components/bt/esp_ble_mesh/core/rpl.c b/components/bt/esp_ble_mesh/core/rpl.c index 4e3e4c91cbc..43f4a4afdaa 100644 --- a/components/bt/esp_ble_mesh/core/rpl.c +++ b/components/bt/esp_ble_mesh/core/rpl.c @@ -17,6 +17,9 @@ void bt_mesh_update_rpl(struct bt_mesh_rpl *rpl, struct bt_mesh_net_rx *rx) { + BT_DBG("UpdateRPL, Src 0x%04x Seq 0x%06x OldIV %u", + rx->ctx.addr, rx->seq, rx->old_iv); + rpl->src = rx->ctx.addr; rpl->seq = rx->seq; rpl->old_iv = rx->old_iv; @@ -33,9 +36,16 @@ void bt_mesh_update_rpl(struct bt_mesh_rpl *rpl, struct bt_mesh_net_rx *rx) */ static bool rpl_check_and_store(struct bt_mesh_net_rx *rx, struct bt_mesh_rpl **match) { + BT_DBG("%s, Src 0x%04x Seq %lu OldIV %u", + match ? "RPLOnlyCheck" : "RPLCheckAndStore", + rx->ctx.addr, rx->seq, rx->old_iv); + for (size_t i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) { struct bt_mesh_rpl *rpl = &bt_mesh.rpl[i]; + BT_DBG("RPL%u, Src 0x%04x Seq %lu OldIV %u", + i, rpl->src, rpl->seq, rpl->old_iv); + /* Empty slot */ if (rpl->src == BLE_MESH_ADDR_UNASSIGNED) { if (match) { @@ -50,6 +60,7 @@ static bool rpl_check_and_store(struct bt_mesh_net_rx *rx, struct bt_mesh_rpl ** /* Existing slot for given address */ if (rpl->src == rx->ctx.addr) { if (rx->old_iv && !rpl->old_iv) { + BT_DBG("DueToOldIV"); return true; } @@ -66,25 +77,30 @@ static bool rpl_check_and_store(struct bt_mesh_net_rx *rx, struct bt_mesh_rpl ** #if CONFIG_BLE_MESH_NOT_RELAY_REPLAY_MSG rx->replay_msg = 1; -#endif +#endif /* CONFIG_BLE_MESH_NOT_RELAY_REPLAY_MSG */ + BT_DBG("DueToSeq"); return true; } } - BT_ERR("RPL is full!"); + BT_ERR("RPLFull"); return true; } bool bt_mesh_rpl_check(struct bt_mesh_net_rx *rx, struct bt_mesh_rpl **match) { + BT_DBG("RPLCheck"); + /* Don't bother checking messages from ourselves */ if (rx->net_if == BLE_MESH_NET_IF_LOCAL) { + BT_DBG("LocalNetIf"); return false; } /* The RPL is used only for the local node */ if (!rx->local_match) { + BT_DBG("LocalNotMatch"); return false; } @@ -96,9 +112,14 @@ void bt_mesh_rpl_update(void) /* Discard "old old" IV Index entries from RPL and flag * any other ones (which are valid) as old. */ + BT_DBG("RPLUpdate"); + for (size_t i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) { struct bt_mesh_rpl *rpl = &bt_mesh.rpl[i]; + BT_DBG("RPL%u, Src 0x%04x Seq %lu OldIV %u", + i, rpl->src, rpl->seq, rpl->old_iv); + if (rpl->src) { if (rpl->old_iv) { (void)memset(rpl, 0, sizeof(*rpl)); @@ -115,6 +136,8 @@ void bt_mesh_rpl_update(void) void bt_mesh_rpl_reset_single(uint16_t src, bool erase) { + BT_DBG("RPLResetSingle, Src 0x%04x Erase %u", src, erase); + if (!BLE_MESH_ADDR_IS_UNICAST(src)) { return; } @@ -132,6 +155,8 @@ void bt_mesh_rpl_reset_single(uint16_t src, bool erase) void bt_mesh_rpl_reset(bool erase) { + BT_DBG("RPLReset, Erase %u", erase); + (void)memset(bt_mesh.rpl, 0, sizeof(bt_mesh.rpl)); if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS) && erase) { diff --git a/components/bt/esp_ble_mesh/core/scan.c b/components/bt/esp_ble_mesh/core/scan.c index c298f184566..a7a685d099e 100644 --- a/components/bt/esp_ble_mesh/core/scan.c +++ b/components/bt/esp_ble_mesh/core/scan.c @@ -29,7 +29,7 @@ #if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" -#endif +#endif /* CONFIG_BLE_MESH_V11_SUPPORT */ /* Scan Window and Interval are equal for continuous scanning */ #define SCAN_INTERVAL 0x20 @@ -44,14 +44,14 @@ static struct bt_mesh_scan_param scan_param = { #if CONFIG_BLE_MESH_RPR_SRV_ACTIVE_SCAN .type = BLE_MESH_SCAN_ACTIVE, -#else +#else /* CONFIG_BLE_MESH_RPR_SRV_ACTIVE_SCAN */ .type = BLE_MESH_SCAN_PASSIVE, -#endif +#endif /* CONFIG_BLE_MESH_RPR_SRV_ACTIVE_SCAN */ #if CONFIG_BLE_MESH_USE_DUPLICATE_SCAN .filter_dup = BLE_MESH_SCAN_FILTER_DUP_ENABLE, -#else +#else /* CONFIG_BLE_MESH_USE_DUPLICATE_SCAN */ .filter_dup = BLE_MESH_SCAN_FILTER_DUP_DISABLE, -#endif +#endif /* CONFIG_BLE_MESH_USE_DUPLICATE_SCAN */ .interval = SCAN_INTERVAL, .window = SCAN_WINDOW, .scan_fil_policy = BLE_MESH_SP_ADV_ALL, @@ -76,6 +76,11 @@ int bt_mesh_unprov_dev_fifo_dequeue(uint8_t *uuid, uint8_t *addr) { uint8_t idx = 0; + BT_DBG("UnprovDevFifoDequeue, PairNum %u StartIdx %u EndIdx %u", + unprov_dev_info_fifo.pair_num, + unprov_dev_info_fifo.start_idx, + unprov_dev_info_fifo.end_idx); + if (unprov_dev_info_fifo.pair_num == 0) { return 0; } @@ -100,9 +105,11 @@ int bt_mesh_unprov_dev_fifo_dequeue(uint8_t *uuid, uint8_t *addr) int bt_mesh_unprov_dev_info_query(uint8_t uuid[16], uint8_t addr[6], uint8_t *adv_type, uint8_t query_type) { + uint8_t pair_num = unprov_dev_info_fifo.pair_num; uint8_t idx = 0; uint8_t cnt = 0; - uint8_t pair_num = unprov_dev_info_fifo.pair_num; + + BT_DBG("UnprovDevInfoQuery, QueryType 0x%02x PairNum %u", query_type, pair_num); if (uuid == NULL && addr == NULL) { BT_WARN("No available information to query"); @@ -111,6 +118,9 @@ int bt_mesh_unprov_dev_info_query(uint8_t uuid[16], uint8_t addr[6], while (cnt < pair_num) { idx = (cnt + unprov_dev_info_fifo.start_idx) % BLE_MESH_STORE_UNPROV_INFO_MAX_NUM; + + BT_DBG("Count %u StartIdx %u Idx %u", cnt, unprov_dev_info_fifo.start_idx, idx); + if (query_type & BLE_MESH_STORE_UNPROV_INFO_QUERY_TYPE_UUID) { if (!memcmp(unprov_dev_info_fifo.info[idx].addr, addr, 6)) { if (query_type & BLE_MESH_STORE_UNPROV_INFO_QUERY_TYPE_EXISTS) { @@ -132,21 +142,25 @@ int bt_mesh_unprov_dev_info_query(uint8_t uuid[16], uint8_t addr[6], break; } } + cnt++; } if (cnt == pair_num) { + BT_DBG("Count == PairNum"); return -1; } return 0; - } int bt_mesh_unprov_dev_fifo_enqueue(uint8_t uuid[16], const uint8_t addr[6], uint8_t adv_type) { uint8_t idx = 0; + BT_DBG("UnprovDevFifoEnqueue, EndIdx %u PairNum %u", + unprov_dev_info_fifo.end_idx, unprov_dev_info_fifo.pair_num); + if (uuid == NULL || addr == NULL) { BT_ERR("Invalid argument %s", __func__); return -EINVAL; @@ -170,6 +184,9 @@ int bt_mesh_unprov_dev_fifo_enqueue(uint8_t uuid[16], const uint8_t addr[6], uin idx = (idx + 1) % BLE_MESH_STORE_UNPROV_INFO_MAX_NUM; unprov_dev_info_fifo.end_idx = idx; unprov_dev_info_fifo.pair_num++; + + BT_DBG("EndIdx %u PairNum %u", unprov_dev_info_fifo.end_idx, unprov_dev_info_fifo.pair_num); + return 0; } @@ -180,19 +197,22 @@ const bt_mesh_addr_t *bt_mesh_get_unprov_dev_addr(void) uint8_t bt_mesh_get_adv_type(void) { + BT_DBG("CurrentAdvType %u", current_adv_type); + return current_adv_type; } - #endif /* (CONFIG_BLE_MESH_PROVISIONER || CONFIG_BLE_MESH_RPR_SRV) */ #if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \ CONFIG_BLE_MESH_PROXY_SOLIC_PDU_RX || \ - (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) + (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) static bool adv_flags_valid(struct net_buf_simple *buf) { uint8_t flags = 0U; + BT_DBG("IsAdvFlagsValid"); + if (buf->len != 1U) { BT_DBG("Unexpected adv flags length %d", buf->len); return false; @@ -200,7 +220,7 @@ static bool adv_flags_valid(struct net_buf_simple *buf) flags = net_buf_simple_pull_u8(buf); - BT_DBG("Received adv pkt with flags: 0x%02x", flags); + BT_DBG("Flags 0x%02x", flags); /* Flags context will not be checked currently */ ARG_UNUSED(flags); @@ -210,6 +230,8 @@ static bool adv_flags_valid(struct net_buf_simple *buf) static bool adv_service_uuid_valid(struct net_buf_simple *buf, uint16_t *uuid) { + BT_DBG("IsAdvServiceUUIDValid"); + if (buf->len != 2U) { BT_DBG("Length not match mesh service uuid"); return false; @@ -217,40 +239,42 @@ static bool adv_service_uuid_valid(struct net_buf_simple *buf, uint16_t *uuid) *uuid = net_buf_simple_pull_le16(buf); - BT_DBG("Received adv pkt with service UUID: %d", *uuid); + BT_DBG("UUID 0x%04x", *uuid); if (*uuid != BLE_MESH_UUID_MESH_PROV_VAL && *uuid != BLE_MESH_UUID_MESH_PROXY_VAL && *uuid != BLE_MESH_UUID_MESH_PROXY_SOLIC_VAL) { + BT_DBG("UnexpectMeshUUID"); return false; } - /** - * @brief In remote provisioning. - * A Node could handle the unprovisioned beacon. + /* In remote provisioning, Node could handle unprovisioned device beacon. * CASE: MESH/SR/RPR/SCN/BV-01-C - */ + */ #if CONFIG_BLE_MESH_RPR_SRV if (*uuid == BLE_MESH_UUID_MESH_PROV_VAL && !IS_ENABLED(CONFIG_BLE_MESH_PB_GATT)) { + BT_DBG("IgnorePBGattUUID"); return false; } -#else +#else /* CONFIG_BLE_MESH_RPR_SRV */ if (*uuid == BLE_MESH_UUID_MESH_PROV_VAL && (bt_mesh_is_provisioner_en() == false || !IS_ENABLED(CONFIG_BLE_MESH_PB_GATT))) { + BT_DBG("IgnorePBGattUUID"); return false; } -#endif - +#endif /* CONFIG_BLE_MESH_RPR_SRV */ if (*uuid == BLE_MESH_UUID_MESH_PROXY_VAL && !IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_CLIENT)) { + BT_DBG("IgnoreProxyUUID"); return false; } if (*uuid == BLE_MESH_UUID_MESH_PROXY_SOLIC_VAL && !IS_ENABLED(CONFIG_BLE_MESH_PROXY_SOLIC_PDU_RX)) { + BT_DBG("IgnoreProxySolicUUID"); return false; } @@ -263,6 +287,8 @@ static void handle_adv_service_data(struct net_buf_simple *buf, { uint16_t type = 0U; + BT_DBG("HandleAdvServiceData, UUID 0x%04x", uuid); + if (!buf || !addr) { BT_ERR("%s, Invalid parameter", __func__); return; @@ -270,7 +296,7 @@ static void handle_adv_service_data(struct net_buf_simple *buf, type = net_buf_simple_pull_le16(buf); if (type != uuid) { - BT_DBG("Invalid Mesh Service Data UUID 0x%04x", type); + BT_DBG("UnexpectMeshUUID 0x%04x", type); return; } @@ -292,8 +318,13 @@ static void handle_adv_service_data(struct net_buf_simple *buf, #if CONFIG_BLE_MESH_RPR_SRV if (bt_mesh_is_provisioned()) { - const bt_mesh_addr_t *addr = bt_mesh_get_unprov_dev_addr(); + const bt_mesh_addr_t *addr = NULL; + + addr = bt_mesh_get_unprov_dev_addr(); + assert(addr); + bt_mesh_unprov_dev_fifo_enqueue(buf->data, addr->val, bt_mesh_get_adv_type()); + bt_mesh_rpr_srv_unprov_beacon_recv(buf, bt_mesh_get_adv_type(), addr, rssi); } #endif /* CONFIG_BLE_MESH_RPR_SRV */ @@ -316,7 +347,8 @@ static void handle_adv_service_data(struct net_buf_simple *buf, BT_DBG("Start to handle Mesh Proxy Service Data"); bt_mesh_proxy_client_gatt_adv_recv(buf, addr, rssi); break; -#endif +#endif /* CONFIG_BLE_MESH_GATT_PROXY_CLIENT */ + #if CONFIG_BLE_MESH_PROXY_SOLIC_PDU_RX case BLE_MESH_UUID_MESH_PROXY_SOLIC_VAL: if (buf->len != (1 + BLE_MESH_NET_HDR_LEN + 8)) { @@ -327,7 +359,8 @@ static void handle_adv_service_data(struct net_buf_simple *buf, BT_DBG("Start to handle Mesh Proxy Solic Service Data"); bt_mesh_proxy_server_solic_recv(buf, addr, rssi); break; -#endif +#endif /* CONFIG_BLE_MESH_PROXY_SOLIC_PDU_RX */ + default: break; } @@ -342,6 +375,8 @@ static bool ble_scan_en; int bt_mesh_start_ble_scan(struct bt_mesh_ble_scan_param *param) { + BT_DBG("StartBLEScan"); + if (ble_scan_en == true) { BT_WARN("%s, Already", __func__); return -EALREADY; @@ -354,6 +389,8 @@ int bt_mesh_start_ble_scan(struct bt_mesh_ble_scan_param *param) int bt_mesh_stop_ble_scan(void) { + BT_DBG("StopBLEScan"); + if (ble_scan_en == false) { BT_WARN("%s, Already", __func__); return -EALREADY; @@ -366,6 +403,8 @@ int bt_mesh_stop_ble_scan(void) bool bt_mesh_ble_scan_state_get(void) { + BT_DBG("BLEScanEn %u", ble_scan_en); + return ble_scan_en; } @@ -375,6 +414,7 @@ static void inline callback_ble_adv_pkt(const bt_mesh_addr_t *addr, { #if !CONFIG_BLE_MESH_USE_BLE_50 bt_mesh_ble_adv_report_t adv_rpt = {0}; + if (ble_scan_en) { memcpy(adv_rpt.addr, addr->val, BD_ADDR_LEN); adv_rpt.addr_type = addr->type; @@ -382,9 +422,12 @@ static void inline callback_ble_adv_pkt(const bt_mesh_addr_t *addr, adv_rpt.length = length; adv_rpt.data = length ? data : NULL; adv_rpt.rssi = rssi; + + BT_DBG("CallbackBLEAdvPkt, AdvType 0x%02x Len %u", adv_type, length); + bt_mesh_ble_scan_cb_evt_to_btc(&adv_rpt); } -#endif +#endif /* !CONFIG_BLE_MESH_USE_BLE_50 */ } #endif /* CONFIG_BLE_MESH_SUPPORT_BLE_SCAN */ @@ -395,6 +438,8 @@ static bool rpr_ext_scan_handle_adv_pkt(const bt_mesh_addr_t *addr, struct net_buf_simple buf = {0}; bool rpr_adv = false; + BT_DBG("RPRExtScanHandleAdvPkt, Provisioned %u", bt_mesh_is_provisioned()); + if (bt_mesh_is_provisioned() == false) { return false; } @@ -408,19 +453,19 @@ static bool rpr_ext_scan_handle_adv_pkt(const bt_mesh_addr_t *addr, static void bt_mesh_scan_cb(struct bt_mesh_adv_report *adv_rpt) { - struct net_buf_simple_state buf_state = {0}; struct net_buf_simple *buf = &adv_rpt->adv_data; + struct net_buf_simple_state buf_state = {0}; #if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ - CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \ + CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \ CONFIG_BLE_MESH_PROXY_SOLIC_PDU_RX || \ - (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) + (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) uint16_t uuid = 0U; #endif #if (CONFIG_BLE_MESH_RPR_SRV || CONFIG_BLE_MESH_SUPPORT_BLE_SCAN) uint8_t *adv_data = buf->data; uint16_t adv_len = buf->len; -#endif +#endif /* (CONFIG_BLE_MESH_RPR_SRV || CONFIG_BLE_MESH_SUPPORT_BLE_SCAN) */ net_buf_simple_save(buf, &buf_state); @@ -429,40 +474,41 @@ static void bt_mesh_scan_cb(struct bt_mesh_adv_report *adv_rpt) adv_rpt->adv_type != 0 && #endif adv_rpt->adv_type != BLE_MESH_ADV_NONCONN_IND && - adv_rpt->adv_type != BLE_MESH_ADV_IND + adv_rpt->adv_type != BLE_MESH_ADV_IND #if CONFIG_BLE_MESH_EXT_ADV - && adv_rpt->adv_type != BLE_MESH_EXT_ADV_NONCONN_IND + && adv_rpt->adv_type != BLE_MESH_EXT_ADV_NONCONN_IND #endif #if CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_RPR_SRV_ACTIVE_SCAN - && adv_rpt->adv_type != BLE_MESH_ADV_SCAN_RSP -#endif - ) { + && adv_rpt->adv_type != BLE_MESH_ADV_SCAN_RSP +#endif /* CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_RPR_SRV_ACTIVE_SCAN */ + ) { #if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN callback_ble_adv_pkt(&adv_rpt->addr, adv_rpt->adv_type, adv_data, adv_len, adv_rpt->rssi); -#endif +#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_SCAN */ + net_buf_simple_restore(buf, &buf_state); return; } - BT_DBG("scan, len %u: %s", buf->len, bt_hex(buf->data, buf->len)); + BT_DBG("MeshScan"); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); #if (CONFIG_BLE_MESH_PROVISIONER || CONFIG_BLE_MESH_RPR_SRV) unprov_dev_addr = &adv_rpt->addr; current_adv_type = adv_rpt->adv_type; -#endif +#endif /* (CONFIG_BLE_MESH_PROVISIONER || CONFIG_BLE_MESH_RPR_SRV) */ #if CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_RPR_SRV_ACTIVE_SCAN if (adv_rpt->adv_type == BLE_MESH_ADV_SCAN_RSP) { - /** - * scan response is only visible for remote provisioning extend scan. - */ + /* scan response is only visible for remote provisioning extend scan */ if (rpr_ext_scan_handle_adv_pkt(&adv_rpt->addr, adv_data, adv_len)) { return; } #if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN callback_ble_adv_pkt(&adv_rpt->addr, adv_rpt->adv_type, adv_data, adv_len, adv_rpt->rssi); -#endif +#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_SCAN */ + net_buf_simple_restore(buf, &buf_state); } #endif /* CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_RPR_SRV_ACTIVE_SCAN */ @@ -472,20 +518,24 @@ static void bt_mesh_scan_cb(struct bt_mesh_adv_report *adv_rpt) uint8_t len, type; len = net_buf_simple_pull_u8(buf); + /* Check for early termination */ if (len == 0U) { #if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN callback_ble_adv_pkt(&adv_rpt->addr, adv_rpt->adv_type, adv_data, adv_len, adv_rpt->rssi); -#endif +#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_SCAN */ + net_buf_simple_restore(buf, &buf_state); return; } if (len > buf->len) { - BT_DBG("AD malformed"); + BT_DBG("MalformedAD"); + #if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN callback_ble_adv_pkt(&adv_rpt->addr, adv_rpt->adv_type, adv_data, adv_len, adv_rpt->rssi); -#endif +#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_SCAN */ + net_buf_simple_restore(buf, &buf_state); return; } @@ -496,13 +546,15 @@ static void bt_mesh_scan_cb(struct bt_mesh_adv_report *adv_rpt) buf->len = len - 1; - if ((type == BLE_MESH_DATA_MESH_PROV || type == BLE_MESH_DATA_MESH_MESSAGE || - type == BLE_MESH_DATA_MESH_BEACON) && (adv_rpt->adv_type != BLE_MESH_ADV_NONCONN_IND + if ((type == BLE_MESH_DATA_MESH_PROV || + type == BLE_MESH_DATA_MESH_MESSAGE || + type == BLE_MESH_DATA_MESH_BEACON) && + (adv_rpt->adv_type != BLE_MESH_ADV_NONCONN_IND #if CONFIG_BLE_MESH_EXT_ADV - && adv_rpt->adv_type != BLE_MESH_EXT_ADV_NONCONN_IND + && adv_rpt->adv_type != BLE_MESH_EXT_ADV_NONCONN_IND #endif )) { - BT_DBG("Ignore mesh packet (type 0x%02x) with adv_type 0x%02x", type, adv_rpt->adv_type); + BT_DBG("IgnorePkt, Type 0x%02x AdvType 0x%02x", type, adv_rpt->adv_type); return; } @@ -526,36 +578,44 @@ static void bt_mesh_scan_cb(struct bt_mesh_adv_report *adv_rpt) #endif /* CONFIG_BLE_MESH_EXT_ADV */ bt_mesh_generic_net_recv(buf, &rx, BLE_MESH_NET_IF_ADV); break; + #if CONFIG_BLE_MESH_PB_ADV case BLE_MESH_DATA_MESH_PROV: if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_node()) { bt_mesh_pb_adv_recv(buf); } + if (IS_ENABLED(CONFIG_BLE_MESH_PROVISIONER) && bt_mesh_is_provisioner_en()) { bt_mesh_provisioner_pb_adv_recv(buf); } break; #endif /* CONFIG_BLE_MESH_PB_ADV */ + case BLE_MESH_DATA_MESH_BEACON: bt_mesh_beacon_recv(buf, adv_rpt->rssi); break; + #if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \ CONFIG_BLE_MESH_PROXY_SOLIC_PDU_RX || \ - (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) + (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) case BLE_MESH_DATA_FLAGS: if (!adv_flags_valid(buf)) { BT_DBG("Adv Flags mismatch, ignore this adv pkt"); + #if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN callback_ble_adv_pkt(&adv_rpt->addr, adv_rpt->adv_type, adv_data, adv_len, adv_rpt->rssi); -#endif +#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_SCAN */ + net_buf_simple_restore(buf, &buf_state); return; } break; + case BLE_MESH_DATA_UUID16_ALL: if (!adv_service_uuid_valid(buf, &uuid)) { BT_DBG("Adv Service UUID mismatch, ignore this adv pkt"); + #if CONFIG_BLE_MESH_RPR_SRV if (rpr_ext_scan_handle_adv_pkt(&adv_rpt->addr, adv_data, adv_len)) { /* If handled as extended scan report successfully, then not @@ -563,18 +623,25 @@ static void bt_mesh_scan_cb(struct bt_mesh_adv_report *adv_rpt) */ return; } -#endif +#endif /* CONFIG_BLE_MESH_RPR_SRV */ + #if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN callback_ble_adv_pkt(&adv_rpt->addr, adv_rpt->adv_type, adv_data, adv_len, adv_rpt->rssi); -#endif +#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_SCAN */ + net_buf_simple_restore(buf, &buf_state); return; } break; + case BLE_MESH_DATA_SVC_DATA16: handle_adv_service_data(buf, &adv_rpt->addr, uuid, adv_rpt->rssi); break; -#endif +#endif /* (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \ + CONFIG_BLE_MESH_PROXY_SOLIC_PDU_RX || \ + (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) */ + default: #if CONFIG_BLE_MESH_RPR_SRV if (rpr_ext_scan_handle_adv_pkt(&adv_rpt->addr, adv_data, adv_len)) { @@ -583,10 +650,12 @@ static void bt_mesh_scan_cb(struct bt_mesh_adv_report *adv_rpt) */ return; } -#endif +#endif /* CONFIG_BLE_MESH_RPR_SRV */ + #if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN callback_ble_adv_pkt(&adv_rpt->addr, adv_rpt->adv_type, adv_data, adv_len, adv_rpt->rssi); -#endif +#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_SCAN */ + net_buf_simple_restore(buf, &buf_state); return; } @@ -600,9 +669,11 @@ int bt_mesh_scan_enable(void) { int err = 0; + BT_DBG("ScanEnable"); + err = bt_le_scan_start(&scan_param, bt_mesh_scan_cb); if (err && err != -EALREADY) { - BT_ERR("starting scan failed (err %d)", err); + BT_ERR("StartScanFailed, Err %d", err); return err; } @@ -613,9 +684,11 @@ int bt_mesh_scan_disable(void) { int err = 0; + BT_DBG("ScanDisable"); + err = bt_le_scan_stop(); if (err && err != -EALREADY) { - BT_ERR("stopping scan failed (err %d)", err); + BT_ERR("StopScanFailed, Err %d", err); return err; } @@ -629,9 +702,13 @@ int bt_mesh_scan_param_update(struct bt_mesh_scan_param *param) if (param == NULL || param->interval == 0 || param->interval < param->window) { + BT_ERR("InvalidScanParam"); return -EINVAL; } + BT_DBG("ScanParamUpdate, Type %u Interval %u Window %u", + param->type, param->interval, param->window); + scan_param.interval = param->interval; scan_param.window = param->window; @@ -641,24 +718,22 @@ int bt_mesh_scan_param_update(struct bt_mesh_scan_param *param) BT_INFO("New scan parameters will take effect after scan starts"); return 0; } - BT_ERR("Failed to stop scan (err %d)", err); + + BT_ERR("StopScanFailed, Err %d", err); return err; } - /** - * Since the user only needs to set the scan interval - * and scan window parameters, only the interval and - * window parameters in the `param` are correct. + /* Since the user only needs to set the scan interval and scan window, + * only the interval and window parameters in the `param` are correct. * - * For the aforementioned reason, when updating the scan - * parameters, the other parameters also need to be set - * correctly, and these other parameters are saved in the - * `scan_param`. Therefore, `scan_param` must be used instead - * of `param` here. + * For the aforementioned reason, when updating the scan parameters, + * the other parameters also need to be set correctly, and these other + * parameters are saved in the `scan_param`. Therefore, `scan_param` + * must be used instead of `param` here. */ err = bt_le_scan_start(&scan_param, bt_mesh_scan_cb); if (err && err != -EALREADY) { - BT_ERR("Failed to start scan (err %d)", err); + BT_ERR("StartScanFailed, Err %d", err); return err; } @@ -668,23 +743,24 @@ int bt_mesh_scan_param_update(struct bt_mesh_scan_param *param) #if CONFIG_BLE_MESH_TEST_USE_WHITE_LIST int bt_mesh_scan_with_wl_enable(void) { - int err = 0; - struct bt_mesh_scan_param scan_param = { .type = BLE_MESH_SCAN_PASSIVE, #if CONFIG_BLE_MESH_USE_DUPLICATE_SCAN .filter_dup = BLE_MESH_SCAN_FILTER_DUP_ENABLE, -#else +#else /* CONFIG_BLE_MESH_USE_DUPLICATE_SCAN */ .filter_dup = BLE_MESH_SCAN_FILTER_DUP_DISABLE, -#endif +#endif /* CONFIG_BLE_MESH_USE_DUPLICATE_SCAN */ .interval = SCAN_INTERVAL, .window = SCAN_WINDOW, .scan_fil_policy = BLE_MESH_SP_ADV_WL, }; + int err = 0; + + BT_DBG("ScanWithWLEnable"); err = bt_le_scan_start(&scan_param, bt_mesh_scan_cb); if (err && err != -EALREADY) { - BT_ERR("starting scan failed (err %d)", err); + BT_ERR("StartScanFailed, Err %d", err); return err; } diff --git a/components/bt/esp_ble_mesh/core/storage/settings.c b/components/bt/esp_ble_mesh/core/storage/settings.c index 437c3d9b074..b48274eadec 100644 --- a/components/bt/esp_ble_mesh/core/storage/settings.c +++ b/components/bt/esp_ble_mesh/core/storage/settings.c @@ -24,7 +24,7 @@ #if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" -#endif +#endif /* CONFIG_BLE_MESH_V11_SUPPORT */ /* BLE Mesh NVS Key and corresponding data struct. * Note: The length of nvs key must be <= 15. @@ -209,6 +209,8 @@ static int role_set(const char *name) bool exist = false; int err = 0; + BT_DBG("RoleSet, Name %s", name); + err = bt_mesh_load_core_settings(name, (uint8_t *)bt_mesh.flags, sizeof(bt_mesh.flags), &exist); if (err) { BT_ERR("Failed to load mesh device role"); @@ -221,9 +223,9 @@ static int role_set(const char *name) !IS_ENABLED(CONFIG_BLE_MESH_PROVISIONER)) { bt_mesh_atomic_set_bit(bt_mesh.flags, BLE_MESH_NODE); } -#else +#else /* CONFIG_BLE_MESH_SETTINGS_BACKWARD_COMPATIBILITY */ return 0; -#endif +#endif /* CONFIG_BLE_MESH_SETTINGS_BACKWARD_COMPATIBILITY */ } return 0; @@ -235,6 +237,8 @@ static int net_set(const char *name) bool exist = false; int err = 0; + BT_DBG("NetSet, Name %s", name); + err = bt_mesh_load_core_settings(name, (uint8_t *)&net, sizeof(net), &exist); if (err) { BT_ERR("Failed to load node net info"); @@ -261,6 +265,8 @@ static int dkca_set(const char *name) bool exist = false; int err = 0; + BT_DBG("DkcaSet, Name %s", name); + err = bt_mesh_load_core_settings(name, bt_mesh.dev_key_ca, sizeof(bt_mesh.dev_key_ca), &exist); if (err) { BT_ERR("Failed to load DevKey Candidate"); @@ -282,6 +288,8 @@ static int iv_set(const char *name) bool exist = false; int err = 0; + BT_DBG("IVSet, Name %s", name); + err = bt_mesh_load_core_settings(name, (uint8_t *)&iv, sizeof(iv), &exist); if (err) { BT_ERR("Failed to load iv_index"); @@ -299,7 +307,7 @@ static int iv_set(const char *name) bt_mesh.ivu_duration = iv.iv_duration; BT_INFO("Restored IV Index 0x%08x (IV Update Flag %u) duration %u hours", - iv.iv_index, iv.iv_update, iv.iv_duration); + iv.iv_index, iv.iv_update, iv.iv_duration); return 0; } @@ -310,6 +318,8 @@ static int seq_set(const char *name) bool exist = false; int err = 0; + BT_DBG("SeqSet, Name %s", name); + err = bt_mesh_load_core_settings(name, (uint8_t *)&seq, sizeof(seq), &exist); if (err) { BT_ERR("Failed to load sequence number"); @@ -331,7 +341,7 @@ static int seq_set(const char *name) bt_mesh.seq += (CONFIG_BLE_MESH_SEQ_STORE_RATE - (bt_mesh.seq % CONFIG_BLE_MESH_SEQ_STORE_RATE)); bt_mesh.seq--; -#endif +#endif /* CONFIG_BLE_MESH_SEQ_STORE_RATE > 0 */ BT_INFO("Restored Sequence Number 0x%06x", bt_mesh.seq); @@ -342,6 +352,8 @@ static struct bt_mesh_rpl *rpl_find(uint16_t src) { int i; + BT_DBG("RPLFind, Src 0x%04x", src); + for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) { if (bt_mesh.rpl[i].src == src) { return &bt_mesh.rpl[i]; @@ -355,6 +367,8 @@ static struct bt_mesh_rpl *rpl_alloc(uint16_t src) { int i; + BT_DBG("RPLAlloc, Src 0x%04x", src); + for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) { if (bt_mesh.rpl[i].src == BLE_MESH_ADDR_UNASSIGNED) { bt_mesh.rpl[i].src = src; @@ -376,6 +390,8 @@ static int rpl_set(const char *name) int err = 0; int i; + BT_DBG("RPLSet, Name %s", name); + buf = bt_mesh_get_core_settings_item(name); if (!buf) { return 0; @@ -429,6 +445,8 @@ static struct bt_mesh_subnet *subnet_exist(uint16_t net_idx) { int i; + BT_DBG("SubnetExist, NetIdx 0x%04x", net_idx); + for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) { if (bt_mesh.sub[i].net_idx == net_idx) { return &bt_mesh.sub[i]; @@ -442,6 +460,8 @@ static struct bt_mesh_subnet *subnet_alloc(uint16_t net_idx) { int i; + BT_DBG("SubnetAlloc, NetIdx 0x%04x", net_idx); + for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) { if (bt_mesh.sub[i].net_idx == BLE_MESH_KEY_UNUSED) { bt_mesh.sub[i].net_idx = net_idx; @@ -456,6 +476,8 @@ static struct bt_mesh_app_key *appkey_exist(uint16_t app_idx) { int i; + BT_DBG("AppKeyExist, AppIdx 0x%04x", app_idx); + for (i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) { if (bt_mesh.app_keys[i].net_idx != BLE_MESH_KEY_UNUSED && bt_mesh.app_keys[i].app_idx == app_idx) { @@ -477,6 +499,8 @@ static int net_key_set(const char *name) int err = 0; int i; + BT_DBG("NetKeySet, Name %s", name); + buf = bt_mesh_get_core_settings_item(name); if (!buf) { return 0; @@ -535,6 +559,8 @@ static int app_key_set(const char *name) int err = 0; int i; + BT_DBG("AppKeySet, Name %s", name); + buf = bt_mesh_get_core_settings_item(name); if (!buf) { return 0; @@ -566,7 +592,6 @@ static int app_key_set(const char *name) if (!app) { app = bt_mesh_app_key_alloc(app_idx); if (!app) { - BT_ERR("No space for a new appkey 0x%03x", app_idx); err = -ENOMEM; goto free; } @@ -581,7 +606,7 @@ static int app_key_set(const char *name) bt_mesh_app_id(app->keys[1].val, &app->keys[1].id); BT_INFO("Restored AppKeyIndex 0x%03x, NetKeyIndex 0x%03x", - app->app_idx, app->net_idx); + app->app_idx, app->net_idx); BT_INFO("Restored AppKey %s", bt_hex(app->keys[0].val, 16)); } @@ -597,6 +622,8 @@ static int hb_pub_set(const char *name) bool exist = false; int err = 0; + BT_DBG("HbPubSet, Name %s", name); + if (!hb_pub) { BT_ERR("Invalid heartbeat publication"); return -EINVAL; @@ -641,6 +668,8 @@ static int cfg_set(const char *name) bool exist = false; int err = 0; + BT_DBG("CfgSet, Name %s", name); + if (!cfg) { BT_ERR("Invalid configuration"); stored_cfg.valid = false; @@ -674,6 +703,8 @@ static int model_set_bind(bool vnd, struct bt_mesh_model *model, uint16_t model_ int err = 0; int i; + BT_DBG("ModelSetBind, Key 0x%04x Vnd %u", model_key, vnd); + /* Start with empty array regardless of cleared or set value */ for (i = 0; i < ARRAY_SIZE(model->keys); i++) { model->keys[i] = BLE_MESH_KEY_UNUSED; @@ -700,6 +731,8 @@ static int model_set_sub(bool vnd, struct bt_mesh_model *model, uint16_t model_k int err = 0; int i; + BT_DBG("ModelSetSub, Key 0x%04x Vnd %u", model_key, vnd); + /* Start with empty array regardless of cleared or set value */ for (i = 0; i < ARRAY_SIZE(model->groups); i++) { model->groups[i] = BLE_MESH_ADDR_UNASSIGNED; @@ -726,6 +759,8 @@ static int model_set_pub(bool vnd, struct bt_mesh_model *model, uint16_t model_k bool exist = false; int err = 0; + BT_DBG("ModelSetPub, Key 0x%04x Vnd %u", model_key, vnd); + if (!model->pub) { BT_INFO("Not support publication, model_id 0x%04x, cid 0x%04x", vnd ? model->vnd.id : model->id, vnd ? model->vnd.company : 0xFFFF); @@ -776,6 +811,8 @@ static int model_set(bool vnd, const char *name) size_t length = 0U; int i; + BT_DBG("ModelSet, Name %s Vnd %u", name, vnd); + buf = bt_mesh_get_core_settings_item(name); if (!buf) { return 0; @@ -792,7 +829,7 @@ static int model_set(bool vnd, const char *name) model = bt_mesh_model_get(vnd, elem_idx, model_idx); if (!model) { BT_ERR("%s model not found, elem_idx %u, model_idx %u", - vnd ? "vnd" : "sig", elem_idx, model_idx); + vnd ? "vnd" : "sig", elem_idx, model_idx); continue; } @@ -827,6 +864,8 @@ static int va_set(const char *name) int err = 0; int i; + BT_DBG("VaSet, Name %s", name); + buf = bt_mesh_get_core_settings_item(name); if (!buf) { return 0; @@ -871,7 +910,7 @@ free: bt_mesh_free_buf(buf); return err; } -#endif +#endif /* CONFIG_BLE_MESH_LABEL_COUNT > 0 */ #if CONFIG_BLE_MESH_PROVISIONER static int p_prov_set(const char *name) @@ -880,6 +919,8 @@ static int p_prov_set(const char *name) bool exist = false; int err = 0; + BT_DBG("PvnrProvSet, Name %s", name); + err = bt_mesh_load_core_settings(name, (uint8_t *)&val, sizeof(val), &exist); if (err) { BT_ERR("Failed to load next address allocation"); @@ -893,7 +934,7 @@ static int p_prov_set(const char *name) bt_mesh_provisioner_restore_prov_info(val.primary_addr, val.alloc_addr); BT_INFO("Restored Primary Address 0x%04x, next address alloc 0x%04x", - val.primary_addr, val.alloc_addr); + val.primary_addr, val.alloc_addr); return 0; } @@ -904,6 +945,8 @@ static int p_net_idx_set(const char *name) bool exist = false; int err = 0; + BT_DBG("PvnrNetIdxSet, Name %s", name); + err = bt_mesh_load_core_settings(name, (uint8_t *)&net_idx, sizeof(net_idx), &exist); if (err) { BT_ERR("Failed to load next NetKeyIndex alloc"); @@ -927,6 +970,8 @@ static int p_app_idx_set(const char *name) bool exist = false; int err = 0; + BT_DBG("PvnrAppIdxSet, Name %s", name); + err = bt_mesh_load_core_settings(name, (uint8_t *)&app_idx, sizeof(app_idx), &exist); if (err) { BT_ERR("Failed to load next AppKeyIndex alloc"); @@ -948,6 +993,8 @@ static struct bt_mesh_subnet *p_subnet_exist(uint16_t net_idx) { int i; + BT_DBG("PvnrSubnetExist, NetIdx 0x%04x", net_idx); + for (i = 0; i < ARRAY_SIZE(bt_mesh.p_sub); i++) { if (bt_mesh.p_sub[i] && bt_mesh.p_sub[i]->net_idx == net_idx) { @@ -962,6 +1009,8 @@ static struct bt_mesh_subnet *p_subnet_alloc(void) { int i; + BT_DBG("PvnrSubnetAlloc"); + for (i = 0; i < ARRAY_SIZE(bt_mesh.p_sub); i++) { if (bt_mesh.p_sub[i] == NULL) { bt_mesh.p_sub[i] = bt_mesh_calloc(sizeof(struct bt_mesh_subnet)); @@ -981,6 +1030,8 @@ static struct bt_mesh_app_key *p_appkey_exist(uint16_t app_idx) { int i; + BT_DBG("PvnrAppKeyExist, AppIdx 0x%04x", app_idx); + for (i = 0; i < ARRAY_SIZE(bt_mesh.p_app_keys); i++) { if (bt_mesh.p_app_keys[i] && bt_mesh.p_app_keys[i]->net_idx != BLE_MESH_KEY_UNUSED && @@ -996,6 +1047,8 @@ static struct bt_mesh_app_key *p_appkey_alloc(void) { int i; + BT_DBG("PvnrAppKeyAlloc"); + for (i = 0; i < ARRAY_SIZE(bt_mesh.p_app_keys); i++) { if (bt_mesh.p_app_keys[i] == NULL) { bt_mesh.p_app_keys[i] = bt_mesh_calloc(sizeof(struct bt_mesh_app_key)); @@ -1022,6 +1075,8 @@ static int p_net_key_set(const char *name) int err = 0; int i; + BT_DBG("PvnrNetKeySet, Name %s", name); + buf = bt_mesh_get_core_settings_item(name); if (!buf) { return 0; @@ -1080,6 +1135,8 @@ static int p_app_key_set(const char *name) int err = 0; int i; + BT_DBG("PvnrAppKeySet, Name %s", name); + buf = bt_mesh_get_core_settings_item(name); if (!buf) { return 0; @@ -1126,7 +1183,7 @@ static int p_app_key_set(const char *name) bt_mesh_app_id(app->keys[1].val, &app->keys[1].id); BT_INFO("Restored AppKeyIndex 0x%03x, NetKeyIndex 0x%03x", - app->app_idx, app->net_idx); + app->app_idx, app->net_idx); BT_INFO("Restored AppKey %s", bt_hex(app->keys[0].val, 16)); } @@ -1142,6 +1199,8 @@ static int node_info_set(uint16_t addr, bool *exist) char get[16] = {'\0'}; int err = 0; + BT_DBG("NodeInfoSet, Addr 0x%04x", addr); + sprintf(get, "mesh/pn/%04x/i", addr); err = bt_mesh_load_core_settings(get, (uint8_t *)&info, sizeof(info), exist); if (err) { @@ -1182,6 +1241,8 @@ static int node_name_set(uint16_t addr) bool exist = false; int err = 0; + BT_DBG("NodeNameSet, Addr 0x%04x", addr); + sprintf(get, "mesh/pn/%04x/n", addr); err = bt_mesh_load_core_settings(get, (uint8_t *)name, BLE_MESH_NODE_NAME_SIZE, &exist); if (err) { @@ -1210,6 +1271,8 @@ static int node_comp_data_set(uint16_t addr) char get[16] = {'\0'}; int err = 0; + BT_DBG("NodeCompDataSet, Addr 0x%04x", addr); + sprintf(get, "mesh/pn/%04x/c", addr); buf = bt_mesh_get_core_settings_item(get); if (!buf) { @@ -1234,6 +1297,8 @@ static int p_node_set(const char *name) size_t length = 0U; int i; + BT_DBG("PvnrNodeSet, Name %s", name); + buf = bt_mesh_get_core_settings_item(name); if (!buf) { return 0; @@ -1288,7 +1353,7 @@ const struct bt_mesh_setting { { "mesh/vnd", vnd_mod_set }, /* For Node & Provisioner */ #if CONFIG_BLE_MESH_LABEL_COUNT > 0 { "mesh/vaddr", va_set }, /* For Node */ -#endif +#endif /* CONFIG_BLE_MESH_LABEL_COUNT > 0 */ #if CONFIG_BLE_MESH_PROVISIONER { "mesh/p_prov", p_prov_set }, /* For Provisioner */ { "mesh/p_netidx", p_net_idx_set }, /* For Provisioner */ @@ -1296,7 +1361,7 @@ const struct bt_mesh_setting { { "mesh/p_netkey", p_net_key_set }, /* For Provisioner */ { "mesh/p_appkey", p_app_key_set }, /* For Provisioner */ { "mesh/p_node", p_node_set }, /* For Provisioner */ -#endif +#endif /* CONFIG_BLE_MESH_PROVISIONER */ }; /** @@ -1318,6 +1383,8 @@ int settings_core_load(void) { int i; + BT_DBG("SettingsCoreLoad"); + for (i = 0; i < ARRAY_SIZE(settings); i++) { if ((!strcmp(settings[i].name, "mesh/net") || !strcmp(settings[i].name, "mesh/netkey") || @@ -1369,6 +1436,8 @@ static int subnet_init(struct bt_mesh_subnet *sub) { int err = 0; + BT_DBG("SubnetInit, NetIdx 0x%04x KrPhase %u", sub->net_idx, sub->kr_phase); + err = bt_mesh_net_keys_create(&sub->keys[0], sub->keys[0].net); if (err) { BT_ERR("Unable to generate keys for subnet"); @@ -1396,7 +1465,7 @@ static int subnet_init(struct bt_mesh_subnet *sub) #if CONFIG_BLE_MESH_DF_SRV bt_mesh_directed_forwarding_sub_init(sub); bt_mesh_recovery_directed_forwarding_table(sub); -#endif +#endif /* CONFIG_BLE_MESH_DF_SRV */ return 0; } @@ -1404,8 +1473,10 @@ static int subnet_init(struct bt_mesh_subnet *sub) static void commit_model(struct bt_mesh_model *model, struct bt_mesh_elem *elem, bool vnd, bool primary, void *user_data) { + BT_DBG("CommitModel, Vnd %u Primary %u", vnd, primary); + if (model->pub && model->pub->update && - model->pub->addr != BLE_MESH_ADDR_UNASSIGNED) { + model->pub->addr != BLE_MESH_ADDR_UNASSIGNED) { int32_t ms = bt_mesh_model_pub_period_get(model); if (ms) { BT_DBG("Starting publish timer (period %u ms)", ms); @@ -1420,10 +1491,13 @@ int settings_core_commit(void) int err = 0; int i; + BT_DBG("SettingsCoreCommit"); + #if CONFIG_BLE_MESH_NODE if (bt_mesh_is_node()) { if (bt_mesh.sub[0].net_idx == BLE_MESH_KEY_UNUSED) { /* Nothing to do since we're not yet provisioned */ + BT_INFO("NodeNotYetProvisioned"); return 0; } @@ -1513,20 +1587,22 @@ int settings_core_commit(void) } /* Pending flags that use K_NO_WAIT as the storage timeout */ -#define NO_WAIT_PENDING_BITS (BIT(BLE_MESH_NET_PENDING) | \ - BIT(BLE_MESH_IV_PENDING) | \ - BIT(BLE_MESH_SEQ_PENDING)) +#define NO_WAIT_PENDING_BITS (BIT(BLE_MESH_NET_PENDING) | \ + BIT(BLE_MESH_IV_PENDING) | \ + BIT(BLE_MESH_SEQ_PENDING)) /* Pending flags that use CONFIG_BLE_MESH_STORE_TIMEOUT */ -#define GENERIC_PENDING_BITS (BIT(BLE_MESH_KEYS_PENDING) | \ - BIT(BLE_MESH_HB_PUB_PENDING) | \ - BIT(BLE_MESH_CFG_PENDING) | \ - BIT(BLE_MESH_MOD_PENDING)) +#define GENERIC_PENDING_BITS (BIT(BLE_MESH_KEYS_PENDING) | \ + BIT(BLE_MESH_HB_PUB_PENDING) | \ + BIT(BLE_MESH_CFG_PENDING) | \ + BIT(BLE_MESH_MOD_PENDING)) static void schedule_store(int flag) { int32_t timeout = 0, remaining = 0; + BT_DBG("ScheduleStore, Flag %ld", flag); + bt_mesh_atomic_set_bit(bt_mesh.flags, flag); /* When Node is not provisioned OR Provisioner is disabled, @@ -1564,7 +1640,8 @@ static void schedule_store(int flag) static void clear_net(void) { - BT_DBG("Clearing Network"); + BT_DBG("ClearNet"); + bt_mesh_erase_core_settings("mesh/net"); } @@ -1572,8 +1649,9 @@ static void store_pending_net(void) { struct net_val net = {0}; - BT_DBG("Primary address 0x%04x DevKey %s", bt_mesh_primary_addr(), - bt_hex(bt_mesh.dev_key, 16)); + BT_DBG("StorePendingNet"); + BT_DBG("PrimaryAddr 0x%04x DevKey %s", + bt_mesh_primary_addr(), bt_hex(bt_mesh.dev_key, 16)); net.primary_addr = bt_mesh_primary_addr(); memcpy(net.dev_key, bt_mesh.dev_key, 16); @@ -1583,13 +1661,15 @@ static void store_pending_net(void) void bt_mesh_store_role(void) { - BT_DBG("Store, device role %lu", bt_mesh_atomic_get(bt_mesh.flags) & BLE_MESH_SETTINGS_ROLE_BIT_MASK); + BT_DBG("StoreRole %lu", bt_mesh_atomic_get(bt_mesh.flags) & BLE_MESH_SETTINGS_ROLE_BIT_MASK); bt_mesh_save_core_settings("mesh/role", (const uint8_t *)bt_mesh.flags, sizeof(bt_mesh.flags)); } void bt_mesh_store_net(void) { + BT_DBG("StoreNetSchedule"); + schedule_store(BLE_MESH_NET_PENDING); } @@ -1597,6 +1677,8 @@ static void store_pending_iv(void) { struct iv_val iv = {0}; + BT_DBG("StorePendingIV"); + iv.iv_index = bt_mesh.iv_index; iv.iv_update = bt_mesh_atomic_test_bit(bt_mesh.flags, BLE_MESH_IVU_IN_PROGRESS); iv.iv_duration = bt_mesh.ivu_duration; @@ -1606,6 +1688,8 @@ static void store_pending_iv(void) void bt_mesh_store_iv(bool only_duration) { + BT_DBG("StoreIVSchedule, OnlyDuration %u", only_duration); + schedule_store(BLE_MESH_IV_PENDING); if (!only_duration) { @@ -1616,7 +1700,8 @@ void bt_mesh_store_iv(bool only_duration) static void clear_iv(void) { - BT_DBG("Clearing IV"); + BT_DBG("ClearIV"); + bt_mesh_erase_core_settings("mesh/iv"); } @@ -1624,6 +1709,8 @@ static void store_pending_seq(void) { struct seq_val seq = {0}; + BT_DBG("StorePendingSeq, Seq 0x%06x", bt_mesh.seq); + sys_put_le24(bt_mesh.seq, seq.val); bt_mesh_save_core_settings("mesh/seq", (const uint8_t *)&seq, sizeof(seq)); @@ -1631,6 +1718,8 @@ static void store_pending_seq(void) void bt_mesh_store_seq(void) { + BT_DBG("StoreSeqSchedule, Seq 0x%06x", bt_mesh.seq); + if (CONFIG_BLE_MESH_SEQ_STORE_RATE && (bt_mesh.seq % CONFIG_BLE_MESH_SEQ_STORE_RATE)) { return; @@ -1641,7 +1730,8 @@ void bt_mesh_store_seq(void) void bt_mesh_clear_seq(void) { - BT_DBG("Clearing Seq"); + BT_DBG("ClearSeq"); + bt_mesh_erase_core_settings("mesh/seq"); } @@ -1651,7 +1741,8 @@ static void store_rpl(struct bt_mesh_rpl *entry) char name[16] = {'\0'}; int err = 0; - BT_DBG("src 0x%04x seq 0x%06x old_iv %u", entry->src, entry->seq, entry->old_iv); + BT_DBG("StoreRPL"); + BT_DBG("Src 0x%04x Seq 0x%06x OldIV %u", entry->src, entry->seq, entry->old_iv); rpl.seq = entry->seq; rpl.old_iv = entry->old_iv; @@ -1677,6 +1768,8 @@ static void clear_rpl(void) uint16_t src = 0U; int i; + BT_DBG("ClearRPL"); + buf = bt_mesh_get_core_settings_item("mesh/rpl"); if (!buf) { bt_mesh_erase_core_settings("mesh/rpl"); @@ -1706,9 +1799,14 @@ static void store_pending_rpl(void) { int i; + BT_DBG("StorePendingRPL"); + for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) { struct bt_mesh_rpl *rpl = &bt_mesh.rpl[i]; + BT_DBG("%u: Src 0x%04x Seq 0x%06x OldIV %u Store %u", + i, rpl->src, rpl->seq, rpl->old_iv, rpl->store); + if (rpl->store) { rpl->store = false; store_rpl(rpl); @@ -1721,6 +1819,8 @@ static void store_pending_hb_pub(void) struct bt_mesh_hb_pub *hb_pub = bt_mesh_hb_pub_get(); struct hb_pub_val val = {0}; + BT_DBG("StorePendingHbPub"); + if (!hb_pub) { BT_ERR("Invalid heartbeat publication"); return; @@ -1738,7 +1838,8 @@ static void store_pending_hb_pub(void) static void clear_hb_pub(void) { - BT_DBG("Clear heartbeat publication"); + BT_DBG("ClearHbPub"); + bt_mesh_erase_core_settings("mesh/hb_pub"); } @@ -1747,6 +1848,8 @@ static void store_pending_cfg(void) struct bt_mesh_cfg_srv *cfg = bt_mesh_cfg_get(); struct cfg_val val = {0}; + BT_DBG("StorePendingCfg"); + if (!cfg) { BT_WARN("NULL configuration state"); return; @@ -1765,7 +1868,8 @@ static void store_pending_cfg(void) static void clear_cfg(void) { - BT_DBG("Clearing configuration"); + BT_DBG("ClearCfg"); + bt_mesh_erase_core_settings("mesh/cfg"); } @@ -1774,7 +1878,7 @@ static void clear_app_key(uint16_t app_idx) char name[16] = {'\0'}; int err = 0; - BT_DBG("AppKeyIndex 0x%03x", app_idx); + BT_DBG("ClearAppKey, AppIdx 0x%04x", app_idx); sprintf(name, "mesh/ak/%04x", app_idx); bt_mesh_erase_core_settings(name); @@ -1790,7 +1894,7 @@ static void clear_net_key(uint16_t net_idx) char name[16] = {'\0'}; int err = 0; - BT_DBG("NetKeyIndex 0x%03x", net_idx); + BT_DBG("ClearNetKey, NetIdx 0x%04x", net_idx); sprintf(name, "mesh/nk/%04x", net_idx); bt_mesh_erase_core_settings(name); @@ -1802,7 +1906,7 @@ static void clear_net_key(uint16_t net_idx) #if CONFIG_BLE_MESH_DF_SRV bt_mesh_clear_directed_forwarding_table_data(net_idx); -#endif +#endif /* CONFIG_BLE_MESH_DF_SRV */ } static void store_net_key(struct bt_mesh_subnet *sub) @@ -1811,8 +1915,8 @@ static void store_net_key(struct bt_mesh_subnet *sub) char name[16] = {'\0'}; int err = 0; - BT_DBG("NetKeyIndex 0x%03x NetKey %s", sub->net_idx, - bt_hex(sub->keys[0].net, 16)); + BT_DBG("StoreNetKey, NetIdx 0x%04x KrFlag %u KrPhase %u", + sub->net_idx, sub->kr_flag, sub->kr_phase); memcpy(&key.val[0], sub->keys[0].net, 16); memcpy(&key.val[1], sub->keys[1].net, 16); @@ -1838,6 +1942,9 @@ static void store_app_key(struct bt_mesh_app_key *app) char name[16] = {'\0'}; int err = 0; + BT_DBG("StoreAppKey, NetIdx 0x%04x AppIdx 0x%04x Updated %u", + app->net_idx, app->app_idx, app->updated); + key.net_idx = app->net_idx; key.updated = app->updated; memcpy(key.val[0], app->keys[0].val, 16); @@ -1860,9 +1967,14 @@ static void store_pending_keys(void) { int i; + BT_DBG("StorePendingKeys"); + for (i = 0; i < ARRAY_SIZE(key_updates); i++) { struct key_update *update = &key_updates[i]; + BT_DBG("%u: KeyIdx 0x%04x Valid %u AppKey %u Clear %u", + i, update->key_idx, update->valid, update->app_key, update->clear); + if (!update->valid) { continue; } @@ -1876,6 +1988,7 @@ static void store_pending_keys(void) } else { if (update->app_key) { struct bt_mesh_app_key *key = NULL; + key = bt_mesh_app_key_get(update->key_idx); if (key) { store_app_key(key); @@ -1884,6 +1997,7 @@ static void store_pending_keys(void) } } else { struct bt_mesh_subnet *sub = NULL; + sub = bt_mesh_subnet_get(update->key_idx); if (sub) { store_net_key(sub); @@ -1903,6 +2017,8 @@ static void store_pending_mod_bind(struct bt_mesh_model *model, bool vnd) uint16_t model_key = 0U; int err = 0; + BT_DBG("StorePendingModBind, Vnd %u", vnd); + model_key = BLE_MESH_GET_MODEL_KEY(model->elem_idx, model->model_idx); sprintf(name, "mesh/%s/%04x/b", vnd ? "v" : "s", model_key); @@ -1915,7 +2031,7 @@ static void store_pending_mod_bind(struct bt_mesh_model *model, bool vnd) err = bt_mesh_add_core_settings_item(vnd ? "mesh/vnd" : "mesh/sig", model_key); if (err) { BT_ERR("Failed to add bound key to %s, model_key 0x%04x", - vnd ? "mesh/vnd" : "mesh/sig", model_key); + vnd ? "mesh/vnd" : "mesh/sig", model_key); } } @@ -1925,6 +2041,8 @@ static void store_pending_mod_sub(struct bt_mesh_model *model, bool vnd) uint16_t model_key = 0U; int err = 0; + BT_DBG("StorePendingModSub, Vnd %u", vnd); + model_key = BLE_MESH_GET_MODEL_KEY(model->elem_idx, model->model_idx); sprintf(name, "mesh/%s/%04x/s", vnd ? "v" : "s", model_key); @@ -1937,7 +2055,7 @@ static void store_pending_mod_sub(struct bt_mesh_model *model, bool vnd) err = bt_mesh_add_core_settings_item(vnd ? "mesh/vnd" : "mesh/sig", model_key); if (err) { BT_ERR("Failed to add subscription to %s, model_key 0x%04x", - vnd ? "mesh/vnd" : "mesh/sig", model_key); + vnd ? "mesh/vnd" : "mesh/sig", model_key); } } @@ -1948,6 +2066,8 @@ static void store_pending_mod_pub(struct bt_mesh_model *model, bool vnd) uint16_t model_key = 0U; int err = 0; + BT_DBG("StorePendingModPub, Vnd %u", vnd); + if (!model->pub) { BT_WARN("Model has no publication support"); return; @@ -1966,7 +2086,7 @@ static void store_pending_mod_pub(struct bt_mesh_model *model, bool vnd) #if CONFIG_BLE_MESH_DF_SRV pub.directed_pub_policy = model->pub->directed_pub_policy; /**< Directed publish policy */ -#endif +#endif /* CONFIG_BLE_MESH_DF_SRV */ err = bt_mesh_save_core_settings(name, (const uint8_t *)&pub, sizeof(pub)); if (err) { @@ -1985,6 +2105,8 @@ static void store_pending_mod(struct bt_mesh_model *model, struct bt_mesh_elem *elem, bool vnd, bool primary, void *user_data) { + BT_DBG("StorePendingMod, Flags %u Vnd %u", model->flags, vnd); + if (!model->flags) { return; } @@ -2010,6 +2132,8 @@ static void clear_mod_bind(struct bt_mesh_model *model, bool vnd) char name[16] = {'\0'}; uint16_t model_key = 0U; + BT_DBG("ClearModBind, Vnd %u", vnd); + model_key = BLE_MESH_GET_MODEL_KEY(model->elem_idx, model->model_idx); sprintf(name, "mesh/%s/%04x/b", vnd ? "v" : "s", model_key); @@ -2022,6 +2146,8 @@ static void clear_mod_sub(struct bt_mesh_model *model, bool vnd) char name[16] = {'\0'}; uint16_t model_key = 0U; + BT_DBG("ClearModSub, Vnd %u", vnd); + model_key = BLE_MESH_GET_MODEL_KEY(model->elem_idx, model->model_idx); sprintf(name, "mesh/%s/%04x/s", vnd ? "v" : "s", model_key); @@ -2031,8 +2157,10 @@ static void clear_mod_sub(struct bt_mesh_model *model, bool vnd) static void clear_mod_pub(struct bt_mesh_model *model, bool vnd) { - char name[16] = {'\0'}; uint16_t model_key = 0U; + char name[16] = {'\0'}; + + BT_DBG("ClearModPub, Vnd %u", vnd); model_key = BLE_MESH_GET_MODEL_KEY(model->elem_idx, model->model_idx); sprintf(name, "mesh/%s/%04x/p", vnd ? "v" : "s", model_key); @@ -2045,6 +2173,8 @@ static void clear_pending_mod(struct bt_mesh_model *model, struct bt_mesh_elem *elem, bool vnd, bool primary, void *user_data) { + BT_DBG("ClearPendingMod, Flags 0x%04x Vnd %u", model->flags, vnd); + if (!model->flags) { return; } @@ -2068,12 +2198,14 @@ static void clear_pending_mod(struct bt_mesh_model *model, #define IS_VA_DEL(_label) ((_label)->ref == 0) static void store_pending_va(void) { + struct label *lab = NULL; struct va_val va = {0}; char name[16] = {'\0'}; - struct label *lab = NULL; uint16_t i = 0U; int err = 0; + BT_DBG("StorePendingVa"); + for (i = 0U; (lab = get_label(i)) != NULL; i++) { if (!bt_mesh_atomic_test_and_clear_bit(lab->flags, BLE_MESH_VA_CHANGED)) { @@ -2092,7 +2224,7 @@ static void store_pending_va(void) } if (err) { BT_ERR("Failed to %s virtual address %s", - IS_VA_DEL(lab) ? "delete" : "store", name); + IS_VA_DEL(lab) ? "delete" : "store", name); return; } @@ -2103,7 +2235,7 @@ static void store_pending_va(void) } if (err) { BT_ERR("Failed to %s 0x%04x in mesh/vaddr", - IS_VA_DEL(lab) ? "delete" : "store", i); + IS_VA_DEL(lab) ? "delete" : "store", i); return; } @@ -2113,6 +2245,8 @@ static void store_pending_va(void) static void store_pending(struct k_work *work) { + BT_DBG("StorePending"); + if (bt_mesh_atomic_test_and_clear_bit(bt_mesh.flags, BLE_MESH_RPL_PENDING)) { if (bt_mesh_is_provisioned() || bt_mesh_is_provisioner_en()) { store_pending_rpl(); @@ -2174,6 +2308,7 @@ static void store_pending(struct k_work *work) bt_mesh_model_foreach(store_pending_mod, NULL); } else { bt_mesh_model_foreach(clear_pending_mod, NULL); + bt_mesh_erase_core_settings("mesh/sig"); bt_mesh_erase_core_settings("mesh/vnd"); } @@ -2187,6 +2322,9 @@ static void store_pending(struct k_work *work) void bt_mesh_store_rpl(struct bt_mesh_rpl *entry) { + BT_DBG("StoreRPLSchedule"); + BT_DBG("Src 0x%04x Seq 0x%06x OldIV %u", entry->src, entry->seq, entry->old_iv); + entry->store = true; schedule_store(BLE_MESH_RPL_PENDING); } @@ -2199,6 +2337,8 @@ static struct key_update *key_update_find(bool app_key, uint16_t key_idx, *free_slot = NULL; + BT_DBG("KeyUpdateFind, KeyIdx 0x%04x AppKey %u", key_idx, app_key); + for (i = 0; i < ARRAY_SIZE(key_updates); i++) { struct key_update *update = &key_updates[i]; @@ -2224,7 +2364,7 @@ void bt_mesh_store_subnet(struct bt_mesh_subnet *sub) struct key_update *free_slot = NULL; struct key_update *update = NULL; - BT_DBG("NetKeyIndex 0x%03x", sub->net_idx); + BT_DBG("StoreSubnetSchedule, NetIdx 0x%04x", sub->net_idx); update = key_update_find(false, sub->net_idx, &free_slot); if (update) { @@ -2234,6 +2374,7 @@ void bt_mesh_store_subnet(struct bt_mesh_subnet *sub) } if (!free_slot) { + BT_DBG("NoFreeSlotForSubnet"); store_net_key(sub); return; } @@ -2251,7 +2392,7 @@ void bt_mesh_store_app_key(struct bt_mesh_app_key *key) struct key_update *free_slot = NULL; struct key_update *update = NULL; - BT_DBG("AppKeyIndex 0x%03x", key->app_idx); + BT_DBG("StoreAppKeySchedule, AppIdx 0x%04x", key->app_idx); update = key_update_find(true, key->app_idx, &free_slot); if (update) { @@ -2261,6 +2402,7 @@ void bt_mesh_store_app_key(struct bt_mesh_app_key *key) } if (!free_slot) { + BT_DBG("NoFreeSlotForAppKey"); store_app_key(key); return; } @@ -2275,22 +2417,29 @@ void bt_mesh_store_app_key(struct bt_mesh_app_key *key) void bt_mesh_store_hb_pub(void) { + BT_DBG("StoreHbPubSchedule"); + schedule_store(BLE_MESH_HB_PUB_PENDING); } void bt_mesh_store_cfg(void) { + BT_DBG("StoreCfgSchedule"); + schedule_store(BLE_MESH_CFG_PENDING); } void bt_mesh_clear_role(void) { - BT_DBG("Clear device role"); + BT_DBG("ClearRole"); + bt_mesh_erase_core_settings("mesh/role"); } void bt_mesh_clear_net(void) { + BT_DBG("ClearNetSchedule"); + schedule_store(BLE_MESH_NET_PENDING); schedule_store(BLE_MESH_IV_PENDING); schedule_store(BLE_MESH_CFG_PENDING); @@ -2301,7 +2450,7 @@ void bt_mesh_clear_subnet(struct bt_mesh_subnet *sub) struct key_update *free_slot = NULL; struct key_update *update = NULL; - BT_DBG("NetKeyIndex 0x%03x", sub->net_idx); + BT_DBG("ClearSubnetSchedule, NetIdx 0x%04x", sub->net_idx); update = key_update_find(false, sub->net_idx, &free_slot); if (update) { @@ -2328,7 +2477,7 @@ void bt_mesh_clear_app_key(struct bt_mesh_app_key *key) struct key_update *free_slot = NULL; struct key_update *update = NULL; - BT_DBG("AppKeyIndex 0x%03x", key->app_idx); + BT_DBG("ClearAppKeySchedule, AppIdx 0x%04x", key->app_idx); update = key_update_find(true, key->app_idx, &free_slot); if (update) { @@ -2355,6 +2504,8 @@ void bt_mesh_clear_rpl_single(uint16_t src) char name[16] = {'\0'}; int err = 0; + BT_DBG("ClearRPLSingle, Src 0x%04x", src); + if (!BLE_MESH_ADDR_IS_UNICAST(src)) { BT_ERR("Invalid src 0x%04x", src); return; @@ -2371,39 +2522,53 @@ void bt_mesh_clear_rpl_single(uint16_t src) void bt_mesh_clear_rpl(void) { + BT_DBG("ClearRPLSchedule"); + schedule_store(BLE_MESH_RPL_PENDING); } void bt_mesh_store_mod_bind(struct bt_mesh_model *model) { + BT_DBG("StoreModBindSchedule"); + model->flags |= BLE_MESH_MOD_BIND_PENDING; schedule_store(BLE_MESH_MOD_PENDING); } void bt_mesh_store_mod_sub(struct bt_mesh_model *model) { + BT_DBG("StoreModSubSchedule"); + model->flags |= BLE_MESH_MOD_SUB_PENDING; schedule_store(BLE_MESH_MOD_PENDING); } void bt_mesh_store_mod_pub(struct bt_mesh_model *model) { + BT_DBG("StoreModPubSchedule"); + model->flags |= BLE_MESH_MOD_PUB_PENDING; schedule_store(BLE_MESH_MOD_PENDING); } void bt_mesh_store_label(void) { + BT_DBG("StoreLabelSchedule"); + schedule_store(BLE_MESH_VA_PENDING); } void bt_mesh_store_dkca(void) { + BT_DBG("StoreDkca"); + bt_mesh_save_core_settings("mesh/dkca", bt_mesh.dev_key_ca, sizeof(bt_mesh.dev_key_ca)); } void bt_mesh_clear_dkca(void) { + BT_DBG("ClearDkca"); + bt_mesh_erase_core_settings("mesh/dkca"); } @@ -2425,7 +2590,7 @@ void bt_mesh_store_prov_info(uint16_t primary_addr, uint16_t alloc_addr) { struct prov_info val = {0}; - BT_DBG("Primary address 0x%04x, next address allocation 0x%04x", primary_addr, alloc_addr); + BT_DBG("StoreProvInfo, PrimaryAddr 0x%04x AllocAddr 0x%04x", primary_addr, alloc_addr); val.primary_addr = primary_addr; val.alloc_addr = alloc_addr; @@ -2435,7 +2600,8 @@ void bt_mesh_store_prov_info(uint16_t primary_addr, uint16_t alloc_addr) void bt_mesh_clear_prov_info(void) { - BT_DBG("Clearing prov info"); + BT_DBG("ClearProvInfo"); + bt_mesh_erase_core_settings("mesh/p_prov"); } @@ -2445,6 +2611,9 @@ static void store_p_net_key(struct bt_mesh_subnet *sub) char name[16] = {'\0'}; int err = 0; + BT_DBG("StorePvnrNetKey, NetIdx 0x%04x KrFlag %u KrPhase %u", + sub->net_idx, sub->kr_flag, sub->kr_phase); + memcpy(&key.val[0], sub->keys[0].net, 16); memcpy(&key.val[1], sub->keys[1].net, 16); key.kr_flag = sub->kr_flag; @@ -2469,6 +2638,9 @@ static void store_p_app_key(struct bt_mesh_app_key *app) char name[16] = {'\0'}; int err = 0; + BT_DBG("StorePvnrAppKey, NetIdx 0x%04x AppIdx 0x%04x Updated %u", + app->net_idx, app->app_idx, app->updated); + key.net_idx = app->net_idx; key.updated = app->updated; memcpy(key.val[0], app->keys[0].val, 16); @@ -2489,7 +2661,7 @@ static void store_p_app_key(struct bt_mesh_app_key *app) void bt_mesh_store_p_net_idx(void) { - BT_DBG("Store, p_net_idx_next 0x%03x", bt_mesh.p_net_idx_next); + BT_DBG("StorePvnrNetIdx, NetIdxNext 0x%04x", bt_mesh.p_net_idx_next); bt_mesh_save_core_settings("mesh/p_netidx", (const uint8_t *)&bt_mesh.p_net_idx_next, sizeof(bt_mesh.p_net_idx_next)); @@ -2497,13 +2669,14 @@ void bt_mesh_store_p_net_idx(void) void bt_mesh_clear_p_net_idx(void) { - BT_DBG("Clearing NetKey Index"); + BT_DBG("ClearPvnrNetIdx"); + bt_mesh_erase_core_settings("mesh/p_netidx"); } void bt_mesh_store_p_app_idx(void) { - BT_DBG("Store, p_app_idx_next 0x%03x", bt_mesh.p_app_idx_next); + BT_DBG("StorePvnrAppIdx, AppIdxNext 0x%04x", bt_mesh.p_app_idx_next); bt_mesh_save_core_settings("mesh/p_appidx", (const uint8_t *)&bt_mesh.p_app_idx_next, sizeof(bt_mesh.p_app_idx_next)); @@ -2511,32 +2684,37 @@ void bt_mesh_store_p_app_idx(void) void bt_mesh_clear_p_app_idx(void) { - BT_DBG("Clearing AppKey Index"); + BT_DBG("ClearPvnrAppIdx"); + bt_mesh_erase_core_settings("mesh/p_appidx"); } void bt_mesh_store_p_subnet(struct bt_mesh_subnet *sub) { + BT_DBG("StorePvnrSubnet"); + if (sub == NULL) { BT_ERR("Invalid subnet"); return; } - BT_DBG("NetKeyIndex 0x%03x NetKey %s", sub->net_idx, - bt_hex(sub->keys[0].net, 16)); + BT_DBG("NetIdx 0x%04x NetKey %s", + sub->net_idx, bt_hex(sub->keys[0].net, 16)); store_p_net_key(sub); } void bt_mesh_store_p_app_key(struct bt_mesh_app_key *key) { + BT_DBG("StorePvnrAppKey"); + if (key == NULL) { BT_ERR("Invalid AppKey"); return; } - BT_DBG("AppKeyIndex 0x%03x AppKey %s", key->app_idx, - bt_hex(key->keys[0].val, 16)); + BT_DBG("AppIdx 0x%03x AppKey %s", + key->app_idx, bt_hex(key->keys[0].val, 16)); store_p_app_key(key); } @@ -2546,7 +2724,7 @@ void bt_mesh_clear_p_subnet(uint16_t net_idx) char name[16] = {'\0'}; int err = 0; - BT_DBG("NetKeyIndex 0x%03x", net_idx); + BT_DBG("ClearPvnrSubnet, NetIdx 0x%04x", net_idx); sprintf(name, "mesh/pnk/%04x", net_idx); bt_mesh_erase_core_settings(name); @@ -2562,7 +2740,7 @@ void bt_mesh_clear_p_app_key(uint16_t app_idx) char name[16] = {'\0'}; int err = 0; - BT_DBG("AppKeyIndex 0x%03x", app_idx); + BT_DBG("ClearPvnrAppKey, AppIdx 0x%04x", app_idx); sprintf(name, "mesh/pak/%04x", app_idx); bt_mesh_erase_core_settings(name); @@ -2579,11 +2757,17 @@ void bt_mesh_store_node_info(struct bt_mesh_node *node) char name[16] = {'\0'}; int err = 0; + BT_DBG("StoreNodeInfo"); + if (node == NULL) { BT_ERR("Invalid node info"); return; } + BT_DBG("UnicastAddr 0x%04x ElemNum %u NetIdx 0x%04x Flags %u IVIndex %lu", + node->unicast_addr, node->element_num, + node->net_idx, node->flags, node->iv_index); + memcpy(val.addr, node->addr, BLE_MESH_ADDR_LEN); val.addr_type = node->addr_type; memcpy(val.dev_uuid, node->dev_uuid, 16); @@ -2613,6 +2797,8 @@ static void clear_node(uint16_t addr) char name[16] = {'\0'}; int err = 0; + BT_DBG("ClearNode, Addr 0x%04x", addr); + /* Clear node information */ sprintf(name, "mesh/pn/%04x/i", addr); bt_mesh_erase_core_settings(name); @@ -2633,13 +2819,13 @@ static void clear_node(uint16_t addr) void bt_mesh_clear_node_info(uint16_t unicast_addr) { + BT_DBG("ClearNodeInfo, Addr 0x%04x", unicast_addr); + if (!BLE_MESH_ADDR_IS_UNICAST(unicast_addr)) { BT_ERR("Invalid unicast address 0x%04x", unicast_addr); return; } - BT_DBG("Unicast address 0x%04x", unicast_addr); - clear_node(unicast_addr); } @@ -2649,11 +2835,15 @@ void bt_mesh_store_node_name(struct bt_mesh_node *node) char name[16] = {'\0'}; int err = 0; + BT_DBG("StoreNodeName"); + if (node == NULL) { BT_ERR("Invalid node info"); return; } + BT_DBG("UnicastAddr 0x%04x NodeName %s", node->unicast_addr, node->name); + strncpy(node_name, node->name, BLE_MESH_NODE_NAME_SIZE + 1); sprintf(name, "mesh/pn/%04x/n", node->unicast_addr); @@ -2668,11 +2858,15 @@ void bt_mesh_store_node_comp_data(struct bt_mesh_node *node) char name[16] = {'\0'}; int err = 0; + BT_DBG("StoreNodeCompData"); + if (!node || !node->comp_data || node->comp_length == 0U) { BT_ERR("Invalid node info"); return; } + BT_DBG("UnicastAddr 0x%04x CompLength %u", node->unicast_addr, node->comp_length); + sprintf(name, "mesh/pn/%04x/c", node->unicast_addr); err = bt_mesh_save_core_settings(name, (const uint8_t *)node->comp_data, node->comp_length); if (err) { @@ -2683,12 +2877,16 @@ void bt_mesh_store_node_comp_data(struct bt_mesh_node *node) int settings_core_init(void) { + BT_DBG("SettingsCoreInit"); + k_delayed_work_init(&pending_store, store_pending); return 0; } int bt_mesh_settings_init(void) { + BT_DBG("SettingsInit"); + bt_mesh_settings_mutex_new(); bt_mesh_settings_init_foreach(); return 0; @@ -2697,12 +2895,16 @@ int bt_mesh_settings_init(void) #if CONFIG_BLE_MESH_DEINIT int settings_core_deinit(void) { + BT_DBG("SettingsCoreDeinit"); + k_delayed_work_free(&pending_store); return 0; } int settings_core_erase(void) { + BT_DBG("SettingsCoreErase"); + /* Erase here must not use the pending_store timer. * This is used for erasing the information which * could not be erased during the previous deinit @@ -2716,6 +2918,8 @@ int settings_core_erase(void) int bt_mesh_settings_deinit(bool erase) { + BT_DBG("SettingsDeinit, Erase %u", erase); + bt_mesh_settings_deinit_foreach(erase); bt_mesh_settings_mutex_free(); return 0; @@ -2724,6 +2928,8 @@ int bt_mesh_settings_deinit(bool erase) void bt_mesh_settings_reset(bool erase) { + BT_DBG("SettingsReset, Erase %u", erase); + k_delayed_work_cancel(&pending_store); if (erase) { bt_mesh_clear_net(); diff --git a/components/bt/esp_ble_mesh/core/storage/settings_nvs.c b/components/bt/esp_ble_mesh/core/storage/settings_nvs.c index ca3ac144ef5..f539c0a35af 100644 --- a/components/bt/esp_ble_mesh/core/storage/settings_nvs.c +++ b/components/bt/esp_ble_mesh/core/storage/settings_nvs.c @@ -17,7 +17,7 @@ enum settings_type { SETTINGS_CORE, #if CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE SETTINGS_UID, -#endif +#endif /* CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE */ }; struct settings_context { @@ -62,15 +62,20 @@ static struct settings_context settings_ctx[] = { int bt_mesh_settings_nvs_open(const char* name, bt_mesh_nvs_handle_t *handle) { + assert(name); + BT_DBG("SettingsNVSOpen, Name %s", name); + #if CONFIG_BLE_MESH_SPECIFIC_PARTITION return nvs_open_from_partition(CONFIG_BLE_MESH_PARTITION_NAME, name, NVS_READWRITE, handle); -#else +#else /* CONFIG_BLE_MESH_SPECIFIC_PARTITION */ return nvs_open(name, NVS_READWRITE, handle); -#endif +#endif /* CONFIG_BLE_MESH_SPECIFIC_PARTITION */ } void bt_mesh_settings_nvs_close(bt_mesh_nvs_handle_t handle) { + BT_DBG("SettingsNVSClose, Handle %lu", handle); + nvs_close(handle); } @@ -79,6 +84,8 @@ void bt_mesh_settings_init_foreach(void) int err = 0; int i; + BT_DBG("SettingsInitForeach"); + #if CONFIG_BLE_MESH_SPECIFIC_PARTITION err = nvs_flash_init_partition(CONFIG_BLE_MESH_PARTITION_NAME); if (err != ESP_OK) { @@ -134,6 +141,8 @@ void bt_mesh_settings_deinit_foreach(bool erase) { int i; + BT_DBG("SettingsDeinitForeach, Erase %u", erase); + for (i = 0; i < ARRAY_SIZE(settings_ctx); i++) { struct settings_context *ctx = &settings_ctx[i]; @@ -152,7 +161,7 @@ void bt_mesh_settings_deinit_foreach(bool erase) #if CONFIG_BLE_MESH_SPECIFIC_PARTITION nvs_flash_deinit_partition(CONFIG_BLE_MESH_PARTITION_NAME); -#endif +#endif /* CONFIG_BLE_MESH_SPECIFIC_PARTITION */ } #endif /* CONFIG_BLE_MESH_DEINIT */ @@ -161,6 +170,8 @@ int bt_mesh_settings_direct_open(bt_mesh_nvs_handle_t *handle) int err = 0; int i; + BT_DBG("SettingsDirectOpen"); + #if CONFIG_BLE_MESH_SPECIFIC_PARTITION err = nvs_flash_init_partition(CONFIG_BLE_MESH_PARTITION_NAME); if (err != ESP_OK) { @@ -178,6 +189,8 @@ int bt_mesh_settings_direct_open(bt_mesh_nvs_handle_t *handle) return -EIO; } + BT_DBG("%u: NVSName %s Handle %lu", i, ctx->nvs_name, ctx->handle); + if (i == SETTINGS_CORE && handle) { *handle = ctx->handle; } @@ -190,25 +203,30 @@ void bt_mesh_settings_direct_close(void) { int i; + BT_DBG("SettingsDirectClose"); + for (i = 0; i < ARRAY_SIZE(settings_ctx); i++) { bt_mesh_settings_nvs_close(settings_ctx[i].handle); } #if CONFIG_BLE_MESH_SPECIFIC_PARTITION nvs_flash_deinit_partition(CONFIG_BLE_MESH_PARTITION_NAME); -#endif +#endif /* CONFIG_BLE_MESH_SPECIFIC_PARTITION */ } /* API used to get BLE Mesh related nvs handle */ static inline bt_mesh_nvs_handle_t settings_get_nvs_handle(enum settings_type type) { + BT_DBG("SettingsGetNVSHandle, Type %u", type); + #if CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE if (type == SETTINGS_CORE) { extern bt_mesh_nvs_handle_t get_core_settings_handle(void); return get_core_settings_handle(); } -#endif +#endif /* CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE */ + return settings_ctx[type].handle; } @@ -218,12 +236,8 @@ static int settings_save(bt_mesh_nvs_handle_t handle, const char *key, const uin { int err = 0; - if (key == NULL) { - BT_ERR("%s, Invalid parameter", __func__); - return -EINVAL; - } - - BT_DBG("nvs %s, key %s", val ? "set" : "erase", key); + BT_DBG("Settings%s, Handle %lu Len %lu Key %s", + val ? "Store" : "Erase", handle, len, key); if (val) { err = nvs_set_blob(handle, key, val, len); @@ -236,7 +250,7 @@ static int settings_save(bt_mesh_nvs_handle_t handle, const char *key, const uin } if (err != ESP_OK) { BT_ERR("Failed to %s %s data (err %d)", - val ? "set" : "erase", key, err); + val ? "set" : "erase", key, err); return -EIO; } @@ -262,6 +276,10 @@ int bt_mesh_save_settings(bt_mesh_nvs_handle_t handle, const char *key, int bt_mesh_save_core_settings(const char *key, const uint8_t *val, size_t len) { bt_mesh_nvs_handle_t handle = settings_get_nvs_handle(SETTINGS_CORE); + + assert(key); + BT_DBG("SaveCoreSettings, Handle %lu Len %lu Key %s", handle, len, key); + return bt_mesh_save_settings(handle, key, val, len); } @@ -269,26 +287,39 @@ int bt_mesh_save_core_settings(const char *key, const uint8_t *val, size_t len) int bt_mesh_save_uid_settings(const char *key, const uint8_t *val, size_t len) { bt_mesh_nvs_handle_t handle = settings_get_nvs_handle(SETTINGS_UID); + + assert(key); + BT_DBG("SaveUIDSettings, Handle %lu Len %lu Key %s", handle, len, key); + return bt_mesh_save_settings(handle, key, val, len); } -#endif +#endif /* CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE */ int bt_mesh_erase_settings(bt_mesh_nvs_handle_t handle, const char *key) { + assert(key); + BT_DBG("EraseSettings, Handle %lu Key %s", handle, key); + return bt_mesh_save_settings(handle, key, NULL, 0); } int bt_mesh_erase_core_settings(const char *key) { + assert(key); + BT_DBG("EraseCoreSettings, Key %s", key); + return bt_mesh_save_core_settings(key, NULL, 0); } #if CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE int bt_mesh_erase_uid_settings(const char *name) { + assert(name); + BT_DBG("EraseUIDSettings, Name %s", name); + return bt_mesh_save_uid_settings(name, NULL, 0); } -#endif +#endif /* CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE */ /* API used to load BLE Mesh related settings */ @@ -297,10 +328,9 @@ static int settings_load(bt_mesh_nvs_handle_t handle, const char *key, { int err = 0; - if (key == NULL || buf == NULL || exist == NULL) { - BT_ERR("%s, Invalid parameter", __func__); - return -EINVAL; - } + BT_DBG("SettingsLoad, Handle %lu Key %s", handle, key); + + assert(buf && exist); err = nvs_get_blob(handle, key, buf, &buf_len); if (err != ESP_OK) { @@ -331,6 +361,10 @@ int bt_mesh_load_settings(bt_mesh_nvs_handle_t handle, const char *key, int bt_mesh_load_core_settings(const char *key, uint8_t *buf, size_t buf_len, bool *exist) { bt_mesh_nvs_handle_t handle = settings_get_nvs_handle(SETTINGS_CORE); + + assert(key); + BT_DBG("LoadCoreSettings, Handle %lu Key %s", handle, key); + return bt_mesh_load_settings(handle, key, buf, buf_len, exist); } @@ -338,9 +372,13 @@ int bt_mesh_load_core_settings(const char *key, uint8_t *buf, size_t buf_len, bo int bt_mesh_load_uid_settings(const char *key, uint8_t *buf, size_t buf_len, bool *exist) { bt_mesh_nvs_handle_t handle = settings_get_nvs_handle(SETTINGS_UID); + + assert(key); + BT_DBG("LoadUIDSettings, Handle %lu Key %s", handle, key); + return bt_mesh_load_settings(handle, key, buf, buf_len, exist); } -#endif +#endif /* CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE */ /* API used to get length of BLE Mesh related settings */ @@ -349,10 +387,7 @@ static size_t settings_get_length(bt_mesh_nvs_handle_t handle, const char *key) size_t len = 0U; int err = 0; - if (key == NULL) { - BT_ERR("%s, Invalid parameter", __func__); - return 0; - } + BT_DBG("SettingsGetLength, Handle %lu Key %s", handle, key); err = nvs_get_blob(handle, key, NULL, &len); if (err != ESP_OK) { @@ -362,6 +397,8 @@ static size_t settings_get_length(bt_mesh_nvs_handle_t handle, const char *key) return 0; } + BT_DBG("Len %lu", len); + return len; } @@ -419,6 +456,10 @@ struct net_buf_simple *bt_mesh_get_settings_item(bt_mesh_nvs_handle_t handle, co struct net_buf_simple *bt_mesh_get_core_settings_item(const char *key) { bt_mesh_nvs_handle_t handle = settings_get_nvs_handle(SETTINGS_CORE); + + assert(key); + BT_DBG("GetCoreSettingsItem, Handle %lu Key %s", handle, key); + return bt_mesh_get_settings_item(handle, key); } @@ -426,9 +467,13 @@ struct net_buf_simple *bt_mesh_get_core_settings_item(const char *key) struct net_buf_simple *bt_mesh_get_uid_settings_item(const char *key) { bt_mesh_nvs_handle_t handle = settings_get_nvs_handle(SETTINGS_UID); + + assert(key); + BT_DBG("GetUIDSettingsItem, Handle %lu Key %s", handle, key); + return bt_mesh_get_settings_item(handle, key); } -#endif +#endif /* CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE */ /* API used to check if the settings item exists */ @@ -438,6 +483,8 @@ bool bt_mesh_is_settings_item_exist(struct net_buf_simple *buf, const uint16_t v size_t length = 0U; int i; + BT_DBG("IsSettingsItemExist, Val 0x%04x", val); + if (!buf) { return false; } @@ -508,6 +555,10 @@ int bt_mesh_add_settings_item(bt_mesh_nvs_handle_t handle, const char *key, cons int bt_mesh_add_core_settings_item(const char *key, const uint16_t val) { bt_mesh_nvs_handle_t handle = settings_get_nvs_handle(SETTINGS_CORE); + + assert(key); + BT_DBG("AddCoreSettingsItem, Handle %lu Val 0x%04x Key %s", handle, val, key); + return bt_mesh_add_settings_item(handle, key, val); } @@ -515,9 +566,13 @@ int bt_mesh_add_core_settings_item(const char *key, const uint16_t val) int bt_mesh_add_uid_settings_item(const char *key, const uint16_t val) { bt_mesh_nvs_handle_t handle = settings_get_nvs_handle(SETTINGS_UID); + + assert(key); + BT_DBG("AddUIDSettingsItem, Handle %lu Val 0x%04x Key %s", handle, val, key); + return bt_mesh_add_settings_item(handle, key, val); } -#endif +#endif /* CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE */ /* API used to remove the settings item */ @@ -580,6 +635,10 @@ int bt_mesh_remove_settings_item(bt_mesh_nvs_handle_t handle, const char *key, c int bt_mesh_remove_core_settings_item(const char *key, const uint16_t val) { bt_mesh_nvs_handle_t handle = settings_get_nvs_handle(SETTINGS_CORE); + + assert(key); + BT_DBG("RemoveCoreSettingsItem, Val 0x%04x Key %s", val, key); + return bt_mesh_remove_settings_item(handle, key, val); } @@ -587,14 +646,21 @@ int bt_mesh_remove_core_settings_item(const char *key, const uint16_t val) int bt_mesh_remove_uid_settings_item(const char *key, const uint16_t val) { bt_mesh_nvs_handle_t handle = settings_get_nvs_handle(SETTINGS_UID); + + assert(key); + BT_DBG("RemoveUIDSettingsItem, Val 0x%04x Key %s", val, key); + return bt_mesh_remove_settings_item(handle, key, val); } -#endif +#endif /* CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE */ int bt_mesh_settings_erase_key(bt_mesh_nvs_handle_t handle, const char *key) { int err = 0; + assert(key); + BT_DBG("SettingsEraseKey, Handle %lu Key %s", handle, key); + err = nvs_erase_key(handle, key); if (err != ESP_OK) { if (err == ESP_ERR_NVS_NOT_FOUND) { @@ -618,6 +684,8 @@ int bt_mesh_settings_erase_all(bt_mesh_nvs_handle_t handle) { int err = 0; + BT_DBG("SettingsEraseAll, Handle %lu", handle); + err = nvs_erase_all(handle); if (err != ESP_OK) { BT_ERR("Failed to erase all (err %d)", err); @@ -632,4 +700,5 @@ int bt_mesh_settings_erase_all(bt_mesh_nvs_handle_t handle) return 0; } + #endif /* CONFIG_BLE_MESH_SETTINGS */ diff --git a/components/bt/esp_ble_mesh/core/storage/settings_uid.c b/components/bt/esp_ble_mesh/core/storage/settings_uid.c index 8fcfe54c636..e1de639722e 100644 --- a/components/bt/esp_ble_mesh/core/storage/settings_uid.c +++ b/components/bt/esp_ble_mesh/core/storage/settings_uid.c @@ -38,15 +38,22 @@ static int settings_direct_erase(uint8_t index); static inline bool settings_uid_empty(struct settings_uid *uid) { - return (uid->id[0] == '\0') ? true : false; + bool empty = (uid->id[0] == '\0') ? true : false; + + BT_DBG("SettingsUIDEmpty, Empty %u", empty); + + return empty; } bt_mesh_nvs_handle_t get_core_settings_handle(void) { int i; + BT_DBG("GetCoreSettingsHandle"); + for (i = 0; i < ARRAY_SIZE(user_ids); i++) { if (user_ids[i].open) { + BT_DBG("I %u Handle %lu", i, user_ids[i].handle); return user_ids[i].handle; } } @@ -59,6 +66,8 @@ int settings_uid_init(void) { int i; + BT_DBG("SettingsUIDInit"); + for (i = 0; i < ARRAY_SIZE(user_ids); i++) { memset(&user_ids[i], 0, sizeof(struct settings_uid)); user_ids[i].handle = INVALID_SETTINGS_HANDLE; @@ -76,6 +85,8 @@ int settings_uid_load(void) int err = 0; int i; + BT_DBG("SettingsUIDLoad"); + /* Before using user id to search settings, we need to * restore all the settings user_ids properly. */ @@ -114,6 +125,8 @@ int settings_uid_deinit(bool erase) { int i; + BT_DBG("SettingsUIDDeinit, Erase %u", erase); + for (i = 0; i < ARRAY_SIZE(user_ids); i++) { memset(&user_ids[i], 0, offsetof(struct settings_uid, handle)); /* Can not reset handle here, since it will be used @@ -128,6 +141,8 @@ int settings_uid_erase(void) { int i; + BT_DBG("SettingsUIDErase"); + for (i = 0; i < ARRAY_SIZE(user_ids); i++) { if (user_ids[i].open == true) { /* When a nvs namespace is open, which means it is @@ -158,6 +173,8 @@ static int settings_direct_erase(uint8_t index) char name[16] = {'\0'}; int err = 0; + BT_DBG("SettingsDirectErase, Index %u", index); + sprintf(name, "%s_%02x", "mesh_core", index); /* Get handle for core settings */ @@ -191,6 +208,8 @@ static uint8_t settings_index_get(const char *id, uint8_t *index) uint8_t idx = 0; int i; + BT_DBG("SettingsIndexGet"); + for (i = 0; i < ARRAY_SIZE(user_ids); i++) { if (strlen(user_ids[i].id) != strlen(id)) { continue; @@ -206,6 +225,8 @@ static uint8_t settings_index_get(const char *id, uint8_t *index) idx = INVALID_SETTINGS_INDEX; } + BT_DBG("Index %u", idx); + if (index) { *index = idx; } @@ -219,6 +240,8 @@ static int settings_open(uint8_t index) int err = 0; int i; + BT_DBG("SettingsOpen, Index %u UID %s", index, uid->id); + /* Check if the nvs namespace is already open */ if (uid->open == true) { BT_WARN("Settings already open, index %d", index); @@ -251,8 +274,6 @@ static int settings_open(uint8_t index) sprintf(uid->id, "%04x", index); } - BT_INFO("Open settings, index %d, uid %s", index, uid->id); - sprintf(name, "mesh/id/%04x", index); err = bt_mesh_save_uid_settings(name, (const uint8_t *)uid->id, SETTINGS_UID_SIZE); if (err) { @@ -288,6 +309,8 @@ static int settings_open(uint8_t index) int bt_mesh_provisioner_open_settings_with_index(uint8_t index) { + BT_DBG("PvnrOpenSettingsWithIndex, Index %u", index); + if (index >= ARRAY_SIZE(user_ids)) { BT_ERR("Invalid settings index %d", index); return -EINVAL; @@ -301,6 +324,8 @@ int bt_mesh_provisioner_open_settings_with_uid(const char *id, uint8_t *index) uint8_t idx = 0; int i; + BT_DBG("PvnrOpenSettingsWithUID"); + if (!id || strlen(id) > SETTINGS_UID_SIZE) { BT_ERR("Invalid settings uid"); return -EINVAL; @@ -328,6 +353,8 @@ int bt_mesh_provisioner_open_settings_with_uid(const char *id, uint8_t *index) idx = i; } + BT_DBG("Index %u", idx); + return settings_open(idx); } @@ -337,13 +364,14 @@ static int settings_close(uint8_t index, bool erase) char name[16] = {'\0'}; int err = 0; + BT_DBG("SettingsClose"); + BT_DBG("Index %u Erase %u UID %s", index, erase, uid->id); + if (uid->open == false) { BT_ERR("Settings not open, index %d", index); return -EIO; } - BT_INFO("Close settings, index %d, uid %s", index, uid->id); - /* Disable Provisioner firstly */ err = bt_mesh_provisioner_disable(BLE_MESH_PROV_ADV | BLE_MESH_PROV_GATT); if (err && err != -EALREADY) { @@ -378,6 +406,8 @@ static int settings_close(uint8_t index, bool erase) int bt_mesh_provisioner_close_settings_with_index(uint8_t index, bool erase) { + BT_DBG("PvnrCloseSettingsWithIndex, Index %u Erase %u", index, erase); + if (index >= ARRAY_SIZE(user_ids)) { BT_ERR("Invalid settings index %d", index); return -EINVAL; @@ -390,6 +420,8 @@ int bt_mesh_provisioner_close_settings_with_uid(const char *id, bool erase, uint { uint8_t idx = 0; + BT_DBG("PvnrCloseSettingsWithUID, Erase %u", erase); + if (!id || strlen(id) > SETTINGS_UID_SIZE) { BT_ERR("Invalid settings uid"); return -EINVAL; @@ -401,6 +433,8 @@ int bt_mesh_provisioner_close_settings_with_uid(const char *id, bool erase, uint return -ENODEV; } + BT_DBG("Index %u ID %s", idx, id); + return settings_close(idx, erase); } @@ -412,13 +446,13 @@ static int settings_delete(uint8_t index) */ struct settings_uid *uid = &user_ids[index]; + BT_DBG("SettingsDelete, Index %u UID %s", index, uid->id); + if (uid->open == true) { BT_ERR("Settings being used, index %d", index); return -EBUSY; } - BT_INFO("Delete settings, index %d, uid %s", index, uid->id); - settings_direct_erase(index); memset(uid, 0, sizeof(struct settings_uid)); @@ -429,6 +463,8 @@ static int settings_delete(uint8_t index) int bt_mesh_provisioner_delete_settings_with_index(uint8_t index) { + BT_DBG("PvnrDeleteSettingsWithIndex, Index %u", index); + if (index >= ARRAY_SIZE(user_ids)) { BT_ERR("Invalid settings index %d", index); return -EINVAL; @@ -441,6 +477,8 @@ int bt_mesh_provisioner_delete_settings_with_uid(const char *id, uint8_t *index) { uint8_t idx = 0; + BT_DBG("PvnrDeleteSettingsWithUID"); + if (!id || strlen(id) > SETTINGS_UID_SIZE) { BT_ERR("Invalid settings uid"); return -EINVAL; @@ -452,16 +490,22 @@ int bt_mesh_provisioner_delete_settings_with_uid(const char *id, uint8_t *index) return -ENODEV; } + BT_DBG("Index %u ID %s", idx, id); + return settings_delete(idx); } const char *bt_mesh_provisioner_get_settings_uid(uint8_t index) { + BT_DBG("PvnrGetSettingsUID, Index %u", index); + if (index >= ARRAY_SIZE(user_ids)) { BT_ERR("Invalid settings index %d", index); return NULL; } + BT_DBG("ID %s", user_ids[index].id); + return user_ids[index].id; } @@ -469,6 +513,8 @@ uint8_t bt_mesh_provisioner_get_settings_index(const char *id) { uint8_t idx = 0; + BT_DBG("PvnrGetSettingsIndex"); + if (!id || strlen(id) > SETTINGS_UID_SIZE) { BT_ERR("Invalid settings uid"); return INVALID_SETTINGS_INDEX; @@ -479,6 +525,8 @@ uint8_t bt_mesh_provisioner_get_settings_index(const char *id) BT_ERR("Settings uid %s not exists", id); } + BT_DBG("Index %u ID %s", idx, id); + return idx; } @@ -487,12 +535,16 @@ uint8_t bt_mesh_provisioner_get_free_settings_count(void) uint8_t count = 0; int i; + BT_DBG("PvnrGetFreeSettingsCount"); + for (i = 0; i < ARRAY_SIZE(user_ids); i++) { if (settings_uid_empty(&user_ids[i])) { count++; } } + BT_DBG("Count %u", count); + return count; } #endif /* CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE */ @@ -503,6 +555,8 @@ int bt_mesh_provisioner_direct_erase_settings(void) bt_mesh_nvs_handle_t handle = 0; int err = 0; + BT_DBG("PvnrDirectEraseSettings"); + err = bt_mesh_settings_direct_open(&handle); if (err) { return err; @@ -514,9 +568,9 @@ int bt_mesh_provisioner_direct_erase_settings(void) } bt_mesh_erase_uid_settings("mesh/uid"); -#else +#else /* CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE */ err = bt_mesh_settings_erase_all(handle); -#endif +#endif /* CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE */ bt_mesh_settings_direct_close(); return err; diff --git a/components/bt/esp_ble_mesh/core/test.c b/components/bt/esp_ble_mesh/core/test.c index 3d3cc3bbd90..6433f9c0d4c 100644 --- a/components/bt/esp_ble_mesh/core/test.c +++ b/components/bt/esp_ble_mesh/core/test.c @@ -41,6 +41,8 @@ int bt_mesh_device_auto_enter_network(struct bt_mesh_device_network_info *info) int i, j, k; int err = 0; + BT_DBG("DeviceAutoEnterNetwork"); + if (info == NULL || !BLE_MESH_ADDR_IS_UNICAST(info->unicast_addr) || !BLE_MESH_ADDR_IS_GROUP(info->group_addr)) { return -EINVAL; @@ -139,6 +141,8 @@ int bt_mesh_test_update_white_list(struct bt_mesh_white_list *wl) { int err = 0; + BT_DBG("TestUpdateWhiteList"); + if (wl == NULL) { BT_ERR("%s, Invalid parameter", __func__); return -EINVAL; @@ -157,7 +161,7 @@ int bt_mesh_test_update_white_list(struct bt_mesh_white_list *wl) int bt_mesh_test_start_scanning(bool wl_en) { - BT_INFO("Scan with filter policy %s", wl_en ? "enabled" : "disabled"); + BT_DBG("TestStartScanning, wl_en %u", wl_en); if (wl_en) { return bt_mesh_scan_with_wl_enable(); @@ -168,6 +172,8 @@ int bt_mesh_test_start_scanning(bool wl_en) int bt_mesh_test_stop_scanning(void) { + BT_DBG("TestStopScanning"); + return bt_mesh_scan_disable(); } #endif /* CONFIG_BLE_MESH_TEST_USE_WHITE_LIST */ @@ -181,6 +187,8 @@ void bt_mesh_test_register_net_pdu_cb(bt_mesh_test_net_pdu_cb_t cb) void bt_mesh_test_set_seq(uint32_t seq) { + BT_DBG("TestSetSeq, Seq 0x%06x", seq); + if (seq > 0xFFFFFF) { BT_ERR("Invalid SEQ 0x%08x", seq); return; diff --git a/components/bt/esp_ble_mesh/core/transport.c b/components/bt/esp_ble_mesh/core/transport.c index 797ff2a1ad3..62704ccfa8b 100644 --- a/components/bt/esp_ble_mesh/core/transport.c +++ b/components/bt/esp_ble_mesh/core/transport.c @@ -29,7 +29,7 @@ #if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" -#endif +#endif /* CONFIG_BLE_MESH_V11_SUPPORT */ /* The transport layer needs at least three buffers for itself to avoid * deadlocks. Ensure that there are a sufficient number of advertising @@ -58,24 +58,24 @@ _Static_assert(CONFIG_BLE_MESH_ADV_BUF_COUNT >= (CONFIG_BLE_MESH_TX_SEG_MAX + 3) /* Number of retransmit attempts (after the initial transmit) per segment */ #define SEG_RETRANSMIT_ATTEMPTS 4 +/* How long to wait for available buffers before giving up */ +#define BUF_TIMEOUT K_NO_WAIT + /* "This timer shall be set to a minimum of 200 + 50 * TTL milliseconds.". * We use 400 since 300 is a common send duration for standard HCI, and we * need to have a timeout that's bigger than that. */ #define SEG_RETRANSMIT_TIMEOUT_UNICAST(tx) (K_MSEC(400) + 50 * (tx)->ttl) + /* When sending to a group, the messages are not acknowledged, and there's no * reason to delay the repetitions significantly. Delaying by more than 0 ms * to avoid flooding the network. */ #define SEG_RETRANSMIT_TIMEOUT_GROUP K_MSEC(50) -#define SEG_RETRANSMIT_TIMEOUT(tx) \ - (BLE_MESH_ADDR_IS_UNICAST((tx)->dst) ? \ - SEG_RETRANSMIT_TIMEOUT_UNICAST(tx) : \ - SEG_RETRANSMIT_TIMEOUT_GROUP) - -/* How long to wait for available buffers before giving up */ -#define BUF_TIMEOUT K_NO_WAIT +#define SEG_RETRANSMIT_TIMEOUT(tx) (BLE_MESH_ADDR_IS_UNICAST((tx)->dst) ? \ + SEG_RETRANSMIT_TIMEOUT_UNICAST(tx) : \ + SEG_RETRANSMIT_TIMEOUT_GROUP) struct seg_info { uint8_t ctl:1; /* Control message */ @@ -160,6 +160,8 @@ static inline void bt_mesh_seg_rx_unlock(void) uint8_t bt_mesh_get_seg_rtx_num(void) { + BT_DBG("SegRTXNum %u", SEG_RETRANSMIT_ATTEMPTS); + return SEG_RETRANSMIT_ATTEMPTS; } @@ -174,6 +176,9 @@ int32_t bt_mesh_get_seg_rtx_timeout(uint16_t dst, uint8_t ttl) struct seg_tx tx = { .ttl = ttl, }; + + BT_DBG("SegRTXTimeout, TTL %u", ttl); + return SEG_RETRANSMIT_TIMEOUT_UNICAST(&tx); } @@ -184,8 +189,10 @@ static int send_unseg(struct bt_mesh_net_tx *tx, struct net_buf_simple *sdu, struct net_buf *buf = NULL; enum bt_mesh_adv_type adv_type = BLE_MESH_ADV_DATA; - BT_DBG("src 0x%04x dst 0x%04x app_idx 0x%04x sdu_len %u", - tx->src, tx->ctx->addr, tx->ctx->app_idx, sdu->len); + BT_DBG("SendUnseg"); + BT_DBG("Src 0x%04x Dst 0x%04x AppIdx 0x%04x CtlOp 0x%02x SduLen %u", + tx->src, tx->ctx->addr, tx->ctx->app_idx, + ctl_op ? *ctl_op : 0xFF, sdu->len); #if CONFIG_BLE_MESH_EXT_ADV #if CONFIG_BLE_MESH_LONG_PACKET @@ -240,13 +247,14 @@ static int send_unseg(struct bt_mesh_net_tx *tx, struct net_buf_simple *sdu, if (!bt_mesh_friend_queue_has_space(tx->sub->net_idx, tx->src, tx->ctx->addr, NULL, 1)) { + BT_WARN("NoSpaceInFrndQueue, SegCount 1"); + if (BLE_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) { - BT_ERR("Not enough space in Friend Queue"); + BT_ERR("NotSentToUnicast"); net_buf_unref(buf); return -ENOBUFS; } - BT_WARN("No space in Friend Queue"); goto send; } @@ -256,6 +264,8 @@ static int send_unseg(struct bt_mesh_net_tx *tx, struct net_buf_simple *sdu, /* PDUs for a specific Friend should only go * out through the Friend Queue. */ + BT_DBG("FrndTxEnqueued, SegCount 1"); + net_buf_unref(buf); send_cb_finalize(cb, cb_data); return 0; @@ -268,19 +278,25 @@ send: static inline uint8_t seg_len(struct seg_info *si) { + uint8_t len = 0; + if (si->ctl) { - return + len = #if CONFIG_BLE_MESH_LONG_PACKET si->long_pkt ? BLE_MESH_EXT_CTL_SEG_SDU_MAX : #endif BLE_MESH_CTL_SEG_SDU_MAX; + } else { + len = +#if CONFIG_BLE_MESH_LONG_PACKET + si->long_pkt ? BLE_MESH_EXT_APP_SEG_SDU_MAX : +#endif + BLE_MESH_APP_SEG_SDU_MAX; } - return -#if CONFIG_BLE_MESH_LONG_PACKET - si->long_pkt ? BLE_MESH_EXT_APP_SEG_SDU_MAX : -#endif - BLE_MESH_APP_SEG_SDU_MAX; + BT_DBG("SegLen %u", len); + + return len; } bool bt_mesh_tx_in_progress(void) @@ -289,15 +305,18 @@ bool bt_mesh_tx_in_progress(void) for (i = 0; i < ARRAY_SIZE(seg_tx); i++) { if (seg_tx[i].nack_count) { + BT_DBG("SegTxInProgress"); return true; } } + BT_DBG("SegTxNotInProgress"); return false; } static void seg_tx_done(struct seg_tx *tx, uint8_t seg_idx) { + BT_DBG("SegTxDone, SegIdx %u", seg_idx); /* If the data is sent to itself, then last seg's ref count be equal to 3 */ if (((IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) || (IS_ENABLED(CONFIG_BLE_MESH_PROVISIONER) && bt_mesh_is_provisioner_en())) && @@ -307,15 +326,17 @@ static void seg_tx_done(struct seg_tx *tx, uint8_t seg_idx) bt_mesh_adv_buf_ref_debug(__func__, tx->seg[seg_idx], 3U, BLE_MESH_BUF_REF_SMALL); } - /** - * When cancelling a segment that is still in the adv sending queue, `tx->seg_pending` - * must else be decremented by one. More detailed information - * can be found in BLEMESH24-26. + /* When cancelling a segment that is still in the adv sending queue, + * the `tx->seg_pending` must be decremented by one. + * More details could be found in BLEMESH24-26. */ if (bt_mesh_atomic_cas(&BLE_MESH_ADV_BUSY(tx->seg[seg_idx]), 1, 0)) { + BT_DBG("SegPendingDec %u", tx->seg_pending); tx->seg_pending--; } + BT_DBG("NackCountDec %u", tx->nack_count); + net_buf_unref(tx->seg[seg_idx]); tx->seg[seg_idx] = NULL; tx->nack_count--; @@ -325,6 +346,8 @@ static void seg_tx_reset(struct seg_tx *tx) { int i; + BT_DBG("SegTxReset"); + bt_mesh_seg_tx_lock(tx); k_delayed_work_cancel(&tx->rtx_timer); @@ -349,6 +372,7 @@ static void seg_tx_reset(struct seg_tx *tx) if (bt_mesh_atomic_test_and_clear_bit(bt_mesh.flags, BLE_MESH_IVU_PENDING)) { BT_DBG("Proceeding with pending IV Update"); + /* bt_mesh_net_iv_update() will re-enable the flag if this * wasn't the only transfer. */ @@ -363,6 +387,8 @@ static inline void seg_tx_complete(struct seg_tx *tx, int err) const struct bt_mesh_send_cb *cb = tx->cb; void *cb_data = tx->cb_data; + BT_DBG("SegTxComplete, Err %d", err); + seg_tx_reset(tx); /* TODO: notify the completion of sending segmented message */ @@ -374,29 +400,36 @@ static inline void seg_tx_complete(struct seg_tx *tx, int err) static void schedule_retransmit(struct seg_tx *tx) { - /* It's possible that a segment broadcast hasn't finished, - * but the tx are already released. Only the seg_pending - * of this segment remains unprocessed. So, here, we - * determine if the tx are released by checking if the - * destination (dst) is unassigned, and then process - * the seg_pending of this segment. + /* It's possible that a segment broadcast hasn't finished, but the tx + * has already been released. Only the seg_pending of this segment + * remains unprocessed. + * So, here we determine if the tx are released by checking if the + * destination (dst) is unassigned, and then process the seg_pending + * of this segment. * See BLEMESH25-92 for details */ + BT_DBG("ScheduleRetransmit, Dst 0x%04x", tx->dst); + bt_mesh_seg_tx_lock(tx); if (tx->dst == BLE_MESH_ADDR_UNASSIGNED) { + BT_DBG("SegPending %u", tx->seg_pending); + if (tx->seg_pending) { tx->seg_pending--; } goto end; } + BT_DBG("SegPending %u Attempts %u", tx->seg_pending, tx->attempts); + if (--tx->seg_pending) { goto end; } if (!BLE_MESH_ADDR_IS_UNICAST(tx->dst) && !tx->attempts) { - BT_INFO("Complete tx sdu to group"); + BT_INFO("TxSduToGroupDone"); + seg_tx_complete(tx, 0); goto end; } @@ -411,6 +444,8 @@ static void seg_first_send_start(uint16_t duration, int err, void *user_data) { struct seg_tx *tx = user_data; + BT_DBG("SegFirstSendStart, Err %d", err); + if (tx->cb && tx->cb->start) { tx->cb->start(duration, err, tx->cb_data); } @@ -420,6 +455,8 @@ static void seg_send_start(uint16_t duration, int err, void *user_data) { struct seg_tx *tx = user_data; + BT_DBG("SegSendStart, Err %d", err); + /* If there's an error in transmitting the 'sent' callback will never * be called. Make sure that we kick the retransmit timer also in this * case since otherwise we risk the transmission of becoming stale. @@ -433,6 +470,8 @@ static void seg_sent(int err, void *user_data) { struct seg_tx *tx = user_data; + BT_DBG("SegSent, Err %d", err); + schedule_retransmit(tx); } @@ -450,17 +489,19 @@ static void seg_tx_send_unacked(struct seg_tx *tx) { int i, err = 0; + BT_DBG("SegTxSendUnacked, Attempts %u", tx->attempts); + bt_mesh_seg_tx_lock(tx); if (!(tx->attempts--)) { BT_WARN("Ran out of retransmit attempts"); + bt_mesh_seg_tx_unlock(tx); + seg_tx_complete(tx, -ETIMEDOUT); return; } - BT_INFO("Attempts: %u", tx->attempts); - for (i = 0; i <= tx->seg_n; i++) { struct net_buf *seg = tx->seg[i]; @@ -473,9 +514,10 @@ static void seg_tx_send_unacked(struct seg_tx *tx) continue; } - tx->seg_pending++; + BT_INFO("SegPendingInc %u", tx->seg_pending); + BT_INFO("SegResend %u/%u Cred %u", i, tx->seg_n, tx->cred); - BT_INFO("Resending %u/%u, cred 0x%02x", i, tx->seg_n, tx->cred); + tx->seg_pending++; /* TODO: * tx->new_key should be replaced with sub->kr_flag, @@ -486,8 +528,10 @@ static void seg_tx_send_unacked(struct seg_tx *tx) &tx->cred, tx->tag, &seg_sent_cb, tx); if (err) { - BT_ERR("Sending segment failed"); + BT_ERR("ResendSegFailed, Err %d", err); + bt_mesh_seg_tx_unlock(tx); + seg_tx_complete(tx, -EIO); return; } @@ -500,6 +544,8 @@ static void seg_retransmit(struct k_work *work) { struct seg_tx *tx = CONTAINER_OF(work, struct seg_tx, rtx_timer); + BT_DBG("SegRetransmit"); + seg_tx_send_unacked(tx); } @@ -516,20 +562,24 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu, int err = 0; int i; - BT_DBG("src 0x%04x dst 0x%04x app_idx 0x%04x aszmic %u sdu_len %u", + BT_DBG("SendSeg"); + BT_DBG("Src 0x%04x Dst 0x%04x AppIdx 0x%04x Aszmic %u SduLen %u", net_tx->src, net_tx->ctx->addr, net_tx->ctx->app_idx, net_tx->aszmic, sdu->len); for (tx = NULL, i = 0; i < ARRAY_SIZE(seg_tx); i++) { - if (!seg_tx[i].nack_count && - /* In some critical conditions, the tx might be - * reset before a segment broadcast is finished. - * If this happens, the seg_pending of the segment - * hasn't been processed. To avoid assigning this - * uncleared tx to a new message, extra checks for - * seg_pending being 0 are added. See BLEMESH25-92 - * for details.*/ - !seg_tx[i].seg_pending) { + /* In some critical conditions, the tx might be reset before + * a segment transmission is finished. + * If this happens, the seg_pending of the segment will not + * be processed. + * And to avoid assigning this uncleared tx to a new message, + * extra checks for seg_pending being 0 are added. + * See BLEMESH25-92 for details. + */ + BT_DBG("Seg%u: NackCount %u SegPending %u", + i, seg_tx[i].nack_count, seg_tx[i].seg_pending); + + if (!seg_tx[i].nack_count && !seg_tx[i].seg_pending) { tx = &seg_tx[i]; break; } @@ -585,15 +635,16 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu, seq_zero = tx->seq_auth & TRANS_SEQ_ZERO_MASK; - BT_DBG("SeqZero 0x%04x", seq_zero); + BT_DBG("SegHdr 0x%02x SegN %u NackCount %u NewKey %u TTL %u SeqZero 0x%04x", + seg_hdr, tx->seg_n, tx->nack_count, tx->new_key, tx->ttl, seq_zero); if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && !bt_mesh_friend_queue_has_space(tx->sub->net_idx, net_tx->src, tx->dst, &tx->seq_auth, tx->seg_n + 1) && BLE_MESH_ADDR_IS_UNICAST(tx->dst)) { - BT_ERR("Not enough space in Friend Queue for %u segments", - tx->seg_n + 1); + BT_WARN("NoSpaceInFrndQueue, SegCount %u", tx->seg_n + 1); + seg_tx_reset(tx); return -ENOBUFS; } @@ -659,6 +710,8 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu, type = BLE_MESH_FRIEND_PDU_PARTIAL; } + BT_DBG("FrndPDUType %u", type); + if (bt_mesh_friend_enqueue_tx(net_tx, type, &tx->seq_auth, tx->seg_n + 1, @@ -667,6 +720,8 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu, /* PDUs for a specific Friend should only go * out through the Friend Queue. */ + BT_DBG("FrndTxEnqueued, SegCount %u", tx->seg_n + 1); + net_buf_unref(seg); continue; } @@ -674,14 +729,16 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu, tx->seg[seg_o] = net_buf_ref(seg); - BT_DBG("Sending %u/%u", seg_o, tx->seg_n); + BT_INFO("SegPendingInc %u", tx->seg_pending); + BT_INFO("SegSend %u/%u Cred %u", seg_o, tx->seg_n, tx->cred); + tx->seg_pending++; err = bt_mesh_net_send(net_tx, seg, seg_o ? &seg_sent_cb : &first_sent_cb, tx); if (err) { - BT_ERR("Sending segment failed (err %d)", err); + BT_ERR("SendSegFailed, Err %d", err); break; } @@ -690,6 +747,7 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu, * which will be used for retransmission later. */ if (tx->cred != net_tx->ctx->send_cred) { + BT_INFO("OldCred %u NewCred %u", tx->cred, net_tx->ctx->send_cred); tx->cred = net_tx->ctx->send_cred; } } @@ -703,7 +761,10 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu, /* This can happen if segments only went into the Friend Queue */ if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && !tx->seg[0]) { + BT_DBG("OnlyToFrndQueue"); + seg_tx_reset(tx); + /* If there was a callback notify sending immediately since * there's no other way to track this (at least currently) * with the Friend Queue. @@ -727,6 +788,8 @@ int bt_mesh_trans_send(struct bt_mesh_net_tx *tx, struct net_buf_simple *msg, uint8_t aid = 0U; int err = 0; + BT_DBG("TransSend"); + if (msg->len < 1) { BT_ERR("Zero-length SDU not allowed"); return -EINVAL; @@ -752,9 +815,9 @@ int bt_mesh_trans_send(struct bt_mesh_net_tx *tx, struct net_buf_simple *msg, } #endif - BT_DBG("net_idx 0x%04x app_idx 0x%04x dst 0x%04x", tx->sub->net_idx, - tx->ctx->app_idx, tx->ctx->addr); - BT_DBG("len %u: %s", msg->len, bt_hex(msg->data, msg->len)); + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Dst 0x%04x", + tx->sub->net_idx, tx->ctx->app_idx, tx->ctx->addr); + BT_DBG("Len %u: %s", msg->len, bt_hex(msg->data, msg->len)); err = bt_mesh_upper_key_get(tx->sub, tx->ctx->app_idx, &key, &aid, tx->ctx->addr); @@ -772,7 +835,7 @@ int bt_mesh_trans_send(struct bt_mesh_net_tx *tx, struct net_buf_simple *msg, tx->aszmic = 1U; } - BT_INFO("%s, send_tag 0x%02x, send_szmic %d, aszmic %d", + BT_INFO("%s, Tag 0x%02x Szmic %u Aszmic %u", bt_mesh_tag_send_segmented(tx->ctx->send_tag) ? "Seg" : "Unseg", tx->ctx->send_tag, tx->ctx->send_szmic, tx->aszmic); @@ -787,7 +850,7 @@ int bt_mesh_trans_send(struct bt_mesh_net_tx *tx, struct net_buf_simple *msg, tx->ctx->addr, bt_mesh.seq, BLE_MESH_NET_IVI_TX); if (err) { - BT_ERR("Encrypt failed (err %d)", err); + BT_ERR("AppEncryptFailed, Err %d", err); return err; } @@ -801,7 +864,7 @@ int bt_mesh_trans_send(struct bt_mesh_net_tx *tx, struct net_buf_simple *msg, static void revoke_dev_key(const uint8_t *dev_key) { if (!memcmp(dev_key, bt_mesh.dev_key_ca, 16)) { - BT_INFO("Revoke Device Key"); + BT_INFO("RevokeDevKey"); memcpy(bt_mesh.dev_key, bt_mesh.dev_key_ca, 16); memset(bt_mesh.dev_key_ca, 0, 16); @@ -822,8 +885,9 @@ static int sdu_recv(struct bt_mesh_net_rx *rx, uint32_t seq, uint8_t hdr, size_t i = 0U; int err = 0; - BT_DBG("ASZMIC %u AKF %u AID 0x%02x", aszmic, AKF(&hdr), AID(&hdr)); - BT_DBG("len %u: %s", buf->len, bt_hex(buf->data, buf->len)); + BT_DBG("SduRecv"); + BT_DBG("Aszmic %u AKF %u AID 0x%02x", aszmic, AKF(&hdr), AID(&hdr)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); if (buf->len < 1 + APP_MIC_LEN(aszmic)) { BT_ERR("Too short SDU + MIC (len %u)", buf->len); @@ -862,7 +926,7 @@ static int sdu_recv(struct bt_mesh_net_rx *rx, uint32_t seq, uint8_t hdr, dev_key = bt_mesh_rx_devkey_get(i, rx->ctx.addr); if (!dev_key) { - BT_DBG("DevKey not found"); + BT_DBG("DevKeyNotFound"); continue; } @@ -873,6 +937,7 @@ static int sdu_recv(struct bt_mesh_net_rx *rx, uint32_t seq, uint8_t hdr, rx->ctx.recv_dst, seq, BLE_MESH_NET_IVI_RX(rx)); if (err) { + BT_DBG("DevKeyNotDecrypt"); continue; } @@ -898,6 +963,7 @@ static int sdu_recv(struct bt_mesh_net_rx *rx, uint32_t seq, uint8_t hdr, } BT_WARN("Unable to decrypt with DevKey"); + bt_mesh_free_buf(sdu); return -ENODEV; } @@ -910,7 +976,7 @@ static int sdu_recv(struct bt_mesh_net_rx *rx, uint32_t seq, uint8_t hdr, key = bt_mesh_rx_appkey_get(i); if (!key) { - BT_DBG("AppKey not found"); + BT_DBG("AppKeyNotFound"); continue; } @@ -944,8 +1010,7 @@ static int sdu_recv(struct bt_mesh_net_rx *rx, uint32_t seq, uint8_t hdr, bt_hex(sdu->data, sdu->len)); if (err) { - BT_DBG("Unable to decrypt with AppKey 0x%03x", - key->app_idx); + BT_DBG("AppKeyNotDecrypt, AppIdx 0x%04x", key->app_idx); continue; } @@ -957,8 +1022,9 @@ static int sdu_recv(struct bt_mesh_net_rx *rx, uint32_t seq, uint8_t hdr, } if (rx->local_match) { - BT_WARN("No matching AppKey"); + BT_WARN("NoMatchAppKey"); } + bt_mesh_free_buf(sdu); return 0; } @@ -968,6 +1034,8 @@ static struct seg_tx *seg_tx_lookup(uint16_t seq_zero, uint8_t obo, uint16_t add struct seg_tx *tx = NULL; int i; + BT_DBG("SegTxLookup, SeqZero 0x%04x OBO %u Addr 0x%04x", seq_zero, obo, addr); + for (i = 0; i < ARRAY_SIZE(seg_tx); i++) { tx = &seg_tx[i]; @@ -976,6 +1044,7 @@ static struct seg_tx *seg_tx_lookup(uint16_t seq_zero, uint8_t obo, uint16_t add } if (tx->dst == addr) { + BT_DBG("SegTxFound, Dst 0x%04x", addr); return tx; } @@ -985,6 +1054,7 @@ static struct seg_tx *seg_tx_lookup(uint16_t seq_zero, uint8_t obo, uint16_t add * responding and therefore accept the message. */ if (obo && tx->nack_count == tx->seg_n + 1) { + BT_DBG("SegTxOboFound, Dst 0x%04x", addr); tx->dst = addr; return tx; } @@ -997,11 +1067,13 @@ static int trans_ack(struct bt_mesh_net_rx *rx, uint8_t hdr, struct net_buf_simple *buf, uint64_t *seq_auth) { struct seg_tx *tx = NULL; + uint16_t seq_zero = 0U; unsigned int bit = 0; uint32_t ack = 0U; - uint16_t seq_zero = 0U; uint8_t obo = 0U; + BT_DBG("TransAck"); + if (buf->len != 6) { BT_ERR("Malformed Segment Ack (len %u)", buf->len); return -EINVAL; @@ -1020,7 +1092,7 @@ static int trans_ack(struct bt_mesh_net_rx *rx, uint8_t hdr, ack = net_buf_simple_pull_be32(buf); - BT_DBG("OBO %u seq_zero 0x%04x ack 0x%08x", obo, seq_zero, ack); + BT_DBG("OBO %u SeqZero 0x%04x Ack 0x%08lx", obo, seq_zero, ack); tx = seg_tx_lookup(seq_zero, obo, rx->ctx.addr); if (!tx) { @@ -1051,6 +1123,7 @@ static int trans_ack(struct bt_mesh_net_rx *rx, uint8_t hdr, while ((bit = find_lsb_set(ack))) { if (tx->seg[bit - 1]) { BT_INFO("Seg %u/%u acked", bit - 1, tx->seg_n); + bt_mesh_seg_tx_lock(tx); seg_tx_done(tx, bit - 1); bt_mesh_seg_tx_unlock(tx); @@ -1075,6 +1148,8 @@ static int trans_heartbeat(struct bt_mesh_net_rx *rx, uint8_t init_ttl = 0U, hops = 0U; uint16_t feat = 0U; + BT_DBG("TransHeartbeat"); + if (buf->len != 3) { BT_ERR("Malformed heartbeat message (len %u)", buf->len); return -EINVAL; @@ -1091,9 +1166,8 @@ static int trans_heartbeat(struct bt_mesh_net_rx *rx, hops = (init_ttl - rx->ctx.recv_ttl + 1); - BT_INFO("src 0x%04x TTL %u InitTTL %u (%u hop%s) feat 0x%04x", - rx->ctx.addr, rx->ctx.recv_ttl, init_ttl, hops, - (hops == 1U) ? "" : "s", feat); + BT_INFO("Src 0x%04x TTL %u InitTTL %u Hops %u Feat 0x%04x", + rx->ctx.addr, rx->ctx.recv_ttl, init_ttl, hops, feat); if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) { bt_mesh_heartbeat_recv(rx->ctx.addr, rx->ctx.recv_dst, hops, feat); @@ -1111,7 +1185,7 @@ static int ctl_recv(struct bt_mesh_net_rx *rx, uint8_t hdr, { uint8_t ctl_op = TRANS_CTL_OP(&hdr); - BT_DBG("OpCode 0x%02x len %u", ctl_op, buf->len); + BT_DBG("CTLRecv, OpCode 0x%02x Len %u", ctl_op, buf->len); BT_BQB(BLE_MESH_BQB_TEST_LOG_LEVEL_PRIMARY_ID_NODE | \ BLE_MESH_BQB_TEST_LOG_LEVEL_SUB_ID_TNPT, @@ -1128,6 +1202,7 @@ static int ctl_recv(struct bt_mesh_net_rx *rx, uint8_t hdr, /* Only acks and heartbeats may need processing without local_match */ if (!rx->local_match) { + BT_DBG("LocalNotMatch"); return 0; } @@ -1142,7 +1217,7 @@ static int ctl_recv(struct bt_mesh_net_rx *rx, uint8_t hdr, case TRANS_CTL_OP_PATH_REQ_SOLIC: return bt_mesh_directed_forwarding_ctl_recv(ctl_op, rx, buf); } -#endif +#endif /* CONFIG_BLE_MESH_DF_SRV */ if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && !bt_mesh_lpn_established()) { switch (ctl_op) { @@ -1195,7 +1270,7 @@ static int trans_unseg(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx, { uint8_t hdr = 0U; - BT_DBG("AFK %u AID 0x%02x", AKF(buf->data), AID(buf->data)); + BT_DBG("TransUnseg, AKF %u AID 0x%02x", AKF(buf->data), AID(buf->data)); if (buf->len < 1) { BT_ERR("Too small unsegmented PDU"); @@ -1203,7 +1278,7 @@ static int trans_unseg(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx, } if (bt_mesh_rpl_check(rx, NULL)) { - BT_WARN("Replay: src 0x%04x dst 0x%04x seq 0x%06x", + BT_WARN("Replay, Src 0x%04x Dst 0x%04x Seq 0x%06x", rx->ctx.addr, rx->ctx.recv_dst, rx->seq); return -EINVAL; } @@ -1216,6 +1291,7 @@ static int trans_unseg(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx, /* SDUs must match a local element or an LPN of this Friend. */ if (!rx->local_match && !rx->friend_match) { + BT_DBG("LocalAndFrndNotMatch"); return 0; } @@ -1241,6 +1317,8 @@ static inline int32_t ack_timeout(struct seg_rx *rx) /* 100 ms for every not yet received segment */ to += K_MSEC(((rx->seg_n + 1) - popcount(rx->block)) * 100U); + BT_DBG("AckTimeout, TTL %u TO %ld", ttl, to); + /* Make sure we don't send more frequently than the duration for * each packet (default is 300ms). */ @@ -1253,6 +1331,8 @@ int bt_mesh_ctl_send(struct bt_mesh_net_tx *tx, uint8_t ctl_op, void *data, { struct net_buf_simple buf = {0}; + BT_DBG("CtlSend"); + net_buf_simple_init_with_data(&buf, data, data_len); if (data_len > BLE_MESH_SDU_UNSEG_MAX) { @@ -1262,9 +1342,9 @@ int bt_mesh_ctl_send(struct bt_mesh_net_tx *tx, uint8_t ctl_op, void *data, /* Set app_idx to unused here since CTL is only encrypted with NetKey */ tx->ctx->app_idx = BLE_MESH_KEY_UNUSED; - BT_DBG("src 0x%04x dst 0x%04x ttl 0x%02x ctl 0x%02x", tx->src, - tx->ctx->addr, tx->ctx->send_ttl, ctl_op); - BT_DBG("len %zu: %s", data_len, bt_hex(data, data_len)); + BT_DBG("Src 0x%04x Dst 0x%04x TTL 0x%02x CTL 0x%02x", + tx->src, tx->ctx->addr, tx->ctx->send_ttl, ctl_op); + BT_DBG("Len %u: %s", data_len, bt_hex(data, data_len)); if (bt_mesh_tag_send_segmented(tx->ctx->send_tag)) { return send_seg(tx, &buf, cb, cb_data, &ctl_op); @@ -1296,7 +1376,7 @@ static int send_ack(struct bt_mesh_subnet *sub, uint16_t src, uint16_t dst, uint16_t seq_zero = *seq_auth & TRANS_SEQ_ZERO_MASK; uint8_t buf[6] = {0}; - BT_DBG("SeqZero 0x%04x Block 0x%08x OBO %u", seq_zero, block, obo); + BT_DBG("SendAck, SeqZero 0x%04x Block 0x%08lx OBO %u", seq_zero, block, obo); if (bt_mesh_lpn_established()) { BT_WARN("Not sending ack when LPN is enabled"); @@ -1320,6 +1400,8 @@ static int send_ack(struct bt_mesh_subnet *sub, uint16_t src, uint16_t dst, static void seg_rx_reset(struct seg_rx *rx, bool full_reset) { + BT_DBG("SegRxReset, FullReset %u", full_reset); + bt_mesh_seg_rx_lock(); k_delayed_work_cancel(&rx->ack_timer); @@ -1364,6 +1446,8 @@ static uint32_t incomplete_timeout(struct seg_rx *rx) /* The less segments being received, the shorter timeout will be used. */ timeout += K_MSEC(ttl * popcount(rx->block) * 100U); + BT_DBG("IncompleteTimeout %lu", timeout); + return MIN(timeout, K_SECONDS(60)); } @@ -1371,11 +1455,15 @@ static void seg_ack(struct k_work *work) { struct seg_rx *rx = CONTAINER_OF(work, struct seg_rx, ack_timer); + BT_DBG("SegAck, Last %lu", rx->last); + bt_mesh_seg_rx_lock(); if (k_uptime_get_32() - rx->last > incomplete_timeout(rx)) { BT_WARN("Incomplete timer expired"); + bt_mesh_seg_rx_unlock(); + seg_rx_reset(rx, false); return; } @@ -1398,6 +1486,8 @@ static void seg_ack(struct k_work *work) static inline uint16_t sdu_len_max(uint8_t seg_n,uint16_t seg_len) { + BT_DBG("IsSduLenOK,Len:%u,SegN:%u", seg_len, seg_n); + return ((seg_n + 1) * seg_len); } @@ -1406,6 +1496,9 @@ static inline bool sdu_len_is_ok(bool ctl, uint8_t seg_n, uint16_t buf_len) struct seg_info si = { .ctl = ctl, }; + + BT_DBG("IsSduLenOK, CTL %u SegN %u", ctl, seg_n); + #if CONFIG_BLE_MESH_LONG_PACKET if ((sdu_len_max(seg_n, buf_len) > CONFIG_BLE_MESH_RX_SDU_MAX)) { si.long_pkt = 1; @@ -1422,8 +1515,13 @@ static struct seg_rx *seg_rx_find_with_buf(struct bt_mesh_net_rx *net_rx, { int i; + BT_DBG("SegRxFind, SeqAuth 0x%llx", *seq_auth); for (i = 0; i < rx_buf_size; i++) { struct seg_rx *rx = &rx_buf[i]; + + BT_DBG("Seg%u/%u: Src 0x%04x Dst 0x%04x SeqAuth 0x%llx", + i, rx->seg_n, rx->src, rx->dst, rx->seq_auth); + if (rx->src != net_rx->ctx.addr || rx->dst != net_rx->ctx.recv_dst) { continue; @@ -1434,9 +1532,9 @@ static struct seg_rx *seg_rx_find_with_buf(struct bt_mesh_net_rx *net_rx, */ #if CONFIG_BLE_MESH_DISCARD_OLD_SEQ_AUTH if (rx->seq_auth >= *seq_auth) { -#else +#else /* CONFIG_BLE_MESH_DISCARD_OLD_SEQ_AUTH */ if (rx->seq_auth == *seq_auth) { -#endif +#endif /* CONFIG_BLE_MESH_DISCARD_OLD_SEQ_AUTH */ return rx; } @@ -1517,6 +1615,8 @@ static struct seg_rx *seg_rx_find(struct bt_mesh_net_rx *net_rx, static bool seg_rx_is_valid(struct seg_rx *rx, struct bt_mesh_net_rx *net_rx, const uint8_t *hdr, uint8_t seg_n) { + BT_DBG("IsSegRxValid"); + if (rx->hdr != *hdr || rx->seg_n != seg_n) { BT_ERR("Invalid segment for ongoing session"); return false; @@ -1557,6 +1657,8 @@ static struct seg_rx *seg_rx_alloc(struct bt_mesh_net_rx *net_rx, } #endif + BT_DBG("SegRxAlloc, SegN %u", seg_n); + for (i = 0; i < rx_buf_size; i++) { struct seg_rx *rx = &seg_rx_buf[i]; @@ -1601,18 +1703,20 @@ static int trans_seg(struct net_buf_simple *buf, struct bt_mesh_net_rx *net_rx, uint8_t seg_o = 0U; int err = 0; + BT_DBG("TransSeg"); + if (buf->len < 5) { BT_ERR("Too short segmented message (len %u)", buf->len); return -EINVAL; } if (bt_mesh_rpl_check(net_rx, &rpl)) { - BT_WARN("Replay: src 0x%04x dst 0x%04x seq 0x%06x", + BT_WARN("Replay, Src 0x%04x Dst 0x%04x Seq 0x%06x", net_rx->ctx.addr, net_rx->ctx.recv_dst, net_rx->seq); return -EINVAL; } - BT_DBG("ASZMIC %u AKF %u AID 0x%02x", ASZMIC(hdr), AKF(hdr), AID(hdr)); + BT_DBG("Aszmic %u AKF %u AID 0x%02x", ASZMIC(hdr), AKF(hdr), AID(hdr)); net_buf_simple_pull(buf, 1); @@ -1657,13 +1761,15 @@ static int trans_seg(struct net_buf_simple *buf, struct bt_mesh_net_rx *net_rx, *seg_count = seg_n + 1; + BT_DBG("Src 0x%04x Dst 0x%04x SeqAuth 0x%llx SegCount %u", + net_rx->ctx.addr, net_rx->ctx.recv_dst, *seq_auth, *seg_count); + /* Look for old RX sessions */ rx = seg_rx_find(net_rx, seq_auth); if (rx) { /* Discard old SeqAuth packet */ if (rx->seq_auth > *seq_auth) { - BT_WARN("Ignoring old SeqAuth, src 0x%04x, dst 0x%04x", - rx->src, rx->dst); + BT_WARN("SeqAuth 0x%llx vs. 0x%llx", rx->seq_auth, *seq_auth); return -EINVAL; } @@ -1678,6 +1784,7 @@ static int trans_seg(struct net_buf_simple *buf, struct bt_mesh_net_rx *net_rx, if (rx->block == BLOCK_COMPLETE(rx->seg_n)) { BT_INFO("Got segment for already complete SDU"); + send_ack(net_rx->sub, net_rx->ctx.recv_dst, net_rx->ctx.addr, net_rx->ctx.send_ttl, seq_auth, rx->block, rx->obo); @@ -1715,10 +1822,11 @@ static int trans_seg(struct net_buf_simple *buf, struct bt_mesh_net_rx *net_rx, net_rx->ctx.addr, net_rx->ctx.recv_dst, seq_auth, *seg_count)) { - BT_ERR("No space in Friend Queue for %u segments", *seg_count); - send_ack(net_rx->sub, net_rx->ctx.recv_dst, net_rx->ctx.addr, - net_rx->ctx.send_ttl, seq_auth, 0, - net_rx->friend_match); + BT_WARN("NoSpaceInFrndQueue, SegCount %u", *seg_count); + + send_ack(net_rx->sub, net_rx->ctx.recv_dst, + net_rx->ctx.addr, net_rx->ctx.send_ttl, + seq_auth, 0, net_rx->friend_match); return -ENOBUFS; } @@ -1729,7 +1837,7 @@ static int trans_seg(struct net_buf_simple *buf, struct bt_mesh_net_rx *net_rx, * eventually be freed up and we'll be able to process * this one. */ - BT_WARN("No free slots for new incoming segmented messages, src: %04x", net_rx->ctx.addr); + BT_WARN("SegRxFull, Src %04x", net_rx->ctx.addr); return -ENOMEM; } @@ -1756,16 +1864,21 @@ found_rx: /* Set the expected final buffer length */ rx->buf.len = seg_n * seg_len(&si) + buf->len; + BT_DBG("Target len %u * %u + %u = %u", + seg_n, seg_len(&si), buf->len, rx->buf.len); + if ((!rx->ext && rx->buf.len > CONFIG_BLE_MESH_RX_SDU_MAX) #if CONFIG_BLE_MESH_LONG_PACKET || (rx->ext && rx->buf.len > BLE_MESH_EXT_RX_SDU_MAX) #endif ) { - BT_ERR("Too large SDU len"); + BT_ERR("Too large SDU len %u", rx->buf.len); send_ack(net_rx->sub, net_rx->ctx.recv_dst, net_rx->ctx.addr, net_rx->ctx.send_ttl, seq_auth, 0, rx->obo); + seg_rx_reset(rx, true); + return -EMSGSIZE; } } else { @@ -1793,6 +1906,7 @@ found_rx: rx->block |= BIT(seg_o); if (rx->block != BLOCK_COMPLETE(seg_n)) { + BT_DBG("FrndPDUPartial"); *pdu_type = BLE_MESH_FRIEND_PDU_PARTIAL; return 0; } @@ -1813,8 +1927,8 @@ found_rx: if (net_rx->ctl) { err = ctl_recv(net_rx, *hdr, &rx->buf, seq_auth); } else { - err = sdu_recv(net_rx, (rx->seq_auth & 0xffffff), *hdr, - ASZMIC(hdr), &rx->buf); + err = sdu_recv(net_rx, (rx->seq_auth & 0xffffff), + *hdr, ASZMIC(hdr), &rx->buf); } seg_rx_reset(rx, false); @@ -1824,12 +1938,14 @@ found_rx: int bt_mesh_trans_recv(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx) { - uint64_t seq_auth = TRANS_SEQ_AUTH_NVAL; enum bt_mesh_friend_pdu_type pdu_type = BLE_MESH_FRIEND_PDU_SINGLE; struct net_buf_simple_state state = {0}; + uint64_t seq_auth = TRANS_SEQ_AUTH_NVAL; uint8_t seg_count = 0U; int err = 0; + BT_DBG("TransRecv"); + if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND)) { rx->friend_match = bt_mesh_friend_match(rx->sub->net_idx, rx->ctx.recv_dst); @@ -1837,20 +1953,21 @@ int bt_mesh_trans_recv(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx) rx->friend_match = false; } - BT_DBG("src 0x%04x dst 0x%04x seq 0x%08x friend_match %u", + BT_DBG("Src 0x%04x Dst 0x%04x Seq 0x%06x FrndMatch %u", rx->ctx.addr, rx->ctx.recv_dst, rx->seq, rx->friend_match); /* Remove network headers */ net_buf_simple_pull(buf, BLE_MESH_NET_HDR_LEN); - BT_DBG("Payload %s", bt_hex(buf->data, buf->len)); + BT_DBG("PDU %u %s", buf->len, bt_hex(buf->data, buf->len)); /* If LPN mode is enabled messages are only accepted when we've * requested the Friend to send them. The messages must also * be encrypted using the Friend Credentials. */ if (IS_ENABLED(CONFIG_BLE_MESH_LOW_POWER) && - bt_mesh_lpn_established() && rx->net_if == BLE_MESH_NET_IF_ADV && + bt_mesh_lpn_established() && + rx->net_if == BLE_MESH_NET_IF_ADV && (!bt_mesh_lpn_waiting_update() || rx->ctx.recv_cred != BLE_MESH_FRIENDSHIP_CRED)) { BT_WARN("Ignoring unexpected message in Low Power mode"); @@ -1867,12 +1984,14 @@ int bt_mesh_trans_recv(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx) * LPN of this Friend. */ if (!rx->local_match && !rx->friend_match) { + BT_DBG("LocalAndFrndNotMatch"); return 0; } err = trans_seg(buf, rx, &pdu_type, &seq_auth, &seg_count); } else { seg_count = 1U; + err = trans_unseg(buf, rx, &seq_auth); } @@ -1912,6 +2031,8 @@ void bt_mesh_rx_reset(void) { int i; + BT_DBG("RxReset"); + for (i = 0; i < ARRAY_SIZE(seg_rx); i++) { seg_rx_reset(&seg_rx[i], true); } @@ -1921,6 +2042,8 @@ void bt_mesh_tx_reset(void) { int i; + BT_DBG("TxReset"); + for (i = 0; i < ARRAY_SIZE(seg_tx); i++) { seg_tx_reset(&seg_tx[i]); } @@ -1930,6 +2053,8 @@ void bt_mesh_rx_reset_single(uint16_t src) { int i; + BT_DBG("RxResetSingle, Src 0x%04x", src); + if (!BLE_MESH_ADDR_IS_UNICAST(src)) { return; } @@ -1946,6 +2071,8 @@ void bt_mesh_tx_reset_single(uint16_t dst) { int i; + BT_DBG("TxResetSingle, Dst 0x%04x", dst); + if (!BLE_MESH_ADDR_IS_UNICAST(dst)) { return; } diff --git a/components/bt/esp_ble_mesh/core/transport.enh.c b/components/bt/esp_ble_mesh/core/transport.enh.c index 583f83e6a30..5721d6635ad 100644 --- a/components/bt/esp_ble_mesh/core/transport.enh.c +++ b/components/bt/esp_ble_mesh/core/transport.enh.c @@ -160,53 +160,93 @@ static inline void bt_mesh_seg_rx_unlock(void) uint8_t bt_mesh_seg_send_interval(void) { - return (bt_mesh_get_sar_sis() + 1) * 10; + uint8_t interval = (bt_mesh_get_sar_sis() + 1) * 10; + + BT_DBG("SegSendInterval %u", interval); + + return interval; } uint8_t bt_mesh_get_seg_rtx_num(void) { - return bt_mesh_get_sar_urc(); + uint8_t num = bt_mesh_get_sar_urc(); + + BT_DBG("SegRTXNum %u", num); + + return num; } int32_t bt_mesh_seg_rtx_interval(uint16_t dst, uint8_t ttl) { + int32_t interval = 0; + if (BLE_MESH_ADDR_IS_UNICAST(dst)) { if (ttl == 0) { - return (bt_mesh_get_sar_uris() + 1) * 25; + interval = (bt_mesh_get_sar_uris() + 1) * 25; + } else { + interval = ((bt_mesh_get_sar_uris() + 1) * 25 + + (bt_mesh_get_sar_urii() + 1) * 25 * (ttl - 1)); } - - return ((bt_mesh_get_sar_uris() + 1) * 25 + - (bt_mesh_get_sar_urii() + 1) * 25 * (ttl - 1)); + } else { + interval = (bt_mesh_get_sar_mris() + 1) * 25; } - return (bt_mesh_get_sar_mris() + 1) * 25; + BT_DBG("SegRTXInterval %ld, Dst 0x%04x TTL %u", interval, dst, ttl); + + return interval; } int32_t bt_mesh_get_seg_rtx_timeout(uint16_t dst, uint8_t ttl) { - return bt_mesh_seg_rtx_interval(dst, ttl); + int32_t timeout = bt_mesh_seg_rtx_interval(dst, ttl); + + BT_DBG("SegRTXTimeout %ld, Dst 0x%04x TTL %u", timeout, dst, ttl); + + return timeout; } uint32_t bt_mesh_seg_discard_timeout(void) { - return K_SECONDS((bt_mesh_get_sar_dt() + 1) * 5); + uint32_t timeout = K_SECONDS((bt_mesh_get_sar_dt() + 1) * 5); + + BT_DBG("SegDiscardTimeout %lu", timeout); + + return timeout; } uint32_t bt_mesh_seg_rx_interval(void) { - return (bt_mesh_get_sar_rsis() + 1) * 10; + uint32_t interval = (bt_mesh_get_sar_rsis() + 1) * 10; + + BT_DBG("SegRxInterval %lu", interval); + + return interval; } uint32_t bt_mesh_seg_ack_timeout(uint8_t seg_n) { - float min = MIN((float)seg_n + 0.5, (float)bt_mesh_get_sar_adi() + 1.5); - return (uint32_t)(min * bt_mesh_seg_rx_interval()); + uint32_t timeout = 0U; + float min = 0.0; + + min = MIN((float)seg_n + 0.5, (float)bt_mesh_get_sar_adi() + 1.5); + timeout = (uint32_t)(min * bt_mesh_seg_rx_interval()); + + BT_DBG("SegAckTimeout %lu, Min %f", timeout, min); + + return timeout; } uint32_t bt_mesh_seg_ack_period(void) { - float val = (float)bt_mesh_get_sar_adi() + 1.5; - return (uint32_t)(val * bt_mesh_seg_rx_interval()); + uint32_t period = 0U; + float val = 0.0; + + val = (float)bt_mesh_get_sar_adi() + 1.5; + period = (uint32_t)(val * bt_mesh_seg_rx_interval()); + + BT_DBG("SegAckPeriod %lu, Val %f", period, val); + + return period; } static int send_unseg(struct bt_mesh_net_tx *tx, struct net_buf_simple *sdu, @@ -216,8 +256,10 @@ static int send_unseg(struct bt_mesh_net_tx *tx, struct net_buf_simple *sdu, struct net_buf *buf = NULL; enum bt_mesh_adv_type adv_type = BLE_MESH_ADV_DATA; - BT_DBG("src 0x%04x dst 0x%04x app_idx 0x%04x sdu_len %u", - tx->src, tx->ctx->addr, tx->ctx->app_idx, sdu->len); + BT_DBG("SendUnseg"); + BT_DBG("Src 0x%04x Dst 0x%04x AppIdx 0x%04x CtlOp 0x%02x SduLen %u", + tx->src, tx->ctx->addr, tx->ctx->app_idx, + ctl_op ? *ctl_op : 0xFF, sdu->len); #if CONFIG_BLE_MESH_EXT_ADV #if CONFIG_BLE_MESH_LONG_PACKET @@ -272,13 +314,14 @@ static int send_unseg(struct bt_mesh_net_tx *tx, struct net_buf_simple *sdu, if (!bt_mesh_friend_queue_has_space(tx->sub->net_idx, tx->src, tx->ctx->addr, NULL, 1)) { + BT_WARN("NoSpaceInFrndQueue, SegCount 1"); + if (BLE_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) { - BT_ERR("Not enough space in Friend Queue"); + BT_ERR("NotSentToUnicast"); net_buf_unref(buf); return -ENOBUFS; } - BT_WARN("No space in Friend Queue"); goto send; } @@ -288,6 +331,8 @@ static int send_unseg(struct bt_mesh_net_tx *tx, struct net_buf_simple *sdu, /* PDUs for a specific Friend should only go * out through the Friend Queue. */ + BT_DBG("FrndTxEnqueued, SegCount 1"); + net_buf_unref(buf); send_cb_finalize(cb, cb_data); return 0; @@ -300,19 +345,25 @@ send: static inline uint8_t seg_len(struct seg_info *si) { + uint8_t len = 0; + if (si->ctl) { - return + len = #if CONFIG_BLE_MESH_LONG_PACKET si->long_pkt ? BLE_MESH_EXT_CTL_SEG_SDU_MAX : #endif BLE_MESH_CTL_SEG_SDU_MAX; + } else { + len = +#if CONFIG_BLE_MESH_LONG_PACKET + si->long_pkt ? BLE_MESH_EXT_APP_SEG_SDU_MAX : +#endif + BLE_MESH_APP_SEG_SDU_MAX; } - return -#if CONFIG_BLE_MESH_LONG_PACKET - si->long_pkt ? BLE_MESH_EXT_APP_SEG_SDU_MAX : -#endif - BLE_MESH_APP_SEG_SDU_MAX; + BT_DBG("SegLen %u", len); + + return len; } bool bt_mesh_tx_in_progress(void) @@ -321,20 +372,28 @@ bool bt_mesh_tx_in_progress(void) for (i = 0; i < ARRAY_SIZE(seg_tx); i++) { if (seg_tx[i].nack_count) { + BT_DBG("SegTxInProgress"); return true; } } + BT_DBG("SegTxNotInProgress"); return false; } static bool seg_tx_blocks(struct seg_tx *tx, uint16_t src, uint16_t dst) { + BT_DBG("SegTxBlocks"); + BT_DBG("Src 0x%04x vs. 0x%04x", tx->src, src); + BT_DBG("Dst 0x%04x vs. 0x%04x", tx->dst, dst); + return (tx->src == src) && (tx->dst == dst); } static void seg_tx_done(struct seg_tx *tx, uint8_t seg_idx) { + BT_DBG("SegTxDone, SegIdx %u", seg_idx); + /* If the segments are sent from local network interface, buf->ref * should be smaller than 4. * For other network interfaces, buf->ref should be smaller than 3. @@ -344,12 +403,16 @@ static void seg_tx_done(struct seg_tx *tx, uint8_t seg_idx) bt_mesh_atomic_set(&BLE_MESH_ADV_BUSY(tx->seg[seg_idx]), 0); net_buf_unref(tx->seg[seg_idx]); + BT_DBG("NackCountDec %u", tx->nack_count); + tx->seg[seg_idx] = NULL; tx->nack_count--; } static void seg_tx_reset(struct seg_tx *tx) { + BT_DBG("SegTxReset"); + bt_mesh_seg_tx_lock(); k_delayed_work_free(&tx->seg_timer); @@ -381,6 +444,7 @@ static void seg_tx_reset(struct seg_tx *tx) if (bt_mesh_atomic_test_and_clear_bit(bt_mesh.flags, BLE_MESH_IVU_PENDING)) { BT_DBG("Proceeding with pending IV Update"); + /* bt_mesh_net_iv_update() will re-enable the flag if this * wasn't the only transfer. */ @@ -395,6 +459,8 @@ static void seg_tx_complete(struct seg_tx *tx, int err) const struct bt_mesh_send_cb *cb = tx->cb; void *cb_data = tx->cb_data; + BT_DBG("SegTxComplete, Err %d", err); + seg_tx_reset(tx); /* TODO: notify the completion of sending segmented message */ @@ -411,10 +477,15 @@ static bool all_seg_acked(struct seg_tx *tx, uint8_t *seg_n) if (seg_n) { *seg_n = i; } + + BT_DBG("NotAllSegAcked, SegN %u", i); + return false; } } + BT_DBG("AllSegAcked"); + return true; } @@ -438,6 +509,10 @@ static bool send_next_segment(struct seg_tx *tx, int *result) struct net_buf *seg = NULL; int err = 0; + BT_DBG("SendNextSeg"); + BT_DBG("Src 0x%04x Dst 0x%04x LastSegN %u SegN %u LSNUpdated %u", + tx->src, tx->dst, tx->last_seg_n, tx->seg_n, tx->lsn_updated); + /* Check if all the segments are acknowledged. This could happen * when the complete Segment ACK (i.e. with all ack bits set) is * received before sending the next segment, which will cause the @@ -469,6 +544,8 @@ static bool send_next_segment(struct seg_tx *tx, int *result) * not been acknowledged. */ if (tx->seg[i]) { + BT_DBG("SegFound %u", i); + tx->last_seg_n = i; seg = tx->seg[i]; break; @@ -490,16 +567,19 @@ static bool send_next_segment(struct seg_tx *tx, int *result) * Segment Retransmission timer is expired earlier. */ if (bt_mesh_atomic_get(&BLE_MESH_ADV_BUSY(seg))) { + BT_DBG("SegSentBusy"); return false; } - BT_INFO("Send next seg %u, cred %u", tx->last_seg_n, tx->cred); + BT_INFO("LastSegN %u Cred %u", tx->last_seg_n, tx->cred); if (tx->resend) { err = bt_mesh_net_resend(tx->sub, seg, tx->new_key, &tx->cred, tx->tag, &seg_sent_cb, tx); if (err) { - BT_ERR("Resend seg %u failed (err %d)", tx->last_seg_n, err); + BT_ERR("ResendSegFailed, LastSegN %u Err %d", + tx->last_seg_n, err); + *result = -EIO; return true; } @@ -508,15 +588,16 @@ static bool send_next_segment(struct seg_tx *tx, int *result) net_tx.ctx->net_idx = tx->sub->net_idx; - /** - * Add one to the ref count only if the segment can be further + /* Add one to the ref count only if the segment can be further * processed by the network. */ seg = net_buf_ref(seg); err = bt_mesh_net_send(&net_tx, seg, &seg_sent_cb, tx); if (err) { - BT_ERR("Send seg %u failed (err %d)", tx->last_seg_n, err); + BT_ERR("SendSegFailed, LastSegN %u Err %d", + tx->last_seg_n, err); + *result = -EIO; return true; } @@ -526,7 +607,9 @@ static bool send_next_segment(struct seg_tx *tx, int *result) * which will be used for retransmission later. */ if (tx->cred != net_tx.ctx->send_cred) { - BT_ERR("Mismatch seg cred %u/%u", tx->cred, net_tx.ctx->send_cred); + BT_ERR("MismatchSegCred %u vs. %u", + tx->cred, net_tx.ctx->send_cred); + *result = -EIO; return true; } @@ -544,6 +627,8 @@ static void send_next_seg(struct k_work *work) tx_complete = send_next_segment(tx, &result); bt_mesh_seg_tx_unlock(); + BT_DBG("SendNextSeg, TxComplete %u", tx_complete); + if (tx_complete) { seg_tx_complete(tx, result); } @@ -555,6 +640,8 @@ static void prepare_next_seg(struct seg_tx *tx) uint8_t seg_n = 0; uint8_t xmit = 0; + BT_DBG("PrepareNextSeg"); + /* Check if all the segments are acknowledged. This could happen * when the complete Segment ACK (i.e. with all ack bits set) is * received before the completion of sending last segment, which @@ -565,6 +652,8 @@ static void prepare_next_seg(struct seg_tx *tx) return; } + BT_DBG("LastSegN %u SegN %u SegNGet %u", tx->last_seg_n, tx->seg_n, seg_n); + /* The last_seg_n must not be larger than the seg_n */ assert(tx->last_seg_n <= tx->seg_n && "Too large last_seg_n"); @@ -598,7 +687,7 @@ static void prepare_next_seg(struct seg_tx *tx) interval = bt_mesh_seg_send_interval(); - BT_INFO("Send next segment %u after %dms", i, interval); + BT_INFO("SendNextSeg %u, Interval %ld", i, interval); k_delayed_work_submit(&tx->seg_timer, interval); return; @@ -610,6 +699,7 @@ static void prepare_next_seg(struct seg_tx *tx) * we need to decrypt it firstly. */ if (tx->resend == 0) { + BT_DBG("TxResendMarked"); tx->resend = 1; } @@ -620,7 +710,7 @@ static void prepare_next_seg(struct seg_tx *tx) /* Start the SAR retransmission timer */ interval = bt_mesh_seg_rtx_interval(tx->dst, tx->ttl); - BT_INFO("All segments sent, resend after %dms", interval); + BT_INFO("AllSegsSent, SegN %u Interval %ld", seg_n, interval); k_delayed_work_submit(&tx->rtx_timer, interval); } @@ -629,6 +719,8 @@ static void seg_send_start(uint16_t duration, int err, void *user_data) { struct seg_tx *tx = user_data; + BT_DBG("SegSendStart, Err %d", err); + /* If there's an error in transmitting the 'sent' callback will never * be called. Make sure that we kick the retransmit timer also in this * case since otherwise we risk the transmission of becoming stale. @@ -638,6 +730,8 @@ static void seg_send_start(uint16_t duration, int err, void *user_data) return; } + BT_DBG("TxResend %u LastSegN %u", tx->resend, tx->last_seg_n); + if (tx->resend == 0 && tx->last_seg_n == 0) { /* Start sending the multi-segment message */ if (tx->cb && tx->cb->start) { @@ -654,6 +748,8 @@ static void seg_send_end(int err, void *user_data) { struct seg_tx *tx = user_data; + BT_DBG("SegSendEnd, Err %d", err); + if (err) { seg_tx_complete(tx, -EIO); } @@ -669,6 +765,10 @@ static bool resend_unacked_seg(struct seg_tx *tx, int *result) struct net_buf *seg = NULL; int err = 0; + BT_DBG("ResendUnackedSeg"); + BT_DBG("Dst 0x%04x Surc %u Surwpc %u Smrc %u", + tx->dst, tx->surc, tx->surwpc, tx->smrc); + /* Check if all the segments are acknowledged. This could happen * when the complete Segment ACK(i.e. with all ack bits set) is * received before the completion of sending last segment, which @@ -738,6 +838,8 @@ static bool resend_unacked_seg(struct seg_tx *tx, int *result) */ for (size_t i = tx->last_seg_n; i <= tx->seg_n; i++) { if (tx->seg[i]) { + BT_DBG("SegFound %u", i); + tx->last_seg_n = i; seg = tx->seg[i]; break; @@ -760,10 +862,11 @@ static bool resend_unacked_seg(struct seg_tx *tx, int *result) * find that the "busy" flag of Segment A is 1. */ if (bt_mesh_atomic_get(&BLE_MESH_ADV_BUSY(seg))) { + BT_DBG("SegSentBusy"); return false; } - BT_INFO("Resend seg %u, cred %u", tx->last_seg_n, tx->cred); + BT_INFO("LastSegN %u Cred %u", tx->last_seg_n, tx->cred); /* TODO: * The "tx->new_key" should be replaced with sub->kr_flag, @@ -774,7 +877,9 @@ static bool resend_unacked_seg(struct seg_tx *tx, int *result) &tx->cred, tx->tag, &seg_sent_cb, tx); if (err) { - BT_ERR("Resend seg %u failed (err %d)", tx->last_seg_n, err); + BT_ERR("ResendSegFailed, LastSegN %u Err %d", + tx->last_seg_n, err); + *result = -EIO; return true; } @@ -794,6 +899,8 @@ static void seg_retransmit(struct k_work *work) tx_complete = resend_unacked_seg(tx, &err); bt_mesh_seg_tx_unlock(); + BT_DBG("SendRetransmit, TxComplete %u", tx_complete); + if (tx_complete) { seg_tx_complete(tx, err); } @@ -811,11 +918,14 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu, int err = 0; size_t i; - BT_DBG("src 0x%04x dst 0x%04x app_idx 0x%04x aszmic %u sdu_len %u", + BT_DBG("SendSeg"); + BT_DBG("Src 0x%04x Dst 0x%04x AppIdx 0x%04x Aszmic %u SduLen %u", net_tx->src, net_tx->ctx->addr, net_tx->ctx->app_idx, net_tx->aszmic, sdu->len); for (i = 0; i < ARRAY_SIZE(seg_tx); i++) { + BT_DBG("Seg%u: NackCount %u", i, seg_tx[i].nack_count); + if (seg_tx[i].nack_count) { /* The lower transport layer shall not transmit segmented messages * for more than one Upper Transport PDU to the same destination @@ -830,6 +940,8 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu, for (tx = NULL, i = 0; i < ARRAY_SIZE(seg_tx); i++) { if (!seg_tx[i].nack_count) { + BT_DBG("SegTxFound %u", i); + tx = &seg_tx[i]; break; } @@ -922,15 +1034,18 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu, seq_zero = tx->seq_auth & TRANS_SEQ_ZERO_MASK; - BT_DBG("SeqZero 0x%04x (segs: %u)", seq_zero, tx->nack_count); + BT_DBG("SegHdr 0x%02x SegN %u NackCount %u NewKey %u TTL %u", + tx->hdr, tx->seg_n, tx->nack_count, tx->new_key, tx->ttl); + BT_DBG("SeqZero 0x%04x Surc %u Surwpc %u Smrc %u", + seq_zero, tx->surc, tx->surwpc, tx->smrc); if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && !bt_mesh_friend_queue_has_space(tx->sub->net_idx, net_tx->src, tx->dst, &tx->seq_auth, tx->seg_n + 1) && BLE_MESH_ADDR_IS_UNICAST(tx->dst)) { - BT_ERR("Not enough space in Friend Queue for %u segments", - tx->seg_n + 1); + BT_WARN("NoSpaceInFrndQueue, SegCount %u", tx->seg_n + 1); + seg_tx_reset(tx); return -ENOBUFS; } @@ -997,6 +1112,8 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu, type = BLE_MESH_FRIEND_PDU_PARTIAL; } + BT_DBG("FrndPDUType %u", type); + if (bt_mesh_friend_enqueue_tx(net_tx, type, &tx->seq_auth, tx->seg_n + 1, @@ -1005,39 +1122,40 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu, /* PDUs for a specific Friend should only go * out through the Friend Queue. */ + BT_DBG("FrndTxEnqueued, SegCount %u", tx->seg_n + 1); + net_buf_unref(seg); continue; } } - /** - * If the net buffer allocation of the subsequent - * segments of this segment message fails, it will - * cause the ref count of the previously allocated - * successful segments to not be unref, which will - * cause the net buffer leakage to occur, so it is - * necessary to wait until all the segments have been - * allocated, and then when the segment is confirmed - * that it will be network layer for further processing, - * then ref of the net buffer should be plus one. + /* If the net buffer allocation of the subsequent segments of + * this segment message fails, it will cause the ref count of + * the previously allocated successful segments to not be unref, + * which will cause the net buffer leakage to occur, so it is + * necessary to wait until all the segments have been allocated, + * and then when the segment is confirmed that it will be network + * layer for further processing, then ref of the net buffer should + * be plus one. */ tx->seg[seg_o] = seg; - BT_DBG("Seg %u/%u prepared", seg_o, tx->seg_n); + BT_DBG("SegPrepared %u/%u", seg_o, tx->seg_n); } /* If all the segments are enqueued in the friend queue, then the * tx->seg[0] will be NULL here. */ if (tx->seg[0]) { - /** - * Add one to the ref count only if the segment can be further + /* Add one to the ref count only if the segment can be further * processed by the network. */ tx->seg[0] = net_buf_ref(tx->seg[0]); + err = bt_mesh_net_send(net_tx, tx->seg[0], &seg_sent_cb, tx); if (err) { - BT_ERR("Send 1st seg failed (err %d)", err); + BT_ERR("SendFirstSegFailed, Err %d", err); + seg_tx_reset(tx); return err; } @@ -1047,13 +1165,17 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu, * which will be used for retransmission later. */ if (tx->cred != net_tx->ctx->send_cred) { + BT_INFO("OldCred %u NewCred %u", tx->cred, net_tx->ctx->send_cred); tx->cred = net_tx->ctx->send_cred; } } /* This can happen if segments only went into the Friend Queue */ if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && !tx->seg[0]) { + BT_DBG("OnlyToFrndQueue"); + seg_tx_reset(tx); + /* If there was a callback notify sending immediately since * there's no other way to track this (at least currently) * with the Friend Queue. @@ -1077,6 +1199,8 @@ int bt_mesh_trans_send(struct bt_mesh_net_tx *tx, struct net_buf_simple *msg, uint8_t aid = 0U; int err = 0; + BT_DBG("TransSend"); + if (msg->len < 1) { BT_ERR("Zero-length SDU not allowed"); return -EINVAL; @@ -1102,9 +1226,9 @@ int bt_mesh_trans_send(struct bt_mesh_net_tx *tx, struct net_buf_simple *msg, } #endif - BT_DBG("net_idx 0x%04x app_idx 0x%04x dst 0x%04x", tx->sub->net_idx, - tx->ctx->app_idx, tx->ctx->addr); - BT_DBG("len %u: %s", msg->len, bt_hex(msg->data, msg->len)); + BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Dst 0x%04x", + tx->sub->net_idx, tx->ctx->app_idx, tx->ctx->addr); + BT_DBG("Len %u: %s", msg->len, bt_hex(msg->data, msg->len)); err = bt_mesh_upper_key_get(tx->sub, tx->ctx->app_idx, &key, &aid, tx->ctx->addr); @@ -1122,7 +1246,7 @@ int bt_mesh_trans_send(struct bt_mesh_net_tx *tx, struct net_buf_simple *msg, tx->aszmic = 1U; } - BT_INFO("%s, send_tag 0x%02x, send_szmic %d, aszmic %d", + BT_INFO("%s, Tag 0x%02x Szmic %u Aszmic %u", bt_mesh_tag_send_segmented(tx->ctx->send_tag) ? "Seg" : "Unseg", tx->ctx->send_tag, tx->ctx->send_szmic, tx->aszmic); @@ -1137,7 +1261,7 @@ int bt_mesh_trans_send(struct bt_mesh_net_tx *tx, struct net_buf_simple *msg, tx->ctx->addr, bt_mesh.seq, BLE_MESH_NET_IVI_TX); if (err) { - BT_ERR("Encrypt failed (err %d)", err); + BT_ERR("AppEncryptFailed, Err %d", err); return err; } @@ -1151,7 +1275,7 @@ int bt_mesh_trans_send(struct bt_mesh_net_tx *tx, struct net_buf_simple *msg, static void revoke_dev_key(const uint8_t *dev_key) { if (!memcmp(dev_key, bt_mesh.dev_key_ca, 16)) { - BT_INFO("Revoke Device Key"); + BT_INFO("RevokeDevKey"); memcpy(bt_mesh.dev_key, bt_mesh.dev_key_ca, 16); memset(bt_mesh.dev_key_ca, 0, 16); @@ -1172,8 +1296,9 @@ static int sdu_recv(struct bt_mesh_net_rx *rx, uint32_t seq, uint8_t hdr, size_t i = 0U; int err = 0; - BT_DBG("ASZMIC %u AKF %u AID 0x%02x", aszmic, AKF(&hdr), AID(&hdr)); - BT_DBG("len %u: %s", buf->len, bt_hex(buf->data, buf->len)); + BT_DBG("SduRecv"); + BT_DBG("Aszmic %u AKF %u AID 0x%02x", aszmic, AKF(&hdr), AID(&hdr)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); if (buf->len < 1 + APP_MIC_LEN(aszmic)) { BT_ERR("Too short SDU + MIC (len %u)", buf->len); @@ -1212,7 +1337,7 @@ static int sdu_recv(struct bt_mesh_net_rx *rx, uint32_t seq, uint8_t hdr, dev_key = bt_mesh_rx_devkey_get(i, rx->ctx.addr); if (!dev_key) { - BT_DBG("DevKey not found"); + BT_DBG("DevKeyNotFound"); continue; } @@ -1223,6 +1348,7 @@ static int sdu_recv(struct bt_mesh_net_rx *rx, uint32_t seq, uint8_t hdr, rx->ctx.recv_dst, seq, BLE_MESH_NET_IVI_RX(rx)); if (err) { + BT_DBG("DevKeyNotDecrypt"); continue; } @@ -1248,6 +1374,7 @@ static int sdu_recv(struct bt_mesh_net_rx *rx, uint32_t seq, uint8_t hdr, } BT_WARN("Unable to decrypt with DevKey"); + bt_mesh_free_buf(sdu); return -ENODEV; } @@ -1260,7 +1387,7 @@ static int sdu_recv(struct bt_mesh_net_rx *rx, uint32_t seq, uint8_t hdr, key = bt_mesh_rx_appkey_get(i); if (!key) { - BT_DBG("AppKey not found"); + BT_DBG("AppKeyNotFound"); continue; } @@ -1294,8 +1421,7 @@ static int sdu_recv(struct bt_mesh_net_rx *rx, uint32_t seq, uint8_t hdr, bt_hex(sdu->data, sdu->len)); if (err) { - BT_DBG("Unable to decrypt with AppKey 0x%03x", - key->app_idx); + BT_DBG("AppKeyNotDecrypt, AppIdx 0x%04x", key->app_idx); continue; } @@ -1307,10 +1433,10 @@ static int sdu_recv(struct bt_mesh_net_rx *rx, uint32_t seq, uint8_t hdr, } if (rx->local_match) { - BT_WARN("No matching AppKey"); + BT_WARN("NoMatchAppKey"); } - bt_mesh_free_buf(sdu); + bt_mesh_free_buf(sdu); return 0; } @@ -1320,6 +1446,8 @@ static struct seg_tx *seg_tx_lookup(uint16_t seq_zero, uint8_t obo, struct seg_tx *tx = NULL; int i; + BT_DBG("SegTxLookup, SeqZero 0x%04x OBO %u Addr 0x%04x", seq_zero, obo, addr); + for (i = 0; i < ARRAY_SIZE(seg_tx); i++) { tx = &seg_tx[i]; @@ -1335,6 +1463,7 @@ static struct seg_tx *seg_tx_lookup(uint16_t seq_zero, uint8_t obo, } if (tx->dst == addr) { + BT_DBG("SegTxFound, Dst 0x%04x", addr); return tx; } @@ -1344,6 +1473,7 @@ static struct seg_tx *seg_tx_lookup(uint16_t seq_zero, uint8_t obo, * responding and therefore accept the message. */ if (obo && tx->nack_count == tx->seg_n + 1) { + BT_DBG("SegTxOboFound, Dst 0x%04x", addr); tx->dst = addr; return tx; } @@ -1370,6 +1500,8 @@ static int recv_seg_ack(struct bt_mesh_net_rx *rx, uint8_t hdr, *tx_complete = false; *result = 0; + BT_DBG("RecvSegAck"); + if (buf->len != 6) { BT_ERR("Malformed Segment Ack (len %u)", buf->len); return -EINVAL; @@ -1388,7 +1520,7 @@ static int recv_seg_ack(struct bt_mesh_net_rx *rx, uint8_t hdr, ack = net_buf_simple_pull_be32(buf); - BT_DBG("OBO %u seq_zero 0x%04x ack 0x%08x", obo, seq_zero, ack); + BT_DBG("OBO %u SeqZero 0x%04x Ack 0x%08lx", obo, seq_zero, ack); tx = seg_tx_lookup(seq_zero, obo, rx->ctx.addr, rx->ctx.net_idx); if (!tx) { @@ -1446,6 +1578,8 @@ static int recv_seg_ack(struct bt_mesh_net_rx *rx, uint8_t hdr, return 0; } + BT_DBG("NewlyMarked"); + /* If at least one segment is newly marked as acknowledged as * a result of receiving the Segment Acknowledgment message, * the lower transport layer shall set the remaining number of @@ -1455,9 +1589,12 @@ static int recv_seg_ack(struct bt_mesh_net_rx *rx, uint8_t hdr, tx->surwpc = bt_mesh_get_sar_urwpc(); } + BT_DBG("Surc %u Surwpc %u", tx->surc, tx->surwpc); + if (tx->surc == 0 || tx->surwpc == 0) { BT_WARN("Ran out of retransmission to 0x%04x (%u/%u)", tx->dst, tx->surc, tx->surwpc); + *tx_complete = true; *result = -ETIMEDOUT; return 0; @@ -1465,6 +1602,8 @@ static int recv_seg_ack(struct bt_mesh_net_rx *rx, uint8_t hdr, assert(all_seg_acked(tx, &seg_n) == false && "All segments acked"); + BT_DBG("SegN %u TxResend %u", seg_n, tx->resend); + if (tx->resend == 1) { /* Only update the last_seg_n to the first unacked SegN while * the first round transmission is finished, because we need @@ -1493,7 +1632,7 @@ static int recv_seg_ack(struct bt_mesh_net_rx *rx, uint8_t hdr, /* Restart the SAR Unicast Retransmission timer */ interval = bt_mesh_seg_rtx_interval(tx->dst, tx->ttl); - BT_INFO("Resend segments after %dms", interval); + BT_INFO("ResendSeg, Interval %ld", interval); k_delayed_work_submit(&tx->rtx_timer, interval); @@ -1512,6 +1651,8 @@ static int trans_ack(struct bt_mesh_net_rx *rx, uint8_t hdr, err = recv_seg_ack(rx, hdr, buf, seq_auth, &tx, &tx_complete, &result); bt_mesh_seg_tx_unlock(); + BT_DBG("TransAck, TxComplete %u", tx_complete); + if (tx_complete) { seg_tx_complete(tx, result); } @@ -1525,6 +1666,8 @@ static int trans_heartbeat(struct bt_mesh_net_rx *rx, uint8_t init_ttl = 0U, hops = 0U; uint16_t feat = 0U; + BT_DBG("TransHeartbeat"); + if (buf->len != 3) { BT_ERR("Malformed heartbeat message (len %u)", buf->len); return -EINVAL; @@ -1541,9 +1684,8 @@ static int trans_heartbeat(struct bt_mesh_net_rx *rx, hops = (init_ttl - rx->ctx.recv_ttl + 1); - BT_INFO("src 0x%04x TTL %u InitTTL %u (%u hop%s) feat 0x%04x", - rx->ctx.addr, rx->ctx.recv_ttl, init_ttl, hops, - (hops == 1U) ? "" : "s", feat); + BT_INFO("Src 0x%04x TTL %u InitTTL %u Hops %u Feat 0x%04x", + rx->ctx.addr, rx->ctx.recv_ttl, init_ttl, hops, feat); if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) { bt_mesh_heartbeat_recv(rx->ctx.addr, rx->ctx.recv_dst, hops, feat); @@ -1561,7 +1703,7 @@ static int ctl_recv(struct bt_mesh_net_rx *rx, uint8_t hdr, { uint8_t ctl_op = TRANS_CTL_OP(&hdr); - BT_DBG("OpCode 0x%02x len %u", ctl_op, buf->len); + BT_DBG("CTLRecv, OpCode 0x%02x Len %u", ctl_op, buf->len); BT_BQB(BLE_MESH_BQB_TEST_LOG_LEVEL_PRIMARY_ID_NODE | \ BLE_MESH_BQB_TEST_LOG_LEVEL_SUB_ID_TNPT, @@ -1578,21 +1720,22 @@ static int ctl_recv(struct bt_mesh_net_rx *rx, uint8_t hdr, /* Only acks and heartbeats may need processing without local_match */ if (!rx->local_match) { + BT_DBG("LocalNotMatch"); return 0; } - if (IS_ENABLED(CONFIG_BLE_MESH_DF_SRV)) { - switch (ctl_op) { - case TRANS_CTL_OP_PATH_REQ: - case TRANS_CTL_OP_PATH_REPLY: - case TRANS_CTL_OP_PATH_CFM: - case TRANS_CTL_OP_PATH_ECHO_REQ: - case TRANS_CTL_OP_PATH_ECHO_REPLY: - case TRANS_CTL_OP_DEP_NODE_UPDATE: - case TRANS_CTL_OP_PATH_REQ_SOLIC: - return bt_mesh_directed_forwarding_ctl_recv(ctl_op, rx, buf); - } +#if CONFIG_BLE_MESH_DF_SRV + switch (ctl_op) { + case TRANS_CTL_OP_PATH_REQ: + case TRANS_CTL_OP_PATH_REPLY: + case TRANS_CTL_OP_PATH_CFM: + case TRANS_CTL_OP_PATH_ECHO_REQ: + case TRANS_CTL_OP_PATH_ECHO_REPLY: + case TRANS_CTL_OP_DEP_NODE_UPDATE: + case TRANS_CTL_OP_PATH_REQ_SOLIC: + return bt_mesh_directed_forwarding_ctl_recv(ctl_op, rx, buf); } +#endif /* CONFIG_BLE_MESH_DF_SRV */ if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && !bt_mesh_lpn_established()) { switch (ctl_op) { @@ -1645,7 +1788,7 @@ static int trans_unseg(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx, { uint8_t hdr = 0U; - BT_DBG("AFK %u AID 0x%02x", AKF(buf->data), AID(buf->data)); + BT_DBG("TransUnseg, AKF %u AID 0x%02x", AKF(buf->data), AID(buf->data)); if (buf->len < 1) { BT_ERR("Too small unsegmented PDU"); @@ -1653,7 +1796,7 @@ static int trans_unseg(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx, } if (bt_mesh_rpl_check(rx, NULL)) { - BT_WARN("Replay: src 0x%04x dst 0x%04x seq 0x%06x", + BT_WARN("Replay, Src 0x%04x Dst 0x%04x Seq 0x%06x", rx->ctx.addr, rx->ctx.recv_dst, rx->seq); return -EINVAL; } @@ -1666,6 +1809,7 @@ static int trans_unseg(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx, /* SDUs must match a local element or an LPN of this Friend. */ if (!rx->local_match && !rx->friend_match) { + BT_DBG("LocalAndFrndNotMatch"); return 0; } @@ -1678,6 +1822,8 @@ int bt_mesh_ctl_send(struct bt_mesh_net_tx *tx, uint8_t ctl_op, void *data, { struct net_buf_simple buf = {0}; + BT_DBG("CtlSend"); + net_buf_simple_init_with_data(&buf, data, data_len); if (data_len > BLE_MESH_SDU_UNSEG_MAX) { @@ -1687,9 +1833,9 @@ int bt_mesh_ctl_send(struct bt_mesh_net_tx *tx, uint8_t ctl_op, void *data, /* Set app_idx to unused here since CTL is only encrypted with NetKey */ tx->ctx->app_idx = BLE_MESH_KEY_UNUSED; - BT_DBG("src 0x%04x dst 0x%04x ttl 0x%02x ctl 0x%02x", tx->src, - tx->ctx->addr, tx->ctx->send_ttl, ctl_op); - BT_DBG("len %zu: %s", data_len, bt_hex(data, data_len)); + BT_DBG("Src 0x%04x Dst 0x%04x TTL 0x%02x CTL 0x%02x", + tx->src, tx->ctx->addr, tx->ctx->send_ttl, ctl_op); + BT_DBG("Len %u: %s", data_len, bt_hex(data, data_len)); if (bt_mesh_tag_send_segmented(tx->ctx->send_tag)) { return send_seg(tx, &buf, cb, cb_data, &ctl_op); @@ -1702,18 +1848,21 @@ static void seg_ack_send_start(uint16_t duration, int err, void *user_data) { struct seg_rx *rx = user_data; - BT_INFO("Send segment ack start (err %d)", err); + BT_INFO("SegAckSendStart, Err %d", err); if (err) { rx->last_ack = k_uptime_get_32(); + + BT_DBG("LastAck %lu", rx->last_ack); } } static void seg_ack_send_end(int err, void *user_data) { struct seg_rx *rx = user_data; + uint32_t interval = 0U; - BT_INFO("Send segment ack end"); + BT_INFO("SegAckSendEnd, InUse %u Err %d", rx->in_use, err); /* This could happen when during the Segment ACK transaction, * the seg_rx is been reset. @@ -1724,6 +1873,9 @@ static void seg_ack_send_end(int err, void *user_data) rx->last_ack = k_uptime_get_32(); + BT_DBG("LastAck %lu SegN %u Sarc %u NewSeg %u", + rx->last_ack, rx->seg_n, rx->sarc, rx->new_seg); + /* If the seg_rx is in use, we will restart the SAR ACK timer if * the SegN is greater than the SAR Segments Threshold. * Note: @@ -1741,10 +1893,12 @@ static void seg_ack_send_end(int err, void *user_data) /* Decrement the SAR ACK Retransmissions Count */ rx->sarc -= 1; - BT_INFO("Resend segment ack after %dms", bt_mesh_seg_rx_interval()); + interval = bt_mesh_seg_rx_interval(); + + BT_INFO("ResendSeg, Interval %lu", interval); /* Introduce a delay for the Segment ACK retransmission */ - k_delayed_work_submit(&rx->ack_timer, bt_mesh_seg_rx_interval()); + k_delayed_work_submit(&rx->ack_timer, interval); } } @@ -1782,7 +1936,7 @@ static int send_ack(struct bt_mesh_subnet *sub, uint16_t src, uint16_t dst, uint16_t seq_zero = *seq_auth & TRANS_SEQ_ZERO_MASK; uint8_t buf[6] = {0}; - BT_DBG("SeqZero 0x%04x Block 0x%08x OBO %u", seq_zero, block, obo); + BT_DBG("SendAck, SeqZero 0x%04x Block 0x%08lx OBO %u", seq_zero, block, obo); if (bt_mesh_lpn_established()) { BT_WARN("Not sending ack when LPN is enabled"); @@ -1806,6 +1960,8 @@ static int send_ack(struct bt_mesh_subnet *sub, uint16_t src, uint16_t dst, static void seg_rx_reset(struct seg_rx *rx, bool full_reset) { + BT_DBG("SegRxReset, FullReset %u", full_reset); + bt_mesh_seg_rx_lock(); k_delayed_work_free(&rx->dis_timer); @@ -1846,6 +2002,8 @@ static void send_seg_ack(struct k_work *work) { struct seg_rx *rx = CONTAINER_OF(work, struct seg_rx, ack_timer); + BT_DBG("SendSegAck, Sub %p", rx->sub); + bt_mesh_seg_rx_lock(); /* This could happen when the SAR ACK timer expired, and a BTC @@ -1872,6 +2030,9 @@ end: static void discard_msg(struct k_work *work) { struct seg_rx *rx = CONTAINER_OF(work, struct seg_rx, dis_timer); + uint32_t timeout = 0U; + + BT_DBG("DiscardMsg, InUse %u Dst 0x%04x", rx->in_use, rx->dst); /* This could happen when the SAR Discard timer expired, and a * BTC event is posted to the BTC queue. @@ -1889,16 +2050,20 @@ static void discard_msg(struct k_work *work) k_delayed_work_cancel(&rx->ack_timer); } - BT_WARN("Discard timer expired (%dms)", bt_mesh_seg_discard_timeout()); + timeout = bt_mesh_seg_discard_timeout(); - /* Not fully reset the seg_rx, in case any segment of this - * message is received later. + BT_WARN("DiscardTimerExpired, timeout %lu", timeout); + + /* Not fully reset the seg_rx, in case any segment of + * this message is received later. */ seg_rx_reset(rx, false); } static inline uint16_t sdu_len_max(uint8_t seg_n,uint16_t seg_len) { + BT_DBG("IsSduLenOK,Len:%u,SegN:%u", seg_len, seg_n); + return ((seg_n + 1) * seg_len); } @@ -1907,6 +2072,9 @@ static inline bool sdu_len_is_ok(bool ctl, uint8_t seg_n, uint16_t buf_len) struct seg_info si = { .ctl = ctl, }; + + BT_DBG("IsSduLenOK, CTL %u SegN %u", ctl, seg_n); + #if CONFIG_BLE_MESH_LONG_PACKET if ((sdu_len_max(seg_n, buf_len) > CONFIG_BLE_MESH_RX_SDU_MAX)) { si.long_pkt = 1; @@ -1919,6 +2087,8 @@ static inline bool sdu_len_is_ok(bool ctl, uint8_t seg_n, uint16_t buf_len) static void seg_rx_reset_pending(struct bt_mesh_net_rx *net_rx, const uint64_t *seq_auth) { + BT_DBG("SegRxResetPending, SeqAuth 0x%llx", *seq_auth); + for (size_t i = 0; i < ARRAY_SIZE(seg_rx); i++) { struct seg_rx *rx = &seg_rx[i]; @@ -1940,9 +2110,13 @@ static struct seg_rx *seg_rx_find_with_buf(struct bt_mesh_net_rx *net_rx, struct seg_rx *rx_buf, uint16_t rx_buf_size ) { + BT_DBG("SegRxFind, SeqAuth 0x%llx", *seq_auth); for (size_t i = 0; i < rx_buf_size; i++) { struct seg_rx *rx = &rx_buf[i]; + BT_DBG("Seg%u/%u: Src 0x%04x Dst 0x%04x SeqAuth 0x%llx", + i,rx->seg_n, rx->src, rx->dst, rx->seq_auth); + if (rx->src == net_rx->ctx.addr && rx->dst == net_rx->ctx.recv_dst) { if (rx->seq_auth >= *seq_auth) { @@ -2025,6 +2199,8 @@ static struct seg_rx *seg_rx_find(struct bt_mesh_net_rx *net_rx, static bool seg_rx_is_valid(struct seg_rx *rx, struct bt_mesh_net_rx *net_rx, const uint8_t *hdr, uint8_t seg_n) { + BT_DBG("IsSegRxValid"); + if (rx->hdr != *hdr || rx->seg_n != seg_n) { BT_ERR("Invalid segment for ongoing session"); return false; @@ -2044,6 +2220,7 @@ static struct seg_rx *seg_rx_alloc(struct bt_mesh_net_rx *net_rx, { int err = 0; +<<<<<<< HEAD /* By default, traditional seg_rx is used for allocation. * If the first segment received is the last segment of * the long packet, and its length is the length of the traditional packet, @@ -2063,6 +2240,12 @@ static struct seg_rx *seg_rx_alloc(struct bt_mesh_net_rx *net_rx, for (size_t i = 0; i < rx_buf_size; i++) { struct seg_rx *rx = &seg_rx_buf[i]; +======= + BT_DBG("SegRxAlloc, SegN %u", seg_n); + + for (size_t i = 0; i < ARRAY_SIZE(seg_rx); i++) { + struct seg_rx *rx = &seg_rx[i]; +>>>>>>> 7652269a401 (feat(ble_mesh): Miscellaneous log enhancement for BLE Mesh) if (rx->in_use) { continue; @@ -2078,7 +2261,7 @@ static struct seg_rx *seg_rx_alloc(struct bt_mesh_net_rx *net_rx, err = k_delayed_work_init(&rx->ack_timer, send_seg_ack); if (err) { BT_ERR("No free ack_timer for new incoming segmented message"); - k_delayed_work_free(&rx->dis_timer); /* Must do */ + k_delayed_work_free(&rx->dis_timer); return NULL; } } @@ -2106,7 +2289,6 @@ static struct seg_rx *seg_rx_alloc(struct bt_mesh_net_rx *net_rx, return rx; } - BT_WARN("No free slots for new incoming segmented messages"); return NULL; } @@ -2122,18 +2304,20 @@ static int trans_seg(struct net_buf_simple *buf, struct bt_mesh_net_rx *net_rx, uint8_t seg_o = 0U; int err = 0; + BT_DBG("TransSeg"); + if (buf->len < 5) { BT_ERR("Too short segmented message (len %u)", buf->len); return -EINVAL; } if (bt_mesh_rpl_check(net_rx, &rpl)) { - BT_WARN("Replay: src 0x%04x dst 0x%04x seq 0x%06x", + BT_WARN("Replay, Src 0x%04x Dst 0x%04x Seq 0x%06x", net_rx->ctx.addr, net_rx->ctx.recv_dst, net_rx->seq); return -EINVAL; } - BT_DBG("ASZMIC %u AKF %u AID 0x%02x", ASZMIC(hdr), AKF(hdr), AID(hdr)); + BT_DBG("Aszmic %u AKF %u AID 0x%02x", ASZMIC(hdr), AKF(hdr), AID(hdr)); net_buf_simple_pull(buf, 1); @@ -2160,6 +2344,9 @@ static int trans_seg(struct net_buf_simple *buf, struct bt_mesh_net_rx *net_rx, *seg_count = seg_n + 1; + BT_DBG("Src 0x%04x Dst 0x%04x SeqAuth 0x%llx SegCount %u", + net_rx->ctx.addr, net_rx->ctx.recv_dst, *seq_auth, *seg_count); + /* If this is the first segment, check if any pending reassembly * exists. If yes, we need to discard the pending reassembly. * Note: @@ -2173,8 +2360,7 @@ static int trans_seg(struct net_buf_simple *buf, struct bt_mesh_net_rx *net_rx, if (rx) { /* Processing result is SeqAuth Error, ignore the segment */ if (rx->seq_auth > *seq_auth) { - BT_WARN("Ignoring old SeqAuth, src 0x%04x, dst 0x%04x", - rx->src, rx->dst); + BT_WARN("SeqAuth 0x%llx vs. 0x%llx", rx->seq_auth, *seq_auth); return -EINVAL; } @@ -2239,7 +2425,8 @@ static int trans_seg(struct net_buf_simple *buf, struct bt_mesh_net_rx *net_rx, net_rx->ctx.addr, net_rx->ctx.recv_dst, seq_auth, *seg_count)) { - BT_ERR("No space in Friend Queue for %u segments", *seg_count); + BT_ERR("NoSpaceInFrndQueue, SegCount %u", *seg_count); + send_ack(net_rx->sub, net_rx->ctx.recv_dst, net_rx->ctx.addr, net_rx->ctx.send_ttl, seq_auth, 0, net_rx->friend_match, NULL); @@ -2249,6 +2436,8 @@ static int trans_seg(struct net_buf_simple *buf, struct bt_mesh_net_rx *net_rx, /* Look for free slot for a new RX session */ rx = seg_rx_alloc(net_rx, hdr, seq_auth, seg_n); if (!rx) { + BT_WARN("SegRxFull, Src %04x", net_rx->ctx.addr); + /* Processing result is Message Rejected, respond with a Segment * ACK with the AckedSegments field set to 0x00000000. */ @@ -2285,14 +2474,20 @@ found_rx: /* Set the expected final buffer length */ rx->buf.len = seg_n * seg_len(&si) + buf->len; +<<<<<<< HEAD BT_DBG("Target len %u * %u + %u = %u", seg_n, seg_len(&si), buf->len, rx->buf.len); +======= + BT_DBG("Target len %u * %u + %u = %u", + seg_n, seg_len(rx->ctl), buf->len, rx->buf.len); +>>>>>>> 7652269a401 (feat(ble_mesh): Miscellaneous log enhancement for BLE Mesh) /* This should not happen, since we have made sure the whole * SDU could be received while handling the first segment. * But if the peer device sends the segments of a segmented * message with different CTL, then the following could happen. */ +<<<<<<< HEAD if ((!rx->ext && rx->buf.len > CONFIG_BLE_MESH_RX_SDU_MAX) #if CONFIG_BLE_MESH_LONG_PACKET || (rx->ext && rx->buf.len > BLE_MESH_EXT_RX_SDU_MAX) @@ -2300,10 +2495,16 @@ found_rx: ) { BT_ERR("Too large SDU len %u/%u", rx->buf.len, CONFIG_BLE_MESH_RX_SDU_MAX); +======= + if (rx->buf.len > CONFIG_BLE_MESH_RX_SDU_MAX) { + BT_ERR("Too large SDU len %u/%u", + rx->buf.len, CONFIG_BLE_MESH_RX_SDU_MAX); +>>>>>>> 7652269a401 (feat(ble_mesh): Miscellaneous log enhancement for BLE Mesh) send_ack(net_rx->sub, net_rx->ctx.recv_dst, net_rx->ctx.addr, net_rx->ctx.send_ttl, seq_auth, 0, rx->obo, NULL); + seg_rx_reset(rx, true); return -EMSGSIZE; @@ -2351,6 +2552,7 @@ found_rx: rx->block |= BIT(seg_o); if (rx->block != BLOCK_COMPLETE(seg_n)) { + BT_DBG("FrndPDUPartial"); *pdu_type = BLE_MESH_FRIEND_PDU_PARTIAL; return 0; } @@ -2374,8 +2576,8 @@ found_rx: if (net_rx->ctl) { err = ctl_recv(net_rx, *hdr, &rx->buf, seq_auth); } else { - err = sdu_recv(net_rx, (rx->seq_auth & 0xffffff), *hdr, - ASZMIC(hdr), &rx->buf); + err = sdu_recv(net_rx, (rx->seq_auth & 0xffffff), + *hdr, ASZMIC(hdr), &rx->buf); } seg_rx_reset(rx, false); @@ -2385,12 +2587,14 @@ found_rx: int bt_mesh_trans_recv(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx) { - uint64_t seq_auth = TRANS_SEQ_AUTH_NVAL; enum bt_mesh_friend_pdu_type pdu_type = BLE_MESH_FRIEND_PDU_SINGLE; struct net_buf_simple_state state = {0}; + uint64_t seq_auth = TRANS_SEQ_AUTH_NVAL; uint8_t seg_count = 0U; int err = 0; + BT_DBG("TransRecv"); + if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND)) { rx->friend_match = bt_mesh_friend_match(rx->sub->net_idx, rx->ctx.recv_dst); @@ -2398,20 +2602,21 @@ int bt_mesh_trans_recv(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx) rx->friend_match = false; } - BT_DBG("src 0x%04x dst 0x%04x seq 0x%08x friend_match %u", + BT_DBG("Src 0x%04x Dst 0x%04x Seq 0x%06x FrndMatch %u", rx->ctx.addr, rx->ctx.recv_dst, rx->seq, rx->friend_match); /* Remove network headers */ net_buf_simple_pull(buf, BLE_MESH_NET_HDR_LEN); - BT_DBG("Payload %s", bt_hex(buf->data, buf->len)); + BT_DBG("PDU %s", bt_hex(buf->data, buf->len)); /* If LPN mode is enabled messages are only accepted when we've * requested the Friend to send them. The messages must also * be encrypted using the Friend Credentials. */ if (IS_ENABLED(CONFIG_BLE_MESH_LOW_POWER) && - bt_mesh_lpn_established() && rx->net_if == BLE_MESH_NET_IF_ADV && + bt_mesh_lpn_established() && + rx->net_if == BLE_MESH_NET_IF_ADV && (!bt_mesh_lpn_waiting_update() || rx->ctx.recv_cred != BLE_MESH_FRIENDSHIP_CRED)) { BT_WARN("Ignoring unexpected message in Low Power mode"); @@ -2428,12 +2633,14 @@ int bt_mesh_trans_recv(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx) * LPN of this Friend. */ if (!rx->local_match && !rx->friend_match) { + BT_DBG("LocalAndFrndNotMatch"); return 0; } err = trans_seg(buf, rx, &pdu_type, &seq_auth, &seg_count); } else { seg_count = 1U; + err = trans_unseg(buf, rx, &seq_auth); } @@ -2471,6 +2678,8 @@ int bt_mesh_trans_recv(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx) void bt_mesh_rx_reset(void) { + BT_DBG("RxReset"); + for (size_t i = 0; i < ARRAY_SIZE(seg_rx); i++) { seg_rx_reset(&seg_rx[i], true); } @@ -2478,6 +2687,8 @@ void bt_mesh_rx_reset(void) void bt_mesh_tx_reset(void) { + BT_DBG("TxReset"); + for (size_t i = 0; i < ARRAY_SIZE(seg_tx); i++) { seg_tx_reset(&seg_tx[i]); } @@ -2485,6 +2696,8 @@ void bt_mesh_tx_reset(void) void bt_mesh_rx_reset_single(uint16_t src) { + BT_DBG("RxResetSingle, Src 0x%04x", src); + if (!BLE_MESH_ADDR_IS_UNICAST(src)) { return; } @@ -2499,6 +2712,8 @@ void bt_mesh_rx_reset_single(uint16_t src) void bt_mesh_tx_reset_single(uint16_t dst) { + BT_DBG("TxResetSingle, Dst 0x%04x", dst); + if (!BLE_MESH_ADDR_IS_UNICAST(dst)) { return; } diff --git a/components/bt/esp_ble_mesh/models/client/client_common.c b/components/bt/esp_ble_mesh/models/client/client_common.c index 8c8afdd563f..e87c68f62c7 100644 --- a/components/bt/esp_ble_mesh/models/client/client_common.c +++ b/components/bt/esp_ble_mesh/models/client/client_common.c @@ -16,7 +16,7 @@ #if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" -#endif +#endif /* CONFIG_BLE_MESH_V11_SUPPORT */ #define HCI_TIME_FOR_START_ADV K_MSEC(5) /* Three adv related hci commands may take 4 ~ 5ms */ @@ -25,9 +25,13 @@ static bt_mesh_client_node_t *client_pick_node(sys_slist_t *list, uint16_t tx_ds bt_mesh_client_node_t *node = NULL; sys_snode_t *cur = NULL; + BT_DBG("ClientPickNode, Dst 0x%04x", tx_dst); + bt_mesh_list_lock(); + if (sys_slist_is_empty(list)) { bt_mesh_list_unlock(); + BT_DBG("ListEmpty"); return NULL; } @@ -36,22 +40,28 @@ static bt_mesh_client_node_t *client_pick_node(sys_slist_t *list, uint16_t tx_ds node = (bt_mesh_client_node_t *)cur; if (node->ctx.addr == tx_dst) { bt_mesh_list_unlock(); + BT_DBG("ListNodeFound"); return node; } } bt_mesh_list_unlock(); + + BT_DBG("ListNodeNotFound"); return NULL; } bt_mesh_client_node_t *bt_mesh_is_client_recv_publish_msg(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, - struct net_buf_simple *buf, bool need_pub) + struct net_buf_simple *buf, + bool need_pub) { bt_mesh_client_internal_data_t *data = NULL; bt_mesh_client_user_data_t *cli = NULL; bt_mesh_client_node_t *node = NULL; + BT_DBG("ClientRecvPublishMsg"); + if (!model || !ctx || !buf) { BT_ERR("%s, Invalid parameter", __func__); return NULL; @@ -63,22 +73,25 @@ bt_mesh_client_node_t *bt_mesh_is_client_recv_publish_msg(struct bt_mesh_model * return NULL; } - /** If the received message address is not a unicast address, - * the address may be a group/virtual address, and we push - * this message to the application layer. + BT_DBG("Src 0x%04x Dst 0x%04x RecvOp 0x%08lx", + ctx->addr, ctx->recv_dst, ctx->recv_op); + + /* If the received message address is not a unicast address, + * the address may be a group/virtual address, and we push + * this message to the application layer. */ if (!BLE_MESH_ADDR_IS_UNICAST(ctx->recv_dst)) { - BT_DBG("Unexpected status message 0x%08x", ctx->recv_op); + BT_DBG("MsgToNonUnicastDst"); if (cli->publish_status && need_pub) { cli->publish_status(ctx->recv_op, model, ctx, buf); } return NULL; } - /** If the source address of the received status message is - * different with the destination address of the sending - * message, then the message is from another element and - * push it to application layer. + /* If the source address of the received status message is + * different with the destination address of the sending + * message, then the message is from another element and + * push it to application layer. */ data = (bt_mesh_client_internal_data_t *)cli->internal_data; if (!data) { @@ -87,7 +100,7 @@ bt_mesh_client_node_t *bt_mesh_is_client_recv_publish_msg(struct bt_mesh_model * } if ((node = client_pick_node(&data->queue, ctx->addr)) == NULL) { - BT_DBG("Unexpected status message 0x%08x", ctx->recv_op); + BT_DBG("MsgFromUnknownSrc"); if (cli->publish_status && need_pub) { cli->publish_status(ctx->recv_op, model, ctx, buf); } @@ -95,7 +108,7 @@ bt_mesh_client_node_t *bt_mesh_is_client_recv_publish_msg(struct bt_mesh_model * } if (node->op_pending != ctx->recv_op) { - BT_DBG("Unexpected status message 0x%08x", ctx->recv_op); + BT_DBG("MsgWithUnknownOp"); if (cli->publish_status && need_pub) { cli->publish_status(ctx->recv_op, model, ctx, buf); } @@ -103,7 +116,7 @@ bt_mesh_client_node_t *bt_mesh_is_client_recv_publish_msg(struct bt_mesh_model * } if (k_delayed_work_remaining_get(&node->timer) == 0) { - BT_DBG("Unexpected status message 0x%08x", ctx->recv_op); + BT_DBG("MsgWithTimerExpired"); if (cli->publish_status && need_pub) { cli->publish_status(ctx->recv_op, model, ctx, buf); } @@ -116,6 +129,9 @@ bt_mesh_client_node_t *bt_mesh_is_client_recv_publish_msg(struct bt_mesh_model * static uint32_t client_get_status_op(const bt_mesh_client_op_pair_t *op_pair, int size, uint32_t opcode) { + BT_DBG("ClientGetStatusOp"); + BT_DBG("OpPair %p Size %u OpCode 0x%08lx", op_pair, size, opcode); + if (!op_pair || size == 0) { return 0; } @@ -123,11 +139,14 @@ static uint32_t client_get_status_op(const bt_mesh_client_op_pair_t *op_pair, const bt_mesh_client_op_pair_t *op = op_pair; for (int i = 0; i < size; i++) { if (op->cli_op == opcode) { + BT_DBG("OpCodeFound"); return op->status_op; } + op++; } + BT_DBG("OpCodeNotFound"); return 0; } @@ -139,17 +158,22 @@ static int32_t client_get_adv_duration(struct bt_mesh_msg_ctx *ctx) /* Initialize with network transmission */ xmit = bt_mesh_net_transmit_get(); + BT_DBG("ClientGetAdvDuration, Xmit 0x%02x", xmit); + if (bt_mesh_tag_immutable_cred(ctx->send_tag)) { #if CONFIG_BLE_MESH_DF_SRV if (ctx->send_cred == BLE_MESH_DIRECTED_CRED) { xmit = bt_mesh_direct_net_transmit_get(); /* Directed network transmission */ + BT_DBG("UseDFXmit 0x%02x", xmit); } -#endif +#endif /* CONFIG_BLE_MESH_DF_SRV */ } adv_int = BLE_MESH_TRANSMIT_INT(xmit); duration = (BLE_MESH_TRANSMIT_COUNT(xmit) + 1) * (adv_int + 10); + BT_DBG("Duration %ld", (int32_t)duration); + return (int32_t)duration; } @@ -187,6 +211,8 @@ static int32_t client_calc_timeout(struct bt_mesh_msg_ctx *ctx, net_buf_simple_tailroom(msg) >= BLE_MESH_MIC_LONG) ? BLE_MESH_MIC_LONG : BLE_MESH_MIC_SHORT; + BT_DBG("NeedSeg %u MicSize %u", need_seg, mic_size); + if (need_seg) { /* Based on the message length, calculate how many segments are needed. * All the messages sent from here are access messages. @@ -243,7 +269,7 @@ static void msg_send_start(uint16_t duration, int err, void *cb_data) { bt_mesh_client_node_t *node = cb_data; - BT_DBG("%s, duration %ums", __func__, duration); + BT_DBG("MsgSendStart, Duration %u Err %d", duration, err); if (err) { if (!k_delayed_work_free(&node->timer)) { @@ -269,6 +295,8 @@ int bt_mesh_client_send_msg(bt_mesh_client_common_param_t *param, bt_mesh_client_node_t *node = NULL; int err = 0; + BT_DBG("ClientSendMsg, NeedAck %u", need_ack); + if (!param || !param->model || !msg) { BT_ERR("%s, Invalid parameter", __func__); return -EINVAL; @@ -376,6 +404,8 @@ int bt_mesh_client_init(struct bt_mesh_model *model) bt_mesh_client_internal_data_t *internal = NULL; bt_mesh_client_user_data_t *client = NULL; + BT_DBG("ClientInit"); + if (!model || !model->op) { BT_ERR("Invalid vendor client model"); return -EINVAL; @@ -413,6 +443,8 @@ int bt_mesh_client_deinit(struct bt_mesh_model *model) { bt_mesh_client_user_data_t *client = NULL; + BT_DBG("ClientDeinit"); + if (!model) { BT_ERR("Invalid vendor client model"); return -EINVAL; @@ -444,6 +476,8 @@ int bt_mesh_client_free_node(bt_mesh_client_node_t *node) bt_mesh_client_internal_data_t *internal = NULL; bt_mesh_client_user_data_t *client = NULL; + BT_DBG("ClientFreeNode"); + if (!node || !node->model) { BT_ERR("Invalid client list item"); return -EINVAL; @@ -461,12 +495,10 @@ int bt_mesh_client_free_node(bt_mesh_client_node_t *node) return -EINVAL; } - // Release the client node from the queue bt_mesh_list_lock(); sys_slist_find_and_remove(&internal->queue, &node->client_node); bt_mesh_list_unlock(); - // Free the node bt_mesh_free(node); return 0; @@ -477,6 +509,8 @@ int bt_mesh_client_clear_list(void *data) bt_mesh_client_internal_data_t *internal = NULL; bt_mesh_client_node_t *node = NULL; + BT_DBG("ClientClearList"); + if (!data) { BT_ERR("%s, Invalid parameter", __func__); return -EINVAL; @@ -485,11 +519,13 @@ int bt_mesh_client_clear_list(void *data) internal = (bt_mesh_client_internal_data_t *)data; bt_mesh_list_lock(); + while (!sys_slist_is_empty(&internal->queue)) { node = (void *)sys_slist_get_not_empty(&internal->queue); k_delayed_work_free(&node->timer); bt_mesh_free(node); } + bt_mesh_list_unlock(); return 0; From e1d539d1ffd32922740feb051f82bdb1cabdee46 Mon Sep 17 00:00:00 2001 From: luoxu Date: Mon, 1 Sep 2025 20:47:15 +0800 Subject: [PATCH 067/106] feat(ble_mesh): Miscellaneous log enhancement for Provisioning --- components/bt/esp_ble_mesh/core/prov_common.c | 34 +++++++++---- components/bt/esp_ble_mesh/core/prov_node.c | 34 +++++++++---- components/bt/esp_ble_mesh/core/prov_pvnr.c | 48 +++++++++++++++---- 3 files changed, 89 insertions(+), 27 deletions(-) diff --git a/components/bt/esp_ble_mesh/core/prov_common.c b/components/bt/esp_ble_mesh/core/prov_common.c index a29ba8fb4fe..bf5657852b8 100644 --- a/components/bt/esp_ble_mesh/core/prov_common.c +++ b/components/bt/esp_ble_mesh/core/prov_common.c @@ -48,6 +48,7 @@ void bt_mesh_prov_buf_init(struct net_buf_simple *buf, uint8_t type) bt_mesh_output_action_t bt_mesh_prov_output_action(uint8_t action) { + BT_DBG("ProvOutputAction:%d", action); switch (action) { case OUTPUT_OOB_BLINK: return BLE_MESH_BLINK; @@ -66,6 +67,7 @@ bt_mesh_output_action_t bt_mesh_prov_output_action(uint8_t action) bt_mesh_input_action_t bt_mesh_prov_input_action(uint8_t action) { + BT_DBG("ProvInputAction:%d", action); switch (action) { case INPUT_OOB_PUSH: return BLE_MESH_PUSH; @@ -151,20 +153,27 @@ static uint8_t bt_mesh_prov_buf_type_get(struct net_buf_simple *buf) uint8_t node_next_xact_id(struct bt_mesh_prov_link *link) { + uint8_t nxt_xact_id = 0; if (link->tx.id != 0 && link->tx.id != 0xFF) { - return ++link->tx.id; + nxt_xact_id = ++link->tx.id; + } else { + link->tx.id = 0x80; + nxt_xact_id = 0x80; } - link->tx.id = 0x80; - return link->tx.id; + BT_DBG("NodeNextXActId:%d", nxt_xact_id); + return nxt_xact_id; } uint8_t pvnr_next_xact_id(struct bt_mesh_prov_link *link) { + uint8_t nxt_xact_id = 0; if (link->tx.id > 0x7F) { link->tx.id = 0; } - return link->tx.id++; + nxt_xact_id = link->tx.id++; + BT_DBG("PvnrNextXActId:%d", nxt_xact_id); + return nxt_xact_id; } bool bt_mesh_gen_prov_start(struct bt_mesh_prov_link *link, @@ -186,7 +195,7 @@ bool bt_mesh_gen_prov_start(struct bt_mesh_prov_link *link, link->rx.id = rx->xact_id; link->rx.fcs = net_buf_simple_pull_u8(buf); - BT_DBG("len %u last_seg %u total_len %u fcs 0x%02x", buf->len, + BT_DBG("LinkId:%08x,len %u last_seg %u total_len %u fcs 0x%02x", link->link_id, buf->len, START_LAST_SEG(rx->gpc), link->rx.buf->len, link->rx.fcs); /* At least one-octet pdu type is needed */ @@ -227,9 +236,10 @@ bool bt_mesh_gen_prov_start(struct bt_mesh_prov_link *link, link->rx.last_seg = START_LAST_SEG(rx->gpc); memcpy(link->rx.buf->data, buf->data, buf->len); XACT_SEG_RECV(link, 0); - + BT_DBG("Seg: %04x, lastSeg: %04x, Data: %s", link->rx.seg, link->rx.last_seg, bt_hex(buf->data, buf->len)); /* Still have some segments to receive */ if (link->rx.seg) { + BT_DBG("Still have some segments to receive: %02x", link->rx.seg); return false; } @@ -242,7 +252,7 @@ bool bt_mesh_gen_prov_cont(struct bt_mesh_prov_link *link, { uint8_t seg = CONT_SEG_INDEX(rx->gpc); - BT_DBG("len %u, seg_index %u", buf->len, seg); + BT_DBG("LinkId:%08x,len %u,seg_index %u", link->link_id, buf->len, seg); if (link->rx.seg == 0 && link->rx.prev_id == rx->xact_id) { BT_INFO("Resending ack"); @@ -287,6 +297,7 @@ bool bt_mesh_gen_prov_cont(struct bt_mesh_prov_link *link, /* Still have some segments to receive */ if (link->rx.seg) { + BT_DBG("Still have some segments to receive: %02x", link->rx.seg); return false; } @@ -346,12 +357,14 @@ void bt_mesh_gen_prov_ack_send(struct bt_mesh_prov_link *link, uint8_t xact_id) net_buf_add_u8(buf, xact_id); net_buf_add_u8(buf, GPC_ACK); + BT_DBG("GenericProvAckSend,LinkId:%08x,XActId:%02x", link->link_id, xact_id); bt_mesh_adv_send(buf, PROV_XMIT, complete, link); net_buf_unref(buf); } static void free_segments(struct bt_mesh_prov_link *link) { + BT_DBG("FreeSegments:%08x", link->link_id); for (size_t i = 0; i < ARRAY_SIZE(link->tx.buf); i++) { struct net_buf *buf = link->tx.buf[i]; @@ -386,6 +399,7 @@ static void buf_sent(int err, void *user_data) int32_t timeout = RETRANSMIT_TIMEOUT; if (!link->tx.buf[0]) { + BT_DBG("LinkId:%08x,NoTxBuf", link->link_id); return; } @@ -412,6 +426,8 @@ static void prov_retransmit(struct k_work *work) struct bt_mesh_prov_link *link = work->user_data; int64_t timeout = TRANSACTION_TIMEOUT; + BT_DBG("LinkRetransmit:%08x,flag:%s", link->link_id, bt_hex(link->flags, sizeof(link->flags))); + if (!bt_mesh_atomic_test_bit(link->flags, LINK_ACTIVE) && !bt_mesh_atomic_test_bit(link->flags, LINK_CLOSING)) { BT_WARN("Link not active"); @@ -493,7 +509,7 @@ static void prov_retransmit(struct k_work *work) BT_DBG("%u bytes: %s", buf->len, bt_hex(buf->data, buf->len)); - if (i + 1 < ARRAY_SIZE(link->tx.buf) && link->tx.buf[i + 1]) { + if (likely(i + 1 < ARRAY_SIZE(link->tx.buf) && link->tx.buf[i + 1])) { bt_mesh_adv_send(buf, PROV_XMIT, NULL, NULL); } else { bt_mesh_adv_send(buf, PROV_XMIT, &buf_sent_cb, link); @@ -521,7 +537,7 @@ static void send_reliable(struct bt_mesh_prov_link *link, uint8_t xmit) break; } - if (i + 1 < ARRAY_SIZE(link->tx.buf) && link->tx.buf[i + 1]) { + if (likely(i + 1 < ARRAY_SIZE(link->tx.buf) && link->tx.buf[i + 1])) { bt_mesh_adv_send(buf, xmit, NULL, NULL); } else { bt_mesh_adv_send(buf, xmit, &buf_sent_cb, link); diff --git a/components/bt/esp_ble_mesh/core/prov_node.c b/components/bt/esp_ble_mesh/core/prov_node.c index cf78947071a..973239097d7 100644 --- a/components/bt/esp_ble_mesh/core/prov_node.c +++ b/components/bt/esp_ble_mesh/core/prov_node.c @@ -2,7 +2,7 @@ /* * SPDX-FileCopyrightText: 2017 Intel Corporation - * SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2018-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -52,6 +52,7 @@ struct bt_mesh_prov_link *bt_mesh_prov_node_get_link(void) static void close_link(uint8_t reason) { + BT_DBG("LinkClose(Rpr:%d),Reason:%d", bt_mesh_atomic_test_bit(prov_link.flags, PB_REMOTE), reason); if (bt_mesh_atomic_test_bit(prov_link.flags, PB_REMOTE)) { if (prov_link.pb_remote_close) { prov_link.pb_remote_close(&prov_link, reason); @@ -69,6 +70,7 @@ void bt_mesh_prov_node_close_link(uint8_t reason) static void reset_state(void) { + BT_INFO("ProvLinkStateReset"); k_delayed_work_cancel(&prov_link.prot_timer); /* Disable Attention Timer if it was set */ @@ -122,6 +124,7 @@ static void reset_adv_link(struct bt_mesh_prov_link *link, uint8_t reason) { ARG_UNUSED(link); + BT_INFO("ResetAdvLink:%08x", link->link_id); bt_mesh_prov_clear_tx(&prov_link, true); if (bt_mesh_prov_get()->link_close) { @@ -267,6 +270,7 @@ static int prov_auth(uint8_t method, uint8_t action, uint8_t size) auth_size = PROV_AUTH_SIZE(&prov_link); + BT_INFO("ProvAuth:method:%d,action:%d,size:%d", method, action, size); switch (method) { case AUTH_METHOD_NO_OOB: if (action || size) { @@ -411,6 +415,7 @@ static void prov_start(const uint8_t *data) if ((bt_mesh_prov_get()->oob_type & BIT(PROV_ONLY_OOB_AUTH_SUPPORT)) && ((data[0] == PROV_ALG_P256_HMAC_SHA256 && data[2] == AUTH_METHOD_NO_OOB) || data[0] == PROV_ALG_P256_CMAC_AES128)) { + BT_WARN("InvalidCapabilities,Alg:%d,Method:%d", data[0], data[2]); close_link(PROV_ERR_NVAL_FMT); return; } @@ -561,9 +566,10 @@ int bt_mesh_input_number(uint32_t num) auth_size = PROV_AUTH_SIZE(&prov_link); - BT_INFO("%u", num); + BT_INFO("ProvInputNumber:%u", num); if (!bt_mesh_atomic_test_and_clear_bit(prov_link.flags, WAIT_NUMBER)) { + BT_WARN("InvalidFlag:WAIT_NUMBER"); return -EINVAL; } @@ -572,6 +578,7 @@ int bt_mesh_input_number(uint32_t num) send_input_complete(); if (!bt_mesh_atomic_test_bit(prov_link.flags, HAVE_DHKEY)) { + BT_INFO("DHKeyExists"); return 0; } @@ -587,6 +594,7 @@ int bt_mesh_input_string(const char *str) BT_INFO("%s", str); if (!bt_mesh_atomic_test_and_clear_bit(prov_link.flags, WAIT_STRING)) { + BT_WARN("InvalidFlag:WAIT_STRING"); return -EINVAL; } @@ -595,6 +603,7 @@ int bt_mesh_input_string(const char *str) send_input_complete(); if (!bt_mesh_atomic_test_bit(prov_link.flags, HAVE_DHKEY)) { + BT_INFO("DHKeyExists"); return 0; } @@ -712,6 +721,7 @@ int bt_mesh_set_oob_pub_key(const uint8_t pub_key_x[32], /* If remote public key is not got, just return */ if (!bt_mesh_atomic_test_bit(prov_link.flags, REMOTE_PUB_KEY)) { + BT_WARN("RemotePubKeyNotSet"); return 0; } @@ -902,6 +912,7 @@ static void prov_data(const uint8_t *data) uint8_t reason = 0; if (bt_mesh_rpr_srv_nppi_check(prov_link.pb_remote_nppi, pdu, net_idx, iv_index, addr, &reason) == false) { + BT_WARN("RprNppiCheckFail:%d", reason); close_link(reason); return; } @@ -924,6 +935,7 @@ static void prov_data(const uint8_t *data) pdu, net_idx, flags, iv_index, addr, dev_key); if (err) { + BT_WARN("RprNppiStoreFail:%d", err); close_link(PROV_ERR_UNEXP_ERR); return; } @@ -964,6 +976,7 @@ static void prov_data(const uint8_t *data) * using Node Identity. */ if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) && identity_enable) { + BT_DBG("EnableProxyIdentity"); bt_mesh_proxy_identity_enable(); } } @@ -973,7 +986,7 @@ static void prov_complete(const uint8_t *data) static void prov_failed(const uint8_t *data) { - BT_WARN("Error: 0x%02x", data[0]); + BT_WARN("ProvError: 0x%02x", data[0]); #if CONFIG_BLE_MESH_RPR_SRV if (bt_mesh_atomic_test_bit(prov_link.flags, PB_REMOTE)) { @@ -1011,7 +1024,7 @@ static const struct { #if CONFIG_BLE_MESH_PB_ADV static void link_open(struct prov_rx *rx, struct net_buf_simple *buf) { - BT_DBG("len %u", buf->len); + BT_DBG("LinkOpenLen:%u", buf->len); if (buf->len < 16) { BT_ERR("Too short bearer open message (len %u)", buf->len); @@ -1065,7 +1078,7 @@ static void link_open(struct prov_rx *rx, struct net_buf_simple *buf) static void link_ack(struct prov_rx *rx, struct net_buf_simple *buf) { - BT_DBG("len %u", buf->len); + BT_DBG("LinkAckLen:%u",buf->len); #if CONFIG_BLE_MESH_RPR_SRV if (bt_mesh_atomic_test_bit(prov_link.flags, PB_REMOTE)) { @@ -1094,7 +1107,7 @@ static void link_close(struct prov_rx *rx, struct net_buf_simple *buf) { uint8_t reason = 0; - BT_DBG("len %u", buf->len); + BT_DBG("LinkCloseLen %u", buf->len); if (buf->len != 1) { BT_ERR("Invalid Link Close length %d", buf->len); @@ -1258,12 +1271,14 @@ static void gen_prov_ack(struct prov_rx *rx, struct net_buf_simple *buf) BT_DBG("len %u", buf->len); if (!prov_link.tx.buf[0]) { + BT_DBG("AlreadyReceived"); return; } #if CONFIG_BLE_MESH_RPR_SRV if (bt_mesh_atomic_test_bit(prov_link.flags, PB_REMOTE)) { if (prov_link.tx.id == 0) { + BT_DBG("ZeroTxId"); return; } @@ -1278,6 +1293,7 @@ static void gen_prov_ack(struct prov_rx *rx, struct net_buf_simple *buf) #endif /* CONFIG_BLE_MESH_RPR_SRV */ if (rx->xact_id == prov_link.tx.id) { + BT_DBG("XActId:%04x,ReceivedAck", rx->xact_id); bt_mesh_prov_clear_tx(&prov_link, true); } } @@ -1342,7 +1358,7 @@ void bt_mesh_pb_adv_recv(struct net_buf_simple *buf) rx.xact_id = net_buf_simple_pull_u8(buf); rx.gpc = net_buf_simple_pull_u8(buf); - BT_DBG("link_id 0x%08x xact_id %u", rx.link_id, rx.xact_id); + BT_DBG("link_id 0x%08x xact_id %u gpc %u", rx.link_id, rx.xact_id, rx.gpc); if (bt_mesh_atomic_test_bit(prov_link.flags, LINK_ACTIVE) && prov_link.link_id != rx.link_id) { @@ -1441,7 +1457,7 @@ int bt_mesh_pb_gatt_recv(struct bt_mesh_conn *conn, struct net_buf_simple *buf) int bt_mesh_pb_gatt_open(struct bt_mesh_conn *conn) { - BT_DBG("conn %p", conn); + BT_DBG("ProvConnOpen %p", conn); /** * It's necessary to determine if it is PB_REMOTE because when the @@ -1482,7 +1498,7 @@ int bt_mesh_pb_gatt_open(struct bt_mesh_conn *conn) int bt_mesh_pb_gatt_close(struct bt_mesh_conn *conn, uint8_t reason) { - BT_DBG("conn %p", conn); + BT_DBG("ProvConnClose %p", conn); if (prov_link.conn != conn) { BT_ERR("Not connected"); diff --git a/components/bt/esp_ble_mesh/core/prov_pvnr.c b/components/bt/esp_ble_mesh/core/prov_pvnr.c index 091e3e86071..e51c7a8d1d4 100644 --- a/components/bt/esp_ble_mesh/core/prov_pvnr.c +++ b/components/bt/esp_ble_mesh/core/prov_pvnr.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -202,6 +202,7 @@ static inline void bt_mesh_pb_gatt_unlock(void) void bt_mesh_provisioner_pbg_count_dec(void) { + BT_DBG("PbgCntDec:%d", prov_ctx.pbg_count); if (prov_ctx.pbg_count) { prov_ctx.pbg_count--; } @@ -210,6 +211,7 @@ void bt_mesh_provisioner_pbg_count_dec(void) static inline void provisioner_pbg_count_inc(void) { prov_ctx.pbg_count++; + BT_DBG("PbgCntInc:%d", prov_ctx.pbg_count); } void bt_mesh_provisioner_clear_link_info(const uint8_t addr[6]) @@ -436,8 +438,8 @@ static int provisioner_start_prov_pb_gatt(const uint8_t uuid[16], const bt_mesh_ */ if (assign_addr == BLE_MESH_ADDR_UNASSIGNED && prov_ctx.alloc_addr == BLE_MESH_ADDR_UNASSIGNED) { - BT_ERR("No available unicast address to assign"); bt_mesh_pb_gatt_unlock(); + BT_ERR("No available unicast address to assign"); return -EIO; } @@ -451,6 +453,7 @@ static int provisioner_start_prov_pb_gatt(const uint8_t uuid[16], const bt_mesh_ !bt_mesh_atomic_test_bit(prov_links[i].flags, LINK_ACTIVE)) { if (bt_mesh_gattc_conn_create(addr, BLE_MESH_UUID_MESH_PROV_VAL)) { bt_mesh_pb_gatt_unlock(); + BT_ERR("ProvGattCreateFailed:%s", bt_hex(addr->val, 6)); return -EIO; } @@ -598,6 +601,7 @@ int bt_mesh_provisioner_add_unprov_dev(struct bt_mesh_unprov_dev_add *add_dev, u start: /* If not provisioning immediately, directly return here */ if (!(flags & START_PROV_NOW)) { + BT_DBG("StartProvNotSet"); return 0; } @@ -617,6 +621,9 @@ start: } if ((err = provisioner_check_unprov_dev_info(add_dev->uuid, add_dev->bearer))) { + if (err == -EALREADY) { + BT_INFO("The device is being provisioning"); + } return err; } @@ -710,6 +717,9 @@ int bt_mesh_provisioner_prov_device_with_addr(const uint8_t uuid[16], const uint } if ((err = provisioner_check_unprov_dev_info(uuid, bearer))) { + if (err == -EALREADY) { + BT_INFO("The device is being provisioning"); + } return err; } @@ -749,10 +759,12 @@ int bt_mesh_provisioner_delete_device(struct bt_mesh_device_delete *del_dev) return -EINVAL; } + BT_INFO("ProvisionerDeleteDevice:%s", bt_hex(del_dev->uuid, 16)); /* Find if the device is in the device queue */ for (i = 0; i < ARRAY_SIZE(unprov_dev); i++) { if (!memcmp(unprov_dev[i].uuid, del_dev->uuid, 16)) { memset(&unprov_dev[i], 0, sizeof(struct unprov_dev_queue)); + BT_INFO("Device is in the queue"); break; } } @@ -761,6 +773,7 @@ int bt_mesh_provisioner_delete_device(struct bt_mesh_device_delete *del_dev) for (i = 0; i < ARRAY_SIZE(prov_links); i++) { if (!memcmp(prov_links[i].uuid, del_dev->uuid, 16)) { close_link(&prov_links[i], CLOSE_REASON_FAILED); + BT_INFO("Device is being provisioned"); break; } } @@ -776,6 +789,7 @@ int bt_mesh_provisioner_set_dev_uuid_match(uint8_t offset, uint8_t length, return -EINVAL; } + BT_INFO("SetUUIDMatch,offset:%d,value:%s,flag:%d", offset, bt_hex(match, length), prov_flag); (void)memset(prov_ctx.match_value, 0, 16); prov_ctx.match_offset = offset; @@ -795,6 +809,7 @@ int bt_mesh_provisioner_adv_pkt_cb_register(unprov_adv_pkt_cb_t cb) return -EINVAL; } + BT_INFO("RegisterAdvCB:%p", notify_unprov_adv_pkt_cb); notify_unprov_adv_pkt_cb = cb; return 0; } @@ -815,6 +830,7 @@ int bt_mesh_provisioner_set_prov_data_info(struct bt_mesh_prov_data_info *info) } prov_ctx.net_idx = info->net_idx; + BT_INFO("SetProvCtx,NetIndex:%d", info->net_idx); } return 0; @@ -881,6 +897,7 @@ void bt_mesh_provisioner_set_prov_bearer(bt_mesh_prov_bearer_t bearers, bool cle } else { prov_ctx.bearers &= ~bearers; } + BT_INFO("ProvCtxBearer:%04x,clear:%d", prov_ctx.bearers, clear); } bt_mesh_prov_bearer_t bt_mesh_provisioner_get_prov_bearer(void) @@ -909,7 +926,7 @@ int bt_mesh_provisioner_set_static_oob_value(const uint8_t *value, uint8_t lengt prov_ctx.static_oob_len = MIN(BLE_MESH_PROV_STATIC_OOB_MAX_LEN, length); memcpy(prov_ctx.static_oob_val, value, prov_ctx.static_oob_len); - + BT_INFO("SetStaticOob:%s", bt_hex(value, prov_ctx.static_oob_len)); return 0; } @@ -984,11 +1001,13 @@ int bt_mesh_test_provisioner_update_alloc_addr(uint16_t unicast_addr, uint16_t e void bt_mesh_provisioner_fast_prov_enable(bool enable) { prov_ctx.fast_prov.enable = enable; + BT_INFO("FastProvEnable:%d", enable); } void bt_mesh_provisioner_set_fast_prov_net_idx(uint16_t net_idx) { prov_ctx.fast_prov.net_idx = net_idx; + BT_INFO("FastProvNetIdx:%d", net_idx); } uint16_t bt_mesh_provisioner_get_fast_prov_net_idx(void) @@ -1017,7 +1036,7 @@ uint8_t bt_mesh_set_fast_prov_unicast_addr_range(uint16_t min, uint16_t max) prov_ctx.fast_prov.unicast_addr_max = max; prov_ctx.alloc_addr = prov_ctx.fast_prov.unicast_addr_min; - + BT_INFO("FastProv,AddrMin:%04x,Max:%04x,allocAddr:%04x", min, max, prov_ctx.alloc_addr); return 0x0; /* status: success */ } @@ -1038,6 +1057,7 @@ static struct net_buf_simple *get_rx_buf(const uint8_t idx) static void reset_adv_link(struct bt_mesh_prov_link *link, uint8_t reason) { + BT_INFO("ResetAdvLink:%08x", link->link_id); bt_mesh_prov_clear_tx(link, true); if (bt_mesh_prov_get()->prov_link_close) { @@ -1106,6 +1126,7 @@ static void send_link_open(struct bt_mesh_prov_link *link) if (bt_mesh_atomic_test_bit(prov_links[i].flags, LINK_ACTIVE) && prov_links[i].link_id == link->link_id) { bt_mesh_rand(&link->link_id, sizeof(link->link_id)); + BT_DBG("ProvLinkIdx:%d,LinkId:%08x", i, link->link_id); break; } } @@ -1280,6 +1301,7 @@ static void prov_capabilities(struct bt_mesh_prov_link *link, if ((algorithms & BIT(PROV_ALG_P256_CMAC_AES128)) || (!((oob_type & BIT(PROV_STATIC_OOB_AVAILABLE)) == 0x00 || output_size == 0x00 || input_size == 0x00))) { + BT_INFO("InvalidOobTypeSet:%02x,Alg:%02x", oob_type, algorithms); goto fail; } } @@ -1358,6 +1380,7 @@ static void prov_capabilities(struct bt_mesh_prov_link *link, * send Remote Provisioning PDU Send with Public Key. */ if (bt_mesh_atomic_test_bit(link->flags, PB_REMOTE)) { + BT_DBG("WaitForRprClientCmd"); return; } @@ -1387,6 +1410,7 @@ static int prov_auth(struct bt_mesh_prov_link *link, bt_mesh_input_action_t input = 0U; uint8_t auth_size = PROV_AUTH_SIZE(link); + BT_INFO("ProvAuth:method:%d,action:%d,size:%d", method, action, size); switch (method) { case AUTH_METHOD_NO_OOB: if (action || size) { @@ -1778,6 +1802,7 @@ static void prov_gen_dh_key(struct bt_mesh_prov_link *link) */ if (link->auth_method == AUTH_METHOD_OUTPUT || link->auth_method == AUTH_METHOD_INPUT) { + BT_INFO("WaitForNextAction:%d", link->auth_method); return; } @@ -1814,6 +1839,7 @@ static void prov_gen_dh_key(struct bt_mesh_prov_link *link) * Input Complete, because if the authentication method is * Output OOB or Input OOB, it will directly return above. */ + BT_DBG("LinkExpect:%d", link->expect); if (link->expect != PROV_INPUT_COMPLETE) { send_confirm(link); } @@ -2094,6 +2120,7 @@ static void send_prov_data(struct bt_mesh_prov_link *link) link->unicast_addr = alloc_addr; } + BT_DBG("ProvAllocAddr:%04x", link->unicast_addr); bt_mesh_prov_buf_init(&buf, PROV_DATA); err = bt_mesh_prov_encrypt(session_key, nonce, pdu, net_buf_simple_add(&buf, 33)); @@ -2310,7 +2337,7 @@ static void prov_complete(struct bt_mesh_prov_link *link, static void prov_failed(struct bt_mesh_prov_link *link, struct net_buf_simple *buf) { - BT_WARN("Error 0x%02x", buf->data[0]); + BT_WARN("ProvError 0x%02x", buf->data[0]); close_link(link, CLOSE_REASON_FAILED); } @@ -2360,7 +2387,7 @@ static void close_link(struct bt_mesh_prov_link *link, uint8_t reason) #if CONFIG_BLE_MESH_PB_ADV static void link_ack(struct bt_mesh_prov_link *link, struct prov_rx *rx, struct net_buf_simple *buf) { - BT_DBG("len %u", buf->len); + BT_DBG("LinkAckLen %u", buf->len); if (buf->len) { BT_ERR("Invalid Link ACK length %d", buf->len); @@ -2388,7 +2415,7 @@ static void link_ack(struct bt_mesh_prov_link *link, struct prov_rx *rx, struct static void link_close(struct bt_mesh_prov_link *link, struct prov_rx *rx, struct net_buf_simple *buf) { - BT_DBG("len %u", buf->len); + BT_DBG("LinkCloseLen %u", buf->len); if (buf->len != 1) { BT_ERR("Invalid Link Close length %d", buf->len); @@ -2511,10 +2538,12 @@ static void gen_prov_ack(struct bt_mesh_prov_link *link, BT_DBG("len %u", buf->len); if (!link->tx.buf[0]) { + BT_DBG("NullTxbuf"); return; } if (!link->tx.id) { + BT_DBG("ZeroTxId"); return; } @@ -2620,7 +2649,7 @@ void bt_mesh_provisioner_pb_adv_recv(struct net_buf_simple *buf) rx.xact_id = net_buf_simple_pull_u8(buf); rx.gpc = net_buf_simple_pull_u8(buf); - BT_DBG("link_id 0x%08x xact_id %u", rx.link_id, rx.xact_id); + BT_DBG("link_id 0x%08x xact_id %u gpc %u", rx.link_id, rx.xact_id, rx.gpc); link = find_pba_link(rx.link_id); if (link == NULL) { @@ -2783,7 +2812,7 @@ static void protocol_timeout(struct k_work *work) { struct bt_mesh_prov_link *link = work->user_data; - BT_WARN("Protocol timeout"); + BT_WARN("Protocol timeout,LinkId:%08x", link->link_id); close_link(link, CLOSE_REASON_TIMEOUT); } @@ -3112,6 +3141,7 @@ int bt_mesh_rpr_cli_pdu_recv(struct bt_mesh_prov_link *link, uint8_t type, return -EINVAL; } + BT_INFO("RprCliProvType:%d", type); prov_handlers[type].func(link, buf); return 0; } From d7b93433bd10a000cc822d58347a5f168dfef46c Mon Sep 17 00:00:00 2001 From: Rainer Date: Wed, 3 Sep 2025 18:11:41 +0800 Subject: [PATCH 068/106] fix(ble_mesh): fixed issues with incorrect logs format and position --- components/bt/esp_ble_mesh/core/cfg_cli.c | 36 ++++++++++---------- components/bt/esp_ble_mesh/core/cfg_srv.c | 34 +++++++++--------- components/bt/esp_ble_mesh/core/friend.c | 6 ++-- components/bt/esp_ble_mesh/core/health_cli.c | 8 ++--- components/bt/esp_ble_mesh/core/net.c | 3 ++ 5 files changed, 45 insertions(+), 42 deletions(-) diff --git a/components/bt/esp_ble_mesh/core/cfg_cli.c b/components/bt/esp_ble_mesh/core/cfg_cli.c index e04588fab71..211f80e9edf 100644 --- a/components/bt/esp_ble_mesh/core/cfg_cli.c +++ b/components/bt/esp_ble_mesh/core/cfg_cli.c @@ -237,7 +237,7 @@ static void comp_data_status(struct bt_mesh_model *model, BT_DBG("CompDataStatus"); BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", ctx->net_idx, ctx->app_idx, ctx->addr); - BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); status.page = net_buf_simple_pull_u8(buf); status.comp_data = bt_mesh_alloc_buf(buf->len); @@ -260,7 +260,7 @@ static void state_status_u8(struct bt_mesh_model *model, BT_DBG("StateStatusU8"); BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", ctx->net_idx, ctx->app_idx, ctx->addr); - BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); status = net_buf_simple_pull_u8(buf); @@ -312,7 +312,7 @@ static void relay_status(struct bt_mesh_model *model, BT_DBG("RelayStatus"); BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", ctx->net_idx, ctx->app_idx, ctx->addr); - BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); status.relay = net_buf_simple_pull_u8(buf); status.retransmit = net_buf_simple_pull_u8(buf); @@ -329,7 +329,7 @@ static void net_key_status(struct bt_mesh_model *model, BT_DBG("NetKeyStatus"); BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", ctx->net_idx, ctx->app_idx, ctx->addr); - BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); status.status = net_buf_simple_pull_u8(buf); status.net_idx = net_buf_simple_pull_le16(buf) & 0xfff; @@ -346,7 +346,7 @@ static void app_key_status(struct bt_mesh_model *model, BT_DBG("AppKeyStatus"); BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", ctx->net_idx, ctx->app_idx, ctx->addr); - BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); status.status = net_buf_simple_pull_u8(buf); key_idx_unpack(buf, &status.net_idx, &status.app_idx); @@ -363,7 +363,7 @@ static void mod_app_status(struct bt_mesh_model *model, BT_DBG("ModAppStatus"); BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", ctx->net_idx, ctx->app_idx, ctx->addr); - BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); status.status = net_buf_simple_pull_u8(buf); status.elem_addr = net_buf_simple_pull_le16(buf); @@ -387,7 +387,7 @@ static void mod_pub_status(struct bt_mesh_model *model, BT_DBG("ModPubStatus"); BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", ctx->net_idx, ctx->app_idx, ctx->addr); - BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); status.status = net_buf_simple_pull_u8(buf); status.elem_addr = net_buf_simple_pull_le16(buf); @@ -417,7 +417,7 @@ static void mod_sub_status(struct bt_mesh_model *model, BT_DBG("ModSubStatus"); BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", ctx->net_idx, ctx->app_idx, ctx->addr); - BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); status.status = net_buf_simple_pull_u8(buf); status.elem_addr = net_buf_simple_pull_le16(buf); @@ -441,7 +441,7 @@ static void hb_sub_status(struct bt_mesh_model *model, BT_DBG("HbSubStatus"); BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", ctx->net_idx, ctx->app_idx, ctx->addr); - BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); status.status = net_buf_simple_pull_u8(buf); status.src = net_buf_simple_pull_le16(buf); @@ -463,7 +463,7 @@ static void hb_pub_status(struct bt_mesh_model *model, BT_DBG("HbPubStatus"); BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", ctx->net_idx, ctx->app_idx, ctx->addr); - BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); status.status = net_buf_simple_pull_u8(buf); status.dst = net_buf_simple_pull_le16(buf); @@ -483,7 +483,7 @@ static void node_reset_status(struct bt_mesh_model *model, BT_DBG("NodeResetStatus"); BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", ctx->net_idx, ctx->app_idx, ctx->addr); - BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); cfg_client_recv_status(model, ctx, NULL, 0); } @@ -497,7 +497,7 @@ static void mod_sub_list(struct bt_mesh_model *model, BT_DBG("ModSubList"); BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", ctx->net_idx, ctx->app_idx, ctx->addr); - BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); list.status = net_buf_simple_pull_u8(buf); list.elem_addr = net_buf_simple_pull_le16(buf); @@ -527,7 +527,7 @@ static void net_key_list(struct bt_mesh_model *model, BT_DBG("NetKeyList"); BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", ctx->net_idx, ctx->app_idx, ctx->addr); - BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); list.net_idx = bt_mesh_alloc_buf(buf->len); if (!list.net_idx) { @@ -548,7 +548,7 @@ static void app_key_list(struct bt_mesh_model *model, BT_DBG("AppKeyList"); BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", ctx->net_idx, ctx->app_idx, ctx->addr); - BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); list.status = net_buf_simple_pull_u8(buf); list.net_idx = net_buf_simple_pull_le16(buf); @@ -571,7 +571,7 @@ static void node_id_status(struct bt_mesh_model *model, BT_DBG("NodeIDStatus"); BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", ctx->net_idx, ctx->app_idx, ctx->addr); - BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); status.status = net_buf_simple_pull_u8(buf); status.net_idx = net_buf_simple_pull_le16(buf); @@ -589,7 +589,7 @@ static void mod_app_list(struct bt_mesh_model *model, BT_DBG("ModAppList"); BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", ctx->net_idx, ctx->app_idx, ctx->addr); - BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); list.status = net_buf_simple_pull_u8(buf); list.elem_addr = net_buf_simple_pull_le16(buf); @@ -619,7 +619,7 @@ static void kr_phase_status(struct bt_mesh_model *model, BT_DBG("KrPhaseStatus"); BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", ctx->net_idx, ctx->app_idx, ctx->addr); - BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); status.status = net_buf_simple_pull_u8(buf); status.net_idx = net_buf_simple_pull_le16(buf); @@ -637,7 +637,7 @@ static void lpn_pollto_status(struct bt_mesh_model *model, BT_DBG("LPNPollToStatus"); BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", ctx->net_idx, ctx->app_idx, ctx->addr); - BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); status.lpn_addr = net_buf_simple_pull_le16(buf); status.timeout = net_buf_simple_pull_u8(buf); diff --git a/components/bt/esp_ble_mesh/core/cfg_srv.c b/components/bt/esp_ble_mesh/core/cfg_srv.c index 84cdb59b3aa..12448eec81e 100644 --- a/components/bt/esp_ble_mesh/core/cfg_srv.c +++ b/components/bt/esp_ble_mesh/core/cfg_srv.c @@ -144,7 +144,7 @@ static void get_comp_data(struct net_buf_simple *buf, } } - BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); } static int fetch_comp_data(struct net_buf_simple *buf, @@ -213,7 +213,7 @@ static void comp_data_get(struct bt_mesh_model *model, BT_DBG("CompDataGet"); BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", ctx->net_idx, ctx->app_idx, ctx->addr); - BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); /* TODO: * @@ -817,7 +817,7 @@ static void beacon_get(struct bt_mesh_model *model, BT_DBG("BeaconGet"); BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", ctx->net_idx, ctx->app_idx, ctx->addr); - BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); bt_mesh_model_msg_init(&msg, OP_BEACON_STATUS); net_buf_simple_add_u8(&msg, bt_mesh_secure_beacon_get()); @@ -837,7 +837,7 @@ static void beacon_set(struct bt_mesh_model *model, BT_DBG("BeaconSet"); BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", ctx->net_idx, ctx->app_idx, ctx->addr); - BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); if (!cfg) { BT_WARN("No Configuration Server context available"); @@ -877,7 +877,7 @@ static void default_ttl_get(struct bt_mesh_model *model, BT_DBG("DefaultTTLGet"); BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", ctx->net_idx, ctx->app_idx, ctx->addr); - BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); bt_mesh_model_msg_init(&msg, OP_DEFAULT_TTL_STATUS); net_buf_simple_add_u8(&msg, bt_mesh_default_ttl_get()); @@ -897,7 +897,7 @@ static void default_ttl_set(struct bt_mesh_model *model, BT_DBG("DefaultTTLSet"); BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", ctx->net_idx, ctx->app_idx, ctx->addr); - BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); if (!cfg) { BT_WARN("No Configuration Server context available"); @@ -944,7 +944,7 @@ static void gatt_proxy_get(struct bt_mesh_model *model, BT_DBG("GattProxyGet"); BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", ctx->net_idx, ctx->app_idx, ctx->addr); - BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); send_gatt_proxy_status(model, ctx); } @@ -958,7 +958,7 @@ static void gatt_proxy_set(struct bt_mesh_model *model, BT_DBG("GattProxySet"); BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", ctx->net_idx, ctx->app_idx, ctx->addr); - BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); if (buf->data[0] != 0x00 && buf->data[0] != 0x01) { BT_WARN("Invalid GATT Proxy value 0x%02x", buf->data[0]); @@ -1021,7 +1021,7 @@ static void net_transmit_get(struct bt_mesh_model *model, BT_DBG("NetTransmitGet"); BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", ctx->net_idx, ctx->app_idx, ctx->addr); - BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); bt_mesh_model_msg_init(&msg, OP_NET_TRANSMIT_STATUS); net_buf_simple_add_u8(&msg, bt_mesh_net_transmit_get()); @@ -1041,7 +1041,7 @@ static void net_transmit_set(struct bt_mesh_model *model, BT_DBG("NetTransmitSet"); BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", ctx->net_idx, ctx->app_idx, ctx->addr); - BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); BT_DBG("Transmit 0x%02x Count %u Interval %u", buf->data[0], @@ -1075,7 +1075,7 @@ static void relay_get(struct bt_mesh_model *model, BT_DBG("RelayGet"); BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", ctx->net_idx, ctx->app_idx, ctx->addr); - BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); bt_mesh_model_msg_init(&msg, OP_RELAY_STATUS); net_buf_simple_add_u8(&msg, bt_mesh_relay_get()); @@ -1096,7 +1096,7 @@ static void relay_set(struct bt_mesh_model *model, BT_DBG("RelaySet"); BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", ctx->net_idx, ctx->app_idx, ctx->addr); - BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); if (!cfg) { BT_WARN("No Configuration Server context available"); @@ -2777,7 +2777,7 @@ static void node_identity_get(struct bt_mesh_model *model, BT_DBG("NodeIdentityGet"); BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", ctx->net_idx, ctx->app_idx, ctx->addr); - BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); idx = net_buf_simple_pull_le16(buf); if (idx > 0xfff) { @@ -2817,7 +2817,7 @@ static void node_identity_set(struct bt_mesh_model *model, BT_DBG("NodeIdentitySet"); BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", ctx->net_idx, ctx->app_idx, ctx->addr); - BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); idx = net_buf_simple_pull_le16(buf); if (idx > 0xfff) { @@ -3098,7 +3098,7 @@ static void node_reset(struct bt_mesh_model *model, BT_DBG("NodeReset"); BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", ctx->net_idx, ctx->app_idx, ctx->addr); - BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); bt_mesh_model_msg_init(&msg, OP_NODE_RESET_STATUS); @@ -3137,7 +3137,7 @@ static void friend_get(struct bt_mesh_model *model, BT_DBG("FrndGet"); BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", ctx->net_idx, ctx->app_idx, ctx->addr); - BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); send_friend_status(model, ctx); } @@ -3151,7 +3151,7 @@ static void friend_set(struct bt_mesh_model *model, BT_DBG("FrndSet"); BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", ctx->net_idx, ctx->app_idx, ctx->addr); - BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); if (buf->data[0] != 0x00 && buf->data[0] != 0x01) { BT_WARN("Invalid Friend value 0x%02x", buf->data[0]); diff --git a/components/bt/esp_ble_mesh/core/friend.c b/components/bt/esp_ble_mesh/core/friend.c index 07de4b7d3c8..0f602f1d356 100644 --- a/components/bt/esp_ble_mesh/core/friend.c +++ b/components/bt/esp_ble_mesh/core/friend.c @@ -332,7 +332,7 @@ static bool friend_sub_exist(struct bt_mesh_friend *frnd, uint16_t addr) { int i; - BT_DBG("IsFrndSubExist, Addr 0x%04x"); + BT_DBG("IsFrndSubExist, Addr 0x%04x", addr); for (i = 0; i < ARRAY_SIZE(frnd->sub_list); i++) { if (frnd->sub_list[i] == addr) { @@ -347,7 +347,7 @@ static void friend_sub_add(struct bt_mesh_friend *frnd, uint16_t addr) { int i; - BT_DBG("FrndSubAdd, Addr 0x%04x"); + BT_DBG("FrndSubAdd, Addr 0x%04x", addr); for (i = 0; i < ARRAY_SIZE(frnd->sub_list); i++) { if (frnd->sub_list[i] == BLE_MESH_ADDR_UNASSIGNED) { @@ -363,7 +363,7 @@ static void friend_sub_rem(struct bt_mesh_friend *frnd, uint16_t addr) { int i; - BT_DBG("FrndSubRem, Addr 0x%04x"); + BT_DBG("FrndSubRem, Addr 0x%04x", addr); for (i = 0; i < ARRAY_SIZE(frnd->sub_list); i++) { if (frnd->sub_list[i] == addr) { diff --git a/components/bt/esp_ble_mesh/core/health_cli.c b/components/bt/esp_ble_mesh/core/health_cli.c index 829ae336932..c458710db12 100644 --- a/components/bt/esp_ble_mesh/core/health_cli.c +++ b/components/bt/esp_ble_mesh/core/health_cli.c @@ -138,7 +138,7 @@ static void health_fault_status(struct bt_mesh_model *model, BT_DBG("HealthFaultStatus"); BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", ctx->net_idx, ctx->app_idx, ctx->addr); - BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); status.test_id = net_buf_simple_pull_u8(buf); status.cid = net_buf_simple_pull_le16(buf); @@ -162,7 +162,7 @@ static void health_current_status(struct bt_mesh_model *model, BT_DBG("HealthCurrentStatus"); BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", ctx->net_idx, ctx->app_idx, ctx->addr); - BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); status.test_id = net_buf_simple_pull_u8(buf); status.cid = net_buf_simple_pull_le16(buf); @@ -186,7 +186,7 @@ static void health_period_status(struct bt_mesh_model *model, BT_DBG("HealthPeriodStatus"); BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", ctx->net_idx, ctx->app_idx, ctx->addr); - BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); status = net_buf_simple_pull_u8(buf); @@ -202,7 +202,7 @@ static void health_attention_status(struct bt_mesh_model *model, BT_DBG("HealthAttentionStatus"); BT_DBG("NetIdx 0x%04x AppIdx 0x%04x Src 0x%04x", ctx->net_idx, ctx->app_idx, ctx->addr); - BT_DBG("Len %u: %s", bt_hex(buf->data, buf->len)); + BT_DBG("Len %u: %s", buf->len, bt_hex(buf->data, buf->len)); status = net_buf_simple_pull_u8(buf); diff --git a/components/bt/esp_ble_mesh/core/net.c b/components/bt/esp_ble_mesh/core/net.c index 5ddbb46ca03..3282120de81 100644 --- a/components/bt/esp_ble_mesh/core/net.c +++ b/components/bt/esp_ble_mesh/core/net.c @@ -2094,6 +2094,9 @@ void bt_mesh_generic_net_recv(struct net_buf_simple *data, /* Save the state so the buffer can later be relayed */ net_buf_simple_save(buf, &state); + BT_DBG("NetRecv, Src 0x%04x Dst 0x%04x Rssi %d NetIf %u", + rx->ctx.addr, rx->ctx.recv_dst, rx->ctx.recv_rssi, net_if); + BT_BQB(BLE_MESH_BQB_TEST_LOG_LEVEL_PRIMARY_ID_NODE | \ BLE_MESH_BQB_TEST_LOG_LEVEL_SUB_ID_NET, "\nNetRecv: ctl: %d, src: %d, dst: %d, ttl: %d, data: 0x%s", From 6b97b01c554218c28ab72d9d8ee29361c2308caa Mon Sep 17 00:00:00 2001 From: luoxu Date: Tue, 9 Sep 2025 15:31:01 +0800 Subject: [PATCH 069/106] fix(ble_mesh): resolve miscellaneous logging issues --- components/bt/esp_ble_mesh/core/adv.c | 4 +- components/bt/esp_ble_mesh/core/adv_common.c | 55 ++++--------------- components/bt/esp_ble_mesh/core/adv_common.h | 42 ++++++++++++++ components/bt/esp_ble_mesh/core/cfg_srv.c | 2 +- components/bt/esp_ble_mesh/core/ext_adv.c | 3 +- components/bt/esp_ble_mesh/core/friend.c | 4 +- components/bt/esp_ble_mesh/core/net.c | 2 +- components/bt/esp_ble_mesh/core/prov_pvnr.c | 2 +- .../bt/esp_ble_mesh/core/proxy_server.c | 8 +-- components/bt/esp_ble_mesh/core/transport.c | 2 +- .../bt/esp_ble_mesh/core/transport.enh.c | 20 +------ 11 files changed, 67 insertions(+), 77 deletions(-) diff --git a/components/bt/esp_ble_mesh/core/adv.c b/components/bt/esp_ble_mesh/core/adv.c index bb7b9771ca1..9a12e8c1254 100644 --- a/components/bt/esp_ble_mesh/core/adv.c +++ b/components/bt/esp_ble_mesh/core/adv.c @@ -29,10 +29,8 @@ static struct bt_mesh_adv_queue *adv_queue; #if CONFIG_BLE_MESH_RELAY_ADV_BUF -#define BLE_MESH_RELAY_QUEUE_SIZE CONFIG_BLE_MESH_RELAY_ADV_BUF_COUNT - static QueueSetHandle_t mesh_queue_set; -#define BLE_MESH_QUEUE_SET_SIZE (BLE_MESH_ADV_QUEUE_SIZE + BLE_MESH_RELAY_QUEUE_SIZE) +#define BLE_MESH_QUEUE_SET_SIZE (bt_mesh_adv_buf_count_get() + bt_mesh_relay_adv_buf_count_get()) #endif /* CONFIG_BLE_MESH_RELAY_ADV_BUF */ static int adv_send(struct net_buf *buf) diff --git a/components/bt/esp_ble_mesh/core/adv_common.c b/components/bt/esp_ble_mesh/core/adv_common.c index 193dcf4c43b..ff4e50ac1c8 100644 --- a/components/bt/esp_ble_mesh/core/adv_common.c +++ b/components/bt/esp_ble_mesh/core/adv_common.c @@ -158,7 +158,7 @@ int bt_mesh_adv_inst_init(enum bt_mesh_adv_inst_type inst_type, uint8_t inst_id) return -EINVAL; } - if (inst_id == BLE_MESH_ADV_INS_UNUSED) { + if (inst_id == BLE_MESH_ADV_INST_UNUSED) { BT_ERR("UnusedAdvInstID"); return -EINVAL; } @@ -181,7 +181,7 @@ int bt_mesh_adv_inst_deinit(enum bt_mesh_adv_inst_type inst_type) bt_le_ext_adv_stop(adv_insts[inst_type].id); - adv_insts[inst_type].id = BLE_MESH_ADV_INS_UNUSED; + adv_insts[inst_type].id = BLE_MESH_ADV_INST_UNUSED; #if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV adv_insts[inst_type].spt_mask = 0; #endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ @@ -243,7 +243,7 @@ struct bt_mesh_adv *ext_long_relay_adv_alloc(int id, enum bt_mesh_adv_type type) #endif /* CONFIG_BLE_MESH_LONG_PACKET_RELAY_ADV_BUF_COUNT */ #endif /* CONFIG_BLE_MESH_LONG_PACKET */ -struct bt_mesh_adv_type_manager *bt_mesh_adv_types_mgnt_get(enum bt_mesh_adv_type adv_type) +struct bt_mesh_adv_type_manager *bt_mesh_adv_types_mgmt_get(enum bt_mesh_adv_type adv_type) { BT_DBG("AdvTypeMgmtGet, AdvType %u", adv_type); @@ -668,21 +668,6 @@ uint16_t bt_mesh_get_stored_relay_count(void) return count; } -static ALWAYS_INLINE -uint16_t bt_mesh_relay_adv_buf_count_get(void) -{ - uint16_t relay_adv_count = 2 + CONFIG_BLE_MESH_RELAY_ADV_BUF_COUNT; - -#if CONFIG_BLE_MESH_EXT_ADV && CONFIG_BLE_MESH_RELAY - relay_adv_count += CONFIG_BLE_MESH_EXT_RELAY_ADV_BUF_COUNT; -#endif - -#if CONFIG_BLE_MESH_LONG_PACKET && CONFIG_BLE_MESH_RELAY - relay_adv_count += CONFIG_BLE_MESH_LONG_PACKET_RELAY_ADV_BUF_COUNT; -#endif - return relay_adv_count; -} - void bt_mesh_relay_adv_init(void) { BT_DBG("RelayAdvInit"); @@ -806,33 +791,6 @@ void bt_mesh_frnd_adv_deinit(void) } #endif /* CONFIG_BLE_MESH_FRIEND */ -static ALWAYS_INLINE -uint16_t bt_mesh_adv_buf_count_get(void) -{ - uint16_t adv_count = 2 + CONFIG_BLE_MESH_ADV_BUF_COUNT; - -#if CONFIG_BLE_MESH_EXT_ADV - adv_count += CONFIG_BLE_MESH_EXT_ADV_BUF_COUNT; -#if !CONFIG_BLE_MESH_RELAY_ADV_BUF && CONFIG_BLE_MESH_RELAY - adv_count += CONFIG_BLE_MESH_EXT_RELAY_ADV_BUF_COUNT; -#endif /* !CONFIG_BLE_MESH_RELAY_ADV_BUF && CONFIG_BLE_MESH_RELAY */ -#endif /* CONFIG_BLE_MESH_EXT_ADV */ - -#if CONFIG_BLE_MESH_LONG_PACKET - adv_count += CONFIG_BLE_MESH_LONG_PACKET_ADV_BUF_COUNT; -#if !CONFIG_BLE_MESH_RELAY_ADV_BUF && CONFIG_BLE_MESH_RELAY - adv_count += CONFIG_BLE_MESH_LONG_PACKET_RELAY_ADV_BUF_COUNT; -#endif /* !CONFIG_BLE_MESH_RELAY_ADV_BUF && CONFIG_BLE_MESH_RELAY */ -#endif /* CONFIG_BLE_MESH_LONG_PACKET */ - -#if (CONFIG_BLE_MESH_SUPPORT_BLE_ADV && \ - !(CONFIG_BLE_MESH_USE_BLE_50 && CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE)) - adv_count += CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT; -#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ - - return adv_count; -} - void bt_mesh_adv_task_init(void adv_thread(void *p)) { BT_DBG("AdvTaskInit"); @@ -861,7 +819,14 @@ void bt_mesh_adv_task_init(void adv_thread(void *p)) #else /* CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL && (CONFIG_SPIRAM_CACHE_WORKAROUND || !CONFIG_IDF_TARGET_ESP32) && CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY */ int ret = xTaskCreatePinnedToCore(adv_thread, BLE_MESH_ADV_TASK_NAME, BLE_MESH_ADV_TASK_STACK_SIZE, NULL, BLE_MESH_ADV_TASK_PRIO, &adv_task.handle, BLE_MESH_ADV_TASK_CORE); +#if CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE + if (ret != pdTRUE) { + BT_ERR("xTaskCreatePinnedToCore failed, ret %d", ret); + return; + } +#else assert(ret == pdTRUE); +#endif /* CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE */ #endif /* CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL && (CONFIG_SPIRAM_CACHE_WORKAROUND || !CONFIG_IDF_TARGET_ESP32) && CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY */ } diff --git a/components/bt/esp_ble_mesh/core/adv_common.h b/components/bt/esp_ble_mesh/core/adv_common.h index f77079a648e..54267ee5222 100644 --- a/components/bt/esp_ble_mesh/core/adv_common.h +++ b/components/bt/esp_ble_mesh/core/adv_common.h @@ -298,6 +298,21 @@ void bt_mesh_adv_inst_type_clear(enum bt_mesh_adv_inst_type inst_type, #endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ #if CONFIG_BLE_MESH_RELAY_ADV_BUF +static ALWAYS_INLINE +uint16_t bt_mesh_relay_adv_buf_count_get(void) +{ + uint16_t relay_adv_count = 2 + CONFIG_BLE_MESH_RELAY_ADV_BUF_COUNT; + +#if CONFIG_BLE_MESH_EXT_ADV && CONFIG_BLE_MESH_RELAY + relay_adv_count += CONFIG_BLE_MESH_EXT_RELAY_ADV_BUF_COUNT; +#endif + +#if CONFIG_BLE_MESH_LONG_PACKET && CONFIG_BLE_MESH_RELAY + relay_adv_count += CONFIG_BLE_MESH_LONG_PACKET_RELAY_ADV_BUF_COUNT; +#endif + return relay_adv_count; +} + void bt_mesh_relay_adv_init(void); bool bt_mesh_ignore_relay_packet(uint32_t timestamp); @@ -325,6 +340,33 @@ void bt_mesh_frnd_adv_deinit(void); #endif /* CONFIG_BLE_MESH_DEINIT */ #endif /* CONFIG_BLE_MESH_FRIEND */ +static ALWAYS_INLINE +uint16_t bt_mesh_adv_buf_count_get(void) +{ + uint16_t adv_count = 2 + CONFIG_BLE_MESH_ADV_BUF_COUNT; + +#if CONFIG_BLE_MESH_EXT_ADV + adv_count += CONFIG_BLE_MESH_EXT_ADV_BUF_COUNT; +#if !CONFIG_BLE_MESH_RELAY_ADV_BUF && CONFIG_BLE_MESH_RELAY + adv_count += CONFIG_BLE_MESH_EXT_RELAY_ADV_BUF_COUNT; +#endif /* !CONFIG_BLE_MESH_RELAY_ADV_BUF && CONFIG_BLE_MESH_RELAY */ +#endif /* CONFIG_BLE_MESH_EXT_ADV */ + +#if CONFIG_BLE_MESH_LONG_PACKET + adv_count += CONFIG_BLE_MESH_LONG_PACKET_ADV_BUF_COUNT; +#if !CONFIG_BLE_MESH_RELAY_ADV_BUF && CONFIG_BLE_MESH_RELAY + adv_count += CONFIG_BLE_MESH_LONG_PACKET_RELAY_ADV_BUF_COUNT; +#endif /* !CONFIG_BLE_MESH_RELAY_ADV_BUF && CONFIG_BLE_MESH_RELAY */ +#endif /* CONFIG_BLE_MESH_LONG_PACKET */ + +#if (CONFIG_BLE_MESH_SUPPORT_BLE_ADV && \ + !(CONFIG_BLE_MESH_USE_BLE_50 && CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE)) + adv_count += CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT; +#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ + + return adv_count; +} + void bt_mesh_adv_task_init(void adv_thread(void *p)); void bt_mesh_adv_common_init(void); diff --git a/components/bt/esp_ble_mesh/core/cfg_srv.c b/components/bt/esp_ble_mesh/core/cfg_srv.c index 12448eec81e..9be3e519834 100644 --- a/components/bt/esp_ble_mesh/core/cfg_srv.c +++ b/components/bt/esp_ble_mesh/core/cfg_srv.c @@ -3356,7 +3356,7 @@ static void krp_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, static uint8_t hb_log(uint16_t val) { BT_DBG("HbLog, Val 0x%04x", val); - + switch (val) { case 0x0000: return 0x00; diff --git a/components/bt/esp_ble_mesh/core/ext_adv.c b/components/bt/esp_ble_mesh/core/ext_adv.c index 37000ce73ef..8b85076aedb 100644 --- a/components/bt/esp_ble_mesh/core/ext_adv.c +++ b/components/bt/esp_ble_mesh/core/ext_adv.c @@ -142,7 +142,8 @@ static int adv_send(struct bt_mesh_adv_inst *inst, uint16_t *adv_duration) err = bt_le_ext_adv_start(inst->id, ¶m, &ad, 1, NULL, 0); } - break; + } + break; #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV case BLE_MESH_ADV_BLE: diff --git a/components/bt/esp_ble_mesh/core/friend.c b/components/bt/esp_ble_mesh/core/friend.c index 0f602f1d356..46060d3b0f2 100644 --- a/components/bt/esp_ble_mesh/core/friend.c +++ b/components/bt/esp_ble_mesh/core/friend.c @@ -792,7 +792,7 @@ int bt_mesh_friend_sub_rem(struct bt_mesh_net_rx *rx, static void enqueue_buf(struct bt_mesh_friend *frnd, struct net_buf *buf) { - BT_DBG("EnqueueBuf, Buf %p QueueSize %u", __func__, buf, frnd->queue_size); + BT_DBG("EnqueueBuf, Buf %p QueueSize %u", buf, frnd->queue_size); net_buf_slist_put(&frnd->queue, buf); frnd->queue_size++; @@ -802,7 +802,7 @@ static void enqueue_update(struct bt_mesh_friend *frnd, uint8_t md) { struct net_buf *buf = NULL; - BT_DBG("EnqueueUpdate, LPN 0x%04x MD %u", __func__, frnd->lpn, md); + BT_DBG("EnqueueUpdate, LPN 0x%04x MD %u", frnd->lpn, md); buf = encode_update(frnd, md); if (!buf) { diff --git a/components/bt/esp_ble_mesh/core/net.c b/components/bt/esp_ble_mesh/core/net.c index 3282120de81..fde5b5cdda7 100644 --- a/components/bt/esp_ble_mesh/core/net.c +++ b/components/bt/esp_ble_mesh/core/net.c @@ -104,7 +104,7 @@ static bool check_dup(struct net_buf_simple *data) } } - BT_DBG("DupCacheAdd, CacheNext %ld", val, dup_cache_next); + BT_DBG("DupCacheAdd, CacheNext %ld %d", val, dup_cache_next); dup_cache[dup_cache_next++] = val; dup_cache_next %= ARRAY_SIZE(dup_cache); diff --git a/components/bt/esp_ble_mesh/core/prov_pvnr.c b/components/bt/esp_ble_mesh/core/prov_pvnr.c index e51c7a8d1d4..d1df4a69e11 100644 --- a/components/bt/esp_ble_mesh/core/prov_pvnr.c +++ b/components/bt/esp_ble_mesh/core/prov_pvnr.c @@ -2812,7 +2812,7 @@ static void protocol_timeout(struct k_work *work) { struct bt_mesh_prov_link *link = work->user_data; - BT_WARN("Protocol timeout,LinkId:%08x", link->link_id); + BT_WARN("Protocol timeout,RmtAddr:%s", bt_hex(link->addr.val, 6)); close_link(link, CLOSE_REASON_TIMEOUT); } diff --git a/components/bt/esp_ble_mesh/core/proxy_server.c b/components/bt/esp_ble_mesh/core/proxy_server.c index 6a498f75086..6021ca7f8fb 100644 --- a/components/bt/esp_ble_mesh/core/proxy_server.c +++ b/components/bt/esp_ble_mesh/core/proxy_server.c @@ -36,7 +36,7 @@ _Static_assert(!(IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) && IS_ENABLED(CON #endif #if CONFIG_BLE_MESH_USE_BLE_50 -static uint8_t proxy_adv_inst = BLE_MESH_ADV_INS_UNUSED; +static uint8_t proxy_adv_inst = BLE_MESH_ADV_INST_UNUSED; #endif /* CONFIG_BLE_MESH_USE_BLE_50 */ #define ADV_OPT (BLE_MESH_ADV_OPT_CONNECTABLE | BLE_MESH_ADV_OPT_ONE_TIME) @@ -2028,7 +2028,7 @@ int32_t bt_mesh_proxy_server_adv_start(void) } #if CONFIG_BLE_MESH_USE_BLE_50 - if (proxy_adv_inst == BLE_MESH_ADV_INS_UNUSED) { + if (proxy_adv_inst == BLE_MESH_ADV_INST_UNUSED) { BT_DBG("ProxyAdvInstUnused"); return K_FOREVER; } @@ -2108,7 +2108,7 @@ int bt_mesh_proxy_server_adv_stop(void) } #if CONFIG_BLE_MESH_USE_BLE_50 - if (proxy_adv_inst == BLE_MESH_ADV_INS_UNUSED) { + if (proxy_adv_inst == BLE_MESH_ADV_INST_UNUSED) { BT_ERR("Proxy adv inst is not initialized!"); return -EINVAL; } @@ -2189,7 +2189,7 @@ int bt_mesh_proxy_server_deinit(void) BT_DBG("ProxyServerDeinit"); #if CONFIG_BLE_MESH_USE_BLE_50 - proxy_adv_inst = BLE_MESH_ADV_INS_UNUSED; + proxy_adv_inst = BLE_MESH_ADV_INST_UNUSED; #endif /* CONFIG_BLE_MESH_USE_BLE_50 */ bt_mesh_proxy_server_adv_flag_set(false); diff --git a/components/bt/esp_ble_mesh/core/transport.c b/components/bt/esp_ble_mesh/core/transport.c index 62704ccfa8b..204854e241c 100644 --- a/components/bt/esp_ble_mesh/core/transport.c +++ b/components/bt/esp_ble_mesh/core/transport.c @@ -788,7 +788,7 @@ int bt_mesh_trans_send(struct bt_mesh_net_tx *tx, struct net_buf_simple *msg, uint8_t aid = 0U; int err = 0; - BT_DBG("TransSend"); + BT_DBG("transcend"); if (msg->len < 1) { BT_ERR("Zero-length SDU not allowed"); diff --git a/components/bt/esp_ble_mesh/core/transport.enh.c b/components/bt/esp_ble_mesh/core/transport.enh.c index 5721d6635ad..967b5233796 100644 --- a/components/bt/esp_ble_mesh/core/transport.enh.c +++ b/components/bt/esp_ble_mesh/core/transport.enh.c @@ -1199,7 +1199,7 @@ int bt_mesh_trans_send(struct bt_mesh_net_tx *tx, struct net_buf_simple *msg, uint8_t aid = 0U; int err = 0; - BT_DBG("TransSend"); + BT_DBG("transcend"); if (msg->len < 1) { BT_ERR("Zero-length SDU not allowed"); @@ -2220,7 +2220,6 @@ static struct seg_rx *seg_rx_alloc(struct bt_mesh_net_rx *net_rx, { int err = 0; -<<<<<<< HEAD /* By default, traditional seg_rx is used for allocation. * If the first segment received is the last segment of * the long packet, and its length is the length of the traditional packet, @@ -2240,12 +2239,8 @@ static struct seg_rx *seg_rx_alloc(struct bt_mesh_net_rx *net_rx, for (size_t i = 0; i < rx_buf_size; i++) { struct seg_rx *rx = &seg_rx_buf[i]; -======= - BT_DBG("SegRxAlloc, SegN %u", seg_n); - for (size_t i = 0; i < ARRAY_SIZE(seg_rx); i++) { - struct seg_rx *rx = &seg_rx[i]; ->>>>>>> 7652269a401 (feat(ble_mesh): Miscellaneous log enhancement for BLE Mesh) + BT_DBG("SegRxAlloc, SegN %u", seg_n); if (rx->in_use) { continue; @@ -2474,20 +2469,14 @@ found_rx: /* Set the expected final buffer length */ rx->buf.len = seg_n * seg_len(&si) + buf->len; -<<<<<<< HEAD BT_DBG("Target len %u * %u + %u = %u", seg_n, seg_len(&si), buf->len, rx->buf.len); -======= - BT_DBG("Target len %u * %u + %u = %u", - seg_n, seg_len(rx->ctl), buf->len, rx->buf.len); ->>>>>>> 7652269a401 (feat(ble_mesh): Miscellaneous log enhancement for BLE Mesh) /* This should not happen, since we have made sure the whole * SDU could be received while handling the first segment. * But if the peer device sends the segments of a segmented * message with different CTL, then the following could happen. */ -<<<<<<< HEAD if ((!rx->ext && rx->buf.len > CONFIG_BLE_MESH_RX_SDU_MAX) #if CONFIG_BLE_MESH_LONG_PACKET || (rx->ext && rx->buf.len > BLE_MESH_EXT_RX_SDU_MAX) @@ -2495,11 +2484,6 @@ found_rx: ) { BT_ERR("Too large SDU len %u/%u", rx->buf.len, CONFIG_BLE_MESH_RX_SDU_MAX); -======= - if (rx->buf.len > CONFIG_BLE_MESH_RX_SDU_MAX) { - BT_ERR("Too large SDU len %u/%u", - rx->buf.len, CONFIG_BLE_MESH_RX_SDU_MAX); ->>>>>>> 7652269a401 (feat(ble_mesh): Miscellaneous log enhancement for BLE Mesh) send_ack(net_rx->sub, net_rx->ctx.recv_dst, net_rx->ctx.addr, net_rx->ctx.send_ttl, From ed7e22cdc755d749938c58312f9803f65a0286ec Mon Sep 17 00:00:00 2001 From: liqigan Date: Thu, 23 Oct 2025 18:08:59 +0800 Subject: [PATCH 070/106] fix(bt/bluedroid): Fixed HID memory leak --- components/bt/common/osi/allocator.c | 5 +---- components/bt/host/bluedroid/api/esp_hidd_api.c | 2 +- components/bt/host/bluedroid/api/esp_hidh_api.c | 6 +++--- components/bt/host/bluedroid/btc/profile/std/hid/btc_hd.c | 6 ++++-- components/bt/host/bluedroid/btc/profile/std/hid/btc_hh.c | 6 ++++-- .../bt/host/bluedroid/btc/profile/std/include/btc_hd.h | 2 +- .../bt/host/bluedroid/btc/profile/std/include/btc_hh.h | 3 +-- components/bt/host/bluedroid/stack/hid/hidd_conn.c | 1 + components/bt/host/bluedroid/stack/l2cap/l2c_utils.c | 2 +- 9 files changed, 17 insertions(+), 16 deletions(-) diff --git a/components/bt/common/osi/allocator.c b/components/bt/common/osi/allocator.c index 86fb705b071..0293daa8c4e 100644 --- a/components/bt/common/osi/allocator.c +++ b/components/bt/common/osi/allocator.c @@ -241,8 +241,5 @@ void *osi_calloc_func(size_t size) void osi_free_func(void *ptr) { -#if HEAP_MEMORY_DEBUG - osi_mem_dbg_clean(ptr, __func__, __LINE__); -#endif - free(ptr); + osi_free(ptr); } diff --git a/components/bt/host/bluedroid/api/esp_hidd_api.c b/components/bt/host/bluedroid/api/esp_hidd_api.c index d7c043666d1..483ba412919 100644 --- a/components/bt/host/bluedroid/api/esp_hidd_api.c +++ b/components/bt/host/bluedroid/api/esp_hidd_api.c @@ -133,7 +133,7 @@ esp_err_t esp_bt_hid_device_send_report(esp_hidd_report_type_t type, uint8_t id, args.send_report.data = data; bt_status_t stat = btc_transfer_context(&msg, &args, sizeof(btc_hidd_args_t), - btc_hd_arg_deep_copy, btc_hd_cb_arg_deep_free); + btc_hd_arg_deep_copy, btc_hd_call_arg_deep_free); return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; } diff --git a/components/bt/host/bluedroid/api/esp_hidh_api.c b/components/bt/host/bluedroid/api/esp_hidh_api.c index e029ee654a0..f1c39bded88 100644 --- a/components/bt/host/bluedroid/api/esp_hidh_api.c +++ b/components/bt/host/bluedroid/api/esp_hidh_api.c @@ -117,7 +117,7 @@ esp_err_t esp_bt_hid_host_set_info(esp_bd_addr_t bd_addr, esp_hidh_hid_info_t *h arg.set_info.hid_info = hid_info; bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hidh_args_t), - btc_hh_arg_deep_copy, btc_hh_cb_arg_deep_free); + btc_hh_arg_deep_copy, btc_hh_call_arg_deep_free); return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; } @@ -224,7 +224,7 @@ esp_err_t esp_bt_hid_host_set_report(esp_bd_addr_t bd_addr, esp_hidh_report_type arg.set_report.report = report; bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hidh_args_t), - btc_hh_arg_deep_copy, btc_hh_cb_arg_deep_free); + btc_hh_arg_deep_copy, btc_hh_call_arg_deep_free); return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; } @@ -243,7 +243,7 @@ esp_err_t esp_bt_hid_host_send_data(esp_bd_addr_t bd_addr, uint8_t *data, size_t arg.send_data.data = data; bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hidh_args_t), - btc_hh_arg_deep_copy, btc_hh_cb_arg_deep_free); + btc_hh_arg_deep_copy, btc_hh_call_arg_deep_free); return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; } diff --git a/components/bt/host/bluedroid/btc/profile/std/hid/btc_hd.c b/components/bt/host/bluedroid/btc/profile/std/hid/btc_hd.c index ffa4751ed4b..5986943bfa4 100644 --- a/components/bt/host/bluedroid/btc/profile/std/hid/btc_hd.c +++ b/components/bt/host/bluedroid/btc/profile/std/hid/btc_hd.c @@ -75,6 +75,8 @@ btc_hd_cb_t btc_hd_cb = {0}; typedef void (bt_hid_copy_cb_t)(btc_msg_t *msg, void *p_dest, void *p_src); +static void btc_hd_cb_arg_deep_free(btc_msg_t *msg); + static inline void btc_hd_cb_to_app(esp_hidd_cb_event_t event, esp_hidd_cb_param_t *param) { esp_hd_cb_t btc_hd_cb = (esp_hd_cb_t)btc_profile_cb_get(BTC_PID_HD); @@ -705,7 +707,7 @@ static void btc_hd_virtual_cable_unplug(void) } } -static void btc_hd_call_arg_deep_free(btc_msg_t *msg) +void btc_hd_call_arg_deep_free(btc_msg_t *msg) { btc_hidd_args_t *arg = (btc_hidd_args_t *)msg->arg; @@ -759,7 +761,7 @@ void btc_hd_call_handler(btc_msg_t *msg) btc_hd_call_arg_deep_free(msg); } -void btc_hd_cb_arg_deep_free(btc_msg_t *msg) +static void btc_hd_cb_arg_deep_free(btc_msg_t *msg) { tBTA_HD *arg = (tBTA_HD *)msg->arg; diff --git a/components/bt/host/bluedroid/btc/profile/std/hid/btc_hh.c b/components/bt/host/bluedroid/btc/profile/std/hid/btc_hh.c index 771283a1029..dda5d0bf9d1 100644 --- a/components/bt/host/bluedroid/btc/profile/std/hid/btc_hh.c +++ b/components/bt/host/bluedroid/btc/profile/std/hid/btc_hh.c @@ -64,6 +64,8 @@ static bdstr_t bdstr; #define is_hidh_init() (btc_hh_cb.status > BTC_HH_DISABLED) #define BTC_TIMEOUT_VUP_MS (3 * 1000) +static void btc_hh_cb_arg_deep_free(btc_msg_t *msg); + static inline void btc_hh_cb_to_app(esp_hidh_cb_event_t event, esp_hidh_cb_param_t *param) { esp_hh_cb_t btc_hh_cb = (esp_hh_cb_t)btc_profile_cb_get(BTC_PID_HH); @@ -1097,7 +1099,7 @@ static void btc_hh_set_idle_time(btc_hidh_args_t *arg) } } -static void btc_hh_call_arg_deep_free(btc_msg_t *msg) +void btc_hh_call_arg_deep_free(btc_msg_t *msg) { btc_hidh_args_t *arg = (btc_hidh_args_t *)msg->arg; @@ -1168,7 +1170,7 @@ void btc_hh_call_handler(btc_msg_t *msg) btc_hh_call_arg_deep_free(msg); } -void btc_hh_cb_arg_deep_free(btc_msg_t *msg) +static void btc_hh_cb_arg_deep_free(btc_msg_t *msg) { tBTA_HH *arg = (tBTA_HH *)msg->arg; diff --git a/components/bt/host/bluedroid/btc/profile/std/include/btc_hd.h b/components/bt/host/bluedroid/btc/profile/std/include/btc_hd.h index 15b59393a32..fa01953e842 100644 --- a/components/bt/host/bluedroid/btc/profile/std/include/btc_hd.h +++ b/components/bt/host/bluedroid/btc/profile/std/include/btc_hd.h @@ -99,7 +99,7 @@ void btc_hd_call_handler(btc_msg_t *msg); void btc_hd_cb_handler(btc_msg_t *msg); void btc_hd_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src); -void btc_hd_cb_arg_deep_free(btc_msg_t *msg); +void btc_hd_call_arg_deep_free(btc_msg_t *msg); void btc_hd_get_profile_status(esp_hidd_profile_status_t *param); diff --git a/components/bt/host/bluedroid/btc/profile/std/include/btc_hh.h b/components/bt/host/bluedroid/btc/profile/std/include/btc_hh.h index f1158c6fddf..827cd095c75 100644 --- a/components/bt/host/bluedroid/btc/profile/std/include/btc_hh.h +++ b/components/bt/host/bluedroid/btc/profile/std/include/btc_hh.h @@ -181,8 +181,7 @@ void btc_hh_call_handler(btc_msg_t *msg); void btc_hh_cb_handler(btc_msg_t *msg); void btc_hh_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src); - -void btc_hh_cb_arg_deep_free(btc_msg_t *msg); +void btc_hh_call_arg_deep_free(btc_msg_t *msg); bool btc_hh_add_added_dev(BD_ADDR bd_addr, uint16_t attr_mask); diff --git a/components/bt/host/bluedroid/stack/hid/hidd_conn.c b/components/bt/host/bluedroid/stack/hid/hidd_conn.c index 5a8e36ee599..5c9164c2c53 100644 --- a/components/bt/host/bluedroid/stack/hid/hidd_conn.c +++ b/components/bt/host/bluedroid/stack/hid/hidd_conn.c @@ -775,6 +775,7 @@ tHID_STATUS hidd_conn_send_data(uint8_t channel, uint8_t msg_type, uint8_t param } return HID_SUCCESS; } + osi_free(p_buf); return HID_ERR_NO_CONNECTION; } #ifdef REPORT_TRANSFER_TIMESTAMP diff --git a/components/bt/host/bluedroid/stack/l2cap/l2c_utils.c b/components/bt/host/bluedroid/stack/l2cap/l2c_utils.c index 89b7d62d942..97cae231f78 100644 --- a/components/bt/host/bluedroid/stack/l2cap/l2c_utils.c +++ b/components/bt/host/bluedroid/stack/l2cap/l2c_utils.c @@ -25,7 +25,6 @@ #include #include -#include "osi/allocator.h" #include "device/controller.h" #include "stack/bt_types.h" #include "stack/hcimsgs.h" @@ -36,6 +35,7 @@ #include "stack/btm_api.h" #include "btm_int.h" #include "stack/hcidefs.h" +#include "bt_common.h" #include "osi/allocator.h" #include "osi/list.h" From 7d4ae881c5bf9a69765eac7b6c4771d60cc45355 Mon Sep 17 00:00:00 2001 From: Erhan Kurubas Date: Wed, 29 Oct 2025 21:38:49 +0100 Subject: [PATCH 071/106] change(app_trace): move sysview to component registry --- components/app_trace/CMakeLists.txt | 22 - components/app_trace/heap_trace_tohost.c | 115 - .../app_trace/include/esp_sysview_trace.h | 101 - components/app_trace/linker.lf | 5 - components/app_trace/sdkconfig.rename | 16 - components/app_trace/sys_view/Config/Global.h | 118 - .../sys_view/Config/SEGGER_RTT_Conf.h | 433 -- .../sys_view/Config/SEGGER_SYSVIEW_Conf.h | 90 - components/app_trace/sys_view/Kconfig.sysview | 113 - components/app_trace/sys_view/SEGGER/SEGGER.h | 255 -- .../app_trace/sys_view/SEGGER/SEGGER_RTT.h | 515 --- .../sys_view/SEGGER/SEGGER_SYSVIEW.c | 3645 ----------------- .../sys_view/SEGGER/SEGGER_SYSVIEW.h | 436 -- .../SEGGER/SEGGER_SYSVIEW_ConfDefaults.h | 592 --- .../sys_view/SEGGER/SEGGER_SYSVIEW_Int.h | 104 - components/app_trace/sys_view/SEGGER/sbom.yml | 6 - .../esp/SEGGER_SYSVIEW_Config_FreeRTOS.c | 224 - .../FreeRTOSV10.4/SEGGER_SYSVIEW_FreeRTOS.c | 270 -- .../FreeRTOSV10.4/SEGGER_SYSVIEW_FreeRTOS.h | 367 -- .../app_trace/sys_view/esp/SEGGER_RTT_esp.c | 382 -- .../sys_view/ext/heap_trace_module.c | 91 - components/app_trace/sys_view/ext/logging.c | 26 - .../app_trace/test_apps/.build-test-rules.yml | 6 +- components/app_trace/test_apps/README.md | 7 +- .../app_trace/test_apps/main/test_trace.c | 233 +- .../app_trace/test_apps/sdkconfig.ci.sysview | 3 - components/app_trace/test_apps/sysview | 1 - components/esp_hw_support/intr_alloc.c | 8 +- components/esp_trace/CMakeLists.txt | 5 - components/esp_trace/Kconfig | 6 - .../encoder/adapter_encoder_sysview.c | 148 - .../adapters/adapter_encoder_sysview.h | 46 - .../esp_trace/include/esp_trace_freertos.h | 6 +- components/esp_trace/linker.lf | 2 - .../riscv/include/freertos/portmacro.h | 2 +- .../xtensa/include/freertos/portmacro.h | 2 +- .../riscv/include/freertos/portmacro.h | 2 +- .../xtensa/include/freertos/portmacro.h | 2 +- components/xtensa/xtensa_intr.c | 2 +- docs/doxygen/Doxyfile | 1 - docs/en/api-guides/app_trace.rst | 17 +- docs/en/api-reference/system/app_trace.rst | 1 - .../release-6.x/6.0/system.rst | 22 +- docs/zh_CN/api-guides/app_trace.rst | 17 +- docs/zh_CN/api-reference/system/app_trace.rst | 1 - .../release-6.x/6.0/system.rst | 22 +- .../sysview_tracing/main/idf_component.yml | 13 + .../sysview_tracing/main/sysview_tracing.c | 32 +- .../sysview_tracing/sdkconfig.ci.sysview_uart | 1 - .../sdkconfig.ci.sysview_uart_esp32c2_26Mhz | 1 - .../system/sysview_tracing/sdkconfig.defaults | 2 +- .../sysview_tracing/sdkconfig.defaults.esp32 | 3 - .../sdkconfig.defaults.esp32c2 | 3 - .../sdkconfig.defaults.esp32c3 | 3 - .../sdkconfig.defaults.esp32c5 | 3 - .../sdkconfig.defaults.esp32c6 | 3 - .../sdkconfig.defaults.esp32c61 | 3 - .../sdkconfig.defaults.esp32h2 | 3 - .../sdkconfig.defaults.esp32p4 | 3 - .../sdkconfig.defaults.esp32s2 | 3 - .../sdkconfig.defaults.esp32s3 | 3 - .../main/idf_component.yml | 13 + .../main/sysview_heap_log.c | 14 +- .../sdkconfig.ci.app_trace_jtag | 1 + .../sdkconfig.defaults | 6 +- tools/ci/check_public_headers_exceptions.txt | 1 - 66 files changed, 146 insertions(+), 8456 deletions(-) delete mode 100644 components/app_trace/heap_trace_tohost.c delete mode 100644 components/app_trace/include/esp_sysview_trace.h delete mode 100644 components/app_trace/sys_view/Config/Global.h delete mode 100644 components/app_trace/sys_view/Config/SEGGER_RTT_Conf.h delete mode 100644 components/app_trace/sys_view/Config/SEGGER_SYSVIEW_Conf.h delete mode 100644 components/app_trace/sys_view/Kconfig.sysview delete mode 100644 components/app_trace/sys_view/SEGGER/SEGGER.h delete mode 100644 components/app_trace/sys_view/SEGGER/SEGGER_RTT.h delete mode 100644 components/app_trace/sys_view/SEGGER/SEGGER_SYSVIEW.c delete mode 100644 components/app_trace/sys_view/SEGGER/SEGGER_SYSVIEW.h delete mode 100644 components/app_trace/sys_view/SEGGER/SEGGER_SYSVIEW_ConfDefaults.h delete mode 100644 components/app_trace/sys_view/SEGGER/SEGGER_SYSVIEW_Int.h delete mode 100644 components/app_trace/sys_view/SEGGER/sbom.yml delete mode 100644 components/app_trace/sys_view/Sample/FreeRTOSV10.4/Config/esp/SEGGER_SYSVIEW_Config_FreeRTOS.c delete mode 100644 components/app_trace/sys_view/Sample/FreeRTOSV10.4/SEGGER_SYSVIEW_FreeRTOS.c delete mode 100644 components/app_trace/sys_view/Sample/FreeRTOSV10.4/SEGGER_SYSVIEW_FreeRTOS.h delete mode 100644 components/app_trace/sys_view/esp/SEGGER_RTT_esp.c delete mode 100644 components/app_trace/sys_view/ext/heap_trace_module.c delete mode 100644 components/app_trace/sys_view/ext/logging.c delete mode 100644 components/app_trace/test_apps/sdkconfig.ci.sysview delete mode 100644 components/app_trace/test_apps/sysview delete mode 100644 components/esp_trace/adapters/encoder/adapter_encoder_sysview.c delete mode 100644 components/esp_trace/include/adapters/adapter_encoder_sysview.h create mode 100644 examples/system/sysview_tracing/main/idf_component.yml delete mode 100644 examples/system/sysview_tracing/sdkconfig.defaults.esp32 delete mode 100644 examples/system/sysview_tracing/sdkconfig.defaults.esp32c2 delete mode 100644 examples/system/sysview_tracing/sdkconfig.defaults.esp32c3 delete mode 100644 examples/system/sysview_tracing/sdkconfig.defaults.esp32c5 delete mode 100644 examples/system/sysview_tracing/sdkconfig.defaults.esp32c6 delete mode 100644 examples/system/sysview_tracing/sdkconfig.defaults.esp32c61 delete mode 100644 examples/system/sysview_tracing/sdkconfig.defaults.esp32h2 delete mode 100644 examples/system/sysview_tracing/sdkconfig.defaults.esp32p4 delete mode 100644 examples/system/sysview_tracing/sdkconfig.defaults.esp32s2 delete mode 100644 examples/system/sysview_tracing/sdkconfig.defaults.esp32s3 create mode 100644 examples/system/sysview_tracing_heap_log/main/idf_component.yml diff --git a/components/app_trace/CMakeLists.txt b/components/app_trace/CMakeLists.txt index 8b711b9ee86..78513c5c295 100644 --- a/components/app_trace/CMakeLists.txt +++ b/components/app_trace/CMakeLists.txt @@ -33,28 +33,6 @@ set(include_dirs "include") set(priv_include_dirs "private_include" "port/include") -if(CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW) - list(APPEND include_dirs - sys_view/Config - sys_view/SEGGER - sys_view/Sample/FreeRTOSV10.4) - - list(APPEND srcs - "sys_view/SEGGER/SEGGER_SYSVIEW.c" - "sys_view/Sample/FreeRTOSV10.4/Config/esp/SEGGER_SYSVIEW_Config_FreeRTOS.c" - "sys_view/Sample/FreeRTOSV10.4/SEGGER_SYSVIEW_FreeRTOS.c" - "sys_view/esp/SEGGER_RTT_esp.c" - "sys_view/ext/heap_trace_module.c" - "sys_view/ext/logging.c") -endif() - -if(CONFIG_HEAP_TRACING_TOHOST) - list(APPEND srcs "heap_trace_tohost.c") - if(CONFIG_IDF_TARGET_ARCH_XTENSA) - set_source_files_properties(heap_trace_tohost.c PROPERTIES COMPILE_FLAGS -Wno-frame-address) - endif() -endif() - idf_component_register(SRCS "${srcs}" INCLUDE_DIRS "${include_dirs}" PRIV_INCLUDE_DIRS "${priv_include_dirs}" diff --git a/components/app_trace/heap_trace_tohost.c b/components/app_trace/heap_trace_tohost.c deleted file mode 100644 index 7ee0bd893e0..00000000000 --- a/components/app_trace/heap_trace_tohost.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include "sdkconfig.h" -#include "freertos/FreeRTOS.h" -#include "esp_heap_trace.h" -#include "esp_heap_caps.h" -#if CONFIG_ESP_TRACE_TRANSPORT_APPTRACE -#include "esp_app_trace.h" -#endif -#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW -#include "esp_sysview_trace.h" -#endif - -#define STACK_DEPTH CONFIG_HEAP_TRACING_STACK_DEPTH - -#if CONFIG_HEAP_TRACING_TOHOST - -#if !CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW -#error None of the heap tracing backends is enabled! You must enable SystemView compatible tracing to use this feature. -#endif - -static bool s_tracing; - -esp_err_t heap_trace_init_tohost(void) -{ - if (s_tracing) { - return ESP_ERR_INVALID_STATE; - } - return ESP_OK; -} - -esp_err_t heap_trace_start(heap_trace_mode_t mode_param) -{ -#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW - esp_err_t ret = esp_sysview_heap_trace_start((uint32_t) -1); - if (ret != ESP_OK) { - return ret; - } -#endif - s_tracing = true; - return ESP_OK; -} - -esp_err_t heap_trace_stop(void) -{ - esp_err_t ret = ESP_ERR_NOT_SUPPORTED; -#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW - ret = esp_sysview_heap_trace_stop(); -#endif - s_tracing = false; - return ret; -} - -esp_err_t heap_trace_resume(void) -{ - return heap_trace_start(HEAP_TRACE_ALL); -} - -size_t heap_trace_get_count(void) -{ - return 0; -} - -esp_err_t heap_trace_get(size_t index, heap_trace_record_t *record) -{ - return ESP_ERR_NOT_SUPPORTED; -} - -esp_err_t heap_trace_summary(heap_trace_summary_t *summary) -{ - return ESP_ERR_NOT_SUPPORTED; -} - -void heap_trace_dump(void) -{ - return; -} - -void heap_trace_dump_caps(__attribute__((unused)) const uint32_t caps) -{ - return; -} - -/* Add a new allocation to the heap trace records */ -static HEAP_IRAM_ATTR void record_allocation(const heap_trace_record_t *record) -{ - if (!s_tracing) { - return; - } -#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW - esp_sysview_heap_trace_alloc(record->address, record->size, record->alloced_by); -#endif -} - -/* record a free event in the heap trace log - - For HEAP_TRACE_ALL, this means filling in the freed_by pointer. - For HEAP_TRACE_LEAKS, this means removing the record from the log. -*/ -static HEAP_IRAM_ATTR void record_free(void *p, void **callers) -{ - if (!s_tracing) { - return; - } -#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW - esp_sysview_heap_trace_free(p, callers); -#endif -} - -#include "heap_trace.inc" - -#endif /*CONFIG_HEAP_TRACING_TOHOST*/ diff --git a/components/app_trace/include/esp_sysview_trace.h b/components/app_trace/include/esp_sysview_trace.h deleted file mode 100644 index 3f6ea49b35f..00000000000 --- a/components/app_trace/include/esp_sysview_trace.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2018-2025 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#ifndef ESP_SYSVIEW_TRACE_H_ -#define ESP_SYSVIEW_TRACE_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include "esp_err.h" -#include "SEGGER_RTT.h" // SEGGER_RTT_ESP_Flush -#include "esp_app_trace_util.h" // ESP_APPTRACE_TMO_INFINITE - -/* Forward declaration for esp_trace integration */ -typedef struct esp_trace_encoder esp_trace_encoder_t; - -/** - * @brief Inject encoder handle to SEGGER RTT layer. - * - * This maintains proper architectural layering. SEGGER RTT can accesses it's transport - * - * @param encoder Pointer to encoder instance from esp_trace - * - * @return 0 if successful, -1 if encoder is not initialized or missing required functions. - */ -int SEGGER_RTT_ESP_SetEncoder(esp_trace_encoder_t *encoder); - -/** - * @brief Get the encoder handle for accessing transport functions. - * - * This is used by SEGGER_SYSVIEW_Config_FreeRTOS.c to access transport lock functions. - * - * @return Pointer to encoder instance, or NULL if not initialized. - */ -esp_trace_encoder_t* SEGGER_SYSVIEW_GetEncoder(void); - -/** - * @brief Flushes remaining data in SystemView trace buffer to host. - * - * @return ESP_OK. - */ -static inline esp_err_t esp_sysview_flush(void) -{ - SEGGER_RTT_ESP_Flush(); - return ESP_OK; -} - -/** - * @brief vprintf-like function to sent log messages to the host. - * - * @param format Address of format string. - * @param args List of arguments. - * - * @return Number of bytes written. - */ -int esp_sysview_vprintf(const char * format, va_list args); - -/** - * @brief Starts SystemView heap tracing. - * - * @param tmo Timeout (in us) to wait for the host to be connected. Use -1 to wait forever. - * - * @return ESP_OK on success, ESP_ERR_TIMEOUT if operation has been timed out. - */ -esp_err_t esp_sysview_heap_trace_start(uint32_t tmo); - -/** - * @brief Stops SystemView heap tracing. - * - * @return ESP_OK. - */ -esp_err_t esp_sysview_heap_trace_stop(void); - -/** - * @brief Sends heap allocation event to the host. - * - * @param addr Address of allocated block. - * @param size Size of allocated block. - * @param callers Pointer to array with callstack addresses. - * Array size must be CONFIG_HEAP_TRACING_STACK_DEPTH. - */ -void esp_sysview_heap_trace_alloc(void *addr, uint32_t size, const void *callers); - -/** - * @brief Sends heap de-allocation event to the host. - * - * @param addr Address of de-allocated block. - * @param callers Pointer to array with callstack addresses. - * Array size must be CONFIG_HEAP_TRACING_STACK_DEPTH. - */ -void esp_sysview_heap_trace_free(void *addr, const void *callers); - -#ifdef __cplusplus -} -#endif - -#endif //ESP_SYSVIEW_TRACE_H_ diff --git a/components/app_trace/linker.lf b/components/app_trace/linker.lf index 51473c671c7..f0c97f6334e 100644 --- a/components/app_trace/linker.lf +++ b/components/app_trace/linker.lf @@ -9,8 +9,3 @@ entries: app_trace_membufs_proto (noflash) if APPTRACE_DEST_UART = y || APPTRACE_DEST_ALL = y: port_uart (noflash) - if ESP_TRACE_LIB_SEGGER_SYSVIEW = y: - SEGGER_SYSVIEW (noflash) - SEGGER_RTT_esp (noflash) - SEGGER_SYSVIEW_Config_FreeRTOS (noflash) - SEGGER_SYSVIEW_FreeRTOS (noflash) diff --git a/components/app_trace/sdkconfig.rename b/components/app_trace/sdkconfig.rename index 59216fb3ff1..432dd53de5b 100644 --- a/components/app_trace/sdkconfig.rename +++ b/components/app_trace/sdkconfig.rename @@ -8,21 +8,5 @@ CONFIG_ESP32_APPTRACE_LOCK_ENABLE CONFIG_APPTRACE_LOCK_ENABLE CONFIG_ESP32_APPTRACE_ONPANIC_HOST_FLUSH_TMO CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO CONFIG_ESP32_APPTRACE_POSTMORTEM_FLUSH_TRAX_THRESH CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH -CONFIG_SYSVIEW_ENABLE CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW CONFIG_SYSVIEW_TS_SOURCE_CCOUNT CONFIG_ESP_TRACE_TS_SOURCE_CCOUNT CONFIG_SYSVIEW_TS_SOURCE_ESP_TIMER CONFIG_ESP_TRACE_TS_SOURCE_ESP_TIMER -CONFIG_SYSVIEW_MAX_TASKS CONFIG_SEGGER_SYSVIEW_MAX_TASKS -CONFIG_SYSVIEW_BUF_WAIT_TMO CONFIG_SEGGER_SYSVIEW_BUF_WAIT_TMO -CONFIG_SYSVIEW_EVT_OVERFLOW_ENABLE CONFIG_SEGGER_SYSVIEW_EVT_OVERFLOW_ENABLE -CONFIG_SYSVIEW_EVT_ISR_ENTER_ENABLE CONFIG_SEGGER_SYSVIEW_EVT_ISR_ENTER_ENABLE -CONFIG_SYSVIEW_EVT_ISR_EXIT_ENABLE CONFIG_SEGGER_SYSVIEW_EVT_ISR_EXIT_ENABLE -CONFIG_SYSVIEW_EVT_ISR_TO_SCHEDULER_ENABLE CONFIG_SEGGER_SYSVIEW_EVT_ISR_TO_SCHED_ENABLE -CONFIG_SYSVIEW_EVT_TASK_START_EXEC_ENABLE CONFIG_SEGGER_SYSVIEW_EVT_TASK_START_EXEC_ENABLE -CONFIG_SYSVIEW_EVT_TASK_STOP_EXEC_ENABLE CONFIG_SEGGER_SYSVIEW_EVT_TASK_STOP_EXEC_ENABLE -CONFIG_SYSVIEW_EVT_TASK_START_READY_ENABLE CONFIG_SEGGER_SYSVIEW_EVT_TASK_START_READY_ENABLE -CONFIG_SYSVIEW_EVT_TASK_STOP_READY_ENABLE CONFIG_SEGGER_SYSVIEW_EVT_TASK_STOP_READY_ENABLE -CONFIG_SYSVIEW_EVT_TASK_CREATE_ENABLE CONFIG_SEGGER_SYSVIEW_EVT_TASK_CREATE_ENABLE -CONFIG_SYSVIEW_EVT_TASK_TERMINATE_ENABLE CONFIG_SEGGER_SYSVIEW_EVT_TASK_TERMINATE_ENABLE -CONFIG_SYSVIEW_EVT_IDLE_ENABLE CONFIG_SEGGER_SYSVIEW_EVT_IDLE_ENABLE -CONFIG_SYSVIEW_EVT_TIMER_ENTER_ENABLE CONFIG_SEGGER_SYSVIEW_EVT_TIMER_ENTER_ENABLE -CONFIG_SYSVIEW_EVT_TIMER_EXIT_ENABLE CONFIG_SEGGER_SYSVIEW_EVT_TIMER_EXIT_ENABLE diff --git a/components/app_trace/sys_view/Config/Global.h b/components/app_trace/sys_view/Config/Global.h deleted file mode 100644 index ed2de5c3e9a..00000000000 --- a/components/app_trace/sys_view/Config/Global.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * SPDX-FileCopyrightText: 1995-2021 SEGGER Microcontroller GmbH - * - * SPDX-License-Identifier: BSD-1-Clause - */ -/********************************************************************* -* SEGGER Microcontroller GmbH * -* The Embedded Experts * -********************************************************************** -* * -* (c) 1995 - 2021 SEGGER Microcontroller GmbH * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER SystemView * Real-time application analysis * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* SEGGER strongly recommends to not make any changes * -* to or modify the source code of this software in order to stay * -* compatible with the SystemView and RTT protocol, and J-Link. * -* * -* Redistribution and use in source and binary forms, with or * -* without modification, are permitted provided that the following * -* condition is met: * -* * -* o Redistributions of source code must retain the above copyright * -* notice, this condition and the following disclaimer. * -* * -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * -* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * -* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * -* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * -* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * -* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * -* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * -* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * -* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * -* DAMAGE. * -* * -********************************************************************** -* * -* SystemView version: 3.42 * -* * -********************************************************************** ----------------------------------------------------------------------- -File : Global.h -Purpose : Global types - In case your application already has a Global.h, you should - merge the files. In order to use Segger code, the types - U8, U16, U32, I8, I16, I32 need to be defined in Global.h; - additional definitions do not hurt. -Revision: $Rev: 12501 $ ----------------------------END-OF-HEADER------------------------------ -*/ - -#ifndef GLOBAL_H // Guard against multiple inclusion -#define GLOBAL_H - -#define U8 unsigned char -#define I8 signed char -#define U16 unsigned short -#define I16 signed short -#ifdef __x86_64__ -#define U32 unsigned -#define I32 int -#else -#define U32 unsigned long -#define I32 signed long -#endif - -// -// CC_NO_LONG_SUPPORT can be defined to compile test -// without long support for compilers that do not -// support C99 and its long type. -// -#ifdef CC_NO_LONG_SUPPORT - #define PTR_ADDR U32 -#else // Supports long type. -#if defined(_WIN32) && !defined(__clang__) && !defined(__MINGW32__) - // - // Microsoft VC6 compiler related - // - #define U64 unsigned __int64 - #define U128 unsigned __int128 - #define I64 __int64 - #define I128 __int128 - #if _MSC_VER <= 1200 - #define U64_C(x) x##UI64 - #else - #define U64_C(x) x##ULL - #endif -#else - // - // C99 compliant compiler - // - #define U64 unsigned long long - #define I64 signed long long - #define U64_C(x) x##ULL -#endif - -#if (defined(_WIN64) || defined(__LP64__)) // 64-bit symbols used by Visual Studio and GCC, maybe others as well. - #define PTR_ADDR U64 -#else - #define PTR_ADDR U32 -#endif -#endif // Supports long type. - -#endif // Avoid multiple inclusion - -/*************************** End of file ****************************/ diff --git a/components/app_trace/sys_view/Config/SEGGER_RTT_Conf.h b/components/app_trace/sys_view/Config/SEGGER_RTT_Conf.h deleted file mode 100644 index 2049b18d5b4..00000000000 --- a/components/app_trace/sys_view/Config/SEGGER_RTT_Conf.h +++ /dev/null @@ -1,433 +0,0 @@ -/* - * SPDX-FileCopyrightText: 1995-2021 SEGGER Microcontroller GmbH - * - * SPDX-License-Identifier: BSD-1-Clause - */ -/********************************************************************* -* SEGGER Microcontroller GmbH * -* The Embedded Experts * -********************************************************************** -* * -* (c) 1995 - 2021 SEGGER Microcontroller GmbH * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER SystemView * Real-time application analysis * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* SEGGER strongly recommends to not make any changes * -* to or modify the source code of this software in order to stay * -* compatible with the SystemView and RTT protocol, and J-Link. * -* * -* Redistribution and use in source and binary forms, with or * -* without modification, are permitted provided that the following * -* condition is met: * -* * -* o Redistributions of source code must retain the above copyright * -* notice, this condition and the following disclaimer. * -* * -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * -* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * -* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * -* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * -* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * -* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * -* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * -* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * -* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * -* DAMAGE. * -* * -********************************************************************** -* * -* SystemView version: 3.42 * -* * -********************************************************************** ----------------------------END-OF-HEADER------------------------------ -File : SEGGER_RTT_Conf.h -Purpose : Implementation of SEGGER real-time transfer (RTT) which - allows real-time communication on targets which support - debugger memory accesses while the CPU is running. -Revision: $Rev: 24316 $ - -*/ - -#ifndef SEGGER_RTT_CONF_H -#define SEGGER_RTT_CONF_H - -#ifdef __IAR_SYSTEMS_ICC__ - #include -#endif - -/********************************************************************* -* -* Defines, configurable -* -********************************************************************** -*/ - -// -// Take in and set to correct values for Cortex-A systems with CPU cache -// -//#define SEGGER_RTT_CPU_CACHE_LINE_SIZE (32) // Largest cache line size (in bytes) in the current system -//#define SEGGER_RTT_UNCACHED_OFF (0xFB000000) // Address alias where RTT CB and buffers can be accessed uncached -// -// Most common case: -// Up-channel 0: RTT -// Up-channel 1: SystemView -// -#ifndef SEGGER_RTT_MAX_NUM_UP_BUFFERS - #define SEGGER_RTT_MAX_NUM_UP_BUFFERS (3) // Max. number of up-buffers (T->H) available on this target (Default: 3) -#endif -// -// Most common case: -// Down-channel 0: RTT -// Down-channel 1: SystemView -// -#ifndef SEGGER_RTT_MAX_NUM_DOWN_BUFFERS - #define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (3) // Max. number of down-buffers (H->T) available on this target (Default: 3) -#endif - -#ifndef BUFFER_SIZE_UP - #define BUFFER_SIZE_UP (1024) // Size of the buffer for terminal output of target, up to host (Default: 1k) -#endif - -#ifndef BUFFER_SIZE_DOWN - #define BUFFER_SIZE_DOWN (16) // Size of the buffer for terminal input to target from host (Usually keyboard input) (Default: 16) -#endif - -#ifndef SEGGER_RTT_PRINTF_BUFFER_SIZE - #define SEGGER_RTT_PRINTF_BUFFER_SIZE (64u) // Size of buffer for RTT printf to bulk-send chars via RTT (Default: 64) -#endif - -#ifndef SEGGER_RTT_MODE_DEFAULT - #define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP // Mode for pre-initialized terminal channel (buffer 0) -#endif - -/********************************************************************* -* -* RTT memcpy configuration -* -* memcpy() is good for large amounts of data, -* but the overhead is big for small amounts, which are usually stored via RTT. -* With SEGGER_RTT_MEMCPY_USE_BYTELOOP a simple byte loop can be used instead. -* -* SEGGER_RTT_MEMCPY() can be used to replace standard memcpy() in RTT functions. -* This is may be required with memory access restrictions, -* such as on Cortex-A devices with MMU. -*/ -#ifndef SEGGER_RTT_MEMCPY_USE_BYTELOOP - #define SEGGER_RTT_MEMCPY_USE_BYTELOOP 0 // 0: Use memcpy/SEGGER_RTT_MEMCPY, 1: Use a simple byte-loop -#endif -// -// Example definition of SEGGER_RTT_MEMCPY to external memcpy with GCC toolchains and Cortex-A targets -// -//#if ((defined __SES_ARM) || (defined __CROSSWORKS_ARM) || (defined __GNUC__)) && (defined (__ARM_ARCH_7A__)) -// #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes) SEGGER_memcpy((pDest), (pSrc), (NumBytes)) -//#endif - -// -// Target is not allowed to perform other RTT operations while string still has not been stored completely. -// Otherwise we would probably end up with a mixed string in the buffer. -// If using RTT from within interrupts, multiple tasks or multi processors, define the SEGGER_RTT_LOCK() and SEGGER_RTT_UNLOCK() function here. -// -// SEGGER_RTT_MAX_INTERRUPT_PRIORITY can be used in the sample lock routines on Cortex-M3/4. -// Make sure to mask all interrupts which can send RTT data, i.e. generate SystemView events, or cause task switches. -// When high-priority interrupts must not be masked while sending RTT data, SEGGER_RTT_MAX_INTERRUPT_PRIORITY needs to be adjusted accordingly. -// (Higher priority = lower priority number) -// Default value for embOS: 128u -// Default configuration in FreeRTOS: configMAX_SYSCALL_INTERRUPT_PRIORITY: ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) -// In case of doubt mask all interrupts: 1 << (8 - BASEPRI_PRIO_BITS) i.e. 1 << 5 when 3 bits are implemented in NVIC -// or define SEGGER_RTT_LOCK() to completely disable interrupts. -// -#ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY - #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) // Interrupt priority to lock on SEGGER_RTT_LOCK on Cortex-M3/4 (Default: 0x20) -#endif - -/********************************************************************* -* -* RTT lock configuration for SEGGER Embedded Studio, -* Rowley CrossStudio and GCC -*/ -#if ((defined(__SES_ARM) || defined(__SES_RISCV) || defined(__CROSSWORKS_ARM) || defined(__GNUC__) || defined(__clang__)) && !defined (__CC_ARM) && !defined(WIN32)) - #if (defined(__ARM_ARCH_6M__) || defined(__ARM_ARCH_8M_BASE__)) - #define SEGGER_RTT_LOCK() { \ - unsigned int _SEGGER_RTT__LockState; \ - __asm volatile ("mrs %0, primask \n\t" \ - "movs r1, #1 \n\t" \ - "msr primask, r1 \n\t" \ - : "=r" (_SEGGER_RTT__LockState) \ - : \ - : "r1", "cc" \ - ); - - #define SEGGER_RTT_UNLOCK() __asm volatile ("msr primask, %0 \n\t" \ - : \ - : "r" (_SEGGER_RTT__LockState) \ - : \ - ); \ - } - #elif (defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_8M_MAIN__)) - #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY - #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) - #endif - #define SEGGER_RTT_LOCK() { \ - unsigned int _SEGGER_RTT__LockState; \ - __asm volatile ("mrs %0, basepri \n\t" \ - "mov r1, %1 \n\t" \ - "msr basepri, r1 \n\t" \ - : "=r" (_SEGGER_RTT__LockState) \ - : "i"(SEGGER_RTT_MAX_INTERRUPT_PRIORITY) \ - : "r1", "cc" \ - ); - - #define SEGGER_RTT_UNLOCK() __asm volatile ("msr basepri, %0 \n\t" \ - : \ - : "r" (_SEGGER_RTT__LockState) \ - : \ - ); \ - } - - #elif (defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__)) - #define SEGGER_RTT_LOCK() { \ - unsigned int _SEGGER_RTT__LockState; \ - __asm volatile ("mrs r1, CPSR \n\t" \ - "mov %0, r1 \n\t" \ - "orr r1, r1, #0xC0 \n\t" \ - "msr CPSR_c, r1 \n\t" \ - : "=r" (_SEGGER_RTT__LockState) \ - : \ - : "r1", "cc" \ - ); - - #define SEGGER_RTT_UNLOCK() __asm volatile ("mov r0, %0 \n\t" \ - "mrs r1, CPSR \n\t" \ - "bic r1, r1, #0xC0 \n\t" \ - "and r0, r0, #0xC0 \n\t" \ - "orr r1, r1, r0 \n\t" \ - "msr CPSR_c, r1 \n\t" \ - : \ - : "r" (_SEGGER_RTT__LockState) \ - : "r0", "r1", "cc" \ - ); \ - } - #elif defined(__riscv) || defined(__riscv_xlen) - #define SEGGER_RTT_LOCK() { \ - unsigned int _SEGGER_RTT__LockState; \ - __asm volatile ("csrr %0, mstatus \n\t" \ - "csrci mstatus, 8 \n\t" \ - "andi %0, %0, 8 \n\t" \ - : "=r" (_SEGGER_RTT__LockState) \ - : \ - : \ - ); - - #define SEGGER_RTT_UNLOCK() __asm volatile ("csrr a1, mstatus \n\t" \ - "or %0, %0, a1 \n\t" \ - "csrs mstatus, %0 \n\t" \ - : \ - : "r" (_SEGGER_RTT__LockState) \ - : "a1" \ - ); \ - } - #else - #define SEGGER_RTT_LOCK() - #define SEGGER_RTT_UNLOCK() - #endif -#endif - -/********************************************************************* -* -* RTT lock configuration for IAR EWARM -*/ -#ifdef __ICCARM__ - #if (defined (__ARM6M__) && (__CORE__ == __ARM6M__)) || \ - (defined (__ARM8M_BASELINE__) && (__CORE__ == __ARM8M_BASELINE__)) - #define SEGGER_RTT_LOCK() { \ - unsigned int _SEGGER_RTT__LockState; \ - _SEGGER_RTT__LockState = __get_PRIMASK(); \ - __set_PRIMASK(1); - - #define SEGGER_RTT_UNLOCK() __set_PRIMASK(_SEGGER_RTT__LockState); \ - } - #elif (defined (__ARM7EM__) && (__CORE__ == __ARM7EM__)) || \ - (defined (__ARM7M__) && (__CORE__ == __ARM7M__)) || \ - (defined (__ARM8M_MAINLINE__) && (__CORE__ == __ARM8M_MAINLINE__)) || \ - (defined (__ARM8M_MAINLINE__) && (__CORE__ == __ARM8M_MAINLINE__)) - #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY - #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) - #endif - #define SEGGER_RTT_LOCK() { \ - unsigned int _SEGGER_RTT__LockState; \ - _SEGGER_RTT__LockState = __get_BASEPRI(); \ - __set_BASEPRI(SEGGER_RTT_MAX_INTERRUPT_PRIORITY); - - #define SEGGER_RTT_UNLOCK() __set_BASEPRI(_SEGGER_RTT__LockState); \ - } - #elif (defined (__ARM7A__) && (__CORE__ == __ARM7A__)) || \ - (defined (__ARM7R__) && (__CORE__ == __ARM7R__)) - #define SEGGER_RTT_LOCK() { \ - unsigned int _SEGGER_RTT__LockState; \ - __asm volatile ("mrs r1, CPSR \n\t" \ - "mov %0, r1 \n\t" \ - "orr r1, r1, #0xC0 \n\t" \ - "msr CPSR_c, r1 \n\t" \ - : "=r" (_SEGGER_RTT__LockState) \ - : \ - : "r1", "cc" \ - ); - - #define SEGGER_RTT_UNLOCK() __asm volatile ("mov r0, %0 \n\t" \ - "mrs r1, CPSR \n\t" \ - "bic r1, r1, #0xC0 \n\t" \ - "and r0, r0, #0xC0 \n\t" \ - "orr r1, r1, r0 \n\t" \ - "msr CPSR_c, r1 \n\t" \ - : \ - : "r" (_SEGGER_RTT__LockState) \ - : "r0", "r1", "cc" \ - ); \ - } - #endif -#endif - -/********************************************************************* -* -* RTT lock configuration for IAR RX -*/ -#ifdef __ICCRX__ - #define SEGGER_RTT_LOCK() { \ - unsigned long _SEGGER_RTT__LockState; \ - _SEGGER_RTT__LockState = __get_interrupt_state(); \ - __disable_interrupt(); - - #define SEGGER_RTT_UNLOCK() __set_interrupt_state(_SEGGER_RTT__LockState); \ - } -#endif - -/********************************************************************* -* -* RTT lock configuration for IAR RL78 -*/ -#ifdef __ICCRL78__ - #define SEGGER_RTT_LOCK() { \ - __istate_t _SEGGER_RTT__LockState; \ - _SEGGER_RTT__LockState = __get_interrupt_state(); \ - __disable_interrupt(); - - #define SEGGER_RTT_UNLOCK() __set_interrupt_state(_SEGGER_RTT__LockState); \ - } -#endif - -/********************************************************************* -* -* RTT lock configuration for KEIL ARM -*/ -#ifdef __CC_ARM - #if (defined __TARGET_ARCH_6S_M) - #define SEGGER_RTT_LOCK() { \ - unsigned int _SEGGER_RTT__LockState; \ - register unsigned char _SEGGER_RTT__PRIMASK __asm( "primask"); \ - _SEGGER_RTT__LockState = _SEGGER_RTT__PRIMASK; \ - _SEGGER_RTT__PRIMASK = 1u; \ - __schedule_barrier(); - - #define SEGGER_RTT_UNLOCK() _SEGGER_RTT__PRIMASK = _SEGGER_RTT__LockState; \ - __schedule_barrier(); \ - } - #elif (defined(__TARGET_ARCH_7_M) || defined(__TARGET_ARCH_7E_M)) - #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY - #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) - #endif - #define SEGGER_RTT_LOCK() { \ - unsigned int _SEGGER_RTT__LockState; \ - register unsigned char BASEPRI __asm( "basepri"); \ - _SEGGER_RTT__LockState = BASEPRI; \ - BASEPRI = SEGGER_RTT_MAX_INTERRUPT_PRIORITY; \ - __schedule_barrier(); - - #define SEGGER_RTT_UNLOCK() BASEPRI = _SEGGER_RTT__LockState; \ - __schedule_barrier(); \ - } - #endif -#endif - -/********************************************************************* -* -* RTT lock configuration for TI ARM -*/ -#ifdef __TI_ARM__ - #if defined (__TI_ARM_V6M0__) - #define SEGGER_RTT_LOCK() { \ - unsigned int _SEGGER_RTT__LockState; \ - _SEGGER_RTT__LockState = __get_PRIMASK(); \ - __set_PRIMASK(1); - - #define SEGGER_RTT_UNLOCK() __set_PRIMASK(_SEGGER_RTT__LockState); \ - } - #elif (defined (__TI_ARM_V7M3__) || defined (__TI_ARM_V7M4__)) - #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY - #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) - #endif - #define SEGGER_RTT_LOCK() { \ - unsigned int _SEGGER_RTT__LockState; \ - _SEGGER_RTT__LockState = _set_interrupt_priority(SEGGER_RTT_MAX_INTERRUPT_PRIORITY); - - #define SEGGER_RTT_UNLOCK() _set_interrupt_priority(_SEGGER_RTT__LockState); \ - } - #endif -#endif - -/********************************************************************* -* -* RTT lock configuration for CCRX -*/ -#ifdef __RX - #include - #define SEGGER_RTT_LOCK() { \ - unsigned long _SEGGER_RTT__LockState; \ - _SEGGER_RTT__LockState = get_psw() & 0x010000; \ - clrpsw_i(); - - #define SEGGER_RTT_UNLOCK() set_psw(get_psw() | _SEGGER_RTT__LockState); \ - } -#endif - -/********************************************************************* -* -* RTT lock configuration for embOS Simulation on Windows -* (Can also be used for generic RTT locking with embOS) -*/ -#if defined(WIN32) || defined(SEGGER_RTT_LOCK_EMBOS) - -void OS_SIM_EnterCriticalSection(void); -void OS_SIM_LeaveCriticalSection(void); - -#define SEGGER_RTT_LOCK() { \ - OS_SIM_EnterCriticalSection(); - -#define SEGGER_RTT_UNLOCK() OS_SIM_LeaveCriticalSection(); \ - } -#endif - -/********************************************************************* -* -* RTT lock configuration fallback -*/ -#ifndef SEGGER_RTT_LOCK - #define SEGGER_RTT_LOCK() // Lock RTT (nestable) (i.e. disable interrupts) -#endif - -#ifndef SEGGER_RTT_UNLOCK - #define SEGGER_RTT_UNLOCK() // Unlock RTT (nestable) (i.e. enable previous interrupt lock state) -#endif - -#endif -/*************************** End of file ****************************/ diff --git a/components/app_trace/sys_view/Config/SEGGER_SYSVIEW_Conf.h b/components/app_trace/sys_view/Config/SEGGER_SYSVIEW_Conf.h deleted file mode 100644 index b4bc13515d9..00000000000 --- a/components/app_trace/sys_view/Config/SEGGER_SYSVIEW_Conf.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * SPDX-FileCopyrightText: 1995-2021 SEGGER Microcontroller GmbH - * - * SPDX-License-Identifier: BSD-1-Clause - */ -/********************************************************************* -* SEGGER Microcontroller GmbH * -* The Embedded Experts * -********************************************************************** -* * -* (c) 1995 - 2021 SEGGER Microcontroller GmbH * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER SystemView * Real-time application analysis * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* SEGGER strongly recommends to not make any changes * -* to or modify the source code of this software in order to stay * -* compatible with the SystemView and RTT protocol, and J-Link. * -* * -* Redistribution and use in source and binary forms, with or * -* without modification, are permitted provided that the following * -* condition is met: * -* * -* o Redistributions of source code must retain the above copyright * -* notice, this condition and the following disclaimer. * -* * -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * -* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * -* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * -* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * -* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * -* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * -* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * -* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * -* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * -* DAMAGE. * -* * -********************************************************************** -* * -* SystemView version: 3.42 * -* * -********************************************************************** --------------------------- END-OF-HEADER ----------------------------- - -File : SEGGER_SYSVIEW_Conf.h -Purpose : SEGGER SystemView configuration file. - Set defines which deviate from the defaults (see SEGGER_SYSVIEW_ConfDefaults.h) here. -Revision: $Rev: 21292 $ - -Additional information: - Required defines which must be set are: - SEGGER_SYSVIEW_GET_TIMESTAMP - SEGGER_SYSVIEW_GET_INTERRUPT_ID - For known compilers and cores, these might be set to good defaults - in SEGGER_SYSVIEW_ConfDefaults.h. - - SystemView needs a (nestable) locking mechanism. - If not defined, the RTT locking mechanism is used, - which then needs to be properly configured. -*/ - -#ifndef SEGGER_SYSVIEW_CONF_H -#define SEGGER_SYSVIEW_CONF_H - -/********************************************************************* -* -* Defines, configurable -* -********************************************************************** -*/ - -/********************************************************************* -* TODO: Add your defines here. * -********************************************************************** -*/ - - -#endif // SEGGER_SYSVIEW_CONF_H - -/*************************** End of file ****************************/ diff --git a/components/app_trace/sys_view/Kconfig.sysview b/components/app_trace/sys_view/Kconfig.sysview deleted file mode 100644 index f9366bb49c1..00000000000 --- a/components/app_trace/sys_view/Kconfig.sysview +++ /dev/null @@ -1,113 +0,0 @@ -menu "SEGGER SystemView" - depends on ESP_TRACE_LIB_SEGGER_SYSVIEW - choice SEGGER_SYSVIEW_DEST_CPU - prompt "CPU to trace" - depends on ESP_TRACE_TRANSPORT_APPTRACE && APPTRACE_DEST_UART && !ESP_SYSTEM_SINGLE_CORE_MODE - default SEGGER_SYSVIEW_DEST_CPU_0 - help - Define the CPU to trace. - - config SEGGER_SYSVIEW_DEST_CPU_0 - bool "CPU0" - help - Send tracing data for Pro CPU. - - config SEGGER_SYSVIEW_DEST_CPU_1 - bool "CPU1" - help - Send tracing data for App CPU. - - endchoice - - config SEGGER_SYSVIEW_MAX_TASKS - int "Maximum supported tasks" - range 1 64 - default 16 - help - Configures maximum supported tasks in sysview debug - - config SEGGER_SYSVIEW_BUF_WAIT_TMO - int "Trace buffer wait timeout" - default 500 - help - Configures timeout (in us) to wait for free space in trace buffer. - Set to -1 to wait forever and avoid lost events. - - config SEGGER_SYSVIEW_EVT_OVERFLOW_ENABLE - bool "Trace Buffer Overflow Event" - default y - help - Enables "Trace Buffer Overflow" event. - - config SEGGER_SYSVIEW_EVT_ISR_ENTER_ENABLE - bool "ISR Enter Event" - default y - help - Enables "ISR Enter" event. - - config SEGGER_SYSVIEW_EVT_ISR_EXIT_ENABLE - bool "ISR Exit Event" - default y - help - Enables "ISR Exit" event. - - config SEGGER_SYSVIEW_EVT_ISR_TO_SCHED_ENABLE - bool "ISR Exit to Scheduler Event" - default y - help - Enables "ISR to Scheduler" event. - - config SEGGER_SYSVIEW_EVT_TASK_START_EXEC_ENABLE - bool "Task Start Execution Event" - default y - help - Enables "Task Start Execution" event. - - config SEGGER_SYSVIEW_EVT_TASK_STOP_EXEC_ENABLE - bool "Task Stop Execution Event" - default y - help - Enables "Task Stop Execution" event. - - config SEGGER_SYSVIEW_EVT_TASK_START_READY_ENABLE - bool "Task Start Ready State Event" - default y - help - Enables "Task Start Ready State" event. - - config SEGGER_SYSVIEW_EVT_TASK_STOP_READY_ENABLE - bool "Task Stop Ready State Event" - default y - help - Enables "Task Stop Ready State" event. - - config SEGGER_SYSVIEW_EVT_TASK_CREATE_ENABLE - bool "Task Create Event" - default y - help - Enables "Task Create" event. - - config SEGGER_SYSVIEW_EVT_TASK_TERMINATE_ENABLE - bool "Task Terminate Event" - default y - help - Enables "Task Terminate" event. - - config SEGGER_SYSVIEW_EVT_IDLE_ENABLE - bool "System Idle Event" - default y - help - Enables "System Idle" event. - - config SEGGER_SYSVIEW_EVT_TIMER_ENTER_ENABLE - bool "Timer Enter Event" - default y - help - Enables "Timer Enter" event. - - config SEGGER_SYSVIEW_EVT_TIMER_EXIT_ENABLE - bool "Timer Exit Event" - default y - help - Enables "Timer Exit" event. -endmenu diff --git a/components/app_trace/sys_view/SEGGER/SEGGER.h b/components/app_trace/sys_view/SEGGER/SEGGER.h deleted file mode 100644 index f07e9466195..00000000000 --- a/components/app_trace/sys_view/SEGGER/SEGGER.h +++ /dev/null @@ -1,255 +0,0 @@ -/* - * SPDX-FileCopyrightText: 1995-2021 SEGGER Microcontroller GmbH - * - * SPDX-License-Identifier: BSD-1-Clause - * - * SPDX-FileContributor: 2023 Espressif Systems (Shanghai) CO LTD - */ -/********************************************************************* -* SEGGER Microcontroller GmbH * -* The Embedded Experts * -********************************************************************** -* * -* (c) 1995 - 2024 SEGGER Microcontroller GmbH * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER SystemView * Real-time application analysis * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* SEGGER strongly recommends to not make any changes * -* to or modify the source code of this software in order to stay * -* compatible with the SystemView and RTT protocol, and J-Link. * -* * -* Redistribution and use in source and binary forms, with or * -* without modification, are permitted provided that the following * -* condition is met: * -* * -* o Redistributions of source code must retain the above copyright * -* notice, this condition and the following disclaimer. * -* * -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * -* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * -* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * -* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * -* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * -* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * -* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * -* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * -* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * -* DAMAGE. * -* * -********************************************************************** -* * -* SystemView version: 3.56 * -* * -********************************************************************** ----------------------------------------------------------------------- -File : SEGGER.h -Purpose : Global types etc & general purpose utility functions -Revision: $Rev: 18102 $ ----------------------------END-OF-HEADER------------------------------ -*/ - -#ifndef SEGGER_H // Guard against multiple inclusion -#define SEGGER_H - -#include // For va_list. -#include "Global.h" // Type definitions: U8, U16, U32, I8, I16, I32 - -#if defined(__cplusplus) -extern "C" { /* Make sure we have C-declarations in C++ programs */ -#endif - -/********************************************************************* -* -* Keywords/specifiers -* -********************************************************************** -*/ - -#ifndef INLINE - #if (defined(__ICCARM__) || defined(__RX) || defined(__ICCRX__)) - // - // Other known compilers. - // - #define INLINE inline - #else - #if (defined(_WIN32) && !defined(__clang__)) - // - // Microsoft VC6 and newer. - // Force inlining without cost checking. - // - #define INLINE __forceinline - #elif defined(__GNUC__) || defined(__clang__) - // - // Force inlining with GCC + clang - // - #define INLINE inline __attribute__((always_inline)) - #elif (defined(__CC_ARM)) - // - // Force inlining with ARMCC (Keil) - // - #define INLINE __inline - #else - // - // Unknown compilers. - // - #define INLINE - #endif - #endif -#endif - -/********************************************************************* -* -* Function-like macros -* -********************************************************************** -*/ - -#define SEGGER_COUNTOF(a) (sizeof((a))/sizeof((a)[0])) -#define SEGGER_MIN(a,b) (((a) < (b)) ? (a) : (b)) -#define SEGGER_MAX(a,b) (((a) > (b)) ? (a) : (b)) - -#ifndef SEGGER_USE_PARA // Some compiler complain about unused parameters. - #define SEGGER_USE_PARA(Para) (void)Para // This works for most compilers. -#endif - -#define SEGGER_ADDR2PTR(Type, Addr) (/*lint -e(923) -e(9078)*/((Type*)((PTR_ADDR)(Addr)))) // Allow cast from address to pointer. -#define SEGGER_PTR2ADDR(p) (/*lint -e(923) -e(9078)*/((PTR_ADDR)(p))) // Allow cast from pointer to address. -#define SEGGER_PTR2PTR(Type, p) (/*lint -e(740) -e(826) -e(9079) -e(9087)*/((Type*)(p))) // Allow cast from one pointer type to another (ignore different size). -#define SEGGER_PTR_DISTANCE(p0, p1) (SEGGER_PTR2ADDR(p0) - SEGGER_PTR2ADDR(p1)) - -/********************************************************************* -* -* Defines -* -********************************************************************** -*/ - -#define SEGGER_PRINTF_FLAG_ADJLEFT (1 << 0) -#define SEGGER_PRINTF_FLAG_SIGNFORCE (1 << 1) -#define SEGGER_PRINTF_FLAG_SIGNSPACE (1 << 2) -#define SEGGER_PRINTF_FLAG_PRECEED (1 << 3) -#define SEGGER_PRINTF_FLAG_ZEROPAD (1 << 4) -#define SEGGER_PRINTF_FLAG_NEGATIVE (1 << 5) - -/********************************************************************* -* -* Types -* -********************************************************************** -*/ - -typedef struct { - char* pBuffer; - int BufferSize; - int Cnt; -} SEGGER_BUFFER_DESC; - -typedef struct { - unsigned int CacheLineSize; // 0: No Cache. Most Systems such as ARM9 use a 32 bytes cache line size. - void (*pfDMB) (void); // Optional DMB function for Data Memory Barrier to make sure all memory operations are completed. - void (*pfClean) (void *p, unsigned long NumBytes); // Optional clean function for cached memory. - void (*pfInvalidate)(void *p, unsigned long NumBytes); // Optional invalidate function for cached memory. -} SEGGER_CACHE_CONFIG; - -typedef struct SEGGER_SNPRINTF_CONTEXT_struct SEGGER_SNPRINTF_CONTEXT; - -struct SEGGER_SNPRINTF_CONTEXT_struct { - void* pContext; // Application specific context. - SEGGER_BUFFER_DESC* pBufferDesc; // Buffer descriptor to use for output. - void (*pfFlush)(SEGGER_SNPRINTF_CONTEXT* pContext); // Callback executed once the buffer is full. Callback decides if the buffer gets cleared to store more or not. -}; - -typedef struct { - void (*pfStoreChar) (SEGGER_BUFFER_DESC* pBufferDesc, SEGGER_SNPRINTF_CONTEXT* pContext, char c); - int (*pfPrintUnsigned) (SEGGER_BUFFER_DESC* pBufferDesc, SEGGER_SNPRINTF_CONTEXT* pContext, U32 v, unsigned Base, char Flags, int Width, int Precision); - int (*pfPrintInt) (SEGGER_BUFFER_DESC* pBufferDesc, SEGGER_SNPRINTF_CONTEXT* pContext, I32 v, unsigned Base, char Flags, int Width, int Precision); -} SEGGER_PRINTF_API; - -typedef void (*SEGGER_pFormatter)(SEGGER_BUFFER_DESC* pBufferDesc, SEGGER_SNPRINTF_CONTEXT* pContext, const SEGGER_PRINTF_API* pApi, va_list* pParamList, char Lead, int Width, int Precision); - -typedef struct SEGGER_PRINTF_FORMATTER { - struct SEGGER_PRINTF_FORMATTER* pNext; // Pointer to next formatter. - SEGGER_pFormatter pfFormatter; // Formatter function. - char Specifier; // Format specifier. -} SEGGER_PRINTF_FORMATTER; - -typedef struct { - U32 (*pfGetHPTimestamp)(void); // Mandatory, pfGetHPTimestamp - int (*pfGetUID) (U8 abUID[16]); // Optional, pfGetUID -} SEGGER_BSP_API; - -/********************************************************************* -* -* Utility functions -* -********************************************************************** -*/ - -// -// Memory operations. -// -void SEGGER_ARM_memcpy(void* pDest, const void* pSrc, int NumBytes); -void SEGGER_memcpy (void* pDest, const void* pSrc, unsigned NumBytes); -void SEGGER_memxor (void* pDest, const void* pSrc, unsigned NumBytes); - -// -// String functions. -// -int SEGGER_atoi (const char* s); -int SEGGER_isalnum (int c); -int SEGGER_isalpha (int c); -unsigned SEGGER_strlen (const char* s); -int SEGGER_tolower (int c); -int SEGGER_strcasecmp (const char* sText1, const char* sText2); -int SEGGER_strncasecmp(const char *sText1, const char *sText2, unsigned Count); - -// -// Buffer/printf related. -// -void SEGGER_StoreChar (SEGGER_BUFFER_DESC* pBufferDesc, char c); -void SEGGER_PrintUnsigned(SEGGER_BUFFER_DESC* pBufferDesc, U32 v, unsigned Base, int Precision); -void SEGGER_PrintInt (SEGGER_BUFFER_DESC* pBufferDesc, I32 v, unsigned Base, int Precision); -int SEGGER_snprintf (char* pBuffer, int BufferSize, const char* sFormat, ...); -int SEGGER_vsnprintf (char* pBuffer, int BufferSize, const char* sFormat, va_list ParamList); -int SEGGER_vsnprintfEx (SEGGER_SNPRINTF_CONTEXT* pContext, const char* sFormat, va_list ParamList); - -int SEGGER_PRINTF_AddFormatter (SEGGER_PRINTF_FORMATTER* pFormatter, SEGGER_pFormatter pfFormatter, char c); -void SEGGER_PRINTF_AddDoubleFormatter (void); -void SEGGER_PRINTF_AddIPFormatter (void); -void SEGGER_PRINTF_AddBLUEFormatter (void); -void SEGGER_PRINTF_AddCONNECTFormatter(void); -void SEGGER_PRINTF_AddSSLFormatter (void); -void SEGGER_PRINTF_AddSSHFormatter (void); -void SEGGER_PRINTF_AddHTMLFormatter (void); - -// -// BSP abstraction API. -// -int SEGGER_BSP_GetUID (U8 abUID[16]); -int SEGGER_BSP_GetUID32(U32* pUID); -void SEGGER_BSP_SetAPI (const SEGGER_BSP_API* pAPI); -void SEGGER_BSP_SeedUID (void); - -// -// Other API. -// -void SEGGER_VERSION_GetString(char acText[8], unsigned Version); - -#if defined(__cplusplus) -} /* Make sure we have C-declarations in C++ programs */ -#endif - -#endif // Avoid multiple inclusion - -/*************************** End of file ****************************/ diff --git a/components/app_trace/sys_view/SEGGER/SEGGER_RTT.h b/components/app_trace/sys_view/SEGGER/SEGGER_RTT.h deleted file mode 100644 index 15d31ea411a..00000000000 --- a/components/app_trace/sys_view/SEGGER/SEGGER_RTT.h +++ /dev/null @@ -1,515 +0,0 @@ -/* - * SPDX-FileCopyrightText: 1995-2021 SEGGER Microcontroller GmbH - * - * SPDX-License-Identifier: BSD-1-Clause - */ -/********************************************************************* -* SEGGER Microcontroller GmbH * -* The Embedded Experts * -********************************************************************** -* * -* (c) 1995 - 2024 SEGGER Microcontroller GmbH * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER SystemView * Real-time application analysis * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* SEGGER strongly recommends to not make any changes * -* to or modify the source code of this software in order to stay * -* compatible with the SystemView and RTT protocol, and J-Link. * -* * -* Redistribution and use in source and binary forms, with or * -* without modification, are permitted provided that the following * -* condition is met: * -* * -* o Redistributions of source code must retain the above copyright * -* notice, this condition and the following disclaimer. * -* * -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * -* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * -* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * -* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * -* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * -* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * -* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * -* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * -* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * -* DAMAGE. * -* * -********************************************************************** -* * -* SystemView version: 3.56 * -* * -********************************************************************** ----------------------------END-OF-HEADER------------------------------ -File : SEGGER_RTT.h -Purpose : Implementation of SEGGER real-time transfer which allows - real-time communication on targets which support debugger - memory accesses while the CPU is running. -Revision: $Rev: 25842 $ ----------------------------------------------------------------------- -*/ - -#ifndef SEGGER_RTT_H -#define SEGGER_RTT_H - -#include "../Config/SEGGER_RTT_Conf.h" - -/********************************************************************* -* -* Defines, defaults -* -********************************************************************** -*/ - -#ifndef RTT_USE_ASM - // - // Some cores support out-of-order memory accesses (reordering of memory accesses in the core) - // For such cores, we need to define a memory barrier to guarantee the order of certain accesses to the RTT ring buffers. - // Needed for: - // Cortex-M7 (ARMv7-M) - // Cortex-M23 (ARM-v8M) - // Cortex-M33 (ARM-v8M) - // Cortex-A/R (ARM-v7A/R) - // - // We do not explicitly check for "Embedded Studio" as the compiler in use determines what we support. - // You can use an external toolchain like IAR inside ES. So there is no point in checking for "Embedded Studio" - // - #if (defined __CROSSWORKS_ARM) // Rowley Crossworks - #define _CC_HAS_RTT_ASM_SUPPORT 1 - #if (defined __ARM_ARCH_7M__) // Cortex-M3 - #define _CORE_HAS_RTT_ASM_SUPPORT 1 - #elif (defined __ARM_ARCH_7EM__) // Cortex-M4/M7 - #define _CORE_HAS_RTT_ASM_SUPPORT 1 - #define _CORE_NEEDS_DMB 1 - #define RTT__DMB() __asm volatile ("dmb\n" : : :); - #elif (defined __ARM_ARCH_8M_BASE__) // Cortex-M23 - #define _CORE_HAS_RTT_ASM_SUPPORT 0 - #define _CORE_NEEDS_DMB 1 - #define RTT__DMB() __asm volatile ("dmb\n" : : :); - #elif (defined __ARM_ARCH_8M_MAIN__) // Cortex-M33 - #define _CORE_HAS_RTT_ASM_SUPPORT 1 - #define _CORE_NEEDS_DMB 1 - #define RTT__DMB() __asm volatile ("dmb\n" : : :); - #elif (defined(__ARM_ARCH_8_1M_MAIN__)) // Cortex-M85 - #define _CORE_HAS_RTT_ASM_SUPPORT 1 - #define _CORE_NEEDS_DMB 1 - #define RTT__DMB() __asm volatile ("dmb\n" : : :); - #else - #define _CORE_HAS_RTT_ASM_SUPPORT 0 - #endif - #elif (defined __ARMCC_VERSION) - // - // ARM compiler - // ARM compiler V6.0 and later is clang based. - // Our ASM part is compatible to clang. - // - #if (__ARMCC_VERSION >= 6000000) - #define _CC_HAS_RTT_ASM_SUPPORT 1 - #else - #define _CC_HAS_RTT_ASM_SUPPORT 0 - #endif - #if (defined __ARM_ARCH_6M__) // Cortex-M0 / M1 - #define _CORE_HAS_RTT_ASM_SUPPORT 0 // No ASM support for this architecture - #elif (defined __ARM_ARCH_7M__) // Cortex-M3 - #define _CORE_HAS_RTT_ASM_SUPPORT 1 - #elif (defined __ARM_ARCH_7EM__) // Cortex-M4/M7 - #define _CORE_HAS_RTT_ASM_SUPPORT 1 - #define _CORE_NEEDS_DMB 1 - #define RTT__DMB() __asm volatile ("dmb\n" : : :); - #elif (defined __ARM_ARCH_8M_BASE__) // Cortex-M23 - #define _CORE_HAS_RTT_ASM_SUPPORT 0 - #define _CORE_NEEDS_DMB 1 - #define RTT__DMB() __asm volatile ("dmb\n" : : :); - #elif (defined __ARM_ARCH_8M_MAIN__) // Cortex-M33 - #define _CORE_HAS_RTT_ASM_SUPPORT 1 - #define _CORE_NEEDS_DMB 1 - #define RTT__DMB() __asm volatile ("dmb\n" : : :); - #elif (defined __ARM_ARCH_8_1M_MAIN__) // Cortex-M85 - #define _CORE_HAS_RTT_ASM_SUPPORT 1 - #define _CORE_NEEDS_DMB 1 - #define RTT__DMB() __asm volatile ("dmb\n" : : :); - #elif ((defined __ARM_ARCH_7A__) || (defined __ARM_ARCH_7R__)) // Cortex-A/R 32-bit ARMv7-A/R - #define _CORE_NEEDS_DMB 1 - #define RTT__DMB() __asm volatile ("dmb\n" : : :); - #else - #define _CORE_HAS_RTT_ASM_SUPPORT 0 - #endif - #elif ((defined __GNUC__) || (defined __clang__)) - // - // GCC / Clang - // - #define _CC_HAS_RTT_ASM_SUPPORT 1 - // ARM 7/9: __ARM_ARCH_5__ / __ARM_ARCH_5E__ / __ARM_ARCH_5T__ / __ARM_ARCH_5T__ / __ARM_ARCH_5TE__ - #if (defined __ARM_ARCH_7M__) // Cortex-M3 - #define _CORE_HAS_RTT_ASM_SUPPORT 1 - #elif (defined __ARM_ARCH_7EM__) // Cortex-M4/M7 - #define _CORE_HAS_RTT_ASM_SUPPORT 1 - #define _CORE_NEEDS_DMB 1 // Only Cortex-M7 needs a DMB but we cannot distinguish M4 and M7 here... - #define RTT__DMB() __asm volatile ("dmb\n" : : :); - #elif (defined __ARM_ARCH_8M_BASE__) // Cortex-M23 - #define _CORE_HAS_RTT_ASM_SUPPORT 0 - #define _CORE_NEEDS_DMB 1 - #define RTT__DMB() __asm volatile ("dmb\n" : : :); - #elif (defined __ARM_ARCH_8M_MAIN__) // Cortex-M33 - #define _CORE_HAS_RTT_ASM_SUPPORT 1 - #define _CORE_NEEDS_DMB 1 - #define RTT__DMB() __asm volatile ("dmb\n" : : :); - #elif (defined __ARM_ARCH_8_1M_MAIN__) // Cortex-M85 - #define _CORE_HAS_RTT_ASM_SUPPORT 1 - #define _CORE_NEEDS_DMB 1 - #define RTT__DMB() __asm volatile ("dmb\n" : : :); - #elif ((defined __ARM_ARCH_7A__) || (defined __ARM_ARCH_7R__)) // Cortex-A/R 32-bit ARMv7-A/R - #define _CORE_NEEDS_DMB 1 - #define RTT__DMB() __asm volatile ("dmb\n" : : :); - #else - #define _CORE_HAS_RTT_ASM_SUPPORT 0 - #endif - #elif ((defined __IASMARM__) || (defined __ICCARM__)) - // - // IAR assembler/compiler - // - #define _CC_HAS_RTT_ASM_SUPPORT 1 - #if (__VER__ < 6300000) - #define VOLATILE - #else - #define VOLATILE volatile - #endif - #if (defined __ARM7M__) // Needed for old versions that do not know the define yet - #if (__CORE__ == __ARM7M__) // Cortex-M3 - #define _CORE_HAS_RTT_ASM_SUPPORT 1 - #endif - #endif - #if (defined __ARM7EM__) - #if (__CORE__ == __ARM7EM__) // Cortex-M4/M7 - #define _CORE_HAS_RTT_ASM_SUPPORT 1 - #define _CORE_NEEDS_DMB 1 - #define RTT__DMB() asm VOLATILE ("DMB"); - #endif - #endif - #if (defined __ARM8M_BASELINE__) - #if (__CORE__ == __ARM8M_BASELINE__) // Cortex-M23 - #define _CORE_HAS_RTT_ASM_SUPPORT 0 - #define _CORE_NEEDS_DMB 1 - #define RTT__DMB() asm VOLATILE ("DMB"); - #endif - #endif - #if (defined __ARM8M_MAINLINE__) - #if (__CORE__ == __ARM8M_MAINLINE__) // Cortex-M33 - #define _CORE_HAS_RTT_ASM_SUPPORT 1 - #define _CORE_NEEDS_DMB 1 - #define RTT__DMB() asm VOLATILE ("DMB"); - #endif - #endif - #if (defined __ARM8EM_MAINLINE__) - #if (__CORE__ == __ARM8EM_MAINLINE__) // Cortex-??? - #define _CORE_HAS_RTT_ASM_SUPPORT 1 - #define _CORE_NEEDS_DMB 1 - #define RTT__DMB() asm VOLATILE ("DMB"); - #endif - #endif - #if (defined __ARM7A__) - #if (__CORE__ == __ARM7A__) // Cortex-A 32-bit ARMv7-A - #define _CORE_NEEDS_DMB 1 - #define RTT__DMB() asm VOLATILE ("DMB"); - #endif - #endif - #if (defined __ARM7R__) - #if (__CORE__ == __ARM7R__) // Cortex-R 32-bit ARMv7-R - #define _CORE_NEEDS_DMB 1 - #define RTT__DMB() asm VOLATILE ("DMB"); - #endif - #endif -// TBD: __ARM8A__ => Cortex-A 64-bit ARMv8-A -// TBD: __ARM8R__ => Cortex-R 64-bit ARMv8-R - #else - // - // Other compilers - // - #define _CC_HAS_RTT_ASM_SUPPORT 0 - #define _CORE_HAS_RTT_ASM_SUPPORT 0 - #endif - // - // If IDE and core support the ASM version, enable ASM version by default - // - #ifndef _CORE_HAS_RTT_ASM_SUPPORT - #define _CORE_HAS_RTT_ASM_SUPPORT 0 // Default for unknown cores - #endif - #if (_CC_HAS_RTT_ASM_SUPPORT && _CORE_HAS_RTT_ASM_SUPPORT) - #define RTT_USE_ASM (1) - #else - #define RTT_USE_ASM (0) - #endif -#endif - -#ifndef _CORE_NEEDS_DMB - #define _CORE_NEEDS_DMB 0 -#endif - -#ifndef RTT__DMB - #if _CORE_NEEDS_DMB - #error "Don't know how to place inline assembly for DMB" - #else - #define RTT__DMB() - #endif -#endif - -#ifndef SEGGER_RTT_CPU_CACHE_LINE_SIZE - #define SEGGER_RTT_CPU_CACHE_LINE_SIZE (0) // On most target systems where RTT is used, we do not have a CPU cache, therefore 0 is a good default here -#endif - -#ifndef SEGGER_RTT_UNCACHED_OFF - #if SEGGER_RTT_CPU_CACHE_LINE_SIZE - #error "SEGGER_RTT_UNCACHED_OFF must be defined when setting SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0" - #else - #define SEGGER_RTT_UNCACHED_OFF (0) - #endif -#endif -#if RTT_USE_ASM - #if SEGGER_RTT_CPU_CACHE_LINE_SIZE - #error "RTT_USE_ASM is not available if SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0" - #endif -#endif - -#ifndef SEGGER_RTT_ASM // defined when SEGGER_RTT.h is included from assembly file -#include -#include -#include - -/********************************************************************* -* -* Defines, fixed -* -********************************************************************** -*/ - -// -// Determine how much we must pad the control block to make it a multiple of a cache line in size -// Assuming: U8 = 1B -// U16 = 2B -// U32 = 4B -// U8/U16/U32* = 4B -// -#if SEGGER_RTT_CPU_CACHE_LINE_SIZE // Avoid division by zero in case we do not have any cache - #define SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(NumBytes) (((NumBytes + SEGGER_RTT_CPU_CACHE_LINE_SIZE - 1) / SEGGER_RTT_CPU_CACHE_LINE_SIZE) * SEGGER_RTT_CPU_CACHE_LINE_SIZE) -#else - #define SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(NumBytes) (NumBytes) -#endif -#define SEGGER_RTT__CB_SIZE (16 + 4 + 4 + (SEGGER_RTT_MAX_NUM_UP_BUFFERS * 24) + (SEGGER_RTT_MAX_NUM_DOWN_BUFFERS * 24)) -#define SEGGER_RTT__CB_PADDING (SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(SEGGER_RTT__CB_SIZE) - SEGGER_RTT__CB_SIZE) - -/********************************************************************* -* -* Types -* -********************************************************************** -*/ - -// -// Description for a circular buffer (also called "ring buffer") -// which is used as up-buffer (T->H) -// -typedef struct { - const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4" - char* pBuffer; // Pointer to start of buffer - unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty. - unsigned WrOff; // Position of next item to be written by either target. - volatile unsigned RdOff; // Position of next item to be read by host. Must be volatile since it may be modified by host. - unsigned Flags; // Contains configuration flags. Flags[31:24] are used for validity check and must be zero. Flags[23:2] are reserved for future use. Flags[1:0] = RTT operating mode. -} SEGGER_RTT_BUFFER_UP; - -// -// Description for a circular buffer (also called "ring buffer") -// which is used as down-buffer (H->T) -// -typedef struct { - const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4" - char* pBuffer; // Pointer to start of buffer - unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty. - volatile unsigned WrOff; // Position of next item to be written by host. Must be volatile since it may be modified by host. - unsigned RdOff; // Position of next item to be read by target (down-buffer). - unsigned Flags; // Contains configuration flags. Flags[31:24] are used for validity check and must be zero. Flags[23:2] are reserved for future use. Flags[1:0] = RTT operating mode. -} SEGGER_RTT_BUFFER_DOWN; - -// -// RTT control block which describes the number of buffers available -// as well as the configuration for each buffer -// -// -typedef struct { - char acID[16]; // Initialized to "SEGGER RTT" - int MaxNumUpBuffers; // Initialized to SEGGER_RTT_MAX_NUM_UP_BUFFERS (type. 2) - int MaxNumDownBuffers; // Initialized to SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (type. 2) - SEGGER_RTT_BUFFER_UP aUp[SEGGER_RTT_MAX_NUM_UP_BUFFERS]; // Up buffers, transferring information up from target via debug probe to host - SEGGER_RTT_BUFFER_DOWN aDown[SEGGER_RTT_MAX_NUM_DOWN_BUFFERS]; // Down buffers, transferring information down from host via debug probe to target -#if SEGGER_RTT__CB_PADDING - unsigned char aDummy[SEGGER_RTT__CB_PADDING]; -#endif -} SEGGER_RTT_CB; - -/********************************************************************* -* -* Global data -* -********************************************************************** -*/ -extern SEGGER_RTT_CB _SEGGER_RTT; - -/********************************************************************* -* -* RTT API functions -* -********************************************************************** -*/ -#ifdef __cplusplus - extern "C" { -#endif -int SEGGER_RTT_AllocDownBuffer (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); -int SEGGER_RTT_AllocUpBuffer (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); -int SEGGER_RTT_ConfigUpBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); -int SEGGER_RTT_ConfigDownBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); -int SEGGER_RTT_GetKey (void); -unsigned SEGGER_RTT_HasData (unsigned BufferIndex); -int SEGGER_RTT_HasKey (void); -unsigned SEGGER_RTT_HasDataUp (unsigned BufferIndex); -void SEGGER_RTT_Init (void); -unsigned SEGGER_RTT_Read (unsigned BufferIndex, void* pBuffer, unsigned BufferSize); -unsigned SEGGER_RTT_ReadNoLock (unsigned BufferIndex, void* pData, unsigned BufferSize); -int SEGGER_RTT_SetNameDownBuffer (unsigned BufferIndex, const char* sName); -int SEGGER_RTT_SetNameUpBuffer (unsigned BufferIndex, const char* sName); -int SEGGER_RTT_SetFlagsDownBuffer (unsigned BufferIndex, unsigned Flags); -int SEGGER_RTT_SetFlagsUpBuffer (unsigned BufferIndex, unsigned Flags); -int SEGGER_RTT_WaitKey (void); -unsigned SEGGER_RTT_Write (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); -unsigned SEGGER_RTT_WriteNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); -unsigned SEGGER_RTT_WriteSkipNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); -unsigned SEGGER_RTT_ASM_WriteSkipNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); -unsigned SEGGER_RTT_WriteString (unsigned BufferIndex, const char* s); -void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); -unsigned SEGGER_RTT_PutChar (unsigned BufferIndex, char c); -unsigned SEGGER_RTT_PutCharSkip (unsigned BufferIndex, char c); -unsigned SEGGER_RTT_PutCharSkipNoLock (unsigned BufferIndex, char c); -unsigned SEGGER_RTT_GetAvailWriteSpace (unsigned BufferIndex); -unsigned SEGGER_RTT_GetBytesInBuffer (unsigned BufferIndex); - -void SEGGER_RTT_ESP_FlushNoLock (void); -void SEGGER_RTT_ESP_Flush (void); -// -// Function macro for performance optimization -// -// @AGv: This macro is used inside SEGGER SystemView code. -// For ESP32 we use our own implementation of RTT, so this macro should not check SEGGER's RTT buffer state. -#define SEGGER_RTT_HASDATA(n) (1) - -#if RTT_USE_ASM - #define SEGGER_RTT_WriteSkipNoLock SEGGER_RTT_ASM_WriteSkipNoLock -#endif - -/********************************************************************* -* -* RTT transfer functions to send RTT data via other channels. -* -********************************************************************** -*/ -unsigned SEGGER_RTT_ReadUpBuffer (unsigned BufferIndex, void* pBuffer, unsigned BufferSize); -unsigned SEGGER_RTT_ReadUpBufferNoLock (unsigned BufferIndex, void* pData, unsigned BufferSize); -unsigned SEGGER_RTT_WriteDownBuffer (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); -unsigned SEGGER_RTT_WriteDownBufferNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); - -#define SEGGER_RTT_HASDATA_UP(n) (((SEGGER_RTT_BUFFER_UP*)((uintptr_t)&_SEGGER_RTT.aUp[n] + SEGGER_RTT_UNCACHED_OFF))->WrOff - ((SEGGER_RTT_BUFFER_UP*)((uintptr_t)&_SEGGER_RTT.aUp[n] + SEGGER_RTT_UNCACHED_OFF))->RdOff) // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly - -/********************************************************************* -* -* RTT "Terminal" API functions -* -********************************************************************** -*/ -int SEGGER_RTT_SetTerminal (unsigned char TerminalId); -int SEGGER_RTT_TerminalOut (unsigned char TerminalId, const char* s); - -/********************************************************************* -* -* RTT printf functions (require SEGGER_RTT_printf.c) -* -********************************************************************** -*/ -int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...); -int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList); - -#ifdef __cplusplus - } -#endif - -#endif // ifndef(SEGGER_RTT_ASM) - -/********************************************************************* -* -* Defines -* -********************************************************************** -*/ - -// -// Operating modes. Define behavior if buffer is full (not enough space for entire message) -// -#define SEGGER_RTT_MODE_NO_BLOCK_SKIP (0) // Skip. Do not block, output nothing. (Default) -#define SEGGER_RTT_MODE_NO_BLOCK_TRIM (1) // Trim: Do not block, output as much as fits. -#define SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL (2) // Block: Wait until there is space in the buffer. -#define SEGGER_RTT_MODE_MASK (3) - -// -// Control sequences, based on ANSI. -// Can be used to control color, and clear the screen -// -#define RTT_CTRL_RESET "\x1B[0m" // Reset to default colors -#define RTT_CTRL_CLEAR "\x1B[2J" // Clear screen, reposition cursor to top left - -#define RTT_CTRL_TEXT_BLACK "\x1B[2;30m" -#define RTT_CTRL_TEXT_RED "\x1B[2;31m" -#define RTT_CTRL_TEXT_GREEN "\x1B[2;32m" -#define RTT_CTRL_TEXT_YELLOW "\x1B[2;33m" -#define RTT_CTRL_TEXT_BLUE "\x1B[2;34m" -#define RTT_CTRL_TEXT_MAGENTA "\x1B[2;35m" -#define RTT_CTRL_TEXT_CYAN "\x1B[2;36m" -#define RTT_CTRL_TEXT_WHITE "\x1B[2;37m" - -#define RTT_CTRL_TEXT_BRIGHT_BLACK "\x1B[1;30m" -#define RTT_CTRL_TEXT_BRIGHT_RED "\x1B[1;31m" -#define RTT_CTRL_TEXT_BRIGHT_GREEN "\x1B[1;32m" -#define RTT_CTRL_TEXT_BRIGHT_YELLOW "\x1B[1;33m" -#define RTT_CTRL_TEXT_BRIGHT_BLUE "\x1B[1;34m" -#define RTT_CTRL_TEXT_BRIGHT_MAGENTA "\x1B[1;35m" -#define RTT_CTRL_TEXT_BRIGHT_CYAN "\x1B[1;36m" -#define RTT_CTRL_TEXT_BRIGHT_WHITE "\x1B[1;37m" - -#define RTT_CTRL_BG_BLACK "\x1B[24;40m" -#define RTT_CTRL_BG_RED "\x1B[24;41m" -#define RTT_CTRL_BG_GREEN "\x1B[24;42m" -#define RTT_CTRL_BG_YELLOW "\x1B[24;43m" -#define RTT_CTRL_BG_BLUE "\x1B[24;44m" -#define RTT_CTRL_BG_MAGENTA "\x1B[24;45m" -#define RTT_CTRL_BG_CYAN "\x1B[24;46m" -#define RTT_CTRL_BG_WHITE "\x1B[24;47m" - -#define RTT_CTRL_BG_BRIGHT_BLACK "\x1B[4;40m" -#define RTT_CTRL_BG_BRIGHT_RED "\x1B[4;41m" -#define RTT_CTRL_BG_BRIGHT_GREEN "\x1B[4;42m" -#define RTT_CTRL_BG_BRIGHT_YELLOW "\x1B[4;43m" -#define RTT_CTRL_BG_BRIGHT_BLUE "\x1B[4;44m" -#define RTT_CTRL_BG_BRIGHT_MAGENTA "\x1B[4;45m" -#define RTT_CTRL_BG_BRIGHT_CYAN "\x1B[4;46m" -#define RTT_CTRL_BG_BRIGHT_WHITE "\x1B[4;47m" - - -#endif - -/*************************** End of file ****************************/ diff --git a/components/app_trace/sys_view/SEGGER/SEGGER_SYSVIEW.c b/components/app_trace/sys_view/SEGGER/SEGGER_SYSVIEW.c deleted file mode 100644 index 4de60ada2e5..00000000000 --- a/components/app_trace/sys_view/SEGGER/SEGGER_SYSVIEW.c +++ /dev/null @@ -1,3645 +0,0 @@ -/* - * SPDX-FileCopyrightText: 1995-2021 SEGGER Microcontroller GmbH - * - * SPDX-License-Identifier: BSD-1-Clause - * - * SPDX-FileContributor: 2023-2024 Espressif Systems (Shanghai) CO LTD - */ -/********************************************************************* -* SEGGER Microcontroller GmbH * -* The Embedded Experts * -********************************************************************** -* * -* (c) 1995 - 2024 SEGGER Microcontroller GmbH * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER SystemView * Real-time application analysis * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* SEGGER strongly recommends to not make any changes * -* to or modify the source code of this software in order to stay * -* compatible with the SystemView and RTT protocol, and J-Link. * -* * -* Redistribution and use in source and binary forms, with or * -* without modification, are permitted provided that the following * -* condition is met: * -* * -* o Redistributions of source code must retain the above copyright * -* notice, this condition and the following disclaimer. * -* * -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * -* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * -* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * -* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * -* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * -* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * -* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * -* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * -* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * -* DAMAGE. * -* * -********************************************************************** -* * -* SystemView version: 3.56 * -* * -********************************************************************** --------------------------- END-OF-HEADER ----------------------------- - -File : SEGGER_SYSVIEW.c -Purpose : System visualization API implementation. -Revision: $Rev: 29105 $ - -Additional information: - Packet format: - Packets with IDs 0..23 are standard packets with known structure. - For efficiency, they do *NOT* contain a length field. - - - Packets with IDs 24..31 are standard packets with extendible - structure and contain a length field. - - - Packet ID 31 is used for SystemView extended events. - - - Packets with IDs >= 32 always contain a length field. - - - Packet IDs: - 0.. 31 : Standard packets, known by SystemView. - 32..1023 : OS-definable packets, described in a SystemView description file. - 1024..2047 : User-definable packets, described in a SystemView description file. - 2048..32767: Undefined. - - Data encoding: - Basic types (int, short, char, ...): - Basic types are encoded little endian with most-significant bit variant - encoding. - Each encoded byte contains 7 data bits [6:0] and the MSB continuation bit. - The continuation bit indicates whether the next byte belongs to the data - (bit set) or this is the last byte (bit clear). - The most significant bits of data are encoded first, proceeding to the - least significant bits in the final byte (little endian). - - Example encoding: - Data: 0x1F4 (500) - Encoded: 0xF4 (First 7 data bits 74 | Continuation bit) - 0x03 (Second 7 data bits 03, no continuation) - - Data: 0xFFFFFFFF - Encoded: 0xFF 0xFF 0xFF 0xFF 0x0F - - Data: 0xA2 (162), 0x03 (3), 0x7000 - Encoded: 0xA2 0x01 0x03 0x80 0xE0 0x01 - - Byte arrays and strings: - Byte arrays and strings are encoded as followed by the raw data. - NumBytes is encoded as a basic type with a theoretical maximum of 4G. - - Example encoding: - Data: "Hello World\0" (0x48 0x65 0x6C 0x6C 0x6F 0x20 0x57 0x6F 0x72 0x6C 0x64 0x00) - Encoded: 0x0B 0x48 0x65 0x6C 0x6C 0x6F 0x20 0x57 0x6F 0x72 0x6C 0x64 - - Examples packets: - 01 F4 03 80 80 10 // Overflow packet. Data is a single U32. - This packet means: 500 packets lost, Timestamp is 0x40000 - - 02 0F 50 // ISR(15) Enter. Timestamp 80 (0x50) - - 03 20 // ISR Exit. Timestamp 32 (0x20) (Shortest possible packet.) - - Sample code for user defined Packets: - #define MY_ID 0x400 // Any value between 0x400 and 0x7FF - void SendMyPacket(unsigned Para0, unsigned Para1, const char* s) { - U8 aPacket[SEGGER_SYSVIEW_INFO_SIZE + 2 * SEGGER_SYSVIEW_QUANTA_U32 + MAX_STR_LEN + 1]; - U8* pPayload; - // - pPayload = SEGGER_SYSVIEW_PPREPARE_PACKET(aPacket); // Prepare the packet for SystemView - pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, Para0); // Add the first parameter to the packet - pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, Para1); // Add the second parameter to the packet - pPayload = SEGGER_SYSVIEW_EncodeString(pPayload, s, MAX_STR_LEN); // Add the string to the packet - // - SEGGER_SYSVIEW_SendPacket(&aPacket[0], pPayload, MY_ID); // Send the packet with EventId = MY_ID - } - - #define MY_ID_1 0x401 - void SendOnePara(unsigned Para0) { - SEGGER_SYSVIEW_RecordU32(MY_ID_1, Para0); - } - -*/ - -/********************************************************************* -* -* #include section -* -********************************************************************** -*/ - -#define SEGGER_SYSVIEW_C // For EXTERN statements in SEGGER_SYSVIEW.h - -#include -#include -#include -#include -#include "SEGGER_SYSVIEW_Int.h" -#include "SEGGER_RTT.h" - -/********************************************************************* -* -* Defines, fixed -* -********************************************************************** -*/ -#if SEGGER_SYSVIEW_ID_SHIFT - #define SHRINK_ID(Id) (((Id) - _SYSVIEW_Globals.RAMBaseAddress) >> SEGGER_SYSVIEW_ID_SHIFT) -#else - #define SHRINK_ID(Id) ((Id) - _SYSVIEW_Globals.RAMBaseAddress) -#endif - -#if SEGGER_SYSVIEW_RTT_CHANNEL > 0 - #define CHANNEL_ID_UP SEGGER_SYSVIEW_RTT_CHANNEL - #define CHANNEL_ID_DOWN SEGGER_SYSVIEW_RTT_CHANNEL -#else - #define CHANNEL_ID_UP _SYSVIEW_Globals.UpChannel - #define CHANNEL_ID_DOWN _SYSVIEW_Globals.DownChannel -#endif - -#if SEGGER_SYSVIEW_CPU_CACHE_LINE_SIZE - #if (SEGGER_SYSVIEW_RTT_BUFFER_SIZE % SEGGER_SYSVIEW_CPU_CACHE_LINE_SIZE) - #error "SEGGER_SYSVIEW_RTT_BUFFER_SIZE must be a multiple of SEGGER_SYSVIEW_CPU_CACHE_LINE_SIZE" - #endif -#endif - -/********************************************************************* -* -* Defines, configurable -* -********************************************************************** -*/ -// Timestamps may be less than full 32-bits, in which case we need to zero -// the unused bits to properly handle overflows. -// Note that this is a quite common scenario, as a 32-bit time such as -// SysTick might be scaled down to reduce bandwidth -// or a 16-bit hardware time might be used. -#if SEGGER_SYSVIEW_TIMESTAMP_BITS < 32 // Eliminate unused bits in case hardware timestamps are less than 32 bits - #define MAKE_DELTA_32BIT(Delta) Delta <<= 32 - SEGGER_SYSVIEW_TIMESTAMP_BITS; \ - Delta >>= 32 - SEGGER_SYSVIEW_TIMESTAMP_BITS; -#else - #define MAKE_DELTA_32BIT(Delta) -#endif - -#if SEGGER_SYSVIEW_SUPPORT_LONG_ID - #define _MAX_ID_BYTES 5u -#else - #define _MAX_ID_BYTES 2u -#endif - -#if SEGGER_SYSVIEW_SUPPORT_LONG_DATA - #define _MAX_DATA_BYTES 5u -#else - #define _MAX_DATA_BYTES 2u -#endif - -/********************************************************************* -* -* Defines, fixed -* -********************************************************************** -*/ -#define ENABLE_STATE_OFF 0 -#define ENABLE_STATE_ON 1 -#define ENABLE_STATE_DROPPING 2 - -#define FORMAT_FLAG_LEFT_JUSTIFY (1u << 0) -#define FORMAT_FLAG_PAD_ZERO (1u << 1) -#define FORMAT_FLAG_PRINT_SIGN (1u << 2) -#define FORMAT_FLAG_ALTERNATE (1u << 3) - -#define MODULE_EVENT_OFFSET (512) - -/********************************************************************* -* -* Types, local -* -********************************************************************** -*/ -typedef struct { - U8* pBuffer; - U8* pPayload; - U8* pPayloadStart; - U32 Options; - unsigned Cnt; -} SEGGER_SYSVIEW_PRINTF_DESC; - -typedef struct { - U8 EnableState; // 0: Disabled, 1: Enabled, (2: Dropping) - U8 UpChannel; - U8 RecursionCnt; - U32 SysFreq; - U32 CPUFreq; - U32 LastTxTimeStamp; - U32 RAMBaseAddress; -#if (SEGGER_SYSVIEW_POST_MORTEM_MODE == 1) - U32 PacketCount; -#else - U32 DropCount; - U8 DownChannel; -#endif - U32 DisabledEvents; - const SEGGER_SYSVIEW_OS_API* pOSAPI; - SEGGER_SYSVIEW_SEND_SYS_DESC_FUNC* pfSendSysDesc; -} SEGGER_SYSVIEW_GLOBALS; - -/********************************************************************* -* -* Function prototypes, required -* -********************************************************************** -*/ -static void _SendPacket(U8* pStartPacket, U8* pEndPacket, unsigned int EventId); - -/********************************************************************* -* -* Static data -* -********************************************************************** -*/ -static const U8 _abSync[10] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - -#if SEGGER_SYSVIEW_CPU_CACHE_LINE_SIZE - #ifdef SEGGER_SYSVIEW_SECTION - // - // Alignment + special section required - // - #if (defined __GNUC__) - __attribute__ ((section (SEGGER_SYSVIEW_SECTION), aligned (SEGGER_SYSVIEW_CPU_CACHE_LINE_SIZE))) static char _UpBuffer [SEGGER_SYSVIEW_RTT_BUFFER_SIZE]; - #if (SEGGER_SYSVIEW_POST_MORTEM_MODE != 1) - __attribute__ ((section (SEGGER_SYSVIEW_SECTION), aligned (SEGGER_SYSVIEW_CPU_CACHE_LINE_SIZE))) static char _DownBuffer[8]; // Small, fixed-size buffer, for back-channel comms - #endif - #elif (defined __ICCARM__) || (defined __ICCRX__) - #pragma location=SEGGER_SYSVIEW_SECTION - #pragma data_alignment=SEGGER_RTT_CPU_CACHE_LINE_SIZE - static char _UpBuffer [SEGGER_SYSVIEW_RTT_BUFFER_SIZE]; - #if (SEGGER_SYSVIEW_POST_MORTEM_MODE != 1) - #pragma location=SEGGER_SYSVIEW_SECTION - #pragma data_alignment=SEGGER_RTT_CPU_CACHE_LINE_SIZE - static char _DownBuffer[8]; // Small, fixed-size buffer, for back-channel comms - #endif - #elif (defined __CC_ARM) - __attribute__ ((section (SEGGER_SYSVIEW_SECTION), aligned (SEGGER_SYSVIEW_CPU_CACHE_LINE_SIZE), zero_init)) static char _UpBuffer [SEGGER_SYSVIEW_RTT_BUFFER_SIZE]; - #if (SEGGER_SYSVIEW_POST_MORTEM_MODE != 1) - __attribute__ ((section (SEGGER_SYSVIEW_SECTION), aligned (SEGGER_SYSVIEW_CPU_CACHE_LINE_SIZE), zero_init)) static char _DownBuffer[8]; // Small, fixed-size buffer, for back-channel comms - #endif - #else - #error "Do not know how to place SystemView buffers in specific section" - #endif - #else - // - // Only alignment required - // - #if (defined __GNUC__) - __attribute__ ((aligned (SEGGER_SYSVIEW_CPU_CACHE_LINE_SIZE))) static char _UpBuffer [SEGGER_SYSVIEW_RTT_BUFFER_SIZE]; - #if (SEGGER_SYSVIEW_POST_MORTEM_MODE != 1) - __attribute__ ((aligned (SEGGER_SYSVIEW_CPU_CACHE_LINE_SIZE))) static char _DownBuffer[8]; // Small, fixed-size buffer, for back-channel comms - #endif - #elif (defined __ICCARM__) || (defined __ICCRX__) - #pragma data_alignment=SEGGER_RTT_CPU_CACHE_LINE_SIZE - static char _UpBuffer [SEGGER_SYSVIEW_RTT_BUFFER_SIZE]; - #if (SEGGER_SYSVIEW_POST_MORTEM_MODE != 1) - #pragma data_alignment=SEGGER_RTT_CPU_CACHE_LINE_SIZE - static char _DownBuffer[8]; // Small, fixed-size buffer, for back-channel comms - #endif - #elif (defined __CC_ARM) - __attribute__ ((aligned (SEGGER_SYSVIEW_CPU_CACHE_LINE_SIZE), zero_init)) static char _UpBuffer [SEGGER_SYSVIEW_RTT_BUFFER_SIZE]; - #if (SEGGER_SYSVIEW_POST_MORTEM_MODE != 1) - __attribute__ ((aligned (SEGGER_SYSVIEW_CPU_CACHE_LINE_SIZE), zero_init)) static char _DownBuffer[8]; // Small, fixed-size buffer, for back-channel comms - #endif - #else - #error "Do not know how to align SystemView buffers to cache line size" - #endif - #endif -#else - #ifdef SEGGER_SYSVIEW_SECTION - // - // Only special section required - // - #if (defined __GNUC__) - __attribute__ ((section (SEGGER_SYSVIEW_SECTION))) static char _UpBuffer [SEGGER_SYSVIEW_RTT_BUFFER_SIZE]; - #if (SEGGER_SYSVIEW_POST_MORTEM_MODE != 1) - __attribute__ ((section (SEGGER_SYSVIEW_SECTION))) static char _DownBuffer[8]; // Small, fixed-size buffer, for back-channel comms - #endif - #elif (defined __ICCARM__) || (defined __ICCRX__) - #pragma location=SEGGER_SYSVIEW_SECTION - static char _UpBuffer [SEGGER_SYSVIEW_RTT_BUFFER_SIZE]; - #if (SEGGER_SYSVIEW_POST_MORTEM_MODE != 1) - #pragma location=SEGGER_SYSVIEW_SECTION - static char _DownBuffer[8]; // Small, fixed-size buffer, for back-channel comms - #endif - #elif (defined __CC_ARM) - __attribute__ ((section (SEGGER_SYSVIEW_SECTION), zero_init)) static char _UpBuffer [SEGGER_SYSVIEW_RTT_BUFFER_SIZE]; - #if (SEGGER_SYSVIEW_POST_MORTEM_MODE != 1) - __attribute__ ((section (SEGGER_SYSVIEW_SECTION), zero_init)) static char _DownBuffer[8]; // Small, fixed-size buffer, for back-channel comms - #endif - #else - #error "Do not know how to place SystemView buffers in specific section" - #endif - #else - // - // Neither special section nor alignment required - // - static char _UpBuffer [SEGGER_SYSVIEW_RTT_BUFFER_SIZE]; - #if (SEGGER_SYSVIEW_POST_MORTEM_MODE != 1) - static char _DownBuffer[8]; // Small, fixed-size buffer, for back-channel comms - #endif - #endif -#endif - -static SEGGER_SYSVIEW_GLOBALS _SYSVIEW_Globals; - -static SEGGER_SYSVIEW_MODULE* _pFirstModule; -static U8 _NumModules; - -/********************************************************************* -* -* Static code -* -********************************************************************** -*/ - -#define ENCODE_U32(pDest, Value) { \ - U8* pSysviewPointer; \ - U32 SysViewData; \ - pSysviewPointer = pDest; \ - SysViewData = Value; \ - while(SysViewData > 0x7F) { \ - *pSysviewPointer++ = (U8)(SysViewData | 0x80); \ - SysViewData >>= 7; \ - }; \ - *pSysviewPointer++ = (U8)SysViewData; \ - pDest = pSysviewPointer; \ - }; - -#if (SEGGER_SYSVIEW_USE_STATIC_BUFFER == 1) -static U8 _aPacket[SEGGER_SYSVIEW_MAX_PACKET_SIZE]; - -#define RECORD_START(PacketSize) SEGGER_SYSVIEW_LOCK(); \ - pPayloadStart = _PreparePacket(_aPacket); - -#define RECORD_END() SEGGER_SYSVIEW_UNLOCK() - -#else - -#define RECORD_START(PacketSize) U8 aPacket[(PacketSize)]; \ - pPayloadStart = _PreparePacket(aPacket); \ - -#define RECORD_END() - -#endif - -/********************************************************************* -* -* _EncodeData() -* -* Function description -* Encode a byte buffer in variable-length format. -* -* Parameters -* pPayload - Pointer to where string will be encoded. -* pSrc - Pointer to data buffer to be encoded. -* NumBytes - Number of bytes in the buffer to be encoded. -* -* Return value -* Pointer to the byte following the value, i.e. the first free -* byte in the payload and the next position to store payload -* content. -* -* Additional information -* The data is encoded as a count byte followed by the contents -* of the data buffer. -* Make sure NumBytes + 1 bytes are free for the payload. -*/ -static U8* _EncodeData(U8* pPayload, const char* pSrc, unsigned int NumBytes) { - unsigned int n; - const U8* p; - - // Espressif doesn't support larger packages yet. Encode data length must be less than 255. - assert(NumBytes < 255); - // - n = 0; - p = (const U8*)pSrc; - // - // Write Len - // - if (NumBytes < 255) { - *pPayload++ = (U8)NumBytes; - } else { - *pPayload++ = 255; - *pPayload++ = ((NumBytes >> 8) & 255); - *pPayload++ = (NumBytes & 255); - } - while (n < NumBytes) { - *pPayload++ = *p++; - n++; - } - return pPayload; -} - -/********************************************************************* -* -* _EncodeFloat() -* -* Function description -* Encode a float value in variable-length format. -* -* Parameters -* pPayload - Pointer to where value will be encoded. -* Value - Value to be encoded. -* -* Return value -* Pointer to the byte following the value, i.e. the first free -* byte in the payload and the next position to store payload -* content. -*/ -static U8* _EncodeFloat(U8* pPayload, float Value) { - float Val = Value; - U8* pSysviewPointer; - U32* SysViewData; - pSysviewPointer = pPayload; - SysViewData = (U32*)&Val; - while((*SysViewData) > 0x7F) { - *pSysviewPointer++ = (U8)((*SysViewData) | 0x80); - (*SysViewData) >>= 7; - }; - *pSysviewPointer++ = (U8)(*SysViewData); - pPayload = pSysviewPointer; - - return pPayload; -} - -/********************************************************************* -* -* _EncodeStr() -* -* Function description -* Encode a string in variable-length format. -* -* Parameters -* pPayload - Pointer to where string will be encoded. -* pText - String to encode. -* Limit - Maximum number of characters to encode from string. -* -* Return value -* Pointer to the byte following the value, i.e. the first free -* byte in the payload and the next position to store payload -* content. -* -* Additional information -* The string is encoded as a count byte followed by the contents -* of the string. -* No more than 1 + Limit bytes will be encoded to the payload. -*/ -static U8 *_EncodeStr(U8 *pPayload, const char *pText, unsigned int Limit) { - U8* pLen; - const char* sStart; - - if (pText == NULL) { - *pPayload++ = (U8)0; - } else { - sStart = pText; // Remember start of string. - // - // Save space to store count byte(s). - // - pLen = pPayload++; -#if (SEGGER_SYSVIEW_MAX_STRING_LEN >= 255) // Length always encodes in 3 bytes - pPayload += 2; -#endif - // - // Limit string to maximum length and copy into payload buffer. - // - if (Limit > SEGGER_SYSVIEW_MAX_STRING_LEN) { - Limit = SEGGER_SYSVIEW_MAX_STRING_LEN; - } - while ((Limit-- > 0) && (*pText != '\0')) { - *pPayload++ = *pText++; - } - // - // Save string length to buffer. - // -#if (SEGGER_SYSVIEW_MAX_STRING_LEN >= 255) // Length always encodes in 3 bytes - Limit = (unsigned int)(pText - sStart); - *pLen++ = (U8)255; - *pLen++ = (U8)((Limit >> 8) & 255); - *pLen++ = (U8)(Limit & 255); -#else // Length always encodes in 1 byte - *pLen = (U8)(pText - sStart); -#endif - } - // - return pPayload; -} - -/********************************************************************* -* -* _PreparePacket() -* -* Function description -* Prepare a SystemView event packet header. -* -* Parameters -* pPacket - Pointer to start of packet to initialize. -* -* Return value -* Pointer to first byte of packet payload. -* -* Additional information -* The payload length and evnetId are not initialized. -* PreparePacket only reserves space for them and they are -* computed and filled in by the sending function. -*/ -static U8* _PreparePacket(U8* pPacket) { - return pPacket + _MAX_ID_BYTES + _MAX_DATA_BYTES; -} - -/********************************************************************* -* -* _HandleIncomingPacket() -* -* Function description -* Read an incoming command from the down channel and process it. -* -* Additional information -* This function is called each time after sending a packet. -* Processing incoming packets is done asynchronous. SystemView might -* already have sent event packets after the host has sent a command. -*/ -#if (SEGGER_SYSVIEW_POST_MORTEM_MODE != 1) -static void _HandleIncomingPacket(void) { - U8 Cmd; - unsigned int Status; - // - Status = SEGGER_RTT_ReadNoLock(CHANNEL_ID_DOWN, &Cmd, 1); - if (Status > 0) { - switch (Cmd) { - case SEGGER_SYSVIEW_COMMAND_ID_START: - SEGGER_SYSVIEW_Start(); - break; - case SEGGER_SYSVIEW_COMMAND_ID_STOP: - SEGGER_SYSVIEW_Stop(); - break; - case SEGGER_SYSVIEW_COMMAND_ID_GET_SYSTIME: - SEGGER_SYSVIEW_RecordSystime(); - break; - case SEGGER_SYSVIEW_COMMAND_ID_GET_TASKLIST: - SEGGER_SYSVIEW_SendTaskList(); - break; - case SEGGER_SYSVIEW_COMMAND_ID_GET_SYSDESC: - SEGGER_SYSVIEW_GetSysDesc(); - break; - case SEGGER_SYSVIEW_COMMAND_ID_GET_NUMMODULES: - SEGGER_SYSVIEW_SendNumModules(); - break; - case SEGGER_SYSVIEW_COMMAND_ID_GET_MODULEDESC: - SEGGER_SYSVIEW_SendModuleDescription(); - break; - case SEGGER_SYSVIEW_COMMAND_ID_GET_MODULE: - Status = SEGGER_RTT_ReadNoLock(CHANNEL_ID_DOWN, &Cmd, 1); - if (Status > 0) { - SEGGER_SYSVIEW_SendModule(Cmd); - } - break; - case SEGGER_SYSVIEW_COMMAND_ID_HEARTBEAT: - break; - default: - if (Cmd >= 128) { // Unknown extended command. Dummy read its parameter. - SEGGER_RTT_ReadNoLock(CHANNEL_ID_DOWN, &Cmd, 1); - } - break; - } - } -} -#endif // (SEGGER_SYSVIEW_POST_MORTEM_MODE != 1) - -/********************************************************************* -* -* _TrySendOverflowPacket() -* -* Function description -* Try to transmit an SystemView Overflow packet containing the -* number of dropped packets. -* -* Additional information -* Format as follows: -* 01 Max. packet len is 1 + 5 + 5 = 11 -* -* Example packets sent -* 01 20 40 -* -* Return value -* !=0: Success, Message sent (stored in RTT-Buffer) -* ==0: Buffer full, Message *NOT* stored -* -*/ -#if (SEGGER_SYSVIEW_POST_MORTEM_MODE != 1) -static int _TrySendOverflowPacket(void) { - U32 TimeStamp; - I32 Delta; - int Status; - U8 aPacket[11]; - U8* pPayload; - - aPacket[0] = SYSVIEW_EVTID_OVERFLOW; // 1 - pPayload = &aPacket[1]; - ENCODE_U32(pPayload, _SYSVIEW_Globals.DropCount); - // - // Compute time stamp delta and append it to packet. - // - TimeStamp = SEGGER_SYSVIEW_GET_TIMESTAMP(); - Delta = TimeStamp - _SYSVIEW_Globals.LastTxTimeStamp; - MAKE_DELTA_32BIT(Delta); - ENCODE_U32(pPayload, Delta); - // - // Try to store packet in RTT buffer and update time stamp when this was successful - // - Status = (int)SEGGER_RTT_WriteSkipNoLock(CHANNEL_ID_UP, aPacket, (unsigned int)(pPayload - aPacket)); - SEGGER_SYSVIEW_ON_EVENT_RECORDED(pPayload - aPacket); - if (Status) { - _SYSVIEW_Globals.LastTxTimeStamp = TimeStamp; - _SYSVIEW_Globals.EnableState--; // EnableState has been 2, will be 1. Always. - } else { - _SYSVIEW_Globals.DropCount++; - } - // - return Status; -} -#endif // (SEGGER_SYSVIEW_POST_MORTEM_MODE != 1) - -/********************************************************************* -* -* _SendSyncInfo() -* -* Function description -* Send SystemView sync packet and system information in -* post mortem mode. -* -* Additional information -* Sync is 10 * 0x00 without timestamp -*/ -#if (SEGGER_SYSVIEW_POST_MORTEM_MODE == 1) -static void _SendSyncInfo(void) { - // - // Add sync packet ( 10 * 0x00) - // Send system description - // Send system time - // Send task list - // Send module description - // Send module information - // - SEGGER_RTT_WriteWithOverwriteNoLock(CHANNEL_ID_UP, _abSync, 10); - SEGGER_SYSVIEW_ON_EVENT_RECORDED(10); - SEGGER_SYSVIEW_RecordVoid(SYSVIEW_EVTID_TRACE_START); - { - U8* pPayload; - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + 4 * SEGGER_SYSVIEW_QUANTA_U32); - // - pPayload = pPayloadStart; - ENCODE_U32(pPayload, _SYSVIEW_Globals.SysFreq); - ENCODE_U32(pPayload, _SYSVIEW_Globals.CPUFreq); - ENCODE_U32(pPayload, _SYSVIEW_Globals.RAMBaseAddress); - ENCODE_U32(pPayload, SEGGER_SYSVIEW_ID_SHIFT); - _SendPacket(pPayloadStart, pPayload, SYSVIEW_EVTID_INIT); - RECORD_END(); - } - if (_SYSVIEW_Globals.pfSendSysDesc) { - _SYSVIEW_Globals.pfSendSysDesc(); - } - SEGGER_SYSVIEW_RecordSystime(); - SEGGER_SYSVIEW_SendTaskList(); - if (_NumModules > 0) { - int n; - SEGGER_SYSVIEW_SendNumModules(); - for (n = 0; n < _NumModules; n++) { - SEGGER_SYSVIEW_SendModule(n); - } - } -} -#endif // (SEGGER_SYSVIEW_POST_MORTEM_MODE == 1) - -/********************************************************************* -* -* _SendPacket() -* -* Function description -* Send a SystemView packet over RTT. RTT channel and mode are -* configured by macros when the SystemView component is initialized. -* This function takes care of maintaining the packet drop count -* and sending overflow packets when necessary. -* The packet must be passed without Id and Length because this -* function prepends it to the packet before transmission. -* -* Parameters -* pStartPacket - Pointer to start of packet payload. -* There must be at least 4 bytes free to prepend Id and Length. -* pEndPacket - Pointer to end of packet payload. -* EventId - Id of the event to send. -* -*/ -static void _SendPacket(U8* pStartPacket, U8* pEndPacket, unsigned int EventId) { - unsigned int NumBytes; - U32 TimeStamp; - U32 Delta; -#if (SEGGER_SYSVIEW_POST_MORTEM_MODE != 1) - unsigned int Status; -#endif - -#if (SEGGER_SYSVIEW_USE_STATIC_BUFFER == 0) - SEGGER_SYSVIEW_LOCK(); -#endif - -#if (SEGGER_SYSVIEW_POST_MORTEM_MODE == 1) - if (_SYSVIEW_Globals.EnableState == 0) { - goto SendDone; - } -#else - if (_SYSVIEW_Globals.EnableState == 1) { // Enabled, no dropped packets remaining - goto Send; - } - if (_SYSVIEW_Globals.EnableState == 0) { - goto SendDone; - } - // - // Handle buffer full situations: - // Have packets been dropped before because buffer was full? - // In this case try to send and overflow packet. - // - if (_SYSVIEW_Globals.EnableState == 2) { - _TrySendOverflowPacket(); - if (_SYSVIEW_Globals.EnableState != 1) { - goto SendDone; - } - } -Send: -#endif - // - // Check if event is disabled from being recorded. - // - if (EventId < 32) { - if (_SYSVIEW_Globals.DisabledEvents & ((U32)1u << EventId)) { - goto SendDone; - } - } - // - // Prepare actual packet. - // If it is a known packet, prepend eventId only, - // otherwise prepend packet length and eventId. - // - if (EventId < 24) { - *--pStartPacket = (U8)EventId; - } else { - // - // Get data length and prepend it. - // - NumBytes = (unsigned int)(pEndPacket - pStartPacket); -#if SEGGER_SYSVIEW_SUPPORT_LONG_DATA - if (NumBytes < 127) { - #error "Seems EventId should be changed to NumBytes in the next line. Please check." - *--pStartPacket = EventId; - } else { - // - // Backwards U32 encode EventId. - // - if (NumBytes < (1ul << 14)) { // Encodes in 2 bytes - *--pStartPacket = (U8)(NumBytes >> 7); - *--pStartPacket = (U8)(NumBytes | 0x80); - } else if (NumBytes < (1ul << 21)) { // Encodes in 3 bytes - *--pStartPacket = (U8)(NumBytes >> 14); - *--pStartPacket = (U8)((NumBytes >> 7) | 0x80); - *--pStartPacket = (U8)(NumBytes | 0x80); - } else if (NumBytes < (1ul << 28)) { // Encodes in 4 bytes - *--pStartPacket = (U8)(NumBytes >> 21); - *--pStartPacket = (U8)((NumBytes >> 14) | 0x80); - *--pStartPacket = (U8)((NumBytes >> 7) | 0x80); - *--pStartPacket = (U8)(NumBytes | 0x80); - } else { // Encodes in 5 bytes - *--pStartPacket = (U8)(NumBytes >> 28); - *--pStartPacket = (U8)((NumBytes >> 21) | 0x80); - *--pStartPacket = (U8)((NumBytes >> 14) | 0x80); - *--pStartPacket = (U8)((NumBytes >> 7) | 0x80); - *--pStartPacket = (U8)(NumBytes | 0x80); - } - } -#else - if (NumBytes > 127) { - *--pStartPacket = (U8)(NumBytes >> 7); - *--pStartPacket = (U8)(NumBytes | 0x80); - } else { - *--pStartPacket = (U8)NumBytes; - } -#endif - // - // Prepend EventId. - // -#if SEGGER_SYSVIEW_SUPPORT_LONG_ID - if (EventId < 127) { - *--pStartPacket = (U8)EventId; - } else { - // - // Backwards U32 encode EventId. - // - if (EventId < (1u << 14)) { // Encodes in 2 bytes - *--pStartPacket = (U8)(EventId >> 7); - *--pStartPacket = (U8)(EventId | 0x80); - } else if (EventId < (1ul << 21)) { // Encodes in 3 bytes - *--pStartPacket = (U8)(EventId >> 14); - *--pStartPacket = (U8)((EventId >> 7) | 0x80); - *--pStartPacket = (U8)(EventId | 0x80); - } else if (EventId < (1ul << 28)) { // Encodes in 4 bytes - *--pStartPacket = (U8)(EventId >> 21); - *--pStartPacket = (U8)((EventId >> 14) | 0x80); - *--pStartPacket = (U8)((EventId >> 7) | 0x80); - *--pStartPacket = (U8)(EventId | 0x80); - } else { // Encodes in 5 bytes - *--pStartPacket = (U8)(EventId >> 28); - *--pStartPacket = (U8)((EventId >> 21) | 0x80); - *--pStartPacket = (U8)((EventId >> 14) | 0x80); - *--pStartPacket = (U8)((EventId >> 7) | 0x80); - *--pStartPacket = (U8)(EventId | 0x80); - } - } -#else - if (EventId > 127) { - *--pStartPacket = (U8)(EventId >> 7); - *--pStartPacket = (U8)(EventId | 0x80); - } else { - *--pStartPacket = (U8)EventId; - } -#endif - } - // - // Compute time stamp delta and append it to packet. - // - TimeStamp = SEGGER_SYSVIEW_GET_TIMESTAMP(); - Delta = TimeStamp - _SYSVIEW_Globals.LastTxTimeStamp; - MAKE_DELTA_32BIT(Delta); - ENCODE_U32(pEndPacket, Delta); -#if (SEGGER_SYSVIEW_POST_MORTEM_MODE == 1) - // - // Store packet in RTT buffer by overwriting old data and update time stamp - // - SEGGER_RTT_WriteWithOverwriteNoLock(CHANNEL_ID_UP, pStartPacket, pEndPacket - pStartPacket); - SEGGER_SYSVIEW_ON_EVENT_RECORDED(pEndPacket - pStartPacket); - _SYSVIEW_Globals.LastTxTimeStamp = TimeStamp; -#else - // - // Try to store packet in RTT buffer and update time stamp when this was successful - // - Status = SEGGER_RTT_WriteSkipNoLock(CHANNEL_ID_UP, pStartPacket, (unsigned int)(pEndPacket - pStartPacket)); - SEGGER_SYSVIEW_ON_EVENT_RECORDED(pEndPacket - pStartPacket); - if (Status) { - _SYSVIEW_Globals.LastTxTimeStamp = TimeStamp; - } else { - _SYSVIEW_Globals.EnableState++; // EnableState has been 1, will be 2. Always. - } -#endif - -#if (SEGGER_SYSVIEW_POST_MORTEM_MODE == 1) - // - // Add sync and system information periodically if we are in post mortem mode - // - if (_SYSVIEW_Globals.RecursionCnt == 0) { // Avoid uncontrolled nesting. This way, this routine can call itself once, but no more often than that. - _SYSVIEW_Globals.RecursionCnt = 1; - if (_SYSVIEW_Globals.PacketCount++ & (1 << SEGGER_SYSVIEW_SYNC_PERIOD_SHIFT)) { - _SendSyncInfo(); - _SYSVIEW_Globals.PacketCount = 0; - } - _SYSVIEW_Globals.RecursionCnt = 0; - } -SendDone: - ; // Avoid "label at end of compound statement" error when using static buffer -#else -SendDone: - // - // Check if host is sending data which needs to be processed. - // Note that since this code is called for every packet, it is very time critical, so we do - // only what is really needed here, which is checking if there is any data - // - if (SEGGER_RTT_HASDATA(CHANNEL_ID_DOWN)) { - if (_SYSVIEW_Globals.RecursionCnt == 0) { // Avoid uncontrolled nesting. This way, this routine can call itself once, but no more often than that. - _SYSVIEW_Globals.RecursionCnt = 1; - _HandleIncomingPacket(); - _SYSVIEW_Globals.RecursionCnt = 0; - } - } -#endif - // -#if (SEGGER_SYSVIEW_USE_STATIC_BUFFER == 0) - SEGGER_SYSVIEW_UNLOCK(); // We are done. Unlock and return -#endif -} - -#ifndef SEGGER_SYSVIEW_EXCLUDE_PRINTF // Define in project to avoid warnings about variable parameter list -/********************************************************************* -* -* _VPrintHost() -* -* Function description -* Send a format string and its parameters to the host. -* -* Parameters -* s Pointer to format string. -* Options Options to be sent to the host. -* pParamList Pointer to the list of arguments for the format string. -*/ -static int _VPrintHost(const char* s, U32 Options, va_list* pParamList) { - U32 aParas[SEGGER_SYSVIEW_MAX_ARGUMENTS]; - U32* pParas; - U32 NumArguments; - const char* p; - char c; - U8* pPayload; - U8* pPayloadStart; -#if SEGGER_SYSVIEW_PRINTF_IMPLICIT_FORMAT - U8 HasNonScalar; - - HasNonScalar = 0; -#endif - // - // Count number of arguments by counting '%' characters in string. - // If enabled, check for non-scalar modifier flags to format string on the target. - // - p = s; - NumArguments = 0; - for (;;) { - c = *p++; - if (c == 0) { - break; - } - if (c == '%') { - c = *p; -#if SEGGER_SYSVIEW_PRINTF_IMPLICIT_FORMAT == 0 - aParas[NumArguments++] = (U32)(va_arg(*pParamList, int)); - if (NumArguments == SEGGER_SYSVIEW_MAX_ARGUMENTS) { - break; - } -#else - if (c == 's') { - HasNonScalar = 1; - break; - } else { - aParas[NumArguments++] = (U32)(va_arg(*pParamList, int)); - if (NumArguments == SEGGER_SYSVIEW_MAX_ARGUMENTS) { - break; - } - } -#endif - } - } - -#if SEGGER_SYSVIEW_PRINTF_IMPLICIT_FORMAT - if (HasNonScalar) { - return -1; - } -#endif - // - // Send string and parameters to host - // - { - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + SEGGER_SYSVIEW_MAX_STRING_LEN + 2 * SEGGER_SYSVIEW_QUANTA_U32 + SEGGER_SYSVIEW_MAX_ARGUMENTS * SEGGER_SYSVIEW_QUANTA_U32); - pPayload = _EncodeStr(pPayloadStart, s, SEGGER_SYSVIEW_MAX_STRING_LEN); - ENCODE_U32(pPayload, Options); - ENCODE_U32(pPayload, NumArguments); - pParas = aParas; - while (NumArguments--) { - ENCODE_U32(pPayload, (*pParas)); - pParas++; - } - _SendPacket(pPayloadStart, pPayload, SYSVIEW_EVTID_PRINT_FORMATTED); - RECORD_END(); - } - return 0; -} - -/********************************************************************* -* -* _StoreChar() -* -* Function description -* Stores a character in the printf-buffer and sends the buffer when -* it is filled. -* -* Parameters -* p Pointer to the buffer description. -* c Character to be printed. -*/ -static void _StoreChar(SEGGER_SYSVIEW_PRINTF_DESC * p, char c) { - unsigned int Cnt; - U8* pPayload; - U32 Options; - - Cnt = p->Cnt; - if ((Cnt + 1u) <= SEGGER_SYSVIEW_MAX_STRING_LEN) { - *(p->pPayload++) = (U8)c; - p->Cnt = Cnt + 1u; - } - // - // Write part of string, when the buffer is full - // - if (p->Cnt == SEGGER_SYSVIEW_MAX_STRING_LEN) { - *(p->pPayloadStart) = (U8)p->Cnt; - pPayload = p->pPayload; - Options = p->Options; - ENCODE_U32(pPayload, Options); - ENCODE_U32(pPayload, 0); - _SendPacket(p->pPayloadStart, pPayload, SYSVIEW_EVTID_PRINT_FORMATTED); - p->pPayloadStart = _PreparePacket(p->pBuffer); - p->pPayload = p->pPayloadStart + 1u; - p->Cnt = 0u; - } -} - -/********************************************************************* -* -* _PrintUnsigned() -* -* Function description -* Print an unsigned integer with the given formatting into the -* formatted string. -* -* Parameters -* pBufferDesc Pointer to the buffer description. -* v Value to be printed. -* Base Base of the value. -* NumDigits Number of digits to be printed. -* FieldWidth Width of the printed field. -* FormatFlags Flags for formatting the value. -*/ -static void _PrintUnsigned(SEGGER_SYSVIEW_PRINTF_DESC * pBufferDesc, unsigned int v, unsigned int Base, unsigned int NumDigits, unsigned int FieldWidth, unsigned int FormatFlags) { - static const char _aV2C[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; - unsigned int Div; - unsigned int Digit; - unsigned int Number; - unsigned int Width; - char c; - - Number = v; - Digit = 1u; - // - // Get actual field width - // - Width = 1u; - while (Number >= Base) { - Number = (Number / Base); - Width++; - } - if (NumDigits > Width) { - Width = NumDigits; - } - // - // Print leading chars if necessary - // - if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) { - if (FieldWidth != 0u) { - if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && (NumDigits == 0u)) { - c = '0'; - } else { - c = ' '; - } - while ((FieldWidth != 0u) && (Width < FieldWidth)) { - FieldWidth--; - _StoreChar(pBufferDesc, c); - } - } - } - // - // Compute Digit. - // Loop until Digit has the value of the highest digit required. - // Example: If the output is 345 (Base 10), loop 2 times until Digit is 100. - // - while (1) { - if (NumDigits > 1u) { // User specified a min number of digits to print? => Make sure we loop at least that often, before checking anything else (> 1 check avoids problems with NumDigits being signed / unsigned) - NumDigits--; - } else { - Div = v / Digit; - if (Div < Base) { // Is our divider big enough to extract the highest digit from value? => Done - break; - } - } - Digit *= Base; - } - // - // Output digits - // - do { - Div = v / Digit; - v -= Div * Digit; - _StoreChar(pBufferDesc, _aV2C[Div]); - Digit /= Base; - } while (Digit); - // - // Print trailing spaces if necessary - // - if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == FORMAT_FLAG_LEFT_JUSTIFY) { - if (FieldWidth != 0u) { - while ((FieldWidth != 0u) && (Width < FieldWidth)) { - FieldWidth--; - _StoreChar(pBufferDesc, ' '); - } - } - } -} - -/********************************************************************* -* -* _PrintInt() -* -* Function description -* Print a signed integer with the given formatting into the -* formatted string. -* -* Parameters -* pBufferDesc Pointer to the buffer description. -* v Value to be printed. -* Base Base of the value. -* NumDigits Number of digits to be printed. -* FieldWidth Width of the printed field. -* FormatFlags Flags for formatting the value. -*/ -static void _PrintInt(SEGGER_SYSVIEW_PRINTF_DESC * pBufferDesc, int v, unsigned int Base, unsigned int NumDigits, unsigned int FieldWidth, unsigned int FormatFlags) { - unsigned int Width; - int Number; - - Number = (v < 0) ? -v : v; - - // - // Get actual field width - // - Width = 1u; - while (Number >= (int)Base) { - Number = (Number / (int)Base); - Width++; - } - if (NumDigits > Width) { - Width = NumDigits; - } - if ((FieldWidth > 0u) && ((v < 0) || ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN))) { - FieldWidth--; - } - - // - // Print leading spaces if necessary - // - if ((((FormatFlags & FORMAT_FLAG_PAD_ZERO) == 0u) || (NumDigits != 0u)) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u)) { - if (FieldWidth != 0u) { - while ((FieldWidth != 0u) && (Width < FieldWidth)) { - FieldWidth--; - _StoreChar(pBufferDesc, ' '); - } - } - } - // - // Print sign if necessary - // - if (v < 0) { - v = -v; - _StoreChar(pBufferDesc, '-'); - } else if ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN) { - _StoreChar(pBufferDesc, '+'); - } else { - - } - // - // Print leading zeros if necessary - // - if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) && (NumDigits == 0u)) { - if (FieldWidth != 0u) { - while ((FieldWidth != 0u) && (Width < FieldWidth)) { - FieldWidth--; - _StoreChar(pBufferDesc, '0'); - } - } - } - // - // Print number without sign - // - _PrintUnsigned(pBufferDesc, (unsigned int)v, Base, NumDigits, FieldWidth, FormatFlags); -} - -/********************************************************************* -* -* _VPrintTarget() -* -* Function description -* Stores a formatted string. -* This data is read by the host. -* -* Parameters -* sFormat Pointer to format string. -* Options Options to be sent to the host. -* pParamList Pointer to the list of arguments for the format string. -*/ -static void _VPrintTarget(const char* sFormat, U32 Options, va_list* pParamList) { - SEGGER_SYSVIEW_PRINTF_DESC BufferDesc; - char c; - int v; - unsigned int NumDigits; - unsigned int FormatFlags; - unsigned int FieldWidth; - U8* pPayloadStart; - const char* s; -#if SEGGER_SYSVIEW_USE_STATIC_BUFFER == 0 - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + SEGGER_SYSVIEW_MAX_STRING_LEN + 1 + 2 * SEGGER_SYSVIEW_QUANTA_U32); - SEGGER_SYSVIEW_LOCK(); -#else - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + SEGGER_SYSVIEW_MAX_STRING_LEN + 1 + 2 * SEGGER_SYSVIEW_QUANTA_U32); -#endif - -#if SEGGER_SYSVIEW_USE_STATIC_BUFFER == 0 - BufferDesc.pBuffer = aPacket; -#else - BufferDesc.pBuffer = _aPacket; -#endif - BufferDesc.Cnt = 0u; - BufferDesc.pPayloadStart = pPayloadStart; - BufferDesc.pPayload = BufferDesc.pPayloadStart + 1u; - BufferDesc.Options = Options; - - do { - c = *sFormat; - sFormat++; - if (c == 0u) { - break; - } - if (c == '%') { - // - // Filter out flags - // - FormatFlags = 0u; - v = 1; - do { - c = *sFormat; - switch (c) { - case '-': FormatFlags |= FORMAT_FLAG_LEFT_JUSTIFY; sFormat++; break; - case '0': FormatFlags |= FORMAT_FLAG_PAD_ZERO; sFormat++; break; - case '+': FormatFlags |= FORMAT_FLAG_PRINT_SIGN; sFormat++; break; - case '#': FormatFlags |= FORMAT_FLAG_ALTERNATE; sFormat++; break; - default: v = 0; break; - } - } while (v); - // - // filter out field with - // - FieldWidth = 0u; - do { - c = *sFormat; - if ((c < '0') || (c > '9')) { - break; - } - sFormat++; - FieldWidth = (FieldWidth * 10u) + ((unsigned int)c - '0'); - } while (1); - - // - // Filter out precision (number of digits to display) - // - NumDigits = 0u; - c = *sFormat; - if (c == '.') { - sFormat++; - do { - c = *sFormat; - if ((c < '0') || (c > '9')) { - break; - } - sFormat++; - NumDigits = NumDigits * 10u + ((unsigned int)c - '0'); - } while (1); - } - // - // Filter out length modifier - // - c = *sFormat; - do { - if ((c == 'l') || (c == 'h')) { - c = *sFormat; - sFormat++; - } else { - break; - } - } while (1); - // - // Handle specifiers - // - switch (c) { - case 'c': { - char c0; - v = va_arg(*pParamList, int); - c0 = (char)v; - _StoreChar(&BufferDesc, c0); - break; - } - case 'd': - v = va_arg(*pParamList, int); - _PrintInt(&BufferDesc, v, 10u, NumDigits, FieldWidth, FormatFlags); - break; - case 'u': - v = va_arg(*pParamList, int); - _PrintUnsigned(&BufferDesc, (unsigned int)v, 10u, NumDigits, FieldWidth, FormatFlags); - break; - case 'x': - case 'X': - v = va_arg(*pParamList, int); - _PrintUnsigned(&BufferDesc, (unsigned int)v, 16u, NumDigits, FieldWidth, FormatFlags); - break; - case 's': - s = va_arg(*pParamList, const char*); - if (s == NULL) { - s = "(null)"; - } - do { - c = *s; - s++; - if (c == '\0') { - break; - } - _StoreChar(&BufferDesc, c); - } while (BufferDesc.Cnt < SEGGER_SYSVIEW_MAX_STRING_LEN); - break; - case 'p': - v = va_arg(*pParamList, int); - _PrintUnsigned(&BufferDesc, (unsigned int)v, 16u, 8u, 8u, 0u); - break; - case '%': - _StoreChar(&BufferDesc, '%'); - break; - default: - break; - } - sFormat++; - } else { - _StoreChar(&BufferDesc, c); - } - } while (*sFormat); - - // - // Write remaining data, if any - // - if (BufferDesc.Cnt != 0u) { - *(BufferDesc.pPayloadStart) = (U8)BufferDesc.Cnt; - ENCODE_U32(BufferDesc.pPayload, BufferDesc.Options); - ENCODE_U32(BufferDesc.pPayload, 0); - _SendPacket(BufferDesc.pPayloadStart, BufferDesc.pPayload, SYSVIEW_EVTID_PRINT_FORMATTED); - } -#if SEGGER_SYSVIEW_USE_STATIC_BUFFER == 0 - SEGGER_SYSVIEW_UNLOCK(); - RECORD_END(); -#else - RECORD_END(); -#endif -} -#endif // SEGGER_SYSVIEW_EXCLUDE_PRINTF - -/********************************************************************* -* -* Public code -* -********************************************************************** -*/ - -/********************************************************************* -* -* SEGGER_SYSVIEW_Init() -* -* Function description -* Initializes the SYSVIEW module. -* Must be called before the SystemView Application connects to -* the system. -* -* Parameters -* SysFreq - Frequency of timestamp, usually CPU core clock frequency. -* CPUFreq - CPU core clock frequency. -* pOSAPI - Pointer to the API structure for OS-specific functions. -* pfSendSysDesc - Pointer to record system description callback function. -* -* Additional information -* This function initializes the RTT channel used to transport -* SEGGER SystemView packets. -* The channel is assigned the label "SysView" for client software -* to identify the SystemView channel. -* -* The channel is configured with the macro SEGGER_SYSVIEW_RTT_CHANNEL. -*/ -void SEGGER_SYSVIEW_Init(U32 SysFreq, U32 CPUFreq, const SEGGER_SYSVIEW_OS_API *pOSAPI, SEGGER_SYSVIEW_SEND_SYS_DESC_FUNC pfSendSysDesc) { -#ifdef SEGGER_RTT_SECTION - // - // Explicitly initialize the RTT Control Block if it is in its dedicated section. - // - SEGGER_RTT_Init(); -#endif -#if (SEGGER_SYSVIEW_POST_MORTEM_MODE == 1) -#if SEGGER_SYSVIEW_RTT_CHANNEL > 0 - SEGGER_RTT_ConfigUpBuffer(SEGGER_SYSVIEW_RTT_CHANNEL, "SysView", &_UpBuffer[0], sizeof(_UpBuffer), SEGGER_RTT_MODE_NO_BLOCK_SKIP); -#else - _SYSVIEW_Globals.UpChannel = (U8)SEGGER_RTT_AllocUpBuffer ("SysView", &_UpBuffer[0], sizeof(_UpBuffer), SEGGER_RTT_MODE_NO_BLOCK_SKIP); -#endif - _SYSVIEW_Globals.RAMBaseAddress = SEGGER_SYSVIEW_ID_BASE; - _SYSVIEW_Globals.LastTxTimeStamp = SEGGER_SYSVIEW_GET_TIMESTAMP(); - _SYSVIEW_Globals.pOSAPI = pOSAPI; - _SYSVIEW_Globals.SysFreq = SysFreq; - _SYSVIEW_Globals.CPUFreq = CPUFreq; - _SYSVIEW_Globals.pfSendSysDesc = pfSendSysDesc; - _SYSVIEW_Globals.EnableState = 0; - _SYSVIEW_Globals.PacketCount = 0; -#else // (SEGGER_SYSVIEW_POST_MORTEM_MODE == 1) -#if SEGGER_SYSVIEW_RTT_CHANNEL > 0 - SEGGER_RTT_ConfigUpBuffer (SEGGER_SYSVIEW_RTT_CHANNEL, "SysView", &_UpBuffer[0], sizeof(_UpBuffer), SEGGER_RTT_MODE_NO_BLOCK_SKIP); - SEGGER_RTT_ConfigDownBuffer (SEGGER_SYSVIEW_RTT_CHANNEL, "SysView", &_DownBuffer[0], sizeof(_DownBuffer), SEGGER_RTT_MODE_NO_BLOCK_SKIP); -#else - _SYSVIEW_Globals.UpChannel = (U8)SEGGER_RTT_AllocUpBuffer ("SysView", &_UpBuffer[0], sizeof(_UpBuffer), SEGGER_RTT_MODE_NO_BLOCK_SKIP); - _SYSVIEW_Globals.DownChannel = _SYSVIEW_Globals.UpChannel; - SEGGER_RTT_ConfigDownBuffer (_SYSVIEW_Globals.DownChannel, "SysView", &_DownBuffer[0], sizeof(_DownBuffer), SEGGER_RTT_MODE_NO_BLOCK_SKIP); -#endif - _SYSVIEW_Globals.RAMBaseAddress = SEGGER_SYSVIEW_ID_BASE; - _SYSVIEW_Globals.LastTxTimeStamp = SEGGER_SYSVIEW_GET_TIMESTAMP(); - _SYSVIEW_Globals.pOSAPI = pOSAPI; - _SYSVIEW_Globals.SysFreq = SysFreq; - _SYSVIEW_Globals.CPUFreq = CPUFreq; - _SYSVIEW_Globals.pfSendSysDesc = pfSendSysDesc; - _SYSVIEW_Globals.EnableState = 0; -#endif // (SEGGER_SYSVIEW_POST_MORTEM_MODE == 1) -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_SetRAMBase() -* -* Function description -* Sets the RAM base address, which is subtracted from IDs in order -* to save bandwidth. -* -* Parameters -* RAMBaseAddress - Lowest RAM Address. (i.e. 0x20000000 on most Cortex-M) -*/ -void SEGGER_SYSVIEW_SetRAMBase(U32 RAMBaseAddress) { - _SYSVIEW_Globals.RAMBaseAddress = RAMBaseAddress; -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_RecordVoid() -* -* Function description -* Formats and sends a SystemView packet with an empty payload. -* -* Parameters -* EventID - SystemView event ID. -*/ -void SEGGER_SYSVIEW_RecordVoid(unsigned int EventID) { - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE); - // - _SendPacket(pPayloadStart, pPayloadStart, EventID); - RECORD_END(); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_RecordU32() -* -* Function description -* Formats and sends a SystemView packet containing a single U32 -* parameter payload. -* -* Parameters -* EventID - SystemView event ID. -* Value - The 32-bit parameter encoded to SystemView packet payload. -*/ -void SEGGER_SYSVIEW_RecordU32(unsigned int EventID, U32 Value) { - U8* pPayload; - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + SEGGER_SYSVIEW_QUANTA_U32); - // - pPayload = pPayloadStart; - ENCODE_U32(pPayload, Value); - _SendPacket(pPayloadStart, pPayload, EventID); - RECORD_END(); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_RecordU32x2() -* -* Function description -* Formats and sends a SystemView packet containing 2 U32 parameter payload. -* -* Parameters -* EventID - SystemView event ID. -* Para0 - The 32-bit parameter encoded to SystemView packet payload. -* Para1 - The 32-bit parameter encoded to SystemView packet payload. -*/ -void SEGGER_SYSVIEW_RecordU32x2(unsigned int EventID, U32 Para0, U32 Para1) { - U8* pPayload; - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + 2 * SEGGER_SYSVIEW_QUANTA_U32); - // - pPayload = pPayloadStart; - ENCODE_U32(pPayload, Para0); - ENCODE_U32(pPayload, Para1); - _SendPacket(pPayloadStart, pPayload, EventID); - RECORD_END(); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_RecordU32x3() -* -* Function description -* Formats and sends a SystemView packet containing 3 U32 parameter payload. -* -* Parameters -* EventID - SystemView event ID. -* Para0 - The 32-bit parameter encoded to SystemView packet payload. -* Para1 - The 32-bit parameter encoded to SystemView packet payload. -* Para2 - The 32-bit parameter encoded to SystemView packet payload. -*/ -void SEGGER_SYSVIEW_RecordU32x3(unsigned int EventID, U32 Para0, U32 Para1, U32 Para2) { - U8* pPayload; - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + 3 * SEGGER_SYSVIEW_QUANTA_U32); - // - pPayload = pPayloadStart; - ENCODE_U32(pPayload, Para0); - ENCODE_U32(pPayload, Para1); - ENCODE_U32(pPayload, Para2); - _SendPacket(pPayloadStart, pPayload, EventID); - RECORD_END(); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_RecordU32x4() -* -* Function description -* Formats and sends a SystemView packet containing 4 U32 parameter payload. -* -* Parameters -* EventID - SystemView event ID. -* Para0 - The 32-bit parameter encoded to SystemView packet payload. -* Para1 - The 32-bit parameter encoded to SystemView packet payload. -* Para2 - The 32-bit parameter encoded to SystemView packet payload. -* Para3 - The 32-bit parameter encoded to SystemView packet payload. -*/ -void SEGGER_SYSVIEW_RecordU32x4(unsigned int EventID, U32 Para0, U32 Para1, U32 Para2, U32 Para3) { - U8* pPayload; - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + 4 * SEGGER_SYSVIEW_QUANTA_U32); - // - pPayload = pPayloadStart; - ENCODE_U32(pPayload, Para0); - ENCODE_U32(pPayload, Para1); - ENCODE_U32(pPayload, Para2); - ENCODE_U32(pPayload, Para3); - _SendPacket(pPayloadStart, pPayload, EventID); - RECORD_END(); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_RecordU32x5() -* -* Function description -* Formats and sends a SystemView packet containing 5 U32 parameter payload. -* -* Parameters -* EventID - SystemView event ID. -* Para0 - The 32-bit parameter encoded to SystemView packet payload. -* Para1 - The 32-bit parameter encoded to SystemView packet payload. -* Para2 - The 32-bit parameter encoded to SystemView packet payload. -* Para3 - The 32-bit parameter encoded to SystemView packet payload. -* Para4 - The 32-bit parameter encoded to SystemView packet payload. -*/ -void SEGGER_SYSVIEW_RecordU32x5(unsigned int EventID, U32 Para0, U32 Para1, U32 Para2, U32 Para3, U32 Para4) { - U8* pPayload; - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + 5 * SEGGER_SYSVIEW_QUANTA_U32); - // - pPayload = pPayloadStart; - ENCODE_U32(pPayload, Para0); - ENCODE_U32(pPayload, Para1); - ENCODE_U32(pPayload, Para2); - ENCODE_U32(pPayload, Para3); - ENCODE_U32(pPayload, Para4); - _SendPacket(pPayloadStart, pPayload, EventID); - RECORD_END(); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_RecordU32x6() -* -* Function description -* Formats and sends a SystemView packet containing 6 U32 parameter payload. -* -* Parameters -* EventID - SystemView event ID. -* Para0 - The 32-bit parameter encoded to SystemView packet payload. -* Para1 - The 32-bit parameter encoded to SystemView packet payload. -* Para2 - The 32-bit parameter encoded to SystemView packet payload. -* Para3 - The 32-bit parameter encoded to SystemView packet payload. -* Para4 - The 32-bit parameter encoded to SystemView packet payload. -* Para5 - The 32-bit parameter encoded to SystemView packet payload. -*/ -void SEGGER_SYSVIEW_RecordU32x6(unsigned int EventID, U32 Para0, U32 Para1, U32 Para2, U32 Para3, U32 Para4, U32 Para5) { - U8* pPayload; - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + 6 * SEGGER_SYSVIEW_QUANTA_U32); - // - pPayload = pPayloadStart; - ENCODE_U32(pPayload, Para0); - ENCODE_U32(pPayload, Para1); - ENCODE_U32(pPayload, Para2); - ENCODE_U32(pPayload, Para3); - ENCODE_U32(pPayload, Para4); - ENCODE_U32(pPayload, Para5); - _SendPacket(pPayloadStart, pPayload, EventID); - RECORD_END(); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_RecordU32x7() -* -* Function description -* Formats and sends a SystemView packet containing 7 U32 parameter payload. -* -* Parameters -* EventID - SystemView event ID. -* Para0 - The 32-bit parameter encoded to SystemView packet payload. -* Para1 - The 32-bit parameter encoded to SystemView packet payload. -* Para2 - The 32-bit parameter encoded to SystemView packet payload. -* Para3 - The 32-bit parameter encoded to SystemView packet payload. -* Para4 - The 32-bit parameter encoded to SystemView packet payload. -* Para5 - The 32-bit parameter encoded to SystemView packet payload. -* Para6 - The 32-bit parameter encoded to SystemView packet payload. -*/ -void SEGGER_SYSVIEW_RecordU32x7(unsigned int EventID, U32 Para0, U32 Para1, U32 Para2, U32 Para3, U32 Para4, U32 Para5, U32 Para6) { - U8* pPayload; - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + 7 * SEGGER_SYSVIEW_QUANTA_U32); - // - pPayload = pPayloadStart; - ENCODE_U32(pPayload, Para0); - ENCODE_U32(pPayload, Para1); - ENCODE_U32(pPayload, Para2); - ENCODE_U32(pPayload, Para3); - ENCODE_U32(pPayload, Para4); - ENCODE_U32(pPayload, Para5); - ENCODE_U32(pPayload, Para6); - _SendPacket(pPayloadStart, pPayload, EventID); - RECORD_END(); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_RecordU32x8() -* -* Function description -* Formats and sends a SystemView packet containing 8 U32 parameter payload. -* -* Parameters -* EventID - SystemView event ID. -* Para0 - The 32-bit parameter encoded to SystemView packet payload. -* Para1 - The 32-bit parameter encoded to SystemView packet payload. -* Para2 - The 32-bit parameter encoded to SystemView packet payload. -* Para3 - The 32-bit parameter encoded to SystemView packet payload. -* Para4 - The 32-bit parameter encoded to SystemView packet payload. -* Para5 - The 32-bit parameter encoded to SystemView packet payload. -* Para6 - The 32-bit parameter encoded to SystemView packet payload. -* Para7 - The 32-bit parameter encoded to SystemView packet payload. -*/ -void SEGGER_SYSVIEW_RecordU32x8(unsigned int EventID, U32 Para0, U32 Para1, U32 Para2, U32 Para3, U32 Para4, U32 Para5, U32 Para6, U32 Para7) { - U8* pPayload; - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + 8 * SEGGER_SYSVIEW_QUANTA_U32); - // - pPayload = pPayloadStart; - ENCODE_U32(pPayload, Para0); - ENCODE_U32(pPayload, Para1); - ENCODE_U32(pPayload, Para2); - ENCODE_U32(pPayload, Para3); - ENCODE_U32(pPayload, Para4); - ENCODE_U32(pPayload, Para5); - ENCODE_U32(pPayload, Para6); - ENCODE_U32(pPayload, Para7); - _SendPacket(pPayloadStart, pPayload, EventID); - RECORD_END(); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_RecordU32x9() -* -* Function description -* Formats and sends a SystemView packet containing 9 U32 parameter payload. -* -* Parameters -* EventID - SystemView event ID. -* Para0 - The 32-bit parameter encoded to SystemView packet payload. -* Para1 - The 32-bit parameter encoded to SystemView packet payload. -* Para2 - The 32-bit parameter encoded to SystemView packet payload. -* Para3 - The 32-bit parameter encoded to SystemView packet payload. -* Para4 - The 32-bit parameter encoded to SystemView packet payload. -* Para5 - The 32-bit parameter encoded to SystemView packet payload. -* Para6 - The 32-bit parameter encoded to SystemView packet payload. -* Para7 - The 32-bit parameter encoded to SystemView packet payload. -* Para8 - The 32-bit parameter encoded to SystemView packet payload. -*/ -void SEGGER_SYSVIEW_RecordU32x9(unsigned int EventID, U32 Para0, U32 Para1, U32 Para2, U32 Para3, U32 Para4, U32 Para5, U32 Para6, U32 Para7, U32 Para8) { - U8* pPayload; - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + 9 * SEGGER_SYSVIEW_QUANTA_U32); - // - pPayload = pPayloadStart; - ENCODE_U32(pPayload, Para0); - ENCODE_U32(pPayload, Para1); - ENCODE_U32(pPayload, Para2); - ENCODE_U32(pPayload, Para3); - ENCODE_U32(pPayload, Para4); - ENCODE_U32(pPayload, Para5); - ENCODE_U32(pPayload, Para6); - ENCODE_U32(pPayload, Para7); - ENCODE_U32(pPayload, Para8); - _SendPacket(pPayloadStart, pPayload, EventID); - RECORD_END(); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_RecordU32x10() -* -* Function description -* Formats and sends a SystemView packet containing 10 U32 parameter payload. -* -* Parameters -* EventID - SystemView event ID. -* Para0 - The 32-bit parameter encoded to SystemView packet payload. -* Para1 - The 32-bit parameter encoded to SystemView packet payload. -* Para2 - The 32-bit parameter encoded to SystemView packet payload. -* Para3 - The 32-bit parameter encoded to SystemView packet payload. -* Para4 - The 32-bit parameter encoded to SystemView packet payload. -* Para5 - The 32-bit parameter encoded to SystemView packet payload. -* Para6 - The 32-bit parameter encoded to SystemView packet payload. -* Para7 - The 32-bit parameter encoded to SystemView packet payload. -* Para8 - The 32-bit parameter encoded to SystemView packet payload. -* Para9 - The 32-bit parameter encoded to SystemView packet payload. -*/ -void SEGGER_SYSVIEW_RecordU32x10(unsigned int EventID, U32 Para0, U32 Para1, U32 Para2, U32 Para3, U32 Para4, U32 Para5, U32 Para6, U32 Para7, U32 Para8, U32 Para9) { - U8* pPayload; - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + 10 * SEGGER_SYSVIEW_QUANTA_U32); - // - pPayload = pPayloadStart; - ENCODE_U32(pPayload, Para0); - ENCODE_U32(pPayload, Para1); - ENCODE_U32(pPayload, Para2); - ENCODE_U32(pPayload, Para3); - ENCODE_U32(pPayload, Para4); - ENCODE_U32(pPayload, Para5); - ENCODE_U32(pPayload, Para6); - ENCODE_U32(pPayload, Para7); - ENCODE_U32(pPayload, Para8); - ENCODE_U32(pPayload, Para9); - _SendPacket(pPayloadStart, pPayload, EventID); - RECORD_END(); -} -/********************************************************************* -* -* SEGGER_SYSVIEW_RecordString() -* -* Function description -* Formats and sends a SystemView packet containing a string. -* -* Parameters -* EventID - SystemView event ID. -* pString - The string to be sent in the SystemView packet payload. -* -* Additional information -* The string is encoded as a count byte followed by the contents -* of the string. -* No more than SEGGER_SYSVIEW_MAX_STRING_LEN bytes will be encoded to the payload. -*/ -void SEGGER_SYSVIEW_RecordString(unsigned int EventID, const char* pString) { - U8* pPayload; - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + 1 + SEGGER_SYSVIEW_MAX_STRING_LEN); - // - pPayload = _EncodeStr(pPayloadStart, pString, SEGGER_SYSVIEW_MAX_STRING_LEN); - _SendPacket(pPayloadStart, pPayload, EventID); - RECORD_END(); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_Start() -* -* Function description -* Start recording SystemView events. -* -* This function is triggered by the SystemView Application on connect. -* For single-shot or post-mortem mode recording, it needs to be called -* by the application. -* -* Additional information -* This function enables transmission of SystemView packets recorded -* by subsequent trace calls and records a SystemView Start event. -* -* As part of start, a SystemView Init packet is sent, containing the system -* frequency. The list of current tasks, the current system time and the -* system description string is sent, too. -* -* Notes -* SEGGER_SYSVIEW_Start and SEGGER_SYSVIEW_Stop do not nest. -* When SEGGER_SYSVIEW_CAN_RESTART is 1, each received start command -* records the system information. This is required to enable restart -* of recordings when SystemView unexpectedly disconnects without sending -* a stop command before. -*/ -void SEGGER_SYSVIEW_Start(void) { -#if (SEGGER_SYSVIEW_CAN_RESTART == 0) - if (_SYSVIEW_Globals.EnableState == 0) { -#endif - _SYSVIEW_Globals.EnableState = 1; -#if (SEGGER_SYSVIEW_POST_MORTEM_MODE == 1) - _SendSyncInfo(); -#else - SEGGER_SYSVIEW_LOCK(); - SEGGER_RTT_WriteSkipNoLock(CHANNEL_ID_UP, _abSync, 10); - SEGGER_SYSVIEW_UNLOCK(); - SEGGER_SYSVIEW_ON_EVENT_RECORDED(10); - SEGGER_SYSVIEW_RecordVoid(SYSVIEW_EVTID_TRACE_START); - { - U8* pPayload; - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + 4 * SEGGER_SYSVIEW_QUANTA_U32); - // - pPayload = pPayloadStart; - ENCODE_U32(pPayload, _SYSVIEW_Globals.SysFreq); - ENCODE_U32(pPayload, _SYSVIEW_Globals.CPUFreq); - ENCODE_U32(pPayload, _SYSVIEW_Globals.RAMBaseAddress); - ENCODE_U32(pPayload, SEGGER_SYSVIEW_ID_SHIFT); - _SendPacket(pPayloadStart, pPayload, SYSVIEW_EVTID_INIT); - RECORD_END(); - } - if (_SYSVIEW_Globals.pfSendSysDesc) { - _SYSVIEW_Globals.pfSendSysDesc(); - } - SEGGER_SYSVIEW_RecordSystime(); - SEGGER_SYSVIEW_SendTaskList(); - SEGGER_SYSVIEW_SendNumModules(); -#endif -#if (SEGGER_SYSVIEW_CAN_RESTART == 0) - } -#endif -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_Stop() -* -* Function description -* Stop recording SystemView events. -* -* This function is triggered by the SystemView Application on disconnect. -* For single-shot or postmortem mode recording, it can be called -* by the application. -* -* Additional information -* This function disables transmission of SystemView packets recorded -* by subsequent trace calls. If transmission is enabled when -* this function is called, a single SystemView Stop event is recorded -* to the trace, send, and then trace transmission is halted. -*/ -void SEGGER_SYSVIEW_Stop(void) { - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE); - // We should send answer for the Stop command in any case. - _SYSVIEW_Globals.EnableState = 1; - if (_SYSVIEW_Globals.EnableState) { - _SendPacket(pPayloadStart, pPayloadStart, SYSVIEW_EVTID_TRACE_STOP); - _SYSVIEW_Globals.EnableState = 0; - } - RECORD_END(); -} - -U8 SEGGER_SYSVIEW_Started(void) { - return _SYSVIEW_Globals.EnableState; -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_GetChannelID() -* -* Function description -* Returns the RTT / channel ID used by SystemView. -*/ -int SEGGER_SYSVIEW_GetChannelID(void) { - return CHANNEL_ID_UP; -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_GetSysDesc() -* -* Function description -* Triggers a send of the system information and description. -* -*/ -void SEGGER_SYSVIEW_GetSysDesc(void) { - U8* pPayload; - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + 2 * SEGGER_SYSVIEW_QUANTA_U32 + SEGGER_SYSVIEW_MAX_STRING_LEN + 3/*1 or 3 bytes for string length*/); - // - pPayload = pPayloadStart; - ENCODE_U32(pPayload, _SYSVIEW_Globals.SysFreq); - ENCODE_U32(pPayload, _SYSVIEW_Globals.CPUFreq); - ENCODE_U32(pPayload, _SYSVIEW_Globals.RAMBaseAddress); - ENCODE_U32(pPayload, SEGGER_SYSVIEW_ID_SHIFT); - _SendPacket(pPayloadStart, pPayload, SYSVIEW_EVTID_INIT); - RECORD_END(); - if (_SYSVIEW_Globals.pfSendSysDesc) { - _SYSVIEW_Globals.pfSendSysDesc(); - } -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_SendTaskInfo() -* -* Function description -* Send a Task Info Packet, containing TaskId for identification, -* task priority and task name. -* -* Parameters -* pInfo - Pointer to task information to send. -*/ -void SEGGER_SYSVIEW_SendTaskInfo(const SEGGER_SYSVIEW_TASKINFO *pInfo) { - U8* pPayload; - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + SEGGER_SYSVIEW_QUANTA_U32 + 1 + 32); - // - pPayload = pPayloadStart; - ENCODE_U32(pPayload, SHRINK_ID(pInfo->TaskID)); - ENCODE_U32(pPayload, pInfo->Prio); - pPayload = _EncodeStr(pPayload, pInfo->sName, 32); - _SendPacket(pPayloadStart, pPayload, SYSVIEW_EVTID_TASK_INFO); - // - pPayload = pPayloadStart; - ENCODE_U32(pPayload, SHRINK_ID(pInfo->TaskID)); - ENCODE_U32(pPayload, pInfo->StackBase); - ENCODE_U32(pPayload, pInfo->StackSize); - ENCODE_U32(pPayload, pInfo->StackUsage); - _SendPacket(pPayloadStart, pPayload, SYSVIEW_EVTID_STACK_INFO); - RECORD_END(); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_SendStackInfo() -* -* Function description -* Send a Stack Info Packet, containing TaskId for identification, -* stack base, stack size and stack usage. -* -* -* Parameters -* pInfo - Pointer to stack information to send. -*/ -void SEGGER_SYSVIEW_SendStackInfo(const SEGGER_SYSVIEW_STACKINFO *pInfo) { - U8* pPayload; - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + 4 * SEGGER_SYSVIEW_QUANTA_U32); - // - pPayload = pPayloadStart; - ENCODE_U32(pPayload, SHRINK_ID(pInfo->TaskID)); - ENCODE_U32(pPayload, pInfo->StackBase); - ENCODE_U32(pPayload, pInfo->StackSize); - ENCODE_U32(pPayload, pInfo->StackUsage); - - RECORD_END(); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_SampleData() -* -* Function description -* Send a Data Sample Packet, containing the data Id and the value. -* -* -* Parameters -* pInfo - Pointer to data sample struct to send. -*/ -void SEGGER_SYSVIEW_SampleData(const SEGGER_SYSVIEW_DATA_SAMPLE *pInfo) { - U8* pPayload; - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + 2 * SEGGER_SYSVIEW_QUANTA_U32); - // - pPayload = pPayloadStart; - ENCODE_U32(pPayload, pInfo->ID); - pPayload = _EncodeFloat(pPayload, *(pInfo->pFloat_Value)); - _SendPacket(pPayloadStart, pPayload, SYSVIEW_EVTID_DATA_SAMPLE); - - RECORD_END(); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_SendTaskList() -* -* Function description -* Send all tasks descriptors to the host. -*/ -void SEGGER_SYSVIEW_SendTaskList(void) { - if (_SYSVIEW_Globals.pOSAPI && _SYSVIEW_Globals.pOSAPI->pfSendTaskList) { - _SYSVIEW_Globals.pOSAPI->pfSendTaskList(); - } -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_SendSysDesc() -* -* Function description -* Send the system description string to the host. -* The system description is used by the SystemView Application -* to identify the current application and handle events accordingly. -* -* The system description is usually called by the system description -* callback, to ensure it is only sent when the SystemView Application -* is connected. -* -* Parameters -* sSysDesc - Pointer to the 0-terminated system description string. -* -* Additional information -* One system description string may not exceed SEGGER_SYSVIEW_MAX_STRING_LEN characters. -* Multiple description strings can be recorded. -* -* The Following items can be described in a system description string. -* Each item is identified by its identifier, followed by '=' and the value. -* Items are separated by ','. -*/ -void SEGGER_SYSVIEW_SendSysDesc(const char *sSysDesc) { - U8* pPayload; - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + 1 + SEGGER_SYSVIEW_MAX_STRING_LEN); - // - pPayload = _EncodeStr(pPayloadStart, sSysDesc, SEGGER_SYSVIEW_MAX_STRING_LEN); - _SendPacket(pPayloadStart, pPayload, SYSVIEW_EVTID_SYSDESC); - RECORD_END(); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_RecordSystime() -* -* Function description -* Formats and sends a SystemView Systime containing a single U64 or U32 -* parameter payload. -*/ -void SEGGER_SYSVIEW_RecordSystime(void) { - U64 Systime; - // This code requeued because SystemView expect the answer from the device. - // If there is no answer, then communication will be broken. - U8 old_en = _SYSVIEW_Globals.EnableState; - _SYSVIEW_Globals.EnableState = 1; - - if (_SYSVIEW_Globals.pOSAPI && _SYSVIEW_Globals.pOSAPI->pfGetTime) { - Systime = _SYSVIEW_Globals.pOSAPI->pfGetTime(); - SEGGER_SYSVIEW_RecordU32x2(SYSVIEW_EVTID_SYSTIME_US, - (U32)(Systime), - (U32)(Systime >> 32)); - } else { - SEGGER_SYSVIEW_RecordU32(SYSVIEW_EVTID_SYSTIME_CYCLES, SEGGER_SYSVIEW_GET_TIMESTAMP()); - } - _SYSVIEW_Globals.EnableState = old_en; -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_RecordEnterISR() -* -* Function description -* Format and send an ISR entry event. -* -* Additional information -* Example packets sent -* 02 0F 50 // ISR(15) Enter. Timestamp is 80 (0x50) -*/ -void SEGGER_SYSVIEW_RecordEnterISR(U32 IrqId) { - unsigned v; - U8* pPayload; - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + SEGGER_SYSVIEW_QUANTA_U32); - // - pPayload = pPayloadStart; - v = IrqId; // SEGGER_SYSVIEW_GET_INTERRUPT_ID(); - ENCODE_U32(pPayload, v); - _SendPacket(pPayloadStart, pPayload, SYSVIEW_EVTID_ISR_ENTER); - RECORD_END(); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_RecordExitISR() -* -* Function description -* Format and send an ISR exit event. -* -* Additional information -* Format as follows: -* 03 // Max. packet len is 6 -* -* Example packets sent -* 03 20 // ISR Exit. Timestamp is 32 (0x20) -*/ -void SEGGER_SYSVIEW_RecordExitISR(void) { - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE); - // - _SendPacket(pPayloadStart, pPayloadStart, SYSVIEW_EVTID_ISR_EXIT); - RECORD_END(); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_RecordExitISRToScheduler() -* -* Function description -* Format and send an ISR exit into scheduler event. -* -* Additional information -* Format as follows: -* 18 // Max. packet len is 6 -* -* Example packets sent -* 18 20 // ISR Exit to Scheduler. Timestamp is 32 (0x20) -*/ -void SEGGER_SYSVIEW_RecordExitISRToScheduler(void) { - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE); - // - _SendPacket(pPayloadStart, pPayloadStart, SYSVIEW_EVTID_ISR_TO_SCHEDULER); - RECORD_END(); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_RecordEnterTimer() -* -* Function description -* Format and send a Timer entry event. -* -* Parameters -* TimerId - Id of the timer which starts. -*/ -void SEGGER_SYSVIEW_RecordEnterTimer(U32 TimerId) { - U8* pPayload; - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + SEGGER_SYSVIEW_QUANTA_U32); - // - pPayload = pPayloadStart; - ENCODE_U32(pPayload, SHRINK_ID(TimerId)); - _SendPacket(pPayloadStart, pPayload, SYSVIEW_EVTID_TIMER_ENTER); - RECORD_END(); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_RecordExitTimer() -* -* Function description -* Format and send a Timer exit event. -*/ -void SEGGER_SYSVIEW_RecordExitTimer(void) { - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE); - // - _SendPacket(pPayloadStart, pPayloadStart, SYSVIEW_EVTID_TIMER_EXIT); - RECORD_END(); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_RecordEndCall() -* -* Function description -* Format and send an End API Call event without return value. -* -* Parameters -* EventID - Id of API function which ends. -*/ -void SEGGER_SYSVIEW_RecordEndCall(unsigned int EventID) { - U8* pPayload; - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + SEGGER_SYSVIEW_QUANTA_U32); - // - pPayload = pPayloadStart; - ENCODE_U32(pPayload, EventID); - _SendPacket(pPayloadStart, pPayload, SYSVIEW_EVTID_END_CALL); - RECORD_END(); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_RecordEndCallU32() -* -* Function description -* Format and send an End API Call event with return value. -* -* Parameters -* EventID - Id of API function which ends. -* Para0 - Return value which will be returned by the API function. -*/ -void SEGGER_SYSVIEW_RecordEndCallU32(unsigned int EventID, U32 Para0) { - U8* pPayload; - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + 2 * SEGGER_SYSVIEW_QUANTA_U32); - // - pPayload = pPayloadStart; - ENCODE_U32(pPayload, EventID); - ENCODE_U32(pPayload, Para0); - _SendPacket(pPayloadStart, pPayload, SYSVIEW_EVTID_END_CALL); - RECORD_END(); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_OnIdle() -* -* Function description -* Record an Idle event. -*/ -void SEGGER_SYSVIEW_OnIdle(void) { - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE); - // - _SendPacket(pPayloadStart, pPayloadStart, SYSVIEW_EVTID_IDLE); - RECORD_END(); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_OnTaskCreate() -* -* Function description -* Record a Task Create event. The Task Create event corresponds -* to creating a task in the OS. -* -* Parameters -* TaskId - Task ID of created task. -*/ -void SEGGER_SYSVIEW_OnTaskCreate(U32 TaskId) { - U8* pPayload; - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + SEGGER_SYSVIEW_QUANTA_U32); - // - pPayload = pPayloadStart; - TaskId = SHRINK_ID(TaskId); - ENCODE_U32(pPayload, TaskId); - _SendPacket(pPayloadStart, pPayload, SYSVIEW_EVTID_TASK_CREATE); - RECORD_END(); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_OnTaskTerminate() -* -* Function description -* Record a Task termination event. -* The Task termination event corresponds to terminating a task in -* the OS. If the TaskId is the currently active task, -* SEGGER_SYSVIEW_OnTaskStopExec may be used, either. -* -* Parameters -* TaskId - Task ID of terminated task. -*/ -void SEGGER_SYSVIEW_OnTaskTerminate(U32 TaskId) { - U8* pPayload; - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + SEGGER_SYSVIEW_QUANTA_U32); - // - pPayload = pPayloadStart; - TaskId = SHRINK_ID(TaskId); - ENCODE_U32(pPayload, TaskId); - _SendPacket(pPayloadStart, pPayload, SYSVIEW_EVTID_TASK_TERMINATE); - RECORD_END(); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_OnTaskStartExec() -* -* Function description -* Record a Task Start Execution event. The Task Start event -* corresponds to when a task has started to execute rather than -* when it is ready to execute. -* -* Parameters -* TaskId - Task ID of task that started to execute. -*/ -void SEGGER_SYSVIEW_OnTaskStartExec(U32 TaskId) { - U8* pPayload; - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + SEGGER_SYSVIEW_QUANTA_U32); - // - pPayload = pPayloadStart; - TaskId = SHRINK_ID(TaskId); - ENCODE_U32(pPayload, TaskId); - _SendPacket(pPayloadStart, pPayload, SYSVIEW_EVTID_TASK_START_EXEC); - RECORD_END(); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_OnTaskStopExec() -* -* Function description -* Record a Task Stop Execution event. The Task Stop event -* corresponds to when a task stops executing and terminates. -*/ -void SEGGER_SYSVIEW_OnTaskStopExec(void) { - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE); - // - _SendPacket(pPayloadStart, pPayloadStart, SYSVIEW_EVTID_TASK_STOP_EXEC); - RECORD_END(); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_OnTaskStartReady() -* -* Function description -* Record a Task Start Ready event. -* -* Parameters -* TaskId - Task ID of task that started to execute. -*/ -void SEGGER_SYSVIEW_OnTaskStartReady(U32 TaskId) { - U8* pPayload; - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + SEGGER_SYSVIEW_QUANTA_U32); - // - pPayload = pPayloadStart; - TaskId = SHRINK_ID(TaskId); - ENCODE_U32(pPayload, TaskId); - _SendPacket(pPayloadStart, pPayload, SYSVIEW_EVTID_TASK_START_READY); - RECORD_END(); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_OnTaskStopReady() -* -* Function description -* Record a Task Stop Ready event. -* -* Parameters -* TaskId - Task ID of task that completed execution. -* Cause - Reason for task to stop (i.e. Idle/Sleep) -*/ -void SEGGER_SYSVIEW_OnTaskStopReady(U32 TaskId, unsigned int Cause) { - U8* pPayload; - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + 2 * SEGGER_SYSVIEW_QUANTA_U32); - // - pPayload = pPayloadStart; - TaskId = SHRINK_ID(TaskId); - ENCODE_U32(pPayload, TaskId); - ENCODE_U32(pPayload, Cause); - _SendPacket(pPayloadStart, pPayload, SYSVIEW_EVTID_TASK_STOP_READY); - RECORD_END(); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_MarkStart() -* -* Function description -* Record a Performance Marker Start event to start measuring runtime. -* -* Parameters -* MarkerId - User defined ID for the marker. -*/ -void SEGGER_SYSVIEW_MarkStart(unsigned MarkerId) { - U8* pPayload; - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + SEGGER_SYSVIEW_QUANTA_U32); - // - pPayload = pPayloadStart; - ENCODE_U32(pPayload, MarkerId); - _SendPacket(pPayloadStart, pPayload, SYSVIEW_EVTID_MARK_START); - RECORD_END(); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_MarkStop() -* -* Function description -* Record a Performance Marker Stop event to stop measuring runtime. -* -* Parameters -* MarkerId - User defined ID for the marker. -*/ -void SEGGER_SYSVIEW_MarkStop(unsigned MarkerId) { - U8 * pPayload; - U8 * pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + SEGGER_SYSVIEW_QUANTA_U32); - // - pPayload = pPayloadStart; - ENCODE_U32(pPayload, MarkerId); - _SendPacket(pPayloadStart, pPayload, SYSVIEW_EVTID_MARK_STOP); - RECORD_END(); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_Mark() -* -* Function description -* Record a Performance Marker intermediate event. -* -* Parameters -* MarkerId - User defined ID for the marker. -*/ -void SEGGER_SYSVIEW_Mark(unsigned int MarkerId) { - U8* pPayload; - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + 2 * SEGGER_SYSVIEW_QUANTA_U32); - // - pPayload = pPayloadStart; - ENCODE_U32(pPayload, SYSVIEW_EVTID_EX_MARK); - ENCODE_U32(pPayload, MarkerId); - _SendPacket(pPayloadStart, pPayload, SYSVIEW_EVTID_EX); - RECORD_END(); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_NameMarker() -* -* Function description -* Send the name of a Performance Marker to be displayed in SystemView. -* -* Marker names are usually set in the system description -* callback, to ensure it is only sent when the SystemView Application -* is connected. -* -* Parameters -* MarkerId - User defined ID for the marker. -* sName - Pointer to the marker name. (Max. SEGGER_SYSVIEW_MAX_STRING_LEN Bytes) -*/ -void SEGGER_SYSVIEW_NameMarker(unsigned int MarkerId, const char* sName) { - U8* pPayload; - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + 2 * SEGGER_SYSVIEW_QUANTA_U32 + 1 + SEGGER_SYSVIEW_MAX_STRING_LEN); - // - pPayload = pPayloadStart; - ENCODE_U32(pPayload, SYSVIEW_EVTID_EX_NAME_MARKER); - ENCODE_U32(pPayload, MarkerId); - pPayload = _EncodeStr(pPayload, sName, SEGGER_SYSVIEW_MAX_STRING_LEN); - _SendPacket(pPayloadStart, pPayload, SYSVIEW_EVTID_EX); - RECORD_END(); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_NameResource() -* -* Function description -* Send the name of a resource to be displayed in SystemView. -* -* Marker names are usually set in the system description -* callback, to ensure it is only sent when the SystemView Application -* is connected. -* -* Parameters -* ResourceId - Id of the resource to be named. i.e. its address. -* sName - Pointer to the resource name. (Max. SEGGER_SYSVIEW_MAX_STRING_LEN Bytes) -*/ -void SEGGER_SYSVIEW_NameResource(U32 ResourceId, const char* sName) { - U8* pPayload; - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + SEGGER_SYSVIEW_QUANTA_U32 + 1 + SEGGER_SYSVIEW_MAX_STRING_LEN); - // - pPayload = pPayloadStart; - ENCODE_U32(pPayload, SHRINK_ID(ResourceId)); - pPayload = _EncodeStr(pPayload, sName, SEGGER_SYSVIEW_MAX_STRING_LEN); - _SendPacket(pPayloadStart, pPayload, SYSVIEW_EVTID_NAME_RESOURCE); - RECORD_END(); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_RegisterData() -* -* Function description -* Register data to sample the values via SystemView. -* -* Register functions are usually set in the system description -* callback, to ensure it is only sent when the SystemView Application -* is connected. -* -* Parameters -* pInfo - Struct containing all possible properties that can be sent via this registration event. -*/ -void SEGGER_SYSVIEW_RegisterData(SEGGER_SYSVIEW_DATA_REGISTER* pInfo) { - U8* pPayload; - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + 8 * SEGGER_SYSVIEW_QUANTA_U32 + 1 + SEGGER_SYSVIEW_MAX_STRING_LEN); - // - pPayload = pPayloadStart; - ENCODE_U32(pPayload, SYSVIEW_EVTID_EX_REGISTER_DATA); - ENCODE_U32(pPayload, pInfo->ID); - pPayload = _EncodeStr(pPayload, pInfo->sName, SEGGER_SYSVIEW_MAX_STRING_LEN); - - if (pInfo->sName != 0) { - ENCODE_U32(pPayload, pInfo->DataType); - ENCODE_U32(pPayload, pInfo->Offset); - ENCODE_U32(pPayload, pInfo->RangeMin); - ENCODE_U32(pPayload, pInfo->RangeMax); - pPayload = _EncodeFloat(pPayload, pInfo->ScalingFactor); - pPayload = _EncodeStr(pPayload, pInfo->sUnit, SEGGER_SYSVIEW_MAX_STRING_LEN); - } else if (pInfo->ScalingFactor != 0) { - ENCODE_U32(pPayload, pInfo->DataType); - ENCODE_U32(pPayload, pInfo->Offset); - ENCODE_U32(pPayload, pInfo->RangeMin); - ENCODE_U32(pPayload, pInfo->RangeMax); - pPayload = _EncodeFloat(pPayload, pInfo->ScalingFactor); - } else if (pInfo->RangeMax != 0) { - ENCODE_U32(pPayload, pInfo->DataType); - ENCODE_U32(pPayload, pInfo->Offset); - ENCODE_U32(pPayload, pInfo->RangeMin); - ENCODE_U32(pPayload, pInfo->RangeMax); - } else if (pInfo->RangeMin != 0) { - ENCODE_U32(pPayload, pInfo->DataType); - ENCODE_U32(pPayload, pInfo->Offset); - ENCODE_U32(pPayload, pInfo->RangeMin); - } else if (pInfo->Offset != 0) { - ENCODE_U32(pPayload, pInfo->DataType); - ENCODE_U32(pPayload, pInfo->Offset); - } else if (pInfo->DataType != 0) { - ENCODE_U32(pPayload, pInfo->DataType); - } - - _SendPacket(pPayloadStart, pPayload, SYSVIEW_EVTID_EX); - RECORD_END(); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_HeapDefine() -* -* Function description -* Define heap. -* -* Parameters -* pHeap - Pointer to heap control structure. -* pBase - Pointer to managed heap memory. -* HeapSize - Size of managed heap memory in bytes. -* MetadataSize - Size of metadata associated with each heap allocation. -* -* Additional information -* SystemView can track allocations across multiple heaps. -* -* HeapSize must be a multiple of the natural alignment unit of the -* target. This size is subject to compression, controlled by the -* specific setting of SEGGER_SYSVIEW_ID_SHIFT. -* -* MetadataSize defines the size of the per-allocation metadata. -* For many heap implementations, the metadata size is a multiple of -* the word size of the machine and typically contains the size -* of the allocated block (used upon deallocation), optional -* pointers to the preceding and/or following blocks, and optionally -* a tag identifying the owner of the block. Note that MetadataSize -* is not compressed within the SystemView packet and is not -* required to be a multiple of 1<> SEGGER_SYSVIEW_ID_SHIFT); - ENCODE_U32(pPayload, MetadataSize); - _SendPacket(pPayloadStart, pPayload, SYSVIEW_EVTID_EX); - RECORD_END(); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_HeapAlloc() -* -* Function description -* Record a system-heap allocation event. -* -* Parameters -* pHeap - Pointer to heap where allocation was made. -* pUserData - Pointer to allocated user data. -* UserDataLen - Size of block allocated to hold user data, excluding any metadata. -* -* Additional information -* The user data must be correctly aligned for the architecture, which -* typically requires that the alignment is at least the alignment -* of a double or a long long. pUserData is, therefore, compressed by -* shrinking as IDs are compressed, controlled by the specific setting -* of SEGGER_SYSVIEW_ID_SHIFT. -* -* In the same way, UserDataLen must reflect the size of the allocated -* block, not the allocation size requested by the application. This -* size is also subject to compression, controlled by the specific setting -* of SEGGER_SYSVIEW_ID_SHIFT. -* -* As an example, assume the allocator is running on a Cortex-M device -* with SEGGER_SYSVIEW_ID_SHIFT set to 2 (the word alignment of the device). -* If a user requests an allocation of 5 bytes, a hypothetical heap -* allocator could allocate a block with size 32 bytes for this. The value -* of UserDataLen sent to SystemView for recording should be 32, not 5, -* and the 32 is compressed by shifting by two bits, the configured value -* of SEGGER_SYSVIEW_ID_SHIFT, and describes the number of bytes that are -* consumed from managed memory from which SystemView can calculate -* accurate heap metrics. -*/ -void SEGGER_SYSVIEW_HeapAlloc(void *pHeap, void* pUserData, unsigned int UserDataLen) { - U8* pPayload; - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + 3 * SEGGER_SYSVIEW_QUANTA_U32); - // - pPayload = pPayloadStart; - ENCODE_U32(pPayload, SYSVIEW_EVTID_EX_HEAP_ALLOC); - ENCODE_U32(pPayload, SHRINK_ID((U32)pHeap)); - ENCODE_U32(pPayload, SHRINK_ID((U32)pUserData)); - ENCODE_U32(pPayload, UserDataLen >> SEGGER_SYSVIEW_ID_SHIFT); - _SendPacket(pPayloadStart, pPayload, SYSVIEW_EVTID_EX); - RECORD_END(); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_HeapAllocEx() -* -* Function description -* Record a per-heap allocation event. -* -* Parameters -* pHeap - Pointer to heap where allocation was made. -* pUserData - Pointer to allocated user data. -* UserDataLen - Size of block allocated to hold user data, excluding any metadata. -* Tag - Block tag, typically used to identify the owner of the block. -* -* Additional information -* The user data must be correctly aligned for the architecture, which -* typically requires that the alignment is at least the alignment -* of a double or a long long. pUserData is, therefore, compressed by -* shrinking as IDs are compressed, controlled by the specific setting -* of SEGGER_SYSVIEW_ID_SHIFT. -* -* In the same way, UserDataLen must reflect the size of the allocated -* block, not the allocation size requested by the application. This -* size is also subject to compression, controlled by the specific setting -* of SEGGER_SYSVIEW_ID_SHIFT. -* -* As an example, assume the allocator is running on a Cortex-M device -* with SEGGER_SYSVIEW_ID_SHIFT set to 2 (the word alignment of the device). -* If a user requests an allocation of 5 bytes, a hypothetical heap -* allocator could allocate a block with size 32 bytes for this. The value -* of UserDataLen sent to SystemView for recording should be 32, not 5, -* and the 32 is compressed by shifting by two bits, the configured value -* of SEGGER_SYSVIEW_ID_SHIFT, and describes the number of bytes that are -* consumed from managed memory from which SystemView can calculate -* accurate heap metrics. -* -* See also -* SEGGER_SYSVIEW_HeapAlloc(). -*/ -void SEGGER_SYSVIEW_HeapAllocEx(void *pHeap, void* pUserData, unsigned int UserDataLen, unsigned int Tag) { - U8* pPayload; - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + 5 * SEGGER_SYSVIEW_QUANTA_U32); - // - pPayload = pPayloadStart; - ENCODE_U32(pPayload, SYSVIEW_EVTID_EX_HEAP_ALLOC_EX); - ENCODE_U32(pPayload, SHRINK_ID((U32)pHeap)); - ENCODE_U32(pPayload, SHRINK_ID((U32)pUserData)); - ENCODE_U32(pPayload, UserDataLen >> SEGGER_SYSVIEW_ID_SHIFT); - ENCODE_U32(pPayload, Tag); - _SendPacket(pPayloadStart, pPayload, SYSVIEW_EVTID_EX); - RECORD_END(); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_HeapFree() -* -* Function description -* Record a heap deallocation event. -* -* Parameters -* pHeap - Pointer to heap where allocation was made. -* pUserData - Pointer to allocated user data. -* -* Additional information -* SystemViews track allocations and knows the size of the -* allocated data. -*/ -void SEGGER_SYSVIEW_HeapFree(void* pHeap, void* pUserData) { - U8* pPayload; - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + 2 * SEGGER_SYSVIEW_QUANTA_U32); - // - pPayload = pPayloadStart; - ENCODE_U32(pPayload, SYSVIEW_EVTID_EX_HEAP_FREE); - ENCODE_U32(pPayload, SHRINK_ID((U32)pHeap)); - ENCODE_U32(pPayload, SHRINK_ID((U32)pUserData)); - _SendPacket(pPayloadStart, pPayload, SYSVIEW_EVTID_EX); - RECORD_END(); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_SendPacket() -* -* Function description -* Send an event packet. -* -* Parameters -* pPacket - Pointer to the start of the packet. -* pPayloadEnd - Pointer to the end of the payload. -* Make sure there are at least 5 bytes free after the payload. -* EventId - Id of the event packet. -* -* Return value -* !=0: Success, Message sent. -* ==0: Buffer full, Message *NOT* sent. -*/ -int SEGGER_SYSVIEW_SendPacket(U8* pPacket, U8* pPayloadEnd, unsigned int EventId) { -#if (SEGGER_SYSVIEW_USE_STATIC_BUFFER == 1) - SEGGER_SYSVIEW_LOCK(); -#endif - _SendPacket(pPacket + 4, pPayloadEnd, EventId); -#if (SEGGER_SYSVIEW_USE_STATIC_BUFFER == 1) - SEGGER_SYSVIEW_UNLOCK(); -#endif - return 0; -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_EncodeU32() -* -* Function description -* Encode a U32 in variable-length format. -* -* Parameters -* pPayload - Pointer to where U32 will be encoded. -* Value - The 32-bit value to be encoded. -* -* Return value -* Pointer to the byte following the value, i.e. the first free -* byte in the payload and the next position to store payload -* content. -*/ -U8* SEGGER_SYSVIEW_EncodeU32(U8* pPayload, U32 Value) { - ENCODE_U32(pPayload, Value); - return pPayload; -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_EncodeString() -* -* Function description -* Encode a string in variable-length format. -* -* Parameters -* pPayload - Pointer to where string will be encoded. -* s - String to encode. -* MaxLen - Maximum number of characters to encode from string. -* -* Return value -* Pointer to the byte following the value, i.e. the first free -* byte in the payload and the next position to store payload -* content. -* -* Additional information -* The string is encoded as a count byte followed by the contents -* of the string. -* No more than 1 + MaxLen bytes will be encoded to the payload. -*/ -U8* SEGGER_SYSVIEW_EncodeString(U8* pPayload, const char* s, unsigned int MaxLen) { - return _EncodeStr(pPayload, s, MaxLen); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_EncodeData() -* -* Function description -* Encode a byte buffer in variable-length format. -* -* Parameters -* pPayload - Pointer to where string will be encoded. -* pSrc - Pointer to data buffer to be encoded. -* NumBytes - Number of bytes in the buffer to be encoded. -* -* Return value -* Pointer to the byte following the value, i.e. the first free -* byte in the payload and the next position to store payload -* content. -* -* Additional information -* The data is encoded as a count byte followed by the contents -* of the data buffer. -* Make sure NumBytes + 1 bytes are free for the payload. -*/ -U8* SEGGER_SYSVIEW_EncodeData(U8 *pPayload, const char* pSrc, unsigned int NumBytes) { - return _EncodeData(pPayload, pSrc, NumBytes); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_EncodeId() -* -* Function description -* Encode a 32-bit Id in shrunken variable-length format. -* -* Parameters -* pPayload - Pointer to where the Id will be encoded. -* Id - The 32-bit value to be encoded. -* -* Return value -* Pointer to the byte following the value, i.e. the first free -* byte in the payload and the next position to store payload -* content. -* -* Additional information -* The parameters to shrink an Id can be configured in -* SEGGER_SYSVIEW_Conf.h and via SEGGER_SYSVIEW_SetRAMBase(). -* SEGGER_SYSVIEW_ID_BASE: Lowest Id reported by the application. -* (i.e. 0x20000000 when all Ids are an address in this RAM) -* SEGGER_SYSVIEW_ID_SHIFT: Number of bits to shift the Id to -* save bandwidth. (i.e. 2 when Ids are 4 byte aligned) -*/ -U8* SEGGER_SYSVIEW_EncodeId(U8* pPayload, U32 Id) { - Id = SHRINK_ID(Id); - ENCODE_U32(pPayload, Id); - return pPayload; -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_ShrinkId() -* -* Function description -* Get the shrunken value of an Id for further processing like in -* SEGGER_SYSVIEW_NameResource(). -* -* Parameters -* Id - The 32-bit value to be shrunken. -* -* Return value -* Shrunken Id. -* -* Additional information -* The parameters to shrink an Id can be configured in -* SEGGER_SYSVIEW_Conf.h and via SEGGER_SYSVIEW_SetRAMBase(). -* SEGGER_SYSVIEW_ID_BASE: Lowest Id reported by the application. -* (i.e. 0x20000000 when all Ids are an address in this RAM) -* SEGGER_SYSVIEW_ID_SHIFT: Number of bits to shift the Id to -* save bandwidth. (i.e. 2 when Ids are 4 byte aligned) -*/ -U32 SEGGER_SYSVIEW_ShrinkId(U32 Id) { - return SHRINK_ID(Id); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_RegisterModule() -* -* Function description -* Register a middleware module for recording its events. -* -* Parameters -* pModule - The middleware module information. -* -* Additional information -* SEGGER_SYSVIEW_MODULE elements: -* sDescription - Pointer to a string containing the module name and optionally the module event description. -* NumEvents - Number of events the module wants to register. -* EventOffset - Offset to be added to the event Ids. Out parameter, set by this function. Do not modify after calling this function. -* pfSendModuleDesc - Callback function pointer to send more detailed module description to SystemView Application. -* pNext - Pointer to next registered module. Out parameter, set by this function. Do not modify after calling this function. -*/ -void SEGGER_SYSVIEW_RegisterModule(SEGGER_SYSVIEW_MODULE* pModule) { - SEGGER_SYSVIEW_LOCK(); - if (_pFirstModule == 0) { - // - // No module registered, yet. - // Start list with new module. - // EventOffset is the base offset for modules - // - pModule->EventOffset = MODULE_EVENT_OFFSET; - pModule->pNext = 0; - _pFirstModule = pModule; - _NumModules = 1; - } else { - // - // Registreded module(s) present. - // Prepend new module in list. - // EventOffset set from number of events and offset of previous module. - // - pModule->EventOffset = _pFirstModule->EventOffset + _pFirstModule->NumEvents; - pModule->pNext = _pFirstModule; - _pFirstModule = pModule; - _NumModules++; - } - SEGGER_SYSVIEW_SendModule(0); - SEGGER_SYSVIEW_UNLOCK(); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_RecordModuleDescription() -* -* Function description -* Sends detailed information of a registered module to the host. -* -* Parameters -* pModule - Pointer to the described module. -* sDescription - Pointer to a description string. -*/ -void SEGGER_SYSVIEW_RecordModuleDescription(const SEGGER_SYSVIEW_MODULE* pModule, const char* sDescription) { - U8 ModuleId; - SEGGER_SYSVIEW_MODULE* p; - - p = _pFirstModule; - ModuleId = 0; - do { - if (p == pModule) { - break; - } - ModuleId++; - p = p->pNext; - } while (p); - { - U8* pPayload; - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + 2 * SEGGER_SYSVIEW_QUANTA_U32 + 1 + SEGGER_SYSVIEW_MAX_STRING_LEN); - // - pPayload = pPayloadStart; - // - // Send module description - // Send event offset and number of events - // - ENCODE_U32(pPayload, ModuleId); - ENCODE_U32(pPayload, (pModule->EventOffset)); - pPayload = _EncodeStr(pPayload, sDescription, SEGGER_SYSVIEW_MAX_STRING_LEN); - _SendPacket(pPayloadStart, pPayload, SYSVIEW_EVTID_MODULEDESC); - RECORD_END(); - } -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_SendModule() -* -* Function description -* Sends the information of a registered module to the host. -* -* Parameters -* ModuleId - Id of the requested module. -*/ -void SEGGER_SYSVIEW_SendModule(U8 ModuleId) { - SEGGER_SYSVIEW_MODULE* pModule; - U32 n; - - if (_pFirstModule != 0) { - pModule = _pFirstModule; - for (n = 0; n < ModuleId; n++) { - pModule = pModule->pNext; - if (pModule == 0) { - break; - } - } - if (pModule != 0) { - U8* pPayload; - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + 2 * SEGGER_SYSVIEW_QUANTA_U32 + 1 + SEGGER_SYSVIEW_MAX_STRING_LEN); - // - pPayload = pPayloadStart; - // - // Send module description - // Send event offset and number of events - // - ENCODE_U32(pPayload, ModuleId); - ENCODE_U32(pPayload, (pModule->EventOffset)); - pPayload = _EncodeStr(pPayload, pModule->sModule, SEGGER_SYSVIEW_MAX_STRING_LEN); - _SendPacket(pPayloadStart, pPayload, SYSVIEW_EVTID_MODULEDESC); - RECORD_END(); - } - if (pModule && pModule->pfSendModuleDesc) { - pModule->pfSendModuleDesc(); - } - } -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_SendModuleDescription() -* -* Function description -* Triggers a send of the registered module descriptions. -* -*/ -void SEGGER_SYSVIEW_SendModuleDescription(void) { - SEGGER_SYSVIEW_MODULE* pModule; - - if (_pFirstModule != 0) { - pModule = _pFirstModule; - do { - if (pModule->pfSendModuleDesc) { - pModule->pfSendModuleDesc(); - } - pModule = pModule->pNext; - } while (pModule); - } -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_SendNumModules() -* -* Function description -* Send the number of registered modules to the host. -*/ -void SEGGER_SYSVIEW_SendNumModules(void) { - U8* pPayload; - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + 2*SEGGER_SYSVIEW_QUANTA_U32); - pPayload = pPayloadStart; - ENCODE_U32(pPayload, _NumModules); - _SendPacket(pPayloadStart, pPayload, SYSVIEW_EVTID_NUMMODULES); - RECORD_END(); -} - -#ifndef SEGGER_SYSVIEW_EXCLUDE_PRINTF // Define in project to avoid warnings about variable parameter list - -/********************************************************************* -* -* SEGGER_SYSVIEW_PrintfHostEx() -* -* Function description -* Print a string which is formatted on the host by the SystemView Application -* with Additional information. -* -* Parameters -* s - String to be formatted. -* Options - Options for the string. i.e. Log level. -* -* Additional information -* All format arguments are treated as 32-bit scalar values. -*/ -void SEGGER_SYSVIEW_PrintfHostEx(const char* s, U32 Options, ...) { - va_list ParamList; -#if SEGGER_SYSVIEW_PRINTF_IMPLICIT_FORMAT - int r; - - va_start(ParamList, Options); - r = _VPrintHost(s, Options, &ParamList); - va_end(ParamList); - - if (r == -1) { - va_start(ParamList, Options); - _VPrintTarget(s, Options, &ParamList); - va_end(ParamList); - } -#else - va_start(ParamList, Options); - _VPrintHost(s, Options, &ParamList); - va_end(ParamList); -#endif -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_VPrintfHostEx() -* -* Function description -* Print a string which is formatted on the host by the SystemView Application -* with Additional information. -* -* Parameters -* s - String to be formatted. -* Options - Options for the string. i.e. Log level. -* pParamList - Pointer to the list of arguments for the format string -* -* Additional information -* All format arguments are treated as 32-bit scalar values. -*/ -void SEGGER_SYSVIEW_VPrintfHostEx(const char* s, U32 Options, va_list *pParamList) { -#if SEGGER_SYSVIEW_PRINTF_IMPLICIT_FORMAT - int r; - va_list ParamListCopy; - va_copy(ParamListCopy, *pParamList); - - r = _VPrintHost(s, Options, pParamList); - - if (r == -1) { - _VPrintTarget(s, Options, &ParamListCopy); - } - va_end(ParamListCopy); -#else - _VPrintHost(s, Options, pParamList); -#endif -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_PrintfHost() -* -* Function description -* Print a string which is formatted on the host by the SystemView Application. -* -* Parameters -* s - String to be formatted. -* -* Additional information -* All format arguments are treated as 32-bit scalar values. -*/ -void SEGGER_SYSVIEW_PrintfHost(const char* s, ...) { - va_list ParamList; -#if SEGGER_SYSVIEW_PRINTF_IMPLICIT_FORMAT - int r; - - va_start(ParamList, s); - r = _VPrintHost(s, SEGGER_SYSVIEW_LOG, &ParamList); - va_end(ParamList); - - if (r == -1) { - va_start(ParamList, s); - _VPrintTarget(s, SEGGER_SYSVIEW_LOG, &ParamList); - va_end(ParamList); - } -#else - va_start(ParamList, s); - _VPrintHost(s, SEGGER_SYSVIEW_LOG, &ParamList); - va_end(ParamList); -#endif -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_VPrintfHost() -* -* Function description -* Print a string which is formatted on the host by the SystemView Application. -* -* Parameters -* s - String to be formatted. -* pParamList - Pointer to the list of arguments for the format string -* -* Additional information -* All format arguments are treated as 32-bit scalar values. -*/ -void SEGGER_SYSVIEW_VPrintfHost(const char* s, va_list *pParamList) { -#if SEGGER_SYSVIEW_PRINTF_IMPLICIT_FORMAT - int r; - va_list ParamListCopy; - va_copy(ParamListCopy, *pParamList); - - r = _VPrintHost(s, SEGGER_SYSVIEW_LOG, pParamList); - - if (r == -1) { - _VPrintTarget(s, SEGGER_SYSVIEW_LOG, &ParamListCopy); - } - va_end(ParamListCopy); -#else - _VPrintHost(s, SEGGER_SYSVIEW_LOG, pParamList); -#endif -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_WarnfHost() -* -* Function description -* Print a warning string which is formatted on the host by -* the SystemView Application. -* -* Parameters -* s - String to be formatted. -* -* Additional information -* All format arguments are treated as 32-bit scalar values. -*/ -void SEGGER_SYSVIEW_WarnfHost(const char* s, ...) { - va_list ParamList; -#if SEGGER_SYSVIEW_PRINTF_IMPLICIT_FORMAT - int r; - - va_start(ParamList, s); - r = _VPrintHost(s, SEGGER_SYSVIEW_WARNING, &ParamList); - va_end(ParamList); - - if (r == -1) { - va_start(ParamList, s); - _VPrintTarget(s, SEGGER_SYSVIEW_WARNING, &ParamList); - va_end(ParamList); - } -#else - va_start(ParamList, s); - _VPrintHost(s, SEGGER_SYSVIEW_WARNING, &ParamList); - va_end(ParamList); -#endif -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_VWarnfHost() -* -* Function description -* Print a warning string which is formatted on the host by -* the SystemView Application. -* -* Parameters -* s - String to be formatted. -* pParamList - Pointer to the list of arguments for the format string -* -* Additional information -* All format arguments are treated as 32-bit scalar values. -*/ -void SEGGER_SYSVIEW_VWarnfHost(const char* s, va_list *pParamList) { -#if SEGGER_SYSVIEW_PRINTF_IMPLICIT_FORMAT - int r; - va_list ParamListCopy; - va_copy(ParamListCopy, *pParamList); - - r = _VPrintHost(s, SEGGER_SYSVIEW_WARNING, pParamList); - - if (r == -1) { - _VPrintTarget(s, SEGGER_SYSVIEW_WARNING, &ParamListCopy); - } - va_end(ParamListCopy); -#else - _VPrintHost(s, SEGGER_SYSVIEW_WARNING, pParamList); -#endif -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_ErrorfHost() -* -* Function description -* Print an error string which is formatted on the host by -* the SystemView Application. -* -* Parameters -* s - String to be formatted. -* -* Additional information -* All format arguments are treated as 32-bit scalar values. -*/ -void SEGGER_SYSVIEW_ErrorfHost(const char* s, ...) { - va_list ParamList; -#if SEGGER_SYSVIEW_PRINTF_IMPLICIT_FORMAT - int r; - - va_start(ParamList, s); - r = _VPrintHost(s, SEGGER_SYSVIEW_ERROR, &ParamList); - va_end(ParamList); - - if (r == -1) { - va_start(ParamList, s); - _VPrintTarget(s, SEGGER_SYSVIEW_ERROR, &ParamList); - va_end(ParamList); - } -#else - va_start(ParamList, s); - _VPrintHost(s, SEGGER_SYSVIEW_ERROR, &ParamList); - va_end(ParamList); -#endif -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_VErrorfHost() -* -* Function description -* Print a warning string which is formatted on the host by -* the SystemView Application. -* -* Parameters -* s - String to be formatted. -* pParamList - Pointer to the list of arguments for the format string -* -* Additional information -* All format arguments are treated as 32-bit scalar values. -*/ -void SEGGER_SYSVIEW_VErrorfHost(const char* s, va_list *pParamList) { -#if SEGGER_SYSVIEW_PRINTF_IMPLICIT_FORMAT - int r; - va_list ParamListCopy; - va_copy(ParamListCopy, *pParamList); - - r = _VPrintHost(s, SEGGER_SYSVIEW_ERROR, pParamList); - - if (r == -1) { - _VPrintTarget(s, SEGGER_SYSVIEW_ERROR, &ParamListCopy); - } - va_end(ParamListCopy); -#else - _VPrintHost(s, SEGGER_SYSVIEW_ERROR, pParamList); -#endif -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_PrintfTargetEx() -* -* Function description -* Print a string which is formatted on the target before sent to -* the host with Additional information. -* -* Parameters -* s - String to be formatted. -* Options - Options for the string. i.e. Log level. -*/ -void SEGGER_SYSVIEW_PrintfTargetEx(const char* s, U32 Options, ...) { - va_list ParamList; - - va_start(ParamList, Options); - _VPrintTarget(s, Options, &ParamList); - va_end(ParamList); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_VPrintfTargetEx() -* -* Function description -* Print a string which is formatted on the target before sent to -* the host with Additional information. -* -* Parameters -* s - String to be formatted. -* Options - Options for the string. i.e. Log level. -* pParamList - Pointer to the list of arguments for the format string -*/ -void SEGGER_SYSVIEW_VPrintfTargetEx(const char* s, U32 Options, va_list *pParamList) { - _VPrintTarget(s, Options, pParamList); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_PrintfTarget() -* -* Function description -* Print a string which is formatted on the target before sent to -* the host. -* -* Parameters -* s - String to be formatted. -*/ -void SEGGER_SYSVIEW_PrintfTarget(const char* s, ...) { - va_list ParamList; - - va_start(ParamList, s); - _VPrintTarget(s, SEGGER_SYSVIEW_LOG, &ParamList); - va_end(ParamList); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_VPrintfTarget() -* -* Function description -* Print a string which is formatted on the target before sent to -* the host. -* -* Parameters -* s - String to be formatted. -* pParamList - Pointer to the list of arguments for the format string -*/ -void SEGGER_SYSVIEW_VPrintfTarget(const char* s, va_list* pParamList) { - _VPrintTarget(s, SEGGER_SYSVIEW_LOG, pParamList); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_WarnfTarget() -* -* Function description -* Print a warning string which is formatted on the target before -* sent to the host. -* -* Parameters -* s - String to be formatted. -*/ -void SEGGER_SYSVIEW_WarnfTarget(const char* s, ...) { - va_list ParamList; - - va_start(ParamList, s); - _VPrintTarget(s, SEGGER_SYSVIEW_WARNING, &ParamList); - va_end(ParamList); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_VWarnfTarget() -* -* Function description -* Print a warning string which is formatted on the target before -* sent to the host. -* -* Parameters -* s - String to be formatted. -* pParamList - Pointer to the list of arguments for the format string -*/ -void SEGGER_SYSVIEW_VWarnfTarget(const char* s, va_list* pParamList) { - _VPrintTarget(s, SEGGER_SYSVIEW_WARNING, pParamList); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_ErrorfTarget() -* -* Function description -* Print an error string which is formatted on the target before -* sent to the host. -* -* Parameters -* s - String to be formatted. -*/ -void SEGGER_SYSVIEW_ErrorfTarget(const char* s, ...) { - va_list ParamList; - - va_start(ParamList, s); - _VPrintTarget(s, SEGGER_SYSVIEW_ERROR, &ParamList); - va_end(ParamList); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_VErrorfTarget() -* -* Function description -* Print an error string which is formatted on the target before -* sent to the host. -* -* Parameters -* s - String to be formatted. -* pParamList - Pointer to the list of arguments for the format string -*/ -void SEGGER_SYSVIEW_VErrorfTarget(const char* s, va_list* pParamList) { - _VPrintTarget(s, SEGGER_SYSVIEW_ERROR, pParamList); -} -#endif // SEGGER_SYSVIEW_EXCLUDE_PRINTF - -/********************************************************************* -* -* SEGGER_SYSVIEW_Print() -* -* Function description -* Print a string to the host. -* -* Parameters -* s - String to sent. -*/ -void SEGGER_SYSVIEW_Print(const char* s) { - U8* pPayload; - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + 2 * SEGGER_SYSVIEW_QUANTA_U32 + SEGGER_SYSVIEW_MAX_STRING_LEN); - // - pPayload = _EncodeStr(pPayloadStart, s, SEGGER_SYSVIEW_MAX_STRING_LEN); - ENCODE_U32(pPayload, SEGGER_SYSVIEW_LOG); - ENCODE_U32(pPayload, 0); - _SendPacket(pPayloadStart, pPayload, SYSVIEW_EVTID_PRINT_FORMATTED); - RECORD_END(); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_Warn() -* -* Function description -* Print a warning string to the host. -* -* Parameters -* s - String to sent. -*/ -void SEGGER_SYSVIEW_Warn(const char* s) { - U8* pPayload; - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + 2 * SEGGER_SYSVIEW_QUANTA_U32 + SEGGER_SYSVIEW_MAX_STRING_LEN); - // - pPayload = _EncodeStr(pPayloadStart, s, SEGGER_SYSVIEW_MAX_STRING_LEN); - ENCODE_U32(pPayload, SEGGER_SYSVIEW_WARNING); - ENCODE_U32(pPayload, 0); - _SendPacket(pPayloadStart, pPayload, SYSVIEW_EVTID_PRINT_FORMATTED); - RECORD_END(); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_Error() -* -* Function description -* Print an error string to the host. -* -* Parameters -* s - String to sent. -*/ -void SEGGER_SYSVIEW_Error(const char* s) { - U8* pPayload; - U8* pPayloadStart; - RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + 2 * SEGGER_SYSVIEW_QUANTA_U32 + SEGGER_SYSVIEW_MAX_STRING_LEN); - // - pPayload = _EncodeStr(pPayloadStart, s, SEGGER_SYSVIEW_MAX_STRING_LEN); - ENCODE_U32(pPayload, SEGGER_SYSVIEW_ERROR); - ENCODE_U32(pPayload, 0); - _SendPacket(pPayloadStart, pPayload, SYSVIEW_EVTID_PRINT_FORMATTED); - RECORD_END(); -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_EnableEvents() -* -* Function description -* Enable standard SystemView events to be generated. -* -* Parameters -* EnableMask - Events to be enabled. -*/ -void SEGGER_SYSVIEW_EnableEvents(U32 EnableMask) { - _SYSVIEW_Globals.DisabledEvents &= ~EnableMask; -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_DisableEvents() -* -* Function description -* Disable standard SystemView events to not be generated. -* -* Parameters -* DisableMask - Events to be disabled. -*/ -void SEGGER_SYSVIEW_DisableEvents(U32 DisableMask) { - _SYSVIEW_Globals.DisabledEvents |= DisableMask; -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_IsStarted() -* -* Function description -* Handle incoming packets if any and check if recording is started. -* -* Return value -* 0: Recording not started. -* > 0: Recording started. -*/ -int SEGGER_SYSVIEW_IsStarted(void) { -#if (SEGGER_SYSVIEW_POST_MORTEM_MODE != 1) - // - // Check if host is sending data which needs to be processed. - // - if (SEGGER_RTT_HASDATA(CHANNEL_ID_DOWN)) { - if (_SYSVIEW_Globals.RecursionCnt == 0) { // Avoid uncontrolled nesting. This way, this routine can call itself once, but no more often than that. - _SYSVIEW_Globals.RecursionCnt = 1; - _HandleIncomingPacket(); - _SYSVIEW_Globals.RecursionCnt = 0; - } - } -#endif - return _SYSVIEW_Globals.EnableState; -} - - -/*************************** End of file ****************************/ diff --git a/components/app_trace/sys_view/SEGGER/SEGGER_SYSVIEW.h b/components/app_trace/sys_view/SEGGER/SEGGER_SYSVIEW.h deleted file mode 100644 index 1ada68c6fc8..00000000000 --- a/components/app_trace/sys_view/SEGGER/SEGGER_SYSVIEW.h +++ /dev/null @@ -1,436 +0,0 @@ -/* - * SPDX-FileCopyrightText: 1995-2021 SEGGER Microcontroller GmbH - * - * SPDX-License-Identifier: BSD-1-Clause - * - * SPDX-FileContributor: 2023-2024 Espressif Systems (Shanghai) CO LTD - */ -/********************************************************************* -* SEGGER Microcontroller GmbH * -* The Embedded Experts * -********************************************************************** -* * -* (c) 1995 - 2024 SEGGER Microcontroller GmbH * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER SystemView * Real-time application analysis * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* SEGGER strongly recommends to not make any changes * -* to or modify the source code of this software in order to stay * -* compatible with the SystemView and RTT protocol, and J-Link. * -* * -* Redistribution and use in source and binary forms, with or * -* without modification, are permitted provided that the following * -* condition is met: * -* * -* o Redistributions of source code must retain the above copyright * -* notice, this condition and the following disclaimer. * -* * -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * -* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * -* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * -* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * -* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * -* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * -* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * -* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * -* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * -* DAMAGE. * -* * -********************************************************************** -* * -* SystemView version: 3.56 * -* * -********************************************************************** --------------------------- END-OF-HEADER ----------------------------- -File : SEGGER_SYSVIEW.h -Purpose : System visualization API. -Revision: $Rev: 28768 $ -*/ - -#ifndef SEGGER_SYSVIEW_H -#define SEGGER_SYSVIEW_H - -/********************************************************************* -* -* #include Section -* -********************************************************************** -*/ - -#include "SEGGER.h" -#include "SEGGER_SYSVIEW_ConfDefaults.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -/********************************************************************* -* -* Defines, fixed -* -********************************************************************** -*/ - -#define SEGGER_SYSVIEW_MAJOR 3 -#define SEGGER_SYSVIEW_MINOR 32 -#define SEGGER_SYSVIEW_REV 0 -#define SEGGER_SYSVIEW_VERSION ((SEGGER_SYSVIEW_MAJOR * 10000) + (SEGGER_SYSVIEW_MINOR * 100) + SEGGER_SYSVIEW_REV) - -#define SEGGER_SYSVIEW_INFO_SIZE 9 // Minimum size, which has to be reserved for a packet. 1-2 byte of message type, 0-2 byte of payload length, 1-5 bytes of timestamp. -#define SEGGER_SYSVIEW_QUANTA_U32 5 // Maximum number of bytes to encode a U32, should be reserved for each 32-bit value in a packet. - -#define SEGGER_SYSVIEW_LOG (0u) -#define SEGGER_SYSVIEW_WARNING (1u) -#define SEGGER_SYSVIEW_ERROR (2u) -#define SEGGER_SYSVIEW_FLAG_APPEND (1u << 6) - -#define SEGGER_SYSVIEW_PREPARE_PACKET(p) (p) + 4 -// -// SystemView events. First 32 IDs from 0 .. 31 are reserved for these -// -#define SYSVIEW_EVTID_NOP 0 // Dummy packet. -#define SYSVIEW_EVTID_OVERFLOW 1 -#define SYSVIEW_EVTID_ISR_ENTER 2 -#define SYSVIEW_EVTID_ISR_EXIT 3 -#define SYSVIEW_EVTID_TASK_START_EXEC 4 -#define SYSVIEW_EVTID_TASK_STOP_EXEC 5 -#define SYSVIEW_EVTID_TASK_START_READY 6 -#define SYSVIEW_EVTID_TASK_STOP_READY 7 -#define SYSVIEW_EVTID_TASK_CREATE 8 -#define SYSVIEW_EVTID_TASK_INFO 9 -#define SYSVIEW_EVTID_TRACE_START 10 -#define SYSVIEW_EVTID_TRACE_STOP 11 -#define SYSVIEW_EVTID_SYSTIME_CYCLES 12 -#define SYSVIEW_EVTID_SYSTIME_US 13 -#define SYSVIEW_EVTID_SYSDESC 14 -#define SYSVIEW_EVTID_MARK_START 15 -#define SYSVIEW_EVTID_MARK_STOP 16 -#define SYSVIEW_EVTID_IDLE 17 -#define SYSVIEW_EVTID_ISR_TO_SCHEDULER 18 -#define SYSVIEW_EVTID_TIMER_ENTER 19 -#define SYSVIEW_EVTID_TIMER_EXIT 20 -#define SYSVIEW_EVTID_STACK_INFO 21 -#define SYSVIEW_EVTID_MODULEDESC 22 -#define SYSVIEW_EVTID_DATA_SAMPLE 23 -#define SYSVIEW_EVTID_INIT 24 -#define SYSVIEW_EVTID_NAME_RESOURCE 25 -#define SYSVIEW_EVTID_PRINT_FORMATTED 26 -#define SYSVIEW_EVTID_NUMMODULES 27 -#define SYSVIEW_EVTID_END_CALL 28 -#define SYSVIEW_EVTID_TASK_TERMINATE 29 - -#define SYSVIEW_EVTID_EX 31 -// -// SystemView extended events. Sent with ID 31. -// -#define SYSVIEW_EVTID_EX_MARK 0 -#define SYSVIEW_EVTID_EX_NAME_MARKER 1 -#define SYSVIEW_EVTID_EX_HEAP_DEFINE 2 -#define SYSVIEW_EVTID_EX_HEAP_ALLOC 3 -#define SYSVIEW_EVTID_EX_HEAP_ALLOC_EX 4 -#define SYSVIEW_EVTID_EX_HEAP_FREE 5 -#define SYSVIEW_EVTID_EX_REGISTER_DATA 6 -// -// Event masks to disable/enable events -// -#define SYSVIEW_EVTMASK_NOP (1 << SYSVIEW_EVTID_NOP) -#define SYSVIEW_EVTMASK_OVERFLOW (1 << SYSVIEW_EVTID_OVERFLOW) -#define SYSVIEW_EVTMASK_ISR_ENTER (1 << SYSVIEW_EVTID_ISR_ENTER) -#define SYSVIEW_EVTMASK_ISR_EXIT (1 << SYSVIEW_EVTID_ISR_EXIT) -#define SYSVIEW_EVTMASK_TASK_START_EXEC (1 << SYSVIEW_EVTID_TASK_START_EXEC) -#define SYSVIEW_EVTMASK_TASK_STOP_EXEC (1 << SYSVIEW_EVTID_TASK_STOP_EXEC) -#define SYSVIEW_EVTMASK_TASK_START_READY (1 << SYSVIEW_EVTID_TASK_START_READY) -#define SYSVIEW_EVTMASK_TASK_STOP_READY (1 << SYSVIEW_EVTID_TASK_STOP_READY) -#define SYSVIEW_EVTMASK_TASK_CREATE (1 << SYSVIEW_EVTID_TASK_CREATE) -#define SYSVIEW_EVTMASK_TASK_INFO (1 << SYSVIEW_EVTID_TASK_INFO) -#define SYSVIEW_EVTMASK_TRACE_START (1 << SYSVIEW_EVTID_TRACE_START) -#define SYSVIEW_EVTMASK_TRACE_STOP (1 << SYSVIEW_EVTID_TRACE_STOP) -#define SYSVIEW_EVTMASK_SYSTIME_CYCLES (1 << SYSVIEW_EVTID_SYSTIME_CYCLES) -#define SYSVIEW_EVTMASK_SYSTIME_US (1 << SYSVIEW_EVTID_SYSTIME_US) -#define SYSVIEW_EVTMASK_SYSDESC (1 << SYSVIEW_EVTID_SYSDESC) -#define SYSVIEW_EVTMASK_USER_START (1 << SYSVIEW_EVTID_USER_START) -#define SYSVIEW_EVTMASK_USER_STOP (1 << SYSVIEW_EVTID_USER_STOP) -#define SYSVIEW_EVTMASK_IDLE (1 << SYSVIEW_EVTID_IDLE) -#define SYSVIEW_EVTMASK_ISR_TO_SCHEDULER (1 << SYSVIEW_EVTID_ISR_TO_SCHEDULER) -#define SYSVIEW_EVTMASK_TIMER_ENTER (1 << SYSVIEW_EVTID_TIMER_ENTER) -#define SYSVIEW_EVTMASK_TIMER_EXIT (1 << SYSVIEW_EVTID_TIMER_EXIT) -#define SYSVIEW_EVTMASK_STACK_INFO (1 << SYSVIEW_EVTID_STACK_INFO) -#define SYSVIEW_EVTMASK_MODULEDESC (1 << SYSVIEW_EVTID_MODULEDESC) -#define SYSVIEW_EVTMASK_DATA_SAMPLE (1 << SYSVIEW_EVTID_DATA_SAMPLE) -#define SYSVIEW_EVTMASK_INIT (1 << SYSVIEW_EVTID_INIT) -#define SYSVIEW_EVTMASK_NAME_RESOURCE (1 << SYSVIEW_EVTID_NAME_RESOURCE) -#define SYSVIEW_EVTMASK_PRINT_FORMATTED (1 << SYSVIEW_EVTID_PRINT_FORMATTED) -#define SYSVIEW_EVTMASK_NUMMODULES (1 << SYSVIEW_EVTID_NUMMODULES) -#define SYSVIEW_EVTMASK_END_CALL (1 << SYSVIEW_EVTID_END_CALL) -#define SYSVIEW_EVTMASK_TASK_TERMINATE (1 << SYSVIEW_EVTID_TASK_TERMINATE) - -#define SYSVIEW_EVTMASK_EX (1 << SYSVIEW_EVTID_EX) - -#define SYSVIEW_EVTMASK_ALL_INTERRUPTS ( SYSVIEW_EVTMASK_ISR_ENTER \ - | SYSVIEW_EVTMASK_ISR_EXIT \ - | SYSVIEW_EVTMASK_ISR_TO_SCHEDULER) -#define SYSVIEW_EVTMASK_ALL_TASKS ( SYSVIEW_EVTMASK_TASK_START_EXEC \ - | SYSVIEW_EVTMASK_TASK_STOP_EXEC \ - | SYSVIEW_EVTMASK_TASK_START_READY \ - | SYSVIEW_EVTMASK_TASK_STOP_READY \ - | SYSVIEW_EVTMASK_TASK_CREATE \ - | SYSVIEW_EVTMASK_TASK_INFO \ - | SYSVIEW_EVTMASK_STACK_INFO \ - | SYSVIEW_EVTMASK_TASK_TERMINATE) - -/********************************************************************* -* -* Structures -* -********************************************************************** -*/ - -typedef struct { - U32 TaskID; - const char* sName; - U32 Prio; - U32 StackBase; - U32 StackSize; - U32 StackUsage; -} SEGGER_SYSVIEW_TASKINFO; - -typedef struct { - U32 TaskID; - U32 StackBase; - U32 StackSize; - U32 StackUsage; -} SEGGER_SYSVIEW_STACKINFO; - -typedef struct { - U32 ID; - union { - U32* pU32_Value; - I32* pI32_Value; - float* pFloat_Value; - }; -} SEGGER_SYSVIEW_DATA_SAMPLE; - -typedef enum { - SEGGER_SYSVIEW_TYPE_U32 = 0, - SEGGER_SYSVIEW_TYPE_I32 = 1, - SEGGER_SYSVIEW_TYPE_FLOAT = 2 -} SEGGER_SYSVIEW_DATA_TYPE; - -typedef struct { - U32 ID; - SEGGER_SYSVIEW_DATA_TYPE DataType; - I32 Offset; - I32 RangeMin; - I32 RangeMax; - float ScalingFactor; - const char* sName; - const char* sUnit; -} SEGGER_SYSVIEW_DATA_REGISTER; - -typedef struct SEGGER_SYSVIEW_MODULE_STRUCT SEGGER_SYSVIEW_MODULE; - -struct SEGGER_SYSVIEW_MODULE_STRUCT { - const char* sModule; - U32 NumEvents; - U32 EventOffset; - void (*pfSendModuleDesc)(void); - SEGGER_SYSVIEW_MODULE* pNext; -}; - -typedef void (SEGGER_SYSVIEW_SEND_SYS_DESC_FUNC)(void); - - -/********************************************************************* -* -* Global data -* -********************************************************************** -*/ - -#ifdef EXTERN - #undef EXTERN -#endif - -#ifndef SEGGER_SYSVIEW_C // Defined in SEGGER_SYSVIEW.c which includes this header beside other C-files - #define EXTERN extern -#else - #define EXTERN -#endif - -EXTERN unsigned int SEGGER_SYSVIEW_TickCnt; -EXTERN unsigned int SEGGER_SYSVIEW_InterruptId; - -#undef EXTERN - -/********************************************************************* -* -* API functions -* -********************************************************************** -*/ - -typedef struct { - U64 (*pfGetTime) (void); - void (*pfSendTaskList) (void); -} SEGGER_SYSVIEW_OS_API; - -/********************************************************************* -* -* Control and initialization functions -*/ -void SEGGER_SYSVIEW_Init (U32 SysFreq, U32 CPUFreq, const SEGGER_SYSVIEW_OS_API *pOSAPI, SEGGER_SYSVIEW_SEND_SYS_DESC_FUNC pfSendSysDesc); -void SEGGER_SYSVIEW_SetRAMBase (U32 RAMBaseAddress); -void SEGGER_SYSVIEW_Start (void); -void SEGGER_SYSVIEW_Stop (void); -void SEGGER_SYSVIEW_GetSysDesc (void); -void SEGGER_SYSVIEW_SendTaskList (void); -void SEGGER_SYSVIEW_SendTaskInfo (const SEGGER_SYSVIEW_TASKINFO* pInfo); -void SEGGER_SYSVIEW_SendStackInfo (const SEGGER_SYSVIEW_STACKINFO* pInfo); -void SEGGER_SYSVIEW_SendSysDesc (const char* sSysDesc); -int SEGGER_SYSVIEW_IsStarted (void); -int SEGGER_SYSVIEW_GetChannelID (void); - -void SEGGER_SYSVIEW_SampleData (const SEGGER_SYSVIEW_DATA_SAMPLE *pInfo); - -// Checks whether tracing has been started -U8 SEGGER_SYSVIEW_Started(void); - -/********************************************************************* -* -* Event recording functions -*/ -void SEGGER_SYSVIEW_RecordVoid (unsigned int EventId); -void SEGGER_SYSVIEW_RecordU32 (unsigned int EventId, U32 Para0); -void SEGGER_SYSVIEW_RecordU32x2 (unsigned int EventId, U32 Para0, U32 Para1); -void SEGGER_SYSVIEW_RecordU32x3 (unsigned int EventId, U32 Para0, U32 Para1, U32 Para2); -void SEGGER_SYSVIEW_RecordU32x4 (unsigned int EventId, U32 Para0, U32 Para1, U32 Para2, U32 Para3); -void SEGGER_SYSVIEW_RecordU32x5 (unsigned int EventId, U32 Para0, U32 Para1, U32 Para2, U32 Para3, U32 Para4); -void SEGGER_SYSVIEW_RecordU32x6 (unsigned int EventId, U32 Para0, U32 Para1, U32 Para2, U32 Para3, U32 Para4, U32 Para5); -void SEGGER_SYSVIEW_RecordU32x7 (unsigned int EventId, U32 Para0, U32 Para1, U32 Para2, U32 Para3, U32 Para4, U32 Para5, U32 Para6); -void SEGGER_SYSVIEW_RecordU32x8 (unsigned int EventId, U32 Para0, U32 Para1, U32 Para2, U32 Para3, U32 Para4, U32 Para5, U32 Para6, U32 Para7); -void SEGGER_SYSVIEW_RecordU32x9 (unsigned int EventId, U32 Para0, U32 Para1, U32 Para2, U32 Para3, U32 Para4, U32 Para5, U32 Para6, U32 Para7, U32 Para8); -void SEGGER_SYSVIEW_RecordU32x10 (unsigned int EventId, U32 Para0, U32 Para1, U32 Para2, U32 Para3, U32 Para4, U32 Para5, U32 Para6, U32 Para7, U32 Para8, U32 Para9); -void SEGGER_SYSVIEW_RecordString (unsigned int EventId, const char* pString); -void SEGGER_SYSVIEW_RecordSystime (void); -void SEGGER_SYSVIEW_RecordEnterISR (U32 IrqId); -void SEGGER_SYSVIEW_RecordExitISR (void); -void SEGGER_SYSVIEW_RecordExitISRToScheduler (void); -void SEGGER_SYSVIEW_RecordEnterTimer (U32 TimerId); -void SEGGER_SYSVIEW_RecordExitTimer (void); -void SEGGER_SYSVIEW_RecordEndCall (unsigned int EventID); -void SEGGER_SYSVIEW_RecordEndCallU32 (unsigned int EventID, U32 Para0); - -void SEGGER_SYSVIEW_OnIdle (void); -void SEGGER_SYSVIEW_OnTaskCreate (U32 TaskId); -void SEGGER_SYSVIEW_OnTaskTerminate (U32 TaskId); -void SEGGER_SYSVIEW_OnTaskStartExec (U32 TaskId); -void SEGGER_SYSVIEW_OnTaskStopExec (void); -void SEGGER_SYSVIEW_OnTaskStartReady (U32 TaskId); -void SEGGER_SYSVIEW_OnTaskStopReady (U32 TaskId, unsigned int Cause); -void SEGGER_SYSVIEW_MarkStart (unsigned int MarkerId); -void SEGGER_SYSVIEW_MarkStop (unsigned int MarkerId); -void SEGGER_SYSVIEW_Mark (unsigned int MarkerId); -void SEGGER_SYSVIEW_NameMarker (unsigned int MarkerId, const char* sName); - -void SEGGER_SYSVIEW_HeapDefine (void* pHeap, void* pBase, unsigned int HeapSize, unsigned int MetadataSize); -void SEGGER_SYSVIEW_HeapAlloc (void* pHeap, void* pUserData, unsigned int UserDataLen); -void SEGGER_SYSVIEW_HeapAllocEx (void* pHeap, void* pUserData, unsigned int UserDataLen, unsigned int Tag); -void SEGGER_SYSVIEW_HeapFree (void* pHeap, void* pUserData); - -void SEGGER_SYSVIEW_NameResource (U32 ResourceId, const char* sName); -void SEGGER_SYSVIEW_RegisterData ( SEGGER_SYSVIEW_DATA_REGISTER* pInfo); - -int SEGGER_SYSVIEW_SendPacket (U8* pPacket, U8* pPayloadEnd, unsigned int EventId); - -/********************************************************************* -* -* Event parameter encoding functions -*/ -U8* SEGGER_SYSVIEW_EncodeU32 (U8* pPayload, U32 Value); -U8* SEGGER_SYSVIEW_EncodeData (U8* pPayload, const char* pSrc, unsigned int Len); -U8* SEGGER_SYSVIEW_EncodeString (U8* pPayload, const char* s, unsigned int MaxLen); -U8* SEGGER_SYSVIEW_EncodeId (U8* pPayload, U32 Id); -U32 SEGGER_SYSVIEW_ShrinkId (U32 Id); - - -/********************************************************************* -* -* Middleware module registration -*/ -void SEGGER_SYSVIEW_RegisterModule (SEGGER_SYSVIEW_MODULE* pModule); -void SEGGER_SYSVIEW_RecordModuleDescription (const SEGGER_SYSVIEW_MODULE* pModule, const char* sDescription); -void SEGGER_SYSVIEW_SendModule (U8 ModuleId); -void SEGGER_SYSVIEW_SendModuleDescription (void); -void SEGGER_SYSVIEW_SendNumModules (void); - -/********************************************************************* -* -* printf-Style functions -*/ -#ifndef SEGGER_SYSVIEW_EXCLUDE_PRINTF // Define in project to avoid warnings about variable parameter list -void SEGGER_SYSVIEW_PrintfHostEx (const char* s, U32 Options, ...); -void SEGGER_SYSVIEW_VPrintfHostEx (const char* s, U32 Options, va_list* pParamList); -void SEGGER_SYSVIEW_PrintfTargetEx (const char* s, U32 Options, ...); -void SEGGER_SYSVIEW_VPrintfTargetEx (const char* s, U32 Options, va_list* pParamList); -void SEGGER_SYSVIEW_PrintfHost (const char* s, ...); -void SEGGER_SYSVIEW_VPrintfHost (const char* s, va_list* pParamList); -void SEGGER_SYSVIEW_PrintfTarget (const char* s, ...); -void SEGGER_SYSVIEW_VPrintfTarget (const char* s, va_list* pParamList); -void SEGGER_SYSVIEW_WarnfHost (const char* s, ...); -void SEGGER_SYSVIEW_VWarnfHost (const char* s, va_list* pParamList); -void SEGGER_SYSVIEW_WarnfTarget (const char* s, ...); -void SEGGER_SYSVIEW_VWarnfTarget (const char* s, va_list* pParamList); -void SEGGER_SYSVIEW_ErrorfHost (const char* s, ...); -void SEGGER_SYSVIEW_VErrorfHost (const char* s, va_list* pParamList); -void SEGGER_SYSVIEW_ErrorfTarget (const char* s, ...); -void SEGGER_SYSVIEW_VErrorfTarget (const char* s, va_list* pParamList); -#endif - -void SEGGER_SYSVIEW_Print (const char* s); -void SEGGER_SYSVIEW_Warn (const char* s); -void SEGGER_SYSVIEW_Error (const char* s); - -/********************************************************************* -* -* Run-time configuration functions -*/ -void SEGGER_SYSVIEW_EnableEvents (U32 EnableMask); -void SEGGER_SYSVIEW_DisableEvents (U32 DisableMask); - -/********************************************************************* -* -* Application-provided functions -*/ -void SEGGER_SYSVIEW_Conf (void); -U32 SEGGER_SYSVIEW_X_GetTimestamp (void); -U32 SEGGER_SYSVIEW_X_GetInterruptId (void); - -void SEGGER_SYSVIEW_X_StartComm (void); -void SEGGER_SYSVIEW_X_OnEventRecorded (unsigned NumBytes); - -#ifdef __cplusplus -} -#endif - -/********************************************************************* -* -* Compatibility API defines -*/ -#define SEGGER_SYSVIEW_OnUserStart SEGGER_SYSVIEW_MarkStart -#define SEGGER_SYSVIEW_OnUserStop SEGGER_SYSVIEW_MarkStop - -#endif - -/*************************** End of file ****************************/ diff --git a/components/app_trace/sys_view/SEGGER/SEGGER_SYSVIEW_ConfDefaults.h b/components/app_trace/sys_view/SEGGER/SEGGER_SYSVIEW_ConfDefaults.h deleted file mode 100644 index 08efb45ba6a..00000000000 --- a/components/app_trace/sys_view/SEGGER/SEGGER_SYSVIEW_ConfDefaults.h +++ /dev/null @@ -1,592 +0,0 @@ -/* - * SPDX-FileCopyrightText: 1995-2021 SEGGER Microcontroller GmbH - * - * SPDX-License-Identifier: BSD-1-Clause - * - * SPDX-FileContributor: 2023-2024 Espressif Systems (Shanghai) CO LTD - */ -/********************************************************************* -* SEGGER Microcontroller GmbH * -* The Embedded Experts * -********************************************************************** -* * -* (c) 1995 - 2024 SEGGER Microcontroller GmbH * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER SystemView * Real-time application analysis * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* SEGGER strongly recommends to not make any changes * -* to or modify the source code of this software in order to stay * -* compatible with the SystemView and RTT protocol, and J-Link. * -* * -* Redistribution and use in source and binary forms, with or * -* without modification, are permitted provided that the following * -* condition is met: * -* * -* o Redistributions of source code must retain the above copyright * -* notice, this condition and the following disclaimer. * -* * -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * -* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * -* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * -* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * -* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * -* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * -* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * -* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * -* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * -* DAMAGE. * -* * -********************************************************************** -* * -* SystemView version: 3.56 * -* * -********************************************************************** --------------------------- END-OF-HEADER ----------------------------- -File : SEGGER_SYSVIEW_ConfDefaults.h -Purpose : Defines defaults for configurable defines used in - SEGGER SystemView. -Revision: $Rev: 26230 $ -*/ - -#ifndef SEGGER_SYSVIEW_CONFDEFAULTS_H -#define SEGGER_SYSVIEW_CONFDEFAULTS_H - -/********************************************************************* -* -* #include Section -* -********************************************************************** -*/ - -#include "SEGGER_SYSVIEW_Conf.h" -#include "SEGGER_RTT_Conf.h" - -#include "esp_assert.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/********************************************************************* -* -* Defines, fixed -* -********************************************************************** -*/ -// -// Use auto-detection for SEGGER_SYSVIEW_CORE define -// based on compiler-/toolchain-specific defines -// to define SEGGER_SYSVIEW_GET_INTERRUPT_ID and SEGGER_SYSVIEW_GET_TIMESTAMP -// -#define SEGGER_SYSVIEW_CORE_OTHER 0 -#define SEGGER_SYSVIEW_CORE_CM0 1 // Cortex-M0/M0+/M1 -#define SEGGER_SYSVIEW_CORE_CM3 2 // Cortex-M3/M4/M7 -#define SEGGER_SYSVIEW_CORE_RX 3 // Renesas RX -#ifndef SEGGER_SYSVIEW_CORE - #if (defined __SES_ARM) || (defined __CROSSWORKS_ARM) || (defined __SEGGER_CC__) || (defined __GNUC__) || (defined __clang__) - #if (defined __ARM_ARCH_6M__) || (defined __ARM_ARCH_8M_BASE__) - #define SEGGER_SYSVIEW_CORE SEGGER_SYSVIEW_CORE_CM0 - #elif (defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_8M_MAIN__)) - #define SEGGER_SYSVIEW_CORE SEGGER_SYSVIEW_CORE_CM3 - #endif - #elif defined(__ICCARM__) - #if (defined (__ARM6M__) && (__CORE__ == __ARM6M__)) \ - || (defined (__ARM8M_BASELINE__) && (__CORE__ == __ARM8M_BASELINE__)) - #define SEGGER_SYSVIEW_CORE SEGGER_SYSVIEW_CORE_CM0 - #elif (defined (__ARM7EM__) && (__CORE__ == __ARM7EM__)) \ - || (defined (__ARM7M__) && (__CORE__ == __ARM7M__)) \ - || (defined (__ARM8M_MAINLINE__) && (__CORE__ == __ARM8M_MAINLINE__)) \ - || (defined (__ARM8M_MAINLINE__) && (__CORE__ == __ARM8M_MAINLINE__)) - #define SEGGER_SYSVIEW_CORE SEGGER_SYSVIEW_CORE_CM3 - #endif - #elif defined(__CC_ARM) - #if (defined(__TARGET_ARCH_6S_M)) - #define SEGGER_SYSVIEW_CORE SEGGER_SYSVIEW_CORE_CM0 - #elif (defined(__TARGET_ARCH_7_M) || defined(__TARGET_ARCH_7E_M)) - #define SEGGER_SYSVIEW_CORE SEGGER_SYSVIEW_CORE_CM3 - #endif - #elif defined(__TI_ARM__) - #ifdef __TI_ARM_V6M0__ - #define SEGGER_SYSVIEW_CORE SEGGER_SYSVIEW_CORE_CM0 - #elif (defined(__TI_ARM_V7M3__) || defined(__TI_ARM_V7M4__)) - #define SEGGER_SYSVIEW_CORE SEGGER_SYSVIEW_CORE_CM3 - #endif - #elif defined(__ICCRX__) - #define SEGGER_SYSVIEW_CORE SEGGER_SYSVIEW_CORE_RX - #elif defined(__RX) - #define SEGGER_SYSVIEW_CORE SEGGER_SYSVIEW_CORE_RX - #endif - - #ifndef SEGGER_SYSVIEW_CORE - #define SEGGER_SYSVIEW_CORE SEGGER_SYSVIEW_CORE_OTHER - #endif -#endif - - -/********************************************************************* -* -* Defines, defaults -* -********************************************************************** -*/ -/********************************************************************* -* -* Define: SEGGER_SYSVIEW_APP_NAME -* -* Description -* The application name to be displayed in SystemView. -* Default -* "SystemView-enabled Application" -* Notes -* Convenience define to be used for SEGGER_SYSVIEW_SendSysDesc(). -*/ -#ifndef SEGGER_SYSVIEW_APP_NAME - #define SEGGER_SYSVIEW_APP_NAME "SystemView-enabled Application" -#endif - -/********************************************************************* -* -* Define: SEGGER_SYSVIEW_DEVICE_NAME -* -* Description -* The target device name to be displayed in SystemView. -* Default -* "undefined device" -* Notes -* Convenience define to be used for SEGGER_SYSVIEW_SendSysDesc(). -*/ -#ifndef SEGGER_SYSVIEW_DEVICE_NAME - #define SEGGER_SYSVIEW_DEVICE_NAME "undefined device" -#endif - -/********************************************************************* -* -* Define: SEGGER_SYSVIEW_GET_INTERRUPT_ID() -* -* Description -* Function macro to retrieve the Id of the currently active -* interrupt. -* Default -* Call user-supplied function SEGGER_SYSVIEW_X_GetInterruptId(). -* Notes -* For some known compilers and cores, a ready-to-use, core-specific -* default is set. -* ARMv7M: Read ICSR[8:0] (active vector) -* ARMv6M: Read ICSR[5:0] (active vector) -*/ -#ifndef SEGGER_SYSVIEW_GET_INTERRUPT_ID - #if SEGGER_SYSVIEW_CORE == SEGGER_SYSVIEW_CORE_CM3 - #define SEGGER_SYSVIEW_GET_INTERRUPT_ID() ((*(U32*)(0xE000ED04)) & 0x1FF) // Get the currently active interrupt Id. (i.e. read Cortex-M ICSR[8:0] = active vector) - #elif SEGGER_SYSVIEW_CORE == SEGGER_SYSVIEW_CORE_CM0 - #if defined(__ICCARM__) - #if (__VER__ > 6010000) - #define SEGGER_SYSVIEW_GET_INTERRUPT_ID() (__get_IPSR()) // Workaround for IAR, which might do a byte-access to 0xE000ED04. Read IPSR instead. - #else - #define SEGGER_SYSVIEW_GET_INTERRUPT_ID() ((*(U32*)(0xE000ED04)) & 0x3F) // Older versions of IAR do not include __get_IPSR, but might also not optimize to byte-access. - #endif - #else - #define SEGGER_SYSVIEW_GET_INTERRUPT_ID() ((*(U32*)(0xE000ED04)) & 0x3F) // Get the currently active interrupt Id. (i.e. read Cortex-M ICSR[5:0] = active vector) - #endif - #else - #define SEGGER_SYSVIEW_GET_INTERRUPT_ID() SEGGER_SYSVIEW_X_GetInterruptId() // Get the currently active interrupt Id from the user-provided function. - #endif -#endif - -/********************************************************************* -* -* Define: SEGGER_SYSVIEW_GET_TIMESTAMP() -* -* Description -* Function macro to retrieve a system timestamp for SYSVIEW events. -* Default -* Call user-supplied function SEGGER_SYSVIEW_X_GetTimestamp(). -* Notes -* For some known compilers and cores, a ready-to-use, core-specific -* default is set. -* ARMv7M: Read Cortex-M Cycle Count register. -* -* The system timestamp clock frequency has to be passed in -* SEGGER_SYSVIEW_Init(). -*/ -#ifndef SEGGER_SYSVIEW_GET_TIMESTAMP - #if defined (SEGGER_SYSVIEW_CORE) && (SEGGER_SYSVIEW_CORE == SEGGER_SYSVIEW_CORE_CM3) - #define SEGGER_SYSVIEW_GET_TIMESTAMP() (*(U32 *)(0xE0001004)) // Retrieve a system timestamp. Cortex-M cycle counter. - #else - #define SEGGER_SYSVIEW_GET_TIMESTAMP() SEGGER_SYSVIEW_X_GetTimestamp() // Retrieve a system timestamp via user-defined function - #endif -#endif - -/********************************************************************* -* -* Define: SEGGER_SYSVIEW_TIMESTAMP_BITS -* -* Description -* Number of valid (low-order) bits delivered in system timestamp. -* Default -* 32 -* Notes -* Value has to match system timestamp clock source. -*/ -// Define number of valid bits low-order delivered by clock source. -#ifndef SEGGER_SYSVIEW_TIMESTAMP_BITS - #define SEGGER_SYSVIEW_TIMESTAMP_BITS 32 -#endif - -/********************************************************************* -* -* Define: SEGGER_SYSVIEW_RTT_CHANNEL -* -* Description -* The RTT channel that SystemView will use. -* Default -* 0: Auto selection. -* Notes -* Value has to be lower than SEGGER_RTT_MAX_NUM_UP_BUFFERS. -*/ -#ifndef SEGGER_SYSVIEW_RTT_CHANNEL - #define SEGGER_SYSVIEW_RTT_CHANNEL 1 -#endif -// Sanity check of RTT channel -#if (SEGGER_SYSVIEW_RTT_CHANNEL == 0) && (SEGGER_RTT_MAX_NUM_UP_BUFFERS < 2) - #error "SEGGER_RTT_MAX_NUM_UP_BUFFERS in SEGGER_RTT_Conf.h has to be > 1!" -#elif (SEGGER_SYSVIEW_RTT_CHANNEL >= SEGGER_RTT_MAX_NUM_UP_BUFFERS) - #error "SEGGER_RTT_MAX_NUM_UP_BUFFERS in SEGGER_RTT_Conf.h has to be > SEGGER_SYSVIEW_RTT_CHANNEL!" -#endif - -/********************************************************************* -* -* Define: SEGGER_SYSVIEW_RTT_BUFFER_SIZE -* -* Description -* Number of bytes that SystemView uses for the RTT buffer. -* Default -* 1024 -*/ -#ifndef SEGGER_SYSVIEW_RTT_BUFFER_SIZE - #define SEGGER_SYSVIEW_RTT_BUFFER_SIZE 1024 -#endif - -/********************************************************************* -* -* Define: SEGGER_SYSVIEW_SECTION -* -* Description -* Section to place the SystemView RTT Buffer into. -* Default -* undefined: Do not place into a specific section. -* Notes -* If SEGGER_RTT_SECTION is defined, the default changes to use -* this section for the SystemView RTT Buffer, too. -*/ -#if !(defined SEGGER_SYSVIEW_SECTION) && (defined SEGGER_RTT_SECTION) - #define SEGGER_SYSVIEW_SECTION SEGGER_RTT_SECTION -#endif - -/********************************************************************* -* -* Define: SEGGER_SYSVIEW_CPU_CACHE_LINE_SIZE -* -* Description -* Largest cache line size (in bytes) in the target system. -* Default -* 0 -* Notes -* Required in systems with caches to make sure that the SystemView -* RTT buffer can be aligned accordingly. -*/ -#ifndef SEGGER_SYSVIEW_CPU_CACHE_LINE_SIZE - #define SEGGER_SYSVIEW_CPU_CACHE_LINE_SIZE 0 -#endif - -/********************************************************************* -* -* Define: SEGGER_SYSVIEW_ID_BASE -* -* Description -* Lowest Id reported by the application. -* Default -* 0 -* Notes -* Value is usually subtracted from mailboxes, semaphores, tasks, -* .... addresses, to compress event parameters. -* Should be the lowest RAM address of the system. -*/ -#ifndef SEGGER_SYSVIEW_ID_BASE - #define SEGGER_SYSVIEW_ID_BASE 0 -#endif - -/********************************************************************* -* -* Define: SEGGER_SYSVIEW_ID_SHIFT -* -* Description -* Number of bits to shift Ids. -* Default -* 0 -* Notes -* Ids are shifted to compress event parameters. -* Should match the alignment of Ids (addresses), -* e.g. 2 when Ids are 4 byte aligned. -*/ -#ifndef SEGGER_SYSVIEW_ID_SHIFT - #define SEGGER_SYSVIEW_ID_SHIFT 0 -#endif - -/********************************************************************* -* -* Define: SEGGER_SYSVIEW_MAX_ARGUMENTS -* -* Description -* Maximum number of arguments which are handled with SystemView -* print routines or may be encoded in one recording function. -* routines. -* Default -* 16 -*/ -#ifndef SEGGER_SYSVIEW_MAX_ARGUMENTS - #define SEGGER_SYSVIEW_MAX_ARGUMENTS 16 -#endif - -/********************************************************************* -* -* Define: SEGGER_SYSVIEW_MAX_STRING_LEN -* -* Description -* Maximum string length which can be used in SystemView print and -* system description routines. -* Default -* 128 -*/ -#ifndef SEGGER_SYSVIEW_MAX_STRING_LEN - #define SEGGER_SYSVIEW_MAX_STRING_LEN 128 -#endif - -ESP_STATIC_ASSERT(SEGGER_SYSVIEW_MAX_STRING_LEN < 255, "SEGGER Sysview string length must be less than 255."); - -/********************************************************************* -* -* Define: SEGGER_SYSVIEW_SUPPORT_LONG_ID -* -* Description -* It set, support encoding Evend Ids longer than 14 bit. -* Default -* 1 -*/ -#ifndef SEGGER_SYSVIEW_SUPPORT_LONG_ID - #define SEGGER_SYSVIEW_SUPPORT_LONG_ID 1 -#endif - -/********************************************************************* -* -* Define: SEGGER_SYSVIEW_SUPPORT_LONG_DATA -* -* Description -* It set, support encoding event data longer than 14 bit. -* Default -* 0 -*/ -#ifndef SEGGER_SYSVIEW_SUPPORT_LONG_DATA - #define SEGGER_SYSVIEW_SUPPORT_LONG_DATA 0 -#endif - -/********************************************************************* -* -* Define: SEGGER_SYSVIEW_PRINTF_IMPLICIT_FORMAT -* -* Description -* If enabled, on SEGGER_SYSVIEW_PrintHost, check the format string -* and if it includes unsupported formatters, use formatting on the -* target instead. -* Default -* 0: Disabled. -*/ -#ifndef SEGGER_SYSVIEW_PRINTF_IMPLICIT_FORMAT - #define SEGGER_SYSVIEW_PRINTF_IMPLICIT_FORMAT 0 -#endif - -/********************************************************************* -* -* Define: SEGGER_SYSVIEW_USE_INTERNAL_RECORDER -* -* Description -* If set, an internal recorder, such as UART or IP is used. -* Default -* 0: Disabled. -* Notes -* Convenience define to be used by SEGGER_SYSVIEW_Conf(), -* such as in embOS configuration to enable Cortex-M cycle counter. -*/ -#ifndef SEGGER_SYSVIEW_USE_INTERNAL_RECORDER - #define SEGGER_SYSVIEW_USE_INTERNAL_RECORDER 0 -#endif - -/********************************************************************* -* -* Define: SEGGER_SYSVIEW_CAN_RESTART -* -* Description -* If enabled, send the SystemView start sequence on every start -* command, not just on the first one. -* Enables restart when SystemView disconnected unexpectedly. -* Default -* 1: Enabled -*/ -#ifndef SEGGER_SYSVIEW_CAN_RESTART - #define SEGGER_SYSVIEW_CAN_RESTART 1 -#endif - -/********************************************************************* -* -* Define: SEGGER_SYSVIEW_START_ON_INIT -* -* Description -* Enable calling SEGGER_SYSVIEW_Start() after initialization. -* Default -* 0: Disabled. -* Notes -* Convenience define to be used by SEGGER_SYSVIEW_Conf(), -* such as in embOS configuration. -*/ -#ifndef SEGGER_SYSVIEW_START_ON_INIT - #define SEGGER_SYSVIEW_START_ON_INIT 0 -#endif - -/********************************************************************* -* -* Define: SEGGER_SYSVIEW_USE_STATIC_BUFFER -* -* Description -* If enabled, use a static buffer instead of a buffer on the stack -* for SystemView event packets. -* Default -* 1: Enabled. -* Notes -* If enabled, the static memory use by SystemView is increased by -* the maximum packet size. SystemView is locked on entry of a -* recording function. -* If disabled, the stack usage by SystemView recording functions -* might be increased by up to the maximum packet size. SystemView -* is locked when writing the packet to the RTT buffer. -*/ -#ifndef SEGGER_SYSVIEW_USE_STATIC_BUFFER - #define SEGGER_SYSVIEW_USE_STATIC_BUFFER 1 -#endif - -/********************************************************************* -* -* Define: SEGGER_SYSVIEW_MAX_PACKET_SIZE -* -* Description -* Maximum packet size for a SystemView event. -* Default -* Automatically calculated. -* Notes -* The maximum packet size is mainly defined by the maximum string -* length and the maximum number of arguments. -*/ -#ifndef SEGGER_SYSVIEW_MAX_PACKET_SIZE - #define SEGGER_SYSVIEW_MAX_PACKET_SIZE (SEGGER_SYSVIEW_INFO_SIZE + SEGGER_SYSVIEW_MAX_STRING_LEN + 2 * SEGGER_SYSVIEW_QUANTA_U32 + SEGGER_SYSVIEW_MAX_ARGUMENTS * SEGGER_SYSVIEW_QUANTA_U32) -#endif - -/********************************************************************* -* -* Define: SEGGER_SYSVIEW_POST_MORTEM_MODE -* -* Description -* If enabled, SystemView records for post-mortem analysis instead -* of real-time analysis. -* Default -* 0: Disabled. -* Notes -* For more information refer to -* https://www.segger.com/products/development-tools/systemview/technology/post-mortem-mode -*/ -#ifndef SEGGER_SYSVIEW_POST_MORTEM_MODE - #define SEGGER_SYSVIEW_POST_MORTEM_MODE 0 -#endif - -/********************************************************************* -* -* Define: SEGGER_SYSVIEW_SYNC_PERIOD_SHIFT -* -* Description -* Configure how frequently synchronization is sent in post-mortem -* mode. -* Default -* 8: (1 << 8) = Every 256 Events. -* Notes -* In post-mortem mode, at least one sync has to be in the RTT buffer. -* Recommended sync frequency: Buffer Size / 16 -* For more information refer to -* https://www.segger.com/products/development-tools/systemview/technology/post-mortem-mode -*/ -#ifndef SEGGER_SYSVIEW_SYNC_PERIOD_SHIFT - #define SEGGER_SYSVIEW_SYNC_PERIOD_SHIFT 8 -#endif - -/********************************************************************* -* -* Define: SEGGER_SYSVIEW_ON_EVENT_RECORDED() -* -* Description -* Function macro to notify recorder about a new event in buffer. -* Default -* undefined: Do not notify recorder. -* Notes -* Used for non-J-Link recorder, -* such as to enable transmission via UART or notify IP task. -*/ -#ifndef SEGGER_SYSVIEW_ON_EVENT_RECORDED - #define SEGGER_SYSVIEW_ON_EVENT_RECORDED(NumBytes) -#endif - -/********************************************************************* -* -* Define: SEGGER_SYSVIEW_LOCK() -* -* Description -* Function macro to (nestable) lock SystemView recording. -* Default -* Use RTT Locking mechanism (defined by SEGGER_RTT_LOCK()). -* Notes -* If SystemView recording is not locked, recording events from -* interrupts and tasks may lead to unpredictable, undefined, event -* data. -*/ -#ifndef SEGGER_SYSVIEW_LOCK - unsigned SEGGER_SYSVIEW_X_SysView_Lock(void); - #define SEGGER_SYSVIEW_LOCK() unsigned _SYSVIEW_int_state = SEGGER_SYSVIEW_X_SysView_Lock() -#endif - -/********************************************************************* -* -* Define: SEGGER_SYSVIEW_UNLOCK -* -* Description -* Function macro to unlock SystemView recording. -* Default -* Use RTT Unlocking mechanism (defined by SEGGER_RTT_UNLOCK()). -*/ -#ifndef SEGGER_SYSVIEW_UNLOCK - void SEGGER_SYSVIEW_X_SysView_Unlock(unsigned int_state); - #define SEGGER_SYSVIEW_UNLOCK() SEGGER_SYSVIEW_X_SysView_Unlock(_SYSVIEW_int_state) -#endif - -#ifdef __cplusplus -} -#endif - -#endif - -/*************************** End of file ****************************/ diff --git a/components/app_trace/sys_view/SEGGER/SEGGER_SYSVIEW_Int.h b/components/app_trace/sys_view/SEGGER/SEGGER_SYSVIEW_Int.h deleted file mode 100644 index 270fd9fc31c..00000000000 --- a/components/app_trace/sys_view/SEGGER/SEGGER_SYSVIEW_Int.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * SPDX-FileCopyrightText: 1995-2021 SEGGER Microcontroller GmbH - * - * SPDX-License-Identifier: BSD-1-Clause - */ -/********************************************************************* -* SEGGER Microcontroller GmbH * -* The Embedded Experts * -********************************************************************** -* * -* (c) 1995 - 2024 SEGGER Microcontroller GmbH * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER SystemView * Real-time application analysis * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* SEGGER strongly recommends to not make any changes * -* to or modify the source code of this software in order to stay * -* compatible with the SystemView and RTT protocol, and J-Link. * -* * -* Redistribution and use in source and binary forms, with or * -* without modification, are permitted provided that the following * -* condition is met: * -* * -* o Redistributions of source code must retain the above copyright * -* notice, this condition and the following disclaimer. * -* * -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * -* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * -* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * -* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * -* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * -* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * -* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * -* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * -* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * -* DAMAGE. * -* * -********************************************************************** -* * -* SystemView version: 3.56 * -* * -********************************************************************** --------------------------- END-OF-HEADER ----------------------------- -File : SEGGER_SYSVIEW_Int.h -Purpose : SEGGER SystemView internal header. -Revision: $Rev: 21281 $ -*/ - -#ifndef SEGGER_SYSVIEW_INT_H -#define SEGGER_SYSVIEW_INT_H - -/********************************************************************* -* -* #include Section -* -********************************************************************** -*/ - -#include "SEGGER_SYSVIEW.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -/********************************************************************* -* -* Private data types -* -********************************************************************** -*/ -// -// Commands that Host can send to target -// -typedef enum { - SEGGER_SYSVIEW_COMMAND_ID_START = 1, - SEGGER_SYSVIEW_COMMAND_ID_STOP, - SEGGER_SYSVIEW_COMMAND_ID_GET_SYSTIME, - SEGGER_SYSVIEW_COMMAND_ID_GET_TASKLIST, - SEGGER_SYSVIEW_COMMAND_ID_GET_SYSDESC, - SEGGER_SYSVIEW_COMMAND_ID_GET_NUMMODULES, - SEGGER_SYSVIEW_COMMAND_ID_GET_MODULEDESC, - SEGGER_SYSVIEW_COMMAND_ID_HEARTBEAT = 127, - // Extended commands: Commands >= 128 have a second parameter - SEGGER_SYSVIEW_COMMAND_ID_GET_MODULE = 128 -} SEGGER_SYSVIEW_COMMAND_ID; - -#ifdef __cplusplus -} -#endif - -#endif - -/*************************** End of file ****************************/ diff --git a/components/app_trace/sys_view/SEGGER/sbom.yml b/components/app_trace/sys_view/SEGGER/sbom.yml deleted file mode 100644 index 7ec0b47fec6..00000000000 --- a/components/app_trace/sys_view/SEGGER/sbom.yml +++ /dev/null @@ -1,6 +0,0 @@ -name: 'SystemView' -version: '3.56' -cpe: cpe:2.3:a:segger:systemview:{}:*:*:*:*:*:*:* -supplier: 'Organization: Espressif Systems (Shanghai) CO LTD' -originator: 'Organization: SEGGER Microcontroller GmbH' -description: Real-time recording and visualization tool for embedded systems. diff --git a/components/app_trace/sys_view/Sample/FreeRTOSV10.4/Config/esp/SEGGER_SYSVIEW_Config_FreeRTOS.c b/components/app_trace/sys_view/Sample/FreeRTOSV10.4/Config/esp/SEGGER_SYSVIEW_Config_FreeRTOS.c deleted file mode 100644 index eb40b843ab4..00000000000 --- a/components/app_trace/sys_view/Sample/FreeRTOSV10.4/Config/esp/SEGGER_SYSVIEW_Config_FreeRTOS.c +++ /dev/null @@ -1,224 +0,0 @@ -/* - * SPDX-FileCopyrightText: 1995-2021 SEGGER Microcontroller GmbH - * - * SPDX-License-Identifier: BSD-1-Clause - * - * SPDX-FileContributor: 2017-2025 Espressif Systems (Shanghai) CO LTD - */ -/********************************************************************* -* SEGGER Microcontroller GmbH * -* The Embedded Experts * -********************************************************************** -* * -* (c) 1995 - 2021 SEGGER Microcontroller GmbH * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER SystemView * Real-time application analysis * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* SEGGER strongly recommends to not make any changes * -* to or modify the source code of this software in order to stay * -* compatible with the SystemView and RTT protocol, and J-Link. * -* * -* Redistribution and use in source and binary forms, with or * -* without modification, are permitted provided that the following * -* condition is met: * -* * -* o Redistributions of source code must retain the above copyright * -* notice, this condition and the following disclaimer. * -* * -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * -* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * -* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * -* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * -* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * -* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * -* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * -* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * -* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * -* DAMAGE. * -* * -********************************************************************** -* * -* SystemView version: 3.42 * -* * -********************************************************************** --------------------------- END-OF-HEADER ----------------------------- - -File : SEGGER_SYSVIEW_Config_FreeRTOS.c -Purpose : Sample setup configuration of SystemView with FreeRTOS. -Revision: $Rev: 7745 $ -*/ -#include -#include "sdkconfig.h" -#include "freertos/FreeRTOS.h" -#include "SEGGER_SYSVIEW.h" -#include "esp_intr_alloc.h" -#include "soc/soc.h" -#include "soc/interrupts.h" -#include "esp_sysview_trace.h" -#include "esp_trace_port_encoder.h" -#include "esp_trace_port_transport.h" -#include "esp_trace_util.h" - -extern const SEGGER_SYSVIEW_OS_API SYSVIEW_X_OS_TraceAPI; - -/* Encoder reference for accessing lock functions - * This is set by SEGGER_RTT_ESP_SetEncoder() during encoder initialization */ -extern esp_trace_encoder_t* SEGGER_SYSVIEW_GetEncoder(void); - -/********************************************************************* -* -* Defines, configurable -* -********************************************************************** -*/ -// The application name to be displayed in SystemViewer -#define SYSVIEW_APP_NAME "FreeRTOS Application" - -// The target device name -#define SYSVIEW_DEVICE_NAME CONFIG_IDF_TARGET -// The target core name -#define SYSVIEW_CORE_NAME "core0" // In dual core, this will be renamed by OpenOCD as core1 - -// The lowest RAM address used for IDs (pointers) -#define SYSVIEW_RAM_BASE (SOC_DROM_LOW) - -#ifdef CONFIG_FREERTOS_TICK_SUPPORT_CORETIMER -#if CONFIG_FREERTOS_CORETIMER_0 - #define SYSTICK_INTR_ID (ETS_INTERNAL_TIMER0_INTR_SOURCE+ETS_INTERNAL_INTR_SOURCE_OFF) -#endif -#if CONFIG_FREERTOS_CORETIMER_1 - #define SYSTICK_INTR_ID (ETS_INTERNAL_TIMER1_INTR_SOURCE+ETS_INTERNAL_INTR_SOURCE_OFF) -#endif - -#elif CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER - #define SYSTICK_INTR_ID (ETS_SYSTIMER_TARGET0_INTR_SOURCE) -#endif // CONFIG_FREERTOS_TICK_SUPPORT_CORETIMER - -// SystemView is single core specific: it implies that SEGGER_SYSVIEW_LOCK() -// disables IRQs (disables rescheduling globally). So we can not use finite timeouts for locks and return error -// in case of expiration, because error will not be handled and SEGGER's code will go further implying that -// everything is fine, so for multi-core env we have to wait on underlying lock forever -#define SEGGER_LOCK_WAIT_TMO ESP_TRACE_TMO_INFINITE - -/********************************************************************* -* -* _cbSendSystemDesc() -* -* Function description -* Sends SystemView description strings. -*/ -static void _cbSendSystemDesc(void) { - char irq_str[32] = "I#"; - SEGGER_SYSVIEW_SendSysDesc("N="SYSVIEW_APP_NAME",D="SYSVIEW_DEVICE_NAME",C="SYSVIEW_CORE_NAME",O=FreeRTOS"); - strcat(itoa(SYSTICK_INTR_ID, irq_str + 2, 10), "=SysTick"); - SEGGER_SYSVIEW_SendSysDesc(irq_str); - size_t isr_count = sizeof(esp_isr_names)/sizeof(esp_isr_names[0]); - for (size_t i = 0; i < isr_count; ++i) { - if (esp_isr_names[i] == NULL || (ETS_INTERNAL_INTR_SOURCE_OFF + i) == SYSTICK_INTR_ID) - continue; - strcat(itoa(ETS_INTERNAL_INTR_SOURCE_OFF + i, irq_str + 2, 10), "="); - strncat(irq_str, esp_isr_names[i], sizeof(irq_str) - strlen(irq_str) - 1); - SEGGER_SYSVIEW_SendSysDesc(irq_str); - } -} - -/********************************************************************* -* -* Global functions -* -********************************************************************** -*/ -void SEGGER_SYSVIEW_Conf(void) { - U32 disable_evts = 0; - - int timestamp_freq = esp_trace_timestamp_init(); - SEGGER_SYSVIEW_Init(timestamp_freq, esp_trace_cpu_freq_get(), - &SYSVIEW_X_OS_TraceAPI, _cbSendSystemDesc); - SEGGER_SYSVIEW_SetRAMBase(SYSVIEW_RAM_BASE); - -#if !CONFIG_SEGGER_SYSVIEW_EVT_OVERFLOW_ENABLE - disable_evts |= SYSVIEW_EVTMASK_OVERFLOW; -#endif -#if !CONFIG_SEGGER_SYSVIEW_EVT_ISR_ENTER_ENABLE - disable_evts |= SYSVIEW_EVTMASK_ISR_ENTER; -#endif -#if !CONFIG_SEGGER_SYSVIEW_EVT_ISR_EXIT_ENABLE - disable_evts |= SYSVIEW_EVTMASK_ISR_EXIT; -#endif -#if !CONFIG_SEGGER_SYSVIEW_EVT_TASK_START_EXEC_ENABLE - disable_evts |= SYSVIEW_EVTMASK_TASK_START_EXEC; -#endif -#if !CONFIG_SEGGER_SYSVIEW_EVT_TASK_STOP_EXEC_ENABLE - disable_evts |= SYSVIEW_EVTMASK_TASK_STOP_EXEC; -#endif -#if !CONFIG_SEGGER_SYSVIEW_EVT_TASK_START_READY_ENABLE - disable_evts |= SYSVIEW_EVTMASK_TASK_START_READY; -#endif -#if !CONFIG_SEGGER_SYSVIEW_EVT_TASK_STOP_READY_ENABLE - disable_evts |= SYSVIEW_EVTMASK_TASK_STOP_READY; -#endif -#if !CONFIG_SEGGER_SYSVIEW_EVT_TASK_CREATE_ENABLE - disable_evts |= SYSVIEW_EVTMASK_TASK_CREATE; -#endif -#if !CONFIG_SEGGER_SYSVIEW_EVT_TASK_TERMINATE_ENABLE - disable_evts |= SYSVIEW_EVTMASK_TASK_TERMINATE; -#endif -#if !CONFIG_SEGGER_SYSVIEW_EVT_IDLE_ENABLE - disable_evts |= SYSVIEW_EVTMASK_IDLE; -#endif -#if !CONFIG_SEGGER_SYSVIEW_EVT_ISR_TO_SCHED_ENABLE - disable_evts |= SYSVIEW_EVTMASK_ISR_TO_SCHEDULER; -#endif -#if !CONFIG_SEGGER_SYSVIEW_EVT_TIMER_ENTER_ENABLE - disable_evts |= SYSVIEW_EVTMASK_TIMER_ENTER; -#endif -#if !CONFIG_SEGGER_SYSVIEW_EVT_TIMER_EXIT_ENABLE - disable_evts |= SYSVIEW_EVTMASK_TIMER_EXIT; -#endif - SEGGER_SYSVIEW_DisableEvents(disable_evts); -} - -U32 SEGGER_SYSVIEW_X_GetTimestamp(void) -{ - return esp_trace_timestamp_get(); -} - -void SEGGER_SYSVIEW_X_RTT_Lock(void) -{ -} - -void SEGGER_SYSVIEW_X_RTT_Unlock(void) -{ -} - -unsigned SEGGER_SYSVIEW_X_SysView_Lock(void) -{ - esp_trace_encoder_t *encoder = SEGGER_SYSVIEW_GetEncoder(); - if (encoder) { - // Use encoder-level lock - return encoder->vt->take_lock(encoder, SEGGER_LOCK_WAIT_TMO); - } - return 0; -} - -void SEGGER_SYSVIEW_X_SysView_Unlock(unsigned int_state) -{ - esp_trace_encoder_t *encoder = SEGGER_SYSVIEW_GetEncoder(); - if (encoder) { - // Use encoder-level unlock - encoder->vt->give_lock(encoder, int_state); - } -} - -/*************************** End of file ****************************/ diff --git a/components/app_trace/sys_view/Sample/FreeRTOSV10.4/SEGGER_SYSVIEW_FreeRTOS.c b/components/app_trace/sys_view/Sample/FreeRTOSV10.4/SEGGER_SYSVIEW_FreeRTOS.c deleted file mode 100644 index 679b40107fe..00000000000 --- a/components/app_trace/sys_view/Sample/FreeRTOSV10.4/SEGGER_SYSVIEW_FreeRTOS.c +++ /dev/null @@ -1,270 +0,0 @@ -/* - * SPDX-FileCopyrightText: 1995-2021 SEGGER Microcontroller GmbH - * - * SPDX-License-Identifier: BSD-1-Clause - * - * SPDX-FileContributor: 2023 Espressif Systems (Shanghai) CO LTD - */ -/********************************************************************* -* SEGGER Microcontroller GmbH * -* The Embedded Experts * -********************************************************************** -* * -* (c) 1995 - 2021 SEGGER Microcontroller GmbH * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER SystemView * Real-time application analysis * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* SEGGER strongly recommends to not make any changes * -* to or modify the source code of this software in order to stay * -* compatible with the SystemView and RTT protocol, and J-Link. * -* * -* Redistribution and use in source and binary forms, with or * -* without modification, are permitted provided that the following * -* condition is met: * -* * -* o Redistributions of source code must retain the above copyright * -* notice, this condition and the following disclaimer. * -* * -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * -* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * -* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * -* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * -* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * -* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * -* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * -* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * -* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * -* DAMAGE. * -* * -********************************************************************** -* * -* SystemView version: 3.42 * -* * -********************************************************************** --------------------------- END-OF-HEADER ----------------------------- - -File : SEGGER_SYSVIEW_FreeRTOS.c -Purpose : Interface between FreeRTOS and SystemView. -Revision: $Rev: 7947 $ -*/ -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "SEGGER_SYSVIEW.h" -#include "SEGGER_SYSVIEW_FreeRTOS.h" -#include "string.h" // Required for memset - - - -typedef struct SYSVIEW_FREERTOS_TASK_STATUS SYSVIEW_FREERTOS_TASK_STATUS; - -struct SYSVIEW_FREERTOS_TASK_STATUS { - U32 xHandle; - const char* pcTaskName; - unsigned uxCurrentPriority; - U32 pxStack; - unsigned uStackHighWaterMark; -}; - -static SYSVIEW_FREERTOS_TASK_STATUS _aTasks[SYSVIEW_FREERTOS_MAX_NOF_TASKS]; -static unsigned _NumTasks; - -/********************************************************************* -* -* _cbSendTaskList() -* -* Function description -* This function is part of the link between FreeRTOS and SYSVIEW. -* Called from SystemView when asked by the host, it uses SYSVIEW -* functions to send the entire task list to the host. -*/ -static void _cbSendTaskList(void) { - unsigned n; - - for (n = 0; n < _NumTasks; n++) { -#if INCLUDE_uxTaskGetStackHighWaterMark // Report Task Stack High Watermark - _aTasks[n].uStackHighWaterMark = uxTaskGetStackHighWaterMark((TaskHandle_t)_aTasks[n].xHandle); -#endif - SYSVIEW_SendTaskInfo((U32)_aTasks[n].xHandle, _aTasks[n].pcTaskName, (unsigned)_aTasks[n].uxCurrentPriority, (U32)_aTasks[n].pxStack, (unsigned)_aTasks[n].uStackHighWaterMark); - } -} - -/********************************************************************* -* -* _cbGetTime() -* -* Function description -* This function is part of the link between FreeRTOS and SYSVIEW. -* Called from SystemView when asked by the host, returns the -* current system time in micro seconds. -*/ -__attribute__((unused)) static U64 _cbGetTime(void) { - U64 Time; - - Time = xTaskGetTickCountFromISR(); - Time *= portTICK_PERIOD_MS; - Time *= 1000; - return Time; -} - -/********************************************************************* -* -* Global functions -* -********************************************************************** -*/ -/********************************************************************* -* -* SYSVIEW_AddTask() -* -* Function description -* Add a task to the internal list and record its information. -*/ -void SYSVIEW_AddTask(U32 xHandle, const char* pcTaskName, unsigned uxCurrentPriority, U32 pxStack, unsigned uStackHighWaterMark) { - - /* On multi-core we have several idle tasks with 'IDLEx' names - Not best solution, because we can filter out user tasks starting with 'IDLE'. - But we can not use 'xTaskGetIdleTaskHandle' because at the moment when this - function is called array of idle tasks handles are not initialized yet. */ - if (memcmp(pcTaskName, "IDLE", 4) == 0) { - return; - } - - if (_NumTasks >= SYSVIEW_FREERTOS_MAX_NOF_TASKS) { - SEGGER_SYSVIEW_Warn("SYSTEMVIEW: Could not record task information. Maximum number of tasks reached."); - return; - } - - _aTasks[_NumTasks].xHandle = xHandle; - _aTasks[_NumTasks].pcTaskName = pcTaskName; - _aTasks[_NumTasks].uxCurrentPriority = uxCurrentPriority; - _aTasks[_NumTasks].pxStack = pxStack; - _aTasks[_NumTasks].uStackHighWaterMark = uStackHighWaterMark; - - _NumTasks++; - - SYSVIEW_SendTaskInfo(xHandle, pcTaskName,uxCurrentPriority, pxStack, uStackHighWaterMark); - -} - -/********************************************************************* -* -* SYSVIEW_UpdateTask() -* -* Function description -* Update a task in the internal list and record its information. -*/ -void SYSVIEW_UpdateTask(U32 xHandle, const char* pcTaskName, unsigned uxCurrentPriority, U32 pxStack, unsigned uStackHighWaterMark) { - unsigned n; - - /* On multi-core we have several idle tasks with 'IDLEx' names - Not best solution, because we can filter out user tasks starting with 'IDLE'. - But we can not use 'xTaskGetIdleTaskHandle' because at the moment when this - function is called array of idle tasks handles are not initialized yet. */ - if (memcmp(pcTaskName, "IDLE", 4) == 0) { - return; - } - - for (n = 0; n < _NumTasks; n++) { - if (_aTasks[n].xHandle == xHandle) { - break; - } - } - if (n < _NumTasks) { - _aTasks[n].pcTaskName = pcTaskName; - _aTasks[n].uxCurrentPriority = uxCurrentPriority; - _aTasks[n].pxStack = pxStack; - _aTasks[n].uStackHighWaterMark = uStackHighWaterMark; - - SYSVIEW_SendTaskInfo(xHandle, pcTaskName, uxCurrentPriority, pxStack, uStackHighWaterMark); - } else { - SYSVIEW_AddTask(xHandle, pcTaskName, uxCurrentPriority, pxStack, uStackHighWaterMark); - } -} - -/********************************************************************* -* -* SYSVIEW_DeleteTask() -* -* Function description -* Delete a task from the internal list. -*/ -void SYSVIEW_DeleteTask(U32 xHandle) { - unsigned n; - - if (_NumTasks == 0) { - return; // Early out - } - for (n = 0; n < _NumTasks; n++) { - if (_aTasks[n].xHandle == xHandle) { - break; - } - } - if (n == (_NumTasks - 1)) { - // - // Task is last item in list. - // Simply zero the item and decrement number of tasks. - // - memset(&_aTasks[n], 0, sizeof(_aTasks[n])); - _NumTasks--; - } else if (n < _NumTasks) { - // - // Task is in the middle of the list. - // Move last item to current position and decrement number of tasks. - // Order of tasks does not really matter, so no need to move all following items. - // - _aTasks[n].xHandle = _aTasks[_NumTasks - 1].xHandle; - _aTasks[n].pcTaskName = _aTasks[_NumTasks - 1].pcTaskName; - _aTasks[n].uxCurrentPriority = _aTasks[_NumTasks - 1].uxCurrentPriority; - _aTasks[n].pxStack = _aTasks[_NumTasks - 1].pxStack; - _aTasks[n].uStackHighWaterMark = _aTasks[_NumTasks - 1].uStackHighWaterMark; - memset(&_aTasks[_NumTasks - 1], 0, sizeof(_aTasks[_NumTasks - 1])); - _NumTasks--; - } -} - -/********************************************************************* -* -* SYSVIEW_SendTaskInfo() -* -* Function description -* Record task information. -*/ -void SYSVIEW_SendTaskInfo(U32 TaskID, const char* sName, unsigned Prio, U32 StackBase, unsigned StackSize) { - SEGGER_SYSVIEW_TASKINFO TaskInfo; - - memset(&TaskInfo, 0, sizeof(TaskInfo)); // Fill all elements with 0 to allow extending the structure in future version without breaking the code - TaskInfo.TaskID = TaskID; - TaskInfo.sName = sName; - TaskInfo.Prio = Prio; - TaskInfo.StackBase = StackBase; - TaskInfo.StackSize = StackSize; - SEGGER_SYSVIEW_SendTaskInfo(&TaskInfo); -} - -/********************************************************************* -* -* Public API structures -* -********************************************************************** -*/ -// Callbacks provided to SYSTEMVIEW by FreeRTOS -const SEGGER_SYSVIEW_OS_API SYSVIEW_X_OS_TraceAPI = { - /* Callback _cbGetTime locks xKernelLock inside xTaskGetTickCountFromISR, this can cause deadlock on multi-core. - To prevent deadlock, always lock xKernelLock before s_sys_view_lock. Omitting the callback here results in sending - SYSVIEW_EVTID_SYSTIME_CYCLES events instead of SYSVIEW_EVTID_SYSTIME_US */ - NULL, - _cbSendTaskList, -}; - -/*************************** End of file ****************************/ diff --git a/components/app_trace/sys_view/Sample/FreeRTOSV10.4/SEGGER_SYSVIEW_FreeRTOS.h b/components/app_trace/sys_view/Sample/FreeRTOSV10.4/SEGGER_SYSVIEW_FreeRTOS.h deleted file mode 100644 index 5d67e93e043..00000000000 --- a/components/app_trace/sys_view/Sample/FreeRTOSV10.4/SEGGER_SYSVIEW_FreeRTOS.h +++ /dev/null @@ -1,367 +0,0 @@ -/* - * SPDX-FileCopyrightText: 1995-2021 SEGGER Microcontroller GmbH - * - * SPDX-License-Identifier: BSD-1-Clause - * - * SPDX-FileContributor: 2023 Espressif Systems (Shanghai) CO LTD - */ -/********************************************************************* -* SEGGER Microcontroller GmbH * -* The Embedded Experts * -********************************************************************** -* * -* (c) 1995 - 2021 SEGGER Microcontroller GmbH * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER SystemView * Real-time application analysis * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* SEGGER strongly recommends to not make any changes * -* to or modify the source code of this software in order to stay * -* compatible with the SystemView and RTT protocol, and J-Link. * -* * -* Redistribution and use in source and binary forms, with or * -* without modification, are permitted provided that the following * -* condition is met: * -* * -* o Redistributions of source code must retain the above copyright * -* notice, this condition and the following disclaimer. * -* * -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * -* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * -* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * -* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * -* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * -* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * -* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * -* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * -* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * -* DAMAGE. * -* * -********************************************************************** -* * -* SystemView version: 3.42 * -* * -********************************************************************** --------------------------- END-OF-HEADER ----------------------------- - -File : SEGGER_SYSVIEW_FreeRTOS.h -Purpose : Interface between FreeRTOS and SystemView. - Tested with FreeRTOS V10.4.3 -Revision: $Rev: 7745 $ - -Notes: - (1) Include this file at the end of FreeRTOSConfig.h -*/ - -#ifndef SYSVIEW_FREERTOS_H -#define SYSVIEW_FREERTOS_H - -#include "SEGGER_SYSVIEW.h" - -/********************************************************************* -* -* Defines, configurable -* -********************************************************************** -*/ - -#define SYSVIEW_FREERTOS_MAX_NOF_TASKS CONFIG_SEGGER_SYSVIEW_MAX_TASKS - -/********************************************************************* -* -* Defines, fixed -* -********************************************************************** -*/ -// for dual-core targets we use event ID to keep core ID bit (0 or 1) -// use the highest - 1 bit of event ID to indicate core ID -// the highest bit can not be used due to event ID encoding method -// this reduces supported ID range to [0..63] (for 1 byte IDs) plus [128..16383] (for 2 bytes IDs) -// so original continuous event IDs range is split into two sub-ranges for 1-bytes IDs and 2-bytes ones - -// events which use apiFastID_OFFSET will have 1 byte ID, -// so for the sake of bandwidth economy events which are generated more frequently should use this ID offset -// currently all used events fall into this range -#define apiFastID_OFFSET (32u) - -#define apiID_VTASKDELETE (1u) -#define apiID_VTASKDELAY (2u) -#define apiID_VTASKDELAYUNTIL (3u) -#define apiID_VTASKSUSPEND (4u) -#define apiID_ULTASKNOTIFYTAKE (5u) -#define apiID_VTASKNOTIFYGIVEFROMISR (6u) -#define apiID_VTASKPRIORITYINHERIT (7u) -#define apiID_VTASKRESUME (8u) -#define apiID_VTASKSTEPTICK (9u) -#define apiID_XTASKPRIORITYDISINHERIT (10u) -#define apiID_XTASKRESUMEFROMISR (11u) -#define apiID_XTASKGENERICNOTIFY (12u) -#define apiID_XTASKGENERICNOTIFYFROMISR (13u) -#define apiID_XTASKNOTIFYWAIT (14u) -#define apiID_XQUEUEGENERICCREATE (15u) -#define apiID_VQUEUEDELETE (16u) -#define apiID_XQUEUEGENERICRECEIVE (17u) -#define apiID_XQUEUEPEEKFROMISR (18u) -#define apiID_XQUEUERECEIVEFROMISR (19u) -#define apiID_VQUEUEADDTOREGISTRY (20u) -#define apiID_XQUEUEGENERICSEND (21u) -#define apiID_XQUEUEGENERICSENDFROMISR (22u) -#define apiID_VTASKPRIORITYSET (23u) -#define apiID_UXTASKPRIORITYGETFROMISR (24u) -#define apiID_XTASKGETTICKCOUNTFROMISR (25u) -#define apiID_XEVENTGROUPCLEARBITSFROMISR (26u) -#define apiID_XEVENTGROUPSETBITSFROMISR (27u) -#define apiID_XEVENTGROUPGETBITSFROMISR (28u) -#define apiID_XQUEUEGIVEFROMISR (29u) -#define apiID_XQUEUEISQUEUEEMPTYFROMISR (30u) -#define apiID_XQUEUEISQUEUEFULLFROMISR (31u) // the maximum allowed apiID for the first ID range - -// events which use apiSlowID_OFFSET will have 2-bytes ID -#define apiSlowID_OFFSET (127u) - -#define apiID_VTASKALLOCATEMPUREGIONS (1u) -#define apiID_UXTASKPRIORITYGET (2u) -#define apiID_ETASKGETSTATE (3u) -#define apiID_VTASKSTARTSCHEDULER (4u) -#define apiID_VTASKENDSCHEDULER (5u) -#define apiID_VTASKSUSPENDALL (6u) -#define apiID_XTASKRESUMEALL (7u) -#define apiID_XTASKGETTICKCOUNT (8u) -#define apiID_UXTASKGETNUMBEROFTASKS (9u) -#define apiID_PCTASKGETTASKNAME (10u) -#define apiID_UXTASKGETSTACKHIGHWATERMARK (11u) -#define apiID_VTASKSETAPPLICATIONTASKTAG (12u) -#define apiID_XTASKGETAPPLICATIONTASKTAG (13u) -#define apiID_VTASKSETTHREADLOCALSTORAGEPOINTER (14u) -#define apiID_PVTASKGETTHREADLOCALSTORAGEPOINTER (15u) -#define apiID_XTASKCALLAPPLICATIONTASKHOOK (16u) -#define apiID_XTASKGETIDLETASKHANDLE (17u) -#define apiID_UXTASKGETSYSTEMSTATE (18u) -#define apiID_VTASKLIST (19u) -#define apiID_VTASKGETRUNTIMESTATS (20u) -#define apiID_XTASKNOTIFYSTATECLEAR (21u) -#define apiID_XTASKGETCURRENTTASKHANDLE (22u) -#define apiID_VTASKSETTIMEOUTSTATE (23u) -#define apiID_XTASKCHECKFORTIMEOUT (24u) -#define apiID_VTASKMISSEDYIELD (25u) -#define apiID_XTASKGETSCHEDULERSTATE (26u) -#define apiID_XTASKGENERICCREATE (27u) -#define apiID_UXTASKGETTASKNUMBER (28u) -#define apiID_VTASKSETTASKNUMBER (29u) -#define apiID_ETASKCONFIRMSLEEPMODESTATUS (30u) -#define apiID_XTIMERCREATE (31u) -#define apiID_PVTIMERGETTIMERID (32u) -#define apiID_VTIMERSETTIMERID (33u) -#define apiID_XTIMERISTIMERACTIVE (34u) -#define apiID_XTIMERGETTIMERDAEMONTASKHANDLE (35u) -#define apiID_XTIMERPENDFUNCTIONCALLFROMISR (36u) -#define apiID_XTIMERPENDFUNCTIONCALL (37u) -#define apiID_PCTIMERGETTIMERNAME (38u) -#define apiID_XTIMERCREATETIMERTASK (39u) -#define apiID_XTIMERGENERICCOMMAND (40u) -#define apiID_UXQUEUEMESSAGESWAITING (41u) -#define apiID_UXQUEUESPACESAVAILABLE (42u) -#define apiID_UXQUEUEMESSAGESWAITINGFROMISR (43u) -#define apiID_XQUEUEALTGENERICSEND (44u) -#define apiID_XQUEUEALTGENERICRECEIVE (45u) -#define apiID_XQUEUECRSENDFROMISR (46u) -#define apiID_XQUEUECRRECEIVEFROMISR (47u) -#define apiID_XQUEUECRSEND (48u) -#define apiID_XQUEUECRRECEIVE (49u) -#define apiID_XQUEUECREATEMUTEX (50u) -#define apiID_XQUEUECREATECOUNTINGSEMAPHORE (51u) -#define apiID_XQUEUEGETMUTEXHOLDER (52u) -#define apiID_XQUEUETAKEMUTEXRECURSIVE (53u) -#define apiID_XQUEUEGIVEMUTEXRECURSIVE (54u) -#define apiID_VQUEUEUNREGISTERQUEUE (55u) -#define apiID_XQUEUECREATESET (56u) -#define apiID_XQUEUEADDTOSET (57u) -#define apiID_XQUEUEREMOVEFROMSET (58u) -#define apiID_XQUEUESELECTFROMSET (59u) -#define apiID_XQUEUESELECTFROMSETFROMISR (60u) -#define apiID_XQUEUEGENERICRESET (61u) -#define apiID_VLISTINITIALISE (62u) -#define apiID_VLISTINITIALISEITEM (63u) -#define apiID_VLISTINSERT (64u) -#define apiID_VLISTINSERTEND (65u) -#define apiID_UXLISTREMOVE (66u) -#define apiID_XEVENTGROUPCREATE (67u) -#define apiID_XEVENTGROUPWAITBITS (68u) -#define apiID_XEVENTGROUPCLEARBITS (69u) -#define apiID_XEVENTGROUPSETBITS (70u) -#define apiID_XEVENTGROUPSYNC (71u) -#define apiID_VEVENTGROUPDELETE (72u) -#define apiID_UXEVENTGROUPGETNUMBER (73u) -#define apiID_XSTREAMBUFFERCREATE (74u) -#define apiID_VSTREAMBUFFERDELETE (75u) -#define apiID_XSTREAMBUFFERRESET (76u) -#define apiID_XSTREAMBUFFERSEND (77u) -#define apiID_XSTREAMBUFFERSENDFROMISR (78u) -#define apiID_XSTREAMBUFFERRECEIVE (79u) -#define apiID_XSTREAMBUFFERRECEIVEFROMISR (80u) - -#ifdef CONFIG_FREERTOS_SMP - -#define traceQUEUE_SEND( pxQueue ) SEGGER_SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICSEND, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), 0u, 0u, 0u) - -#else // CONFIG_FREERTOS_SMP - -#if ( configUSE_QUEUE_SETS != 1 ) - #define traceQUEUE_SEND( pxQueue ) SEGGER_SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICSEND, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), (U32)pvItemToQueue, xTicksToWait, xCopyPosition) -#else - #define traceQUEUE_SEND( pxQueue ) SEGGER_SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICSEND, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), 0u, 0u, 0u) -#endif - -#endif // CONFIG_FREERTOS_SMP - - -#define traceSTART() SEGGER_SYSVIEW_Conf() - -#define traceTASK_NOTIFY_TAKE(uxIndexToWait) SEGGER_SYSVIEW_RecordU32x2(apiFastID_OFFSET + apiID_ULTASKNOTIFYTAKE, xClearCountOnExit, xTicksToWait) -#define traceTASK_DELAY() SEGGER_SYSVIEW_RecordU32 (apiFastID_OFFSET + apiID_VTASKDELAY, xTicksToDelay) -#define traceTASK_DELAY_UNTIL(xTimeToWake) SEGGER_SYSVIEW_RecordVoid (apiFastID_OFFSET + apiID_VTASKDELAYUNTIL) -#define traceTASK_NOTIFY_GIVE_FROM_ISR(uxIndexToNotify) SEGGER_SYSVIEW_RecordU32x2(apiFastID_OFFSET + apiID_VTASKNOTIFYGIVEFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxTCB), (U32)pxHigherPriorityTaskWoken) - -#define traceTASK_PRIORITY_INHERIT( pxTCB, uxPriority ) SEGGER_SYSVIEW_RecordU32 (apiFastID_OFFSET + apiID_VTASKPRIORITYINHERIT, (U32)pxMutexHolder) -#define traceTASK_RESUME( pxTCB ) SEGGER_SYSVIEW_RecordU32 (apiFastID_OFFSET + apiID_VTASKRESUME, SEGGER_SYSVIEW_ShrinkId((U32)pxTCB)) -#define traceINCREASE_TICK_COUNT( xTicksToJump ) SEGGER_SYSVIEW_RecordU32 (apiFastID_OFFSET + apiID_VTASKSTEPTICK, xTicksToJump) -#define traceTASK_SUSPEND( pxTCB ) SEGGER_SYSVIEW_RecordU32 (apiFastID_OFFSET + apiID_VTASKSUSPEND, SEGGER_SYSVIEW_ShrinkId((U32)pxTCB)) -#define traceTASK_PRIORITY_DISINHERIT( pxTCB, uxBasePriority ) SEGGER_SYSVIEW_RecordU32 (apiFastID_OFFSET + apiID_XTASKPRIORITYDISINHERIT, (U32)pxMutexHolder) -#define traceTASK_RESUME_FROM_ISR( pxTCB ) SEGGER_SYSVIEW_RecordU32 (apiFastID_OFFSET + apiID_XTASKRESUMEFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxTCB)) -#define traceTASK_NOTIFY(uxIndexToNotify) SEGGER_SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XTASKGENERICNOTIFY, SEGGER_SYSVIEW_ShrinkId((U32)pxTCB), ulValue, eAction, (U32)pulPreviousNotificationValue) -#define traceTASK_NOTIFY_FROM_ISR(uxIndexToWait) SEGGER_SYSVIEW_RecordU32x5(apiFastID_OFFSET + apiID_XTASKGENERICNOTIFYFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxTCB), ulValue, eAction, (U32)pulPreviousNotificationValue, (U32)pxHigherPriorityTaskWoken) -#define traceTASK_NOTIFY_WAIT(uxIndexToWait) SEGGER_SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XTASKNOTIFYWAIT, ulBitsToClearOnEntry, ulBitsToClearOnExit, (U32)pulNotificationValue, xTicksToWait) - -#define traceQUEUE_CREATE( pxNewQueue ) SEGGER_SYSVIEW_RecordU32x3(apiFastID_OFFSET + apiID_XQUEUEGENERICCREATE, uxQueueLength, uxItemSize, ucQueueType) -#define traceQUEUE_DELETE( pxQueue ) SEGGER_SYSVIEW_RecordU32 (apiFastID_OFFSET + apiID_VQUEUEDELETE, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue)) -#define traceQUEUE_PEEK( pxQueue ) SEGGER_SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICRECEIVE, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), SEGGER_SYSVIEW_ShrinkId((U32)pvBuffer), xTicksToWait, 1) -#define traceQUEUE_PEEK_FROM_ISR( pxQueue ) SEGGER_SYSVIEW_RecordU32x2(apiFastID_OFFSET + apiID_XQUEUEPEEKFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), SEGGER_SYSVIEW_ShrinkId((U32)pvBuffer)) -#define traceQUEUE_PEEK_FROM_ISR_FAILED( pxQueue ) SEGGER_SYSVIEW_RecordU32x2(apiFastID_OFFSET + apiID_XQUEUEPEEKFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), SEGGER_SYSVIEW_ShrinkId((U32)pvBuffer)) -#define traceQUEUE_RECEIVE( pxQueue ) SEGGER_SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICRECEIVE, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), SEGGER_SYSVIEW_ShrinkId((U32)0), xTicksToWait, 1) -#define traceQUEUE_RECEIVE_FAILED( pxQueue ) SEGGER_SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICRECEIVE, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), SEGGER_SYSVIEW_ShrinkId((U32)0), xTicksToWait, 1) -#define traceQUEUE_SEMAPHORE_RECEIVE( pxQueue ) SEGGER_SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICRECEIVE, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), SEGGER_SYSVIEW_ShrinkId((U32)0), xTicksToWait, 0) -#define traceQUEUE_RECEIVE_FROM_ISR( pxQueue ) SEGGER_SYSVIEW_RecordU32x3(apiFastID_OFFSET + apiID_XQUEUERECEIVEFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), SEGGER_SYSVIEW_ShrinkId((U32)pvBuffer), (U32)pxHigherPriorityTaskWoken) -#define traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue ) SEGGER_SYSVIEW_RecordU32x3(apiFastID_OFFSET + apiID_XQUEUERECEIVEFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), SEGGER_SYSVIEW_ShrinkId((U32)pvBuffer), (U32)pxHigherPriorityTaskWoken) -#define traceQUEUE_REGISTRY_ADD( xQueue, pcQueueName ) SEGGER_SYSVIEW_RecordU32x2(apiFastID_OFFSET + apiID_VQUEUEADDTOREGISTRY, SEGGER_SYSVIEW_ShrinkId((U32)xQueue), (U32)pcQueueName) -#define traceQUEUE_SEND_FAILED( pxQueue ) SEGGER_SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICSEND, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), (U32)pvItemToQueue, xTicksToWait, xCopyPosition) -#define traceQUEUE_SEND_FROM_ISR( pxQueue ) SEGGER_SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICSENDFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), (U32)pvItemToQueue, (U32)pxHigherPriorityTaskWoken, xCopyPosition) -#define traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ) SEGGER_SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICSENDFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), (U32)pvItemToQueue, (U32)pxHigherPriorityTaskWoken, xCopyPosition) -#define traceQUEUE_GIVE_FROM_ISR( pxQueue ) SEGGER_SYSVIEW_RecordU32x2(apiFastID_OFFSET + apiID_XQUEUEGIVEFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), (U32)pxHigherPriorityTaskWoken) -#define traceQUEUE_GIVE_FROM_ISR_FAILED( pxQueue ) SEGGER_SYSVIEW_RecordU32x2(apiFastID_OFFSET + apiID_XQUEUEGIVEFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), (U32)pxHigherPriorityTaskWoken) -#define traceSTREAM_BUFFER_CREATE( pxStreamBuffer, xIsMessageBuffer ) SEGGER_SYSVIEW_RecordU32x2(apiSlowID_OFFSET + apiID_XSTREAMBUFFERCREATE, (U32)xIsMessageBuffer, (U32)pxStreamBuffer) -#define traceSTREAM_BUFFER_CREATE_FAILED( xIsMessageBuffer ) SEGGER_SYSVIEW_RecordU32x2(apiSlowID_OFFSET + apiID_XSTREAMBUFFERCREATE, (U32)xIsMessageBuffer, 0u) -#define traceSTREAM_BUFFER_DELETE( xStreamBuffer ) SEGGER_SYSVIEW_RecordU32 (apiSlowID_OFFSET + apiID_VSTREAMBUFFERDELETE, (U32)xStreamBuffer) -#define traceSTREAM_BUFFER_RESET( xStreamBuffer ) SEGGER_SYSVIEW_RecordU32 (apiSlowID_OFFSET + apiID_XSTREAMBUFFERRESET, (U32)xStreamBuffer) -#define traceSTREAM_BUFFER_SEND( xStreamBuffer, xBytesSent ) SEGGER_SYSVIEW_RecordU32x2(apiSlowID_OFFSET + apiID_XSTREAMBUFFERSEND, (U32)xStreamBuffer, (U32)xBytesSent) -#define traceSTREAM_BUFFER_SEND_FAILED( xStreamBuffer ) SEGGER_SYSVIEW_RecordU32x2(apiSlowID_OFFSET + apiID_XSTREAMBUFFERSEND, (U32)xStreamBuffer, 0u) -#define traceSTREAM_BUFFER_SEND_FROM_ISR( xStreamBuffer, xBytesSent ) SEGGER_SYSVIEW_RecordU32x2(apiSlowID_OFFSET + apiID_XSTREAMBUFFERSENDFROMISR, (U32)xStreamBuffer, (U32)xBytesSent) -#define traceSTREAM_BUFFER_RECEIVE( xStreamBuffer, xReceivedLength ) SEGGER_SYSVIEW_RecordU32x2(apiSlowID_OFFSET + apiID_XSTREAMBUFFERRECEIVE, (U32)xStreamBuffer, (U32)xReceivedLength) -#define traceSTREAM_BUFFER_RECEIVE_FAILED( xStreamBuffer ) SEGGER_SYSVIEW_RecordU32x2(apiSlowID_OFFSET + apiID_XSTREAMBUFFERRECEIVE, (U32)xStreamBuffer, 0u) -#define traceSTREAM_BUFFER_RECEIVE_FROM_ISR( xStreamBuffer, xReceivedLength ) SEGGER_SYSVIEW_RecordU32x2(apiSlowID_OFFSET + apiID_XSTREAMBUFFERRECEIVEFROMISR, (U32)xStreamBuffer, (U32)xReceivedLength) - -#define traceTASK_DELETE( pxTCB ) do { \ - SEGGER_SYSVIEW_RecordU32(apiFastID_OFFSET + apiID_VTASKDELETE, SEGGER_SYSVIEW_ShrinkId((U32)pxTCB)); \ - SYSVIEW_DeleteTask((U32)pxTCB); \ - } while(0) - - -#if( portSTACK_GROWTH < 0 ) -#define traceTASK_CREATE(pxNewTCB) if (pxNewTCB != NULL) { \ - SEGGER_SYSVIEW_OnTaskCreate((U32)pxNewTCB); \ - SYSVIEW_AddTask((U32)pxNewTCB, \ - &(pxNewTCB->pcTaskName[0]), \ - pxNewTCB->uxPriority, \ - (U32)pxNewTCB->pxStack, \ - ((U32)pxNewTCB->pxTopOfStack - (U32)pxNewTCB->pxStack) \ - ); \ - } -#else -#define traceTASK_CREATE(pxNewTCB) if (pxNewTCB != NULL) { \ - SEGGER_SYSVIEW_OnTaskCreate((U32)pxNewTCB); \ - SYSVIEW_AddTask((U32)pxNewTCB, \ - &(pxNewTCB->pcTaskName[0]), \ - pxNewTCB->uxPriority, \ - (U32)pxNewTCB->pxStack, \ - (U32)(pxNewTCB->pxStack-pxNewTCB->pxTopOfStack) \ - ); \ - } -#endif -#define traceTASK_PRIORITY_SET(pxTask, uxNewPriority) { \ - SEGGER_SYSVIEW_RecordU32x2(apiFastID_OFFSET+apiID_VTASKPRIORITYSET, \ - SEGGER_SYSVIEW_ShrinkId((U32)pxTCB), \ - uxNewPriority \ - ); \ - SYSVIEW_UpdateTask((U32)pxTask, \ - &(pxTask->pcTaskName[0]), \ - uxNewPriority, \ - (U32)pxTask->pxStack, \ - 0 \ - ); \ - } -// -// Define INCLUDE_xTaskGetIdleTaskHandle as 1 in FreeRTOSConfig.h to allow identification of Idle state. -// -// SMP FreeRTOS uses unpinned IDLE tasks, so sometimes IDEL0 runs on CPU1, IDLE1 runs on CPU0 and so on. -// So IDLE state detection based on 'xTaskGetIdleTaskHandle' does not work for SMP kernel. -// We could compare current task handle with every element of the array returned by 'xTaskGetIdleTaskHandle', -// but it deos not seem to be efficient enough to be worth of making code more complex and less readabl. -// So always use task name comparison mechanism for SMP kernel. -#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 && !defined(CONFIG_FREERTOS_SMP)) - #define traceTASK_SWITCHED_IN() if(prvGetTCBFromHandle(NULL) == xTaskGetIdleTaskHandle()) { \ - SEGGER_SYSVIEW_OnIdle(); \ - } else { \ - SEGGER_SYSVIEW_OnTaskStartExec((U32)prvGetTCBFromHandle(NULL)); \ - } -#else - #define traceTASK_SWITCHED_IN() { \ - if (memcmp(prvGetTCBFromHandle(NULL)->pcTaskName, "IDLE", 4) != 0) { \ - SEGGER_SYSVIEW_OnTaskStartExec((U32)prvGetTCBFromHandle(NULL)); \ - } else { \ - SEGGER_SYSVIEW_OnIdle(); \ - } \ - } -#endif - -#define traceMOVED_TASK_TO_READY_STATE(pxTCB) SEGGER_SYSVIEW_OnTaskStartReady((U32)pxTCB) -#define traceREADDED_TASK_TO_READY_STATE(pxTCB) - -#define traceMOVED_TASK_TO_DELAYED_LIST() SEGGER_SYSVIEW_OnTaskStopReady((U32)prvGetTCBFromHandle(NULL), (1u << 2)) -#define traceMOVED_TASK_TO_OVERFLOW_DELAYED_LIST() SEGGER_SYSVIEW_OnTaskStopReady((U32)prvGetTCBFromHandle(NULL), (1u << 2)) -#define traceMOVED_TASK_TO_SUSPENDED_LIST(pxTCB) SEGGER_SYSVIEW_OnTaskStopReady((U32)pxTCB, ((3u << 3) | 3)) - - -#define traceISR_EXIT_TO_SCHEDULER() SEGGER_SYSVIEW_RecordExitISRToScheduler() -#define traceISR_EXIT() SEGGER_SYSVIEW_RecordExitISR() -#define traceISR_ENTER(n) SEGGER_SYSVIEW_RecordEnterISR(n) - -/********************************************************************* -* -* API functions -* -********************************************************************** -*/ -#ifdef __cplusplus -extern "C" { -#endif -void SYSVIEW_AddTask (U32 xHandle, const char* pcTaskName, unsigned uxCurrentPriority, U32 pxStack, unsigned uStackHighWaterMark); -void SYSVIEW_UpdateTask (U32 xHandle, const char* pcTaskName, unsigned uxCurrentPriority, U32 pxStack, unsigned uStackHighWaterMark); -void SYSVIEW_DeleteTask (U32 xHandle); -void SYSVIEW_SendTaskInfo (U32 TaskID, const char* sName, unsigned Prio, U32 StackBase, unsigned StackSize); - -#ifdef __cplusplus -} -#endif - -#endif - -/*************************** End of file ****************************/ diff --git a/components/app_trace/sys_view/esp/SEGGER_RTT_esp.c b/components/app_trace/sys_view/esp/SEGGER_RTT_esp.c deleted file mode 100644 index fa93f452aa8..00000000000 --- a/components/app_trace/sys_view/esp/SEGGER_RTT_esp.c +++ /dev/null @@ -1,382 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "string.h" -#include "freertos/FreeRTOS.h" -#include "SEGGER_RTT.h" -#include "SEGGER_SYSVIEW.h" -#include "SEGGER_SYSVIEW_Conf.h" - -#include "esp_log.h" -#include "esp_cpu.h" -#include "esp_trace_port_transport.h" -#include "esp_trace_port_encoder.h" -#include "esp_trace_types.h" -#include "esp_private/startup_internal.h" -#include "adapters/adapter_encoder_sysview.h" - -const static char *TAG = "segger_rtt"; - -#define SYSVIEW_EVENTS_BUF_SZ 255U - -// size of down channel data buf -#define SYSVIEW_DOWN_BUF_SIZE 32 -#if CONFIG_SEGGER_SYSVIEW_BUF_WAIT_TMO == -1 -#define SEGGER_HOST_WAIT_TMO ESP_TRACE_TMO_INFINITE -#else -#define SEGGER_HOST_WAIT_TMO CONFIG_SEGGER_SYSVIEW_BUF_WAIT_TMO -#endif - -static uint8_t s_events_buf[SYSVIEW_EVENTS_BUF_SZ]; -static uint16_t s_events_buf_filled; -static uint8_t s_down_buf[SYSVIEW_DOWN_BUF_SIZE]; - -/** - * @brief Encoder reference for SEGGER RTT layer - * - * This maintains proper architectural layering: - * - SEGGER RTT is part of the SystemView encoder implementation - * - It accesses transport through the encoder's transport reference (s_encoder->tp) - * - NOT through global singleton (that would be a layer violation) - * - * Set by SEGGER_RTT_ESP_SetEncoder() during encoder init. - */ -static esp_trace_encoder_t *s_encoder = NULL; - -/********************************************************************* -* -* Public code -* -********************************************************************** -*/ - -/********************************************************************* -* -* SEGGER_RTT_ESP_SetEncoder() -* -* Function description -* Inject encoder handle from esp_trace adapter. -* This allows SEGGER RTT to access transport through the encoder's -* transport reference, maintaining proper architectural layering. -* -* Parameters -* encoder Pointer to encoder instance from esp_trace -* -* Return value -* 0 if successful, -1 if encoder is not initialized or missing required functions in transport. -*/ -int SEGGER_RTT_ESP_SetEncoder(esp_trace_encoder_t *encoder) -{ - /* Check if adapters have all required functions */ - if (!encoder || !encoder->ctx || - !encoder->vt->give_lock || - !encoder->vt->take_lock || - !encoder->tp->vt->down_buffer_config || - !encoder->tp->vt->write || - !encoder->tp->vt->flush_nolock || - !encoder->tp->vt->read || - !encoder->tp->vt->get_link_type) { - ESP_LOGE(TAG, "Encoder not initialized or missing required functions in transport"); - return -1; - } - - s_encoder = encoder; - - return 0; -} - -/********************************************************************* -* -* SEGGER_SYSVIEW_GetEncoder() -* -* Function description -* Returns the encoder handle for accessing transport functions. -* This is used by SEGGER_SYSVIEW_Config_FreeRTOS.c to access -* transport lock functions. -* -* Parameters -* None -* -* Return value -* Pointer to encoder instance, or NULL if not initialized. -*/ -esp_trace_encoder_t* SEGGER_SYSVIEW_GetEncoder(void) -{ - return s_encoder; -} - -/********************************************************************* -* -* SEGGER_RTT_ESP_GetDestCpu() -* -* Function description -* Gets the destination CPU from the encoder context. -* -* Parameters -* None -* -* Return value -* CPU ID (0 or 1) to trace -*/ -static int SEGGER_RTT_ESP_GetDestCpu(void) -{ - sysview_encoder_ctx_t *ctx = s_encoder->ctx; - return ctx->dest_cpu; -} - -/********************************************************************* -* -* SEGGER_RTT_ESP_FlushNoLock() -* -* Function description -* Flushes buffered events. -* -* Parameters -* min_sz Threshold for flushing data. If current filling level is above this value, data will be flushed. JTAG destinations only. -* tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinitely. -* -* Return value -* None. -*/ -void SEGGER_RTT_ESP_FlushNoLock(void) -{ - esp_err_t res; - - if (!s_encoder) { - ESP_LOGE(TAG, "Encoder not initialized"); - return; - } - - esp_trace_transport_t *tp = s_encoder->tp; - - if (s_events_buf_filled > 0) { - res = tp->vt->write(tp, s_events_buf, s_events_buf_filled, SEGGER_HOST_WAIT_TMO); - if (res != ESP_OK) { - ESP_LOGE(TAG, "Failed to write buffered events (%d)!", res); - } - } - // flush even if we failed to write buffered events, because no new events will be sent after STOP - res = tp->vt->flush_nolock(tp); - if (res != ESP_OK) { - ESP_LOGE(TAG, "Failed to flush buffered events (%d)!", res); - } - - s_events_buf_filled = 0; -} - -/********************************************************************* -* -* SEGGER_RTT_ESP_Flush() -* -* Function description -* Flushes buffered events. -* -* -* Return value -* None. -*/ -void SEGGER_RTT_ESP_Flush(void) -{ - SEGGER_SYSVIEW_LOCK(); - SEGGER_RTT_ESP_FlushNoLock(); - SEGGER_SYSVIEW_UNLOCK(); -} - -/********************************************************************* -* -* SEGGER_RTT_ReadNoLock() -* -* Function description -* Reads characters from SEGGER real-time-terminal control block -* which have been previously stored by the host. -* Do not lock against interrupts and multiple access. -* -* Parameters -* BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal"). -* pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to. -* BufferSize Size of the target application buffer. -* -* Return value -* Number of bytes that have been read. -*/ -unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) -{ - if (!s_encoder) { - return 0; - } - size_t size = BufferSize; - esp_err_t res = s_encoder->tp->vt->read(s_encoder->tp, pData, &size, 0); - return res != ESP_OK ? 0 : size; -} - -/********************************************************************* -* -* SEGGER_RTT_WriteSkipNoLock -* -* Function description -* Stores a specified number of characters in SEGGER RTT -* control block which is then read by the host. -* SEGGER_RTT_WriteSkipNoLock does not lock the application and -* skips all data, if the data does not fit into the buffer. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). -* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. -* NumBytes Number of bytes to be stored in the SEGGER RTT control block. -* -* Return value -* Number of bytes which have been stored in the "Up"-buffer. -* -* Notes -* (1) If there is not enough space in the "Up"-buffer, all data is dropped. -* (2) For performance reasons this function does not call Init() -* and may only be called after RTT has been initialized. -* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. -*/ -unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) -{ - if (!s_encoder) { - return 0; // Encoder is not initialized - } - - esp_trace_transport_t *tp = s_encoder->tp; - uint8_t *pbuf = (uint8_t *)pBuffer; - uint8_t event_id = *pbuf; - - if (tp->vt->get_link_type(tp) == ESP_TRACE_LINK_UART) { - int dest_cpu = SEGGER_RTT_ESP_GetDestCpu(); - if ( - (dest_cpu != esp_cpu_get_core_id()) && - ( - (event_id == SYSVIEW_EVTID_ISR_ENTER) || - (event_id == SYSVIEW_EVTID_ISR_EXIT) || - (event_id == SYSVIEW_EVTID_TASK_START_EXEC) || - (event_id == SYSVIEW_EVTID_TASK_STOP_EXEC) || - (event_id == SYSVIEW_EVTID_TASK_START_READY) || - (event_id == SYSVIEW_EVTID_TASK_STOP_READY) || - (event_id == SYSVIEW_EVTID_MARK_START) || - (event_id == SYSVIEW_EVTID_MARK_STOP) || - (event_id == SYSVIEW_EVTID_TIMER_ENTER) || - (event_id == SYSVIEW_EVTID_TIMER_EXIT) || - (event_id == SYSVIEW_EVTID_STACK_INFO) || - (event_id == SYSVIEW_EVTID_MODULEDESC) - ) - ) { - return NumBytes; - } - - // This is workaround for SystemView! - // Without this line SystemView will hangs on when heap tracing enabled. - if (event_id == SYSVIEW_EVTID_MODULEDESC) { - return NumBytes; - } - } - - if (NumBytes > SYSVIEW_EVENTS_BUF_SZ) { - ESP_LOGE(TAG, "Too large event %u bytes!", NumBytes); - return 0; - } - if (tp->vt->get_link_type(tp) == ESP_TRACE_LINK_DEBUG_PROBE) { - if (esp_cpu_get_core_id()) { // dual core specific code - // use the highest - 1 bit of event ID to indicate core ID - // the highest bit can not be used due to event ID encoding method - // this reduces supported ID range to [0..63] (for 1 byte IDs) plus [128..16383] (for 2 bytes IDs) - if (*pbuf & 0x80) { // 2 bytes ID - *(pbuf + 1) |= (1 << 6); - } else if (NumBytes != 10 || *pbuf != 0) { // ignore sync sequence - *pbuf |= (1 << 6); - } - } - - if (s_events_buf_filled + NumBytes > SYSVIEW_EVENTS_BUF_SZ) { - - esp_err_t res = tp->vt->write(tp, s_events_buf, s_events_buf_filled, SEGGER_HOST_WAIT_TMO); - if (res != ESP_OK) { - return 0; // skip current data buffer only, accumulated events are kept - } - s_events_buf_filled = 0; - } - } - memcpy(&s_events_buf[s_events_buf_filled], pBuffer, NumBytes); - s_events_buf_filled += NumBytes; - - if (tp->vt->get_link_type(tp) == ESP_TRACE_LINK_UART) { - esp_err_t res = tp->vt->write(tp, pBuffer, NumBytes, SEGGER_HOST_WAIT_TMO); - if (res != ESP_OK) { - return 0; // skip current data buffer only, accumulated events are kept - } - s_events_buf_filled = 0; - } - - if (event_id == SYSVIEW_EVTID_TRACE_STOP) { - SEGGER_RTT_ESP_FlushNoLock(); - } - return NumBytes; -} - -/********************************************************************* -* -* SEGGER_RTT_ConfigUpBuffer -* -* Function description -* Run-time configuration of a specific up-buffer (T->H). -* Buffer to be configured is specified by index. -* This includes: Buffer address, size, name, flags, ... -* -* Parameters -* BufferIndex Index of the buffer to configure. -* sName Pointer to a constant name string. -* pBuffer Pointer to a buffer to be used. -* BufferSize Size of the buffer. -* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). -* -* Return value -* >= 0 - O.K. -* < 0 - Error -* -* Additional information -* Buffer 0 is configured on compile-time. -* May only be called once per buffer. -* Buffer name and flags can be reconfigured using the appropriate functions. -*/ -int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) -{ - s_events_buf_filled = 0; - return 0; -} - -/********************************************************************* -* -* SEGGER_RTT_ConfigDownBuffer -* -* Function description -* Run-time configuration of a specific down-buffer (H->T). -* Buffer to be configured is specified by index. -* This includes: Buffer address, size, name, flags, ... -* -* Parameters -* BufferIndex Index of the buffer to configure. -* sName Pointer to a constant name string. -* pBuffer Pointer to a buffer to be used. -* BufferSize Size of the buffer. -* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). -* -* Return value -* >= 0 O.K. -* < 0 Error -* -* Additional information -* Buffer 0 is configured on compile-time. -* May only be called once per buffer. -* Buffer name and flags can be reconfigured using the appropriate functions. -*/ -int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) -{ - if (!s_encoder) { - return -1; - } - return s_encoder->tp->vt->down_buffer_config(s_encoder->tp, s_down_buf, sizeof(s_down_buf)); -} diff --git a/components/app_trace/sys_view/ext/heap_trace_module.c b/components/app_trace/sys_view/ext/heap_trace_module.c deleted file mode 100644 index fc149c2e491..00000000000 --- a/components/app_trace/sys_view/ext/heap_trace_module.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2018-2025 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include -#include -#include "SEGGER_SYSVIEW.h" -#include "SEGGER_RTT.h" -#include "esp_app_trace.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" - -#include "esp_log.h" -const static char *TAG = "sysview_heap_trace"; - -#ifdef CONFIG_HEAP_TRACING_STACK_DEPTH -#define CALLSTACK_SIZE CONFIG_HEAP_TRACING_STACK_DEPTH -#else -#define CALLSTACK_SIZE 0 -#endif - -static SEGGER_SYSVIEW_MODULE s_esp_sysview_heap_module = { - .sModule = "M=ESP32 SystemView Heap Tracing Module", - .NumEvents = 2, -}; - -static bool s_mod_registered; - -esp_err_t esp_sysview_heap_trace_start(uint32_t tmo) -{ - uint32_t tmo_ticks = tmo / (1000 * portTICK_PERIOD_MS); - - ESP_EARLY_LOGV(TAG, "%s", __func__); - do { - if (tmo != (uint32_t) -1) { - // Currently timeout implementation is simple and has granularity of 1 OS tick, - // so just count down the number of times to call vTaskDelay - if (tmo_ticks-- == 0) { - return ESP_ERR_TIMEOUT; - } - } - vTaskDelay(1); - } while (!SEGGER_SYSVIEW_Started()); - - SEGGER_SYSVIEW_RegisterModule(&s_esp_sysview_heap_module); - s_mod_registered = true; - return ESP_OK; -} - -esp_err_t esp_sysview_heap_trace_stop(void) -{ - ESP_EARLY_LOGV(TAG, "%s", __func__); - SEGGER_RTT_ESP_Flush(); - return ESP_OK; -} - -void esp_sysview_heap_trace_alloc(const void *addr, uint32_t size, const void *callers) -{ - U8 aPacket[SEGGER_SYSVIEW_INFO_SIZE + (2 + CALLSTACK_SIZE)*SEGGER_SYSVIEW_QUANTA_U32]; - U8* pPayload = SEGGER_SYSVIEW_PREPARE_PACKET(aPacket); - U32 *calls = (U32 *)callers; - - if (!s_mod_registered) { - return; - } - ESP_EARLY_LOGV(TAG, "%s %p %lu", __func__, addr, size); - pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, (U32)addr); - pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, size); - for (int i = 0; i < CALLSTACK_SIZE; i++) { - pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, calls[i]); - } - SEGGER_SYSVIEW_SendPacket(&aPacket[0], pPayload, s_esp_sysview_heap_module.EventOffset + 0); -} - -void esp_sysview_heap_trace_free(const void *addr, const void *callers) -{ - U8 aPacket[SEGGER_SYSVIEW_INFO_SIZE + (1 + CALLSTACK_SIZE)*SEGGER_SYSVIEW_QUANTA_U32]; - U8* pPayload = SEGGER_SYSVIEW_PREPARE_PACKET(aPacket); - U32 *calls = (U32 *)callers; - - if (!s_mod_registered) { - return; - } - ESP_EARLY_LOGV(TAG, "%s %p", __func__, addr); - pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, (U32)addr); - for (int i = 0; i < CALLSTACK_SIZE; i++) { - pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, calls[i]); - } - SEGGER_SYSVIEW_SendPacket(&aPacket[0], pPayload, s_esp_sysview_heap_module.EventOffset + 1); -} diff --git a/components/app_trace/sys_view/ext/logging.c b/components/app_trace/sys_view/ext/logging.c deleted file mode 100644 index d6b7ee80d1e..00000000000 --- a/components/app_trace/sys_view/ext/logging.c +++ /dev/null @@ -1,26 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2018-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include -#include -#include -#include "SEGGER_SYSVIEW_Int.h" -#include "freertos/FreeRTOS.h" - -static portMUX_TYPE s_log_mutex = portMUX_INITIALIZER_UNLOCKED; - -int esp_sysview_vprintf(const char * format, va_list args) -{ - static char log_buffer[SEGGER_SYSVIEW_MAX_STRING_LEN]; - - portENTER_CRITICAL(&s_log_mutex); - size_t len = vsnprintf(log_buffer, sizeof(log_buffer), format, args); - if (len > sizeof(log_buffer) - 1) { - log_buffer[sizeof(log_buffer) - 1] = 0; - } - SEGGER_SYSVIEW_Print(log_buffer); - portEXIT_CRITICAL(&s_log_mutex); - return len; -} diff --git a/components/app_trace/test_apps/.build-test-rules.yml b/components/app_trace/test_apps/.build-test-rules.yml index fbbd2d55b1d..aa5223768ae 100644 --- a/components/app_trace/test_apps/.build-test-rules.yml +++ b/components/app_trace/test_apps/.build-test-rules.yml @@ -2,11 +2,7 @@ components/app_trace/test_apps: depends_components: - - app_trace - - esp_timer - - soc - - esp_hw_support - - esp_driver_uart + - esp_trace - esp_driver_gptimer disable: - if: IDF_TARGET in ["esp32h21", "esp32h4"] diff --git a/components/app_trace/test_apps/README.md b/components/app_trace/test_apps/README.md index ecca19c3a70..4b730b74b5a 100644 --- a/components/app_trace/test_apps/README.md +++ b/components/app_trace/test_apps/README.md @@ -8,9 +8,4 @@ To build and run this test app for app_trace related tests: IDF_TARGET=esp32 idf.py @app_trace build flash monitor ``` -To build and run this test app for SystemView related tests: -```bash -IDF_TARGET=esp32 idf.py @sysview build flash monitor -``` - -`@app_trace` and `@sysview` arguments apply additional `idf.py` options, from [app_trace](app_trace) and [sysview](sysview) files. +`@app_trace` argument apply additional `idf.py` options, from [app_trace](app_trace) and file. diff --git a/components/app_trace/test_apps/main/test_trace.c b/components/app_trace/test_apps/main/test_trace.c index 17488215225..6c11afe16d1 100644 --- a/components/app_trace/test_apps/main/test_trace.c +++ b/components/app_trace/test_apps/main/test_trace.c @@ -16,10 +16,10 @@ #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" #include "freertos/task.h" +#include "esp_app_trace.h" #define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE #include "esp_log.h" -#include "esp_app_trace.h" #define ESP_APPTRACE_TEST_USE_PRINT_LOCK 0 #define ESP_APPTRACE_TEST_PRN_WRERR_MAX 5 @@ -65,7 +65,6 @@ const static char *TAG = "esp_apptrace_test"; #define ESP_APPTRACE_TEST_LOGV( format, ... ) ESP_APPTRACE_TEST_LOG_LEVEL(V, ESP_LOG_VERBOSE, format, ##__VA_ARGS__) #define ESP_APPTRACE_TEST_LOGO( format, ... ) ESP_APPTRACE_TEST_LOG_LEVEL(E, ESP_LOG_NONE, format, ##__VA_ARGS__) -#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW == 0 #define ESP_APPTRACE_TEST_WRITE(_b_, _s_) esp_apptrace_write(_b_, _s_, ESP_APPTRACE_TMO_INFINITE) #define ESP_APPTRACE_TEST_WRITE_FROM_ISR(_b_, _s_) esp_apptrace_write(_b_, _s_, 0UL) #define ESP_APPTRACE_TEST_WRITE_NOWAIT(_b_, _s_) esp_apptrace_write(_b_, _s_, 0) @@ -693,233 +692,3 @@ TEST_CASE("Log trace test (2 tasks)", "[trace][ignore]") xSemaphoreTake(arg2.done, portMAX_DELAY); vSemaphoreDelete(arg2.done); } - -#else // #if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW == 0 - -typedef struct { - gptimer_handle_t gptimer; - uint32_t period; - int flags; - uint32_t id; -} esp_sysviewtrace_timer_arg_t; - -typedef struct { - SemaphoreHandle_t done; - SemaphoreHandle_t *sync; - esp_sysviewtrace_timer_arg_t *timer; - uint32_t work_count; - uint32_t sleep_tmo; - uint32_t id; -} esp_sysviewtrace_task_arg_t; - -static bool esp_sysview_test_timer_isr(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_ctx) -{ - esp_sysviewtrace_timer_arg_t *tim_arg = (esp_sysviewtrace_timer_arg_t *)user_ctx; - (void) tim_arg; - return false; -} - -static void esp_sysviewtrace_test_task(void *p) -{ - esp_sysviewtrace_task_arg_t *arg = (esp_sysviewtrace_task_arg_t *) p; - volatile uint32_t tmp = 0; - printf("%p: run sysview task\n", xTaskGetCurrentTaskHandle()); - - if (arg->timer) { - gptimer_alarm_config_t alarm_config = { - .reload_count = 0, - .alarm_count = arg->timer->period, - .flags.auto_reload_on_alarm = true, - }; - gptimer_event_callbacks_t cbs = { - .on_alarm = esp_sysview_test_timer_isr, - }; - TEST_ESP_OK(gptimer_register_event_callbacks(arg->timer->gptimer, &cbs, arg->timer)); - TEST_ESP_OK(gptimer_enable(arg->timer->gptimer)); - TEST_ESP_OK(gptimer_set_alarm_action(arg->timer->gptimer, &alarm_config)); - TEST_ESP_OK(gptimer_start(arg->timer->gptimer)); - } - - int i = 0; - while (1) { - static uint32_t count; - printf("%" PRIu32, arg->id); - if ((++count % 80) == 0) { - printf("\n"); - } - if (arg->sync) { - xSemaphoreTake(*arg->sync, portMAX_DELAY); - } - for (uint32_t k = 0; k < arg->work_count; k++) { - tmp++; - } - vTaskDelay(arg->sleep_tmo / portTICK_PERIOD_MS); - i++; - if (arg->sync) { - xSemaphoreGive(*arg->sync); - } - } - ESP_APPTRACE_TEST_LOGI("%p: finished", xTaskGetCurrentTaskHandle()); - - xSemaphoreGive(arg->done); - vTaskDelay(1); - vTaskDelete(NULL); -} - -TEST_CASE("SysView trace test 1", "[trace][ignore]") -{ - TaskHandle_t thnd; - - esp_sysviewtrace_timer_arg_t tim_arg1 = { - .flags = ESP_INTR_FLAG_SHARED, - .id = 0, - .period = 500, - }; - esp_sysviewtrace_task_arg_t arg1 = { - .done = xSemaphoreCreateBinary(), - .sync = NULL, - .work_count = 10000, - .sleep_tmo = 1, - .timer = &tim_arg1, - .id = 0, - }; - esp_sysviewtrace_timer_arg_t tim_arg2 = { - .flags = 0, - .id = 1, - .period = 100, - }; - esp_sysviewtrace_task_arg_t arg2 = { - .done = xSemaphoreCreateBinary(), - .sync = NULL, - .work_count = 10000, - .sleep_tmo = 1, - .timer = &tim_arg2, - .id = 1, - }; - - gptimer_config_t timer_config = { - .clk_src = GPTIMER_CLK_SRC_DEFAULT, - .direction = GPTIMER_COUNT_UP, - .resolution_hz = 1000000, - }; - timer_config.flags.intr_shared = (tim_arg1.flags & ESP_INTR_FLAG_SHARED) == ESP_INTR_FLAG_SHARED; - TEST_ESP_OK(gptimer_new_timer(&timer_config, &tim_arg1.gptimer)); - timer_config.flags.intr_shared = (tim_arg2.flags & ESP_INTR_FLAG_SHARED) == ESP_INTR_FLAG_SHARED; - TEST_ESP_OK(gptimer_new_timer(&timer_config, &tim_arg2.gptimer)); - - xTaskCreatePinnedToCore(esp_sysviewtrace_test_task, "svtrace0", 2048, &arg1, 3, &thnd, 0); - ESP_APPTRACE_TEST_LOGI("Created task %p", thnd); -#if CONFIG_FREERTOS_UNICORE == 0 - xTaskCreatePinnedToCore(esp_sysviewtrace_test_task, "svtrace1", 2048, &arg2, 5, &thnd, 1); -#else - xTaskCreatePinnedToCore(esp_sysviewtrace_test_task, "svtrace1", 2048, &arg2, 5, &thnd, 0); -#endif - ESP_APPTRACE_TEST_LOGI("Created task %p", thnd); - - xSemaphoreTake(arg1.done, portMAX_DELAY); - vSemaphoreDelete(arg1.done); - xSemaphoreTake(arg2.done, portMAX_DELAY); - vSemaphoreDelete(arg2.done); - TEST_ESP_OK(gptimer_stop(tim_arg1.gptimer)); - TEST_ESP_OK(gptimer_disable(tim_arg1.gptimer)); - TEST_ESP_OK(gptimer_del_timer(tim_arg1.gptimer)); - TEST_ESP_OK(gptimer_stop(tim_arg2.gptimer)); - TEST_ESP_OK(gptimer_disable(tim_arg2.gptimer)); - TEST_ESP_OK(gptimer_del_timer(tim_arg2.gptimer)); -} - -TEST_CASE("SysView trace test 2", "[trace][ignore]") -{ - TaskHandle_t thnd; - - esp_sysviewtrace_timer_arg_t tim_arg1 = { - .flags = ESP_INTR_FLAG_SHARED, - .id = 0, - .period = 500, - }; - esp_sysviewtrace_task_arg_t arg1 = { - .done = xSemaphoreCreateBinary(), - .sync = NULL, - .work_count = 10000, - .sleep_tmo = 1, - .timer = &tim_arg1, - .id = 0, - }; - esp_sysviewtrace_timer_arg_t tim_arg2 = { - .flags = 0, - .id = 1, - .period = 100, - }; - esp_sysviewtrace_task_arg_t arg2 = { - .done = xSemaphoreCreateBinary(), - .sync = NULL, - .work_count = 10000, - .sleep_tmo = 1, - .timer = &tim_arg2, - .id = 1, - }; - - SemaphoreHandle_t test_sync = xSemaphoreCreateBinary(); - xSemaphoreGive(test_sync); - esp_sysviewtrace_task_arg_t arg3 = { - .done = xSemaphoreCreateBinary(), - .sync = &test_sync, - .work_count = 1000, - .sleep_tmo = 1, - .timer = NULL, - .id = 2, - }; - esp_sysviewtrace_task_arg_t arg4 = { - .done = xSemaphoreCreateBinary(), - .sync = &test_sync, - .work_count = 10000, - .sleep_tmo = 1, - .timer = NULL, - .id = 3, - }; - - gptimer_config_t timer_config = { - .clk_src = GPTIMER_CLK_SRC_DEFAULT, - .direction = GPTIMER_COUNT_UP, - .resolution_hz = 1000000, - }; - timer_config.flags.intr_shared = (tim_arg1.flags & ESP_INTR_FLAG_SHARED) == ESP_INTR_FLAG_SHARED; - TEST_ESP_OK(gptimer_new_timer(&timer_config, &tim_arg1.gptimer)); - timer_config.flags.intr_shared = (tim_arg2.flags & ESP_INTR_FLAG_SHARED) == ESP_INTR_FLAG_SHARED; - TEST_ESP_OK(gptimer_new_timer(&timer_config, &tim_arg2.gptimer)); - - xTaskCreatePinnedToCore(esp_sysviewtrace_test_task, "svtrace0", 2048, &arg1, 3, &thnd, 0); - printf("Created task %p\n", thnd); -#if CONFIG_FREERTOS_UNICORE == 0 - xTaskCreatePinnedToCore(esp_sysviewtrace_test_task, "svtrace1", 2048, &arg2, 4, &thnd, 1); -#else - xTaskCreatePinnedToCore(esp_sysviewtrace_test_task, "svtrace1", 2048, &arg2, 4, &thnd, 0); -#endif - printf("Created task %p\n", thnd); - - xTaskCreatePinnedToCore(esp_sysviewtrace_test_task, "svsync0", 2048, &arg3, 3, &thnd, 0); - printf("Created task %p\n", thnd); -#if CONFIG_FREERTOS_UNICORE == 0 - xTaskCreatePinnedToCore(esp_sysviewtrace_test_task, "svsync1", 2048, &arg4, 5, &thnd, 1); -#else - xTaskCreatePinnedToCore(esp_sysviewtrace_test_task, "svsync1", 2048, &arg4, 5, &thnd, 0); -#endif - printf("Created task %p\n", thnd); - - xSemaphoreTake(arg1.done, portMAX_DELAY); - vSemaphoreDelete(arg1.done); - xSemaphoreTake(arg2.done, portMAX_DELAY); - vSemaphoreDelete(arg2.done); - xSemaphoreTake(arg3.done, portMAX_DELAY); - vSemaphoreDelete(arg3.done); - xSemaphoreTake(arg4.done, portMAX_DELAY); - vSemaphoreDelete(arg4.done); - vSemaphoreDelete(test_sync); - TEST_ESP_OK(gptimer_stop(tim_arg1.gptimer)); - TEST_ESP_OK(gptimer_disable(tim_arg1.gptimer)); - TEST_ESP_OK(gptimer_del_timer(tim_arg1.gptimer)); - TEST_ESP_OK(gptimer_stop(tim_arg2.gptimer)); - TEST_ESP_OK(gptimer_disable(tim_arg2.gptimer)); - TEST_ESP_OK(gptimer_del_timer(tim_arg2.gptimer)); -} -#endif // CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW == 0 diff --git a/components/app_trace/test_apps/sdkconfig.ci.sysview b/components/app_trace/test_apps/sdkconfig.ci.sysview deleted file mode 100644 index 73ca998c6cd..00000000000 --- a/components/app_trace/test_apps/sdkconfig.ci.sysview +++ /dev/null @@ -1,3 +0,0 @@ -CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW=y -CONFIG_ESP_TRACE_TRANSPORT_APPTRACE=y -CONFIG_APPTRACE_DEST_JTAG=y diff --git a/components/app_trace/test_apps/sysview b/components/app_trace/test_apps/sysview deleted file mode 100644 index 88ca4007694..00000000000 --- a/components/app_trace/test_apps/sysview +++ /dev/null @@ -1 +0,0 @@ --DSDKCONFIG_DEFAULTS="sdkconfig.defaults;sdkconfig.ci.sysview" -B build/sysview -DSDKCONFIG=build/sysview/sdkconfig diff --git a/components/esp_hw_support/intr_alloc.c b/components/esp_hw_support/intr_alloc.c index 942e681c4fe..df10ef47363 100644 --- a/components/esp_hw_support/intr_alloc.c +++ b/components/esp_hw_support/intr_alloc.c @@ -481,7 +481,7 @@ static void ESP_INTR_IRAM_ATTR shared_intr_isr(void *arg) esp_os_exit_critical_isr(&spinlock); } -#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW +#if CONFIG_ESP_TRACE_ENABLE //Common non-shared isr handler wrapper. static void ESP_INTR_IRAM_ATTR non_shared_intr_isr(void *arg) { @@ -489,7 +489,7 @@ static void ESP_INTR_IRAM_ATTR non_shared_intr_isr(void *arg) esp_os_enter_critical_isr(&spinlock); traceISR_ENTER(ns_isr_arg->source + ETS_INTERNAL_INTR_SOURCE_OFF); // FIXME: can we call ISR and check os_task_switch_is_pended() after releasing spinlock? - // when CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW = 0 ISRs for non-shared IRQs are called without spinlock + // when CONFIG_ESP_TRACE_LIB_NONE is set ISRs for non-shared IRQs are called without spinlock ns_isr_arg->isr(ns_isr_arg->isr_arg); // check if we will return to scheduler or to interrupted task after ISR if (!os_task_switch_is_pended(esp_cpu_get_core_id())) { @@ -631,7 +631,7 @@ esp_err_t esp_intr_alloc_intrstatus_bind(int source, int flags, uint32_t intrsta //Mark as unusable for other interrupt sources. This is ours now! vd->flags = VECDESC_FL_NONSHARED; if (handler) { -#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW +#if CONFIG_ESP_TRACE_ENABLE non_shared_isr_arg_t *ns_isr_arg = heap_caps_malloc(sizeof(non_shared_isr_arg_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); if (!ns_isr_arg) { esp_os_exit_critical(&spinlock); @@ -831,7 +831,7 @@ static esp_err_t intr_free_for_current_cpu(intr_handle_t handle) if ((handle->vector_desc->flags & VECDESC_FL_NONSHARED) || free_shared_vector) { ESP_EARLY_LOGV(TAG, "esp_intr_free: Disabling int, killing handler"); -#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW +#if CONFIG_ESP_TRACE_ENABLE if (!free_shared_vector) { void *isr_arg = esp_cpu_intr_get_handler_arg(handle->vector_desc->intno); if (isr_arg) { diff --git a/components/esp_trace/CMakeLists.txt b/components/esp_trace/CMakeLists.txt index f32c0d6d8d4..1e26e6ce7fb 100644 --- a/components/esp_trace/CMakeLists.txt +++ b/components/esp_trace/CMakeLists.txt @@ -14,11 +14,6 @@ if(CONFIG_ESP_TRACE_ENABLE) if(CONFIG_ESP_TRACE_TRANSPORT_APPTRACE) list(APPEND srcs "adapters/transport/adapter_transport_apptrace.c") endif() - - if(CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW) - list(APPEND srcs "adapters/encoder/adapter_encoder_sysview.c") - endif() - endif() set(includes diff --git a/components/esp_trace/Kconfig b/components/esp_trace/Kconfig index b6f7ec9a9bc..944ac322fb0 100644 --- a/components/esp_trace/Kconfig +++ b/components/esp_trace/Kconfig @@ -6,9 +6,6 @@ menu "ESP Trace Configuration" help Select the trace library to use. - config ESP_TRACE_LIB_SEGGER_SYSVIEW - bool "SEGGER SystemView" - config ESP_TRACE_LIB_EXTERNAL bool "External library from component registry" help @@ -25,12 +22,9 @@ menu "ESP Trace Configuration" config ESP_TRACE_LIB_NAME string - default "sysview" if ESP_TRACE_LIB_SEGGER_SYSVIEW default "ext" if ESP_TRACE_LIB_EXTERNAL default "none" if ESP_TRACE_LIB_NONE - rsource "$IDF_PATH/components/app_trace/sys_view/Kconfig.sysview" - choice ESP_TRACE_TRANSPORT prompt "Trace transport" default ESP_TRACE_TRANSPORT_NONE diff --git a/components/esp_trace/adapters/encoder/adapter_encoder_sysview.c b/components/esp_trace/adapters/encoder/adapter_encoder_sysview.c deleted file mode 100644 index 6061c4110d6..00000000000 --- a/components/esp_trace/adapters/encoder/adapter_encoder_sysview.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include -#include -#include - -#include "esp_err.h" -#include "esp_heap_caps.h" -#include "esp_trace_types.h" -#include "esp_trace_registry.h" -#include "esp_trace_port_encoder.h" -#include "esp_trace_port_transport.h" -#include "adapters/adapter_encoder_sysview.h" -#include "esp_trace_util.h" -#include "esp_sysview_trace.h" -#include "SEGGER_SYSVIEW.h" -#include "SEGGER_RTT.h" - -/* - * This adapter is used to create a public system-wide APIs for SystemView. - * All encoding and transport operations are done by SystemView component. (SEGGER_RTT_esp.c) - */ - -#define SYSVIEW_FLUSH_TMO_US (1000 * 1000) /* 1second */ -#define SYSVIEW_FLUSH_THRESH 0 - -/** - * @brief Initializes sysview encoder. - * This function is called for each core. - * Adapter implementations do NOT need their own multi-core protection. Core does it for them. - * - * @param enc Pointer to the encoder structure. Must not be NULL. - * @param enc_cfg Pointer to the encoder configuration. Can be NULL for defaults. - * - * @return ESP_OK on success, otherwise \see esp_err_t - */ -static esp_err_t init(esp_trace_encoder_t *enc, const void *enc_cfg) -{ - static bool initialized = false; - - if (!enc) { - return ESP_ERR_INVALID_ARG; - } - - if (initialized) { - return ESP_OK; - } - - const esp_trace_sysview_config_t *cfg = enc_cfg; - int dest_cpu = 0; // Default to CPU0 - - if (cfg) { - dest_cpu = cfg->dest_cpu; - } - - // Allocate and initialize encoder context - sysview_encoder_ctx_t *ctx = heap_caps_calloc(1, sizeof(*ctx), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); - if (!ctx) { - return ESP_ERR_NO_MEM; - } - - /* Segger Sysview needs locking mechanism. */ - esp_trace_lock_init(&ctx->lock); - ctx->dest_cpu = dest_cpu; - enc->ctx = ctx; - - if (SEGGER_RTT_ESP_SetEncoder(enc) != 0) { - heap_caps_free(ctx); - enc->ctx = NULL; - return ESP_ERR_NOT_SUPPORTED; - } - - /* Configure transport for SystemView requirements */ - if (enc->tp->vt->set_config) { - uint32_t flush_tmo = SYSVIEW_FLUSH_TMO_US; - uint32_t flush_thresh = SYSVIEW_FLUSH_THRESH; - uint32_t header_size = 2; /* SystemView uses 2-byte (16-bit) trace headers */ - enc->tp->vt->set_config(enc->tp, ESP_TRACE_TRANSPORT_CFG_FLUSH_TMO, &flush_tmo); - enc->tp->vt->set_config(enc->tp, ESP_TRACE_TRANSPORT_CFG_FLUSH_THRESH, &flush_thresh); - enc->tp->vt->set_config(enc->tp, ESP_TRACE_TRANSPORT_CFG_HEADER_SIZE, &header_size); - } - - SEGGER_SYSVIEW_Conf(); - - initialized = true; - - return ESP_OK; -} - -/** - * @brief Panic handler - * - * Called during system panic to finalize encoder state. - * - * @param enc Pointer to the encoder structure. Must not be NULL. - * @param info Panic information - */ -static void panic_handler(esp_trace_encoder_t *enc, const void *info) -{ - (void)enc; - (void)info; - - SEGGER_RTT_ESP_Flush(); -} - -/** - * @brief Takes the lock of sysview encoder. - * - * @param enc Pointer to the encoder structure. Must not be NULL. - * @param tmo Timeout for the operation (in us). - */ -static unsigned int take_lock(esp_trace_encoder_t *enc, uint32_t tmo_us) -{ - sysview_encoder_ctx_t *ctx = enc->ctx; - esp_trace_lock_take(&ctx->lock, tmo_us); - - return ctx->lock.int_state; -} - -/** - * @brief Gives the lock of sysview encoder. - * - * @param enc Pointer to the encoder structure. Must not be NULL. - * @param int_state The interrupt state. - */ -static void give_lock(esp_trace_encoder_t *enc, unsigned int_state) -{ - sysview_encoder_ctx_t *ctx = enc->ctx; - - // Restore interrupt state before releasing lock - ctx->lock.int_state = int_state; - esp_trace_lock_give(&ctx->lock); -} - -/** - * @brief Sysview encoder vtable. - */ -static const esp_trace_encoder_vtable_t s_sysview_vt = { - .init = init, - .panic_handler = panic_handler, - .take_lock = take_lock, - .give_lock = give_lock, -}; - -ESP_TRACE_REGISTER_ENCODER("sysview", &s_sysview_vt); diff --git a/components/esp_trace/include/adapters/adapter_encoder_sysview.h b/components/esp_trace/include/adapters/adapter_encoder_sysview.h deleted file mode 100644 index cd367324ccd..00000000000 --- a/components/esp_trace/include/adapters/adapter_encoder_sysview.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#pragma once - -#include "esp_trace_util.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief SystemView encoder configuration - */ -typedef struct { - /** - * @brief CPU to trace (0 or 1) - * - * Determines which CPU's events are captured by SystemView. - * Only relevant when using UART apptrace transport. - * - * - 0: Capture events from CPU0 (Pro CPU) - * - 1: Capture events from CPU1 (App CPU) - * - * @note This parameter is ignored for single-core systems - * @note This parameter is ignored when using JTAG transport - */ - int dest_cpu; -} esp_trace_sysview_config_t; - -/** - * @brief SystemView encoder context structure - * - * This structure is shared between the sysview adapter and the SEGGER RTT layer - * to allow proper access to encoder-specific configuration. - */ -typedef struct { - int dest_cpu; ///< CPU to trace (0 or 1) - esp_trace_lock_t lock; ///< Encoder lock -} sysview_encoder_ctx_t; - -#ifdef __cplusplus -} -#endif diff --git a/components/esp_trace/include/esp_trace_freertos.h b/components/esp_trace/include/esp_trace_freertos.h index fc8d75c89db..41175d92386 100644 --- a/components/esp_trace/include/esp_trace_freertos.h +++ b/components/esp_trace/include/esp_trace_freertos.h @@ -14,14 +14,10 @@ * This header provides a unified interface for FreeRTOS tracing. * It dispatches to the appropriate implementation based on configuration: * - * - CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW: Uses SEGGER SystemView * - CONFIG_ESP_TRACE_LIB_EXTERNAL: Uses external component's implementation * (external component must provide esp_trace_freertos_impl.h see components/esp_trace/README.md for more details) */ -#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW -#include "SEGGER_SYSVIEW_FreeRTOS.h" -#undef INLINE /* to avoid redefinition */ -#elif CONFIG_ESP_TRACE_LIB_EXTERNAL +#if CONFIG_ESP_TRACE_LIB_EXTERNAL #include "esp_trace_freertos_impl.h" #endif diff --git a/components/esp_trace/linker.lf b/components/esp_trace/linker.lf index ba230f2034f..b2dbeec9304 100644 --- a/components/esp_trace/linker.lf +++ b/components/esp_trace/linker.lf @@ -6,8 +6,6 @@ entries: esp_trace_core (noflash) esp_trace_registry (noflash) port_utils (noflash) - if ESP_TRACE_LIB_SEGGER_SYSVIEW: - adapter_encoder_sysview (noflash) if ESP_TRACE_TRANSPORT_APPTRACE: adapter_transport_apptrace (noflash) diff --git a/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/include/freertos/portmacro.h b/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/include/freertos/portmacro.h index b017c5105da..5928bc3154b 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/include/freertos/portmacro.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/include/freertos/portmacro.h @@ -401,7 +401,7 @@ bool xPortcheckValidStackMem(const void *ptr); // --------------------- App-Trace ------------------------- -#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW +#if CONFIG_ESP_TRACE_ENABLE extern volatile BaseType_t xPortSwitchFlag; #define os_task_switch_is_pended(_cpu_) (xPortSwitchFlag) #else diff --git a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/portmacro.h b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/portmacro.h index a460e179ca4..2c59f7b5737 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/portmacro.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/portmacro.h @@ -421,7 +421,7 @@ bool xPortcheckValidStackMem(const void *ptr); // --------------------- App-Trace ------------------------- -#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW +#if CONFIG_ESP_TRACE_ENABLE extern volatile BaseType_t xPortSwitchFlag; #define os_task_switch_is_pended(_cpu_) (xPortSwitchFlag) #else diff --git a/components/freertos/FreeRTOS-Kernel/portable/riscv/include/freertos/portmacro.h b/components/freertos/FreeRTOS-Kernel/portable/riscv/include/freertos/portmacro.h index a5b7b1b914d..08c75032407 100644 --- a/components/freertos/FreeRTOS-Kernel/portable/riscv/include/freertos/portmacro.h +++ b/components/freertos/FreeRTOS-Kernel/portable/riscv/include/freertos/portmacro.h @@ -740,7 +740,7 @@ bool xPortcheckValidStackMem(const void *ptr); // --------------------- App-Trace ------------------------- -#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW +#if CONFIG_ESP_TRACE_ENABLE extern volatile UBaseType_t xPortSwitchFlag[portNUM_PROCESSORS]; #define os_task_switch_is_pended(_cpu_) (xPortSwitchFlag[_cpu_]) #else diff --git a/components/freertos/FreeRTOS-Kernel/portable/xtensa/include/freertos/portmacro.h b/components/freertos/FreeRTOS-Kernel/portable/xtensa/include/freertos/portmacro.h index b8200604142..34f387ff25c 100644 --- a/components/freertos/FreeRTOS-Kernel/portable/xtensa/include/freertos/portmacro.h +++ b/components/freertos/FreeRTOS-Kernel/portable/xtensa/include/freertos/portmacro.h @@ -658,7 +658,7 @@ bool xPortcheckValidStackMem(const void *ptr); // --------------------- App-Trace ------------------------- -#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW +#if CONFIG_ESP_TRACE_ENABLE extern volatile uint32_t port_switch_flag[portNUM_PROCESSORS]; #define os_task_switch_is_pended(_cpu_) (port_switch_flag[_cpu_]) #else diff --git a/components/xtensa/xtensa_intr.c b/components/xtensa/xtensa_intr.c index a2f9bfc69b3..7279bcdf768 100644 --- a/components/xtensa/xtensa_intr.c +++ b/components/xtensa/xtensa_intr.c @@ -156,7 +156,7 @@ xt_handler xt_set_interrupt_handler(int n, xt_handler f, void * arg) return ((old == &xt_unhandled_interrupt) ? 0 : old); } -#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW +#if CONFIG_ESP_TRACE_ENABLE void * xt_get_interrupt_handler_arg(int n) { xt_handler_table_entry * entry; diff --git a/docs/doxygen/Doxyfile b/docs/doxygen/Doxyfile index 885dbeb6aa2..309bc098816 100644 --- a/docs/doxygen/Doxyfile +++ b/docs/doxygen/Doxyfile @@ -22,7 +22,6 @@ PROJECT_NAME = "IDF Programming Guide" INPUT = \ $(PROJECT_PATH)/components/app_trace/include/esp_app_trace.h \ - $(PROJECT_PATH)/components/app_trace/include/esp_sysview_trace.h \ $(PROJECT_PATH)/components/app_update/include/esp_ota_ops.h \ $(PROJECT_PATH)/components/bootloader_support/include/bootloader_random.h \ $(PROJECT_PATH)/components/bootloader_support/include/esp_app_format.h \ diff --git a/docs/en/api-guides/app_trace.rst b/docs/en/api-guides/app_trace.rst index dcc88f7410b..c3d6456b171 100644 --- a/docs/en/api-guides/app_trace.rst +++ b/docs/en/api-guides/app_trace.rst @@ -400,7 +400,20 @@ Another useful ESP-IDF feature built on top of application tracing library is th How To Use It """"""""""""" -Support for this feature is enabled by ``Component config`` > ``ESP Trace Configuration`` > ``Trace library`` > ``SEGGER SystemView`` menuconfig option. There are several other options enabled under the same menu: +SystemView support is provided by the managed component ``espressif/esp_sysview``. The SystemView menu becomes visible only after: + +1. Adding the component dependency in ``idf_component.yml``: + + .. code-block:: yaml + + dependencies: + espressif/esp_sysview: ^1 + +2. Selecting the external library in menuconfig: ``Component config`` > ``ESP Trace Configuration`` > ``Trace library`` > ``External library from component registry``. + +After that, you can configure SystemView in ``Component config`` > ``SEGGER SystemView Configuration``. For full, up-to-date instructions, see the component README: `esp_sysview `_. + +There are several other options enabled under the same menu: 1. {IDF_TARGET_NAME} timer to use as SystemView timestamp source: (:ref:`CONFIG_ESP_TRACE_TIMESTAMP_SOURCE`) selects the source of timestamps for SystemView events. In the single core mode, timestamps are generated using {IDF_TARGET_NAME} internal cycle counter running at maximum frequency. (:ref:`CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ`) In the dual-core mode, external timer is used to generate timestamps. It's frequency is 1/2 of the CPU frequency. @@ -513,7 +526,7 @@ After trace data are collected, users can use a special tool to visualize the re This command will create a single trace file that can be loaded directly into SystemView 3.60+ for multi-core visualization. - **Note:** SystemView versions before 3.60 do not support multi-core tracing. For older versions, when tracing from {IDF_TARGET_NAME} with JTAG interfaces in the dual-core mode, two separate files are generated: one for PRO CPU and another for APP CPU. Users can load each file into separate instances of the tool. For tracing over UART, users can select ``Component config`` > ``ESP Trace Configuration`` > ``SEGGER SystemView`` in menuconfig to choose which CPU (Pro or App) has to be traced. + **Note:** SystemView versions before 3.60 do not support multi-core tracing. For older versions, when tracing from {IDF_TARGET_NAME} with JTAG interfaces in the dual-core mode, two separate files are generated: one for PRO CPU and another for APP CPU. Users can load each file into separate instances of the tool. For tracing over UART, after selecting the external library in menuconfig, users can select ``Component config`` > ``SEGGER SystemView Configuration`` to choose which CPU (Pro or App) has to be traced. For older SystemView versions, analyzing data for every core in separate instances can be awkward. An alternative is to use the Eclipse plugin called *Impulse*, which can load several trace files, making it possible to inspect events from both cores in one view. This plugin also has no limitation of 1,000,000 events as compared to the free version of SystemView. diff --git a/docs/en/api-reference/system/app_trace.rst b/docs/en/api-reference/system/app_trace.rst index 427b4a06293..06d71508df1 100644 --- a/docs/en/api-reference/system/app_trace.rst +++ b/docs/en/api-reference/system/app_trace.rst @@ -25,4 +25,3 @@ API Reference ------------- .. include-build-file:: inc/esp_app_trace.inc -.. include-build-file:: inc/esp_sysview_trace.inc diff --git a/docs/en/migration-guides/release-6.x/6.0/system.rst b/docs/en/migration-guides/release-6.x/6.0/system.rst index 97337b3d52c..4ed7c7fe155 100644 --- a/docs/en/migration-guides/release-6.x/6.0/system.rst +++ b/docs/en/migration-guides/release-6.x/6.0/system.rst @@ -134,10 +134,26 @@ New configuration: CONFIG_APPTRACE_DEST_UART=y CONFIG_APPTRACE_DEST_UART_NUM=0 # or 1, 2 depending on target -SystemView Configuration -^^^^^^^^^^^^^^^^^^^^^^^^ +SEGGER SystemView +^^^^^^^^^^^^^^^^^ -The SystemView configuration has been moved to a new location in the menuconfig: ``Component config`` > ``ESP Trace Configuration`` > ``Trace library`` > ``SEGGER SystemView``. +The SystemView component has been moved to a separate repository. `esp_sysview `_ is now a managed component. + +Configuration +^^^^^^^^^^^^^^ + +The SystemView configuration has been moved to a new location in the menuconfig. It becomes visible only when the project adds the ``esp_sysview`` component dependency in ``idf_component.yml`` and the external library is selected in menuconfig. + +Add the dependency in your component manifest: + +.. code-block:: yaml + + dependencies: + espressif/esp_sysview: ^1 + +Then, in menuconfig, select: ``Component config`` > ``ESP Trace Configuration`` > ``Trace library`` > ``External library from component registry``. + +After that, the SystemView configuration can be shown by selecting ``Component config`` > ``SEGGER SystemView Configuration``. The SystemView no longer has its own separate destination configuration. It shares the configuration with the application tracing transport (JTAG or UART). diff --git a/docs/zh_CN/api-guides/app_trace.rst b/docs/zh_CN/api-guides/app_trace.rst index 8ea25142c02..8eecd6328c2 100644 --- a/docs/zh_CN/api-guides/app_trace.rst +++ b/docs/zh_CN/api-guides/app_trace.rst @@ -400,7 +400,20 @@ ESP-IDF 中另一个基于应用层跟踪库的实用功能是系统级跟踪, 如何使用 """""""" -若需使用这个功能,需要在 menuconfig 中通过 ``Component config`` > ``ESP Trace Configuration`` > ``Trace library`` > ``SEGGER SystemView`` 选项启用此功能。同一菜单栏下还有其它几个选项: +SystemView 支持由托管组件 ``espressif/esp_sysview`` 提供。SystemView 菜单仅在以下步骤完成后才会显示: + +1. 在 ``idf_component.yml`` 中添加组件依赖: + + .. code-block:: yaml + + dependencies: + espressif/esp_sysview: ^1 + +2. 在 menuconfig 中选择外部库:``Component config`` > ``ESP Trace Configuration`` > ``Trace library`` > ``External library from component registry``。 + +之后,您可以在 ``Component config`` > ``SEGGER SystemView Configuration`` 中配置 SystemView。有关完整的最新说明,请参阅组件 README:`esp_sysview `_。 + +同一菜单栏下还有其它几个选项: 1. {IDF_TARGET_NAME} 用作 SystemView 时间戳源的定时器选择:(:ref:`CONFIG_ESP_TRACE_TIMESTAMP_SOURCE`)用于选择 SystemView 事件的时间戳源。在单核模式下,时间戳由以最大频率运行的 {IDF_TARGET_NAME} 内部周期计数器生成。(:ref:`CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ`)在双核模式下,使用外部定时器生成时间戳,其频率为 CPU 频率的 1/2。 @@ -513,7 +526,7 @@ Start 子命令语法: 此命令将创建一个单独的跟踪文件,可以直接加载到 SystemView 3.60+ 中进行多核可视化。 - **注意:** SystemView 3.60 之前的版本不支持多核跟踪。对于旧版本,当使用 JTAG 接口跟踪双核模式下的 {IDF_TARGET_NAME} 时会生成两个文件:一个用于 PRO CPU,另一个用于 APP CPU。用户可将每个文件载入不同的工具实例。使用 UART 进行跟踪时,用户可以在 menuconfig 中选择 ``Component config`` > ``ESP Trace Configuration`` > ``SEGGER SystemView`` 来指定需要跟踪的 CPU(Pro 或 App)。 + **注意:** SystemView 3.60 之前的版本不支持多核跟踪。对于旧版本,当使用 JTAG 接口跟踪双核模式下的 {IDF_TARGET_NAME} 时会生成两个文件:一个用于 PRO CPU,另一个用于 APP CPU。用户可将每个文件载入不同的工具实例。使用 UART 进行跟踪时,在 menuconfig 中选择外部库后,用户可以选择 ``Component config`` > ``SEGGER SystemView Configuration`` 来指定需要跟踪的 CPU(Pro 或 App)。 对于旧版本的 SystemView,在不同的实例中分别分析每个核的数据可能较为不便。另一个选择是使用名为 *Impulse* 的 Eclipse 插件,该插件可同时加载多个跟踪文件,实现在同一视图中检查来自两个核心的事件。与 SystemView 免费版相比,此插件还不受 100 万事件数量的限制。 diff --git a/docs/zh_CN/api-reference/system/app_trace.rst b/docs/zh_CN/api-reference/system/app_trace.rst index 983d8e69f3e..f6da0b6bec1 100644 --- a/docs/zh_CN/api-reference/system/app_trace.rst +++ b/docs/zh_CN/api-reference/system/app_trace.rst @@ -25,4 +25,3 @@ API 参考 ------------- .. include-build-file:: inc/esp_app_trace.inc -.. include-build-file:: inc/esp_sysview_trace.inc diff --git a/docs/zh_CN/migration-guides/release-6.x/6.0/system.rst b/docs/zh_CN/migration-guides/release-6.x/6.0/system.rst index b9cdd4b055e..45a2f340fd1 100644 --- a/docs/zh_CN/migration-guides/release-6.x/6.0/system.rst +++ b/docs/zh_CN/migration-guides/release-6.x/6.0/system.rst @@ -134,10 +134,26 @@ UART 目标配置已简化: CONFIG_APPTRACE_DEST_UART=y CONFIG_APPTRACE_DEST_UART_NUM=0 # 或 1、2,具体取决于目标芯片 -SystemView 配置 -^^^^^^^^^^^^^^^^^^^^^^^^ +SEGGER SystemView +^^^^^^^^^^^^^^^^^ -SystemView 配置已移至 menuconfig 中的新位置:``Component config`` > ``ESP Trace Configuration`` > ``Trace library`` > ``SEGGER SystemView``。 +SystemView 组件已移至独立仓库。`esp_sysview `_ 现为托管组件。 + +配置 +^^^^^^^^^^^^^^ + +SystemView 配置已移至 menuconfig。仅当在项目的 ``idf_component.yml`` 中添加 ``esp_sysview`` 组件依赖,并在 menuconfig 中选择外部库后,相关配置菜单才会显示。 + +在组件清单中添加依赖: + +.. code-block:: yaml + + dependencies: + espressif/esp_sysview: ^1 + +随后在 menuconfig 中选择:``Component config`` > ``ESP Trace Configuration`` > ``Trace library`` > ``External library from component registry``。 + +之后,可在 ``Component config`` > ``SEGGER SystemView Configuration`` 中进行 SystemView 配置。 SystemView 不再拥有独立的传输目标配置。它与应用程序跟踪传输方式(JTAG 或 UART)共享配置。 diff --git a/examples/system/sysview_tracing/main/idf_component.yml b/examples/system/sysview_tracing/main/idf_component.yml new file mode 100644 index 00000000000..52aa253449c --- /dev/null +++ b/examples/system/sysview_tracing/main/idf_component.yml @@ -0,0 +1,13 @@ +## IDF Component Manager Manifest File +dependencies: + ## Required IDF version + idf: + version: '>=6.0' + # # Put list of dependencies here + #espressif/esp_sysview: ^1 + esp_sysview: + git: https://github.com/espressif/idf-extra-components.git + path: esp_sysview + version: "refs/pull/600/head" + matches: + - if: "idf_version >=6.0" diff --git a/examples/system/sysview_tracing/main/sysview_tracing.c b/examples/system/sysview_tracing/main/sysview_tracing.c index 498e29fb146..79505963558 100644 --- a/examples/system/sysview_tracing/main/sysview_tracing.c +++ b/examples/system/sysview_tracing/main/sysview_tracing.c @@ -19,11 +19,11 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "driver/gptimer.h" +#include "soc/uart_pins.h" #include "esp_trace.h" static const char *TAG = "example"; -#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW #if !CONFIG_USE_CUSTOM_EVENT_ID #define SYSVIEW_EXAMPLE_SEND_EVENT_ID 0 @@ -71,15 +71,6 @@ static void example_sysview_event_send(uint32_t id, uint32_t val) #endif // !CONFIG_USE_CUSTOM_EVENT_ID -#else - -#define SYSVIEW_EXAMPLE_SEND_EVENT_START() -#define SYSVIEW_EXAMPLE_SEND_EVENT_END(_val_) -#define SYSVIEW_EXAMPLE_WAIT_EVENT_START() -#define SYSVIEW_EXAMPLE_WAIT_EVENT_END(_val_) - -#endif // CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW - typedef struct { gptimer_handle_t gptimer; int count; @@ -136,13 +127,32 @@ static void example_task(void *p) } } +esp_trace_open_params_t esp_trace_get_user_params(void) +{ + static esp_apptrace_config_t app_trace_config = APPTRACE_CONFIG_DEFAULT(); +#if CONFIG_APPTRACE_DEST_UART + /* Override default values to use console pins as a uart channel */ + app_trace_config.dest_cfg.uart.tx_pin_num = U0TXD_GPIO_NUM; + app_trace_config.dest_cfg.uart.rx_pin_num = U0RXD_GPIO_NUM; +#endif + + esp_trace_open_params_t trace_params = { + .core_cfg = NULL, + .encoder_name = "sysview", + .encoder_cfg = NULL, + .transport_name = "apptrace", + .transport_cfg = &app_trace_config, + }; + return trace_params; +} + void app_main(void) { ESP_LOGI(TAG, "Hello from sysview_tracing example!"); static example_event_data_t event_data[CONFIG_FREERTOS_NUMBER_OF_CORES]; -#if CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW && CONFIG_USE_CUSTOM_EVENT_ID +#if CONFIG_USE_CUSTOM_EVENT_ID // Currently OpenOCD does not support requesting module info from target. So do the following... // Wait until SystemView module receives START command from host, // after that data can be sent to the host using onboard API, diff --git a/examples/system/sysview_tracing/sdkconfig.ci.sysview_uart b/examples/system/sysview_tracing/sdkconfig.ci.sysview_uart index 9d16ef2ee1a..c9de8f194bb 100644 --- a/examples/system/sysview_tracing/sdkconfig.ci.sysview_uart +++ b/examples/system/sysview_tracing/sdkconfig.ci.sysview_uart @@ -1,4 +1,3 @@ CONFIG_ESP_CONSOLE_NONE=y CONFIG_APPTRACE_DEST_UART=y -CONFIG_APPTRACE_DEST_UART_NUM=0 CONFIG_USE_CUSTOM_EVENT_ID=y diff --git a/examples/system/sysview_tracing/sdkconfig.ci.sysview_uart_esp32c2_26Mhz b/examples/system/sysview_tracing/sdkconfig.ci.sysview_uart_esp32c2_26Mhz index 1efa43fecec..a582e762d84 100644 --- a/examples/system/sysview_tracing/sdkconfig.ci.sysview_uart_esp32c2_26Mhz +++ b/examples/system/sysview_tracing/sdkconfig.ci.sysview_uart_esp32c2_26Mhz @@ -1,6 +1,5 @@ CONFIG_IDF_TARGET="esp32c2" CONFIG_ESP_CONSOLE_NONE=y CONFIG_APPTRACE_DEST_UART=y -CONFIG_APPTRACE_DEST_UART_NUM=0 CONFIG_APPTRACE_UART_BAUDRATE=74880 CONFIG_XTAL_FREQ_26=y diff --git a/examples/system/sysview_tracing/sdkconfig.defaults b/examples/system/sysview_tracing/sdkconfig.defaults index a555ba97272..9a260fdef2e 100644 --- a/examples/system/sysview_tracing/sdkconfig.defaults +++ b/examples/system/sysview_tracing/sdkconfig.defaults @@ -2,7 +2,7 @@ CONFIG_FREERTOS_HZ=1000 # Enable FreeRTOS SystemView Tracing by default CONFIG_ESP_TRACE_ENABLE=y -CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW=y +CONFIG_ESP_TRACE_LIB_EXTERNAL=y CONFIG_ESP_TRACE_TRANSPORT_APPTRACE=y CONFIG_ESP_TRACE_TS_SOURCE_ESP_TIMER=y CONFIG_SEGGER_SYSVIEW_EVT_OVERFLOW_ENABLE=y diff --git a/examples/system/sysview_tracing/sdkconfig.defaults.esp32 b/examples/system/sysview_tracing/sdkconfig.defaults.esp32 deleted file mode 100644 index d2b38b39764..00000000000 --- a/examples/system/sysview_tracing/sdkconfig.defaults.esp32 +++ /dev/null @@ -1,3 +0,0 @@ -CONFIG_IDF_TARGET="esp32" -CONFIG_APPTRACE_UART_TX_GPIO=1 -CONFIG_APPTRACE_UART_RX_GPIO=3 diff --git a/examples/system/sysview_tracing/sdkconfig.defaults.esp32c2 b/examples/system/sysview_tracing/sdkconfig.defaults.esp32c2 deleted file mode 100644 index f6cfe1f0348..00000000000 --- a/examples/system/sysview_tracing/sdkconfig.defaults.esp32c2 +++ /dev/null @@ -1,3 +0,0 @@ -CONFIG_IDF_TARGET="esp32c2" -CONFIG_APPTRACE_UART_TX_GPIO=20 -CONFIG_APPTRACE_UART_RX_GPIO=19 diff --git a/examples/system/sysview_tracing/sdkconfig.defaults.esp32c3 b/examples/system/sysview_tracing/sdkconfig.defaults.esp32c3 deleted file mode 100644 index 0b063b705e8..00000000000 --- a/examples/system/sysview_tracing/sdkconfig.defaults.esp32c3 +++ /dev/null @@ -1,3 +0,0 @@ -CONFIG_IDF_TARGET="esp32c3" -CONFIG_APPTRACE_UART_TX_GPIO=21 -CONFIG_APPTRACE_UART_RX_GPIO=20 diff --git a/examples/system/sysview_tracing/sdkconfig.defaults.esp32c5 b/examples/system/sysview_tracing/sdkconfig.defaults.esp32c5 deleted file mode 100644 index a09b017d7b0..00000000000 --- a/examples/system/sysview_tracing/sdkconfig.defaults.esp32c5 +++ /dev/null @@ -1,3 +0,0 @@ -CONFIG_IDF_TARGET="esp32c5" -CONFIG_APPTRACE_UART_TX_GPIO=11 -CONFIG_APPTRACE_UART_RX_GPIO=12 diff --git a/examples/system/sysview_tracing/sdkconfig.defaults.esp32c6 b/examples/system/sysview_tracing/sdkconfig.defaults.esp32c6 deleted file mode 100644 index 4b3e4257a06..00000000000 --- a/examples/system/sysview_tracing/sdkconfig.defaults.esp32c6 +++ /dev/null @@ -1,3 +0,0 @@ -CONFIG_IDF_TARGET="esp32c6" -CONFIG_APPTRACE_UART_TX_GPIO=16 -CONFIG_APPTRACE_UART_RX_GPIO=17 diff --git a/examples/system/sysview_tracing/sdkconfig.defaults.esp32c61 b/examples/system/sysview_tracing/sdkconfig.defaults.esp32c61 deleted file mode 100644 index 390158a7249..00000000000 --- a/examples/system/sysview_tracing/sdkconfig.defaults.esp32c61 +++ /dev/null @@ -1,3 +0,0 @@ -CONFIG_IDF_TARGET="esp32c61" -CONFIG_APPTRACE_UART_TX_GPIO=11 -CONFIG_APPTRACE_UART_RX_GPIO=10 diff --git a/examples/system/sysview_tracing/sdkconfig.defaults.esp32h2 b/examples/system/sysview_tracing/sdkconfig.defaults.esp32h2 deleted file mode 100644 index f5d32877b05..00000000000 --- a/examples/system/sysview_tracing/sdkconfig.defaults.esp32h2 +++ /dev/null @@ -1,3 +0,0 @@ -CONFIG_IDF_TARGET="esp32h2" -CONFIG_APPTRACE_UART_TX_GPIO=24 -CONFIG_APPTRACE_UART_RX_GPIO=23 diff --git a/examples/system/sysview_tracing/sdkconfig.defaults.esp32p4 b/examples/system/sysview_tracing/sdkconfig.defaults.esp32p4 deleted file mode 100644 index dbd30404c70..00000000000 --- a/examples/system/sysview_tracing/sdkconfig.defaults.esp32p4 +++ /dev/null @@ -1,3 +0,0 @@ -CONFIG_IDF_TARGET="esp32p4" -CONFIG_APPTRACE_UART_TX_GPIO=37 -CONFIG_APPTRACE_UART_RX_GPIO=38 diff --git a/examples/system/sysview_tracing/sdkconfig.defaults.esp32s2 b/examples/system/sysview_tracing/sdkconfig.defaults.esp32s2 deleted file mode 100644 index 1ff8e8cb8e0..00000000000 --- a/examples/system/sysview_tracing/sdkconfig.defaults.esp32s2 +++ /dev/null @@ -1,3 +0,0 @@ -CONFIG_IDF_TARGET="esp32s2" -CONFIG_APPTRACE_UART_TX_GPIO=43 -CONFIG_APPTRACE_UART_RX_GPIO=44 diff --git a/examples/system/sysview_tracing/sdkconfig.defaults.esp32s3 b/examples/system/sysview_tracing/sdkconfig.defaults.esp32s3 deleted file mode 100644 index a4aa377ac05..00000000000 --- a/examples/system/sysview_tracing/sdkconfig.defaults.esp32s3 +++ /dev/null @@ -1,3 +0,0 @@ -CONFIG_IDF_TARGET="esp32s3" -CONFIG_APPTRACE_UART_TX_GPIO=43 -CONFIG_APPTRACE_UART_RX_GPIO=44 diff --git a/examples/system/sysview_tracing_heap_log/main/idf_component.yml b/examples/system/sysview_tracing_heap_log/main/idf_component.yml new file mode 100644 index 00000000000..52aa253449c --- /dev/null +++ b/examples/system/sysview_tracing_heap_log/main/idf_component.yml @@ -0,0 +1,13 @@ +## IDF Component Manager Manifest File +dependencies: + ## Required IDF version + idf: + version: '>=6.0' + # # Put list of dependencies here + #espressif/esp_sysview: ^1 + esp_sysview: + git: https://github.com/espressif/idf-extra-components.git + path: esp_sysview + version: "refs/pull/600/head" + matches: + - if: "idf_version >=6.0" diff --git a/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c b/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c index 339083a4b7d..9fedde99b98 100644 --- a/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c +++ b/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c @@ -11,7 +11,7 @@ #include #include "esp_err.h" #include "esp_app_trace.h" -#include "esp_sysview_trace.h" +#include "esp_sysview_heap_trace_module.h" // from esp_sysview managed component #include "esp_heap_trace.h" #include "esp_log.h" #include "freertos/FreeRTOS.h" @@ -73,6 +73,18 @@ static void alloc_task(void *p) } } +esp_trace_open_params_t esp_trace_get_user_params(void) +{ + esp_trace_open_params_t trace_params = { + .core_cfg = NULL, + .encoder_name = "sysview", + .encoder_cfg = NULL, + .transport_name = "apptrace", + .transport_cfg = NULL, + }; + return trace_params; +} + void app_main(void) { ESP_LOGI(TAG, "Ready for OpenOCD connection"); diff --git a/examples/system/sysview_tracing_heap_log/sdkconfig.ci.app_trace_jtag b/examples/system/sysview_tracing_heap_log/sdkconfig.ci.app_trace_jtag index e69de29bb2d..772bddde156 100644 --- a/examples/system/sysview_tracing_heap_log/sdkconfig.ci.app_trace_jtag +++ b/examples/system/sysview_tracing_heap_log/sdkconfig.ci.app_trace_jtag @@ -0,0 +1 @@ +CONFIG_APPTRACE_DEST_JTAG=y diff --git a/examples/system/sysview_tracing_heap_log/sdkconfig.defaults b/examples/system/sysview_tracing_heap_log/sdkconfig.defaults index a709f86cbae..68fa9a59f70 100644 --- a/examples/system/sysview_tracing_heap_log/sdkconfig.defaults +++ b/examples/system/sysview_tracing_heap_log/sdkconfig.defaults @@ -2,11 +2,11 @@ CONFIG_FREERTOS_HZ=1000 # Enable application tracing by default CONFIG_ESP_TRACE_ENABLE=y -CONFIG_ESP_TRACE_LIB_SEGGER_SYSVIEW=y +CONFIG_ESP_TRACE_LIB_EXTERNAL=y CONFIG_ESP_TRACE_TRANSPORT_APPTRACE=y CONFIG_ESP_TRACE_TS_SOURCE_GPTIMER=y -CONFIG_APPTRACE_DEST_JTAG=y -# Enable FreeRTOS SystemView Tracing by default + +# FreeRTOS SystemView Tracing Settings CONFIG_SEGGER_SYSVIEW_EVT_OVERFLOW_ENABLE=y CONFIG_SEGGER_SYSVIEW_EVT_ISR_ENTER_ENABLE=y CONFIG_SEGGER_SYSVIEW_EVT_ISR_EXIT_ENABLE=y diff --git a/tools/ci/check_public_headers_exceptions.txt b/tools/ci/check_public_headers_exceptions.txt index eafb64d259b..fd36952dbe8 100644 --- a/tools/ci/check_public_headers_exceptions.txt +++ b/tools/ci/check_public_headers_exceptions.txt @@ -74,7 +74,6 @@ components/heap/tlsf/tlsf_control_functions.h ### Here are the files that do not compile for some reason # -components/app_trace/include/esp_sysview_trace.h components/esp_gdbstub/include/esp_gdbstub.h components/esp_hw_support/include/esp_memprot.h From 6a030cfad9f147603f7b7e3c300d61691935bbbf Mon Sep 17 00:00:00 2001 From: Erhan Kurubas Date: Thu, 6 Nov 2025 13:39:49 +0100 Subject: [PATCH 072/106] change(examples): disable sysview tests until sysview component is uploaded to registry --- examples/system/.build-test-rules.yml | 6 ++++++ examples/system/sysview_tracing/main/idf_component.yml | 8 +------- .../sysview_tracing_heap_log/main/idf_component.yml | 8 +------- 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/examples/system/.build-test-rules.yml b/examples/system/.build-test-rules.yml index 1e5638d7513..e7504dc9bb3 100644 --- a/examples/system/.build-test-rules.yml +++ b/examples/system/.build-test-rules.yml @@ -257,6 +257,9 @@ examples/system/select: examples/system/sysview_tracing: disable: - if: SOC_GPTIMER_SUPPORTED != 1 + - if: IDF_TARGET in ["esp32", "esp32s2", "esp32s3", "esp32c2", "esp32c3", "esp32c5", "esp32c61", "esp32c6", "esp32h2", "esp32h21", "esp32h4", "esp32p4"] + temporary: true + reason: temporarily disabled until the sysview component is published in the component registry disable_test: - if: IDF_TARGET == "esp32h21" temporary: true @@ -268,6 +271,9 @@ examples/system/sysview_tracing: examples/system/sysview_tracing_heap_log: disable: - if: SOC_GPTIMER_SUPPORTED != 1 + - if: IDF_TARGET in ["esp32", "esp32s2", "esp32s3", "esp32c2", "esp32c3", "esp32c5", "esp32c61", "esp32c6", "esp32h2", "esp32h21", "esp32h4", "esp32p4"] + temporary: true + reason: temporarily disabled until the sysview component is published in the component registry disable_test: - if: IDF_TARGET == "esp32h21" temporary: true diff --git a/examples/system/sysview_tracing/main/idf_component.yml b/examples/system/sysview_tracing/main/idf_component.yml index 52aa253449c..aade821c232 100644 --- a/examples/system/sysview_tracing/main/idf_component.yml +++ b/examples/system/sysview_tracing/main/idf_component.yml @@ -4,10 +4,4 @@ dependencies: idf: version: '>=6.0' # # Put list of dependencies here - #espressif/esp_sysview: ^1 - esp_sysview: - git: https://github.com/espressif/idf-extra-components.git - path: esp_sysview - version: "refs/pull/600/head" - matches: - - if: "idf_version >=6.0" + espressif/esp_sysview: ^1 diff --git a/examples/system/sysview_tracing_heap_log/main/idf_component.yml b/examples/system/sysview_tracing_heap_log/main/idf_component.yml index 52aa253449c..aade821c232 100644 --- a/examples/system/sysview_tracing_heap_log/main/idf_component.yml +++ b/examples/system/sysview_tracing_heap_log/main/idf_component.yml @@ -4,10 +4,4 @@ dependencies: idf: version: '>=6.0' # # Put list of dependencies here - #espressif/esp_sysview: ^1 - esp_sysview: - git: https://github.com/espressif/idf-extra-components.git - path: esp_sysview - version: "refs/pull/600/head" - matches: - - if: "idf_version >=6.0" + espressif/esp_sysview: ^1 From 4e8a733205ca4d71438d040035df64b60a03655a Mon Sep 17 00:00:00 2001 From: Zhang Shuxian Date: Mon, 10 Nov 2025 10:48:35 +0800 Subject: [PATCH 073/106] docs: Update translation for sysview --- docs/zh_CN/api-guides/app_trace.rst | 6 +++--- docs/zh_CN/migration-guides/release-6.x/6.0/system.rst | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/zh_CN/api-guides/app_trace.rst b/docs/zh_CN/api-guides/app_trace.rst index 8eecd6328c2..b4aa69dd8da 100644 --- a/docs/zh_CN/api-guides/app_trace.rst +++ b/docs/zh_CN/api-guides/app_trace.rst @@ -400,7 +400,7 @@ ESP-IDF 中另一个基于应用层跟踪库的实用功能是系统级跟踪, 如何使用 """""""" -SystemView 支持由托管组件 ``espressif/esp_sysview`` 提供。SystemView 菜单仅在以下步骤完成后才会显示: +SystemView 功能由托管组件 ``espressif/esp_sysview`` 提供。完成以下步骤后才会显示 SystemView 配置菜单: 1. 在 ``idf_component.yml`` 中添加组件依赖: @@ -411,9 +411,9 @@ SystemView 支持由托管组件 ``espressif/esp_sysview`` 提供。SystemView 2. 在 menuconfig 中选择外部库:``Component config`` > ``ESP Trace Configuration`` > ``Trace library`` > ``External library from component registry``。 -之后,您可以在 ``Component config`` > ``SEGGER SystemView Configuration`` 中配置 SystemView。有关完整的最新说明,请参阅组件 README:`esp_sysview `_。 +之后,可通过 ``Component config`` > ``SEGGER SystemView Configuration`` 配置 SystemView。完整的最新使用指南,请参阅 `esp_sysview README `_。 -同一菜单栏下还有其它几个选项: +此配置菜单还包含以下选项: 1. {IDF_TARGET_NAME} 用作 SystemView 时间戳源的定时器选择:(:ref:`CONFIG_ESP_TRACE_TIMESTAMP_SOURCE`)用于选择 SystemView 事件的时间戳源。在单核模式下,时间戳由以最大频率运行的 {IDF_TARGET_NAME} 内部周期计数器生成。(:ref:`CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ`)在双核模式下,使用外部定时器生成时间戳,其频率为 CPU 频率的 1/2。 diff --git a/docs/zh_CN/migration-guides/release-6.x/6.0/system.rst b/docs/zh_CN/migration-guides/release-6.x/6.0/system.rst index 45a2f340fd1..b99ce2d38dc 100644 --- a/docs/zh_CN/migration-guides/release-6.x/6.0/system.rst +++ b/docs/zh_CN/migration-guides/release-6.x/6.0/system.rst @@ -137,12 +137,12 @@ UART 目标配置已简化: SEGGER SystemView ^^^^^^^^^^^^^^^^^ -SystemView 组件已移至独立仓库。`esp_sysview `_ 现为托管组件。 +SystemView 组件已迁移至独立仓库。`esp_sysview `_ 现为托管组件。 配置 -^^^^^^^^^^^^^^ +^^^^ -SystemView 配置已移至 menuconfig。仅当在项目的 ``idf_component.yml`` 中添加 ``esp_sysview`` 组件依赖,并在 menuconfig 中选择外部库后,相关配置菜单才会显示。 +SystemView 配置在 menuconfig 中的位置已变更。仅当项目在 ``idf_component.yml`` 中添加 ``esp_sysview`` 组件依赖,并在 menuconfig 中选择外部库时,相关配置选项才会显示。 在组件清单中添加依赖: @@ -151,9 +151,9 @@ SystemView 配置已移至 menuconfig。仅当在项目的 ``idf_component.yml`` dependencies: espressif/esp_sysview: ^1 -随后在 menuconfig 中选择:``Component config`` > ``ESP Trace Configuration`` > ``Trace library`` > ``External library from component registry``。 +随后在 menuconfig 中依次选择:``Component config`` > ``ESP Trace Configuration`` > ``Trace library`` > ``External library from component registry``。 -之后,可在 ``Component config`` > ``SEGGER SystemView Configuration`` 中进行 SystemView 配置。 +之后,可通过 ``Component config`` > ``SEGGER SystemView Configuration`` 查看 SystemView 配置选项。 SystemView 不再拥有独立的传输目标配置。它与应用程序跟踪传输方式(JTAG 或 UART)共享配置。 From f20351eb3b6791ae94a6e7c3de4e793142a4ecef Mon Sep 17 00:00:00 2001 From: Laukik Hase Date: Tue, 23 Sep 2025 19:05:55 +0530 Subject: [PATCH 074/106] fix(esp_tee): Use HAL APIs instead of ROM APIs for SPI flash service calls Currently, REE SPI flash HAL operations are routed as service calls to TEE, but the TEE implementation incorrectly uses ROM APIs instead of HAL APIs. This leads to issues and is not the recommended approach. --- components/esp_hal_mspi/CMakeLists.txt | 2 +- .../esp_hal_mspi/spi_flash_hal_common.inc | 13 ++----------- components/esp_rom/CMakeLists.txt | 17 ++++------------- components/esp_tee/subproject/CMakeLists.txt | 2 +- .../subproject/main/ld/esp32c5/esp_tee.ld.in | 7 +++++++ .../subproject/main/ld/esp32c6/esp_tee.ld.in | 7 +++++++ .../subproject/main/ld/esp32h2/esp_tee.ld.in | 7 +++++++ .../test_apps/tee_cli_app/sdkconfig.ci.release | 2 -- .../test_apps/tee_cli_app/sdkconfig.ci.sb_fe | 4 ++++ .../test_apps/tee_test_fw/sdkconfig.ci.tee_ota | 4 ++++ .../test_apps/tee_test_fw/sdkconfig.defaults | 3 --- 11 files changed, 37 insertions(+), 31 deletions(-) diff --git a/components/esp_hal_mspi/CMakeLists.txt b/components/esp_hal_mspi/CMakeLists.txt index 65489e01917..21f45931725 100644 --- a/components/esp_hal_mspi/CMakeLists.txt +++ b/components/esp_hal_mspi/CMakeLists.txt @@ -6,7 +6,7 @@ set(includes "include" "${target}/include") if(esp_tee_build) if(CONFIG_SECURE_TEE_EXT_FLASH_MEMPROT_SPI1) - list(APPEND srcs "spi_flash_hal.c") + list(APPEND srcs "spi_flash_hal.c" "spi_flash_hal_iram.c") endif() elseif(NOT BOOTLOADER_BUILD) if(NOT CONFIG_APP_BUILD_TYPE_PURE_RAM_APP) diff --git a/components/esp_hal_mspi/spi_flash_hal_common.inc b/components/esp_hal_mspi/spi_flash_hal_common.inc index 564e5794a66..81f2c229193 100644 --- a/components/esp_hal_mspi/spi_flash_hal_common.inc +++ b/components/esp_hal_mspi/spi_flash_hal_common.inc @@ -131,15 +131,7 @@ esp_err_t spi_flash_hal_configure_host_io_mode( addr_bitlen += SPI_FLASH_LL_CONTINUOUS_MODE_BIT_NUMS; #endif spi_flash_ll_set_extra_address(dev, 0); - // TODO: [IDF-13582] - // Currently, REE and TEE use different sets of APIs for flash operations - - // REE uses the IDF SPI flash driver while TEE call the ROM APIs. This inconsistency - // leads to compatibility issues on ESP32-C5. - // One specific issue arises when esp_flash_read() is used in REE, which internally - // calls spi_flash_ll_wb_mode_enable(). This function enables the WB mode bit in - // the flash write operation. However, the ROM API does not support this - // feature, resulting in failures when TEE attempts to access flash after this call. -#if SOC_SPI_MEM_SUPPORT_WB_MODE_INDEPENDENT_CONTROL && !CONFIG_SECURE_ENABLE_TEE +#if SOC_SPI_MEM_SUPPORT_WB_MODE_INDEPENDENT_CONTROL spi_flash_ll_wb_mode_enable(dev, true); #endif } @@ -218,8 +210,7 @@ esp_err_t spi_flash_hal_common_command(spi_flash_host_inst_t *host, spi_flash_tr if (trans->miso_len > 0) { spi_flash_ll_get_buffer_data(dev, trans->miso_data, trans->miso_len); } - // TODO: [IDF-13582] -#if SOC_SPI_MEM_SUPPORT_WB_MODE_INDEPENDENT_CONTROL && !CONFIG_SECURE_ENABLE_TEE +#if SOC_SPI_MEM_SUPPORT_WB_MODE_INDEPENDENT_CONTROL spi_flash_ll_wb_mode_enable(dev, false); #endif return ESP_OK; diff --git a/components/esp_rom/CMakeLists.txt b/components/esp_rom/CMakeLists.txt index c8540aa4867..6049ad7c952 100644 --- a/components/esp_rom/CMakeLists.txt +++ b/components/esp_rom/CMakeLists.txt @@ -152,21 +152,12 @@ if(CONFIG_ESP_ROM_HAS_VERSION) endif() if(ESP_TEE_BUILD) - if(CONFIG_IDF_TARGET_ESP32H4 AND NOT CONFIG_ESP32H4_SELECTS_REV_MP) # TODO: ESP32H4 IDF-13835 - rom_linker_script("beta5.heap") - rom_linker_script("beta5.spiflash") - if(CONFIG_ESP_ROM_HAS_NEWLIB_NANO_FORMAT) - rom_linker_script("beta5.newlib-nano") - endif() - else() - rom_linker_script("heap") - rom_linker_script("spiflash") - if(CONFIG_ESP_ROM_HAS_NEWLIB_NANO_FORMAT) - rom_linker_script("newlib-nano") - endif() + rom_linker_script("heap") + if(CONFIG_ESP_ROM_HAS_NEWLIB_NANO_FORMAT) + rom_linker_script("newlib-nano") endif() rom_linker_script("libc") - if(CONFIG_ESP_ROM_HAS_SUBOPTIMAL_NEWLIB_ON_MISALIGNED_MEMORY) # TODO IDF-13852: use optimized memcpy for TEE ? + if(CONFIG_ESP_ROM_HAS_SUBOPTIMAL_NEWLIB_ON_MISALIGNED_MEMORY) rom_linker_script("libc-suboptimal_for_misaligned_mem") endif() endif() diff --git a/components/esp_tee/subproject/CMakeLists.txt b/components/esp_tee/subproject/CMakeLists.txt index 78f009d8616..91370fa0779 100644 --- a/components/esp_tee/subproject/CMakeLists.txt +++ b/components/esp_tee/subproject/CMakeLists.txt @@ -25,7 +25,7 @@ set(ESP_TEE_BUILD 1) set(NON_OS_BUILD 1) # Additional components -list(APPEND COMPONENTS bootloader_support efuse esp_security mbedtls esp_stdio) +list(APPEND COMPONENTS bootloader_support efuse esp_hal_mspi esp_security mbedtls esp_stdio) # TEE-specific components list(APPEND COMPONENTS tee_flash_mgr tee_ota_ops tee_sec_storage tee_attestation) diff --git a/components/esp_tee/subproject/main/ld/esp32c5/esp_tee.ld.in b/components/esp_tee/subproject/main/ld/esp32c5/esp_tee.ld.in index 73cc9a4599f..3fa95a92f9d 100644 --- a/components/esp_tee/subproject/main/ld/esp32c5/esp_tee.ld.in +++ b/components/esp_tee/subproject/main/ld/esp32c5/esp_tee.ld.in @@ -40,6 +40,11 @@ PROVIDE ( esp_tee_app_config = SRAM_REE_SEG_START + 0x2b0 ); PROVIDE ( GDMA = 0x60080000 ); +/* SPI Flash functions required from the ROM (refer esp32c5.rom.spiflash.ld) */ +PROVIDE ( spi_flash_check_and_flush_cache = 0x40000230 ); +PROVIDE ( spi_flash_chip_generic_config_host_io_mode = 0x400002d4 ); +PROVIDE ( memspi_host_flush_cache = 0x40000318 ); + /* Default entry point: */ ENTRY(esp_tee_init); @@ -98,6 +103,7 @@ SECTIONS *libhal.a:cache_hal.c*(.literal .text .literal.* .text.*) *libhal.a:wdt_hal_iram.c*(.literal .text .literal.* .text.*) *libhal.a:apm_hal.c*(.literal .text .literal.* .text.*) + *libesp_hal_mspi.a:*(.literal .text .literal.* .text.*) /* IDF components */ *libbootloader_support.a:*(.literal .text .literal.* .text.*) *libesp_hw_support.a:*(.literal .text .literal.* .text.*) @@ -146,6 +152,7 @@ SECTIONS /* HAL (noflash) */ *libhal.a:mmu_hal.c*(.rodata .srodata .rodata.* .srodata.*) *libhal.a:cache_hal.c*(.rodata .srodata .rodata.* .srodata.*) + *libesp_hal_mspi.a:*(.rodata .srodata .rodata.* .srodata.*) _tee_rodata_end = ABSOLUTE(.); _tee_dram_end = ABSOLUTE(.); } > sram_tee_seg diff --git a/components/esp_tee/subproject/main/ld/esp32c6/esp_tee.ld.in b/components/esp_tee/subproject/main/ld/esp32c6/esp_tee.ld.in index 121f4f4b656..98e4d6a5610 100644 --- a/components/esp_tee/subproject/main/ld/esp32c6/esp_tee.ld.in +++ b/components/esp_tee/subproject/main/ld/esp32c6/esp_tee.ld.in @@ -40,6 +40,11 @@ PROVIDE ( esp_tee_app_config = SRAM_REE_SEG_START + 0x2e0 ); PROVIDE ( GDMA = 0x60080000 ); +/* SPI Flash functions required from the ROM (refer esp32c6.rom.spiflash.ld) */ +PROVIDE ( spi_flash_check_and_flush_cache = 0x4000021c ); +PROVIDE ( spi_flash_chip_generic_config_host_io_mode = 0x400002c4 ); +PROVIDE ( memspi_host_flush_cache = 0x40000308 ); + /* Default entry point: */ ENTRY(esp_tee_init); @@ -98,6 +103,7 @@ SECTIONS *libhal.a:cache_hal.c*(.literal .text .literal.* .text.*) *libhal.a:wdt_hal_iram.c*(.literal .text .literal.* .text.*) *libhal.a:apm_hal.c*(.literal .text .literal.* .text.*) + *libesp_hal_mspi.a:*(.literal .text .literal.* .text.*) /* IDF components */ *libbootloader_support.a:*(.literal .text .literal.* .text.*) *libesp_hw_support.a:*(.literal .text .literal.* .text.*) @@ -146,6 +152,7 @@ SECTIONS /* HAL (noflash) */ *libhal.a:mmu_hal.c*(.rodata .srodata .rodata.* .srodata.*) *libhal.a:cache_hal.c*(.rodata .srodata .rodata.* .srodata.*) + *libesp_hal_mspi.a:*(.rodata .srodata .rodata.* .srodata.*) _tee_rodata_end = ABSOLUTE(.); _tee_dram_end = ABSOLUTE(.); } > sram_tee_seg diff --git a/components/esp_tee/subproject/main/ld/esp32h2/esp_tee.ld.in b/components/esp_tee/subproject/main/ld/esp32h2/esp_tee.ld.in index 121f4f4b656..0f38b3c64d0 100644 --- a/components/esp_tee/subproject/main/ld/esp32h2/esp_tee.ld.in +++ b/components/esp_tee/subproject/main/ld/esp32h2/esp_tee.ld.in @@ -40,6 +40,11 @@ PROVIDE ( esp_tee_app_config = SRAM_REE_SEG_START + 0x2e0 ); PROVIDE ( GDMA = 0x60080000 ); +/* SPI Flash functions required from the ROM (refer esp32h2.rom.spiflash.ld) */ +PROVIDE ( spi_flash_check_and_flush_cache = 0x40000214 ); +PROVIDE ( spi_flash_chip_generic_config_host_io_mode = 0x400002bc ); +PROVIDE ( memspi_host_flush_cache = 0x40000300 ); + /* Default entry point: */ ENTRY(esp_tee_init); @@ -98,6 +103,7 @@ SECTIONS *libhal.a:cache_hal.c*(.literal .text .literal.* .text.*) *libhal.a:wdt_hal_iram.c*(.literal .text .literal.* .text.*) *libhal.a:apm_hal.c*(.literal .text .literal.* .text.*) + *libesp_hal_mspi.a:*(.literal .text .literal.* .text.*) /* IDF components */ *libbootloader_support.a:*(.literal .text .literal.* .text.*) *libesp_hw_support.a:*(.literal .text .literal.* .text.*) @@ -146,6 +152,7 @@ SECTIONS /* HAL (noflash) */ *libhal.a:mmu_hal.c*(.rodata .srodata .rodata.* .srodata.*) *libhal.a:cache_hal.c*(.rodata .srodata .rodata.* .srodata.*) + *libesp_hal_mspi.a:*(.rodata .srodata .rodata.* .srodata.*) _tee_rodata_end = ABSOLUTE(.); _tee_dram_end = ABSOLUTE(.); } > sram_tee_seg diff --git a/components/esp_tee/test_apps/tee_cli_app/sdkconfig.ci.release b/components/esp_tee/test_apps/tee_cli_app/sdkconfig.ci.release index 52e758739c9..e96f96e949c 100644 --- a/components/esp_tee/test_apps/tee_cli_app/sdkconfig.ci.release +++ b/components/esp_tee/test_apps/tee_cli_app/sdkconfig.ci.release @@ -1,8 +1,6 @@ # Reducing TEE I/DRAM sizes # 28KB CONFIG_SECURE_TEE_IRAM_SIZE=0x7000 -# 16KB -CONFIG_SECURE_TEE_DRAM_SIZE=0x4000 # TEE Secure Storage: Release mode CONFIG_SECURE_TEE_SEC_STG_MODE_RELEASE=y diff --git a/components/esp_tee/test_apps/tee_cli_app/sdkconfig.ci.sb_fe b/components/esp_tee/test_apps/tee_cli_app/sdkconfig.ci.sb_fe index bdec94c11b8..54cfec34a03 100644 --- a/components/esp_tee/test_apps/tee_cli_app/sdkconfig.ci.sb_fe +++ b/components/esp_tee/test_apps/tee_cli_app/sdkconfig.ci.sb_fe @@ -15,3 +15,7 @@ CONFIG_NVS_SEC_KEY_PROTECT_USING_FLASH_ENC=y # TEE Secure Storage: Release mode CONFIG_SECURE_TEE_SEC_STG_MODE_RELEASE=y CONFIG_SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID=5 + +# Increasing TEE DRAM size +# 18KB +CONFIG_SECURE_TEE_DRAM_SIZE=0x4800 diff --git a/components/esp_tee/test_apps/tee_test_fw/sdkconfig.ci.tee_ota b/components/esp_tee/test_apps/tee_test_fw/sdkconfig.ci.tee_ota index 09d30653ea5..7cbca448490 100644 --- a/components/esp_tee/test_apps/tee_test_fw/sdkconfig.ci.tee_ota +++ b/components/esp_tee/test_apps/tee_test_fw/sdkconfig.ci.tee_ota @@ -15,3 +15,7 @@ CONFIG_SECURE_TEE_ATT_KEY_STR_ID="tee_att_keyN" # Enabling flash protection over SPI1 CONFIG_SECURE_TEE_EXT_FLASH_MEMPROT_SPI1=y + +# Increasing TEE DRAM size +# 19KB +CONFIG_SECURE_TEE_DRAM_SIZE=0x4c00 diff --git a/components/esp_tee/test_apps/tee_test_fw/sdkconfig.defaults b/components/esp_tee/test_apps/tee_test_fw/sdkconfig.defaults index c7570128d89..161c206fc4a 100644 --- a/components/esp_tee/test_apps/tee_test_fw/sdkconfig.defaults +++ b/components/esp_tee/test_apps/tee_test_fw/sdkconfig.defaults @@ -11,6 +11,3 @@ CONFIG_SECURE_TEE_TEST_MODE=y # Setting partition table CONFIG_PARTITION_TABLE_SINGLE_APP_TEE=y CONFIG_PARTITION_TABLE_OFFSET=0xF000 - -# TEE IRAM size -CONFIG_SECURE_TEE_IRAM_SIZE=0x8400 From cf36853d0db1473a4c6015de767af4d55e2fc56e Mon Sep 17 00:00:00 2001 From: Laukik Hase Date: Wed, 24 Sep 2025 18:34:34 +0530 Subject: [PATCH 075/106] fix(esp_tee): Handle the SPI1 WB mode incompatibility in TEE flash APIs on ESP32-C5 - When `esp_flash_read()` is invoked from REE, it internally enables WB mode via `spi_flash_ll_wb_mode_enable()`. However, the ROM flash APIs used by TEE do not support WB mode, resulting in failures when TEE attempts to access flash after this call. - This commit adds a workaround in the TEE flash layer by saving WB mode state, temporarily disabling it for ROM API calls, and restoring it afterward. --- .../bootloader_flash/src/bootloader_flash.c | 64 ++++++++++++++++--- 1 file changed, 55 insertions(+), 9 deletions(-) diff --git a/components/bootloader_support/bootloader_flash/src/bootloader_flash.c b/components/bootloader_support/bootloader_flash/src/bootloader_flash.c index 2bfe1cb0efd..c06cdc91e56 100644 --- a/components/bootloader_support/bootloader_flash/src/bootloader_flash.c +++ b/components/bootloader_support/bootloader_flash/src/bootloader_flash.c @@ -217,13 +217,10 @@ static uint32_t current_mapped_size; // Current bootloader mapping (ab)used for bootloader_read() static uint32_t current_read_mapping = UINT32_MAX; -#if ESP_TEE_BUILD && CONFIG_IDF_TARGET_ESP32C6 -extern void spi_common_set_dummy_output(esp_rom_spiflash_read_mode_t mode); -extern void spi_dummy_len_fix(uint8_t spi, uint8_t freqdiv); - -/* TODO: [ESP-TEE] Workarounds for the ROM read API - * - * The esp_rom_spiflash_read API requires two workarounds on ESP32-C6 ECO0: +#if ESP_TEE_BUILD +/* [ESP-TEE] Workarounds for the ROM SPI flash APIs */ +/* + * TODO: The esp_rom_spiflash_read API requires two workarounds on ESP32-C6 ECO0 - * * 1. [IDF-7199] Call esp_rom_spiflash_write API once before reading. * Without this, reads return corrupted data. @@ -231,10 +228,14 @@ extern void spi_dummy_len_fix(uint8_t spi, uint8_t freqdiv); * 2. Configure ROM flash parameters before each read using the function below. * Without this, the first byte read is corrupted. * - * Note: These workarounds are not needed for ESP32-C6 ECO1 and later versions. + * NOTE: These workarounds are not needed for ESP32-C6 ECO1 and later versions. */ static void rom_read_api_workaround(void) { +#if CONFIG_ESP32C6_REV_MIN_0 + extern void spi_common_set_dummy_output(esp_rom_spiflash_read_mode_t mode); + extern void spi_dummy_len_fix(uint8_t spi, uint8_t freqdiv); + static bool is_first_call = true; if (is_first_call) { uint32_t dummy_val = UINT32_MAX; @@ -268,6 +269,43 @@ static void rom_read_api_workaround(void) spi_dummy_len_fix(1, freqdiv); esp_rom_spiflash_config_readmode(read_mode); spi_common_set_dummy_output(read_mode); +#endif +} + +/* + * TODO: [IDF-13582] + * + * When `esp_flash_read()` is invoked from REE, it enables SPI1 WB (write-back) mode + * via `spi_flash_ll_wb_mode_enable()`. The ROM flash APIs used by TEE do not support + * WB mode, causing failures when TEE later accesses flash. + * + * Workaround applied in TEE flash layer: + * 1. Save the current WB mode state. + * 2. Temporarily disable WB mode before calling ROM flash APIs. + * 3. Restore WB mode state after the ROM API call completes. + * + * NOTE: This workaround will become removed once IDF-13582 is implemented. + */ +static inline bool spi1_wb_mode_save_and_disable(void) +{ +#if SOC_SPI_MEM_SUPPORT_WB_MODE_INDEPENDENT_CONTROL + if (REG_GET_BIT(SPI_MEM_RD_STATUS_REG(1), SPI_MEM_WB_MODE_EN)) { + REG_CLR_BIT(SPI_MEM_RD_STATUS_REG(1), SPI_MEM_WB_MODE_EN); + return true; + } +#endif + return false; +} + +static inline void spi1_wb_mode_restore(bool saved_state) +{ +#if SOC_SPI_MEM_SUPPORT_WB_MODE_INDEPENDENT_CONTROL + if (saved_state) { + REG_SET_BIT(SPI_MEM_RD_STATUS_REG(1), SPI_MEM_WB_MODE_EN); + } +#else + (void)saved_state; +#endif } #endif @@ -416,8 +454,9 @@ static esp_err_t bootloader_flash_read_no_decrypt(size_t src_addr, void *dest, s #else #if !ESP_TEE_BUILD cache_hal_disable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL); -#elif CONFIG_ESP32C6_REV_MIN_0 +#else rom_read_api_workaround(); + bool is_wb_saved = spi1_wb_mode_save_and_disable(); #endif #endif @@ -428,6 +467,8 @@ static esp_err_t bootloader_flash_read_no_decrypt(size_t src_addr, void *dest, s #else #if !ESP_TEE_BUILD cache_hal_enable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL); +#else + spi1_wb_mode_restore(is_wb_saved); #endif #endif @@ -550,6 +591,10 @@ esp_err_t bootloader_flash_write(size_t dest_addr, void *src, size_t size, bool return err; } +#if ESP_TEE_BUILD + bool is_wb_saved = spi1_wb_mode_save_and_disable(); +#endif + esp_rom_spiflash_result_t rc = ESP_ROM_SPIFLASH_RESULT_OK; if (write_encrypted && !ENCRYPTION_IS_VIRTUAL) { @@ -564,6 +609,7 @@ esp_err_t bootloader_flash_write(size_t dest_addr, void *src, size_t size, bool * from being read from already memory-mapped addresses that were modified. */ #if ESP_TEE_BUILD + spi1_wb_mode_restore(is_wb_saved); spi_flash_check_and_flush_cache(dest_addr, size); #endif From f307e80fe228e386eedb382130e3d670b505b107 Mon Sep 17 00:00:00 2001 From: Laukik Hase Date: Tue, 16 Sep 2025 18:33:24 +0530 Subject: [PATCH 076/106] feat(esp_tee): Enable MSPI tuning for Flash and PSRAM --- components/esp_hw_support/CMakeLists.txt | 13 +++++++ .../mspi_timing_tuning/mspi_timing_tuning.c | 14 ++++++++ .../port/esp32c5/mspi_timing_tuning_configs.h | 8 ++--- .../scripts/esp32c5/sec_srv_tbl_default.yml | 24 +++++++++++++ .../esp_tee/src/esp_secure_service_wrapper.c | 34 +++++++++++++++++++ .../main/core/esp_secure_services_iram.c | 33 ++++++++++++++++++ 6 files changed, 120 insertions(+), 6 deletions(-) diff --git a/components/esp_hw_support/CMakeLists.txt b/components/esp_hw_support/CMakeLists.txt index 9399a8c92c5..be0e5ada4e6 100644 --- a/components/esp_hw_support/CMakeLists.txt +++ b/components/esp_hw_support/CMakeLists.txt @@ -175,7 +175,20 @@ if(NOT non_os_build) else() if(ESP_TEE_BUILD) list(APPEND srcs "esp_clk.c" "hw_random.c") + if(CONFIG_SECURE_TEE_EXT_FLASH_MEMPROT_SPI1) + list(APPEND srcs "mspi_timing_tuning/mspi_timing_tuning.c") + if(CONFIG_SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY) + list(APPEND srcs "mspi_timing_tuning/tuning_scheme_impl/mspi_timing_by_mspi_delay.c") + endif() + if(CONFIG_SOC_MEMSPI_TIMING_TUNING_BY_DQS) + list(APPEND srcs "mspi_timing_tuning/tuning_scheme_impl/mspi_timing_by_dqs.c") + endif() + if(CONFIG_SOC_MEMSPI_TIMING_TUNING_BY_FLASH_DELAY) + list(APPEND srcs "mspi_timing_tuning/tuning_scheme_impl/mspi_timing_by_flash_delay.c") + endif() + endif() endif() + # Requires "_esp_error_check_failed()" function list(APPEND priv_requires "esp_system") endif() diff --git a/components/esp_hw_support/mspi_timing_tuning/mspi_timing_tuning.c b/components/esp_hw_support/mspi_timing_tuning/mspi_timing_tuning.c index 62e9d301ae5..97517c565ec 100644 --- a/components/esp_hw_support/mspi_timing_tuning/mspi_timing_tuning.c +++ b/components/esp_hw_support/mspi_timing_tuning/mspi_timing_tuning.c @@ -15,7 +15,12 @@ #include "soc/soc.h" #include "hal/spi_flash_hal.h" #include "hal/mspi_ll.h" +#if !ESP_TEE_BUILD #include "esp_private/esp_cache_private.h" +#else +#include "hal/cache_ll.h" +#include "hal/cache_hal.h" +#endif #include "esp_private/mspi_timing_tuning.h" #include "esp_private/mspi_timing_config.h" #include "esp_private/mspi_timing_by_mspi_delay.h" @@ -553,7 +558,12 @@ void mspi_timing_change_speed_mode_cache_safe(bool switch_down) * for preventing concurrent from MSPI to external memory */ #if SOC_CACHE_FREEZE_SUPPORTED +#if !ESP_TEE_BUILD esp_cache_freeze_ext_mem_cache(); +#else + /* NOTE: [ESP-TEE] Check implementation when SoCs with 2-level cache are supported */ + cache_hal_freeze(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL); +#endif #endif //#if SOC_CACHE_FREEZE_SUPPORTED if (switch_down) { @@ -565,7 +575,11 @@ void mspi_timing_change_speed_mode_cache_safe(bool switch_down) } #if SOC_CACHE_FREEZE_SUPPORTED +#if !ESP_TEE_BUILD esp_cache_unfreeze_ext_mem_cache(); +#else + cache_hal_unfreeze(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL); +#endif #endif //#if SOC_CACHE_FREEZE_SUPPORTED #if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE && !CONFIG_FREERTOS_UNICORE diff --git a/components/esp_hw_support/mspi_timing_tuning/port/esp32c5/mspi_timing_tuning_configs.h b/components/esp_hw_support/mspi_timing_tuning/port/esp32c5/mspi_timing_tuning_configs.h index 92262108aa5..c213631d96f 100644 --- a/components/esp_hw_support/mspi_timing_tuning/port/esp32c5/mspi_timing_tuning_configs.h +++ b/components/esp_hw_support/mspi_timing_tuning/port/esp32c5/mspi_timing_tuning_configs.h @@ -28,10 +28,7 @@ #define MSPI_TIMING_FLASH_MODULE_CLOCK 120 #endif //------------------------------------FLASH Needs Tuning or not-------------------------------------// -/* TODO: [ESP-TEE | IDF-10425] The SPI1 controller is protected by APM when ESP-TEE is enabled. - * MSPI tuning requires access to this controller, so it is currently disabled. - */ -#if MSPI_TIMING_FLASH_STR_MODE && !CONFIG_SECURE_ENABLE_TEE +#if MSPI_TIMING_FLASH_STR_MODE #define MSPI_TIMING_FLASH_NEEDS_TUNING (MSPI_TIMING_FLASH_MODULE_CLOCK > 40) #endif @@ -50,8 +47,7 @@ #define MSPI_TIMING_PSRAM_MODULE_CLOCK 10 //Define this to 10MHz #endif //------------------------------------PSRAM Needs Tuning or not-------------------------------------// -/* TODO: [ESP-TEE | IDF-10425] */ -#if MSPI_TIMING_PSRAM_STR_MODE && !CONFIG_SECURE_ENABLE_TEE +#if MSPI_TIMING_PSRAM_STR_MODE #define MSPI_TIMING_PSRAM_NEEDS_TUNING (MSPI_TIMING_PSRAM_MODULE_CLOCK > 40) #endif diff --git a/components/esp_tee/scripts/esp32c5/sec_srv_tbl_default.yml b/components/esp_tee/scripts/esp32c5/sec_srv_tbl_default.yml index 038e8388762..eca52728504 100644 --- a/components/esp_tee/scripts/esp32c5/sec_srv_tbl_default.yml +++ b/components/esp_tee/scripts/esp32c5/sec_srv_tbl_default.yml @@ -96,6 +96,30 @@ secure_services: type: IDF function: spi_flash_chip_generic_config_host_io_mode args: 2 + - id: 23 + type: IDF + function: mspi_timing_flash_tuning + args: 0 + - id: 24 + type: IDF + function: mspi_timing_psram_tuning + args: 0 + - id: 25 + type: IDF + function: mspi_timing_enter_low_speed_mode + args: 1 + - id: 26 + type: IDF + function: mspi_timing_enter_high_speed_mode + args: 1 + - id: 27 + type: IDF + function: mspi_timing_change_speed_mode_cache_safe + args: 1 + - id: 28 + type: IDF + function: spi_timing_get_flash_timing_param + args: 1 # ID: 30-53 (24) - Interrupt Handling - family: interrupt_handling entries: diff --git a/components/esp_tee/src/esp_secure_service_wrapper.c b/components/esp_tee/src/esp_secure_service_wrapper.c index a34ec4df56f..a6c8e39ea3a 100644 --- a/components/esp_tee/src/esp_secure_service_wrapper.c +++ b/components/esp_tee/src/esp_secure_service_wrapper.c @@ -13,7 +13,9 @@ #include "rom/digital_signature.h" #include "hal/mmu_types.h" #include "hal/wdt_hal.h" +#include "hal/spi_flash_hal.h" #include "hal/spi_flash_types.h" +#include "esp_private/mspi_timing_tuning.h" #include "esp_hmac.h" #include "esp_ds.h" #include "esp_crypto_lock.h" @@ -490,4 +492,36 @@ esp_err_t IRAM_ATTR __wrap_spi_flash_chip_generic_config_host_io_mode(esp_flash_ { return esp_tee_service_call(3, SS_SPI_FLASH_CHIP_GENERIC_CONFIG_HOST_IO_MODE, chip, flags); } + +#if CONFIG_IDF_TARGET_ESP32C5 +void IRAM_ATTR __wrap_mspi_timing_flash_tuning(void) +{ + esp_tee_service_call(1, SS_MSPI_TIMING_FLASH_TUNING); +} + +void IRAM_ATTR __wrap_mspi_timing_psram_tuning(void) +{ + esp_tee_service_call(1, SS_MSPI_TIMING_PSRAM_TUNING); +} + +void IRAM_ATTR __wrap_mspi_timing_enter_low_speed_mode(bool control_spi1) +{ + esp_tee_service_call(2, SS_MSPI_TIMING_ENTER_LOW_SPEED_MODE, control_spi1); +} + +void IRAM_ATTR __wrap_mspi_timing_enter_high_speed_mode(bool control_spi1) +{ + esp_tee_service_call(2, SS_MSPI_TIMING_ENTER_HIGH_SPEED_MODE, control_spi1); +} + +void IRAM_ATTR __wrap_mspi_timing_change_speed_mode_cache_safe(bool switch_down) +{ + esp_tee_service_call(2, SS_MSPI_TIMING_CHANGE_SPEED_MODE_CACHE_SAFE, switch_down); +} + +void IRAM_ATTR __wrap_spi_timing_get_flash_timing_param(spi_flash_hal_timing_config_t *out_timing_config) +{ + esp_tee_service_call(2, SS_SPI_TIMING_GET_FLASH_TIMING_PARAM, out_timing_config); +} +#endif #endif diff --git a/components/esp_tee/subproject/main/core/esp_secure_services_iram.c b/components/esp_tee/subproject/main/core/esp_secure_services_iram.c index 169448f406a..0413e147b7c 100644 --- a/components/esp_tee/subproject/main/core/esp_secure_services_iram.c +++ b/components/esp_tee/subproject/main/core/esp_secure_services_iram.c @@ -18,6 +18,7 @@ #include "hal/spi_flash_types.h" #include "spi_flash_chip_generic.h" #include "memspi_host_driver.h" +#include "esp_private/mspi_timing_tuning.h" #include "esp_flash.h" #include "riscv/rv_utils.h" @@ -417,4 +418,36 @@ esp_err_t _ss_spi_flash_chip_generic_config_host_io_mode(esp_flash_t *chip, uint { return spi_flash_chip_generic_config_host_io_mode(chip, flags); } + +#if CONFIG_IDF_TARGET_ESP32C5 +void _ss_mspi_timing_psram_tuning(void) +{ + mspi_timing_psram_tuning(); +} + +void _ss_mspi_timing_flash_tuning(void) +{ + mspi_timing_flash_tuning(); +} + +void _ss_mspi_timing_enter_low_speed_mode(bool control_spi1) +{ + mspi_timing_enter_low_speed_mode(control_spi1); +} + +void _ss_mspi_timing_enter_high_speed_mode(bool control_spi1) +{ + mspi_timing_enter_high_speed_mode(control_spi1); +} + +void _ss_mspi_timing_change_speed_mode_cache_safe(bool switch_down) +{ + mspi_timing_change_speed_mode_cache_safe(switch_down); +} + +void _ss_spi_timing_get_flash_timing_param(spi_flash_hal_timing_config_t *out_timing_config) +{ + spi_timing_get_flash_timing_param(out_timing_config); +} +#endif #endif From bec5090de56ba2a8f8f67d7990aab114a09dde5b Mon Sep 17 00:00:00 2001 From: Jin Cheng Date: Mon, 10 Nov 2025 16:42:56 +0800 Subject: [PATCH 077/106] fix(bt/controller): Fixed some controller bugs - Fixed Bluetooth hardware error of 'CHMAP_ERROR' - Fixed encryption collision bug --- components/bt/controller/lib_esp32 | 2 +- components/esp_rom/esp32/ld/esp32.rom.ld | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/components/bt/controller/lib_esp32 b/components/bt/controller/lib_esp32 index 45910ee1e50..a184fa951eb 160000 --- a/components/bt/controller/lib_esp32 +++ b/components/bt/controller/lib_esp32 @@ -1 +1 @@ -Subproject commit 45910ee1e50236e9d7219429666d7be7965427aa +Subproject commit a184fa951eb366c3d99a968a4171feb33b99fb82 diff --git a/components/esp_rom/esp32/ld/esp32.rom.ld b/components/esp_rom/esp32/ld/esp32.rom.ld index 8fd3ab18c10..6cca533158f 100644 --- a/components/esp_rom/esp32/ld/esp32.rom.ld +++ b/components/esp_rom/esp32/ld/esp32.rom.ld @@ -1633,6 +1633,9 @@ PROVIDE ( ld_pscan_em_init = 0x4003e5e8 ); PROVIDE ( ld_acl_rsw_start = 0x40032e90 ); PROVIDE ( ld_acl_sniff_enter = 0x40031244 ); PROVIDE ( ld_acl_sniff_trans_sched = 0x40033734 ); +PROVIDE ( ld_acl_afh_apply = 0x40030e94 ); +PROVIDE ( ld_acl_afh_switch_on_cbk = 0x40030fa8 ); +PROVIDE ( ld_acl_afh_switch_off_cbk = 0x400310c4 ); PROVIDE ( lc_pwr_decr_ind_handler = 0x4002859c ); PROVIDE ( lc_pwr_incr_ind_handler = 0x400284a8 ); PROVIDE ( lc_pwr_max_ind_handler = 0x40028690 ); From c26ed5dba0be4d2ae40c008642fbf72030775342 Mon Sep 17 00:00:00 2001 From: Armando Date: Fri, 12 Jul 2024 10:39:49 +0800 Subject: [PATCH 078/106] feat(psram): support 250MHz in experimental --- components/esp_hw_support/port/esp32p4/Kconfig.ldo | 8 ++++---- .../test_apps/esp_hw_support_unity_tests/main/test_ldo.c | 2 +- components/esp_psram/device/esp_psram_impl_ap_hex.c | 9 ++------- components/esp_psram/esp32p4/Kconfig.spiram | 6 +++++- components/hal/esp32p4/include/hal/ldo_ll.h | 2 +- 5 files changed, 13 insertions(+), 14 deletions(-) diff --git a/components/esp_hw_support/port/esp32p4/Kconfig.ldo b/components/esp_hw_support/port/esp32p4/Kconfig.ldo index 0e5a20fdd8d..804f685f87f 100644 --- a/components/esp_hw_support/port/esp32p4/Kconfig.ldo +++ b/components/esp_hw_support/port/esp32p4/Kconfig.ldo @@ -52,15 +52,15 @@ menu "LDO Regulator Configurations" choice ESP_LDO_VOLTAGE_PSRAM_DOMAIN prompt "PSRAM power domain voltage" depends on ESP_LDO_RESERVE_PSRAM - default ESP_LDO_VOLTAGE_PSRAM_1900_MV + default ESP_LDO_VOLTAGE_PSRAM_1800_MV help Select the voltage used by the PSRAM power domain. - config ESP_LDO_VOLTAGE_PSRAM_1900_MV - bool "1.9V" + config ESP_LDO_VOLTAGE_PSRAM_1800_MV + bool "1.8V" endchoice config ESP_LDO_VOLTAGE_PSRAM_DOMAIN int - default 1900 if ESP_LDO_VOLTAGE_PSRAM_1900_MV + default 1800 if ESP_LDO_VOLTAGE_PSRAM_1800_MV endmenu diff --git a/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/test_ldo.c b/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/test_ldo.c index fbf38beb4aa..4144bfeeda3 100644 --- a/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/test_ldo.c +++ b/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/test_ldo.c @@ -72,7 +72,7 @@ TEST_CASE("LDO channel state dump", "[LDO][manual][ignore]") esp_ldo_channel_handle_t success_ldo_chans[3] = {}; esp_ldo_channel_config_t ldo_chan_config = { .chan_id = 2, - .voltage_mv = 1900, + .voltage_mv = 1800, }; TEST_ESP_OK(esp_ldo_acquire_channel(&ldo_chan_config, &success_ldo_chans[0])); diff --git a/components/esp_psram/device/esp_psram_impl_ap_hex.c b/components/esp_psram/device/esp_psram_impl_ap_hex.c index 27ab8941241..e7b7001fba9 100644 --- a/components/esp_psram/device/esp_psram_impl_ap_hex.c +++ b/components/esp_psram/device/esp_psram_impl_ap_hex.c @@ -57,6 +57,8 @@ #if CONFIG_SPIRAM_SPEED_80M #define AP_HEX_PSRAM_MPLL_DEFAULT_FREQ_MHZ 320 +#elif CONFIG_SPIRAM_SPEED_250M +#define AP_HEX_PSRAM_MPLL_DEFAULT_FREQ_MHZ 500 #else #define AP_HEX_PSRAM_MPLL_DEFAULT_FREQ_MHZ 400 #endif @@ -467,13 +469,6 @@ esp_err_t esp_psram_impl_enable(void) mode_reg.mr2.density == 0x7 ? PSRAM_SIZE_32MB : mode_reg.mr2.density == 0x6 ? PSRAM_SIZE_64MB : 0; -#if CONFIG_SPIRAM_SPEED_250M - if (mode_reg.mr2.density == 0x7) { - ESP_EARLY_LOGE(TAG, "PSRAM Not support 250MHz speed"); - return ESP_ERR_NOT_SUPPORTED; - } -#endif - s_config_mspi_for_psram(); mspi_timing_psram_tuning(); psram_ctrlr_ll_enable_variable_dummy(PSRAM_CTRLR_LL_MSPI_ID_2, true); diff --git a/components/esp_psram/esp32p4/Kconfig.spiram b/components/esp_psram/esp32p4/Kconfig.spiram index b8e741fa247..4626fde0bdb 100644 --- a/components/esp_psram/esp32p4/Kconfig.spiram +++ b/components/esp_psram/esp32p4/Kconfig.spiram @@ -30,8 +30,11 @@ menu "PSRAM config" help Select the speed for the PSRAM chip. + config SPIRAM_SPEED_250M + depends on !ESP32P4_SELECTS_REV_LESS_V3 + bool "250MHz clock speed" + config SPIRAM_SPEED_200M - depends on IDF_EXPERIMENTAL_FEATURES bool "200MHz clock speed" config SPIRAM_SPEED_80M @@ -47,6 +50,7 @@ menu "PSRAM config" default 80 if SPIRAM_SPEED_80M default 100 if SPIRAM_SPEED_100M default 200 if SPIRAM_SPEED_200M + default 250 if SPIRAM_SPEED_250M config SPIRAM_FETCH_INSTRUCTIONS bool diff --git a/components/hal/esp32p4/include/hal/ldo_ll.h b/components/hal/esp32p4/include/hal/ldo_ll.h index 1a270305ddf..a8d8c164836 100644 --- a/components/hal/esp32p4/include/hal/ldo_ll.h +++ b/components/hal/esp32p4/include/hal/ldo_ll.h @@ -129,7 +129,7 @@ static inline void ldo_ll_voltage_to_dref_mul(int ldo_unit, int voltage_mv, uint matched_dref = EFUSE.rd_mac_sys_2.ldo_vo1_dref; } } - if (ldo_unit == 1 && voltage_mv == 1900) { + if (ldo_unit == 1 && voltage_mv == 1800) { if (EFUSE.rd_mac_sys_2.ldo_vo2_dref && EFUSE.rd_mac_sys_3.ldo_vo2_mul) { matched_mul = EFUSE.rd_mac_sys_3.ldo_vo2_mul; matched_dref = EFUSE.rd_mac_sys_2.ldo_vo2_dref; From 6815f7a71b9cfe8bfebc11be783bf35cf3607e04 Mon Sep 17 00:00:00 2001 From: "harshal.patil" Date: Thu, 13 Nov 2025 12:33:41 +0530 Subject: [PATCH 079/106] test(examples): Fix cert bundle stress test --- .../protocols/https_x509_bundle/sdkconfig.ci.default_crt_bundle | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/protocols/https_x509_bundle/sdkconfig.ci.default_crt_bundle b/examples/protocols/https_x509_bundle/sdkconfig.ci.default_crt_bundle index d0e1451c3e3..59a0ecd5c5b 100644 --- a/examples/protocols/https_x509_bundle/sdkconfig.ci.default_crt_bundle +++ b/examples/protocols/https_x509_bundle/sdkconfig.ci.default_crt_bundle @@ -1,4 +1,5 @@ CONFIG_IDF_TARGET="esp32" +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_CROSS_SIGNED_VERIFY=y CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=y # QEMU-Related configurations From 21a2b068c63f35f51015a7f7acd66f43c154e4e7 Mon Sep 17 00:00:00 2001 From: Chen Jian Hua Date: Fri, 14 Nov 2025 13:33:23 +0800 Subject: [PATCH 080/106] feat(ble/bluedroid): Add more debug log for bluedroid (cherry picked from commit 1aeb965607215e0c08c0035c7a8dfdc4ecba981e) Co-authored-by: chenjianhua --- components/bt/common/include/bt_common.h | 10 ++++ components/bt/common/include/bt_user_config.h | 18 +++++++ components/bt/common/osi/allocator.c | 8 ++- components/bt/common/osi/thread.c | 50 +++++++++++++++++ components/bt/host/bluedroid/Kconfig.in | 41 +++++++++++--- .../host/bluedroid/bta/gatt/bta_gattc_act.c | 6 +++ .../bt/host/bluedroid/bta/gatt/bta_gattc_co.c | 4 +- .../host/bluedroid/bta/gatt/bta_gattc_utils.c | 5 +- .../bluedroid/bta/include/bta/bta_gatt_api.h | 2 + .../common/include/common/bt_trace.h | 8 +++ components/bt/host/bluedroid/hci/hci_layer.c | 28 ++++++++++ .../bt/host/bluedroid/hci/packet_fragmenter.c | 3 +- .../bt/host/bluedroid/stack/btm/btm_acl.c | 2 +- .../bt/host/bluedroid/stack/btm/btm_ble.c | 32 +++++------ .../host/bluedroid/stack/btm/btm_ble_bgconn.c | 1 + .../bt/host/bluedroid/stack/btm/btm_ble_gap.c | 1 + .../bt/host/bluedroid/stack/btm/btm_dev.c | 10 ++-- .../host/bluedroid/stack/gatt/att_protocol.c | 6 +-- .../bt/host/bluedroid/stack/gatt/gatt_main.c | 3 +- .../bt/host/bluedroid/stack/gatt/gatt_sr.c | 4 +- .../bt/host/bluedroid/stack/gatt/gatt_utils.c | 5 +- .../bt/host/bluedroid/stack/hcic/hciblecmds.c | 6 +++ .../bt/host/bluedroid/stack/l2cap/l2c_api.c | 6 ++- .../bt/host/bluedroid/stack/l2cap/l2c_ble.c | 32 +++++------ .../bt/host/bluedroid/stack/l2cap/l2c_utils.c | 3 ++ .../bt/host/bluedroid/stack/smp/smp_act.c | 54 +++++++++---------- .../bt/host/bluedroid/stack/smp/smp_api.c | 8 +-- .../bt/host/bluedroid/stack/smp/smp_keys.c | 26 ++++----- .../bt/host/bluedroid/stack/smp/smp_utils.c | 3 +- 29 files changed, 276 insertions(+), 109 deletions(-) diff --git a/components/bt/common/include/bt_common.h b/components/bt/common/include/bt_common.h index 1ebd5b14383..220456b8a86 100644 --- a/components/bt/common/include/bt_common.h +++ b/components/bt/common/include/bt_common.h @@ -61,6 +61,16 @@ #define HEAP_MEMORY_DEBUG FALSE #endif +#if UC_BT_BLUEDROID_THREAD_DEBUG +#define OSI_THREAD_DEBUG TRUE +#else +#define OSI_THREAD_DEBUG FALSE +#endif + +#define OSI_THREAD_BLOCK_TIME UC_BT_BLUEDROID_THREAD_BLOCK_TIME + +#define OSI_THREAD_BLOCK_MSG UC_BT_BLUEDROID_THREAD_BLOCK_MSG + #ifndef BT_BLE_DYNAMIC_ENV_MEMORY #define BT_BLE_DYNAMIC_ENV_MEMORY FALSE #endif diff --git a/components/bt/common/include/bt_user_config.h b/components/bt/common/include/bt_user_config.h index 5632b5fe22a..2d695fa1c33 100644 --- a/components/bt/common/include/bt_user_config.h +++ b/components/bt/common/include/bt_user_config.h @@ -107,6 +107,24 @@ #define UC_BT_BLUEDROID_MEM_DEBUG FALSE #endif +#ifdef CONFIG_BT_BLUEDROID_THREAD_DEBUG +#define UC_BT_BLUEDROID_THREAD_DEBUG TRUE +#else +#define UC_BT_BLUEDROID_THREAD_DEBUG FALSE +#endif + +#ifdef CONFIG_BT_BLUEDROID_THREAD_BLOCK_TIME +#define UC_BT_BLUEDROID_THREAD_BLOCK_TIME CONFIG_BT_BLUEDROID_THREAD_BLOCK_TIME +#else +#define UC_BT_BLUEDROID_THREAD_BLOCK_TIME 1000 +#endif + +#ifdef CONFIG_BT_BLUEDROID_THREAD_BLOCK_MSG +#define UC_BT_BLUEDROID_THREAD_BLOCK_MSG CONFIG_BT_BLUEDROID_THREAD_BLOCK_MSG +#else +#define UC_BT_BLUEDROID_THREAD_BLOCK_MSG 50 +#endif + #ifdef CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST #define UC_HEAP_ALLOCATION_FROM_SPIRAM_FIRST CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST #else diff --git a/components/bt/common/osi/allocator.c b/components/bt/common/osi/allocator.c index 86fb705b071..30de8bb0289 100644 --- a/components/bt/common/osi/allocator.c +++ b/components/bt/common/osi/allocator.c @@ -216,7 +216,9 @@ void *osi_malloc_func(size_t size) void *p = osi_malloc_base(size); if (size != 0 && p == NULL) { - OSI_TRACE_ERROR("malloc failed (caller=%p size=%u)\n", __builtin_return_address(0), size); + OSI_TRACE_ERROR("malloc failed (caller=%p size=%u)", __builtin_return_address(0), size); + OSI_TRACE_ERROR("heap info: free=%d, largest_block=%d", + heap_caps_get_free_size(MALLOC_CAP_DEFAULT), heap_caps_get_largest_free_block(MALLOC_CAP_DEFAULT)); #if HEAP_ALLOCATION_FAILS_ABORT assert(0); #endif @@ -230,7 +232,9 @@ void *osi_calloc_func(size_t size) void *p = osi_calloc_base(size); if (size != 0 && p == NULL) { - OSI_TRACE_ERROR("calloc failed (caller=%p size=%u)\n", __builtin_return_address(0), size); + OSI_TRACE_ERROR("calloc failed (caller=%p size=%u)", __builtin_return_address(0), size); + OSI_TRACE_ERROR("heap info: free=%d, largest_block=%d", + heap_caps_get_free_size(MALLOC_CAP_DEFAULT), heap_caps_get_largest_free_block(MALLOC_CAP_DEFAULT)); #if HEAP_ALLOCATION_FAILS_ABORT assert(0); #endif diff --git a/components/bt/common/osi/thread.c b/components/bt/common/osi/thread.c index 91bc7906cea..95475670be5 100644 --- a/components/bt/common/osi/thread.c +++ b/components/bt/common/osi/thread.c @@ -61,6 +61,10 @@ struct osi_event { static const size_t DEFAULT_WORK_QUEUE_CAPACITY = 100; +#if OSI_THREAD_DEBUG +static void osi_thread_run_item(osi_thread_t *thread, int wq_idx, struct work_item *item); +#endif + static struct work_queue *osi_work_queue_create(size_t capacity) { if (capacity == 0) { @@ -162,7 +166,11 @@ static void osi_thread_run(void *arg) struct work_item item; while (!thread->stop && idx < thread->work_queue_num) { if (osi_thead_work_queue_get(thread->work_queues[idx], &item) == true) { + #if OSI_THREAD_DEBUG + osi_thread_run_item(thread, idx, &item); + #else item.func(item.context); + #endif idx = 0; continue; } else { @@ -451,3 +459,45 @@ bool osi_thread_post_event(struct osi_event *event, uint32_t timeout) return ret; } + +#if OSI_THREAD_DEBUG +static void osi_thread_run_item(osi_thread_t *thread, int wq_idx, struct work_item *item) +{ + uint32_t pre_time; + uint32_t pre_msg_cnt; + uint32_t cur_time; + uint32_t cur_msg_cnt; + + pre_time = esp_log_timestamp(); + pre_msg_cnt = uxQueueMessagesWaiting(thread->work_queues[wq_idx]->queue); + item->func(item->context); + cur_time = esp_log_timestamp(); + cur_msg_cnt = uxQueueMessagesWaiting(thread->work_queues[wq_idx]->queue); + if ((cur_time - pre_time) >= OSI_THREAD_BLOCK_TIME || + (cur_msg_cnt > pre_msg_cnt && (cur_msg_cnt - pre_msg_cnt) >= OSI_THREAD_BLOCK_MSG)) { + OSI_TRACE_ERROR("%s was blocked while running item: %p exec_time=[%u %u] msg_inc=[%u %u]", + pcTaskGetName(thread->thread_handle), item->func, cur_time, pre_time, cur_msg_cnt, pre_msg_cnt); + assert(0); + } +} + +void osi_thread_workqueue_dump(osi_thread_t *thread) +{ + int idx = 0; + struct work_item item; + + vTaskSuspendAll(); + + while (idx < thread->work_queue_num) { + if (osi_thead_work_queue_get(thread->work_queues[idx], &item) == true) { + esp_rom_printf("[%u] %p %p\n", idx, item.func, item.context); + idx = 0; + continue; + } else { + idx++; + } + } + + xTaskResumeAll(); +} +#endif // OSI_THREAD_DEBUG diff --git a/components/bt/host/bluedroid/Kconfig.in b/components/bt/host/bluedroid/Kconfig.in index 1d4b24b195b..aca97930f6b 100644 --- a/components/bt/host/bluedroid/Kconfig.in +++ b/components/bt/host/bluedroid/Kconfig.in @@ -33,13 +33,6 @@ config BT_BTU_TASK_STACK_SIZE help This select btu task stack size -config BT_BLUEDROID_MEM_DEBUG - bool "Bluedroid memory debug" - depends on BT_BLUEDROID_ENABLED - default n - help - Bluedroid memory debug - config BT_BLUEDROID_ESP_COEX_VSC bool "Enable Espressif Vendor-specific HCI commands for coexist status configuration" depends on BT_BLUEDROID_ENABLED @@ -462,6 +455,40 @@ config BT_BLE_RPA_SUPPORTED For other BLE chips, devices support network privacy mode and device privacy mode, users can switch the two modes according to their own needs. So this option is enabled by default. +menu "Bluedroid debug option" + config BT_BLUEDROID_MEM_DEBUG + bool "Bluedroid memory debug" + depends on BT_BLUEDROID_ENABLED + default n + help + Bluedroid memory debug + + config BT_BLUEDROID_THREAD_DEBUG + bool "Bluedroid thread debug" + depends on BT_BLUEDROID_ENABLED + default n + help + Enable Bluedroid thread debug mode. + Used to debug whether the thread is blocked and + dump information about the thread’s related work queue. + + config BT_BLUEDROID_THREAD_BLOCK_TIME + int "OSI thread block time (in ms)" + depends on BT_BLUEDROID_THREAD_DEBUG + default 1000 + help + Indicates how long it takes for the thread to execute an item + before it is considered blocked. + + config BT_BLUEDROID_THREAD_BLOCK_MSG + int "OSI thread block message count" + depends on BT_BLUEDROID_THREAD_DEBUG + default 50 + help + Indicates how many messages are added to the queue + while the threadis executing an item before it is considered blocked. +endmenu #BT debug option + config BT_STACK_NO_LOG bool "Disable BT debug logs (minimize bin size)" depends on BT_BLUEDROID_ENABLED diff --git a/components/bt/host/bluedroid/bta/gatt/bta_gattc_act.c b/components/bt/host/bluedroid/bta/gatt/bta_gattc_act.c index eb2b091eae1..06c565dc2d2 100644 --- a/components/bt/host/bluedroid/bta/gatt/bta_gattc_act.c +++ b/components/bt/host/bluedroid/bta/gatt/bta_gattc_act.c @@ -727,6 +727,7 @@ void bta_gattc_conn(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) #if (GATTC_CACHE_NVS == TRUE) p_clcb->p_srcb->state = BTA_GATTC_SERV_LOAD; if (bta_gattc_cache_load(p_clcb)) { + APPL_TRACE_DEBUG("%s found gattc cache", __func__); p_clcb->p_srcb->state = BTA_GATTC_SERV_IDLE; bta_gattc_reset_discover_st(p_clcb->p_srcb, BTA_GATT_OK); //register service change @@ -734,6 +735,7 @@ void bta_gattc_conn(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) } else #endif { /* cache is building */ + APPL_TRACE_DEBUG("%s cache not found, start discovery %u", __func__, bta_gattc_cb.auto_disc); if (bta_gattc_cb.auto_disc) { p_clcb->p_srcb->state = BTA_GATTC_SERV_DISC; /* cache load failure, start discovery */ @@ -1847,6 +1849,8 @@ void bta_gattc_process_api_refresh(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg) UINT8 i; UNUSED(p_cb); + APPL_TRACE_DEBUG("%s", __func__); + if (p_srvc_cb != NULL) { /* try to find a CLCB */ if (p_srvc_cb->connected && p_srvc_cb->num_clcb != 0) { @@ -1965,6 +1969,8 @@ void bta_gattc_process_api_cache_clean(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_m tBTA_GATTC_SERV *p_srvc_cb = bta_gattc_find_srvr_cache(p_msg->api_clean.remote_bda); UNUSED(p_cb); + APPL_TRACE_DEBUG("%s", __func__); + if (p_srvc_cb != NULL && p_srvc_cb->p_srvc_cache != NULL) { //mark it and delete the cache */ list_free(p_srvc_cb->p_srvc_cache); diff --git a/components/bt/host/bluedroid/bta/gatt/bta_gattc_co.c b/components/bt/host/bluedroid/bta/gatt/bta_gattc_co.c index 8ec3a55dffd..d6ca7bca475 100644 --- a/components/bt/host/bluedroid/bta/gatt/bta_gattc_co.c +++ b/components/bt/host/bluedroid/bta/gatt/bta_gattc_co.c @@ -444,6 +444,8 @@ void bta_gattc_co_cache_addr_init(void) void bta_gattc_co_cache_addr_deinit(void) { + APPL_TRACE_DEBUG("%s is_open=%d", __func__, cache_env->is_open); + if(!cache_env->is_open) { return; } @@ -553,7 +555,7 @@ void bta_gattc_co_cache_addr_save(BD_ADDR bd_addr, hash_key_t hash_key) memcpy(cache_env->cache_addr[new_index].addr, bd_addr, sizeof(BD_ADDR)); memcpy(cache_env->cache_addr[new_index].hash_key, hash_key, sizeof(hash_key_t)); cache_env->num_addr++; - APPL_TRACE_DEBUG("%s(), num = %d", __func__, cache_env->num_addr); + APPL_TRACE_DEBUG("%s bd_addr="MACSTR" num=%d", __func__, MAC2STR(bd_addr), cache_env->num_addr); } nvs_handle_t *fp = &cache_env->addr_fp; diff --git a/components/bt/host/bluedroid/bta/gatt/bta_gattc_utils.c b/components/bt/host/bluedroid/bta/gatt/bta_gattc_utils.c index f0216f2de79..4b2d0192529 100644 --- a/components/bt/host/bluedroid/bta/gatt/bta_gattc_utils.c +++ b/components/bt/host/bluedroid/bta/gatt/bta_gattc_utils.c @@ -327,6 +327,8 @@ void bta_gattc_clcb_dealloc_by_conn_id(UINT16 conn_id) { tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id); + APPL_TRACE_DEBUG("%s conn_id=%u p_clcb=%p", __func__, conn_id, p_clcb); + if (p_clcb) { tBTA_GATTC_RCB *p_clreg = p_clcb->p_rcb; bta_gattc_clcb_dealloc(p_clcb); @@ -523,8 +525,7 @@ BOOLEAN bta_gattc_enqueue(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) cmd_data->api_write.p_value = (UINT8 *)(cmd_data + 1); memcpy(cmd_data->api_write.p_value, p_data->api_write.p_value, len); } else { - APPL_TRACE_ERROR("%s(), line = %d, alloc fail, size %d,no memory. free=%d, largest_block=%d", __func__, __LINE__, - heap_caps_get_free_size(MALLOC_CAP_DEFAULT), heap_caps_get_largest_free_block(MALLOC_CAP_DEFAULT)); + APPL_TRACE_ERROR("%s(), line = %d, alloc fail, no memory.", __func__, __LINE__); return FALSE; } } else { diff --git a/components/bt/host/bluedroid/bta/include/bta/bta_gatt_api.h b/components/bt/host/bluedroid/bta/include/bta/bta_gatt_api.h index a42d14084ba..0208edd9549 100644 --- a/components/bt/host/bluedroid/bta/include/bta/bta_gatt_api.h +++ b/components/bt/host/bluedroid/bta/include/bta/bta_gatt_api.h @@ -39,9 +39,11 @@ #endif +#if (APPL_INITIAL_TRACE_LEVEL >= BT_TRACE_LEVEL_DEBUG) #ifndef BTA_GATT_DEBUG #define BTA_GATT_DEBUG FALSE #endif +#endif typedef enum { BTGATT_DB_PRIMARY_SERVICE, diff --git a/components/bt/host/bluedroid/common/include/common/bt_trace.h b/components/bt/host/bluedroid/common/include/common/bt_trace.h index bd3b1ed8fcd..85ddbe58d46 100644 --- a/components/bt/host/bluedroid/common/include/common/bt_trace.h +++ b/components/bt/host/bluedroid/common/include/common/bt_trace.h @@ -57,6 +57,14 @@ static inline void trc_dump_buffer(const char *prefix, uint8_t *data, uint16_t l #define BTTRC_DUMP_BUFFER(_prefix, _data, _len) #endif +#ifndef MAC2STR +#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] +#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" +#endif + +/* Support up to 64 bytes of buffer */ +const char *bt_hex2str(const void *buf, size_t len); + //static const char BTE_LOGMSG_MODULE[] = "bte_logmsg_module"; /* BTrgs);E tracing IDs for debug purposes */ diff --git a/components/bt/host/bluedroid/hci/hci_layer.c b/components/bt/host/bluedroid/hci/hci_layer.c index 59b69bc0a71..12d36296a1f 100644 --- a/components/bt/host/bluedroid/hci/hci_layer.c +++ b/components/bt/host/bluedroid/hci/hci_layer.c @@ -51,6 +51,10 @@ #define HCI_DOWNSTREAM_DATA_QUEUE_IDX (0) +#ifndef MIN +#define MIN(a,b) (((a)<(b))?(a):(b)) +#endif + typedef struct { bool timer_is_set; osi_alarm_t *command_response_timer; @@ -707,3 +711,27 @@ const char *hci_status_code_to_string(uint8_t status) } } #endif + +const char *bt_hex2str(const void *buf, size_t len) +{ + static const char hex[] = "0123456789abcdef"; + static char str[129]; + const uint8_t *b = buf; + size_t i; + + len = MIN(len, (sizeof(str) - 1) / 2); + + for (i = 0; i < len; i++) { + str[i * 2] = hex[b[i] >> 4]; + str[i * 2 + 1] = hex[b[i] & 0xf]; + } + + str[i * 2] = '\0'; + + return str; +} + +int get_hci_work_queue_size(int wq_idx) +{ + return osi_thread_queue_wait_size(hci_host_thread, wq_idx); +} diff --git a/components/bt/host/bluedroid/hci/packet_fragmenter.c b/components/bt/host/bluedroid/hci/packet_fragmenter.c index dff48be0a31..bfb9843eb39 100644 --- a/components/bt/host/bluedroid/hci/packet_fragmenter.c +++ b/components/bt/host/bluedroid/hci/packet_fragmenter.c @@ -173,8 +173,7 @@ static void reassemble_and_dispatch(BT_HDR *packet) partial_packet = (BT_HDR *)osi_calloc(full_length + sizeof(BT_HDR)); if (partial_packet == NULL) { - HCI_TRACE_WARNING("%s full_length %d no memory, free=%d, largest_block=%d", __func__, full_length, - heap_caps_get_free_size(MALLOC_CAP_DEFAULT), heap_caps_get_largest_free_block(MALLOC_CAP_DEFAULT)); + HCI_TRACE_WARNING("%s full_length %d no memory.", __func__, full_length); assert(0); } diff --git a/components/bt/host/bluedroid/stack/btm/btm_acl.c b/components/bt/host/bluedroid/stack/btm/btm_acl.c index fdce6261ff2..c97e09f97db 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_acl.c +++ b/components/bt/host/bluedroid/stack/btm/btm_acl.c @@ -786,7 +786,7 @@ void btm_acl_encrypt_change (UINT16 handle, UINT8 status, UINT8 encr_enable) tBTM_SEC_DEV_REC *p_dev_rec; tBTM_BL_ROLE_CHG_DATA evt; - BTM_TRACE_DEBUG ("btm_acl_encrypt_change handle=%d status=%d encr_enabl=%d\n", + BTM_TRACE_DEBUG ("btm_acl_encrypt_change handle=%d status=%d encr_enable=%d\n", handle, status, encr_enable); p = btm_handle_to_acl(handle); if (p == NULL) { diff --git a/components/bt/host/bluedroid/stack/btm/btm_ble.c b/components/bt/host/bluedroid/stack/btm/btm_ble.c index da8137e4327..cfecb85887f 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_ble.c +++ b/components/bt/host/bluedroid/stack/btm/btm_ble.c @@ -77,18 +77,16 @@ BOOLEAN BTM_SecAddBleDevice (BD_ADDR bd_addr, BD_NAME bd_name, tBT_DEVICE_TYPE d tBTM_SEC_DEV_REC *p_dev_rec; tBTM_INQ_INFO *p_info = NULL; - BTM_TRACE_DEBUG ("BTM_SecAddBleDevice dev_type=0x%x", dev_type); + BTM_TRACE_DEBUG ("%s dev_type=0x%x bd_addr="MACSTR"", __func__, dev_type, MAC2STR(bd_addr)); p_dev_rec = btm_find_dev (bd_addr); if (!p_dev_rec) { - BTM_TRACE_DEBUG("Add a new device"); - /* There is no device record, allocate one. * If we can not find an empty spot for this one, let it fail. */ if (list_length(btm_cb.p_sec_dev_rec_list) < BTM_SEC_MAX_DEVICE_RECORDS) { - p_dev_rec = (tBTM_SEC_DEV_REC *)osi_malloc(sizeof(tBTM_SEC_DEV_REC)); - if(p_dev_rec) { - list_append(btm_cb.p_sec_dev_rec_list, p_dev_rec); + p_dev_rec = (tBTM_SEC_DEV_REC *)osi_malloc(sizeof(tBTM_SEC_DEV_REC)); + if (p_dev_rec) { + list_append(btm_cb.p_sec_dev_rec_list, p_dev_rec); BTM_TRACE_DEBUG ("allocate a new dev rec idx=0x%x\n", list_length(btm_cb.p_sec_dev_rec_list)); /* Mark this record as in use and initialize */ @@ -158,22 +156,20 @@ BOOLEAN BTM_SecAddBleDevice (BD_ADDR bd_addr, BD_NAME bd_name, tBT_DEVICE_TYPE d BOOLEAN BTM_SecAddBleKey (BD_ADDR bd_addr, tBTM_LE_KEY_VALUE *p_le_key, tBTM_LE_KEY_TYPE key_type) { tBTM_SEC_DEV_REC *p_dev_rec; - BTM_TRACE_DEBUG ("BTM_SecAddBleKey"); p_dev_rec = btm_find_dev (bd_addr); + if (!p_dev_rec || !p_le_key || (key_type != BTM_LE_KEY_PENC && key_type != BTM_LE_KEY_PID && key_type != BTM_LE_KEY_PCSRK && key_type != BTM_LE_KEY_LENC && key_type != BTM_LE_KEY_LCSRK && key_type != BTM_LE_KEY_LID)) { - BTM_TRACE_WARNING ("BTM_SecAddBleKey() Wrong Type, or No Device record \ - for bdaddr: %08x%04x, Type: %d", - (bd_addr[0] << 24) + (bd_addr[1] << 16) + (bd_addr[2] << 8) + bd_addr[3], - (bd_addr[4] << 8) + bd_addr[5], key_type); + BTM_TRACE_WARNING ("BTM_SecAddBleKey() Wrong Type, or No Device record \ + for bdaddr: "MACSTR", key_type: %02x", + MAC2STR(bd_addr), key_type); return (FALSE); } - BTM_TRACE_DEBUG ("BTM_SecAddLeKey() BDA: %08x%04x, Type: 0x%02x", - (bd_addr[0] << 24) + (bd_addr[1] << 16) + (bd_addr[2] << 8) + bd_addr[3], - (bd_addr[4] << 8) + bd_addr[5], key_type); + BTM_TRACE_DEBUG ("BTM_SecAddLeKey() BDA: "MACSTR", key_type: 0x%02x", + MAC2STR(bd_addr), key_type); btm_sec_save_le_key (bd_addr, key_type, p_le_key, FALSE); @@ -1756,15 +1752,14 @@ void btm_ble_ltk_request_reply(BD_ADDR bda, BOOLEAN use_stk, BT_OCTET16 stk) tBTM_CB *p_cb = &btm_cb; if (p_rec == NULL) { - BTM_TRACE_ERROR("btm_ble_ltk_request_reply received for unknown device"); + BTM_TRACE_ERROR("%s received for unknown device "MACSTR"", __func__, MAC2STR(bda)); return; } - BTM_TRACE_DEBUG ("btm_ble_ltk_request_reply"); + BTM_TRACE_DEBUG ("%s key_type=%x key_size=%d", __func__, p_rec->ble.key_type, p_rec->ble.keys.key_size); p_cb->enc_handle = p_rec->ble_hci_handle; p_cb->key_size = p_rec->ble.keys.key_size; - BTM_TRACE_DEBUG("key size = %d", p_rec->ble.keys.key_size); if (use_stk) { btsnd_hcic_ble_ltk_req_reply(btm_cb.enc_handle, stk); } else { /* calculate LTK using peer device */ @@ -2044,7 +2039,8 @@ void btm_ble_conn_complete(UINT8 *p, UINT16 evt_len, BOOLEAN enhanced) STREAM_TO_UINT8 (role, p); STREAM_TO_UINT8 (bda_type, p); STREAM_TO_BDADDR (bda, p); - BTM_TRACE_DEBUG("status = %d, handle = %d, role = %d, bda_type = %d",status,handle,role,bda_type); + BTM_TRACE_DEBUG("status=%d handle=%d role=%d bda_type=%d bda="MACSTR"", + status, handle, role, bda_type, MAC2STR(bda)); if (status == 0) { if (enhanced) { STREAM_TO_BDADDR (local_rpa, p); diff --git a/components/bt/host/bluedroid/stack/btm/btm_ble_bgconn.c b/components/bt/host/bluedroid/stack/btm/btm_ble_bgconn.c index bf9b1adbff3..1210a26458d 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_ble_bgconn.c +++ b/components/bt/host/bluedroid/stack/btm/btm_ble_bgconn.c @@ -821,6 +821,7 @@ tBTM_BLE_CONN_ST btm_ble_get_conn_st(void) *******************************************************************************/ void btm_ble_set_conn_st(tBTM_BLE_CONN_ST new_st) { + BTM_TRACE_DEBUG("%s old=%u new=%u", __func__, btm_cb.ble_ctr_cb.conn_state, new_st); btm_cb.ble_ctr_cb.conn_state = new_st; if (new_st == BLE_BG_CONN || new_st == BLE_DIR_CONN) { diff --git a/components/bt/host/bluedroid/stack/btm/btm_ble_gap.c b/components/bt/host/bluedroid/stack/btm/btm_ble_gap.c index faf2e1848f0..edb52e9e66d 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_ble_gap.c +++ b/components/bt/host/bluedroid/stack/btm/btm_ble_gap.c @@ -2136,6 +2136,7 @@ void BTM_Recovery_Pre_State(void) { #if ((BLE_42_ADV_EN == TRUE) || (BLE_42_SCAN_EN == TRUE)) tBTM_BLE_INQ_CB *ble_inq_cb = &btm_cb.ble_ctr_cb.inq_var; + BTM_TRACE_DEBUG("%s state=0x%x", __func__, ble_inq_cb->state); #endif // #if ((BLE_42_ADV_EN == TRUE) || (BLE_42_SCAN_EN == TRUE)) #if (BLE_42_ADV_EN == TRUE) if (ble_inq_cb->state & BTM_BLE_ADVERTISING) { diff --git a/components/bt/host/bluedroid/stack/btm/btm_dev.c b/components/bt/host/bluedroid/stack/btm/btm_dev.c index 1784d4a3535..cc5ad3358b0 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_dev.c +++ b/components/bt/host/bluedroid/stack/btm/btm_dev.c @@ -73,9 +73,11 @@ BOOLEAN BTM_SecAddDevice (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name, /* There is no device record, allocate one. * If we can not find an empty spot for this one, let it fail. */ if (list_length(btm_cb.p_sec_dev_rec_list) < BTM_SEC_MAX_DEVICE_RECORDS) { - p_dev_rec = (tBTM_SEC_DEV_REC *)osi_malloc(sizeof(tBTM_SEC_DEV_REC)); - if(p_dev_rec) { - list_append(btm_cb.p_sec_dev_rec_list, p_dev_rec); + p_dev_rec = (tBTM_SEC_DEV_REC *)osi_malloc(sizeof(tBTM_SEC_DEV_REC)); + if(p_dev_rec) { + BTM_TRACE_DEBUG("%s alloc a new dev rec %p bd_addr="MACSTR"", + __func__, p_dev_rec, MAC2STR(bd_addr)); + list_append(btm_cb.p_sec_dev_rec_list, p_dev_rec); /* Mark this record as in use and initialize */ memset (p_dev_rec, 0, sizeof (tBTM_SEC_DEV_REC)); p_dev_rec->sec_flags = BTM_SEC_IN_USE; @@ -360,6 +362,8 @@ tBTM_SEC_DEV_REC *btm_sec_alloc_dev (BD_ADDR bd_addr) if (list_length(btm_cb.p_sec_dev_rec_list) < BTM_SEC_MAX_DEVICE_RECORDS){ p_dev_new_rec = (tBTM_SEC_DEV_REC *)osi_malloc(sizeof(tBTM_SEC_DEV_REC)); if (p_dev_new_rec) { + BTM_TRACE_DEBUG("%s alloc a new dev rec %p bd_addr="MACSTR"", + __func__, p_dev_new_rec, MAC2STR(bd_addr)); new_entry_found = TRUE; malloc_new_entry = TRUE; } else { diff --git a/components/bt/host/bluedroid/stack/gatt/att_protocol.c b/components/bt/host/bluedroid/stack/gatt/att_protocol.c index 310a9756efe..c242cc8e053 100644 --- a/components/bt/host/bluedroid/stack/gatt/att_protocol.c +++ b/components/bt/host/bluedroid/stack/gatt/att_protocol.c @@ -33,7 +33,7 @@ #define GATT_HDR_FIND_TYPE_VALUE_LEN 21 #define GATT_OP_CODE_SIZE 1 /********************************************************************** -** ATT protocl message building utility * +** ATT protocol message building utility * ***********************************************************************/ /******************************************************************************* ** @@ -462,7 +462,7 @@ BT_HDR *attp_build_sr_msg(tGATT_TCB *p_tcb, UINT8 op_code, tGATT_SR_MSG *p_msg) ** Description This function sends the server response or indication message ** to client. ** -** Parameter p_tcb: pointer to the connecton control block. +** Parameter p_tcb: pointer to the connection control block. ** p_msg: pointer to message parameters structure. ** ** Returns GATT_SUCCESS if successfully sent; otherwise error code. @@ -628,7 +628,7 @@ tGATT_STATUS attp_send_cl_msg (tGATT_TCB *p_tcb, UINT16 clcb_idx, UINT8 op_code, if (p_cmd != NULL) { status = attp_cl_send_cmd(p_tcb, clcb_idx, op_code, p_cmd); } - + GATT_TRACE_DEBUG("%s opcode=%x status=%x", __func__, op_code, status); } else { GATT_TRACE_ERROR("Peer device not connected"); } diff --git a/components/bt/host/bluedroid/stack/gatt/gatt_main.c b/components/bt/host/bluedroid/stack/gatt/gatt_main.c index e5d98237125..0783255d0be 100644 --- a/components/bt/host/bluedroid/stack/gatt/gatt_main.c +++ b/components/bt/host/bluedroid/stack/gatt/gatt_main.c @@ -995,6 +995,7 @@ void gatt_data_process (tGATT_TCB *p_tcb, BT_HDR *p_buf) pseudo_op_code = op_code & (~GATT_WRITE_CMD_MASK); if (pseudo_op_code < GATT_OP_CODE_MAX) { + GATT_TRACE_DEBUG("%s opcode=%x msg_len=%u", __func__, op_code, msg_len); if (op_code == GATT_SIGN_CMD_WRITE) { #if (SMP_INCLUDED == TRUE) gatt_verify_signature(p_tcb, p_buf); @@ -1220,7 +1221,6 @@ tGATT_CH_STATE gatt_get_ch_state(tGATT_TCB *p_tcb) { tGATT_CH_STATE ch_state = GATT_CH_CLOSE; if (p_tcb) { - GATT_TRACE_DEBUG ("gatt_get_ch_state: ch_state=%d", p_tcb->ch_state); ch_state = p_tcb->ch_state; } return ch_state; @@ -1233,6 +1233,7 @@ uint16_t gatt_get_local_mtu(void) void gatt_set_local_mtu(uint16_t mtu) { + GATT_TRACE_DEBUG("%s mtu=%u", __func__, mtu); gatt_default.local_mtu = mtu; } diff --git a/components/bt/host/bluedroid/stack/gatt/gatt_sr.c b/components/bt/host/bluedroid/stack/gatt/gatt_sr.c index 5947239cf1f..585a4c921a0 100644 --- a/components/bt/host/bluedroid/stack/gatt/gatt_sr.c +++ b/components/bt/host/bluedroid/stack/gatt/gatt_sr.c @@ -405,7 +405,7 @@ tGATT_STATUS gatt_sr_process_app_rsp (tGATT_TCB *p_tcb, tGATT_IF gatt_if, tGATT_STATUS ret_code = GATT_SUCCESS; UNUSED(trans_id); - GATT_TRACE_DEBUG("gatt_sr_process_app_rsp gatt_if=%d\n", gatt_if); + GATT_TRACE_DEBUG("gatt_sr_process_app_rsp gatt_if=%d opcode=%x\n", gatt_if, op_code); gatt_sr_update_cback_cnt(p_tcb, gatt_if, FALSE, FALSE); @@ -1827,6 +1827,7 @@ void gatt_server_handle_client_req (tGATT_TCB *p_tcb, UINT8 op_code, { /* there is pending command, discard this one */ if (!gatt_sr_cmd_empty(p_tcb) && op_code != GATT_HANDLE_VALUE_CONF) { + GATT_TRACE_WARNING("%s discard command opcode=%02x", __func__, op_code); return; } @@ -1891,6 +1892,7 @@ void gatt_server_handle_client_req (tGATT_TCB *p_tcb, UINT8 op_code, break; default: + GATT_TRACE_ERROR("%s unknown command opcode=%02x", __func__, op_code); break; } } diff --git a/components/bt/host/bluedroid/stack/gatt/gatt_utils.c b/components/bt/host/bluedroid/stack/gatt/gatt_utils.c index 5565169a782..9335c3905da 100644 --- a/components/bt/host/bluedroid/stack/gatt/gatt_utils.c +++ b/components/bt/host/bluedroid/stack/gatt/gatt_utils.c @@ -1369,7 +1369,8 @@ void gatt_rsp_timeout(TIMER_LIST_ENT *p_tle) } } - GATT_TRACE_WARNING("gatt_rsp_timeout disconnecting..."); + GATT_TRACE_WARNING("gatt_rsp_timeout conn_id=%x op=%u op_sub=%u retry_count=%u disconnecting...", + p_clcb->conn_id, p_clcb->operation, p_clcb->op_subtype, p_clcb->retry_count); gatt_disconnect (p_clcb->p_tcb); } @@ -1811,7 +1812,7 @@ void gatt_clcb_dealloc (tGATT_CLCB *p_clcb) btu_free_timer(&p_clcb->rsp_timer_ent); memset(p_clcb, 0, sizeof(tGATT_CLCB)); list_remove(gatt_cb.p_clcb_list, p_clcb); - p_clcb = NULL; + p_clcb = NULL; } } diff --git a/components/bt/host/bluedroid/stack/hcic/hciblecmds.c b/components/bt/host/bluedroid/stack/hcic/hciblecmds.c index 5ad13216f77..bd74d9dea15 100644 --- a/components/bt/host/bluedroid/stack/hcic/hciblecmds.c +++ b/components/bt/host/bluedroid/stack/hcic/hciblecmds.c @@ -618,6 +618,8 @@ BOOLEAN btsnd_hcic_ble_start_enc (UINT16 handle, UINT8 rand[HCIC_BLE_RAND_DI_SIZ BT_HDR *p; UINT8 *pp; + HCI_TRACE_DEBUG("%s handle=%u LTK=%s", __func__, handle, bt_hex2str(ltk, HCIC_BLE_ENCRYT_KEY_SIZE)); + if ((p = HCI_GET_CMD_BUF(HCIC_PARAM_SIZE_BLE_START_ENC)) == NULL) { return (FALSE); } @@ -644,6 +646,8 @@ BOOLEAN btsnd_hcic_ble_ltk_req_reply (UINT16 handle, UINT8 ltk[HCIC_BLE_ENCRYT_K BT_HDR *p; UINT8 *pp; + HCI_TRACE_DEBUG("%s handle=%u LTK=%s", __func__, handle, bt_hex2str(ltk, HCIC_BLE_ENCRYT_KEY_SIZE)); + if ((p = HCI_GET_CMD_BUF(HCIC_PARAM_SIZE_LTK_REQ_REPLY)) == NULL) { return (FALSE); } @@ -668,6 +672,8 @@ BOOLEAN btsnd_hcic_ble_ltk_req_neg_reply (UINT16 handle) BT_HDR *p; UINT8 *pp; + HCI_TRACE_WARNING("%s handle=%u", __func__, handle); + if ((p = HCI_GET_CMD_BUF(HCIC_PARAM_SIZE_LTK_REQ_NEG_REPLY)) == NULL) { return (FALSE); } diff --git a/components/bt/host/bluedroid/stack/l2cap/l2c_api.c b/components/bt/host/bluedroid/stack/l2cap/l2c_api.c index fa01790d5f3..30375118313 100644 --- a/components/bt/host/bluedroid/stack/l2cap/l2c_api.c +++ b/components/bt/host/bluedroid/stack/l2cap/l2c_api.c @@ -215,7 +215,7 @@ UINT16 L2CA_ConnectReq (UINT16 psm, BD_ADDR p_bd_addr) ** ** Parameters: PSM: L2CAP PSM for the connection ** BD address of the peer -** Enhaced retransmission mode configurations +** Enhanced retransmission mode configurations ** Returns the CID of the connection, or 0 if it failed to start ** @@ -760,7 +760,7 @@ bool L2CA_GetIdentifiers(uint16_t lcid, uint16_t *rcid, uint16_t *handle) ** ** NOTE This timeout takes effect after at least 1 channel has been ** established and removed. L2CAP maintains its own timer from -** whan a connection is established till the first channel is +** when a connection is established till the first channel is ** set up. *******************************************************************************/ BOOLEAN L2CA_SetIdleTimeout (UINT16 cid, UINT16 timeout, BOOLEAN is_global) @@ -1901,6 +1901,8 @@ BOOLEAN L2CA_RemoveFixedChnl (UINT16 fixed_cid, BD_ADDR rem_bda) tL2C_CCB *p_ccb; tBT_TRANSPORT transport = BT_TRANSPORT_BR_EDR; + L2CAP_TRACE_DEBUG("%s cid=%04x bda="MACSTR"", __func__, fixed_cid, MAC2STR(rem_bda)); + /* Check CID is valid and registered */ if ( (fixed_cid < L2CAP_FIRST_FIXED_CHNL) || (fixed_cid > L2CAP_LAST_FIXED_CHNL) || (l2cb.fixed_reg[fixed_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedData_Cb == NULL) ) { diff --git a/components/bt/host/bluedroid/stack/l2cap/l2c_ble.c b/components/bt/host/bluedroid/stack/l2cap/l2c_ble.c index 3ce25ab977b..d3ae413b5fb 100644 --- a/components/bt/host/bluedroid/stack/l2cap/l2c_ble.c +++ b/components/bt/host/bluedroid/stack/l2cap/l2c_ble.c @@ -92,6 +92,8 @@ BOOLEAN L2CA_CancelBleConnectReq (BD_ADDR rem_bda) { tL2C_LCB *p_lcb; + L2CAP_TRACE_DEBUG("%s rem_bda="MACSTR"", __func__, MAC2STR(rem_bda)); + /* There can be only one BLE connection request outstanding at a time */ if (btm_ble_get_conn_st() == BLE_CONN_IDLE) { L2CAP_TRACE_WARNING ("L2CA_CancelBleConnectReq - no connection pending"); @@ -99,10 +101,8 @@ BOOLEAN L2CA_CancelBleConnectReq (BD_ADDR rem_bda) } if (memcmp (rem_bda, l2cb.ble_connecting_bda, BD_ADDR_LEN)) { - L2CAP_TRACE_WARNING ("L2CA_CancelBleConnectReq - different BDA Connecting: %08x%04x Cancel: %08x%04x", - (l2cb.ble_connecting_bda[0] << 24) + (l2cb.ble_connecting_bda[1] << 16) + (l2cb.ble_connecting_bda[2] << 8) + l2cb.ble_connecting_bda[3], - (l2cb.ble_connecting_bda[4] << 8) + l2cb.ble_connecting_bda[5], - (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3], (rem_bda[4] << 8) + rem_bda[5]); + L2CAP_TRACE_WARNING ("L2CA_CancelBleConnectReq - different BDA Connecting: "MACSTR" Cancel: "MACSTR"", + MAC2STR(l2cb.ble_connecting_bda), MAC2STR(rem_bda)); return (FALSE); } @@ -148,16 +148,12 @@ BOOLEAN L2CA_UpdateBleConnParams (BD_ADDR rem_bda, UINT16 min_int, UINT16 max_in /* If we don't have one, create one and accept the connection. */ if (!p_lcb || !p_acl_cb) { - L2CAP_TRACE_WARNING ("L2CA_UpdateBleConnParams - unknown BD_ADDR %08x%04x", - (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3], - (rem_bda[4] << 8) + rem_bda[5]); + L2CAP_TRACE_WARNING ("L2CA_UpdateBleConnParams - unknown BD_ADDR "MACSTR"", MAC2STR(rem_bda)); return (FALSE); } if (p_lcb->transport != BT_TRANSPORT_LE) { - L2CAP_TRACE_WARNING ("L2CA_UpdateBleConnParams - BD_ADDR %08x%04x not LE", - (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3], - (rem_bda[4] << 8) + rem_bda[5]); + L2CAP_TRACE_WARNING ("L2CA_UpdateBleConnParams - BD_ADDR "MACSTR" not LE", MAC2STR(rem_bda)); return (FALSE); } @@ -172,7 +168,7 @@ BOOLEAN L2CA_UpdateBleConnParams (BD_ADDR rem_bda, UINT16 min_int, UINT16 max_in if (p_lcb->conn_update_mask & L2C_BLE_UPDATE_PARAM_FULL){ status = HCI_ERR_ILLEGAL_COMMAND; need_cb = true; - L2CAP_TRACE_ERROR("There are two connection parameter requests that are being updated, please try later "); + L2CAP_TRACE_ERROR("%s connection parameter update in progress, please try later", __func__); } if ((need_cb == TRUE) && (conn_callback_func.update_conn_param_cb != NULL)) { @@ -221,20 +217,16 @@ BOOLEAN L2CA_EnableUpdateBleConnParams (BD_ADDR rem_bda, BOOLEAN enable) p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_LE); if (!p_lcb) { - L2CAP_TRACE_WARNING ("L2CA_EnableUpdateBleConnParams - unknown BD_ADDR %08x%04x", - (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3], - (rem_bda[4] << 8) + rem_bda[5]); + L2CAP_TRACE_WARNING ("L2CA_EnableUpdateBleConnParams - unknown BD_ADDR "MACSTR"", MAC2STR(rem_bda)); return (FALSE); } - L2CAP_TRACE_API ("%s - BD_ADDR %08x%04x enable %d current upd state 0x%02x", __FUNCTION__, - (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3], - (rem_bda[4] << 8) + rem_bda[5], enable, p_lcb->conn_update_mask); + L2CAP_TRACE_API ("%s - BD_ADDR "MACSTR" enable %d current upd state 0x%02x", + __func__, MAC2STR(rem_bda), enable, p_lcb->conn_update_mask); if (p_lcb->transport != BT_TRANSPORT_LE) { - L2CAP_TRACE_WARNING ("%s - BD_ADDR %08x%04x not LE (link role %d)", __FUNCTION__, - (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3], - (rem_bda[4] << 8) + rem_bda[5], p_lcb->link_role); + L2CAP_TRACE_WARNING ("%s - BD_ADDR "MACSTR" not LE (link role %d)", + __func__, MAC2STR(rem_bda), p_lcb->link_role); return (FALSE); } diff --git a/components/bt/host/bluedroid/stack/l2cap/l2c_utils.c b/components/bt/host/bluedroid/stack/l2cap/l2c_utils.c index 89b7d62d942..f7d8908938d 100644 --- a/components/bt/host/bluedroid/stack/l2cap/l2c_utils.c +++ b/components/bt/host/bluedroid/stack/l2cap/l2c_utils.c @@ -158,6 +158,9 @@ void l2cu_release_lcb (tL2C_LCB *p_lcb) { tL2C_CCB *p_ccb; + L2CAP_TRACE_DEBUG("%s handle=%u bda="MACSTR"", + __func__, p_lcb->handle, MAC2STR(p_lcb->remote_bd_addr)); + p_lcb->in_use = FALSE; p_lcb->is_bonding = FALSE; #if (BLE_INCLUDED == TRUE) diff --git a/components/bt/host/bluedroid/stack/smp/smp_act.c b/components/bt/host/bluedroid/stack/smp/smp_act.c index a41fbdd1b17..591c083c5d5 100644 --- a/components/bt/host/bluedroid/stack/smp/smp_act.c +++ b/components/bt/host/bluedroid/stack/smp/smp_act.c @@ -79,7 +79,7 @@ static bool lmp_version_below(BD_ADDR bda, uint8_t version) *******************************************************************************/ static void smp_update_key_mask (tSMP_CB *p_cb, UINT8 key_type, BOOLEAN recv) { - SMP_TRACE_DEBUG("%s before update role=%d recv=%d local_i_key = %02x, local_r_key = %02x\n", + SMP_TRACE_DEBUG("%s before update role=%d recv=%d local_i_key = %02x, local_r_key = %02x", __func__, p_cb->role, recv, p_cb->local_i_key, p_cb->local_r_key); if (((p_cb->le_secure_connections_mode_is_used) || @@ -103,8 +103,8 @@ static void smp_update_key_mask (tSMP_CB *p_cb, UINT8 key_type, BOOLEAN recv) } } - SMP_TRACE_DEBUG("updated local_i_key = %02x, local_r_key = %02x\n", p_cb->local_i_key, - p_cb->local_r_key); + SMP_TRACE_DEBUG("updated local_i_key = %02x, local_r_key = %02x", + p_cb->local_i_key, p_cb->local_r_key); } /******************************************************************************* @@ -115,7 +115,7 @@ void smp_send_app_cback(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) { tSMP_EVT_DATA cb_data; tSMP_STATUS callback_rc; - SMP_TRACE_DEBUG("%s p_cb->cb_evt=%d\n", __func__, p_cb->cb_evt); + SMP_TRACE_DEBUG("%s cb_evt=%d", __func__, p_cb->cb_evt); if (p_cb->p_callback && p_cb->cb_evt != 0) { switch (p_cb->cb_evt) { case SMP_IO_CAP_REQ_EVT: @@ -171,11 +171,11 @@ void smp_send_app_cback(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) p_cb->local_r_key = 0; } - SMP_TRACE_DEBUG ("rcvd auth_req: 0x%02x, io_cap: %d \ - loc_oob_flag: %d loc_enc_size: %d," - "local_i_key: 0x%02x, local_r_key: 0x%02x\n", - p_cb->loc_auth_req, p_cb->local_io_capability, p_cb->loc_oob_flag, - p_cb->loc_enc_size, p_cb->local_i_key, p_cb->local_r_key); + SMP_TRACE_DEBUG ("rcvd auth_req: 0x%02x, io_cap: %d," + "loc_oob_flag: %d loc_enc_size: %d," + "local_i_key: 0x%02x, local_r_key: 0x%02x", + p_cb->loc_auth_req, p_cb->local_io_capability, p_cb->loc_oob_flag, + p_cb->loc_enc_size, p_cb->local_i_key, p_cb->local_r_key); p_cb->secure_connections_only_mode_required = (btm_cb.security_mode == BTM_SEC_MODE_SC) ? TRUE : FALSE; @@ -222,8 +222,6 @@ void smp_send_app_cback(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) p_cb->discard_sec_req = FALSE; smp_sm_event(p_cb, SMP_DISCARD_SEC_REQ_EVT, NULL); } - - SMP_TRACE_DEBUG("%s return\n", __func__); } /******************************************************************************* @@ -249,7 +247,7 @@ void smp_send_pair_fail(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) *******************************************************************************/ void smp_send_pair_req(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) { - SMP_TRACE_DEBUG("%s\n", __func__); + SMP_TRACE_DEBUG("%s", __func__); #if (BLE_INCLUDED == TRUE) tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (p_cb->pairing_bda); @@ -269,7 +267,7 @@ void smp_send_pair_req(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) *******************************************************************************/ void smp_send_pair_rsp(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) { - SMP_TRACE_DEBUG("%s\n", __func__); + SMP_TRACE_DEBUG("%s", __func__); #if (BLE_INCLUDED == TRUE) p_cb->local_i_key &= p_cb->peer_i_key; @@ -291,7 +289,7 @@ void smp_send_pair_rsp(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) *******************************************************************************/ void smp_send_confirm(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) { - SMP_TRACE_DEBUG("%s\n", __func__); + SMP_TRACE_DEBUG("%s", __func__); smp_send_cmd(SMP_OPCODE_CONFIRM, p_cb); } @@ -313,7 +311,7 @@ void smp_send_init(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) *******************************************************************************/ void smp_send_rand(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) { - SMP_TRACE_DEBUG("%s\n", __func__); + SMP_TRACE_DEBUG("%s", __func__); smp_send_cmd(SMP_OPCODE_RAND, p_cb); } @@ -323,7 +321,7 @@ void smp_send_rand(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) *******************************************************************************/ void smp_send_pair_public_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) { - SMP_TRACE_DEBUG("%s\n", __func__); + SMP_TRACE_DEBUG("%s", __func__); smp_send_cmd(SMP_OPCODE_PAIR_PUBLIC_KEY, p_cb); } @@ -365,7 +363,7 @@ void smp_send_enc_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) { tBTM_LE_LENC_KEYS le_key; - SMP_TRACE_DEBUG("%s p_cb->loc_enc_size = %d\n", __func__, p_cb->loc_enc_size); + SMP_TRACE_DEBUG("%s loc_enc_size = %d", __func__, p_cb->loc_enc_size); smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_ENC, FALSE); smp_send_cmd(SMP_OPCODE_ENCRYPT_INFO, p_cb); @@ -383,8 +381,6 @@ void smp_send_enc_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) (tBTM_LE_KEY_VALUE *)&le_key, TRUE); } - SMP_TRACE_DEBUG ("%s\n", __func__); - smp_key_distribution(p_cb, NULL); #endif ///BLE_INCLUDED == TRUE } @@ -395,7 +391,7 @@ void smp_send_enc_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) *******************************************************************************/ void smp_send_id_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) { - SMP_TRACE_DEBUG("%s\n", __func__); + SMP_TRACE_DEBUG("%s", __func__); smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_ID, FALSE); smp_send_cmd(SMP_OPCODE_IDENTITY_INFO, p_cb); @@ -420,7 +416,7 @@ void smp_send_id_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) void smp_send_csrk_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) { tBTM_LE_LCSRK_KEYS key; - SMP_TRACE_DEBUG("%s\n", __func__); + SMP_TRACE_DEBUG("%s", __func__); smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_CSRK, FALSE); if (smp_send_cmd(SMP_OPCODE_SIGN_INFO, p_cb)) { @@ -455,12 +451,10 @@ void smp_proc_sec_req(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) tBTM_BLE_SEC_REQ_ACT sec_req_act; UINT8 reason; - SMP_TRACE_DEBUG("%s auth_req=0x%x", __func__, auth_req); - p_cb->cb_evt = 0; btm_ble_link_sec_check(p_cb->pairing_bda, auth_req, &sec_req_act); - SMP_TRACE_DEBUG("%s sec_req_act=0x%x", __func__, sec_req_act); + SMP_TRACE_DEBUG("%s auth_req=0x%x sec_req_act=0x%x", __func__, auth_req, sec_req_act); switch (sec_req_act) { case BTM_BLE_SEC_REQ_ACT_ENCRYPT: @@ -475,6 +469,8 @@ void smp_proc_sec_req(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) /* respond to non SC pairing request as failure in SC only mode */ if (p_cb->secure_connections_only_mode_required && (auth_req & SMP_SC_SUPPORT_BIT) == 0) { + SMP_TRACE_ERROR("%s SC mode not support, auth_req=0x%x", + __func__, auth_req); reason = SMP_PAIR_AUTH_FAIL; smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason); } else { @@ -503,7 +499,7 @@ void smp_proc_sec_req(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) void smp_proc_sec_grant(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) { UINT8 res = *(UINT8 *)p_data; - SMP_TRACE_DEBUG("%s", __func__); + SMP_TRACE_DEBUG("%s res=0x%x", __func__, res); if (res != SMP_SUCCESS) { smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, p_data); } else { /*otherwise, start pairing */ @@ -560,7 +556,7 @@ void smp_proc_pair_cmd(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) UINT8 reason = SMP_ENC_KEY_SIZE; tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (p_cb->pairing_bda); - SMP_TRACE_DEBUG("%s\n", __func__); + SMP_TRACE_DEBUG("%s", __func__); /* erase all keys if it is slave proc pairing req*/ if (p_dev_rec && (p_cb->role == HCI_ROLE_SLAVE)) { btm_sec_clear_ble_keys(p_dev_rec); @@ -682,7 +678,7 @@ void smp_proc_confirm(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) UINT8 *p = (UINT8 *)p_data; UINT8 reason = SMP_INVALID_PARAMETERS; - SMP_TRACE_DEBUG("%s\n", __func__); + SMP_TRACE_DEBUG("%s", __func__); if (smp_command_has_invalid_parameters(p_cb)) { smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason); @@ -1170,6 +1166,7 @@ void smp_proc_compare(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) } } else { + SMP_TRACE_ERROR("%s pairing failed - check confirm value error", __func__); reason = p_cb->failure = SMP_CONFIRM_VALUE_ERR; smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason); } @@ -1213,6 +1210,7 @@ void smp_start_enc(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) } if (cmd != BTM_CMD_STARTED && cmd != BTM_BUSY) { + SMP_TRACE_ERROR("%s start encryption failed, cmd=0x%x", __func__, cmd); smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason); } } @@ -1239,7 +1237,7 @@ void smp_enc_cmpl(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) UINT8 enc_enable = *(UINT8 *)p_data; UINT8 reason = enc_enable ? SMP_SUCCESS : SMP_ENC_FAIL; - SMP_TRACE_DEBUG("%s\n", __func__); + SMP_TRACE_DEBUG("%s %u", __func__, enc_enable); smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason); } diff --git a/components/bt/host/bluedroid/stack/smp/smp_api.c b/components/bt/host/bluedroid/stack/smp/smp_api.c index 78e295f4f1f..28c4761413a 100644 --- a/components/bt/host/bluedroid/stack/smp/smp_api.c +++ b/components/bt/host/bluedroid/stack/smp/smp_api.c @@ -236,7 +236,7 @@ BOOLEAN SMP_PairCancel (BD_ADDR bd_addr) if ( (p_cb->state != SMP_STATE_IDLE) && (!memcmp (p_cb->pairing_bda, bd_addr, BD_ADDR_LEN)) ) { p_cb->is_pair_cancel = TRUE; - SMP_TRACE_DEBUG("Cancel Pairing: set fail reason Unknown"); + SMP_TRACE_ERROR("%s Cancel Pairing: set fail reason Unknown", __func__); smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &err_code); status = TRUE; } @@ -434,6 +434,8 @@ void SMP_OobDataReply(BD_ADDR bd_addr, tSMP_STATUS res, UINT8 len, UINT8 *p_data } if (res != SMP_SUCCESS || len == 0 || !p_data) { + SMP_TRACE_ERROR("%s pairing failed, res=0x%x len=%u p_data=%p", + __func__, res, len, p_data); smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure); } else { if (len > BT_OCTET16_LEN) { @@ -524,10 +526,10 @@ void SMP_SecureConnectionOobDataReply(UINT8 *p_data) ** Description This function is called to encrypt the data with the specified ** key ** -** Parameters: key - Pointer to key key[0] conatins the MSB +** Parameters: key - Pointer to key key[0] contains the MSB ** key_len - key length ** plain_text - Pointer to data to be encrypted -** plain_text[0] conatins the MSB +** plain_text[0] contains the MSB ** pt_len - plain text length ** p_out - output of the encrypted texts ** diff --git a/components/bt/host/bluedroid/stack/smp/smp_keys.c b/components/bt/host/bluedroid/stack/smp/smp_keys.c index aec6f709c56..855017a76a8 100644 --- a/components/bt/host/bluedroid/stack/smp/smp_keys.c +++ b/components/bt/host/bluedroid/stack/smp/smp_keys.c @@ -332,7 +332,7 @@ void smp_generate_stk(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) output.opcode = HCI_BLE_ENCRYPT; memcpy(output.param_buf, p_cb->ltk, SMP_ENCRYT_DATA_SIZE); } else if (!smp_calculate_legacy_short_term_key(p_cb, &output)) { - SMP_TRACE_ERROR("%s failed", __func__); + SMP_TRACE_ERROR("%s pairing failed", __func__); smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status); return; } @@ -459,7 +459,7 @@ void smp_compute_csrk(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) UINT16_TO_STREAM(p, r); if (!SMP_Encrypt(er, BT_OCTET16_LEN, buffer, 4, &output)) { - SMP_TRACE_ERROR("smp_generate_csrk failed\n"); + SMP_TRACE_ERROR("%s pairing failed", __func__); if (p_cb->smp_over_br) { #if (CLASSIC_BT_INCLUDED == TRUE) smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &status); @@ -549,7 +549,7 @@ void smp_concatenate_peer( tSMP_CB *p_cb, UINT8 **p_data, UINT8 op_code) ** Function smp_gen_p1_4_confirm ** ** Description Generate Confirm/Compare Step1: -** p1 = pres || preq || rat' || iat' +** p1 = press || preq || rat' || iat' ** ** Returns void ** @@ -574,22 +574,22 @@ void smp_gen_p1_4_confirm( tSMP_CB *p_cb, BT_OCTET16 p1) UINT8_TO_STREAM(p, p_cb->addr_type); /* LSB : iat': responder's address type */ UINT8_TO_STREAM(p, addr_type); - /* concatinate preq */ + /* concatenate preq */ smp_concatenate_local(p_cb, &p, SMP_OPCODE_PAIRING_REQ); - /* concatinate pres */ + /* concatenate press */ smp_concatenate_peer(p_cb, &p, SMP_OPCODE_PAIRING_RSP); } else { /* LSB : iat': initiator's address type */ UINT8_TO_STREAM(p, addr_type); /* LSB : rat': responder's(local) address type */ UINT8_TO_STREAM(p, p_cb->addr_type); - /* concatinate preq */ + /* concatenate preq */ smp_concatenate_peer(p_cb, &p, SMP_OPCODE_PAIRING_REQ); - /* concatinate pres */ + /* concatenate press */ smp_concatenate_local(p_cb, &p, SMP_OPCODE_PAIRING_RSP); } #if SMP_DEBUG == TRUE - SMP_TRACE_DEBUG("p1 = pres || preq || rat' || iat'\n"); + SMP_TRACE_DEBUG("p1 = press || preq || rat' || iat'\n"); smp_debug_print_nbyte_little_endian ((UINT8 *)p1, (const UINT8 *)"P1", 16); #endif } @@ -654,7 +654,7 @@ void smp_calculate_comfirm (tSMP_CB *p_cb, BT_OCTET16 rand, BD_ADDR bda) tSMP_STATUS status = SMP_PAIR_FAIL_UNKNOWN; SMP_TRACE_DEBUG ("smp_calculate_comfirm \n"); - /* generate p1 = pres || preq || rat' || iat' */ + /* generate p1 = press || preq || rat' || iat' */ smp_gen_p1_4_confirm(p_cb, p1); /* p1 = rand XOR p1 */ @@ -664,7 +664,7 @@ void smp_calculate_comfirm (tSMP_CB *p_cb, BT_OCTET16 rand, BD_ADDR bda) /* calculate e(k, r XOR p1), where k = TK */ if (!SMP_Encrypt(p_cb->tk, BT_OCTET16_LEN, p1, BT_OCTET16_LEN, &output)) { - SMP_TRACE_ERROR("smp_generate_csrk failed"); + SMP_TRACE_ERROR("%s calculate TK failed", __func__); smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status); } else { smp_calculate_comfirm_cont(p_cb, &output); @@ -701,7 +701,7 @@ static void smp_calculate_comfirm_cont(tSMP_CB *p_cb, tSMP_ENC *p) /* calculate: Confirm = E(k, p1' XOR p2) */ if (!SMP_Encrypt(p_cb->tk, BT_OCTET16_LEN, p2, BT_OCTET16_LEN, &output)) { - SMP_TRACE_ERROR("smp_calculate_comfirm_cont failed\n"); + SMP_TRACE_ERROR("%s pairing failed", __func__); smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status); } else { SMP_TRACE_DEBUG("p_cb->rand_enc_proc_state=%d\n", p_cb->rand_enc_proc_state); @@ -861,7 +861,7 @@ static void smp_generate_ltk_cont(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) /* LTK = d1(ER, DIV, 0)= e(ER, DIV)*/ if (!SMP_Encrypt(er, BT_OCTET16_LEN, (UINT8 *)&p_cb->div, sizeof(UINT16), &output)) { - SMP_TRACE_ERROR("%s failed\n", __func__); + SMP_TRACE_ERROR("%s failed", __func__); smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status); } else { /* mask the LTK */ @@ -1373,6 +1373,8 @@ void smp_calculate_numeric_comparison_display_number(tSMP_CB *p_cb, } if (p_cb->number_to_display >= (BTM_MAX_PASSKEY_VAL + 1)) { + SMP_TRACE_ERROR("%s pairing failed - invalid number to display %u", + __func__, p_cb->number_to_display); UINT8 reason; reason = p_cb->failure = SMP_PAIR_FAIL_UNKNOWN; smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason); diff --git a/components/bt/host/bluedroid/stack/smp/smp_utils.c b/components/bt/host/bluedroid/stack/smp/smp_utils.c index 48ba6c0ae30..f7ade05ac06 100644 --- a/components/bt/host/bluedroid/stack/smp/smp_utils.c +++ b/components/bt/host/bluedroid/stack/smp/smp_utils.c @@ -366,6 +366,7 @@ BOOLEAN smp_send_cmd(UINT8 cmd_code, tSMP_CB *p_cb) } if (!sent) { + SMP_TRACE_ERROR("%s failed, cmd_code=0x%02x", __func__, cmd_code); if (p_cb->smp_over_br) { #if (CLASSIC_BT_INCLUDED == TRUE) smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &failure); @@ -392,7 +393,7 @@ void smp_rsp_timeout(TIMER_LIST_ENT *p_tle) UINT8 failure = SMP_RSP_TIMEOUT; UNUSED(p_tle); - SMP_TRACE_EVENT("%s state:%d br_state:%d", __FUNCTION__, p_cb->state, p_cb->br_state); + SMP_TRACE_ERROR("%s state=%d br_state=%d", __func__, p_cb->state, p_cb->br_state); if (p_cb->smp_over_br) { #if (CLASSIC_BT_INCLUDED == TRUE) From 5bcc442e390299e11595ac913dbf33233182c1cb Mon Sep 17 00:00:00 2001 From: Chen Jian Hua Date: Fri, 14 Nov 2025 13:33:24 +0800 Subject: [PATCH 081/106] fix(bt/bluedroid): Fixed memory debug error (cherry picked from commit 9df842f2c3622c4212a093b708436dc6b41fe7d2) Co-authored-by: chenjianhua --- components/bt/common/osi/include/osi/allocator.h | 1 + 1 file changed, 1 insertion(+) diff --git a/components/bt/common/osi/include/osi/allocator.h b/components/bt/common/osi/include/osi/allocator.h index d95040538d8..071892ffafe 100644 --- a/components/bt/common/osi/include/osi/allocator.h +++ b/components/bt/common/osi/include/osi/allocator.h @@ -21,6 +21,7 @@ #include #include +#include "bt_common.h" #include "esp_heap_caps.h" char *osi_strdup(const char *str); From de9ad7d9a0fa9160e45361f0d17510045e3d1441 Mon Sep 17 00:00:00 2001 From: Chen Jian Hua Date: Fri, 14 Nov 2025 13:33:25 +0800 Subject: [PATCH 082/106] fix(bt/example): Fixed hf_ag build error (cherry picked from commit 98864d279f694c65eeb861cf12086412b29e1983) Co-authored-by: yangfeng --- .../bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_hf.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_hf.c b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_hf.c index c60bde9997c..d4b0defcc4e 100644 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_hf.c +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_hf.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -25,7 +25,6 @@ #include "sdkconfig.h" #include "bt_app_core.h" #include "bt_app_hf.h" -#include "osi/allocator.h" const char *c_hf_evt_str[] = { "CONNECTION_STATE_EVT", /*!< SERVICE LEVEL CONNECTION STATE CONTROL */ @@ -231,7 +230,7 @@ static void bt_app_send_data_task(void *arg) if (frame_data_num == 0) { continue; } - buf = osi_malloc(frame_data_num); + buf = (uint8_t *)malloc(frame_data_num); if (!buf) { ESP_LOGE(BT_HF_TAG, "%s, no mem", __FUNCTION__); continue; @@ -241,7 +240,7 @@ static void bt_app_send_data_task(void *arg) if (!done) { ESP_LOGE(BT_HF_TAG, "rb send fail"); } - osi_free(buf); + free(buf); vRingbufferGetInfo(s_m_rb, NULL, NULL, NULL, NULL, &item_size); if(s_audio_code == ESP_HF_AUDIO_STATE_CONNECTED_MSBC) { From 35f050a97d619fefebaa8339fdfc2eb2dc45c2fc Mon Sep 17 00:00:00 2001 From: armando Date: Fri, 17 Oct 2025 15:29:33 +0800 Subject: [PATCH 083/106] feat(isp): added shadow reg settings --- components/esp_driver_isp/src/isp_bf.c | 3 + components/esp_driver_isp/src/isp_blc.c | 3 + components/esp_driver_isp/src/isp_ccm.c | 3 + components/esp_driver_isp/src/isp_color.c | 3 + components/esp_driver_isp/src/isp_core.c | 2 + components/esp_driver_isp/src/isp_sharpen.c | 3 + components/esp_driver_isp/src/isp_wbg.c | 3 + components/hal/esp32p4/include/hal/isp_ll.h | 226 +++++++++++++++++++ docs/en/api-reference/peripherals/isp.rst | 2 +- docs/zh_CN/api-reference/peripherals/isp.rst | 2 +- 10 files changed, 248 insertions(+), 2 deletions(-) diff --git a/components/esp_driver_isp/src/isp_bf.c b/components/esp_driver_isp/src/isp_bf.c index 066076624f0..1c71d0eefd0 100644 --- a/components/esp_driver_isp/src/isp_bf.c +++ b/components/esp_driver_isp/src/isp_bf.c @@ -43,6 +43,9 @@ esp_err_t esp_isp_bf_configure(isp_proc_handle_t proc, const esp_isp_bf_config_t isp_hal_bf_config(&(proc->hal), NULL); } + bool valid = isp_ll_shadow_update_bf(proc->hal.hw); + ESP_RETURN_ON_FALSE_ISR(valid, ESP_ERR_INVALID_STATE, TAG, "failed to update bf shadow register"); + return ESP_OK; } diff --git a/components/esp_driver_isp/src/isp_blc.c b/components/esp_driver_isp/src/isp_blc.c index c808e66d04d..f8faa2774bc 100644 --- a/components/esp_driver_isp/src/isp_blc.c +++ b/components/esp_driver_isp/src/isp_blc.c @@ -58,6 +58,9 @@ esp_err_t esp_isp_blc_configure(isp_proc_handle_t isp_proc, const esp_isp_blc_co // Configure stretch enable for each channel isp_ll_blc_enable_stretch(isp_proc->hal.hw, config->stretch.top_left_chan_stretch_en, config->stretch.top_right_chan_stretch_en, config->stretch.bottom_left_chan_stretch_en, config->stretch.bottom_right_chan_stretch_en); + bool valid = isp_ll_shadow_update_blc(isp_proc->hal.hw); + ESP_RETURN_ON_FALSE_ISR(valid, ESP_ERR_INVALID_STATE, TAG, "failed to update blc shadow register"); + return ESP_OK; } diff --git a/components/esp_driver_isp/src/isp_ccm.c b/components/esp_driver_isp/src/isp_ccm.c index b8b28bad44b..d41bfd64ece 100644 --- a/components/esp_driver_isp/src/isp_ccm.c +++ b/components/esp_driver_isp/src/isp_ccm.c @@ -33,11 +33,14 @@ esp_err_t esp_isp_ccm_configure(isp_proc_handle_t proc, const esp_isp_ccm_config } bool ret = true; + bool valid = false; portENTER_CRITICAL(&proc->spinlock); isp_ll_ccm_set_clk_ctrl_mode(proc->hal.hw, ISP_LL_PIPELINE_CLK_CTRL_AUTO); ret = isp_hal_ccm_set_matrix(&proc->hal, ccm_cfg->saturation, ccm_cfg->matrix); + valid = isp_ll_shadow_update_ccm(proc->hal.hw); portEXIT_CRITICAL(&proc->spinlock); ESP_RETURN_ON_FALSE(ret, ESP_ERR_INVALID_ARG, TAG, "invalid argument: ccm matrix contain NaN or out of range"); + ESP_RETURN_ON_FALSE(valid, ESP_ERR_INVALID_STATE, TAG, "failed to update ccm shadow register"); return ESP_OK; } diff --git a/components/esp_driver_isp/src/isp_color.c b/components/esp_driver_isp/src/isp_color.c index d10504e3f2f..c3da6d5cdc1 100644 --- a/components/esp_driver_isp/src/isp_color.c +++ b/components/esp_driver_isp/src/isp_color.c @@ -43,6 +43,9 @@ esp_err_t esp_isp_color_configure(isp_proc_handle_t proc, const esp_isp_color_co isp_hal_color_config(&(proc->hal), NULL); } + bool valid = isp_ll_shadow_update_color(proc->hal.hw); + ESP_RETURN_ON_FALSE_ISR(valid, ESP_ERR_INVALID_STATE, TAG, "failed to update color shadow register"); + return ESP_OK; } diff --git a/components/esp_driver_isp/src/isp_core.c b/components/esp_driver_isp/src/isp_core.c index b1d1b45e147..2fb6510d091 100644 --- a/components/esp_driver_isp/src/isp_core.c +++ b/components/esp_driver_isp/src/isp_core.c @@ -178,6 +178,8 @@ esp_err_t esp_isp_new_processor(const esp_isp_processor_cfg_t *proc_config, isp_ isp_ll_set_byte_swap(proc->hal.hw, true); } + isp_ll_shadow_set_mode(proc->hal.hw, ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC); + proc->in_color_format = in_color_format; proc->out_color_format = out_color_format; proc->h_res = proc_config->h_res; diff --git a/components/esp_driver_isp/src/isp_sharpen.c b/components/esp_driver_isp/src/isp_sharpen.c index b8ac88abeb9..c0dd2fc2581 100644 --- a/components/esp_driver_isp/src/isp_sharpen.c +++ b/components/esp_driver_isp/src/isp_sharpen.c @@ -45,6 +45,9 @@ esp_err_t esp_isp_sharpen_configure(isp_proc_handle_t proc, const esp_isp_sharpe isp_hal_sharpen_config(&(proc->hal), NULL); } + bool valid = isp_ll_shadow_update_sharpen(proc->hal.hw); + ESP_RETURN_ON_FALSE_ISR(valid, ESP_ERR_INVALID_STATE, TAG, "failed to update sharp shadow register"); + return ESP_OK; } diff --git a/components/esp_driver_isp/src/isp_wbg.c b/components/esp_driver_isp/src/isp_wbg.c index e03d0eda52c..96b809840c5 100644 --- a/components/esp_driver_isp/src/isp_wbg.c +++ b/components/esp_driver_isp/src/isp_wbg.c @@ -61,6 +61,9 @@ esp_err_t esp_isp_wbg_set_wb_gain(isp_proc_handle_t isp_proc, isp_wbg_gain_t gai // Set WBG gain isp_ll_awb_set_wb_gain(isp_proc->hal.hw, gain); + bool valid = isp_ll_shadow_update_wbg(isp_proc->hal.hw); + ESP_RETURN_ON_FALSE_ISR(valid, ESP_ERR_INVALID_STATE, TAG, "failed to update wbg shadow register"); + return ESP_OK; } diff --git a/components/hal/esp32p4/include/hal/isp_ll.h b/components/hal/esp32p4/include/hal/isp_ll.h index 2fec895ab4b..63f2da2ec94 100644 --- a/components/hal/esp32p4/include/hal/isp_ll.h +++ b/components/hal/esp32p4/include/hal/isp_ll.h @@ -197,6 +197,14 @@ typedef enum { ISP_LL_PIPELINE_CLK_CTRL_ALWAYS_ON, ///< Always on } isp_ll_pipeline_clk_ctrl_t; +/** + * @brief Shadow mode + */ +typedef enum { + ISP_SHADOW_MODE_DISABLE, + ISP_SHADOW_MODE_UPDATE_EVERY_VSYNC, + ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC, +} isp_ll_shadow_mode_t; /*--------------------------------------------------------------- Clock @@ -1852,6 +1860,224 @@ static inline void isp_ll_demosaic_set_padding_line_tail_valid_end_pixel(isp_dev HAL_FORCE_MODIFY_U32_REG_FIELD(hw->demosaic_matrix_ctrl, demosaic_tail_pixen_pulse_th, end_pixel); } +#if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300 +/*--------------------------------------------------------------- + Shadow +---------------------------------------------------------------*/ +/** + * @brief Shadow mode + * + * @param[in] hw Hardware instance address + * @param[in] mode 'isp_ll_shadow_mode_t` + */ +static inline void isp_ll_shadow_set_mode(isp_dev_t *hw, isp_ll_shadow_mode_t mode) +{ + hw->shadow_reg_ctrl.shadow_update_sel = mode; +} + +/** + * @brief Update BLC shadow register + * + * @param[in] hw Hardware instance address + * @return + * - True if update is successful, False otherwise + */ +static inline bool isp_ll_shadow_update_blc(isp_dev_t *hw) +{ + //only valid when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC + HAL_ASSERT(hw->shadow_reg_ctrl.shadow_update_sel == ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC); + + if (hw->shadow_reg_ctrl.blc_update == 1) { + return false; + } + + //self clear when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC + hw->shadow_reg_ctrl.blc_update = 1; + + return true; +} + +/** + * @brief Update DPC shadow register + * + * @param[in] hw Hardware instance address + * @return + * - True if update is successful, False otherwise + */ +static inline bool isp_ll_shadow_update_dpc(isp_dev_t *hw) +{ + //only valid when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC + HAL_ASSERT(hw->shadow_reg_ctrl.shadow_update_sel == ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC); + + if (hw->shadow_reg_ctrl.dpc_update == 1) { + return false; + } + + //self clear when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC + hw->shadow_reg_ctrl.dpc_update = 1; + + return true; +} + +/** + * @brief Update BF shadow register + * + * @param[in] hw Hardware instance address + * @return + * - True if update is successful, False otherwise + */ +static inline bool isp_ll_shadow_update_bf(isp_dev_t *hw) +{ + //only valid when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC + HAL_ASSERT(hw->shadow_reg_ctrl.shadow_update_sel == ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC); + + if (hw->shadow_reg_ctrl.bf_update == 1) { + return false; + } + + //self clear when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC + hw->shadow_reg_ctrl.bf_update = 1; + + return true; +} + +/** + * @brief Update WBG shadow register + * + * @param[in] hw Hardware instance address + * @return + * - True if update is successful, False otherwise + */ +static inline bool isp_ll_shadow_update_wbg(isp_dev_t *hw) +{ + //only valid when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC + HAL_ASSERT(hw->shadow_reg_ctrl.shadow_update_sel == ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC); + + if (hw->shadow_reg_ctrl.wbg_update == 1) { + return false; + } + + //self clear when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC + hw->shadow_reg_ctrl.wbg_update = 1; + + return true; +} + +/** + * @brief Update CCM shadow register + * + * @param[in] hw Hardware instance address + * @return + * - True if update is successful, False otherwise + */ +static inline bool isp_ll_shadow_update_ccm(isp_dev_t *hw) +{ + //only valid when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC + HAL_ASSERT(hw->shadow_reg_ctrl.shadow_update_sel == ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC); + + if (hw->shadow_reg_ctrl.ccm_update == 1) { + return false; + } + + //self clear when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC + hw->shadow_reg_ctrl.ccm_update = 1; + + return true; +} + +/** + * @brief Update Sharpen shadow register + * + * @param[in] hw Hardware instance address + * @return + * - True if update is successful, False otherwise + */ +static inline bool isp_ll_shadow_update_sharpen(isp_dev_t *hw) +{ + //only valid when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC + HAL_ASSERT(hw->shadow_reg_ctrl.shadow_update_sel == ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC); + + if (hw->shadow_reg_ctrl.sharp_update == 1) { + return false; + } + + //self clear when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC + hw->shadow_reg_ctrl.sharp_update = 1; + + return true; +} + +/** + * @brief Update Color shadow register + * + * @param[in] hw Hardware instance address + * @return + * - True if update is successful, False otherwise + */ +static inline bool isp_ll_shadow_update_color(isp_dev_t *hw) +{ + //only valid when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC + HAL_ASSERT(hw->shadow_reg_ctrl.shadow_update_sel == ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC); + + if (hw->shadow_reg_ctrl.color_update == 1) { + return false; + } + + //self clear when ISP_SHADOW_MODE_UPDATE_ONLY_NEXT_VSYNC + hw->shadow_reg_ctrl.color_update = 1; + + return true; +} + +#else +static inline void isp_ll_shadow_set_mode(isp_dev_t *hw, isp_ll_shadow_mode_t mode) +{ + //for compatibility +} + +static inline bool isp_ll_shadow_update_blc(isp_dev_t *hw) +{ + //for compatibility + return true; +} + +static inline bool isp_ll_shadow_update_dpc(isp_dev_t *hw) +{ + //for compatibility + return true; +} + +static inline bool isp_ll_shadow_update_bf(isp_dev_t *hw) +{ + //for compatibility + return true; +} + +static inline bool isp_ll_shadow_update_wbg(isp_dev_t *hw) +{ + //for compatibility + return true; +} + +static inline bool isp_ll_shadow_update_ccm(isp_dev_t *hw) +{ + //for compatibility + return true; +} + +static inline bool isp_ll_shadow_update_sharpen(isp_dev_t *hw) +{ + //for compatibility + return true; +} + +static inline bool isp_ll_shadow_update_color(isp_dev_t *hw) +{ + //for compatibility + return true; +} +#endif + /*--------------------------------------------------------------- Sharpen ---------------------------------------------------------------*/ diff --git a/docs/en/api-reference/peripherals/isp.rst b/docs/en/api-reference/peripherals/isp.rst index 21ef85af139..1b5c308cd10 100644 --- a/docs/en/api-reference/peripherals/isp.rst +++ b/docs/en/api-reference/peripherals/isp.rst @@ -723,7 +723,7 @@ Calling :cpp:func:`esp_isp_demosaic_configure` to configure Demosaic function, y ... }; - ESP_ERROR_CHECK(esp_isp_demosaic_configure(isp_proc, &sharpen_config)); + ESP_ERROR_CHECK(esp_isp_demosaic_configure(isp_proc, &demosaic_config)); ESP_ERROR_CHECK(esp_isp_demosaic_enable(isp_proc)); After calling :cpp:func:`esp_isp_demosaic_configure`, you need to enable the ISP Demosaic controller, by calling :cpp:func:`esp_isp_demosaic_enable`. This function: diff --git a/docs/zh_CN/api-reference/peripherals/isp.rst b/docs/zh_CN/api-reference/peripherals/isp.rst index aa08fb99c35..6a17eb1b6ba 100644 --- a/docs/zh_CN/api-reference/peripherals/isp.rst +++ b/docs/zh_CN/api-reference/peripherals/isp.rst @@ -724,7 +724,7 @@ ISP 去马赛克控制器 ... }; - ESP_ERROR_CHECK(esp_isp_demosaic_configure(isp_proc, &sharpen_config)); + ESP_ERROR_CHECK(esp_isp_demosaic_configure(isp_proc, &demosaic_config)); ESP_ERROR_CHECK(esp_isp_demosaic_enable(isp_proc)); 调用 :cpp:func:`esp_isp_demosaic_configure` 后,需要通过调用 :cpp:func:`esp_isp_demosaic_enable` 来启用 ISP 去马赛克控制器。此函数: From 4db2d48d1ecadf2d98bb64946514135b0464bd6d Mon Sep 17 00:00:00 2001 From: "C.S.M" Date: Tue, 28 Oct 2025 11:51:37 +0800 Subject: [PATCH 084/106] test(usj): Fix usj test --- .../test_apps/usb_serial_jtag/main/test_usb_serial_jtag.c | 1 + 1 file changed, 1 insertion(+) diff --git a/components/esp_driver_usb_serial_jtag/test_apps/usb_serial_jtag/main/test_usb_serial_jtag.c b/components/esp_driver_usb_serial_jtag/test_apps/usb_serial_jtag/main/test_usb_serial_jtag.c index 9d5ced30117..88e91fd6878 100644 --- a/components/esp_driver_usb_serial_jtag/test_apps/usb_serial_jtag/main/test_usb_serial_jtag.c +++ b/components/esp_driver_usb_serial_jtag/test_apps/usb_serial_jtag/main/test_usb_serial_jtag.c @@ -113,6 +113,7 @@ TEST_CASE("see if fsync appears to work", "[usb_serial_jtag]") start_us = esp_timer_get_time(); fsync(0); end_us = esp_timer_get_time(); + vTaskDelay(pdMS_TO_TICKS(500)); printf("With data in queue: %d us\n", (int)(end_us - start_us)); TEST_ASSERT_GREATER_THAN_INT(1000, end_us - start_us); TEST_ASSERT_LESS_THAN_INT(45000, end_us - start_us); //50ms means fsync hit a timeout From 93d9104e296a6fe1010f4257c3d9c58acc983807 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Mon, 13 Oct 2025 15:49:23 +0800 Subject: [PATCH 085/106] fix(esp_driver_usb_serial_jtag): check USJ accessibility before read/write Add connection checks to usb_serial_jtag_write and usb_serial_jtag_read functions to return -EIO error code when the USB Serial JTAG is not connected. --- .../src/usb_serial_jtag_vfs.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/components/esp_driver_usb_serial_jtag/src/usb_serial_jtag_vfs.c b/components/esp_driver_usb_serial_jtag/src/usb_serial_jtag_vfs.c index 040d946cb0d..930feaaebf3 100644 --- a/components/esp_driver_usb_serial_jtag/src/usb_serial_jtag_vfs.c +++ b/components/esp_driver_usb_serial_jtag/src/usb_serial_jtag_vfs.c @@ -181,6 +181,10 @@ static int usb_serial_jtag_rx_char_no_driver(int fd) static ssize_t usb_serial_jtag_write(int fd, const void * data, size_t size) { + if (!usb_serial_jtag_is_connected()) { + // TODO: IDF-14303 + return -1; + } const char *data_c = (const char *)data; /* Even though newlib does stream locking on each individual stream, we need * a dedicated lock if two streams (stdout and stderr) point to the @@ -225,6 +229,10 @@ static void usb_serial_jtag_return_char(int fd, int c) static ssize_t usb_serial_jtag_read(int fd, void* data, size_t size) { + if (!usb_serial_jtag_is_connected()) { + // TODO: IDF-14303 + return -1; + } assert(fd == USJ_LOCAL_FD); char *data_c = (char *) data; size_t received = 0; @@ -348,6 +356,10 @@ static int usb_serial_jtag_wait_tx_done_no_driver(int fd) static int usb_serial_jtag_fsync(int fd) { + if (!usb_serial_jtag_is_connected()) { + // TODO: IDF-14303 + return -1; + } _lock_acquire_recursive(&s_ctx.write_lock); int r = s_ctx.fsync_func(fd); _lock_release_recursive(&s_ctx.write_lock); From baa138bf2ad638b7c8edbdfb2bb625c284bafb40 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Mon, 13 Oct 2025 17:20:04 +0800 Subject: [PATCH 086/106] test(esp_pm): add test case for USJ printing performance during wake-up Add a new test case to verify that USJ printing doesn't block CPU on chip wake-up from light sleep. The test measures the average time per print operation and ensures it's below 5000 microseconds. --- .../test_apps/esp_pm/main/CMakeLists.txt | 2 +- .../esp_pm/test_apps/esp_pm/main/test_pm.c | 24 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/components/esp_pm/test_apps/esp_pm/main/CMakeLists.txt b/components/esp_pm/test_apps/esp_pm/main/CMakeLists.txt index c55abb96b0b..9326fcbd3bb 100644 --- a/components/esp_pm/test_apps/esp_pm/main/CMakeLists.txt +++ b/components/esp_pm/test_apps/esp_pm/main/CMakeLists.txt @@ -5,5 +5,5 @@ set(sources "test_app_main.c" # the component must be registered as a WHOLE_ARCHIVE idf_component_register(SRCS ${sources} INCLUDE_DIRS "." - PRIV_REQUIRES unity esp_pm ulp esp_timer esp_psram esp_driver_gptimer + PRIV_REQUIRES unity esp_pm ulp esp_timer esp_psram esp_driver_gptimer vfs WHOLE_ARCHIVE) diff --git a/components/esp_pm/test_apps/esp_pm/main/test_pm.c b/components/esp_pm/test_apps/esp_pm/main/test_pm.c index 9f69163629b..67b5f6f4e3f 100644 --- a/components/esp_pm/test_apps/esp_pm/main/test_pm.c +++ b/components/esp_pm/test_apps/esp_pm/main/test_pm.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -400,6 +401,29 @@ TEST_CASE("esp_timer with SKIP_UNHANDLED_EVENTS does not wake up CPU from sleep" TEST_ESP_OK(esp_timer_delete(periodic_timer)); } +TEST_CASE("Test USJ printing doesn't block CPU on chip wake-up", "[pm]") +{ + light_sleep_enable(); + fflush(stdout); + fsync(fileno(stdout)); + int64_t printing_time_cost_us = 0, time_end, time_start; + + for (int i = 0; i < 20; ++i) + { + time_start = esp_timer_get_time(); + printf("Dummy print %02d\n", i); + fflush(stdout); + fsync(fileno(stdout)); + time_end = esp_timer_get_time(); + printing_time_cost_us += time_end - time_start; + vTaskDelay(10); + } + int32_t avg_cost = (int32_t)(printing_time_cost_us / 20); + printf("Average cost per print %ld\n", avg_cost); + TEST_ASSERT_LESS_THAN(5000, avg_cost); + light_sleep_disable(); +} + #endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE #endif // CONFIG_PM_ENABLE From dcf03ca0d2c73af94014dfa665950fd22eb45b10 Mon Sep 17 00:00:00 2001 From: Euripedes Rocha Filho Date: Wed, 15 Oct 2025 16:54:08 +0200 Subject: [PATCH 087/106] remove(mqtt): Moves esp-mqtt to component manager esp-mqtt is now a managed component at espressif/mqtt --- .gitlab/ci/rules.yml | 1 - .gitmodules | 4 - components/mqtt/CMakeLists.txt | 6 - components/mqtt/esp-mqtt | 1 - .../mqtt/host_test/mocks/heap/CMakeLists.txt | 4 - .../mqtt/host_test/mocks/heap/heap_mock.c | 16 - .../mqtt/test_apps/.build-test-rules.yml | 19 - .../mqtt/test_apps/common/CMakeLists.txt | 4 - .../common/include/test_mqtt_connection.h | 18 - .../test_apps/common/test_mqtt_connection.c | 144 ------- .../mqtt/test_apps/test_mqtt/CMakeLists.txt | 9 - components/mqtt/test_apps/test_mqtt/README.md | 2 - .../test_apps/test_mqtt/main/CMakeLists.txt | 8 - .../test_mqtt/main/Kconfig.projbuild | 14 - .../mqtt/test_apps/test_mqtt/main/test_mqtt.c | 122 ------ .../test_mqtt/main/test_mqtt_client_broker.c | 227 ---------- .../test_mqtt/main/test_mqtt_client_broker.h | 50 --- .../test_apps/test_mqtt/pytest_mqtt_ut.py | 11 - .../test_apps/test_mqtt/sdkconfig.defaults | 3 - .../mqtt/test_apps/test_mqtt5/CMakeLists.txt | 9 - .../mqtt/test_apps/test_mqtt5/README.md | 2 - .../test_apps/test_mqtt5/main/CMakeLists.txt | 4 - .../test_mqtt5/main/Kconfig.projbuild | 14 - .../test_apps/test_mqtt5/main/test_mqtt5.c | 172 -------- .../main/test_mqtt5_client_broker.c | 285 ------------- .../main/test_mqtt5_client_broker.h | 51 --- .../test_apps/test_mqtt5/pytest_mqtt5_ut.py | 11 - .../test_apps/test_mqtt5/sdkconfig.defaults | 4 - docs/doxygen/Doxyfile | 2 - docs/en/COPYRIGHT.rst | 1 - docs/en/api-guides/performance/ram-usage.rst | 1 - docs/en/api-guides/performance/speed.rst | 2 - docs/en/api-guides/unit-tests.rst | 1 - docs/en/api-guides/wifi-expansion.rst | 4 +- docs/en/api-reference/peripherals/ds.rst | 2 +- docs/en/api-reference/protocols/esp_tls.rst | 2 +- docs/en/api-reference/protocols/mqtt.rst | 206 +-------- .../release-6.x/6.0/protocols.rst | 16 + docs/sphinx-known-warnings.txt | 15 +- docs/zh_CN/COPYRIGHT.rst | 4 +- .../api-guides/performance/ram-usage.rst | 1 - docs/zh_CN/api-guides/performance/speed.rst | 2 - docs/zh_CN/api-guides/unit-tests.rst | 1 - docs/zh_CN/api-reference/peripherals/ds.rst | 2 +- .../zh_CN/api-reference/protocols/esp_tls.rst | 2 +- docs/zh_CN/api-reference/protocols/mqtt.rst | 209 +--------- .../release-6.x/6.0/protocols.rst | 16 + .../main/idf_component.yml | 2 + examples/protocols/.build-test-rules.yml | 65 +-- .../protocols/mqtt/{tcp => }/CMakeLists.txt | 4 +- examples/protocols/mqtt/{ssl => }/README.md | 31 +- .../mqtt/custom_outbox/CMakeLists.txt | 20 - .../protocols/mqtt/custom_outbox/README.md | 100 ----- .../mqtt/custom_outbox/main/CMakeLists.txt | 4 - .../mqtt/custom_outbox/main/Kconfig.projbuild | 13 - .../mqtt/custom_outbox/main/app_main.c | 173 -------- .../mqtt/custom_outbox/main/custom_outbox.cpp | 393 ------------------ .../mqtt/custom_outbox/main/idf_component.yml | 3 - .../mqtt/custom_outbox/sdkconfig.ci.esp32c6 | 1 - .../mqtt/custom_outbox/sdkconfig.defaults | 3 - examples/protocols/mqtt/main/CMakeLists.txt | 6 + .../protocols/mqtt/main/Kconfig.projbuild | 41 ++ .../protocols/mqtt/{ssl => }/main/app_main.c | 81 ++-- .../mqtt/{tcp => }/main/idf_component.yml | 3 + .../main/mosquitto.org.crt | 0 .../mqtt/{ssl => }/pytest_mqtt_ssl.py | 27 +- .../protocols/mqtt/{tcp => }/sdkconfig.ci | 6 +- examples/protocols/mqtt/sdkconfig.defaults | 3 + examples/protocols/mqtt/ssl/CMakeLists.txt | 11 - .../protocols/mqtt/ssl/main/CMakeLists.txt | 3 - .../protocols/mqtt/ssl/main/Kconfig.projbuild | 26 -- .../protocols/mqtt/ssl/main/idf_component.yml | 3 - .../mqtt/ssl/main/mqtt_eclipseprojects_io.pem | 30 -- examples/protocols/mqtt/ssl/sdkconfig.ci | 22 - examples/protocols/mqtt/ssl_ds/CMakeLists.txt | 18 - examples/protocols/mqtt/ssl_ds/README.md | 105 ----- .../protocols/mqtt/ssl_ds/main/CMakeLists.txt | 3 - .../protocols/mqtt/ssl_ds/main/app_main.c | 156 ------- .../mqtt/ssl_ds/main/idf_component.yml | 5 - examples/protocols/mqtt/ssl_ds/partitions.csv | 6 - .../protocols/mqtt/ssl_ds/sdkconfig.defaults | 7 - .../mqtt/ssl_ds/sdkconfig.defaults.esp32h2 | 2 - .../mqtt/ssl_mutual_auth/CMakeLists.txt | 13 - .../protocols/mqtt/ssl_mutual_auth/README.md | 82 ---- .../mqtt/ssl_mutual_auth/main/CMakeLists.txt | 3 - .../mqtt/ssl_mutual_auth/main/app_main.c | 155 ------- .../mqtt/ssl_mutual_auth/main/client.crt | 1 - .../mqtt/ssl_mutual_auth/main/client.key | 1 - .../ssl_mutual_auth/main/idf_component.yml | 3 - .../protocols/mqtt/ssl_psk/CMakeLists.txt | 9 - examples/protocols/mqtt/ssl_psk/README.md | 78 ---- .../mqtt/ssl_psk/main/CMakeLists.txt | 3 - .../protocols/mqtt/ssl_psk/main/app_main.c | 151 ------- .../mqtt/ssl_psk/main/idf_component.yml | 3 - .../protocols/mqtt/ssl_psk/sdkconfig.defaults | 1 - examples/protocols/mqtt/tcp/README.md | 375 ----------------- .../protocols/mqtt/tcp/main/CMakeLists.txt | 3 - .../protocols/mqtt/tcp/main/Kconfig.projbuild | 13 - examples/protocols/mqtt/tcp/main/app_main.c | 162 -------- .../protocols/mqtt/tcp/pytest_mqtt_tcp.py | 97 ----- .../protocols/mqtt/tcp/sdkconfig.ci.p4_eppp | 5 - .../protocols/mqtt/tcp/sdkconfig.ci.p4_wifi | 3 - .../mqtt/tcp/sdkconfig.ci.ppp_connect | 3 - examples/protocols/mqtt/ws/CMakeLists.txt | 9 - examples/protocols/mqtt/ws/README.md | 61 --- .../protocols/mqtt/ws/main/CMakeLists.txt | 3 - .../protocols/mqtt/ws/main/Kconfig.projbuild | 9 - examples/protocols/mqtt/ws/main/app_main.c | 144 ------- .../protocols/mqtt/ws/main/idf_component.yml | 3 - .../mqtt/ws/pytest_mqtt_ws_example.py | 108 ----- examples/protocols/mqtt/ws/sdkconfig.ci | 11 - examples/protocols/mqtt/wss/CMakeLists.txt | 11 - examples/protocols/mqtt/wss/README.md | 73 ---- .../protocols/mqtt/wss/main/CMakeLists.txt | 3 - .../protocols/mqtt/wss/main/Kconfig.projbuild | 20 - examples/protocols/mqtt/wss/main/app_main.c | 135 ------ .../protocols/mqtt/wss/main/idf_component.yml | 3 - .../mqtt/wss/main/mqtt_eclipseprojects_io.pem | 30 -- .../mqtt/wss/pytest_mqtt_wss_example.py | 111 ----- examples/protocols/mqtt/wss/sdkconfig.ci | 13 - examples/protocols/mqtt5/CMakeLists.txt | 4 +- examples/protocols/mqtt5/main/CMakeLists.txt | 9 +- .../protocols/mqtt5/main/Kconfig.projbuild | 40 +- examples/protocols/mqtt5/main/app_main.c | 77 ++-- .../protocols/mqtt5/main/idf_component.yml | 7 + .../ssl_ds => mqtt5}/main/mosquitto.org.crt | 1 - examples/protocols/mqtt5/pytest_mqtt5.py | 5 +- examples/protocols/mqtt5/sdkconfig.ci | 3 +- examples/protocols/mqtt5/sdkconfig.defaults | 5 + tools/ci/astyle-rules.yml | 2 - tools/ci/check_copyright_ignore.txt | 11 - tools/ci/check_kconfigs.py | 38 +- tools/ci/static-analysis-rules.yml | 1 - .../test_apps/protocols/.build-test-rules.yml | 18 - .../protocols/mqtt/build_test/CMakeLists.txt | 14 - .../protocols/mqtt/build_test/README.md | 6 - .../mqtt/build_test/main/CMakeLists.txt | 4 - .../mqtt/build_test/main/mqtt_app.cpp | 101 ----- .../mqtt/publish_connect_test/CMakeLists.txt | 16 - .../mqtt/publish_connect_test/README.md | 25 -- .../mqtt/publish_connect_test/ca.crt | 19 - .../mqtt/publish_connect_test/ca.der | Bin 797 -> 0 bytes .../mqtt/publish_connect_test/ca.key | 28 -- .../mqtt/publish_connect_test/client_inv.crt | 19 - .../publish_connect_test/client_no_pwd.key | 28 -- .../mqtt/publish_connect_test/client_pwd.crt | 18 - .../mqtt/publish_connect_test/client_pwd.key | 30 -- .../publish_connect_test/main/CMakeLists.txt | 4 - .../main/Kconfig.projbuild | 94 ----- .../publish_connect_test/main/connect_test.c | 197 --------- .../main/idf_component.yml | 8 - .../main/mqtt_eclipseprojects_io.pem | 30 -- .../main/publish_connect_test.c | 334 --------------- .../main/publish_connect_test.h | 59 --- .../publish_connect_test/main/publish_test.c | 229 ---------- .../publish_connect_test/pytest_mqtt_app.py | 276 ------------ .../pytest_mqtt_publish_app.py | 335 --------------- .../publish_connect_test/sdkconfig.ci.default | 20 - .../sdkconfig.ci.local_broker | 13 - .../mqtt/publish_connect_test/sdkconfig.qemu | 23 - .../mqtt/publish_connect_test/server.key | 27 -- 161 files changed, 329 insertions(+), 6840 deletions(-) delete mode 100644 components/mqtt/CMakeLists.txt delete mode 160000 components/mqtt/esp-mqtt delete mode 100644 components/mqtt/host_test/mocks/heap/CMakeLists.txt delete mode 100644 components/mqtt/host_test/mocks/heap/heap_mock.c delete mode 100644 components/mqtt/test_apps/.build-test-rules.yml delete mode 100644 components/mqtt/test_apps/common/CMakeLists.txt delete mode 100644 components/mqtt/test_apps/common/include/test_mqtt_connection.h delete mode 100644 components/mqtt/test_apps/common/test_mqtt_connection.c delete mode 100644 components/mqtt/test_apps/test_mqtt/CMakeLists.txt delete mode 100644 components/mqtt/test_apps/test_mqtt/README.md delete mode 100644 components/mqtt/test_apps/test_mqtt/main/CMakeLists.txt delete mode 100644 components/mqtt/test_apps/test_mqtt/main/Kconfig.projbuild delete mode 100644 components/mqtt/test_apps/test_mqtt/main/test_mqtt.c delete mode 100644 components/mqtt/test_apps/test_mqtt/main/test_mqtt_client_broker.c delete mode 100644 components/mqtt/test_apps/test_mqtt/main/test_mqtt_client_broker.h delete mode 100644 components/mqtt/test_apps/test_mqtt/pytest_mqtt_ut.py delete mode 100644 components/mqtt/test_apps/test_mqtt/sdkconfig.defaults delete mode 100644 components/mqtt/test_apps/test_mqtt5/CMakeLists.txt delete mode 100644 components/mqtt/test_apps/test_mqtt5/README.md delete mode 100644 components/mqtt/test_apps/test_mqtt5/main/CMakeLists.txt delete mode 100644 components/mqtt/test_apps/test_mqtt5/main/Kconfig.projbuild delete mode 100644 components/mqtt/test_apps/test_mqtt5/main/test_mqtt5.c delete mode 100644 components/mqtt/test_apps/test_mqtt5/main/test_mqtt5_client_broker.c delete mode 100644 components/mqtt/test_apps/test_mqtt5/main/test_mqtt5_client_broker.h delete mode 100644 components/mqtt/test_apps/test_mqtt5/pytest_mqtt5_ut.py delete mode 100644 components/mqtt/test_apps/test_mqtt5/sdkconfig.defaults create mode 100644 examples/mesh/ip_internal_network/main/idf_component.yml rename examples/protocols/mqtt/{tcp => }/CMakeLists.txt (73%) rename examples/protocols/mqtt/{ssl => }/README.md (59%) delete mode 100644 examples/protocols/mqtt/custom_outbox/CMakeLists.txt delete mode 100644 examples/protocols/mqtt/custom_outbox/README.md delete mode 100644 examples/protocols/mqtt/custom_outbox/main/CMakeLists.txt delete mode 100644 examples/protocols/mqtt/custom_outbox/main/Kconfig.projbuild delete mode 100644 examples/protocols/mqtt/custom_outbox/main/app_main.c delete mode 100644 examples/protocols/mqtt/custom_outbox/main/custom_outbox.cpp delete mode 100644 examples/protocols/mqtt/custom_outbox/main/idf_component.yml delete mode 100644 examples/protocols/mqtt/custom_outbox/sdkconfig.ci.esp32c6 delete mode 100644 examples/protocols/mqtt/custom_outbox/sdkconfig.defaults create mode 100644 examples/protocols/mqtt/main/CMakeLists.txt create mode 100644 examples/protocols/mqtt/main/Kconfig.projbuild rename examples/protocols/mqtt/{ssl => }/main/app_main.c (70%) rename examples/protocols/mqtt/{tcp => }/main/idf_component.yml (80%) rename examples/protocols/mqtt/{ssl_mutual_auth => }/main/mosquitto.org.crt (100%) rename examples/protocols/mqtt/{ssl => }/pytest_mqtt_ssl.py (82%) rename examples/protocols/mqtt/{tcp => }/sdkconfig.ci (68%) create mode 100644 examples/protocols/mqtt/sdkconfig.defaults delete mode 100644 examples/protocols/mqtt/ssl/CMakeLists.txt delete mode 100644 examples/protocols/mqtt/ssl/main/CMakeLists.txt delete mode 100644 examples/protocols/mqtt/ssl/main/Kconfig.projbuild delete mode 100644 examples/protocols/mqtt/ssl/main/idf_component.yml delete mode 100644 examples/protocols/mqtt/ssl/main/mqtt_eclipseprojects_io.pem delete mode 100644 examples/protocols/mqtt/ssl/sdkconfig.ci delete mode 100644 examples/protocols/mqtt/ssl_ds/CMakeLists.txt delete mode 100644 examples/protocols/mqtt/ssl_ds/README.md delete mode 100644 examples/protocols/mqtt/ssl_ds/main/CMakeLists.txt delete mode 100644 examples/protocols/mqtt/ssl_ds/main/app_main.c delete mode 100644 examples/protocols/mqtt/ssl_ds/main/idf_component.yml delete mode 100644 examples/protocols/mqtt/ssl_ds/partitions.csv delete mode 100644 examples/protocols/mqtt/ssl_ds/sdkconfig.defaults delete mode 100644 examples/protocols/mqtt/ssl_ds/sdkconfig.defaults.esp32h2 delete mode 100644 examples/protocols/mqtt/ssl_mutual_auth/CMakeLists.txt delete mode 100644 examples/protocols/mqtt/ssl_mutual_auth/README.md delete mode 100644 examples/protocols/mqtt/ssl_mutual_auth/main/CMakeLists.txt delete mode 100644 examples/protocols/mqtt/ssl_mutual_auth/main/app_main.c delete mode 100644 examples/protocols/mqtt/ssl_mutual_auth/main/client.crt delete mode 100644 examples/protocols/mqtt/ssl_mutual_auth/main/client.key delete mode 100644 examples/protocols/mqtt/ssl_mutual_auth/main/idf_component.yml delete mode 100644 examples/protocols/mqtt/ssl_psk/CMakeLists.txt delete mode 100644 examples/protocols/mqtt/ssl_psk/README.md delete mode 100644 examples/protocols/mqtt/ssl_psk/main/CMakeLists.txt delete mode 100644 examples/protocols/mqtt/ssl_psk/main/app_main.c delete mode 100644 examples/protocols/mqtt/ssl_psk/main/idf_component.yml delete mode 100644 examples/protocols/mqtt/ssl_psk/sdkconfig.defaults delete mode 100644 examples/protocols/mqtt/tcp/README.md delete mode 100644 examples/protocols/mqtt/tcp/main/CMakeLists.txt delete mode 100644 examples/protocols/mqtt/tcp/main/Kconfig.projbuild delete mode 100644 examples/protocols/mqtt/tcp/main/app_main.c delete mode 100644 examples/protocols/mqtt/tcp/pytest_mqtt_tcp.py delete mode 100644 examples/protocols/mqtt/tcp/sdkconfig.ci.p4_eppp delete mode 100644 examples/protocols/mqtt/tcp/sdkconfig.ci.p4_wifi delete mode 100644 examples/protocols/mqtt/tcp/sdkconfig.ci.ppp_connect delete mode 100644 examples/protocols/mqtt/ws/CMakeLists.txt delete mode 100644 examples/protocols/mqtt/ws/README.md delete mode 100644 examples/protocols/mqtt/ws/main/CMakeLists.txt delete mode 100644 examples/protocols/mqtt/ws/main/Kconfig.projbuild delete mode 100644 examples/protocols/mqtt/ws/main/app_main.c delete mode 100644 examples/protocols/mqtt/ws/main/idf_component.yml delete mode 100644 examples/protocols/mqtt/ws/pytest_mqtt_ws_example.py delete mode 100644 examples/protocols/mqtt/ws/sdkconfig.ci delete mode 100644 examples/protocols/mqtt/wss/CMakeLists.txt delete mode 100644 examples/protocols/mqtt/wss/README.md delete mode 100644 examples/protocols/mqtt/wss/main/CMakeLists.txt delete mode 100644 examples/protocols/mqtt/wss/main/Kconfig.projbuild delete mode 100644 examples/protocols/mqtt/wss/main/app_main.c delete mode 100644 examples/protocols/mqtt/wss/main/idf_component.yml delete mode 100644 examples/protocols/mqtt/wss/main/mqtt_eclipseprojects_io.pem delete mode 100644 examples/protocols/mqtt/wss/pytest_mqtt_wss_example.py delete mode 100644 examples/protocols/mqtt/wss/sdkconfig.ci rename examples/protocols/{mqtt/ssl_ds => mqtt5}/main/mosquitto.org.crt (99%) delete mode 100644 tools/test_apps/protocols/mqtt/build_test/CMakeLists.txt delete mode 100644 tools/test_apps/protocols/mqtt/build_test/README.md delete mode 100644 tools/test_apps/protocols/mqtt/build_test/main/CMakeLists.txt delete mode 100644 tools/test_apps/protocols/mqtt/build_test/main/mqtt_app.cpp delete mode 100644 tools/test_apps/protocols/mqtt/publish_connect_test/CMakeLists.txt delete mode 100644 tools/test_apps/protocols/mqtt/publish_connect_test/README.md delete mode 100644 tools/test_apps/protocols/mqtt/publish_connect_test/ca.crt delete mode 100644 tools/test_apps/protocols/mqtt/publish_connect_test/ca.der delete mode 100644 tools/test_apps/protocols/mqtt/publish_connect_test/ca.key delete mode 100644 tools/test_apps/protocols/mqtt/publish_connect_test/client_inv.crt delete mode 100644 tools/test_apps/protocols/mqtt/publish_connect_test/client_no_pwd.key delete mode 100644 tools/test_apps/protocols/mqtt/publish_connect_test/client_pwd.crt delete mode 100644 tools/test_apps/protocols/mqtt/publish_connect_test/client_pwd.key delete mode 100644 tools/test_apps/protocols/mqtt/publish_connect_test/main/CMakeLists.txt delete mode 100644 tools/test_apps/protocols/mqtt/publish_connect_test/main/Kconfig.projbuild delete mode 100644 tools/test_apps/protocols/mqtt/publish_connect_test/main/connect_test.c delete mode 100644 tools/test_apps/protocols/mqtt/publish_connect_test/main/idf_component.yml delete mode 100644 tools/test_apps/protocols/mqtt/publish_connect_test/main/mqtt_eclipseprojects_io.pem delete mode 100644 tools/test_apps/protocols/mqtt/publish_connect_test/main/publish_connect_test.c delete mode 100644 tools/test_apps/protocols/mqtt/publish_connect_test/main/publish_connect_test.h delete mode 100644 tools/test_apps/protocols/mqtt/publish_connect_test/main/publish_test.c delete mode 100644 tools/test_apps/protocols/mqtt/publish_connect_test/pytest_mqtt_app.py delete mode 100644 tools/test_apps/protocols/mqtt/publish_connect_test/pytest_mqtt_publish_app.py delete mode 100644 tools/test_apps/protocols/mqtt/publish_connect_test/sdkconfig.ci.default delete mode 100644 tools/test_apps/protocols/mqtt/publish_connect_test/sdkconfig.ci.local_broker delete mode 100644 tools/test_apps/protocols/mqtt/publish_connect_test/sdkconfig.qemu delete mode 100644 tools/test_apps/protocols/mqtt/publish_connect_test/server.key diff --git a/.gitlab/ci/rules.yml b/.gitlab/ci/rules.yml index ce89384f0f7..590ff2f0878 100644 --- a/.gitlab/ci/rules.yml +++ b/.gitlab/ci/rules.yml @@ -150,7 +150,6 @@ - "components/esp_coex/lib" - "components/lwip/lwip" - "components/mbedtls/mbedtls" - - "components/mqtt/esp-mqtt" - "components/openthread/lib" - "components/openthread/openthread" - "components/protobuf-c/protobuf-c" diff --git a/.gitmodules b/.gitmodules index 6c3df372811..86ec4a3da5e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -54,10 +54,6 @@ path = components/lwip/lwip url = ../../espressif/esp-lwip.git -[submodule "components/mqtt/esp-mqtt"] - path = components/mqtt/esp-mqtt - url = ../../espressif/esp-mqtt.git - [submodule "components/protobuf-c/protobuf-c"] path = components/protobuf-c/protobuf-c url = ../../protobuf-c/protobuf-c.git diff --git a/components/mqtt/CMakeLists.txt b/components/mqtt/CMakeLists.txt deleted file mode 100644 index d2bb24a78ed..00000000000 --- a/components/mqtt/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -if(NOT EXISTS ${CMAKE_CURRENT_LIST_DIR}/esp-mqtt/CMakeLists.txt) - set(COMMAND "git submodule update --init --recursive") - message(FATAL_ERROR "Missing esp-mqtt submodule. Please run '${COMMAND}' in ESP-IDF directory to fix this.") -else() - include(${CMAKE_CURRENT_LIST_DIR}/esp-mqtt/CMakeLists.txt) -endif() diff --git a/components/mqtt/esp-mqtt b/components/mqtt/esp-mqtt deleted file mode 160000 index 6af4446a48e..00000000000 --- a/components/mqtt/esp-mqtt +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 6af4446a48ea7fa54948edc4e62277ed70abb6e1 diff --git a/components/mqtt/host_test/mocks/heap/CMakeLists.txt b/components/mqtt/host_test/mocks/heap/CMakeLists.txt deleted file mode 100644 index 0a0c8a6341c..00000000000 --- a/components/mqtt/host_test/mocks/heap/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -idf_component_get_property(original_heap_dir heap COMPONENT_OVERRIDEN_DIR) - -idf_component_register(SRCS heap_mock.c - INCLUDE_DIRS "${original_heap_dir}/include") diff --git a/components/mqtt/host_test/mocks/heap/heap_mock.c b/components/mqtt/host_test/mocks/heap/heap_mock.c deleted file mode 100644 index e0fc666ba0a..00000000000 --- a/components/mqtt/host_test/mocks/heap/heap_mock.c +++ /dev/null @@ -1,16 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include "esp_heap_caps.h" -#include -#include - - - -void *heap_caps_calloc(size_t n, size_t size, uint32_t caps) { - (void)caps; - return calloc(n, size); - -} diff --git a/components/mqtt/test_apps/.build-test-rules.yml b/components/mqtt/test_apps/.build-test-rules.yml deleted file mode 100644 index 2e58826b905..00000000000 --- a/components/mqtt/test_apps/.build-test-rules.yml +++ /dev/null @@ -1,19 +0,0 @@ -# Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps - -components/mqtt/test_apps: - disable: - - if: IDF_TARGET not in ["esp32", "esp32c3"] - reason: component test apps, needn't build all targets (chosen two, one for each architecture) - disable_test: - - if: IDF_TARGET != "esp32" - temporary: false - reason: Only esp32 target has ethernet runners - depends_components: - - mqtt - - tcp_transport - - app_update - - esp_eth - - esp_netif - - esp_event - depends_filepatterns: - - components/mqtt/test_apps/common/**/* diff --git a/components/mqtt/test_apps/common/CMakeLists.txt b/components/mqtt/test_apps/common/CMakeLists.txt deleted file mode 100644 index 97ab3b53bca..00000000000 --- a/components/mqtt/test_apps/common/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ - -idf_component_register(SRCS test_mqtt_connection.c - INCLUDE_DIRS ${CMAKE_CURRENT_LIST_DIR}/include - PRIV_REQUIRES unity esp_event esp_netif esp_eth) diff --git a/components/mqtt/test_apps/common/include/test_mqtt_connection.h b/components/mqtt/test_apps/common/include/test_mqtt_connection.h deleted file mode 100644 index 460beccfe64..00000000000 --- a/components/mqtt/test_apps/common/include/test_mqtt_connection.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#pragma once -#include "soc/soc_caps.h" - -/** - * Connection test fixture setup, so we expect the broker is available - * on network - */ -void connect_test_fixture_setup(void); - -/** - * Cleans up the connection - */ -void connect_test_fixture_teardown(void); diff --git a/components/mqtt/test_apps/common/test_mqtt_connection.c b/components/mqtt/test_apps/common/test_mqtt_connection.c deleted file mode 100644 index cb51a4e739e..00000000000 --- a/components/mqtt/test_apps/common/test_mqtt_connection.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include "freertos/FreeRTOS.h" -#include "freertos/event_groups.h" -#include "unity.h" -#include "esp_event.h" -#include "esp_netif.h" -#include "esp_eth.h" -#include "esp_log.h" - - -#if SOC_EMAC_SUPPORTED -#define ETH_START_BIT BIT(0) -#define ETH_STOP_BIT BIT(1) -#define ETH_CONNECT_BIT BIT(2) -#define ETH_GOT_IP_BIT BIT(3) -#define ETH_STOP_TIMEOUT_MS (10000) -#define ETH_GET_IP_TIMEOUT_MS (60000) - - -static const char *TAG = "esp32_eth_test_fixture"; -static EventGroupHandle_t s_eth_event_group = NULL; -static esp_netif_t *s_eth_netif = NULL; -static esp_eth_mac_t *s_mac = NULL; -static esp_eth_phy_t *s_phy = NULL; -static esp_eth_handle_t s_eth_handle = NULL; -static esp_eth_netif_glue_handle_t s_eth_glue = NULL; - - -/** Event handler for Ethernet events */ -static void eth_event_handler(void *arg, esp_event_base_t event_base, - int32_t event_id, void *event_data) -{ - EventGroupHandle_t eth_event_group = (EventGroupHandle_t)arg; - switch (event_id) { - case ETHERNET_EVENT_CONNECTED: - xEventGroupSetBits(eth_event_group, ETH_CONNECT_BIT); - ESP_LOGI(TAG, "Ethernet Link Up"); - break; - case ETHERNET_EVENT_DISCONNECTED: - ESP_LOGI(TAG, "Ethernet Link Down"); - break; - case ETHERNET_EVENT_START: - xEventGroupSetBits(eth_event_group, ETH_START_BIT); - ESP_LOGI(TAG, "Ethernet Started"); - break; - case ETHERNET_EVENT_STOP: - xEventGroupSetBits(eth_event_group, ETH_STOP_BIT); - ESP_LOGI(TAG, "Ethernet Stopped"); - break; - default: - break; - } -} - -/** Event handler for IP_EVENT_ETH_GOT_IP */ -static void got_ip_event_handler(void *arg, esp_event_base_t event_base, - int32_t event_id, void *event_data) -{ - EventGroupHandle_t eth_event_group = (EventGroupHandle_t)arg; - ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data; - const esp_netif_ip_info_t *ip_info = &event->ip_info; - ESP_LOGI(TAG, "Ethernet Got IP Address"); - ESP_LOGI(TAG, "~~~~~~~~~~~"); - ESP_LOGI(TAG, "ETHIP:" IPSTR, IP2STR(&ip_info->ip)); - ESP_LOGI(TAG, "ETHMASK:" IPSTR, IP2STR(&ip_info->netmask)); - ESP_LOGI(TAG, "ETHGW:" IPSTR, IP2STR(&ip_info->gw)); - ESP_LOGI(TAG, "~~~~~~~~~~~"); - xEventGroupSetBits(eth_event_group, ETH_GOT_IP_BIT); -} - -static esp_err_t test_uninstall_driver(esp_eth_handle_t eth_hdl, uint32_t ms_to_wait) -{ - int i = 0; - ms_to_wait += 100; - for (i = 0; i < ms_to_wait / 100; i++) { - vTaskDelay(pdMS_TO_TICKS(100)); - if (esp_eth_driver_uninstall(eth_hdl) == ESP_OK) { - break; - } - } - if (i < ms_to_wait / 10) { - return ESP_OK; - } else { - return ESP_FAIL; - } -} - - -void connect_test_fixture_setup(void) -{ - EventBits_t bits; - s_eth_event_group = xEventGroupCreate(); - TEST_ASSERT(s_eth_event_group != NULL); - TEST_ESP_OK(esp_event_loop_create_default()); - // create TCP/IP netif - esp_netif_config_t netif_cfg = ESP_NETIF_DEFAULT_ETH(); - s_eth_netif = esp_netif_new(&netif_cfg); - - eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); - eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG(); - s_mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config); - eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); - s_phy = esp_eth_phy_new_generic(&phy_config); - esp_eth_config_t eth_config = ETH_DEFAULT_CONFIG(s_mac, s_phy); - - // install Ethernet driver - TEST_ESP_OK(esp_eth_driver_install(ð_config, &s_eth_handle)); - // combine driver with netif - s_eth_glue = esp_eth_new_netif_glue(s_eth_handle); - TEST_ESP_OK(esp_netif_attach(s_eth_netif, s_eth_glue)); - // register user defined event handlers - TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, s_eth_event_group)); - TEST_ESP_OK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, s_eth_event_group)); - // start Ethernet driver - TEST_ESP_OK(esp_eth_start(s_eth_handle)); - /* wait for IP lease */ - bits = xEventGroupWaitBits(s_eth_event_group, ETH_GOT_IP_BIT, true, true, pdMS_TO_TICKS(ETH_GET_IP_TIMEOUT_MS)); - TEST_ASSERT((bits & ETH_GOT_IP_BIT) == ETH_GOT_IP_BIT); -} - -void connect_test_fixture_teardown(void) -{ - EventBits_t bits; - // stop Ethernet driver - TEST_ESP_OK(esp_eth_stop(s_eth_handle)); - /* wait for connection stop */ - bits = xEventGroupWaitBits(s_eth_event_group, ETH_STOP_BIT, true, true, pdMS_TO_TICKS(ETH_STOP_TIMEOUT_MS)); - TEST_ASSERT((bits & ETH_STOP_BIT) == ETH_STOP_BIT); - TEST_ESP_OK(esp_eth_del_netif_glue(s_eth_glue)); - /* driver should be uninstalled within 2 seconds */ - TEST_ESP_OK(test_uninstall_driver(s_eth_handle, 2000)); - TEST_ESP_OK(s_phy->del(s_phy)); - TEST_ESP_OK(s_mac->del(s_mac)); - TEST_ESP_OK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_ETH_GOT_IP, got_ip_event_handler)); - TEST_ESP_OK(esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, eth_event_handler)); - esp_netif_destroy(s_eth_netif); - TEST_ESP_OK(esp_event_loop_delete_default()); - vEventGroupDelete(s_eth_event_group); -} -#endif // SOC_EMAC_SUPPORTED diff --git a/components/mqtt/test_apps/test_mqtt/CMakeLists.txt b/components/mqtt/test_apps/test_mqtt/CMakeLists.txt deleted file mode 100644 index a3ae29f78cb..00000000000 --- a/components/mqtt/test_apps/test_mqtt/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -#This is the project CMakeLists.txt file for the test subproject -cmake_minimum_required(VERSION 3.22) - -set(EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/test_apps/components" - "../common") - -set(COMPONENTS main) -include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(esp_mqtt_client_test) diff --git a/components/mqtt/test_apps/test_mqtt/README.md b/components/mqtt/test_apps/test_mqtt/README.md deleted file mode 100644 index 1fb88efd154..00000000000 --- a/components/mqtt/test_apps/test_mqtt/README.md +++ /dev/null @@ -1,2 +0,0 @@ -| Supported Targets | ESP32 | ESP32-C3 | -| ----------------- | ----- | -------- | diff --git a/components/mqtt/test_apps/test_mqtt/main/CMakeLists.txt b/components/mqtt/test_apps/test_mqtt/main/CMakeLists.txt deleted file mode 100644 index 0647fe29f13..00000000000 --- a/components/mqtt/test_apps/test_mqtt/main/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -set(srcs test_mqtt_client_broker.c test_mqtt.c) - -if(CONFIG_MQTT_PROTOCOL_5) - list(APPEND srcs test_mqtt5_client_broker.c test_mqtt5.c) -endif() - -idf_component_register(SRCS "${srcs}" - PRIV_REQUIRES cmock test_utils mqtt nvs_flash app_update spi_flash common) diff --git a/components/mqtt/test_apps/test_mqtt/main/Kconfig.projbuild b/components/mqtt/test_apps/test_mqtt/main/Kconfig.projbuild deleted file mode 100644 index 30b2c1087a6..00000000000 --- a/components/mqtt/test_apps/test_mqtt/main/Kconfig.projbuild +++ /dev/null @@ -1,14 +0,0 @@ -menu "ESP-MQTT Unit Test Config" - - config MQTT_TEST_BROKER_URI - string "URI of the test broker" - default "mqtt://mqtt.eclipseprojects.io" - help - URL of an mqtt broker which this test connects to. - - config MQTT5_TEST_BROKER_URI - string "URI of the test broker" - default "mqtt://mqtt.eclipseprojects.io" - help - URL of an mqtt broker which this test connects to. -endmenu diff --git a/components/mqtt/test_apps/test_mqtt/main/test_mqtt.c b/components/mqtt/test_apps/test_mqtt/main/test_mqtt.c deleted file mode 100644 index cb56a5e0636..00000000000 --- a/components/mqtt/test_apps/test_mqtt/main/test_mqtt.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Unlicense OR CC0-1.0 - * - * This test code is in the Public Domain (or CC0 licensed, at your option.) - * - * Unless required by applicable law or agreed to in writing, this - * software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, either express or implied. - */ - -#include -#include "unity_fixture.h" -#include "unity_fixture_extras.h" -#include "test_utils.h" -#include "memory_checks.h" -#include "mqtt_client.h" -#include "esp_ota_ops.h" -#include "test_mqtt_client_broker.h" -#include "test_mqtt_connection.h" -#include "esp_partition.h" - -TEST_GROUP(mqtt); - -TEST_SETUP(mqtt){ - test_utils_record_free_mem(); - TEST_ESP_OK(test_utils_set_leak_level(0, ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_GENERAL)); -} - -TEST_TEAR_DOWN(mqtt){ - test_utils_finish_and_evaluate_leaks(test_utils_get_leak_level(ESP_LEAK_TYPE_WARNING, ESP_COMP_LEAK_ALL), - test_utils_get_leak_level(ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_ALL)); -} - -TEST(mqtt, init_with_invalid_url) -{ - const esp_mqtt_client_config_t mqtt_cfg = { - .broker.address.uri = "INVALID", - }; - esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg); - TEST_ASSERT_EQUAL(NULL, client ); -} - -TEST(mqtt, init_and_deinit) -{ - const esp_mqtt_client_config_t mqtt_cfg = { - // no connection takes place, but the uri has to be valid for init() to succeed - .broker.address.uri = "mqtts://localhost:8883", - }; - esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg); - TEST_ASSERT_NOT_EQUAL(NULL, client ); - esp_mqtt_client_destroy(client); -} - -static const char* this_bin_addr(void) -{ - esp_partition_mmap_handle_t out_handle; - const void *binary_address; - const esp_partition_t* partition = esp_ota_get_running_partition(); - esp_partition_mmap(partition, 0, partition->size, ESP_PARTITION_MMAP_DATA, &binary_address, &out_handle); - return binary_address; -} - -TEST(mqtt, enqueue_and_destroy_outbox) -{ - const char * bin_addr = this_bin_addr(); - - // Reseting leak detection since this_bin_addr adds to allocated memory. - test_utils_record_free_mem(); - TEST_ESP_OK(test_utils_set_leak_level(0, ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_GENERAL)); - const int messages = 20; - const int size = 2000; - const esp_mqtt_client_config_t mqtt_cfg = { - // no connection takes place, but the uri has to be valid for init() to succeed - .broker.address.uri = "mqtts://localhost:8883", - }; - esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg); - TEST_ASSERT_NOT_EQUAL(NULL, client ); - int bytes_before = esp_get_free_heap_size(); - for (int i=0; iqos; - xEventGroupSetBits(s_event_group, DATA_BIT); - } -} - -static void mqtt_data_handler_lwt(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) -{ - if (event_id == MQTT_EVENT_DATA) { - esp_mqtt_event_handle_t event = event_data; - ESP_LOGI("mqtt-lwt", "MQTT_EVENT_DATA"); - ESP_LOGI("mqtt-lwt", "TOPIC=%.*s", event->topic_len, event->topic); - ESP_LOGI("mqtt-lwt", "DATA=%.*s", event->data_len, event->data); - if (strncmp(event->data, "no-lwt", event->data_len) == 0) { - // no lwt, just to indicate the test has finished - xEventGroupSetBits(s_event_group, DATA_BIT); - } else { - // count up any potential lwt message - int * count = handler_args; - *count = *count + 1; - ESP_LOGE("mqtt-lwt", "count=%d", *count); - } - } -} - -static void mqtt_data_handler_subscribe(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) -{ - if (event_id == MQTT_EVENT_SUBSCRIBED) { - esp_mqtt_event_handle_t event = event_data; - ESP_LOGI("mqtt-subscribe", "MQTT_EVENT_SUBSCRIBED, data size=%d", event->data_len); - int * sub_payload = handler_args; - if (event->data_len == 1) { - ESP_LOGI("mqtt-subscribe", "DATA=%d", *(uint8_t*)event->data); - *sub_payload = *(uint8_t*)event->data; - } - xEventGroupSetBits(s_event_group, DATA_BIT); - } -} - - -static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) -{ - switch ((esp_mqtt_event_id_t)event_id) { - case MQTT_EVENT_CONNECTED: - xEventGroupSetBits(s_event_group, CONNECT_BIT); - break; - - case MQTT_EVENT_DISCONNECTED: - xEventGroupSetBits(s_event_group, DISCONNECT_BIT); - break; - default: - break; - } -} - -bool mqtt_connect_disconnect(void) -{ - const esp_mqtt_client_config_t mqtt_cfg = { - .broker.address.uri = CONFIG_MQTT_TEST_BROKER_URI, - .network.disable_auto_reconnect = true, - }; - s_event_group = xEventGroupCreate(); - esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg); - TEST_ASSERT_TRUE(NULL != client ); - esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL); - TEST_ASSERT_TRUE(ESP_OK == esp_mqtt_client_start(client)); - WAIT_FOR_EVENT(CONNECT_BIT); - esp_mqtt_client_disconnect(client); - WAIT_FOR_EVENT(DISCONNECT_BIT); - esp_mqtt_client_reconnect(client); - WAIT_FOR_EVENT(CONNECT_BIT); - esp_mqtt_client_destroy(client); - vEventGroupDelete(s_event_group); - return true; -} - -bool mqtt_subscribe_publish(void) -{ - const esp_mqtt_client_config_t mqtt_cfg = { - .broker.address.uri = CONFIG_MQTT_TEST_BROKER_URI, - }; - char* topic = append_mac("topic"); - TEST_ASSERT_TRUE(NULL != topic); - s_event_group = xEventGroupCreate(); - esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg); - TEST_ASSERT_TRUE(NULL != client ); - esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL); - TEST_ASSERT_TRUE(ESP_OK == esp_mqtt_client_start(client)); - WAIT_FOR_EVENT(CONNECT_BIT); - int qos = -1; - esp_mqtt_client_register_event(client, MQTT_EVENT_DATA, mqtt_data_handler_qos, &qos); - TEST_ASSERT_TRUE(esp_mqtt_client_subscribe(client, topic, 2) != -1); - TEST_ASSERT_TRUE(esp_mqtt_client_publish(client, topic, "message", 0, 2, 0) != -1); - WAIT_FOR_EVENT(DATA_BIT); - TEST_ASSERT_TRUE(qos == 2); - TEST_ASSERT_TRUE(esp_mqtt_client_publish(client, topic, "message", 0, 1, 0) != -1); - WAIT_FOR_EVENT(DATA_BIT); - TEST_ASSERT_TRUE(qos == 1); - esp_mqtt_client_destroy(client); - vEventGroupDelete(s_event_group); - free(topic); - return true; -} - -bool mqtt_lwt_clean_disconnect(void) -{ - char* lwt = append_mac("lwt"); - TEST_ASSERT_TRUE(lwt); - const esp_mqtt_client_config_t mqtt_cfg1 = { - .broker.address.uri = CONFIG_MQTT_TEST_BROKER_URI, - .credentials.set_null_client_id = true, - .session.last_will.topic = lwt, - .session.last_will.msg = "lwt_msg" - }; - const esp_mqtt_client_config_t mqtt_cfg2 = { - .broker.address.uri = CONFIG_MQTT_TEST_BROKER_URI, - .credentials.set_null_client_id = true, - .session.last_will.topic = lwt, - .session.last_will.msg = "lwt_msg" - }; - s_event_group = xEventGroupCreate(); - - esp_mqtt_client_handle_t client1 = esp_mqtt_client_init(&mqtt_cfg1); - esp_mqtt_client_handle_t client2 = esp_mqtt_client_init(&mqtt_cfg2); - TEST_ASSERT_TRUE(NULL != client1 && NULL != client2 ); - esp_mqtt_client_register_event(client1, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL); - esp_mqtt_client_register_event(client2, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL); - TEST_ASSERT_TRUE(esp_mqtt_client_start(client1) == ESP_OK); - WAIT_FOR_EVENT(CONNECT_BIT); - TEST_ASSERT_TRUE(esp_mqtt_client_start(client2) == ESP_OK); - WAIT_FOR_EVENT(CONNECT_BIT); - int counter = 0; - esp_mqtt_client_register_event(client1, MQTT_EVENT_DATA, mqtt_data_handler_lwt, &counter); - esp_mqtt_client_register_event(client2, MQTT_EVENT_DATA, mqtt_data_handler_lwt, &counter); - TEST_ASSERT_TRUE(esp_mqtt_client_subscribe(client1, lwt, 0) != -1); - TEST_ASSERT_TRUE(esp_mqtt_client_subscribe(client2, lwt, 0) != -1); - esp_mqtt_client_disconnect(client1); - WAIT_FOR_EVENT(DISCONNECT_BIT); - esp_mqtt_client_reconnect(client1); - WAIT_FOR_EVENT(CONNECT_BIT); - TEST_ASSERT_TRUE(esp_mqtt_client_subscribe(client1, lwt, 0) != -1); - esp_mqtt_client_stop(client2); - esp_mqtt_client_start(client2); - WAIT_FOR_EVENT(CONNECT_BIT); - TEST_ASSERT_TRUE(esp_mqtt_client_subscribe(client2, lwt, 0) != -1); - TEST_ASSERT_TRUE(esp_mqtt_client_publish(client1, lwt, "no-lwt", 0, 0, 0) != -1); - WAIT_FOR_EVENT(DATA_BIT); - TEST_ASSERT_TRUE(counter == 0); - esp_mqtt_client_destroy(client1); - esp_mqtt_client_destroy(client2); - vEventGroupDelete(s_event_group); - free(lwt); - return true; -} - -bool mqtt_subscribe_payload(void) -{ - const esp_mqtt_client_config_t mqtt_cfg = { - .broker.address.uri = CONFIG_MQTT_TEST_BROKER_URI, - .network.disable_auto_reconnect = true, - }; - char* topic = append_mac("topic"); - TEST_ASSERT_TRUE(NULL != topic); - s_event_group = xEventGroupCreate(); - esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg); - TEST_ASSERT_TRUE(NULL != client ); - esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL); - TEST_ASSERT_TRUE(ESP_OK == esp_mqtt_client_start(client)); - WAIT_FOR_EVENT(CONNECT_BIT); - int qos_payload = -1; - esp_mqtt_client_register_event(client, MQTT_EVENT_SUBSCRIBED, mqtt_data_handler_subscribe, &qos_payload); - TEST_ASSERT_TRUE(esp_mqtt_client_subscribe(client, topic, 2) != -1); - WAIT_FOR_EVENT(DATA_BIT); - TEST_ASSERT_TRUE(qos_payload == 2); - TEST_ASSERT_TRUE(esp_mqtt_client_subscribe(client, topic, 0) != -1); - WAIT_FOR_EVENT(DATA_BIT); - TEST_ASSERT_TRUE(qos_payload == 0); - esp_mqtt_client_destroy(client); - vEventGroupDelete(s_event_group); - free(topic); - return true; -} diff --git a/components/mqtt/test_apps/test_mqtt/main/test_mqtt_client_broker.h b/components/mqtt/test_apps/test_mqtt/main/test_mqtt_client_broker.h deleted file mode 100644 index 63e7856f70d..00000000000 --- a/components/mqtt/test_apps/test_mqtt/main/test_mqtt_client_broker.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#pragma once -#include "esp_log.h" - -/** - * @brief MQTT client-broker tests are not implemented as separate test cases - * due to time consuming connection setup/teardown. - * This utility macro is used to run functional cases as MQTT tests - * and evaluate as separate assertions in one "mqtt broker tests" test case. - */ -#define RUN_MQTT_BROKER_TEST(test_name) \ - do { \ - ESP_LOGI("mqtt_test", "Running test:" #test_name "()"); \ - TEST_ASSERT_TRUE_MESSAGE(test_name(), "Mqtt test failed: " #test_name "() "); \ - ESP_LOGI("mqtt_test", "Test:" #test_name "() passed "); \ - } while(0) - - -/** - * @brief This module contains mqtt test cases interacting the client with a (real) broker - */ - -/** - * @brief The client subscribes and publishes on the same topic - * and verifies the received published qos in the event - */ -bool mqtt_subscribe_publish(void); - -/** - * @brief The client connects, disconnects and reconnects. - * Tests basic client state transitions - */ -bool mqtt_connect_disconnect(void); - -/** - * @brief Two clients with defined lwt connect and subscribe to lwt topic. - * This test verifies that no lwt is send when each of the client disconnects. - * (we expect a clean disconnection, so no last-will being sent) - */ -bool mqtt_lwt_clean_disconnect(void); - -/** - * @brief The client subscribes to a topic with certain qos - * and verifies the qos in SUBACK message from the broker. - */ -bool mqtt_subscribe_payload(void); diff --git a/components/mqtt/test_apps/test_mqtt/pytest_mqtt_ut.py b/components/mqtt/test_apps/test_mqtt/pytest_mqtt_ut.py deleted file mode 100644 index 429b857470a..00000000000 --- a/components/mqtt/test_apps/test_mqtt/pytest_mqtt_ut.py +++ /dev/null @@ -1,11 +0,0 @@ -# SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD -# SPDX-License-Identifier: Unlicense OR CC0-1.0 -import pytest -from pytest_embedded import Dut -from pytest_embedded_idf.utils import idf_parametrize - - -@pytest.mark.ethernet -@idf_parametrize('target', ['esp32'], indirect=['target']) -def test_mqtt_client(dut: Dut) -> None: - dut.expect_unity_test_output() diff --git a/components/mqtt/test_apps/test_mqtt/sdkconfig.defaults b/components/mqtt/test_apps/test_mqtt/sdkconfig.defaults deleted file mode 100644 index 2bcae3f3bc3..00000000000 --- a/components/mqtt/test_apps/test_mqtt/sdkconfig.defaults +++ /dev/null @@ -1,3 +0,0 @@ -# General options for additional checks -CONFIG_ESP_TASK_WDT_EN=n -CONFIG_UNITY_ENABLE_FIXTURE=y diff --git a/components/mqtt/test_apps/test_mqtt5/CMakeLists.txt b/components/mqtt/test_apps/test_mqtt5/CMakeLists.txt deleted file mode 100644 index 2d7e6af6f9c..00000000000 --- a/components/mqtt/test_apps/test_mqtt5/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -#This is the project CMakeLists.txt file for the test subproject -cmake_minimum_required(VERSION 3.22) - -set(EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/test_apps/components" - "../common") - -set(COMPONENTS main) -include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(esp_mqtt5_client_test) diff --git a/components/mqtt/test_apps/test_mqtt5/README.md b/components/mqtt/test_apps/test_mqtt5/README.md deleted file mode 100644 index 1fb88efd154..00000000000 --- a/components/mqtt/test_apps/test_mqtt5/README.md +++ /dev/null @@ -1,2 +0,0 @@ -| Supported Targets | ESP32 | ESP32-C3 | -| ----------------- | ----- | -------- | diff --git a/components/mqtt/test_apps/test_mqtt5/main/CMakeLists.txt b/components/mqtt/test_apps/test_mqtt5/main/CMakeLists.txt deleted file mode 100644 index d33a86ceb8d..00000000000 --- a/components/mqtt/test_apps/test_mqtt5/main/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -set(srcs test_mqtt5_client_broker.c test_mqtt5.c) - -idf_component_register(SRCS "${srcs}" - PRIV_REQUIRES cmock test_utils mqtt nvs_flash app_update spi_flash common) diff --git a/components/mqtt/test_apps/test_mqtt5/main/Kconfig.projbuild b/components/mqtt/test_apps/test_mqtt5/main/Kconfig.projbuild deleted file mode 100644 index 30b2c1087a6..00000000000 --- a/components/mqtt/test_apps/test_mqtt5/main/Kconfig.projbuild +++ /dev/null @@ -1,14 +0,0 @@ -menu "ESP-MQTT Unit Test Config" - - config MQTT_TEST_BROKER_URI - string "URI of the test broker" - default "mqtt://mqtt.eclipseprojects.io" - help - URL of an mqtt broker which this test connects to. - - config MQTT5_TEST_BROKER_URI - string "URI of the test broker" - default "mqtt://mqtt.eclipseprojects.io" - help - URL of an mqtt broker which this test connects to. -endmenu diff --git a/components/mqtt/test_apps/test_mqtt5/main/test_mqtt5.c b/components/mqtt/test_apps/test_mqtt5/main/test_mqtt5.c deleted file mode 100644 index 9d8705d83f7..00000000000 --- a/components/mqtt/test_apps/test_mqtt5/main/test_mqtt5.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include "unity_fixture.h" -#include "unity_fixture_extras.h" -#include "test_utils.h" -#include "memory_checks.h" -#include "mqtt_client.h" -#include "esp_ota_ops.h" -#include "test_mqtt5_client_broker.h" -#include "test_mqtt_connection.h" -#include "esp_partition.h" - - -TEST_GROUP(mqtt5); - -TEST_SETUP(mqtt5) -{ - test_utils_record_free_mem(); - TEST_ESP_OK(test_utils_set_leak_level(0, ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_GENERAL)); -} - -TEST_TEAR_DOWN(mqtt5) -{ - test_utils_finish_and_evaluate_leaks(test_utils_get_leak_level(ESP_LEAK_TYPE_WARNING, ESP_COMP_LEAK_ALL), - test_utils_get_leak_level(ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_ALL)); -} - -static esp_mqtt5_user_property_item_t user_property_arr[3] = { - {"board", "esp32"}, - {"u", "user"}, - {"p", "password"} -}; - -TEST(mqtt5, init_with_invalid_url) -{ - const esp_mqtt_client_config_t mqtt5_cfg = { - .broker.address.uri = "INVALID", - .session.protocol_ver = MQTT_PROTOCOL_V_5, - }; - esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt5_cfg); - TEST_ASSERT_EQUAL(NULL, client ); -} - -TEST(mqtt5, init_and_deinit) -{ - const esp_mqtt_client_config_t mqtt5_cfg = { - // no connection takes place, but the uri has to be valid for init() to succeed - .broker.address.uri = "mqtts://localhost:8883", - .session.protocol_ver = MQTT_PROTOCOL_V_5, - .credentials.username = "123", - .credentials.authentication.password = "456", - .session.last_will.topic = "/topic/will", - .session.last_will.msg = "i will leave", - .session.last_will.msg_len = 12, - .session.last_will.qos = 1, - .session.last_will.retain = true, - }; - esp_mqtt5_connection_property_config_t connect_property = { - .session_expiry_interval = 10, - .maximum_packet_size = 1024, - .receive_maximum = 65535, - .topic_alias_maximum = 2, - .request_resp_info = true, - .request_problem_info = true, - .will_delay_interval = 10, - .payload_format_indicator = true, - .message_expiry_interval = 10, - .content_type = "json", - .response_topic = "/test/response", - .correlation_data = "123456", - .correlation_data_len = 6, - }; - - esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt5_cfg); - esp_mqtt5_client_set_user_property(&connect_property.user_property, user_property_arr, 3); - esp_mqtt5_client_set_user_property(&connect_property.will_user_property, user_property_arr, 3); - esp_mqtt5_client_set_connect_property(client, &connect_property); - esp_mqtt5_client_delete_user_property(connect_property.user_property); - esp_mqtt5_client_delete_user_property(connect_property.will_user_property); - TEST_ASSERT_NOT_EQUAL(NULL, client ); - esp_mqtt_client_destroy(client); -} - -static const char *this_bin_addr(void) -{ - esp_partition_mmap_handle_t out_handle; - const void *binary_address; - const esp_partition_t *partition = esp_ota_get_running_partition(); - esp_partition_mmap(partition, 0, partition->size, ESP_PARTITION_MMAP_DATA, &binary_address, &out_handle); - return binary_address; -} - -TEST(mqtt5, enqueue_and_destroy_outbox) -{ - const char *bin_addr = this_bin_addr(); - // Reseting leak detection since this_bin_addr adds to allocated memory. - test_utils_record_free_mem(); - TEST_ESP_OK(test_utils_set_leak_level(0, ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_GENERAL)); - const int messages = 20; - const int size = 2000; - const esp_mqtt_client_config_t mqtt5_cfg = { - // no connection takes place, but the uri has to be valid for init() to succeed - .broker.address.uri = "mqtts://localhost:8883", - .session.protocol_ver = MQTT_PROTOCOL_V_5, - }; - esp_mqtt5_publish_property_config_t publish_property = { - .payload_format_indicator = 1, - .message_expiry_interval = 1000, - .topic_alias = 0, - .response_topic = "/topic/test/response", - .correlation_data = "123456", - .correlation_data_len = 6, - .content_type = "json", - }; - esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt5_cfg); - TEST_ASSERT_NOT_EQUAL(NULL, client ); - int bytes_before = esp_get_free_heap_size(); - for (int i = 0; i < messages; i ++) { - esp_mqtt5_client_set_user_property(&publish_property.user_property, user_property_arr, 3); - esp_mqtt5_client_set_publish_property(client, &publish_property); - esp_mqtt_client_publish(client, "test", bin_addr, size, 1, 0); - esp_mqtt5_client_delete_user_property(publish_property.user_property); - publish_property.user_property = NULL; - } - int bytes_after = esp_get_free_heap_size(); - // check that outbox allocated all messages on heap - TEST_ASSERT_GREATER_OR_EQUAL(messages * size, bytes_before - bytes_after); - - esp_mqtt_client_destroy(client); -} - -#if SOC_EMAC_SUPPORTED -/** - * This test cases uses ethernet kit, so build and use it only if EMAC supported - */ -TEST(mqtt5, broker_tests) -{ - test_case_uses_tcpip(); - connect_test_fixture_setup(); - - RUN_MQTT5_BROKER_TEST(mqtt5_connect_disconnect); - RUN_MQTT5_BROKER_TEST(mqtt5_subscribe_publish); - RUN_MQTT5_BROKER_TEST(mqtt5_lwt_clean_disconnect); - RUN_MQTT5_BROKER_TEST(mqtt5_subscribe_payload); - - connect_test_fixture_teardown(); -} -#endif // SOC_EMAC_SUPPORTED - -TEST_GROUP_RUNNER(mqtt5) -{ -#if !DISABLED_FOR_TARGETS(ESP32H2) - RUN_TEST_CASE(mqtt5, init_with_invalid_url); - RUN_TEST_CASE(mqtt5, init_and_deinit); - RUN_TEST_CASE(mqtt5, enqueue_and_destroy_outbox); - -#if SOC_EMAC_SUPPORTED - RUN_TEST_CASE(mqtt5, broker_tests); -#endif // SOC_EMAC_SUPPORTED -#endif //!DISABLED_FOR_TARGETS(ESP32H2) -} - - -void app_main(void) -{ - UNITY_MAIN(mqtt5); -} diff --git a/components/mqtt/test_apps/test_mqtt5/main/test_mqtt5_client_broker.c b/components/mqtt/test_apps/test_mqtt5/main/test_mqtt5_client_broker.c deleted file mode 100644 index 0ac4c3dd019..00000000000 --- a/components/mqtt/test_apps/test_mqtt5/main/test_mqtt5_client_broker.c +++ /dev/null @@ -1,285 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "freertos/FreeRTOS.h" -#include "freertos/event_groups.h" -#include "mqtt_client.h" -#include "esp_log.h" -#include "esp_mac.h" - -#define WAIT_FOR_EVENT(event) \ - TEST_ASSERT_TRUE(xEventGroupWaitBits(s_event_group, event, pdTRUE, pdTRUE, pdMS_TO_TICKS(COMMON_OPERATION_TIMEOUT)) & event); - -#define TEST_ASSERT_TRUE(condition) TEST_ASSERT_TRUE_LINE(condition, __LINE__) -#define TEST_ASSERT_TRUE_LINE(condition, line) \ - do { \ - if (!(condition)) { \ - ESP_LOGE("test_mqtt5_client_broker.c", \ - "Assertion failed in line %d", line); \ - return false; \ - } \ - } while(0) - - -static const int COMMON_OPERATION_TIMEOUT = 10000; -static const int CONNECT_BIT = BIT0; -static const int DISCONNECT_BIT = BIT1; -static const int DATA_BIT = BIT2; - -static EventGroupHandle_t s_event_group; - -static esp_mqtt5_user_property_item_t user_property_arr[3] = { - {"board", "esp32"}, - {"u", "user"}, - {"p", "password"} -}; - -static char* append_mac(const char* string) -{ - uint8_t mac[6]; - char *id_string = NULL; - esp_read_mac(mac, ESP_MAC_WIFI_STA); - asprintf(&id_string, "%s_%02x%02X%02X", string, mac[3], mac[4], mac[5]); - return id_string; -} - -static void mqtt5_data_handler_qos(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) -{ - if (event_id == MQTT_EVENT_DATA) { - esp_mqtt_event_handle_t event = event_data; - int * qos = handler_args; - *qos = event->qos; - xEventGroupSetBits(s_event_group, DATA_BIT); - } -} - -static void mqtt5_data_handler_lwt(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) -{ - if (event_id == MQTT_EVENT_DATA) { - esp_mqtt_event_handle_t event = event_data; - ESP_LOGI("mqtt-lwt", "MQTT_EVENT_DATA"); - ESP_LOGI("mqtt-lwt", "TOPIC=%.*s", event->topic_len, event->topic); - ESP_LOGI("mqtt-lwt", "DATA=%.*s", event->data_len, event->data); - if (strncmp(event->data, "no-lwt", event->data_len) == 0) { - // no lwt, just to indicate the test has finished - xEventGroupSetBits(s_event_group, DATA_BIT); - } else { - // count up any potential lwt message - int * count = handler_args; - *count = *count + 1; - ESP_LOGE("mqtt5-lwt", "count=%d", *count); - } - } -} - -static void mqtt5_data_handler_subscribe(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) -{ - if (event_id == MQTT_EVENT_SUBSCRIBED) { - esp_mqtt_event_handle_t event = event_data; - ESP_LOGI("mqtt5-subscribe", "MQTT_EVENT_SUBSCRIBED, data size=%d", event->data_len); - int * sub_payload = handler_args; - if (event->data_len == 1) { - ESP_LOGI("mqtt5-subscribe", "DATA=%d", *(uint8_t*)event->data); - *sub_payload = *(uint8_t*)event->data; - } - xEventGroupSetBits(s_event_group, DATA_BIT); - } -} - - -static void mqtt5_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) -{ - switch ((esp_mqtt_event_id_t)event_id) { - case MQTT_EVENT_CONNECTED: - xEventGroupSetBits(s_event_group, CONNECT_BIT); - break; - - case MQTT_EVENT_DISCONNECTED: - xEventGroupSetBits(s_event_group, DISCONNECT_BIT); - break; - default: - break; - } -} - -bool mqtt5_connect_disconnect(void) -{ - const esp_mqtt_client_config_t mqtt5_cfg = { - .broker.address.uri = CONFIG_MQTT5_TEST_BROKER_URI, - .network.disable_auto_reconnect = true, - .session.protocol_ver = MQTT_PROTOCOL_V_5, - }; - esp_mqtt5_connection_property_config_t connect_property = { - .session_expiry_interval = 10, - .maximum_packet_size = 1024, - .receive_maximum = 65535, - .topic_alias_maximum = 2, - .request_resp_info = true, - .request_problem_info = true, - }; - esp_mqtt5_disconnect_property_config_t disconnect_property = { - .session_expiry_interval = 10, - .disconnect_reason = 0, - }; - s_event_group = xEventGroupCreate(); - esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt5_cfg); - TEST_ASSERT_TRUE(NULL != client ); - esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt5_event_handler, NULL); - TEST_ASSERT_TRUE(ESP_OK == esp_mqtt5_client_set_user_property(&connect_property.user_property, user_property_arr, 3)); - TEST_ASSERT_TRUE(ESP_OK == esp_mqtt5_client_set_connect_property(client, &connect_property)); - esp_mqtt5_client_delete_user_property(connect_property.user_property); - TEST_ASSERT_TRUE(ESP_OK == esp_mqtt_client_start(client)); - WAIT_FOR_EVENT(CONNECT_BIT); - TEST_ASSERT_TRUE(ESP_OK == esp_mqtt5_client_set_user_property(&disconnect_property.user_property, user_property_arr, 3)); - TEST_ASSERT_TRUE(ESP_OK == esp_mqtt5_client_set_disconnect_property(client, &disconnect_property)); - esp_mqtt5_client_delete_user_property(disconnect_property.user_property); - esp_mqtt_client_disconnect(client); - WAIT_FOR_EVENT(DISCONNECT_BIT); - esp_mqtt_client_reconnect(client); - WAIT_FOR_EVENT(CONNECT_BIT); - esp_mqtt_client_destroy(client); - vEventGroupDelete(s_event_group); - return true; -} - -bool mqtt5_subscribe_publish(void) -{ - const esp_mqtt_client_config_t mqtt5_cfg = { - .broker.address.uri = CONFIG_MQTT5_TEST_BROKER_URI, - .session.protocol_ver = MQTT_PROTOCOL_V_5, - }; - esp_mqtt5_publish_property_config_t publish_property = { - .payload_format_indicator = 1, - .message_expiry_interval = 1000, - .topic_alias = 1, - .response_topic = "/topic/test/response", - .correlation_data = "123456", - .correlation_data_len = 6, - .content_type = "json", - }; - esp_mqtt5_subscribe_property_config_t subscribe_property = { - .subscribe_id = 25555, - .no_local_flag = false, - .retain_as_published_flag = true, - .retain_handle = 0, - }; - char* topic = append_mac("topic"); - TEST_ASSERT_TRUE(NULL != topic); - s_event_group = xEventGroupCreate(); - esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt5_cfg); - TEST_ASSERT_TRUE(NULL != client ); - esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt5_event_handler, NULL); - TEST_ASSERT_TRUE(ESP_OK == esp_mqtt_client_start(client)); - WAIT_FOR_EVENT(CONNECT_BIT); - int qos = -1; - esp_mqtt_client_register_event(client, MQTT_EVENT_DATA, mqtt5_data_handler_qos, &qos); - TEST_ASSERT_TRUE(ESP_OK == esp_mqtt5_client_set_subscribe_property(client, &subscribe_property)); - TEST_ASSERT_TRUE(esp_mqtt_client_subscribe(client, topic, 2) != -1); - TEST_ASSERT_TRUE(ESP_OK == esp_mqtt5_client_set_publish_property(client, &publish_property)); - TEST_ASSERT_TRUE(esp_mqtt_client_publish(client, topic, "message", 0, 2, 0) != -1); - WAIT_FOR_EVENT(DATA_BIT); - TEST_ASSERT_TRUE(qos == 2); - TEST_ASSERT_TRUE(esp_mqtt_client_publish(client, topic, "message", 0, 1, 0) != -1); - WAIT_FOR_EVENT(DATA_BIT); - TEST_ASSERT_TRUE(qos == 1); - esp_mqtt_client_destroy(client); - vEventGroupDelete(s_event_group); - free(topic); - return true; -} - -bool mqtt5_lwt_clean_disconnect(void) -{ - char* lwt = append_mac("lwt"); - TEST_ASSERT_TRUE(lwt); - const esp_mqtt_client_config_t mqtt5_cfg1 = { - .broker.address.uri = CONFIG_MQTT5_TEST_BROKER_URI, - .credentials.set_null_client_id = true, - .session.last_will.topic = lwt, - .session.last_will.msg = "lwt_msg", - .session.protocol_ver = MQTT_PROTOCOL_V_5, - }; - const esp_mqtt_client_config_t mqtt5_cfg2 = { - .broker.address.uri = CONFIG_MQTT5_TEST_BROKER_URI, - .credentials.set_null_client_id = true, - .session.last_will.topic = lwt, - .session.last_will.msg = "lwt_msg", - .session.protocol_ver = MQTT_PROTOCOL_V_5, - }; - esp_mqtt5_connection_property_config_t connect_property = { - .will_delay_interval = 10, - .payload_format_indicator = true, - .message_expiry_interval = 10, - .content_type = "json", - .response_topic = "/test/response", - .correlation_data = "123456", - .correlation_data_len = 6, - }; - s_event_group = xEventGroupCreate(); - - esp_mqtt_client_handle_t client1 = esp_mqtt_client_init(&mqtt5_cfg1); - esp_mqtt_client_handle_t client2 = esp_mqtt_client_init(&mqtt5_cfg2); - TEST_ASSERT_TRUE(NULL != client1 && NULL != client2 ); - esp_mqtt_client_register_event(client1, ESP_EVENT_ANY_ID, mqtt5_event_handler, NULL); - esp_mqtt_client_register_event(client2, ESP_EVENT_ANY_ID, mqtt5_event_handler, NULL); - TEST_ASSERT_TRUE(ESP_OK == esp_mqtt5_client_set_connect_property(client1, &connect_property)); - TEST_ASSERT_TRUE(ESP_OK == esp_mqtt5_client_set_connect_property(client2, &connect_property)); - TEST_ASSERT_TRUE(esp_mqtt_client_start(client1) == ESP_OK); - WAIT_FOR_EVENT(CONNECT_BIT); - TEST_ASSERT_TRUE(esp_mqtt_client_start(client2) == ESP_OK); - WAIT_FOR_EVENT(CONNECT_BIT); - int counter = 0; - esp_mqtt_client_register_event(client1, MQTT_EVENT_DATA, mqtt5_data_handler_lwt, &counter); - esp_mqtt_client_register_event(client2, MQTT_EVENT_DATA, mqtt5_data_handler_lwt, &counter); - TEST_ASSERT_TRUE(esp_mqtt_client_subscribe(client1, lwt, 0) != -1); - TEST_ASSERT_TRUE(esp_mqtt_client_subscribe(client2, lwt, 0) != -1); - esp_mqtt_client_disconnect(client1); - WAIT_FOR_EVENT(DISCONNECT_BIT); - esp_mqtt_client_reconnect(client1); - WAIT_FOR_EVENT(CONNECT_BIT); - TEST_ASSERT_TRUE(esp_mqtt_client_subscribe(client1, lwt, 0) != -1); - esp_mqtt_client_stop(client2); - esp_mqtt_client_start(client2); - WAIT_FOR_EVENT(CONNECT_BIT); - TEST_ASSERT_TRUE(esp_mqtt_client_subscribe(client2, lwt, 0) != -1); - TEST_ASSERT_TRUE(esp_mqtt_client_publish(client1, lwt, "no-lwt", 0, 0, 0) != -1); - WAIT_FOR_EVENT(DATA_BIT); - TEST_ASSERT_TRUE(counter == 0); - esp_mqtt_client_destroy(client1); - esp_mqtt_client_destroy(client2); - vEventGroupDelete(s_event_group); - free(lwt); - return true; -} - -bool mqtt5_subscribe_payload(void) -{ - const esp_mqtt_client_config_t mqtt5_cfg = { - .broker.address.uri = CONFIG_MQTT5_TEST_BROKER_URI, - .network.disable_auto_reconnect = true, - .session.protocol_ver = MQTT_PROTOCOL_V_5, - }; - char* topic = append_mac("topic"); - TEST_ASSERT_TRUE(NULL != topic); - s_event_group = xEventGroupCreate(); - esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt5_cfg); - TEST_ASSERT_TRUE(NULL != client ); - esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt5_event_handler, NULL); - TEST_ASSERT_TRUE(ESP_OK == esp_mqtt_client_start(client)); - WAIT_FOR_EVENT(CONNECT_BIT); - int qos_payload = -1; - esp_mqtt_client_register_event(client, MQTT_EVENT_SUBSCRIBED, mqtt5_data_handler_subscribe, &qos_payload); - TEST_ASSERT_TRUE(esp_mqtt_client_subscribe(client, topic, 2) != -1); - WAIT_FOR_EVENT(DATA_BIT); - TEST_ASSERT_TRUE(qos_payload == 2); - TEST_ASSERT_TRUE(esp_mqtt_client_subscribe(client, topic, 0) != -1); - WAIT_FOR_EVENT(DATA_BIT); - TEST_ASSERT_TRUE(qos_payload == 0); - esp_mqtt_client_destroy(client); - vEventGroupDelete(s_event_group); - free(topic); - return true; -} diff --git a/components/mqtt/test_apps/test_mqtt5/main/test_mqtt5_client_broker.h b/components/mqtt/test_apps/test_mqtt5/main/test_mqtt5_client_broker.h deleted file mode 100644 index a181dd8e068..00000000000 --- a/components/mqtt/test_apps/test_mqtt5/main/test_mqtt5_client_broker.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#pragma once -#include "esp_log.h" - -/** - * @brief MQTT5 client-broker tests are not implemented as separate test cases - * due to time consuming connection setup/teardown. - * This utility macro is used to run functional cases as MQTT tests - * and evaluate as separate assertions in one "mqtt5 broker tests" test case. - */ -#define RUN_MQTT5_BROKER_TEST(test_name) \ - do { \ - ESP_LOGI("mqtt5_test", "Running test:" #test_name "()"); \ - TEST_ASSERT_TRUE_MESSAGE(test_name(), "Mqtt5 test failed: " #test_name "() "); \ - ESP_LOGI("mqtt5_test", "Test:" #test_name "() passed "); \ - } while(0) - - -/** - * @brief This module contains mqtt5 test cases interacting the client with a (real) broker - */ - -/** - * @brief The client subscribes and publishes on the same topic - * and verifies the received published qos in the event - */ -bool mqtt5_subscribe_publish(void); - -/** - * @brief The client connects, disconnects and reconnects. - * Tests basic client state transitions - */ -bool mqtt5_connect_disconnect(void); - -/** - * @brief Two clients with defined lwt connect and subscribe to lwt topic. - * This test verifies that no lwt is send when each of the client disconnects. - * (we expect a clean disconnection, so no last-will being sent) - */ -bool mqtt5_lwt_clean_disconnect(void); - -/** - * @brief The client subscribes to a topic with certain qos - * and verifies the qos in SUBACK message from the broker. - */ -bool mqtt5_subscribe_payload(void); diff --git a/components/mqtt/test_apps/test_mqtt5/pytest_mqtt5_ut.py b/components/mqtt/test_apps/test_mqtt5/pytest_mqtt5_ut.py deleted file mode 100644 index 7e38dfac8d3..00000000000 --- a/components/mqtt/test_apps/test_mqtt5/pytest_mqtt5_ut.py +++ /dev/null @@ -1,11 +0,0 @@ -# SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD -# SPDX-License-Identifier: Unlicense OR CC0-1.0 -import pytest -from pytest_embedded import Dut -from pytest_embedded_idf.utils import idf_parametrize - - -@pytest.mark.ethernet -@idf_parametrize('target', ['esp32'], indirect=['target']) -def test_mqtt5_client(dut: Dut) -> None: - dut.expect_unity_test_output() diff --git a/components/mqtt/test_apps/test_mqtt5/sdkconfig.defaults b/components/mqtt/test_apps/test_mqtt5/sdkconfig.defaults deleted file mode 100644 index 06c58d7b6a5..00000000000 --- a/components/mqtt/test_apps/test_mqtt5/sdkconfig.defaults +++ /dev/null @@ -1,4 +0,0 @@ -# General options for additional checks -CONFIG_ESP_TASK_WDT_EN=n -CONFIG_MQTT_PROTOCOL_5=y -CONFIG_UNITY_ENABLE_FIXTURE=y diff --git a/docs/doxygen/Doxyfile b/docs/doxygen/Doxyfile index 885dbeb6aa2..0254f01537f 100644 --- a/docs/doxygen/Doxyfile +++ b/docs/doxygen/Doxyfile @@ -290,8 +290,6 @@ INPUT = \ $(PROJECT_PATH)/components/lwip/include/apps/ping/ping_sock.h \ $(PROJECT_PATH)/components/mbedtls/esp_crt_bundle/include/esp_crt_bundle.h \ $(PROJECT_PATH)/components/mbedtls/port/include/ecdsa/ecdsa_alt.h \ - $(PROJECT_PATH)/components/mqtt/esp-mqtt/include/mqtt_client.h \ - $(PROJECT_PATH)/components/mqtt/esp-mqtt/include/mqtt5_client.h \ $(PROJECT_PATH)/components/nvs_flash/include/nvs_flash.h \ $(PROJECT_PATH)/components/nvs_flash/include/nvs.h \ $(PROJECT_PATH)/components/nvs_flash/include/nvs_bootloader.h \ diff --git a/docs/en/COPYRIGHT.rst b/docs/en/COPYRIGHT.rst index 46187483a26..988a688fe4c 100644 --- a/docs/en/COPYRIGHT.rst +++ b/docs/en/COPYRIGHT.rst @@ -53,7 +53,6 @@ These third party libraries can be included into the application (firmware) prod * :component_file:`SD/MMC driver ` is derived from `OpenBSD SD/MMC driver`_, Copyright (C) 2006 Uwe Stuehler, and is licensed under BSD License. -* :component:`ESP-MQTT ` Package (contiki-mqtt), Copyright (C) 2014 Stephen Robinson, MQTT-ESP - Tuan PM is licensed under Apache License 2.0 as described in :component_file:`LICENSE file `. * :component:`BLE Mesh ` is adapted from Zephyr Project, Copyright (C) 2017-2018 Intel Corporation and licensed under Apache License 2.0. diff --git a/docs/en/api-guides/performance/ram-usage.rst b/docs/en/api-guides/performance/ram-usage.rst index 3020f250728..9773c06e582 100644 --- a/docs/en/api-guides/performance/ram-usage.rst +++ b/docs/en/api-guides/performance/ram-usage.rst @@ -132,7 +132,6 @@ The default stack sizes for these tasks are usually set conservatively high to a :SOC_BT_SUPPORTED: - :doc:`/api-reference/bluetooth/nimble/index` has task stack size :ref:`CONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE`. - The Ethernet driver creates a task for the MAC to receive Ethernet frames. If using the default config ``ETH_MAC_DEFAULT_CONFIG`` then the task stack size is 4 KB. This setting can be changed by passing a custom :cpp:class:`eth_mac_config_t` struct when initializing the Ethernet MAC. - FreeRTOS idle task stack size is configured by :ref:`CONFIG_FREERTOS_IDLE_TASK_STACKSIZE`. - - If using the :doc:`/api-reference/protocols/mqtt` component, it creates a task with stack size configured by :ref:`CONFIG_MQTT_TASK_STACK_SIZE`. MQTT stack size can also be configured using ``task_stack`` field of :cpp:class:`esp_mqtt_client_config_t`. - To see how to optimize RAM usage when using ``mDNS``, please check `Minimizing RAM Usage `__. .. note:: diff --git a/docs/en/api-guides/performance/speed.rst b/docs/en/api-guides/performance/speed.rst index 58e191a2004..07b21fce4a6 100644 --- a/docs/en/api-guides/performance/speed.rst +++ b/docs/en/api-guides/performance/speed.rst @@ -209,7 +209,6 @@ Common priorities are: :SOC_BT_SUPPORTED: - :doc:`/api-reference/bluetooth/controller_vhci` task has high priority (23, ``ESP_TASK_BT_CONTROLLER_PRIO``). The Bluetooth Controller needs to respond to requests with low latency, so it should always be among the highest priority task in the system. :SOC_BT_SUPPORTED: - :doc:`/api-reference/bluetooth/nimble/index` task has high priority (21). - The Ethernet driver creates a task for the MAC to receive Ethernet frames. If using the default config ``ETH_MAC_DEFAULT_CONFIG`` then the priority is medium-high (15). This setting can be changed by passing a custom :cpp:class:`eth_mac_config_t` struct when initializing the Ethernet MAC. - - If using the :doc:`/api-reference/protocols/mqtt` component, it creates a task with default priority 5 (:ref:`configurable`), depending on :ref:`CONFIG_MQTT_USE_CUSTOM_CONFIG`, and also configurable at runtime by ``task_prio`` field in the :cpp:class:`esp_mqtt_client_config_t`) - To see what is the task priority for ``mDNS`` service, please check `Performance Optimization `__. .. only:: SOC_HP_CPU_HAS_MULTIPLE_CORES @@ -233,7 +232,6 @@ Common priorities are: All Bluedroid Tasks are pinned to the same core, which is Core 0 by default (:ref:`configurable `). - The Ethernet driver creates a task for the MAC to receive Ethernet frames. If using the default config ``ETH_MAC_DEFAULT_CONFIG`` then the priority is medium-high (15) and the task is not pinned to any core. These settings can be changed by passing a custom :cpp:class:`eth_mac_config_t` struct when initializing the Ethernet MAC. - - If using the :doc:`/api-reference/protocols/mqtt` component, it creates a task with default priority 5 (:ref:`configurable `, depending on :ref:`CONFIG_MQTT_USE_CUSTOM_CONFIG`) and not pinned to any core (:ref:`configurable `). - To see what is the task priority for ``mDNS`` service, please check `Performance Optimization `__. diff --git a/docs/en/api-guides/unit-tests.rst b/docs/en/api-guides/unit-tests.rst index e8e9f6cb430..f04cc861d1d 100644 --- a/docs/en/api-guides/unit-tests.rst +++ b/docs/en/api-guides/unit-tests.rst @@ -349,7 +349,6 @@ Examples of component mocks can be found under :idf:`tools/mocks` in the IDF dir - :component_file:`unit test for the NVS Page class `. - :component_file:`unit test for esp_event `. -- :component_file:`unit test for mqtt `. .. _adjustments_for_mocks: diff --git a/docs/en/api-guides/wifi-expansion.rst b/docs/en/api-guides/wifi-expansion.rst index 5aa23c28f7c..8beb81bc22a 100644 --- a/docs/en/api-guides/wifi-expansion.rst +++ b/docs/en/api-guides/wifi-expansion.rst @@ -26,7 +26,9 @@ Please follow the instructions described in the component documentation which is .. only:: not SOC_WIFI_SUPPORTED - To explore the Wi-Fi Expansion functionality on {IDF_TARGET_NAME}, you can get started with this example: :idf_file:`examples/protocols/mqtt/tcp/README.md` and choose Wi-Fi connection in the project configuration menu. + To explore the Wi‑Fi Expansion functionality on {IDF_TARGET_NAME}, you can: + + - Start with the built‑in MQTT over TLS example ``examples/protocols/mqtt`` (or the MQTT 5.0 variant ``examples/protocols/mqtt5``) and choose Wi‑Fi connection in the project configuration menu; .. only:: SOC_WIRELESS_HOST_SUPPORTED diff --git a/docs/en/api-reference/peripherals/ds.rst b/docs/en/api-reference/peripherals/ds.rst index 4f027ff3d7a..7c3531833c1 100644 --- a/docs/en/api-reference/peripherals/ds.rst +++ b/docs/en/api-reference/peripherals/ds.rst @@ -66,7 +66,7 @@ As mentioned in the `ESP-TLS` documentation, the application only needs to provi Example for SSL Mutual Authentication Using DS ---------------------------------------------- -The example :example:`protocols/mqtt/ssl_ds` shows how to use the DS peripheral for mutual authentication. The example uses `mqtt_client` (Implemented through `ESP-MQTT`) to connect to broker ``test.mosquitto.org`` using SSL transport with mutual authentication. The SSL part is internally performed with `ESP-TLS`. See :example_file:`protocols/mqtt/ssl_ds/README.md` for more details. +The SSL mutual authentication example that previously lived under ``examples/protocols/mqtt/ssl_ds`` is now shipped with the standalone `espressif/mqtt `__ component. Follow the component documentation to fetch the SSL DS example and build it together with ESP-MQTT. The example continues to use `mqtt_client` (implemented by ESP-MQTT) to connect to ``test.mosquitto.org`` over mutual-authenticated TLS, with the TLS portion handled by `ESP-TLS`. API Reference ------------- diff --git a/docs/en/api-reference/protocols/esp_tls.rst b/docs/en/api-reference/protocols/esp_tls.rst index 4c55749b2c6..f69e1fc58bb 100644 --- a/docs/en/api-reference/protocols/esp_tls.rst +++ b/docs/en/api-reference/protocols/esp_tls.rst @@ -229,7 +229,7 @@ To enable the secure element support, and use it in your project for TLS connect When using Digital Signature for the TLS connection, along with the other required params, only the client certification (`clientcert_buf`) and the DS params (`ds_data`) are required and the client key (`clientkey_buf`) can be set to NULL. - * An example of mutual authentication with the DS peripheral can be found at :example:`ssl mutual auth` which internally uses (ESP-TLS) for the TLS connection. + * A mutual-authentication example that utilizes the DS peripheral is shipped with the standalone `espressif/mqtt `__ component and internally relies on ESP-TLS for the TLS connection. Follow the component documentation to fetch and build that example. .. only:: SOC_ECDSA_SUPPORTED diff --git a/docs/en/api-reference/protocols/mqtt.rst b/docs/en/api-reference/protocols/mqtt.rst index cde304e3400..9bd2b45fbdc 100644 --- a/docs/en/api-reference/protocols/mqtt.rst +++ b/docs/en/api-reference/protocols/mqtt.rst @@ -8,201 +8,31 @@ Overview ESP-MQTT is an implementation of `MQTT `__ protocol client, which is a lightweight publish/subscribe messaging protocol. Now ESP-MQTT supports `MQTT v5.0 `__. +The ESP-IDF component ``ESP-MQTT`` has been moved from ESP-IDF since version v6.0 to a separate repository: -Features --------- +* `esp-mqtt component on GitHub `__ - * Support MQTT over TCP, SSL with Mbed TLS, MQTT over WebSocket, and MQTT over WebSocket Secure - * Easy to setup with URI - * Multiple instances (multiple clients in one application) - * Support subscribing, publishing, authentication, last will messages, keep alive pings, and all 3 Quality of Service (QoS) levels (it should be a fully functional client) +To add ESP-MQTT component in your project, please run ``idf.py add-dependency espressif/mqtt``. +Hosted Documentation +--------------------- + +The documentation can be found on the link below: + +* `esp-mqtt documentation `__ Application Examples -------------------- - - :example:`protocols/mqtt/tcp` demonstrates how to implement MQTT communication over TCP (default port 1883). +Two reference examples are available in ESP-IDF: - - :example:`protocols/mqtt/ssl` demonstrates how to use SSL transport to implement MQTT communication over TLS (default port 8883). +- MQTT over TLS (certificate bundle): ``examples/protocols/mqtt`` + - Validates the broker with ESP-IDF's certificate bundle (default). + - Default broker URI targets ``mqtts://test.mosquitto.org:8886`` (Let's Encrypt chain). + - Alternative configuration pins Mosquitto CA and uses ``mqtts://test.mosquitto.org:8883``. - - :example:`protocols/mqtt/ssl_ds` demonstrates how to use digital signature peripheral for authentication to implement MQTT communication over TLS (default port 8883). +- MQTT 5.0 over TLS (certificate bundle): ``examples/protocols/mqtt5`` + - Uses MQTT v5.0 with TLS and validation via the certificate bundle. + - Default broker URI targets ``mqtts://test.mosquitto.org:8886``. - - :example:`protocols/mqtt/ssl_mutual_auth` demonstrates how to use certificates for authentication to implement MQTT communication (default port 8883). - - - :example:`protocols/mqtt/ssl_psk` demonstrates how to use pre-shared keys for authentication to implement MQTT communication over TLS (default port 8883). - - - :example:`protocols/mqtt/ws` demonstrates how to implement MQTT communication over WebSocket (default port 80). - - - :example:`protocols/mqtt/wss` demonstrates how to implement MQTT communication over WebSocket Secure (default port 443). - - - :example:`protocols/mqtt5` demonstrates how to use ESP-MQTT library to connect to broker with MQTT v5.0. - - - :example:`protocols/mqtt/custom_outbox` demonstrates how to customize the outbox in the ESP-MQTT library. - -MQTT Message Retransmission ---------------------------- - -A new MQTT message can be created by calling :cpp:func:`esp_mqtt_client_publish ` or its non-blocking counterpart :cpp:func:`esp_mqtt_client_enqueue `. - -Messages with QoS 0 are sent only once. QoS 1 and 2 behave differently since the protocol requires additional steps to complete the process. - -The ESP-MQTT library opts to always retransmit unacknowledged QoS 1 and 2 publish messages to prevent data loss in faulty connections, even though the MQTT specification requires the re-transmission only on reconnect with Clean Session flag been set to 0 (set :cpp:member:`disable_clean_session ` to true for this behavior). - -QoS 1 and 2 messages that may need retransmission are always enqueued, but first transmission try occurs immediately if :cpp:func:`esp_mqtt_client_publish ` is used. A transmission retry for unacknowledged messages will occur after :cpp:member:`message_retransmit_timeout `. After :ref:`CONFIG_MQTT_OUTBOX_EXPIRED_TIMEOUT_MS` messages will expire and be deleted. If :ref:`CONFIG_MQTT_REPORT_DELETED_MESSAGES` is set, an event will be sent to notify the user. - -Configuration -------------- - -The configuration is made by setting fields in :cpp:class:`esp_mqtt_client_config_t` struct. The configuration struct has the following sub structs to configure different aspects of the client operation. - - * :cpp:class:`esp_mqtt_client_config_t::broker_t` - Allow to set address and security verification. - * :cpp:class:`esp_mqtt_client_config_t::credentials_t` - Client credentials for authentication. - * :cpp:class:`esp_mqtt_client_config_t::session_t` - Configuration for MQTT session aspects. - * :cpp:class:`esp_mqtt_client_config_t::network_t` - Networking related configuration. - * :cpp:class:`esp_mqtt_client_config_t::task_t` - Allow to configure FreeRTOS task. - * :cpp:class:`esp_mqtt_client_config_t::buffer_t` - Buffer size for input and output. - -In the following sections, the most common aspects are detailed. - -Broker -^^^^^^^^^^^ - -=========== -Address -=========== - -Broker address can be set by usage of :cpp:class:`address ` struct. The configuration can be made by usage of :cpp:member:`uri ` field or the combination of :cpp:member:`hostname `, :cpp:member:`transport ` and :cpp:member:`port `. Optionally, :cpp:member:`path ` could be set, this field is useful in WebSocket connections. - -The :cpp:member:`uri ` field is used in the format ``scheme://hostname:port/path``. - -- Currently support ``mqtt``, ``mqtts``, ``ws``, ``wss`` schemes -- MQTT over TCP samples: - - - ``mqtt://mqtt.eclipseprojects.io``: MQTT over TCP, default port 1883 - - ``mqtt://mqtt.eclipseprojects.io:1884``: MQTT over TCP, port 1884 - - ``mqtt://username:password@mqtt.eclipseprojects.io:1884``: MQTT over TCP, - port 1884, with username and password - -- MQTT over SSL samples: - - - ``mqtts://mqtt.eclipseprojects.io``: MQTT over SSL, port 8883 - - ``mqtts://mqtt.eclipseprojects.io:8884``: MQTT over SSL, port 8884 - -- MQTT over WebSocket samples: - - - ``ws://mqtt.eclipseprojects.io:80/mqtt`` - -- MQTT over WebSocket Secure samples: - - - ``wss://mqtt.eclipseprojects.io:443/mqtt`` - -- Minimal configurations: - -.. code-block:: c - - const esp_mqtt_client_config_t mqtt_cfg = { - .broker.address.uri = "mqtt://mqtt.eclipseprojects.io", - }; - esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg); - esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, client); - esp_mqtt_client_start(client); - -.. note:: - - By default MQTT client uses event loop library to post related MQTT events (connected, subscribed, published, etc.). - -============ -Verification -============ - -For secure connections with TLS used, and to guarantee Broker's identity, the :cpp:class:`verification ` struct must be set. -The broker certificate may be set in PEM or DER format. To select DER, the equivalent :cpp:member:`certificate_len ` field must be set. Otherwise, a null-terminated string in PEM format should be provided to :cpp:member:`certificate ` field. - -- Get certificate from server, example: ``mqtt.eclipseprojects.io`` - .. code:: - - openssl s_client -showcerts -connect mqtt.eclipseprojects.io:8883 < /dev/null \ - 2> /dev/null | openssl x509 -outform PEM > mqtt_eclipse_org.pem - -- Check the sample application: :example:`protocols/mqtt/ssl` -- Configuration: - -.. code:: c - - const esp_mqtt_client_config_t mqtt_cfg = { - .broker = { - .address.uri = "mqtts://mqtt.eclipseprojects.io:8883", - .verification.certificate = (const char *)mqtt_eclipse_org_pem_start, - }, - }; - -For details about other fields, please check the `API Reference`_ and :ref:`esp_tls_server_verification`. - -Client Credentials -^^^^^^^^^^^^^^^^^^ - -All client related credentials are under the :cpp:class:`credentials ` field. - - * :cpp:member:`username `: pointer to the username used for connecting to the broker, can also be set by URI - * :cpp:member:`client_id `: pointer to the client ID, defaults to ``ESP32_%CHIPID%`` where ``%CHIPID%`` are the last 3 bytes of MAC address in hex format - -============== -Authentication -============== - -It is possible to set authentication parameters through the :cpp:class:`authentication ` field. The client supports the following authentication methods: - - * :cpp:member:`password `: use a password by setting - * :cpp:member:`certificate ` and :cpp:member:`key `: mutual authentication with TLS, and both can be provided in PEM or DER format - * :cpp:member:`use_secure_element `: use secure element (ATECC608A) interfaced to ESP32 series - * :cpp:member:`ds_data `: use Digital Signature Peripheral available in some Espressif devices - -Session -^^^^^^^^^^^ - -For MQTT session-related configurations, :cpp:class:`session ` fields should be used. - -======================= -Last Will and Testament -======================= - -MQTT allows for a last will and testament (LWT) message to notify other clients when a client ungracefully disconnects. This is configured by the following fields in the :cpp:class:`last_will ` struct. - - * :cpp:member:`topic `: pointer to the LWT message topic - * :cpp:member:`msg `: pointer to the LWT message - * :cpp:member:`msg_len `: length of the LWT message, required if :cpp:member:`msg ` is not null-terminated - * :cpp:member:`qos `: quality of service for the LWT message - * :cpp:member:`retain `: specifies the retain flag of the LWT message - -Change Settings in Project Configuration Menu -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The settings for MQTT can be found using :code:`idf.py menuconfig`, under ``Component config`` > ``ESP-MQTT Configuration``. - -The following settings are available: - -- :ref:`CONFIG_MQTT_PROTOCOL_311`: enable 3.1.1 version of MQTT protocol - -- :ref:`CONFIG_MQTT_TRANSPORT_SSL` and :ref:`CONFIG_MQTT_TRANSPORT_WEBSOCKET`: enable specific MQTT transport layer, such as SSL, WEBSOCKET, and WEBSOCKET_SECURE - -- :ref:`CONFIG_MQTT_CUSTOM_OUTBOX`: disable default implementation of mqtt_outbox, so a specific implementation can be supplied - - -Events ------- -The following events may be posted by the MQTT client: - -* ``MQTT_EVENT_BEFORE_CONNECT``: The client is initialized and about to start connecting to the broker. -* ``MQTT_EVENT_CONNECTED``: The client has successfully established a connection to the broker. The client is now ready to send and receive data. -* ``MQTT_EVENT_DISCONNECTED``: The client has aborted the connection due to being unable to read or write data, e.g., because the server is unavailable. -* ``MQTT_EVENT_SUBSCRIBED``: The broker has acknowledged the client's subscribe request. The event data contains the message ID of the subscribe message. -* ``MQTT_EVENT_UNSUBSCRIBED``: The broker has acknowledged the client's unsubscribe request. The event data contains the message ID of the unsubscribe message. -* ``MQTT_EVENT_PUBLISHED``: The broker has acknowledged the client's publish message. This is only posted for QoS level 1 and 2, as level 0 does not use acknowledgements. The event data contains the message ID of the publish message. -* ``MQTT_EVENT_DATA``: The client has received a publish message. The event data contains: message ID, name of the topic it was published to, received data and its length. For data that exceeds the internal buffer, multiple ``MQTT_EVENT_DATA`` events are posted and :cpp:member:`current_data_offset ` and :cpp:member:`total_data_len ` from event data updated to keep track of the fragmented message. -* ``MQTT_EVENT_ERROR``: The client has encountered an error. The field :cpp:type:`error_handle ` in the event data contains :cpp:type:`error_type ` that can be used to identify the error. The type of error determines which parts of the :cpp:type:`error_handle ` struct is filled. - -API Reference -------------- - -.. include-build-file:: inc/mqtt_client.inc -.. include-build-file:: inc/mqtt5_client.inc +For additional transport modes (TCP, WS/WSS, mutual auth, etc.), see the examples in the `espressif/mqtt component repository `__. diff --git a/docs/en/migration-guides/release-6.x/6.0/protocols.rst b/docs/en/migration-guides/release-6.x/6.0/protocols.rst index cc7641e6e52..98e874aef43 100644 --- a/docs/en/migration-guides/release-6.x/6.0/protocols.rst +++ b/docs/en/migration-guides/release-6.x/6.0/protocols.rst @@ -105,3 +105,19 @@ Discussions ~~~~~~~~~~~ * `Discussions for version v2 `__ + +ESP-MQTT +-------- + +Breaking change: ESP-MQTT moved to a managed component and example set updated. + +- The ESP-MQTT component has been removed from ESP-IDF and is now a managed component: ``espressif/mqtt``. + - To add the component to an application, run ``idf.py add-dependency espressif/mqtt``. + - Include headers and APIs remain the same (``mqtt_client.h``), but the component is fetched via the Component Manager. + +- Example changes in ESP-IDF: + - Legacy MQTT TLS examples under ``examples/protocols/mqtt/ssl*`` were removed. + - New reference examples are available: + + - ``examples/protocols/mqtt``: MQTT over TLS. + - ``examples/protocols/mqtt5``: MQTT v5.0 over TLS. diff --git a/docs/sphinx-known-warnings.txt b/docs/sphinx-known-warnings.txt index b5669ed51dd..69b18c02485 100644 --- a/docs/sphinx-known-warnings.txt +++ b/docs/sphinx-known-warnings.txt @@ -7,6 +7,7 @@ # Warnings in this file must be in the same overall order as the log file. # esp_ble_mesh_defs.inc:line: WARNING: Invalid C++ declaration: Expected identifier in nested name. [error at 0] + ^ esp_ble_mesh_defs.inc:line: WARNING: Error in declarator or parameters-and-qualifiers @@ -305,19 +306,5 @@ If declarator-id: struct twai_error_flags_t -------------------------^ -mqtt_client.inc:line: WARNING: Duplicate C++ declaration, also defined at api-reference/protocols/mqtt:line. -Declaration is '.. cpp:type:: struct esp_mqtt_event_t esp_mqtt_event_t'. -mqtt_client.inc:line: WARNING: Duplicate C++ declaration, also defined at api-reference/protocols/mqtt:line. -Declaration is '.. cpp:type:: struct esp_mqtt_client_config_t esp_mqtt_client_config_t'. -mqtt_client.inc:line: WARNING: Duplicate C++ declaration, also defined at api-reference/protocols/mqtt:line. -Declaration is '.. cpp:enum:: esp_mqtt_event_id_t'. -mqtt_client.inc:line: WARNING: Duplicate C++ declaration, also defined at api-reference/protocols/mqtt:line. -Declaration is '.. cpp:enum:: esp_mqtt_connect_return_code_t'. -mqtt_client.inc:line: WARNING: Duplicate C++ declaration, also defined at api-reference/protocols/mqtt:line. -Declaration is '.. cpp:enum:: esp_mqtt_error_type_t'. -mqtt_client.inc:line: WARNING: Duplicate C++ declaration, also defined at api-reference/protocols/mqtt:line. -Declaration is '.. cpp:enum:: esp_mqtt_transport_t'. -mqtt_client.inc:line: WARNING: Duplicate C++ declaration, also defined at api-reference/protocols/mqtt:line. -Declaration is '.. cpp:enum:: esp_mqtt_protocol_ver_t'. esp_heap_trace.inc:line: WARNING: Duplicate C++ declaration, also defined at api-reference/system/heap_debug:line. Declaration is '.. cpp:type:: struct heap_trace_record_t heap_trace_record_t'. diff --git a/docs/zh_CN/COPYRIGHT.rst b/docs/zh_CN/COPYRIGHT.rst index 5c300ec0c65..30ea8fe7edf 100644 --- a/docs/zh_CN/COPYRIGHT.rst +++ b/docs/zh_CN/COPYRIGHT.rst @@ -53,7 +53,7 @@ * :component_file:`SD/MMC 驱动程序 ` 派生自 `OpenBSD SD/MMC 驱动程序`_,版权归 2006 Uwe Stuehler 所有,并根据 BSD 许可证进行许可。 -* :component:`ESP-MQTT ` 包 (contiki-mqtt),版权归 2014 Stephen Robinson 和 MQTT-ESP - Tuan PM 所有,根据 :component_file:`LICENSE 文件 ` 中描述的 Apache License 2.0 进行许可。 + * :component:`BLE Mesh ` 改编自 Zephyr 项目,版权归 2017-2018 英特尔公司所有,并根据 Apache License 2.0 进行许可。 @@ -161,7 +161,7 @@ TJpgDec - Tiny JPEG 解压器 R0.01 (C) 2011 ChaN,是一个用于小型嵌入 .. _protobuf-c: https://github.com/protobuf-c/protobuf-c .. _Unity: https://github.com/ThrowTheSwitch/Unity .. _asio: https://github.com/chriskohlhoff/asio -.. _mqtt: https://github.com/espressif/esp-mqtt + .. _zephyr: https://github.com/zephyrproject-rtos/zephyr .. _mynewt-nimble: https://github.com/apache/mynewt-nimble .. _ESP-IDF 编程指南: https://docs.espressif.com/projects/esp-idf/zh_CN/latest/ diff --git a/docs/zh_CN/api-guides/performance/ram-usage.rst b/docs/zh_CN/api-guides/performance/ram-usage.rst index d58bd9ebe85..72239a0cd36 100644 --- a/docs/zh_CN/api-guides/performance/ram-usage.rst +++ b/docs/zh_CN/api-guides/performance/ram-usage.rst @@ -132,7 +132,6 @@ ESP-IDF 包含一系列堆 API,可以在运行时测量空闲堆内存,请 :SOC_BT_SUPPORTED: - :doc:`/api-reference/bluetooth/nimble/index` 的栈内存大小为 :ref:`CONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE`。 - 以太网驱动程序会创建任务,用于使 MAC 接收以太网帧,在默认配置 ``ETH_MAC_DEFAULT_CONFIG`` 下,任务栈内存大小为 4 KB。在初始化以太网 MAC 时,传递自定义 :cpp:class:`eth_mac_config_t` 结构体可以更改此设置。 - FreeRTOS 空闲任务栈内存大小由 :ref:`CONFIG_FREERTOS_IDLE_TASK_STACKSIZE` 配置。 - - 使用 :doc:`/api-reference/protocols/mqtt` 组件时会创建一个任务,其栈内存大小由 :ref:`CONFIG_MQTT_TASK_STACK_SIZE` 配置。MQTT 栈内存大小也可以使用 :cpp:class:`esp_mqtt_client_config_t` 结构体中的 ``task_stack`` 字段配置。 - 有关使用 ``mDNS`` 时内存优化的详细信息,请参阅 `优化内存使用 `__。 .. note:: diff --git a/docs/zh_CN/api-guides/performance/speed.rst b/docs/zh_CN/api-guides/performance/speed.rst index f4b5343f50d..0f9f49d126a 100644 --- a/docs/zh_CN/api-guides/performance/speed.rst +++ b/docs/zh_CN/api-guides/performance/speed.rst @@ -209,7 +209,6 @@ ESP-IDF 启动的系统任务预设了固定优先级。启动时,一些任务 :SOC_BT_SUPPORTED: - :doc:`/api-reference/bluetooth/controller_vhci` 任务优先级较高 (23, ``ESP_TASK_BT_CONTROLLER_PRIO``)。蓝牙控制器需要以低延迟响应请求,因此其任务应始终为系统最高优先级的任务之一。 :SOC_BT_SUPPORTED: - :doc:`/api-reference/bluetooth/nimble/index` 任务优先级较高 (21). - 以太网驱动程序会创建一个 MAC 任务,用于接收以太网帧。如果使用默认配置 ``ETH_MAC_DEFAULT_CONFIG`` ,则该任务为中高优先级 (15)。可以在以太网 MAC 初始化时输入自定义 :cpp:class:`eth_mac_config_t` 结构体来更改此设置。 - - 如果使用 :doc:`/api-reference/protocols/mqtt` 组件,它会创建优先级默认为 5 的任务( :ref:`可配置 ` ),可通过 :ref:`CONFIG_MQTT_USE_CUSTOM_CONFIG` 调整,也可以在运行时通过 :cpp:class:`esp_mqtt_client_config_t` 结构体中的 ``task_prio`` 字段调整。 - 关于 ``mDNS`` 服务的任务优先级,参见 `性能优化 `__ 。 .. only:: SOC_HP_CPU_HAS_MULTIPLE_CORES @@ -233,7 +232,6 @@ ESP-IDF 启动的系统任务预设了固定优先级。启动时,一些任务 所有 Bluedroid 任务默认固定在同一个核心上执行,即核 0( :ref:`可配置 ` )。 - 以太网驱动程序会创建一个 MAC 任务,用于接收以太网帧。如果使用默认配置 ``ETH_MAC_DEFAULT_CONFIG`` ,则该任务为中高优先级 (15) 且并未固定在特定内核上执行。可以在以太网 MAC 初始化时输入自定义 :cpp:class:`eth_mac_config_t` 结构体来更改此设置。 - - 如果使用 :doc:`/api-reference/protocols/mqtt` 组件,它会创建优先级默认为 5 的任务( :ref:`可配置 ` ,也可通过 :ref:`CONFIG_MQTT_USE_CUSTOM_CONFIG` 调整)。该任务未固定在特定内核上执行( :ref:`可配置 ` )。 - 关于 ``mDNS`` 服务的任务优先级,参见 `性能优化 `__ 。 diff --git a/docs/zh_CN/api-guides/unit-tests.rst b/docs/zh_CN/api-guides/unit-tests.rst index 87f8c4bc4f2..51f9b6e332d 100644 --- a/docs/zh_CN/api-guides/unit-tests.rst +++ b/docs/zh_CN/api-guides/unit-tests.rst @@ -349,7 +349,6 @@ Mocks - :component_file:`NVS 页面类的单元测试 `。 - :component_file:`esp_event 的单元测试 `。 -- :component_file:`mqtt 的单元测试 `。 .. _adjustments_for_mocks: diff --git a/docs/zh_CN/api-reference/peripherals/ds.rst b/docs/zh_CN/api-reference/peripherals/ds.rst index 3b147c213e8..e9d23ce0b73 100644 --- a/docs/zh_CN/api-reference/peripherals/ds.rst +++ b/docs/zh_CN/api-reference/peripherals/ds.rst @@ -66,7 +66,7 @@ TLS 连接所需的 DS 外设配置 使用 DS 外设进行 SSL 双向认证 ----------------------------- -示例 :example:`protocols/mqtt/ssl_ds` 展示了如何使用 DS 外设进行 SSL 双向认证。在示例中,使用了 `mqtt_client` (通过 `ESP-MQTT` 实现),通过 SSL 传输连接到代理服务器 ``test.mosquitto.org``,并进行 SSL 双向认证。SSL 部分在内部使用 `ESP-TLS` 完成。更多细节,请参阅 :example_file:`protocols/mqtt/ssl_ds/README.md`。 +此前位于 ``examples/protocols/mqtt/ssl_ds`` 的 SSL 双向认证示例现已随独立的 `espressif/mqtt `__ 组件一同提供。请按照该组件文档说明获取 SSL DS 示例并与 ESP-MQTT 一起构建。示例继续使用通过 `ESP-MQTT` 实现的 `mqtt_client` 连接到 ``test.mosquitto.org``,并使用 `ESP-TLS` 完成 TLS 双向认证。 API 参考 -------- diff --git a/docs/zh_CN/api-reference/protocols/esp_tls.rst b/docs/zh_CN/api-reference/protocols/esp_tls.rst index 2f73174fc65..5faee5a8c7f 100644 --- a/docs/zh_CN/api-reference/protocols/esp_tls.rst +++ b/docs/zh_CN/api-reference/protocols/esp_tls.rst @@ -229,7 +229,7 @@ ESP-TLS 支持在 ESP32 系列芯片上使用 ATECC608A 加密芯片,但必须 当使用数字签名进行 TLS 连接时,除其他必要参数外,仅需提供客户端证书 (``clientcert_buf``) 和数字签名参数 (``ds_data``) ,此时可将客户端密钥 (``clientkey_buf``) 设置为 NULL。 - * 使用数字签名外设进行双向认证的示例请参阅 :example:`SSL 双向认证 `,该示例使用 ESP-TLS 实现 TLS 连接。 + * 使用数字签名外设进行双向认证的示例现随独立的 `espressif/mqtt `__ 组件一同提供,并在内部通过 ESP-TLS 建立 TLS 连接。请按照该组件文档说明获取并构建该示例。 .. only:: SOC_ECDSA_SUPPORTED diff --git a/docs/zh_CN/api-reference/protocols/mqtt.rst b/docs/zh_CN/api-reference/protocols/mqtt.rst index 27d36416ba5..e4eb58bcf51 100644 --- a/docs/zh_CN/api-reference/protocols/mqtt.rst +++ b/docs/zh_CN/api-reference/protocols/mqtt.rst @@ -6,203 +6,34 @@ ESP-MQTT 概述 -------- -ESP-MQTT 是 `MQTT `__ 协议客户端的实现,MQTT 是一种基于发布/订阅模式的轻量级消息传输协议。ESP-MQTT 当前支持 `MQTT v5.0 `__。 +ESP‑MQTT 是 `MQTT `__ 协议客户端的实现,属于轻量级发布/订阅消息协议。ESP‑MQTT 现已支持 `MQTT v5.0 `__。 +自 ESP‑IDF v6.0 起,``ESP‑MQTT`` 组件已从 ESP‑IDF 中移至独立仓库: -特性 --------- +* `esp-mqtt 组件仓库 `__ - * 支持基于 TCP 的 MQTT、基于 Mbed TLS 的 SSL、基于 WebSocket 的 MQTT 以及基于 WebSocket Secure 的 MQTT - * 通过 URI 简化配置流程 - * 多个实例(一个应用程序中有多个客户端) - * 支持订阅、发布、认证、遗嘱消息、保持连接心跳机制以及 3 个服务质量 (QoS) 级别(组成全功能客户端) +如需在项目中添加 ESP‑MQTT 组件,请运行 ``idf.py add-dependency espressif/mqtt``。 +托管文档 +--------------------- + +文档链接如下: + +* `esp-mqtt 文档 `__ 应用示例 -------------------- +-------------------- - - :example:`protocols/mqtt/tcp` 演示了如何通过 TCP 实现 MQTT 通信(默认端口 1883)。 +ESP‑IDF 中提供了两个参考示例: - - :example:`protocols/mqtt/ssl` 演示了如何使用 SSL 传输来实现基于 TLS 的 MQTT 通信(默认端口 8883)。 +- 基于 TLS(证书包)的 MQTT 示例:``examples/protocols/mqtt`` + - 默认使用 ESP‑IDF 证书包进行服务器验证。 + - 默认 Broker URI 为 ``mqtts://test.mosquitto.org:8886`` (Let's Encrypt 链)。 + - 也可固定 Mosquitto CA,并使用 ``mqtts://test.mosquitto.org:8883``。 - - :example:`protocols/mqtt/ssl_ds` 演示了如何使用数字签名外设进行身份验证,以实现基于 TLS 的 MQTT 通信(默认端口 8883)。 +- 基于 TLS(证书包)的 MQTT 5.0 示例:``examples/protocols/mqtt5`` + - 使用 MQTT v5.0 与 TLS,并通过证书包进行验证。 + - 默认 Broker URI 为 ``mqtts://test.mosquitto.org:8886``。 - - :example:`protocols/mqtt/ssl_mutual_auth` 演示了如何使用证书进行身份验证实现 MQTT 通信(默认端口 8883)。 +如需更多传输模式(TCP、WS/WSS、双向认证等)的示例,请参考 `espressif/mqtt 组件仓库 `__。 - - :example:`protocols/mqtt/ssl_psk` 演示了如何使用预共享密钥进行身份验证,以实现基于 TLS 的 MQTT 通信(默认端口 8883)。 - - - :example:`protocols/mqtt/ws` 演示了如何通过 WebSocket 实现 MQTT 通信(默认端口 80)。 - - - :example:`protocols/mqtt/wss` 演示了如何通过 WebSocket Secure 实现 MQTT 通信(默认端口 443)。 - - - :example:`protocols/mqtt5` 演示了如何使用 ESP-MQTT 库通过 MQTT v5.0 连接到代理。 - - - :example:`protocols/mqtt/custom_outbox` 演示了如何自定义 ESP-MQTT 库中的 outbox。 - -MQTT 消息重传 --------------------------- - -调用 :cpp:func:`esp_mqtt_client_publish ` 或其非阻塞形式 :cpp:func:`esp_mqtt_client_enqueue `,可以创建新的 MQTT 消息。 - -QoS 0 的消息将只发送一次,QoS 1 和 2 具有不同行为,因为协议需要执行额外步骤来完成该过程。 - -ESP-MQTT 库将始终重新传输未确认的 QoS 1 和 2 发布消息,以避免连接错误导致信息丢失,虽然 MQTT 规范要求仅在重新连接且 Clean Session 标志设置为 0 时重新传输(针对此行为,将 :cpp:member:`disable_clean_session ` 设置为 true)。 - -可能需要重传的 QoS 1 和 2 消息总是处于排队状态,但若使用 :cpp:func:`esp_mqtt_client_publish ` 则会立即进行第一次传输尝试。未确认消息的重传将在 :cpp:member:`message_retransmit_timeout ` 之后进行。在 :ref:`CONFIG_MQTT_OUTBOX_EXPIRED_TIMEOUT_MS` 之后,消息会过期并被删除。如已设置 :ref:`CONFIG_MQTT_REPORT_DELETED_MESSAGES`,则会发送事件来通知用户。 - -配置 -------------- - -通过设置 :cpp:class:`esp_mqtt_client_config_t` 结构体中的字段来进行配置。配置结构体包含以下子结构体,用于配置客户端的多种操作。 - - * :cpp:class:`esp_mqtt_client_config_t::broker_t` - 允许设置地址和安全验证。 - * :cpp:class:`esp_mqtt_client_config_t::credentials_t` - 用于身份验证的客户端凭据。 - * :cpp:class:`esp_mqtt_client_config_t::session_t` - MQTT 会话相关配置。 - * :cpp:class:`esp_mqtt_client_config_t::network_t` - 网络相关配置。 - * :cpp:class:`esp_mqtt_client_config_t::task_t` - 允许配置 FreeRTOS 任务。 - * :cpp:class:`esp_mqtt_client_config_t::buffer_t` - 输入输出的缓冲区大小。 - -下文将详细介绍不同配置。 - -服务器 -^^^^^^^^^^^^ - -=========== -地址 -=========== - -通过 :cpp:class:`address ` 结构体的 :cpp:member:`uri ` 字段或者 :cpp:member:`hostname `、:cpp:member:`transport ` 以及 :cpp:member:`port ` 的组合,可以设置服务器地址。也可以选择设置 :cpp:member:`path `,该字段对 WebSocket 连接而言非常有用。 - -使用 :cpp:member:`uri ` 字段的格式为 ``scheme://hostname:port/path``。 - -- 当前支持 ``mqtt``、``mqtts``、``ws`` 和 ``wss`` 协议 -- 基于 TCP 的 MQTT 示例: - - - ``mqtt://mqtt.eclipseprojects.io``:基于 TCP 的 MQTT,默认端口 1883 - - ``mqtt://mqtt.eclipseprojects.io:1884``:基于 TCP 的 MQTT,端口 1884 - - ``mqtt://username:password@mqtt.eclipseprojects.io:1884``:基于 TCP 的 MQTT, - 端口 1884,带有用户名和密码 - -- 基于 SSL 的 MQTT 示例: - - - ``mqtts://mqtt.eclipseprojects.io``:基于 SSL 的 MQTT,端口 8883 - - ``mqtts://mqtt.eclipseprojects.io:8884``:基于 SSL 的 MQTT,端口 8884 - -- 基于 WebSocket 的 MQTT 示例: - - - ``ws://mqtt.eclipseprojects.io:80/mqtt`` - -- 基于 WebSocket Secure 的 MQTT 示例: - - - ``wss://mqtt.eclipseprojects.io:443/mqtt`` - -- 最简配置: - -.. code-block:: c - - const esp_mqtt_client_config_t mqtt_cfg = { - .broker.address.uri = "mqtt://mqtt.eclipseprojects.io", - }; - esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg); - esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, client); - esp_mqtt_client_start(client); - -.. note:: - - 默认情况下,MQTT 客户端使用事件循环库来发布相关 MQTT 事件(已连接、已订阅、已发布等)。 - -============= -验证 -============= - -为验证服务器身份,对于使用 TLS 的安全链接,必须设置 :cpp:class:`verification ` 结构体。 -服务器证书可设置为 PEM 或 DER 格式。如要选择 DER 格式,必须设置等效 :cpp:member:`certificate_len ` 字段,否则应在 :cpp:member:`certificate ` 字段传入以空字符结尾的 PEM 格式字符串。 - -- 从服务器获取证书,例如:``mqtt.eclipseprojects.io`` - .. code:: - - openssl s_client -showcerts -connect mqtt.eclipseprojects.io:8883 < /dev/null \ - 2> /dev/null | openssl x509 -outform PEM > mqtt_eclipse_org.pem - -- 检查示例应用程序::example:`protocols/mqtt/ssl` -- 配置: - -.. code:: c - - const esp_mqtt_client_config_t mqtt_cfg = { - .broker = { - .address.uri = "mqtts://mqtt.eclipseprojects.io:8883", - .verification.certificate = (const char *)mqtt_eclipse_org_pem_start, - }, - }; - -了解其他字段的详细信息,请查看 `API 参考`_ 以及 :ref:`esp_tls_server_verification`。 - -客户端凭据 -^^^^^^^^^^^^^^^^^^^^^^^^ - -:cpp:class:`credentials ` 字段下包含所有客户端相关凭据。 - - * :cpp:member:`username `:指向用于连接服务器用户名的指针,也可通过 URI 设置 - * :cpp:member:`client_id `:指向客户端 ID 的指针,默认为 ``ESP32_%CHIPID%``,其中 ``%CHIPID%`` 是十六进制 MAC 地址的最后 3 个字节 - -=============== -认证 -=============== - -可以通过 :cpp:class:`authentication ` 字段设置认证参数。客户端支持以下认证方式: - - * :cpp:member:`password `:使用密码 - * * :cpp:member:`certificate ` 和 :cpp:member:`key `:进行双向 TLS 身份验证,PEM 或 DER 格式均可 - * :cpp:member:`use_secure_element `:使用 ESP32 系列中的安全元素 (ATECC608A) - * :cpp:member:`ds_data `:使用某些乐鑫设备的数字签名外设 - -会话 -^^^^^^^^^^^^ - -使用 :cpp:class:`session ` 字段进行 MQTT 会话相关配置。 - -======================== -遗嘱消息 (LWT) -======================== - -通过设置 :cpp:class:`last_will ` 结构体的以下字段,MQTT 会在一个客户端意外断开连接时通过遗嘱消息通知其他客户端。 - - * :cpp:member:`topic `:指向 LWT 消息主题的指针 - * :cpp:member:`msg `:指向 LWT 消息的指针 - * :cpp:member:`msg_len `:LWT 消息的长度,:cpp:member:`msg ` 不以空字符结尾时需要该字段 - * :cpp:member:`qos `:LWT 消息的服务质量 - * :cpp:member:`retain `:指定 LWT 消息的保留标志 - -在项目配置菜单中设置 MQTT -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -通过 :code:`idf.py menuconfig`,可以在 ``Component config`` > ``ESP-MQTT Configuration`` 中找到 MQTT 设置。 - -相关设置如下: - -- :ref:`CONFIG_MQTT_PROTOCOL_311`:启用 MQTT 协议 3.1.1 版本 - -- :ref:`CONFIG_MQTT_TRANSPORT_SSL` 和 :ref:`CONFIG_MQTT_TRANSPORT_WEBSOCKET`:启用特定 MQTT 传输层,例如 SSL、WEBSOCKET 和 WEBSOCKET_SECURE - -- :ref:`CONFIG_MQTT_CUSTOM_OUTBOX`:禁用 mqtt_outbox 默认实现,因此可以提供特定实现 - - -事件 ------------- -MQTT 客户端可能会发布以下事件: - -* ``MQTT_EVENT_BEFORE_CONNECT``:客户端已初始化并即将开始连接至服务器。 -* ``MQTT_EVENT_CONNECTED``:客户端已成功连接至服务器。客户端已准备好收发数据。 -* ``MQTT_EVENT_DISCONNECTED``:由于无法读取或写入数据,例如因为服务器无法使用,客户端已终止连接。 -* ``MQTT_EVENT_SUBSCRIBED``:服务器已确认客户端的订阅请求。事件数据将包含订阅消息的消息 ID。 -* ``MQTT_EVENT_UNSUBSCRIBED``:服务器已确认客户端的退订请求。事件数据将包含退订消息的消息 ID。 -* ``MQTT_EVENT_PUBLISHED``:服务器已确认客户端的发布消息。消息将仅针对 QoS 级别 1 和 2 发布,因为级别 0 不会进行确认。事件数据将包含发布消息的消息 ID。 -* ``MQTT_EVENT_DATA``:客户端已收到发布消息。事件数据包含:消息 ID、发布消息所属主题名称、收到的数据及其长度。对于超出内部缓冲区的数据,将发布多个 ``MQTT_EVENT_DATA``,并更新事件数据的 :cpp:member:`current_data_offset ` 和 :cpp:member:`total_data_len` 以跟踪碎片化消息。 -* ``MQTT_EVENT_ERROR``:客户端遇到错误。使用事件数据 :cpp:type:`error_handle ` 字段中的 :cpp:type:`error_type `,可以发现错误。错误类型决定 :cpp:type:`error_handle ` 结构体的哪些部分会被填充。 - -API 参考 -------------- - -.. include-build-file:: inc/mqtt_client.inc -.. include-build-file:: inc/mqtt5_client.inc diff --git a/docs/zh_CN/migration-guides/release-6.x/6.0/protocols.rst b/docs/zh_CN/migration-guides/release-6.x/6.0/protocols.rst index ff42031df5c..7e06d4412bb 100644 --- a/docs/zh_CN/migration-guides/release-6.x/6.0/protocols.rst +++ b/docs/zh_CN/migration-guides/release-6.x/6.0/protocols.rst @@ -105,3 +105,19 @@ ESP-Modbus ~~~~ * `v2 版本讨论 `__ + +ESP-MQTT +-------- + +重大变更:ESP-MQTT 迁移为托管组件,并更新了示例集。 + +- ESP-MQTT 组件已从 ESP-IDF 中移除,现在作为托管组件 ``espressif/mqtt`` 提供。 + - 在应用中添加该组件,请运行 ``idf.py add-dependency espressif/mqtt``。 + - 头文件与 API(``mqtt_client.h``)保持一致,但组件通过 Component Manager 获取。 + +- ESP-IDF 中的示例变更: + - 移除了 ``examples/protocols/mqtt/ssl*`` 下的旧版 MQTT TLS 示例。 + - 新增参考示例: + + - ``examples/protocols/mqtt``:基于 TLS 的 MQTT。 + - ``examples/protocols/mqtt5``:基于 TLS 的 MQTT v5.0。 diff --git a/examples/mesh/ip_internal_network/main/idf_component.yml b/examples/mesh/ip_internal_network/main/idf_component.yml new file mode 100644 index 00000000000..30d9122e5d9 --- /dev/null +++ b/examples/mesh/ip_internal_network/main/idf_component.yml @@ -0,0 +1,2 @@ +dependencies: + espressif/mqtt: "^1.0.0" diff --git a/examples/protocols/.build-test-rules.yml b/examples/protocols/.build-test-rules.yml index efa086a46f8..3b4f1b4388e 100644 --- a/examples/protocols/.build-test-rules.yml +++ b/examples/protocols/.build-test-rules.yml @@ -14,13 +14,6 @@ temporary: true reason: not supported yet # TODO: [ESP32H21] IDF-11581 [ESP32H4] IDF-12360 -.mqtt_dependencies: &mqtt_dependencies - <<: *default_rules - depends_filepatterns: - - components/mqtt/**/* - depends_components+: - - mqtt - examples/protocols/dns_over_https: <<: *default_rules examples/protocols/esp_http_client: @@ -162,61 +155,21 @@ examples/protocols/l2tap: - if: IDF_TARGET != "esp32" reason: only test on esp32 -examples/protocols/mqtt/custom_outbox: - <<: *mqtt_dependencies - -examples/protocols/mqtt/ssl: - <<: *mqtt_dependencies +examples/protocols/mqtt: + <<: *default_rules disable_test: - if: IDF_TARGET != "esp32" - reason: only test on esp32 - -examples/protocols/mqtt/ssl_ds: - <<: *mqtt_dependencies - disable+: - - if: SOC_DIG_SIGN_SUPPORTED != 1 - temporary: false - reason: DS not present - depends_filepatterns+: - - examples/protocols/mqtt/ssl_ds/**/* - -examples/protocols/mqtt/ssl_mutual_auth: - <<: *mqtt_dependencies - -examples/protocols/mqtt/ssl_psk: - <<: *mqtt_dependencies -examples/protocols/mqtt/tcp: - <<: *mqtt_dependencies - disable_test: - - if: IDF_TARGET != "esp32" - reason: only test on esp32 - depends_filepatterns+: - - examples/protocols/mqtt/tcp/**/* - -examples/protocols/mqtt/ws: - <<: *mqtt_dependencies - disable_test: - - if: IDF_TARGET != "esp32" - reason: only test on esp32 - depends_filepatterns+: - - examples/protocols/mqtt/ws/**/* - -examples/protocols/mqtt/wss: - <<: *mqtt_dependencies - disable_test: - - if: IDF_TARGET != "esp32" - reason: only test on esp32 - depends_filepatterns+: - - examples/protocols/mqtt/wss/**/* - + reason: only test on esp32 for now + depends_components+: + - esp-tls examples/protocols/mqtt5: - <<: *mqtt_dependencies + <<: *default_rules disable_test: - if: IDF_TARGET != "esp32" - reason: only test on esp32 - depends_filepatterns+: - - examples/protocols/mqtt5/**/* + reason: only test on esp32 for now + depends_components+: + - esp-tls examples/protocols/smtp_client: <<: *default_rules diff --git a/examples/protocols/mqtt/tcp/CMakeLists.txt b/examples/protocols/mqtt/CMakeLists.txt similarity index 73% rename from examples/protocols/mqtt/tcp/CMakeLists.txt rename to examples/protocols/mqtt/CMakeLists.txt index 573e5a9f884..5e53bad667f 100644 --- a/examples/protocols/mqtt/tcp/CMakeLists.txt +++ b/examples/protocols/mqtt/CMakeLists.txt @@ -1,4 +1,4 @@ -# The following four lines of boilerplate have to be in your project's CMakeLists +# The following lines of boilerplate have to be in your project's CMakeLists # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.22) @@ -6,4 +6,4 @@ cmake_minimum_required(VERSION 3.22) include($ENV{IDF_PATH}/tools/cmake/project.cmake) # "Trim" the build. Include the minimal set of components, main, and anything it depends on. idf_build_set_property(MINIMAL_BUILD ON) -project(mqtt_tcp) +project(mqtt_ssl) diff --git a/examples/protocols/mqtt/ssl/README.md b/examples/protocols/mqtt/README.md similarity index 59% rename from examples/protocols/mqtt/ssl/README.md rename to examples/protocols/mqtt/README.md index 0407edad92a..033a00ac4ad 100644 --- a/examples/protocols/mqtt/ssl/README.md +++ b/examples/protocols/mqtt/README.md @@ -5,12 +5,26 @@ (See the README.md file in the upper level 'examples' directory for more information about examples.) -This example connects to the broker mqtt.eclipseprojects.io using ssl transport and as a demonstration subscribes/unsubscribes and send a message on certain topic. -(Please note that the public broker is maintained by the community so may not be always available, for details please see this [disclaimer](https://iot.eclipse.org/getting-started/#sandboxes)) +This example shows how to use the external ESP-MQTT client (managed component `espressif/mqtt`) from an ESP-IDF project. It connects to an MQTT broker over TLS and demonstrates basic operations: connect, subscribe, publish, receive data, and unsubscribe. You can switch between MQTT 3.1.1 and MQTT 5.0 via menuconfig. -It uses ESP-MQTT library which implements mqtt client to connect to mqtt broker. +This example connects to the broker test.mosquitto.org (Please note that the public broker is maintained by the community so may not be always available) -## How to use example +Two TLS validation configurations are available: +- Certificate bundle (default): Uses ESP‑IDF's certificate bundle and targets `test.mosquitto.org:8886` (Let's Encrypt chain). +- Embedded Mosquitto CA: Pins `mosquitto.org.crt` to validate `test.mosquitto.org:8883` (mirrors the legacy SSL example). + +## Features + +- Uses the managed component `espressif/mqtt` (fetched via IDF Component Manager) +- TLS connection with server verification using the certificate bundle +- Basic operations: subscribe, publish (QoS0, QoS1), receive data, unsubscribe + +- Important: Changing the certificate validation method does not automatically update the Broker URI in menuconfig. Make sure the port matches your selection: + - Bundle: use `mqtts://test.mosquitto.org:8886` + - Mosquitto CA: use `mqtts://test.mosquitto.org:8883` +- Certificate bundle mode uses `esp_crt_bundle_attach` and targets port `8886`. +- Mosquitto CA mode embeds and pins `mosquitto.org.crt` and targets port `8883`. +- The managed component dependency is declared in `main/idf_component.yml` and will be downloaded automatically. ### Hardware Required @@ -21,15 +35,6 @@ This example can be executed on any ESP32 board, the only required interface is * Open the project configuration menu (`idf.py menuconfig`) * Configure Wi-Fi or Ethernet under "Example Connection Configuration" menu. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more details. -PEM certificate for this example could be extracted from an openssl `s_client` command connecting to mqtt.eclipseprojects.io. -In case a host operating system has `openssl` and `sed` packages installed, one could execute the following command to download and save the root certificate to a file (Note for Windows users: Both Linux like environment or Windows native packages may be used). -``` -echo "" | openssl s_client -showcerts -connect mqtt.eclipseprojects.io:8883 | sed -n "1,/Root/d; /BEGIN/,/END/p" | openssl x509 -outform PEM >mqtt_eclipse_org.pem -``` -Please note that this is not a general command for downloading a root certificate for an arbitrary host; -this command works with mqtt.eclipseprojects.io as the site provides root certificate in the chain, which then could be extracted -with text operation. - ### Build and Flash Build the project and flash it to the board, then run monitor tool to view serial output: diff --git a/examples/protocols/mqtt/custom_outbox/CMakeLists.txt b/examples/protocols/mqtt/custom_outbox/CMakeLists.txt deleted file mode 100644 index 5048b1ee742..00000000000 --- a/examples/protocols/mqtt/custom_outbox/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ -# The following four lines of boilerplate have to be in your project's CMakeLists -# in this exact order for cmake to work correctly -cmake_minimum_required(VERSION 3.22) - -include($ENV{IDF_PATH}/tools/cmake/project.cmake) -# "Trim" the build. Include the minimal set of components, main, and anything it depends on. -idf_build_set_property(MINIMAL_BUILD ON) -project(mqtt_tcp_custom_outbox) - -# Add custom outbox implementation to mqtt component -idf_component_get_property(mqtt mqtt COMPONENT_LIB) -target_sources(${mqtt} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/main/custom_outbox.cpp) - -# Our C++ needs an extra dependency to mqtt component, so we add it to mqtt component. -# This is needed because we are adding another source to the mqtt component and the build -# system needs to be aware of it to be able to compile and link the mqtt component. -# First we get our dependency -idf_component_get_property(pthread pthread COMPONENT_LIB) -# And them we link the components -target_link_libraries(${mqtt} ${pthread}) diff --git a/examples/protocols/mqtt/custom_outbox/README.md b/examples/protocols/mqtt/custom_outbox/README.md deleted file mode 100644 index 5b64bcdba9d..00000000000 --- a/examples/protocols/mqtt/custom_outbox/README.md +++ /dev/null @@ -1,100 +0,0 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | - -# ESP-MQTT custom outbox sample application -(See the README.md file in the upper level 'examples' directory for more information about examples.) - -This example is a slightly modified version of the tcp example to show how to configure a custom outbox. -This example connects to the broker URI selected using `idf.py menuconfig` (using mqtt tcp transport) and as a demonstration subscribes/unsubscribes and send a message on certain topic. -(Please note that the public broker is maintained by the community so may not be always available, for details please see this [disclaimer](https://iot.eclipse.org/getting-started/#sandboxes)) - -Note: If the URI equals `FROM_STDIN` then the broker address is read from stdin upon application startup (used for testing) - -It uses ESP-MQTT library which implements mqtt client to connect to mqtt broker. - -## Necessary changes to customize the outbox - -To customize the outbox the first step is to enable it in the menuconfig option. - -With this option enabled, the default implementation isn't defined and the function definition needs to be added to mqtt component. -Any extra dependencies needed by the new sources also need to be added to the mqtt component. Refer to the example CMakeLists.txt file -for the details on how to do it. - -## The custom outbox in the example - -For the sake of this example the customized outbox implements the same functionalits of the regular but using C++ as a language. - -The implementation uses [C++ Polymorphic memory resources]() to control memory allocations and limit the usage of the memory. - -## How to use example - -### Hardware Required - -This example can be executed on any ESP32 board, the only required interface is WiFi and connection to internet. - -### Configure the project - -* Open the project configuration menu (`idf.py menuconfig`) -* Configure Wi-Fi or Ethernet under "Example Connection Configuration" menu. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more details. - -Note that the mandatory configurations for this example, mqtt custom outbox and C++ exceptions are automatically added by the `sdkconfig.defaults` file. -### Build and Flash - -Build the project and flash it to the board, then run monitor tool to view serial output: - -``` -idf.py -p PORT flash monitor -``` - -(To exit the serial monitor, type ``Ctrl-]``.) - -See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects. - -## Example Output - -``` -I (4635) example_common: Connected to example_netif_sta -I (4645) example_common: - IPv4 address: 192.168.33.206, -I (4645) example_common: - IPv6 address: fe80:0000:0000:0000:7e9e:bdff:fecf:00c0, type: ESP_IP6_ADDR_IS_LINK_LOCAL -I (4655) Monotonic: Monotonic: 400 bytes allocated, 400 total bytes in use -I (4665) Monotonic: Monotonic: 1000 bytes allocated, 1400 total bytes in use -I (4675) Monotonic: Monotonic: 128 bytes allocated, 1528 total bytes in use -I (4685) Pool: Pool: 32 bytes allocated, 32 total bytes in use -I (4685) Monotonic: Monotonic: 7688 bytes allocated, 9216 total bytes in use -I (4695) Monotonic: Monotonic: 128 bytes allocated, 9344 total bytes in use -I (4705) Pool: Pool: 480 bytes allocated, 512 total bytes in use -I (4715) Monotonic: Monotonic: 992 bytes allocated, 10336 total bytes in use -I (4715) Monotonic: Monotonic: 128 bytes allocated, 10464 total bytes in use -I (4725) Pool: Pool: 23 bytes allocated, 535 total bytes in use -I (4735) MQTT_EXAMPLE: Enqueued msg_id=14345 -I (4735) Pool: Pool: 29 bytes allocated, 564 total bytes in use -I (4745) MQTT_EXAMPLE: Enqueued msg_id=3507 -I (4745) MQTT_EXAMPLE: Other event id:7 -I (4755) main_task: Returned from app_main() -I (5085) MQTT_EXAMPLE: MQTT_EVENT_CONNECTED -I (5085) Pool: Pool: 23 bytes allocated, 587 total bytes in use -I (5085) MQTT_EXAMPLE: sent publish successful, msg_id=47425 -I (5085) Pool: Pool: 18 bytes allocated, 605 total bytes in use -I (5095) MQTT_EXAMPLE: sent subscribe successful, msg_id=60709 -I (5105) Pool: Pool: 18 bytes allocated, 623 total bytes in use -I (5105) MQTT_EXAMPLE: sent subscribe successful, msg_id=33273 -I (5395) Pool: Pool: 23 bytes deallocated, 623 total bytes in use -I (5395) MQTT_EXAMPLE: MQTT_EVENT_PUBLISHED, msg_id=47425 -I (6005) Pool: Pool: 18 bytes deallocated, 623 total bytes in use -I (6005) MQTT_EXAMPLE: MQTT_EVENT_SUBSCRIBED, msg_id=60709 -I (6005) MQTT_EXAMPLE: sent publish successful, msg_id=0 -I (6015) Pool: Pool: 18 bytes deallocated, 623 total bytes in use -I (6015) MQTT_EXAMPLE: MQTT_EVENT_SUBSCRIBED, msg_id=33273 -I (6025) MQTT_EXAMPLE: sent publish successful, msg_id=0 -I (6035) MQTT_EXAMPLE: MQTT_EVENT_DATA -TOPIC=/topic/qos1 -DATA=data_3 -I (6315) MQTT_EXAMPLE: MQTT_EVENT_DATA -TOPIC=/topic/qos1 -DATA=data_3 -I (6315) Pool: Pool: 23 bytes deallocated, 623 total bytes in use -I (6315) MQTT_EXAMPLE: MQTT_EVENT_PUBLISHED, msg_id=14345 -I (6615) MQTT_EXAMPLE: MQTT_EVENT_DATA -TOPIC=/topic/qos0 -DATA=data -``` diff --git a/examples/protocols/mqtt/custom_outbox/main/CMakeLists.txt b/examples/protocols/mqtt/custom_outbox/main/CMakeLists.txt deleted file mode 100644 index 7423b6078fb..00000000000 --- a/examples/protocols/mqtt/custom_outbox/main/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -idf_component_register(SRCS "app_main.c" - INCLUDE_DIRS "." - PRIV_REQUIRES mqtt nvs_flash esp_netif - ) diff --git a/examples/protocols/mqtt/custom_outbox/main/Kconfig.projbuild b/examples/protocols/mqtt/custom_outbox/main/Kconfig.projbuild deleted file mode 100644 index c11539fb8d2..00000000000 --- a/examples/protocols/mqtt/custom_outbox/main/Kconfig.projbuild +++ /dev/null @@ -1,13 +0,0 @@ -menu "Example Configuration" - - config BROKER_URL - string "Broker URL" - default "mqtt://mqtt.eclipseprojects.io" - help - URL of the broker to connect to - - config BROKER_URL_FROM_STDIN - bool - default y if BROKER_URL = "FROM_STDIN" - -endmenu diff --git a/examples/protocols/mqtt/custom_outbox/main/app_main.c b/examples/protocols/mqtt/custom_outbox/main/app_main.c deleted file mode 100644 index b30bc46aa4b..00000000000 --- a/examples/protocols/mqtt/custom_outbox/main/app_main.c +++ /dev/null @@ -1,173 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Unlicense OR CC0-1.0 - */ -/* MQTT (over TCP) Example with custom outbox - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ - -#include -#include -#include -#include -#include "esp_system.h" -#include "nvs_flash.h" -#include "esp_event.h" -#include "esp_netif.h" -#include "protocol_examples_common.h" - -#include "esp_log.h" -#include "mqtt_client.h" - -static const char *TAG = "MQTT_EXAMPLE"; - - -static void log_error_if_nonzero(const char *message, int error_code) -{ - if (error_code != 0) { - ESP_LOGE(TAG, "Last error %s: 0x%x", message, error_code); - } -} - -/* - * @brief Event handler registered to receive MQTT events - * - * This function is called by the MQTT client event loop. - * - * @param handler_args user data registered to the event. - * @param base Event base for the handler(always MQTT Base in this example). - * @param event_id The id for the received event. - * @param event_data The data for the event, esp_mqtt_event_handle_t. - */ -static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) -{ - ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%" PRIi32 "", base, event_id); - esp_mqtt_event_handle_t event = event_data; - esp_mqtt_client_handle_t client = event->client; - int msg_id; - switch ((esp_mqtt_event_id_t)event_id) { - case MQTT_EVENT_CONNECTED: - ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED"); - msg_id = esp_mqtt_client_publish(client, "/topic/qos1", "data_3", 0, 1, 0); - ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id); - - msg_id = esp_mqtt_client_subscribe(client, "/topic/qos0", 0); - ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id); - - msg_id = esp_mqtt_client_subscribe(client, "/topic/qos1", 1); - ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id); - - break; - case MQTT_EVENT_DISCONNECTED: - ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED"); - break; - - case MQTT_EVENT_SUBSCRIBED: - ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id); - msg_id = esp_mqtt_client_publish(client, "/topic/qos0", "data", 0, 0, 0); - ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id); - break; - case MQTT_EVENT_UNSUBSCRIBED: - ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id); - break; - case MQTT_EVENT_PUBLISHED: - ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id); - break; - case MQTT_EVENT_DATA: - ESP_LOGI(TAG, "MQTT_EVENT_DATA"); - printf("TOPIC=%.*s\r\n", event->topic_len, event->topic); - printf("DATA=%.*s\r\n", event->data_len, event->data); - break; - case MQTT_EVENT_ERROR: - ESP_LOGI(TAG, "MQTT_EVENT_ERROR"); - if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) { - log_error_if_nonzero("reported from esp-tls", event->error_handle->esp_tls_last_esp_err); - log_error_if_nonzero("reported from tls stack", event->error_handle->esp_tls_stack_err); - log_error_if_nonzero("captured as transport's socket errno", event->error_handle->esp_transport_sock_errno); - ESP_LOGI(TAG, "Last errno string (%s)", strerror(event->error_handle->esp_transport_sock_errno)); - - } - break; - default: - ESP_LOGI(TAG, "Other event id:%d", event->event_id); - break; - } -} - -static void mqtt_app_start(void) -{ - esp_mqtt_client_config_t mqtt_cfg = { - .broker.address.uri = CONFIG_BROKER_URL, - }; -#if CONFIG_BROKER_URL_FROM_STDIN - char line[128]; - - if (strcmp(mqtt_cfg.broker.address.uri, "FROM_STDIN") == 0) { - int count = 0; - printf("Please enter url of mqtt broker\n"); - while (count < 128) { - int c = fgetc(stdin); - if (c == '\n') { - line[count] = '\0'; - break; - } else if (c > 0 && c < 127) { - line[count] = c; - ++count; - } - vTaskDelay(10 / portTICK_PERIOD_MS); - } - mqtt_cfg.broker.address.uri = line; - printf("Broker url: %s\n", line); - } else { - ESP_LOGE(TAG, "Configuration mismatch: wrong broker url"); - abort(); - } -#endif /* CONFIG_BROKER_URL_FROM_STDIN */ - - esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg); - /* The last argument may be used to pass data to the event handler, in this example mqtt_event_handler */ - esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL); - - /*Let's enqueue a few messages to the outbox to see the allocations*/ - int msg_id; - msg_id = esp_mqtt_client_enqueue(client, "/topic/qos1", "data_3", 0, 1, 0, true); - ESP_LOGI(TAG, "Enqueued msg_id=%d", msg_id); - msg_id = esp_mqtt_client_enqueue(client, "/topic/qos2", "QoS2 message", 0, 2, 0, true); - ESP_LOGI(TAG, "Enqueued msg_id=%d", msg_id); - - /* Now we start the client and it's possible to see the memory usage for the operations in the outbox. */ - esp_mqtt_client_start(client); -} - -void app_main(void) -{ - ESP_LOGI(TAG, "[APP] Startup.."); - ESP_LOGI(TAG, "[APP] Free memory: %" PRIu32 " bytes", esp_get_free_heap_size()); - ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version()); - - esp_log_level_set("*", ESP_LOG_INFO); - esp_log_level_set("mqtt_client", ESP_LOG_VERBOSE); - esp_log_level_set("MQTT_EXAMPLE", ESP_LOG_VERBOSE); - esp_log_level_set("TRANSPORT_BASE", ESP_LOG_VERBOSE); - esp_log_level_set("esp-tls", ESP_LOG_VERBOSE); - esp_log_level_set("TRANSPORT", ESP_LOG_VERBOSE); - esp_log_level_set("custom_outbox", ESP_LOG_VERBOSE); - - ESP_ERROR_CHECK(nvs_flash_init()); - ESP_ERROR_CHECK(esp_netif_init()); - ESP_ERROR_CHECK(esp_event_loop_create_default()); - - /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. - * Read "Establishing Wi-Fi or Ethernet Connection" section in - * examples/protocols/README.md for more information about this function. - */ - ESP_ERROR_CHECK(example_connect()); - - mqtt_app_start(); -} diff --git a/examples/protocols/mqtt/custom_outbox/main/custom_outbox.cpp b/examples/protocols/mqtt/custom_outbox/main/custom_outbox.cpp deleted file mode 100644 index 2db9d7e49da..00000000000 --- a/examples/protocols/mqtt/custom_outbox/main/custom_outbox.cpp +++ /dev/null @@ -1,393 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Unlicense OR CC0-1.0 - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "esp_log.h" -#include "mqtt_outbox.h" - -constexpr auto TAG = "custom_outbox"; - -/* - * The trace resource class is created here as an example on how to build a custom memory resource - * The class is only needed to show where we are allocating from and to track allocations and deallocations. - */ -class trace_resource : public std::pmr::memory_resource { -public: - explicit trace_resource(std::string resource_name, std::pmr::memory_resource *upstream_resource = std::pmr::get_default_resource()) : upstream{upstream_resource}, name{std::move(resource_name)} {} - [[nodiscard]] std::string_view get_name() const noexcept - { - return std::string_view(name); - } - [[nodiscard]] auto upstream_resource() const - { - return upstream; - } -private: - void *do_allocate(std::size_t bytes, std::size_t alignment) override - { - auto *allocated = upstream->allocate(bytes, alignment); - allocated_total += bytes; - ESP_LOGI(name.c_str(), "%s: %zu bytes allocated, %zu total bytes in use", name.c_str(), bytes, allocated_total); - return allocated; - } - void do_deallocate(void *ptr, std::size_t bytes, std::size_t alignment) override - { - upstream->deallocate(ptr, bytes, alignment); - ESP_LOGI(name.c_str(), "%s: %zu bytes deallocated, %zu total bytes in use", name.c_str(), bytes, allocated_total); - } - - [[nodiscard]] bool do_is_equal(const std::pmr::memory_resource &other) const noexcept override - { - return this == &other; - } - size_t allocated_total{}; - std::pmr::memory_resource *upstream; - std::string name; -}; - -struct outbox_item { - /* Defining the allocator_type to let compiler know that our type is allocator aware, - * This way the allocator used for the outbox is propagated to the messages*/ - using allocator_type = std::pmr::polymorphic_allocator<>; - - /* Few strong types to diferetiate parameters*/ - enum class id_t : int {}; - enum class type_t : int {}; - enum class qos_t : int {}; - - /* Allocator aware constructors */ - outbox_item( - std::pmr::vector message, - id_t msg_id, - type_t msg_type, - qos_t msg_qos, - outbox_tick_t tick, - pending_state_t pending_state, - allocator_type alloc = {} - ) : message(std::move(message), alloc), id(msg_id), type(msg_type), qos(msg_qos), tick(tick), pending_state(pending_state) {} - - /*Copy and move constructors have an extra allocator parameter, for copy default and allocator aware are the same.*/ - outbox_item(const outbox_item &other, allocator_type alloc = {}) : message(other.message, alloc), id(other.id), type(other.type), qos(other.qos), tick(other.tick), pending_state(other.pending_state) {} - outbox_item(outbox_item &&other, allocator_type alloc) noexcept : message(std::move(other.message), alloc), id(other.id), type(other.type), qos(other.qos), tick(other.tick), pending_state(other.pending_state) - {} - - outbox_item(const outbox_item &) = default; - outbox_item(outbox_item &&other) = default; - outbox_item &operator=(const outbox_item &rhs) = default; - outbox_item &operator=(outbox_item &&other) = default; - ~outbox_item() = default; - - /* Getters to support outbox operation */ - [[nodiscard]] auto state() const noexcept - { - return pending_state; - } - - [[nodiscard]] allocator_type get_allocator() const - { - return message.get_allocator(); - } - - void set(pending_state state) noexcept - { - pending_state = state; - } - - void set(outbox_tick_t n_tick) noexcept - { - tick = n_tick; - } - - [[nodiscard]] auto get_id() const noexcept - { - return id; - } - - [[nodiscard]] auto get_type() const noexcept - { - return type; - } - - [[nodiscard]] auto get_tick() const noexcept - { - return tick; - } - - [[nodiscard]] auto get_data(size_t *len, uint16_t *msg_id, int *msg_type, int *msg_qos) - { - *len = message.size(); - *msg_id = static_cast(id); - *msg_type = static_cast(type); - *msg_qos = static_cast(qos); - return message.data(); - } - - [[nodiscard]] auto get_size() const noexcept - { - return message.size(); - } - -private: - std::pmr::vector message; - id_t id; - type_t type; - qos_t qos; - outbox_tick_t tick; - pending_state_t pending_state; -}; - -/* - * For the outbox_t we let the special member functions as default and - * we don't extend the allocator aware versions for the sake of the simplicity, since the operations are not needed in the usage. - */ -struct outbox_t { - using allocator_type = std::pmr::polymorphic_allocator<>; - explicit outbox_t(allocator_type alloc = {}) : queue(alloc) {} - - outbox_item_handle_t get(outbox_item::id_t msg_id) - { - if (auto item = std::ranges::find_if(queue, [msg_id](auto & item) { - return item.get_id() == msg_id; - }); - item != std::end(queue)) { - return &(*item); - } - return nullptr; - } - - int delete_expired(outbox_tick_t current_tick, outbox_tick_t timeout) - { - return std::erase_if(queue, [current_tick, timeout, this](const outbox_item & item) { - if (current_tick - item.get_tick() > timeout) { - total_size -= item.get_size(); - return true; - } - return false; - }); - } - - outbox_item::id_t delete_single_expired(outbox_tick_t current_tick, outbox_tick_t timeout) - { - if (auto erase = std::ranges::find_if(queue, [current_tick, timeout](auto & item) { - return (current_tick - item.get_tick() > timeout); - }); erase != std::end(queue)) { - auto msg_id = erase->get_id(); - total_size -= erase->get_size(); - queue.erase(erase); - return msg_id; - } - return outbox_item::id_t{-1}; - } - - auto erase(outbox_item_handle_t to_erase) - { - return erase_if([to_erase](auto & item) { - return &item == to_erase; - }); - } - - auto erase(outbox_item::id_t msg_id, outbox_item::type_t msg_type) - { - return erase_if([msg_id, msg_type](auto & item) { - return (item.get_id() == msg_id && (item.get_type() == msg_type)); - }); - } - - [[nodiscard]] auto size() const noexcept - { - return total_size; - } - - void clear() - { - queue.clear(); - } - - outbox_item_handle_t enqueue(outbox_message_handle_t message, outbox_tick_t tick) noexcept - { - try { - auto &item = - queue.emplace_back(std::pmr::vector {message->data, message->data + message->len}, - outbox_item::id_t{message->msg_id}, - outbox_item::type_t{message->msg_type}, - outbox_item::qos_t{message->msg_qos}, - tick, - QUEUED - ); - total_size += item.get_size(); - ESP_LOGD(TAG, "ENQUEUE msgid=%d, msg_type=%d, len=%d, size=%" PRIu64, message->msg_id, message->msg_type, message->len + message->remaining_len, outbox_get_size(this)); - return &item; - } catch (const std::exception &e) { - return nullptr; - } - } - - outbox_item_handle_t dequeue(pending_state_t state, outbox_tick_t *tick) - { - if (auto item = std::ranges::find_if(queue, [state](auto & item) { - return item.state() == state; - }); - item != std::end(queue)) { - if (tick != nullptr) { - *tick = item->get_tick(); - } - return &(*item); - } - return nullptr; - } - [[nodiscard]] allocator_type get_allocator() const - { - return queue.get_allocator(); - } -private: - [[nodiscard]] esp_err_t erase_if(std::predicate auto &&predicate) - { - if (auto to_erase = std::ranges::find_if(queue, predicate); to_erase != std::end(queue)) { - total_size -= to_erase->get_size(); - queue.erase(to_erase); - return ESP_OK; - } - return ESP_FAIL; - } - std::size_t total_size{}; - std::pmr::deque queue ; -}; - -extern "C" { - - outbox_handle_t outbox_init() - { - /* First we create a fixed size memory buffer to be used. */ - static constexpr auto work_memory_size = 16 * 1024; - static std::array resource_buffer{}; - try { - /* - * Since the outbox is managed by a C API we can't rely on C++ automatic cleanup and smart pointers but, on production code it would be better to add the - * memory resources to outbox_t, applying RAII principles, and make only outbox_item allocator aware. For the sake of the example we are keeping them - * separated to explictly show the relations. - * First we create the monotonic buffer and add null_memory_resource as upstream. This way if our working memory is exausted an exception is thrown. - */ - auto *monotonic_resource = new std::pmr::monotonic_buffer_resource{resource_buffer.data(), resource_buffer.size(), std::pmr::null_memory_resource()}; - /*Here we add our custom trace wrapper type to trace allocations and deallocations*/ - auto *trace_monotonic = new trace_resource("Monotonic", monotonic_resource); - - /* We compose monotonic buffer with pool resource, since the monotonic deallocate is a no-op and we need to remove messages to not go out of memory.*/ - auto *pool_resource = new std::pmr::unsynchronized_pool_resource{trace_monotonic}; - auto *trace_pool = new trace_resource("Pool", pool_resource); - /* Our outbox class is created using the trace_pool as memory resource */ - auto *outbox = new outbox_t{trace_pool}; - return outbox; - } catch (const std::exception &e) { - ESP_LOGD(TAG, "Not enough memory to construct the outbox, review the resource_buffer size"); - return nullptr; - - } - } - - outbox_item_handle_t outbox_enqueue(outbox_handle_t outbox, outbox_message_handle_t message, outbox_tick_t tick) - { - return outbox->enqueue(message, tick); - } - - outbox_item_handle_t outbox_get(outbox_handle_t outbox, int msg_id) - { - return outbox->get(outbox_item::id_t{msg_id}); - } - - outbox_item_handle_t outbox_dequeue(outbox_handle_t outbox, pending_state_t pending, outbox_tick_t *tick) - { - return outbox->dequeue(pending, tick); - } -} - -uint8_t *outbox_item_get_data(outbox_item_handle_t item, size_t *len, uint16_t *msg_id, int *msg_type, int *qos) -{ - if (item == nullptr) { - return nullptr; - } - return item->get_data(len, msg_id, msg_type, qos); -} - -esp_err_t outbox_delete_item(outbox_handle_t outbox, outbox_item_handle_t item_to_delete) -{ - return outbox->erase(item_to_delete); - -} - -esp_err_t outbox_delete(outbox_handle_t outbox, int msg_id, int msg_type) -{ - return outbox->erase(outbox_item::id_t{msg_id}, outbox_item::type_t{msg_type}); -} - -int outbox_delete_single_expired(outbox_handle_t outbox, outbox_tick_t current_tick, outbox_tick_t timeout) -{ - return static_cast(outbox->delete_single_expired(current_tick, timeout)); -} - -int outbox_delete_expired(outbox_handle_t outbox, outbox_tick_t current_tick, outbox_tick_t timeout) -{ - return outbox->delete_expired(current_tick, timeout); -} - -esp_err_t outbox_set_pending(outbox_handle_t outbox, int msg_id, pending_state_t pending) -{ - if (auto *item = outbox->get(outbox_item::id_t{msg_id}); item != nullptr) { - item->set(pending); - return ESP_OK; - } - return ESP_FAIL; -} - -pending_state_t outbox_item_get_pending(outbox_item_handle_t item) -{ - if (item != nullptr) { - return item->state(); - } - return QUEUED; -} - -esp_err_t outbox_set_tick(outbox_handle_t outbox, int msg_id, outbox_tick_t tick) -{ - if (auto *item = outbox->get(outbox_item::id_t{msg_id}); item != nullptr) { - item->set(tick); - return ESP_OK; - } - return ESP_FAIL; -} - -uint64_t outbox_get_size(outbox_handle_t outbox) -{ - return outbox->size(); -} - -void outbox_delete_all_items(outbox_handle_t outbox) -{ - outbox->clear(); -} - -void outbox_destroy(outbox_handle_t outbox) -{ - auto *trace_pool = static_cast(outbox->get_allocator().resource()); - auto *pool_resource = static_cast(trace_pool->upstream_resource()); - auto *trace_monotonic = static_cast(pool_resource->upstream_resource()); - auto *monotonic_resource = static_cast(trace_monotonic->upstream_resource()); - - delete monotonic_resource; - delete trace_monotonic; - delete pool_resource; - delete trace_pool; - delete outbox; -} diff --git a/examples/protocols/mqtt/custom_outbox/main/idf_component.yml b/examples/protocols/mqtt/custom_outbox/main/idf_component.yml deleted file mode 100644 index 718194867b7..00000000000 --- a/examples/protocols/mqtt/custom_outbox/main/idf_component.yml +++ /dev/null @@ -1,3 +0,0 @@ -dependencies: - protocol_examples_common: - path: ${IDF_PATH}/examples/common_components/protocol_examples_common diff --git a/examples/protocols/mqtt/custom_outbox/sdkconfig.ci.esp32c6 b/examples/protocols/mqtt/custom_outbox/sdkconfig.ci.esp32c6 deleted file mode 100644 index 1686559de40..00000000000 --- a/examples/protocols/mqtt/custom_outbox/sdkconfig.ci.esp32c6 +++ /dev/null @@ -1 +0,0 @@ -CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE=y diff --git a/examples/protocols/mqtt/custom_outbox/sdkconfig.defaults b/examples/protocols/mqtt/custom_outbox/sdkconfig.defaults deleted file mode 100644 index 11f90ceacf9..00000000000 --- a/examples/protocols/mqtt/custom_outbox/sdkconfig.defaults +++ /dev/null @@ -1,3 +0,0 @@ -CONFIG_MQTT_CUSTOM_OUTBOX=y -CONFIG_COMPILER_CXX_EXCEPTIONS=y -CONFIG_COMPILER_OPTIMIZATION_SIZE=y diff --git a/examples/protocols/mqtt/main/CMakeLists.txt b/examples/protocols/mqtt/main/CMakeLists.txt new file mode 100644 index 00000000000..a48d3cd3eff --- /dev/null +++ b/examples/protocols/mqtt/main/CMakeLists.txt @@ -0,0 +1,6 @@ +idf_component_register( + SRCS "app_main.c" + PRIV_REQUIRES esp-tls esp_wifi esp_event nvs_flash + INCLUDE_DIRS "." + EMBED_TXTFILES "mosquitto.org.crt" +) diff --git a/examples/protocols/mqtt/main/Kconfig.projbuild b/examples/protocols/mqtt/main/Kconfig.projbuild new file mode 100644 index 00000000000..a13af0e96cf --- /dev/null +++ b/examples/protocols/mqtt/main/Kconfig.projbuild @@ -0,0 +1,41 @@ +menu "Example Configuration" + + choice EXAMPLE_CERT_VALIDATION + prompt "Certificate validation method" + default EXAMPLE_CERT_VALIDATE_BUNDLE + help + Choose how the broker's TLS server certificate is validated. + - Certificate bundle (default). + - Embedded certificate + + config EXAMPLE_CERT_VALIDATE_BUNDLE + bool "Certificate bundle" + + config EXAMPLE_CERT_VALIDATE_MOSQUITTO_CA + bool "Embedded Certificate" + + endchoice + + config EXAMPLE_MQTT_BROKER_URI + string "MQTT broker URI" + default "mqtts://test.mosquitto.org:8886" + default "mqtts://test.mosquitto.org:8883" if EXAMPLE_CERT_VALIDATE_MOSQUITTO_CA + help + URI to the MQTT broker. + When using the example broker the port must be set to 8883 if testing + embedded certificate + + config EXAMPLE_BROKER_CERTIFICATE_OVERRIDE + string "Broker certificate override (PEM body)" + default "" + help + Optional: override server certificate by embedding a PEM constructed + from this base64 body. Leave empty to use the certificate bundle or the + embedded Mosquitto CA. Provide only the base64 payload without the + BEGIN/END markers. + + config EXAMPLE_BROKER_CERTIFICATE_OVERRIDDEN + bool + default y if EXAMPLE_BROKER_CERTIFICATE_OVERRIDE != "" + +endmenu diff --git a/examples/protocols/mqtt/ssl/main/app_main.c b/examples/protocols/mqtt/main/app_main.c similarity index 70% rename from examples/protocols/mqtt/ssl/main/app_main.c rename to examples/protocols/mqtt/main/app_main.c index ed5e04f1f36..5a9f6cb56a0 100644 --- a/examples/protocols/mqtt/ssl/main/app_main.c +++ b/examples/protocols/mqtt/main/app_main.c @@ -1,4 +1,9 @@ -/* MQTT over SSL Example +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +/* MQTT over TLS Example This example code is in the Public Domain (or CC0 licensed, at your option.) @@ -7,48 +12,38 @@ CONDITIONS OF ANY KIND, either express or implied. */ -#include -#include +#include #include +#include +#include #include -#include "esp_system.h" -#include "esp_partition.h" -#include "nvs_flash.h" + #include "esp_event.h" +#include "esp_log.h" #include "esp_netif.h" +#include "esp_system.h" +#include "nvs_flash.h" +#include "sdkconfig.h" + #include "protocol_examples_common.h" -#include "esp_log.h" +#include "esp_crt_bundle.h" #include "mqtt_client.h" -#include "esp_tls.h" -#include "esp_ota_ops.h" -#include static const char *TAG = "mqtts_example"; - -#if CONFIG_BROKER_CERTIFICATE_OVERRIDDEN == 1 -static const uint8_t mqtt_eclipseprojects_io_pem_start[] = "-----BEGIN CERTIFICATE-----\n" CONFIG_BROKER_CERTIFICATE_OVERRIDE "\n-----END CERTIFICATE-----"; -#else -extern const uint8_t mqtt_eclipseprojects_io_pem_start[] asm("_binary_mqtt_eclipseprojects_io_pem_start"); +#if CONFIG_EXAMPLE_BROKER_CERTIFICATE_OVERRIDDEN +static const char cert_override_pem[] = + "-----BEGIN CERTIFICATE-----\n" + CONFIG_EXAMPLE_BROKER_CERTIFICATE_OVERRIDE "\n" + "-----END CERTIFICATE-----"; #endif -extern const uint8_t mqtt_eclipseprojects_io_pem_end[] asm("_binary_mqtt_eclipseprojects_io_pem_end"); -// -// Note: this function is for testing purposes only publishing part of the active partition -// (to be checked against the original binary) -// -static void send_binary(esp_mqtt_client_handle_t client) -{ - esp_partition_mmap_handle_t out_handle; - const void *binary_address; - const esp_partition_t *partition = esp_ota_get_running_partition(); - esp_partition_mmap(partition, 0, partition->size, ESP_PARTITION_MMAP_DATA, &binary_address, &out_handle); - // sending only the configured portion of the partition (if it's less than the partition size) - int binary_size = MIN(CONFIG_BROKER_BIN_SIZE_TO_SEND, partition->size); - int msg_id = esp_mqtt_client_publish(client, "/topic/binary", binary_address, binary_size, 0, 0); - ESP_LOGI(TAG, "binary sent with msg_id=%d", msg_id); -} +#if CONFIG_EXAMPLE_CERT_VALIDATE_MOSQUITTO_CA +/* Embedded Mosquitto CA certificate for test.mosquitto.org:8883 */ +extern const uint8_t mosquitto_org_crt_start[] asm("_binary_mosquitto_org_crt_start"); +extern const uint8_t mosquitto_org_crt_end[] asm("_binary_mosquitto_org_crt_end"); +#endif /* * @brief Event handler registered to receive MQTT events @@ -69,13 +64,13 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_ switch ((esp_mqtt_event_id_t)event_id) { case MQTT_EVENT_CONNECTED: ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED"); - msg_id = esp_mqtt_client_subscribe(client, "/topic/qos0", 0); + msg_id = esp_mqtt_client_subscribe(client, "topic/qos0", 0); ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id); - msg_id = esp_mqtt_client_subscribe(client, "/topic/qos1", 1); + msg_id = esp_mqtt_client_subscribe(client, "topic/qos1", 1); ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id); - msg_id = esp_mqtt_client_unsubscribe(client, "/topic/qos1"); + msg_id = esp_mqtt_client_unsubscribe(client, "topic/qos1"); ESP_LOGI(TAG, "sent unsubscribe successful, msg_id=%d", msg_id); break; case MQTT_EVENT_DISCONNECTED: @@ -84,7 +79,7 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_ case MQTT_EVENT_SUBSCRIBED: ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d, return code=0x%02x ", event->msg_id, (uint8_t)*event->data); - msg_id = esp_mqtt_client_publish(client, "/topic/qos0", "data", 0, 0, 0); + msg_id = esp_mqtt_client_publish(client, "topic/qos0", "data", 0, 0, 0); ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id); break; case MQTT_EVENT_UNSUBSCRIBED: @@ -97,17 +92,13 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_ ESP_LOGI(TAG, "MQTT_EVENT_DATA"); printf("TOPIC=%.*s\r\n", event->topic_len, event->topic); printf("DATA=%.*s\r\n", event->data_len, event->data); - if (strncmp(event->data, "send binary please", event->data_len) == 0) { - ESP_LOGI(TAG, "Sending the binary"); - send_binary(client); - } break; case MQTT_EVENT_ERROR: ESP_LOGI(TAG, "MQTT_EVENT_ERROR"); if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) { ESP_LOGI(TAG, "Last error code reported from esp-tls: 0x%x", event->error_handle->esp_tls_last_esp_err); ESP_LOGI(TAG, "Last tls stack error number: 0x%x", event->error_handle->esp_tls_stack_err); - ESP_LOGI(TAG, "Last captured errno : %d (%s)", event->error_handle->esp_transport_sock_errno, + ESP_LOGI(TAG, "Last captured errno : %d (%s)", event->error_handle->esp_transport_sock_errno, strerror(event->error_handle->esp_transport_sock_errno)); } else if (event->error_handle->error_type == MQTT_ERROR_TYPE_CONNECTION_REFUSED) { ESP_LOGI(TAG, "Connection refused error: 0x%x", event->error_handle->connect_return_code); @@ -125,8 +116,14 @@ static void mqtt_app_start(void) { const esp_mqtt_client_config_t mqtt_cfg = { .broker = { - .address.uri = CONFIG_BROKER_URI, - .verification.certificate = (const char *)mqtt_eclipseprojects_io_pem_start + .address.uri = CONFIG_EXAMPLE_MQTT_BROKER_URI, +#if CONFIG_EXAMPLE_BROKER_CERTIFICATE_OVERRIDDEN + .verification.certificate = cert_override_pem, +#elif CONFIG_EXAMPLE_CERT_VALIDATE_MOSQUITTO_CA + .verification.certificate = (const char *)mosquitto_org_crt_start, +#else + .verification.crt_bundle_attach = esp_crt_bundle_attach, /* Use built-in certificate bundle */ +#endif }, }; diff --git a/examples/protocols/mqtt/tcp/main/idf_component.yml b/examples/protocols/mqtt/main/idf_component.yml similarity index 80% rename from examples/protocols/mqtt/tcp/main/idf_component.yml rename to examples/protocols/mqtt/main/idf_component.yml index 59805d8c7a3..689500cf6b7 100644 --- a/examples/protocols/mqtt/tcp/main/idf_component.yml +++ b/examples/protocols/mqtt/main/idf_component.yml @@ -1,7 +1,10 @@ dependencies: protocol_examples_common: path: ${IDF_PATH}/examples/common_components/protocol_examples_common + espressif/mqtt: "^1.0.0" espressif/esp_wifi_remote: version: ">=0.10,<2.0" rules: - if: "target in [esp32p4, esp32h2]" + idf: + version: ">=5.3" diff --git a/examples/protocols/mqtt/ssl_mutual_auth/main/mosquitto.org.crt b/examples/protocols/mqtt/main/mosquitto.org.crt similarity index 100% rename from examples/protocols/mqtt/ssl_mutual_auth/main/mosquitto.org.crt rename to examples/protocols/mqtt/main/mosquitto.org.crt diff --git a/examples/protocols/mqtt/ssl/pytest_mqtt_ssl.py b/examples/protocols/mqtt/pytest_mqtt_ssl.py similarity index 82% rename from examples/protocols/mqtt/ssl/pytest_mqtt_ssl.py rename to examples/protocols/mqtt/pytest_mqtt_ssl.py index c34cea6e50f..ebc68886e35 100644 --- a/examples/protocols/mqtt/ssl/pytest_mqtt_ssl.py +++ b/examples/protocols/mqtt/pytest_mqtt_ssl.py @@ -11,7 +11,6 @@ from threading import Thread import paho.mqtt.client as mqtt import pexpect import pytest -from pytest_embedded import Dut from pytest_embedded_idf.utils import idf_parametrize event_client_connected = Event() @@ -41,19 +40,17 @@ def on_message(client, userdata, msg): # type: (mqtt.Client, tuple, mqtt.client global event_client_received_binary if msg.topic == '/topic/binary': binary, bin_size = userdata - print('Receiving binary from esp and comparing with {}, size {}...'.format(binary, bin_size)) + print(f'Receiving binary from esp and comparing with {binary}, size {bin_size}...') with open(binary, 'rb') as f: - bin = f.read() - if bin[:bin_size] == msg.payload[:bin_size]: + data = f.read() + if data[:bin_size] == msg.payload[:bin_size]: print('...matches!') event_client_received_binary.set() return recv_binary = binary + '.received' with open(recv_binary, 'w', encoding='utf-8') as fw: fw.write(msg.payload) - raise ValueError( - 'Received binary (saved as: {}) does not match the original file: {}'.format(recv_binary, binary) - ) + raise ValueError(f'Received binary (saved as: {recv_binary}) does not match the original file: {binary}') payload = msg.payload.decode() if not event_client_received_correct.is_set() and payload == 'data': @@ -66,7 +63,7 @@ def on_message(client, userdata, msg): # type: (mqtt.Client, tuple, mqtt.client @pytest.mark.ethernet @idf_parametrize('target', ['esp32'], indirect=['target']) -def test_examples_protocol_mqtt_ssl(dut): # type: (Dut) -> None +def test_examples_protocol_mqtt_ssl(dut): # type: ignore broker_url = '' broker_port = 0 """ @@ -103,28 +100,24 @@ def test_examples_protocol_mqtt_ssl(dut): # type: (Dut) -> None print('Connecting...') client.connect(broker_url, broker_port, 60) except Exception: - print( - 'ENV_TEST_FAILURE: Unexpected error while connecting to broker {}: {}:'.format( - broker_url, sys.exc_info()[0] - ) - ) + print(f'ENV_TEST_FAILURE: Unexpected error while connecting to broker {broker_url}: {sys.exc_info()[0]}:') raise # Starting a py-client in a separate thread thread1 = Thread(target=mqtt_client_task, args=(client,)) thread1.start() try: - print('Connecting py-client to broker {}:{}...'.format(broker_url, broker_port)) + print(f'Connecting py-client to broker {broker_url}:{broker_port}...') if not event_client_connected.wait(timeout=30): - raise ValueError('ENV_TEST_FAILURE: Test script cannot connect to broker: {}'.format(broker_url)) + raise ValueError(f'ENV_TEST_FAILURE: Test script cannot connect to broker: {broker_url}') try: ip_address = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[0] - print('Connected to AP with IP: {}'.format(ip_address)) + print(f'Connected to AP with IP: {ip_address}') except pexpect.TIMEOUT: print('ENV_TEST_FAILURE: Cannot connect to AP') raise print('Checking py-client received msg published from esp...') if not event_client_received_correct.wait(timeout=30): - raise ValueError('Wrong data received, msg log: {}'.format(message_log)) + raise ValueError(f'Wrong data received, msg log: {message_log}') print('Checking esp-client received msg published from py-client...') dut.expect(r'DATA=send binary please', timeout=30) print('Receiving binary data from running partition...') diff --git a/examples/protocols/mqtt/tcp/sdkconfig.ci b/examples/protocols/mqtt/sdkconfig.ci similarity index 68% rename from examples/protocols/mqtt/tcp/sdkconfig.ci rename to examples/protocols/mqtt/sdkconfig.ci index 6cace410d21..d8a42deaa5d 100644 --- a/examples/protocols/mqtt/tcp/sdkconfig.ci +++ b/examples/protocols/mqtt/sdkconfig.ci @@ -1,5 +1,3 @@ -CONFIG_LOG_DEFAULT_LEVEL_DEBUG=y -CONFIG_BROKER_URL="FROM_STDIN" CONFIG_EXAMPLE_CONNECT_ETHERNET=y CONFIG_EXAMPLE_CONNECT_WIFI=n CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y @@ -9,5 +7,7 @@ CONFIG_EXAMPLE_ETH_MDIO_GPIO=18 CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5 CONFIG_EXAMPLE_ETH_PHY_ADDR=1 CONFIG_EXAMPLE_CONNECT_IPV6=y -CONFIG_LWIP_TCPIP_CORE_LOCKING=y CONFIG_LWIP_CHECK_THREAD_SAFETY=y + +CONFIG_EXAMPLE_MQTT_BROKER_URI="mqtts://${EXAMPLE_MQTT_BROKER_SSL}" +CONFIG_EXAMPLE_BROKER_CERTIFICATE_OVERRIDE="${EXAMPLE_MQTT_BROKER_CERTIFICATE}" diff --git a/examples/protocols/mqtt/sdkconfig.defaults b/examples/protocols/mqtt/sdkconfig.defaults new file mode 100644 index 00000000000..ba8223dfb9f --- /dev/null +++ b/examples/protocols/mqtt/sdkconfig.defaults @@ -0,0 +1,3 @@ +# Enable the built-in certificate bundle for TLS server verification +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=y +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=y diff --git a/examples/protocols/mqtt/ssl/CMakeLists.txt b/examples/protocols/mqtt/ssl/CMakeLists.txt deleted file mode 100644 index 9a191c401c2..00000000000 --- a/examples/protocols/mqtt/ssl/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -# The following four lines of boilerplate have to be in your project's CMakeLists -# in this exact order for cmake to work correctly -cmake_minimum_required(VERSION 3.22) - - -include($ENV{IDF_PATH}/tools/cmake/project.cmake) -# "Trim" the build. Include the minimal set of components, main, and anything it depends on. -idf_build_set_property(MINIMAL_BUILD ON) -project(mqtt_ssl) - -target_add_binary_data(${PROJECT_NAME}.elf "main/mqtt_eclipseprojects_io.pem" TEXT) diff --git a/examples/protocols/mqtt/ssl/main/CMakeLists.txt b/examples/protocols/mqtt/ssl/main/CMakeLists.txt deleted file mode 100644 index d6ca62dc1f5..00000000000 --- a/examples/protocols/mqtt/ssl/main/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -idf_component_register(SRCS "app_main.c" - PRIV_REQUIRES mqtt esp_partition nvs_flash esp_netif app_update - INCLUDE_DIRS ".") diff --git a/examples/protocols/mqtt/ssl/main/Kconfig.projbuild b/examples/protocols/mqtt/ssl/main/Kconfig.projbuild deleted file mode 100644 index 5e9357d1a69..00000000000 --- a/examples/protocols/mqtt/ssl/main/Kconfig.projbuild +++ /dev/null @@ -1,26 +0,0 @@ -menu "Example Configuration" - - config BROKER_URI - string "Broker URL" - default "mqtts://mqtt.eclipseprojects.io:8883" - help - URL of an mqtt broker which this example connects to. - - config BROKER_CERTIFICATE_OVERRIDE - string "Broker certificate override" - default "" - help - Please leave empty if broker certificate included from a textfile; otherwise fill in a base64 part of PEM - format certificate - - config BROKER_CERTIFICATE_OVERRIDDEN - bool - default y if BROKER_CERTIFICATE_OVERRIDE != "" - - config BROKER_BIN_SIZE_TO_SEND - # This option is not visible and is used only to set parameters for example tests - # Here we configure the data size to send and to be expected in the python script - int - default 20000 - -endmenu diff --git a/examples/protocols/mqtt/ssl/main/idf_component.yml b/examples/protocols/mqtt/ssl/main/idf_component.yml deleted file mode 100644 index 718194867b7..00000000000 --- a/examples/protocols/mqtt/ssl/main/idf_component.yml +++ /dev/null @@ -1,3 +0,0 @@ -dependencies: - protocol_examples_common: - path: ${IDF_PATH}/examples/common_components/protocol_examples_common diff --git a/examples/protocols/mqtt/ssl/main/mqtt_eclipseprojects_io.pem b/examples/protocols/mqtt/ssl/main/mqtt_eclipseprojects_io.pem deleted file mode 100644 index 43b222a60a5..00000000000 --- a/examples/protocols/mqtt/ssl/main/mqtt_eclipseprojects_io.pem +++ /dev/null @@ -1,30 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIFFjCCAv6gAwIBAgIRAJErCErPDBinU/bWLiWnX1owDQYJKoZIhvcNAQELBQAw -TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh -cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjAwOTA0MDAwMDAw -WhcNMjUwOTE1MTYwMDAwWjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg -RW5jcnlwdDELMAkGA1UEAxMCUjMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK -AoIBAQC7AhUozPaglNMPEuyNVZLD+ILxmaZ6QoinXSaqtSu5xUyxr45r+XXIo9cP -R5QUVTVXjJ6oojkZ9YI8QqlObvU7wy7bjcCwXPNZOOftz2nwWgsbvsCUJCWH+jdx -sxPnHKzhm+/b5DtFUkWWqcFTzjTIUu61ru2P3mBw4qVUq7ZtDpelQDRrK9O8Zutm -NHz6a4uPVymZ+DAXXbpyb/uBxa3Shlg9F8fnCbvxK/eG3MHacV3URuPMrSXBiLxg -Z3Vms/EY96Jc5lP/Ooi2R6X/ExjqmAl3P51T+c8B5fWmcBcUr2Ok/5mzk53cU6cG -/kiFHaFpriV1uxPMUgP17VGhi9sVAgMBAAGjggEIMIIBBDAOBgNVHQ8BAf8EBAMC -AYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMBIGA1UdEwEB/wQIMAYB -Af8CAQAwHQYDVR0OBBYEFBQusxe3WFbLrlAJQOYfr52LFMLGMB8GA1UdIwQYMBaA -FHm0WeZ7tuXkAXOACIjIGlj26ZtuMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcw -AoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzAnBgNVHR8EIDAeMBygGqAYhhZodHRw -Oi8veDEuYy5sZW5jci5vcmcvMCIGA1UdIAQbMBkwCAYGZ4EMAQIBMA0GCysGAQQB -gt8TAQEBMA0GCSqGSIb3DQEBCwUAA4ICAQCFyk5HPqP3hUSFvNVneLKYY611TR6W -PTNlclQtgaDqw+34IL9fzLdwALduO/ZelN7kIJ+m74uyA+eitRY8kc607TkC53wl -ikfmZW4/RvTZ8M6UK+5UzhK8jCdLuMGYL6KvzXGRSgi3yLgjewQtCPkIVz6D2QQz -CkcheAmCJ8MqyJu5zlzyZMjAvnnAT45tRAxekrsu94sQ4egdRCnbWSDtY7kh+BIm -lJNXoB1lBMEKIq4QDUOXoRgffuDghje1WrG9ML+Hbisq/yFOGwXD9RiX8F6sw6W4 -avAuvDszue5L3sz85K+EC4Y/wFVDNvZo4TYXao6Z0f+lQKc0t8DQYzk1OXVu8rp2 -yJMC6alLbBfODALZvYH7n7do1AZls4I9d1P4jnkDrQoxB3UqQ9hVl3LEKQ73xF1O -yK5GhDDX8oVfGKF5u+decIsH4YaTw7mP3GFxJSqv3+0lUFJoi5Lc5da149p90Ids -hCExroL1+7mryIkXPeFM5TgO9r0rvZaBFOvV2z0gp35Z0+L4WPlbuEjN/lxPFin+ -HlUjr8gRsI3qfJOQFy/9rKIJR0Y/8Omwt/8oTWgy1mdeHmmjk7j1nYsvC9JSQ6Zv -MldlTTKB3zhThV1+XWYp6rjd5JW1zbVWEkLNxE7GJThEUG3szgBVGP7pSWTUTsqX -nLRbwHOoq7hHwg== ------END CERTIFICATE----- diff --git a/examples/protocols/mqtt/ssl/sdkconfig.ci b/examples/protocols/mqtt/ssl/sdkconfig.ci deleted file mode 100644 index 3e3a8595fd0..00000000000 --- a/examples/protocols/mqtt/ssl/sdkconfig.ci +++ /dev/null @@ -1,22 +0,0 @@ -CONFIG_BROKER_URI="mqtts://${EXAMPLE_MQTT_BROKER_SSL}" -CONFIG_BROKER_CERTIFICATE_OVERRIDE="${EXAMPLE_MQTT_BROKER_CERTIFICATE}" -CONFIG_MQTT_USE_CUSTOM_CONFIG=y -CONFIG_MQTT_TCP_DEFAULT_PORT=1883 -CONFIG_MQTT_SSL_DEFAULT_PORT=8883 -CONFIG_MQTT_WS_DEFAULT_PORT=80 -CONFIG_MQTT_WSS_DEFAULT_PORT=443 -CONFIG_MQTT_BUFFER_SIZE=16384 -CONFIG_MQTT_TASK_STACK_SIZE=6144 -CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y -CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN=16384 -CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=4096 -CONFIG_EXAMPLE_CONNECT_ETHERNET=y -CONFIG_EXAMPLE_CONNECT_WIFI=n -CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y -CONFIG_EXAMPLE_ETH_PHY_GENERIC=y -CONFIG_EXAMPLE_ETH_MDC_GPIO=23 -CONFIG_EXAMPLE_ETH_MDIO_GPIO=18 -CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5 -CONFIG_EXAMPLE_ETH_PHY_ADDR=1 -CONFIG_EXAMPLE_CONNECT_IPV6=y -CONFIG_LWIP_CHECK_THREAD_SAFETY=y diff --git a/examples/protocols/mqtt/ssl_ds/CMakeLists.txt b/examples/protocols/mqtt/ssl_ds/CMakeLists.txt deleted file mode 100644 index a1f5cf86a6a..00000000000 --- a/examples/protocols/mqtt/ssl_ds/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -# The following four lines of boilerplate have to be in your project's CMakeLists -# in this exact order for cmake to work correctly -cmake_minimum_required(VERSION 3.22) - - -include($ENV{IDF_PATH}/tools/cmake/project.cmake) -# "Trim" the build. Include the minimal set of components, main, and anything it depends on. -idf_build_set_property(MINIMAL_BUILD ON) -project(mqtt_ssl_ds) - -# Flash the custom partition named `esp_secure_cert`. -set(partition esp_secure_cert) -idf_build_get_property(project_dir PROJECT_DIR) -set(image_file ${project_dir}/esp_secure_cert_data/${partition}.bin) -partition_table_get_partition_info(offset "--partition-name ${partition}" "offset") -esptool_py_flash_target_image(flash "${partition}" "${offset}" "${image_file}") - -target_add_binary_data(${CMAKE_PROJECT_NAME}.elf "main/mosquitto.org.crt" TEXT) diff --git a/examples/protocols/mqtt/ssl_ds/README.md b/examples/protocols/mqtt/ssl_ds/README.md deleted file mode 100644 index f89d1726ec8..00000000000 --- a/examples/protocols/mqtt/ssl_ds/README.md +++ /dev/null @@ -1,105 +0,0 @@ -| Supported Targets | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | - -# ESP-MQTT SSL Mutual Authentication with Digital Signature -(See the README.md file in the upper level 'examples' directory for more information about examples.) - -Espressif's ESP32-S2, ESP32-S3, ESP32-C3, ESP32-C6, ESP32-H2 and ESP32-P4 MCU have a built-in Digital Signature (DS) Peripheral, which provides hardware acceleration for RSA signature. More details can be found at [Digital Signature with ESP-TLS](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/api-reference/protocols/esp_tls.html#digital-signature-with-esp-tls). - -This example connects to the broker test.mosquitto.org using ssl transport with client certificate(RSA) and as a demonstration subscribes/unsubscribes and sends a message on certain topic.The RSA signature operation required in the ssl connection is performed with help of the Digital Signature (DS) peripheral. -(Please note that the public broker is maintained by the community so may not be always available, for details please visit http://test.mosquitto.org) - -It uses ESP-MQTT library which implements mqtt client to connect to mqtt broker. -## How to use example - -### Hardware Required - -This example can be executed on any of the supported ESP32 family board (which has a built-in DS peripheral), the only required interface is WiFi/Ethernet and connection to internet. - -### Configure the project - -#### 1) Selecting the target - -Please select the supported target with the following command: -``` -idf.py set-target /* target */ -``` -More details can be found at [Selecting the target](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/build-system.html#selecting-the-target). - -#### 2) Generate your client key and certificate - -Navigate to the main directory - -``` -cd main -``` - -Generate a client key and a CSR. When you are generating the CSR, do not use the default values. At a minimum, the CSR must include the Country, Organisation and Common Name fields. - -``` -openssl genrsa -out client.key -openssl req -out client.csr -key client.key -new -``` - -Paste the generated CSR in the [Mosquitto test certificate signer](https://test.mosquitto.org/ssl/index.php), click Submit and downloaded the `client.crt`. This `client.crt` file shall be used as the device certificate. - -#### 3) Configure the DS peripheral - -* i) Install the [esp_secure_cert configuration utility](https://github.com/espressif/esp_secure_cert_mgr/tree/main/tools#esp_secure_cert-configuration-tool) with following command: -``` -pip install esp-secure-cert-tool -``` -* ii) The DS peripheral can be configured by executing the following command: - -``` -configure_esp_secure_cert.py -p /* Serial port */ --device-cert /* Device cert */ --private-key /* RSA priv key */ --target_chip /* target chip */ --configure_ds --skip_flash -``` -This command shall generate a partition named `esp_secure_cert.bin` in the `esp_secure_cert_data` directory. This partition would be aumatically detected by the build system and flashed at appropriate offset when `idf.py flash` command is used. For this process, the command must be executed in the current folder only. - -In the command USB COM port is nothing but the serial port to which the ESP chip is connected. see -[check serial port](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/establish-serial-connection.html#check-port-on-windows) for more details. -RSA private key is nothing but the client private key ( RSA ) generated in Step 2. - -> Note: More details about the `esp-secure-cert-tool` utility can be found [here](https://github.com/espressif/esp_secure_cert_mgr/tree/main/tools). - -#### 4) Connection configuration -* Open the project configuration menu (`idf.py menuconfig`) -* Configure Wi-Fi or Ethernet under "Example Connection Configuration" menu. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more details. - -### Build and Flash - -Build the project and flash it to the board, then run monitor tool to view serial output: - -``` -idf.py -p PORT flash monitor -``` - -(To exit the serial monitor, type ``Ctrl-]``.) - -See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects. - -## Example Output - -``` -I (3714) event: sta ip: 192.168.0.139, mask: 255.255.255.0, gw: 192.168.0.2 -I (3714) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE -I (3964) MQTT_CLIENT: Sending MQTT CONNECT message, type: 1, id: 0000 -I (4164) MQTTS_EXAMPLE: MQTT_EVENT_CONNECTED -I (4174) MQTTS_EXAMPLE: sent publish successful, msg_id=41464 -I (4174) MQTTS_EXAMPLE: sent subscribe successful, msg_id=17886 -I (4174) MQTTS_EXAMPLE: sent subscribe successful, msg_id=42970 -I (4184) MQTTS_EXAMPLE: sent unsubscribe successful, msg_id=50241 -I (4314) MQTTS_EXAMPLE: MQTT_EVENT_PUBLISHED, msg_id=41464 -I (4484) MQTTS_EXAMPLE: MQTT_EVENT_SUBSCRIBED, msg_id=17886 -I (4484) MQTTS_EXAMPLE: sent publish successful, msg_id=0 -I (4684) MQTTS_EXAMPLE: MQTT_EVENT_SUBSCRIBED, msg_id=42970 -I (4684) MQTTS_EXAMPLE: sent publish successful, msg_id=0 -I (4884) MQTT_CLIENT: deliver_publish, message_length_read=19, message_length=19 -I (4884) MQTTS_EXAMPLE: MQTT_EVENT_DATA -TOPIC=/topic/qos0 -DATA=data -I (5194) MQTT_CLIENT: deliver_publish, message_length_read=19, message_length=19 -I (5194) MQTTS_EXAMPLE: MQTT_EVENT_DATA -TOPIC=/topic/qos0 -DATA=data -``` diff --git a/examples/protocols/mqtt/ssl_ds/main/CMakeLists.txt b/examples/protocols/mqtt/ssl_ds/main/CMakeLists.txt deleted file mode 100644 index 055d4c563a1..00000000000 --- a/examples/protocols/mqtt/ssl_ds/main/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -idf_component_register(SRCS "app_main.c" - PRIV_REQUIRES mqtt esp_netif - INCLUDE_DIRS ".") diff --git a/examples/protocols/mqtt/ssl_ds/main/app_main.c b/examples/protocols/mqtt/ssl_ds/main/app_main.c deleted file mode 100644 index 7b54cfbf846..00000000000 --- a/examples/protocols/mqtt/ssl_ds/main/app_main.c +++ /dev/null @@ -1,156 +0,0 @@ -/* MQTT Mutual Authentication Example - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ -#include -#include -#include -#include -#include "esp_system.h" -#include "nvs_flash.h" -#include "esp_event.h" -#include "esp_netif.h" -#include "protocol_examples_common.h" - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/semphr.h" -#include "freertos/queue.h" - -#include "lwip/sockets.h" -#include "lwip/dns.h" -#include "lwip/netdb.h" - -#include "esp_log.h" -#include "mqtt_client.h" -#include "rsa_sign_alt.h" -#include "esp_secure_cert_read.h" - -static const char *TAG = "mqtts_example"; - -extern const uint8_t server_cert_pem_start[] asm("_binary_mosquitto_org_crt_start"); -extern const uint8_t server_cert_pem_end[] asm("_binary_mosquitto_org_crt_end"); - -/* - * @brief Event handler registered to receive MQTT events - * - * This function is called by the MQTT client event loop. - * - * @param handler_args user data registered to the event. - * @param base Event base for the handler(always MQTT Base in this example). - * @param event_id The id for the received event. - * @param event_data The data for the event, esp_mqtt_event_handle_t. - */ -static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) -{ - ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%" PRIi32, base, event_id); - esp_mqtt_event_handle_t event = event_data; - esp_mqtt_client_handle_t client = event->client; - int msg_id; - // your_context_t *context = event->context; - switch ((esp_mqtt_event_id_t)event_id) { - case MQTT_EVENT_CONNECTED: - ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED"); - msg_id = esp_mqtt_client_subscribe(client, "/topic/qos0", 0); - ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id); - - msg_id = esp_mqtt_client_subscribe(client, "/topic/qos1", 1); - ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id); - - msg_id = esp_mqtt_client_unsubscribe(client, "/topic/qos1"); - ESP_LOGI(TAG, "sent unsubscribe successful, msg_id=%d", msg_id); - break; - case MQTT_EVENT_DISCONNECTED: - ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED"); - break; - - case MQTT_EVENT_SUBSCRIBED: - ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d, return code=0x%02x ", event->msg_id, (uint8_t)*event->data); - msg_id = esp_mqtt_client_publish(client, "/topic/qos0", "data", 0, 0, 0); - ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id); - break; - case MQTT_EVENT_UNSUBSCRIBED: - ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id); - break; - case MQTT_EVENT_PUBLISHED: - ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id); - break; - case MQTT_EVENT_DATA: - ESP_LOGI(TAG, "MQTT_EVENT_DATA"); - printf("TOPIC=%.*s\r\n", event->topic_len, event->topic); - printf("DATA=%.*s\r\n", event->data_len, event->data); - break; - case MQTT_EVENT_ERROR: - ESP_LOGI(TAG, "MQTT_EVENT_ERROR"); - break; - default: - ESP_LOGI(TAG, "Other event id:%d", event->event_id); - break; - } -} - -static void mqtt_app_start(void) -{ - /* The context is used by the DS peripheral, should not be freed */ - esp_ds_data_ctx_t *ds_data = esp_secure_cert_get_ds_ctx(); - if (ds_data == NULL) { - ESP_LOGE(TAG, "Error in reading DS data from NVS"); - vTaskDelete(NULL); - } - char *device_cert = NULL; - esp_err_t ret; - uint32_t len; - ret = esp_secure_cert_get_device_cert(&device_cert, &len); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to obtain the device certificate"); - vTaskDelete(NULL); - } - - const esp_mqtt_client_config_t mqtt_cfg = { - .broker = { - .address.uri = "mqtts://test.mosquitto.org:8884", - .verification.certificate = (const char *)server_cert_pem_start, - }, - .credentials = { - .authentication = { - .certificate = (const char *)device_cert, - .key = NULL, - .ds_data = (void *)ds_data - }, - }, - }; - - ESP_LOGI(TAG, "[APP] Free memory: %" PRIu32 " bytes", esp_get_free_heap_size()); - esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg); - esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL); - esp_mqtt_client_start(client); -} - -void app_main(void) -{ - ESP_LOGI(TAG, "[APP] Startup.."); - ESP_LOGI(TAG, "[APP] Free memory: %" PRIu32 " bytes", esp_get_free_heap_size()); - ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version()); - - esp_log_level_set("*", ESP_LOG_INFO); - esp_log_level_set("mqtt_client", ESP_LOG_VERBOSE); - esp_log_level_set("transport_base", ESP_LOG_VERBOSE); - esp_log_level_set("transport", ESP_LOG_VERBOSE); - esp_log_level_set("outbox", ESP_LOG_VERBOSE); - - ESP_ERROR_CHECK(nvs_flash_init()); - ESP_ERROR_CHECK(esp_netif_init()); - ESP_ERROR_CHECK(esp_event_loop_create_default()); - - /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. - * Read "Establishing Wi-Fi or Ethernet Connection" section in - * examples/protocols/README.md for more information about this function. - */ - ESP_ERROR_CHECK(example_connect()); - - mqtt_app_start(); -} diff --git a/examples/protocols/mqtt/ssl_ds/main/idf_component.yml b/examples/protocols/mqtt/ssl_ds/main/idf_component.yml deleted file mode 100644 index 947ec180420..00000000000 --- a/examples/protocols/mqtt/ssl_ds/main/idf_component.yml +++ /dev/null @@ -1,5 +0,0 @@ -## IDF Component Manager Manifest File -dependencies: - espressif/esp_secure_cert_mgr: "^2.0.2" - protocol_examples_common: - path: ${IDF_PATH}/examples/common_components/protocol_examples_common diff --git a/examples/protocols/mqtt/ssl_ds/partitions.csv b/examples/protocols/mqtt/ssl_ds/partitions.csv deleted file mode 100644 index 1423949dc97..00000000000 --- a/examples/protocols/mqtt/ssl_ds/partitions.csv +++ /dev/null @@ -1,6 +0,0 @@ -# ESP-IDF Partition Table -# Name, Type, SubType, Offset, Size, Flags -esp_secure_cert,0x3F,,,0x2000, -nvs,data,nvs,,24K, -phy_init,data,phy,,4K, -factory,app,factory,0x20000,1500K, diff --git a/examples/protocols/mqtt/ssl_ds/sdkconfig.defaults b/examples/protocols/mqtt/ssl_ds/sdkconfig.defaults deleted file mode 100644 index 94e282f1d65..00000000000 --- a/examples/protocols/mqtt/ssl_ds/sdkconfig.defaults +++ /dev/null @@ -1,7 +0,0 @@ -CONFIG_PARTITION_TABLE_CUSTOM=y -# Setting partition table offset to 0xC000 would make the address of -# `esp_secure_cert` partition as 0xD000 (comes next in the sequence). -# Modules that are programmed with Espressif Secure Pre Provisioining service -# uses this offset for `esp_secure_cert` and hence this change aligns this example -# to work on those modules. -CONFIG_PARTITION_TABLE_OFFSET=0xC000 diff --git a/examples/protocols/mqtt/ssl_ds/sdkconfig.defaults.esp32h2 b/examples/protocols/mqtt/ssl_ds/sdkconfig.defaults.esp32h2 deleted file mode 100644 index dcbc3a5a77a..00000000000 --- a/examples/protocols/mqtt/ssl_ds/sdkconfig.defaults.esp32h2 +++ /dev/null @@ -1,2 +0,0 @@ -CONFIG_EXAMPLE_CONNECT_WIFI=n -CONFIG_EXAMPLE_CONNECT_ETHERNET=y diff --git a/examples/protocols/mqtt/ssl_mutual_auth/CMakeLists.txt b/examples/protocols/mqtt/ssl_mutual_auth/CMakeLists.txt deleted file mode 100644 index ee38996770c..00000000000 --- a/examples/protocols/mqtt/ssl_mutual_auth/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -# The following four lines of boilerplate have to be in your project's CMakeLists -# in this exact order for cmake to work correctly -cmake_minimum_required(VERSION 3.22) - - -include($ENV{IDF_PATH}/tools/cmake/project.cmake) -# "Trim" the build. Include the minimal set of components, main, and anything it depends on. -idf_build_set_property(MINIMAL_BUILD ON) -project(mqtt_ssl_mutual_auth) - -target_add_binary_data(${CMAKE_PROJECT_NAME}.elf "main/client.crt" TEXT) -target_add_binary_data(${CMAKE_PROJECT_NAME}.elf "main/client.key" TEXT) -target_add_binary_data(${CMAKE_PROJECT_NAME}.elf "main/mosquitto.org.crt" TEXT) diff --git a/examples/protocols/mqtt/ssl_mutual_auth/README.md b/examples/protocols/mqtt/ssl_mutual_auth/README.md deleted file mode 100644 index 4750ff1ff4b..00000000000 --- a/examples/protocols/mqtt/ssl_mutual_auth/README.md +++ /dev/null @@ -1,82 +0,0 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | - -# ESP-MQTT SSL Sample application (mutual authentication) - -(See the README.md file in the upper level 'examples' directory for more information about examples.) - -This example connects to the broker test.mosquitto.org using ssl transport with client certificate and as a demonstration subscribes/unsubscribes and send a message on certain topic. -(Please note that the public broker is maintained by the community so may not be always available, for details please visit http://test.mosquitto.org) - -It uses ESP-MQTT library which implements mqtt client to connect to mqtt broker. - -## How to use example - -### Hardware Required - -This example can be executed on any ESP32 board, the only required interface is WiFi and connection to internet. - -### Configure the project - -* Open the project configuration menu (`idf.py menuconfig`) -* Configure Wi-Fi or Ethernet under "Example Connection Configuration" menu. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more details. - -* Generate your client keys and certificate - -Navigate to the main directory - -``` -cd main -``` - -Generate a client key and a CSR. When you are generating the CSR, do not use the default values. At a minimum, the CSR must include the Country, Organisation and Common Name fields. - -``` -openssl genrsa -out client.key -openssl req -out client.csr -key client.key -new -``` - -Paste the generated CSR in the [Mosquitto test certificate signer](https://test.mosquitto.org/ssl/index.php), click Submit and copy the downloaded `client.crt` in the `main` directory. - -Please note, that the supplied files `client.crt` and `client.key` in the `main` directory are only placeholders for your client certificate and key (i.e. the example "as is" would compile but would not connect to the broker) - -The server certificate `mosquitto.org.crt` can be downloaded in pem format from [mosquitto.org.crt](https://test.mosquitto.org/ssl/mosquitto.org.crt). - -### Build and Flash - -Build the project and flash it to the board, then run monitor tool to view serial output: - -``` -idf.py -p PORT flash monitor -``` - -(To exit the serial monitor, type ``Ctrl-]``.) - -See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects. - -## Example Output - -``` -I (3714) event: sta ip: 192.168.0.139, mask: 255.255.255.0, gw: 192.168.0.2 -I (3714) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE -I (3964) MQTT_CLIENT: Sending MQTT CONNECT message, type: 1, id: 0000 -I (4164) MQTTS_EXAMPLE: MQTT_EVENT_CONNECTED -I (4174) MQTTS_EXAMPLE: sent publish successful, msg_id=41464 -I (4174) MQTTS_EXAMPLE: sent subscribe successful, msg_id=17886 -I (4174) MQTTS_EXAMPLE: sent subscribe successful, msg_id=42970 -I (4184) MQTTS_EXAMPLE: sent unsubscribe successful, msg_id=50241 -I (4314) MQTTS_EXAMPLE: MQTT_EVENT_PUBLISHED, msg_id=41464 -I (4484) MQTTS_EXAMPLE: MQTT_EVENT_SUBSCRIBED, msg_id=17886 -I (4484) MQTTS_EXAMPLE: sent publish successful, msg_id=0 -I (4684) MQTTS_EXAMPLE: MQTT_EVENT_SUBSCRIBED, msg_id=42970 -I (4684) MQTTS_EXAMPLE: sent publish successful, msg_id=0 -I (4884) MQTT_CLIENT: deliver_publish, message_length_read=19, message_length=19 -I (4884) MQTTS_EXAMPLE: MQTT_EVENT_DATA -TOPIC=/topic/qos0 -DATA=data -I (5194) MQTT_CLIENT: deliver_publish, message_length_read=19, message_length=19 -I (5194) MQTTS_EXAMPLE: MQTT_EVENT_DATA -TOPIC=/topic/qos0 -DATA=data -``` - diff --git a/examples/protocols/mqtt/ssl_mutual_auth/main/CMakeLists.txt b/examples/protocols/mqtt/ssl_mutual_auth/main/CMakeLists.txt deleted file mode 100644 index 31650f39dd1..00000000000 --- a/examples/protocols/mqtt/ssl_mutual_auth/main/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -idf_component_register(SRCS "app_main.c" - PRIV_REQUIRES mqtt esp_wifi nvs_flash - INCLUDE_DIRS ".") diff --git a/examples/protocols/mqtt/ssl_mutual_auth/main/app_main.c b/examples/protocols/mqtt/ssl_mutual_auth/main/app_main.c deleted file mode 100644 index 90ba71c51a0..00000000000 --- a/examples/protocols/mqtt/ssl_mutual_auth/main/app_main.c +++ /dev/null @@ -1,155 +0,0 @@ -/* MQTT Mutual Authentication Example - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ -#include -#include -#include -#include -#include "esp_wifi.h" -#include "esp_system.h" -#include "nvs_flash.h" -#include "esp_event.h" -#include "esp_netif.h" -#include "protocol_examples_common.h" - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/semphr.h" -#include "freertos/queue.h" - -#include "lwip/sockets.h" -#include "lwip/dns.h" -#include "lwip/netdb.h" - -#include "esp_log.h" -#include "mqtt_client.h" - -static const char *TAG = "mqtts_example"; - -extern const uint8_t client_cert_pem_start[] asm("_binary_client_crt_start"); -extern const uint8_t client_cert_pem_end[] asm("_binary_client_crt_end"); -extern const uint8_t client_key_pem_start[] asm("_binary_client_key_start"); -extern const uint8_t client_key_pem_end[] asm("_binary_client_key_end"); -extern const uint8_t server_cert_pem_start[] asm("_binary_mosquitto_org_crt_start"); -extern const uint8_t server_cert_pem_end[] asm("_binary_mosquitto_org_crt_end"); - -static void log_error_if_nonzero(const char *message, int error_code) -{ - if (error_code != 0) { - ESP_LOGE(TAG, "Last error %s: 0x%x", message, error_code); - } -} - -/* - * @brief Event handler registered to receive MQTT events - * - * This function is called by the MQTT client event loop. - * - * @param handler_args user data registered to the event. - * @param base Event base for the handler(always MQTT Base in this example). - * @param event_id The id for the received event. - * @param event_data The data for the event, esp_mqtt_event_handle_t. - */ -static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) -{ - ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%" PRIi32, base, event_id); - esp_mqtt_event_handle_t event = event_data; - esp_mqtt_client_handle_t client = event->client; - int msg_id; - switch ((esp_mqtt_event_id_t)event_id) { - case MQTT_EVENT_CONNECTED: - ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED"); - msg_id = esp_mqtt_client_subscribe(client, "/topic/qos0", 0); - ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id); - - msg_id = esp_mqtt_client_subscribe(client, "/topic/qos1", 1); - ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id); - - msg_id = esp_mqtt_client_unsubscribe(client, "/topic/qos1"); - ESP_LOGI(TAG, "sent unsubscribe successful, msg_id=%d", msg_id); - break; - case MQTT_EVENT_DISCONNECTED: - ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED"); - break; - - case MQTT_EVENT_SUBSCRIBED: - ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d, return code=0x%02x ", event->msg_id, (uint8_t)*event->data); - msg_id = esp_mqtt_client_publish(client, "/topic/qos0", "data", 0, 0, 0); - ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id); - break; - case MQTT_EVENT_UNSUBSCRIBED: - ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id); - break; - case MQTT_EVENT_PUBLISHED: - ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id); - break; - case MQTT_EVENT_DATA: - ESP_LOGI(TAG, "MQTT_EVENT_DATA"); - printf("TOPIC=%.*s\r\n", event->topic_len, event->topic); - printf("DATA=%.*s\r\n", event->data_len, event->data); - break; - case MQTT_EVENT_ERROR: - ESP_LOGI(TAG, "MQTT_EVENT_ERROR"); - if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) { - log_error_if_nonzero("reported from esp-tls", event->error_handle->esp_tls_last_esp_err); - log_error_if_nonzero("reported from tls stack", event->error_handle->esp_tls_stack_err); - log_error_if_nonzero("captured as transport's socket errno", event->error_handle->esp_transport_sock_errno); - ESP_LOGI(TAG, "Last errno string (%s)", strerror(event->error_handle->esp_transport_sock_errno)); - - } - break; - default: - ESP_LOGI(TAG, "Other event id:%d", event->event_id); - break; - } -} - -static void mqtt_app_start(void) -{ - const esp_mqtt_client_config_t mqtt_cfg = { - .broker.address.uri = "mqtts://test.mosquitto.org:8884", - .broker.verification.certificate = (const char *)server_cert_pem_start, - .credentials = { - .authentication = { - .certificate = (const char *)client_cert_pem_start, - .key = (const char *)client_key_pem_start, - }, - } - }; - - ESP_LOGI(TAG, "[APP] Free memory: %" PRIu32 " bytes", esp_get_free_heap_size()); - esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg); - /* The last argument may be used to pass data to the event handler, in this example mqtt_event_handler */ - esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL); - esp_mqtt_client_start(client); -} - -void app_main(void) -{ - ESP_LOGI(TAG, "[APP] Startup.."); - ESP_LOGI(TAG, "[APP] Free memory: %" PRIu32 " bytes", esp_get_free_heap_size()); - ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version()); - - esp_log_level_set("*", ESP_LOG_INFO); - esp_log_level_set("mqtt_client", ESP_LOG_VERBOSE); - esp_log_level_set("transport_base", ESP_LOG_VERBOSE); - esp_log_level_set("transport", ESP_LOG_VERBOSE); - esp_log_level_set("outbox", ESP_LOG_VERBOSE); - - ESP_ERROR_CHECK(nvs_flash_init()); - ESP_ERROR_CHECK(esp_netif_init()); - ESP_ERROR_CHECK(esp_event_loop_create_default()); - - /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. - * Read "Establishing Wi-Fi or Ethernet Connection" section in - * examples/protocols/README.md for more information about this function. - */ - ESP_ERROR_CHECK(example_connect()); - - mqtt_app_start(); -} diff --git a/examples/protocols/mqtt/ssl_mutual_auth/main/client.crt b/examples/protocols/mqtt/ssl_mutual_auth/main/client.crt deleted file mode 100644 index 7a3074b907e..00000000000 --- a/examples/protocols/mqtt/ssl_mutual_auth/main/client.crt +++ /dev/null @@ -1 +0,0 @@ -Please paste your client certificate here (follow instructions in README.md) diff --git a/examples/protocols/mqtt/ssl_mutual_auth/main/client.key b/examples/protocols/mqtt/ssl_mutual_auth/main/client.key deleted file mode 100644 index a956f850c4a..00000000000 --- a/examples/protocols/mqtt/ssl_mutual_auth/main/client.key +++ /dev/null @@ -1 +0,0 @@ -Please paste here your client key (follow instructions in README.md) diff --git a/examples/protocols/mqtt/ssl_mutual_auth/main/idf_component.yml b/examples/protocols/mqtt/ssl_mutual_auth/main/idf_component.yml deleted file mode 100644 index 718194867b7..00000000000 --- a/examples/protocols/mqtt/ssl_mutual_auth/main/idf_component.yml +++ /dev/null @@ -1,3 +0,0 @@ -dependencies: - protocol_examples_common: - path: ${IDF_PATH}/examples/common_components/protocol_examples_common diff --git a/examples/protocols/mqtt/ssl_psk/CMakeLists.txt b/examples/protocols/mqtt/ssl_psk/CMakeLists.txt deleted file mode 100644 index 6d376f6e968..00000000000 --- a/examples/protocols/mqtt/ssl_psk/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -# The following four lines of boilerplate have to be in your project's CMakeLists -# in this exact order for cmake to work correctly -cmake_minimum_required(VERSION 3.22) - - -include($ENV{IDF_PATH}/tools/cmake/project.cmake) -# "Trim" the build. Include the minimal set of components, main, and anything it depends on. -idf_build_set_property(MINIMAL_BUILD ON) -project(mqtt_ssl_psk) diff --git a/examples/protocols/mqtt/ssl_psk/README.md b/examples/protocols/mqtt/ssl_psk/README.md deleted file mode 100644 index d5dbb1b48e4..00000000000 --- a/examples/protocols/mqtt/ssl_psk/README.md +++ /dev/null @@ -1,78 +0,0 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | - -# ESP-MQTT SSL example with PSK verification - -(See the README.md file in the upper level 'examples' directory for more information about examples.) - -This example connects to a local broker configured to PSK authentication - -## How to use example - -### Hardware Required - -This example can be executed on any ESP32 board, the only required interface is WiFi (or ethernet) to connect to a MQTT -broker with preconfigured PSK verification method. - -#### Mosquitto settings -In case of using mosquitto broker, here is how to enable PSK authentication in `mosquitto.config`, -``` -psk_hint hint -psk_file path_to_your_psk_file -allow_anonymous true -``` -Note: Last line enables anonymous mode, as this example does not use mqtt username and password. - -PSK file then has to contain pairs of hints and keys, as shown below: -``` -hint:BAD123 -``` - -Important note: Keys are stored as text hexadecimal values in PSK file, while the example code stores key as plain binary -as required by MQTT API. (See the example source for details: `"BAD123" -> 0xBA, 0xD1, 0x23`) - -### Configure the project - -* Run `idf.py menuconfig` -* Configure Wi-Fi or Ethernet under "Example Connection Configuration" menu. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more details. - -### Build and Flash - - -(To exit the serial monitor, type ``Ctrl-]``.) - -See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects. - -## Example Output - -``` -I (2160) example_connect: Ethernet Link Up -I (4650) example_connect: Connected to Ethernet -I (4650) example_connect: IPv4 address: 192.168.0.1 -I (4650) MQTTS_EXAMPLE: [APP] Free memory: 244792 bytes -I (4660) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE -D (4670) MQTT_CLIENT: MQTT client_id=ESP32_c6B4F8 -D (4680) MQTT_CLIENT: Core selection disabled -I (4680) MQTTS_EXAMPLE: Other event id:7 -D (4680) esp-tls: host:192.168.0.2: strlen 13 -D (4700) esp-tls: ssl psk authentication -D (4700) esp-tls: handshake in progress... -D (4720) MQTT_CLIENT: Transport connected to mqtts://192.168.0.2:8883 -I (4720) MQTT_CLIENT: Sending MQTT CONNECT message, type: 1, id: 0000 -D (4720) MQTT_CLIENT: mqtt_message_receive: first byte: 0x20 -D (4730) MQTT_CLIENT: mqtt_message_receive: read "remaining length" byte: 0x2 -D (4730) MQTT_CLIENT: mqtt_message_receive: total message length: 4 (already read: 2) -D (4740) MQTT_CLIENT: mqtt_message_receive: read_len=2 -D (4750) MQTT_CLIENT: mqtt_message_receive: transport_read():4 4 -D (4750) MQTT_CLIENT: Connected -I (4760) MQTTS_EXAMPLE: MQTT_EVENT_CONNECTED -D (4760) MQTT_CLIENT: mqtt_enqueue id: 4837, type=8 successful -D (4770) OUTBOX: ENQUEUE msgid=4837, msg_type=8, len=18, size=18 -D (4770) MQTT_CLIENT: Sent subscribe topic=/topic/qos0, id: 4837, type=8 successful -I (4780) MQTTS_EXAMPLE: sent subscribe successful, msg_id=4837 -D (4790) MQTT_CLIENT: mqtt_enqueue id: 58982, type=8 successful -D (4790) OUTBOX: ENQUEUE msgid=58982, msg_type=8, len=18, size=36 -D (4800) MQTT_CLIENT: Sent subscribe topic=/topic/qos1, id: 58982, type=8 successful -I (4810) MQTTS_EXAMPLE: sent subscribe successful, msg_id=58982 -``` - diff --git a/examples/protocols/mqtt/ssl_psk/main/CMakeLists.txt b/examples/protocols/mqtt/ssl_psk/main/CMakeLists.txt deleted file mode 100644 index 31650f39dd1..00000000000 --- a/examples/protocols/mqtt/ssl_psk/main/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -idf_component_register(SRCS "app_main.c" - PRIV_REQUIRES mqtt esp_wifi nvs_flash - INCLUDE_DIRS ".") diff --git a/examples/protocols/mqtt/ssl_psk/main/app_main.c b/examples/protocols/mqtt/ssl_psk/main/app_main.c deleted file mode 100644 index ee9e81859e4..00000000000 --- a/examples/protocols/mqtt/ssl_psk/main/app_main.c +++ /dev/null @@ -1,151 +0,0 @@ -/* MQTT over SSL Example - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ - -#include -#include -#include -#include -#include "esp_wifi.h" -#include "esp_system.h" -#include "nvs_flash.h" -#include "esp_event.h" -#include "esp_netif.h" -#include "protocol_examples_common.h" - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/semphr.h" -#include "freertos/queue.h" - -#include "lwip/sockets.h" -#include "lwip/dns.h" -#include "lwip/netdb.h" - -#include "esp_log.h" -#include "mqtt_client.h" -#include "esp_tls.h" - -/* - * Add here URI of mqtt broker which supports PSK authentication - */ -#define EXAMPLE_BROKER_URI "mqtts://192.168.0.2" - -static const char *TAG = "mqtts_example"; - -/* - * Define psk key and hint as defined in mqtt broker - * example for mosquitto server, content of psk_file: - * hint:BAD123 - * - */ -static const uint8_t s_key[] = { 0xBA, 0xD1, 0x23 }; - -static const psk_hint_key_t psk_hint_key = { - .key = s_key, - .key_size = sizeof(s_key), - .hint = "hint" - }; - -/* - * @brief Event handler registered to receive MQTT events - * - * This function is called by the MQTT client event loop. - * - * @param handler_args user data registered to the event. - * @param base Event base for the handler(always MQTT Base in this example). - * @param event_id The id for the received event. - * @param event_data The data for the event, esp_mqtt_event_handle_t. - */ -static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) -{ - ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%" PRIi32 "", base, event_id); - esp_mqtt_event_handle_t event = event_data; - esp_mqtt_client_handle_t client = event->client; - int msg_id; - switch ((esp_mqtt_event_id_t)event_id) { - case MQTT_EVENT_CONNECTED: - ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED"); - msg_id = esp_mqtt_client_subscribe(client, "/topic/qos0", 0); - ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id); - - msg_id = esp_mqtt_client_subscribe(client, "/topic/qos1", 1); - ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id); - - msg_id = esp_mqtt_client_unsubscribe(client, "/topic/qos1"); - ESP_LOGI(TAG, "sent unsubscribe successful, msg_id=%d", msg_id); - break; - case MQTT_EVENT_DISCONNECTED: - ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED"); - break; - - case MQTT_EVENT_SUBSCRIBED: - ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d, return code=0x%02x ", event->msg_id, (uint8_t)*event->data); - msg_id = esp_mqtt_client_publish(client, "/topic/qos0", "data", 0, 0, 0); - ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id); - break; - case MQTT_EVENT_UNSUBSCRIBED: - ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id); - break; - case MQTT_EVENT_PUBLISHED: - ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id); - break; - case MQTT_EVENT_DATA: - ESP_LOGI(TAG, "MQTT_EVENT_DATA"); - printf("TOPIC=%.*s\r\n", event->topic_len, event->topic); - printf("DATA=%.*s\r\n", event->data_len, event->data); - break; - case MQTT_EVENT_ERROR: - ESP_LOGI(TAG, "MQTT_EVENT_ERROR"); - break; - default: - ESP_LOGI(TAG, "Other event id:%d", event->event_id); - break; - } -} - - -static void mqtt_app_start(void) -{ - const esp_mqtt_client_config_t mqtt_cfg = { - .broker.address.uri = EXAMPLE_BROKER_URI, - .broker.verification.psk_hint_key = &psk_hint_key, - }; - - ESP_LOGI(TAG, "[APP] Free memory: %" PRIu32 " bytes", esp_get_free_heap_size()); - esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg); - /* The last argument may be used to pass data to the event handler, in this example mqtt_event_handler */ - esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL); - esp_mqtt_client_start(client); -} - -void app_main(void) -{ - ESP_LOGI(TAG, "[APP] Startup.."); - ESP_LOGI(TAG, "[APP] Free memory: %" PRIu32 " bytes", esp_get_free_heap_size()); - ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version()); - - esp_log_level_set("*", ESP_LOG_INFO); - esp_log_level_set("mqtt_client", ESP_LOG_VERBOSE); - esp_log_level_set("transport_base", ESP_LOG_VERBOSE); - esp_log_level_set("esp-tls", ESP_LOG_VERBOSE); - esp_log_level_set("transport", ESP_LOG_VERBOSE); - esp_log_level_set("outbox", ESP_LOG_VERBOSE); - - ESP_ERROR_CHECK(nvs_flash_init()); - ESP_ERROR_CHECK(esp_netif_init()); - ESP_ERROR_CHECK(esp_event_loop_create_default()); - - /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. - * Read "Establishing Wi-Fi or Ethernet Connection" section in - * examples/protocols/README.md for more information about this function. - */ - ESP_ERROR_CHECK(example_connect()); - - mqtt_app_start(); -} diff --git a/examples/protocols/mqtt/ssl_psk/main/idf_component.yml b/examples/protocols/mqtt/ssl_psk/main/idf_component.yml deleted file mode 100644 index 718194867b7..00000000000 --- a/examples/protocols/mqtt/ssl_psk/main/idf_component.yml +++ /dev/null @@ -1,3 +0,0 @@ -dependencies: - protocol_examples_common: - path: ${IDF_PATH}/examples/common_components/protocol_examples_common diff --git a/examples/protocols/mqtt/ssl_psk/sdkconfig.defaults b/examples/protocols/mqtt/ssl_psk/sdkconfig.defaults deleted file mode 100644 index 1df83e8f392..00000000000 --- a/examples/protocols/mqtt/ssl_psk/sdkconfig.defaults +++ /dev/null @@ -1 +0,0 @@ -CONFIG_ESP_TLS_PSK_VERIFICATION=y diff --git a/examples/protocols/mqtt/tcp/README.md b/examples/protocols/mqtt/tcp/README.md deleted file mode 100644 index cb9f2cca07c..00000000000 --- a/examples/protocols/mqtt/tcp/README.md +++ /dev/null @@ -1,375 +0,0 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | - -# ESP-MQTT sample application -(See the README.md file in the upper level 'examples' directory for more information about examples.) - -This example connects to the broker URI selected using `idf.py menuconfig` (using mqtt tcp transport) and as a demonstration subscribes/unsubscribes and send a message on certain topic. -(Please note that the public broker is maintained by the community so may not be always available, for details please see this [disclaimer](https://iot.eclipse.org/getting-started/#sandboxes)) - -Note: If the URI equals `FROM_STDIN` then the broker address is read from stdin upon application startup (used for testing) - -It uses ESP-MQTT library which implements mqtt client to connect to mqtt broker. - -## How to use example - -### Hardware Required - -This example can be executed on any ESP32 board, the only required interface is WiFi and connection to internet. - -### Configure the project - -* Open the project configuration menu (`idf.py menuconfig`) -* Configure Wi-Fi or Ethernet under "Example Connection Configuration" menu. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more details. - -### Build and Flash - -Build the project and flash it to the board, then run monitor tool to view serial output: - -``` -idf.py -p PORT flash monitor -``` - -(To exit the serial monitor, type ``Ctrl-]``.) - -See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects. - -## Example Output - -``` -I (3714) event: sta ip: 192.168.0.139, mask: 255.255.255.0, gw: 192.168.0.2 -I (3714) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE -I (3964) MQTT_CLIENT: Sending MQTT CONNECT message, type: 1, id: 0000 -I (4164) MQTT_EXAMPLE: MQTT_EVENT_CONNECTED -I (4174) MQTT_EXAMPLE: sent publish successful, msg_id=41464 -I (4174) MQTT_EXAMPLE: sent subscribe successful, msg_id=17886 -I (4174) MQTT_EXAMPLE: sent subscribe successful, msg_id=42970 -I (4184) MQTT_EXAMPLE: sent unsubscribe successful, msg_id=50241 -I (4314) MQTT_EXAMPLE: MQTT_EVENT_PUBLISHED, msg_id=41464 -I (4484) MQTT_EXAMPLE: MQTT_EVENT_SUBSCRIBED, msg_id=17886 -I (4484) MQTT_EXAMPLE: sent publish successful, msg_id=0 -I (4684) MQTT_EXAMPLE: MQTT_EVENT_SUBSCRIBED, msg_id=42970 -I (4684) MQTT_EXAMPLE: sent publish successful, msg_id=0 -I (4884) MQTT_CLIENT: deliver_publish, message_length_read=19, message_length=19 -I (4884) MQTT_EXAMPLE: MQTT_EVENT_DATA -TOPIC=/topic/qos0 -DATA=data -I (5194) MQTT_CLIENT: deliver_publish, message_length_read=19, message_length=19 -I (5194) MQTT_EXAMPLE: MQTT_EVENT_DATA -TOPIC=/topic/qos0 -DATA=data -``` - -## Using Wi-Fi connection with ESP32P4 - -It is possible to use Wi-Fi connection on targets that do not support native Wi-Fi peripheral. This example demonstrates using `esp_wifi_remote` on ESP32P4 in the test configuration defined as `sdkconfig.ci.p4_wifi`. This configuration requires another ESP target with native Wi-Fi support physically connected to the ESP32-P4. - -This uses [esp_hosted](https://components.espressif.com/components/espressif/esp_hosted) project by default, please refer to its documentation for more details. -Note, that `esp_hosted` library currently transmits Wi-Fi credentials in plain text. In case this is a concern, please choose the `eppp` option in `esp_wifi_remote` configuration menu (`CONFIG_ESP_WIFI_REMOTE_LIBRARY_EPPP=y`) and setup master-slave verification (please see [eppp: Configure master-slave verification](#eppp)). - -### esp-hosted: Configure the slave project - -You first need to build and flash the slave project. It's possible to perform this action directly from the host project, these commands can be used to set the slave target device (for example ESP32C6), build and flash the slave project. You will have to hold the RST button to keep the host device (ESP32-P4) in reset while flashing the slave device. -``` -idf.py -C managed_components/espressif__esp_hosted/slave/ -B build_slave set-target esp32c6 -idf.py -C managed_components/espressif__esp_hosted/slave/ -B build_slave build flash monitor -``` - -### esp-hosted: Example Output of the slave device - -``` -I (348) cpu_start: Unicore app -I (357) cpu_start: Pro cpu start user code -I (357) cpu_start: cpu freq: 160000000 Hz -I (357) app_init: Application information: -I (360) app_init: Project name: network_adapter -I (365) app_init: App version: qa-test-full-master-esp32c5-202 -I (372) app_init: Compile time: Aug 30 2024 08:10:15 -I (378) app_init: ELF file SHA256: 6220fafe8... -I (383) app_init: ESP-IDF: v5.4-dev-2600-g1157a27964c-dirt -I (390) efuse_init: Min chip rev: v0.0 -I (395) efuse_init: Max chip rev: v0.99 -I (400) efuse_init: Chip rev: v0.1 -I (405) heap_init: Initializing. RAM available for dynamic allocation: -I (412) heap_init: At 4082FCD0 len 0004C940 (306 KiB): RAM -I (418) heap_init: At 4087C610 len 00002F54 (11 KiB): RAM -I (424) heap_init: At 50000000 len 00003FE8 (15 KiB): RTCRAM -I (432) spi_flash: detected chip: generic -I (435) spi_flash: flash io: dio -I (440) sleep_gpio: Configure to isolate all GPIO pins in sleep state -I (447) sleep_gpio: Enable automatic switching of GPIO sleep configuration -I (454) coexist: coex firmware version: 8da3f50af -I (481) coexist: coexist rom version 5b8dcfa -I (481) main_task: Started on CPU0 -I (481) main_task: Calling app_main() -I (482) fg_mcu_slave: ********************************************************************* -I (491) fg_mcu_slave: ESP-Hosted-MCU Slave FW version :: 0.0.6 -I (501) fg_mcu_slave: Transport used :: SDIO only -I (510) fg_mcu_slave: ********************************************************************* -I (519) fg_mcu_slave: Supported features are: -I (524) fg_mcu_slave: - WLAN over SDIO -I (528) h_bt: - BT/BLE -I (531) h_bt: - HCI Over SDIO -I (535) h_bt: - BLE only -I (539) fg_mcu_slave: capabilities: 0xd -I (543) fg_mcu_slave: Supported extended features are: -I (549) h_bt: - BT/BLE (extended) -I (553) fg_mcu_slave: extended capabilities: 0x0 -I (563) h_bt: ESP Bluetooth MAC addr: 40:4c:ca:5b:a0:8a -I (564) BLE_INIT: Using main XTAL as clock source -I (574) BLE_INIT: ble controller commit:[7491a85] -I (575) BLE_INIT: Bluetooth MAC: 40:4c:ca:5b:a0:8a -I (581) phy_init: phy_version 310,dde1ba9,Jun 4 2024,16:38:11 -I (641) phy: libbtbb version: 04952fd, Jun 4 2024, 16:38:26 -I (642) SDIO_SLAVE: Using SDIO interface -I (642) SDIO_SLAVE: sdio_init: sending mode: SDIO_SLAVE_SEND_STREAM -I (648) SDIO_SLAVE: sdio_init: ESP32-C6 SDIO RxQ[20] timing[0] - -I (1155) fg_mcu_slave: Start Data Path -I (1165) fg_mcu_slave: Initial set up done -I (1165) slave_ctrl: event ESPInit -``` - -### esp_hosted: Example Output of the master device (ESP32-P4) - -``` -I (1833) sdio_wrapper: Function 0 Blocksize: 512 -I (1843) sdio_wrapper: Function 1 Blocksize: 512 -I (1843) H_SDIO_DRV: SDIO Host operating in STREAMING MODE -I (1853) H_SDIO_DRV: generate slave intr -I (1863) transport: Received INIT event from ESP32 peripheral -I (1873) transport: EVENT: 12 -I (1873) transport: EVENT: 11 -I (1873) transport: capabilities: 0xd -I (1873) transport: Features supported are: -I (1883) transport: * WLAN -I (1883) transport: - HCI over SDIO -I (1893) transport: - BLE only -I (1893) transport: EVENT: 13 -I (1893) transport: ESP board type is : 13 - -I (1903) transport: Base transport is set-up - -I (1903) transport: Slave chip Id[12] -I (1913) hci_stub_drv: Host BT Support: Disabled -I (1913) H_SDIO_DRV: Received INIT event -I (1923) rpc_evt: EVENT: ESP INIT - -I (1923) rpc_wrap: Received Slave ESP Init -I (2703) rpc_core: <-- RPC_Req [0x116], uid 1 -I (2823) rpc_rsp: --> RPC_Resp [0x216], uid 1 -I (2823) rpc_core: <-- RPC_Req [0x139], uid 2 -I (2833) rpc_rsp: --> RPC_Resp [0x239], uid 2 -I (2833) rpc_core: <-- RPC_Req [0x104], uid 3 -I (2843) rpc_rsp: --> RPC_Resp [0x204], uid 3 -I (2843) rpc_core: <-- RPC_Req [0x118], uid 4 -I (2933) rpc_rsp: --> RPC_Resp [0x218], uid 4 -I (2933) example_connect: Connecting to Cermakowifi... -I (2933) rpc_core: <-- RPC_Req [0x11c], uid 5 -I (2943) rpc_evt: Event [0x2b] received -I (2943) rpc_evt: Event [0x2] received -I (2953) rpc_evt: EVT rcvd: Wi-Fi Start -I (2953) rpc_core: <-- RPC_Req [0x101], uid 6 -I (2973) rpc_rsp: --> RPC_Resp [0x21c], uid 5 -I (2973) H_API: esp_wifi_remote_connect -I (2973) rpc_core: <-- RPC_Req [0x11a], uid 7 -I (2983) rpc_rsp: --> RPC_Resp [0x201], uid 6 -I (3003) rpc_rsp: --> RPC_Resp [0x21a], uid 7 -I (3003) example_connect: Waiting for IP(s) -I (5723) rpc_evt: Event [0x2b] received -I (5943) esp_wifi_remote: esp_wifi_internal_reg_rxcb: sta: 0x400309fe -0x400309fe: wifi_sta_receive at /home/david/esp/idf/components/esp_wifi/src/wifi_netif.c:38 - -I (7573) example_connect: Got IPv6 event: Interface "example_netif_sta" address: fe80:0000:0000:0000:424c:caff:fe5b:a088, type: ESP_IP6_ADDR_IS_LINK_LOCAL -I (9943) esp_netif_handlers: example_netif_sta ip: 192.168.0.29, mask: 255.255.255.0, gw: 192.168.0.1 -I (9943) example_connect: Got IPv4 event: Interface "example_netif_sta" address: 192.168.0.29 -I (9943) example_common: Connected to example_netif_sta -I (9953) example_common: - IPv4 address: 192.168.0.29, -I (9963) example_common: - IPv6 address: fe80:0000:0000:0000:424c:caff:fe5b:a088, type: ESP_IP6_ADDR_IS_LINK_LOCAL -I (9973) mqtt_example: Other event id:7 -I (9973) main_task: Returned from app_main() -I (10253) mqtt_example: MQTT_EVENT_CONNECTED -I (10253) mqtt_example: sent publish successful, msg_id=45053 -I (10253) mqtt_example: sent subscribe successful, msg_id=34643 -I (10263) mqtt_example: sent subscribe successful, msg_id=2358 -I (10263) mqtt_example: sent unsubscribe successful, msg_id=57769 -I (10453) mqtt_example: MQTT_EVENT_PUBLISHED, msg_id=45053 -I (10603) mqtt_example: MQTT_EVENT_SUBSCRIBED, msg_id=34643 -I (10603) mqtt_example: sent publish successful, msg_id=0 -I (10603) mqtt_example: MQTT_EVENT_SUBSCRIBED, msg_id=2358 -I (10613) mqtt_example: sent publish successful, msg_id=0 -I (10613) mqtt_example: MQTT_EVENT_UNSUBSCRIBED, msg_id=57769 -I (10713) mqtt_example: MQTT_EVENT_DATA -TOPIC=/topic/qos0 -DATA=data -I (10863) mqtt_example: MQTT_EVENT_DATA -TOPIC=/topic/qos0 -DATA=data -``` - -### eppp: Configure master-slave verification - -In order to secure the physical connection between the ESP32-P4 (master) and the slave device, it is necessary to set certificates and keys for each side. -To bootstrap this step, you can use one-time generated self-signed RSA keys and certificates running: -``` -./managed_components/espressif__esp_wifi_remote/examples/test_certs/generate_test_certs.sh espressif.local -``` - -#### eppp: Configure the slave project - -It is recommended to create a new project from `esp_wifi_remote` component's example with -``` -idf.py create-project-from-example "espressif/esp_wifi_remote:server" -``` -but you can also build and flash the slave project directly from the `managed_components` directory using: -``` -idf.py -C managed_components/espressif__esp_wifi_remote/examples/server/ -B build_slave -``` - -Please follow these steps to setup the slave application: -* `idf.py set-target` -- choose the slave target (must support Wi-Fi) -* `idf.py menuconfig` -- configure the physical connection and verification details: - - `CONFIG_ESP_WIFI_REMOTE_EPPP_CLIENT_CA` -- CA for verifying ESP32-P4 application - - `CONFIG_ESP_WIFI_REMOTE_EPPP_SERVER_CRT` -- slave's certificate - - `CONFIG_ESP_WIFI_REMOTE_EPPP_SERVER_KEY` -- slave's private key -* `idf.py build flash monitor` - -#### eppp: Configure the master project (ESP32-P4) - -similarly to the slave project, we have to configure -* the physical connection -* the verification - - `CONFIG_ESP_WIFI_REMOTE_EPPP_SERVER_CA` -- CA for verifying the slave application - - `CONFIG_ESP_WIFI_REMOTE_EPPP_CLIENT_CRT` -- our own certificate - - `CONFIG_ESP_WIFI_REMOTE_EPPP_CLIENT_KEY` -- our own private key - -After project configuration, you build and flash the board with -``` -idf.py build flash monitor -``` - -### eppp: Example Output of the slave device - -``` -I (7982) main_task: Returned from app_main() -I (8242) rpc_server: Received header id 2 -I (8242) pp: pp rom version: 5b8dcfa -I (8242) net80211: net80211 rom version: 5b8dcfa -I (8252) wifi:wifi driver task: 4082be8c, prio:23, stack:6656, core=0 -I (8252) wifi:wifi firmware version: feaf82d -I (8252) wifi:wifi certification version: v7.0 -I (8252) wifi:config NVS flash: enabled -I (8262) wifi:config nano formatting: disabled -I (8262) wifi:mac_version:HAL_MAC_ESP32AX_761,ut_version:N, band:0x1 -I (8272) wifi:Init data frame dynamic rx buffer num: 32 -I (8272) wifi:Init static rx mgmt buffer num: 5 -I (8282) wifi:Init management short buffer num: 32 -I (8282) wifi:Init dynamic tx buffer num: 32 -I (8292) wifi:Init static tx FG buffer num: 2 -I (8292) wifi:Init static rx buffer size: 1700 (rxctrl:92, csi:512) -I (8302) wifi:Init static rx buffer num: 10 -I (8302) wifi:Init dynamic rx buffer num: 32 -I (8302) wifi_init: rx ba win: 6 -I (8312) wifi_init: accept mbox: 6 -I (8312) wifi_init: tcpip mbox: 32 -I (8322) wifi_init: udp mbox: 6 -I (8322) wifi_init: tcp mbox: 6 -I (8322) wifi_init: tcp tx win: 5760 -I (8332) wifi_init: tcp rx win: 5760 -I (8332) wifi_init: tcp mss: 1440 -I (8342) wifi_init: WiFi IRAM OP enabled -I (8342) wifi_init: WiFi RX IRAM OP enabled -I (8352) wifi_init: WiFi SLP IRAM OP enabled -I (8362) rpc_server: Received header id 11 -I (8362) rpc_server: Received header id 4 -I (8372) rpc_server: Received header id 6 -I (8372) phy_init: phy_version 270,339aa07,Apr 3 2024,16:36:11 -I (8492) wifi:enable tsf -I (8492) rpc_server: Received WIFI event 41 -I (8502) rpc_server: Received WIFI event 2 -I (8732) rpc_server: Received header id 10 -I (8742) rpc_server: Received header id 5 -I (8752) rpc_server: Received header id 8 -I (11452) wifi:new:<6,0>, old:<1,0>, ap:<255,255>, sta:<6,0>, prof:1, snd_ch_cfg:0x0 -I (11452) wifi:(connect)dot11_authmode:0x3, pairwise_cipher:0x3, group_cipher:0x1 -I (11452) wifi:state: init -> auth (0xb0) -I (11462) rpc_server: Received WIFI event 41 -I (11462) wifi:state: auth -> assoc (0x0) -I (11472) wifi:(assoc)RESP, Extended Capabilities length:8, operating_mode_notification:0 -I (11472) wifi:(assoc)RESP, Extended Capabilities, MBSSID:0, TWT Responder:0, OBSS Narrow Bandwidth RU In OFDMA Tolerance:0 -I (11482) wifi:Extended Capabilities length:8, operating_mode_notification:1 -I (11492) wifi:state: assoc -> run (0x10) -I (11492) wifi:(trc)phytype:CBW20-SGI, snr:50, maxRate:144, highestRateIdx:0 -W (11502) wifi:(trc)band:2G, phymode:3, highestRateIdx:0, lowestRateIdx:11, dataSchedTableSize:14 -I (11512) wifi:(trc)band:2G, rate(S-MCS7, rateIdx:0), ampdu(rate:S-MCS7, schedIdx(0, stop:8)), snr:50, ampduState:wait operational -I (11522) wifi:ifidx:0, rssi:-45, nf:-95, phytype(0x3, CBW20-SGI), phymode(0x3, 11bgn), max_rate:144, he:0, vht:0, ht:1 -I (11532) wifi:(ht)max.RxAMPDULenExponent:3(65535 bytes), MMSS:6(8 us) -W (11542) wifi:idx:0, ifx:0, tid:0, TAHI:0x1002cb4, TALO:0x1b942980, (ssn:0, win:64, cur_ssn:0), CONF:0xc0000005 -I (11572) wifi:connected with Cermakowifi, aid = 2, channel 6, BW20, bssid = 80:29:94:1b:b4:2c -I (11572) wifi:cipher(pairwise:0x3, group:0x1), pmf:0, security:WPA2-PSK, phy:11bgn, rssi:-45 -I (11582) wifi:pm start, type: 1, twt_start:0 - -I (11582) wifi:pm start, type:1, aid:0x2, trans-BSSID:80:29:94:1b:b4:2c, BSSID[5]:0x2c, mbssid(max-indicator:0, index:0), he:0 -I (11592) wifi:dp: 1, bi: 102400, li: 3, scale listen interval from 307200 us to 307200 us -I (11602) wifi:set rx beacon pti, rx_bcn_pti: 10, bcn_timeout: 25000, mt_pti: 10, mt_time: 10000 -I (11612) wifi:[ADDBA]TX addba request, tid:0, dialogtoken:1, bufsize:64, A-MSDU:0(not supported), policy:1(IMR), ssn:0(0x0) -I (11622) wifi:[ADDBA]TX addba request, tid:7, dialogtoken:2, bufsize:64, A-MSDU:0(not supported), policy:1(IMR), ssn:0(0x20) -I (11632) wifi:[ADDBA]TX addba request, tid:5, dialogtoken:3, bufsize:64, A-MSDU:0(not supported), policy:1(IMR), ssn:0(0x0) -I (11642) wifi:[ADDBA]RX addba response, status:0, tid:7/tb:0(0x1), bufsize:64, batimeout:0, txa_wnd:64 -I (11652) wifi:[ADDBA]RX addba response, status:0, tid:5/tb:0(0x1), bufsize:64, batimeout:0, txa_wnd:64 -I (11662) wifi:[ADDBA]RX addba response, status:0, tid:0/tb:1(0x1), bufsize:64, batimeout:0, txa_wnd:64 -I (11672) wifi:AP's beacon interval = 102400 us, DTIM period = 1 -I (11682) rpc_server: Received WIFI event 4 -I (15682) esp_netif_handlers: sta ip: 192.168.0.33, mask: 255.255.255.0, gw: 192.168.0.1 -I (15682) rpc_server: Received IP event 0 -I (15682) rpc_server: Main DNS:185.162.24.55 -I (15682) rpc_server: IP address:192.168.0.33 -``` - -### eppp: Example Output of the master device (ESP32-P4) - -``` -I (445) example_connect: Start example_connect. -I (455) uart: queue free spaces: 16 -I (455) eppp_link: Waiting for IP address 0 -I (3195) esp-netif_lwip-ppp: Connected -I (3195) eppp_link: Got IPv4 event: Interface "pppos_client(EPPP0)" address: 192.168.11.2 -I (3195) esp-netif_lwip-ppp: Connected -I (3195) eppp_link: Connected! 0 -I (5475) example_connect: Waiting for IP(s) -I (8405) esp_wifi_remote: esp_wifi_internal_reg_rxcb: sta: 0x4001c68a -I (9445) example_connect: Got IPv6 event: Interface "pppos_client" address: fe80:0000:0000:0000:5632:04ff:fe08:5054, type: ESP_IP6_ADDR_IS_LINK_LOCAL -I (12415) rpc_client: Main DNS:185.162.24.55 -I (12415) esp_netif_handlers: pppos_client ip: 192.168.11.2, mask: 255.255.255.255, gw: 192.168.11.1 -I (12415) rpc_client: EPPP IP:192.168.11.1 -I (12415) example_connect: Got IPv4 event: Interface "pppos_client" address: 192.168.11.2 -I (12425) rpc_client: WIFI IP:192.168.0.33 -I (12435) example_common: Connected to pppos_client -I (12445) rpc_client: WIFI GW:192.168.0.1 -I (12455) example_common: - IPv6 address: fe80:0000:0000:0000:5632:04ff:fe08:5054, type: ESP_IP6_ADDR_IS_LINK_LOCAL -I (12455) rpc_client: WIFI mask:255.255.255.0 -I (12465) example_common: Connected to pppos_client -I (12475) example_common: - IPv4 address: 192.168.11.2, -I (12475) example_common: - IPv6 address: fe80:0000:0000:0000:5c3b:1291:05ca:6dc8, type: ESP_IP6_ADDR_IS_LINK_LOCAL -I (12495) mqtt_example: Other event id:7 -I (12495) main_task: Returned from app_main() -I (12905) mqtt_example: MQTT_EVENT_CONNECTED -I (12905) mqtt_example: sent publish successful, msg_id=36013 -I (12905) mqtt_example: sent subscribe successful, msg_id=44233 -I (12905) mqtt_example: sent subscribe successful, msg_id=36633 -I (12915) mqtt_example: sent unsubscribe successful, msg_id=15480 -I (13115) mqtt_example: MQTT_EVENT_PUBLISHED, msg_id=36013 -I (13415) mqtt_example: MQTT_EVENT_SUBSCRIBED, msg_id=44233 -I (13415) mqtt_example: sent publish successful, msg_id=0 -I (13415) mqtt_example: MQTT_EVENT_SUBSCRIBED, msg_id=36633 -I (13415) mqtt_example: sent publish successful, msg_id=0 -I (13425) mqtt_example: MQTT_EVENT_DATA -TOPIC=/topic/qos1 -DATA=data_3 -I (13435) mqtt_example: MQTT_EVENT_UNSUBSCRIBED, msg_id=15480 -I (13615) mqtt_example: MQTT_EVENT_DATA -TOPIC=/topic/qos0 -DATA=data -I (13925) mqtt_example: MQTT_EVENT_DATA -TOPIC=/topic/qos0 -``` diff --git a/examples/protocols/mqtt/tcp/main/CMakeLists.txt b/examples/protocols/mqtt/tcp/main/CMakeLists.txt deleted file mode 100644 index 3bf739cf890..00000000000 --- a/examples/protocols/mqtt/tcp/main/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -idf_component_register(SRCS "app_main.c" - PRIV_REQUIRES mqtt nvs_flash esp_netif - INCLUDE_DIRS ".") diff --git a/examples/protocols/mqtt/tcp/main/Kconfig.projbuild b/examples/protocols/mqtt/tcp/main/Kconfig.projbuild deleted file mode 100644 index c11539fb8d2..00000000000 --- a/examples/protocols/mqtt/tcp/main/Kconfig.projbuild +++ /dev/null @@ -1,13 +0,0 @@ -menu "Example Configuration" - - config BROKER_URL - string "Broker URL" - default "mqtt://mqtt.eclipseprojects.io" - help - URL of the broker to connect to - - config BROKER_URL_FROM_STDIN - bool - default y if BROKER_URL = "FROM_STDIN" - -endmenu diff --git a/examples/protocols/mqtt/tcp/main/app_main.c b/examples/protocols/mqtt/tcp/main/app_main.c deleted file mode 100644 index 396aca6694a..00000000000 --- a/examples/protocols/mqtt/tcp/main/app_main.c +++ /dev/null @@ -1,162 +0,0 @@ -/* MQTT (over TCP) Example - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ - -#include -#include -#include -#include -#include -#include "esp_system.h" -#include "nvs_flash.h" -#include "esp_event.h" -#include "esp_netif.h" -#include "protocol_examples_common.h" - -#include "esp_log.h" -#include "mqtt_client.h" - -static const char *TAG = "mqtt_example"; - - -static void log_error_if_nonzero(const char *message, int error_code) -{ - if (error_code != 0) { - ESP_LOGE(TAG, "Last error %s: 0x%x", message, error_code); - } -} - -/* - * @brief Event handler registered to receive MQTT events - * - * This function is called by the MQTT client event loop. - * - * @param handler_args user data registered to the event. - * @param base Event base for the handler(always MQTT Base in this example). - * @param event_id The id for the received event. - * @param event_data The data for the event, esp_mqtt_event_handle_t. - */ -static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) -{ - ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%" PRIi32 "", base, event_id); - esp_mqtt_event_handle_t event = event_data; - esp_mqtt_client_handle_t client = event->client; - int msg_id; - switch ((esp_mqtt_event_id_t)event_id) { - case MQTT_EVENT_CONNECTED: - ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED"); - msg_id = esp_mqtt_client_publish(client, "/topic/qos1", "data_3", 0, 1, 0); - ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id); - - msg_id = esp_mqtt_client_subscribe(client, "/topic/qos0", 0); - ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id); - - msg_id = esp_mqtt_client_subscribe(client, "/topic/qos1", 1); - ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id); - - msg_id = esp_mqtt_client_unsubscribe(client, "/topic/qos1"); - ESP_LOGI(TAG, "sent unsubscribe successful, msg_id=%d", msg_id); - break; - case MQTT_EVENT_DISCONNECTED: - ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED"); - break; - - case MQTT_EVENT_SUBSCRIBED: - ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d, return code=0x%02x ", event->msg_id, (uint8_t)*event->data); - msg_id = esp_mqtt_client_publish(client, "/topic/qos0", "data", 0, 0, 0); - ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id); - break; - case MQTT_EVENT_UNSUBSCRIBED: - ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id); - break; - case MQTT_EVENT_PUBLISHED: - ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id); - break; - case MQTT_EVENT_DATA: - ESP_LOGI(TAG, "MQTT_EVENT_DATA"); - printf("TOPIC=%.*s\r\n", event->topic_len, event->topic); - printf("DATA=%.*s\r\n", event->data_len, event->data); - break; - case MQTT_EVENT_ERROR: - ESP_LOGI(TAG, "MQTT_EVENT_ERROR"); - if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) { - log_error_if_nonzero("reported from esp-tls", event->error_handle->esp_tls_last_esp_err); - log_error_if_nonzero("reported from tls stack", event->error_handle->esp_tls_stack_err); - log_error_if_nonzero("captured as transport's socket errno", event->error_handle->esp_transport_sock_errno); - ESP_LOGI(TAG, "Last errno string (%s)", strerror(event->error_handle->esp_transport_sock_errno)); - - } - break; - default: - ESP_LOGI(TAG, "Other event id:%d", event->event_id); - break; - } -} - -static void mqtt_app_start(void) -{ - esp_mqtt_client_config_t mqtt_cfg = { - .broker.address.uri = CONFIG_BROKER_URL, - }; -#if CONFIG_BROKER_URL_FROM_STDIN - char line[128]; - - if (strcmp(mqtt_cfg.broker.address.uri, "FROM_STDIN") == 0) { - int count = 0; - printf("Please enter url of mqtt broker\n"); - while (count < 128) { - int c = fgetc(stdin); - if (c == '\n') { - line[count] = '\0'; - break; - } else if (c > 0 && c < 127) { - line[count] = c; - ++count; - } - vTaskDelay(10 / portTICK_PERIOD_MS); - } - mqtt_cfg.broker.address.uri = line; - printf("Broker url: %s\n", line); - } else { - ESP_LOGE(TAG, "Configuration mismatch: wrong broker url"); - abort(); - } -#endif /* CONFIG_BROKER_URL_FROM_STDIN */ - - esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg); - /* The last argument may be used to pass data to the event handler, in this example mqtt_event_handler */ - esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL); - esp_mqtt_client_start(client); -} - -void app_main(void) -{ - ESP_LOGI(TAG, "[APP] Startup.."); - ESP_LOGI(TAG, "[APP] Free memory: %" PRIu32 " bytes", esp_get_free_heap_size()); - ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version()); - - esp_log_level_set("*", ESP_LOG_INFO); - esp_log_level_set("mqtt_client", ESP_LOG_VERBOSE); - esp_log_level_set("mqtt_example", ESP_LOG_VERBOSE); - esp_log_level_set("transport_base", ESP_LOG_VERBOSE); - esp_log_level_set("esp-tls", ESP_LOG_VERBOSE); - esp_log_level_set("transport", ESP_LOG_VERBOSE); - esp_log_level_set("outbox", ESP_LOG_VERBOSE); - - ESP_ERROR_CHECK(nvs_flash_init()); - ESP_ERROR_CHECK(esp_netif_init()); - ESP_ERROR_CHECK(esp_event_loop_create_default()); - - /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. - * Read "Establishing Wi-Fi or Ethernet Connection" section in - * examples/protocols/README.md for more information about this function. - */ - ESP_ERROR_CHECK(example_connect()); - - mqtt_app_start(); -} diff --git a/examples/protocols/mqtt/tcp/pytest_mqtt_tcp.py b/examples/protocols/mqtt/tcp/pytest_mqtt_tcp.py deleted file mode 100644 index f8deb23ff67..00000000000 --- a/examples/protocols/mqtt/tcp/pytest_mqtt_tcp.py +++ /dev/null @@ -1,97 +0,0 @@ -# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD -# SPDX-License-Identifier: Unlicense OR CC0-1.0 -import logging -import os -import socket -import struct -import sys -import time -from threading import Thread - -import pexpect -import pytest -from common_test_methods import get_host_ip4_by_dest_ip -from pytest_embedded import Dut -from pytest_embedded_idf.utils import idf_parametrize - -msgid = -1 - - -def mqqt_server_sketch(my_ip, port): # type: (str, str) -> None - global msgid - print('Starting the server on {}'.format(my_ip)) - s = None - try: - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - s.settimeout(60) - s.bind((my_ip, port)) - s.listen(1) - q, addr = s.accept() - q.settimeout(30) - print('connection accepted') - except Exception: - print( - 'Local server on {}:{} listening/accepting failure: {}' - 'Possibly check permissions or firewall settings' - 'to accept connections on this address'.format(my_ip, port, sys.exc_info()[0]) - ) - raise - data = q.recv(1024) - # check if received initial empty message - print('received from client {!r}'.format(data)) - data = bytearray([0x20, 0x02, 0x00, 0x00]) - q.send(data) - # try to receive qos1 - data = q.recv(1024) - msgid = struct.unpack('>H', data[15:17])[0] - print('received from client {!r}, msgid: {}'.format(data, msgid)) - data = bytearray([0x40, 0x02, data[15], data[16]]) - q.send(data) - time.sleep(5) - s.close() - print('server closed') - - -@pytest.mark.ethernet -@idf_parametrize('target', ['esp32'], indirect=['target']) -def test_examples_protocol_mqtt_qos1(dut: Dut) -> None: - global msgid - """ - steps: (QoS1: Happy flow) - 1. start the broker broker (with correctly sending ACK) - 2. DUT client connects to a broker and publishes qos1 message - 3. Test evaluates that qos1 message is queued and removed from queued after ACK received - 4. Test the broker received the same message id evaluated in step 3 - """ - # check and log bin size - binary_file = os.path.join(dut.app.binary_path, 'mqtt_tcp.bin') - bin_size = os.path.getsize(binary_file) - logging.info('[Performance][mqtt_tcp_bin_size]: %s KB', bin_size // 1024) - # waiting for getting the IP address - try: - ip_address = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)', timeout=30).group(1).decode() - print('Connected to AP/Ethernet with IP: {}'.format(ip_address)) - except pexpect.TIMEOUT: - raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP/Ethernet') - - # 2. start mqtt broker sketch - host_ip = get_host_ip4_by_dest_ip(ip_address) - thread1 = Thread(target=mqqt_server_sketch, args=(host_ip, 1883)) - thread1.start() - - data_write = 'mqtt://' + host_ip - print('writing to device: {}'.format(data_write)) - dut.write(data_write) - thread1.join() - print('Message id received from server: {}'.format(msgid)) - # 3. check the message id was enqueued and then deleted - msgid_enqueued = dut.expect(b'outbox: ENQUEUE msgid=([0-9]+)', timeout=30).group(1).decode() - msgid_deleted = dut.expect(b'outbox: DELETED msgid=([0-9]+)', timeout=30).group(1).decode() - # 4. check the msgid of received data are the same as that of enqueued and deleted from outbox - if msgid_enqueued == str(msgid) and msgid_deleted == str(msgid): - print('PASS: Received correct msg id') - else: - print('Failure!') - raise ValueError( - 'Mismatch of msgid: received: {}, enqueued {}, deleted {}'.format(msgid, msgid_enqueued, msgid_deleted) - ) diff --git a/examples/protocols/mqtt/tcp/sdkconfig.ci.p4_eppp b/examples/protocols/mqtt/tcp/sdkconfig.ci.p4_eppp deleted file mode 100644 index 8d423df4706..00000000000 --- a/examples/protocols/mqtt/tcp/sdkconfig.ci.p4_eppp +++ /dev/null @@ -1,5 +0,0 @@ -CONFIG_IDF_TARGET="esp32p4" -CONFIG_EXAMPLE_CONNECT_WIFI=y -CONFIG_ESP_WIFI_REMOTE_LIBRARY_EPPP=y -CONFIG_ESP_WIFI_REMOTE_EPPP_UART_TX_PIN=17 -CONFIG_ESP_WIFI_REMOTE_EPPP_UART_RX_PIN=16 diff --git a/examples/protocols/mqtt/tcp/sdkconfig.ci.p4_wifi b/examples/protocols/mqtt/tcp/sdkconfig.ci.p4_wifi deleted file mode 100644 index a2ea93a3597..00000000000 --- a/examples/protocols/mqtt/tcp/sdkconfig.ci.p4_wifi +++ /dev/null @@ -1,3 +0,0 @@ -CONFIG_IDF_TARGET="esp32p4" -CONFIG_EXAMPLE_CONNECT_WIFI=y -CONFIG_ESP_WIFI_REMOTE_LIBRARY_HOSTED=y diff --git a/examples/protocols/mqtt/tcp/sdkconfig.ci.ppp_connect b/examples/protocols/mqtt/tcp/sdkconfig.ci.ppp_connect deleted file mode 100644 index 7366a909ec9..00000000000 --- a/examples/protocols/mqtt/tcp/sdkconfig.ci.ppp_connect +++ /dev/null @@ -1,3 +0,0 @@ -CONFIG_EXAMPLE_CONNECT_WIFI=n -CONFIG_EXAMPLE_CONNECT_PPP=y -CONFIG_EXAMPLE_CONNECT_PPP_DEVICE_UART=y diff --git a/examples/protocols/mqtt/ws/CMakeLists.txt b/examples/protocols/mqtt/ws/CMakeLists.txt deleted file mode 100644 index e6853e080b2..00000000000 --- a/examples/protocols/mqtt/ws/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -# The following four lines of boilerplate have to be in your project's CMakeLists -# in this exact order for cmake to work correctly -cmake_minimum_required(VERSION 3.22) - - -include($ENV{IDF_PATH}/tools/cmake/project.cmake) -# "Trim" the build. Include the minimal set of components, main, and anything it depends on. -idf_build_set_property(MINIMAL_BUILD ON) -project(mqtt_websocket) diff --git a/examples/protocols/mqtt/ws/README.md b/examples/protocols/mqtt/ws/README.md deleted file mode 100644 index 5d1724fd31b..00000000000 --- a/examples/protocols/mqtt/ws/README.md +++ /dev/null @@ -1,61 +0,0 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | - -# ESP-MQTT MQTT over Websocket - -(See the README.md file in the upper level 'examples' directory for more information about examples.) - -This example connects to the broker mqtt.eclipseprojects.io over web sockets as a demonstration subscribes/unsubscribes and send a message on certain topic. -(Please note that the public broker is maintained by the community so may not be always available, for details please see this [disclaimer](https://iot.eclipse.org/getting-started/#sandboxes)) - -It uses ESP-MQTT library which implements mqtt client to connect to mqtt broker. - -## How to use example - -### Hardware Required - -This example can be executed on any ESP32 board, the only required interface is WiFi and connection to internet. - -### Configure the project - -* Open the project configuration menu (`idf.py menuconfig`) -* Configure Wi-Fi or Ethernet under "Example Connection Configuration" menu. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more details. - -### Build and Flash - -Build the project and flash it to the board, then run monitor tool to view serial output: - -``` -idf.py -p PORT flash monitor -``` - -(To exit the serial monitor, type ``Ctrl-]``.) - -See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects. - -## Example Output - -``` -I (3714) event: sta ip: 192.168.0.139, mask: 255.255.255.0, gw: 192.168.0.2 -I (3714) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE -I (3964) MQTT_CLIENT: Sending MQTT CONNECT message, type: 1, id: 0000 -I (4164) MQTTWS_EXAMPLE: MQTT_EVENT_CONNECTED -I (4174) MQTTWS_EXAMPLE: sent publish successful, msg_id=41464 -I (4174) MQTTWS_EXAMPLE: sent subscribe successful, msg_id=17886 -I (4174) MQTTWS_EXAMPLE: sent subscribe successful, msg_id=42970 -I (4184) MQTTWS_EXAMPLE: sent unsubscribe successful, msg_id=50241 -I (4314) MQTTWS_EXAMPLE: MQTT_EVENT_PUBLISHED, msg_id=41464 -I (4484) MQTTWS_EXAMPLE: MQTT_EVENT_SUBSCRIBED, msg_id=17886 -I (4484) MQTTWS_EXAMPLE: sent publish successful, msg_id=0 -I (4684) MQTTWS_EXAMPLE: MQTT_EVENT_SUBSCRIBED, msg_id=42970 -I (4684) MQTTWS_EXAMPLE: sent publish successful, msg_id=0 -I (4884) MQTT_CLIENT: deliver_publish, message_length_read=19, message_length=19 -I (4884) MQTTWS_EXAMPLE: MQTT_EVENT_DATA -TOPIC=/topic/qos0 -DATA=data -I (5194) MQTT_CLIENT: deliver_publish, message_length_read=19, message_length=19 -I (5194) MQTTWS_EXAMPLE: MQTT_EVENT_DATA -TOPIC=/topic/qos0 -DATA=data -``` - diff --git a/examples/protocols/mqtt/ws/main/CMakeLists.txt b/examples/protocols/mqtt/ws/main/CMakeLists.txt deleted file mode 100644 index 31650f39dd1..00000000000 --- a/examples/protocols/mqtt/ws/main/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -idf_component_register(SRCS "app_main.c" - PRIV_REQUIRES mqtt esp_wifi nvs_flash - INCLUDE_DIRS ".") diff --git a/examples/protocols/mqtt/ws/main/Kconfig.projbuild b/examples/protocols/mqtt/ws/main/Kconfig.projbuild deleted file mode 100644 index e547a5156cd..00000000000 --- a/examples/protocols/mqtt/ws/main/Kconfig.projbuild +++ /dev/null @@ -1,9 +0,0 @@ -menu "Example Configuration" - - config BROKER_URI - string "Broker URL" - default "ws://mqtt.eclipseprojects.io:80/mqtt" - help - URL of an mqtt broker which this example connects to. - -endmenu diff --git a/examples/protocols/mqtt/ws/main/app_main.c b/examples/protocols/mqtt/ws/main/app_main.c deleted file mode 100644 index f518fdfacc5..00000000000 --- a/examples/protocols/mqtt/ws/main/app_main.c +++ /dev/null @@ -1,144 +0,0 @@ -/* MQTT over Websockets Example - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ -#include -#include -#include -#include -#include "esp_wifi.h" -#include "esp_system.h" -#include "nvs_flash.h" -#include "esp_event.h" -#include "esp_netif.h" -#include "protocol_examples_common.h" - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/semphr.h" -#include "freertos/queue.h" - -#include "lwip/sockets.h" -#include "lwip/dns.h" -#include "lwip/netdb.h" - -#include "esp_log.h" -#include "mqtt_client.h" - -static const char *TAG = "mqttws_example"; - -static void log_error_if_nonzero(const char *message, int error_code) -{ - if (error_code != 0) { - ESP_LOGE(TAG, "Last error %s: 0x%x", message, error_code); - } -} - -/* - * @brief Event handler registered to receive MQTT events - * - * This function is called by the MQTT client event loop. - * - * @param handler_args user data registered to the event. - * @param base Event base for the handler(always MQTT Base in this example). - * @param event_id The id for the received event. - * @param event_data The data for the event, esp_mqtt_event_handle_t. - */ -static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) -{ - ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%" PRIi32, base, event_id); - esp_mqtt_event_handle_t event = event_data; - esp_mqtt_client_handle_t client = event->client; - int msg_id; - switch ((esp_mqtt_event_id_t)event_id) { - case MQTT_EVENT_CONNECTED: - ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED"); - msg_id = esp_mqtt_client_publish(client, "/topic/qos1", "data_3", 0, 1, 0); - ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id); - msg_id = esp_mqtt_client_subscribe(client, "/topic/qos0", 0); - ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id); - - msg_id = esp_mqtt_client_subscribe(client, "/topic/qos1", 1); - ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id); - - msg_id = esp_mqtt_client_unsubscribe(client, "/topic/qos1"); - ESP_LOGI(TAG, "sent unsubscribe successful, msg_id=%d", msg_id); - break; - case MQTT_EVENT_DISCONNECTED: - ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED"); - break; - - case MQTT_EVENT_SUBSCRIBED: - ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d, return code=0x%02x ", event->msg_id, (uint8_t)*event->data); - msg_id = esp_mqtt_client_publish(client, "/topic/qos0", "data", 0, 0, 0); - ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id); - break; - case MQTT_EVENT_UNSUBSCRIBED: - ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id); - break; - case MQTT_EVENT_PUBLISHED: - ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id); - break; - case MQTT_EVENT_DATA: - ESP_LOGI(TAG, "MQTT_EVENT_DATA"); - printf("TOPIC=%.*s\r\n", event->topic_len, event->topic); - printf("DATA=%.*s\r\n", event->data_len, event->data); - break; - case MQTT_EVENT_ERROR: - ESP_LOGI(TAG, "MQTT_EVENT_ERROR"); - if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) { - log_error_if_nonzero("reported from esp-tls", event->error_handle->esp_tls_last_esp_err); - log_error_if_nonzero("reported from tls stack", event->error_handle->esp_tls_stack_err); - log_error_if_nonzero("captured as transport's socket errno", event->error_handle->esp_transport_sock_errno); - ESP_LOGI(TAG, "Last errno string (%s)", strerror(event->error_handle->esp_transport_sock_errno)); - - } - break; - default: - ESP_LOGI(TAG, "Other event id:%d", event->event_id); - break; - } -} - -static void mqtt_app_start(void) -{ - const esp_mqtt_client_config_t mqtt_cfg = { - .broker.address.uri = CONFIG_BROKER_URI, - }; - - esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg); - /* The last argument may be used to pass data to the event handler, in this example mqtt_event_handler */ - esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL); - esp_mqtt_client_start(client); -} - -void app_main(void) -{ - ESP_LOGI(TAG, "[APP] Startup.."); - ESP_LOGI(TAG, "[APP] Free memory: %" PRIu32 " bytes", esp_get_free_heap_size()); - ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version()); - - esp_log_level_set("*", ESP_LOG_INFO); - esp_log_level_set("mqtt_client", ESP_LOG_VERBOSE); - esp_log_level_set("mqtt_example", ESP_LOG_VERBOSE); - esp_log_level_set("transport_base", ESP_LOG_VERBOSE); - esp_log_level_set("transport_ws", ESP_LOG_VERBOSE); - esp_log_level_set("transport", ESP_LOG_VERBOSE); - esp_log_level_set("outbox", ESP_LOG_VERBOSE); - - ESP_ERROR_CHECK(nvs_flash_init()); - ESP_ERROR_CHECK(esp_netif_init()); - ESP_ERROR_CHECK(esp_event_loop_create_default()); - - /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. - * Read "Establishing Wi-Fi or Ethernet Connection" section in - * examples/protocols/README.md for more information about this function. - */ - ESP_ERROR_CHECK(example_connect()); - - mqtt_app_start(); -} diff --git a/examples/protocols/mqtt/ws/main/idf_component.yml b/examples/protocols/mqtt/ws/main/idf_component.yml deleted file mode 100644 index 718194867b7..00000000000 --- a/examples/protocols/mqtt/ws/main/idf_component.yml +++ /dev/null @@ -1,3 +0,0 @@ -dependencies: - protocol_examples_common: - path: ${IDF_PATH}/examples/common_components/protocol_examples_common diff --git a/examples/protocols/mqtt/ws/pytest_mqtt_ws_example.py b/examples/protocols/mqtt/ws/pytest_mqtt_ws_example.py deleted file mode 100644 index 3ad6bd74260..00000000000 --- a/examples/protocols/mqtt/ws/pytest_mqtt_ws_example.py +++ /dev/null @@ -1,108 +0,0 @@ -#!/usr/bin/env python -# -# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD -# SPDX-License-Identifier: Unlicense OR CC0-1.0 -import logging -import os -import re -import sys -from threading import Event -from threading import Thread - -import paho.mqtt.client as mqtt -import pytest -from pytest_embedded import Dut -from pytest_embedded_idf.utils import idf_parametrize - -event_client_connected = Event() -event_stop_client = Event() -event_client_received_correct = Event() -message_log = '' - - -# The callback for when the client receives a CONNACK response from the server. -def on_connect(client, userdata, flags, rc): # type: (mqtt.Client, tuple, bool, str) -> None - _ = (userdata, flags) - print('Connected with result code ' + str(rc)) - event_client_connected.set() - client.subscribe('/topic/qos0') - - -def mqtt_client_task(client): # type: (mqtt.Client) -> None - while not event_stop_client.is_set(): - client.loop() - - -# The callback for when a PUBLISH message is received from the server. -def on_message(client, userdata, msg): # type: (mqtt.Client, tuple, mqtt.client.MQTTMessage) -> None - _ = userdata - global message_log - payload = msg.payload.decode() - if not event_client_received_correct.is_set() and payload == 'data': - client.publish('/topic/qos0', 'data_to_esp32') - if msg.topic == '/topic/qos0' and payload == 'data': - event_client_received_correct.set() - message_log += 'Received data:' + msg.topic + ' ' + payload + '\n' - - -@pytest.mark.ethernet -@idf_parametrize('target', ['esp32'], indirect=['target']) -def test_examples_protocol_mqtt_ws(dut): # type: (Dut) -> None - broker_url = '' - broker_port = 0 - """ - steps: | - 1. join AP and connects to ws broker - 2. Test connects a client to the same broker - 3. Test evaluates it received correct qos0 message - 4. Test ESP32 client received correct qos0 message - """ - # check and log bin size - binary_file = os.path.join(dut.app.binary_path, 'mqtt_websocket.bin') - bin_size = os.path.getsize(binary_file) - logging.info('[Performance][mqtt_websocket_bin_size]: %s KB', bin_size // 1024) - # Look for host:port in sdkconfig - try: - value = re.search(r'\:\/\/([^:]+)\:([0-9]+)', dut.app.sdkconfig.get('BROKER_URI')) - assert value is not None - broker_url = value.group(1) - broker_port = int(value.group(2)) - except Exception: - print('ENV_TEST_FAILURE: Cannot find broker url in sdkconfig') - raise - client = None - # 1. Test connects to a broker - try: - client = mqtt.Client(transport='websockets') - client.on_connect = on_connect - client.on_message = on_message - print('Connecting...') - client.connect(broker_url, broker_port, 60) - except Exception: - print( - 'ENV_TEST_FAILURE: Unexpected error while connecting to broker {}: {}:'.format( - broker_url, sys.exc_info()[0] - ) - ) - raise - # Starting a py-client in a separate thread - thread1 = Thread(target=mqtt_client_task, args=(client,)) - thread1.start() - try: - print('Connecting py-client to broker {}:{}...'.format(broker_url, broker_port)) - if not event_client_connected.wait(timeout=30): - raise ValueError('ENV_TEST_FAILURE: Test script cannot connect to broker: {}'.format(broker_url)) - try: - ip_address = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[0] - print('Connected to AP with IP: {}'.format(ip_address)) - except Dut.ExpectTimeout: - print('ENV_TEST_FAILURE: Cannot connect to AP') - raise - print('Checking py-client received msg published from esp...') - if not event_client_received_correct.wait(timeout=30): - raise ValueError('Wrong data received, msg log: {}'.format(message_log)) - print('Checking esp-client received msg published from py-client...') - dut.expect(r'DATA=data_to_esp32', timeout=30) - finally: - event_stop_client.set() - thread1.join() diff --git a/examples/protocols/mqtt/ws/sdkconfig.ci b/examples/protocols/mqtt/ws/sdkconfig.ci deleted file mode 100644 index 50da43291ac..00000000000 --- a/examples/protocols/mqtt/ws/sdkconfig.ci +++ /dev/null @@ -1,11 +0,0 @@ -CONFIG_BROKER_URI="ws://${EXAMPLE_MQTT_BROKER_WS}/ws" -CONFIG_EXAMPLE_CONNECT_ETHERNET=y -CONFIG_EXAMPLE_CONNECT_WIFI=n -CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y -CONFIG_EXAMPLE_ETH_PHY_GENERIC=y -CONFIG_EXAMPLE_ETH_MDC_GPIO=23 -CONFIG_EXAMPLE_ETH_MDIO_GPIO=18 -CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5 -CONFIG_EXAMPLE_ETH_PHY_ADDR=1 -CONFIG_EXAMPLE_CONNECT_IPV6=y -CONFIG_LWIP_CHECK_THREAD_SAFETY=y diff --git a/examples/protocols/mqtt/wss/CMakeLists.txt b/examples/protocols/mqtt/wss/CMakeLists.txt deleted file mode 100644 index f02bf83c198..00000000000 --- a/examples/protocols/mqtt/wss/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -# The following four lines of boilerplate have to be in your project's CMakeLists -# in this exact order for cmake to work correctly -cmake_minimum_required(VERSION 3.22) - - -include($ENV{IDF_PATH}/tools/cmake/project.cmake) -# "Trim" the build. Include the minimal set of components, main, and anything it depends on. -idf_build_set_property(MINIMAL_BUILD ON) -project(mqtt_websocket_secure) - -target_add_binary_data(${PROJECT_NAME}.elf "main/mqtt_eclipseprojects_io.pem" TEXT) diff --git a/examples/protocols/mqtt/wss/README.md b/examples/protocols/mqtt/wss/README.md deleted file mode 100644 index b401d3191ce..00000000000 --- a/examples/protocols/mqtt/wss/README.md +++ /dev/null @@ -1,73 +0,0 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | - -# ESP-MQTT MQTT over WSS Sample application -(See the README.md file in the upper level 'examples' directory for more information about examples.) - -This example connects to the broker mqtt.eclipseprojects.io over secure websockets and as a demonstration subscribes/unsubscribes and send a message on certain topic. -(Please note that the public broker is maintained by the community so may not be always available, for details please see this [disclaimer](https://iot.eclipse.org/getting-started/#sandboxes)) - -It uses ESP-MQTT library which implements mqtt client to connect to mqtt broker. - -## How to use example - -### Hardware Required - -This example can be executed on any ESP32 board, the only required interface is WiFi and connection to internet. - -### Configure the project - -* Open the project configuration menu (`idf.py menuconfig`) -* Configure Wi-Fi or Ethernet under "Example Connection Configuration" menu. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more details. - -Note how to create a PEM certificate for mqtt.eclipseprojects.io: - -PEM certificate for this example could be extracted from an openssl `s_client` command connecting to mqtt.eclipseprojects.io. -In case a host operating system has `openssl` and `sed` packages installed, one could execute the following command to download and save the root certificate to a file (Note for Windows users: Both Linux like environment or Windows native packages may be used). -``` -echo "" | openssl s_client -showcerts -connect mqtt.eclipseprojects.io:443 | sed -n "1,/Root/d; /BEGIN/,/END/p" | openssl x509 -outform PEM >mqtt_eclipse_org.pem -``` -Please note that this is not a general command for downloading a root certificate for an arbitrary host; -this command works with mqtt.eclipseprojects.io as the site provides root certificate in the chain, which then could be extracted -with text operation. - -### Build and Flash - -Build the project and flash it to the board, then run monitor tool to view serial output: - -``` -idf.py -p PORT flash monitor -``` - -(To exit the serial monitor, type ``Ctrl-]``.) - -See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects. - -## Example Output - -``` -I (3714) event: sta ip: 192.168.0.139, mask: 255.255.255.0, gw: 192.168.0.2 -I (3714) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE -I (3964) MQTT_CLIENT: Sending MQTT CONNECT message, type: 1, id: 0000 -I (4164) MQTTWSS_EXAMPLE: MQTT_EVENT_CONNECTED -I (4174) MQTTWSS_EXAMPLE: sent publish successful, msg_id=41464 -I (4174) MQTTWSS_EXAMPLE: sent subscribe successful, msg_id=17886 -I (4174) MQTTWSS_EXAMPLE: sent subscribe successful, msg_id=42970 -I (4184) MQTTWSS_EXAMPLE: sent unsubscribe successful, msg_id=50241 -I (4314) MQTTWSS_EXAMPLE: MQTT_EVENT_PUBLISHED, msg_id=41464 -I (4484) MQTTWSS_EXAMPLE: MQTT_EVENT_SUBSCRIBED, msg_id=17886 -I (4484) MQTTWSS_EXAMPLE: sent publish successful, msg_id=0 -I (4684) MQTTWSS_EXAMPLE: MQTT_EVENT_SUBSCRIBED, msg_id=42970 -I (4684) MQTTWSS_EXAMPLE: sent publish successful, msg_id=0 -I (4884) MQTT_CLIENT: deliver_publish, message_length_read=19, message_length=19 -I (4884) MQTTWSS_EXAMPLE: MQTT_EVENT_DATA -TOPIC=/topic/qos0 -DATA=data -I (5194) MQTT_CLIENT: deliver_publish, message_length_read=19, message_length=19 -I (5194) MQTTWSS_EXAMPLE: MQTT_EVENT_DATA -TOPIC=/topic/qos0 -DATA=data -``` - - - diff --git a/examples/protocols/mqtt/wss/main/CMakeLists.txt b/examples/protocols/mqtt/wss/main/CMakeLists.txt deleted file mode 100644 index 31650f39dd1..00000000000 --- a/examples/protocols/mqtt/wss/main/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -idf_component_register(SRCS "app_main.c" - PRIV_REQUIRES mqtt esp_wifi nvs_flash - INCLUDE_DIRS ".") diff --git a/examples/protocols/mqtt/wss/main/Kconfig.projbuild b/examples/protocols/mqtt/wss/main/Kconfig.projbuild deleted file mode 100644 index b6d1f593ddf..00000000000 --- a/examples/protocols/mqtt/wss/main/Kconfig.projbuild +++ /dev/null @@ -1,20 +0,0 @@ -menu "Example Configuration" - - config BROKER_URI - string "Broker URL" - default "wss://mqtt.eclipseprojects.io:443/mqtt" - help - URL of an mqtt broker which this example connects to. - - config BROKER_CERTIFICATE_OVERRIDE - string "Server certificate override" - default "" - help - Please leave empty if server certificate included from a textfile; otherwise fill in a base64 part of PEM - format certificate - - config BROKER_CERTIFICATE_OVERRIDDEN - bool - default y if BROKER_CERTIFICATE_OVERRIDE != "" - -endmenu diff --git a/examples/protocols/mqtt/wss/main/app_main.c b/examples/protocols/mqtt/wss/main/app_main.c deleted file mode 100644 index 3de96c0b9c7..00000000000 --- a/examples/protocols/mqtt/wss/main/app_main.c +++ /dev/null @@ -1,135 +0,0 @@ -/* MQTT over Secure Websockets Example - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ -#include -#include -#include -#include -#include "esp_wifi.h" -#include "esp_system.h" -#include "nvs_flash.h" -#include "esp_event.h" -#include "esp_netif.h" -#include "protocol_examples_common.h" - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/semphr.h" -#include "freertos/queue.h" - -#include "lwip/sockets.h" -#include "lwip/dns.h" -#include "lwip/netdb.h" - -#include "esp_log.h" -#include "mqtt_client.h" - -static const char *TAG = "mqttwss_example"; - - -#if CONFIG_BROKER_CERTIFICATE_OVERRIDDEN == 1 -static const uint8_t mqtt_eclipseprojects_io_pem_start[] = "-----BEGIN CERTIFICATE-----\n" CONFIG_BROKER_CERTIFICATE_OVERRIDE "\n-----END CERTIFICATE-----"; -#else -extern const uint8_t mqtt_eclipseprojects_io_pem_start[] asm("_binary_mqtt_eclipseprojects_io_pem_start"); -#endif -extern const uint8_t mqtt_eclipseprojects_io_pem_end[] asm("_binary_mqtt_eclipseprojects_io_pem_end"); - -static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event) -{ - esp_mqtt_client_handle_t client = event->client; - int msg_id; - // your_context_t *context = event->context; - switch (event->event_id) { - case MQTT_EVENT_CONNECTED: - ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED"); - msg_id = esp_mqtt_client_subscribe(client, "/topic/qos0", 0); - ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id); - - msg_id = esp_mqtt_client_subscribe(client, "/topic/qos1", 1); - ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id); - - msg_id = esp_mqtt_client_unsubscribe(client, "/topic/qos1"); - ESP_LOGI(TAG, "sent unsubscribe successful, msg_id=%d", msg_id); - break; - case MQTT_EVENT_DISCONNECTED: - ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED"); - break; - - case MQTT_EVENT_SUBSCRIBED: - ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d, return code=0x%02x ", event->msg_id, (uint8_t)*event->data); - msg_id = esp_mqtt_client_publish(client, "/topic/qos0", "data", 0, 0, 0); - ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id); - break; - case MQTT_EVENT_UNSUBSCRIBED: - ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id); - break; - case MQTT_EVENT_PUBLISHED: - ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id); - break; - case MQTT_EVENT_DATA: - ESP_LOGI(TAG, "MQTT_EVENT_DATA"); - printf("TOPIC=%.*s\r\n", event->topic_len, event->topic); - printf("DATA=%.*s\r\n", event->data_len, event->data); - break; - case MQTT_EVENT_ERROR: - ESP_LOGI(TAG, "MQTT_EVENT_ERROR"); - break; - default: - ESP_LOGI(TAG, "Other event id:%d", event->event_id); - break; - } - return ESP_OK; -} - -static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) -{ - /* The argument passed to esp_mqtt_client_register_event can de accessed as handler_args*/ - ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%" PRIi32, base, event_id); - mqtt_event_handler_cb(event_data); -} - -static void mqtt_app_start(void) -{ - const esp_mqtt_client_config_t mqtt_cfg = { - .broker.address.uri = CONFIG_BROKER_URI, - .broker.verification.certificate = (const char *)mqtt_eclipseprojects_io_pem_start, - }; - - ESP_LOGI(TAG, "[APP] Free memory: %" PRIu32 " bytes", esp_get_free_heap_size()); - esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg); - /* The last argument may be used to pass data to the event handler, in this example mqtt_event_handler */ - esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL); - - esp_mqtt_client_start(client); -} - -void app_main(void) -{ - ESP_LOGI(TAG, "[APP] Startup.."); - ESP_LOGI(TAG, "[APP] Free memory: %" PRIu32 " bytes", esp_get_free_heap_size()); - ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version()); - - esp_log_level_set("*", ESP_LOG_INFO); - esp_log_level_set("mqtt_client", ESP_LOG_VERBOSE); - esp_log_level_set("mqtt_example", ESP_LOG_VERBOSE); - esp_log_level_set("transport_base", ESP_LOG_VERBOSE); - esp_log_level_set("transport", ESP_LOG_VERBOSE); - esp_log_level_set("outbox", ESP_LOG_VERBOSE); - - ESP_ERROR_CHECK(nvs_flash_init()); - ESP_ERROR_CHECK(esp_netif_init()); - ESP_ERROR_CHECK(esp_event_loop_create_default()); - - /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. - * Read "Establishing Wi-Fi or Ethernet Connection" section in - * examples/protocols/README.md for more information about this function. - */ - ESP_ERROR_CHECK(example_connect()); - - mqtt_app_start(); -} diff --git a/examples/protocols/mqtt/wss/main/idf_component.yml b/examples/protocols/mqtt/wss/main/idf_component.yml deleted file mode 100644 index 718194867b7..00000000000 --- a/examples/protocols/mqtt/wss/main/idf_component.yml +++ /dev/null @@ -1,3 +0,0 @@ -dependencies: - protocol_examples_common: - path: ${IDF_PATH}/examples/common_components/protocol_examples_common diff --git a/examples/protocols/mqtt/wss/main/mqtt_eclipseprojects_io.pem b/examples/protocols/mqtt/wss/main/mqtt_eclipseprojects_io.pem deleted file mode 100644 index 43b222a60a5..00000000000 --- a/examples/protocols/mqtt/wss/main/mqtt_eclipseprojects_io.pem +++ /dev/null @@ -1,30 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIFFjCCAv6gAwIBAgIRAJErCErPDBinU/bWLiWnX1owDQYJKoZIhvcNAQELBQAw -TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh -cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjAwOTA0MDAwMDAw -WhcNMjUwOTE1MTYwMDAwWjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg -RW5jcnlwdDELMAkGA1UEAxMCUjMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK -AoIBAQC7AhUozPaglNMPEuyNVZLD+ILxmaZ6QoinXSaqtSu5xUyxr45r+XXIo9cP -R5QUVTVXjJ6oojkZ9YI8QqlObvU7wy7bjcCwXPNZOOftz2nwWgsbvsCUJCWH+jdx -sxPnHKzhm+/b5DtFUkWWqcFTzjTIUu61ru2P3mBw4qVUq7ZtDpelQDRrK9O8Zutm -NHz6a4uPVymZ+DAXXbpyb/uBxa3Shlg9F8fnCbvxK/eG3MHacV3URuPMrSXBiLxg -Z3Vms/EY96Jc5lP/Ooi2R6X/ExjqmAl3P51T+c8B5fWmcBcUr2Ok/5mzk53cU6cG -/kiFHaFpriV1uxPMUgP17VGhi9sVAgMBAAGjggEIMIIBBDAOBgNVHQ8BAf8EBAMC -AYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMBIGA1UdEwEB/wQIMAYB -Af8CAQAwHQYDVR0OBBYEFBQusxe3WFbLrlAJQOYfr52LFMLGMB8GA1UdIwQYMBaA -FHm0WeZ7tuXkAXOACIjIGlj26ZtuMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcw -AoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzAnBgNVHR8EIDAeMBygGqAYhhZodHRw -Oi8veDEuYy5sZW5jci5vcmcvMCIGA1UdIAQbMBkwCAYGZ4EMAQIBMA0GCysGAQQB -gt8TAQEBMA0GCSqGSIb3DQEBCwUAA4ICAQCFyk5HPqP3hUSFvNVneLKYY611TR6W -PTNlclQtgaDqw+34IL9fzLdwALduO/ZelN7kIJ+m74uyA+eitRY8kc607TkC53wl -ikfmZW4/RvTZ8M6UK+5UzhK8jCdLuMGYL6KvzXGRSgi3yLgjewQtCPkIVz6D2QQz -CkcheAmCJ8MqyJu5zlzyZMjAvnnAT45tRAxekrsu94sQ4egdRCnbWSDtY7kh+BIm -lJNXoB1lBMEKIq4QDUOXoRgffuDghje1WrG9ML+Hbisq/yFOGwXD9RiX8F6sw6W4 -avAuvDszue5L3sz85K+EC4Y/wFVDNvZo4TYXao6Z0f+lQKc0t8DQYzk1OXVu8rp2 -yJMC6alLbBfODALZvYH7n7do1AZls4I9d1P4jnkDrQoxB3UqQ9hVl3LEKQ73xF1O -yK5GhDDX8oVfGKF5u+decIsH4YaTw7mP3GFxJSqv3+0lUFJoi5Lc5da149p90Ids -hCExroL1+7mryIkXPeFM5TgO9r0rvZaBFOvV2z0gp35Z0+L4WPlbuEjN/lxPFin+ -HlUjr8gRsI3qfJOQFy/9rKIJR0Y/8Omwt/8oTWgy1mdeHmmjk7j1nYsvC9JSQ6Zv -MldlTTKB3zhThV1+XWYp6rjd5JW1zbVWEkLNxE7GJThEUG3szgBVGP7pSWTUTsqX -nLRbwHOoq7hHwg== ------END CERTIFICATE----- diff --git a/examples/protocols/mqtt/wss/pytest_mqtt_wss_example.py b/examples/protocols/mqtt/wss/pytest_mqtt_wss_example.py deleted file mode 100644 index cb4a22e3704..00000000000 --- a/examples/protocols/mqtt/wss/pytest_mqtt_wss_example.py +++ /dev/null @@ -1,111 +0,0 @@ -#!/usr/bin/env python -# -# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD -# SPDX-License-Identifier: Unlicense OR CC0-1.0 -import logging -import os -import re -import ssl -import sys -from threading import Event -from threading import Thread - -import paho.mqtt.client as mqtt -import pexpect -import pytest -from pytest_embedded import Dut -from pytest_embedded_idf.utils import idf_parametrize - -event_client_connected = Event() -event_stop_client = Event() -event_client_received_correct = Event() -message_log = '' - - -# The callback for when the client receives a CONNACK response from the server. -def on_connect(client, userdata, flags, rc): # type: (mqtt.Client, tuple, bool, str) -> None - _ = (userdata, flags) - print('Connected with result code ' + str(rc)) - event_client_connected.set() - client.subscribe('/topic/qos0') - - -def mqtt_client_task(client): # type: (mqtt.Client) -> None - while not event_stop_client.is_set(): - client.loop() - - -# The callback for when a PUBLISH message is received from the server. -def on_message(client, userdata, msg): # type: (mqtt.Client, tuple, mqtt.client.MQTTMessage) -> None - _ = userdata - global message_log - payload = msg.payload.decode() - if not event_client_received_correct.is_set() and payload == 'data': - client.publish('/topic/qos0', 'data_to_esp32') - if msg.topic == '/topic/qos0' and payload == 'data': - event_client_received_correct.set() - message_log += 'Received data:' + msg.topic + ' ' + payload + '\n' - - -@pytest.mark.ethernet -@idf_parametrize('target', ['esp32'], indirect=['target']) -def test_examples_protocol_mqtt_wss(dut): # type: (Dut) -> None - broker_url = '' - broker_port = 0 - """ - steps: | - 1. join AP and connects to wss broker - 2. Test connects a client to the same broker - 3. Test evaluates it received correct qos0 message - 4. Test ESP32 client received correct qos0 message - """ - # check and log bin size - binary_file = os.path.join(dut.app.binary_path, 'mqtt_websocket_secure.bin') - bin_size = os.path.getsize(binary_file) - logging.info('[Performance][mqtt_websocket_secure_bin_size]: %s KB', bin_size // 1024) - # Look for host:port in sdkconfig - try: - value = re.search(r'\:\/\/([^:]+)\:([0-9]+)', dut.app.sdkconfig.get('BROKER_URI')) - assert value is not None - broker_url = value.group(1) - broker_port = int(value.group(2)) - except Exception: - print('ENV_TEST_FAILURE: Cannot find broker url in sdkconfig') - raise - client = None - # 1. Test connects to a broker - try: - client = mqtt.Client(transport='websockets') - client.on_connect = on_connect - client.on_message = on_message - client.tls_set(None, None, None, cert_reqs=ssl.CERT_NONE, tls_version=ssl.PROTOCOL_TLSv1_2, ciphers=None) - print('Connecting...') - client.connect(broker_url, broker_port, 60) - except Exception: - print( - 'ENV_TEST_FAILURE: Unexpected error while connecting to broker {}: {}:'.format( - broker_url, sys.exc_info()[0] - ) - ) - raise - # Starting a py-client in a separate thread - thread1 = Thread(target=mqtt_client_task, args=(client,)) - thread1.start() - try: - print('Connecting py-client to broker {}:{}...'.format(broker_url, broker_port)) - if not event_client_connected.wait(timeout=30): - raise ValueError('ENV_TEST_FAILURE: Test script cannot connect to broker: {}'.format(broker_url)) - try: - ip_address = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[0] - print('Connected to AP with IP: {}'.format(ip_address)) - except pexpect.TIMEOUT: - print('ENV_TEST_FAILURE: Cannot connect to AP') - raise - print('Checking py-client received msg published from esp...') - if not event_client_received_correct.wait(timeout=30): - raise ValueError('Wrong data received, msg log: {}'.format(message_log)) - print('Checking esp-client received msg published from py-client...') - dut.expect(r'DATA=data_to_esp32', timeout=30) - finally: - event_stop_client.set() - thread1.join() diff --git a/examples/protocols/mqtt/wss/sdkconfig.ci b/examples/protocols/mqtt/wss/sdkconfig.ci deleted file mode 100644 index 30715342249..00000000000 --- a/examples/protocols/mqtt/wss/sdkconfig.ci +++ /dev/null @@ -1,13 +0,0 @@ -CONFIG_BROKER_URI="wss://${EXAMPLE_MQTT_BROKER_WSS}/ws" -CONFIG_BROKER_CERTIFICATE_OVERRIDE="${EXAMPLE_MQTT_BROKER_CERTIFICATE}" -CONFIG_EXAMPLE_CONNECT_ETHERNET=y -CONFIG_EXAMPLE_CONNECT_WIFI=n -CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y -CONFIG_EXAMPLE_ETH_PHY_GENERIC=y -CONFIG_EXAMPLE_ETH_MDC_GPIO=23 -CONFIG_EXAMPLE_ETH_MDIO_GPIO=18 -CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5 -CONFIG_EXAMPLE_ETH_PHY_ADDR=1 -CONFIG_EXAMPLE_CONNECT_IPV6=y -CONFIG_LWIP_TCPIP_CORE_LOCKING=y -CONFIG_LWIP_CHECK_THREAD_SAFETY=y diff --git a/examples/protocols/mqtt5/CMakeLists.txt b/examples/protocols/mqtt5/CMakeLists.txt index 39ef4351e24..af81c57894a 100644 --- a/examples/protocols/mqtt5/CMakeLists.txt +++ b/examples/protocols/mqtt5/CMakeLists.txt @@ -1,9 +1,9 @@ -# The following four lines of boilerplate have to be in your project's CMakeLists +# The following lines of boilerplate have to be in your project's CMakeLists # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.22) - include($ENV{IDF_PATH}/tools/cmake/project.cmake) + # "Trim" the build. Include the minimal set of components, main, and anything it depends on. idf_build_set_property(MINIMAL_BUILD ON) project(mqtt5) diff --git a/examples/protocols/mqtt5/main/CMakeLists.txt b/examples/protocols/mqtt5/main/CMakeLists.txt index 3bf739cf890..a48d3cd3eff 100644 --- a/examples/protocols/mqtt5/main/CMakeLists.txt +++ b/examples/protocols/mqtt5/main/CMakeLists.txt @@ -1,3 +1,6 @@ -idf_component_register(SRCS "app_main.c" - PRIV_REQUIRES mqtt nvs_flash esp_netif - INCLUDE_DIRS ".") +idf_component_register( + SRCS "app_main.c" + PRIV_REQUIRES esp-tls esp_wifi esp_event nvs_flash + INCLUDE_DIRS "." + EMBED_TXTFILES "mosquitto.org.crt" +) diff --git a/examples/protocols/mqtt5/main/Kconfig.projbuild b/examples/protocols/mqtt5/main/Kconfig.projbuild index c11539fb8d2..a13af0e96cf 100644 --- a/examples/protocols/mqtt5/main/Kconfig.projbuild +++ b/examples/protocols/mqtt5/main/Kconfig.projbuild @@ -1,13 +1,41 @@ menu "Example Configuration" - config BROKER_URL - string "Broker URL" - default "mqtt://mqtt.eclipseprojects.io" + choice EXAMPLE_CERT_VALIDATION + prompt "Certificate validation method" + default EXAMPLE_CERT_VALIDATE_BUNDLE help - URL of the broker to connect to + Choose how the broker's TLS server certificate is validated. + - Certificate bundle (default). + - Embedded certificate - config BROKER_URL_FROM_STDIN + config EXAMPLE_CERT_VALIDATE_BUNDLE + bool "Certificate bundle" + + config EXAMPLE_CERT_VALIDATE_MOSQUITTO_CA + bool "Embedded Certificate" + + endchoice + + config EXAMPLE_MQTT_BROKER_URI + string "MQTT broker URI" + default "mqtts://test.mosquitto.org:8886" + default "mqtts://test.mosquitto.org:8883" if EXAMPLE_CERT_VALIDATE_MOSQUITTO_CA + help + URI to the MQTT broker. + When using the example broker the port must be set to 8883 if testing + embedded certificate + + config EXAMPLE_BROKER_CERTIFICATE_OVERRIDE + string "Broker certificate override (PEM body)" + default "" + help + Optional: override server certificate by embedding a PEM constructed + from this base64 body. Leave empty to use the certificate bundle or the + embedded Mosquitto CA. Provide only the base64 payload without the + BEGIN/END markers. + + config EXAMPLE_BROKER_CERTIFICATE_OVERRIDDEN bool - default y if BROKER_URL = "FROM_STDIN" + default y if EXAMPLE_BROKER_CERTIFICATE_OVERRIDE != "" endmenu diff --git a/examples/protocols/mqtt5/main/app_main.c b/examples/protocols/mqtt5/main/app_main.c index e82fd70a963..4060fe10d62 100644 --- a/examples/protocols/mqtt5/main/app_main.c +++ b/examples/protocols/mqtt5/main/app_main.c @@ -1,8 +1,10 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ +/* MQTT 5.0 over TLS Example + */ #include #include @@ -14,10 +16,18 @@ #include "esp_netif.h" #include "protocol_examples_common.h" #include "esp_log.h" +#include "esp_crt_bundle.h" #include "mqtt_client.h" +#include "sdkconfig.h" static const char *TAG = "mqtt5_example"; +#if CONFIG_EXAMPLE_CERT_VALIDATE_MOSQUITTO_CA +/* Embedded Mosquitto CA certificate for test.mosquitto.org:8883 */ +extern const uint8_t mosquitto_org_crt_start[] asm("_binary_mosquitto_org_crt_start"); +extern const uint8_t mosquitto_org_crt_end[] asm("_binary_mosquitto_org_crt_end"); +#endif + static void log_error_if_nonzero(const char *message, int error_code) { if (error_code != 0) { @@ -25,6 +35,13 @@ static void log_error_if_nonzero(const char *message, int error_code) } } +#if CONFIG_EXAMPLE_BROKER_CERTIFICATE_OVERRIDDEN +static const char cert_override_pem[] = + "-----BEGIN CERTIFICATE-----\n" + CONFIG_EXAMPLE_BROKER_CERTIFICATE_OVERRIDE "\n" + "-----END CERTIFICATE-----"; +#endif + static esp_mqtt5_user_property_item_t user_property_arr[] = { {"board", "esp32"}, {"u", "user"}, @@ -204,45 +221,29 @@ static void mqtt5_app_start(void) .correlation_data = "123456", .correlation_data_len = 6, }; - - esp_mqtt_client_config_t mqtt5_cfg = { - .broker.address.uri = CONFIG_BROKER_URL, - .session.protocol_ver = MQTT_PROTOCOL_V_5, - .network.disable_auto_reconnect = true, - .credentials.username = "123", - .credentials.authentication.password = "456", - .session.last_will.topic = "/topic/will", - .session.last_will.msg = "i will leave", - .session.last_will.msg_len = 12, - .session.last_will.qos = 1, - .session.last_will.retain = true, +const esp_mqtt_client_config_t mqtt5_cfg = { + .broker = { + .address.uri = CONFIG_EXAMPLE_MQTT_BROKER_URI, +#if CONFIG_EXAMPLE_BROKER_CERTIFICATE_OVERRIDDEN + .verification.certificate = cert_override_pem, +#elif CONFIG_EXAMPLE_CERT_VALIDATE_MOSQUITTO_CA + .verification.certificate = (const char *)mosquitto_org_crt_start, +#else + .verification.crt_bundle_attach = esp_crt_bundle_attach, +#endif + }, + .session = { + .protocol_ver = MQTT_PROTOCOL_V_5, + .last_will = { + .topic = "/topic/will", + .msg = "i will leave", + .msg_len = 12, + .qos = 1, + .retain = true, + }, + }, }; -#if CONFIG_BROKER_URL_FROM_STDIN - char line[128]; - - if (strcmp(mqtt5_cfg.uri, "FROM_STDIN") == 0) { - int count = 0; - printf("Please enter url of mqtt broker\n"); - while (count < 128) { - int c = fgetc(stdin); - if (c == '\n') { - line[count] = '\0'; - break; - } else if (c > 0 && c < 127) { - line[count] = c; - ++count; - } - vTaskDelay(10 / portTICK_PERIOD_MS); - } - mqtt5_cfg.broker.address.uri = line; - printf("Broker url: %s\n", line); - } else { - ESP_LOGE(TAG, "Configuration mismatch: wrong broker url"); - abort(); - } -#endif /* CONFIG_BROKER_URL_FROM_STDIN */ - esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt5_cfg); /* Set connection properties and user properties */ diff --git a/examples/protocols/mqtt5/main/idf_component.yml b/examples/protocols/mqtt5/main/idf_component.yml index 718194867b7..689500cf6b7 100644 --- a/examples/protocols/mqtt5/main/idf_component.yml +++ b/examples/protocols/mqtt5/main/idf_component.yml @@ -1,3 +1,10 @@ dependencies: protocol_examples_common: path: ${IDF_PATH}/examples/common_components/protocol_examples_common + espressif/mqtt: "^1.0.0" + espressif/esp_wifi_remote: + version: ">=0.10,<2.0" + rules: + - if: "target in [esp32p4, esp32h2]" + idf: + version: ">=5.3" diff --git a/examples/protocols/mqtt/ssl_ds/main/mosquitto.org.crt b/examples/protocols/mqtt5/main/mosquitto.org.crt similarity index 99% rename from examples/protocols/mqtt/ssl_ds/main/mosquitto.org.crt rename to examples/protocols/mqtt5/main/mosquitto.org.crt index 8a3d44f57c9..e76dbd85598 100644 --- a/examples/protocols/mqtt/ssl_ds/main/mosquitto.org.crt +++ b/examples/protocols/mqtt5/main/mosquitto.org.crt @@ -22,4 +22,3 @@ sMwfu1HFvjy5Z0iMDU8PUDepjVolOCue9ashlS4EB5IECdSR2TItnAIiIwimx839 LdUdRudafMu5T5Xma182OC0/u/xRlEm+tvKGGmfFcN0piqVl8OrSPBgIlb+1IKJE m/XriWr/Cq4h/JfB7NTsezVslgkBaoU= -----END CERTIFICATE----- ---- diff --git a/examples/protocols/mqtt5/pytest_mqtt5.py b/examples/protocols/mqtt5/pytest_mqtt5.py index dc7063e956c..251e54cc501 100644 --- a/examples/protocols/mqtt5/pytest_mqtt5.py +++ b/examples/protocols/mqtt5/pytest_mqtt5.py @@ -22,9 +22,9 @@ def test_examples_protocol_mqtt5(dut: Dut) -> None: # check and log bin size binary_file = os.path.join(dut.app.binary_path, 'mqtt5.bin') bin_size = os.path.getsize(binary_file) - logging.info('mqtt5_bin_size : {}KB'.format(bin_size // 1024)) + logging.info(f'mqtt5_bin_size : {bin_size // 1024}KB') # check if connected or not - dut.expect_exact('MQTT_EVENT_CONNECTED', timeout=30) + dut.expect_exact('MQTT_EVENT_CONNECTED', timeout=60) # check log res = dut.expect(r'sent publish successful, msg_id=(\d+)[^\d]') msgid_pub1 = res.group(1).decode('utf8') @@ -62,4 +62,3 @@ def test_examples_protocol_mqtt5(dut: Dut) -> None: assert msgid_unsubd == msgid_unsub dut.expect_exact('MQTT_EVENT_DISCONNECTED') - logging.info('MQTT5 pytest pass') diff --git a/examples/protocols/mqtt5/sdkconfig.ci b/examples/protocols/mqtt5/sdkconfig.ci index 8f46cb0ebea..a7efa857a69 100644 --- a/examples/protocols/mqtt5/sdkconfig.ci +++ b/examples/protocols/mqtt5/sdkconfig.ci @@ -7,4 +7,5 @@ CONFIG_EXAMPLE_ETH_MDIO_GPIO=18 CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5 CONFIG_EXAMPLE_ETH_PHY_ADDR=1 CONFIG_MQTT_PROTOCOL_5=y -CONFIG_BROKER_URL="mqtt://${EXAMPLE_MQTTV5_BROKER_TCP}" +CONFIG_EXAMPLE_MQTT_BROKER_URI="mqtts://${EXAMPLE_MQTT_BROKER_SSL}" +CONFIG_EXAMPLE_BROKER_CERTIFICATE_OVERRIDE="${EXAMPLE_MQTT_BROKER_CERTIFICATE}" diff --git a/examples/protocols/mqtt5/sdkconfig.defaults b/examples/protocols/mqtt5/sdkconfig.defaults index db60a2ab38a..4dc6b428e90 100644 --- a/examples/protocols/mqtt5/sdkconfig.defaults +++ b/examples/protocols/mqtt5/sdkconfig.defaults @@ -1 +1,6 @@ +# Enable the built-in certificate bundle for TLS server verification +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=y +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=y + +# Enable MQTT v5 support in the managed ESP-MQTT component CONFIG_MQTT_PROTOCOL_5=y diff --git a/tools/ci/astyle-rules.yml b/tools/ci/astyle-rules.yml index 29c40ab0d11..f2f51aa9463 100644 --- a/tools/ci/astyle-rules.yml +++ b/tools/ci/astyle-rules.yml @@ -22,7 +22,6 @@ submodules: - "/components/heap/tlsf/" - "/components/lwip/lwip/" - "/components/mbedtls/mbedtls/" - - "/components/mqtt/esp-mqtt/" - "/components/openthread/lib/" - "/components/openthread/openthread/" - "/components/protobuf-c/protobuf-c/" @@ -71,7 +70,6 @@ components_not_formatted_temporary: - "/components/ieee802154/" - "/components/lwip/" - "/components/mbedtls/" - - "/components/mqtt/" - "/components/nvs_flash/" - "/components/nvs_sec_provider/" - "/components/openthread/" diff --git a/tools/ci/check_copyright_ignore.txt b/tools/ci/check_copyright_ignore.txt index 229dde405d7..e8ca3ecec99 100644 --- a/tools/ci/check_copyright_ignore.txt +++ b/tools/ci/check_copyright_ignore.txt @@ -855,13 +855,6 @@ examples/protocols/https_server/wss_server/main/keep_alive.h examples/protocols/https_server/wss_server/main/wss_server_example.c examples/protocols/https_x509_bundle/main/https_x509_bundle_example_main.c examples/protocols/icmp_echo/main/echo_example_main.c -examples/protocols/mqtt/ssl/main/app_main.c -examples/protocols/mqtt/ssl_ds/main/app_main.c -examples/protocols/mqtt/ssl_mutual_auth/main/app_main.c -examples/protocols/mqtt/ssl_psk/main/app_main.c -examples/protocols/mqtt/tcp/main/app_main.c -examples/protocols/mqtt/ws/main/app_main.c -examples/protocols/mqtt/wss/main/app_main.c examples/protocols/sntp/main/sntp_example_main.c examples/protocols/sockets/non_blocking/main/non_blocking_socket_example.c examples/protocols/sockets/tcp_client_multi_net/main/tcp_client_multiple.c @@ -942,10 +935,6 @@ tools/test_apps/protocols/esp_netif/build_config/main/init_macro.h tools/test_apps/protocols/esp_netif/build_config/main/main.cpp tools/test_apps/protocols/esp_netif/build_config/main/netif_init_c99.c tools/test_apps/protocols/esp_netif/build_config/main/netif_init_cpp.cpp -tools/test_apps/protocols/mqtt/build_test/main/mqtt_app.cpp -tools/test_apps/protocols/mqtt/publish_connect_test/main/connect_test.c -tools/test_apps/protocols/mqtt/publish_connect_test/main/publish_connect_test.c -tools/test_apps/protocols/mqtt/publish_connect_test/main/publish_test.c tools/test_apps/security/secure_boot/main/secure_boot_main.c tools/test_apps/security/secure_boot/main/secure_boot_main_esp32.c tools/test_apps/system/bootloader_sections/main/test_main.c diff --git a/tools/ci/check_kconfigs.py b/tools/ci/check_kconfigs.py index 08b086ebfb1..79de5f0955e 100755 --- a/tools/ci/check_kconfigs.py +++ b/tools/ci/check_kconfigs.py @@ -3,7 +3,6 @@ # SPDX-FileCopyrightText: 2018-2023 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 -from __future__ import print_function, unicode_literals import argparse import os @@ -11,7 +10,8 @@ import re import subprocess import sys -from idf_ci_utils import IDF_PATH, get_submodule_dirs +from idf_ci_utils import IDF_PATH +from idf_ci_utils import get_submodule_dirs # regular expression for matching Kconfig files RE_KCONFIG = r'^Kconfig(\.projbuild)?(\.in)?$' @@ -20,8 +20,6 @@ RE_KCONFIG = r'^Kconfig(\.projbuild)?(\.in)?$' # Note: ignore_dirs is a tuple in order to be able to use it directly with the startswith() built-in function which # accepts tuples but no lists. IGNORE_DIRS: tuple = ( - # Kconfigs from submodules need to be ignored: - os.path.join(IDF_PATH, 'components', 'mqtt', 'esp-mqtt'), # Test Kconfigs are also ignored os.path.join(IDF_PATH, 'tools', 'ldgen', 'test', 'data'), os.path.join(IDF_PATH, 'tools', 'kconfig_new', 'test'), @@ -30,9 +28,9 @@ IGNORE_DIRS: tuple = ( ignore_dirs: tuple = IGNORE_DIRS -def valid_directory(path:str) -> str: +def valid_directory(path: str) -> str: if not os.path.isdir(path): - raise argparse.ArgumentTypeError('{} is not a valid directory!'.format(path)) + raise argparse.ArgumentTypeError(f'{path} is not a valid directory!') return str(path) @@ -52,7 +50,7 @@ parser.add_argument( '-d', nargs='*', help='Extra paths for recursively searching Kconfig files. (for example $IDF_PATH)', - type=valid_directory + type=valid_directory, ) args, unknown_args = parser.parse_known_args() @@ -67,21 +65,17 @@ files_to_check: list = args.files # except IGNORE_DIRS and submodules (if exclude is given) # paths to KConfig files are passed to esp-idf-kconfig kconfcheck tool if args.includes: - for directory in args.includes: - for root, dirnames, filenames in os.walk(directory): - for filename in filenames: - full_path = os.path.join(root, filename) - if full_path.startswith(ignore_dirs): - continue - if re.search(RE_KCONFIG, filename): - files_to_check.append(f'{full_path}') - elif re.search(RE_KCONFIG, filename, re.IGNORECASE): - # On Windows Kconfig files are working with different cases! - print( - '{}: Incorrect filename. The case should be "Kconfig"!'.format( - full_path - ) - ) + for directory in args.includes: + for root, dirnames, filenames in os.walk(directory): + for filename in filenames: + full_path = os.path.join(root, filename) + if full_path.startswith(ignore_dirs): + continue + if re.search(RE_KCONFIG, filename): + files_to_check.append(f'{full_path}') + elif re.search(RE_KCONFIG, filename, re.IGNORECASE): + # On Windows Kconfig files are working with different cases! + print(f'{full_path}: Incorrect filename. The case should be "Kconfig"!') if __name__ == '__main__': diff --git a/tools/ci/static-analysis-rules.yml b/tools/ci/static-analysis-rules.yml index df2d539301e..f7e6f42aba4 100644 --- a/tools/ci/static-analysis-rules.yml +++ b/tools/ci/static-analysis-rules.yml @@ -20,7 +20,6 @@ skip: - "components/esp_wifi/lib_esp32" - "components/lwip/lwip" - "components/mbedtls/mbedtls" - - "components/mqtt/esp-mqtt" - "components/openthread/lib" - "components/openthread/openthread" - "components/protobuf-c/protobuf-c" diff --git a/tools/test_apps/protocols/.build-test-rules.yml b/tools/test_apps/protocols/.build-test-rules.yml index 1aef48dffc6..2674c2f74ee 100644 --- a/tools/test_apps/protocols/.build-test-rules.yml +++ b/tools/test_apps/protocols/.build-test-rules.yml @@ -6,24 +6,6 @@ tools/test_apps/protocols/esp_netif/build_config: temporary: false reason: No need to test on all targets -tools/test_apps/protocols/mqtt/publish_connect_test: - enable: - - if: IDF_TARGET in ["esp32", "esp32c3", "esp32s2"] - temporary: true - reason: the other targets are not tested yet - disable_test: - - if: IDF_TARGET not in ["esp32"] - temporary: true - reason: lack of runners - depends_components: - - mqtt - - esp_netif - depends_filepatterns: - - tools/ci/python_packages/common_test_methods.py - - examples/common_components/**/* - - examples/protocols/mqtt/* - - examples/protocols/mqtt5/* - tools/test_apps/protocols/netif_components: enable: - if: IDF_TARGET == "esp32" diff --git a/tools/test_apps/protocols/mqtt/build_test/CMakeLists.txt b/tools/test_apps/protocols/mqtt/build_test/CMakeLists.txt deleted file mode 100644 index 6481f74b8ed..00000000000 --- a/tools/test_apps/protocols/mqtt/build_test/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -# The following four lines of boilerplate have to be in your project's CMakeLists -# in this exact order for cmake to work correctly -cmake_minimum_required(VERSION 3.22) - -# (Not part of the boilerplate) -# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. -set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) - -include($ENV{IDF_PATH}/tools/cmake/project.cmake) - -# "Trim" the build. Include the minimal set of components, main, and anything it depends on. -set(COMPONENTS main) - -project(mqtt_tcp) diff --git a/tools/test_apps/protocols/mqtt/build_test/README.md b/tools/test_apps/protocols/mqtt/build_test/README.md deleted file mode 100644 index b7a5eb4ec0e..00000000000 --- a/tools/test_apps/protocols/mqtt/build_test/README.md +++ /dev/null @@ -1,6 +0,0 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- | - -# Build only test for C++ - -This test app ensures that calling all mqtt-client API could be called from C++ diff --git a/tools/test_apps/protocols/mqtt/build_test/main/CMakeLists.txt b/tools/test_apps/protocols/mqtt/build_test/main/CMakeLists.txt deleted file mode 100644 index 852d5655856..00000000000 --- a/tools/test_apps/protocols/mqtt/build_test/main/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -idf_component_register(SRCS "mqtt_app.cpp" - INCLUDE_DIRS "." - PRIV_REQUIRES nvs_flash esp_event esp_netif mqtt) -target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format") diff --git a/tools/test_apps/protocols/mqtt/build_test/main/mqtt_app.cpp b/tools/test_apps/protocols/mqtt/build_test/main/mqtt_app.cpp deleted file mode 100644 index 2960f41d5ac..00000000000 --- a/tools/test_apps/protocols/mqtt/build_test/main/mqtt_app.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/* Build only example to check mqtt client API from C++ - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ - -#include -#include "esp_system.h" -#include "nvs_flash.h" -#include "esp_event.h" -#include "esp_netif.h" -#include "esp_log.h" -#include "mqtt_client.h" - -static const char *TAG = "mqtt_example"; - - -static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event) -{ - switch (event->event_id) { - case MQTT_EVENT_CONNECTED: - ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED"); - break; - case MQTT_EVENT_DISCONNECTED: - ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED"); - break; - - case MQTT_EVENT_SUBSCRIBED: - ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id); - break; - case MQTT_EVENT_UNSUBSCRIBED: - ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id); - break; - case MQTT_EVENT_PUBLISHED: - ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id); - break; - case MQTT_EVENT_DATA: - ESP_LOGI(TAG, "MQTT_EVENT_DATA"); - break; - case MQTT_EVENT_ERROR: - ESP_LOGI(TAG, "MQTT_EVENT_ERROR"); - break; - default: - ESP_LOGI(TAG, "Other event id:%d", event->event_id); - break; - } - return ESP_OK; -} - -static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) { - ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%d", base, event_id); - mqtt_event_handler_cb((esp_mqtt_event_handle_t)event_data); -} - -static void mqtt_app_start(void) -{ - esp_mqtt_client_config_t mqtt_cfg = { }; - - esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg); - esp_mqtt_client_register_event(client, MQTT_EVENT_ANY, mqtt_event_handler, client); - esp_mqtt_client_start(client); - esp_mqtt_set_config(client, &mqtt_cfg); - int msg_id = esp_mqtt_client_publish(client, "/topic/qos1", "data", 0, 0, 0); - ESP_LOGI(TAG, "mqtt api returned %d", msg_id); - msg_id = esp_mqtt_client_subscribe(client, "/topic/qos0", 0); - ESP_LOGI(TAG, "mqtt api returned %d", msg_id); - msg_id = esp_mqtt_client_subscribe(client, "/topic/qos1", 1); - ESP_LOGI(TAG, "mqtt api returned %d", msg_id); - msg_id = esp_mqtt_client_unsubscribe(client, "/topic/qos1"); - ESP_LOGI(TAG, "mqtt api returned %d", msg_id); - esp_err_t err = esp_mqtt_client_set_uri(client, "mqtt://localhost:1883"); - ESP_LOGI(TAG, "mqtt api returned %d", err); - err = esp_mqtt_client_reconnect(client); - err = esp_mqtt_client_disconnect(client); - err = esp_mqtt_client_stop(client); - err = esp_mqtt_client_destroy(client); -} - -extern "C" void app_main(void) -{ - ESP_LOGI(TAG, "[APP] Startup.."); - ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size()); - ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version()); - - esp_log_level_set("*", ESP_LOG_INFO); - esp_log_level_set("mqtt_client", ESP_LOG_VERBOSE); - esp_log_level_set("mqtt_example", ESP_LOG_VERBOSE); - esp_log_level_set("transport_tcp", ESP_LOG_VERBOSE); - esp_log_level_set("transport_ssl", ESP_LOG_VERBOSE); - esp_log_level_set("transport", ESP_LOG_VERBOSE); - esp_log_level_set("outbox", ESP_LOG_VERBOSE); - - ESP_ERROR_CHECK(nvs_flash_init()); - ESP_ERROR_CHECK(esp_netif_init()); - ESP_ERROR_CHECK(esp_event_loop_create_default()); - - mqtt_app_start(); -} diff --git a/tools/test_apps/protocols/mqtt/publish_connect_test/CMakeLists.txt b/tools/test_apps/protocols/mqtt/publish_connect_test/CMakeLists.txt deleted file mode 100644 index be93606864a..00000000000 --- a/tools/test_apps/protocols/mqtt/publish_connect_test/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ -# The following four lines of boilerplate have to be in your project's CMakeLists -# in this exact order for cmake to work correctly -cmake_minimum_required(VERSION 3.22) - -include($ENV{IDF_PATH}/tools/cmake/project.cmake) -idf_build_set_property(MINIMAL_BUILD ON) - -project(mqtt_publish_connect_test) - -target_add_binary_data(mqtt_publish_connect_test.elf "main/mqtt_eclipseprojects_io.pem" TEXT) -target_add_binary_data(mqtt_publish_connect_test.elf "ca.crt" TEXT) -target_add_binary_data(mqtt_publish_connect_test.elf "ca.der" TEXT) -target_add_binary_data(mqtt_publish_connect_test.elf "client_pwd.key" TEXT) -target_add_binary_data(mqtt_publish_connect_test.elf "client_pwd.crt" TEXT) -target_add_binary_data(mqtt_publish_connect_test.elf "client_no_pwd.key" TEXT) -target_add_binary_data(mqtt_publish_connect_test.elf "client_inv.crt" TEXT) diff --git a/tools/test_apps/protocols/mqtt/publish_connect_test/README.md b/tools/test_apps/protocols/mqtt/publish_connect_test/README.md deleted file mode 100644 index ec2cd41e2da..00000000000 --- a/tools/test_apps/protocols/mqtt/publish_connect_test/README.md +++ /dev/null @@ -1,25 +0,0 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-S2 | -| ----------------- | ----- | -------- | -------- | - -# ESP-MQTT advanced publish and connect test project - -Main purpose of this application is to test the MQTT library to correctly publish and receive messages (of different size and sequences) over different transports. -It is possible to run this example manually without any test to exercise how the MQTT library deals with - -- reception of fragmented messages -- runtime updates of URI - -## Runtime settings - -This app waits for user input to provide these parameters: -- test-type: "conn" if connection test (host, port, test-case number) -- publish test: - * transport: string parameter, one of: tcp, ssl, ws, wss - * pattern: sample string to be transmitted as message - * pattern repeats: number of repeats of pattern in one MQTT message - * repeated: number of repeats ESP32 publishes the message, also ESP32 expects to receive the same message the same number of repeats - * qos: number specifying qos, one of: 0, 1, 2 - -## Hardware Required - -This test-app can be executed on any ESP32 board, the only required interface is WiFi and connection to a local network, then depending on the test either a mqtt test broker or a tls server. diff --git a/tools/test_apps/protocols/mqtt/publish_connect_test/ca.crt b/tools/test_apps/protocols/mqtt/publish_connect_test/ca.crt deleted file mode 100644 index e371e070cae..00000000000 --- a/tools/test_apps/protocols/mqtt/publish_connect_test/ca.crt +++ /dev/null @@ -1,19 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDGTCCAgGgAwIBAgIUY6kAA+U+ZPIJYIff8dlbi6NCzKswDQYJKoZIhvcNAQEL -BQAwFDESMBAGA1UEAwwJRXNwcmVzc2lmMB4XDTI1MDQwMjA1MjcwMloXDTM1MDMz -MTA1MjcwMlowFDESMBAGA1UEAwwJRXNwcmVzc2lmMIIBIjANBgkqhkiG9w0BAQEF -AAOCAQ8AMIIBCgKCAQEAwSY/p8zDP8W3f37xfL1jy/WcWVOOS2msWRyxjpXQM2e+ -66McSkn8mVKTW5/aZ96sFQbmBBuhp3ypopH+kBQHxK4kla6roEcN/Nx9wpC8X64l -U9EqPmOvcIG8HElEY05LzZ9Rzc4LIBREq/sM8FE5+YHO2za8rN2XIaMii0mm2alf -o1MFEq1nkHBeJKlXkk6eZDwcQ9kqLWBz9YQWygE2pmDCjdCoY97/dZpgAjvkrAGN -9UYno9ZmNOYefL1P1ZmVtdBRW/xDGTDSZCJGYHOrtvfD8VS6cguOOl+rsy3obFdh -A4AgGFEFtfdY/+2fJHFkn6Pep6j+7h8f9n89qpSwswIDAQABo2MwYTAdBgNVHQ4E -FgQUJ+QsjjuS10OtEEcU0Wh2XhXTa1YwHwYDVR0jBBgwFoAUJ+QsjjuS10OtEEcU -0Wh2XhXTa1YwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAoQwDQYJKoZI -hvcNAQELBQADggEBABKWpI+QdMYoDwyssIbfwpbqJxb5M1w3PLnMsPzg1d5aEqLh -zwN9EnEQ5TxfeC7Lxdv3hKEGtif/aVxBhs48wPSxD7Fuw17kX6P4l9Cu9Ro2+1Oy -0lUxHi61xXxf7zVkdPQ0JLXdSMUvSUuKfvBtHCwEfdC+lsamxIDmCJys69kDhsCM -VJzY8Yz4MA9WOY3Z2YYMRp6ryFBZ9UgSUEnFxSOpggymkcM5mNxod1jshvSJ3FDG -dmvfbmK0+dN3rCiooORsIYVbopAYxralavA9IY24oiULE+GyVt5pNSONmJ96Y7GK -dL72B8RxX+jUSzgu/N3D1DwbPHP/xRiI7EqaYvg= ------END CERTIFICATE----- diff --git a/tools/test_apps/protocols/mqtt/publish_connect_test/ca.der b/tools/test_apps/protocols/mqtt/publish_connect_test/ca.der deleted file mode 100644 index 8f0d12006aceaf0753b903aba07c6822dfbb2fe2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 797 zcmXqLVwN;$Vq#pt%*4pVB$B+6f%&Oj$|uf*_WK`iMt3iEI0ro;}B{AmXz6H_wMa%b$(sZkz2{b9cJpVx?}+ zWj9yGFAioETAMzhAWmgv_$0r1DK;|BH??#ViodpqonkawmT;)|!iwa3|4U~jFj+rY z!`S=PO?~mTG?Qm?HGBQ9&YZgSLSXbCXGw!gDN1e$#jCe{Km0LdR}pugRs8DBx-W9V z6PX(nBm!BtevkP7cD_ns%KXLmmaq8tPG0_7z3r+g8#XgBGcqtPPBut1kOhXgEFX&) zi-`IYoj&VH*PYi2xQkrOD2o%loE>H$50X}9kuVTzz^;HFq(GRF@jnZz0W**?-~$Qp zg9KQZnV4FTqX8Jpz-VA(5Sq56e?rMI4St?A8`|z4n)XUv?5A;zxy{Zq8~!}FdM`?7 z(Zlo1wL*mgPi^8W^iChW{k>%&+cx$8nK6!S=WGsq*~q^!?{M6c_{Be_Us(55%ItUW zrc0rQa(Y{j*2KRzO)2?eqO$d_$5DMx@2