diff --git a/.gitlab/ci/pre_check.yml b/.gitlab/ci/pre_check.yml index 5b1adf24297c..29e89745e2cb 100644 --- a/.gitlab/ci/pre_check.yml +++ b/.gitlab/ci/pre_check.yml @@ -72,7 +72,7 @@ check_chip_support_components: expire_in: 1 week script: - python tools/ci/check_soc_headers_leak.py - - find ${IDF_PATH}/components/soc/**/include/soc/ -name "*_struct.h" -print0 | xargs -0 -n1 ./tools/ci/check_soc_struct_headers.py + - find ${IDF_PATH}/components/soc/**/include/soc/ ${IDF_PATH}/components/soc/**/register/soc/ -name "*_struct.h" -print0 | xargs -0 -n1 ./tools/ci/check_soc_struct_headers.py - tools/ci/check_esp_memory_utils_headers.sh check_esp_err_to_name: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1b2302474710..fb4db68e28ff 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -156,7 +156,7 @@ repos: require_serial: true additional_dependencies: - PyYAML == 5.3.1 - - idf-build-apps~=2.5 + - idf-build-apps>=2.6.2,<3 - id: sort-yaml-files name: sort yaml files entry: tools/ci/sort_yaml.py diff --git a/ROADMAP.md b/ROADMAP.md index a65140b80d2e..d312176298c0 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -1,4 +1,6 @@ -# ESP-IDF Project Roadmap 2024 +# ESP-IDF Project Roadmap 2025 + +* [中文版](./ROADMAP_CN.md) This document outlines the goals of ESP-IDF project and is shared for the convenience of our customers. It is important to clarify that this document is not a binding commitment to our customers. Instead, its primary purpose is to offer a clear roadmap and direction for the project's development. By openly sharing this information, we aim to enhance our customers' understanding, promote transparency and ensure alignment with the overarching objectives of the ESP-IDF project. @@ -10,32 +12,24 @@ In both minor and major releases, we integrate new chip support to enhance our p Furthermore, we prioritize bugfix releases for active branches, focusing on improving the stability and performance of products already in production. By addressing bugs promptly, we aim to enhance the overall user experience and provide tangible benefits to customers relying on our solutions. This proactive maintenance strategy reflects our commitment to delivering reliable, high-quality products to our valued customer base. -Below are the main objectives that ESP-IDF project/teams would like to implement in 2024. +Below are the main objectives that ESP-IDF project/teams would like to implement in 2025. - New Chip Support - - Add support for ESP32-P4 - Add support for ESP32-C5 - Add support for ESP32-C61 -- More Minor Releases +- More Minor/Major Releases - - Release IDF v5.3 in 2024 - - Release IDF v5.4 at the start of 2025 + - Release IDF v5.5 in the middle of 2025 + - Release IDF v6.0 at the end of 2025 - More Bugfix Releases - - Release v4.4.8 for IDF v4.4 before ESP-IDF v4.4 goes End of Life in July 2024 - - Do more bugfix releases for IDF v5.1 before release/5.1 enters maintenance period in June 2024 - - Do more bug fixes releases for release/5.2 and release/5.3, and push the two releases to be more stable and production-ready - -- Updates of Libraries - - - Update GDB to 14.2 - - Update LLVM to 18.1.2 - - Update MbedTLS to 3.6 (LTS) - - Update LWIP to 2.2.0 - - Change minimal Python requirement to 3.9 + - Release v5.0.8 and v5.0.9 before ESP-IDF v5.0 goes End of Life in May 2025 + - Release v5.1.6 and v5.1.7 before ESP-IDF v5.1 goes End of Life in December 2025 + - Do more bugfix releases for IDF v5.2 and IDF v5.3 before release/5.2 and release/5.3 enter maintenance period + - Do more bug fixes releases for release/5.4 and release/5.5, and push the two releases to be more stable and production-ready Please note that support status of previous silicones could be found on [ESP-IDF Release and SoC Compatibility](https://github.com/espressif/esp-idf#esp-idf-release-and-soc-compatibility). @@ -49,75 +43,86 @@ Below are the main roadmap details for functional areas inside ESP-IDF. - New Chip Support - - Add full support for ESP32-P4 in ESP-IDF v5.3, refer to [ESP32-P4 Support Status](https://github.com/espressif/esp-idf/issues/12996) - - Add preview support for ESP32-C5 in ESP-IDF v5.3 and full support for ESP32-C5 in ESP-IDF v5.4, refer to [ESP32-C5 Support Status](https://github.com/espressif/esp-idf/issues/14021) - - Add preview support for the early samples of ESP32-C61 in ESP-IDF v5.4 and full support for mass production version in ESP-IDF v5.4.x. Refer to [ESP32-C61 Support Status](https://developer.espressif.com/pages/chip-support-status/esp32c61/#esp-idf) + - Add the initial support for the mass production version of ESP32-C5 in ESP-IDF v5.5, refer to [ESP32-C5 Support Status](https://github.com/espressif/esp-idf/issues/14021) + - Add the initial support for the mass production version of ESP32-C61 in ESP-IDF v5.5, refer to [ESP32-C61 Support Status](https://developer.espressif.com/pages/chip-support-status/esp32c61/#esp-idf) - Bugfix releases - - Do bugfix release IDF v4.4.8 and stop maintaining ESP-IDF v4.4 in July 2024 - - Release bugfix IDF v5.0.6 and IDF v5.0.7 in 2024 (maintenance period) - - Release bugfix IDF v5.1.3 and IDF v5.1.4 in H1 of 2024, and release IDF v5.1.5 in H2 of 2024 - - Push release/5.1 to maintenance period from June 2024 - - Do more bug fixes releases for release/5.2 (IDF v5.2.1, IDF v5.2.2, IDF v5.2.3) and release/5.3 (IDF v5.3.1, IDF v5.3.2), and push releases to be more stable and more production-ready + - Do bugfix releases v5.0.8 and v5.0.9 and stop maintaining ESP-IDF v5.0 in May 2025 + - Do bugfix releases v5.1.6 and v5.1.7 and stop maintaining ESP-IDF v5.1 in December 2025 + - Release bugfix IDF v5.2.4 and IDF v5.2.5 in 2025, and push release/5.2 to maintenance period from February 2025 + - Release bugfix IDF v5.3.3 and IDF v5.3.4 in 2025, and push release/5.3 to maintenance period from July 2025 + - Do more bug fixes releases for release/5.4 (IDF v5.4.1, IDF v5.4.2, IDF v5.4.3) and release/5.5 (IDF v5.5.1, IDF v5.5.2), and push releases to be more stable and more production-ready ## ESP-IDF Planning information For the full list of ESP-IDF releases, please visit https://github.com/espressif/esp-idf/releases -### ESP-IDF Major Releases +All the information provided here is subject to change without notice, due to business reasons and other factors. -No Major Releases planned +### ESP-IDF Major Releases +```mermaid +timeline + + title ESP-IDF Major Releases + section 2025 Q1
Major Release Planning + No version planned : N/A + section 2025 Q2
Major Release Planning + No version planned : N/A + section 2025 Q3
Major Release Planning + No version planned : N/A + section 2025 Q4
Major Release Planning + v6.0-beta1 : 2025/11/13 + v6.0-beta2 : 2025/12/05 + v6.0-RC1 : 2026/01/14 + v6.0-RC2 : 2026/02/06 + v6.0 : 2026/02/13 +``` + +> [!NOTE] +> However for the December release, we are also considering another minor version v5.6. We would consolidate the planning in the middle of 2025 and replace v6.0 with v5.6 if v5.6 version planning is decided. + ### ESP-IDF Minor Releases -#### Quarter One - -- v5.2-RC1, estimate release date: 2024/02/02 -- v5.2 final release, estimate release date: 2024/02/08 - -#### Quarter Two - -- v5.3-beta1, estimate release date:: 2024/05/13 -- v5.3-beta2, estimate release date:: 2024/05/31 -- v5.3-RC1, estimate release date:: 2024/07/08 - -#### Quarter Three - -- v5.3-RC2, estimate release date:: 2024/07/26 -- v5.3 final release, estimate release date:: 2024/08/02 - -#### Quarter Four - -- v5.4-beta1, estimate release date:: 2024/11/08 -- v5.4-beta2, estimate release date:: 2024/11/29 -- v5.4-RC1, estimate release date:: 2025/01/09 -- v5.4-RC2, estimate release date:: 2025/01/29 -- v5.4 final release, estimate release date: 2025/02/05 +```mermaid +timeline + + title ESP-IDF Minor Releases + section 2025 Q1
Minor Release Planning + No version planned : N/A + section 2025 Q2
Minor Release Planning + v5.5-beta1 : 2025/05/14 + v5.5-beta2 : 2025/06/04 + section 2025 Q3
Minor Release Planning + v5.5-RC1 : 2025/07/07 + v5.5-RC2 : 2025/07/28 + v5.5 : 2025/08/04 + section 2025 Q4
Minor Release Planning + No version planned : N/A +``` ### ESP-IDF Bugfix Releases -#### Quarter One - -- v5.1.3, estimate release date: 2024/02/08 -- v5.0.6, estimate release date: 2024/02/18 -- v4.4.7, estimate release date:: 2024/03/19 -- v5.2.1, estimate release date:: 2024/03/31 - -#### Quarter Two - -- v5.1.4, estimate release date:: 2024/05/06 -- v5.2.2, estimate release date:: 2024/06/17 -- v4.4.8, estimate release date:: 2024/07/19 - -#### Quarter Three - -- v5.0.7, estimate release date: 2024/08/22 -- v5.3.1, estimate release date: 2024/09/16 -- v5.2.3, estimate release date: 2024/10/10 - -#### Quarter Four - -- v5.1.5, estimate release date: 2024/11/04  (Maintenance period since June 2024) -- v5.3.2, estimate release date: 2024/12/31 -- v5.2.4, estimate release date: 2025/02/20 (Service period ends Feb. 2025) +```mermaid +timeline + + title ESP-IDF Bugfix Releases + section 2025 Q1
Bugfix Release Planning + v5.0.8 : 2025/01/14 + v5.1.6 : 2025/02/18 + v5.2.4 : 2025/02/23 + v5.4.1 : 2025/03/27 + v5.3.3 : 2025/04/04 + section 2025 Q2
Bugfix Release Planning + v5.0.9 : 2025/05/16 + v5.4.2 : 2025/06/30 + section 2025 Q3
Bugfix Release Planning + v5.3.4 : 2025/08/03 + v5.2.5 : 2025/09/04 + v5.5.1 : 2025/09/11 + v5.4.3 : 2025/10/08 + section 2025 Q4
Bugfix Release Planning + v5.5.2 : 2025/11/12 + v5.1.7 : 2026/01/06 +``` \ No newline at end of file diff --git a/ROADMAP_CN.md b/ROADMAP_CN.md index 4c6f40d99146..68f8894b47b2 100644 --- a/ROADMAP_CN.md +++ b/ROADMAP_CN.md @@ -1,4 +1,6 @@ -# ESP-IDF 项目路线图 2024 (v1.0) +# ESP-IDF 项目路线图 2025 + +* [English Version](./ROADMAP.md) 本文档概述了 ESP-IDF 项目的年度计划,方便客户据此规划自己的项目周期。需要说明的是该文档并不是我们对客户的约束性承诺。相反,其主要目的是为客户提供 ESP-IDF 项目开发的路线图和方向。通过公开这些信息,我们希望增进客户对 ESP-IDF 项目的理解,提高透明度,并确保与 ESP-IDF 项目的总体目标保持一致。 @@ -10,32 +12,24 @@ 此外,ESP-IDF 各活跃分支的 Bugfix 版本发布也是我们项目的重中之重,着力提升已量产产品的稳定性和性能。通过及时解决问题,我们期待提升用户的整体体验,切实惠及使用乐鑫解决方案的客户。通过积极维护 ESP-IDF 的各活跃分支,我们践行了对宝贵的客户群提供可靠、高质量产品的承诺。 -以下是 ESP-IDF 项目在 2024 年计划实现的主要目标。 +以下是 ESP-IDF 项目在 2025 年计划实现的主要目标。 * 新芯片支持 - * 增加对 ESP32-P4 芯片的支持 * 增加对 ESP32-C5 芯片的支持 * 增加对 ESP32-C61 芯片的支持 -* 发布更多的次要版本 - - * 在 2024 年发布 IDF v5.3 - * 在 2025 年初发布 IDF v5.4 - -* 发布更多 Bugfix 版本 +* 发布更多的次要和主要版本 - * 在 2024 年 7 月底 IDF v4.4 停止维护之前,发布 IDF v4.4.8 - * 在 2024 年 6 月底,release/5.1 分支进入维护周期之前,发布更多 Bugfix 版本 - * release/5.2 分支和 release/5.3 分支发布更多 Bugfix 版本,使这两个分支更加稳定和产品化 + * 在 2025 年中发布 IDF v5.5 + * 在 2025 年底发布 IDF v6.0 -* 上游库与工具链的更新 +* 发布更多 bugfix 版本 - * 将 GDB 升级至 14.2 - * 将 LLVM 升级至 18.1.2 - * 更新 MbedTLS 至 3.6(LTS) - * 更新 LWIP 至 2.2.0 - * 将最低 Python 要求更改为 3.9 + * 在 2025 年 5 月底 IDF v5.0 停止维护之前,发布 IDF v5.0.8 和 IDF v5.0.9 + * 在 2025 年 12 月底 IDF v5.1 停止维护之前,发布 IDF v5.1.6 和 IDF v5.1.7 + * 在 release/5.2 分支和 release/5.3 分支进入维护周期之前,发布更多 bugfix 版本 + * release/5.4 分支和 release/5.5 分支发布更多 bugfix 版本,使这两个分支更加稳定和产品化 请注意,获取之前芯片的支持状态,请参阅 [ESP-IDF 发布和 SoC 兼容性](https://github.com/espressif/esp-idf/blob/master/README_CN.md#esp-idf-与乐鑫芯片)。 @@ -49,75 +43,86 @@ ESP-IDF 项目重视持续维护和更新,确保我们的客户始终处于技 * 新芯片支持 - * 在 ESP-IDF v5.3 中为 ESP32-P4 提供完整支持,参考 [ESP32-P4 支持状态](https://github.com/espressif/esp-idf/issues/12996) - * 在 ESP-IDF v5.3 中为 ESP32-C5 提供预览支持,并在 ESP-IDF v5.4 中为 ESP32-C5 提供完整支持,参考 [ESP32-C5 支持状态](https://github.com/espressif/esp-idf/issues/14021) - * 在 ESP-IDF v5.4 中增加对 ESP32-C61 早期样品的预览支持,并在 IDF v5.4.x 中增加对 ESP32-C61 量产版本的完整支持,参考 [ESP32-C61 支持状态](https://developer.espressif.com/pages/chip-support-status/esp32c61/#esp-idf) + * 在 ESP-IDF v5.4 中为 ESP32-C5 提供预览支持,并在 ESP-IDF v5.5 中为 ESP32-C5 提供完整支持,参考 [ESP32-C5 支持状态](https://github.com/espressif/esp-idf/issues/14021) + * 在 ESP-IDF v5.4 中增加对 ESP32-C61 早期样品的预览支持,并在 IDF v5.5 中增加对 ESP32-C61 量产版本的完整支持,参考 [ESP32-C61 支持状态](https://developer.espressif.com/pages/chip-support-status/esp32c61/#esp-idf) * Bugfix 版本发布 - * 发布 Bugfix 版本 IDF v4.4.8,并在 2024 年 7 月底停止维护 ESP-IDF v4.4 - * 2024 年,release/5.0 分支已处于维护周期,发布 IDF v5.0.6 和 IDF v5.0.7 - * 2024 年上半年发布 Bugfix 版本 IDF v5.1.3 和 IDF v5.1.4,并在 2024 年下半年发布 IDF v5.1.5 - * 自 2024 年 6 月起,release/5.1 分支进入到维护周期 - * release/5.2 分支发布更多 Bugfix 版本,包括 IDF v5.2.1、IDF v5.2.2、IDF v5.2.3;release/5.3 分支发布更多 Bugfix 版本,包括 IDF v5.3.1、IDF v5.3.2。通过发布这些 Bugfix 版本,使 release/5.2 分支和 release/5.3 分支更加稳定和产品化。 + * 发布 Bugfix 版本 IDF v5.0.8 和 IDF v5.0.9,并在 2025 年 5 月底停止维护 ESP-IDF v5.0 + * 发布 Bugfix 版本 IDF v5.1.6 和 IDF v5.1.7,并在 2025 年 12 月底停止维护 ESP-IDF v5.1 + * 发布 Bugfix 版本 IDF v5.2.4 和 IDF v5.2.5,release/5.2 分支自 2025 年 2 月进入维护周期 + * 发布 Bugfix 版本 IDF v5.3.3 和 IDF v5.3.4,release/5.3 分支自 2025 年 7 月进入维护周期 + * release/5.4 分支发布更多 bugfix 版本,包括 IDF v5.4.1、IDF v5.4.2、IDF v5.4.3;release/5.5 分支发布更多 bugfix 版本,包括 IDF v5.5.1、IDF v5.5.2。通过发布这些 Bugfix 版本,使 release/5.4 分支和 release/5.5 分支更加稳定和产品化。 ## ESP-IDF 发布计划 获取 ESP-IDF 的完整发布列表,请访问 https://github.com/espressif/esp-idf/releases -### ESP-IDF 主要版本发布 +此处提供的所有信息均可因业务原因及其他因素而在没有通知的情况下进行更改。 -2024 年,无主要版本发布计划 +### ESP-IDF 主要版本发布 +```mermaid +timeline + + title ESP-IDF Major Releases + section 2025 Q1
Major Release Planning + No version planned : N/A + section 2025 Q2
Major Release Planning + No version planned : N/A + section 2025 Q3
Major Release Planning + No version planned : N/A + section 2025 Q4
Major Release Planning + v6.0-beta1 : 2025/11/13 + v6.0-beta2 : 2025/12/05 + v6.0-RC1 : 2026/01/14 + v6.0-RC2 : 2026/02/06 + v6.0 : 2026/02/13 +``` + +> [!NOTE] +> 但对于 12 月份的发布,我们也在考虑发布另外一个次要版本。我们将在 2025 年中期确定 v5.6 的计划,如一经确定,我们将把 12 月份的 v6.0 发布变更为 v5.6 发布。 + ### ESP-IDF 次要版本发布 -#### 第一季度 - -* v5.2-RC1,预计发布日期:2024/02/02 -* v5.2 正式发布,预计发布日期:2024/02/08 - -#### 第二季度 - -* v5.3-beta1,预计发布日期:2024/05/13 -* v5.3-beta2,预计发布日期:2024/05/31 -* v5.3-RC1,预计发布日期:2024/07/08 - -#### 第三季度 - -* v5.3-RC2,预计发布日期:2024/07/26 -* v5.3 正式发布,预计发布日期:2024/08/02 - -#### 第四季度 - -* v5.4-beta1,预计发布日期:2024/11/08 -* v5.4-beta2,预计发布日期:2024/11/29 -* v5.4-RC1,预计发布日期:2025/01/09 -* v5.4-RC2,预计发布日期:2025/01/29 -* v5.4 正式发布,预计发布日期:2025/02/05 +```mermaid +timeline + + title ESP-IDF Minor Releases + section 2025 Q1
Minor Release Planning + No version planned : N/A + section 2025 Q2
Minor Release Planning + v5.5-beta1 : 2025/05/14 + v5.5-beta2 : 2025/06/04 + section 2025 Q3
Minor Release Planning + v5.5-RC1 : 2025/07/07 + v5.5-RC2 : 2025/07/28 + v5.5 : 2025/08/04 + section 2025 Q4
Minor Release Planning + No version planned : N/A +``` ### ESP-IDF Bugfix 版本发布 -#### 第一季度 - -* v5.1.3,预计发布日期:2024/02/08 -* v5.0.6,预计发布日期:2024/02/18 -* v4.4.7,预计发布日期:2024/03/19 -* v5.2.1,预计发布日期:2024/03/31 - -#### 第二季度 - -* v5.1.4,预计发布日期:2024/05/06 -* v5.2.2,预计发布日期:2024/06/17 -* v4.4.8,预计发布日期:2024/07/19 - -#### 第三季度 - -* v5.0.7,预计发布日期:2024/08/22 -* v5.3.1,预计发布日期:2024/09/16 -* v5.2.3,预计发布日期:2024/10/10 - -#### 第四季度 - -* v5.1.5,预计发布日期:2024/11/04(自 2024 年 6 月进入维护周期) -* v5.3.2,预计发布日期:2024/12/31 -* v5.2.4,预计发布日期:2025/02/20(服务周期截止至 2025 年 2 月) \ No newline at end of file +```mermaid +timeline + + title ESP-IDF Bugfix Releases + section 2025 Q1
Bugfix Release Planning + v5.0.8 : 2025/01/14 + v5.1.6 : 2025/02/18 + v5.2.4 : 2025/02/23 + v5.4.1 : 2025/03/27 + v5.3.3 : 2025/04/04 + section 2025 Q2
Bugfix Release Planning + v5.0.9 : 2025/05/16 + v5.4.2 : 2025/06/30 + section 2025 Q3
Bugfix Release Planning + v5.3.4 : 2025/08/03 + v5.2.5 : 2025/09/04 + v5.5.1 : 2025/09/11 + v5.4.3 : 2025/10/08 + section 2025 Q4
Bugfix Release Planning + v5.5.2 : 2025/11/12 + v5.1.7 : 2026/01/06 +``` \ No newline at end of file diff --git a/components/app_update/esp_ota_ops.c b/components/app_update/esp_ota_ops.c index 63e33b9c0945..c212c5f8d055 100644 --- a/components/app_update/esp_ota_ops.c +++ b/components/app_update/esp_ota_ops.c @@ -867,8 +867,7 @@ static esp_err_t esp_ota_current_ota_is_workable(bool valid) if (err != ESP_OK) { return err; } - ESP_LOGI(TAG, "Rollback to previously worked partition. Restart."); - esp_restart(); + ESP_LOGI(TAG, "Rollback to previously worked partition."); } } else { ESP_LOGE(TAG, "Running firmware is factory"); @@ -882,11 +881,20 @@ esp_err_t esp_ota_mark_app_valid_cancel_rollback(void) return esp_ota_current_ota_is_workable(true); } -esp_err_t esp_ota_mark_app_invalid_rollback_and_reboot(void) +esp_err_t esp_ota_mark_app_invalid_rollback(void) { return esp_ota_current_ota_is_workable(false); } +esp_err_t esp_ota_mark_app_invalid_rollback_and_reboot(void) +{ + esp_err_t ret = esp_ota_mark_app_invalid_rollback(); + if (ret == ESP_OK) { + esp_restart(); + } + return ret; +} + static bool check_invalid_otadata (const esp_ota_select_entry_t *s) { return s->ota_seq != UINT32_MAX && s->crc == bootloader_common_ota_select_crc(s) && diff --git a/components/app_update/include/esp_ota_ops.h b/components/app_update/include/esp_ota_ops.h index 5f4a8a05cf68..fff87f359b2b 100644 --- a/components/app_update/include/esp_ota_ops.h +++ b/components/app_update/include/esp_ota_ops.h @@ -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 */ @@ -334,12 +334,24 @@ uint8_t esp_ota_get_app_partition_count(void); esp_err_t esp_ota_mark_app_valid_cancel_rollback(void); /** - * @brief This function is called to roll back to the previously workable app with reboot. + * @brief This function is called to roll back to the previously workable app without reboot. * - * If rollback is successful then device will reset else API will return with error code. * Checks applications on a flash drive that can be booted in case of rollback. * If the flash does not have at least one app (except the running app) then rollback is not possible. * @return + * - ESP_OK: if successful. + * - ESP_FAIL: if not successful. + * - ESP_ERR_OTA_ROLLBACK_FAILED: The rollback is not possible because the available OTA partitions + * on the flash do not contain a valid application. + */ +esp_err_t esp_ota_mark_app_invalid_rollback(void); + +/** + * @brief This function is called to roll back to the previously workable app with reboot. + * + * Equivalent to calling esp_ota_mark_app_invalid_rollback(), and, if successful, followed by esp_restart(). + * + * @return * - ESP_FAIL: if not successful. * - ESP_ERR_OTA_ROLLBACK_FAILED: The rollback is not possible due to flash does not have any apps. */ diff --git a/components/bootloader_support/include/bootloader_memory_utils.h b/components/bootloader_support/include/bootloader_memory_utils.h index e77e4cc8aab1..cd6378ca6c45 100644 --- a/components/bootloader_support/include/bootloader_memory_utils.h +++ b/components/bootloader_support/include/bootloader_memory_utils.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2010-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2010-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -87,6 +87,7 @@ __attribute__((always_inline)) inline static bool esp_ptr_in_diram_iram(const void *p) { // TODO: IDF-5980 esp32c6 D/I RAM share the same address #if SOC_DIRAM_IRAM_LOW == SOC_DIRAM_DRAM_LOW + (void)p; return false; #else return ((intptr_t)p >= SOC_DIRAM_IRAM_LOW && (intptr_t)p < SOC_DIRAM_IRAM_HIGH); @@ -105,6 +106,7 @@ inline static bool esp_ptr_in_rtc_iram_fast(const void *p) { #if SOC_RTC_FAST_MEM_SUPPORTED && (SOC_RTC_IRAM_LOW != SOC_RTC_DRAM_LOW) return ((intptr_t)p >= SOC_RTC_IRAM_LOW && (intptr_t)p < SOC_RTC_IRAM_HIGH); #else + (void)p; return false; #endif } @@ -121,6 +123,7 @@ inline static bool esp_ptr_in_rtc_dram_fast(const void *p) { #if SOC_RTC_FAST_MEM_SUPPORTED return ((intptr_t)p >= SOC_RTC_DRAM_LOW && (intptr_t)p < SOC_RTC_DRAM_HIGH); #else + (void)p; return false; #endif } diff --git a/components/bootloader_support/src/esp32h2/bootloader_esp32h2.c b/components/bootloader_support/src/esp32h2/bootloader_esp32h2.c index 4c5b6e7e1068..aad2c526007b 100644 --- a/components/bootloader_support/src/esp32h2/bootloader_esp32h2.c +++ b/components/bootloader_support/src/esp32h2/bootloader_esp32h2.c @@ -41,7 +41,6 @@ #include "hal/lpwdt_ll.h" #include "soc/lp_wdt_reg.h" #include "soc/pmu_reg.h" -#include "soc/lpperi_struct.h" #include "hal/efuse_hal.h" #include "hal/regi2c_ctrl_ll.h" #include "hal/brownout_ll.h" @@ -110,9 +109,6 @@ esp_err_t bootloader_init(void) { esp_err_t ret = ESP_OK; - // Assign the compatible LPPERI register address in case it is used in the bootloader - lpperi_compatible_reg_addr_init(); - bootloader_hardware_init(); bootloader_ana_reset_config(); bootloader_super_wdt_auto_feed(); diff --git a/components/bootloader_support/src/esp32h2/flash_encryption_secure_features.c b/components/bootloader_support/src/esp32h2/flash_encryption_secure_features.c index f1a6d2aef9c3..d4b063a4d6b7 100644 --- a/components/bootloader_support/src/esp32h2/flash_encryption_secure_features.c +++ b/components/bootloader_support/src/esp32h2/flash_encryption_secure_features.c @@ -1,15 +1,18 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include "esp_flash_encrypt.h" #include "esp_secure_boot.h" #include "esp_efuse.h" #include "esp_efuse_table.h" #include "esp_log.h" +#include "hal/spi_flash_encrypted_ll.h" +#include "soc/soc_caps.h" #include "sdkconfig.h" static __attribute__((unused)) const char *TAG = "flash_encrypt"; @@ -33,6 +36,14 @@ esp_err_t esp_flash_encryption_enable_secure_features(void) esp_efuse_write_field_bit(ESP_EFUSE_DIS_DIRECT_BOOT); +#if defined(CONFIG_SECURE_FLASH_ENCRYPTION_MODE_RELEASE) && defined(SOC_FLASH_ENCRYPTION_XTS_AES_SUPPORT_PSEUDO_ROUND) + if (spi_flash_encrypt_ll_is_pseudo_rounds_function_supported()) { + ESP_LOGI(TAG, "Enable XTS-AES pseudo rounds function..."); + uint8_t xts_pseudo_level = CONFIG_SECURE_FLASH_PSEUDO_ROUND_FUNC_STRENGTH; + esp_efuse_write_field_blob(ESP_EFUSE_XTS_DPA_PSEUDO_LEVEL, &xts_pseudo_level, ESP_EFUSE_XTS_DPA_PSEUDO_LEVEL[0]->bit_count); + } +#endif + #if defined(CONFIG_SECURE_BOOT_V2_ENABLED) && !defined(CONFIG_SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS) // This bit is set when enabling Secure Boot V2, but we can't enable it until this later point in the first boot // otherwise the Flash Encryption key cannot be read protected diff --git a/components/bootloader_support/src/flash_encrypt.c b/components/bootloader_support/src/flash_encrypt.c index 4bfa33e87dc2..381f17ed40e2 100644 --- a/components/bootloader_support/src/flash_encrypt.c +++ b/components/bootloader_support/src/flash_encrypt.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 */ @@ -12,6 +12,7 @@ #include "esp_flash_encrypt.h" #include "esp_secure_boot.h" #include "hal/efuse_hal.h" +#include "hal/spi_flash_encrypted_ll.h" #include "hal/spi_flash_encrypt_hal.h" #include "soc/soc_caps.h" @@ -210,8 +211,10 @@ void esp_flash_encryption_set_release_mode(void) #endif // !CONFIG_IDF_TARGET_ESP32 #ifdef SOC_FLASH_ENCRYPTION_XTS_AES_SUPPORT_PSEUDO_ROUND - uint8_t xts_pseudo_level = ESP_XTS_AES_PSEUDO_ROUNDS_LOW; - esp_efuse_write_field_blob(ESP_EFUSE_XTS_DPA_PSEUDO_LEVEL, &xts_pseudo_level, ESP_EFUSE_XTS_DPA_PSEUDO_LEVEL[0]->bit_count); + if (spi_flash_encrypt_ll_is_pseudo_rounds_function_supported()) { + uint8_t xts_pseudo_level = ESP_XTS_AES_PSEUDO_ROUNDS_LOW; + esp_efuse_write_field_blob(ESP_EFUSE_XTS_DPA_PSEUDO_LEVEL, &xts_pseudo_level, ESP_EFUSE_XTS_DPA_PSEUDO_LEVEL[0]->bit_count); + } #endif #ifdef CONFIG_IDF_TARGET_ESP32 @@ -476,11 +479,13 @@ bool esp_flash_encryption_cfg_verify_release_mode(void) result &= secure; #if SOC_FLASH_ENCRYPTION_XTS_AES_SUPPORT_PSEUDO_ROUND - uint8_t xts_pseudo_level = 0; - esp_efuse_read_field_blob(ESP_EFUSE_XTS_DPA_PSEUDO_LEVEL, &xts_pseudo_level, ESP_EFUSE_XTS_DPA_PSEUDO_LEVEL[0]->bit_count); - if (!xts_pseudo_level) { - result &= false; - ESP_LOGW(TAG, "Not enabled XTS-AES pseudo rounds function (set XTS_DPA_PSEUDO_LEVEL->1 or more)"); + if (spi_flash_encrypt_ll_is_pseudo_rounds_function_supported()) { + uint8_t xts_pseudo_level = 0; + esp_efuse_read_field_blob(ESP_EFUSE_XTS_DPA_PSEUDO_LEVEL, &xts_pseudo_level, ESP_EFUSE_XTS_DPA_PSEUDO_LEVEL[0]->bit_count); + if (!xts_pseudo_level) { + result &= false; + ESP_LOGW(TAG, "Not enabled XTS-AES pseudo rounds function (set XTS_DPA_PSEUDO_LEVEL->1 or more)"); + } } #endif diff --git a/components/bt/CMakeLists.txt b/components/bt/CMakeLists.txt index 77493be647d7..c7d0b9c47197 100644 --- a/components/bt/CMakeLists.txt +++ b/components/bt/CMakeLists.txt @@ -905,7 +905,7 @@ if(CONFIG_BT_ENABLED) add_prebuilt_library(libble_app "${CMAKE_CURRENT_LIST_DIR}/controller/lib_esp32c6/esp32c6-bt-lib/esp32c61/libble_app.a") else() - if(CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY) + if(CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY AND CONFIG_IDF_TARGET_ESP32C2) add_prebuilt_library(libble_app "controller/lib_${target_name}/${target_name}-bt-lib/libble_app_flash.a") else() diff --git a/components/bt/controller/esp32/bt.c b/components/bt/controller/esp32/bt.c index d94c9c050726..30c3f02e6244 100644 --- a/components/bt/controller/esp32/bt.c +++ b/components/bt/controller/esp32/bt.c @@ -450,7 +450,11 @@ static DRAM_ATTR uint8_t btdm_lpcycle_us_frac = 0; // number of fractional bit f #if CONFIG_BTDM_CTRL_MODEM_SLEEP_MODE_ORIG // used low power clock -static DRAM_ATTR uint8_t btdm_lpclk_sel; +#if CONFIG_BTDM_CTRL_LPCLK_SEL_EXT_32K_XTAL +static DRAM_ATTR uint8_t btdm_lpclk_sel = ESP_BT_SLEEP_CLOCK_EXT_32K_XTAL; +#else +static DRAM_ATTR uint8_t btdm_lpclk_sel = ESP_BT_SLEEP_CLOCK_MAIN_XTAL; +#endif /* CONFIG_BTDM_CTRL_LPCLK_SEL_EXT_32K_XTAL */ #endif /* #ifdef CONFIG_BTDM_CTRL_MODEM_SLEEP_MODE_ORIG */ static DRAM_ATTR QueueHandle_t s_wakeup_req_sem = NULL; @@ -1492,6 +1496,117 @@ static void hli_queue_setup_pinned_to_core(int core_id) } #endif /* CONFIG_BTDM_CTRL_HLI */ +// init low-power control resources +static esp_err_t btdm_low_power_mode_init(void) +{ + esp_err_t err = ESP_OK; + +#ifdef CONFIG_PM_ENABLE + s_btdm_allow_light_sleep = false; +#endif + + // set default sleep clock cycle and its fractional bits + btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT; + btdm_lpcycle_us = 2 << (btdm_lpcycle_us_frac); + +#if CONFIG_BTDM_CTRL_MODEM_SLEEP_MODE_ORIG + if (btdm_lpclk_sel == ESP_BT_SLEEP_CLOCK_EXT_32K_XTAL) { + // check whether or not EXT_CRYS is working + if (rtc_clk_slow_src_get() == SOC_RTC_SLOW_CLK_SRC_XTAL32K) { +#ifdef CONFIG_PM_ENABLE + s_btdm_allow_light_sleep = true; +#endif + } else { + ESP_LOGW(BTDM_LOG_TAG, "32.768kHz XTAL not detected, fall back to main XTAL as Bluetooth sleep clock\n" + "light sleep mode will not be able to apply when bluetooth is enabled"); + btdm_lpclk_sel = ESP_BT_SLEEP_CLOCK_MAIN_XTAL; // set default value + } + } else if (btdm_lpclk_sel != ESP_BT_SLEEP_CLOCK_MAIN_XTAL) { + assert(0); + } + + bool select_src_ret __attribute__((unused)); + bool set_div_ret __attribute__((unused)); + if (btdm_lpclk_sel == ESP_BT_SLEEP_CLOCK_MAIN_XTAL) { + select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_XTAL); + set_div_ret = btdm_lpclk_set_div(esp_clk_xtal_freq() * 2 / MHZ - 1); + assert(select_src_ret && set_div_ret); + btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT; + btdm_lpcycle_us = 2 << (btdm_lpcycle_us_frac); + } else { // btdm_lpclk_sel == BTDM_LPCLK_SEL_XTAL32K + select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_XTAL32K); + set_div_ret = btdm_lpclk_set_div(0); + assert(select_src_ret && set_div_ret); + btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT; + btdm_lpcycle_us = (RTC_CLK_CAL_FRACT > 15) ? (1000000 << (RTC_CLK_CAL_FRACT - 15)) : + (1000000 >> (15 - RTC_CLK_CAL_FRACT)); + assert(btdm_lpcycle_us != 0); + } + btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_ORIG); + +#elif CONFIG_BTDM_CTRL_MODEM_SLEEP_MODE_EVED + btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_EVED); +#else + btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_NONE); +#endif + +#ifdef CONFIG_PM_ENABLE + if (!s_btdm_allow_light_sleep) { + if ((err = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "btLS", &s_light_sleep_pm_lock)) != ESP_OK) { + return err; + } + } + if ((err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "bt", &s_pm_lock)) != ESP_OK) { + return err; + } + esp_timer_create_args_t create_args = { + .callback = btdm_slp_tmr_callback, + .arg = NULL, + .name = "btSlp" + }; + if ((err = esp_timer_create(&create_args, &s_btdm_slp_tmr)) != ESP_OK) { + return err; + } + + s_pm_lock_acquired = true; +#endif + + return err; +} + +esp_bt_sleep_clock_t esp_bt_get_lpclk_src(void) +{ +#if CONFIG_BTDM_CTRL_MODEM_SLEEP_MODE_ORIG + if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_INITED && + btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED) { + return ESP_BT_SLEEP_CLOCK_NONE; + } + return btdm_lpclk_sel; +#else + return ESP_BT_SLEEP_CLOCK_NONE; +#endif +} + +esp_err_t esp_bt_set_lpclk_src(esp_bt_sleep_clock_t lpclk) +{ +#if CONFIG_BTDM_CTRL_MODEM_SLEEP_MODE_ORIG + if (lpclk < ESP_BT_SLEEP_CLOCK_MAIN_XTAL || lpclk > ESP_BT_SLEEP_CLOCK_EXT_32K_XTAL) { + return ESP_ERR_INVALID_ARG; + } + + if (btdm_controller_status == ESP_BT_CONTROLLER_STATUS_INITED || + btdm_controller_status == ESP_BT_CONTROLLER_STATUS_ENABLED) { + ESP_LOGW(BTDM_LOG_TAG, "Please set the Bluetooth sleep clock source before Bluetooth initialization"); + return ESP_ERR_INVALID_STATE; + } + + btdm_lpclk_sel = lpclk; + return ESP_OK; +#else + return ESP_ERR_NOT_SUPPORTED; +#endif +} + esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) { esp_err_t err; @@ -1556,85 +1671,17 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) periph_module_enable(PERIPH_BT_MODULE); periph_module_reset(PERIPH_BT_MODULE); -#ifdef CONFIG_PM_ENABLE - s_btdm_allow_light_sleep = false; -#endif - - // set default sleep clock cycle and its fractional bits - btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT; - btdm_lpcycle_us = 2 << (btdm_lpcycle_us_frac); - -#if CONFIG_BTDM_CTRL_MODEM_SLEEP_MODE_ORIG - - btdm_lpclk_sel = BTDM_LPCLK_SEL_XTAL; // set default value -#if CONFIG_BTDM_CTRL_LPCLK_SEL_EXT_32K_XTAL - // check whether or not EXT_CRYS is working - if (rtc_clk_slow_src_get() == SOC_RTC_SLOW_CLK_SRC_XTAL32K) { - btdm_lpclk_sel = BTDM_LPCLK_SEL_XTAL32K; // External 32kHz XTAL -#ifdef CONFIG_PM_ENABLE - s_btdm_allow_light_sleep = true; -#endif - } else { - ESP_LOGW(BTDM_LOG_TAG, "32.768kHz XTAL not detected, fall back to main XTAL as Bluetooth sleep clock\n" - "light sleep mode will not be able to apply when bluetooth is enabled"); - btdm_lpclk_sel = BTDM_LPCLK_SEL_XTAL; // set default value - } -#else - btdm_lpclk_sel = BTDM_LPCLK_SEL_XTAL; // set default value -#endif - - bool select_src_ret __attribute__((unused)); - bool set_div_ret __attribute__((unused)); - if (btdm_lpclk_sel == BTDM_LPCLK_SEL_XTAL) { - select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_XTAL); - set_div_ret = btdm_lpclk_set_div(esp_clk_xtal_freq() * 2 / MHZ - 1); - assert(select_src_ret && set_div_ret); - btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT; - btdm_lpcycle_us = 2 << (btdm_lpcycle_us_frac); - } else { // btdm_lpclk_sel == BTDM_LPCLK_SEL_XTAL32K - select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_XTAL32K); - set_div_ret = btdm_lpclk_set_div(0); - assert(select_src_ret && set_div_ret); - btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT; - btdm_lpcycle_us = (RTC_CLK_CAL_FRACT > 15) ? (1000000 << (RTC_CLK_CAL_FRACT - 15)) : - (1000000 >> (15 - RTC_CLK_CAL_FRACT)); - assert(btdm_lpcycle_us != 0); - } - btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_ORIG); - -#elif CONFIG_BTDM_CTRL_MODEM_SLEEP_MODE_EVED - btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_EVED); -#else - btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_NONE); -#endif - #if CONFIG_BTDM_CTRL_HCI_UART_FLOW_CTRL_EN sdk_config_set_uart_flow_ctrl_enable(true); #else sdk_config_set_uart_flow_ctrl_enable(false); #endif -#ifdef CONFIG_PM_ENABLE - if (!s_btdm_allow_light_sleep) { - if ((err = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "btLS", &s_light_sleep_pm_lock)) != ESP_OK) { - goto error; - } - } - if ((err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "bt", &s_pm_lock)) != ESP_OK) { - goto error; - } - esp_timer_create_args_t create_args = { - .callback = btdm_slp_tmr_callback, - .arg = NULL, - .name = "btSlp" - }; - if ((err = esp_timer_create(&create_args, &s_btdm_slp_tmr)) != ESP_OK) { + if ((err = btdm_low_power_mode_init()) != ESP_OK) { + ESP_LOGE(BTDM_LOG_TAG, "Low power module initialization failed"); goto error; } - s_pm_lock_acquired = true; -#endif - #if CONFIG_SW_COEXIST_ENABLE coex_init(); #endif @@ -1673,10 +1720,9 @@ esp_err_t esp_bt_controller_deinit(void) return ESP_OK; } -static void bt_controller_deinit_internal(void) +// deinit low power control resources +static void btdm_low_power_mode_deinit(void) { - periph_module_disable(PERIPH_BT_MODULE); - #ifdef CONFIG_PM_ENABLE if (!s_btdm_allow_light_sleep) { esp_pm_lock_delete(s_light_sleep_pm_lock); @@ -1697,6 +1743,16 @@ static void bt_controller_deinit_internal(void) s_pm_lock_acquired = false; #endif + btdm_lpcycle_us = 0; + btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_NONE); +} + +static void bt_controller_deinit_internal(void) +{ + periph_module_disable(PERIPH_BT_MODULE); + + btdm_low_power_mode_deinit(); + if (s_wakeup_req_sem) { semphr_delete_wrapper(s_wakeup_req_sem); s_wakeup_req_sem = NULL; @@ -1709,9 +1765,6 @@ static void bt_controller_deinit_internal(void) btdm_controller_status = ESP_BT_CONTROLLER_STATUS_IDLE; - btdm_lpcycle_us = 0; - btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_NONE); - esp_bt_power_domain_off(); esp_phy_modem_deinit(); diff --git a/components/bt/controller/esp32c2/bt.c b/components/bt/controller/esp32c2/bt.c index fe26d28fd68d..26b9e9bd8691 100644 --- a/components/bt/controller/esp32c2/bt.c +++ b/components/bt/controller/esp32c2/bt.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 */ @@ -1147,9 +1147,17 @@ esp_err_t esp_ble_tx_power_set(esp_ble_power_type_t power_type, esp_power_level_ switch (power_type) { case ESP_BLE_PWR_TYPE_DEFAULT: + if (ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0, power_level) == 0) { + stat = ESP_OK; + } + break; case ESP_BLE_PWR_TYPE_ADV: + if (ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_ADV, 0xFF, power_level) == 0) { + stat = ESP_OK; + } + break; case ESP_BLE_PWR_TYPE_SCAN: - if (ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0, power_level) == 0) { + if (ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_SCAN, 0, power_level) == 0) { stat = ESP_OK; } break; @@ -1179,9 +1187,13 @@ esp_err_t esp_ble_tx_power_set_enhanced(esp_ble_enhanced_power_type_t power_type esp_err_t stat = ESP_FAIL; switch (power_type) { case ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT: + if (ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0, power_level) == 0) { + stat = ESP_OK; + } + break; case ESP_BLE_ENHANCED_PWR_TYPE_SCAN: case ESP_BLE_ENHANCED_PWR_TYPE_INIT: - if (ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0, power_level) == 0) { + if (ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_SCAN, 0, power_level) == 0) { stat = ESP_OK; } break; @@ -1204,11 +1216,15 @@ esp_power_level_t esp_ble_tx_power_get(esp_ble_power_type_t power_type) int tx_level = 0; switch (power_type) { - case ESP_BLE_PWR_TYPE_ADV: - case ESP_BLE_PWR_TYPE_SCAN: case ESP_BLE_PWR_TYPE_DEFAULT: tx_level = ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0); break; + case ESP_BLE_PWR_TYPE_ADV: + tx_level = ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_ADV, 0); + break; + case ESP_BLE_PWR_TYPE_SCAN: + tx_level = ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_SCAN, 0); + break; case ESP_BLE_PWR_TYPE_CONN_HDL0: case ESP_BLE_PWR_TYPE_CONN_HDL1: case ESP_BLE_PWR_TYPE_CONN_HDL2: @@ -1237,9 +1253,11 @@ esp_power_level_t esp_ble_tx_power_get_enhanced(esp_ble_enhanced_power_type_t po switch (power_type) { case ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT: + tx_level = ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0); + break; case ESP_BLE_ENHANCED_PWR_TYPE_SCAN: case ESP_BLE_ENHANCED_PWR_TYPE_INIT: - tx_level = ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0); + tx_level = ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_SCAN, 0); break; case ESP_BLE_ENHANCED_PWR_TYPE_ADV: case ESP_BLE_ENHANCED_PWR_TYPE_CONN: diff --git a/components/bt/controller/esp32c5/Kconfig.in b/components/bt/controller/esp32c5/Kconfig.in index 6ad2a9ce8c05..677016becd9d 100644 --- a/components/bt/controller/esp32c5/Kconfig.in +++ b/components/bt/controller/esp32c5/Kconfig.in @@ -310,6 +310,24 @@ config BT_LE_CONTROLLER_LOG_DUMP_ONLY help Only operate in dump mode +config BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + bool "Store ble controller logs to flash(Experimental)" + depends on !BT_LE_CONTROLLER_LOG_DUMP_ONLY + depends on BT_LE_CONTROLLER_LOG_ENABLED + default n + help + Store ble controller logs to flash memory. + +config BT_LE_CONTROLLER_LOG_PARTITION_SIZE + int "size of ble controller log partition(Multiples of 4K)" + depends on BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + default 65536 + help + The size of ble controller log partition shall be a multiples of 4K. + The name of log partition shall be "bt_ctrl_log". + The partition type shall be ESP_PARTITION_TYPE_DATA. + The partition sub_type shall be ESP_PARTITION_SUBTYPE_ANY. + config BT_LE_LOG_CTRL_BUF1_SIZE int "size of the first BLE controller LOG buffer" depends on BT_LE_CONTROLLER_LOG_ENABLED @@ -575,3 +593,89 @@ config BT_LE_SCAN_DUPL_CACHE_REFRESH_PERIOD config BT_LE_MSYS_INIT_IN_CONTROLLER bool "Msys Mbuf Init in Controller" default y + +config BT_LE_TX_CCA_ENABLED + bool "Enable TX CCA feature" + default n + help + Enable CCA feature to cancel sending the packet if the signal power is stronger than CCA threshold. + +config BT_LE_CCA_RSSI_THRESH + int "CCA RSSI threshold value" + depends on BT_LE_TX_CCA_ENABLED + range 20 100 + default 20 + help + Power threshold of CCA in unit of -1 dBm. + +choice BT_LE_DFT_TX_POWER_LEVEL_DBM + prompt "BLE default Tx power level(dBm)" + default BT_LE_DFT_TX_POWER_LEVEL_P9 + help + Specify default Tx power level(dBm). + config BT_LE_DFT_TX_POWER_LEVEL_N24 + bool "-24dBm" + config BT_LE_DFT_TX_POWER_LEVEL_N21 + bool "-21dBm" + config BT_LE_DFT_TX_POWER_LEVEL_N18 + bool "-18dBm" + config BT_LE_DFT_TX_POWER_LEVEL_N15 + bool "-15dBm" + config BT_LE_DFT_TX_POWER_LEVEL_N12 + bool "-12dBm" + config BT_LE_DFT_TX_POWER_LEVEL_N9 + bool "-9dBm" + config BT_LE_DFT_TX_POWER_LEVEL_N6 + bool "-6dBm" + config BT_LE_DFT_TX_POWER_LEVEL_N3 + bool "-3dBm" + config BT_LE_DFT_TX_POWER_LEVEL_N0 + bool "0dBm" + config BT_LE_DFT_TX_POWER_LEVEL_P3 + bool "+3dBm" + config BT_LE_DFT_TX_POWER_LEVEL_P6 + bool "+6dBm" + config BT_LE_DFT_TX_POWER_LEVEL_P9 + bool "+9dBm" + config BT_LE_DFT_TX_POWER_LEVEL_P12 + bool "+12dBm" + config BT_LE_DFT_TX_POWER_LEVEL_P15 + bool "+15dBm" + config BT_LE_DFT_TX_POWER_LEVEL_P18 + bool "+18dBm" + config BT_LE_DFT_TX_POWER_LEVEL_P20 + bool "+20dBm" +endchoice + +config BT_LE_DFT_TX_POWER_LEVEL_DBM_EFF + int + default -15 if BT_LE_DFT_TX_POWER_LEVEL_N15 + default -12 if BT_LE_DFT_TX_POWER_LEVEL_N12 + default -9 if BT_LE_DFT_TX_POWER_LEVEL_N9 + default -6 if BT_LE_DFT_TX_POWER_LEVEL_N6 + default -3 if BT_LE_DFT_TX_POWER_LEVEL_N3 + default 0 if BT_LE_DFT_TX_POWER_LEVEL_N0 + default 3 if BT_LE_DFT_TX_POWER_LEVEL_P3 + default 6 if BT_LE_DFT_TX_POWER_LEVEL_P6 + default 9 if BT_LE_DFT_TX_POWER_LEVEL_P9 + default 12 if BT_LE_DFT_TX_POWER_LEVEL_P12 + default 15 if BT_LE_DFT_TX_POWER_LEVEL_P15 + default 18 if BT_LE_DFT_TX_POWER_LEVEL_P18 + default 20 if BT_LE_DFT_TX_POWER_LEVEL_P20 + default 0 + +config BT_LE_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS + bool "Enable enhanced Access Address check in CONNECT_IND" + default n + help + Enabling this option will add stricter verification of the Access Address in the CONNECT_IND PDU. + This improves security by ensuring that only connection requests with valid Access Addresses are accepted. + If disabled, only basic checks are applied, improving compatibility. + +config BT_CTRL_RUN_IN_FLASH_ONLY + bool "Reduce BLE IRAM usage (READ DOCS FIRST) (EXPERIMENTAL)" + default n + help + Move most IRAM into flash. This will increase the usage of flash and reduce ble performance. + Because the code is moved to the flash, the execution speed of the code is reduced. + To have a small impact on performance, you need to enable flash suspend (SPI_FLASH_AUTO_SUSPEND). diff --git a/components/bt/controller/esp32c5/bt.c b/components/bt/controller/esp32c5/bt.c index 1742094628b4..8466cd5bf0ac 100644 --- a/components/bt/controller/esp32c5/bt.c +++ b/components/bt/controller/esp32c5/bt.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 */ @@ -127,6 +127,10 @@ extern void r_ble_lll_rfmgmt_set_sleep_cb(void *s_cb, void *w_cb, void *s_arg, extern void r_ble_rtc_wake_up_state_clr(void); extern int os_msys_init(void); extern void os_msys_deinit(void); +#if CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY +extern void r_ble_ll_scan_start_time_init_compensation(uint32_t init_compensation); +extern void r_priv_sdk_config_insert_proc_time_set(uint16_t insert_proc_time); +#endif // CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY #if CONFIG_FREERTOS_USE_TICKLESS_IDLE extern sleep_retention_entries_config_t *r_esp_ble_mac_retention_link_get(uint8_t *size, uint8_t extra); extern void r_esp_ble_set_wakeup_overhead(uint32_t overhead); @@ -170,6 +174,9 @@ static int esp_ecc_gen_dh_key(const uint8_t *peer_pub_key_x, const uint8_t *peer const uint8_t *our_priv_key, uint8_t *out_dhkey); #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, bool end); +#if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE +static void esp_bt_ctrl_log_partition_get_and_erase_first_block(void); +#endif // #if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED /* Local variable definition *************************************************************************** @@ -178,6 +185,204 @@ static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, b static DRAM_ATTR esp_bt_controller_status_t ble_controller_status = ESP_BT_CONTROLLER_STATUS_IDLE; #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED const static uint32_t log_bufs_size[] = {CONFIG_BT_LE_LOG_CTRL_BUF1_SIZE, CONFIG_BT_LE_LOG_HCI_BUF_SIZE, CONFIG_BT_LE_LOG_CTRL_BUF2_SIZE}; +enum log_out_mode { + LOG_DUMP_MEMORY, + LOG_ASYNC_OUT, + LOG_STORAGE_TO_FLASH, +}; + +bool log_is_inited = false; +#if CONFIG_BT_LE_CONTROLLER_LOG_DUMP_ONLY +uint8_t log_output_mode = LOG_DUMP_MEMORY; +#else +#if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE +uint8_t log_output_mode = LOG_STORAGE_TO_FLASH; +#else +uint8_t log_output_mode = LOG_ASYNC_OUT; +#endif // CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE +#endif // CONFIG_BT_LE_CONTROLLER_LOG_DUMP_ONLY + +void esp_bt_log_output_mode_set(uint8_t output_mode) +{ + log_output_mode = output_mode; +} + +uint8_t esp_bt_log_output_mode_get(void) +{ + return log_output_mode; +} + +esp_err_t esp_bt_controller_log_init(uint8_t log_output_mode) +{ + esp_err_t ret = ESP_OK; + interface_func_t bt_controller_log_interface; + bt_controller_log_interface = esp_bt_controller_log_interface; + bool task_create; + uint8_t buffers = 0; + + if (log_is_inited) { + return ret; + } + +#if CONFIG_BT_LE_CONTROLLER_LOG_CTRL_ENABLED + buffers |= ESP_BLE_LOG_BUF_CONTROLLER; +#endif // CONFIG_BT_LE_CONTROLLER_LOG_CTRL_ENABLED +#if CONFIG_BT_LE_CONTROLLER_LOG_HCI_ENABLED + buffers |= ESP_BLE_LOG_BUF_HCI; +#endif // CONFIG_BT_LE_CONTROLLER_LOG_HCI_ENABLED + + switch (log_output_mode) { + case LOG_DUMP_MEMORY: + task_create = false; + break; + case LOG_ASYNC_OUT: + case LOG_STORAGE_TO_FLASH: + task_create = true; +#if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + if (log_output_mode == LOG_STORAGE_TO_FLASH) { + esp_bt_ctrl_log_partition_get_and_erase_first_block(); + } +#endif // CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + break; + default: + assert(0); + } + + ret = r_ble_log_init_async(bt_controller_log_interface, task_create, buffers, (uint32_t *)log_bufs_size); + if (ret == ESP_OK) { + log_is_inited = true; + } + + return ret; +} + +void esp_bt_ontroller_log_deinit(void) +{ + r_ble_log_deinit_async(); + log_is_inited = false; +} + +#if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE +#include "esp_partition.h" +#include "hal/wdt_hal.h" + +#define MAX_STORAGE_SIZE (CONFIG_BT_LE_CONTROLLER_LOG_PARTITION_SIZE) +#define BLOCK_SIZE (4096) +#define THRESHOLD (3072) +#define PARTITION_NAME "bt_ctrl_log" + +static const esp_partition_t *log_partition; +static uint32_t write_index = 0; +static uint32_t next_erase_index = BLOCK_SIZE; +static bool block_erased = false; +static bool stop_write = false; +static bool is_filled = false; + +static void esp_bt_ctrl_log_partition_get_and_erase_first_block(void) +{ + log_partition = NULL; + assert(MAX_STORAGE_SIZE % BLOCK_SIZE == 0); + // Find the partition map in the partition table + log_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, PARTITION_NAME); + assert(log_partition != NULL); + // Prepare data to be read later using the mapped address + ESP_ERROR_CHECK(esp_partition_erase_range(log_partition, 0, BLOCK_SIZE)); + write_index = 0; + next_erase_index = BLOCK_SIZE; + block_erased = false; + is_filled = false; + stop_write = false; +} + +static int esp_bt_controller_log_storage(uint32_t len, const uint8_t *addr, bool end) +{ + if (len > MAX_STORAGE_SIZE) { + return -1; + } + + if (stop_write) { + return 0; + } + + if (((write_index) % BLOCK_SIZE) >= THRESHOLD && !block_erased) { + // esp_rom_printf("Ers nxt: %d,%d\n", next_erase_index, write_index); + esp_partition_erase_range(log_partition, next_erase_index, BLOCK_SIZE); + next_erase_index = (next_erase_index + BLOCK_SIZE) % MAX_STORAGE_SIZE; + block_erased = true; + } + + if (((write_index + len) / BLOCK_SIZE) > (write_index / BLOCK_SIZE)) { + block_erased = false; + } + + if (write_index + len <= MAX_STORAGE_SIZE) { + esp_partition_write(log_partition, write_index, addr, len); + write_index = (write_index + len) % MAX_STORAGE_SIZE; + } else { + uint32_t first_part_len = MAX_STORAGE_SIZE - write_index; + esp_partition_write(log_partition, write_index, addr, first_part_len); + esp_partition_write(log_partition, 0, addr + first_part_len, len - first_part_len); + write_index = len - first_part_len; + is_filled = true; + // esp_rom_printf("old idx: %d,%d\n",next_erase_index, write_index); + } + + return 0; +} + +void esp_bt_read_ctrl_log_from_flash(bool output) +{ + esp_partition_mmap_handle_t mmap_handle; + uint32_t read_index; + const void *mapped_ptr; + const uint8_t *buffer; + uint32_t print_len; + uint32_t max_print_len; + esp_err_t err; + + print_len = 0; + max_print_len = 4096; + err = esp_partition_mmap(log_partition, 0, MAX_STORAGE_SIZE, ESP_PARTITION_MMAP_DATA, &mapped_ptr, &mmap_handle); + if (err != ESP_OK) { + ESP_LOGE("FLASH", "Mmap failed: %s", esp_err_to_name(err)); + return; + } + + portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; + portENTER_CRITICAL_SAFE(&spinlock); + esp_panic_handler_reconfigure_wdts(5000); + r_ble_log_async_output_dump_all(true); + esp_bt_ontroller_log_deinit(); + stop_write = true; + + buffer = (const uint8_t *)mapped_ptr; + esp_panic_handler_reconfigure_wdts(5000); + if (is_filled) { + read_index = next_erase_index; + } else { + read_index = 0; + } + + esp_rom_printf("\r\nREAD_CHECK:%ld,%ld,%d\r\n",read_index, write_index, is_filled); + esp_rom_printf("\r\n[DUMP_START:"); + while (read_index != write_index) { + esp_rom_printf("%02x ", buffer[read_index]); + if (print_len > max_print_len) { + esp_panic_handler_reconfigure_wdts(5000); + print_len = 0; + } + + print_len++; + read_index = (read_index + 1) % MAX_STORAGE_SIZE; + } + + esp_rom_printf(":DUMP_END]\r\n"); + portEXIT_CRITICAL_SAFE(&spinlock); + esp_partition_munmap(mmap_handle); + err = esp_bt_controller_log_init(log_output_mode); + assert(err == ESP_OK); +} +#endif // CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED /* This variable tells if BLE is running */ @@ -186,10 +391,20 @@ static bool s_ble_active = false; static DRAM_ATTR esp_pm_lock_handle_t s_pm_lock = NULL; #endif // CONFIG_PM_ENABLE static DRAM_ATTR modem_clock_lpclk_src_t s_bt_lpclk_src = MODEM_CLOCK_LPCLK_SRC_INVALID; - #define BLE_RTC_DELAY_US_LIGHT_SLEEP (2500) #define BLE_RTC_DELAY_US_MODEM_SLEEP (500) +#define BLE_CONTROLLER_MALLOC_CAPS (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT|MALLOC_CAP_DMA) +void *malloc_ble_controller_mem(size_t size) +{ + return heap_caps_malloc(size, BLE_CONTROLLER_MALLOC_CAPS); +} + +uint32_t get_ble_controller_free_heap_size(void) +{ + return heap_caps_get_free_size(BLE_CONTROLLER_MALLOC_CAPS); +} + static const struct osi_coex_funcs_t s_osi_coex_funcs_ro = { ._magic = OSI_COEX_MAGIC_VALUE, ._version = OSI_COEX_VERSION, @@ -283,8 +498,11 @@ static int esp_ecc_gen_dh_key(const uint8_t *peer_pub_key_x, const uint8_t *peer static int esp_intr_alloc_wrapper(int source, int flags, intr_handler_t handler, void *arg, void **ret_handle_in) { - int rc = esp_intr_alloc(source, flags | ESP_INTR_FLAG_IRAM, handler, - arg, (intr_handle_t *)ret_handle_in); +#if CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY + int rc = esp_intr_alloc(source, flags, handler, arg, (intr_handle_t *)ret_handle_in); +#else + int rc = esp_intr_alloc(source, flags | ESP_INTR_FLAG_IRAM, handler, arg, (intr_handle_t *)ret_handle_in); +#endif return rc; } @@ -377,7 +595,6 @@ static esp_err_t sleep_modem_ble_mac_retention_init(void *arg) ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Modem BLE MAC retention initialization"); } return err; - return ESP_OK; } static esp_err_t sleep_modem_ble_mac_modem_state_init(uint8_t extra) @@ -409,6 +626,7 @@ void IRAM_ATTR sleep_modem_light_sleep_overhead_set(uint32_t overhead) } #endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */ + esp_err_t controller_sleep_init(void) { esp_err_t rc = 0; @@ -423,13 +641,13 @@ esp_err_t controller_sleep_init(void) BLE_RTC_DELAY_US_MODEM_SLEEP); #endif /* FREERTOS_USE_TICKLESS_IDLE */ #endif // CONFIG_BT_LE_SLEEP_ENABLE + #ifdef CONFIG_PM_ENABLE rc = esp_pm_lock_create(ESP_PM_CPU_FREQ_MAX, 0, "bt", &s_pm_lock); if (rc != ESP_OK) { goto error; } #endif // CONFIG_PM_ENABLE - #if CONFIG_BT_LE_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE /* Create a new regdma link for BLE related register restoration */ rc = sleep_modem_ble_mac_modem_state_init(0); @@ -611,7 +829,6 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) uint8_t hci_transport_mode; memset(&npl_info, 0, sizeof(ble_npl_count_info_t)); - if (ble_controller_status != ESP_BT_CONTROLLER_STATUS_IDLE) { ESP_LOGW(NIMBLE_PORT_LOG_TAG, "invalid controller state"); return ESP_ERR_INVALID_STATE; @@ -674,20 +891,7 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) #endif // CONFIG_SW_COEXIST_ENABLE #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED - interface_func_t bt_controller_log_interface; - bt_controller_log_interface = esp_bt_controller_log_interface; - uint8_t buffers = 0; -#if CONFIG_BT_LE_CONTROLLER_LOG_CTRL_ENABLED - buffers |= ESP_BLE_LOG_BUF_CONTROLLER; -#endif // CONFIG_BT_LE_CONTROLLER_LOG_CTRL_ENABLED -#if CONFIG_BT_LE_CONTROLLER_LOG_HCI_ENABLED - buffers |= ESP_BLE_LOG_BUF_HCI; -#endif // CONFIG_BT_LE_CONTROLLER_LOG_HCI_ENABLED -#if CONFIG_BT_LE_CONTROLLER_LOG_DUMP_ONLY - ret = r_ble_log_init_async(bt_controller_log_interface, false, buffers, (uint32_t *)log_bufs_size); -#else - ret = r_ble_log_init_async(bt_controller_log_interface, true, buffers, (uint32_t *)log_bufs_size); -#endif // CONFIG_BT_CONTROLLER_LOG_DUMP + ret = esp_bt_controller_log_init(log_output_mode); if (ret != ESP_OK) { ESP_LOGW(NIMBLE_PORT_LOG_TAG, "ble_controller_log_init failed %d", ret); goto modem_deint; @@ -720,6 +924,7 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) ESP_LOGW(NIMBLE_PORT_LOG_TAG, "controller_sleep_init failed %d", ret); goto free_controller; } + ESP_ERROR_CHECK(esp_read_mac((uint8_t *)mac, ESP_MAC_BT)); ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Bluetooth MAC: %02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); @@ -748,7 +953,7 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) modem_deint: esp_ble_unregister_bb_funcs(); #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED - r_ble_log_deinit_async(); + esp_bt_ontroller_log_deinit(); #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED esp_phy_modem_deinit(); // modem_clock_deselect_lp_clock_source(PERIPH_BT_MODULE); @@ -784,7 +989,7 @@ esp_err_t esp_bt_controller_deinit(void) r_ble_controller_deinit(); esp_ble_unregister_bb_funcs(); #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED - r_ble_log_deinit_async(); + esp_bt_ontroller_log_deinit(); #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED #if CONFIG_BT_NIMBLE_ENABLED @@ -830,6 +1035,10 @@ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode) coex_enable(); #endif // CONFIG_SW_COEXIST_ENABLE +#if CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY + r_ble_ll_scan_start_time_init_compensation(500); + r_priv_sdk_config_insert_proc_time_set(500); +#endif // CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY if (r_ble_controller_enable(mode) != 0) { ret = ESP_FAIL; goto error; @@ -990,9 +1199,17 @@ esp_err_t esp_ble_tx_power_set(esp_ble_power_type_t power_type, esp_power_level_ switch (power_type) { case ESP_BLE_PWR_TYPE_DEFAULT: + if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0, power_level) == 0) { + stat = ESP_OK; + } + break; case ESP_BLE_PWR_TYPE_ADV: + if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_ADV, 0xFF, power_level) == 0) { + stat = ESP_OK; + } + break; case ESP_BLE_PWR_TYPE_SCAN: - if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0, power_level) == 0) { + if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_SCAN, 0, power_level) == 0) { stat = ESP_OK; } break; @@ -1023,9 +1240,13 @@ esp_err_t esp_ble_tx_power_set_enhanced(esp_ble_enhanced_power_type_t power_type esp_err_t stat = ESP_FAIL; switch (power_type) { case ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT: + if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0, power_level) == 0) { + stat = ESP_OK; + } + break; case ESP_BLE_ENHANCED_PWR_TYPE_SCAN: case ESP_BLE_ENHANCED_PWR_TYPE_INIT: - if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0, power_level) == 0) { + if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_SCAN, 0, power_level) == 0) { stat = ESP_OK; } break; @@ -1048,11 +1269,15 @@ esp_power_level_t esp_ble_tx_power_get(esp_ble_power_type_t power_type) int tx_level = 0; switch (power_type) { - case ESP_BLE_PWR_TYPE_ADV: - case ESP_BLE_PWR_TYPE_SCAN: case ESP_BLE_PWR_TYPE_DEFAULT: tx_level = r_ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0); break; + case ESP_BLE_PWR_TYPE_ADV: + tx_level = r_ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_ADV, 0); + break; + case ESP_BLE_PWR_TYPE_SCAN: + tx_level = r_ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_SCAN, 0); + break; case ESP_BLE_PWR_TYPE_CONN_HDL0: case ESP_BLE_PWR_TYPE_CONN_HDL1: case ESP_BLE_PWR_TYPE_CONN_HDL2: @@ -1082,9 +1307,11 @@ esp_power_level_t esp_ble_tx_power_get_enhanced(esp_ble_enhanced_power_type_t po switch (power_type) { case ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT: + tx_level = r_ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0); + break; case ESP_BLE_ENHANCED_PWR_TYPE_SCAN: case ESP_BLE_ENHANCED_PWR_TYPE_INIT: - tx_level = r_ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0); + tx_level = r_ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_SCAN, 0); break; case ESP_BLE_ENHANCED_PWR_TYPE_ADV: case ESP_BLE_ENHANCED_PWR_TYPE_CONN: @@ -1104,24 +1331,40 @@ esp_power_level_t esp_ble_tx_power_get_enhanced(esp_ble_enhanced_power_type_t po #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, bool end) { - for (int i = 0; i < len; i++) { - esp_rom_printf("%02x ", addr[i]); - } - if (end) { - esp_rom_printf("\n"); + if (log_output_mode == LOG_STORAGE_TO_FLASH) { +#if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + esp_bt_controller_log_storage(len, addr, end); +#endif //CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + } else { + portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; + portENTER_CRITICAL_SAFE(&spinlock); + esp_panic_handler_reconfigure_wdts(1000); + for (int i = 0; i < len; i++) { + esp_rom_printf("%02x ", addr[i]); + } + + if (end) { + esp_rom_printf("\n"); + } + portEXIT_CRITICAL_SAFE(&spinlock); } } void esp_ble_controller_log_dump_all(bool output) { - portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; - - portENTER_CRITICAL_SAFE(&spinlock); - esp_panic_handler_reconfigure_wdts(5000); - BT_ASSERT_PRINT("\r\n[DUMP_START:"); - r_ble_log_async_output_dump_all(output); - BT_ASSERT_PRINT(":DUMP_END]\r\n"); - portEXIT_CRITICAL_SAFE(&spinlock); + if (log_output_mode == LOG_STORAGE_TO_FLASH) { +#if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + esp_bt_read_ctrl_log_from_flash(output); +#endif // CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + } else { + portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; + portENTER_CRITICAL_SAFE(&spinlock); + esp_panic_handler_reconfigure_wdts(5000); + BT_ASSERT_PRINT("\r\n[DUMP_START:"); + r_ble_log_async_output_dump_all(output); + BT_ASSERT_PRINT(":DUMP_END]\r\n"); + portEXIT_CRITICAL_SAFE(&spinlock); + } } #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED diff --git a/components/bt/controller/esp32c5/esp_bt_cfg.h b/components/bt/controller/esp32c5/esp_bt_cfg.h index b8bbfd3d4b7c..cac3edc04597 100644 --- a/components/bt/controller/esp32c5/esp_bt_cfg.h +++ b/components/bt/controller/esp32c5/esp_bt_cfg.h @@ -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 */ @@ -148,6 +148,12 @@ extern "C" { #define DEFAULT_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF CONFIG_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF +#ifdef CONFIG_BT_LE_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS +#define DEFAULT_BT_LE_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS (CONFIG_BT_LE_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS) +#else +#define DEFAULT_BT_LE_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS (0) +#endif + #ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_UART #define HCI_UART_EN CONFIG_BT_LE_HCI_INTERFACE_USE_UART #else @@ -216,8 +222,7 @@ extern "C" { #define RTC_FREQ_N (32768) /* in Hz */ -#define BLE_LL_TX_PWR_DBM_N (9) - +#define BLE_LL_TX_PWR_DBM_N (CONFIG_BT_LE_DFT_TX_POWER_LEVEL_DBM_EFF) #define RUN_BQB_TEST (0) #define RUN_QA_TEST (0) diff --git a/components/bt/controller/esp32c6/Kconfig.in b/components/bt/controller/esp32c6/Kconfig.in index 421b4f591722..12db967d0450 100644 --- a/components/bt/controller/esp32c6/Kconfig.in +++ b/components/bt/controller/esp32c6/Kconfig.in @@ -697,3 +697,11 @@ config BT_LE_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS Enabling this option will add stricter verification of the Access Address in the CONNECT_IND PDU. This improves security by ensuring that only connection requests with valid Access Addresses are accepted. If disabled, only basic checks are applied, improving compatibility. + +config BT_CTRL_RUN_IN_FLASH_ONLY + bool "Reduce BLE IRAM usage (READ DOCS FIRST) (EXPERIMENTAL)" + default n + help + Move most IRAM into flash. This will increase the usage of flash and reduce ble performance. + Because the code is moved to the flash, the execution speed of the code is reduced. + To have a small impact on performance, you need to enable flash suspend (SPI_FLASH_AUTO_SUSPEND). diff --git a/components/bt/controller/esp32c6/bt.c b/components/bt/controller/esp32c6/bt.c index e4ec8b682b36..5dd632f58c85 100644 --- a/components/bt/controller/esp32c6/bt.c +++ b/components/bt/controller/esp32c6/bt.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 */ @@ -130,6 +130,10 @@ extern void r_ble_lll_rfmgmt_set_sleep_cb(void *s_cb, void *w_cb, void *s_arg, extern void r_ble_rtc_wake_up_state_clr(void); extern int os_msys_init(void); extern void os_msys_deinit(void); +#if CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY +extern void r_ble_ll_scan_start_time_init_compensation(uint32_t init_compensation); +extern void r_priv_sdk_config_insert_proc_time_set(uint16_t insert_proc_time); +#endif // CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY #if CONFIG_FREERTOS_USE_TICKLESS_IDLE extern sleep_retention_entries_config_t *r_esp_ble_mac_retention_link_get(uint8_t *size, uint8_t extra); extern void r_esp_ble_set_wakeup_overhead(uint32_t overhead); @@ -494,11 +498,13 @@ static int esp_ecc_gen_dh_key(const uint8_t *peer_pub_key_x, const uint8_t *peer return rc; } -static int esp_intr_alloc_wrapper(int source, int flags, intr_handler_t handler, - void *arg, void **ret_handle_in) +static int esp_intr_alloc_wrapper(int source, int flags, intr_handler_t handler, void *arg, void **ret_handle_in) { - int rc = esp_intr_alloc(source, flags | ESP_INTR_FLAG_IRAM, handler, - arg, (intr_handle_t *)ret_handle_in); +#if CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY + int rc = esp_intr_alloc(source, flags, handler, arg, (intr_handle_t *)ret_handle_in); +#else + int rc = esp_intr_alloc(source, flags | ESP_INTR_FLAG_IRAM, handler, arg, (intr_handle_t *)ret_handle_in); +#endif return rc; } @@ -1050,6 +1056,10 @@ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode) coex_enable(); #endif // CONFIG_SW_COEXIST_ENABLE +#if CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY + r_ble_ll_scan_start_time_init_compensation(500); + r_priv_sdk_config_insert_proc_time_set(500); +#endif // CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY if (r_ble_controller_enable(mode) != 0) { ret = ESP_FAIL; goto error; @@ -1210,9 +1220,17 @@ esp_err_t esp_ble_tx_power_set(esp_ble_power_type_t power_type, esp_power_level_ switch (power_type) { case ESP_BLE_PWR_TYPE_DEFAULT: + if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0, power_level) == 0) { + stat = ESP_OK; + } + break; case ESP_BLE_PWR_TYPE_ADV: + if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_ADV, 0xFF, power_level) == 0) { + stat = ESP_OK; + } + break; case ESP_BLE_PWR_TYPE_SCAN: - if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0, power_level) == 0) { + if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_SCAN, 0, power_level) == 0) { stat = ESP_OK; } break; @@ -1243,9 +1261,13 @@ esp_err_t esp_ble_tx_power_set_enhanced(esp_ble_enhanced_power_type_t power_type esp_err_t stat = ESP_FAIL; switch (power_type) { case ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT: + if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0, power_level) == 0) { + stat = ESP_OK; + } + break; case ESP_BLE_ENHANCED_PWR_TYPE_SCAN: case ESP_BLE_ENHANCED_PWR_TYPE_INIT: - if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0, power_level) == 0) { + if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_SCAN, 0, power_level) == 0) { stat = ESP_OK; } break; @@ -1268,11 +1290,15 @@ esp_power_level_t esp_ble_tx_power_get(esp_ble_power_type_t power_type) int tx_level = 0; switch (power_type) { - case ESP_BLE_PWR_TYPE_ADV: - case ESP_BLE_PWR_TYPE_SCAN: case ESP_BLE_PWR_TYPE_DEFAULT: tx_level = r_ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0); break; + case ESP_BLE_PWR_TYPE_ADV: + tx_level = r_ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_ADV, 0); + break; + case ESP_BLE_PWR_TYPE_SCAN: + tx_level = r_ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_SCAN, 0); + break; case ESP_BLE_PWR_TYPE_CONN_HDL0: case ESP_BLE_PWR_TYPE_CONN_HDL1: case ESP_BLE_PWR_TYPE_CONN_HDL2: @@ -1302,9 +1328,11 @@ esp_power_level_t esp_ble_tx_power_get_enhanced(esp_ble_enhanced_power_type_t po switch (power_type) { case ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT: + tx_level = r_ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0); + break; case ESP_BLE_ENHANCED_PWR_TYPE_SCAN: case ESP_BLE_ENHANCED_PWR_TYPE_INIT: - tx_level = r_ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0); + tx_level = r_ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_SCAN, 0); break; case ESP_BLE_ENHANCED_PWR_TYPE_ADV: case ESP_BLE_ENHANCED_PWR_TYPE_CONN: diff --git a/components/bt/controller/esp32h2/Kconfig.in b/components/bt/controller/esp32h2/Kconfig.in index 4b281d029cee..c8936bdbec08 100644 --- a/components/bt/controller/esp32h2/Kconfig.in +++ b/components/bt/controller/esp32h2/Kconfig.in @@ -698,3 +698,11 @@ config BT_LE_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS Enabling this option will add stricter verification of the Access Address in the CONNECT_IND PDU. This improves security by ensuring that only connection requests with valid Access Addresses are accepted. If disabled, only basic checks are applied, improving compatibility. + +config BT_CTRL_RUN_IN_FLASH_ONLY + bool "Reduce BLE IRAM usage (READ DOCS FIRST) (EXPERIMENTAL)" + default n + help + Move most IRAM into flash. This will increase the usage of flash and reduce ble performance. + Because the code is moved to the flash, the execution speed of the code is reduced. + To have a small impact on performance, you need to enable flash suspend (SPI_FLASH_AUTO_SUSPEND). diff --git a/components/bt/controller/esp32h2/bt.c b/components/bt/controller/esp32h2/bt.c index fd0ec127a4af..e4168cb00b7e 100644 --- a/components/bt/controller/esp32h2/bt.c +++ b/components/bt/controller/esp32h2/bt.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 */ @@ -125,6 +125,10 @@ extern void r_ble_lll_rfmgmt_set_sleep_cb(void *s_cb, void *w_cb, void *s_arg, extern void r_ble_rtc_wake_up_state_clr(void); extern int os_msys_init(void); extern void os_msys_deinit(void); +#if CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY +extern void r_ble_ll_scan_start_time_init_compensation(uint32_t init_compensation); +extern void r_priv_sdk_config_insert_proc_time_set(uint16_t insert_proc_time); +#endif // CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY #if CONFIG_FREERTOS_USE_TICKLESS_IDLE extern sleep_retention_entries_config_t *r_esp_ble_mac_retention_link_get(uint8_t *size, uint8_t extra); extern void r_esp_ble_set_wakeup_overhead(uint32_t overhead); @@ -495,8 +499,11 @@ static int esp_ecc_gen_dh_key(const uint8_t *peer_pub_key_x, const uint8_t *peer static int esp_intr_alloc_wrapper(int source, int flags, intr_handler_t handler, void *arg, void **ret_handle_in) { - int rc = esp_intr_alloc(source, flags | ESP_INTR_FLAG_IRAM, handler, - arg, (intr_handle_t *)ret_handle_in); +#if CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY + int rc = esp_intr_alloc(source, flags, handler, arg, (intr_handle_t *)ret_handle_in); +#else + int rc = esp_intr_alloc(source, flags | ESP_INTR_FLAG_IRAM, handler, arg, (intr_handle_t *)ret_handle_in); +#endif return rc; } @@ -1020,7 +1027,10 @@ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode) #if CONFIG_SW_COEXIST_ENABLE coex_enable(); #endif // CONFIG_SW_COEXIST_ENABLE - +#if CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY + r_ble_ll_scan_start_time_init_compensation(500); + r_priv_sdk_config_insert_proc_time_set(500); +#endif // CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY if (r_ble_controller_enable(mode) != 0) { ret = ESP_FAIL; goto error; @@ -1181,9 +1191,17 @@ esp_err_t esp_ble_tx_power_set(esp_ble_power_type_t power_type, esp_power_level_ switch (power_type) { case ESP_BLE_PWR_TYPE_DEFAULT: + if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0, power_level) == 0) { + stat = ESP_OK; + } + break; case ESP_BLE_PWR_TYPE_ADV: + if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_ADV, 0xFF, power_level) == 0) { + stat = ESP_OK; + } + break; case ESP_BLE_PWR_TYPE_SCAN: - if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0, power_level) == 0) { + if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_SCAN, 0, power_level) == 0) { stat = ESP_OK; } break; @@ -1214,9 +1232,13 @@ esp_err_t esp_ble_tx_power_set_enhanced(esp_ble_enhanced_power_type_t power_type esp_err_t stat = ESP_FAIL; switch (power_type) { case ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT: + if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0, power_level) == 0) { + stat = ESP_OK; + } + break; case ESP_BLE_ENHANCED_PWR_TYPE_SCAN: case ESP_BLE_ENHANCED_PWR_TYPE_INIT: - if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0, power_level) == 0) { + if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_SCAN, 0, power_level) == 0) { stat = ESP_OK; } break; @@ -1239,11 +1261,15 @@ esp_power_level_t esp_ble_tx_power_get(esp_ble_power_type_t power_type) int tx_level = 0; switch (power_type) { - case ESP_BLE_PWR_TYPE_ADV: - case ESP_BLE_PWR_TYPE_SCAN: case ESP_BLE_PWR_TYPE_DEFAULT: tx_level = r_ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0); break; + case ESP_BLE_PWR_TYPE_ADV: + tx_level = r_ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_ADV, 0); + break; + case ESP_BLE_PWR_TYPE_SCAN: + tx_level = r_ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_SCAN, 0); + break; case ESP_BLE_PWR_TYPE_CONN_HDL0: case ESP_BLE_PWR_TYPE_CONN_HDL1: case ESP_BLE_PWR_TYPE_CONN_HDL2: @@ -1273,9 +1299,11 @@ esp_power_level_t esp_ble_tx_power_get_enhanced(esp_ble_enhanced_power_type_t po switch (power_type) { case ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT: + tx_level = r_ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0); + break; case ESP_BLE_ENHANCED_PWR_TYPE_SCAN: case ESP_BLE_ENHANCED_PWR_TYPE_INIT: - tx_level = r_ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0); + tx_level = r_ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_SCAN, 0); break; case ESP_BLE_ENHANCED_PWR_TYPE_ADV: case ESP_BLE_ENHANCED_PWR_TYPE_CONN: diff --git a/components/bt/controller/lib_esp32 b/components/bt/controller/lib_esp32 index 35fb599d3733..e847faba2d86 160000 --- a/components/bt/controller/lib_esp32 +++ b/components/bt/controller/lib_esp32 @@ -1 +1 @@ -Subproject commit 35fb599d3733f50254c056171edebcaa3c57d06b +Subproject commit e847faba2d86e90b5f21d6310bb4723c4e32ba1c diff --git a/components/bt/controller/lib_esp32c2/esp32c2-bt-lib b/components/bt/controller/lib_esp32c2/esp32c2-bt-lib index 339d66ea3dce..1e510cbc5074 160000 --- a/components/bt/controller/lib_esp32c2/esp32c2-bt-lib +++ b/components/bt/controller/lib_esp32c2/esp32c2-bt-lib @@ -1 +1 @@ -Subproject commit 339d66ea3dce6e97bee6ce41aa3d06761efcaad2 +Subproject commit 1e510cbc50746259d53389309363058b89396a49 diff --git a/components/bt/controller/lib_esp32c5/esp32c5-bt-lib b/components/bt/controller/lib_esp32c5/esp32c5-bt-lib index b4f67e85c54c..e55480fc0db4 160000 --- a/components/bt/controller/lib_esp32c5/esp32c5-bt-lib +++ b/components/bt/controller/lib_esp32c5/esp32c5-bt-lib @@ -1 +1 @@ -Subproject commit b4f67e85c54cc8f55b5130e47805dc8c906a736c +Subproject commit e55480fc0db4c767434f5677188065f484aa5706 diff --git a/components/bt/controller/lib_esp32c6/esp32c6-bt-lib b/components/bt/controller/lib_esp32c6/esp32c6-bt-lib index 2c3b919de822..9cf1bbd021d9 160000 --- a/components/bt/controller/lib_esp32c6/esp32c6-bt-lib +++ b/components/bt/controller/lib_esp32c6/esp32c6-bt-lib @@ -1 +1 @@ -Subproject commit 2c3b919de82278768a98f66c02c63a148026a613 +Subproject commit 9cf1bbd021d98b3da9ad8465e7fbfca8085f3a1d diff --git a/components/bt/controller/lib_esp32h2/esp32h2-bt-lib b/components/bt/controller/lib_esp32h2/esp32h2-bt-lib index 59c26f308e18..092666b0f427 160000 --- a/components/bt/controller/lib_esp32h2/esp32h2-bt-lib +++ b/components/bt/controller/lib_esp32h2/esp32h2-bt-lib @@ -1 +1 @@ -Subproject commit 59c26f308e18809cc02351febcbecad542a365c9 +Subproject commit 092666b0f427e4226325389fc53e4b8df4a8a1fc diff --git a/components/bt/host/bluedroid/Kconfig.in b/components/bt/host/bluedroid/Kconfig.in index 6cacf29367ab..d9fa58912360 100644 --- a/components/bt/host/bluedroid/Kconfig.in +++ b/components/bt/host/bluedroid/Kconfig.in @@ -43,7 +43,8 @@ config BT_BLUEDROID_MEM_DEBUG config BT_BLUEDROID_ESP_COEX_VSC bool "Enable Espressif Vendor-specific HCI commands for coexist status configuration" depends on BT_BLUEDROID_ENABLED - default y + default y if (ESP_COEX_SW_COEXIST_ENABLE || BT_CONTROLLER_DISABLED) + default n help Enable Espressif Vendor-specific HCI commands for coexist status configuration diff --git a/components/bt/host/bluedroid/bta/pba/bta_pba_client_act.c b/components/bt/host/bluedroid/bta/pba/bta_pba_client_act.c index 8c69e6244a64..7ed5aaa8fc72 100644 --- a/components/bt/host/bluedroid/bta/pba/bta_pba_client_act.c +++ b/components/bt/host/bluedroid/bta/pba/bta_pba_client_act.c @@ -334,7 +334,7 @@ static void goep_event_callback(UINT16 handle, UINT8 event, tGOEPC_MSG *p_msg) switch (event) { case GOEPC_OPENED_EVT: - p_data = (tBTA_PBA_CLIENT_DATA *)osi_malloc(sizeof(tBTA_PBA_CLIENT_GOEP_CONNECT)); + p_data = (tBTA_PBA_CLIENT_DATA *)osi_malloc(sizeof(tBTA_PBA_CLIENT_DATA)); assert(p_data != NULL); p_data->goep_connect.hdr.event = BTA_PBA_CLIENT_GOEP_CONNECT_EVT; p_data->goep_connect.hdr.layer_specific = handle; @@ -342,14 +342,14 @@ static void goep_event_callback(UINT16 handle, UINT8 event, tGOEPC_MSG *p_msg) p_data->goep_connect.peer_mtu = p_msg->opened.peer_mtu; break; case GOEPC_CLOSED_EVT: - p_data = (tBTA_PBA_CLIENT_DATA *)osi_malloc(sizeof(tBTA_PBA_CLIENT_GOEP_DISCONNECT)); + p_data = (tBTA_PBA_CLIENT_DATA *)osi_malloc(sizeof(tBTA_PBA_CLIENT_DATA)); assert(p_data != NULL); p_data->goep_disconnect.hdr.event = BTA_PBA_CLIENT_GOEP_DISCONNECT_EVT; p_data->goep_disconnect.hdr.layer_specific = handle; p_data->goep_disconnect.reason = p_msg->closed.reason; break; case GOEPC_RESPONSE_EVT: - p_data = (tBTA_PBA_CLIENT_DATA *)osi_malloc(sizeof(tBTA_PBA_CLIENT_GOEP_RESPONSE)); + p_data = (tBTA_PBA_CLIENT_DATA *)osi_malloc(sizeof(tBTA_PBA_CLIENT_DATA)); assert(p_data != NULL); p_data->goep_response.hdr.layer_specific = handle; p_data->goep_response.pkt = p_msg->response.pkt; diff --git a/components/bt/host/bluedroid/bta/pba/bta_pba_client_api.c b/components/bt/host/bluedroid/bta/pba/bta_pba_client_api.c index 4670c28cf16a..8169a7d6de40 100644 --- a/components/bt/host/bluedroid/bta/pba/bta_pba_client_api.c +++ b/components/bt/host/bluedroid/bta/pba/bta_pba_client_api.c @@ -80,6 +80,7 @@ void BTA_PbaClientOpen(BD_ADDR bd_addr, tBTA_SEC sec_mask, UINT32 supported_feat if ((p_buf = (tBTA_PBA_CLIENT_API_OPEN *)osi_malloc(sizeof(tBTA_PBA_CLIENT_API_OPEN))) != NULL) { p_buf->hdr.event = BTA_PBA_CLIENT_API_OPEN_EVT; p_buf->sec_mask = sec_mask; + p_buf->supported_feat = supported_feat; p_buf->mtu = mtu; bdcpy(p_buf->bd_addr, bd_addr); bta_sys_sendmsg(p_buf); diff --git a/components/bt/host/bluedroid/bta/pba/bta_pba_client_sdp.c b/components/bt/host/bluedroid/bta/pba/bta_pba_client_sdp.c index 901e3beab4e8..030ddad66c0b 100644 --- a/components/bt/host/bluedroid/bta/pba/bta_pba_client_sdp.c +++ b/components/bt/host/bluedroid/bta/pba/bta_pba_client_sdp.c @@ -214,8 +214,8 @@ BOOLEAN bta_pba_client_do_disc(tBTA_PBA_CLIENT_CCB *p_ccb) { tSDP_UUID uuid_list[1]; UINT16 num_uuid = 1; - UINT16 attr_list[4]; - UINT8 num_attr; + UINT16 attr_list[6]; + UINT8 num_attr = 6; BOOLEAN db_inited = FALSE; /* get proto list and features */ @@ -225,7 +225,6 @@ BOOLEAN bta_pba_client_do_disc(tBTA_PBA_CLIENT_CCB *p_ccb) attr_list[3] = ATTR_ID_GOEP_L2CAP_PSM; attr_list[4] = ATTR_ID_SUPPORTED_REPOSITORIES; attr_list[5] = ATTR_ID_PBAP_SUPPORTED_FEATURES; - num_attr = 6; uuid_list[0].uu.uuid16 = UUID_SERVCLASS_PBAP_PSE; uuid_list[0].len = LEN_UUID_16; diff --git a/components/bt/host/bluedroid/stack/btm/btm_acl.c b/components/bt/host/bluedroid/stack/btm/btm_acl.c index 4b7e7eedcea9..93ca1062fa29 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_acl.c +++ b/components/bt/host/bluedroid/stack/btm/btm_acl.c @@ -335,7 +335,7 @@ void btm_acl_created (BD_ADDR bda, DEV_CLASS dc, UINT8 bdn[BTM_MAX_REM_BD_NAME_L #if (CLASSIC_BT_INCLUDED == TRUE) const UINT8 req_pend = (p_dev_rec->sm4 & BTM_SM4_REQ_PEND); #endif ///CLASSIC_BT_INCLUDED == TRUE - /* Store the Peer Security Capabilites (in SM4 and rmt_sec_caps) */ + /* Store the Peer Security Capabilities (in SM4 and rmt_sec_caps) */ #if (SMP_INCLUDED == TRUE) btm_sec_set_peer_sec_caps(p, p_dev_rec); #endif ///SMP_INCLUDED == TRUE @@ -350,7 +350,7 @@ void btm_acl_created (BD_ADDR bda, DEV_CLASS dc, UINT8 bdn[BTM_MAX_REM_BD_NAME_L return; } } else { - /* If remote features indicated secure connection (SC) mode, check the remote feautres again*/ + /* If remote features indicated secure connection (SC) mode, check the remote features again*/ /* this is to prevent from BIAS attack where attacker can downgrade SC mode*/ btm_read_remote_features (p->hci_handle); } @@ -474,7 +474,7 @@ void btm_acl_removed (BD_ADDR bda, tBT_TRANSPORT transport) BTM_TRACE_DEBUG("Bonded\n"); } } else { - BTM_TRACE_DEBUG("Bletooth link down\n"); + BTM_TRACE_DEBUG("Bluetooth link down\n"); p_dev_rec->sec_flags &= ~(BTM_SEC_AUTHORIZED | BTM_SEC_AUTHENTICATED | BTM_SEC_ENCRYPTED | BTM_SEC_ROLE_SWITCHED); } @@ -1016,7 +1016,7 @@ void btm_process_remote_ext_features (tACL_CONN *p_acl_cb, UINT8 num_read_pages) const UINT8 req_pend = (p_dev_rec->sm4 & BTM_SM4_REQ_PEND); #if (SMP_INCLUDED == TRUE) - /* Store the Peer Security Capabilites (in SM4 and rmt_sec_caps) */ + /* Store the Peer Security Capabilities (in SM4 and rmt_sec_caps) */ btm_sec_set_peer_sec_caps(p_acl_cb, p_dev_rec); #endif ///SMP_INCLUDED == TRUE BTM_TRACE_API("%s: pend:%d\n", __FUNCTION__, req_pend); @@ -1455,7 +1455,7 @@ void btm_process_clk_off_comp_evt (UINT16 hci_handle, UINT16 clock_offset) ** ** Function btm_acl_role_changed ** -** Description This function is called whan a link's master/slave role change +** Description This function is called when a link's master/slave role change ** event or command status event (with error) is received. ** It updates the link control block, and calls ** the registered callback with status and role (if registered). @@ -2705,7 +2705,7 @@ void btm_acl_connected(BD_ADDR bda, UINT16 handle, UINT8 link_type, UINT8 enc_mo l2c_link_hci_conn_comp(status, handle, bda); } #if BTM_SCO_INCLUDED == TRUE - else { + else if (link_type == HCI_LINK_TYPE_SCO) { memset(&esco_data, 0, sizeof(tBTM_ESCO_DATA)); esco_data.link_type = HCI_LINK_TYPE_SCO; memcpy (esco_data.bd_addr, bda, BD_ADDR_LEN); diff --git a/components/bt/host/bluedroid/stack/btm/btm_sco.c b/components/bt/host/bluedroid/stack/btm/btm_sco.c index 7dede5d4d3f8..ceb7830a4b98 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_sco.c +++ b/components/bt/host/bluedroid/stack/btm/btm_sco.c @@ -117,8 +117,6 @@ void btm_sco_init (void) } #endif /* Initialize nonzero defaults */ - btm_cb.sco_cb.sco_disc_reason = BTM_INVALID_SCO_DISC_REASON; - btm_cb.sco_cb.def_esco_parms = btm_esco_defaults; /* Initialize with defaults */ btm_cb.sco_cb.desired_sco_mode = BTM_DEFAULT_SCO_MODE; } @@ -1048,7 +1046,6 @@ void btm_sco_connected (UINT8 hci_status, BD_ADDR bda, UINT16 hci_handle, tBTM_CHG_ESCO_PARAMS parms; #endif - btm_cb.sco_cb.sco_disc_reason = hci_status; BTM_TRACE_API("%s, handle %x", __FUNCTION__, hci_handle); #if (BTM_MAX_SCO_LINKS>0) for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) { @@ -1224,16 +1221,11 @@ void btm_sco_removed (UINT16 hci_handle, UINT8 reason) #if (BTM_MAX_SCO_LINKS>0) tSCO_CONN *p = &btm_cb.sco_cb.sco_db[0]; UINT16 xx; -#endif - btm_cb.sco_cb.sco_disc_reason = reason; - -#if (BTM_MAX_SCO_LINKS>0) p = &btm_cb.sco_cb.sco_db[0]; for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) { if ((p->state != SCO_ST_UNUSED) && (p->state != SCO_ST_LISTENING) && (p->hci_handle == hci_handle)) { btm_sco_flush_sco_data(xx); - p->state = SCO_ST_UNUSED; #if BTM_SCO_HCI_INCLUDED == TRUE btm_cb.sco_cb.xmit_window_size += p->sent_not_acked; @@ -1375,24 +1367,6 @@ UINT16 BTM_ReadScoPacketTypes (UINT16 sco_inx) #endif } -/******************************************************************************* -** -** Function BTM_ReadScoDiscReason -** -** Description This function is returns the reason why an (e)SCO connection -** has been removed. It contains the value until read, or until -** another (e)SCO connection has disconnected. -** -** Returns HCI reason or BTM_INVALID_SCO_DISC_REASON if not set. -** -*******************************************************************************/ -UINT16 BTM_ReadScoDiscReason (void) -{ - UINT16 res = btm_cb.sco_cb.sco_disc_reason; - btm_cb.sco_cb.sco_disc_reason = BTM_INVALID_SCO_DISC_REASON; - return (res); -} - /******************************************************************************* ** ** Function BTM_ReadDeviceScoPacketTypes @@ -1894,10 +1868,6 @@ UINT8 *BTM_ReadScoBdAddr(UINT16 sco_inx) { return ((UINT8 *) NULL); } -UINT16 BTM_ReadScoDiscReason (void) -{ - return (BTM_INVALID_SCO_DISC_REASON); -} tBTM_STATUS BTM_SetEScoMode (tBTM_SCO_TYPE sco_mode, tBTM_ESCO_PARAMS *p_parms) { return (BTM_MODE_UNSUPPORTED); diff --git a/components/bt/host/bluedroid/stack/btm/include/btm_int.h b/components/bt/host/bluedroid/stack/btm/include/btm_int.h index df7e435db1a7..7392f4b9f807 100644 --- a/components/bt/host/bluedroid/stack/btm/include/btm_int.h +++ b/components/bt/host/bluedroid/stack/btm/include/btm_int.h @@ -470,7 +470,6 @@ typedef struct { tSCO_CONN sco_db[BTM_MAX_SCO_LINKS]; tBTM_ESCO_PARAMS def_esco_parms; BD_ADDR xfer_addr; - UINT16 sco_disc_reason; BOOLEAN esco_supported; /* TRUE if 1.2 cntlr AND supports eSCO links */ tBTM_SCO_TYPE desired_sco_mode; tBTM_SCO_TYPE xfer_sco_type; diff --git a/components/bt/host/bluedroid/stack/include/stack/btm_api.h b/components/bt/host/bluedroid/stack/include/stack/btm_api.h index 63a40ca088ff..71a651f19a28 100644 --- a/components/bt/host/bluedroid/stack/include/stack/btm_api.h +++ b/components/bt/host/bluedroid/stack/include/stack/btm_api.h @@ -1028,9 +1028,6 @@ typedef void (tBTM_ACL_DB_CHANGE_CB) (BD_ADDR p_bda, DEV_CLASS p_dc, #define BTM_INVALID_SCO_INDEX 0xFFFF #define BTM_INVALID_HCI_HANDLE 0xFFFF -/* Define an invalid SCO disconnect reason */ -#define BTM_INVALID_SCO_DISC_REASON 0xFFFF - /* Define first active SCO index */ #define BTM_FIRST_ACTIVE_SCO_INDEX BTM_MAX_SCO_LINKS @@ -3261,21 +3258,6 @@ UINT16 BTM_ReadScoHandle (UINT16 sco_inx); UINT8 *BTM_ReadScoBdAddr (UINT16 sco_inx); -/******************************************************************************* -** -** Function BTM_ReadScoDiscReason -** -** Description This function is returns the reason why an (e)SCO connection -** has been removed. It contains the value until read, or until -** another (e)SCO connection has disconnected. -** -** Returns HCI reason or BTM_INVALID_SCO_DISC_REASON if not set. -** -*******************************************************************************/ -//extern -UINT16 BTM_ReadScoDiscReason (void); - - /******************************************************************************* ** ** Function BTM_SetEScoMode diff --git a/components/bt/host/nimble/nimble b/components/bt/host/nimble/nimble index 6c53703528c6..a4cd6027a544 160000 --- a/components/bt/host/nimble/nimble +++ b/components/bt/host/nimble/nimble @@ -1 +1 @@ -Subproject commit 6c53703528c6d55d6d7752952c1532610bf8a124 +Subproject commit a4cd6027a544966d569db92c68e557f09e1f3d76 diff --git a/components/bt/include/esp32/include/esp_bt.h b/components/bt/include/esp32/include/esp_bt.h index 116d1f37eaa6..21b5c80d10c8 100644 --- a/components/bt/include/esp32/include/esp_bt.h +++ b/components/bt/include/esp32/include/esp_bt.h @@ -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 */ @@ -393,6 +393,15 @@ typedef enum { ESP_SCO_DATA_PATH_PCM = 1, /*!< data over PCM interface */ } esp_sco_data_path_t; +/** + * @brief Bluetooth sleep clock + */ +typedef enum { + ESP_BT_SLEEP_CLOCK_NONE = 0, /*!< Sleep clock not configured */ + ESP_BT_SLEEP_CLOCK_MAIN_XTAL = 1, /*!< SoC main crystal */ + ESP_BT_SLEEP_CLOCK_EXT_32K_XTAL = 2, /*!< External 32.768kHz crystal/oscillator */ +} esp_bt_sleep_clock_t; + /** * @brief Initialize the Bluetooth Controller to allocate tasks and other resources * @@ -690,6 +699,30 @@ void esp_vhci_host_send_packet(uint8_t *data, uint16_t len); * - ESP_FAIL: Failure */ esp_err_t esp_vhci_host_register_callback(const esp_vhci_host_callback_t *callback); + +/** + * @brief Get the Bluetooth module sleep clock source. + * + * @note This function should be called after `esp_bt_controller_init()` + * + * @return + * - Clock source used in Bluetooth low power mode + */ +esp_bt_sleep_clock_t esp_bt_get_lpclk_src(void); + +/** + * @brief Set the Bluetooth module sleep clock source. + * + * @note This function should be called before `esp_bt_controller_init()` + * + * @param[in] lpclk Bluetooth sleep clock source + * + * @return + * - ESP_OK: Success + * - ESP_ERR_INVALID_ARG: Invalid argument + */ +esp_err_t esp_bt_set_lpclk_src(esp_bt_sleep_clock_t lpclk); + #ifdef __cplusplus } #endif diff --git a/components/bt/include/esp32c5/include/esp_bt.h b/components/bt/include/esp32c5/include/esp_bt.h index 4b0000de2310..ae97d9c8fb7b 100644 --- a/components/bt/include/esp32c5/include/esp_bt.h +++ b/components/bt/include/esp32c5/include/esp_bt.h @@ -159,7 +159,7 @@ esp_err_t esp_ble_tx_power_set_enhanced(esp_ble_enhanced_power_type_t power_type */ esp_power_level_t esp_ble_tx_power_get_enhanced(esp_ble_enhanced_power_type_t power_type, uint16_t handle); -#define CONFIG_VERSION 0x20240422 +#define CONFIG_VERSION 0x20241121 #define CONFIG_MAGIC 0x5A5AA5A5 /** @@ -213,6 +213,8 @@ typedef struct { uint8_t ignore_wl_for_direct_adv; /*!< Ignore the whitelist for direct advertising */ uint8_t enable_pcl; /*!< Enable power control */ uint8_t csa2_select; /*!< Select CSA#2*/ + uint8_t enable_csr; /*!< Enable CSR */ + uint8_t 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 config_magic; /*!< Magic number for configuration validation */ } esp_bt_controller_config_t; diff --git a/components/bt/linker_esp_ble_controller.lf b/components/bt/linker_esp_ble_controller.lf index d6bd1df10c00..0af407f8eb50 100644 --- a/components/bt/linker_esp_ble_controller.lf +++ b/components/bt/linker_esp_ble_controller.lf @@ -1,8 +1,21 @@ +[sections:bt_iram_text] +entries: + .iram1+ + +[sections:high_perf_iram_text] +entries: + .high_perf_code_iram1+ + [scheme:bt_default] entries: bt_bss -> dram0_bss bt_common -> dram0_bss data -> dram0_data + high_perf_iram_text -> iram0_text + if BT_CTRL_RUN_IN_FLASH_ONLY = y: + bt_iram_text -> flash_text + else: + bt_iram_text -> iram0_text # For the following fragments, order matters for # 'ALIGN(4) ALIGN(4, post) SURROUND(sym)', which generates: @@ -27,7 +40,6 @@ entries: bt_common -> dram0_bss ALIGN(4) ALIGN(4, post) SURROUND(bt_common), data -> dram0_data ALIGN(4) ALIGN(4, post) SURROUND(bt_data) - [mapping:ble_app] archive: libble_app.a entries: diff --git a/components/driver/touch_sensor/esp32/touch_sensor.c b/components/driver/touch_sensor/esp32/touch_sensor.c index 8731a080da28..686207817fc9 100644 --- a/components/driver/touch_sensor/esp32/touch_sensor.c +++ b/components/driver/touch_sensor/esp32/touch_sensor.c @@ -512,7 +512,9 @@ esp_err_t touch_pad_filter_delete(void) esp_err_t ret = ESP_OK; xSemaphoreTake(rtc_touch_mux, portMAX_DELAY); if (s_touch_pad_filter->timer) { - ESP_GOTO_ON_ERROR(esp_timer_stop(s_touch_pad_filter->timer), err, TOUCH_TAG, "failed to stop the timer"); + if (esp_timer_is_active(s_touch_pad_filter->timer)) { + ESP_GOTO_ON_ERROR(esp_timer_stop(s_touch_pad_filter->timer), err, TOUCH_TAG, "failed to stop the timer"); + } ESP_GOTO_ON_ERROR(esp_timer_delete(s_touch_pad_filter->timer), err, TOUCH_TAG, "failed to delete the timer"); s_touch_pad_filter->timer = NULL; } diff --git a/components/driver/twai/twai.c b/components/driver/twai/twai.c index b6ba2da450f8..2b1e152700a1 100644 --- a/components/driver/twai/twai.c +++ b/components/driver/twai/twai.c @@ -293,6 +293,7 @@ static void twai_intr_handler_main(void *arg) static void twai_configure_gpio(twai_obj_t *p_obj) { uint8_t controller_id = p_obj->controller_id; + assert(GPIO_IS_VALID_OUTPUT_GPIO(p_obj->tx_io)); //coverity check uint64_t gpio_mask = BIT64(p_obj->tx_io); //Set RX pin @@ -330,6 +331,7 @@ static void twai_configure_gpio(twai_obj_t *p_obj) static void twai_release_gpio(twai_obj_t *p_obj) { assert(p_obj); + assert(GPIO_IS_VALID_OUTPUT_GPIO(p_obj->tx_io)); //coverity check uint64_t gpio_mask = BIT64(p_obj->tx_io); esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, twai_controller_periph_signals.controllers[p_obj->controller_id].rx_sig, false); diff --git a/components/esp_adc/test_apps/adc/CMakeLists.txt b/components/esp_adc/test_apps/adc/CMakeLists.txt index d941bb8ebdb4..f5a1bb70ead4 100644 --- a/components/esp_adc/test_apps/adc/CMakeLists.txt +++ b/components/esp_adc/test_apps/adc/CMakeLists.txt @@ -21,3 +21,9 @@ if(CONFIG_COMPILER_DUMP_RTL_FILES) DEPENDS ${elf} ) endif() + +message(STATUS "Checking adc registers are not read-write by half-word") +include($ENV{IDF_PATH}/tools/ci/check_register_rw_half_word.cmake) +check_register_rw_half_word(SOC_MODULES "rtc_io" "sens" "syscon" "rtc_cntl" "apb_saradc" + "system" "pmu" "pcr" "hp_sys_clkrst" "lpperi" "lp_adc" + HAL_MODULES "adc") diff --git a/components/esp_coex/lib b/components/esp_coex/lib index 7b588f2dbb12..f8196c58116b 160000 --- a/components/esp_coex/lib +++ b/components/esp_coex/lib @@ -1 +1 @@ -Subproject commit 7b588f2dbb12ddcd46c075dcd041f4d03a59154f +Subproject commit f8196c58116bed53358608ec9499ea72720e2acf diff --git a/components/esp_common/include/esp_check.h b/components/esp_common/include/esp_check.h index 56f2cbbc478a..a3f969b25562 100644 --- a/components/esp_common/include/esp_check.h +++ b/components/esp_common/include/esp_check.h @@ -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 */ @@ -307,18 +307,6 @@ extern "C" { } \ } while(0) -/** - * Macro which can be used to check the error code. If the code is not ESP_OK, it prints the message and returns. - * It logs the message in debug mode. - */ -#define ESP_RETURN_ON_ERROR_DEBUG(x, log_tag, format, ...) do { \ - esp_err_t err_rc_ = (x); \ - if (unlikely(err_rc_ != ESP_OK)) { \ - ESP_LOGD(log_tag, "%s(%d): " format, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ - return err_rc_; \ - } \ - } while(0) - /** * A version of ESP_RETURN_ON_ERROR() macro that can be called from ISR. */ @@ -366,20 +354,6 @@ extern "C" { } \ } while(0) -/** - * Macro which can be used to check the error code. If the code is not ESP_OK, it prints the message, - * sets the local variable 'ret' to the code, and then exits by jumping to 'goto_tag'. - * It logs the message in debug mode. - */ -#define ESP_GOTO_ON_ERROR_DEBUG(x, goto_tag, log_tag, format, ...) do { \ - esp_err_t err_rc_ = (x); \ - if (unlikely(err_rc_ != ESP_OK)) { \ - ESP_LOGD(log_tag, "%s(%d): " format, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ - ret = err_rc_; \ - goto goto_tag; \ - } \ - } while(0) - /** * A version of ESP_GOTO_ON_ERROR() macro that can be called from ISR. */ @@ -403,18 +377,6 @@ extern "C" { } \ } while(0) -/** - * Macro which can be used to check the condition. If the condition is not 'true', it prints the message - * and returns with the supplied 'err_code'. - * It logs the message in debug mode. - */ -#define ESP_RETURN_ON_FALSE_DEBUG(a, err_code, log_tag, format, ...) do { \ - if (unlikely(!(a))) { \ - ESP_LOGD(log_tag, "%s(%d): " format, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ - return err_code; \ - } \ - } while(0) - /** * A version of ESP_RETURN_ON_FALSE() macro that can be called from ISR. */ @@ -458,19 +420,6 @@ extern "C" { } \ } while (0) -/** - * Macro which can be used to check the condition. If the condition is not 'true', it prints the message, - * sets the local variable 'ret' to the supplied 'err_code', and then exits by jumping to 'goto_tag'. - * It logs the message in debug mode. - */ -#define ESP_GOTO_ON_FALSE_DEBUG(a, err_code, goto_tag, log_tag, format, ...) do { \ - if (unlikely(!(a))) { \ - ESP_LOGD(log_tag, "%s(%d): " format, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ - ret = err_code; \ - goto goto_tag; \ - } \ - } while (0) - /** * A version of ESP_GOTO_ON_FALSE() macro that can be called from ISR. */ diff --git a/components/esp_driver_ana_cmpr/test_apps/analog_comparator/CMakeLists.txt b/components/esp_driver_ana_cmpr/test_apps/analog_comparator/CMakeLists.txt index c5b8c3e782aa..6bc3f821733e 100644 --- a/components/esp_driver_ana_cmpr/test_apps/analog_comparator/CMakeLists.txt +++ b/components/esp_driver_ana_cmpr/test_apps/analog_comparator/CMakeLists.txt @@ -19,3 +19,8 @@ if(CONFIG_COMPILER_DUMP_RTL_FILES) DEPENDS ${elf} ) endif() + +message(STATUS "Checking analog comparator registers are not read-write by half-word") +include($ENV{IDF_PATH}/tools/ci/check_register_rw_half_word.cmake) +check_register_rw_half_word(SOC_MODULES "gpio_ext" "lp_system" "gpio" + HAL_MODULES "ana_cmpr") diff --git a/components/esp_driver_bitscrambler/CMakeLists.txt b/components/esp_driver_bitscrambler/CMakeLists.txt index b7b7ef65316a..d1c7fa5a6ec4 100644 --- a/components/esp_driver_bitscrambler/CMakeLists.txt +++ b/components/esp_driver_bitscrambler/CMakeLists.txt @@ -1,29 +1,14 @@ idf_build_get_property(target IDF_TARGET) +if(${target} STREQUAL "linux") + return() # This component is not supported by the POSIX/Linux simulator +endif() set(srcs) -set(include_dirs) -set(priv_requires) - -set(my_priv_requires "soc" "hal" "esp_hw_support" "esp_mm") if(CONFIG_SOC_BITSCRAMBLER_SUPPORTED) - list(APPEND srcs "bitscrambler.c" "bitscrambler_loopback.c") - list(APPEND include_dirs "include") -endif() - -# Note that (according to the docs) "The values of REQUIRES and PRIV_REQUIRES -# should not depend on any configuration choices (CONFIG_xxx macros)." We work -# around that by setting the actual priv_requires value in the target checks, -# rather than make it depend on CONFIG_SOC_BITSCRAMBLER_SUPPORTED. - -if(target STREQUAL "esp32p4") - list(APPEND srcs "bitscrambler_esp32p4.c") - set(priv_requires ${my_priv_requires}) + list(APPEND srcs "src/bitscrambler.c" "src/bitscrambler_loopback.c" "src/bitscrambler_${target}.c") endif() - idf_component_register(SRCS ${srcs} - PRIV_REQUIRES ${priv_requires} - INCLUDE_DIRS ${include_dirs} - PRIV_INCLUDE_DIRS "priv_include" - ) + PRIV_REQUIRES "esp_mm" + INCLUDE_DIRS "include") diff --git a/components/esp_driver_bitscrambler/bitscrambler_loopback_private.h b/components/esp_driver_bitscrambler/bitscrambler_loopback_private.h deleted file mode 100644 index ca0f6502a9ca..000000000000 --- a/components/esp_driver_bitscrambler/bitscrambler_loopback_private.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -//This file contains private functions for interop between bitscrambler.c -//and bitscrambler_loopback.c. - -#pragma once - -#include "bitscrambler_private.h" - -#ifdef __cplusplus -extern "C" { -#endif - -void bitscrambler_loopback_free(bitscrambler_handle_t bs); - -#ifdef __cplusplus -} -#endif diff --git a/components/esp_driver_bitscrambler/bitscrambler_private.h b/components/esp_driver_bitscrambler/bitscrambler_private.h deleted file mode 100644 index 401e5346a9d0..000000000000 --- a/components/esp_driver_bitscrambler/bitscrambler_private.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -//This file contains private functions for interop between bitscrambler.c -//and bitscrambler_loopback.c. -#pragma once - -#include -#include "soc/bitscrambler_peri_select.h" -#include "hal/bitscrambler_ll.h" - -typedef struct bitscrambler_t bitscrambler_t; - -struct bitscrambler_t { - bitscrambler_config_t cfg; - bitscrambler_dev_t *hw; - bool loopback; //true if this is a loopback bitscrambler, i.e. the RX - //channel is also claimed -}; - -esp_err_t bitscrambler_init_loopback(bitscrambler_handle_t handle, const bitscrambler_config_t *config); diff --git a/components/esp_driver_bitscrambler/include/driver/bitscrambler.h b/components/esp_driver_bitscrambler/include/driver/bitscrambler.h index de8caac73c00..4c13629e2bce 100644 --- a/components/esp_driver_bitscrambler/include/driver/bitscrambler.h +++ b/components/esp_driver_bitscrambler/include/driver/bitscrambler.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 */ @@ -7,15 +7,36 @@ #include #include "esp_err.h" +#include "soc/soc_caps.h" #include "hal/bitscrambler_types.h" +#if SOC_BITSCRAMBLER_SUPPORTED #include "soc/bitscrambler_peri_select.h" +#endif #ifdef __cplusplus extern "C" { #endif +/** + * @brief Declare a BitScrambler binary program. + * + * This macro declares an external reference to a BitScrambler binary program. + * The binary program is expected to be linked into the binary with a specific + * naming convention. + * + * @param VAR The variable name to declare. + * @param NAME The name of the binary program. + */ #define BITSCRAMBLER_PROGRAM(VAR, NAME) extern const uint8_t VAR[] asm("_binary_bitscrambler_program_" NAME "_start") +/** + * @brief Handle for the bitscrambler instance. + * + * This typedef defines a handle for a bitscrambler instance, which is used to + * manage and interact with the bitscrambler. The handle is a pointer to an + * opaque structure, meaning that the internal details of the structure are + * hidden from the user. + */ typedef struct bitscrambler_t *bitscrambler_handle_t; /** diff --git a/components/esp_driver_bitscrambler/include/esp_private/bitscrambler.h b/components/esp_driver_bitscrambler/include/esp_private/bitscrambler.h new file mode 100644 index 000000000000..7ed4498dde5c --- /dev/null +++ b/components/esp_driver_bitscrambler/include/esp_private/bitscrambler.h @@ -0,0 +1,20 @@ +/* + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include "driver/bitscrambler.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef esp_err_t (*bitscrambler_extra_clean_up_func_t)(bitscrambler_handle_t bs, void* user_ctx); + +esp_err_t bitscrambler_register_extra_clean_up(bitscrambler_handle_t handle, bitscrambler_extra_clean_up_func_t clean_up, void* user_ctx); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_driver_bitscrambler/bitscrambler.c b/components/esp_driver_bitscrambler/src/bitscrambler.c similarity index 91% rename from components/esp_driver_bitscrambler/bitscrambler.c rename to components/esp_driver_bitscrambler/src/bitscrambler.c index e9ff25320fe9..aae1f96d376f 100644 --- a/components/esp_driver_bitscrambler/bitscrambler.c +++ b/components/esp_driver_bitscrambler/src/bitscrambler.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 */ @@ -8,8 +8,6 @@ #include "esp_log.h" #include "driver/bitscrambler.h" #include "bitscrambler_private.h" -#include "bitscrambler_loopback_private.h" -#include "soc/soc.h" #include "hal/bitscrambler_ll.h" #include "esp_private/periph_ctrl.h" @@ -42,7 +40,7 @@ typedef struct { uint8_t unused; } bitscrambler_program_hdr_t; -#define INST_LEN_WORDS 9 //length of one instruction in 32-bit words as defined by HW +#define INST_LEN_WORDS BITSCRAMBLER_LL_INST_LEN_WORDS // For now, hardware only has one TX and on RX unit. Need to make this more flexible if we get // non-specific and/or more channels. @@ -102,6 +100,7 @@ static void enable_clocks(bitscrambler_t *bs) if (ref_count == 0) { //we're the first to enable the BitScrambler module bitscrambler_ll_set_bus_clock_sys_enable(1); bitscrambler_ll_reset_sys(); + bitscrambler_ll_mem_power_by_pmu(); } if (bs->cfg.dir == BITSCRAMBLER_DIR_RX || bs->loopback) { bitscrambler_ll_set_bus_clock_rx_enable(1); @@ -125,6 +124,7 @@ static void disable_clocks(bitscrambler_t *bs) } if (ref_count == 0) { //we're the last to disable the BitScrambler module bitscrambler_ll_set_bus_clock_sys_enable(0); + bitscrambler_ll_mem_force_power_off(); } } } @@ -223,7 +223,7 @@ esp_err_t bitscrambler_load_program(bitscrambler_handle_t bs, const void *progra //Set options from header bitscrambler_ll_set_lut_width(bs->hw, bs->cfg.dir, hdr.lut_width); - bitscrambler_ll_set_prefetch_mode(bs->hw, bs->cfg.dir, hdr.prefetch ? BITSCRAMBLER_PREFETCH_ENABLED : BITSCRAMBLER_PREFETCH_DISABLED); + bitscrambler_ll_enable_prefetch_on_reset(bs->hw, bs->cfg.dir, hdr.prefetch); bitscrambler_ll_set_eof_mode(bs->hw, bs->cfg.dir, hdr.eof_on); bitscrambler_ll_set_tailing_bits(bs->hw, bs->cfg.dir, hdr.trailing_bits); //fixed options @@ -251,18 +251,33 @@ esp_err_t bitscrambler_load_lut(bitscrambler_handle_t handle, void *lut, size_t return ESP_OK; } +esp_err_t bitscrambler_register_extra_clean_up(bitscrambler_handle_t handle, bitscrambler_extra_clean_up_func_t clean_up, void* user_ctx) +{ + if (!handle) { + return ESP_ERR_INVALID_ARG; + } + handle->extra_clean_up = clean_up; + handle->clean_up_user_ctx = user_ctx; + return ESP_OK; +} + void bitscrambler_free(bitscrambler_handle_t handle) { + if (!handle) { + return; + } disable_clocks(handle); if (handle->loopback) { atomic_flag_clear(&tx_in_use); atomic_flag_clear(&rx_in_use); - bitscrambler_loopback_free(handle); } else if (handle->cfg.dir == BITSCRAMBLER_DIR_TX) { atomic_flag_clear(&tx_in_use); } else if (handle->cfg.dir == BITSCRAMBLER_DIR_RX) { atomic_flag_clear(&rx_in_use); } + if (handle->extra_clean_up) { + handle->extra_clean_up(handle, handle->clean_up_user_ctx); + } free(handle); } @@ -285,7 +300,7 @@ esp_err_t bitscrambler_reset(bitscrambler_handle_t handle) //If the halt bit is set, the Bitscrambler should (eventually) go to idle state. If it //does not, something got stuck. int timeout = BITSCRAMBLER_RESET_ITERATIONS; - while ((bitscrambler_ll_current_state(handle->hw, handle->cfg.dir) != BITSCRAMBLER_STATE_IDLE) && timeout != 0) { + while ((bitscrambler_ll_get_current_state(handle->hw, handle->cfg.dir) != BITSCRAMBLER_STATE_IDLE) && timeout != 0) { timeout--; } if (timeout == 0) { diff --git a/components/esp_driver_bitscrambler/src/bitscrambler_esp32c5.c b/components/esp_driver_bitscrambler/src/bitscrambler_esp32c5.c new file mode 100644 index 000000000000..741fc61af2ee --- /dev/null +++ b/components/esp_driver_bitscrambler/src/bitscrambler_esp32c5.c @@ -0,0 +1,21 @@ +/* + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "soc/gdma_channel.h" +#include "bitscrambler_soc_specific.h" + +// Note: these are indexed by the values of the SOC_BITSCRAMBLER_ATTACH_ defines +// in soc/bitscrambler_peri_select.h +// This map is used by the bitscrambler loopback driver only. + +const bitscrambler_periph_desc_t g_bitscrambler_periph_desc[] = { + [SOC_BITSCRAMBLER_ATTACH_GPSPI2] = {GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_SPI, 2), SOC_GDMA_TRIG_PERIPH_SPI2_BUS}, + [SOC_BITSCRAMBLER_ATTACH_UHCI] = {GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_UHCI, 0), SOC_GDMA_TRIG_PERIPH_UHCI0_BUS}, + [SOC_BITSCRAMBLER_ATTACH_I2S0] = {GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_I2S, 0), SOC_GDMA_TRIG_PERIPH_I2S0_BUS}, + [SOC_BITSCRAMBLER_ATTACH_AES] = {GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_AES, 0), SOC_GDMA_TRIG_PERIPH_AES0_BUS}, + [SOC_BITSCRAMBLER_ATTACH_SHA] = {GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_SHA, 0), SOC_GDMA_TRIG_PERIPH_SHA0_BUS}, + [SOC_BITSCRAMBLER_ATTACH_ADC] = {GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_ADC, 0), SOC_GDMA_TRIG_PERIPH_ADC0_BUS}, + [SOC_BITSCRAMBLER_ATTACH_PARL_IO] = {GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_PARLIO, 0), SOC_GDMA_TRIG_PERIPH_PARLIO0_BUS}, +}; diff --git a/components/esp_driver_bitscrambler/bitscrambler_esp32p4.c b/components/esp_driver_bitscrambler/src/bitscrambler_esp32p4.c similarity index 100% rename from components/esp_driver_bitscrambler/bitscrambler_esp32p4.c rename to components/esp_driver_bitscrambler/src/bitscrambler_esp32p4.c diff --git a/components/esp_driver_bitscrambler/bitscrambler_loopback.c b/components/esp_driver_bitscrambler/src/bitscrambler_loopback.c similarity index 64% rename from components/esp_driver_bitscrambler/bitscrambler_loopback.c rename to components/esp_driver_bitscrambler/src/bitscrambler_loopback.c index 800406997f72..6969f31f435f 100644 --- a/components/esp_driver_bitscrambler/bitscrambler_loopback.c +++ b/components/esp_driver_bitscrambler/src/bitscrambler_loopback.c @@ -1,40 +1,46 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" #include "driver/bitscrambler.h" -#include "bitscrambler_private.h" -#include "bitscrambler_loopback_private.h" #include "esp_private/gdma.h" +#include "esp_private/gdma_link.h" +#include "esp_private/bitscrambler.h" #include "hal/dma_types.h" +#include "hal/cache_hal.h" #include "hal/cache_ll.h" -#include "hal/gdma_ll.h" +#include "bitscrambler_private.h" #include "bitscrambler_soc_specific.h" -#include "freertos/FreeRTOS.h" -#include "freertos/semphr.h" #include "esp_err.h" #include "esp_check.h" -#include "soc/ahb_dma_struct.h" #include "esp_heap_caps.h" #include "esp_cache.h" #include "esp_dma_utils.h" +#include "esp_memory_utils.h" const static char *TAG = "bs_loop"; -//Note: given that the first member is a bitscrambler_t, this can be safely passed to -//any of the non-loopback bitscrambler functions. typedef struct { bitscrambler_t bs; - dma_descriptor_t *tx_desc_link; // descriptor link list, the length of the link is determined by the copy buffer size - dma_descriptor_t *rx_desc_link; // descriptor link list, the length of the link is determined by the copy buffer size gdma_channel_handle_t tx_channel; // GDMA TX channel handle gdma_channel_handle_t rx_channel; // GDMA RX channel handle + gdma_link_list_handle_t tx_link_list; // GDMA TX link list handle, the length of the link is determined by the copy buffer size + gdma_link_list_handle_t rx_link_list; // GDMA RX link list handle, the length of the link is determined by the copy buffer size SemaphoreHandle_t sema_done; size_t max_transfer_sz_bytes; } bitscrambler_loopback_t; +/// @brief make sure bs is indeed the first member of bitscrambler_loopback_t so we can cast it to a bitscrambler_t and safely passed to +// any of the non-loopback bitscrambler functions. +_Static_assert(offsetof(bitscrambler_loopback_t, bs) == 0, "bs needs to be 1st member of bitscrambler_loopback_t"); + +static void bitscrambler_loopback_free(bitscrambler_loopback_t *bsl); +static esp_err_t bitscrambler_loopback_cleanup(bitscrambler_handle_t bs, void* user_ctx); + static esp_err_t new_dma_channel(const gdma_channel_alloc_config_t *cfg, gdma_channel_handle_t *handle, int bus) { esp_err_t ret = ESP_OK; @@ -63,8 +69,6 @@ static IRAM_ATTR bool trans_done_cb(gdma_channel_handle_t dma_chan, gdma_event_d esp_err_t bitscrambler_loopback_create(bitscrambler_handle_t *handle, int attach_to, size_t max_transfer_sz_bytes) { - ///make sure bs is indeed the first member of bitscrambler_loopback_t so we can cast it to a bitscrambler_t - _Static_assert(offsetof(bitscrambler_loopback_t, bs) == 0, "bs needs to be 1st member of bitscrambler_loopback_t"); if (!handle) { return ESP_ERR_INVALID_ARG; } @@ -85,6 +89,9 @@ esp_err_t bitscrambler_loopback_create(bitscrambler_handle_t *handle, int attach }; ESP_GOTO_ON_ERROR(bitscrambler_init_loopback(&bs->bs, &cfg), err, TAG, "failed bitscrambler init for loopback"); + // register extra cleanup function to free loopback resources + bitscrambler_register_extra_clean_up(&bs->bs, bitscrambler_loopback_cleanup, bs); + bs->sema_done = xSemaphoreCreateBinary(); if (!bs->sema_done) { goto err; @@ -93,19 +100,25 @@ esp_err_t bitscrambler_loopback_create(bitscrambler_handle_t *handle, int attach bs->max_transfer_sz_bytes = max_transfer_sz_bytes; int desc_ct = (max_transfer_sz_bytes + DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED - 1) / DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED; int bus = g_bitscrambler_periph_desc[attach_to].bus; - uint32_t caps = (bus == SOC_GDMA_BUS_AXI) ? MALLOC_CAP_DMA_DESC_AXI : MALLOC_CAP_DMA_DESC_AHB; +#ifdef SOC_GDMA_BUS_AXI size_t align = (bus == SOC_GDMA_BUS_AXI) ? 8 : 4; - bs->rx_desc_link = heap_caps_aligned_calloc(align, desc_ct, sizeof(dma_descriptor_t), caps); - bs->tx_desc_link = heap_caps_aligned_calloc(align, desc_ct, sizeof(dma_descriptor_t), caps); - if (!bs->rx_desc_link || !bs->tx_desc_link) { - ret = ESP_ERR_NO_MEM; - goto err; - } +#else + size_t align = 4; +#endif + + // create DMA link list for TX and RX + gdma_link_list_config_t dma_link_cfg = { + .buffer_alignment = 4, + .item_alignment = align, + .num_items = desc_ct, + }; + ESP_GOTO_ON_ERROR(gdma_new_link_list(&dma_link_cfg, &bs->tx_link_list), err, TAG, "failed to create TX link list"); + ESP_GOTO_ON_ERROR(gdma_new_link_list(&dma_link_cfg, &bs->rx_link_list), err, TAG, "failed to create RX link list"); // create TX channel and RX channel, they should reside in the same DMA pair gdma_channel_alloc_config_t tx_alloc_config = { - .flags.reserve_sibling = 1, .direction = GDMA_CHANNEL_DIRECTION_TX, + .flags.reserve_sibling = 1, }; ESP_GOTO_ON_ERROR(new_dma_channel(&tx_alloc_config, &bs->tx_channel, bus), err, TAG, "failed to create GDMA TX channel"); gdma_channel_alloc_config_t rx_alloc_config = { @@ -132,18 +145,13 @@ esp_err_t bitscrambler_loopback_create(bitscrambler_handle_t *handle, int attach return ESP_OK; err: - bitscrambler_loopback_free(&bs->bs); + bitscrambler_loopback_free(bs); free(bs); return ret; } -//note this is never called directly; bitscrambler_free calls this to clear -//the loopback-specific things of a loopback bitscrambler. -//bitscrambler_loopback_create also calls this in an error situation, so -//we should only delete not-NULL members. -void bitscrambler_loopback_free(bitscrambler_handle_t bs) +static void bitscrambler_loopback_free(bitscrambler_loopback_t *bsl) { - bitscrambler_loopback_t *bsl = (bitscrambler_loopback_t*)bs; if (bsl->rx_channel) { gdma_disconnect(bsl->rx_channel); gdma_del_channel(bsl->rx_channel); @@ -152,36 +160,22 @@ void bitscrambler_loopback_free(bitscrambler_handle_t bs) gdma_disconnect(bsl->tx_channel); gdma_del_channel(bsl->tx_channel); } + if (bsl->tx_link_list) { + gdma_del_link_list(bsl->tx_link_list); + } + if (bsl->rx_link_list) { + gdma_del_link_list(bsl->rx_link_list); + } if (bsl->sema_done) { vSemaphoreDelete(bsl->sema_done); } - free(bsl->rx_desc_link); - free(bsl->tx_desc_link); } -static int fill_dma_links(dma_descriptor_t *link, void *buffer, size_t len_bytes, int set_eof) +static esp_err_t bitscrambler_loopback_cleanup(bitscrambler_handle_t bs, void* user_ctx) { - uint8_t *buffer_p = (uint8_t*)buffer; - int link_ct = 0; - for (int p = 0; p < len_bytes; p += DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED) { - int seg_len = len_bytes - p; - if (seg_len > DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED) { - seg_len = DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED; - } - link[link_ct].dw0.size = seg_len; - link[link_ct].dw0.length = seg_len; - link[link_ct].dw0.err_eof = 0; - link[link_ct].dw0.suc_eof = 0; - link[link_ct].dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA; - link[link_ct].buffer = &buffer_p[p]; - link[link_ct].next = &link[link_ct + 1]; - link_ct++; - } - link[link_ct - 1].next = NULL; //fix last entry to end transaction - if (set_eof) { - link[link_ct - 1].dw0.suc_eof = 1; - } - return link_ct; + bitscrambler_loopback_t *bsl = (bitscrambler_loopback_t*)user_ctx; + bitscrambler_loopback_free(bsl); + return ESP_OK; } /* @@ -232,18 +226,39 @@ esp_err_t bitscrambler_loopback_run(bitscrambler_handle_t bs, void *buffer_in, s gdma_reset(bsl->tx_channel); bitscrambler_reset(bs); - int link_ct_in = fill_dma_links(bsl->tx_desc_link, buffer_in, length_bytes_in, 1); - int link_ct_out = fill_dma_links(bsl->rx_desc_link, buffer_out, length_bytes_out, 0); + // mount in and out buffer to the DMA link list + gdma_buffer_mount_config_t in_buf_mount_config = { + .buffer = buffer_in, + .length = length_bytes_in, + .flags = { + .mark_eof = true, + .mark_final = true, + } + }; + gdma_link_mount_buffers(bsl->tx_link_list, 0, &in_buf_mount_config, 1, NULL); + gdma_buffer_mount_config_t out_buf_mount_config = { + .buffer = buffer_out, + .length = length_bytes_out, + .flags = { + .mark_eof = false, + .mark_final = true, + } + }; + gdma_link_mount_buffers(bsl->rx_link_list, 0, &out_buf_mount_config, 1, NULL); - //Note: we add the ESP_CACHE_MSYNC_FLAG_UNALIGNED flag for now as otherwise esp_cache_msync will complain about - //the size not being aligned... we miss out on a check to see if the address is aligned this way. This needs to - //be improved, but potentially needs a fix in esp_cache_msync not to check the size. + int int_mem_cache_line_size = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_INT_MEM, CACHE_TYPE_DATA); + int ext_mem_cache_line_size = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_DATA); - esp_cache_msync(bsl->rx_desc_link, link_ct_out * sizeof(dma_descriptor_t), ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED); - esp_cache_msync(bsl->tx_desc_link, link_ct_in * sizeof(dma_descriptor_t), ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED); - esp_cache_msync(buffer_in, length_bytes_in, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED); - gdma_start(bsl->rx_channel, (intptr_t)bsl->rx_desc_link); - gdma_start(bsl->tx_channel, (intptr_t)bsl->tx_desc_link); + bool need_cache_sync = esp_ptr_internal(buffer_in) ? (int_mem_cache_line_size > 0) : (ext_mem_cache_line_size > 0); + if (need_cache_sync) { + //Note: we add the ESP_CACHE_MSYNC_FLAG_UNALIGNED flag for now as otherwise esp_cache_msync will complain about + //the size not being aligned... we miss out on a check to see if the address is aligned this way. This needs to + //be improved, but potentially needs a fix in esp_cache_msync not to check the size. + esp_cache_msync(buffer_in, length_bytes_in, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED); + } + + gdma_start(bsl->rx_channel, gdma_link_get_head_addr(bsl->rx_link_list)); + gdma_start(bsl->tx_channel, gdma_link_get_head_addr(bsl->tx_link_list)); bitscrambler_start(bs); int timeout_ms = (length_bytes_out + length_bytes_in) / (BS_MIN_BYTES_PER_SEC / 1000); @@ -256,17 +271,13 @@ esp_err_t bitscrambler_loopback_run(bitscrambler_handle_t bs, void *buffer_in, s ret = ESP_ERR_TIMEOUT; } - esp_cache_msync(buffer_out, length_bytes_out, ESP_CACHE_MSYNC_FLAG_DIR_M2C); + need_cache_sync = esp_ptr_internal(buffer_out) ? (int_mem_cache_line_size > 0) : (ext_mem_cache_line_size > 0); + if (need_cache_sync) { + esp_cache_msync(buffer_out, length_bytes_out, ESP_CACHE_MSYNC_FLAG_DIR_M2C); + } if (bytes_written) { - size_t l = 0; - for (int i = 0; i < link_ct_out; i++) { - l += bsl->rx_desc_link[i].dw0.length; - if (bsl->rx_desc_link[i].dw0.suc_eof) { - break; - } - } - *bytes_written = l; + *bytes_written = gdma_link_count_buffer_size_till_eof(bsl->rx_link_list, 0); } return ret; diff --git a/components/esp_driver_bitscrambler/src/bitscrambler_private.h b/components/esp_driver_bitscrambler/src/bitscrambler_private.h new file mode 100644 index 000000000000..ba3269749851 --- /dev/null +++ b/components/esp_driver_bitscrambler/src/bitscrambler_private.h @@ -0,0 +1,32 @@ +/* + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "esp_err.h" +#include "hal/bitscrambler_ll.h" +#include "esp_private/bitscrambler.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct bitscrambler_t bitscrambler_t; + +struct bitscrambler_t { + bitscrambler_config_t cfg; + bitscrambler_dev_t *hw; + bitscrambler_extra_clean_up_func_t extra_clean_up; // Optional extra clean-up function + void* clean_up_user_ctx; // User context for extra clean-up function + bool loopback; //true if this is a loopback bitscrambler, i.e. the RX channel is also claimed +}; + +esp_err_t bitscrambler_init_loopback(bitscrambler_handle_t handle, const bitscrambler_config_t *config); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_driver_bitscrambler/priv_include/bitscrambler_soc_specific.h b/components/esp_driver_bitscrambler/src/bitscrambler_soc_specific.h similarity index 67% rename from components/esp_driver_bitscrambler/priv_include/bitscrambler_soc_specific.h rename to components/esp_driver_bitscrambler/src/bitscrambler_soc_specific.h index 435324bae24d..19261fc323ee 100644 --- a/components/esp_driver_bitscrambler/priv_include/bitscrambler_soc_specific.h +++ b/components/esp_driver_bitscrambler/src/bitscrambler_soc_specific.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 */ @@ -8,9 +8,17 @@ #include "esp_private/gdma.h" #include "soc/bitscrambler_peri_select.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct { gdma_trigger_t dma_trigger; int bus; } bitscrambler_periph_desc_t; extern const bitscrambler_periph_desc_t g_bitscrambler_periph_desc[]; + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_driver_bitscrambler/test_apps/bitscrambler/CMakeLists.txt b/components/esp_driver_bitscrambler/test_apps/bitscrambler/CMakeLists.txt index 7d5f20871e4c..15b0569b511f 100644 --- a/components/esp_driver_bitscrambler/test_apps/bitscrambler/CMakeLists.txt +++ b/components/esp_driver_bitscrambler/test_apps/bitscrambler/CMakeLists.txt @@ -6,3 +6,8 @@ set(COMPONENTS main) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(test_bitscrambler) + +message(STATUS "Checking bitscrambler registers are not read-write by half-word") +include($ENV{IDF_PATH}/tools/ci/check_register_rw_half_word.cmake) +check_register_rw_half_word(SOC_MODULES "bitscrambler" "pcr" "hp_sys_clkrst" + HAL_MODULES "bitscrambler") diff --git a/components/esp_driver_bitscrambler/test_apps/bitscrambler/README.md b/components/esp_driver_bitscrambler/test_apps/bitscrambler/README.md index 909282018f26..c40f7cc09732 100644 --- a/components/esp_driver_bitscrambler/test_apps/bitscrambler/README.md +++ b/components/esp_driver_bitscrambler/test_apps/bitscrambler/README.md @@ -1,2 +1,2 @@ -| Supported Targets | ESP32-P4 | -| ----------------- | -------- | +| Supported Targets | ESP32-C5 | ESP32-P4 | +| ----------------- | -------- | -------- | diff --git a/components/esp_driver_bitscrambler/test_apps/bitscrambler/main/test_bitscrambler.c b/components/esp_driver_bitscrambler/test_apps/bitscrambler/main/test_bitscrambler.c index 527c59917a59..45a6035920dd 100644 --- a/components/esp_driver_bitscrambler/test_apps/bitscrambler/main/test_bitscrambler.c +++ b/components/esp_driver_bitscrambler/test_apps/bitscrambler/main/test_bitscrambler.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 */ @@ -9,7 +9,7 @@ #include "unity_test_utils.h" #include "driver/bitscrambler.h" #include "driver/bitscrambler_loopback.h" -#include "esp_dma_utils.h" +#include "esp_heap_caps.h" BITSCRAMBLER_PROGRAM(bitscrambler_program_trivial, "trivial"); BITSCRAMBLER_PROGRAM(bitscrambler_program_timeout, "timeout"); @@ -33,6 +33,7 @@ TEST_CASE("Basic BitScrambler I/O", "[bs]") bitscrambler_free(bs); TEST_ASSERT_EQUAL_HEX8_ARRAY(data_in, data_out, len); + TEST_ASSERT_EQUAL(len, res_len); free(data_in); free(data_out); diff --git a/components/esp_driver_bitscrambler/test_apps/bitscrambler/pytest_bitscrambler.py b/components/esp_driver_bitscrambler/test_apps/bitscrambler/pytest_bitscrambler.py index 1b73fbd6e86e..d73d1fed4b0b 100644 --- a/components/esp_driver_bitscrambler/test_apps/bitscrambler/pytest_bitscrambler.py +++ b/components/esp_driver_bitscrambler/test_apps/bitscrambler/pytest_bitscrambler.py @@ -1,10 +1,11 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut @pytest.mark.esp32p4 +@pytest.mark.esp32c5 @pytest.mark.generic def test_bitscrambler(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_driver_cam/test_apps/csi/CMakeLists.txt b/components/esp_driver_cam/test_apps/csi/CMakeLists.txt index ce5bab63b2f7..b8463898a663 100644 --- a/components/esp_driver_cam/test_apps/csi/CMakeLists.txt +++ b/components/esp_driver_cam/test_apps/csi/CMakeLists.txt @@ -6,3 +6,9 @@ set(COMPONENTS main) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(test_csi) + + +message(STATUS "Checking camera registers are not read-write by half-word") +include($ENV{IDF_PATH}/tools/ci/check_register_rw_half_word.cmake) +check_register_rw_half_word(SOC_MODULES "lcd_cam" "hp_sys_clkrst" "*csi*" + HAL_MODULES "cam" "*csi*") diff --git a/components/esp_driver_dac/test_apps/dac/CMakeLists.txt b/components/esp_driver_dac/test_apps/dac/CMakeLists.txt index 0e63a5808476..3bb25973d830 100644 --- a/components/esp_driver_dac/test_apps/dac/CMakeLists.txt +++ b/components/esp_driver_dac/test_apps/dac/CMakeLists.txt @@ -19,3 +19,8 @@ if(CONFIG_COMPILER_DUMP_RTL_FILES) DEPENDS ${elf} ) endif() + +message(STATUS "Checking dac registers are not read-write by half-word") +include($ENV{IDF_PATH}/tools/ci/check_register_rw_half_word.cmake) +check_register_rw_half_word(SOC_MODULES "rtc_io" "sens" "apb_saradc" + HAL_MODULES "dac") diff --git a/components/esp_driver_i2c/i2c_master.c b/components/esp_driver_i2c/i2c_master.c index 51a1cc8fb5c6..61f24794cad5 100644 --- a/components/esp_driver_i2c/i2c_master.c +++ b/components/esp_driver_i2c/i2c_master.c @@ -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 */ @@ -1134,6 +1134,13 @@ esp_err_t i2c_master_bus_rm_device(i2c_master_dev_handle_t handle) esp_err_t i2c_del_master_bus(i2c_master_bus_handle_t bus_handle) { ESP_LOGD(TAG, "del i2c bus(%d)", bus_handle->base->port_num); + + // Check if the device list is empty + if (!SLIST_EMPTY(&bus_handle->device_list)) { + ESP_LOGE(TAG, "Cannot delete I2C bus(%d): devices are still attached, please remove all devices and then delete bus", bus_handle->base->port_num); + return ESP_ERR_INVALID_STATE; + } + ESP_RETURN_ON_ERROR(i2c_master_bus_destroy(bus_handle), TAG, "destroy i2c bus failed"); return ESP_OK; } diff --git a/components/esp_driver_i2c/test_apps/i2c_test_apps/main/test_i2c_common.c b/components/esp_driver_i2c/test_apps/i2c_test_apps/main/test_i2c_common.c index 53034af1bda6..e7480fcd78da 100644 --- a/components/esp_driver_i2c/test_apps/i2c_test_apps/main/test_i2c_common.c +++ b/components/esp_driver_i2c/test_apps/i2c_test_apps/main/test_i2c_common.c @@ -141,8 +141,9 @@ TEST_CASE("I2C device add & remove check", "[i2c]") i2c_master_bus_rm_device(dev_1); i2c_master_bus_rm_device(dev_2); - i2c_master_bus_rm_device(dev_3); + TEST_ESP_ERR(ESP_ERR_INVALID_STATE, i2c_del_master_bus(bus_handle)); + i2c_master_bus_rm_device(dev_3); TEST_ESP_OK(i2c_del_master_bus(bus_handle)); } diff --git a/components/esp_driver_i2s/i2s_common.c b/components/esp_driver_i2s/i2s_common.c index 11487a80a22b..61d85c66f54e 100644 --- a/components/esp_driver_i2s/i2s_common.c +++ b/components/esp_driver_i2s/i2s_common.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 */ @@ -892,12 +892,12 @@ void i2s_gpio_check_and_set(i2s_chan_handle_t handle, int gpio, uint32_t signal_ if (gpio != (int)I2S_GPIO_UNUSED) { gpio_func_sel(gpio, PIN_FUNC_GPIO); if (is_input) { - /* Set direction, for some GPIOs, the input function are not enabled as default */ - gpio_set_direction(gpio, GPIO_MODE_INPUT); + /* Enable the input, for some GPIOs, the input function are not enabled as default */ + gpio_input_enable(gpio); esp_rom_gpio_connect_in_signal(gpio, signal_idx, is_invert); } else { i2s_output_gpio_reserve(handle, gpio); - gpio_set_direction(gpio, GPIO_MODE_OUTPUT); + /* output will be enabled in esp_rom_gpio_connect_out_signal */ esp_rom_gpio_connect_out_signal(gpio, signal_idx, is_invert, 0); } } @@ -908,7 +908,7 @@ void i2s_gpio_loopback_set(i2s_chan_handle_t handle, int gpio, uint32_t out_sig_ if (gpio != (int)I2S_GPIO_UNUSED) { i2s_output_gpio_reserve(handle, gpio); gpio_func_sel(gpio, PIN_FUNC_GPIO); - gpio_set_direction(gpio, GPIO_MODE_INPUT_OUTPUT); + gpio_input_enable(gpio); esp_rom_gpio_connect_out_signal(gpio, out_sig_idx, 0, 0); esp_rom_gpio_connect_in_signal(gpio, in_sig_idx, 0); } diff --git a/components/esp_driver_i2s/test_apps/i2s/CMakeLists.txt b/components/esp_driver_i2s/test_apps/i2s/CMakeLists.txt index 13fa5a9dc0ee..a5d1a43fada2 100644 --- a/components/esp_driver_i2s/test_apps/i2s/CMakeLists.txt +++ b/components/esp_driver_i2s/test_apps/i2s/CMakeLists.txt @@ -19,3 +19,8 @@ if(CONFIG_COMPILER_DUMP_RTL_FILES) DEPENDS ${elf} ) endif() + +message(STATUS "Checking i2s registers are not read-write by half-word") +include($ENV{IDF_PATH}/tools/ci/check_register_rw_half_word.cmake) +check_register_rw_half_word(SOC_MODULES "i2s" "pcr" "hp_sys_clkrst" + HAL_MODULES "i2s") diff --git a/components/esp_driver_i2s/test_apps/lp_i2s/CMakeLists.txt b/components/esp_driver_i2s/test_apps/lp_i2s/CMakeLists.txt index ec34dfb4ba7d..710d76198eb8 100644 --- a/components/esp_driver_i2s/test_apps/lp_i2s/CMakeLists.txt +++ b/components/esp_driver_i2s/test_apps/lp_i2s/CMakeLists.txt @@ -6,3 +6,8 @@ set(COMPONENTS main) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(lp_i2s_test) + +message(STATUS "Checking lp_i2s registers are not read-write by half-word") +include($ENV{IDF_PATH}/tools/ci/check_register_rw_half_word.cmake) +check_register_rw_half_word(SOC_MODULES "lp_i2s" "pcr" "hp_sys_clkrst" + HAL_MODULES "lp_i2s") diff --git a/components/esp_driver_isp/src/isp_ae.c b/components/esp_driver_isp/src/isp_ae.c index f6d421b45014..2ef283ed1a2e 100644 --- a/components/esp_driver_isp/src/isp_ae.c +++ b/components/esp_driver_isp/src/isp_ae.c @@ -101,6 +101,7 @@ esp_err_t esp_isp_new_ae_controller(isp_proc_handle_t isp_proc, const esp_isp_ae ESP_GOTO_ON_ERROR(intr_priority != isp_proc->intr_priority, err2, TAG, "intr_priority error"); ESP_GOTO_ON_ERROR(esp_isp_register_isr(ae_ctlr->isp_proc, ISP_SUBMODULE_AE), err2, TAG, "fail to register ISR"); + isp_ll_ae_set_clk_ctrl_mode(isp_proc->hal.hw, ISP_LL_PIPELINE_CLK_CTRL_AUTO); isp_ll_ae_set_sample_point(isp_proc->hal.hw, ae_config->sample_point); isp_ll_ae_enable(isp_proc->hal.hw, false); isp_hal_ae_window_config(&isp_proc->hal, &ae_config->window); @@ -141,7 +142,6 @@ esp_err_t esp_isp_ae_controller_enable(isp_ae_ctlr_t ae_ctlr) ESP_RETURN_ON_FALSE(atomic_compare_exchange_strong(&ae_ctlr->fsm, &expected_fsm, ISP_FSM_ENABLE), ESP_ERR_INVALID_STATE, TAG, "controller not in init state"); - isp_ll_ae_clk_enable(ae_ctlr->isp_proc->hal.hw, true); isp_ll_enable_intr(ae_ctlr->isp_proc->hal.hw, ISP_LL_EVENT_AE_MASK, true); isp_ll_ae_enable(ae_ctlr->isp_proc->hal.hw, true); @@ -155,7 +155,6 @@ esp_err_t esp_isp_ae_controller_disable(isp_ae_ctlr_t ae_ctlr) ESP_RETURN_ON_FALSE(atomic_compare_exchange_strong(&ae_ctlr->fsm, &expected_fsm, ISP_FSM_INIT), ESP_ERR_INVALID_STATE, TAG, "controller not in enable state"); - isp_ll_ae_clk_enable(ae_ctlr->isp_proc->hal.hw, false); isp_ll_enable_intr(ae_ctlr->isp_proc->hal.hw, ISP_LL_EVENT_AE_MASK, false); isp_ll_ae_enable(ae_ctlr->isp_proc->hal.hw, false); esp_intr_disable(ae_ctlr->intr_handle); diff --git a/components/esp_driver_isp/src/isp_af.c b/components/esp_driver_isp/src/isp_af.c index 28c2055328d0..b64fbf326678 100644 --- a/components/esp_driver_isp/src/isp_af.c +++ b/components/esp_driver_isp/src/isp_af.c @@ -127,6 +127,7 @@ esp_err_t esp_isp_new_af_controller(isp_proc_handle_t isp_proc, const esp_isp_af isp_ll_af_set_edge_thresh_mode(isp_proc->hal.hw, ISP_LL_AF_EDGE_DETECTOR_MODE_MANUAL); isp_ll_af_set_edge_thresh(isp_proc->hal.hw, af_config->edge_thresh); isp_ll_clear_intr(isp_proc->hal.hw, ISP_LL_EVENT_AF_MASK); + isp_ll_af_set_clk_ctrl_mode(isp_proc->hal.hw, ISP_LL_PIPELINE_CLK_CTRL_AUTO); *ret_hdl = af_ctlr; @@ -168,7 +169,6 @@ esp_err_t esp_isp_af_controller_enable(isp_af_ctlr_t af_ctlr) ESP_RETURN_ON_FALSE(atomic_compare_exchange_strong(&af_ctlr->fsm, &expected_fsm, ISP_FSM_ENABLE), ESP_ERR_INVALID_STATE, TAG, "controller not in init state"); - isp_ll_af_clk_enable(af_ctlr->isp_proc->hal.hw, true); isp_ll_enable_intr(af_ctlr->isp_proc->hal.hw, ISP_LL_EVENT_AF_MASK, true); isp_ll_af_enable(af_ctlr->isp_proc->hal.hw, true); @@ -182,7 +182,6 @@ esp_err_t esp_isp_af_controller_disable(isp_af_ctlr_t af_ctlr) ESP_RETURN_ON_FALSE(atomic_compare_exchange_strong(&af_ctlr->fsm, &expected_fsm, ISP_FSM_INIT), ESP_ERR_INVALID_STATE, TAG, "controller not in enable state"); - isp_ll_af_clk_enable(af_ctlr->isp_proc->hal.hw, false); isp_ll_enable_intr(af_ctlr->isp_proc->hal.hw, ISP_LL_EVENT_AF_MASK, false); isp_ll_af_enable(af_ctlr->isp_proc->hal.hw, false); esp_intr_disable(af_ctlr->intr_handle); diff --git a/components/esp_driver_isp/src/isp_awb.c b/components/esp_driver_isp/src/isp_awb.c index eb8abbb7d73f..46ce95bab218 100644 --- a/components/esp_driver_isp/src/isp_awb.c +++ b/components/esp_driver_isp/src/isp_awb.c @@ -109,6 +109,7 @@ esp_err_t esp_isp_new_awb_controller(isp_proc_handle_t isp_proc, const esp_isp_a // Configure the hardware 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); ESP_GOTO_ON_ERROR(s_esp_isp_awb_config_hardware(isp_proc, awb_cfg), err2, TAG, "configure awb hardware failed"); @@ -155,7 +156,6 @@ esp_err_t esp_isp_awb_controller_enable(isp_awb_ctlr_t awb_ctlr) ESP_ERR_INVALID_STATE, TAG, "controller not in init state"); esp_err_t ret = ESP_OK; - isp_ll_awb_clk_enable(awb_ctlr->isp_proc->hal.hw, true); isp_ll_enable_intr(awb_ctlr->isp_proc->hal.hw, ISP_LL_EVENT_AWB_MASK, true); return ret; @@ -169,7 +169,6 @@ esp_err_t esp_isp_awb_controller_disable(isp_awb_ctlr_t awb_ctlr) ESP_ERR_INVALID_STATE, TAG, "controller not in enable state"); isp_ll_enable_intr(awb_ctlr->isp_proc->hal.hw, ISP_LL_EVENT_AWB_MASK, false); - isp_ll_awb_clk_enable(awb_ctlr->isp_proc->hal.hw, false); esp_intr_disable(awb_ctlr->intr_handle); return ESP_OK; diff --git a/components/esp_driver_isp/src/isp_bf.c b/components/esp_driver_isp/src/isp_bf.c index 0d673c534ba5..f6f0befc2f0c 100644 --- a/components/esp_driver_isp/src/isp_bf.c +++ b/components/esp_driver_isp/src/isp_bf.c @@ -24,7 +24,6 @@ static const char *TAG = "ISP_BF"; esp_err_t esp_isp_bf_configure(isp_proc_handle_t proc, const esp_isp_bf_config_t *config) { 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"); if (config) { bool valid_padding_setting = (!config->padding_line_tail_valid_end_pixel && !config->padding_line_tail_valid_start_pixel) || (config->padding_line_tail_valid_end_pixel > config->padding_line_tail_valid_start_pixel); @@ -39,6 +38,7 @@ esp_err_t esp_isp_bf_configure(isp_proc_handle_t proc, const esp_isp_bf_config_t }; memcpy(bf_hal_cfg.bf_template, config->bf_template, ISP_BF_TEMPLATE_X_NUMS * ISP_BF_TEMPLATE_X_NUMS * sizeof(uint8_t)); isp_hal_bf_config(&(proc->hal), &bf_hal_cfg); + isp_ll_bf_set_clk_ctrl_mode(proc->hal.hw, ISP_LL_PIPELINE_CLK_CTRL_AUTO); } else { isp_hal_bf_config(&(proc->hal), NULL); } @@ -51,7 +51,6 @@ 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_ll_bf_clk_enable(proc->hal.hw, true); isp_ll_bf_enable(proc->hal.hw, true); proc->bf_fsm = ISP_FSM_ENABLE; @@ -64,7 +63,6 @@ esp_err_t esp_isp_bf_disable(isp_proc_handle_t proc) ESP_RETURN_ON_FALSE(proc->bf_fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "bf isn't enabled yet"); isp_ll_bf_enable(proc->hal.hw, false); - isp_ll_bf_clk_enable(proc->hal.hw, false); proc->bf_fsm = ISP_FSM_INIT; return ESP_OK; diff --git a/components/esp_driver_isp/src/isp_ccm.c b/components/esp_driver_isp/src/isp_ccm.c index 5fb45984884e..fd04c70cfbbf 100644 --- a/components/esp_driver_isp/src/isp_ccm.c +++ b/components/esp_driver_isp/src/isp_ccm.c @@ -23,6 +23,7 @@ esp_err_t esp_isp_ccm_configure(isp_proc_handle_t proc, const esp_isp_ccm_config bool ret = true; 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); portEXIT_CRITICAL(&proc->spinlock); ESP_RETURN_ON_FALSE(ret, ESP_ERR_INVALID_ARG, TAG, "invalid argument: ccm matrix contain NaN or out of range"); @@ -35,7 +36,6 @@ 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"); portENTER_CRITICAL(&proc->spinlock); - isp_ll_ccm_clk_enable(proc->hal.hw, true); isp_ll_ccm_enable(proc->hal.hw, true); portEXIT_CRITICAL(&proc->spinlock); @@ -48,7 +48,6 @@ esp_err_t esp_isp_ccm_disable(isp_proc_handle_t proc) portENTER_CRITICAL(&proc->spinlock); isp_ll_ccm_enable(proc->hal.hw, false); - isp_ll_ccm_clk_enable(proc->hal.hw, false); portEXIT_CRITICAL(&proc->spinlock); return ESP_OK; diff --git a/components/esp_driver_isp/src/isp_color.c b/components/esp_driver_isp/src/isp_color.c index 09e118c62685..cfd8227c89e2 100644 --- a/components/esp_driver_isp/src/isp_color.c +++ b/components/esp_driver_isp/src/isp_color.c @@ -38,6 +38,7 @@ esp_err_t esp_isp_color_configure(isp_proc_handle_t proc, const esp_isp_color_co .color_brightness = config->color_brightness, }; isp_hal_color_config(&(proc->hal), &color_hal_cfg); + isp_ll_color_set_clk_ctrl_mode(proc->hal.hw, ISP_LL_PIPELINE_CLK_CTRL_AUTO); } else { isp_hal_color_config(&(proc->hal), NULL); } @@ -50,7 +51,6 @@ 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_ll_color_clk_enable(proc->hal.hw, true); isp_ll_color_enable(proc->hal.hw, true); proc->color_fsm = ISP_FSM_ENABLE; @@ -63,7 +63,6 @@ esp_err_t esp_isp_color_disable(isp_proc_handle_t proc) ESP_RETURN_ON_FALSE(proc->color_fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "color isn't enabled yet"); isp_ll_color_enable(proc->hal.hw, false); - isp_ll_color_clk_enable(proc->hal.hw, false); proc->color_fsm = ISP_FSM_INIT; return ESP_OK; diff --git a/components/esp_driver_isp/src/isp_hist.c b/components/esp_driver_isp/src/isp_hist.c index 739a8a2ac788..f2c8620acc68 100644 --- a/components/esp_driver_isp/src/isp_hist.c +++ b/components/esp_driver_isp/src/isp_hist.c @@ -94,6 +94,7 @@ static esp_err_t s_esp_isp_hist_config_hardware(isp_proc_handle_t isp_proc, cons if (hist_cfg->hist_mode == ISP_HIST_SAMPLING_RGB) { isp_ll_hist_set_rgb_coefficient(isp_proc->hal.hw, &hist_cfg->rgb_coefficient); } + isp_ll_hist_set_clk_ctrl_mode(isp_proc->hal.hw, ISP_LL_PIPELINE_CLK_CTRL_AUTO); return ESP_OK; } @@ -158,7 +159,6 @@ esp_err_t esp_isp_hist_controller_enable(isp_hist_ctlr_t hist_ctlr) ESP_RETURN_ON_FALSE(atomic_compare_exchange_strong(&hist_ctlr->fsm, &expected_fsm, ISP_FSM_ENABLE), ESP_ERR_INVALID_STATE, TAG, "controller not in init state"); - isp_ll_hist_clk_enable(hist_ctlr->isp_proc->hal.hw, true); isp_ll_enable_intr(hist_ctlr->isp_proc->hal.hw, ISP_LL_EVENT_HIST_MASK, true); return ESP_OK; @@ -173,7 +173,6 @@ esp_err_t esp_isp_hist_controller_disable(isp_hist_ctlr_t hist_ctlr) ESP_ERR_INVALID_STATE, TAG, "controller not in enable state"); isp_ll_enable_intr(hist_ctlr->isp_proc->hal.hw, ISP_LL_EVENT_HIST_MASK, false); - isp_ll_hist_clk_enable(hist_ctlr->isp_proc->hal.hw, false); esp_intr_disable(hist_ctlr->intr_handle); return ESP_OK; diff --git a/components/esp_driver_isp/src/isp_lsc.c b/components/esp_driver_isp/src/isp_lsc.c index d8996e290598..a1b8e4c113ba 100644 --- a/components/esp_driver_isp/src/isp_lsc.c +++ b/components/esp_driver_isp/src/isp_lsc.c @@ -70,6 +70,7 @@ esp_err_t esp_isp_lsc_configure(isp_proc_handle_t isp_proc, const esp_isp_lsc_co ESP_RETURN_ON_FALSE(num_grids_x <= num_grids_x_max && num_grids_y <= num_grids_y_max, ESP_ERR_INVALID_ARG, TAG, "invalid h_res or v_res"); ESP_RETURN_ON_FALSE(config->gain_array->gain_r && config->gain_array->gain_gr && config->gain_array->gain_gb && config->gain_array->gain_b, ESP_ERR_INVALID_ARG, TAG, "null pointer to gain arrays"); + isp_ll_lsc_set_clk_ctrl_mode(isp_proc->hal.hw, ISP_LL_PIPELINE_CLK_CTRL_AUTO); isp_ll_lsc_set_xtablesize(isp_proc->hal.hw, num_grids_x); for (int y = 0; y < num_grids_y; y++) { @@ -90,7 +91,6 @@ 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_ll_lsc_clk_enable(isp_proc->hal.hw, true); isp_ll_lsc_enable(isp_proc->hal.hw, true); isp_proc->lsc_fsm = ISP_FSM_ENABLE; @@ -103,7 +103,6 @@ esp_err_t esp_isp_lsc_disable(isp_proc_handle_t isp_proc) ESP_RETURN_ON_FALSE(isp_proc->lsc_fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "lsc isn't enabled yet"); isp_ll_lsc_enable(isp_proc->hal.hw, false); - isp_ll_lsc_clk_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 abd88956ce28..750a5adb13d6 100644 --- a/components/esp_driver_isp/src/isp_sharpen.c +++ b/components/esp_driver_isp/src/isp_sharpen.c @@ -40,6 +40,7 @@ esp_err_t esp_isp_sharpen_configure(isp_proc_handle_t proc, const esp_isp_sharpe }; memcpy(sharpen_hal_cfg.sharpen_template, config->sharpen_template, ISP_SHARPEN_TEMPLATE_X_NUMS * ISP_SHARPEN_TEMPLATE_X_NUMS * sizeof(uint8_t)); isp_hal_sharpen_config(&(proc->hal), &sharpen_hal_cfg); + isp_ll_sharp_set_clk_ctrl_mode(proc->hal.hw, ISP_LL_PIPELINE_CLK_CTRL_AUTO); } else { isp_hal_sharpen_config(&(proc->hal), NULL); } @@ -52,7 +53,6 @@ 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_ll_sharp_clk_enable(proc->hal.hw, true); 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; @@ -67,7 +67,6 @@ esp_err_t esp_isp_sharpen_disable(isp_proc_handle_t proc) isp_ll_sharp_enable(proc->hal.hw, false); isp_ll_enable_intr(proc->hal.hw, ISP_LL_EVENT_SHARP_FRAME, false); - isp_ll_sharp_clk_enable(proc->hal.hw, false); proc->sharpen_fsm = ISP_FSM_INIT; return ESP_OK; diff --git a/components/esp_driver_isp/test_apps/isp/CMakeLists.txt b/components/esp_driver_isp/test_apps/isp/CMakeLists.txt index d940d8240b16..62a2bf08e1e5 100644 --- a/components/esp_driver_isp/test_apps/isp/CMakeLists.txt +++ b/components/esp_driver_isp/test_apps/isp/CMakeLists.txt @@ -6,3 +6,9 @@ set(COMPONENTS main) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(test_isp) + + +message(STATUS "Checking isp registers are not read-write by half-word") +include($ENV{IDF_PATH}/tools/ci/check_register_rw_half_word.cmake) +check_register_rw_half_word(SOC_MODULES "isp" "hp_sys_clkrst" + HAL_MODULES "isp") diff --git a/components/esp_driver_parlio/src/parlio_tx.c b/components/esp_driver_parlio/src/parlio_tx.c index dcdfd8f0730f..561f44935111 100644 --- a/components/esp_driver_parlio/src/parlio_tx.c +++ b/components/esp_driver_parlio/src/parlio_tx.c @@ -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 */ @@ -62,6 +62,7 @@ typedef struct parlio_tx_unit_t { #endif portMUX_TYPE spinlock; // prevent resource accessing by user and interrupt concurrently uint32_t out_clk_freq_hz; // output clock frequency + parlio_clock_source_t clk_src; // Parallel IO internal clock source size_t max_transfer_bits; // maximum transfer size in bits size_t queue_depth; // size of transaction queue size_t num_trans_inflight; // indicates the number of transactions that are undergoing but not recycled to ready_queue @@ -290,6 +291,7 @@ static esp_err_t parlio_select_periph_clock(parlio_tx_unit_t *tx_unit, const par if (tx_unit->out_clk_freq_hz != config->output_clk_freq_hz) { ESP_LOGW(TAG, "precision loss, real output frequency: %"PRIu32, tx_unit->out_clk_freq_hz); } + tx_unit->clk_src = clk_src; return ESP_OK; } @@ -465,6 +467,18 @@ static void IRAM_ATTR parlio_tx_do_transaction(parlio_tx_unit_t *tx_unit, parlio tx_unit->cur_trans = t; + // If the external clock is a non-free-running clock, it needs to be switched to the internal free-running clock first. + // And then switched back to the actual clock after the reset is completed. + bool switch_clk = tx_unit->clk_src == PARLIO_CLK_SRC_EXTERNAL ? true : false; + if (switch_clk) { + PARLIO_CLOCK_SRC_ATOMIC() { + parlio_ll_tx_set_clock_source(hal->regs, PARLIO_CLK_SRC_XTAL); + } + } + PARLIO_RCC_ATOMIC() { + parlio_ll_tx_reset_clock(hal->regs); + } + // DMA transfer data based on bytes not bits, so convert the bit length to bytes, round up gdma_buffer_mount_config_t mount_config = { .buffer = (void *)t->payload, @@ -474,14 +488,21 @@ static void IRAM_ATTR parlio_tx_do_transaction(parlio_tx_unit_t *tx_unit, parlio .mark_final = true, // singly link list, mark final descriptor } }; + // Since the threshold of the clock divider counter is not updated simultaneously with the clock source switching. + // The update of the threshold relies on the moment when the counter reaches the threshold each time. + // We place gdma_link_mount_buffers between reset clock and disable clock to ensure enough time for updating the threshold of the clock divider counter. gdma_link_mount_buffers(tx_unit->dma_link, 0, &mount_config, 1, NULL); - parlio_ll_tx_reset_fifo(hal->regs); - PARLIO_RCC_ATOMIC() { - parlio_ll_tx_reset_clock(hal->regs); + + if (switch_clk) { + PARLIO_CLOCK_SRC_ATOMIC() { + parlio_ll_tx_set_clock_source(hal->regs, PARLIO_CLK_SRC_EXTERNAL); + } } PARLIO_CLOCK_SRC_ATOMIC() { parlio_ll_tx_enable_clock(hal->regs, false); } + // reset tx fifo after disabling tx core clk to avoid unexpected rempty interrupt + parlio_ll_tx_reset_fifo(hal->regs); parlio_ll_tx_set_idle_data_value(hal->regs, t->idle_value); parlio_ll_tx_set_trans_bit_len(hal->regs, t->payload_bits); diff --git a/components/esp_driver_parlio/test_apps/parlio/main/test_board.h b/components/esp_driver_parlio/test_apps/parlio/main/test_board.h index a03a13ee22ff..1b43af7b49ba 100644 --- a/components/esp_driver_parlio/test_apps/parlio/main/test_board.h +++ b/components/esp_driver_parlio/test_apps/parlio/main/test_board.h @@ -22,6 +22,7 @@ extern "C" { #if CONFIG_IDF_TARGET_ESP32C6 #define TEST_CLK_GPIO 10 +#define TEST_EXT_CLK_GPIO 12 #define TEST_VALID_GPIO 11 #define TEST_DATA0_GPIO 0 #define TEST_DATA1_GPIO 1 @@ -33,6 +34,7 @@ extern "C" { #define TEST_DATA7_GPIO 7 #elif CONFIG_IDF_TARGET_ESP32C5 #define TEST_CLK_GPIO 25 +#define TEST_EXT_CLK_GPIO 10 #define TEST_VALID_GPIO 26 #define TEST_DATA0_GPIO 0 #define TEST_DATA1_GPIO 1 @@ -44,6 +46,7 @@ extern "C" { #define TEST_DATA7_GPIO 7 #elif CONFIG_IDF_TARGET_ESP32H2 #define TEST_VALID_GPIO 2 +#define TEST_EXT_CLK_GPIO 4 #define TEST_CLK_GPIO 3 #define TEST_DATA0_GPIO 8 #define TEST_DATA1_GPIO 5 @@ -55,6 +58,7 @@ extern "C" { #define TEST_DATA7_GPIO 12 #elif CONFIG_IDF_TARGET_ESP32P4 #define TEST_CLK_GPIO 33 +#define TEST_EXT_CLK_GPIO 34 #define TEST_VALID_GPIO 32 #define TEST_DATA0_GPIO 24 #define TEST_DATA1_GPIO 25 diff --git a/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_tx.c b/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_tx.c index d2bdfde79ec0..deb158bba525 100644 --- a/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_tx.c +++ b/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_tx.c @@ -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 */ @@ -11,9 +11,11 @@ #include "unity.h" #include "driver/parlio_tx.h" #include "driver/gpio.h" +#include "hal/parlio_ll.h" #include "soc/soc_caps.h" #include "esp_attr.h" #include "test_board.h" +#include "soc/parl_io_struct.h" TEST_CASE("parallel_tx_unit_install_uninstall", "[parlio_tx]") { @@ -338,3 +340,109 @@ TEST_CASE("parlio can transmit PSRAM buffer", "[parlio_tx]") free(buffer); } #endif // SOC_PSRAM_DMA_CAPABLE + +static void test_gpio_simulate_rising_edge(int gpio_sig, size_t times) +{ + while (times--) { + gpio_set_level(gpio_sig, 0); + gpio_set_level(gpio_sig, 1); + gpio_set_level(gpio_sig, 0); + } +} + +static uint8_t test_gpio_get_output_data(gpio_num_t* gpio, size_t gpio_num) +{ + uint8_t result = 0; + for (size_t i = 0; i < gpio_num; i++) { + int level = gpio_get_level(gpio[i]); + result |= level << i; + } + return result; +} + +static void test_use_external_non_free_running_clock(parlio_tx_unit_handle_t tx_unit, parlio_tx_unit_config_t config, int test_round) +{ + uint32_t clock_div = config.input_clk_src_freq_hz / config.output_clk_freq_hz; + TEST_ESP_OK(parlio_new_tx_unit(&config, &tx_unit)); + TEST_ESP_OK(parlio_tx_unit_enable(tx_unit)); + // let core clock running for a while to update the clock divider threshold + esp_rom_delay_us(100); + parlio_transmit_config_t transmit_config = { + .idle_value = 0xAA, + }; + __attribute__((aligned(64))) uint8_t payload[256] = {0}; + for (int i = 0; i < 256; i++) { + payload[i] = i; + } + + for (int round = 0; round < test_round; round++) { + TEST_ESP_OK(parlio_tx_unit_transmit(tx_unit, payload, 256 * sizeof(uint8_t) * 8, &transmit_config)); + for (int i = 0; i < 256; i++) { + // After "clock_div" times external pulses pass through the internal frequency divider, the parlio core clock generates a single pulse. + test_gpio_simulate_rising_edge(TEST_EXT_CLK_GPIO, clock_div); + TEST_ASSERT_EQUAL(i, test_gpio_get_output_data(config.data_gpio_nums, config.data_width)); + } + // In order to update the idle value, an additional rising edge is required + test_gpio_simulate_rising_edge(TEST_EXT_CLK_GPIO, clock_div); + TEST_ASSERT_EQUAL(transmit_config.idle_value, test_gpio_get_output_data(config.data_gpio_nums, config.data_width)); + TEST_ESP_OK(parlio_tx_unit_wait_all_done(tx_unit, 100)); + } + TEST_ESP_OK(parlio_tx_unit_disable(tx_unit)); + TEST_ESP_OK(parlio_del_tx_unit(tx_unit)); +} + +TEST_CASE("parallel tx unit use external non-free running clock", "[parlio_tx]") +{ + printf("use gpio as external clock source\r\n"); + // configure the data gpio for loopback test + gpio_config_t gpio_conf = { + .mode = GPIO_MODE_INPUT, + .pin_bit_mask = BIT64(TEST_DATA0_GPIO) | BIT64(TEST_DATA1_GPIO) | BIT64(TEST_DATA2_GPIO) | BIT64(TEST_DATA3_GPIO) | + BIT64(TEST_DATA4_GPIO) | BIT64(TEST_DATA5_GPIO) | BIT64(TEST_DATA6_GPIO) | BIT64(TEST_DATA7_GPIO), + }; + TEST_ESP_OK(gpio_config(&gpio_conf)); + // configure the external clock output gpio + gpio_conf.mode = GPIO_MODE_OUTPUT; + gpio_conf.pin_bit_mask = BIT64(TEST_EXT_CLK_GPIO); + TEST_ESP_OK(gpio_config(&gpio_conf)); + + printf("install parlio tx unit\r\n"); + parlio_tx_unit_handle_t tx_unit = NULL; + parlio_tx_unit_config_t config = { + .clk_src = PARLIO_CLK_SRC_DEFAULT, + .data_width = 8, + .clk_in_gpio_num = TEST_EXT_CLK_GPIO, + .input_clk_src_freq_hz = 80 * 1000 * 1000, // Note that this is not the real input frequency, we just use it to calculate the clock divider + .valid_gpio_num = -1, // don't generate valid signal + .clk_out_gpio_num = TEST_CLK_GPIO, + .data_gpio_nums = { + TEST_DATA0_GPIO, + TEST_DATA1_GPIO, + TEST_DATA2_GPIO, + TEST_DATA3_GPIO, + TEST_DATA4_GPIO, + TEST_DATA5_GPIO, + TEST_DATA6_GPIO, + TEST_DATA7_GPIO, + }, + .output_clk_freq_hz = 1 * 1000 * 1000, // For the same reason, this is not the real output frequency + .trans_queue_depth = 8, + .max_transfer_size = 256, + .bit_pack_order = PARLIO_BIT_PACK_ORDER_LSB, + .sample_edge = PARLIO_SAMPLE_EDGE_POS, + }; + + uint8_t test_round = 50; + printf("test input clk freq is greater than output clk freq\r\n"); + test_use_external_non_free_running_clock(tx_unit, config, test_round); + + // changes input clk freq + config.input_clk_src_freq_hz = 1 * 1000 * 1000; + printf("test special condition, input clk freq equals to output clk freq\r\n"); + test_use_external_non_free_running_clock(tx_unit, config, test_round); + + TEST_ESP_OK(gpio_reset_pin(TEST_EXT_CLK_GPIO)); + for (int i = 0; i < 8; i++) { + TEST_ESP_OK(gpio_reset_pin(config.data_gpio_nums[i])); + } +}; diff --git a/components/esp_driver_rmt/src/rmt_common.c b/components/esp_driver_rmt/src/rmt_common.c index 23d123d55315..066df4f1a420 100644 --- a/components/esp_driver_rmt/src/rmt_common.c +++ b/components/esp_driver_rmt/src/rmt_common.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 */ @@ -158,12 +158,64 @@ void rmt_release_group_handle(rmt_group_t *group) } } -esp_err_t rmt_select_periph_clock(rmt_channel_handle_t chan, rmt_clock_source_t clk_src) +#if !SOC_RMT_CHANNEL_CLK_INDEPENDENT +static esp_err_t s_rmt_set_group_prescale(rmt_channel_t *chan, uint32_t expect_resolution_hz, uint32_t *ret_channel_prescale) +{ + uint32_t periph_src_clk_hz = 0; + rmt_group_t *group = chan->group; + int group_id = group->group_id; + + ESP_RETURN_ON_ERROR(esp_clk_tree_src_get_freq_hz(group->clk_src, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &periph_src_clk_hz), TAG, "get clock source freq failed"); + + uint32_t group_resolution_hz = 0; + uint32_t group_prescale = 0; + uint32_t channel_prescale = 0; + + if (group->resolution_hz == 0) { + while (++group_prescale <= RMT_LL_GROUP_CLOCK_MAX_INTEGER_PRESCALE) { + group_resolution_hz = periph_src_clk_hz / group_prescale; + channel_prescale = (group_resolution_hz + expect_resolution_hz / 2) / expect_resolution_hz; + // use the first value found during the search that satisfies the division requirement (highest frequency) + if (channel_prescale > 0 && channel_prescale <= RMT_LL_CHANNEL_CLOCK_MAX_PRESCALE) { + break; + } + } + } else { + group_prescale = periph_src_clk_hz / group->resolution_hz; + channel_prescale = (group->resolution_hz + expect_resolution_hz / 2) / expect_resolution_hz; + } + + ESP_RETURN_ON_FALSE(group_prescale > 0 && group_prescale <= RMT_LL_GROUP_CLOCK_MAX_INTEGER_PRESCALE, ESP_ERR_INVALID_ARG, TAG, + "group prescale out of the range"); + ESP_RETURN_ON_FALSE(channel_prescale > 0 && channel_prescale <= RMT_LL_CHANNEL_CLOCK_MAX_PRESCALE, ESP_ERR_INVALID_ARG, TAG, + "channel prescale out of the range"); + + // group prescale is shared by all rmt_channel, only set once. use critical section to avoid race condition. + bool prescale_conflict = false; + group_resolution_hz = periph_src_clk_hz / group_prescale; + portENTER_CRITICAL(&group->spinlock); + if (group->resolution_hz == 0) { + group->resolution_hz = group_resolution_hz; + RMT_CLOCK_SRC_ATOMIC() { + rmt_ll_set_group_clock_src(group->hal.regs, chan->channel_id, group->clk_src, group_prescale, 1, 0); + rmt_ll_enable_group_clock(group->hal.regs, true); + } + } else { + prescale_conflict = (group->resolution_hz != group_resolution_hz); + } + portEXIT_CRITICAL(&group->spinlock); + ESP_RETURN_ON_FALSE(!prescale_conflict, ESP_ERR_INVALID_ARG, TAG, + "group resolution conflict, already is %"PRIu32" but attempt to %"PRIu32"", group->resolution_hz, group_resolution_hz); + ESP_LOGD(TAG, "group (%d) clock resolution:%"PRIu32"Hz", group_id, group->resolution_hz); + *ret_channel_prescale = channel_prescale; + return ESP_OK; +} +#endif // SOC_RMT_CHANNEL_CLK_INDEPENDENT + +esp_err_t rmt_select_periph_clock(rmt_channel_handle_t chan, rmt_clock_source_t clk_src, uint32_t expect_channel_resolution) { esp_err_t ret = ESP_OK; rmt_group_t *group = chan->group; - int channel_id = chan->channel_id; - uint32_t periph_src_clk_hz = 0; bool clock_selection_conflict = false; // check if we need to update the group clock source, group clock source is shared by all channels portENTER_CRITICAL(&group->spinlock); @@ -173,7 +225,7 @@ esp_err_t rmt_select_periph_clock(rmt_channel_handle_t chan, rmt_clock_source_t clock_selection_conflict = (group->clk_src != clk_src); } portEXIT_CRITICAL(&group->spinlock); - ESP_RETURN_ON_FALSE(!clock_selection_conflict, ESP_ERR_INVALID_STATE, TAG, + ESP_RETURN_ON_FALSE(!clock_selection_conflict, ESP_ERR_INVALID_ARG, TAG, "group clock conflict, already is %d but attempt to %d", group->clk_src, clk_src); // TODO: [clk_tree] to use a generic clock enable/disable or acquire/release function for all clock source @@ -185,10 +237,6 @@ esp_err_t rmt_select_periph_clock(rmt_channel_handle_t chan, rmt_clock_source_t } #endif // SOC_RMT_SUPPORT_RC_FAST - // get clock source frequency - ESP_RETURN_ON_ERROR(esp_clk_tree_src_get_freq_hz((soc_module_clk_t)clk_src, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &periph_src_clk_hz), - TAG, "get clock source frequency failed"); - #if CONFIG_PM_ENABLE // if DMA is not used, we're using CPU to push the data to the RMT FIFO // if the CPU frequency goes down, the transfer+encoding scheme could be unstable because CPU can't fill the data in time @@ -203,19 +251,40 @@ esp_err_t rmt_select_periph_clock(rmt_channel_handle_t chan, rmt_clock_source_t } #endif // SOC_RMT_SUPPORT_APB - sprintf(chan->pm_lock_name, "rmt_%d_%d", group->group_id, channel_id); // e.g. rmt_0_0 + sprintf(chan->pm_lock_name, "rmt_%d_%d", group->group_id, chan->channel_id); // e.g. rmt_0_0 ret = esp_pm_lock_create(pm_lock_type, 0, chan->pm_lock_name, &chan->pm_lock); ESP_RETURN_ON_ERROR(ret, TAG, "create pm lock failed"); #endif // CONFIG_PM_ENABLE esp_clk_tree_enable_src((soc_module_clk_t)clk_src, true); - // no division for group clock source, to achieve highest resolution + uint32_t real_div; +#if SOC_RMT_CHANNEL_CLK_INDEPENDENT + uint32_t periph_src_clk_hz = 0; + // get clock source frequency + ESP_RETURN_ON_ERROR(esp_clk_tree_src_get_freq_hz((soc_module_clk_t)clk_src, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &periph_src_clk_hz), + TAG, "get clock source frequency failed"); RMT_CLOCK_SRC_ATOMIC() { - rmt_ll_set_group_clock_src(group->hal.regs, channel_id, clk_src, 1, 1, 0); + rmt_ll_set_group_clock_src(group->hal.regs, chan->channel_id, clk_src, 1, 1, 0); rmt_ll_enable_group_clock(group->hal.regs, true); } group->resolution_hz = periph_src_clk_hz; ESP_LOGD(TAG, "group clock resolution:%"PRIu32, group->resolution_hz); + real_div = (group->resolution_hz + expect_channel_resolution / 2) / expect_channel_resolution; +#else + // set division for group clock source, to achieve highest resolution while guaranteeing the channel resolution. + ESP_RETURN_ON_ERROR(s_rmt_set_group_prescale(chan, expect_channel_resolution, &real_div), TAG, "set rmt group prescale failed"); +#endif // SOC_RMT_CHANNEL_CLK_INDEPENDENT + + if (chan->direction == RMT_CHANNEL_DIRECTION_TX) { + rmt_ll_tx_set_channel_clock_div(group->hal.regs, chan->channel_id, real_div); + } else { + rmt_ll_rx_set_channel_clock_div(group->hal.regs, chan->channel_id, real_div); + } + // resolution lost due to division, calculate the real resolution + chan->resolution_hz = group->resolution_hz / real_div; + if (chan->resolution_hz != expect_channel_resolution) { + ESP_LOGW(TAG, "channel resolution loss, real=%"PRIu32, chan->resolution_hz); + } return ret; } diff --git a/components/esp_driver_rmt/src/rmt_private.h b/components/esp_driver_rmt/src/rmt_private.h index eb191ec1c9a6..d4cecb61a9f7 100644 --- a/components/esp_driver_rmt/src/rmt_private.h +++ b/components/esp_driver_rmt/src/rmt_private.h @@ -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 */ @@ -19,6 +19,7 @@ #include "hal/rmt_hal.h" #include "hal/dma_types.h" #include "hal/cache_ll.h" +#include "hal/hal_utils.h" #include "esp_intr_alloc.h" #include "esp_heap_caps.h" #include "esp_clk_tree.h" @@ -113,7 +114,7 @@ struct rmt_group_t { portMUX_TYPE spinlock; // to protect per-group register level concurrent access rmt_hal_context_t hal; // hal layer for each group rmt_clock_source_t clk_src; // record the group clock source, group clock is shared by all channels - uint32_t resolution_hz; // resolution of group clock + uint32_t resolution_hz; // resolution of group clock. clk_src_hz / prescale = resolution_hz uint32_t occupy_mask; // a set bit in the mask indicates the channel is not available rmt_tx_channel_t *tx_channels[SOC_RMT_TX_CANDIDATES_PER_GROUP]; // array of RMT TX channels rmt_rx_channel_t *rx_channels[SOC_RMT_RX_CANDIDATES_PER_GROUP]; // array of RMT RX channels @@ -219,17 +220,18 @@ rmt_group_t *rmt_acquire_group_handle(int group_id); void rmt_release_group_handle(rmt_group_t *group); /** - * @brief Set clock source for RMT peripheral + * @brief Set clock source and resolution for RMT peripheral * * @param chan RMT channel handle * @param clk_src Clock source + * @param expect_channel_resolution Expected channel resolution * @return * - ESP_OK: Set clock source successfully * - ESP_ERR_NOT_SUPPORTED: Set clock source failed because the clk_src is not supported * - ESP_ERR_INVALID_STATE: Set clock source failed because the clk_src is different from other RMT channel * - ESP_FAIL: Set clock source failed because of other error */ -esp_err_t rmt_select_periph_clock(rmt_channel_handle_t chan, rmt_clock_source_t clk_src); +esp_err_t rmt_select_periph_clock(rmt_channel_handle_t chan, rmt_clock_source_t clk_src, uint32_t expect_channel_resolution); /** * @brief Set interrupt priority to RMT group diff --git a/components/esp_driver_rmt/src/rmt_rx.c b/components/esp_driver_rmt/src/rmt_rx.c index 3e77b7644f08..05ecc295aec8 100644 --- a/components/esp_driver_rmt/src/rmt_rx.c +++ b/components/esp_driver_rmt/src/rmt_rx.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 */ @@ -276,16 +276,9 @@ esp_err_t rmt_new_rx_channel(const rmt_rx_channel_config_t *config, rmt_channel_ ESP_GOTO_ON_ERROR(ret, err, TAG, "install rx interrupt failed"); } - // select the clock source - ESP_GOTO_ON_ERROR(rmt_select_periph_clock(&rx_channel->base, config->clk_src), err, TAG, "set group clock failed"); - // set channel clock resolution, find the divider to get the closest resolution - uint32_t real_div = (group->resolution_hz + config->resolution_hz / 2) / config->resolution_hz; - rmt_ll_rx_set_channel_clock_div(hal->regs, channel_id, real_div); - // resolution loss due to division, calculate the real resolution - rx_channel->base.resolution_hz = group->resolution_hz / real_div; - if (rx_channel->base.resolution_hz != config->resolution_hz) { - ESP_LOGW(TAG, "channel resolution loss, real=%"PRIu32, rx_channel->base.resolution_hz); - } + rx_channel->base.direction = RMT_CHANNEL_DIRECTION_RX; + // select the clock source and set clock resolution + ESP_GOTO_ON_ERROR(rmt_select_periph_clock(&rx_channel->base, config->clk_src, config->resolution_hz), err, TAG, "set clock resolution failed"); rx_channel->filter_clock_resolution_hz = group->resolution_hz; // On esp32 and esp32s2, the counting clock used by the RX filter always comes from APB clock @@ -323,7 +316,6 @@ esp_err_t rmt_new_rx_channel(const rmt_rx_channel_config_t *config, rmt_channel_ // initialize other members of rx channel portMUX_INITIALIZE(&rx_channel->base.spinlock); atomic_init(&rx_channel->base.fsm, RMT_FSM_INIT); - rx_channel->base.direction = RMT_CHANNEL_DIRECTION_RX; rx_channel->base.hw_mem_base = &RMTMEM.channels[channel_id + RMT_RX_CHANNEL_OFFSET_IN_GROUP].symbols[0]; // polymorphic methods rx_channel->base.del = rmt_del_rx_channel; @@ -630,12 +622,12 @@ static bool IRAM_ATTR rmt_isr_handle_rx_done(rmt_rx_channel_t *rx_chan) // even user process the partial received data, the remain buffer may still be insufficient if (mem_want > mem_have) { - ESP_DRAM_LOGE(TAG, "user buffer too small, received symbols truncated"); + ESP_DRAM_LOGD(TAG, "user buffer too small, received symbols truncated"); copy_size = mem_have; } } } else { - ESP_DRAM_LOGE(TAG, "user buffer too small, received symbols truncated"); + ESP_DRAM_LOGD(TAG, "user buffer too small, received symbols truncated"); copy_size = mem_have; } } @@ -656,7 +648,7 @@ static bool IRAM_ATTR rmt_isr_handle_rx_done(rmt_rx_channel_t *rx_chan) portEXIT_CRITICAL_ISR(&channel->spinlock); // this clear operation can only take effect after we copy out the received data and reset the pointer rmt_ll_clear_interrupt_status(hal->regs, RMT_LL_EVENT_RX_ERROR(channel_id)); - ESP_DRAM_LOGE(TAG, "hw buffer too small, received symbols truncated"); + ESP_DRAM_LOGD(TAG, "hw buffer too small, received symbols truncated"); } #endif // !SOC_RMT_SUPPORT_RX_PINGPONG @@ -715,12 +707,12 @@ static bool IRAM_ATTR rmt_isr_handle_rx_threshold(rmt_rx_channel_t *rx_chan) // even user process the partial received data, the remain buffer size still insufficient if (mem_want > mem_have) { - ESP_DRAM_LOGE(TAG, "user buffer too small, received symbols truncated"); + ESP_DRAM_LOGD(TAG, "user buffer too small, received symbols truncated"); copy_size = mem_have; } } } else { - ESP_DRAM_LOGE(TAG, "user buffer too small, received symbols truncated"); + ESP_DRAM_LOGD(TAG, "user buffer too small, received symbols truncated"); copy_size = mem_have; } } diff --git a/components/esp_driver_rmt/src/rmt_tx.c b/components/esp_driver_rmt/src/rmt_tx.c index acf34ab87384..891125216f74 100644 --- a/components/esp_driver_rmt/src/rmt_tx.c +++ b/components/esp_driver_rmt/src/rmt_tx.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 */ @@ -331,16 +331,9 @@ esp_err_t rmt_new_tx_channel(const rmt_tx_channel_config_t *config, rmt_channel_ ESP_GOTO_ON_ERROR(rmt_tx_init_dma_link(tx_channel, config), err, TAG, "install tx DMA failed"); } #endif - // select the clock source - ESP_GOTO_ON_ERROR(rmt_select_periph_clock(&tx_channel->base, config->clk_src), err, TAG, "set group clock failed"); - // set channel clock resolution, find the divider to get the closest resolution - uint32_t real_div = (group->resolution_hz + config->resolution_hz / 2) / config->resolution_hz; - rmt_ll_tx_set_channel_clock_div(hal->regs, channel_id, real_div); - // resolution lost due to division, calculate the real resolution - tx_channel->base.resolution_hz = group->resolution_hz / real_div; - if (tx_channel->base.resolution_hz != config->resolution_hz) { - ESP_LOGW(TAG, "channel resolution loss, real=%"PRIu32, tx_channel->base.resolution_hz); - } + tx_channel->base.direction = RMT_CHANNEL_DIRECTION_TX; + // select the clock source and set clock resolution + ESP_GOTO_ON_ERROR(rmt_select_periph_clock(&tx_channel->base, config->clk_src, config->resolution_hz), err, TAG, "set clock resolution failed"); rmt_ll_tx_set_mem_blocks(hal->regs, channel_id, tx_channel->base.mem_block_num); // set limit threshold, after transmit ping_pong_symbols size, an interrupt event would be generated @@ -376,7 +369,6 @@ esp_err_t rmt_new_tx_channel(const rmt_tx_channel_config_t *config, rmt_channel_ portMUX_INITIALIZE(&tx_channel->base.spinlock); atomic_init(&tx_channel->base.fsm, RMT_FSM_INIT); - tx_channel->base.direction = RMT_CHANNEL_DIRECTION_TX; tx_channel->base.hw_mem_base = &RMTMEM.channels[channel_id + RMT_TX_CHANNEL_OFFSET_IN_GROUP].symbols[0]; // polymorphic methods tx_channel->base.del = rmt_del_tx_channel; diff --git a/components/esp_driver_rmt/test_apps/rmt/main/test_rmt_common.c b/components/esp_driver_rmt/test_apps/rmt/main/test_rmt_common.c index fa00514215bb..59b2adc65fc0 100644 --- a/components/esp_driver_rmt/test_apps/rmt/main/test_rmt_common.c +++ b/components/esp_driver_rmt/test_apps/rmt/main/test_rmt_common.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 */ @@ -155,3 +155,34 @@ TEST_CASE("rmt interrupt priority", "[rmt]") TEST_ESP_OK(rmt_del_channel(rx_channel)); TEST_ESP_OK(rmt_del_channel(another_rx_channel)); } + +#if !SOC_RMT_CHANNEL_CLK_INDEPENDENT +TEST_CASE("rmt multiple channels with different resolution", "[rmt]") +{ + rmt_tx_channel_config_t tx_channel_cfg = { + .mem_block_symbols = SOC_RMT_MEM_WORDS_PER_CHANNEL, + .gpio_num = TEST_RMT_GPIO_NUM_A, + .clk_src = RMT_CLK_SRC_DEFAULT, + .resolution_hz = 20 * 1000, // 20KHz + .trans_queue_depth = 1, + }; + rmt_channel_handle_t tx_channel = NULL; + rmt_rx_channel_config_t rx_channel_cfg = { + .mem_block_symbols = SOC_RMT_MEM_WORDS_PER_CHANNEL, + .gpio_num = TEST_RMT_GPIO_NUM_B, + .clk_src = RMT_CLK_SRC_DEFAULT, + .resolution_hz = 40 * 1000 * 1000, // 40MHz + }; + rmt_channel_handle_t rx_channel = NULL; + + TEST_ESP_OK(rmt_new_tx_channel(&tx_channel_cfg, &tx_channel)); + + TEST_ESP_ERR(ESP_ERR_INVALID_ARG, rmt_new_rx_channel(&rx_channel_cfg, &rx_channel)); + rx_channel_cfg.resolution_hz = 1 * 1000 * 1000; // 1MHz + + TEST_ESP_OK(rmt_new_rx_channel(&rx_channel_cfg, &rx_channel)); + + TEST_ESP_OK(rmt_del_channel(tx_channel)); + TEST_ESP_OK(rmt_del_channel(rx_channel)); +} +#endif //SOC_RMT_CHANNEL_CLK_INDEPENDENT diff --git a/components/esp_driver_sdmmc/include/driver/sdmmc_default_configs.h b/components/esp_driver_sdmmc/include/driver/sdmmc_default_configs.h index 5b0bc07f0ffb..1112bcd1bcb9 100644 --- a/components/esp_driver_sdmmc/include/driver/sdmmc_default_configs.h +++ b/components/esp_driver_sdmmc/include/driver/sdmmc_default_configs.h @@ -49,7 +49,8 @@ extern "C" { .set_input_delay = &sdmmc_host_set_input_delay, \ .dma_aligned_buffer = NULL, \ .pwr_ctrl_handle = NULL, \ - .get_dma_info = &sdmmc_host_get_dma_info, \ + .get_dma_info = NULL, \ + .check_buffer_alignment = &sdmmc_host_check_buffer_alignment, \ .is_slot_set_to_uhs1 = &sdmmc_host_is_slot_set_to_uhs1, \ } diff --git a/components/esp_driver_sdmmc/include/driver/sdmmc_host.h b/components/esp_driver_sdmmc/include/driver/sdmmc_host.h index 037dbe83cf81..d6d3f856ac36 100644 --- a/components/esp_driver_sdmmc/include/driver/sdmmc_host.h +++ b/components/esp_driver_sdmmc/include/driver/sdmmc_host.h @@ -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 */ @@ -11,6 +11,7 @@ #include #include +#include #include "esp_err.h" #include "driver/sdmmc_types.h" #include "driver/sdmmc_default_configs.h" @@ -276,13 +277,27 @@ esp_err_t sdmmc_host_set_input_delay(int slot, sdmmc_delay_phase_t delay_phase); /** * @brief Get the DMA memory information for the host driver * + * @deprecated This API is deprecated + * * @param[in] slot slot number (SDMMC_HOST_SLOT_0 or SDMMC_HOST_SLOT_1) * @param[out] dma_mem_info DMA memory information structure * @return * - ESP_OK: ON success. * - ESP_ERR_INVALID_ARG: Invalid argument. */ -esp_err_t sdmmc_host_get_dma_info(int slot, esp_dma_mem_info_t *dma_mem_info); +esp_err_t sdmmc_host_get_dma_info(int slot, esp_dma_mem_info_t *dma_mem_info) __attribute__((deprecated("This API is deprecated"))); + +/** + * @brief Check if the buffer meets the alignment requirements + * + * @param[in] slot slot number (SDMMC_HOST_SLOT_0 or SDMMC_HOST_SLOT_1) + * @param[in] buf buffer pointer + * @param[in] size buffer size + * + * @return + * True for aligned buffer, false for not aligned buffer + */ +bool sdmmc_host_check_buffer_alignment(int slot, const void *buf, size_t size); /** * @brief Check if the slot is set to uhs1 or not diff --git a/components/esp_driver_sdmmc/src/sdmmc_host.c b/components/esp_driver_sdmmc/src/sdmmc_host.c index 92099c6104eb..ef10e7f2ef56 100644 --- a/components/esp_driver_sdmmc/src/sdmmc_host.c +++ b/components/esp_driver_sdmmc/src/sdmmc_host.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 */ @@ -20,9 +20,11 @@ #include "driver/sdmmc_host.h" #include "esp_private/esp_clk_tree_common.h" #include "esp_private/periph_ctrl.h" +#include "esp_private/esp_cache_private.h" #include "sdmmc_internal.h" #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" +#include "esp_memory_utils.h" #include "esp_clk_tree.h" #include "soc/sdmmc_periph.h" #include "soc/soc_caps.h" @@ -1161,6 +1163,38 @@ esp_err_t sdmmc_host_get_dma_info(int slot, esp_dma_mem_info_t *dma_mem_info) return ESP_OK; } +bool sdmmc_host_check_buffer_alignment(int slot, const void *buf, size_t size) +{ + //for future-proof + (void)slot; + + if (!buf || !size) { + return ESP_FAIL; + } + + esp_err_t ret = ESP_FAIL; + int cache_flags = 0; + size_t cache_alignment_bytes = 0; + if (esp_ptr_external_ram(buf)) { + cache_flags |= MALLOC_CAP_SPIRAM; + } + ret = esp_cache_get_alignment(cache_flags, &cache_alignment_bytes); + assert(ret == ESP_OK); + + bool is_aligned = false; + size_t alignment = 0; + + if (cache_alignment_bytes != 0) { + alignment = cache_alignment_bytes; + } else { + alignment = 4; + } + + is_aligned = ((intptr_t)buf % alignment == 0) && (size % alignment == 0); + + return is_aligned; +} + esp_err_t sdmmc_host_get_state(sdmmc_host_state_t* state) { if (state == NULL) { diff --git a/components/esp_driver_sdmmc/src/sdmmc_transaction.c b/components/esp_driver_sdmmc/src/sdmmc_transaction.c index 55cf55a40299..c9b5fd80e68f 100644 --- a/components/esp_driver_sdmmc/src/sdmmc_transaction.c +++ b/components/esp_driver_sdmmc/src/sdmmc_transaction.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 */ @@ -147,12 +147,9 @@ esp_err_t sdmmc_host_do_transaction(int slot, sdmmc_command_t* cmdinfo) ret = ESP_ERR_INVALID_SIZE; goto out; } - esp_dma_mem_info_t dma_mem_info; - sdmmc_host_get_dma_info(slot, &dma_mem_info); -#ifdef SOC_SDMMC_PSRAM_DMA_CAPABLE - dma_mem_info.extra_heap_caps |= MALLOC_CAP_SPIRAM; -#endif - if (!esp_dma_is_buffer_alignment_satisfied(cmdinfo->data, cmdinfo->buflen, dma_mem_info)) { + + bool is_aligned = sdmmc_host_check_buffer_alignment(slot, cmdinfo->data, cmdinfo->buflen); + if (!is_aligned) { ESP_LOGE(TAG, "%s: buffer %p can not be used for DMA", __func__, cmdinfo->data); ret = ESP_ERR_INVALID_ARG; goto out; diff --git a/components/esp_driver_sdmmc/test_apps/sd_test_utils/components/common_test_flows/sdmmc_test_rw_common.c b/components/esp_driver_sdmmc/test_apps/sd_test_utils/components/common_test_flows/sdmmc_test_rw_common.c index b883e0043594..ca337fa8a90e 100644 --- a/components/esp_driver_sdmmc/test_apps/sd_test_utils/components/common_test_flows/sdmmc_test_rw_common.c +++ b/components/esp_driver_sdmmc/test_apps/sd_test_utils/components/common_test_flows/sdmmc_test_rw_common.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 */ @@ -9,7 +9,6 @@ #include #include #include -#include "esp_dma_utils.h" #include "esp_heap_caps.h" #include "test_utils.h" #include "sdkconfig.h" @@ -53,13 +52,9 @@ static void do_single_rw_perf_test(sdmmc_card_t* card, size_t start_block, const char* alloc_str = (extra_alloc_caps & MALLOC_CAP_SPIRAM) ? "spiram" : " sram "; printf(" %8d | %3d | %d | %s | %4.1f ", start_block, block_count, alignment, alloc_str, total_size / 1024.0f); - size_t actual_size = 0; uint32_t *buffer = NULL; - esp_dma_mem_info_t dma_mem_info = { - .extra_heap_caps = extra_alloc_caps, - .dma_alignment_bytes = 64, - }; - TEST_ESP_OK(esp_dma_capable_malloc(total_size + 4, &dma_mem_info, (void**) &buffer, &actual_size)); + buffer = heap_caps_malloc(total_size + 4, MALLOC_CAP_DMA); + TEST_ASSERT(buffer); size_t offset = alignment % 4; uint8_t* c_buffer = (uint8_t*) buffer + offset; @@ -107,12 +102,10 @@ void sdmmc_test_rw_unaligned_buffer(sdmmc_card_t* card) const size_t block_count = buffer_size / 512; const size_t extra = 4; const size_t total_size = buffer_size + extra; - size_t actual_size = 0; uint8_t *buffer = NULL; - esp_dma_mem_info_t dma_mem_info = { - .dma_alignment_bytes = 64, - }; - TEST_ESP_OK(esp_dma_capable_malloc(total_size + 4, &dma_mem_info, (void**) &buffer, &actual_size)); + + buffer = heap_caps_malloc(total_size + 4, MALLOC_CAP_DMA); + TEST_ASSERT(buffer); // Check read behavior: do aligned write, then unaligned read const uint32_t seed = 0x89abcdef; diff --git a/components/esp_driver_sdspi/CMakeLists.txt b/components/esp_driver_sdspi/CMakeLists.txt index b9af00622a0c..73bb453bc727 100644 --- a/components/esp_driver_sdspi/CMakeLists.txt +++ b/components/esp_driver_sdspi/CMakeLists.txt @@ -15,7 +15,7 @@ if(${target} STREQUAL "linux") set(priv_requires esp_timer) else() set(requires sdmmc esp_driver_spi esp_driver_gpio) - set(priv_requires esp_timer) + set(priv_requires esp_timer esp_mm) endif() idf_component_register(SRCS ${srcs} diff --git a/components/esp_driver_sdspi/include/driver/sdspi_host.h b/components/esp_driver_sdspi/include/driver/sdspi_host.h index e6ead840f8c4..73410bdb02ab 100644 --- a/components/esp_driver_sdspi/include/driver/sdspi_host.h +++ b/components/esp_driver_sdspi/include/driver/sdspi_host.h @@ -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 */ @@ -8,6 +8,7 @@ #include #include +#include #include "esp_err.h" #include "sd_protocol_types.h" #include "driver/gpio.h" @@ -61,7 +62,8 @@ typedef int sdspi_dev_handle_t; .set_input_delay = NULL, \ .dma_aligned_buffer = NULL, \ .pwr_ctrl_handle = NULL, \ - .get_dma_info = &sdspi_host_get_dma_info, \ + .get_dma_info = NULL, \ + .check_buffer_alignment = sdspi_host_check_buffer_alignment, \ .is_slot_set_to_uhs1 = NULL, \ } @@ -223,13 +225,27 @@ esp_err_t sdspi_host_io_int_wait(sdspi_dev_handle_t handle, TickType_t timeout_t /** * @brief Get the DMA memory information for the host driver * + * @deprecated This API is deprecated + * * @param[in] slot Not used * @param[out] dma_mem_info DMA memory information structure * @return * - ESP_OK: ON success. * - ESP_ERR_INVALID_ARG: Invalid argument. */ -esp_err_t sdspi_host_get_dma_info(int slot, esp_dma_mem_info_t *dma_mem_info); +esp_err_t sdspi_host_get_dma_info(int slot, esp_dma_mem_info_t *dma_mem_info) __attribute__((deprecated("This API is deprecated"))); + +/** + * @brief Check if the buffer meets the alignment requirements + * + * @param[in] slot slot number (SDMMC_HOST_SLOT_0 or SDMMC_HOST_SLOT_1) + * @param[in] buf buffer pointer + * @param[in] size buffer size + * + * @return + * True for aligned buffer, false for not aligned buffer + */ +bool sdspi_host_check_buffer_alignment(int slot, const void *buf, size_t size); #ifdef __cplusplus } diff --git a/components/esp_driver_sdspi/src/sdspi_host.c b/components/esp_driver_sdspi/src/sdspi_host.c index f532dd49099d..90f4df80421c 100644 --- a/components/esp_driver_sdspi/src/sdspi_host.c +++ b/components/esp_driver_sdspi/src/sdspi_host.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 */ @@ -21,6 +21,7 @@ #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" #include "soc/soc_memory_layout.h" +#include "esp_private/esp_cache_private.h" /// Max number of transactions in flight (used in start_command_write_blocks) #define SDSPI_TRANSACTION_COUNT 4 @@ -1009,3 +1010,18 @@ esp_err_t sdspi_host_get_dma_info(int slot, esp_dma_mem_info_t *dma_mem_info) dma_mem_info->dma_alignment_bytes = 4; return ESP_OK; } + +bool sdspi_host_check_buffer_alignment(int slot, const void *buf, size_t size) +{ + //for future-proof + (void)slot; + + if (!buf || !size) { + return ESP_FAIL; + } + + //spi master driver will deal with the buffer alignment + bool is_aligned = ((intptr_t)buf % 4 == 0) && (size % 4 == 0); + + return is_aligned; +} diff --git a/components/esp_driver_spi/src/gpspi/spi_slave.c b/components/esp_driver_spi/src/gpspi/spi_slave.c index ae9d6d8f8c86..4d41aa60e045 100644 --- a/components/esp_driver_spi/src/gpspi/spi_slave.c +++ b/components/esp_driver_spi/src/gpspi/spi_slave.c @@ -471,7 +471,7 @@ esp_err_t SPI_SLAVE_ATTR spi_slave_queue_reset(spi_host_device_t host) spi_slave_trans_priv_t trans; while (uxQueueMessagesWaiting(spihost[host]->trans_queue)) { - xQueueReceive(spihost[host]->trans_queue, &trans, 0); + SPI_CHECK(pdTRUE == xQueueReceive(spihost[host]->trans_queue, &trans, 0), "can't reset queue", ESP_ERR_INVALID_STATE); spi_slave_uninstall_priv_trans(host, &trans); } spihost[host]->cur_trans.trans = NULL; @@ -524,15 +524,20 @@ esp_err_t SPI_SLAVE_ISR_ATTR spi_slave_queue_reset_isr(spi_host_device_t host) ESP_RETURN_ON_FALSE_ISR(is_valid_host(host), ESP_ERR_INVALID_ARG, SPI_TAG, "invalid host"); ESP_RETURN_ON_FALSE_ISR(spihost[host], ESP_ERR_INVALID_ARG, SPI_TAG, "host not slave"); + esp_err_t err = ESP_OK; spi_slave_trans_priv_t trans; BaseType_t do_yield = pdFALSE; while (pdFALSE == xQueueIsQueueEmptyFromISR(spihost[host]->trans_queue)) { - xQueueReceiveFromISR(spihost[host]->trans_queue, &trans, &do_yield); + if (pdTRUE != xQueueReceiveFromISR(spihost[host]->trans_queue, &trans, &do_yield)) { + err = ESP_ERR_INVALID_STATE; + break; + } spi_slave_uninstall_priv_trans(host, &trans); } if (do_yield) { portYIELD_FROM_ISR(); } + ESP_RETURN_ON_ERROR_ISR(err, SPI_TAG, "can't reset queue"); spihost[host]->cur_trans.trans = NULL; return ESP_OK; diff --git a/components/esp_driver_spi/src/gpspi/spi_slave_hd.c b/components/esp_driver_spi/src/gpspi/spi_slave_hd.c index adf545d4ee6d..3f70338433d7 100644 --- a/components/esp_driver_spi/src/gpspi/spi_slave_hd.c +++ b/components/esp_driver_spi/src/gpspi/spi_slave_hd.c @@ -437,7 +437,7 @@ static IRAM_ATTR void s_spi_slave_hd_segment_isr(void *arg) bool rx_sent = false; if (!host->tx_curr_trans.trans) { ret = xQueueReceiveFromISR(host->tx_trans_queue, &host->tx_curr_trans, &awoken); - if (ret == pdTRUE) { + if ((ret == pdTRUE) && host->tx_curr_trans.trans) { spicommon_dma_desc_setup_link(hal->dmadesc_tx->desc, host->tx_curr_trans.aligned_buffer, host->tx_curr_trans.trans->len, false); spi_dma_reset(host->dma_ctx->tx_dma_chan); spi_slave_hd_hal_txdma(hal); @@ -456,7 +456,7 @@ static IRAM_ATTR void s_spi_slave_hd_segment_isr(void *arg) } if (!host->rx_curr_trans.trans) { ret = xQueueReceiveFromISR(host->rx_trans_queue, &host->rx_curr_trans, &awoken); - if (ret == pdTRUE) { + if ((ret == pdTRUE) && host->rx_curr_trans.trans) { spicommon_dma_desc_setup_link(hal->dmadesc_rx->desc, host->rx_curr_trans.aligned_buffer, host->rx_curr_trans.trans->len, true); spi_dma_reset(host->dma_ctx->rx_dma_chan); spi_slave_hd_hal_rxdma(hal); diff --git a/components/esp_driver_spi/test_apps/master/CMakeLists.txt b/components/esp_driver_spi/test_apps/master/CMakeLists.txt index a089345e26a2..4dcfbc1419fd 100644 --- a/components/esp_driver_spi/test_apps/master/CMakeLists.txt +++ b/components/esp_driver_spi/test_apps/master/CMakeLists.txt @@ -19,3 +19,8 @@ if(CONFIG_COMPILER_DUMP_RTL_FILES) DEPENDS ${elf} ) endif() + +message(STATUS "Checking spi registers are not read-write by half-word") +include($ENV{IDF_PATH}/tools/ci/check_register_rw_half_word.cmake) +check_register_rw_half_word(SOC_MODULES "spi" "syscon" "pcr" "system" "hp_sys_clkrst" + HAL_MODULES "spi") diff --git a/components/esp_driver_touch_sens/test_apps/touch_sens/CMakeLists.txt b/components/esp_driver_touch_sens/test_apps/touch_sens/CMakeLists.txt index e774828c4d60..8c138d6cdbd0 100644 --- a/components/esp_driver_touch_sens/test_apps/touch_sens/CMakeLists.txt +++ b/components/esp_driver_touch_sens/test_apps/touch_sens/CMakeLists.txt @@ -20,3 +20,9 @@ if(CONFIG_COMPILER_DUMP_RTL_FILES) DEPENDS ${elf} ) endif() + +message(STATUS "Checking touch sensor registers are not read-write by half-word") +include($ENV{IDF_PATH}/tools/ci/check_register_rw_half_word.cmake) +check_register_rw_half_word(SOC_MODULES "rtc_cntl" "sens" "rtc_io" "lp_analog_peri" + "lp_clkrst" "lp_system" "lpperi" "touch" "pmu" + HAL_MODULES "touch_sensor") diff --git a/components/esp_eth/src/mac/esp_eth_mac_esp_gpio.c b/components/esp_eth/src/mac/esp_eth_mac_esp_gpio.c index 3117832b294c..949f58309435 100644 --- a/components/esp_eth/src/mac/esp_eth_mac_esp_gpio.c +++ b/components/esp_eth/src/mac/esp_eth_mac_esp_gpio.c @@ -32,13 +32,13 @@ static esp_err_t emac_esp_gpio_matrix_init(gpio_num_t gpio_num, uint32_t signal_ ESP_LOGD(TAG, "%s skipping signal in_idx %" PRIu32 ", out_idx %" PRIu32, __func__, signal_in_idx, signal_out_idx); return ESP_OK; } - ESP_RETURN_ON_ERROR(gpio_set_direction(gpio_num, mode), TAG, "failed to set direction %i at GPIO #%i", mode, gpio_num); switch(mode) { case GPIO_MODE_INPUT: ESP_RETURN_ON_FALSE(signal_in_idx != SIG_GPIO_OUT_IDX, ESP_ERR_NOT_SUPPORTED, TAG, "requested periph signal cannot be connect via GPIO Matrix"); ESP_RETURN_ON_FALSE(esp_gpio_is_reserved(BIT64(gpio_num)) == false, ESP_ERR_INVALID_STATE, TAG, "GPIO %i is reserved", gpio_num); + gpio_input_enable(gpio_num); esp_rom_gpio_connect_in_signal(gpio_num, signal_in_idx, false); break; case GPIO_MODE_OUTPUT: @@ -55,6 +55,7 @@ static esp_err_t emac_esp_gpio_matrix_init(gpio_num_t gpio_num, uint32_t signal_ TAG, "requested periph signal cannot be connect via GPIO Matrix"); ESP_RETURN_ON_FALSE((esp_gpio_reserve(BIT64(gpio_num)) & BIT64(gpio_num)) == 0, ESP_ERR_INVALID_STATE, TAG, "GPIO %i is already reserved", gpio_num); + gpio_input_enable(gpio_num); esp_rom_gpio_connect_out_signal(gpio_num, signal_out_idx, false, false); esp_rom_gpio_connect_in_signal(gpio_num, signal_in_idx, false); break; @@ -67,7 +68,7 @@ static esp_err_t emac_esp_gpio_matrix_init(gpio_num_t gpio_num, uint32_t signal_ return ESP_OK; } -static esp_err_t emac_esp_iomux_init(gpio_num_t gpio_num, const emac_iomux_info_t *iomux_info, bool is_input) +static esp_err_t emac_esp_iomux_init(gpio_num_t gpio_num, const emac_iomux_info_t *iomux_info, uint32_t signal_idx, bool is_input) { // silently skip undefined iomux functions (for example, ESP32 does not use MII COL_IN/CRS_IN) if (iomux_info == NULL) { @@ -81,16 +82,23 @@ static esp_err_t emac_esp_iomux_init(gpio_num_t gpio_num, const emac_iomux_info_ } // loop over target iomux_info until reached end of list indicated by invalid GPIO num while (iomux_info->gpio_num != GPIO_NUM_MAX) { - // if requested GPIO number can be IO muxed or select single pad that can be muxed on the target + // if requested GPIO number can be IO muxed or select the only pad that can be muxed on the target if(gpio_num == iomux_info->gpio_num || gpio_num == GPIO_NUM_MAX) { ESP_RETURN_ON_FALSE((esp_gpio_reserve(BIT64(iomux_info->gpio_num)) & BIT64(iomux_info->gpio_num)) == 0, ESP_ERR_INVALID_STATE, TAG, "GPIO %i is already reserved", iomux_info->gpio_num); s_emac_esp_used_gpio_mask |= BIT64(iomux_info->gpio_num); - ESP_RETURN_ON_ERROR(gpio_func_sel(iomux_info->gpio_num, iomux_info->func), TAG, "failed to set GPIO function at GPIO %i", iomux_info->gpio_num); if (is_input) { - PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[iomux_info->gpio_num]); + ESP_RETURN_ON_ERROR(gpio_func_sel(iomux_info->gpio_num, iomux_info->func), TAG, "failed to set GPIO function at GPIO %i", iomux_info->gpio_num); + // if the signal can be also connected via IO matrix, disconnect it (SIG_GPIO_OUT_IDX indicates no IO matrix) + if (signal_idx != SIG_GPIO_OUT_IDX) { + // enable input and disconnect from IO Matrix + gpio_iomux_in(iomux_info->gpio_num, signal_idx); + } else { + // just enable input + gpio_input_enable(iomux_info->gpio_num); + } } else { - PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[iomux_info->gpio_num]); + gpio_iomux_out(iomux_info->gpio_num, iomux_info->func, false); } ESP_RETURN_ON_ERROR(gpio_set_pull_mode(iomux_info->gpio_num, GPIO_FLOATING), TAG, "failed to set pull mode at GPIO %i", iomux_info->gpio_num); @@ -158,34 +166,34 @@ esp_err_t emac_esp_iomux_init_mii(const eth_mac_mii_gpio_config_t *mii_gpio) { ESP_RETURN_ON_FALSE(emac_mii_iomux_pins.clk_tx != NULL, ESP_ERR_NOT_SUPPORTED, TAG, "target does not support MII IOMUX"); - ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(mii_gpio, tx_clk_num), emac_mii_iomux_pins.clk_tx, true), - TAG, "invalid TX_CLK GPIO number"); - ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(mii_gpio, tx_en_num), emac_mii_iomux_pins.tx_en, false), - TAG, "invalid TX_EN GPIO number"); - ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(mii_gpio, txd0_num), emac_mii_iomux_pins.txd0, false), - TAG, "invalid TXD0 GPIO number"); - ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(mii_gpio, txd1_num), emac_mii_iomux_pins.txd1, false), - TAG, "invalid TXD1 GPIO number"); - ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(mii_gpio, txd2_num), emac_mii_iomux_pins.txd2, false), - TAG, "invalid TXD2 GPIO number"); - ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(mii_gpio, txd3_num), emac_mii_iomux_pins.txd3, false), - TAG, "invalid TXD3 GPIO number"); - ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(mii_gpio, rx_clk_num), emac_mii_iomux_pins.clk_rx, true), - TAG, "invalid RX_CLK GPIO number"); - ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(mii_gpio, rx_dv_num), emac_mii_iomux_pins.rx_dv, true), - TAG, "invalid RX_DV GPIO number"); - ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(mii_gpio, rxd0_num), emac_mii_iomux_pins.rxd0, true), - TAG, "invalid RXD0 GPIO number"); - ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(mii_gpio, rxd1_num), emac_mii_iomux_pins.rxd1, true), - TAG, "invalid RXD1 GPIO number"); - ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(mii_gpio, rxd2_num), emac_mii_iomux_pins.rxd2, true), - TAG, "invalid RXD2 GPIO number"); - ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(mii_gpio, rxd3_num), emac_mii_iomux_pins.rxd3, true), - TAG, "invalid RXD3 GPIO number"); - ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(mii_gpio, col_in_num), emac_mii_iomux_pins.col_in, true), - TAG, "invalid COL_IN GPIO number"); - ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(mii_gpio, crs_in_num), emac_mii_iomux_pins.crs_in, true), - TAG, "invalid CRS_IN GPIO number"); + ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(mii_gpio, tx_clk_num), emac_mii_iomux_pins.clk_tx, + emac_io_idx.mii_tx_clk_i_idx, true), TAG, "invalid TX_CLK GPIO number"); + ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(mii_gpio, tx_en_num), emac_mii_iomux_pins.tx_en, + emac_io_idx.mii_tx_en_o_idx, false), TAG, "invalid TX_EN GPIO number"); + ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(mii_gpio, txd0_num), emac_mii_iomux_pins.txd0, + emac_io_idx.mii_txd0_o_idx, false), TAG, "invalid TXD0 GPIO number"); + ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(mii_gpio, txd1_num), emac_mii_iomux_pins.txd1, + emac_io_idx.mii_txd1_o_idx, false), TAG, "invalid TXD1 GPIO number"); + ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(mii_gpio, txd2_num), emac_mii_iomux_pins.txd2, + emac_io_idx.mii_txd2_o_idx, false), TAG, "invalid TXD2 GPIO number"); + ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(mii_gpio, txd3_num), emac_mii_iomux_pins.txd3, + emac_io_idx.mii_txd3_o_idx, false), TAG, "invalid TXD3 GPIO number"); + ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(mii_gpio, rx_clk_num), emac_mii_iomux_pins.clk_rx, + emac_io_idx.mii_rx_clk_i_idx, true), TAG, "invalid RX_CLK GPIO number"); + ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(mii_gpio, rx_dv_num), emac_mii_iomux_pins.rx_dv, + emac_io_idx.mii_rx_dv_i_idx, true), TAG, "invalid RX_DV GPIO number"); + ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(mii_gpio, rxd0_num), emac_mii_iomux_pins.rxd0, + emac_io_idx.mii_rxd0_i_idx, true), TAG, "invalid RXD0 GPIO number"); + ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(mii_gpio, rxd1_num), emac_mii_iomux_pins.rxd1, + emac_io_idx.mii_rxd1_i_idx, true), TAG, "invalid RXD1 GPIO number"); + ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(mii_gpio, rxd2_num), emac_mii_iomux_pins.rxd2, + emac_io_idx.mii_rxd2_i_idx, true), TAG, "invalid RXD2 GPIO number"); + ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(mii_gpio, rxd3_num), emac_mii_iomux_pins.rxd3, + emac_io_idx.mii_rxd3_i_idx, true), TAG, "invalid RXD3 GPIO number"); + ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(mii_gpio, col_in_num), emac_mii_iomux_pins.col_in, + emac_io_idx.mii_col_i_idx, true), TAG, "invalid COL_IN GPIO number"); + ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(mii_gpio, crs_in_num), emac_mii_iomux_pins.crs_in, + emac_io_idx.mii_crs_i_idx, true), TAG, "invalid CRS_IN GPIO number"); return ESP_OK; } @@ -193,7 +201,8 @@ esp_err_t emac_esp_iomux_rmii_clk_input(int num) { ESP_RETURN_ON_FALSE(emac_rmii_iomux_pins.clki != NULL, ESP_ERR_NOT_SUPPORTED, TAG, "target does not support RMII CLKI IOMUX"); - ESP_RETURN_ON_ERROR(emac_esp_iomux_init(num, emac_rmii_iomux_pins.clki, true), TAG, "invalid RMII CLK input GPIO number"); + ESP_RETURN_ON_ERROR(emac_esp_iomux_init(num, emac_rmii_iomux_pins.clki, emac_io_idx.rmii_refclk_i_idx, true), + TAG, "invalid RMII CLK input GPIO number"); return ESP_OK; } @@ -201,7 +210,8 @@ esp_err_t emac_esp_iomux_rmii_clk_ouput(int num) { ESP_RETURN_ON_FALSE(emac_rmii_iomux_pins.clko != NULL, ESP_ERR_NOT_SUPPORTED, TAG, "target does not support RMII CLKO IOMUX"); - ESP_RETURN_ON_ERROR(emac_esp_iomux_init(num, emac_rmii_iomux_pins.clko, false), TAG, "invalid RMII CLK output GPIO number"); + ESP_RETURN_ON_ERROR(emac_esp_iomux_init(num, emac_rmii_iomux_pins.clko, emac_io_idx.rmii_refclk_o_idx, false), + TAG, "invalid RMII CLK output GPIO number"); return ESP_OK; } @@ -209,18 +219,18 @@ esp_err_t emac_esp_iomux_init_rmii(const eth_mac_rmii_gpio_config_t *rmii_gpio) { ESP_RETURN_ON_FALSE(emac_rmii_iomux_pins.clki != NULL, ESP_ERR_NOT_SUPPORTED, TAG, "target does not support RMII IOMUX"); - ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(rmii_gpio, tx_en_num), emac_rmii_iomux_pins.tx_en, false), - TAG, "invalid TX_EN GPIO number"); - ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(rmii_gpio, txd0_num), emac_rmii_iomux_pins.txd0, false), - TAG, "invalid TXD0 GPIO number"); - ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(rmii_gpio, txd1_num), emac_rmii_iomux_pins.txd1, false), - TAG, "invalid TXD1 GPIO number"); - ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(rmii_gpio, crs_dv_num), emac_rmii_iomux_pins.crs_dv, true), - TAG,"invalid CRS_DV GPIO number"); - ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(rmii_gpio, rxd0_num), emac_rmii_iomux_pins.rxd0, true), - TAG,"invalid RXD0 GPIO number"); - ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(rmii_gpio, rxd1_num), emac_rmii_iomux_pins.rxd1, true), - TAG,"invalid RXD1 GPIO number"); + ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(rmii_gpio, tx_en_num), emac_rmii_iomux_pins.tx_en, + emac_io_idx.mii_tx_en_o_idx, false), TAG, "invalid TX_EN GPIO number"); + ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(rmii_gpio, txd0_num), emac_rmii_iomux_pins.txd0, + emac_io_idx.mii_txd0_o_idx, false), TAG, "invalid TXD0 GPIO number"); + ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(rmii_gpio, txd1_num), emac_rmii_iomux_pins.txd1, + emac_io_idx.mii_txd1_o_idx, false), TAG, "invalid TXD1 GPIO number"); + ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(rmii_gpio, crs_dv_num), emac_rmii_iomux_pins.crs_dv, + emac_io_idx.mii_crs_i_idx, true), TAG,"invalid CRS_DV GPIO number"); + ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(rmii_gpio, rxd0_num), emac_rmii_iomux_pins.rxd0, + emac_io_idx.mii_rxd0_i_idx, true), TAG,"invalid RXD0 GPIO number"); + ESP_RETURN_ON_ERROR(emac_esp_iomux_init(GET_GPIO_OR_SINGLE(rmii_gpio, rxd1_num), emac_rmii_iomux_pins.rxd1, + emac_io_idx.mii_rxd1_i_idx, true), TAG,"invalid RXD1 GPIO number"); return ESP_OK; } @@ -229,7 +239,8 @@ esp_err_t emac_esp_iomux_rmii_init_tx_er(int num) { ESP_RETURN_ON_FALSE(emac_rmii_iomux_pins.tx_er != NULL, ESP_ERR_NOT_SUPPORTED, TAG, "target does not support RMII TX_ER IOMUX"); - ESP_RETURN_ON_ERROR(emac_esp_iomux_init(num, emac_rmii_iomux_pins.tx_er, false), TAG, "invalid TX_ER GPIO number"); + ESP_RETURN_ON_ERROR(emac_esp_iomux_init(num, emac_rmii_iomux_pins.tx_er, emac_io_idx.mii_tx_er_o_idx, false), + TAG, "invalid TX_ER GPIO number"); return ESP_OK; } @@ -237,7 +248,8 @@ esp_err_t emac_esp_iomux_rmii_init_rx_er(int num) { ESP_RETURN_ON_FALSE(emac_rmii_iomux_pins.rx_er != NULL, ESP_ERR_NOT_SUPPORTED, TAG, "target does not support RMII RX_ER IOMUX"); - ESP_RETURN_ON_ERROR(emac_esp_iomux_init(num, emac_rmii_iomux_pins.rx_er, true), TAG, "invalid RX_ER GPIO number"); + ESP_RETURN_ON_ERROR(emac_esp_iomux_init(num, emac_rmii_iomux_pins.rx_er, emac_io_idx.mii_rx_er_i_idx, true), + TAG, "invalid RX_ER GPIO number"); return ESP_OK; } @@ -245,7 +257,8 @@ esp_err_t emac_esp_iomux_mii_init_tx_er(int num) { ESP_RETURN_ON_FALSE(emac_mii_iomux_pins.tx_er != NULL, ESP_ERR_NOT_SUPPORTED, TAG, "target does not support MII TX_ER IOMUX"); - ESP_RETURN_ON_ERROR(emac_esp_iomux_init(num, emac_mii_iomux_pins.tx_er, false), TAG, "invalid TX_ER GPIO number"); + ESP_RETURN_ON_ERROR(emac_esp_iomux_init(num, emac_mii_iomux_pins.tx_er, emac_io_idx.mii_tx_er_o_idx, false), + TAG, "invalid TX_ER GPIO number"); return ESP_OK; } @@ -253,7 +266,8 @@ esp_err_t emac_esp_iomux_mii_init_rx_er(int num) { ESP_RETURN_ON_FALSE(emac_mii_iomux_pins.rx_er != NULL, ESP_ERR_NOT_SUPPORTED, TAG, "target does not support RMII RX_ER IOMUX"); - ESP_RETURN_ON_ERROR(emac_esp_iomux_init(num, emac_mii_iomux_pins.rx_er, true), TAG, "invalid RX_ER GPIO number"); + ESP_RETURN_ON_ERROR(emac_esp_iomux_init(num, emac_mii_iomux_pins.rx_er, emac_io_idx.mii_rx_er_i_idx, true), + TAG, "invalid RX_ER GPIO number"); return ESP_OK; } diff --git a/components/esp_eth/src/phy/esp_eth_phy_802_3.c b/components/esp_eth/src/phy/esp_eth_phy_802_3.c index b0c22cb53f46..49a2b55a617e 100644 --- a/components/esp_eth/src/phy/esp_eth_phy_802_3.c +++ b/components/esp_eth/src/phy/esp_eth_phy_802_3.c @@ -9,10 +9,11 @@ #include "esp_log.h" #include "esp_check.h" #include "esp_eth.h" +#include "esp_private/gpio.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "driver/gpio.h" -#include "esp_rom_gpio.h" +#include "soc/io_mux_reg.h" #include "esp_rom_sys.h" #include "esp_eth_phy_802_3.h" @@ -440,9 +441,9 @@ esp_err_t esp_eth_phy_802_3_del(phy_802_3_t *phy_802_3) esp_err_t esp_eth_phy_802_3_reset_hw(phy_802_3_t *phy_802_3, uint32_t reset_assert_us) { if (phy_802_3->reset_gpio_num >= 0) { - esp_rom_gpio_pad_select_gpio(phy_802_3->reset_gpio_num); - gpio_set_direction(phy_802_3->reset_gpio_num, GPIO_MODE_OUTPUT); + gpio_func_sel(phy_802_3->reset_gpio_num, PIN_FUNC_GPIO); gpio_set_level(phy_802_3->reset_gpio_num, 0); + gpio_output_enable(phy_802_3->reset_gpio_num); if (reset_assert_us < 10000) { esp_rom_delay_us(reset_assert_us); } else { diff --git a/components/esp_eth/src/spi/dm9051/esp_eth_mac_dm9051.c b/components/esp_eth/src/spi/dm9051/esp_eth_mac_dm9051.c index b19c031ef606..bf421d63800a 100644 --- a/components/esp_eth/src/spi/dm9051/esp_eth_mac_dm9051.c +++ b/components/esp_eth/src/spi/dm9051/esp_eth_mac_dm9051.c @@ -10,6 +10,8 @@ #include #include "esp_eth_mac_spi.h" #include "driver/gpio.h" +#include "esp_private/gpio.h" +#include "soc/io_mux_reg.h" #include "driver/spi_master.h" #include "esp_attr.h" #include "esp_log.h" @@ -23,7 +25,6 @@ #include "freertos/semphr.h" #include "dm9051.h" #include "sdkconfig.h" -#include "esp_rom_gpio.h" #include "esp_rom_sys.h" #include "esp_cpu.h" #include "esp_timer.h" @@ -784,9 +785,9 @@ static esp_err_t emac_dm9051_init(esp_eth_mac_t *mac) emac_dm9051_t *emac = __containerof(mac, emac_dm9051_t, parent); esp_eth_mediator_t *eth = emac->eth; if (emac->int_gpio_num >= 0) { - esp_rom_gpio_pad_select_gpio(emac->int_gpio_num); - gpio_set_direction(emac->int_gpio_num, GPIO_MODE_INPUT); - gpio_set_pull_mode(emac->int_gpio_num, GPIO_PULLDOWN_ONLY); + gpio_func_sel(emac->int_gpio_num, PIN_FUNC_GPIO); + gpio_input_enable(emac->int_gpio_num); + gpio_pulldown_en(emac->int_gpio_num); gpio_set_intr_type(emac->int_gpio_num, GPIO_INTR_POSEDGE); gpio_intr_enable(emac->int_gpio_num); gpio_isr_handler_add(emac->int_gpio_num, dm9051_isr_handler, emac); @@ -806,7 +807,6 @@ static esp_err_t emac_dm9051_init(esp_eth_mac_t *mac) err: if (emac->int_gpio_num >= 0) { gpio_isr_handler_remove(emac->int_gpio_num); - gpio_reset_pin(emac->int_gpio_num); } eth->on_state_changed(eth, ETH_STATE_DEINIT, NULL); return ret; @@ -819,7 +819,6 @@ static esp_err_t emac_dm9051_deinit(esp_eth_mac_t *mac) mac->stop(mac); if (emac->int_gpio_num >= 0) { gpio_isr_handler_remove(emac->int_gpio_num); - gpio_reset_pin(emac->int_gpio_num); } if (emac->poll_timer && esp_timer_is_active(emac->poll_timer)) { esp_timer_stop(emac->poll_timer); diff --git a/components/esp_eth/src/spi/ksz8851snl/esp_eth_mac_ksz8851snl.c b/components/esp_eth/src/spi/ksz8851snl/esp_eth_mac_ksz8851snl.c index ae0b60f88186..556c4208f6a5 100644 --- a/components/esp_eth/src/spi/ksz8851snl/esp_eth_mac_ksz8851snl.c +++ b/components/esp_eth/src/spi/ksz8851snl/esp_eth_mac_ksz8851snl.c @@ -13,7 +13,8 @@ #include "esp_check.h" #include "esp_cpu.h" #include "driver/gpio.h" -#include "esp_rom_gpio.h" +#include "esp_private/gpio.h" +#include "soc/io_mux_reg.h" #include "driver/spi_master.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" @@ -328,9 +329,9 @@ static esp_err_t emac_ksz8851_init(esp_eth_mac_t *mac) emac_ksz8851snl_t *emac = __containerof(mac, emac_ksz8851snl_t, parent); esp_eth_mediator_t *eth = emac->eth; if (emac->int_gpio_num >= 0) { - esp_rom_gpio_pad_select_gpio(emac->int_gpio_num); - gpio_set_direction(emac->int_gpio_num, GPIO_MODE_INPUT); - gpio_set_pull_mode(emac->int_gpio_num, GPIO_PULLUP_ONLY); + gpio_func_sel(emac->int_gpio_num, PIN_FUNC_GPIO); + gpio_input_enable(emac->int_gpio_num); + gpio_pullup_en(emac->int_gpio_num); gpio_set_intr_type(emac->int_gpio_num, GPIO_INTR_NEGEDGE); // NOTE(v.chistyakov): active low gpio_intr_enable(emac->int_gpio_num); gpio_isr_handler_add(emac->int_gpio_num, ksz8851_isr_handler, emac); @@ -352,7 +353,6 @@ static esp_err_t emac_ksz8851_init(esp_eth_mac_t *mac) ESP_LOGD(TAG, "MAC initialization failed"); if (emac->int_gpio_num >= 0) { gpio_isr_handler_remove(emac->int_gpio_num); - gpio_reset_pin(emac->int_gpio_num); } eth->on_state_changed(eth, ETH_STATE_DEINIT, NULL); return ret; @@ -365,7 +365,6 @@ static esp_err_t emac_ksz8851_deinit(esp_eth_mac_t *mac) mac->stop(mac); if (emac->int_gpio_num >= 0) { gpio_isr_handler_remove(emac->int_gpio_num); - gpio_reset_pin(emac->int_gpio_num); } if (emac->poll_timer && esp_timer_is_active(emac->poll_timer)) { esp_timer_stop(emac->poll_timer); diff --git a/components/esp_eth/src/spi/ksz8851snl/esp_eth_phy_ksz8851snl.c b/components/esp_eth/src/spi/ksz8851snl/esp_eth_phy_ksz8851snl.c index cbec083a0cc4..fa4ec04e3168 100644 --- a/components/esp_eth/src/spi/ksz8851snl/esp_eth_phy_ksz8851snl.c +++ b/components/esp_eth/src/spi/ksz8851snl/esp_eth_phy_ksz8851snl.c @@ -11,7 +11,8 @@ #include "esp_heap_caps.h" #include "esp_log.h" #include "driver/gpio.h" -#include "esp_rom_gpio.h" +#include "esp_private/gpio.h" +#include "soc/io_mux_reg.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "ksz8851.h" @@ -100,9 +101,9 @@ static esp_err_t phy_ksz8851_reset_hw(esp_eth_phy_t *phy) // NOTE(v.chistyakov): set reset_gpio_num to a negative value can skip hardware reset phy chip if (ksz8851->reset_gpio_num >= 0) { ESP_LOGD(TAG, "hard reset"); - esp_rom_gpio_pad_select_gpio(ksz8851->reset_gpio_num); - gpio_set_direction(ksz8851->reset_gpio_num, GPIO_MODE_OUTPUT); + gpio_func_sel(ksz8851->reset_gpio_num, PIN_FUNC_GPIO); gpio_set_level(ksz8851->reset_gpio_num, 0); + gpio_output_enable(ksz8851->reset_gpio_num); esp_rom_delay_us(ksz8851->reset_timeout_ms * 1000); gpio_set_level(ksz8851->reset_gpio_num, 1); } diff --git a/components/esp_eth/src/spi/w5500/esp_eth_mac_w5500.c b/components/esp_eth/src/spi/w5500/esp_eth_mac_w5500.c index 2f0ea028fe7e..a5ab63db8092 100644 --- a/components/esp_eth/src/spi/w5500/esp_eth_mac_w5500.c +++ b/components/esp_eth/src/spi/w5500/esp_eth_mac_w5500.c @@ -9,6 +9,8 @@ #include #include "esp_eth_mac_spi.h" #include "driver/gpio.h" +#include "esp_private/gpio.h" +#include "soc/io_mux_reg.h" #include "driver/spi_master.h" #include "esp_attr.h" #include "esp_log.h" @@ -16,7 +18,6 @@ #include "esp_system.h" #include "esp_intr_alloc.h" #include "esp_heap_caps.h" -#include "esp_rom_gpio.h" #include "esp_cpu.h" #include "esp_timer.h" #include "freertos/FreeRTOS.h" @@ -812,9 +813,9 @@ static esp_err_t emac_w5500_init(esp_eth_mac_t *mac) emac_w5500_t *emac = __containerof(mac, emac_w5500_t, parent); esp_eth_mediator_t *eth = emac->eth; if (emac->int_gpio_num >= 0) { - esp_rom_gpio_pad_select_gpio(emac->int_gpio_num); - gpio_set_direction(emac->int_gpio_num, GPIO_MODE_INPUT); - gpio_set_pull_mode(emac->int_gpio_num, GPIO_PULLUP_ONLY); + gpio_func_sel(emac->int_gpio_num, PIN_FUNC_GPIO); + gpio_input_enable(emac->int_gpio_num); + gpio_pullup_en(emac->int_gpio_num); gpio_set_intr_type(emac->int_gpio_num, GPIO_INTR_NEGEDGE); // active low gpio_intr_enable(emac->int_gpio_num); gpio_isr_handler_add(emac->int_gpio_num, w5500_isr_handler, emac); diff --git a/components/esp_eth/src/spi/w5500/esp_eth_phy_w5500.c b/components/esp_eth/src/spi/w5500/esp_eth_phy_w5500.c index 834cf54088fc..0acad7c7473d 100644 --- a/components/esp_eth/src/spi/w5500/esp_eth_phy_w5500.c +++ b/components/esp_eth/src/spi/w5500/esp_eth_phy_w5500.c @@ -12,7 +12,8 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "driver/gpio.h" -#include "esp_rom_gpio.h" +#include "esp_private/gpio.h" +#include "soc/io_mux_reg.h" #include "esp_rom_sys.h" #include "w5500.h" @@ -153,9 +154,9 @@ static esp_err_t w5500_reset_hw(esp_eth_phy_t *phy) phy_w5500_t *w5500 = __containerof(phy, phy_w5500_t, parent); // set reset_gpio_num to a negative value can skip hardware reset phy chip if (w5500->reset_gpio_num >= 0) { - esp_rom_gpio_pad_select_gpio(w5500->reset_gpio_num); - gpio_set_direction(w5500->reset_gpio_num, GPIO_MODE_OUTPUT); + gpio_func_sel(w5500->reset_gpio_num, PIN_FUNC_GPIO); gpio_set_level(w5500->reset_gpio_num, 0); + gpio_output_enable(w5500->reset_gpio_num); esp_rom_delay_us(100); // insert min input assert time gpio_set_level(w5500->reset_gpio_num, 1); } diff --git a/components/esp_eth/test_apps/.build-test-rules.yml b/components/esp_eth/test_apps/.build-test-rules.yml index 5499c2b035a1..dc4d00c17b3e 100644 --- a/components/esp_eth/test_apps/.build-test-rules.yml +++ b/components/esp_eth/test_apps/.build-test-rules.yml @@ -2,7 +2,7 @@ components/esp_eth/test_apps: enable: - - if: IDF_TARGET == "esp32" - reason: only test on esp32 + - if: IDF_TARGET in ["esp32", "esp32p4"] + reason: ESP32 and ESP32P4 have internal EMAC. SPI Ethernet runners are based on ESP32. depends_components: - esp_eth diff --git a/components/esp_eth/test_apps/README.md b/components/esp_eth/test_apps/README.md index 0e2cf8cb135a..9747c000db1c 100644 --- a/components/esp_eth/test_apps/README.md +++ b/components/esp_eth/test_apps/README.md @@ -1,6 +1,6 @@ # EMAC Test -| Supported Targets | ESP32 | -| ----------------- | ----- | +| Supported Targets | ESP32 | ESP32-P4 | +| ----------------- | ----- | -------- | This test app is used to test Ethernet MAC behavior with different chips. diff --git a/components/esp_eth/test_apps/pytest_esp_eth.py b/components/esp_eth/test_apps/pytest_esp_eth.py index 3e954ed2c790..07b45872ef02 100644 --- a/components/esp_eth/test_apps/pytest_esp_eth.py +++ b/components/esp_eth/test_apps/pytest_esp_eth.py @@ -265,6 +265,29 @@ def test_esp_eth_ip101(dut: IdfDut) -> None: ethernet_l2_test(dut) +# ----------- IP101 ESP32P4 ----------- +@pytest.mark.esp32p4 +@pytest.mark.eth_ip101 +@pytest.mark.parametrize('config', [ + 'default_ip101_esp32p4', +], indirect=True) +def test_esp32p4_ethernet(dut: IdfDut) -> None: + ethernet_test(dut) + dut.serial.hard_reset() + ethernet_l2_test(dut) + + +@pytest.mark.esp32p4 +@pytest.mark.eth_ip101 +@pytest.mark.parametrize('config', [ + 'default_ip101_esp32p4', +], indirect=True) +def test_esp32p4_emac(dut: IdfDut) -> None: + ethernet_int_emac_test(dut) + dut.serial.hard_reset() + ethernet_heap_alloc_test(dut) + + # ----------- LAN8720 ----------- @pytest.mark.esp32 @pytest.mark.eth_lan8720 diff --git a/components/esp_eth/test_apps/sdkconfig.ci.default_ip101_esp32p4 b/components/esp_eth/test_apps/sdkconfig.ci.default_ip101_esp32p4 index 7a385264d3a1..a73773ba2549 100644 --- a/components/esp_eth/test_apps/sdkconfig.ci.default_ip101_esp32p4 +++ b/components/esp_eth/test_apps/sdkconfig.ci.default_ip101_esp32p4 @@ -8,6 +8,4 @@ CONFIG_ESP_TASK_WDT_EN=n CONFIG_TARGET_USE_INTERNAL_ETHERNET=y CONFIG_TARGET_ETH_PHY_DEVICE_IP101=y -CONFIG_TARGET_USE_DEFAULT_EMAC_CONFIG=n -CONFIG_TARGET_IO_MDC=31 -CONFIG_TARGET_IO_MDIO=27 +CONFIG_TARGET_USE_DEFAULT_EMAC_CONFIG=y diff --git a/components/esp_http_client/esp_http_client.c b/components/esp_http_client/esp_http_client.c index ef581df9fb4d..9ed66e02bef5 100644 --- a/components/esp_http_client/esp_http_client.c +++ b/components/esp_http_client/esp_http_client.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 */ @@ -15,6 +15,7 @@ #include "http_header.h" #include "esp_transport.h" #include "esp_transport_tcp.h" +#include "esp_transport_ssl.h" #include "http_utils.h" #include "http_auth.h" #include "sdkconfig.h" @@ -255,7 +256,7 @@ static int http_on_header_field(http_parser *parser, const char *at, size_t leng { esp_http_client_t *client = parser->data; http_on_header_event(client); - ESP_RETURN_ON_FALSE_DEBUG(http_utils_append_string(&client->current_header_key, at, length), -1, TAG, "Failed to append string"); + HTTP_RET_ON_FALSE_DBG(http_utils_append_string(&client->current_header_key, at, length), -1, TAG, "Failed to append string"); return 0; } @@ -267,14 +268,14 @@ static int http_on_header_value(http_parser *parser, const char *at, size_t leng return 0; } if (strcasecmp(client->current_header_key, "Location") == 0) { - ESP_RETURN_ON_FALSE_DEBUG(http_utils_append_string(&client->location, at, length), -1, TAG, "Failed to append string"); + HTTP_RET_ON_FALSE_DBG(http_utils_append_string(&client->location, at, length), -1, TAG, "Failed to append string"); } else if (strcasecmp(client->current_header_key, "Transfer-Encoding") == 0 && memcmp(at, "chunked", length) == 0) { client->response->is_chunked = true; } else if (strcasecmp(client->current_header_key, "WWW-Authenticate") == 0) { - ESP_RETURN_ON_FALSE_DEBUG(http_utils_append_string(&client->auth_header, at, length), -1, TAG, "Failed to append string"); + HTTP_RET_ON_FALSE_DBG(http_utils_append_string(&client->auth_header, at, length), -1, TAG, "Failed to append string"); } - ESP_RETURN_ON_FALSE_DEBUG(http_utils_append_string(&client->current_header_value, at, length), -1, TAG, "Failed to append string"); + HTTP_RET_ON_FALSE_DBG(http_utils_append_string(&client->current_header_value, at, length), -1, TAG, "Failed to append string"); return 0; } @@ -554,12 +555,12 @@ static esp_err_t _set_config(esp_http_client_handle_t client, const esp_http_cli } if (config->transport_type == HTTP_TRANSPORT_OVER_SSL) { - ESP_GOTO_ON_FALSE_DEBUG(http_utils_assign_string(&client->connection_info.scheme, "https", -1), ESP_ERR_NO_MEM, error, TAG, "failed to assign string"); + HTTP_GOTO_ON_FALSE_DBG(http_utils_assign_string(&client->connection_info.scheme, "https", -1), ESP_ERR_NO_MEM, error, TAG, "failed to assign string"); if (client->connection_info.port == 0) { client->connection_info.port = DEFAULT_HTTPS_PORT; } } else { - ESP_GOTO_ON_FALSE_DEBUG(http_utils_assign_string(&client->connection_info.scheme, "http", -1), ESP_ERR_NO_MEM, error, TAG, "failed to assign string"); + HTTP_GOTO_ON_FALSE_DBG(http_utils_assign_string(&client->connection_info.scheme, "http", -1), ESP_ERR_NO_MEM, error, TAG, "failed to assign string"); if (client->connection_info.port == 0) { client->connection_info.port = DEFAULT_HTTP_PORT; } @@ -639,11 +640,11 @@ static esp_err_t esp_http_client_prepare_digest_auth(esp_http_client_handle_t cl // Freeing the allocated memory for auth_data->uri and setting it to NULL to prevent potential memory leaks free(client->auth_data->uri); client->auth_data->uri = NULL; - ESP_GOTO_ON_FALSE_DEBUG(http_utils_assign_string(&client->auth_data->uri, client->connection_info.path, -1), ESP_ERR_NO_MEM, error, TAG, "failed to assign string"); + HTTP_GOTO_ON_FALSE_DBG(http_utils_assign_string(&client->auth_data->uri, client->connection_info.path, -1), ESP_ERR_NO_MEM, error, TAG, "failed to assign string"); if (client->connection_info.query) { - ESP_GOTO_ON_FALSE_DEBUG(http_utils_append_string(&client->auth_data->uri, "?", -1), ESP_ERR_NO_MEM, error, TAG, "Failed to append string"); - ESP_GOTO_ON_FALSE_DEBUG(http_utils_append_string(&client->auth_data->uri, client->connection_info.query, -1), ESP_ERR_NO_MEM, error, TAG, "Failed to append string"); + HTTP_GOTO_ON_FALSE_DBG(http_utils_append_string(&client->auth_data->uri, "?", -1), ESP_ERR_NO_MEM, error, TAG, "Failed to append string"); + HTTP_GOTO_ON_FALSE_DBG(http_utils_append_string(&client->auth_data->uri, client->connection_info.query, -1), ESP_ERR_NO_MEM, error, TAG, "Failed to append string"); } client->auth_data->cnonce = ((uint64_t)esp_random() << 32) + esp_random(); @@ -739,10 +740,26 @@ static bool init_common_tcp_transport(esp_http_client_handle_t client, const esp return true; } +static esp_err_t http_convert_addr_family_to_tls(esp_http_client_addr_type_t http_addr_family, esp_tls_addr_family_t *tls_addr_family) +{ + esp_err_t ret = ESP_OK; + if (http_addr_family == HTTP_ADDR_TYPE_UNSPEC) { + *tls_addr_family = ESP_TLS_AF_UNSPEC; + } else if (http_addr_family == HTTP_ADDR_TYPE_INET) { + *tls_addr_family = ESP_TLS_AF_INET; + } else if (http_addr_family == HTTP_ADDR_TYPE_INET6) { + *tls_addr_family = ESP_TLS_AF_INET6; + } else { + ret = ESP_ERR_INVALID_ARG; + } + return ret; +} + esp_http_client_handle_t esp_http_client_init(const esp_http_client_config_t *config) { esp_http_client_handle_t client; + esp_tls_addr_family_t addr_family = ESP_TLS_AF_UNSPEC; esp_err_t ret = ESP_OK; esp_transport_handle_t tcp = NULL; char *host_name; @@ -776,6 +793,8 @@ esp_http_client_handle_t esp_http_client_init(const esp_http_client_config_t *co ESP_LOGE(TAG, "Error initialize transport"); goto error; } + ESP_GOTO_ON_ERROR(http_convert_addr_family_to_tls(config->addr_type, &addr_family), error, TAG, "Failed to convert addr type %d", config->addr_type); + esp_transport_ssl_set_addr_family(tcp, addr_family); ESP_GOTO_ON_FALSE(init_common_tcp_transport(client, config, tcp), ESP_FAIL, error, TAG, "Failed to set TCP config"); @@ -791,6 +810,7 @@ esp_http_client_handle_t esp_http_client_init(const esp_http_client_config_t *co ESP_LOGE(TAG, "Error initialize SSL Transport"); goto error; } + esp_transport_ssl_set_addr_family(ssl, addr_family); ESP_GOTO_ON_FALSE(init_common_tcp_transport(client, config, ssl), ESP_FAIL, error, TAG, "Failed to set SSL config"); @@ -1101,7 +1121,7 @@ esp_err_t esp_http_client_set_url(esp_http_client_handle_t client, const char *u old_port = client->connection_info.port; if (purl.field_data[UF_HOST].len) { - ESP_GOTO_ON_FALSE_DEBUG(http_utils_assign_string(&client->connection_info.host, url + purl.field_data[UF_HOST].off, purl.field_data[UF_HOST].len), ESP_ERR_NO_MEM, error, TAG, "failed to assign string"); + HTTP_GOTO_ON_FALSE_DBG(http_utils_assign_string(&client->connection_info.host, url + purl.field_data[UF_HOST].off, purl.field_data[UF_HOST].len), ESP_ERR_NO_MEM, error, TAG, "failed to assign string"); } // Close the connection if host was changed if (old_host && client->connection_info.host @@ -1122,7 +1142,7 @@ esp_err_t esp_http_client_set_url(esp_http_client_handle_t client, const char *u } if (purl.field_data[UF_SCHEMA].len) { - ESP_GOTO_ON_FALSE_DEBUG(http_utils_assign_string(&client->connection_info.scheme, url + purl.field_data[UF_SCHEMA].off, purl.field_data[UF_SCHEMA].len), ESP_ERR_NO_MEM, error, TAG, "failed to assign string"); + HTTP_GOTO_ON_FALSE_DBG(http_utils_assign_string(&client->connection_info.scheme, url + purl.field_data[UF_SCHEMA].off, purl.field_data[UF_SCHEMA].len), ESP_ERR_NO_MEM, error, TAG, "failed to assign string"); if (strcasecmp(client->connection_info.scheme, "http") == 0) { client->connection_info.port = DEFAULT_HTTP_PORT; @@ -1143,16 +1163,16 @@ esp_err_t esp_http_client_set_url(esp_http_client_handle_t client, const char *u if (purl.field_data[UF_USERINFO].len) { char *user_info = NULL; - ESP_GOTO_ON_FALSE_DEBUG(http_utils_assign_string(&user_info, url + purl.field_data[UF_USERINFO].off, purl.field_data[UF_USERINFO].len), ESP_ERR_NO_MEM, error, TAG, "failed to assign string"); + HTTP_GOTO_ON_FALSE_DBG(http_utils_assign_string(&user_info, url + purl.field_data[UF_USERINFO].off, purl.field_data[UF_USERINFO].len), ESP_ERR_NO_MEM, error, TAG, "failed to assign string"); if (user_info) { char *username = user_info; char *password = strchr(user_info, ':'); if (password) { *password = 0; password ++; - ESP_GOTO_ON_FALSE_DEBUG(http_utils_assign_string(&client->connection_info.password, password, -1), ESP_ERR_NO_MEM, error, TAG, "failed to assign string"); + HTTP_GOTO_ON_FALSE_DBG(http_utils_assign_string(&client->connection_info.password, password, -1), ESP_ERR_NO_MEM, error, TAG, "failed to assign string"); } - ESP_GOTO_ON_FALSE_DEBUG(http_utils_assign_string(&client->connection_info.username, username, -1), ESP_ERR_NO_MEM, error, TAG, "failed to assign string"); + HTTP_GOTO_ON_FALSE_DBG(http_utils_assign_string(&client->connection_info.username, username, -1), ESP_ERR_NO_MEM, error, TAG, "failed to assign string"); free(user_info); } else { return ESP_ERR_NO_MEM; @@ -1161,13 +1181,13 @@ esp_err_t esp_http_client_set_url(esp_http_client_handle_t client, const char *u //Reset path and query if there are no information if (purl.field_data[UF_PATH].len) { - ESP_GOTO_ON_FALSE_DEBUG(http_utils_assign_string(&client->connection_info.path, url + purl.field_data[UF_PATH].off, purl.field_data[UF_PATH].len), ESP_ERR_NO_MEM, error, TAG, "failed to assign string"); + HTTP_GOTO_ON_FALSE_DBG(http_utils_assign_string(&client->connection_info.path, url + purl.field_data[UF_PATH].off, purl.field_data[UF_PATH].len), ESP_ERR_NO_MEM, error, TAG, "failed to assign string"); } else { - ESP_GOTO_ON_FALSE_DEBUG(http_utils_assign_string(&client->connection_info.path, "/", -1), ESP_ERR_NO_MEM, error, TAG, "failed to assign string"); + HTTP_GOTO_ON_FALSE_DBG(http_utils_assign_string(&client->connection_info.path, "/", -1), ESP_ERR_NO_MEM, error, TAG, "failed to assign string"); } if (purl.field_data[UF_QUERY].len) { - ESP_GOTO_ON_FALSE_DEBUG(http_utils_assign_string(&client->connection_info.query, url + purl.field_data[UF_QUERY].off, purl.field_data[UF_QUERY].len), ESP_ERR_NO_MEM, error, TAG, "failed to assign string"); + HTTP_GOTO_ON_FALSE_DBG(http_utils_assign_string(&client->connection_info.query, url + purl.field_data[UF_QUERY].off, purl.field_data[UF_QUERY].len), ESP_ERR_NO_MEM, error, TAG, "failed to assign string"); } else if (client->connection_info.query) { free(client->connection_info.query); client->connection_info.query = NULL; @@ -1189,6 +1209,15 @@ int esp_http_client_get_errno(esp_http_client_handle_t client) return esp_transport_get_errno(client->transport); } +esp_err_t esp_http_client_get_and_clear_last_tls_error(esp_http_client_handle_t client, int *tls_code, int *tls_flags) +{ + if (!client) { + ESP_LOGE(TAG, "Invalid client handle"); + return ESP_FAIL; + } + return esp_tls_get_and_clear_last_error(esp_transport_get_error_handle(client->transport), tls_code, tls_flags); +} + esp_err_t esp_http_client_set_method(esp_http_client_handle_t client, esp_http_client_method_t method) { client->connection_info.method = method; @@ -1792,7 +1821,7 @@ esp_err_t esp_http_client_set_auth_data(esp_http_client_handle_t client, const c if (client == NULL || auth_data == NULL || len <= 0) { return ESP_ERR_INVALID_ARG; } - ESP_RETURN_ON_FALSE_DEBUG(http_utils_append_string(&client->auth_header, auth_data, len), ESP_ERR_NO_MEM, TAG, "Failed to append string"); + HTTP_RET_ON_FALSE_DBG(http_utils_append_string(&client->auth_header, auth_data, len), ESP_ERR_NO_MEM, TAG, "Failed to append string"); return ESP_OK; } @@ -1841,20 +1870,20 @@ esp_err_t esp_http_client_add_auth(esp_http_client_handle_t client) client->auth_data->method = strdup(HTTP_METHOD_MAPPING[client->connection_info.method]); client->auth_data->nc = 1; - ESP_RETURN_ON_ERROR_DEBUG(http_utils_get_substring_between(auth_header, "realm=\"", "\"", &client->auth_data->realm), TAG, "Unable to extract substring between specified strings"); - ESP_RETURN_ON_ERROR_DEBUG(http_utils_get_substring_between(auth_header, "algorithm=", ",", &client->auth_data->algorithm), TAG, "Unable to extract substring between specified strings"); + HTTP_RET_ON_ERR_DBG(http_utils_get_string_between(auth_header, "realm=\"", "\"", &client->auth_data->realm), TAG, "Unable to extract substring between specified strings"); + HTTP_RET_ON_ERR_DBG(http_utils_get_string_between(auth_header, "algorithm=", ",", &client->auth_data->algorithm), TAG, "Unable to extract substring between specified strings"); if (client->auth_data->algorithm == NULL) { - ESP_RETURN_ON_ERROR_DEBUG(http_utils_get_substring_after(auth_header, "algorithm=", &client->auth_data->algorithm), TAG, "Unable to extract substring after specified string"); + HTTP_RET_ON_ERR_DBG(http_utils_get_string_after(auth_header, "algorithm=", &client->auth_data->algorithm), TAG, "Unable to extract substring after specified string"); } if (client->auth_data->algorithm == NULL) { client->auth_data->algorithm = strdup("MD5"); } - ESP_RETURN_ON_ERROR_DEBUG(http_utils_get_substring_between(auth_header, "qop=\"", "\"", &client->auth_data->qop), TAG, "Unable to extract substring between specified strings"); - ESP_RETURN_ON_ERROR_DEBUG(http_utils_get_substring_between(auth_header, "nonce=\"", "\"", &client->auth_data->nonce), TAG, "Unable to extract substring between specified strings"); - ESP_RETURN_ON_ERROR_DEBUG(http_utils_get_substring_between(auth_header, "opaque=\"", "\"", &client->auth_data->opaque), TAG, "Unable to extract substring between specified strings"); + HTTP_RET_ON_ERR_DBG(http_utils_get_string_between(auth_header, "qop=\"", "\"", &client->auth_data->qop), TAG, "Unable to extract substring between specified strings"); + HTTP_RET_ON_ERR_DBG(http_utils_get_string_between(auth_header, "nonce=\"", "\"", &client->auth_data->nonce), TAG, "Unable to extract substring between specified strings"); + HTTP_RET_ON_ERR_DBG(http_utils_get_string_between(auth_header, "opaque=\"", "\"", &client->auth_data->opaque), TAG, "Unable to extract substring between specified strings"); client->process_again = 1; return ESP_OK; diff --git a/components/esp_http_client/include/esp_http_client.h b/components/esp_http_client/include/esp_http_client.h index 1a2bc794363d..0d0137af860d 100644 --- a/components/esp_http_client/include/esp_http_client.h +++ b/components/esp_http_client/include/esp_http_client.h @@ -129,6 +129,15 @@ typedef enum { HTTP_AUTH_TYPE_DIGEST, /*!< HTTP Digest authentication */ } esp_http_client_auth_type_t; +/* +* @brief HTTP Address type +*/ +typedef enum { + HTTP_ADDR_TYPE_UNSPEC = AF_UNSPEC, /**< Unspecified address family. */ + HTTP_ADDR_TYPE_INET = AF_INET, /**< IPv4 address family. */ + HTTP_ADDR_TYPE_INET6 = AF_INET6, /**< IPv6 address family. */ +} esp_http_client_addr_type_t; + /** * @brief HTTP configuration */ @@ -194,6 +203,7 @@ typedef struct { #if CONFIG_ESP_HTTP_CLIENT_ENABLE_CUSTOM_TRANSPORT struct esp_transport_item_t *transport; #endif + esp_http_client_addr_type_t addr_type; /*!< Address type used in http client configurations */ } esp_http_client_config_t; /** @@ -457,6 +467,23 @@ esp_err_t esp_http_client_set_user_data(esp_http_client_handle_t client, void *d */ int esp_http_client_get_errno(esp_http_client_handle_t client); +/** + * @brief Returns last error in esp_tls with detailed mbedtls related error codes. + * The error information is cleared internally upon return + * + * @param[in] client The esp_http_client handle + * @param[out] esp_tls_error_code last error code returned from mbedtls api (set to zero if none) + * This pointer could be NULL if caller does not care about esp_tls_code + * @param[out] esp_tls_flags last certification verification flags (set to zero if none) + * This pointer could be NULL if caller does not care about esp_tls_code + * + * @return + * - ESP_FAIL if invalid parameters + * - ESP_OK (0) if no error occurred + * - specific error code (based on ESP_ERR_ESP_TLS_BASE) otherwise + */ +esp_err_t esp_http_client_get_and_clear_last_tls_error(esp_http_client_handle_t client, int *esp_tls_error_code, int *esp_tls_flags); + /** * @brief Set http request method * diff --git a/components/esp_http_client/lib/http_header.c b/components/esp_http_client/lib/http_header.c index 74cbbef0bc2f..023930f13755 100644 --- a/components/esp_http_client/lib/http_header.c +++ b/components/esp_http_client/lib/http_header.c @@ -81,9 +81,9 @@ static esp_err_t http_header_new_item(http_header_handle_t header, const char *k item = calloc(1, sizeof(http_header_item_t)); ESP_RETURN_ON_FALSE(item, ESP_ERR_NO_MEM, TAG, "Memory exhausted"); - ESP_GOTO_ON_FALSE_DEBUG(http_utils_assign_string(&item->key, key, -1), ESP_ERR_NO_MEM, _header_new_item_exit, TAG, "Failed to assign string"); + HTTP_GOTO_ON_FALSE_DBG(http_utils_assign_string(&item->key, key, -1), ESP_ERR_NO_MEM, _header_new_item_exit, TAG, "Failed to assign string"); http_utils_trim_whitespace(&item->key); - ESP_GOTO_ON_FALSE_DEBUG(http_utils_assign_string(&item->value, value, -1), ESP_ERR_NO_MEM, _header_new_item_exit, TAG, "Failed to assign string"); + HTTP_GOTO_ON_FALSE_DBG(http_utils_assign_string(&item->value, value, -1), ESP_ERR_NO_MEM, _header_new_item_exit, TAG, "Failed to assign string"); http_utils_trim_whitespace(&item->value); STAILQ_INSERT_TAIL(header, item, next); return ret; diff --git a/components/esp_http_client/lib/http_utils.c b/components/esp_http_client/lib/http_utils.c index 8e53fb1fd62d..ec6a20fcf52e 100644 --- a/components/esp_http_client/lib/http_utils.c +++ b/components/esp_http_client/lib/http_utils.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 */ @@ -110,41 +110,7 @@ void http_utils_trim_whitespace(char **str) memmove(*str, start, strlen(start) + 1); } -char *http_utils_get_string_between(const char *str, const char *begin, const char *end) -{ - char *found = strcasestr(str, begin); - char *ret = NULL; - if (found) { - found += strlen(begin); - char *found_end = strcasestr(found, end); - if (found_end) { - ret = calloc(1, found_end - found + 1); - mem_check(ret); - memcpy(ret, found, found_end - found); - return ret; - } - } - return NULL; -} - -char *http_utils_get_string_after(const char *str, const char *begin) -{ - char *found = strcasestr(str, begin); - char *ret = NULL; - if (found) { - found += strlen(begin); - char *found_end = (char *)str + strlen(str); - if (found_end) { - ret = calloc(1, found_end - found + 1); - mem_check(ret); - memcpy(ret, found, found_end - found); - return ret; - } - } - return NULL; -} - -esp_err_t http_utils_get_substring_between(const char *str, const char *begin, const char *end, char **out) +esp_err_t http_utils_get_string_between(const char *str, const char *begin, const char *end, char **out) { *out = NULL; char *found = strcasestr(str, begin); @@ -160,7 +126,7 @@ esp_err_t http_utils_get_substring_between(const char *str, const char *begin, c return ESP_OK; } -esp_err_t http_utils_get_substring_after(const char *str, const char *begin, char **out) +esp_err_t http_utils_get_string_after(const char *str, const char *begin, char **out) { *out = NULL; char *found = strcasestr(str, begin); diff --git a/components/esp_http_client/lib/include/http_utils.h b/components/esp_http_client/lib/include/http_utils.h index 113c76be5941..3bb9d87ddf3c 100644 --- a/components/esp_http_client/lib/include/http_utils.h +++ b/components/esp_http_client/lib/include/http_utils.h @@ -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 */ @@ -9,6 +9,43 @@ #define _HTTP_UTILS_H_ #include +/** + * Macro which can be used to check the error code. If the code is not ESP_OK, it prints the message and returns. + * It logs the message in debug mode. + */ +#define HTTP_RET_ON_ERR_DBG(x, log_tag, format, ...) do { \ + esp_err_t err_rc_ = (x); \ + if (unlikely(err_rc_ != ESP_OK)) { \ + ESP_LOGD(log_tag, "%s(%d): " format, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ + return err_rc_; \ + } \ + } while(0) + +/** + * Macro which can be used to check the condition. If the condition is not 'true', it prints the message + * and returns with the supplied 'err_code'. + * It logs the message in debug mode. + */ +#define HTTP_RET_ON_FALSE_DBG(a, err_code, log_tag, format, ...) do { \ + if (unlikely(!(a))) { \ + ESP_LOGD(log_tag, "%s(%d): " format, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ + return err_code; \ + } \ + } while(0) + +/** + * Macro which can be used to check the condition. If the condition is not 'true', it prints the message, + * sets the local variable 'ret' to the supplied 'err_code', and then exits by jumping to 'goto_tag'. + * It logs the message in debug mode. + */ +#define HTTP_GOTO_ON_FALSE_DBG(a, err_code, goto_tag, log_tag, format, ...) do { \ + if (unlikely(!(a))) { \ + ESP_LOGD(log_tag, "%s(%d): " format, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ + ret = err_code; \ + goto goto_tag; \ + } \ + } while (0) + /** * @brief Assign new_str to *str pointer, and realloc *str if it not NULL * @@ -43,29 +80,6 @@ char *http_utils_append_string(char **str, const char *new_str, int len); */ void http_utils_trim_whitespace(char **str); -/** - * @brief Gets the string between 2 string. - * It will allocate a new memory space for this string, so you need to free it when no longer use - * - * @param[in] str The source string - * @param[in] begin The begin string - * @param[in] end The end string - * - * @return The string between begin and end - */ -char *http_utils_get_string_between(const char *str, const char *begin, const char *end) __attribute__((deprecated("Use http_utils_get_substring_between instead.")));; - -/** - * @brief Returns a string that contains the part after the search string till the end of the source string. - * It will allocate a new memory space for this string, so you need to free it when no longer used - * - * @param[in] str The source string - * @param[in] begin The search string - * - * @return The string between begin and the end of str - */ -char *http_utils_get_string_after(const char *str, const char *begin) __attribute__((deprecated("Use http_utils_get_substring_after instead.")));; - /** * @brief Extracts the substring between two specified delimiters. * Allocates memory for the extracted substring and stores it in `out`. @@ -80,7 +94,7 @@ char *http_utils_get_string_after(const char *str, const char *begin) __attribut * - ESP_OK: Operation succeeded (even if no substring is found). * - ESP_ERR_NO_MEM: Memory allocation failed. */ -esp_err_t http_utils_get_substring_between(const char *str, const char *begin, const char *end, char **out); +esp_err_t http_utils_get_string_between(const char *str, const char *begin, const char *end, char **out); /** * @brief Extracts the substring starting after a specified delimiter until the end of the source string. @@ -95,7 +109,7 @@ esp_err_t http_utils_get_substring_between(const char *str, const char *begin, c * - ESP_OK: Operation succeeded (even if no substring is found). * - ESP_ERR_NO_MEM: Memory allocation failed. */ -esp_err_t http_utils_get_substring_after(const char *str, const char *begin, char **out); +esp_err_t http_utils_get_string_after(const char *str, const char *begin, char **out); /** * @brief Join 2 strings to one diff --git a/components/esp_hw_support/CMakeLists.txt b/components/esp_hw_support/CMakeLists.txt index 0c68d0913499..4235e184e212 100644 --- a/components/esp_hw_support/CMakeLists.txt +++ b/components/esp_hw_support/CMakeLists.txt @@ -151,6 +151,10 @@ if(NOT non_os_build) list(APPEND srcs "power_supply/brownout.c") endif() + if(CONFIG_ESP_VBAT_INIT_AUTO) + list(APPEND srcs "power_supply/vbat.c") + endif() + else() if(ESP_TEE_BUILD) list(APPEND srcs "esp_clk.c" "hw_random.c") diff --git a/components/esp_hw_support/Kconfig b/components/esp_hw_support/Kconfig index 2fbfad0b40b5..e184b5dea5a5 100644 --- a/components/esp_hw_support/Kconfig +++ b/components/esp_hw_support/Kconfig @@ -247,7 +247,7 @@ menu "Hardware Settings" orsource "./port/$IDF_TARGET/Kconfig.ldo" - orsource "./power_supply/port/$IDF_TARGET/Kconfig.bod" + orsource "./power_supply/port/$IDF_TARGET/Kconfig.power" # Invisible bringup bypass options for esp_hw_support component config ESP_BRINGUP_BYPASS_CPU_CLK_SETTING diff --git a/components/esp_hw_support/dma/gdma_link.c b/components/esp_hw_support/dma/gdma_link.c index 45923f57a956..5381b150e152 100644 --- a/components/esp_hw_support/dma/gdma_link.c +++ b/components/esp_hw_support/dma/gdma_link.c @@ -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 */ @@ -141,13 +141,14 @@ esp_err_t gdma_del_link_list(gdma_link_list_handle_t list) return ESP_OK; } -esp_err_t gdma_link_mount_buffers(gdma_link_list_handle_t list, uint32_t start_item_index, const gdma_buffer_mount_config_t *buf_config_array, size_t num_buf, uint32_t *end_item_index) +esp_err_t gdma_link_mount_buffers(gdma_link_list_handle_t list, int start_item_index, const gdma_buffer_mount_config_t *buf_config_array, size_t num_buf, int *end_item_index) { ESP_RETURN_ON_FALSE(list && buf_config_array && num_buf, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); - ESP_RETURN_ON_FALSE(start_item_index < list->num_items, ESP_ERR_INVALID_ARG, TAG, "invalid start item index"); size_t buffer_alignment = list->buffer_alignment; size_t item_size = list->item_size; uint32_t list_item_capacity = list->num_items; + // ensure the start_item_index is between 0 and `list_item_capacity - 1` + start_item_index = (start_item_index % list_item_capacity + list_item_capacity) % list_item_capacity; size_t max_buffer_mount_length = ALIGN_DOWN(GDMA_MAX_BUFFER_SIZE_PER_LINK_ITEM, buffer_alignment); uint32_t begin_item_idx = start_item_index; gdma_link_list_item_t *lli_nc = NULL; @@ -155,7 +156,7 @@ esp_err_t gdma_link_mount_buffers(gdma_link_list_handle_t list, uint32_t start_i uint32_t num_items_avail = 0; // if the link list is responsible for checking the ownership, we need to skip the items that are owned by the DMA if (list->flags.check_owner) { - for (uint32_t i = 0; i < list_item_capacity; i++) { + for (int i = 0; i < list_item_capacity; i++) { lli_nc = (gdma_link_list_item_t *)(list->items_nc + (i + start_item_index) % list_item_capacity * item_size); if (lli_nc->dw0.owner == GDMA_LLI_OWNER_CPU) { num_items_avail++; @@ -166,8 +167,8 @@ esp_err_t gdma_link_mount_buffers(gdma_link_list_handle_t list, uint32_t start_i } // check alignment and length for each buffer - for (size_t i = 0; i < num_buf; i++) { - const gdma_buffer_mount_config_t *config = &buf_config_array[i]; + for (size_t bi = 0; bi < num_buf; bi++) { + const gdma_buffer_mount_config_t *config = &buf_config_array[bi]; uint8_t *buf = (uint8_t *)config->buffer; size_t len = config->length; // check the buffer alignment @@ -183,8 +184,8 @@ esp_err_t gdma_link_mount_buffers(gdma_link_list_handle_t list, uint32_t start_i lli_nc->next = (gdma_link_list_item_t *)(list->items + start_item_index * item_size); begin_item_idx = start_item_index; - for (size_t i = 0; i < num_buf; i++) { - const gdma_buffer_mount_config_t *config = &buf_config_array[i]; + for (size_t bi = 0; bi < num_buf; bi++) { + const gdma_buffer_mount_config_t *config = &buf_config_array[bi]; uint8_t *buf = (uint8_t *)config->buffer; size_t len = config->length; // skip zero-length buffer @@ -193,7 +194,7 @@ esp_err_t gdma_link_mount_buffers(gdma_link_list_handle_t list, uint32_t start_i } uint32_t num_items_need = (len + max_buffer_mount_length - 1) / max_buffer_mount_length; // mount the buffer to the link list - for (uint32_t i = 0; i < num_items_need; i++) { + for (int i = 0; i < num_items_need; i++) { lli_nc = (gdma_link_list_item_t *)(list->items_nc + (i + begin_item_idx) % list_item_capacity * item_size); lli_nc->buffer = buf; lli_nc->dw0.length = len > max_buffer_mount_length ? max_buffer_mount_length : len; @@ -232,16 +233,25 @@ esp_err_t gdma_link_concat(gdma_link_list_handle_t first_link, int first_link_it { ESP_RETURN_ON_FALSE(first_link && second_link, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); gdma_link_list_item_t *lli_nc = NULL; - lli_nc = (gdma_link_list_item_t *)(first_link->items_nc + (first_link->num_items + first_link_item_index) % first_link->num_items * first_link->item_size); - lli_nc->next = (gdma_link_list_item_t *)(second_link->items + (second_link->num_items + second_link_item_index) % second_link->num_items * second_link->item_size); + // ensure the first_link_item_index is between 0 and `num_items - 1` + int num_items = first_link->num_items; + first_link_item_index = (first_link_item_index % num_items + num_items) % num_items; + lli_nc = (gdma_link_list_item_t *)(first_link->items_nc + first_link_item_index * first_link->item_size); + // ensure the second_link_item_index is between 0 and `num_items - 1` + num_items = second_link->num_items; + second_link_item_index = (second_link_item_index % num_items + num_items) % num_items; + // concatenate the two link lists + lli_nc->next = (gdma_link_list_item_t *)(second_link->items + second_link_item_index * second_link->item_size); return ESP_OK; } esp_err_t gdma_link_set_owner(gdma_link_list_handle_t list, int item_index, gdma_lli_owner_t owner) { ESP_RETURN_ON_FALSE_ISR(list, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); - ESP_RETURN_ON_FALSE_ISR(item_index < list->num_items, ESP_ERR_INVALID_ARG, TAG, "invalid item index"); - gdma_link_list_item_t *lli = (gdma_link_list_item_t *)(list->items_nc + (list->num_items + item_index) % list->num_items * list->item_size); + int num_items = list->num_items; + // ensure the item_index is between 0 and `num_items - 1` + item_index = (item_index % num_items + num_items) % num_items; + gdma_link_list_item_t *lli = (gdma_link_list_item_t *)(list->items_nc + item_index * list->item_size); lli->dw0.owner = owner; return ESP_OK; } @@ -249,8 +259,31 @@ esp_err_t gdma_link_set_owner(gdma_link_list_handle_t list, int item_index, gdma esp_err_t gdma_link_get_owner(gdma_link_list_handle_t list, int item_index, gdma_lli_owner_t *owner) { ESP_RETURN_ON_FALSE_ISR(list && owner, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); - ESP_RETURN_ON_FALSE_ISR(item_index < list->num_items, ESP_ERR_INVALID_ARG, TAG, "invalid item index"); - gdma_link_list_item_t *lli = (gdma_link_list_item_t *)(list->items_nc + (list->num_items + item_index) % list->num_items * list->item_size); + int num_items = list->num_items; + // ensure the item_index is between 0 and `num_items - 1` + item_index = (item_index % num_items + num_items) % num_items; + gdma_link_list_item_t *lli = (gdma_link_list_item_t *)(list->items_nc + item_index * list->item_size); *owner = lli->dw0.owner; return ESP_OK; } + +size_t gdma_link_count_buffer_size_till_eof(gdma_link_list_handle_t list, int start_item_index) +{ + if (!list) { + return 0; + } + int num_items = list->num_items; + // ensure the start_item_index is between 0 and `num_items - 1` + start_item_index = (start_item_index % num_items + num_items) % num_items; + size_t buf_size = 0; + gdma_link_list_item_t *lli_nc = NULL; + for (int i = 0; i < num_items; i++) { + lli_nc = (gdma_link_list_item_t *)(list->items_nc + (start_item_index + i) % num_items * list->item_size); + buf_size += lli_nc->dw0.length; + // break if the current item is the last one or the EOF item + if (lli_nc->dw0.suc_eof || lli_nc->next == NULL) { + break; + } + } + return buf_size; +} diff --git a/components/esp_hw_support/dma/include/esp_private/gdma_link.h b/components/esp_hw_support/dma/include/esp_private/gdma_link.h index fa350e792a6f..6972d16d1691 100644 --- a/components/esp_hw_support/dma/include/esp_private/gdma_link.h +++ b/components/esp_hw_support/dma/include/esp_private/gdma_link.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 */ @@ -91,7 +91,7 @@ typedef struct { * - ESP_ERR_INVALID_ARG: Mount the buffer failed because of invalid argument * - ESP_FAIL: Mount the buffer failed because of other error */ -esp_err_t gdma_link_mount_buffers(gdma_link_list_handle_t list, uint32_t start_item_index, const gdma_buffer_mount_config_t *buf_config_array, size_t num_buf, uint32_t *end_item_index); +esp_err_t gdma_link_mount_buffers(gdma_link_list_handle_t list, int start_item_index, const gdma_buffer_mount_config_t *buf_config_array, size_t num_buf, int *end_item_index); /** * @brief Get the address of the head item in the link list @@ -164,6 +164,16 @@ esp_err_t gdma_link_set_owner(gdma_link_list_handle_t list, int item_index, gdma */ esp_err_t gdma_link_get_owner(gdma_link_list_handle_t list, int item_index, gdma_lli_owner_t *owner); +/** + * @brief Get the size of the buffer that is mounted to the link list until the eof item (inclusive) + * + * @param[in] list Link list handle, allocated by `gdma_new_link_list` + * @param[in] start_item_index Index of the first item in the link list to be calculated + * @return Size of the buffer that is mounted to the link list until the eof item (inclusive). + * If the link list is empty or invalid, return 0. + */ +size_t gdma_link_count_buffer_size_till_eof(gdma_link_list_handle_t list, int start_item_index); + #ifdef __cplusplus } #endif diff --git a/components/esp_hw_support/esp_clock_output.c b/components/esp_hw_support/esp_clock_output.c index efc20d525450..7c0fc8ef2dbe 100644 --- a/components/esp_hw_support/esp_clock_output.c +++ b/components/esp_hw_support/esp_clock_output.c @@ -17,6 +17,7 @@ #include "hal/clk_tree_ll.h" #include "soc/soc_caps.h" #include "soc/io_mux_reg.h" +#include "esp_private/gpio.h" typedef struct clkout_channel_handle { bool is_mapped; @@ -143,7 +144,6 @@ static esp_clock_output_mapping_t* clkout_mapping_alloc(clkout_channel_handle_t* #elif SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX gpio_set_pull_mode(gpio_num, GPIO_FLOATING); gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[gpio_num], PIN_FUNC_GPIO); - gpio_set_direction(gpio_num, GPIO_MODE_OUTPUT); esp_rom_gpio_connect_out_signal(gpio_num, CLKOUT_CHANNEL_TO_GPIO_SIG_ID(allocated_mapping->clkout_channel_hdl->channel_id), false, false); #endif } @@ -175,7 +175,7 @@ static void clkout_mapping_free(esp_clock_output_mapping_t *mapping_hdl) if (--mapping_hdl->ref_cnt == 0) { gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[mapping_hdl->mapped_io], PIN_FUNC_GPIO); esp_rom_gpio_connect_out_signal(mapping_hdl->mapped_io, SIG_GPIO_OUT_IDX, false, false); - gpio_set_direction(mapping_hdl->mapped_io, GPIO_MODE_DISABLE); + gpio_output_disable(mapping_hdl->mapped_io); portENTER_CRITICAL(&mapping_hdl->clkout_channel_hdl->clkout_channel_lock); mapping_hdl->clkout_channel_hdl->mapped_io_bmap &= ~BIT(mapping_hdl->mapped_io); diff --git a/components/esp_hw_support/include/esp_intr_alloc.h b/components/esp_hw_support/include/esp_intr_alloc.h index 60e357618722..b2f1b7bfc6ac 100644 --- a/components/esp_hw_support/include/esp_intr_alloc.h +++ b/components/esp_hw_support/include/esp_intr_alloc.h @@ -94,7 +94,7 @@ extern "C" { * the int can be left enabled while the flash cache is disabled. * * @return ESP_ERR_INVALID_ARG if cpu or intno is invalid - * ESP_OK otherwise + * ESP_OK on success */ esp_err_t esp_intr_mark_shared(int intno, int cpu, bool is_in_iram); @@ -108,7 +108,7 @@ esp_err_t esp_intr_mark_shared(int intno, int cpu, bool is_in_iram); * @param cpu CPU on which the interrupt should be marked as shared (0 or 1) * * @return ESP_ERR_INVALID_ARG if cpu or intno is invalid - * ESP_OK otherwise + * ESP_OK on success */ esp_err_t esp_intr_reserve(int intno, int cpu); @@ -131,9 +131,10 @@ esp_err_t esp_intr_reserve(int intno, int cpu); * @param flags An ORred mask of the ESP_INTR_FLAG_* defines. These restrict the * choice of interrupts that this routine can choose from. If this value * is 0, it will default to allocating a non-shared interrupt of level - * 1, 2 or 3. If this is ESP_INTR_FLAG_SHARED, it will allocate a shared - * interrupt of level 1. Setting ESP_INTR_FLAG_INTRDISABLED will return - * from this function with the interrupt disabled. + * 1, 2 or 3. If ESP_INTR_FLAG_SHARED mask is provided, a shared interrupt of + * the given level will be allocated (or level 1 if not specified). + * Setting ESP_INTR_FLAG_INTRDISABLED will return from this function with the + * interrupt disabled. * @param handler The interrupt handler. Must be NULL when an interrupt of level >3 * is requested, because these types of interrupts aren't C-callable. * @param arg Optional argument for passed to the interrupt handler @@ -143,13 +144,13 @@ esp_err_t esp_intr_reserve(int intno, int cpu); * * @return ESP_ERR_INVALID_ARG if the combination of arguments is invalid. * ESP_ERR_NOT_FOUND No free interrupt found with the specified flags - * ESP_OK otherwise + * ESP_OK on success */ esp_err_t esp_intr_alloc(int source, int flags, intr_handler_t handler, void *arg, intr_handle_t *ret_handle); /** - * @brief Allocate an interrupt with the given parameters. + * @brief Allocate an interrupt with the given parameters, including an interrupt status register. * * * This essentially does the same as esp_intr_alloc, but allows specifying a register and mask @@ -165,9 +166,10 @@ esp_err_t esp_intr_alloc(int source, int flags, intr_handler_t handler, void *ar * @param flags An ORred mask of the ESP_INTR_FLAG_* defines. These restrict the * choice of interrupts that this routine can choose from. If this value * is 0, it will default to allocating a non-shared interrupt of level - * 1, 2 or 3. If this is ESP_INTR_FLAG_SHARED, it will allocate a shared - * interrupt of level 1. Setting ESP_INTR_FLAG_INTRDISABLED will return - * from this function with the interrupt disabled. + * 1, 2 or 3. If ESP_INTR_FLAG_SHARED mask is provided, a shared interrupt of + * the given level will be allocated (or level 1 if not specified). + * Setting ESP_INTR_FLAG_INTRDISABLED will return from this function with the + * interrupt disabled. * @param intrstatusreg The address of an interrupt status register * @param intrstatusmask A mask. If a read of address intrstatusreg has any of the bits * that are 1 in the mask set, the ISR will be called. If not, it will be @@ -181,11 +183,92 @@ esp_err_t esp_intr_alloc(int source, int flags, intr_handler_t handler, void *ar * * @return ESP_ERR_INVALID_ARG if the combination of arguments is invalid. * ESP_ERR_NOT_FOUND No free interrupt found with the specified flags - * ESP_OK otherwise + * ESP_OK on success */ esp_err_t esp_intr_alloc_intrstatus(int source, int flags, uint32_t intrstatusreg, uint32_t intrstatusmask, intr_handler_t handler, void *arg, intr_handle_t *ret_handle); +/** + * @brief Allocate an interrupt with the given parameters that can be bound to an existing interrupt handler. + * + * + * This function does the same as esp_intr_alloc, but allows specifying a previously allocated handler as + * the interrupt to share with the given source. This can be very handy to treat two pre-determined interrupt + * sources in the same interrupt handler. The interrupt will be allocated on the same core as the given + * `shared_handle`. Moreover, make sure to specify the same interrupt level as the one being used by `shared_handle` + * to prevent any failure from this function. + * + * @param source The interrupt source. One of the ETS_*_INTR_SOURCE interrupt mux + * sources, as defined in soc/soc.h, or one of the internal + * ETS_INTERNAL_*_INTR_SOURCE sources as defined in this header. + * @param flags An ORred mask of the ESP_INTR_FLAG_* defines. These restrict the + * choice of interrupts that this routine can choose from. If this value + * is 0, it will default to allocating a non-shared interrupt of level + * 1, 2 or 3. If ESP_INTR_FLAG_SHARED mask is provided, a shared interrupt of + * the given level will be allocated (or level 1 if not specified). + * Setting ESP_INTR_FLAG_INTRDISABLED will return from this function with the + * interrupt disabled. + * @param handler The interrupt handler. Must be NULL when an interrupt of level >3 + * is requested, because these types of interrupts aren't C-callable. + * @param arg Optional argument for passed to the interrupt handler + * @param shared_handle Previously allocated interrupt to share the CPU interrupt line with. If NULL, + * calling this function equivalent to esp_intr_alloc, else, ESP_INTR_FLAG_SHARED must + * be provided in the flags parameter. + * @param ret_handle Pointer to an intr_handle_t to store a handle that can later be + * used to request details or free the interrupt. Can be NULL if no handle + * is required. + * + * @return ESP_ERR_INVALID_ARG if the combination of arguments is invalid. + * ESP_ERR_NOT_FOUND No free interrupt found with the specified flasg or the given level is different + * from the one assigned to the share_handle parameter. + * ESP_OK on success + */ +esp_err_t esp_intr_alloc_bind(int source, int flags, intr_handler_t handler, void *arg, intr_handle_t shared_handle, intr_handle_t *ret_handle); + + +/** + * @brief Allocate an interrupt with the given parameters, including an interrupt status register, that can + * be bound to an existing interrupt handler + * + * + * This function does the same as esp_intr_alloc_intrstatus, but allows specifying a previously allocated handler as + * the interrupt to share with the given source. This can be very handy to treat two pre-determined interrupt + * sources in the same interrupt handler. The interrupt will be allocated on the same core as the given + * `shared_handle`. Moreover, make sure to specify the same interrupt level as the one being used by `shared_handle` + * to prevent any failure from this function. + * + * @param source The interrupt source. One of the ETS_*_INTR_SOURCE interrupt mux + * sources, as defined in soc/soc.h, or one of the internal + * ETS_INTERNAL_*_INTR_SOURCE sources as defined in this header. + * @param flags An ORred mask of the ESP_INTR_FLAG_* defines. These restrict the + * choice of interrupts that this routine can choose from. If this value + * is 0, it will default to allocating a non-shared interrupt of level + * 1, 2 or 3. If ESP_INTR_FLAG_SHARED mask is provided, a shared interrupt of + * the given level will be allocated (or level 1 if not specified). + * Setting ESP_INTR_FLAG_INTRDISABLED will return from this function with the + * interrupt disabled. + * @param intrstatusreg The address of an interrupt status register + * @param intrstatusmask A mask. If a read of address intrstatusreg has any of the bits + * that are 1 in the mask set, the ISR will be called. If not, it will be + * skipped. + * @param handler The interrupt handler. Must be NULL when an interrupt of level >3 + * is requested, because these types of interrupts aren't C-callable. + * @param arg Optional argument for passed to the interrupt handler + * @param shared_handle Previously allocated interrupt to share the CPU interrupt line with. If NULL, + * calling this function equivalent to esp_intr_alloc, else, ESP_INTR_FLAG_SHARED must + * be provided in the flags parameter. + * @param ret_handle Pointer to an intr_handle_t to store a handle that can later be + * used to request details or free the interrupt. Can be NULL if no handle + * is required. + * + * @return ESP_ERR_INVALID_ARG if the combination of arguments is invalid. + * ESP_ERR_NOT_FOUND No free interrupt found with the specified flasg or the given level is different + * from the one assigned to the share_handle parameter. + * ESP_OK on success + */ +esp_err_t esp_intr_alloc_intrstatus_bind(int source, int flags, uint32_t intrstatusreg, uint32_t intrstatusmask, intr_handler_t handler, + void *arg, intr_handle_t shared_handle, intr_handle_t *ret_handle); + /** * @brief Disable and free an interrupt. * @@ -202,7 +285,7 @@ esp_err_t esp_intr_alloc_intrstatus(int source, int flags, uint32_t intrstatusre * * @return ESP_ERR_INVALID_ARG the handle is NULL * ESP_FAIL failed to release this handle - * ESP_OK otherwise + * ESP_OK on success */ esp_err_t esp_intr_free(intr_handle_t handle); @@ -239,7 +322,7 @@ int esp_intr_get_intno(intr_handle_t handle); * @param handle The handle, as obtained by esp_intr_alloc or esp_intr_alloc_intrstatus * * @return ESP_ERR_INVALID_ARG if the combination of arguments is invalid. - * ESP_OK otherwise + * ESP_OK on success */ esp_err_t esp_intr_disable(intr_handle_t handle); @@ -252,7 +335,7 @@ esp_err_t esp_intr_disable(intr_handle_t handle); * @param handle The handle, as obtained by esp_intr_alloc or esp_intr_alloc_intrstatus * * @return ESP_ERR_INVALID_ARG if the combination of arguments is invalid. - * ESP_OK otherwise + * ESP_OK on success */ esp_err_t esp_intr_enable(intr_handle_t handle); @@ -266,7 +349,7 @@ esp_err_t esp_intr_enable(intr_handle_t handle); * Handlers residing in IRAM can be called when cache is disabled. * * @return ESP_ERR_INVALID_ARG if the combination of arguments is invalid. - * ESP_OK otherwise + * ESP_OK on success */ esp_err_t esp_intr_set_in_iram(intr_handle_t handle, bool is_in_iram); diff --git a/components/esp_hw_support/include/esp_memory_utils.h b/components/esp_hw_support/include/esp_memory_utils.h index de0cea32c453..4b3a5db4cae1 100644 --- a/components/esp_hw_support/include/esp_memory_utils.h +++ b/components/esp_hw_support/include/esp_memory_utils.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2010-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2010-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -86,6 +86,7 @@ __attribute__((always_inline)) inline static bool esp_ptr_in_diram_iram(const void *p) { // TODO: IDF-5980 esp32c6 D/I RAM share the same address #if SOC_DIRAM_IRAM_LOW == SOC_DIRAM_DRAM_LOW + (void)p; return false; #else return ((intptr_t)p >= SOC_DIRAM_IRAM_LOW && (intptr_t)p < SOC_DIRAM_IRAM_HIGH); @@ -104,6 +105,7 @@ inline static bool esp_ptr_in_rtc_iram_fast(const void *p) { #if SOC_RTC_FAST_MEM_SUPPORTED && (SOC_RTC_IRAM_LOW != SOC_RTC_DRAM_LOW) return ((intptr_t)p >= SOC_RTC_IRAM_LOW && (intptr_t)p < SOC_RTC_IRAM_HIGH); #else + (void)p; return false; #endif } @@ -120,6 +122,7 @@ inline static bool esp_ptr_in_rtc_dram_fast(const void *p) { #if SOC_RTC_FAST_MEM_SUPPORTED return ((intptr_t)p >= SOC_RTC_DRAM_LOW && (intptr_t)p < SOC_RTC_DRAM_HIGH); #else + (void)p; return false; #endif } diff --git a/components/esp_hw_support/intr_alloc.c b/components/esp_hw_support/intr_alloc.c index 4365aa31a63d..39f19b24a640 100644 --- a/components/esp_hw_support/intr_alloc.c +++ b/components/esp_hw_support/intr_alloc.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 */ @@ -72,6 +72,16 @@ struct shared_vector_desc_t { #define VECDESC_FL_INIRAM (1<<1) #define VECDESC_FL_SHARED (1<<2) #define VECDESC_FL_NONSHARED (1<<3) +#define VECDESC_FL_TYPE_MASK (0xf) + +#if SOC_CPU_HAS_FLEXIBLE_INTC +/* On targets that have configurable interrupts levels, store the assigned level in the flags */ +#define VECDESC_FL_LEVEL_SHIFT (8) +/* Allocate 4 bits in the flag */ +#define VECDESC_FL_LEVEL_MASK (0xf) +/* Help to extract the level from flags */ +#define VECDESC_FL_LEVEL(flags) (((flags) >> VECDESC_FL_LEVEL_SHIFT) & VECDESC_FL_LEVEL_MASK) +#endif //Pack using bitfields for better memory use struct vector_desc_t { @@ -212,7 +222,7 @@ esp_err_t esp_intr_mark_shared(int intno, int cpu, bool is_int_ram) portEXIT_CRITICAL(&spinlock); return ESP_ERR_NO_MEM; } - vd->flags = VECDESC_FL_SHARED; + vd->flags = (vd->flags & ~VECDESC_FL_TYPE_MASK) | VECDESC_FL_SHARED; if (is_int_ram) { vd->flags |= VECDESC_FL_INIRAM; } @@ -258,7 +268,17 @@ static bool is_vect_desc_usable(vector_desc_t *vd, int flags, int cpu, int force return false; } -#ifndef SOC_CPU_HAS_FLEXIBLE_INTC +#if SOC_CPU_HAS_FLEXIBLE_INTC + /* On target that have configurable interrupts levels, check if the interrupt has already + * been allocated, and if yes, make sure the levels are compatible. */ + const int vector_lvl = VECDESC_FL_LEVEL(vd->flags); + /* A non-zero value means the level has already been set prior to this allocation, make + * sure the current level matches what we need. */ + if (vector_lvl != 0 && (flags & (1 << vector_lvl)) == 0) { + ALCHLOG("....Unusable: incompatible priority"); + return false; + } +#else //Check if the interrupt priority is acceptable if (!(flags & (1 << intr_desc.priority))) { ALCHLOG("....Unusable: incompatible priority"); @@ -480,8 +500,8 @@ bool esp_intr_ptr_in_isr_region(void* ptr) //We use ESP_EARLY_LOG* here because this can be called before the scheduler is running. -esp_err_t esp_intr_alloc_intrstatus(int source, int flags, uint32_t intrstatusreg, uint32_t intrstatusmask, intr_handler_t handler, - void *arg, intr_handle_t *ret_handle) +esp_err_t esp_intr_alloc_intrstatus_bind(int source, int flags, uint32_t intrstatusreg, uint32_t intrstatusmask, intr_handler_t handler, + void *arg, intr_handle_t shared_handle, intr_handle_t *ret_handle) { intr_handle_data_t *ret=NULL; int force = -1; @@ -509,7 +529,10 @@ esp_err_t esp_intr_alloc_intrstatus(int source, int flags, uint32_t intrstatusre if ((flags & ESP_INTR_FLAG_IRAM) && handler && !esp_intr_ptr_in_isr_region(handler)) { return ESP_ERR_INVALID_ARG; } - + //Shared handler must be passed with share interrupt flag + if (shared_handle != NULL && (flags & ESP_INTR_FLAG_SHARED) == 0) { + return ESP_ERR_INVALID_ARG; + } //Default to prio 1 for shared interrupts. Default to prio 1, 2 or 3 for non-shared interrupts. if ((flags & ESP_INTR_FLAG_LEVELMASK) == 0) { if (flags & ESP_INTR_FLAG_SHARED) { @@ -549,7 +572,17 @@ esp_err_t esp_intr_alloc_intrstatus(int source, int flags, uint32_t intrstatusre portENTER_CRITICAL(&spinlock); uint32_t cpu = esp_cpu_get_core_id(); - //See if we can find an interrupt that matches the flags. + if (shared_handle != NULL) { + /* Sanity check, should not occur */ + if (shared_handle->vector_desc == NULL) { + portEXIT_CRITICAL(&spinlock); + return ESP_ERR_INVALID_ARG; + } + /* If a shared vector was given, force the current interrupt source to same CPU interrupt line */ + force = shared_handle->vector_desc->intno; + /* Allocate the interrupt on the same core as the given handle */ + cpu = shared_handle->vector_desc->cpu; + } int intr = get_available_int(flags, cpu, force, source); if (intr == -1) { //None found. Bail out. @@ -640,6 +673,7 @@ esp_err_t esp_intr_alloc_intrstatus(int source, int flags, uint32_t intrstatusre #if SOC_CPU_HAS_FLEXIBLE_INTC //Extract the level from the interrupt passed flags int level = esp_intr_flags_to_level(flags); + vd->flags |= level << VECDESC_FL_LEVEL_SHIFT; esp_cpu_intr_set_priority(intr, level); if (flags & ESP_INTR_FLAG_EDGE) { @@ -671,6 +705,13 @@ esp_err_t esp_intr_alloc_intrstatus(int source, int flags, uint32_t intrstatusre return ESP_OK; } +esp_err_t esp_intr_alloc_intrstatus(int source, int flags, uint32_t intrstatusreg, uint32_t intrstatusmask, intr_handler_t handler, + void *arg, intr_handle_t *ret_handle) +{ + return esp_intr_alloc_intrstatus_bind(source, flags, intrstatusreg, intrstatusmask, handler, arg, NULL, ret_handle); +} + + esp_err_t esp_intr_alloc(int source, int flags, intr_handler_t handler, void *arg, intr_handle_t *ret_handle) { /* @@ -681,6 +722,13 @@ esp_err_t esp_intr_alloc(int source, int flags, intr_handler_t handler, void *ar return esp_intr_alloc_intrstatus(source, flags, 0, 0, handler, arg, ret_handle); } + +esp_err_t esp_intr_alloc_bind(int source, int flags, intr_handler_t handler, void *arg, intr_handle_t shared_handle, intr_handle_t *ret_handle) +{ + return esp_intr_alloc_intrstatus_bind(source, flags, 0, 0, handler, arg, shared_handle, ret_handle); +} + + esp_err_t IRAM_ATTR esp_intr_set_in_iram(intr_handle_t handle, bool is_in_iram) { if (!handle) { @@ -790,6 +838,10 @@ static esp_err_t intr_free_for_current_cpu(intr_handle_t handle) //we save.(We can also not use the same exit path for empty shared ints anymore if we delete //the desc.) For now, just mark it as free. handle->vector_desc->flags &= ~(VECDESC_FL_NONSHARED|VECDESC_FL_RESERVED|VECDESC_FL_SHARED); +#if SOC_CPU_HAS_FLEXIBLE_INTC + //Clear the assigned level + handle->vector_desc->flags &= ~(VECDESC_FL_LEVEL_MASK << VECDESC_FL_LEVEL_SHIFT); +#endif handle->vector_desc->source = ETS_INTERNAL_UNUSED_INTR_SOURCE; //Also kill non_iram mask bit. @@ -802,11 +854,17 @@ static esp_err_t intr_free_for_current_cpu(intr_handle_t handle) int esp_intr_get_intno(intr_handle_t handle) { + if (handle == NULL || handle->vector_desc == NULL) { + return -1; + } return handle->vector_desc->intno; } int esp_intr_get_cpu(intr_handle_t handle) { + if (handle == NULL || handle->vector_desc == NULL) { + return -1; + } return handle->vector_desc->cpu; } diff --git a/components/esp_hw_support/port/esp32c5/private_include/pmu_param.h b/components/esp_hw_support/port/esp32c5/private_include/pmu_param.h index b375e9333304..0ec68bb2f64b 100644 --- a/components/esp_hw_support/port/esp32c5/private_include/pmu_param.h +++ b/components/esp_hw_support/port/esp32c5/private_include/pmu_param.h @@ -438,7 +438,7 @@ typedef struct pmu_sleep_machine_constant { } lp; struct { uint16_t min_slp_time_us; /* Minimum sleep protection time (unit: microsecond) */ - uint16_t clock_domain_sync_time_us; /* The Slow OSC clock domain synchronizes time with the Fast OSC domain, at least 4 slow clock cycles (unit: microsecond) */ + uint16_t clock_domain_sync_time_us; /* Synchronizing the rtc clock timer to modem system requires at least 1 us (unit: microsecond) */ uint16_t system_dfs_up_work_time_us; /* System DFS up scaling work time (unit: microsecond) */ uint16_t analog_wait_time_us; /* HP LDO power up wait time (unit: microsecond) */ uint8_t isolate_wait_time_us; /* Waiting for all isolate signals to be ready (unit: microsecond) */ @@ -471,19 +471,19 @@ typedef struct pmu_sleep_machine_constant { }, \ .hp = { \ .min_slp_time_us = 450, \ - .clock_domain_sync_time_us = 150, \ + .clock_domain_sync_time_us = 2, \ .system_dfs_up_work_time_us = 124, \ .analog_wait_time_us = 154, \ .isolate_wait_time_us = 1, \ .reset_wait_time_us = 1, \ .power_supply_wait_time_us = 2, \ .power_up_wait_time_us = 2, \ - .regdma_s2m_work_time_us = 172, \ - .regdma_s2a_work_time_us = 480, \ - .regdma_m2a_work_time_us = 278, \ - .regdma_a2s_work_time_us = 382, \ - .regdma_rf_on_work_time_us = 70, \ - .regdma_rf_off_work_time_us = 23, \ + .regdma_s2m_work_time_us = 275, \ + .regdma_s2a_work_time_us = 587, \ + .regdma_m2a_work_time_us = 320, \ + .regdma_a2s_work_time_us = 494, \ + .regdma_rf_on_work_time_us = 60, \ + .regdma_rf_off_work_time_us = 25, \ .xtal_wait_stable_time_us = 250, \ .pll_wait_stable_time_us = 300 \ } \ diff --git a/components/esp_hw_support/port/esp32h21/esp_cpu_intr.c b/components/esp_hw_support/port/esp32h21/esp_cpu_intr.c index 79769f6018a2..e4dddd54cacb 100644 --- a/components/esp_hw_support/port/esp32h21/esp_cpu_intr.c +++ b/components/esp_hw_support/port/esp32h21/esp_cpu_intr.c @@ -10,13 +10,11 @@ void esp_cpu_intr_get_desc(int core_id, int intr_num, esp_cpu_intr_desc_t *intr_desc_ret) { /* On the ESP32-H21, interrupt: - * - 1 is for Wi-Fi * - 6 for "permanently disabled interrupt" * * Interrupts 3, 4 and 7 are unavailable for PULP CPU as they are bound to Core-Local Interrupts (CLINT) */ - //TODO: [ESP32H21] IDF-11537 - const uint32_t rsvd_mask = BIT(1) | BIT(3) | BIT(4) | BIT(6) | BIT(7); + const uint32_t rsvd_mask = BIT(3) | BIT(4) | BIT(6) | BIT(7); intr_desc_ret->priority = 1; intr_desc_ret->type = ESP_CPU_INTR_TYPE_NA; diff --git a/components/esp_hw_support/power_supply/brownout.c b/components/esp_hw_support/power_supply/brownout.c index aa20d8c46ca7..d2b73df4d818 100644 --- a/components/esp_hw_support/power_supply/brownout.c +++ b/components/esp_hw_support/power_supply/brownout.c @@ -91,7 +91,8 @@ void esp_brownout_init(void) #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C2 rtc_isr_register(rtc_brownout_isr_handler, NULL, RTC_CNTL_BROWN_OUT_INT_ENA_M, RTC_INTR_FLAG_IRAM); #else - esp_intr_alloc_intrstatus(power_supply_periph_signal.irq, ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_SHARED, (uint32_t)brownout_ll_intr_get_status_reg(), BROWNOUT_DETECTOR_LL_INTERRUPT_MASK, &rtc_brownout_isr_handler, NULL, NULL); + intr_handle_t bod_intr; + esp_intr_alloc_intrstatus(power_supply_periph_signal.irq, ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_SHARED, (uint32_t)brownout_ll_intr_get_status_reg(), BROWNOUT_DETECTOR_LL_INTERRUPT_MASK, &rtc_brownout_isr_handler, NULL, &bod_intr); #endif brownout_ll_intr_enable(true); diff --git a/components/esp_hw_support/power_supply/include/esp_private/vbat.h b/components/esp_hw_support/power_supply/include/esp_private/vbat.h new file mode 100644 index 000000000000..bfba630a2b22 --- /dev/null +++ b/components/esp_hw_support/power_supply/include/esp_private/vbat.h @@ -0,0 +1,25 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Initialize the VBAT (RTC Backup Battery) management system. + * + * @return + * - ESP_OK: Initialization was successful. + */ +esp_err_t esp_vbat_init(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hw_support/power_supply/port/esp32/Kconfig.bod b/components/esp_hw_support/power_supply/port/esp32/Kconfig.bod deleted file mode 100644 index b79c97eb6b11..000000000000 --- a/components/esp_hw_support/power_supply/port/esp32/Kconfig.bod +++ /dev/null @@ -1,64 +0,0 @@ -menu "Brownout Detector" - - config ESP_BROWNOUT_DET - bool "Hardware brownout detect & reset" - depends on !IDF_ENV_FPGA - default y - help - The ESP has a built-in brownout detector which can detect if the voltage is lower than - a specific value. If this happens, it will reset the chip in order to prevent unintended - behaviour. - - choice ESP_BROWNOUT_DET_LVL_SEL - prompt "Brownout voltage level" - depends on ESP_BROWNOUT_DET - default ESP_BROWNOUT_DET_LVL_SEL_0 - help - The brownout detector will reset the chip when the supply voltage is approximately - below this level. Note that there may be some variation of brownout voltage level - between each ESP chip. - - #The voltage levels here are estimates, more work needs to be done to figure out the exact voltages - #of the brownout threshold levels. - config ESP_BROWNOUT_DET_LVL_SEL_0 - bool "2.43V +/- 0.05" - config ESP_BROWNOUT_DET_LVL_SEL_1 - bool "2.48V +/- 0.05" - config ESP_BROWNOUT_DET_LVL_SEL_2 - bool "2.58V +/- 0.05" - config ESP_BROWNOUT_DET_LVL_SEL_3 - bool "2.62V +/- 0.05" - config ESP_BROWNOUT_DET_LVL_SEL_4 - bool "2.67V +/- 0.05" - config ESP_BROWNOUT_DET_LVL_SEL_5 - bool "2.70V +/- 0.05" - config ESP_BROWNOUT_DET_LVL_SEL_6 - bool "2.77V +/- 0.05" - config ESP_BROWNOUT_DET_LVL_SEL_7 - bool "2.80V +/- 0.05" - endchoice - - config ESP_BROWNOUT_DET_LVL - int - default 0 if ESP_BROWNOUT_DET_LVL_SEL_0 - default 1 if ESP_BROWNOUT_DET_LVL_SEL_1 - default 2 if ESP_BROWNOUT_DET_LVL_SEL_2 - default 3 if ESP_BROWNOUT_DET_LVL_SEL_3 - default 4 if ESP_BROWNOUT_DET_LVL_SEL_4 - default 5 if ESP_BROWNOUT_DET_LVL_SEL_5 - default 6 if ESP_BROWNOUT_DET_LVL_SEL_6 - default 7 if ESP_BROWNOUT_DET_LVL_SEL_7 - - config ESP_BROWNOUT_USE_INTR - bool - default n - help - This config allows to trigger an interrupt when brownout detected. Software restart will be done - at the end of the default callback. - Two occasions need to restart the chip with interrupt so far. - (1). For ESP32 version 1, brown-out reset function doesn't work (see ESP32 errata 3.4). - So that we must restart from interrupt. - (2). For special workflow, the chip needs do more things instead of restarting directly. This part - needs to be done in callback function of interrupt. - -endmenu diff --git a/components/esp_hw_support/power_supply/port/esp32/Kconfig.power b/components/esp_hw_support/power_supply/port/esp32/Kconfig.power new file mode 100644 index 000000000000..628b3bfa8db2 --- /dev/null +++ b/components/esp_hw_support/power_supply/port/esp32/Kconfig.power @@ -0,0 +1,68 @@ +menu "Power Supplier" + + menu "Brownout Detector" + + config ESP_BROWNOUT_DET + bool "Hardware brownout detect & reset" + depends on !IDF_ENV_FPGA + default y + help + The ESP has a built-in brownout detector which can detect if the voltage is lower than + a specific value. If this happens, it will reset the chip in order to prevent unintended + behaviour. + + choice ESP_BROWNOUT_DET_LVL_SEL + prompt "Brownout voltage level" + depends on ESP_BROWNOUT_DET + default ESP_BROWNOUT_DET_LVL_SEL_0 + help + The brownout detector will reset the chip when the supply voltage is approximately + below this level. Note that there may be some variation of brownout voltage level + between each ESP chip. + + #The voltage levels here are estimates, more work needs to be done to figure out the exact voltages + #of the brownout threshold levels. + config ESP_BROWNOUT_DET_LVL_SEL_0 + bool "2.43V +/- 0.05" + config ESP_BROWNOUT_DET_LVL_SEL_1 + bool "2.48V +/- 0.05" + config ESP_BROWNOUT_DET_LVL_SEL_2 + bool "2.58V +/- 0.05" + config ESP_BROWNOUT_DET_LVL_SEL_3 + bool "2.62V +/- 0.05" + config ESP_BROWNOUT_DET_LVL_SEL_4 + bool "2.67V +/- 0.05" + config ESP_BROWNOUT_DET_LVL_SEL_5 + bool "2.70V +/- 0.05" + config ESP_BROWNOUT_DET_LVL_SEL_6 + bool "2.77V +/- 0.05" + config ESP_BROWNOUT_DET_LVL_SEL_7 + bool "2.80V +/- 0.05" + endchoice + + config ESP_BROWNOUT_DET_LVL + int + default 0 if ESP_BROWNOUT_DET_LVL_SEL_0 + default 1 if ESP_BROWNOUT_DET_LVL_SEL_1 + default 2 if ESP_BROWNOUT_DET_LVL_SEL_2 + default 3 if ESP_BROWNOUT_DET_LVL_SEL_3 + default 4 if ESP_BROWNOUT_DET_LVL_SEL_4 + default 5 if ESP_BROWNOUT_DET_LVL_SEL_5 + default 6 if ESP_BROWNOUT_DET_LVL_SEL_6 + default 7 if ESP_BROWNOUT_DET_LVL_SEL_7 + + config ESP_BROWNOUT_USE_INTR + bool + default n + help + This config allows to trigger an interrupt when brownout detected. Software restart will be done + at the end of the default callback. + Two occasions need to restart the chip with interrupt so far. + (1). For ESP32 version 1, brown-out reset function doesn't work (see ESP32 errata 3.4). + So that we must restart from interrupt. + (2). For special workflow, the chip needs do more things instead of restarting directly. This part + needs to be done in callback function of interrupt. + + endmenu + +endmenu diff --git a/components/esp_hw_support/power_supply/port/esp32c2/Kconfig.bod b/components/esp_hw_support/power_supply/port/esp32c2/Kconfig.bod deleted file mode 100644 index 0d0fb822e752..000000000000 --- a/components/esp_hw_support/power_supply/port/esp32c2/Kconfig.bod +++ /dev/null @@ -1,55 +0,0 @@ -menu "Brownout Detector" - config ESP_BROWNOUT_DET - bool "Hardware brownout detect & reset" - depends on !IDF_ENV_FPGA - default y - help - The ESP32-C2 has a built-in brownout detector which can detect if the voltage is lower than - a specific value. If this happens, it will reset the chip in order to prevent unintended - behaviour. - - choice ESP_BROWNOUT_DET_LVL_SEL - prompt "Brownout voltage level" - depends on ESP_BROWNOUT_DET - default ESP_BROWNOUT_DET_LVL_SEL_7 - help - The brownout detector will reset the chip when the supply voltage is approximately - below this level. Note that there may be some variation of brownout voltage level - between each chip. - - #The voltage levels here are estimates, more work needs to be done to figure out the exact voltages - #of the brownout threshold levels. - config ESP_BROWNOUT_DET_LVL_SEL_7 - bool "2.51V" - config ESP_BROWNOUT_DET_LVL_SEL_6 - bool "2.64V" - config ESP_BROWNOUT_DET_LVL_SEL_5 - bool "2.76V" - config ESP_BROWNOUT_DET_LVL_SEL_4 - bool "2.92V" - config ESP_BROWNOUT_DET_LVL_SEL_3 - bool "3.10V" - config ESP_BROWNOUT_DET_LVL_SEL_2 - bool "3.27V" - endchoice - - config ESP_BROWNOUT_DET_LVL - int - default 2 if ESP_BROWNOUT_DET_LVL_SEL_2 - default 3 if ESP_BROWNOUT_DET_LVL_SEL_3 - default 4 if ESP_BROWNOUT_DET_LVL_SEL_4 - default 5 if ESP_BROWNOUT_DET_LVL_SEL_5 - default 6 if ESP_BROWNOUT_DET_LVL_SEL_6 - default 7 if ESP_BROWNOUT_DET_LVL_SEL_7 - - config ESP_BROWNOUT_USE_INTR - bool - default n - help - This config allows to trigger an interrupt when brownout detected. Software restart will be done - at the end of the default callback. - This is because for some special workflow, the chip needs do more things when brownout happens - before restart instead of restarting directly. This part needs to be done in callback function - of interrupt. - -endmenu diff --git a/components/esp_hw_support/power_supply/port/esp32c2/Kconfig.power b/components/esp_hw_support/power_supply/port/esp32c2/Kconfig.power new file mode 100644 index 000000000000..a57499977b5f --- /dev/null +++ b/components/esp_hw_support/power_supply/port/esp32c2/Kconfig.power @@ -0,0 +1,59 @@ +menu "Power Supplier" + + menu "Brownout Detector" + config ESP_BROWNOUT_DET + bool "Hardware brownout detect & reset" + depends on !IDF_ENV_FPGA + default y + help + The ESP32-C2 has a built-in brownout detector which can detect if the voltage is lower than + a specific value. If this happens, it will reset the chip in order to prevent unintended + behaviour. + + choice ESP_BROWNOUT_DET_LVL_SEL + prompt "Brownout voltage level" + depends on ESP_BROWNOUT_DET + default ESP_BROWNOUT_DET_LVL_SEL_7 + help + The brownout detector will reset the chip when the supply voltage is approximately + below this level. Note that there may be some variation of brownout voltage level + between each chip. + + #The voltage levels here are estimates, more work needs to be done to figure out the exact voltages + #of the brownout threshold levels. + config ESP_BROWNOUT_DET_LVL_SEL_7 + bool "2.51V" + config ESP_BROWNOUT_DET_LVL_SEL_6 + bool "2.64V" + config ESP_BROWNOUT_DET_LVL_SEL_5 + bool "2.76V" + config ESP_BROWNOUT_DET_LVL_SEL_4 + bool "2.92V" + config ESP_BROWNOUT_DET_LVL_SEL_3 + bool "3.10V" + config ESP_BROWNOUT_DET_LVL_SEL_2 + bool "3.27V" + endchoice + + config ESP_BROWNOUT_DET_LVL + int + default 2 if ESP_BROWNOUT_DET_LVL_SEL_2 + default 3 if ESP_BROWNOUT_DET_LVL_SEL_3 + default 4 if ESP_BROWNOUT_DET_LVL_SEL_4 + default 5 if ESP_BROWNOUT_DET_LVL_SEL_5 + default 6 if ESP_BROWNOUT_DET_LVL_SEL_6 + default 7 if ESP_BROWNOUT_DET_LVL_SEL_7 + + config ESP_BROWNOUT_USE_INTR + bool + default n + help + This config allows to trigger an interrupt when brownout detected. Software restart will be done + at the end of the default callback. + This is because for some special workflow, the chip needs do more things when brownout happens + before restart instead of restarting directly. This part needs to be done in callback function + of interrupt. + + endmenu + +endmenu diff --git a/components/esp_hw_support/power_supply/port/esp32c3/Kconfig.bod b/components/esp_hw_support/power_supply/port/esp32c3/Kconfig.bod deleted file mode 100644 index 19eb8e94d9c0..000000000000 --- a/components/esp_hw_support/power_supply/port/esp32c3/Kconfig.bod +++ /dev/null @@ -1,55 +0,0 @@ -menu "Brownout Detector" - config ESP_BROWNOUT_DET - bool "Hardware brownout detect & reset" - depends on !IDF_ENV_FPGA - default y - help - The ESP32-C3 has a built-in brownout detector which can detect if the voltage is lower than - a specific value. If this happens, it will reset the chip in order to prevent unintended - behaviour. - - choice ESP_BROWNOUT_DET_LVL_SEL - prompt "Brownout voltage level" - depends on ESP_BROWNOUT_DET - default ESP_BROWNOUT_DET_LVL_SEL_7 - help - The brownout detector will reset the chip when the supply voltage is approximately - below this level. Note that there may be some variation of brownout voltage level - between each chip. - - #The voltage levels here are estimates, more work needs to be done to figure out the exact voltages - #of the brownout threshold levels. - config ESP_BROWNOUT_DET_LVL_SEL_7 - bool "2.51V" - config ESP_BROWNOUT_DET_LVL_SEL_6 - bool "2.64V" - config ESP_BROWNOUT_DET_LVL_SEL_5 - bool "2.76V" - config ESP_BROWNOUT_DET_LVL_SEL_4 - bool "2.92V" - config ESP_BROWNOUT_DET_LVL_SEL_3 - bool "3.10V" - config ESP_BROWNOUT_DET_LVL_SEL_2 - bool "3.27V" - endchoice - - config ESP_BROWNOUT_DET_LVL - int - default 2 if ESP_BROWNOUT_DET_LVL_SEL_2 - default 3 if ESP_BROWNOUT_DET_LVL_SEL_3 - default 4 if ESP_BROWNOUT_DET_LVL_SEL_4 - default 5 if ESP_BROWNOUT_DET_LVL_SEL_5 - default 6 if ESP_BROWNOUT_DET_LVL_SEL_6 - default 7 if ESP_BROWNOUT_DET_LVL_SEL_7 - - config ESP_BROWNOUT_USE_INTR - bool - default n - help - This config allows to trigger an interrupt when brownout detected. Software restart will be done - at the end of the default callback. - This is because for some special workflow, the chip needs do more things when brownout happens - before restart instead of restarting directly. This part needs to be done in callback function - of interrupt. - -endmenu diff --git a/components/esp_hw_support/power_supply/port/esp32c3/Kconfig.power b/components/esp_hw_support/power_supply/port/esp32c3/Kconfig.power new file mode 100644 index 000000000000..4b0903f4015b --- /dev/null +++ b/components/esp_hw_support/power_supply/port/esp32c3/Kconfig.power @@ -0,0 +1,59 @@ +menu "Power Supplier" + + menu "Brownout Detector" + config ESP_BROWNOUT_DET + bool "Hardware brownout detect & reset" + depends on !IDF_ENV_FPGA + default y + help + The ESP32-C3 has a built-in brownout detector which can detect if the voltage is lower than + a specific value. If this happens, it will reset the chip in order to prevent unintended + behaviour. + + choice ESP_BROWNOUT_DET_LVL_SEL + prompt "Brownout voltage level" + depends on ESP_BROWNOUT_DET + default ESP_BROWNOUT_DET_LVL_SEL_7 + help + The brownout detector will reset the chip when the supply voltage is approximately + below this level. Note that there may be some variation of brownout voltage level + between each chip. + + #The voltage levels here are estimates, more work needs to be done to figure out the exact voltages + #of the brownout threshold levels. + config ESP_BROWNOUT_DET_LVL_SEL_7 + bool "2.51V" + config ESP_BROWNOUT_DET_LVL_SEL_6 + bool "2.64V" + config ESP_BROWNOUT_DET_LVL_SEL_5 + bool "2.76V" + config ESP_BROWNOUT_DET_LVL_SEL_4 + bool "2.92V" + config ESP_BROWNOUT_DET_LVL_SEL_3 + bool "3.10V" + config ESP_BROWNOUT_DET_LVL_SEL_2 + bool "3.27V" + endchoice + + config ESP_BROWNOUT_DET_LVL + int + default 2 if ESP_BROWNOUT_DET_LVL_SEL_2 + default 3 if ESP_BROWNOUT_DET_LVL_SEL_3 + default 4 if ESP_BROWNOUT_DET_LVL_SEL_4 + default 5 if ESP_BROWNOUT_DET_LVL_SEL_5 + default 6 if ESP_BROWNOUT_DET_LVL_SEL_6 + default 7 if ESP_BROWNOUT_DET_LVL_SEL_7 + + config ESP_BROWNOUT_USE_INTR + bool + default n + help + This config allows to trigger an interrupt when brownout detected. Software restart will be done + at the end of the default callback. + This is because for some special workflow, the chip needs do more things when brownout happens + before restart instead of restarting directly. This part needs to be done in callback function + of interrupt. + + endmenu + +endmenu diff --git a/components/esp_hw_support/power_supply/port/esp32c5/Kconfig.bod b/components/esp_hw_support/power_supply/port/esp32c5/Kconfig.bod deleted file mode 100644 index 4583c6bee3e2..000000000000 --- a/components/esp_hw_support/power_supply/port/esp32c5/Kconfig.bod +++ /dev/null @@ -1,55 +0,0 @@ -menu "Brownout Detector" - config ESP_BROWNOUT_DET - bool "Hardware brownout detect & reset" - depends on !IDF_ENV_FPGA && SOC_BOD_SUPPORTED - default y - help - The ESP32-C5 has a built-in brownout detector which can detect if the voltage is lower than - a specific value. If this happens, it will reset the chip in order to prevent unintended - behaviour. - - choice ESP_BROWNOUT_DET_LVL_SEL - prompt "Brownout voltage level" - depends on ESP_BROWNOUT_DET - default ESP_BROWNOUT_DET_LVL_SEL_7 - help - The brownout detector will reset the chip when the supply voltage is approximately - below this level. Note that there may be some variation of brownout voltage level - between each chip. - - #The voltage levels here are estimates, more work needs to be done to figure out the exact voltages - #of the brownout threshold levels. - config ESP_BROWNOUT_DET_LVL_SEL_7 - bool "2.51V" - config ESP_BROWNOUT_DET_LVL_SEL_6 - bool "2.64V" - config ESP_BROWNOUT_DET_LVL_SEL_5 - bool "2.76V" - config ESP_BROWNOUT_DET_LVL_SEL_4 - bool "2.92V" - config ESP_BROWNOUT_DET_LVL_SEL_3 - bool "3.10V" - config ESP_BROWNOUT_DET_LVL_SEL_2 - bool "3.27V" - endchoice - - config ESP_BROWNOUT_DET_LVL - int - default 2 if ESP_BROWNOUT_DET_LVL_SEL_2 - default 3 if ESP_BROWNOUT_DET_LVL_SEL_3 - default 4 if ESP_BROWNOUT_DET_LVL_SEL_4 - default 5 if ESP_BROWNOUT_DET_LVL_SEL_5 - default 6 if ESP_BROWNOUT_DET_LVL_SEL_6 - default 7 if ESP_BROWNOUT_DET_LVL_SEL_7 - - config ESP_BROWNOUT_USE_INTR - bool - default n - help - This config allows to trigger an interrupt when brownout detected. Software restart will be done - at the end of the default callback. - This is because for some special workflow, the chip needs do more things when brownout happens - before restart instead of restarting directly. This part needs to be done in callback function - of interrupt. - -endmenu diff --git a/components/esp_hw_support/power_supply/port/esp32c5/Kconfig.power b/components/esp_hw_support/power_supply/port/esp32c5/Kconfig.power new file mode 100644 index 000000000000..1bc2552c8b69 --- /dev/null +++ b/components/esp_hw_support/power_supply/port/esp32c5/Kconfig.power @@ -0,0 +1,59 @@ +menu "Power Supplier" + + menu "Brownout Detector" + config ESP_BROWNOUT_DET + bool "Hardware brownout detect & reset" + depends on !IDF_ENV_FPGA + default y + help + The ESP32-C5 has a built-in brownout detector which can detect if the voltage is lower than + a specific value. If this happens, it will reset the chip in order to prevent unintended + behaviour. + + choice ESP_BROWNOUT_DET_LVL_SEL + prompt "Brownout voltage level" + depends on ESP_BROWNOUT_DET + default ESP_BROWNOUT_DET_LVL_SEL_7 + help + The brownout detector will reset the chip when the supply voltage is approximately + below this level. Note that there may be some variation of brownout voltage level + between each chip. + + #The voltage levels here are estimates, more work needs to be done to figure out the exact voltages + #of the brownout threshold levels. + config ESP_BROWNOUT_DET_LVL_SEL_7 + bool "2.51V" + config ESP_BROWNOUT_DET_LVL_SEL_6 + bool "2.64V" + config ESP_BROWNOUT_DET_LVL_SEL_5 + bool "2.76V" + config ESP_BROWNOUT_DET_LVL_SEL_4 + bool "2.92V" + config ESP_BROWNOUT_DET_LVL_SEL_3 + bool "3.10V" + config ESP_BROWNOUT_DET_LVL_SEL_2 + bool "3.27V" + endchoice + + config ESP_BROWNOUT_DET_LVL + int + default 2 if ESP_BROWNOUT_DET_LVL_SEL_2 + default 3 if ESP_BROWNOUT_DET_LVL_SEL_3 + default 4 if ESP_BROWNOUT_DET_LVL_SEL_4 + default 5 if ESP_BROWNOUT_DET_LVL_SEL_5 + default 6 if ESP_BROWNOUT_DET_LVL_SEL_6 + default 7 if ESP_BROWNOUT_DET_LVL_SEL_7 + + config ESP_BROWNOUT_USE_INTR + bool + default n + help + This config allows to trigger an interrupt when brownout detected. Software restart will be done + at the end of the default callback. + This is because for some special workflow, the chip needs do more things when brownout happens + before restart instead of restarting directly. This part needs to be done in callback function + of interrupt. + + endmenu + +endmenu diff --git a/components/esp_hw_support/power_supply/port/esp32c6/Kconfig.bod b/components/esp_hw_support/power_supply/port/esp32c6/Kconfig.bod deleted file mode 100644 index 5c3d440e837f..000000000000 --- a/components/esp_hw_support/power_supply/port/esp32c6/Kconfig.bod +++ /dev/null @@ -1,55 +0,0 @@ -menu "Brownout Detector" - config ESP_BROWNOUT_DET - bool "Hardware brownout detect & reset" - depends on !IDF_ENV_FPGA - default y - help - The ESP32-C6 has a built-in brownout detector which can detect if the voltage is lower than - a specific value. If this happens, it will reset the chip in order to prevent unintended - behaviour. - - choice ESP_BROWNOUT_DET_LVL_SEL - prompt "Brownout voltage level" - depends on ESP_BROWNOUT_DET - default ESP_BROWNOUT_DET_LVL_SEL_7 - help - The brownout detector will reset the chip when the supply voltage is approximately - below this level. Note that there may be some variation of brownout voltage level - between each chip. - - #The voltage levels here are estimates, more work needs to be done to figure out the exact voltages - #of the brownout threshold levels. - config ESP_BROWNOUT_DET_LVL_SEL_7 - bool "2.51V" - config ESP_BROWNOUT_DET_LVL_SEL_6 - bool "2.64V" - config ESP_BROWNOUT_DET_LVL_SEL_5 - bool "2.76V" - config ESP_BROWNOUT_DET_LVL_SEL_4 - bool "2.92V" - config ESP_BROWNOUT_DET_LVL_SEL_3 - bool "3.10V" - config ESP_BROWNOUT_DET_LVL_SEL_2 - bool "3.27V" - endchoice - - config ESP_BROWNOUT_DET_LVL - int - default 2 if ESP_BROWNOUT_DET_LVL_SEL_2 - default 3 if ESP_BROWNOUT_DET_LVL_SEL_3 - default 4 if ESP_BROWNOUT_DET_LVL_SEL_4 - default 5 if ESP_BROWNOUT_DET_LVL_SEL_5 - default 6 if ESP_BROWNOUT_DET_LVL_SEL_6 - default 7 if ESP_BROWNOUT_DET_LVL_SEL_7 - - config ESP_BROWNOUT_USE_INTR - bool - default n - help - This config allows to trigger an interrupt when brownout detected. Software restart will be done - at the end of the default callback. - This is because for some special workflow, the chip needs do more things when brownout happens - before restart instead of restarting directly. This part needs to be done in callback function - of interrupt. - -endmenu diff --git a/components/esp_hw_support/power_supply/port/esp32c6/Kconfig.power b/components/esp_hw_support/power_supply/port/esp32c6/Kconfig.power new file mode 100644 index 000000000000..cccc74909360 --- /dev/null +++ b/components/esp_hw_support/power_supply/port/esp32c6/Kconfig.power @@ -0,0 +1,59 @@ +menu "Power Supplier" + + menu "Brownout Detector" + config ESP_BROWNOUT_DET + bool "Hardware brownout detect & reset" + depends on !IDF_ENV_FPGA + default y + help + The ESP32-C6 has a built-in brownout detector which can detect if the voltage is lower than + a specific value. If this happens, it will reset the chip in order to prevent unintended + behaviour. + + choice ESP_BROWNOUT_DET_LVL_SEL + prompt "Brownout voltage level" + depends on ESP_BROWNOUT_DET + default ESP_BROWNOUT_DET_LVL_SEL_7 + help + The brownout detector will reset the chip when the supply voltage is approximately + below this level. Note that there may be some variation of brownout voltage level + between each chip. + + #The voltage levels here are estimates, more work needs to be done to figure out the exact voltages + #of the brownout threshold levels. + config ESP_BROWNOUT_DET_LVL_SEL_7 + bool "2.51V" + config ESP_BROWNOUT_DET_LVL_SEL_6 + bool "2.64V" + config ESP_BROWNOUT_DET_LVL_SEL_5 + bool "2.76V" + config ESP_BROWNOUT_DET_LVL_SEL_4 + bool "2.92V" + config ESP_BROWNOUT_DET_LVL_SEL_3 + bool "3.10V" + config ESP_BROWNOUT_DET_LVL_SEL_2 + bool "3.27V" + endchoice + + config ESP_BROWNOUT_DET_LVL + int + default 2 if ESP_BROWNOUT_DET_LVL_SEL_2 + default 3 if ESP_BROWNOUT_DET_LVL_SEL_3 + default 4 if ESP_BROWNOUT_DET_LVL_SEL_4 + default 5 if ESP_BROWNOUT_DET_LVL_SEL_5 + default 6 if ESP_BROWNOUT_DET_LVL_SEL_6 + default 7 if ESP_BROWNOUT_DET_LVL_SEL_7 + + config ESP_BROWNOUT_USE_INTR + bool + default n + help + This config allows to trigger an interrupt when brownout detected. Software restart will be done + at the end of the default callback. + This is because for some special workflow, the chip needs do more things when brownout happens + before restart instead of restarting directly. This part needs to be done in callback function + of interrupt. + + endmenu + +endmenu diff --git a/components/esp_hw_support/power_supply/port/esp32c61/Kconfig.bod b/components/esp_hw_support/power_supply/port/esp32c61/Kconfig.bod deleted file mode 100644 index f1b083e18a2f..000000000000 --- a/components/esp_hw_support/power_supply/port/esp32c61/Kconfig.bod +++ /dev/null @@ -1,55 +0,0 @@ -menu "Brownout Detector" - config ESP_BROWNOUT_DET - bool "Hardware brownout detect & reset" - depends on !IDF_ENV_FPGA - default y - help - The ESP32-C61 has a built-in brownout detector which can detect if the voltage is lower than - a specific value. If this happens, it will reset the chip in order to prevent unintended - behaviour. - - choice ESP_BROWNOUT_DET_LVL_SEL - prompt "Brownout voltage level" - depends on ESP_BROWNOUT_DET - default ESP_BROWNOUT_DET_LVL_SEL_7 - help - The brownout detector will reset the chip when the supply voltage is approximately - below this level. Note that there may be some variation of brownout voltage level - between each chip. - - #The voltage levels here are estimates, more work needs to be done to figure out the exact voltages - #of the brownout threshold levels. - config ESP_BROWNOUT_DET_LVL_SEL_7 - bool "2.51V" - config ESP_BROWNOUT_DET_LVL_SEL_6 - bool "2.64V" - config ESP_BROWNOUT_DET_LVL_SEL_5 - bool "2.76V" - config ESP_BROWNOUT_DET_LVL_SEL_4 - bool "2.92V" - config ESP_BROWNOUT_DET_LVL_SEL_3 - bool "3.10V" - config ESP_BROWNOUT_DET_LVL_SEL_2 - bool "3.27V" - endchoice - - config ESP_BROWNOUT_DET_LVL - int - default 2 if ESP_BROWNOUT_DET_LVL_SEL_2 - default 3 if ESP_BROWNOUT_DET_LVL_SEL_3 - default 4 if ESP_BROWNOUT_DET_LVL_SEL_4 - default 5 if ESP_BROWNOUT_DET_LVL_SEL_5 - default 6 if ESP_BROWNOUT_DET_LVL_SEL_6 - default 7 if ESP_BROWNOUT_DET_LVL_SEL_7 - - config ESP_BROWNOUT_USE_INTR - bool - default n - help - This config allows to trigger an interrupt when brownout detected. Software restart will be done - at the end of the default callback. - This is because for some special workflow, the chip needs do more things when brownout happens - before restart instead of restarting directly. This part needs to be done in callback function - of interrupt. - -endmenu diff --git a/components/esp_hw_support/power_supply/port/esp32c61/Kconfig.power b/components/esp_hw_support/power_supply/port/esp32c61/Kconfig.power new file mode 100644 index 000000000000..50291ad62666 --- /dev/null +++ b/components/esp_hw_support/power_supply/port/esp32c61/Kconfig.power @@ -0,0 +1,59 @@ +menu "Power Supplier" + + menu "Brownout Detector" + config ESP_BROWNOUT_DET + bool "Hardware brownout detect & reset" + depends on !IDF_ENV_FPGA + default y + help + The ESP32-C61 has a built-in brownout detector which can detect if the voltage is lower than + a specific value. If this happens, it will reset the chip in order to prevent unintended + behaviour. + + choice ESP_BROWNOUT_DET_LVL_SEL + prompt "Brownout voltage level" + depends on ESP_BROWNOUT_DET + default ESP_BROWNOUT_DET_LVL_SEL_7 + help + The brownout detector will reset the chip when the supply voltage is approximately + below this level. Note that there may be some variation of brownout voltage level + between each chip. + + #The voltage levels here are estimates, more work needs to be done to figure out the exact voltages + #of the brownout threshold levels. + config ESP_BROWNOUT_DET_LVL_SEL_7 + bool "2.51V" + config ESP_BROWNOUT_DET_LVL_SEL_6 + bool "2.64V" + config ESP_BROWNOUT_DET_LVL_SEL_5 + bool "2.76V" + config ESP_BROWNOUT_DET_LVL_SEL_4 + bool "2.92V" + config ESP_BROWNOUT_DET_LVL_SEL_3 + bool "3.10V" + config ESP_BROWNOUT_DET_LVL_SEL_2 + bool "3.27V" + endchoice + + config ESP_BROWNOUT_DET_LVL + int + default 2 if ESP_BROWNOUT_DET_LVL_SEL_2 + default 3 if ESP_BROWNOUT_DET_LVL_SEL_3 + default 4 if ESP_BROWNOUT_DET_LVL_SEL_4 + default 5 if ESP_BROWNOUT_DET_LVL_SEL_5 + default 6 if ESP_BROWNOUT_DET_LVL_SEL_6 + default 7 if ESP_BROWNOUT_DET_LVL_SEL_7 + + config ESP_BROWNOUT_USE_INTR + bool + default n + help + This config allows to trigger an interrupt when brownout detected. Software restart will be done + at the end of the default callback. + This is because for some special workflow, the chip needs do more things when brownout happens + before restart instead of restarting directly. This part needs to be done in callback function + of interrupt. + + endmenu + +endmenu diff --git a/components/esp_hw_support/power_supply/port/esp32h2/Kconfig.bod b/components/esp_hw_support/power_supply/port/esp32h2/Kconfig.bod deleted file mode 100644 index d0a38ee74fa3..000000000000 --- a/components/esp_hw_support/power_supply/port/esp32h2/Kconfig.bod +++ /dev/null @@ -1,61 +0,0 @@ -menu "Brownout Detector" - config ESP_BROWNOUT_DET - bool "Hardware brownout detect & reset" - depends on !IDF_ENV_FPGA - default y - help - The ESP32-H2 has a built-in brownout detector which can detect if the voltage is lower than - a specific value. If this happens, it will reset the chip in order to prevent unintended - behaviour. - - choice ESP_BROWNOUT_DET_LVL_SEL - prompt "Brownout voltage level" - depends on ESP_BROWNOUT_DET - default ESP_BROWNOUT_DET_LVL_SEL_0 - help - The brownout detector will reset the chip when the supply voltage is approximately - below this level. Note that there may be some variation of brownout voltage level - between each chip. - - #The voltage levels here are estimates, more work needs to be done to figure out the exact voltages - #of the brownout threshold levels. - config ESP_BROWNOUT_DET_LVL_SEL_7 - bool "2.94V" - config ESP_BROWNOUT_DET_LVL_SEL_6 - bool "2.88V" - config ESP_BROWNOUT_DET_LVL_SEL_5 - bool "2.83V" - config ESP_BROWNOUT_DET_LVL_SEL_4 - bool "2.78V" - config ESP_BROWNOUT_DET_LVL_SEL_3 - bool "2.73V" - config ESP_BROWNOUT_DET_LVL_SEL_2 - bool "2.67V" - config ESP_BROWNOUT_DET_LVL_SEL_1 - bool "2.62V" - config ESP_BROWNOUT_DET_LVL_SEL_0 - bool "2.57V" - endchoice - - config ESP_BROWNOUT_DET_LVL - int - default 0 if ESP_BROWNOUT_DET_LVL_SEL_0 - default 1 if ESP_BROWNOUT_DET_LVL_SEL_1 - default 2 if ESP_BROWNOUT_DET_LVL_SEL_2 - default 3 if ESP_BROWNOUT_DET_LVL_SEL_3 - default 4 if ESP_BROWNOUT_DET_LVL_SEL_4 - default 5 if ESP_BROWNOUT_DET_LVL_SEL_5 - default 6 if ESP_BROWNOUT_DET_LVL_SEL_6 - default 7 if ESP_BROWNOUT_DET_LVL_SEL_7 - - config ESP_BROWNOUT_USE_INTR - bool - default n - help - This config allows to trigger an interrupt when brownout detected. Software restart will be done - at the end of the default callback. - This is because for some special workflow, the chip needs do more things when brownout happens - before restart instead of restarting directly. This part needs to be done in callback function - of interrupt. - -endmenu diff --git a/components/esp_hw_support/power_supply/port/esp32h2/Kconfig.power b/components/esp_hw_support/power_supply/port/esp32h2/Kconfig.power new file mode 100644 index 000000000000..579ae69d191c --- /dev/null +++ b/components/esp_hw_support/power_supply/port/esp32h2/Kconfig.power @@ -0,0 +1,215 @@ +menu "Power Supplier" + + menu "Brownout Detector" + config ESP_BROWNOUT_DET + bool "Hardware brownout detect & reset" + depends on !IDF_ENV_FPGA + default y + help + The ESP32-H2 has a built-in brownout detector which can detect if the voltage is lower than + a specific value. If this happens, it will reset the chip in order to prevent unintended + behaviour. + + choice ESP_BROWNOUT_DET_LVL_SEL + prompt "Brownout voltage level" + depends on ESP_BROWNOUT_DET + default ESP_BROWNOUT_DET_LVL_SEL_0 + help + The brownout detector will reset the chip when the supply voltage is approximately + below this level. Note that there may be some variation of brownout voltage level + between each chip. + + #The voltage levels here are estimates, more work needs to be done to figure out the exact voltages + #of the brownout threshold levels. + config ESP_BROWNOUT_DET_LVL_SEL_7 + bool "2.94V" + config ESP_BROWNOUT_DET_LVL_SEL_6 + bool "2.88V" + config ESP_BROWNOUT_DET_LVL_SEL_5 + bool "2.83V" + config ESP_BROWNOUT_DET_LVL_SEL_4 + bool "2.78V" + config ESP_BROWNOUT_DET_LVL_SEL_3 + bool "2.73V" + config ESP_BROWNOUT_DET_LVL_SEL_2 + bool "2.67V" + config ESP_BROWNOUT_DET_LVL_SEL_1 + bool "2.62V" + config ESP_BROWNOUT_DET_LVL_SEL_0 + bool "2.57V" + endchoice + + config ESP_BROWNOUT_DET_LVL + int + default 0 if ESP_BROWNOUT_DET_LVL_SEL_0 + default 1 if ESP_BROWNOUT_DET_LVL_SEL_1 + default 2 if ESP_BROWNOUT_DET_LVL_SEL_2 + default 3 if ESP_BROWNOUT_DET_LVL_SEL_3 + default 4 if ESP_BROWNOUT_DET_LVL_SEL_4 + default 5 if ESP_BROWNOUT_DET_LVL_SEL_5 + default 6 if ESP_BROWNOUT_DET_LVL_SEL_6 + default 7 if ESP_BROWNOUT_DET_LVL_SEL_7 + + config ESP_BROWNOUT_USE_INTR + bool + default n + help + This config allows to trigger an interrupt when brownout detected. Software restart will be done + at the end of the default callback. + This is because for some special workflow, the chip needs do more things when brownout happens + before restart instead of restarting directly. This part needs to be done in callback function + of interrupt. + + endmenu + + + menu "RTC Backup Battery" + + config ESP_VBAT_INIT_AUTO + bool "Enable VBAT power supply for RTC battery" + default n + depends on SOC_VBAT_SUPPORTED + help + Enable this option to allow the use of a button cell battery to power the RTC (Real-Time Clock) domain. + When this option is enabled, the hardware will configure VBAT as the power supply source for the RTC. + + - Ensure a compatible battery (2.5V ~ 3.6V) is connected to the VBAT pin. + - The VBAT battery provides power to retain RTC state and keep low-power peripherals active + during deep sleep. + - When this option is disabled, the RTC battery input (VBAT) must not be left floating. + + config ESP_VBAT_USE_RECHARGEABLE_BATTERY + bool "The battery for RTC battery is a rechargeable battery" + default n + depends on ESP_VBAT_INIT_AUTO + help + Select this option if the RTC backup battery used in your design is a rechargeable battery. + + When enabled, the system will configure the RTC battery management circuitry to operate + in a mode suitable for charging a rechargeable battery. This includes enabling + charging current regulation via resistor and voltage monitoring to ensure safe and efficient charging. + + Use this option carefully to avoid damage to non-rechargeable batteries. + + choice ESP_VBAT_DET_LVL_LOW_SEL + prompt "VBAT start charging voltage level" + default ESP_VBAT_DET_LVL_LOW_SEL_2 + depends on ESP_VBAT_USE_RECHARGEABLE_BATTERY + help + The brownout detector will start charging when the supply voltage drops below the selected threshold. + This ensures that the power supply is maintained at a stable level. + + config ESP_VBAT_DET_LVL_LOW_SEL_7 + bool "2.94V" + config ESP_VBAT_DET_LVL_LOW_SEL_6 + bool "2.88V" + config ESP_VBAT_DET_LVL_LOW_SEL_5 + bool "2.83V" + config ESP_VBAT_DET_LVL_LOW_SEL_4 + bool "2.78V" + config ESP_VBAT_DET_LVL_LOW_SEL_3 + bool "2.73V" + config ESP_VBAT_DET_LVL_LOW_SEL_2 + bool "2.67V" + config ESP_VBAT_DET_LVL_LOW_SEL_1 + bool "2.62V" + config ESP_VBAT_DET_LVL_LOW_SEL_0 + bool "2.57V" + endchoice + + choice ESP_VBAT_DET_LVL_HIGH_SEL + prompt "VBAT stop charging voltage level" + default ESP_VBAT_DET_LVL_HIGH_SEL_7 + depends on ESP_VBAT_USE_RECHARGEABLE_BATTERY + help + The brownout detector will stop charging when the supply voltage arrives the selected threshold. + + config ESP_VBAT_DET_LVL_HIGH_SEL_7 + bool "2.94V" + config ESP_VBAT_DET_LVL_HIGH_SEL_6 + bool "2.88V" + config ESP_VBAT_DET_LVL_HIGH_SEL_5 + bool "2.83V" + config ESP_VBAT_DET_LVL_HIGH_SEL_4 + bool "2.78V" + config ESP_VBAT_DET_LVL_HIGH_SEL_3 + bool "2.73V" + config ESP_VBAT_DET_LVL_HIGH_SEL_2 + bool "2.67V" + config ESP_VBAT_DET_LVL_HIGH_SEL_1 + bool "2.62V" + config ESP_VBAT_DET_LVL_HIGH_SEL_0 + bool "2.57V" + endchoice + + choice ESP_VBAT_BROWNOUT_DET_LVL_SEL + prompt "VBAT brownout voltage level" + default ESP_VBAT_BROWNOUT_DET_LVL_SEL_0 + depends on ESP_VBAT_INIT_AUTO + help + The brownout detector will git a brownout signal when vbat brownout detected. + + config ESP_VBAT_BROWNOUT_DET_LVL_SEL_7 + bool "2.94V" + config ESP_VBAT_BROWNOUT_DET_LVL_SEL_6 + bool "2.88V" + config ESP_VBAT_BROWNOUT_DET_LVL_SEL_5 + bool "2.83V" + config ESP_VBAT_BROWNOUT_DET_LVL_SEL_4 + bool "2.78V" + config ESP_VBAT_BROWNOUT_DET_LVL_SEL_3 + bool "2.73V" + config ESP_VBAT_BROWNOUT_DET_LVL_SEL_2 + bool "2.67V" + config ESP_VBAT_BROWNOUT_DET_LVL_SEL_1 + bool "2.62V" + config ESP_VBAT_BROWNOUT_DET_LVL_SEL_0 + bool "2.57V" + endchoice + + config ESP_VBAT_DET_LVL_LOW + int + depends on ESP_VBAT_USE_RECHARGEABLE_BATTERY + default 0 if ESP_VBAT_DET_LVL_LOW_SEL_0 + default 1 if ESP_VBAT_DET_LVL_LOW_SEL_1 + default 2 if ESP_VBAT_DET_LVL_LOW_SEL_2 + default 3 if ESP_VBAT_DET_LVL_LOW_SEL_3 + default 4 if ESP_VBAT_DET_LVL_LOW_SEL_4 + default 5 if ESP_VBAT_DET_LVL_LOW_SEL_5 + default 6 if ESP_VBAT_DET_LVL_LOW_SEL_6 + default 7 if ESP_VBAT_DET_LVL_LOW_SEL_7 + + config ESP_VBAT_DET_LVL_HIGH + int + depends on ESP_VBAT_USE_RECHARGEABLE_BATTERY + default 0 if ESP_VBAT_DET_LVL_HIGH_SEL_0 + default 1 if ESP_VBAT_DET_LVL_HIGH_SEL_1 + default 2 if ESP_VBAT_DET_LVL_HIGH_SEL_2 + default 3 if ESP_VBAT_DET_LVL_HIGH_SEL_3 + default 4 if ESP_VBAT_DET_LVL_HIGH_SEL_4 + default 5 if ESP_VBAT_DET_LVL_HIGH_SEL_5 + default 6 if ESP_VBAT_DET_LVL_HIGH_SEL_6 + default 7 if ESP_VBAT_DET_LVL_HIGH_SEL_7 + + config ESP_VBAT_BROWNOUT_DET_LVL + int + default 0 if ESP_VBAT_BROWNOUT_DET_LVL_SEL_0 + default 1 if ESP_VBAT_BROWNOUT_DET_LVL_SEL_1 + default 2 if ESP_VBAT_BROWNOUT_DET_LVL_SEL_2 + default 3 if ESP_VBAT_BROWNOUT_DET_LVL_SEL_3 + default 4 if ESP_VBAT_BROWNOUT_DET_LVL_SEL_4 + default 5 if ESP_VBAT_BROWNOUT_DET_LVL_SEL_5 + default 6 if ESP_VBAT_BROWNOUT_DET_LVL_SEL_6 + default 7 if ESP_VBAT_BROWNOUT_DET_LVL_SEL_7 + + config ESP_VBAT_CHARGER_CIRCUIT_RESISTOR_VAL + int "vbat charger circuit resistor value (ohms), should be multiple of 500" + depends on ESP_VBAT_USE_RECHARGEABLE_BATTERY + range 1000 8500 + default 1000 + help + The resistor value of charger circuit. + + endmenu + +endmenu diff --git a/components/esp_hw_support/power_supply/port/esp32h21/Kconfig.bod b/components/esp_hw_support/power_supply/port/esp32h21/Kconfig.bod deleted file mode 100644 index 61eca9bba617..000000000000 --- a/components/esp_hw_support/power_supply/port/esp32h21/Kconfig.bod +++ /dev/null @@ -1,61 +0,0 @@ -menu "Brownout Detector" - config ESP_BROWNOUT_DET - bool "Hardware brownout detect & reset" - depends on !IDF_ENV_FPGA - default y - help - The ESP32-H21 has a built-in brownout detector which can detect if the voltage is lower than - a specific value. If this happens, it will reset the chip in order to prevent unintended - behaviour. - - choice ESP_BROWNOUT_DET_LVL_SEL - prompt "Brownout voltage level" - depends on ESP_BROWNOUT_DET - default ESP_BROWNOUT_DET_LVL_SEL_0 - help - The brownout detector will reset the chip when the supply voltage is approximately - below this level. Note that there may be some variation of brownout voltage level - between each chip. - - #The voltage levels here are estimates, more work needs to be done to figure out the exact voltages - #of the brownout threshold levels. - config ESP_BROWNOUT_DET_LVL_SEL_7 - bool "2.94V" - config ESP_BROWNOUT_DET_LVL_SEL_6 - bool "2.88V" - config ESP_BROWNOUT_DET_LVL_SEL_5 - bool "2.83V" - config ESP_BROWNOUT_DET_LVL_SEL_4 - bool "2.78V" - config ESP_BROWNOUT_DET_LVL_SEL_3 - bool "2.73V" - config ESP_BROWNOUT_DET_LVL_SEL_2 - bool "2.67V" - config ESP_BROWNOUT_DET_LVL_SEL_1 - bool "2.62V" - config ESP_BROWNOUT_DET_LVL_SEL_0 - bool "2.57V" - endchoice - - config ESP_BROWNOUT_DET_LVL - int - default 0 if ESP_BROWNOUT_DET_LVL_SEL_0 - default 1 if ESP_BROWNOUT_DET_LVL_SEL_1 - default 2 if ESP_BROWNOUT_DET_LVL_SEL_2 - default 3 if ESP_BROWNOUT_DET_LVL_SEL_3 - default 4 if ESP_BROWNOUT_DET_LVL_SEL_4 - default 5 if ESP_BROWNOUT_DET_LVL_SEL_5 - default 6 if ESP_BROWNOUT_DET_LVL_SEL_6 - default 7 if ESP_BROWNOUT_DET_LVL_SEL_7 - - config ESP_BROWNOUT_USE_INTR - bool - default n - help - This config allows to trigger an interrupt when brownout detected. Software restart will be done - at the end of the default callback. - This is because for some special workflow, the chip needs do more things when brownout happens - before restart instead of restarting directly. This part needs to be done in callback function - of interrupt. - -endmenu diff --git a/components/esp_hw_support/power_supply/port/esp32h21/Kconfig.power b/components/esp_hw_support/power_supply/port/esp32h21/Kconfig.power new file mode 100644 index 000000000000..d01bbdfe721d --- /dev/null +++ b/components/esp_hw_support/power_supply/port/esp32h21/Kconfig.power @@ -0,0 +1,65 @@ +menu "Power Supplier" + + menu "Brownout Detector" + config ESP_BROWNOUT_DET + bool "Hardware brownout detect & reset" + depends on !IDF_ENV_FPGA + default y + help + The ESP32-H21 has a built-in brownout detector which can detect if the voltage is lower than + a specific value. If this happens, it will reset the chip in order to prevent unintended + behaviour. + + choice ESP_BROWNOUT_DET_LVL_SEL + prompt "Brownout voltage level" + depends on ESP_BROWNOUT_DET + default ESP_BROWNOUT_DET_LVL_SEL_0 + help + The brownout detector will reset the chip when the supply voltage is approximately + below this level. Note that there may be some variation of brownout voltage level + between each chip. + + #The voltage levels here are estimates, more work needs to be done to figure out the exact voltages + #of the brownout threshold levels. + config ESP_BROWNOUT_DET_LVL_SEL_7 + bool "2.94V" + config ESP_BROWNOUT_DET_LVL_SEL_6 + bool "2.88V" + config ESP_BROWNOUT_DET_LVL_SEL_5 + bool "2.83V" + config ESP_BROWNOUT_DET_LVL_SEL_4 + bool "2.78V" + config ESP_BROWNOUT_DET_LVL_SEL_3 + bool "2.73V" + config ESP_BROWNOUT_DET_LVL_SEL_2 + bool "2.67V" + config ESP_BROWNOUT_DET_LVL_SEL_1 + bool "2.62V" + config ESP_BROWNOUT_DET_LVL_SEL_0 + bool "2.57V" + endchoice + + config ESP_BROWNOUT_DET_LVL + int + default 0 if ESP_BROWNOUT_DET_LVL_SEL_0 + default 1 if ESP_BROWNOUT_DET_LVL_SEL_1 + default 2 if ESP_BROWNOUT_DET_LVL_SEL_2 + default 3 if ESP_BROWNOUT_DET_LVL_SEL_3 + default 4 if ESP_BROWNOUT_DET_LVL_SEL_4 + default 5 if ESP_BROWNOUT_DET_LVL_SEL_5 + default 6 if ESP_BROWNOUT_DET_LVL_SEL_6 + default 7 if ESP_BROWNOUT_DET_LVL_SEL_7 + + config ESP_BROWNOUT_USE_INTR + bool + default n + help + This config allows to trigger an interrupt when brownout detected. Software restart will be done + at the end of the default callback. + This is because for some special workflow, the chip needs do more things when brownout happens + before restart instead of restarting directly. This part needs to be done in callback function + of interrupt. + + endmenu + +endmenu diff --git a/components/esp_hw_support/power_supply/port/esp32p4/Kconfig.bod b/components/esp_hw_support/power_supply/port/esp32p4/Kconfig.bod deleted file mode 100644 index 14a7a2dc2307..000000000000 --- a/components/esp_hw_support/power_supply/port/esp32p4/Kconfig.bod +++ /dev/null @@ -1,49 +0,0 @@ -menu "Brownout Detector" - config ESP_BROWNOUT_DET - bool "Hardware brownout detect & reset" - depends on !IDF_ENV_FPGA - default y - help - The ESP32-P4 has a built-in brownout detector which can detect if the voltage is lower than - a specific value. If this happens, it will reset the chip in order to prevent unintended - behaviour. - - choice ESP_BROWNOUT_DET_LVL_SEL - prompt "Brownout voltage level" - default ESP_BROWNOUT_DET_LVL_SEL_7 - depends on ESP_BROWNOUT_DET - help - The brownout detector will reset the chip when the supply voltage is approximately - below this level. Note that there may be some variation of brownout voltage level - between each chip. - - Please note that this config is only valid when P4 SOC version is above v1.0. When you are using a - earlier P4 SOC version (v0.x), the brownout value should be fixed around 2.52V and not configurable. - - #The voltage levels here are estimates, more work needs to be done to figure out the exact voltages - #of the brownout threshold levels. - config ESP_BROWNOUT_DET_LVL_SEL_7 - bool "2.6V" - config ESP_BROWNOUT_DET_LVL_SEL_6 - bool "2.52V" - config ESP_BROWNOUT_DET_LVL_SEL_5 - bool "2.42V" - endchoice - - config ESP_BROWNOUT_DET_LVL - int - default 5 if ESP_BROWNOUT_DET_LVL_SEL_5 - default 6 if ESP_BROWNOUT_DET_LVL_SEL_6 - default 7 if ESP_BROWNOUT_DET_LVL_SEL_7 - - config ESP_BROWNOUT_USE_INTR - bool - default n - help - This config allows to trigger an interrupt when brownout detected. Software restart will be done - at the end of the default callback. - This is because for some special workflow, the chip needs do more things when brownout happens - before restart instead of restarting directly. This part needs to be done in callback function - of interrupt. - -endmenu diff --git a/components/esp_hw_support/power_supply/port/esp32p4/Kconfig.power b/components/esp_hw_support/power_supply/port/esp32p4/Kconfig.power new file mode 100644 index 000000000000..2e308de59831 --- /dev/null +++ b/components/esp_hw_support/power_supply/port/esp32p4/Kconfig.power @@ -0,0 +1,159 @@ +menu "Power Supplier" + + menu "Brownout Detector" + + config ESP_BROWNOUT_DET + bool "Hardware brownout detect & reset" + depends on !IDF_ENV_FPGA + default y + help + The ESP32-P4 has a built-in brownout detector which can detect if the voltage is lower than + a specific value. If this happens, it will reset the chip in order to prevent unintended + behaviour. + + choice ESP_BROWNOUT_DET_LVL_SEL + prompt "Brownout voltage level" + default ESP_BROWNOUT_DET_LVL_SEL_7 + depends on ESP_BROWNOUT_DET + help + The brownout detector will reset the chip when the supply voltage is approximately + below this level. Note that there may be some variation of brownout voltage level + between each chip. + + Please note that this config is only valid when P4 SOC version is above v1.0. When you are using a + earlier P4 SOC version (v0.x), the brownout value should be fixed around 2.52V and not configurable. + + #The voltage levels here are estimates, more work needs to be done to figure out the exact voltages + #of the brownout threshold levels. + + config ESP_BROWNOUT_DET_LVL_SEL_7 + bool "2.6V" + config ESP_BROWNOUT_DET_LVL_SEL_6 + bool "2.52V" + config ESP_BROWNOUT_DET_LVL_SEL_5 + bool "2.42V" + endchoice + + config ESP_BROWNOUT_DET_LVL + int + default 5 if ESP_BROWNOUT_DET_LVL_SEL_5 + default 6 if ESP_BROWNOUT_DET_LVL_SEL_6 + default 7 if ESP_BROWNOUT_DET_LVL_SEL_7 + + config ESP_BROWNOUT_USE_INTR + bool + default n + help + This config allows to trigger an interrupt when brownout detected. Software restart will be done + at the end of the default callback. + This is because for some special workflow, the chip needs do more things when brownout happens + before restart instead of restarting directly. This part needs to be done in callback function + of interrupt. + + endmenu + + menu "RTC Backup Battery" + + config ESP_VBAT_INIT_AUTO + bool "Enable VBAT power supply for RTC battery" + default n + depends on SOC_VBAT_SUPPORTED + help + Enable this option to allow the use of a button cell battery to power the RTC (Real-Time Clock) domain. + When this option is enabled, the hardware will configure VBAT as the power supply source for the RTC. + + - Ensure a compatible battery (2.5V ~ 3.6V) is connected to the VBAT pin. + - The VBAT battery provides power to retain RTC state and keep low-power peripherals active + during deep sleep. + - When this option is disabled, the RTC battery input (VBAT) must not be left floating. + + config ESP_VBAT_USE_RECHARGEABLE_BATTERY + bool "The battery for RTC battery is a rechargeable battery" + default n + depends on ESP_VBAT_INIT_AUTO + help + Select this option if the RTC backup battery used in your design is a rechargeable battery. + + When enabled, the system will configure the RTC battery management circuitry to operate + in a mode suitable for charging a rechargeable battery. This includes enabling + charging current regulation via resistor and voltage monitoring to ensure safe and efficient charging. + + Use this option carefully to avoid damage to non-rechargeable batteries. + + choice ESP_VBAT_DET_LVL_LOW_SEL + prompt "VBAT start charging voltage level" + default ESP_VBAT_DET_LVL_LOW_SEL_6 + depends on ESP_VBAT_USE_RECHARGEABLE_BATTERY + help + The brownout detector will start charging when the supply voltage drops below the selected threshold. + This ensures that the power supply is maintained at a stable level. + + config ESP_VBAT_DET_LVL_LOW_SEL_7 + bool "2.6V" + config ESP_VBAT_DET_LVL_LOW_SEL_6 + bool "2.52V" + config ESP_VBAT_DET_LVL_LOW_SEL_5 + bool "2.42V" + endchoice + + choice ESP_VBAT_DET_LVL_HIGH_SEL + prompt "VBAT stop charging voltage level" + default ESP_VBAT_DET_LVL_HIGH_SEL_7 + depends on ESP_VBAT_USE_RECHARGEABLE_BATTERY + help + The brownout detector will stop charging when the supply voltage arrives the selected threshold. + + config ESP_VBAT_DET_LVL_HIGH_SEL_7 + bool "2.6V" + config ESP_VBAT_DET_LVL_HIGH_SEL_6 + bool "2.52V" + config ESP_VBAT_DET_LVL_HIGH_SEL_5 + bool "2.42V" + endchoice + + choice ESP_VBAT_BROWNOUT_DET_LVL_SEL + prompt "VBAT brownout voltage level" + default ESP_VBAT_BROWNOUT_DET_LVL_SEL_5 + depends on ESP_VBAT_INIT_AUTO + help + The brownout detector will git a brownout signal when vbat brownout detected. + + config ESP_VBAT_BROWNOUT_DET_LVL_SEL_7 + bool "2.6V" + config ESP_VBAT_BROWNOUT_DET_LVL_SEL_6 + bool "2.52V" + config ESP_VBAT_BROWNOUT_DET_LVL_SEL_5 + bool "2.42V" + endchoice + + config ESP_VBAT_DET_LVL_LOW + int + depends on ESP_VBAT_USE_RECHARGEABLE_BATTERY + default 5 if ESP_VBAT_DET_LVL_LOW_SEL_5 + default 6 if ESP_VBAT_DET_LVL_LOW_SEL_6 + default 7 if ESP_VBAT_DET_LVL_LOW_SEL_7 + + config ESP_VBAT_DET_LVL_HIGH + int + depends on ESP_VBAT_USE_RECHARGEABLE_BATTERY + default 5 if ESP_VBAT_DET_LVL_HIGH_SEL_5 + default 6 if ESP_VBAT_DET_LVL_HIGH_SEL_6 + default 7 if ESP_VBAT_DET_LVL_HIGH_SEL_7 + + config ESP_VBAT_BROWNOUT_DET_LVL + int + default 5 if ESP_VBAT_BROWNOUT_DET_LVL_SEL_5 + default 6 if ESP_VBAT_BROWNOUT_DET_LVL_SEL_6 + default 7 if ESP_VBAT_BROWNOUT_DET_LVL_SEL_7 + + config ESP_VBAT_CHARGER_CIRCUIT_RESISTOR_VAL + int "vbat charger circuit resistor value (ohms), should be multiple of 500" + depends on ESP_VBAT_USE_RECHARGEABLE_BATTERY + range 1000 8500 + default 1000 + help + The resistor value of charger circuit. + + endmenu + +endmenu diff --git a/components/esp_hw_support/power_supply/port/esp32s2/Kconfig.bod b/components/esp_hw_support/power_supply/port/esp32s2/Kconfig.bod deleted file mode 100644 index d7103f235c1c..000000000000 --- a/components/esp_hw_support/power_supply/port/esp32s2/Kconfig.bod +++ /dev/null @@ -1,59 +0,0 @@ -menu "Brownout Detector" - - config ESP_BROWNOUT_DET - bool "Hardware brownout detect & reset" - depends on !IDF_ENV_FPGA - default y - help - The ESP32-S2 has a built-in brownout detector which can detect if the voltage is lower than - a specific value. If this happens, it will reset the chip in order to prevent unintended - behaviour. - - choice ESP_BROWNOUT_DET_LVL_SEL - prompt "Brownout voltage level" - depends on ESP_BROWNOUT_DET - default ESP_BROWNOUT_DET_LVL_SEL_7 - help - The brownout detector will reset the chip when the supply voltage is approximately - below this level. Note that there may be some variation of brownout voltage level - between each ESP3-S2 chip. - - #The voltage levels here are estimates, more work needs to be done to figure out the exact voltages - #of the brownout threshold levels. - config ESP_BROWNOUT_DET_LVL_SEL_7 - bool "2.44V" - config ESP_BROWNOUT_DET_LVL_SEL_6 - bool "2.56V" - config ESP_BROWNOUT_DET_LVL_SEL_5 - bool "2.67V" - config ESP_BROWNOUT_DET_LVL_SEL_4 - bool "2.84V" - config ESP_BROWNOUT_DET_LVL_SEL_3 - bool "2.98V" - config ESP_BROWNOUT_DET_LVL_SEL_2 - bool "3.19V" - config ESP_BROWNOUT_DET_LVL_SEL_1 - bool "3.30V" - endchoice - - config ESP_BROWNOUT_DET_LVL - int - default 1 if ESP_BROWNOUT_DET_LVL_SEL_1 - default 2 if ESP_BROWNOUT_DET_LVL_SEL_2 - default 3 if ESP_BROWNOUT_DET_LVL_SEL_3 - default 4 if ESP_BROWNOUT_DET_LVL_SEL_4 - default 5 if ESP_BROWNOUT_DET_LVL_SEL_5 - default 6 if ESP_BROWNOUT_DET_LVL_SEL_6 - default 7 if ESP_BROWNOUT_DET_LVL_SEL_7 - - config ESP_BROWNOUT_USE_INTR - bool - default n - help - This config allows to trigger an interrupt when brownout detected. Software restart will be done - at the end of the default callback. - This is because for some special workflow, the chip needs do more things when brownout happens - before restart instead of restarting directly. This part needs to be done in callback function - of interrupt. - -endmenu diff --git a/components/esp_hw_support/power_supply/port/esp32s2/Kconfig.power b/components/esp_hw_support/power_supply/port/esp32s2/Kconfig.power new file mode 100644 index 000000000000..56611086c358 --- /dev/null +++ b/components/esp_hw_support/power_supply/port/esp32s2/Kconfig.power @@ -0,0 +1,63 @@ +menu "Power Supplier" + + menu "Brownout Detector" + + config ESP_BROWNOUT_DET + bool "Hardware brownout detect & reset" + depends on !IDF_ENV_FPGA + default y + help + The ESP32-S2 has a built-in brownout detector which can detect if the voltage is lower than + a specific value. If this happens, it will reset the chip in order to prevent unintended + behaviour. + + choice ESP_BROWNOUT_DET_LVL_SEL + prompt "Brownout voltage level" + depends on ESP_BROWNOUT_DET + default ESP_BROWNOUT_DET_LVL_SEL_7 + help + The brownout detector will reset the chip when the supply voltage is approximately + below this level. Note that there may be some variation of brownout voltage level + between each ESP3-S2 chip. + + #The voltage levels here are estimates, more work needs to be done to figure out the exact voltages + #of the brownout threshold levels. + config ESP_BROWNOUT_DET_LVL_SEL_7 + bool "2.44V" + config ESP_BROWNOUT_DET_LVL_SEL_6 + bool "2.56V" + config ESP_BROWNOUT_DET_LVL_SEL_5 + bool "2.67V" + config ESP_BROWNOUT_DET_LVL_SEL_4 + bool "2.84V" + config ESP_BROWNOUT_DET_LVL_SEL_3 + bool "2.98V" + config ESP_BROWNOUT_DET_LVL_SEL_2 + bool "3.19V" + config ESP_BROWNOUT_DET_LVL_SEL_1 + bool "3.30V" + endchoice + + config ESP_BROWNOUT_DET_LVL + int + default 1 if ESP_BROWNOUT_DET_LVL_SEL_1 + default 2 if ESP_BROWNOUT_DET_LVL_SEL_2 + default 3 if ESP_BROWNOUT_DET_LVL_SEL_3 + default 4 if ESP_BROWNOUT_DET_LVL_SEL_4 + default 5 if ESP_BROWNOUT_DET_LVL_SEL_5 + default 6 if ESP_BROWNOUT_DET_LVL_SEL_6 + default 7 if ESP_BROWNOUT_DET_LVL_SEL_7 + + config ESP_BROWNOUT_USE_INTR + bool + default n + help + This config allows to trigger an interrupt when brownout detected. Software restart will be done + at the end of the default callback. + This is because for some special workflow, the chip needs do more things when brownout happens + before restart instead of restarting directly. This part needs to be done in callback function + of interrupt. + + endmenu + +endmenu diff --git a/components/esp_hw_support/power_supply/port/esp32s3/Kconfig.bod b/components/esp_hw_support/power_supply/port/esp32s3/Kconfig.bod deleted file mode 100644 index 6db64c1147b3..000000000000 --- a/components/esp_hw_support/power_supply/port/esp32s3/Kconfig.bod +++ /dev/null @@ -1,59 +0,0 @@ -menu "Brownout Detector" - - config ESP_BROWNOUT_DET - bool "Hardware brownout detect & reset" - depends on !IDF_ENV_FPGA - default y - help - The ESP32-S3 has a built-in brownout detector which can detect if the voltage is lower than - a specific value. If this happens, it will reset the chip in order to prevent unintended - behaviour. - - choice ESP_BROWNOUT_DET_LVL_SEL - prompt "Brownout voltage level" - depends on ESP_BROWNOUT_DET - default ESP_BROWNOUT_DET_LVL_SEL_7 - help - The brownout detector will reset the chip when the supply voltage is approximately - below this level. Note that there may be some variation of brownout voltage level - between each ESP3-S3 chip. - - #The voltage levels here are estimates, more work needs to be done to figure out the exact voltages - #of the brownout threshold levels. - config ESP_BROWNOUT_DET_LVL_SEL_7 - bool "2.44V" - config ESP_BROWNOUT_DET_LVL_SEL_6 - bool "2.56V" - config ESP_BROWNOUT_DET_LVL_SEL_5 - bool "2.67V" - config ESP_BROWNOUT_DET_LVL_SEL_4 - bool "2.84V" - config ESP_BROWNOUT_DET_LVL_SEL_3 - bool "2.98V" - config ESP_BROWNOUT_DET_LVL_SEL_2 - bool "3.19V" - config ESP_BROWNOUT_DET_LVL_SEL_1 - bool "3.30V" - endchoice - - config ESP_BROWNOUT_DET_LVL - int - default 1 if ESP_BROWNOUT_DET_LVL_SEL_1 - default 2 if ESP_BROWNOUT_DET_LVL_SEL_2 - default 3 if ESP_BROWNOUT_DET_LVL_SEL_3 - default 4 if ESP_BROWNOUT_DET_LVL_SEL_4 - default 5 if ESP_BROWNOUT_DET_LVL_SEL_5 - default 6 if ESP_BROWNOUT_DET_LVL_SEL_6 - default 7 if ESP_BROWNOUT_DET_LVL_SEL_7 - - config ESP_BROWNOUT_USE_INTR - bool - default n - help - This config allows to trigger an interrupt when brownout detected. Software restart will be done - at the end of the default callback. - This is because for some special workflow, the chip needs do more things when brownout happens - before restart instead of restarting directly. This part needs to be done in callback function - of interrupt. - -endmenu diff --git a/components/esp_hw_support/power_supply/port/esp32s3/Kconfig.power b/components/esp_hw_support/power_supply/port/esp32s3/Kconfig.power new file mode 100644 index 000000000000..d8a3d5ac1053 --- /dev/null +++ b/components/esp_hw_support/power_supply/port/esp32s3/Kconfig.power @@ -0,0 +1,63 @@ +menu "Power Supplier" + + menu "Brownout Detector" + + config ESP_BROWNOUT_DET + bool "Hardware brownout detect & reset" + depends on !IDF_ENV_FPGA + default y + help + The ESP32-S3 has a built-in brownout detector which can detect if the voltage is lower than + a specific value. If this happens, it will reset the chip in order to prevent unintended + behaviour. + + choice ESP_BROWNOUT_DET_LVL_SEL + prompt "Brownout voltage level" + depends on ESP_BROWNOUT_DET + default ESP_BROWNOUT_DET_LVL_SEL_7 + help + The brownout detector will reset the chip when the supply voltage is approximately + below this level. Note that there may be some variation of brownout voltage level + between each ESP3-S3 chip. + + #The voltage levels here are estimates, more work needs to be done to figure out the exact voltages + #of the brownout threshold levels. + config ESP_BROWNOUT_DET_LVL_SEL_7 + bool "2.44V" + config ESP_BROWNOUT_DET_LVL_SEL_6 + bool "2.56V" + config ESP_BROWNOUT_DET_LVL_SEL_5 + bool "2.67V" + config ESP_BROWNOUT_DET_LVL_SEL_4 + bool "2.84V" + config ESP_BROWNOUT_DET_LVL_SEL_3 + bool "2.98V" + config ESP_BROWNOUT_DET_LVL_SEL_2 + bool "3.19V" + config ESP_BROWNOUT_DET_LVL_SEL_1 + bool "3.30V" + endchoice + + config ESP_BROWNOUT_DET_LVL + int + default 1 if ESP_BROWNOUT_DET_LVL_SEL_1 + default 2 if ESP_BROWNOUT_DET_LVL_SEL_2 + default 3 if ESP_BROWNOUT_DET_LVL_SEL_3 + default 4 if ESP_BROWNOUT_DET_LVL_SEL_4 + default 5 if ESP_BROWNOUT_DET_LVL_SEL_5 + default 6 if ESP_BROWNOUT_DET_LVL_SEL_6 + default 7 if ESP_BROWNOUT_DET_LVL_SEL_7 + + config ESP_BROWNOUT_USE_INTR + bool + default n + help + This config allows to trigger an interrupt when brownout detected. Software restart will be done + at the end of the default callback. + This is because for some special workflow, the chip needs do more things when brownout happens + before restart instead of restarting directly. This part needs to be done in callback function + of interrupt. + + endmenu + +endmenu diff --git a/components/esp_hw_support/power_supply/vbat.c b/components/esp_hw_support/power_supply/vbat.c new file mode 100644 index 000000000000..6b360a58fc3e --- /dev/null +++ b/components/esp_hw_support/power_supply/vbat.c @@ -0,0 +1,92 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include "esp_attr.h" +#include "esp_intr_alloc.h" +#include "hal/vbat_ll.h" +#include "hal/brownout_ll.h" +#include "hal/vbat_hal.h" +#include "freertos/FreeRTOS.h" +#include "sdkconfig.h" +#include "esp_private/startup_internal.h" +#include "esp_check.h" +#include "soc/power_supply_periph.h" + +#define VBAT_BROWNOUT_DET_LVL CONFIG_ESP_VBAT_BROWNOUT_DET_LVL + +#if CONFIG_ESP_VBAT_USE_RECHARGEABLE_BATTERY +#define VBAT_CHARGE_DET_LVL_LOW CONFIG_ESP_VBAT_DET_LVL_LOW +#define VBAT_CHARGE_DET_LVL_HIGH CONFIG_ESP_VBAT_DET_LVL_HIGH +#define VBAT_CHARGER_RESISTOR_VALUE CONFIG_ESP_VBAT_CHARGER_CIRCUIT_RESISTOR_VAL + +#if (VBAT_CHARGER_RESISTOR_VALUE < 1000 || VBAT_CHARGER_RESISTOR_VALUE > 4500 || VBAT_CHARGER_RESISTOR_VALUE % 500 != 0) +#error "vbat charger resistor (ESP_VBAT_CHARGER_CIRCUIT_RESISTOR_VAL) must be between 1000 and 4500 ohms and must be a multiple of 500." +#endif + +#if (VBAT_BROWNOUT_DET_LVL >= VBAT_CHARGE_DET_LVL_LOW) +#error "vbat charger low threshold is equal or lower than vbat brownout threshold, please put vbat brownout threshold lower than vbat charger low threshold" +#endif + +#endif + +static const char TAG[] = "VBAT"; + +IRAM_ATTR static void vbat_isr_handler(void *arg) +{ + uint32_t int_status; + vbat_ll_get_interrupt_status(&int_status); + vbat_ll_clear_intr_mask(int_status); + + if (int_status & VBAT_LL_CHARGER_UNDERVOLTAGE_INTR) { + ESP_DRAM_LOGW(TAG, "RTC battery voltage low, start charging..."); + vbat_ll_start_battery_charge(true); + } + + if (int_status & VBAT_LL_CHARGER_UPVOLTAGE_INTR) { + ESP_DRAM_LOGW(TAG, "RTC battery voltage reaches high limit , stop charging..."); + vbat_ll_start_battery_charge(false); + } + + if (int_status & VBAT_LL_BROWNOUT_INTR) { + // TODO: A callback may needed here to inform an under voltage event. + ESP_DRAM_LOGW(TAG, "RTC battery voltage low, please change battery..."); + } + +} + +esp_err_t esp_vbat_init(void) +{ + intr_handle_t vbat_intr; +#if CONFIG_ESP_VBAT_USE_RECHARGEABLE_BATTERY + vbat_hal_config_t vbat_cfg = { + .enable_vbat_charger = true, + .charger_resistor_value = VBAT_CHARGER_RESISTOR_VALUE, + .low_threshold = VBAT_CHARGE_DET_LVL_LOW, + .high_threshold = VBAT_CHARGE_DET_LVL_HIGH, + .brownout_threshold = VBAT_BROWNOUT_DET_LVL, + .undervoltage_filter_time = 20, + .upvoltage_filter_time = 10, + .interrupt_mask = (VBAT_LL_CHARGER_MASK | VBAT_LL_DETECT_MASK), + }; + +#else + vbat_hal_config_t vbat_cfg = { + .enable_vbat_charger = false, + .brownout_threshold = VBAT_BROWNOUT_DET_LVL, + .interrupt_mask = VBAT_LL_DETECT_MASK, + }; +#endif + + vbat_hal_config(&vbat_cfg); + + ESP_RETURN_ON_ERROR(esp_intr_alloc_intrstatus(power_supply_periph_signal.irq, ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_SHARED, (uint32_t)brownout_ll_intr_get_status_reg(), VBAT_LL_CHARGER_MASK | VBAT_LL_DETECT_MASK, &vbat_isr_handler, NULL, &vbat_intr), TAG, "Allocate vbat isr failed"); + + return ESP_OK; +} diff --git a/components/esp_hw_support/sleep_gpio.c b/components/esp_hw_support/sleep_gpio.c index 001cdec8aff5..7cb8fbfef378 100644 --- a/components/esp_hw_support/sleep_gpio.c +++ b/components/esp_hw_support/sleep_gpio.c @@ -61,19 +61,6 @@ void esp_sleep_config_gpio_isolate(void) gpio_sleep_set_pull_mode(gpio_num, GPIO_FLOATING); } } -#if CONFIG_ESP_SLEEP_PSRAM_LEAKAGE_WORKAROUND && CONFIG_SPIRAM - int32_t mspi_io_cs1_io_num = esp_mspi_get_io(ESP_MSPI_IO_CS1); - if (GPIO_IS_VALID_GPIO(mspi_io_cs1_io_num)) { - gpio_sleep_set_pull_mode(mspi_io_cs1_io_num, GPIO_PULLUP_ONLY); - } -#endif // CONFIG_ESP_SLEEP_PSRAM_LEAKAGE_WORKAROUND && CONFIG_SPIRAM - -#if CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND - int32_t mspi_io_cs0_io_num = esp_mspi_get_io(ESP_MSPI_IO_CS0); - if (GPIO_IS_VALID_GPIO(mspi_io_cs0_io_num)) { - gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_CS0), GPIO_PULLUP_ONLY); - } -#endif // CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND #if CONFIG_ESP_SLEEP_MSPI_NEED_ALL_IO_PU gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_CLK), GPIO_PULLUP_ONLY); @@ -102,6 +89,21 @@ void esp_sleep_enable_gpio_switch(bool enable) ESP_EARLY_LOGI(TAG, "%s automatic switching of GPIO sleep configuration", enable ? "Enable" : "Disable"); for (gpio_num_t gpio_num = GPIO_NUM_0; gpio_num < GPIO_NUM_MAX; gpio_num++) { if (GPIO_IS_VALID_GPIO(gpio_num)) { + /* If the PSRAM is disable in ESP32xx chips equipped with PSRAM, there will be a large current leakage. */ +#if CONFIG_ESP_SLEEP_PSRAM_LEAKAGE_WORKAROUND && CONFIG_SPIRAM + if (gpio_num == esp_mspi_get_io(ESP_MSPI_IO_CS1)) { + gpio_sleep_sel_dis(gpio_num); + continue; + } +#endif // CONFIG_ESP_SLEEP_PSRAM_LEAKAGE_WORKAROUND && CONFIG_SPIRAM + +#if CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND + if (gpio_num == esp_mspi_get_io(ESP_MSPI_IO_CS0)) { + gpio_sleep_sel_dis(gpio_num); + continue; + } +#endif // CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND + if (enable) { gpio_sleep_sel_en(gpio_num); } else { @@ -190,13 +192,9 @@ void esp_deep_sleep_wakeup_io_reset(void) #if CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND || CONFIG_PM_SLP_DISABLE_GPIO ESP_SYSTEM_INIT_FN(esp_sleep_startup_init, SECONDARY, BIT(0), 105) { -/* If the TOP domain is powered off, the GPIO will also be powered off during sleep, - and all configurations in the sleep state of GPIO will not take effect.*/ -#if !CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP // Configure to isolate (disable the Input/Output/Pullup/Pulldown // function of the pin) all GPIO pins in sleep state esp_sleep_config_gpio_isolate(); -#endif // Enable automatic switching of GPIO configuration esp_sleep_enable_gpio_switch(true); return ESP_OK; diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index c02adcf5b20d..7bfd4576d8dd 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -674,6 +674,9 @@ FORCE_INLINE_ATTR void misc_modules_sleep_prepare(uint32_t pd_flags, bool deep_s } #endif #if CONFIG_MAC_BB_PD +# if CONFIG_IDF_TARGET_ESP32C5 + clk_ll_soc_root_clk_auto_gating_bypass(false); +# endif mac_bb_power_down_cb_execute(); #endif #if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL @@ -736,6 +739,9 @@ FORCE_INLINE_ATTR void misc_modules_wake_prepare(uint32_t pd_flags) #endif #if CONFIG_MAC_BB_PD mac_bb_power_up_cb_execute(); +# if CONFIG_IDF_TARGET_ESP32C5 + clk_ll_soc_root_clk_auto_gating_bypass(true); +# endif #endif #if REGI2C_ANA_CALI_PD_WORKAROUND regi2c_analog_cali_reg_write(); diff --git a/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/CMakeLists.txt b/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/CMakeLists.txt index 5d29e8ed6fdd..bc5e4d342376 100644 --- a/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/CMakeLists.txt +++ b/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/CMakeLists.txt @@ -22,7 +22,7 @@ if(CONFIG_SOC_ETM_SUPPORTED) endif() if(CONFIG_SOC_GPTIMER_SUPPORTED) - list(APPEND SRC "test_intr_alloc.c") + list(APPEND srcs "test_intr_alloc.c") endif() # In order for the cases defined by `TEST_CASE` to be linked into the final elf, diff --git a/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/test_intr_alloc.c b/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/test_intr_alloc.c index 662f2f3973a1..4ffb1117b0af 100644 --- a/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/test_intr_alloc.c +++ b/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/test_intr_alloc.c @@ -66,7 +66,7 @@ static void timer_test(int flags) } if ((flags & ESP_INTR_FLAG_SHARED)) { - /* Check that the allocated interrupts are acutally shared */ + /* Check that the allocated interrupts are actually shared */ int intr_num = esp_intr_get_intno(inth[0]); for (int i = 0; i < SOC_TIMER_GROUP_TOTAL_TIMERS; i++) { TEST_ASSERT_EQUAL(intr_num, esp_intr_get_intno(inth[i])); @@ -124,6 +124,106 @@ void static test_isr(void*arg) } +TEST_CASE("Intr_alloc test, shared interrupts don't affect level", "[intr_alloc]") +{ + intr_handle_t handle_lvl_1; + intr_handle_t handle_lvl_2; + + /* Allocate an interrupt of level 1 that will be shared with another source */ + esp_err_t err = esp_intr_alloc(ETS_FROM_CPU_INTR2_SOURCE, + ESP_INTR_FLAG_LEVEL1 | ESP_INTR_FLAG_SHARED, + test_isr, NULL, &handle_lvl_1); + TEST_ESP_OK(err); + + /* Allocate a shared interrupt of a different level */ + err = esp_intr_alloc(ETS_FROM_CPU_INTR3_SOURCE, + ESP_INTR_FLAG_LEVEL2 | ESP_INTR_FLAG_SHARED, + test_isr, NULL, &handle_lvl_2); + TEST_ESP_OK(err); + + /* Make sure the allocated CPU line is NOT the same for both sources */ + const int intlvl1 = esp_intr_get_intno(handle_lvl_1); + const int intlvl2 = esp_intr_get_intno(handle_lvl_2); + printf("Level 1 interrupt allocated: %d\n", intlvl1); + printf("Level 2 interrupt allocated: %d\n", intlvl2); + TEST_ASSERT(intlvl1 != intlvl2); + + TEST_ESP_OK(esp_intr_free(handle_lvl_1)); + TEST_ESP_OK(esp_intr_free(handle_lvl_2)); +} + + +#if SOC_CPU_HAS_FLEXIBLE_INTC + +/** + * On targets that have flexible interrupt levels, make sure that a shared interrupt sees its level + * being cleared (and reconfigurable) uupon remove and reallocation. + */ +TEST_CASE("Intr_alloc test, shared interrupts custom level cleared", "[intr_alloc]") +{ + intr_handle_t handle; + + esp_err_t err = esp_intr_alloc(ETS_FROM_CPU_INTR2_SOURCE, + ESP_INTR_FLAG_LEVEL1 | ESP_INTR_FLAG_SHARED, + test_isr, NULL, &handle); + TEST_ESP_OK(err); + const int first_intno = esp_intr_get_intno(handle); + /* Make sure the priority is correct */ + TEST_ASSERT_EQUAL(1, esp_cpu_intr_get_priority(first_intno)); + + /* Free the shared interrupt and try to reallocate it with another level */ + TEST_ESP_OK(esp_intr_free(handle)); + + err = esp_intr_alloc(ETS_FROM_CPU_INTR3_SOURCE, + ESP_INTR_FLAG_LEVEL2 | ESP_INTR_FLAG_SHARED, + test_isr, NULL, &handle); + TEST_ESP_OK(err); + + /* Make sure they are both the same and the level has been updated */ + const int second_intno = esp_intr_get_intno(handle); + TEST_ASSERT_EQUAL(2, esp_cpu_intr_get_priority(second_intno)); + TEST_ASSERT(first_intno == second_intno); + + /* Delete the interrupt */ + TEST_ESP_OK(esp_intr_free(handle)); +} + +#endif + + +/** + * Make sure we can map two given sources to the same interrupt line when their levels match. + */ +TEST_CASE("Intr_alloc test, shared interrupt line for two sources", "[intr_alloc]") +{ + intr_handle_t handle_1; + intr_handle_t handle_2; + + esp_err_t err = esp_intr_alloc(ETS_FROM_CPU_INTR2_SOURCE, + ESP_INTR_FLAG_LEVEL1 | ESP_INTR_FLAG_SHARED, + test_isr, NULL, &handle_1); + TEST_ESP_OK(err); + + /* Map another source to the exact same interrupt line */ + err = esp_intr_alloc_bind(ETS_FROM_CPU_INTR3_SOURCE, + ESP_INTR_FLAG_LEVEL1 | ESP_INTR_FLAG_SHARED, + test_isr, NULL, handle_1, &handle_2); + TEST_ESP_OK(err); + /* Make sure they are both using the same interrupt line */ + TEST_ASSERT_EQUAL(esp_intr_get_intno(handle_1), esp_intr_get_intno(handle_2)); + + /* Reallocate the second interrupt source with a higher level, it must fail */ + TEST_ESP_OK(esp_intr_free(handle_2)); + err = esp_intr_alloc_bind(ETS_FROM_CPU_INTR3_SOURCE, + ESP_INTR_FLAG_LEVEL2 | ESP_INTR_FLAG_SHARED, + test_isr, NULL, handle_1, &handle_2); + TEST_ASSERT(err != ESP_OK); + + /* Free the remaining handler */ + TEST_ESP_OK(esp_intr_free(handle_1)); +} + + TEST_CASE("Allocate previously freed interrupt, with different flags", "[intr_alloc]") { intr_handle_t intr; diff --git a/components/esp_lcd/spi/esp_lcd_panel_io_spi.c b/components/esp_lcd/spi/esp_lcd_panel_io_spi.c index 9586c84ab37e..579483402941 100644 --- a/components/esp_lcd/spi/esp_lcd_panel_io_spi.c +++ b/components/esp_lcd/spi/esp_lcd_panel_io_spi.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 */ @@ -17,6 +17,7 @@ #include "esp_lcd_panel_io.h" #include "driver/spi_master.h" #include "driver/gpio.h" +#include "hal/gpio_ll.h" #include "esp_log.h" #include "esp_check.h" #include "esp_lcd_common.h" @@ -404,12 +405,13 @@ static esp_err_t panel_io_spi_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, cons return ret; } -static void lcd_spi_pre_trans_cb(spi_transaction_t *trans) +IRAM_ATTR static void lcd_spi_pre_trans_cb(spi_transaction_t *trans) { esp_lcd_panel_io_spi_t *spi_panel_io = trans->user; lcd_spi_trans_descriptor_t *lcd_trans = __containerof(trans, lcd_spi_trans_descriptor_t, base); if (spi_panel_io->dc_gpio_num >= 0) { // set D/C line level if necessary - gpio_set_level(spi_panel_io->dc_gpio_num, lcd_trans->flags.dc_gpio_level); + // use ll function to speed up + gpio_ll_set_level(&GPIO, spi_panel_io->dc_gpio_num, lcd_trans->flags.dc_gpio_level); } } diff --git a/components/esp_mm/heap_align_hw.c b/components/esp_mm/heap_align_hw.c index 96787f19d095..d31ea59bd37c 100644 --- a/components/esp_mm/heap_align_hw.c +++ b/components/esp_mm/heap_align_hw.c @@ -20,7 +20,7 @@ #define HEAP_IRAM_ATTR IRAM_ATTR #endif -#define CAPS_NEEDING_ALIGNMENT (MALLOC_CAP_DMA|MALLOC_CAP_DMA_DESC_AHB|MALLOC_CAP_DMA_DESC_AXI|MALLOC_CAP_CACHE_ALIGNED) +#define CAPS_NEEDING_ALIGNMENT (MALLOC_CAP_DMA|MALLOC_CAP_DMA_DESC_AHB|MALLOC_CAP_DMA_DESC_AXI|MALLOC_CAP_CACHE_ALIGNED|MALLOC_CAP_SIMD) HEAP_IRAM_ATTR void esp_heap_adjust_alignment_to_hw(size_t *p_alignment, size_t *p_size, uint32_t *p_caps) { @@ -72,6 +72,14 @@ HEAP_IRAM_ATTR void esp_heap_adjust_alignment_to_hw(size_t *p_alignment, size_t if (cache_alignment_bytes > alignment) { alignment = cache_alignment_bytes; } + +#if SOC_SIMD_INSTRUCTION_SUPPORTED + // SIMD instructions preferred data alignment, SOC_SIMD_PREFERRED_DATA_ALIGNMENT, which is also definitely a power of two + if (caps & MALLOC_CAP_SIMD) { + alignment = (alignment > SOC_SIMD_PREFERRED_DATA_ALIGNMENT) ? alignment : SOC_SIMD_PREFERRED_DATA_ALIGNMENT; + } +#endif + // Align up `size` to resulting alignment as well. size = (size + alignment - 1) & (~(alignment - 1)); diff --git a/components/esp_phy/CMakeLists.txt b/components/esp_phy/CMakeLists.txt index 7acb639a7da4..24defd87b174 100644 --- a/components/esp_phy/CMakeLists.txt +++ b/components/esp_phy/CMakeLists.txt @@ -101,6 +101,10 @@ if(CONFIG_ESP_PHY_ENABLED) if(CONFIG_ESP_PHY_INIT_DATA_IN_PARTITION) idf_component_get_property(esp_common_dir esp_common COMPONENT_DIR) + idf_component_get_property(esp_rom_dir esp_rom COMPONENT_DIR) + idf_component_get_property(newlib_dir newlib COMPONENT_DIR) + idf_component_get_property(soc_dir soc COMPONENT_DIR) + idf_component_get_property(log_dir log COMPONENT_DIR) partition_table_get_partition_info(phy_partition_offset "--partition-type data --partition-subtype phy" "offset") @@ -118,8 +122,9 @@ if(CONFIG_ESP_PHY_ENABLED) DEPENDS ${CMAKE_CURRENT_LIST_DIR}/${idf_target}/phy_init_data.c COMMAND ${CMAKE_C_COMPILER} -c ${CMAKE_CURRENT_LIST_DIR}/${idf_target}/phy_init_data.c -I ${esp_common_dir}/include -I ${CMAKE_CURRENT_LIST_DIR}/include - -I ${CMAKE_CURRENT_LIST_DIR}/${idf_target}/include - -I ${config_dir} -o phy_init_data.obj + -I ${CMAKE_CURRENT_LIST_DIR}/${idf_target}/include -I ${esp_rom_dir}/include + -I ${soc_dir}/${idf_target}/include -I ${newlib_dir}/platform_include + -I ${log_dir}/include -I ${config_dir} -o phy_init_data.obj COMMAND ${CMAKE_OBJCOPY} -O binary phy_init_data.obj ${phy_init_data_bin} ) add_custom_target(phy_init_data ALL DEPENDS ${phy_init_data_bin}) diff --git a/components/esp_phy/esp32c5/phy_init_data.c b/components/esp_phy/esp32c5/phy_init_data.c index 6373e70f949e..b8d7eadcc602 100644 --- a/components/esp_phy/esp32c5/phy_init_data.c +++ b/components/esp_phy/esp32c5/phy_init_data.c @@ -5,7 +5,10 @@ */ #include "sdkconfig.h" +#include "soc/soc_caps.h" #include "phy_init_data.h" +#include "esp_private/phy.h" +#include "esp_check.h" const char __attribute__((section(".rodata"))) phy_init_magic_pre[] = PHY_INIT_MAGIC; @@ -273,3 +276,69 @@ const esp_phy_init_data_t phy_init_data= { { } }; const char __attribute__((section(".rodata"))) phy_init_magic_post[] = PHY_INIT_MAGIC; + +#if SOC_PM_MODEM_RETENTION_BY_REGDMA && CONFIG_MAC_BB_PD + +#include "esp_private/sleep_retention.h" + +static const char* TAG = "phy_sleep"; + +static esp_err_t sleep_retention_wifi_bb_init(void *arg) +{ + #define N_REGS_WIFI_AGC() (126) + #define N_REGS_WIFI_TX() (20) + #define N_REGS_WIFI_NRX() (141) + #define N_REGS_WIFI_BB() (63) + #define N_REGS_WIFI_BRX() (39) + #define N_REGS_WIFI_FE_COEX() (19) + #define N_REGS_WIFI_FE_DATA() (31) + #define N_REGS_WIFI_FE_CTRL() (55) + + const static sleep_retention_entries_config_t bb_regs_retention[] = { + [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b00, 0x600a7000, 0x600a7000, N_REGS_WIFI_AGC(), 0, 0), .owner = BIT(0) | BIT(1) }, /* AGC */ + [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b01, 0x600a7400, 0x600a7400, N_REGS_WIFI_TX(), 0, 0), .owner = BIT(0) | BIT(1) }, /* TX */ + [2] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b02, 0x600a7800, 0x600a7800, N_REGS_WIFI_NRX(), 0, 0), .owner = BIT(0) | BIT(1) }, /* NRX */ + [3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b03, 0x600a7c00, 0x600a7c00, N_REGS_WIFI_BB(), 0, 0), .owner = BIT(0) | BIT(1) }, /* BB */ + [4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b05, 0x600a0000, 0x600a0000, N_REGS_WIFI_FE_COEX(), 0, 0), .owner = BIT(0) | BIT(1) }, /* FE COEX */ + [5] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b06, 0x600a8000, 0x600a8000, N_REGS_WIFI_BRX(), 0, 0), .owner = BIT(0) | BIT(1) }, /* BRX */ + [6] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b07, 0x600a0400, 0x600a0400, N_REGS_WIFI_FE_DATA(), 0, 0), .owner = BIT(0) | BIT(1) }, /* FE DATA */ + [7] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b08, 0x600a0800, 0x600a0800, N_REGS_WIFI_FE_CTRL(), 0, 0), .owner = BIT(0) | BIT(1) }, /* FE CTRL */ + [8] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b09, 0x600a0c00, 0x600a0c00, 20, 0, 0), .owner = BIT(0) | BIT(1) } /* FE WIFI DATA */ + }; + esp_err_t err = sleep_retention_entries_create(bb_regs_retention, ARRAY_SIZE(bb_regs_retention), 3, SLEEP_RETENTION_MODULE_WIFI_BB); + ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for modem (%s) retention", "WiFi BB"); + ESP_LOGD(TAG, "WiFi BB sleep retention initialization"); + return ESP_OK; +} + +void esp_phy_sleep_data_init(void) +{ + sleep_retention_module_init_param_t init_param = { + .cbs = { .create = { .handle = sleep_retention_wifi_bb_init, .arg = NULL } }, + .depends = RETENTION_MODULE_BITMAP_INIT(CLOCK_MODEM) + }; + esp_err_t err = sleep_retention_module_init(SLEEP_RETENTION_MODULE_WIFI_BB, &init_param); + if (err != ESP_OK) { + ESP_LOGW(TAG, "WiFi BB sleep retention init failed"); + return; + } + err = sleep_retention_module_allocate(SLEEP_RETENTION_MODULE_WIFI_BB); + if (err != ESP_OK) { + ESP_LOGW(TAG, "failed to allocate sleep retention linked list for wifi bb retention"); + } +} + +void esp_phy_sleep_data_deinit(void) +{ + esp_err_t err = sleep_retention_module_free(SLEEP_RETENTION_MODULE_WIFI_BB); + if (err != ESP_OK) { + ESP_LOGW(TAG, "failed to free sleep retention linked list for wifi bb retention"); + return; + } + err = sleep_retention_module_deinit(SLEEP_RETENTION_MODULE_WIFI_BB); + if (err != ESP_OK) { + ESP_LOGW(TAG, "WiFi BB sleep retention deinit failed"); + } +} + +#endif /* SOC_PM_MODEM_RETENTION_BY_REGDMA && CONFIG_MAC_BB_PD */ diff --git a/components/esp_phy/esp32c6/phy_init_data.c b/components/esp_phy/esp32c6/phy_init_data.c index 499b60d6609b..a32c3c4668d3 100644 --- a/components/esp_phy/esp32c6/phy_init_data.c +++ b/components/esp_phy/esp32c6/phy_init_data.c @@ -5,7 +5,10 @@ */ #include "sdkconfig.h" +#include "soc/soc_caps.h" #include "phy_init_data.h" +#include "esp_private/phy.h" +#include "esp_check.h" const char __attribute__((section(".rodata"))) phy_init_magic_pre[] = PHY_INIT_MAGIC; @@ -144,3 +147,63 @@ const esp_phy_init_data_t phy_init_data= { { } }; const char __attribute__((section(".rodata"))) phy_init_magic_post[] = PHY_INIT_MAGIC; + +#if SOC_PM_MODEM_RETENTION_BY_REGDMA && CONFIG_MAC_BB_PD + +#include "esp_private/sleep_retention.h" + +static const char* TAG = "phy_sleep"; + +static esp_err_t sleep_retention_wifi_bb_init(void *arg) +{ + #define N_REGS_WIFI_AGC() (121) + #define N_REGS_WIFI_TX() (14) + #define N_REGS_WIFI_NRX() (136) + #define N_REGS_WIFI_BB() (53) + #define N_REGS_WIFI_BRX() (39) + #define N_REGS_WIFI_FE_COEX() (58) + + const static sleep_retention_entries_config_t bb_regs_retention[] = { + [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b00, 0x600a7000, 0x600a7000, N_REGS_WIFI_AGC(), 0, 0), .owner = BIT(0) | BIT(1) }, /* AGC */ + [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b01, 0x600a7400, 0x600a7400, N_REGS_WIFI_TX(), 0, 0), .owner = BIT(0) | BIT(1) }, /* TX */ + [2] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b02, 0x600a7800, 0x600a7800, N_REGS_WIFI_NRX(), 0, 0), .owner = BIT(0) | BIT(1) }, /* NRX */ + [3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b03, 0x600a7c00, 0x600a7c00, N_REGS_WIFI_BB(), 0, 0), .owner = BIT(0) | BIT(1) }, /* BB */ + [4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b05, 0x600a0000, 0x600a0000, N_REGS_WIFI_FE_COEX(), 0, 0), .owner = BIT(0) | BIT(1) }, /* FE COEX */ + }; + esp_err_t err = sleep_retention_entries_create(bb_regs_retention, ARRAY_SIZE(bb_regs_retention), 3, SLEEP_RETENTION_MODULE_WIFI_BB); + ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for modem (%s) retention", "WiFi BB"); + ESP_LOGD(TAG, "WiFi BB sleep retention initialization"); + return ESP_OK; +} + +void esp_phy_sleep_data_init(void) +{ + sleep_retention_module_init_param_t init_param = { + .cbs = { .create = { .handle = sleep_retention_wifi_bb_init, .arg = NULL } }, + .depends = RETENTION_MODULE_BITMAP_INIT(CLOCK_MODEM) + }; + esp_err_t err = sleep_retention_module_init(SLEEP_RETENTION_MODULE_WIFI_BB, &init_param); + if (err != ESP_OK) { + ESP_LOGW(TAG, "WiFi BB sleep retention init failed"); + return; + } + err = sleep_retention_module_allocate(SLEEP_RETENTION_MODULE_WIFI_BB); + if (err != ESP_OK) { + ESP_LOGW(TAG, "failed to allocate sleep retention linked list for wifi bb retention"); + } +} + +void esp_phy_sleep_data_deinit(void) +{ + esp_err_t err = sleep_retention_module_free(SLEEP_RETENTION_MODULE_WIFI_BB); + if (err != ESP_OK) { + ESP_LOGW(TAG, "failed to free sleep retention linked list for wifi bb retention"); + return; + } + err = sleep_retention_module_deinit(SLEEP_RETENTION_MODULE_WIFI_BB); + if (err != ESP_OK) { + ESP_LOGW(TAG, "WiFi BB sleep retention deinit failed"); + } +} + +#endif /* SOC_PM_MODEM_RETENTION_BY_REGDMA && CONFIG_MAC_BB_PD */ diff --git a/components/esp_phy/esp32c61/phy_init_data.c b/components/esp_phy/esp32c61/phy_init_data.c index 801431525687..503fa18c799a 100644 --- a/components/esp_phy/esp32c61/phy_init_data.c +++ b/components/esp_phy/esp32c61/phy_init_data.c @@ -5,7 +5,10 @@ */ #include "sdkconfig.h" +#include "soc/soc_caps.h" #include "phy_init_data.h" +#include "esp_private/phy.h" +#include "esp_check.h" const char __attribute__((section(".rodata"))) phy_init_magic_pre[] = PHY_INIT_MAGIC; @@ -145,3 +148,68 @@ const esp_phy_init_data_t phy_init_data= { { } }; const char __attribute__((section(".rodata"))) phy_init_magic_post[] = PHY_INIT_MAGIC; + +#if SOC_PM_MODEM_RETENTION_BY_REGDMA && CONFIG_MAC_BB_PD + +#include "esp_private/sleep_retention.h" + +static const char* TAG = "phy_sleep"; + +static esp_err_t sleep_retention_wifi_bb_init(void *arg) +{ + #define N_REGS_WIFI_AGC() (121) + #define N_REGS_WIFI_TX() (14) + #define N_REGS_WIFI_NRX() (136) + #define N_REGS_WIFI_BB() (53) + #define N_REGS_WIFI_BRX() (39) + #define N_REGS_WIFI_FE_COEX() (58) + #define N_REGS_WIFI_FE_DATA() (41) + #define N_REGS_WIFI_FE_CTRL() (87) + + const static sleep_retention_entries_config_t bb_regs_retention[] = { + [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b00, 0x600a7000, 0x600a7000, N_REGS_WIFI_AGC(), 0, 0), .owner = BIT(0) | BIT(1) }, /* AGC */ + [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b01, 0x600a7400, 0x600a7400, N_REGS_WIFI_TX(), 0, 0), .owner = BIT(0) | BIT(1) }, /* TX */ + [2] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b02, 0x600a7800, 0x600a7800, N_REGS_WIFI_NRX(), 0, 0), .owner = BIT(0) | BIT(1) }, /* NRX */ + [3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b03, 0x600a7c00, 0x600a7c00, N_REGS_WIFI_BB(), 0, 0), .owner = BIT(0) | BIT(1) }, /* BB */ + [4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b05, 0x600a0000, 0x600a0000, N_REGS_WIFI_FE_COEX(), 0, 0), .owner = BIT(0) | BIT(1) }, /* FE COEX */ + [5] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b06, 0x600a8000, 0x600a8000, N_REGS_WIFI_BRX(), 0, 0), .owner = BIT(0) | BIT(1) }, /* BRX */ + [6] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b07, 0x600a0400, 0x600a0400, N_REGS_WIFI_FE_DATA(), 0, 0), .owner = BIT(0) | BIT(1) }, /* FE DATA */ + [7] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b08, 0x600a0800, 0x600a0800, N_REGS_WIFI_FE_CTRL(), 0, 0), .owner = BIT(0) | BIT(1) }, /* FE CTRL */ + }; + esp_err_t err = sleep_retention_entries_create(bb_regs_retention, ARRAY_SIZE(bb_regs_retention), 3, SLEEP_RETENTION_MODULE_WIFI_BB); + ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for modem (%s) retention", "WiFi BB"); + ESP_LOGD(TAG, "WiFi BB sleep retention initialization"); + return ESP_OK; +} + +void esp_phy_sleep_data_init(void) +{ + sleep_retention_module_init_param_t init_param = { + .cbs = { .create = { .handle = sleep_retention_wifi_bb_init, .arg = NULL } }, + .depends = RETENTION_MODULE_BITMAP_INIT(CLOCK_MODEM) + }; + esp_err_t err = sleep_retention_module_init(SLEEP_RETENTION_MODULE_WIFI_BB, &init_param); + if (err != ESP_OK) { + ESP_LOGW(TAG, "WiFi BB sleep retention init failed"); + return; + } + err = sleep_retention_module_allocate(SLEEP_RETENTION_MODULE_WIFI_BB); + if (err != ESP_OK) { + ESP_LOGW(TAG, "failed to allocate sleep retention linked list for wifi bb retention"); + } +} + +void esp_phy_sleep_data_deinit(void) +{ + esp_err_t err = sleep_retention_module_free(SLEEP_RETENTION_MODULE_WIFI_BB); + if (err != ESP_OK) { + ESP_LOGW(TAG, "failed to free sleep retention linked list for wifi bb retention"); + return; + } + err = sleep_retention_module_deinit(SLEEP_RETENTION_MODULE_WIFI_BB); + if (err != ESP_OK) { + ESP_LOGW(TAG, "WiFi BB sleep retention deinit failed"); + } +} + +#endif /* SOC_PM_MODEM_RETENTION_BY_REGDMA && CONFIG_MAC_BB_PD */ diff --git a/components/esp_phy/include/esp_private/phy.h b/components/esp_phy/include/esp_private/phy.h index d2e508528b19..8498084bc1d3 100644 --- a/components/esp_phy/include/esp_private/phy.h +++ b/components/esp_phy/include/esp_private/phy.h @@ -8,6 +8,7 @@ #include #include "sdkconfig.h" #include "esp_phy_init.h" +#include "soc/soc_caps.h" #ifdef __cplusplus extern "C" { @@ -243,6 +244,18 @@ uint32_t phy_ana_i2c_master_burst_rf_onoff(bool on); void phy_wakeup_from_modem_state_extra_init(void); #endif +#if SOC_PM_MODEM_RETENTION_BY_REGDMA && CONFIG_MAC_BB_PD +/** + * @brief PHY module sleep data (includes AGC, TX, NRX, BB, FE, etc..) initialize. + */ +void esp_phy_sleep_data_init(void); + +/** + * @brief PHY module sleep data de-initialize. + */ +void esp_phy_sleep_data_deinit(void); +#endif + #ifdef __cplusplus } #endif diff --git a/components/esp_phy/lib b/components/esp_phy/lib index 1e3487dc778d..7114c37cbc16 160000 --- a/components/esp_phy/lib +++ b/components/esp_phy/lib @@ -1 +1 @@ -Subproject commit 1e3487dc778d48c15229af05ce0f03f78e15528c +Subproject commit 7114c37cbc163e373e8dd4a7ecfdeacddc9fa8c2 diff --git a/components/esp_phy/linker.lf b/components/esp_phy/linker.lf index 40d3b99c9d05..5dc2f9f23b38 100644 --- a/components/esp_phy/linker.lf +++ b/components/esp_phy/linker.lf @@ -29,3 +29,5 @@ entries: phy_init:esp_phy_enable (noflash) phy_init:esp_phy_disable (noflash) phy_init:esp_wifi_bt_power_domain_off (noflash) + if PM_SLP_IRAM_OPT = y: + phy_override:phy_get_tsens_value (noflash) diff --git a/components/esp_phy/src/phy_init.c b/components/esp_phy/src/phy_init.c index ec7b6be4c80c..ceaea6ac211a 100644 --- a/components/esp_phy/src/phy_init.c +++ b/components/esp_phy/src/phy_init.c @@ -50,10 +50,6 @@ #endif #include "hal/efuse_hal.h" -#if SOC_PM_MODEM_RETENTION_BY_REGDMA -#include "esp_private/sleep_retention.h" -#endif - #if CONFIG_IDF_TARGET_ESP32 extern wifi_mac_time_update_cb_t s_wifi_mac_time_update_cb; #endif @@ -484,26 +480,6 @@ static uint32_t* s_mac_bb_pd_mem = NULL; static uint8_t s_macbb_backup_mem_ref = 0; /* Reference of powering down MAC and BB */ static bool s_mac_bb_pu = true; -#elif SOC_PM_MODEM_RETENTION_BY_REGDMA -static esp_err_t sleep_retention_wifi_bb_init(void *arg) -{ - const static sleep_retention_entries_config_t bb_regs_retention[] = { - [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b00, 0x600a7000, 0x600a7000, 121, 0, 0), .owner = BIT(0) | BIT(1) }, /* AGC */ - [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b01, 0x600a7400, 0x600a7400, 14, 0, 0), .owner = BIT(0) | BIT(1) }, /* TX */ - [2] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b02, 0x600a7800, 0x600a7800, 136, 0, 0), .owner = BIT(0) | BIT(1) }, /* NRX */ - [3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b03, 0x600a7c00, 0x600a7c00, 53, 0, 0), .owner = BIT(0) | BIT(1) }, /* BB */ - [4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b05, 0x600a0000, 0x600a0000, 58, 0, 0), .owner = BIT(0) | BIT(1) }, /* FE COEX */ -#ifndef SOC_PM_RETENTION_HAS_CLOCK_BUG - [5] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b06, 0x600a8000, 0x000a8000, 39, 0, 0), .owner = BIT(0) | BIT(1) }, /* BRX */ - [6] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b07, 0x600a0400, 0x600a0400, 41, 0, 0), .owner = BIT(0) | BIT(1) }, /* FE DATA */ - [7] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b08, 0x600a0800, 0x600a0800, 87, 0, 0), .owner = BIT(0) | BIT(1) } /* FE CTRL */ -#endif - }; - esp_err_t err = sleep_retention_entries_create(bb_regs_retention, ARRAY_SIZE(bb_regs_retention), 3, SLEEP_RETENTION_MODULE_WIFI_BB); - ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for modem (%s) retention", "WiFi BB"); - ESP_LOGD(TAG, "WiFi BB sleep retention initialization"); - return ESP_OK; -} #endif // SOC_PM_MODEM_RETENTION_BY_BACKUPDMA void esp_mac_bb_pd_mem_init(void) @@ -516,19 +492,7 @@ void esp_mac_bb_pd_mem_init(void) } _lock_release(&s_phy_access_lock); #elif SOC_PM_MODEM_RETENTION_BY_REGDMA - sleep_retention_module_init_param_t init_param = { - .cbs = { .create = { .handle = sleep_retention_wifi_bb_init, .arg = NULL } }, - .depends = RETENTION_MODULE_BITMAP_INIT(CLOCK_MODEM) - }; - esp_err_t err = sleep_retention_module_init(SLEEP_RETENTION_MODULE_WIFI_BB, &init_param); - if (err != ESP_OK) { - ESP_LOGW(TAG, "WiFi BB sleep retention init failed"); - return; - } - err = sleep_retention_module_allocate(SLEEP_RETENTION_MODULE_WIFI_BB); - if (err != ESP_OK) { - ESP_LOGW(TAG, "failed to allocate sleep retention linked list for wifi bb retention"); - } + esp_phy_sleep_data_init(); #endif } @@ -543,15 +507,7 @@ void esp_mac_bb_pd_mem_deinit(void) } _lock_release(&s_phy_access_lock); #elif SOC_PM_MODEM_RETENTION_BY_REGDMA - esp_err_t err = sleep_retention_module_free(SLEEP_RETENTION_MODULE_WIFI_BB); - if (err != ESP_OK) { - ESP_LOGW(TAG, "failed to free sleep retention linked list for wifi bb retention"); - return; - } - err = sleep_retention_module_deinit(SLEEP_RETENTION_MODULE_WIFI_BB); - if (err != ESP_OK) { - ESP_LOGW(TAG, "WiFi BB sleep retention deinit failed"); - } + esp_phy_sleep_data_deinit(); #endif } diff --git a/components/esp_pm/linker.lf b/components/esp_pm/linker.lf index a5d95c06b4e3..fde5ef2ba69c 100644 --- a/components/esp_pm/linker.lf +++ b/components/esp_pm/linker.lf @@ -39,6 +39,16 @@ entries: sleep_modem:modem_domain_pd_allowed (noflash) sleep_modem:periph_inform_out_light_sleep_overhead (noflash) sar_periph_ctrl:sar_periph_ctrl_power_disable (noflash) + if SOC_TEMP_SENSOR_SUPPORTED = y: + sar_periph_ctrl_common:temperature_sensor_power_acquire (noflash) + sar_periph_ctrl_common:temperature_sensor_power_release (noflash) + sar_periph_ctrl_common:temperature_sensor_get_raw_value (noflash) + sar_periph_ctrl_common:temp_sensor_get_raw_value (noflash) + regi2c_ctrl:regi2c_saradc_enable (noflash) + regi2c_ctrl:regi2c_saradc_disable (noflash) + if SOC_ADC_SUPPORTED = y: + adc_share_hw_ctrl:adc_apb_periph_claim (noflash) + adc_share_hw_ctrl:adc_apb_periph_free (noflash) [mapping:esp_system_pm] archive: libesp_system.a diff --git a/components/esp_psram/device/esp_psram_impl_ap_quad.c b/components/esp_psram/device/esp_psram_impl_ap_quad.c index 742b2315c054..a709533944fd 100644 --- a/components/esp_psram/device/esp_psram_impl_ap_quad.c +++ b/components/esp_psram/device/esp_psram_impl_ap_quad.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 */ @@ -16,7 +16,7 @@ #include "esp_private/mspi_timing_tuning.h" #include "esp_private/esp_gpio_reserve.h" #include "hal/psram_ctrlr_ll.h" -#include "esp_quad_psram_defs.h" +#include "esp_quad_psram_defs_ap.h" #include "soc/soc_caps.h" static const char* TAG = "quad_psram"; @@ -31,7 +31,7 @@ uint8_t esp_psram_impl_get_cs_io(void) return s_psram_cs_io; } -void psram_exec_cmd(int spi_num, psram_hal_cmd_mode_t mode, +void psram_exec_cmd(int spi_num, psram_cmd_mode_t mode, uint32_t cmd, int cmd_bit_len, uint32_t addr, int addr_bit_len, int dummy_bits, @@ -60,7 +60,7 @@ void psram_exec_cmd(int spi_num, psram_hal_cmd_mode_t mode, static void psram_disable_qio_mode(int spi_num) { psram_exec_cmd(spi_num, PSRAM_HAL_CMD_QPI, - PSRAM_EXIT_QMODE, 8, /* command and command bit len*/ + PSRAM_QUAD_EXIT_QMODE, 8, /* command and command bit len*/ 0, 0, /* address and address bit len*/ 0, /* dummy bit len */ NULL, 0, /* tx data and tx bit len*/ @@ -72,10 +72,10 @@ static void psram_disable_qio_mode(int spi_num) //TODO IDF-4307 //switch psram burst length(32 bytes or 1024 bytes) //datasheet says it should be 1024 bytes by default -static void psram_set_wrap_burst_length(int spi_num, psram_hal_cmd_mode_t mode) +static void psram_set_wrap_burst_length(int spi_num, psram_cmd_mode_t mode) { psram_exec_cmd(spi_num, mode, - PSRAM_SET_BURST_LEN, 8, /* command and command bit len*/ + PSRAM_QUAD_SET_BURST_LEN, 8, /* command and command bit len*/ 0, 0, /* address and address bit len*/ 0, /* dummy bit len */ NULL, 0, /* tx data and tx bit len*/ @@ -88,7 +88,7 @@ static void psram_set_wrap_burst_length(int spi_num, psram_hal_cmd_mode_t mode) static void psram_reset_mode(int spi_num) { psram_exec_cmd(spi_num, PSRAM_HAL_CMD_SPI, - PSRAM_RESET_EN, 8, /* command and command bit len*/ + PSRAM_QUAD_RESET_EN, 8, /* command and command bit len*/ 0, 0, /* address and address bit len*/ 0, /* dummy bit len */ NULL, 0, /* tx data and tx bit len*/ @@ -97,7 +97,7 @@ static void psram_reset_mode(int spi_num) false); /* whether is program/erase operation */ psram_exec_cmd(spi_num, PSRAM_HAL_CMD_SPI, - PSRAM_RESET, 8, /* command and command bit len*/ + PSRAM_QUAD_RESET, 8, /* command and command bit len*/ 0, 0, /* address and address bit len*/ 0, /* dummy bit len */ NULL, 0, /* tx data and tx bit len*/ @@ -144,7 +144,7 @@ bool psram_support_wrap_size(uint32_t wrap_size) static void psram_read_id(int spi_num, uint8_t* dev_id, int id_bits) { psram_exec_cmd(spi_num, PSRAM_HAL_CMD_SPI, - PSRAM_DEVICE_ID, 8, /* command and command bit len*/ + PSRAM_QUAD_DEVICE_ID, 8, /* command and command bit len*/ 0, 24, /* address and address bit len*/ 0, /* dummy bit len */ NULL, 0, /* tx data and tx bit len*/ @@ -157,7 +157,7 @@ static void psram_read_id(int spi_num, uint8_t* dev_id, int id_bits) static void psram_enable_qio_mode(int spi_num) { psram_exec_cmd(spi_num, PSRAM_HAL_CMD_SPI, - PSRAM_ENTER_QMODE, 8, /* command and command bit len*/ + PSRAM_QUAD_ENTER_QMODE, 8, /* command and command bit len*/ 0, 0, /* address and address bit len*/ 0, /* dummy bit len */ NULL, 0, /* tx data and tx bit len*/ @@ -168,14 +168,56 @@ static void psram_enable_qio_mode(int spi_num) static void psram_set_cs_timing(void) { - psram_ctrlr_ll_set_cs_hold(PSRAM_CTRLR_LL_MSPI_ID_0, PSRAM_CS_HOLD_VAL); - psram_ctrlr_ll_set_cs_setup(PSRAM_CTRLR_LL_MSPI_ID_0, PSRAM_CS_SETUP_VAL); + psram_ctrlr_ll_set_cs_hold(PSRAM_CTRLR_LL_MSPI_ID_0, PSRAM_QUAD_CS_HOLD_VAL); + psram_ctrlr_ll_set_cs_setup(PSRAM_CTRLR_LL_MSPI_ID_0, PSRAM_QUAD_CS_SETUP_VAL); +#if CONFIG_SPIRAM_ECC_ENABLE + psram_ctrlr_ll_set_ecc_cs_hold(PSRAM_CTRLR_LL_MSPI_ID_0, PSRAM_QUAD_CS_ECC_HOLD_TIME_VAL); +#endif } +#if CONFIG_SPIRAM_ECC_ENABLE +static void s_mspi_ecc_show_info(void) +{ + for (int i = 0; i < PSRAM_CTRLR_LL_PMS_REGION_NUMS; i++) { + ESP_EARLY_LOGV(TAG, "region[%d] addr: 0x%08x", i, psram_ctrlr_ll_get_pms_region_start_addr(PSRAM_CTRLR_LL_MSPI_ID_0, i)); + ESP_EARLY_LOGV(TAG, "region[%d] size: 0x%08x", i, psram_ctrlr_ll_get_pms_region_size(PSRAM_CTRLR_LL_MSPI_ID_0, i)); + } + + uint32_t page_size = psram_ctrlr_ll_get_page_size(PSRAM_CTRLR_LL_MSPI_ID_0); + ESP_EARLY_LOGV(TAG, "ECC page size: %d", page_size); +} + +/** + * Enable error correcting code feature + * + * Can add an input parameter for selecting ECC mode if needed + */ +static void s_configure_psram_ecc(void) +{ + psram_ctrlr_ll_set_ecc_mode(PSRAM_CTRLR_LL_MSPI_ID_0, PSRAM_LL_ECC_MODE_16TO18); + psram_ctrlr_ll_enable_skip_page_corner(PSRAM_CTRLR_LL_MSPI_ID_0, true); + psram_ctrlr_ll_enable_split_trans(PSRAM_CTRLR_LL_MSPI_ID_0, true); + psram_ctrlr_ll_set_page_size(PSRAM_CTRLR_LL_MSPI_ID_0, PSRAM_QUAD_PAGE_SIZE); + psram_ctrlr_ll_enable_ecc_addr_conversion(PSRAM_CTRLR_LL_MSPI_ID_0, true); + + /** + * Enable ECC region 0 (ACE0) + * Default: ACE0 range: 0 ~ 256MB + * For current Quad PSRAM, ACE0 is enough + */ + psram_ctrlr_ll_set_pms_region_start_addr(PSRAM_CTRLR_LL_MSPI_ID_0, 0, 0); + psram_ctrlr_ll_set_pms_region_size(PSRAM_CTRLR_LL_MSPI_ID_0, 0, 4096); + psram_ctrlr_ll_set_pms_region_attr(PSRAM_CTRLR_LL_MSPI_ID_0, 0, PSRAM_CTRLR_LL_PMS_ATTR_WRITABLE | PSRAM_CTRLR_LL_PMS_ATTR_READABLE); + psram_ctrlr_ll_enable_pms_region_ecc(PSRAM_CTRLR_LL_MSPI_ID_0, 0, true); + ESP_EARLY_LOGI(TAG, "ECC is enabled"); + s_mspi_ecc_show_info(); +} +#endif + static void psram_gpio_config(void) { //CS1 - uint8_t cs1_io = PSRAM_CS_IO; + uint8_t cs1_io = PSRAM_QUAD_CS_IO; if (cs1_io == MSPI_IOMUX_PIN_NUM_CS1) { gpio_ll_func_sel(&GPIO, cs1_io, FUNC_SPICS1_SPICS1); } else { @@ -185,7 +227,7 @@ static void psram_gpio_config(void) s_psram_cs_io = cs1_io; //WP HD - uint8_t wp_io = PSRAM_SPIWP_SD3_IO; + uint8_t wp_io = PSRAM_QUAD_SPIWP_SD3_IO; #if SOC_SPI_MEM_SUPPORT_CONFIG_GPIO_BY_EFUSE const uint32_t spiconfig = esp_rom_efuse_get_flash_gpio_info(); if (spiconfig == ESP_ROM_EFUSE_FLASH_DEFAULT_SPI) { @@ -224,7 +266,7 @@ static void s_config_psram_clock(void) bool s_check_aps3204_2tmode(void) { uint64_t full_eid = 0; - psram_read_id(PSRAM_CTRLR_LL_MSPI_ID_1, (uint8_t *)&full_eid, PSRAM_EID_BITS_NUM); + psram_read_id(PSRAM_CTRLR_LL_MSPI_ID_1, (uint8_t *)&full_eid, PSRAM_QUAD_EID_BITS_NUM); bool is_2t = false; uint32_t eid_47_16 = __builtin_bswap32((full_eid >> 16) & UINT32_MAX); @@ -240,6 +282,9 @@ esp_err_t esp_psram_impl_enable(void) { psram_gpio_config(); psram_set_cs_timing(); +#if CONFIG_SPIRAM_ECC_ENABLE + s_configure_psram_ecc(); +#endif #if SOC_SPI_MEM_SUPPORT_TIMING_TUNING //enter MSPI slow mode to init PSRAM device registers @@ -250,31 +295,31 @@ esp_err_t esp_psram_impl_enable(void) //We use SPI1 to init PSRAM psram_disable_qio_mode(PSRAM_CTRLR_LL_MSPI_ID_1); - psram_read_id(PSRAM_CTRLR_LL_MSPI_ID_1, (uint8_t *)&psram_id, PSRAM_ID_BITS_NUM); - if (!PSRAM_IS_VALID(psram_id)) { + psram_read_id(PSRAM_CTRLR_LL_MSPI_ID_1, (uint8_t *)&psram_id, PSRAM_QUAD_ID_BITS_NUM); + if (!PSRAM_QUAD_IS_VALID(psram_id)) { /* 16Mbit psram ID read error workaround: * treat the first read id as a dummy one as the pre-condition, * Send Read ID command again */ - psram_read_id(PSRAM_CTRLR_LL_MSPI_ID_1, (uint8_t *)&psram_id, PSRAM_ID_BITS_NUM); - if (!PSRAM_IS_VALID(psram_id)) { + psram_read_id(PSRAM_CTRLR_LL_MSPI_ID_1, (uint8_t *)&psram_id, PSRAM_QUAD_ID_BITS_NUM); + if (!PSRAM_QUAD_IS_VALID(psram_id)) { ESP_EARLY_LOGE(TAG, "PSRAM ID read error: 0x%08x, PSRAM chip not found or not supported, or wrong PSRAM line mode", (uint32_t)psram_id); return ESP_ERR_NOT_SUPPORTED; } } - if (PSRAM_IS_64MBIT_TRIAL(psram_id)) { + if (PSRAM_QUAD_IS_64MBIT_TRIAL(psram_id)) { s_psram_size = PSRAM_SIZE_8MB; } else { - uint8_t density = PSRAM_SIZE_ID(psram_id); - const int eid = PSRAM_EID_BIT_47_40(psram_id); + uint8_t density = PSRAM_QUAD_SIZE_ID(psram_id); + const int eid = PSRAM_QUAD_EID_BIT_47_40(psram_id); s_psram_size = density == 0x0 ? PSRAM_SIZE_2MB : density == 0x1 ? PSRAM_SIZE_4MB : density == 0x2 ? PSRAM_SIZE_8MB : /* Do not use `density` for QEMU PSRAM since we don't want any future QSPI PSRAM * that are 16MB or 32MB to be interpreted as QEMU PSRAM devices */ - eid == PSRAM_QEMU_16MB_ID ? PSRAM_SIZE_16MB : - eid == PSRAM_QEMU_32MB_ID ? PSRAM_SIZE_32MB : 0; + eid == PSRAM_QUAD_QEMU_16MB_ID ? PSRAM_SIZE_16MB : + eid == PSRAM_QUAD_QEMU_32MB_ID ? PSRAM_SIZE_32MB : 0; } if ((s_psram_size == PSRAM_SIZE_8MB) && s_check_aps3204_2tmode()) { @@ -306,10 +351,10 @@ esp_err_t esp_psram_impl_enable(void) static void config_psram_spi_phases(void) { psram_ctrlr_ll_set_read_mode(PSRAM_CTRLR_LL_MSPI_ID_0, PSRAM_HAL_CMD_QPI); - psram_ctrlr_ll_set_wr_cmd(PSRAM_CTRLR_LL_MSPI_ID_0, PSRAM_CMD_LENGTH, PSRAM_QUAD_WRITE); - psram_ctrlr_ll_set_rd_cmd(PSRAM_CTRLR_LL_MSPI_ID_0, PSRAM_CMD_LENGTH, PSRAM_FAST_READ_QUAD); - psram_ctrlr_ll_set_addr_bitlen(PSRAM_CTRLR_LL_MSPI_ID_0, PSRAM_ADDR_LENGTH); - psram_ctrlr_ll_set_rd_dummy(PSRAM_CTRLR_LL_MSPI_ID_0, PSRAM_FAST_READ_QUAD_DUMMY); + psram_ctrlr_ll_set_wr_cmd(PSRAM_CTRLR_LL_MSPI_ID_0, PSRAM_QUAD_CMD_LENGTH, PSRAM_QUAD_WRITE_QUAD); + psram_ctrlr_ll_set_rd_cmd(PSRAM_CTRLR_LL_MSPI_ID_0, PSRAM_QUAD_CMD_LENGTH, PSRAM_QUAD_FAST_READ_QUAD); + psram_ctrlr_ll_set_addr_bitlen(PSRAM_CTRLR_LL_MSPI_ID_0, PSRAM_QUAD_ADDR_LENGTH); + psram_ctrlr_ll_set_rd_dummy(PSRAM_CTRLR_LL_MSPI_ID_0, PSRAM_QUAD_FAST_READ_QUAD_DUMMY); psram_ctrlr_ll_set_cs_pin(PSRAM_CTRLR_LL_MSPI_ID_0, PSRAM_LL_CS_ID_1); } @@ -330,9 +375,7 @@ esp_err_t esp_psram_impl_get_physical_size(uint32_t *out_size_bytes) /** * This function is to get the available physical psram size in bytes. - * - * When ECC is enabled, the available size will be reduced. - * On S3 Quad PSRAM, ECC is not enabled for now. + * If ECC is enabled, available PSRAM size will be 7/8 times its physical size. */ esp_err_t esp_psram_impl_get_available_size(uint32_t *out_size_bytes) { @@ -340,6 +383,10 @@ esp_err_t esp_psram_impl_get_available_size(uint32_t *out_size_bytes) return ESP_ERR_INVALID_ARG; } +#if CONFIG_SPIRAM_ECC_ENABLE + *out_size_bytes = s_psram_size * 7 / 8; +#else *out_size_bytes = s_psram_size; +#endif return (s_psram_size ? ESP_OK : ESP_ERR_INVALID_STATE); } diff --git a/components/esp_psram/device/esp_quad_psram_defs.h b/components/esp_psram/device/esp_quad_psram_defs.h deleted file mode 100644 index e78437768f2e..000000000000 --- a/components/esp_psram/device/esp_quad_psram_defs.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -//Commands for PSRAM chip - -#pragma once - -#include "soc/spi_pins.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define PSRAM_READ 0x03 -#define PSRAM_FAST_READ 0x0B -#define PSRAM_FAST_READ_QUAD 0xEB -#define PSRAM_WRITE 0x02 -#define PSRAM_QUAD_WRITE 0x38 -#define PSRAM_ENTER_QMODE 0x35 -#define PSRAM_EXIT_QMODE 0xF5 -#define PSRAM_RESET_EN 0x66 -#define PSRAM_RESET 0x99 -#define PSRAM_SET_BURST_LEN 0xC0 -#define PSRAM_DEVICE_ID 0x9F - -#define PSRAM_FAST_READ_DUMMY 4 -#define PSRAM_FAST_READ_QUAD_DUMMY 6 - -// ID -#define PSRAM_ID_BITS_NUM 24 -#define PSRAM_EID_BITS_NUM 48 -#define PSRAM_ID_KGD_M 0xff -#define PSRAM_ID_KGD_S 8 -#define PSRAM_ID_KGD 0x5d -#define PSRAM_ID_EID_BIT_47_40_M 0xff -#define PSRAM_ID_EID_BIT_47_40_S 16 - -// Use the [47:45](bit47~bit45) of EID to distinguish the psram size: -// -// BIT47 | BIT46 | BIT45 | SIZE(MBIT) -// ------------------------------------- -// 0 | 0 | 0 | 16 -// 0 | 0 | 1 | 32 -// 0 | 1 | 0 | 64 -#define PSRAM_EID_BIT_47_45_M 0x07 -#define PSRAM_EID_BIT_47_45_S 5 - -#define PSRAM_KGD(id) (((id) >> PSRAM_ID_KGD_S) & PSRAM_ID_KGD_M) -#define PSRAM_EID_BIT_47_40(id) (((id) >> PSRAM_ID_EID_BIT_47_40_S) & PSRAM_ID_EID_BIT_47_40_M) -#define PSRAM_SIZE_ID(id) ((PSRAM_EID_BIT_47_40(id) >> PSRAM_EID_BIT_47_45_S) & PSRAM_EID_BIT_47_45_M) -#define PSRAM_IS_VALID(id) (PSRAM_KGD(id) == PSRAM_ID_KGD) - -#define PSRAM_IS_64MBIT_TRIAL(id) (PSRAM_EID_BIT_47_40(id) == 0x26) - -// IO-pins for PSRAM. -// PSRAM clock and cs IO should be configured based on hardware design. -#define PSRAM_CLK_IO MSPI_IOMUX_PIN_NUM_CLK -#define PSRAM_CS_IO MSPI_IOMUX_PIN_NUM_CS1 -#define PSRAM_SPIQ_SD0_IO MSPI_IOMUX_PIN_NUM_MISO -#define PSRAM_SPID_SD1_IO MSPI_IOMUX_PIN_NUM_MOSI -#define PSRAM_SPIWP_SD3_IO MSPI_IOMUX_PIN_NUM_WP -#define PSRAM_SPIHD_SD2_IO MSPI_IOMUX_PIN_NUM_HD - -#define PSRAM_CMD_LENGTH 8 -#define PSRAM_ADDR_LENGTH 24 - -#define PSRAM_CS_HOLD_VAL 1 -#define PSRAM_CS_SETUP_VAL 1 - -// QEMU has a simulated 16MB and 32MB Quad SPI PSRAM. Use a fake ID for these. -#define PSRAM_QEMU_16MB_ID 0x6a -#define PSRAM_QEMU_32MB_ID 0x8e - -#ifdef __cplusplus -} -#endif diff --git a/components/esp_psram/device/esp_quad_psram_defs_ap.h b/components/esp_psram/device/esp_quad_psram_defs_ap.h new file mode 100644 index 000000000000..829a1442e12b --- /dev/null +++ b/components/esp_psram/device/esp_quad_psram_defs_ap.h @@ -0,0 +1,87 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +//Commands for PSRAM chip + +#pragma once + +#include "soc/spi_pins.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*--------------------------------------------------------------------------------- + * AP Memory PSRAM + *-------------------------------------------------------------------------------*/ + +#define PSRAM_QUAD_READ 0x03 +#define PSRAM_QUAD_FAST_READ 0x0B +#define PSRAM_QUAD_FAST_READ_QUAD 0xEB +#define PSRAM_QUAD_WRITE 0x02 +#define PSRAM_QUAD_WRITE_QUAD 0x38 +#define PSRAM_QUAD_ENTER_QMODE 0x35 +#define PSRAM_QUAD_EXIT_QMODE 0xF5 +#define PSRAM_QUAD_RESET_EN 0x66 +#define PSRAM_QUAD_RESET 0x99 +#define PSRAM_QUAD_SET_BURST_LEN 0xC0 +#define PSRAM_QUAD_DEVICE_ID 0x9F + +#define PSRAM_QUAD_FAST_READ_DUMMY 4 +#define PSRAM_QUAD_FAST_READ_QUAD_DUMMY 6 + +// ID +#define PSRAM_QUAD_ID_BITS_NUM 24 +#define PSRAM_QUAD_EID_BITS_NUM 48 +#define PSRAM_QUAD_ID_KGD_M 0xff +#define PSRAM_QUAD_ID_KGD_S 8 +#define PSRAM_QUAD_ID_KGD 0x5d +#define PSRAM_QUAD_ID_EID_BIT_47_40_M 0xff +#define PSRAM_QUAD_ID_EID_BIT_47_40_S 16 + +// Use the [47:45](bit47~bit45) of EID to distinguish the psram size: +// +// BIT47 | BIT46 | BIT45 | SIZE(MBIT) +// ------------------------------------- +// 0 | 0 | 0 | 16 +// 0 | 0 | 1 | 32 +// 0 | 1 | 0 | 64 +#define PSRAM_QUAD_EID_BIT_47_45_M 0x07 +#define PSRAM_QUAD_EID_BIT_47_45_S 5 + +#define PSRAM_QUAD_KGD(id) (((id) >> PSRAM_QUAD_ID_KGD_S) & PSRAM_QUAD_ID_KGD_M) +#define PSRAM_QUAD_EID_BIT_47_40(id) (((id) >> PSRAM_QUAD_ID_EID_BIT_47_40_S) & PSRAM_QUAD_ID_EID_BIT_47_40_M) +#define PSRAM_QUAD_SIZE_ID(id) ((PSRAM_QUAD_EID_BIT_47_40(id) >> PSRAM_QUAD_EID_BIT_47_45_S) & PSRAM_QUAD_EID_BIT_47_45_M) +#define PSRAM_QUAD_IS_VALID(id) (PSRAM_QUAD_KGD(id) == PSRAM_QUAD_ID_KGD) + +#define PSRAM_QUAD_IS_64MBIT_TRIAL(id) (PSRAM_QUAD_EID_BIT_47_40(id) == 0x26) + +// IO-pins for PSRAM. +// PSRAM clock and cs IO should be configured based on hardware design. +#define PSRAM_QUAD_CLK_IO MSPI_IOMUX_PIN_NUM_CLK +#define PSRAM_QUAD_CS_IO MSPI_IOMUX_PIN_NUM_CS1 +#define PSRAM_QUAD_SPIQ_SD0_IO MSPI_IOMUX_PIN_NUM_MISO +#define PSRAM_QUAD_SPID_SD1_IO MSPI_IOMUX_PIN_NUM_MOSI +#define PSRAM_QUAD_SPIWP_SD3_IO MSPI_IOMUX_PIN_NUM_WP +#define PSRAM_QUAD_SPIHD_SD2_IO MSPI_IOMUX_PIN_NUM_HD + +#define PSRAM_QUAD_CMD_LENGTH 8 +#define PSRAM_QUAD_ADDR_LENGTH 24 + +#define PSRAM_QUAD_CS_HOLD_VAL 1 +#define PSRAM_QUAD_CS_SETUP_VAL 1 +#define PSRAM_QUAD_CS_ECC_HOLD_TIME_VAL 3 + +#define PSRAM_QUAD_PAGE_SIZE 512 +#define PSRAM_QUAD_ECC_ENABLE_MASK BIT(8) + +// QEMU has a simulated 16MB and 32MB Quad SPI PSRAM. Use a fake ID for these. +#define PSRAM_QUAD_QEMU_16MB_ID 0x6a +#define PSRAM_QUAD_QEMU_32MB_ID 0x8e + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_psram/esp32c5/Kconfig.spiram b/components/esp_psram/esp32c5/Kconfig.spiram index ca941e8f1d55..a27b718f9c56 100644 --- a/components/esp_psram/esp32c5/Kconfig.spiram +++ b/components/esp_psram/esp32c5/Kconfig.spiram @@ -68,5 +68,13 @@ menu "SPI RAM config" This is a helper indicating this condition: `CONFIG_SPIRAM_XIP_FROM_PSRAM && CONFIG_IDF_TARGET_ESP32C5` + config SPIRAM_ECC_ENABLE + bool "Enable PSRAM ECC" + default n + help + Enable MSPI Error-Correcting Code function when accessing PSRAM. + + If enabled, 1/8 of the PSRAM total size will be reserved for error-correcting code. + source "$IDF_PATH/components/esp_psram/Kconfig.spiram.common" # insert non-chip-specific items here endmenu diff --git a/components/esp_psram/esp32c61/Kconfig.spiram b/components/esp_psram/esp32c61/Kconfig.spiram index fefbd96463cb..a5e97acfc624 100644 --- a/components/esp_psram/esp32c61/Kconfig.spiram +++ b/components/esp_psram/esp32c61/Kconfig.spiram @@ -68,5 +68,13 @@ menu "SPI RAM config" This is a helper indicating this condition: `CONFIG_SPIRAM_XIP_FROM_PSRAM && CONFIG_IDF_TARGET_ESP32C61` + config SPIRAM_ECC_ENABLE + bool "Enable PSRAM ECC" + default n + help + Enable MSPI Error-Correcting Code function when accessing PSRAM. + + If enabled, 1/8 of the PSRAM total size will be reserved for error-correcting code. + source "$IDF_PATH/components/esp_psram/Kconfig.spiram.common" # insert non-chip-specific items here endmenu diff --git a/components/esp_psram/esp_psram.c b/components/esp_psram/esp_psram.c index 80a9cdeb5f4c..0ca1f8f79224 100644 --- a/components/esp_psram/esp_psram.c +++ b/components/esp_psram/esp_psram.c @@ -369,7 +369,7 @@ esp_err_t esp_psram_extram_add_to_heap_allocator(void) { esp_err_t ret = ESP_FAIL; - uint32_t byte_aligned_caps[] = {MALLOC_CAP_SPIRAM | MALLOC_CAP_DEFAULT, 0, MALLOC_CAP_8BIT | MALLOC_CAP_32BIT}; + uint32_t byte_aligned_caps[] = {MALLOC_CAP_SPIRAM | MALLOC_CAP_DEFAULT, 0, MALLOC_CAP_8BIT | MALLOC_CAP_32BIT | MALLOC_CAP_SIMD}; ret = heap_caps_add_region_with_caps(byte_aligned_caps, s_psram_ctx.regions_to_heap[PSRAM_MEM_8BIT_ALIGNED].vaddr_start, s_psram_ctx.regions_to_heap[PSRAM_MEM_8BIT_ALIGNED].vaddr_end); diff --git a/components/esp_rom/esp32c2/ld/esp32c2.rom.ble-eco4.ld b/components/esp_rom/esp32c2/ld/esp32c2.rom.ble-eco4.ld index cd2dc6e15da9..5d0a91ae8008 100644 --- a/components/esp_rom/esp32c2/ld/esp32c2.rom.ble-eco4.ld +++ b/components/esp_rom/esp32c2/ld/esp32c2.rom.ble-eco4.ld @@ -192,7 +192,7 @@ r_ble_ll_conn_chk_csm_flags = 0x40000d48; r_ble_ll_conn_chk_phy_upd_start = 0x40000d4c; r_ble_ll_conn_comp_event_send = 0x40000d50; r_ble_ll_conn_connect_ind_pdu_make = 0x40000d54; -r_ble_ll_conn_create = 0x40000d58; +//r_ble_ll_conn_create = 0x40000d58; r_ble_ll_conn_create_cancel = 0x40000d5c; r_ble_ll_conn_created = 0x40000d60; r_ble_ll_conn_cth_flow_enable = 0x40000d64; @@ -322,7 +322,7 @@ r_ble_ll_event_dbuf_overflow = 0x40000f50; r_ble_ll_event_send = 0x40000f54; r_ble_ll_event_tx_pkt = 0x40000f58; r_ble_ll_ext_adv_phy_mode_to_local_phy = 0x40000f5c; -r_ble_ll_ext_conn_create = 0x40000f60; +//r_ble_ll_ext_conn_create = 0x40000f60; r_ble_ll_ext_scan_parse_adv_info = 0x40000f64; r_ble_ll_ext_scan_parse_aux_ptr = 0x40000f68; r_ble_ll_flush_pkt_queue = 0x40000f6c; @@ -489,7 +489,7 @@ r_ble_ll_scan_dup_check_legacy = 0x400011ec; r_ble_ll_scan_dup_move_to_head = 0x400011f0; r_ble_ll_scan_dup_new = 0x400011f4; r_ble_ll_scan_dup_update_ext = 0x400011f8; -r_ble_ll_scan_dup_update_legacy = 0x400011fc; +//r_ble_ll_scan_dup_update_legacy = 0x400011fc; r_ble_ll_scan_enabled = 0x40001200; r_ble_ll_scan_end_adv_evt = 0x40001204; //r_ble_ll_scan_env_init = 0x40001208; @@ -706,7 +706,7 @@ r_ble_lll_conn_process_in_isr = 0x40001550; r_ble_lll_conn_recv_ack = 0x40001554; r_ble_lll_conn_recv_valid_packet = 0x40001558; r_ble_lll_conn_reset_pending_sched = 0x4000155c; -r_ble_lll_conn_rx_pkt_isr = 0x40001560; +//r_ble_lll_conn_rx_pkt_isr = 0x40001560; r_ble_lll_conn_sched_next_anchor = 0x40001564; r_ble_lll_conn_sched_next_event = 0x40001568; r_ble_lll_conn_set_slave_flow_control = 0x4000156c; diff --git a/components/esp_rom/esp32c2/ld/esp32c2.rom.ble.ld b/components/esp_rom/esp32c2/ld/esp32c2.rom.ble.ld index 52c45ef81747..c4e201cc0750 100644 --- a/components/esp_rom/esp32c2/ld/esp32c2.rom.ble.ld +++ b/components/esp_rom/esp32c2/ld/esp32c2.rom.ble.ld @@ -394,7 +394,7 @@ r_ble_ll_scan_dup_check_legacy = 0x400011ec; r_ble_ll_scan_dup_move_to_head = 0x400011f0; r_ble_ll_scan_dup_new = 0x400011f4; r_ble_ll_scan_dup_update_ext = 0x400011f8; -r_ble_ll_scan_dup_update_legacy = 0x400011fc; +//r_ble_ll_scan_dup_update_legacy = 0x400011fc; r_ble_ll_scan_enabled = 0x40001200; r_ble_ll_scan_end_adv_evt = 0x40001204; r_ble_ll_scan_ext_initiator_start = 0x4000120c; @@ -611,7 +611,7 @@ r_ble_lll_per_adv_coex_dpc_update_on_data_updated = 0x40001638; r_ble_lll_per_adv_coex_dpc_update_on_scheduled = 0x4000163c; r_ble_lll_per_adv_coex_dpc_update_on_start = 0x40001640; r_ble_lll_rfmgmt_is_enabled = 0x40001660; -r_ble_lll_rfmgmt_release = 0x40001664; +//r_ble_lll_rfmgmt_release = 0x40001664; r_ble_lll_rfmgmt_scan_changed = 0x40001670; r_ble_lll_rfmgmt_sched_changed = 0x40001674; r_ble_lll_rfmgmt_set_sleep_cb = 0x40001678; diff --git a/components/esp_rom/esp32c61/ld/esp32c61.rom.pp.ld b/components/esp_rom/esp32c61/ld/esp32c61.rom.pp.ld index 7362e8be002f..dcc07aab8029 100644 --- a/components/esp_rom/esp32c61/ld/esp32c61.rom.pp.ld +++ b/components/esp_rom/esp32c61/ld/esp32c61.rom.pp.ld @@ -122,7 +122,7 @@ pm_local_tsf_process = 0x40000cd4; pm_set_beacon_filter = 0x40000cd8; pm_is_in_wifi_slice_threshold = 0x40000cdc; pm_is_waked = 0x40000ce0; -pm_keep_alive = 0x40000ce4; +//pm_keep_alive = 0x40000ce4; pm_on_beacon_rx = 0x40000ce8; pm_on_data_rx = 0x40000cec; pm_on_data_tx = 0x40000cf0; diff --git a/components/esp_rom/patches/esp_rom_spiflash.c b/components/esp_rom/patches/esp_rom_spiflash.c index 50ac4aaa765d..73ff4c92a7ed 100644 --- a/components/esp_rom/patches/esp_rom_spiflash.c +++ b/components/esp_rom/patches/esp_rom_spiflash.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 */ @@ -24,8 +24,6 @@ #define SPI_IDX 1 -#if CONFIG_SPI_FLASH_ROM_DRIVER_PATCH - #if CONFIG_IDF_TARGET_ESP32 extern esp_rom_spiflash_chip_t g_rom_spiflash_chip; @@ -111,6 +109,12 @@ __attribute__((__unused__)) esp_rom_spiflash_result_t esp_rom_spiflash_clear_bp( } esp_rom_spiflash_result_t esp_rom_spiflash_unlock(void) __attribute__((alias("esp_rom_spiflash_clear_bp"))); +#endif // CONFIG_IDF_TARGET_ESP32 + +#if CONFIG_SPI_FLASH_ROM_DRIVER_PATCH + +#if CONFIG_IDF_TARGET_ESP32 + static esp_rom_spiflash_result_t esp_rom_spiflash_enable_write(esp_rom_spiflash_chip_t *spi); //only support spi1 diff --git a/components/esp_security/Kconfig b/components/esp_security/Kconfig index bedc822779be..7a8c9ff63164 100644 --- a/components/esp_security/Kconfig +++ b/components/esp_security/Kconfig @@ -38,7 +38,7 @@ menu "ESP Security Specific" endmenu config ESP_CRYPTO_FORCE_ECC_CONSTANT_TIME_POINT_MUL - bool "Forcfully enable ECC constant time point multiplication operations" + bool "Forcefully enable ECC constant time point multiplication operations" depends on SOC_ECC_CONSTANT_TIME_POINT_MUL default N help diff --git a/components/esp_security/src/init.c b/components/esp_security/src/init.c index d12e1fe3265d..ab75144cdac6 100644 --- a/components/esp_security/src/init.c +++ b/components/esp_security/src/init.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 */ @@ -12,6 +12,8 @@ #include "esp_efuse_table.h" #include "esp_security_priv.h" #include "esp_err.h" +#include "hal/efuse_hal.h" + #if SOC_KEY_MANAGER_ECDSA_KEY_DEPLOY || SOC_KEY_MANAGER_FE_KEY_DEPLOY #include "hal/key_mgr_ll.h" #endif @@ -40,8 +42,14 @@ ESP_SYSTEM_INIT_FN(esp_security_init, SECONDARY, BIT(0), 103) esp_crypto_dpa_protection_startup(); #endif -#ifdef CONFIG_ESP_CRYPTO_FORCE_ECC_CONSTANT_TIME_POINT_MUL - if (!esp_efuse_read_field_bit(ESP_EFUSE_ECC_FORCE_CONST_TIME)) { +#if CONFIG_ESP_CRYPTO_FORCE_ECC_CONSTANT_TIME_POINT_MUL + bool force_constant_time = true; +#if CONFIG_IDF_TARGET_ESP32H2 + if (!ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 102)) { + force_constant_time = false; + } +#endif + if (!esp_efuse_read_field_bit(ESP_EFUSE_ECC_FORCE_CONST_TIME) && force_constant_time) { ESP_EARLY_LOGD(TAG, "Forcefully enabling ECC constant time operations"); esp_err_t err = esp_efuse_write_field_bit(ESP_EFUSE_ECC_FORCE_CONST_TIME); if (err != ESP_OK) { diff --git a/components/esp_system/crosscore_int.c b/components/esp_system/crosscore_int.c index 551184b525b3..77620417aac5 100644 --- a/components/esp_system/crosscore_int.c +++ b/components/esp_system/crosscore_int.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 */ @@ -11,6 +11,7 @@ #include "esp_intr_alloc.h" #include "esp_debug_helpers.h" #include "soc/periph_defs.h" +#include "soc/system_intr.h" #include "hal/crosscore_int_ll.h" #include "freertos/FreeRTOS.h" @@ -20,10 +21,6 @@ #include "esp_gdbstub.h" #endif -#if CONFIG_IDF_TARGET_ESP32H21 -#define ETS_FROM_CPU_INTR0_SOURCE ETS_CPU_INTR_FROM_CPU_0_SOURCE -#endif - #define REASON_YIELD BIT(0) #define REASON_FREQ_SWITCH BIT(1) #define REASON_PRINT_BACKTRACE BIT(2) @@ -98,12 +95,12 @@ void esp_crosscore_int_init(void) esp_err_t err __attribute__((unused)) = ESP_OK; #if CONFIG_FREERTOS_NUMBER_OF_CORES > 1 if (esp_cpu_get_core_id() == 0) { - err = esp_intr_alloc(ETS_FROM_CPU_INTR0_SOURCE, ESP_INTR_FLAG_IRAM, esp_crosscore_isr, (void*)&reason[0], NULL); + err = esp_intr_alloc(SYS_CPU_INTR_FROM_CPU_0_SOURCE, ESP_INTR_FLAG_IRAM, esp_crosscore_isr, (void*)&reason[0], NULL); } else { - err = esp_intr_alloc(ETS_FROM_CPU_INTR1_SOURCE, ESP_INTR_FLAG_IRAM, esp_crosscore_isr, (void*)&reason[1], NULL); + err = esp_intr_alloc(SYS_CPU_INTR_FROM_CPU_1_SOURCE, ESP_INTR_FLAG_IRAM, esp_crosscore_isr, (void*)&reason[1], NULL); } #else - err = esp_intr_alloc(ETS_FROM_CPU_INTR0_SOURCE, ESP_INTR_FLAG_IRAM, esp_crosscore_isr, (void*)&reason[0], NULL); + err = esp_intr_alloc(SYS_CPU_INTR_FROM_CPU_0_SOURCE, ESP_INTR_FLAG_IRAM, esp_crosscore_isr, (void*)&reason[0], NULL); #endif ESP_ERROR_CHECK(err); } diff --git a/components/esp_system/int_wdt.c b/components/esp_system/int_wdt.c index 90f9daf719f4..50bae64fc318 100644 --- a/components/esp_system/int_wdt.c +++ b/components/esp_system/int_wdt.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 */ @@ -12,6 +12,7 @@ #include "hal/wdt_hal.h" #include "hal/mwdt_ll.h" #include "hal/timer_ll.h" +#include "soc/system_intr.h" #include "freertos/FreeRTOS.h" #include "esp_cpu.h" #include "esp_check.h" @@ -28,15 +29,10 @@ #include "esp_private/sleep_retention.h" #endif -#if CONFIG_IDF_TARGET_ESP32H21 -#define ETS_TG0_WDT_LEVEL_INTR_SOURCE ETS_TG0_WDT_INTR_SOURCE -#define ETS_TG1_WDT_LEVEL_INTR_SOURCE ETS_TG1_WDT_INTR_SOURCE -#endif - #if SOC_TIMER_GROUPS > 1 /* If we have two hardware timer groups, use the second one for interrupt watchdog. */ -#define WDT_LEVEL_INTR_SOURCE ETS_TG1_WDT_LEVEL_INTR_SOURCE +#define WDT_LEVEL_INTR_SOURCE SYS_TG1_WDT_INTR_SOURCE #define IWDT_PRESCALER MWDT_LL_DEFAULT_CLK_PRESCALER // Tick period of 500us if WDT source clock is 80MHz #define IWDT_TICKS_PER_US 500 #define IWDT_INSTANCE WDT_MWDT1 @@ -46,7 +42,7 @@ #else -#define WDT_LEVEL_INTR_SOURCE ETS_TG0_WDT_LEVEL_INTR_SOURCE +#define WDT_LEVEL_INTR_SOURCE SYS_TG0_WDT_INTR_SOURCE #define IWDT_PRESCALER MWDT_LL_DEFAULT_CLK_PRESCALER // Tick period of 500us if WDT source clock is 80MHz #define IWDT_TICKS_PER_US 500 #define IWDT_INSTANCE WDT_MWDT0 diff --git a/components/esp_system/port/cpu_start.c b/components/esp_system/port/cpu_start.c index 208729117cb8..1ef9b2c05d23 100644 --- a/components/esp_system/port/cpu_start.c +++ b/components/esp_system/port/cpu_start.c @@ -53,7 +53,6 @@ #elif CONFIG_IDF_TARGET_ESP32H2 #include "esp32h2/rom/cache.h" #include "esp_memprot.h" -#include "soc/lpperi_struct.h" #elif CONFIG_IDF_TARGET_ESP32C2 #include "esp32c2/rom/cache.h" #include "esp32c2/rom/secure_boot.h" @@ -453,13 +452,6 @@ void IRAM_ATTR call_start_cpu0(void) } #endif -#if CONFIG_IDF_TARGET_ESP32H2 - // Some modules' register layout are not binary compatible among the different chip revisions, - // they will be wrapped into a new compatible instance which will point to the correct register address according to the revision. - // To ensure the compatible instance is initialized before used, the initialization is done after BBS is cleared - lpperi_compatible_reg_addr_init(); -#endif - #if !CONFIG_APP_BUILD_TYPE_PURE_RAM_APP && !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE && !SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE // It helps to fix missed cache settings for other cores. It happens when bootloader is unicore. do_multicore_settings(); diff --git a/components/esp_system/port/soc/esp32c5/clk.c b/components/esp_system/port/soc/esp32c5/clk.c index a617a63e5417..77f43e6f272f 100644 --- a/components/esp_system/port/soc/esp32c5/clk.c +++ b/components/esp_system/port/soc/esp32c5/clk.c @@ -23,6 +23,7 @@ #include "esp_cpu.h" #include "hal/efuse_hal.h" #include "hal/wdt_hal.h" +#include "hal/clk_tree_ll.h" #if SOC_MODEM_CLOCK_SUPPORTED #include "hal/modem_lpcon_ll.h" #endif @@ -222,14 +223,12 @@ __attribute__((weak)) void esp_perip_clk_init(void) modem_clock_select_lp_clock_source(PERIPH_WIFI_MODULE, modem_lpclk_src, 0); #endif - if (ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 1)) { - /* On ESP32-C5 ECO1, clearing BIT(31) of PCR_FPGA_DEBUG_REG is used to fix - * the issue where the modem module fails to transmit and receive packets - * due to the loss of the modem root clock caused by automatic clock gating - * during soc root clock source switching. For detailed information, refer - * to IDF-11064. */ - REG_CLR_BIT(PCR_FPGA_DEBUG_REG, BIT(31)); - } + /* On ESP32-C5 ECO1, clearing BIT(31) of PCR_FPGA_DEBUG_REG is used to fix + * the issue where the modem module fails to transmit and receive packets + * due to the loss of the modem root clock caused by automatic clock gating + * during soc root clock source switching. For detailed information, refer + * to IDF-11064. */ + clk_ll_soc_root_clk_auto_gating_bypass(true); ESP_EARLY_LOGW(TAG, "esp_perip_clk_init() has not been implemented yet"); #if 0 // TODO: [ESP32C5] IDF-8844 diff --git a/components/esp_system/startup_funcs.c b/components/esp_system/startup_funcs.c index 5c7ce4449251..2855dc325a02 100644 --- a/components/esp_system/startup_funcs.c +++ b/components/esp_system/startup_funcs.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 */ @@ -41,6 +41,7 @@ #include "esp_private/esp_clk.h" #include "esp_private/spi_flash_os.h" #include "esp_private/brownout.h" +#include "esp_private/vbat.h" #include "esp_rom_caps.h" #include "esp_rom_sys.h" @@ -78,6 +79,7 @@ ESP_SYSTEM_INIT_FN(init_brownout, CORE, BIT(0), 104) { // [refactor-todo] leads to call chain rtc_is_register (driver) -> esp_intr_alloc (esp32/esp32s2) -> // malloc (newlib) -> heap_caps_malloc (heap), so heap must be at least initialized + esp_err_t ret = ESP_OK; #if CONFIG_ESP_BROWNOUT_DET esp_brownout_init(); #else @@ -85,7 +87,12 @@ ESP_SYSTEM_INIT_FN(init_brownout, CORE, BIT(0), 104) brownout_ll_ana_reset_enable(false); #endif // SOC_CAPS_NO_RESET_BY_ANA_BOD #endif // CONFIG_ESP_BROWNOUT_DET - return ESP_OK; + +#if CONFIG_ESP_VBAT_INIT_AUTO + ret = esp_vbat_init(); +#endif + + return ret; } #endif diff --git a/components/esp_system/task_wdt/task_wdt_impl_timergroup.c b/components/esp_system/task_wdt/task_wdt_impl_timergroup.c index 628e5bb7f586..bb972c2f9417 100644 --- a/components/esp_system/task_wdt/task_wdt_impl_timergroup.c +++ b/components/esp_system/task_wdt/task_wdt_impl_timergroup.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 */ @@ -11,6 +11,7 @@ #include "hal/wdt_hal.h" #include "hal/mwdt_ll.h" #include "hal/timer_ll.h" +#include "soc/system_intr.h" #include "esp_check.h" #include "esp_err.h" #include "esp_attr.h" @@ -29,11 +30,8 @@ #define TWDT_PRESCALER MWDT_LL_DEFAULT_CLK_PRESCALER // Tick period of 500us if WDT source clock is 80MHz #define TWDT_PERIPH_MODULE PERIPH_TIMG0_MODULE #define TWDT_TIMER_GROUP 0 -#if CONFIG_IDF_TARGET_ESP32H21 -#define TWDT_INTR_SOURCE ETS_TG0_WDT_INTR_SOURCE -#else -#define TWDT_INTR_SOURCE ETS_TG0_WDT_LEVEL_INTR_SOURCE -#endif +#define TWDT_INTR_SOURCE SYS_TG0_WDT_INTR_SOURCE + /** * Context for the software implementation of the Task WatchDog Timer. * This will be passed as a parameter to public functions below. */ diff --git a/components/esp_tee/include/esp_tee.h b/components/esp_tee/include/esp_tee.h index 3afd53b8bc3c..c22d887b493c 100644 --- a/components/esp_tee/include/esp_tee.h +++ b/components/esp_tee/include/esp_tee.h @@ -52,6 +52,7 @@ typedef struct { void *ns_int_handler; void *ns_iram_end; void *ns_irom_end; + void *ns_drom_start; void *ns_drom_end; } __attribute__((aligned(4))) __attribute__((__packed__)) esp_tee_config_t; diff --git a/components/esp_tee/include/private/esp_tee_binary.h b/components/esp_tee/include/private/esp_tee_binary.h index 0599531a8a2e..4870db5b9530 100644 --- a/components/esp_tee/include/private/esp_tee_binary.h +++ b/components/esp_tee/include/private/esp_tee_binary.h @@ -37,6 +37,9 @@ extern "C" { #define SOC_S_IROM_HIGH (SOC_IROM_LOW + SOC_S_IDROM_SIZE) #define SOC_S_DROM_LOW (SOC_DROM_LOW) #define SOC_S_DROM_HIGH (SOC_DROM_LOW + SOC_S_IDROM_SIZE) +/* REE I/DRAM */ +#define SOC_NS_IDRAM_START (SOC_S_DRAM_END) +#define SOC_NS_IDRAM_END (SOC_DIRAM_DRAM_HIGH) #define SOC_MMU_TOTAL_SIZE (SOC_DRAM0_CACHE_ADDRESS_HIGH - SOC_DRAM0_CACHE_ADDRESS_LOW) #define SOC_MMU_END_VADDR (SOC_DROM_LOW + SOC_MMU_TOTAL_SIZE) @@ -47,6 +50,10 @@ extern "C" { #include #include +/* Secure Service table */ +typedef void (*secure_service_t)(void); +extern const secure_service_t tee_secure_service_table[]; + /** * @brief TEE initialization function called by the bootloader at boot time. * Performs secure system initialization before switching to the REE. diff --git a/components/esp_tee/src/esp_tee_config.c b/components/esp_tee/src/esp_tee_config.c index fce4c7ddf8ff..eec0210f9e36 100644 --- a/components/esp_tee/src/esp_tee_config.c +++ b/components/esp_tee/src/esp_tee_config.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -15,6 +15,8 @@ extern uint32_t _u2m_switch(int argc, va_list ap); extern uint32_t _iram_end; /* REE IROM end */ extern uint32_t _instruction_reserved_end; +/* REE DROM start */ +extern uint32_t _rodata_reserved_start; /* REE DROM end */ extern uint32_t _rodata_reserved_end; @@ -31,5 +33,6 @@ esp_tee_config_t esp_tee_app_config __attribute__((section(".esp_tee_app_cfg"))) .ns_entry_addr = &_u2m_switch, .ns_iram_end = &_iram_end, .ns_irom_end = &_instruction_reserved_end, + .ns_drom_start = &_rodata_reserved_start, .ns_drom_end = &_rodata_reserved_end, }; diff --git a/components/esp_tee/subproject/main/CMakeLists.txt b/components/esp_tee/subproject/main/CMakeLists.txt index ebdf46b7c040..8eb3d1c693e2 100644 --- a/components/esp_tee/subproject/main/CMakeLists.txt +++ b/components/esp_tee/subproject/main/CMakeLists.txt @@ -15,6 +15,7 @@ set(include) set(srcs "core/esp_tee_init.c" "core/esp_tee_intr.c" "core/esp_secure_services.c" + "core/esp_secure_dispatcher.c" "core/esp_secure_service_table.c") # Arch specific implementation for TEE diff --git a/components/esp_tee/subproject/main/core/esp_secure_dispatcher.c b/components/esp_tee/subproject/main/core/esp_secure_dispatcher.c new file mode 100644 index 000000000000..51df15a5d996 --- /dev/null +++ b/components/esp_tee/subproject/main/core/esp_secure_dispatcher.c @@ -0,0 +1,110 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "esp_log.h" +#include "esp_tee.h" +#include "secure_service_num.h" + +#define ESP_TEE_MAX_INPUT_ARG 10 + +static const char *TAG = "esp_tee_sec_disp"; + +/** + * @brief Entry point to the TEE binary during secure service call. It decipher the call and dispatch it + * to corresponding Secure Service API in secure world. + * TODO: Fix the assembly routine here for compatibility with all levels of compiler optimizations + */ +#pragma GCC push_options +#pragma GCC optimize ("Og") + +int esp_tee_service_dispatcher(int argc, va_list ap) +{ + if (argc > ESP_TEE_MAX_INPUT_ARG) { + ESP_LOGE(TAG, "Input arguments overflow! Received %d, Permitted %d", + argc, ESP_TEE_MAX_INPUT_ARG); + return -1; + } + + int ret = -1; + void *fp_secure_service; + uint32_t argv[ESP_TEE_MAX_INPUT_ARG], *argp; + + uint32_t sid = va_arg(ap, uint32_t); + argc--; + + if (sid >= MAX_SECURE_SERVICES) { + ESP_LOGE(TAG, "Invalid Service ID!"); + va_end(ap); + return -1; + } + + fp_secure_service = (void *)tee_secure_service_table[sid]; + + for (int i = 0; i < argc; i++) { + argv[i] = va_arg(ap, uint32_t); + } + argp = &argv[0]; + va_end(ap); + + asm volatile( + "mv t0, %1 \n" + "beqz t0, service_call \n" + + "lw a0, 0(%3) \n" + "addi t0, t0, -1 \n" + "beqz t0, service_call \n" + + "lw a1, 4(%3) \n" + "addi t0, t0, -1 \n" + "beqz t0, service_call \n" + + "lw a2, 8(%3) \n" + "addi t0, t0, -1 \n" + "beqz t0, service_call \n" + + "lw a3, 12(%3) \n" + "addi t0, t0, -1 \n" + "beqz t0, service_call \n" + + "lw a4, 16(%3) \n" + "addi t0, t0, -1 \n" + "beqz t0, service_call \n" + + "lw a5, 20(%3) \n" + "addi t0, t0, -1 \n" + "beqz t0, service_call \n" + + "lw a6, 24(%3) \n" + "addi t0, t0, -1 \n" + "beqz t0, service_call \n" + + "lw a7, 28(%3) \n" + "addi t0, t0, -1 \n" + "beqz t0, service_call \n" + + "addi %3, %3, 32 \n" + "mv t2, sp \n" + "loop: \n" + "lw t1, 0(%3) \n" + "sw t1, 0(t2) \n" + "addi t0, t0, -1 \n" + "addi t2, t2, 4 \n" + "addi %3, %3, 4 \n" + "bnez t0, loop \n" + + "service_call: \n" + "mv t1, %2 \n" + "jalr 0(t1) \n" + "mv %0, a0 \n" + : "=r"(ret) + : "r"(argc), "r"(fp_secure_service), "r"(argp) + : "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "t0", "t1", "t2" + ); + + return ret; +} +#pragma GCC pop_options diff --git a/components/esp_tee/subproject/main/core/esp_secure_services.c b/components/esp_tee/subproject/main/core/esp_secure_services.c index 99a84910493c..e90fdb6b303e 100644 --- a/components/esp_tee/subproject/main/core/esp_secure_services.c +++ b/components/esp_tee/subproject/main/core/esp_secure_services.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 */ @@ -7,6 +7,7 @@ #include "esp_cpu.h" #include "esp_efuse.h" +#include "esp_fault.h" #include "esp_flash.h" #include "esp_flash_encrypt.h" #include "esp_rom_efuse.h" @@ -23,7 +24,6 @@ #include "sha/sha_dma.h" #include "esp_tee.h" -#include "secure_service_num.h" #include "esp_tee_intr.h" #include "esp_tee_aes_intr.h" #include "esp_tee_rv_utils.h" @@ -33,13 +33,19 @@ #include "esp_tee_ota_ops.h" #include "esp_attestation.h" -#define ESP_TEE_MAX_INPUT_ARG 10 - -static const char *TAG = "esp_tee_sec_srv"; - -typedef void (*secure_service_t)(void); - -extern const secure_service_t tee_secure_service_table[]; +FORCE_INLINE_ATTR bool is_valid_ree_address(const void *ree_addr) +{ + return ((((size_t)ree_addr >= SOC_NS_IDRAM_START) && + ((size_t)ree_addr < SOC_NS_IDRAM_END) + ) || + ((ree_addr >= esp_tee_app_config.ns_drom_start) && + ((size_t)ree_addr < SOC_S_MMU_MMAP_RESV_START_VADDR) + ) || + (((size_t)ree_addr >= SOC_RTC_DATA_LOW) && + ((size_t)ree_addr < SOC_RTC_DATA_HIGH) + ) + ); +} void _ss_invalid_secure_service(void) { @@ -107,6 +113,15 @@ bool _ss_efuse_hal_get_disable_wafer_version_major(void) void _ss_efuse_hal_get_mac(uint8_t *mac) { + bool valid_addr = ((is_valid_ree_address((void *)mac)) & + (is_valid_ree_address((void *)(mac + 6)))); + + if (!valid_addr) { + return; + } + + ESP_FAULT_ASSERT(valid_addr); + efuse_hal_get_mac(mac); } @@ -169,6 +184,15 @@ int _ss_esp_aes_crypt_cbc(esp_aes_context *ctx, const unsigned char *input, unsigned char *output) { + bool valid_addr = ((is_valid_ree_address((void *)input) && is_valid_ree_address((void *)output)) & + (is_valid_ree_address((void *)(input + length)) && is_valid_ree_address((void *)(output + length)))); + + if (!valid_addr) { + return -1; + } + + ESP_FAULT_ASSERT(valid_addr); + return esp_aes_crypt_cbc(ctx, mode, length, iv, input, output); } @@ -180,6 +204,15 @@ int _ss_esp_aes_crypt_cfb128(esp_aes_context *ctx, const unsigned char *input, unsigned char *output) { + bool valid_addr = ((is_valid_ree_address((void *)input) && is_valid_ree_address((void *)output)) & + (is_valid_ree_address((void *)(input + length)) && is_valid_ree_address((void *)(output + length)))); + + if (!valid_addr) { + return -1; + } + + ESP_FAULT_ASSERT(valid_addr); + return esp_aes_crypt_cfb128(ctx, mode, length, iv_off, iv, input, output); } @@ -190,6 +223,15 @@ int _ss_esp_aes_crypt_cfb8(esp_aes_context *ctx, const unsigned char *input, unsigned char *output) { + bool valid_addr = ((is_valid_ree_address((void *)input) && is_valid_ree_address((void *)output)) & + (is_valid_ree_address((void *)(input + length)) && is_valid_ree_address((void *)(output + length)))); + + if (!valid_addr) { + return -1; + } + + ESP_FAULT_ASSERT(valid_addr); + return esp_aes_crypt_cfb8(ctx, mode, length, iv, input, output); } @@ -201,6 +243,15 @@ int _ss_esp_aes_crypt_ctr(esp_aes_context *ctx, const unsigned char *input, unsigned char *output) { + bool valid_addr = ((is_valid_ree_address((void *)input) && is_valid_ree_address((void *)output)) & + (is_valid_ree_address((void *)(input + length)) && is_valid_ree_address((void *)(output + length)))); + + if (!valid_addr) { + return -1; + } + + ESP_FAULT_ASSERT(valid_addr); + return esp_aes_crypt_ctr(ctx, length, nc_off, nonce_counter, stream_block, input, output); } @@ -209,6 +260,15 @@ int _ss_esp_aes_crypt_ecb(esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16]) { + bool valid_addr = ((is_valid_ree_address((void *)input) && is_valid_ree_address((void *)output)) & + (is_valid_ree_address((void *)(input + 16)) && is_valid_ree_address((void *)(output + 16)))); + + if (!valid_addr) { + return -1; + } + + ESP_FAULT_ASSERT(valid_addr); + return esp_aes_crypt_ecb(ctx, mode, input, output); } @@ -219,6 +279,15 @@ int _ss_esp_aes_crypt_ofb(esp_aes_context *ctx, const unsigned char *input, unsigned char *output) { + bool valid_addr = ((is_valid_ree_address((void *)input) && is_valid_ree_address((void *)output)) & + (is_valid_ree_address((void *)(input + length)) && is_valid_ree_address((void *)(output + length)))); + + if (!valid_addr) { + return -1; + } + + ESP_FAULT_ASSERT(valid_addr); + return esp_aes_crypt_ofb(ctx, length, iv_off, iv, input, output); } @@ -226,12 +295,35 @@ int _ss_esp_aes_crypt_ofb(esp_aes_context *ctx, void _ss_esp_sha(esp_sha_type sha_type, const unsigned char *input, size_t ilen, unsigned char *output) { + bool valid_addr = ((is_valid_ree_address((void *)input) && is_valid_ree_address((void *)output)) & + (is_valid_ree_address((void *)(input + ilen)))); + + if (!valid_addr) { + return; + } + + ESP_FAULT_ASSERT(valid_addr); + esp_sha(sha_type, input, ilen, output); } int _ss_esp_sha_dma(esp_sha_type sha_type, const void *input, uint32_t ilen, const void *buf, uint32_t buf_len, bool is_first_block) { + bool valid_addr = (is_valid_ree_address((void *)input) && + is_valid_ree_address((void *)((char *)input + ilen)) + ); + if (buf_len) { + valid_addr &= (is_valid_ree_address((void *)buf) && + is_valid_ree_address((void *)((char *)buf + buf_len)) + ); + } + + if (!valid_addr) { + return -1; + } + ESP_FAULT_ASSERT(valid_addr); + return esp_sha_dma(sha_type, input, ilen, buf, buf_len, is_first_block); } @@ -254,6 +346,15 @@ int _ss_esp_tee_ota_begin(void) int _ss_esp_tee_ota_write(uint32_t rel_offset, void *data, size_t size) { + bool valid_addr = ((is_valid_ree_address((void *)data)) & + (is_valid_ree_address((void *)((char *)data + size)))); + + if (!valid_addr) { + return -1; + } + + ESP_FAULT_ASSERT(valid_addr); + return esp_tee_ota_write(rel_offset, data, size); } @@ -276,23 +377,76 @@ esp_err_t _ss_esp_tee_sec_storage_gen_key(uint16_t slot_id, uint8_t key_type) esp_err_t _ss_esp_tee_sec_storage_get_signature(uint16_t slot_id, uint8_t *hash, size_t hlen, esp_tee_sec_storage_sign_t *out_sign) { + bool valid_addr = ((is_valid_ree_address((void *)hash) && is_valid_ree_address((void *)out_sign)) & + (is_valid_ree_address((void *)(hash + hlen)) && + is_valid_ree_address((void *)((char *)out_sign + sizeof(esp_tee_sec_storage_sign_t))))); + + if (!valid_addr) { + return ESP_ERR_INVALID_ARG; + } + + ESP_FAULT_ASSERT(valid_addr); + return esp_tee_sec_storage_get_signature(slot_id, hash, hlen, out_sign); } esp_err_t _ss_esp_tee_sec_storage_get_pubkey(uint16_t slot_id, esp_tee_sec_storage_pubkey_t *pubkey) { + bool valid_addr = ((is_valid_ree_address((void *)pubkey)) & + (is_valid_ree_address((void *)((char *)pubkey + sizeof(esp_tee_sec_storage_pubkey_t))))); + + if (!valid_addr) { + return ESP_ERR_INVALID_ARG; + } + + ESP_FAULT_ASSERT(valid_addr); + return esp_tee_sec_storage_get_pubkey(slot_id, pubkey); } esp_err_t _ss_esp_tee_sec_storage_encrypt(uint16_t slot_id, uint8_t *input, uint8_t len, uint8_t *aad, uint16_t aad_len, uint8_t *tag, uint16_t tag_len, uint8_t *output) { + bool valid_addr = (is_valid_ree_address((void *)input) && is_valid_ree_address((void *)tag) && + is_valid_ree_address((void *)output)); + + valid_addr &= (is_valid_ree_address((void *)(input + len)) && is_valid_ree_address((void *)(tag + tag_len)) && + is_valid_ree_address((void *)(output + len)) + ); + + if (aad) { + valid_addr &= (is_valid_ree_address((void *)aad) && is_valid_ree_address((void *)(aad + aad_len))); + } + + if (!valid_addr) { + return ESP_ERR_INVALID_ARG; + } + + ESP_FAULT_ASSERT(valid_addr); + return esp_tee_sec_storage_encrypt(slot_id, input, len, aad, aad_len, tag, tag_len, output); } esp_err_t _ss_esp_tee_sec_storage_decrypt(uint16_t slot_id, uint8_t *input, uint8_t len, uint8_t *aad, uint16_t aad_len, uint8_t *tag, uint16_t tag_len, uint8_t *output) { + bool valid_addr = (is_valid_ree_address((void *)input) && is_valid_ree_address((void *)tag) && + is_valid_ree_address((void *)output)); + + valid_addr &= (is_valid_ree_address((void *)(input + len)) && is_valid_ree_address((void *)(tag + tag_len)) && + is_valid_ree_address((void *)(output + len)) + ); + + if (aad) { + valid_addr &= (is_valid_ree_address((void *)aad) && is_valid_ree_address((void *)(aad + aad_len))); + } + + if (!valid_addr) { + return ESP_ERR_INVALID_ARG; + } + + ESP_FAULT_ASSERT(valid_addr); + return esp_tee_sec_storage_decrypt(slot_id, input, len, aad, aad_len, tag, tag_len, output); } @@ -311,11 +465,21 @@ esp_err_t _ss_esp_tee_sec_storage_clear_slot(uint16_t slot_id) esp_err_t _ss_esp_tee_att_generate_token(const uint32_t nonce, const uint32_t client_id, const char *psa_cert_ref, uint8_t *token_buf, const size_t token_buf_size, uint32_t *token_len) { + bool valid_addr = (is_valid_ree_address((void *)psa_cert_ref) && is_valid_ree_address((void *)token_buf) && + is_valid_ree_address((void *)token_len)); + + valid_addr &= (is_valid_ree_address((void *)((char *)psa_cert_ref + 32)) && is_valid_ree_address((void *)((char *)token_buf + token_buf_size))); + + if (!valid_addr) { + return ESP_ERR_INVALID_ARG; + } + + ESP_FAULT_ASSERT(valid_addr); + return esp_att_generate_token(nonce, client_id, psa_cert_ref, token_buf, token_buf_size, token_len); } /* ---------------------------------------------- MMU HAL ------------------------------------------------- */ - void _ss_mmu_hal_map_region(uint32_t mmu_id, mmu_target_t mem_type, uint32_t vaddr, uint32_t paddr, uint32_t len, uint32_t *out_len) { @@ -359,102 +523,3 @@ bool _ss_mmu_hal_paddr_to_vaddr(uint32_t mmu_id, uint32_t paddr, mmu_target_t ta ESP_FAULT_ASSERT(!paddr_chk); return mmu_hal_paddr_to_vaddr(mmu_id, paddr, target, type, out_vaddr); } - -/* ---------------------------------------------- Secure Service Dispatcher ------------------------------------------------- */ - -/** - * @brief Entry point to the TEE binary during secure service call. It decipher the call and dispatch it - * to corresponding Secure Service API in secure world. - * TODO: Fix the assembly routine here for compatibility with all levels of compiler optimizations - */ -#pragma GCC push_options -#pragma GCC optimize ("Og") - -int esp_tee_service_dispatcher(int argc, va_list ap) -{ - if (argc > ESP_TEE_MAX_INPUT_ARG) { - ESP_LOGE(TAG, "Input arguments overflow! Received %d, Permitted %d", - argc, ESP_TEE_MAX_INPUT_ARG); - return -1; - } - - int ret = -1; - void *fp_secure_service; - uint32_t argv[ESP_TEE_MAX_INPUT_ARG], *argp; - - uint32_t sid = va_arg(ap, uint32_t); - argc--; - - if (sid >= MAX_SECURE_SERVICES) { - ESP_LOGE(TAG, "Invalid Service ID!"); - va_end(ap); - return -1; - } - - fp_secure_service = (void *)tee_secure_service_table[sid]; - - for (int i = 0; i < argc; i++) { - argv[i] = va_arg(ap, uint32_t); - } - argp = &argv[0]; - va_end(ap); - - asm volatile( - "mv t0, %1 \n" - "beqz t0, service_call \n" - - "lw a0, 0(%3) \n" - "addi t0, t0, -1 \n" - "beqz t0, service_call \n" - - "lw a1, 4(%3) \n" - "addi t0, t0, -1 \n" - "beqz t0, service_call \n" - - "lw a2, 8(%3) \n" - "addi t0, t0, -1 \n" - "beqz t0, service_call \n" - - "lw a3, 12(%3) \n" - "addi t0, t0, -1 \n" - "beqz t0, service_call \n" - - "lw a4, 16(%3) \n" - "addi t0, t0, -1 \n" - "beqz t0, service_call \n" - - "lw a5, 20(%3) \n" - "addi t0, t0, -1 \n" - "beqz t0, service_call \n" - - "lw a6, 24(%3) \n" - "addi t0, t0, -1 \n" - "beqz t0, service_call \n" - - "lw a7, 28(%3) \n" - "addi t0, t0, -1 \n" - "beqz t0, service_call \n" - - "addi %3, %3, 32 \n" - "mv t2, sp \n" - "loop: \n" - "lw t1, 0(%3) \n" - "sw t1, 0(t2) \n" - "addi t0, t0, -1 \n" - "addi t2, t2, 4 \n" - "addi %3, %3, 4 \n" - "bnez t0, loop \n" - - "service_call: \n" - "mv t1, %2 \n" - "jalr 0(t1) \n" - "mv %0, a0 \n" - : "=r"(ret) - : "r"(argc), "r"(fp_secure_service), "r"(argp) - : "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "t0", "t1", "t2" - ); - - return ret; -} - -#pragma GCC pop_options diff --git a/components/esp_wifi/lib b/components/esp_wifi/lib index 83cfa7ecceb7..196459bdee76 160000 --- a/components/esp_wifi/lib +++ b/components/esp_wifi/lib @@ -1 +1 @@ -Subproject commit 83cfa7ecceb7a3ce277f8c2e5e682ccdf5f02e5e +Subproject commit 196459bdee76b91a4c020785e7280a38582c3395 diff --git a/components/freertos/test_apps/freertos/kernel/event_groups/test_freertos_eventgroups.c b/components/freertos/test_apps/freertos/kernel/event_groups/test_freertos_eventgroups.c index 00ff6980c9ea..f1101360b28a 100644 --- a/components/freertos/test_apps/freertos/kernel/event_groups/test_freertos_eventgroups.c +++ b/components/freertos/test_apps/freertos/kernel/event_groups/test_freertos_eventgroups.c @@ -185,6 +185,7 @@ TEST_CASE("FreeRTOS Event Groups do not cause priority inversion when higher pri /*-----------------Test case for event group trace facilities-----------------*/ #ifdef CONFIG_FREERTOS_USE_TRACE_FACILITY +#if SOC_GPTIMER_SUPPORTED /* * Test event group Trace Facility functions such as * xEventGroupClearBitsFromISR(), xEventGroupSetBitsFromISR() @@ -261,4 +262,5 @@ TEST_CASE("FreeRTOS Event Group ISR", "[freertos]") vSemaphoreDelete(done_sem); vTaskDelay(10); //Give time for idle task to clear up deleted tasks } +#endif //SOC_GPTIMER_SUPPORTED #endif //CONFIG_FREERTOS_USE_TRACE_FACILITY diff --git a/components/freertos/test_apps/freertos/kernel/tasks/test_freertos_task_notify.c b/components/freertos/test_apps/freertos/kernel/tasks/test_freertos_task_notify.c index 68f71497c19f..ade25fa33636 100644 --- a/components/freertos/test_apps/freertos/kernel/tasks/test_freertos_task_notify.c +++ b/components/freertos/test_apps/freertos/kernel/tasks/test_freertos_task_notify.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 */ @@ -21,6 +21,8 @@ #include "unity.h" #include "test_utils.h" +#if SOC_GPTIMER_SUPPORTED + #define NO_OF_NOTIFS 4 #define NO_OF_TASKS 2 //Sender and receiver #define MESSAGE 0xFF @@ -196,9 +198,10 @@ TEST_CASE("Test Task_Notify", "[freertos]") TEST_ESP_OK(gptimer_del_timer(gptimers[i])); } } +#endif //SOC_GPTIMER_SUPPORTED /* Test causes asserts, so it cannot be run as a normal unity test case. - Test case is ran as a seperate test case in test_task_notify_too_high_index_fails + Test case is ran as a separate test case in test_task_notify_too_high_index_fails */ TEST_CASE("Notify too high index fails", "[ignore]") { @@ -207,7 +210,7 @@ TEST_CASE("Notify too high index fails", "[ignore]") } /* Test causes asserts, so it cannot be run as a normal unity test case. - Test case is ran as a seperate test case in test_task_notify_wait_too_high_index_fails + Test case is ran as a separate test case in test_task_notify_wait_too_high_index_fails */ TEST_CASE("Notify Wait too high index fails", "[ignore]") { diff --git a/components/freertos/test_apps/freertos/kernel/tasks/test_task_delay.c b/components/freertos/test_apps/freertos/kernel/tasks/test_task_delay.c index 8451d3fbf6c2..e5128d94de8a 100644 --- a/components/freertos/test_apps/freertos/kernel/tasks/test_task_delay.c +++ b/components/freertos/test_apps/freertos/kernel/tasks/test_task_delay.c @@ -13,6 +13,7 @@ #include "portTestMacro.h" /* ------------------------------------------------------------------------------------------------------------------ */ +#if SOC_GPTIMER_SUPPORTED /* Test vTaskDelay @@ -178,3 +179,4 @@ TEST_CASE("Tasks: Test vTaskDelayUntil", "[freertos]") } #endif /* ( INCLUDE_xTaskDelayUntil == 1 ) */ +#endif //SOC_GPTIMER_SUPPORTED diff --git a/components/freertos/test_apps/freertos/kernel/tasks/test_task_suspend_resume.c b/components/freertos/test_apps/freertos/kernel/tasks/test_task_suspend_resume.c index 0df02840a8d2..b7c8ffa883d3 100644 --- a/components/freertos/test_apps/freertos/kernel/tasks/test_task_suspend_resume.c +++ b/components/freertos/test_apps/freertos/kernel/tasks/test_task_suspend_resume.c @@ -118,6 +118,8 @@ TEST_CASE("Suspend the current running task", "[freertos]") TEST_ASSERT_TRUE(resumed); } +#if SOC_GPTIMER_SUPPORTED + static volatile bool timer_isr_fired; static gptimer_handle_t gptimer = NULL; @@ -203,3 +205,5 @@ TEST_CASE("Resume task from ISR (other core)", "[freertos]") test_resume_task_from_isr(!UNITY_FREERTOS_CPU); } #endif // CONFIG_FREERTOS_UNICORE + +#endif //SOC_GPTIMER_SUPPORTED 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 97acb852571a..e6dd88c7aa6a 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 @@ -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 */ @@ -24,6 +24,8 @@ GP timer is used to trigger an interrupt. Test cases will register an interrupt interrupt callback. The functions below simply the interrupt registration/trigger/deregistration process. */ +#if SOC_GPTIMER_SUPPORTED + static gptimer_handle_t gptimer = NULL; static bool (*registered_intr_callback)(void *) = NULL; @@ -84,6 +86,8 @@ static void deregister_intr_cb(void) TEST_ESP_OK(gptimer_del_timer(gptimer_temp)); } +#endif //SOC_GPTIMER_SUPPORTED + /* --------------------------------------------------------------------------------------------------------------------- Test vTaskSuspendAll() and xTaskResumeAll() basic @@ -265,6 +269,9 @@ Only runs on !CONFIG_FREERTOS_UNICORE --------------------------------------------------------------------------------------------------------------------- */ #if !CONFIG_FREERTOS_UNICORE + +#if SOC_GPTIMER_SUPPORTED + static volatile int test_unblk_sync; static SemaphoreHandle_t test_unblk_done_sem; @@ -394,6 +401,8 @@ TEST_CASE("Test vTaskSuspendAll allows scheduling on other cores", "[freertos]") vTaskDelay(10); } +#endif //SOC_GPTIMER_SUPPORTED + /* --------------------------------------------------------------------------------------------------------------------- Test vTaskSuspendAll doesn't block unpinned tasks from being scheduled on other cores @@ -539,6 +548,8 @@ Test xTaskResumeAll() resumes pended tasks on the current core #define TEST_PENDED_NUM_BLOCKED_TASKS 4 +#if SOC_GPTIMER_SUPPORTED + static bool test_pended_isr(void *arg) { TaskHandle_t *blkd_tsks = (TaskHandle_t *)arg; @@ -639,6 +650,8 @@ TEST_CASE("Test xTaskResumeAll resumes pended tasks", "[freertos]") vTaskDelay(10); } +#endif //SOC_GPTIMER_SUPPORTED + /* --------------------------------------------------------------------------------------------------------------------- Test xTaskSuspendAll on both cores pends all tasks and xTaskResumeAll on both cores resumes all tasks diff --git a/components/freertos/test_apps/freertos/pytest_freertos.py b/components/freertos/test_apps/freertos/pytest_freertos.py index e2cdb05bd2c8..15d798b9313e 100644 --- a/components/freertos/test_apps/freertos/pytest_freertos.py +++ b/components/freertos/test_apps/freertos/pytest_freertos.py @@ -13,7 +13,7 @@ # TODO: [ESP32C61] IDF-11146 pytest.param('smp', marks=[ pytest.mark.supported_targets, - pytest.mark.temp_skip_ci(targets=['esp32p4', 'esp32c5', 'esp32c61'], + pytest.mark.temp_skip_ci(targets=['esp32p4', 'esp32c5', 'esp32c61', 'esp32h21'], reason='test failed/TBD IDF-8113') ]), ] diff --git a/components/hal/CMakeLists.txt b/components/hal/CMakeLists.txt index 47c1d8a404d3..4fd7ac1757c5 100644 --- a/components/hal/CMakeLists.txt +++ b/components/hal/CMakeLists.txt @@ -217,6 +217,10 @@ if(NOT BOOTLOADER_BUILD AND NOT esp_tee_build) list(APPEND srcs "brownout_hal.c") endif() + if(CONFIG_SOC_VBAT_SUPPORTED) + list(APPEND srcs "vbat_hal.c") + endif() + if(CONFIG_SOC_JPEG_CODEC_SUPPORTED) list(APPEND srcs "jpeg_hal.c") endif() diff --git a/components/hal/Kconfig b/components/hal/Kconfig index 264fbb6a9651..2c8e44d657b1 100644 --- a/components/hal/Kconfig +++ b/components/hal/Kconfig @@ -105,11 +105,13 @@ menu "Hardware Abstraction Layer (HAL) and Low Level (LL)" config HAL_ECDSA_GEN_SIG_CM bool "Enable countermeasure for ECDSA signature generation" + depends on IDF_TARGET_ESP32H2 default n - # ToDo - IDF-11051 help Enable this option to apply the countermeasure for ECDSA signature operation This countermeasure masks the real ECDSA sign operation under dummy sign operations to add randomness in the generated power signature. + This countermeasure is only necessary for ESP32-H2 < v1.2. + endmenu diff --git a/components/hal/aes_hal.c b/components/hal/aes_hal.c index 92760958e02b..f70ed1b9875f 100644 --- a/components/hal/aes_hal.c +++ b/components/hal/aes_hal.c @@ -43,7 +43,9 @@ void aes_hal_transform_block(const void *input_block, void *output_block) #ifdef SOC_AES_SUPPORT_PSEUDO_ROUND_FUNCTION void aes_hal_enable_pseudo_rounds(bool enable, uint8_t base, uint8_t increment, uint8_t key_rng_cnt) { - aes_ll_enable_pseudo_rounds(enable, base, increment, key_rng_cnt); + if (aes_ll_is_pseudo_rounds_function_supported()) { + aes_ll_enable_pseudo_rounds(enable, base, increment, key_rng_cnt); + } } #endif // SOC_AES_SUPPORT_PSEUDO_ROUND_FUNCTION diff --git a/components/hal/ecc_hal.c b/components/hal/ecc_hal.c index 3de372cdf501..79c28ce50195 100644 --- a/components/hal/ecc_hal.c +++ b/components/hal/ecc_hal.c @@ -178,9 +178,7 @@ int ecc_hal_read_mod_op_result(uint8_t *r, uint16_t len) #endif /* SOC_ECC_EXTENDED_MODES_SUPPORTED */ -#ifdef SOC_ECC_CONSTANT_TIME_POINT_MUL void ecc_hal_enable_constant_time_point_mul(bool enable) { ecc_ll_enable_constant_time_point_mul(enable); } -#endif /* SOC_ECC_CONSTANT_TIME_POINT_MUL */ diff --git a/components/hal/ecdsa_hal.c b/components/hal/ecdsa_hal.c index bec830e3914b..5c10802e2c94 100644 --- a/components/hal/ecdsa_hal.c +++ b/components/hal/ecdsa_hal.c @@ -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 */ @@ -12,6 +12,7 @@ #if CONFIG_HAL_ECDSA_GEN_SIG_CM #include "esp_fault.h" #include "esp_random.h" +#include "soc/chip_revision.h" #endif #ifdef SOC_KEY_MANAGER_ECDSA_KEY_DEPLOY @@ -136,7 +137,15 @@ void ecdsa_hal_gen_signature(ecdsa_hal_config_t *conf, const uint8_t *hash, configure_ecdsa_periph(conf); #if CONFIG_HAL_ECDSA_GEN_SIG_CM +#if CONFIG_IDF_TARGET_ESP32H2 + if (!ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 102)) { + ecdsa_hal_gen_signature_with_countermeasure(hash, r_out, s_out, len); + } else { + ecdsa_hal_gen_signature_inner(hash, r_out, s_out, len); + } +#else ecdsa_hal_gen_signature_with_countermeasure(hash, r_out, s_out, len); +#endif #else /* CONFIG_HAL_ECDSA_GEN_SIG_CM */ ecdsa_hal_gen_signature_inner(hash, r_out, s_out, len); #endif /* !CONFIG_HAL_ECDSA_GEN_SIG_CM */ diff --git a/components/hal/esp32/include/hal/rmt_ll.h b/components/hal/esp32/include/hal/rmt_ll.h index 147c6c089dbe..2f86a0c21d48 100644 --- a/components/hal/esp32/include/hal/rmt_ll.h +++ b/components/hal/esp32/include/hal/rmt_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ diff --git a/components/hal/esp32/include/hal/spi_flash_encrypted_ll.h b/components/hal/esp32/include/hal/spi_flash_encrypted_ll.h index 682be3081597..7827c5cab9fb 100644 --- a/components/hal/esp32/include/hal/spi_flash_encrypted_ll.h +++ b/components/hal/esp32/include/hal/spi_flash_encrypted_ll.h @@ -11,6 +11,7 @@ ******************************************************************************/ // The Lowlevel layer for SPI Flash Encryption. +#pragma once #include "soc/dport_reg.h" #include "soc/flash_encryption_reg.h" diff --git a/components/hal/esp32/include/hal/touch_sensor_ll.h b/components/hal/esp32/include/hal/touch_sensor_ll.h index 268a35e1bea2..53929a20bf8b 100644 --- a/components/hal/esp32/include/hal/touch_sensor_ll.h +++ b/components/hal/esp32/include/hal/touch_sensor_ll.h @@ -270,7 +270,7 @@ static inline void touch_ll_set_measure_interval_ticks(uint16_t interval_ticks) */ static inline void touch_ll_set_charge_speed(uint32_t touch_num, touch_charge_speed_t charge_speed) { - RTCIO.touch_pad[touch_num].dac = charge_speed; + RTCIO.touch_pad[touch_num].slope = charge_speed; } /** @@ -586,7 +586,7 @@ static inline void touch_ll_get_voltage_attenuation(touch_volt_atten_t *atten) */ static inline void touch_ll_set_slope(touch_pad_t touch_num, touch_cnt_slope_t slope) { - RTCIO.touch_pad[touch_num].dac = slope; + RTCIO.touch_pad[touch_num].slope = slope; } /** @@ -601,7 +601,7 @@ static inline void touch_ll_set_slope(touch_pad_t touch_num, touch_cnt_slope_t s */ static inline void touch_ll_get_slope(touch_pad_t touch_num, touch_cnt_slope_t *slope) { - *slope = (touch_cnt_slope_t)RTCIO.touch_pad[touch_num].dac; + *slope = (touch_cnt_slope_t)RTCIO.touch_pad[touch_num].slope; } /** @@ -681,8 +681,8 @@ static inline void touch_ll_stop_fsm(void) */ static inline void touch_ll_start_sw_meas(void) { - SENS.sar_touch_ctrl2.touch_start_en = 0; SENS.sar_touch_ctrl2.touch_start_en = 1; + SENS.sar_touch_ctrl2.touch_start_en = 0; } /** diff --git a/components/hal/esp32c2/include/hal/ecc_ll.h b/components/hal/esp32c2/include/hal/ecc_ll.h index 58ddd82dd002..ca84307425f9 100644 --- a/components/hal/esp32c2/include/hal/ecc_ll.h +++ b/components/hal/esp32c2/include/hal/ecc_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -171,6 +171,12 @@ static inline void ecc_ll_read_param(ecc_ll_param_t param, uint8_t *buf, uint16_ memcpy(buf, (void *)reg, len); } +static inline void ecc_ll_enable_constant_time_point_mul(bool enable) +{ + // Not supported for ESP32-C2 + (void) enable; //unused +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32c2/include/hal/spi_flash_encrypted_ll.h b/components/hal/esp32c2/include/hal/spi_flash_encrypted_ll.h index 8d59c99148ae..7c8b10376ee6 100644 --- a/components/hal/esp32c2/include/hal/spi_flash_encrypted_ll.h +++ b/components/hal/esp32c2/include/hal/spi_flash_encrypted_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,6 +11,7 @@ ******************************************************************************/ // The Lowlevel layer for SPI Flash Encryption. +#pragma once #include #include @@ -24,7 +25,7 @@ extern "C" { #endif -/// Choose type of chip you want to encrypt manully +/// Choose type of chip you want to encrypt manually typedef enum { FLASH_ENCRYPTION_MANU = 0, ///!< Manually encrypt the flash chip. @@ -51,7 +52,7 @@ static inline void spi_flash_encrypt_ll_disable(void) } /** - * Choose type of chip you want to encrypt manully + * Choose type of chip you want to encrypt manually * * @param type The type of chip to be encrypted * diff --git a/components/hal/esp32c3/include/hal/rmt_ll.h b/components/hal/esp32c3/include/hal/rmt_ll.h index c76924fedf28..0d829b356937 100644 --- a/components/hal/esp32c3/include/hal/rmt_ll.h +++ b/components/hal/esp32c3/include/hal/rmt_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -37,6 +37,11 @@ extern "C" { #define RMT_LL_MAX_FILTER_VALUE 255 #define RMT_LL_MAX_IDLE_VALUE 32767 +// Maximum values due to limited register bit width +#define RMT_LL_CHANNEL_CLOCK_MAX_PRESCALE 256 +#define RMT_LL_GROUP_CLOCK_MAX_INTEGER_PRESCALE 256 +#define RMT_LL_GROUP_CLOCK_MAX_FRACTAL_PRESCALE 64 + typedef enum { RMT_LL_MEM_OWNER_SW = 0, RMT_LL_MEM_OWNER_HW = 1, diff --git a/components/hal/esp32c3/include/hal/spi_flash_encrypted_ll.h b/components/hal/esp32c3/include/hal/spi_flash_encrypted_ll.h index 8857e1f915ab..7c8b10376ee6 100644 --- a/components/hal/esp32c3/include/hal/spi_flash_encrypted_ll.h +++ b/components/hal/esp32c3/include/hal/spi_flash_encrypted_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,6 +11,7 @@ ******************************************************************************/ // The Lowlevel layer for SPI Flash Encryption. +#pragma once #include #include @@ -24,7 +25,7 @@ extern "C" { #endif -/// Choose type of chip you want to encrypt manully +/// Choose type of chip you want to encrypt manually typedef enum { FLASH_ENCRYPTION_MANU = 0, ///!< Manually encrypt the flash chip. @@ -51,7 +52,7 @@ static inline void spi_flash_encrypt_ll_disable(void) } /** - * Choose type of chip you want to encrypt manully + * Choose type of chip you want to encrypt manually * * @param type The type of chip to be encrypted * diff --git a/components/hal/esp32c5/include/hal/aes_ll.h b/components/hal/esp32c5/include/hal/aes_ll.h index 7051bc3189b5..0b6b1698034f 100644 --- a/components/hal/esp32c5/include/hal/aes_ll.h +++ b/components/hal/esp32c5/include/hal/aes_ll.h @@ -264,6 +264,14 @@ static inline void aes_ll_enable_pseudo_rounds(bool enable, uint8_t base, uint8_ } } +/** + * @brief Check if the pseudo round function is supported + */ +static inline bool aes_ll_is_pseudo_rounds_function_supported(void) +{ + return true; +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32c5/include/hal/bitscrambler_ll.h b/components/hal/esp32c5/include/hal/bitscrambler_ll.h new file mode 100644 index 000000000000..e0bb8b6cde0a --- /dev/null +++ b/components/hal/esp32c5/include/hal/bitscrambler_ll.h @@ -0,0 +1,373 @@ +/* + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +#pragma once + +#include +#include +#include +#include "soc/bitscrambler_struct.h" +#include "hal/bitscrambler_types.h" +#include "soc/pcr_struct.h" +#include "soc/hp_system_struct.h" +#include "hal/misc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define BITSCRAMBLER_LL_GET_HW(num) (((num) == 0) ? (&BITSCRAMBLER) : NULL) + +#define BITSCRAMBLER_LL_INST_LEN_WORDS 9 //length of one instruction in 32-bit words as defined by HW + +/** + * @brief Select peripheral BitScrambler is attached to + * + * @param hw BitScrambler hardware instance address. + * @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX + * @param peri Peripheral to select, should pick the value from soc/bitscrambler_peri_select.h + */ +static inline void bitscrambler_ll_select_peripheral(bitscrambler_dev_t *hw, bitscrambler_direction_t dir, int peri) +{ + if (dir == BITSCRAMBLER_DIR_TX) { + HP_SYSTEM.bitscrambler_peri_sel.bitscrambler_tx_sel = peri; + } else { // RX + HP_SYSTEM.bitscrambler_peri_sel.bitscrambler_rx_sel = peri; + } +} + +/** + * @brief Enable the BitScrambler + * + * @param hw BitScrambler hardware instance address. + * @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX + */ +static inline void bitscrambler_ll_enable(bitscrambler_dev_t *hw, bitscrambler_direction_t dir) +{ + hw->ctrl[dir].ena = 1; +} + +/** + * @brief Disable the BitScrambler + * + * @param hw BitScrambler hardware instance address. + * @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX + */ +static inline void bitscrambler_ll_disable(bitscrambler_dev_t *hw, bitscrambler_direction_t dir) +{ + hw->ctrl[dir].ena = 0; +} + + +/** + * @brief Write a word to the instruction memory + * + * @param hw BitScrambler hardware instance address. + * @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX + * @param inst_idx Instruction to write to + * @param word_idx Word within the instruction to write to + * @param data Data to write + */ +static inline void bitscrambler_ll_instmem_write(bitscrambler_dev_t *hw, bitscrambler_direction_t dir, int inst_idx, int word_idx, uint32_t data) +{ + hw->inst_cfg[dir].cfg0.inst_idx = inst_idx; + hw->inst_cfg[dir].cfg0.inst_pos = word_idx; + hw->inst_cfg[dir].cfg1.inst = data; +} + +/** + * @brief Read a word from the instruction memory + * + * @param hw BitScrambler hardware instance address. + * @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX + * @param inst_idx Instruction to write to + * @param word_idx Word within the instruction to write to + * + * @returns Word read from instruction memory + */ +static inline uint32_t bitscrambler_ll_instmem_read(bitscrambler_dev_t *hw, bitscrambler_direction_t dir, int inst_idx, int word_idx) +{ + hw->inst_cfg[dir].cfg0.inst_idx = inst_idx; + hw->inst_cfg[dir].cfg0.inst_pos = word_idx; + return hw->inst_cfg[dir].cfg1.inst; +} + +/** + * @brief Write a word to LUT memory + * + * @param hw BitScrambler hardware instance address. + * @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX + * @param word_idx Word within the LUT to write to + * @param data Data to write + */ +static inline void bitscrambler_ll_lutmem_write(bitscrambler_dev_t *hw, bitscrambler_direction_t dir, int word_idx, uint32_t data) +{ + hw->lut_cfg[dir].cfg0.lut_idx = word_idx; + hw->lut_cfg[dir].cfg1.lut = data; +} + +/** + * @brief Set width of LUT memory (as seen by Bitscrambler, not by host) + * + * @param hw BitScrambler hardware instance address. + * @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX + * @param width Width selection + */ +static inline void bitscrambler_ll_set_lut_width(bitscrambler_dev_t *hw, bitscrambler_direction_t dir, bitscrambler_lut_width_t width) +{ + hw->lut_cfg[dir].cfg0.lut_mode = width; +} + +/** + * @brief Get width of LUT memory + * + * @param hw BitScrambler hardware instance address. + * @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX + */ +static inline int bitscrambler_ll_get_lut_width(bitscrambler_dev_t *hw, bitscrambler_direction_t dir) +{ + return hw->lut_cfg[dir].cfg0.lut_mode; +} + +/** + * @brief Enable loopback mode, where the RX BitScrambler is disabled and the TX BitScrambler loops + * back to the receive DMA path to memory. + * + * @param hw BitScrambler hardware instance address. + * @param en True if loopback mode is enabled; false otherwise + */ +static inline void bitscrambler_ll_enable_loopback(bitscrambler_dev_t *hw, bool en) +{ + hw->sys.loop_mode = en ? 1 : 0; +} + +/** + * @brief Set condition-checking mode + * + * @param hw BitScrambler hardware instance address. + * @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX + * @param mode Mode to set + */ +static inline void bitscrambler_ll_set_cond_mode(bitscrambler_dev_t *hw, bitscrambler_direction_t dir, bitscrambler_cond_mode_t mode) +{ + hw->ctrl[dir].cond_mode = mode; +} + +/** + * @brief Enable prefetch mode + * + * @param hw BitScrambler hardware instance address. + * @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX + * @param en True to enable prefetch mode; false to disable + */ +static inline void bitscrambler_ll_enable_prefetch_on_reset(bitscrambler_dev_t *hw, bitscrambler_direction_t dir, bool en) +{ + // 0: means do prefetch on reset, 1: means no reset prefetch, user has to load the instruction manually in the assembly code + hw->ctrl[dir].fetch_mode = en ? 0 : 1; +} + +/** + * @brief Set EOF mode + * + * @param hw BitScrambler hardware instance address. + * @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX + * @param mode Mode to set + */ +static inline void bitscrambler_ll_set_eof_mode(bitscrambler_dev_t *hw, bitscrambler_direction_t dir, bitscrambler_eof_mode_t mode) +{ + hw->ctrl[dir].eof_mode = mode; +} + +/** + * @brief Set mode of dummy-reading after EOF + * + * @param hw BitScrambler hardware instance address. + * @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX + * @param mode Mode to set + */ +static inline void bitscrambler_ll_set_dummy_mode(bitscrambler_dev_t *hw, bitscrambler_direction_t dir, bitscrambler_dummy_mode_t mode) +{ + hw->ctrl[dir].rd_dummy = mode; +} + +/** + * @brief Set halting mode + * + * @param hw BitScrambler hardware instance address. + * @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX + * @param mode Mode to set + */ +static inline void bitscrambler_ll_set_halt_mode(bitscrambler_dev_t *hw, bitscrambler_direction_t dir, bitscrambler_halt_mode_t mode) +{ + hw->ctrl[dir].halt_mode = mode; +} + +/** + * @brief Set amount of bits to ignore after EOF + * + * @param hw BitScrambler hardware instance address. + * @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX + * @param bitcount Number of bits to ignore + */ +static inline void bitscrambler_ll_set_tailing_bits(bitscrambler_dev_t *hw, bitscrambler_direction_t dir, int bitcount) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tail_bits[dir], tailing_bits, bitcount); +} + +/** + * @brief Reset BitScrambler FIFO + * + * @param hw BitScrambler hardware instance address. + * @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX + */ +static inline void bitscrambler_ll_reset_fifo(bitscrambler_dev_t *hw, bitscrambler_direction_t dir) +{ + hw->ctrl[dir].fifo_rst = 1; + hw->ctrl[dir].fifo_rst = 0; +} + +/** + * @brief Clear trace of EOF counts + * + * @param hw BitScrambler hardware instance address. + * @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX + */ +static inline void bitscrambler_ll_clear_eof_trace(bitscrambler_dev_t *hw, bitscrambler_direction_t dir) +{ + hw->state[dir].eof_trace_clr = 1; + hw->state[dir].eof_trace_clr = 0; +} + +/** + * @brief Set state of BitScrambler + * + * @param hw BitScrambler hardware instance address. + * @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX + * @param state One of BITSCRAMBLER_SET_STATE_[RUN|HALT|PAUSE]. Note the WAIT state cannot be set externally. + */ +static inline void bitscrambler_ll_set_state(bitscrambler_dev_t *hw, bitscrambler_direction_t dir, bitscrambler_set_state_t state) +{ + hw->ctrl[dir].pause = (state == BITSCRAMBLER_SET_STATE_PAUSE) ? 1 : 0; + hw->ctrl[dir].halt = (state == BITSCRAMBLER_SET_STATE_HALT) ? 1 : 0; +} + +/** + * @brief Return current BitScrambler state + * + * @param hw BitScrambler hardware instance address. + * @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX + * + * @returns one of BITSCRAMBLER_STATE_* values + */ +static inline bitscrambler_state_t bitscrambler_ll_get_current_state(bitscrambler_dev_t *hw, bitscrambler_direction_t dir) +{ + if (hw->state[dir].in_idle) { + return BITSCRAMBLER_STATE_IDLE; + } + if (hw->state[dir].in_run) { + return BITSCRAMBLER_STATE_RUN; + } + if (hw->state[dir].in_wait) { + return BITSCRAMBLER_STATE_WAIT; + } + if (hw->state[dir].in_pause) { + return BITSCRAMBLER_STATE_PAUSED; + } + return BITSCRAMBLER_STATE_UNKNOWN; +} + +/** + * @brief Enable the bus clock for BitScrambler module + */ +static inline void _bitscrambler_ll_set_bus_clock_sys_enable(bool enable) +{ + PCR.bs_conf.bs_clk_en = enable; +} + +/** + * @brief Enable the bus clock for RX BitScrambler module + */ +static inline void _bitscrambler_ll_set_bus_clock_rx_enable(bool enable) +{ + // empty +} + +/** + * @brief Enable the bus clock for TX BitScrambler module + */ +static inline void _bitscrambler_ll_set_bus_clock_tx_enable(bool enable) +{ + // empty +} + +/** + * @brief Force power on the bitscrambler memory block, regardless of the outside PMU logic + */ +static inline void bitscrambler_ll_mem_force_power_on(void) +{ + PCR.bs_pd_ctrl.bs_mem_force_pu = 1; + PCR.bs_pd_ctrl.bs_mem_force_pd = 0; +} + +/** + * @brief Force power off the bitscrambler memory block, regardless of the outside PMU logic + */ +static inline void bitscrambler_ll_mem_force_power_off(void) +{ + PCR.bs_pd_ctrl.bs_mem_force_pd = 1; + PCR.bs_pd_ctrl.bs_mem_force_pu = 0; +} + +/** + * @brief Power control the bitscrambler memory block by the outside PMU logic + */ +static inline void bitscrambler_ll_mem_power_by_pmu(void) +{ + PCR.bs_pd_ctrl.bs_mem_force_pd = 0; + PCR.bs_pd_ctrl.bs_mem_force_pu = 0; +} + +/** + * @brief Reset the BitScrambler module + */ +static inline void _bitscrambler_ll_reset_sys(void) +{ + PCR.bs_conf.bs_rst_en = 1; + PCR.bs_conf.bs_rst_en = 0; +} + +/** + * @brief Reset the BitScrambler RX module + */ +static inline void _bitscrambler_ll_reset_rx(void) +{ + PCR.bs_func_conf.bs_rx_rst_en = 1; + PCR.bs_func_conf.bs_rx_rst_en = 0; +} + +/** + * @brief Reset the BitScrambler TX module + */ +static inline void _bitscrambler_ll_reset_tx(void) +{ + PCR.bs_func_conf.bs_tx_rst_en = 1; + PCR.bs_func_conf.bs_tx_rst_en = 0; +} + +/// 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 bitscrambler_ll_set_bus_clock_sys_enable(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; _bitscrambler_ll_set_bus_clock_sys_enable(__VA_ARGS__) +#define bitscrambler_ll_set_bus_clock_rx_enable(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; _bitscrambler_ll_set_bus_clock_rx_enable(__VA_ARGS__) +#define bitscrambler_ll_set_bus_clock_tx_enable(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; _bitscrambler_ll_set_bus_clock_tx_enable(__VA_ARGS__) + +#define bitscrambler_ll_reset_sys(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; _bitscrambler_ll_reset_sys(__VA_ARGS__) +#define bitscrambler_ll_reset_rx(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; _bitscrambler_ll_reset_rx(__VA_ARGS__) +#define bitscrambler_ll_reset_tx(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; _bitscrambler_ll_reset_tx(__VA_ARGS__) + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32c5/include/hal/brownout_ll.h b/components/hal/esp32c5/include/hal/brownout_ll.h index e103d2639c9e..af0f6c812254 100644 --- a/components/hal/esp32c5/include/hal/brownout_ll.h +++ b/components/hal/esp32c5/include/hal/brownout_ll.h @@ -121,7 +121,7 @@ static inline void brownout_ll_ana_reset_enable(bool enable) __attribute__((always_inline)) static inline void brownout_ll_intr_clear(void) { - LP_ANA_PERI.int_clr.bod_mode0_int_clr = 1; + LP_ANA_PERI.int_clr.val = BROWNOUT_DETECTOR_LL_INTERRUPT_MASK; } /** diff --git a/components/hal/esp32c5/include/hal/clk_tree_ll.h b/components/hal/esp32c5/include/hal/clk_tree_ll.h index ca391faddd89..f723a6e238c3 100644 --- a/components/hal/esp32c5/include/hal/clk_tree_ll.h +++ b/components/hal/esp32c5/include/hal/clk_tree_ll.h @@ -9,16 +9,19 @@ #include #include "soc/soc.h" #include "soc/clk_tree_defs.h" +#include "soc/pcr_reg.h" #include "soc/pcr_struct.h" #include "soc/lp_clkrst_struct.h" #include "soc/pmu_reg.h" #include "soc/pmu_struct.h" +#include "soc/chip_revision.h" #include "hal/regi2c_ctrl.h" #include "soc/regi2c_bbpll.h" #include "hal/assert.h" #include "hal/log.h" #include "esp32c5/rom/rtc.h" #include "hal/misc.h" +#include "hal/efuse_hal.h" #ifdef __cplusplus extern "C" { @@ -420,6 +423,22 @@ static inline __attribute__((always_inline)) uint32_t clk_ll_apb_get_divider(voi return HAL_FORCE_READ_U32_REG_FIELD(PCR.apb_freq_conf, apb_div_num) + 1; } +/** + * @brief Enable or disable the soc root clock auto gating logic + * + * @param ena true to enable, false to disable + */ +static inline __attribute__((always_inline)) void clk_ll_soc_root_clk_auto_gating_bypass(bool ena) +{ + if (ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 1)) { + if (ena) { + REG_CLR_BIT(PCR_FPGA_DEBUG_REG, BIT(31)); + } else { + REG_SET_BIT(PCR_FPGA_DEBUG_REG, BIT(31)); + } + } +} + /** * @brief Select the clock source for RTC_SLOW_CLK * diff --git a/components/hal/esp32c5/include/hal/i2s_ll.h b/components/hal/esp32c5/include/hal/i2s_ll.h index 0a33745fd787..45cc720a762b 100644 --- a/components/hal/esp32c5/include/hal/i2s_ll.h +++ b/components/hal/esp32c5/include/hal/i2s_ll.h @@ -496,7 +496,7 @@ static inline void i2s_ll_rx_set_ws_width(i2s_dev_t *hw, int width) */ static inline void i2s_ll_rx_set_eof_num(i2s_dev_t *hw, int eof_num) { - hw->rx_eof_num.rx_eof_num = eof_num; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->rx_eof_num, rx_eof_num, eof_num); } /** diff --git a/components/hal/esp32c5/include/hal/parlio_ll.h b/components/hal/esp32c5/include/hal/parlio_ll.h index 735de524d1af..5d4032ad280f 100644 --- a/components/hal/esp32c5/include/hal/parlio_ll.h +++ b/components/hal/esp32c5/include/hal/parlio_ll.h @@ -397,6 +397,7 @@ static inline uint32_t parlio_ll_rx_get_fifo_cycle_cnt(parl_io_dev_t *dev) * @param dev Parallel IO register base address * @param src Clock source */ +__attribute__((always_inline)) static inline void parlio_ll_tx_set_clock_source(parl_io_dev_t *dev, parlio_clock_source_t src) { (void)dev; diff --git a/components/hal/esp32c5/include/hal/psram_ctrlr_ll.h b/components/hal/esp32c5/include/hal/psram_ctrlr_ll.h index 0a9946ff5766..868dcee35c5d 100644 --- a/components/hal/esp32c5/include/hal/psram_ctrlr_ll.h +++ b/components/hal/esp32c5/include/hal/psram_ctrlr_ll.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 */ @@ -30,7 +30,10 @@ extern "C" { #define PSRAM_CTRLR_LL_MSPI_ID_0 0 #define PSRAM_CTRLR_LL_MSPI_ID_1 1 -#define PSRAM_LL_CS_SEL SPI_MEM_CS1_DIS_M +#define PSRAM_LL_CS_SEL SPI_MEM_CS1_DIS_M +#define PSRAM_CTRLR_LL_PMS_REGION_NUMS 4 +#define PSRAM_CTRLR_LL_PMS_ATTR_WRITABLE (1<<0) +#define PSRAM_CTRLR_LL_PMS_ATTR_READABLE (1<<1) /** * @brief PSRAM enum for cs id. @@ -40,6 +43,14 @@ typedef enum { PSRAM_LL_CS_ID_1 = 1, } psram_ll_cs_id_t; +/** + * @brief PSRAM ECC mode + */ +typedef enum { + PSRAM_LL_ECC_MODE_16TO17 = 0, + PSRAM_LL_ECC_MODE_16TO18 = 1, +} psram_ll_ecc_mode_t; + /** * @brief Set PSRAM write cmd * @@ -140,7 +151,7 @@ static inline uint32_t psram_ctrlr_ll_calculate_clock_reg(uint8_t clkdiv) * @param mspi_id mspi_id * @param read_mode read mode */ -static inline void psram_ctrlr_ll_set_read_mode(uint32_t mspi_id, psram_hal_cmd_mode_t read_mode) +static inline void psram_ctrlr_ll_set_read_mode(uint32_t mspi_id, psram_cmd_mode_t read_mode) { typeof (SPIMEM0.mem_cache_sctrl) mem_cache_sctrl; mem_cache_sctrl.val = SPIMEM0.mem_cache_sctrl.val; @@ -258,6 +269,235 @@ static inline void psram_ctrlr_ll_enable_quad_command(uint32_t mspi_id, bool ena SPIMEM1.ctrl.fcmd_quad = ena; } +/*--------------------------------------------------------------- + ECC +---------------------------------------------------------------*/ +/** + * @brief Set ECC CS hold + * + * @param mspi_id mspi_id + * @param hold_n cs hold time + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_set_ecc_cs_hold(uint32_t mspi_id, uint32_t hold_n) +{ + HAL_ASSERT(hold_n > 0); + SPIMEM0.smem_ac.smem_ecc_cs_hold_time = hold_n - 1; +} + +/** + * @brief Set ECC mode + * + * @param mspi_id mspi_id + * @param mode ecc mode + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_set_ecc_mode(uint32_t mspi_id, psram_ll_ecc_mode_t mode) +{ + SPIMEM0.smem_ac.smem_ecc_16to18_byte_en = mode; +} + +/** + * @brief Set page size + * + * @param mspi_id mspi_id + * @param size page size + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_set_page_size(uint32_t mspi_id, uint32_t size) +{ + uint32_t size_val = 0; + switch (size) { + case 256: + size_val = 0; + break; + case 512: + size_val = 1; + break; + case 1024: + size_val = 2; + break; + case 2048: + size_val = 3; + break; + default: + HAL_ASSERT(false); + break; + } + + SPIMEM0.smem_ecc_ctrl.smem_page_size = size_val; +} + +/** + * @brief Get page size + * + * @param mspi_id mspi_id + * + * @return page size + */ +__attribute__((always_inline)) +static inline uint32_t psram_ctrlr_ll_get_page_size(uint32_t mspi_id) +{ + (void)mspi_id; + uint32_t page_size = 0; + + uint32_t reg_val = SPIMEM0.smem_ecc_ctrl.smem_page_size; + switch(reg_val) { + case 0: + page_size = 256; + break; + case 1: + page_size = 512; + break; + case 2: + page_size = 1024; + break; + case 3: + page_size = 2048; + break; + default: + HAL_ASSERT(false); + } + + return page_size; +} + +/** + * @brief Skip page corner + * + * @param mspi_id mspi_id + * @param en enable / disable + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_enable_skip_page_corner(uint32_t mspi_id, bool en) +{ + SPIMEM0.smem_ac.smem_ecc_skip_page_corner = en; +} + +/** + * @brief Enable splitting transactions + * + * @param mspi_id mspi_id + * @param en enable / disable + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_enable_split_trans(uint32_t mspi_id, bool en) +{ + (void)mspi_id; + SPIMEM0.smem_ac.smem_split_trans_en = en; +} + +/** + * @brief Enable ECC address conversion + * + * @param mspi_id mspi_id + * @param en enable / disable + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_enable_ecc_addr_conversion(uint32_t mspi_id, bool en) +{ + (void)mspi_id; + SPIMEM0.smem_ecc_ctrl.smem_ecc_addr_en = en; +} + +/*--------------------------------------------------------------- + PMS +---------------------------------------------------------------*/ +/** + * @brief Enable PMS ECC + * + * @param mspi_id mspi_id + * @param region_id region_id + * @param en enable / disable + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_enable_pms_region_ecc(uint32_t mspi_id, uint32_t region_id, bool en) +{ + (void)mspi_id; + HAL_ASSERT(region_id < PSRAM_CTRLR_LL_PMS_REGION_NUMS); + SPIMEM0.smem_pmsn_attr[region_id].smem_pmsn_ecc = en; +} + +/** + * @brief Set PMS attr + * + * @param mspi_id mspi_id + * @param region_id region_id + * @param attr_mask attribute mask + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_set_pms_region_attr(uint32_t mspi_id, uint32_t region_id, uint32_t attr_mask) +{ + (void)mspi_id; + HAL_ASSERT(region_id < PSRAM_CTRLR_LL_PMS_REGION_NUMS); + SPIMEM0.smem_pmsn_attr[region_id].smem_pmsn_wr_attr = 0; + SPIMEM0.smem_pmsn_attr[region_id].smem_pmsn_rd_attr = 0; + if (attr_mask & PSRAM_CTRLR_LL_PMS_ATTR_WRITABLE) { + SPIMEM0.smem_pmsn_attr[region_id].smem_pmsn_wr_attr = 1; + } + if (attr_mask & PSRAM_CTRLR_LL_PMS_ATTR_READABLE) { + SPIMEM0.smem_pmsn_attr[region_id].smem_pmsn_rd_attr = 1; + } +} + +/** + * @brief Set PMS address + * + * @param mspi_id mspi_id + * @param region_id region_id + * @param addr start addr + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_set_pms_region_start_addr(uint32_t mspi_id, uint32_t region_id, uint32_t addr) +{ + (void)mspi_id; + HAL_ASSERT(region_id < PSRAM_CTRLR_LL_PMS_REGION_NUMS); + SPIMEM0.smem_pmsn_addr[region_id].smem_pmsn_addr_s = addr; +} + +/** + * @brief Set PMS size + * + * @param mspi_id mspi_id + * @param region_id region_id + * @param size size + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_set_pms_region_size(uint32_t mspi_id, uint32_t region_id, uint32_t size) +{ + (void)mspi_id; + HAL_ASSERT(region_id < PSRAM_CTRLR_LL_PMS_REGION_NUMS); + SPIMEM0.smem_pmsn_size[region_id].smem_pmsn_size = size; +} + +/** + * @brief Get PMS address + * + * @param mspi_id mspi_id + * @param region_id region_id + */ +__attribute__((always_inline)) +static inline uint32_t psram_ctrlr_ll_get_pms_region_start_addr(uint32_t mspi_id, uint32_t region_id) +{ + (void)mspi_id; + HAL_ASSERT(region_id < PSRAM_CTRLR_LL_PMS_REGION_NUMS); + return SPIMEM0.smem_pmsn_addr[region_id].smem_pmsn_addr_s; +} + +/** + * @brief Get PMS size + * + * @param mspi_id mspi_id + * @param region_id region_id + */ +__attribute__((always_inline)) +static inline uint32_t psram_ctrlr_ll_get_pms_region_size(uint32_t mspi_id, uint32_t region_id) +{ + (void)mspi_id; + HAL_ASSERT(region_id < PSRAM_CTRLR_LL_PMS_REGION_NUMS); + return SPIMEM0.smem_pmsn_size[region_id].smem_pmsn_size; +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32c5/include/hal/rmt_ll.h b/components/hal/esp32c5/include/hal/rmt_ll.h index 0e54a0b37867..688dd6095190 100644 --- a/components/hal/esp32c5/include/hal/rmt_ll.h +++ b/components/hal/esp32c5/include/hal/rmt_ll.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 */ @@ -38,6 +38,11 @@ extern "C" { #define RMT_LL_MAX_FILTER_VALUE 255 #define RMT_LL_MAX_IDLE_VALUE 32767 +// Maximum values due to limited register bit width +#define RMT_LL_CHANNEL_CLOCK_MAX_PRESCALE 256 +#define RMT_LL_GROUP_CLOCK_MAX_INTEGER_PRESCALE 256 +#define RMT_LL_GROUP_CLOCK_MAX_FRACTAL_PRESCALE 64 + typedef enum { RMT_LL_MEM_OWNER_SW = 0, RMT_LL_MEM_OWNER_HW = 1, diff --git a/components/hal/esp32c5/include/hal/spi_flash_encrypted_ll.h b/components/hal/esp32c5/include/hal/spi_flash_encrypted_ll.h index 49239efd2711..4c5ed687af5e 100644 --- a/components/hal/esp32c5/include/hal/spi_flash_encrypted_ll.h +++ b/components/hal/esp32c5/include/hal/spi_flash_encrypted_ll.h @@ -11,6 +11,7 @@ ******************************************************************************/ // The Lowlevel layer for SPI Flash Encryption. +#pragma once #include #include @@ -169,6 +170,14 @@ static inline void spi_flash_encrypt_ll_enable_pseudo_rounds(uint8_t mode, uint8 } } +/** + * @brief Check if the pseudo round function is supported + */ +static inline bool spi_flash_encrypt_ll_is_pseudo_rounds_function_supported(void) +{ + return true; +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32c5/include/hal/spi_ll.h b/components/hal/esp32c5/include/hal/spi_ll.h index 943143f3f4b6..44363e920a05 100644 --- a/components/hal/esp32c5/include/hal/spi_ll.h +++ b/components/hal/esp32c5/include/hal/spi_ll.h @@ -180,7 +180,7 @@ static inline void spi_ll_clk_source_pre_div(spi_dev_t *hw, uint8_t hs_div, uint { // In IDF master driver 'mst_div' will be const 2 and 'hs_div' is actually pre_div temporally (void) hs_div; - PCR.spi2_clkm_conf.spi2_clkm_div_num = mst_div - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.spi2_clkm_conf, spi2_clkm_div_num, mst_div - 1); } /** diff --git a/components/hal/esp32c6/include/hal/brownout_ll.h b/components/hal/esp32c6/include/hal/brownout_ll.h index 61248cfe4761..b70875a9fd4d 100644 --- a/components/hal/esp32c6/include/hal/brownout_ll.h +++ b/components/hal/esp32c6/include/hal/brownout_ll.h @@ -121,7 +121,7 @@ static inline void brownout_ll_ana_reset_enable(bool enable) __attribute__((always_inline)) static inline void brownout_ll_intr_clear(void) { - LP_ANA_PERI.int_clr.bod_mode0 = 1; + LP_ANA_PERI.int_clr.val = BROWNOUT_DETECTOR_LL_INTERRUPT_MASK; } /** diff --git a/components/hal/esp32c6/include/hal/ecc_ll.h b/components/hal/esp32c6/include/hal/ecc_ll.h index cb8b4ca2cd28..d144dbff2978 100644 --- a/components/hal/esp32c6/include/hal/ecc_ll.h +++ b/components/hal/esp32c6/include/hal/ecc_ll.h @@ -173,6 +173,12 @@ static inline void ecc_ll_read_param(ecc_ll_param_t param, uint8_t *buf, uint16_ memcpy(buf, (void *)reg, len); } +static inline void ecc_ll_enable_constant_time_point_mul(bool enable) +{ + // Not supported for ESP32-C6 + (void) enable; //unused +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32c6/include/hal/parlio_ll.h b/components/hal/esp32c6/include/hal/parlio_ll.h index 3eb277d14f98..1679dc35c297 100644 --- a/components/hal/esp32c6/include/hal/parlio_ll.h +++ b/components/hal/esp32c6/include/hal/parlio_ll.h @@ -373,6 +373,7 @@ static inline void parlio_ll_rx_update_config(parl_io_dev_t *dev) * @param dev Parallel IO register base address * @param src Clock source */ +__attribute__((always_inline)) static inline void parlio_ll_tx_set_clock_source(parl_io_dev_t *dev, parlio_clock_source_t src) { (void)dev; diff --git a/components/hal/esp32c6/include/hal/rmt_ll.h b/components/hal/esp32c6/include/hal/rmt_ll.h index 9fdc75764e0b..58ccb893a013 100644 --- a/components/hal/esp32c6/include/hal/rmt_ll.h +++ b/components/hal/esp32c6/include/hal/rmt_ll.h @@ -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 */ @@ -38,6 +38,11 @@ extern "C" { #define RMT_LL_MAX_FILTER_VALUE 255 #define RMT_LL_MAX_IDLE_VALUE 32767 +// Maximum values due to limited register bit width +#define RMT_LL_CHANNEL_CLOCK_MAX_PRESCALE 256 +#define RMT_LL_GROUP_CLOCK_MAX_INTEGER_PRESCALE 256 +#define RMT_LL_GROUP_CLOCK_MAX_FRACTAL_PRESCALE 64 + typedef enum { RMT_LL_MEM_OWNER_SW = 0, RMT_LL_MEM_OWNER_HW = 1, diff --git a/components/hal/esp32c6/include/hal/spi_flash_encrypted_ll.h b/components/hal/esp32c6/include/hal/spi_flash_encrypted_ll.h index 20c303344a43..debef0835f7e 100644 --- a/components/hal/esp32c6/include/hal/spi_flash_encrypted_ll.h +++ b/components/hal/esp32c6/include/hal/spi_flash_encrypted_ll.h @@ -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 */ @@ -11,6 +11,7 @@ ******************************************************************************/ // The Lowlevel layer for SPI Flash Encryption. +#pragma once #include #include @@ -24,7 +25,7 @@ extern "C" { #endif -/// Choose type of chip you want to encrypt manully +/// Choose type of chip you want to encrypt manually typedef enum { FLASH_ENCRYPTION_MANU = 0, ///!< Manually encrypt the flash chip. @@ -51,7 +52,7 @@ static inline void spi_flash_encrypt_ll_disable(void) } /** - * Choose type of chip you want to encrypt manully + * Choose type of chip you want to encrypt manually * * @param type The type of chip to be encrypted * diff --git a/components/hal/esp32c61/include/hal/brownout_ll.h b/components/hal/esp32c61/include/hal/brownout_ll.h index ac3b966d56a7..8991ec6f9327 100644 --- a/components/hal/esp32c61/include/hal/brownout_ll.h +++ b/components/hal/esp32c61/include/hal/brownout_ll.h @@ -121,7 +121,7 @@ static inline void brownout_ll_ana_reset_enable(bool enable) __attribute__((always_inline)) static inline void brownout_ll_intr_clear(void) { - LP_ANA.int_clr.bod_mode0_int_clr = 1; + LP_ANA.int_clr.val = BROWNOUT_DETECTOR_LL_INTERRUPT_MASK; } /** diff --git a/components/hal/esp32c61/include/hal/psram_ctrlr_ll.h b/components/hal/esp32c61/include/hal/psram_ctrlr_ll.h index 0a9946ff5766..868dcee35c5d 100644 --- a/components/hal/esp32c61/include/hal/psram_ctrlr_ll.h +++ b/components/hal/esp32c61/include/hal/psram_ctrlr_ll.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 */ @@ -30,7 +30,10 @@ extern "C" { #define PSRAM_CTRLR_LL_MSPI_ID_0 0 #define PSRAM_CTRLR_LL_MSPI_ID_1 1 -#define PSRAM_LL_CS_SEL SPI_MEM_CS1_DIS_M +#define PSRAM_LL_CS_SEL SPI_MEM_CS1_DIS_M +#define PSRAM_CTRLR_LL_PMS_REGION_NUMS 4 +#define PSRAM_CTRLR_LL_PMS_ATTR_WRITABLE (1<<0) +#define PSRAM_CTRLR_LL_PMS_ATTR_READABLE (1<<1) /** * @brief PSRAM enum for cs id. @@ -40,6 +43,14 @@ typedef enum { PSRAM_LL_CS_ID_1 = 1, } psram_ll_cs_id_t; +/** + * @brief PSRAM ECC mode + */ +typedef enum { + PSRAM_LL_ECC_MODE_16TO17 = 0, + PSRAM_LL_ECC_MODE_16TO18 = 1, +} psram_ll_ecc_mode_t; + /** * @brief Set PSRAM write cmd * @@ -140,7 +151,7 @@ static inline uint32_t psram_ctrlr_ll_calculate_clock_reg(uint8_t clkdiv) * @param mspi_id mspi_id * @param read_mode read mode */ -static inline void psram_ctrlr_ll_set_read_mode(uint32_t mspi_id, psram_hal_cmd_mode_t read_mode) +static inline void psram_ctrlr_ll_set_read_mode(uint32_t mspi_id, psram_cmd_mode_t read_mode) { typeof (SPIMEM0.mem_cache_sctrl) mem_cache_sctrl; mem_cache_sctrl.val = SPIMEM0.mem_cache_sctrl.val; @@ -258,6 +269,235 @@ static inline void psram_ctrlr_ll_enable_quad_command(uint32_t mspi_id, bool ena SPIMEM1.ctrl.fcmd_quad = ena; } +/*--------------------------------------------------------------- + ECC +---------------------------------------------------------------*/ +/** + * @brief Set ECC CS hold + * + * @param mspi_id mspi_id + * @param hold_n cs hold time + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_set_ecc_cs_hold(uint32_t mspi_id, uint32_t hold_n) +{ + HAL_ASSERT(hold_n > 0); + SPIMEM0.smem_ac.smem_ecc_cs_hold_time = hold_n - 1; +} + +/** + * @brief Set ECC mode + * + * @param mspi_id mspi_id + * @param mode ecc mode + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_set_ecc_mode(uint32_t mspi_id, psram_ll_ecc_mode_t mode) +{ + SPIMEM0.smem_ac.smem_ecc_16to18_byte_en = mode; +} + +/** + * @brief Set page size + * + * @param mspi_id mspi_id + * @param size page size + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_set_page_size(uint32_t mspi_id, uint32_t size) +{ + uint32_t size_val = 0; + switch (size) { + case 256: + size_val = 0; + break; + case 512: + size_val = 1; + break; + case 1024: + size_val = 2; + break; + case 2048: + size_val = 3; + break; + default: + HAL_ASSERT(false); + break; + } + + SPIMEM0.smem_ecc_ctrl.smem_page_size = size_val; +} + +/** + * @brief Get page size + * + * @param mspi_id mspi_id + * + * @return page size + */ +__attribute__((always_inline)) +static inline uint32_t psram_ctrlr_ll_get_page_size(uint32_t mspi_id) +{ + (void)mspi_id; + uint32_t page_size = 0; + + uint32_t reg_val = SPIMEM0.smem_ecc_ctrl.smem_page_size; + switch(reg_val) { + case 0: + page_size = 256; + break; + case 1: + page_size = 512; + break; + case 2: + page_size = 1024; + break; + case 3: + page_size = 2048; + break; + default: + HAL_ASSERT(false); + } + + return page_size; +} + +/** + * @brief Skip page corner + * + * @param mspi_id mspi_id + * @param en enable / disable + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_enable_skip_page_corner(uint32_t mspi_id, bool en) +{ + SPIMEM0.smem_ac.smem_ecc_skip_page_corner = en; +} + +/** + * @brief Enable splitting transactions + * + * @param mspi_id mspi_id + * @param en enable / disable + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_enable_split_trans(uint32_t mspi_id, bool en) +{ + (void)mspi_id; + SPIMEM0.smem_ac.smem_split_trans_en = en; +} + +/** + * @brief Enable ECC address conversion + * + * @param mspi_id mspi_id + * @param en enable / disable + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_enable_ecc_addr_conversion(uint32_t mspi_id, bool en) +{ + (void)mspi_id; + SPIMEM0.smem_ecc_ctrl.smem_ecc_addr_en = en; +} + +/*--------------------------------------------------------------- + PMS +---------------------------------------------------------------*/ +/** + * @brief Enable PMS ECC + * + * @param mspi_id mspi_id + * @param region_id region_id + * @param en enable / disable + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_enable_pms_region_ecc(uint32_t mspi_id, uint32_t region_id, bool en) +{ + (void)mspi_id; + HAL_ASSERT(region_id < PSRAM_CTRLR_LL_PMS_REGION_NUMS); + SPIMEM0.smem_pmsn_attr[region_id].smem_pmsn_ecc = en; +} + +/** + * @brief Set PMS attr + * + * @param mspi_id mspi_id + * @param region_id region_id + * @param attr_mask attribute mask + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_set_pms_region_attr(uint32_t mspi_id, uint32_t region_id, uint32_t attr_mask) +{ + (void)mspi_id; + HAL_ASSERT(region_id < PSRAM_CTRLR_LL_PMS_REGION_NUMS); + SPIMEM0.smem_pmsn_attr[region_id].smem_pmsn_wr_attr = 0; + SPIMEM0.smem_pmsn_attr[region_id].smem_pmsn_rd_attr = 0; + if (attr_mask & PSRAM_CTRLR_LL_PMS_ATTR_WRITABLE) { + SPIMEM0.smem_pmsn_attr[region_id].smem_pmsn_wr_attr = 1; + } + if (attr_mask & PSRAM_CTRLR_LL_PMS_ATTR_READABLE) { + SPIMEM0.smem_pmsn_attr[region_id].smem_pmsn_rd_attr = 1; + } +} + +/** + * @brief Set PMS address + * + * @param mspi_id mspi_id + * @param region_id region_id + * @param addr start addr + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_set_pms_region_start_addr(uint32_t mspi_id, uint32_t region_id, uint32_t addr) +{ + (void)mspi_id; + HAL_ASSERT(region_id < PSRAM_CTRLR_LL_PMS_REGION_NUMS); + SPIMEM0.smem_pmsn_addr[region_id].smem_pmsn_addr_s = addr; +} + +/** + * @brief Set PMS size + * + * @param mspi_id mspi_id + * @param region_id region_id + * @param size size + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_set_pms_region_size(uint32_t mspi_id, uint32_t region_id, uint32_t size) +{ + (void)mspi_id; + HAL_ASSERT(region_id < PSRAM_CTRLR_LL_PMS_REGION_NUMS); + SPIMEM0.smem_pmsn_size[region_id].smem_pmsn_size = size; +} + +/** + * @brief Get PMS address + * + * @param mspi_id mspi_id + * @param region_id region_id + */ +__attribute__((always_inline)) +static inline uint32_t psram_ctrlr_ll_get_pms_region_start_addr(uint32_t mspi_id, uint32_t region_id) +{ + (void)mspi_id; + HAL_ASSERT(region_id < PSRAM_CTRLR_LL_PMS_REGION_NUMS); + return SPIMEM0.smem_pmsn_addr[region_id].smem_pmsn_addr_s; +} + +/** + * @brief Get PMS size + * + * @param mspi_id mspi_id + * @param region_id region_id + */ +__attribute__((always_inline)) +static inline uint32_t psram_ctrlr_ll_get_pms_region_size(uint32_t mspi_id, uint32_t region_id) +{ + (void)mspi_id; + HAL_ASSERT(region_id < PSRAM_CTRLR_LL_PMS_REGION_NUMS); + return SPIMEM0.smem_pmsn_size[region_id].smem_pmsn_size; +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32c61/include/hal/spi_flash_encrypted_ll.h b/components/hal/esp32c61/include/hal/spi_flash_encrypted_ll.h index 0d79cbd67813..3a7f63b56f91 100644 --- a/components/hal/esp32c61/include/hal/spi_flash_encrypted_ll.h +++ b/components/hal/esp32c61/include/hal/spi_flash_encrypted_ll.h @@ -11,6 +11,7 @@ ******************************************************************************/ // The Lowlevel layer for SPI Flash Encryption. +#pragma once #include #include @@ -169,6 +170,14 @@ static inline void spi_flash_encrypt_ll_enable_pseudo_rounds(uint8_t mode, uint8 } } +/** + * @brief Check if the pseudo round function is supported + */ +static inline bool spi_flash_encrypt_ll_is_pseudo_rounds_function_supported(void) +{ + return true; +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32c61/include/hal/spi_ll.h b/components/hal/esp32c61/include/hal/spi_ll.h index 7b5c03332e22..70fcfe9d706c 100644 --- a/components/hal/esp32c61/include/hal/spi_ll.h +++ b/components/hal/esp32c61/include/hal/spi_ll.h @@ -181,7 +181,7 @@ static inline void spi_ll_clk_source_pre_div(spi_dev_t *hw, uint8_t hs_div, uint { // In IDF master driver 'mst_div' will be const 2 and 'hs_div' is actually pre_div temporally (void) hs_div; - PCR.spi2_clkm_conf.spi2_clkm_div_num = mst_div - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.spi2_clkm_conf, spi2_clkm_div_num, mst_div - 1); } /** diff --git a/components/hal/esp32c61/include/hal/uart_ll.h b/components/hal/esp32c61/include/hal/uart_ll.h index 5910cad8afe8..5cff1d1f5e84 100644 --- a/components/hal/esp32c61/include/hal/uart_ll.h +++ b/components/hal/esp32c61/include/hal/uart_ll.h @@ -30,7 +30,7 @@ extern "C" { // Get UART hardware instance with giving uart num #define UART_LL_GET_HW(num) (((num) == UART_NUM_0) ? (&UART0) : (((num) == UART_NUM_1) ? (&UART1) : (&UART2))) -#define UART_LL_MIN_WAKEUP_THRESH (2) +#define UART_LL_MIN_WAKEUP_THRESH (3) #define UART_LL_INTR_MASK (0x7ffff) //All interrupt mask #define UART_LL_FSM_IDLE (0x0) diff --git a/components/hal/esp32h2/include/hal/aes_ll.h b/components/hal/esp32h2/include/hal/aes_ll.h index f13d417eb57b..7c505e71fe07 100644 --- a/components/hal/esp32h2/include/hal/aes_ll.h +++ b/components/hal/esp32h2/include/hal/aes_ll.h @@ -12,6 +12,9 @@ #include "soc/pcr_struct.h" #include "hal/aes_types.h" +#include "hal/efuse_hal.h" +#include "soc/chip_revision.h" + #ifdef __cplusplus extern "C" { #endif @@ -241,6 +244,38 @@ static inline void aes_ll_interrupt_clear(void) REG_WRITE(AES_INT_CLEAR_REG, 1); } +/** + * @brief Enable the pseudo-round function during AES operations + * + * @param enable true to enable, false to disable + * @param base basic number of pseudo rounds, zero if disable + * @param increment increment number of pseudo rounds, zero if disable + * @param key_rng_cnt update frequency of the pseudo-key, zero if disable + */ +static inline void aes_ll_enable_pseudo_rounds(bool enable, uint8_t base, uint8_t increment, uint8_t key_rng_cnt) +{ + REG_SET_FIELD(AES_PSEUDO_REG, AES_PSEUDO_EN, enable); + + if (enable) { + REG_SET_FIELD(AES_PSEUDO_REG, AES_PSEUDO_BASE, base); + REG_SET_FIELD(AES_PSEUDO_REG, AES_PSEUDO_INC, increment); + REG_SET_FIELD(AES_PSEUDO_REG, AES_PSEUDO_RNG_CNT, key_rng_cnt); + } else { + REG_SET_FIELD(AES_PSEUDO_REG, AES_PSEUDO_BASE, 0); + REG_SET_FIELD(AES_PSEUDO_REG, AES_PSEUDO_INC, 0); + REG_SET_FIELD(AES_PSEUDO_REG, AES_PSEUDO_RNG_CNT, 0); + } +} + +/** + * @brief Check if the pseudo round function is supported + * The AES pseudo round function is only avliable in chip version + * above 1.2 in ESP32-H2 + */ +static inline bool aes_ll_is_pseudo_rounds_function_supported(void) +{ + return ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 102); +} #ifdef __cplusplus } diff --git a/components/hal/esp32h2/include/hal/brownout_ll.h b/components/hal/esp32h2/include/hal/brownout_ll.h index 9dce284ac8b0..8816a36a4ae9 100644 --- a/components/hal/esp32h2/include/hal/brownout_ll.h +++ b/components/hal/esp32h2/include/hal/brownout_ll.h @@ -122,7 +122,7 @@ static inline void brownout_ll_ana_reset_enable(bool enable) __attribute__((always_inline)) static inline void brownout_ll_intr_clear(void) { - LP_ANA_PERI.int_clr.bod_mode0_int_clr = 1; + LP_ANA_PERI.int_clr.val = BROWNOUT_DETECTOR_LL_INTERRUPT_MASK; } /** diff --git a/components/hal/esp32h2/include/hal/ecc_ll.h b/components/hal/esp32h2/include/hal/ecc_ll.h index 46667692a700..c57200f6273a 100644 --- a/components/hal/esp32h2/include/hal/ecc_ll.h +++ b/components/hal/esp32h2/include/hal/ecc_ll.h @@ -12,6 +12,8 @@ #include "soc/ecc_mult_reg.h" #include "soc/pcr_struct.h" #include "soc/pcr_reg.h" +#include "soc/chip_revision.h" +#include "hal/efuse_hal.h" #ifdef __cplusplus extern "C" { @@ -211,6 +213,18 @@ static inline ecc_mod_base_t ecc_ll_get_mod_base(void) return (ecc_mod_base_t)(REG_GET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_MOD_BASE)); } +static inline void ecc_ll_enable_constant_time_point_mul(bool enable) +{ + // ECC constant time point multiplication is supported only on rev 1.2 and above + if (ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 102)){ + 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); + } + } +} + static inline void ecc_ll_read_param(ecc_ll_param_t param, uint8_t *buf, uint16_t len) { uint32_t reg; diff --git a/components/hal/esp32h2/include/hal/ecdsa_ll.h b/components/hal/esp32h2/include/hal/ecdsa_ll.h index 393d5392fc2b..bea4ef26efba 100644 --- a/components/hal/esp32h2/include/hal/ecdsa_ll.h +++ b/components/hal/esp32h2/include/hal/ecdsa_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 */ @@ -9,8 +9,10 @@ #include #include "hal/assert.h" #include "soc/ecdsa_reg.h" +#include "soc/ecdsa_struct.h" #include "soc/pcr_struct.h" #include "hal/ecdsa_types.h" +#include "hal/ecc_ll.h" #ifdef __cplusplus extern "C" { @@ -31,7 +33,7 @@ typedef enum { * @brief Interrupt types in ECDSA */ typedef enum { - ECDSA_INT_CALC_DONE, + ECDSA_INT_PREP_DONE, ECDSA_INT_SHA_RELEASE, } ecdsa_ll_intr_type_t; @@ -97,8 +99,8 @@ static inline void ecdsa_ll_reset_register(void) static inline void ecdsa_ll_enable_intr(ecdsa_ll_intr_type_t type) { switch (type) { - case ECDSA_INT_CALC_DONE: - REG_SET_FIELD(ECDSA_INT_ENA_REG, ECDSA_CALC_DONE_INT_ENA, 1); + case ECDSA_INT_PREP_DONE: + REG_SET_FIELD(ECDSA_INT_ENA_REG, ECDSA_PREP_DONE_INT_ENA, 1); break; case ECDSA_INT_SHA_RELEASE: REG_SET_FIELD(ECDSA_INT_ENA_REG, ECDSA_SHA_RELEASE_INT_ENA, 1); @@ -117,8 +119,8 @@ static inline void ecdsa_ll_enable_intr(ecdsa_ll_intr_type_t type) static inline void ecdsa_ll_disable_intr(ecdsa_ll_intr_type_t type) { switch (type) { - case ECDSA_INT_CALC_DONE: - REG_SET_FIELD(ECDSA_INT_ENA_REG, ECDSA_CALC_DONE_INT_ENA, 0); + case ECDSA_INT_PREP_DONE: + REG_SET_FIELD(ECDSA_INT_ENA_REG, ECDSA_PREP_DONE_INT_ENA, 0); break; case ECDSA_INT_SHA_RELEASE: REG_SET_FIELD(ECDSA_INT_ENA_REG, ECDSA_SHA_RELEASE_INT_ENA, 0); @@ -137,8 +139,8 @@ static inline void ecdsa_ll_disable_intr(ecdsa_ll_intr_type_t type) static inline void ecdsa_ll_clear_intr(ecdsa_ll_intr_type_t type) { switch (type) { - case ECDSA_INT_CALC_DONE: - REG_SET_FIELD(ECDSA_INT_CLR_REG, ECDSA_CALC_DONE_INT_CLR, 1); + case ECDSA_INT_PREP_DONE: + REG_SET_FIELD(ECDSA_INT_CLR_REG, ECDSA_PREP_DONE_INT_CLR, 1); break; case ECDSA_INT_SHA_RELEASE: REG_SET_FIELD(ECDSA_INT_CLR_REG, ECDSA_SHA_RELEASE_INT_CLR, 1); diff --git a/components/hal/esp32h2/include/hal/lp_clkrst_ll.h b/components/hal/esp32h2/include/hal/lp_clkrst_ll.h index 1e269388b0df..07679f110927 100644 --- a/components/hal/esp32h2/include/hal/lp_clkrst_ll.h +++ b/components/hal/esp32h2/include/hal/lp_clkrst_ll.h @@ -63,7 +63,7 @@ static inline void lp_clkrst_ll_select_modem_32k_clock_source(lp_clkrst_dev_t *h __attribute__((always_inline)) static inline void _lp_clkrst_ll_enable_rng_clock(bool en) { - LPPERI.clk_en->rng_ck_en = en; + LPPERI_REG_SET(clk_en.rng_ck_en, en); } /// LPPERI.clk_en is a shared register, so this function must be used in an atomic way diff --git a/components/hal/esp32h2/include/hal/modem_syscon_ll.h b/components/hal/esp32h2/include/hal/modem_syscon_ll.h index 9d6f3e8bbe23..1a29054dac22 100644 --- a/components/hal/esp32h2/include/hal/modem_syscon_ll.h +++ b/components/hal/esp32h2/include/hal/modem_syscon_ll.h @@ -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 */ @@ -60,15 +60,10 @@ static inline void modem_syscon_ll_enable_modem_sec_clock(modem_syscon_dev_t *hw hw->clk_conf.clk_modem_sec_apb_en = en; } -__attribute__((always_inline)) -static inline void modem_syscon_ll_enable_ble_timer_apb(modem_syscon_dev_t *hw, bool en) -{ - hw->clk_conf.clk_ble_timer_apb_en = en; -} - __attribute__((always_inline)) static inline void modem_syscon_ll_enable_ble_timer_clock(modem_syscon_dev_t *hw, bool en) { + hw->clk_conf.clk_ble_timer_apb_en = en; hw->clk_conf.clk_ble_timer_en = en; } diff --git a/components/hal/esp32h2/include/hal/parlio_ll.h b/components/hal/esp32h2/include/hal/parlio_ll.h index 59b738cd9d61..e41a13a3e0b1 100644 --- a/components/hal/esp32h2/include/hal/parlio_ll.h +++ b/components/hal/esp32h2/include/hal/parlio_ll.h @@ -398,6 +398,7 @@ static inline uint32_t parlio_ll_rx_get_fifo_cycle_cnt(parl_io_dev_t *dev) * @param dev Parallel IO register base address * @param src Clock source */ +__attribute__((always_inline)) static inline void parlio_ll_tx_set_clock_source(parl_io_dev_t *dev, parlio_clock_source_t src) { (void)dev; diff --git a/components/hal/esp32h2/include/hal/rmt_ll.h b/components/hal/esp32h2/include/hal/rmt_ll.h index 4ebb3a1e0628..924f9d24db66 100644 --- a/components/hal/esp32h2/include/hal/rmt_ll.h +++ b/components/hal/esp32h2/include/hal/rmt_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 */ @@ -38,6 +38,11 @@ extern "C" { #define RMT_LL_MAX_FILTER_VALUE 255 #define RMT_LL_MAX_IDLE_VALUE 32767 +// Maximum values due to limited register bit width +#define RMT_LL_CHANNEL_CLOCK_MAX_PRESCALE 256 +#define RMT_LL_GROUP_CLOCK_MAX_INTEGER_PRESCALE 256 +#define RMT_LL_GROUP_CLOCK_MAX_FRACTAL_PRESCALE 64 + typedef enum { RMT_LL_MEM_OWNER_SW = 0, RMT_LL_MEM_OWNER_HW = 1, diff --git a/components/hal/esp32h2/include/hal/rtc_io_ll.h b/components/hal/esp32h2/include/hal/rtc_io_ll.h index 2f69a7777c9f..56f82c256d3c 100644 --- a/components/hal/esp32h2/include/hal/rtc_io_ll.h +++ b/components/hal/esp32h2/include/hal/rtc_io_ll.h @@ -38,8 +38,8 @@ typedef enum { */ static inline void _rtcio_ll_enable_io_clock(bool enable) { - LPPERI.clk_en->lp_io_ck_en = enable; - while (LPPERI.clk_en->lp_io_ck_en != enable) { + LPPERI_REG_SET(clk_en.lp_io_ck_en, enable); + while (LPPERI_REG_GET(clk_en.lp_io_ck_en) != enable) { ; } } diff --git a/components/hal/esp32h2/include/hal/spi_flash_encrypted_ll.h b/components/hal/esp32h2/include/hal/spi_flash_encrypted_ll.h index 20c303344a43..eefe8b30ab0e 100644 --- a/components/hal/esp32h2/include/hal/spi_flash_encrypted_ll.h +++ b/components/hal/esp32h2/include/hal/spi_flash_encrypted_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,6 +11,7 @@ ******************************************************************************/ // The Lowlevel layer for SPI Flash Encryption. +#pragma once #include #include @@ -20,11 +21,14 @@ #include "soc/soc_caps.h" #include "hal/assert.h" +#include "hal/efuse_hal.h" +#include "soc/chip_revision.h" + #ifdef __cplusplus extern "C" { #endif -/// Choose type of chip you want to encrypt manully +/// Choose type of chip you want to encrypt manually typedef enum { FLASH_ENCRYPTION_MANU = 0, ///!< Manually encrypt the flash chip. @@ -51,7 +55,7 @@ static inline void spi_flash_encrypt_ll_disable(void) } /** - * Choose type of chip you want to encrypt manully + * Choose type of chip you want to encrypt manually * * @param type The type of chip to be encrypted * @@ -146,6 +150,39 @@ static inline bool spi_flash_encrypt_ll_check(uint32_t address, uint32_t length) return ((address % length) == 0) ? true : false; } +/** + * @brief Enable the pseudo-round function during XTS-AES operations + * + * @param mode set the mode for pseudo rounds, zero to disable, with increasing security upto three. + * @param base basic number of pseudo rounds, zero if disable + * @param increment increment number of pseudo rounds, zero if disable + * @param key_rng_cnt update frequency of the pseudo-key, zero if disable + */ +static inline void spi_flash_encrypt_ll_enable_pseudo_rounds(uint8_t mode, uint8_t base, uint8_t increment, uint8_t key_rng_cnt) +{ + REG_SET_FIELD(XTS_AES_PSEUDO_ROUND_CONF_REG(0), XTS_AES_MODE_PSEUDO, mode); + + if (mode) { + REG_SET_FIELD(XTS_AES_PSEUDO_ROUND_CONF_REG(0), XTS_AES_PSEUDO_BASE, base); + REG_SET_FIELD(XTS_AES_PSEUDO_ROUND_CONF_REG(0), XTS_AES_PSEUDO_INC, increment); + REG_SET_FIELD(XTS_AES_PSEUDO_ROUND_CONF_REG(0), XTS_AES_PSEUDO_RNG_CNT, key_rng_cnt); + } else { + REG_SET_FIELD(XTS_AES_PSEUDO_ROUND_CONF_REG(0), XTS_AES_PSEUDO_BASE, 0); + REG_SET_FIELD(XTS_AES_PSEUDO_ROUND_CONF_REG(0), XTS_AES_PSEUDO_INC, 0); + REG_SET_FIELD(XTS_AES_PSEUDO_ROUND_CONF_REG(0), XTS_AES_PSEUDO_RNG_CNT, 0); + } +} + +/** + * @brief Check if the pseudo round function is supported + * The XTS-AES pseudo round function is only avliable in chip version + * above 1.2 in ESP32-H2 + */ +static inline bool spi_flash_encrypt_ll_is_pseudo_rounds_function_supported(void) +{ + return ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 102); +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32h2/include/hal/vbat_ll.h b/components/hal/esp32h2/include/hal/vbat_ll.h new file mode 100644 index 000000000000..f637ee4db055 --- /dev/null +++ b/components/hal/esp32h2/include/hal/vbat_ll.h @@ -0,0 +1,162 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/******************************************************************************* + * NOTICE + * The ll is not public api, don't use in application code. + * See readme.md in hal/readme.md + ******************************************************************************/ + +#pragma once + +#include +#include "esp_bit_defs.h" +#include "soc/lp_analog_peri_struct.h" +#include "hal/regi2c_ctrl.h" +#include "soc/regi2c_brownout.h" + + +typedef enum { + VBAT_LL_CHARGER_UPVOLTAGE_INTR = BIT(27), + VBAT_LL_CHARGER_UNDERVOLTAGE_INTR = BIT(28), + VBAT_LL_BROWNOUT_INTR = BIT(30), +} vbat_ll_intr_t; + +#define VBAT_LL_CHARGER_MASK (BIT(27)|BIT(28)) +#define VBAT_LL_DETECT_MASK (BIT(30)) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Set vbat brownout threshold voltage + * + * @param threshold vbat brownout threshold + */ +static inline void vbat_ll_set_brownout_threshold(uint8_t threshold) +{ + // Give same value + REGI2C_WRITE_MASK(I2C_BOD, I2C_PMU_OR_DREF_VBAT_L, threshold); + REGI2C_WRITE_MASK(I2C_BOD, I2C_PMU_OR_DREF_VBAT_H, threshold); +} + +/** + * @brief Set vbat charge threshold voltage + * + * @param threshold vbat charge threshold + */ +static inline void vbat_ll_set_charger_threshold(uint8_t threshold_l, uint8_t threshold_h) +{ + REGI2C_WRITE_MASK(I2C_BOD, I2C_BIAS_OR_DREF_VBAT_CHARGER_L, threshold_l); + REGI2C_WRITE_MASK(I2C_BOD, I2C_BIAS_OR_DREF_VBAT_CHARGER_H, threshold_h); +} + +/** + * @brief Enable or disable the VBAT charger comparator + * + * @param enable Set to `true` to enable the comparator, or `false` to disable it. + */ +static inline void vbat_ll_enable_charger_comparator(bool enable) +{ + REGI2C_WRITE_MASK(I2C_BOD, I2C_BIAS_OR_FORCE_PU_VBAT_CHARGER, enable); +} + +/** + * @brief Set the under voltage filter time for the charger detector + * + * @param time_tick The filter time in ticks (unit depends on the hardware implementation). + */ +static inline void vbat_ll_set_undervoltage_filter_time(uint32_t time_tick) +{ + LP_ANA_PERI.vddbat_charge_cntl.vddbat_charge_undervoltage_target = time_tick; +} + +/** + * @brief Set the upvoltage filter time for the charger detector + * + * @param time_tick The filter time in ticks (unit depends on the hardware implementation). + */ +static inline void vbat_ll_set_upvoltage_filter_time(uint32_t time_tick) +{ + LP_ANA_PERI.vddbat_charge_cntl.vddbat_charge_upvoltage_target = time_tick; +} + +/** + * @brief Set the charger resistor value for VBAT charging + * + * @param resistor Resistor value to be set (unit depends on the hardware implementation). + */ +static inline void vbat_ll_set_charger_resistor(uint32_t resistor) +{ + REGI2C_WRITE_MASK(I2C_BOD, I2C_BIAS_OR_DRES_CHARGER, resistor); +} + +/* + * @brief Start or stop the VBAT battery charging process + * + * @param start Set to true to start charging, or false to stop charging. + */ +static inline void vbat_ll_start_battery_charge(bool start) +{ + LP_ANA_PERI.vddbat_bod_cntl.vddbat_charger = start; +} + +/** + * @brief Enable the interrupt mask for vbat usage + * + * @param mask A bitmask representing the interrupts to enable. + * Each bit corresponds to a specific interrupt source. + * @param enable true for enabling the interrupt, otherwise false. + * + * @note Avoid concurrency risky with brownout_ll_intr_enable + */ +static inline void vbat_ll_enable_intr_mask(uint32_t mask, bool enable) +{ + if (enable) { + LP_ANA_PERI.int_ena.val |= mask; + } else { + LP_ANA_PERI.int_ena.val &= ~mask; + } +} + +/** + * @brief Clear the interrupt mask for vbat usage + * + * @param mask A bitmask representing the interrupts to clear. + * Each bit corresponds to a specific interrupt source. + */ +static inline void vbat_ll_clear_intr_mask(uint32_t mask) +{ + LP_ANA_PERI.int_clr.val = mask; +} + +/** + * @brief Get the current interrupt mask for vbat usage + * + * @param intr_status Pointer to a variable where the interrupt status mask will be stored. + * The function will write the current interrupt status to this variable. + */ +static inline void vbat_ll_get_interrupt_status(uint32_t *intr_status) +{ + *intr_status = LP_ANA_PERI.int_st.val; +} + +/** + * @brief Clear the VBAT count for charge detection + * + * This function clears the internal counter that tracks the number of charge events detected + * related to the VBAT power supply. It is typically used to reset the count for monitoring purposes. + */ +static inline void vbat_ll_clear_count(void) +{ + LP_ANA_PERI.vddbat_charge_cntl.vddbat_charge_cnt_clr = 1; + LP_ANA_PERI.vddbat_charge_cntl.vddbat_charge_cnt_clr = 0; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32h21/include/hal/crosscore_int_ll.h b/components/hal/esp32h21/include/hal/crosscore_int_ll.h index f0ff2d0140a8..c76790d756bc 100644 --- a/components/hal/esp32h21/include/hal/crosscore_int_ll.h +++ b/components/hal/esp32h21/include/hal/crosscore_int_ll.h @@ -8,8 +8,6 @@ #include "esp_attr.h" #include "soc/intpri_reg.h" -//TODO: [ESP32H21] IDF-11537, inherit from h2 - #ifdef __cplusplus extern "C" { #endif diff --git a/components/hal/esp32h21/include/hal/ecc_ll.h b/components/hal/esp32h21/include/hal/ecc_ll.h new file mode 100644 index 000000000000..75ac321369e7 --- /dev/null +++ b/components/hal/esp32h21/include/hal/ecc_ll.h @@ -0,0 +1,255 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include +#include "hal/assert.h" +#include "hal/ecc_types.h" +#include "soc/ecc_mult_reg.h" +#include "soc/pcr_struct.h" +#include "soc/pcr_reg.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + ECC_PARAM_PX = 0x0, + ECC_PARAM_PY, + ECC_PARAM_K, + ECC_PARAM_QX, + ECC_PARAM_QY, + ECC_PARAM_QZ, +} ecc_ll_param_t; + +/** + * @brief Enable the bus clock for ECC peripheral module + * + * @param true to enable the module, false to disable the module + */ +static inline void ecc_ll_enable_bus_clock(bool enable) +{ + PCR.ecc_conf.ecc_clk_en = enable; +} + +/** + * @brief Reset the ECC peripheral module + */ +static inline void ecc_ll_reset_register(void) +{ + PCR.ecc_conf.ecc_rst_en = 1; + PCR.ecc_conf.ecc_rst_en = 0; + + // Clear reset on ECDSA, otherwise ECC is held in reset + PCR.ecdsa_conf.ecdsa_rst_en = 0; +} + +static inline void ecc_ll_power_up(void) +{ + REG_CLR_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_PD); + REG_CLR_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_FORCE_PD); +} + +static inline void ecc_ll_power_down(void) +{ + REG_CLR_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_FORCE_PU); + REG_SET_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_PD); +} + +static inline void ecc_ll_enable_interrupt(void) +{ + REG_SET_FIELD(ECC_MULT_INT_ENA_REG, ECC_MULT_CALC_DONE_INT_ENA, 1); +} + +static inline void ecc_ll_disable_interrupt(void) +{ + REG_SET_FIELD(ECC_MULT_INT_ENA_REG, ECC_MULT_CALC_DONE_INT_ENA, 0); +} + +static inline void ecc_ll_clear_interrupt(void) +{ + REG_SET_FIELD(ECC_MULT_INT_CLR_REG, ECC_MULT_CALC_DONE_INT_CLR, 1); +} + +static inline void ecc_ll_set_mode(ecc_mode_t mode) +{ + switch(mode) { + case ECC_MODE_POINT_MUL: + REG_SET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_WORK_MODE, 0); + break; + case ECC_MODE_VERIFY: + REG_SET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_WORK_MODE, 2); + break; + case ECC_MODE_VERIFY_THEN_POINT_MUL: + REG_SET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_WORK_MODE, 3); + break; + case ECC_MODE_JACOBIAN_POINT_MUL: + REG_SET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_WORK_MODE, 4); + break; + case ECC_MODE_POINT_ADD: + REG_SET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_WORK_MODE, 5); + break; + case ECC_MODE_JACOBIAN_POINT_VERIFY: + REG_SET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_WORK_MODE, 6); + break; + case ECC_MODE_POINT_VERIFY_JACOBIAN_MUL: + REG_SET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_WORK_MODE, 7); + break; + case ECC_MODE_MOD_ADD: + REG_SET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_WORK_MODE, 8); + break; + case ECC_MODE_MOD_SUB: + REG_SET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_WORK_MODE, 9); + break; + case ECC_MODE_MOD_MUL: + REG_SET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_WORK_MODE, 10); + break; + case ECC_MODE_INVERSE_MUL: + REG_SET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_WORK_MODE, 11); + break; + default: + HAL_ASSERT(false && "Unsupported mode"); + break; + } +} + +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; + case ECC_CURVE_SECP192R1: + REG_CLR_BIT(ECC_MULT_CONF_REG, ECC_MULT_KEY_LENGTH); + break; + default: + HAL_ASSERT(false && "Unsupported curve"); + return; + } +} + +static inline void ecc_ll_set_mod_base(ecc_mod_base_t base) +{ + switch(base) { + case ECC_MOD_N: + REG_CLR_BIT(ECC_MULT_CONF_REG, ECC_MULT_MOD_BASE); + break; + case ECC_MOD_P: + REG_SET_BIT(ECC_MULT_CONF_REG, ECC_MULT_MOD_BASE); + break; + default: + HAL_ASSERT(false && "Unsupported curve"); + return; + } +} + +static inline void ecc_ll_enable_constant_time_point_mul(bool enable) +{ + 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); + } +} + +static inline void ecc_ll_write_param(ecc_ll_param_t param, const uint8_t *buf, uint16_t len) +{ + uint32_t reg; + uint32_t word; + switch (param) { + case ECC_PARAM_PX: + reg = ECC_MULT_PX_MEM; + break; + case ECC_PARAM_PY: + reg = ECC_MULT_PY_MEM; + break; + case ECC_PARAM_K: + reg = ECC_MULT_K_MEM; + break; + case ECC_PARAM_QX: + reg = ECC_MULT_QX_MEM; + break; + case ECC_PARAM_QY: + reg = ECC_MULT_QY_MEM; + break; + case ECC_PARAM_QZ: + reg = ECC_MULT_QZ_MEM; + break; + default: + HAL_ASSERT(false && "Invalid parameter"); + return; + } + + for (int i = 0; i < len; i += 4) { + memcpy(&word, buf + i, 4); + REG_WRITE(reg + i, word); + } +} + +static inline void ecc_ll_start_calc(void) +{ + REG_SET_BIT(ECC_MULT_CONF_REG, ECC_MULT_START); +} + +static inline int ecc_ll_is_calc_finished(void) +{ + return REG_GET_FIELD(ECC_MULT_INT_RAW_REG, ECC_MULT_CALC_DONE_INT_RAW); +} + +static inline ecc_mode_t ecc_ll_get_mode(void) +{ + return (ecc_mode_t)(REG_GET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_WORK_MODE)); +} + +static inline int ecc_ll_get_verification_result(void) +{ + return REG_GET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_VERIFICATION_RESULT); +} + +static inline ecc_curve_t ecc_ll_get_curve(void) +{ + return (ecc_curve_t)(REG_GET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_KEY_LENGTH)); +} + +static inline ecc_mod_base_t ecc_ll_get_mod_base(void) +{ + return (ecc_mod_base_t)(REG_GET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_MOD_BASE)); +} + +static inline void ecc_ll_read_param(ecc_ll_param_t param, uint8_t *buf, uint16_t len) +{ + uint32_t reg; + switch (param) { + case ECC_PARAM_PX: + reg = ECC_MULT_PX_MEM; + break; + case ECC_PARAM_PY: + reg = ECC_MULT_PY_MEM; + break; + case ECC_PARAM_K: + reg = ECC_MULT_K_MEM; + break; + case ECC_PARAM_QX: + reg = ECC_MULT_QX_MEM; + break; + case ECC_PARAM_QY: + reg = ECC_MULT_QY_MEM; + break; + case ECC_PARAM_QZ: + reg = ECC_MULT_QZ_MEM; + break; + default: + HAL_ASSERT(false && "Invalid parameter"); + return; + } + + memcpy(buf, (void *)reg, len); +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32h21/include/hal/mpi_ll.h b/components/hal/esp32h21/include/hal/mpi_ll.h new file mode 100644 index 000000000000..fc4d03bc814e --- /dev/null +++ b/components/hal/esp32h21/include/hal/mpi_ll.h @@ -0,0 +1,184 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include +#include +#include "hal/assert.h" +#include "hal/mpi_types.h" +#include "soc/pcr_reg.h" +#include "soc/pcr_struct.h" +#include "soc/rsa_reg.h" +#include "soc/mpi_periph.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @brief Enable the bus clock for MPI peripheral module + * + * @param enable true to enable the module, false to disable the module + */ +static inline void mpi_ll_enable_bus_clock(bool enable) +{ + PCR.rsa_conf.rsa_clk_en = enable; +} + +/** + * @brief Reset the MPI peripheral module + */ +static inline void mpi_ll_reset_register(void) +{ + PCR.rsa_conf.rsa_rst_en = 1; + PCR.rsa_conf.rsa_rst_en = 0; + + // Clear reset on digital signature also, otherwise RSA is held in reset + PCR.ds_conf.ds_rst_en = 0; + PCR.ecdsa_conf.ecdsa_rst_en = 0; +} + +static inline size_t mpi_ll_calculate_hardware_words(size_t words) +{ + return words; +} + +static inline void mpi_ll_power_up(void) +{ + /* Power up the MPI peripheral */ + REG_CLR_BIT(PCR_RSA_PD_CTRL_REG, PCR_RSA_MEM_PD); + REG_CLR_BIT(PCR_RSA_PD_CTRL_REG, PCR_RSA_MEM_FORCE_PD); +} + +static inline void mpi_ll_power_down(void) +{ + /* Power down the MPI peripheral */ + REG_CLR_BIT(PCR_RSA_PD_CTRL_REG, PCR_RSA_MEM_FORCE_PU); + REG_SET_BIT(PCR_RSA_PD_CTRL_REG, PCR_RSA_MEM_PD); +} + +static inline void mpi_ll_enable_interrupt(void) +{ + REG_WRITE(RSA_INT_ENA_REG, 1); +} + +static inline void mpi_ll_disable_interrupt(void) +{ + REG_WRITE(RSA_INT_ENA_REG, 0); +} + +static inline void mpi_ll_clear_interrupt(void) +{ + REG_WRITE(RSA_INT_CLR_REG, 1); +} + +static inline bool mpi_ll_check_memory_init_complete(void) +{ + return REG_READ(RSA_QUERY_CLEAN_REG) == 0; +} + +static inline void mpi_ll_start_op(mpi_op_t op) +{ + REG_WRITE(MPI_OPERATIONS_REG[op], 1); +} + +static inline bool mpi_ll_get_int_status(void) +{ + return REG_READ(RSA_QUERY_IDLE_REG) == 0; +} + +/* Copy MPI bignum (p) to hardware memory block at 'mem_base'. + + If num_words is higher than the number of words (n) in the bignum then + these additional words will be zeroed in the memory buffer. +*/ +static inline void mpi_ll_write_to_mem_block(mpi_param_t param, size_t offset, const uint32_t* p, size_t n, size_t num_words) +{ + uint32_t mem_base = MPI_BLOCK_BASES[param] + offset; + uint32_t* pbase = (uint32_t*) mem_base; + uint32_t copy_words = MIN(num_words, n); + + /* Copy MPI data to memory block registers */ + for (int i = 0; i < copy_words; i++) { + pbase[i] = p[i]; + } + + /* Zero any remaining memory block data */ + for (int i = copy_words; i < num_words; i++) { + pbase[i] = 0; + } +} + +static inline void mpi_ll_write_m_prime(uint32_t Mprime) +{ + REG_WRITE(RSA_M_PRIME_REG, Mprime); +} + +static inline void mpi_ll_write_rinv(uint32_t rinv) +{ + REG_WRITE(MPI_BLOCK_BASES[MPI_PARAM_Z], rinv); +} + +static inline void mpi_ll_write_at_offset(mpi_param_t param, int offset, uint32_t value) +{ + uint32_t mem_base = MPI_BLOCK_BASES[param] + offset; + REG_WRITE(mem_base, value); +} + +/* Read MPI bignum (p) back from hardware memory block. + + Reads z_words words from block. +*/ +static inline void mpi_ll_read_from_mem_block(uint32_t* p, size_t n, size_t num_words) +{ + uint32_t mem_base = MPI_BLOCK_BASES[MPI_PARAM_Z]; + /* Copy data from memory block registers */ + const size_t REG_WIDTH = sizeof(uint32_t); + for (size_t i = 0; i < num_words; i++) { + p[i] = REG_READ(mem_base + (i * REG_WIDTH)); + } + /* Zero any remaining limbs in the bignum, if the buffer is bigger + than num_words */ + for (size_t i = num_words; i < n; i++) { + p[i] = 0; + } +} + +static inline void mpi_ll_set_mode(size_t length) +{ + REG_WRITE(RSA_MODE_REG, length); +} + +static inline void mpi_ll_disable_constant_time(void) +{ + REG_WRITE(RSA_CONSTANT_TIME_REG, 0); +} + +static inline void mpi_ll_enable_constant_time(void) +{ + REG_WRITE(RSA_CONSTANT_TIME_REG, 1); +} + +static inline void mpi_ll_disable_search(void) +{ + REG_WRITE(RSA_SEARCH_ENABLE_REG, 0); +} + +static inline void mpi_ll_enable_search(void) +{ + REG_WRITE(RSA_SEARCH_ENABLE_REG, 1); +} + +static inline void mpi_ll_set_search_position(size_t pos) +{ + REG_WRITE(RSA_SEARCH_POS_REG, pos); +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32h21/include/hal/spi_flash_encrypted_ll.h b/components/hal/esp32h21/include/hal/spi_flash_encrypted_ll.h index 24df42b49f46..340363bcde05 100644 --- a/components/hal/esp32h21/include/hal/spi_flash_encrypted_ll.h +++ b/components/hal/esp32h21/include/hal/spi_flash_encrypted_ll.h @@ -11,6 +11,7 @@ ******************************************************************************/ // The Lowlevel layer for SPI Flash Encryption. +#pragma once #include #include diff --git a/components/hal/esp32p4/include/hal/adc_ll.h b/components/hal/esp32p4/include/hal/adc_ll.h index 3b18c4d3f295..f0ee358b9f06 100644 --- a/components/hal/esp32p4/include/hal/adc_ll.h +++ b/components/hal/esp32p4/include/hal/adc_ll.h @@ -205,8 +205,8 @@ static inline void adc_ll_digi_set_convert_mode(adc_ll_digi_convert_mode_t mode) static inline void adc_ll_digi_controller_clk_div(uint32_t div_num, uint32_t div_b, uint32_t div_a) { HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl23, reg_adc_clk_div_num, div_num); - HP_SYS_CLKRST.peri_clk_ctrl23.reg_adc_clk_div_numerator = div_a; - HP_SYS_CLKRST.peri_clk_ctrl23.reg_adc_clk_div_denominator = div_b; + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl23, reg_adc_clk_div_numerator, div_a); + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl23, reg_adc_clk_div_denominator, div_b); } /** diff --git a/components/hal/esp32p4/include/hal/bitscrambler_ll.h b/components/hal/esp32p4/include/hal/bitscrambler_ll.h index 33c6276c9e32..647cd75a3f5c 100644 --- a/components/hal/esp32p4/include/hal/bitscrambler_ll.h +++ b/components/hal/esp32p4/include/hal/bitscrambler_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 */ @@ -22,6 +22,8 @@ extern "C" { #define BITSCRAMBLER_LL_GET_HW(num) (((num) == 0) ? (&BITSCRAMBLER) : NULL) +#define BITSCRAMBLER_LL_INST_LEN_WORDS 9 //length of one instruction in 32-bit words as defined by HW + /** * @brief Select peripheral BitScrambler is attached to * @@ -156,15 +158,16 @@ static inline void bitscrambler_ll_set_cond_mode(bitscrambler_dev_t *hw, bitscra } /** - * @brief Set prefetch mode + * @brief Enable prefetch mode * * @param hw BitScrambler hardware instance address. * @param dir Direction, BITSCRAMBLER_DIR_TX or BITSCRAMBLER_DIR_RX - * @param mode Mode to set + * @param en True to enable prefetch mode; false to disable */ -static inline void bitscrambler_ll_set_prefetch_mode(bitscrambler_dev_t *hw, bitscrambler_direction_t dir, bitscrambler_prefetch_mode_t mode) +static inline void bitscrambler_ll_enable_prefetch_on_reset(bitscrambler_dev_t *hw, bitscrambler_direction_t dir, bool en) { - hw->ctrl[dir].fetch_mode = mode; + // 0: means do prefetch on reset, 1: means no reset prefetch, user has to load the instruction manually in the assembly code + hw->ctrl[dir].fetch_mode = en ? 0 : 1; } /** @@ -212,7 +215,7 @@ static inline void bitscrambler_ll_set_halt_mode(bitscrambler_dev_t *hw, bitscra */ static inline void bitscrambler_ll_set_tailing_bits(bitscrambler_dev_t *hw, bitscrambler_direction_t dir, int bitcount) { - HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tailing_bits[dir], tailing_bits, bitcount); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tail_bits[dir], tailing_bits, bitcount); } /** @@ -260,7 +263,7 @@ static inline void bitscrambler_ll_set_state(bitscrambler_dev_t *hw, bitscramble * * @returns one of BITSCRAMBLER_STATE_* values */ -static inline bitscrambler_state_t bitscrambler_ll_current_state(bitscrambler_dev_t *hw, bitscrambler_direction_t dir) +static inline bitscrambler_state_t bitscrambler_ll_get_current_state(bitscrambler_dev_t *hw, bitscrambler_direction_t dir) { if (hw->state[dir].in_idle) { return BITSCRAMBLER_STATE_IDLE; @@ -301,6 +304,30 @@ static inline void _bitscrambler_ll_set_bus_clock_tx_enable(bool enable) HP_SYS_CLKRST.soc_clk_ctrl1.reg_bitscrambler_tx_sys_clk_en = enable; } +/** + * @brief Force power on the bitscrambler memory block, regardless of the outside PMU logic + */ +static inline void bitscrambler_ll_mem_force_power_on(void) +{ + // empty +} + +/** + * @brief Force power off the bitscrambler memory block, regardless of the outside PMU logic + */ +static inline void bitscrambler_ll_mem_force_power_off(void) +{ + // empty +} + +/** + * @brief Power control the bitscrambler memory block by the outside PMU logic + */ +static inline void bitscrambler_ll_mem_power_by_pmu(void) +{ + // empty +} + /** * @brief Reset the BitScrambler module */ diff --git a/components/hal/esp32p4/include/hal/brownout_ll.h b/components/hal/esp32p4/include/hal/brownout_ll.h index 9f13dde6af03..7f7a47de505c 100644 --- a/components/hal/esp32p4/include/hal/brownout_ll.h +++ b/components/hal/esp32p4/include/hal/brownout_ll.h @@ -102,6 +102,8 @@ static inline void brownout_ll_set_intr_wait_cycles(uint8_t cycle) * @brief Enable brown out interrupt * * @param enable true: enable, false: disable + * + * @note Avoid concurrency risky with vbat_ll_enable_intr_mask */ static inline void brownout_ll_intr_enable(bool enable) { @@ -127,7 +129,7 @@ static inline void brownout_ll_ana_reset_enable(bool enable) __attribute__((always_inline)) static inline void brownout_ll_intr_clear(void) { - LP_ANA_PERI.int_clr.bod_mode0_int_clr = 1; + LP_ANA_PERI.int_clr.val = BROWNOUT_DETECTOR_LL_INTERRUPT_MASK; } /** diff --git a/components/hal/esp32p4/include/hal/ecc_ll.h b/components/hal/esp32p4/include/hal/ecc_ll.h index 880df252462b..05a7ed8fcd0f 100644 --- a/components/hal/esp32p4/include/hal/ecc_ll.h +++ b/components/hal/esp32p4/include/hal/ecc_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -240,6 +240,12 @@ static inline void ecc_ll_read_param(ecc_ll_param_t param, uint8_t *buf, uint16_ memcpy(buf, (void *)reg, len); } +static inline void ecc_ll_enable_constant_time_point_mul(bool enable) +{ + // Not supported for ESP32-P4 + (void) enable; //unused +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32p4/include/hal/isp_ll.h b/components/hal/esp32p4/include/hal/isp_ll.h index 00712b12564c..528426309157 100644 --- a/components/hal/esp32p4/include/hal/isp_ll.h +++ b/components/hal/esp32p4/include/hal/isp_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 */ @@ -167,6 +167,14 @@ typedef enum { ISP_LL_LUT_DPC, ///< LUT for DPC } isp_ll_lut_t; +/** + * @brief ISP pipeline clock control mode + */ +typedef enum { + ISP_LL_PIPELINE_CLK_CTRL_AUTO, ///< HW control, off when in frame interval + ISP_LL_PIPELINE_CLK_CTRL_ALWAYS_ON, ///< Always on +} isp_ll_pipeline_clk_ctrl_t; + /*--------------------------------------------------------------- Clock @@ -495,14 +503,14 @@ static inline void isp_ll_set_bayer_mode(isp_dev_t *hw, color_raw_element_order_ AF ---------------------------------------------------------------*/ /** - * @brief Enable / Disable AF clock + * @brief Set AF clock control mode * * @param[in] hw - * @param[in] enable Enable / Disable + * @param[in] mode 'isp_ll_pipeline_clk_ctrl_t` */ -static inline void isp_ll_af_clk_enable(isp_dev_t *hw, bool enable) +static inline void isp_ll_af_set_clk_ctrl_mode(isp_dev_t *hw, isp_ll_pipeline_clk_ctrl_t mode) { - hw->clk_en.clk_af_force_on = enable; + hw->clk_en.clk_af_force_on = mode; } /** @@ -547,7 +555,7 @@ static inline void isp_ll_af_manual_update(isp_dev_t *hw) static inline void isp_ll_af_set_edge_thresh_mode(isp_dev_t *hw, isp_ll_af_edge_detector_mode_t mode) { if (mode == ISP_LL_AF_EDGE_DETECTOR_MODE_AUTO) { - hw->af_threshold.af_threshold = 0; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->af_threshold, af_threshold, 0); } } @@ -561,7 +569,7 @@ static inline void isp_ll_af_set_edge_thresh(isp_dev_t *hw, uint32_t thresh) { HAL_ASSERT(thresh != 0); - hw->af_threshold.af_threshold = thresh; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->af_threshold, af_threshold, thresh); } /** @@ -572,7 +580,7 @@ static inline void isp_ll_af_set_edge_thresh(isp_dev_t *hw, uint32_t thresh) */ static inline void isp_ll_af_set_auto_edge_thresh_pixel_num(isp_dev_t *hw, uint32_t pixel_num) { - HAL_ASSERT(hw->af_threshold.af_threshold == 0); + HAL_ASSERT(HAL_FORCE_READ_U32_REG_FIELD(hw->af_threshold, af_threshold) == 0); hw->af_ctrl1.af_thpixnum = pixel_num; } @@ -678,7 +686,7 @@ static inline uint32_t isp_ll_af_get_window_lum(isp_dev_t *hw, uint32_t window_i */ static inline void isp_ll_af_env_detector_set_period(isp_dev_t *hw, uint32_t period) { - hw->af_ctrl0.af_env_period = period; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->af_ctrl0, af_env_period, period); } /** @@ -730,14 +738,14 @@ static inline void isp_ll_af_env_detector_set_ratio(isp_dev_t *hw, uint32_t rati BF ---------------------------------------------------------------*/ /** - * @brief Enable / Disable BF clock + * @brief Set BF clock control mode * * @param[in] hw Hardware instance address - * @param[in] enable Enable / Disable + * @param[in] mode 'isp_ll_pipeline_clk_ctrl_t` */ -static inline void isp_ll_bf_clk_enable(isp_dev_t *hw, bool enable) +static inline void isp_ll_bf_set_clk_ctrl_mode(isp_dev_t *hw, isp_ll_pipeline_clk_ctrl_t mode) { - hw->clk_en.clk_bf_force_on = enable; + hw->clk_en.clk_bf_force_on = mode; } /** @@ -781,7 +789,7 @@ static inline void isp_ll_bf_set_padding_mode(isp_dev_t *hw, isp_bf_edge_padding */ static inline void isp_ll_bf_set_padding_data(isp_dev_t *hw, uint32_t padding_data) { - hw->bf_matrix_ctrl.bf_padding_data = padding_data; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->bf_matrix_ctrl, bf_padding_data, padding_data); } /** @@ -792,7 +800,7 @@ static inline void isp_ll_bf_set_padding_data(isp_dev_t *hw, uint32_t padding_da */ static inline void isp_ll_bf_set_padding_line_tail_valid_start_pixel(isp_dev_t *hw, uint32_t start_pixel) { - hw->bf_matrix_ctrl.bf_tail_pixen_pulse_tl = start_pixel; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->bf_matrix_ctrl, bf_tail_pixen_pulse_tl, start_pixel); } /** @@ -803,7 +811,7 @@ static inline void isp_ll_bf_set_padding_line_tail_valid_start_pixel(isp_dev_t * */ static inline void isp_ll_bf_set_padding_line_tail_valid_end_pixel(isp_dev_t *hw, uint32_t end_pixel) { - hw->bf_matrix_ctrl.bf_tail_pixen_pulse_th = end_pixel; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->bf_matrix_ctrl, bf_tail_pixen_pulse_th, end_pixel); } /** @@ -832,14 +840,14 @@ static inline void isp_ll_bf_set_template(isp_dev_t *hw, uint8_t template_arr[SO CCM ---------------------------------------------------------------*/ /** - * @brief Enable / Disable CCM clock + * @brief Set CCM clock control mode * * @param[in] hw Hardware instance address - * @param[in] enable Enable / Disable + * @param[in] mode 'isp_ll_pipeline_clk_ctrl_t` */ -static inline void isp_ll_ccm_clk_enable(isp_dev_t *hw, bool enable) +static inline void isp_ll_ccm_set_clk_ctrl_mode(isp_dev_t *hw, isp_ll_pipeline_clk_ctrl_t mode) { - hw->clk_en.clk_ccm_force_on = enable; + hw->clk_en.clk_ccm_force_on = mode; } /** @@ -876,14 +884,14 @@ static inline void isp_ll_ccm_set_matrix(isp_dev_t *hw, isp_ll_ccm_gain_t fixed_ Color ---------------------------------------------------------------*/ /** - * @brief Enable / Disable Color clock + * @brief Set Color clock control mode * * @param[in] hw Hardware instance address - * @param[in] enable Enable / Disable + * @param[in] mode 'isp_ll_pipeline_clk_ctrl_t` */ -static inline void isp_ll_color_clk_enable(isp_dev_t *hw, bool enable) +static inline void isp_ll_color_set_clk_ctrl_mode(isp_dev_t *hw, isp_ll_pipeline_clk_ctrl_t mode) { - hw->clk_en.clk_color_force_on = enable; + hw->clk_en.clk_color_force_on = mode; } /** @@ -1071,14 +1079,14 @@ static inline void isp_ll_cam_enable(isp_dev_t *hw, bool enable) ---------------------------------------------------------------*/ /** - * @brief Enable / Disable AE clock + * @brief Set AE clock control mode * * @param[in] hw Hardware instance address - * @param[in] enable Enable / Disable + * @param[in] mode 'isp_ll_pipeline_clk_ctrl_t` */ -static inline void isp_ll_ae_clk_enable(isp_dev_t *hw, bool enable) +static inline void isp_ll_ae_set_clk_ctrl_mode(isp_dev_t *hw, isp_ll_pipeline_clk_ctrl_t mode) { - hw->clk_en.clk_ae_force_on = enable; + hw->clk_en.clk_ae_force_on = mode; } /** @@ -1166,8 +1174,8 @@ static inline void isp_ll_ae_set_subwin_pixnum_recip(isp_dev_t *hw, int subwin_p */ static inline void isp_ll_ae_env_detector_set_thresh(isp_dev_t *hw, uint32_t low_thresh, uint32_t high_thresh) { - hw->ae_monitor.ae_monitor_tl = low_thresh; - hw->ae_monitor.ae_monitor_th = high_thresh; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->ae_monitor, ae_monitor_tl, low_thresh); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->ae_monitor, ae_monitor_th, high_thresh); } /** @@ -1185,14 +1193,14 @@ static inline void isp_ll_ae_env_detector_set_period(isp_dev_t *hw, uint32_t per LSC ---------------------------------------------------------------*/ /** - * @brief Enable / Disable LSC clock + * @brief Set LSC clock control mode * * @param[in] hw Hardware instance address - * @param[in] enable Enable / Disable + * @param[in] mode 'isp_ll_pipeline_clk_ctrl_t` */ -static inline void isp_ll_lsc_clk_enable(isp_dev_t *hw, bool enable) +static inline void isp_ll_lsc_set_clk_ctrl_mode(isp_dev_t *hw, isp_ll_pipeline_clk_ctrl_t mode) { - hw->clk_en.clk_lsc_force_on = enable; + hw->clk_en.clk_lsc_force_on = mode; } /** @@ -1337,14 +1345,14 @@ static inline void isp_ll_clear_intr(isp_dev_t *hw, uint32_t mask) AWB ---------------------------------------------------------------*/ /** - * @brief Enable / Disable AWB clock + * @brief Set AWB clock control mode * * @param[in] hw Hardware instance address - * @param[in] enable Enable / Disable + * @param[in] mode 'isp_ll_pipeline_clk_ctrl_t` */ -static inline void isp_ll_awb_clk_enable(isp_dev_t *hw, bool enable) +static inline void isp_ll_awb_set_clk_ctrl_mode(isp_dev_t *hw, isp_ll_pipeline_clk_ctrl_t mode) { - hw->clk_en.clk_awb_force_on = enable; + hw->clk_en.clk_awb_force_on = mode; } /** @@ -1495,14 +1503,14 @@ static inline uint32_t isp_ll_awb_get_accumulated_b_value(isp_dev_t *hw) Demosaic ---------------------------------------------------------------*/ /** - * @brief Enable / Disable demosaic clock + * @brief Set demosaic clock control mode * * @param[in] hw Hardware instance address - * @param[in] enable Enable / Disable + * @param[in] mode 'isp_ll_pipeline_clk_ctrl_t` */ -static inline void isp_ll_demosaic_clk_enable(isp_dev_t *hw, bool enable) +static inline void isp_ll_demosaic_set_clk_ctrl_mode(isp_dev_t *hw, isp_ll_pipeline_clk_ctrl_t mode) { - hw->clk_en.clk_demosaic_force_on = enable; + hw->clk_en.clk_demosaic_force_on = mode; } /** @@ -1549,7 +1557,7 @@ static inline void isp_ll_demosaic_set_padding_mode(isp_dev_t *hw, isp_demosaic_ __attribute__((always_inline)) static inline void isp_ll_demosaic_set_padding_data(isp_dev_t *hw, uint32_t padding_data) { - hw->demosaic_matrix_ctrl.demosaic_padding_data = padding_data; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->demosaic_matrix_ctrl, demosaic_padding_data, padding_data); } /** @@ -1561,7 +1569,7 @@ static inline void isp_ll_demosaic_set_padding_data(isp_dev_t *hw, uint32_t padd __attribute__((always_inline)) static inline void isp_ll_demosaic_set_padding_line_tail_valid_start_pixel(isp_dev_t *hw, uint32_t start_pixel) { - hw->demosaic_matrix_ctrl.demosaic_tail_pixen_pulse_tl = start_pixel; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->demosaic_matrix_ctrl, demosaic_tail_pixen_pulse_tl, start_pixel); } /** @@ -1573,21 +1581,21 @@ static inline void isp_ll_demosaic_set_padding_line_tail_valid_start_pixel(isp_d __attribute__((always_inline)) static inline void isp_ll_demosaic_set_padding_line_tail_valid_end_pixel(isp_dev_t *hw, uint32_t end_pixel) { - hw->demosaic_matrix_ctrl.demosaic_tail_pixen_pulse_th = end_pixel; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->demosaic_matrix_ctrl, demosaic_tail_pixen_pulse_th, end_pixel); } /*--------------------------------------------------------------- Sharpen ---------------------------------------------------------------*/ /** - * @brief Enable / Disable sharpen clock + * @brief Set sharpen clock control mode * * @param[in] hw Hardware instance address - * @param[in] enable Enable / Disable + * @param[in] mode 'isp_ll_pipeline_clk_ctrl_t` */ -static inline void isp_ll_sharp_clk_enable(isp_dev_t *hw, bool enable) +static inline void isp_ll_sharp_set_clk_ctrl_mode(isp_dev_t *hw, isp_ll_pipeline_clk_ctrl_t mode) { - hw->clk_en.clk_sharp_force_on = enable; + hw->clk_en.clk_sharp_force_on = mode; } /** @@ -1610,7 +1618,7 @@ static inline void isp_ll_sharp_enable(isp_dev_t *hw, bool enable) __attribute__((always_inline)) static inline void isp_ll_sharp_set_low_thresh(isp_dev_t *hw, uint8_t thresh) { - hw->sharp_ctrl0.sharp_threshold_low = thresh; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->sharp_ctrl0, sharp_threshold_low, thresh); } /** @@ -1622,7 +1630,7 @@ static inline void isp_ll_sharp_set_low_thresh(isp_dev_t *hw, uint8_t thresh) __attribute__((always_inline)) static inline void isp_ll_sharp_set_high_thresh(isp_dev_t *hw, uint8_t thresh) { - hw->sharp_ctrl0.sharp_threshold_high = thresh; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->sharp_ctrl0, sharp_threshold_high, thresh); } /** @@ -1635,7 +1643,7 @@ __attribute__((always_inline)) static inline void isp_ll_sharp_set_medium_freq_coeff(isp_dev_t *hw, isp_sharpen_m_freq_coeff coeff) { //val between `sharp_amount_low` and `sharp_threshold_high` will be multiplied by `sharp_amount_low` - hw->sharp_ctrl0.sharp_amount_low = coeff.val; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->sharp_ctrl0, sharp_amount_low, coeff.val); } /** @@ -1648,7 +1656,7 @@ __attribute__((always_inline)) static inline void isp_ll_sharp_set_high_freq_coeff(isp_dev_t *hw, isp_sharpen_h_freq_coeff_t coeff) { //val higher than `sharp_threshold_high` will be multiplied by `sharp_amount_high` - hw->sharp_ctrl0.sharp_amount_high = coeff.val; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->sharp_ctrl0, sharp_amount_high, coeff.val); } /** @@ -1672,7 +1680,7 @@ static inline void isp_ll_sharp_set_padding_mode(isp_dev_t *hw, isp_sharpen_edge __attribute__((always_inline)) static inline void isp_ll_sharp_set_padding_data(isp_dev_t *hw, uint32_t padding_data) { - hw->sharp_matrix_ctrl.sharp_padding_data = padding_data; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->sharp_matrix_ctrl, sharp_padding_data, padding_data); } /** @@ -1684,7 +1692,7 @@ static inline void isp_ll_sharp_set_padding_data(isp_dev_t *hw, uint32_t padding __attribute__((always_inline)) static inline void isp_ll_sharp_set_padding_line_tail_valid_start_pixel(isp_dev_t *hw, uint32_t start_pixel) { - hw->sharp_matrix_ctrl.sharp_tail_pixen_pulse_tl = start_pixel; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->sharp_matrix_ctrl, sharp_tail_pixen_pulse_tl, start_pixel); } /** @@ -1696,7 +1704,7 @@ static inline void isp_ll_sharp_set_padding_line_tail_valid_start_pixel(isp_dev_ __attribute__((always_inline)) static inline void isp_ll_sharp_set_padding_line_tail_valid_end_pixel(isp_dev_t *hw, uint32_t end_pixel) { - hw->sharp_matrix_ctrl.sharp_tail_pixen_pulse_th = end_pixel; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->sharp_matrix_ctrl, sharp_tail_pixen_pulse_th, end_pixel); } /** @@ -1733,32 +1741,32 @@ static inline void isp_ll_sharp_set_template(isp_dev_t *hw, uint8_t template_arr __attribute__((always_inline)) static inline uint8_t isp_ll_sharp_get_high_freq_pixel_max(isp_dev_t *hw) { - return hw->sharp_ctrl1.sharp_gradient_max; + return HAL_FORCE_READ_U32_REG_FIELD(hw->sharp_ctrl1, sharp_gradient_max); } /*--------------------------------------------------------------- RGB/YUV ---------------------------------------------------------------*/ /** - * @brief Enable / Disable rgb2yuv clock + * @brief Set rgb2yuv clock control mode * * @param[in] hw Hardware instance address - * @param[in] enable 0: hw control; 1: always on + * @param[in] mode 'isp_ll_pipeline_clk_ctrl_t` */ -static inline void isp_ll_rgb2yuv_clk_enable(isp_dev_t *hw, bool enable) +static inline void isp_ll_rgb2yuv_set_clk_ctrl_mode(isp_dev_t *hw, isp_ll_pipeline_clk_ctrl_t mode) { - hw->clk_en.clk_rgb2yuv_force_on = enable; + hw->clk_en.clk_rgb2yuv_force_on = mode; } /** - * @brief Enable / Disable yuv2rgb clock + * @brief Set yuv2rgb clock control mode * * @param[in] hw Hardware instance address - * @param[in] enable 0: hw control; 1: always on + * @param[in] mode 'isp_ll_pipeline_clk_ctrl_t` */ -static inline void isp_ll_yuv2rgb_clk_enable(isp_dev_t *hw, bool enable) +static inline void isp_ll_yuv2rgb_set_clk_ctrl_mode(isp_dev_t *hw, isp_ll_pipeline_clk_ctrl_t mode) { - hw->clk_en.clk_yuv2rgb_force_on = enable; + hw->clk_en.clk_yuv2rgb_force_on = mode; } /** @@ -1868,14 +1876,14 @@ static inline void isp_ll_gamma_set_correction_curve(isp_dev_t *hw, color_compon HIST ---------------------------------------------------------------*/ /** - * @brief enable histogram clock + * @brief Set histogram clock control mode * * @param[in] hw Hardware instance address - * @param[in] enable true: enable the clock. false: disable the clock + * @param[in] mode 'isp_ll_pipeline_clk_ctrl_t` */ -static inline void isp_ll_hist_clk_enable(isp_dev_t *hw, bool enable) +static inline void isp_ll_hist_set_clk_ctrl_mode(isp_dev_t *hw, isp_ll_pipeline_clk_ctrl_t mode) { - hw->clk_en.clk_hist_force_on = enable; + hw->clk_en.clk_hist_force_on = mode; } /** diff --git a/components/hal/esp32p4/include/hal/lp_i2s_ll.h b/components/hal/esp32p4/include/hal/lp_i2s_ll.h index 23e81cd2a5f2..ed6851a58c9b 100644 --- a/components/hal/esp32p4/include/hal/lp_i2s_ll.h +++ b/components/hal/esp32p4/include/hal/lp_i2s_ll.h @@ -114,7 +114,7 @@ static inline void lp_i2s_ll_enable_mem(int id, bool en) static inline void lp_i2s_ll_set_rx_mem_threshold(lp_i2s_dev_t *hw, uint32_t words) { - LP_I2S.rx_mem_conf.rx_mem_threshold = words; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->rx_mem_conf, rx_mem_threshold, words); } /*--------------------------------------------------------------- @@ -785,7 +785,7 @@ static inline void lp_vad_ll_set_speak_activity_thresh(lp_i2s_dev_t *hw, int thr */ static inline void lp_vad_ll_set_non_speak_activity_thresh(lp_i2s_dev_t *hw, int thresh) { - hw->vad_param1.param_hangover_silent = thresh; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->vad_param1, param_hangover_silent, thresh); } /** diff --git a/components/hal/esp32p4/include/hal/parlio_ll.h b/components/hal/esp32p4/include/hal/parlio_ll.h index 2ca418cb596f..eca2b83689c0 100644 --- a/components/hal/esp32p4/include/hal/parlio_ll.h +++ b/components/hal/esp32p4/include/hal/parlio_ll.h @@ -427,6 +427,7 @@ static inline uint32_t parlio_ll_rx_get_fifo_cycle_cnt(parl_io_dev_t *dev) * @param dev Parallel IO register base address * @param src Clock source */ +__attribute__((always_inline)) static inline void _parlio_ll_tx_set_clock_source(parl_io_dev_t *dev, parlio_clock_source_t src) { (void)dev; diff --git a/components/hal/esp32p4/include/hal/rmt_ll.h b/components/hal/esp32p4/include/hal/rmt_ll.h index 105aa426925e..59e04d3ad797 100644 --- a/components/hal/esp32p4/include/hal/rmt_ll.h +++ b/components/hal/esp32p4/include/hal/rmt_ll.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 */ @@ -37,6 +37,11 @@ extern "C" { #define RMT_LL_MAX_FILTER_VALUE 255 #define RMT_LL_MAX_IDLE_VALUE 32767 +// Maximum values due to limited register bit width +#define RMT_LL_CHANNEL_CLOCK_MAX_PRESCALE 256 +#define RMT_LL_GROUP_CLOCK_MAX_INTEGER_PRESCALE 256 +#define RMT_LL_GROUP_CLOCK_MAX_FRACTAL_PRESCALE 64 + typedef enum { RMT_LL_MEM_OWNER_SW = 0, RMT_LL_MEM_OWNER_HW = 1, diff --git a/components/hal/esp32p4/include/hal/spi_flash_encrypted_ll.h b/components/hal/esp32p4/include/hal/spi_flash_encrypted_ll.h index 9c3304832bf9..948e964db3d3 100644 --- a/components/hal/esp32p4/include/hal/spi_flash_encrypted_ll.h +++ b/components/hal/esp32p4/include/hal/spi_flash_encrypted_ll.h @@ -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 */ @@ -11,6 +11,7 @@ ******************************************************************************/ // The Lowlevel layer for SPI Flash Encryption. +#pragma once #include #include @@ -24,7 +25,7 @@ extern "C" { #endif -/// Choose type of chip you want to encrypt manully +/// Choose type of chip you want to encrypt manually typedef enum { FLASH_ENCRYPTION_MANU = 0, ///!< Manually encrypt the flash chip. @@ -51,7 +52,7 @@ static inline void spi_flash_encrypt_ll_disable(void) } /** - * Choose type of chip you want to encrypt manully + * Choose type of chip you want to encrypt manually * * @param type The type of chip to be encrypted * diff --git a/components/hal/esp32p4/include/hal/spi_ll.h b/components/hal/esp32p4/include/hal/spi_ll.h index 2b7211f4d60d..5adb3c375065 100644 --- a/components/hal/esp32p4/include/hal/spi_ll.h +++ b/components/hal/esp32p4/include/hal/spi_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 */ @@ -215,11 +215,11 @@ __attribute__((always_inline)) static inline void spi_ll_clk_source_pre_div(spi_dev_t *hw, uint8_t hs_div, uint8_t mst_div) { if (hw == &GPSPI2) { - HP_SYS_CLKRST.peri_clk_ctrl116.reg_gpspi2_hs_clk_div_num = hs_div - 1; - HP_SYS_CLKRST.peri_clk_ctrl116.reg_gpspi2_mst_clk_div_num = mst_div - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl116, reg_gpspi2_hs_clk_div_num, hs_div - 1); + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl116, reg_gpspi2_mst_clk_div_num, mst_div - 1); } else if (hw == &GPSPI3) { - HP_SYS_CLKRST.peri_clk_ctrl117.reg_gpspi3_hs_clk_div_num = hs_div - 1; - HP_SYS_CLKRST.peri_clk_ctrl117.reg_gpspi3_mst_clk_div_num = mst_div - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl117, reg_gpspi3_hs_clk_div_num, hs_div - 1); + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl117, reg_gpspi3_mst_clk_div_num, mst_div - 1); } } diff --git a/components/hal/esp32p4/include/hal/touch_sensor_ll.h b/components/hal/esp32p4/include/hal/touch_sensor_ll.h index f7d34bb56a2b..76639412b9ec 100644 --- a/components/hal/esp32p4/include/hal/touch_sensor_ll.h +++ b/components/hal/esp32p4/include/hal/touch_sensor_ll.h @@ -408,7 +408,7 @@ static inline void touch_ll_read_chan_data(uint32_t touch_num, uint8_t sample_cf LP_ANA_PERI.touch_mux0.touch_freq_sel = sample_cfg_id; LP_ANA_PERI.touch_mux0.touch_data_sel = type; // Channel shift workaround - *data = LP_TOUCH.chn_data[touch_num + 1].pad_data; + *data = HAL_FORCE_READ_U32_REG_FIELD(LP_TOUCH.chn_data[touch_num + 1], pad_data); } /** @@ -564,7 +564,7 @@ static inline uint32_t touch_ll_get_intr_status_mask(void) static inline void touch_ll_set_timeout(uint32_t timeout_cycles) { if (timeout_cycles) { - LP_ANA_PERI.touch_scan_ctrl2.touch_timeout_num = timeout_cycles; + HAL_FORCE_MODIFY_U32_REG_FIELD(LP_ANA_PERI.touch_scan_ctrl2, touch_timeout_num, timeout_cycles); LP_ANA_PERI.touch_scan_ctrl2.touch_timeout_en = 1; } else { LP_ANA_PERI.touch_scan_ctrl2.touch_timeout_en = 0; @@ -847,7 +847,7 @@ static inline void touch_ll_set_proximity_sensing_channel(uint8_t prox_chan, uin */ static inline void touch_ll_proximity_set_total_scan_times(uint32_t scan_times) { - LP_ANA_PERI.touch_filter1.touch_approach_limit = scan_times; + HAL_FORCE_MODIFY_U32_REG_FIELD(LP_ANA_PERI.touch_filter1, touch_approach_limit, scan_times); } /** diff --git a/components/hal/esp32p4/include/hal/vbat_ll.h b/components/hal/esp32p4/include/hal/vbat_ll.h new file mode 100644 index 000000000000..be742e38ae5e --- /dev/null +++ b/components/hal/esp32p4/include/hal/vbat_ll.h @@ -0,0 +1,162 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/******************************************************************************* + * NOTICE + * The ll is not public api, don't use in application code. + * See readme.md in hal/readme.md + ******************************************************************************/ + +#pragma once + +#include +#include "esp_bit_defs.h" +#include "soc/lp_analog_peri_struct.h" +#include "hal/regi2c_ctrl.h" +#include "soc/regi2c_brownout.h" + + +typedef enum { + VBAT_LL_CHARGER_UPVOLTAGE_INTR = BIT(27), + VBAT_LL_CHARGER_UNDERVOLTAGE_INTR = BIT(28), + VBAT_LL_BROWNOUT_INTR = BIT(30), +} vbat_ll_intr_t; + +#define VBAT_LL_CHARGER_MASK (BIT(27)|BIT(28)) +#define VBAT_LL_DETECT_MASK (BIT(30)) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Set vbat brownout threshold voltage + * + * @param threshold vbat brownout threshold + */ +static inline void vbat_ll_set_brownout_threshold(uint8_t threshold) +{ + // Give same value + REGI2C_WRITE_MASK(I2C_BOD, I2C_BIAS_OR_DREF_VBAT_L, threshold); + REGI2C_WRITE_MASK(I2C_BOD, I2C_BIAS_OR_DREF_VBAT_H, threshold); +} + +/** + * @brief Set vbat charge threshold voltage + * + * @param threshold vbat charge threshold + */ +static inline void vbat_ll_set_charger_threshold(uint8_t threshold_l, uint8_t threshold_h) +{ + REGI2C_WRITE_MASK(I2C_BOD, I2C_BIAS_OR_DREF_VBAT_CHARGER_L, threshold_l); + REGI2C_WRITE_MASK(I2C_BOD, I2C_BIAS_OR_DREF_VBAT_CHARGER_H, threshold_h); +} + +/** + * @brief Enable or disable the VBAT charger comparator + * + * @param enable Set to `true` to enable the comparator, or `false` to disable it. + */ +static inline void vbat_ll_enable_charger_comparator(bool enable) +{ + REGI2C_WRITE_MASK(I2C_BOD, I2C_BIAS_OR_FORCE_PU_VBAT_CHARGER, enable); +} + +/** + * @brief Set the under voltage filter time for the charger detector + * + * @param time_tick The filter time in ticks (unit depends on the hardware implementation). + */ +static inline void vbat_ll_set_undervoltage_filter_time(uint32_t time_tick) +{ + LP_ANA_PERI.vddbat_charge_cntl.vddbat_charge_undervoltage_target = time_tick; +} + +/** + * @brief Set the upvoltage filter time for the charger detector + * + * @param time_tick The filter time in ticks (unit depends on the hardware implementation). + */ +static inline void vbat_ll_set_upvoltage_filter_time(uint32_t time_tick) +{ + LP_ANA_PERI.vddbat_charge_cntl.vddbat_charge_upvoltage_target = time_tick; +} + +/** + * @brief Set the charger resistor value for VBAT charging + * + * @param resistor Resistor value to be set (unit depends on the hardware implementation). + */ +static inline void vbat_ll_set_charger_resistor(uint32_t resistor) +{ + REGI2C_WRITE_MASK(I2C_BOD, I2C_BIAS_OR_DRES_CHARGER, resistor); +} + +/* + * @brief Start or stop the VBAT battery charging process + * + * @param start Set to true to start charging, or false to stop charging. + */ +static inline void vbat_ll_start_battery_charge(bool start) +{ + LP_ANA_PERI.vddbat_bod_cntl.vddbat_charger = start; +} + +/** + * @brief Enable the interrupt mask for vbat usage + * + * @param mask A bitmask representing the interrupts to enable. + * Each bit corresponds to a specific interrupt source. + * @param enable true for enabling the interrupt, otherwise false. + * + * @note Avoid concurrency risky with brownout_ll_intr_enable + */ +static inline void vbat_ll_enable_intr_mask(uint32_t mask, bool enable) +{ + if (enable) { + LP_ANA_PERI.int_ena.val |= mask; + } else { + LP_ANA_PERI.int_ena.val &= ~mask; + } +} + +/** + * @brief Clear the interrupt mask for vbat usage + * + * @param mask A bitmask representing the interrupts to clear. + * Each bit corresponds to a specific interrupt source. + */ +static inline void vbat_ll_clear_intr_mask(uint32_t mask) +{ + LP_ANA_PERI.int_clr.val = mask; +} + +/** + * @brief Get the current interrupt mask for vbat usage + * + * @param intr_status Pointer to a variable where the interrupt status mask will be stored. + * The function will write the current interrupt status to this variable. + */ +static inline void vbat_ll_get_interrupt_status(uint32_t *intr_status) +{ + *intr_status = LP_ANA_PERI.int_st.val; +} + +/** + * @brief Clear the VBAT count for charge detection + * + * This function clears the internal counter that tracks the number of charge events detected + * related to the VBAT power supply. It is typically used to reset the count for monitoring purposes. + */ +static inline void vbat_ll_clear_count(void) +{ + LP_ANA_PERI.vddbat_charge_cntl.vddbat_charge_cnt_clr = 1; + LP_ANA_PERI.vddbat_charge_cntl.vddbat_charge_cnt_clr = 0; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32s2/include/hal/rmt_ll.h b/components/hal/esp32s2/include/hal/rmt_ll.h index 98eb39dfe054..729afa2a6ad3 100644 --- a/components/hal/esp32s2/include/hal/rmt_ll.h +++ b/components/hal/esp32s2/include/hal/rmt_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ diff --git a/components/hal/esp32s2/include/hal/spi_flash_encrypted_ll.h b/components/hal/esp32s2/include/hal/spi_flash_encrypted_ll.h index 529fb990076d..93e369d2fda6 100644 --- a/components/hal/esp32s2/include/hal/spi_flash_encrypted_ll.h +++ b/components/hal/esp32s2/include/hal/spi_flash_encrypted_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,6 +11,7 @@ ******************************************************************************/ // The Lowlevel layer for SPI Flash Encryption. +#pragma once #include #include @@ -24,7 +25,7 @@ extern "C" { #endif -/// Choose type of chip you want to encrypt manully +/// Choose type of chip you want to encrypt manually typedef enum { FLASH_ENCRYPTION_MANU = 0, ///!< Manually encrypt the flash chip. @@ -61,7 +62,7 @@ static inline void spi_flash_encrypt_ll_disable(void) } /** - * Choose type of chip you want to encrypt manully + * Choose type of chip you want to encrypt manually * * @param type The type of chip to be encrypted * diff --git a/components/hal/esp32s2/include/hal/touch_sensor_ll.h b/components/hal/esp32s2/include/hal/touch_sensor_ll.h index 78de4e8bff08..2ce086cc6f71 100644 --- a/components/hal/esp32s2/include/hal/touch_sensor_ll.h +++ b/components/hal/esp32s2/include/hal/touch_sensor_ll.h @@ -260,7 +260,7 @@ static inline void touch_ll_set_measure_interval_ticks(uint16_t interval_ticks) */ static inline void touch_ll_set_charge_speed(uint32_t touch_num, touch_charge_speed_t charge_speed) { - RTCIO.touch_pad[touch_num].dac = charge_speed; + RTCIO.touch_pad[touch_num].slope = charge_speed; } /** @@ -923,7 +923,7 @@ static inline void touch_ll_get_voltage_attenuation(touch_volt_atten_t *atten) */ static inline void touch_ll_set_slope(touch_pad_t touch_num, touch_cnt_slope_t slope) { - RTCIO.touch_pad[touch_num].dac = slope; + RTCIO.touch_pad[touch_num].slope = slope; } /** @@ -938,7 +938,7 @@ static inline void touch_ll_set_slope(touch_pad_t touch_num, touch_cnt_slope_t s */ static inline void touch_ll_get_slope(touch_pad_t touch_num, touch_cnt_slope_t *slope) { - *slope = (touch_cnt_slope_t)RTCIO.touch_pad[touch_num].dac; + *slope = (touch_cnt_slope_t)RTCIO.touch_pad[touch_num].slope; } /** @@ -1061,8 +1061,8 @@ static inline bool touch_ll_get_fsm_state(void) */ static inline void touch_ll_start_sw_meas(void) { - RTCCNTL.touch_ctrl2.touch_start_en = 0; RTCCNTL.touch_ctrl2.touch_start_en = 1; + RTCCNTL.touch_ctrl2.touch_start_en = 0; } /** diff --git a/components/hal/esp32s3/include/hal/psram_ctrlr_ll.h b/components/hal/esp32s3/include/hal/psram_ctrlr_ll.h index ff8245bdf749..ba9be84f77b7 100644 --- a/components/hal/esp32s3/include/hal/psram_ctrlr_ll.h +++ b/components/hal/esp32s3/include/hal/psram_ctrlr_ll.h @@ -109,7 +109,7 @@ static inline void psram_ctrlr_ll_set_rd_dummy(uint32_t mspi_id, uint32_t dummy_ * @param mspi_id mspi_id * @param read_mode read mode */ -static inline void psram_ctrlr_ll_set_read_mode(uint32_t mspi_id, psram_hal_cmd_mode_t read_mode) +static inline void psram_ctrlr_ll_set_read_mode(uint32_t mspi_id, psram_cmd_mode_t read_mode) { typeof (SPIMEM0.cache_sctrl) cache_sctrl; cache_sctrl.val = SPIMEM0.cache_sctrl.val; diff --git a/components/hal/esp32s3/include/hal/rmt_ll.h b/components/hal/esp32s3/include/hal/rmt_ll.h index e999add0260e..5923dbef8117 100644 --- a/components/hal/esp32s3/include/hal/rmt_ll.h +++ b/components/hal/esp32s3/include/hal/rmt_ll.h @@ -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 */ @@ -37,6 +37,11 @@ extern "C" { #define RMT_LL_MAX_FILTER_VALUE 255 #define RMT_LL_MAX_IDLE_VALUE 32767 +// Maximum values due to limited register bit width +#define RMT_LL_CHANNEL_CLOCK_MAX_PRESCALE 256 +#define RMT_LL_GROUP_CLOCK_MAX_INTEGER_PRESCALE 256 +#define RMT_LL_GROUP_CLOCK_MAX_FRACTAL_PRESCALE 64 + typedef enum { RMT_LL_MEM_OWNER_SW = 0, RMT_LL_MEM_OWNER_HW = 1, diff --git a/components/hal/esp32s3/include/hal/spi_flash_encrypted_ll.h b/components/hal/esp32s3/include/hal/spi_flash_encrypted_ll.h index dae3528dd9d0..d5b168c55e89 100644 --- a/components/hal/esp32s3/include/hal/spi_flash_encrypted_ll.h +++ b/components/hal/esp32s3/include/hal/spi_flash_encrypted_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,6 +11,7 @@ ******************************************************************************/ // The Lowlevel layer for SPI Flash Encryption. +#pragma once #include #include @@ -24,7 +25,7 @@ extern "C" { #endif -/// Choose type of chip you want to encrypt manully +/// Choose type of chip you want to encrypt manually typedef enum { FLASH_ENCRYPTION_MANU = 0, ///!< Manually encrypt the flash chip. @@ -51,7 +52,7 @@ static inline void spi_flash_encrypt_ll_disable(void) } /** - * Choose type of chip you want to encrypt manully + * Choose type of chip you want to encrypt manually * * @param type The type of chip to be encrypted * diff --git a/components/hal/esp32s3/include/hal/touch_sensor_ll.h b/components/hal/esp32s3/include/hal/touch_sensor_ll.h index 193950ee7068..d57129e5c0e7 100644 --- a/components/hal/esp32s3/include/hal/touch_sensor_ll.h +++ b/components/hal/esp32s3/include/hal/touch_sensor_ll.h @@ -1086,8 +1086,8 @@ static inline bool touch_ll_get_fsm_state(void) */ static inline void touch_ll_start_sw_meas(void) { - RTCCNTL.touch_ctrl2.touch_start_en = 0; RTCCNTL.touch_ctrl2.touch_start_en = 1; + RTCCNTL.touch_ctrl2.touch_start_en = 0; } /** diff --git a/components/hal/include/hal/bitscrambler_types.h b/components/hal/include/hal/bitscrambler_types.h index 25f0f8421bc4..56516fa14d7d 100644 --- a/components/hal/include/hal/bitscrambler_types.h +++ b/components/hal/include/hal/bitscrambler_types.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 */ @@ -44,14 +44,6 @@ typedef enum { BITSCRAMBLER_COND_MODE_NOTEQUAL = 1, /*!< Use "!=" to generate the condition */ } bitscrambler_cond_mode_t; -/** - * @brief Prefetch mode of bitscrambler - */ -typedef enum { - BITSCRAMBLER_PREFETCH_ENABLED = 0, /*!< Hardware prefetch is enabled */ - BITSCRAMBLER_PREFETCH_DISABLED = 1, /*!< Hardware prefetch is disabled, but the bitscrambler instructions can still do the prefetch */ -} bitscrambler_prefetch_mode_t; - /** * @brief Halt mode of bitscrambler */ diff --git a/components/hal/include/hal/ecc_hal.h b/components/hal/include/hal/ecc_hal.h index 4d9916e251ea..8f8b047903df 100644 --- a/components/hal/include/hal/ecc_hal.h +++ b/components/hal/include/hal/ecc_hal.h @@ -195,14 +195,12 @@ int ecc_hal_read_mod_op_result(uint8_t *r, uint16_t len); #endif /* SOC_ECC_EXTENDED_MODES_SUPPORTED */ -#ifdef SOC_ECC_CONSTANT_TIME_POINT_MUL /** * @brief Enable constant time multiplication operations * * @param true: enable; false: disable */ void ecc_hal_enable_constant_time_point_mul(bool enable); -#endif /* SOC_ECC_CONSTANT_TIME_POINT_MUL */ #ifdef __cplusplus } diff --git a/components/hal/include/hal/ecdsa_hal.h b/components/hal/include/hal/ecdsa_hal.h index 45c88b1fa754..699441037540 100644 --- a/components/hal/include/hal/ecdsa_hal.h +++ b/components/hal/include/hal/ecdsa_hal.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 */ diff --git a/components/hal/include/hal/psram_types.h b/components/hal/include/hal/psram_types.h index 586b6890604d..3d6fc9752c8f 100644 --- a/components/hal/include/hal/psram_types.h +++ b/components/hal/include/hal/psram_types.h @@ -18,7 +18,7 @@ extern "C" { typedef enum { PSRAM_HAL_CMD_QPI, /*!< Quad command for psram command */ PSRAM_HAL_CMD_SPI, /*!< SPI command for psram command */ -} psram_hal_cmd_mode_t; +} psram_cmd_mode_t; #ifdef __cplusplus } diff --git a/components/hal/include/hal/vbat_hal.h b/components/hal/include/hal/vbat_hal.h new file mode 100644 index 000000000000..e450ed712770 --- /dev/null +++ b/components/hal/include/hal/vbat_hal.h @@ -0,0 +1,37 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + uint32_t interrupt_mask; // interrupt mask. + uint16_t charger_resistor_value; // charger resistor value + bool enable_vbat_charger; // whether enable vbat charger comparator + uint8_t low_threshold; // low voltage threshold + uint8_t high_threshold; // high voltage threshold + uint8_t brownout_threshold; // brownout threshold + uint8_t undervoltage_filter_time; // under voltage filter time + uint8_t upvoltage_filter_time; // up voltage filter time +} vbat_hal_config_t; + +/** + * @brief Config vbat hal. + * + * @param cfg Pointer of vbat configuration structure. + */ +void vbat_hal_config(const vbat_hal_config_t *cfg); + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/spi_flash_encrypt_hal_iram.c b/components/hal/spi_flash_encrypt_hal_iram.c index 68a309a92d21..9feb151db58b 100644 --- a/components/hal/spi_flash_encrypt_hal_iram.c +++ b/components/hal/spi_flash_encrypt_hal_iram.c @@ -54,6 +54,8 @@ bool spi_flash_encryption_hal_check(uint32_t address, uint32_t length) #ifdef SOC_FLASH_ENCRYPTION_XTS_AES_SUPPORT_PSEUDO_ROUND void spi_flash_encryption_hal_enable_pseudo_rounds(uint8_t mode, uint8_t base, uint8_t increment, uint8_t key_rng_cnt) { - spi_flash_encrypt_ll_enable_pseudo_rounds(mode, base, increment, key_rng_cnt); + if (spi_flash_encrypt_ll_is_pseudo_rounds_function_supported()) { + spi_flash_encrypt_ll_enable_pseudo_rounds(mode, base, increment, key_rng_cnt); + } } #endif /* SOC_FLASH_ENCRYPTION_XTS_AES_SUPPORT_PSEUDO_ROUND */ 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 6869315c8856..433915e57546 100644 --- a/components/hal/test_apps/crypto/main/ecc/test_ecc.c +++ b/components/hal/test_apps/crypto/main/ecc/test_ecc.c @@ -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: CC0-1.0 */ @@ -87,9 +87,7 @@ static void ecc_point_mul(const uint8_t *k_le, const uint8_t *x_le, const uint8_ } else { ecc_hal_set_mode(ECC_MODE_POINT_MUL); } -#ifdef SOC_ECC_CONSTANT_TIME_POINT_MUL ecc_hal_enable_constant_time_point_mul(true); -#endif /* SOC_ECC_CONSTANT_TIME_POINT_MUL */ ecc_hal_start_calc(); while (!ecc_hal_is_calc_finished()) { @@ -167,6 +165,12 @@ TEST(ecc, ecc_point_multiplication_on_SECP192R1_and_SECP256R1) static void test_ecc_point_mul_inner_constant_time(void) { +#if CONFIG_IDF_TARGET_ESP32H2 + if (!ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 102)) { + TEST_IGNORE_MESSAGE("Skipping test, not supported on ESP32-H2 enable_vbat_charger); + if (cfg->enable_vbat_charger) { + uint8_t resistor_reg = (cfg->charger_resistor_value - 1000) / 500; + vbat_ll_set_charger_resistor(resistor_reg); + vbat_ll_set_charger_threshold(cfg->low_threshold, cfg->high_threshold); + vbat_ll_set_undervoltage_filter_time(cfg->undervoltage_filter_time); + vbat_ll_set_upvoltage_filter_time(cfg->upvoltage_filter_time); + } + vbat_ll_set_brownout_threshold(cfg->brownout_threshold); + vbat_ll_enable_intr_mask(cfg->interrupt_mask, true); +} diff --git a/components/heap/include/esp_heap_caps.h b/components/heap/include/esp_heap_caps.h index e875e4badd08..0229809c18fe 100644 --- a/components/heap/include/esp_heap_caps.h +++ b/components/heap/include/esp_heap_caps.h @@ -46,6 +46,7 @@ extern "C" { #define MALLOC_CAP_DMA_DESC_AHB (1<<17) ///< Memory must be capable of containing AHB DMA descriptors #define MALLOC_CAP_DMA_DESC_AXI (1<<18) ///< Memory must be capable of containing AXI DMA descriptors #define MALLOC_CAP_CACHE_ALIGNED (1<<19) ///< Memory must be aligned to the cache line size of any intermediate caches +#define MALLOC_CAP_SIMD (1<<20) ///< Memory must be capable of being used for SIMD instructions (i.e. allow for SIMD-specific-bit data accesses) #define MALLOC_CAP_INVALID (1<<31) ///< Memory can't be used / list end marker diff --git a/components/heap/port/esp32p4/memory_layout.c b/components/heap/port/esp32p4/memory_layout.c index 79357938c00b..dadd34a75560 100644 --- a/components/heap/port/esp32p4/memory_layout.c +++ b/components/heap/port/esp32p4/memory_layout.c @@ -44,6 +44,9 @@ enum { #define MALLOC_RTCRAM_BASE_CAPS ESP32P4_MEM_COMMON_CAPS | MALLOC_CAP_INTERNAL | MALLOC_CAP_EXEC #endif +// The memory used for SIMD instructions requires the bus of its memory regions be able to transfer the data in 128-bit +// TCM and RTCRAM memory regions cannot satisfy 128-bit data access + /** * Defined the attributes and allocation priority of each memory on the chip, * The heap allocator will traverse all types of memory types in column High Priority Matching and match the specified caps at first, @@ -51,11 +54,11 @@ enum { * in turn to continue matching. */ const soc_memory_type_desc_t soc_memory_types[SOC_MEMORY_TYPE_NUM] = { - /* Mem Type Name | High Priority Matching | Medium Priority Matching | Low Priority Matching */ - [SOC_MEMORY_TYPE_L2MEM] = { "RAM", { MALLOC_L2MEM_BASE_CAPS, 0, 0 }}, - [SOC_MEMORY_TYPE_SPIRAM] = { "SPIRAM", { MALLOC_CAP_SPIRAM, ESP32P4_MEM_COMMON_CAPS, 0 }}, - [SOC_MEMORY_TYPE_TCM] = { "TCM", { MALLOC_CAP_TCM, ESP32P4_MEM_COMMON_CAPS | MALLOC_CAP_INTERNAL, 0 }}, - [SOC_MEMORY_TYPE_RTCRAM] = { "RTCRAM", { MALLOC_CAP_RTCRAM, 0, MALLOC_RTCRAM_BASE_CAPS}}, + /* Mem Type Name | High Priority Matching | Medium Priority Matching | Low Priority Matching */ + [SOC_MEMORY_TYPE_L2MEM] = { "RAM", { MALLOC_L2MEM_BASE_CAPS | MALLOC_CAP_SIMD, 0, 0 }}, + [SOC_MEMORY_TYPE_SPIRAM] = { "SPIRAM", { MALLOC_CAP_SPIRAM, 0, ESP32P4_MEM_COMMON_CAPS | MALLOC_CAP_SIMD }}, + [SOC_MEMORY_TYPE_TCM] = { "TCM", { MALLOC_CAP_TCM, ESP32P4_MEM_COMMON_CAPS | MALLOC_CAP_INTERNAL, 0 }}, + [SOC_MEMORY_TYPE_RTCRAM] = { "RTCRAM", { MALLOC_CAP_RTCRAM, 0, MALLOC_RTCRAM_BASE_CAPS}}, }; const size_t soc_memory_type_count = sizeof(soc_memory_types) / sizeof(soc_memory_type_desc_t); diff --git a/components/heap/port/esp32s2/memory_layout.c b/components/heap/port/esp32s2/memory_layout.c index e64ebe80aaf9..6bd57135ce79 100644 --- a/components/heap/port/esp32s2/memory_layout.c +++ b/components/heap/port/esp32s2/memory_layout.c @@ -58,7 +58,7 @@ const soc_memory_type_desc_t soc_memory_types[] = { /* Mem Type Name | High Priority Matching | Medium Priority Matching | Low Priority Matching */ [SOC_MEMORY_TYPE_DIRAM] = { "RAM", { MALLOC_DIRAM_BASE_CAPS, 0, 0 }}, //TODO, in fact, part of them support EDMA, to be supported. - [SOC_MEMORY_TYPE_SPIRAM] = { "SPIRAM", { MALLOC_CAP_SPIRAM, ESP32S2_MEM_COMMON_CAPS, 0 }}, + [SOC_MEMORY_TYPE_SPIRAM] = { "SPIRAM", { MALLOC_CAP_SPIRAM, 0, ESP32S2_MEM_COMMON_CAPS }}, [SOC_MEMORY_TYPE_RTCRAM] = { "RTCRAM", { MALLOC_CAP_RTCRAM, 0, MALLOC_RTCRAM_BASE_CAPS }}, }; diff --git a/components/heap/port/esp32s3/memory_layout.c b/components/heap/port/esp32s3/memory_layout.c index b5a0a60a6bd9..2e07f63f28c9 100644 --- a/components/heap/port/esp32s3/memory_layout.c +++ b/components/heap/port/esp32s3/memory_layout.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -49,19 +49,21 @@ enum { #define MALLOC_RTCRAM_BASE_CAPS ESP32S3_MEM_COMMON_CAPS | MALLOC_CAP_INTERNAL | MALLOC_CAP_EXEC #endif +// The memory used for SIMD instructions requires the bus of its memory regions be able to transfer the data in 128-bit + /** * Defined the attributes and allocation priority of each memory on the chip, * The heap allocator will traverse all types of memory types in column High Priority Matching and match the specified caps at first, - * if no memory caps matched or the allocation is failed, it will go to columns Medium Priorty Matching and Low Priority Matching + * if no memory caps matched or the allocation is failed, it will go to columns Medium Priority Matching and Low Priority Matching * in turn to continue matching. */ const soc_memory_type_desc_t soc_memory_types[SOC_MEMORY_TYPE_NUM] = { -/* Mem Type Name | High Priority Matching | Medium Priorty Matching | Low Priority Matching */ - [SOC_MEMORY_TYPE_DIRAM] = { "RAM", { MALLOC_DIRAM_BASE_CAPS, 0, 0 }}, - [SOC_MEMORY_TYPE_DRAM] = { "DRAM", { 0, ESP32S3_MEM_COMMON_CAPS | MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA, 0 }}, - [SOC_MEMORY_TYPE_IRAM] = { "IRAM", { MALLOC_CAP_EXEC, MALLOC_CAP_32BIT | MALLOC_CAP_INTERNAL, 0 }}, - [SOC_MEMORY_TYPE_SPIRAM] = { "SPIRAM", { MALLOC_CAP_SPIRAM, ESP32S3_MEM_COMMON_CAPS, 0 }}, - [SOC_MEMORY_TYPE_RTCRAM] = { "RTCRAM", { MALLOC_CAP_RTCRAM, 0, MALLOC_RTCRAM_BASE_CAPS }}, +/* Mem Type Name | High Priority Matching | Medium Priority Matching | Low Priority Matching */ + [SOC_MEMORY_TYPE_DIRAM] = { "RAM", { MALLOC_DIRAM_BASE_CAPS | MALLOC_CAP_SIMD, 0, 0 }}, + [SOC_MEMORY_TYPE_DRAM] = { "DRAM", { 0, ESP32S3_MEM_COMMON_CAPS | MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA | MALLOC_CAP_SIMD, 0 }}, + [SOC_MEMORY_TYPE_IRAM] = { "IRAM", { MALLOC_CAP_EXEC, MALLOC_CAP_32BIT | MALLOC_CAP_INTERNAL, 0 }}, + [SOC_MEMORY_TYPE_SPIRAM] = { "SPIRAM", { MALLOC_CAP_SPIRAM, 0, ESP32S3_MEM_COMMON_CAPS | MALLOC_CAP_SIMD }}, + [SOC_MEMORY_TYPE_RTCRAM] = { "RTCRAM", { MALLOC_CAP_RTCRAM, 0, MALLOC_RTCRAM_BASE_CAPS }}, }; const size_t soc_memory_type_count = sizeof(soc_memory_types) / sizeof(soc_memory_type_desc_t); diff --git a/components/idf_test/include/esp32h21/.gitkeep b/components/idf_test/include/esp32h21/.gitkeep deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/components/idf_test/include/esp32h21/idf_performance_target.h b/components/idf_test/include/esp32h21/idf_performance_target.h new file mode 100644 index 000000000000..6645df749683 --- /dev/null +++ b/components/idf_test/include/esp32h21/idf_performance_target.h @@ -0,0 +1,9 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#define IDF_PERFORMANCE_MAX_ESP_TIMER_GET_TIME_PER_CALL 1900 diff --git a/components/ieee802154/driver/esp_ieee802154_dev.c b/components/ieee802154/driver/esp_ieee802154_dev.c index d7a1b4f26945..b252457ca78d 100644 --- a/components/ieee802154/driver/esp_ieee802154_dev.c +++ b/components/ieee802154/driver/esp_ieee802154_dev.c @@ -602,7 +602,7 @@ static IRAM_ATTR void isr_handle_tx_abort(ieee802154_ll_tx_abort_reason_t tx_abo NEEDS_NEXT_OPT(true); break; case IEEE802154_TX_ABORT_BY_TX_COEX_BREAK: -#if CONFIG_ESP_COEX_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE +#if (CONFIG_ESP_COEX_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE) esp_coex_ieee802154_coex_break_notify(); #endif IEEE802154_ASSERT(s_ieee802154_state == IEEE802154_STATE_TX || s_ieee802154_state == IEEE802154_STATE_TX_CCA); @@ -872,6 +872,7 @@ static inline esp_err_t ieee802154_transmit_internal(const uint8_t *frame, bool IEEE802154_SET_TXRX_PTI(IEEE802154_SCENE_TX); if (cca) { + ieee802154_ll_set_ed_duration(CCA_DETECTION_TIME); ieee802154_set_cmd(IEEE802154_CMD_CCA_TX_START); ieee802154_set_state(IEEE802154_STATE_TX_CCA); } else { @@ -921,6 +922,7 @@ esp_err_t ieee802154_transmit_at(const uint8_t *frame, bool cca, uint32_t time) tx_init(frame); IEEE802154_SET_TXRX_PTI(IEEE802154_SCENE_TX_AT); if (cca) { + ieee802154_ll_set_ed_duration(CCA_DETECTION_TIME); tx_target_time = time - IEEE802154_ED_TRIG_TX_RAMPUP_TIME_US; ieee802154_set_state(IEEE802154_STATE_TX_CCA); ieee802154_enter_critical(); diff --git a/components/lwip/apps/ping/ping_sock.c b/components/lwip/apps/ping/ping_sock.c index fc302cfa7330..827f01e15ee4 100644 --- a/components/lwip/apps/ping/ping_sock.c +++ b/components/lwip/apps/ping/ping_sock.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -7,6 +7,7 @@ #include #include #include +#include #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "lwip/opt.h" @@ -25,6 +26,33 @@ #include "ping/ping_sock.h" #include "esp_check.h" +#ifndef CONFIG_LWIP_NETIF_API +// If POSIX NETIF_API not enabled, we need to supply the implementation of if_indextoname() +// using tcpip_api_call() +#include "lwip/priv/tcpip_priv.h" + +struct tcpip_netif_name { + struct tcpip_api_call_data call; + u8_t ifindex; + char *ifname; +}; + +static err_t do_netif_index_to_name(struct tcpip_api_call_data *msg) +{ + struct tcpip_netif_name *params = __containerof(msg, struct tcpip_netif_name, call); + return netif_index_to_name(params->ifindex, params->ifname) ? ERR_OK : ERR_IF; +} + +char *if_indextoname(unsigned int ifindex, char *ifname) +{ + struct tcpip_netif_name params = { .ifindex = ifindex, .ifname = ifname }; + if (tcpip_api_call(do_netif_index_to_name, ¶ms.call) != ERR_OK) { + return NULL; + } + return ifname; +} +#endif // CONFIG_LWIP_NETIF_API == 0 + const static char *TAG = "ping_sock"; #define PING_TIME_DIFF_MS(_end, _start) ((uint32_t)(((_end).tv_sec - (_start).tv_sec) * 1000 + \ @@ -267,7 +295,7 @@ esp_err_t esp_ping_new_session(const esp_ping_config_t *config, const esp_ping_c /* set if index */ if(config->interface) { struct ifreq iface; - if(netif_index_to_name(config->interface, iface.ifr_name) == NULL) { + if (if_indextoname(config->interface, iface.ifr_name) == NULL) { ESP_LOGE(TAG, "fail to find interface name with netif index %" PRIu32, config->interface); goto err; } diff --git a/components/lwip/port/include/lwipopts.h b/components/lwip/port/include/lwipopts.h index 4eb38acea80d..3a7671472dc5 100644 --- a/components/lwip/port/include/lwipopts.h +++ b/components/lwip/port/include/lwipopts.h @@ -362,7 +362,7 @@ extern "C" { */ #define LWIP_HOOK_DHCP_POST_INIT(netif, result) \ (dhcp_ip_addr_restore(netif) ? ( dhcp_set_state(dhcp, DHCP_STATE_BOUND), \ - dhcp_network_changed(netif), \ + dhcp_network_changed_link_up(netif), \ (result) = ERR_OK , \ true ) : \ false) diff --git a/components/lwip/test_apps/main/CMakeLists.txt b/components/lwip/test_apps/main/CMakeLists.txt index bfd19d127786..012a9ca9e30c 100644 --- a/components/lwip/test_apps/main/CMakeLists.txt +++ b/components/lwip/test_apps/main/CMakeLists.txt @@ -1,4 +1,4 @@ idf_component_register(SRCS "lwip_test.c" REQUIRES test_utils INCLUDE_DIRS "." - PRIV_REQUIRES unity lwip test_utils) + PRIV_REQUIRES unity lwip test_utils nvs_flash) diff --git a/components/lwip/test_apps/sdkconfig.defaults b/components/lwip/test_apps/sdkconfig.defaults index 168e08d4cd4d..de762f8fe112 100644 --- a/components/lwip/test_apps/sdkconfig.defaults +++ b/components/lwip/test_apps/sdkconfig.defaults @@ -1,2 +1,5 @@ CONFIG_UNITY_ENABLE_FIXTURE=y CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=n + +# Added to enable compilation of DHCP last IP restore feature +CONFIG_LWIP_DHCP_RESTORE_LAST_IP=y diff --git a/components/mbedtls/Kconfig b/components/mbedtls/Kconfig index 77775423b494..7fd3d87ab6af 100644 --- a/components/mbedtls/Kconfig +++ b/components/mbedtls/Kconfig @@ -590,16 +590,16 @@ menu "mbedTLS" config MBEDTLS_HARDWARE_ECDSA_SIGN_MASKING_CM bool "Mask original ECDSA sign operation under dummy sign operations" select HAL_ECDSA_GEN_SIG_CM - # ToDo: IDF-11051 default y help - The ECDSA peripheral before ECO5 does not offer constant time ECDSA sign operation. + The ECDSA peripheral before ESP32-H2 v1.2 does not offer constant time ECDSA sign operation. This time can be observed through power profiling of the device, making the ECDSA private key vulnerable to side-channel timing attacks. This countermeasure masks the real ECDSA sign operation under dummy sign operations to add randomness in the generated power signature. It is highly recommended to also enable Secure Boot for the device in addition to this countermeasure so that only trusted software can execute on the device. + This countermeasure can be safely disabled for ESP32-H2 v1.2 and above. config MBEDTLS_HARDWARE_ECDSA_SIGN_CONSTANT_TIME_CM bool "Make ECDSA signature operation pseudo constant time for software" @@ -612,6 +612,7 @@ menu "mbedTLS" of an arbitrary message. The signature time would appear to be constant to the external entity after enabling this option. + This countermeasure can be safely disabled for ESP32-H2 v1.2 and above. endmenu diff --git a/components/mbedtls/port/ecc/esp_ecc.c b/components/mbedtls/port/ecc/esp_ecc.c index d6b0c6a6329e..436da6bb5193 100644 --- a/components/mbedtls/port/ecc/esp_ecc.c +++ b/components/mbedtls/port/ecc/esp_ecc.c @@ -45,14 +45,13 @@ int esp_ecc_point_multiply(const ecc_point_t *point, const uint8_t *scalar, ecc_ ecc_hal_write_mul_param(scalar, point->x, point->y, len); ecc_hal_set_mode(work_mode); -#ifdef SOC_ECC_CONSTANT_TIME_POINT_MUL - /* Enable constant-time point multiplication operations for the ECC hardware accelerator - This protects the ECC multiplication operation from timing attacks. - This increases the time taken (by almost 50%) for some point multiplication - operations performed by the ECC hardware accelerator. - */ + /* + * Enable constant-time point multiplication operations for the ECC hardware accelerator, + * if supported for the given target. This protects the ECC multiplication operation from + * timing attacks. This increases the time taken (by almost 50%) for some point + * multiplication operations performed by the ECC hardware accelerator. + */ ecc_hal_enable_constant_time_point_mul(true); -#endif /* SOC_ECC_CONSTANT_TIME_POINT_MUL */ ecc_hal_start_calc(); memset(result, 0, sizeof(ecc_point_t)); diff --git a/components/mbedtls/port/ecdsa/ecdsa_alt.c b/components/mbedtls/port/ecdsa/ecdsa_alt.c index 7dc3b8138ff9..7dd3e6d01e99 100644 --- a/components/mbedtls/port/ecdsa/ecdsa_alt.c +++ b/components/mbedtls/port/ecdsa/ecdsa_alt.c @@ -27,6 +27,8 @@ #if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_CONSTANT_TIME_CM #include "esp_timer.h" +#include "soc/chip_revision.h" +#include "hal/efuse_hal.h" #if CONFIG_ESP_CRYPTO_DPA_PROTECTION_LEVEL_HIGH /* @@ -362,9 +364,11 @@ static int esp_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi* r, mbedtls_mpi* s #endif ecdsa_hal_gen_signature(&conf, sha_le, r_le, s_le, len); #if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_CONSTANT_TIME_CM - sig_time = esp_timer_get_time() - sig_time; - if (sig_time < ECDSA_CM_FIXED_SIG_TIME) { - esp_rom_delay_us(ECDSA_CM_FIXED_SIG_TIME - sig_time); + if (!ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 102)) { + sig_time = esp_timer_get_time() - sig_time; + if (sig_time < ECDSA_CM_FIXED_SIG_TIME) { + esp_rom_delay_us(ECDSA_CM_FIXED_SIG_TIME - sig_time); + } } #endif process_again = !ecdsa_hal_get_operation_result() diff --git a/components/newlib/src/stdatomic.c b/components/newlib/src/stdatomic.c index f3d4ee2ebb21..428a800eca51 100644 --- a/components/newlib/src/stdatomic.c +++ b/components/newlib/src/stdatomic.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 */ @@ -32,6 +32,14 @@ ATOMIC_FUNCTIONS(1, unsigned char) ATOMIC_FUNCTIONS(2, short unsigned int) ATOMIC_FUNCTIONS(4, unsigned int) +#ifndef __clang__ +/* LLVM automatically replaces __atomic_test_and_set -> __atomic_exchange_1 call when compiling */ +bool __atomic_test_and_set(volatile void *ptr, int memorder) +{ + return __atomic_exchange_1(ptr, true, memorder); +} +#endif + #elif __riscv_atomic == 1 bool CLANG_ATOMIC_SUFFIX(__atomic_always_lock_free)(unsigned int size, const volatile void *) diff --git a/components/newlib/test_apps/newlib/main/test_stdatomic.c b/components/newlib/test_apps/newlib/main/test_stdatomic.c index 56d7db55a0f6..50c33846ba25 100644 --- a/components/newlib/test_apps/newlib/main/test_stdatomic.c +++ b/components/newlib/test_apps/newlib/main/test_stdatomic.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: Unlicense OR CC0-1.0 */ @@ -26,6 +26,19 @@ atomic_uint *g_atomic32; atomic_ushort *g_atomic16; atomic_uchar *g_atomic8; +TEST_CASE("stdatomic - test_atomic_flag", "[newlib_stdatomic]") +{ + bool x8 = 0; + g_atomic8 = heap_caps_calloc(sizeof(*g_atomic8), 1, MALLOC_CAP_DEFAULT); + + x8 = atomic_flag_test_and_set(g_atomic8); + TEST_ASSERT_EQUAL_HEX8(0x00, x8); + TEST_ASSERT_EQUAL_HEX8(0x01, *g_atomic8); + atomic_flag_clear(g_atomic8); + TEST_ASSERT_EQUAL_HEX8(0x00, *g_atomic8); + free(g_atomic8); +} + TEST_CASE("stdatomic - test_64bit_atomics", "[newlib_stdatomic]") { unsigned long long x64 = 0; @@ -262,7 +275,7 @@ TEST_CASE("stdatomic - test_" #NAME, "[newlib_stdatomic]") free(var_##NAME); \ } -// Note that the assert at the end is doing an excat bitwise comparison. +// Note that the assert at the end is doing an exact bitwise comparison. // This easily can fail due to rounding errors. However, there is currently // no corresponding Unity assert macro for long double. USE THIS WITH CARE! #define TEST_RACE_OPERATION_LONG_DOUBLE(NAME, LHSTYPE, PRE, POST, INIT, FINAL) \ diff --git a/components/openthread/include/esp_openthread_border_router.h b/components/openthread/include/esp_openthread_border_router.h index 8960fc861d58..6fe915bc5373 100644 --- a/components/openthread/include/esp_openthread_border_router.h +++ b/components/openthread/include/esp_openthread_border_router.h @@ -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 */ @@ -9,6 +9,7 @@ #include "esp_netif.h" #include "esp_netif_types.h" #include "esp_openthread.h" +#include "esp_openthread_spinel.h" #include "openthread/instance.h" #ifdef __cplusplus @@ -60,42 +61,6 @@ esp_err_t esp_openthread_border_router_deinit(void); */ esp_netif_t *esp_openthread_get_backbone_netif(void); -/** - * @brief Registers the callback for RCP failure. - * - */ -void esp_openthread_register_rcp_failure_handler(esp_openthread_rcp_failure_handler handler); - -/** - * @brief Registers the callback for spinel compatibility error. - * - * @note This function must be called before esp_openthread_init. - * - * @param[in] callback The callback. - * - */ -void esp_openthread_set_compatibility_error_callback(esp_openthread_compatibility_error_callback callback); - -/** - * @brief Deinitializes the connection to RCP. - * - * @return - * - ESP_OK on success - * - ESP_ERR_INVALID_STATE if fail to deinitialize RCP - * - */ -esp_err_t esp_openthread_rcp_deinit(void); - -/** - * @brief Initializes the connection to RCP. - * - * @return - * - ESP_OK on success - * - ESP_FAIL if fail to initialize RCP - * - */ -esp_err_t esp_openthread_rcp_init(void); - /** * @brief Sets the meshcop(e) instance name. * diff --git a/components/openthread/include/esp_openthread_spinel.h b/components/openthread/include/esp_openthread_spinel.h new file mode 100644 index 000000000000..70c74413e203 --- /dev/null +++ b/components/openthread/include/esp_openthread_spinel.h @@ -0,0 +1,71 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "sdkconfig.h" +#include "esp_openthread_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Registers the callback for RCP failure. + * + */ +void esp_openthread_register_rcp_failure_handler(esp_openthread_rcp_failure_handler handler); + +/** + * @brief Registers the callback for spinel compatibility error. + * + * @note This function should be called before esp_openthread_init. + * + * @param[in] callback The callback. + * + */ +void esp_openthread_set_compatibility_error_callback(esp_openthread_compatibility_error_callback callback); + +/** + * @brief Deinitializes the connection to RCP. + * + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_STATE if fail to deinitialize RCP + * + */ +esp_err_t esp_openthread_rcp_deinit(void); + +/** + * @brief Initializes the connection to RCP. + * + * @return + * - ESP_OK on success + * - ESP_FAIL if fail to initialize RCP + * + */ +esp_err_t esp_openthread_rcp_init(void); + +/** + * @brief Set the RCP version string. + * + * @note This function should be called before esp_openthread_init. When the RCP version string is not an empty string, + * compatibility checks will be performed during the initialization of the ESP OpenThread radio spinel. + * The `esp_openthread_compatibility_error_callback` will be triggered if the desired RCP version does not match + * the actual version running on the RCP. If needed, a NULL parameter can be passed to clear the version string. + * + * @param[in] version_str The pointer to RCP version string. + * + * @return + * - ESP_OK on success + * - ESP_FAIL if fail to set RCP version string + * + */ +esp_err_t esp_openthread_rcp_version_set(const char *version_str); + +#ifdef __cplusplus +} +#endif diff --git a/components/openthread/include/esp_openthread_types.h b/components/openthread/include/esp_openthread_types.h index ce1d258a3dce..df552ed1428e 100644 --- a/components/openthread/include/esp_openthread_types.h +++ b/components/openthread/include/esp_openthread_types.h @@ -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 */ @@ -198,8 +198,16 @@ typedef struct { esp_openthread_port_config_t port_config; /*!< The port configuration */ } esp_openthread_platform_config_t; +/** + * @brief The OpenThread rcp failure handler + * + */ typedef void (*esp_openthread_rcp_failure_handler)(void); +/** + * @brief The OpenThread compatibility error callback + * + */ typedef void (*esp_openthread_compatibility_error_callback)(void); #ifdef __cplusplus diff --git a/components/openthread/private_include/esp_openthread_radio.h b/components/openthread/private_include/esp_openthread_radio.h index f39dcb07c694..20e455668192 100644 --- a/components/openthread/private_include/esp_openthread_radio.h +++ b/components/openthread/private_include/esp_openthread_radio.h @@ -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 */ @@ -12,7 +12,7 @@ #include "esp_openthread_types.h" #include "openthread/instance.h" -#if !CONFIG_IEEE802154_TEST && (CONFIG_ESP_COEX_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE) +#if (CONFIG_ESP_COEX_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE) #include "esp_coex_i154.h" #endif @@ -58,7 +58,7 @@ void esp_openthread_radio_update(esp_openthread_mainloop_context_t *mainloop); esp_err_t esp_openthread_radio_process(otInstance *instance, const esp_openthread_mainloop_context_t *mainloop); -#if !CONFIG_IEEE802154_TEST && (CONFIG_ESP_COEX_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE) +#if (CONFIG_ESP_COEX_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE) /** * @brief Set the coexist config. 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 8be3cf6b80b7..4f3b1f7fd650 100644 --- a/components/openthread/private_include/openthread-core-esp32x-ftd-config.h +++ b/components/openthread/private_include/openthread-core-esp32x-ftd-config.h @@ -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 */ @@ -461,7 +461,7 @@ #define OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE 1 #endif -#if !CONFIG_OPENTHREAD_RADIO_NATIVE +#if (CONFIG_OPENTHREAD_RADIO_SPINEL_UART || CONFIG_OPENTHREAD_RADIO_SPINEL_SPI) /** * @def OPENTHREAD_SPINEL_CONFIG_COMPATIBILITY_ERROR_CALLBACK_ENABLE * @@ -494,17 +494,7 @@ #define OPENTHREAD_POSIX_CONFIG_RCP_TIME_SYNC_INTERVAL (60 * 1000 * 1000) #endif -#if !CONFIG_IEEE802154_TEST && (CONFIG_ESP_COEX_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE) -/** - * @def OPENTHREAD_SPINEL_CONFIG_VENDOR_HOOK_ENABLE - * - * Enables compilation of vendor specific code for Spinel - */ -#ifndef OPENTHREAD_SPINEL_CONFIG_VENDOR_HOOK_ENABLE -#define OPENTHREAD_SPINEL_CONFIG_VENDOR_HOOK_ENABLE 1 -#endif -#endif -#endif // !CONFIG_OPENTHREAD_RADIO_NATIVE +#endif // CONFIG_OPENTHREAD_RADIO_SPINEL_UART || CONFIG_OPENTHREAD_RADIO_SPINEL_SPI #if CONFIG_OPENTHREAD_LINK_METRICS /** diff --git a/components/openthread/src/ncp/esp_openthread_ncp.cpp b/components/openthread/src/ncp/esp_openthread_ncp.cpp index 4c80ef34f89c..c9ddd03e3ea2 100644 --- a/components/openthread/src/ncp/esp_openthread_ncp.cpp +++ b/components/openthread/src/ncp/esp_openthread_ncp.cpp @@ -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 */ @@ -9,7 +9,7 @@ #include "esp_openthread_ncp.h" #include "ncp_base.hpp" -#if !CONFIG_IEEE802154_TEST && (CONFIG_ESP_COEX_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE) +#if (CONFIG_ESP_COEX_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE) #include "esp_coex_i154.h" #endif @@ -70,7 +70,7 @@ otError NcpBase::VendorGetPropertyHandler(spinel_prop_key_t aPropKey) switch (aPropKey) { case SPINEL_PROP_VENDOR_ESP_COEX_EVENT: { -#if !CONFIG_IEEE802154_TEST && (CONFIG_ESP_COEX_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE) +#if (CONFIG_ESP_COEX_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE) esp_ieee802154_coex_config_t config = esp_ieee802154_get_coex_config(); const uint8_t *args = reinterpret_cast(&config); error = mEncoder.WriteDataWithLen(args, sizeof(esp_ieee802154_coex_config_t)); @@ -110,7 +110,7 @@ otError NcpBase::VendorSetPropertyHandler(spinel_prop_key_t aPropKey) break; } case SPINEL_PROP_VENDOR_ESP_COEX_EVENT: { -#if !CONFIG_IEEE802154_TEST && (CONFIG_ESP_COEX_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE) +#if (CONFIG_ESP_COEX_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE) const uint8_t *args = nullptr; uint16_t len = 0; mDecoder.ReadDataWithLen(args, len); diff --git a/components/openthread/src/port/esp_openthread_radio.c b/components/openthread/src/port/esp_openthread_radio.c index 7afe4172a02e..09de3a245293 100644 --- a/components/openthread/src/port/esp_openthread_radio.c +++ b/components/openthread/src/port/esp_openthread_radio.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 */ @@ -32,7 +32,7 @@ #include "utils/link_metrics.h" #include "utils/mac_frame.h" -#if !CONFIG_IEEE802154_TEST && (CONFIG_ESP_COEX_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE) +#if (CONFIG_ESP_COEX_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE) #include "esp_coex_i154.h" #endif @@ -815,7 +815,7 @@ uint32_t otPlatRadioGetSupportedChannelMask(otInstance *aInstance) return CONFIG_OPENTHREAD_SUPPORTED_CHANNEL_MASK; } -#if !CONFIG_IEEE802154_TEST && (CONFIG_ESP_COEX_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE) +#if (CONFIG_ESP_COEX_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE) void esp_openthread_set_coex_config(esp_ieee802154_coex_config_t config) { esp_ieee802154_set_coex_config(config); diff --git a/components/openthread/src/port/esp_openthread_radio_spinel.cpp b/components/openthread/src/port/esp_openthread_radio_spinel.cpp index 059e2bc02b0f..066bf8b5c66c 100644 --- a/components/openthread/src/port/esp_openthread_radio_spinel.cpp +++ b/components/openthread/src/port/esp_openthread_radio_spinel.cpp @@ -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 */ @@ -25,6 +25,9 @@ #include "openthread/platform/time.h" #include "platform/exit_code.h" #include "spinel_driver.hpp" +#include + +#define OT_SPINEL_RCP_VERSION_MAX_SIZE 100 using ot::Spinel::RadioSpinel; using esp::openthread::SpinelInterfaceAdapter; @@ -56,34 +59,7 @@ static const esp_openthread_radio_config_t *s_esp_openthread_radio_config = NULL static esp_openthread_compatibility_error_callback s_compatibility_error_callback = NULL; -#if !CONFIG_IEEE802154_TEST && (CONFIG_ESP_COEX_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE) - -#define SPINEL_PROP_VENDOR_ESP_COEX_EVENT (SPINEL_PROP_VENDOR_ESP__BEGIN + 3) - -static esp_ieee802154_coex_config_t s_coex_config = { - .idle = IEEE802154_IDLE, - .txrx = IEEE802154_LOW, - .txrx_at = IEEE802154_MIDDLE, -}; - -static void esp_openthread_restore_coex_config(void *context) -{ - esp_openthread_set_coex_config(s_coex_config); -} - -static esp_err_t esp_openthread_radio_spinel_coex_config_init(void) -{ - s_radio.SetVendorRestorePropertiesCallback(esp_openthread_restore_coex_config, esp_openthread_get_instance()); - esp_ieee802154_coex_config_t coex_config; - uint16_t coex_config_len = 0; - ESP_RETURN_ON_ERROR(s_radio.Get(SPINEL_PROP_VENDOR_ESP_COEX_EVENT, SPINEL_DATATYPE_DATA_WLEN_S, &coex_config, &coex_config_len), - OT_PLAT_LOG_TAG, "Fail to get coex config"); - ESP_RETURN_ON_FALSE(coex_config_len == sizeof(esp_ieee802154_coex_config_t), ESP_FAIL, OT_PLAT_LOG_TAG, - "Fail to get coex config"); - s_coex_config = coex_config; - return ESP_OK; -} -#endif +static char s_internal_rcp_version[OT_SPINEL_RCP_VERSION_MAX_SIZE] = {'\0'}; static void esp_openthread_radio_config_set(const esp_openthread_radio_config_t *config) { @@ -136,11 +112,18 @@ esp_err_t esp_openthread_radio_init(const esp_openthread_platform_config_t *conf "Spinel interface init failed"); #endif s_spinel_driver.Init(s_spinel_interface.GetSpinelInterface(), true, iidList, ot::Spinel::kSpinelHeaderMaxNumIid); + if (strlen(s_internal_rcp_version) > 0) { + const char *running_rcp_version = s_spinel_driver.GetVersion(); + if (strcmp(s_internal_rcp_version, running_rcp_version) != 0) { + if (s_compatibility_error_callback) { + s_compatibility_error_callback(); + } else { + ESP_LOGW(OT_PLAT_LOG_TAG, "The running rcp does not match the provided rcp"); + } + } + } s_radio.SetCompatibilityErrorCallback(ot_spinel_compatibility_error_callback, esp_openthread_get_instance()); s_radio.Init(/*skip_rcp_compatibility_check=*/false, /*reset_radio=*/true, &s_spinel_driver, s_radio_caps, /*RCP_time_sync=*/true); -#if !CONFIG_IEEE802154_TEST && (CONFIG_ESP_COEX_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE) - ESP_RETURN_ON_ERROR(esp_openthread_radio_spinel_coex_config_init(), OT_PLAT_LOG_TAG, "Coex config init failed"); -#endif #if CONFIG_OPENTHREAD_RADIO_SPINEL_SPI // CONFIG_OPENTHREAD_RADIO_SPINEL_SPI ESP_RETURN_ON_ERROR(s_spinel_interface.GetSpinelInterface().AfterRadioInit(), OT_PLAT_LOG_TAG, "Spinel interface init failed"); #endif @@ -185,12 +168,24 @@ esp_err_t esp_openthread_rcp_init(void) radiospinel_workflow); } +esp_err_t esp_openthread_rcp_version_set(const char *version_str) +{ + if (version_str == NULL) { + memset(s_internal_rcp_version, 0, OT_SPINEL_RCP_VERSION_MAX_SIZE); + return ESP_OK; + } + ESP_RETURN_ON_FALSE(strlen(version_str) > 0 && strlen(version_str) < OT_SPINEL_RCP_VERSION_MAX_SIZE, ESP_FAIL, OT_PLAT_LOG_TAG, "Invalid rcp version"); + strcpy(s_internal_rcp_version, version_str); + return ESP_OK; +} + void esp_openthread_radio_deinit(void) { s_radio.Deinit(); s_spinel_driver.Deinit(); s_spinel_interface.GetSpinelInterface().Disable(); esp_openthread_platform_workflow_unregister(radiospinel_workflow); + s_compatibility_error_callback = NULL; } esp_err_t esp_openthread_radio_process(otInstance *instance, const esp_openthread_mainloop_context_t *mainloop) @@ -515,39 +510,3 @@ uint32_t otPlatRadioGetSupportedChannelMask(otInstance *aInstance) // Refer to `GetRadioChannelMask(bool aPreferred)`: FALSE to get supported channel mask return s_radio.GetRadioChannelMask(false); } - -#if !CONFIG_IEEE802154_TEST && (CONFIG_ESP_COEX_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE) - -void esp_openthread_set_coex_config(esp_ieee802154_coex_config_t config) -{ - otError err = s_radio.Set(SPINEL_PROP_VENDOR_ESP_COEX_EVENT, SPINEL_DATATYPE_DATA_WLEN_S, &s_coex_config, sizeof(esp_ieee802154_coex_config_t)); - ESP_RETURN_ON_FALSE(err == OT_ERROR_NONE, , OT_PLAT_LOG_TAG, "Fail to set coex config"); - s_coex_config = config; -} - -esp_ieee802154_coex_config_t esp_openthread_get_coex_config(void) -{ - return s_coex_config; -} - -namespace ot { -namespace Spinel { - -otError RadioSpinel::VendorHandleValueIs(spinel_prop_key_t aPropKey) -{ - otError error = OT_ERROR_NONE; - - switch (aPropKey) - { - default: - ESP_LOGW(OT_PLAT_LOG_TAG, "Not Implemented!"); - error = OT_ERROR_NOT_FOUND; - break; - } - return error; -} - -} // namespace Spinel -} // namespace ot - -#endif diff --git a/components/openthread/src/port/esp_openthread_state.c b/components/openthread/src/port/esp_openthread_state.c index 98806154af9a..7dac89c3efa5 100644 --- a/components/openthread/src/port/esp_openthread_state.c +++ b/components/openthread/src/port/esp_openthread_state.c @@ -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 */ @@ -63,7 +63,7 @@ static void handle_ot_netdata_change(void) static void handle_ot_role_change(otInstance* instance) { -#if !CONFIG_IEEE802154_TEST && (CONFIG_ESP_COEX_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE) +#if ((CONFIG_ESP_COEX_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE) && OPENTHREAD_RADIO_NATIVE) otLinkModeConfig linkmode = otThreadGetLinkMode(instance); esp_ieee802154_coex_config_t config = esp_openthread_get_coex_config(); config.txrx = (linkmode.mRxOnWhenIdle) ? IEEE802154_LOW : IEEE802154_MIDDLE; @@ -83,14 +83,13 @@ static void handle_ot_role_change(otInstance* instance) otOperationalDataset dataset; ESP_GOTO_ON_FALSE(otDatasetGetActive(instance, &dataset) == OT_ERROR_NONE, ESP_FAIL, exit, TAG, "Failed to get the active dataset"); - ESP_GOTO_ON_ERROR(esp_event_post(OPENTHREAD_EVENT, OPENTHREAD_EVENT_ATTACHED, &dataset, sizeof(dataset), 0), - exit, TAG, "Failed to post OPENTHREAD_EVENT_ATTACHED. Err: %s", esp_err_to_name(ret)); + ret = esp_event_post(OPENTHREAD_EVENT, OPENTHREAD_EVENT_ATTACHED, &dataset, sizeof(dataset), 0); + ESP_GOTO_ON_ERROR(ret, exit, TAG, "Failed to post OPENTHREAD_EVENT_ATTACHED. Err: %s", esp_err_to_name(ret)); } } else if (role == OT_DEVICE_ROLE_DETACHED) { if (s_previous_role != OT_DEVICE_ROLE_DISABLED) { - ESP_GOTO_ON_ERROR( - esp_event_post(OPENTHREAD_EVENT, OPENTHREAD_EVENT_DETACHED, &s_previous_role, sizeof(s_previous_role), 0), - exit, TAG, "Failed to post OPENTHREAD_EVENT_DETACHED. Err: %s", esp_err_to_name(ret)); + ret = esp_event_post(OPENTHREAD_EVENT, OPENTHREAD_EVENT_DETACHED, &s_previous_role, sizeof(s_previous_role), 0); + ESP_GOTO_ON_ERROR(ret, exit, TAG, "Failed to post OPENTHREAD_EVENT_DETACHED. Err: %s", esp_err_to_name(ret)); } } exit: diff --git a/components/openthread/src/port/esp_spi_spinel_interface.cpp b/components/openthread/src/port/esp_spi_spinel_interface.cpp index 61d6cfab2fa1..3a4094916977 100644 --- a/components/openthread/src/port/esp_spi_spinel_interface.cpp +++ b/components/openthread/src/port/esp_spi_spinel_interface.cpp @@ -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 */ @@ -266,8 +266,8 @@ otError SpiSpinelInterface::WaitForFrame(uint64_t timeout_us) otError SpiSpinelInterface::HardwareReset(void) { if (mRcpFailureHandler) { - ConductSPITransaction(true, 0, 0); // clear mRcpFailureHandler(); + ConductSPITransaction(true, 0, 0); // clear } return OT_ERROR_NONE; } diff --git a/components/sdmmc/include/esp_private/sdmmc_common.h b/components/sdmmc/include/esp_private/sdmmc_common.h index 07096e6d6c01..ccf599ef4e54 100644 --- a/components/sdmmc/include/esp_private/sdmmc_common.h +++ b/components/sdmmc/include/esp_private/sdmmc_common.h @@ -28,7 +28,6 @@ #include "sys/param.h" #include "soc/soc_memory_layout.h" #include "soc/soc_caps.h" -#include "esp_dma_utils.h" #ifdef __cplusplus extern "C" { @@ -187,6 +186,12 @@ esp_err_t sdmmc_wait_for_idle(sdmmc_card_t* card, uint32_t status); #define SDMMC_IO_BLOCK_SIZE 512 esp_err_t sdmmc_allocate_aligned_buf(sdmmc_card_t* card); +/** + * For newly added host driver function pointers, + * use this function to check if they are correctly initialised. + */ +esp_err_t sdmmc_check_host_function_ptr_integrity(sdmmc_card_t *card); + #ifdef __cplusplus } #endif diff --git a/components/sdmmc/include/sd_protocol_types.h b/components/sdmmc/include/sd_protocol_types.h index 70cdf76d1221..66a5bfe499a4 100644 --- a/components/sdmmc/include/sd_protocol_types.h +++ b/components/sdmmc/include/sd_protocol_types.h @@ -242,6 +242,7 @@ typedef struct { void* dma_aligned_buffer; /*!< Leave it NULL. Reserved for cache aligned buffers for SDIO mode */ sd_pwr_ctrl_handle_t pwr_ctrl_handle; /*!< Power control handle */ esp_err_t (*get_dma_info)(int slot, esp_dma_mem_info_t *dma_mem_info); /*!< host function to dma memory information*/ + bool (*check_buffer_alignment)(int slot, const void *buf, size_t size); /*!< Check if buffer meets alignment requirements */ esp_err_t (*is_slot_set_to_uhs1)(int slot, bool *is_uhs1); /*!< host slot is set to uhs1 or not*/ } sdmmc_host_t; diff --git a/components/sdmmc/sdmmc_cmd.c b/components/sdmmc/sdmmc_cmd.c index 71f23ec756b6..a928dee6d2ec 100644 --- a/components/sdmmc/sdmmc_cmd.c +++ b/components/sdmmc/sdmmc_cmd.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 */ @@ -340,14 +340,13 @@ esp_err_t sdmmc_send_cmd_send_scr(sdmmc_card_t* card, sdmmc_scr_t *out_scr) { size_t datalen = 8; esp_err_t err = ESP_FAIL; - void *buf = NULL; - size_t actual_size = 0; - esp_dma_mem_info_t dma_mem_info; - card->host.get_dma_info(card->host.slot, &dma_mem_info); - err = esp_dma_capable_malloc(datalen, &dma_mem_info, &buf, &actual_size); - if (err != ESP_OK) { - return err; + + void *buf = heap_caps_malloc(datalen, MALLOC_CAP_DMA); + if (!buf) { + ESP_LOGE(TAG, "%s: not enough mem, err=0x%x", __func__, ESP_ERR_NO_MEM); + return ESP_ERR_NO_MEM; } + size_t actual_size = heap_caps_get_allocated_size(buf); sdmmc_command_t cmd = { .data = buf, @@ -412,14 +411,13 @@ esp_err_t sdmmc_send_cmd_num_of_written_blocks(sdmmc_card_t* card, size_t* out_n { size_t datalen = sizeof(uint32_t); esp_err_t err = ESP_OK; - void* buf = NULL; - esp_dma_mem_info_t dma_mem_info; - card->host.get_dma_info(card->host.slot, &dma_mem_info); - size_t actual_size = 0; - err = esp_dma_capable_malloc(datalen, &dma_mem_info, &buf, &actual_size); - if (err != ESP_OK) { - return err; + + void *buf = heap_caps_malloc(datalen, MALLOC_CAP_DMA); + if (!buf) { + ESP_LOGE(TAG, "%s: not enough mem, err=0x%x", __func__, ESP_ERR_NO_MEM); + return ESP_ERR_NO_MEM; } + size_t actual_size = heap_caps_get_allocated_size(buf); sdmmc_command_t cmd = { .data = buf, @@ -454,12 +452,9 @@ esp_err_t sdmmc_write_sectors(sdmmc_card_t* card, const void* src, esp_err_t err = ESP_OK; size_t block_size = card->csd.sector_size; - esp_dma_mem_info_t dma_mem_info; - card->host.get_dma_info(card->host.slot, &dma_mem_info); -#ifdef SOC_SDMMC_PSRAM_DMA_CAPABLE - dma_mem_info.extra_heap_caps |= MALLOC_CAP_SPIRAM; -#endif - if (esp_dma_is_buffer_alignment_satisfied(src, block_size * block_count, dma_mem_info) + bool is_aligned = card->host.check_buffer_alignment(card->host.slot, src, block_size * block_count); + + if (is_aligned #if !SOC_SDMMC_PSRAM_DMA_CAPABLE && !esp_ptr_external_ram(src) #endif @@ -471,13 +466,14 @@ esp_err_t sdmmc_write_sectors(sdmmc_card_t* card, const void* src, // DMA-capable buffer. void *tmp_buf = NULL; size_t actual_size = 0; - // Clear the SPIRAM flag. We don't want to force the allocation into SPIRAM, the allocator + // We don't want to force the allocation into SPIRAM, the allocator // will decide based on the buffer size and memory availability. - dma_mem_info.extra_heap_caps &= ~MALLOC_CAP_SPIRAM; - err = esp_dma_capable_malloc(block_size, &dma_mem_info, &tmp_buf, &actual_size); - if (err != ESP_OK) { - return err; + tmp_buf = heap_caps_malloc(block_size, MALLOC_CAP_DMA); + if (!tmp_buf) { + ESP_LOGE(TAG, "%s: not enough mem, err=0x%x", __func__, ESP_ERR_NO_MEM); + return ESP_ERR_NO_MEM; } + actual_size = heap_caps_get_allocated_size(tmp_buf); const uint8_t* cur_src = (const uint8_t*) src; for (size_t i = 0; i < block_count; ++i) { @@ -594,9 +590,9 @@ esp_err_t sdmmc_read_sectors(sdmmc_card_t* card, void* dst, esp_err_t err = ESP_OK; size_t block_size = card->csd.sector_size; - esp_dma_mem_info_t dma_mem_info; - card->host.get_dma_info(card->host.slot, &dma_mem_info); - if (esp_dma_is_buffer_alignment_satisfied(dst, block_size * block_count, dma_mem_info) + bool is_aligned = card->host.check_buffer_alignment(card->host.slot, dst, block_size * block_count); + + if (is_aligned #if !SOC_SDMMC_PSRAM_DMA_CAPABLE && !esp_ptr_external_ram(dst) #endif @@ -608,10 +604,13 @@ esp_err_t sdmmc_read_sectors(sdmmc_card_t* card, void* dst, // DMA-capable buffer. void *tmp_buf = NULL; size_t actual_size = 0; - err = esp_dma_capable_malloc(block_size, &dma_mem_info, &tmp_buf, &actual_size); - if (err != ESP_OK) { - return err; + tmp_buf = heap_caps_malloc(block_size, MALLOC_CAP_DMA); + if (!tmp_buf) { + ESP_LOGE(TAG, "%s: not enough mem, err=0x%x", __func__, ESP_ERR_NO_MEM); + return ESP_ERR_NO_MEM; } + actual_size = heap_caps_get_allocated_size(tmp_buf); + uint8_t* cur_dst = (uint8_t*) dst; for (size_t i = 0; i < block_count; ++i) { err = sdmmc_read_sectors_dma(card, tmp_buf, start_block + i, 1, actual_size); diff --git a/components/sdmmc/sdmmc_common.c b/components/sdmmc/sdmmc_common.c index 169a95dd9b6b..f2e6a9938868 100644 --- a/components/sdmmc/sdmmc_common.c +++ b/components/sdmmc/sdmmc_common.c @@ -395,20 +395,30 @@ esp_err_t sdmmc_allocate_aligned_buf(sdmmc_card_t* card) { if (card->host.flags & SDMMC_HOST_FLAG_ALLOC_ALIGNED_BUF) { void* buf = NULL; - size_t actual_size = 0; - esp_dma_mem_info_t dma_mem_info; - card->host.get_dma_info(card->host.slot, &dma_mem_info); - esp_err_t ret = esp_dma_capable_malloc(SDMMC_IO_BLOCK_SIZE, &dma_mem_info, &buf, &actual_size); - if (ret != ESP_OK) { - return ret; + size_t actual_size = 0; + buf = heap_caps_malloc(SDMMC_IO_BLOCK_SIZE, MALLOC_CAP_DMA); + if (!buf) { + ESP_LOGE(TAG, "%s: not enough mem, err=0x%x", __func__, ESP_ERR_NO_MEM); + return ESP_ERR_NO_MEM; } + actual_size = heap_caps_get_allocated_size(buf); + assert(actual_size == SDMMC_IO_BLOCK_SIZE); card->host.dma_aligned_buffer = buf; } return ESP_OK; } +esp_err_t sdmmc_check_host_function_ptr_integrity(sdmmc_card_t *card) +{ + if (!card->host.check_buffer_alignment) { + ESP_LOGE(TAG, "%s: host drv check_buffer_alignment not initialised, err=0x%x", __func__, ESP_ERR_INVALID_ARG); + return ESP_ERR_INVALID_ARG; + } + return ESP_OK; +} + uint32_t sdmmc_get_erase_timeout_ms(const sdmmc_card_t* card, int arg, size_t erase_size_kb) { if (card->is_mmc) { diff --git a/components/sdmmc/sdmmc_init.c b/components/sdmmc/sdmmc_init.c index 3e62209d368a..6e7bf863f8f8 100644 --- a/components/sdmmc/sdmmc_init.c +++ b/components/sdmmc/sdmmc_init.c @@ -68,6 +68,9 @@ esp_err_t sdmmc_card_init(const sdmmc_host_t* config, sdmmc_card_t* card) /* Check if host flags are compatible with slot configuration. */ SDMMC_INIT_STEP(!is_spi, sdmmc_fix_host_flags); + /* Check if host function pointers are correctly initialised */ + SDMMC_INIT_STEP(always, sdmmc_check_host_function_ptr_integrity); + /* Reset SDIO (CMD52, RES) before re-initializing IO (CMD5). */ SDMMC_INIT_STEP(io_supported, sdmmc_io_reset); diff --git a/components/sdmmc/sdmmc_io.c b/components/sdmmc/sdmmc_io.c index 64492f2da3f5..953a7ee0c467 100644 --- a/components/sdmmc/sdmmc_io.c +++ b/components/sdmmc/sdmmc_io.c @@ -319,9 +319,8 @@ esp_err_t sdmmc_io_rw_extended(sdmmc_card_t* card, int func, .blklen = SDMMC_IO_BLOCK_SIZE /* TODO: read max block size from CIS */ }; - esp_dma_mem_info_t dma_mem_info; - card->host.get_dma_info(card->host.slot, &dma_mem_info); - if (unlikely(datalen > 0 && !esp_dma_is_buffer_alignment_satisfied(datap, buflen, dma_mem_info))) { + bool is_aligned = card->host.check_buffer_alignment(card->host.slot, datap, buflen); + if (unlikely(datalen > 0 && !is_aligned)) { if (datalen > SDMMC_IO_BLOCK_SIZE || card->host.dma_aligned_buffer == NULL) { // User gives unaligned buffer while `SDMMC_HOST_FLAG_ALLOC_ALIGNED_BUF` not set. return ESP_ERR_INVALID_ARG; @@ -463,9 +462,8 @@ esp_err_t sdmmc_io_read_blocks(sdmmc_card_t* card, uint32_t function, addr &= ~SDMMC_IO_FIXED_ADDR; } - esp_dma_mem_info_t dma_mem_info; - card->host.get_dma_info(card->host.slot, &dma_mem_info); - if (unlikely(!esp_dma_is_buffer_alignment_satisfied(dst, size, dma_mem_info))) { + bool is_aligned = card->host.check_buffer_alignment(card->host.slot, dst, size); + if (unlikely(!is_aligned)) { return ESP_ERR_INVALID_ARG; } return sdmmc_io_rw_extended(card, function, addr, arg, dst, size); @@ -481,9 +479,8 @@ esp_err_t sdmmc_io_write_blocks(sdmmc_card_t* card, uint32_t function, addr &= ~SDMMC_IO_FIXED_ADDR; } - esp_dma_mem_info_t dma_mem_info; - card->host.get_dma_info(card->host.slot, &dma_mem_info); - if (unlikely(!esp_dma_is_buffer_alignment_satisfied(src, size, dma_mem_info))) { + bool is_aligned = card->host.check_buffer_alignment(card->host.slot, src, size); + if (unlikely(!is_aligned)) { return ESP_ERR_INVALID_ARG; } return sdmmc_io_rw_extended(card, function, addr, arg, (void*) src, size); diff --git a/components/sdmmc/sdmmc_mmc.c b/components/sdmmc/sdmmc_mmc.c index a4fed8a4c97d..24bbe9ef9f5c 100644 --- a/components/sdmmc/sdmmc_mmc.c +++ b/components/sdmmc/sdmmc_mmc.c @@ -28,14 +28,12 @@ esp_err_t sdmmc_init_mmc_read_ext_csd(sdmmc_card_t* card) esp_err_t err = ESP_OK; uint8_t* ext_csd = NULL; size_t actual_size = 0; - esp_dma_mem_info_t dma_mem_info; - card->host.get_dma_info(card->host.slot, &dma_mem_info); - err = esp_dma_capable_malloc(EXT_CSD_MMC_SIZE, &dma_mem_info, (void *)&ext_csd, &actual_size); - if (err != ESP_OK) { - ESP_LOGE(TAG, "%s: could not allocate ext_csd", __func__); - return err; + ext_csd = heap_caps_malloc(EXT_CSD_MMC_SIZE, MALLOC_CAP_DMA); + if (!ext_csd) { + ESP_LOGE(TAG, "%s: not enough mem, err=0x%x", __func__, ESP_ERR_NO_MEM); + return ESP_ERR_NO_MEM; } - + actual_size = heap_caps_get_allocated_size(ext_csd); uint32_t sectors = 0; ESP_LOGD(TAG, "MMC version: %d", card->csd.mmc_ver); @@ -257,13 +255,13 @@ esp_err_t sdmmc_init_mmc_check_ext_csd(sdmmc_card_t* card) /* ensure EXT_CSD buffer is available before starting any SD-card operation */ uint8_t* ext_csd = NULL; size_t actual_size = 0; - esp_dma_mem_info_t dma_mem_info; - card->host.get_dma_info(card->host.slot, &dma_mem_info); - esp_err_t err = esp_dma_capable_malloc(EXT_CSD_MMC_SIZE, &dma_mem_info, (void *)&ext_csd, &actual_size); - if (err != ESP_OK) { - ESP_LOGE(TAG, "%s: could not allocate ext_csd", __func__); - return err; + esp_err_t err = ESP_FAIL; + ext_csd = heap_caps_malloc(EXT_CSD_MMC_SIZE, MALLOC_CAP_DMA); + if (!ext_csd) { + ESP_LOGE(TAG, "%s: not enough mem, err=0x%x", __func__, ESP_ERR_NO_MEM); + return ESP_ERR_NO_MEM; } + actual_size = heap_caps_get_allocated_size(ext_csd); /* ensure card is in transfer state before read ext_csd */ uint32_t status; diff --git a/components/sdmmc/sdmmc_sd.c b/components/sdmmc/sdmmc_sd.c index 45b13beb6ed0..b1bf76401583 100644 --- a/components/sdmmc/sdmmc_sd.c +++ b/components/sdmmc/sdmmc_sd.c @@ -92,13 +92,13 @@ esp_err_t sdmmc_init_sd_ssr(sdmmc_card_t* card) */ uint32_t* sd_ssr = NULL; size_t actual_size = 0; - esp_dma_mem_info_t dma_mem_info; - card->host.get_dma_info(card->host.slot, &dma_mem_info); - err = esp_dma_capable_calloc(1, SD_SSR_SIZE, &dma_mem_info, (void *)&sd_ssr, &actual_size); - if (err != ESP_OK) { - ESP_LOGE(TAG, "%s: could not allocate sd_ssr", __func__); - return err; + + sd_ssr = heap_caps_calloc(1, SD_SSR_SIZE, MALLOC_CAP_DMA); + if (!sd_ssr) { + ESP_LOGE(TAG, "%s: not enough mem, err=0x%x", __func__, ESP_ERR_NO_MEM); + return ESP_ERR_NO_MEM; } + actual_size = heap_caps_get_allocated_size(sd_ssr); sdmmc_command_t cmd = { .data = sd_ssr, @@ -240,14 +240,12 @@ esp_err_t sdmmc_enter_higher_speed_mode(sdmmc_card_t* card) return ESP_ERR_NOT_SUPPORTED; } - size_t actual_size = 0; sdmmc_switch_func_rsp_t *response = NULL; - esp_dma_mem_info_t dma_mem_info; - card->host.get_dma_info(card->host.slot, &dma_mem_info); - esp_err_t err = esp_dma_capable_malloc(sizeof(*response), &dma_mem_info, (void *)&response, &actual_size); - assert(actual_size == sizeof(*response)); - if (err != ESP_OK) { - return err; + esp_err_t err = ESP_FAIL; + response = heap_caps_malloc(sizeof(*response), MALLOC_CAP_DMA); + if (!response) { + ESP_LOGE(TAG, "%s: not enough mem, err=0x%x", __func__, ESP_ERR_NO_MEM); + return ESP_ERR_NO_MEM; } err = sdmmc_send_cmd_switch_func(card, 0, SD_ACCESS_MODE, 0, response); diff --git a/components/soc/CMakeLists.txt b/components/soc/CMakeLists.txt index f1523b1f3a53..01ec2bf6010a 100644 --- a/components/soc/CMakeLists.txt +++ b/components/soc/CMakeLists.txt @@ -27,10 +27,6 @@ if(target STREQUAL "esp32") list(APPEND srcs "${target_folder}/dport_access.c") endif() -if(target STREQUAL "esp32h2") - list(APPEND srcs "${target_folder}/lpperi_struct.c") -endif() - if(CONFIG_SOC_ADC_SUPPORTED) list(APPEND srcs "${target_folder}/adc_periph.c") endif() diff --git a/components/soc/esp32/emac_periph.c b/components/soc/esp32/emac_periph.c index a33327011596..389ee539214e 100644 --- a/components/soc/esp32/emac_periph.c +++ b/components/soc/esp32/emac_periph.c @@ -25,7 +25,9 @@ const emac_io_info_t emac_io_idx = { .mii_col_i_idx = SIG_GPIO_OUT_IDX, .mii_crs_i_idx = SIG_GPIO_OUT_IDX, .mii_tx_er_o_idx = SIG_GPIO_OUT_IDX, - .mii_rx_er_i_idx = SIG_GPIO_OUT_IDX + .mii_rx_er_i_idx = SIG_GPIO_OUT_IDX, + .rmii_refclk_i_idx = SIG_GPIO_OUT_IDX, + .rmii_refclk_o_idx = SIG_GPIO_OUT_IDX }; static const emac_iomux_info_t emac_rmii_iomux_clki[] = { diff --git a/components/soc/esp32/include/soc/system_intr.h b/components/soc/esp32/include/soc/system_intr.h new file mode 100644 index 000000000000..a681733c8def --- /dev/null +++ b/components/soc/esp32/include/soc/system_intr.h @@ -0,0 +1,13 @@ +/** + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +// Maps misc system interrupt to hardware interrupt names +#define SYS_CPU_INTR_FROM_CPU_0_SOURCE ETS_FROM_CPU_INTR0_SOURCE +#define SYS_CPU_INTR_FROM_CPU_1_SOURCE ETS_FROM_CPU_INTR1_SOURCE + +#define SYS_TG0_WDT_INTR_SOURCE ETS_TG0_WDT_LEVEL_INTR_SOURCE +#define SYS_TG1_WDT_INTR_SOURCE ETS_TG1_WDT_LEVEL_INTR_SOURCE diff --git a/components/soc/esp32/register/soc/rtc_io_struct.h b/components/soc/esp32/register/soc/rtc_io_struct.h index ced01aa512d5..69aa73a038db 100644 --- a/components/soc/esp32/register/soc/rtc_io_struct.h +++ b/components/soc/esp32/register/soc/rtc_io_struct.h @@ -236,7 +236,7 @@ typedef volatile struct rtc_io_dev_s { uint32_t xpd: 1; /*touch sensor power on.*/ uint32_t tie_opt: 1; /*default touch sensor tie option. 0: tie low 1: tie high.*/ uint32_t start: 1; /*start touch sensor.*/ - uint32_t dac: 3; /*touch sensor slope control. 3-bit for each touch panel default 100.*/ + uint32_t slope: 3; /*touch sensor slope control. 3-bit for each touch panel default 100.*/ uint32_t reserved26: 1; uint32_t rue: 1; /*the pull up enable of the pad*/ uint32_t rde: 1; /*the pull down enable of the pad*/ diff --git a/components/soc/esp32c2/include/soc/system_intr.h b/components/soc/esp32c2/include/soc/system_intr.h new file mode 100644 index 000000000000..9f7be4017249 --- /dev/null +++ b/components/soc/esp32c2/include/soc/system_intr.h @@ -0,0 +1,12 @@ +/** + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +// Maps misc system interrupt to hardware interrupt names +#define SYS_CPU_INTR_FROM_CPU_0_SOURCE ETS_FROM_CPU_INTR0_SOURCE + +#define SYS_TG0_WDT_INTR_SOURCE ETS_TG0_WDT_LEVEL_INTR_SOURCE +#define SYS_TG1_WDT_INTR_SOURCE ETS_TG1_WDT_LEVEL_INTR_SOURCE diff --git a/components/soc/esp32c2/temperature_sensor_periph.c b/components/soc/esp32c2/temperature_sensor_periph.c index e75c60b31783..165403570fee 100644 --- a/components/soc/esp32c2/temperature_sensor_periph.c +++ b/components/soc/esp32c2/temperature_sensor_periph.c @@ -5,8 +5,9 @@ */ #include "soc/temperature_sensor_periph.h" +#include "esp_attr.h" -const temperature_sensor_attribute_t temperature_sensor_attributes[TEMPERATURE_SENSOR_ATTR_RANGE_NUM] = { +DRAM_ATTR temperature_sensor_attribute_t temperature_sensor_attributes[TEMPERATURE_SENSOR_ATTR_RANGE_NUM] = { /*Offset reg_val min max error */ {-2, 5, 50, 125, 3}, {-1, 7, 20, 100, 2}, diff --git a/components/soc/esp32c3/include/soc/system_intr.h b/components/soc/esp32c3/include/soc/system_intr.h new file mode 100644 index 000000000000..9f7be4017249 --- /dev/null +++ b/components/soc/esp32c3/include/soc/system_intr.h @@ -0,0 +1,12 @@ +/** + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +// Maps misc system interrupt to hardware interrupt names +#define SYS_CPU_INTR_FROM_CPU_0_SOURCE ETS_FROM_CPU_INTR0_SOURCE + +#define SYS_TG0_WDT_INTR_SOURCE ETS_TG0_WDT_LEVEL_INTR_SOURCE +#define SYS_TG1_WDT_INTR_SOURCE ETS_TG1_WDT_LEVEL_INTR_SOURCE diff --git a/components/soc/esp32c3/temperature_sensor_periph.c b/components/soc/esp32c3/temperature_sensor_periph.c index e75c60b31783..165403570fee 100644 --- a/components/soc/esp32c3/temperature_sensor_periph.c +++ b/components/soc/esp32c3/temperature_sensor_periph.c @@ -5,8 +5,9 @@ */ #include "soc/temperature_sensor_periph.h" +#include "esp_attr.h" -const temperature_sensor_attribute_t temperature_sensor_attributes[TEMPERATURE_SENSOR_ATTR_RANGE_NUM] = { +DRAM_ATTR temperature_sensor_attribute_t temperature_sensor_attributes[TEMPERATURE_SENSOR_ATTR_RANGE_NUM] = { /*Offset reg_val min max error */ {-2, 5, 50, 125, 3}, {-1, 7, 20, 100, 2}, diff --git a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in index 4d7cfaf710b6..77670c4e895a 100644 --- a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in @@ -251,6 +251,10 @@ config SOC_PHY_SUPPORTED bool default y +config SOC_BITSCRAMBLER_SUPPORTED + bool + default y + config SOC_XTAL_SUPPORT_40M bool default y diff --git a/components/soc/esp32c5/include/soc/bitscrambler_peri_select.h b/components/soc/esp32c5/include/soc/bitscrambler_peri_select.h new file mode 100644 index 000000000000..131bcfaa232b --- /dev/null +++ b/components/soc/esp32c5/include/soc/bitscrambler_peri_select.h @@ -0,0 +1,20 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +/* + * @brief BitScrambler attachment targets + * Note that these are the values written to HP_SYSTEM_BITSCRAMBLER_PERI_SEL_REG. + */ + +#define SOC_BITSCRAMBLER_ATTACH_GPSPI2 1 +#define SOC_BITSCRAMBLER_ATTACH_UHCI 2 +#define SOC_BITSCRAMBLER_ATTACH_I2S0 3 +#define SOC_BITSCRAMBLER_ATTACH_AES 4 +#define SOC_BITSCRAMBLER_ATTACH_SHA 5 +#define SOC_BITSCRAMBLER_ATTACH_ADC 6 +#define SOC_BITSCRAMBLER_ATTACH_PARL_IO 7 +#define SOC_BITSCRAMBLER_ATTACH_MAX 7 diff --git a/components/soc/esp32c5/include/soc/clic_reg.h b/components/soc/esp32c5/include/soc/clic_reg.h index 324cfd8c8ab9..d0ba099ba1c2 100644 --- a/components/soc/esp32c5/include/soc/clic_reg.h +++ b/components/soc/esp32c5/include/soc/clic_reg.h @@ -12,97 +12,159 @@ extern "C" { #define NLBITS 3 #define CLIC_EXT_INTR_NUM_OFFSET 16 -#define DUALCORE_CLIC_CTRL_OFF 0x10000 -#define DR_REG_CLIC_BASE ( 0x20800000 ) -#define DR_REG_CLIC_CTRL_BASE ( 0x20801000 ) +#define DR_REG_CLIC_BASE (0x20800000) +#define DR_REG_CLIC_CTRL_BASE (0x20801000) #define CLIC_INT_CONFIG_REG (DR_REG_CLIC_BASE + 0x0) -/* CLIC_INT_CONFIG_NMBITS : R/W ;bitpos:[6:5] ;default: 2'd0 ; */ -/*description: .*/ +/* CLIC_INT_CONFIG_NLBITS : R/W ;bitpos:[27:24] ;default: 4'd0 ; */ +/*description: user mode interrupt priority effective digits, the maximum value is 8..*/ +#define CLIC_INT_CONFIG_UNLBITS 0x0000000F +#define CLIC_INT_CONFIG_UNLBITS_M ((CLIC_INT_CONFIG_UNLBITS_V) << (CLIC_INT_CONFIG_UNLBITS_S)) +#define CLIC_INT_CONFIG_UNLBITS_V 0xF +#define CLIC_INT_CONFIG_UNLBITS_S 24 +/* CLIC_INT_CONFIG_NLBITS : R/W ;bitpos:[19:16] ;default: 4'd0 ; */ +/*description: supervisor mode interrupt priority effective digits, the maximum value is 8..*/ +#define CLIC_INT_CONFIG_SNLBITS 0x0000000F +#define CLIC_INT_CONFIG_SNLBITS_M ((CLIC_INT_CONFIG_SNLBITS_V) << (CLIC_INT_CONFIG_SNLBITS_S)) +#define CLIC_INT_CONFIG_SNLBITS_V 0xF +#define CLIC_INT_CONFIG_SNLBITS_S 16 +/* CLIC_INT_CONFIG_NMBITS : R/W ;bitpos:[5:4] ;default: 2'd0 ; */ +/*description: the effective number of bits in the privileged state.*/ #define CLIC_INT_CONFIG_NMBITS 0x00000003 -#define CLIC_INT_CONFIG_NMBITS_M ((CLIC_INT_CONFIG_NMBITS_V)<<(CLIC_INT_CONFIG_NMBITS_S)) +#define CLIC_INT_CONFIG_NMBITS_M ((CLIC_INT_CONFIG_NMBITS_V) << (CLIC_INT_CONFIG_NMBITS_S)) #define CLIC_INT_CONFIG_NMBITS_V 0x3 -#define CLIC_INT_CONFIG_NMBITS_S 5 -/* CLIC_INT_CONFIG_NLBITS : R/W ;bitpos:[4:1] ;default: 4'd0 ; */ -/*description: .*/ -#define CLIC_INT_CONFIG_NLBITS 0x0000000F -#define CLIC_INT_CONFIG_NLBITS_M ((CLIC_INT_CONFIG_NLBITS_V)<<(CCLIC_INT_CONFIG_NLBITS_S)) -#define CLIC_INT_CONFIG_NLBITS_V 0xF -#define CLIC_INT_CONFIG_NLBITS_S 1 -/* CLIC_INT_CONFIG_NVBITS : R/W ;bitpos:[0] ;default: 1'd1 ; */ -/*description: .*/ -#define CLIC_INT_CONFIG_NVBITS (BIT(0)) -#define CLIC_INT_CONFIG_NVBITS_M (BIT(0)) -#define CLIC_INT_CONFIG_NVBITS_V 0x1 -#define CLIC_INT_CONFIG_NVBITS_S 0 +#define CLIC_INT_CONFIG_NMBITS_S 4 +/* CLIC_INT_CONFIG_NLBITS : R/W ;bitpos:[3:0] ;default: 4'd0 ; */ +/*description: machine mode interrupt priority effective digits, the maximum value is 8.*/ +#define CLIC_INT_CONFIG_MNLBITS 0x0000000F +#define CLIC_INT_CONFIG_MNLBITS_M ((CLIC_INT_CONFIG_MNLBITS_V) << (CLIC_INT_CONFIG_MNLBITS_S)) +#define CLIC_INT_CONFIG_MNLBITS_V 0xF +#define CLIC_INT_CONFIG_MNLBITS_S 0 #define CLIC_INT_INFO_REG (DR_REG_CLIC_BASE + 0x4) -/* CLIC_INT_INFO_NUM_INT : R/W ;bitpos:[24:21] ;default: 4'd0 ; */ -/*description: .*/ +/* CLIC_INT_INFO_NUM_INT : RO ;bitpos:[24:21] ;default: 4'd3 ; */ +/*description: The effective bits of priority in the CLICINTCTL register.*/ #define CLIC_INT_INFO_CTLBITS 0x0000000F -#define CLIC_INT_INFO_CTLBITS_M ((CLIC_INT_INFO_CTLBITS_V)<<(CLIC_INT_INFO_CTLBITS_S)) +#define CLIC_INT_INFO_CTLBITS_M ((CLIC_INT_INFO_CTLBITS_V) << (CLIC_INT_INFO_CTLBITS_S)) #define CLIC_INT_INFO_CTLBITS_V 0xF #define CLIC_INT_INFO_CTLBITS_S 21 -/* CLIC_INT_INFO_VERSION : R/W ;bitpos:[20:13] ;default: 8'd0 ; */ -/*description: .*/ +/* CLIC_INT_INFO_VERSION : RO ;bitpos:[20:13] ;default: 8'd0 ; */ +/*description: The lower 4 bits are the modified version of the hardware implementation; the upper 4 bits are the CLIC +architecture version information.*/ #define CLIC_INT_INFO_VERSION 0x000000FF -#define CLIC_INT_INFO_VERSION_M ((CLIC_INT_INFO_VERSION_V)<<(CLIC_INT_INFO_VERSION_S)) +#define CLIC_INT_INFO_VERSION_M ((CLIC_INT_INFO_VERSION_V) << (CLIC_INT_INFO_VERSION_S)) #define CLIC_INT_INFO_VERSION_V 0xFF #define CLIC_INT_INFO_VERSION_S 13 -/* CLIC_INT_INFO_NUM_INT : R/W ;bitpos:[12:0] ;default: 13'd0 ; */ -/*description: .*/ -#define CLIC_INT_INFO_NUM_INT 0x00001FFF -#define CLIC_INT_INFO_NUM_INT_M ((CLIC_INT_INFO_NUM_INT_V)<<(CLIC_INT_INFO_NUM_INT_S)) -#define CLIC_INT_INFO_NUM_INT_V 0x1FFF -#define CLIC_INT_INFO_NUM_INT_S 0 +/* CLIC_INT_INFO_NUM_INT : RO ;bitpos:[12:0] ;default: 13'd48 ; */ +/*description: number of interrupt sources.*/ +#define CLIC_INT_INFO_NUM_INT 0x00001FFF +#define CLIC_INT_INFO_NUM_INT_M ((CLIC_INT_INFO_NUM_INT_V) << (CLIC_INT_INFO_NUM_INT_S)) +#define CLIC_INT_INFO_NUM_INT_V 0x1FFF +#define CLIC_INT_INFO_NUM_INT_S 0 #define CLIC_INT_THRESH_REG (DR_REG_CLIC_BASE + 0x8) /* CLIC_CPU_INT_THRESH : R/W ;bitpos:[31:24] ;default: 8'd0 ; */ -/*description: .*/ -#define CLIC_CPU_INT_THRESH 0x000000FF -#define CLIC_CPU_INT_THRESH_M ((CLIC_CPU_INT_THRESH_V)<<(CLIC_CPU_INT_THRESH_S)) +/*description: Threshold for machine mode interruption..*/ +#define CLIC_CPU_INT_THRESH 0x000000FF +#define CLIC_CPU_INT_THRESH_M ((CLIC_CPU_INT_THRESH_V) << (CLIC_CPU_INT_THRESH_S)) #define CLIC_CPU_INT_THRESH_V 0xFF #define CLIC_CPU_INT_THRESH_S 24 -#define CLIC_INT_CTRL_REG(i) (DR_REG_CLIC_CTRL_BASE + (i) * 4) -/* CLIC_INT_CTL : R/W ;bitpos:[31:24] ;default: 8'd0 ; */ -/*description: .*/ +#define CLIC_INT_CTRL_REG(i) (DR_REG_CLIC_CTRL_BASE + (i)*4) +/* CLIC_INT_CTL : R/W ;bitpos:[31:24] ;default: 8'h1f ; */ +/*description: This register is used to indicate the priority of each interrupt +source participating in the arbitration, and at the same time to cooperate with +CLICCFG.nlbits to generate the interrupt priority to the CPU.*/ #define CLIC_INT_CTL 0x000000FF -#define CLIC_INT_CTL_M ((CLIC_INT_CTL_V)<<(CLIC_INT_CTL_S)) +#define CLIC_INT_CTL_M ((CLIC_INT_CTL_V) << (CLIC_INT_CTL_S)) #define CLIC_INT_CTL_V 0xFF #define CLIC_INT_CTL_S 24 /* CLIC_INT_ATTR_MODE : R/W ;bitpos:[23:22] ;default: 2'b11 ; */ -/*description: .*/ +/*description: This field is used to configure the privileged mode of the interrupt. +0: user mode, 3: machine mode*/ #define CLIC_INT_ATTR_MODE 0x00000003 -#define CLIC_INT_ATTR_MODE_M ((CLIC_INT_ATTR_MODE_V)<<(CLIC_INT_ATTR_MODE_S)) +#define CLIC_INT_ATTR_MODE_M ((CLIC_INT_ATTR_MODE_V) << (CLIC_INT_ATTR_MODE_S)) #define CLIC_INT_ATTR_MODE_V 0x3 #define CLIC_INT_ATTR_MODE_S 22 /* CLIC_INT_ATTR_TRIG : R/W ;bitpos:[18:17] ;default: 2'd0 ; */ -/*description: .*/ +/*description: This field is used to distinguish pulse interruption and level +interruption. When trig[0] is 0, it means level interruption. When trig[0] is 1, +trig[1] is 0, it means interrupt on rising edge, and trig[1] is 1 means interrupt +on falling edge.*/ #define CLIC_INT_ATTR_TRIG 0x00000003 -#define CLIC_INT_ATTR_TRIG_M ((CLIC_INT_ATTR_TRIG_V)<<(CLIC_INT_ATTR_TRIG_S)) +#define CLIC_INT_ATTR_TRIG_M ((CLIC_INT_ATTR_TRIG_V) << (CLIC_INT_ATTR_TRIG_S)) #define CLIC_INT_ATTR_TRIG_V 0x3 #define CLIC_INT_ATTR_TRIG_S 17 /* CLIC_INT_ATTR_SHV : R/W ;bitpos:[16] ;default: 1'd0 ; */ -/*description: .*/ +/*description: Represents whether the interrupt is a hardware vector interrupt.*/ #define CLIC_INT_ATTR_SHV (BIT(16)) #define CLIC_INT_ATTR_SHV_M (BIT(16)) #define CLIC_INT_ATTR_SHV_V 0x1 #define CLIC_INT_ATTR_SHV_S 16 /* CLIC_INT_IE : R/W ;bitpos:[8] ;default: 1'd0 ; */ -/*description: .*/ +/*description: Interrupt Enable Register.*/ #define CLIC_INT_IE (BIT(8)) #define CLIC_INT_IE_M (BIT(8)) #define CLIC_INT_IE_V 0x1 #define CLIC_INT_IE_S 8 /* CLIC_INT_IP : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: .*/ +/*description: Interrupt Pending Register. This bit has different set and clear logic in the +case of level interrupt and edge interrupt*/ #define CLIC_INT_IP (BIT(0)) #define CLIC_INT_IP_M (BIT(0)) #define CLIC_INT_IP_V 0x1 #define CLIC_INT_IP_S 0 +// each of following registers are 8bits +#define BYTE_CLIC_INT_IP_REG(i) (DR_REG_CLIC_CTRL_BASE + (i) * 4) +/* BYTE_CLIC_INT_IP : R/W ;bitpos:[0] ;default: 1'd0 ; */ +/*description: Interrupt Pending Register. This bit has different set and clear logic in the +case of level interrupt and edge interrupt*/ +#define BYTE_CLIC_INT_IP (BIT(0)) +#define BYTE_CLIC_INT_IP_M (BIT(0)) +#define BYTE_CLIC_INT_IP_V 0x1 +#define BYTE_CLIC_INT_IP_S 0 + +#define BYTE_CLIC_INT_IE_REG(i) (DR_REG_CLIC_CTRL_BASE + 1 + (i) * 4) +/* BYTE_CLIC_INT_IE : R/W ;bitpos:[0] ;default: 1'd0 ; */ +/*description: Interrupt Enable Register.*/ +#define BYTE_CLIC_INT_IE (BIT(0)) +#define BYTE_CLIC_INT_IE_M (BIT(0)) +#define BYTE_CLIC_INT_IE_V 0x1 +#define BYTE_CLIC_INT_IE_S 0 + +#define BYTE_CLIC_INT_ATTR_REG(i) (DR_REG_CLIC_CTRL_BASE + 2 + (i) * 4) +/* BYTE_CLIC_INT_ATTR_SHV : R/W ;bitpos:[0] ;default: 1'd0 ; */ +/*description: 1 means hardware vector interrupt.*/ +#define BYTE_CLIC_INT_ATTR_SHV (BIT(0)) +#define BYTE_CLIC_INT_ATTR_SHV_M (BIT(0)) +#define BYTE_CLIC_INT_ATTR_SHV_V 0x1 +#define BYTE_CLIC_INT_ATTR_SHV_S 0 +/* BYTE_CLIC_INT_ATTR_TRIG: R/W ; bitpos:[2:1] ;default: 2'd0 ; */ +/*description: + [X0] -> level trigger + [01] -> rising edge trigger + [11] -> falling edge trigger */ +#define BYTE_CLIC_INT_ATTR_TRIG 0x00000003 +#define BYTE_CLIC_INT_ATTR_TRIG_M ((BYTE_CLIC_INT_ATTR_TRIG_V) << (BYTE_CLIC_INT_ATTR_TRIG_S)) +#define BYTE_CLIC_INT_ATTR_TRIG_V 0x3 +#define BYTE_CLIC_INT_ATTR_TRIG_S 1 +/* BYTE_CLIC_INT_ATTR_MODE: R/W ; bitpos:[7:6] ;default: 2'd0 ; */ +/*description: privilege level for interrupt, 0: user mode, 3: machine mode */ +#define BYTE_CLIC_INT_ATTR_MODE 0x00000003 +#define BYTE_CLIC_INT_ATTR_MODE_M ((BYTE_CLIC_INT_ATTR_MODE_V) << (BYTE_CLIC_INT_ATTR_MODE_S)) +#define BYTE_CLIC_INT_ATTR_MODE_V 0x3 +#define BYTE_CLIC_INT_ATTR_MODE_S 6 + +#define BYTE_CLIC_INT_CTL_REG(i) (DR_REG_CLIC_CTRL_BASE + 3 + (i) * 4) +/* BYTE_CLIC_INT_ATTR_MODE: R/W ; bitpos:[7:5] ;default: 3'd0 ; */ +/*description: interrupt priority */ +#define BYTE_CLIC_INT_CTL 0x00000007 +#define BYTE_CLIC_INT_CTL_M ((BYTE_CLIC_INT_CTL_V) << (BYTE_CLIC_INT_CTL_S)) +#define BYTE_CLIC_INT_CTL_V 0x7 +#define BYTE_CLIC_INT_CTL_S 5 + #ifdef __cplusplus } #endif diff --git a/components/soc/esp32c5/include/soc/soc_caps.h b/components/soc/esp32c5/include/soc/soc_caps.h index 911977a2edff..a33e04ba2fa9 100644 --- a/components/soc/esp32c5/include/soc/soc_caps.h +++ b/components/soc/esp32c5/include/soc/soc_caps.h @@ -84,6 +84,7 @@ #define SOC_SPIRAM_SUPPORTED 1 #define SOC_BT_SUPPORTED 1 #define SOC_PHY_SUPPORTED 1 +#define SOC_BITSCRAMBLER_SUPPORTED 1 /*-------------------------- XTAL CAPS ---------------------------------------*/ #define SOC_XTAL_SUPPORT_40M 1 diff --git a/components/soc/esp32c5/include/soc/system_intr.h b/components/soc/esp32c5/include/soc/system_intr.h new file mode 100644 index 000000000000..9f7be4017249 --- /dev/null +++ b/components/soc/esp32c5/include/soc/system_intr.h @@ -0,0 +1,12 @@ +/** + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +// Maps misc system interrupt to hardware interrupt names +#define SYS_CPU_INTR_FROM_CPU_0_SOURCE ETS_FROM_CPU_INTR0_SOURCE + +#define SYS_TG0_WDT_INTR_SOURCE ETS_TG0_WDT_LEVEL_INTR_SOURCE +#define SYS_TG1_WDT_INTR_SOURCE ETS_TG1_WDT_LEVEL_INTR_SOURCE diff --git a/components/soc/esp32c5/register/soc/bitscrambler_struct.h b/components/soc/esp32c5/register/soc/bitscrambler_struct.h index 7bf84e8264be..dc98ec027b12 100644 --- a/components/soc/esp32c5/register/soc/bitscrambler_struct.h +++ b/components/soc/esp32c5/register/soc/bitscrambler_struct.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 */ @@ -405,22 +405,198 @@ typedef union { uint32_t val; } bitscrambler_version_reg_t; +///////////////////// TX and RX registers are exactly the same ////////////////////////////////// +// The following registers are used for both TX and RX, so we can use the same struct for both // +///////////////////////////////////////////////////////////////////////////////////////////////// + +/** Type of inst_cfg0 register + * Control and configuration registers + */ +typedef union { + struct { + /** inst_idx : R/W; bitpos: [2:0]; default: 0; + * write this bits to specify the one of 8 instruction + */ + uint32_t inst_idx:3; + /** inst_pos : R/W; bitpos: [6:3]; default: 0; + * write this bits to specify the bit position of 257 bit instruction which in units + * of 32 bits + */ + uint32_t inst_pos:4; + uint32_t reserved_7:25; + }; + uint32_t val; +} bitscrambler_inst_cfg0_reg_t; + +/** Type of inst_cfg1 register + * Control and configuration registers + */ +typedef union { + struct { + /** inst : R/W; bitpos: [31:0]; default: 4; + * write this bits to update instruction, Read this bits to get instruction. + */ + uint32_t inst:32; + }; + uint32_t val; +} bitscrambler_inst_cfg1_reg_t; + +/** Type of lut_cfg0 register + * Control and configuration registers + */ +typedef union { + struct { + /** lut_idx : R/W; bitpos: [10:0]; default: 0; + * write this bits to specify the bytes position of LUT RAM based on lut_mode + */ + uint32_t lut_idx:11; + /** lut_mode : R/W; bitpos: [12:11]; default: 0; + * write this bits to specify the bytes mode of LUT RAM, 0: 1 byte,1: 2bytes, 2: 4 + * bytes + */ + uint32_t lut_mode:2; + uint32_t reserved_13:19; + }; + uint32_t val; +} bitscrambler_lut_cfg0_reg_t; + +/** Type of lut_cfg1 register + * Control and configuration registers + */ +typedef union { + struct { + /** lut : R/W; bitpos: [31:0]; default: 20; + * write this bits to update LUT, Read this bits to get LUT + */ + uint32_t lut:32; + }; + uint32_t val; +} bitscrambler_lut_cfg1_reg_t; + +/** Type of tailing_bits register + * Control and configuration registers + */ +typedef union { + struct { + /** tailing_bits : R/W; bitpos: [15:0]; default: 0; + * write this bits to specify the extra data bit length after getting EOF + */ + uint32_t tailing_bits:16; + uint32_t reserved_16:16; + }; + uint32_t val; +} bitscrambler_tailing_bits_reg_t; + +/** Type of ctrl register + * Control and configuration registers + */ +typedef union { + struct { + /** ena : R/W; bitpos: [0]; default: 0; + * write this bit to enable the bitscrambler tx + */ + uint32_t ena:1; + /** pause : R/W; bitpos: [1]; default: 0; + * write this bit to pause the bitscrambler tx core + */ + uint32_t pause:1; + /** halt : R/W; bitpos: [2]; default: 1; + * write this bit to halt the bitscrambler tx core + */ + uint32_t halt:1; + /** eof_mode : R/W; bitpos: [3]; default: 0; + * write this bit to ser the bitscrambler tx core EOF signal generating mode which is + * combined with reg_bitscrambler_tailing_bits, 0: counter by read dma fifo, 0 + * counter by write peripheral buffer + */ + uint32_t eof_mode:1; + /** cond_mode : R/W; bitpos: [4]; default: 0; + * write this bit to specify the LOOP instruction condition mode of bitscrambler tx + * core, 0: use the little than operator to get the condition, 1: use not equal + * operator to get the condition + */ + uint32_t cond_mode:1; + /** fetch_mode : R/W; bitpos: [5]; default: 0; + * write this bit to set the bitscrambler tx core fetch instruction mode, 0: prefetch + * by reset, 1: fetch by instructions + */ + uint32_t fetch_mode:1; + /** halt_mode : R/W; bitpos: [6]; default: 0; + * write this bit to set the bitscrambler tx core halt mode when halt is set, 0: + * wait write data back done, , 1: ignore write data back + */ + uint32_t halt_mode:1; + /** rd_dummy : R/W; bitpos: [7]; default: 0; + * write this bit to set the bitscrambler tx core read data mode when EOF received.0: + * wait read data, 1: ignore read data + */ + uint32_t rd_dummy:1; + /** fifo_rst : WT; bitpos: [8]; default: 0; + * write this bit to reset the bitscrambler tx fifo + */ + uint32_t fifo_rst:1; + uint32_t reserved_9:23; + }; + uint32_t val; +} bitscrambler_ctrl_reg_t; + +/** Group: Status registers */ +/** Type of state register + * Status registers + */ +typedef union { + struct { + /** in_idle : RO; bitpos: [0]; default: 1; + * represents the bitscrambler tx core in halt mode + */ + uint32_t in_idle:1; + /** in_run : RO; bitpos: [1]; default: 0; + * represents the bitscrambler tx core in run mode + */ + uint32_t in_run:1; + /** in_wait : RO; bitpos: [2]; default: 0; + * represents the bitscrambler tx core in wait mode to wait write back done + */ + uint32_t in_wait:1; + /** in_pause : RO; bitpos: [3]; default: 0; + * represents the bitscrambler tx core in pause mode + */ + uint32_t in_pause:1; + /** fifo_empty : RO; bitpos: [4]; default: 0; + * represents the bitscrambler tx fifo in empty state + */ + uint32_t fifo_empty:1; + uint32_t reserved_5:11; + /** eof_get_cnt : RO; bitpos: [29:16]; default: 0; + * represents the bytes numbers of bitscrambler tx core when get EOF + */ + uint32_t eof_get_cnt:14; + /** eof_overload : RO; bitpos: [30]; default: 0; + * represents the some EOFs will be lost for bitscrambler tx core + */ + uint32_t eof_overload:1; + /** eof_trace_clr : WT; bitpos: [31]; default: 0; + * write this bit to clear reg_bitscrambler_eof_overload and + * reg_bitscrambler_eof_get_cnt registers + */ + uint32_t eof_trace_clr:1; + }; + uint32_t val; +} bitscrambler_state_reg_t; + typedef struct { - volatile bitscrambler_tx_inst_cfg0_reg_t tx_inst_cfg0; - volatile bitscrambler_tx_inst_cfg1_reg_t tx_inst_cfg1; - volatile bitscrambler_rx_inst_cfg0_reg_t rx_inst_cfg0; - volatile bitscrambler_rx_inst_cfg1_reg_t rx_inst_cfg1; - volatile bitscrambler_tx_lut_cfg0_reg_t tx_lut_cfg0; - volatile bitscrambler_tx_lut_cfg1_reg_t tx_lut_cfg1; - volatile bitscrambler_rx_lut_cfg0_reg_t rx_lut_cfg0; - volatile bitscrambler_rx_lut_cfg1_reg_t rx_lut_cfg1; - volatile bitscrambler_tx_tailing_bits_reg_t tx_tailing_bits; - volatile bitscrambler_rx_tailing_bits_reg_t rx_tailing_bits; - volatile bitscrambler_tx_ctrl_reg_t tx_ctrl; - volatile bitscrambler_rx_ctrl_reg_t rx_ctrl; - volatile bitscrambler_tx_state_reg_t tx_state; - volatile bitscrambler_rx_state_reg_t rx_state; + volatile struct { + bitscrambler_inst_cfg0_reg_t cfg0; + bitscrambler_inst_cfg1_reg_t cfg1; + } inst_cfg[2]; + volatile struct { + bitscrambler_lut_cfg0_reg_t cfg0; + bitscrambler_lut_cfg1_reg_t cfg1; + } lut_cfg[2]; + volatile bitscrambler_tailing_bits_reg_t tail_bits[2]; + volatile bitscrambler_ctrl_reg_t ctrl[2]; + volatile bitscrambler_state_reg_t state[2]; uint32_t reserved_038[48]; volatile bitscrambler_sys_reg_t sys; volatile bitscrambler_version_reg_t version; diff --git a/components/soc/esp32c5/temperature_sensor_periph.c b/components/soc/esp32c5/temperature_sensor_periph.c index 37e0e7e501c9..e44488fb1c79 100644 --- a/components/soc/esp32c5/temperature_sensor_periph.c +++ b/components/soc/esp32c5/temperature_sensor_periph.c @@ -8,8 +8,9 @@ #include "soc/regdma.h" #include "soc/temperature_sensor_periph.h" #include "soc/apb_saradc_reg.h" +#include "esp_attr.h" -const temperature_sensor_attribute_t temperature_sensor_attributes[TEMPERATURE_SENSOR_ATTR_RANGE_NUM] = { +DRAM_ATTR temperature_sensor_attribute_t temperature_sensor_attributes[TEMPERATURE_SENSOR_ATTR_RANGE_NUM] = { /*Offset reg_val min max error */ {-2, 5, 50, 125, 3}, {-1, 7, 20, 100, 2}, diff --git a/components/soc/esp32c6/include/soc/system_intr.h b/components/soc/esp32c6/include/soc/system_intr.h new file mode 100644 index 000000000000..9f7be4017249 --- /dev/null +++ b/components/soc/esp32c6/include/soc/system_intr.h @@ -0,0 +1,12 @@ +/** + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +// Maps misc system interrupt to hardware interrupt names +#define SYS_CPU_INTR_FROM_CPU_0_SOURCE ETS_FROM_CPU_INTR0_SOURCE + +#define SYS_TG0_WDT_INTR_SOURCE ETS_TG0_WDT_LEVEL_INTR_SOURCE +#define SYS_TG1_WDT_INTR_SOURCE ETS_TG1_WDT_LEVEL_INTR_SOURCE diff --git a/components/soc/esp32c6/temperature_sensor_periph.c b/components/soc/esp32c6/temperature_sensor_periph.c index 291327d2bfce..c0f47c153466 100644 --- a/components/soc/esp32c6/temperature_sensor_periph.c +++ b/components/soc/esp32c6/temperature_sensor_periph.c @@ -8,8 +8,9 @@ #include "soc/regdma.h" #include "soc/temperature_sensor_periph.h" #include "soc/apb_saradc_reg.h" +#include "esp_attr.h" -const temperature_sensor_attribute_t temperature_sensor_attributes[TEMPERATURE_SENSOR_ATTR_RANGE_NUM] = { +DRAM_ATTR temperature_sensor_attribute_t temperature_sensor_attributes[TEMPERATURE_SENSOR_ATTR_RANGE_NUM] = { /*Offset reg_val min max error */ {-2, 5, 50, 125, 3}, {-1, 7, 20, 100, 2}, diff --git a/components/soc/esp32c61/include/soc/system_intr.h b/components/soc/esp32c61/include/soc/system_intr.h new file mode 100644 index 000000000000..9f7be4017249 --- /dev/null +++ b/components/soc/esp32c61/include/soc/system_intr.h @@ -0,0 +1,12 @@ +/** + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +// Maps misc system interrupt to hardware interrupt names +#define SYS_CPU_INTR_FROM_CPU_0_SOURCE ETS_FROM_CPU_INTR0_SOURCE + +#define SYS_TG0_WDT_INTR_SOURCE ETS_TG0_WDT_LEVEL_INTR_SOURCE +#define SYS_TG1_WDT_INTR_SOURCE ETS_TG1_WDT_LEVEL_INTR_SOURCE diff --git a/components/soc/esp32c61/register/soc/clic_reg.h b/components/soc/esp32c61/register/soc/clic_reg.h index 5ce606a178b7..ba8987ece3be 100644 --- a/components/soc/esp32c61/register/soc/clic_reg.h +++ b/components/soc/esp32c61/register/soc/clic_reg.h @@ -16,139 +16,154 @@ extern "C" { #define DR_REG_CLIC_BASE (0x20800000) #define DR_REG_CLIC_CTRL_BASE (0x20801000) -#define CLIC_INT_CONFIG_REG (DR_REG_CLIC_BASE + 0x0) -/* CLIC_INT_CONFIG_NMBITS : R/W ;bitpos:[6:5] ;default: 2'd0 ; */ -/*description: .*/ -#define CLIC_INT_CONFIG_NMBITS 0x00000003 -#define CLIC_INT_CONFIG_NMBITS_M ((CLIC_INT_CONFIG_NMBITS_V) << (CLIC_INT_CONFIG_NMBITS_S)) -#define CLIC_INT_CONFIG_NMBITS_V 0x3 -#define CLIC_INT_CONFIG_NMBITS_S 5 -/* CLIC_INT_CONFIG_NLBITS : R/W ;bitpos:[4:1] ;default: 4'd0 ; */ -/*description: .*/ -#define CLIC_INT_CONFIG_NLBITS 0x0000000F -#define CLIC_INT_CONFIG_NLBITS_M ((CLIC_INT_CONFIG_NLBITS_V) << (CCLIC_INT_CONFIG_NLBITS_S)) -#define CLIC_INT_CONFIG_NLBITS_V 0xF -#define CLIC_INT_CONFIG_NLBITS_S 1 -/* CLIC_INT_CONFIG_NVBITS : R/W ;bitpos:[0] ;default: 1'd1 ; */ -/*description: .*/ -#define CLIC_INT_CONFIG_NVBITS (BIT(0)) -#define CLIC_INT_CONFIG_NVBITS_M (BIT(0)) -#define CLIC_INT_CONFIG_NVBITS_V 0x1 -#define CLIC_INT_CONFIG_NVBITS_S 0 +#define CLIC_INT_CONFIG_REG (DR_REG_CLIC_BASE + 0x0) +/* CLIC_INT_CONFIG_NLBITS : R/W ;bitpos:[27:24] ;default: 4'd0 ; */ +/*description: user mode interrupt priority effective digits, the maximum value is 8..*/ +#define CLIC_INT_CONFIG_UNLBITS 0x0000000F +#define CLIC_INT_CONFIG_UNLBITS_M ((CLIC_INT_CONFIG_UNLBITS_V) << (CLIC_INT_CONFIG_UNLBITS_S)) +#define CLIC_INT_CONFIG_UNLBITS_V 0xF +#define CLIC_INT_CONFIG_UNLBITS_S 24 +/* CLIC_INT_CONFIG_NLBITS : R/W ;bitpos:[19:16] ;default: 4'd0 ; */ +/*description: supervisor mode interrupt priority effective digits, the maximum value is 8..*/ +#define CLIC_INT_CONFIG_SNLBITS 0x0000000F +#define CLIC_INT_CONFIG_SNLBITS_M ((CLIC_INT_CONFIG_SNLBITS_V) << (CLIC_INT_CONFIG_SNLBITS_S)) +#define CLIC_INT_CONFIG_SNLBITS_V 0xF +#define CLIC_INT_CONFIG_SNLBITS_S 16 +/* CLIC_INT_CONFIG_NMBITS : R/W ;bitpos:[5:4] ;default: 2'd0 ; */ +/*description: the effective number of bits in the privileged state.*/ +#define CLIC_INT_CONFIG_NMBITS 0x00000003 +#define CLIC_INT_CONFIG_NMBITS_M ((CLIC_INT_CONFIG_NMBITS_V) << (CLIC_INT_CONFIG_NMBITS_S)) +#define CLIC_INT_CONFIG_NMBITS_V 0x3 +#define CLIC_INT_CONFIG_NMBITS_S 4 +/* CLIC_INT_CONFIG_NLBITS : R/W ;bitpos:[3:0] ;default: 4'd0 ; */ +/*description: machine mode interrupt priority effective digits, the maximum value is 8.*/ +#define CLIC_INT_CONFIG_MNLBITS 0x0000000F +#define CLIC_INT_CONFIG_MNLBITS_M ((CLIC_INT_CONFIG_MNLBITS_V) << (CLIC_INT_CONFIG_MNLBITS_S)) +#define CLIC_INT_CONFIG_MNLBITS_V 0xF +#define CLIC_INT_CONFIG_MNLBITS_S 0 -#define CLIC_INT_INFO_REG (DR_REG_CLIC_BASE + 0x4) -/* CLIC_INT_INFO_NUM_INT : R/W ;bitpos:[24:21] ;default: 4'd0 ; */ -/*description: .*/ -#define CLIC_INT_INFO_CTLBITS 0x0000000F -#define CLIC_INT_INFO_CTLBITS_M ((CLIC_INT_INFO_CTLBITS_V) << (CLIC_INT_INFO_CTLBITS_S)) -#define CLIC_INT_INFO_CTLBITS_V 0xF -#define CLIC_INT_INFO_CTLBITS_S 21 -/* CLIC_INT_INFO_VERSION : R/W ;bitpos:[20:13] ;default: 8'd0 ; */ -/*description: .*/ -#define CLIC_INT_INFO_VERSION 0x000000FF -#define CLIC_INT_INFO_VERSION_M ((CLIC_INT_INFO_VERSION_V) << (CLIC_INT_INFO_VERSION_S)) -#define CLIC_INT_INFO_VERSION_V 0xFF -#define CLIC_INT_INFO_VERSION_S 13 -/* CLIC_INT_INFO_NUM_INT : R/W ;bitpos:[12:0] ;default: 13'd0 ; */ -/*description: .*/ +#define CLIC_INT_INFO_REG (DR_REG_CLIC_BASE + 0x4) +/* CLIC_INT_INFO_NUM_INT : RO ;bitpos:[24:21] ;default: 4'd3 ; */ +/*description: The effective bits of priority in the CLICINTCTL register.*/ +#define CLIC_INT_INFO_CTLBITS 0x0000000F +#define CLIC_INT_INFO_CTLBITS_M ((CLIC_INT_INFO_CTLBITS_V) << (CLIC_INT_INFO_CTLBITS_S)) +#define CLIC_INT_INFO_CTLBITS_V 0xF +#define CLIC_INT_INFO_CTLBITS_S 21 +/* CLIC_INT_INFO_VERSION : RO ;bitpos:[20:13] ;default: 8'd0 ; */ +/*description: The lower 4 bits are the modified version of the hardware implementation; the upper 4 bits are the CLIC +architecture version information.*/ +#define CLIC_INT_INFO_VERSION 0x000000FF +#define CLIC_INT_INFO_VERSION_M ((CLIC_INT_INFO_VERSION_V) << (CLIC_INT_INFO_VERSION_S)) +#define CLIC_INT_INFO_VERSION_V 0xFF +#define CLIC_INT_INFO_VERSION_S 13 +/* CLIC_INT_INFO_NUM_INT : RO ;bitpos:[12:0] ;default: 13'd48 ; */ +/*description: number of interrupt sources.*/ #define CLIC_INT_INFO_NUM_INT 0x00001FFF #define CLIC_INT_INFO_NUM_INT_M ((CLIC_INT_INFO_NUM_INT_V) << (CLIC_INT_INFO_NUM_INT_S)) #define CLIC_INT_INFO_NUM_INT_V 0x1FFF #define CLIC_INT_INFO_NUM_INT_S 0 -#define CLIC_INT_THRESH_REG (DR_REG_CLIC_BASE + 0x8) +#define CLIC_INT_THRESH_REG (DR_REG_CLIC_BASE + 0x8) /* CLIC_CPU_INT_THRESH : R/W ;bitpos:[31:24] ;default: 8'd0 ; */ -/*description: .*/ +/*description: Threshold for machine mode interruption..*/ #define CLIC_CPU_INT_THRESH 0x000000FF -#define CLIC_CPU_INT_THRESH_M ((CLIC_CPU_INT_THRESH_V) << (CLIC_CPU_INT_THRESH_S)) -#define CLIC_CPU_INT_THRESH_V 0xFF -#define CLIC_CPU_INT_THRESH_S 24 +#define CLIC_CPU_INT_THRESH_M ((CLIC_CPU_INT_THRESH_V) << (CLIC_CPU_INT_THRESH_S)) +#define CLIC_CPU_INT_THRESH_V 0xFF +#define CLIC_CPU_INT_THRESH_S 24 -#define CLIC_INT_CTRL_REG(i) (DR_REG_CLIC_CTRL_BASE + (i)*4) -/* CLIC_INT_CTL : R/W ;bitpos:[31:24] ;default: 8'd0 ; */ -/*description: .*/ -#define CLIC_INT_CTL 0x000000FF -#define CLIC_INT_CTL_M ((CLIC_INT_CTL_V) << (CLIC_INT_CTL_S)) -#define CLIC_INT_CTL_V 0xFF -#define CLIC_INT_CTL_S 24 +#define CLIC_INT_CTRL_REG(i) (DR_REG_CLIC_CTRL_BASE + (i)*4) +/* CLIC_INT_CTL : R/W ;bitpos:[31:24] ;default: 8'h1f ; */ +/*description: This register is used to indicate the priority of each interrupt +source participating in the arbitration, and at the same time to cooperate with +CLICCFG.nlbits to generate the interrupt priority to the CPU.*/ +#define CLIC_INT_CTL 0x000000FF +#define CLIC_INT_CTL_M ((CLIC_INT_CTL_V) << (CLIC_INT_CTL_S)) +#define CLIC_INT_CTL_V 0xFF +#define CLIC_INT_CTL_S 24 /* CLIC_INT_ATTR_MODE : R/W ;bitpos:[23:22] ;default: 2'b11 ; */ -/*description: .*/ -#define CLIC_INT_ATTR_MODE 0x00000003 -#define CLIC_INT_ATTR_MODE_M ((CLIC_INT_ATTR_MODE_V) << (CLIC_INT_ATTR_MODE_S)) -#define CLIC_INT_ATTR_MODE_V 0x3 -#define CLIC_INT_ATTR_MODE_S 22 +/*description: This field is used to configure the privileged mode of the interrupt. +0: user mode, 3: machine mode*/ +#define CLIC_INT_ATTR_MODE 0x00000003 +#define CLIC_INT_ATTR_MODE_M ((CLIC_INT_ATTR_MODE_V) << (CLIC_INT_ATTR_MODE_S)) +#define CLIC_INT_ATTR_MODE_V 0x3 +#define CLIC_INT_ATTR_MODE_S 22 /* CLIC_INT_ATTR_TRIG : R/W ;bitpos:[18:17] ;default: 2'd0 ; */ -/*description: .*/ -#define CLIC_INT_ATTR_TRIG 0x00000003 -#define CLIC_INT_ATTR_TRIG_M ((CLIC_INT_ATTR_TRIG_V) << (CLIC_INT_ATTR_TRIG_S)) -#define CLIC_INT_ATTR_TRIG_V 0x3 -#define CLIC_INT_ATTR_TRIG_S 17 +/*description: This field is used to distinguish pulse interruption and level +interruption. When trig[0] is 0, it means level interruption. When trig[0] is 1, +trig[1] is 0, it means interrupt on rising edge, and trig[1] is 1 means interrupt +on falling edge.*/ +#define CLIC_INT_ATTR_TRIG 0x00000003 +#define CLIC_INT_ATTR_TRIG_M ((CLIC_INT_ATTR_TRIG_V) << (CLIC_INT_ATTR_TRIG_S)) +#define CLIC_INT_ATTR_TRIG_V 0x3 +#define CLIC_INT_ATTR_TRIG_S 17 /* CLIC_INT_ATTR_SHV : R/W ;bitpos:[16] ;default: 1'd0 ; */ -/*description: .*/ -#define CLIC_INT_ATTR_SHV (BIT(16)) -#define CLIC_INT_ATTR_SHV_M (BIT(16)) -#define CLIC_INT_ATTR_SHV_V 0x1 -#define CLIC_INT_ATTR_SHV_S 16 +/*description: Represents whether the interrupt is a hardware vector interrupt.*/ +#define CLIC_INT_ATTR_SHV (BIT(16)) +#define CLIC_INT_ATTR_SHV_M (BIT(16)) +#define CLIC_INT_ATTR_SHV_V 0x1 +#define CLIC_INT_ATTR_SHV_S 16 /* CLIC_INT_IE : R/W ;bitpos:[8] ;default: 1'd0 ; */ -/*description: .*/ -#define CLIC_INT_IE (BIT(8)) -#define CLIC_INT_IE_M (BIT(8)) -#define CLIC_INT_IE_V 0x1 -#define CLIC_INT_IE_S 8 +/*description: Interrupt Enable Register.*/ +#define CLIC_INT_IE (BIT(8)) +#define CLIC_INT_IE_M (BIT(8)) +#define CLIC_INT_IE_V 0x1 +#define CLIC_INT_IE_S 8 /* CLIC_INT_IP : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: .*/ -#define CLIC_INT_IP (BIT(0)) -#define CLIC_INT_IP_M (BIT(0)) -#define CLIC_INT_IP_V 0x1 -#define CLIC_INT_IP_S 0 +/*description: Interrupt Pending Register. This bit has different set and clear logic in the +case of level interrupt and edge interrupt*/ +#define CLIC_INT_IP (BIT(0)) +#define CLIC_INT_IP_M (BIT(0)) +#define CLIC_INT_IP_V 0x1 +#define CLIC_INT_IP_S 0 // each of following registers are 8bits -#define BYTE_CLIC_INT_IP_REG(i) (DR_REG_CLIC_CTRL_BASE + (i)*4) +#define BYTE_CLIC_INT_IP_REG(i) (DR_REG_CLIC_CTRL_BASE + (i) * 4) /* BYTE_CLIC_INT_IP : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: .*/ -#define BYTE_CLIC_INT_IP (BIT(0)) -#define BYTE_CLIC_INT_IP_M (BIT(0)) -#define BYTE_CLIC_INT_IP_V 0x1 -#define BYTE_CLIC_INT_IP_S 0 +/*description: Interrupt Pending Register. This bit has different set and clear logic in the +case of level interrupt and edge interrupt*/ +#define BYTE_CLIC_INT_IP (BIT(0)) +#define BYTE_CLIC_INT_IP_M (BIT(0)) +#define BYTE_CLIC_INT_IP_V 0x1 +#define BYTE_CLIC_INT_IP_S 0 -#define BYTE_CLIC_INT_IE_REG(i) (DR_REG_CLIC_CTRL_BASE + 1 + (i)*4) +#define BYTE_CLIC_INT_IE_REG(i) (DR_REG_CLIC_CTRL_BASE + 1 + (i) * 4) /* BYTE_CLIC_INT_IE : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: .*/ -#define BYTE_CLIC_INT_IE (BIT(0)) -#define BYTE_CLIC_INT_IE_M (BIT(0)) -#define BYTE_CLIC_INT_IE_V 0x1 -#define BYTE_CLIC_INT_IE_S 0 +/*description: Interrupt Enable Register.*/ +#define BYTE_CLIC_INT_IE (BIT(0)) +#define BYTE_CLIC_INT_IE_M (BIT(0)) +#define BYTE_CLIC_INT_IE_V 0x1 +#define BYTE_CLIC_INT_IE_S 0 -#define BYTE_CLIC_INT_ATTR_REG(i) (DR_REG_CLIC_CTRL_BASE + 2 + (i)*4) +#define BYTE_CLIC_INT_ATTR_REG(i) (DR_REG_CLIC_CTRL_BASE + 2 + (i) * 4) /* BYTE_CLIC_INT_ATTR_SHV : R/W ;bitpos:[0] ;default: 1'd0 ; */ /*description: 1 means hardware vector interrupt.*/ -#define BYTE_CLIC_INT_ATTR_SHV (BIT(0)) -#define BYTE_CLIC_INT_ATTR_SHV_M (BIT(0)) -#define BYTE_CLIC_INT_ATTR_SHV_V 0x1 -#define BYTE_CLIC_INT_ATTR_SHV_S 0 +#define BYTE_CLIC_INT_ATTR_SHV (BIT(0)) +#define BYTE_CLIC_INT_ATTR_SHV_M (BIT(0)) +#define BYTE_CLIC_INT_ATTR_SHV_V 0x1 +#define BYTE_CLIC_INT_ATTR_SHV_S 0 /* BYTE_CLIC_INT_ATTR_TRIG: R/W ; bitpos:[2:1] ;default: 2'd0 ; */ /*description: [X0] -> level trigger [01] -> rising edge trigger [11] -> falling edge trigger */ -#define BYTE_CLIC_INT_ATTR_TRIG 0x00000003 -#define BYTE_CLIC_INT_ATTR_TRIG_M ((BYTE_CLIC_INT_ATTR_TRIG_V) << (BYTE_CLIC_INT_ATTR_TRIG_S)) -#define BYTE_CLIC_INT_ATTR_TRIG_V 0x3 -#define BYTE_CLIC_INT_ATTR_TRIG_S 1 +#define BYTE_CLIC_INT_ATTR_TRIG 0x00000003 +#define BYTE_CLIC_INT_ATTR_TRIG_M ((BYTE_CLIC_INT_ATTR_TRIG_V) << (BYTE_CLIC_INT_ATTR_TRIG_S)) +#define BYTE_CLIC_INT_ATTR_TRIG_V 0x3 +#define BYTE_CLIC_INT_ATTR_TRIG_S 1 /* BYTE_CLIC_INT_ATTR_MODE: R/W ; bitpos:[7:6] ;default: 2'd0 ; */ -/*description: privilege level for interrupt, fixed to 2'b11 */ -#define BYTE_CLIC_INT_ATTR_MODE 0x00000003 -#define BYTE_CLIC_INT_ATTR_MODE_M ((BYTE_CLIC_INT_ATTR_MODE_V) << (BYTE_CLIC_INT_ATTR_MODE_S)) -#define BYTE_CLIC_INT_ATTR_MODE_V 0x3 -#define BYTE_CLIC_INT_ATTR_MODE_S 6 +/*description: privilege level for interrupt, 0: user mode, 3: machine mode */ +#define BYTE_CLIC_INT_ATTR_MODE 0x00000003 +#define BYTE_CLIC_INT_ATTR_MODE_M ((BYTE_CLIC_INT_ATTR_MODE_V) << (BYTE_CLIC_INT_ATTR_MODE_S)) +#define BYTE_CLIC_INT_ATTR_MODE_V 0x3 +#define BYTE_CLIC_INT_ATTR_MODE_S 6 -#define BYTE_CLIC_INT_CTL_REG(i) (DR_REG_CLIC_CTRL_BASE + 3 + (i)*4) +#define BYTE_CLIC_INT_CTL_REG(i) (DR_REG_CLIC_CTRL_BASE + 3 + (i) * 4) /* BYTE_CLIC_INT_ATTR_MODE: R/W ; bitpos:[7:5] ;default: 3'd0 ; */ /*description: interrupt priority */ -#define BYTE_CLIC_INT_CTL 0x00000007 -#define BYTE_CLIC_INT_CTL_M ((BYTE_CLIC_INT_CTL_V) << (BYTE_CLIC_INT_CTL_S)) -#define BYTE_CLIC_INT_CTL_V 0x7 -#define BYTE_CLIC_INT_CTL_S 5 +#define BYTE_CLIC_INT_CTL 0x00000007 +#define BYTE_CLIC_INT_CTL_M ((BYTE_CLIC_INT_CTL_V) << (BYTE_CLIC_INT_CTL_S)) +#define BYTE_CLIC_INT_CTL_V 0x7 +#define BYTE_CLIC_INT_CTL_S 5 #ifdef __cplusplus } diff --git a/components/soc/esp32c61/temperature_sensor_periph.c b/components/soc/esp32c61/temperature_sensor_periph.c index dc9467387208..2b107dc91e98 100644 --- a/components/soc/esp32c61/temperature_sensor_periph.c +++ b/components/soc/esp32c61/temperature_sensor_periph.c @@ -8,8 +8,9 @@ #include "soc/regdma.h" #include "soc/temperature_sensor_periph.h" #include "soc/apb_saradc_reg.h" +#include "esp_attr.h" -const temperature_sensor_attribute_t temperature_sensor_attributes[TEMPERATURE_SENSOR_ATTR_RANGE_NUM] = { +DRAM_ATTR temperature_sensor_attribute_t temperature_sensor_attributes[TEMPERATURE_SENSOR_ATTR_RANGE_NUM] = { /*Offset reg_val min max error */ {-2, 5, 50, 125, 3}, {-1, 7, 20, 100, 2}, diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index c88a1151b5d2..ef1882ffbca8 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -179,6 +179,10 @@ config SOC_BOD_SUPPORTED bool default y +config SOC_VBAT_SUPPORTED + bool + default y + config SOC_APM_SUPPORTED bool default y @@ -255,6 +259,10 @@ config SOC_AES_SUPPORT_AES_256 bool default y +config SOC_AES_SUPPORT_PSEUDO_ROUND_FUNCTION + bool + default y + config SOC_ADC_DIG_CTRL_SUPPORTED bool default y @@ -1287,6 +1295,10 @@ config SOC_FLASH_ENCRYPTION_XTS_AES_128 bool default y +config SOC_FLASH_ENCRYPTION_XTS_AES_SUPPORT_PSEUDO_ROUND + bool + default y + config SOC_APM_CTRL_FILTER_SUPPORTED bool default y @@ -1295,6 +1307,10 @@ config SOC_CRYPTO_DPA_PROTECTION_SUPPORTED bool default y +config SOC_ECC_CONSTANT_TIME_POINT_MUL + bool + default y + config SOC_ECDSA_USES_MPI bool default y diff --git a/components/soc/esp32h2/include/soc/chip_rev.h b/components/soc/esp32h2/include/soc/chip_rev.h new file mode 100644 index 000000000000..87da4a43c092 --- /dev/null +++ b/components/soc/esp32h2/include/soc/chip_rev.h @@ -0,0 +1,13 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "soc/efuse_struct.h" + +#define ESP_SOC_GET_CHIP_REV (EFUSE.rd_mac_sys_3.wafer_version_major * 100 + EFUSE.rd_mac_sys_3.wafer_version_minor) + +#define REG_COMPATIBLE_ADDR(rev, before_addr, after_addr) ((ESP_SOC_GET_CHIP_REV >= (rev)) ? (after_addr) : (before_addr)) diff --git a/components/soc/esp32h2/include/soc/ecdsa_struct.h b/components/soc/esp32h2/include/soc/ecdsa_struct.h new file mode 100644 index 000000000000..9457cb32b0c9 --- /dev/null +++ b/components/soc/esp32h2/include/soc/ecdsa_struct.h @@ -0,0 +1,53 @@ +/** + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#ifdef __cplusplus +extern "C" { +#endif + +#include "soc/ecdsa_rev_0_0_struct.h" +#include "soc/ecdsa_rev_1_2_struct.h" + +/** + * @brief Compatible ecdsa struct wrapper + * + */ +typedef union { + volatile ecdsa_dev_rev_0_0_t rev_0_0; + volatile ecdsa_dev_rev_1_2_t rev_1_2; +} ecdsa_dev_t; + +extern ecdsa_dev_t ECDSA; + +/* Note: For ECDSA register on ESP32-H2, you need to use the ECDSA struct through + * ECDSA_REG_GET and ECDSA_REG_SET to access the ECDSA peripheral register and its fields respectively. + * For e.g., ECDSA_REG_SET(ECDSA.clk.clk_gate_force_on, enable) is used to set the register value. + * The ECDSA struct should not be referenced directly. + */ + +/** The ECDSA date version of chip revision 1.2*/ +#define ECDSA_REV1_2_DATE (0x2403120) + +/** + * @brief Set the register value compatibly + * @param reg The register to set + * @param val The value to set + */ +#define ECDSA_REG_SET(reg, val) (ECDSA.rev_1_2.date.ecdsa_date >= ECDSA_REV1_2_DATE ? \ + (ECDSA.rev_1_2.reg = (val)) : (ECDSA.rev_0_0.reg = (val))) + +/** + * @brief Get the register value compatibly + * @param reg The register to get + */ +#define ECDSA_REG_GET(reg) (ECDSA.rev_1_2.date.ecdsa_date >= ECDSA_REV1_2_DATE ? \ + (ECDSA.rev_1_2.reg) : (ECDSA.rev_0_0.reg)) + +#ifdef __cplusplus +} +#endif diff --git a/components/soc/esp32h2/include/soc/lpperi_struct.h b/components/soc/esp32h2/include/soc/lpperi_struct.h index 40c20b7686b4..f450ede75c10 100644 --- a/components/soc/esp32h2/include/soc/lpperi_struct.h +++ b/components/soc/esp32h2/include/soc/lpperi_struct.h @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -/* For compatibility of ECO0 and ECO5 */ +/* This is a wrapper for revisions compatibility */ #pragma once @@ -17,31 +17,33 @@ extern "C" { #endif /** - * @brief Compatible lpperi struct for ECO0-ECO4 and ECO5 + * @brief Compatible lpperi struct wrapper * */ -typedef struct { - volatile lpperi_clk_en_reg_t *clk_en; - volatile lpperi_reset_en_reg_t *reset_en; - volatile lpperi_rng_cfg_reg_t *rng_cfg; - volatile lpperi_rng_data_reg_t *rng_data; - volatile lpperi_cpu_reg_t *cpu; - volatile lpperi_bus_timeout_reg_t *bus_timeout; - volatile lpperi_bus_timeout_addr_reg_t *bus_timeout_addr; - volatile lpperi_bus_timeout_uid_reg_t *bus_timeout_uid; - volatile lpperi_mem_ctrl_reg_t *mem_ctrl; - volatile lpperi_interrupt_source_reg_t *interrupt_source; - volatile lpperi_debug_sel0_reg_t *debug_sel0; - volatile lpperi_debug_sel1_reg_t *debug_sel1; - volatile lpperi_date_reg_t *date; +typedef union { + volatile lpperi_rev0_0_dev_t rev0_0; /* Struct for LPPERI v0.0 < rev < v1.2 */ + volatile lpperi_rev1_2_dev_t rev1_2; /* Struct for LPPERI rev >= v1.2*/ } lpperi_dev_t; -extern lpperi_dev_t LPPERI; // Compatible instance that achieved in 'lpperi_struct.c' +extern lpperi_dev_t LPPERI; + +/** The LPPERI date version of chip revision 1.2*/ +#define LPPERI_REV1_2_DATE (0x2308030) + +/** + * @brief Set the register value compatibly + * @param reg The register to set (can carry the field, like clk_en.lp_io_ck_en) + * @param val The value to set + */ +#define LPPERI_REG_SET(reg, val) (LPPERI.rev1_2.date.lpperi_date >= LPPERI_REV1_2_DATE ? \ + (LPPERI.rev1_2.reg = (val)) : (LPPERI.rev0_0.reg = (val))) /** - * @brief Initialize the LP_PERI register address according to the register version + * @brief Get the register value compatibly + * @param reg The register to get (can carry the field, like clk_en.lp_io_ck_en) */ -void lpperi_compatible_reg_addr_init(void); +#define LPPERI_REG_GET(reg) (LPPERI.rev1_2.date.lpperi_date >= LPPERI_REV1_2_DATE ? \ + (LPPERI.rev1_2.reg) : (LPPERI.rev0_0.reg)) #ifdef __cplusplus } diff --git a/components/soc/esp32h2/include/soc/regi2c_brownout.h b/components/soc/esp32h2/include/soc/regi2c_brownout.h index 0d2caf531c15..200894c86ac0 100644 --- a/components/soc/esp32h2/include/soc/regi2c_brownout.h +++ b/components/soc/esp32h2/include/soc/regi2c_brownout.h @@ -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 */ @@ -19,12 +19,12 @@ #define I2C_BOD I2C_PMU #define I2C_BOD_HOSTID I2C_PMU_HOSTID -#define I2C_PMU_OR_DREFL_VBAT 17 -#define I2C_PMU_OR_DREFL_VBAT_MSB 4 -#define I2C_PMU_OR_DREFL_VBAT_LSB 2 -#define I2C_PMU_OR_DREFH_VBAT 17 -#define I2C_PMU_OR_DREFH_VBAT_MSB 7 -#define I2C_PMU_OR_DREFH_VBAT_LSB 5 +#define I2C_PMU_OR_DREF_VBAT_L 17 +#define I2C_PMU_OR_DREF_VBAT_L_MSB 4 +#define I2C_PMU_OR_DREF_VBAT_L_LSB 2 +#define I2C_PMU_OR_DREF_VBAT_H 17 +#define I2C_PMU_OR_DREF_VBAT_H_MSB 7 +#define I2C_PMU_OR_DREF_VBAT_H_LSB 5 #define I2C_PMU_OR_XPD_DIGDET 18 #define I2C_PMU_OR_XPD_DIGDET_MSB 0 @@ -44,6 +44,22 @@ #define I2C_PMU_OR_DREFH_VDDA_MSB 7 #define I2C_PMU_OR_DREFH_VDDA_LSB 5 +#define I2C_BIAS_OR_DREF_VBAT_CHARGER_L 20 +#define I2C_BIAS_OR_DREF_VBAT_CHARGER_L_MSB 4 +#define I2C_BIAS_OR_DREF_VBAT_CHARGER_L_LSB 2 +#define I2C_BIAS_OR_DREF_VBAT_CHARGER_H 20 +#define I2C_BIAS_OR_DREF_VBAT_CHARGER_H_MSB 7 +#define I2C_BIAS_OR_DREF_VBAT_CHARGER_H_LSB 5 + +#define I2C_BIAS_OR_FORCE_PU_VBAT_CHARGER 20 +#define I2C_BIAS_OR_FORCE_PU_VBAT_CHARGER_MSB 0 +#define I2C_BIAS_OR_FORCE_PU_VBAT_CHARGER_LSB 0 + +/** Change the charging current by adjusting the value of the series resistor. 1kΩ + N * 0.5kΩ */ +#define I2C_BIAS_OR_DRES_CHARGER 15 +#define I2C_BIAS_OR_DRES_CHARGER_MSB 7 +#define I2C_BIAS_OR_DRES_CHARGER_LSB 4 + #define I2C_BOD_THRESHOLD_L I2C_PMU_OR_DREFL_VDDA #define I2C_BOD_THRESHOLD_L_MSB I2C_PMU_OR_DREFL_VDDA_MSB #define I2C_BOD_THRESHOLD_L_LSB I2C_PMU_OR_DREFL_VDDA_LSB diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index 7bfcd16fc2e4..40e199d1dbc9 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -77,6 +77,7 @@ #define SOC_FLASH_ENC_SUPPORTED 1 #define SOC_SECURE_BOOT_SUPPORTED 1 #define SOC_BOD_SUPPORTED 1 +#define SOC_VBAT_SUPPORTED 1 #define SOC_APM_SUPPORTED 1 /*!< Support for APM peripheral */ #define SOC_PMU_SUPPORTED 1 #define SOC_LP_TIMER_SUPPORTED 1 @@ -104,6 +105,8 @@ #define SOC_AES_SUPPORT_AES_128 (1) #define SOC_AES_SUPPORT_AES_256 (1) +#define SOC_AES_SUPPORT_PSEUDO_ROUND_FUNCTION (1) /*!< Only avliable in chip version above 1.2*/ + /*-------------------------- ADC CAPS -------------------------------*/ /*!< SAR ADC Module*/ #define SOC_ADC_DIG_CTRL_SUPPORTED 1 @@ -510,6 +513,7 @@ #define SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX (64) #define SOC_FLASH_ENCRYPTION_XTS_AES 1 #define SOC_FLASH_ENCRYPTION_XTS_AES_128 1 +#define SOC_FLASH_ENCRYPTION_XTS_AES_SUPPORT_PSEUDO_ROUND 1 /*!< Only avliable in chip version above 1.2*/ /*-------------------------- APM CAPS ----------------------------------------*/ #define SOC_APM_CTRL_FILTER_SUPPORTED 1 /*!< Support for APM control filter */ @@ -517,9 +521,11 @@ /*------------------------ Anti DPA (Security) CAPS --------------------------*/ #define SOC_CRYPTO_DPA_PROTECTION_SUPPORTED 1 +/*--------------------------- ECC CAPS ---------------------------------------*/ +#define SOC_ECC_CONSTANT_TIME_POINT_MUL 1 + /*------------------------- ECDSA CAPS -------------------------*/ #define SOC_ECDSA_USES_MPI (1) - /*-------------------------- UART CAPS ---------------------------------------*/ // ESP32-H2 has 2 UARTs #define SOC_UART_NUM (2) diff --git a/components/soc/esp32h2/include/soc/system_intr.h b/components/soc/esp32h2/include/soc/system_intr.h new file mode 100644 index 000000000000..9f7be4017249 --- /dev/null +++ b/components/soc/esp32h2/include/soc/system_intr.h @@ -0,0 +1,12 @@ +/** + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +// Maps misc system interrupt to hardware interrupt names +#define SYS_CPU_INTR_FROM_CPU_0_SOURCE ETS_FROM_CPU_INTR0_SOURCE + +#define SYS_TG0_WDT_INTR_SOURCE ETS_TG0_WDT_LEVEL_INTR_SOURCE +#define SYS_TG1_WDT_INTR_SOURCE ETS_TG1_WDT_LEVEL_INTR_SOURCE diff --git a/components/soc/esp32h2/ld/esp32h2.peripherals.ld b/components/soc/esp32h2/ld/esp32h2.peripherals.ld index 59ecdedb6d59..6c8740507f88 100644 --- a/components/soc/esp32h2/ld/esp32h2.peripherals.ld +++ b/components/soc/esp32h2/ld/esp32h2.peripherals.ld @@ -40,7 +40,7 @@ PROVIDE ( RSA = 0x6008A000 ); PROVIDE ( ECC = 0x6008B000 ); PROVIDE ( DS = 0x6008C000 ); PROVIDE ( HMAC = 0x6008D000 ); - +PROVIDE ( ECDSA = 0x6008E000 ); PROVIDE ( IO_MUX = 0x60090000 ); PROVIDE ( GPIO = 0x60091000 ); PROVIDE ( GPIO_EXT = 0x60091f00 ); @@ -66,8 +66,7 @@ PROVIDE ( LP_TIMER = 0x600B0C00 ); PROVIDE ( LP_AON = 0x600B1000 ); PROVIDE ( LP_WDT = 0x600B1C00 ); PROVIDE ( I2C_ANA_MST = 0x600B2400 ); -PROVIDE ( LPPERI_REV0_0 = 0x600B2800 ); -PROVIDE ( LPPERI_REV1_2 = 0x600B2800 ); +PROVIDE ( LPPERI = 0x600B2800 ); PROVIDE ( LP_ANA_PERI = 0x600B2C00 ); PROVIDE ( LP_APM = 0x600B3800 ); PROVIDE ( OTP_DEBUG = 0x600B3C00 ); diff --git a/components/soc/esp32h2/lpperi_struct.c b/components/soc/esp32h2/lpperi_struct.c deleted file mode 100644 index ea396eec9d50..000000000000 --- a/components/soc/esp32h2/lpperi_struct.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include -#include "assert.h" -#include "soc/lpperi_struct.h" - -#define LPPERI_REV1_2_DATE (0x2308030) -#define LPPERI_REG_ADDR(reg) ((LPPERI_REV1_2.date.lpperi_date >= LPPERI_REV1_2_DATE) ? \ - &LPPERI_REV1_2.reg : \ - (volatile typeof(LPPERI_REV1_2.reg) *)&LPPERI_REV0_0.reg) - -/** - * @brief Compatible LPPERI instance - * @note Set NULL as default so that to abort when use the LPPEIR before initialization - * If you want to use the LPPERI before it is initialized, please use `lpperi_reg.h` instead - */ -lpperi_dev_t LPPERI = {}; - -/** - * @brief Initialize the LP_PERI register address according to the register version - */ -void lpperi_compatible_reg_addr_init(void) -{ - LPPERI.clk_en = LPPERI_REG_ADDR(clk_en); - LPPERI.reset_en = LPPERI_REG_ADDR(reset_en); - LPPERI.rng_cfg = ((LPPERI_REV1_2.date.lpperi_date >= LPPERI_REV1_2_DATE) ? &LPPERI_REV1_2.rng_cfg : NULL); - LPPERI.rng_data = LPPERI_REG_ADDR(rng_data); - LPPERI.cpu = LPPERI_REG_ADDR(cpu); - LPPERI.bus_timeout = LPPERI_REG_ADDR(bus_timeout); - LPPERI.bus_timeout_addr = LPPERI_REG_ADDR(bus_timeout_addr); - LPPERI.bus_timeout_uid = LPPERI_REG_ADDR(bus_timeout_uid); - LPPERI.mem_ctrl = LPPERI_REG_ADDR(mem_ctrl); - LPPERI.interrupt_source = LPPERI_REG_ADDR(interrupt_source); - LPPERI.debug_sel0 = LPPERI_REG_ADDR(debug_sel0); - LPPERI.debug_sel1 = LPPERI_REG_ADDR(debug_sel1); - LPPERI.date = LPPERI_REG_ADDR(date); -} - -__attribute__((constructor)) -static void s_lpperi_compatible_init_check(void) -{ - // Make sure it is initialized - assert(LPPERI.clk_en != NULL); -} diff --git a/components/soc/esp32h2/register/soc/aes_reg.h b/components/soc/esp32h2/register/soc/aes_reg.h index c096489ca4bc..bf09b4b34a57 100644 --- a/components/soc/esp32h2/register/soc/aes_reg.h +++ b/components/soc/esp32h2/register/soc/aes_reg.h @@ -1,5 +1,5 @@ /** - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -412,6 +412,63 @@ extern "C" { #define AES_DMA_EXIT_V 0x00000001U #define AES_DMA_EXIT_S 0 +/** AES_RX_RESET_REG register + * AES-DMA reset rx-fifo register + */ +#define AES_RX_RESET_REG (DR_REG_AES_BASE + 0xc0) +/** AES_RX_RESET : WT; bitpos: [0]; default: 0; + * Set this bit to reset rx_fifo under dma_aes working mode. + */ +#define AES_RX_RESET (BIT(0)) +#define AES_RX_RESET_M (AES_RX_RESET_V << AES_RX_RESET_S) +#define AES_RX_RESET_V 0x00000001U +#define AES_RX_RESET_S 0 + +/** AES_TX_RESET_REG register + * AES-DMA reset tx-fifo register + */ +#define AES_TX_RESET_REG (DR_REG_AES_BASE + 0xc4) +/** AES_TX_RESET : WT; bitpos: [0]; default: 0; + * Set this bit to reset tx_fifo under dma_aes working mode. + */ +#define AES_TX_RESET (BIT(0)) +#define AES_TX_RESET_M (AES_TX_RESET_V << AES_TX_RESET_S) +#define AES_TX_RESET_V 0x00000001U +#define AES_TX_RESET_S 0 + +/** AES_PSEUDO_REG register + * AES PSEUDO function configure register + */ +#define AES_PSEUDO_REG (DR_REG_AES_BASE + 0xd0) +/** AES_PSEUDO_EN : R/W; bitpos: [0]; default: 0; + * This bit decides whether the pseudo round function is enable or not. + */ +#define AES_PSEUDO_EN (BIT(0)) +#define AES_PSEUDO_EN_M (AES_PSEUDO_EN_V << AES_PSEUDO_EN_S) +#define AES_PSEUDO_EN_V 0x00000001U +#define AES_PSEUDO_EN_S 0 +/** AES_PSEUDO_BASE : R/W; bitpos: [4:1]; default: 2; + * Those bits decides the basic number of pseudo round number. + */ +#define AES_PSEUDO_BASE 0x0000000FU +#define AES_PSEUDO_BASE_M (AES_PSEUDO_BASE_V << AES_PSEUDO_BASE_S) +#define AES_PSEUDO_BASE_V 0x0000000FU +#define AES_PSEUDO_BASE_S 1 +/** AES_PSEUDO_INC : R/W; bitpos: [6:5]; default: 2; + * Those bits decides the increment number of pseudo round number + */ +#define AES_PSEUDO_INC 0x00000003U +#define AES_PSEUDO_INC_M (AES_PSEUDO_INC_V << AES_PSEUDO_INC_S) +#define AES_PSEUDO_INC_V 0x00000003U +#define AES_PSEUDO_INC_S 5 +/** AES_PSEUDO_RNG_CNT : R/W; bitpos: [9:7]; default: 7; + * Those bits decides the update frequency of the pseudo-key. + */ +#define AES_PSEUDO_RNG_CNT 0x00000007U +#define AES_PSEUDO_RNG_CNT_M (AES_PSEUDO_RNG_CNT_V << AES_PSEUDO_RNG_CNT_S) +#define AES_PSEUDO_RNG_CNT_V 0x00000007U +#define AES_PSEUDO_RNG_CNT_S 7 + #ifdef __cplusplus } #endif diff --git a/components/soc/esp32h2/register/soc/aes_struct.h b/components/soc/esp32h2/register/soc/aes_struct.h index 716d9a5abdaf..55474adf3564 100644 --- a/components/soc/esp32h2/register/soc/aes_struct.h +++ b/components/soc/esp32h2/register/soc/aes_struct.h @@ -1,5 +1,5 @@ /** - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -398,6 +398,61 @@ typedef union { uint32_t val; } aes_dma_exit_reg_t; +/** Type of rx_reset register + * AES-DMA reset rx-fifo register + */ +typedef union { + struct { + /** rx_reset : WT; bitpos: [0]; default: 0; + * Set this bit to reset rx_fifo under dma_aes working mode. + */ + uint32_t rx_reset:1; + uint32_t reserved_1:31; + }; + uint32_t val; +} aes_rx_reset_reg_t; + +/** Type of tx_reset register + * AES-DMA reset tx-fifo register + */ +typedef union { + struct { + /** tx_reset : WT; bitpos: [0]; default: 0; + * Set this bit to reset tx_fifo under dma_aes working mode. + */ + uint32_t tx_reset:1; + uint32_t reserved_1:31; + }; + uint32_t val; +} aes_tx_reset_reg_t; + + +/** Group: Configuration register */ +/** Type of pseudo register + * AES PSEUDO function configure register + */ +typedef union { + struct { + /** pseudo_en : R/W; bitpos: [0]; default: 0; + * This bit decides whether the pseudo round function is enable or not. + */ + uint32_t pseudo_en:1; + /** pseudo_base : R/W; bitpos: [4:1]; default: 2; + * Those bits decides the basic number of pseudo round number. + */ + uint32_t pseudo_base:4; + /** pseudo_inc : R/W; bitpos: [6:5]; default: 2; + * Those bits decides the increment number of pseudo round number + */ + uint32_t pseudo_inc:2; + /** pseudo_rng_cnt : R/W; bitpos: [9:7]; default: 7; + * Those bits decides the update frequency of the pseudo-key. + */ + uint32_t pseudo_rng_cnt:3; + uint32_t reserved_10:22; + }; + uint32_t val; +} aes_pseudo_reg_t; /** Group: memory type */ @@ -483,12 +538,17 @@ typedef struct { volatile aes_int_ena_reg_t int_ena; volatile aes_date_reg_t date; volatile aes_dma_exit_reg_t dma_exit; + uint32_t reserved_0bc; + volatile aes_rx_reset_reg_t rx_reset; + volatile aes_tx_reset_reg_t tx_reset; + uint32_t reserved_0c8[2]; + volatile aes_pseudo_reg_t pseudo; } aes_dev_t; extern aes_dev_t AES; #ifndef __cplusplus -_Static_assert(sizeof(aes_dev_t) == 0xbc, "Invalid size of aes_dev_t structure"); +_Static_assert(sizeof(aes_dev_t) == 0xd4, "Invalid size of aes_dev_t structure"); #endif #ifdef __cplusplus diff --git a/components/soc/esp32h2/register/soc/ecdsa_reg.h b/components/soc/esp32h2/register/soc/ecdsa_reg.h index 88f19ad16ce0..d3d0cf908d57 100644 --- a/components/soc/esp32h2/register/soc/ecdsa_reg.h +++ b/components/soc/esp32h2/register/soc/ecdsa_reg.h @@ -1,5 +1,5 @@ /** - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -7,208 +7,388 @@ #include #include "soc/soc.h" +#include "soc/chip_rev.h" + #ifdef __cplusplus extern "C" { #endif + +/** Version register */ + +/** ECDSA_DATE_REG register + * Version control + * register + */ +#define ECDSA_DATE_REG (DR_REG_ECDSA_BASE + 0xfc) +/* ECDSA_DATE : R/W; bitpos: [28:0]; default: 35684752 (0x21FFB30) for rev 0.0; + * ECDSA_DATE : R/W; bitpos: [28:0]; default: 37761312 (0x2403120) for rev 1.2; + * ECDSA version control + * register + */ +#define ECDSA_DATE 0x0FFFFFFFU +#define ECDSA_DATE_M (ECDSA_DATE_V << ECDSA_DATE_S) +#define ECDSA_DATE_V 0x0FFFFFFFU +#define ECDSA_DATE_S 0 + +/** + * @brief Get the correct value of a field according to the register version + * @note ESP32-H2 v1.2 updated the register ECDSA_DATE_REG to a new version, + * At the same time the value of some registers was changed + * This macro can help to get the correct value of a field according to the register version + ** @param old: the value of the field for the old version where DATE == 0x021FFB30 (rev 0.0) + * @param new: the value of the field for the new version where DATE == 0x2403120 (rev 1.2) + */ +#define ECDSA_REG_GET_OFFSET(old, new) (REG_GET_FIELD(ECDSA_DATE_REG, ECDSA_DATE) >= 0x02403120 ? (new) : (old)) + +/** Configuration registers */ + /** ECDSA_CONF_REG register - * ECDSA configure register + * ECDSA configure + * register */ #define ECDSA_CONF_REG (DR_REG_ECDSA_BASE + 0x4) -/** ECDSA_WORK_MODE : R/W; bitpos: [0]; default: 0; - * The work mode bits of ECDSA Accelerator. 0: Signature Verify mode. 1: Signature - * Generate Mode. - */ -#define ECDSA_WORK_MODE (BIT(0)) + +/* ECDSA_WORK_MODE : R/W; + * bitpos: [0]; default: 0; for DATE == 0x21FFB30 (rev 0.0) + * bitpos: [1:0]; default: 0; for DATE == 0x2403120 (rev 1.2) + * The work mode bits of ECDSA Accelerator. + * 0: Signature Generate Mode. + * 1: Signature Verify Mode. + * 2: Export public key Mode. (only available for DATE == 0x2403120 (rev 1.2)) + * 3: Invalid mode. (only available for DATE == 0x2403120 (rev 1.2)) + */ +#define ECDSA_WORK_MODE ECDSA_REG_GET_OFFSET(BIT(0), 0x00000003U) #define ECDSA_WORK_MODE_M (ECDSA_WORK_MODE_V << ECDSA_WORK_MODE_S) -#define ECDSA_WORK_MODE_V 0x00000001U +#define ECDSA_WORK_MODE_V ECDSA_REG_GET_OFFSET(0x00000001U, 0x00000003U) #define ECDSA_WORK_MODE_S 0 -/** ECDSA_ECC_CURVE : R/W; bitpos: [1]; default: 0; - * The ecc curve select bit of ECDSA Accelerator. 0: P-192. 1: P-256. + +/* ECDSA_ECC_CURVE : R/W; + * bitpos: [1]; default: 0; for DATE == 0x21FFB30 (rev 0.0) + * bitpos: [2]; default: 0; for DATE == 0x2403120 (rev 1.2) + * The ecc curve select bit of ECDSA Accelerator. + * 0: P-192. 1: P-256. */ -#define ECDSA_ECC_CURVE (BIT(1)) +#define ECDSA_ECC_CURVE ECDSA_REG_GET_OFFSET(BIT(1), BIT(2)) #define ECDSA_ECC_CURVE_M (ECDSA_ECC_CURVE_V << ECDSA_ECC_CURVE_S) #define ECDSA_ECC_CURVE_V 0x00000001U -#define ECDSA_ECC_CURVE_S 1 -/** ECDSA_SOFTWARE_SET_K : R/W; bitpos: [2]; default: 0; - * The source of k select bit. 0: k is automatically generated by TRNG. 1: k is - * written by software. +#define ECDSA_ECC_CURVE_S ECDSA_REG_GET_OFFSET(1, 2) +/* ECDSA_SOFTWARE_SET_K : R/W; bitpos: [2]; default: 0; + * The source of k select bit. 0: k is automatically generated by TRNG. 1: + * k is written by + * software. */ -#define ECDSA_SOFTWARE_SET_K (BIT(2)) +#define ECDSA_SOFTWARE_SET_K ECDSA_REG_GET_OFFSET(BIT(2), BIT(3)) #define ECDSA_SOFTWARE_SET_K_M (ECDSA_SOFTWARE_SET_K_V << ECDSA_SOFTWARE_SET_K_S) #define ECDSA_SOFTWARE_SET_K_V 0x00000001U -#define ECDSA_SOFTWARE_SET_K_S 2 -/** ECDSA_SOFTWARE_SET_Z : R/W; bitpos: [3]; default: 0; - * The source of z select bit. 0: z is generated from SHA result. 1: z is written by - * software. +#define ECDSA_SOFTWARE_SET_K_S ECDSA_REG_GET_OFFSET(2, 3) + +/* ECDSA_SOFTWARE_SET_Z : R/W; bitpos: [3]; default: 0; + * The source of z select bit. 0: z is generated from SHA result. 1: z is + * written by + * software. */ -#define ECDSA_SOFTWARE_SET_Z (BIT(3)) +#define ECDSA_SOFTWARE_SET_Z ECDSA_REG_GET_OFFSET(BIT(3), BIT(4)) #define ECDSA_SOFTWARE_SET_Z_M (ECDSA_SOFTWARE_SET_Z_V << ECDSA_SOFTWARE_SET_Z_S) #define ECDSA_SOFTWARE_SET_Z_V 0x00000001U -#define ECDSA_SOFTWARE_SET_Z_S 3 +#define ECDSA_SOFTWARE_SET_Z_S ECDSA_REG_GET_OFFSET(3, 4) + +/* ECDSA_K_DETERMINISTIC : R/W; bitpos: [5]; default: 0; + * The source of k select bit. 0: k is generated from TRNG. 1: k is + * written by + * software. + */ +#define ECDSA_DETERMINISTIC_K (BIT(5)) +#define ECDSA_DETERMINISTIC_K_M (ECDSA_DETERMINISTIC_K_V << ECDSA_DETERMINISTIC_K_S) +#define ECDSA_DETERMINISTIC_K_V 0x00000001U +#define ECDSA_DETERMINISTIC_K_S 5 + + +/** Clock and reset registers */ /** ECDSA_CLK_REG register - * ECDSA clock gate register + * ECDSA clock gate + * register */ #define ECDSA_CLK_REG (DR_REG_ECDSA_BASE + 0x8) -/** ECDSA_CLK_GATE_FORCE_ON : R/W; bitpos: [0]; default: 0; - * Write 1 to force on register clock gate. +/* ECDSA_CLK_GATE_FORCE_ON : R/W; bitpos: [0]; default: 0; + * Write 1 to force on register clock + * gate. */ #define ECDSA_CLK_GATE_FORCE_ON (BIT(0)) #define ECDSA_CLK_GATE_FORCE_ON_M (ECDSA_CLK_GATE_FORCE_ON_V << ECDSA_CLK_GATE_FORCE_ON_S) #define ECDSA_CLK_GATE_FORCE_ON_V 0x00000001U #define ECDSA_CLK_GATE_FORCE_ON_S 0 + +/** Interrupt registers */ + /** ECDSA_INT_RAW_REG register - * ECDSA interrupt raw register, valid in level. + * ECDSA interrupt raw register, valid in + * level. */ #define ECDSA_INT_RAW_REG (DR_REG_ECDSA_BASE + 0xc) -/** ECDSA_CALC_DONE_INT_RAW : RO/WTC/SS; bitpos: [0]; default: 0; - * The raw interrupt status bit for the ecdsa_calc_done_int interrupt - */ -#define ECDSA_CALC_DONE_INT_RAW (BIT(0)) -#define ECDSA_CALC_DONE_INT_RAW_M (ECDSA_CALC_DONE_INT_RAW_V << ECDSA_CALC_DONE_INT_RAW_S) -#define ECDSA_CALC_DONE_INT_RAW_V 0x00000001U -#define ECDSA_CALC_DONE_INT_RAW_S 0 -/** ECDSA_SHA_RELEASE_INT_RAW : RO/WTC/SS; bitpos: [1]; default: 0; - * The raw interrupt status bit for the ecdsa_sha_release_int interrupt + +/* ECDSA_PREP_DONE_INT_RAW : RO/WTC/SS; bitpos: [0]; default: 0; + * The raw interrupt status bit for the ecdsa_prep_done_int + * interrupt + * This bit was named as ECDSA_CALC_DONE_INT_RAW in rev 0.0 and changed to ECDSA_PREP_DONE_INT_RAW in rev 1.2 + * functionality is the same + */ +#define ECDSA_PREP_DONE_INT_RAW (BIT(0)) +#define ECDSA_PREP_DONE_INT_RAW_M (ECDSA_PREP_DONE_INT_RAW_V << ECDSA_PREP_DONE_INT_RAW_S) +#define ECDSA_PREP_DONE_INT_RAW_V 0x00000001U +#define ECDSA_PREP_DONE_INT_RAW_S 0 + +/* ECDSA_PROC_DONE_INT_RAW : RO/WTC/SS; bitpos: [1]; default: 0; + * The raw interrupt status bit for the ecdsa_proc_done_int + * interrupt + * This bit is only available for DATE == 0x2403120 (rev 1.2) + */ +#define ECDSA_PROC_DONE_INT_RAW (BIT(1)) +#define ECDSA_PROC_DONE_INT_RAW_M (ECDSA_PROC_DONE_INT_RAW_V << ECDSA_PROC_DONE_INT_RAW_S) +#define ECDSA_PROC_DONE_INT_RAW_V 0x00000001U +#define ECDSA_PROC_DONE_INT_RAW_S 1 + +/* ECDSA_POST_DONE_INT_RAW : RO/WTC/SS; bitpos: [2]; default: 0; + * The raw interrupt status bit for the ecdsa_post_done_int + * interrupt + * This bit is only available for DATE == 0x2403120 (rev 1.2) + */ +#define ECDSA_POST_DONE_INT_RAW (BIT(2)) +#define ECDSA_POST_DONE_INT_RAW_M (ECDSA_POST_DONE_INT_RAW_V << ECDSA_POST_DONE_INT_RAW_S) +#define ECDSA_POST_DONE_INT_RAW_V 0x00000001U +#define ECDSA_POST_DONE_INT_RAW_S 2 + +/* ECDSA_SHA_RELEASE_INT_RAW : RO/WTC/SS; bitpos: [1]; default: 0; + * The raw interrupt status bit for the ecdsa_sha_release_int + * interrupt + * This bit is only available for DATE == 0x2403120 (rev 1.2) */ -#define ECDSA_SHA_RELEASE_INT_RAW (BIT(1)) +#define ECDSA_SHA_RELEASE_INT_RAW ECDSA_REG_GET_OFFSET(BIT(1), BIT(3)) #define ECDSA_SHA_RELEASE_INT_RAW_M (ECDSA_SHA_RELEASE_INT_RAW_V << ECDSA_SHA_RELEASE_INT_RAW_S) #define ECDSA_SHA_RELEASE_INT_RAW_V 0x00000001U -#define ECDSA_SHA_RELEASE_INT_RAW_S 1 +#define ECDSA_SHA_RELEASE_INT_RAW_S ECDSA_REG_GET_OFFSET(1, 3) /** ECDSA_INT_ST_REG register - * ECDSA interrupt status register. + * ECDSA interrupt status + * register. */ #define ECDSA_INT_ST_REG (DR_REG_ECDSA_BASE + 0x10) -/** ECDSA_CALC_DONE_INT_ST : RO; bitpos: [0]; default: 0; - * The masked interrupt status bit for the ecdsa_calc_done_int interrupt - */ -#define ECDSA_CALC_DONE_INT_ST (BIT(0)) -#define ECDSA_CALC_DONE_INT_ST_M (ECDSA_CALC_DONE_INT_ST_V << ECDSA_CALC_DONE_INT_ST_S) -#define ECDSA_CALC_DONE_INT_ST_V 0x00000001U -#define ECDSA_CALC_DONE_INT_ST_S 0 -/** ECDSA_SHA_RELEASE_INT_ST : RO; bitpos: [1]; default: 0; - * The masked interrupt status bit for the ecdsa_sha_release_int interrupt + +/* ECDSA_PREP_DONE_INT_ST : RO; bitpos: [0]; default: 0; + * The masked interrupt status bit for the ecdsa_prep_done_int + * interrupt + * This bit was named as ECDSA_CALC_DONE_INT_ST in rev 0.0 and changed to ECDSA_PREP_DONE_INT_ST in rev 1.2 + * functionality is the same + */ +#define ECDSA_PREP_DONE_INT_ST (BIT(0)) +#define ECDSA_PREP_DONE_INT_ST_M (ECDSA_PREP_DONE_INT_ST_V << ECDSA_PREP_DONE_INT_ST_S) +#define ECDSA_PREP_DONE_INT_ST_V 0x00000001U +#define ECDSA_PREP_DONE_INT_ST_S 0 + +/* ECDSA_PROC_DONE_INT_ST : RO; bitpos: [1]; default: 0; + * The masked interrupt status bit for the ecdsa_proc_done_int + * interrupt + * This bit is only available for DATE == 0x2403120 (rev 1.2) + */ +#define ECDSA_PROC_DONE_INT_ST (BIT(1)) +#define ECDSA_PROC_DONE_INT_ST_M (ECDSA_PROC_DONE_INT_ST_V << ECDSA_PROC_DONE_INT_ST_S) +#define ECDSA_PROC_DONE_INT_ST_V 0x00000001U +#define ECDSA_PROC_DONE_INT_ST_S 1 + +/* ECDSA_POST_DONE_INT_ST : RO; bitpos: [2]; default: 0; + * The masked interrupt status bit for the ecdsa_post_done_int + * interrupt + * This bit is only available for DATE == 0x2403120 (rev 1.2) + */ +#define ECDSA_POST_DONE_INT_ST (BIT(2)) +#define ECDSA_POST_DONE_INT_ST_M (ECDSA_POST_DONE_INT_ST_V << ECDSA_POST_DONE_INT_ST_S) +#define ECDSA_POST_DONE_INT_ST_V 0x00000001U +#define ECDSA_POST_DONE_INT_ST_S 2 + +/* ECDSA_SHA_RELEASE_INT_ST : RO; + * bitpos: [1] for DATE == 0x21FFB30 (rev 0.0) ; default: 0; + * bitpos: [3] for DATE == 0x2403120 (rev 1.2) ; default: 0; + * The masked interrupt status bit for the ecdsa_sha_release_int + * interrupt */ -#define ECDSA_SHA_RELEASE_INT_ST (BIT(1)) +#define ECDSA_SHA_RELEASE_INT_ST ECDSA_REG_GET_OFFSET(BIT(1), BIT(3)) #define ECDSA_SHA_RELEASE_INT_ST_M (ECDSA_SHA_RELEASE_INT_ST_V << ECDSA_SHA_RELEASE_INT_ST_S) #define ECDSA_SHA_RELEASE_INT_ST_V 0x00000001U -#define ECDSA_SHA_RELEASE_INT_ST_S 1 +#define ECDSA_SHA_RELEASE_INT_ST_S ECDSA_REG_GET_OFFSET(1, 3) /** ECDSA_INT_ENA_REG register - * ECDSA interrupt enable register. + * ECDSA interrupt enable + * register. */ #define ECDSA_INT_ENA_REG (DR_REG_ECDSA_BASE + 0x14) -/** ECDSA_CALC_DONE_INT_ENA : R/W; bitpos: [0]; default: 0; - * The interrupt enable bit for the ecdsa_calc_done_int interrupt - */ -#define ECDSA_CALC_DONE_INT_ENA (BIT(0)) -#define ECDSA_CALC_DONE_INT_ENA_M (ECDSA_CALC_DONE_INT_ENA_V << ECDSA_CALC_DONE_INT_ENA_S) -#define ECDSA_CALC_DONE_INT_ENA_V 0x00000001U -#define ECDSA_CALC_DONE_INT_ENA_S 0 -/** ECDSA_SHA_RELEASE_INT_ENA : R/W; bitpos: [1]; default: 0; - * The interrupt enable bit for the ecdsa_sha_release_int interrupt + +/* ECDSA_PREP_DONE_INT_ENA : R/W; bitpos: [0]; default: 0; + * The interrupt enable bit for the ecdsa_prep_done_int + * interrupt + * This bit was named as ECDSA_CALC_DONE_INT_ENA in rev 0.0 and changed to ECDSA_PREP_DONE_INT_ENA in rev 1.2 + * functionality is the same + */ +#define ECDSA_PREP_DONE_INT_ENA (BIT(0)) +#define ECDSA_PREP_DONE_INT_ENA_M (ECDSA_PREP_DONE_INT_ENA_V << ECDSA_PREP_DONE_INT_ENA_S) +#define ECDSA_PREP_DONE_INT_ENA_V 0x00000001U +#define ECDSA_PREP_DONE_INT_ENA_S 0 + +/* ECDSA_PROC_DONE_INT_ENA : R/W; bitpos: [1]; default: 0; + * The interrupt enable bit for the ecdsa_proc_done_int + * interrupt + * This bit is only available for DATE == 0x2403120 (rev 1.2) + */ +#define ECDSA_PROC_DONE_INT_ENA (BIT(1)) +#define ECDSA_PROC_DONE_INT_ENA_M (ECDSA_PROC_DONE_INT_ENA_V << ECDSA_PROC_DONE_INT_ENA_S) +#define ECDSA_PROC_DONE_INT_ENA_V 0x00000001U +#define ECDSA_PROC_DONE_INT_ENA_S 1 + +/* ECDSA_POST_DONE_INT_ENA : R/W; bitpos: [2]; default: 0; + * The interrupt enable bit for the ecdsa_post_done_int + * interrupt + * This bit is only available for DATE == 0x2403120 (rev 1.2) + */ +#define ECDSA_POST_DONE_INT_ENA (BIT(2)) +#define ECDSA_POST_DONE_INT_ENA_M (ECDSA_POST_DONE_INT_ENA_V << ECDSA_POST_DONE_INT_ENA_S) +#define ECDSA_POST_DONE_INT_ENA_V 0x00000001U +#define ECDSA_POST_DONE_INT_ENA_S 2 + +/* ECDSA_SHA_RELEASE_INT_ENA : R/W; + * bitpos: [1] for DATE == 0x21FFB30 (rev 0.0); default: 0; + * bitpos: [3] for DATE == 0x2403120 (rev 1.2); default: 0; + * The interrupt enable bit for the ecdsa_sha_release_int + * interrupt */ -#define ECDSA_SHA_RELEASE_INT_ENA (BIT(1)) +#define ECDSA_SHA_RELEASE_INT_ENA (ECDSA_REG_GET_OFFSET(BIT(1), BIT(3))) #define ECDSA_SHA_RELEASE_INT_ENA_M (ECDSA_SHA_RELEASE_INT_ENA_V << ECDSA_SHA_RELEASE_INT_ENA_S) #define ECDSA_SHA_RELEASE_INT_ENA_V 0x00000001U -#define ECDSA_SHA_RELEASE_INT_ENA_S 1 +#define ECDSA_SHA_RELEASE_INT_ENA_S (ECDSA_REG_GET_OFFSET(1, 3)) /** ECDSA_INT_CLR_REG register - * ECDSA interrupt clear register. + * ECDSA interrupt clear + * register. */ #define ECDSA_INT_CLR_REG (DR_REG_ECDSA_BASE + 0x18) -/** ECDSA_CALC_DONE_INT_CLR : WT; bitpos: [0]; default: 0; - * Set this bit to clear the ecdsa_calc_done_int interrupt + + +/* ECDSA_PREP_DONE_INT_CLR : WT; bitpos: [0]; default: 0; + * Set this bit to clear the ecdsa_prep_done_int interrupt + * This bit was named as ECDSA_CALC_DONE_INT_CLR in rev 0.0 and changed to ECDSA_PREP_DONE_INT_CLR in rev 1.2 + * functionality is the same + */ +#define ECDSA_PREP_DONE_INT_CLR (BIT(0)) +#define ECDSA_PREP_DONE_INT_CLR_M (ECDSA_PREP_DONE_INT_CLR_V << ECDSA_PREP_DONE_INT_CLR_S) +#define ECDSA_PREP_DONE_INT_CLR_V 0x00000001U +#define ECDSA_PREP_DONE_INT_CLR_S 0 + +#define ECDSA_PROC_DONE_INT_CLR (BIT(1)) +#define ECDSA_PROC_DONE_INT_CLR_M (ECDSA_PROC_DONE_INT_CLR_V << ECDSA_PROC_DONE_INT_CLR_S) +#define ECDSA_PROC_DONE_INT_CLR_V 0x00000001U +#define ECDSA_PROC_DONE_INT_CLR_S 1 + +/* This bit is only available for DATE == 0x2403120 (rev 1.2) + * ECDSA_POST_DONE_INT_CLR : WT; bitpos: [2]; default: 0; + * Set this bit to clear the ecdsa_post_done_int interrupt */ -#define ECDSA_CALC_DONE_INT_CLR (BIT(0)) -#define ECDSA_CALC_DONE_INT_CLR_M (ECDSA_CALC_DONE_INT_CLR_V << ECDSA_CALC_DONE_INT_CLR_S) -#define ECDSA_CALC_DONE_INT_CLR_V 0x00000001U -#define ECDSA_CALC_DONE_INT_CLR_S 0 -/** ECDSA_SHA_RELEASE_INT_CLR : WT; bitpos: [1]; default: 0; - * Set this bit to clear the ecdsa_sha_release_int interrupt + +#define ECDSA_POST_DONE_INT_CLR (BIT(2)) +#define ECDSA_POST_DONE_INT_CLR_M (ECDSA_POST_DONE_INT_CLR_V << ECDSA_POST_DONE_INT_CLR_S) +#define ECDSA_POST_DONE_INT_CLR_V 0x00000001U +#define ECDSA_POST_DONE_INT_CLR_S 2 + +/* ECDSA_SHA_RELEASE_INT_CLR : WT; + * bitpos: [1] for DATE == 0x21FFB30 (rev 0.0); default: 0; + * bitpos: [3] for DATE == 0x2403120 (rev 1.2); default: 0; + * Set this bit to clear the ecdsa_sha_release_int + * interrupt */ -#define ECDSA_SHA_RELEASE_INT_CLR (BIT(1)) +#define ECDSA_SHA_RELEASE_INT_CLR (ECDSA_REG_GET_OFFSET(BIT(1), BIT(3))) #define ECDSA_SHA_RELEASE_INT_CLR_M (ECDSA_SHA_RELEASE_INT_CLR_V << ECDSA_SHA_RELEASE_INT_CLR_S) #define ECDSA_SHA_RELEASE_INT_CLR_V 0x00000001U -#define ECDSA_SHA_RELEASE_INT_CLR_S 1 +#define ECDSA_SHA_RELEASE_INT_CLR_S (ECDSA_REG_GET_OFFSET(1, 3)) /** ECDSA_START_REG register - * ECDSA start register + * ECDSA start + * register */ #define ECDSA_START_REG (DR_REG_ECDSA_BASE + 0x1c) -/** ECDSA_START : WT; bitpos: [0]; default: 0; - * Write 1 to start calculation of ECDSA Accelerator. This bit will be self-cleared - * after configuration. +/* ECDSA_START : WT; bitpos: [0]; default: 0; + * Write 1 to start calculation of ECDSA Accelerator. This bit will be + * self-cleared after + * configuration. */ #define ECDSA_START (BIT(0)) #define ECDSA_START_M (ECDSA_START_V << ECDSA_START_S) #define ECDSA_START_V 0x00000001U #define ECDSA_START_S 0 -/** ECDSA_LOAD_DONE : WT; bitpos: [1]; default: 0; - * Write 1 to input load done signal of ECDSA Accelerator. This bit will be - * self-cleared after configuration. +/* ECDSA_LOAD_DONE : WT; bitpos: [1]; default: 0; + * Write 1 to input load done signal of ECDSA Accelerator. This bit will + * be self-cleared after + * configuration. */ #define ECDSA_LOAD_DONE (BIT(1)) #define ECDSA_LOAD_DONE_M (ECDSA_LOAD_DONE_V << ECDSA_LOAD_DONE_S) #define ECDSA_LOAD_DONE_V 0x00000001U #define ECDSA_LOAD_DONE_S 1 -/** ECDSA_GET_DONE : WT; bitpos: [2]; default: 0; - * Write 1 to input get done signal of ECDSA Accelerator. This bit will be - * self-cleared after configuration. +/* ECDSA_GET_DONE : WT; bitpos: [2]; default: 0; + * Write 1 to input get done signal of ECDSA Accelerator. This bit will be + * self-cleared after + * configuration. */ #define ECDSA_GET_DONE (BIT(2)) #define ECDSA_GET_DONE_M (ECDSA_GET_DONE_V << ECDSA_GET_DONE_S) #define ECDSA_GET_DONE_V 0x00000001U #define ECDSA_GET_DONE_S 2 +/** Status registers */ + /** ECDSA_STATE_REG register - * ECDSA status register + * ECDSA status + * register */ #define ECDSA_STATE_REG (DR_REG_ECDSA_BASE + 0x20) -/** ECDSA_BUSY : RO; bitpos: [1:0]; default: 0; - * The status bits of ECDSA Accelerator. ECDSA is at 0: IDLE, 1: LOAD, 2: GET, 3: BUSY - * state. +/* ECDSA_BUSY : RO; bitpos: [2:0]; default: 0; + * The status bits of ECDSA Accelerator. ECDSA is at 0: IDLE, 1: LOAD, 2: + * GET, 3: BUSY + * state. */ #define ECDSA_BUSY 0x00000003U #define ECDSA_BUSY_M (ECDSA_BUSY_V << ECDSA_BUSY_S) #define ECDSA_BUSY_V 0x00000003U #define ECDSA_BUSY_S 0 + +/** Result registers */ + /** ECDSA_RESULT_REG register - * ECDSA result register + * ECDSA result + * register */ #define ECDSA_RESULT_REG (DR_REG_ECDSA_BASE + 0x24) -/** ECDSA_OPERATION_RESULT : RO/SS; bitpos: [0]; default: 0; - * The operation result bit of ECDSA Accelerator, only valid when ECDSA calculation is - * done. +/* ECDSA_OPERATION_RESULT : RO/SS; bitpos: [0]; default: 0; + * The operation result bit of ECDSA Accelerator, only valid when ECDSA + * calculation is + * done. */ #define ECDSA_OPERATION_RESULT (BIT(0)) #define ECDSA_OPERATION_RESULT_M (ECDSA_OPERATION_RESULT_V << ECDSA_OPERATION_RESULT_S) #define ECDSA_OPERATION_RESULT_V 0x00000001U #define ECDSA_OPERATION_RESULT_S 0 -/** ECDSA_DATE_REG register - * Version control register - */ -#define ECDSA_DATE_REG (DR_REG_ECDSA_BASE + 0xfc) -/** ECDSA_DATE : R/W; bitpos: [27:0]; default: 35684752; - * ECDSA version control register - */ -#define ECDSA_DATE 0x0FFFFFFFU -#define ECDSA_DATE_M (ECDSA_DATE_V << ECDSA_DATE_S) -#define ECDSA_DATE_V 0x0FFFFFFFU -#define ECDSA_DATE_S 0 + +/** SHA register */ /** ECDSA_SHA_MODE_REG register - * ECDSA control SHA register + * ECDSA control SHA + * register */ #define ECDSA_SHA_MODE_REG (DR_REG_ECDSA_BASE + 0x200) -/** ECDSA_SHA_MODE : R/W; bitpos: [2:0]; default: 0; - * The work mode bits of SHA Calculator in ECDSA Accelerator. 1: SHA-224. 2: SHA-256. - * Others: invalid. +/* ECDSA_SHA_MODE : R/W; bitpos: [3:0]; default: 0; + * The work mode bits of SHA Calculator in ECDSA Accelerator. 1: SHA-224. + * 2: SHA-256. Others: + * invalid. */ #define ECDSA_SHA_MODE 0x00000007U #define ECDSA_SHA_MODE_M (ECDSA_SHA_MODE_V << ECDSA_SHA_MODE_S) @@ -216,12 +396,14 @@ extern "C" { #define ECDSA_SHA_MODE_S 0 /** ECDSA_SHA_START_REG register - * ECDSA control SHA register + * ECDSA control SHA + * register */ #define ECDSA_SHA_START_REG (DR_REG_ECDSA_BASE + 0x210) -/** ECDSA_SHA_START : WT; bitpos: [0]; default: 0; - * Write 1 to start the first calculation of SHA Calculator in ECDSA Accelerator. This - * bit will be self-cleared after configuration. +/* ECDSA_SHA_START : WT; bitpos: [0]; default: 0; + * Write 1 to start the first calculation of SHA Calculator in ECDSA + * Accelerator. This bit will be self-cleared after + * configuration. */ #define ECDSA_SHA_START (BIT(0)) #define ECDSA_SHA_START_M (ECDSA_SHA_START_V << ECDSA_SHA_START_S) @@ -229,12 +411,14 @@ extern "C" { #define ECDSA_SHA_START_S 0 /** ECDSA_SHA_CONTINUE_REG register - * ECDSA control SHA register + * ECDSA control SHA + * register */ #define ECDSA_SHA_CONTINUE_REG (DR_REG_ECDSA_BASE + 0x214) -/** ECDSA_SHA_CONTINUE : WT; bitpos: [0]; default: 0; - * Write 1 to start the latter calculation of SHA Calculator in ECDSA Accelerator. This - * bit will be self-cleared after configuration. +/* ECDSA_SHA_CONTINUE : WT; bitpos: [0]; default: 0; + * Write 1 to start the latter calculation of SHA Calculator in ECDSA + * Accelerator. This bit will be self-cleared after + * configuration. */ #define ECDSA_SHA_CONTINUE (BIT(0)) #define ECDSA_SHA_CONTINUE_M (ECDSA_SHA_CONTINUE_V << ECDSA_SHA_CONTINUE_S) @@ -242,18 +426,21 @@ extern "C" { #define ECDSA_SHA_CONTINUE_S 0 /** ECDSA_SHA_BUSY_REG register - * ECDSA status register + * ECDSA status + * register */ #define ECDSA_SHA_BUSY_REG (DR_REG_ECDSA_BASE + 0x218) -/** ECDSA_SHA_BUSY : RO; bitpos: [0]; default: 0; - * The busy status bit of SHA Calculator in ECDSA Accelerator. 1:SHA is in - * calculation. 0: SHA is idle. +/* ECDSA_SHA_BUSY : RO; bitpos: [0]; default: 0; + * The busy status bit of SHA Calculator in ECDSA Accelerator. 1:SHA is in + * calculation. 0: SHA is + * idle. */ #define ECDSA_SHA_BUSY (BIT(0)) #define ECDSA_SHA_BUSY_M (ECDSA_SHA_BUSY_V << ECDSA_SHA_BUSY_S) #define ECDSA_SHA_BUSY_V 0x00000001U #define ECDSA_SHA_BUSY_S 0 + /** ECDSA_MESSAGE_MEM register * The memory that stores message. */ @@ -263,31 +450,31 @@ extern "C" { /** ECDSA_R_MEM register * The memory that stores r. */ -#define ECDSA_R_MEM (DR_REG_ECDSA_BASE + 0xa00) +#define ECDSA_R_MEM (DR_REG_ECDSA_BASE + REG_COMPATIBLE_ADDR(102, 0xa00, 0x340)) #define ECDSA_R_MEM_SIZE_BYTES 32 /** ECDSA_S_MEM register * The memory that stores s. */ -#define ECDSA_S_MEM (DR_REG_ECDSA_BASE + 0xa20) +#define ECDSA_S_MEM (DR_REG_ECDSA_BASE + REG_COMPATIBLE_ADDR(102, 0xa20, 0x360)) #define ECDSA_S_MEM_SIZE_BYTES 32 /** ECDSA_Z_MEM register * The memory that stores software written z. */ -#define ECDSA_Z_MEM (DR_REG_ECDSA_BASE + 0xa40) +#define ECDSA_Z_MEM (DR_REG_ECDSA_BASE + REG_COMPATIBLE_ADDR(102, 0xa40, 0x380)) #define ECDSA_Z_MEM_SIZE_BYTES 32 /** ECDSA_QAX_MEM register * The memory that stores x coordinates of QA or software written k. */ -#define ECDSA_QAX_MEM (DR_REG_ECDSA_BASE + 0xa60) +#define ECDSA_QAX_MEM (DR_REG_ECDSA_BASE + REG_COMPATIBLE_ADDR(102, 0xa60, 0x3a0)) #define ECDSA_QAX_MEM_SIZE_BYTES 32 /** ECDSA_QAY_MEM register * The memory that stores y coordinates of QA. */ -#define ECDSA_QAY_MEM (DR_REG_ECDSA_BASE + 0xa80) +#define ECDSA_QAY_MEM (DR_REG_ECDSA_BASE + REG_COMPATIBLE_ADDR(102, 0xa80, 0x3c0)) #define ECDSA_QAY_MEM_SIZE_BYTES 32 #ifdef __cplusplus diff --git a/components/soc/esp32h2/register/soc/ecdsa_struct.h b/components/soc/esp32h2/register/soc/ecdsa_rev_0_0_struct.h similarity index 82% rename from components/soc/esp32h2/register/soc/ecdsa_struct.h rename to components/soc/esp32h2/register/soc/ecdsa_rev_0_0_struct.h index ca9076e5526c..30fbec52aaf5 100644 --- a/components/soc/esp32h2/register/soc/ecdsa_struct.h +++ b/components/soc/esp32h2/register/soc/ecdsa_rev_0_0_struct.h @@ -1,5 +1,5 @@ /** - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -40,7 +40,7 @@ typedef union { uint32_t reserved_4:28; }; uint32_t val; -} ecdsa_conf_reg_t; +} ecdsa_rev_0_0_conf_reg_t; /** Type of start register * ECDSA start register @@ -65,7 +65,7 @@ typedef union { uint32_t reserved_3:29; }; uint32_t val; -} ecdsa_start_reg_t; +} ecdsa_rev_0_0_start_reg_t; /** Group: Clock and reset registers */ @@ -81,7 +81,7 @@ typedef union { uint32_t reserved_1:31; }; uint32_t val; -} ecdsa_clk_reg_t; +} ecdsa_rev_0_0_clk_reg_t; /** Group: Interrupt registers */ @@ -101,7 +101,7 @@ typedef union { uint32_t reserved_2:30; }; uint32_t val; -} ecdsa_int_raw_reg_t; +} ecdsa_rev_0_0_int_raw_reg_t; /** Type of int_st register * ECDSA interrupt status register. @@ -119,7 +119,7 @@ typedef union { uint32_t reserved_2:30; }; uint32_t val; -} ecdsa_int_st_reg_t; +} ecdsa_rev_0_0_int_st_reg_t; /** Type of int_ena register * ECDSA interrupt enable register. @@ -137,7 +137,7 @@ typedef union { uint32_t reserved_2:30; }; uint32_t val; -} ecdsa_int_ena_reg_t; +} ecdsa_rev_0_0_int_ena_reg_t; /** Type of int_clr register * ECDSA interrupt clear register. @@ -155,7 +155,7 @@ typedef union { uint32_t reserved_2:30; }; uint32_t val; -} ecdsa_int_clr_reg_t; +} ecdsa_rev_0_0_int_clr_reg_t; /** Group: Status registers */ @@ -172,7 +172,7 @@ typedef union { uint32_t reserved_2:30; }; uint32_t val; -} ecdsa_state_reg_t; +} ecdsa_rev_0_0_state_reg_t; /** Group: Result registers */ @@ -189,7 +189,7 @@ typedef union { uint32_t reserved_1:31; }; uint32_t val; -} ecdsa_result_reg_t; +} ecdsa_rev_0_0_result_reg_t; /** Group: SHA register */ @@ -206,7 +206,7 @@ typedef union { uint32_t reserved_3:29; }; uint32_t val; -} ecdsa_sha_mode_reg_t; +} ecdsa_rev_0_0_sha_mode_reg_t; /** Type of sha_start register * ECDSA control SHA register @@ -221,7 +221,7 @@ typedef union { uint32_t reserved_1:31; }; uint32_t val; -} ecdsa_sha_start_reg_t; +} ecdsa_rev_0_0_sha_start_reg_t; /** Type of sha_continue register * ECDSA control SHA register @@ -236,7 +236,7 @@ typedef union { uint32_t reserved_1:31; }; uint32_t val; -} ecdsa_sha_continue_reg_t; +} ecdsa_rev_0_0_sha_continue_reg_t; /** Type of sha_busy register * ECDSA status register @@ -251,7 +251,7 @@ typedef union { uint32_t reserved_1:31; }; uint32_t val; -} ecdsa_sha_busy_reg_t; +} ecdsa_rev_0_0_sha_busy_reg_t; /** Group: Version register */ @@ -263,46 +263,57 @@ typedef union { /** date : R/W; bitpos: [27:0]; default: 35684752; * ECDSA version control register */ - uint32_t date:28; + uint32_t ecdsa_date:28; uint32_t reserved_28:4; }; uint32_t val; -} ecdsa_date_reg_t; - +} ecdsa_rev_0_0_date_reg_t; +/** + * ECDSA message register + */ typedef struct { - uint32_t reserved_000; - volatile ecdsa_conf_reg_t conf; - volatile ecdsa_clk_reg_t clk; - volatile ecdsa_int_raw_reg_t int_raw; - volatile ecdsa_int_st_reg_t int_st; - volatile ecdsa_int_ena_reg_t int_ena; - volatile ecdsa_int_clr_reg_t int_clr; - volatile ecdsa_start_reg_t start; - volatile ecdsa_state_reg_t state; - volatile ecdsa_result_reg_t result; - uint32_t reserved_028[53]; - volatile ecdsa_date_reg_t date; - uint32_t reserved_100[64]; - volatile ecdsa_sha_mode_reg_t sha_mode; - uint32_t reserved_204[3]; - volatile ecdsa_sha_start_reg_t sha_start; - volatile ecdsa_sha_continue_reg_t sha_continue; - volatile ecdsa_sha_busy_reg_t sha_busy; - uint32_t reserved_21c[25]; volatile uint32_t message[8]; - uint32_t reserved_2a0[472]; +} ecdsa_rev_0_0_message_reg_t; + +/** + * ECDSA memory register + */ +typedef struct { volatile uint32_t r[8]; volatile uint32_t s[8]; volatile uint32_t z[8]; volatile uint32_t qax[8]; volatile uint32_t qay[8]; -} ecdsa_dev_t; +} ecdsa_rev_0_0_mem_reg_t; -extern ecdsa_dev_t ECDSA; +typedef struct { + uint32_t reserved_000; + volatile ecdsa_rev_0_0_conf_reg_t conf; + volatile ecdsa_rev_0_0_clk_reg_t clk; + volatile ecdsa_rev_0_0_int_raw_reg_t int_raw; + volatile ecdsa_rev_0_0_int_st_reg_t int_st; + volatile ecdsa_rev_0_0_int_ena_reg_t int_ena; + volatile ecdsa_rev_0_0_int_clr_reg_t int_clr; + volatile ecdsa_rev_0_0_start_reg_t start; + volatile ecdsa_rev_0_0_state_reg_t state; + volatile ecdsa_rev_0_0_result_reg_t result; + uint32_t reserved_028[53]; + volatile ecdsa_rev_0_0_date_reg_t date; + uint32_t reserved_100[64]; + volatile ecdsa_rev_0_0_sha_mode_reg_t sha_mode; + uint32_t reserved_204[3]; + volatile ecdsa_rev_0_0_sha_start_reg_t sha_start; + volatile ecdsa_rev_0_0_sha_continue_reg_t sha_continue; + volatile ecdsa_rev_0_0_sha_busy_reg_t sha_busy; + uint32_t reserved_21c[25]; + volatile ecdsa_rev_0_0_message_reg_t message; + uint32_t reserved_2a0[472]; + volatile ecdsa_rev_0_0_mem_reg_t mem; +} ecdsa_dev_rev_0_0_t; #ifndef __cplusplus -_Static_assert(sizeof(ecdsa_dev_t) == 0xaa0, "Invalid size of ecdsa_dev_t structure"); +_Static_assert(sizeof(ecdsa_dev_rev_0_0_t) == 0xaa0, "Invalid size of ecdsa_dev_rev_0_0_t structure"); #endif #ifdef __cplusplus diff --git a/components/soc/esp32h2/register/soc/ecdsa_rev_1_2_struct.h b/components/soc/esp32h2/register/soc/ecdsa_rev_1_2_struct.h new file mode 100644 index 000000000000..16b5021d4deb --- /dev/null +++ b/components/soc/esp32h2/register/soc/ecdsa_rev_1_2_struct.h @@ -0,0 +1,368 @@ +/** + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#ifdef __cplusplus +extern "C" { +#endif + +/** Group: Data Memory */ + +/** Group: Configuration registers */ +/** Type of conf register + * ECDSA configure register + */ +typedef union { + struct { + /** work_mode : R/W; bitpos: [1:0]; default: 0; + * The work mode bits of ECDSA Accelerator. + * 0: Signature Verify Mode. + * 1: Signature Generate Mode. + * 2: Export Public Key Mode. + * 3: invalid. + */ + uint32_t work_mode:2; + + /** ecc_curve : R/W; bitpos: [2]; default: 0; + * The ecc curve select bit of ECDSA Accelerator. 0: P-192. 1: P-256. + */ + uint32_t ecc_curve:1; + /** software_set_k : R/W; bitpos: [3]; default: 0; + * The source of k select bit. 0: k is automatically generated by TRNG. 1: k is + * written by software. + */ + uint32_t software_set_k:1; + + /** software_set_z : R/W; bitpos: [4]; default: 0; + * The source of z select bit. 0: z is generated from SHA result. 1: z is written by + * software. + */ + uint32_t software_set_z:1; + + /** ecdsa_deterministic_k : R/W; bitpos: [5]; default: 0; + * The source of hardware generated k. 0: k is generated by TRNG. 1: k is generated by + * deterministic derivation algorithm. + */ + + uint32_t ecdsa_deterministic_k:1; + + uint32_t reserved_6:26; + }; + uint32_t val; +} ecdsa_conf_reg_t; + +/** Type of start register + * ECDSA start register + */ +typedef union { + struct { + /** start : WT; bitpos: [0]; default: 0; + * Write 1 to start calculation of ECDSA Accelerator. This bit will be self-cleared + * after configuration. + */ + uint32_t start:1; + /** load_done : WT; bitpos: [1]; default: 0; + * Write 1 to input load done signal of ECDSA Accelerator. This bit will be + * self-cleared after configuration. + */ + uint32_t load_done:1; + /** get_done : WT; bitpos: [2]; default: 0; + * Write 1 to input get done signal of ECDSA Accelerator. This bit will be + * self-cleared after configuration. + */ + uint32_t get_done:1; + uint32_t reserved_3:29; + }; + uint32_t val; +} ecdsa_start_reg_t; + + +/** Group: Clock and reset registers */ +/** Type of clk register + * ECDSA clock gate register + */ +typedef union { + struct { + /** clk_gate_force_on : R/W; bitpos: [0]; default: 0; + * Write 1 to force on register clock gate. + */ + uint32_t clk_gate_force_on:1; + uint32_t reserved_1:31; + }; + uint32_t val; +} ecdsa_clk_reg_t; + + +/** Group: Interrupt registers */ +/** Type of int_raw register + * ECDSA interrupt raw register, valid in level. + */ +typedef union { + struct { + /** prep_done_int_raw : RO/WTC/SS; bitpos: [0]; default: 0; + * The raw interrupt status bit for the ecdsa_prep_done_int interrupt + */ + uint32_t prep_done_int_raw:1; + /** proc_done_int_raw : RO/WTC/SS; bitpos: [1]; default: 0; + * The raw interrupt status bit for the ecdsa_proc_done_int interrupt + */ + uint32_t proc_done_int_raw:1; + /** post_done_int_raw : RO/WTC/SS; bitpos: [2]; default: 0; + * The raw interrupt status bit for the ecdsa_post_done_int interrupt + */ + uint32_t post_done_int_raw:1; + /** sha_release_int_raw : RO/WTC/SS; bitpos: [3]; default: 0; + * The raw interrupt status bit for the ecdsa_sha_release_int interrupt + */ + uint32_t sha_release_int_raw:1; + + uint32_t reserved_4:28; + }; + uint32_t val; +} ecdsa_int_raw_reg_t; + +/** Type of int_st register + * ECDSA interrupt status register. + */ +typedef union { + struct { + /** prep_done_int_st : RO; bitpos: [0]; default: 0; + * The masked interrupt status bit for the ecdsa_prep_done_int interrupt + */ + uint32_t prep_done_int_st:1; + /** proc_done_int_st : RO; bitpos: [1]; default: 0; + * The masked interrupt status bit for the ecdsa_proc_done_int interrupt + */ + uint32_t proc_done_int_st:1; + /** post_done_int_st : RO; bitpos: [2]; default: 0; + * The masked interrupt status bit for the ecdsa_post_done_int interrupt + */ + uint32_t post_done_int_st:1; + /** sha_release_int_st : RO; bitpos: [3]; default: 0; + * The masked interrupt status bit for the ecdsa_sha_release_int interrupt + */ + uint32_t sha_release_int_st:1; + uint32_t reserved_4:28; + }; + uint32_t val; +} ecdsa_int_st_reg_t; + +/** Type of int_ena register + * ECDSA interrupt enable register. + */ +typedef union { + struct { + /** prep_done_int_ena : R/W; bitpos: [0]; default: 0; + * The interrupt enable bit for the ecdsa_prep_done_int interrupt + */ + uint32_t prep_done_int_ena:1; + /** sha_release_int_ena : R/W; bitpos: [1]; default: 0; + * The interrupt enable bit for the ecdsa_sha_release_int interrupt + */ + uint32_t proc_done_int_ena:1; + /** post_done_int_ena : R/W; bitpos: [2]; default: 0; + * The interrupt enable bit for the ecdsa_post_done_int interrupt + */ + uint32_t post_done_int_ena:1; + /** sha_release_int_ena : R/W; bitpos: [3]; default: 0; + * The interrupt enable bit for the ecdsa_sha_release_int interrupt + */ + uint32_t sha_release_int_ena:1; + uint32_t reserved_4:28; + }; + uint32_t val; +} ecdsa_int_ena_reg_t; + +/** Type of int_clr register + * ECDSA interrupt clear register. + */ +typedef union { + struct { + /** prep_done_int_clr : WT; bitpos: [0]; default: 0; + * Set this bit to clear the ecdsa_prep_done_int interrupt + */ + uint32_t prep_done_int_clr:1; + /** proc_done_int_clr : WT; bitpos: [1]; default: 0; + * Set this bit to clear the ecdsa_proc_done_int interrupt + */ + uint32_t proc_done_int_clr:1; + /** post_done_int_clr : WT; bitpos: [2]; default: 0; + * Set this bit to clear the ecdsa_post_done_int interrupt + */ + uint32_t post_done_int_clr:1; + /** sha_release_int_clr : WT; bitpos: [3]; default: 0; + * Set this bit to clear the ecdsa_sha_release_int interrupt + */ + uint32_t sha_release_int_clr:1; + uint32_t reserved_4:28; + }; + uint32_t val; +} ecdsa_int_clr_reg_t; + + +/** Group: Status registers */ +/** Type of state register + * ECDSA status register + */ +typedef union { + struct { + /** busy : RO; bitpos: [1:0]; default: 0; + * The status bits of ECDSA Accelerator. ECDSA is at 0: IDLE, 1: LOAD, 2: GET, 3: BUSY + * state. + */ + uint32_t busy:2; + uint32_t reserved_2:30; + }; + uint32_t val; +} ecdsa_state_reg_t; + + +/** Group: Result registers */ +/** Type of result register + * ECDSA result register + */ +typedef union { + struct { + /** operation_result : RO/SS; bitpos: [0]; default: 0; + * The operation result bit of ECDSA Accelerator, only valid when ECDSA calculation is + * done. + */ + uint32_t operation_result:1; + uint32_t reserved_1:31; + }; + uint32_t val; +} ecdsa_result_reg_t; + + +/** Group: SHA register */ +/** Type of sha_mode register + * ECDSA control SHA register + */ +typedef union { + struct { + /** sha_mode : R/W; bitpos: [2:0]; default: 0; + * The work mode bits of SHA Calculator in ECDSA Accelerator. 1: SHA-224. 2: SHA-256. + * Others: invalid. + */ + uint32_t sha_mode:3; + uint32_t reserved_3:29; + }; + uint32_t val; +} ecdsa_sha_mode_reg_t; + +/** Type of sha_start register + * ECDSA control SHA register + */ +typedef union { + struct { + /** sha_start : WT; bitpos: [0]; default: 0; + * Write 1 to start the first calculation of SHA Calculator in ECDSA Accelerator. This + * bit will be self-cleared after configuration. + */ + uint32_t sha_start:1; + uint32_t reserved_1:31; + }; + uint32_t val; +} ecdsa_sha_start_reg_t; + +/** Type of sha_continue register + * ECDSA control SHA register + */ +typedef union { + struct { + /** sha_continue : WT; bitpos: [0]; default: 0; + * Write 1 to start the latter calculation of SHA Calculator in ECDSA Accelerator. This + * bit will be self-cleared after configuration. + */ + uint32_t sha_continue:1; + uint32_t reserved_1:31; + }; + uint32_t val; +} ecdsa_sha_continue_reg_t; + +/** Type of sha_busy register + * ECDSA status register + */ +typedef union { + struct { + /** sha_busy : RO; bitpos: [0]; default: 0; + * The busy status bit of SHA Calculator in ECDSA Accelerator. 1:SHA is in + * calculation. 0: SHA is idle. + */ + uint32_t sha_busy:1; + uint32_t reserved_1:31; + }; + uint32_t val; +} ecdsa_sha_busy_reg_t; + + +/** Group: Version register */ +/** Type of date register + * Version control register + */ +typedef union { + struct { + /** ECDSA_DATE : R/W; bitpos: [27:0]; default: 37761312; + * ECDSA version control register + */ + uint32_t ecdsa_date:28; + uint32_t reserved_28:4; + }; + uint32_t val; +} ecdsa_date_reg_t; + +/** + * ECDSA message register + */ +typedef struct { + volatile uint32_t message[8]; +} ecdsa_message_reg_t; + +/** + * ECDSA memory register + */ +typedef struct { + volatile uint32_t r[8]; + volatile uint32_t s[8]; + volatile uint32_t z[8]; + volatile uint32_t qax[8]; + volatile uint32_t qay[8]; +} ecdsa_mem_reg_t; + +typedef struct { + uint32_t reserved_000; + volatile ecdsa_conf_reg_t conf; + volatile ecdsa_clk_reg_t clk; + volatile ecdsa_int_raw_reg_t int_raw; + volatile ecdsa_int_st_reg_t int_st; + volatile ecdsa_int_ena_reg_t int_ena; + volatile ecdsa_int_clr_reg_t int_clr; + volatile ecdsa_start_reg_t start; + volatile ecdsa_state_reg_t state; + volatile ecdsa_result_reg_t result; + uint32_t reserved_028[53]; + volatile ecdsa_date_reg_t date; + uint32_t reserved_100[64]; + volatile ecdsa_sha_mode_reg_t sha_mode; + uint32_t reserved_204[3]; + volatile ecdsa_sha_start_reg_t sha_start; + volatile ecdsa_sha_continue_reg_t sha_continue; + volatile ecdsa_sha_busy_reg_t sha_busy; + uint32_t reserved_21c[25]; + volatile ecdsa_message_reg_t message; + uint32_t reserved_2a0[40]; + volatile ecdsa_mem_reg_t mem; + uint32_t reserved_300[432]; +} ecdsa_dev_rev_1_2_t; + +#ifndef __cplusplus +_Static_assert(sizeof(ecdsa_dev_rev_1_2_t) == 0xaa0, "Invalid size of ecdsa_dev_rev_1_2_t structure"); +#endif + +#ifdef __cplusplus +} +#endif diff --git a/components/soc/esp32h2/register/soc/lpperi_rev0_0_struct.h b/components/soc/esp32h2/register/soc/lpperi_rev0_0_struct.h index 970b12ed10c0..b3826439ace7 100644 --- a/components/soc/esp32h2/register/soc/lpperi_rev0_0_struct.h +++ b/components/soc/esp32h2/register/soc/lpperi_rev0_0_struct.h @@ -301,9 +301,6 @@ typedef struct { volatile lpperi_rev0_0_date_reg_t date; } lpperi_rev0_0_dev_t; -/* Please don't use the following instance, use the compatible instance LPPERI in `lpperi_struct.h` instead. */ -extern lpperi_rev0_0_dev_t LPPERI_REV0_0; - #ifndef __cplusplus _Static_assert(sizeof(lpperi_rev0_0_dev_t) == 0x400, "Invalid size of lpperi_rev0_0_dev_t structure"); #endif diff --git a/components/soc/esp32h2/register/soc/lpperi_rev1_2_struct.h b/components/soc/esp32h2/register/soc/lpperi_rev1_2_struct.h index 5f3598e3c673..338f92014b46 100644 --- a/components/soc/esp32h2/register/soc/lpperi_rev1_2_struct.h +++ b/components/soc/esp32h2/register/soc/lpperi_rev1_2_struct.h @@ -316,9 +316,6 @@ typedef struct { volatile lpperi_date_reg_t date; } lpperi_rev1_2_dev_t; -/* Please don't use the following instance, use the compatible instance LPPERI in `lpperi_struct.h` instead. */ -extern lpperi_rev1_2_dev_t LPPERI_REV1_2; - #ifndef __cplusplus _Static_assert(sizeof(lpperi_rev1_2_dev_t) == 0x400, "Invalid size of lpperi_rev1_2_dev_t structure"); #endif diff --git a/components/soc/esp32h2/register/soc/spi_mem_struct.h b/components/soc/esp32h2/register/soc/spi_mem_struct.h index 45810eb9afab..b8af9dcebec7 100644 --- a/components/soc/esp32h2/register/soc/spi_mem_struct.h +++ b/components/soc/esp32h2/register/soc/spi_mem_struct.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -1033,7 +1033,16 @@ typedef volatile struct spi_mem_dev_s { }; uint32_t val; } dpa_ctrl; - uint32_t reserved_38c; + union { + struct { + uint32_t reg_mode_pseudo : 2; /*Set the mode of pseudo. 2'b00: crypto without pseudo. 2'b01: state T with pseudo and state D without pseudo. 2'b10: state T with pseudo and state D with few pseudo. 2'b11: crypto with pseudo.*/ + uint32_t reg_pseudo_rng_cnt : 3; /*xts aes peseudo function base round that must be performed.*/ + uint32_t reg_pseudo_base : 4; /*xts aes peseudo function base round that must be performed.*/ + uint32_t reg_pseudo_inc : 2; /*xts aes peseudo function increment round that will be performed randomly between 0 & 2**(inc+1).*/ + uint32_t reserved11 : 21; /*reserved*/ + }; + uint32_t val; + } xts_pseudo_round_conf; uint32_t reserved_390; uint32_t reserved_394; uint32_t reserved_398; @@ -1071,6 +1080,11 @@ typedef volatile struct spi_mem_dev_s { } spi_mem_dev_t; extern spi_mem_dev_t SPIMEM0; extern spi_mem_dev_t SPIMEM1; + +#ifndef __cplusplus +_Static_assert(sizeof(spi_mem_dev_t) == 0x400, "Invalid size of spi_mem_dev_t structure"); +#endif + #ifdef __cplusplus } #endif diff --git a/components/soc/esp32h2/register/soc/xts_aes_reg.h b/components/soc/esp32h2/register/soc/xts_aes_reg.h index 921701bc7421..b81c0a3f3863 100644 --- a/components/soc/esp32h2/register/soc/xts_aes_reg.h +++ b/components/soc/esp32h2/register/soc/xts_aes_reg.h @@ -1,5 +1,5 @@ /** - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -124,6 +124,42 @@ formance of cryption will decrease together with this number increasing).*/ #define XTS_AES_CRYPT_SECURITY_LEVEL_V 0x7 #define XTS_AES_CRYPT_SECURITY_LEVEL_S 0 +/** XTS_AES_PSEUDO_ROUND_CONF_REG register + * SPI memory encryption PSEUDO register + */ +#define XTS_AES_PSEUDO_ROUND_CONF_REG(i) (REG_SPI_MEM_BASE(i) + 0x38c) +/** XTS_AES_MODE_PSEUDO : R/W; bitpos: [1:0]; default: 0; + * Set the mode of pseudo. 2'b00: crypto without pseudo. 2'b01: state T with pseudo + * and state D without pseudo. 2'b10: state T with pseudo and state D with few pseudo. + * 2'b11: crypto with pseudo. + */ +#define XTS_AES_MODE_PSEUDO 0x00000003U +#define XTS_AES_MODE_PSEUDO_M (XTS_AES_MODE_PSEUDO_V << XTS_AES_MODE_PSEUDO_S) +#define XTS_AES_MODE_PSEUDO_V 0x00000003U +#define XTS_AES_MODE_PSEUDO_S 0 +/** XTS_AES_PSEUDO_RNG_CNT : R/W; bitpos: [4:2]; default: 7; + * xts aes peseudo function base round that must be performed. + */ +#define XTS_AES_PSEUDO_RNG_CNT 0x00000007U +#define XTS_AES_PSEUDO_RNG_CNT_M (XTS_AES_PSEUDO_RNG_CNT_V << XTS_AES_PSEUDO_RNG_CNT_S) +#define XTS_AES_PSEUDO_RNG_CNT_V 0x00000007U +#define XTS_AES_PSEUDO_RNG_CNT_S 2 +/** XTS_AES_PSEUDO_BASE : R/W; bitpos: [8:5]; default: 2; + * xts aes peseudo function base round that must be performed. + */ +#define XTS_AES_PSEUDO_BASE 0x0000000FU +#define XTS_AES_PSEUDO_BASE_M (XTS_AES_PSEUDO_BASE_V << XTS_AES_PSEUDO_BASE_S) +#define XTS_AES_PSEUDO_BASE_V 0x0000000FU +#define XTS_AES_PSEUDO_BASE_S 5 +/** XTS_AES_PSEUDO_INC : R/W; bitpos: [10:9]; default: 2; + * xts aes peseudo function increment round that will be performed randomly between 0 & + * 2**(inc+1). + */ +#define XTS_AES_PSEUDO_INC 0x00000003U +#define XTS_AES_PSEUDO_INC_M (XTS_AES_PSEUDO_INC_V << XTS_AES_PSEUDO_INC_S) +#define XTS_AES_PSEUDO_INC_V 0x00000003U +#define XTS_AES_PSEUDO_INC_S 9 + #ifdef __cplusplus } #endif diff --git a/components/soc/esp32h2/temperature_sensor_periph.c b/components/soc/esp32h2/temperature_sensor_periph.c index a4cc33aa6fe0..46f079333d2f 100644 --- a/components/soc/esp32h2/temperature_sensor_periph.c +++ b/components/soc/esp32h2/temperature_sensor_periph.c @@ -8,8 +8,9 @@ #include "soc/regdma.h" #include "soc/temperature_sensor_periph.h" #include "soc/apb_saradc_reg.h" +#include "esp_attr.h" -const temperature_sensor_attribute_t temperature_sensor_attributes[TEMPERATURE_SENSOR_ATTR_RANGE_NUM] = { +DRAM_ATTR temperature_sensor_attribute_t temperature_sensor_attributes[TEMPERATURE_SENSOR_ATTR_RANGE_NUM] = { /*Offset reg_val min max error */ {-2, 5, 50, 125, 3}, {-1, 7, 20, 100, 2}, diff --git a/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in index 38497a77e403..82de6dac3de6 100644 --- a/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in @@ -23,6 +23,18 @@ config SOC_SYSTIMER_SUPPORTED bool default y +config SOC_MPI_SUPPORTED + bool + default y + +config SOC_ECC_SUPPORTED + bool + default y + +config SOC_ECC_EXTENDED_MODES_SUPPORTED + bool + default y + config SOC_FLASH_ENC_SUPPORTED bool default y @@ -299,6 +311,10 @@ config SOC_SHA_SUPPORT_SHA256 bool default y +config SOC_ECC_CONSTANT_TIME_POINT_MUL + bool + default y + config SOC_SPI_PERIPH_NUM int default 2 diff --git a/components/soc/esp32h21/include/soc/soc_caps.h b/components/soc/esp32h21/include/soc/soc_caps.h index ab40d193d2ea..207c2080fb50 100644 --- a/components/soc/esp32h21/include/soc/soc_caps.h +++ b/components/soc/esp32h21/include/soc/soc_caps.h @@ -43,12 +43,12 @@ // #define SOC_I2C_SUPPORTED 1 //TODO: [ESP32H21] IDF-11578, IDF-11580 #define SOC_SYSTIMER_SUPPORTED 1 //TODO: [ESP32H21] IDF-11596, IDF-11598 // #define SOC_SUPPORT_COEXISTENCE 1 //TODO: [ESP32H21] IDF-11658, IDF-11659, IDF-11660 -// #define SOC_MPI_SUPPORTED 1 +#define SOC_MPI_SUPPORTED 1 // #define SOC_SHA_SUPPORTED 1 //TODO: [ESP32H21] IDF-11501 // #define SOC_HMAC_SUPPORTED 1 //TODO: [ESP32H21] IDF-11495 // #define SOC_DIG_SIGN_SUPPORTED 1 //TODO: [ESP32H21] IDF-11497 -// #define SOC_ECC_SUPPORTED 1 //TODO: [ESP32H21] IDF-11502 -// #define SOC_ECC_EXTENDED_MODES_SUPPORTED 1 //TODO: [ESP32H21] IDF-11502 +#define SOC_ECC_SUPPORTED 1 +#define SOC_ECC_EXTENDED_MODES_SUPPORTED 1 // #define SOC_ECDSA_SUPPORTED 1 //TODO: [ESP32H21] IDF-11496 #define SOC_FLASH_ENC_SUPPORTED 1 //TODO: [ESP32H21] IDF-11499 // #define SOC_SECURE_BOOT_SUPPORTED 1 //TODO: [ESP32H21] IDF-11500 @@ -373,6 +373,9 @@ #define SOC_SHA_SUPPORT_SHA224 (1) #define SOC_SHA_SUPPORT_SHA256 (1) +/*--------------------------- ECC CAPS ---------------------------------------*/ +#define SOC_ECC_CONSTANT_TIME_POINT_MUL 1 + /*-------------------------- SPI CAPS ----------------------------------------*/ #define SOC_SPI_PERIPH_NUM 2 #define SOC_SPI_PERIPH_CS_NUM(i) 6 diff --git a/components/soc/esp32h21/include/soc/system_intr.h b/components/soc/esp32h21/include/soc/system_intr.h new file mode 100644 index 000000000000..69134abba568 --- /dev/null +++ b/components/soc/esp32h21/include/soc/system_intr.h @@ -0,0 +1,12 @@ +/** + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +// Maps misc system interrupt to hardware interrupt names +#define SYS_CPU_INTR_FROM_CPU_0_SOURCE ETS_CPU_INTR_FROM_CPU_0_SOURCE + +#define SYS_TG0_WDT_INTR_SOURCE ETS_TG0_WDT_INTR_SOURCE +#define SYS_TG1_WDT_INTR_SOURCE ETS_TG1_WDT_INTR_SOURCE diff --git a/components/soc/esp32h21/mpi_periph.c b/components/soc/esp32h21/mpi_periph.c new file mode 100644 index 000000000000..247af09430e7 --- /dev/null +++ b/components/soc/esp32h21/mpi_periph.c @@ -0,0 +1,21 @@ +/* + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "soc/rsa_reg.h" +#include "soc/mpi_periph.h" + +const uint32_t MPI_BLOCK_BASES[SOC_MPI_MEM_BLOCKS_NUM] = { + RSA_X_MEM, + RSA_Y_MEM, + RSA_Z_MEM, + RSA_M_MEM, +}; + +const uint32_t MPI_OPERATIONS_REG[SOC_MPI_OPERATIONS_NUM] = { + RSA_SET_START_MULT_REG, + RSA_SET_START_MODMULT_REG, + RSA_SET_START_MODEXP_REG, +}; diff --git a/components/soc/esp32h21/register/soc/plic_reg.h b/components/soc/esp32h21/register/soc/plic_reg.h index c9baf66064ba..5cfc6bd20cda 100644 --- a/components/soc/esp32h21/register/soc/plic_reg.h +++ b/components/soc/esp32h21/register/soc/plic_reg.h @@ -10,7 +10,6 @@ extern "C" { #endif -//TODO: [ESP32H21] IDF-11859 #define DR_REG_PLIC_MX_BASE ( 0x20001000 ) #define DR_REG_PLIC_UX_BASE ( 0x20001400 ) diff --git a/components/soc/esp32p4/emac_periph.c b/components/soc/esp32p4/emac_periph.c index 2ae26ddd25a0..8482d97205ff 100644 --- a/components/soc/esp32p4/emac_periph.c +++ b/components/soc/esp32p4/emac_periph.c @@ -25,7 +25,9 @@ const emac_io_info_t emac_io_idx = { .mii_col_i_idx = EMAC_PHY_COL_PAD_IN_IDX, .mii_crs_i_idx = EMAC_PHY_CRS_PAD_IN_IDX, .mii_tx_er_o_idx = EMAC_PHY_TXER_PAD_OUT_IDX, - .mii_rx_er_i_idx = EMAC_PHY_RXER_PAD_IN_IDX + .mii_rx_er_i_idx = EMAC_PHY_RXER_PAD_IN_IDX, + .rmii_refclk_i_idx = SIG_GPIO_OUT_IDX, + .rmii_refclk_o_idx = SIG_GPIO_OUT_IDX }; static const emac_iomux_info_t emac_rmii_iomux_clki[] = { diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index c62bcfd0cd81..c5b719d7630b 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -219,6 +219,10 @@ config SOC_BOD_SUPPORTED bool default y +config SOC_VBAT_SUPPORTED + bool + default y + config SOC_APM_SUPPORTED bool default y @@ -335,6 +339,10 @@ config SOC_BITSCRAMBLER_SUPPORTED bool default y +config SOC_SIMD_INSTRUCTION_SUPPORTED + bool + default y + config SOC_XTAL_SUPPORT_40M bool default y @@ -547,6 +555,10 @@ config SOC_CPU_HAS_LOCKUP_RESET bool default y +config SOC_SIMD_PREFERRED_DATA_ALIGNMENT + int + default 16 + config SOC_DS_SIGNATURE_MAX_BIT_LEN int default 4096 diff --git a/components/soc/esp32p4/include/soc/clic_reg.h b/components/soc/esp32p4/include/soc/clic_reg.h index 1bfe74d623e6..97a6e785940d 100644 --- a/components/soc/esp32p4/include/soc/clic_reg.h +++ b/components/soc/esp32p4/include/soc/clic_reg.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -14,95 +14,151 @@ extern "C" { #define CLIC_EXT_INTR_NUM_OFFSET 16 #define DUALCORE_CLIC_CTRL_OFF 0x10000 -#define DR_REG_CLIC_BASE ( 0x20800000 ) -#define DR_REG_CLIC_CTRL_BASE ( 0x20801000 ) +#define DR_REG_CLIC_BASE (0x20800000) +#define DR_REG_CLIC_CTRL_BASE (0x20801000) #define CLIC_INT_CONFIG_REG (DR_REG_CLIC_BASE + 0x0) -/* CLIC_INT_CONFIG_NMBITS : R/W ;bitpos:[6:5] ;default: 2'd0 ; */ -/*description: .*/ +/* CLIC_INT_CONFIG_NMBITS : RO ;bitpos:[6:5] ;default: 2'd0 ; */ +/*description: the effective number of bits in the privileged state.*/ #define CLIC_INT_CONFIG_NMBITS 0x00000003 -#define CLIC_INT_CONFIG_NMBITS_M ((CLIC_INT_CONFIG_NMBITS_V)<<(CLIC_INT_CONFIG_NMBITS_S)) +#define CLIC_INT_CONFIG_NMBITS_M ((CLIC_INT_CONFIG_NMBITS_V) << (CLIC_INT_CONFIG_NMBITS_S)) #define CLIC_INT_CONFIG_NMBITS_V 0x3 #define CLIC_INT_CONFIG_NMBITS_S 5 /* CLIC_INT_CONFIG_NLBITS : R/W ;bitpos:[4:1] ;default: 4'd0 ; */ -/*description: .*/ -#define CLIC_INT_CONFIG_NLBITS 0x0000000F -#define CLIC_INT_CONFIG_NLBITS_M ((CLIC_INT_CONFIG_NLBITS_V)<<(CCLIC_INT_CONFIG_NLBITS_S)) -#define CLIC_INT_CONFIG_NLBITS_V 0xF -#define CLIC_INT_CONFIG_NLBITS_S 1 -/* CLIC_INT_CONFIG_NVBITS : R/W ;bitpos:[0] ;default: 1'd1 ; */ -/*description: .*/ +/*description: interrupt priority effective digits, the maximum value is 8.*/ +#define CLIC_INT_CONFIG_MNLBITS 0x0000000F +#define CLIC_INT_CONFIG_MNLBITS_M ((CLIC_INT_CONFIG_MNLBITS_V) << (CLIC_INT_CONFIG_MNLBITS_S)) +#define CLIC_INT_CONFIG_MNLBITS_V 0xF +#define CLIC_INT_CONFIG_MNLBITS_S 1 +/* CLIC_INT_CONFIG_NVBITS : RO ;bitpos:[0] ;default: 1'd1 ; */ +/*description: hardware vector interrupt implementation flag bit.*/ #define CLIC_INT_CONFIG_NVBITS (BIT(0)) #define CLIC_INT_CONFIG_NVBITS_M (BIT(0)) #define CLIC_INT_CONFIG_NVBITS_V 0x1 #define CLIC_INT_CONFIG_NVBITS_S 0 #define CLIC_INT_INFO_REG (DR_REG_CLIC_BASE + 0x4) -/* CLIC_INT_INFO_NUM_INT : R/W ;bitpos:[24:21] ;default: 4'd0 ; */ -/*description: .*/ +/* CLIC_INT_INFO_NUM_INT : RO ;bitpos:[24:21] ;default: 4'd3 ; */ +/*description: The effective bits of priority in the CLICINTCTL register.*/ #define CLIC_INT_INFO_CTLBITS 0x0000000F -#define CLIC_INT_INFO_CTLBITS_M ((CLIC_INT_INFO_CTLBITS_V)<<(CLIC_INT_INFO_CTLBITS_S)) +#define CLIC_INT_INFO_CTLBITS_M ((CLIC_INT_INFO_CTLBITS_V) << (CLIC_INT_INFO_CTLBITS_S)) #define CLIC_INT_INFO_CTLBITS_V 0xF #define CLIC_INT_INFO_CTLBITS_S 21 -/* CLIC_INT_INFO_VERSION : R/W ;bitpos:[20:13] ;default: 8'd0 ; */ -/*description: .*/ +/* CLIC_INT_INFO_VERSION : RO ;bitpos:[20:13] ;default: 8'd0 ; */ +/*description: The lower 4 bits are the modified version of the hardware implementation; the upper 4 bits are the CLIC +architecture version information.*/ #define CLIC_INT_INFO_VERSION 0x000000FF -#define CLIC_INT_INFO_VERSION_M ((CLIC_INT_INFO_VERSION_V)<<(CLIC_INT_INFO_VERSION_S)) +#define CLIC_INT_INFO_VERSION_M ((CLIC_INT_INFO_VERSION_V) << (CLIC_INT_INFO_VERSION_S)) #define CLIC_INT_INFO_VERSION_V 0xFF #define CLIC_INT_INFO_VERSION_S 13 -/* CLIC_INT_INFO_NUM_INT : R/W ;bitpos:[12:0] ;default: 13'd0 ; */ -/*description: .*/ +/* CLIC_INT_INFO_NUM_INT : RO ;bitpos:[12:0] ;default: 13'd48 ; */ +/*description: number of interrupt sources.*/ #define CLIC_INT_INFO_NUM_INT 0x00001FFF -#define CLIC_INT_INFO_NUM_INT_M ((CLIC_INT_INFO_NUM_INT_V)<<(CLIC_INT_INFO_NUM_INT_S)) +#define CLIC_INT_INFO_NUM_INT_M ((CLIC_INT_INFO_NUM_INT_V) << (CLIC_INT_INFO_NUM_INT_S)) #define CLIC_INT_INFO_NUM_INT_V 0x1FFF #define CLIC_INT_INFO_NUM_INT_S 0 #define CLIC_INT_THRESH_REG (DR_REG_CLIC_BASE + 0x8) /* CLIC_CPU_INT_THRESH : R/W ;bitpos:[31:24] ;default: 8'd0 ; */ -/*description: .*/ +/*description: Threshold for machine mode interruption..*/ #define CLIC_CPU_INT_THRESH 0x000000FF -#define CLIC_CPU_INT_THRESH_M ((CLIC_CPU_INT_THRESH_V)<<(CLIC_CPU_INT_THRESH_S)) +#define CLIC_CPU_INT_THRESH_M ((CLIC_CPU_INT_THRESH_V) << (CLIC_CPU_INT_THRESH_S)) #define CLIC_CPU_INT_THRESH_V 0xFF #define CLIC_CPU_INT_THRESH_S 24 -#define CLIC_INT_CTRL_REG(i) (DR_REG_CLIC_CTRL_BASE + (i) * 4) -/* CLIC_INT_CTL : R/W ;bitpos:[31:24] ;default: 8'd0 ; */ -/*description: .*/ +#define CLIC_INT_CTRL_REG(i) (DR_REG_CLIC_CTRL_BASE + (i)*4) +/* CLIC_INT_CTL : R/W ;bitpos:[31:24] ;default: 8'h1f ; */ +/*description: This register is used to indicate the priority of each interrupt +source participating in the arbitration, and at the same time to cooperate with +CLICCFG.nlbits to generate the interrupt priority to the CPU.*/ #define CLIC_INT_CTL 0x000000FF -#define CLIC_INT_CTL_M ((CLIC_INT_CTL_V)<<(CLIC_INT_CTL_S)) +#define CLIC_INT_CTL_M ((CLIC_INT_CTL_V) << (CLIC_INT_CTL_S)) #define CLIC_INT_CTL_V 0xFF #define CLIC_INT_CTL_S 24 -/* CLIC_INT_ATTR_MODE : R/W ;bitpos:[23:22] ;default: 2'b11 ; */ -/*description: .*/ +/* CLIC_INT_ATTR_MODE : RO ;bitpos:[23:22] ;default: 2'b11 ; */ +/*description: This field is used to configure the privileged mode of the interrupt.*/ #define CLIC_INT_ATTR_MODE 0x00000003 -#define CLIC_INT_ATTR_MODE_M ((CLIC_INT_ATTR_MODE_V)<<(CLIC_INT_ATTR_MODE_S)) +#define CLIC_INT_ATTR_MODE_M ((CLIC_INT_ATTR_MODE_V) << (CLIC_INT_ATTR_MODE_S)) #define CLIC_INT_ATTR_MODE_V 0x3 #define CLIC_INT_ATTR_MODE_S 22 /* CLIC_INT_ATTR_TRIG : R/W ;bitpos:[18:17] ;default: 2'd0 ; */ -/*description: .*/ +/*description: This field is used to distinguish pulse interruption and level +interruption. When trig[0] is 0, it means level interruption. When trig[0] is 1, +trig[1] is 0, it means interrupt on rising edge, and trig[1] is 1 means interrupt +on falling edge.*/ #define CLIC_INT_ATTR_TRIG 0x00000003 -#define CLIC_INT_ATTR_TRIG_M ((CLIC_INT_ATTR_TRIG_V)<<(CLIC_INT_ATTR_TRIG_S)) +#define CLIC_INT_ATTR_TRIG_M ((CLIC_INT_ATTR_TRIG_V) << (CLIC_INT_ATTR_TRIG_S)) #define CLIC_INT_ATTR_TRIG_V 0x3 #define CLIC_INT_ATTR_TRIG_S 17 /* CLIC_INT_ATTR_SHV : R/W ;bitpos:[16] ;default: 1'd0 ; */ -/*description: .*/ +/*description: Represents whether the interrupt is a hardware vector interrupt.*/ #define CLIC_INT_ATTR_SHV (BIT(16)) #define CLIC_INT_ATTR_SHV_M (BIT(16)) #define CLIC_INT_ATTR_SHV_V 0x1 #define CLIC_INT_ATTR_SHV_S 16 /* CLIC_INT_IE : R/W ;bitpos:[8] ;default: 1'd0 ; */ -/*description: .*/ +/*description: Interrupt Enable Register.*/ #define CLIC_INT_IE (BIT(8)) #define CLIC_INT_IE_M (BIT(8)) #define CLIC_INT_IE_V 0x1 #define CLIC_INT_IE_S 8 /* CLIC_INT_IP : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: .*/ +/*description: Interrupt Pending Register. This bit has different set and clear logic in the +case of level interrupt and edge interrupt*/ #define CLIC_INT_IP (BIT(0)) #define CLIC_INT_IP_M (BIT(0)) #define CLIC_INT_IP_V 0x1 #define CLIC_INT_IP_S 0 +// each of following registers are 8bits +#define BYTE_CLIC_INT_IP_REG(i) (DR_REG_CLIC_CTRL_BASE + (i) * 4) +/* BYTE_CLIC_INT_IP : R/W ;bitpos:[0] ;default: 1'd0 ; */ +/*description: Interrupt Pending Register. This bit has different set and clear logic in the +case of level interrupt and edge interrupt*/ +#define BYTE_CLIC_INT_IP (BIT(0)) +#define BYTE_CLIC_INT_IP_M (BIT(0)) +#define BYTE_CLIC_INT_IP_V 0x1 +#define BYTE_CLIC_INT_IP_S 0 + +#define BYTE_CLIC_INT_IE_REG(i) (DR_REG_CLIC_CTRL_BASE + 1 + (i) * 4) +/* BYTE_CLIC_INT_IE : R/W ;bitpos:[0] ;default: 1'd0 ; */ +/*description: Interrupt Enable Register.*/ +#define BYTE_CLIC_INT_IE (BIT(0)) +#define BYTE_CLIC_INT_IE_M (BIT(0)) +#define BYTE_CLIC_INT_IE_V 0x1 +#define BYTE_CLIC_INT_IE_S 0 + +#define BYTE_CLIC_INT_ATTR_REG(i) (DR_REG_CLIC_CTRL_BASE + 2 + (i) * 4) +/* BYTE_CLIC_INT_ATTR_SHV : R/W ;bitpos:[0] ;default: 1'd0 ; */ +/*description: 1 means hardware vector interrupt.*/ +#define BYTE_CLIC_INT_ATTR_SHV (BIT(0)) +#define BYTE_CLIC_INT_ATTR_SHV_M (BIT(0)) +#define BYTE_CLIC_INT_ATTR_SHV_V 0x1 +#define BYTE_CLIC_INT_ATTR_SHV_S 0 +/* BYTE_CLIC_INT_ATTR_TRIG: R/W ; bitpos:[2:1] ;default: 2'd0 ; */ +/*description: + [X0] -> level trigger + [01] -> rising edge trigger + [11] -> falling edge trigger */ +#define BYTE_CLIC_INT_ATTR_TRIG 0x00000003 +#define BYTE_CLIC_INT_ATTR_TRIG_M ((BYTE_CLIC_INT_ATTR_TRIG_V) << (BYTE_CLIC_INT_ATTR_TRIG_S)) +#define BYTE_CLIC_INT_ATTR_TRIG_V 0x3 +#define BYTE_CLIC_INT_ATTR_TRIG_S 1 +/* BYTE_CLIC_INT_ATTR_MODE: RO ; bitpos:[7:6] ;default: 2'd0 ; */ +/*description: privilege level for interrupt, fixed to 2'b11 */ +#define BYTE_CLIC_INT_ATTR_MODE 0x00000003 +#define BYTE_CLIC_INT_ATTR_MODE_M ((BYTE_CLIC_INT_ATTR_MODE_V) << (BYTE_CLIC_INT_ATTR_MODE_S)) +#define BYTE_CLIC_INT_ATTR_MODE_V 0x3 +#define BYTE_CLIC_INT_ATTR_MODE_S 6 + +#define BYTE_CLIC_INT_CTL_REG(i) (DR_REG_CLIC_CTRL_BASE + 3 + (i) * 4) +/* BYTE_CLIC_INT_ATTR_MODE: R/W ; bitpos:[7:5] ;default: 3'd0 ; */ +/*description: interrupt priority */ +#define BYTE_CLIC_INT_CTL 0x00000007 +#define BYTE_CLIC_INT_CTL_M ((BYTE_CLIC_INT_CTL_V) << (BYTE_CLIC_INT_CTL_S)) +#define BYTE_CLIC_INT_CTL_V 0x7 +#define BYTE_CLIC_INT_CTL_S 5 + #ifdef __cplusplus } #endif diff --git a/components/soc/esp32p4/include/soc/regi2c_brownout.h b/components/soc/esp32p4/include/soc/regi2c_brownout.h index b7297808f491..6637ae9662b3 100644 --- a/components/soc/esp32p4/include/soc/regi2c_brownout.h +++ b/components/soc/esp32p4/include/soc/regi2c_brownout.h @@ -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 */ @@ -23,3 +23,26 @@ #define I2C_BOD_THRESHOLD_H 0x9 #define I2C_BOD_THRESHOLD_H_MSB 7 #define I2C_BOD_THRESHOLD_H_LSB 5 + +#define I2C_BIAS_OR_DREF_VBAT_L 8 +#define I2C_BIAS_OR_DREF_VBAT_L_MSB 4 +#define I2C_BIAS_OR_DREF_VBAT_L_LSB 2 +#define I2C_BIAS_OR_DREF_VBAT_H 8 +#define I2C_BIAS_OR_DREF_VBAT_H_MSB 7 +#define I2C_BIAS_OR_DREF_VBAT_H_LSB 5 + +#define I2C_BIAS_OR_DREF_VBAT_CHARGER_L 10 +#define I2C_BIAS_OR_DREF_VBAT_CHARGER_L_MSB 4 +#define I2C_BIAS_OR_DREF_VBAT_CHARGER_L_LSB 2 +#define I2C_BIAS_OR_DREF_VBAT_CHARGER_H 10 +#define I2C_BIAS_OR_DREF_VBAT_CHARGER_H_MSB 7 +#define I2C_BIAS_OR_DREF_VBAT_CHARGER_H_LSB 5 + +#define I2C_BIAS_OR_FORCE_PU_VBAT_CHARGER 10 +#define I2C_BIAS_OR_FORCE_PU_VBAT_CHARGER_MSB 0 +#define I2C_BIAS_OR_FORCE_PU_VBAT_CHARGER_LSB 0 + +/** Change the charging current by adjusting the value of the series resistor. 1kΩ + N * 0.5kΩ */ +#define I2C_BIAS_OR_DRES_CHARGER 3 +#define I2C_BIAS_OR_DRES_CHARGER_MSB 7 +#define I2C_BIAS_OR_DRES_CHARGER_LSB 4 diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index b09328f48ce9..3e4ed6d390d4 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -71,6 +71,7 @@ #define SOC_FLASH_ENC_SUPPORTED 1 #define SOC_SECURE_BOOT_SUPPORTED 1 #define SOC_BOD_SUPPORTED 1 +#define SOC_VBAT_SUPPORTED 1 #define SOC_APM_SUPPORTED 1 #define SOC_PMU_SUPPORTED 1 #define SOC_DCDC_SUPPORTED 1 @@ -100,6 +101,7 @@ #define SOC_DEEP_SLEEP_SUPPORTED 1 #define SOC_PM_SUPPORTED 1 #define SOC_BITSCRAMBLER_SUPPORTED 1 +#define SOC_SIMD_INSTRUCTION_SUPPORTED 1 /*-------------------------- XTAL CAPS ---------------------------------------*/ #define SOC_XTAL_SUPPORT_40M 1 @@ -191,6 +193,8 @@ #define SOC_CPU_HAS_LOCKUP_RESET 1 +#define SOC_SIMD_PREFERRED_DATA_ALIGNMENT 16 // The preferred data alignment accepted by the SIMD instructions, in bytes + /*-------------------------- DIGITAL SIGNATURE CAPS ----------------------------------------*/ /** The maximum length of a Digital Signature in bits. */ #define SOC_DS_SIGNATURE_MAX_BIT_LEN (4096) diff --git a/components/soc/esp32p4/include/soc/system_intr.h b/components/soc/esp32p4/include/soc/system_intr.h new file mode 100644 index 000000000000..a681733c8def --- /dev/null +++ b/components/soc/esp32p4/include/soc/system_intr.h @@ -0,0 +1,13 @@ +/** + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +// Maps misc system interrupt to hardware interrupt names +#define SYS_CPU_INTR_FROM_CPU_0_SOURCE ETS_FROM_CPU_INTR0_SOURCE +#define SYS_CPU_INTR_FROM_CPU_1_SOURCE ETS_FROM_CPU_INTR1_SOURCE + +#define SYS_TG0_WDT_INTR_SOURCE ETS_TG0_WDT_LEVEL_INTR_SOURCE +#define SYS_TG1_WDT_INTR_SOURCE ETS_TG1_WDT_LEVEL_INTR_SOURCE diff --git a/components/soc/esp32p4/register/soc/bitscrambler_struct.h b/components/soc/esp32p4/register/soc/bitscrambler_struct.h index aeb4fee033c1..c21874b22666 100644 --- a/components/soc/esp32p4/register/soc/bitscrambler_struct.h +++ b/components/soc/esp32p4/register/soc/bitscrambler_struct.h @@ -593,7 +593,7 @@ typedef struct { bitscrambler_lut_cfg0_reg_t cfg0; bitscrambler_lut_cfg1_reg_t cfg1; } lut_cfg[2]; - volatile bitscrambler_tailing_bits_reg_t tailing_bits[2]; + volatile bitscrambler_tailing_bits_reg_t tail_bits[2]; volatile bitscrambler_ctrl_reg_t ctrl[2]; volatile bitscrambler_state_reg_t state[2]; uint32_t reserved_038[48]; diff --git a/components/soc/esp32p4/temperature_sensor_periph.c b/components/soc/esp32p4/temperature_sensor_periph.c index a681a41e3ba3..2b831ba45c55 100644 --- a/components/soc/esp32p4/temperature_sensor_periph.c +++ b/components/soc/esp32p4/temperature_sensor_periph.c @@ -6,7 +6,7 @@ #include "soc/temperature_sensor_periph.h" -const temperature_sensor_attribute_t temperature_sensor_attributes[TEMPERATURE_SENSOR_ATTR_RANGE_NUM] = { +temperature_sensor_attribute_t temperature_sensor_attributes[TEMPERATURE_SENSOR_ATTR_RANGE_NUM] = { /*Offset reg_val min max error */ {-2, 5, 50, 125, 3}, {-1, 7, 20, 100, 2}, diff --git a/components/soc/esp32s2/include/soc/system_intr.h b/components/soc/esp32s2/include/soc/system_intr.h new file mode 100644 index 000000000000..9f7be4017249 --- /dev/null +++ b/components/soc/esp32s2/include/soc/system_intr.h @@ -0,0 +1,12 @@ +/** + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +// Maps misc system interrupt to hardware interrupt names +#define SYS_CPU_INTR_FROM_CPU_0_SOURCE ETS_FROM_CPU_INTR0_SOURCE + +#define SYS_TG0_WDT_INTR_SOURCE ETS_TG0_WDT_LEVEL_INTR_SOURCE +#define SYS_TG1_WDT_INTR_SOURCE ETS_TG1_WDT_LEVEL_INTR_SOURCE diff --git a/components/soc/esp32s2/register/soc/rtc_io_struct.h b/components/soc/esp32s2/register/soc/rtc_io_struct.h index cc10eabcf2fc..71642c1a1fee 100644 --- a/components/soc/esp32s2/register/soc/rtc_io_struct.h +++ b/components/soc/esp32s2/register/soc/rtc_io_struct.h @@ -117,7 +117,7 @@ typedef volatile struct rtc_io_dev_s { uint32_t xpd: 1; /*TOUCH_XPD*/ uint32_t tie_opt: 1; /*TOUCH_TIE_OPT*/ uint32_t start: 1; /*TOUCH_START*/ - uint32_t dac: 3; /*TOUCH_DAC*/ + uint32_t slope: 3; /*TOUCH_SLOPE*/ uint32_t reserved26: 1; uint32_t rue: 1; /*RUE*/ uint32_t rde: 1; /*RDE*/ diff --git a/components/soc/esp32s2/temperature_sensor_periph.c b/components/soc/esp32s2/temperature_sensor_periph.c index e75c60b31783..165403570fee 100644 --- a/components/soc/esp32s2/temperature_sensor_periph.c +++ b/components/soc/esp32s2/temperature_sensor_periph.c @@ -5,8 +5,9 @@ */ #include "soc/temperature_sensor_periph.h" +#include "esp_attr.h" -const temperature_sensor_attribute_t temperature_sensor_attributes[TEMPERATURE_SENSOR_ATTR_RANGE_NUM] = { +DRAM_ATTR temperature_sensor_attribute_t temperature_sensor_attributes[TEMPERATURE_SENSOR_ATTR_RANGE_NUM] = { /*Offset reg_val min max error */ {-2, 5, 50, 125, 3}, {-1, 7, 20, 100, 2}, diff --git a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in index 4e60e5ac6e5d..0ac4830bf4ee 100644 --- a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in @@ -243,6 +243,10 @@ config SOC_PM_SUPPORTED bool default y +config SOC_SIMD_INSTRUCTION_SUPPORTED + bool + default y + config SOC_XTAL_SUPPORT_40M bool default y @@ -395,6 +399,10 @@ config SOC_CPU_WATCHPOINT_MAX_REGION_SIZE int default 64 +config SOC_SIMD_PREFERRED_DATA_ALIGNMENT + int + default 16 + config SOC_DS_SIGNATURE_MAX_BIT_LEN int default 4096 diff --git a/components/soc/esp32s3/include/soc/soc_caps.h b/components/soc/esp32s3/include/soc/soc_caps.h index 51e6fed5b45d..ae28654f8edb 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -82,6 +82,7 @@ #define SOC_DEEP_SLEEP_SUPPORTED 1 #define SOC_LP_PERIPH_SHARE_INTERRUPT 1 // LP peripherals sharing the same interrupt source #define SOC_PM_SUPPORTED 1 +#define SOC_SIMD_INSTRUCTION_SUPPORTED 1 /*-------------------------- XTAL CAPS ---------------------------------------*/ #define SOC_XTAL_SUPPORT_40M 1 @@ -148,6 +149,8 @@ #define SOC_CPU_WATCHPOINTS_NUM 2 #define SOC_CPU_WATCHPOINT_MAX_REGION_SIZE 64 // bytes +#define SOC_SIMD_PREFERRED_DATA_ALIGNMENT 16 // The preferred data alignment accepted by the SIMD instructions, in bytes + /*-------------------------- DIGITAL SIGNATURE CAPS ----------------------------------------*/ /** The maximum length of a Digital Signature in bits. */ #define SOC_DS_SIGNATURE_MAX_BIT_LEN (4096) diff --git a/components/soc/esp32s3/include/soc/system_intr.h b/components/soc/esp32s3/include/soc/system_intr.h new file mode 100644 index 000000000000..a681733c8def --- /dev/null +++ b/components/soc/esp32s3/include/soc/system_intr.h @@ -0,0 +1,13 @@ +/** + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +// Maps misc system interrupt to hardware interrupt names +#define SYS_CPU_INTR_FROM_CPU_0_SOURCE ETS_FROM_CPU_INTR0_SOURCE +#define SYS_CPU_INTR_FROM_CPU_1_SOURCE ETS_FROM_CPU_INTR1_SOURCE + +#define SYS_TG0_WDT_INTR_SOURCE ETS_TG0_WDT_LEVEL_INTR_SOURCE +#define SYS_TG1_WDT_INTR_SOURCE ETS_TG1_WDT_LEVEL_INTR_SOURCE diff --git a/components/soc/esp32s3/temperature_sensor_periph.c b/components/soc/esp32s3/temperature_sensor_periph.c index e75c60b31783..165403570fee 100644 --- a/components/soc/esp32s3/temperature_sensor_periph.c +++ b/components/soc/esp32s3/temperature_sensor_periph.c @@ -5,8 +5,9 @@ */ #include "soc/temperature_sensor_periph.h" +#include "esp_attr.h" -const temperature_sensor_attribute_t temperature_sensor_attributes[TEMPERATURE_SENSOR_ATTR_RANGE_NUM] = { +DRAM_ATTR temperature_sensor_attribute_t temperature_sensor_attributes[TEMPERATURE_SENSOR_ATTR_RANGE_NUM] = { /*Offset reg_val min max error */ {-2, 5, 50, 125, 3}, {-1, 7, 20, 100, 2}, diff --git a/components/soc/include/soc/emac_periph.h b/components/soc/include/soc/emac_periph.h index ad1807064394..9ada2b173b92 100644 --- a/components/soc/include/soc/emac_periph.h +++ b/components/soc/include/soc/emac_periph.h @@ -38,6 +38,8 @@ typedef struct { uint32_t mii_crs_i_idx; uint32_t mii_rx_er_i_idx; uint32_t mii_tx_er_o_idx; + uint32_t rmii_refclk_i_idx; + uint32_t rmii_refclk_o_idx; } emac_io_info_t; typedef struct { diff --git a/components/soc/include/soc/temperature_sensor_periph.h b/components/soc/include/soc/temperature_sensor_periph.h index d52739255415..e82ff3f7be23 100644 --- a/components/soc/include/soc/temperature_sensor_periph.h +++ b/components/soc/include/soc/temperature_sensor_periph.h @@ -25,7 +25,7 @@ typedef struct { int error_max; } temperature_sensor_attribute_t; -extern const temperature_sensor_attribute_t temperature_sensor_attributes[TEMPERATURE_SENSOR_ATTR_RANGE_NUM]; +extern temperature_sensor_attribute_t temperature_sensor_attributes[TEMPERATURE_SENSOR_ATTR_RANGE_NUM]; #if SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION typedef struct { diff --git a/components/spi_flash/test_apps/esp_flash/pytest_esp_flash.py b/components/spi_flash/test_apps/esp_flash/pytest_esp_flash.py index 8d1ae4371509..93dc7627c2fa 100644 --- a/components/spi_flash/test_apps/esp_flash/pytest_esp_flash.py +++ b/components/spi_flash/test_apps/esp_flash/pytest_esp_flash.py @@ -25,6 +25,8 @@ def test_esp_flash(dut: Dut) -> None: @pytest.mark.esp32c2 @pytest.mark.esp32c6 @pytest.mark.esp32h2 +@pytest.mark.esp32c5 +@pytest.mark.esp32c61 @pytest.mark.generic @pytest.mark.parametrize( 'config', diff --git a/components/spi_flash/test_apps/esp_flash/sdkconfig.ci.rom_patch b/components/spi_flash/test_apps/esp_flash/sdkconfig.ci.rom_patch new file mode 100644 index 000000000000..fd63e157f937 --- /dev/null +++ b/components/spi_flash/test_apps/esp_flash/sdkconfig.ci.rom_patch @@ -0,0 +1 @@ +CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=n diff --git a/components/tcp_transport/include/esp_transport_ssl.h b/components/tcp_transport/include/esp_transport_ssl.h index ca2355a11d12..ad339396ffce 100644 --- a/components/tcp_transport/include/esp_transport_ssl.h +++ b/components/tcp_transport/include/esp_transport_ssl.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -45,7 +45,7 @@ void esp_transport_ssl_set_cert_data(esp_transport_handle_t t, const char *data, void esp_transport_ssl_set_cert_data_der(esp_transport_handle_t t, const char *data, int len); /** - * @brief Enable the use of certification bundle for server verfication for + * @brief Enable the use of certification bundle for server verification for * an SSL connection. * It must be first enabled in menuconfig. * @@ -211,6 +211,14 @@ void esp_transport_ssl_set_keep_alive(esp_transport_handle_t t, esp_transport_ke */ void esp_transport_ssl_set_interface_name(esp_transport_handle_t t, struct ifreq *if_name); +/** + * @brief Set addr family of transport + * + * @param[in] t The transport handle + * @param[in] addr_family The addr family + */ +void esp_transport_ssl_set_addr_family(esp_transport_handle_t t, esp_tls_addr_family_t addr_family); + #ifdef CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS /** * @brief Session ticket operation diff --git a/components/tcp_transport/transport_ssl.c b/components/tcp_transport/transport_ssl.c index 0a3adbac3b24..00bd8d2fffcc 100644 --- a/components/tcp_transport/transport_ssl.c +++ b/components/tcp_transport/transport_ssl.c @@ -397,6 +397,12 @@ void esp_transport_ssl_set_client_cert_data(esp_transport_handle_t t, const char ssl->cfg.clientcert_pem_bytes = len + 1; } +void esp_transport_ssl_set_addr_family(esp_transport_handle_t t, esp_tls_addr_family_t addr_family) +{ + GET_SSL_FROM_TRANSPORT_OR_RETURN(ssl, t); + ssl->cfg.addr_family = addr_family; +} + #ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN void esp_transport_ssl_set_client_key_ecdsa_peripheral(esp_transport_handle_t t, uint8_t ecdsa_efuse_blk) { diff --git a/components/usb/CMakeLists.txt b/components/usb/CMakeLists.txt index f81514661950..fc4c06026efe 100644 --- a/components/usb/CMakeLists.txt +++ b/components/usb/CMakeLists.txt @@ -19,12 +19,9 @@ if(CONFIG_SOC_USB_OTG_SUPPORTED) "usb_helpers.c" "usb_host.c" "usb_private.c" - "usbh.c") - if(NOT ${target} STREQUAL "esp32p4") - list(APPEND srcs "usb_phy.c") - else() - list(APPEND srcs "usb_phy_p4.c") - endif() + "usbh.c" + "usb_phy.c" + ) list(APPEND include "include") list(APPEND priv_includes "private_include") endif() diff --git a/components/usb/include/esp_private/usb_phy.h b/components/usb/include/esp_private/usb_phy.h index e8e892a856e6..74a25ccc3482 100644 --- a/components/usb/include/esp_private/usb_phy.h +++ b/components/usb/include/esp_private/usb_phy.h @@ -11,6 +11,8 @@ #include "soc/soc_caps.h" #include "hal/usb_phy_types.h" +#define USB_PHY_SUPPORTS_P4_OTG11 1 // This version of usb_phy supports P4 OTG1.1 PHY + #ifdef __cplusplus extern "C" { #endif diff --git a/components/usb/include/usb/usb_host.h b/components/usb/include/usb/usb_host.h index d5036fdad9bf..0524674822c5 100644 --- a/components/usb/include/usb/usb_host.h +++ b/components/usb/include/usb/usb_host.h @@ -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 */ diff --git a/components/usb/test_apps/.build-test-rules.yml b/components/usb/test_apps/.build-test-rules.yml index 44446d7b2255..947b7394a3ca 100644 --- a/components/usb/test_apps/.build-test-rules.yml +++ b/components/usb/test_apps/.build-test-rules.yml @@ -21,10 +21,6 @@ components/usb/test_apps: components/usb/test_apps/phy: enable: - if: SOC_USB_OTG_SUPPORTED == 1 - disable_test: - - if: IDF_TARGET in ["esp32p4"] - temporary: true - reason: ESP32-P4 PHY driver not yet migrated depends_components: - usb depends_filepatterns: diff --git a/components/usb/test_apps/hcd/CMakeLists.txt b/components/usb/test_apps/hcd/CMakeLists.txt index 3294266f463b..f22a5c347adf 100644 --- a/components/usb/test_apps/hcd/CMakeLists.txt +++ b/components/usb/test_apps/hcd/CMakeLists.txt @@ -6,6 +6,6 @@ include($ENV{IDF_PATH}/tools/cmake/project.cmake) set(EXTRA_COMPONENT_DIRS "../common") # "Trim" the build. Include the minimal set of components, main, and anything it depends on. -set(COMPONENTS main) +idf_build_set_property(MINIMAL_BUILD ON) project(test_app_usb_host) diff --git a/components/usb/test_apps/hcd/main/test_hcd_common.c b/components/usb/test_apps/hcd/main/test_hcd_common.c index dbc2896028aa..77d5366277c1 100644 --- a/components/usb/test_apps/hcd/main/test_hcd_common.c +++ b/components/usb/test_apps/hcd/main/test_hcd_common.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 */ @@ -159,7 +159,11 @@ hcd_port_handle_t test_hcd_setup(void) // Initialize the internal USB PHY to connect to the USB OTG peripheral usb_phy_config_t phy_config = { .controller = USB_PHY_CTRL_OTG, +#if CONFIG_IDF_TARGET_ESP32P4 // ESP32-P4 has 2 USB-DWC peripherals, each with its dedicated PHY. We support HS+UTMI only ATM. + .target = USB_PHY_TARGET_UTMI, +#else .target = USB_PHY_TARGET_INT, +#endif .otg_mode = USB_OTG_MODE_HOST, .otg_speed = USB_PHY_SPEED_UNDEFINED, // In Host mode, the speed is determined by the connected device .ext_io_conf = NULL, diff --git a/components/usb/test_apps/phy/CMakeLists.txt b/components/usb/test_apps/phy/CMakeLists.txt index 5724e9e64003..43d31c8c8cbe 100644 --- a/components/usb/test_apps/phy/CMakeLists.txt +++ b/components/usb/test_apps/phy/CMakeLists.txt @@ -4,6 +4,6 @@ cmake_minimum_required(VERSION 3.16) 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) +idf_build_set_property(MINIMAL_BUILD ON) project(test_app_usb_phy) diff --git a/components/usb/test_apps/phy/main/test_app_main.c b/components/usb/test_apps/phy/main/test_app_main.c index a7994e87999a..d8c9119f73f7 100644 --- a/components/usb/test_apps/phy/main/test_app_main.c +++ b/components/usb/test_apps/phy/main/test_app_main.c @@ -10,6 +10,7 @@ #include "esp_private/usb_phy.h" #include "hal/usb_wrap_ll.h" // For USB_WRAP_LL_EXT_PHY_SUPPORTED symbol #include "soc/soc_caps.h" // For SOC_USB_UTMI_PHY_NUM symbol +#include "sdkconfig.h" // For CONFIG_IDF_TARGET_*** #if USB_WRAP_LL_EXT_PHY_SUPPORTED #define EXT_PHY_SUPPORTED 1 @@ -55,9 +56,13 @@ void app_main(void) /** * Test init and deinit of internal FSLS PHY + * + * 1. Init + deinit in Host mode + * 2. Init + deinit in Device mode */ TEST_CASE("Init internal FSLS PHY", "[phy]") { + // Host mode usb_phy_handle_t phy_handle = NULL; const usb_phy_config_t phy_config = { .controller = USB_PHY_CTRL_OTG, @@ -70,6 +75,20 @@ TEST_CASE("Init internal FSLS PHY", "[phy]") TEST_ASSERT_EQUAL(ESP_OK, usb_new_phy(&phy_config, &phy_handle)); TEST_ASSERT_NOT_NULL(phy_handle); TEST_ASSERT_EQUAL(ESP_OK, usb_del_phy(phy_handle)); + + // Device mode + usb_phy_handle_t phy_handle_2 = NULL; + const usb_phy_config_t phy_config_2 = { + .controller = USB_PHY_CTRL_OTG, + .target = USB_PHY_TARGET_INT, + .otg_mode = USB_OTG_MODE_DEVICE, + .otg_speed = USB_PHY_SPEED_FULL, + .ext_io_conf = NULL, + .otg_io_conf = NULL, + }; + TEST_ASSERT_EQUAL(ESP_OK, usb_new_phy(&phy_config_2, &phy_handle_2)); + TEST_ASSERT_NOT_NULL(phy_handle_2); + TEST_ASSERT_EQUAL(ESP_OK, usb_del_phy(phy_handle_2)); } /** @@ -137,44 +156,85 @@ TEST_CASE("Init internal UTMI PHY", "[phy]") } /** - * Test init and deinit of all PHYs at the same time + * Test init and deinit of all PHYs at the same time multiple times */ -TEST_CASE("Init all PHYs", "[phy]") +TEST_CASE("Init all PHYs in a loop", "[phy]") { + for (int i = 0; i < 2; i++) { + usb_phy_handle_t phy_handle = NULL; + usb_phy_handle_t phy_handle_2 = NULL; + usb_phy_config_t phy_config = { + .controller = USB_PHY_CTRL_OTG, + .target = USB_PHY_TARGET_INT, + .otg_mode = USB_OTG_MODE_HOST, + .otg_speed = USB_PHY_SPEED_UNDEFINED, + .ext_io_conf = NULL, + .otg_io_conf = NULL, + }; + TEST_ASSERT_EQUAL(ESP_OK, usb_new_phy(&phy_config, &phy_handle)); + TEST_ASSERT_NOT_NULL(phy_handle); + + // Our current targets support either UTMI or external PHY + // so if/else suffice here +#if UTMI_PHY_SUPPORTED + phy_config.target = USB_PHY_TARGET_UTMI; +#else + phy_config.target = USB_PHY_TARGET_EXT; + const usb_phy_ext_io_conf_t ext_io_conf = { // Some random values + .vp_io_num = 1, + .vm_io_num = 1, + .rcv_io_num = 1, + .suspend_n_io_num = 1, + .oen_io_num = 1, + .vpo_io_num = 1, + .vmo_io_num = 1, + .fs_edge_sel_io_num = 1, + }; + phy_config.ext_io_conf = &ext_io_conf; +#endif + TEST_ASSERT_EQUAL(ESP_OK, usb_new_phy(&phy_config, &phy_handle_2)); + TEST_ASSERT_NOT_NULL(phy_handle_2); + + TEST_ASSERT_EQUAL(ESP_OK, usb_del_phy(phy_handle)); + TEST_ASSERT_EQUAL(ESP_OK, usb_del_phy(phy_handle_2)); + } +} + +#if CONFIG_IDF_TARGET_ESP32P4 +/** + * Test backward compatibility of ESP32-P4 PHY + * + * Initial P4 device support was for USB-DWC HS and UTMI PHY. To maintain backward compatibility on ESP32-P4 in USB Device mode, + * we select UTMI PHY in case otg_speed is UNDEFINED or HIGH + */ +TEST_CASE("ESP32-P4 TinyUSB backward compatibility", "[phy]") +{ + // This configuration is used in esp_tinyusb usb_phy_handle_t phy_handle = NULL; - usb_phy_handle_t phy_handle_2 = NULL; usb_phy_config_t phy_config = { .controller = USB_PHY_CTRL_OTG, .target = USB_PHY_TARGET_INT, - .otg_mode = USB_OTG_MODE_HOST, + .otg_mode = USB_OTG_MODE_DEVICE, .otg_speed = USB_PHY_SPEED_UNDEFINED, .ext_io_conf = NULL, .otg_io_conf = NULL, }; TEST_ASSERT_EQUAL(ESP_OK, usb_new_phy(&phy_config, &phy_handle)); TEST_ASSERT_NOT_NULL(phy_handle); + TEST_ASSERT_EQUAL(ESP_OK, usb_del_phy(phy_handle)); - // Our current targets support either UTMI or external PHY - // so if/else suffice here -#if UTMI_PHY_SUPPORTED - phy_config.target = USB_PHY_TARGET_UTMI; -#else - const usb_phy_ext_io_conf_t ext_io_conf = { // Some random values - .vp_io_num = 1, - .vm_io_num = 1, - .rcv_io_num = 1, - .suspend_n_io_num = 1, - .oen_io_num = 1, - .vpo_io_num = 1, - .vmo_io_num = 1, - .fs_edge_sel_io_num = 1, + // This configuration is used in upstream tinyusb examples + usb_phy_handle_t phy_handle_2 = NULL; + usb_phy_config_t phy_config_2 = { + .controller = USB_PHY_CTRL_OTG, + .target = USB_PHY_TARGET_INT, + .otg_mode = USB_OTG_MODE_DEVICE, + .otg_speed = USB_PHY_SPEED_HIGH, + .ext_io_conf = NULL, + .otg_io_conf = NULL, }; - phy_config.target = USB_PHY_TARGET_EXT; - phy_config.ext_io_conf = &ext_io_conf; -#endif - TEST_ASSERT_EQUAL(ESP_OK, usb_new_phy(&phy_config, &phy_handle_2)); + TEST_ASSERT_EQUAL(ESP_OK, usb_new_phy(&phy_config_2, &phy_handle_2)); TEST_ASSERT_NOT_NULL(phy_handle_2); - - TEST_ASSERT_EQUAL(ESP_OK, usb_del_phy(phy_handle)); TEST_ASSERT_EQUAL(ESP_OK, usb_del_phy(phy_handle_2)); } +#endif diff --git a/components/usb/test_apps/phy/pytest_usb_phy.py b/components/usb/test_apps/phy/pytest_usb_phy.py index 27cb20eca7b5..fef606d3f0bc 100644 --- a/components/usb/test_apps/phy/pytest_usb_phy.py +++ b/components/usb/test_apps/phy/pytest_usb_phy.py @@ -8,6 +8,5 @@ @pytest.mark.esp32s3 @pytest.mark.esp32p4 @pytest.mark.generic -@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='P4 PHY not yet migrated') def test_usb_phy(dut: Dut) -> None: dut.run_all_single_board_cases(group='phy') diff --git a/components/usb/test_apps/usb_host/CMakeLists.txt b/components/usb/test_apps/usb_host/CMakeLists.txt index 3294266f463b..f22a5c347adf 100644 --- a/components/usb/test_apps/usb_host/CMakeLists.txt +++ b/components/usb/test_apps/usb_host/CMakeLists.txt @@ -6,6 +6,6 @@ include($ENV{IDF_PATH}/tools/cmake/project.cmake) set(EXTRA_COMPONENT_DIRS "../common") # "Trim" the build. Include the minimal set of components, main, and anything it depends on. -set(COMPONENTS main) +idf_build_set_property(MINIMAL_BUILD ON) project(test_app_usb_host) diff --git a/components/usb/test_apps/usb_host/main/test_usb_host_common.c b/components/usb/test_apps/usb_host/main/test_usb_host_common.c index 1f2daa4e8832..854e23d3f780 100644 --- a/components/usb/test_apps/usb_host/main/test_usb_host_common.c +++ b/components/usb/test_apps/usb_host/main/test_usb_host_common.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 */ @@ -31,7 +31,11 @@ void test_usb_host_setup_phy(void) // Initialize the internal USB PHY to connect to the USB OTG peripheral usb_phy_config_t phy_config = { .controller = USB_PHY_CTRL_OTG, +#if CONFIG_IDF_TARGET_ESP32P4 // ESP32-P4 has 2 USB-DWC peripherals, each with its dedicated PHY. We support HS+UTMI only ATM. + .target = USB_PHY_TARGET_UTMI, +#else .target = USB_PHY_TARGET_INT, +#endif .otg_mode = USB_OTG_MODE_HOST, .otg_speed = USB_PHY_SPEED_UNDEFINED, // In Host mode, the speed is determined by the connected device .ext_io_conf = NULL, diff --git a/components/usb/usb_host.c b/components/usb/usb_host.c index 50a3722cd675..cc8a4dc83b92 100644 --- a/components/usb/usb_host.c +++ b/components/usb/usb_host.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 */ @@ -469,7 +469,11 @@ esp_err_t usb_host_install(const usb_host_config_t *config) // Host Library defaults to internal PHY usb_phy_config_t phy_config = { .controller = USB_PHY_CTRL_OTG, +#if CONFIG_IDF_TARGET_ESP32P4 // ESP32-P4 has 2 USB-DWC peripherals, each with its dedicated PHY. We support HS+UTMI only ATM. + .target = USB_PHY_TARGET_UTMI, +#else .target = USB_PHY_TARGET_INT, +#endif .otg_mode = USB_OTG_MODE_HOST, .otg_speed = USB_PHY_SPEED_UNDEFINED, // In Host mode, the speed is determined by the connected device .ext_io_conf = NULL, diff --git a/components/usb/usb_phy.c b/components/usb/usb_phy.c index 1cf9a25b8173..a20a6d6dcb9d 100644 --- a/components/usb/usb_phy.c +++ b/components/usb/usb_phy.c @@ -6,6 +6,7 @@ #include #include +#include "sdkconfig.h" #include "esp_log.h" #include "esp_check.h" #include "esp_private/periph_ctrl.h" @@ -13,6 +14,7 @@ #include "esp_private/critical_section.h" #include "soc/usb_dwc_periph.h" #include "hal/usb_wrap_hal.h" +#include "hal/usb_utmi_hal.h" #include "esp_rom_gpio.h" #include "driver/gpio.h" #include "soc/soc_caps.h" @@ -40,12 +42,19 @@ struct phy_context_t { }; typedef struct { - phy_context_t *internal_phy; /**< internal PHY context */ + phy_context_t *fsls_phy; /**< internal FSLS PHY context */ + phy_context_t *utmi_phy; /**< internal UTMI PHY context */ phy_context_t *external_phy; /**< external PHY context */ uint32_t ref_count; /**< reference count used to protect p_phy_ctrl_obj */ } phy_ctrl_obj_t; static phy_ctrl_obj_t *p_phy_ctrl_obj = NULL; +// Mapping of OTG1.1 peripheral in usb_dwc_info struct +#if CONFIG_IDF_TARGET_ESP32P4 +static const int otg11_index = 1; +#else +static const int otg11_index = 0; +#endif DEFINE_CRIT_SECTION_LOCK_STATIC(phy_spinlock); #define PHY_ENTER_CRITICAL() esp_os_enter_critical(&phy_spinlock) @@ -126,13 +135,21 @@ esp_err_t usb_phy_otg_set_mode(usb_phy_handle_t handle, usb_otg_mode_t mode) ESP_RETURN_ON_FALSE(handle->controller == USB_PHY_CTRL_OTG, ESP_FAIL, USBPHY_TAG, "phy source is not USB_OTG"); handle->otg_mode = mode; - const usb_otg_signal_conn_t *otg_sig = usb_dwc_info.controllers[0].otg_signals; + // On targets with multiple internal PHYs (FSLS and UTMI) + // we support only fixed PHY to USB-DWC mapping: + // USB-DWC2.0 <-> UTMI PHY + // USB-DWC1.1 <-> FSLS PHY + if (handle->target == USB_PHY_TARGET_UTMI) { + return ESP_OK; // No need to configure anything for UTMI PHY + } + + const usb_otg_signal_conn_t *otg_sig = usb_dwc_info.controllers[otg11_index].otg_signals; assert(otg_sig); if (mode == USB_OTG_MODE_HOST) { esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, otg_sig->iddig, false); // connected connector is A side esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, otg_sig->bvalid, false); esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, otg_sig->vbusvalid, false); // receiving a valid Vbus from host - esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, otg_sig->avalid, false); + esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, otg_sig->avalid, false); // HIGH to force USB host mode if (handle->target == USB_PHY_TARGET_INT) { // Configure pull resistors for host usb_wrap_pull_override_vals_t vals = { @@ -158,10 +175,15 @@ esp_err_t usb_phy_otg_dev_set_speed(usb_phy_handle_t handle, usb_phy_speed_t spe ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_ARG, USBPHY_TAG, "handle argument is invalid"); ESP_RETURN_ON_FALSE(speed < USB_PHY_SPEED_MAX, ESP_ERR_INVALID_ARG, USBPHY_TAG, "speed argument is invalid"); ESP_RETURN_ON_FALSE(handle->controller == USB_PHY_CTRL_OTG, ESP_FAIL, USBPHY_TAG, "phy source is not USB_OTG"); - ESP_RETURN_ON_FALSE((handle->target == USB_PHY_TARGET_INT && handle->otg_mode == USB_OTG_MODE_DEVICE), ESP_FAIL, + ESP_RETURN_ON_FALSE((handle->target != USB_PHY_TARGET_EXT && handle->otg_mode == USB_OTG_MODE_DEVICE), ESP_FAIL, USBPHY_TAG, "set speed not supported"); + ESP_RETURN_ON_FALSE((handle->target == USB_PHY_TARGET_UTMI) == (speed == USB_PHY_SPEED_HIGH), ESP_ERR_NOT_SUPPORTED, USBPHY_TAG, "UTMI can be HighSpeed only"); // This is our software limitation handle->otg_speed = speed; + if (handle->target == USB_PHY_TARGET_UTMI) { + return ESP_OK; // No need to configure anything for UTMI PHY + } + // Configure pull resistors for device usb_wrap_pull_override_vals_t vals = { .dp_pd = false, @@ -181,13 +203,14 @@ esp_err_t usb_phy_otg_dev_set_speed(usb_phy_handle_t handle, usb_phy_speed_t spe esp_err_t usb_phy_action(usb_phy_handle_t handle, usb_phy_action_t action) { ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_ARG, USBPHY_TAG, "handle argument is invalid"); + ESP_RETURN_ON_FALSE(handle->target != USB_PHY_TARGET_UTMI, ESP_ERR_NOT_SUPPORTED, USBPHY_TAG, "Operation not supported on UTMI PHY"); ESP_RETURN_ON_FALSE(action < USB_PHY_ACTION_MAX, ESP_ERR_INVALID_ARG, USBPHY_TAG, "action argument is invalid"); ESP_RETURN_ON_FALSE((action == USB_PHY_ACTION_HOST_ALLOW_CONN && handle->controller == USB_PHY_CTRL_OTG) || (action == USB_PHY_ACTION_HOST_FORCE_DISCONN && handle->controller == USB_PHY_CTRL_OTG), ESP_ERR_INVALID_ARG, USBPHY_TAG, "wrong target for the action"); esp_err_t ret = ESP_OK; - const usb_fsls_serial_signal_conn_t *fsls_sig = usb_dwc_info.controllers[0].fsls_signals; + const usb_fsls_serial_signal_conn_t *fsls_sig = usb_dwc_info.controllers[otg11_index].fsls_signals; assert(fsls_sig); switch (action) { @@ -274,15 +297,31 @@ static esp_err_t usb_phy_install(void) esp_err_t usb_new_phy(const usb_phy_config_t *config, usb_phy_handle_t *handle_ret) { + usb_phy_target_t phy_target = config->target; + + // Backward compatibility code: + // Initial P4 device support was for USB-DWC HS and UTMI PHY. + // To maintain backward compatibility on ESP32-P4 in USB Device mode, we select UTMI PHY + // In case otg_speed is UNDEFINED or HIGH +#if CONFIG_IDF_TARGET_ESP32P4 + if (config->otg_mode == USB_OTG_MODE_DEVICE && + (config->otg_speed == USB_PHY_SPEED_UNDEFINED || config->otg_speed == USB_PHY_SPEED_HIGH)) { + if (phy_target != USB_PHY_TARGET_UTMI) { + ESP_LOGW(USBPHY_TAG, "Using UTMI PHY instead of requested %s PHY", (phy_target == USB_PHY_TARGET_INT) ? "internal" : "external"); + phy_target = USB_PHY_TARGET_UTMI; + } + } +#endif + ESP_RETURN_ON_FALSE(config, ESP_ERR_INVALID_ARG, USBPHY_TAG, "config argument is invalid"); - ESP_RETURN_ON_FALSE(config->target < USB_PHY_TARGET_MAX, ESP_ERR_INVALID_ARG, USBPHY_TAG, "specified PHY argument is invalid"); + ESP_RETURN_ON_FALSE(phy_target < USB_PHY_TARGET_MAX, ESP_ERR_INVALID_ARG, USBPHY_TAG, "specified PHY argument is invalid"); ESP_RETURN_ON_FALSE(config->controller < USB_PHY_CTRL_MAX, ESP_ERR_INVALID_ARG, USBPHY_TAG, "specified source argument is invalid"); - ESP_RETURN_ON_FALSE(config->target != USB_PHY_TARGET_EXT || config->ext_io_conf, ESP_ERR_INVALID_ARG, USBPHY_TAG, "ext_io_conf must be provided for ext PHY"); + ESP_RETURN_ON_FALSE(phy_target != USB_PHY_TARGET_EXT || config->ext_io_conf, ESP_ERR_INVALID_ARG, USBPHY_TAG, "ext_io_conf must be provided for ext PHY"); #if !USB_WRAP_LL_EXT_PHY_SUPPORTED - ESP_RETURN_ON_FALSE(config->target != USB_PHY_TARGET_EXT, ESP_ERR_NOT_SUPPORTED, USBPHY_TAG, "Ext PHY not supported on this target"); + ESP_RETURN_ON_FALSE(phy_target != USB_PHY_TARGET_EXT, ESP_ERR_NOT_SUPPORTED, USBPHY_TAG, "Ext PHY not supported on this target"); #endif #if !SOC_USB_UTMI_PHY_NUM - ESP_RETURN_ON_FALSE(config->target != USB_PHY_TARGET_UTMI, ESP_ERR_NOT_SUPPORTED, USBPHY_TAG, "UTMI PHY not supported on this target"); + ESP_RETURN_ON_FALSE(phy_target != USB_PHY_TARGET_UTMI, ESP_ERR_NOT_SUPPORTED, USBPHY_TAG, "UTMI PHY not supported on this target"); #endif ESP_RETURN_ON_ERROR(usb_phy_install(), USBPHY_TAG, "usb_phy driver installation failed"); @@ -292,43 +331,57 @@ esp_err_t usb_new_phy(const usb_phy_config_t *config, usb_phy_handle_t *handle_r ESP_GOTO_ON_FALSE(phy_context, ESP_ERR_NO_MEM, cleanup, USBPHY_TAG, "no mem for phy context"); PHY_ENTER_CRITICAL(); - usb_phy_get_phy_status(config->target, &phy_context->status); + usb_phy_get_phy_status(phy_target, &phy_context->status); if (phy_context->status == USB_PHY_STATUS_FREE) { new_phy = true; p_phy_ctrl_obj->ref_count++; - if (config->target == USB_PHY_TARGET_EXT) { + if (phy_target == USB_PHY_TARGET_EXT) { p_phy_ctrl_obj->external_phy = phy_context; - } else { - p_phy_ctrl_obj->internal_phy = phy_context; + } else if (phy_target == USB_PHY_TARGET_INT) { + p_phy_ctrl_obj->fsls_phy = phy_context; + } else { // USB_PHY_TARGET_UTMI + p_phy_ctrl_obj->utmi_phy = phy_context; } } PHY_EXIT_CRITICAL(); ESP_GOTO_ON_FALSE(new_phy, ESP_ERR_INVALID_STATE, cleanup, USBPHY_TAG, "selected PHY is in use"); - phy_context->target = config->target; + phy_context->target = phy_target; phy_context->controller = config->controller; phy_context->status = USB_PHY_STATUS_IN_USE; - USB_PHY_RCC_ATOMIC() { - usb_wrap_hal_init(&phy_context->wrap_hal); + if (phy_target != USB_PHY_TARGET_UTMI) { + USB_PHY_RCC_ATOMIC() { + usb_wrap_hal_init(&phy_context->wrap_hal); + } + } else { +#if (SOC_USB_UTMI_PHY_NUM > 0) + usb_utmi_hal_context_t utmi_hal_context; // Unused for now + USB_PHY_RCC_ATOMIC() { + usb_utmi_hal_init(&utmi_hal_context); + } +#endif } if (config->controller == USB_PHY_CTRL_OTG) { #if USB_WRAP_LL_EXT_PHY_SUPPORTED - usb_wrap_hal_phy_set_external(&phy_context->wrap_hal, (config->target == USB_PHY_TARGET_EXT)); + usb_wrap_hal_phy_set_external(&phy_context->wrap_hal, (phy_target == USB_PHY_TARGET_EXT)); #endif } - if (config->target == USB_PHY_TARGET_INT) { + // For FSLS PHY that shares pads with GPIO peripheral, we must set drive capability to 3 (40mA) +#if !CONFIG_IDF_TARGET_ESP32P4 // TODO: We must set drive capability for FSLS PHY for P4 too, to pass Full Speed eye diagram test + if (phy_target == USB_PHY_TARGET_INT) { gpio_set_drive_capability(USBPHY_DM_NUM, GPIO_DRIVE_CAP_3); gpio_set_drive_capability(USBPHY_DP_NUM, GPIO_DRIVE_CAP_3); } +#endif *handle_ret = (usb_phy_handle_t) phy_context; - if (config->ext_io_conf && config->target == USB_PHY_TARGET_EXT) { + if (phy_target == USB_PHY_TARGET_EXT) { phy_context->iopins = (usb_phy_ext_io_conf_t *) calloc(1, sizeof(usb_phy_ext_io_conf_t)); ESP_GOTO_ON_FALSE(phy_context->iopins, ESP_ERR_NO_MEM, cleanup, USBPHY_TAG, "no mem for storing I/O pins"); memcpy(phy_context->iopins, config->ext_io_conf, sizeof(usb_phy_ext_io_conf_t)); - const usb_fsls_serial_signal_conn_t *fsls_sig = usb_dwc_info.controllers[0].fsls_signals; + const usb_fsls_serial_signal_conn_t *fsls_sig = usb_dwc_info.controllers[otg11_index].fsls_signals; ESP_ERROR_CHECK(phy_external_iopins_configure(phy_context->iopins, fsls_sig)); } if (config->otg_mode != USB_PHY_MODE_DEFAULT) { @@ -338,7 +391,7 @@ esp_err_t usb_new_phy(const usb_phy_config_t *config, usb_phy_handle_t *handle_r ESP_ERROR_CHECK(usb_phy_otg_dev_set_speed(*handle_ret, config->otg_speed)); } if (config->otg_io_conf && (phy_context->controller == USB_PHY_CTRL_OTG)) { - const usb_otg_signal_conn_t *otg_sig = usb_dwc_info.controllers[0].otg_signals; + const usb_otg_signal_conn_t *otg_sig = usb_dwc_info.controllers[otg11_index].otg_signals; ESP_ERROR_CHECK(phy_otg_iopins_configure(config->otg_io_conf, otg_sig)); } return ESP_OK; @@ -365,6 +418,9 @@ static void phy_uninstall(void) USB_PHY_RCC_ATOMIC() { // Disable USB peripheral without reset the module usb_wrap_hal_disable(); +#if (SOC_USB_UTMI_PHY_NUM > 0) + usb_utmi_hal_disable(); +#endif } } PHY_EXIT_CRITICAL(); @@ -379,10 +435,12 @@ esp_err_t usb_del_phy(usb_phy_handle_t handle) p_phy_ctrl_obj->ref_count--; if (handle->target == USB_PHY_TARGET_EXT) { p_phy_ctrl_obj->external_phy = NULL; - } else { + } else if (handle->target == USB_PHY_TARGET_INT) { // Clear pullup and pulldown loads on D+ / D-, and disable the pads usb_wrap_hal_phy_disable_pull_override(&handle->wrap_hal); - p_phy_ctrl_obj->internal_phy = NULL; + p_phy_ctrl_obj->fsls_phy = NULL; + } else { // USB_PHY_TARGET_UTMI + p_phy_ctrl_obj->utmi_phy = NULL; } PHY_EXIT_CRITICAL(); free(handle->iopins); @@ -398,8 +456,10 @@ esp_err_t usb_phy_get_phy_status(usb_phy_target_t target, usb_phy_status_t *stat if (target == USB_PHY_TARGET_EXT && p_phy_ctrl_obj->external_phy) { *status = p_phy_ctrl_obj->external_phy->status; - } else if (target == USB_PHY_TARGET_INT && p_phy_ctrl_obj->internal_phy) { - *status = p_phy_ctrl_obj->internal_phy->status; + } else if (target == USB_PHY_TARGET_INT && p_phy_ctrl_obj->fsls_phy) { + *status = p_phy_ctrl_obj->fsls_phy->status; + } else if (target == USB_PHY_TARGET_UTMI && p_phy_ctrl_obj->utmi_phy) { + *status = p_phy_ctrl_obj->utmi_phy->status; } else { *status = USB_PHY_STATUS_FREE; } diff --git a/components/usb/usb_phy_p4.c b/components/usb/usb_phy_p4.c deleted file mode 100644 index 43611c393c4b..000000000000 --- a/components/usb/usb_phy_p4.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -// TODO: Remove this file when proper support of P4 PHYs is implemented IDF-11144 -#include "hal/usb_utmi_hal.h" -#include "esp_private/usb_phy.h" - -#include "soc/soc_caps.h" -#if SOC_RCC_IS_INDEPENDENT -#define USB_UTMI_BUS_CLK_ATOMIC() -#else -#include "esp_private/periph_ctrl.h" -#define USB_UTMI_BUS_CLK_ATOMIC() PERIPH_RCC_ATOMIC() -#endif - -static usb_utmi_hal_context_t s_utmi_hal_context; - -esp_err_t usb_new_phy(const usb_phy_config_t *config, usb_phy_handle_t *handle_ret) -{ - USB_UTMI_BUS_CLK_ATOMIC() { - usb_utmi_hal_init(&s_utmi_hal_context); - } - return ESP_OK; -} - -esp_err_t usb_del_phy(usb_phy_handle_t handle) -{ - // Note: handle argument is not checked, because we don't have phy_handle for P4 yet - USB_UTMI_BUS_CLK_ATOMIC() { - usb_utmi_hal_disable(); - } - return ESP_OK; -} - -esp_err_t usb_phy_get_phy_status(usb_phy_target_t target, usb_phy_status_t *status) -{ - return ESP_OK; -} - -esp_err_t usb_phy_action(usb_phy_handle_t handle, usb_phy_action_t action) -{ - return ESP_OK; -} diff --git a/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c b/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c index f804f40dfa23..52cec2e4d23d 100644 --- a/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c +++ b/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c @@ -1168,6 +1168,10 @@ struct wpabuf * crypto_ecdh_set_peerkey(struct crypto_ecdh *ecdh, int inc_y, int secret_key = 0; mbedtls_ecdh_context *ctx = (mbedtls_ecdh_context *)ecdh; + if (!ctx) { + wpa_printf(MSG_ERROR, "ECDH Context is NULL"); + return 0; + } mbedtls_ctr_drbg_context ctr_drbg; mbedtls_entropy_context entropy; @@ -1221,7 +1225,7 @@ struct wpabuf * crypto_ecdh_set_peerkey(struct crypto_ecdh *ecdh, int inc_y, /* Setup ECDH context from EC key */ /* Call to mbedtls_ecdh_get_params() will initialize the context when not LEGACY context */ - if (ctx != NULL && peer != NULL) { + if (peer != NULL) { mbedtls_ecp_copy(ACCESS_ECDH(&ctx, Qp), &(mbedtls_pk_ec(*peer))->MBEDTLS_PRIVATE(Q)); #ifndef CONFIG_MBEDTLS_ECDH_LEGACY_CONTEXT ctx->MBEDTLS_PRIVATE(var) = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0; diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_common.c b/components/wpa_supplicant/esp_supplicant/src/esp_common.c index 41a0d4d49dcf..30ca52251341 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_common.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_common.c @@ -733,16 +733,16 @@ int wpa_drv_send_action(struct wpa_supplicant *wpa_s, const u8 *data, size_t data_len, int no_cck) { - int ret = 0; - wifi_mgmt_frm_req_t *req = os_zalloc(sizeof(*req) + data_len);; - if (!req) { - return -1; - } + int ret = -1; + wifi_mgmt_frm_req_t *req; if (!wpa_s->current_bss) { - wpa_printf(MSG_ERROR, "STA not associated, return"); - ret = -1; - goto cleanup; + return ret; + } + + req = os_zalloc(sizeof(*req) + data_len); + if (!req) { + return ret; } req->ifx = WIFI_IF_STA; @@ -750,14 +750,14 @@ int wpa_drv_send_action(struct wpa_supplicant *wpa_s, req->data_len = data_len; os_memcpy(req->data, data, req->data_len); - if (esp_wifi_send_mgmt_frm_internal(req) != 0) { + ret = esp_wifi_send_mgmt_frm_internal(req); + + if (ret != 0) { wpa_printf(MSG_ERROR, "action frame sending failed"); - ret = -1; - goto cleanup; + } else { + wpa_printf(MSG_INFO, "action frame sent"); } - wpa_printf(MSG_INFO, "action frame sent"); -cleanup: os_free(req); return ret; } diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c index 0f6239cfa0cc..f2cdaa1198c3 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c @@ -168,7 +168,10 @@ void *hostap_init(void) wpa_printf(MSG_DEBUG, "overriding transition_disable config with 0 as authmode is not WPA3"); } +#ifdef CONFIG_SAE auth_conf->sae_require_mfp = 1; +#endif /* CONFIG_SAE */ + //TODO change it when AP support GCMP-PSK auth_conf->group_mgmt_cipher = WPA_CIPHER_AES_128_CMAC; @@ -316,8 +319,7 @@ u16 esp_send_assoc_resp(struct hostapd_data *hapd, const u8 *addr, reply = os_zalloc(sizeof(wifi_mgmt_frm_req_t) + sizeof(uint16_t)); if (!reply) { wpa_printf(MSG_ERROR, "failed to allocate memory for assoc response"); - res = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto done; + return WLAN_STATUS_UNSPECIFIED_FAILURE; } reply->ifx = WIFI_IF_AP; reply->subtype = subtype; @@ -330,7 +332,6 @@ u16 esp_send_assoc_resp(struct hostapd_data *hapd, const u8 *addr, wpa_printf(MSG_INFO, "esp_send_assoc_resp_failed: send failed"); } #undef ASSOC_RESP_LENGTH -done: os_free(reply); return res; } diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c b/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c index f93722edb1c0..776469d2e4ec 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -694,32 +694,39 @@ int esp_send_sae_auth_reply(struct hostapd_data *hapd, u16 auth_alg, u16 auth_transaction, u16 resp, const u8 *ies, size_t ies_len) { - int reply_res = ESP_FAIL; - ies_len += 3 * sizeof(uint16_t); + int status = ESP_FAIL; + /* Calculate total frame data length (auth_alg + transaction + resp + IEs) */ + size_t data_len = ies_len + 3 * sizeof(uint16_t); - wifi_mgmt_frm_req_t *req = os_zalloc(sizeof(*req) + ies_len); + wifi_mgmt_frm_req_t *req = os_zalloc(sizeof(*req) + data_len); if (!req) { - wpa_printf(MSG_ERROR, "failed to send sae auth reply"); - return reply_res; + wpa_printf(MSG_ERROR, "Failed to allocate SAE authentication reply"); + return status; + } + + /* Populate the frame data */ + ((uint16_t *)req->data)[0] = htole16(auth_alg); /* Authentication algorithm */ + ((uint16_t *)req->data)[1] = htole16(auth_transaction); /* Transaction number */ + ((uint16_t *)req->data)[2] = htole16(resp); /* Response code */ + + if (ies && ies_len) { + os_memcpy(&((uint16_t *)req->data)[3], ies, ies_len); } - ((uint16_t *)req->data)[0] = htole16(auth_alg); - ((uint16_t *)req->data)[1] = htole16(auth_transaction); - ((uint16_t *)req->data)[2] = htole16(resp); - os_memcpy(&((uint16_t *)req->data)[3], ies, ies_len - 3 * sizeof(uint16_t)); req->ifx = WIFI_IF_AP; req->subtype = (WLAN_FC_STYPE_AUTH << 4); - req->data_len = ies_len; + req->data_len = data_len; os_memcpy(req->da, bssid, ETH_ALEN); if (esp_wifi_send_mgmt_frm_internal(req) != 0) { - wpa_printf(MSG_INFO, "%s: send failed", __func__); + wpa_printf(MSG_INFO, "%s: SAE authentication reply send failed", __func__); } else { - reply_res = ESP_OK; + status = ESP_OK; } os_free(req); - return reply_res; + + return status; } void esp_wifi_register_wpa3_ap_cb(struct wpa_funcs *wpa_cb) diff --git a/components/wpa_supplicant/src/ap/ieee802_11.c b/components/wpa_supplicant/src/ap/ieee802_11.c index aa4e602cfd7c..653926d70ba2 100644 --- a/components/wpa_supplicant/src/ap/ieee802_11.c +++ b/components/wpa_supplicant/src/ap/ieee802_11.c @@ -179,6 +179,7 @@ static int auth_sae_send_confirm(struct hostapd_data *hapd, #ifdef ESP_SUPPLICANT if (sta->remove_pending) { reply_res = -1; + wpabuf_free(data); } else { if (sta->sae_data) wpabuf_free(sta->sae_data); diff --git a/components/wpa_supplicant/src/rsn_supp/wpa.c b/components/wpa_supplicant/src/rsn_supp/wpa.c index aef17fc9c0db..d05b4afa824e 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa.c +++ b/components/wpa_supplicant/src/rsn_supp/wpa.c @@ -189,21 +189,9 @@ static bool is_wpa2_enterprise_connection(void) } #endif -/** - * get_bssid - Get the current BSSID - * @priv: private driver interface data - * @bssid: buffer for BSSID (ETH_ALEN = 6 bytes) - * - * Returns: 0 on success, -1 on failure - * - * Query kernel driver for the current BSSID and copy it to bssid. - * Setting bssid to 00:00:00:00:00:00 is recommended if the STA is not - * associated. - */ -static inline int wpa_sm_get_bssid(struct wpa_sm *sm, u8 *bssid) +const u8 * wpa_sm_get_auth_addr(struct wpa_sm *sm) { - memcpy(bssid, sm->bssid, ETH_ALEN); - return 0; + return sm->bssid; } /* @@ -233,11 +221,13 @@ static inline int wpa_sm_ether_send(struct wpa_sm *sm, const u8 *dest, u16 proto * @msg_len: Length of message * @key_mic: Pointer to the buffer to which the EAPOL-Key MIC is written */ -void wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck, size_t kck_len, +int wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck, size_t kck_len, int ver, const u8 *dest, u16 proto, u8 *msg, size_t msg_len, u8 *key_mic) { + int ret = -1; if (is_zero_ether_addr(dest) && is_zero_ether_addr(sm->bssid)) { +#ifndef ESP_SUPPLICANT /* * Association event was not yet received; try to fetch * BSSID from the driver. @@ -251,6 +241,9 @@ void wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck, size_t kck_len, ") as the destination for EAPOL-Key", MAC2STR(dest)); } +#else + return ret; +#endif } if (key_mic && wpa_eapol_key_mic(kck, kck_len, sm->key_mgmt, ver, msg, msg_len, @@ -263,9 +256,9 @@ void wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck, size_t kck_len, wpa_hexdump_key(MSG_DEBUG, "WPA: KCK", kck, kck_len); wpa_hexdump(MSG_DEBUG, "WPA: Derived Key MIC", key_mic, wpa_mic_len(sm->key_mgmt, sm->pmk_len)); wpa_hexdump(MSG_MSGDUMP, "WPA: TX EAPOL-Key", msg, msg_len); - wpa_sm_ether_send(sm, dest, proto, msg, msg_len); + return wpa_sm_ether_send(sm, dest, proto, msg, msg_len); out: - return; + return ret; } /** @@ -284,7 +277,7 @@ static void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise) struct wpa_eapol_key *reply; struct wpa_eapol_key_192 *reply192; int key_info, ver; - u8 bssid[ETH_ALEN], *rbuf, *key_mic; + u8 *rbuf, *key_mic; if (wpa_use_akm_defined(sm->key_mgmt)) ver = WPA_KEY_INFO_TYPE_AKM_DEFINED; @@ -295,12 +288,6 @@ static void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise) else ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; - if (wpa_sm_get_bssid(sm, bssid) < 0) { - wpa_printf(MSG_DEBUG, "Failed to read BSSID for EAPOL-Key " - "request"); - return; - } - mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len); hdrlen = mic_len == 24 ? sizeof(*reply192) : sizeof(*reply); rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, @@ -342,7 +329,7 @@ static void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise) wpa_printf(MSG_DEBUG, "WPA: Sending EAPOL-Key Request (error=%d " "pairwise=%d ptk_set=%d len=%lu)", error, pairwise, sm->ptk_set, (unsigned long) rlen); - wpa_eapol_key_send(sm, sm->ptk.kck, sm->ptk.kck_len, ver, bssid, + wpa_eapol_key_send(sm, sm->ptk.kck, sm->ptk.kck_len, ver, wpa_sm_get_auth_addr(sm), ETH_P_EAPOL, rbuf, rlen, key_mic); wpa_sm_free_eapol(rbuf); } @@ -2731,8 +2718,6 @@ struct wpa_sm * get_wpa_sm(void) int wpa_sm_set_ap_rsnxe(const u8 *ie, size_t len) { struct wpa_sm *sm = &gWpaSm; - if (!sm) - return -1; os_free(sm->ap_rsnxe); if (!ie || len == 0) { diff --git a/docs/docs_not_updated/esp32c5.txt b/docs/docs_not_updated/esp32c5.txt index ad52183126b8..65bf76fc83ef 100644 --- a/docs/docs_not_updated/esp32c5.txt +++ b/docs/docs_not_updated/esp32c5.txt @@ -24,9 +24,7 @@ api-reference/storage/fatfsgen.rst api-reference/storage/index.rst api-reference/storage/nvs_partition_parse.rst api-reference/peripherals/twai.rst -api-reference/peripherals/gptimer.rst api-reference/peripherals/touch_element.rst -api-reference/peripherals/lcd.rst api-reference/peripherals/spi_features.rst api-reference/peripherals/touch_pad.rst api-reference/peripherals/sd_pullup_requirements.rst diff --git a/docs/doxygen/Doxyfile b/docs/doxygen/Doxyfile index 3bc068d0cf53..eae55fe2e58f 100644 --- a/docs/doxygen/Doxyfile +++ b/docs/doxygen/Doxyfile @@ -284,6 +284,7 @@ INPUT = \ $(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/doxygen/Doxyfile_esp32c5 b/docs/doxygen/Doxyfile_esp32c5 index 853631e4efb9..1d3f3c758456 100644 --- a/docs/doxygen/Doxyfile_esp32c5 +++ b/docs/doxygen/Doxyfile_esp32c5 @@ -1,4 +1,7 @@ INPUT += \ + $(PROJECT_PATH)/components/esp_driver_bitscrambler/include/driver/bitscrambler.h \ + $(PROJECT_PATH)/components/esp_driver_bitscrambler/include/driver/bitscrambler_loopback.h \ + $(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/bitscrambler_peri_select.h \ $(PROJECT_PATH)/components/ulp/lp_core/include/lp_core_i2c.h \ $(PROJECT_PATH)/components/ulp/lp_core/include/lp_core_uart.h \ $(PROJECT_PATH)/components/ulp/lp_core/include/lp_core_etm.h \ diff --git a/docs/en/api-guides/build-system.rst b/docs/en/api-guides/build-system.rst index a2469d325d97..7a78291adddb 100644 --- a/docs/en/api-guides/build-system.rst +++ b/docs/en/api-guides/build-system.rst @@ -25,19 +25,19 @@ ESP-IDF makes these components explicit and configurable. To do that, when a pro Concepts -------- -- A "project" is a directory that contains all the files and configuration to build a single "app" (executable), as well as additional supporting elements such as a partition table, data/filesystem partitions, and a bootloader. +- A ``project`` is a directory that contains all the files and configuration to build a single ``app`` (executable), as well as additional supporting elements such as a partition table, data partitions or filesystem partitions, and a bootloader. -- "Project configuration" is held in a single file called ``sdkconfig`` in the root directory of the project. This configuration file is modified via ``idf.py menuconfig`` to customize the configuration of the project. A single project contains exactly one project configuration. +- ``Project configuration`` is held in a single file called ``sdkconfig`` in the root directory of the project. This configuration file is modified via ``idf.py menuconfig`` to customize the configuration of the project. A single project contains exactly one project configuration. -- An "app" is an executable that is built by ESP-IDF. A single project will usually build two apps - a "project app" (the main executable, ie your custom firmware) and a "bootloader app" (the initial bootloader program which launches the project app). +- An ``app`` is an executable that is built by ESP-IDF. A single project will usually build two apps - a "project app" (the main executable, ie your custom firmware) and a "bootloader app" (the initial bootloader program which launches the project app). -- "components" are modular pieces of standalone code that are compiled into static libraries (.a files) and linked to an app. Some are provided by ESP-IDF itself, others may be sourced from other places. +- ``Components`` are modular pieces of standalone code that are compiled into static libraries (.a files) and linked to an app. Some are provided by ESP-IDF itself, others may be sourced from other places. -- "Target" is the hardware for which an application is built. A full list of supported targets in your version of ESP-IDF can be seen by running `idf.py --list-targets`. +- ``Target`` is the hardware for which an application is built. A full list of supported targets in your version of ESP-IDF can be seen by running `idf.py --list-targets`. Some things are not part of the project: -- "ESP-IDF" is not part of the project. Instead, it is standalone, and linked to the project via the ``IDF_PATH`` environment variable which holds the path of the ``esp-idf`` directory. This allows the ESP-IDF framework to be decoupled from your project. +- ``ESP-IDF`` is not part of the project. Instead, it is standalone, and linked to the project via the ``IDF_PATH`` environment variable which holds the path of the ``esp-idf`` directory. This allows the ESP-IDF framework to be decoupled from your project. - The toolchain for compilation is not part of the project. The toolchain should be installed in the system command line PATH. @@ -47,8 +47,8 @@ Using the Build System .. _idf.py: -``idf.py`` ----------- +idf.py +------ The ``idf.py`` command-line tool provides a front-end for easily managing your project builds. It manages the following tools: @@ -56,13 +56,13 @@ The ``idf.py`` command-line tool provides a front-end for easily managing your p - Ninja_ which builds the project - `esptool.py`_ for flashing the target. -You can read more about configuring the build system using ``idf.py`` :doc:`here `. +For more details about configuring the build system using ``idf.py``, please refer to :doc:`IDF Frontend `. Using CMake Directly -------------------- -:ref:`idf.py` is a wrapper around CMake_ for convenience. However, you can also invoke CMake directly if you prefer. +:ref:`idf.py` is a wrapper around CMake_ for convenience. However, you can also invoke CMake directly. .. highlight:: bash @@ -125,7 +125,6 @@ When adding custom non-build steps like "flash" to the IDE, it is recommended to For more detailed information about integrating ESP-IDF with CMake into an IDE, see `Build System Metadata`_. - .. _setting-python-interpreter: Setting up the Python Interpreter @@ -615,15 +614,14 @@ Including Components in the Build - Components mentioned explicitly in ``COMPONENTS``. - Those components' requirements (evaluated recursively). - - The "common" components that every component depends on. + - The :ref:`common components ` that every component depends on. - Setting ``COMPONENTS`` to the minimal list of required components can significantly reduce compile times. -- The ``MINIMAL_BUILD`` :ref:`build property ` can be set to ``ON``, which acts as a shortcut to configure the ``COMPONENTS`` variable to include only the ``main`` component. If the ``COMPONENTS`` variable is defined while the ``MINIMAL_BUILD`` property is enabled, ``COMPONENTS`` will take precedence. +- The ``MINIMAL_BUILD`` :ref:`build property ` can be set to ``ON``, which acts as a shortcut to configure the ``COMPONENTS`` variable to include only the ``main`` component. This means that the build will include only the :ref:`common components `, the ``main`` component, and all dependencies associated with it, both direct and indirect. If the ``COMPONENTS`` variable is defined while the ``MINIMAL_BUILD`` property is enabled, ``COMPONENTS`` will take precedence. .. note:: - When using the ``COMPONENTS`` variable or the ``MINIMAL_BUILD`` build property to specify components, certain features and configurations, such as those provided by esp_psram or espcoredump components, may not be included by default. To include these features, you must add the relevant components to the ``COMPONENTS`` variable or list them in the ``REQUIRES`` or ``PRIV_REQUIRES`` argument during component registration. - + Certain features and configurations, such as those provided by esp_psram or espcoredump components, may not be available to your project by default if the minimal list of components is used. When using the ``COMPONENTS`` variable, ensure that all necessary components are included. Similarly, when using the ``MINIMAL_BUILD`` build property, ensure that all required components are specified in the ``REQUIRES`` or ``PRIV_REQUIRES`` argument during component registration. .. _component-circular-dependencies: diff --git a/docs/en/api-guides/core_dump.rst b/docs/en/api-guides/core_dump.rst index 3ecd93c04640..d03ac3b209d0 100644 --- a/docs/en/api-guides/core_dump.rst +++ b/docs/en/api-guides/core_dump.rst @@ -17,7 +17,8 @@ Configurations -------------- .. note:: - The ``Core dump`` configuration options are available only if the ``espcoredump`` component is included in the build. + + The ``Core dump`` configuration options are available only if the ``espcoredump`` component is included in the build. To include ``Core dump`` into your project, add the ``espcoredump`` component as a dependency in either ``REQUIRES`` or ``PRIV_REQUIRES`` when registering your component with ``idf_component_register``. Destination ^^^^^^^^^^^ @@ -137,8 +138,6 @@ Automatic Decoding If :ref:`CONFIG_ESP_COREDUMP_DECODE` is set to automatically decode the UART core dump, ESP-IDF monitor will automatically decode the data, translate any function addresses to source code lines, and display it in the monitor. The output to ESP-IDF monitor would resemble the following output: -The :ref:`CONFIG_ESP_COREDUMP_UART_DELAY` allows for an optional delay to be added before the core dump file is output to UART. - .. code-block:: none =============================================================== @@ -187,6 +186,7 @@ The :ref:`CONFIG_ESP_COREDUMP_UART_DELAY` allows for an optional delay to be add ===================== ESP32 CORE DUMP END ===================== =============================================================== +The :ref:`CONFIG_ESP_COREDUMP_UART_DELAY` allows for an optional delay to be added before the core dump file is output to UART. Manual Decoding ^^^^^^^^^^^^^^^ @@ -217,10 +217,12 @@ or Core Dump Commands ------------------ -ESP-IDF provides special commands to help to retrieve and analyze core dumps: +ESP-IDF provides special commands to retrieve and analyze core dumps: + +* ``idf.py coredump-info`` - reads coredump from flash and prints crashed task's registers, call stack, list of available tasks in the system, memory regions, and contents of memory stored in core dump (TCBs and stacks). +* ``idf.py coredump-debug`` - reads coredump from flash, saves it as ELF file and runs a GDB debug session with this file. You can examine memory, variables, and task states manually. Note that since not all memory is saved in the core dump, only the values of variables allocated on the stack are meaningful. -* ``idf.py coredump-info`` - prints crashed task's registers, call stack, list of available tasks in the system, memory regions, and contents of memory stored in core dump (TCBs and stacks). -* ``idf.py coredump-debug`` - creates core dump ELF file and runs GDB debug session with this file. You can examine memory, variables, and task states manually. Note that since not all memory is saved in the core dump, only the values of variables allocated on the stack are meaningful. +``idf.py coredump-info --help`` and ``idf.py coredump-debug --help`` commands can be used to get more details on usage. For example, they can save the coredump into a file and avoid the need to read it from flash every time these commands are run. For advanced users who want to pass additional arguments or use custom ELF files, it is possible to use the `esp-coredump `_ tool directly. For more information, use in ESP-IDF environment: @@ -287,13 +289,6 @@ Example (gdb) p global_var $1 = 25 '\031' - -Running ``idf.py coredump-info`` and ``idf.py coredump-debug`` --------------------------------------------------------------- - -``idf.py coredump-info --help`` and ``idf.py coredump-debug --help`` commands can be used to get more details on usage. - - Related Documents ^^^^^^^^^^^^^^^^^ diff --git a/docs/en/api-guides/external-ram.rst b/docs/en/api-guides/external-ram.rst index 9ecd2ad8da0b..81f1452ddc13 100644 --- a/docs/en/api-guides/external-ram.rst +++ b/docs/en/api-guides/external-ram.rst @@ -47,7 +47,8 @@ Configuring External RAM ======================== .. note:: - The ``SPI RAM`` configuration options are available only if the ``esp_psram`` component is included in the build. + + The ``SPI RAM`` configuration options are available only if the ``esp_psram`` component is included in the build. To include ``SPI RAM`` into your project, add the ``esp_psram`` component as a dependency in either ``REQUIRES`` or ``PRIV_REQUIRES`` when registering your component with ``idf_component_register``. ESP-IDF fully supports the use of external RAM in applications. Once the external RAM is initialized at startup, ESP-IDF can be configured to integrate the external RAM in several ways: diff --git a/docs/en/api-guides/performance/size.rst b/docs/en/api-guides/performance/size.rst index d48b699d2635..4d434cbfd3f0 100644 --- a/docs/en/api-guides/performance/size.rst +++ b/docs/en/api-guides/performance/size.rst @@ -202,23 +202,26 @@ Under **Component Config** > **mbedTLS**, there are multiple mbedTLS features en These include: -- :ref:`CONFIG_MBEDTLS_HAVE_TIME` -- :ref:`CONFIG_MBEDTLS_ECDSA_DETERMINISTIC` -- :ref:`CONFIG_MBEDTLS_SHA512_C` -- :ref:`CONFIG_MBEDTLS_SHA3_C` -- :ref:`CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS` -- :ref:`CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS` -- :ref:`CONFIG_MBEDTLS_SSL_CONTEXT_SERIALIZATION` -- :ref:`CONFIG_MBEDTLS_SSL_ALPN` -- :ref:`CONFIG_MBEDTLS_SSL_RENEGOTIATION` -- :ref:`CONFIG_MBEDTLS_CCM_C` -- :ref:`CONFIG_MBEDTLS_GCM_C` -- :ref:`CONFIG_MBEDTLS_ECP_C` (Alternatively: Leave this option enabled but disable some of the elliptic curves listed in the sub-menu.) -- :ref:`CONFIG_MBEDTLS_ECP_NIST_OPTIM` -- :ref:`CONFIG_MBEDTLS_ECP_FIXED_POINT_OPTIM` -- Change :ref:`CONFIG_MBEDTLS_TLS_MODE` if both server & client functionalities are not needed. -- Consider disabling some cipher suites listed in the ``TLS Key Exchange Methods`` sub-menu (i.e., :ref:`CONFIG_MBEDTLS_KEY_EXCHANGE_RSA`). -- Consider disabling :ref:`CONFIG_MBEDTLS_ERROR_STRINGS` if the application is already pulling in mbedTLS error strings through using :cpp:func:`mbedtls_strerror`. +.. list:: + + - :ref:`CONFIG_MBEDTLS_HAVE_TIME` + - :ref:`CONFIG_MBEDTLS_ECDSA_DETERMINISTIC` + - :ref:`CONFIG_MBEDTLS_SHA512_C` + - :ref:`CONFIG_MBEDTLS_SHA3_C` + - :ref:`CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS` + - :ref:`CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS` + - :ref:`CONFIG_MBEDTLS_SSL_CONTEXT_SERIALIZATION` + - :ref:`CONFIG_MBEDTLS_SSL_ALPN` + - :ref:`CONFIG_MBEDTLS_SSL_RENEGOTIATION` + - :ref:`CONFIG_MBEDTLS_CCM_C` + - :ref:`CONFIG_MBEDTLS_GCM_C` + - :ref:`CONFIG_MBEDTLS_ECP_C` (Alternatively: Leave this option enabled but disable some of the elliptic curves listed in the sub-menu.) + - :ref:`CONFIG_MBEDTLS_ECP_NIST_OPTIM` + - :ref:`CONFIG_MBEDTLS_ECP_FIXED_POINT_OPTIM` + - Change :ref:`CONFIG_MBEDTLS_TLS_MODE` if both server & client functionalities are not needed. + - Consider disabling some cipher suites listed in the ``TLS Key Exchange Methods`` sub-menu (i.e., :ref:`CONFIG_MBEDTLS_KEY_EXCHANGE_RSA`). + - Consider disabling :ref:`CONFIG_MBEDTLS_ERROR_STRINGS` if the application is already pulling in mbedTLS error strings through using :cpp:func:`mbedtls_strerror`. + :esp32h2: - For {IDF_TARGET_NAME} v1.2 and above, consider disabling :ref:`CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_MASKING_CM` and :ref:`CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_CONSTANT_TIME_CM` as the software countermeasures for the ECDSA sign operation are not required. The help text for each option has some more information for reference. diff --git a/docs/en/api-reference/peripherals/bitscrambler.rst b/docs/en/api-reference/peripherals/bitscrambler.rst index ab38a3798194..eb3d0a536e58 100644 --- a/docs/en/api-reference/peripherals/bitscrambler.rst +++ b/docs/en/api-reference/peripherals/bitscrambler.rst @@ -193,6 +193,10 @@ Resource allocation and program loading In loopback mode, a BitScrambler object is created using :cpp:func:`bitscrambler_loopback_create`. If there is a BitScrambler peripheral matching the requested characteristics, this function will return a handle to it. You can then use :cpp:func:`bitscrambler_load_program` to load a program into it, then call :cpp:func:`bitscrambler_loopback_run` to transform a memory buffer using the loaded program. You can call :cpp:func:`bitscrambler_loopback_run` any number of times; it's also permissible to use :cpp:func:`bitscrambler_load_program` to change programs between calls. Finally, to free the hardware resources and clean up memory, call :cpp:func:`bitscrambler_free`. +Application Example +------------------- + +* :example:`peripherals/bitscrambler` demonstrates how to use the BitScrambler loopback mode to transform a buffer of data into a different format. API Reference ------------- diff --git a/docs/en/api-reference/peripherals/i2c.rst b/docs/en/api-reference/peripherals/i2c.rst index 88a9b70aa629..79fdc8d8f804 100644 --- a/docs/en/api-reference/peripherals/i2c.rst +++ b/docs/en/api-reference/peripherals/i2c.rst @@ -215,6 +215,8 @@ Uninstall I2C master bus and device If a previously installed I2C bus or device is no longer needed, it's recommended to recycle the resource by calling :cpp:func:`i2c_master_bus_rm_device` or :cpp:func:`i2c_del_master_bus`, so as to release the underlying hardware. +Please note that removing all devices attached to bus before delete the master bus. + Install I2C slave device ~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/en/api-reference/peripherals/rmt.rst b/docs/en/api-reference/peripherals/rmt.rst index 7915c48454de..c266332a8e67 100644 --- a/docs/en/api-reference/peripherals/rmt.rst +++ b/docs/en/api-reference/peripherals/rmt.rst @@ -144,7 +144,7 @@ Once the :cpp:type:`rmt_rx_channel_config_t` structure is populated with mandato .. note:: - Due to a software limitation in the GPIO driver, when both TX and RX channels are bound to the same GPIO, ensure the RX Channel is initialized before the TX Channel. If the TX Channel was set up first, then during the RX Channel setup, the previous RMT TX Channel signal will be overridden by the GPIO control signal. + When multiple RMT channels are allocated at the same time, the group’s prescale is determined based on the resolution of the first channel. The driver then selects the appropriate prescale from low to high. To avoid prescale conflicts when allocating multiple channels, allocate channels in order of their target resolution, either from highest to lowest or lowest to highest. Uninstall RMT Channel ~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/en/api-reference/protocols/mqtt.rst b/docs/en/api-reference/protocols/mqtt.rst index b408c3bc2d8a..b221a926f6dc 100644 --- a/docs/en/api-reference/protocols/mqtt.rst +++ b/docs/en/api-reference/protocols/mqtt.rst @@ -205,3 +205,4 @@ API Reference ------------- .. include-build-file:: inc/mqtt_client.inc +.. include-build-file:: inc/mqtt5_client.inc diff --git a/docs/en/api-reference/system/intr_alloc.rst b/docs/en/api-reference/system/intr_alloc.rst index 6effc5d7dfb7..67193a639426 100644 --- a/docs/en/api-reference/system/intr_alloc.rst +++ b/docs/en/api-reference/system/intr_alloc.rst @@ -32,7 +32,7 @@ Overview Because there are more interrupt sources than interrupts, sometimes it makes sense to share an interrupt in multiple drivers. The :cpp:func:`esp_intr_alloc` abstraction exists to hide all these implementation details. -A driver can allocate an interrupt for a certain peripheral by calling :cpp:func:`esp_intr_alloc` (or :cpp:func:`esp_intr_alloc_intrstatus`). It can use the flags passed to this function to specify the type, priority, and trigger method of the interrupt to allocate. The interrupt allocation code will then find an applicable interrupt, use the interrupt matrix to hook it up to the peripheral, and install the given interrupt handler and ISR to it. +A driver can allocate an interrupt for a certain peripheral by calling :cpp:func:`esp_intr_alloc`, :cpp:func:`esp_intr_alloc_bind`, :cpp:func:`esp_intr_alloc_intrstatus`, or :cpp:func:`esp_intr_alloc_intrstatus_bind`. It can use the flags passed to this function to specify the type, priority, and trigger method of the interrupt to allocate. The interrupt allocation code will then find an applicable interrupt, use the interrupt matrix to hook it up to the peripheral, and install the given interrupt handler and ISR to it. The interrupt allocator presents two different types of interrupts, namely shared interrupts and non-shared interrupts, both of which require different handling. Non-shared interrupts will allocate a separate interrupt for every :cpp:func:`esp_intr_alloc` call, and this interrupt is use solely for the peripheral attached to it, with only one ISR that will get called. Shared interrupts can have multiple peripherals triggering them, with multiple ISRs being called when one of the peripherals attached signals an interrupt. Thus, ISRs that are intended for shared interrupts should check the interrupt status of the peripheral they service in order to check if any action is required. @@ -138,9 +138,7 @@ Several handlers can be assigned to a same source, given that all handlers are a Sources attached to non-shared interrupt do not support this feature. -.. only:: not SOC_CPU_HAS_FLEXIBLE_INTC - - By default, when ``ESP_INTR_FLAG_SHARED`` flag is specified, the interrupt allocator will allocate only priority level 1 interrupts. Use ``ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_LOWMED`` to also allow allocating shared interrupts at priority levels 2 and 3. +By default, when ``ESP_INTR_FLAG_SHARED`` flag is specified, the interrupt allocator will allocate only priority level 1 interrupts. Use ``ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_LOWMED`` to also allow allocating shared interrupts at priority levels 2 and 3. Though the framework supports this feature, you have to use it **very carefully**. There usually exist two ways to stop an interrupt from being triggered: **disable the source** or **mask peripheral interrupt status**. ESP-IDF only handles enabling and disabling of the source itself, leaving status and mask bits to be handled by users. @@ -150,6 +148,8 @@ Though the framework supports this feature, you have to use it **very carefully* Leaving some status bits unhandled without masking them, while disabling the handlers for them, will cause the interrupt(s) to be triggered indefinitely, resulting therefore in a system crash. +When calling :cpp:func:`esp_intr_alloc` or :cpp:func:`esp_intr_alloc_intrstatus`, the interrupt allocator selects the first interrupt that meets the level requirements for mapping the specified source, without considering other sources already mapped to the shared interrupt line. However, by using the functions :cpp:func:`esp_intr_alloc_bind` or :cpp:func:`esp_intr_alloc_intrstatus_bind`, you can explicitly specify the interrupt handler to be shared with the given interrupt source. + Troubleshooting Interrupt Allocation ------------------------------------ diff --git a/docs/en/api-reference/system/mem_alloc.rst b/docs/en/api-reference/system/mem_alloc.rst index dbe30659a0b8..363d57fbc823 100644 --- a/docs/en/api-reference/system/mem_alloc.rst +++ b/docs/en/api-reference/system/mem_alloc.rst @@ -1,6 +1,8 @@ Heap Memory Allocation ====================== +{IDF_TARGET_SIMD_PREFERRED_DATA_ALIGNMENT: default="16", esp32s3="16", esp32p4="16"} + :link_to_translation:`zh_CN:[中文]` Stack and Heap @@ -134,6 +136,13 @@ Memory allocated with ``MALLOC_CAP_32BIT`` can **only** be accessed via 32-bit r On ESP32 only external SPI RAM under 4 MiB in size can be allocated this way. To use the region above the 4 MiB limit, you can use the :doc:`himem API `. +.. only:: SOC_SIMD_INSTRUCTION_SUPPORTED + + SIMD-Instruction-Capable Memory + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + ``MALLOC_CAP_SIMD`` flag can be used to allocate memory which is accessible by SIMD (Single Instruction Multiple Data) instructions. The use of this flag also aligns the memory to a SIMD preferred data alignment size ({IDF_TARGET_SIMD_PREFERRED_DATA_ALIGNMENT}-byte) for a better performance. + Thread Safety ------------- diff --git a/docs/en/api-reference/system/ota.rst b/docs/en/api-reference/system/ota.rst index 891dc99fea75..2c3944a3b8d7 100644 --- a/docs/en/api-reference/system/ota.rst +++ b/docs/en/api-reference/system/ota.rst @@ -140,7 +140,7 @@ A brief description of where the states are set: * ``ESP_OTA_IMG_VALID`` state is set by :cpp:func:`esp_ota_mark_app_valid_cancel_rollback` function. * ``ESP_OTA_IMG_UNDEFINED`` state is set by :cpp:func:`esp_ota_set_boot_partition` function if :ref:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` option is not enabled. * ``ESP_OTA_IMG_NEW`` state is set by :cpp:func:`esp_ota_set_boot_partition` function if :ref:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` option is enabled. -* ``ESP_OTA_IMG_INVALID`` state is set by :cpp:func:`esp_ota_mark_app_invalid_rollback_and_reboot` function. +* ``ESP_OTA_IMG_INVALID`` state is set by function :cpp:func:`esp_ota_mark_app_invalid_rollback` or :cpp:func:`esp_ota_mark_app_invalid_rollback_and_reboot`. * ``ESP_OTA_IMG_ABORTED`` state is set if there was no confirmation of the application operability and occurs reboots (if :ref:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` option is enabled). * ``ESP_OTA_IMG_PENDING_VERIFY`` state is set in a bootloader if :ref:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` option is enabled and selected app has ``ESP_OTA_IMG_NEW`` state. @@ -165,7 +165,7 @@ A Typical Anti-rollback Scheme Is - To make it bootable, run the function :cpp:func:`esp_ota_set_boot_partition`. If the security version of the new application is smaller than the version in the chip, the new application will be erased. Update to new firmware is not possible. - Reboot. - In the bootloader, an application with a security version greater than or equal to the version in the chip will be selected. If otadata is in the initial state, and one firmware was loaded via a serial channel, whose secure version is higher than the chip, then the secure version of efuse will be immediately updated in the bootloader. -- New application booted. Then the application should perform diagnostics of the operation and if it is completed successfully, you should call :cpp:func:`esp_ota_mark_app_valid_cancel_rollback` function to mark the running application with the ``ESP_OTA_IMG_VALID`` state and update the secure version on chip. Note that if was called :cpp:func:`esp_ota_mark_app_invalid_rollback_and_reboot` function a rollback may not happen as the device may not have any bootable apps. It will then return ``ESP_ERR_OTA_ROLLBACK_FAILED`` error and stay in the ``ESP_OTA_IMG_PENDING_VERIFY`` state. +- New application booted. Then the application should perform diagnostics of the operation and if it is completed successfully, you should call :cpp:func:`esp_ota_mark_app_valid_cancel_rollback` function to mark the running application with the ``ESP_OTA_IMG_VALID`` state and update the secure version on chip. Note that if the :cpp:func:`esp_ota_mark_app_invalid_rollback` or :cpp:func:`esp_ota_mark_app_invalid_rollback_with_reboot` function is called a rollback may not happen as the device may not have any bootable apps. It will then return ``ESP_ERR_OTA_ROLLBACK_FAILED`` error and stay in the ``ESP_OTA_IMG_PENDING_VERIFY`` state. - The next update of app is possible if a running app is in the ``ESP_OTA_IMG_VALID`` state. Recommendation: @@ -215,7 +215,7 @@ Restrictions: .. only:: esp32 - - In ESP32 it is stored in efuse ``EFUSE_BLK3_RDATA4_REG``. (when a eFuse bit is programmed to 1, it can never be reverted to 0). The number of bits set in this register is the ``security_version`` from app. + - In ESP32, it is stored in efuse ``EFUSE_BLK3_RDATA4_REG``. (when an eFuse bit is programmed to 1, it can never be reverted to 0). The number of bits set in this register is the ``security_version`` from app. .. _secure-ota-updates: @@ -223,11 +223,11 @@ Restrictions: Secure OTA Updates Without Secure Boot -------------------------------------- -The verification of signed OTA updates can be performed even without enabling hardware secure boot. This can be achieved by setting :ref:`CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT` and :ref:`CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT` +The verification of signed OTA updates can be performed even without enabling hardware secure boot. This can be achieved by setting :ref:`CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT` and :ref:`CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT`. .. only:: esp32 - For more information refer to :ref:`signed-app-verify` + For more information, please refer to :ref:`signed-app-verify`. Tuning OTA Performance ---------------------- @@ -275,7 +275,7 @@ Before anything else, make sure that the ``otatool`` module is imported. sys.path.append(otatool_dir) # this enables Python to find otatool module from otatool import * # import all names inside otatool module -The starting point for using the tool's Python API to do is create a ``OtatoolTarget`` object: +The starting point for using the tool's Python API to do is create an ``OtatoolTarget`` object: .. code-block:: python diff --git a/docs/en/migration-guides/release-5.x/5.5/system.rst b/docs/en/migration-guides/release-5.x/5.5/system.rst index bd0681b6a046..e12d4dc1e407 100644 --- a/docs/en/migration-guides/release-5.x/5.5/system.rst +++ b/docs/en/migration-guides/release-5.x/5.5/system.rst @@ -13,10 +13,10 @@ Log **Log V2** is introduced in this ESP-IDF version as an enhanced and optional logging implementation. It is fully compatible with **Log V1**, allowing projects to continue using **Log V1** without changes. Developers can enable **Log V2** via the Kconfig option :ref:`CONFIG_LOG_VERSION`. In future ESP-IDF versions, **Log V2** may become the default. -**Key Points:** +**Key Points** - Centralized log handling, dynamic formatting, and greater flexibility. -- Slightly higher stack and IRAM usage, with a reduced binary size (refer to measurements in the log document). +- Slightly higher stack and IRAM usage, with a reduced binary size (refer to measurements in the `Logging Library <../../../system/log.rst>`_ document). - **Log V2**-specific features (e.g., dynamic formatting, detecting the execution context) are not backward-compatible with **Log V1**. If you use the ``esp_log_write`` (or ``esp_log_writev``) function, replace it with ``esp_log`` (or ``esp_log_va``) to reduce one nested call. @@ -38,4 +38,4 @@ The log handler (``esp_log``) supports internal formatting, so there is no need Pre-Encrypted OTA ----------------- -The 'pre_encrypted_ota' example has been moved to `idf-extra-components `__ repository. +The ``pre_encrypted_ota`` example has been moved to the `idf-extra-components `__ repository. diff --git a/docs/zh_CN/api-guides/build-system.rst b/docs/zh_CN/api-guides/build-system.rst index 0e21ecd165d6..97ac467ab1cd 100644 --- a/docs/zh_CN/api-guides/build-system.rst +++ b/docs/zh_CN/api-guides/build-system.rst @@ -25,7 +25,7 @@ ESP-IDF 可以显式地指定和配置每个组件。在构建项目的时候, 概念 ---- -- ``项目`` 特指一个目录,其中包含了构建可执行应用程序所需的全部文件和配置,以及其他支持型文件,例如分区表、数据/文件系统分区和引导加载程序。 +- ``项目`` 特指一个目录,其中包含了构建 ``应用程序`` (即可执行文件)所需的全部文件和配置,还包含了其他支持型文件,例如分区表、数据分区或文件系统分区,以及引导加载程序。 - ``项目配置`` 保存在项目根目录下名为 ``sdkconfig`` 的文件中,可以通过 ``idf.py menuconfig`` 进行修改,且一个项目只能包含一个项目配置。 @@ -48,7 +48,7 @@ ESP-IDF 可以显式地指定和配置每个组件。在构建项目的时候, .. _idf.py: idf.py --------- +------ ``idf.py`` 命令行工具提供了一个前端,可以帮助你轻松管理项目的构建过程,它管理了以下工具: @@ -56,17 +56,17 @@ idf.py - Ninja_,用于构建项目 - `esptool.py`_,烧录目标硬件设备 -可通过 ``idf.py`` 配置构建系统,具体可参考 :doc:`相关文档 `。 +可通过 ``idf.py`` 配置构建系统,具体可参考 :doc:`IDF 前端工具 `。 直接使用 CMake -------------- -为了方便,:ref:`idf.py` 已经封装了 CMake_ 命令,但是你愿意,也可以直接调用 CMake。 +为了方便,:ref:`idf.py` 已经封装了 CMake_ 命令。你也可以直接调用 CMake。 .. highlight:: bash -当 ``idf.py`` 在执行某些操作时,它会打印出其运行的每条命令以便参考。例如运行 ``idf.py build`` 命令与在 bash shell(或者 Windows Command Prompt)中运行以下命令是相同的:: +当 ``idf.py`` 在执行某些操作时,它会打印运行的每条命令以便参考。例如,运行 ``idf.py build`` 命令等同于在 bash shell 中运行以下命令(或在 Windows 命令提示符中运行类似的命令):: mkdir -p build cd build @@ -79,7 +79,7 @@ idf.py 若在 CMake 中使用 ``ninja`` 或 ``make``,则多数 ``idf.py`` 子命令也会有其对应的目标,例如在构建目录下运行 ``make menuconfig`` 或 ``ninja menuconfig`` 与运行 ``idf.py menuconfig`` 是相同的。 -.. Note:: +.. note:: 如果你已经熟悉了 CMake_,那么可能会发现 ESP-IDF 的 CMake 构建系统不同寻常,为了减少样板文件,该系统封装了 CMake 的许多功能。请参考 :ref:`write-pure-component` 以编写更多 “CMake 风格”的组件。 @@ -103,7 +103,7 @@ idf.py ESPPORT=/dev/ttyUSB0 ninja flash -.. Note:: +.. note:: 在命令的开头为环境变量赋值属于 Bash shell 的语法,可在 Linux 、macOS 和 Windows 的类 Bash shell 中运行,但在 Windows Command Prompt 中无法运行。 @@ -111,7 +111,7 @@ idf.py make -j3 app-flash ESPPORT=COM4 ESPBAUD=2000000 -.. Note:: +.. note:: 在命令末尾为变量赋值属于 ``make`` 的语法,适用于所有平台的 ``make``。 @@ -127,7 +127,6 @@ idf.py .. _setting-python-interpreter: - 设置 Python 解释器 ------------------ @@ -602,7 +601,7 @@ Spark Plug 组件 通用组件依赖项 -------------- -为避免重复性工作,各组件都用自动依赖一些“通用”IDF 组件,即使它们没有被明确提及。这些组件的头文件会一直包含在构建系统中。 +为避免重复性工作,各组件都用自动依赖一些“通用” IDF 组件,即使它们没有被明确提及。这些组件的头文件会一直包含在构建系统中。 通用组件包括:cxx、newlib、freertos、esp_hw_support、heap、log、soc、hal、esp_rom、esp_common、esp_system。 @@ -615,15 +614,14 @@ Spark Plug 组件 * ``COMPONENTS`` 中明确提及的组件。 * 这些组件的依赖项(以及递归运算后的组件)。 - * 每个组件都依赖的通用组件。 + * 每个组件都依赖的 :ref:`通用组件 `。 - 将 ``COMPONENTS`` 设置为所需组件的最小列表,可以显著减少项目的构建时间。 -- 可以将 ``MINIMAL_BUILD`` :ref:`构建属性 ` 设为 ``ON``,从而快捷配置 ``COMPONENTS`` 变量,使其仅包含 ``main`` 组件。如果在启用 ``MINIMAL_BUILD`` 属性的同时定义了 ``COMPONENTS`` 变量,则 ``COMPONENTS`` 会优先生效。 +- 可以将 ``MINIMAL_BUILD`` :ref:`构建属性 ` 设为 ``ON``,从而快捷配置 ``COMPONENTS`` 变量,使其仅包含 ``main`` 组件。构建过程将仅包括 :ref:`通用组件 `、``main`` 组件和所有相关依赖项(包括直接和间接依赖)。如果在启用 ``MINIMAL_BUILD`` 属性的同时定义了 ``COMPONENTS`` 变量,则 ``COMPONENTS`` 会优先生效。 .. note:: - 使用 ``COMPONENTS`` 变量或 ``MINIMAL_BUILD`` 构建属性指定组件时,一些功能和配置(如 esp_psram 或 espcoredump 组件提供的功能和配置)可能不会被默认包含。如需使用这些功能,须将相关组件添加到 ``COMPONENTS`` 变量中,或在组件注册时将其列入 ``REQUIRES`` 或 ``PRIV_REQUIRES`` 参数。 - + 如果使用最小组件列表,某些功能和配置(如 esp_psram 或 espcoredump 组件提供的功能和配置)可能默认无法在项目中使用。使用 ``COMPONENTS`` 变量时,请确保包含所有必要的组件。同样地,使用 ``MINIMAL_BUILD`` 构建属性时,请确保在组件注册时通过 ``REQUIRES`` 或 ``PRIV_REQUIRES`` 参数指定所有所需组件。 .. _component-circular-dependencies: diff --git a/docs/zh_CN/api-guides/core_dump.rst b/docs/zh_CN/api-guides/core_dump.rst index 4a4ed94bf2a5..0b1b01455043 100644 --- a/docs/zh_CN/api-guides/core_dump.rst +++ b/docs/zh_CN/api-guides/core_dump.rst @@ -17,7 +17,8 @@ -------------- .. note:: - 只有在构建中包含 ``espcoredump`` 组件时,``Core dump`` 配置选项才可用。 + + 只有在构建中包含 ``espcoredump`` 组件时,``Core dump`` 配置选项才可用。要在项目中包含 ``Core dump`` 功能,在使用 ``idf_component_register`` 注册组件时,将 ``espcoredump`` 组件添加为 ``REQUIRES`` 或 ``PRIV_REQUIRES`` 的依赖项。 目标 ^^^^^^^^^^^ @@ -137,8 +138,6 @@ ELF 格式具备扩展特性,支持在发生崩溃时保存更多关于错误 如果设置 :ref:`CONFIG_ESP_COREDUMP_DECODE`,使其自动解码 UART 核心转储文件,ESP-IDF 监视器会自动解码数据,将所有函数地址转换为源代码行,并在监视器中显示相应信息。ESP-IDF 监视器会输出类似以下内容: -此外,选项 :ref:`CONFIG_ESP_COREDUMP_UART_DELAY` 支持在将核心转储文件输出到 UART 前添加延迟。 - .. code-block:: none =============================================================== @@ -187,6 +186,7 @@ ELF 格式具备扩展特性,支持在发生崩溃时保存更多关于错误 ===================== ESP32 CORE DUMP END ===================== =============================================================== +此外,选项 :ref:`CONFIG_ESP_COREDUMP_UART_DELAY` 支持在将核心转储文件输出到 UART 前添加延迟。 手动解码 ^^^^^^^^^^^^^^^ @@ -217,10 +217,12 @@ ELF 格式具备扩展特性,支持在发生崩溃时保存更多关于错误 核心转储命令 ------------------ -ESP-IDF 提供了一些特殊命令,有助于检索和分析核心转储: +ESP-IDF 提供了一些特殊命令,用于检索和分析核心转储: + +* ``idf.py coredump-info`` - 从 flash 中读取核心转储,打印崩溃任务的寄存器、调用栈、系统可用任务列表、内存区域以及核心转储中存储的内存内容(包括 TCB 和栈)。 +* ``idf.py coredump-debug`` - 从 flash 中读取核心转储,将其保存为 ELF 文件,并使用该文件运行 GDB 调试会话。你可以手动检查内存、变量和任务状态。请注意,由于并未将所有内存保存在核心转储中,因此只有在栈上分配的变量的值才有意义。 -* ``idf.py coredump-info`` - 打印崩溃任务的寄存器、调用栈、系统可用任务列表、内存区域以及核心转储中存储的内存内容(包括 TCB 和栈)。 -* ``idf.py coredump-debug`` - 创建核心转储 ELF 文件,并使用该文件运行 GDB 调试会话。你可以手动检查内存、变量和任务状态。请注意,由于并未将所有内存保存在核心转储中,因此只有在栈上分配的变量的值才有意义。 +运行 ``idf.py coredump-info --help`` 和 ``idf.py coredump-debug --help`` 命令可以查看更详细的使用说明。例如,它们可以将核心转储保存到文件中,避免每次执行命令时都需要从 flash 中读取。 高阶用户如果需要传递额外参数或使用自定义 ELF 文件,可直接使用 `esp-coredump `_ 工具。如果在 ESP-IDF 环境中使用该工具,可运行如下命令查询更多信息: @@ -287,13 +289,6 @@ ESP-IDF 提供了一些特殊命令,有助于检索和分析核心转储: (gdb) p global_var $1 = 25 '\031' - -运行 ``idf.py coredump-info`` 和 ``idf.py coredump-debug`` --------------------------------------------------------------- - -要获取更多有关使用方法的详情,请运行 ``idf.py coredump-info --help`` 和 ``idf.py coredump-debug --help`` 命令。 - - 相关文档 ^^^^^^^^^^^^^^^^^ diff --git a/docs/zh_CN/api-guides/external-ram.rst b/docs/zh_CN/api-guides/external-ram.rst index 4dd921ddefb1..d6a5b24f9681 100644 --- a/docs/zh_CN/api-guides/external-ram.rst +++ b/docs/zh_CN/api-guides/external-ram.rst @@ -47,7 +47,8 @@ ======================== .. note:: - 只有在构建中包含 ``esp_psram`` 组件时,``SPI RAM`` 配置选项才可用。 + + 只有在构建中包含 ``esp_psram`` 组件时,``SPI RAM`` 配置选项才可用。要在项目中包含 ``SPI RAM`` 功能,使用 ``idf_component_register`` 注册组件时,将 ``esp_psram`` 组件添加为 ``REQUIRES`` 或 ``PRIV_REQUIRES`` 的依赖项。 ESP-IDF 完全支持将片外 RAM 集成到你的应用程序中。在启动并完成片外 RAM 初始化后,可以将 ESP-IDF 配置为用多种方式处理片外 RAM: @@ -55,7 +56,7 @@ ESP-IDF 完全支持将片外 RAM 集成到你的应用程序中。在启动并 * :ref:`external_ram_config_memory_map` * :ref:`external_ram_config_capability_allocator` - * :ref:`external_ram_config_malloc` (default) + * :ref:`external_ram_config_malloc` (默认方式) * :ref:`external_ram_config_bss` * :ref:`external_ram_config_noinit` :SOC_SPIRAM_XIP_SUPPORTED: * :ref:`external_ram_config_xip` diff --git a/docs/zh_CN/api-guides/performance/size.rst b/docs/zh_CN/api-guides/performance/size.rst index a609b638bcdb..e6fe7c0c5253 100644 --- a/docs/zh_CN/api-guides/performance/size.rst +++ b/docs/zh_CN/api-guides/performance/size.rst @@ -202,23 +202,26 @@ MbedTLS 功能 这些功能包括: -- :ref:`CONFIG_MBEDTLS_HAVE_TIME` -- :ref:`CONFIG_MBEDTLS_ECDSA_DETERMINISTIC` -- :ref:`CONFIG_MBEDTLS_SHA512_C` -- :ref:`CONFIG_MBEDTLS_SHA3_C` -- :ref:`CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS` -- :ref:`CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS` -- :ref:`CONFIG_MBEDTLS_SSL_CONTEXT_SERIALIZATION` -- :ref:`CONFIG_MBEDTLS_SSL_ALPN` -- :ref:`CONFIG_MBEDTLS_SSL_RENEGOTIATION` -- :ref:`CONFIG_MBEDTLS_CCM_C` -- :ref:`CONFIG_MBEDTLS_GCM_C` -- :ref:`CONFIG_MBEDTLS_ECP_C` (或者:启用此选项,但在子菜单中禁用部分椭圆曲线) -- :ref:`CONFIG_MBEDTLS_ECP_NIST_OPTIM` -- :ref:`CONFIG_MBEDTLS_ECP_FIXED_POINT_OPTIM` -- 如果不需要 mbedTLS 的服务器和客户端功能,可以修改 :ref:`CONFIG_MBEDTLS_TLS_MODE`。 -- 可以考虑禁用在 ``TLS Key Exchange Methods`` 子菜单中列出的一些密码套件(例如 :ref:`CONFIG_MBEDTLS_KEY_EXCHANGE_RSA`),以减小代码大小。 -- 如果应用程序已经通过使用 :cpp:func:`mbedtls_strerror` 拉取 mbedTLS 错误字符串,则可以考虑禁用 :ref:`CONFIG_MBEDTLS_ERROR_STRINGS`。 +.. list:: + + - :ref:`CONFIG_MBEDTLS_HAVE_TIME` + - :ref:`CONFIG_MBEDTLS_ECDSA_DETERMINISTIC` + - :ref:`CONFIG_MBEDTLS_SHA512_C` + - :ref:`CONFIG_MBEDTLS_SHA3_C` + - :ref:`CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS` + - :ref:`CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS` + - :ref:`CONFIG_MBEDTLS_SSL_CONTEXT_SERIALIZATION` + - :ref:`CONFIG_MBEDTLS_SSL_ALPN` + - :ref:`CONFIG_MBEDTLS_SSL_RENEGOTIATION` + - :ref:`CONFIG_MBEDTLS_CCM_C` + - :ref:`CONFIG_MBEDTLS_GCM_C` + - :ref:`CONFIG_MBEDTLS_ECP_C` (或者:启用此选项,但在子菜单中禁用部分椭圆曲线) + - :ref:`CONFIG_MBEDTLS_ECP_NIST_OPTIM` + - :ref:`CONFIG_MBEDTLS_ECP_FIXED_POINT_OPTIM` + - 如果不需要 mbedTLS 的服务器和客户端功能,可以修改 :ref:`CONFIG_MBEDTLS_TLS_MODE`。 + - 可以考虑禁用在 ``TLS Key Exchange Methods`` 子菜单中列出的一些密码套件(例如 :ref:`CONFIG_MBEDTLS_KEY_EXCHANGE_RSA`),以减小代码大小。 + - 如果应用程序已经通过使用 :cpp:func:`mbedtls_strerror` 拉取 mbedTLS 错误字符串,则可以考虑禁用 :ref:`CONFIG_MBEDTLS_ERROR_STRINGS`。 + :esp32h2: - 对于 {IDF_TARGET_NAME} v1.2 及以上版本,可以考虑禁用 :ref:`CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_MASKING_CM` 和 :ref:`CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_CONSTANT_TIME_CM`,因为无需再使用 ECDSA 签名的软件防护措施。 每个选项的帮助文本中都有更多信息可供参考。 diff --git a/docs/zh_CN/api-reference/peripherals/i2c.rst b/docs/zh_CN/api-reference/peripherals/i2c.rst index d2f456837f89..8efb05a9bdf3 100644 --- a/docs/zh_CN/api-reference/peripherals/i2c.rst +++ b/docs/zh_CN/api-reference/peripherals/i2c.rst @@ -216,6 +216,8 @@ I2C 主机设备需要 :cpp:type:`i2c_device_config_t` 指定的配置: 如果不再需要之前安装的 I2C 总线或设备,建议调用 :cpp:func:`i2c_master_bus_rm_device` 或 :cpp:func:`i2c_del_master_bus` 来回收资源,以释放底层硬件。 +请注意在删除 I2C master 总线之前应当删除该总线上所有的设备。 + 安装 I2C 从机设备 ~~~~~~~~~~~~~~~~~~~ diff --git a/docs/zh_CN/api-reference/peripherals/rmt.rst b/docs/zh_CN/api-reference/peripherals/rmt.rst index d1c0a91df0fa..0eac78bb3fb9 100644 --- a/docs/zh_CN/api-reference/peripherals/rmt.rst +++ b/docs/zh_CN/api-reference/peripherals/rmt.rst @@ -144,7 +144,7 @@ RMT 接收器可以对输入信号采样,将其转换为 RMT 数据格式, .. note:: - 由于 GPIO 驱动程序中的软件限制,当 TX 和 RX 通道都绑定到同一 GPIO 时,请确保在 TX 通道之前初始化 RX 通道。如果先设置 TX 通道,那么在 RX 通道设置期间,GPIO 控制信号将覆盖先前的 RMT TX 通道信号。 + 同时分配多个 RMT 通道时,RMT 组的分频系数将以第一个通道的分辨率来计算,驱动会从低到高寻找合适的分频系数。若分配多个通道时出现分频系数冲突,请调整分配通道的顺序,按照目标分辨率的大小按序申请通道(从大到小或者从小到大)。 卸载 RMT 通道 ~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/zh_CN/api-reference/protocols/mqtt.rst b/docs/zh_CN/api-reference/protocols/mqtt.rst index 7ad56ec21e23..b2a79f7445c3 100644 --- a/docs/zh_CN/api-reference/protocols/mqtt.rst +++ b/docs/zh_CN/api-reference/protocols/mqtt.rst @@ -205,3 +205,4 @@ API 参考 ------------- .. include-build-file:: inc/mqtt_client.inc +.. include-build-file:: inc/mqtt5_client.inc diff --git a/docs/zh_CN/api-reference/system/intr_alloc.rst b/docs/zh_CN/api-reference/system/intr_alloc.rst index d50fd63c7190..803e0fbede5f 100644 --- a/docs/zh_CN/api-reference/system/intr_alloc.rst +++ b/docs/zh_CN/api-reference/system/intr_alloc.rst @@ -8,31 +8,31 @@ .. only:: esp32 or esp32s3 - {IDF_TARGET_NAME} 有两个核,每个核有 32 个中断。每个中断都有一个确定的优先级别,大多数中断(但不是全部)都连接到中断矩阵。 + {IDF_TARGET_NAME} 有两个核,每个核有 32 个中断。每个中断都有一个确定的优先级别,大多数中断(但不是全部)都连接到中断矩阵。 .. only:: esp32s2 - {IDF_TARGET_NAME} 有一个核,32 个中断。每个中断都有一个确定的优先级别,大多数中断(但不是全部)都连接到中断矩阵。 + {IDF_TARGET_NAME} 有一个核,32 个中断。每个中断都有一个确定的优先级别,大多数中断(但不是全部)都连接到中断矩阵。 .. only:: esp32c2 or esp32c3 - {IDF_TARGET_NAME} 有一个核,31 个中断。每个中断的优先级别都可独立地通过编程设置。 + {IDF_TARGET_NAME} 有一个核,31 个中断。每个中断的优先级别都可独立地通过编程设置。 .. only:: esp32c6 or esp32h2 - {IDF_TARGET_NAME} 有一个核,28 个外部异步中断。每个中断的优先级别都可独立地通过编程设置。此外,还有 4 个核心本地中断源 (CLINT)。详细信息请参见 **{IDF_TARGET_NAME} 技术参考手册** [`PDF <{IDF_TARGET_TRM_CN_URL}#riscvcpu>`__]。 + {IDF_TARGET_NAME} 有一个核,28 个外部异步中断。每个中断的优先级别都可独立地通过编程设置。此外,还有 4 个核心本地中断源 (CLINT)。详细信息请参见 **{IDF_TARGET_NAME} 技术参考手册** [`PDF <{IDF_TARGET_TRM_CN_URL}#riscvcpu>`__]。 .. only:: esp32p4 - {IDF_TARGET_NAME} 有两个核,每个核有 32 个外部异步中断。每个中断的优先级别都可独立地通过编程设置。此外,每个核还有 3 个核心本地中断源 (CLINT)。详细信息请参见 **{IDF_TARGET_NAME} 技术参考手册** [`PDF <{IDF_TARGET_TRM_CN_URL}#riscvcpu>`__]。 + {IDF_TARGET_NAME} 有两个核,每个核有 32 个外部异步中断。每个中断的优先级别都可独立地通过编程设置。此外,每个核还有 3 个核心本地中断源 (CLINT)。详细信息请参见 **{IDF_TARGET_NAME} 技术参考手册** [`PDF <{IDF_TARGET_TRM_CN_URL}#riscvcpu>`__]。 .. only:: esp32c5 or esp32c61 - {IDF_TARGET_NAME} 有一个核,32 个外部异步中断。每个中断的优先级别都可独立地通过编程设置。此外,还有 3 个核心本地中断源 (CLINT)。详细信息请参见 **{IDF_TARGET_NAME} 技术参考手册** > **高性能处理器** [`PDF <{IDF_TARGET_TRM_CN_URL}#riscvcpu>`__]。 + {IDF_TARGET_NAME} 有一个核,32 个外部异步中断。每个中断的优先级别都可独立地通过编程设置。此外,还有 3 个核心本地中断源 (CLINT)。详细信息请参见 **{IDF_TARGET_NAME} 技术参考手册** > **高性能处理器** [`PDF <{IDF_TARGET_TRM_CN_URL}#riscvcpu>`__]。 由于中断源数量多于中断,有时多个驱动程序可以共用一个中断。:cpp:func:`esp_intr_alloc` 抽象隐藏了这些实现细节。 -驱动程序可以通过调用 :cpp:func:`esp_intr_alloc`,或 :cpp:func:`esp_intr_alloc_intrstatus` 为某个外设分配中断。通过向此函数传递 flag,可以指定中断类型、优先级和触发方式。然后,中断分配代码会找到适用的中断,使用中断矩阵将其连接到外设,并为其安装给定的中断处理程序和 ISR。 +驱动程序可以通过调用 :cpp:func:`esp_intr_alloc`、:cpp:func:`esp_intr_alloc_bind`、 :cpp:func:`esp_intr_alloc_intrstatus` 或 :cpp:func:`esp_intr_alloc_intrstatus_bind` 为某个外设分配中断。通过向此函数传递 flag,可以指定中断类型、优先级和触发方式。然后,中断分配代码会找到适用的中断,使用中断矩阵将其连接到外设,并为其安装给定的中断处理程序和 ISR。 中断分配器提供两种不同的中断类型:共享中断和非共享中断,这两种中断需要不同处理方式。非共享中断在每次调用 :cpp:func:`esp_intr_alloc` 时,都会分配一个单独的中断,该中断仅用于与其相连的外设,只调用一个 ISR。共享中断则可以由多个外设触发,当其中一个外设发出中断信号时,会调用多个 ISR。因此,针对共享中断的 ISR 应检查对应外设的中断状态,以确定是否需要采取任何操作。 @@ -138,9 +138,7 @@ IRAM 安全中断处理程序 关联到非共享中断的源不支持此功能。 -.. only:: not SOC_CPU_HAS_FLEXIBLE_INTC - - 默认情况下,指定 ``ESP_INTR_FLAG_SHARED`` flag 时,中断分配器仅分配优先级为 1 的中断。可以使用 ``ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_LOWMED`` 允许分配优先级为 2 和 3 的共享中断。 +默认情况下,指定 ``ESP_INTR_FLAG_SHARED`` flag 时,中断分配器仅分配优先级为 1 的中断。可以使用 ``ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_LOWMED`` 允许分配优先级为 2 和 3 的共享中断。 尽管支持此功能,使用时也必须 **非常小心**。通常存在两种办法可以阻止中断触发: **禁用源** 或 **屏蔽外设中断状态**。ESP-IDF 仅处理源本身的启用和禁用,中断源的状态位和屏蔽位须由用户操作。 @@ -150,6 +148,8 @@ IRAM 安全中断处理程序 如果不屏蔽状态位而让其处于未处理状态,同时禁用这些状态位的处理程序,就会导致无限次触发中断,引起系统崩溃。 +调用 :cpp:func:`esp_intr_alloc` 或 :cpp:func:`esp_intr_alloc_intrstatus` 时,中断分配器会选择第一个满足电平要求的中断为指定的源映射中断,而不会考虑已经映射到共享中断线上的其他源。然而,通过使用 :cpp:func:`esp_intr_alloc_bind` 或 :cpp:func:`esp_intr_alloc_intrstatus_bind` 函数,可以显式地指定中断处理程序与给定的中断源共享。 + 排除中断分配故障 ------------------ diff --git a/docs/zh_CN/api-reference/system/mem_alloc.rst b/docs/zh_CN/api-reference/system/mem_alloc.rst index ed203af3abd9..ea3709de69f3 100644 --- a/docs/zh_CN/api-reference/system/mem_alloc.rst +++ b/docs/zh_CN/api-reference/system/mem_alloc.rst @@ -1,6 +1,8 @@ 堆内存分配 ====================== +{IDF_TARGET_SIMD_PREFERRED_DATA_ALIGNMENT: default="16", esp32s3="16", esp32p4="16"} + :link_to_translation:`en:[English]` 栈 (stack) 和堆 (heap) 的区别 @@ -134,6 +136,13 @@ DMA 存储器 在 ESP32 上,只有不超过 4 MiB 的外部 SPI RAM 可以通过上述方式分配。要使用超过 4 MiB 限制的区域,可以使用 :doc:`himem API`。 +.. only:: SOC_SIMD_INSTRUCTION_SUPPORTED + + SIMD 指令可访问内存 + ^^^^^^^^^^^^^^^^^^^ + + ``MALLOC_CAP_SIMD`` 标志用于分配可被 SIMD(单指令多数据)指令访问的内存。使用该标志时,分配的内存会自动对齐到 SIMD 最佳数据对齐大小({IDF_TARGET_SIMD_PREFERRED_DATA_ALIGNMENT}-byte),从而提升性能。 + 线程安全性 ------------- diff --git a/docs/zh_CN/api-reference/system/ota.rst b/docs/zh_CN/api-reference/system/ota.rst index 81280b2880a7..85f89589cb1d 100644 --- a/docs/zh_CN/api-reference/system/ota.rst +++ b/docs/zh_CN/api-reference/system/ota.rst @@ -12,7 +12,7 @@ OTA 升级机制可以让设备在固件正常运行时根据接收数据(如 - **安全更新模式**:可靠、稳定的分区更新,即使在更新期间断电,芯片仍能正常运行,并能够启动当前的应用程序。以下分区支持此模式: - - 应用程序分区。要进行 OTA 更新,需在设备的 :doc:`../../api-guides/partition-tables` 分区表中配置至少两个 OTA 应用程序分区槽(例如 ``ota_0`` 和 ``ota_1``)以及一个 OTA 数据分区。OTA 操作函数会将新的应用程序固件镜像写入当前未被选为启动分区的 OTA 应用程序分区槽。镜像验证通过后,OTA 数据分区将被更新,以指定在下次启动时使用该镜像。 + - 应用程序分区。要进行 OTA 更新,需在设备的 :doc:`../../api-guides/partition-tables` 中配置至少两个 OTA 应用程序分区槽(例如 ``ota_0`` 和 ``ota_1``)以及一个 OTA 数据分区。OTA 操作函数会将新的应用程序固件镜像写入当前未被选为启动分区的 OTA 应用程序分区槽。镜像验证通过后,OTA 数据分区将被更新,以指定在下次启动时使用该镜像。 - **非安全更新模式**:此更新过程容易受到干扰,如果在更新过程中断电,可能会导致当前应用程序无法加载,甚至进入无法恢复的状态。在此模式下,新的镜像会先下载到临时分区,下载完成后复制到最终的目标分区。如果在最终复制过程中发生中断,可能会导致问题。以下分区支持此模式: @@ -140,7 +140,7 @@ Kconfig 中的 :ref:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` 可以帮助用户 * ``ESP_OTA_IMG_VALID`` 由函数 :cpp:func:`esp_ota_mark_app_valid_cancel_rollback` 设置。 * 如果 :ref:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` 没有使能,``ESP_OTA_IMG_UNDEFINED`` 由函数 :cpp:func:`esp_ota_set_boot_partition` 设置。 * 如果 :ref:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` 使能,``ESP_OTA_IMG_NEW`` 由函数 :cpp:func:`esp_ota_set_boot_partition` 设置。 -* ``ESP_OTA_IMG_INVALID`` 由函数 :cpp:func:`esp_ota_mark_app_invalid_rollback_and_reboot` 设置。 +* ``ESP_OTA_IMG_INVALID`` 由函数 :cpp:func:`esp_ota_mark_app_invalid_rollback` 或 :cpp:func:`esp_ota_mark_app_invalid_rollback_and_reboot` 设置。 * 如果应用程序的可操作性无法确认,发生重启(:ref:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` 使能),则设置 ``ESP_OTA_IMG_ABORTED``。 * 如果 :ref:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` 使能,选取的应用程序状态为 ``ESP_OTA_IMG_NEW``,则在引导加载程序中设置 ``ESP_OTA_IMG_PENDING_VERIFY``。 @@ -165,7 +165,7 @@ Kconfig 中的 :ref:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` 可以帮助用户 - 运行函数 :cpp:func:`esp_ota_set_boot_partition`,将新版应用程序设为可启动。如果新版应用程序的安全版本号低于芯片中的应用安全版本号,新版应用程序会被擦除,无法更新到新固件。 - 重新启动。 - 在引导加载程序中选取安全版本号等于或高于芯片中应用安全版本号的应用程序。如果 otadata 处于初始阶段,通过串行通道加载了安全版本号高于芯片中应用安全版本号的固件,则引导加载程序中 eFuse 的安全版本号会立即更新。 -- 新版应用程序启动,之后进行可操作性检测,如果通过检测,则调用函数 :cpp:func:`esp_ota_mark_app_valid_cancel_rollback`,将应用程序标记为 ``ESP_OTA_IMG_VALID``,更新芯片中应用程序的安全版本号。注意,如果调用函数 :cpp:func:`esp_ota_mark_app_invalid_rollback_and_reboot`,可能会因为设备中没有可启动的应用程序而回滚失败,返回 ``ESP_ERR_OTA_ROLLBACK_FAILED`` 错误,应用程序状态一直为 ``ESP_OTA_IMG_PENDING_VERIFY``。 +- 新版应用程序启动,之后进行可操作性检测,如果通过检测,则调用函数 :cpp:func:`esp_ota_mark_app_valid_cancel_rollback`,将应用程序标记为 ``ESP_OTA_IMG_VALID``,更新芯片中应用程序的安全版本号。注意,如果调用了函数 :cpp:func:`esp_ota_mark_app_invalid_rollback` 或 :cpp:func:`esp_ota_mark_app_invalid_rollback_with_reboot`,也可能会因为设备中没有可启动的应用程序而回滚失败,返回 ``ESP_ERR_OTA_ROLLBACK_FAILED`` 错误,应用程序状态一直处于 ``ESP_OTA_IMG_PENDING_VERIFY`` 状态。 - 如果运行的应用程序处于 ``ESP_OTA_IMG_VALID`` 状态,则可再次更新。 建议: diff --git a/docs/zh_CN/migration-guides/release-5.x/5.5/system.rst b/docs/zh_CN/migration-guides/release-5.x/5.5/system.rst index de99ca24583d..fdc0440f9515 100644 --- a/docs/zh_CN/migration-guides/release-5.x/5.5/system.rst +++ b/docs/zh_CN/migration-guides/release-5.x/5.5/system.rst @@ -4,11 +4,38 @@ :link_to_translation:`zh_CN:[中文]` 系统时间 ------------------------ +-------- * ``{IDF_TARGET_NAME}/rtc.h`` 已弃用,应使用 ``esp_rtc_time.h`` 替代。 -Log ---- +日志 +---- -.. include:: ../../../../en/migration-guides/release-5.x/5.5/system.rst +**Log V2** 是 ESP-IDF v5.5 版本提供的增强型可选日志功能。它与 **Log V1** 完全兼容,项目无需修改即可继续使用 **Log V1**。开发者可以通过 Kconfig 选项 :ref:`CONFIG_LOG_VERSION` 启用 **Log V2**。未来的 ESP-IDF 版本可能默认使用 **Log V2**。 + +**特性** + +- 集中化日志处理、可动态设置的格式参数和更高的灵活性。 +- 消耗更多的栈和内存,但二进制文件体积更小(具体数据详见文档 `日志库 <../../../system/log.rst>`_)。 +- **Log V2** 的特定功能(如动态设置格式、执行上下文检测)不能向后兼容 **Log V1**。 + +如需使用 ``esp_log_write`` (或 ``esp_log_writev``)函数,请替换为 ``esp_log`` (或 ``esp_log_va``),以减少一层嵌套调用。 + +日志处理程序 (``esp_log``) 支持内部格式化,因此无需手动构建格式。可以通过 ``ESP_LOG_LEVEL_LOCAL`` 简化以下代码。 + +.. code-block:: c + + #if ESP_LOG_VERSION == 2 + ESP_LOG_LEVEL_LOCAL(ESP_LOG_ERROR, OT_PLAT_LOG_TAG, format, args); + #else + if (LOG_LOCAL_LEVEL >= ESP_LOG_ERROR) { + esp_log(ESP_LOG_CONFIG_INIT(ESP_LOG_ERROR), OT_PLAT_LOG_TAG, LOG_COLOR_E "E(%lu) %s:", esp_log_timestamp(), OT_PLAT_LOG_TAG); + esp_log_va(ESP_LOG_CONFIG_INIT(ESP_LOG_ERROR), OT_PLAT_LOG_TAG, format, args); + esp_log(ESP_LOG_CONFIG_INIT(ESP_LOG_ERROR), OT_PLAT_LOG_TAG, LOG_RESET_COLOR "\n"); + } + #endif + +预加密 OTA +------------ + +``pre_encrypted_ota`` 示例已移至 `idf-extra-components `__ 仓库。 diff --git a/examples/bluetooth/bluedroid/ble/gatt_server/sdkconfig.defaults b/examples/bluetooth/bluedroid/ble/gatt_server/sdkconfig.defaults index 0329933a8f80..ad218785e70a 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_server/sdkconfig.defaults +++ b/examples/bluetooth/bluedroid/ble/gatt_server/sdkconfig.defaults @@ -6,17 +6,3 @@ CONFIG_BT_ENABLED=y CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y # CONFIG_BT_LE_50_FEATURE_SUPPORT is not used on ESP32, ESP32-C3 and ESP32-S3. # CONFIG_BT_LE_50_FEATURE_SUPPORT is not set - -CONFIG_EXAMPLE_CI_ID=4 -CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} -CONFIG_BT_BLUEDROID_MEM_DEBUG=y -CONFIG_BT_GATTS_PPCP_CHAR_GAP=y -CONFIG_BT_BLE_BLUFI_ENABLE=y -CONFIG_BT_GATTS_ROBUST_CACHING_ENABLED=y -CONFIG_BT_GATTC_CACHE_NVS_FLASH=y -CONFIG_BT_SMP_SLAVE_CON_PARAMS_UPD_ENABLE=y -CONFIG_BT_BLE_SMP_ID_RESET_ENABLE=y -CONFIG_BT_BLE_HOST_QUEUE_CONG_CHECK=y -CONFIG_BT_BLE_ACT_SCAN_REP_ADV_SCAN=y -CONFIG_BT_BLE_HIGH_DUTY_ADV_INTERVAL=y -CONFIG_BT_ABORT_WHEN_ALLOCATION_FAILS=y diff --git a/examples/bluetooth/blufi/main/blufi_example_main.c b/examples/bluetooth/blufi/main/blufi_example_main.c index 982158558b0b..fb406afe8c39 100644 --- a/examples/bluetooth/blufi/main/blufi_example_main.c +++ b/examples/bluetooth/blufi/main/blufi_example_main.c @@ -382,12 +382,22 @@ static void example_event_callback(esp_blufi_cb_event_t event, esp_blufi_cb_para BLUFI_INFO("Recv STA BSSID %s\n", sta_config.sta.ssid); break; case ESP_BLUFI_EVENT_RECV_STA_SSID: + if (param->sta_ssid.ssid_len >= sizeof(sta_config.sta.ssid)/sizeof(sta_config.sta.ssid[0])) { + esp_blufi_send_error_info(ESP_BLUFI_DATA_FORMAT_ERROR); + BLUFI_INFO("Invalid STA SSID\n"); + break; + } strncpy((char *)sta_config.sta.ssid, (char *)param->sta_ssid.ssid, param->sta_ssid.ssid_len); sta_config.sta.ssid[param->sta_ssid.ssid_len] = '\0'; esp_wifi_set_config(WIFI_IF_STA, &sta_config); BLUFI_INFO("Recv STA SSID %s\n", sta_config.sta.ssid); break; case ESP_BLUFI_EVENT_RECV_STA_PASSWD: + if (param->sta_passwd.passwd_len >= sizeof(sta_config.sta.password)/sizeof(sta_config.sta.password[0])) { + esp_blufi_send_error_info(ESP_BLUFI_DATA_FORMAT_ERROR); + BLUFI_INFO("Invalid STA PASSWORD\n"); + break; + } strncpy((char *)sta_config.sta.password, (char *)param->sta_passwd.passwd, param->sta_passwd.passwd_len); sta_config.sta.password[param->sta_passwd.passwd_len] = '\0'; sta_config.sta.threshold.authmode = EXAMPLE_WIFI_SCAN_AUTH_MODE_THRESHOLD; @@ -395,6 +405,11 @@ static void example_event_callback(esp_blufi_cb_event_t event, esp_blufi_cb_para BLUFI_INFO("Recv STA PASSWORD %s\n", sta_config.sta.password); break; case ESP_BLUFI_EVENT_RECV_SOFTAP_SSID: + if (param->softap_ssid.ssid_len >= sizeof(ap_config.ap.ssid)/sizeof(ap_config.ap.ssid[0])) { + esp_blufi_send_error_info(ESP_BLUFI_DATA_FORMAT_ERROR); + BLUFI_INFO("Invalid SOFTAP SSID\n"); + break; + } strncpy((char *)ap_config.ap.ssid, (char *)param->softap_ssid.ssid, param->softap_ssid.ssid_len); ap_config.ap.ssid[param->softap_ssid.ssid_len] = '\0'; ap_config.ap.ssid_len = param->softap_ssid.ssid_len; @@ -402,6 +417,11 @@ static void example_event_callback(esp_blufi_cb_event_t event, esp_blufi_cb_para BLUFI_INFO("Recv SOFTAP SSID %s, ssid len %d\n", ap_config.ap.ssid, ap_config.ap.ssid_len); break; case ESP_BLUFI_EVENT_RECV_SOFTAP_PASSWD: + if (param->softap_passwd.passwd_len >= sizeof(ap_config.sta.ssid)/sizeof(ap_config.sta.ssid[0])) { + esp_blufi_send_error_info(ESP_BLUFI_DATA_FORMAT_ERROR); + BLUFI_INFO("Invalid SOFTAP PASSWD\n"); + break; + } strncpy((char *)ap_config.ap.password, (char *)param->softap_passwd.passwd, param->softap_passwd.passwd_len); ap_config.ap.password[param->softap_passwd.passwd_len] = '\0'; esp_wifi_set_config(WIFI_IF_AP, &ap_config); diff --git a/examples/bluetooth/blufi/main/blufi_security.c b/examples/bluetooth/blufi/main/blufi_security.c index 470e38ce1620..c3cc0e5099ce 100644 --- a/examples/bluetooth/blufi/main/blufi_security.c +++ b/examples/bluetooth/blufi/main/blufi_security.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -67,6 +67,12 @@ extern void btc_blufi_report_error(esp_blufi_error_state_t state); void blufi_dh_negotiate_data_handler(uint8_t *data, int len, uint8_t **output_data, int *output_len, bool *need_free) { + if (data == NULL || len < 3) { + BLUFI_ERROR("BLUFI Invalid data format"); + btc_blufi_report_error(ESP_BLUFI_DATA_FORMAT_ERROR); + return; + } + int ret; uint8_t type = data[0]; @@ -96,6 +102,13 @@ void blufi_dh_negotiate_data_handler(uint8_t *data, int len, uint8_t **output_da btc_blufi_report_error(ESP_BLUFI_DH_PARAM_ERROR); return; } + + if (len < (blufi_sec->dh_param_len + 1)) { + BLUFI_ERROR("%s, invalid dh param len\n", __func__); + btc_blufi_report_error(ESP_BLUFI_DH_PARAM_ERROR); + return; + } + uint8_t *param = blufi_sec->dh_param; memcpy(blufi_sec->dh_param, &data[1], blufi_sec->dh_param_len); ret = mbedtls_dhm_read_params(&blufi_sec->dhm, ¶m, ¶m[blufi_sec->dh_param_len]); @@ -108,6 +121,12 @@ void blufi_dh_negotiate_data_handler(uint8_t *data, int len, uint8_t **output_da blufi_sec->dh_param = NULL; const int dhm_len = mbedtls_dhm_get_len(&blufi_sec->dhm); + + if (dhm_len > DH_SELF_PUB_KEY_LEN) { + BLUFI_ERROR("%s dhm len not support %d\n", __func__, dhm_len); + btc_blufi_report_error(ESP_BLUFI_DH_PARAM_ERROR); + } + ret = mbedtls_dhm_make_public(&blufi_sec->dhm, dhm_len, blufi_sec->self_public_key, dhm_len, myrand, NULL); if (ret) { BLUFI_ERROR("%s make public failed %d\n", __func__, ret); diff --git a/examples/openthread/ot_br/main/Kconfig.projbuild b/examples/openthread/ot_br/main/Kconfig.projbuild index b18168829b69..e8d3a95717d4 100644 --- a/examples/openthread/ot_br/main/Kconfig.projbuild +++ b/examples/openthread/ot_br/main/Kconfig.projbuild @@ -8,6 +8,18 @@ menu "OpenThread Border Router Example" SSID and PSK, and then form a Thread network automatically. Otherwise, user need to configure Wi-Fi and Thread manually. + config OPENTHREAD_SUPPORT_HW_RESET_RCP + bool 'Enable hardware RCP resetting' + default False + help + If enabled, the Thread Border Router will support hardware resetting the RCP + when processing RCP failure. + + config OPENTHREAD_HW_RESET_RCP_PIN + int 'Pin to RCP reset' + depends on OPENTHREAD_SUPPORT_HW_RESET_RCP + default 7 + menu "External coexist wire type and pin config" config EXTERNAL_COEX_WIRE_TYPE int "The wire_type of external coexist" diff --git a/examples/openthread/ot_br/main/esp_ot_br.c b/examples/openthread/ot_br/main/esp_ot_br.c index 46bbc54810c2..bbd5ae3f0a33 100644 --- a/examples/openthread/ot_br/main/esp_ot_br.c +++ b/examples/openthread/ot_br/main/esp_ot_br.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: CC0-1.0 * @@ -38,6 +38,7 @@ #include "mdns.h" #include "nvs_flash.h" #include "protocol_examples_common.h" +#include "driver/gpio.h" #include "driver/uart.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" @@ -62,6 +63,26 @@ #define TAG "esp_ot_br" +#if CONFIG_OPENTHREAD_SUPPORT_HW_RESET_RCP +#define PIN_TO_RCP_RESET CONFIG_OPENTHREAD_HW_RESET_RCP_PIN +static void rcp_failure_hardware_reset_handler(void) +{ + gpio_config_t reset_pin_config; + memset(&reset_pin_config, 0, sizeof(reset_pin_config)); + reset_pin_config.intr_type = GPIO_INTR_DISABLE; + reset_pin_config.pin_bit_mask = BIT(PIN_TO_RCP_RESET); + reset_pin_config.mode = GPIO_MODE_OUTPUT; + reset_pin_config.pull_down_en = GPIO_PULLDOWN_DISABLE; + reset_pin_config.pull_up_en = GPIO_PULLUP_DISABLE; + gpio_config(&reset_pin_config); + gpio_set_level(PIN_TO_RCP_RESET, 0); + vTaskDelay(pdMS_TO_TICKS(10)); + gpio_set_level(PIN_TO_RCP_RESET, 1); + vTaskDelay(pdMS_TO_TICKS(30)); + gpio_reset_pin(PIN_TO_RCP_RESET); +} +#endif + #if CONFIG_EXTERNAL_COEX_ENABLE static void ot_br_external_coexist_init(void) { @@ -192,6 +213,9 @@ void app_main(void) ESP_ERROR_CHECK(nvs_flash_init()); ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_event_loop_create_default()); +#if CONFIG_OPENTHREAD_SUPPORT_HW_RESET_RCP + esp_openthread_register_rcp_failure_handler(rcp_failure_hardware_reset_handler); +#endif xTaskCreate(ot_task_worker, "ot_br_main", 8192, xTaskGetCurrentTaskHandle(), 5, NULL); xTaskCreate(ot_br_init, "ot_br_init", 6144, NULL, 4, NULL); } diff --git a/examples/openthread/ot_br/sdkconfig.ci.br b/examples/openthread/ot_br/sdkconfig.ci.br index e69de29bb2d1..ceb3c1a0a05a 100644 --- a/examples/openthread/ot_br/sdkconfig.ci.br +++ b/examples/openthread/ot_br/sdkconfig.ci.br @@ -0,0 +1,2 @@ +CONFIG_OPENTHREAD_SUPPORT_HW_RESET_RCP=y +CONFIG_OPENTHREAD_HW_RESET_RCP_PIN=6 diff --git a/examples/openthread/ot_br/sdkconfig.ci.br_spi b/examples/openthread/ot_br/sdkconfig.ci.br_spi index 1778799eb74b..7afe286169cf 100644 --- a/examples/openthread/ot_br/sdkconfig.ci.br_spi +++ b/examples/openthread/ot_br/sdkconfig.ci.br_spi @@ -1 +1,3 @@ CONFIG_OPENTHREAD_RADIO_SPINEL_SPI=y +CONFIG_OPENTHREAD_SUPPORT_HW_RESET_RCP=y +CONFIG_OPENTHREAD_HW_RESET_RCP_PIN=7 diff --git a/examples/openthread/ot_br/sdkconfig.ci.spinel_trel b/examples/openthread/ot_br/sdkconfig.ci.spinel_trel new file mode 100644 index 000000000000..58ad47256fce --- /dev/null +++ b/examples/openthread/ot_br/sdkconfig.ci.spinel_trel @@ -0,0 +1 @@ +CONFIG_OPENTHREAD_RADIO_TREL=y diff --git a/examples/openthread/ot_br/sdkconfig.ci.spinel_trel_ext_coex b/examples/openthread/ot_br/sdkconfig.ci.spinel_trel_ext_coex new file mode 100644 index 000000000000..571881d7f6cc --- /dev/null +++ b/examples/openthread/ot_br/sdkconfig.ci.spinel_trel_ext_coex @@ -0,0 +1,2 @@ +CONFIG_OPENTHREAD_RADIO_TREL=y +CONFIG_EXTERNAL_COEX_ENABLE=y diff --git a/examples/openthread/ot_ci_function.py b/examples/openthread/ot_ci_function.py index ddcdfa28c409..c84b96593eb0 100644 --- a/examples/openthread/ot_ci_function.py +++ b/examples/openthread/ot_ci_function.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 # !/usr/bin/env python3 # this file defines some functions for testing cli and br under pytest framework @@ -408,20 +408,21 @@ def get_host_ipv4_address() -> str: return host_ipv4_address -def start_avahi() -> None: - time.sleep(1) - command = '/etc/init.d/dbus start' +def restart_avahi() -> None: + command = 'avahi-daemon -k' subprocess.Popen(command, shell=True) - time.sleep(5) + time.sleep(2) command = 'avahi-daemon' subprocess.Popen(command, shell=True) time.sleep(5) -def host_publish_service() -> None: - command = 'avahi-publish-service testxxx _testxxx._udp 12347 test=1235 dn="for_ci_br_test"' +def start_avahi() -> None: + time.sleep(1) + command = '/etc/init.d/dbus start' subprocess.Popen(command, shell=True) - time.sleep(2) + time.sleep(5) + restart_avahi() def host_close_service() -> None: diff --git a/examples/openthread/pytest_otbr.py b/examples/openthread/pytest_otbr.py index bfa04f42318e..846247e2adec 100644 --- a/examples/openthread/pytest_otbr.py +++ b/examples/openthread/pytest_otbr.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 # !/usr/bin/env python3 import copy @@ -447,7 +447,10 @@ def test_service_discovery_of_WiFi_device(Init_interface:bool, Init_avahi:bool, command = 'dns browse _testxxx._udp.default.service.arpa' tmp = ocf.get_ouput_string(cli, command, 5) assert 'Port:12347' not in str(tmp) - ocf.host_publish_service() + ocf.restart_avahi() + command = 'avahi-publish-service testxxx _testxxx._udp 12347 test=1235 dn="for_ci_br_test"' + sp = subprocess.Popen(command, shell=True) + time.sleep(2) ocf.wait(cli, 5) command = 'dns browse _testxxx._udp.default.service.arpa' @@ -455,14 +458,13 @@ def test_service_discovery_of_WiFi_device(Init_interface:bool, Init_avahi:bool, assert 'response for _testxxx' in str(tmp) assert 'Port:12347' in str(tmp) - command = 'dns browse _testxxx._udp.default.service.arpa' + command = 'dns service testxxx _testxxx._udp.default.service.arpa.' tmp = ocf.get_ouput_string(cli, command, 5) - ocf.execute_command(cli, 'dns service testxxx _testxxx._udp.default.service.arpa.') - tmp = cli.expect(pexpect.TIMEOUT, timeout=5) assert 'response for testxxx' in str(tmp) assert 'Port:12347' in str(tmp) finally: ocf.host_close_service() + sp.terminate() ocf.execute_command(br, 'factoryreset') ocf.execute_command(cli, 'factoryreset') time.sleep(3) diff --git a/examples/peripherals/bitscrambler/CMakeLists.txt b/examples/peripherals/bitscrambler/CMakeLists.txt index 62c7ef22721f..8e78254acef8 100644 --- a/examples/peripherals/bitscrambler/CMakeLists.txt +++ b/examples/peripherals/bitscrambler/CMakeLists.txt @@ -5,4 +5,8 @@ cmake_minimum_required(VERSION 3.16) 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(bitscrambler_example) diff --git a/examples/peripherals/bitscrambler/README.md b/examples/peripherals/bitscrambler/README.md index 2b1363121f2b..6a5f00a00d22 100644 --- a/examples/peripherals/bitscrambler/README.md +++ b/examples/peripherals/bitscrambler/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-P4 | -| ----------------- | -------- | +| Supported Targets | ESP32-C5 | ESP32-P4 | +| ----------------- | -------- | -------- | # BitScrambler Loopback Example @@ -23,6 +23,15 @@ See the Getting Started Guide for full steps to configure and use ESP-IDF to bui ## Example Output +```text +I (305) bs_example: BitScrambler example main +BitScrambler program complete. Input 40, output 40 bytes: +FF 00 00 00 00 00 00 00 +80 80 80 80 80 80 80 80 +01 02 04 08 10 20 40 80 +00 FF 00 FF 00 FF 00 FF +FF 00 FF 00 FF 00 FF 00 +``` ## Troubleshooting diff --git a/examples/peripherals/bitscrambler/main/CMakeLists.txt b/examples/peripherals/bitscrambler/main/CMakeLists.txt index e59e3e6b3f2d..e78d9ab257dd 100644 --- a/examples/peripherals/bitscrambler/main/CMakeLists.txt +++ b/examples/peripherals/bitscrambler/main/CMakeLists.txt @@ -1,6 +1,5 @@ - idf_component_register(SRCS "bitscrambler_example_main.c" - PRIV_REQUIRES "esp_driver_bitscrambler" - INCLUDE_DIRS ".") + PRIV_REQUIRES "esp_driver_bitscrambler" + INCLUDE_DIRS ".") target_bitscrambler_add_src("example.bsasm") diff --git a/examples/peripherals/bitscrambler/main/bitscrambler_example_main.c b/examples/peripherals/bitscrambler/main/bitscrambler_example_main.c index 3b4970ecb22d..26457f929aaf 100644 --- a/examples/peripherals/bitscrambler/main/bitscrambler_example_main.c +++ b/examples/peripherals/bitscrambler/main/bitscrambler_example_main.c @@ -1,22 +1,17 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: CC0-1.0 */ #include #include -#include -#include -#include -#include "esp_err.h" -#include "esp_log.h" -#include "esp_check.h" -#include -#include "driver/bitscrambler_loopback.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" +#include "esp_err.h" +#include "esp_log.h" #include "esp_heap_caps.h" +#include "driver/bitscrambler_loopback.h" //Assign a symbol to the example bitscrambler program. Note that the actual //assembly and including in the binary happens in the CMakeLists.txt file. diff --git a/examples/peripherals/bitscrambler/main/example.bsasm b/examples/peripherals/bitscrambler/main/example.bsasm index 329ce6fb21b6..1c718f4d2002 100644 --- a/examples/peripherals/bitscrambler/main/example.bsasm +++ b/examples/peripherals/bitscrambler/main/example.bsasm @@ -1,10 +1,13 @@ +# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Unlicense OR CC0-1.0 + # Example bitscrambler program. Reads in 8 bytes and spits out 8 bytes are # the 'rotated' version of the input bytes. Specifically, output byte 0 # consists of bit 0 of input byte 0, bit 0 of input byte 1, bit 0 of input # byte 2 etc. Output byte 1 consists of bit 1 of input byte 0, bit 1 of # input byte 1, bit 1 of input byte 2, etc. -cfg trailing_bytes 64 #If we have an EOF on the input, we still +cfg trailing_bytes 8 #If we have an EOF on the input, we still #need to process the 64 bits in M0/M1 cfg prefetch true #We expect M0/M1 to be filled cfg lut_width_bits 8 #Not really applicable here diff --git a/examples/peripherals/bitscrambler/pytest_bitscrambler_loopback_example.py b/examples/peripherals/bitscrambler/pytest_bitscrambler_loopback_example.py new file mode 100644 index 000000000000..df9bbf7617ff --- /dev/null +++ b/examples/peripherals/bitscrambler/pytest_bitscrambler_loopback_example.py @@ -0,0 +1,22 @@ +# SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: CC0-1.0 +import pytest +from pytest_embedded import Dut + + +@pytest.mark.esp32p4 +@pytest.mark.esp32c5 +@pytest.mark.generic +def test_bitscrambler_loopback_example(dut: Dut) -> None: + dut.expect_exact('BitScrambler example main', timeout=5) + dut.expect_exact('BitScrambler program complete. Input 40, output 40 bytes') + + expected_lines = [ + 'FF 00 00 00 00 00 00 00', + '80 80 80 80 80 80 80 80', + '01 02 04 08 10 20 40 80', + '00 FF 00 FF 00 FF 00 FF', + 'FF 00 FF 00 FF 00 FF 00', + ] + for line in expected_lines: + dut.expect_exact(line) diff --git a/examples/peripherals/usb/README.md b/examples/peripherals/usb/README.md index c25ec63e52a6..b7bbe883601c 100644 --- a/examples/peripherals/usb/README.md +++ b/examples/peripherals/usb/README.md @@ -8,19 +8,21 @@ Pin assignment is only needed for ESP chips that have a USB-OTG peripheral. If your board doesn't have a USB connector connected to the USB-OTG dedicated GPIOs, you may have to DIY a cable and connect **D+** and **D-** to the pins listed below. ``` -ESP BOARD USB CONNECTOR (type A) - -- - | || VCC -[USBPHY_DM_NUM] ------> | || D- -[USBPHY_DP_NUM] ------> | || D+ - | || GND - -- +ESP BOARD USB CONNECTOR (type A) + -- + | || VBUS (5V) +[USB_DM] ------> | || D- +[USB_DP] ------> | || D+ + | || GND + -- ``` -Refer to `soc/usb_pins.h` to find the real GPIO number of **USBPHY_DP_NUM** and **USBPHY_DM_NUM**. -| | USB_DP | USB_DM | -| ----------- | ------ | ------ | -| ESP32-S2/S3 | GPIO20 | GPIO19 | -| ESP32-P4 | pin 51 | pin 50 | +### USB PHY pin mapping + +| | USB_DP | USB_DM | +| ------------ | ------ | ------ | +| ESP32-S2/S3 | GPIO20 | GPIO19 | +| ESP32-P4 2.0 | pin 51 | pin 50 | +| ESP32-P4 1.1 | GPIO27 | GPIO26 | > 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. diff --git a/examples/protocols/.build-test-rules.yml b/examples/protocols/.build-test-rules.yml index 996d90d6a0b8..813f74fe041c 100644 --- a/examples/protocols/.build-test-rules.yml +++ b/examples/protocols/.build-test-rules.yml @@ -107,8 +107,8 @@ examples/protocols/https_request: temporary: true reason: not supported on h2 disable_test: - - if: IDF_TARGET != "esp32" - reason: only test on esp32 + - if: IDF_TARGET not in ["esp32", "esp32c2"] + reason: only test on these target examples/protocols/https_server/simple: <<: *default_dependencies diff --git a/examples/protocols/https_request/pytest_https_request.py b/examples/protocols/https_request/pytest_https_request.py index 340945937ec9..e24bff59fd57 100644 --- a/examples/protocols/https_request/pytest_https_request.py +++ b/examples/protocols/https_request/pytest_https_request.py @@ -10,6 +10,7 @@ import pexpect import pytest +from common_test_methods import get_env_config_variable from common_test_methods import get_host_ip4_by_dest_ip from pytest_embedded import Dut from RangeHTTPServer import RangeRequestHandler @@ -236,3 +237,95 @@ def test_examples_protocol_https_request(dut: Dut) -> None: logging.info("Failed the test for \"https_request using server unsupported ciphersuites\"") raise logging.info("Passed the test for \"https_request using server unsupported ciphersuites\"") + + +@pytest.mark.esp32c2 +@pytest.mark.wifi_ap +@pytest.mark.xtal_26mhz +@pytest.mark.parametrize( + 'config, baud', [ + ('esp32c2_rom_mbedtls', '74880'), + ], indirect=True +) +def test_examples_protocol_https_request_rom_impl(dut: Dut) -> None: + # Connect to AP + if dut.app.sdkconfig.get('EXAMPLE_WIFI_SSID_PWD_FROM_STDIN') is True: + dut.expect('Please input ssid password:') + env_name = 'wifi_ap' + ap_ssid = get_env_config_variable(env_name, 'ap_ssid') + ap_password = get_env_config_variable(env_name, 'ap_password') + dut.write(f'{ap_ssid} {ap_password}') + # check and log bin size + binary_file = os.path.join(dut.app.binary_path, 'https_request.bin') + bin_size = os.path.getsize(binary_file) + logging.info('https_request_bin_size : {}KB'.format(bin_size // 1024)) + logging.info('Starting https_request simple test app') + + try: + ip_address = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=60)[1].decode() + print('Connected to AP/Ethernet with IP: {}'.format(ip_address)) + except pexpect.exceptions.TIMEOUT: + raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP/Ethernet') + + # Check for connection using crt bundle + logging.info("Testing for \"https_request using crt bundle\"") + try: + dut.expect('https_request using crt bundle', timeout=30) + dut.expect(['Certificate validated', + 'Connection established...', + 'Reading HTTP response...', + 'HTTP/1.1 200 OK', + 'connection closed'], expect_all=True) + except Exception: + logging.info("Failed the test for \"https_request using crt bundle\"") + raise + logging.info("Passed the test for \"https_request using crt bundle\"") + + # Check for connection using cacert_buf + logging.info("Testing for \"https_request using cacert_buf\"") + try: + dut.expect('https_request using cacert_buf', timeout=20) + dut.expect(['Connection established...', + 'Reading HTTP response...', + 'HTTP/1.1 200 OK', + 'connection closed'], expect_all=True) + except Exception: + logging.info("Passed the test for \"https_request using cacert_buf\"") + raise + logging.info("Passed the test for \"https_request using cacert_buf\"") + + # Check for connection using global ca_store + logging.info("Testing for \"https_request using global ca_store\"") + try: + dut.expect('https_request using global ca_store', timeout=20) + dut.expect(['Connection established...', + 'Reading HTTP response...', + 'HTTP/1.1 200 OK', + 'connection closed'], expect_all=True) + except Exception: + logging.info("Failed the test for \"https_request using global ca_store\"") + raise + logging.info("Passed the test for \"https_request using global ca_store\"") + + # Check for connection using specified server supported ciphersuites + logging.info("Testing for \"https_request using server supported ciphersuites\"") + try: + dut.expect('https_request using server supported ciphersuites', timeout=20) + dut.expect(['Connection established...', + 'Reading HTTP response...', + 'HTTP/1.1 200 OK', + 'connection closed'], expect_all=True) + except Exception: + logging.info("Failed the test for \"https_request using server supported ciphersuites\"") + raise + logging.info("Passed the test for \"https_request using server supported ciphersuites\"") + + # Check for connection using specified server unsupported ciphersuites + logging.info("Testing for \"https_request using server unsupported ciphersuites\"") + try: + dut.expect('https_request using server unsupported ciphersuites', timeout=20) + dut.expect('Connection failed...', timeout=30) + except Exception: + logging.info("Failed the test for \"https_request using server unsupported ciphersuites\"") + raise + logging.info("Passed the test for \"https_request using server unsupported ciphersuites\"") diff --git a/examples/protocols/https_request/sdkconfig.ci.esp32c2_rom_mbedtls b/examples/protocols/https_request/sdkconfig.ci.esp32c2_rom_mbedtls new file mode 100644 index 000000000000..40d3055d5fe1 --- /dev/null +++ b/examples/protocols/https_request/sdkconfig.ci.esp32c2_rom_mbedtls @@ -0,0 +1,5 @@ +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y +CONFIG_EXAMPLE_CONNECT_WIFI=y +CONFIG_EXAMPLE_WIFI_SSID_PWD_FROM_STDIN=y +CONFIG_MBEDTLS_USE_CRYPTO_ROM_IMPL=y diff --git a/examples/protocols/icmp_echo/main/echo_example_main.c b/examples/protocols/icmp_echo/main/echo_example_main.c index 67f68093d250..4e54bde86459 100644 --- a/examples/protocols/icmp_echo/main/echo_example_main.c +++ b/examples/protocols/icmp_echo/main/echo_example_main.c @@ -19,6 +19,9 @@ #include "argtable3/argtable3.h" #include "protocol_examples_common.h" #include "ping/ping_sock.h" +#include "esp_check.h" + +const static char *TAG = "echo_example"; static void cmd_ping_on_ping_success(esp_ping_handle_t hdl, void *args) { @@ -170,9 +173,8 @@ static int do_ping_cmd(int argc, char **argv) .on_ping_end = cmd_ping_on_ping_end }; esp_ping_handle_t ping; - esp_ping_new_session(&config, &cbs, &ping); - esp_ping_start(ping); - + ESP_RETURN_ON_FALSE(esp_ping_new_session(&config, &cbs, &ping) == ESP_OK, -1, TAG, "esp_ping_new_session failed"); + ESP_RETURN_ON_FALSE(esp_ping_start(ping) == ESP_OK, -1, TAG, "esp_ping_start() failed"); return 0; } diff --git a/examples/wifi/getting_started/station/pytest_wifi_station.py b/examples/wifi/getting_started/station/pytest_wifi_station.py new file mode 100644 index 000000000000..b63ba1235517 --- /dev/null +++ b/examples/wifi/getting_started/station/pytest_wifi_station.py @@ -0,0 +1,49 @@ +# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Unlicense OR CC0-1.0 +import os +from typing import Callable +from typing import Tuple + +import pytest +from pytest_embedded import Dut + +# diff of esp32s2/esp32s3 ~45K, others ~50K +DIFF_THRESHOLD = { + 'esp32s2': 40 * 1000, + 'esp32s3': 40 * 1000, + 'default': 45 * 1000, +} + + +@pytest.mark.esp32 +@pytest.mark.esp32c2 +@pytest.mark.esp32c3 +@pytest.mark.esp32s2 +@pytest.mark.esp32s3 +@pytest.mark.esp32c5 +@pytest.mark.esp32c6 +@pytest.mark.esp32c61 +@pytest.mark.wifi_two_dut +@pytest.mark.parametrize( + 'count, config, skip_autoflash', [ + (2, 'default|enable_softap', 'y') + ], indirect=True +) +def test_wifi_sdkconfig_disable_softap_save_binary_size( + dut: Tuple[Dut, Dut], + log_performance: Callable[[str, object], None], +) -> None: + # dut logs are not needed + dut[0].serial.close() + dut[1].serial.close() + + app_without_softap = dut[0].app + app_with_softap = dut[1].app + assert app_without_softap.sdkconfig['ESP_WIFI_SOFTAP_SUPPORT'] is False + assert app_with_softap.sdkconfig['ESP_WIFI_SOFTAP_SUPPORT'] is True + + diff = os.path.getsize(app_with_softap.bin_file) - os.path.getsize(app_without_softap.bin_file) + log_performance('wifi_disable_softap_save_bin_size', f'{diff} bytes') + + diff_threshold = DIFF_THRESHOLD.get(dut[0].target) or DIFF_THRESHOLD['default'] + assert diff > diff_threshold diff --git a/examples/wifi/getting_started/station/sdkconfig.ci.enable_softap b/examples/wifi/getting_started/station/sdkconfig.ci.enable_softap new file mode 100644 index 000000000000..cf2d4f2434e3 --- /dev/null +++ b/examples/wifi/getting_started/station/sdkconfig.ci.enable_softap @@ -0,0 +1 @@ +CONFIG_ESP_WIFI_SOFTAP_SUPPORT=y diff --git a/examples/wifi/wifi_aware/nan_console/main/nan_main.c b/examples/wifi/wifi_aware/nan_console/main/nan_main.c index a2734340ce28..c0a6de4eca46 100644 --- a/examples/wifi/wifi_aware/nan_console/main/nan_main.c +++ b/examples/wifi/wifi_aware/nan_console/main/nan_main.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -235,10 +235,14 @@ static int wifi_cmd_nan_disc(int argc, char **argv) nan_cfg.warm_up_sec = nan_args.warmup_time->ival[0]; } - g_nan_netif = esp_netif_create_default_wifi_nan(); + if (!g_nan_netif) { + g_nan_netif = esp_netif_create_default_wifi_nan(); + } + if ((esp_wifi_nan_start(&nan_cfg)) != ESP_OK) { ESP_LOGI(TAG, "Failed to start NAN"); esp_netif_destroy_default_wifi(g_nan_netif); + g_nan_netif = NULL; return 1; } return 0; @@ -252,6 +256,7 @@ static int wifi_cmd_nan_disc(int argc, char **argv) return 1; } esp_netif_destroy_default_wifi(g_nan_netif); + g_nan_netif = NULL; } return 0; @@ -443,7 +448,7 @@ void register_nan(void) nan_args.init = arg_lit0("S", "start", "NAN Start"); nan_args.deinit = arg_lit0("T", "stop", "NAN Stop"); nan_args.master_pref = arg_int0("p", "mast_pref", "<1-254>", "NAN Master Preference"); - nan_args.op_channel = arg_int0("c", "op_chan", "<1-11>", "NAN Operating Channe"); + nan_args.op_channel = arg_int0("c", "op_chan", "<1-11>", "NAN Operating Channel"); nan_args.warmup_time = arg_int0("w", "warmup", "<5-120>", "NAN Warmup Time in Sec"); nan_args.end = arg_end(1); diff --git a/tools/ci/check_register_rw_half_word.py b/tools/ci/check_register_rw_half_word.py index 3a5aa569dd52..05c31c9e6c26 100644 --- a/tools/ci/check_register_rw_half_word.py +++ b/tools/ci/check_register_rw_half_word.py @@ -50,7 +50,7 @@ def main( for capture in captures: error_usages = [f'.{capture}', f'->{capture}'] for error_usage in error_usages: - word_bound_pattern = rf'{re.escape(error_usage)}\b' + word_bound_pattern = rf'{re.escape(error_usage)}\s*[;|=](.*)\b' # print the line number where the error_usage is found for match in re.finditer(word_bound_pattern, content, re.MULTILINE): no_violation_found = False diff --git a/tools/ci/check_soc_struct_headers.py b/tools/ci/check_soc_struct_headers.py index f121296f5000..efdcfe86c2b2 100755 --- a/tools/ci/check_soc_struct_headers.py +++ b/tools/ci/check_soc_struct_headers.py @@ -1,12 +1,11 @@ #!/usr/bin/env python -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 - # A check script that just works at the time of writing... # # also builds a structure tree for further reference # -# Input file format must be similiar to those headers generated by regtool, or this script makes no sense at all +# Input file format must be similar to those headers generated by regtool, or this script makes no sense at all # # Known limitation: # 1. won't accept /* ... */ /* ... */': badly behavior with multiline comment @@ -21,18 +20,18 @@ # 5. typedef volatile struct xxx{}: xxx must exists # # Otherwise won't fail but warning - import os import re import sys from typing import Any +from typing import Optional class MemberField: member_type = '' bitfield = None - def __init__(self, m_type: str, m_bits: int=None) -> None: + def __init__(self, m_type: str, m_bits: Optional[int]=None) -> None: self.member_type = m_type self.bitfield = m_bits @@ -74,7 +73,7 @@ class SoCStructureHeaderChecker: # named typedef, or named struct/union. referd but will not delete __temp_ref_types = dict() # type: dict - def __expand_type(self, member_type: str, bitfield: int=None) -> Any: + def __expand_type(self, member_type: str, bitfield: Optional[int]=None) -> Any: if member_type == 'uint32_t': return MemberField(member_type, bitfield) if bitfield is not None: @@ -121,7 +120,7 @@ def __getline(self, incomment:bool=False) -> Any: # skip empty line return self.__getline() if rawline.count(';') > 1: - print('\033[0;34mINFO\033[0m: line: {}: possibily multiple expression within same line'.format(self.__linecount)) + print('\033[0;34mINFO\033[0m: line: {}: possibly multiple expression within same line'.format(self.__linecount)) print(rawline) return rawline @@ -129,7 +128,7 @@ def __process_structure(self, name: str, is_typedef: bool, is_volatile: bool) -> ret_val = 0 # first check for anonymous register structs if is_typedef and is_volatile and name is None: - print('\033[0;31mERROR\033[0m: line {}: annoymous struct'.format(self.__linecount)) + print('\033[0;31mERROR\033[0m: line {}: anonymous struct'.format(self.__linecount)) ret_val = -1 node_tree = dict() bitcount = 0 @@ -252,7 +251,7 @@ def __process_union(self, name: str, is_typedef: bool, is_volatile: bool) -> Any ret_val = 0 # first check for anonymous register structs if is_typedef and is_volatile and name is None: - print('\033[0;31mERROR\033[0m: line {}: annoymous union'.format(self.__linecount)) + print('\033[0;31mERROR\033[0m: line {}: anonymous union'.format(self.__linecount)) ret_val = -1 node_tree = dict() # type: Any has_struct_count = 0 @@ -334,7 +333,7 @@ def __process_union(self, name: str, is_typedef: bool, is_volatile: bool) -> Any node_tree[match_obj.groups()[1]] = member_node else: if '*' not in match_obj.groups()[0]: - print('\033[0;31mERROR\033[0m: line {}: unknown type {}'.format(self.__linecount, match_obj.groups()[0])) + print('\033[0;31mWARN\033[0m: line {}: unknown type {}'.format(self.__linecount, match_obj.groups()[0])) else: print('\033[0;33mWARN\033[0m: line {}: pointer type {}'.format(self.__linecount, match_obj.groups()[0])) continue diff --git a/tools/ci/dynamic_pipelines/constants.py b/tools/ci/dynamic_pipelines/constants.py index d724cbfe15af..23efe9e6255c 100644 --- a/tools/ci/dynamic_pipelines/constants.py +++ b/tools/ci/dynamic_pipelines/constants.py @@ -34,6 +34,9 @@ REPORT_TEMPLATE_FILEPATH = os.path.join( IDF_PATH, 'tools', 'ci', 'dynamic_pipelines', 'templates', 'report.template.html' ) +TOP_N_APPS_BY_SIZE_DIFF = 10 +SIZE_DIFFERENCE_BYTES_THRESHOLD = 500 +BINARY_SIZE_METRIC_NAME = 'binary_size' RETRY_JOB_PICTURE_PATH = 'tools/ci/dynamic_pipelines/templates/retry-jobs.png' RETRY_JOB_TITLE = '\n\nRetry failed jobs with with help of "retry_failed_jobs" stage of the pipeline:' diff --git a/tools/ci/dynamic_pipelines/report.py b/tools/ci/dynamic_pipelines/report.py index e7d1e29d26f9..6d86a9b58ac5 100644 --- a/tools/ci/dynamic_pipelines/report.py +++ b/tools/ci/dynamic_pipelines/report.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import abc import copy @@ -9,21 +9,24 @@ import typing as t from textwrap import dedent -import yaml from artifacts_handler import ArtifactType from gitlab import GitlabUpdateError from gitlab_api import Gitlab from idf_build_apps import App from idf_build_apps.constants import BuildStatus +from idf_ci.app import AppWithMetricsInfo from idf_ci.uploader import AppUploader from prettytable import PrettyTable +from .constants import BINARY_SIZE_METRIC_NAME from .constants import COMMENT_START_MARKER from .constants import REPORT_TEMPLATE_FILEPATH from .constants import RETRY_JOB_PICTURE_LINK from .constants import RETRY_JOB_PICTURE_PATH from .constants import RETRY_JOB_TITLE +from .constants import SIZE_DIFFERENCE_BYTES_THRESHOLD from .constants import TEST_RELATED_APPS_DOWNLOAD_URLS_FILENAME +from .constants import TOP_N_APPS_BY_SIZE_DIFF from .models import GitlabJob from .models import TestCase from .utils import fetch_failed_testcases_failure_ratio @@ -59,7 +62,8 @@ def get_download_link_for_url(url: str) -> str: return '' - def write_report_to_file(self, report_str: str, job_id: int, output_filepath: str) -> t.Optional[str]: + @staticmethod + def write_report_to_file(report_str: str, job_id: int, output_filepath: str) -> t.Optional[str]: """ Writes the report to a file and constructs a modified URL based on environment settings. @@ -203,51 +207,44 @@ def _filter_items( @staticmethod def _sort_items( - items: t.List[t.Union[TestCase, GitlabJob]], - key: t.Union[str, t.Callable[[t.Union[TestCase, GitlabJob]], t.Any]], + items: t.List[t.Union[TestCase, GitlabJob, AppWithMetricsInfo]], + key: t.Union[str, t.Callable[[t.Union[TestCase, GitlabJob, AppWithMetricsInfo]], t.Any]], order: str = 'asc', - ) -> t.List[t.Union[TestCase, GitlabJob]]: + sort_function: t.Optional[t.Callable[[t.Any], t.Any]] = None + ) -> t.List[t.Union[TestCase, GitlabJob, AppWithMetricsInfo]]: """ - Sort items based on a given key and order. + Sort items based on a given key, order, and optional custom sorting function. :param items: List of items to sort. :param key: A string representing the attribute name or a function to extract the sorting key. :param order: Order of sorting ('asc' for ascending, 'desc' for descending). + :param sort_function: A custom function to control sorting logic (e.g., prioritizing positive/negative/zero values). :return: List of sorted instances. """ key_func = None if isinstance(key, str): - def key_func(item: t.Any) -> t.Any: return getattr(item, key) - if key_func is not None: - try: - items = sorted(items, key=key_func, reverse=(order == 'desc')) - except TypeError: - print(f'Comparison for the key {key} is not supported') + sorting_key = sort_function if sort_function is not None else key_func + try: + items = sorted(items, key=sorting_key, reverse=(order == 'desc')) + except TypeError: + print(f'Comparison for the key {key} is not supported') + return items @abc.abstractmethod def _get_report_str(self) -> str: raise NotImplementedError - def _generate_comment(self, print_report_path: bool) -> str: + def _generate_comment(self) -> str: # Report in HTML format to avoid exceeding length limits comment = f'#### {self.title}\n' report_str = self._get_report_str() + comment += f'{self.additional_info}\n' + self.write_report_to_file(report_str, self.job_id, self.output_filepath) - if self.additional_info: - comment += f'{self.additional_info}\n' - - report_url_path = self.write_report_to_file(report_str, self.job_id, self.output_filepath) - if print_report_path and report_url_path: - comment += dedent( - f""" - Full {self.title} here: {report_url_path} (with commit {self.commit_id[:8]}) - - """ - ) return comment def _update_mr_comment(self, comment: str, print_retry_jobs_message: bool) -> None: @@ -285,8 +282,8 @@ def _get_updated_comment(self, existing_comment: str, new_comment: str) -> str: updated_str = f'{existing_comment.strip()}\n\n{new_comment}' return updated_str - def post_report(self, print_report_path: bool = True, print_retry_jobs_message: bool = False) -> None: - comment = self._generate_comment(print_report_path) + def post_report(self, print_retry_jobs_message: bool = False) -> None: + comment = self._generate_comment() print(comment) @@ -311,123 +308,358 @@ def __init__( ): super().__init__(project_id, mr_iid, pipeline_id, job_id, commit_id, title=title) self.apps = apps - + self._uploader = AppUploader(self.pipeline_id) self.apps_presigned_url_filepath = TEST_RELATED_APPS_DOWNLOAD_URLS_FILENAME + self.report_titles_map = { + 'failed_apps': 'Failed Apps', + 'built_test_related_apps': 'Built Apps - Test Related', + 'built_non_test_related_apps': 'Built Apps - Non Test Related', + 'new_test_related_apps': 'New Apps - Test Related', + 'new_non_test_related_apps': 'New Apps - Non Test Related', + 'skipped_apps': 'Skipped Apps', + } + self.failed_apps_report_file = 'failed_apps.html' + self.built_apps_report_file = 'built_apps.html' + self.skipped_apps_report_file = 'skipped_apps.html' - def _get_report_str(self) -> str: - if not self.apps: - print('No apps found, skip generating build report') - return 'No Apps Built' + @staticmethod + def custom_sort(item: AppWithMetricsInfo) -> t.Tuple[int, t.Any]: + """ + Custom sort function to: + 1. Push items with zero binary sizes to the end. + 2. Sort other items by absolute size_difference_percentage. + """ + # Priority: 0 for zero binaries, 1 for non-zero binaries + zero_binary_priority = 1 if item.metrics[BINARY_SIZE_METRIC_NAME].source_value != 0 or item.metrics[BINARY_SIZE_METRIC_NAME].target_value != 0 else 0 + # Secondary sort: Negative absolute size_difference_percentage for descending order + size_difference_sort = abs(item.metrics[BINARY_SIZE_METRIC_NAME].difference_percentage) + return zero_binary_priority, size_difference_sort - uploader = AppUploader(self.pipeline_id) + def _generate_top_n_apps_by_size_table(self) -> str: + """ + Generate a markdown table for the top N apps by size difference. + Only includes apps with size differences greater than 500 bytes. + """ + filtered_apps = [app for app in self.apps if abs(app.metrics[BINARY_SIZE_METRIC_NAME].difference) > SIZE_DIFFERENCE_BYTES_THRESHOLD] + + top_apps = sorted( + filtered_apps, + key=lambda app: abs(app.metrics[BINARY_SIZE_METRIC_NAME].difference_percentage), + reverse=True + )[:TOP_N_APPS_BY_SIZE_DIFF] + + if not top_apps: + return '' + + table = (f'\n⚠️⚠️⚠️ Top {len(top_apps)} Apps with Binary Size Sorted by Size Difference\n' + f'Note: Apps with changes of less than {SIZE_DIFFERENCE_BYTES_THRESHOLD} bytes are not shown.\n') + table += '| App Dir | Build Dir | Size Diff (bytes) | Size Diff (%) |\n' + table += '|---------|-----------|-------------------|---------------|\n' + for app in top_apps: + table += dedent( + f'| {app.app_dir} | {app.build_dir} | ' + f'{app.metrics[BINARY_SIZE_METRIC_NAME].difference} | ' + f'{app.metrics[BINARY_SIZE_METRIC_NAME].difference_percentage}% |\n' + ) + table += ('\n**For more details, please click on the numbers in the summary above ' + 'to view the corresponding report files.** ⬆️⬆️⬆️\n\n') - table_str = '' + return table - failed_apps = [app for app in self.apps if app.build_status == BuildStatus.FAILED] - if failed_apps: - table_str += '

Failed Apps

' - - failed_apps_table = PrettyTable() - failed_apps_table.field_names = [ - 'App Dir', - 'Build Dir', - 'Failed Reason', - 'Build Log', - ] - for app in failed_apps: - failed_apps_table.add_row( - [ - app.app_dir, - app.build_dir, - app.build_comment or '', - self.get_download_link_for_url(uploader.get_app_presigned_url(app, ArtifactType.LOGS)), - ] - ) + @staticmethod + def split_new_and_existing_apps(apps: t.Iterable[AppWithMetricsInfo]) -> t.Tuple[t.List[AppWithMetricsInfo], t.List[AppWithMetricsInfo]]: + """ + Splits apps into new apps and existing apps. + + :param apps: Iterable of apps to process. + :return: A tuple (new_apps, existing_apps). + """ + new_apps = [app for app in apps if app.is_new_app] + existing_apps = [app for app in apps if not app.is_new_app] + return new_apps, existing_apps + + def filter_apps_by_criteria(self, build_status: str, preserve: bool) -> t.List[AppWithMetricsInfo]: + """ + Filters apps based on build status and preserve criteria. + + :param build_status: Build status to filter by. + :param preserve: Whether to filter preserved apps. + :return: Filtered list of apps. + """ + return [ + app for app in self.apps + if app.build_status == build_status and app.preserve == preserve + ] + + def get_built_apps_report_parts(self) -> t.List[str]: + """ + Generates report parts for new and existing apps. - table_str += self.table_to_html_str(failed_apps_table) + :return: List of report parts. + """ + new_test_related_apps, built_test_related_apps = self.split_new_and_existing_apps( + self.filter_apps_by_criteria(BuildStatus.SUCCESS, True) + ) + + new_non_test_related_apps, built_non_test_related_apps = self.split_new_and_existing_apps( + self.filter_apps_by_criteria(BuildStatus.SUCCESS, False) + ) + + sections = [] + + if new_test_related_apps: + new_test_related_apps_table_section = self.create_table_section( + title=self.report_titles_map['new_test_related_apps'], + items=new_test_related_apps, + headers=[ + 'App Dir', + 'Build Dir', + 'Bin Files with Build Log (without map and elf)', + 'Map and Elf Files', + 'Your Branch App Size', + ], + row_attrs=[ + 'app_dir', + 'build_dir', + ], + value_functions=[ + ( + 'Your Branch App Size', + lambda app: str(app.metrics[BINARY_SIZE_METRIC_NAME].source_value) + ), + ( + 'Bin Files with Build Log (without map and elf)', + lambda app: self.get_download_link_for_url( + self._uploader.get_app_presigned_url(app, ArtifactType.BUILD_DIR_WITHOUT_MAP_AND_ELF_FILES) + ), + ), + ( + 'Map and Elf Files', + lambda app: self.get_download_link_for_url( + self._uploader.get_app_presigned_url(app, ArtifactType.MAP_AND_ELF_FILES) + ), + ), + ], + ) + sections.extend(new_test_related_apps_table_section) - built_test_related_apps = [app for app in self.apps if app.build_status == BuildStatus.SUCCESS and app.preserve] if built_test_related_apps: - table_str += '

Built Apps (Test Related)

' - - built_apps_table = PrettyTable() - built_apps_table.field_names = [ - 'App Dir', - 'Build Dir', - 'Bin Files with Build Log (without map and elf)', - 'Map and Elf Files', - ] - app_presigned_urls_dict: t.Dict[str, t.Dict[str, str]] = {} - for app in built_test_related_apps: - _d = { - ArtifactType.BUILD_DIR_WITHOUT_MAP_AND_ELF_FILES.value: uploader.get_app_presigned_url( - app, ArtifactType.BUILD_DIR_WITHOUT_MAP_AND_ELF_FILES + built_test_related_apps = self._sort_items( + built_test_related_apps, + key='metrics.binary_size.difference_percentage', + order='desc', + sort_function=self.custom_sort, + ) + + built_test_related_apps_table_section = self.create_table_section( + title=self.report_titles_map['built_test_related_apps'], + items=built_test_related_apps, + headers=[ + 'App Dir', + 'Build Dir', + 'Bin Files with Build Log (without map and elf)', + 'Map and Elf Files', + 'Your Branch App Size', + 'Target Branch App Size', + 'Size Diff', + 'Size Diff, %', + ], + row_attrs=[ + 'app_dir', + 'build_dir', + ], + value_functions=[ + ( + 'Your Branch App Size', + lambda app: str(app.metrics[BINARY_SIZE_METRIC_NAME].source_value) ), - ArtifactType.MAP_AND_ELF_FILES.value: uploader.get_app_presigned_url( - app, ArtifactType.MAP_AND_ELF_FILES + ( + 'Target Branch App Size', + lambda app: str(app.metrics[BINARY_SIZE_METRIC_NAME].target_value) ), - } - - built_apps_table.add_row( - [ - app.app_dir, - app.build_dir, - self.get_download_link_for_url(_d[ArtifactType.BUILD_DIR_WITHOUT_MAP_AND_ELF_FILES]), - self.get_download_link_for_url(_d[ArtifactType.MAP_AND_ELF_FILES]), - ] - ) + ( + 'Size Diff', + lambda app: str(app.metrics[BINARY_SIZE_METRIC_NAME].difference) + ), + ( + 'Size Diff, %', + lambda app: str(app.metrics[BINARY_SIZE_METRIC_NAME].difference_percentage) + ), + ( + 'Bin Files with Build Log (without map and elf)', + lambda app: self.get_download_link_for_url( + self._uploader.get_app_presigned_url(app, ArtifactType.BUILD_DIR_WITHOUT_MAP_AND_ELF_FILES) + ), + ), + ( + 'Map and Elf Files', + lambda app: self.get_download_link_for_url( + self._uploader.get_app_presigned_url(app, ArtifactType.MAP_AND_ELF_FILES) + ), + ), + ], + ) + sections.extend(built_test_related_apps_table_section) + + if new_non_test_related_apps: + new_non_test_related_apps_table_section = self.create_table_section( + title=self.report_titles_map['new_non_test_related_apps'], + items=new_non_test_related_apps, + headers=[ + 'App Dir', + 'Build Dir', + 'Build Log', + 'Your Branch App Size', + ], + row_attrs=[ + 'app_dir', + 'build_dir', + ], + value_functions=[ + ( + 'Your Branch App Size', + lambda app: str(app.metrics[BINARY_SIZE_METRIC_NAME].source_value) + ), + ('Build Log', lambda app: self.get_download_link_for_url( + self._uploader.get_app_presigned_url(app, ArtifactType.LOGS))), + ], + ) + sections.extend(new_non_test_related_apps_table_section) - app_presigned_urls_dict[app.build_path] = _d + if built_non_test_related_apps: + built_non_test_related_apps = self._sort_items( + built_non_test_related_apps, + key='metrics.binary_size.difference_percentage', + order='desc', + sort_function=self.custom_sort, + ) + built_non_test_related_apps_table_section = self.create_table_section( + title=self.report_titles_map['built_non_test_related_apps'], + items=built_non_test_related_apps, + headers=[ + 'App Dir', + 'Build Dir', + 'Build Log', + 'Your Branch App Size', + 'Target Branch App Size', + 'Size Diff', + 'Size Diff, %', + ], + row_attrs=[ + 'app_dir', + 'build_dir', + ], + value_functions=[ + ( + 'Your Branch App Size', + lambda app: str(app.metrics[BINARY_SIZE_METRIC_NAME].source_value) + ), + ( + 'Target Branch App Size', + lambda app: str(app.metrics[BINARY_SIZE_METRIC_NAME].target_value) + ), + ( + 'Size Diff', + lambda app: str(app.metrics[BINARY_SIZE_METRIC_NAME].difference) + ), + ( + 'Size Diff, %', + lambda app: str(app.metrics[BINARY_SIZE_METRIC_NAME].difference_percentage) + ), + ('Build Log', lambda app: self.get_download_link_for_url( + self._uploader.get_app_presigned_url(app, ArtifactType.LOGS))), + ], + ) + sections.extend(built_non_test_related_apps_table_section) - # also generate a yaml file that includes the apps and the presigned urls - # for helping debugging locally - with open(self.apps_presigned_url_filepath, 'w') as fw: - yaml.dump(app_presigned_urls_dict, fw) + built_apps_report_url = self.write_report_to_file( + self.generate_html_report(''.join(sections)), + self.job_id, + self.built_apps_report_file, + ) - table_str += self.table_to_html_str(built_apps_table) + self.additional_info += self.generate_additional_info_section( + self.report_titles_map['built_test_related_apps'], + len(built_test_related_apps), + built_apps_report_url, + ) + self.additional_info += self.generate_additional_info_section( + self.report_titles_map['built_non_test_related_apps'], + len(built_non_test_related_apps), + built_apps_report_url, + ) + self.additional_info += self.generate_additional_info_section( + self.report_titles_map['new_test_related_apps'], + len(new_test_related_apps), + built_apps_report_url, + ) + self.additional_info += self.generate_additional_info_section( + self.report_titles_map['new_non_test_related_apps'], + len(new_non_test_related_apps), + built_apps_report_url, + ) - built_non_test_related_apps = [ - app for app in self.apps if app.build_status == BuildStatus.SUCCESS and not app.preserve - ] - if built_non_test_related_apps: - table_str += '

Built Apps (Non Test Related)

' - - built_apps_table = PrettyTable() - built_apps_table.field_names = [ - 'App Dir', - 'Build Dir', - 'Build Log', - ] - for app in built_non_test_related_apps: - built_apps_table.add_row( - [ - app.app_dir, - app.build_dir, - self.get_download_link_for_url(uploader.get_app_presigned_url(app, ArtifactType.LOGS)), - ] - ) + self.additional_info += self._generate_top_n_apps_by_size_table() + + return sections - table_str += self.table_to_html_str(built_apps_table) + def get_failed_apps_report_parts(self) -> t.List[str]: + failed_apps = [app for app in self.apps if app.build_status == BuildStatus.FAILED] + if not failed_apps: + return [] + + failed_apps_table_section = self.create_table_section( + title=self.report_titles_map['failed_apps'], + items=failed_apps, + headers=['App Dir', 'Build Dir', 'Failed Reason', 'Build Log'], + row_attrs=['app_dir', 'build_dir', 'build_comment'], + value_functions=[ + ('Build Log', lambda app: self.get_download_link_for_url(self._uploader.get_app_presigned_url(app, ArtifactType.LOGS))), + ], + ) + failed_apps_report_url = self.write_report_to_file( + self.generate_html_report(''.join(failed_apps_table_section)), + self.job_id, + self.failed_apps_report_file, + ) + self.additional_info += self.generate_additional_info_section( + self.report_titles_map['failed_apps'], len(failed_apps), failed_apps_report_url + ) + return failed_apps_table_section + def get_skipped_apps_report_parts(self) -> t.List[str]: skipped_apps = [app for app in self.apps if app.build_status == BuildStatus.SKIPPED] - if skipped_apps: - table_str += '

Skipped Apps

' - - skipped_apps_table = PrettyTable() - skipped_apps_table.field_names = ['App Dir', 'Build Dir', 'Skipped Reason', 'Build Log'] - for app in skipped_apps: - skipped_apps_table.add_row( - [ - app.app_dir, - app.build_dir, - app.build_comment or '', - self.get_download_link_for_url(uploader.get_app_presigned_url(app, ArtifactType.LOGS)), - ] - ) + if not skipped_apps: + return [] - table_str += self.table_to_html_str(skipped_apps_table) + skipped_apps_table_section = self.create_table_section( + title=self.report_titles_map['skipped_apps'], + items=skipped_apps, + headers=['App Dir', 'Build Dir', 'Skipped Reason', 'Build Log'], + row_attrs=['app_dir', 'build_dir', 'build_comment'], + value_functions=[ + ('Build Log', lambda app: self.get_download_link_for_url(self._uploader.get_app_presigned_url(app, ArtifactType.LOGS))), + ], + ) + skipped_apps_report_url = self.write_report_to_file( + self.generate_html_report(''.join(skipped_apps_table_section)), + self.job_id, + self.skipped_apps_report_file, + ) + self.additional_info += self.generate_additional_info_section( + self.report_titles_map['skipped_apps'], len(skipped_apps), skipped_apps_report_url + ) + return skipped_apps_table_section + + def _get_report_str(self) -> str: + self.additional_info = f'**Build Summary (with commit {self.commit_id[:8]}):**\n' + failed_apps_report_parts = self.get_failed_apps_report_parts() + skipped_apps_report_parts = self.get_skipped_apps_report_parts() + built_apps_report_parts = self.get_built_apps_report_parts() - return self.generate_html_report(table_str) + return self.generate_html_report( + ''.join(failed_apps_report_parts + built_apps_report_parts + skipped_apps_report_parts) + ) class TargetTestReportGenerator(ReportGenerator): diff --git a/tools/ci/dynamic_pipelines/scripts/generate_report.py b/tools/ci/dynamic_pipelines/scripts/generate_report.py index 43e5ecab8a78..e3c4b9d34993 100644 --- a/tools/ci/dynamic_pipelines/scripts/generate_report.py +++ b/tools/ci/dynamic_pipelines/scripts/generate_report.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import argparse import glob @@ -9,8 +9,10 @@ from dynamic_pipelines.report import BuildReportGenerator from dynamic_pipelines.report import JobReportGenerator from dynamic_pipelines.report import TargetTestReportGenerator +from dynamic_pipelines.utils import fetch_app_metrics from dynamic_pipelines.utils import fetch_failed_jobs from dynamic_pipelines.utils import parse_testcases_from_filepattern +from idf_ci.app import enrich_apps_with_metrics_info from idf_ci.app import import_apps_from_txt @@ -73,6 +75,11 @@ def generate_build_report(args: argparse.Namespace) -> None: apps: t.List[t.Any] = [ app for file_name in glob.glob(args.app_list_filepattern) for app in import_apps_from_txt(file_name) ] + app_metrics = fetch_app_metrics( + source_commit_sha=os.environ.get('CI_COMMIT_SHA'), + target_commit_sha=os.environ.get('CI_MERGE_REQUEST_TARGET_BRANCH_SHA'), + ) + apps = enrich_apps_with_metrics_info(app_metrics, apps) report_generator = BuildReportGenerator( args.project_id, args.mr_iid, args.pipeline_id, args.job_id, args.commit_id, apps=apps ) @@ -84,7 +91,7 @@ def generate_target_test_report(args: argparse.Namespace) -> None: report_generator = TargetTestReportGenerator( args.project_id, args.mr_iid, args.pipeline_id, args.job_id, args.commit_id, test_cases=test_cases ) - report_generator.post_report(print_report_path=False) + report_generator.post_report() def generate_jobs_report(args: argparse.Namespace) -> None: @@ -93,8 +100,10 @@ def generate_jobs_report(args: argparse.Namespace) -> None: if not jobs: return - report_generator = JobReportGenerator(args.project_id, args.mr_iid, args.pipeline_id, args.job_id, args.commit_id, jobs=jobs) - report_generator.post_report(print_report_path=False, print_retry_jobs_message=any(job.is_failed for job in jobs)) + report_generator = JobReportGenerator( + args.project_id, args.mr_iid, args.pipeline_id, args.job_id, args.commit_id, jobs=jobs + ) + report_generator.post_report(print_retry_jobs_message=any(job.is_failed for job in jobs)) if __name__ == '__main__': diff --git a/tools/ci/dynamic_pipelines/templates/test_child_pipeline.yml b/tools/ci/dynamic_pipelines/templates/test_child_pipeline.yml index 08b25bc2d9b1..9b5c04318e6c 100644 --- a/tools/ci/dynamic_pipelines/templates/test_child_pipeline.yml +++ b/tools/ci/dynamic_pipelines/templates/test_child_pipeline.yml @@ -7,6 +7,9 @@ generate_pytest_build_report: when: always artifacts: paths: + - failed_apps.html + - built_apps.html + - skipped_apps.html - build_report.html - test_related_apps_download_urls.yml expire_in: 1 week diff --git a/tools/ci/dynamic_pipelines/tests/test_report_generator/reports_sample_data/apps b/tools/ci/dynamic_pipelines/tests/test_report_generator/reports_sample_data/apps new file mode 100644 index 000000000000..57d3df17c2a1 --- /dev/null +++ b/tools/ci/dynamic_pipelines/tests/test_report_generator/reports_sample_data/apps @@ -0,0 +1,9 @@ +{"build_system": "idf_cmake", "app_dir": "tools/test_apps/system/panic", "target": "esp32s3", "sdkconfig_path": "/builds/espressif/esp-idf/tools/test_apps/system/panic/sdkconfig.ci.coredump_flash_capture_dram", "config_name": "coredump_flash_capture_dram", "sdkconfig_defaults_str": null, "dry_run": false, "verbose": false, "check_warnings": true, "preserve": false, "copy_sdkconfig": false, "index": null, "build_status": "build failed", "build_comment": "Compilation error", "cmake_vars": {}, "work_dir": "tools/test_apps/system/panic", "build_dir": "build_esp32s3_coredump_flash_capture_dram", "build_log_filename": "build_log.txt", "size_json_filename": "size.json"} +{"build_system": "idf_cmake", "app_dir": "tools/test_apps/system/ram_loadable_app", "target": "esp32", "sdkconfig_path": "/builds/espressif/esp-idf/tools/test_apps/system/ram_loadable_app/sdkconfig.ci.defaults", "config_name": "defaults", "sdkconfig_defaults_str": null, "dry_run": false, "verbose": false, "check_warnings": true, "preserve": true, "copy_sdkconfig": false, "index": null, "build_status": "build success", "build_comment": null, "cmake_vars": {}, "work_dir": "tools/test_apps/system/ram_loadable_app", "build_dir": "build_esp32_defaults", "build_log_filename": "build_log.txt", "size_json_filename": "size.json"} +{"build_system": "idf_cmake", "app_dir": "tools/test_apps/system/ram_loadable_app", "target": "esp32", "sdkconfig_path": "/builds/espressif/esp-idf/tools/test_apps/system/ram_loadable_app/sdkconfig.ci.pure_ram", "config_name": "pure_ram", "sdkconfig_defaults_str": null, "dry_run": false, "verbose": false, "check_warnings": true, "preserve": true, "copy_sdkconfig": false, "index": null, "build_status": "build success", "build_comment": null, "cmake_vars": {}, "work_dir": "tools/test_apps/system/ram_loadable_app", "build_dir": "build_esp32_pure_ram", "build_log_filename": "build_log.txt", "size_json_filename": "size.json"} +{"build_system": "idf_cmake", "app_dir": "tools/test_apps/system/startup", "target": "esp32", "sdkconfig_path": "/builds/espressif/esp-idf/tools/test_apps/system/startup/sdkconfig.ci.flash_80m_qio", "config_name": "flash_80m_qio", "sdkconfig_defaults_str": null, "dry_run": false, "verbose": false, "check_warnings": true, "preserve": true, "copy_sdkconfig": false, "index": null, "build_status": "build success", "build_comment": null, "cmake_vars": {}, "work_dir": "tools/test_apps/system/startup", "build_dir": "build_esp32_flash_80m_qio", "build_log_filename": "build_log.txt", "size_json_filename": "size.json"} +{"build_system": "idf_cmake", "app_dir": "tools/test_apps/system/startup", "target": "esp32s3", "sdkconfig_path": "/builds/espressif/esp-idf/tools/test_apps/system/startup/sdkconfig.ci.stack_check_verbose_log", "config_name": "stack_check_verbose_log", "sdkconfig_defaults_str": null, "dry_run": false, "verbose": false, "check_warnings": true, "preserve": true, "copy_sdkconfig": false, "index": null, "build_status": "build success", "build_comment": null, "cmake_vars": {}, "work_dir": "tools/test_apps/system/startup", "build_dir": "build_esp32s3_stack_check_verbose_log", "build_log_filename": "build_log.txt", "size_json_filename": "size.json"} +{"build_system": "idf_cmake", "app_dir": "tools/test_apps/system/test_watchpoint", "target": "esp32", "sdkconfig_path": null, "config_name": "default", "sdkconfig_defaults_str": null, "dry_run": false, "verbose": false, "check_warnings": true, "preserve": false, "copy_sdkconfig": false, "index": null, "build_status": "skipped", "build_comment": "Skipped due to unmet dependencies", "cmake_vars": {}, "work_dir": "tools/test_apps/system/test_watchpoint", "build_dir": "build_esp32_default", "build_log_filename": "build_log.txt", "size_json_filename": "size.json"} +{"build_system": "idf_cmake", "app_dir": "tools/test_apps/system/test_watchpoint", "target": "esp32c3", "sdkconfig_path": null, "config_name": "default", "sdkconfig_defaults_str": null, "dry_run": false, "verbose": false, "check_warnings": true, "preserve": false, "copy_sdkconfig": false, "index": null, "build_status": "skipped", "build_comment": "Skipped due to unmet dependencies", "cmake_vars": {}, "work_dir": "tools/test_apps/system/test_watchpoint", "build_dir": "build_esp32c3_default", "build_log_filename": "build_log.txt", "size_json_filename": "size.json"} +{"build_system": "idf_cmake", "app_dir": "tools/test_apps/system/unicore_bootloader", "target": "esp32", "sdkconfig_path": "/builds/espressif/esp-idf/tools/test_apps/system/unicore_bootloader/sdkconfig.ci.multicore", "config_name": "multicore", "sdkconfig_defaults_str": null, "dry_run": false, "verbose": false, "check_warnings": true, "preserve": false, "copy_sdkconfig": false, "index": null, "build_status": "build failed", "build_comment": "Compilation error", "cmake_vars": {}, "work_dir": "tools/test_apps/system/unicore_bootloader", "build_dir": "build_esp32_multicore", "build_log_filename": "build_log.txt", "size_json_filename": "size.json"} +{"build_system": "idf_cmake", "app_dir": "tools/test_apps/system/unicore_bootloader", "target": "esp32s3", "sdkconfig_path": "/builds/espressif/esp-idf/tools/test_apps/system/unicore_bootloader/sdkconfig.ci.unicore_psram", "config_name": "unicore_psram", "sdkconfig_defaults_str": null, "dry_run": false, "verbose": false, "check_warnings": true, "preserve": true, "copy_sdkconfig": false, "index": null, "build_status": "build success", "build_comment": null, "cmake_vars": {}, "work_dir": "tools/test_apps/system/unicore_bootloader", "build_dir": "build_esp32s3_unicore_psram", "build_log_filename": "build_log.txt", "size_json_filename": "size.json"} diff --git a/tools/ci/dynamic_pipelines/tests/test_report_generator/reports_sample_data/apps_size_info_api_response.json b/tools/ci/dynamic_pipelines/tests/test_report_generator/reports_sample_data/apps_size_info_api_response.json new file mode 100644 index 000000000000..7e24ee8bd5df --- /dev/null +++ b/tools/ci/dynamic_pipelines/tests/test_report_generator/reports_sample_data/apps_size_info_api_response.json @@ -0,0 +1,146 @@ +{ + "tools/test_apps/system/panic_coredump_flash_capture_dram_esp32s3": { + "source_commit_id": "bacfa4aa59a37b70b800f1758106fa5f5af99f16", + "target_commit_id": "36d5d8c31c7d3332b43bd5fe4d40b515c6a71097", + "app_name": "panic", + "config_name": "coredump_flash_capture_dram", + "target": "esp32s3", + "metrics": { + "binary_size": { + "source_value": 156936, + "target_value": 162936, + "difference": 6000, + "difference_percentage": 3.82 + } + }, + "app_path": "tools/test_apps/system/panic_coredump" + }, + "tools/test_apps/system/ram_loadable_app_defaults_esp32": { + "source_commit_id": "bacfa4aa59a37b70b800f1758106fa5f5af99f16", + "target_commit_id": "36d5d8c31c7d3332b43bd5fe4d40b515c6a71097", + "app_name": "ram_loadable_app", + "config_name": "defaults", + "target": "esp32", + "metrics": { + "binary_size": { + "source_value": 171448, + "target_value": 173000, + "difference": 1552, + "difference_percentage": 0.91 + } + }, + "app_path": "tools/test_apps/system/ram_loadable_app" + }, + "tools/test_apps/system/ram_loadable_app_pure_ram_esp32": { + "source_commit_id": "bacfa4aa59a37b70b800f1758106fa5f5af99f16", + "target_commit_id": "36d5d8c31c7d3332b43bd5fe4d40b515c6a71097", + "app_name": "ram_loadable_app", + "config_name": "pure_ram", + "target": "esp32", + "metrics": { + "binary_size": { + "source_value": 156632, + "target_value": 158200, + "difference": 1568, + "difference_percentage": 1.0 + } + }, + "app_path": "tools/test_apps/system/ram_loadable_app" + }, + "tools/test_apps/system/startup_flash_80m_qio_esp32": { + "source_commit_id": "bacfa4aa59a37b70b800f1758106fa5f5af99f16", + "target_commit_id": "36d5d8c31c7d3332b43bd5fe4d40b515c6a71097", + "app_name": "startup", + "config_name": "flash_80m_qio", + "target": "esp32", + "metrics": { + "binary_size": { + "source_value": 225692, + "target_value": 230000, + "difference": 4308, + "difference_percentage": 1.91 + } + }, + "app_path": "tools/test_apps/system/startup" + }, + "tools/test_apps/system/startup_stack_check_verbose_log_esp32s3": { + "source_commit_id": "bacfa4aa59a37b70b800f1758106fa5f5af99f16", + "target_commit_id": "36d5d8c31c7d3332b43bd5fe4d40b515c6a71097", + "app_name": "startup", + "config_name": "stack_check_verbose_log", + "target": "esp32s3", + "metrics": { + "binary_size": { + "source_value": 156936, + "target_value": 160000, + "difference": 3064, + "difference_percentage": 1.95 + } + }, + "app_path": "tools/test_apps/system/startup" + }, + "tools/test_apps/system/test_watchpoint_default_esp32": { + "source_commit_id": "bacfa4aa59a37b70b800f1758106fa5f5af99f16", + "target_commit_id": "36d5d8c31c7d3332b43bd5fe4d40b515c6a71097", + "app_name": "test_watchpoint", + "config_name": "default", + "target": "esp32", + "metrics": { + "binary_size": { + "source_value": 147896, + "target_value": 150000, + "difference": 2104, + "difference_percentage": 1.42 + } + }, + "app_path": "tools/test_apps/system/test_watchpoint" + }, + "tools/test_apps/system/test_watchpoint_default_esp32c3": { + "source_commit_id": "bacfa4aa59a37b70b800f1758106fa5f5af99f16", + "target_commit_id": "36d5d8c31c7d3332b43bd5fe4d40b515c6a71097", + "app_name": "test_watchpoint", + "config_name": "default", + "target": "esp32c3", + "metrics": { + "binary_size": { + "source_value": 189456, + "target_value": 190456, + "difference": 1000, + "difference_percentage": 0.53 + } + }, + "app_path": "tools/test_apps/system/test_watchpoint" + }, + "tools/test_apps/system/unicore_bootloader_multicore_esp32": { + "source_commit_id": "bacfa4aa59a37b70b800f1758106fa5f5af99f16", + "target_commit_id": "36d5d8c31c7d3332b43bd5fe4d40b515c6a71097", + "app_name": "unicore_bootloader", + "config_name": "multicore", + "target": "esp32", + "metrics": { + "binary_size": { + "source_value": 216784, + "target_value": 220000, + "difference": 3216, + "difference_percentage": 1.48 + } + }, + "app_path": "tools/test_apps/system/unicore_bootloader" + }, + "tools/test_apps/system/unicore_bootloader_unicore_psram_esp32s3": { + "source_commit_id": "bacfa4aa59a37b70b800f1758106fa5f5af99f16", + "target_commit_id": "36d5d8c31c7d3332b43bd5fe4d40b515c6a71097", + "app_name": "unicore_bootloader", + "config_name": "unicore_psram", + "target": "esp32s3", + "metrics": { + "binary_size": { + "source_value": 189456, + "target_value": 191456, + "difference": 2000, + "difference_percentage": 1.06 + } + }, + "app_path": "tools/test_apps/system/unicore_bootloader" + } +} diff --git a/tools/ci/dynamic_pipelines/tests/test_report_generator/reports_sample_data/expected_build_report.html b/tools/ci/dynamic_pipelines/tests/test_report_generator/reports_sample_data/expected_build_report.html new file mode 100644 index 000000000000..bcece174302d --- /dev/null +++ b/tools/ci/dynamic_pipelines/tests/test_report_generator/reports_sample_data/expected_build_report.html @@ -0,0 +1,246 @@ + + + + + Build Report + + + + + + + +

Failed Apps

+ + + + + + + + + + + + + + + + + + + + + + +
App DirBuild DirFailed ReasonBuild Log
tools/test_apps/system/panicbuild_esp32s3_coredump_flash_capture_dramCompilation errorDownload
tools/test_apps/system/unicore_bootloaderbuild_esp32_multicoreCompilation errorDownload
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
App DirBuild DirBin Files with Build Log (without map and elf)Map and Elf FilesYour Branch App SizeTarget Branch App SizeSize DiffSize Diff, %
tools/test_apps/system/startupbuild_esp32s3_stack_check_verbose_logDownloadDownload15693616000030641.95
tools/test_apps/system/startupbuild_esp32_flash_80m_qioDownloadDownload22569223000043081.91
tools/test_apps/system/unicore_bootloaderbuild_esp32s3_unicore_psramDownloadDownload18945619145620001.06
tools/test_apps/system/ram_loadable_appbuild_esp32_pure_ramDownloadDownload15663215820015681.0
tools/test_apps/system/ram_loadable_appbuild_esp32_defaultsDownloadDownload17144817300015520.91

Skipped Apps

+ + + + + + + + + + + + + + + + + + + + + + +
App DirBuild DirSkipped ReasonBuild Log
tools/test_apps/system/test_watchpointbuild_esp32_defaultSkipped due to unmet dependenciesDownload
tools/test_apps/system/test_watchpointbuild_esp32c3_defaultSkipped due to unmet dependenciesDownload
+ + + + + + + + diff --git a/tools/ci/dynamic_pipelines/tests/test_report_generator/test_report_generator.py b/tools/ci/dynamic_pipelines/tests/test_report_generator/test_report_generator.py index 5ab856a8eec6..3a632df2fd28 100644 --- a/tools/ci/dynamic_pipelines/tests/test_report_generator/test_report_generator.py +++ b/tools/ci/dynamic_pipelines/tests/test_report_generator/test_report_generator.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import json import os.path @@ -12,8 +12,11 @@ sys.path.insert(0, os.path.join(f'{os.environ.get("IDF_PATH")}', 'tools', 'ci')) from dynamic_pipelines.models import GitlabJob # noqa: E402 -from dynamic_pipelines.report import JobReportGenerator, TargetTestReportGenerator # noqa: E402 +from dynamic_pipelines.report import JobReportGenerator, TargetTestReportGenerator, BuildReportGenerator # noqa: E402 from dynamic_pipelines.utils import load_file, parse_testcases_from_filepattern # noqa: E402 +from idf_build_apps.constants import BuildStatus # noqa: E402 +from idf_ci.app import import_apps_from_txt # noqa: E402 +from idf_ci.app import enrich_apps_with_metrics_info # noqa: E402 class TestReportGeneration(unittest.TestCase): @@ -27,6 +30,7 @@ def setUp(self) -> None: def setup_patches(self) -> None: self.gitlab_patcher = patch('dynamic_pipelines.report.Gitlab') + self.uploader_patcher = patch('dynamic_pipelines.report.AppUploader') self.failure_rate_patcher = patch('dynamic_pipelines.report.fetch_failed_testcases_failure_ratio') self.env_patcher = patch.dict('os.environ', { 'CI_DASHBOARD_HOST': 'https://test_dashboard_host', @@ -36,6 +40,7 @@ def setup_patches(self) -> None: }) self.MockGitlab = self.gitlab_patcher.start() + self.MockUploader = self.uploader_patcher.start() self.test_cases_failure_rate = self.failure_rate_patcher.start() self.env_patcher.start() @@ -43,8 +48,10 @@ def setup_patches(self) -> None: self.mock_mr = MagicMock() self.MockGitlab.return_value.project = self.mock_project self.mock_project.mergerequests.get.return_value = self.mock_mr + self.MockUploader.return_value.get_app_presigned_url.return_value = 'https://example.com/presigned-url' self.addCleanup(self.gitlab_patcher.stop) + self.addCleanup(self.uploader_patcher.stop) self.addCleanup(self.failure_rate_patcher.stop) self.addCleanup(self.env_patcher.stop) self.addCleanup(self.cleanup_files) @@ -54,6 +61,9 @@ def cleanup_files(self) -> None: self.target_test_report_generator.skipped_test_cases_report_file, self.target_test_report_generator.succeeded_cases_report_file, self.target_test_report_generator.failed_cases_report_file, + self.build_report_generator.failed_apps_report_file, + self.build_report_generator.built_apps_report_file, + self.build_report_generator.skipped_apps_report_file, ] for file_path in files_to_delete: if os.path.exists(file_path): @@ -66,13 +76,18 @@ def load_test_and_job_reports(self) -> None: self.expected_job_report_html = load_file( os.path.join(self.reports_sample_data_path, 'expected_job_report.html') ) + self.expected_build_report_html = load_file( + os.path.join(self.reports_sample_data_path, 'expected_build_report.html') + ) def create_report_generators(self) -> None: jobs_response_raw = load_file(os.path.join(self.reports_sample_data_path, 'jobs_api_response.json')) failure_rate_jobs_response = load_file(os.path.join(self.reports_sample_data_path, 'failure_rate_jobs_response.json')) + built_apps_size_info_response = json.loads(load_file(os.path.join(self.reports_sample_data_path, 'apps_size_info_api_response.json'))) failure_rates = {item['name']: item for item in json.loads(failure_rate_jobs_response).get('jobs', [])} jobs = [GitlabJob.from_json_data(job_json, failure_rates.get(job_json['name'], {})) for job_json in json.loads(jobs_response_raw)['jobs']] test_cases = parse_testcases_from_filepattern(os.path.join(self.reports_sample_data_path, 'XUNIT_*.xml')) + apps = enrich_apps_with_metrics_info(built_apps_size_info_response, import_apps_from_txt(os.path.join(self.reports_sample_data_path, 'apps'))) self.target_test_report_generator = TargetTestReportGenerator( project_id=123, mr_iid=1, @@ -91,6 +106,15 @@ def create_report_generators(self) -> None: title='Job Report', jobs=jobs ) + self.build_report_generator = BuildReportGenerator( + project_id=123, + mr_iid=1, + pipeline_id=456, + job_id=0, + commit_id='cccc', + title='Build Report', + apps=apps + ) self.target_test_report_generator._known_failure_cases_set = { '*.test_wpa_supplicant_ut', 'esp32c3.release.test_esp_timer', @@ -148,6 +172,179 @@ def test_job_report_html_structure(self) -> None: report = self.job_report_generator._get_report_str() self.assertEqual(report, self.expected_job_report_html) + def test_generate_top_n_apps_by_size_table(self) -> None: + apps_with_size_diff = [ + MagicMock( + app_dir=f'app_dir_{i}', + build_dir=f'build_dir_{i}', + build_status=BuildStatus.SUCCESS, + metrics={ + 'binary_size': MagicMock( + source=i * 10000, + target=i * 10000 + i * 1000, + difference=i * 1000, + difference_percentage=i * 0.5, + ) + } + ) + for i in range(1, 6) + ] + build_report_generator = BuildReportGenerator( + project_id=123, + mr_iid=1, + pipeline_id=456, + job_id=0, + commit_id='cccc', + title='Build Report', + apps=apps_with_size_diff + ) + + top_apps_table = build_report_generator._generate_top_n_apps_by_size_table() + + self.assertIn('| App Dir | Build Dir | Size Diff (bytes) | Size Diff (%) |', top_apps_table) + self.assertIn('| app_dir_5 | build_dir_5 | 5000 | 2.5% |', top_apps_table) + self.assertIn('| app_dir_1 | build_dir_1 | 1000 | 0.5% |', top_apps_table) + + def test_get_built_apps_report_parts(self) -> None: + apps = [ + MagicMock( + app_dir='test_app_1', + build_dir='build_dir_1', + size_difference=1000, + size_difference_percentage=1.0, + build_status=BuildStatus.SUCCESS, + preserve=True, + metrics={ + 'binary_size': MagicMock( + difference=1000, + difference_percentage=1.0 + ) + } + ), + MagicMock( + app_dir='test_app_2', + build_dir='build_dir_2', + size_difference=2000, + size_difference_percentage=2.0, + build_status=BuildStatus.SUCCESS, + preserve=False, + metrics={ + 'binary_size': MagicMock( + difference=2000, + difference_percentage=2.0 + ) + } + ), + ] + + build_report_generator = BuildReportGenerator( + project_id=123, + mr_iid=1, + pipeline_id=456, + job_id=0, + commit_id='cccc', + title='Build Report', + apps=apps + ) + + built_apps_report_parts = build_report_generator.get_built_apps_report_parts() + + self.assertGreater(len(built_apps_report_parts), 0) + self.assertIn('test_app_1', ''.join(built_apps_report_parts)) + self.assertIn('test_app_2', ''.join(built_apps_report_parts)) + + def test_get_failed_apps_report_parts(self) -> None: + failed_apps = [ + MagicMock( + app_dir='failed_app_1', + build_dir='build_dir_1', + build_comment='Compilation error', + build_status=BuildStatus.FAILED, + metrics={ + 'binary_size': MagicMock( + difference=None, + difference_percentage=None + ) + } + ), + MagicMock( + app_dir='failed_app_2', + build_dir='build_dir_2', + build_comment='Linker error', + build_status=BuildStatus.FAILED, + metrics={ + 'binary_size': MagicMock( + difference=None, + difference_percentage=None + ) + } + ), + ] + + build_report_generator = BuildReportGenerator( + project_id=123, + mr_iid=1, + pipeline_id=456, + job_id=0, + commit_id='cccc', + title='Build Report', + apps=failed_apps + ) + + failed_apps_report_parts = build_report_generator.get_failed_apps_report_parts() + + self.assertGreater(len(failed_apps_report_parts), 0) + self.assertIn('failed_app_1', ''.join(failed_apps_report_parts)) + self.assertIn('failed_app_2', ''.join(failed_apps_report_parts)) + + def test_get_skipped_apps_report_parts(self) -> None: + skipped_apps = [ + MagicMock( + app_dir='skipped_app_1', + build_dir='build_dir_1', + build_comment='Dependencies unmet', + build_status=BuildStatus.SKIPPED, + metrics={ + 'binary_size': MagicMock( + difference=None, + difference_percentage=None + ) + } + ), + MagicMock( + app_dir='skipped_app_2', + build_dir='build_dir_2', + build_comment='Feature flag disabled', + build_status=BuildStatus.SKIPPED, + metrics={ + 'binary_size': MagicMock( + difference=None, + difference_percentage=None + ) + } + ), + ] + + build_report_generator = BuildReportGenerator( + project_id=123, + mr_iid=1, + pipeline_id=456, + job_id=0, + commit_id='cccc', + title='Build Report', + apps=skipped_apps + ) + + skipped_apps_report_parts = build_report_generator.get_skipped_apps_report_parts() + + self.assertGreater(len(skipped_apps_report_parts), 0) + self.assertIn('skipped_app_1', ''.join(skipped_apps_report_parts)) + self.assertIn('skipped_app_2', ''.join(skipped_apps_report_parts)) + + def test_build_report_html_structure(self) -> None: + report = self.build_report_generator._get_report_str() + self.assertEqual(report, self.expected_build_report_html) + if __name__ == '__main__': unittest.main() diff --git a/tools/ci/dynamic_pipelines/utils.py b/tools/ci/dynamic_pipelines/utils.py index 936d9e15fbd3..69489bd7cc7c 100644 --- a/tools/ci/dynamic_pipelines/utils.py +++ b/tools/ci/dynamic_pipelines/utils.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import glob import os @@ -168,6 +168,37 @@ def fetch_failed_testcases_failure_ratio(failed_testcases: t.List[TestCase], bra return failed_testcases +def fetch_app_metrics( + source_commit_sha: str, + target_commit_sha: str, +) -> t.Dict: + """ + Fetches the app metrics for the given source commit SHA and target branch SHA. + :param source_commit_sha: The source commit SHA. + :param target_branch_sha: The commit SHA of the branch to compare app sizes against. + :return: A dict of sizes of built binaries. + """ + build_info_map = dict() + response = requests.post( + f'{CI_DASHBOARD_API}/apps/metrics', + headers={'CI-Job-Token': CI_JOB_TOKEN}, + json={ + 'source_commit_sha': source_commit_sha, + 'target_commit_sha': target_commit_sha, + } + ) + if response.status_code != 200: + print(f'Failed to fetch build info: {response.status_code} - {response.text}') + else: + response_data = response.json() + build_info_map = { + f"{info['app_path']}_{info['config_name']}_{info['target']}": info + for info in response_data.get('data', []) + } + + return build_info_map + + def load_file(file_path: str) -> str: """ Loads the content of a file. diff --git a/tools/ci/idf_ci/app.py b/tools/ci/idf_ci/app.py index 03bdb7d9d62e..336c37411502 100644 --- a/tools/ci/idf_ci/app.py +++ b/tools/ci/idf_ci/app.py @@ -1,10 +1,11 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import os import sys import typing as t from typing import Literal +from dynamic_pipelines.constants import BINARY_SIZE_METRIC_NAME from idf_build_apps import App from idf_build_apps import CMakeApp from idf_build_apps import json_to_app @@ -29,6 +30,51 @@ def _post_build(self) -> None: self.uploader.upload_app(self.build_path) +class Metrics: + """ + Represents a metric and its values for source, target, and the differences. + """ + def __init__( + self, + source_value: t.Optional[float] = None, + target_value: t.Optional[float] = None, + difference: t.Optional[float] = None, + difference_percentage: t.Optional[float] = None, + ) -> None: + self.source_value = source_value or 0.0 + self.target_value = target_value or 0.0 + self.difference = difference or 0.0 + self.difference_percentage = difference_percentage or 0.0 + + def to_dict(self) -> dict[str, t.Any]: + """ + Converts the Metrics object to a dictionary. + """ + return { + 'source_value': self.source_value, + 'target_value': self.target_value, + 'difference': self.difference, + 'difference_percentage': self.difference_percentage, + } + + +class AppWithMetricsInfo(IdfCMakeApp): + metrics: t.Dict[str, Metrics] + is_new_app: bool + + def __init__(self, **kwargs: t.Any) -> None: + super().__init__(**kwargs) + + self.metrics = { + metric_name: metric_data + for metric_name, metric_data in kwargs.get('metrics', {}).items() + } + self.is_new_app = kwargs.get('is_new_app', False) + + class Config: + arbitrary_types_allowed = True + + def dump_apps_to_txt(apps: t.List[App], output_filepath: str) -> None: with open(output_filepath, 'w') as fw: for app in apps: @@ -47,3 +93,63 @@ def import_apps_from_txt(input_filepath: str) -> t.List[App]: sys.exit(1) return apps + + +def enrich_apps_with_metrics_info( + app_metrics_info_map: t.Dict[str, t.Dict[str, t.Any]], + apps: t.List[App] +) -> t.List[AppWithMetricsInfo]: + def _get_full_attributes(obj: App) -> t.Dict[str, t.Any]: + """ + Retrieves all attributes of an object, including properties and computed fields. + """ + attributes: t.Dict[str, t.Any] = obj.__dict__.copy() + for attr in dir(obj): + if not attr.startswith('_'): # Skip private/internal attributes + try: + value = getattr(obj, attr) + # Include only if it's not already in __dict__ + if attr not in attributes: + attributes[attr] = value + except Exception: + # Skip attributes that raise exceptions (e.g., methods needing args) + pass + return attributes + + default_metrics_structure = { + BINARY_SIZE_METRIC_NAME: Metrics( + source_value=0, + target_value=0, + difference=0, + difference_percentage=0.0, + ), + } + + apps_with_metrics_info = [] + for app in apps: + key = f'{app.app_dir}_{app.config_name}_{app.target}' + app_attributes = _get_full_attributes(app) + + metrics = { + metric_name: default_metric + for metric_name, default_metric in default_metrics_structure.items() + } + is_new_app = False + + if key in app_metrics_info_map: + info = app_metrics_info_map[key] + for metric_name, metric_data in info.get('metrics', {}).items(): + metrics[metric_name] = Metrics( + source_value=metric_data.get('source_value', 0), + target_value=metric_data.get('target_value', 0), + difference=metric_data.get('difference', 0), + difference_percentage=metric_data.get('difference_percentage', 0.0), + ) + + is_new_app = info.get('is_new_app', False) + + app_attributes.update({'metrics': metrics, 'is_new_app': is_new_app}) + + apps_with_metrics_info.append(AppWithMetricsInfo(**app_attributes)) + + return apps_with_metrics_info diff --git a/tools/idf_py_actions/debug_ext.py b/tools/idf_py_actions/debug_ext.py index 299913afebce..ccf744d20b0f 100644 --- a/tools/idf_py_actions/debug_ext.py +++ b/tools/idf_py_actions/debug_ext.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import json import os @@ -464,8 +464,9 @@ def coredump_debug(action: str, { 'names': ['--chip-rev'], 'help': 'Specify the chip revision (e.g., 0.1). If provided, the corresponding ROM ELF file will be used ' - 'for decoding the core dump, improving stack traces. This is only needed for core dumps from IDF ' - ' dict: - return { - 'type': 'file', - 'name': x, - 'content': content_ - } +FileStructure = t.Dict[str, t.Union[t.Optional[str], 'FileStructure']] -def generate_local_folder_structure(structure_: dict, path_: str) -> None: - if structure_['type'] == 'folder': - new_path_ = os.path.join(path_, structure_['name']) - os.makedirs(new_path_) - for item_ in structure_['content']: - generate_local_folder_structure(item_, new_path_) - else: - new_path_ = os.path.join(path_, structure_['name']) - with open(new_path_, 'w') as f_: - f_.write(structure_['content']) +class DirectoryStructureError(Exception): + '''Base exception for directory structure errors.''' + pass + + +class MissingStructureError(DirectoryStructureError): + '''Raised when a directory or file is missing.''' + pass + + +class ContentMismatchError(DirectoryStructureError): + '''Raised when a file's content does not match the expected content.''' + pass + + +class IOErrorInStructure(DirectoryStructureError): + '''Raised when an I/O error occurs during structure validation.''' + pass + + +def validate_directory_structure(base_path: str, + expected_structure: FileStructure) -> None: + ''' + Checks if the directory structure + and file contents match the expected structure. + + :param base_path: The root directory to check. + :param expected_structure: A nested dictionary representing + the expected structure. + Keys are folder names or file names. + For files, values are either: + - None (skip content check) or + - string (expected content). -def compare_folders(fp1: str, fp2: str) -> bool: - if os.path.isdir(fp1) != os.path.isdir(fp2): - return False - if os.path.isdir(fp1): - if set(os.listdir(fp1)) != set(os.listdir(fp2)): - return False - return all([compare_folders(os.path.join(fp1, path_), os.path.join(fp2, path_)) for path_ in os.listdir(fp1)]) - with open(fp1, 'rb') as f1_, open(fp2, 'rb') as f2_: - return f1_.read() == f2_.read() + For folders values are dictionaries defining + their structure. + + :raises DirectoryStructureError: If the structure or contents do not match. + ''' + def normalize_case(items: t.List[str]) -> t.Dict[str, str]: + return {item.lower(): item for item in items} + + def escape_output(text: str) -> str: + return (text.replace('"', '\"') + .replace('\n', '\\n') + .replace('\t', '\\t') + .replace('\r', '\\r')) + + def validate_structure(current_path: str, + structure: FileStructure) -> None: + current_items = os.listdir(current_path) + normalized_items = normalize_case(current_items) + + for name, substructure in structure.items(): + expected_name = normalized_items.get(name.lower()) + if not expected_name: + raise MissingStructureError( + f'Missing item: {os.path.join(current_path, name)}') + + full_path = os.path.join(current_path, expected_name) + + # File + if isinstance(substructure, str) or substructure is None: + if not os.path.isfile(full_path): + raise MissingStructureError(f'Missing file: {full_path}') + + if isinstance(substructure, str): # Check file content + try: + with open(full_path, 'r', encoding='utf-8') as file: + content = file.read() + if content != substructure: + raise ContentMismatchError( + f'Content mismatch in file: {full_path}\n' + f'Expected: "{escape_output(substructure)}"\n' + f'Found: "{escape_output(content)}"' + ) + except OSError as e: + raise IOErrorInStructure( + f'Error reading file {full_path}: {e}') + + # Folder + elif isinstance(substructure, dict): + if not os.path.isdir(full_path): + raise MissingStructureError( + f'Missing directory: {full_path}') + # Recursively check the subdirectory + validate_structure(full_path, substructure) + + else: + raise DirectoryStructureError( + f'Invalid structure definition for {name}.') + + validate_structure(base_path, expected_structure) @pytest.mark.esp32 @@ -63,164 +132,109 @@ def compare_folders(fp1: str, fp2: str) -> bool: 'test_read_write_partition_gen_ln_default_dt', ], indirect=True) def test_examples_fatfsgen(config: str, dut: Dut) -> None: + # Default timeout - a bit overkill, but better than failing tests + timeout = 60 + + def expect(msg: str, timeout: int = timeout) -> None: + dut.expect(msg, timeout=timeout) + # Expects list of strings sequentially - def expect_all(msg_list: List[str], to: int) -> None: + def expect_all(msg_list: t.List[str], timeout: int = timeout) -> None: for msg in msg_list: - dut.expect(msg, timeout=to) + expect(msg, timeout) # Expects prefix string followed by date in the format 'yyyy-mm-dd' - def expect_date(prefix: str, to: int) -> datetime: + def expect_date(prefix: str, timeout: int = timeout) -> datetime: expect_str = prefix + '(\\d+)-(\\d+)-(\\d+)' - match_ = dut.expect(re.compile(str.encode(expect_str)), timeout=to) + match_ = dut.expect(re.compile(str.encode(expect_str)), + timeout=timeout) year_ = int(match_[1].decode()) month_ = int(match_[2].decode()) day_ = int(match_[3].decode()) return datetime(year_, month_, day_) - # Calculates absolute difference in days between date_reference and date_actual. - # Raises exception if difference exceeds tolerance - def evaluate_dates(date_reference: datetime, date_actual: datetime, days_tolerance: int) -> None: + # Calculates absolute difference in days + # between date_reference and date_actual. + # Raises exception if difference exceeds date_tolerance + # 30 days by default, + def check_dates(date_reference: datetime, + date_actual: datetime, + days_date_tolerance: int = 30) -> None: td = date_actual - date_reference - if abs(td.days) > days_tolerance: - raise Exception(f'Too big date difference. Actual: {date_actual}, reference: {date_reference}, tolerance: {days_tolerance} day(s)') - - # Expect timeout - timeout = 20 - - # We tolerate 30 days difference between actual file creation and date when test was executed. - tolerance = 30 - filename_ln = 'sublongnames/testlongfilenames.txt' - filename_sn = 'sub/test.txt' - date_modified = datetime.today() - date_default = datetime(1980, 1, 1) - fatfs_parser_path = os.path.join(idf_path, 'components', 'fatfs', 'fatfsparse.py') - - if config in ['test_read_write_partition_gen', 'test_read_write_partition_gen_default_dt']: - filename = filename_sn - filename_expected = f'/spiflash/{filename}' - date_ref = date_default if config == 'test_read_write_partition_gen_default_dt' else date_modified - expect_all(['example: Mounting FAT filesystem', - 'example: Opening file', - 'example: File written', - 'example: Reading file', - 'example: Read from file: \'This is written by the device\'', - 'example: Reading file'], timeout) - date_act = expect_date(f'The file \'{filename_expected}\' was modified at date: ', timeout) - evaluate_dates(date_ref, date_act, tolerance) - expect_all(['example: Read from file: \'This is generated on the host\'', - 'example: Unmounting FAT filesystem', - 'example: Done'], timeout) - - target = ParttoolTarget(dut.port) - target.read_partition(PartitionName('storage'), 'temp.img') - run(['python', fatfs_parser_path, '--wear-leveling', 'temp.img'], stderr=STDOUT) - folder_ = { - 'type': 'folder', - 'name': 'SUB', - 'content': [ - file_('TEST.TXT', content_='this is test\n'), - ] - } - struct_: dict = { - 'type': 'folder', - 'name': 'testf', - 'content': [ - file_('HELLO.TXT', content_='This is generated on the host\n'), - file_('INNER.TXT', content_='This is written by the device'), - folder_ - ] - } - generate_local_folder_structure(struct_, path_='.') - try: - assert compare_folders('testf', 'Espressif') - finally: - shutil.rmtree('Espressif', ignore_errors=True) - shutil.rmtree('testf', ignore_errors=True) - - elif config in ['test_read_only_partition_gen', 'test_read_only_partition_gen_default_dt']: - filename = filename_sn - filename_expected = f'/spiflash/{filename}' - date_ref = date_default if config == 'test_read_only_partition_gen_default_dt' else date_modified - expect_all(['example: Mounting FAT filesystem', - 'example: Reading file'], timeout) - date_act = expect_date(f'The file \'{filename_expected}\' was modified at date: ', timeout) - evaluate_dates(date_ref, date_act, tolerance) - expect_all(['example: Read from file: \'this is test\'', - 'example: Unmounting FAT filesystem', - 'example: Done'], timeout) - target = ParttoolTarget(dut.port) - target.read_partition(PartitionName('storage'), 'temp.img') - run(['python', fatfs_parser_path, '--long-name-support', 'temp.img'], stderr=STDOUT) - folder_ = { - 'type': 'folder', - 'name': 'sublongnames', - 'content': [ - file_('testlongfilenames.txt', content_='this is test; long name it has\n'), - ] - } - struct_ = { - 'type': 'folder', - 'name': 'testf', - 'content': [ - file_('hellolongname.txt', content_='This is generated on the host; long name it has\n'), - folder_ - ] - } - generate_local_folder_structure(struct_, path_='.') - try: - assert compare_folders('testf', 'Espressif') - finally: - shutil.rmtree('Espressif', ignore_errors=True) - shutil.rmtree('testf', ignore_errors=True) - - elif config in ['test_read_write_partition_gen_ln', 'test_read_write_partition_gen_ln_default_dt']: - filename = filename_ln - filename_expected = f'/spiflash/{filename}' - date_ref = date_default if config == 'test_read_write_partition_gen_ln_default_dt' else date_modified - expect_all(['example: Mounting FAT filesystem', - 'example: Opening file', + if abs(td.days) > days_date_tolerance: + raise Exception(f'Too big date difference. \ + Actual: {date_actual}, \ + reference: {date_reference}, \ + date_tolerance: {days_date_tolerance} day(s)') + + fatfs_parser_path = os.path.join(idf_path, 'components', + 'fatfs', 'fatfsparse.py') + + config_read_only = '_read_only' in config + config_long_names = '_ln' in config + config_default_date = '_default_dt' in config + + expect('example: Mounting FAT filesystem') + + if not config_read_only: + expect_all(['example: Opening file', 'example: File written', 'example: Reading file', - 'example: Read from file: \'This is written by the device\'', - 'example: Reading file'], timeout) - date_act = expect_date(f'The file \'{filename_expected}\' was modified at date: ', timeout) - evaluate_dates(date_ref, date_act, tolerance) - expect_all(['example: Read from file: \'This is generated on the host; long name it has\'', - 'example: Unmounting FAT filesystem', - 'example: Done'], timeout) - - elif config in ['test_read_only_partition_gen_ln', 'test_read_only_partition_gen_ln_default_dt']: - filename = filename_ln - filename_expected = f'/spiflash/{filename}' - date_ref = date_default if config == 'test_read_only_partition_gen_ln_default_dt' else date_modified - expect_all(['example: Mounting FAT filesystem', - 'example: Reading file'], timeout) - date_act = expect_date(f'The file \'{filename_expected}\' was modified at date: ', timeout) - evaluate_dates(date_ref, date_act, tolerance) - expect_all(['example: Read from file: \'this is test; long name it has\'', - 'example: Unmounting FAT filesystem', - 'example: Done'], timeout) - target = ParttoolTarget(dut.port) - target.read_partition(PartitionName('storage'), 'temp.img') - run(['python', fatfs_parser_path, 'temp.img'], stderr=STDOUT) - folder_ = { - 'type': 'folder', - 'name': 'SUB', - 'content': [ - file_('TEST.TXT', content_='this is test\n'), - ] - } - struct_ = { - 'type': 'folder', - 'name': 'testf', - 'content': [ - file_('HELLO.TXT', content_='This is generated on the host\n'), - folder_ - ] - } - generate_local_folder_structure(struct_, path_='.') - try: - assert compare_folders('testf', 'Espressif') - finally: - shutil.rmtree('Espressif', ignore_errors=True) - shutil.rmtree('testf', ignore_errors=True) + 'example: Read from file: ' + + '\'This is written by the device\''], 30) + + expect('example: Reading file') + + stat_filename = 'sublongnames/testlongfilenames.txt' \ + if config_long_names \ + else 'sub/test.txt' + + modification_date = expect_date( + f'The file \'/spiflash/{stat_filename}\' was modified at date: ') + + date_ref = datetime(1980, 1, 1) \ + if config_default_date \ + else datetime.today() + + check_dates(date_ref, modification_date) + + expect_all(['example: Unmounting FAT filesystem', + 'example: Done']) + + dut.serial.close() + sleep(1) + + target = ParttoolTarget(dut.serial.port, 1843200) + target.read_partition(PartitionName('storage'), 'temp.img') + if config_long_names: + run(['python', fatfs_parser_path, '--long-name-support', 'temp.img'], + stderr=STDOUT) + else: + run(['python', fatfs_parser_path, 'temp.img'], + stderr=STDOUT) + + long_names_read_only: FileStructure = { + 'sublongnames': { + 'testlongfilenames.txt': 'this is test; long name it has\n', + }, + 'hellolongname.txt': 'This is generated on the host; long name it has\n', + } + + short_names_read_only: FileStructure = { + 'sub': { + 'test.txt': 'this is test\n', + }, + 'hello.txt': 'This is generated on the host\n', + } + + file_structure: FileStructure = long_names_read_only \ + if config_long_names \ + else short_names_read_only + + if not config_read_only and not config_long_names: + file_structure['inner.txt'] = 'This is written by the device' + + try: + validate_directory_structure('Espressif', file_structure) + finally: + shutil.rmtree('Espressif', ignore_errors=True) diff --git a/tools/test_apps/storage/fatfsgen/sdkconfig.ci.test_read_write_partition_gen b/tools/test_apps/storage/fatfsgen/sdkconfig.ci.test_read_write_partition_gen index 7ac9efc449e1..3586c92f1f0b 100644 --- a/tools/test_apps/storage/fatfsgen/sdkconfig.ci.test_read_write_partition_gen +++ b/tools/test_apps/storage/fatfsgen/sdkconfig.ci.test_read_write_partition_gen @@ -2,4 +2,4 @@ CONFIG_EXAMPLE_FATFS_MODE_READ_ONLY=n CONFIG_FATFS_LFN_HEAP=n CONFIG_FATFS_LFN_STACK=n CONFIG_FATFS_LFN_NONE=y -CONFIG_EXAMPLE_FATFS_WRITE_COUNT=300 +CONFIG_EXAMPLE_FATFS_WRITE_COUNT=30 diff --git a/tools/test_apps/storage/fatfsgen/sdkconfig.ci.test_read_write_partition_gen_default_dt b/tools/test_apps/storage/fatfsgen/sdkconfig.ci.test_read_write_partition_gen_default_dt index 4b8a2d1e1efe..6c488f4597aa 100644 --- a/tools/test_apps/storage/fatfsgen/sdkconfig.ci.test_read_write_partition_gen_default_dt +++ b/tools/test_apps/storage/fatfsgen/sdkconfig.ci.test_read_write_partition_gen_default_dt @@ -3,4 +3,4 @@ CONFIG_FATFS_LFN_HEAP=n CONFIG_FATFS_LFN_STACK=n CONFIG_FATFS_LFN_NONE=y CONFIG_EXAMPLE_FATFS_DEFAULT_DATETIME=y -CONFIG_EXAMPLE_FATFS_WRITE_COUNT=300 +CONFIG_EXAMPLE_FATFS_WRITE_COUNT=30 diff --git a/tools/test_apps/storage/fatfsgen/sdkconfig.ci.test_read_write_partition_gen_ln b/tools/test_apps/storage/fatfsgen/sdkconfig.ci.test_read_write_partition_gen_ln index eee1bd998f20..2ebbec80fc53 100644 --- a/tools/test_apps/storage/fatfsgen/sdkconfig.ci.test_read_write_partition_gen_ln +++ b/tools/test_apps/storage/fatfsgen/sdkconfig.ci.test_read_write_partition_gen_ln @@ -2,4 +2,4 @@ CONFIG_EXAMPLE_FATFS_MODE_READ_ONLY=n CONFIG_FATFS_LFN_HEAP=y CONFIG_FATFS_LFN_NONE=n CONFIG_FATFS_LFN_STACK=n -CONFIG_EXAMPLE_FATFS_WRITE_COUNT=300 +CONFIG_EXAMPLE_FATFS_WRITE_COUNT=30 diff --git a/tools/test_apps/storage/fatfsgen/sdkconfig.ci.test_read_write_partition_gen_ln_default_dt b/tools/test_apps/storage/fatfsgen/sdkconfig.ci.test_read_write_partition_gen_ln_default_dt index e1a9b879f185..a4b75eaf76a0 100644 --- a/tools/test_apps/storage/fatfsgen/sdkconfig.ci.test_read_write_partition_gen_ln_default_dt +++ b/tools/test_apps/storage/fatfsgen/sdkconfig.ci.test_read_write_partition_gen_ln_default_dt @@ -3,4 +3,4 @@ CONFIG_FATFS_LFN_HEAP=y CONFIG_FATFS_LFN_NONE=n CONFIG_FATFS_LFN_STACK=n CONFIG_EXAMPLE_FATFS_DEFAULT_DATETIME=y -CONFIG_EXAMPLE_FATFS_WRITE_COUNT=300 +CONFIG_EXAMPLE_FATFS_WRITE_COUNT=30 diff --git a/tools/test_apps/system/panic/CMakeLists.txt b/tools/test_apps/system/panic/CMakeLists.txt index e9db4327f57b..a3984845610f 100644 --- a/tools/test_apps/system/panic/CMakeLists.txt +++ b/tools/test_apps/system/panic/CMakeLists.txt @@ -36,8 +36,8 @@ if(NOT CONFIG_TEST_MEMPROT AND NOT CONFIG_ESP_COREDUMP_CAPTURE_DRAM) esp_common esp_hw_support soc hal freertos) if(CONFIG_ESP_COREDUMP_CHECKSUM_SHA256) if(CONFIG_IDF_TARGET_ESP32S2) - # due to the ram limitation, coredump is removed from esp32s2 built - list(REMOVE_ITEM ubsan_components espcoredump) + # due to the ram limitation, coredump and freertos are removed from esp32s2 built + list(REMOVE_ITEM ubsan_components espcoredump freertos) endif() endif() foreach(component IN LISTS ubsan_components) diff --git a/tools/unit-test-app/components/test_utils/CMakeLists.txt b/tools/unit-test-app/components/test_utils/CMakeLists.txt index 291b9638a240..5b2ba8900f4c 100644 --- a/tools/unit-test-app/components/test_utils/CMakeLists.txt +++ b/tools/unit-test-app/components/test_utils/CMakeLists.txt @@ -11,7 +11,7 @@ if(CONFIG_IDF_TARGET_ESP32) # where PCNT can count the pulses generated by RMT, and RMT is clocked from REF_TICK # REF_TICK won't be affected by DFS list(APPEND srcs "ref_clock_impl_rmt_pcnt.c") -else() +elseif(CONFIG_SOC_GPTIMER_SUPPORTED) list(APPEND srcs "ref_clock_impl_timergroup.c") endif()