diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS index 4cc21ca35c8d..983c82a17c2a 100644 --- a/.gitlab/CODEOWNERS +++ b/.gitlab/CODEOWNERS @@ -173,6 +173,7 @@ /examples/cxx/ @esp-idf-codeowners/system /examples/ethernet/ @esp-idf-codeowners/network /examples/get-started/ @esp-idf-codeowners/system +/examples/ieee802154/ @esp-idf-codeowners/ieee802154 /examples/mesh/ @esp-idf-codeowners/wifi /examples/network/ @esp-idf-codeowners/network @esp-idf-codeowners/wifi /examples/openthread/ @esp-idf-codeowners/ieee802154 diff --git a/.gitlab/ci/build.yml b/.gitlab/ci/build.yml index b58a008f3928..64f4020e567c 100644 --- a/.gitlab/ci/build.yml +++ b/.gitlab/ci/build.yml @@ -180,6 +180,15 @@ build_pytest_examples_esp32h2: IDF_TARGET: esp32h2 TEST_DIR: examples +build_pytest_examples_esp32p4: + extends: + - .build_pytest_no_jtag_template + - .rules:build:example_test-esp32p4 + parallel: 2 + variables: + IDF_TARGET: esp32p4 + TEST_DIR: examples + build_pytest_examples_jtag: # for all targets extends: - .build_pytest_jtag_template @@ -251,6 +260,15 @@ build_pytest_components_esp32h2: IDF_TARGET: esp32h2 TEST_DIR: components +build_pytest_components_esp32p4: + extends: + - .build_pytest_template + - .rules:build:component_ut-esp32p4 + parallel: 4 + variables: + IDF_TARGET: esp32p4 + TEST_DIR: components + build_only_components_apps: extends: - .build_cmake_template @@ -324,6 +342,14 @@ build_pytest_test_apps_esp32h2: IDF_TARGET: esp32h2 TEST_DIR: tools/test_apps +build_pytest_test_apps_esp32p4: + extends: + - .build_pytest_template + - .rules:build:custom_test-esp32p4 + variables: + IDF_TARGET: esp32p4 + TEST_DIR: tools/test_apps + build_only_tools_test_apps: extends: - .build_cmake_template diff --git a/.gitlab/ci/default-build-test-rules.yml b/.gitlab/ci/default-build-test-rules.yml index d3066c3938c5..89024c5b73b6 100644 --- a/.gitlab/ci/default-build-test-rules.yml +++ b/.gitlab/ci/default-build-test-rules.yml @@ -9,8 +9,8 @@ extra_default_build_targets: - esp32p4 -bypass_check_test_targets: - - esp32p4 +# bypass_check_test_targets: +# - esp32p4 # # These lines would # - enable the README.md check for esp32c6. Don't forget to add the build jobs in .gitlab/ci/build.yml diff --git a/.gitlab/ci/pre_check.yml b/.gitlab/ci/pre_check.yml index b4a96cf73c14..e0d68f60bb2e 100644 --- a/.gitlab/ci/pre_check.yml +++ b/.gitlab/ci/pre_check.yml @@ -15,6 +15,7 @@ check_pre_commit: script: - fetch_submodules - pre-commit run --files $MODIFIED_FILES + - pre-commit run --hook-stage post-commit validate-sbom-manifest check_version: # Don't run this for feature/bugfix branches, so that it is possible to modify diff --git a/.gitlab/ci/rules.yml b/.gitlab/ci/rules.yml index 589a89528ff6..5d74f7131749 100644 --- a/.gitlab/ci/rules.yml +++ b/.gitlab/ci/rules.yml @@ -830,6 +830,44 @@ - <<: *if-dev-push changes: *patterns-target_test-wifi +.rules:build:component_ut-esp32p4: + rules: + - <<: *if-revert-branch + when: never + - <<: *if-protected + - <<: *if-label-build + - <<: *if-label-component_ut + - <<: *if-label-component_ut_esp32p4 + - <<: *if-label-target_test + - <<: *if-dev-push + changes: *patterns-build_components + - <<: *if-dev-push + changes: *patterns-build_system + - <<: *if-dev-push + changes: *patterns-component_ut + - <<: *if-dev-push + changes: *patterns-component_ut-adc + - <<: *if-dev-push + changes: *patterns-component_ut-flash_multi + - <<: *if-dev-push + changes: *patterns-component_ut-i154 + - <<: *if-dev-push + changes: *patterns-component_ut-nvs_encr_hmac + - <<: *if-dev-push + changes: *patterns-component_ut-sdio + - <<: *if-dev-push + changes: *patterns-component_ut-usb + - <<: *if-dev-push + changes: *patterns-component_ut-wifi + - <<: *if-dev-push + changes: *patterns-downloadable-tools + - <<: *if-dev-push + changes: *patterns-target_test-adc + - <<: *if-dev-push + changes: *patterns-target_test-ecdsa + - <<: *if-dev-push + changes: *patterns-target_test-wifi + .rules:build:component_ut-esp32s2: rules: - <<: *if-revert-branch @@ -1069,6 +1107,32 @@ - <<: *if-dev-push changes: *patterns-target_test-wifi +.rules:build:custom_test-esp32p4: + rules: + - <<: *if-revert-branch + when: never + - <<: *if-protected + - <<: *if-label-build + - <<: *if-label-custom_test + - <<: *if-label-custom_test_esp32p4 + - <<: *if-label-target_test + - <<: *if-dev-push + changes: *patterns-build_components + - <<: *if-dev-push + changes: *patterns-build_system + - <<: *if-dev-push + changes: *patterns-custom_test + - <<: *if-dev-push + changes: *patterns-custom_test-wifi + - <<: *if-dev-push + changes: *patterns-downloadable-tools + - <<: *if-dev-push + changes: *patterns-target_test-adc + - <<: *if-dev-push + changes: *patterns-target_test-ecdsa + - <<: *if-dev-push + changes: *patterns-target_test-wifi + .rules:build:custom_test-esp32s2: rules: - <<: *if-revert-branch @@ -1830,7 +1894,7 @@ - <<: *if-dev-push changes: *patterns-target_test-adc -.rules:test:component_ut-esp32c6-i154: +.rules:test:component_ut-esp32h2: rules: - <<: *if-revert-branch when: never @@ -1838,12 +1902,12 @@ - <<: *if-label-build-only when: never - <<: *if-label-component_ut - - <<: *if-label-component_ut_esp32c6 + - <<: *if-label-component_ut_esp32h2 - <<: *if-label-target_test - <<: *if-dev-push - changes: *patterns-component_ut-i154 + changes: *patterns-component_ut -.rules:test:component_ut-esp32h2: +.rules:test:component_ut-esp32h2-adc: rules: - <<: *if-revert-branch when: never @@ -1854,9 +1918,11 @@ - <<: *if-label-component_ut_esp32h2 - <<: *if-label-target_test - <<: *if-dev-push - changes: *patterns-component_ut + changes: *patterns-component_ut-adc + - <<: *if-dev-push + changes: *patterns-target_test-adc -.rules:test:component_ut-esp32h2-adc: +.rules:test:component_ut-esp32h2-ecdsa: rules: - <<: *if-revert-branch when: never @@ -1867,11 +1933,9 @@ - <<: *if-label-component_ut_esp32h2 - <<: *if-label-target_test - <<: *if-dev-push - changes: *patterns-component_ut-adc - - <<: *if-dev-push - changes: *patterns-target_test-adc + changes: *patterns-target_test-ecdsa -.rules:test:component_ut-esp32h2-ecdsa: +.rules:test:component_ut-esp32p4: rules: - <<: *if-revert-branch when: never @@ -1879,10 +1943,10 @@ - <<: *if-label-build-only when: never - <<: *if-label-component_ut - - <<: *if-label-component_ut_esp32h2 + - <<: *if-label-component_ut_esp32p4 - <<: *if-label-target_test - <<: *if-dev-push - changes: *patterns-target_test-ecdsa + changes: *patterns-component_ut .rules:test:component_ut-esp32s2: rules: @@ -2102,6 +2166,19 @@ - <<: *if-dev-push changes: *patterns-custom_test +.rules:test:custom_test-esp32p4: + rules: + - <<: *if-revert-branch + when: never + - <<: *if-protected + - <<: *if-label-build-only + when: never + - <<: *if-label-custom_test + - <<: *if-label-custom_test_esp32p4 + - <<: *if-label-target_test + - <<: *if-dev-push + changes: *patterns-custom_test + .rules:test:custom_test-esp32s2: rules: - <<: *if-revert-branch @@ -2438,6 +2515,21 @@ - <<: *if-dev-push changes: *patterns-target_test-adc +.rules:test:example_test-esp32p4: + rules: + - <<: *if-revert-branch + when: never + - <<: *if-protected + - <<: *if-label-build-only + when: never + - <<: *if-label-example_test + - <<: *if-label-example_test_esp32p4 + - <<: *if-label-target_test + - <<: *if-dev-push + changes: *patterns-build-example_test + - <<: *if-dev-push + changes: *patterns-example_test + .rules:test:example_test-esp32s2: rules: - <<: *if-revert-branch diff --git a/.gitlab/ci/target-test.yml b/.gitlab/ci/target-test.yml index 8e7892eb117b..78360181d4ec 100644 --- a/.gitlab/ci/target-test.yml +++ b/.gitlab/ci/target-test.yml @@ -247,6 +247,15 @@ pytest_examples_esp32h2_generic: artifacts: false tags: [ esp32h2, generic ] +pytest_examples_esp32p4_generic: + extends: + - .pytest_examples_dir_template + - .rules:test:example_test-esp32p4 + needs: + - job: build_pytest_examples_esp32p4 + artifacts: false + tags: [ esp32p4, generic ] + pytest_examples_esp32_ethernet_ota: extends: - .pytest_examples_dir_template @@ -1253,6 +1262,16 @@ pytest_components_esp32h2_generic: tags: [ esp32h2, generic ] parallel: 2 +pytest_components_esp32p4_generic: + extends: + - .pytest_components_dir_template + - .rules:test:component_ut-esp32p4 + needs: + - job: build_pytest_components_esp32p4 + artifacts: false + tags: [ esp32p4, generic ] + parallel: 2 + pytest_components_esp32h2_generic_multi_device: extends: - .pytest_components_dir_template @@ -1306,12 +1325,12 @@ pytest_components_esp32c6_adc: artifacts: false tags: [ esp32c6, adc ] -pytest_components_esp32c6_i154: +pytest_examples_esp32c6_i154: extends: - - .pytest_components_dir_template - - .rules:test:component_ut-esp32c6-i154 + - .pytest_examples_dir_template + - .rules:test:example_test-esp32c6 needs: - - job: build_pytest_components_esp32c6 + - job: build_pytest_examples_esp32c6 artifacts: false tags: [ esp32c6, ieee802154 ] @@ -1522,6 +1541,15 @@ pytest_test_apps_esp32h2_generic: artifacts: false tags: [ esp32h2, generic ] +pytest_test_apps_esp32p4_generic: + extends: + - .pytest_test_apps_dir_template + - .rules:test:custom_test-esp32p4 + needs: + - job: build_pytest_test_apps_esp32p4 + artifacts: false + tags: [ esp32p4, generic ] + pytest_test_apps_esp32s3_mspi_f8r8: extends: - .pytest_test_apps_dir_template diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d4621b27c23a..8735049c2681 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -196,7 +196,7 @@ repos: - id: check-copyright args: ['--ignore', 'tools/ci/check_copyright_ignore.txt', '--config', 'tools/ci/check_copyright_config.yaml'] - repo: https://github.com/espressif/conventional-precommit-linter - rev: v1.4.1 + rev: v1.6.0 hooks: - id: conventional-precommit-linter stages: [commit-msg] diff --git a/components/app_update/test_apps/pytest_app_update_ut.py b/components/app_update/test_apps/pytest_app_update_ut.py index 594bdbf2f339..9ff51bb993b8 100644 --- a/components/app_update/test_apps/pytest_app_update_ut.py +++ b/components/app_update/test_apps/pytest_app_update_ut.py @@ -19,7 +19,7 @@ def run_multiple_stages(dut: Dut, test_case_num: int, stages: int) -> None: @pytest.mark.supported_targets -@pytest.mark.temp_skip_ci(targets=['esp32c6', 'esp32h2'], reason='c6/h2 support TBD') +@pytest.mark.temp_skip_ci(targets=['esp32c6', 'esp32h2', 'esp32p4'], reason='c6/h2/p4 support TBD') # TODO: IDF-8959 @pytest.mark.generic def test_app_update(dut: Dut) -> None: extra_data = dut.parse_test_menu() diff --git a/components/bootloader_support/src/bootloader_clock_init.c b/components/bootloader_support/src/bootloader_clock_init.c index a56316feb09d..f06a5aa0f294 100644 --- a/components/bootloader_support/src/bootloader_clock_init.c +++ b/components/bootloader_support/src/bootloader_clock_init.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2017-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2017-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -86,6 +86,7 @@ __attribute__((weak)) void bootloader_clock_configure(void) } #endif // CONFIG_ESP_SYSTEM_RTC_EXT_XTAL +// TODO: IDF-8938 Need refactor! Does not belong to clock configuration. #if CONFIG_IDF_TARGET_ESP32C6 // CLR ENA CLEAR_PERI_REG_MASK(LP_WDT_INT_ENA_REG, LP_WDT_SUPER_WDT_INT_ENA); /* SWD */ @@ -113,7 +114,18 @@ __attribute__((weak)) void bootloader_clock_configure(void) SET_PERI_REG_MASK(PMU_HP_INT_CLR_REG, PMU_SOC_WAKEUP_INT_CLR); /* SLP_REJECT */ SET_PERI_REG_MASK(PMU_HP_INT_CLR_REG, PMU_SOC_SLEEP_REJECT_INT_CLR); /* SLP_WAKEUP */ #elif CONFIG_IDF_TARGET_ESP32P4 -// TODO: IDF-8008 + // CLR ENA + CLEAR_PERI_REG_MASK(LP_WDT_INT_ENA_REG, LP_WDT_SUPER_WDT_INT_ENA); /* SWD */ + CLEAR_PERI_REG_MASK(LP_TIMER_LP_INT_ENA_REG, LP_TIMER_MAIN_TIMER_LP_INT_ENA); /* MAIN_TIMER */ + CLEAR_PERI_REG_MASK(LP_ANALOG_PERI_LP_INT_ENA_REG, LP_ANALOG_PERI_BOD_MODE0_LP_INT_ENA); /* BROWN_OUT */ + CLEAR_PERI_REG_MASK(LP_WDT_INT_ENA_REG, LP_WDT_LP_WDT_INT_ENA); /* WDT */ + CLEAR_PERI_REG_MASK(PMU_HP_INT_ENA_REG, PMU_SOC_WAKEUP_INT_ENA); /* SLP_REJECT */ + CLEAR_PERI_REG_MASK(PMU_HP_INT_ENA_REG, PMU_SOC_SLEEP_REJECT_INT_ENA); /* SLP_WAKEUP */ + // SET CLR + SET_PERI_REG_MASK(LP_WDT_INT_CLR_REG, LP_WDT_SUPER_WDT_INT_CLR); /* SWD */ + SET_PERI_REG_MASK(LP_TIMER_LP_INT_CLR_REG, LP_TIMER_MAIN_TIMER_LP_INT_CLR); /* MAIN_TIMER */ + SET_PERI_REG_MASK(LP_ANALOG_PERI_LP_INT_CLR_REG, LP_ANALOG_PERI_LP_INT_CLR_REG); /* BROWN_OUT */ + SET_PERI_REG_MASK(LP_WDT_INT_CLR_REG, LP_WDT_LP_WDT_INT_CLR); /* WDT */ #else REG_WRITE(RTC_CNTL_INT_ENA_REG, 0); REG_WRITE(RTC_CNTL_INT_CLR_REG, UINT32_MAX); diff --git a/components/bootloader_support/src/bootloader_console.c b/components/bootloader_support/src/bootloader_console.c index f248434e59b0..85512b360701 100644 --- a/components/bootloader_support/src/bootloader_console.c +++ b/components/bootloader_support/src/bootloader_console.c @@ -19,7 +19,7 @@ #include "esp32s2/rom/usb/usb_common.h" #endif #if SOC_USB_SERIAL_JTAG_SUPPORTED -#include "hal/usb_phy_ll.h" +#include "hal/usb_fsls_phy_ll.h" #endif #include "esp_rom_gpio.h" #include "esp_rom_uart.h" @@ -106,8 +106,8 @@ void bootloader_console_init(void) esp_rom_uart_set_as_console(ESP_ROM_USB_OTG_NUM); esp_rom_install_channel_putc(1, bootloader_console_write_char_usb); #if SOC_USB_SERIAL_JTAG_SUPPORTED - usb_phy_ll_usb_wrap_pad_enable(&USB_WRAP, true); - usb_phy_ll_int_otg_enable(&USB_WRAP); + usb_fsls_phy_ll_usb_wrap_pad_enable(&USB_WRAP, true); + usb_fsls_phy_ll_int_otg_enable(&USB_WRAP); #endif } #endif //CONFIG_ESP_CONSOLE_USB_CDC diff --git a/components/bootloader_support/src/esp32c5/flash_encryption_secure_features.c b/components/bootloader_support/src/esp32c5/flash_encryption_secure_features.c new file mode 100644 index 000000000000..615aa8ce7b31 --- /dev/null +++ b/components/bootloader_support/src/esp32c5/flash_encryption_secure_features.c @@ -0,0 +1,60 @@ +/* + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#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 "sdkconfig.h" + +static __attribute__((unused)) const char *TAG = "flash_encrypt"; + +esp_err_t esp_flash_encryption_enable_secure_features(void) +{ +#ifndef CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC + ESP_LOGI(TAG, "Disable UART bootloader encryption..."); + esp_efuse_write_field_bit(ESP_EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT); +#else + ESP_LOGW(TAG, "Not disabling UART bootloader encryption"); +#endif + +#ifndef CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_CACHE + ESP_LOGI(TAG, "Disable UART bootloader cache..."); + esp_efuse_write_field_bit(ESP_EFUSE_DIS_DOWNLOAD_ICACHE); +#else + ESP_LOGW(TAG, "Not disabling UART bootloader cache - SECURITY COMPROMISED"); +#endif + +#ifndef CONFIG_SECURE_BOOT_ALLOW_JTAG + ESP_LOGI(TAG, "Disable JTAG..."); + esp_efuse_write_field_bit(ESP_EFUSE_DIS_PAD_JTAG); + esp_efuse_write_field_bit(ESP_EFUSE_DIS_USB_JTAG); +#else + ESP_LOGW(TAG, "Not disabling JTAG - SECURITY COMPROMISED"); +#endif + + esp_efuse_write_field_bit(ESP_EFUSE_DIS_DIRECT_BOOT); + +#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 + esp_efuse_write_field_bit(ESP_EFUSE_WR_DIS_RD_DIS); +#endif + +#ifndef CONFIG_SECURE_FLASH_SKIP_WRITE_PROTECTION_CACHE + // Set write-protection for DIS_ICACHE to prevent bricking chip in case it will be set accidentally. + // esp32c5 has DIS_ICACHE. Write-protection bit = 2. + // List of eFuses with the same write protection bit: + // SWAP_UART_SDIO_EN, DIS_ICACHE, DIS_USB_JTAG, DIS_DOWNLOAD_ICACHE, + // DIS_USB_SERIAL_JTAG, DIS_FORCE_DOWNLOAD, DIS_TWAI, JTAG_SEL_ENABLE, + // DIS_PAD_JTAG, DIS_DOWNLOAD_MANUAL_ENCRYPT. + esp_efuse_write_field_bit(ESP_EFUSE_WR_DIS_DIS_ICACHE); +#endif + + return ESP_OK; +} diff --git a/components/bootloader_support/src/esp32p4/bootloader_esp32p4.c b/components/bootloader_support/src/esp32p4/bootloader_esp32p4.c index d0d841fd8ced..fbd773dd023c 100644 --- a/components/bootloader_support/src/esp32p4/bootloader_esp32p4.c +++ b/components/bootloader_support/src/esp32p4/bootloader_esp32p4.c @@ -44,6 +44,8 @@ #include "hal/lpwdt_ll.h" #include "soc/lp_wdt_reg.h" #include "hal/efuse_hal.h" +#include "soc/regi2c_syspll.h" +#include "soc/regi2c_cpll.h" static const char *TAG = "boot.esp32p4"; @@ -88,10 +90,15 @@ static void bootloader_super_wdt_auto_feed(void) static inline void bootloader_hardware_init(void) { - //TODO: IDF-7528 - // /* Enable analog i2c master clock */ - // SET_PERI_REG_MASK(MODEM_LPCON_CLK_CONF_REG, MODEM_LPCON_CLK_I2C_MST_EN); - // SET_PERI_REG_MASK(MODEM_LPCON_I2C_MST_CLK_CONF_REG, MODEM_LPCON_CLK_I2C_MST_SEL_160M); + // regi2c is enabled by default on ESP32P4, do nothing + + // On ESP32P4 ECO0, the default (power on reset) CPLL and SPLL frequencies are very high, lower them to avoid bias may not be enough in bootloader + // And we are fixing SPLL to be 480MHz at all runtime + // Suppose to fix the issue on ECO1, will check when chip comes back + // TODO: IDF-8939 + REGI2C_WRITE_MASK(I2C_CPLL, I2C_CPLL_OC_DIV_7_0, 6); // lower default cpu_pll freq to 400M + REGI2C_WRITE_MASK(I2C_SYSPLL, I2C_SYSPLL_OC_DIV_7_0, 8); // lower default sys_pll freq to 480M + esp_rom_delay_us(100); } static inline void bootloader_ana_reset_config(void) diff --git a/components/bootloader_support/test_apps/.build-test-rules.yml b/components/bootloader_support/test_apps/.build-test-rules.yml index c4bd99932432..e850144738a2 100644 --- a/components/bootloader_support/test_apps/.build-test-rules.yml +++ b/components/bootloader_support/test_apps/.build-test-rules.yml @@ -5,6 +5,7 @@ components/bootloader_support/test_apps/rtc_custom_section: - if: SOC_RTC_MEM_SUPPORTED == 1 reason: this feature is supported on chips that have RTC memory disable: + # TODO: [ESP32C5] IDF-8653 - if: IDF_TARGET == "esp32c5" temporary: true reason: not supported yet diff --git a/components/bt/controller/lib_esp32h2/esp32h2-bt-lib b/components/bt/controller/lib_esp32h2/esp32h2-bt-lib index 9f593464c059..49a90d0ad509 160000 --- a/components/bt/controller/lib_esp32h2/esp32h2-bt-lib +++ b/components/bt/controller/lib_esp32h2/esp32h2-bt-lib @@ -1 +1 @@ -Subproject commit 9f593464c0593db5100b426d1a6a9a1ce4a55beb +Subproject commit 49a90d0ad509a1ec95fcacfc67d578a97de4c1ee diff --git a/components/bt/esp_ble_mesh/Kconfig.in b/components/bt/esp_ble_mesh/Kconfig.in index b324df84764d..65581a973481 100644 --- a/components/bt/esp_ble_mesh/Kconfig.in +++ b/components/bt/esp_ble_mesh/Kconfig.in @@ -19,10 +19,9 @@ if BLE_MESH bool "Support Duplicate Scan in BLE Mesh" select BTDM_BLE_SCAN_DUPL if IDF_TARGET_ESP32 select BTDM_BLE_MESH_SCAN_DUPL_EN if IDF_TARGET_ESP32 - select BT_CTRL_BLE_SCAN_DUPL if IDF_TARGET_ESP32C3 - select BT_CTRL_BLE_MESH_SCAN_DUPL_EN if IDF_TARGET_ESP32C3 - select BT_LE_SCAN_DUPL if IDF_TARGET_ESP32C6 - select BT_LE_SCAN_DUPL if IDF_TARGET_ESP32H2 + select BT_CTRL_BLE_SCAN_DUPL if IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3 + select BT_CTRL_BLE_MESH_SCAN_DUPL_EN if IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3 + select BT_LE_SCAN_DUPL if IDF_TARGET_ESP32C6 || IDF_TARGET_ESP32H2 select BT_NIMBLE_VS_SUPPORT if BT_NIMBLE_ENABLED default y help @@ -623,6 +622,21 @@ if BLE_MESH number of each node should also be taken into consideration. For example, if Provisioner can provision up to 20 nodes and each node contains two elements, then the replay protection list size of Provisioner should be at least 40. + + config BLE_MESH_NOT_RELAY_REPLAY_MSG + bool "Not relay replayed messages in a mesh network" + depends on BLE_MESH_EXPERIMENTAL + default n + help + There may be many expired messages in a complex mesh network that would be + considered replayed messages. + Enable this option will refuse to relay such messages, which could help to + reduce invalid packets in the mesh network. + However, it should be noted that enabling this option may result in packet + loss in certain environments. + Therefore, users need to decide whether to enable this option according to + the actual usage situation. + config BLE_MESH_MSG_CACHE_SIZE int "Network message cache size" @@ -1451,7 +1465,7 @@ if BLE_MESH config BLE_MESH_MBT_CLI bool "BLOB Transfer Client model" - default y + default n help Enable support for BLOB Transfer Client model. @@ -1469,7 +1483,7 @@ if BLE_MESH config BLE_MESH_MBT_SRV bool "BLOB Transfer Server model" - default y + default n help Enable support for BLOB Transfer Server model. @@ -1607,4 +1621,12 @@ if BLE_MESH endmenu + config BLE_MESH_EXPERIMENTAL + bool "Make BLE Mesh experimental features visible" + default n + help + Make BLE Mesh Experimental features visible. + Experimental features list: + - CONFIG_BLE_MESH_NOT_RELAY_REPLAY_MSG + endif # BLE_MESH diff --git a/components/bt/esp_ble_mesh/core/main.c b/components/bt/esp_ble_mesh/core/main.c index deea8d74ee56..ad94e2c88b2a 100644 --- a/components/bt/esp_ble_mesh/core/main.c +++ b/components/bt/esp_ble_mesh/core/main.c @@ -109,6 +109,11 @@ void bt_mesh_node_reset(void) return; } + if (bt_mesh_prov_active()) { + BT_WARN("%s, link is still active", __func__); + return; + } + bt_mesh.iv_index = 0U; bt_mesh.seq = 0U; diff --git a/components/bt/esp_ble_mesh/core/net.c b/components/bt/esp_ble_mesh/core/net.c index 340cf7d7ac13..66ae08c80d75 100644 --- a/components/bt/esp_ble_mesh/core/net.c +++ b/components/bt/esp_ble_mesh/core/net.c @@ -1542,7 +1542,7 @@ static void bt_mesh_net_relay(struct net_buf_simple *sbuf, #endif if (!buf) { - BT_ERR("Out of relay buffers"); + BT_INFO("Out of relay buffers"); return; } @@ -1855,7 +1855,11 @@ void bt_mesh_net_recv(struct net_buf_simple *data, int8_t rssi, * was neither a local element nor an LPN we're Friends for. */ if (!BLE_MESH_ADDR_IS_UNICAST(rx.ctx.recv_dst) || - (!rx.local_match && !rx.friend_match)) { + (!rx.local_match && !rx.friend_match +#if CONFIG_BLE_MESH_NOT_RELAY_REPLAY_MSG + && !rx.replay_msg +#endif + )) { net_buf_simple_restore(&buf, &state); bt_mesh_net_relay(&buf, &rx); } diff --git a/components/bt/esp_ble_mesh/core/net.h b/components/bt/esp_ble_mesh/core/net.h index 60ca5dc6abb0..7da8c4a07824 100644 --- a/components/bt/esp_ble_mesh/core/net.h +++ b/components/bt/esp_ble_mesh/core/net.h @@ -391,6 +391,9 @@ struct bt_mesh_net_rx { net_if:2, /* Network interface */ local_match:1, /* Matched a local element */ friend_match:1, /* Matched an LPN we're friends for */ +#if CONFIG_BLE_MESH_NOT_RELAY_REPLAY_MSG + replay_msg:1, /* Replayed messages */ +#endif sbr_rpl:1; /* Bridge RPL attacker */ uint16_t msg_cache_idx; /* Index of entry in message cache */ }; diff --git a/components/bt/esp_ble_mesh/core/rpl.c b/components/bt/esp_ble_mesh/core/rpl.c index 2b4435080547..4e3e4c91cbce 100644 --- a/components/bt/esp_ble_mesh/core/rpl.c +++ b/components/bt/esp_ble_mesh/core/rpl.c @@ -64,6 +64,10 @@ static bool rpl_check_and_store(struct bt_mesh_net_rx *rx, struct bt_mesh_rpl ** return false; } +#if CONFIG_BLE_MESH_NOT_RELAY_REPLAY_MSG + rx->replay_msg = 1; +#endif + return true; } } diff --git a/components/bt/host/bluedroid/Kconfig.in b/components/bt/host/bluedroid/Kconfig.in index e63d98447a65..0d5e18d17818 100644 --- a/components/bt/host/bluedroid/Kconfig.in +++ b/components/bt/host/bluedroid/Kconfig.in @@ -1087,6 +1087,14 @@ config BT_SMP_ENABLE depends on BT_BLUEDROID_ENABLED default BT_CLASSIC_ENABLED || BT_BLE_SMP_ENABLE +config BT_SMP_MAX_BONDS + int "BT/BLE maximum bond device count" + depends on BT_SMP_ENABLE + range 1 32 + default 15 + help + The number of security records for peer devices. + config BT_BLE_ACT_SCAN_REP_ADV_SCAN bool "Report adv data and scan response individually when BLE active scan" depends on BT_BLUEDROID_ENABLED && BT_BLE_ENABLED diff --git a/components/bt/host/bluedroid/bta/gatt/bta_gattc_act.c b/components/bt/host/bluedroid/bta/gatt/bta_gattc_act.c index 8bd3fecd77a8..b2302fa469fd 100644 --- a/components/bt/host/bluedroid/bta/gatt/bta_gattc_act.c +++ b/components/bt/host/bluedroid/bta/gatt/bta_gattc_act.c @@ -122,9 +122,9 @@ void bta_gattc_reset_discover_st(tBTA_GATTC_SERV *p_srcb, tBTA_GATT_STATUS statu static void bta_gattc_enable(tBTA_GATTC_CB *p_cb) { APPL_TRACE_DEBUG("bta_gattc_enable"); - /* This is a workaround because the task priority of btc (BTA_GATTC_CLOSE_EVT - in that task) is lower than the priority of the btu task. - Consequently, the p_cb->state fails to be restored to BTA_GATTC_STATE_DISABLED + /* This is a workaround because the task priority of btc (BTA_GATTC_CLOSE_EVT + in that task) is lower than the priority of the btu task. + Consequently, the p_cb->state fails to be restored to BTA_GATTC_STATE_DISABLED and remains in the BTA_GATTC_STATE_DISABLING state. */ if (p_cb->state == BTA_GATTC_STATE_DISABLED || p_cb->state == BTA_GATTC_STATE_DISABLING) { /* initialize control block */ @@ -161,7 +161,6 @@ void bta_gattc_disable(tBTA_GATTC_CB *p_cb) for (i = 0; i < BTA_GATTC_CL_MAX; i ++) { if (p_cb->cl_rcb[i].in_use) { p_cb->state = BTA_GATTC_STATE_DISABLING; - p_cb->cl_rcb[i].in_use = false; /* don't deregister HH GATT IF */ /* HH GATT IF will be deregistered by bta_hh_le_deregister when disable HH */ #if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE) @@ -204,9 +203,9 @@ void bta_gattc_register(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_data) cb_data.reg_oper.status = BTA_GATT_NO_RESOURCES; /* check if GATTC module is already enabled . Else enable */ - /* This is a workaround because the task priority of btc (BTA_GATTC_CLOSE_EVT - in that task) is lower than the priority of the btu task. - Consequently, the p_cb->state fails to be restored to BTA_GATTC_STATE_DISABLED + /* This is a workaround because the task priority of btc (BTA_GATTC_CLOSE_EVT + in that task) is lower than the priority of the btu task. + Consequently, the p_cb->state fails to be restored to BTA_GATTC_STATE_DISABLED and remains in the BTA_GATTC_STATE_DISABLING state. */ if (p_cb->state == BTA_GATTC_STATE_DISABLED || p_cb->state == BTA_GATTC_STATE_DISABLING) { bta_gattc_enable (p_cb); diff --git a/components/bt/host/bluedroid/common/include/common/bluedroid_user_config.h b/components/bt/host/bluedroid/common/include/common/bluedroid_user_config.h index 898978f6218c..ce8e80a2d5b3 100644 --- a/components/bt/host/bluedroid/common/include/common/bluedroid_user_config.h +++ b/components/bt/host/bluedroid/common/include/common/bluedroid_user_config.h @@ -203,6 +203,12 @@ #define UC_BT_SMP_SLAVE_CON_PARAMS_UPD_ENABLE FALSE #endif +#ifdef CONFIG_BT_SMP_MAX_BONDS +#define UC_BT_SMP_MAX_BONDS CONFIG_BT_SMP_MAX_BONDS +#else +#define UC_BT_SMP_MAX_BONDS 8 +#endif + //Device Nane Maximum Length #ifdef CONFIG_BT_MAX_DEVICE_NAME_LEN #define UC_MAX_LOC_BD_NAME_LEN CONFIG_BT_MAX_DEVICE_NAME_LEN diff --git a/components/bt/host/bluedroid/common/include/common/bt_target.h b/components/bt/host/bluedroid/common/include/common/bt_target.h index f467d11200f4..b193805dfb8d 100644 --- a/components/bt/host/bluedroid/common/include/common/bt_target.h +++ b/components/bt/host/bluedroid/common/include/common/bt_target.h @@ -894,13 +894,9 @@ #define BTM_DEFAULT_SCO_MODE 2 #endif -/* The number of security records for peer devices. 100 AS Default*/ +/* The number of security records for peer devices. 15 AS Default*/ #ifndef BTM_SEC_MAX_DEVICE_RECORDS -#if SMP_INCLUDED == TRUE -#define BTM_SEC_MAX_DEVICE_RECORDS 15 // 100 -#else -#define BTM_SEC_MAX_DEVICE_RECORDS 8 -#endif /* SMP_INCLUDED == TRUE */ +#define BTM_SEC_MAX_DEVICE_RECORDS UC_BT_SMP_MAX_BONDS #endif /* The number of security records for services. 32 AS Default*/ diff --git a/components/bt/host/nimble/nimble b/components/bt/host/nimble/nimble index f29df73af659..c3e0414b2809 160000 --- a/components/bt/host/nimble/nimble +++ b/components/bt/host/nimble/nimble @@ -1 +1 @@ -Subproject commit f29df73af65971479782db6f3dcf39d26ca278e5 +Subproject commit c3e0414b280911c5be56896d5159f6e54a0a52b4 diff --git a/components/driver/CMakeLists.txt b/components/driver/CMakeLists.txt index 3c7d4c2fc0a7..3c65725a0e3d 100644 --- a/components/driver/CMakeLists.txt +++ b/components/driver/CMakeLists.txt @@ -10,8 +10,6 @@ set(srcs) # Always included headers set(includes "deprecated" "i2c/include" - "ledc/include" - "parlio/include" "touch_sensor/include" "twai/include" "usb_serial_jtag/include") @@ -34,11 +32,6 @@ if(CONFIG_SOC_DAC_SUPPORTED) "deprecated/${target}/dac_legacy.c") endif() -# Parallel IO related source files -if(CONFIG_SOC_PARLIO_SUPPORTED) - list(APPEND srcs "parlio/parlio_common.c" "parlio/parlio_tx.c") -endif() - # GPTimer legacy driver if(CONFIG_SOC_GPTIMER_SUPPORTED) list(APPEND srcs "deprecated/timer_legacy.c") @@ -54,13 +47,6 @@ if(CONFIG_SOC_I2S_SUPPORTED) list(APPEND srcs "deprecated/i2s_legacy.c") endif() -# LEDC related source files -if(CONFIG_SOC_LEDC_SUPPORTED) - list(APPEND srcs "ledc/ledc.c") - - list(APPEND ldfragments "ledc/linker.lf") -endif() - # MCPWM legacy driver if(CONFIG_SOC_MCPWM_SUPPORTED) list(APPEND srcs "deprecated/mcpwm_legacy.c") @@ -127,7 +113,7 @@ else() esp_driver_gpio esp_driver_pcnt esp_driver_gptimer esp_driver_spi esp_driver_mcpwm esp_driver_ana_cmpr esp_driver_i2s esp_driver_sdmmc esp_driver_sdspi esp_driver_sdio esp_driver_dac esp_driver_rmt esp_driver_tsens esp_driver_sdm esp_driver_i2c - esp_driver_uart + esp_driver_uart esp_driver_ledc esp_driver_parlio LDFRAGMENTS ${ldfragments} ) endif() diff --git a/components/driver/Kconfig b/components/driver/Kconfig index 01d8babbd8ef..96f30ad32c93 100644 --- a/components/driver/Kconfig +++ b/components/driver/Kconfig @@ -81,26 +81,4 @@ menu "Driver Configurations" USB Serial/JTAG is in use. endmenu # USB Serial/JTAG Configuration - menu "Parallel IO Configuration" - depends on SOC_PARLIO_SUPPORTED - - config PARLIO_ENABLE_DEBUG_LOG - bool "Enable debug log" - default n - help - Wether to enable the debug log message for parallel IO driver. - Note that, this option only controls the parallel IO driver log, won't affect other drivers. - - config PARLIO_ISR_IRAM_SAFE - bool "Parallel IO ISR IRAM-Safe" - default n - select GDMA_CTRL_FUNC_IN_IRAM # the driver needs to start the GDMA in the interrupt - help - Ensure the Parallel IO interrupt is IRAM-Safe by allowing the interrupt handler to be - executable when the cache is disabled (e.g. SPI Flash write). - - endmenu # Parallel IO Configuration - - orsource "./ledc/Kconfig.ledc" - endmenu # Driver configurations diff --git a/components/driver/test_apps/.build-test-rules.yml b/components/driver/test_apps/.build-test-rules.yml index 735ddbaa9962..7fa7eca8b357 100644 --- a/components/driver/test_apps/.build-test-rules.yml +++ b/components/driver/test_apps/.build-test-rules.yml @@ -18,10 +18,6 @@ components/driver/test_apps/i2s_test_apps/legacy_i2s_driver: temporary: true reason: lack of runners -components/driver/test_apps/ledc: - disable: - - if: SOC_LEDC_SUPPORTED != 1 - components/driver/test_apps/legacy_adc_driver: disable: - if: SOC_ADC_SUPPORTED != 1 @@ -37,12 +33,20 @@ components/driver/test_apps/legacy_i2c_driver: components/driver/test_apps/legacy_mcpwm_driver: disable: - if: SOC_MCPWM_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: test not pass, should be re-enable # TODO: IDF-8963 depends_filepatterns: - components/driver/deprecated/**/*mcpwm* components/driver/test_apps/legacy_pcnt_driver: disable: - if: SOC_PCNT_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: test not pass, should be re-enable # TODO: IDF-8965 depends_filepatterns: - components/driver/deprecated/**/*pcnt* @@ -67,16 +71,12 @@ components/driver/test_apps/legacy_sigma_delta_driver: components/driver/test_apps/legacy_timer_driver: disable: - if: SOC_GPTIMER_SUPPORTED != 1 - depends_filepatterns: - - components/driver/deprecated/**/*timer* - -components/driver/test_apps/parlio: - disable: - - if: SOC_PARLIO_SUPPORTED != 1 disable_test: - if: IDF_TARGET == "esp32p4" temporary: true - reason: lack of runner + reason: test not pass, should be re-enable # TODO: IDF-8962 + depends_filepatterns: + - components/driver/deprecated/**/*timer* components/driver/test_apps/touch_sensor_v1: disable: @@ -89,6 +89,10 @@ components/driver/test_apps/touch_sensor_v2: components/driver/test_apps/twai: disable: - if: SOC_TWAI_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: test not pass, should be re-enable # TODO: IDF-8966 components/driver/test_apps/usb_serial_jtag: disable: diff --git a/components/driver/test_apps/ledc/CMakeLists.txt b/components/driver/test_apps/ledc/CMakeLists.txt deleted file mode 100644 index 5d032f7d92f1..000000000000 --- a/components/driver/test_apps/ledc/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ -# This is the project CMakeLists.txt file for the test subproject -cmake_minimum_required(VERSION 3.16) - -# "Trim" the build. Include the minimal set of components, main, and anything it depends on. -set(COMPONENTS main) - -include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(ledc_test) - -if(CONFIG_COMPILER_DUMP_RTL_FILES) - add_custom_target(check_test_app_sections ALL - COMMAND ${PYTHON} $ENV{IDF_PATH}/tools/ci/check_callgraph.py - --rtl-dirs ${CMAKE_BINARY_DIR}/esp-idf/driver/,${CMAKE_BINARY_DIR}/esp-idf/hal/ - --elf-file ${CMAKE_BINARY_DIR}/ledc_test.elf - find-refs - --from-sections=.iram0.text - --to-sections=.flash.text,.flash.rodata - --exit-code - DEPENDS ${elf} - ) -endif() diff --git a/components/driver/test_apps/legacy_i2c_driver/pytest_i2c_legacy.py b/components/driver/test_apps/legacy_i2c_driver/pytest_i2c_legacy.py index 4f9c8aae0af2..d922eb6c40be 100644 --- a/components/driver/test_apps/legacy_i2c_driver/pytest_i2c_legacy.py +++ b/components/driver/test_apps/legacy_i2c_driver/pytest_i2c_legacy.py @@ -6,6 +6,7 @@ @pytest.mark.supported_targets +@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='esp32p4 support TBD') # TODO: IDF-8960 @pytest.mark.generic @pytest.mark.parametrize( 'config', diff --git a/components/driver/test_apps/legacy_rmt_driver/pytest_legacy_rmt_driver.py b/components/driver/test_apps/legacy_rmt_driver/pytest_legacy_rmt_driver.py index fc3e2d4d5646..a49ce250f8c3 100644 --- a/components/driver/test_apps/legacy_rmt_driver/pytest_legacy_rmt_driver.py +++ b/components/driver/test_apps/legacy_rmt_driver/pytest_legacy_rmt_driver.py @@ -11,6 +11,7 @@ @pytest.mark.esp32c3 @pytest.mark.esp32c6 @pytest.mark.esp32h2 +@pytest.mark.esp32p4 @pytest.mark.generic @pytest.mark.parametrize('config', [ 'release', diff --git a/components/driver/test_apps/legacy_rtc_temp_driver/pytest_legacy_temp_sensor_driver.py b/components/driver/test_apps/legacy_rtc_temp_driver/pytest_legacy_temp_sensor_driver.py index 04d23916baf1..cfa870a30a39 100644 --- a/components/driver/test_apps/legacy_rtc_temp_driver/pytest_legacy_temp_sensor_driver.py +++ b/components/driver/test_apps/legacy_rtc_temp_driver/pytest_legacy_temp_sensor_driver.py @@ -11,6 +11,7 @@ @pytest.mark.esp32c2 @pytest.mark.esp32c6 @pytest.mark.esp32h2 +@pytest.mark.esp32p4 @pytest.mark.generic @pytest.mark.parametrize('config', [ 'release', diff --git a/components/driver/test_apps/legacy_sigma_delta_driver/pytest_legacy_sigma_delta.py b/components/driver/test_apps/legacy_sigma_delta_driver/pytest_legacy_sigma_delta.py index cba1b0ab0016..1419d0841bfc 100644 --- a/components/driver/test_apps/legacy_sigma_delta_driver/pytest_legacy_sigma_delta.py +++ b/components/driver/test_apps/legacy_sigma_delta_driver/pytest_legacy_sigma_delta.py @@ -11,6 +11,7 @@ @pytest.mark.esp32h2 @pytest.mark.esp32s2 @pytest.mark.esp32s3 +@pytest.mark.esp32p4 @pytest.mark.generic @pytest.mark.parametrize( 'config', diff --git a/components/driver/test_apps/legacy_timer_driver/pytest_legacy_timer_driver.py b/components/driver/test_apps/legacy_timer_driver/pytest_legacy_timer_driver.py index a3bf1518d97a..43c6726f6895 100644 --- a/components/driver/test_apps/legacy_timer_driver/pytest_legacy_timer_driver.py +++ b/components/driver/test_apps/legacy_timer_driver/pytest_legacy_timer_driver.py @@ -5,6 +5,7 @@ from pytest_embedded import Dut +@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='esp32p4 support TBD') # TODO: IDF-8962 @pytest.mark.supported_targets @pytest.mark.generic @pytest.mark.parametrize('config', [ diff --git a/components/driver/test_apps/parlio/README.md b/components/driver/test_apps/parlio/README.md deleted file mode 100644 index 7b822bdb0efd..000000000000 --- a/components/driver/test_apps/parlio/README.md +++ /dev/null @@ -1,2 +0,0 @@ -| Supported Targets | ESP32-C6 | ESP32-H2 | ESP32-P4 | -| ----------------- | -------- | -------- | -------- | diff --git a/components/driver/test_apps/parlio/main/CMakeLists.txt b/components/driver/test_apps/parlio/main/CMakeLists.txt deleted file mode 100644 index d3cd015683ca..000000000000 --- a/components/driver/test_apps/parlio/main/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -set(srcs "test_app_main.c" - "test_parlio_tx.c") - -# In order for the cases defined by `TEST_CASE` to be linked into the final elf, -# the component can be registered as WHOLE_ARCHIVE -idf_component_register(SRCS ${srcs} - PRIV_REQUIRES unity driver - WHOLE_ARCHIVE) diff --git a/components/driver/test_apps/twai/pytest_twai.py b/components/driver/test_apps/twai/pytest_twai.py index d3d8ddeca352..95595646e5aa 100644 --- a/components/driver/test_apps/twai/pytest_twai.py +++ b/components/driver/test_apps/twai/pytest_twai.py @@ -15,7 +15,6 @@ @pytest.mark.esp32h2 @pytest.mark.esp32s2 @pytest.mark.esp32s3 -@pytest.mark.esp32p4 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -42,7 +41,6 @@ def fixture_create_socket_can() -> Bus: @pytest.mark.esp32h2 @pytest.mark.esp32s2 @pytest.mark.esp32s3 -@pytest.mark.esp32p4 @pytest.mark.skip(reason='Runner not set up yet') @pytest.mark.parametrize( 'config', @@ -75,7 +73,6 @@ def test_twai_listen_only(dut: Dut, socket_can: Bus) -> None: @pytest.mark.esp32h2 @pytest.mark.esp32s2 @pytest.mark.esp32s3 -@pytest.mark.esp32p4 @pytest.mark.skip(reason='Runner not set up yet') @pytest.mark.parametrize( 'config', diff --git a/components/driver/usb_serial_jtag/usb_serial_jtag.c b/components/driver/usb_serial_jtag/usb_serial_jtag.c index 85ac7b9b92f4..c6c8951d3f13 100644 --- a/components/driver/usb_serial_jtag/usb_serial_jtag.c +++ b/components/driver/usb_serial_jtag/usb_serial_jtag.c @@ -9,7 +9,7 @@ #include #include "esp_log.h" #include "hal/usb_serial_jtag_ll.h" -#include "hal/usb_phy_ll.h" +#include "hal/usb_fsls_phy_ll.h" #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" #include "freertos/ringbuf.h" @@ -186,7 +186,7 @@ esp_err_t usb_serial_jtag_driver_install(usb_serial_jtag_driver_config_t *usb_se atomic_store(&p_usb_serial_jtag_obj->fifo_status, FIFO_IDLE); // Configure PHY - usb_phy_ll_int_jtag_enable(&USB_SERIAL_JTAG); + usb_fsls_phy_ll_int_jtag_enable(&USB_SERIAL_JTAG); usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY| USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT); diff --git a/components/driver/usb_serial_jtag/usb_serial_jtag_connection_monitor.c b/components/driver/usb_serial_jtag/usb_serial_jtag_connection_monitor.c index 44a9f37edab6..a3d9b0f78bbc 100644 --- a/components/driver/usb_serial_jtag/usb_serial_jtag_connection_monitor.c +++ b/components/driver/usb_serial_jtag/usb_serial_jtag_connection_monitor.c @@ -53,7 +53,9 @@ static void IRAM_ATTR usb_serial_jtag_sof_tick_hook(void) #if CONFIG_USJ_NO_AUTO_LS_ON_CONNECTION esp_pm_lock_release(s_usb_serial_jtag_pm_lock); #endif +#if !CONFIG_IDF_TARGET_ESP32P4 // TODO: IDF-7496 SOC_USB_SERIAL_JTAG_PHY_ON_BBPLL rtc_clk_bbpll_remove_consumer(); +#endif s_usb_serial_jtag_conn_status = false; } } else { @@ -61,7 +63,9 @@ static void IRAM_ATTR usb_serial_jtag_sof_tick_hook(void) #if CONFIG_USJ_NO_AUTO_LS_ON_CONNECTION esp_pm_lock_acquire(s_usb_serial_jtag_pm_lock); #endif +#if !CONFIG_IDF_TARGET_ESP32P4 // TODO: IDF-7496 SOC_USB_SERIAL_JTAG_PHY_ON_BBPLL rtc_clk_bbpll_add_consumer(); +#endif s_usb_serial_jtag_conn_status = true; remaining_allowed_no_sof_ticks = ALLOWED_NO_SOF_TICKS; } @@ -76,7 +80,10 @@ ESP_SYSTEM_INIT_FN(usb_serial_jtag_conn_status_init, SECONDARY, BIT(0), 230) // We always assume it is connected at first, so acquires the lock to avoid auto light sleep esp_pm_lock_acquire(s_usb_serial_jtag_pm_lock); #endif +#if !CONFIG_IDF_TARGET_ESP32P4 // TODO: IDF-7496 SOC_USB_SERIAL_JTAG_PHY_ON_BBPLL +// TODO: esp32p4 USJ rely on SPLL, if it will also be disabled during sleep, we need to call spll_add_consumer? rtc_clk_bbpll_add_consumer(); +#endif s_usb_serial_jtag_conn_status = true; remaining_allowed_no_sof_ticks = ALLOWED_NO_SOF_TICKS; diff --git a/components/efuse/esp32c5/esp_efuse_fields.c b/components/efuse/esp32c5/esp_efuse_fields.c new file mode 100644 index 000000000000..1aaa111a44d5 --- /dev/null +++ b/components/efuse/esp32c5/esp_efuse_fields.c @@ -0,0 +1,56 @@ +/* + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp_efuse.h" +#include "esp_efuse_utility.h" +#include "esp_efuse_table.h" +#include "stdlib.h" +#include "esp_types.h" +#include "esp32c5/rom/efuse.h" +#include "assert.h" +#include "esp_err.h" +#include "esp_log.h" +#include "soc/efuse_periph.h" +#include "sys/param.h" + +static __attribute__((unused)) const char *TAG = "efuse"; + +// TODO: [ESP32C5] IDF-8674 + +// Contains functions that provide access to efuse fields which are often used in IDF. + +// Returns chip package from efuse +uint32_t esp_efuse_get_pkg_ver(void) +{ + uint32_t pkg_ver = 0; + esp_efuse_read_field_blob(ESP_EFUSE_PKG_VERSION, &pkg_ver, ESP_EFUSE_PKG_VERSION[0]->bit_count); + return pkg_ver; +} + + +esp_err_t esp_efuse_set_rom_log_scheme(esp_efuse_rom_log_scheme_t log_scheme) +{ + int cur_log_scheme = 0; + esp_efuse_read_field_blob(ESP_EFUSE_UART_PRINT_CONTROL, &cur_log_scheme, 2); + if (!cur_log_scheme) { // not burned yet + return esp_efuse_write_field_blob(ESP_EFUSE_UART_PRINT_CONTROL, &log_scheme, 2); + } else { + return ESP_ERR_INVALID_STATE; + } +} + +esp_err_t esp_efuse_disable_rom_download_mode(void) +{ + return esp_efuse_write_field_bit(ESP_EFUSE_DIS_DOWNLOAD_MODE); +} + +esp_err_t esp_efuse_enable_rom_secure_download_mode(void) +{ + if (esp_efuse_read_field_bit(ESP_EFUSE_DIS_DOWNLOAD_MODE)) { + return ESP_ERR_INVALID_STATE; + } + return esp_efuse_write_field_bit(ESP_EFUSE_ENABLE_SECURITY_DOWNLOAD); +} diff --git a/components/efuse/esp32c5/sources.cmake b/components/efuse/esp32c5/sources.cmake new file mode 100644 index 000000000000..9dffd72008d3 --- /dev/null +++ b/components/efuse/esp32c5/sources.cmake @@ -0,0 +1,4 @@ +set(EFUSE_SOC_SRCS "esp_efuse_table.c" + "esp_efuse_fields.c" + "esp_efuse_rtc_calib.c" + "esp_efuse_utility.c") diff --git a/components/efuse/test_apps/.build-test-rules.yml b/components/efuse/test_apps/.build-test-rules.yml index 34cb1f2a4dca..f66bd8228aa5 100644 --- a/components/efuse/test_apps/.build-test-rules.yml +++ b/components/efuse/test_apps/.build-test-rules.yml @@ -2,8 +2,8 @@ components/efuse/test_apps: disable_test: - - if: IDF_TARGET in ["esp32s2", "esp32s3"] + - if: IDF_TARGET in ["esp32s2", "esp32s3", "esp32p4"] temporary: true - reason: eFuse for S2 and S3 is similar to the C3 chip, so we only test for C3. + reason: eFuse for S2 and S3 is similar to the C3 chip, so we only test for C3. P4 not tested yet. # TODO: IDF-8967 disable: - if: SOC_EFUSE_SUPPORTED != 1 diff --git a/components/esp_driver_gpio/test_apps/.build-test-rules.yml b/components/esp_driver_gpio/test_apps/.build-test-rules.yml index d9694c7aef26..f0eb84e6e240 100644 --- a/components/esp_driver_gpio/test_apps/.build-test-rules.yml +++ b/components/esp_driver_gpio/test_apps/.build-test-rules.yml @@ -1,6 +1,10 @@ # Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps components/esp_driver_gpio/test_apps: + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: test not pass, should be re-enable # TODO: IDF-8968 depends_components: - esp_driver_gpio diff --git a/components/esp_driver_gpio/test_apps/gpio/pytest_gpio.py b/components/esp_driver_gpio/test_apps/gpio/pytest_gpio.py index 09cba4204402..2af5378174c5 100644 --- a/components/esp_driver_gpio/test_apps/gpio/pytest_gpio.py +++ b/components/esp_driver_gpio/test_apps/gpio/pytest_gpio.py @@ -10,6 +10,7 @@ ] +@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='esp32p4 support TBD') @pytest.mark.supported_targets @pytest.mark.generic @pytest.mark.parametrize('config', CONFIGS, indirect=True) @@ -22,7 +23,6 @@ def test_gpio(dut: IdfDut) -> None: @pytest.mark.esp32s3 @pytest.mark.esp32c6 @pytest.mark.esp32h2 -@pytest.mark.esp32p4 @pytest.mark.generic @pytest.mark.parametrize('config', CONFIGS, indirect=True) def test_rtc_io(dut: IdfDut) -> None: diff --git a/components/esp_driver_i2c/test_apps/i2c_test_apps/pytest_i2c.py b/components/esp_driver_i2c/test_apps/i2c_test_apps/pytest_i2c.py index afcf27563fdf..ba43e0a82609 100644 --- a/components/esp_driver_i2c/test_apps/i2c_test_apps/pytest_i2c.py +++ b/components/esp_driver_i2c/test_apps/i2c_test_apps/pytest_i2c.py @@ -7,6 +7,7 @@ @pytest.mark.supported_targets @pytest.mark.generic +@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='esp32p4 support TBD') # TODO: IDF-8960 @pytest.mark.parametrize( 'config', [ diff --git a/components/esp_driver_ledc/CMakeLists.txt b/components/esp_driver_ledc/CMakeLists.txt new file mode 100644 index 000000000000..8958ebaa93e0 --- /dev/null +++ b/components/esp_driver_ledc/CMakeLists.txt @@ -0,0 +1,14 @@ + +set(srcs) +set(public_include "include") + +if(CONFIG_SOC_LEDC_SUPPORTED) + list(APPEND srcs "src/ledc.c") +endif() + +idf_component_register( + SRCS ${srcs} + INCLUDE_DIRS ${public_include} + PRIV_REQUIRES "esp_pm" "esp_driver_gpio" + LDFRAGMENTS "linker.lf" +) diff --git a/components/driver/ledc/Kconfig.ledc b/components/esp_driver_ledc/Kconfig similarity index 87% rename from components/driver/ledc/Kconfig.ledc rename to components/esp_driver_ledc/Kconfig index 74f8b7a37b5b..940f4db5331c 100644 --- a/components/driver/ledc/Kconfig.ledc +++ b/components/esp_driver_ledc/Kconfig @@ -1,4 +1,4 @@ -menu "LEDC Configuration" +menu "ESP-Driver:LEDC Configurations" config LEDC_CTRL_FUNC_IN_IRAM bool "Place LEDC control functions into IRAM" @@ -8,4 +8,4 @@ menu "LEDC Configuration" so that these functions can be IRAM-safe and able to be called in an IRAM context. Enabling this option can improve driver performance as well. -endmenu # LEDC Configuration +endmenu diff --git a/components/driver/ledc/include/driver/ledc.h b/components/esp_driver_ledc/include/driver/ledc.h similarity index 98% rename from components/driver/ledc/include/driver/ledc.h rename to components/esp_driver_ledc/include/driver/ledc.h index d4a149c9bfbb..2ce9877c7900 100644 --- a/components/driver/ledc/include/driver/ledc.h +++ b/components/esp_driver_ledc/include/driver/ledc.h @@ -634,10 +634,10 @@ esp_err_t ledc_cb_register(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_ * @note Be aware of the maximum value available on each element */ typedef struct { - uint32_t dir : 1; /*!< Duty change direction. Set 1 as increase, 0 as decrease */ - uint32_t cycle_num : SOC_LEDC_FADE_PARAMS_BIT_WIDTH; /*!< Number of PWM cycles of each step [0, 2**SOC_LEDC_FADE_PARAMS_BIT_WIDTH-1] */ - uint32_t scale : SOC_LEDC_FADE_PARAMS_BIT_WIDTH; /*!< Duty change of each step [0, 2**SOC_LEDC_FADE_PARAMS_BIT_WIDTH-1] */ - uint32_t step_num : SOC_LEDC_FADE_PARAMS_BIT_WIDTH; /*!< Total number of steps in one hardware fade [0, 2**SOC_LEDC_FADE_PARAMS_BIT_WIDTH-1] */ + uint32_t dir : 1; /*!< Duty change direction. Set 1 as increase, 0 as decrease */ + uint32_t cycle_num : SOC_LEDC_FADE_PARAMS_BIT_WIDTH; /*!< Number of PWM cycles of each step [0, 2**SOC_LEDC_FADE_PARAMS_BIT_WIDTH-1] */ + uint32_t scale : SOC_LEDC_FADE_PARAMS_BIT_WIDTH; /*!< Duty change of each step [0, 2**SOC_LEDC_FADE_PARAMS_BIT_WIDTH-1] */ + uint32_t step_num : SOC_LEDC_FADE_PARAMS_BIT_WIDTH; /*!< Total number of steps in one hardware fade [0, 2**SOC_LEDC_FADE_PARAMS_BIT_WIDTH-1] */ } ledc_fade_param_config_t; /** diff --git a/components/driver/ledc/linker.lf b/components/esp_driver_ledc/linker.lf similarity index 89% rename from components/driver/ledc/linker.lf rename to components/esp_driver_ledc/linker.lf index 4119b65081de..1bb52d58a1b3 100644 --- a/components/driver/ledc/linker.lf +++ b/components/esp_driver_ledc/linker.lf @@ -1,5 +1,5 @@ [mapping:ledc_driver] -archive: libdriver.a +archive: libesp_driver_ledc.a entries: if LEDC_CTRL_FUNC_IN_IRAM = y: ledc: ledc_stop (noflash) diff --git a/components/driver/ledc/ledc.c b/components/esp_driver_ledc/src/ledc.c similarity index 98% rename from components/driver/ledc/ledc.c rename to components/esp_driver_ledc/src/ledc.c index 99c6a4cdf9f1..1c58eecb48b4 100644 --- a/components/driver/ledc/ledc.c +++ b/components/esp_driver_ledc/src/ledc.c @@ -221,7 +221,7 @@ esp_err_t ledc_timer_set(ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_ } static IRAM_ATTR esp_err_t ledc_duty_config(ledc_mode_t speed_mode, ledc_channel_t channel, int hpoint_val, -int duty_val, ledc_duty_direction_t duty_direction, uint32_t duty_num, uint32_t duty_cycle, uint32_t duty_scale) + int duty_val, ledc_duty_direction_t duty_direction, uint32_t duty_num, uint32_t duty_cycle, uint32_t duty_scale) { if (hpoint_val >= 0) { ledc_hal_set_hpoint(&(p_ledc_obj[speed_mode]->ledc_hal), channel, hpoint_val); @@ -347,7 +347,7 @@ static inline uint32_t ledc_calculate_divisor(uint32_t src_clk_freq, int freq_hz * NOTE: We are also going to round up the value when necessary, thanks to: * (freq_hz * precision / 2) */ - return ( ( (uint64_t) src_clk_freq << LEDC_LL_FRACTIONAL_BITS ) + freq_hz * precision / 2 ) + return (((uint64_t) src_clk_freq << LEDC_LL_FRACTIONAL_BITS) + freq_hz * precision / 2) / (freq_hz * precision); } @@ -453,7 +453,6 @@ static uint32_t ledc_auto_clk_divisor(ledc_mode_t speed_mode, int freq_hz, uint3 return ret; } - /** * @brief Function setting the LEDC timer divisor with the given source clock, * frequency and resolution. If the clock configuration passed is @@ -462,7 +461,7 @@ static uint32_t ledc_auto_clk_divisor(ledc_mode_t speed_mode, int freq_hz, uint3 static esp_err_t ledc_set_timer_div(ledc_mode_t speed_mode, ledc_timer_t timer_num, ledc_clk_cfg_t clk_cfg, int freq_hz, int duty_resolution) { uint32_t div_param = 0; - const uint32_t precision = ( 0x1 << duty_resolution ); + const uint32_t precision = (0x1 << duty_resolution); /* The clock sources are not initialized on purpose. To produce compiler warning if used but the selector functions * don't set them properly. */ /* Timer-specific mux. Set to timer-specific clock or LEDC_SCLK if a global clock is used. */ @@ -480,7 +479,7 @@ static esp_err_t ledc_set_timer_div(ledc_mode_t speed_mode, ledc_timer_t timer_n /* Before calculating the divisor, we need to have the RC_FAST frequency. * If it hasn't been measured yet, try calibrating it now. */ - if(s_ledc_slow_clk_rc_fast_freq == 0 && ledc_slow_clk_calibrate() == false) { + if (s_ledc_slow_clk_rc_fast_freq == 0 && ledc_slow_clk_calibrate() == false) { goto error; } @@ -554,7 +553,7 @@ static esp_err_t ledc_set_timer_div(ledc_mode_t speed_mode, ledc_timer_t timer_n if (i != timer_num && p_ledc_obj[speed_mode]->glb_clk_is_acquired[i]) { portEXIT_CRITICAL(&ledc_spinlock); ESP_RETURN_ON_FALSE(false, ESP_FAIL, LEDC_TAG, - "timer clock conflict, already is %d but attempt to %d", p_ledc_obj[speed_mode]->glb_clk, glb_clk); + "timer clock conflict, already is %d but attempt to %d", p_ledc_obj[speed_mode]->glb_clk, glb_clk); } } } @@ -571,7 +570,7 @@ static esp_err_t ledc_set_timer_div(ledc_mode_t speed_mode, ledc_timer_t timer_n ESP_LOGD(LEDC_TAG, "In slow speed mode, global clk set: %d", glb_clk); -#if !CONFIG_IDF_TARGET_ESP32P4 //depend on sleep support IDF-7528 and IDF-7529 +#if !CONFIG_IDF_TARGET_ESP32P4 //depend on sleep support IDF-7528 /* keep ESP_PD_DOMAIN_RC_FAST on during light sleep */ extern void esp_sleep_periph_use_8m(bool use_or_not); esp_sleep_periph_use_8m(glb_clk == LEDC_SLOW_CLK_RC_FAST); @@ -593,11 +592,12 @@ static esp_err_t ledc_timer_del(ledc_mode_t speed_mode, ledc_timer_t timer_sel) bool is_configured = true; bool is_deleted = false; portENTER_CRITICAL(&ledc_spinlock); - if (p_ledc_obj[speed_mode]->glb_clk_is_acquired[timer_sel] == false #if SOC_LEDC_HAS_TIMER_SPECIFIC_MUX - && p_ledc_obj[speed_mode]->timer_specific_clk[timer_sel] == LEDC_TIMER_SPECIFIC_CLK_UNINIT + if (p_ledc_obj[speed_mode]->glb_clk_is_acquired[timer_sel] == false && p_ledc_obj[speed_mode]->timer_specific_clk[timer_sel] == LEDC_TIMER_SPECIFIC_CLK_UNINIT) +#else + if (p_ledc_obj[speed_mode]->glb_clk_is_acquired[timer_sel] == false) #endif - ) { + { is_configured = false; } else if (p_ledc_obj[speed_mode]->timer_is_stopped[timer_sel] == true) { is_deleted = true; @@ -974,7 +974,7 @@ static void IRAM_ATTR ledc_fade_isr(void *arg) } else { // Calculate new duty config parameters delta = (s_ledc_fade_rec[speed_mode][channel]->direction == LEDC_DUTY_DIR_DECREASE) ? - (duty_cur - duty_tar) : (duty_tar - duty_cur); + (duty_cur - duty_tar) : (duty_tar - duty_cur); if (delta > scale) { next_duty = duty_cur; step = (delta / scale > LEDC_DUTY_NUM_MAX) ? LEDC_DUTY_NUM_MAX : (delta / scale); @@ -1227,7 +1227,7 @@ esp_err_t ledc_fade_stop(ledc_mode_t speed_mode, ledc_channel_t channel) LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); LEDC_ARG_CHECK(channel < LEDC_CHANNEL_MAX, "channel"); LEDC_CHECK(p_ledc_obj[speed_mode] != NULL, LEDC_NOT_INIT, ESP_ERR_INVALID_STATE); - LEDC_CHECK(ledc_fade_channel_init_check(speed_mode, channel) == ESP_OK , LEDC_FADE_INIT_ERROR_STR, ESP_FAIL); + LEDC_CHECK(ledc_fade_channel_init_check(speed_mode, channel) == ESP_OK, LEDC_FADE_INIT_ERROR_STR, ESP_FAIL); ledc_fade_t *fade = s_ledc_fade_rec[speed_mode][channel]; ledc_fade_fsm_t state = fade->fsm; bool wait_for_idle = false; @@ -1250,7 +1250,7 @@ esp_err_t ledc_fade_stop(ledc_mode_t speed_mode, ledc_channel_t channel) 1, //uint32_t duty_num, 1, //uint32_t duty_cycle, 0 //uint32_t duty_scale - ); + ); _ledc_update_duty(speed_mode, channel); state = fade->fsm; assert(state != LEDC_FSM_IDLE && state != LEDC_FSM_KILLED_PENDING); @@ -1490,7 +1490,7 @@ esp_err_t ledc_fill_multi_fade_param_list(ledc_mode_t speed_mode, ledc_channel_t uint32_t cycle, scale, step; gamma_corrected_phase_tail = gamma_correction_operator(phase_tail); uint32_t duty_delta = (dir == LEDC_DUTY_DIR_INCREASE) ? (gamma_corrected_phase_tail - gamma_corrected_phase_head) : - (gamma_corrected_phase_head - gamma_corrected_phase_tail); + (gamma_corrected_phase_head - gamma_corrected_phase_tail); uint32_t cycles_per_phase = avg_cycles_per_phase + surplus_cycles_last_phase; if (duty_delta == 0) { scale = 0; @@ -1549,7 +1549,7 @@ esp_err_t ledc_fill_multi_fade_param_list(ledc_mode_t speed_mode, ledc_channel_t } uint32_t remaining_duty_delta = (dir == LEDC_DUTY_DIR_INCREASE) ? (gamma_corrected_phase_tail - gamma_corrected_phase_head) : - (gamma_corrected_phase_head - gamma_corrected_phase_tail); + (gamma_corrected_phase_head - gamma_corrected_phase_tail); if (remaining_duty_delta) { total_fade_range += 1; } diff --git a/components/esp_driver_ledc/test_apps/.build-test-rules.yml b/components/esp_driver_ledc/test_apps/.build-test-rules.yml new file mode 100644 index 000000000000..00d99826d130 --- /dev/null +++ b/components/esp_driver_ledc/test_apps/.build-test-rules.yml @@ -0,0 +1,11 @@ +# Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps + +components/esp_driver_ledc/test_apps/ledc: + disable: + - if: SOC_LEDC_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: test not pass, should be re-enable # TODO: IDF-8969 + depends_components: + - esp_driver_ledc diff --git a/components/esp_driver_ledc/test_apps/ledc/CMakeLists.txt b/components/esp_driver_ledc/test_apps/ledc/CMakeLists.txt new file mode 100644 index 000000000000..1a8d35567e60 --- /dev/null +++ b/components/esp_driver_ledc/test_apps/ledc/CMakeLists.txt @@ -0,0 +1,22 @@ +# This is the project CMakeLists.txt file for the test subproject +cmake_minimum_required(VERSION 3.16) + +# "Trim" the build. Include the minimal set of components, main, and anything it depends on. +set(COMPONENTS main) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(ledc_test) + +if(CONFIG_COMPILER_DUMP_RTL_FILES) + add_custom_target( + check_test_app_sections ALL + COMMAND ${PYTHON} $ENV{IDF_PATH}/tools/ci/check_callgraph.py + --rtl-dirs ${CMAKE_BINARY_DIR}/esp-idf/esp_driver_ledc/,${CMAKE_BINARY_DIR}/esp-idf/hal/ + --elf-file ${CMAKE_BINARY_DIR}/ledc_test.elf + find-refs + --from-sections=.iram0.text + --to-sections=.flash.text,.flash.rodata + --exit-code + DEPENDS ${elf} + ) +endif() diff --git a/components/driver/test_apps/ledc/README.md b/components/esp_driver_ledc/test_apps/ledc/README.md similarity index 100% rename from components/driver/test_apps/ledc/README.md rename to components/esp_driver_ledc/test_apps/ledc/README.md diff --git a/components/driver/test_apps/ledc/main/CMakeLists.txt b/components/esp_driver_ledc/test_apps/ledc/main/CMakeLists.txt similarity index 53% rename from components/driver/test_apps/ledc/main/CMakeLists.txt rename to components/esp_driver_ledc/test_apps/ledc/main/CMakeLists.txt index 5a5d4f716a4e..63794907bf1a 100644 --- a/components/driver/test_apps/ledc/main/CMakeLists.txt +++ b/components/esp_driver_ledc/test_apps/ledc/main/CMakeLists.txt @@ -3,6 +3,8 @@ set(srcs "test_app_main.c" # In order for the cases defined by `TEST_CASE` to be linked into the final elf, # the component can be registered as WHOLE_ARCHIVE -idf_component_register(SRCS ${srcs} - PRIV_REQUIRES unity esp_driver_pcnt driver esp_timer esp_psram - WHOLE_ARCHIVE) +idf_component_register( + SRCS ${srcs} + PRIV_REQUIRES unity esp_driver_pcnt esp_driver_ledc esp_driver_gpio esp_timer esp_psram + WHOLE_ARCHIVE +) diff --git a/components/driver/test_apps/ledc/main/test_app_main.c b/components/esp_driver_ledc/test_apps/ledc/main/test_app_main.c similarity index 100% rename from components/driver/test_apps/ledc/main/test_app_main.c rename to components/esp_driver_ledc/test_apps/ledc/main/test_app_main.c diff --git a/components/driver/test_apps/ledc/main/test_ledc.c b/components/esp_driver_ledc/test_apps/ledc/main/test_ledc.c similarity index 99% rename from components/driver/test_apps/ledc/main/test_ledc.c rename to components/esp_driver_ledc/test_apps/ledc/main/test_ledc.c index fd7fda188046..1d3f7b6b8041 100644 --- a/components/driver/test_apps/ledc/main/test_ledc.c +++ b/components/esp_driver_ledc/test_apps/ledc/main/test_ledc.c @@ -589,7 +589,7 @@ TEST_CASE("LEDC set and get frequency", "[ledc][timeout=60]") #if SOC_CLK_TREE_SUPPORTED static void timer_set_clk_src_and_freq_test(ledc_mode_t speed_mode, ledc_clk_cfg_t clk_src, uint32_t duty_res, - uint32_t freq_hz) + uint32_t freq_hz) { ledc_timer_config_t ledc_time_config = { .speed_mode = speed_mode, diff --git a/components/driver/test_apps/ledc/pytest_ledc.py b/components/esp_driver_ledc/test_apps/ledc/pytest_ledc.py similarity index 82% rename from components/driver/test_apps/ledc/pytest_ledc.py rename to components/esp_driver_ledc/test_apps/ledc/pytest_ledc.py index 5d4daa5beb40..c93955b3a94b 100644 --- a/components/driver/test_apps/ledc/pytest_ledc.py +++ b/components/esp_driver_ledc/test_apps/ledc/pytest_ledc.py @@ -6,7 +6,7 @@ @pytest.mark.supported_targets -@pytest.mark.temp_skip_ci(targets=['esp32s3'], reason='skip due to duplication with test_ledc_psram') +@pytest.mark.temp_skip_ci(targets=['esp32s3', 'esp32p4'], reason='skip due to duplication with test_ledc_psram, p4 TBD') # TODO: IDF-8969 @pytest.mark.generic @pytest.mark.parametrize( 'config', diff --git a/components/driver/test_apps/ledc/sdkconfig.ci.iram_safe b/components/esp_driver_ledc/test_apps/ledc/sdkconfig.ci.iram_safe similarity index 100% rename from components/driver/test_apps/ledc/sdkconfig.ci.iram_safe rename to components/esp_driver_ledc/test_apps/ledc/sdkconfig.ci.iram_safe diff --git a/components/driver/test_apps/ledc/sdkconfig.ci.release b/components/esp_driver_ledc/test_apps/ledc/sdkconfig.ci.release similarity index 100% rename from components/driver/test_apps/ledc/sdkconfig.ci.release rename to components/esp_driver_ledc/test_apps/ledc/sdkconfig.ci.release diff --git a/components/driver/test_apps/ledc/sdkconfig.defaults b/components/esp_driver_ledc/test_apps/ledc/sdkconfig.defaults similarity index 100% rename from components/driver/test_apps/ledc/sdkconfig.defaults rename to components/esp_driver_ledc/test_apps/ledc/sdkconfig.defaults diff --git a/components/driver/test_apps/ledc/sdkconfig.defaults.esp32s3 b/components/esp_driver_ledc/test_apps/ledc/sdkconfig.defaults.esp32s3 similarity index 100% rename from components/driver/test_apps/ledc/sdkconfig.defaults.esp32s3 rename to components/esp_driver_ledc/test_apps/ledc/sdkconfig.defaults.esp32s3 diff --git a/components/esp_driver_mcpwm/test_apps/.build-test-rules.yml b/components/esp_driver_mcpwm/test_apps/.build-test-rules.yml index cbc941233cd2..0a58b194acf6 100644 --- a/components/esp_driver_mcpwm/test_apps/.build-test-rules.yml +++ b/components/esp_driver_mcpwm/test_apps/.build-test-rules.yml @@ -3,5 +3,9 @@ components/esp_driver_mcpwm/test_apps/mcpwm: disable: - if: SOC_MCPWM_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: test not pass, should be re-enable # TODO: IDF-8963 depends_components: - esp_driver_mcpwm diff --git a/components/esp_driver_parlio/CMakeLists.txt b/components/esp_driver_parlio/CMakeLists.txt new file mode 100644 index 000000000000..2b70fac211dc --- /dev/null +++ b/components/esp_driver_parlio/CMakeLists.txt @@ -0,0 +1,12 @@ +set(srcs) +set(public_include "include") +if(CONFIG_SOC_PARLIO_SUPPORTED) + list(APPEND srcs "src/parlio_common.c" + "src/parlio_tx.c" + "src/parlio_rx.c") +endif() + +idf_component_register(SRCS ${srcs} + INCLUDE_DIRS ${public_include} + PRIV_REQUIRES "esp_pm" "esp_driver_gpio" + ) diff --git a/components/esp_driver_parlio/Kconfig b/components/esp_driver_parlio/Kconfig new file mode 100644 index 000000000000..ad6f91847a11 --- /dev/null +++ b/components/esp_driver_parlio/Kconfig @@ -0,0 +1,19 @@ +menu "ESP-Driver:Parallel IO Configurations" + depends on SOC_PARLIO_SUPPORTED + + config PARLIO_ENABLE_DEBUG_LOG + bool "Enable debug log" + default n + help + Wether to enable the debug log message for parallel IO driver. + Note that, this option only controls the parallel IO driver log, won't affect other drivers. + + config PARLIO_ISR_IRAM_SAFE + bool "Parallel IO ISR IRAM-Safe" + default n + select GDMA_CTRL_FUNC_IN_IRAM # the driver needs to start the GDMA in the interrupt + help + Ensure the Parallel IO interrupt is IRAM-Safe by allowing the interrupt handler to be + executable when the cache is disabled (e.g. SPI Flash write). + +endmenu # Parallel IO Configuration diff --git a/components/esp_driver_parlio/include/driver/parlio_rx.h b/components/esp_driver_parlio/include/driver/parlio_rx.h new file mode 100644 index 000000000000..a080c399d19d --- /dev/null +++ b/components/esp_driver_parlio/include/driver/parlio_rx.h @@ -0,0 +1,334 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include +#include "esp_err.h" +#include "driver/parlio_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Parallel IO RX unit configuration + */ +typedef struct { + size_t trans_queue_depth; /*!< Depth of internal transaction queue */ + size_t max_recv_size; /*!< Maximum receive size in one transaction, in bytes. This decides the number of DMA nodes will be used for each transaction */ + size_t data_width; /*!< Parallel IO data width, can set to 1/2/4/8/..., but can't be greater than PARLIO_RX_UNIT_MAX_DATA_WIDTH */ + parlio_clock_source_t clk_src; /*!< Parallel IO clock source */ + uint32_t ext_clk_freq_hz; /*!< The external source clock frequency. Only be valid when select PARLIO_CLK_SRC_EXTERNAL as clock source */ + uint32_t exp_clk_freq_hz; /*!< The expected sample/bit clock frequency, which is divided from the internal or external clock regarding the clock source */ + gpio_num_t clk_in_gpio_num; /*!< The the external clock input pin. Only be valid when select PARLIO_CLK_SRC_EXTERNAL as clock source. Set to -1 if not needed */ + gpio_num_t clk_out_gpio_num; /*!< The sample/bit clock output pin. Set to -1 if not needed */ + gpio_num_t valid_gpio_num; /*!< GPIO number of the valid signal. The signal on this pin is used to indicate whether the data on the data lines are valid. + Only takes effect when using level or pulse delimiter, set to `-1` if only use the soft delimiter */ + gpio_num_t data_gpio_nums[PARLIO_RX_UNIT_MAX_DATA_WIDTH]; /*!< Parallel IO data GPIO numbers, set to `-1` if it's not used, + The driver will take [0 .. (data_width - 1)] as the data pins */ + struct { + uint32_t free_clk : 1; /*!< Whether the input external clock is a free-running clock. A free-running clock will always keep running (e.g. I2S bclk), + a non-free-running clock will start when there are data transporting and stop when the bus idle (e.g. SPI). + This flag only takes effect when select PARLIO_CLK_SRC_EXTERNAL as clock source */ + uint32_t clk_gate_en : 1; /*!< Enable RX clock gating, only available when the clock direction is output(not supported on ESP32-C6) + the output clock will be controlled by the valid gpio, + i.e. high level of valid gpio to enable the clock output, low to disable */ + uint32_t io_loop_back: 1; /*!< For debug/test, the signal output from the GPIO will be fed to the input path as well */ + uint32_t io_no_init: 1; /*!< Set to skip initializing the GPIO, but only attach the pralio rx signals to those GPIOs via IO Matrix. + So that the signals that have attached to those GPIO won't be overwritten. Mainly used for self communication or self monitoring */ + } flags; /*!< RX driver flags */ +} parlio_rx_unit_config_t; + +/** + * @brief Create a Parallel IO RX unit + * + * @param[in] config Parallel IO RX unit configuration + * @param[out] ret_unit Returned Parallel IO RX unit handle + * @return + * - ESP_ERR_INVALID_ARG Invalid arguments in the parameter list or the rx unit configuration + * - ESP_ERR_NOT_FOUND No available rx unit found + * - ESP_ERR_NO_MEM No enough memory for the rx unit resources + * - ESP_OK Success to allocate the rx unit + */ +esp_err_t parlio_new_rx_unit(const parlio_rx_unit_config_t *config, parlio_rx_unit_handle_t *ret_unit); + +/** + * @brief Delete a Parallel IO RX unit + * + * @param[in] rx_unit Parallel IO RX unit handle that created by `parlio_new_rx_unit` + * @return + * - ESP_ERR_INVALID_ARG rx_unit is NULL + * - ESP_ERR_INVALID_STATE The rx unit is enabled, can't delete an enabled rx unit + * - ESP_OK Success to delete the rx unit + */ +esp_err_t parlio_del_rx_unit(parlio_rx_unit_handle_t rx_unit); + +/** + * @brief Configuration of level delimiter + */ +typedef struct { + uint32_t valid_sig_line_id; /*!< The data line id of valid/enable signal. + The selected data line will be used as the valid/enable signal (i.e. level signal) in this delimiter. + As the line of valid/enable signal is shared with the data line, this line_id will be conflict + with the data line if set the id within 'data_width', + therefore the range is (data_width, PARLIO_RX_UNIT_MAX_DATA_WIDTH]. */ + parlio_sample_edge_t sample_edge; /*!< Parallel IO sample edge */ + parlio_bit_pack_order_t bit_pack_order; /*!< Set how we pack the bits into one bytes */ + uint32_t eof_data_len; /*!< Set the data length to trigger the End Of Frame (EOF, i.e. transaction done) + interrupt, if the data length is set to `0`, that mean the EOF will only triggers + when the enable signal inactivated */ + uint32_t timeout_ticks; /*!< The number of source clock ticks to trigger timeout interrupt. Set 0 to disable the receive timeout interrupt + The timeout counter starts when the valid/enable signal is invalid/disabled. */ + struct { + uint32_t active_low_en: 1; /*!< Set true to set the valid signal active when the level is low, + otherwise, the valid signal becomes active when its level is high */ + } flags; /*!< Extra flags */ +} parlio_rx_level_delimiter_config_t; + +/** + * @brief Create a level delimiter + * @note This function only allocate the software resources, the hardware configurations + * will lazy installed while the transaction that using this delimiter start processing + * @note The enable signal must be aligned with the valid data. + * @note There're at most `SOC_PARLIO_RX_UNIT_MAX_DATA_WIDTH - 1` IO pins left for RXD + * + * @param[in] config Level delimiter configuration + * @param[out] ret_delimiter Returned delimiter handle + * @return + * - ESP_ERR_INVALID_ARG Invalid arguments in the parameter list or the level delimiter configuration + * - ESP_ERR_NO_MEM No enough memory for the level delimiter resources + * - ESP_OK Success to allocate the level delimiter + */ +esp_err_t parlio_new_rx_level_delimiter(const parlio_rx_level_delimiter_config_t *config, + parlio_rx_delimiter_handle_t *ret_delimiter); + +/** + * @brief Configuration of pulse delimiter + */ +typedef struct { + uint32_t valid_sig_line_id; /*!< The data line id of valid/enable signal. + The selected data line will be used as the valid/enable signal (i.e. pulse signal) in this delimiter. + As the line of valid/enable signal is shared with the data line, this line_id will be conflict + with the data line if set the id within 'data_width', + therefore the range is (data_width, PARLIO_RX_UNIT_MAX_DATA_WIDTH]. */ + parlio_sample_edge_t sample_edge; /*!< Parallel IO sample edge */ + parlio_bit_pack_order_t bit_pack_order; /*!< Set how we pack the bits into one bytes */ + uint32_t eof_data_len; /*!< Set the data length to trigger the End Of Frame (EOF, i.e. transaction done) + interrupt, if the data length is set to `0`, that mean the EOF will only triggers + when the end pulse detected, please ensure there is an end pulse for a frame and + `has_end_pulse` flag is set */ + uint32_t timeout_ticks; /*!< The number of source clock ticks to trigger timeout interrupt. Set 0 to disable the receive timeout interrupt + The timeout counter starts when the valid/enable signal is invalid/disabled. */ + struct { + uint32_t start_bit_included: 1; /*!< Whether data bit is included in the start pulse */ + uint32_t end_bit_included: 1; /*!< Whether data bit is included in the end pulse, only valid when `has_end_pulse` is true */ + uint32_t has_end_pulse: 1; /*!< Whether there's an end pulse to terminate the transaction, + if no, the transaction will be terminated by user configured transcation length */ + uint32_t pulse_invert: 1; /*!< Whether to invert the pulse */ + } flags; /*!< Extra flags */ +} parlio_rx_pulse_delimiter_config_t; + +/** + * @brief Create a pulse delimiter + * @note This function only allocate the software resources, the hardware configurations + * will lazy installed while the transaction that using this delimiter start processing + * @note There're at most `SOC_PARLIO_RX_UNIT_MAX_DATA_WIDTH - 1` IO pins left for RXD + * + * @param[in] config Pulse delimiter configuration + * @param[out] ret_delimiter Returned delimiter handle + * @return + * - ESP_ERR_INVALID_ARG Invalid arguments in the parameter list or the pulse delimiter configuration + * - ESP_ERR_NO_MEM No enough memory for the pulse delimiter resources + * - ESP_OK Success to allocate the pulse delimiter + */ +esp_err_t parlio_new_rx_pulse_delimiter(const parlio_rx_pulse_delimiter_config_t *config, + parlio_rx_delimiter_handle_t *ret_delimiter); + +/** + * @brief Configuration of soft delimiter + */ +typedef struct { + parlio_sample_edge_t sample_edge; /*!< Parallel IO sample edge */ + parlio_bit_pack_order_t bit_pack_order; /*!< Set how we pack the bits into one bytes, set 1 to pack the bits into a byte from LSB, + otherwise from MSB */ + uint32_t eof_data_len; /*!< Set the data length to trigger the End Of Frame (EOF, i.e. transaction done) + interrupt, if the data length is set to `0`, that mean the EOF will only triggers + when the end pulse detected, please ensure there is an end pulse for a frame and + `parlio_rx_pulse_delimiter_config_t::has_end_pulse` flag is set */ + uint32_t timeout_ticks; /*!< The number of APB clock ticks to trigger timeout interrupt. Set 0 to disable the receive timeout interrupt */ +} parlio_rx_soft_delimiter_config_t; + +/** + * @brief Create a pulse delimiter + * @note This function only allocate the software resources, the hardware configurations + * will lazy installed while the transaction that using this delimiter start processing + * @param[in] config Soft delimiter configuration + * @param[out] ret_delimiter Returned delimiter handle + * @return + * - ESP_ERR_INVALID_ARG Invalid arguments in the parameter list or the soft delimiter configuration + * - ESP_ERR_NO_MEM No enough memory for the soft delimiter resources + * - ESP_OK Success to allocate the soft delimiter + */ +esp_err_t parlio_new_rx_soft_delimiter(const parlio_rx_soft_delimiter_config_t *config, + parlio_rx_delimiter_handle_t *ret_delimiter); + +/** + * @brief Start/stop the soft delimiter + * @note Soft delimiter need to start or stop manually because it has no validating/enabling signal to indicate the data has started or stopped + * + * @param[in] rx_unit Parallel IO RX unit handle that created by `parlio_new_rx_unit` + * @param[in] delimiter Delimiter handle + * @param[in] start_stop Set true to start, set false to stop + * @return + * - ESP_ERR_INVALID_ARG Invalid arguments in the parameter list or not soft delimiter + * - ESP_ERR_INVALID_STATE The rx unit not enabled + * - ESP_OK Success to start or stop the soft delimiter + */ +esp_err_t parlio_rx_soft_delimiter_start_stop(parlio_rx_unit_handle_t rx_unit, parlio_rx_delimiter_handle_t delimiter, bool start_stop); + +/** + * @brief Delete the delimiter + * @note To delete the delimiter safely, please delete it after disable all the RX units + * + * @param[in] delimiter Delimiter handle + * @return + * - ESP_ERR_INVALID_ARG The input delimiter is NULL + * - ESP_ERR_INVALID_STATE The delimiter is on receiving + * - ESP_OK Success to delete the delimiter + */ +esp_err_t parlio_del_rx_delimiter(parlio_rx_delimiter_handle_t delimiter); + +/** + * @brief Enable the Parallel IO RX unit + * + * @param[in] rx_unit Parallel IO RX unit handle that created by `parlio_new_rx_unit` + * @param[in] reset_queue Whether to reset the receiving queue. + * If set to false, the legacy receive transactions in the queue are still available, + * If set to true, the legacy receive transactions in the queue are dropped. + * @return + * - ESP_ERR_INVALID_ARG The input rx_unit is NULL + * - ESP_ERR_INVALID_STATE The rx unit has been enabled + * - ESP_OK Success to enable the rx unit + */ +esp_err_t parlio_rx_unit_enable(parlio_rx_unit_handle_t rx_unit, bool reset_queue); + +/** + * @brief Disable the Parallel IO RX unit + * + * @param[in] rx_unit Parallel IO RX unit handle that created by `parlio_new_rx_unit` + * @return + * - ESP_ERR_INVALID_ARG The input rx_unit is NULL + * - ESP_ERR_INVALID_STATE The rx unit has been disabled + * - ESP_OK Success to disable the rx unit + */ +esp_err_t parlio_rx_unit_disable(parlio_rx_unit_handle_t rx_unit); + +/** + * @brief Configuration of a receive transaction + */ +typedef struct { + parlio_rx_delimiter_handle_t delimiter; /*!< The delimiter of this receiving transaction */ + struct { + uint32_t partial_rx_en: 1; /*!< Whether this is an infinite transaction that supposed to receive continuously and partially */ + uint32_t indirect_mount: 1; /*!< This flag only take effect when `partial_rx_en` is enabled. + * Enable this flag, an INTERNAL DMA buffer will be mounted to the DMA descriptor instead, + * The data will be copy to the payload in every interrupt. So that to guarantee the payload buffer + * is valid during the `on_receive_done` callback. + * Either `partial_rx_en` or `indirect_mount` is disabled, + * the user given finite payload will be mounted to the DMA descriptor directly. + * By default, the user given receive payload will be mounted to the DMA descriptor directly. + */ + } flags; /*!< Extra flags */ +} parlio_receive_config_t; + +/** + * @brief Receive data by Parallel IO RX unit + * @note This is a non-blocking and asynchronous function. To block or realize synchronous receive, + * please call `parlio_rx_unit_wait_all_done` after this function + * @note The receive transaction will start immediately when there is not other transaction on receiving, + * Otherwise it will be sent to the transaction queue to wait for the bus. + * + * @param[in] rx_unit Parallel IO RX unit handle that created by `parlio_new_rx_unit` + * @param[in] payload The payload buffer pointer + * @param[in] payload_size The size of the payload buffer, in bytes. + * @param[in] recv_cfg The configuration of this receive transaction + * @return + * - ESP_ERR_INVALID_ARG Invalid arguments in the parameter list or the receive configuration + * - ESP_ERR_NO_MEM No memory for the internal DMA buffer (only when parlio_receive_config_t::indirect_mount enabled) + * - ESP_ERR_INVALID_STATE Transaction queue is full, failed to queue the current transaction. + * Or the internal buffer is under using by an infinite transaction, can't allocate a new one + * - ESP_OK Success to queue the current receiving transaction + */ +esp_err_t parlio_rx_unit_receive(parlio_rx_unit_handle_t rx_unit, + void *payload, + size_t payload_size, + const parlio_receive_config_t* recv_cfg); + +/** + * @brief Wait for all pending RX transactions done + * @note This function will block until all receiving transactions done or timeout. + * When timeout occurs, either the timeout limitation too short for all transactions done, + * or the peripheral got stuck and no more interrupts trigger (e.g., external clock stopped). + * + * @param[in] rx_unit Parallel IO RX unit handle that created by `parlio_new_rx_unit` + * @param[in] timeout_ms Timeout in milliseconds, `-1` means to wait forever (software timeout) + * @return + * - ESP_ERR_INVALID_ARG The input rx_unit is NULL + * - ESP_ERR_TIMEOUT Wait for all transactions done timeout + * - ESP_OK All transaction done + */ +esp_err_t parlio_rx_unit_wait_all_done(parlio_rx_unit_handle_t rx_unit, int timeout_ms); + +/** + * @brief Event callback data + */ +typedef struct { + parlio_rx_delimiter_handle_t delimiter; /*!< The current delimiter of this receiving event */ + void *data; /*!< The data buffer address that just finished receiving */ + size_t recv_bytes; /*!< The number of received bytes in the data buffer */ +} parlio_rx_event_data_t; + +/** + * @brief The template of the Parallel IO RX callback function + * + * @param[in] rx_unit Parallel IO RX unit handle that given from ISR + * @param[in] edata The event data that given from ISR + * @param[in] user_data The user specified data that given while registering the callbacks + * + * @return + * - True: to awoke high priority tasks + * - False: not to awoke high priority tasks + */ +typedef bool (*parlio_rx_callback_t)(parlio_rx_unit_handle_t rx_unit, const parlio_rx_event_data_t *edata, void *user_data); + +/** + * @brief Parallel IO RX event callbacks + */ +typedef struct { + parlio_rx_callback_t on_partial_receive; /*!< Callback of received partial data */ + parlio_rx_callback_t on_receive_done; /*!< Callback of receiving transaction done */ + parlio_rx_callback_t on_timeout; /*!< Callback of hardware receiving timeout */ +} parlio_rx_event_callbacks_t; + +/** + * @brief Register event callbacks for Parallel IO RX unit + * + * @param[in] rx_unit Parallel IO RX unit handle that created by `parlio_new_rx_unit` + * @param[in] cbs Callback group, set callback to NULL to deregister the corresponding callback (callback group pointer shouldn't be NULL) + * @param[in] user_data User specified data that will be transported to the callbacks + * @return + * - ESP_ERR_INVALID_ARG The input rx_unit is NULL + * - ESP_ERR_INVALID_STATE The rx unit has been enabled, callback should be registered before enabling the unit + * - ESP_OK Success to register the callbacks + */ +esp_err_t parlio_rx_unit_register_event_callbacks(parlio_rx_unit_handle_t rx_unit, const parlio_rx_event_callbacks_t *cbs, void *user_data); + +#ifdef __cplusplus +} +#endif diff --git a/components/driver/parlio/include/driver/parlio_tx.h b/components/esp_driver_parlio/include/driver/parlio_tx.h similarity index 100% rename from components/driver/parlio/include/driver/parlio_tx.h rename to components/esp_driver_parlio/include/driver/parlio_tx.h diff --git a/components/driver/parlio/include/driver/parlio_types.h b/components/esp_driver_parlio/include/driver/parlio_types.h similarity index 63% rename from components/driver/parlio/include/driver/parlio_types.h rename to components/esp_driver_parlio/include/driver/parlio_types.h index c6dbff9b2a6d..b909d5489541 100644 --- a/components/driver/parlio/include/driver/parlio_types.h +++ b/components/esp_driver_parlio/include/driver/parlio_types.h @@ -21,6 +21,16 @@ extern "C" { */ typedef struct parlio_tx_unit_t *parlio_tx_unit_handle_t; +/** + * @brief Type of Parallel IO RX unit handle + */ +typedef struct parlio_rx_unit_t *parlio_rx_unit_handle_t; + +/** + * @brief Type of Parallel IO RX frame delimiter handle + */ +typedef struct parlio_rx_delimiter_t *parlio_rx_delimiter_handle_t; + #ifdef __cplusplus } #endif diff --git a/components/driver/parlio/parlio_common.c b/components/esp_driver_parlio/src/parlio_common.c similarity index 58% rename from components/driver/parlio/parlio_common.c rename to components/esp_driver_parlio/src/parlio_common.c index 409a3f7f0f6c..cd5a7aeb7000 100644 --- a/components/driver/parlio/parlio_common.c +++ b/components/esp_driver_parlio/src/parlio_common.c @@ -89,3 +89,62 @@ void parlio_release_group_handle(parlio_group_t *group) ESP_LOGD(TAG, "del group(%d)", group_id); } } + +esp_err_t parlio_register_unit_to_group(parlio_unit_base_handle_t unit) +{ + parlio_group_t *group = NULL; + int unit_id = -1; + for (int i = 0; i < SOC_PARLIO_GROUPS; i++) { + group = parlio_acquire_group_handle(i); + parlio_unit_base_handle_t *group_unit = NULL; + ESP_RETURN_ON_FALSE(group, ESP_ERR_NO_MEM, TAG, "no memory for group (%d)", i); + portENTER_CRITICAL(&group->spinlock); + if (unit->dir == PARLIO_DIR_TX) { + for (int j = 0; j < SOC_PARLIO_TX_UNITS_PER_GROUP; j++) { + group_unit = &group->tx_units[j]; + if (*group_unit == NULL) { + *group_unit = unit; + unit_id = j; + break; + } + } + } else { + for (int j = 0; j < SOC_PARLIO_RX_UNITS_PER_GROUP; j++) { + group_unit = &group->rx_units[j]; + if (*group_unit == NULL) { + *group_unit = unit; + unit_id = j; + break; + } + } + } + portEXIT_CRITICAL(&group->spinlock); + if (unit_id < 0) { + /* didn't find a free unit slot in the group */ + parlio_release_group_handle(group); + group = NULL; + } else { + unit->unit_id = unit_id; + unit->group = group; + break; + } + } + ESP_RETURN_ON_FALSE(unit_id >= 0, ESP_ERR_NOT_FOUND, TAG, + "no free %s unit", unit->dir == PARLIO_DIR_TX ? "tx" : "rx"); + return ESP_OK; +} + +void parlio_unregister_unit_from_group(parlio_unit_base_handle_t unit) +{ + assert(unit); + parlio_group_t *group = unit->group; + portENTER_CRITICAL(&group->spinlock); + if (unit->dir == PARLIO_DIR_TX) { + group->tx_units[unit->unit_id] = NULL; + } else { + group->rx_units[unit->unit_id] = NULL; + } + portEXIT_CRITICAL(&group->spinlock); + /* the parlio unit has a reference of the group, release it now */ + parlio_release_group_handle(group); +} diff --git a/components/driver/parlio/parlio_private.h b/components/esp_driver_parlio/src/parlio_private.h similarity index 67% rename from components/driver/parlio/parlio_private.h rename to components/esp_driver_parlio/src/parlio_private.h index f2ae0283fd1b..1a889797347e 100644 --- a/components/driver/parlio/parlio_private.h +++ b/components/esp_driver_parlio/src/parlio_private.h @@ -84,6 +84,11 @@ enum { PARLIO_TX_QUEUE_MAX, }; +typedef enum { + PARLIO_DIR_TX, + PARLIO_DIR_RX, +} parlio_dir_t; + typedef enum { PARLIO_TX_FSM_INIT_WAIT, PARLIO_TX_FSM_INIT, @@ -93,16 +98,43 @@ typedef enum { PARLIO_TX_FSM_RUN, } parlio_tx_fsm_t; +typedef struct parlio_unit_t *parlio_unit_base_handle_t; + typedef struct parlio_group_t { - int group_id; // group ID, index from 0 - portMUX_TYPE spinlock; // to protect per-group register level concurrent access - parlio_hal_context_t hal; // hal layer for each group - parlio_tx_unit_handle_t tx_units[SOC_PARLIO_TX_UNITS_PER_GROUP]; // tx unit handles + int group_id; // group ID, index from 0 + portMUX_TYPE spinlock; // to protect per-group register level concurrent access + parlio_hal_context_t hal; // hal layer for each group + parlio_unit_base_handle_t tx_units[SOC_PARLIO_TX_UNITS_PER_GROUP]; // tx unit handles + parlio_unit_base_handle_t rx_units[SOC_PARLIO_RX_UNITS_PER_GROUP]; // rx unit handles } parlio_group_t; -parlio_group_t *parlio_acquire_group_handle(int group_id); +/** + * @brief The common field of rx and tx unit structure + * + */ +struct parlio_unit_t { + int unit_id; // unit id + parlio_dir_t dir; + parlio_group_t *group; // group handle +}; -void parlio_release_group_handle(parlio_group_t *group); +/** + * @brief Register the rx or tx unit to the parlio group + * + * @param[in] unit The TX/RX unit base handle + * @return + * - ESP_ERR_NO_MEM No memory for the unit + * - ESP_ERR_NOT_FOUND No available unit found on this group + * - ESP_OK Success to register the unit on the group + */ +esp_err_t parlio_register_unit_to_group(parlio_unit_base_handle_t unit); + +/** + * @brief Unregister the rx or tx unit from the parlio group + * + * @param[in] unit The TX/RX unit base handle + */ +void parlio_unregister_unit_from_group(parlio_unit_base_handle_t unit); #ifdef __cplusplus } diff --git a/components/esp_driver_parlio/src/parlio_rx.c b/components/esp_driver_parlio/src/parlio_rx.c new file mode 100644 index 000000000000..59eb54e5af5b --- /dev/null +++ b/components/esp_driver_parlio/src/parlio_rx.c @@ -0,0 +1,959 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include "sdkconfig.h" +#include "freertos/FreeRTOS.h" +#include "freertos/idf_additions.h" +#if CONFIG_PARLIO_ENABLE_DEBUG_LOG +// The local log level must be defined before including esp_log.h +// Set the maximum log level for this source file +#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG +#endif +#include "esp_log.h" +#include "esp_check.h" +#include "esp_attr.h" +#include "esp_err.h" +#include "esp_rom_gpio.h" +#include "esp_pm.h" +#include "soc/parlio_periph.h" +#include "hal/parlio_ll.h" +#include "hal/gpio_hal.h" +#include "hal/dma_types.h" +#include "hal/hal_utils.h" +#include "driver/gpio.h" +#include "driver/parlio_rx.h" +#include "parlio_private.h" +#include "esp_memory_utils.h" +#include "esp_clk_tree.h" +#include "esp_attr.h" +#include "esp_private/gdma.h" + +static const char *TAG = "parlio-rx"; + +/** + * @brief Parlio RX transaction + */ +typedef struct { + parlio_rx_delimiter_handle_t delimiter; /*!< Delimiter of this transaction */ + void *payload; /*!< The payload of this transaction, will be mounted to DMA descriptor */ + size_t size; /*!< The payload size in byte */ + size_t recv_bytes; /*!< The received bytes of this transaction + will be reset when all data filled in the infinite transaction */ + struct { + uint32_t infinite : 1; /*!< Whether this is an infinite transaction */ + uint32_t indirect_mount : 1; /*!< Whether the user payload mount to the descriptor indirectly via an internal DMA buffer */ + } flags; +} parlio_rx_transaction_t; + +/** + * @brief Parlio RX unit resource management + */ +typedef struct parlio_rx_unit_t { + /* Unit general Resources */ + struct parlio_unit_t base; /*!< base unit */ + parlio_clock_source_t clk_src; /*!< clock source of the unit */ + parlio_rx_unit_config_t cfg; /*!< basic configuration of the rx unit */ + volatile bool is_enabled; /*!< State flag that indicates whether the unit is enabled */ + /* Mutex Lock */ + SemaphoreHandle_t mutex; /*!< Mutex lock for concurrence safety, + * which should be acquired and released in a same function */ + + /* Power Management */ + esp_pm_lock_handle_t pm_lock; /*!< power management lock */ +#if CONFIG_PM_ENABLE + char pm_lock_name[PARLIO_PM_LOCK_NAME_LEN_MAX]; /*!< pm lock name */ +#endif + + /* Transaction Resources */ + QueueHandle_t trans_que; /*!< Static transaction queue handle */ + parlio_rx_transaction_t curr_trans; /*!< The current transaction */ + SemaphoreHandle_t trans_sem; /*!< Binary semaphore to deliver transaction done signal, + * which can be acquired and released between different functions */ + + /* DMA Resources */ + gdma_channel_handle_t dma_chan; /*!< DMA channel */ + size_t max_recv_size; /*!< Maximum receive size for a normal transaction */ + size_t desc_num; /*!< DMA descriptor number */ + dma_descriptor_t *dma_descs; /*!< DMA descriptor array pointer */ + dma_descriptor_t *curr_desc; /*!< The pointer of the current descriptor */ + void *usr_recv_buf; /*!< The pointe to the user's receiving buffer */ + /* Infinite transaction specific */ + void *dma_buf; /*!< Additional internal DMA buffer only for infinite transactions */ + + /* Callback */ + parlio_rx_event_callbacks_t cbs; /*!< The group of callback function pointers */ + void *user_data; /*!< User data that supposed to be transported to the callback functions */ + +} parlio_rx_unit_t; + +/** + * @brief Delimiter mode + */ +typedef enum { + PARLIO_RX_LEVEL_MODE, /*!< Delimit by the level of valid signal */ + PARLIO_RX_PULSE_MODE, /*!< Delimit by the pulse of valid signal */ + PARLIO_RX_SOFT_MODE, /*!< Delimit by the length of received data */ +} parlio_rx_delimiter_mode_t; + +/** + * @brief Pralio RX delimiter management + */ +typedef struct parlio_rx_delimiter_t { + parlio_rx_delimiter_mode_t mode; /*!< Delimiter mode */ + bool under_using; /*!< Whether this delimiter is under using */ + + uint32_t valid_sig; + gpio_num_t valid_sig_line_id; /*!< The data line id for the valid signal */ + parlio_sample_edge_t sample_edge; /*!< The sampling edge of the data */ + parlio_bit_pack_order_t bit_pack_order; /*!< The order to pack the bit on the data line */ + uint32_t eof_data_len; /*!< The length of the data to trigger the eof interrupt */ + uint32_t timeout_ticks; /*!< The ticks of source clock that can trigger hardware timeout */ + struct { + uint32_t active_low_en: 1; /*!< Whether the transmitting data validate when the valid signal at low level */ + uint32_t start_bit_included: 1; /*!< Whether data bit is included in the start pulse */ + uint32_t end_bit_included: 1; /*!< Whether data bit is included in the end pulse, only valid when `has_end_pulse` is true */ + uint32_t has_end_pulse: 1; /*!< Whether there's an end pulse to terminate the transaction, + if no, the transaction will be terminated by user configured transcation length */ + uint32_t pulse_invert: 1; /*!< Whether to invert the pulse */ + } flags; +} parlio_rx_delimiter_t; + +static portMUX_TYPE s_rx_spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED; + +static IRAM_ATTR size_t s_parlio_mount_transaction_buffer(parlio_rx_unit_handle_t rx_unit, parlio_rx_transaction_t *trans) +{ + dma_descriptor_t *p_desc = rx_unit->dma_descs; + /* Update the current transaction to the next one, and declare the delimiter is under using of the rx unit */ + memcpy(&rx_unit->curr_trans, trans, sizeof(parlio_rx_transaction_t)); + portENTER_CRITICAL_SAFE(&s_rx_spinlock); + trans->delimiter->under_using = true; + portEXIT_CRITICAL_SAFE(&s_rx_spinlock); + + uint32_t desc_num = trans->size / DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED; + uint32_t remain_num = trans->size % DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED; + /* If there are still data remained, need one more descriptor */ + desc_num += remain_num ? 1 : 0; + if (trans->flags.infinite && desc_num < 2) { + /* At least 2 descriptors needed */ + desc_num = 2; + } + size_t mount_size = 0; + size_t offset = 0; + /* Loop the descriptors to assign the data */ + for (int i = 0; i < desc_num; i++) { + size_t rest_size = trans->size - offset; + if (rest_size >= 2 * DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED) { + mount_size = trans->size / desc_num; + } else if (rest_size <= DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED) { + mount_size = (desc_num == 2) && (i == 0) ? rest_size / 2 : rest_size; + } else { + mount_size = rest_size / 2; + } + p_desc[i].buffer = (void *)((uint8_t *)trans->payload + offset); + p_desc[i].dw0.size = mount_size; + p_desc[i].dw0.length = mount_size; + p_desc[i].dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA; + // Link the descriptor + if (i > 0) { + p_desc[i - 1].next = &p_desc[i]; + } + offset += mount_size; + } + /* For infinite transaction, link the descriptor as a ring */ + p_desc[desc_num - 1].next = trans->flags.infinite ? &p_desc[0] : NULL; + /* Reset the current DMA node */ + rx_unit->curr_desc = p_desc; + + return offset; +} + +static IRAM_ATTR void s_parlio_set_delimiter_config(parlio_rx_unit_handle_t rx_unit, parlio_rx_delimiter_handle_t deli) +{ + parlio_hal_context_t *hal = &(rx_unit->base.group->hal); + + /* Set the clock sampling edge and the bit order */ + parlio_ll_rx_set_sample_clock_edge(hal->regs, deli->sample_edge); + parlio_ll_rx_set_bit_pack_order(hal->regs, deli->bit_pack_order); + + /* Set receive mode according to the delimiter */ + switch (deli->mode) { + case PARLIO_RX_LEVEL_MODE: + /* Select the level receive mode */ + parlio_ll_rx_set_level_recv_mode(hal->regs, deli->flags.active_low_en); + parlio_ll_rx_treat_data_line_as_en(hal->regs, deli->valid_sig_line_id); + break; + case PARLIO_RX_PULSE_MODE: + /* Select the pulse receive mode */ + parlio_ll_rx_set_pulse_recv_mode(hal->regs, deli->flags.start_bit_included, + deli->flags.end_bit_included, + !deli->flags.has_end_pulse, + deli->flags.pulse_invert); + parlio_ll_rx_treat_data_line_as_en(hal->regs, deli->valid_sig_line_id); + break; + default: + /* Select the soft receive mode */ + parlio_ll_rx_set_soft_recv_mode(hal->regs); + break; + } + + /* Set EOF configuration */ + if (deli->eof_data_len) { + /* If EOF data length specified, set the eof condition to data length and set data bytes */ + parlio_ll_rx_set_recv_bit_len(hal->regs, deli->eof_data_len * 8); + parlio_ll_rx_set_eof_condition(hal->regs, PARLIO_LL_RX_EOF_COND_RX_FULL); + } else { + /* If EOF data length not specified, set the eof condition to the external enable signal */ + parlio_ll_rx_set_eof_condition(hal->regs, PARLIO_LL_RX_EOF_COND_EN_INACTIVE); + } + + /* Set timeout configuration */ + if (deli->timeout_ticks) { + parlio_ll_rx_enable_timeout(hal->regs, true); + parlio_ll_rx_set_timeout_thres(hal->regs, deli->timeout_ticks); + } else { + parlio_ll_rx_enable_timeout(hal->regs, false); + } + + /* Set the validation signal if the validation signal number is set for level or pulse delimiter */ + if (deli->mode != PARLIO_RX_SOFT_MODE) { + esp_rom_gpio_connect_in_signal(rx_unit->cfg.valid_gpio_num, deli->valid_sig, false); + /* Update the valid_sig_line_num */ + parlio_ll_rx_treat_data_line_as_en(hal->regs, deli->valid_sig_line_id); + } + + /* Update/synchronize the new configurations */ + parlio_ll_rx_update_config(hal->regs); +} + +static esp_err_t s_parlio_rx_unit_set_gpio(parlio_rx_unit_handle_t rx_unit, const parlio_rx_unit_config_t *config) +{ + int group_id = rx_unit->base.group->group_id; + int unit_id = rx_unit->base.unit_id; + /* Default GPIO configuration */ + gpio_config_t gpio_conf = { + .intr_type = GPIO_INTR_DISABLE, + .pull_down_en = false, + .pull_up_en = true, + }; + + /* When the source clock comes from external, enable the gpio input direction and connect to the clock input signal */ + if (config->clk_src == PARLIO_CLK_SRC_EXTERNAL) { + ESP_RETURN_ON_FALSE(config->clk_in_gpio_num >= 0, ESP_ERR_INVALID_ARG, TAG, "clk_in_gpio_num must be set while the clock input from external"); + /* Connect the clock in signal to the GPIO matrix if it is set */ + if (!config->flags.io_no_init) { + gpio_conf.mode = config->flags.io_loop_back ? GPIO_MODE_INPUT_OUTPUT : GPIO_MODE_INPUT; + gpio_conf.pin_bit_mask = BIT64(config->clk_in_gpio_num); + ESP_RETURN_ON_ERROR(gpio_config(&gpio_conf), TAG, "config clk in GPIO failed"); + } + esp_rom_gpio_connect_in_signal(config->clk_in_gpio_num, + parlio_periph_signals.groups[group_id].rx_units[unit_id].clk_in_sig, false); + } + /* When the source clock comes from internal and supported to output the internal clock, + * enable the gpio output direction and connect to the clock output signal */ + if (config->clk_out_gpio_num >= 0) { +#if SOC_PARLIO_RX_CLK_SUPPORT_OUTPUT + gpio_conf.mode = config->flags.io_loop_back ? GPIO_MODE_INPUT_OUTPUT : GPIO_MODE_OUTPUT; + gpio_conf.pin_bit_mask = BIT64(config->clk_out_gpio_num); + ESP_RETURN_ON_ERROR(gpio_config(&gpio_conf), TAG, "config clk out GPIO failed"); + esp_rom_gpio_connect_out_signal(config->clk_out_gpio_num, + parlio_periph_signals.groups[group_id].rx_units[unit_id].clk_out_sig, false, false); +#else + ESP_RETURN_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, TAG, "this target not support to output the clock"); +#endif // SOC_PARLIO_RX_CLK_SUPPORT_OUTPUT + } + + gpio_conf.mode = config->flags.io_loop_back ? GPIO_MODE_INPUT_OUTPUT : GPIO_MODE_INPUT; + /* Initialize the valid GPIO as input */ + if (config->valid_gpio_num >= 0) { + if (!config->flags.io_no_init) { + gpio_conf.pin_bit_mask = BIT64(config->valid_gpio_num); + ESP_RETURN_ON_ERROR(gpio_config(&gpio_conf), TAG, "config data GPIO failed"); + } + /* Not connect the signal here, the signal is lazy connected until the delimiter takes effect */ + } + + /* Initialize the data GPIO as input and bind them to the corresponding data line signals */ + for (int i = 0; i < config->data_width; i++) { + /* Loop the data_gpio_nums to connect data and valid signals via GPIO matrix */ + if (config->data_gpio_nums[i] >= 0) { + if (!config->flags.io_no_init) { + gpio_conf.pin_bit_mask = BIT64(config->data_gpio_nums[i]); + ESP_RETURN_ON_ERROR(gpio_config(&gpio_conf), TAG, "config data GPIO failed"); + gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[config->data_gpio_nums[i]], PIN_FUNC_GPIO); + } + esp_rom_gpio_connect_in_signal(config->data_gpio_nums[i], + parlio_periph_signals.groups[group_id].rx_units[unit_id].data_sigs[i], false); + } else { + ESP_LOGW(TAG, "data line %d not assigned", i); + } + } + + return ESP_OK; +} + +static IRAM_ATTR bool s_parlio_rx_default_eof_callback(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data) +{ + parlio_rx_unit_handle_t rx_unit = (parlio_rx_unit_handle_t)user_data; + BaseType_t high_task_woken = pdFALSE; + bool need_yield = false; + + parlio_rx_event_data_t evt_data = { + .delimiter = rx_unit->curr_trans.delimiter, + }; + + if (event_data->flags.abnormal_eof) { + /* If received an abnormal EOF, it's a timeout event on parlio RX */ + if (rx_unit->cbs.on_timeout) { + need_yield |= rx_unit->cbs.on_timeout(rx_unit, &evt_data, rx_unit->user_data); + } + } else { + /* If received a normal EOF, it's a receive done event on parlio RX */ + if (rx_unit->cbs.on_receive_done) { + evt_data.data = rx_unit->usr_recv_buf; + evt_data.recv_bytes = rx_unit->curr_trans.recv_bytes; + need_yield |= rx_unit->cbs.on_receive_done(rx_unit, &evt_data, rx_unit->user_data); + } + } + + if (rx_unit->curr_trans.flags.infinite) { + /* For infinite transactions, reset the receiving bytes when the transaction is done */ + rx_unit->curr_trans.recv_bytes = 0; + } else { + parlio_rx_transaction_t next_trans = {}; + /* The current transaction finished, try to get the next transaction from the transaction queue */ + if (xQueueReceiveFromISR(rx_unit->trans_que, &next_trans, &high_task_woken) == pdTRUE) { + if (rx_unit->cfg.flags.free_clk) { + parlio_ll_rx_enable_clock(rx_unit->base.group->hal.regs, false); + } + /* If the delimiter of the next transaction is not same as the current one, need to re-config the hardware */ + if (next_trans.delimiter != rx_unit->curr_trans.delimiter) { + s_parlio_set_delimiter_config(rx_unit, next_trans.delimiter); + } + /* Mount the new transaction buffer and start the new transaction */ + s_parlio_mount_transaction_buffer(rx_unit, &next_trans); + gdma_start(rx_unit->dma_chan, (intptr_t)rx_unit->dma_descs); + if (rx_unit->cfg.flags.free_clk) { + parlio_ll_rx_start(rx_unit->base.group->hal.regs, true); + parlio_ll_rx_enable_clock(rx_unit->base.group->hal.regs, true); + } + } else if (rx_unit->curr_trans.delimiter) { // Add condition in case the curr_trans has been cleared in the last timeout isr + /* No more transaction pending to receive, clear the current transaction */ + portENTER_CRITICAL_ISR(&s_rx_spinlock); + rx_unit->curr_trans.delimiter->under_using = false; + memset(&rx_unit->curr_trans, 0, sizeof(parlio_rx_transaction_t)); + portEXIT_CRITICAL_ISR(&s_rx_spinlock); + need_yield |= high_task_woken == pdTRUE; + xSemaphoreGiveFromISR(rx_unit->trans_sem, &high_task_woken); + } + } + + need_yield |= high_task_woken == pdTRUE; + return need_yield; +} + +static IRAM_ATTR bool s_parlio_rx_default_desc_done_callback(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data) +{ + parlio_rx_unit_handle_t rx_unit = (parlio_rx_unit_handle_t)user_data; + bool need_yield = false; + /* No need to process the data if error EOF (i.e. timeout) happened */ + if (event_data->flags.abnormal_eof) { + return false; + } + + /* Get the finished descriptor from the current descriptor */ + dma_descriptor_t *finished_desc = rx_unit->curr_desc; + parlio_rx_event_data_t evt_data = { + .delimiter = rx_unit->curr_trans.delimiter, + .data = finished_desc->buffer, + .recv_bytes = finished_desc->dw0.length, + }; + if (rx_unit->cbs.on_partial_receive) { + need_yield |= rx_unit->cbs.on_partial_receive(rx_unit, &evt_data, rx_unit->user_data); + } + /* For the infinite transaction, need to copy the data in DMA buffer to the user receiving buffer */ + if (rx_unit->curr_trans.flags.infinite && rx_unit->curr_trans.flags.indirect_mount) { + memcpy(rx_unit->usr_recv_buf + rx_unit->curr_trans.recv_bytes, evt_data.data, evt_data.recv_bytes); + } else { + portENTER_CRITICAL_ISR(&s_rx_spinlock); + rx_unit->curr_trans.delimiter->under_using = false; + portEXIT_CRITICAL_ISR(&s_rx_spinlock); + } + /* Update received bytes */ + if (rx_unit->curr_trans.recv_bytes >= rx_unit->curr_trans.size) { + rx_unit->curr_trans.recv_bytes = 0; + } + rx_unit->curr_trans.recv_bytes += evt_data.recv_bytes; + /* Move to the next DMA descriptor */ + rx_unit->curr_desc = rx_unit->curr_desc->next; + + return need_yield; +} + +static esp_err_t s_parlio_rx_create_dma_descriptors(parlio_rx_unit_handle_t rx_unit, uint32_t max_recv_size) +{ + ESP_RETURN_ON_FALSE(rx_unit, ESP_ERR_INVALID_ARG, TAG, "invalid param"); + + uint32_t desc_num = max_recv_size / DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED + 1; + /* set at least 2 descriptors */ + if (desc_num < 2) { + desc_num = 4; + } + rx_unit->desc_num = desc_num; + + /* Allocated and link the descriptor nodes */ + rx_unit->dma_descs = (dma_descriptor_t *)heap_caps_calloc(desc_num, sizeof(dma_descriptor_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA); + ESP_RETURN_ON_FALSE(rx_unit->dma_descs, ESP_ERR_NO_MEM, TAG, "no memory for DMA descriptors"); + + rx_unit->max_recv_size = max_recv_size; + + return ESP_OK; +} + +static esp_err_t s_parlio_rx_unit_init_dma(parlio_rx_unit_handle_t rx_unit) +{ + /* Allocate and connect the GDMA channel */ + gdma_channel_alloc_config_t dma_chan_config = { + .direction = GDMA_CHANNEL_DIRECTION_RX, + }; + ESP_RETURN_ON_ERROR(gdma_new_channel(&dma_chan_config, &rx_unit->dma_chan), TAG, "allocate RX DMA channel failed"); + gdma_connect(rx_unit->dma_chan, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_PARLIO, 0)); + + /* Set GDMA strategy */ + gdma_strategy_config_t gdma_strategy_conf = { + .auto_update_desc = true, + .owner_check = false, // no need to check owner + }; + gdma_apply_strategy(rx_unit->dma_chan, &gdma_strategy_conf); + + /* Register callbacks */ + gdma_rx_event_callbacks_t cbs = { + .on_recv_eof = s_parlio_rx_default_eof_callback, + .on_recv_done = s_parlio_rx_default_desc_done_callback, + }; + gdma_register_rx_event_callbacks(rx_unit->dma_chan, &cbs, rx_unit); + + return ESP_OK; +} + +static esp_err_t s_parlio_select_periph_clock(parlio_rx_unit_handle_t rx_unit, const parlio_rx_unit_config_t *config) +{ + parlio_hal_context_t *hal = &rx_unit->base.group->hal; + parlio_clock_source_t clk_src = config->clk_src; + uint32_t src_freq_hz = 0; + uint32_t exp_freq_hz = 0; + hal_utils_clk_div_t clk_div = { + .integer = 1, + }; + /* if the source clock is input from the GPIO, then we're in the slave mode */ + if (clk_src != PARLIO_CLK_SRC_EXTERNAL) { + ESP_RETURN_ON_FALSE(config->exp_clk_freq_hz, ESP_ERR_INVALID_ARG, TAG, "output clock frequency not set"); + exp_freq_hz = config->exp_clk_freq_hz; + /* get the internal clock source frequency */ + esp_clk_tree_src_get_freq_hz(clk_src, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &src_freq_hz); + } else { + ESP_RETURN_ON_FALSE(config->ext_clk_freq_hz, ESP_ERR_INVALID_ARG, TAG, "input clock frequency not set"); + exp_freq_hz = config->exp_clk_freq_hz > 0 ? config->exp_clk_freq_hz : config->ext_clk_freq_hz; + src_freq_hz = config->ext_clk_freq_hz; + } + /* set clock division, round up */ + hal_utils_clk_info_t clk_info = { + .src_freq_hz = src_freq_hz, + .exp_freq_hz = exp_freq_hz, + .max_integ = PARLIO_LL_RX_MAX_CLK_INT_DIV, + .min_integ = 1, + .round_opt = HAL_DIV_ROUND, + }; +#if PARLIO_LL_RX_MAX_CLK_FRACT_DIV + clk_info.max_fract = PARLIO_LL_RX_MAX_CLK_FRACT_DIV; + rx_unit->cfg.exp_clk_freq_hz = hal_utils_calc_clk_div_frac_accurate(&clk_info, &clk_div); +#else + rx_unit->cfg.exp_clk_freq_hz = hal_utils_calc_clk_div_integer(&clk_info, &clk_div.integer); +#endif + +#if CONFIG_PM_ENABLE + if (clk_src != PARLIO_CLK_SRC_EXTERNAL) { + /* XTAL and PLL clock source will be turned off in light sleep, so we need to create a NO_LIGHT_SLEEP lock */ + sprintf(rx_unit->pm_lock_name, "parlio_rx_%d_%d", rx_unit->base.group->group_id, rx_unit->base.unit_id); // e.g. parlio_rx_0_0 + esp_err_t ret = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, rx_unit->pm_lock_name, &rx_unit->pm_lock); + ESP_RETURN_ON_ERROR(ret, TAG, "create NO_LIGHT_SLEEP lock failed"); + } +#endif + + /* Set clock configuration */ + parlio_ll_rx_set_clock_source(hal->regs, clk_src); + parlio_ll_rx_set_clock_div(hal->regs, &clk_div); + + rx_unit->clk_src = clk_src; + /* warning if precision lost due to division */ + if ((clk_src != PARLIO_CLK_SRC_EXTERNAL) && + (config->exp_clk_freq_hz != rx_unit->cfg.exp_clk_freq_hz)) { + ESP_LOGW(TAG, "precision loss, real output frequency: %"PRIu32, rx_unit->cfg.exp_clk_freq_hz); + } + + return ESP_OK; +} + +static esp_err_t s_parlio_destroy_rx_unit(parlio_rx_unit_handle_t rx_unit) +{ + /* Free the transaction queue */ + if (rx_unit->trans_que) { + vQueueDeleteWithCaps(rx_unit->trans_que); + } + /* Free the mutex lock */ + if (rx_unit->mutex) { + vSemaphoreDeleteWithCaps(rx_unit->mutex); + } + /* Free the transaction semaphore */ + if (rx_unit->trans_sem) { + vSemaphoreDeleteWithCaps(rx_unit->trans_sem); + } + /* Free the power management lock */ + if (rx_unit->pm_lock) { + ESP_RETURN_ON_ERROR(esp_pm_lock_delete(rx_unit->pm_lock), TAG, "delete pm lock failed"); + } + /* Delete the GDMA channel */ + if (rx_unit->dma_chan) { + ESP_RETURN_ON_ERROR(gdma_disconnect(rx_unit->dma_chan), TAG, "disconnect dma channel failed"); + ESP_RETURN_ON_ERROR(gdma_del_channel(rx_unit->dma_chan), TAG, "delete dma channel failed"); + } + /* Free the DMA descriptors */ + if (rx_unit->dma_descs) { + free(rx_unit->dma_descs); + } + /* Free the internal DMA buffer */ + if (rx_unit->dma_buf) { + free(rx_unit->dma_buf); + } + /* Unregister the RX unit from the PARLIO group */ + if (rx_unit->base.group) { + parlio_unregister_unit_from_group(&rx_unit->base); + } + /* Free the RX unit */ + free(rx_unit); + return ESP_OK; +} + +esp_err_t parlio_new_rx_unit(const parlio_rx_unit_config_t *config, parlio_rx_unit_handle_t *ret_unit) +{ +#if CONFIG_PARLIO_ENABLE_DEBUG_LOG + esp_log_level_set(TAG, ESP_LOG_DEBUG); +#endif + ESP_RETURN_ON_FALSE(config && ret_unit, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + /* Check the data width to be the the power of 2 */ + ESP_RETURN_ON_FALSE(__builtin_popcount(config->data_width) == 1, ESP_ERR_INVALID_ARG, TAG, + "data line number should be the power of 2 without counting valid signal"); + ESP_RETURN_ON_FALSE(config->data_width <= (int)PARLIO_RX_UNIT_MAX_DATA_WIDTH, ESP_ERR_INVALID_ARG, TAG, + "data line number should be within %d", (int)PARLIO_RX_UNIT_MAX_DATA_WIDTH); + + esp_err_t ret = ESP_OK; + parlio_rx_unit_handle_t unit = NULL; + + /* Allocate unit memory */ + unit = heap_caps_calloc(1, sizeof(parlio_rx_unit_t), PARLIO_MEM_ALLOC_CAPS); + ESP_GOTO_ON_FALSE(unit, ESP_ERR_NO_MEM, err, TAG, "no memory for rx unit"); + unit->base.dir = PARLIO_DIR_RX; + unit->is_enabled = false; + + /* Initialize mutex lock */ + unit->mutex = xSemaphoreCreateMutexWithCaps(PARLIO_MEM_ALLOC_CAPS); + ESP_GOTO_ON_FALSE(unit->mutex, ESP_ERR_NO_MEM, err, TAG, "no memory for mutex semaphore"); + /* Create transaction binary semaphore */ + unit->trans_sem = xSemaphoreCreateBinaryWithCaps(PARLIO_MEM_ALLOC_CAPS); + ESP_GOTO_ON_FALSE(unit->trans_sem, ESP_ERR_NO_MEM, err, TAG, "no memory for transaction semaphore"); + xSemaphoreGive(unit->trans_sem); + + /* Create the transaction queue. Choose `parlio_rx_transaction_t` as the queue element instead of its pointer + * Because the queue will do the copy to the element, no need to worry about the item in the queue will expire, + * so that we don't have to allocate additional memory to store the transaction. */ + unit->trans_que = xQueueCreateWithCaps(config->trans_queue_depth, sizeof(parlio_rx_transaction_t), PARLIO_MEM_ALLOC_CAPS); + ESP_GOTO_ON_FALSE(unit->trans_que, ESP_ERR_NO_MEM, err, TAG, "no memory for transaction queue"); + + ESP_GOTO_ON_ERROR(s_parlio_rx_create_dma_descriptors(unit, config->max_recv_size), err, TAG, "create dma descriptor failed"); + /* Register and attach the rx unit to the group */ + ESP_GOTO_ON_ERROR(parlio_register_unit_to_group(&unit->base), err, TAG, "failed to register the rx unit to the group"); + memcpy(&unit->cfg, config, sizeof(parlio_rx_unit_config_t)); + /* If not using external clock source, the internal clock is always a free running clock */ + if (config->clk_src != PARLIO_CLK_SRC_EXTERNAL) { + unit->cfg.flags.free_clk = 1; + } + + parlio_group_t *group = unit->base.group; + parlio_hal_context_t *hal = &group->hal; + /* Initialize GPIO */ + ESP_GOTO_ON_ERROR(s_parlio_rx_unit_set_gpio(unit, config), err, TAG, "failed to set GPIO"); + /* Install DMA service */ + ESP_GOTO_ON_ERROR(s_parlio_rx_unit_init_dma(unit), err, TAG, "install rx DMA failed"); + /* Reset RX module */ + parlio_ll_rx_reset_clock(hal->regs); + parlio_ll_rx_reset_fifo(hal->regs); + parlio_ll_rx_enable_clock(hal->regs, false); + parlio_ll_rx_start(hal->regs, false); + /* parlio_ll_clock_source_t and parlio_clock_source_t are binary compatible if the clock source is from internal */ + ESP_GOTO_ON_ERROR(s_parlio_select_periph_clock(unit, config), err, TAG, "set clock source failed"); + /* Set the data width */ + parlio_ll_rx_set_bus_width(hal->regs, config->data_width); +#if SOC_PARLIO_RX_CLK_SUPPORT_GATING + parlio_ll_rx_enable_clock_gating(hal->regs, config->flags.clk_gate_en); +#else + if (config->flags.clk_gate_en) { + ESP_LOGW(TAG, "The current target does not support clock gating"); + } +#endif // SOC_PARLIO_RX_CLK_SUPPORT_GATING + + /* return RX unit handle */ + *ret_unit = unit; + + ESP_LOGD(TAG, "new rx unit(%d,%d) at %p, trans_queue_depth=%zu", + group->group_id, unit->base.unit_id, (void *)unit, unit->cfg.trans_queue_depth); + return ESP_OK; + +err: + if (unit) { + s_parlio_destroy_rx_unit(unit); + } + return ret; +} + +esp_err_t parlio_del_rx_unit(parlio_rx_unit_handle_t rx_unit) +{ + ESP_RETURN_ON_FALSE(rx_unit, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + // Not necessary to take the semaphore while checking the flag because it's going to be deleted + ESP_RETURN_ON_FALSE(!rx_unit->is_enabled, ESP_ERR_INVALID_STATE, TAG, "the unit has not disabled"); + + ESP_LOGD(TAG, "del rx unit (%d, %d)", rx_unit->base.group->group_id, rx_unit->base.unit_id); + return s_parlio_destroy_rx_unit(rx_unit); +} + +esp_err_t parlio_rx_unit_enable(parlio_rx_unit_handle_t rx_unit, bool reset_queue) +{ + ESP_RETURN_ON_FALSE(rx_unit, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + + esp_err_t ret = ESP_OK; + parlio_hal_context_t *hal = &rx_unit->base.group->hal; + + xSemaphoreTake(rx_unit->mutex, portMAX_DELAY); + ESP_GOTO_ON_FALSE(!rx_unit->is_enabled, ESP_ERR_INVALID_STATE, err, TAG, "the unit has enabled or running"); + rx_unit->is_enabled = true; + + /* Acquire the power management lock incase */ + if (rx_unit->pm_lock) { + esp_pm_lock_acquire(rx_unit->pm_lock); + } + + /* For non-free running clock, the unit can't stop once enabled, otherwise the data alignment will go wrong */ + if (!rx_unit->cfg.flags.free_clk) { + parlio_ll_rx_reset_fifo(hal->regs); + parlio_ll_rx_start(hal->regs, true); + parlio_ll_rx_enable_clock(hal->regs, true); + } + + /* Check if we need to start a pending transaction */ + parlio_rx_transaction_t trans = {}; + if (reset_queue) { + xQueueReset(rx_unit->trans_que); + xSemaphoreGive(rx_unit->trans_sem); + } else if (xQueueReceive(rx_unit->trans_que, &trans, 0) == pdTRUE) { + // The semaphore always supposed to be taken successfully + assert(xSemaphoreTake(rx_unit->trans_sem, 0) == pdTRUE); + if (rx_unit->cfg.flags.free_clk) { + parlio_ll_rx_enable_clock(hal->regs, false); + } + s_parlio_set_delimiter_config(rx_unit, trans.delimiter); + s_parlio_mount_transaction_buffer(rx_unit, &trans); + gdma_start(rx_unit->dma_chan, (intptr_t)rx_unit->curr_desc); + if (rx_unit->cfg.flags.free_clk) { + parlio_ll_rx_start(hal->regs, true); + parlio_ll_rx_enable_clock(hal->regs, true); + } + } +err: + xSemaphoreGive(rx_unit->mutex); + + return ret; +} + +esp_err_t parlio_rx_unit_disable(parlio_rx_unit_handle_t rx_unit) +{ + ESP_RETURN_ON_FALSE(rx_unit, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + + esp_err_t ret = ESP_OK; + parlio_hal_context_t *hal = &rx_unit->base.group->hal; + + xSemaphoreTake(rx_unit->mutex, portMAX_DELAY); + ESP_GOTO_ON_FALSE(rx_unit->is_enabled, ESP_ERR_INVALID_STATE, err, TAG, "the unit has disabled"); + rx_unit->is_enabled = false; + /* stop the RX engine */ + gdma_stop(rx_unit->dma_chan); + parlio_ll_rx_enable_clock(hal->regs, false); + parlio_ll_rx_start(hal->regs, false); + if (rx_unit->curr_trans.delimiter) { + portENTER_CRITICAL(&s_rx_spinlock); + rx_unit->curr_trans.delimiter->under_using = false; + portEXIT_CRITICAL(&s_rx_spinlock); + } + xSemaphoreGive(rx_unit->trans_sem); + + /* For continuous receiving, free the temporary buffer and stop the DMA */ + if (rx_unit->dma_buf) { + free(rx_unit->dma_buf); + rx_unit->dma_buf = NULL; + } + /* release power management lock */ + if (rx_unit->pm_lock) { + esp_pm_lock_release(rx_unit->pm_lock); + } + /* Erase the current transaction */ + memset(&rx_unit->curr_trans, 0, sizeof(parlio_rx_transaction_t)); +err: + xSemaphoreGive(rx_unit->mutex); + + return ret; +} + +esp_err_t parlio_new_rx_level_delimiter(const parlio_rx_level_delimiter_config_t *config, + parlio_rx_delimiter_handle_t *ret_delimiter) +{ + ESP_RETURN_ON_FALSE(config && ret_delimiter, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + /* Validation signal line must specified for level delimiter */ + ESP_RETURN_ON_FALSE(config->valid_sig_line_id < PARLIO_RX_UNIT_MAX_DATA_WIDTH, + ESP_ERR_INVALID_ARG, TAG, "no valid signal line specified"); + + parlio_rx_delimiter_handle_t delimiter = NULL; + + /* Allocate memory for the delimiter */ + delimiter = (parlio_rx_delimiter_handle_t)heap_caps_calloc(1, sizeof(parlio_rx_delimiter_t), PARLIO_MEM_ALLOC_CAPS); + ESP_RETURN_ON_FALSE(delimiter, ESP_ERR_NO_MEM, TAG, "no memory for rx delimiter"); + + /* Assign configuration for the level delimiter */ + delimiter->mode = PARLIO_RX_LEVEL_MODE; + delimiter->valid_sig_line_id = config->valid_sig_line_id; + delimiter->sample_edge = config->sample_edge; + delimiter->bit_pack_order = config->bit_pack_order; + delimiter->eof_data_len = config->eof_data_len; + delimiter->timeout_ticks = config->timeout_ticks; + delimiter->flags.active_low_en = config->flags.active_low_en; + + *ret_delimiter = delimiter; + + return ESP_OK; +} + +esp_err_t parlio_new_rx_pulse_delimiter(const parlio_rx_pulse_delimiter_config_t *config, + parlio_rx_delimiter_handle_t *ret_delimiter) +{ + ESP_RETURN_ON_FALSE(config && ret_delimiter, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + /* Validation signal line must specified for pulse delimiter */ + ESP_RETURN_ON_FALSE(config->valid_sig_line_id < PARLIO_RX_UNIT_MAX_DATA_WIDTH, + ESP_ERR_INVALID_ARG, TAG, "no valid signal line specified"); + /* Guarantee there is an end symbol, end by length or pulse */ + ESP_RETURN_ON_FALSE(config->eof_data_len || config->flags.has_end_pulse, + ESP_ERR_INVALID_ARG, TAG, "Either eof_data_len or has_end_pulse should be set"); + /* If end by length, the maximum length is limited */ + ESP_RETURN_ON_FALSE(config->eof_data_len <= PARLIO_LL_RX_MAX_BYTES_PER_FRAME, ESP_ERR_INVALID_ARG, + TAG, "EOF data length exceed the max value %d", PARLIO_LL_RX_MAX_BYTES_PER_FRAME); + + parlio_rx_delimiter_handle_t delimiter = NULL; + + /* Allocate memory for the delimiter */ + delimiter = (parlio_rx_delimiter_handle_t)heap_caps_calloc(1, sizeof(parlio_rx_delimiter_t), PARLIO_MEM_ALLOC_CAPS); + ESP_RETURN_ON_FALSE(delimiter, ESP_ERR_NO_MEM, TAG, "no memory for rx delimiter"); + + /* Assign configuration for the pulse delimiter */ + delimiter->mode = PARLIO_RX_PULSE_MODE; + delimiter->valid_sig_line_id = config->valid_sig_line_id; + delimiter->sample_edge = config->sample_edge; + delimiter->bit_pack_order = config->bit_pack_order; + delimiter->eof_data_len = config->eof_data_len; + delimiter->timeout_ticks = config->timeout_ticks; + delimiter->flags.start_bit_included = config->flags.start_bit_included; + delimiter->flags.has_end_pulse = config->flags.has_end_pulse; + delimiter->flags.end_bit_included = config->flags.end_bit_included; + delimiter->flags.pulse_invert = config->flags.pulse_invert; + + *ret_delimiter = delimiter; + + return ESP_OK; +} + +esp_err_t parlio_new_rx_soft_delimiter(const parlio_rx_soft_delimiter_config_t *config, + parlio_rx_delimiter_handle_t *ret_delimiter) +{ + ESP_RETURN_ON_FALSE(config && ret_delimiter, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + /* The soft delimiter can only end by length, EOF length should be within range (0, PARLIO_LL_RX_MAX_BYTES_PER_FRAME] */ + ESP_RETURN_ON_FALSE(config->eof_data_len > 0 && config->eof_data_len <= PARLIO_LL_RX_MAX_BYTES_PER_FRAME, ESP_ERR_INVALID_ARG, + TAG, "EOF data length is 0 or exceed the max value %d", PARLIO_LL_RX_MAX_BYTES_PER_FRAME); + + parlio_rx_delimiter_handle_t delimiter = NULL; + + /* Allocate memory for the delimiter */ + delimiter = (parlio_rx_delimiter_handle_t)heap_caps_calloc(1, sizeof(parlio_rx_delimiter_t), PARLIO_MEM_ALLOC_CAPS); + ESP_RETURN_ON_FALSE(delimiter, ESP_ERR_NO_MEM, TAG, "no memory for rx delimiter"); + + /* Assign configuration for the soft delimiter */ + delimiter->mode = PARLIO_RX_SOFT_MODE; + delimiter->under_using = false; + delimiter->sample_edge = config->sample_edge; + delimiter->bit_pack_order = config->bit_pack_order; + delimiter->eof_data_len = config->eof_data_len; + delimiter->timeout_ticks = config->timeout_ticks; + + *ret_delimiter = delimiter; + + return ESP_OK; +} + +esp_err_t parlio_rx_soft_delimiter_start_stop(parlio_rx_unit_handle_t rx_unit, parlio_rx_delimiter_handle_t delimiter, bool start_stop) +{ + ESP_RETURN_ON_FALSE(rx_unit && delimiter, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + ESP_RETURN_ON_FALSE(delimiter->mode == PARLIO_RX_SOFT_MODE, ESP_ERR_INVALID_ARG, TAG, "The delimiter is not soft delimiter"); + + esp_err_t ret = ESP_OK; + + xSemaphoreTake(rx_unit->mutex, portMAX_DELAY); + ESP_GOTO_ON_FALSE(rx_unit->is_enabled, ESP_ERR_INVALID_STATE, err, TAG, "the unit has not enabled"); + parlio_hal_context_t *hal = &(rx_unit->base.group->hal); + parlio_ll_rx_start_soft_recv(hal->regs, start_stop); +err: + xSemaphoreGive(rx_unit->mutex); + return ret; +} + +esp_err_t parlio_del_rx_delimiter(parlio_rx_delimiter_handle_t delimiter) +{ + ESP_RETURN_ON_FALSE(delimiter, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + ESP_RETURN_ON_FALSE(!delimiter->under_using, ESP_ERR_INVALID_STATE, TAG, "the delimiter is under using"); + free(delimiter); + return ESP_OK; +} + +static esp_err_t s_parlio_rx_unit_do_transaction(parlio_rx_unit_handle_t rx_unit, parlio_rx_transaction_t *trans) +{ + bool is_stopped = false; + /* Get whether DMA stopped atomically */ + portENTER_CRITICAL_ISR(&s_rx_spinlock); + is_stopped = rx_unit->curr_trans.delimiter == NULL; + portEXIT_CRITICAL_ISR(&s_rx_spinlock); + if (is_stopped) { + if (rx_unit->cfg.flags.free_clk) { + parlio_ll_rx_enable_clock(rx_unit->base.group->hal.regs, false); + } + if (trans->delimiter != rx_unit->curr_trans.delimiter) { + s_parlio_set_delimiter_config(rx_unit, trans->delimiter); + } + s_parlio_mount_transaction_buffer(rx_unit, trans); + // Take semaphore without block time here, only indicate there are transactions on receiving + xSemaphoreTake(rx_unit->trans_sem, 0); + gdma_start(rx_unit->dma_chan, (intptr_t)rx_unit->curr_desc); + if (rx_unit->cfg.flags.free_clk) { + parlio_ll_rx_start(rx_unit->base.group->hal.regs, true); + parlio_ll_rx_enable_clock(rx_unit->base.group->hal.regs, true); + } + } else { // Otherwise send to the queue + /* Send the transaction to the queue */ + ESP_RETURN_ON_FALSE(xQueueSend(rx_unit->trans_que, trans, 0) == pdTRUE, + ESP_ERR_INVALID_STATE, TAG, "transaction queue is full, failed to send transaction to the queue"); + } + return ESP_OK; +} + +esp_err_t parlio_rx_unit_receive(parlio_rx_unit_handle_t rx_unit, + void *payload, + size_t payload_size, + const parlio_receive_config_t* recv_cfg) +{ + ESP_RETURN_ON_FALSE(rx_unit && payload && recv_cfg, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + ESP_RETURN_ON_FALSE(recv_cfg->delimiter, ESP_ERR_INVALID_ARG, TAG, "no delimiter specified"); + ESP_RETURN_ON_FALSE(payload_size <= rx_unit->max_recv_size, ESP_ERR_INVALID_ARG, TAG, "trans length too large"); +#if CONFIG_GDMA_ISR_IRAM_SAFE + ESP_RETURN_ON_FALSE(esp_ptr_internal(payload), ESP_ERR_INVALID_ARG, TAG, "payload not in internal RAM"); +#endif + if (recv_cfg->delimiter->eof_data_len) { + ESP_RETURN_ON_FALSE(payload_size >= recv_cfg->delimiter->eof_data_len, ESP_ERR_INVALID_ARG, + TAG, "payload size should be greater than eof_data_len"); + } + if (recv_cfg->delimiter->mode != PARLIO_RX_SOFT_MODE) { + ESP_RETURN_ON_FALSE(rx_unit->cfg.valid_gpio_num >= 0, ESP_ERR_INVALID_ARG, TAG, "The validate gpio of this unit is not set"); + /* Check if the valid_sig_line_id is equal or greater than data width, otherwise valid_sig_line_id is conflict with data signal. + * Specifically, level or pulse delimiter requires one data line as valid signal, so these two delimiters can't support PARLIO_RX_UNIT_MAX_DATA_WIDTH */ + ESP_RETURN_ON_FALSE(recv_cfg->delimiter->valid_sig_line_id >= rx_unit->cfg.data_width, + ESP_ERR_INVALID_ARG, TAG, "the valid_sig_line_id of this delimiter is conflict with rx unit data width"); + /* Assign the signal here to ensure iram safe */ + recv_cfg->delimiter->valid_sig = parlio_periph_signals.groups[rx_unit->base.group->group_id]. + rx_units[rx_unit->base.unit_id]. + data_sigs[recv_cfg->delimiter->valid_sig_line_id]; + } + void *p_buffer = payload; + + /* Create the internal DMA buffer for the infinite transaction if indirect_mount is set */ + if (recv_cfg->flags.partial_rx_en && recv_cfg->flags.indirect_mount) { + ESP_RETURN_ON_FALSE(!rx_unit->dma_buf, ESP_ERR_INVALID_STATE, TAG, "infinite transaction is using the internal DMA buffer"); + /* Allocate the internal DMA buffer to store the data temporary */ + rx_unit->dma_buf = heap_caps_calloc(1, payload_size, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA); + ESP_RETURN_ON_FALSE(rx_unit->dma_buf, ESP_ERR_NO_MEM, TAG, "No memory for the internal DMA buffer"); + /* Use the internal DMA buffer so that the user buffer can always be available */ + p_buffer = rx_unit->dma_buf; + } + + /* Create the transaction */ + parlio_rx_transaction_t transaction = { + .delimiter = recv_cfg->delimiter, + .payload = p_buffer, + .size = payload_size, + .recv_bytes = 0, + .flags.infinite = recv_cfg->flags.partial_rx_en, + .flags.indirect_mount = recv_cfg->flags.indirect_mount, + }; + rx_unit->usr_recv_buf = payload; + + xSemaphoreTake(rx_unit->mutex, portMAX_DELAY); + esp_err_t ret = s_parlio_rx_unit_do_transaction(rx_unit, &transaction); + xSemaphoreGive(rx_unit->mutex); + return ret; +} + +esp_err_t parlio_rx_unit_wait_all_done(parlio_rx_unit_handle_t rx_unit, int timeout_ms) +{ + ESP_RETURN_ON_FALSE(rx_unit, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + + TickType_t ticks = timeout_ms < 0 ? portMAX_DELAY : pdMS_TO_TICKS(timeout_ms); + /* Waiting for the all transactions done */ + ESP_RETURN_ON_FALSE(xSemaphoreTake(rx_unit->trans_sem, ticks) == pdTRUE, ESP_ERR_TIMEOUT, TAG, "wait all transactions done timeout"); + /* Put back the signal */ + xSemaphoreGive(rx_unit->trans_sem); + + return ESP_OK; +} + +esp_err_t parlio_rx_unit_register_event_callbacks(parlio_rx_unit_handle_t rx_unit, const parlio_rx_event_callbacks_t *cbs, void *user_data) +{ + esp_err_t ret = ESP_OK; + + ESP_RETURN_ON_FALSE(rx_unit, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + ESP_RETURN_ON_FALSE(cbs, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + +#if CONFIG_PARLIO_ISR_IRAM_SAFE + ESP_RETURN_ON_FALSE(!cbs->on_partial_receive || esp_ptr_in_iram(cbs->on_partial_receive), ESP_ERR_INVALID_ARG, + TAG, "on_partial_receive not in IRAM"); + ESP_RETURN_ON_FALSE(!cbs->on_receive_done || esp_ptr_in_iram(cbs->on_receive_done), ESP_ERR_INVALID_ARG, + TAG, "on_receive_done not in IRAM"); + ESP_RETURN_ON_FALSE(!cbs->on_timeout || esp_ptr_in_iram(cbs->on_timeout), ESP_ERR_INVALID_ARG, + TAG, "on_timeout not in IRAM"); + ESP_RETURN_ON_FALSE(!user_data || esp_ptr_internal(user_data), ESP_ERR_INVALID_ARG, + TAG, "user_data not in internal RAM"); +#endif + xSemaphoreTake(rx_unit->mutex, portMAX_DELAY); + ESP_GOTO_ON_FALSE(!rx_unit->is_enabled, ESP_ERR_INVALID_STATE, err, TAG, "the unit has enabled or running"); + + memcpy(&rx_unit->cbs, cbs, sizeof(parlio_rx_event_callbacks_t)); + rx_unit->user_data = user_data; +err: + xSemaphoreGive(rx_unit->mutex); + return ret; +} diff --git a/components/driver/parlio/parlio_tx.c b/components/esp_driver_parlio/src/parlio_tx.c similarity index 91% rename from components/driver/parlio/parlio_tx.c rename to components/esp_driver_parlio/src/parlio_tx.c index 19ea3445cbb9..3ec006ab5ce3 100644 --- a/components/driver/parlio/parlio_tx.c +++ b/components/esp_driver_parlio/src/parlio_tx.c @@ -45,9 +45,8 @@ typedef struct { } parlio_tx_trans_desc_t; typedef struct parlio_tx_unit_t { - int unit_id; // unit id + struct parlio_unit_t base; // base unit size_t data_width; // data width - parlio_group_t *group; // group handle intr_handle_t intr; // allocated interrupt handle esp_pm_lock_handle_t pm_lock; // power management lock gdma_channel_handle_t dma_chan; // DMA channel @@ -71,44 +70,6 @@ typedef struct parlio_tx_unit_t { static void parlio_tx_default_isr(void *args); -static esp_err_t parlio_tx_register_to_group(parlio_tx_unit_t *unit) -{ - parlio_group_t *group = NULL; - int unit_id = -1; - for (int i = 0; i < SOC_PARLIO_GROUPS; i++) { - group = parlio_acquire_group_handle(i); - ESP_RETURN_ON_FALSE(group, ESP_ERR_NO_MEM, TAG, "no memory for group (%d)", i); - portENTER_CRITICAL(&group->spinlock); - for (int j = 0; j < SOC_PARLIO_TX_UNITS_PER_GROUP; j++) { - if (group->tx_units[j] == NULL) { - group->tx_units[j] = unit; - unit_id = j; - break; - } - } - portEXIT_CRITICAL(&group->spinlock); - if (unit_id < 0) { - // didn't find a free unit slot in the group - parlio_release_group_handle(group); - } else { - unit->unit_id = unit_id; - unit->group = group; - break; - } - } - ESP_RETURN_ON_FALSE(unit_id >= 0, ESP_ERR_NOT_FOUND, TAG, "no free tx unit"); - return ESP_OK; -} - -static void parlio_tx_unregister_to_group(parlio_tx_unit_t *unit, parlio_group_t *group) -{ - portENTER_CRITICAL(&group->spinlock); - group->tx_units[unit->unit_id] = NULL; - portEXIT_CRITICAL(&group->spinlock); - // the tx unit has a reference of the group, release it now - parlio_release_group_handle(group); -} - static esp_err_t parlio_tx_create_trans_queue(parlio_tx_unit_t *tx_unit, const parlio_tx_unit_config_t *config) { esp_err_t ret; @@ -157,9 +118,9 @@ static esp_err_t parlio_destroy_tx_unit(parlio_tx_unit_t *tx_unit) vQueueDeleteWithCaps(tx_unit->trans_queues[i]); } } - if (tx_unit->group) { + if (tx_unit->base.group) { // de-register from group - parlio_tx_unregister_to_group(tx_unit, tx_unit->group); + parlio_unregister_unit_from_group(&tx_unit->base); } free(tx_unit->dma_nodes); free(tx_unit); @@ -168,8 +129,8 @@ static esp_err_t parlio_destroy_tx_unit(parlio_tx_unit_t *tx_unit) static esp_err_t parlio_tx_unit_configure_gpio(parlio_tx_unit_t *tx_unit, const parlio_tx_unit_config_t *config) { - int group_id = tx_unit->group->group_id; - int unit_id = tx_unit->unit_id; + int group_id = tx_unit->base.group->group_id; + int unit_id = tx_unit->base.unit_id; gpio_config_t gpio_conf = { .intr_type = GPIO_INTR_DISABLE, .mode = config->flags.io_loop_back ? GPIO_MODE_INPUT_OUTPUT : GPIO_MODE_OUTPUT, @@ -185,6 +146,7 @@ static esp_err_t parlio_tx_unit_configure_gpio(parlio_tx_unit_t *tx_unit, const esp_rom_gpio_connect_out_signal(config->data_gpio_nums[i], parlio_periph_signals.groups[group_id].tx_units[unit_id].data_sigs[i], false, false); gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[config->data_gpio_nums[i]], PIN_FUNC_GPIO); + } } // Note: the valid signal will override TXD[PARLIO_LL_TX_DATA_LINE_AS_VALID_SIG] @@ -231,13 +193,11 @@ static esp_err_t parlio_tx_unit_init_dma(parlio_tx_unit_t *tx_unit) static esp_err_t parlio_select_periph_clock(parlio_tx_unit_t *tx_unit, const parlio_tx_unit_config_t *config) { - parlio_hal_context_t *hal = &tx_unit->group->hal; - // parlio_ll_clock_source_t and parlio_clock_source_t are binary compatible if the clock source is from internal - parlio_ll_clock_source_t clk_src = (parlio_ll_clock_source_t)(config->clk_src); + parlio_hal_context_t *hal = &tx_unit->base.group->hal; + parlio_clock_source_t clk_src = config->clk_in_gpio_num >= 0 ? PARLIO_CLK_SRC_EXTERNAL : config->clk_src; uint32_t periph_src_clk_hz = 0; // if the source clock is input from the GPIO, then we're in the slave mode - if (config->clk_in_gpio_num >= 0) { - clk_src = PARLIO_LL_CLK_SRC_PAD; + if (clk_src == PARLIO_CLK_SRC_EXTERNAL) { periph_src_clk_hz = config->input_clk_src_freq_hz; } else { // get the internal clock source frequency @@ -246,9 +206,9 @@ static esp_err_t parlio_select_periph_clock(parlio_tx_unit_t *tx_unit, const par ESP_RETURN_ON_FALSE(periph_src_clk_hz, ESP_ERR_INVALID_ARG, TAG, "invalid clock source frequency"); #if CONFIG_PM_ENABLE - if (clk_src != PARLIO_LL_CLK_SRC_PAD) { + if (clk_src != PARLIO_CLK_SRC_EXTERNAL) { // XTAL and PLL clock source will be turned off in light sleep, so we need to create a NO_LIGHT_SLEEP lock - sprintf(tx_unit->pm_lock_name, "parlio_tx_%d_%d", tx_unit->group->group_id, tx_unit->unit_id); // e.g. parlio_tx_0_0 + sprintf(tx_unit->pm_lock_name, "parlio_tx_%d_%d", tx_unit->base.group->group_id, tx_unit->base.unit_id); // e.g. parlio_tx_0_0 esp_err_t ret = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, tx_unit->pm_lock_name, &tx_unit->pm_lock); ESP_RETURN_ON_ERROR(ret, TAG, "create NO_LIGHT_SLEEP lock failed"); } @@ -315,17 +275,17 @@ esp_err_t parlio_new_tx_unit(const parlio_tx_unit_config_t *config, parlio_tx_un ESP_GOTO_ON_FALSE(unit->dma_nodes, ESP_ERR_NO_MEM, err, TAG, "no memory for DMA nodes"); // Link the descriptors for (int i = 0; i < dma_nodes_num; i++) { - unit->dma_nodes[i].next = (i == dma_nodes_num - 1) ? NULL : &(unit->dma_nodes[i+1]); + unit->dma_nodes[i].next = (i == dma_nodes_num - 1) ? NULL : &(unit->dma_nodes[i + 1]); } unit->max_transfer_bits = config->max_transfer_size * 8; - + unit->base.dir = PARLIO_DIR_TX; unit->data_width = data_width; //create transaction queue ESP_GOTO_ON_ERROR(parlio_tx_create_trans_queue(unit, config), err, TAG, "create transaction queue failed"); // register the unit to a group - ESP_GOTO_ON_ERROR(parlio_tx_register_to_group(unit), err, TAG, "register unit to group failed"); - parlio_group_t *group = unit->group; + ESP_GOTO_ON_ERROR(parlio_register_unit_to_group(&unit->base), err, TAG, "register unit to group failed"); + parlio_group_t *group = unit->base.group; parlio_hal_context_t *hal = &group->hal; // select the clock source ESP_GOTO_ON_ERROR(parlio_select_periph_clock(unit, config), err, TAG, "set clock source failed"); @@ -384,7 +344,7 @@ esp_err_t parlio_new_tx_unit(const parlio_tx_unit_config_t *config, parlio_tx_un // return TX unit handle *ret_unit = unit; ESP_LOGD(TAG, "new tx unit(%d,%d) at %p, out clk=%"PRIu32"Hz, queue_depth=%zu, idle_mask=%"PRIx32, - group->group_id, unit->unit_id, unit, unit->out_clk_freq_hz, unit->queue_depth, unit->idle_value_mask); + group->group_id, unit->base.unit_id, unit, unit->out_clk_freq_hz, unit->queue_depth, unit->idle_value_mask); return ESP_OK; err: @@ -398,7 +358,7 @@ esp_err_t parlio_del_tx_unit(parlio_tx_unit_handle_t unit) { ESP_RETURN_ON_FALSE(unit, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); ESP_RETURN_ON_FALSE(atomic_load(&unit->fsm) == PARLIO_TX_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "unit not in init state"); - ESP_LOGD(TAG, "del tx unit(%d,%d)", unit->group->group_id, unit->unit_id); + ESP_LOGD(TAG, "del tx unit(%d,%d)", unit->base.group->group_id, unit->base.unit_id); return parlio_destroy_tx_unit(unit); } @@ -463,7 +423,7 @@ esp_err_t parlio_tx_unit_register_event_callbacks(parlio_tx_unit_handle_t tx_uni static void IRAM_ATTR parlio_tx_do_transaction(parlio_tx_unit_t *tx_unit, parlio_tx_trans_desc_t *t) { - parlio_hal_context_t *hal = &tx_unit->group->hal; + parlio_hal_context_t *hal = &tx_unit->base.group->hal; tx_unit->cur_trans = t; @@ -496,7 +456,7 @@ esp_err_t parlio_tx_unit_enable(parlio_tx_unit_handle_t tx_unit) if (tx_unit->pm_lock) { esp_pm_lock_acquire(tx_unit->pm_lock); } - parlio_hal_context_t *hal = &tx_unit->group->hal; + parlio_hal_context_t *hal = &tx_unit->base.group->hal; parlio_ll_enable_interrupt(hal->regs, PARLIO_LL_EVENT_TX_EOF, true); atomic_store(&tx_unit->fsm, PARLIO_TX_FSM_ENABLE); } else { @@ -544,7 +504,7 @@ esp_err_t parlio_tx_unit_disable(parlio_tx_unit_handle_t tx_unit) ESP_RETURN_ON_FALSE(valid_state, ESP_ERR_INVALID_STATE, TAG, "unit can't be disabled in state %d", expected_fsm); // stop the TX engine - parlio_hal_context_t *hal = &tx_unit->group->hal; + parlio_hal_context_t *hal = &tx_unit->base.group->hal; gdma_stop(tx_unit->dma_chan); parlio_ll_tx_start(hal->regs, false); parlio_ll_enable_interrupt(hal->regs, PARLIO_LL_EVENT_TX_EOF, false); @@ -607,7 +567,7 @@ esp_err_t parlio_tx_unit_transmit(parlio_tx_unit_handle_t tx_unit, const void *p static void IRAM_ATTR parlio_tx_default_isr(void *args) { parlio_tx_unit_t *tx_unit = (parlio_tx_unit_t *)args; - parlio_group_t *group = tx_unit->group; + parlio_group_t *group = tx_unit->base.group; parlio_hal_context_t *hal = &group->hal; BaseType_t high_task_woken = pdFALSE; bool need_yield = false; diff --git a/components/esp_driver_parlio/test_apps/.build-test-rules.yml b/components/esp_driver_parlio/test_apps/.build-test-rules.yml new file mode 100644 index 000000000000..bc30d2fe7ba2 --- /dev/null +++ b/components/esp_driver_parlio/test_apps/.build-test-rules.yml @@ -0,0 +1,11 @@ +# Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps + +components/esp_driver_parlio/test_apps/parlio: + disable: + - if: SOC_PARLIO_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: lack of runner + depends_components: + - esp_driver_parlio diff --git a/components/driver/test_apps/parlio/CMakeLists.txt b/components/esp_driver_parlio/test_apps/parlio/CMakeLists.txt similarity index 87% rename from components/driver/test_apps/parlio/CMakeLists.txt rename to components/esp_driver_parlio/test_apps/parlio/CMakeLists.txt index 66fa38dd6a59..91e4cdb68b0d 100644 --- a/components/driver/test_apps/parlio/CMakeLists.txt +++ b/components/esp_driver_parlio/test_apps/parlio/CMakeLists.txt @@ -10,7 +10,7 @@ project(parlio_test) if(CONFIG_COMPILER_DUMP_RTL_FILES) add_custom_target(check_test_app_sections ALL COMMAND ${PYTHON} $ENV{IDF_PATH}/tools/ci/check_callgraph.py - --rtl-dirs ${CMAKE_BINARY_DIR}/esp-idf/driver/,${CMAKE_BINARY_DIR}/esp-idf/hal/ + --rtl-dirs ${CMAKE_BINARY_DIR}/esp-idf/esp_driver_parlio/,${CMAKE_BINARY_DIR}/esp-idf/hal/ --elf-file ${CMAKE_BINARY_DIR}/parlio_test.elf find-refs --from-sections=.iram0.text diff --git a/components/esp_driver_parlio/test_apps/parlio/README.md b/components/esp_driver_parlio/test_apps/parlio/README.md new file mode 100644 index 000000000000..b450dc5ffac0 --- /dev/null +++ b/components/esp_driver_parlio/test_apps/parlio/README.md @@ -0,0 +1,2 @@ +| Supported Targets | ESP32-C6 | ESP32-H2 | +| ----------------- | -------- | -------- | diff --git a/components/esp_driver_parlio/test_apps/parlio/main/CMakeLists.txt b/components/esp_driver_parlio/test_apps/parlio/main/CMakeLists.txt new file mode 100644 index 000000000000..3ee6db54cecc --- /dev/null +++ b/components/esp_driver_parlio/test_apps/parlio/main/CMakeLists.txt @@ -0,0 +1,15 @@ +set(srcs "test_app_main.c" + "test_parlio_rx.c" + "test_parlio_tx.c") + +# TODO: IDF-7840, semaphore in 'spi_bus_lock.c' is not IRAM safe +if(CONFIG_PARLIO_ISR_IRAM_SAFE) + list(REMOVE_ITEM srcs "test_parlio_rx.c") +endif() + +# In order for the cases defined by `TEST_CASE` to be linked into the final elf, +# the component can be registered as WHOLE_ARCHIVE +idf_component_register(SRCS ${srcs} + PRIV_REQUIRES unity esp_driver_parlio esp_driver_gpio + esp_driver_i2s esp_driver_spi + WHOLE_ARCHIVE) diff --git a/components/driver/test_apps/parlio/main/test_app_main.c b/components/esp_driver_parlio/test_apps/parlio/main/test_app_main.c similarity index 100% rename from components/driver/test_apps/parlio/main/test_app_main.c rename to components/esp_driver_parlio/test_apps/parlio/main/test_app_main.c diff --git a/components/driver/test_apps/parlio/main/test_board.h b/components/esp_driver_parlio/test_apps/parlio/main/test_board.h similarity index 78% rename from components/driver/test_apps/parlio/main/test_board.h rename to components/esp_driver_parlio/test_apps/parlio/main/test_board.h index 08aecfd0813e..81c64cbc8c76 100644 --- a/components/driver/test_apps/parlio/main/test_board.h +++ b/components/esp_driver_parlio/test_apps/parlio/main/test_board.h @@ -11,8 +11,17 @@ extern "C" { #endif +#if CONFIG_PARLIO_ISR_IRAM_SAFE +#define TEST_PARLIO_CALLBACK_ATTR IRAM_ATTR +#define TEST_PARLIO_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT) +#else +#define TEST_PARLIO_CALLBACK_ATTR +#define TEST_PARLIO_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT +#endif + #if CONFIG_IDF_TARGET_ESP32C6 #define TEST_CLK_GPIO 10 +#define TEST_VALID_GPIO 11 #define TEST_DATA0_GPIO 0 #define TEST_DATA1_GPIO 1 #define TEST_DATA2_GPIO 2 @@ -23,6 +32,7 @@ extern "C" { #define TEST_DATA7_GPIO 7 #elif CONFIG_IDF_TARGET_ESP32H2 #define TEST_CLK_GPIO 10 +#define TEST_VALID_GPIO 11 #define TEST_DATA0_GPIO 0 #define TEST_DATA1_GPIO 1 #define TEST_DATA2_GPIO 2 diff --git a/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_rx.c b/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_rx.c new file mode 100644 index 000000000000..c9b38bde6af0 --- /dev/null +++ b/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_rx.c @@ -0,0 +1,557 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "sdkconfig.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "unity.h" +#include "esp_log.h" +#include "esp_rom_gpio.h" +#include "driver/parlio_rx.h" +#include "driver/i2s_tdm.h" +#include "driver/spi_master.h" +#include "driver/gpio.h" +#include "hal/gpio_hal.h" +#include "soc/soc_caps.h" +#include "soc/i2s_periph.h" +#include "soc/spi_periph.h" +#include "soc/parlio_periph.h" +#include "esp_attr.h" +#include "test_board.h" + +#define TEST_SPI_HOST SPI2_HOST +#define TEST_I2S_PORT I2S_NUM_0 +#define TEST_VALID_SIG (PARLIO_RX_UNIT_MAX_DATA_WIDTH - 1) +#define TEST_DEFAULT_UNIT_CONFIG(_clk_src, _clk_freq) { \ + .trans_queue_depth = 10, \ + .max_recv_size = 10 * 1024, \ + .data_width = 1, \ + .clk_src = _clk_src, \ + .ext_clk_freq_hz = _clk_src == PARLIO_CLK_SRC_EXTERNAL ? _clk_freq : 0, \ + .clk_in_gpio_num = _clk_src == PARLIO_CLK_SRC_EXTERNAL ? TEST_CLK_GPIO : -1, \ + .exp_clk_freq_hz = _clk_freq, \ + .clk_out_gpio_num = -1, \ + .valid_gpio_num = TEST_VALID_GPIO, \ + .data_gpio_nums = { \ + [0] = TEST_DATA0_GPIO, \ + [1 ... (PARLIO_RX_UNIT_MAX_DATA_WIDTH - 1)] = -1, \ + }, \ + .flags = { \ + .clk_gate_en = false, \ + .io_loop_back = true, \ + } \ +} + +#define TEST_TASK_DATA_READY_BIT 0x01 +#define TEST_TASK_FINISHED_BIT 0x02 + +typedef struct { + uint32_t partial_recv_cnt; + uint32_t recv_done_cnt; + uint32_t timeout_cnt; +} test_data_t; + +TEST_PARLIO_CALLBACK_ATTR +static bool test_parlio_rx_partial_recv_callback(parlio_rx_unit_handle_t rx_unit, const parlio_rx_event_data_t *edata, void *user_data) +{ + test_data_t *test_data = (test_data_t *)user_data; + test_data->partial_recv_cnt++; + return false; +} + +TEST_PARLIO_CALLBACK_ATTR +static bool test_parlio_rx_done_callback(parlio_rx_unit_handle_t rx_unit, const parlio_rx_event_data_t *edata, void *user_data) +{ + test_data_t *test_data = (test_data_t *)user_data; + test_data->recv_done_cnt++; + return false; +} + +TEST_PARLIO_CALLBACK_ATTR +static bool test_parlio_rx_timeout_callback(parlio_rx_unit_handle_t rx_unit, const parlio_rx_event_data_t *edata, void *user_data) +{ + test_data_t *test_data = (test_data_t *)user_data; + test_data->timeout_cnt++; + return false; +} + +static void connect_signal_internally(uint32_t gpio, uint32_t sigo, uint32_t sigi) +{ + gpio_config_t gpio_conf = { + .pin_bit_mask = BIT64(gpio), + .mode = GPIO_MODE_INPUT_OUTPUT, + .intr_type = GPIO_INTR_DISABLE, + .pull_down_en = false, + .pull_up_en = false, + }; + gpio_config(&gpio_conf); + esp_rom_gpio_connect_out_signal(gpio, sigo, false, false); + esp_rom_gpio_connect_in_signal(gpio, sigi, false); +} + +#define TEST_EOF_DATA_LEN 64 + +static void pulse_delimiter_sender_task_i2s(void *args) +{ + uint32_t *task_flags = (uint32_t *)args; + i2s_chan_handle_t tx_chan = NULL; + i2s_chan_config_t tx_chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(TEST_I2S_PORT, I2S_ROLE_MASTER); + TEST_ESP_OK(i2s_new_channel(&tx_chan_cfg, &tx_chan, NULL)); + i2s_tdm_config_t tx_tdm_cfg = { + .clk_cfg = I2S_TDM_CLK_DEFAULT_CONFIG(48000), + .slot_cfg = I2S_TDM_PCM_SHORT_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO, + I2S_TDM_SLOT0 | I2S_TDM_SLOT1 | I2S_TDM_SLOT2 | I2S_TDM_SLOT3), + .gpio_cfg = { + .mclk = I2S_GPIO_UNUSED, + .bclk = TEST_CLK_GPIO, + .ws = TEST_VALID_GPIO, + .dout = TEST_DATA0_GPIO, + .din = -1, + .invert_flags = { + .mclk_inv = false, + .bclk_inv = false, + .ws_inv = false, + }, + }, + }; + TEST_ESP_OK(i2s_channel_init_tdm_mode(tx_chan, &tx_tdm_cfg)); + + uint32_t buf_size = 2048; + uint16_t *w_buf = (uint16_t *)calloc(1, buf_size); + assert(w_buf); // Check if w_buf allocation success + + for (int i = 0; i < buf_size / 2; i += 2) { + w_buf[i] = 0x1234; + w_buf[i + 1] = 0x5678; + } + + size_t w_bytes = buf_size; + + // Preload the data into DMA buffer + while (w_bytes == buf_size) { + TEST_ESP_OK(i2s_channel_preload_data(tx_chan, w_buf, buf_size, &w_bytes)); + } + // Transmission will start after enable the tx channel + TEST_ESP_OK(i2s_channel_enable(tx_chan)); + + // Connect GPIO signals + connect_signal_internally(TEST_CLK_GPIO, + i2s_periph_signal[TEST_I2S_PORT].m_tx_bck_sig, + parlio_periph_signals.groups[0].rx_units[0].clk_in_sig); + connect_signal_internally(TEST_VALID_GPIO, + i2s_periph_signal[TEST_I2S_PORT].m_tx_ws_sig, + parlio_periph_signals.groups[0].rx_units[0].data_sigs[TEST_VALID_SIG]); + connect_signal_internally(TEST_DATA0_GPIO, + i2s_periph_signal[TEST_I2S_PORT].data_out_sig, + parlio_periph_signals.groups[0].rx_units[0].data_sigs[0]); + + while (!((*task_flags) & TEST_TASK_FINISHED_BIT)) { + vTaskDelay(pdMS_TO_TICKS(1)); + *task_flags |= TEST_TASK_DATA_READY_BIT; + } + + TEST_ESP_OK(i2s_channel_disable(tx_chan)); + TEST_ESP_OK(i2s_del_channel(tx_chan)); + free(w_buf); + + *task_flags = 0; + while (1) { + vTaskDelay(portMAX_DELAY); + } +} + +static void cs_high(spi_transaction_t *trans) +{ + gpio_set_level(TEST_VALID_GPIO, 1); +} + +static void cs_low(spi_transaction_t *trans) +{ + gpio_set_level(TEST_VALID_GPIO, 0); +} + +#define TEST_SPI_CLK_FREQ 100000 + +static void level_delimiter_sender_task_spi(void *args) +{ + uint32_t *task_flags = (uint32_t *)args; + spi_device_handle_t dev_handle; + + spi_bus_config_t bus_cfg = { + .miso_io_num = -1, + .mosi_io_num = TEST_DATA0_GPIO, + .sclk_io_num = TEST_CLK_GPIO, + .quadwp_io_num = -1, + .quadhd_io_num = -1, + .max_transfer_sz = 2048, + }; + spi_device_interface_config_t dev_cfg = { + .command_bits = 0, + .address_bits = 0, + .clock_speed_hz = TEST_SPI_CLK_FREQ, + .mode = 0, + .duty_cycle_pos = 128, + .spics_io_num = TEST_VALID_GPIO, + .queue_size = 5, + .flags = SPI_DEVICE_HALFDUPLEX | SPI_DEVICE_POSITIVE_CS, + .pre_cb = cs_high, + .post_cb = cs_low, + }; + //Initialize the SPI bus and add device + TEST_ESP_OK(spi_bus_initialize(TEST_SPI_HOST, &bus_cfg, SPI_DMA_CH_AUTO)); + TEST_ESP_OK(spi_bus_add_device(TEST_SPI_HOST, &dev_cfg, &dev_handle)); + + // Initialize CS gpio + gpio_set_level(TEST_VALID_GPIO, 0); + gpio_config_t cs_cfg = { + .pin_bit_mask = BIT64(TEST_VALID_GPIO), + .mode = GPIO_MODE_OUTPUT, + }; + gpio_config(&cs_cfg); + + // Connect SPI signals to parlio rx signals + connect_signal_internally(TEST_CLK_GPIO, + spi_periph_signal[TEST_SPI_HOST].spiclk_out, + parlio_periph_signals.groups[0].rx_units[0].clk_in_sig); + connect_signal_internally(TEST_VALID_GPIO, + spi_periph_signal[TEST_SPI_HOST].spics_out[0], + parlio_periph_signals.groups[0].rx_units[0].data_sigs[TEST_VALID_SIG]); + connect_signal_internally(TEST_DATA0_GPIO, + spi_periph_signal[TEST_SPI_HOST].spid_out, + parlio_periph_signals.groups[0].rx_units[0].data_sigs[0]); + + // Prepare the data the be transmitted + uint8_t *data = (uint8_t *)calloc(1, TEST_EOF_DATA_LEN); + for (int i = 0; i < TEST_EOF_DATA_LEN; i += 4) { + data[i] = 0x12; + data[i + 1] = 0x34; + data[i + 2] = 0x56; + data[i + 3] = 0x78; + } + spi_transaction_t t = { + .cmd = 0, + .length = TEST_EOF_DATA_LEN * 8, + .flags = 0, + .tx_buffer = data, + .user = NULL, + }; + + // Transmit data every 1ms, until the main test thread finished receiving + while (!((*task_flags) & TEST_TASK_FINISHED_BIT)) { + TEST_ESP_OK(spi_device_transmit(dev_handle, &t)); + vTaskDelay(pdMS_TO_TICKS(1)); + *task_flags |= TEST_TASK_DATA_READY_BIT; + } + + // Remove the SPI device and free the bus + TEST_ESP_OK(spi_bus_remove_device(dev_handle)); + TEST_ESP_OK(spi_bus_free(TEST_SPI_HOST)); + // Free data buffer + free(data); + + // Reset the flag to indicate the sending loop has quit + *task_flags = 0; + // Waiting to be deleted + while (1) { + vTaskDelay(portMAX_DELAY); + } +} + +static bool test_delimiter(parlio_rx_delimiter_handle_t deli, bool free_running_clk, void (*sender_task_thread)(void *args)) +{ + parlio_rx_unit_handle_t rx_unit = NULL; + + parlio_rx_unit_config_t config = TEST_DEFAULT_UNIT_CONFIG(PARLIO_CLK_SRC_EXTERNAL, 1000000); + config.flags.free_clk = free_running_clk; + TEST_ESP_OK(parlio_new_rx_unit(&config, &rx_unit)); + TEST_ESP_OK(parlio_rx_unit_enable(rx_unit, true)); + + TaskHandle_t sender_task; + /* The flag to transport finish information between main test thread and the sender thread + * Set it as static to make sure it'll be valid in another thread */ + static uint32_t task_flags = 0; + xTaskCreate(sender_task_thread, "sender task", 4096, &task_flags, 5, &sender_task); + // Waiting for the data ready on line + while ((task_flags & TEST_TASK_DATA_READY_BIT)) { + vTaskDelay(1); + } + + parlio_receive_config_t recv_config = { + .delimiter = deli, + .flags.partial_rx_en = false, + }; + uint8_t recv_buff[TEST_EOF_DATA_LEN]; + bool is_success = false; + // sample 5 times + for (int i = 0; i < 5 && !is_success; i++) { + TEST_ESP_OK(parlio_rx_unit_receive(rx_unit, recv_buff, TEST_EOF_DATA_LEN, &recv_config)); + TEST_ESP_OK(parlio_rx_unit_wait_all_done(rx_unit, 5000)); + for (int k = 0; k < TEST_EOF_DATA_LEN; k++) { + printf("%x ", recv_buff[k]); + if ((k & 0xf) == 0xf) { + printf("\n"); + } + } + printf("\n"); + for (int j = 0; j < TEST_EOF_DATA_LEN; j++) { + // Check if 0x12 0x34 0x56 0x78 appeared in the buffer + if (recv_buff[j] == 0x12 && recv_buff[j + 1] == 0x34 && + recv_buff[j + 2] == 0x56 && recv_buff[j + 3] == 0x78) { + is_success = true; + break; + } + } + } + // Indicate the test finished, no need to send data + task_flags |= TEST_TASK_FINISHED_BIT; + // Waiting for the sender task quit + while (task_flags) { + vTaskDelay(1); + } + // Delete the sender task + vTaskDelete(sender_task); + + TEST_ESP_OK(parlio_rx_unit_disable(rx_unit)); + TEST_ESP_OK(parlio_del_rx_unit(rx_unit)); + return is_success; +} + +// This test case uses level delimiter +TEST_CASE("parallel_rx_unit_level_delimiter_test_via_spi", "[parlio_rx]") +{ + parlio_rx_level_delimiter_config_t lvl_deli_cfg = { + .valid_sig_line_id = TEST_VALID_SIG, + .sample_edge = PARLIO_SAMPLE_EDGE_POS, + .bit_pack_order = PARLIO_BIT_PACK_ORDER_MSB, + .eof_data_len = TEST_EOF_DATA_LEN, + .timeout_ticks = 0, + .flags = { + .active_low_en = 0, + }, + }; + parlio_rx_delimiter_handle_t deli = NULL; + TEST_ESP_OK(parlio_new_rx_level_delimiter(&lvl_deli_cfg, &deli)); + bool is_success = test_delimiter(deli, false, level_delimiter_sender_task_spi); + TEST_ESP_OK(parlio_del_rx_delimiter(deli)); + TEST_ASSERT(is_success); +} + +// This test case uses pulse delimiter +TEST_CASE("parallel_rx_unit_pulse_delimiter_test_via_i2s", "[parlio_rx]") +{ + parlio_rx_pulse_delimiter_config_t pls_deli_cfg = { + .valid_sig_line_id = TEST_VALID_SIG, + .sample_edge = PARLIO_SAMPLE_EDGE_POS, + .bit_pack_order = PARLIO_BIT_PACK_ORDER_MSB, + .eof_data_len = TEST_EOF_DATA_LEN, + .timeout_ticks = 0, + .flags = { + .start_bit_included = 0, + .end_bit_included = 0, + .has_end_pulse = 0, + .pulse_invert = 0, + }, + }; + parlio_rx_delimiter_handle_t deli = NULL; + TEST_ESP_OK(parlio_new_rx_pulse_delimiter(&pls_deli_cfg, &deli)); + bool is_success = test_delimiter(deli, true, pulse_delimiter_sender_task_i2s); + TEST_ESP_OK(parlio_del_rx_delimiter(deli)); + TEST_ASSERT(is_success); +} + +TEST_CASE("parallel_rx_unit_install_uninstall", "[parlio_rx]") +{ + printf("install rx units exhaustively\r\n"); + parlio_rx_unit_handle_t units[SOC_PARLIO_GROUPS * SOC_PARLIO_RX_UNITS_PER_GROUP]; + int k = 0; + parlio_rx_unit_config_t config = TEST_DEFAULT_UNIT_CONFIG(PARLIO_CLK_SRC_DEFAULT, 1000000); + for (int i = 0; i < SOC_PARLIO_GROUPS; i++) { + for (int j = 0; j < SOC_PARLIO_RX_UNITS_PER_GROUP; j++) { + TEST_ESP_OK(parlio_new_rx_unit(&config, &units[k++])); + } + } + TEST_ESP_ERR(ESP_ERR_NOT_FOUND, parlio_new_rx_unit(&config, &units[0])); + + for (int i = 0; i < k; i++) { + TEST_ESP_OK(parlio_del_rx_unit(units[i])); + } + + // clock from external + config.clk_src = PARLIO_CLK_SRC_EXTERNAL; + // clock gpio must be set when the clock is input from external + TEST_ESP_ERR(ESP_ERR_INVALID_ARG, parlio_new_rx_unit(&config, &units[0])); + + // clock from internal + config.clk_src = PARLIO_CLK_SRC_DEFAULT; + config.clk_out_gpio_num = TEST_CLK_GPIO; +#if SOC_PARLIO_RX_CLK_SUPPORT_OUTPUT + TEST_ESP_OK(parlio_new_rx_unit(&config, &units[0])); + TEST_ESP_OK(parlio_del_rx_unit(units[0])); +#else + // failed because of not support output the clock to a gpio + TEST_ESP_ERR(ESP_ERR_NOT_SUPPORTED, parlio_new_rx_unit(&config, &units[0])); + config.clk_out_gpio_num = -1; +#endif + config.data_width = 3; + // data width should be power of 2 + TEST_ESP_ERR(ESP_ERR_INVALID_ARG, parlio_new_rx_unit(&config, &units[0])); + + config.data_width = 4; + TEST_ESP_OK(parlio_new_rx_unit(&config, &units[0])); + TEST_ESP_OK(parlio_rx_unit_enable(units[0], true)); + // delete unit before it's disabled is not allowed + TEST_ESP_ERR(ESP_ERR_INVALID_STATE, parlio_del_rx_unit(units[0])); + TEST_ESP_OK(parlio_rx_unit_disable(units[0])); + TEST_ESP_OK(parlio_del_rx_unit(units[0])); +} + +#define TEST_PAYLOAD_SIZE 5000 + +// This test case uses soft delimiter +TEST_CASE("parallel_rx_unit_receive_transaction_test", "[parlio_rx]") +{ + parlio_rx_unit_handle_t rx_unit = NULL; + parlio_rx_delimiter_handle_t deli = NULL; + + parlio_rx_unit_config_t config = TEST_DEFAULT_UNIT_CONFIG(PARLIO_CLK_SRC_DEFAULT, 1000000); + config.flags.free_clk = 1; + TEST_ESP_OK(parlio_new_rx_unit(&config, &rx_unit)); + + parlio_rx_soft_delimiter_config_t sft_deli_cfg = { + .sample_edge = PARLIO_SAMPLE_EDGE_POS, + .eof_data_len = TEST_PAYLOAD_SIZE, + .timeout_ticks = 0, + }; + TEST_ESP_OK(parlio_new_rx_soft_delimiter(&sft_deli_cfg, &deli)); + + parlio_rx_event_callbacks_t cbs = { + .on_partial_receive = test_parlio_rx_partial_recv_callback, + .on_receive_done = test_parlio_rx_done_callback, + }; + test_data_t test_data = { + .partial_recv_cnt = 0, + .recv_done_cnt = 0, + }; + TEST_ESP_OK(parlio_rx_unit_register_event_callbacks(rx_unit, &cbs, &test_data)); + TEST_ESP_OK(parlio_rx_unit_enable(rx_unit, true)); + + parlio_receive_config_t recv_config = { + .delimiter = deli, + .flags.partial_rx_en = false, + }; + uint8_t *payload = heap_caps_calloc(1, TEST_PAYLOAD_SIZE, TEST_PARLIO_MEM_ALLOC_CAPS); + TEST_ASSERT(payload); + + printf("Testing one normal transaction...\n"); + TEST_ESP_OK(parlio_rx_soft_delimiter_start_stop(rx_unit, deli, true)); + TEST_ESP_OK(parlio_rx_unit_receive(rx_unit, payload, TEST_PAYLOAD_SIZE, &recv_config)); + TEST_ESP_OK(parlio_rx_unit_wait_all_done(rx_unit, 5000)); + TEST_ESP_OK(parlio_rx_soft_delimiter_start_stop(rx_unit, deli, false)); + TEST_ASSERT_EQUAL_UINT32(2, test_data.partial_recv_cnt); + TEST_ASSERT_EQUAL_UINT32(1, test_data.recv_done_cnt); + memset(&test_data, 0, sizeof(test_data_t)); + + printf("Testing normal transactions in queue...\n"); + TEST_ESP_OK(parlio_rx_soft_delimiter_start_stop(rx_unit, deli, true)); + // push 5 repeated transactions to the queue + for (int i = 0; i < 5; i++) { + TEST_ESP_OK(parlio_rx_unit_receive(rx_unit, payload, TEST_PAYLOAD_SIZE, &recv_config)); + } + TEST_ESP_OK(parlio_rx_unit_wait_all_done(rx_unit, 5000)); + TEST_ESP_OK(parlio_rx_soft_delimiter_start_stop(rx_unit, deli, false)); + TEST_ASSERT_EQUAL_UINT32(10, test_data.partial_recv_cnt); + TEST_ASSERT_EQUAL_UINT32(5, test_data.recv_done_cnt); + memset(&test_data, 0, sizeof(test_data_t)); + + printf("Testing resume transactions in queue after enabling...\n"); + TEST_ESP_OK(parlio_rx_soft_delimiter_start_stop(rx_unit, deli, true)); + // push 5 repeated transactions to the queue + for (int i = 0; i < 10; i++) { + TEST_ESP_OK(parlio_rx_unit_receive(rx_unit, payload, TEST_PAYLOAD_SIZE, &recv_config)); + } + TEST_ESP_OK(parlio_rx_unit_disable(rx_unit)); + memset(&test_data, 0, sizeof(test_data_t)); + TEST_ESP_OK(parlio_rx_unit_enable(rx_unit, false)); + TEST_ESP_OK(parlio_rx_unit_wait_all_done(rx_unit, 5000)); + TEST_ESP_OK(parlio_rx_soft_delimiter_start_stop(rx_unit, deli, false)); + TEST_ASSERT_GREATER_THAN(2, test_data.partial_recv_cnt); + TEST_ASSERT_GREATER_THAN(1, test_data.recv_done_cnt); + memset(&test_data, 0, sizeof(test_data_t)); + + printf("Testing the infinite transaction...\n"); + recv_config.flags.partial_rx_en = true; + TEST_ESP_OK(parlio_rx_soft_delimiter_start_stop(rx_unit, deli, true)); + TEST_ESP_OK(parlio_rx_unit_receive(rx_unit, payload, TEST_PAYLOAD_SIZE, &recv_config)); + // Won't receive done semaphore in infinite transaction + TEST_ESP_ERR(ESP_ERR_TIMEOUT, parlio_rx_unit_wait_all_done(rx_unit, 500)); + TEST_ESP_OK(parlio_rx_soft_delimiter_start_stop(rx_unit, deli, false)); + TEST_ASSERT_GREATER_THAN(6, test_data.partial_recv_cnt); + TEST_ASSERT_GREATER_THAN(3, test_data.recv_done_cnt); + memset(&test_data, 0, sizeof(test_data_t)); + + TEST_ESP_OK(parlio_rx_unit_disable(rx_unit)); + TEST_ESP_OK(parlio_del_rx_delimiter(deli)); + TEST_ESP_OK(parlio_del_rx_unit(rx_unit)); + free(payload); +}; + +TEST_CASE("parallel_rx_unit_receive_timeout_test", "[parlio_rx]") +{ + parlio_rx_unit_handle_t rx_unit = NULL; + parlio_rx_delimiter_handle_t timeout_deli = NULL; + + parlio_rx_unit_config_t config = TEST_DEFAULT_UNIT_CONFIG(PARLIO_CLK_SRC_DEFAULT, 1000000); + config.flags.free_clk = 1; + config.flags.clk_gate_en = 1; + TEST_ESP_OK(parlio_new_rx_unit(&config, &rx_unit)); + + parlio_rx_level_delimiter_config_t lvl_deli_cfg = { + .valid_sig_line_id = TEST_VALID_SIG, + .sample_edge = PARLIO_SAMPLE_EDGE_POS, + .bit_pack_order = PARLIO_BIT_PACK_ORDER_MSB, + .eof_data_len = TEST_PAYLOAD_SIZE, + .timeout_ticks = 400, + .flags = { + .active_low_en = 0, + }, + }; + TEST_ESP_OK(parlio_new_rx_level_delimiter(&lvl_deli_cfg, &timeout_deli)); + + parlio_rx_event_callbacks_t cbs = { + .on_timeout = test_parlio_rx_timeout_callback, + }; + test_data_t test_data = { + .timeout_cnt = 0, + }; + TEST_ESP_OK(parlio_rx_unit_register_event_callbacks(rx_unit, &cbs, &test_data)); + TEST_ESP_OK(parlio_rx_unit_enable(rx_unit, true)); + + parlio_receive_config_t recv_config = { + .delimiter = timeout_deli, + .flags.partial_rx_en = false, + }; + uint8_t *payload = heap_caps_calloc(1, TEST_PAYLOAD_SIZE, TEST_PARLIO_MEM_ALLOC_CAPS); + TEST_ASSERT(payload); + + printf("Testing the timeout callback...\n"); + // push 5 repeated transactions to the queue + for (int i = 0; i < 5; i++) { + TEST_ESP_OK(parlio_rx_unit_receive(rx_unit, payload, TEST_PAYLOAD_SIZE, &recv_config)); + gpio_set_level(TEST_VALID_GPIO, 1); + vTaskDelay(pdMS_TO_TICKS(10)); + gpio_set_level(TEST_VALID_GPIO, 0); + vTaskDelay(pdMS_TO_TICKS(5)); + printf("Transaction %d finished\n", i); + } + TEST_ASSERT_TRUE(test_data.timeout_cnt); + + TEST_ESP_OK(parlio_rx_unit_disable(rx_unit)); + TEST_ESP_OK(parlio_del_rx_delimiter(timeout_deli)); + TEST_ESP_OK(parlio_del_rx_unit(rx_unit)); + free(payload); +} diff --git a/components/driver/test_apps/parlio/main/test_parlio_tx.c b/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_tx.c similarity index 98% rename from components/driver/test_apps/parlio/main/test_parlio_tx.c rename to components/esp_driver_parlio/test_apps/parlio/main/test_parlio_tx.c index 0b5dd59b35f6..061fefae1226 100644 --- a/components/driver/test_apps/parlio/main/test_parlio_tx.c +++ b/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_tx.c @@ -15,12 +15,6 @@ #include "esp_attr.h" #include "test_board.h" -#if CONFIG_PARLIO_ISR_IRAM_SAFE -#define TEST_PARLIO_CALLBACK_ATTR IRAM_ATTR -#else -#define TEST_PARLIO_CALLBACK_ATTR -#endif - TEST_CASE("parallel_tx_unit_install_uninstall", "[parlio_tx]") { printf("install tx units exhaustively\r\n"); diff --git a/components/driver/test_apps/parlio/pytest_parlio_unity.py b/components/esp_driver_parlio/test_apps/parlio/pytest_parlio_unity.py similarity index 100% rename from components/driver/test_apps/parlio/pytest_parlio_unity.py rename to components/esp_driver_parlio/test_apps/parlio/pytest_parlio_unity.py diff --git a/components/driver/test_apps/parlio/sdkconfig.ci.iram_safe b/components/esp_driver_parlio/test_apps/parlio/sdkconfig.ci.iram_safe similarity index 100% rename from components/driver/test_apps/parlio/sdkconfig.ci.iram_safe rename to components/esp_driver_parlio/test_apps/parlio/sdkconfig.ci.iram_safe diff --git a/components/driver/test_apps/parlio/sdkconfig.ci.release b/components/esp_driver_parlio/test_apps/parlio/sdkconfig.ci.release similarity index 100% rename from components/driver/test_apps/parlio/sdkconfig.ci.release rename to components/esp_driver_parlio/test_apps/parlio/sdkconfig.ci.release diff --git a/components/driver/test_apps/parlio/sdkconfig.defaults b/components/esp_driver_parlio/test_apps/parlio/sdkconfig.defaults similarity index 100% rename from components/driver/test_apps/parlio/sdkconfig.defaults rename to components/esp_driver_parlio/test_apps/parlio/sdkconfig.defaults diff --git a/components/esp_driver_pcnt/test_apps/.build-test-rules.yml b/components/esp_driver_pcnt/test_apps/.build-test-rules.yml index d94a1f9237b4..2119175e78ca 100644 --- a/components/esp_driver_pcnt/test_apps/.build-test-rules.yml +++ b/components/esp_driver_pcnt/test_apps/.build-test-rules.yml @@ -3,5 +3,9 @@ components/esp_driver_pcnt/test_apps/pulse_cnt: disable: - if: SOC_PCNT_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: test not pass, should be re-enable # TODO: IDF-8965 depends_components: - esp_driver_pcnt diff --git a/components/esp_driver_rmt/test_apps/.build-test-rules.yml b/components/esp_driver_rmt/test_apps/.build-test-rules.yml index 2a97c6cdec19..7360259435db 100644 --- a/components/esp_driver_rmt/test_apps/.build-test-rules.yml +++ b/components/esp_driver_rmt/test_apps/.build-test-rules.yml @@ -3,5 +3,9 @@ components/esp_driver_rmt/test_apps/rmt: disable: - if: SOC_RMT_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: test not passing, should be re-enabled # TODO: IDF-8961 depends_components: - esp_driver_rmt diff --git a/components/esp_driver_sdm/test_apps/sigma_delta/pytest_sigma_delta.py b/components/esp_driver_sdm/test_apps/sigma_delta/pytest_sigma_delta.py index 6f5763207d68..c092b46beaff 100644 --- a/components/esp_driver_sdm/test_apps/sigma_delta/pytest_sigma_delta.py +++ b/components/esp_driver_sdm/test_apps/sigma_delta/pytest_sigma_delta.py @@ -17,6 +17,7 @@ @pytest.mark.esp32s2 @pytest.mark.esp32s3 @pytest.mark.esp32h2 +@pytest.mark.esp32p4 @pytest.mark.generic @pytest.mark.parametrize('config', CONFIGS, indirect=True) def test_sdm(dut: IdfDut) -> None: diff --git a/components/esp_driver_sdmmc/test_apps/.build-test-rules.yml b/components/esp_driver_sdmmc/test_apps/.build-test-rules.yml index 7a4947815c75..cc6c1807730a 100644 --- a/components/esp_driver_sdmmc/test_apps/.build-test-rules.yml +++ b/components/esp_driver_sdmmc/test_apps/.build-test-rules.yml @@ -1,6 +1,11 @@ components/esp_driver_sdmmc/test_apps/sdmmc: disable: - if: SOC_SDMMC_HOST_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: lack of runner # TODO: IDF-8970 + depends_components: - sdmmc - esp_driver_sdmmc diff --git a/components/esp_driver_spi/test_apps/.build-test-rules.yml b/components/esp_driver_spi/test_apps/.build-test-rules.yml index f863d7c16b91..f2306768be4f 100644 --- a/components/esp_driver_spi/test_apps/.build-test-rules.yml +++ b/components/esp_driver_spi/test_apps/.build-test-rules.yml @@ -7,20 +7,36 @@ components/esp_driver_spi/test_apps/spi/master: disable: - if: SOC_GPSPI_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: not supported # TODO: IDF-8942 <<: *spi_depends_default components/esp_driver_spi/test_apps/spi/param: disable: - if: SOC_GPSPI_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: not supported # TODO: IDF-8942 <<: *spi_depends_default components/esp_driver_spi/test_apps/spi/slave: disable: - if: SOC_GPSPI_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: not supported # TODO: IDF-8942 <<: *spi_depends_default components/esp_driver_spi/test_apps/spi/slave_hd: disable: - if: SOC_GPSPI_SUPPORTED != 1 - if: SOC_SPI_SUPPORT_SLAVE_HD_VER2 != 1 + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: not supported # TODO: IDF-8942 <<: *spi_depends_default diff --git a/components/esp_driver_spi/test_apps/spi/master/pytest_spi_master.py b/components/esp_driver_spi/test_apps/spi/master/pytest_spi_master.py index 90c22cbe737b..7315d363a305 100644 --- a/components/esp_driver_spi/test_apps/spi/master/pytest_spi_master.py +++ b/components/esp_driver_spi/test_apps/spi/master/pytest_spi_master.py @@ -5,6 +5,7 @@ # If `test_env` is define, should not run on generic runner +@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='p4 support TBD') # TODO: IDF-8942 @pytest.mark.supported_targets @pytest.mark.esp32h2 @pytest.mark.generic @@ -28,6 +29,7 @@ def test_master_esp_flash(case_tester) -> None: # type: ignore # if `test_env` not defined, will run on `generic_multi_device` by default +@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='p4 support TBD') # TODO: IDF-8942 @pytest.mark.supported_targets @pytest.mark.esp32h2 @pytest.mark.generic_multi_device diff --git a/components/esp_driver_spi/test_apps/spi/param/pytest_spi_param.py b/components/esp_driver_spi/test_apps/spi/param/pytest_spi_param.py index 38c3f126ad8e..4a1d8d7e56d1 100644 --- a/components/esp_driver_spi/test_apps/spi/param/pytest_spi_param.py +++ b/components/esp_driver_spi/test_apps/spi/param/pytest_spi_param.py @@ -5,6 +5,7 @@ # If `test_env` is define, should not run on generic runner +@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='p4 support TBD') # TODO: IDF-8942 @pytest.mark.supported_targets @pytest.mark.esp32h2 @pytest.mark.generic @@ -16,6 +17,7 @@ def test_param_single_dev(case_tester) -> None: # type: ignore # if `test_env` not defined, will run on `generic_multi_device` by default +@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='p4 support TBD') # TODO: IDF-8942 @pytest.mark.supported_targets @pytest.mark.esp32h2 @pytest.mark.generic_multi_device diff --git a/components/esp_driver_spi/test_apps/spi/slave/pytest_spi_slave.py b/components/esp_driver_spi/test_apps/spi/slave/pytest_spi_slave.py index 53dba53dc5d5..f468b8d4dfce 100644 --- a/components/esp_driver_spi/test_apps/spi/slave/pytest_spi_slave.py +++ b/components/esp_driver_spi/test_apps/spi/slave/pytest_spi_slave.py @@ -5,6 +5,7 @@ # If `test_env` is define, should not run on generic runner +@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='p4 support TBD') # TODO: IDF-8942 @pytest.mark.supported_targets @pytest.mark.esp32h2 @pytest.mark.generic @@ -17,6 +18,7 @@ def test_slave_single_dev(case_tester) -> None: # type: ignore # if `test_env` not defined, will run on `generic_multi_device` by default +@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='p4 support TBD') # TODO: IDF-8942 @pytest.mark.supported_targets @pytest.mark.esp32h2 @pytest.mark.generic_multi_device diff --git a/components/esp_driver_tsens/test_apps/temperature_sensor/pytest_temperature_sensor.py b/components/esp_driver_tsens/test_apps/temperature_sensor/pytest_temperature_sensor.py index bf7e71df17a1..996d370bfce5 100644 --- a/components/esp_driver_tsens/test_apps/temperature_sensor/pytest_temperature_sensor.py +++ b/components/esp_driver_tsens/test_apps/temperature_sensor/pytest_temperature_sensor.py @@ -12,6 +12,7 @@ @pytest.mark.esp32c2 @pytest.mark.esp32c6 @pytest.mark.esp32h2 +@pytest.mark.esp32p4 @pytest.mark.generic @pytest.mark.parametrize('config', [ 'release', @@ -22,6 +23,7 @@ def test_temperature_sensor_driver(dut: Dut) -> None: @pytest.mark.esp32c6 @pytest.mark.esp32h2 +@pytest.mark.esp32p4 @pytest.mark.generic @pytest.mark.parametrize('config', [ 'iram_safe', diff --git a/components/esp_driver_uart/test_apps/.build-test-rules.yml b/components/esp_driver_uart/test_apps/.build-test-rules.yml index 1e0bdf7afb99..403036b446e1 100644 --- a/components/esp_driver_uart/test_apps/.build-test-rules.yml +++ b/components/esp_driver_uart/test_apps/.build-test-rules.yml @@ -14,6 +14,10 @@ components/esp_driver_uart/test_apps/rs485: components/esp_driver_uart/test_apps/uart: disable: - if: SOC_UART_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: test not pass, should be re-enable # TODO: IDF-8971 depends_components: - esp_driver_uart - esp_driver_gpio diff --git a/components/esp_driver_uart/test_apps/uart/pytest_uart.py b/components/esp_driver_uart/test_apps/uart/pytest_uart.py index dea1980c9d2a..aaa323ea8dbc 100644 --- a/components/esp_driver_uart/test_apps/uart/pytest_uart.py +++ b/components/esp_driver_uart/test_apps/uart/pytest_uart.py @@ -5,7 +5,7 @@ @pytest.mark.supported_targets -@pytest.mark.temp_skip_ci(targets=['esp32s3'], reason='skip due to duplication with test_uart_single_dev_psram') +@pytest.mark.temp_skip_ci(targets=['esp32s3', 'esp32p4'], reason='skip due to duplication with test_uart_single_dev_psram, p4 TBD') # TODO: IDF-8971 @pytest.mark.generic @pytest.mark.parametrize( 'config', diff --git a/components/esp_event/test_apps/pytest_esp_event.py b/components/esp_event/test_apps/pytest_esp_event.py index 8e9cbd553870..22dd4e7ea0c8 100644 --- a/components/esp_event/test_apps/pytest_esp_event.py +++ b/components/esp_event/test_apps/pytest_esp_event.py @@ -14,24 +14,10 @@ def test_esp_event(dut: Dut) -> None: @pytest.mark.esp32 -@pytest.mark.host_test -@pytest.mark.qemu -@pytest.mark.parametrize('qemu_extra_args', [ - '-global driver=timer.esp32.timg,property=wdt_disable,value=true', -], indirect=True) # need to disable wdt since it is not synchronized with target cpu clock on QEMU for ESP32 -def test_esp_event_qemu_esp32(dut: Dut) -> None: - for case in dut.test_menu: - if 'qemu-ignore' not in case.groups and not case.is_ignored and case.type == 'normal': - dut._run_normal_case(case) - - @pytest.mark.esp32c3 @pytest.mark.host_test @pytest.mark.qemu -@pytest.mark.parametrize('qemu_extra_args', [ - '-icount 3', -], indirect=True) # need to add -icount 3 to make WDT accurate on QEMU for ESP32-C3 -def test_esp_event_qemu_esp32c3(dut: Dut) -> None: +def test_esp_event_qemu(dut: Dut) -> None: for case in dut.test_menu: if 'qemu-ignore' not in case.groups and not case.is_ignored and case.type == 'normal': dut._run_normal_case(case) diff --git a/components/esp_event/test_apps/sdkconfig.defaults b/components/esp_event/test_apps/sdkconfig.defaults index e69de29bb2d1..ba19fc5604d8 100644 --- a/components/esp_event/test_apps/sdkconfig.defaults +++ b/components/esp_event/test_apps/sdkconfig.defaults @@ -0,0 +1,3 @@ +# This "default" configuration is appended to all other configurations +# The contents of "sdkconfig.debug_helpers" is also appended to all other configurations (see CMakeLists.txt) +CONFIG_ESP_TASK_WDT_INIT=n diff --git a/components/esp_hw_support/CMakeLists.txt b/components/esp_hw_support/CMakeLists.txt index 317fe0635229..7ad19816a825 100644 --- a/components/esp_hw_support/CMakeLists.txt +++ b/components/esp_hw_support/CMakeLists.txt @@ -151,7 +151,15 @@ if(NOT BOOTLOADER_BUILD) "sleep_modes.c" # TODO: IDF-7528, IDF-7529 "sleep_wake_stub.c" # TODO: IDF-7529 "sleep_gpio.c" # TODO: IDF-7528, IDF-7529 - "port/esp_clk_tree_common.c" # TODO: IDF-7526 + ) + endif() + if(CONFIG_IDF_TARGET_ESP32C5) + list(REMOVE_ITEM srcs + "sleep_cpu.c" # TODO: [ESP32C5] IDF-8638, IDF-8640 + "sleep_modes.c" # TODO: [ESP32C5] IDF-8638, IDF-8640 + "sleep_wake_stub.c" # TODO: [ESP32C5] IDF-8638, IDF-8640 + "sleep_gpio.c" # TODO: [ESP32C5] IDF-8638, IDF-8640 + "port/esp_clk_tree_common.c" # TODO: [ESP32C5] IDF-8638, IDF-8640 ) endif() else() diff --git a/components/esp_hw_support/Kconfig b/components/esp_hw_support/Kconfig index e9b8a4b66b15..689cdea102a9 100644 --- a/components/esp_hw_support/Kconfig +++ b/components/esp_hw_support/Kconfig @@ -247,7 +247,8 @@ menu "Hardware Settings" menu "Main XTAL Config" choice XTAL_FREQ_SEL prompt "Main XTAL frequency" - default XTAL_FREQ_40 if SOC_XTAL_SUPPORT_40M + default XTAL_FREQ_48 if SOC_XTAL_SUPPORT_48M + default XTAL_FREQ_40 if (SOC_XTAL_SUPPORT_40M && !SOC_XTAL_SUPPORT_48M) help This option selects the operating frequency of the XTAL (crystal) clock used to drive the ESP target. The selected value MUST reflect the frequency of the given hardware. @@ -270,6 +271,9 @@ menu "Hardware Settings" config XTAL_FREQ_40 depends on SOC_XTAL_SUPPORT_40M bool "40 MHz" + config XTAL_FREQ_48 + depends on SOC_XTAL_SUPPORT_48M + bool "48 MHz" config XTAL_FREQ_AUTO depends on SOC_XTAL_SUPPORT_AUTO_DETECT bool "Autodetect" @@ -283,6 +287,7 @@ menu "Hardware Settings" default 26 if XTAL_FREQ_26 default 32 if XTAL_FREQ_32 default 40 if XTAL_FREQ_40 + default 48 if XTAL_FREQ_48 default 0 if XTAL_FREQ_AUTO endmenu @@ -332,7 +337,10 @@ menu "Hardware Settings" # Invisible bringup bypass options for esp_hw_support component config ESP_BRINGUP_BYPASS_CPU_CLK_SETTING bool - default y if !SOC_CLK_TREE_SUPPORTED + # TODO: [ESP32C5] IDF-8642 IDF_TARGET_ESP32C5 is added because clock + # is required when bringup on C5 beta3, remove it when clock tree is + # supported + default y if !SOC_CLK_TREE_SUPPORTED && !IDF_TARGET_ESP32C5 default n help This option is only used for new chip bringup, when diff --git a/components/esp_hw_support/cpu.c b/components/esp_hw_support/cpu.c index 7fefa9d432d2..904b760a6a53 100644 --- a/components/esp_hw_support/cpu.c +++ b/components/esp_hw_support/cpu.c @@ -11,7 +11,7 @@ #include "soc/soc_caps.h" // TODO: IDF-5645 -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C5 #include "soc/lp_aon_reg.h" #include "soc/pcr_reg.h" #define SYSTEM_CPU_PER_CONF_REG PCR_CPU_WAITI_CONF_REG @@ -107,7 +107,7 @@ void esp_cpu_reset(int core_id) else REG_SET_BIT(LP_CLKRST_HPCPU_RESET_CTRL0_REG, LP_CLKRST_HPCORE1_SW_RESET); #else -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2// TODO: IDF-5645 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C5 // TODO: IDF-5645 SET_PERI_REG_MASK(LP_AON_CPUCORE0_CFG_REG, LP_AON_CPU_CORE0_SW_RESET); #else assert(core_id >= 0 && core_id < SOC_CPU_CORES_NUM); diff --git a/components/esp_hw_support/esp_clk.c b/components/esp_hw_support/esp_clk.c index 35ec4e58d8fb..ad9d58ba57fb 100644 --- a/components/esp_hw_support/esp_clk.c +++ b/components/esp_hw_support/esp_clk.c @@ -39,6 +39,9 @@ #elif CONFIG_IDF_TARGET_ESP32H2 #include "esp32h2/rom/rtc.h" #include "esp32h2/rtc.h" +#elif CONFIG_IDF_TARGET_ESP32P4 +#include "esp32p4/rom/rtc.h" +#include "esp32p4/rtc.h" #endif #define MHZ (1000000) @@ -90,7 +93,7 @@ int IRAM_ATTR esp_clk_cpu_freq(void) int IRAM_ATTR esp_clk_apb_freq(void) { // TODO: IDF-5173 Require cleanup, implementation should be unified -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 return rtc_clk_apb_freq_get(); #else return MIN(s_get_cpu_freq_mhz() * MHZ, APB_CLK_FREQ); diff --git a/components/esp_hw_support/esp_ds.c b/components/esp_hw_support/esp_ds.c index 29f25b763816..75878d028a60 100644 --- a/components/esp_hw_support/esp_ds.c +++ b/components/esp_hw_support/esp_ds.c @@ -46,6 +46,10 @@ #include "esp32c6/rom/digital_signature.h" #endif +#if CONFIG_IDF_TARGET_ESP32C5 +#include "esp32c5/rom/digital_signature.h" +#endif + #if CONFIG_IDF_TARGET_ESP32H2 #include "esp32h2/rom/digital_signature.h" #endif diff --git a/components/esp_hw_support/esp_hmac.c b/components/esp_hw_support/esp_hmac.c index c71c021d0e38..f79899b97d37 100644 --- a/components/esp_hw_support/esp_hmac.c +++ b/components/esp_hw_support/esp_hmac.c @@ -197,7 +197,9 @@ esp_err_t esp_hmac_jtag_enable(hmac_key_id_t key_id, const uint8_t *token) esp_err_t esp_hmac_jtag_disable() { esp_crypto_hmac_lock_acquire(); + ets_hmac_enable(); REG_WRITE(HMAC_SET_INVALIDATE_JTAG_REG, 1); + ets_hmac_disable(); esp_crypto_hmac_lock_release(); ESP_LOGD(TAG, "Invalidate JTAG result register. JTAG disabled."); @@ -279,7 +281,9 @@ esp_err_t esp_hmac_jtag_disable() { esp_crypto_dma_lock_acquire(); + ets_hmac_enable(); REG_WRITE(HMAC_SET_INVALIDATE_JTAG_REG, 1); + ets_hmac_disable(); esp_crypto_dma_lock_release(); diff --git a/components/esp_hw_support/include/esp_chip_info.h b/components/esp_hw_support/include/esp_chip_info.h index 3922c0aeb6a2..98126ff4e5e7 100644 --- a/components/esp_hw_support/include/esp_chip_info.h +++ b/components/esp_hw_support/include/esp_chip_info.h @@ -27,8 +27,8 @@ typedef enum { CHIP_ESP32C2 = 12, //!< ESP32-C2 CHIP_ESP32C6 = 13, //!< ESP32-C6 CHIP_ESP32H2 = 16, //!< ESP32-H2 + CHIP_ESP32C5 = 17, //!< ESP32-C5 beta3 CHIP_ESP32P4 = 18, //!< ESP32-P4 - CHIP_ESP32C5 = 19, //!< ESP32-C5 CHIP_POSIX_LINUX = 999, //!< The code is running on POSIX/Linux simulator } esp_chip_model_t; diff --git a/components/esp_hw_support/include/esp_private/rtc_clk.h b/components/esp_hw_support/include/esp_private/rtc_clk.h index 620b03654f3d..86faa8e9e1f6 100644 --- a/components/esp_hw_support/include/esp_private/rtc_clk.h +++ b/components/esp_hw_support/include/esp_private/rtc_clk.h @@ -17,9 +17,9 @@ extern "C" { /** * @brief Switch CPU clock source to XTAL, and let cpu frequency equal to main XTAL frequency. * - * This function does not disable BBPLL. If BBPLL requires to be disabled to save power, please call - * `rtc_clk_cpu_freq_set_xtal` instead. It does one extra check to see whether can disable the BBPLL after switching the - * CPU clock source to XTAL. + * This function does not disable CPU's source PLL. If the PLL requires to be disabled to save power, please call + * `rtc_clk_cpu_freq_set_xtal` instead. It does one extra check (if necessary) to see whether can disable the + * corresponding PLL after switching the CPU clock source to XTAL. * * Currently, this function should only be called in `esp_restart_noos` and `esp_restart_noos_dig` to switch the CPU * clock source back to XTAL (by default) before reset. diff --git a/components/esp_hw_support/include/soc/esp32c5/esp_crypto_lock.h b/components/esp_hw_support/include/soc/esp32c5/esp_crypto_lock.h new file mode 100644 index 000000000000..617d0231d85f --- /dev/null +++ b/components/esp_hw_support/include/soc/esp32c5/esp_crypto_lock.h @@ -0,0 +1,80 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Acquire lock for HMAC cryptography peripheral + * + * Internally also locks the SHA peripheral, as the HMAC depends on the SHA peripheral + */ +void esp_crypto_hmac_lock_acquire(void); + +/** + * @brief Release lock for HMAC cryptography peripheral + * + * Internally also releases the SHA peripheral, as the HMAC depends on the SHA peripheral + */ +void esp_crypto_hmac_lock_release(void); + +/** + * @brief Acquire lock for DS cryptography peripheral + * + * Internally also locks the HMAC (which locks SHA), AES and MPI peripheral, as the DS depends on these peripherals + */ +void esp_crypto_ds_lock_acquire(void); + +/** + * @brief Release lock for DS cryptography peripheral + * + * Internally also releases the HMAC (which locks SHA), AES and MPI peripheral, as the DS depends on these peripherals + */ +void esp_crypto_ds_lock_release(void); + +/** + * @brief Acquire lock for the SHA and AES cryptography peripheral. + * + */ +void esp_crypto_sha_aes_lock_acquire(void); + +/** + * @brief Release lock for the SHA and AES cryptography peripheral. + * + */ +void esp_crypto_sha_aes_lock_release(void); + + +/** + * @brief Acquire lock for the mpi cryptography peripheral. + * + */ +void esp_crypto_mpi_lock_acquire(void); + +/** + * @brief Release lock for the mpi/rsa cryptography peripheral. + * + */ +void esp_crypto_mpi_lock_release(void); + +/** + * @brief Acquire lock for the ECC cryptography peripheral. + * + */ +void esp_crypto_ecc_lock_acquire(void); + +/** + * @brief Release lock for the ECC cryptography peripheral. + * + */ +void esp_crypto_ecc_lock_release(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hw_support/include/soc/esp32c5/rtc.h b/components/esp_hw_support/include/soc/esp32c5/rtc.h new file mode 100644 index 000000000000..4892a1d1792b --- /dev/null +++ b/components/esp_hw_support/include/soc/esp32c5/rtc.h @@ -0,0 +1,32 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file esp32c5/rtc.h + * + * This file contains declarations of rtc related functions. + */ + +/** + * @brief Get current value of RTC counter in microseconds + * + * Note: this function may take up to 1 RTC_SLOW_CLK cycle to execute + * + * @return current value of RTC counter in microseconds + */ +uint64_t esp_rtc_get_time_us(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hw_support/modem_clock.c b/components/esp_hw_support/modem_clock.c index f17551378885..901163dd7f32 100644 --- a/components/esp_hw_support/modem_clock.c +++ b/components/esp_hw_support/modem_clock.c @@ -245,8 +245,8 @@ void IRAM_ATTR modem_clock_module_mac_reset(periph_module_t module) case PERIPH_IEEE802154_MODULE: modem_syscon_ll_reset_zbmac(ctx->hal->syscon_dev); break; - default: #endif + default: assert(0); } portEXIT_CRITICAL_SAFE(&ctx->lock); diff --git a/components/esp_hw_support/port/esp32c5/CMakeLists.txt b/components/esp_hw_support/port/esp32c5/CMakeLists.txt index e69de29bb2d1..f95ebf131dba 100644 --- a/components/esp_hw_support/port/esp32c5/CMakeLists.txt +++ b/components/esp_hw_support/port/esp32c5/CMakeLists.txt @@ -0,0 +1,17 @@ +set(srcs "rtc_clk_init.c" + "rtc_clk.c" + "rtc_time.c" + "pmu_init.c" + "pmu_param.c" + "chip_info.c" + ) + +if(NOT BOOTLOADER_BUILD) + list(APPEND srcs "sar_periph_ctrl.c" + "esp_crypto_lock.c") +endif() + +add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" "${srcs}") + +target_sources(${COMPONENT_LIB} PRIVATE "${srcs}") +target_include_directories(${COMPONENT_LIB} PUBLIC . private_include) diff --git a/components/esp_hw_support/port/esp32c5/Kconfig.hw_support b/components/esp_hw_support/port/esp32c5/Kconfig.hw_support new file mode 100644 index 000000000000..87910b7d1c07 --- /dev/null +++ b/components/esp_hw_support/port/esp32c5/Kconfig.hw_support @@ -0,0 +1,41 @@ +choice ESP32C5_REV_MIN + prompt "Minimum Supported ESP32-C5 Revision" + default ESP32C5_REV_MIN_0 + help + Required minimum chip revision. ESP-IDF will check for it and + reject to boot if the chip revision fails the check. + This ensures the chip used will have some modifications (features, or bugfixes). + + The complied binary will only support chips above this revision, + this will also help to reduce binary size. + + config ESP32C5_REV_MIN_0 + bool "Rev v0.0" +endchoice + +config ESP32C5_REV_MIN_FULL + int + default 0 if ESP32C5_REV_MIN_0 + +config ESP_REV_MIN_FULL + int + default ESP32C5_REV_MIN_FULL + + # + # MAX Revision + # + + comment "Maximum Supported ESP32-C5 Revision (Rev v0.99)" + # Maximum revision that IDF supports. + # It can not be changed by user. + # Only Espressif can change it when a new version will be supported in IDF. + # Supports all chips starting from ESP32C5_REV_MIN_FULL to ESP32C5_REV_MAX_FULL + +config ESP32C5_REV_MAX_FULL + int + default 99 + # keep in sync the "Maximum Supported Revision" description with this value + +config ESP_REV_MAX_FULL + int + default ESP32C5_REV_MAX_FULL diff --git a/components/esp_hw_support/port/esp32c5/Kconfig.mac b/components/esp_hw_support/port/esp32c5/Kconfig.mac new file mode 100644 index 000000000000..126ef59b83f5 --- /dev/null +++ b/components/esp_hw_support/port/esp32c5/Kconfig.mac @@ -0,0 +1,46 @@ +choice ESP32C5_UNIVERSAL_MAC_ADDRESSES + bool "Number of universally administered (by IEEE) MAC address" + default ESP32C5_UNIVERSAL_MAC_ADDRESSES_FOUR + help + Configure the number of universally administered (by IEEE) MAC addresses. + + During initialization, MAC addresses for each network interface are generated or derived from a + single base MAC address. + + If the number of universal MAC addresses is four, all four interfaces (WiFi station, WiFi softap, + Bluetooth and Ethernet) receive a universally administered MAC address. These are generated + sequentially by adding 0, 1, 2 and 3 (respectively) to the final octet of the base MAC address. + + If the number of universal MAC addresses is two, only two interfaces (WiFi station and Bluetooth) + receive a universally administered MAC address. These are generated sequentially by adding 0 + and 1 (respectively) to the base MAC address. The remaining two interfaces (WiFi softap and Ethernet) + receive local MAC addresses. These are derived from the universal WiFi station and Bluetooth MAC + addresses, respectively. + + When using the default (Espressif-assigned) base MAC address, either setting can be used. When using + a custom universal MAC address range, the correct setting will depend on the allocation of MAC + addresses in this range (either 2 or 4 per device.) + + Note that ESP32-C5 has no integrated Ethernet MAC. Although it's possible to use the esp_read_mac() + API to return a MAC for Ethernet, this can only be used with an external MAC peripheral. + + config ESP32C5_UNIVERSAL_MAC_ADDRESSES_TWO + bool "Two" + select ESP_MAC_UNIVERSAL_MAC_ADDRESSES_TWO + select ESP_MAC_ADDR_UNIVERSE_WIFI_STA + select ESP_MAC_ADDR_UNIVERSE_BT + + config ESP32C5_UNIVERSAL_MAC_ADDRESSES_FOUR + bool "Four" + select ESP_MAC_UNIVERSAL_MAC_ADDRESSES_FOUR + select ESP_MAC_ADDR_UNIVERSE_IEEE802154 + select ESP_MAC_ADDR_UNIVERSE_WIFI_STA + select ESP_MAC_ADDR_UNIVERSE_WIFI_AP + select ESP_MAC_ADDR_UNIVERSE_BT + select ESP_MAC_ADDR_UNIVERSE_ETH +endchoice + +config ESP32C5_UNIVERSAL_MAC_ADDRESSES + int + default 2 if ESP32C5_UNIVERSAL_MAC_ADDRESSES_TWO + default 4 if ESP32C5_UNIVERSAL_MAC_ADDRESSES_FOUR diff --git a/components/esp_hw_support/port/esp32c5/Kconfig.rtc b/components/esp_hw_support/port/esp32c5/Kconfig.rtc new file mode 100644 index 000000000000..9c756e882c5c --- /dev/null +++ b/components/esp_hw_support/port/esp32c5/Kconfig.rtc @@ -0,0 +1,37 @@ +choice RTC_CLK_SRC + prompt "RTC clock source" + default RTC_CLK_SRC_INT_RC32K + help + Choose which clock is used as RTC clock source. + + config RTC_CLK_SRC_EXT_CRYS + bool "External 32kHz crystal" + select ESP_SYSTEM_RTC_EXT_XTAL + config RTC_CLK_SRC_EXT_OSC + bool "External 32kHz oscillator at 32K_XP pin" + select ESP_SYSTEM_RTC_EXT_OSC + config RTC_CLK_SRC_INT_RC32K + bool "Internal 32kHz RC oscillator" +endchoice + +config RTC_CLK_CAL_CYCLES + int "Number of cycles for RTC_SLOW_CLK calibration" + default 3000 if RTC_CLK_SRC_EXT_CRYS || RTC_CLK_SRC_EXT_OSC || RTC_CLK_SRC_INT_RC32K + default 1024 if RTC_CLK_SRC_INT_RC + range 0 27000 if RTC_CLK_SRC_EXT_CRYS || RTC_CLK_SRC_EXT_OSC || RTC_CLK_SRC_INT_RC32K + range 0 32766 if RTC_CLK_SRC_INT_RC + help + When the startup code initializes RTC_SLOW_CLK, it can perform + calibration by comparing the RTC_SLOW_CLK frequency with main XTAL + frequency. This option sets the number of RTC_SLOW_CLK cycles measured + by the calibration routine. Higher numbers increase calibration + precision, which may be important for applications which spend a lot of + time in deep sleep. Lower numbers reduce startup time. + + When this option is set to 0, clock calibration will not be performed at + startup, and approximate clock frequencies will be assumed: + + - 136000 Hz if internal RC oscillator is used as clock source. For this use value 1024. + - 32768 Hz if the 32k crystal oscillator is used. For this use value 3000 or more. + In case more value will help improve the definition of the launch of the crystal. + If the crystal could not start, it will be switched to internal RC. diff --git a/components/esp_hw_support/port/esp32c5/chip_info.c b/components/esp_hw_support/port/esp32c5/chip_info.c new file mode 100644 index 000000000000..04b7ba11134f --- /dev/null +++ b/components/esp_hw_support/port/esp32c5/chip_info.c @@ -0,0 +1,18 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "esp_chip_info.h" +#include "hal/efuse_hal.h" + +void esp_chip_info(esp_chip_info_t *out_info) +{ + memset(out_info, 0, sizeof(*out_info)); + out_info->model = CHIP_ESP32C5; + out_info->revision = efuse_hal_chip_revision(); + out_info->cores = 1; + out_info->features = CHIP_FEATURE_WIFI_BGN | CHIP_FEATURE_BLE; +} diff --git a/components/esp_hw_support/port/esp32c5/cpu_region_protect.c b/components/esp_hw_support/port/esp32c5/cpu_region_protect.c index e69de29bb2d1..807cc90abfad 100644 --- a/components/esp_hw_support/port/esp32c5/cpu_region_protect.c +++ b/components/esp_hw_support/port/esp32c5/cpu_region_protect.c @@ -0,0 +1,30 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "sdkconfig.h" +#include "soc/soc.h" +#include "esp_cpu.h" +#include "esp_fault.h" + +#ifdef BOOTLOADER_BUILD +// Without L bit set +#define CONDITIONAL_NONE 0x0 +#define CONDITIONAL_RX PMP_R | PMP_X +#define CONDITIONAL_RW PMP_R | PMP_W +#define CONDITIONAL_RWX PMP_R | PMP_W | PMP_X +#else +// With L bit set +#define CONDITIONAL_NONE NONE +#define CONDITIONAL_RX RX +#define CONDITIONAL_RW RW +#define CONDITIONAL_RWX RWX +#endif + +void esp_cpu_configure_region_protection(void) +{ +// TODO: [ESP32C5] IDF-8833 +} diff --git a/components/esp_hw_support/port/esp32c5/esp_clk_tree.c b/components/esp_hw_support/port/esp32c5/esp_clk_tree.c index e69de29bb2d1..b5ccf2ccbd5b 100644 --- a/components/esp_hw_support/port/esp32c5/esp_clk_tree.c +++ b/components/esp_hw_support/port/esp32c5/esp_clk_tree.c @@ -0,0 +1,25 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "esp_clk_tree.h" +#include "esp_err.h" +#include "esp_check.h" +#include "soc/rtc.h" +#include "hal/clk_tree_hal.h" +#include "hal/clk_tree_ll.h" +#include "esp_private/esp_clk_tree_common.h" + +static const char *TAG = "esp_clk_tree"; + +esp_err_t esp_clk_tree_src_get_freq_hz(soc_module_clk_t clk_src, esp_clk_tree_src_freq_precision_t precision, +uint32_t *freq_value) +{ + // TODO: [ESP32C5] IDF-8642 + ESP_LOGW(TAG, "esp_clk_tree_src_get_freq_hz() has not implemented yet"); + *freq_value = 0; + return ESP_OK; +} diff --git a/components/esp_hw_support/port/esp32c5/esp_crypto_lock.c b/components/esp_hw_support/port/esp32c5/esp_crypto_lock.c new file mode 100644 index 000000000000..d5192c858925 --- /dev/null +++ b/components/esp_hw_support/port/esp32c5/esp_crypto_lock.c @@ -0,0 +1,89 @@ +/* + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include "esp_crypto_lock.h" + +/* Lock overview: +SHA: peripheral independent, but DMA is shared with AES +AES: peripheral independent, but DMA is shared with SHA +MPI/RSA: independent +ECC: independent +HMAC: needs SHA +DS: needs HMAC (which needs SHA), AES and MPI +*/ + +/* Lock for DS peripheral */ +static _lock_t s_crypto_ds_lock; + +/* Lock for HMAC peripheral */ +static _lock_t s_crypto_hmac_lock; + +/* Lock for the MPI/RSA peripheral, also used by the DS peripheral */ +static _lock_t s_crypto_mpi_lock; + +/* Single lock for SHA and AES, sharing a reserved GDMA channel */ +static _lock_t s_crypto_sha_aes_lock; + +/* Lock for ECC peripheral */ +static _lock_t s_crypto_ecc_lock; + +void esp_crypto_hmac_lock_acquire(void) +{ + _lock_acquire(&s_crypto_hmac_lock); + esp_crypto_sha_aes_lock_acquire(); +} + +void esp_crypto_hmac_lock_release(void) +{ + esp_crypto_sha_aes_lock_release(); + _lock_release(&s_crypto_hmac_lock); +} + +void esp_crypto_ds_lock_acquire(void) +{ + _lock_acquire(&s_crypto_ds_lock); + esp_crypto_hmac_lock_acquire(); + esp_crypto_mpi_lock_acquire(); +} + +void esp_crypto_ds_lock_release(void) +{ + esp_crypto_mpi_lock_release(); + esp_crypto_hmac_lock_release(); + _lock_release(&s_crypto_ds_lock); +} + +void esp_crypto_sha_aes_lock_acquire(void) +{ + _lock_acquire(&s_crypto_sha_aes_lock); +} + +void esp_crypto_sha_aes_lock_release(void) +{ + _lock_release(&s_crypto_sha_aes_lock); +} + +void esp_crypto_mpi_lock_acquire(void) +{ + _lock_acquire(&s_crypto_mpi_lock); +} + +void esp_crypto_mpi_lock_release(void) +{ + _lock_release(&s_crypto_mpi_lock); +} + +void esp_crypto_ecc_lock_acquire(void) +{ + _lock_acquire(&s_crypto_ecc_lock); +} + +void esp_crypto_ecc_lock_release(void) +{ + _lock_release(&s_crypto_ecc_lock); +} diff --git a/components/esp_hw_support/port/esp32c5/io_mux.c b/components/esp_hw_support/port/esp32c5/io_mux.c index e69de29bb2d1..6e9cd8430329 100644 --- a/components/esp_hw_support/port/esp32c5/io_mux.c +++ b/components/esp_hw_support/port/esp32c5/io_mux.c @@ -0,0 +1,33 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "freertos/FreeRTOS.h" +#include "esp_private/io_mux.h" +#include "hal/gpio_ll.h" + +static portMUX_TYPE s_io_mux_spinlock = portMUX_INITIALIZER_UNLOCKED; +static soc_module_clk_t s_io_mux_clk_src = 0; // by default, the clock source is not set explicitly by any consumer (e.g. SDM, Filter) + +esp_err_t io_mux_set_clock_source(soc_module_clk_t clk_src) +{ + bool clk_conflict = false; + // check is the IO MUX has been set to another clock source + portENTER_CRITICAL(&s_io_mux_spinlock); + if (s_io_mux_clk_src != 0 && s_io_mux_clk_src != clk_src) { + clk_conflict = true; + } else { + s_io_mux_clk_src = clk_src; + } + portEXIT_CRITICAL(&s_io_mux_spinlock); + + if (clk_conflict) { + return ESP_ERR_INVALID_STATE; + } + + gpio_ll_iomux_set_clk_src(clk_src); + + return ESP_OK; +} diff --git a/components/esp_hw_support/port/esp32c5/pmu_init.c b/components/esp_hw_support/port/esp32c5/pmu_init.c new file mode 100644 index 000000000000..f45c223e15a7 --- /dev/null +++ b/components/esp_hw_support/port/esp32c5/pmu_init.c @@ -0,0 +1,207 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include "sdkconfig.h" +#include "esp_attr.h" +#include "soc/soc.h" +#include "soc/pmu_struct.h" +#include "hal/pmu_hal.h" +#include "pmu_param.h" +#include "esp_private/esp_pmu.h" +#include "soc/regi2c_dig_reg.h" +#include "regi2c_ctrl.h" + +static __attribute__((unused)) const char *TAG = "pmu_init"; + +typedef struct { + const pmu_hp_system_power_param_t *power; + const pmu_hp_system_clock_param_t *clock; + const pmu_hp_system_digital_param_t *digital; + const pmu_hp_system_analog_param_t *analog; + const pmu_hp_system_retention_param_t *retent; +} pmu_hp_system_param_t; + +typedef struct { + const pmu_lp_system_power_param_t *power; + const pmu_lp_system_analog_param_t *analog; +} pmu_lp_system_param_t; + +pmu_context_t * __attribute__((weak)) IRAM_ATTR PMU_instance(void) +{ + /* It should be explicitly defined in the internal RAM, because this + * instance will be used in pmu_sleep.c */ + static DRAM_ATTR pmu_hal_context_t pmu_hal = { .dev = &PMU }; + static DRAM_ATTR pmu_sleep_machine_constant_t pmu_mc = PMU_SLEEP_MC_DEFAULT(); + static DRAM_ATTR pmu_context_t pmu_context = { .hal = &pmu_hal, .mc = (void *)&pmu_mc }; + return &pmu_context; +} + +void pmu_hp_system_init(pmu_context_t *ctx, pmu_hp_mode_t mode, pmu_hp_system_param_t *param) +{ + const pmu_hp_system_power_param_t *power = param->power; + const pmu_hp_system_clock_param_t *clock = param->clock; + const pmu_hp_system_digital_param_t *dig = param->digital; + const pmu_hp_system_analog_param_t *anlg = param->analog; + const pmu_hp_system_retention_param_t *ret = param->retent; + + assert(ctx->hal); + /* Default configuration of hp-system power in active, modem and sleep modes */ + pmu_ll_hp_set_dig_power(ctx->hal->dev, mode, power->dig_power.val); + pmu_ll_hp_set_clk_power(ctx->hal->dev, mode, power->clk_power.val); + pmu_ll_hp_set_xtal_xpd (ctx->hal->dev, mode, power->xtal.xpd_xtal); + + /* Default configuration of hp-system clock in active, modem and sleep modes */ + pmu_ll_hp_set_icg_func (ctx->hal->dev, mode, clock->icg_func); + pmu_ll_hp_set_icg_apb (ctx->hal->dev, mode, clock->icg_apb); + pmu_ll_hp_set_icg_modem (ctx->hal->dev, mode, clock->icg_modem.code); + pmu_ll_hp_set_sysclk_nodiv (ctx->hal->dev, mode, clock->sysclk.dig_sysclk_nodiv); + pmu_ll_hp_set_icg_sysclk_enable (ctx->hal->dev, mode, clock->sysclk.icg_sysclk_en); + pmu_ll_hp_set_sysclk_slp_sel (ctx->hal->dev, mode, clock->sysclk.sysclk_slp_sel); + pmu_ll_hp_set_icg_sysclk_slp_sel(ctx->hal->dev, mode, clock->sysclk.icg_slp_sel); + pmu_ll_hp_set_dig_sysclk (ctx->hal->dev, mode, clock->sysclk.dig_sysclk_sel); + + /* Default configuration of hp-system digital sub-system in active, modem + * and sleep modes */ + pmu_ll_hp_set_uart_wakeup_enable(ctx->hal->dev, mode, dig->syscntl.uart_wakeup_en); + pmu_ll_hp_set_hold_all_lp_pad (ctx->hal->dev, mode, dig->syscntl.lp_pad_hold_all); + pmu_ll_hp_set_hold_all_hp_pad (ctx->hal->dev, mode, dig->syscntl.hp_pad_hold_all); + pmu_ll_hp_set_dig_pad_slp_sel (ctx->hal->dev, mode, dig->syscntl.dig_pad_slp_sel); + pmu_ll_hp_set_pause_watchdog (ctx->hal->dev, mode, dig->syscntl.dig_pause_wdt); + pmu_ll_hp_set_cpu_stall (ctx->hal->dev, mode, dig->syscntl.dig_cpu_stall); + + /* Default configuration of hp-system analog sub-system in active, modem and + * sleep modes */ + pmu_ll_hp_set_bias_xpd (ctx->hal->dev, mode, anlg->bias.xpd_bias); + pmu_ll_hp_set_dbg_atten (ctx->hal->dev, mode, anlg->bias.dbg_atten); + pmu_ll_hp_set_current_power_off (ctx->hal->dev, mode, anlg->bias.pd_cur); + pmu_ll_hp_set_bias_sleep_enable (ctx->hal->dev, mode, anlg->bias.bias_sleep); + pmu_ll_hp_set_regulator_sleep_memory_xpd (ctx->hal->dev, mode, anlg->regulator0.slp_mem_xpd); + pmu_ll_hp_set_regulator_sleep_logic_xpd (ctx->hal->dev, mode, anlg->regulator0.slp_logic_xpd); + pmu_ll_hp_set_regulator_xpd (ctx->hal->dev, mode, anlg->regulator0.xpd); + pmu_ll_hp_set_regulator_sleep_memory_dbias(ctx->hal->dev, mode, anlg->regulator0.slp_mem_dbias); + pmu_ll_hp_set_regulator_sleep_logic_dbias (ctx->hal->dev, mode, anlg->regulator0.slp_logic_dbias); + pmu_ll_hp_set_regulator_dbias (ctx->hal->dev, mode, anlg->regulator0.dbias); + pmu_ll_hp_set_regulator_driver_bar (ctx->hal->dev, mode, anlg->regulator1.drv_b); + + /* Default configuration of hp-system retention sub-system in active, modem + * and sleep modes */ + pmu_ll_hp_set_retention_param(ctx->hal->dev, mode, ret->retention.val); + pmu_ll_hp_set_backup_icg_func(ctx->hal->dev, mode, ret->backup_clk); + + /* Some PMU initial parameter configuration */ + pmu_ll_imm_update_dig_icg_modem_code(ctx->hal->dev, true); + pmu_ll_imm_update_dig_icg_switch(ctx->hal->dev, true); + + pmu_ll_hp_set_sleep_protect_mode(ctx->hal->dev, PMU_SLEEP_PROTECT_HP_LP_SLEEP); +} + +void pmu_lp_system_init(pmu_context_t *ctx, pmu_lp_mode_t mode, pmu_lp_system_param_t *param) +{ + const pmu_lp_system_power_param_t *power = param->power; + const pmu_lp_system_analog_param_t *anlg = param->analog; + + assert(ctx->hal); + /* Default configuration of lp-system power in active and sleep modes */ + pmu_ll_lp_set_dig_power(ctx->hal->dev, mode, power->dig_power.val); + pmu_ll_lp_set_clk_power(ctx->hal->dev, mode, power->clk_power.val); + pmu_ll_lp_set_xtal_xpd (ctx->hal->dev, PMU_MODE_LP_SLEEP, power->xtal.xpd_xtal); + + /* Default configuration of lp-system analog sub-system in active and + * sleep modes */ + pmu_ll_lp_set_bias_xpd (ctx->hal->dev, PMU_MODE_LP_SLEEP, anlg->bias.xpd_bias); + pmu_ll_lp_set_dbg_atten (ctx->hal->dev, PMU_MODE_LP_SLEEP, anlg->bias.dbg_atten); + pmu_ll_lp_set_current_power_off (ctx->hal->dev, PMU_MODE_LP_SLEEP, anlg->bias.pd_cur); + pmu_ll_lp_set_bias_sleep_enable (ctx->hal->dev, PMU_MODE_LP_SLEEP, anlg->bias.bias_sleep); + pmu_ll_lp_set_regulator_slp_xpd (ctx->hal->dev, mode, anlg->regulator0.slp_xpd); + pmu_ll_lp_set_regulator_xpd (ctx->hal->dev, mode, anlg->regulator0.xpd); + pmu_ll_lp_set_regulator_sleep_dbias(ctx->hal->dev, mode, anlg->regulator0.slp_dbias); + pmu_ll_lp_set_regulator_dbias (ctx->hal->dev, mode, anlg->regulator0.dbias); + pmu_ll_lp_set_regulator_driver_bar (ctx->hal->dev, mode, anlg->regulator1.drv_b); +} + +static inline void pmu_power_domain_force_default(pmu_context_t *ctx) +{ + assert(ctx); + // for bypass reserved power domain + const pmu_hp_power_domain_t pmu_hp_domains[] = { + PMU_HP_PD_TOP, + PMU_HP_PD_HP_AON, + PMU_HP_PD_CPU, + PMU_HP_PD_WIFI + }; + + for (uint8_t idx = 0; idx < (sizeof(pmu_hp_domains) / sizeof(pmu_hp_power_domain_t)); idx++) { + pmu_ll_hp_set_power_force_reset (ctx->hal->dev, pmu_hp_domains[idx], false); + pmu_ll_hp_set_power_force_isolate (ctx->hal->dev, pmu_hp_domains[idx], false); + pmu_ll_hp_set_power_force_power_up (ctx->hal->dev, pmu_hp_domains[idx], false); + pmu_ll_hp_set_power_force_no_reset (ctx->hal->dev, pmu_hp_domains[idx], false); + pmu_ll_hp_set_power_force_no_isolate(ctx->hal->dev, pmu_hp_domains[idx], false); + pmu_ll_hp_set_power_force_power_down(ctx->hal->dev, pmu_hp_domains[idx], false); + } + /* Isolate all memory banks while sleeping, avoid memory leakage current */ + pmu_ll_hp_set_memory_no_isolate (ctx->hal->dev, 0); + + pmu_ll_lp_set_power_force_reset (ctx->hal->dev, false); + pmu_ll_lp_set_power_force_isolate (ctx->hal->dev, false); + pmu_ll_lp_set_power_force_power_up (ctx->hal->dev, false); + pmu_ll_lp_set_power_force_no_reset (ctx->hal->dev, false); + pmu_ll_lp_set_power_force_no_isolate(ctx->hal->dev, false); + pmu_ll_lp_set_power_force_power_down(ctx->hal->dev, false); +} + +static inline void pmu_hp_system_param_default(pmu_hp_mode_t mode, pmu_hp_system_param_t *param) +{ + param->power = pmu_hp_system_power_param_default(mode); + param->clock = pmu_hp_system_clock_param_default(mode); + param->digital = pmu_hp_system_digital_param_default(mode); + param->analog = pmu_hp_system_analog_param_default(mode); + param->retent = pmu_hp_system_retention_param_default(mode); +} + +static void pmu_hp_system_init_default(pmu_context_t *ctx) +{ + assert(ctx); + pmu_hp_system_param_t param = { 0 }; + for (pmu_hp_mode_t mode = PMU_MODE_HP_ACTIVE; mode < PMU_MODE_HP_MAX; mode++) { + pmu_hp_system_param_default(mode, ¶m); + pmu_hp_system_init(ctx, mode, ¶m); + } +} + +static inline void pmu_lp_system_param_default(pmu_lp_mode_t mode, pmu_lp_system_param_t *param) +{ + param->power = pmu_lp_system_power_param_default(mode); + param->analog = pmu_lp_system_analog_param_default(mode); +} + +static void pmu_lp_system_init_default(pmu_context_t *ctx) +{ + assert(ctx); + pmu_lp_system_param_t param; + for (pmu_lp_mode_t mode = PMU_MODE_LP_ACTIVE; mode < PMU_MODE_LP_MAX; mode++) { + pmu_lp_system_param_default(mode, ¶m); + pmu_lp_system_init(ctx, mode, ¶m); + } +} + +void pmu_init(void) +{ + /* Peripheral reg i2c power up */ + SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_PERIF_I2C_RSTB); + SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_XPD_PERIF_I2C); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_ENIF_RTC_DREG, 1); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_ENIF_DIG_DREG, 1); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_RTC_REG, 0); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_DIG_REG, 0); + + pmu_hp_system_init_default(PMU_instance()); + pmu_lp_system_init_default(PMU_instance()); + + pmu_power_domain_force_default(PMU_instance()); +} diff --git a/components/esp_hw_support/port/esp32c5/pmu_param.c b/components/esp_hw_support/port/esp32c5/pmu_param.c new file mode 100644 index 000000000000..3a8d6aacf1d8 --- /dev/null +++ b/components/esp_hw_support/port/esp32c5/pmu_param.c @@ -0,0 +1,447 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include "sdkconfig.h" +#include "soc/soc.h" +#include "pmu_param.h" +#include "soc/pmu_icg_mapping.h" +#include "esp_private/esp_pmu.h" + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) +#endif + +#define PMU_HP_ACTIVE_POWER_CONFIG_DEFAULT() { \ + .dig_power = { \ + .vdd_spi_pd_en = 0, \ + .mem_dslp = 0, \ + .mem_pd_en = 0, \ + .wifi_pd_en = 0, \ + .cpu_pd_en = 0, \ + .aon_pd_en = 0, \ + .top_pd_en = 0 \ + }, \ + .clk_power = { \ + .i2c_iso_en = 0, \ + .i2c_retention = 0, \ + .xpd_bb_i2c = 1, \ + .xpd_bbpll_i2c = 1, \ + .xpd_bbpll = 1 \ + }, \ + .xtal = { \ + .xpd_xtal = 1 \ + } \ +} + +#define PMU_HP_MODEM_POWER_CONFIG_DEFAULT() { \ + .dig_power = { \ + .vdd_spi_pd_en = 0, \ + .mem_dslp = 0, \ + .mem_pd_en = 0, \ + .wifi_pd_en = 0, \ + .cpu_pd_en = 1, \ + .aon_pd_en = 0, \ + .top_pd_en = 0 \ + }, \ + .clk_power = { \ + .i2c_iso_en = 0, \ + .i2c_retention = 0, \ + .xpd_bb_i2c = 1, \ + .xpd_bbpll_i2c = 1, \ + .xpd_bbpll = 1 \ + }, \ + .xtal = { \ + .xpd_xtal = 1 \ + } \ +} + +#define PMU_HP_SLEEP_POWER_CONFIG_DEFAULT() { \ + .dig_power = { \ + .vdd_spi_pd_en = 1, \ + .mem_dslp = 0, \ + .mem_pd_en = 0, \ + .wifi_pd_en = 1, \ + .cpu_pd_en = 0, \ + .aon_pd_en = 0, \ + .top_pd_en = 0 \ + }, \ + .clk_power = { \ + .i2c_iso_en = 1, \ + .i2c_retention = 1, \ + .xpd_bb_i2c = 1, \ + .xpd_bbpll_i2c = 0, \ + .xpd_bbpll = 0, \ + }, \ + .xtal = { \ + .xpd_xtal = 0 \ + } \ +} + +const pmu_hp_system_power_param_t * pmu_hp_system_power_param_default(pmu_hp_mode_t mode) +{ + static const pmu_hp_system_power_param_t hp_power[] = { + PMU_HP_ACTIVE_POWER_CONFIG_DEFAULT(), + PMU_HP_MODEM_POWER_CONFIG_DEFAULT(), + PMU_HP_SLEEP_POWER_CONFIG_DEFAULT() + }; + assert(mode < ARRAY_SIZE(hp_power)); + return &hp_power[mode]; +} + +#define PMU_HP_ACTIVE_CLOCK_CONFIG_DEFAULT() { \ + .icg_func = 0xffffffff, \ + .icg_apb = 0xffffffff, \ + .icg_modem = { \ + .code = PMU_HP_ICG_MODEM_CODE_ACTIVE \ + }, \ + .sysclk = { \ + .dig_sysclk_nodiv = 0, \ + .icg_sysclk_en = 1, \ + .sysclk_slp_sel = 0, \ + .icg_slp_sel = 0, \ + .dig_sysclk_sel = PMU_HP_SYSCLK_XTAL \ + } \ +} + +#define PMU_HP_MODEM_CLOCK_CONFIG_DEFAULT() { \ + .icg_func = 0, \ + .icg_apb = 0, \ + .icg_modem = { \ + .code = PMU_HP_ICG_MODEM_CODE_MODEM \ + }, \ + .sysclk = { \ + .dig_sysclk_nodiv = 0, \ + .icg_sysclk_en = 1, \ + .sysclk_slp_sel = 1, \ + .icg_slp_sel = 1, \ + .dig_sysclk_sel = PMU_HP_SYSCLK_PLL \ + } \ +} + +#define PMU_HP_SLEEP_CLOCK_CONFIG_DEFAULT() { \ + .icg_func = 0, \ + .icg_apb = 0, \ + .icg_modem = { \ + .code = PMU_HP_ICG_MODEM_CODE_SLEEP \ + }, \ + .sysclk = { \ + .dig_sysclk_nodiv = 0, \ + .icg_sysclk_en = 0, \ + .sysclk_slp_sel = 1, \ + .icg_slp_sel = 1, \ + .dig_sysclk_sel = PMU_HP_SYSCLK_XTAL \ + } \ +} + +const pmu_hp_system_clock_param_t * pmu_hp_system_clock_param_default(pmu_hp_mode_t mode) +{ + static const pmu_hp_system_clock_param_t hp_clock[] = { + PMU_HP_ACTIVE_CLOCK_CONFIG_DEFAULT(), + PMU_HP_MODEM_CLOCK_CONFIG_DEFAULT(), + PMU_HP_SLEEP_CLOCK_CONFIG_DEFAULT() + }; + assert(mode < ARRAY_SIZE(hp_clock)); + return &hp_clock[mode]; +} + +#define PMU_HP_ACTIVE_DIGITAL_CONFIG_DEFAULT() { \ + .syscntl = { \ + .uart_wakeup_en = 0, \ + .lp_pad_hold_all = 0, \ + .hp_pad_hold_all = 0, \ + .dig_pad_slp_sel = 0, \ + .dig_pause_wdt = 0, \ + .dig_cpu_stall = 0 \ + } \ +} + +#define PMU_HP_MODEM_DIGITAL_CONFIG_DEFAULT() { \ + .syscntl = { \ + .uart_wakeup_en = 1, \ + .lp_pad_hold_all = 0, \ + .hp_pad_hold_all = 0, \ + .dig_pad_slp_sel = 0, \ + .dig_pause_wdt = 1, \ + .dig_cpu_stall = 1 \ + } \ +} + +#define PMU_HP_SLEEP_DIGITAL_CONFIG_DEFAULT() { \ + .syscntl = { \ + .uart_wakeup_en = 1, \ + .lp_pad_hold_all = 0, \ + .hp_pad_hold_all = 0, \ + .dig_pad_slp_sel = 1, \ + .dig_pause_wdt = 1, \ + .dig_cpu_stall = 1 \ + } \ +} + +const pmu_hp_system_digital_param_t * pmu_hp_system_digital_param_default(pmu_hp_mode_t mode) +{ + static const pmu_hp_system_digital_param_t hp_digital[] = { + PMU_HP_ACTIVE_DIGITAL_CONFIG_DEFAULT(), + PMU_HP_MODEM_DIGITAL_CONFIG_DEFAULT(), + PMU_HP_SLEEP_DIGITAL_CONFIG_DEFAULT() + }; + assert(mode < ARRAY_SIZE(hp_digital)); + return &hp_digital[mode]; +} + +#define PMU_HP_ACTIVE_ANALOG_CONFIG_DEFAULT() { \ + .bias = { \ + .xpd_bias = 1, \ + .dbg_atten = 0x0, \ + .pd_cur = 0, \ + .bias_sleep = 0 \ + }, \ + .regulator0 = { \ + .lp_dbias_vol = 0xd, \ + .hp_dbias_vol = 0x1c,\ + .dbias_sel = 1, \ + .dbias_init = 1, \ + .slp_mem_xpd = 0, \ + .slp_logic_xpd = 0, \ + .xpd = 1, \ + .slp_mem_dbias = 0, \ + .slp_logic_dbias = 0, \ + .dbias = HP_CALI_DBIAS \ + }, \ + .regulator1 = { \ + .drv_b = 0x0 \ + } \ +} + +#define PMU_HP_MODEM_ANALOG_CONFIG_DEFAULT() { \ + .bias = { \ + .xpd_bias = 0, \ + .dbg_atten = 0x0, \ + .pd_cur = 0, \ + .bias_sleep = 0 \ + }, \ + .regulator0 = { \ + .slp_mem_xpd = 0, \ + .slp_logic_xpd = 0, \ + .xpd = 1, \ + .slp_mem_dbias = 0, \ + .slp_logic_dbias = 0, \ + .dbias = HP_CALI_DBIAS \ + }, \ + .regulator1 = { \ + .drv_b = 0x0 \ + } \ +} + +#define PMU_HP_SLEEP_ANALOG_CONFIG_DEFAULT() { \ + .bias = { \ + .xpd_bias = 0, \ + .dbg_atten = 0x0, \ + .pd_cur = 0, \ + .bias_sleep = 0 \ + }, \ + .regulator0 = { \ + .slp_mem_xpd = 0, \ + .slp_logic_xpd = 0, \ + .xpd = 1, \ + .slp_mem_dbias = 0, \ + .slp_logic_dbias = 0, \ + .dbias = 1 \ + }, \ + .regulator1 = { \ + .drv_b = 0x0 \ + } \ +} + +const pmu_hp_system_analog_param_t * pmu_hp_system_analog_param_default(pmu_hp_mode_t mode) +{ + static const pmu_hp_system_analog_param_t hp_analog[] = { + PMU_HP_ACTIVE_ANALOG_CONFIG_DEFAULT(), + PMU_HP_MODEM_ANALOG_CONFIG_DEFAULT(), + PMU_HP_SLEEP_ANALOG_CONFIG_DEFAULT() + }; + assert(mode < ARRAY_SIZE(hp_analog)); + return &hp_analog[mode]; +} + +#define PMU_HP_RETENTION_REGDMA_CONFIG(dir, entry) ((((dir)<<2) | (entry & 0x3)) & 0x7) + +#define PMU_HP_ACTIVE_RETENTION_CONFIG_DEFAULT() { \ + .retention = { \ + .hp_sleep2active_backup_modem_clk_code = 2, \ + .hp_modem2active_backup_modem_clk_code = 2, \ + .hp_active_retention_mode = 0, \ + .hp_sleep2active_retention_en = 0, \ + .hp_modem2active_retention_en = 0, \ + .hp_sleep2active_backup_clk_sel = 0, \ + .hp_modem2active_backup_clk_sel = 1, \ + .hp_sleep2active_backup_mode = PMU_HP_RETENTION_REGDMA_CONFIG(0, 0), \ + .hp_modem2active_backup_mode = PMU_HP_RETENTION_REGDMA_CONFIG(0, 2), \ + .hp_sleep2active_backup_en = 0, \ + .hp_modem2active_backup_en = 0, \ + }, \ + .backup_clk = ( \ + BIT(PMU_ICG_FUNC_ENA_REGDMA) | \ + BIT(PMU_ICG_FUNC_ENA_TG0) | \ + BIT(PMU_ICG_FUNC_ENA_TG1) | \ + BIT(PMU_ICG_FUNC_ENA_HPBUS) | \ + BIT(PMU_ICG_FUNC_ENA_MSPI) | \ + BIT(PMU_ICG_FUNC_ENA_IOMUX) | \ + BIT(PMU_ICG_FUNC_ENA_SPI2) | \ + BIT(PMU_ICG_FUNC_ENA_UART0) | \ + BIT(PMU_ICG_FUNC_ENA_SYSTIMER) \ + ) \ +} + +#define PMU_HP_MODEM_RETENTION_CONFIG_DEFAULT() { \ + .retention = { \ + .hp_sleep2modem_backup_modem_clk_code = 1, \ + .hp_modem_retention_mode = 0, \ + .hp_sleep2modem_retention_en = 0, \ + .hp_sleep2modem_backup_clk_sel = 0, \ + .hp_sleep2modem_backup_mode = PMU_HP_RETENTION_REGDMA_CONFIG(0, 1), \ + .hp_sleep2modem_backup_en = 0, \ + }, \ + .backup_clk = ( \ + BIT(PMU_ICG_FUNC_ENA_REGDMA) | \ + BIT(PMU_ICG_FUNC_ENA_TG0) | \ + BIT(PMU_ICG_FUNC_ENA_TG1) | \ + BIT(PMU_ICG_FUNC_ENA_HPBUS) | \ + BIT(PMU_ICG_FUNC_ENA_MSPI) | \ + BIT(PMU_ICG_FUNC_ENA_IOMUX) | \ + BIT(PMU_ICG_FUNC_ENA_SPI2) | \ + BIT(PMU_ICG_FUNC_ENA_UART0) | \ + BIT(PMU_ICG_FUNC_ENA_SYSTIMER) \ + ) \ +} + +#define PMU_HP_SLEEP_RETENTION_CONFIG_DEFAULT() { \ + .retention = { \ + .hp_modem2sleep_backup_modem_clk_code = 0, \ + .hp_active2sleep_backup_modem_clk_code = 2, \ + .hp_sleep_retention_mode = 0, \ + .hp_modem2sleep_retention_en = 0, \ + .hp_active2sleep_retention_en = 0, \ + .hp_modem2sleep_backup_clk_sel = 0, \ + .hp_active2sleep_backup_clk_sel = 0, \ + .hp_modem2sleep_backup_mode = PMU_HP_RETENTION_REGDMA_CONFIG(1, 1), \ + .hp_active2sleep_backup_mode = PMU_HP_RETENTION_REGDMA_CONFIG(1, 0), \ + .hp_modem2sleep_backup_en = 0, \ + .hp_active2sleep_backup_en = 0, \ + }, \ + .backup_clk = ( \ + BIT(PMU_ICG_FUNC_ENA_REGDMA) | \ + BIT(PMU_ICG_FUNC_ENA_TG0) | \ + BIT(PMU_ICG_FUNC_ENA_TG1) | \ + BIT(PMU_ICG_FUNC_ENA_HPBUS) | \ + BIT(PMU_ICG_FUNC_ENA_MSPI) | \ + BIT(PMU_ICG_FUNC_ENA_IOMUX) | \ + BIT(PMU_ICG_FUNC_ENA_SPI2) | \ + BIT(PMU_ICG_FUNC_ENA_UART0) | \ + BIT(PMU_ICG_FUNC_ENA_SYSTIMER) \ + ) \ +} + +const pmu_hp_system_retention_param_t * pmu_hp_system_retention_param_default(pmu_hp_mode_t mode) +{ + static const pmu_hp_system_retention_param_t hp_retention[] = { + PMU_HP_ACTIVE_RETENTION_CONFIG_DEFAULT(), + PMU_HP_MODEM_RETENTION_CONFIG_DEFAULT(), + PMU_HP_SLEEP_RETENTION_CONFIG_DEFAULT() + }; + assert(mode < ARRAY_SIZE(hp_retention)); + return &hp_retention[mode]; +} + + +/** LP system default parameter */ + +#if CONFIG_ESP_SYSTEM_RTC_EXT_XTAL +# define PMU_SLOW_CLK_USE_EXT_XTAL (1) +#else +# define PMU_SLOW_CLK_USE_EXT_XTAL (0) +#endif + +#define PMU_LP_ACTIVE_POWER_CONFIG_DEFAULT() { \ + .dig_power = { \ + .mem_dslp = 0, \ + .peri_pd_en = 0, \ + }, \ + .clk_power = { \ + .xpd_xtal32k = PMU_SLOW_CLK_USE_EXT_XTAL, \ + .xpd_rc32k = 1, \ + .xpd_fosc = 1, \ + .pd_osc = 0 \ + } \ +} + +#define PMU_LP_SLEEP_POWER_CONFIG_DEFAULT() { \ + .dig_power = { \ + .mem_dslp = 1, \ + .peri_pd_en = 0, \ + }, \ + .clk_power = { \ + .xpd_xtal32k = 0, \ + .xpd_rc32k = 0, \ + .xpd_fosc = 0, \ + .pd_osc = 0 \ + }, \ + .xtal = { \ + .xpd_xtal = 0 \ + } \ +} + +const pmu_lp_system_power_param_t * pmu_lp_system_power_param_default(pmu_lp_mode_t mode) +{ + static const pmu_lp_system_power_param_t lp_power[] = { + PMU_LP_ACTIVE_POWER_CONFIG_DEFAULT(), + PMU_LP_SLEEP_POWER_CONFIG_DEFAULT() + }; + assert(mode < ARRAY_SIZE(lp_power)); + return &lp_power[mode]; +} + +#define PMU_LP_ACTIVE_ANALOG_CONFIG_DEFAULT() { \ + .regulator0 = { \ + .slp_xpd = 0, \ + .xpd = 1, \ + .slp_dbias = 0, \ + .dbias = LP_CALI_DBIAS \ + }, \ + .regulator1 = { \ + .drv_b = 0x0 \ + } \ +} + +#define PMU_LP_SLEEP_ANALOG_CONFIG_DEFAULT() { \ + .bias = { \ + .xpd_bias = 0, \ + .dbg_atten = 0, \ + .pd_cur = 1, \ + .bias_sleep = 1, \ + }, \ + .regulator0 = { \ + .slp_xpd = 0, \ + .xpd = 1, \ + .slp_dbias = 0, \ + .dbias = 12 \ + }, \ + .regulator1 = { \ + .drv_b = 0x0 \ + } \ +} + +const pmu_lp_system_analog_param_t * pmu_lp_system_analog_param_default(pmu_lp_mode_t mode) +{ + static const pmu_lp_system_analog_param_t lp_analog[] = { + PMU_LP_ACTIVE_ANALOG_CONFIG_DEFAULT(), + PMU_LP_SLEEP_ANALOG_CONFIG_DEFAULT() + }; + assert(mode < ARRAY_SIZE(lp_analog)); + return &lp_analog[mode]; +} 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 new file mode 100644 index 000000000000..b4c14c0eaa81 --- /dev/null +++ b/components/esp_hw_support/port/esp32c5/private_include/pmu_param.h @@ -0,0 +1,481 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include +#include "soc/soc_caps.h" +#if SOC_PMU_SUPPORTED +#include "soc/pmu_struct.h" +#include "hal/pmu_hal.h" +#endif + +// TODO: [ESP32C5] IDF-8643 + +#ifdef __cplusplus +extern "C" { +#endif + + +#define HP_CALI_DBIAS 25 +#define LP_CALI_DBIAS 26 + +#if SOC_PMU_SUPPORTED + +// FOR XTAL FORCE PU IN SLEEP +#define PMU_PD_CUR_SLEEP_ON 0 +#define PMU_BIASSLP_SLEEP_ON 0 + +// FOR BOTH LIGHTSLEEP & DEEPSLEEP +#define PMU_PD_CUR_SLEEP_DEFAULT 1 +#define PMU_BIASSLP_SLEEP_DEFAULT 1 +#define PMU_LP_XPD_SLEEP_DEFAULT 1 +#define PMU_LP_SLP_XPD_SLEEP_DEFAULT 0 +#define PMU_LP_SLP_DBIAS_SLEEP_DEFAULT 0 + +// FOR LIGHTSLEEP +#define PMU_HP_DRVB_LIGHTSLEEP 0 +#define PMU_LP_DRVB_LIGHTSLEEP 0 +#define PMU_HP_XPD_LIGHTSLEEP 1 + +#define PMU_DBG_ATTEN_LIGHTSLEEP_DEFAULT 0 +#define PMU_HP_DBIAS_LIGHTSLEEP_0V6 1 +#define PMU_LP_DBIAS_LIGHTSLEEP_0V7 12 + +// FOR DEEPSLEEP +#define PMU_DBG_HP_DEEPSLEEP 0 +#define PMU_HP_XPD_DEEPSLEEP 0 +#define PMU_LP_DRVB_DEEPSLEEP 0 + +#define PMU_DBG_ATTEN_DEEPSLEEP_DEFAULT 12 +#define PMU_LP_DBIAS_DEEPSLEEP_0V7 23 + +typedef struct { + pmu_hp_dig_power_reg_t dig_power; + pmu_hp_clk_power_reg_t clk_power; + pmu_hp_xtal_reg_t xtal; +} pmu_hp_system_power_param_t; + +const pmu_hp_system_power_param_t* pmu_hp_system_power_param_default(pmu_hp_mode_t mode); + +typedef struct { + uint32_t icg_func; + uint32_t icg_apb; + pmu_hp_icg_modem_reg_t icg_modem; + pmu_hp_sysclk_reg_t sysclk; +} pmu_hp_system_clock_param_t; + +const pmu_hp_system_clock_param_t* pmu_hp_system_clock_param_default(pmu_hp_mode_t mode); + +typedef struct { + pmu_hp_sys_cntl_reg_t syscntl; +} pmu_hp_system_digital_param_t; + +const pmu_hp_system_digital_param_t* pmu_hp_system_digital_param_default(pmu_hp_mode_t mode); + +typedef struct { + pmu_hp_bias_reg_t bias; + pmu_hp_regulator0_reg_t regulator0; + pmu_hp_regulator1_reg_t regulator1; +} pmu_hp_system_analog_param_t; + +const pmu_hp_system_analog_param_t* pmu_hp_system_analog_param_default(pmu_hp_mode_t mode); + +typedef struct { + pmu_hp_backup_reg_t retention; + uint32_t backup_clk; +} pmu_hp_system_retention_param_t; + +const pmu_hp_system_retention_param_t* pmu_hp_system_retention_param_default(pmu_hp_mode_t mode); + +typedef struct { + pmu_lp_dig_power_reg_t dig_power; + pmu_lp_clk_power_reg_t clk_power; + pmu_lp_xtal_reg_t xtal; +} pmu_lp_system_power_param_t; + +const pmu_lp_system_power_param_t* pmu_lp_system_power_param_default(pmu_lp_mode_t mode); + + + +typedef struct { + pmu_lp_bias_reg_t bias; + pmu_lp_regulator0_reg_t regulator0; + pmu_lp_regulator1_reg_t regulator1; +} pmu_lp_system_analog_param_t; + +const pmu_lp_system_analog_param_t* pmu_lp_system_analog_param_default(pmu_lp_mode_t mode); + + + +/* Following software configuration instance type from pmu_struct.h used for the PMU state machine in sleep flow*/ +typedef union { + struct { + uint32_t reserved0 : 21; + uint32_t vdd_spi_pd_en: 1; + uint32_t mem_dslp : 1; + uint32_t mem_pd_en : 4; + uint32_t wifi_pd_en : 1; + uint32_t reserved1 : 1; + uint32_t cpu_pd_en : 1; + uint32_t aon_pd_en : 1; + uint32_t top_pd_en : 1; + }; + struct { + uint32_t reserved2 : 26; + uint32_t i2c_iso_en : 1; + uint32_t i2c_retention: 1; + uint32_t xpd_bb_i2c : 1; + uint32_t xpd_bbpll_i2c: 1; + uint32_t xpd_bbpll : 1; + uint32_t reserved3 : 1; + }; + struct { + uint32_t reserved4 : 31; + uint32_t xpd_xtal : 1; + }; + uint32_t val; +} pmu_hp_power_t; + +typedef union { + struct { + uint32_t reserved0 : 30; + uint32_t mem_dslp : 1; + uint32_t peri_pd_en: 1; + }; + struct { + uint32_t reserved1 : 28; + uint32_t xpd_xtal32k: 1; + uint32_t xpd_rc32k : 1; + uint32_t xpd_fosc : 1; + uint32_t pd_osc : 1; + }; + struct { + uint32_t reserved2 : 31; + uint32_t xpd_xtal : 1; + }; + uint32_t val; +} pmu_lp_power_t; + +typedef struct { + struct { + uint32_t reserved0 : 25; + uint32_t xpd_bias : 1; + uint32_t dbg_atten : 4; + uint32_t pd_cur : 1; + uint32_t bias_sleep: 1; + }; + struct { + uint32_t reserved1 : 16; + uint32_t slp_mem_xpd : 1; + uint32_t slp_logic_xpd : 1; + uint32_t xpd : 1; + uint32_t slp_mem_dbias : 4; + uint32_t slp_logic_dbias: 4; + uint32_t dbias : 5; + }; + struct { + uint32_t reserved2: 8; + uint32_t drv_b : 24; + }; +} pmu_hp_analog_t; + +typedef struct { + struct { + uint32_t reserved0 : 25; + uint32_t xpd_bias : 1; + uint32_t dbg_atten : 4; + uint32_t pd_cur : 1; + uint32_t bias_sleep: 1; + }; + struct { + uint32_t reserved1: 21; + uint32_t slp_xpd : 1; + uint32_t xpd : 1; + uint32_t slp_dbias: 4; + uint32_t dbias : 5; + }; + struct { + uint32_t reserved2: 28; + uint32_t drv_b : 4; + }; +} pmu_lp_analog_t; + +typedef struct { + uint32_t modem_wakeup_wait_cycle; + uint16_t analog_wait_target_cycle; + uint16_t digital_power_down_wait_cycle; + uint16_t digital_power_supply_wait_cycle; + uint16_t digital_power_up_wait_cycle; + uint16_t pll_stable_wait_cycle; + uint8_t modify_icg_cntl_wait_cycle; + uint8_t switch_icg_cntl_wait_cycle; + uint8_t min_slp_slow_clk_cycle; +} pmu_hp_param_t; + +typedef struct { + uint16_t digital_power_supply_wait_cycle; + uint8_t min_slp_slow_clk_cycle; + uint8_t analog_wait_target_cycle; + uint8_t digital_power_down_wait_cycle; + uint8_t digital_power_up_wait_cycle; +} pmu_lp_param_t; + +typedef struct { + union { + uint16_t xtal_stable_wait_slow_clk_cycle; + uint16_t xtal_stable_wait_cycle; + }; +} pmu_hp_lp_param_t; + +#define PMU_HP_SLEEP_MIN_SLOW_CLK_CYCLES (10) +#define PMU_LP_SLEEP_MIN_SLOW_CLK_CYCLES (10) + +#define PMU_HP_WAKEUP_DELAY_CYCLES (0) +#define PMU_HP_XTAL_STABLE_WAIT_CYCLES (3155) /* Not used, Fast OSC as PMU work clock source is about 201 us, corresponding to PMU_LP_XTAL_STABLE_WAIT_SLOW_CLK_CYCLES */ +#define PMU_HP_PLL_STABLE_WAIT_CYCLES (2) +#define PMU_HP_ANALOG_WAIT_TARGET_CYCLES (2419) /* Fast OSC as PMU work clock source is about 154 us */ +#define PMU_HP_DIGITAL_POWER_SUPPLY_WAIT_CYCLES (32) +#define PMU_HP_DIGITAL_POWER_UP_WAIT_CYCLES (32) +#define PMU_HP_MODEM_WAKEUP_WAIT_CYCLES (20700) /* Fast OSC as PMU work clock source is about 1318.6 us */ + +#define PMU_LP_WAKEUP_DELAY_CYCLES (0) +#define PMU_LP_XTAL_STABLE_WAIT_SLOW_CLK_CYCLES (30) /* Slow OSC as PMU slow clock source is about 201 us */ +#define PMU_LP_ANALOG_WAIT_TARGET_CYCLES (23) /* Slow OSC as PMU slow clock source is about 154 us */ +#define PMU_LP_DIGITAL_POWER_SUPPLY_WAIT_CYCLES (32) /* Fast OSC as PMU work clock source is about 2 us */ +#define PMU_LP_DIGITAL_POWER_UP_WAIT_CYCLES (32) /* Fast OSC as PMU work clock source is about 2 us */ + +#define PMU_LP_ANALOG_WAIT_TARGET_TIME_DSLP_US (500) /* Slow OSC as PMU slow clock source in deepsleep is about 500 us */ + +typedef struct { + struct { + pmu_hp_power_t dig_power; + pmu_hp_power_t clk_power; + pmu_hp_power_t xtal; + } hp_sys; + struct { + pmu_lp_power_t dig_power; + pmu_lp_power_t clk_power; + pmu_lp_power_t xtal; + } lp_sys[PMU_MODE_LP_MAX]; +} pmu_sleep_power_config_t; + +#define PMU_SLEEP_POWER_CONFIG_DEFAULT(pd_flags) { \ + .hp_sys = { \ + .dig_power = { \ + .vdd_spi_pd_en = ((pd_flags) & PMU_SLEEP_PD_VDDSDIO) ? 1 : 0, \ + .wifi_pd_en = ((pd_flags) & PMU_SLEEP_PD_MODEM) ? 1 : 0, \ + .cpu_pd_en = ((pd_flags) & PMU_SLEEP_PD_CPU) ? 1 : 0, \ + .aon_pd_en = ((pd_flags) & PMU_SLEEP_PD_HP_AON) ? 1 : 0, \ + .top_pd_en = ((pd_flags) & PMU_SLEEP_PD_TOP) ? 1 : 0, \ + .mem_pd_en = 0, \ + .mem_dslp = 0 \ + }, \ + .clk_power = { \ + .i2c_iso_en = 1, \ + .i2c_retention = 1, \ + .xpd_bb_i2c = 0, \ + .xpd_bbpll_i2c = 0, \ + .xpd_bbpll = 0 \ + }, \ + .xtal = { \ + .xpd_xtal = ((pd_flags) & PMU_SLEEP_PD_XTAL) ? 0 : 1, \ + } \ + }, \ + .lp_sys[PMU_MODE_LP_ACTIVE] = { \ + .dig_power = { \ + .peri_pd_en = 0, \ + .mem_dslp = 0 \ + }, \ + .clk_power = { \ + .xpd_xtal32k = ((pd_flags) & PMU_SLEEP_PD_XTAL32K) ? 0 : 1, \ + .xpd_rc32k = ((pd_flags) & PMU_SLEEP_PD_RC32K) ? 0 : 1, \ + .xpd_fosc = 1 \ + } \ + }, \ + .lp_sys[PMU_MODE_LP_SLEEP] = { \ + .dig_power = { \ + .peri_pd_en = ((pd_flags) & PMU_SLEEP_PD_LP_PERIPH) ? 1 : 0, \ + .mem_dslp = 1 \ + }, \ + .clk_power = { \ + .xpd_xtal32k = ((pd_flags) & PMU_SLEEP_PD_XTAL32K) ? 0 : 1, \ + .xpd_rc32k = ((pd_flags) & PMU_SLEEP_PD_RC32K) ? 0 : 1, \ + .xpd_fosc = ((pd_flags) & PMU_SLEEP_PD_RC_FAST) ? 0 : 1 \ + }, \ + .xtal = { \ + .xpd_xtal = ((pd_flags) & PMU_SLEEP_PD_XTAL) ? 0 : 1, \ + } \ + } \ +} + +typedef struct { + pmu_hp_sys_cntl_reg_t syscntl; +} pmu_sleep_digital_config_t; + +#define PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(pd_flags) { \ + .syscntl = { \ + .dig_pad_slp_sel = ((pd_flags) & PMU_SLEEP_PD_TOP) ? 0 : 1, \ + } \ +} + +typedef struct { + struct { + pmu_hp_analog_t analog; + } hp_sys; + struct { + pmu_lp_analog_t analog; + } lp_sys[PMU_MODE_LP_MAX]; +} pmu_sleep_analog_config_t; + +#define PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(pd_flags) { \ + .hp_sys = { \ + .analog = { \ + .drv_b = PMU_HP_DRVB_LIGHTSLEEP, \ + .pd_cur = PMU_PD_CUR_SLEEP_DEFAULT, \ + .bias_sleep = PMU_BIASSLP_SLEEP_DEFAULT, \ + .xpd = PMU_HP_XPD_LIGHTSLEEP, \ + .dbg_atten = PMU_DBG_ATTEN_LIGHTSLEEP_DEFAULT, \ + .dbias = PMU_HP_DBIAS_LIGHTSLEEP_0V6 \ + } \ + }, \ + .lp_sys[PMU_MODE_LP_SLEEP] = { \ + .analog = { \ + .drv_b = PMU_LP_DRVB_DEEPSLEEP, \ + .pd_cur = PMU_PD_CUR_SLEEP_DEFAULT, \ + .bias_sleep = PMU_BIASSLP_SLEEP_DEFAULT, \ + .slp_xpd = PMU_LP_SLP_XPD_SLEEP_DEFAULT, \ + .slp_dbias = PMU_LP_SLP_DBIAS_SLEEP_DEFAULT, \ + .xpd = PMU_LP_XPD_SLEEP_DEFAULT, \ + .dbg_atten = PMU_DBG_ATTEN_LIGHTSLEEP_DEFAULT, \ + .dbias = PMU_LP_DBIAS_LIGHTSLEEP_0V7 \ + } \ + } \ +} + +#define PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(pd_flags) { \ + .hp_sys = { \ + .analog = { \ + .pd_cur = PMU_PD_CUR_SLEEP_ON, \ + .bias_sleep = PMU_BIASSLP_SLEEP_ON, \ + .xpd = PMU_HP_XPD_DEEPSLEEP, \ + .dbg_atten = PMU_DBG_HP_DEEPSLEEP \ + } \ + }, \ + .lp_sys[PMU_MODE_LP_SLEEP] = { \ + .analog = { \ + .drv_b = PMU_LP_DRVB_DEEPSLEEP, \ + .pd_cur = PMU_PD_CUR_SLEEP_DEFAULT, \ + .bias_sleep = PMU_BIASSLP_SLEEP_DEFAULT, \ + .slp_xpd = PMU_LP_SLP_XPD_SLEEP_DEFAULT, \ + .slp_dbias = PMU_LP_SLP_DBIAS_SLEEP_DEFAULT, \ + .xpd = PMU_LP_XPD_SLEEP_DEFAULT, \ + .dbg_atten = PMU_DBG_ATTEN_DEEPSLEEP_DEFAULT, \ + .dbias = PMU_LP_DBIAS_DEEPSLEEP_0V7 \ + } \ + } \ +} + +typedef struct { + pmu_hp_param_t hp_sys; + pmu_lp_param_t lp_sys; + pmu_hp_lp_param_t hp_lp; +} pmu_sleep_param_config_t; + +#define PMU_SLEEP_PARAM_CONFIG_DEFAULT(pd_flags) { \ + .hp_sys = { \ + .min_slp_slow_clk_cycle = PMU_HP_SLEEP_MIN_SLOW_CLK_CYCLES, \ + .analog_wait_target_cycle = PMU_HP_ANALOG_WAIT_TARGET_CYCLES, \ + .digital_power_supply_wait_cycle = PMU_HP_DIGITAL_POWER_SUPPLY_WAIT_CYCLES, \ + .digital_power_up_wait_cycle = PMU_HP_DIGITAL_POWER_UP_WAIT_CYCLES, \ + .modem_wakeup_wait_cycle = PMU_HP_MODEM_WAKEUP_WAIT_CYCLES, \ + .pll_stable_wait_cycle = PMU_HP_PLL_STABLE_WAIT_CYCLES \ + }, \ + .lp_sys = { \ + .min_slp_slow_clk_cycle = PMU_LP_SLEEP_MIN_SLOW_CLK_CYCLES, \ + .analog_wait_target_cycle = PMU_LP_ANALOG_WAIT_TARGET_CYCLES, \ + .digital_power_supply_wait_cycle = PMU_LP_DIGITAL_POWER_SUPPLY_WAIT_CYCLES, \ + .digital_power_up_wait_cycle = PMU_LP_DIGITAL_POWER_UP_WAIT_CYCLES \ + }, \ + .hp_lp = { \ + .xtal_stable_wait_slow_clk_cycle = PMU_LP_XTAL_STABLE_WAIT_SLOW_CLK_CYCLES \ + } \ +} + +typedef struct { + pmu_sleep_power_config_t power; + pmu_sleep_digital_config_t digital; + pmu_sleep_analog_config_t analog; + pmu_sleep_param_config_t param; +} pmu_sleep_config_t; + +typedef struct pmu_sleep_machine_constant { + struct { + uint16_t min_slp_time_us; /* Mininum sleep protection time (unit: microsecond) */ + uint8_t wakeup_wait_cycle; /* Modem wakeup signal (WiFi MAC and BEACON wakeup) waits for the slow & fast clock domain synchronization and the wakeup signal triggers the PMU FSM switching wait cycle (unit: slow clock cycle) */ + uint8_t reserved0; + uint16_t reserved1; + uint16_t analog_wait_time_us; /* LP LDO power up wait time (unit: microsecond) */ + uint16_t xtal_wait_stable_time_us; /* Main XTAL stabilization wait time (unit: microsecond) */ + uint8_t clk_switch_cycle; /* Clock switch to FOSC (unit: slow clock cycle) */ + uint8_t clk_power_on_wait_cycle; /* Clock power on wait cycle (unit: slow clock cycle) */ + uint16_t power_supply_wait_time_us; /* (unit: microsecond) */ + uint16_t power_up_wait_time_us; /* (unit: microsecond) */ + } lp; + struct { + uint16_t min_slp_time_us; /* Mininum 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 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) */ + uint16_t power_supply_wait_time_us; /* (unit: microsecond) */ + uint16_t power_up_wait_time_us; /* (unit: microsecond) */ + uint16_t regdma_s2m_work_time_us; /* Modem Subsystem (S2M switch) REGDMA restore time (unit: microsecond) */ + uint16_t regdma_s2a_work_time_us; /* SOC System (Digital Peripheral + Modem Subsystem) REGDMA (S2A switch) restore time (unit: microsecond) */ + uint16_t regdma_m2a_work_time_us; /* Digital Peripheral (M2A switch) REGDMA restore time (unit: microsecond) */ + uint16_t regdma_a2s_work_time_us; /* SOC System (Digital Peripheral + Modem Subsystem) REGDMA (A2S switch) backup time (unit: microsecond) */ + uint16_t regdma_rf_on_work_time_us; /* The REGDMA work time of RF enable (unit: microsecond) */ + uint16_t regdma_rf_off_work_time_us; /* The REGDMA work time of RF disable (unit: microsecond) */ + uint16_t xtal_wait_stable_time_us; /* Main XTAL stabilization wait time (unit: microsecond) */ + uint16_t pll_wait_stable_time_us; /* PLL stabilization wait time (unit: microsecond) */ + } hp; +} pmu_sleep_machine_constant_t; + +#define PMU_SLEEP_MC_DEFAULT() { \ + .lp = { \ + .min_slp_time_us = 450, \ + .wakeup_wait_cycle = 4, \ + .analog_wait_time_us = 154, \ + .xtal_wait_stable_time_us = 250, \ + .clk_switch_cycle = 1, \ + .clk_power_on_wait_cycle = 1, \ + .power_supply_wait_time_us = 2, \ + .power_up_wait_time_us = 2 \ + }, \ + .hp = { \ + .min_slp_time_us = 450, \ + .clock_domain_sync_time_us = 150, \ + .system_dfs_up_work_time_us = 124, \ + .analog_wait_time_us = 154, \ + .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, \ + .xtal_wait_stable_time_us = 250, \ + .pll_wait_stable_time_us = 1 \ + } \ +} + +#endif // SOC_PMU_SUPPORTED + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hw_support/port/esp32c5/rtc_clk.c b/components/esp_hw_support/port/esp32c5/rtc_clk.c new file mode 100644 index 000000000000..dbd235fd4acf --- /dev/null +++ b/components/esp_hw_support/port/esp32c5/rtc_clk.c @@ -0,0 +1,441 @@ +/* + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include "sdkconfig.h" +#include "esp32c5/rom/rtc.h" +#include "soc/rtc.h" +#include "esp_private/rtc_clk.h" +#include "esp_hw_log.h" +#include "esp_rom_sys.h" +#include "hal/clk_tree_ll.h" +#include "hal/regi2c_ctrl_ll.h" +#include "soc/io_mux_reg.h" +#include "soc/lp_aon_reg.h" +#include "esp_private/sleep_event.h" + +#ifdef BOOTLOADER_BUILD +#include "hal/modem_lpcon_ll.h" +#else +#include "esp_private/esp_modem_clock.h" +#endif + +static const char *TAG = "rtc_clk"; + +// Current PLL frequency, in 480MHz. Zero if PLL is not enabled. +static int s_cur_pll_freq; + +static uint32_t s_bbpll_digi_consumers_ref_count = 0; // Currently, it only tracks whether the 48MHz PHY clock is in-use by USB Serial/JTAG + +void rtc_clk_bbpll_add_consumer(void) +{ + s_bbpll_digi_consumers_ref_count += 1; +} + +void rtc_clk_bbpll_remove_consumer(void) +{ + s_bbpll_digi_consumers_ref_count -= 1; +} + +void rtc_clk_32k_enable(bool enable) +{ + if (enable) { + clk_ll_xtal32k_enable(CLK_LL_XTAL32K_ENABLE_MODE_CRYSTAL); + } else { + clk_ll_xtal32k_disable(); + } +} + +void rtc_clk_32k_enable_external(void) +{ + // EXT_OSC_SLOW_GPIO_NUM == GPIO_NUM_0 + PIN_INPUT_ENABLE(IO_MUX_GPIO0_REG); + REG_SET_BIT(LP_AON_GPIO_HOLD0_REG, BIT(EXT_OSC_SLOW_GPIO_NUM)); + clk_ll_xtal32k_enable(CLK_LL_XTAL32K_ENABLE_MODE_EXTERNAL); +} + +void rtc_clk_32k_bootstrap(uint32_t cycle) +{ + /* No special bootstrapping needed for ESP32-C5, 'cycle' argument is to keep the signature + * same as for the ESP32. Just enable the XTAL here. + */ + (void)cycle; + rtc_clk_32k_enable(true); +} + +bool rtc_clk_32k_enabled(void) +{ + return clk_ll_xtal32k_is_enabled(); +} + +void rtc_clk_rc32k_enable(bool enable) +{ + if (enable) { + clk_ll_rc32k_enable(); + esp_rom_delay_us(SOC_DELAY_RC32K_ENABLE); + } else { + clk_ll_rc32k_disable(); + } +} + +void rtc_clk_8m_enable(bool clk_8m_en) +{ + if (clk_8m_en) { + clk_ll_rc_fast_enable(); + esp_rom_delay_us(SOC_DELAY_RC_FAST_ENABLE); + } else { + clk_ll_rc_fast_disable(); + } +} + +bool rtc_clk_8m_enabled(void) +{ + return clk_ll_rc_fast_is_enabled(); +} + +void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src) +{ + clk_ll_rtc_slow_set_src(clk_src); + esp_rom_delay_us(SOC_DELAY_RTC_SLOW_CLK_SWITCH); +} + +soc_rtc_slow_clk_src_t rtc_clk_slow_src_get(void) +{ + return clk_ll_rtc_slow_get_src(); +} + +uint32_t rtc_clk_slow_freq_get_hz(void) +{ + switch (rtc_clk_slow_src_get()) { + // case SOC_RTC_SLOW_CLK_SRC_RC_SLOW: return SOC_CLK_RC_SLOW_FREQ_APPROX; + case SOC_RTC_SLOW_CLK_SRC_XTAL32K: return SOC_CLK_XTAL32K_FREQ_APPROX; + case SOC_RTC_SLOW_CLK_SRC_RC32K: return SOC_CLK_RC32K_FREQ_APPROX; + case SOC_RTC_SLOW_CLK_SRC_OSC_SLOW: return SOC_CLK_OSC_SLOW_FREQ_APPROX; + default: return 0; + } +} + +void rtc_clk_fast_src_set(soc_rtc_fast_clk_src_t clk_src) +{ + clk_ll_rtc_fast_set_src(clk_src); + esp_rom_delay_us(SOC_DELAY_RTC_FAST_CLK_SWITCH); +} + +soc_rtc_fast_clk_src_t rtc_clk_fast_src_get(void) +{ + return clk_ll_rtc_fast_get_src(); +} + +static void rtc_clk_bbpll_disable(void) +{ + clk_ll_bbpll_disable(); + s_cur_pll_freq = 0; +} + +static void rtc_clk_bbpll_enable(void) +{ + clk_ll_bbpll_enable(); +} + +static void rtc_clk_enable_i2c_ana_master_clock(bool enable) +{ +#ifdef BOOTLOADER_BUILD + modem_lpcon_ll_enable_i2c_master_clock(&MODEM_LPCON, enable); +#else + if (enable) { + modem_clock_module_enable(PERIPH_ANA_I2C_MASTER_MODULE); + } else { + modem_clock_module_disable(PERIPH_ANA_I2C_MASTER_MODULE); + } +#endif +} + +static void rtc_clk_bbpll_configure(rtc_xtal_freq_t xtal_freq, int pll_freq) +{ + assert((pll_freq == CLK_LL_PLL_160M_FREQ_MHZ) || \ + (pll_freq == CLK_LL_PLL_240M_FREQ_MHZ)); + /* Digital part */ + clk_ll_bbpll_set_freq_mhz(CLK_LL_PLL_480M_FREQ_MHZ); + /* Analog part */ + rtc_clk_enable_i2c_ana_master_clock(true); + /* BBPLL CALIBRATION START */ + regi2c_ctrl_ll_bbpll_calibration_start(); + clk_ll_bbpll_set_config(CLK_LL_PLL_480M_FREQ_MHZ, xtal_freq); + /* WAIT CALIBRATION DONE */ + while(!regi2c_ctrl_ll_bbpll_calibration_is_done()); + /* BBPLL CALIBRATION STOP */ + regi2c_ctrl_ll_bbpll_calibration_stop(); + rtc_clk_enable_i2c_ana_master_clock(false); + s_cur_pll_freq = CLK_LL_PLL_480M_FREQ_MHZ; +} + +/** + * Switch to use XTAL as the CPU clock source. + * Must satisfy: cpu_freq = XTAL_FREQ / div. + * Does not disable the PLL. + */ +static void rtc_clk_cpu_freq_to_xtal(int cpu_freq, int div) +{ + /* Configure clk mspi fast to XTAL*/ + clk_ll_mspi_fast_sel_clk(SOC_MOD_CLK_XTAL); + clk_ll_mspi_fast_set_divider(1); + + clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_XTAL); + clk_ll_ahb_set_divider(div); + clk_ll_cpu_set_divider(div); + esp_rom_set_cpu_ticks_per_us(cpu_freq); +} + +static void rtc_clk_cpu_freq_to_8m(void) +{ + /* Configure clk mspi fast to XTAL*/ + clk_ll_mspi_fast_sel_clk(SOC_MOD_CLK_XTAL); + clk_ll_mspi_fast_set_divider(1); + + clk_ll_ahb_set_divider(1); + clk_ll_cpu_set_divider(1); + clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_RC_FAST); + esp_rom_set_cpu_ticks_per_us(20); +} + +/** + * Switch to one of PLL-based frequencies. Current frequency can be XTAL or PLL. + * PLL must already be enabled. + * @param cpu_freq new CPU frequency + */ +static void rtc_clk_cpu_freq_to_pll_mhz(int cpu_freq_mhz) +{ + rtc_cpu_freq_config_t cfg; + rtc_clk_cpu_freq_mhz_to_config(cpu_freq_mhz, &cfg); + // Set AHB always be 40MHz + clk_ll_ahb_set_divider(cfg.source_freq_mhz / 40); + clk_ll_cpu_set_divider(cfg.div); + clk_ll_cpu_set_src(cfg.source); + esp_rom_set_cpu_ticks_per_us(cpu_freq_mhz); + + /* Configure clk mspi fast to 80m*/ + clk_ll_mspi_fast_set_divider(6); + clk_ll_mspi_fast_sel_clk(MSPI_CLK_SRC_SPLL); +} + +bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t *out_config) +{ + uint32_t source_freq_mhz; + soc_cpu_clk_src_t source; + uint32_t divider; // divider = freq of SOC_ROOT_CLK / freq of CPU_CLK + uint32_t real_freq_mhz; + + uint32_t xtal_freq = (uint32_t)rtc_clk_xtal_freq_get(); + if (freq_mhz == 48 || freq_mhz == 24 || freq_mhz == 16 || freq_mhz == 12 || freq_mhz == 8) { + divider = xtal_freq / freq_mhz; + source_freq_mhz = xtal_freq; + source = SOC_CPU_CLK_SRC_XTAL; + real_freq_mhz = freq_mhz; + } else if (freq_mhz == 240 || freq_mhz == 120) { + real_freq_mhz = freq_mhz; + source = SOC_CPU_CLK_SRC_PLL_F240; + source_freq_mhz = CLK_LL_PLL_240M_FREQ_MHZ; + divider = CLK_LL_PLL_240M_FREQ_MHZ / freq_mhz; + }else if (freq_mhz == 160 || freq_mhz == 80 || freq_mhz == 40) { + real_freq_mhz = freq_mhz; + source = SOC_CPU_CLK_SRC_PLL_F160; + source_freq_mhz = CLK_LL_PLL_160M_FREQ_MHZ; + divider = CLK_LL_PLL_160M_FREQ_MHZ / freq_mhz; + } else { + // unsupported frequency + return false; + } + *out_config = (rtc_cpu_freq_config_t) { + .source = source, + .div = divider, + .source_freq_mhz = source_freq_mhz, + .freq_mhz = real_freq_mhz + }; + return true; +} + +__attribute__((weak)) void rtc_clk_set_cpu_switch_to_bbpll(int event_id) +{ +} + +void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config) +{ + soc_cpu_clk_src_t old_cpu_clk_src = clk_ll_cpu_get_src(); + if (config->source == SOC_CPU_CLK_SRC_XTAL) { + /* Configure clk mspi fast to 80m*/ + rtc_clk_cpu_freq_to_xtal(config->freq_mhz, config->div); + if (((old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL_F160) || (old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL_F240)) && !s_bbpll_digi_consumers_ref_count) { + // We don't turn off the bbpll if some consumers depend on bbpll + rtc_clk_bbpll_disable(); + } + } else if ((config->source == SOC_CPU_CLK_SRC_PLL_F160) || (config->source == SOC_CPU_CLK_SRC_PLL_F240)) { + if ((old_cpu_clk_src != SOC_CPU_CLK_SRC_PLL_F160) && (old_cpu_clk_src != SOC_CPU_CLK_SRC_PLL_F240)) { + rtc_clk_set_cpu_switch_to_bbpll(SLEEP_EVENT_HW_BBPLL_EN_START); + rtc_clk_bbpll_enable(); + rtc_clk_bbpll_configure(rtc_clk_xtal_freq_get(), config->source_freq_mhz); + } + rtc_clk_cpu_freq_to_pll_mhz(config->freq_mhz); + rtc_clk_set_cpu_switch_to_bbpll(SLEEP_EVENT_HW_BBPLL_EN_STOP); + } else if (config->source == SOC_CPU_CLK_SRC_RC_FAST) { + rtc_clk_cpu_freq_to_8m(); + if (((old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL_F160) || (old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL_F240)) && !s_bbpll_digi_consumers_ref_count) { + // We don't turn off the bbpll if some consumers depend on bbpll + rtc_clk_bbpll_disable(); + } + } +} + +void rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t *out_config) +{ + soc_cpu_clk_src_t source = clk_ll_cpu_get_src(); + uint32_t source_freq_mhz; + uint32_t div; // div = freq of SOC_ROOT_CLK / freq of CPU_CLK + uint32_t freq_mhz; + switch (source) { + case SOC_CPU_CLK_SRC_XTAL: { + div = clk_ll_cpu_get_divider(); + source_freq_mhz = (uint32_t)rtc_clk_xtal_freq_get(); + freq_mhz = source_freq_mhz / div; + break; + } + case SOC_CPU_CLK_SRC_PLL_F160: { + div = clk_ll_cpu_get_divider(); + source_freq_mhz = CLK_LL_PLL_160M_FREQ_MHZ; + freq_mhz = source_freq_mhz / div; + break; + } + case SOC_CPU_CLK_SRC_PLL_F240: { + div = clk_ll_cpu_get_divider(); + source_freq_mhz = CLK_LL_PLL_240M_FREQ_MHZ; + freq_mhz = source_freq_mhz / div; + break; + } + case SOC_CPU_CLK_SRC_RC_FAST: + div = clk_ll_cpu_get_divider(); + source_freq_mhz = 20; + freq_mhz = source_freq_mhz / div; + break; + default: + ESP_HW_LOGE(TAG, "unsupported frequency configuration"); + abort(); + } + *out_config = (rtc_cpu_freq_config_t) { + .source = source, + .source_freq_mhz = source_freq_mhz, + .div = div, + .freq_mhz = freq_mhz + }; +} + +void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t *config) +{ + if (config->source == SOC_CPU_CLK_SRC_XTAL) { + rtc_clk_cpu_freq_to_xtal(config->freq_mhz, config->div); + } else if (((config->source == SOC_CPU_CLK_SRC_PLL_F160) || (config->source == SOC_CPU_CLK_SRC_PLL_F240)) && + s_cur_pll_freq == config->source_freq_mhz) { + rtc_clk_cpu_freq_to_pll_mhz(config->freq_mhz); + } else if (config->source == SOC_CPU_CLK_SRC_RC_FAST) { + rtc_clk_cpu_freq_to_8m(); + } else { + /* fallback */ + rtc_clk_cpu_freq_set_config(config); + } +} + +void rtc_clk_cpu_freq_set_xtal(void) +{ + rtc_clk_cpu_set_to_default_config(); + // We don't turn off the bbpll if some consumers depend on bbpll + if (!s_bbpll_digi_consumers_ref_count) { + rtc_clk_bbpll_disable(); + } +} + +void rtc_clk_cpu_set_to_default_config(void) +{ + int freq_mhz = (int)rtc_clk_xtal_freq_get(); + + rtc_clk_cpu_freq_to_xtal(freq_mhz, 1); +} + +void rtc_clk_cpu_freq_to_pll_and_pll_lock_release(int cpu_freq_mhz) +{ + rtc_clk_cpu_freq_to_pll_mhz(cpu_freq_mhz); + clk_ll_cpu_clk_src_lock_release(); +} + +rtc_xtal_freq_t rtc_clk_xtal_freq_get(void) +{ + return CONFIG_XTAL_FREQ; +} + +void rtc_clk_xtal_freq_update(rtc_xtal_freq_t xtal_freq) +{ + clk_ll_xtal_store_freq_mhz(xtal_freq); +} + +static uint32_t rtc_clk_ahb_freq_get(void) +{ + soc_cpu_clk_src_t source = clk_ll_cpu_get_src(); + uint32_t soc_root_freq_mhz; + uint32_t divider; + switch (source) { + case SOC_CPU_CLK_SRC_XTAL: + soc_root_freq_mhz = rtc_clk_xtal_freq_get(); + divider = clk_ll_ahb_get_divider(); + break; + case SOC_CPU_CLK_SRC_PLL_F160: + soc_root_freq_mhz = CLK_LL_PLL_160M_FREQ_MHZ; + divider = clk_ll_ahb_get_divider(); + break; + case SOC_CPU_CLK_SRC_PLL_F240: + soc_root_freq_mhz = CLK_LL_PLL_240M_FREQ_MHZ; + divider = clk_ll_ahb_get_divider(); + break; + case SOC_CPU_CLK_SRC_RC_FAST: + soc_root_freq_mhz = 20; + divider = clk_ll_ahb_get_divider(); + break; + default: + // Unknown SOC_ROOT clock source + soc_root_freq_mhz = 0; + divider = 1; + ESP_HW_LOGE(TAG, "Invalid SOC_ROOT_CLK"); + break; + } + return soc_root_freq_mhz / divider; +} + +uint32_t rtc_clk_apb_freq_get(void) +{ + return rtc_clk_ahb_freq_get() / clk_ll_apb_get_divider() * MHZ; +} + +void rtc_dig_clk8m_enable(void) +{ + clk_ll_rc_fast_digi_enable(); + esp_rom_delay_us(SOC_DELAY_RC_FAST_DIGI_SWITCH); +} + +void rtc_dig_clk8m_disable(void) +{ + clk_ll_rc_fast_digi_disable(); + esp_rom_delay_us(SOC_DELAY_RC_FAST_DIGI_SWITCH); +} + +bool rtc_dig_8m_enabled(void) +{ + return clk_ll_rc_fast_digi_is_enabled(); +} + +/* Name used in libphy.a:phy_chip_v7.o + * TODO: update the library to use rtc_clk_xtal_freq_get + */ +rtc_xtal_freq_t rtc_get_xtal(void) __attribute__((alias("rtc_clk_xtal_freq_get"))); diff --git a/components/esp_hw_support/port/esp32c5/rtc_clk_init.c b/components/esp_hw_support/port/esp32c5/rtc_clk_init.c new file mode 100644 index 000000000000..afaa53475fb8 --- /dev/null +++ b/components/esp_hw_support/port/esp32c5/rtc_clk_init.c @@ -0,0 +1,116 @@ +/* + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include "esp32c5/rom/ets_sys.h" +#include "esp32c5/rom/rtc.h" +#include "esp32c5/rom/uart.h" +#include "soc/rtc.h" +#include "esp_cpu.h" +#include "regi2c_ctrl.h" +#include "soc/lp_clkrst_reg.h" +#include "soc/regi2c_dig_reg.h" +#include "esp_hw_log.h" +#include "sdkconfig.h" +#include "esp_rom_uart.h" +#include "esp_private/esp_pmu.h" +#include "hal/clk_tree_ll.h" +// #include "hal/pmu_ll.h" +#include "hal/modem_syscon_ll.h" +#include "hal/modem_lpcon_ll.h" +#include "soc/pmu_reg.h" +#include "pmu_param.h" + +static const char *TAG = "rtc_clk_init"; + +/** + * Initialize the ICG map of some modem clock domains in the PMU_ACTIVE state + * + * A pre-initialization interface is used to initialize the ICG map of the + * MODEM_APB, I2C_MST and LP_APB clock domains in the PMU_ACTIVE state, and + * disable the clock gating of these clock domains in the PMU_ACTIVE state, + * because the system clock source (PLL) in the system boot up process needs + * to use the i2c master peripheral. + * + * ICG map of all modem clock domains under different power states (PMU_ACTIVE, + * PMU_MODEM and PMU_SLEEP) will be initialized in esp_perip_clk_init(). + */ +static void rtc_clk_modem_clock_domain_active_state_icg_map_preinit(void) +{ + /* Configure modem ICG code in PMU_ACTIVE state */ + pmu_ll_hp_set_icg_modem(&PMU, PMU_MODE_HP_ACTIVE, PMU_HP_ICG_MODEM_CODE_ACTIVE); + + /* Disable clock gating for MODEM_APB, I2C_MST and LP_APB clock domains in PMU_ACTIVE state */ + modem_syscon_ll_set_modem_apb_icg_bitmap(&MODEM_SYSCON, BIT(PMU_HP_ICG_MODEM_CODE_ACTIVE)); + modem_lpcon_ll_set_i2c_master_icg_bitmap(&MODEM_LPCON, BIT(PMU_HP_ICG_MODEM_CODE_ACTIVE)); + modem_lpcon_ll_set_lp_apb_icg_bitmap(&MODEM_LPCON, BIT(PMU_HP_ICG_MODEM_CODE_ACTIVE)); + + /* Software trigger force update modem ICG code and ICG switch */ + pmu_ll_imm_update_dig_icg_modem_code(&PMU, true); + pmu_ll_imm_update_dig_icg_switch(&PMU, true); +} + + +void rtc_clk_init(rtc_clk_config_t cfg) +{ + rtc_cpu_freq_config_t old_config, new_config; + + rtc_clk_modem_clock_domain_active_state_icg_map_preinit(); + + /* Set tuning parameters for RC_FAST, RC_SLOW, and RC32K clocks. + * Note: this doesn't attempt to set the clocks to precise frequencies. + * Instead, we calibrate these clocks against XTAL frequency later, when necessary. + * - SCK_DCAP value controls tuning of RC_SLOW clock. + * The higher the value of DCAP is, the lower is the frequency. + * - CK8M_DFREQ value controls tuning of RC_FAST clock. + * CLK_8M_DFREQ constant gives the best temperature characteristics. + * - RC32K_DFREQ value controls tuning of RC32K clock. + */ + REG_SET_FIELD(LP_CLKRST_FOSC_CNTL_REG, LP_CLKRST_FOSC_DFREQ, cfg.clk_8m_dfreq); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_SCK_DCAP, cfg.slow_clk_dcap); + REG_SET_FIELD(LP_CLKRST_RC32K_CNTL_REG, LP_CLKRST_RC32K_DFREQ, cfg.rc32k_dfreq); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_ENIF_RTC_DREG, 1); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_ENIF_DIG_DREG, 1); + REG_SET_FIELD(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_ACTIVE_HP_REGULATOR_DBIAS, HP_CALI_DBIAS); + REG_SET_FIELD(PMU_HP_SLEEP_LP_REGULATOR0_REG, PMU_HP_SLEEP_LP_REGULATOR_DBIAS, LP_CALI_DBIAS); + + clk_ll_rc_fast_tick_conf(); + + rtc_xtal_freq_t xtal_freq = cfg.xtal_freq; + esp_rom_uart_tx_wait_idle(0); + rtc_clk_xtal_freq_update(xtal_freq); + + /* Set CPU frequency */ + rtc_clk_cpu_freq_get_config(&old_config); + uint32_t freq_before = old_config.freq_mhz; + bool res = rtc_clk_cpu_freq_mhz_to_config(cfg.cpu_freq_mhz, &new_config); + if (!res) { + ESP_HW_LOGE(TAG, "invalid CPU frequency value"); + abort(); + } + rtc_clk_cpu_freq_set_config(&new_config); + + /* Re-calculate the ccount to make time calculation correct. */ + esp_cpu_set_cycle_count( (uint64_t)esp_cpu_get_cycle_count() * cfg.cpu_freq_mhz / freq_before ); + + /* Slow & fast clocks setup */ + // We will not power off RC_FAST in bootloader stage even if it is not being used as any + // cpu / rtc_fast / rtc_slow clock sources, this is because RNG always needs it in the bootloader stage. + bool need_rc_fast_en = true; + if (cfg.slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) { + rtc_clk_32k_enable(true); + } else if (cfg.slow_clk_src == SOC_RTC_SLOW_CLK_SRC_OSC_SLOW) { + rtc_clk_32k_enable_external(); + } else if (cfg.slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC32K) { + rtc_clk_rc32k_enable(true); + } + rtc_clk_8m_enable(need_rc_fast_en); + rtc_clk_fast_src_set(cfg.fast_clk_src); + rtc_clk_slow_src_set(cfg.slow_clk_src); +} diff --git a/components/esp_hw_support/port/esp32c5/rtc_time.c b/components/esp_hw_support/port/esp32c5/rtc_time.c new file mode 100644 index 000000000000..49be74760b6e --- /dev/null +++ b/components/esp_hw_support/port/esp32c5/rtc_time.c @@ -0,0 +1,284 @@ +/* + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "esp32c5/rom/ets_sys.h" +#include "soc/rtc.h" +#include "soc/lp_timer_reg.h" +#include "hal/lp_timer_hal.h" +#include "hal/clk_tree_ll.h" +#include "hal/timer_ll.h" +#include "soc/timer_group_reg.h" +#include "esp_rom_sys.h" +#include "assert.h" +#include "hal/efuse_hal.h" +#include "soc/chip_revision.h" +#include "esp_private/periph_ctrl.h" + +static const char *TAG = "rtc_time"; + +// TODO: [ESP32C5] IDF-8667 + +/* Calibration of RTC_SLOW_CLK is performed using a special feature of TIMG0. + * This feature counts the number of XTAL clock cycles within a given number of + * RTC_SLOW_CLK cycles. + * + * Slow clock calibration feature has two modes of operation: one-off and cycling. + * In cycling mode (which is enabled by default on SoC reset), counting of XTAL + * cycles within RTC_SLOW_CLK cycle is done continuously. Cycling mode is enabled + * using TIMG_RTC_CALI_START_CYCLING bit. In one-off mode counting is performed + * once, and TIMG_RTC_CALI_RDY bit is set when counting is done. One-off mode is + * enabled using TIMG_RTC_CALI_START bit. + */ + +/* On ESP32C5, TIMG_RTC_CALI_CLK_SEL can config to 0, 1, 2, 3 + * 0 or 3: calibrate RC_SLOW clock + * 1: calibrate RC_FAST clock + * 2: calibrate 32K clock, which 32k depends on reg_32k_sel: 0: Internal 32 kHz RC oscillator, 1: External 32 kHz XTAL, 2: External 32kHz clock input by lp_pad_gpio0 + */ +#define TIMG_RTC_CALI_CLK_SEL_RC_SLOW 0 +#define TIMG_RTC_CALI_CLK_SEL_RC_FAST 1 +#define TIMG_RTC_CALI_CLK_SEL_32K 2 + +/** + * @brief Clock calibration function used by rtc_clk_cal + * + * Calibration of RTC_SLOW_CLK is performed using a special feature of TIMG0. + * This feature counts the number of XTAL clock cycles within a given number of + * RTC_SLOW_CLK cycles. + * + * Slow clock calibration feature has two modes of operation: one-off and cycling. + * In cycling mode (which is enabled by default on SoC reset), counting of XTAL + * cycles within RTC_SLOW_CLK cycle is done continuously. Cycling mode is enabled + * using TIMG_RTC_CALI_START_CYCLING bit. In one-off mode counting is performed + * once, and TIMG_RTC_CALI_RDY bit is set when counting is done. One-off mode is + * enabled using TIMG_RTC_CALI_START bit. + * + * @param cal_clk which clock to calibrate + * @param slowclk_cycles number of slow clock cycles to count + * @return number of XTAL clock cycles within the given number of slow clock cycles + */ +static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) +{ + assert(slowclk_cycles < TIMG_RTC_CALI_MAX_V); + + uint32_t cali_clk_sel = 0; + soc_rtc_slow_clk_src_t slow_clk_src = rtc_clk_slow_src_get(); + soc_rtc_slow_clk_src_t old_32k_cal_clk_sel = clk_ll_32k_calibration_get_target(); + if (cal_clk == RTC_CAL_RTC_MUX) { + cal_clk = (rtc_cal_sel_t)slow_clk_src; + } + if (cal_clk == RTC_CAL_RC_FAST) { + cali_clk_sel = TIMG_RTC_CALI_CLK_SEL_RC_FAST; +#if !CONFIG_IDF_TARGET_ESP32C5 // TODO: [ESP32C5] IDF-8642 Seems RC_SLOW can't be calibrated + } else if (cal_clk == RTC_CAL_RC_SLOW) { + cali_clk_sel = TIMG_RTC_CALI_CLK_SEL_RC_SLOW; +#endif // !CONFIG_IDF_TARGET_ESP32C5 + } else { + cali_clk_sel = TIMG_RTC_CALI_CLK_SEL_32K; + clk_ll_32k_calibration_set_target((soc_rtc_slow_clk_src_t)cal_clk); + } + + + /* Enable requested clock (150k clock is always on) */ + // All clocks on/off takes time to be stable, so we shouldn't frequently enable/disable the clock + // Only enable if orignally was disabled, and set back to the disable state after calibration is done + // If the clock is already on, then do nothing + bool dig_32k_xtal_enabled = clk_ll_xtal32k_digi_is_enabled(); + if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_enabled) { + clk_ll_xtal32k_digi_enable(); + } + + bool rc_fast_enabled = clk_ll_rc_fast_is_enabled(); + bool dig_rc_fast_enabled = clk_ll_rc_fast_digi_is_enabled(); + if (cal_clk == RTC_CAL_RC_FAST) { + if (!rc_fast_enabled) { + rtc_clk_8m_enable(true); + } + if (!dig_rc_fast_enabled) { + rtc_dig_clk8m_enable(); + } + } + + bool rc32k_enabled = clk_ll_rc32k_is_enabled(); + bool dig_rc32k_enabled = clk_ll_rc32k_digi_is_enabled(); + if (cal_clk == RTC_CAL_RC32K) { + if (!rc32k_enabled) { + rtc_clk_rc32k_enable(true); + } + if (!dig_rc32k_enabled) { + clk_ll_rc32k_digi_enable(); + } + } + + /* There may be another calibration process already running during we call this function, + * so we should wait the last process is done. + */ + if (GET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING)) { + /** + * Set a small timeout threshold to accelerate the generation of timeout. + * The internal circuit will be reset when the timeout occurs and will not affect the next calibration. + */ + REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, 1); + while (!GET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_RDY) + && !GET_PERI_REG_MASK(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT)); + } + + /* Prepare calibration */ + REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_CLK_SEL, cali_clk_sel); + CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING); + REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_MAX, slowclk_cycles); + /* Figure out how long to wait for calibration to finish */ + + /* Set timeout reg and expect time delay*/ + uint32_t expected_freq; + if (cali_clk_sel == TIMG_RTC_CALI_CLK_SEL_32K) { + REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_SLOW_CLK_32K_CAL_TIMEOUT_THRES(slowclk_cycles)); + expected_freq = SOC_CLK_XTAL32K_FREQ_APPROX; + } else if (cali_clk_sel == TIMG_RTC_CALI_CLK_SEL_RC_FAST) { + REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_FAST_CLK_20M_CAL_TIMEOUT_THRES(slowclk_cycles)); + expected_freq = SOC_CLK_RC_FAST_FREQ_APPROX; + } else { + REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_SLOW_CLK_150K_CAL_TIMEOUT_THRES(slowclk_cycles)); + expected_freq = SOC_CLK_RC_SLOW_FREQ_APPROX; + } + uint32_t us_time_estimate = (uint32_t) (((uint64_t) slowclk_cycles) * MHZ / expected_freq); + /* Start calibration */ + CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START); + SET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START); + + /* Wait for calibration to finish up to another us_time_estimate */ + esp_rom_delay_us(us_time_estimate); + uint32_t cal_val; + while (true) { + if (GET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_RDY)) { + cal_val = REG_GET_FIELD(TIMG_RTCCALICFG1_REG(0), TIMG_RTC_CALI_VALUE); + + /*The Fosc CLK of calibration circuit is divided by 32 for ECO1. + So we need to multiply the frequency of the Fosc for ECO1 and above chips by 32 times. + And ensure that this modification will not affect ECO0.*/ + if (ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 1)) { + if (cal_clk == RTC_CAL_RC_FAST) { + cal_val = cal_val >> 5; + } + } + break; + } + if (GET_PERI_REG_MASK(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT)) { + cal_val = 0; + break; + } + } + CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START); + + /* if dig_32k_xtal was originally off and enabled due to calibration, then set back to off state */ + if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_enabled) { + clk_ll_xtal32k_digi_disable(); + } + + if (cal_clk == RTC_CAL_RC_FAST) { + if (!dig_rc_fast_enabled) { + rtc_dig_clk8m_disable(); + } + if (!rc_fast_enabled) { + rtc_clk_8m_enable(false); + } + } + + if (cal_clk == RTC_CAL_RC32K) { + if (!dig_rc32k_enabled) { + clk_ll_rc32k_digi_disable(); + } + if (!rc32k_enabled) { + rtc_clk_rc32k_enable(false); + } + } + + // Always set back the calibration 32kHz clock selection + if (old_32k_cal_clk_sel != SOC_RTC_SLOW_CLK_SRC_INVALID) { + clk_ll_32k_calibration_set_target(old_32k_cal_clk_sel); + } + + return cal_val; +} + +static bool rtc_clk_cal_32k_valid(rtc_xtal_freq_t xtal_freq, uint32_t slowclk_cycles, uint64_t actual_xtal_cycles) +{ + uint64_t expected_xtal_cycles = (xtal_freq * 1000000ULL * slowclk_cycles) >> 15; // xtal_freq(hz) * slowclk_cycles / 32768 + uint64_t delta = expected_xtal_cycles / 2000; // 5/10000 = 0.05% error range + return (actual_xtal_cycles >= (expected_xtal_cycles - delta)) && (actual_xtal_cycles <= (expected_xtal_cycles + delta)); +} + +uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) +{ + rtc_xtal_freq_t xtal_freq = rtc_clk_xtal_freq_get(); + + /*The Fosc CLK of calibration circuit is divided by 32 for ECO1. + So we need to divide the calibrate cycles of the FOSC for ECO1 and above chips by 32 to + avoid excessive calibration time.*/ + if (ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 1)) { + if (cal_clk == RTC_CAL_RC_FAST) { + slowclk_cycles = slowclk_cycles >> 5; + } + } + + uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk, slowclk_cycles); + + if (cal_clk == RTC_CAL_32K_XTAL && !rtc_clk_cal_32k_valid(xtal_freq, slowclk_cycles, xtal_cycles)) { + return 0; + } + + uint64_t divider = ((uint64_t)xtal_freq) * slowclk_cycles; + uint64_t period_64 = ((xtal_cycles << RTC_CLK_CAL_FRACT) + divider / 2 - 1) / divider; + uint32_t period = (uint32_t)(period_64 & UINT32_MAX); + return period; +} + +uint64_t rtc_time_us_to_slowclk(uint64_t time_in_us, uint32_t period) +{ + /* Overflow will happen in this function if time_in_us >= 2^45, which is about 400 days. + * TODO: fix overflow. + */ + return (time_in_us << RTC_CLK_CAL_FRACT) / period; +} + +uint64_t rtc_time_slowclk_to_us(uint64_t rtc_cycles, uint32_t period) +{ + return (rtc_cycles * period) >> RTC_CLK_CAL_FRACT; +} + +uint64_t rtc_time_get(void) +{ + // return lp_timer_hal_get_cycle_count(); + ESP_EARLY_LOGW(TAG, "rtc_time_get has not been implemented yet"); + return 0; +} + +void rtc_clk_wait_for_slow_cycle(void) //This function may not by useful any more +{ + // TODO: IDF-5781 + ESP_EARLY_LOGW(TAG, "rtc_clk_wait_for_slow_cycle() has not been implemented yet"); +} + +uint32_t rtc_clk_freq_cal(uint32_t cal_val) +{ + if (cal_val == 0) { + return 0; // cal_val will be denominator, return 0 as the symbol of failure. + } + return 1000000ULL * (1 << RTC_CLK_CAL_FRACT) / cal_val; +} + +/// @brief if the calibration is used, we need to enable the timer group0 first +__attribute__((constructor)) +static void enable_timer_group0_for_calibration(void) +{ + PERIPH_RCC_ACQUIRE_ATOMIC(PERIPH_TIMG0_MODULE, ref_count) { + if (ref_count == 0) { + timer_ll_enable_bus_clock(0, true); + timer_ll_reset_register(0); + } + } +} diff --git a/components/esp_hw_support/port/esp32c5/sar_periph_ctrl.c b/components/esp_hw_support/port/esp32c5/sar_periph_ctrl.c new file mode 100644 index 000000000000..d6b9d5090641 --- /dev/null +++ b/components/esp_hw_support/port/esp32c5/sar_periph_ctrl.c @@ -0,0 +1,125 @@ +/* + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * SAR related peripherals are interdependent. This file + * provides a united control to these registers, as multiple + * components require these controls. + * + * Related peripherals are: + * - ADC + * - PWDET + */ + +#include "sdkconfig.h" +#include "esp_log.h" +#include "freertos/FreeRTOS.h" +// #include "esp_private/sar_periph_ctrl.h" +// #include "esp_private/esp_modem_clock.h" +// #include "hal/sar_ctrl_ll.h" + +static const char *TAG = "sar_periph_ctrl"; +extern portMUX_TYPE rtc_spinlock; + +// TODO: [ESP32C5] IDF-8701, IDF-8703, IDF-8727 + +void sar_periph_ctrl_init(void) +{ + // sar_ctrl_ll_force_power_ctrl_from_pwdet(true); + + //Add other periph power control initialisation here + ESP_EARLY_LOGW(TAG, "sar_periph_ctrl_init has not implemented on C5 yet"); +} + +void sar_periph_ctrl_power_enable(void) +{ + // portENTER_CRITICAL_SAFE(&rtc_spinlock); + // sar_ctrl_ll_force_power_ctrl_from_pwdet(true); + // portEXIT_CRITICAL_SAFE(&rtc_spinlock); + ESP_EARLY_LOGW(TAG, "sar_periph_ctrl_power_enable has not implemented on C5 yet"); +} + +void sar_periph_ctrl_power_disable(void) +{ + // portENTER_CRITICAL_SAFE(&rtc_spinlock); + // sar_ctrl_ll_force_power_ctrl_from_pwdet(false); + // portEXIT_CRITICAL_SAFE(&rtc_spinlock); + ESP_EARLY_LOGW(TAG, "sar_periph_ctrl_power_disable has not implemented on C5 yet"); +} + +/** + * This gets incremented when s_sar_power_acquire() is called, + * and decremented when s_sar_power_release() is called. + * PWDET is powered down when the value reaches zero. + * Should be modified within critical section. + */ +static int s_pwdet_power_on_cnt; + +static void s_sar_power_acquire(void) +{ + // modem_clock_module_enable(PERIPH_MODEM_ADC_COMMON_FE_MODULE); + portENTER_CRITICAL_SAFE(&rtc_spinlock); + s_pwdet_power_on_cnt++; + if (s_pwdet_power_on_cnt == 1) { + // sar_ctrl_ll_set_power_mode_from_pwdet(SAR_CTRL_LL_POWER_ON); + } + portEXIT_CRITICAL_SAFE(&rtc_spinlock); + ESP_EARLY_LOGW(TAG, "s_sar_power_acquire has not implemented on C5 yet"); +} + +static void s_sar_power_release(void) +{ + portENTER_CRITICAL_SAFE(&rtc_spinlock); + s_pwdet_power_on_cnt--; + if (s_pwdet_power_on_cnt < 0) { + portEXIT_CRITICAL(&rtc_spinlock); + ESP_LOGE(TAG, "%s called, but s_pwdet_power_on_cnt == 0", __func__); + abort(); + } else if (s_pwdet_power_on_cnt == 0) { + // sar_ctrl_ll_set_power_mode_from_pwdet(SAR_CTRL_LL_POWER_FSM); + } + portEXIT_CRITICAL_SAFE(&rtc_spinlock); + ESP_EARLY_LOGW(TAG, "s_sar_power_release has not implemented on C5 yet"); + // modem_clock_module_disable(PERIPH_MODEM_ADC_COMMON_FE_MODULE); +} + + +/*------------------------------------------------------------------------------ +* PWDET Power +*----------------------------------------------------------------------------*/ +void sar_periph_ctrl_pwdet_power_acquire(void) +{ + s_sar_power_acquire(); +} + +void sar_periph_ctrl_pwdet_power_release(void) +{ + s_sar_power_release(); +} + + +/*------------------------------------------------------------------------------ +* ADC Power +*----------------------------------------------------------------------------*/ +void sar_periph_ctrl_adc_oneshot_power_acquire(void) +{ + s_sar_power_acquire(); +} + +void sar_periph_ctrl_adc_oneshot_power_release(void) +{ + s_sar_power_release(); +} + +void sar_periph_ctrl_adc_continuous_power_acquire(void) +{ + s_sar_power_acquire(); +} + +void sar_periph_ctrl_adc_continuous_power_release(void) +{ + s_sar_power_release(); +} diff --git a/components/esp_hw_support/port/esp32c5/systimer.c b/components/esp_hw_support/port/esp32c5/systimer.c new file mode 100644 index 000000000000..f217295de288 --- /dev/null +++ b/components/esp_hw_support/port/esp32c5/systimer.c @@ -0,0 +1,37 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "sdkconfig.h" +#include "esp_private/systimer.h" + +#if CONFIG_XTAL_FREQ_40 +/** + * @brief systimer's clock source is fixed to XTAL (40MHz), and has a fixed fractional divider (2.5). + * So the resolution of the systimer is 40MHz/2.5 = 16MHz. + */ + +uint64_t systimer_ticks_to_us(uint64_t ticks) +{ + return ticks / 16; +} + +uint64_t systimer_us_to_ticks(uint64_t us) +{ + return us * 16; +} +#elif CONFIG_XTAL_FREQ_48 +uint64_t systimer_ticks_to_us(uint64_t ticks) +{ + return ticks * 5 / 96; +} + +uint64_t systimer_us_to_ticks(uint64_t us) +{ + return us * 96 / 5; +} +#else +#error "Unsupported XTAL frequency by systimer" +#endif // CONFIG_XTAL_FREQ_xx diff --git a/components/esp_hw_support/port/esp32c6/rtc_time.c b/components/esp_hw_support/port/esp32c6/rtc_time.c index 53aaed511cc6..08d5c572cf07 100644 --- a/components/esp_hw_support/port/esp32c6/rtc_time.c +++ b/components/esp_hw_support/port/esp32c6/rtc_time.c @@ -7,7 +7,6 @@ #include #include "esp32c6/rom/ets_sys.h" #include "soc/rtc.h" -#include "soc/lp_timer_reg.h" #include "hal/lp_timer_hal.h" #include "hal/clk_tree_ll.h" #include "hal/timer_ll.h" diff --git a/components/esp_hw_support/port/esp32h2/rtc_clk.c b/components/esp_hw_support/port/esp32h2/rtc_clk.c index bb8e288b53b8..4c657513c0ae 100644 --- a/components/esp_hw_support/port/esp32h2/rtc_clk.c +++ b/components/esp_hw_support/port/esp32h2/rtc_clk.c @@ -19,7 +19,6 @@ #include "hal/regi2c_ctrl_ll.h" #include "soc/io_mux_reg.h" #include "soc/lp_aon_reg.h" -#include "soc/lp_clkrst_reg.h" #include "esp_private/sleep_event.h" #ifdef BOOTLOADER_BUILD diff --git a/components/esp_hw_support/port/esp32h2/rtc_clk_init.c b/components/esp_hw_support/port/esp32h2/rtc_clk_init.c index 02d8b9bc4a3e..8ce3a854a0b5 100644 --- a/components/esp_hw_support/port/esp32h2/rtc_clk_init.c +++ b/components/esp_hw_support/port/esp32h2/rtc_clk_init.c @@ -41,6 +41,7 @@ void rtc_clk_init(rtc_clk_config_t cfg) REG_SET_FIELD(LP_CLKRST_FOSC_CNTL_REG, LP_CLKRST_FOSC_DFREQ, cfg.clk_8m_dfreq); REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OC_SCK_DCAP, cfg.slow_clk_dcap); REG_SET_FIELD(LP_CLKRST_RC32K_CNTL_REG, LP_CLKRST_RC32K_DFREQ, cfg.rc32k_dfreq); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_EN_I2C_RTC_DREG, 0); REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_EN_I2C_DIG_DREG, 0); REG_SET_FIELD(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_ACTIVE_HP_REGULATOR_DBIAS, HP_CALI_DBIAS); diff --git a/components/esp_hw_support/port/esp32h2/rtc_time.c b/components/esp_hw_support/port/esp32h2/rtc_time.c index 58816b1b024d..de72113a47ec 100644 --- a/components/esp_hw_support/port/esp32h2/rtc_time.c +++ b/components/esp_hw_support/port/esp32h2/rtc_time.c @@ -7,7 +7,7 @@ #include #include "esp32h2/rom/ets_sys.h" #include "soc/rtc.h" -#include "soc/lp_timer_reg.h" +#include "hal/lp_timer_hal.h" #include "hal/clk_tree_ll.h" #include "hal/timer_ll.h" #include "soc/timer_group_reg.h" @@ -249,10 +249,7 @@ uint64_t rtc_time_slowclk_to_us(uint64_t rtc_cycles, uint32_t period) uint64_t rtc_time_get(void) { - SET_PERI_REG_MASK(LP_TIMER_UPDATE_REG, LP_TIMER_MAIN_TIMER_UPDATE); - uint64_t t = READ_PERI_REG(LP_TIMER_MAIN_BUF0_LOW_REG); - t |= ((uint64_t) READ_PERI_REG(LP_TIMER_MAIN_BUF0_HIGH_REG)) << 32; - return t; + return lp_timer_hal_get_cycle_count(); } void rtc_clk_wait_for_slow_cycle(void) //This function may not by useful any more diff --git a/components/esp_hw_support/port/esp32p4/CMakeLists.txt b/components/esp_hw_support/port/esp32p4/CMakeLists.txt index 5bb37ab371af..e7e47df66b2e 100644 --- a/components/esp_hw_support/port/esp32p4/CMakeLists.txt +++ b/components/esp_hw_support/port/esp32p4/CMakeLists.txt @@ -16,12 +16,7 @@ if(NOT BOOTLOADER_BUILD) endif() -list(REMOVE_ITEM srcs - "pmu_param.c" # TODO: IDF-7531 - "pmu_sleep.c" # TODO: IDF-7531 - "pmu_init.c" # TODO: IDF-7531 - ) - add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" "${srcs}") target_sources(${COMPONENT_LIB} PRIVATE "${srcs}") +target_include_directories(${COMPONENT_LIB} PUBLIC . private_include) diff --git a/components/esp_hw_support/port/esp32p4/Kconfig.rtc b/components/esp_hw_support/port/esp32p4/Kconfig.rtc index 0ca1162422f7..8105f9f1a02f 100644 --- a/components/esp_hw_support/port/esp32p4/Kconfig.rtc +++ b/components/esp_hw_support/port/esp32p4/Kconfig.rtc @@ -1,5 +1,3 @@ -# TODO: IDF-7526 - choice RTC_CLK_SRC prompt "RTC clock source" default RTC_CLK_SRC_INT_RC @@ -11,18 +9,15 @@ choice RTC_CLK_SRC config RTC_CLK_SRC_EXT_CRYS bool "External 32kHz crystal" select ESP_SYSTEM_RTC_EXT_XTAL - config RTC_CLK_SRC_EXT_OSC - bool "External 32kHz oscillator at 32K_XP pin" - select ESP_SYSTEM_RTC_EXT_OSC config RTC_CLK_SRC_INT_RC32K bool "Internal 32kHz RC oscillator" endchoice config RTC_CLK_CAL_CYCLES int "Number of cycles for RTC_SLOW_CLK calibration" - default 3000 if RTC_CLK_SRC_EXT_CRYS || RTC_CLK_SRC_EXT_OSC || RTC_CLK_SRC_INT_8MD256 + default 3000 if RTC_CLK_SRC_EXT_CRYS || RTC_CLK_SRC_INT_RC32K default 1024 if RTC_CLK_SRC_INT_RC - range 0 27000 if RTC_CLK_SRC_EXT_CRYS || RTC_CLK_SRC_EXT_OSC || RTC_CLK_SRC_INT_8MD256 + range 0 27000 if RTC_CLK_SRC_EXT_CRYS || RTC_CLK_SRC_INT_RC32K range 0 32766 if RTC_CLK_SRC_INT_RC help When the startup code initializes RTC_SLOW_CLK, it can perform diff --git a/components/esp_hw_support/port/esp32p4/esp_clk_tree.c b/components/esp_hw_support/port/esp32p4/esp_clk_tree.c index 29060d1242b2..215b4fbad852 100644 --- a/components/esp_hw_support/port/esp32p4/esp_clk_tree.c +++ b/components/esp_hw_support/port/esp32p4/esp_clk_tree.c @@ -9,11 +9,12 @@ #include "esp_err.h" #include "esp_check.h" #include "soc/rtc.h" +#include "hal/clk_tree_hal.h" #include "hal/clk_tree_ll.h" +#include "esp_private/esp_clk_tree_common.h" static const char *TAG = "esp_clk_tree"; -// TODO: IDF-7526 esp_err_t esp_clk_tree_src_get_freq_hz(soc_module_clk_t clk_src, esp_clk_tree_src_freq_precision_t precision, uint32_t *freq_value) { @@ -23,18 +24,55 @@ uint32_t *freq_value) uint32_t clk_src_freq = 0; switch (clk_src) { + case SOC_MOD_CLK_CPU: + clk_src_freq = clk_hal_cpu_get_freq_hz(); + break; case SOC_MOD_CLK_XTAL: - clk_src_freq = 40 * MHZ; + clk_src_freq = clk_hal_xtal_get_freq_mhz() * MHZ; break; - case SOC_MOD_CLK_XTAL_D2: - clk_src_freq = (40 * MHZ) >> 1; + case SOC_MOD_CLK_PLL_F20M: + clk_src_freq = CLK_LL_PLL_20M_FREQ_MHZ * MHZ; break; - case SOC_MOD_CLK_LP_PLL: - clk_src_freq = 8 * MHZ; + case SOC_MOD_CLK_PLL_F80M: + clk_src_freq = CLK_LL_PLL_80M_FREQ_MHZ * MHZ; break; case SOC_MOD_CLK_PLL_F160M: clk_src_freq = CLK_LL_PLL_160M_FREQ_MHZ * MHZ; break; + case SOC_MOD_CLK_PLL_F240M: + clk_src_freq = CLK_LL_PLL_240M_FREQ_MHZ * MHZ; + break; + case SOC_MOD_CLK_CPLL: + clk_src_freq = clk_ll_cpll_get_freq_mhz(clk_hal_xtal_get_freq_mhz()) * MHZ; + break; + case SOC_MOD_CLK_SPLL: + clk_src_freq = CLK_LL_PLL_480M_FREQ_MHZ * MHZ; + break; + case SOC_MOD_CLK_MPLL: + clk_src_freq = clk_ll_mpll_get_freq_mhz(clk_hal_xtal_get_freq_mhz()) * MHZ; + break; + // case SOC_MOD_CLK_APLL: TODO: IDF-8884 + // break; + // case SOC_MOD_CLK_SDIO_PLL: TODO: IDF-8886 + // break; + case SOC_MOD_CLK_RTC_SLOW: + clk_src_freq = esp_clk_tree_lp_slow_get_freq_hz(precision); + break; + case SOC_MOD_CLK_RTC_FAST: + clk_src_freq = esp_clk_tree_lp_fast_get_freq_hz(precision); + break; + case SOC_MOD_CLK_RC_FAST: + clk_src_freq = esp_clk_tree_rc_fast_get_freq_hz(precision); + break; + case SOC_MOD_CLK_XTAL32K: + clk_src_freq = esp_clk_tree_xtal32k_get_freq_hz(precision); + break; + case SOC_MOD_CLK_XTAL_D2: + clk_src_freq = (clk_hal_xtal_get_freq_mhz() * MHZ) >> 1; + break; + case SOC_MOD_CLK_LP_PLL: + clk_src_freq = clk_ll_lp_pll_get_freq_mhz() * MHZ; + break; default: break; } diff --git a/components/esp_hw_support/port/esp32p4/pmu_init.c b/components/esp_hw_support/port/esp32p4/pmu_init.c new file mode 100644 index 000000000000..6c06a6fbbe87 --- /dev/null +++ b/components/esp_hw_support/port/esp32p4/pmu_init.c @@ -0,0 +1,200 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include "sdkconfig.h" +#include "esp_attr.h" +#include "soc/soc.h" +#include "soc/pmu_struct.h" +#include "hal/pmu_hal.h" +#include "pmu_param.h" +#include "esp_private/esp_pmu.h" +#include "soc/regi2c_dig_reg.h" +#include "regi2c_ctrl.h" +#include "soc/pmu_reg.h" + +// TODO: IDF-7531 + +static __attribute__((unused)) const char *TAG = "pmu_init"; + +typedef struct { + const pmu_hp_system_power_param_t *power; + const pmu_hp_system_clock_param_t *clock; + const pmu_hp_system_digital_param_t *digital; + const pmu_hp_system_analog_param_t *analog; + const pmu_hp_system_retention_param_t *retent; +} pmu_hp_system_param_t; + +typedef struct { + const pmu_lp_system_power_param_t *power; + const pmu_lp_system_analog_param_t *analog; +} pmu_lp_system_param_t; + +pmu_context_t * __attribute__((weak)) IRAM_ATTR PMU_instance(void) +{ + /* It should be explicitly defined in the internal RAM, because this + * instance will be used in pmu_sleep.c */ + static DRAM_ATTR pmu_hal_context_t pmu_hal = { .dev = &PMU }; + static DRAM_ATTR pmu_sleep_machine_constant_t pmu_mc = PMU_SLEEP_MC_DEFAULT(); + static DRAM_ATTR pmu_context_t pmu_context = { .hal = &pmu_hal, .mc = (void *)&pmu_mc }; + return &pmu_context; +} + +void pmu_hp_system_init(pmu_context_t *ctx, pmu_hp_mode_t mode, pmu_hp_system_param_t *param) +{ + const pmu_hp_system_power_param_t *power = param->power; + const pmu_hp_system_clock_param_t *clock = param->clock; + const pmu_hp_system_digital_param_t *dig = param->digital; + const pmu_hp_system_analog_param_t *anlg = param->analog; + const pmu_hp_system_retention_param_t *ret = param->retent; + + assert(ctx->hal); + /* Default configuration of hp-system power in active, modem and sleep modes */ + pmu_ll_hp_set_dig_power(ctx->hal->dev, mode, power->dig_power.val); + pmu_ll_hp_set_clk_power(ctx->hal->dev, mode, power->clk_power.val); + pmu_ll_hp_set_xtal_xpd (ctx->hal->dev, mode, power->xtal.xpd_xtal); + + /* Default configuration of hp-system clock in active, modem and sleep modes */ + pmu_ll_hp_set_icg_func (ctx->hal->dev, mode, clock->icg_func); + pmu_ll_hp_set_icg_apb (ctx->hal->dev, mode, clock->icg_apb); + pmu_ll_hp_set_icg_modem (ctx->hal->dev, mode, clock->icg_modem.code); + pmu_ll_hp_set_sysclk_nodiv (ctx->hal->dev, mode, clock->sysclk.dig_sysclk_nodiv); + pmu_ll_hp_set_icg_sysclk_enable (ctx->hal->dev, mode, clock->sysclk.icg_sysclk_en); + pmu_ll_hp_set_sysclk_slp_sel (ctx->hal->dev, mode, clock->sysclk.sysclk_slp_sel); + pmu_ll_hp_set_icg_sysclk_slp_sel(ctx->hal->dev, mode, clock->sysclk.icg_slp_sel); + pmu_ll_hp_set_dig_sysclk (ctx->hal->dev, mode, clock->sysclk.dig_sysclk_sel); + + /* Default configuration of hp-system digital sub-system in active, modem + * and sleep modes */ + pmu_ll_hp_set_uart_wakeup_enable(ctx->hal->dev, mode, dig->syscntl.uart_wakeup_en); + pmu_ll_hp_set_hold_all_lp_pad (ctx->hal->dev, mode, dig->syscntl.lp_pad_hold_all); + pmu_ll_hp_set_hold_all_hp_pad (ctx->hal->dev, mode, dig->syscntl.hp_pad_hold_all); + pmu_ll_hp_set_dig_pad_slp_sel (ctx->hal->dev, mode, dig->syscntl.dig_pad_slp_sel); + pmu_ll_hp_set_pause_watchdog (ctx->hal->dev, mode, dig->syscntl.dig_pause_wdt); + pmu_ll_hp_set_cpu_stall (ctx->hal->dev, mode, dig->syscntl.dig_cpu_stall); + + /* Default configuration of hp-system analog sub-system in active, modem and + * sleep modes */ + pmu_ll_hp_set_bias_xpd (ctx->hal->dev, mode, anlg->bias.xpd_bias); + pmu_ll_hp_set_dcm_mode (ctx->hal->dev, mode, anlg->bias.dcm_mode); + pmu_ll_hp_set_bias_xpd (ctx->hal->dev, mode, anlg->bias.xpd_bias); + pmu_ll_hp_set_dbg_atten (ctx->hal->dev, mode, anlg->bias.dbg_atten); + pmu_ll_hp_set_current_power_off (ctx->hal->dev, mode, anlg->bias.pd_cur); + pmu_ll_hp_set_bias_sleep_enable (ctx->hal->dev, mode, anlg->bias.bias_sleep); + pmu_ll_hp_set_regulator_sleep_memory_xpd (ctx->hal->dev, mode, anlg->regulator0.slp_mem_xpd); + pmu_ll_hp_set_regulator_sleep_logic_xpd (ctx->hal->dev, mode, anlg->regulator0.slp_logic_xpd); + pmu_ll_hp_set_regulator_sleep_memory_dbias(ctx->hal->dev, mode, anlg->regulator0.slp_mem_dbias); + pmu_ll_hp_set_regulator_sleep_logic_dbias (ctx->hal->dev, mode, anlg->regulator0.slp_logic_dbias); + pmu_ll_hp_set_regulator_driver_bar (ctx->hal->dev, mode, anlg->regulator1.drv_b); + + /* Default configuration of hp-system retention sub-system in active, modem + * and sleep modes */ + pmu_ll_hp_set_retention_param(ctx->hal->dev, mode, ret->retention.val); + pmu_ll_hp_set_backup_icg_func(ctx->hal->dev, mode, ret->backup_clk); + + /* Some PMU initial parameter configuration */ + pmu_ll_imm_update_dig_icg_modem_code(ctx->hal->dev, true); + pmu_ll_imm_update_dig_icg_switch(ctx->hal->dev, true); + + pmu_ll_hp_set_sleep_protect_mode(ctx->hal->dev, PMU_SLEEP_PROTECT_HP_LP_SLEEP); +} + +void pmu_lp_system_init(pmu_context_t *ctx, pmu_lp_mode_t mode, pmu_lp_system_param_t *param) +{ + const pmu_lp_system_power_param_t *power = param->power; + const pmu_lp_system_analog_param_t *anlg = param->analog; + + assert(ctx->hal); + /* Default configuration of lp-system power in active and sleep modes */ + pmu_ll_lp_set_dig_power(ctx->hal->dev, mode, power->dig_power.val); + pmu_ll_lp_set_clk_power(ctx->hal->dev, mode, power->clk_power.val); + pmu_ll_lp_set_xtal_xpd (ctx->hal->dev, PMU_MODE_LP_SLEEP, power->xtal.xpd_xtal); + + /* Default configuration of lp-system analog sub-system in active and + * sleep modes */ + pmu_ll_lp_set_bias_xpd (ctx->hal->dev, PMU_MODE_LP_SLEEP, anlg->bias.xpd_bias); + pmu_ll_lp_set_dbg_atten (ctx->hal->dev, PMU_MODE_LP_SLEEP, anlg->bias.dbg_atten); + pmu_ll_lp_set_current_power_off (ctx->hal->dev, PMU_MODE_LP_SLEEP, anlg->bias.pd_cur); + pmu_ll_lp_set_bias_sleep_enable (ctx->hal->dev, PMU_MODE_LP_SLEEP, anlg->bias.bias_sleep); + pmu_ll_lp_set_regulator_slp_xpd (ctx->hal->dev, mode, anlg->regulator0.slp_xpd); + pmu_ll_lp_set_regulator_sleep_dbias(ctx->hal->dev, mode, anlg->regulator0.slp_dbias); + pmu_ll_lp_set_regulator_driver_bar (ctx->hal->dev, mode, anlg->regulator1.drv_b); +} + +static inline void pmu_power_domain_force_default(pmu_context_t *ctx) +{ + assert(ctx); + // for bypass reserved power domain + const pmu_hp_power_domain_t pmu_hp_domains[] = { + PMU_HP_PD_TOP, + PMU_HP_PD_CNNT, + PMU_HP_PD_HPMEM, + }; + + for (uint8_t idx = 0; idx < (sizeof(pmu_hp_domains) / sizeof(pmu_hp_power_domain_t)); idx++) { + pmu_ll_hp_set_power_force_reset (ctx->hal->dev, pmu_hp_domains[idx], false); + pmu_ll_hp_set_power_force_isolate (ctx->hal->dev, pmu_hp_domains[idx], false); + pmu_ll_hp_set_power_force_power_up (ctx->hal->dev, pmu_hp_domains[idx], false); + pmu_ll_hp_set_power_force_no_reset (ctx->hal->dev, pmu_hp_domains[idx], false); + pmu_ll_hp_set_power_force_no_isolate(ctx->hal->dev, pmu_hp_domains[idx], false); + pmu_ll_hp_set_power_force_power_down(ctx->hal->dev, pmu_hp_domains[idx], false); + } + /* Isolate all memory banks while sleeping, avoid memory leakage current */ + pmu_ll_hp_set_memory_no_isolate (ctx->hal->dev, 0); + + pmu_ll_lp_set_power_force_reset (ctx->hal->dev, false); + pmu_ll_lp_set_power_force_isolate (ctx->hal->dev, false); + pmu_ll_lp_set_power_force_power_up (ctx->hal->dev, false); + pmu_ll_lp_set_power_force_no_reset (ctx->hal->dev, false); + pmu_ll_lp_set_power_force_no_isolate(ctx->hal->dev, false); + pmu_ll_lp_set_power_force_power_down(ctx->hal->dev, false); + pmu_ll_set_dcdc_force_power_up(ctx->hal->dev, false); + pmu_ll_set_dcdc_force_power_down(ctx->hal->dev, false); +} + +static inline void pmu_hp_system_param_default(pmu_hp_mode_t mode, pmu_hp_system_param_t *param) +{ + param->power = pmu_hp_system_power_param_default(mode); + param->clock = pmu_hp_system_clock_param_default(mode); + param->digital = pmu_hp_system_digital_param_default(mode); + param->analog = pmu_hp_system_analog_param_default(mode); + param->retent = pmu_hp_system_retention_param_default(mode); +} + +static void pmu_hp_system_init_default(pmu_context_t *ctx) +{ + assert(ctx); + pmu_hp_system_param_t param = { 0 }; + for (pmu_hp_mode_t mode = PMU_MODE_HP_ACTIVE; mode < PMU_MODE_HP_MAX; mode++) { + pmu_hp_system_param_default(mode, ¶m); + pmu_hp_system_init(ctx, mode, ¶m); + } +} + +static inline void pmu_lp_system_param_default(pmu_lp_mode_t mode, pmu_lp_system_param_t *param) +{ + param->power = pmu_lp_system_power_param_default(mode); + param->analog = pmu_lp_system_analog_param_default(mode); +} + +static void pmu_lp_system_init_default(pmu_context_t *ctx) +{ + assert(ctx); + pmu_lp_system_param_t param; + for (pmu_lp_mode_t mode = PMU_MODE_LP_ACTIVE; mode < PMU_MODE_LP_MAX; mode++) { + pmu_lp_system_param_default(mode, ¶m); + pmu_lp_system_init(ctx, mode, ¶m); + } +} + +void pmu_init(void) +{ + pmu_hp_system_init_default(PMU_instance()); + pmu_lp_system_init_default(PMU_instance()); + pmu_power_domain_force_default(PMU_instance()); +} diff --git a/components/esp_hw_support/port/esp32p4/pmu_param.c b/components/esp_hw_support/port/esp32p4/pmu_param.c new file mode 100644 index 000000000000..1788bb77d080 --- /dev/null +++ b/components/esp_hw_support/port/esp32p4/pmu_param.c @@ -0,0 +1,356 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include "sdkconfig.h" +#include "soc/soc.h" +#include "pmu_param.h" +#include "soc/pmu_icg_mapping.h" +#include "esp_private/esp_pmu.h" + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) +#endif + +// TODO: IDF-7531 +#define PMU_HP_ACTIVE_POWER_CONFIG_DEFAULT() { \ + .dig_power = { \ + .mem_dslp = 0, \ + .mem_pd_en = 0, \ + .cnnt_pd_en = 0, \ + .top_pd_en = 0, \ + .dcdc_switch_pd_en = 0 \ + }, \ + .clk_power = { \ + .i2c_iso_en = 0, \ + .i2c_retention = 0, \ + .xpd_pll_i2c = 1, \ + .xpd_pll = 1 \ + }, \ + .xtal = { \ + .xpd_xtal = 1 \ + } \ +} + +#define PMU_HP_SLEEP_POWER_CONFIG_DEFAULT() { \ + .dig_power = { \ + .mem_dslp = 0, \ + .mem_pd_en = 0, \ + .cnnt_pd_en = 0, \ + .top_pd_en = 0, \ + .dcdc_switch_pd_en = 1 \ + }, \ + .clk_power = { \ + .i2c_iso_en = 1, \ + .i2c_retention = 1, \ + .xpd_pll_i2c = 1, \ + .xpd_pll = 0 \ + }, \ + .xtal = { \ + .xpd_xtal = 0 \ + } \ +} + +const pmu_hp_system_power_param_t * pmu_hp_system_power_param_default(pmu_hp_mode_t mode) +{ + static const pmu_hp_system_power_param_t hp_power[] = { + PMU_HP_ACTIVE_POWER_CONFIG_DEFAULT(), + PMU_HP_ACTIVE_POWER_CONFIG_DEFAULT(), + PMU_HP_SLEEP_POWER_CONFIG_DEFAULT() + }; + assert(mode < ARRAY_SIZE(hp_power)); + return &hp_power[mode]; +} + +#define PMU_HP_ACTIVE_CLOCK_CONFIG_DEFAULT() { \ + .icg_func = 0xffffffff, \ + .icg_apb = 0xffffffff, \ + .icg_modem = { \ + .code = PMU_HP_ICG_MODEM_CODE_ACTIVE \ + }, \ + .sysclk = { \ + .dig_sysclk_nodiv = 0, \ + .icg_sysclk_en = 1, \ + .sysclk_slp_sel = 0, \ + .icg_slp_sel = 0, \ + .dig_sysclk_sel = PMU_HP_SYSCLK_XTAL \ + } \ +} + +#define PMU_HP_SLEEP_CLOCK_CONFIG_DEFAULT() { \ + .icg_func = 0, \ + .icg_apb = 0, \ + .icg_modem = { \ + .code = PMU_HP_ICG_MODEM_CODE_SLEEP \ + }, \ + .sysclk = { \ + .dig_sysclk_nodiv = 0, \ + .icg_sysclk_en = 0, \ + .sysclk_slp_sel = 1, \ + .icg_slp_sel = 1, \ + .dig_sysclk_sel = PMU_HP_SYSCLK_XTAL \ + } \ +} + +const pmu_hp_system_clock_param_t * pmu_hp_system_clock_param_default(pmu_hp_mode_t mode) +{ + static const pmu_hp_system_clock_param_t hp_clock[] = { + PMU_HP_ACTIVE_CLOCK_CONFIG_DEFAULT(), + PMU_HP_ACTIVE_CLOCK_CONFIG_DEFAULT(), + PMU_HP_SLEEP_CLOCK_CONFIG_DEFAULT() + }; + assert(mode < ARRAY_SIZE(hp_clock)); + return &hp_clock[mode]; +} + +#define PMU_HP_ACTIVE_DIGITAL_CONFIG_DEFAULT() { \ + .syscntl = { \ + .uart_wakeup_en = 0, \ + .lp_pad_hold_all = 0, \ + .hp_pad_hold_all = 0, \ + .dig_pad_slp_sel = 0, \ + .dig_pause_wdt = 0, \ + .dig_cpu_stall = 0 \ + } \ +} + +#define PMU_HP_SLEEP_DIGITAL_CONFIG_DEFAULT() { \ + .syscntl = { \ + .uart_wakeup_en = 1, \ + .lp_pad_hold_all = 0, \ + .hp_pad_hold_all = 0, \ + .dig_pad_slp_sel = 0, \ + .dig_pause_wdt = 1, \ + .dig_cpu_stall = 1 \ + } \ +} + +const pmu_hp_system_digital_param_t * pmu_hp_system_digital_param_default(pmu_hp_mode_t mode) +{ + static const pmu_hp_system_digital_param_t hp_digital[] = { + PMU_HP_ACTIVE_DIGITAL_CONFIG_DEFAULT(), + PMU_HP_ACTIVE_DIGITAL_CONFIG_DEFAULT(), + PMU_HP_SLEEP_DIGITAL_CONFIG_DEFAULT() + }; + assert(mode < ARRAY_SIZE(hp_digital)); + return &hp_digital[mode]; +} + +#define PMU_HP_ACTIVE_ANALOG_CONFIG_DEFAULT() { \ + .bias = { \ + .dcm_mode = 1, \ + .xpd_bias = 1, \ + .dbg_atten = 0x0, \ + .pd_cur = 0, \ + .bias_sleep = 0 \ + }, \ + .regulator0 = { \ + .lp_dbias_vol = 0xd, \ + .hp_dbias_vol = 0x1c,\ + .dbias_sel = 1, \ + .dbias_init = 1, \ + .slp_mem_xpd = 0, \ + .slp_logic_xpd = 0, \ + .slp_mem_dbias = 0, \ + .slp_logic_dbias = 0, \ + }, \ + .regulator1 = { \ + .drv_b = 0x0 \ + } \ +} + +#define PMU_HP_SLEEP_ANALOG_CONFIG_DEFAULT() { \ + .bias = { \ + .dcm_mode = 0, \ + .xpd_bias = 0, \ + .dbg_atten = 0x0, \ + .pd_cur = 1, \ + .bias_sleep = 1 \ + }, \ + .regulator0 = { \ + .slp_mem_xpd = 0, \ + .slp_logic_xpd = 0, \ + .slp_mem_dbias = 0, \ + .slp_logic_dbias = 0, \ + }, \ + .regulator1 = { \ + .drv_b = 0x0 \ + } \ +} + +const pmu_hp_system_analog_param_t * pmu_hp_system_analog_param_default(pmu_hp_mode_t mode) +{ + static const pmu_hp_system_analog_param_t hp_analog[] = { + PMU_HP_ACTIVE_ANALOG_CONFIG_DEFAULT(), + PMU_HP_ACTIVE_ANALOG_CONFIG_DEFAULT(), + PMU_HP_SLEEP_ANALOG_CONFIG_DEFAULT() + }; + assert(mode < ARRAY_SIZE(hp_analog)); + return &hp_analog[mode]; +} + +#define PMU_HP_RETENTION_REGDMA_CONFIG(dir, entry) ((((dir)<<2) | (entry & 0x3)) & 0x7) + +#define PMU_HP_ACTIVE_RETENTION_CONFIG_DEFAULT() { \ + .retention = { \ + .hp_sleep2active_backup_modem_clk_code = 2, \ + .hp_modem2active_backup_modem_clk_code = 2, \ + .hp_active_retention_mode = 0, \ + .hp_sleep2active_retention_en = 0, \ + .hp_modem2active_retention_en = 0, \ + .hp_sleep2active_backup_clk_sel = 0, \ + .hp_modem2active_backup_clk_sel = 0, \ + .hp_sleep2active_backup_mode = PMU_HP_RETENTION_REGDMA_CONFIG(0, 0), \ + .hp_modem2active_backup_mode = PMU_HP_RETENTION_REGDMA_CONFIG(0, 2), \ + .hp_sleep2active_backup_en = 0, \ + .hp_modem2active_backup_en = 0, \ + }, \ + .backup_clk = ( \ + BIT(PMU_ICG_FUNC_ENA_L2MEM_MEM) | \ + BIT(PMU_ICG_FUNC_ENA_L2MEM_SYS) | \ + BIT(PMU_ICG_FUNC_ENA_REGDMA) | \ + BIT(PMU_ICG_FUNC_ENA_HP_CLKRST) | \ + BIT(PMU_ICG_FUNC_ENA_SYSREG_APB) | \ + BIT(PMU_ICG_FUNC_ENA_ICM_CPU) | \ + BIT(PMU_ICG_FUNC_ENA_ICM_APB) | \ + BIT(PMU_ICG_FUNC_ENA_ICM_SYS) | \ + BIT(PMU_ICG_FUNC_ENA_ICM_MEM) | \ + BIT(PMU_ICG_FUNC_ENA_INTRMTX_APB) \ + ) \ +} + +#define PMU_HP_SLEEP_RETENTION_CONFIG_DEFAULT() { \ + .retention = { \ + .hp_modem2sleep_backup_modem_clk_code = 0, \ + .hp_active2sleep_backup_modem_clk_code = 2, \ + .hp_sleep_retention_mode = 0, \ + .hp_modem2sleep_retention_en = 0, \ + .hp_active2sleep_retention_en = 0, \ + .hp_modem2sleep_backup_clk_sel = 0, \ + .hp_active2sleep_backup_clk_sel = 0, \ + .hp_modem2sleep_backup_mode = PMU_HP_RETENTION_REGDMA_CONFIG(1, 1), \ + .hp_active2sleep_backup_mode = PMU_HP_RETENTION_REGDMA_CONFIG(1, 0), \ + .hp_modem2sleep_backup_en = 0, \ + .hp_active2sleep_backup_en = 0, \ + }, \ + .backup_clk = ( \ + BIT(PMU_ICG_FUNC_ENA_L2MEM_MEM) | \ + BIT(PMU_ICG_FUNC_ENA_L2MEM_SYS) | \ + BIT(PMU_ICG_FUNC_ENA_REGDMA) | \ + BIT(PMU_ICG_FUNC_ENA_HP_CLKRST) | \ + BIT(PMU_ICG_FUNC_ENA_SYSREG_APB) | \ + BIT(PMU_ICG_FUNC_ENA_ICM_CPU) | \ + BIT(PMU_ICG_FUNC_ENA_ICM_APB) | \ + BIT(PMU_ICG_FUNC_ENA_ICM_SYS) | \ + BIT(PMU_ICG_FUNC_ENA_ICM_MEM) | \ + BIT(PMU_ICG_FUNC_ENA_INTRMTX_APB) \ + ) \ +} + +const pmu_hp_system_retention_param_t * pmu_hp_system_retention_param_default(pmu_hp_mode_t mode) +{ + static const pmu_hp_system_retention_param_t hp_retention[] = { + PMU_HP_ACTIVE_RETENTION_CONFIG_DEFAULT(), + PMU_HP_ACTIVE_RETENTION_CONFIG_DEFAULT(), + PMU_HP_SLEEP_RETENTION_CONFIG_DEFAULT() + }; + assert(mode < ARRAY_SIZE(hp_retention)); + return &hp_retention[mode]; +} + + +/** LP system default parameter */ + +#if CONFIG_ESP_SYSTEM_RTC_EXT_XTAL +# define PMU_SLOW_CLK_USE_EXT_XTAL (1) +#else +# define PMU_SLOW_CLK_USE_EXT_XTAL (0) +#endif + +#define PMU_LP_ACTIVE_POWER_CONFIG_DEFAULT() { \ + .dig_power = { \ + .lp_pad_slp_sel = 0, \ + .bod_source_sel = 0, \ + .vddbat_mode = 0, \ + .mem_dslp = 0, \ + .peri_pd_en = 0, \ + }, \ + .clk_power = { \ + .xpd_lppll = 0, \ + .xpd_xtal32k = PMU_SLOW_CLK_USE_EXT_XTAL, \ + .xpd_rc32k = 0, \ + .xpd_fosc = 1, \ + .pd_osc = 0 \ + } \ +} + +#define PMU_LP_SLEEP_POWER_CONFIG_DEFAULT() { \ + .dig_power = { \ + .lp_pad_slp_sel = 0, \ + .bod_source_sel = 0, \ + .vddbat_mode = 0, \ + .mem_dslp = 1, \ + .peri_pd_en = 0, \ + }, \ + .clk_power = { \ + .xpd_lppll = 0, \ + .xpd_xtal32k = 0, \ + .xpd_rc32k = 0, \ + .xpd_fosc = 0, \ + .pd_osc = 0 \ + }, \ + .xtal = { \ + .xpd_xtal = 0 \ + } \ +} + +const pmu_lp_system_power_param_t * pmu_lp_system_power_param_default(pmu_lp_mode_t mode) +{ + static const pmu_lp_system_power_param_t lp_power[] = { + PMU_LP_ACTIVE_POWER_CONFIG_DEFAULT(), + PMU_LP_SLEEP_POWER_CONFIG_DEFAULT() + }; + assert(mode < ARRAY_SIZE(lp_power)); + return &lp_power[mode]; +} + +#define PMU_LP_ACTIVE_ANALOG_CONFIG_DEFAULT() { \ + .regulator0 = { \ + .slp_xpd = 0, \ + .slp_dbias = 0, \ + }, \ + .regulator1 = { \ + .drv_b = 0x0 \ + } \ +} + +#define PMU_LP_SLEEP_ANALOG_CONFIG_DEFAULT() { \ + .bias = { \ + .xpd_bias = 0, \ + .dbg_atten = 0, \ + .pd_cur = 1, \ + .bias_sleep = 1, \ + }, \ + .regulator0 = { \ + .slp_xpd = 0, \ + .slp_dbias = 0, \ + }, \ + .regulator1 = { \ + .drv_b = 0x0 \ + } \ +} + +const pmu_lp_system_analog_param_t * pmu_lp_system_analog_param_default(pmu_lp_mode_t mode) +{ + static const pmu_lp_system_analog_param_t lp_analog[] = { + PMU_LP_ACTIVE_ANALOG_CONFIG_DEFAULT(), + PMU_LP_SLEEP_ANALOG_CONFIG_DEFAULT() + }; + assert(mode < ARRAY_SIZE(lp_analog)); + return &lp_analog[mode]; +} diff --git a/components/esp_hw_support/port/esp32p4/pmu_sleep.c b/components/esp_hw_support/port/esp32p4/pmu_sleep.c new file mode 100644 index 000000000000..9308709356ae --- /dev/null +++ b/components/esp_hw_support/port/esp32p4/pmu_sleep.c @@ -0,0 +1,7 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +// TODO: IDF-7531 diff --git a/components/esp_hw_support/port/esp32p4/private_include/pmu_param.h b/components/esp_hw_support/port/esp32p4/private_include/pmu_param.h new file mode 100644 index 000000000000..8da662b633d5 --- /dev/null +++ b/components/esp_hw_support/port/esp32p4/private_include/pmu_param.h @@ -0,0 +1,488 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include +#include "soc/pmu_struct.h" +#include "hal/pmu_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// FOR XTAL FORCE PU IN SLEEP +#define PMU_PD_CUR_SLEEP_ON 0 +#define PMU_BIASSLP_SLEEP_ON 0 + +// FOR BOTH LIGHTSLEEP & DEEPSLEEP +#define PMU_PD_CUR_SLEEP_DEFAULT 1 +#define PMU_BIASSLP_SLEEP_DEFAULT 1 +#define PMU_LP_XPD_SLEEP_DEFAULT 1 +#define PMU_LP_SLP_XPD_SLEEP_DEFAULT 0 +#define PMU_LP_SLP_DBIAS_SLEEP_DEFAULT 0 + +// FOR LIGHTSLEEP +#define PMU_HP_DRVB_LIGHTSLEEP 0 +#define PMU_LP_DRVB_LIGHTSLEEP 0 +#define PMU_HP_XPD_LIGHTSLEEP 1 + +#define PMU_DBG_ATTEN_LIGHTSLEEP_DEFAULT 0 +#define PMU_HP_DBIAS_LIGHTSLEEP_0V6 1 +#define PMU_LP_DBIAS_LIGHTSLEEP_0V7 12 + +// FOR DEEPSLEEP +#define PMU_DBG_HP_DEEPSLEEP 0 +#define PMU_HP_XPD_DEEPSLEEP 0 +#define PMU_LP_DRVB_DEEPSLEEP 0 + +#define PMU_DBG_ATTEN_DEEPSLEEP_DEFAULT 12 +#define PMU_LP_DBIAS_DEEPSLEEP_0V7 23 + +typedef struct { + pmu_hp_dig_power_reg_t dig_power; + pmu_hp_clk_power_reg_t clk_power; + pmu_hp_xtal_reg_t xtal; +} pmu_hp_system_power_param_t; + +const pmu_hp_system_power_param_t* pmu_hp_system_power_param_default(pmu_hp_mode_t mode); + +typedef struct { + uint32_t icg_func; + uint32_t icg_apb; + pmu_hp_icg_modem_reg_t icg_modem; + pmu_hp_sysclk_reg_t sysclk; +} pmu_hp_system_clock_param_t; + +const pmu_hp_system_clock_param_t* pmu_hp_system_clock_param_default(pmu_hp_mode_t mode); + +typedef struct { + pmu_hp_sys_cntl_reg_t syscntl; +} pmu_hp_system_digital_param_t; + +const pmu_hp_system_digital_param_t* pmu_hp_system_digital_param_default(pmu_hp_mode_t mode); + +typedef struct { + pmu_hp_bias_reg_t bias; + pmu_hp_regulator0_reg_t regulator0; + pmu_hp_regulator1_reg_t regulator1; +} pmu_hp_system_analog_param_t; + +const pmu_hp_system_analog_param_t* pmu_hp_system_analog_param_default(pmu_hp_mode_t mode); + +typedef struct { + pmu_hp_backup_reg_t retention; + uint32_t backup_clk; +} pmu_hp_system_retention_param_t; + +const pmu_hp_system_retention_param_t* pmu_hp_system_retention_param_default(pmu_hp_mode_t mode); + +typedef struct { + pmu_lp_dig_power_reg_t dig_power; + pmu_lp_clk_power_reg_t clk_power; + pmu_lp_xtal_reg_t xtal; +} pmu_lp_system_power_param_t; + +const pmu_lp_system_power_param_t* pmu_lp_system_power_param_default(pmu_lp_mode_t mode); + +typedef struct { + pmu_lp_bias_reg_t bias; + pmu_lp_regulator0_reg_t regulator0; + pmu_lp_regulator1_reg_t regulator1; +} pmu_lp_system_analog_param_t; + +const pmu_lp_system_analog_param_t* pmu_lp_system_analog_param_default(pmu_lp_mode_t mode); + + +/* Following software configuration instance type from pmu_struct.h used for the PMU state machine in sleep flow*/ +typedef union { + struct { + uint32_t reserved0 : 21; + uint32_t dcdc_switch_pd_en: 1; + uint32_t mem_dslp : 1; + uint32_t mem_pd_en : 1; + uint32_t reserved1 : 6; + uint32_t cnnt_pd_en : 1; + uint32_t top_pd_en : 1; + }; + struct { + uint32_t reserved2 : 21; + uint32_t i2c_iso_en : 1; + uint32_t i2c_retention: 1; + uint32_t xpd_pll_i2c : 4; + uint32_t xpd_pll : 4; + uint32_t reserved3 : 1; + }; + struct { + uint32_t reserved4 : 31; + uint32_t xpd_xtal : 1; + }; + uint32_t val; +} pmu_hp_power_t; + +typedef union { + struct { + uint32_t reserved0 : 26; + uint32_t lp_pad_slp_sel : 1; + uint32_t bod_source_sel : 1; + uint32_t vddbat_mode : 2; + uint32_t mem_dslp : 1; + uint32_t peri_pd_en: 1; + }; + struct { + uint32_t reserved1 : 27; + uint32_t xpd_lppll : 1; + uint32_t xpd_xtal32k: 1; + uint32_t xpd_rc32k : 1; + uint32_t xpd_fosc : 1; + uint32_t pd_osc : 1; + }; + struct { + uint32_t reserved2 : 31; + uint32_t xpd_xtal : 1; + }; + uint32_t val; +} pmu_lp_power_t; + +typedef struct { + struct { + uint32_t reserved0 : 25; + uint32_t xpd_bias : 1; + uint32_t dbg_atten : 4; + uint32_t pd_cur : 1; + uint32_t bias_sleep: 1; + }; + struct { + uint32_t reserved1 : 16; + uint32_t slp_mem_xpd : 1; + uint32_t slp_logic_xpd : 1; + uint32_t xpd : 1; + uint32_t slp_mem_dbias : 4; + uint32_t slp_logic_dbias: 4; + uint32_t dbias : 5; + }; + struct { + uint32_t reserved2: 8; + uint32_t drv_b : 24; + }; +} pmu_hp_analog_t; + +typedef struct { + struct { + uint32_t reserved0 : 25; + uint32_t xpd_bias : 1; + uint32_t dbg_atten : 4; + uint32_t pd_cur : 1; + uint32_t bias_sleep: 1; + }; + struct { + uint32_t reserved1: 21; + uint32_t slp_xpd : 1; + uint32_t xpd : 1; + uint32_t slp_dbias: 4; + uint32_t dbias : 5; + }; + struct { + uint32_t reserved2: 28; + uint32_t drv_b : 4; + }; +} pmu_lp_analog_t; + +typedef struct { + uint32_t modem_wakeup_wait_cycle; + uint16_t analog_wait_target_cycle; + uint16_t digital_power_down_wait_cycle; + uint16_t digital_power_supply_wait_cycle; + uint16_t digital_power_up_wait_cycle; + uint16_t pll_stable_wait_cycle; + uint8_t modify_icg_cntl_wait_cycle; + uint8_t switch_icg_cntl_wait_cycle; + uint8_t min_slp_slow_clk_cycle; +} pmu_hp_param_t; + +typedef struct { + uint16_t digital_power_supply_wait_cycle; + uint8_t min_slp_slow_clk_cycle; + uint8_t analog_wait_target_cycle; + uint8_t digital_power_down_wait_cycle; + uint8_t digital_power_up_wait_cycle; +} pmu_lp_param_t; + +typedef struct { + union { + uint16_t xtal_stable_wait_slow_clk_cycle; + uint16_t xtal_stable_wait_cycle; + }; +} pmu_hp_lp_param_t; + +#define PMU_HP_SLEEP_MIN_SLOW_CLK_CYCLES (10) +#define PMU_LP_SLEEP_MIN_SLOW_CLK_CYCLES (10) + +#define PMU_HP_WAKEUP_DELAY_CYCLES (0) +#define PMU_HP_XTAL_STABLE_WAIT_CYCLES (3155) /* Not used, Fast OSC as PMU work clock source is about 201 us, corresponding to PMU_LP_XTAL_STABLE_WAIT_SLOW_CLK_CYCLES */ +#define PMU_HP_PLL_STABLE_WAIT_CYCLES (2) +#define PMU_HP_ANALOG_WAIT_TARGET_CYCLES (2419) /* Fast OSC as PMU work clock source is about 154 us */ +#define PMU_HP_DIGITAL_POWER_SUPPLY_WAIT_CYCLES (32) +#define PMU_HP_DIGITAL_POWER_UP_WAIT_CYCLES (32) +#define PMU_HP_MODEM_WAKEUP_WAIT_CYCLES (20700) /* Fast OSC as PMU work clock source is about 1318.6 us */ + +#define PMU_LP_WAKEUP_DELAY_CYCLES (0) +#define PMU_LP_XTAL_STABLE_WAIT_SLOW_CLK_CYCLES (30) /* Slow OSC as PMU slow clock source is about 201 us */ +#define PMU_LP_ANALOG_WAIT_TARGET_CYCLES (23) /* Slow OSC as PMU slow clock source is about 154 us */ +#define PMU_LP_DIGITAL_POWER_SUPPLY_WAIT_CYCLES (32) /* Fast OSC as PMU work clock source is about 2 us */ +#define PMU_LP_DIGITAL_POWER_UP_WAIT_CYCLES (32) /* Fast OSC as PMU work clock source is about 2 us */ + +#define PMU_LP_ANALOG_WAIT_TARGET_TIME_DSLP_US (500) /* Slow OSC as PMU slow clock source in deepsleep is about 500 us */ + +typedef struct { + struct { + pmu_hp_power_t dig_power; + pmu_hp_power_t clk_power; + pmu_hp_power_t xtal; + } hp_sys; + struct { + pmu_lp_power_t dig_power; + pmu_lp_power_t clk_power; + pmu_lp_power_t xtal; + } lp_sys[PMU_MODE_LP_MAX]; +} pmu_sleep_power_config_t; + +#define PMU_SLEEP_POWER_CONFIG_DEFAULT(pd_flags) { \ + .hp_sys = { \ + .dig_power = { \ + .cnnt_pd_en = ((pd_flags) & PMU_SLEEP_PD_CNNT) ? 1 : 0, \ + .top_pd_en = ((pd_flags) & PMU_SLEEP_PD_TOP) ? 1 : 0, \ + .mem_pd_en = ((pd_flags) & PMU_SLEEP_PD_MEM) ? 1 : 0, \ + .mem_dslp = 0 \ + }, \ + .clk_power = { \ + .i2c_iso_en = 1, \ + .i2c_retention = 1, \ + .xpd_pll_i2c = 0, \ + .xpd_pll = 0 \ + }, \ + .xtal = { \ + .xpd_xtal = ((pd_flags) & PMU_SLEEP_PD_XTAL) ? 0 : 1, \ + } \ + }, \ + .lp_sys[PMU_MODE_LP_ACTIVE] = { \ + .dig_power = { \ + .lp_pad_slp_sel = 0, \ + .bod_source_sel = 0, \ + .vddbat_mode = 0, \ + .peri_pd_en = 0, \ + .mem_dslp = 0 \ + }, \ + .clk_power = { \ + .xpd_lppll = 1, \ + .xpd_xtal32k = ((pd_flags) & PMU_SLEEP_PD_XTAL32K) ? 0 : 1, \ + .xpd_rc32k = ((pd_flags) & PMU_SLEEP_PD_RC32K) ? 0 : 1, \ + .xpd_fosc = 1 \ + } \ + }, \ + .lp_sys[PMU_MODE_LP_SLEEP] = { \ + .dig_power = { \ + .lp_pad_slp_sel = 0, \ + .bod_source_sel = 0, \ + .vddbat_mode = 0, \ + .peri_pd_en = ((pd_flags) & PMU_SLEEP_PD_LP_PERIPH) ? 1 : 0, \ + .mem_dslp = 1 \ + }, \ + .clk_power = { \ + .xpd_lppll = 0,\ + .xpd_xtal32k = ((pd_flags) & PMU_SLEEP_PD_XTAL32K) ? 0 : 1, \ + .xpd_rc32k = ((pd_flags) & PMU_SLEEP_PD_RC32K) ? 0 : 1, \ + .xpd_fosc = ((pd_flags) & PMU_SLEEP_PD_RC_FAST) ? 0 : 1 \ + }, \ + .xtal = { \ + .xpd_xtal = ((pd_flags) & PMU_SLEEP_PD_XTAL) ? 0 : 1, \ + } \ + } \ +} + +typedef struct { + pmu_hp_sys_cntl_reg_t syscntl; +} pmu_sleep_digital_config_t; + +#define PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(pd_flags) { \ + .syscntl = { \ + .dig_pad_slp_sel = ((pd_flags) & PMU_SLEEP_PD_TOP) ? 0 : 1, \ + } \ +} + +typedef struct { + struct { + pmu_hp_analog_t analog; + } hp_sys; + struct { + pmu_lp_analog_t analog; + } lp_sys[PMU_MODE_LP_MAX]; +} pmu_sleep_analog_config_t; + +#define PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(pd_flags) { \ + .hp_sys = { \ + .analog = { \ + .drv_b = PMU_HP_DRVB_LIGHTSLEEP, \ + .pd_cur = PMU_PD_CUR_SLEEP_DEFAULT, \ + .bias_sleep = PMU_BIASSLP_SLEEP_DEFAULT, \ + .xpd = PMU_HP_XPD_LIGHTSLEEP, \ + .dbg_atten = PMU_DBG_ATTEN_LIGHTSLEEP_DEFAULT, \ + .dbias = PMU_HP_DBIAS_LIGHTSLEEP_0V6 \ + } \ + }, \ + .lp_sys[PMU_MODE_LP_ACTIVE] = { \ + .analog = { \ + .slp_xpd = 0, \ + .slp_dbias = 0, \ + .xpd = 1, \ + .dbias = 0x1a, \ + .drv_b = 0x0 \ + } \ + }, \ + .lp_sys[PMU_MODE_LP_SLEEP] = { \ + .analog = { \ + .drv_b = PMU_LP_DRVB_DEEPSLEEP, \ + .pd_cur = PMU_PD_CUR_SLEEP_DEFAULT, \ + .bias_sleep = PMU_BIASSLP_SLEEP_DEFAULT, \ + .slp_xpd = PMU_LP_SLP_XPD_SLEEP_DEFAULT, \ + .slp_dbias = PMU_LP_SLP_DBIAS_SLEEP_DEFAULT, \ + .xpd = PMU_LP_XPD_SLEEP_DEFAULT, \ + .dbg_atten = PMU_DBG_ATTEN_LIGHTSLEEP_DEFAULT, \ + .dbias = PMU_LP_DBIAS_LIGHTSLEEP_0V7 \ + } \ + } \ +} + +#define PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(pd_flags) { \ + .hp_sys = { \ + .analog = { \ + .pd_cur = PMU_PD_CUR_SLEEP_ON, \ + .bias_sleep = PMU_BIASSLP_SLEEP_ON, \ + .xpd = PMU_HP_XPD_DEEPSLEEP, \ + .dbg_atten = PMU_DBG_HP_DEEPSLEEP \ + } \ + }, \ + .lp_sys[PMU_MODE_LP_ACTIVE] = { \ + .analog = { \ + .xpd = 1, \ + .dbias = 0x1a, \ + .slp_xpd = 0, \ + .slp_dbias = 0, \ + .drv_b = 0x7 \ + } \ + }, \ + .lp_sys[PMU_MODE_LP_SLEEP] = { \ + .analog = { \ + .drv_b = PMU_LP_DRVB_DEEPSLEEP, \ + .pd_cur = PMU_PD_CUR_SLEEP_DEFAULT, \ + .bias_sleep = PMU_BIASSLP_SLEEP_DEFAULT, \ + .slp_xpd = PMU_LP_SLP_XPD_SLEEP_DEFAULT, \ + .slp_dbias = PMU_LP_SLP_DBIAS_SLEEP_DEFAULT, \ + .xpd = PMU_LP_XPD_SLEEP_DEFAULT, \ + .dbg_atten = PMU_DBG_ATTEN_DEEPSLEEP_DEFAULT, \ + .dbias = PMU_LP_DBIAS_DEEPSLEEP_0V7 \ + } \ + } \ +} + +typedef struct { + pmu_hp_param_t hp_sys; + pmu_lp_param_t lp_sys; + pmu_hp_lp_param_t hp_lp; +} pmu_sleep_param_config_t; + +#define PMU_SLEEP_PARAM_CONFIG_DEFAULT(pd_flags) { \ + .hp_sys = { \ + .min_slp_slow_clk_cycle = PMU_HP_SLEEP_MIN_SLOW_CLK_CYCLES, \ + .analog_wait_target_cycle = PMU_HP_ANALOG_WAIT_TARGET_CYCLES, \ + .digital_power_supply_wait_cycle = PMU_HP_DIGITAL_POWER_SUPPLY_WAIT_CYCLES, \ + .digital_power_up_wait_cycle = PMU_HP_DIGITAL_POWER_UP_WAIT_CYCLES, \ + .modem_wakeup_wait_cycle = PMU_HP_MODEM_WAKEUP_WAIT_CYCLES, \ + .pll_stable_wait_cycle = PMU_HP_PLL_STABLE_WAIT_CYCLES \ + }, \ + .lp_sys = { \ + .min_slp_slow_clk_cycle = PMU_LP_SLEEP_MIN_SLOW_CLK_CYCLES, \ + .analog_wait_target_cycle = PMU_LP_ANALOG_WAIT_TARGET_CYCLES, \ + .digital_power_supply_wait_cycle = PMU_LP_DIGITAL_POWER_SUPPLY_WAIT_CYCLES, \ + .digital_power_up_wait_cycle = PMU_LP_DIGITAL_POWER_UP_WAIT_CYCLES \ + }, \ + .hp_lp = { \ + .xtal_stable_wait_slow_clk_cycle = PMU_LP_XTAL_STABLE_WAIT_SLOW_CLK_CYCLES \ + } \ +} + +typedef struct { + pmu_sleep_power_config_t power; + pmu_sleep_digital_config_t digital; + pmu_sleep_analog_config_t analog; + pmu_sleep_param_config_t param; +} pmu_sleep_config_t; + +typedef struct pmu_sleep_machine_constant { + struct { + uint16_t min_slp_time_us; /* Mininum sleep protection time (unit: microsecond) */ + uint8_t wakeup_wait_cycle; /* Modem wakeup signal (WiFi MAC and BEACON wakeup) waits for the slow & fast clock domain synchronization and the wakeup signal triggers the PMU FSM switching wait cycle (unit: slow clock cycle) */ + uint8_t reserved0; + uint16_t reserved1; + uint16_t analog_wait_time_us; /* LP LDO power up wait time (unit: microsecond) */ + uint16_t xtal_wait_stable_time_us; /* Main XTAL stabilization wait time (unit: microsecond) */ + uint8_t clk_switch_cycle; /* Clock switch to FOSC (unit: slow clock cycle) */ + uint8_t clk_power_on_wait_cycle; /* Clock power on wait cycle (unit: slow clock cycle) */ + uint16_t power_supply_wait_time_us; /* (unit: microsecond) */ + uint16_t power_up_wait_time_us; /* (unit: microsecond) */ + } lp; + struct { + uint16_t min_slp_time_us; /* Mininum 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 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) */ + uint16_t power_supply_wait_time_us; /* (unit: microsecond) */ + uint16_t power_up_wait_time_us; /* (unit: microsecond) */ + uint16_t regdma_s2m_work_time_us; /* Modem Subsystem (S2M switch) REGDMA restore time (unit: microsecond) */ + uint16_t regdma_s2a_work_time_us; /* SOC System (Digital Peripheral + Modem Subsystem) REGDMA (S2A switch) restore time (unit: microsecond) */ + uint16_t regdma_m2a_work_time_us; /* Digital Peripheral (M2A switch) REGDMA restore time (unit: microsecond) */ + uint16_t regdma_a2s_work_time_us; /* SOC System (Digital Peripheral + Modem Subsystem) REGDMA (A2S switch) backup time (unit: microsecond) */ + uint16_t regdma_rf_on_work_time_us; /* The REGDMA work time of RF enable (unit: microsecond) */ + uint16_t regdma_rf_off_work_time_us; /* The REGDMA work time of RF disable (unit: microsecond) */ + uint16_t xtal_wait_stable_time_us; /* Main XTAL stabilization wait time (unit: microsecond) */ + uint16_t pll_wait_stable_time_us; /* PLL stabilization wait time (unit: microsecond) */ + } hp; +} pmu_sleep_machine_constant_t; + +#define PMU_SLEEP_MC_DEFAULT() { \ + .lp = { \ + .min_slp_time_us = 450, \ + .wakeup_wait_cycle = 4, \ + .analog_wait_time_us = 154, \ + .xtal_wait_stable_time_us = 250, \ + .clk_switch_cycle = 1, \ + .clk_power_on_wait_cycle = 1, \ + .power_supply_wait_time_us = 2, \ + .power_up_wait_time_us = 2 \ + }, \ + .hp = { \ + .min_slp_time_us = 450, \ + .clock_domain_sync_time_us = 150, \ + .system_dfs_up_work_time_us = 124, \ + .analog_wait_time_us = 154, \ + .power_supply_wait_time_us = 2, \ + .power_up_wait_time_us = 2, \ + .regdma_s2m_work_time_us = 172, \ + .regdma_s2a_work_time_us = 430, \ + .regdma_m2a_work_time_us = 265, \ + .regdma_a2s_work_time_us = 338, \ + .regdma_rf_on_work_time_us = 70, \ + .regdma_rf_off_work_time_us = 23, \ + .xtal_wait_stable_time_us = 250, \ + .pll_wait_stable_time_us = 1 \ + } \ +} + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hw_support/port/esp32p4/rtc_clk.c b/components/esp_hw_support/port/esp32p4/rtc_clk.c index df3890a6c352..a484a17a735e 100644 --- a/components/esp_hw_support/port/esp32p4/rtc_clk.c +++ b/components/esp_hw_support/port/esp32p4/rtc_clk.c @@ -10,7 +10,6 @@ #include #include #include "sdkconfig.h" -#include "esp32p4/rom/ets_sys.h" #include "esp32p4/rom/rtc.h" #include "soc/rtc.h" #include "esp_private/rtc_clk.h" @@ -18,25 +17,14 @@ #include "esp_rom_sys.h" #include "hal/clk_tree_ll.h" #include "hal/regi2c_ctrl_ll.h" +#include "hal/gpio_ll.h" #include "soc/io_mux_reg.h" -#include "soc/lp_clkrst_reg.h" +#include "esp_private/sleep_event.h" // TODO: IDF-7528 static const char *TAG = "rtc_clk"; -// Current PLL frequency, in 480MHz. Zero if PLL is not enabled. -static int s_cur_pll_freq; - -static uint32_t s_bbpll_digi_consumers_ref_count = 0; // Currently, it only tracks whether the 48MHz PHY clock is in-use by USB Serial/JTAG - -void rtc_clk_bbpll_add_consumer(void) -{ - s_bbpll_digi_consumers_ref_count += 1; -} - -void rtc_clk_bbpll_remove_consumer(void) -{ - s_bbpll_digi_consumers_ref_count -= 1; -} +// CPLL frequency option, in 360/400MHz. Zero if CPLL is not enabled. +static int s_cur_cpll_freq = 0; void rtc_clk_32k_enable(bool enable) { @@ -47,10 +35,6 @@ void rtc_clk_32k_enable(bool enable) } } -void rtc_clk_32k_enable_external(void) -{ -} - void rtc_clk_32k_bootstrap(uint32_t cycle) { /* No special bootstrapping needed for ESP32-P4, 'cycle' argument is to keep the signature @@ -90,6 +74,22 @@ bool rtc_clk_8m_enabled(void) return clk_ll_rc_fast_is_enabled(); } +void rtc_clk_lp_pll_enable(bool enable) +{ + if (enable) { + clk_ll_lp_pll_enable(); + esp_rom_delay_us(SOC_DELAY_LP_PLL_ENABLE); + } else { + clk_ll_lp_pll_disable(); + } +} + +void rtc_clk_lp_pll_src_set(soc_lp_pll_clk_src_t clk_src) +{ + clk_ll_lp_pll_set_src(clk_src); + esp_rom_delay_us(SOC_DELAY_LP_PLL_SWITCH); +} + void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src) { clk_ll_rtc_slow_set_src(clk_src); @@ -107,7 +107,6 @@ uint32_t rtc_clk_slow_freq_get_hz(void) case SOC_RTC_SLOW_CLK_SRC_RC_SLOW: return SOC_CLK_RC_SLOW_FREQ_APPROX; case SOC_RTC_SLOW_CLK_SRC_XTAL32K: return SOC_CLK_XTAL32K_FREQ_APPROX; case SOC_RTC_SLOW_CLK_SRC_RC32K: return SOC_CLK_RC32K_FREQ_APPROX; - case SOC_RTC_SLOW_CLK_SRC_OSC_SLOW: return SOC_CLK_OSC_SLOW_FREQ_APPROX; default: return 0; } } @@ -123,77 +122,144 @@ soc_rtc_fast_clk_src_t rtc_clk_fast_src_get(void) return clk_ll_rtc_fast_get_src(); } -static void rtc_clk_bbpll_disable(void) +static void rtc_clk_cpll_disable(void) { - clk_ll_bbpll_disable(); - s_cur_pll_freq = 0; + clk_ll_cpll_disable(); + s_cur_cpll_freq = 0; } -static void rtc_clk_bbpll_enable(void) +static void rtc_clk_cpll_enable(void) { - clk_ll_bbpll_enable(); + clk_ll_cpll_enable(); } -static void rtc_clk_bbpll_configure(rtc_xtal_freq_t xtal_freq, int pll_freq) +static void rtc_clk_cpll_configure(rtc_xtal_freq_t xtal_freq, int cpll_freq) { /* Digital part */ - clk_ll_bbpll_set_freq_mhz(pll_freq); + clk_ll_cpll_set_freq_mhz(cpll_freq); /* Analog part */ - /* BBPLL CALIBRATION START */ - regi2c_ctrl_ll_bbpll_calibration_start(); - clk_ll_bbpll_set_config(pll_freq, xtal_freq); + /* CPLL CALIBRATION START */ + regi2c_ctrl_ll_cpll_calibration_start(); + clk_ll_cpll_set_config(cpll_freq, xtal_freq); /* WAIT CALIBRATION DONE */ - while(!regi2c_ctrl_ll_bbpll_calibration_is_done()); - /* BBPLL CALIBRATION STOP */ - regi2c_ctrl_ll_bbpll_calibration_stop(); + while(!regi2c_ctrl_ll_cpll_calibration_is_done()); + esp_rom_delay_us(10); // wait for true stop + /* CPLL CALIBRATION STOP */ + regi2c_ctrl_ll_cpll_calibration_stop(); - s_cur_pll_freq = pll_freq; + s_cur_cpll_freq = cpll_freq; } /** * Switch to use XTAL as the CPU clock source. * Must satisfy: cpu_freq = XTAL_FREQ / div. * Does not disable the PLL. + * + * If to_default is set, then will configure CPU - MEM - SYS - APB frequencies back to power-on reset configuration (40 - 20 - 20 - 10) + * If to_default is not set, then will configure to 40 - 40 - 40 - 40 */ -static void rtc_clk_cpu_freq_to_xtal(int cpu_freq, int div) -{ - clk_ll_ahb_set_ls_divider(div); - clk_ll_cpu_set_ls_divider(div); +static void rtc_clk_cpu_freq_to_xtal(int cpu_freq, int div, bool to_default) +{ + // let f_cpu = f_mem = f_sys = f_apb + uint32_t mem_divider = 1; + uint32_t sys_divider = 1; + uint32_t apb_divider = 1; + if (to_default) { + // f_cpu = 2 * f_mem = 2 * f_sys = 4 * f_apb + mem_divider = 2; + apb_divider = 2; + } + // Update bit does not control CPU clock sel mux. Therefore, there will be a middle state during the switch (CPU falls) + // Since before the switch, the clock source is CPLL, there is divider value constraints. + // Setting the new dividers first is unguaranteed (hardware could automatically modify the real dividers) + // Therefore, we will switch cpu clock source first, and then set the desired dividers. clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_XTAL); - ets_update_cpu_frequency(cpu_freq); + clk_ll_cpu_set_divider(div, 0, 0); + clk_ll_mem_set_divider(mem_divider); + clk_ll_sys_set_divider(sys_divider); + clk_ll_apb_set_divider(apb_divider); + clk_ll_bus_update(); + esp_rom_set_cpu_ticks_per_us(cpu_freq); } static void rtc_clk_cpu_freq_to_8m(void) { - clk_ll_ahb_set_ls_divider(1); - clk_ll_cpu_set_ls_divider(1); + // let f_cpu = f_mem = f_sys = f_apb + clk_ll_cpu_set_divider(1, 0, 0); + clk_ll_mem_set_divider(1); + clk_ll_sys_set_divider(1); + clk_ll_apb_set_divider(1); clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_RC_FAST); - ets_update_cpu_frequency(20); + clk_ll_bus_update(); + esp_rom_set_cpu_ticks_per_us(20); } /** - * Switch to one of PLL-based frequencies. Current frequency can be XTAL or PLL. - * PLL must already be enabled. + * Switch to one of CPLL-based frequencies. Current frequency can be XTAL or CPLL. + * CPLL must already be enabled. * @param cpu_freq new CPU frequency */ -static void rtc_clk_cpu_freq_to_pll_mhz(int cpu_freq_mhz) -{ - clk_ll_cpu_set_hs_divider(CLK_LL_PLL_480M_FREQ_MHZ / cpu_freq_mhz); +static void rtc_clk_cpu_freq_to_cpll_mhz(int cpu_freq_mhz, hal_utils_clk_div_t *div) +{ + // CPLL -> CPU_CLK -> MEM_CLK -> SYS_CLK -> APB_CLK + // Constraint: MEM_CLK <= 200MHz, APB_CLK <= 100MHz + // This implies that when clock source is CPLL, + // If cpu_divider < 2, mem_divider must be larger or equal to 2 + // If cpu_divider < 2, mem_divider = 2, sys_divider < 2, apb_divider must be larger or equal to 2 + // Current available configurations: + // 360 - 360 - 180 - 180 - 90 + // 360 - 180 - 180 - 180 - 90 + // 360 - 90 - 90 - 90 - 90 + uint32_t mem_divider = 1; + uint32_t sys_divider = 1; // We are not going to change this + uint32_t apb_divider = 1; + switch (cpu_freq_mhz) { + case 360: + mem_divider = 2; + apb_divider = 2; + break; + case 180: + mem_divider = 1; + apb_divider = 2; + break; + case 90: + mem_divider = 1; + apb_divider = 1; + break; + default: + // Unsupported configuration + // This is dangerous to modify dividers. Hardware could automatically correct the divider, and it won't be + // reflected to the registers. Therefore, you won't even be able to calculate out the real mem_clk, apb_clk freq. + // To avoid such case, we will strictly do abort here. + abort(); + } + // Update bit does not control CPU clock sel mux. Therefore, there may be a middle state during the switch (CPU rises) + // We will switch cpu clock source first, and then set the desired dividers. + // It is likely that the hardware will automatically adjust dividers to meet mem_clk, apb_clk freq constraints when + // cpu clock source is set. + // However, the desired dividers will be written into registers anyways afterwards. + // This ensures the final confguration is the desired one. clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_PLL); - ets_update_cpu_frequency(cpu_freq_mhz); + clk_ll_cpu_set_divider(div->integer, div->numerator, div->denominator); + clk_ll_mem_set_divider(mem_divider); + clk_ll_sys_set_divider(sys_divider); + clk_ll_apb_set_divider(apb_divider); + clk_ll_bus_update(); + esp_rom_set_cpu_ticks_per_us(cpu_freq_mhz); } bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t *out_config) { uint32_t source_freq_mhz; soc_cpu_clk_src_t source; - uint32_t divider; // divider = freq of SOC_ROOT_CLK / freq of CPU_CLK + hal_utils_clk_div_t divider = {0}; // divider = freq of HP_ROOT_CLK / freq of CPU_CLK uint32_t real_freq_mhz; + // Keep default CPLL at 360MHz uint32_t xtal_freq = (uint32_t)rtc_clk_xtal_freq_get(); if (freq_mhz <= xtal_freq && freq_mhz != 0) { - divider = xtal_freq / freq_mhz; - real_freq_mhz = (xtal_freq + divider / 2) / divider; /* round */ + divider.integer = xtal_freq / freq_mhz; + real_freq_mhz = (xtal_freq + divider.integer / 2) / divider.integer; /* round */ if (real_freq_mhz != freq_mhz) { // no suitable divider return false; @@ -201,21 +267,27 @@ bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t *ou source_freq_mhz = xtal_freq; source = SOC_CPU_CLK_SRC_XTAL; - } else if (freq_mhz == 80) { + } else if (freq_mhz == 90) { real_freq_mhz = freq_mhz; - source = SOC_CPU_CLK_SRC_PLL; - source_freq_mhz = CLK_LL_PLL_480M_FREQ_MHZ; - divider = 6; - } else if (freq_mhz == 120) { + source = SOC_CPU_CLK_SRC_CPLL; + source_freq_mhz = CLK_LL_PLL_360M_FREQ_MHZ; + divider.integer = 4; + } else if (freq_mhz == 180) { real_freq_mhz = freq_mhz; - source = SOC_CPU_CLK_SRC_PLL; - source_freq_mhz = CLK_LL_PLL_480M_FREQ_MHZ; - divider = 4; - } else if (freq_mhz == 160) { + source = SOC_CPU_CLK_SRC_CPLL; + source_freq_mhz = CLK_LL_PLL_360M_FREQ_MHZ; + divider.integer = 2; + } else if (freq_mhz == 360) { real_freq_mhz = freq_mhz; - source = SOC_CPU_CLK_SRC_PLL; - source_freq_mhz = CLK_LL_PLL_480M_FREQ_MHZ; - divider = 3; + source = SOC_CPU_CLK_SRC_CPLL; + source_freq_mhz = CLK_LL_PLL_360M_FREQ_MHZ; + divider.integer = 1; + } else if (freq_mhz == 400) { + // If CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ selects 400MHz, then at app startup stage will need a CPLL calibration to raise its freq from 360MHz to 400MHz + real_freq_mhz = freq_mhz; + source = SOC_CPU_CLK_SRC_CPLL; + source_freq_mhz = CLK_LL_PLL_400M_FREQ_MHZ; + divider.integer = 1; } else { // unsupported frequency return false; @@ -233,22 +305,25 @@ void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config) { soc_cpu_clk_src_t old_cpu_clk_src = clk_ll_cpu_get_src(); if (config->source == SOC_CPU_CLK_SRC_XTAL) { - rtc_clk_cpu_freq_to_xtal(config->freq_mhz, config->div); - if ((old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL) && !s_bbpll_digi_consumers_ref_count) { - // We don't turn off the bbpll if some consumers depend on bbpll - rtc_clk_bbpll_disable(); + rtc_clk_cpu_freq_to_xtal(config->freq_mhz, config->div.integer, false); + if (old_cpu_clk_src == SOC_CPU_CLK_SRC_CPLL) { + rtc_clk_cpll_disable(); + } + } else if (config->source == SOC_CPU_CLK_SRC_CPLL) { + if (old_cpu_clk_src != SOC_CPU_CLK_SRC_CPLL) { + rtc_clk_cpll_enable(); } - } else if (config->source == SOC_CPU_CLK_SRC_PLL) { - if (old_cpu_clk_src != SOC_CPU_CLK_SRC_PLL) { - rtc_clk_bbpll_enable(); - rtc_clk_bbpll_configure(rtc_clk_xtal_freq_get(), config->source_freq_mhz); + if (config->source_freq_mhz != s_cur_cpll_freq) { + rtc_xtal_freq_t xtal_freq_mhz = rtc_clk_xtal_freq_get(); + // Calibrate CPLL freq to a new value requires to switch CPU clock source to XTAL first + rtc_clk_cpu_freq_to_xtal((uint32_t)xtal_freq_mhz, 1, false); + rtc_clk_cpll_configure(xtal_freq_mhz, config->source_freq_mhz); } - rtc_clk_cpu_freq_to_pll_mhz(config->freq_mhz); + rtc_clk_cpu_freq_to_cpll_mhz(config->freq_mhz, (hal_utils_clk_div_t *)&config->div); } else if (config->source == SOC_CPU_CLK_SRC_RC_FAST) { rtc_clk_cpu_freq_to_8m(); - if ((old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL) && !s_bbpll_digi_consumers_ref_count) { - // We don't turn off the bbpll if some consumers depend on bbpll - rtc_clk_bbpll_disable(); + if (old_cpu_clk_src == SOC_CPU_CLK_SRC_CPLL) { + rtc_clk_cpll_disable(); } } } @@ -257,30 +332,30 @@ void rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t *out_config) { soc_cpu_clk_src_t source = clk_ll_cpu_get_src(); uint32_t source_freq_mhz; - uint32_t div; // div = freq of SOC_ROOT_CLK / freq of CPU_CLK + hal_utils_clk_div_t div = {0}; // div = freq of SOC_ROOT_CLK / freq of CPU_CLK uint32_t freq_mhz; + clk_ll_cpu_get_divider(&div.integer, &div.numerator, &div.denominator); + if (div.denominator == 0) { + div.denominator = 1; + div.numerator = 0; + } switch (source) { case SOC_CPU_CLK_SRC_XTAL: { - div = clk_ll_cpu_get_ls_divider(); source_freq_mhz = (uint32_t)rtc_clk_xtal_freq_get(); - freq_mhz = source_freq_mhz / div; break; } - case SOC_CPU_CLK_SRC_PLL: { - div = clk_ll_cpu_get_hs_divider(); - source_freq_mhz = clk_ll_bbpll_get_freq_mhz(); - freq_mhz = source_freq_mhz / div; + case SOC_CPU_CLK_SRC_CPLL: { + source_freq_mhz = clk_ll_cpll_get_freq_mhz((uint32_t)rtc_clk_xtal_freq_get()); break; } case SOC_CPU_CLK_SRC_RC_FAST: - div = clk_ll_cpu_get_ls_divider(); source_freq_mhz = 20; - freq_mhz = source_freq_mhz / div; break; default: ESP_HW_LOGE(TAG, "unsupported frequency configuration"); abort(); } + freq_mhz = source_freq_mhz * div.denominator / (div.integer * div.denominator + div.numerator); *out_config = (rtc_cpu_freq_config_t) { .source = source, .source_freq_mhz = source_freq_mhz, @@ -292,10 +367,10 @@ void rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t *out_config) void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t *config) { if (config->source == SOC_CPU_CLK_SRC_XTAL) { - rtc_clk_cpu_freq_to_xtal(config->freq_mhz, config->div); - } else if (config->source == SOC_CPU_CLK_SRC_PLL && - s_cur_pll_freq == config->source_freq_mhz) { - rtc_clk_cpu_freq_to_pll_mhz(config->freq_mhz); + rtc_clk_cpu_freq_to_xtal(config->freq_mhz, config->div.integer, false); + } else if (config->source == SOC_CPU_CLK_SRC_CPLL && + s_cur_cpll_freq == config->source_freq_mhz) { + rtc_clk_cpu_freq_to_cpll_mhz(config->freq_mhz, (hal_utils_clk_div_t *)&config->div); } else if (config->source == SOC_CPU_CLK_SRC_RC_FAST) { rtc_clk_cpu_freq_to_8m(); } else { @@ -306,18 +381,17 @@ void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t *config) void rtc_clk_cpu_freq_set_xtal(void) { - rtc_clk_cpu_set_to_default_config(); - // We don't turn off the bbpll if some consumers depend on bbpll - if (!s_bbpll_digi_consumers_ref_count) { - rtc_clk_bbpll_disable(); - } + int freq_mhz = (int)rtc_clk_xtal_freq_get(); + + rtc_clk_cpu_freq_to_xtal(freq_mhz, 1, false); + rtc_clk_cpll_disable(); } void rtc_clk_cpu_set_to_default_config(void) { int freq_mhz = (int)rtc_clk_xtal_freq_get(); - rtc_clk_cpu_freq_to_xtal(freq_mhz, 1); + rtc_clk_cpu_freq_to_xtal(freq_mhz, 1, true); } rtc_xtal_freq_t rtc_clk_xtal_freq_get(void) @@ -335,53 +409,52 @@ void rtc_clk_xtal_freq_update(rtc_xtal_freq_t xtal_freq) clk_ll_xtal_store_freq_mhz(xtal_freq); } -static uint32_t rtc_clk_ahb_freq_get(void) +uint32_t rtc_clk_apb_freq_get(void) { soc_cpu_clk_src_t source = clk_ll_cpu_get_src(); - uint32_t soc_root_freq_mhz; - uint32_t divider; + uint32_t source_freq_mhz; switch (source) { case SOC_CPU_CLK_SRC_XTAL: - soc_root_freq_mhz = rtc_clk_xtal_freq_get(); - divider = clk_ll_ahb_get_ls_divider(); + source_freq_mhz = (uint32_t)rtc_clk_xtal_freq_get(); break; - case SOC_CPU_CLK_SRC_PLL: - soc_root_freq_mhz = clk_ll_bbpll_get_freq_mhz(); - divider = clk_ll_ahb_get_hs_divider(); + case SOC_CPU_CLK_SRC_CPLL: + source_freq_mhz = clk_ll_cpll_get_freq_mhz((uint32_t)rtc_clk_xtal_freq_get()); break; case SOC_CPU_CLK_SRC_RC_FAST: - soc_root_freq_mhz = 20; - divider = clk_ll_ahb_get_ls_divider(); + source_freq_mhz = 20; break; default: - // Unknown SOC_ROOT clock source - soc_root_freq_mhz = 0; - divider = 1; - ESP_HW_LOGE(TAG, "Invalid SOC_ROOT_CLK"); + // Unknown HP_ROOT clock source + source_freq_mhz = 0; + ESP_HW_LOGE(TAG, "Invalid HP_ROOT_CLK"); break; } - return soc_root_freq_mhz / divider; -} - -uint32_t rtc_clk_apb_freq_get(void) -{ - return rtc_clk_ahb_freq_get() / clk_ll_apb_get_divider() * MHZ; + uint32_t integer, numerator, denominator; + clk_ll_cpu_get_divider(&integer, &numerator, &denominator); + if (denominator == 0) { + denominator = 1; + numerator = 0; + } + uint32_t cpu_freq_hz = source_freq_mhz * MHZ * denominator / (integer * denominator + numerator); + uint32_t mem_freq_hz = cpu_freq_hz / clk_ll_mem_get_divider(); + uint32_t sys_freq_hz = mem_freq_hz / clk_ll_sys_get_divider(); + return sys_freq_hz / clk_ll_apb_get_divider(); } void rtc_clk_apll_enable(bool enable) { - // TODO: IDF-7526 + // TODO: IDF-8884 } uint32_t rtc_clk_apll_coeff_calc(uint32_t freq, uint32_t *_o_div, uint32_t *_sdm0, uint32_t *_sdm1, uint32_t *_sdm2) { - // TODO: IDF-7526 + // TODO: IDF-8884 return 0; } void rtc_clk_apll_coeff_set(uint32_t o_div, uint32_t sdm0, uint32_t sdm1, uint32_t sdm2) { - // TODO: IDF-7526 + // TODO: IDF-8884 } void rtc_dig_clk8m_enable(void) @@ -401,11 +474,6 @@ bool rtc_dig_8m_enabled(void) return clk_ll_rc_fast_digi_is_enabled(); } -/* Name used in libphy.a:phy_chip_v7.o - * TODO: update the library to use rtc_clk_xtal_freq_get - */ -rtc_xtal_freq_t rtc_get_xtal(void) __attribute__((alias("rtc_clk_xtal_freq_get"))); - //------------------------------------MPLL-------------------------------------// void rtc_clk_mpll_disable(void) { diff --git a/components/esp_hw_support/port/esp32p4/rtc_clk_init.c b/components/esp_hw_support/port/esp32p4/rtc_clk_init.c index 436d2e33fb88..6d6ff9963126 100644 --- a/components/esp_hw_support/port/esp32p4/rtc_clk_init.c +++ b/components/esp_hw_support/port/esp32p4/rtc_clk_init.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -14,8 +14,11 @@ #include "soc/rtc.h" #include "esp_cpu.h" #include "regi2c_ctrl.h" -#include "soc/lp_clkrst_reg.h" #include "soc/regi2c_dig_reg.h" +#include "soc/regi2c_bias.h" +#include "soc/lp_clkrst_reg.h" +#include "soc/lp_system_reg.h" +#include "soc/pmu_reg.h" #include "esp_hw_log.h" #include "sdkconfig.h" #include "esp_rom_uart.h" @@ -24,43 +27,13 @@ static const char *TAG = "rtc_clk_init"; -#if SOC_PMU_SUPPORTED -/** - * Initialize the ICG map of some modem clock domains in the PMU_ACTIVE state - * - * A pre-initialization interface is used to initialize the ICG map of the - * MODEM_APB, I2C_MST and LP_APB clock domains in the PMU_ACTIVE state, and - * disable the clock gating of these clock domains in the PMU_ACTIVE state, - * because the system clock source (PLL) in the system boot up process needs - * to use the i2c master peripheral. - * - * ICG map of all modem clock domains under different power states (PMU_ACTIVE, - * PMU_MODEM and PMU_SLEEP) will be initialized in esp_perip_clk_init(). - */ -static void rtc_clk_modem_clock_domain_active_state_icg_map_preinit(void) -{ - /* Configure modem ICG code in PMU_ACTIVE state */ - pmu_ll_hp_set_icg_modem(&PMU, PMU_MODE_HP_ACTIVE, PMU_HP_ICG_MODEM_CODE_ACTIVE); - - /* Disable clock gating for MODEM_APB, I2C_MST and LP_APB clock domains in PMU_ACTIVE state */ - modem_syscon_ll_set_modem_apb_icg_bitmap(&MODEM_SYSCON, BIT(PMU_HP_ICG_MODEM_CODE_ACTIVE)); - modem_lpcon_ll_set_i2c_master_icg_bitmap(&MODEM_LPCON, BIT(PMU_HP_ICG_MODEM_CODE_ACTIVE)); - modem_lpcon_ll_set_lp_apb_icg_bitmap(&MODEM_LPCON, BIT(PMU_HP_ICG_MODEM_CODE_ACTIVE)); - - /* Software trigger force update modem ICG code and ICG switch */ - pmu_ll_imm_update_dig_icg_modem_code(&PMU, true); - pmu_ll_imm_update_dig_icg_switch(&PMU, true); -} -#endif //#if SOC_PMU_SUPPORTED +static uint32_t HP_CALI_DBIAS = 27; //about 1.25v +static uint32_t LP_CALI_DBIAS = 29; //about 1.25v void rtc_clk_init(rtc_clk_config_t cfg) { rtc_cpu_freq_config_t old_config, new_config; -#if SOC_PMU_SUPPORTED - rtc_clk_modem_clock_domain_active_state_icg_map_preinit(); -#endif //#if SOC_PMU_SUPPORTED - /* Set tuning parameters for RC_FAST, RC_SLOW, and RC32K clocks. * Note: this doesn't attempt to set the clocks to precise frequencies. * Instead, we calibrate these clocks against XTAL frequency later, when necessary. @@ -74,6 +47,25 @@ void rtc_clk_init(rtc_clk_config_t cfg) REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_SCK_DCAP, cfg.slow_clk_dcap); REG_SET_FIELD(LP_CLKRST_RC32K_CNTL_REG, LP_CLKRST_RC32K_DFREQ, cfg.rc32k_dfreq); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_FORCE_RTC_DREG, 1); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_FORCE_DIG_DREG, 1); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_RTC_REG, 0); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_DIG_REG, 0); + + REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_OR_FORCE_XPD_CK, 0); + REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_OR_FORCE_XPD_REF_OUT_BUF, 0); + REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_OR_FORCE_XPD_IPH, 0); + REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_OR_FORCE_XPD_VGATE_BUF, 0); + + REG_SET_FIELD(PMU_HP_SLEEP_LP_REGULATOR0_REG, PMU_HP_SLEEP_LP_REGULATOR_DBIAS, LP_CALI_DBIAS); + + // Switch to DCDC + SET_PERI_REG_MASK(PMU_DCM_CTRL_REG, PMU_DCDC_ON_REQ); + CLEAR_PERI_REG_MASK(LP_SYSTEM_REG_SYS_CTRL_REG, LP_SYSTEM_REG_LP_FIB_DCDC_SWITCH); //0: enable, 1: disable + REG_SET_FIELD(PMU_HP_ACTIVE_BIAS_REG, PMU_HP_ACTIVE_DCM_VSET, HP_CALI_DBIAS); + esp_rom_delay_us(1000); + CLEAR_PERI_REG_MASK(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_ACTIVE_HP_REGULATOR_XPD); + rtc_xtal_freq_t xtal_freq = cfg.xtal_freq; esp_rom_uart_tx_wait_idle(0); rtc_clk_xtal_freq_update(xtal_freq); @@ -97,8 +89,6 @@ void rtc_clk_init(rtc_clk_config_t cfg) bool need_rc_fast_en = true; if (cfg.slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) { rtc_clk_32k_enable(true); - } else if (cfg.slow_clk_src == SOC_RTC_SLOW_CLK_SRC_OSC_SLOW) { - rtc_clk_32k_enable_external(); } else if (cfg.slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC32K) { rtc_clk_rc32k_enable(true); } diff --git a/components/esp_hw_support/port/esp32p4/rtc_time.c b/components/esp_hw_support/port/esp32p4/rtc_time.c index d1d20b6f1499..d7af8c728b5d 100644 --- a/components/esp_hw_support/port/esp32p4/rtc_time.c +++ b/components/esp_hw_support/port/esp32p4/rtc_time.c @@ -8,58 +8,65 @@ #include #include "esp32p4/rom/ets_sys.h" #include "soc/rtc.h" -#include "soc/lp_timer_reg.h" #include "hal/lp_timer_hal.h" #include "hal/clk_tree_ll.h" #include "hal/timer_ll.h" +#include "soc/hp_sys_clkrst_reg.h" #include "soc/timer_group_reg.h" #include "esp_rom_sys.h" #include "esp_private/periph_ctrl.h" static const char *TAG = "rtc_time"; -/* Calibration of RTC_SLOW_CLK is performed using a special feature of TIMG0. +/* Calibration of clock frequency is performed using a special feature of TIMG0. * This feature counts the number of XTAL clock cycles within a given number of - * RTC_SLOW_CLK cycles. - * - * Slow clock calibration feature has two modes of operation: one-off and cycling. - * In cycling mode (which is enabled by default on SoC reset), counting of XTAL - * cycles within RTC_SLOW_CLK cycle is done continuously. Cycling mode is enabled - * using TIMG_RTC_CALI_START_CYCLING bit. In one-off mode counting is performed - * once, and TIMG_RTC_CALI_RDY bit is set when counting is done. One-off mode is - * enabled using TIMG_RTC_CALI_START bit. + * clock cycles. */ -/* On ESP32P4, TIMG_RTC_CALI_CLK_SEL can config to 0, 1, 2, 3 - * 0 or 3: calibrate RC_SLOW clock - * 1: calibrate RC_FAST clock - * 2: calibrate 32K clock, which 32k depends on reg_32k_sel: 0: Internal 32 kHz RC oscillator, 1: External 32 kHz XTAL, 2: External 32kHz clock input by lp_pad_gpio0 - */ -#define TIMG_RTC_CALI_CLK_SEL_RC_SLOW 0 -#define TIMG_RTC_CALI_CLK_SEL_RC_FAST 1 -#define TIMG_RTC_CALI_CLK_SEL_32K 2 +#define CLK_CAL_TIMEOUT_THRES(cal_clk, cycles) ((cal_clk == RTC_CAL_RC32K || cal_clk == RTC_CAL_32K_XTAL) ? (cycles << 12) : (cycles << 10)) + +// Calibration can only be performed on relatively slow speed clock signal. Therefore, for high-speed clocks, +// calibration is performed on their DIV_CLKs. The divider is configurable. We set: +#define CLK_CAL_DIV_VAL(cal_clk) \ + ((cal_clk == RTC_CAL_RC_SLOW || cal_clk == RTC_CAL_RC32K || cal_clk == RTC_CAL_32K_XTAL) ? 1 : \ + (cal_clk == RTC_CAL_LP_PLL) ? 50 : \ + (cal_clk == RTC_CAL_RC_FAST) ? 200 : \ + 4000) + +// CLK_CAL_FREQ_APPROX = CLK_FREQ_APPROX / CLK_CAL_DIV_VAL +#define CLK_CAL_FREQ_APPROX(cal_clk) \ + ((cal_clk == RTC_CAL_MPLL) ? (CLK_LL_PLL_500M_FREQ_MHZ * MHZ / 4000) : \ + (cal_clk == RTC_CAL_SPLL) ? (CLK_LL_PLL_480M_FREQ_MHZ * MHZ / 4000) : \ + (cal_clk == RTC_CAL_CPLL) ? (CLK_LL_PLL_400M_FREQ_MHZ * MHZ / 4000) : \ + (cal_clk == RTC_CAL_APLL) ? (105 * MHZ / 4000) : \ + (cal_clk == RTC_CAL_SDIO_PLL0 || cal_clk == RTC_CAL_SDIO_PLL1 || cal_clk == RTC_CAL_SDIO_PLL2) ? (200 * MHZ / 4000) : \ + (cal_clk == RTC_CAL_RC_FAST) ? (SOC_CLK_RC_FAST_FREQ_APPROX / 200) : \ + (cal_clk == RTC_CAL_RC_SLOW) ? (SOC_CLK_RC_SLOW_FREQ_APPROX) : \ + (cal_clk == RTC_CAL_RC32K) ? (SOC_CLK_RC32K_FREQ_APPROX) : \ + (cal_clk == RTC_CAL_32K_XTAL) ? (SOC_CLK_XTAL32K_FREQ_APPROX) : \ + (cal_clk == RTC_CAL_LP_PLL) ? (CLK_LL_PLL_8M_FREQ_MHZ * MHZ / 50) : \ + 0) uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) { assert(slowclk_cycles < TIMG_RTC_CALI_MAX_V); - uint32_t cali_clk_sel = 0; - soc_rtc_slow_clk_src_t slow_clk_src = rtc_clk_slow_src_get(); - soc_rtc_slow_clk_src_t old_32k_cal_clk_sel = clk_ll_32k_calibration_get_target(); if (cal_clk == RTC_CAL_RTC_MUX) { - cal_clk = (rtc_cal_sel_t)slow_clk_src; + soc_rtc_slow_clk_src_t slow_clk_src = rtc_clk_slow_src_get(); + if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC_SLOW) { + cal_clk = RTC_CAL_RC_SLOW; + } else if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) { + cal_clk = RTC_CAL_32K_XTAL; + } else if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC32K) { + cal_clk = RTC_CAL_RC32K; + } } - if (cal_clk == RTC_CAL_RC_FAST) { - cali_clk_sel = TIMG_RTC_CALI_CLK_SEL_RC_FAST; - } else if (cal_clk == RTC_CAL_RC_SLOW) { - cali_clk_sel = TIMG_RTC_CALI_CLK_SEL_RC_SLOW; - } else { - cali_clk_sel = TIMG_RTC_CALI_CLK_SEL_32K; - clk_ll_32k_calibration_set_target((soc_rtc_slow_clk_src_t)cal_clk); + if (cal_clk < 0 || cal_clk >= RTC_CAL_INVALID_CLK) { + ESP_EARLY_LOGE(TAG, "clock not supported to be calibrated"); + return 0; } - - /* Enable requested clock (150k clock is always on) */ + /* Enable requested clock (some clocks are always on) */ // All clocks on/off takes time to be stable, so we shouldn't frequently enable/disable the clock // Only enable if orignally was disabled, and set back to the disable state after calibration is done // If the clock is already on, then do nothing @@ -104,23 +111,17 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) } /* Prepare calibration */ - REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_CLK_SEL, cali_clk_sel); + REG_SET_FIELD(HP_SYS_CLKRST_PERI_CLK_CTRL21_REG, HP_SYS_CLKRST_REG_TIMERGRP0_TGRT_CLK_SRC_SEL, cal_clk); + uint32_t clk_cal_divider = CLK_CAL_DIV_VAL(cal_clk); + REG_SET_FIELD(HP_SYS_CLKRST_PERI_CLK_CTRL21_REG, HP_SYS_CLKRST_REG_TIMERGRP0_TGRT_CLK_DIV_NUM, clk_cal_divider - 1); CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING); REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_MAX, slowclk_cycles); /* Figure out how long to wait for calibration to finish */ /* Set timeout reg and expect time delay*/ - uint32_t expected_freq; - if (cali_clk_sel == TIMG_RTC_CALI_CLK_SEL_32K) { - REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_SLOW_CLK_32K_CAL_TIMEOUT_THRES(slowclk_cycles)); - expected_freq = SOC_CLK_XTAL32K_FREQ_APPROX; - } else if (cali_clk_sel == TIMG_RTC_CALI_CLK_SEL_RC_FAST) { - REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_FAST_CLK_20M_CAL_TIMEOUT_THRES(slowclk_cycles)); - expected_freq = SOC_CLK_RC_FAST_FREQ_APPROX; - } else { - REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_SLOW_CLK_150K_CAL_TIMEOUT_THRES(slowclk_cycles)); - expected_freq = SOC_CLK_RC_SLOW_FREQ_APPROX; - } + REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, CLK_CAL_TIMEOUT_THRES(cal_clk, slowclk_cycles)); + uint32_t expected_freq = CLK_CAL_FREQ_APPROX(cal_clk); + assert(expected_freq); uint32_t us_time_estimate = (uint32_t) (((uint64_t) slowclk_cycles) * MHZ / expected_freq); /* Start calibration */ CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START); @@ -132,6 +133,7 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) while (true) { if (GET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_RDY)) { cal_val = REG_GET_FIELD(TIMG_RTCCALICFG1_REG(0), TIMG_RTC_CALI_VALUE); + cal_val /= clk_cal_divider; break; } if (GET_PERI_REG_MASK(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT)) { @@ -164,11 +166,6 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) } } - // Always set back the calibration 32kHz clock selection - if (old_32k_cal_clk_sel != SOC_RTC_SLOW_CLK_SRC_INVALID) { - clk_ll_32k_calibration_set_target(old_32k_cal_clk_sel); - } - return cal_val; } @@ -211,9 +208,7 @@ uint64_t rtc_time_slowclk_to_us(uint64_t rtc_cycles, uint32_t period) uint64_t rtc_time_get(void) { - // return lp_timer_hal_get_cycle_count(0); - ESP_EARLY_LOGE(TAG, "rtc_time_get has not been implemented yet"); - return 0; + return lp_timer_hal_get_cycle_count(); } void rtc_clk_wait_for_slow_cycle(void) //This function may not by useful any more diff --git a/components/esp_hw_support/port/esp_clk_tree_common.c b/components/esp_hw_support/port/esp_clk_tree_common.c index a5e701f0c411..4e256bb4752d 100644 --- a/components/esp_hw_support/port/esp_clk_tree_common.c +++ b/components/esp_hw_support/port/esp_clk_tree_common.c @@ -177,6 +177,8 @@ uint32_t esp_clk_tree_lp_fast_get_freq_hz(esp_clk_tree_src_freq_precision_t prec case SOC_RTC_FAST_CLK_SRC_XTAL_DIV: #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 //SOC_RTC_FAST_CLK_SRC_XTAL_D4 return clk_hal_xtal_get_freq_mhz() * MHZ >> 2; +#elif CONFIG_IDF_TARGET_ESP32P4 //SOC_RTC_FAST_CLK_SRC_XTAL + return clk_hal_xtal_get_freq_mhz() * MHZ; #else //SOC_RTC_FAST_CLK_SRC_XTAL_D2 return clk_hal_xtal_get_freq_mhz() * MHZ >> 1; #endif diff --git a/components/esp_hw_support/rtc_module.c b/components/esp_hw_support/rtc_module.c index 3e7e44bce805..aed8e0e78ea8 100644 --- a/components/esp_hw_support/rtc_module.c +++ b/components/esp_hw_support/rtc_module.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2016-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2016-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -26,14 +26,14 @@ #endif #include "sys/queue.h" -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4// TODO: IDF-8008 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 // TODO: IDF-8008 static const char *TAG = "rtc_module"; #endif // rtc_spinlock is used by other peripheral drivers portMUX_TYPE rtc_spinlock = portMUX_INITIALIZER_UNLOCKED; -#if !CONFIG_IDF_TARGET_ESP32C6 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP32P4 // TODO: IDF-8008 +#if !CONFIG_IDF_TARGET_ESP32C6 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP32P4 && !CONFIG_IDF_TARGET_ESP32C5 // TODO: IDF-8008 #define NOT_REGISTERED (-1) @@ -101,7 +101,7 @@ static esp_err_t rtc_isr_ensure_installed(void) esp_err_t rtc_isr_register(intr_handler_t handler, void* handler_arg, uint32_t rtc_intr_mask, uint32_t flags) { -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 // TODO: IDF-8008 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 // TODO: IDF-8008 ESP_EARLY_LOGW(TAG, "rtc_isr_register() has not been implemented yet"); return ESP_OK; #else @@ -132,7 +132,7 @@ esp_err_t rtc_isr_register(intr_handler_t handler, void* handler_arg, uint32_t r esp_err_t rtc_isr_deregister(intr_handler_t handler, void* handler_arg) { -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 // TODO: IDF-8008 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 // TODO: IDF-8008 ESP_EARLY_LOGW(TAG, "rtc_isr_deregister() has not been implemented yet"); return ESP_OK; #else @@ -161,7 +161,7 @@ esp_err_t rtc_isr_deregister(intr_handler_t handler, void* handler_arg) #endif } -#if !CONFIG_IDF_TARGET_ESP32C6 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP32P4 // TODO: IDF-8008 +#if !CONFIG_IDF_TARGET_ESP32C6 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP32P4 && !CONFIG_IDF_TARGET_ESP32C5 // TODO: IDF-8008 /** * @brief This helper function can be used to avoid the interrupt to be triggered with cache disabled. * There are lots of different signals on RTC module (i.e. sleep_wakeup, wdt, brownout_detect, etc.) @@ -184,7 +184,7 @@ static void s_rtc_isr_noniram_hook_relieve(uint32_t rtc_intr_mask) IRAM_ATTR void rtc_isr_noniram_disable(uint32_t cpu) { -#if !CONFIG_IDF_TARGET_ESP32C6 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP32P4 // TODO: IDF-8008 +#if !CONFIG_IDF_TARGET_ESP32C6 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP32P4 && !CONFIG_IDF_TARGET_ESP32C5 // TODO: IDF-8008 if (rtc_isr_cpu == cpu) { rtc_intr_enabled |= RTCCNTL.int_ena.val; RTCCNTL.int_ena.val &= rtc_intr_cache; @@ -194,7 +194,7 @@ IRAM_ATTR void rtc_isr_noniram_disable(uint32_t cpu) IRAM_ATTR void rtc_isr_noniram_enable(uint32_t cpu) { -#if !CONFIG_IDF_TARGET_ESP32C6 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP32P4 // TODO: IDF-8008 +#if !CONFIG_IDF_TARGET_ESP32C6 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP32P4 && !CONFIG_IDF_TARGET_ESP32C5 // TODO: IDF-8008 if (rtc_isr_cpu == cpu) { RTCCNTL.int_ena.val = rtc_intr_enabled; rtc_intr_enabled = 0; diff --git a/components/esp_hw_support/sleep_clock.c b/components/esp_hw_support/sleep_clock.c index ab60b0980fcb..bc81b0385d93 100644 --- a/components/esp_hw_support/sleep_clock.c +++ b/components/esp_hw_support/sleep_clock.c @@ -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 */ @@ -33,7 +33,7 @@ esp_err_t sleep_clock_system_retention_init(void) { #if CONFIG_IDF_TARGET_ESP32C6 #define N_REGS_PCR() (((PCR_SRAM_POWER_CONF_REG - DR_REG_PCR_BASE) / 4) + 1) -#elif CONFIG_IDF_TARGET_ESP32H2 +#elif CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C5 #define N_REGS_PCR() (((PCR_PWDET_SAR_CLK_CONF_REG - DR_REG_PCR_BASE) / 4) + 1) #endif const static sleep_retention_entries_config_t pcr_regs_retention[] = { @@ -53,7 +53,11 @@ void sleep_clock_system_retention_deinit(void) esp_err_t sleep_clock_modem_retention_init(void) { +#if CONFIG_IDF_TARGET_ESP32C5 + #define N_REGS_SYSCON() (((MODEM_SYSCON_MEM_RF2_CONF_REG - MODEM_SYSCON_TEST_CONF_REG) / 4) + 1) +#else #define N_REGS_SYSCON() (((MODEM_SYSCON_MEM_CONF_REG - MODEM_SYSCON_TEST_CONF_REG) / 4) + 1) +#endif #if SOC_PM_RETENTION_SW_TRIGGER_REGDMA #define N_REGS_LPCON() (((MODEM_LPCON_MEM_CONF_REG - MODEM_LPCON_TEST_CONF_REG) / 4) + 1) #endif diff --git a/components/esp_hw_support/sleep_cpu.c b/components/esp_hw_support/sleep_cpu.c index f77c4e336c7b..5de60e6a29ad 100644 --- a/components/esp_hw_support/sleep_cpu.c +++ b/components/esp_hw_support/sleep_cpu.c @@ -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 */ @@ -47,6 +47,14 @@ #include "soc/plic_reg.h" #include "soc/clint_reg.h" #include "esp32c6/rom/cache.h" +#elif CONFIG_IDF_TARGET_ESP32C5 +#include "esp32c5/rom/rtc.h" +#include "riscv/rvsleep-frames.h" +#include "soc/intpri_reg.h" +#include "soc/cache_reg.h" +#include "soc/clic_reg.h" +#include "soc/clint_reg.h" +#include "esp32c5/rom/cache.h" #elif CONFIG_IDF_TARGET_ESP32H2 #include "esp32h2/rom/rtc.h" #include "riscv/rvsleep-frames.h" @@ -329,7 +337,7 @@ static inline void * cpu_domain_cache_config_sleep_frame_alloc_and_init(void) #if CONFIG_IDF_TARGET_ESP32C6 { .start = EXTMEM_L1_CACHE_CTRL_REG, .end = EXTMEM_L1_CACHE_CTRL_REG + 4 }, { .start = EXTMEM_L1_CACHE_WRAP_AROUND_CTRL_REG, .end = EXTMEM_L1_CACHE_WRAP_AROUND_CTRL_REG + 4 } -#elif CONFIG_IDF_TARGET_ESP32H2 +#elif CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C5 { .start = CACHE_L1_CACHE_CTRL_REG, .end = CACHE_L1_CACHE_CTRL_REG + 4 }, { .start = CACHE_L1_CACHE_WRAP_AROUND_CTRL_REG, .end = CACHE_L1_CACHE_WRAP_AROUND_CTRL_REG + 4 } #endif diff --git a/components/esp_hw_support/sleep_cpu_asm.S b/components/esp_hw_support/sleep_cpu_asm.S index 65d0e6de0668..788035d11bd9 100644 --- a/components/esp_hw_support/sleep_cpu_asm.S +++ b/components/esp_hw_support/sleep_cpu_asm.S @@ -9,7 +9,7 @@ #include "soc/soc_caps.h" #include "sdkconfig.h" -#if !CONFIG_IDF_TARGET_ESP32C6 && !CONFIG_IDF_TARGET_ESP32H2 +#if !CONFIG_IDF_TARGET_ESP32C6 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP32C5 #include "soc/lp_aon_reg.h" #include "soc/extmem_reg.h" #endif @@ -115,7 +115,7 @@ rv_core_critical_regs_save: csrr t0, mscratch sw t0, RV_SLP_CTX_T0(t3) -#if !CONFIG_IDF_TARGET_ESP32C6 && !CONFIG_IDF_TARGET_ESP32H2 +#if !CONFIG_IDF_TARGET_ESP32C6 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP32C5 /* writeback dcache is required here!!! */ la t0, EXTMEM_CACHE_SYNC_MAP_REG li t1, 0x10 diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 4fbe9edf9992..545698c24034 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -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 */ @@ -81,6 +81,9 @@ #elif CONFIG_IDF_TARGET_ESP32C6 #include "esp32c6/rom/rtc.h" #include "hal/gpio_ll.h" +#elif CONFIG_IDF_TARGET_ESP32C5 +#include "esp32c5/rom/rtc.h" +#include "hal/gpio_ll.h" #elif CONFIG_IDF_TARGET_ESP32H2 #include "esp32h2/rom/rtc.h" #include "esp32h2/rom/cache.h" @@ -131,6 +134,9 @@ #elif CONFIG_IDF_TARGET_ESP32C6 #define DEFAULT_SLEEP_OUT_OVERHEAD_US (318) #define DEFAULT_HARDWARE_OUT_OVERHEAD_US (56) +#elif CONFIG_IDF_TARGET_ESP32C5 // TODO: [ESP32C5] IDF-8638, IDF-8640 +#define DEFAULT_SLEEP_OUT_OVERHEAD_US (318) +#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (56) #elif CONFIG_IDF_TARGET_ESP32H2 #define DEFAULT_SLEEP_OUT_OVERHEAD_US (118)// TODO: IDF-6267 #define DEFAULT_HARDWARE_OUT_OVERHEAD_US (9) diff --git a/components/esp_hw_support/sleep_system_peripheral.c b/components/esp_hw_support/sleep_system_peripheral.c index 4bf9be2e7ca7..d4fa793ee3a5 100644 --- a/components/esp_hw_support/sleep_system_peripheral.c +++ b/components/esp_hw_support/sleep_system_peripheral.c @@ -125,7 +125,7 @@ esp_err_t sleep_sys_periph_tg0_retention_init(void) esp_err_t sleep_sys_periph_iomux_retention_init(void) { -#if CONFIG_IDF_TARGET_ESP32C6 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32C5 // TODO: [ESP32C5] IDF-8638, IDF-8640 #define N_REGS_IOMUX_0() (((PERIPHS_IO_MUX_SPID_U - REG_IO_MUX_BASE) / 4) + 1) #define N_REGS_IOMUX_1() (((GPIO_FUNC34_OUT_SEL_CFG_REG - GPIO_FUNC0_OUT_SEL_CFG_REG) / 4) + 1) #define N_REGS_IOMUX_2() (((GPIO_FUNC124_IN_SEL_CFG_REG - GPIO_STATUS_NEXT_REG) / 4) + 1) diff --git a/components/esp_hw_support/test_apps/.build-test-rules.yml b/components/esp_hw_support/test_apps/.build-test-rules.yml index 43acc7dfd8ae..962e25992965 100644 --- a/components/esp_hw_support/test_apps/.build-test-rules.yml +++ b/components/esp_hw_support/test_apps/.build-test-rules.yml @@ -9,10 +9,18 @@ components/esp_hw_support/test_apps/dma: components/esp_hw_support/test_apps/esp_hw_support_unity_tests: disable: - if: SOC_GPSPI_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: test not pass, should be re-enable # TODO: IDF-8972 components/esp_hw_support/test_apps/etm: disable: - if: SOC_ETM_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: test not pass, should be re-enable # TODO: IDF-8974 depends_components: - esp_driver_gptimer - esp_driver_gpio diff --git a/components/esp_hw_support/test_apps/dma/pytest_dma.py b/components/esp_hw_support/test_apps/dma/pytest_dma.py index 0f5cc388d91e..cc78dd5f0ec6 100644 --- a/components/esp_hw_support/test_apps/dma/pytest_dma.py +++ b/components/esp_hw_support/test_apps/dma/pytest_dma.py @@ -10,6 +10,7 @@ @pytest.mark.esp32c3 @pytest.mark.esp32c6 @pytest.mark.esp32h2 +@pytest.mark.esp32p4 @pytest.mark.generic @pytest.mark.parametrize( 'config', diff --git a/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/pytest_esp_hw_support.py b/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/pytest_esp_hw_support.py index e8523e104c2d..a96369107b01 100644 --- a/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/pytest_esp_hw_support.py +++ b/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/pytest_esp_hw_support.py @@ -5,6 +5,7 @@ from pytest_embedded import Dut +@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='esp32p4 support TBD') # TODO: IDF-8972 @pytest.mark.generic @pytest.mark.parametrize( 'config', diff --git a/components/esp_hw_support/test_apps/rtc_clk/pytest_rtc_clk.py b/components/esp_hw_support/test_apps/rtc_clk/pytest_rtc_clk.py index 20eb2e85f2c0..817b6188c2eb 100644 --- a/components/esp_hw_support/test_apps/rtc_clk/pytest_rtc_clk.py +++ b/components/esp_hw_support/test_apps/rtc_clk/pytest_rtc_clk.py @@ -33,6 +33,6 @@ def test_rtc_no_xtal32k(dut: Dut) -> None: @pytest.mark.generic @pytest.mark.supported_targets -@pytest.mark.temp_skip_ci(targets=['esp32c6', 'esp32h2'], reason='c6/h2 support TBD') +@pytest.mark.temp_skip_ci(targets=['esp32c6', 'esp32h2', 'esp32p4'], reason='c6/h2/p4 support TBD') # TODO: IDF-8973 def test_rtc_calib(case_tester: Any) -> None: case_tester.run_all_multi_stage_cases() diff --git a/components/esp_lcd/include/esp_lcd_panel_io.h b/components/esp_lcd/include/esp_lcd_panel_io.h index 4a6e7c45e545..ffae62e68059 100644 --- a/components/esp_lcd/include/esp_lcd_panel_io.h +++ b/components/esp_lcd/include/esp_lcd_panel_io.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -137,10 +137,12 @@ typedef struct { int lcd_cmd_bits; /*!< Bit-width of LCD command */ int lcd_param_bits; /*!< Bit-width of LCD parameter */ struct { - unsigned int dc_low_on_data: 1; /*!< If this flag is enabled, DC line = 0 means transfer data, DC line = 1 means transfer command; vice versa */ + unsigned int dc_high_on_cmd: 1; /*!< If enabled, DC level = 1 indicates command transfer */ + unsigned int dc_low_on_data: 1; /*!< If enabled, DC level = 0 indicates color data transfer */ + unsigned int dc_low_on_param: 1; /*!< If enabled, DC level = 0 indicates parameter transfer */ unsigned int octal_mode: 1; /*!< transmit with octal mode (8 data lines), this mode is used to simulate Intel 8080 timing */ unsigned int quad_mode: 1; /*!< transmit with quad mode (4 data lines), this mode is useful when transmitting LCD parameters (Only use one line for command) */ - unsigned int sio_mode: 1; /*!< Read and write through a single data line (MOSI) */ + unsigned int sio_mode: 1; /*!< Read and write through a single data line (MOSI) */ unsigned int lsb_first: 1; /*!< transmit LSB bit first */ unsigned int cs_high_active: 1; /*!< CS line is high active */ } flags; /*!< Extra flags to fine-tune the SPI device */ diff --git a/components/esp_lcd/src/esp_lcd_panel_io_spi.c b/components/esp_lcd/src/esp_lcd_panel_io_spi.c index 663e3f2a62cb..c1b9bde53d21 100644 --- a/components/esp_lcd/src/esp_lcd_panel_io_spi.c +++ b/components/esp_lcd/src/esp_lcd_panel_io_spi.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -51,7 +51,9 @@ typedef struct { int lcd_cmd_bits; // Bit width of LCD command int lcd_param_bits; // Bit width of LCD parameter struct { - unsigned int dc_data_level: 1; // Indicates the level of DC line when tranfering data + unsigned int dc_cmd_level: 1; // Indicates the level of DC line when transferring command + unsigned int dc_data_level: 1; // Indicates the level of DC line when transferring color data + unsigned int dc_param_level: 1; // Indicates the level of DC line when transferring parameters unsigned int octal_mode: 1; // Indicates whether the transmitting is enabled with octal mode (8 data lines) unsigned int quad_mode: 1; // Indicates whether the transmitting is enabled with quad mode (4 data lines) } flags; @@ -93,7 +95,9 @@ esp_err_t esp_lcd_new_panel_io_spi(esp_lcd_spi_bus_handle_t bus, const esp_lcd_p ESP_GOTO_ON_ERROR(gpio_config(&io_conf), err, TAG, "configure GPIO for D/C line failed"); } + spi_panel_io->flags.dc_cmd_level = io_config->flags.dc_high_on_cmd; spi_panel_io->flags.dc_data_level = !io_config->flags.dc_low_on_data; + spi_panel_io->flags.dc_param_level = !io_config->flags.dc_low_on_param; spi_panel_io->flags.octal_mode = io_config->flags.octal_mode; spi_panel_io->flags.quad_mode = io_config->flags.quad_mode; spi_panel_io->on_color_trans_done = io_config->on_color_trans_done; @@ -224,7 +228,7 @@ static esp_err_t panel_io_spi_tx_param(esp_lcd_panel_io_t *io, int lcd_cmd, cons if (send_cmd) { spi_lcd_prepare_cmd_buffer(spi_panel_io, &lcd_cmd); - lcd_trans->flags.dc_gpio_level = !spi_panel_io->flags.dc_data_level; // set D/C line to command mode + lcd_trans->flags.dc_gpio_level = spi_panel_io->flags.dc_cmd_level; // set D/C level in command phase lcd_trans->base.length = spi_panel_io->lcd_cmd_bits; lcd_trans->base.tx_buffer = &lcd_cmd; // command is short, using polling mode @@ -234,7 +238,7 @@ static esp_err_t panel_io_spi_tx_param(esp_lcd_panel_io_t *io, int lcd_cmd, cons if (param && param_size) { spi_lcd_prepare_param_buffer(spi_panel_io, param, param_size); - lcd_trans->flags.dc_gpio_level = spi_panel_io->flags.dc_data_level; // set D/C line to data mode + lcd_trans->flags.dc_gpio_level = spi_panel_io->flags.dc_param_level; // set D/C level in param phase lcd_trans->base.length = param_size * 8; // transaction length is in bits lcd_trans->base.tx_buffer = param; lcd_trans->base.flags &= ~SPI_TRANS_CS_KEEP_ACTIVE; @@ -278,7 +282,7 @@ static esp_err_t panel_io_spi_rx_param(esp_lcd_panel_io_t *io, int lcd_cmd, void if (send_cmd) { spi_lcd_prepare_cmd_buffer(spi_panel_io, &lcd_cmd); - lcd_trans->flags.dc_gpio_level = !spi_panel_io->flags.dc_data_level; // set D/C line to command mode + lcd_trans->flags.dc_gpio_level = spi_panel_io->flags.dc_cmd_level; // set D/C level in command phase lcd_trans->base.length = spi_panel_io->lcd_cmd_bits; lcd_trans->base.tx_buffer = &lcd_cmd; // command is short, using polling mode @@ -287,7 +291,7 @@ static esp_err_t panel_io_spi_rx_param(esp_lcd_panel_io_t *io, int lcd_cmd, void } if (param && param_size) { - lcd_trans->flags.dc_gpio_level = spi_panel_io->flags.dc_data_level; // set D/C line to data mode + lcd_trans->flags.dc_gpio_level = spi_panel_io->flags.dc_param_level; // set D/C level in param phase lcd_trans->base.length = 0; lcd_trans->base.tx_buffer = NULL; lcd_trans->base.rxlength = param_size * 8; // Read length in bits @@ -327,7 +331,7 @@ static esp_err_t panel_io_spi_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, cons spi_lcd_prepare_cmd_buffer(spi_panel_io, &lcd_cmd); lcd_trans->base.user = spi_panel_io; - lcd_trans->flags.dc_gpio_level = !spi_panel_io->flags.dc_data_level; // set D/C line to command mode + lcd_trans->flags.dc_gpio_level = spi_panel_io->flags.dc_cmd_level; // set D/C level in command phase lcd_trans->base.length = spi_panel_io->lcd_cmd_bits; lcd_trans->base.tx_buffer = &lcd_cmd; if (color && color_size) { @@ -370,7 +374,7 @@ static esp_err_t panel_io_spi_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, cons } lcd_trans->base.user = spi_panel_io; - lcd_trans->flags.dc_gpio_level = spi_panel_io->flags.dc_data_level; // set D/C line to data mode + lcd_trans->flags.dc_gpio_level = spi_panel_io->flags.dc_data_level; // set D/C level in data phase lcd_trans->base.length = chunk_size * 8; // transaction length is in bits lcd_trans->base.tx_buffer = color; if (spi_panel_io->flags.octal_mode) { diff --git a/components/esp_lcd/test_apps/.build-test-rules.yml b/components/esp_lcd/test_apps/.build-test-rules.yml index 75564d3e091d..2ba3dd854a8d 100644 --- a/components/esp_lcd/test_apps/.build-test-rules.yml +++ b/components/esp_lcd/test_apps/.build-test-rules.yml @@ -42,3 +42,7 @@ components/esp_lcd/test_apps/spi_lcd: - esp_driver_spi disable: - if: SOC_GPSPI_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: test not pass, should be re-enable # TODO: IDF-8975 diff --git a/components/esp_lcd/test_apps/spi_lcd/pytest_spi_lcd.py b/components/esp_lcd/test_apps/spi_lcd/pytest_spi_lcd.py index b6590fc4c706..f2ad352216e7 100644 --- a/components/esp_lcd/test_apps/spi_lcd/pytest_spi_lcd.py +++ b/components/esp_lcd/test_apps/spi_lcd/pytest_spi_lcd.py @@ -5,6 +5,7 @@ from pytest_embedded import Dut +@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='esp32p4 support TBD') # TODO: IDF-8975 @pytest.mark.supported_targets @pytest.mark.generic @pytest.mark.parametrize( diff --git a/components/esp_partition/host_test/.build-test-rules.yml b/components/esp_partition/host_test/.build-test-rules.yml index b46c55645349..b129dc131a00 100644 --- a/components/esp_partition/host_test/.build-test-rules.yml +++ b/components/esp_partition/host_test/.build-test-rules.yml @@ -4,3 +4,6 @@ components/esp_partition/host_test/partition_api_test: enable: - if: IDF_TARGET == "linux" reason: only test on linux + depends_components: + - spi_flash + - esp_partition diff --git a/components/esp_phy/Kconfig b/components/esp_phy/Kconfig index b94aca1cbe32..59d7fe783d73 100644 --- a/components/esp_phy/Kconfig +++ b/components/esp_phy/Kconfig @@ -107,7 +107,7 @@ menu "PHY" config ESP_PHY_ENABLE_USB bool "Enable USB when phy init" - depends on USB_OTG_SUPPORTED || ESP_CONSOLE_USB_SERIAL_JTAG || ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG + depends on SOC_USB_OTG_SUPPORTED || ESP_CONSOLE_USB_SERIAL_JTAG || ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG default y if IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3 default n help diff --git a/components/esp_phy/lib b/components/esp_phy/lib index bf6003e60c8b..98617ae683c7 160000 --- a/components/esp_phy/lib +++ b/components/esp_phy/lib @@ -1 +1 @@ -Subproject commit bf6003e60c8bf7205ff16db660df7d7022a284d1 +Subproject commit 98617ae683c7456706c7de6e27b7f0355c77dc9b diff --git a/components/esp_pm/test_apps/.build-test-rules.yml b/components/esp_pm/test_apps/.build-test-rules.yml new file mode 100644 index 000000000000..fdac75267fad --- /dev/null +++ b/components/esp_pm/test_apps/.build-test-rules.yml @@ -0,0 +1,7 @@ +# Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps + +components/esp_pm/test_apps: + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: test not pass, should be re-enable # TODO: IDF-8976 diff --git a/components/esp_pm/test_apps/esp_pm/pytest_esp_pm.py b/components/esp_pm/test_apps/esp_pm/pytest_esp_pm.py index 9c241c1971ed..9d6fb7ad888b 100644 --- a/components/esp_pm/test_apps/esp_pm/pytest_esp_pm.py +++ b/components/esp_pm/test_apps/esp_pm/pytest_esp_pm.py @@ -5,6 +5,7 @@ from pytest_embedded import Dut +@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='esp32p4 support TBD') # TODO: IDF-8976 @pytest.mark.generic @pytest.mark.supported_targets @pytest.mark.parametrize('config', [ diff --git a/components/esp_psram/device/esp_psram_impl_ap_hex.c b/components/esp_psram/device/esp_psram_impl_ap_hex.c index c0fde7265d96..59fa7d6500a9 100644 --- a/components/esp_psram/device/esp_psram_impl_ap_hex.c +++ b/components/esp_psram/device/esp_psram_impl_ap_hex.c @@ -8,7 +8,7 @@ #include "esp_attr.h" #include "esp_err.h" #include "esp_log.h" -#include "esp_clk_tree.h" +#include "hal/clk_tree_hal.h" #include "esp_private/periph_ctrl.h" #include "esp_private/rtc_clk.h" #include "esp_private/esp_ldo_psram.h" @@ -356,11 +356,8 @@ esp_err_t esp_psram_impl_enable(void) { esp_ldo_vdd_psram_early_init(); #if SOC_CLK_MPLL_SUPPORTED - uint32_t xtal_freq = 0; - ESP_ERROR_CHECK(esp_clk_tree_src_get_freq_hz(SOC_MOD_CLK_XTAL, ESP_CLK_TREE_SRC_FREQ_PRECISION_EXACT, &xtal_freq)); - assert(xtal_freq == 40000000); rtc_clk_mpll_enable(); - rtc_clk_mpll_configure(xtal_freq / 1000000, AP_HEX_PSRAM_MPLL_DEFAULT_FREQ_MHZ); + rtc_clk_mpll_configure(clk_hal_xtal_get_freq_mhz(), AP_HEX_PSRAM_MPLL_DEFAULT_FREQ_MHZ); #endif PSRAM_RCC_ATOMIC() { diff --git a/components/esp_ringbuf/test_apps/CMakeLists.txt b/components/esp_ringbuf/test_apps/CMakeLists.txt index 18338d23a2e7..2a88829ff258 100644 --- a/components/esp_ringbuf/test_apps/CMakeLists.txt +++ b/components/esp_ringbuf/test_apps/CMakeLists.txt @@ -2,7 +2,7 @@ # CMakeLists in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.16) -list(PREPEND SDKCONFIG_DEFAULTS "$ENV{IDF_PATH}/tools/test_apps/configs/sdkconfig.debug_helpers") +list(PREPEND SDKCONFIG_DEFAULTS "$ENV{IDF_PATH}/tools/test_apps/configs/sdkconfig.debug_helpers" "sdkconfig.defaults") # "Trim" the build. Include the minimal set of components, main, and anything it depends on. set(COMPONENTS main) diff --git a/components/esp_rom/test_apps/.build-test-rules.yml b/components/esp_rom/test_apps/.build-test-rules.yml index 1eb663e7974a..a67fcbb8eacc 100644 --- a/components/esp_rom/test_apps/.build-test-rules.yml +++ b/components/esp_rom/test_apps/.build-test-rules.yml @@ -9,3 +9,6 @@ components/esp_rom/test_apps/rom_tests: - if: IDF_TARGET in ["esp32", "esp32c2"] temporary: false reason: lack of memory for testing miniz compressing + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: test not pass, should be re-enable # TODO: IDF-8977 diff --git a/components/esp_system/Kconfig b/components/esp_system/Kconfig index e0b42653d220..0f944aaac44a 100644 --- a/components/esp_system/Kconfig +++ b/components/esp_system/Kconfig @@ -345,6 +345,7 @@ menu "ESP System Settings" prompt "UART console baud rate" if ESP_CONSOLE_UART_CUSTOM depends on ESP_CONSOLE_UART default 74880 if (IDF_TARGET_ESP32C2 && XTAL_FREQ_26) + default 138240 if (IDF_TARGET_ESP32C5_BETA3_VERSION && XTAL_FREQ_48) default 115200 range 1200 4000000 if !PM_ENABLE range 1200 1000000 if PM_ENABLE diff --git a/components/esp_system/port/arch/riscv/panic_arch.c b/components/esp_system/port/arch/riscv/panic_arch.c index a4f64dbdc7f7..03336a2fec7c 100644 --- a/components/esp_system/port/arch/riscv/panic_arch.c +++ b/components/esp_system/port/arch/riscv/panic_arch.c @@ -8,7 +8,7 @@ #include "spi_flash_mmap.h" -#if CONFIG_IDF_TARGET_ESP32P4 +#if CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 #include "soc/cache_reg.h" #else #include "soc/extmem_reg.h" diff --git a/components/esp_system/port/brownout.c b/components/esp_system/port/brownout.c index 568e1044ddec..37b4fae49f4e 100644 --- a/components/esp_system/port/brownout.c +++ b/components/esp_system/port/brownout.c @@ -73,7 +73,7 @@ void esp_brownout_init(void) brownout_hal_config(&cfg); brownout_ll_intr_clear(); -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C5 // TODO: [ESP32C5] IDF-8647 // TODO IDF-6606: LP_RTC_TIMER interrupt source is shared by lp_timer and brownout detector, but lp_timer interrupt // is not used now. An interrupt allocator is needed when lp_timer intr gets supported. esp_intr_alloc(ETS_LP_RTC_TIMER_INTR_SOURCE, ESP_INTR_FLAG_IRAM, &rtc_brownout_isr_handler, NULL, NULL); diff --git a/components/esp_system/port/cpu_start.c b/components/esp_system/port/cpu_start.c index cddcdf980e39..f4167b124c4a 100644 --- a/components/esp_system/port/cpu_start.c +++ b/components/esp_system/port/cpu_start.c @@ -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 */ @@ -52,6 +52,10 @@ #include "esp32c6/rtc.h" #include "esp32c6/rom/cache.h" #include "esp_memprot.h" +#elif CONFIG_IDF_TARGET_ESP32C5 +#include "esp32c5/rtc.h" +#include "esp32c5/rom/cache.h" +#include "esp_memprot.h" #elif CONFIG_IDF_TARGET_ESP32H2 #include "esp32h2/rtc.h" #include "esp32h2/rom/cache.h" @@ -688,12 +692,12 @@ void IRAM_ATTR call_start_cpu0(void) #endif #endif -#if !CONFIG_IDF_TARGET_ESP32P4 //TODO: IDF-7529 +#if !CONFIG_IDF_TARGET_ESP32P4 && !CONFIG_IDF_TARGET_ESP32C5 //TODO: IDF-7529, IDF-8638 // Need to unhold the IOs that were hold right before entering deep sleep, which are used as wakeup pins if (rst_reas[0] == RESET_REASON_CORE_DEEP_SLEEP) { esp_deep_sleep_wakeup_io_reset(); } -#endif //#if !CONFIG_IDF_TARGET_ESP32P4 +#endif //#if !CONFIG_IDF_TARGET_ESP32P4 & !CONFIG_IDF_TARGET_ESP32C5 #if !CONFIG_APP_BUILD_TYPE_PURE_RAM_APP esp_cache_err_int_init(); diff --git a/components/esp_system/port/soc/esp32c5/CMakeLists.txt b/components/esp_system/port/soc/esp32c5/CMakeLists.txt index e69de29bb2d1..4764e7e4d497 100644 --- a/components/esp_system/port/soc/esp32c5/CMakeLists.txt +++ b/components/esp_system/port/soc/esp32c5/CMakeLists.txt @@ -0,0 +1,8 @@ +set(srcs "clk.c" + "reset_reason.c" + "system_internal.c" + "cache_err_int.c") + +add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" ${srcs}) + +target_sources(${COMPONENT_LIB} PRIVATE ${srcs}) diff --git a/components/esp_system/port/soc/esp32c5/Kconfig.cpu b/components/esp_system/port/soc/esp32c5/Kconfig.cpu index e69de29bb2d1..bd6b177c234b 100644 --- a/components/esp_system/port/soc/esp32c5/Kconfig.cpu +++ b/components/esp_system/port/soc/esp32c5/Kconfig.cpu @@ -0,0 +1,28 @@ +choice ESP_DEFAULT_CPU_FREQ_MHZ + prompt "CPU frequency" + default ESP_DEFAULT_CPU_FREQ_MHZ_40 if IDF_ENV_FPGA + default ESP_DEFAULT_CPU_FREQ_MHZ_240 + help + CPU frequency to be set on application startup. + + config ESP_DEFAULT_CPU_FREQ_MHZ_40 + bool "40 MHz" + depends on IDF_ENV_FPGA + config ESP_DEFAULT_CPU_FREQ_MHZ_80 + bool "80 MHz" + config ESP_DEFAULT_CPU_FREQ_MHZ_120 + bool "120 MHz" + config ESP_DEFAULT_CPU_FREQ_MHZ_160 + bool "160 MHz" + config ESP_DEFAULT_CPU_FREQ_MHZ_240 + bool "240 MHz" +endchoice + +config ESP_DEFAULT_CPU_FREQ_MHZ + int + default 40 if ESP_DEFAULT_CPU_FREQ_MHZ_40 + default 60 if ESP_DEFAULT_CPU_FREQ_MHZ_60 + default 80 if ESP_DEFAULT_CPU_FREQ_MHZ_80 + default 120 if ESP_DEFAULT_CPU_FREQ_MHZ_120 + default 160 if ESP_DEFAULT_CPU_FREQ_MHZ_160 + default 240 if ESP_DEFAULT_CPU_FREQ_MHZ_240 diff --git a/components/esp_system/port/soc/esp32c5/Kconfig.system b/components/esp_system/port/soc/esp32c5/Kconfig.system index e69de29bb2d1..756610417d62 100644 --- a/components/esp_system/port/soc/esp32c5/Kconfig.system +++ b/components/esp_system/port/soc/esp32c5/Kconfig.system @@ -0,0 +1,46 @@ +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 + TODO: [ESP32C5] IDF-8647 + 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 + +endmenu diff --git a/components/esp_system/port/soc/esp32c5/cache_err_int.c b/components/esp_system/port/soc/esp32c5/cache_err_int.c new file mode 100644 index 000000000000..4382ac2e7afc --- /dev/null +++ b/components/esp_system/port/soc/esp32c5/cache_err_int.c @@ -0,0 +1,76 @@ +/* + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + The cache has an interrupt that can be raised as soon as an access to a cached + region (flash) is done without the cache being enabled. We use that here + to panic the CPU, which from a debugging perspective is better than grabbing bad + data from the bus. +*/ +#include "esp_rom_sys.h" +#include "esp_attr.h" +#include "esp_log.h" +#include "esp_intr_alloc.h" +#include "soc/periph_defs.h" +#include "soc/soc.h" +#include "riscv/interrupt.h" +#include "hal/cache_ll.h" + +static const char *TAG = "CACHE_ERR"; + +const char cache_error_msg[] = "Cache access error"; + +const char *esp_cache_err_panic_string(void) +{ + const uint32_t access_err_status = cache_ll_l1_get_access_error_intr_status(0, CACHE_LL_L1_ACCESS_EVENT_MASK); + + /* Return the error string if a cache error is active */ + const char* err_str = access_err_status ? cache_error_msg : NULL; + + return err_str; +} + +bool esp_cache_err_has_active_err(void) +{ + return cache_ll_l1_get_access_error_intr_status(0, CACHE_LL_L1_ACCESS_EVENT_MASK); +} + +void esp_cache_err_int_init(void) +{ + const uint32_t core_id = 0; + + /* Disable cache interrupts if enabled. */ + ESP_INTR_DISABLE(ETS_CACHEERR_INUM); + + /** + * Bind all cache errors to ETS_CACHEERR_INUM interrupt. we will deal with + * them in handler by different types + * + * On ESP32C5 boards, the cache is a shared one but buses are still + * distinct. So, we have an bus0 and a bus1 sharing the same cache. + * This error can occur if a bus performs a request but the cache + * is disabled. + */ + esp_rom_route_intr_matrix(core_id, ETS_CACHE_INTR_SOURCE, ETS_CACHEERR_INUM); + + /* Set the type and priority to cache error interrupts. */ + esprv_intc_int_set_type(ETS_CACHEERR_INUM, INTR_TYPE_LEVEL); + esprv_intc_int_set_priority(ETS_CACHEERR_INUM, SOC_INTERRUPT_LEVEL_MEDIUM); + + ESP_DRAM_LOGV(TAG, "access error intr clr & ena mask is: 0x%x", CACHE_LL_L1_ACCESS_EVENT_MASK); + /* On the hardware side, start by clearing all the bits reponsible for cache access error */ + cache_ll_l1_clear_access_error_intr(0, CACHE_LL_L1_ACCESS_EVENT_MASK); + /* Then enable cache access error interrupts. */ + cache_ll_l1_enable_access_error_intr(0, CACHE_LL_L1_ACCESS_EVENT_MASK); + + /* Enable the interrupts for cache error. */ + ESP_INTR_ENABLE(ETS_CACHEERR_INUM); +} + +int esp_cache_err_get_cpuid(void) +{ + return 0; +} diff --git a/components/esp_system/port/soc/esp32c5/clk.c b/components/esp_system/port/soc/esp32c5/clk.c new file mode 100644 index 000000000000..37b8c59d04a2 --- /dev/null +++ b/components/esp_system/port/soc/esp32c5/clk.c @@ -0,0 +1,301 @@ +/* + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include "sdkconfig.h" +#include "esp_attr.h" +#include "esp_log.h" +#include "esp_clk_internal.h" +#include "esp32c5/rom/ets_sys.h" +#include "esp32c5/rom/uart.h" +#include "soc/soc.h" +#include "soc/rtc.h" +#include "soc/rtc_periph.h" +#include "soc/i2s_reg.h" +#include "esp_cpu.h" +#include "hal/wdt_hal.h" +#include "hal/modem_lpcon_ll.h" +#include "esp_private/esp_modem_clock.h" +#include "esp_private/periph_ctrl.h" +#include "esp_private/esp_clk.h" +#include "esp_private/esp_pmu.h" +#include "esp_rom_uart.h" +#include "esp_rom_sys.h" + +/* Number of cycles to wait from the 32k XTAL oscillator to consider it running. + * Larger values increase startup delay. Smaller values may cause false positive + * detection (i.e. oscillator runs for a few cycles and then stops). + */ +#define SLOW_CLK_CAL_CYCLES CONFIG_RTC_CLK_CAL_CYCLES + +#define MHZ (1000000) + +static void select_rtc_slow_clk(soc_rtc_slow_clk_src_t rtc_slow_clk_src); + +static const char *TAG = "clk"; + +// TODO: [ESP32C5] IDF-8642 + __attribute__((weak)) void esp_clk_init(void) +{ +#if SOC_PMU_SUPPORTED + pmu_init(); +#endif + + assert((rtc_clk_xtal_freq_get() == RTC_XTAL_FREQ_40M) || (rtc_clk_xtal_freq_get() == RTC_XTAL_FREQ_48M)); + + modem_lpcon_ll_set_pwr_tick_target(&MODEM_LPCON, rtc_clk_xtal_freq_get() - 1); + + rtc_clk_8m_enable(true); + rtc_clk_fast_src_set(SOC_RTC_FAST_CLK_SRC_RC_FAST); + +#ifdef CONFIG_BOOTLOADER_WDT_ENABLE + // WDT uses a SLOW_CLK clock source. After a function select_rtc_slow_clk a frequency of this source can changed. + // If the frequency changes from 150kHz to 32kHz, then the timeout set for the WDT will increase 4.6 times. + // Therefore, for the time of frequency change, set a new lower timeout value (1.6 sec). + // This prevents excessive delay before resetting in case the supply voltage is drawdown. + // (If frequency is changed from 150kHz to 32kHz then WDT timeout will increased to 1.6sec * 150/32 = 7.5 sec). + wdt_hal_context_t rtc_wdt_ctx = RWDT_HAL_CONTEXT_DEFAULT(); + uint32_t stage_timeout_ticks = (uint32_t)(1600ULL * rtc_clk_slow_freq_get_hz() / 1000ULL); + wdt_hal_write_protect_disable(&rtc_wdt_ctx); + wdt_hal_feed(&rtc_wdt_ctx); + //Bootloader has enabled RTC WDT until now. We're only modifying timeout, so keep the stage and timeout action the same + wdt_hal_config_stage(&rtc_wdt_ctx, WDT_STAGE0, stage_timeout_ticks, WDT_STAGE_ACTION_RESET_RTC); + wdt_hal_write_protect_enable(&rtc_wdt_ctx); +#endif + +#if defined(CONFIG_RTC_CLK_SRC_EXT_CRYS) + select_rtc_slow_clk(SOC_RTC_SLOW_CLK_SRC_XTAL32K); +#elif defined(CONFIG_RTC_CLK_SRC_EXT_OSC) + select_rtc_slow_clk(SOC_RTC_SLOW_CLK_SRC_OSC_SLOW); +#elif defined(CONFIG_RTC_CLK_SRC_INT_RC32K) + select_rtc_slow_clk(SOC_RTC_SLOW_CLK_SRC_RC32K); +#else + abort(); +#endif + +#ifdef CONFIG_BOOTLOADER_WDT_ENABLE + // After changing a frequency WDT timeout needs to be set for new frequency. + stage_timeout_ticks = (uint32_t)((uint64_t)CONFIG_BOOTLOADER_WDT_TIME_MS * rtc_clk_slow_freq_get_hz() / 1000); + wdt_hal_write_protect_disable(&rtc_wdt_ctx); + wdt_hal_feed(&rtc_wdt_ctx); + wdt_hal_config_stage(&rtc_wdt_ctx, WDT_STAGE0, stage_timeout_ticks, WDT_STAGE_ACTION_RESET_RTC); + wdt_hal_write_protect_enable(&rtc_wdt_ctx); +#endif + + rtc_cpu_freq_config_t old_config, new_config; + rtc_clk_cpu_freq_get_config(&old_config); + const uint32_t old_freq_mhz = old_config.freq_mhz; + const uint32_t new_freq_mhz = CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ; + + bool res = rtc_clk_cpu_freq_mhz_to_config(new_freq_mhz, &new_config); + assert(res); + + // Wait for UART TX to finish, otherwise some UART output will be lost + // when switching APB frequency + esp_rom_uart_tx_wait_idle(CONFIG_ESP_CONSOLE_UART_NUM); + + if (res) { + rtc_clk_cpu_freq_set_config(&new_config); + } + + // Re calculate the ccount to make time calculation correct. + esp_cpu_set_cycle_count( (uint64_t)esp_cpu_get_cycle_count() * new_freq_mhz / old_freq_mhz ); +} + +static void select_rtc_slow_clk(soc_rtc_slow_clk_src_t rtc_slow_clk_src) +{ + uint32_t cal_val = 0; + /* number of times to repeat 32k XTAL calibration + * before giving up and switching to the internal RC + */ + int retry_32k_xtal = 3; + + do { + if (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K || rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_OSC_SLOW) { + /* 32k XTAL oscillator needs to be enabled and running before it can + * be used. Hardware doesn't have a direct way of checking if the + * oscillator is running. Here we use rtc_clk_cal function to count + * the number of main XTAL cycles in the given number of 32k XTAL + * oscillator cycles. If the 32k XTAL has not started up, calibration + * will time out, returning 0. + */ + ESP_EARLY_LOGD(TAG, "waiting for 32k oscillator to start up"); + rtc_cal_sel_t cal_sel = 0; + if (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) { + rtc_clk_32k_enable(true); + cal_sel = RTC_CAL_32K_XTAL; + } else if (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_OSC_SLOW) { + rtc_clk_32k_enable_external(); + cal_sel = RTC_CAL_32K_OSC_SLOW; + } + // When SLOW_CLK_CAL_CYCLES is set to 0, clock calibration will not be performed at startup. + if (SLOW_CLK_CAL_CYCLES > 0) { + cal_val = rtc_clk_cal(cal_sel, SLOW_CLK_CAL_CYCLES); + if (cal_val == 0) { + if (retry_32k_xtal-- > 0) { + continue; + } +#if CONFIG_IDF_TARGET_ESP32C5 + ESP_EARLY_LOGW(TAG, "32 kHz clock not found, switching to internal 32 kHz oscillator"); + rtc_slow_clk_src = SOC_RTC_SLOW_CLK_SRC_RC32K; +#else + ESP_EARLY_LOGW(TAG, "32 kHz clock not found, switching to internal 150 kHz oscillator"); + rtc_slow_clk_src = SOC_RTC_SLOW_CLK_SRC_RC_SLOW; +#endif + } + } + } else if (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC32K) { + rtc_clk_rc32k_enable(true); + } + rtc_clk_slow_src_set(rtc_slow_clk_src); + + if (SLOW_CLK_CAL_CYCLES > 0) { + /* TODO: 32k XTAL oscillator has some frequency drift at startup. + * Improve calibration routine to wait until the frequency is stable. + */ + cal_val = rtc_clk_cal(RTC_CAL_RTC_MUX, SLOW_CLK_CAL_CYCLES); + } else { + const uint64_t cal_dividend = (1ULL << RTC_CLK_CAL_FRACT) * 1000000ULL; + cal_val = (uint32_t) (cal_dividend / rtc_clk_slow_freq_get_hz()); + } + } while (cal_val == 0); + ESP_EARLY_LOGD(TAG, "RTC_SLOW_CLK calibration value: %d", cal_val); + esp_clk_slowclk_cal_set(cal_val); +} + +void rtc_clk_select_rtc_slow_clk(void) +{ + select_rtc_slow_clk(SOC_RTC_SLOW_CLK_SRC_XTAL32K); +} + +/* This function is not exposed as an API at this point. + * All peripheral clocks are default enabled after chip is powered on. + * This function disables some peripheral clocks when cpu starts. + * These peripheral clocks are enabled when the peripherals are initialized + * and disabled when they are de-initialized. + */ +__attribute__((weak)) void esp_perip_clk_init(void) +{ +#if 0 // TODO: [ESP32C5] IDF-8844 + /* During system initialization, the low-power clock source of the modem + * (WiFi, BLE or Coexist) follows the configuration of the slow clock source + * of the system. If the WiFi, BLE or Coexist module needs a higher + * precision sleep clock (for example, the BLE needs to use the main XTAL + * oscillator (40 MHz) to provide the clock during the sleep process in some + * scenarios), the module needs to switch to the required clock source by + * itself. */ //TODO - WIFI-5233 + soc_rtc_slow_clk_src_t rtc_slow_clk_src = rtc_clk_slow_src_get(); + modem_clock_lpclk_src_t modem_lpclk_src = (modem_clock_lpclk_src_t) ( \ + (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) ? MODEM_CLOCK_LPCLK_SRC_XTAL32K \ + : (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC32K) ? MODEM_CLOCK_LPCLK_SRC_RC32K \ + : (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_OSC_SLOW) ? MODEM_CLOCK_LPCLK_SRC_EXT32K \ + : MODEM_CLOCK_LPCLK_SRC_RC32K); + + modem_clock_select_lp_clock_source(PERIPH_WIFI_MODULE, modem_lpclk_src, 0); +#endif + + ESP_EARLY_LOGW(TAG, "esp_perip_clk_init() has not been implemented yet"); +#if 0 // TODO: [ESP32C5] IDF-8844 + uint32_t common_perip_clk, hwcrypto_perip_clk, wifi_bt_sdio_clk = 0; + uint32_t common_perip_clk1 = 0; + + soc_reset_reason_t rst_reason = esp_rom_get_reset_reason(0); + + /* For reason that only reset CPU, do not disable the clocks + * that have been enabled before reset. + */ + if (rst_reason == RESET_REASON_CPU0_MWDT0 || rst_reason == RESET_REASON_CPU0_SW || + rst_reason == RESET_REASON_CPU0_RTC_WDT || rst_reason == RESET_REASON_CPU0_MWDT1) { + common_perip_clk = ~READ_PERI_REG(SYSTEM_PERIP_CLK_EN0_REG); + hwcrypto_perip_clk = ~READ_PERI_REG(SYSTEM_PERIP_CLK_EN1_REG); + wifi_bt_sdio_clk = ~READ_PERI_REG(SYSTEM_WIFI_CLK_EN_REG); + } else { + common_perip_clk = SYSTEM_WDG_CLK_EN | + SYSTEM_I2S0_CLK_EN | +#if CONFIG_ESP_CONSOLE_UART_NUM != 0 + SYSTEM_UART_CLK_EN | +#endif +#if CONFIG_ESP_CONSOLE_UART_NUM != 1 + SYSTEM_UART1_CLK_EN | +#endif + SYSTEM_SPI2_CLK_EN | + SYSTEM_I2C_EXT0_CLK_EN | + SYSTEM_UHCI0_CLK_EN | + SYSTEM_RMT_CLK_EN | + SYSTEM_LEDC_CLK_EN | + SYSTEM_TIMERGROUP1_CLK_EN | + SYSTEM_SPI3_CLK_EN | + SYSTEM_SPI4_CLK_EN | + SYSTEM_TWAI_CLK_EN | + SYSTEM_I2S1_CLK_EN | + SYSTEM_SPI2_DMA_CLK_EN | + SYSTEM_SPI3_DMA_CLK_EN; + + common_perip_clk1 = 0; + hwcrypto_perip_clk = SYSTEM_CRYPTO_AES_CLK_EN | + SYSTEM_CRYPTO_SHA_CLK_EN | + SYSTEM_CRYPTO_RSA_CLK_EN; + wifi_bt_sdio_clk = SYSTEM_WIFI_CLK_WIFI_EN | + SYSTEM_WIFI_CLK_BT_EN_M | + SYSTEM_WIFI_CLK_UNUSED_BIT5 | + SYSTEM_WIFI_CLK_UNUSED_BIT12; + } + + //Reset the communication peripherals like I2C, SPI, UART, I2S and bring them to known state. + common_perip_clk |= SYSTEM_I2S0_CLK_EN | +#if CONFIG_ESP_CONSOLE_UART_NUM != 0 + SYSTEM_UART_CLK_EN | +#endif +#if CONFIG_ESP_CONSOLE_UART_NUM != 1 + SYSTEM_UART1_CLK_EN | +#endif + SYSTEM_SPI2_CLK_EN | + SYSTEM_I2C_EXT0_CLK_EN | + SYSTEM_UHCI0_CLK_EN | + SYSTEM_RMT_CLK_EN | + SYSTEM_UHCI1_CLK_EN | + SYSTEM_SPI3_CLK_EN | + SYSTEM_SPI4_CLK_EN | + SYSTEM_I2C_EXT1_CLK_EN | + SYSTEM_I2S1_CLK_EN | + SYSTEM_SPI2_DMA_CLK_EN | + SYSTEM_SPI3_DMA_CLK_EN; + common_perip_clk1 = 0; + + /* Change I2S clock to audio PLL first. Because if I2S uses 160MHz clock, + * the current is not reduced when disable I2S clock. + */ + // TOCK(check replacement) + // REG_SET_FIELD(I2S_CLKM_CONF_REG(0), I2S_CLK_SEL, I2S_CLK_AUDIO_PLL); + // REG_SET_FIELD(I2S_CLKM_CONF_REG(1), I2S_CLK_SEL, I2S_CLK_AUDIO_PLL); + + /* Disable some peripheral clocks. */ + CLEAR_PERI_REG_MASK(SYSTEM_PERIP_CLK_EN0_REG, common_perip_clk); + SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN0_REG, common_perip_clk); + + CLEAR_PERI_REG_MASK(SYSTEM_PERIP_CLK_EN1_REG, common_perip_clk1); + SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN1_REG, common_perip_clk1); + + /* Disable hardware crypto clocks. */ + CLEAR_PERI_REG_MASK(SYSTEM_PERIP_CLK_EN1_REG, hwcrypto_perip_clk); + SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN1_REG, hwcrypto_perip_clk); + + /* Disable WiFi/BT/SDIO clocks. */ + CLEAR_PERI_REG_MASK(SYSTEM_WIFI_CLK_EN_REG, wifi_bt_sdio_clk); + SET_PERI_REG_MASK(SYSTEM_WIFI_CLK_EN_REG, SYSTEM_WIFI_CLK_EN); + + /* Set WiFi light sleep clock source to RTC slow clock */ + REG_SET_FIELD(SYSTEM_BT_LPCK_DIV_INT_REG, SYSTEM_BT_LPCK_DIV_NUM, 0); + CLEAR_PERI_REG_MASK(SYSTEM_BT_LPCK_DIV_FRAC_REG, SYSTEM_LPCLK_SEL_8M); + SET_PERI_REG_MASK(SYSTEM_BT_LPCK_DIV_FRAC_REG, SYSTEM_LPCLK_SEL_RTC_SLOW); + + /* Enable RNG clock. */ + periph_module_enable(PERIPH_RNG_MODULE); +#endif +} diff --git a/components/esp_system/port/soc/esp32c5/reset_reason.c b/components/esp_system/port/soc/esp32c5/reset_reason.c new file mode 100644 index 000000000000..1f9402586b60 --- /dev/null +++ b/components/esp_system/port/soc/esp32c5/reset_reason.c @@ -0,0 +1,116 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp_system.h" +#include "esp_rom_sys.h" +#include "esp_private/system_internal.h" +#include "soc/rtc_periph.h" +#include "esp32c5/rom/rtc.h" + +static void esp_reset_reason_clear_hint(void); + +static esp_reset_reason_t s_reset_reason; + +// TODO: [ESP32C5] IDF-8660 + +static esp_reset_reason_t get_reset_reason(soc_reset_reason_t rtc_reset_reason, esp_reset_reason_t reset_reason_hint) +{ + switch (rtc_reset_reason) { + case RESET_REASON_CHIP_POWER_ON: + return ESP_RST_POWERON; + + case RESET_REASON_CPU0_SW: + case RESET_REASON_CORE_SW: + if (reset_reason_hint == ESP_RST_PANIC || + reset_reason_hint == ESP_RST_BROWNOUT || + reset_reason_hint == ESP_RST_TASK_WDT || + reset_reason_hint == ESP_RST_INT_WDT) { + return reset_reason_hint; + } + return ESP_RST_SW; + + case RESET_REASON_CORE_DEEP_SLEEP: + return ESP_RST_DEEPSLEEP; + + case RESET_REASON_CORE_MWDT0: + return ESP_RST_TASK_WDT; + + case RESET_REASON_CORE_MWDT1: + return ESP_RST_INT_WDT; + + case RESET_REASON_CORE_RTC_WDT: + case RESET_REASON_SYS_RTC_WDT: + case RESET_REASON_SYS_SUPER_WDT: + case RESET_REASON_CPU0_RTC_WDT: + case RESET_REASON_CPU0_MWDT0: + case RESET_REASON_CPU0_MWDT1: + return ESP_RST_WDT; + + case RESET_REASON_SYS_BROWN_OUT: + return ESP_RST_BROWNOUT; + + case RESET_REASON_CORE_USB_UART: + case RESET_REASON_CORE_USB_JTAG: + return ESP_RST_USB; + + default: + return ESP_RST_UNKNOWN; + } +} + +static void __attribute__((constructor)) esp_reset_reason_init(void) +{ + esp_reset_reason_t hint = esp_reset_reason_get_hint(); + s_reset_reason = get_reset_reason(esp_rom_get_reset_reason(PRO_CPU_NUM), hint); + if (hint != ESP_RST_UNKNOWN) { + esp_reset_reason_clear_hint(); + } +} + +esp_reset_reason_t esp_reset_reason(void) +{ + return s_reset_reason; +} + +/* Reset reason hint is stored in RTC_RESET_CAUSE_REG, a.k.a. RTC_CNTL_STORE6_REG, + * a.k.a. RTC_ENTRY_ADDR_REG. It is safe to use this register both for the + * deep sleep wake stub entry address and for reset reason hint, since wake stub + * is only used for deep sleep reset, and in this case the reason provided by + * esp_rom_get_reset_reason is unambiguous. + * + * Same layout is used as for RTC_APB_FREQ_REG (a.k.a. RTC_CNTL_STORE5_REG): + * the value is replicated in low and high half-words. In addition to that, + * MSB is set to 1, which doesn't happen when RTC_CNTL_STORE6_REG contains + * deep sleep wake stub address. + */ + +#define RST_REASON_BIT 0x80000000 +#define RST_REASON_MASK 0x7FFF +#define RST_REASON_SHIFT 16 + +/* in IRAM, can be called from panic handler */ +void IRAM_ATTR esp_reset_reason_set_hint(esp_reset_reason_t hint) +{ + assert((hint & (~RST_REASON_MASK)) == 0); + uint32_t val = hint | (hint << RST_REASON_SHIFT) | RST_REASON_BIT; + REG_WRITE(RTC_RESET_CAUSE_REG, val); +} + +/* in IRAM, can be called from panic handler */ +esp_reset_reason_t esp_reset_reason_get_hint(void) +{ + uint32_t reset_reason_hint = REG_READ(RTC_RESET_CAUSE_REG); + uint32_t high = (reset_reason_hint >> RST_REASON_SHIFT) & RST_REASON_MASK; + uint32_t low = reset_reason_hint & RST_REASON_MASK; + if ((reset_reason_hint & RST_REASON_BIT) == 0 || high != low) { + return ESP_RST_UNKNOWN; + } + return (esp_reset_reason_t) low; +} +static inline void esp_reset_reason_clear_hint(void) +{ + REG_WRITE(RTC_RESET_CAUSE_REG, 0); +} diff --git a/components/esp_system/port/soc/esp32c5/system_internal.c b/components/esp_system/port/soc/esp32c5/system_internal.c new file mode 100644 index 000000000000..ea56bfead825 --- /dev/null +++ b/components/esp_system/port/soc/esp32c5/system_internal.c @@ -0,0 +1,122 @@ +/* + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "sdkconfig.h" +#include "esp_system.h" +#include "esp_private/system_internal.h" +#include "esp_attr.h" +#include "esp_log.h" +#include "esp_rom_sys.h" +#include "riscv/rv_utils.h" +#include "esp_rom_uart.h" +#include "soc/gpio_reg.h" +#include "esp_cpu.h" +#include "soc/rtc.h" +#include "esp_private/rtc_clk.h" +#include "soc/rtc_periph.h" +#include "soc/uart_reg.h" +#include "hal/clk_tree_ll.h" +#include "hal/wdt_hal.h" +#include "hal/modem_syscon_ll.h" +#include "hal/modem_lpcon_ll.h" +#include "esp_private/cache_err_int.h" + +#include "esp32c5/rom/cache.h" +#include "esp32c5/rom/rtc.h" +#include "soc/pcr_reg.h" + +void IRAM_ATTR esp_system_reset_modules_on_exit(void) +{ + // Flush any data left in UART FIFOs before reset the UART peripheral + esp_rom_uart_tx_wait_idle(0); + esp_rom_uart_tx_wait_idle(1); + + modem_syscon_ll_reset_all(&MODEM_SYSCON); + modem_lpcon_ll_reset_all(&MODEM_LPCON); + + // Set SPI Flash Freq to 40M + clk_ll_mspi_fast_sel_clk(MSPI_CLK_SRC_XTAL); + clk_ll_mspi_fast_set_divider(1); + + // Set Peripheral clk rst + SET_PERI_REG_MASK(PCR_MSPI_CLK_CONF_REG, PCR_MSPI_AXI_RST_EN); + SET_PERI_REG_MASK(PCR_MSPI_CONF_REG, PCR_MSPI_RST_EN); + SET_PERI_REG_MASK(PCR_UART0_CONF_REG, PCR_UART0_RST_EN); + SET_PERI_REG_MASK(PCR_UART1_CONF_REG, PCR_UART1_RST_EN); + SET_PERI_REG_MASK(PCR_SYSTIMER_CONF_REG, PCR_SYSTIMER_RST_EN); + SET_PERI_REG_MASK(PCR_GDMA_CONF_REG, PCR_GDMA_RST_EN); + SET_PERI_REG_MASK(PCR_SDIO_SLAVE_CONF_REG, PCR_SDIO_SLAVE_RST_EN); + SET_PERI_REG_MASK(PCR_MODEM_CONF_REG, PCR_MODEM_RST_EN); + SET_PERI_REG_MASK(PCR_PWM_CONF_REG, PCR_PWM_RST_EN); + + // Clear Peripheral clk rst + CLEAR_PERI_REG_MASK(PCR_MSPI_CLK_CONF_REG, PCR_MSPI_AXI_RST_EN); + CLEAR_PERI_REG_MASK(PCR_MSPI_CONF_REG, PCR_MSPI_RST_EN); + CLEAR_PERI_REG_MASK(PCR_UART0_CONF_REG, PCR_UART0_RST_EN); + CLEAR_PERI_REG_MASK(PCR_UART1_CONF_REG, PCR_UART1_RST_EN); + CLEAR_PERI_REG_MASK(PCR_SYSTIMER_CONF_REG, PCR_SYSTIMER_RST_EN); + CLEAR_PERI_REG_MASK(PCR_GDMA_CONF_REG, PCR_GDMA_RST_EN); + CLEAR_PERI_REG_MASK(PCR_SDIO_SLAVE_CONF_REG, PCR_SDIO_SLAVE_RST_EN); + CLEAR_PERI_REG_MASK(PCR_MODEM_CONF_REG, PCR_MODEM_RST_EN); + CLEAR_PERI_REG_MASK(PCR_PWM_CONF_REG, PCR_PWM_RST_EN); +} + +/* "inner" restart function for after RTOS, interrupts & anything else on this + * core are already stopped. Stalls other core, resets hardware, + * triggers restart. +*/ +void IRAM_ATTR esp_restart_noos(void) +{ + // Disable interrupts + rv_utils_intr_global_disable(); + // Enable RTC watchdog for 1 second + wdt_hal_context_t rtc_wdt_ctx; + wdt_hal_init(&rtc_wdt_ctx, WDT_RWDT, 0, false); + uint32_t stage_timeout_ticks = (uint32_t)(1000ULL * rtc_clk_slow_freq_get_hz() / 1000ULL); + wdt_hal_write_protect_disable(&rtc_wdt_ctx); + wdt_hal_config_stage(&rtc_wdt_ctx, WDT_STAGE0, stage_timeout_ticks, WDT_STAGE_ACTION_RESET_SYSTEM); + wdt_hal_config_stage(&rtc_wdt_ctx, WDT_STAGE1, stage_timeout_ticks, WDT_STAGE_ACTION_RESET_RTC); + //Enable flash boot mode so that flash booting after restart is protected by the RTC WDT. + wdt_hal_set_flashboot_en(&rtc_wdt_ctx, true); + wdt_hal_write_protect_enable(&rtc_wdt_ctx); + + // C5 is a single core SoC, no need to reset and stall the other CPU + + // Disable TG0/TG1 watchdogs + wdt_hal_context_t wdt0_context = {.inst = WDT_MWDT0, .mwdt_dev = &TIMERG0}; + wdt_hal_write_protect_disable(&wdt0_context); + wdt_hal_disable(&wdt0_context); + wdt_hal_write_protect_enable(&wdt0_context); + + wdt_hal_context_t wdt1_context = {.inst = WDT_MWDT1, .mwdt_dev = &TIMERG1}; + wdt_hal_write_protect_disable(&wdt1_context); + wdt_hal_disable(&wdt1_context); + wdt_hal_write_protect_enable(&wdt1_context); + + // Disable cache + Cache_Disable_ICache(); + + // Reset wifi/bluetooth/ethernet/sdio (bb/mac) + // Moved to module internal + // SET_PERI_REG_MASK(SYSTEM_CORE_RST_EN_REG, + // SYSTEM_SDIO_RST | // SDIO_HINF_HINF_SDIO_RST? + // SYSTEM_EMAC_RST | SYSTEM_MACPWR_RST | // TODO: IDF-5325 (ethernet) + // REG_WRITE(SYSTEM_CORE_RST_EN_REG, 0); + + esp_system_reset_modules_on_exit(); + + // Set CPU back to XTAL source, same as hard reset, but keep BBPLL on so that USB Serial JTAG can log at 1st stage bootloader. +#if !CONFIG_IDF_ENV_FPGA + rtc_clk_cpu_set_to_default_config(); +#endif + + // Reset PRO CPU + esp_rom_software_reset_cpu(0); + while (true) { + ; + } +} diff --git a/components/esp_system/port/soc/esp32p4/Kconfig.cpu b/components/esp_system/port/soc/esp32p4/Kconfig.cpu index 23782a074151..18ad8025983f 100644 --- a/components/esp_system/port/soc/esp32p4/Kconfig.cpu +++ b/components/esp_system/port/soc/esp32p4/Kconfig.cpu @@ -1,25 +1,18 @@ -# TODO: IDF-7526 , Check all this file to update the frequency choice ESP_DEFAULT_CPU_FREQ_MHZ prompt "CPU frequency" default ESP_DEFAULT_CPU_FREQ_MHZ_40 if IDF_ENV_FPGA || ESP_BRINGUP_BYPASS_CPU_CLK_SETTING - default ESP_DEFAULT_CPU_FREQ_MHZ_160 + default ESP_DEFAULT_CPU_FREQ_MHZ_360 help CPU frequency to be set on application startup. config ESP_DEFAULT_CPU_FREQ_MHZ_40 bool "40 MHz" depends on IDF_ENV_FPGA || ESP_BRINGUP_BYPASS_CPU_CLK_SETTING - config ESP_DEFAULT_CPU_FREQ_MHZ_80 - bool "80 MHz" - config ESP_DEFAULT_CPU_FREQ_MHZ_120 - bool "120 MHz" - config ESP_DEFAULT_CPU_FREQ_MHZ_160 - bool "160 MHz" + config ESP_DEFAULT_CPU_FREQ_MHZ_360 + bool "360 MHz" endchoice config ESP_DEFAULT_CPU_FREQ_MHZ int default 40 if ESP_DEFAULT_CPU_FREQ_MHZ_40 - default 80 if ESP_DEFAULT_CPU_FREQ_MHZ_80 - default 120 if ESP_DEFAULT_CPU_FREQ_MHZ_120 - default 160 if ESP_DEFAULT_CPU_FREQ_MHZ_160 + default 360 if ESP_DEFAULT_CPU_FREQ_MHZ_360 diff --git a/components/esp_system/port/soc/esp32p4/clk.c b/components/esp_system/port/soc/esp32p4/clk.c index 86c1ab2766fc..6f90f7c51c55 100644 --- a/components/esp_system/port/soc/esp32p4/clk.c +++ b/components/esp_system/port/soc/esp32p4/clk.c @@ -68,8 +68,6 @@ static const char *TAG = "clk"; #if defined(CONFIG_RTC_CLK_SRC_EXT_CRYS) select_rtc_slow_clk(SOC_RTC_SLOW_CLK_SRC_XTAL32K); -#elif defined(CONFIG_RTC_CLK_SRC_EXT_OSC) - select_rtc_slow_clk(SOC_RTC_SLOW_CLK_SRC_OSC_SLOW); #elif defined(CONFIG_RTC_CLK_SRC_INT_RC32K) select_rtc_slow_clk(SOC_RTC_SLOW_CLK_SRC_RC32K); #else @@ -114,7 +112,7 @@ static void select_rtc_slow_clk(soc_rtc_slow_clk_src_t rtc_slow_clk_src) int retry_32k_xtal = 3; do { - if (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K || rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_OSC_SLOW) { + if (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) { /* 32k XTAL oscillator needs to be enabled and running before it can * be used. Hardware doesn't have a direct way of checking if the * oscillator is running. Here we use rtc_clk_cal function to count @@ -127,9 +125,6 @@ static void select_rtc_slow_clk(soc_rtc_slow_clk_src_t rtc_slow_clk_src) if (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) { rtc_clk_32k_enable(true); cal_sel = RTC_CAL_32K_XTAL; - } else if (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_OSC_SLOW) { - rtc_clk_32k_enable_external(); - cal_sel = RTC_CAL_32K_OSC_SLOW; } // When SLOW_CLK_CAL_CYCLES is set to 0, clock calibration will not be performed at startup. if (SLOW_CLK_CAL_CYCLES > 0) { diff --git a/components/esp_system/port/soc/esp32p4/system_internal.c b/components/esp_system/port/soc/esp32p4/system_internal.c index be53f1a61ee7..8aaa97ce475f 100644 --- a/components/esp_system/port/soc/esp32p4/system_internal.c +++ b/components/esp_system/port/soc/esp32p4/system_internal.c @@ -106,9 +106,9 @@ void IRAM_ATTR esp_restart_noos(void) esp_system_reset_modules_on_exit(); - // Set CPU back to XTAL source, no PLL, same as hard reset + // Set CPU back to XTAL source (and MEM_CLK, APB_CLK back to power-on reset frequencies), same as hard reset, keep CPLL on. #if !CONFIG_IDF_ENV_FPGA - rtc_clk_cpu_freq_set_xtal(); + rtc_clk_cpu_set_to_default_config(); #endif #if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE diff --git a/components/esp_system/system_time.c b/components/esp_system/system_time.c index f7122399485a..668ddeb88ca1 100644 --- a/components/esp_system/system_time.c +++ b/components/esp_system/system_time.c @@ -29,6 +29,8 @@ #include "esp32h2/rtc.h" #elif CONFIG_IDF_TARGET_ESP32P4 #include "esp32p4/rtc.h" +#elif CONFIG_IDF_TARGET_ESP32C5 +#include "esp32c5/rtc.h" #endif #include "esp_private/startup_internal.h" diff --git a/components/esp_system/test_apps/.build-test-rules.yml b/components/esp_system/test_apps/.build-test-rules.yml index 1eebf6ca171e..8f79155fb338 100644 --- a/components/esp_system/test_apps/.build-test-rules.yml +++ b/components/esp_system/test_apps/.build-test-rules.yml @@ -3,6 +3,10 @@ components/esp_system/test_apps/esp_system_unity_tests: disable: - if: CONFIG_NAME == "psram" and SOC_SPIRAM_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: test not pass, should be re-enable # TODO: IDF-8978 components/esp_system/test_apps/linux_apis: enable: diff --git a/components/esp_system/test_apps/esp_system_unity_tests/pytest_esp_system_unity_tests.py b/components/esp_system/test_apps/esp_system_unity_tests/pytest_esp_system_unity_tests.py index 4d094eb313ca..a0d329287fd5 100644 --- a/components/esp_system/test_apps/esp_system_unity_tests/pytest_esp_system_unity_tests.py +++ b/components/esp_system/test_apps/esp_system_unity_tests/pytest_esp_system_unity_tests.py @@ -5,6 +5,7 @@ from pytest_embedded import Dut +@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='esp32p4 support TBD') # TODO: IDF-8978 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -19,6 +20,7 @@ def test_esp_system(dut: Dut) -> None: dut.run_all_single_board_cases() +@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='esp32p4 support TBD') # TODO: IDF-8978 @pytest.mark.generic @pytest.mark.parametrize( 'config', diff --git a/components/esp_timer/src/ets_timer_legacy.c b/components/esp_timer/src/ets_timer_legacy.c index dc80901a4380..a37b88f253bb 100644 --- a/components/esp_timer/src/ets_timer_legacy.c +++ b/components/esp_timer/src/ets_timer_legacy.c @@ -34,6 +34,8 @@ #include "esp32c2/rom/ets_sys.h" #elif CONFIG_IDF_TARGET_ESP32C6 #include "esp32c6/rom/ets_sys.h" +#elif CONFIG_IDF_TARGET_ESP32C5 +#include "esp32c5/rom/ets_sys.h" #elif CONFIG_IDF_TARGET_ESP32H2 #include "esp32h2/rom/ets_sys.h" #elif CONFIG_IDF_TARGET_ESP32P4 diff --git a/components/esp_timer/src/system_time.c b/components/esp_timer/src/system_time.c index 253ea56c7643..0cd4e118f7db 100644 --- a/components/esp_timer/src/system_time.c +++ b/components/esp_timer/src/system_time.c @@ -29,6 +29,8 @@ #include "esp32c2/rtc.h" #elif CONFIG_IDF_TARGET_ESP32C6 #include "esp32c6/rtc.h" +#elif CONFIG_IDF_TARGET_ESP32C5 +#include "esp32c5/rtc.h" #elif CONFIG_IDF_TARGET_ESP32H2 #include "esp32h2/rtc.h" #elif CONFIG_IDF_TARGET_ESP32P4 diff --git a/components/esp_timer/test_apps/pytest_esp_timer_ut.py b/components/esp_timer/test_apps/pytest_esp_timer_ut.py index 83afa3638841..fe83f58d4f6e 100644 --- a/components/esp_timer/test_apps/pytest_esp_timer_ut.py +++ b/components/esp_timer/test_apps/pytest_esp_timer_ut.py @@ -1,12 +1,13 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded import Dut +# TODO: IDF-8979 CONFIGS = [ - pytest.param('general', marks=[pytest.mark.supported_targets, pytest.mark.temp_skip_ci(targets=['esp32h2'], reason='h2 support TBD')]), - pytest.param('release', marks=[pytest.mark.supported_targets, pytest.mark.temp_skip_ci(targets=['esp32h2'], reason='h2 support TBD')]), + pytest.param('general', marks=[pytest.mark.supported_targets, pytest.mark.temp_skip_ci(targets=['esp32h2', 'esp32p4'], reason='h2/p4 support TBD')]), + pytest.param('release', marks=[pytest.mark.supported_targets, pytest.mark.temp_skip_ci(targets=['esp32h2', 'esp32p4'], reason='h2/p4 support TBD')]), pytest.param('single_core', marks=[pytest.mark.esp32]), pytest.param('freertos_compliance', marks=[pytest.mark.esp32]), pytest.param('isr_dispatch_esp32', marks=[pytest.mark.esp32]), diff --git a/components/esp_wifi/lib b/components/esp_wifi/lib index aa0de74487b6..f0f992e62223 160000 --- a/components/esp_wifi/lib +++ b/components/esp_wifi/lib @@ -1 +1 @@ -Subproject commit aa0de74487b6f753b433e1d6f107fc3b7e505f16 +Subproject commit f0f992e62223596f226d3e43d871821247d4df55 diff --git a/components/esp_wifi/src/wifi_init.c b/components/esp_wifi/src/wifi_init.c index 73b11acf9abf..effe3f52f8c1 100644 --- a/components/esp_wifi/src/wifi_init.c +++ b/components/esp_wifi/src/wifi_init.c @@ -190,6 +190,7 @@ static void esp_wifi_config_info(void) #endif #ifdef CONFIG_ESP_NETIF_TCPIP_LWIP + ESP_LOGI(TAG, "accept mbox: %d", CONFIG_LWIP_TCP_ACCEPTMBOX_SIZE); ESP_LOGI(TAG, "tcpip mbox: %d", CONFIG_LWIP_TCPIP_RECVMBOX_SIZE); ESP_LOGI(TAG, "udp mbox: %d", CONFIG_LWIP_UDP_RECVMBOX_SIZE); ESP_LOGI(TAG, "tcp mbox: %d", CONFIG_LWIP_TCP_RECVMBOX_SIZE); diff --git a/components/fatfs/host_test/.build-test-rules.yml b/components/fatfs/host_test/.build-test-rules.yml index 668da2d32030..17714e9c87dc 100644 --- a/components/fatfs/host_test/.build-test-rules.yml +++ b/components/fatfs/host_test/.build-test-rules.yml @@ -1,3 +1,7 @@ components/fatfs/host_test: enable: - if: IDF_TARGET == "linux" + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: test not pass, should be re-enable # TODO: IDF-8980 diff --git a/components/fatfs/test_apps/.build-test-rules.yml b/components/fatfs/test_apps/.build-test-rules.yml index d82778045190..0a1970ea43a4 100644 --- a/components/fatfs/test_apps/.build-test-rules.yml +++ b/components/fatfs/test_apps/.build-test-rules.yml @@ -1,11 +1,42 @@ # Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps -components/fatfs/test_apps/sdcard: +components/fatfs/test_apps/flash_ro: disable_test: - - if: IDF_TARGET in ["esp32s3", "esp32c2", "esp32c6", "esp32h2"] - temporary: true - reason: No sdspi runners for these targets + - if: IDF_TARGET not in ["esp32", "esp32c3"] + reason: only one target per arch needed + + depends_components: + - esp_partition + - spi_flash + - fatfs + - vfs + +components/fatfs/test_apps/flash_wl: + disable_test: + - if: IDF_TARGET not in ["esp32", "esp32c3"] + reason: only one target per arch needed + + depends_components: + - esp_partition + - spi_flash + - fatfs + - vfs + - wear_leveling + +components/fatfs/test_apps/sdcard: disable: - if: IDF_TARGET == "esp32p4" temporary: true reason: target esp32p4 is not supported yet # TODO: IDF-7501 + + disable_test: + - if: IDF_TARGET not in ["esp32", "esp32c3"] + temporary: true + reason: lack of runners + + depends_components: + - esp_driver_sdmmc + - esp_driver_spi + - sdmmc + - fatfs + - vfs diff --git a/components/fatfs/test_apps/flash_ro/pytest_fatfs_flash_ro.py b/components/fatfs/test_apps/flash_ro/pytest_fatfs_flash_ro.py index eda296ef2e0d..77912fddda10 100644 --- a/components/fatfs/test_apps/flash_ro/pytest_fatfs_flash_ro.py +++ b/components/fatfs/test_apps/flash_ro/pytest_fatfs_flash_ro.py @@ -5,8 +5,8 @@ from pytest_embedded import Dut -@pytest.mark.supported_targets -@pytest.mark.generic +@pytest.mark.esp32 +@pytest.mark.esp32c3 def test_fatfs_flash_ro(dut: Dut) -> None: dut.expect_exact('Press ENTER to see the list of tests') dut.write('') diff --git a/components/fatfs/test_apps/flash_wl/pytest_fatfs_flash_wl.py b/components/fatfs/test_apps/flash_wl/pytest_fatfs_flash_wl.py index af8c5db6d482..da56a45d4c90 100644 --- a/components/fatfs/test_apps/flash_wl/pytest_fatfs_flash_wl.py +++ b/components/fatfs/test_apps/flash_wl/pytest_fatfs_flash_wl.py @@ -5,8 +5,8 @@ from pytest_embedded import Dut -@pytest.mark.supported_targets -@pytest.mark.generic +@pytest.mark.esp32 +@pytest.mark.esp32c3 @pytest.mark.parametrize( 'config', [ @@ -23,7 +23,7 @@ def test_fatfs_flash_wl_generic(dut: Dut) -> None: dut.expect_unity_test_output(timeout=180) -@pytest.mark.supported_targets +@pytest.mark.esp32 @pytest.mark.psram @pytest.mark.parametrize( 'config', diff --git a/components/fatfs/test_apps/sdcard/pytest_fatfs_sdcard.py b/components/fatfs/test_apps/sdcard/pytest_fatfs_sdcard.py index fe720a02516b..8088f7a7af37 100644 --- a/components/fatfs/test_apps/sdcard/pytest_fatfs_sdcard.py +++ b/components/fatfs/test_apps/sdcard/pytest_fatfs_sdcard.py @@ -6,6 +6,7 @@ @pytest.mark.esp32 +@pytest.mark.esp32c3 @pytest.mark.sdcard_sdmode @pytest.mark.parametrize( 'config', @@ -23,7 +24,6 @@ def test_fatfs_sdcard_generic_sdmmc(dut: Dut) -> None: @pytest.mark.esp32 -@pytest.mark.esp32s2 @pytest.mark.esp32c3 @pytest.mark.sdcard_spimode @pytest.mark.parametrize( diff --git a/components/freertos/test_apps/.build-test-rules.yml b/components/freertos/test_apps/.build-test-rules.yml index bf8ffe8b5b1a..70737f731f09 100644 --- a/components/freertos/test_apps/.build-test-rules.yml +++ b/components/freertos/test_apps/.build-test-rules.yml @@ -5,6 +5,10 @@ components/freertos/test_apps/freertos: - if: CONFIG_NAME == "smp" and IDF_TARGET == "esp32p4" temporary: true reason: target(s) not supported yet + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: test not pass, should be re-enable # IDF-8981 components/freertos/test_apps/orig_inc_path: enable: diff --git a/components/freertos/test_apps/freertos/pytest_freertos.py b/components/freertos/test_apps/freertos/pytest_freertos.py index a2e81f14f22c..488595c1712f 100644 --- a/components/freertos/test_apps/freertos/pytest_freertos.py +++ b/components/freertos/test_apps/freertos/pytest_freertos.py @@ -1,14 +1,15 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import pytest from pytest_embedded import Dut +# TODO: IDF-8981 CONFIGS = [ - pytest.param('default', marks=[pytest.mark.supported_targets, pytest.mark.temp_skip_ci(targets=['esp32h2'], reason='test failed')]), - pytest.param('freertos_options', marks=[pytest.mark.supported_targets, pytest.mark.temp_skip_ci(targets=['esp32h2'], reason='test failed')]), + pytest.param('default', marks=[pytest.mark.supported_targets, pytest.mark.temp_skip_ci(targets=['esp32h2', 'esp32p4'], reason='test failed')]), + pytest.param('freertos_options', marks=[pytest.mark.supported_targets, pytest.mark.temp_skip_ci(targets=['esp32h2', 'esp32p4'], reason='test failed')]), pytest.param('psram', marks=[pytest.mark.esp32]), - pytest.param('release', marks=[pytest.mark.supported_targets]), + pytest.param('release', marks=[pytest.mark.supported_targets, pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='test failed')]), pytest.param('single_core', marks=[pytest.mark.esp32]), pytest.param('smp', marks=[pytest.mark.supported_targets, pytest.mark.temp_skip_ci(targets=['esp32h2', 'esp32p4'], reason='test failed/TBD IDF-8113')]), ] @@ -20,6 +21,7 @@ def test_freertos(dut: Dut) -> None: dut.run_all_single_board_cases() +@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='esp32p4 support TBD') # IDF-8981 @pytest.mark.supported_targets @pytest.mark.generic @pytest.mark.parametrize('config', ['freertos_options'], indirect=True) @@ -31,6 +33,7 @@ def test_task_notify_too_high_index_fails(dut: Dut) -> None: dut.expect_exact('Rebooting...') +@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='esp32p4 support TBD') # IDF-8981 @pytest.mark.supported_targets @pytest.mark.generic @pytest.mark.parametrize('config', ['freertos_options'], indirect=True) diff --git a/components/hal/CMakeLists.txt b/components/hal/CMakeLists.txt index 6de6bcb5cf52..f18198cc9fe4 100644 --- a/components/hal/CMakeLists.txt +++ b/components/hal/CMakeLists.txt @@ -246,7 +246,7 @@ if(NOT BOOTLOADER_BUILD) list(APPEND srcs "usb_hal.c" "usb_dwc_hal.c" - "usb_phy_hal.c") + "usb_fsls_phy_hal.c") endif() if(${target} STREQUAL "esp32") diff --git a/components/hal/esp32/clk_tree_hal.c b/components/hal/esp32/clk_tree_hal.c index 4d90ff49701b..8b3a6972f4b8 100644 --- a/components/hal/esp32/clk_tree_hal.c +++ b/components/hal/esp32/clk_tree_hal.c @@ -50,7 +50,7 @@ uint32_t clk_hal_cpu_get_freq_hz(void) } } -uint32_t clk_hal_ahb_get_freq_hz(void) +static uint32_t clk_hal_ahb_get_freq_hz(void) { // AHB_CLK path is highly dependent on CPU_CLK path switch (clk_ll_cpu_get_src()) { diff --git a/components/hal/esp32c2/clk_tree_hal.c b/components/hal/esp32c2/clk_tree_hal.c index ba870243b36f..b05e0abcdcf5 100644 --- a/components/hal/esp32c2/clk_tree_hal.c +++ b/components/hal/esp32c2/clk_tree_hal.c @@ -39,7 +39,7 @@ uint32_t clk_hal_cpu_get_freq_hz(void) } } -uint32_t clk_hal_ahb_get_freq_hz(void) +static uint32_t clk_hal_ahb_get_freq_hz(void) { // AHB_CLK path is highly dependent on CPU_CLK path switch (clk_ll_cpu_get_src()) { diff --git a/components/hal/esp32c3/clk_tree_hal.c b/components/hal/esp32c3/clk_tree_hal.c index 39c58befd22d..67b8971d398b 100644 --- a/components/hal/esp32c3/clk_tree_hal.c +++ b/components/hal/esp32c3/clk_tree_hal.c @@ -39,7 +39,7 @@ uint32_t clk_hal_cpu_get_freq_hz(void) } } -uint32_t clk_hal_ahb_get_freq_hz(void) +static uint32_t clk_hal_ahb_get_freq_hz(void) { // AHB_CLK path is highly dependent on CPU_CLK path switch (clk_ll_cpu_get_src()) { diff --git a/components/hal/esp32c3/include/hal/usb_phy_ll.h b/components/hal/esp32c3/include/hal/usb_fsls_phy_ll.h similarity index 89% rename from components/hal/esp32c3/include/hal/usb_phy_ll.h rename to components/hal/esp32c3/include/hal/usb_fsls_phy_ll.h index 40d4cd180069..b8d98219b0c2 100644 --- a/components/hal/esp32c3/include/hal/usb_phy_ll.h +++ b/components/hal/esp32c3/include/hal/usb_fsls_phy_ll.h @@ -17,7 +17,7 @@ extern "C" { * * @param hw Start address of the USB Serial_JTAG registers */ -static inline void usb_phy_ll_int_jtag_enable(usb_serial_jtag_dev_t *hw) +static inline void usb_fsls_phy_ll_int_jtag_enable(usb_serial_jtag_dev_t *hw) { // USB_Serial_JTAG use internal PHY hw->conf0.phy_sel = 0; diff --git a/components/hal/esp32c6/clk_tree_hal.c b/components/hal/esp32c6/clk_tree_hal.c index ca6ccd1e20a1..d117efb3645f 100644 --- a/components/hal/esp32c6/clk_tree_hal.c +++ b/components/hal/esp32c6/clk_tree_hal.c @@ -35,7 +35,7 @@ uint32_t clk_hal_cpu_get_freq_hz(void) return clk_hal_soc_root_get_freq_mhz(source) * MHZ / divider; } -uint32_t clk_hal_ahb_get_freq_hz(void) +static uint32_t clk_hal_ahb_get_freq_hz(void) { soc_cpu_clk_src_t source = clk_ll_cpu_get_src(); uint32_t divider = (source == SOC_CPU_CLK_SRC_PLL) ? clk_ll_ahb_get_hs_divider() : clk_ll_ahb_get_ls_divider(); diff --git a/components/hal/esp32c6/include/hal/ieee802154_ll.h b/components/hal/esp32c6/include/hal/ieee802154_ll.h index eec479e96a5b..14e548a1d3c0 100644 --- a/components/hal/esp32c6/include/hal/ieee802154_ll.h +++ b/components/hal/esp32c6/include/hal/ieee802154_ll.h @@ -12,3 +12,5 @@ #define IEEE802154_TXPOWER_VALUE_MAX 20 #define IEEE802154_TXPOWER_VALUE_MIN -15 #define IEEE802154_TXPOWER_INDEX_MIN 3 + +#define IEEE802154_RSSI_COMPENSATION_VALUE 0 diff --git a/components/hal/esp32c6/include/hal/parlio_ll.h b/components/hal/esp32c6/include/hal/parlio_ll.h index 1d1265e74e13..78d126a33fc0 100644 --- a/components/hal/esp32c6/include/hal/parlio_ll.h +++ b/components/hal/esp32c6/include/hal/parlio_ll.h @@ -39,12 +39,6 @@ extern "C" { #endif -typedef enum { - PARLIO_LL_CLK_SRC_XTAL = PARLIO_CLK_SRC_XTAL, - PARLIO_LL_CLK_SRC_PLL_F240M = PARLIO_CLK_SRC_PLL_F240M, - PARLIO_LL_CLK_SRC_PAD, // clock source from GPIO pad -} parlio_ll_clock_source_t; - typedef enum { PARLIO_LL_RX_EOF_COND_RX_FULL, /*!< RX unit generates EOF event when it receives enough data */ PARLIO_LL_RX_EOF_COND_EN_INACTIVE, /*!< RX unit generates EOF event when the external enable signal becomes inactive */ @@ -82,18 +76,21 @@ static inline void parlio_ll_reset_register(int group_id) * @param dev Parallel IO register base address * @param src Clock source */ -static inline void parlio_ll_rx_set_clock_source(parl_io_dev_t *dev, parlio_ll_clock_source_t src) +static inline void parlio_ll_rx_set_clock_source(parl_io_dev_t *dev, parlio_clock_source_t src) { (void)dev; uint32_t clk_sel = 0; switch (src) { - case PARLIO_LL_CLK_SRC_XTAL: + case PARLIO_CLK_SRC_XTAL: clk_sel = 0; break; - case PARLIO_LL_CLK_SRC_PLL_F240M: + case PARLIO_CLK_SRC_PLL_F240M: clk_sel = 1; break; - case PARLIO_LL_CLK_SRC_PAD: + case PARLIO_CLK_SRC_RC_FAST: + clk_sel = 2; + break; + case PARLIO_CLK_SRC_EXTERNAL: clk_sel = 3; break; @@ -149,6 +146,7 @@ static inline void parlio_ll_rx_enable_clock(parl_io_dev_t *dev, bool en) * @param dev Parallel IO register base address * @param cond RX EOF condition */ +__attribute__((always_inline)) static inline void parlio_ll_rx_set_eof_condition(parl_io_dev_t *dev, parlio_ll_rx_eof_cond_t cond) { dev->rx_cfg0.rx_eof_gen_sel = cond; @@ -160,6 +158,7 @@ static inline void parlio_ll_rx_set_eof_condition(parl_io_dev_t *dev, parlio_ll_ * @param dev Parallel IO register base address * @param en True to start, False to stop */ +__attribute__((always_inline)) static inline void parlio_ll_rx_start(parl_io_dev_t *dev, bool en) { dev->rx_cfg0.rx_start = en; @@ -173,6 +172,7 @@ static inline void parlio_ll_rx_start(parl_io_dev_t *dev, bool en) * @param dev Parallel IO register base address * @param bitlen Number of bits to receive in the next transaction, bitlen must be a multiple of 8 */ +__attribute__((always_inline)) static inline void parlio_ll_rx_set_recv_bit_len(parl_io_dev_t *dev, uint32_t bitlen) { HAL_FORCE_MODIFY_U32_REG_FIELD(dev->rx_cfg0, rx_data_bytelen, bitlen / 8); @@ -182,12 +182,13 @@ static inline void parlio_ll_rx_set_recv_bit_len(parl_io_dev_t *dev, uint32_t bi * @brief Set the sub mode of the level controlled receive mode * * @param dev Parallel IO register base address - * @param active_level Level of the external enable signal, true for active high, false for active low + * @param active_low_en Level of the external enable signal, true for active low, false for active high */ -static inline void parlio_ll_rx_set_level_recv_mode(parl_io_dev_t *dev, bool active_level) +__attribute__((always_inline)) +static inline void parlio_ll_rx_set_level_recv_mode(parl_io_dev_t *dev, bool active_low_en) { dev->rx_cfg0.rx_smp_mode_sel = 0; - dev->rx_cfg0.rx_level_submode_sel = !active_level; // 0: active low, 1: active high + dev->rx_cfg0.rx_level_submode_sel = active_low_en; } /** @@ -199,6 +200,7 @@ static inline void parlio_ll_rx_set_level_recv_mode(parl_io_dev_t *dev, bool act * @param end_by_len Whether to use the frame length to determine the end of the frame * @param pulse_inv Whether the pulse is inverted */ +__attribute__((always_inline)) static inline void parlio_ll_rx_set_pulse_recv_mode(parl_io_dev_t *dev, bool start_inc, bool end_inc, bool end_by_len, bool pulse_inv) { uint32_t submode = 0; @@ -226,6 +228,7 @@ static inline void parlio_ll_rx_set_pulse_recv_mode(parl_io_dev_t *dev, bool sta * * @param dev Parallel IO register base address */ +__attribute__((always_inline)) static inline void parlio_ll_rx_set_soft_recv_mode(parl_io_dev_t *dev) { dev->rx_cfg0.rx_smp_mode_sel = 2; @@ -248,6 +251,7 @@ static inline void parlio_ll_rx_start_soft_recv(parl_io_dev_t *dev, bool en) * @param dev Parallel IO register base address * @param edge Sample clock edge */ +__attribute__((always_inline)) static inline void parlio_ll_rx_set_sample_clock_edge(parl_io_dev_t *dev, parlio_sample_edge_t edge) { dev->rx_cfg0.rx_clk_edge_sel = edge; @@ -259,6 +263,7 @@ static inline void parlio_ll_rx_set_sample_clock_edge(parl_io_dev_t *dev, parlio * @param dev Parallel IO register base address * @param order Packing order */ +__attribute__((always_inline)) static inline void parlio_ll_rx_set_bit_pack_order(parl_io_dev_t *dev, parlio_bit_pack_order_t order) { dev->rx_cfg0.rx_bit_pack_order = order; @@ -318,6 +323,7 @@ static inline void parlio_ll_rx_reset_fifo(parl_io_dev_t *dev) * @param dev Parallel IO register base address * @param line_num Data line number (0-15) */ +__attribute__((always_inline)) static inline void parlio_ll_rx_treat_data_line_as_en(parl_io_dev_t *dev, uint32_t line_num) { dev->rx_cfg1.rx_ext_en_sel = line_num; @@ -329,6 +335,7 @@ static inline void parlio_ll_rx_treat_data_line_as_en(parl_io_dev_t *dev, uint32 * @param dev Parallel IO register base address * @param en True to enable, False to disable */ +__attribute__((always_inline)) static inline void parlio_ll_rx_enable_timeout(parl_io_dev_t *dev, bool en) { dev->rx_cfg1.rx_timeout_en = en; @@ -340,6 +347,7 @@ static inline void parlio_ll_rx_enable_timeout(parl_io_dev_t *dev, bool en) * @param dev Parallel IO register base address * @param thres Threshold of RX timeout */ +__attribute__((always_inline)) static inline void parlio_ll_rx_set_timeout_thres(parl_io_dev_t *dev, uint32_t thres) { HAL_FORCE_MODIFY_U32_REG_FIELD(dev->rx_cfg1, rx_timeout_threshold, thres); @@ -350,6 +358,7 @@ static inline void parlio_ll_rx_set_timeout_thres(parl_io_dev_t *dev, uint32_t t * * @param dev Parallel IO register base address */ +__attribute__((always_inline)) static inline void parlio_ll_rx_update_config(parl_io_dev_t *dev) { dev->rx_cfg1.rx_reg_update = 1; @@ -364,18 +373,21 @@ static inline void parlio_ll_rx_update_config(parl_io_dev_t *dev) * @param dev Parallel IO register base address * @param src Clock source */ -static inline void parlio_ll_tx_set_clock_source(parl_io_dev_t *dev, parlio_ll_clock_source_t src) +static inline void parlio_ll_tx_set_clock_source(parl_io_dev_t *dev, parlio_clock_source_t src) { (void)dev; uint32_t clk_sel = 0; switch (src) { - case PARLIO_LL_CLK_SRC_XTAL: + case PARLIO_CLK_SRC_XTAL: clk_sel = 0; break; - case PARLIO_LL_CLK_SRC_PLL_F240M: + case PARLIO_CLK_SRC_PLL_F240M: clk_sel = 1; break; - case PARLIO_LL_CLK_SRC_PAD: + case PARLIO_CLK_SRC_RC_FAST: + clk_sel = 2; + break; + case PARLIO_CLK_SRC_EXTERNAL: clk_sel = 3; break; diff --git a/components/hal/esp32c6/include/hal/usb_phy_ll.h b/components/hal/esp32c6/include/hal/usb_fsls_phy_ll.h similarity index 89% rename from components/hal/esp32c6/include/hal/usb_phy_ll.h rename to components/hal/esp32c6/include/hal/usb_fsls_phy_ll.h index 312ff236cd61..4893e96106de 100644 --- a/components/hal/esp32c6/include/hal/usb_phy_ll.h +++ b/components/hal/esp32c6/include/hal/usb_fsls_phy_ll.h @@ -17,7 +17,7 @@ extern "C" { * * @param hw Start address of the USB Serial_JTAG registers */ -static inline void usb_phy_ll_int_jtag_enable(usb_serial_jtag_dev_t *hw) +static inline void usb_fsls_phy_ll_int_jtag_enable(usb_serial_jtag_dev_t *hw) { // USB_Serial_JTAG use internal PHY hw->conf0.phy_sel = 0; diff --git a/components/hal/esp32h2/clk_tree_hal.c b/components/hal/esp32h2/clk_tree_hal.c index 56f193e1a7b0..fcd6b042ba09 100644 --- a/components/hal/esp32h2/clk_tree_hal.c +++ b/components/hal/esp32h2/clk_tree_hal.c @@ -36,7 +36,7 @@ uint32_t clk_hal_cpu_get_freq_hz(void) return clk_hal_soc_root_get_freq_mhz(source) * MHZ / clk_ll_cpu_get_divider(); } -uint32_t clk_hal_ahb_get_freq_hz(void) +static uint32_t clk_hal_ahb_get_freq_hz(void) { soc_cpu_clk_src_t source = clk_ll_cpu_get_src(); return clk_hal_soc_root_get_freq_mhz(source) * MHZ / clk_ll_ahb_get_divider(); diff --git a/components/hal/esp32h2/include/hal/ieee802154_ll.h b/components/hal/esp32h2/include/hal/ieee802154_ll.h index fdc212b582a1..c873c5515ea1 100644 --- a/components/hal/esp32h2/include/hal/ieee802154_ll.h +++ b/components/hal/esp32h2/include/hal/ieee802154_ll.h @@ -12,3 +12,5 @@ #define IEEE802154_TXPOWER_VALUE_MAX 20 #define IEEE802154_TXPOWER_VALUE_MIN -24 #define IEEE802154_TXPOWER_INDEX_MIN 0 + +#define IEEE802154_RSSI_COMPENSATION_VALUE 10 diff --git a/components/hal/esp32h2/include/hal/parlio_ll.h b/components/hal/esp32h2/include/hal/parlio_ll.h index f4938b1c4b0e..e0236e0f8a7d 100644 --- a/components/hal/esp32h2/include/hal/parlio_ll.h +++ b/components/hal/esp32h2/include/hal/parlio_ll.h @@ -41,12 +41,6 @@ extern "C" { #endif -typedef enum { - PARLIO_LL_CLK_SRC_XTAL = PARLIO_CLK_SRC_XTAL, - PARLIO_LL_CLK_SRC_PLL_F96M = PARLIO_CLK_SRC_PLL_F96M, - PARLIO_LL_CLK_SRC_PAD, // clock source from GPIO pad -} parlio_ll_clock_source_t; - typedef enum { PARLIO_LL_RX_EOF_COND_RX_FULL, /*!< RX unit generates EOF event when it receives enough data */ PARLIO_LL_RX_EOF_COND_EN_INACTIVE, /*!< RX unit generates EOF event when the external enable signal becomes inactive */ @@ -84,18 +78,21 @@ static inline void parlio_ll_reset_register(int group_id) * @param dev Parallel IO register base address * @param src Clock source */ -static inline void parlio_ll_rx_set_clock_source(parl_io_dev_t *dev, parlio_ll_clock_source_t src) +static inline void parlio_ll_rx_set_clock_source(parl_io_dev_t *dev, parlio_clock_source_t src) { (void)dev; uint32_t clk_sel = 0; switch (src) { - case PARLIO_LL_CLK_SRC_XTAL: + case PARLIO_CLK_SRC_XTAL: clk_sel = 0; break; - case PARLIO_LL_CLK_SRC_PLL_F96M: + case PARLIO_CLK_SRC_PLL_F96M: clk_sel = 1; break; - case PARLIO_LL_CLK_SRC_PAD: + case PARLIO_CLK_SRC_RC_FAST: + clk_sel = 2; + break; + case PARLIO_CLK_SRC_EXTERNAL: clk_sel = 3; break; @@ -137,6 +134,7 @@ static inline void parlio_ll_rx_reset_clock(parl_io_dev_t *dev) * @param dev Parallel IO register base address * @param en True to enable, False to disable */ +__attribute__((always_inline)) static inline void parlio_ll_rx_enable_clock(parl_io_dev_t *dev, bool en) { (void)dev; @@ -149,6 +147,7 @@ static inline void parlio_ll_rx_enable_clock(parl_io_dev_t *dev, bool en) * @param dev Parallel IO register base address * @param cond RX EOF condition */ +__attribute__((always_inline)) static inline void parlio_ll_rx_set_eof_condition(parl_io_dev_t *dev, parlio_ll_rx_eof_cond_t cond) { dev->rx_genrl_cfg.rx_eof_gen_sel = cond; @@ -160,6 +159,7 @@ static inline void parlio_ll_rx_set_eof_condition(parl_io_dev_t *dev, parlio_ll_ * @param dev Parallel IO register base address * @param en True to start, False to stop */ +__attribute__((always_inline)) static inline void parlio_ll_rx_start(parl_io_dev_t *dev, bool en) { dev->rx_start_cfg.rx_start = en; @@ -173,6 +173,7 @@ static inline void parlio_ll_rx_start(parl_io_dev_t *dev, bool en) * @param dev Parallel IO register base address * @param bitlen Number of bits to receive in the next transaction, bitlen must be a multiple of 8 */ +__attribute__((always_inline)) static inline void parlio_ll_rx_set_recv_bit_len(parl_io_dev_t *dev, uint32_t bitlen) { dev->rx_data_cfg.rx_bitlen = bitlen; @@ -182,12 +183,13 @@ static inline void parlio_ll_rx_set_recv_bit_len(parl_io_dev_t *dev, uint32_t bi * @brief Set the sub mode of the level controlled receive mode * * @param dev Parallel IO register base address - * @param active_level Level of the external enable signal, true for active high, false for active low + * @param active_low_en Level of the external enable signal, true for active low, false for active high */ -static inline void parlio_ll_rx_set_level_recv_mode(parl_io_dev_t *dev, bool active_level) +__attribute__((always_inline)) +static inline void parlio_ll_rx_set_level_recv_mode(parl_io_dev_t *dev, bool active_low_en) { dev->rx_mode_cfg.rx_smp_mode_sel = 0; - dev->rx_mode_cfg.rx_ext_en_inv = !active_level; // 0: active low, 1: active high + dev->rx_mode_cfg.rx_ext_en_inv = active_low_en; } /** @@ -199,6 +201,7 @@ static inline void parlio_ll_rx_set_level_recv_mode(parl_io_dev_t *dev, bool act * @param end_by_len Whether to use the frame length to determine the end of the frame * @param pulse_inv Whether the pulse is inverted */ +__attribute__((always_inline)) static inline void parlio_ll_rx_set_pulse_recv_mode(parl_io_dev_t *dev, bool start_inc, bool end_inc, bool end_by_len, bool pulse_inv) { uint32_t submode = 0; @@ -224,6 +227,7 @@ static inline void parlio_ll_rx_set_pulse_recv_mode(parl_io_dev_t *dev, bool sta * * @param dev Parallel IO register base address */ +__attribute__((always_inline)) static inline void parlio_ll_rx_set_soft_recv_mode(parl_io_dev_t *dev) { dev->rx_mode_cfg.rx_smp_mode_sel = 2; @@ -246,6 +250,7 @@ static inline void parlio_ll_rx_start_soft_recv(parl_io_dev_t *dev, bool en) * @param dev Parallel IO register base address * @param edge Sample clock edge */ +__attribute__((always_inline)) static inline void parlio_ll_rx_set_sample_clock_edge(parl_io_dev_t *dev, parlio_sample_edge_t edge) { dev->rx_clk_cfg.rx_clk_i_inv = edge; @@ -258,6 +263,7 @@ static inline void parlio_ll_rx_set_sample_clock_edge(parl_io_dev_t *dev, parlio * @param dev Parallel IO register base address * @param order Packing order */ +__attribute__((always_inline)) static inline void parlio_ll_rx_set_bit_pack_order(parl_io_dev_t *dev, parlio_bit_pack_order_t order) { dev->rx_data_cfg.rx_data_order_inv = order; @@ -313,6 +319,7 @@ static inline void parlio_ll_rx_reset_fifo(parl_io_dev_t *dev) * @param dev Parallel IO register base address * @param line_num Data line number (0-15) */ +__attribute__((always_inline)) static inline void parlio_ll_rx_treat_data_line_as_en(parl_io_dev_t *dev, uint32_t line_num) { dev->rx_mode_cfg.rx_ext_en_sel = line_num; @@ -335,6 +342,7 @@ static inline void parlio_ll_rx_enable_clock_gating(parl_io_dev_t *dev, bool en) * @param dev Parallel IO register base address * @param en True to enable, False to disable */ +__attribute__((always_inline)) static inline void parlio_ll_rx_enable_timeout(parl_io_dev_t *dev, bool en) { dev->rx_genrl_cfg.rx_timeout_en = en; @@ -346,6 +354,7 @@ static inline void parlio_ll_rx_enable_timeout(parl_io_dev_t *dev, bool en) * @param dev Parallel IO register base address * @param thres Threshold of RX timeout */ +__attribute__((always_inline)) static inline void parlio_ll_rx_set_timeout_thres(parl_io_dev_t *dev, uint32_t thres) { HAL_FORCE_MODIFY_U32_REG_FIELD(dev->rx_genrl_cfg, rx_timeout_thres, thres); @@ -356,6 +365,7 @@ static inline void parlio_ll_rx_set_timeout_thres(parl_io_dev_t *dev, uint32_t t * * @param dev Parallel IO register base address */ +__attribute__((always_inline)) static inline void parlio_ll_rx_update_config(parl_io_dev_t *dev) { dev->reg_update.rx_reg_update = 1; @@ -370,18 +380,21 @@ static inline void parlio_ll_rx_update_config(parl_io_dev_t *dev) * @param dev Parallel IO register base address * @param src Clock source */ -static inline void parlio_ll_tx_set_clock_source(parl_io_dev_t *dev, parlio_ll_clock_source_t src) +static inline void parlio_ll_tx_set_clock_source(parl_io_dev_t *dev, parlio_clock_source_t src) { (void)dev; uint32_t clk_sel = 0; switch (src) { - case PARLIO_LL_CLK_SRC_XTAL: + case PARLIO_CLK_SRC_XTAL: clk_sel = 0; break; - case PARLIO_LL_CLK_SRC_PLL_F96M: + case PARLIO_CLK_SRC_PLL_F96M: clk_sel = 1; break; - case PARLIO_LL_CLK_SRC_PAD: + case PARLIO_CLK_SRC_RC_FAST: + clk_sel = 2; + break; + case PARLIO_CLK_SRC_EXTERNAL: clk_sel = 3; break; diff --git a/components/hal/esp32h2/include/hal/usb_phy_ll.h b/components/hal/esp32h2/include/hal/usb_fsls_phy_ll.h similarity index 89% rename from components/hal/esp32h2/include/hal/usb_phy_ll.h rename to components/hal/esp32h2/include/hal/usb_fsls_phy_ll.h index 9713aae330ec..271f2fd83beb 100644 --- a/components/hal/esp32h2/include/hal/usb_phy_ll.h +++ b/components/hal/esp32h2/include/hal/usb_fsls_phy_ll.h @@ -17,7 +17,7 @@ extern "C" { * * @param hw Start address of the USB Serial_JTAG registers */ -static inline void usb_phy_ll_int_jtag_enable(usb_serial_jtag_dev_t *hw) +static inline void usb_fsls_phy_ll_int_jtag_enable(usb_serial_jtag_dev_t *hw) { // USB_Serial_JTAG use internal PHY hw->conf0.phy_sel = 0; diff --git a/components/hal/esp32p4/clk_tree_hal.c b/components/hal/esp32p4/clk_tree_hal.c new file mode 100644 index 000000000000..8e5b95fdbd7d --- /dev/null +++ b/components/hal/esp32p4/clk_tree_hal.c @@ -0,0 +1,82 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "hal/clk_tree_hal.h" +#include "hal/clk_tree_ll.h" +#include "soc/rtc.h" +#include "hal/assert.h" +#include "hal/log.h" + +static const char *CLK_HAL_TAG = "clk_hal"; + +uint32_t clk_hal_soc_root_get_freq_mhz(soc_cpu_clk_src_t cpu_clk_src) +{ + switch (cpu_clk_src) { + case SOC_CPU_CLK_SRC_XTAL: + return clk_hal_xtal_get_freq_mhz(); + case SOC_CPU_CLK_SRC_CPLL: + return clk_ll_cpll_get_freq_mhz(clk_hal_xtal_get_freq_mhz()); + case SOC_CPU_CLK_SRC_RC_FAST: + return SOC_CLK_RC_FAST_FREQ_APPROX / MHZ; + default: + // Unknown CPU_CLK mux input + HAL_ASSERT(false); + return 0; + } +} + +uint32_t clk_hal_cpu_get_freq_hz(void) +{ + soc_cpu_clk_src_t source = clk_ll_cpu_get_src(); + uint32_t integer, numerator, denominator; + clk_ll_cpu_get_divider(&integer, &numerator, &denominator); + if (denominator == 0) { + denominator = 1; + numerator = 0; + } + return clk_hal_soc_root_get_freq_mhz(source) * MHZ * denominator / (integer * denominator + numerator); +} + +static uint32_t clk_hal_mem_get_freq_hz(void) +{ + return clk_hal_cpu_get_freq_hz() / clk_ll_mem_get_divider(); +} + +static uint32_t clk_hal_sys_get_freq_hz(void) +{ + return clk_hal_mem_get_freq_hz() / clk_ll_sys_get_divider(); +} + +uint32_t clk_hal_apb_get_freq_hz(void) +{ + return clk_hal_sys_get_freq_hz() / clk_ll_apb_get_divider(); +} + +uint32_t clk_hal_lp_slow_get_freq_hz(void) +{ + switch (clk_ll_rtc_slow_get_src()) { + case SOC_RTC_SLOW_CLK_SRC_RC_SLOW: + return SOC_CLK_RC_SLOW_FREQ_APPROX; + case SOC_RTC_SLOW_CLK_SRC_XTAL32K: + return SOC_CLK_XTAL32K_FREQ_APPROX; + case SOC_RTC_SLOW_CLK_SRC_RC32K: + return SOC_CLK_RC32K_FREQ_APPROX; + default: + // Unknown RTC_SLOW_CLK mux input + HAL_ASSERT(false); + return 0; + } +} + +uint32_t clk_hal_xtal_get_freq_mhz(void) +{ + uint32_t freq = clk_ll_xtal_load_freq_mhz(); + if (freq == 0) { + HAL_LOGW(CLK_HAL_TAG, "invalid RTC_XTAL_FREQ_REG value, assume 40MHz"); + return (uint32_t)RTC_XTAL_FREQ_40M; + } + return freq; +} diff --git a/components/hal/esp32p4/include/hal/clk_tree_ll.h b/components/hal/esp32p4/include/hal/clk_tree_ll.h index eec54323fcbd..b21407ca9385 100644 --- a/components/hal/esp32p4/include/hal/clk_tree_ll.h +++ b/components/hal/esp32p4/include/hal/clk_tree_ll.h @@ -10,8 +10,12 @@ #include "soc/soc.h" #include "soc/clk_tree_defs.h" #include "soc/rtc.h" +#include "soc/hp_sys_clkrst_reg.h" +#include "soc/hp_sys_clkrst_struct.h" +#include "soc/lp_clkrst_struct.h" #include "soc/pmu_reg.h" #include "hal/regi2c_ctrl.h" +#include "soc/regi2c_cpll.h" #include "soc/regi2c_mpll.h" #include "hal/assert.h" #include "hal/log.h" @@ -24,15 +28,21 @@ extern "C" { #define MHZ (1000000) +#define CLK_LL_PLL_8M_FREQ_MHZ (8) + +#define CLK_LL_PLL_20M_FREQ_MHZ (20) #define CLK_LL_PLL_80M_FREQ_MHZ (80) -#define CLK_LL_PLL_120M_FREQ_MHZ (120) #define CLK_LL_PLL_160M_FREQ_MHZ (160) #define CLK_LL_PLL_240M_FREQ_MHZ (240) +#define CLK_LL_PLL_360M_FREQ_MHZ (360) +#define CLK_LL_PLL_400M_FREQ_MHZ (400) + #define CLK_LL_PLL_480M_FREQ_MHZ (480) +#define CLK_LL_PLL_500M_FREQ_MHZ (500) /* APLL multiplier output frequency range */ -// TODO: IDF-7526 check if the APLL frequency range is same as before +// TODO: IDF-8884 check if the APLL frequency range is same as before // apll_multiplier_out = xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536) #define CLK_LL_APLL_MULTIPLIER_MIN_HZ (350000000) // 350 MHz #define CLK_LL_APLL_MULTIPLIER_MAX_HZ (500000000) // 500 MHz @@ -53,7 +63,6 @@ extern "C" { */ typedef enum { CLK_LL_XTAL32K_ENABLE_MODE_CRYSTAL, //!< Enable the external 32kHz crystal for XTAL32K_CLK - CLK_LL_XTAL32K_ENABLE_MODE_EXTERNAL, //!< Enable the external clock signal for OSC_SLOW_CLK CLK_LL_XTAL32K_ENABLE_MODE_BOOTSTRAP, //!< Bootstrap the crystal oscillator for faster XTAL32K_CLK start up */ } clk_ll_xtal32k_enable_mode_t; @@ -69,18 +78,39 @@ typedef struct { /** - * @brief Power up BBPLL circuit + * @brief Power up CPLL circuit + */ +static inline __attribute__((always_inline)) void clk_ll_cpll_enable(void) +{ + SET_PERI_REG_MASK(PMU_IMM_HP_CK_POWER_REG, PMU_TIE_HIGH_XPD_CPLL | PMU_TIE_HIGH_XPD_CPLL_I2C); + SET_PERI_REG_MASK(PMU_IMM_HP_CK_POWER_REG, PMU_TIE_HIGH_GLOBAL_CPLL_ICG); +} + +/** + * @brief Power down CPLL circuit */ -static inline __attribute__((always_inline)) void clk_ll_bbpll_enable(void) +static inline __attribute__((always_inline)) void clk_ll_cpll_disable(void) { + SET_PERI_REG_MASK(PMU_IMM_HP_CK_POWER_REG, PMU_TIE_LOW_GLOBAL_CPLL_ICG) ; + SET_PERI_REG_MASK(PMU_IMM_HP_CK_POWER_REG, PMU_TIE_LOW_XPD_CPLL | PMU_TIE_LOW_XPD_CPLL_I2C); } /** - * @brief Power down BBPLL circuit + * @brief Enable the internal oscillator output for LP_PLL_CLK */ -static inline __attribute__((always_inline)) void clk_ll_bbpll_disable(void) +static inline __attribute__((always_inline)) void clk_ll_lp_pll_enable(void) { + // Enable lp_pll xpd status + SET_PERI_REG_MASK(PMU_HP_SLEEP_LP_CK_POWER_REG, PMU_HP_SLEEP_XPD_LPPLL); +} +/** + * @brief Disable the internal oscillator output for LP_PLL_CLK + */ +static inline __attribute__((always_inline)) void clk_ll_lp_pll_disable(void) +{ + // Disable lp_pll xpd status + CLEAR_PERI_REG_MASK(PMU_HP_SLEEP_LP_CK_POWER_REG, PMU_HP_SLEEP_XPD_LPPLL); } /** @@ -106,7 +136,14 @@ static inline __attribute__((always_inline)) void clk_ll_mpll_disable(void) */ static inline __attribute__((always_inline)) void clk_ll_xtal32k_enable(clk_ll_xtal32k_enable_mode_t mode) { - + // Configure xtal32k + clk_ll_xtal32k_config_t cfg = CLK_LL_XTAL32K_CONFIG_DEFAULT(); + LP_AON_CLKRST.xtal32k.dac_xtal32k = cfg.dac; + LP_AON_CLKRST.xtal32k.dres_xtal32k = cfg.dres; + LP_AON_CLKRST.xtal32k.dgm_xtal32k = cfg.dgm; + LP_AON_CLKRST.xtal32k.dbuf_xtal32k = cfg.dbuf; + // Enable xtal32k xpd + SET_PERI_REG_MASK(PMU_HP_SLEEP_LP_CK_POWER_REG, PMU_HP_SLEEP_XPD_XTAL32K); } /** @@ -114,7 +151,8 @@ static inline __attribute__((always_inline)) void clk_ll_xtal32k_enable(clk_ll_x */ static inline __attribute__((always_inline)) void clk_ll_xtal32k_disable(void) { - + // Disable xtal32k xpd + CLEAR_PERI_REG_MASK(PMU_HP_SLEEP_LP_CK_POWER_REG, PMU_HP_SLEEP_XPD_XTAL32K); } /** @@ -124,7 +162,7 @@ static inline __attribute__((always_inline)) void clk_ll_xtal32k_disable(void) */ static inline __attribute__((always_inline)) bool clk_ll_xtal32k_is_enabled(void) { - return 0; + return REG_GET_FIELD(PMU_HP_SLEEP_LP_CK_POWER_REG, PMU_HP_SLEEP_XPD_XTAL32K) == 1; } /** @@ -132,7 +170,8 @@ static inline __attribute__((always_inline)) bool clk_ll_xtal32k_is_enabled(void */ static inline __attribute__((always_inline)) void clk_ll_rc32k_enable(void) { - + // Enable rc32k xpd status + SET_PERI_REG_MASK(PMU_HP_SLEEP_LP_CK_POWER_REG, PMU_HP_SLEEP_XPD_RC32K); } /** @@ -140,7 +179,8 @@ static inline __attribute__((always_inline)) void clk_ll_rc32k_enable(void) */ static inline __attribute__((always_inline)) void clk_ll_rc32k_disable(void) { - + // Disable rc32k xpd status + CLEAR_PERI_REG_MASK(PMU_HP_SLEEP_LP_CK_POWER_REG, PMU_HP_SLEEP_XPD_RC32K); } /** @@ -150,7 +190,7 @@ static inline __attribute__((always_inline)) void clk_ll_rc32k_disable(void) */ static inline __attribute__((always_inline)) bool clk_ll_rc32k_is_enabled(void) { - return 0; + return REG_GET_FIELD(PMU_HP_SLEEP_LP_CK_POWER_REG, PMU_HP_SLEEP_XPD_RC32K) == 1; } /** @@ -158,7 +198,7 @@ static inline __attribute__((always_inline)) bool clk_ll_rc32k_is_enabled(void) */ static inline __attribute__((always_inline)) void clk_ll_rc_fast_enable(void) { - + SET_PERI_REG_MASK(PMU_HP_SLEEP_LP_CK_POWER_REG, PMU_HP_SLEEP_XPD_FOSC_CLK); } /** @@ -166,7 +206,7 @@ static inline __attribute__((always_inline)) void clk_ll_rc_fast_enable(void) */ static inline __attribute__((always_inline)) void clk_ll_rc_fast_disable(void) { - + CLEAR_PERI_REG_MASK(PMU_HP_SLEEP_LP_CK_POWER_REG, PMU_HP_SLEEP_XPD_FOSC_CLK); } /** @@ -176,7 +216,7 @@ static inline __attribute__((always_inline)) void clk_ll_rc_fast_disable(void) */ static inline __attribute__((always_inline)) bool clk_ll_rc_fast_is_enabled(void) { - return 0; + return REG_GET_FIELD(PMU_HP_SLEEP_LP_CK_POWER_REG, PMU_HP_SLEEP_XPD_FOSC_CLK) == 1; } /** @@ -184,7 +224,7 @@ static inline __attribute__((always_inline)) bool clk_ll_rc_fast_is_enabled(void */ static inline __attribute__((always_inline)) void clk_ll_rc_fast_digi_enable(void) { - + LP_AON_CLKRST.clk_to_hp.icg_hp_fosc = 1; } /** @@ -192,7 +232,7 @@ static inline __attribute__((always_inline)) void clk_ll_rc_fast_digi_enable(voi */ static inline __attribute__((always_inline)) void clk_ll_rc_fast_digi_disable(void) { - + LP_AON_CLKRST.clk_to_hp.icg_hp_fosc = 0; } /** @@ -202,7 +242,7 @@ static inline __attribute__((always_inline)) void clk_ll_rc_fast_digi_disable(vo */ static inline __attribute__((always_inline)) bool clk_ll_rc_fast_digi_is_enabled(void) { - return 0; + return LP_AON_CLKRST.clk_to_hp.icg_hp_fosc; } /** @@ -210,7 +250,7 @@ static inline __attribute__((always_inline)) bool clk_ll_rc_fast_digi_is_enabled */ static inline __attribute__((always_inline)) void clk_ll_xtal32k_digi_enable(void) { - + LP_AON_CLKRST.clk_to_hp.icg_hp_xtal32k = 1; } /** @@ -218,7 +258,7 @@ static inline __attribute__((always_inline)) void clk_ll_xtal32k_digi_enable(voi */ static inline __attribute__((always_inline)) void clk_ll_xtal32k_digi_disable(void) { - + LP_AON_CLKRST.clk_to_hp.icg_hp_xtal32k = 0; } /** @@ -228,7 +268,7 @@ static inline __attribute__((always_inline)) void clk_ll_xtal32k_digi_disable(vo */ static inline __attribute__((always_inline)) bool clk_ll_xtal32k_digi_is_enabled(void) { - return 0; + return LP_AON_CLKRST.clk_to_hp.icg_hp_xtal32k; } /** @@ -236,7 +276,7 @@ static inline __attribute__((always_inline)) bool clk_ll_xtal32k_digi_is_enabled */ static inline __attribute__((always_inline)) void clk_ll_rc32k_digi_enable(void) { - + LP_AON_CLKRST.clk_to_hp.icg_hp_osc32k = 1; } /** @@ -244,7 +284,7 @@ static inline __attribute__((always_inline)) void clk_ll_rc32k_digi_enable(void) */ static inline __attribute__((always_inline)) void clk_ll_rc32k_digi_disable(void) { - + LP_AON_CLKRST.clk_to_hp.icg_hp_osc32k = 0; } /** @@ -254,39 +294,83 @@ static inline __attribute__((always_inline)) void clk_ll_rc32k_digi_disable(void */ static inline __attribute__((always_inline)) bool clk_ll_rc32k_digi_is_enabled(void) { - return 0; + return LP_AON_CLKRST.clk_to_hp.icg_hp_osc32k; } /** - * @brief Get PLL_CLK frequency + * @brief Get CPLL_CLK frequency (only reliable when CPLL power is on) + * + * @param xtal_freq_mhz XTAL frequency, in MHz * - * @return PLL clock frequency, in MHz. Returns 0 if register field value is invalid. + * @return CPLL clock frequency, in MHz */ -static inline __attribute__((always_inline)) uint32_t clk_ll_bbpll_get_freq_mhz(void) +static inline __attribute__((always_inline)) uint32_t clk_ll_cpll_get_freq_mhz(uint32_t xtal_freq_mhz) { - // The target has a fixed 480MHz SPLL - return CLK_LL_PLL_480M_FREQ_MHZ; + uint8_t div = REGI2C_READ_MASK(I2C_CPLL, I2C_CPLL_OC_DIV_7_0); + uint8_t ref_div = REGI2C_READ_MASK(I2C_CPLL, I2C_CPLL_OC_REF_DIV); + return xtal_freq_mhz * (div + 4) / (ref_div + 1); } /** - * @brief Set BBPLL frequency from XTAL source (Digital part) + * @brief Set CPLL frequency from XTAL source (Digital part) * - * @param pll_freq_mhz PLL frequency, in MHz + * @param cpll_freq_mhz CPLL frequency, in MHz */ -static inline __attribute__((always_inline)) void clk_ll_bbpll_set_freq_mhz(uint32_t pll_freq_mhz) +static inline __attribute__((always_inline)) void clk_ll_cpll_set_freq_mhz(uint32_t cpll_freq_mhz) { - + // Do nothing. CPLL frequency controlled by analog only on the target. + (void)cpll_freq_mhz; } /** - * @brief Set BBPLL frequency from XTAL source (Analog part) + * @brief Set CPLL frequency from XTAL source (Analog part - through regi2c) * - * @param pll_freq_mhz PLL frequency, in MHz + * @param cpll_freq_mhz CPLL frequency, in MHz * @param xtal_freq_mhz XTAL frequency, in MHz */ -static inline __attribute__((always_inline)) void clk_ll_bbpll_set_config(uint32_t pll_freq_mhz, uint32_t xtal_freq_mhz) +static inline __attribute__((always_inline)) void clk_ll_cpll_set_config(uint32_t cpll_freq_mhz, uint32_t xtal_freq_mhz) { + uint8_t div_ref; + uint8_t div7_0; + uint8_t dchgp = 5; + uint8_t dcur = 3; + uint8_t oc_enb_fcal = 0; + // Currently, only supporting 40MHz XTAL + HAL_ASSERT(xtal_freq_mhz == RTC_XTAL_FREQ_40M); + switch (cpll_freq_mhz) { + case CLK_LL_PLL_400M_FREQ_MHZ: + /* Configure 400M CPLL */ + div7_0 = 6; + div_ref = 0; + break; + case CLK_LL_PLL_360M_FREQ_MHZ: + default: + /* Configure 360M CPLL */ + div7_0 = 5; + div_ref = 0; + break; + } + uint8_t i2c_cpll_lref = (oc_enb_fcal << I2C_CPLL_OC_ENB_FCAL_LSB) | (dchgp << I2C_CPLL_OC_DCHGP_LSB) | (div_ref); + uint8_t i2c_cpll_div_7_0 = div7_0; + uint8_t i2c_cpll_dcur = (1 << I2C_CPLL_OC_DLREF_SEL_LSB ) | (3 << I2C_CPLL_OC_DHREF_SEL_LSB) | dcur; + REGI2C_WRITE(I2C_CPLL, I2C_CPLL_OC_REF_DIV, i2c_cpll_lref); + REGI2C_WRITE(I2C_CPLL, I2C_CPLL_OC_DIV_7_0, i2c_cpll_div_7_0); + REGI2C_WRITE(I2C_CPLL, I2C_CPLL_OC_DCUR, i2c_cpll_dcur); +} + +/** + * @brief Get MPLL_CLK frequency (only reliable when MPLL power is on) + * + * @param xtal_freq_mhz XTAL frequency, in MHz + * + * @return MPLL clock frequency, in MHz + */ +static inline __attribute__((always_inline)) uint32_t clk_ll_mpll_get_freq_mhz(uint32_t xtal_freq_mhz) +{ + uint8_t div = REGI2C_READ_MASK(I2C_MPLL, I2C_MPLL_DIV_ADDR); + uint8_t ref_div = REGI2C_READ_MASK(I2C_MPLL, I2C_MPLL_REF_DIV_ADDR); + return xtal_freq_mhz * (div + 1) / (ref_div + 1); } /** @@ -306,6 +390,15 @@ static inline __attribute__((always_inline)) void clk_ll_mpll_set_config(uint32_ REGI2C_WRITE(I2C_MPLL, I2C_MPLL_DIV_REG_ADDR, val); } +/** + * @brief To enable the change of cpu_div_num, mem_div_num, sys_div_num, and apb_div_num + */ +static inline __attribute__((always_inline)) void clk_ll_bus_update(void) +{ + HP_SYS_CLKRST.root_clk_ctrl0.reg_soc_clk_div_update = 1; + while (HP_SYS_CLKRST.root_clk_ctrl0.reg_soc_clk_div_update); +} + /** * @brief Select the clock source for CPU_CLK (SOC Clock Root) * @@ -313,7 +406,20 @@ static inline __attribute__((always_inline)) void clk_ll_mpll_set_config(uint32_ */ static inline __attribute__((always_inline)) void clk_ll_cpu_set_src(soc_cpu_clk_src_t in_sel) { - + switch (in_sel) { + case SOC_CPU_CLK_SRC_XTAL: + LP_AON_CLKRST.hp_clk_ctrl.hp_root_clk_src_sel = 0; + break; + case SOC_CPU_CLK_SRC_CPLL: + LP_AON_CLKRST.hp_clk_ctrl.hp_root_clk_src_sel = 1; + break; + case SOC_CPU_CLK_SRC_RC_FAST: + LP_AON_CLKRST.hp_clk_ctrl.hp_root_clk_src_sel = 2; + break; + default: + // Unsupported CPU_CLK mux input sel + abort(); + } } /** @@ -323,167 +429,249 @@ static inline __attribute__((always_inline)) void clk_ll_cpu_set_src(soc_cpu_clk */ static inline __attribute__((always_inline)) soc_cpu_clk_src_t clk_ll_cpu_get_src(void) { - return SOC_CPU_CLK_SRC_XTAL; + uint32_t clk_sel = LP_AON_CLKRST.hp_clk_ctrl.hp_root_clk_src_sel; + switch (clk_sel) { + case 0: + return SOC_CPU_CLK_SRC_XTAL; + case 1: + return SOC_CPU_CLK_SRC_CPLL; + case 2: + return SOC_CPU_CLK_SRC_RC_FAST; + default: + // Invalid HP_ROOT_CLK_SRC_SEL value + return SOC_CPU_CLK_SRC_INVALID; + } } /** - * @brief Set CPU_CLK's high-speed divider (valid when SOC_ROOT clock source is PLL) + * @brief Set CPU_CLK divider. freq of CPU_CLK = freq of HP_ROOT_CLK / divider * - * @param divider Divider. (PCR_HS_DIV_NUM + 1) * (PCR_CPU_HS_DIV_NUM + 1) = divider. + * @param integer Integer part of the divider + * @param numerator Numerator part of the divider + * @param denominator Denominator part of the divider */ -static inline __attribute__((always_inline)) void clk_ll_cpu_set_hs_divider(uint32_t divider) +static inline __attribute__((always_inline)) void clk_ll_cpu_set_divider(uint32_t integer, uint32_t numerator, uint32_t denominator) { - + HAL_ASSERT(integer >= 1 && integer <= HP_SYS_CLKRST_REG_CPU_CLK_DIV_NUM_V); + HAL_ASSERT(numerator <= HP_SYS_CLKRST_REG_CPU_CLK_DIV_NUMERATOR_V); + HAL_ASSERT(denominator <= HP_SYS_CLKRST_REG_CPU_CLK_DIV_DENOMINATOR_V); + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.root_clk_ctrl0, reg_cpu_clk_div_num, integer - 1); + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.root_clk_ctrl0, reg_cpu_clk_div_numerator, numerator); + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.root_clk_ctrl0, reg_cpu_clk_div_denominator, denominator); } /** - * @brief Set CPU_CLK's low-speed divider (valid when SOC_ROOT clock source is XTAL/RC_FAST) + * @brief Get CPU_CLK divider * - * @param divider Divider. (PCR_LS_DIV_NUM + 1) * (PCR_CPU_LS_DIV_NUM + 1) = divider. + * @param integer Integer part of the divider + * @param numerator Numerator part of the divider + * @param denominator Denominator part of the divider */ -static inline __attribute__((always_inline)) void clk_ll_cpu_set_ls_divider(uint32_t divider) +static inline __attribute__((always_inline)) void clk_ll_cpu_get_divider(uint32_t *integer, uint32_t *numerator, uint32_t *denominator) { - + *integer = HAL_FORCE_READ_U32_REG_FIELD(HP_SYS_CLKRST.root_clk_ctrl0, reg_cpu_clk_div_num) + 1; + *numerator = HAL_FORCE_READ_U32_REG_FIELD(HP_SYS_CLKRST.root_clk_ctrl0, reg_cpu_clk_div_numerator); + *denominator = HAL_FORCE_READ_U32_REG_FIELD(HP_SYS_CLKRST.root_clk_ctrl0, reg_cpu_clk_div_denominator); } /** - * @brief Get CPU_CLK's high-speed divider + * @brief Set MEM_CLK divider. freq of MEM_CLK = freq of CPU_CLK / divider * - * @return Divider. Divider = (PCR_HS_DIV_NUM + 1) * (PCR_CPU_HS_DIV_NUM + 1). - */ -static inline __attribute__((always_inline)) uint32_t clk_ll_cpu_get_hs_divider(void) -{ - return 0; -} - -/** - * @brief Get CPU_CLK's low-speed divider + * ESP32P4 MEM_CLK supports fractional divnum (not supported in software yet) + * + * @note There is constraint on the mem divider. Hardware could change the actual divider if the configured value is + * unachievable. Be careful on this. Check TRM or upper layer. * - * @return Divider. Divider = (PCR_LS_DIV_NUM + 1) * (PCR_CPU_LS_DIV_NUM + 1). + * @param divider Divider. CLK_DIV_NUM = divider - 1. */ -static inline __attribute__((always_inline)) uint32_t clk_ll_cpu_get_ls_divider(void) +static inline __attribute__((always_inline)) void clk_ll_mem_set_divider(uint32_t divider) { - return 0; + HAL_ASSERT(divider >= 1 && divider <= 2); // We haven't confirmed the reliable functionality of cache when cpu_clk freq is more than 2 times faster than the cache clk freq. Need to verify before removing the constraint of divider <= 2. + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.root_clk_ctrl1, reg_mem_clk_div_num, divider - 1); } /** - * @brief Set AHB_CLK's high-speed divider (valid when SOC_ROOT clock source is PLL) + * @brief Get MEM_CLK divider + * + * Fractional divnum not used now. * - * @param divider Divider. (PCR_HS_DIV_NUM + 1) * (PCR_AHB_HS_DIV_NUM + 1) = divider. + * @return Divider. Divider = (CLK_DIV_NUM + 1). */ -static inline __attribute__((always_inline)) void clk_ll_ahb_set_hs_divider(uint32_t divider) +static inline __attribute__((always_inline)) uint32_t clk_ll_mem_get_divider(void) { - + return HAL_FORCE_READ_U32_REG_FIELD(HP_SYS_CLKRST.root_clk_ctrl1, reg_mem_clk_div_num) + 1; } /** - * @brief Set AHB_CLK's low-speed divider (valid when SOC_ROOT clock source is XTAL/RC_FAST) + * @brief Set SYS_CLK divider. freq of SYS_CLK = freq of MEM_CLK / divider * - * @param divider Divider. (PCR_LS_DIV_NUM + 1) * (PCR_AHB_LS_DIV_NUM + 1) = divider. + * ESP32P4 SYS_CLK supports fractional divnum (not supported in software yet) + * + * @param divider Divider. CLK_DIV_NUM = divider - 1. */ -static inline __attribute__((always_inline)) void clk_ll_ahb_set_ls_divider(uint32_t divider) +static inline __attribute__((always_inline)) void clk_ll_sys_set_divider(uint32_t divider) { - + HAL_ASSERT(divider >= 1); + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.root_clk_ctrl1, reg_sys_clk_div_num, divider - 1); } /** - * @brief Get AHB_CLK's high-speed divider + * @brief Get SYS_CLK divider + * + * Fractional divnum not used now. * - * @return Divider. Divider = (PCR_HS_DIV_NUM + 1) * (PCR_AHB_HS_DIV_NUM + 1). + * @return Divider. Divider = (CLK_DIV_NUM + 1). */ -static inline __attribute__((always_inline)) uint32_t clk_ll_ahb_get_hs_divider(void) +static inline __attribute__((always_inline)) uint32_t clk_ll_sys_get_divider(void) { - return 0; + return HAL_FORCE_READ_U32_REG_FIELD(HP_SYS_CLKRST.root_clk_ctrl1, reg_sys_clk_div_num) + 1; } /** - * @brief Get AHB_CLK's low-speed divider + * @brief Set APB_CLK divider. freq of APB_CLK = freq of SYS_CLK / divider + * + * ESP32P4 APB_CLK supports fractional divnum (not supported in software yet) + * + * @note There is constraint on the apb divider. Hardware could change the actual divider if the configured value is + * unachievable. Be careful on this. Check TRM or upper layer. * - * @return Divider. Divider = (PCR_LS_DIV_NUM + 1) * (PCR_AHB_LS_DIV_NUM + 1). + * @param divider Divider. CLK_DIV_NUM = divider - 1. */ -static inline __attribute__((always_inline)) uint32_t clk_ll_ahb_get_ls_divider(void) +static inline __attribute__((always_inline)) void clk_ll_apb_set_divider(uint32_t divider) { - return 1; + HAL_ASSERT(divider >= 1); + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.root_clk_ctrl2, reg_apb_clk_div_num, divider - 1); } /** - * @brief Set APB_CLK divider. freq of APB_CLK = freq of AHB_CLK / divider + * @brief Get APB_CLK divider * - * @param divider Divider. PCR_APB_DIV_NUM = divider - 1. + * Fractional divnum not used now. + * + * @return Divider. Divider = (CLK_DIV_NUM + 1). */ -static inline __attribute__((always_inline)) void clk_ll_apb_set_divider(uint32_t divider) +static inline __attribute__((always_inline)) uint32_t clk_ll_apb_get_divider(void) { - + return HAL_FORCE_READ_U32_REG_FIELD(HP_SYS_CLKRST.root_clk_ctrl2, reg_apb_clk_div_num) + 1; } /** - * @brief Get APB_CLK divider + * @brief Set PLL_F50M_CLK divider. freq of PLL_F50M_CLK = freq of MPLL_CLK / divider * - * @return Divider. Divider = (PCR_APB_DIV_NUM + 1). + * @param divider Divider. CLK_DIV_NUM = divider - 1. */ -static inline __attribute__((always_inline)) uint32_t clk_ll_apb_get_divider(void) +static inline __attribute__((always_inline)) void clk_ll_pll_f50m_set_divider(uint32_t divider) { - return 1; + HAL_ASSERT(divider >= 1); + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.ref_clk_ctrl0, reg_ref_50m_clk_div_num, divider - 1); } /** - * @brief Set MSPI_FAST_CLK's high-speed divider (valid when SOC_ROOT clock source is PLL) + * @brief Set PLL_F25M_CLK divider. freq of PLL_F25M_CLK = freq of MPLL_CLK / divider * - * @param divider Divider. + * @param divider Divider. CLK_DIV_NUM = divider - 1. */ -static inline __attribute__((always_inline)) void clk_ll_mspi_fast_set_hs_divider(uint32_t divider) +static inline __attribute__((always_inline)) void clk_ll_pll_f25m_set_divider(uint32_t divider) { - + HAL_ASSERT(divider >= 1); + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.ref_clk_ctrl0, reg_ref_25m_clk_div_num, divider - 1); } /** - * @brief Set MSPI_FAST_CLK's low-speed divider (valid when SOC_ROOT clock source is XTAL/RC_FAST) + * @brief Select the clock source for RTC_SLOW_CLK * - * @param divider Divider. + * @param in_sel One of the clock sources in soc_rtc_slow_clk_src_t */ -static inline __attribute__((always_inline)) void clk_ll_mspi_fast_set_ls_divider(uint32_t divider) +static inline __attribute__((always_inline)) void clk_ll_rtc_slow_set_src(soc_rtc_slow_clk_src_t in_sel) { - + switch (in_sel) { + case SOC_RTC_SLOW_CLK_SRC_RC_SLOW: + LP_AON_CLKRST.lp_clk_conf.slow_clk_sel = 0; + break; + case SOC_RTC_SLOW_CLK_SRC_XTAL32K: + LP_AON_CLKRST.lp_clk_conf.slow_clk_sel = 1; + break; + case SOC_RTC_SLOW_CLK_SRC_RC32K: + LP_AON_CLKRST.lp_clk_conf.slow_clk_sel = 2; + break; + // LP_AON_CLKRST.lp_clk_conf.slow_clk_sel = 3 is for SOC_RTC_SLOW_CLK_SRC_OSC_SLOW (a 32kHz clock signal generated + // by an external circuit connecting to XTAL_32K_N (i.e. GPIO0)), but we don't use it on ESP32P4, since osc_slow + // clock can not be calibrated to get its actual frequency + default: + // Unsupported RTC_SLOW_CLK mux input sel + abort(); + } } /** - * @brief Select the calibration 32kHz clock source for timergroup0 + * @brief Get the clock source for RTC_SLOW_CLK * - * @param in_sel One of the 32kHz clock sources (RC32K_CLK, XTAL32K_CLK, OSC_SLOW_CLK) + * @return Currently selected clock source (one of soc_rtc_slow_clk_src_t values) */ -static inline __attribute__((always_inline)) void clk_ll_32k_calibration_set_target(soc_rtc_slow_clk_src_t in_sel) +static inline __attribute__((always_inline)) soc_rtc_slow_clk_src_t clk_ll_rtc_slow_get_src(void) { - + uint32_t clk_sel = LP_AON_CLKRST.lp_clk_conf.slow_clk_sel; + switch (clk_sel) { + case 0: + return SOC_RTC_SLOW_CLK_SRC_RC_SLOW; + case 1: + return SOC_RTC_SLOW_CLK_SRC_XTAL32K; + case 2: + return SOC_RTC_SLOW_CLK_SRC_RC32K; + default: + return SOC_RTC_SLOW_CLK_SRC_INVALID; + } } /** - * @brief Get the calibration 32kHz clock source for timergroup0 + * @brief Select the clock source for LP_PLL_CLK * - * @return soc_rtc_slow_clk_src_t Currently selected calibration 32kHz clock (one of the 32kHz clocks) + * @param in_sel One of the clock sources in soc_lp_pll_clk_src_t */ -static inline __attribute__((always_inline)) soc_rtc_slow_clk_src_t clk_ll_32k_calibration_get_target(void) +static inline __attribute__((always_inline)) void clk_ll_lp_pll_set_src(soc_lp_pll_clk_src_t in_sel) { - return (soc_rtc_slow_clk_src_t)0; + uint32_t field_value; + switch (in_sel) { + case SOC_LP_PLL_CLK_SRC_RC32K: + field_value = 0; + break; + case SOC_LP_PLL_CLK_SRC_XTAL32K: + field_value = 1; + break; + default: + // Unsupported LP_PLL_CLK mux input sel + abort(); + } + LP_AON_CLKRST.lp_clk_conf.ana_sel_ref_pll8m = field_value; } /** - * @brief Select the clock source for RTC_SLOW_CLK + * @brief Get the clock source for LP_PLL_CLK * - * @param in_sel One of the clock sources in soc_rtc_slow_clk_src_t + * @return Currently selected clock source (one of soc_lp_pll_clk_src_t values) */ -static inline __attribute__((always_inline)) void clk_ll_rtc_slow_set_src(soc_rtc_slow_clk_src_t in_sel) +static inline __attribute__((always_inline)) soc_lp_pll_clk_src_t clk_ll_lp_pll_get_src(void) { - + uint32_t clk_sel = LP_AON_CLKRST.lp_clk_conf.ana_sel_ref_pll8m; + switch (clk_sel) { + case 0: + return SOC_LP_PLL_CLK_SRC_RC32K; + case 1: + return SOC_LP_PLL_CLK_SRC_XTAL32K; + default: + return SOC_LP_PLL_CLK_SRC_INVALID; + } } /** - * @brief Get the clock source for RTC_SLOW_CLK + * @brief Get LP_PLL_CLK frequency * - * @return Currently selected clock source (one of soc_rtc_slow_clk_src_t values) + * @return LP_PLL clock frequency, in MHz */ -static inline __attribute__((always_inline)) soc_rtc_slow_clk_src_t clk_ll_rtc_slow_get_src(void) +static inline __attribute__((always_inline)) uint32_t clk_ll_lp_pll_get_freq_mhz(void) { - return (soc_rtc_slow_clk_src_t)0; + // The target has a fixed 8MHz LP_PLL + return CLK_LL_PLL_8M_FREQ_MHZ; } /** @@ -493,7 +681,20 @@ static inline __attribute__((always_inline)) soc_rtc_slow_clk_src_t clk_ll_rtc_s */ static inline __attribute__((always_inline)) void clk_ll_rtc_fast_set_src(soc_rtc_fast_clk_src_t in_sel) { - + switch (in_sel) { + case SOC_RTC_FAST_CLK_SRC_RC_FAST: + LP_AON_CLKRST.lp_clk_conf.fast_clk_sel = 0; + break; + case SOC_RTC_FAST_CLK_SRC_XTAL: + LP_AON_CLKRST.lp_clk_conf.fast_clk_sel = 1; + break; + case SOC_RTC_FAST_CLK_SRC_LP_PLL: + LP_AON_CLKRST.lp_clk_conf.fast_clk_sel = 2; + break; + default: + // Unsupported RTC_FAST_CLK mux input sel + abort(); + } } /** @@ -503,7 +704,17 @@ static inline __attribute__((always_inline)) void clk_ll_rtc_fast_set_src(soc_rt */ static inline __attribute__((always_inline)) soc_rtc_fast_clk_src_t clk_ll_rtc_fast_get_src(void) { - return (soc_rtc_fast_clk_src_t)0; + uint32_t clk_sel = LP_AON_CLKRST.lp_clk_conf.fast_clk_sel; + switch (clk_sel) { + case 0: + return SOC_RTC_FAST_CLK_SRC_RC_FAST; + case 1: + return SOC_RTC_FAST_CLK_SRC_XTAL; + case 2: + return SOC_RTC_FAST_CLK_SRC_LP_PLL; + default: + return SOC_RTC_FAST_CLK_SRC_INVALID; + } } /** @@ -513,7 +724,8 @@ static inline __attribute__((always_inline)) soc_rtc_fast_clk_src_t clk_ll_rtc_f */ static inline __attribute__((always_inline)) void clk_ll_rc_fast_set_divider(uint32_t divider) { - + // No divider on the target + HAL_ASSERT(divider == 1); } /** @@ -534,6 +746,8 @@ static inline __attribute__((always_inline)) uint32_t clk_ll_rc_fast_get_divider */ static inline __attribute__((always_inline)) void clk_ll_rc_slow_set_divider(uint32_t divider) { + // No divider on the target + HAL_ASSERT(divider == 1); } /************************** LP STORAGE REGISTER STORE/LOAD **************************/ @@ -549,7 +763,13 @@ static inline __attribute__((always_inline)) void clk_ll_rc_slow_set_divider(uin */ static inline __attribute__((always_inline)) void clk_ll_xtal_store_freq_mhz(uint32_t xtal_freq_mhz) { - + // Read the status of whether disabling logging from ROM code + uint32_t reg = READ_PERI_REG(RTC_XTAL_FREQ_REG) & RTC_DISABLE_ROM_LOG; + // If so, need to write back this setting + if (reg == RTC_DISABLE_ROM_LOG) { + xtal_freq_mhz |= 1; + } + WRITE_PERI_REG(RTC_XTAL_FREQ_REG, (xtal_freq_mhz & UINT16_MAX) | ((xtal_freq_mhz & UINT16_MAX) << 16)); } /** @@ -562,7 +782,14 @@ static inline __attribute__((always_inline)) void clk_ll_xtal_store_freq_mhz(uin */ static inline __attribute__((always_inline)) uint32_t clk_ll_xtal_load_freq_mhz(void) { - return 40; + // Read from RTC storage register + uint32_t xtal_freq_reg = READ_PERI_REG(RTC_XTAL_FREQ_REG); + if ((xtal_freq_reg & 0xFFFF) == ((xtal_freq_reg >> 16) & 0xFFFF) && + xtal_freq_reg != 0 && xtal_freq_reg != UINT32_MAX) { + return xtal_freq_reg & ~RTC_DISABLE_ROM_LOG & UINT16_MAX; + } + // If the format in reg is invalid + return 0; } /** @@ -575,6 +802,7 @@ static inline __attribute__((always_inline)) uint32_t clk_ll_xtal_load_freq_mhz( */ static inline __attribute__((always_inline)) void clk_ll_rtc_slow_store_cal(uint32_t cal_value) { + REG_WRITE(RTC_SLOW_CLK_CAL_REG, cal_value); } /** @@ -586,7 +814,7 @@ static inline __attribute__((always_inline)) void clk_ll_rtc_slow_store_cal(uint */ static inline __attribute__((always_inline)) uint32_t clk_ll_rtc_slow_load_cal(void) { - return 0; + return REG_READ(RTC_SLOW_CLK_CAL_REG); } #ifdef __cplusplus diff --git a/components/hal/esp32p4/include/hal/gpio_ll.h b/components/hal/esp32p4/include/hal/gpio_ll.h index f92a1b6b9904..a068f17cd883 100644 --- a/components/hal/esp32p4/include/hal/gpio_ll.h +++ b/components/hal/esp32p4/include/hal/gpio_ll.h @@ -676,7 +676,7 @@ static inline int gpio_ll_get_in_signal_connected_io(gpio_dev_t *hw, uint32_t in static inline void gpio_ll_force_hold_all(void) { // WT flag, it gets self-cleared after the configuration is done - PMU.imm_pad_hold_all.tie_high_hp_pad_hold_all = 1; + PMU.imm.pad_hold_all.tie_high_hp_pad_hold_all = 1; } /** @@ -686,7 +686,7 @@ static inline void gpio_ll_force_hold_all(void) static inline void gpio_ll_force_unhold_all(void) { // WT flag, it gets self-cleared after the configuration is done - PMU.imm_pad_hold_all.tie_low_hp_pad_hold_all = 1; + PMU.imm.pad_hold_all.tie_low_hp_pad_hold_all = 1; } /** diff --git a/components/hal/esp32p4/include/hal/lp_core_ll.h b/components/hal/esp32p4/include/hal/lp_core_ll.h index 73274fda12b7..67fd2bb215e3 100644 --- a/components/hal/esp32p4/include/hal/lp_core_ll.h +++ b/components/hal/esp32p4/include/hal/lp_core_ll.h @@ -88,7 +88,7 @@ static inline void lp_core_ll_debug_module_enable(bool enable) */ static inline void lp_core_ll_rst_at_sleep_enable(bool enable) { - PMU.lp_cpu_pwr0.lp_cpu_slp_reset_en = enable; + PMU.lp_ext.pwr0.slp_reset_en = enable; } /** @@ -98,7 +98,7 @@ static inline void lp_core_ll_rst_at_sleep_enable(bool enable) */ static inline void lp_core_ll_stall_at_sleep_request(bool enable) { - PMU.lp_cpu_pwr0.lp_cpu_slp_stall_en = enable; + PMU.lp_ext.pwr0.slp_stall_en = enable; } /** @@ -108,7 +108,7 @@ static inline void lp_core_ll_stall_at_sleep_request(bool enable) */ static inline void lp_core_ll_set_wakeup_source(uint32_t flags) { - PMU.lp_cpu_pwr2.lp_cpu_wakeup_en = flags; + PMU.lp_ext.pwr2.wakeup_en = flags; } /** @@ -116,7 +116,7 @@ static inline void lp_core_ll_set_wakeup_source(uint32_t flags) */ static inline uint32_t lp_core_ll_get_wakeup_source(void) { - return PMU.lp_cpu_pwr2.lp_cpu_wakeup_en; + return PMU.lp_ext.pwr2.wakeup_en; } /** diff --git a/components/hal/esp32p4/include/hal/parlio_ll.h b/components/hal/esp32p4/include/hal/parlio_ll.h index 21a543f995c1..cc070cf95b9d 100644 --- a/components/hal/esp32p4/include/hal/parlio_ll.h +++ b/components/hal/esp32p4/include/hal/parlio_ll.h @@ -126,38 +126,6 @@ static inline void parlio_ll_rx_set_clock_source(parl_io_dev_t *dev, parlio_ll_c /// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance #define parlio_ll_rx_set_clock_source(...) (void)__DECLARE_RCC_ATOMIC_ENV; parlio_ll_rx_set_clock_source(__VA_ARGS__) -/** - * @brief Get the clock source for the RX unit - * - * @param dev Parallel IO register base address - * @return - * parlio_clock_source_t RX core clock source - */ -static inline parlio_ll_clock_source_t parlio_ll_rx_get_clock_source(parl_io_dev_t *dev) -{ - (void)dev; - uint32_t clk_sel = HP_SYS_CLKRST.peri_clk_ctrl117.reg_parlio_rx_clk_src_sel; - switch (clk_sel) { - case 0: - return PARLIO_LL_CLK_SRC_XTAL; - case 1: - return PARLIO_LL_CLK_SRC_RC_FAST; - case 2: - return PARLIO_LL_CLK_SRC_PLL_F160M; - case 3: - return PARLIO_LL_CLK_SRC_PAD; - default: // unsupported clock source - HAL_ASSERT(false); - break; - } - return PARLIO_LL_CLK_SRC_XTAL; -} - - -/// 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_ATOMIC_ENV variable in advance -#define parlio_ll_rx_get_clock_source(...) (void)__DECLARE_RCC_ATOMIC_ENV; parlio_ll_rx_get_clock_source(__VA_ARGS__) - /** * @brief Set the clock divider for the RX unit * @@ -199,6 +167,7 @@ static inline void parlio_ll_rx_reset_clock(parl_io_dev_t *dev) * @param dev Parallel IO register base address * @param en True to enable, False to disable */ +__attribute__((always_inline)) static inline void parlio_ll_rx_enable_clock(parl_io_dev_t *dev, bool en) { (void)dev; @@ -227,6 +196,7 @@ static inline void parlio_ll_rx_set_eof_condition(parl_io_dev_t *dev, parlio_ll_ * @param dev Parallel IO register base address * @param en True to start, False to stop */ +__attribute__((always_inline)) static inline void parlio_ll_rx_start(parl_io_dev_t *dev, bool en) { dev->rx_start_cfg.rx_start = en; @@ -479,37 +449,6 @@ static inline void parlio_ll_tx_set_clock_source(parl_io_dev_t *dev, parlio_ll_c /// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance #define parlio_ll_tx_set_clock_source(...) (void)__DECLARE_RCC_ATOMIC_ENV; parlio_ll_tx_set_clock_source(__VA_ARGS__) -/** - * @brief Get the clock source for the TX unit - * - * @param dev Parallel IO register base address - * @return - * parlio_clock_source_t TX core clock source - */ -static inline parlio_ll_clock_source_t parlio_ll_tx_get_clock_source(parl_io_dev_t *dev) -{ - (void)dev; - uint32_t clk_sel = HP_SYS_CLKRST.peri_clk_ctrl118.reg_parlio_tx_clk_src_sel; - switch (clk_sel) { - case 0: - return PARLIO_LL_CLK_SRC_XTAL; - case 1: - return PARLIO_LL_CLK_SRC_RC_FAST; - case 2: - return PARLIO_LL_CLK_SRC_PLL_F160M; - case 3: - return PARLIO_LL_CLK_SRC_PAD; - default: // unsupported clock source - HAL_ASSERT(false); - break; - } - return PARLIO_LL_CLK_SRC_XTAL; -} - -/// 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_ATOMIC_ENV variable in advance -#define parlio_ll_tx_get_clock_source(...) (void)__DECLARE_RCC_ATOMIC_ENV; parlio_ll_tx_get_clock_source(__VA_ARGS__) - /** * @brief Set the clock divider for the TX unit * diff --git a/components/hal/esp32p4/include/hal/pmu_hal.h b/components/hal/esp32p4/include/hal/pmu_hal.h new file mode 100644 index 000000000000..724e8f741df1 --- /dev/null +++ b/components/hal/esp32p4/include/hal/pmu_hal.h @@ -0,0 +1,45 @@ +/* + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +// The HAL layer for PMU + +#pragma once + +#include "soc/soc_caps.h" +#include "hal/pmu_ll.h" +#include "hal/pmu_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + pmu_dev_t *dev; +} pmu_hal_context_t; + +void pmu_hal_hp_set_digital_power_up_wait_cycle(pmu_hal_context_t *hal, uint32_t power_supply_wait_cycle, uint32_t power_up_wait_cycle); + +uint32_t pmu_hal_hp_get_digital_power_up_wait_cycle(pmu_hal_context_t *hal); + +void pmu_hal_lp_set_digital_power_up_wait_cycle(pmu_hal_context_t *hal, uint32_t power_supply_wait_cycle, uint32_t power_up_wait_cycle); + +uint32_t pmu_hal_lp_get_digital_power_up_wait_cycle(pmu_hal_context_t *hal); + +void pmu_hal_hp_set_sleep_active_backup_enable(pmu_hal_context_t *hal); + +void pmu_hal_hp_set_sleep_active_backup_disable(pmu_hal_context_t *hal); + +void pmu_hal_hp_set_sleep_modem_backup_enable(pmu_hal_context_t *hal); + +void pmu_hal_hp_set_sleep_modem_backup_disable(pmu_hal_context_t *hal); + +void pmu_hal_hp_set_modem_active_backup_enable(pmu_hal_context_t *hal); + +void pmu_hal_hp_set_modem_active_backup_disable(pmu_hal_context_t *hal); + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32p4/include/hal/pmu_ll.h b/components/hal/esp32p4/include/hal/pmu_ll.h index 1b898aee3197..cdf992f51f97 100644 --- a/components/hal/esp32p4/include/hal/pmu_ll.h +++ b/components/hal/esp32p4/include/hal/pmu_ll.h @@ -4,8 +4,9 @@ * SPDX-License-Identifier: Apache-2.0 */ -// The LL layer for ESP32-C6 PMU register operations +// The LL layer for ESP32-P4 PMU register operations +// TODO: IDF-5731 #pragma once #include @@ -20,14 +21,675 @@ extern "C" { #endif +/** + * @brief Set the power domain that needs to be powered down in the digital power + * + * @param hw Beginning address of the peripheral registers. + * @param mode The pmu mode + * @param flag Digital power domain flag + * + * @return None + */ +FORCE_INLINE_ATTR void pmu_ll_hp_set_dig_power(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t flag) +{ + hw->hp_sys[mode].dig_power.val = flag; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_icg_func(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t icg_func) +{ + hw->hp_sys[mode].icg_func = icg_func; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_icg_apb(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t bitmap) +{ + hw->hp_sys[mode].icg_apb = bitmap; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_icg_modem(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t code) +{ + hw->hp_sys[mode].icg_modem.code = code; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_power_detect_bypass_enable(pmu_dev_t *hw, pmu_hp_mode_t mode, bool bypass_en) +{ + hw->hp_sys[mode].syscntl.power_det_bypass = bypass_en; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_uart_wakeup_enable(pmu_dev_t *hw, pmu_hp_mode_t mode, bool wakeup_en) +{ + hw->hp_sys[mode].syscntl.uart_wakeup_en = wakeup_en; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_hold_all_lp_pad(pmu_dev_t *hw, pmu_hp_mode_t mode, bool hold_all) +{ + hw->hp_sys[mode].syscntl.lp_pad_hold_all = hold_all; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_hold_all_hp_pad(pmu_dev_t *hw, pmu_hp_mode_t mode, bool hold_all) +{ + hw->hp_sys[mode].syscntl.hp_pad_hold_all = hold_all; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_dig_pad_slp_sel(pmu_dev_t *hw, pmu_hp_mode_t mode, bool slp_sel) +{ + hw->hp_sys[mode].syscntl.dig_pad_slp_sel = slp_sel; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_pause_watchdog(pmu_dev_t *hw, pmu_hp_mode_t mode, bool pause_wdt) +{ + hw->hp_sys[mode].syscntl.dig_pause_wdt = pause_wdt; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_cpu_stall(pmu_dev_t *hw, pmu_hp_mode_t mode, bool cpu_stall) +{ + hw->hp_sys[mode].syscntl.dig_cpu_stall = cpu_stall; +} + +/** + * @brief Set the power domain that needs to be powered down in the clock power + * + * @param hw Beginning address of the peripheral registers. + * @param mode The pmu mode + * @param flag Clock power domain flag + * + * @return None + */ +FORCE_INLINE_ATTR void pmu_ll_hp_set_clk_power(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t xpd_flag) +{ + hw->hp_sys[mode].clk_power.val = xpd_flag; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_xtal_xpd(pmu_dev_t *hw, pmu_hp_mode_t mode, bool xpd_xtal) +{ + hw->hp_sys[mode].xtal.xpd_xtal = xpd_xtal; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_dcm_mode(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t dcm_mode) +{ + hw->hp_sys[mode].bias.dcm_mode = mode; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_bias_xpd(pmu_dev_t *hw, pmu_hp_mode_t mode, bool xpd_bias) +{ + hw->hp_sys[mode].bias.xpd_bias = xpd_bias; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_dbg_atten(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t value) +{ + hw->hp_sys[mode].bias.dbg_atten = value; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_current_power_off(pmu_dev_t *hw, pmu_hp_mode_t mode, bool off) +{ + hw->hp_sys[mode].bias.pd_cur = off; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_bias_sleep_enable(pmu_dev_t *hw, pmu_hp_mode_t mode, bool en) +{ + hw->hp_sys[mode].bias.bias_sleep = en; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_retention_param(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t param) +{ + hw->hp_sys[mode].backup.val = param; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_sleep_to_active_backup_enable(pmu_dev_t *hw) +{ + hw->hp_sys[PMU_MODE_HP_ACTIVE].backup.hp_sleep2active_backup_en = 1; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_sleep_to_active_backup_disable(pmu_dev_t *hw) +{ + hw->hp_sys[PMU_MODE_HP_ACTIVE].backup.hp_sleep2active_backup_en = 0; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_modem_to_active_backup_enable(pmu_dev_t *hw) +{ + hw->hp_sys[PMU_MODE_HP_ACTIVE].backup.hp_modem2active_backup_en = 1; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_modem_to_active_backup_disable(pmu_dev_t *hw) +{ + hw->hp_sys[PMU_MODE_HP_ACTIVE].backup.hp_modem2active_backup_en = 0; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_active_to_sleep_backup_enable(pmu_dev_t *hw) +{ + hw->hp_sys[PMU_MODE_HP_SLEEP].backup.hp_active2sleep_backup_en = 1; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_active_to_sleep_backup_disable(pmu_dev_t *hw) +{ + hw->hp_sys[PMU_MODE_HP_SLEEP].backup.hp_active2sleep_backup_en = 0; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_modem_to_sleep_backup_enable(pmu_dev_t *hw) +{ + hw->hp_sys[PMU_MODE_HP_SLEEP].backup.hp_modem2sleep_backup_en = 1; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_modem_to_sleep_backup_disable(pmu_dev_t *hw) +{ + hw->hp_sys[PMU_MODE_HP_SLEEP].backup.hp_modem2sleep_backup_en = 0; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_backup_icg_func(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t icg_func) +{ + hw->hp_sys[mode].backup_clk = icg_func; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_sysclk_nodiv(pmu_dev_t *hw, pmu_hp_mode_t mode, bool sysclk_nodiv) +{ + hw->hp_sys[mode].sysclk.dig_sysclk_nodiv = sysclk_nodiv; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_icg_sysclk_enable(pmu_dev_t *hw, pmu_hp_mode_t mode, bool icg_sysclk_en) +{ + hw->hp_sys[mode].sysclk.icg_sysclk_en = icg_sysclk_en; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_sysclk_slp_sel(pmu_dev_t *hw, pmu_hp_mode_t mode, bool slp_sel) +{ + hw->hp_sys[mode].sysclk.sysclk_slp_sel = slp_sel; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_icg_sysclk_slp_sel(pmu_dev_t *hw, pmu_hp_mode_t mode, bool slp_sel) +{ + hw->hp_sys[mode].sysclk.icg_slp_sel = slp_sel; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_dig_sysclk(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t sysclk_sel) +{ + hw->hp_sys[mode].sysclk.dig_sysclk_sel = sysclk_sel; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_regulator_sleep_logic_xpd(pmu_dev_t *hw, pmu_hp_mode_t mode, bool slp_xpd) +{ + hw->hp_sys[mode].regulator0.slp_logic_xpd = slp_xpd; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_regulator_sleep_memory_xpd(pmu_dev_t *hw, pmu_hp_mode_t mode, bool slp_xpd) +{ + hw->hp_sys[mode].regulator0.slp_mem_xpd = slp_xpd; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_regulator_xpd(pmu_dev_t *hw, pmu_hp_mode_t mode, bool xpd) +{ + hw->hp_sys[mode].regulator0.xpd = xpd; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_regulator_sleep_logic_dbias(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t slp_dbias) +{ + hw->hp_sys[mode].regulator0.slp_logic_dbias = slp_dbias; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_regulator_sleep_memory_dbias(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t slp_dbias) +{ + hw->hp_sys[mode].regulator0.slp_mem_dbias = slp_dbias; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_regulator_dbias(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t dbias) +{ + hw->hp_sys[mode].regulator0.dbias = dbias; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_regulator_driver_bar(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t drv_b) +{ + hw->hp_sys[mode].regulator1.drv_b = drv_b; +} + + +FORCE_INLINE_ATTR void pmu_ll_lp_set_regulator_slp_xpd(pmu_dev_t *hw, pmu_lp_mode_t mode, bool slp_xpd) +{ + hw->lp_sys[mode].regulator0.slp_xpd = slp_xpd; +} + +FORCE_INLINE_ATTR void pmu_ll_lp_set_regulator_xpd(pmu_dev_t *hw, pmu_lp_mode_t mode, bool xpd) +{ + hw->lp_sys[mode].regulator0.xpd = xpd; +} + +FORCE_INLINE_ATTR void pmu_ll_lp_set_regulator_sleep_dbias(pmu_dev_t *hw, pmu_lp_mode_t mode, uint32_t slp_dbias) +{ + hw->lp_sys[mode].regulator0.slp_dbias = slp_dbias; +} + +FORCE_INLINE_ATTR void pmu_ll_lp_set_regulator_dbias(pmu_dev_t *hw, pmu_lp_mode_t mode, uint32_t dbias) +{ + hw->lp_sys[mode].regulator0.dbias = dbias; +} + +FORCE_INLINE_ATTR void pmu_ll_lp_set_regulator_driver_bar(pmu_dev_t *hw, pmu_lp_mode_t mode, uint32_t drv_b) +{ + hw->lp_sys[mode].regulator1.drv_b = drv_b; +} + +FORCE_INLINE_ATTR void pmu_ll_lp_set_xtal_xpd(pmu_dev_t *hw, pmu_lp_mode_t mode, bool xpd_xtal) +{ + HAL_ASSERT(mode == PMU_MODE_LP_SLEEP); + hw->lp_sys[mode].xtal.xpd_xtal = xpd_xtal; +} + + +FORCE_INLINE_ATTR void pmu_ll_lp_set_dig_power(pmu_dev_t *hw, pmu_lp_mode_t mode, uint32_t flag) +{ + hw->lp_sys[mode].dig_power.val = flag; +} + +FORCE_INLINE_ATTR void pmu_ll_lp_set_clk_power(pmu_dev_t *hw, pmu_lp_mode_t mode, uint32_t xpd_flag) +{ + hw->lp_sys[mode].clk_power.val = xpd_flag; +} + +FORCE_INLINE_ATTR uint32_t pmu_ll_lp_get_clk_power(pmu_dev_t *hw, pmu_lp_mode_t mode) +{ + return hw->lp_sys[mode].clk_power.val; +} + +FORCE_INLINE_ATTR void pmu_ll_lp_set_bias_xpd(pmu_dev_t *hw, pmu_lp_mode_t mode, bool xpd_bias) +{ + HAL_ASSERT(mode == PMU_MODE_LP_SLEEP); + hw->lp_sys[mode].bias.xpd_bias = xpd_bias; +} + +FORCE_INLINE_ATTR void pmu_ll_lp_set_dbg_atten(pmu_dev_t *hw, pmu_lp_mode_t mode, uint32_t value) +{ + HAL_ASSERT(mode == PMU_MODE_LP_SLEEP); + hw->lp_sys[mode].bias.dbg_atten = value; +} + +FORCE_INLINE_ATTR void pmu_ll_lp_set_current_power_off(pmu_dev_t *hw, pmu_lp_mode_t mode, bool off) +{ + HAL_ASSERT(mode == PMU_MODE_LP_SLEEP); + hw->lp_sys[mode].bias.pd_cur = off; +} + +FORCE_INLINE_ATTR void pmu_ll_lp_set_bias_sleep_enable(pmu_dev_t *hw, pmu_lp_mode_t mode, bool en) +{ + HAL_ASSERT(mode == PMU_MODE_LP_SLEEP); + hw->lp_sys[mode].bias.bias_sleep = en; +} + + +/****/ +FORCE_INLINE_ATTR void pmu_ll_imm_set_clk_power(pmu_dev_t *hw, uint32_t flag) +{ + hw->imm.clk_power.val = flag; +} + +FORCE_INLINE_ATTR void pmu_ll_imm_set_icg_slp_sel(pmu_dev_t *hw, bool slp_sel) +{ + if (slp_sel) { + hw->imm.sleep_sysclk.tie_high_icg_slp_sel = 1; + } else { + hw->imm.sleep_sysclk.tie_low_icg_slp_sel = 1; + } +} + +FORCE_INLINE_ATTR void pmu_ll_imm_update_dig_sysclk_sel(pmu_dev_t *hw, bool update) +{ + hw->imm.sleep_sysclk.update_dig_sysclk_sel = update; +} + +FORCE_INLINE_ATTR void pmu_ll_imm_update_dig_icg_switch(pmu_dev_t *hw, bool update) +{ + hw->imm.sleep_sysclk.update_dig_icg_switch = update; +} + +FORCE_INLINE_ATTR void pmu_ll_imm_update_dig_icg_func(pmu_dev_t *hw, bool icg_func_update) +{ + hw->imm.hp_func_icg.update_dig_icg_func_en = icg_func_update; +} + +FORCE_INLINE_ATTR void pmu_ll_imm_update_dig_icg_apb(pmu_dev_t *hw, bool icg_apb_update) +{ + hw->imm.hp_apb_icg.update_dig_icg_apb_en = icg_apb_update; +} + +FORCE_INLINE_ATTR void pmu_ll_imm_update_dig_icg_modem_code(pmu_dev_t *hw, bool icg_modem_update) +{ + hw->imm.modem_icg.update_dig_icg_modem_en = icg_modem_update; +} + +FORCE_INLINE_ATTR void pmu_ll_imm_set_lp_rootclk_sel(pmu_dev_t *hw, bool rootclk_sel) +{ + if (rootclk_sel) { + hw->imm.lp_icg.tie_high_lp_rootclk_sel = 1; + } else { + hw->imm.lp_icg.tie_low_lp_rootclk_sel = 1; + } +} + +FORCE_INLINE_ATTR void pmu_ll_imm_set_hp_pad_hold_all(pmu_dev_t *hw, bool hold_all) +{ + if (hold_all) { + hw->imm.pad_hold_all.tie_high_hp_pad_hold_all = 1; + } else { + hw->imm.pad_hold_all.tie_low_hp_pad_hold_all = 1; + } +} + +FORCE_INLINE_ATTR void pmu_ll_imm_set_lp_pad_hold_all(pmu_dev_t *hw, bool hold_all) +{ + if (hold_all) { + hw->imm.pad_hold_all.tie_high_lp_pad_hold_all = 1; + } else { + hw->imm.pad_hold_all.tie_low_lp_pad_hold_all = 1; + } +} + +/*** */ +FORCE_INLINE_ATTR void pmu_ll_hp_set_power_force_reset(pmu_dev_t *hw, pmu_hp_power_domain_t domain, bool rst) +{ + hw->power.hp_pd[domain].force_reset = rst; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_power_force_isolate(pmu_dev_t *hw, pmu_hp_power_domain_t domain, bool iso) +{ + hw->power.hp_pd[domain].force_iso = iso; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_power_force_power_up(pmu_dev_t *hw, pmu_hp_power_domain_t domain, bool fpu) +{ + hw->power.hp_pd[domain].force_pu = fpu; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_power_force_no_reset(pmu_dev_t *hw, pmu_hp_power_domain_t domain, bool no_rst) +{ + hw->power.hp_pd[domain].force_no_reset = no_rst; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_power_force_no_isolate(pmu_dev_t *hw, pmu_hp_power_domain_t domain, bool no_iso) +{ + hw->power.hp_pd[domain].force_no_iso = no_iso; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_power_force_power_down(pmu_dev_t *hw, pmu_hp_power_domain_t domain, bool fpd) +{ + hw->power.hp_pd[domain].force_pd = fpd; +} + +FORCE_INLINE_ATTR void pmu_ll_lp_set_power_force_reset(pmu_dev_t *hw, bool rst) +{ + hw->power.lp_peri.force_reset = rst; +} + +FORCE_INLINE_ATTR void pmu_ll_lp_set_power_force_isolate(pmu_dev_t *hw, bool iso) +{ + hw->power.lp_peri.force_iso = iso; +} + +FORCE_INLINE_ATTR void pmu_ll_lp_set_power_force_power_up(pmu_dev_t *hw, bool fpu) +{ + hw->power.lp_peri.force_pu = fpu; +} + +FORCE_INLINE_ATTR void pmu_ll_lp_set_power_force_no_reset(pmu_dev_t *hw, bool no_rst) +{ + hw->power.lp_peri.force_no_reset = no_rst; +} + +FORCE_INLINE_ATTR void pmu_ll_lp_set_power_force_no_isolate(pmu_dev_t *hw, bool no_iso) +{ + hw->power.lp_peri.force_no_iso = no_iso; +} + +FORCE_INLINE_ATTR void pmu_ll_lp_set_power_force_power_down(pmu_dev_t *hw, bool fpd) +{ + hw->power.lp_peri.force_pd = fpd; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_memory_isolate(pmu_dev_t *hw, uint32_t iso) +{ + // hw->power.mem_cntl.force_hp_mem_iso = iso; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_memory_power_down(pmu_dev_t *hw, uint32_t fpd) +{ + // hw->power.mem_cntl.force_hp_mem_pd = fpd; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_memory_no_isolate(pmu_dev_t *hw, uint32_t no_iso) +{ + // hw->power.mem_cntl.force_hp_mem_no_iso = no_iso; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_memory_power_up(pmu_dev_t *hw, uint32_t fpu) +{ + // hw->power.mem_cntl.force_hp_mem_pu = fpu; +} + +/*** */ +FORCE_INLINE_ATTR void pmu_ll_hp_set_sleep_enable(pmu_dev_t *hw) +{ + hw->wakeup.cntl0.sleep_req = 1; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_reject_enable(pmu_dev_t *hw, uint32_t reject) +{ + hw->wakeup.cntl1.sleep_reject_ena = reject; + hw->wakeup.cntl1.slp_reject_en = 1; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_reject_disable(pmu_dev_t *hw) +{ + hw->wakeup.cntl1.slp_reject_en = 0; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_wakeup_enable(pmu_dev_t *hw, uint32_t wakeup) +{ + hw->wakeup.cntl2 = wakeup; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_sleep_protect_mode(pmu_dev_t *hw, int mode) +{ + hw->wakeup.cntl3.sleep_prt_sel = mode; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_min_sleep_cycle(pmu_dev_t *hw, uint32_t slow_clk_cycle) +{ + hw->wakeup.cntl3.hp_min_slp_val = slow_clk_cycle; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_clear_reject_cause(pmu_dev_t *hw) +{ + hw->wakeup.cntl4.slp_reject_cause_clr = 1; +} + +FORCE_INLINE_ATTR bool pmu_ll_hp_is_sleep_wakeup(pmu_dev_t *hw) +{ + return (hw->hp_ext.int_raw.wakeup == 1); +} + +FORCE_INLINE_ATTR bool pmu_ll_hp_is_sleep_reject(pmu_dev_t *hw) +{ + return (hw->hp_ext.int_raw.reject == 1); +} + +FORCE_INLINE_ATTR void pmu_ll_hp_clear_wakeup_intr_status(pmu_dev_t *hw) +{ + hw->hp_ext.int_clr.wakeup = 1; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_clear_reject_intr_status(pmu_dev_t *hw) +{ + hw->hp_ext.int_clr.reject = 1; +} + +FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_wakeup_cause(pmu_dev_t *hw) +{ + return hw->wakeup.status0; +} + +FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_reject_cause(pmu_dev_t *hw) +{ + return hw->wakeup.status1; +} + +FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_lite_wakeup_cause(pmu_dev_t *hw) +{ + return hw->wakeup.status2; +} + FORCE_INLINE_ATTR uint32_t pmu_ll_lp_get_interrupt_raw(pmu_dev_t *hw) { - return hw->lp_int_raw.val; + return hw->lp_ext.int_raw.val; } FORCE_INLINE_ATTR void pmu_ll_lp_clear_intsts_mask(pmu_dev_t *hw, uint32_t mask) { - hw->lp_int_raw.val = mask; + hw->lp_ext.int_clr.val = mask; +} + +FORCE_INLINE_ATTR void pmu_ll_lp_set_min_sleep_cycle(pmu_dev_t *hw, uint32_t slow_clk_cycle) +{ + hw->wakeup.cntl3.lp_min_slp_val = slow_clk_cycle; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_modify_icg_cntl_wait_cycle(pmu_dev_t *hw, uint32_t cycle) +{ + hw->hp_ext.clk_cntl.modify_icg_cntl_wait = cycle; +} + +FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_modify_icg_cntl_wait_cycle(pmu_dev_t *hw) +{ + return hw->hp_ext.clk_cntl.modify_icg_cntl_wait; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_switch_icg_cntl_wait_cycle(pmu_dev_t *hw, uint32_t cycle) +{ + hw->hp_ext.clk_cntl.switch_icg_cntl_wait = cycle; +} + +FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_switch_icg_cntl_wait_cycle(pmu_dev_t *hw) +{ + return hw->hp_ext.clk_cntl.switch_icg_cntl_wait; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_digital_power_down_wait_cycle(pmu_dev_t *hw, uint32_t cycle) +{ + hw->power.wait_timer0.powerdown_timer = cycle; +} + +FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_digital_power_down_wait_cycle(pmu_dev_t *hw) +{ + return hw->power.wait_timer0.powerdown_timer; +} + +FORCE_INLINE_ATTR void pmu_ll_lp_set_digital_power_down_wait_cycle(pmu_dev_t *hw, uint32_t cycle) +{ + hw->power.wait_timer1.powerdown_timer = cycle; +} + +FORCE_INLINE_ATTR uint32_t pmu_ll_lp_get_digital_power_down_wait_cycle(pmu_dev_t *hw) +{ + return hw->power.wait_timer1.powerdown_timer; +} + +FORCE_INLINE_ATTR void pmu_ll_lp_set_analog_wait_target_cycle(pmu_dev_t *hw, uint32_t slow_clk_cycle) +{ + hw->wakeup.cntl5.lp_ana_wait_target = slow_clk_cycle; +} + +FORCE_INLINE_ATTR uint32_t pmu_ll_lp_get_analog_wait_target_cycle(pmu_dev_t *hw) +{ + return hw->wakeup.cntl5.lp_ana_wait_target; +} + +FORCE_INLINE_ATTR void pmu_ll_set_modem_wait_target_cycle(pmu_dev_t *hw, uint32_t cycle) +{ + hw->wakeup.cntl5.modem_wait_target = cycle; +} + +FORCE_INLINE_ATTR uint32_t pmu_ll_get_modem_wait_target_cycle(pmu_dev_t *hw) +{ + return hw->wakeup.cntl5.modem_wait_target; +} + +FORCE_INLINE_ATTR void pmu_ll_set_xtal_stable_wait_cycle(pmu_dev_t *hw, uint32_t cycle) +{ + hw->power.clk_wait.wait_xtal_stable = cycle; +} + +FORCE_INLINE_ATTR uint32_t pmu_ll_get_xtal_stable_wait_cycle(pmu_dev_t *hw) +{ + return hw->power.clk_wait.wait_xtal_stable; +} + +FORCE_INLINE_ATTR void pmu_ll_set_pll_stable_wait_cycle(pmu_dev_t *hw, uint32_t cycle) +{ + hw->power.clk_wait.wait_pll_stable = cycle; +} + +FORCE_INLINE_ATTR uint32_t pmu_ll_get_pll_stable_wait_cycle(pmu_dev_t *hw) +{ + return hw->power.clk_wait.wait_pll_stable; +} + +FORCE_INLINE_ATTR void pmu_ll_lp_set_digital_power_supply_wait_cycle(pmu_dev_t *hw, uint32_t cycle) +{ + hw->power.wait_timer1.wait_timer = cycle; +} + +FORCE_INLINE_ATTR uint32_t pmu_ll_lp_get_digital_power_supply_wait_cycle(pmu_dev_t *hw) +{ + return hw->power.wait_timer1.wait_timer; +} + +FORCE_INLINE_ATTR void pmu_ll_lp_set_digital_power_up_wait_cycle(pmu_dev_t *hw, uint32_t cycle) +{ + hw->power.wait_timer1.powerup_timer = cycle; +} + +FORCE_INLINE_ATTR uint32_t pmu_ll_lp_get_digital_power_up_wait_cycle(pmu_dev_t *hw) +{ + return hw->power.wait_timer1.powerup_timer; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_analog_wait_target_cycle(pmu_dev_t *hw, uint32_t cycle) +{ + hw->wakeup.cntl7.ana_wait_target = cycle; +} + +FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_analog_wait_target_cycle(pmu_dev_t *hw) +{ + return hw->wakeup.cntl7.ana_wait_target; +} + +FORCE_INLINE_ATTR uint32_t pmu_ll_hp_set_lite_wakeup_enable(pmu_dev_t *hw, bool wakeup_en) +{ + return hw->wakeup.cntl8.lp_lite_wakeup_ena = wakeup_en; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_digital_power_supply_wait_cycle(pmu_dev_t *hw, uint32_t cycle) +{ + hw->power.wait_timer0.wait_timer = cycle; +} + +FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_digital_power_supply_wait_cycle(pmu_dev_t *hw) +{ + return hw->power.wait_timer0.wait_timer; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_digital_power_up_wait_cycle(pmu_dev_t *hw, uint32_t cycle) +{ + hw->power.wait_timer0.powerup_timer = cycle; +} + +FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_digital_power_up_wait_cycle(pmu_dev_t *hw) +{ + return hw->power.wait_timer0.powerup_timer; +} + +FORCE_INLINE_ATTR void pmu_ll_set_dcdc_force_power_up(pmu_dev_t *hw, bool fpu) +{ + hw->power.dcdc_switch.force_pu = fpu; +} + +FORCE_INLINE_ATTR void pmu_ll_set_dcdc_force_power_down(pmu_dev_t *hw, bool fpd) +{ + hw->power.dcdc_switch.force_pd = fpd; } #ifdef __cplusplus diff --git a/components/hal/esp32p4/include/hal/regi2c_ctrl_ll.h b/components/hal/esp32p4/include/hal/regi2c_ctrl_ll.h index c4d7e26646dd..5647164b2398 100644 --- a/components/hal/esp32p4/include/hal/regi2c_ctrl_ll.h +++ b/components/hal/esp32p4/include/hal/regi2c_ctrl_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -16,34 +16,30 @@ extern "C" { #endif -//TODO: IDF-7526 - /** - * @brief Start BBPLL self-calibration + * @brief Start CPLL self-calibration */ -static inline __attribute__((always_inline)) void regi2c_ctrl_ll_bbpll_calibration_start(void) +static inline __attribute__((always_inline)) void regi2c_ctrl_ll_cpll_calibration_start(void) { - REG_CLR_BIT(I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_HIGH); - REG_SET_BIT(I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_LOW); + CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_ANA_PLL_CTRL0_REG, HP_SYS_CLKRST_REG_CPU_PLL_CAL_STOP); } /** - * @brief Stop BBPLL self-calibration + * @brief Stop CPLL self-calibration */ -static inline __attribute__((always_inline)) void regi2c_ctrl_ll_bbpll_calibration_stop(void) +static inline __attribute__((always_inline)) void regi2c_ctrl_ll_cpll_calibration_stop(void) { - REG_CLR_BIT(I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_LOW); - REG_SET_BIT(I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_HIGH); + SET_PERI_REG_MASK(HP_SYS_CLKRST_ANA_PLL_CTRL0_REG, HP_SYS_CLKRST_REG_CPU_PLL_CAL_STOP); } /** - * @brief Check whether BBPLL calibration is done + * @brief Check whether CPLL calibration is done * * @return True if calibration is done; otherwise false */ -static inline __attribute__((always_inline)) bool regi2c_ctrl_ll_bbpll_calibration_is_done(void) +static inline __attribute__((always_inline)) bool regi2c_ctrl_ll_cpll_calibration_is_done(void) { - return REG_GET_BIT(I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_CAL_DONE); + return REG_GET_BIT(HP_SYS_CLKRST_ANA_PLL_CTRL0_REG, HP_SYS_CLKRST_REG_CPU_PLL_CAL_END); } /** diff --git a/components/hal/esp32p4/include/hal/rtc_io_ll.h b/components/hal/esp32p4/include/hal/rtc_io_ll.h index 197fb0c2de86..763e8f2eeee2 100644 --- a/components/hal/esp32p4/include/hal/rtc_io_ll.h +++ b/components/hal/esp32p4/include/hal/rtc_io_ll.h @@ -305,7 +305,7 @@ static inline void rtcio_ll_force_hold_disable(int rtcio_num) */ static inline void rtcio_ll_force_hold_all(void) { - PMU.imm_pad_hold_all.tie_high_lp_pad_hold_all = 1; + PMU.imm.pad_hold_all.tie_high_lp_pad_hold_all = 1; } /** @@ -315,7 +315,7 @@ static inline void rtcio_ll_force_hold_all(void) */ static inline void rtcio_ll_force_unhold_all(void) { - PMU.imm_pad_hold_all.tie_low_lp_pad_hold_all = 1; + PMU.imm.pad_hold_all.tie_low_lp_pad_hold_all = 1; } /** diff --git a/components/hal/esp32p4/include/hal/sdmmc_ll.h b/components/hal/esp32p4/include/hal/sdmmc_ll.h index 4a447433af7d..4397c10fbeb7 100644 --- a/components/hal/esp32p4/include/hal/sdmmc_ll.h +++ b/components/hal/esp32p4/include/hal/sdmmc_ll.h @@ -87,9 +87,9 @@ static inline void sdmmc_ll_select_clk_source(sdmmc_dev_t *hw, soc_periph_sdmmc_ case SDMMC_CLK_SRC_PLL160M: clk_val = 0; break; - case SDMMC_CLK_SRC_PLL200M: - clk_val = 1; - break; + // case SDMMC_CLK_SRC_PLL200M: // TODO: IDF-8886 + // clk_val = 1; + // break; default: HAL_ASSERT(false); break; diff --git a/components/hal/esp32p4/include/hal/touch_sensor_ll.h b/components/hal/esp32p4/include/hal/touch_sensor_ll.h index 117ff8d2e1d6..7f15fad2b579 100644 --- a/components/hal/esp32p4/include/hal/touch_sensor_ll.h +++ b/components/hal/esp32p4/include/hal/touch_sensor_ll.h @@ -126,7 +126,7 @@ static inline void touch_ll_get_charge_times(uint8_t sampler_id, uint16_t *charg static inline void touch_ll_set_measure_interval_ticks(uint16_t interval_ticks) { // touch sensor sleep cycle Time = interval_ticks / RTC_SLOW_CLK - HAL_FORCE_MODIFY_U32_REG_FIELD(PMU.touch_pwr_cntl, touch_sleep_cycles, interval_ticks); + HAL_FORCE_MODIFY_U32_REG_FIELD(PMU.touch_pwr_cntl, sleep_cycles, interval_ticks); } /** @@ -136,7 +136,7 @@ static inline void touch_ll_set_measure_interval_ticks(uint16_t interval_ticks) */ static inline void touch_ll_get_measure_interval_ticks(uint16_t *interval_ticks) { - *interval_ticks = HAL_FORCE_READ_U32_REG_FIELD(PMU.touch_pwr_cntl, touch_sleep_cycles); + *interval_ticks = HAL_FORCE_READ_U32_REG_FIELD(PMU.touch_pwr_cntl, sleep_cycles); } /** @@ -211,7 +211,7 @@ static inline void touch_ll_start_fsm_repeated_timer(bool is_sleep) */ touch_ll_force_done_curr_measurement(); if (is_sleep) { - PMU.touch_pwr_cntl.touch_sleep_timer_en = 1; + PMU.touch_pwr_cntl.sleep_timer_en = 1; } else { LP_ANA_PERI.touch_mux0.touch_start_en = 1; } @@ -225,7 +225,7 @@ static inline void touch_ll_start_fsm_repeated_timer(bool is_sleep) static inline void touch_ll_stop_fsm_repeated_timer(bool is_sleep) { if (is_sleep) { - PMU.touch_pwr_cntl.touch_sleep_timer_en = 0; + PMU.touch_pwr_cntl.sleep_timer_en = 0; } else { LP_ANA_PERI.touch_mux0.touch_start_en = 0; } diff --git a/components/hal/esp32p4/pmu_hal.c b/components/hal/esp32p4/pmu_hal.c new file mode 100644 index 000000000000..c82388f1be4f --- /dev/null +++ b/components/hal/esp32p4/pmu_hal.c @@ -0,0 +1,63 @@ + +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +// The HAL layer for PMU (ESP32-P4 specific part) + +// TODO: IDF-5731 + +#include "soc/soc.h" +#include "esp_attr.h" +#include "hal/pmu_hal.h" +#include "hal/pmu_types.h" + +void IRAM_ATTR pmu_hal_hp_set_digital_power_up_wait_cycle(pmu_hal_context_t *hal, uint32_t power_supply_wait_cycle, uint32_t power_up_wait_cycle) +{ + pmu_ll_hp_set_digital_power_supply_wait_cycle(hal->dev, power_supply_wait_cycle); + pmu_ll_hp_set_digital_power_up_wait_cycle(hal->dev, power_up_wait_cycle); +} + +uint32_t IRAM_ATTR pmu_hal_hp_get_digital_power_up_wait_cycle(pmu_hal_context_t *hal) +{ + uint32_t power_supply_wait_cycle = pmu_ll_hp_get_digital_power_supply_wait_cycle(hal->dev); + uint32_t power_up_wait_cycle = pmu_ll_hp_get_digital_power_up_wait_cycle(hal->dev); + return power_supply_wait_cycle + power_up_wait_cycle; +} + +void IRAM_ATTR pmu_hal_lp_set_digital_power_up_wait_cycle(pmu_hal_context_t *hal, uint32_t power_supply_wait_cycle, uint32_t power_up_wait_cycle) +{ + pmu_ll_lp_set_digital_power_supply_wait_cycle(hal->dev, power_supply_wait_cycle); + pmu_ll_lp_set_digital_power_up_wait_cycle(hal->dev, power_up_wait_cycle); +} + +uint32_t IRAM_ATTR pmu_hal_lp_get_digital_power_up_wait_cycle(pmu_hal_context_t *hal) +{ + uint32_t power_supply_wait_cycle = pmu_ll_lp_get_digital_power_supply_wait_cycle(hal->dev); + uint32_t power_up_wait_cycle = pmu_ll_lp_get_digital_power_up_wait_cycle(hal->dev); + return power_supply_wait_cycle + power_up_wait_cycle; +} + +void pmu_hal_hp_set_sleep_active_backup_enable(pmu_hal_context_t *hal) +{ + pmu_ll_hp_set_active_to_sleep_backup_enable(hal->dev); + pmu_ll_hp_set_sleep_to_active_backup_enable(hal->dev); +} + +void pmu_hal_hp_set_sleep_active_backup_disable(pmu_hal_context_t *hal) +{ + pmu_ll_hp_set_sleep_to_active_backup_disable(hal->dev); + pmu_ll_hp_set_active_to_sleep_backup_disable(hal->dev); +} + +void pmu_hal_hp_set_modem_active_backup_enable(pmu_hal_context_t *hal) +{ + pmu_ll_hp_set_modem_to_active_backup_enable(hal->dev); +} + +void pmu_hal_hp_set_modem_active_backup_disable(pmu_hal_context_t *hal) +{ + pmu_ll_hp_set_modem_to_active_backup_disable(hal->dev); +} diff --git a/components/hal/esp32s2/clk_tree_hal.c b/components/hal/esp32s2/clk_tree_hal.c index cb7978dbee58..a301028c6ceb 100644 --- a/components/hal/esp32s2/clk_tree_hal.c +++ b/components/hal/esp32s2/clk_tree_hal.c @@ -57,7 +57,7 @@ uint32_t clk_hal_cpu_get_freq_hz(void) } } -uint32_t clk_hal_ahb_get_freq_hz(void) +static uint32_t clk_hal_ahb_get_freq_hz(void) { // AHB_CLK path is highly dependent on CPU_CLK path switch (clk_ll_cpu_get_src()) { diff --git a/components/hal/esp32s2/include/hal/usb_phy_ll.h b/components/hal/esp32s2/include/hal/usb_fsls_phy_ll.h similarity index 73% rename from components/hal/esp32s2/include/hal/usb_phy_ll.h rename to components/hal/esp32s2/include/hal/usb_fsls_phy_ll.h index 9c561cbb4019..91de90b145de 100644 --- a/components/hal/esp32s2/include/hal/usb_phy_ll.h +++ b/components/hal/esp32s2/include/hal/usb_fsls_phy_ll.h @@ -21,7 +21,7 @@ extern "C" { * * @param hw Start address of the USB Wrap registers */ -static inline void usb_phy_ll_int_otg_enable(usb_wrap_dev_t *hw) +static inline void usb_fsls_phy_ll_int_otg_enable(usb_wrap_dev_t *hw) { hw->otg_conf.phy_sel = 0; } @@ -31,7 +31,7 @@ static inline void usb_phy_ll_int_otg_enable(usb_wrap_dev_t *hw) * * @param hw Start address of the USB Wrap registers */ -static inline void usb_phy_ll_ext_otg_enable(usb_wrap_dev_t *hw) +static inline void usb_fsls_phy_ll_ext_otg_enable(usb_wrap_dev_t *hw) { //Enable external PHY hw->otg_conf.phy_sel = 1; @@ -46,7 +46,7 @@ static inline void usb_phy_ll_ext_otg_enable(usb_wrap_dev_t *hw) * @param dm_pu D- pullup load * @param dm_pd D- pulldown load */ -static inline void usb_phy_ll_int_load_conf(usb_wrap_dev_t *hw, bool dp_pu, bool dp_pd, bool dm_pu, bool dm_pd) +static inline void usb_fsls_phy_ll_int_load_conf(usb_wrap_dev_t *hw, bool dp_pu, bool dp_pd, bool dm_pu, bool dm_pd) { usb_wrap_otg_conf_reg_t conf; conf.val = hw->otg_conf.val; @@ -63,7 +63,7 @@ static inline void usb_phy_ll_int_load_conf(usb_wrap_dev_t *hw, bool dp_pu, bool * @param hw Start address of the USB Wrap registers * @param pad_en Enable the PHY control to D+/D- pad */ -static inline void usb_phy_ll_usb_wrap_pad_enable(usb_wrap_dev_t *hw, bool pad_en) +static inline void usb_fsls_phy_ll_usb_wrap_pad_enable(usb_wrap_dev_t *hw, bool pad_en) { hw->otg_conf.pad_enable = pad_en; } @@ -74,7 +74,7 @@ static inline void usb_phy_ll_usb_wrap_pad_enable(usb_wrap_dev_t *hw, bool pad_e * @param hw Start address of the USB Wrap registers * @param en Whether to enable the internal PHY's test mode */ -static inline void usb_phy_ll_int_enable_test_mode(usb_wrap_dev_t *hw, bool en) +static inline void usb_fsls_phy_ll_int_enable_test_mode(usb_wrap_dev_t *hw, bool en) { if (en) { // Clear USB_WRAP_TEST_CONF_REG @@ -92,25 +92,25 @@ static inline void usb_phy_ll_int_enable_test_mode(usb_wrap_dev_t *hw, bool en) * Enable the bus clock for USB Wrap module * @param clk_en True if enable the clock of USB Wrap module */ -FORCE_INLINE_ATTR void usb_phy_ll_usb_wrap_enable_bus_clock(bool clk_en) +FORCE_INLINE_ATTR void usb_fsls_phy_ll_usb_wrap_enable_bus_clock(bool clk_en) { REG_SET_FIELD(DPORT_PERIP_CLK_EN0_REG, DPORT_USB_CLK_EN, clk_en); } // SYSTEM.perip_clk_enx are shared registers, so this function must be used in an atomic way -#define usb_phy_ll_usb_wrap_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; usb_phy_ll_usb_wrap_enable_bus_clock(__VA_ARGS__) +#define usb_fsls_phy_ll_usb_wrap_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; usb_fsls_phy_ll_usb_wrap_enable_bus_clock(__VA_ARGS__) /** * @brief Reset the USB Wrap module */ -FORCE_INLINE_ATTR void usb_phy_ll_usb_wrap_reset_register(void) +FORCE_INLINE_ATTR void usb_fsls_phy_ll_usb_wrap_reset_register(void) { REG_SET_FIELD(DPORT_PERIP_RST_EN0_REG, DPORT_USB_RST, 1); REG_SET_FIELD(DPORT_PERIP_RST_EN0_REG, DPORT_USB_RST, 0); } // SYSTEM.perip_clk_enx are shared registers, so this function must be used in an atomic way -#define usb_phy_ll_usb_wrap_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; usb_phy_ll_usb_wrap_reset_register(__VA_ARGS__) +#define usb_fsls_phy_ll_usb_wrap_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; usb_fsls_phy_ll_usb_wrap_reset_register(__VA_ARGS__) #ifdef __cplusplus } diff --git a/components/hal/esp32s3/clk_tree_hal.c b/components/hal/esp32s3/clk_tree_hal.c index 6e62a377a01c..095efc91cf98 100644 --- a/components/hal/esp32s3/clk_tree_hal.c +++ b/components/hal/esp32s3/clk_tree_hal.c @@ -47,7 +47,7 @@ uint32_t clk_hal_cpu_get_freq_hz(void) } } -uint32_t clk_hal_ahb_get_freq_hz(void) +static uint32_t clk_hal_ahb_get_freq_hz(void) { // AHB_CLK path is highly dependent on CPU_CLK path switch (clk_ll_cpu_get_src()) { diff --git a/components/hal/esp32s3/include/hal/usb_phy_ll.h b/components/hal/esp32s3/include/hal/usb_fsls_phy_ll.h similarity index 79% rename from components/hal/esp32s3/include/hal/usb_phy_ll.h rename to components/hal/esp32s3/include/hal/usb_fsls_phy_ll.h index 0045bc13a445..aa4f637913e3 100644 --- a/components/hal/esp32s3/include/hal/usb_phy_ll.h +++ b/components/hal/esp32s3/include/hal/usb_fsls_phy_ll.h @@ -23,7 +23,7 @@ extern "C" { * * @param hw Start address of the USB Wrap registers */ -static inline void usb_phy_ll_int_otg_enable(usb_wrap_dev_t *hw) +static inline void usb_fsls_phy_ll_int_otg_enable(usb_wrap_dev_t *hw) { // USB_OTG use internal PHY hw->otg_conf.phy_sel = 0; @@ -38,7 +38,7 @@ static inline void usb_phy_ll_int_otg_enable(usb_wrap_dev_t *hw) * * @param hw Start address of the USB Wrap registers */ -static inline void usb_phy_ll_ext_otg_enable(usb_wrap_dev_t *hw) +static inline void usb_fsls_phy_ll_ext_otg_enable(usb_wrap_dev_t *hw) { // USB_OTG use external PHY hw->otg_conf.phy_sel = 1; @@ -53,7 +53,7 @@ static inline void usb_phy_ll_ext_otg_enable(usb_wrap_dev_t *hw) * * @param hw Start address of the USB Serial_JTAG registers */ -static inline void usb_phy_ll_int_jtag_enable(usb_serial_jtag_dev_t *hw) +static inline void usb_fsls_phy_ll_int_jtag_enable(usb_serial_jtag_dev_t *hw) { // USB_Serial_JTAG use internal PHY hw->conf0.phy_sel = 0; @@ -74,7 +74,7 @@ static inline void usb_phy_ll_int_jtag_enable(usb_serial_jtag_dev_t *hw) * * @param hw Start address of the USB Serial_JTAG registers */ -static inline void usb_phy_ll_ext_jtag_enable(usb_serial_jtag_dev_t *hw) +static inline void usb_fsls_phy_ll_ext_jtag_enable(usb_serial_jtag_dev_t *hw) { // USB_Serial_JTAG use external PHY hw->conf0.phy_sel = 1; @@ -93,7 +93,7 @@ static inline void usb_phy_ll_ext_jtag_enable(usb_serial_jtag_dev_t *hw) * @param dm_pu D- pullup load * @param dm_pd D- pulldown load */ -static inline void usb_phy_ll_int_load_conf(usb_wrap_dev_t *hw, bool dp_pu, bool dp_pd, bool dm_pu, bool dm_pd) +static inline void usb_fsls_phy_ll_int_load_conf(usb_wrap_dev_t *hw, bool dp_pu, bool dp_pd, bool dm_pu, bool dm_pd) { usb_wrap_otg_conf_reg_t conf; conf.val = hw->otg_conf.val; @@ -112,7 +112,7 @@ static inline void usb_phy_ll_int_load_conf(usb_wrap_dev_t *hw, bool dp_pu, bool * @param hw Start address of the USB Wrap registers * @param pad_en Enable the PHY control to D+/D- pad */ -static inline void usb_phy_ll_usb_wrap_pad_enable(usb_wrap_dev_t *hw, bool pad_en) +static inline void usb_fsls_phy_ll_usb_wrap_pad_enable(usb_wrap_dev_t *hw, bool pad_en) { hw->otg_conf.pad_enable = pad_en; } @@ -123,7 +123,7 @@ static inline void usb_phy_ll_usb_wrap_pad_enable(usb_wrap_dev_t *hw, bool pad_e * @param hw Start address of the USB Wrap registers * @param en Whether to enable the internal PHY's test mode */ -static inline void usb_phy_ll_int_enable_test_mode(usb_wrap_dev_t *hw, bool en) +static inline void usb_fsls_phy_ll_int_enable_test_mode(usb_wrap_dev_t *hw, bool en) { if (en) { // Clear USB_WRAP_TEST_CONF_REG @@ -141,25 +141,25 @@ static inline void usb_phy_ll_int_enable_test_mode(usb_wrap_dev_t *hw, bool en) * Enable the bus clock for USB Wrap module * @param clk_en True if enable the clock of USB Wrap module */ -FORCE_INLINE_ATTR void usb_phy_ll_usb_wrap_enable_bus_clock(bool clk_en) +FORCE_INLINE_ATTR void usb_fsls_phy_ll_usb_wrap_enable_bus_clock(bool clk_en) { SYSTEM.perip_clk_en0.usb_clk_en = clk_en; } // SYSTEM.perip_clk_enx are shared registers, so this function must be used in an atomic way -#define usb_phy_ll_usb_wrap_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; usb_phy_ll_usb_wrap_enable_bus_clock(__VA_ARGS__) +#define usb_fsls_phy_ll_usb_wrap_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; usb_fsls_phy_ll_usb_wrap_enable_bus_clock(__VA_ARGS__) /** * @brief Reset the USB Wrap module */ -FORCE_INLINE_ATTR void usb_phy_ll_usb_wrap_reset_register(void) +FORCE_INLINE_ATTR void usb_fsls_phy_ll_usb_wrap_reset_register(void) { SYSTEM.perip_rst_en0.usb_rst = 1; SYSTEM.perip_rst_en0.usb_rst = 0; } // SYSTEM.perip_clk_enx are shared registers, so this function must be used in an atomic way -#define usb_phy_ll_usb_wrap_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; usb_phy_ll_usb_wrap_reset_register(__VA_ARGS__) +#define usb_fsls_phy_ll_usb_wrap_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; usb_fsls_phy_ll_usb_wrap_reset_register(__VA_ARGS__) #ifdef __cplusplus } diff --git a/components/hal/include/hal/clk_tree_hal.h b/components/hal/include/hal/clk_tree_hal.h index e05ab128c906..7a7d6ace9d46 100644 --- a/components/hal/include/hal/clk_tree_hal.h +++ b/components/hal/include/hal/clk_tree_hal.h @@ -30,13 +30,6 @@ uint32_t clk_hal_soc_root_get_freq_mhz(soc_cpu_clk_src_t cpu_clk_src); */ uint32_t clk_hal_cpu_get_freq_hz(void); -/** - * @brief Get AHB_CLK frequency - * - * @return AHB clock frequency, in Hz. Returns 0 if internal clock configuration is invalid. - */ -uint32_t clk_hal_ahb_get_freq_hz(void); - /** * @brief Get APB_CLK frequency * diff --git a/components/hal/include/hal/parlio_hal.h b/components/hal/include/hal/parlio_hal.h index 69dffbabd031..ec73ab8eacfc 100644 --- a/components/hal/include/hal/parlio_hal.h +++ b/components/hal/include/hal/parlio_hal.h @@ -13,6 +13,7 @@ #pragma once #include +#include "hal/parlio_types.h" #ifdef __cplusplus extern "C" { diff --git a/components/hal/include/hal/parlio_types.h b/components/hal/include/hal/parlio_types.h index 53b99c59aba1..baaeeb4d9d7d 100644 --- a/components/hal/include/hal/parlio_types.h +++ b/components/hal/include/hal/parlio_types.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -58,9 +58,12 @@ typedef soc_periph_parlio_clk_src_t parlio_clock_source_t; /// Maximum data width of TX unit #define PARLIO_TX_UNIT_MAX_DATA_WIDTH SOC_PARLIO_TX_UNIT_MAX_DATA_WIDTH +/// Maximum data width of RX unit +#define PARLIO_RX_UNIT_MAX_DATA_WIDTH SOC_PARLIO_RX_UNIT_MAX_DATA_WIDTH #else typedef int parlio_clock_source_t; #define PARLIO_TX_UNIT_MAX_DATA_WIDTH 0 +#define PARLIO_RX_UNIT_MAX_DATA_WIDTH 0 #endif // SOC_PARLIO_SUPPORTED #ifdef __cplusplus diff --git a/components/hal/include/hal/pmu_types.h b/components/hal/include/hal/pmu_types.h index cd219752324a..30ee06c7058e 100644 --- a/components/hal/include/hal/pmu_types.h +++ b/components/hal/include/hal/pmu_types.h @@ -6,19 +6,22 @@ #pragma once +#include +#include "soc/soc_caps.h" +#include "sdkconfig.h" + #ifdef __cplusplus extern "C" { #endif -#include -#include "soc/soc_caps.h" - /** * @brief PMU modes of HP system */ typedef enum { PMU_MODE_HP_ACTIVE = 0, /*!< PMU in HP_ACTIVE mode */ +#if !CONFIG_IDF_TARGET_ESP32P4 // TODO: IDF-5731 Use a soc caps PMU_MODE_HP_MODEM, /*!< PMU in HP_MODEM mode */ +#endif PMU_MODE_HP_SLEEP, /*!< PMU in HP_SLEEP mode */ PMU_MODE_HP_MAX, } pmu_hp_mode_t; @@ -32,6 +35,7 @@ typedef enum { PMU_MODE_LP_MAX, } pmu_lp_mode_t; +#if !CONFIG_IDF_TARGET_ESP32P4 // TODO: IDF-5731 Use a soc caps typedef enum { PMU_HP_PD_TOP = 0, /*!< Power domain of digital top */ #if SOC_PM_SUPPORT_HP_AON_PD @@ -41,6 +45,15 @@ typedef enum { PMU_HP_PD_RESERVED = 3, /*!< Reserved power domain */ PMU_HP_PD_WIFI = 4, /*!< Power domain of WIFI */ } pmu_hp_power_domain_t; +#else // TODO: check this..... +typedef enum { + PMU_HP_PD_TOP = 0, /* Power domain of digital top */ + PMU_HP_PD_CNNT = 1, /* Power domain of HP CPU */ + PMU_HP_PD_HPMEM = 2, /* HP_MEM */ + PMU_HP_PD_RESERVED, /* Reserved power domain*/ + PMU_HP_PD_MAX +} pmu_hp_power_domain_t; +#endif #ifdef __cplusplus } diff --git a/components/hal/include/hal/usb_phy_hal.h b/components/hal/include/hal/usb_fsls_phy_hal.h similarity index 73% rename from components/hal/include/hal/usb_phy_hal.h rename to components/hal/include/hal/usb_fsls_phy_hal.h index 6312744bff55..5e4915fe7b40 100644 --- a/components/hal/include/hal/usb_phy_hal.h +++ b/components/hal/include/hal/usb_fsls_phy_hal.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -31,7 +31,7 @@ typedef struct { #if SOC_USB_SERIAL_JTAG_SUPPORTED usb_serial_jtag_dev_t *jtag_dev; /**< Pointer to base address of USB Serial JTAG registers */ #endif -} usb_phy_hal_context_t; +} usb_fsls_phy_hal_context_t; /** @@ -39,7 +39,7 @@ typedef struct { * * @param hal Context of the HAL layer */ -void usb_phy_hal_init(usb_phy_hal_context_t *hal); +void usb_fsls_phy_hal_init(usb_fsls_phy_hal_context_t *hal); /** * @brief Configure internal/external PHY for USB_OTG @@ -47,7 +47,7 @@ void usb_phy_hal_init(usb_phy_hal_context_t *hal); * @param hal Context of the HAL layer * @param phy_target USB PHY target */ -void usb_phy_hal_otg_conf(usb_phy_hal_context_t *hal, usb_phy_target_t phy_target); +void usb_fsls_phy_hal_otg_conf(usb_fsls_phy_hal_context_t *hal, usb_phy_target_t phy_target); #if SOC_USB_SERIAL_JTAG_SUPPORTED /** @@ -56,7 +56,7 @@ void usb_phy_hal_otg_conf(usb_phy_hal_context_t *hal, usb_phy_target_t phy_targe * @param hal Context of the HAL layer * @param phy_target USB PHY target */ -void usb_phy_hal_jtag_conf(usb_phy_hal_context_t *hal, usb_phy_target_t phy_target); +void usb_fsls_phy_hal_jtag_conf(usb_fsls_phy_hal_context_t *hal, usb_phy_target_t phy_target); #endif /** @@ -64,7 +64,7 @@ void usb_phy_hal_jtag_conf(usb_phy_hal_context_t *hal, usb_phy_target_t phy_targ * * @param hal Context of the HAL layer */ -void usb_phy_hal_int_load_conf_host(usb_phy_hal_context_t *hal); +void usb_fsls_phy_hal_int_load_conf_host(usb_fsls_phy_hal_context_t *hal); /** * @brief Configure pullup/pulldown loads for the D+/D- as a device @@ -72,7 +72,7 @@ void usb_phy_hal_int_load_conf_host(usb_phy_hal_context_t *hal); * @param hal Context of the HAL layer * @param speed USB speed */ -void usb_phy_hal_int_load_conf_dev(usb_phy_hal_context_t *hal, usb_phy_speed_t speed); +void usb_fsls_phy_hal_int_load_conf_dev(usb_fsls_phy_hal_context_t *hal, usb_phy_speed_t speed); /** * @brief Enable/Disable test mode for internal PHY to mimick host-device disconnection @@ -80,7 +80,7 @@ void usb_phy_hal_int_load_conf_dev(usb_phy_hal_context_t *hal, usb_phy_speed_t s * @param hal Context of the HAL layer * @param disconn Whether to disconnect */ -void usb_phy_hal_int_mimick_disconn(usb_phy_hal_context_t *hal, bool disconn); +void usb_fsls_phy_hal_int_mimick_disconn(usb_fsls_phy_hal_context_t *hal, bool disconn); #endif diff --git a/components/hal/usb_fsls_phy_hal.c b/components/hal/usb_fsls_phy_hal.c new file mode 100644 index 000000000000..7bceb8c364c3 --- /dev/null +++ b/components/hal/usb_fsls_phy_hal.c @@ -0,0 +1,64 @@ +/* + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "hal/usb_fsls_phy_ll.h" +#include "hal/usb_fsls_phy_hal.h" + +void usb_fsls_phy_hal_init(usb_fsls_phy_hal_context_t *hal) +{ + hal->wrap_dev = &USB_WRAP; +#if SOC_USB_SERIAL_JTAG_SUPPORTED + hal->jtag_dev = &USB_SERIAL_JTAG; +#endif +} + +void usb_fsls_phy_hal_otg_conf(usb_fsls_phy_hal_context_t *hal, usb_phy_target_t phy_target) +{ + if (phy_target == USB_PHY_TARGET_EXT) { + usb_fsls_phy_ll_ext_otg_enable(hal->wrap_dev); + } else if (phy_target == USB_PHY_TARGET_INT) { + usb_fsls_phy_ll_usb_wrap_pad_enable(hal->wrap_dev, true); + usb_fsls_phy_ll_int_otg_enable(hal->wrap_dev); + } +} + +#if SOC_USB_SERIAL_JTAG_SUPPORTED +void usb_fsls_phy_hal_jtag_conf(usb_fsls_phy_hal_context_t *hal, usb_phy_target_t phy_target) +{ + if (phy_target == USB_PHY_TARGET_EXT) { + usb_fsls_phy_ll_ext_jtag_enable(hal->jtag_dev); + } else if (phy_target == USB_PHY_TARGET_INT) { + usb_fsls_phy_ll_int_jtag_enable(hal->jtag_dev); + } +} +#endif + +void usb_fsls_phy_hal_int_load_conf_host(usb_fsls_phy_hal_context_t *hal) +{ + // HOST - upstream: dp_pd = 1, dm_pd = 1 + usb_fsls_phy_ll_int_load_conf(hal->wrap_dev, false, true, false, true); +} + +void usb_fsls_phy_hal_int_load_conf_dev(usb_fsls_phy_hal_context_t *hal, usb_phy_speed_t speed) +{ + // DEVICE - downstream + if (speed == USB_PHY_SPEED_LOW) { + // LS: dm_pu = 1 + usb_fsls_phy_ll_int_load_conf(hal->wrap_dev, false, false, true, false); + } else { + // FS: dp_pu = 1 + usb_fsls_phy_ll_int_load_conf(hal->wrap_dev, true, false, false, false); + } +} + +void usb_fsls_phy_hal_int_mimick_disconn(usb_fsls_phy_hal_context_t *hal, bool disconn) +{ + /* + We mimick a disconnect by enabling the internal PHY's test mode, then forcing the output_enable to HIGH. This will: + A HIGH output_enable will cause the received VP and VM to be zero, thus mimicking a disconnection. + */ + usb_fsls_phy_ll_int_enable_test_mode(hal->wrap_dev, disconn); +} diff --git a/components/hal/usb_phy_hal.c b/components/hal/usb_phy_hal.c deleted file mode 100644 index 5a0f83bf7a66..000000000000 --- a/components/hal/usb_phy_hal.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "hal/usb_phy_ll.h" -#include "hal/usb_phy_hal.h" - -void usb_phy_hal_init(usb_phy_hal_context_t *hal) -{ - hal->wrap_dev = &USB_WRAP; -#if SOC_USB_SERIAL_JTAG_SUPPORTED - hal->jtag_dev = &USB_SERIAL_JTAG; -#endif -} - -void usb_phy_hal_otg_conf(usb_phy_hal_context_t *hal, usb_phy_target_t phy_target) -{ - if (phy_target == USB_PHY_TARGET_EXT) { - usb_phy_ll_ext_otg_enable(hal->wrap_dev); - } else if (phy_target == USB_PHY_TARGET_INT) { - usb_phy_ll_usb_wrap_pad_enable(hal->wrap_dev, true); - usb_phy_ll_int_otg_enable(hal->wrap_dev); - } -} - -#if SOC_USB_SERIAL_JTAG_SUPPORTED -void usb_phy_hal_jtag_conf(usb_phy_hal_context_t *hal, usb_phy_target_t phy_target) -{ - if (phy_target == USB_PHY_TARGET_EXT) { - usb_phy_ll_ext_jtag_enable(hal->jtag_dev); - } else if (phy_target == USB_PHY_TARGET_INT) { - usb_phy_ll_int_jtag_enable(hal->jtag_dev); - } -} -#endif - -void usb_phy_hal_int_load_conf_host(usb_phy_hal_context_t *hal) -{ - // HOST - upstream: dp_pd = 1, dm_pd = 1 - usb_phy_ll_int_load_conf(hal->wrap_dev, false, true, false, true); -} - -void usb_phy_hal_int_load_conf_dev(usb_phy_hal_context_t *hal, usb_phy_speed_t speed) -{ - // DEVICE - downstream - if (speed == USB_PHY_SPEED_LOW) { - // LS: dm_pu = 1 - usb_phy_ll_int_load_conf(hal->wrap_dev, false, false, true, false); - } else { - // FS: dp_pu = 1 - usb_phy_ll_int_load_conf(hal->wrap_dev, true, false, false, false); - } -} - -void usb_phy_hal_int_mimick_disconn(usb_phy_hal_context_t *hal, bool disconn) -{ - /* - We mimick a disconnect by enabling the internal PHY's test mode, then forcing the output_enable to HIGH. This will: - A HIGH output_enable will cause the received VP and VM to be zero, thus mimicking a disconnection. - */ - usb_phy_ll_int_enable_test_mode(hal->wrap_dev, disconn); -} diff --git a/components/ieee802154/driver/esp_ieee802154_dev.c b/components/ieee802154/driver/esp_ieee802154_dev.c index 5dc35d56baea..172f51532d89 100644 --- a/components/ieee802154/driver/esp_ieee802154_dev.c +++ b/components/ieee802154/driver/esp_ieee802154_dev.c @@ -151,7 +151,7 @@ static void ieee802154_rx_frame_info_update(void) uint8_t lqi = s_rx_frame[s_rx_index][len]; s_rx_frame_info[s_rx_index].channel = ieee802154_freq_to_channel(ieee802154_ll_get_freq()); - s_rx_frame_info[s_rx_index].rssi = rssi; + s_rx_frame_info[s_rx_index].rssi = rssi + IEEE802154_RSSI_COMPENSATION_VALUE; s_rx_frame_info[s_rx_index].lqi = lqi; s_recent_rx_frame_info_index = s_rx_index; diff --git a/components/ieee802154/test_apps/.build-test-rules.yml b/components/ieee802154/test_apps/.build-test-rules.yml deleted file mode 100644 index 2200b10c864e..000000000000 --- a/components/ieee802154/test_apps/.build-test-rules.yml +++ /dev/null @@ -1,5 +0,0 @@ -# Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps - -components/ieee802154/test_apps/test_ieee802154: - enable: - - if: IDF_TARGET == "esp32c6" diff --git a/components/ieee802154/test_apps/test_ieee802154/README.md b/components/ieee802154/test_apps/test_ieee802154/README.md deleted file mode 100644 index 65eeecb079e2..000000000000 --- a/components/ieee802154/test_apps/test_ieee802154/README.md +++ /dev/null @@ -1,3 +0,0 @@ -| Supported Targets | ESP32-C6 | -| ----------------- | -------- | - diff --git a/components/ieee802154/test_apps/test_ieee802154/sdkconfig.defaults b/components/ieee802154/test_apps/test_ieee802154/sdkconfig.defaults deleted file mode 100644 index e62539901786..000000000000 --- a/components/ieee802154/test_apps/test_ieee802154/sdkconfig.defaults +++ /dev/null @@ -1,4 +0,0 @@ -# This file was generated using idf.py save-defconfig. It can be edited manually. -# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration -# -CONFIG_IDF_TARGET_ESP32C6=y diff --git a/components/lwip/Kconfig b/components/lwip/Kconfig index 6204816fd429..5268f2482c91 100644 --- a/components/lwip/Kconfig +++ b/components/lwip/Kconfig @@ -196,6 +196,13 @@ menu "LWIP" Enabling this option allows checking for the destination address of a received IPv4 Packet. + config LWIP_IP_DEFAULT_TTL + int "The value for Time-To-Live used by transport layers" + range 1 255 + default 64 + help + Set value for Time-To-Live used by transport layers. + config LWIP_IP4_FRAG bool "Enable fragment outgoing IP4 packets" default y @@ -665,6 +672,20 @@ menu "LWIP" mail box is full, the LWIP drops the packets. So generally we need to make sure the TCP receive mail box is big enough to avoid packet drop between LWIP core and application. + config LWIP_TCP_ACCEPTMBOX_SIZE + int "Default TCP accept mail box size" + default 6 + range 1 64 if !LWIP_WND_SCALE + range 1 255 if LWIP_WND_SCALE + help + Set TCP accept mail box size. Generally bigger value means supporting larger backlogs + but more memory. The recommended value is 6, but applications can set it to a lower value + if listening servers are meant to have a smaller backlog. + + TCP accept mail box is a per socket mail box, when the application listens for connections + with a given listening TCP socket. If the mailbox is full, LWIP will send a RST packet and + the client will fail to connect. + config LWIP_TCP_QUEUE_OOSEQ bool "Queue incoming out-of-order segments" default y diff --git a/components/lwip/port/include/lwipopts.h b/components/lwip/port/include/lwipopts.h index 55ce6558f82b..c3687319abd3 100644 --- a/components/lwip/port/include/lwipopts.h +++ b/components/lwip/port/include/lwipopts.h @@ -248,6 +248,11 @@ extern "C" { */ #define IP_REASS_MAX_PBUFS CONFIG_LWIP_IP_REASS_MAX_PBUFS +/** + * IP_DEFAULT_TTL: Default value for Time-To-Live used by transport layers. + */ +#define IP_DEFAULT_TTL CONFIG_LWIP_IP_DEFAULT_TTL + /* ---------------------------------- ---------- ICMP options ---------- @@ -849,7 +854,7 @@ static inline uint32_t timeout_from_offered(uint32_t lease, uint32_t min) * The queue size value itself is platform-dependent, but is passed to * sys_mbox_new() when the acceptmbox is created. */ -#define DEFAULT_ACCEPTMBOX_SIZE 6 +#define DEFAULT_ACCEPTMBOX_SIZE CONFIG_LWIP_TCP_ACCEPTMBOX_SIZE /** * DEFAULT_THREAD_STACKSIZE: The stack size used by any other lwIP thread. diff --git a/components/mbedtls/test_apps/.build-test-rules.yml b/components/mbedtls/test_apps/.build-test-rules.yml index 705dd4b66b6e..3026c4d10d6b 100644 --- a/components/mbedtls/test_apps/.build-test-rules.yml +++ b/components/mbedtls/test_apps/.build-test-rules.yml @@ -5,3 +5,7 @@ components/mbedtls/test_apps: - if: CONFIG_NAME == "psram" and SOC_SPIRAM_SUPPORTED != 1 - if: CONFIG_NAME == "psram_all_ext" and SOC_SPIRAM_SUPPORTED != 1 - if: CONFIG_NAME == "ecdsa_sign" and SOC_ECDSA_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: test not pass, should be re-enable # TODO: IDF-8982 diff --git a/components/mbedtls/test_apps/pytest_mbedtls_ut.py b/components/mbedtls/test_apps/pytest_mbedtls_ut.py index 7167a54fdf7a..a95752dd579e 100644 --- a/components/mbedtls/test_apps/pytest_mbedtls_ut.py +++ b/components/mbedtls/test_apps/pytest_mbedtls_ut.py @@ -5,6 +5,7 @@ from pytest_embedded import Dut +@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='esp32p4 support TBD') # TODO: IDF-8982 @pytest.mark.supported_targets @pytest.mark.generic def test_mbedtls(dut: Dut) -> None: diff --git a/components/newlib/test_apps/newlib/pytest_newlib.py b/components/newlib/test_apps/newlib/pytest_newlib.py index 4569c93f0811..ce50c0656db9 100644 --- a/components/newlib/test_apps/newlib/pytest_newlib.py +++ b/components/newlib/test_apps/newlib/pytest_newlib.py @@ -31,6 +31,7 @@ def validate_sbom(dut: Dut) -> None: assert toolchain_newlib_version == sbom_newlib_version, 'toolchain_newlib_version != sbom_newlib_version' +@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='esp32p4 support TBD') # TODO: IDF-8983 @pytest.mark.generic @pytest.mark.parametrize( 'config', diff --git a/components/nvs_flash/.build-test-rules.yml b/components/nvs_flash/.build-test-rules.yml index 93b76378a994..3902727a7147 100644 --- a/components/nvs_flash/.build-test-rules.yml +++ b/components/nvs_flash/.build-test-rules.yml @@ -1,3 +1,17 @@ components/nvs_flash/host_test: + depends_components: + - spi_flash + - nvs_flash + - nvs_sec_provider + - esp_partition enable: - if: IDF_TARGET == "linux" + +components/nvs_flash/test_apps: + depends_components: + - spi_flash + - nvs_flash + - nvs_sec_provider + - esp_partition + disable_test: + - if: IDF_TARGET not in ["esp32", "esp32c3"] diff --git a/components/nvs_flash/test_apps/pytest_nvs_flash.py b/components/nvs_flash/test_apps/pytest_nvs_flash.py index 174664912ed3..02d8e0747cc0 100644 --- a/components/nvs_flash/test_apps/pytest_nvs_flash.py +++ b/components/nvs_flash/test_apps/pytest_nvs_flash.py @@ -10,8 +10,8 @@ ] -@pytest.mark.supported_targets -@pytest.mark.generic +@pytest.mark.esp32 +@pytest.mark.esp32c3 @pytest.mark.parametrize('config', ['default'], indirect=True) def test_nvs_flash(dut: IdfDut) -> None: dut.expect_exact('Press ENTER to see the list of tests') diff --git a/components/openthread/lib b/components/openthread/lib index 648c28e79256..e0969fc15c19 160000 --- a/components/openthread/lib +++ b/components/openthread/lib @@ -1 +1 @@ -Subproject commit 648c28e792567bc00602c92e43518c1784599251 +Subproject commit e0969fc15c1991d91446a0dc5e4625ed2c0bb014 diff --git a/components/pthread/test_apps/pthread_unity_tests/main/test_pthread_cxx.cpp b/components/pthread/test_apps/pthread_unity_tests/main/test_pthread_cxx.cpp index 58e33f87edd5..27dabd5e00f8 100644 --- a/components/pthread/test_apps/pthread_unity_tests/main/test_pthread_cxx.cpp +++ b/components/pthread/test_apps/pthread_unity_tests/main/test_pthread_cxx.cpp @@ -72,8 +72,7 @@ static void thread_main() } } -// IDF-6423 - assert and crash when running this testcase on QEMU -TEST_CASE("pthread C++", "[pthread][qemu-ignore]") +TEST_CASE("pthread C++", "[pthread]") { global_sp_mtx.reset(new int(1)); global_sp_recur_mtx.reset(new int(-1000)); diff --git a/components/pthread/test_apps/pthread_unity_tests/pytest_pthread_unity_tests.py b/components/pthread/test_apps/pthread_unity_tests/pytest_pthread_unity_tests.py index 17f9a4cd90fd..1ee39baa7202 100644 --- a/components/pthread/test_apps/pthread_unity_tests/pytest_pthread_unity_tests.py +++ b/components/pthread/test_apps/pthread_unity_tests/pytest_pthread_unity_tests.py @@ -45,9 +45,7 @@ def test_pthread_single_core(dut: Dut) -> None: indirect=True, ) def test_pthread_tls(dut: Dut) -> None: - dut.expect_exact('Press ENTER to see the list of tests') - dut.write('[thread-specific]') - dut.expect_unity_test_output(timeout=300) + dut.run_all_single_board_cases(group='thread-specific', timeout=300) @pytest.mark.generic @@ -59,9 +57,7 @@ def test_pthread_tls(dut: Dut) -> None: indirect=True, ) def test_pthread_single_core_tls(dut: Dut) -> None: - dut.expect_exact('Press ENTER to see the list of tests') - dut.write('[thread-specific]') - dut.expect_unity_test_output(timeout=300) + dut.run_all_single_board_cases(group='thread-specific', timeout=300) @pytest.mark.host_test diff --git a/components/soc/esp32/include/soc/soc.h b/components/soc/esp32/include/soc/soc.h index 696a057a8be6..e1db268f4dd8 100644 --- a/components/soc/esp32/include/soc/soc.h +++ b/components/soc/esp32/include/soc/soc.h @@ -158,7 +158,6 @@ #define APB_CLK_FREQ_ROM ( 26*1000000 ) #define CPU_CLK_FREQ_ROM APB_CLK_FREQ_ROM #define CPU_CLK_FREQ_MHZ_BTLD (80) // The cpu clock frequency (in MHz) to set at 2nd stage bootloader system clock configuration -#define CPU_CLK_FREQ APB_CLK_FREQ //this may be incorrect, please refer to ESP_DEFAULT_CPU_FREQ_MHZ #define APB_CLK_FREQ ( 80*1000000 ) //unit: Hz #define MODEM_REQUIRED_MIN_APB_CLK_FREQ ( 80*1000000 ) #define REF_CLK_FREQ ( 1000000 ) diff --git a/components/soc/esp32c2/include/soc/soc.h b/components/soc/esp32c2/include/soc/soc.h index 5186fdb044bd..b271cc2ca29d 100644 --- a/components/soc/esp32c2/include/soc/soc.h +++ b/components/soc/esp32c2/include/soc/soc.h @@ -143,9 +143,7 @@ //Periheral Clock {{ #define APB_CLK_FREQ_ROM ( 40*1000000 ) #define CPU_CLK_FREQ_ROM APB_CLK_FREQ_ROM -#define EFUSE_CLK_FREQ_ROM ( 20*1000000) #define CPU_CLK_FREQ_MHZ_BTLD (80) // The cpu clock frequency (in MHz) to set at 2nd stage bootloader system clock configuration -#define CPU_CLK_FREQ APB_CLK_FREQ #define APB_CLK_FREQ (SOC_XTAL_FREQ_MHZ * 1000000 ) #define MODEM_REQUIRED_MIN_APB_CLK_FREQ ( 80*1000000 ) #define REF_CLK_FREQ ( 1000000 ) diff --git a/components/soc/esp32c3/include/soc/soc.h b/components/soc/esp32c3/include/soc/soc.h index 0f686cac4afb..3cfc76dcef49 100644 --- a/components/soc/esp32c3/include/soc/soc.h +++ b/components/soc/esp32c3/include/soc/soc.h @@ -136,9 +136,7 @@ //Periheral Clock {{ #define APB_CLK_FREQ_ROM ( 40*1000000 ) #define CPU_CLK_FREQ_ROM APB_CLK_FREQ_ROM -#define EFUSE_CLK_FREQ_ROM ( 20*1000000) #define CPU_CLK_FREQ_MHZ_BTLD (80) // The cpu clock frequency (in MHz) to set at 2nd stage bootloader system clock configuration -#define CPU_CLK_FREQ APB_CLK_FREQ #define APB_CLK_FREQ ( 80*1000000 ) #define MODEM_REQUIRED_MIN_APB_CLK_FREQ ( 80*1000000 ) #define REF_CLK_FREQ ( 1000000 ) diff --git a/components/soc/esp32c5/include/soc/soc.h b/components/soc/esp32c5/include/soc/soc.h index d32981407ec1..3794c3ae525b 100644 --- a/components/soc/esp32c5/include/soc/soc.h +++ b/components/soc/esp32c5/include/soc/soc.h @@ -137,9 +137,7 @@ //Periheral Clock {{ #define APB_CLK_FREQ_ROM ( 40*1000000 ) #define CPU_CLK_FREQ_ROM APB_CLK_FREQ_ROM -#define EFUSE_CLK_FREQ_ROM ( 20*1000000) #define CPU_CLK_FREQ_MHZ_BTLD (80) // The cpu clock frequency (in MHz) to set at 2nd stage bootloader system clock configuration -#define CPU_CLK_FREQ APB_CLK_FREQ #define APB_CLK_FREQ ( 40*1000000 ) #define MODEM_REQUIRED_MIN_APB_CLK_FREQ ( 80*1000000 ) #define REF_CLK_FREQ ( 1000000 ) diff --git a/components/soc/esp32c6/include/soc/clk_tree_defs.h b/components/soc/esp32c6/include/soc/clk_tree_defs.h index 0d4706495617..77279c913b5b 100644 --- a/components/soc/esp32c6/include/soc/clk_tree_defs.h +++ b/components/soc/esp32c6/include/soc/clk_tree_defs.h @@ -460,6 +460,8 @@ typedef enum { typedef enum { PARLIO_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */ PARLIO_CLK_SRC_PLL_F240M = SOC_MOD_CLK_PLL_F240M, /*!< Select PLL_F240M as the source clock */ + PARLIO_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as the source clock */ + PARLIO_CLK_SRC_EXTERNAL = -1, /*!< Select EXTERNAL clock as the source clock */ PARLIO_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F240M, /*!< Select PLL_F240M as the default clock choice */ } soc_periph_parlio_clk_src_t; diff --git a/components/soc/esp32c6/include/soc/soc.h b/components/soc/esp32c6/include/soc/soc.h index 2641a8feaf7a..bdcf25740e1e 100644 --- a/components/soc/esp32c6/include/soc/soc.h +++ b/components/soc/esp32c6/include/soc/soc.h @@ -138,9 +138,7 @@ //Periheral Clock {{ #define APB_CLK_FREQ_ROM ( 40*1000000 ) #define CPU_CLK_FREQ_ROM APB_CLK_FREQ_ROM -#define EFUSE_CLK_FREQ_ROM ( 20*1000000) #define CPU_CLK_FREQ_MHZ_BTLD (80) // The cpu clock frequency (in MHz) to set at 2nd stage bootloader system clock configuration -#define CPU_CLK_FREQ APB_CLK_FREQ #define APB_CLK_FREQ ( 40*1000000 ) #define MODEM_REQUIRED_MIN_APB_CLK_FREQ ( 80*1000000 ) #define REF_CLK_FREQ ( 1000000 ) diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index b6fe1555a7e4..c22957239c91 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -815,6 +815,14 @@ config SOC_PARLIO_TX_CLK_SUPPORT_GATING bool default y +config SOC_PARLIO_RX_CLK_SUPPORT_GATING + bool + default y + +config SOC_PARLIO_RX_CLK_SUPPORT_OUTPUT + bool + default y + config SOC_PARLIO_TRANS_BIT_ALIGN bool default y diff --git a/components/soc/esp32h2/include/soc/clk_tree_defs.h b/components/soc/esp32h2/include/soc/clk_tree_defs.h index d56380c04aed..f6170d762f14 100644 --- a/components/soc/esp32h2/include/soc/clk_tree_defs.h +++ b/components/soc/esp32h2/include/soc/clk_tree_defs.h @@ -451,7 +451,7 @@ typedef enum { /** * @brief Array initializer for all supported clock sources of PARLIO */ -#define SOC_PARLIO_CLKS {SOC_MOD_CLK_XTAL, SOC_MOD_CLK_PLL_F96M} +#define SOC_PARLIO_CLKS {SOC_MOD_CLK_XTAL, SOC_MOD_CLK_PLL_F96M, SOC_MOD_CLK_RC_FAST} /** * @brief PARLIO clock source @@ -459,6 +459,8 @@ typedef enum { typedef enum { PARLIO_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */ PARLIO_CLK_SRC_PLL_F96M = SOC_MOD_CLK_PLL_F96M, /*!< Select PLL_F96M as the source clock */ + PARLIO_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as the source clock */ + PARLIO_CLK_SRC_EXTERNAL = -1, /*!< Select EXTERNAL clock as the source clock */ PARLIO_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F96M, /*!< Select PLL_F96M as the default clock choice */ } soc_periph_parlio_clk_src_t; diff --git a/components/soc/esp32h2/include/soc/soc.h b/components/soc/esp32h2/include/soc/soc.h index 017ae691a26c..5acd53bcc96a 100644 --- a/components/soc/esp32h2/include/soc/soc.h +++ b/components/soc/esp32h2/include/soc/soc.h @@ -136,9 +136,7 @@ //Periheral Clock {{ #define APB_CLK_FREQ_ROM ( 32*1000000 ) #define CPU_CLK_FREQ_ROM APB_CLK_FREQ_ROM -#define EFUSE_CLK_FREQ_ROM ( 20*1000000) #define CPU_CLK_FREQ_MHZ_BTLD (64) // The cpu clock frequency (in MHz) to set at 2nd stage bootloader system clock configuration -#define CPU_CLK_FREQ APB_CLK_FREQ #define APB_CLK_FREQ ( 32*1000000 ) #define MODEM_REQUIRED_MIN_APB_CLK_FREQ ( 32*1000000 ) #define REF_CLK_FREQ ( 1000000 ) diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index 1b5ea3aedb7a..90194277dc0d 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -323,6 +323,8 @@ #define SOC_PARLIO_TX_UNIT_MAX_DATA_WIDTH 8 /*!< Number of data lines of the TX unit */ #define SOC_PARLIO_RX_UNIT_MAX_DATA_WIDTH 8 /*!< Number of data lines of the RX unit */ #define SOC_PARLIO_TX_CLK_SUPPORT_GATING 1 /*!< Support gating TX clock */ +#define SOC_PARLIO_RX_CLK_SUPPORT_GATING 1 /*!< Support gating RX clock */ +#define SOC_PARLIO_RX_CLK_SUPPORT_OUTPUT 1 /*!< Support output RX clock to a GPIO */ #define SOC_PARLIO_TRANS_BIT_ALIGN 1 /*!< Support bit alignment in transaction */ /*--------------------------- MPI CAPS ---------------------------------------*/ diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index 688ea961b3cf..361d7bd73e3b 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -47,10 +47,6 @@ config SOC_ETM_SUPPORTED bool default y -config SOC_PARLIO_SUPPORTED - bool - default y - config SOC_ASYNC_MEMCPY_SUPPORTED bool default y @@ -147,6 +143,10 @@ config SOC_SECURE_BOOT_SUPPORTED bool default y +config SOC_PMU_SUPPORTED + bool + default y + config SOC_LP_TIMER_SUPPORTED bool default y @@ -171,6 +171,10 @@ config SOC_SDMMC_HOST_SUPPORTED bool default y +config SOC_CLK_TREE_SUPPORTED + bool + default y + config SOC_WDT_SUPPORTED bool default y @@ -555,10 +559,6 @@ config SOC_I2S_SUPPORTS_XTAL bool default y -config SOC_I2S_SUPPORTS_APLL - bool - default y - config SOC_I2S_SUPPORTS_PCM bool default y @@ -1305,16 +1305,12 @@ config SOC_PSRAM_VDD_POWER_MPLL config SOC_CLK_RC_FAST_SUPPORT_CALIBRATION bool - default n + default y config SOC_MODEM_CLOCK_IS_INDEPENDENT bool default n -config SOC_CLK_APLL_SUPPORTED - bool - default y - config SOC_CLK_MPLL_SUPPORTED bool default y @@ -1323,11 +1319,11 @@ config SOC_CLK_XTAL32K_SUPPORTED bool default y -config SOC_CLK_OSC_SLOW_SUPPORTED +config SOC_CLK_RC32K_SUPPORTED bool default y -config SOC_CLK_RC32K_SUPPORTED +config SOC_CLK_LP_FAST_SUPPORT_LP_PLL bool default y diff --git a/components/soc/esp32p4/include/soc/clk_tree_defs.h b/components/soc/esp32p4/include/soc/clk_tree_defs.h index 6c9bbe62b4e5..b936723f940c 100644 --- a/components/soc/esp32p4/include/soc/clk_tree_defs.h +++ b/components/soc/esp32p4/include/soc/clk_tree_defs.h @@ -37,33 +37,25 @@ extern "C" { * * XTAL32K_CLK can also be calibrated to get its exact frequency. * - * 6) External Slow Clock (optional): OSC_SLOW - * - * A slow clock signal generated by an external circuit can be connected to GPIO1 to be the clock source for the - * RTC_SLOW_CLK. - * - * OSC_SLOW_CLK can also be calibrated to get its exact frequency. - * * * PLL Clocks: * * from 40MHz XTAL oscillator frequency multipliers: - * 1) CPLL (400MHz), used for CPU, MSPI-Flash, MSPI-PSRAM clock source - * 2) MPLL (500MHz), used for MSPI-PSRAM clock source; and is further divided to PLL_F50M, PLL_F25M, to be used for peripheral's clock sources - * 3) SPLL (480MHz), directly used for MSPI-Flash, MSPI-PSRAM, GPSPI clock sources; and is further divided to PLL_F240M, PLL_F160M, PLL_F120M, PLL_F80M, PLL_F20M, to be used for peripherals' clock sources - * 4) APLL (configurable), can be the clock source for peripherals (GPSPI, I2S, LCD, CAM, etc.) + * 1) CPLL (320/360/400MHz), CPU_PLL, used for CPU, MSPI-Flash, MSPI-PSRAM clock source + * 2) MPLL (configurable, 400MHz at power-on reset), MSPI_PLL, used for MSPI-PSRAM clock source; and is further divided to PLL_F50M, PLL_F25M, to be used for peripheral's clock sources + * 3) SPLL (480MHz), SYS_PLL (AXI/AHB), directly used for MSPI-Flash, MSPI-PSRAM, GPSPI clock sources; and is further divided to PLL_F240M, PLL_F160M, PLL_F120M, PLL_F80M, PLL_F20M, to be used for peripherals' clock sources + * 4) APLL (configurable), AUDIO_PLL, can be the clock source for peripherals (I2S, GPSPI, LCD, CAM, etc.) * 5) SDIO_PLL0/1/2 * * from 32kHz slow clock oscillator frequency multiplier: * 6) LP_PLL (8MHz), used for RTC_FAST_CLK clock source and LP peripherals' clock sources */ -/* With the default value of FOSC_DFREQ = 100, RC_FAST clock frequency is 17.5 MHz +/- 7% */ // TODO: check +/* With the default value of FOSC_DFREQ = 100, RC_FAST clock frequency is 17.5 MHz +/- 7% */ #define SOC_CLK_RC_FAST_FREQ_APPROX 17500000 /*!< Approximate RC_FAST_CLK frequency in Hz */ #define SOC_CLK_RC_SLOW_FREQ_APPROX 136000 /*!< Approximate RC_SLOW_CLK frequency in Hz */ #define SOC_CLK_RC32K_FREQ_APPROX 32768 /*!< Approximate RC32K_CLK frequency in Hz */ #define SOC_CLK_XTAL32K_FREQ_APPROX 32768 /*!< Approximate XTAL32K_CLK frequency in Hz */ -#define SOC_CLK_OSC_SLOW_FREQ_APPROX 32768 /*!< Approximate OSC_SLOW_CLK (external slow clock) frequency in Hz */ // Naming convention: SOC_ROOT_CLK_{loc}_{type}_[attr] // {loc}: EXT, INT @@ -87,7 +79,8 @@ typedef enum { */ typedef enum { SOC_CPU_CLK_SRC_XTAL = 0, /*!< Select XTAL_CLK as CPU_CLK source */ - SOC_CPU_CLK_SRC_PLL = 1, /*!< Select (C)PLL_CLK as CPU_CLK source (CPLL_CLK is the output of 40MHz crystal oscillator frequency multiplier, 400MHz) */ + SOC_CPU_CLK_SRC_CPLL = 1, /*!< Select CPLL_CLK as CPU_CLK source (CPLL_CLK is the output of 40MHz crystal oscillator frequency multiplier, can be 320/360/400MHz) */ + SOC_CPU_CLK_SRC_PLL = SOC_CPU_CLK_SRC_CPLL, /*!< Alias name for `SOC_CPU_CLK_SRC_CPLL` */ SOC_CPU_CLK_SRC_RC_FAST = 2, /*!< Select RC_FAST_CLK as CPU_CLK source */ SOC_CPU_CLK_SRC_INVALID, /*!< Invalid CPU_CLK source */ } soc_cpu_clk_src_t; @@ -100,7 +93,6 @@ typedef enum { SOC_RTC_SLOW_CLK_SRC_RC_SLOW = 0, /*!< Select RC_SLOW_CLK as RTC_SLOW_CLK source */ SOC_RTC_SLOW_CLK_SRC_XTAL32K = 1, /*!< Select XTAL32K_CLK as RTC_SLOW_CLK source */ SOC_RTC_SLOW_CLK_SRC_RC32K = 2, /*!< Select RC32K_CLK as RTC_SLOW_CLK source */ - SOC_RTC_SLOW_CLK_SRC_OSC_SLOW = 3, /*!< Select OSC_SLOW_CLK (external slow clock) as RTC_SLOW_CLK source */ SOC_RTC_SLOW_CLK_SRC_INVALID, /*!< Invalid RTC_SLOW_CLK source */ } soc_rtc_slow_clk_src_t; @@ -139,17 +131,16 @@ typedef enum { SOC_MOD_CLK_CPU = 1, /*!< CPU_CLK can be sourced from XTAL, CPLL, or RC_FAST by configuring soc_cpu_clk_src_t */ // For RTC domain SOC_MOD_CLK_RTC_FAST, /*!< RTC_FAST_CLK can be sourced from XTAL, RC_FAST, or LP_PLL by configuring soc_rtc_fast_clk_src_t */ - SOC_MOD_CLK_RTC_SLOW, /*!< RTC_SLOW_CLK can be sourced from RC_SLOW, XTAL32K, RC32K, or OSC_SLOW by configuring soc_rtc_slow_clk_src_t */ + SOC_MOD_CLK_RTC_SLOW, /*!< RTC_SLOW_CLK can be sourced from RC_SLOW, XTAL32K, or RC32K by configuring soc_rtc_slow_clk_src_t */ // For digital domain: peripherals - SOC_MOD_CLK_PLL_F20M, /*!< PLL_F20M_CLK is derived from SPLL (clock gating + fixed divider of 24), it has a fixed frequency of 20MHz */ - SOC_MOD_CLK_PLL_F25M, /*!< PLL_F25M_CLK is derived from MPLL (clock gating + fixed divider of 20), it has a fixed frequency of 25MHz */ - SOC_MOD_CLK_PLL_F80M, /*!< PLL_F80M_CLK is derived from SPLL (clock gating + fixed divider of 6), it has a fixed frequency of 80MHz */ - SOC_MOD_CLK_PLL_F160M, /*!< PLL_F160M_CLK is derived from SPLL (clock gating + fixed divider of 3), it has a fixed frequency of 160MHz */ - SOC_MOD_CLK_PLL_F200M, /*!< PLL_F200M_CLK is derived from SPLL (clock gating + fixed divider of 3), it has a fixed frequency of 200MHz */ - SOC_MOD_CLK_PLL_F240M, /*!< PLL_F240M_CLK is derived from SPLL (clock gating + fixed divider of 2), it has a fixed frequency of 240MHz */ - SOC_MOD_CLK_CPLL, /*!< CPLL is from 40MHz XTAL oscillator frequency multipliers, it has a fixed frequency of 400MHz */ - SOC_MOD_CLK_SPLL, /*!< SPLL is from 40MHz XTAL oscillator frequency multipliers, it has a fixed frequency of 480MHz */ - SOC_MOD_CLK_MPLL, /*!< MPLL is from 40MHz XTAL oscillator frequency multipliers, it has a fixed frequency of 500MHz */ + SOC_MOD_CLK_PLL_F20M, /*!< PLL_F20M_CLK is derived from SPLL (clock gating + "fixed" divider of 24), it has a fixed frequency of 20MHz */ + SOC_MOD_CLK_PLL_F25M, /*!< PLL_F25M_CLK is derived from MPLL (clock gating + configurable divider), it will have a frequency of 25MHz */ + SOC_MOD_CLK_PLL_F80M, /*!< PLL_F80M_CLK is derived from SPLL (clock gating + "fixed" divider of 6), it has a fixed frequency of 80MHz */ + SOC_MOD_CLK_PLL_F160M, /*!< PLL_F160M_CLK is derived from SPLL (clock gating + "fixed" divider of 3), it has a fixed frequency of 160MHz */ + SOC_MOD_CLK_PLL_F240M, /*!< PLL_F240M_CLK is derived from SPLL (clock gating + "fixed" divider of 2), it has a fixed frequency of 240MHz */ + SOC_MOD_CLK_CPLL, /*!< CPLL is from 40MHz XTAL oscillator frequency multipliers */ + SOC_MOD_CLK_SPLL, /*!< SPLL is from 40MHz XTAL oscillator frequency multipliers, it has a "fixed" frequency of 480MHz */ + SOC_MOD_CLK_MPLL, /*!< MPLL is from 40MHz XTAL oscillator frequency multipliers */ SOC_MOD_CLK_XTAL32K, /*!< XTAL32K_CLK comes from the external 32kHz crystal, passing a clock gating to the peripherals */ SOC_MOD_CLK_RC_FAST, /*!< RC_FAST_CLK comes from the internal 20MHz rc oscillator, passing a clock gating to the peripherals */ SOC_MOD_CLK_XTAL, /*!< XTAL_CLK comes from the external 40MHz crystal */ @@ -439,7 +430,6 @@ typedef enum { } soc_periph_i2c_clk_src_t; /////////////////////////////////////////////////SPI//////////////////////////////////////////////////////////////////// -//TODO: IDF-7502 /** * @brief Array initializer for all supported clock sources of SPI */ @@ -625,7 +615,7 @@ typedef enum { /** * @brief Array initializer for all supported clock sources of SDMMC */ -#define SOC_SDMMC_CLKS {SOC_MOD_CLK_PLL_F160M, SOC_MOD_CLK_PLL_F200M} +#define SOC_SDMMC_CLKS {SOC_MOD_CLK_PLL_F160M} /** * @brief Type of SDMMC clock source @@ -633,7 +623,7 @@ typedef enum { typedef enum { SDMMC_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_160M as the default choice */ SDMMC_CLK_SRC_PLL160M = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_160M as the source clock */ - SDMMC_CLK_SRC_PLL200M = SOC_MOD_CLK_PLL_F200M, /*!< Select PLL_200M as the source clock */ + // SOC_MOD_CLK_SDIO_PLL TODO:IDF-8886 } soc_periph_sdmmc_clk_src_t; //////////////////////////////////////////////////Temp Sensor/////////////////////////////////////////////////////////// diff --git a/components/soc/esp32p4/include/soc/io_mux_reg.h b/components/soc/esp32p4/include/soc/io_mux_reg.h index 6ccbab665c82..e994c28bcd89 100644 --- a/components/soc/esp32p4/include/soc/io_mux_reg.h +++ b/components/soc/esp32p4/include/soc/io_mux_reg.h @@ -220,7 +220,7 @@ #define USB_OTG_INT_PHY_DM_GPIO_NUM USB_INT_PHY1_DM_GPIO_NUM #define USB_OTG_INT_PHY_DP_GPIO_NUM USB_INT_PHY1_DP_GPIO_NUM -// #define EXT_OSC_SLOW_GPIO_NUM 1 // TODO: IDF-7526 +#define EXT_OSC_SLOW_GPIO_NUM 0 // XTAL_32K_N #define MAX_RTC_GPIO_NUM 16 #define MAX_PAD_GPIO_NUM 54 diff --git a/components/soc/esp32p4/include/soc/lp_system_reg.h b/components/soc/esp32p4/include/soc/lp_system_reg.h index 5df842922002..910c591aaaa0 100644 --- a/components/soc/esp32p4/include/soc/lp_system_reg.h +++ b/components/soc/esp32p4/include/soc/lp_system_reg.h @@ -88,13 +88,35 @@ extern "C" { #define LP_SYSTEM_REG_ANA_FIB_M (LP_SYSTEM_REG_ANA_FIB_V << LP_SYSTEM_REG_ANA_FIB_S) #define LP_SYSTEM_REG_ANA_FIB_V 0x0000007FU #define LP_SYSTEM_REG_ANA_FIB_S 14 -/** LP_SYSTEM_REG_LP_FIB_SEL : R/W; bitpos: [28:21]; default: 255; +/** LP_SYSTEM_REG_LP_FIB_BOD_RESET : R/W; bitpos: [22]; default: 1; * need_des */ -#define LP_SYSTEM_REG_LP_FIB_SEL 0x000000FFU -#define LP_SYSTEM_REG_LP_FIB_SEL_M (LP_SYSTEM_REG_LP_FIB_SEL_V << LP_SYSTEM_REG_LP_FIB_SEL_S) -#define LP_SYSTEM_REG_LP_FIB_SEL_V 0x000000FFU -#define LP_SYSTEM_REG_LP_FIB_SEL_S 21 +#define LP_SYSTEM_REG_LP_FIB_BOD_RST BIT(22) +#define LP_SYSTEM_REG_LP_FIB_BOD_RST_M (LP_SYSTEM_REG_LP_FIB_BOD_RST_V << LP_SYSTEM_REG_LP_FIB_BOD_RST_S) +#define LP_SYSTEM_REG_LP_FIB_BOD_RST_V 0x00000001U +#define LP_SYSTEM_REG_LP_FIB_BOD_RST_S 22 +/** LP_SYSTEM_REG_LP_FIB_SUPER_WDT_RST : R/W; bitpos: [23]; default: 1; + * need_des + */ +#define LP_SYSTEM_REG_LP_FIB_SUPER_WDT_RST BIT(23) +#define LP_SYSTEM_REG_LP_FIB_SUPER_WDT_RST_M (LP_SYSTEM_REG_LP_FIB_SUPER_WDT_RST_V << LP_SYSTEM_REG_LP_FIB_SUPER_WDT_RST_S) +#define LP_SYSTEM_REG_LP_FIB_SUPER_WDT_RST_V 0x00000001U +#define LP_SYSTEM_REG_LP_FIB_SUPER_WDT_RST_S 23 +/** LP_SYSTEM_REG_LP_FIB_DCDC_SWITCH : R/W; bitpos: [25]; default: 1; + * need_des + */ +#define LP_SYSTEM_REG_LP_FIB_DCDC_SWITCH BIT(25) +#define LP_SYSTEM_REG_LP_FIB_DCDC_SWITCH_M (LP_SYSTEM_REG_LP_FIB_DCDC_SWITCH_V << LP_SYSTEM_REG_LP_FIB_DCDC_SWITCH_S) +#define LP_SYSTEM_REG_LP_FIB_DCDC_SWITCH_V 0x00000001U +#define LP_SYSTEM_REG_LP_FIB_DCDC_SWITCH_S 25 + +/** LP_SYSTEM_REG_LP_FIB_VSET_ENABLE : R/W; bitpos: [26]; default: 1; + * need_des + */ +#define LP_SYSTEM_REG_LP_FIB_VSET_ENABLE BIT(26) +#define LP_SYSTEM_REG_LP_FIB_VSET_ENABLE_M (LP_SYSTEM_REG_LP_FIB_VSET_ENABLE_V << LP_SYSTEM_REG_LP_FIB_VSET_ENABLE_S) +#define LP_SYSTEM_REG_LP_FIB_VSET_ENABLE_V 0x00000001U +#define LP_SYSTEM_REG_LP_FIB_VSET_ENABLE_S 26 /** LP_SYSTEM_REG_LP_CORE_ETM_WAKEUP_FLAG_CLR : WT; bitpos: [29]; default: 0; * need_des */ diff --git a/components/soc/esp32p4/include/soc/pmu_icg_mapping.h b/components/soc/esp32p4/include/soc/pmu_icg_mapping.h index a4fa889f1f17..9021eaaba7d8 100644 --- a/components/soc/esp32p4/include/soc/pmu_icg_mapping.h +++ b/components/soc/esp32p4/include/soc/pmu_icg_mapping.h @@ -6,30 +6,60 @@ #pragma once -#define PMU_ICG_FUNC_CORE0_CPU_CLK_EN 0 -#define PMU_ICG_FUNC_CORE1_CPU_CLK_EN 1 -#define PMU_ICG_FUNC_CORE0_CLIC_CLK_EN 2 -#define PMU_ICG_FUNC_CORE1_CLIC_CLK_EN 3 -#define PMU_ICG_FUNC_MISC_CPU_CLK_EN 4 -#define PMU_ICG_FUNC_MISC_SYS_CLK_EN 5 -#define PMU_ICG_FUNC_ICM_SYS_CLK_EN 6 -#define PMU_ICG_FUNC_ICM_CPU_CLK_EN 7 -#define PMU_ICG_FUNC_ICM_MEM_CLK_EN 8 -#define PMU_ICG_FUNC_ICM_APB_CLK_EN 9 -#define PMU_ICG_FUNC_TCM_CPU_CLK_EN 10 -#define PMU_ICG_FUNC_L2MEM_MEM_CLK_EN 11 -#define PMU_ICG_FUNC_L2MEM_SYS_CLK_EN 12 -#define PMU_ICG_FUNC_L1CACHE_CPU_CLK_EN 13 -#define PMU_ICG_FUNC_LICACHE_D_CPU_CLK_EN 14 -#define PMU_ICG_FUNC_L1CACHE_I0_CPU_CLK_EN 15 -#define PMU_ICG_FUNC_L1CACHE_I1_CPU_CLK_EN 16 -#define PMU_ICG_FUNC_L1CACHE_MEM_CLK_EN 17 -#define PMU_ICG_FUNC_L1CACHE_D_MEM_CLK_EN 18 -#define PMU_ICG_FUNC_L1CACHE_I0_MEM_CLK_EN 19 -#define PMU_ICG_FUNC_L1CACHE_I1_MEM_CLK_EN 20 -#define PMU_ICG_FUNC_L2CACHE_MEM_CLK_EN 21 -#define PMU_ICG_FUNC_L2CACHE_SYS_CLK_EN 22 -#define PMU_ICG_FUNC_REGDMA_SYS_CLK_EN 23 -#define PMU_ICG_FUNC_HP_CLKRST_APB_CLK_EN 24 -#define PMU_ICG_FUNC_SYSREG_APB_CLK_EN 25 -#define PMU_ICG_FUNC_INTRMTX_APB_CLK_EN 26 +// TODO: IDF-5731 + +#define PMU_ICG_APB_ENA_CORE0_CPU 0 +#define PMU_ICG_APB_ENA_CORE1_CPU 1 +#define PMU_ICG_APB_ENA_CORE0_CLIC 2 +#define PMU_ICG_APB_ENA_CORE1_CLIC 3 +#define PMU_ICG_APB_ENA_MISC_CPU 4 +#define PMU_ICG_APB_ENA_MISC_SYS 5 +#define PMU_ICG_APB_ENA_ICM_SYS 6 +#define PMU_ICG_APB_ENA_ICM_CPU 7 +#define PMU_ICG_APB_ENA_ICM_MEM 8 +#define PMU_ICG_APB_ENA_ICM_APB 9 +#define PMU_ICG_APB_ENA_TCM_CPU 10 +#define PMU_ICG_APB_ENA_L2MEM_MEM 11 +#define PMU_ICG_APB_ENA_L2MEM_SYS 12 +#define PMU_ICG_APB_ENA_L1CACHE_CPU 13 +#define PMU_ICG_APB_ENA_L1CACHE_D_CPU 14 +#define PMU_ICG_APB_ENA_L1CACHE_I0_CPU 15 +#define PMU_ICG_APB_ENA_L1CACHE_I1_CPU 16 +#define PMU_ICG_APB_ENA_L1CACHE_MEM 17 +#define PMU_ICG_APB_ENA_L1CACHE_D_MEM 18 +#define PMU_ICG_APB_ENA_L1CACHE_I0_MEM 19 +#define PMU_ICG_APB_ENA_L1CACHE_I1_MEM 20 +#define PMU_ICG_APB_ENA_L2CACHE_MEM 21 +#define PMU_ICG_APB_ENA_L2CACHE_SYS 22 +#define PMU_ICG_APB_ENA_REGDMA 23 +#define PMU_ICG_APB_ENA_HP_CLKRST 24 +#define PMU_ICG_APB_ENA_SYSREG_APB 25 +#define PMU_ICG_APB_ENA_INTRMTX_APB 26 + +#define PMU_ICG_FUNC_ENA_CORE0_CPU 0 +#define PMU_ICG_FUNC_ENA_CORE1_CPU 1 +#define PMU_ICG_FUNC_ENA_CORE0_CLIC 2 +#define PMU_ICG_FUNC_ENA_CORE1_CLIC 3 +#define PMU_ICG_FUNC_ENA_MISC_CPU 4 +#define PMU_ICG_FUNC_ENA_MISC_SYS 5 +#define PMU_ICG_FUNC_ENA_ICM_SYS 6 +#define PMU_ICG_FUNC_ENA_ICM_CPU 7 +#define PMU_ICG_FUNC_ENA_ICM_MEM 8 +#define PMU_ICG_FUNC_ENA_ICM_APB 9 +#define PMU_ICG_FUNC_ENA_TCM_CPU 10 +#define PMU_ICG_FUNC_ENA_L2MEM_MEM 11 +#define PMU_ICG_FUNC_ENA_L2MEM_SYS 12 +#define PMU_ICG_FUNC_ENA_L1CACHE_CPU 13 +#define PMU_ICG_FUNC_ENA_L1CACHE_D_CPU 14 +#define PMU_ICG_FUNC_ENA_L1CACHE_I0_CPU 15 +#define PMU_ICG_FUNC_ENA_L1CACHE_I1_CPU 16 +#define PMU_ICG_FUNC_ENA_L1CACHE_MEM 17 +#define PMU_ICG_FUNC_ENA_L1CACHE_D_MEM 18 +#define PMU_ICG_FUNC_ENA_L1CACHE_I0_MEM 19 +#define PMU_ICG_FUNC_ENA_L1CACHE_I1_MEM 20 +#define PMU_ICG_FUNC_ENA_L2CACHE_MEM 21 +#define PMU_ICG_FUNC_ENA_L2CACHE_SYS 22 +#define PMU_ICG_FUNC_ENA_REGDMA 23 +#define PMU_ICG_FUNC_ENA_HP_CLKRST 24 +#define PMU_ICG_FUNC_ENA_SYSREG_APB 25 +#define PMU_ICG_FUNC_ENA_INTRMTX_APB 26 diff --git a/components/soc/esp32p4/include/soc/pmu_reg.h b/components/soc/esp32p4/include/soc/pmu_reg.h index d3896a132065..1be61770a823 100644 --- a/components/soc/esp32p4/include/soc/pmu_reg.h +++ b/components/soc/esp32p4/include/soc/pmu_reg.h @@ -1569,13 +1569,34 @@ extern "C" { #define PMU_TIE_LOW_CALI_XTAL_ICG_M (PMU_TIE_LOW_CALI_XTAL_ICG_V << PMU_TIE_LOW_CALI_XTAL_ICG_S) #define PMU_TIE_LOW_CALI_XTAL_ICG_V 0x00000001U #define PMU_TIE_LOW_CALI_XTAL_ICG_S 0 -/** PMU_TIE_LOW_GLOBAL_PLL_ICG : WT; bitpos: [4:1]; default: 0; +/** PMU_TIE_LOW_GLOBAL_CPLL_ICG : WT; bitpos: [1]; default: 0; * need_des */ -#define PMU_TIE_LOW_GLOBAL_PLL_ICG 0x0000000FU -#define PMU_TIE_LOW_GLOBAL_PLL_ICG_M (PMU_TIE_LOW_GLOBAL_PLL_ICG_V << PMU_TIE_LOW_GLOBAL_PLL_ICG_S) -#define PMU_TIE_LOW_GLOBAL_PLL_ICG_V 0x0000000FU -#define PMU_TIE_LOW_GLOBAL_PLL_ICG_S 1 +#define PMU_TIE_LOW_GLOBAL_CPLL_ICG (BIT(1)) +#define PMU_TIE_LOW_GLOBAL_CPLL_ICG_M (PMU_TIE_LOW_GLOBAL_CPLL_ICG_V << PMU_TIE_LOW_GLOBAL_CPLL_ICG_S) +#define PMU_TIE_LOW_GLOBAL_CPLL_ICG_V 0x00000001U +#define PMU_TIE_LOW_GLOBAL_CPLL_ICG_S 1 +/** PMU_TIE_LOW_GLOBAL_SPLL_ICG : WT; bitpos: [2]; default: 0; + * need_des + */ +#define PMU_TIE_LOW_GLOBAL_SPLL_ICG (BIT(2)) +#define PMU_TIE_LOW_GLOBAL_SPLL_ICG_M (PMU_TIE_LOW_GLOBAL_SPLL_ICG_V << PMU_TIE_LOW_GLOBAL_SPLL_ICG_S) +#define PMU_TIE_LOW_GLOBAL_SPLL_ICG_V 0x00000001U +#define PMU_TIE_LOW_GLOBAL_SPLL_ICG_S 2 +/** PMU_TIE_LOW_GLOBAL_APLL_ICG : WT; bitpos: [3]; default: 0; + * need_des + */ +#define PMU_TIE_LOW_GLOBAL_APLL_ICG (BIT(3)) +#define PMU_TIE_LOW_GLOBAL_APLL_ICG_M (PMU_TIE_LOW_GLOBAL_APLL_ICG_V << PMU_TIE_LOW_GLOBAL_APLL_ICG_S) +#define PMU_TIE_LOW_GLOBAL_APLL_ICG_V 0x00000001U +#define PMU_TIE_LOW_GLOBAL_APLL_ICG_S 3 +/** PMU_TIE_LOW_GLOBAL_SDIOPLL_ICG : WT; bitpos: [4]; default: 0; + * need_des + */ +#define PMU_TIE_LOW_GLOBAL_SDIOPLL_ICG (BIT(4)) +#define PMU_TIE_LOW_GLOBAL_SDIOPLL_ICG_M (PMU_TIE_LOW_GLOBAL_SDIOPLL_ICG_V << PMU_TIE_LOW_GLOBAL_SDIOPLL_ICG_S) +#define PMU_TIE_LOW_GLOBAL_SDIOPLL_ICG_V 0x00000001U +#define PMU_TIE_LOW_GLOBAL_SDIOPLL_ICG_S 4 /** PMU_TIE_LOW_GLOBAL_XTAL_ICG : WT; bitpos: [5]; default: 0; * need_des */ @@ -1590,20 +1611,62 @@ extern "C" { #define PMU_TIE_LOW_I2C_RETENTION_M (PMU_TIE_LOW_I2C_RETENTION_V << PMU_TIE_LOW_I2C_RETENTION_S) #define PMU_TIE_LOW_I2C_RETENTION_V 0x00000001U #define PMU_TIE_LOW_I2C_RETENTION_S 6 -/** PMU_TIE_LOW_XPD_PLL_I2C : WT; bitpos: [10:7]; default: 0; +/** PMU_TIE_LOW_XPD_CPLL_I2C : WT; bitpos: [7]; default: 0; + * need_des + */ +#define PMU_TIE_LOW_XPD_CPLL_I2C (BIT(7)) +#define PMU_TIE_LOW_XPD_CPLL_I2C_M (PMU_TIE_LOW_XPD_CPLL_I2C_V << PMU_TIE_LOW_XPD_CPLL_I2C_S) +#define PMU_TIE_LOW_XPD_CPLL_I2C_V 0x00000001U +#define PMU_TIE_LOW_XPD_CPLL_I2C_S 7 +/** PMU_TIE_LOW_XPD_SPLL_I2C : WT; bitpos: [8]; default: 0; + * need_des + */ +#define PMU_TIE_LOW_XPD_SPLL_I2C (BIT(8)) +#define PMU_TIE_LOW_XPD_SPLL_I2C_M (PMU_TIE_LOW_XPD_SPLL_I2C_V << PMU_TIE_LOW_XPD_SPLL_I2C_S) +#define PMU_TIE_LOW_XPD_SPLL_I2C_V 0x00000001U +#define PMU_TIE_LOW_XPD_SPLL_I2C_S 8 +/** PMU_TIE_LOW_XPD_APLL_I2C : WT; bitpos: [9]; default: 0; + * need_des + */ +#define PMU_TIE_LOW_XPD_APLL_I2C (BIT(9)) +#define PMU_TIE_LOW_XPD_APLL_I2C_M (PMU_TIE_LOW_XPD_APLL_I2C_V << PMU_TIE_LOW_XPD_APLL_I2C_S) +#define PMU_TIE_LOW_XPD_APLL_I2C_V 0x00000001U +#define PMU_TIE_LOW_XPD_APLL_I2C_S 9 +/** PMU_TIE_LOW_XPD_SDIOPLL_I2C : WT; bitpos: [10]; default: 0; + * need_des + */ +#define PMU_TIE_LOW_XPD_SDIOPLL_I2C (BIT(10)) +#define PMU_TIE_LOW_XPD_SDIOPLL_I2C_M (PMU_TIE_LOW_XPD_SDIOPLL_I2C_V << PMU_TIE_LOW_XPD_SDIOPLL_I2C_S) +#define PMU_TIE_LOW_XPD_SDIOPLL_I2C_V 0x00000001U +#define PMU_TIE_LOW_XPD_SDIOPLL_I2C_S 10 +/** PMU_TIE_LOW_XPD_CPLL : WT; bitpos: [11]; default: 0; + * need_des + */ +#define PMU_TIE_LOW_XPD_CPLL (BIT(11)) +#define PMU_TIE_LOW_XPD_CPLL_M (PMU_TIE_LOW_XPD_CPLL_V << PMU_TIE_LOW_XPD_CPLL_S) +#define PMU_TIE_LOW_XPD_CPLL_V 0x00000001U +#define PMU_TIE_LOW_XPD_CPLL_S 11 +/** PMU_TIE_LOW_XPD_SPLL : WT; bitpos: [12]; default: 0; + * need_des + */ +#define PMU_TIE_LOW_XPD_SPLL (BIT(12)) +#define PMU_TIE_LOW_XPD_SPLL_M (PMU_TIE_LOW_XPD_SPLL_V << PMU_TIE_LOW_XPD_SPLL_S) +#define PMU_TIE_LOW_XPD_SPLL_V 0x00000001U +#define PMU_TIE_LOW_XPD_SPLL_S 12 +/** PMU_TIE_LOW_XPD_APLL : WT; bitpos: [13]; default: 0; * need_des */ -#define PMU_TIE_LOW_XPD_PLL_I2C 0x0000000FU -#define PMU_TIE_LOW_XPD_PLL_I2C_M (PMU_TIE_LOW_XPD_PLL_I2C_V << PMU_TIE_LOW_XPD_PLL_I2C_S) -#define PMU_TIE_LOW_XPD_PLL_I2C_V 0x0000000FU -#define PMU_TIE_LOW_XPD_PLL_I2C_S 7 -/** PMU_TIE_LOW_XPD_PLL : WT; bitpos: [14:11]; default: 0; +#define PMU_TIE_LOW_XPD_APLL (BIT(13)) +#define PMU_TIE_LOW_XPD_APLL_M (PMU_TIE_LOW_XPD_APLL_V << PMU_TIE_LOW_XPD_APLL_S) +#define PMU_TIE_LOW_XPD_APLL_V 0x00000001U +#define PMU_TIE_LOW_XPD_APLL_S 13 +/** PMU_TIE_LOW_XPD_SDIOPLL : WT; bitpos: [14]; default: 0; * need_des */ -#define PMU_TIE_LOW_XPD_PLL 0x0000000FU -#define PMU_TIE_LOW_XPD_PLL_M (PMU_TIE_LOW_XPD_PLL_V << PMU_TIE_LOW_XPD_PLL_S) -#define PMU_TIE_LOW_XPD_PLL_V 0x0000000FU -#define PMU_TIE_LOW_XPD_PLL_S 11 +#define PMU_TIE_LOW_XPD_SDIOPLL (BIT(14)) +#define PMU_TIE_LOW_XPD_SDIOPLL_M (PMU_TIE_LOW_XPD_SDIOPLL_V << PMU_TIE_LOW_XPD_SDIOPLL_S) +#define PMU_TIE_LOW_XPD_SDIOPLL_V 0x00000001U +#define PMU_TIE_LOW_XPD_SDIOPLL_S 14 /** PMU_TIE_LOW_XPD_XTAL : WT; bitpos: [15]; default: 0; * need_des */ @@ -1618,13 +1681,34 @@ extern "C" { #define PMU_TIE_HIGH_CALI_XTAL_ICG_M (PMU_TIE_HIGH_CALI_XTAL_ICG_V << PMU_TIE_HIGH_CALI_XTAL_ICG_S) #define PMU_TIE_HIGH_CALI_XTAL_ICG_V 0x00000001U #define PMU_TIE_HIGH_CALI_XTAL_ICG_S 16 -/** PMU_TIE_HIGH_GLOBAL_PLL_ICG : WT; bitpos: [20:17]; default: 0; +/** PMU_TIE_HIGH_GLOBAL_CPLL_ICG : WT; bitpos: [17]; default: 0; * need_des */ -#define PMU_TIE_HIGH_GLOBAL_PLL_ICG 0x0000000FU -#define PMU_TIE_HIGH_GLOBAL_PLL_ICG_M (PMU_TIE_HIGH_GLOBAL_PLL_ICG_V << PMU_TIE_HIGH_GLOBAL_PLL_ICG_S) -#define PMU_TIE_HIGH_GLOBAL_PLL_ICG_V 0x0000000FU -#define PMU_TIE_HIGH_GLOBAL_PLL_ICG_S 17 +#define PMU_TIE_HIGH_GLOBAL_CPLL_ICG (BIT(17)) +#define PMU_TIE_HIGH_GLOBAL_CPLL_ICG_M (PMU_TIE_HIGH_GLOBAL_CPLL_ICG_V << PMU_TIE_HIGH_GLOBAL_CPLL_ICG_S) +#define PMU_TIE_HIGH_GLOBAL_CPLL_ICG_V 0x00000001U +#define PMU_TIE_HIGH_GLOBAL_CPLL_ICG_S 17 +/** PMU_TIE_HIGH_GLOBAL_SPLL_ICG : WT; bitpos: [18]; default: 0; + * need_des + */ +#define PMU_TIE_HIGH_GLOBAL_SPLL_ICG (BIT(18)) +#define PMU_TIE_HIGH_GLOBAL_SPLL_ICG_M (PMU_TIE_HIGH_GLOBAL_SPLL_ICG_V << PMU_TIE_HIGH_GLOBAL_SPLL_ICG_S) +#define PMU_TIE_HIGH_GLOBAL_SPLL_ICG_V 0x00000001U +#define PMU_TIE_HIGH_GLOBAL_SPLL_ICG_S 18 +/** PMU_TIE_HIGH_GLOBAL_APLL_ICG : WT; bitpos: [19]; default: 0; + * need_des + */ +#define PMU_TIE_HIGH_GLOBAL_APLL_ICG (BIT(19)) +#define PMU_TIE_HIGH_GLOBAL_APLL_ICG_M (PMU_TIE_HIGH_GLOBAL_APLL_ICG_V << PMU_TIE_HIGH_GLOBAL_APLL_ICG_S) +#define PMU_TIE_HIGH_GLOBAL_APLL_ICG_V 0x00000001U +#define PMU_TIE_HIGH_GLOBAL_APLL_ICG_S 19 +/** PMU_TIE_HIGH_GLOBAL_SDIOPLL_ICG : WT; bitpos: [20]; default: 0; + * need_des + */ +#define PMU_TIE_HIGH_GLOBAL_SDIOPLL_ICG (BIT(20)) +#define PMU_TIE_HIGH_GLOBAL_SDIOPLL_ICG_M (PMU_TIE_HIGH_GLOBAL_SDIOPLL_ICG_V << PMU_TIE_HIGH_GLOBAL_SDIOPLL_ICG_S) +#define PMU_TIE_HIGH_GLOBAL_SDIOPLL_ICG_V 0x00000001U +#define PMU_TIE_HIGH_GLOBAL_SDIOPLL_ICG_S 20 /** PMU_TIE_HIGH_GLOBAL_XTAL_ICG : WT; bitpos: [21]; default: 0; * need_des */ @@ -1639,20 +1723,62 @@ extern "C" { #define PMU_TIE_HIGH_I2C_RETENTION_M (PMU_TIE_HIGH_I2C_RETENTION_V << PMU_TIE_HIGH_I2C_RETENTION_S) #define PMU_TIE_HIGH_I2C_RETENTION_V 0x00000001U #define PMU_TIE_HIGH_I2C_RETENTION_S 22 -/** PMU_TIE_HIGH_XPD_PLL_I2C : WT; bitpos: [26:23]; default: 0; +/** PMU_TIE_HIGH_XPD_CPLL_I2C : WT; bitpos: [23]; default: 0; + * need_des + */ +#define PMU_TIE_HIGH_XPD_CPLL_I2C (BIT(23)) +#define PMU_TIE_HIGH_XPD_CPLL_I2C_M (PMU_TIE_HIGH_XPD_CPLL_I2C_V << PMU_TIE_HIGH_XPD_CPLL_I2C_S) +#define PMU_TIE_HIGH_XPD_CPLL_I2C_V 0x00000001U +#define PMU_TIE_HIGH_XPD_CPLL_I2C_S 23 +/** PMU_TIE_HIGH_XPD_SPLL_I2C : WT; bitpos: [24]; default: 0; + * need_des + */ +#define PMU_TIE_HIGH_XPD_SPLL_I2C (BIT(24)) +#define PMU_TIE_HIGH_XPD_SPLL_I2C_M (PMU_TIE_HIGH_XPD_SPLL_I2C_V << PMU_TIE_HIGH_XPD_SPLL_I2C_S) +#define PMU_TIE_HIGH_XPD_SPLL_I2C_V 0x00000001U +#define PMU_TIE_HIGH_XPD_SPLL_I2C_S 24 +/** PMU_TIE_HIGH_XPD_APLL_I2C : WT; bitpos: [25]; default: 0; + * need_des + */ +#define PMU_TIE_HIGH_XPD_APLL_I2C (BIT(25)) +#define PMU_TIE_HIGH_XPD_APLL_I2C_M (PMU_TIE_HIGH_XPD_APLL_I2C_V << PMU_TIE_HIGH_XPD_APLL_I2C_S) +#define PMU_TIE_HIGH_XPD_APLL_I2C_V 0x00000001U +#define PMU_TIE_HIGH_XPD_APLL_I2C_S 25 +/** PMU_TIE_HIGH_XPD_SDIOPLL_I2C : WT; bitpos: [26]; default: 0; + * need_des + */ +#define PMU_TIE_HIGH_XPD_SDIOPLL_I2C (BIT(26)) +#define PMU_TIE_HIGH_XPD_SDIOPLL_I2C_M (PMU_TIE_HIGH_XPD_SDIOPLL_I2C_V << PMU_TIE_HIGH_XPD_SDIOPLL_I2C_S) +#define PMU_TIE_HIGH_XPD_SDIOPLL_I2C_V 0x00000001U +#define PMU_TIE_HIGH_XPD_SDIOPLL_I2C_S 26 +/** PMU_TIE_HIGH_XPD_CPLL : WT; bitpos: [27]; default: 0; + * need_des + */ +#define PMU_TIE_HIGH_XPD_CPLL (BIT(27)) +#define PMU_TIE_HIGH_XPD_CPLL_M (PMU_TIE_HIGH_XPD_CPLL_V << PMU_TIE_HIGH_XPD_CPLL_S) +#define PMU_TIE_HIGH_XPD_CPLL_V 0x00000001U +#define PMU_TIE_HIGH_XPD_CPLL_S 27 +/** PMU_TIE_HIGH_XPD_SPLL : WT; bitpos: [28]; default: 0; + * need_des + */ +#define PMU_TIE_HIGH_XPD_SPLL (BIT(28)) +#define PMU_TIE_HIGH_XPD_SPLL_M (PMU_TIE_HIGH_XPD_SPLL_V << PMU_TIE_HIGH_XPD_SPLL_S) +#define PMU_TIE_HIGH_XPD_SPLL_V 0x00000001U +#define PMU_TIE_HIGH_XPD_SPLL_S 28 +/** PMU_TIE_HIGH_XPD_APLL : WT; bitpos: [29]; default: 0; * need_des */ -#define PMU_TIE_HIGH_XPD_PLL_I2C 0x0000000FU -#define PMU_TIE_HIGH_XPD_PLL_I2C_M (PMU_TIE_HIGH_XPD_PLL_I2C_V << PMU_TIE_HIGH_XPD_PLL_I2C_S) -#define PMU_TIE_HIGH_XPD_PLL_I2C_V 0x0000000FU -#define PMU_TIE_HIGH_XPD_PLL_I2C_S 23 -/** PMU_TIE_HIGH_XPD_PLL : WT; bitpos: [30:27]; default: 0; +#define PMU_TIE_HIGH_XPD_APLL (BIT(29)) +#define PMU_TIE_HIGH_XPD_APLL_M (PMU_TIE_HIGH_XPD_APLL_V << PMU_TIE_HIGH_XPD_APLL_S) +#define PMU_TIE_HIGH_XPD_APLL_V 0x00000001U +#define PMU_TIE_HIGH_XPD_APLL_S 29 +/** PMU_TIE_HIGH_XPD_SDIOPLL : WT; bitpos: [30]; default: 0; * need_des */ -#define PMU_TIE_HIGH_XPD_PLL 0x0000000FU -#define PMU_TIE_HIGH_XPD_PLL_M (PMU_TIE_HIGH_XPD_PLL_V << PMU_TIE_HIGH_XPD_PLL_S) -#define PMU_TIE_HIGH_XPD_PLL_V 0x0000000FU -#define PMU_TIE_HIGH_XPD_PLL_S 27 +#define PMU_TIE_HIGH_XPD_SDIOPLL (BIT(30)) +#define PMU_TIE_HIGH_XPD_SDIOPLL_M (PMU_TIE_HIGH_XPD_SDIOPLL_V << PMU_TIE_HIGH_XPD_SDIOPLL_S) +#define PMU_TIE_HIGH_XPD_SDIOPLL_V 0x00000001U +#define PMU_TIE_HIGH_XPD_SDIOPLL_S 30 /** PMU_TIE_HIGH_XPD_XTAL : WT; bitpos: [31]; default: 0; * need_des */ diff --git a/components/soc/esp32p4/include/soc/pmu_struct.h b/components/soc/esp32p4/include/soc/pmu_struct.h index 24e2b993839c..3fe0c6dd86e5 100644 --- a/components/soc/esp32p4/include/soc/pmu_struct.h +++ b/components/soc/esp32p4/include/soc/pmu_struct.h @@ -6,2920 +6,765 @@ #pragma once #include +#include "soc/pmu_reg.h" #ifdef __cplusplus extern "C" { #endif -/** Group: configure_register */ -/** Type of hp_active_dig_power register - * need_des - */ typedef union { struct { - uint32_t reserved_0:21; - /** hp_active_dcdc_switch_pd_en : R/W; bitpos: [21]; default: 0; - * need_des - */ - uint32_t hp_active_dcdc_switch_pd_en:1; - /** hp_active_hp_mem_dslp : R/W; bitpos: [22]; default: 0; - * need_des - */ - uint32_t hp_active_hp_mem_dslp:1; - /** hp_active_pd_hp_mem_pd_en : R/W; bitpos: [23]; default: 0; - * need_des - */ - uint32_t hp_active_pd_hp_mem_pd_en:1; - uint32_t reserved_24:6; - /** hp_active_pd_cnnt_pd_en : R/W; bitpos: [30]; default: 0; - * need_des - */ - uint32_t hp_active_pd_cnnt_pd_en:1; - /** hp_active_pd_top_pd_en : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t hp_active_pd_top_pd_en:1; + uint32_t reserved0 : 21; + // uint32_t vdd_spi_pd_en: 1; + uint32_t dcdc_switch_pd_en :1;//new + uint32_t mem_dslp : 1; + uint32_t mem_pd_en : 1; + // uint32_t wifi_pd_en : 1; + uint32_t reserved1 : 6; + // uint32_t cpu_pd_en : 1; + uint32_t cnnt_pd_en : 1; //new + // uint32_t aon_pd_en : 1; + uint32_t top_pd_en : 1; }; uint32_t val; -} pmu_hp_active_dig_power_reg_t; +} pmu_hp_dig_power_reg_t; -/** Type of hp_active_icg_hp_func register - * need_des - */ typedef union { struct { - /** hp_active_dig_icg_func_en : R/W; bitpos: [31:0]; default: 4294967295; - * need_des - */ - uint32_t hp_active_dig_icg_func_en:32; + uint32_t reserved0: 30; + uint32_t code : 2; }; uint32_t val; -} pmu_hp_active_icg_hp_func_reg_t; +} pmu_hp_icg_modem_reg_t; -/** Type of hp_active_icg_hp_apb register - * need_des - */ typedef union { struct { - /** hp_active_dig_icg_apb_en : R/W; bitpos: [31:0]; default: 4294967295; - * need_des - */ - uint32_t hp_active_dig_icg_apb_en:32; + uint32_t reserved0 : 23; + uint32_t power_det_bypass : 1; //new + uint32_t uart_wakeup_en : 1; + uint32_t lp_pad_hold_all: 1; + uint32_t hp_pad_hold_all: 1; + uint32_t dig_pad_slp_sel: 1; + uint32_t dig_pause_wdt : 1; + uint32_t dig_cpu_stall : 1; + uint32_t reserved1 : 2; }; uint32_t val; -} pmu_hp_active_icg_hp_apb_reg_t; +} pmu_hp_sys_cntl_reg_t; -/** Type of hp_active_icg_modem register - * need_des - */ typedef union { struct { - uint32_t reserved_0:30; - /** hp_active_dig_icg_modem_code : R/W; bitpos: [31:30]; default: 0; - * need_des - */ - uint32_t hp_active_dig_icg_modem_code:2; + uint32_t reserved0 : 21; + uint32_t i2c_iso_en : 1; + uint32_t i2c_retention: 1; + // uint32_t xpd_bb_i2c : 1; + uint32_t xpd_pll_i2c : 4; //cha + uint32_t xpd_pll : 4; //cha + uint32_t reserved1 : 1; }; uint32_t val; -} pmu_hp_active_icg_modem_reg_t; +} pmu_hp_clk_power_reg_t; -/** Type of hp_active_hp_sys_cntl register - * need_des - */ typedef union { struct { - uint32_t reserved_0:23; - /** hp_active_hp_power_det_bypass : R/W; bitpos: [23]; default: 0; - * need_des - */ - uint32_t hp_active_hp_power_det_bypass:1; - /** hp_active_uart_wakeup_en : R/W; bitpos: [24]; default: 0; - * need_des - */ - uint32_t hp_active_uart_wakeup_en:1; - /** hp_active_lp_pad_hold_all : R/W; bitpos: [25]; default: 0; - * need_des - */ - uint32_t hp_active_lp_pad_hold_all:1; - /** hp_active_hp_pad_hold_all : R/W; bitpos: [26]; default: 0; - * need_des - */ - uint32_t hp_active_hp_pad_hold_all:1; - /** hp_active_dig_pad_slp_sel : R/W; bitpos: [27]; default: 0; - * need_des - */ - uint32_t hp_active_dig_pad_slp_sel:1; - /** hp_active_dig_pause_wdt : R/W; bitpos: [28]; default: 0; - * need_des - */ - uint32_t hp_active_dig_pause_wdt:1; - /** hp_active_dig_cpu_stall : R/W; bitpos: [29]; default: 0; - * need_des - */ - uint32_t hp_active_dig_cpu_stall:1; - uint32_t reserved_30:2; + uint32_t reserved0 : 18; + uint32_t dcm_vset : 5; //new + uint32_t dcm_mode : 2; //new + uint32_t xpd_bias : 1; + uint32_t dbg_atten : 4; + uint32_t pd_cur : 1; + uint32_t bias_sleep: 1; }; uint32_t val; -} pmu_hp_active_hp_sys_cntl_reg_t; +} pmu_hp_bias_reg_t; + +typedef union { + struct { /* HP: Active State */ + uint32_t reserved0 : 4; + uint32_t hp_sleep2active_backup_modem_clk_code: 2; + uint32_t hp_modem2active_backup_modem_clk_code: 2; + uint32_t reserved1 : 2; + uint32_t hp_active_retention_mode : 1; + uint32_t hp_sleep2active_retention_en : 1; + uint32_t hp_modem2active_retention_en : 1; + uint32_t reserved2 : 1; + uint32_t hp_sleep2active_backup_clk_sel : 2; + uint32_t hp_modem2active_backup_clk_sel : 2; + uint32_t reserved3 : 2; + uint32_t hp_sleep2active_backup_mode : 3; + uint32_t hp_modem2active_backup_mode : 3; + uint32_t reserved4 : 3; + uint32_t hp_sleep2active_backup_en : 1; + uint32_t hp_modem2active_backup_en : 1; + uint32_t reserved5 : 1; + }; + struct { /* HP: Modem State */ + uint32_t reserved6 : 4; + uint32_t hp_sleep2modem_backup_modem_clk_code : 2; + uint32_t reserved7 : 4; + uint32_t hp_modem_retention_mode : 1; + uint32_t hp_sleep2modem_retention_en : 1; + uint32_t reserved8 : 2; + uint32_t hp_sleep2modem_backup_clk_sel : 2; + uint32_t reserved9 : 4; + uint32_t hp_sleep2modem_backup_mode : 3; + uint32_t reserved10 : 6; + uint32_t hp_sleep2modem_backup_en : 1; + uint32_t reserved11 : 2; + }; + struct { /* HP: Sleep State */ + uint32_t reserved12 : 6; + uint32_t hp_modem2sleep_backup_modem_clk_code : 2; + uint32_t hp_active2sleep_backup_modem_clk_code: 2; + uint32_t hp_sleep_retention_mode : 1; + uint32_t reserved13 : 1; + uint32_t hp_modem2sleep_retention_en : 1; + uint32_t hp_active2sleep_retention_en : 1; + uint32_t reserved14 : 2; + uint32_t hp_modem2sleep_backup_clk_sel : 2; + uint32_t hp_active2sleep_backup_clk_sel : 2; + uint32_t reserved15 : 3; + uint32_t hp_modem2sleep_backup_mode : 3; + uint32_t hp_active2sleep_backup_mode : 3; + uint32_t reserved16 : 1; + uint32_t hp_modem2sleep_backup_en : 1; + uint32_t hp_active2sleep_backup_en : 1; + }; + uint32_t val; +} pmu_hp_backup_reg_t; -/** Type of hp_active_hp_ck_power register - * need_des - */ typedef union { struct { - uint32_t reserved_0:21; - /** hp_active_i2c_iso_en : R/W; bitpos: [21]; default: 0; - * need_des - */ - uint32_t hp_active_i2c_iso_en:1; - /** hp_active_i2c_retention : R/W; bitpos: [22]; default: 0; - * need_des - */ - uint32_t hp_active_i2c_retention:1; - /** hp_active_xpd_pll_i2c : R/W; bitpos: [26:23]; default: 0; - * need_des - */ - uint32_t hp_active_xpd_pll_i2c:4; - /** hp_active_xpd_pll : R/W; bitpos: [30:27]; default: 0; - * need_des - */ - uint32_t hp_active_xpd_pll:4; - uint32_t reserved_31:1; + uint32_t reserved0 : 26; + uint32_t dig_sysclk_nodiv: 1; + uint32_t icg_sysclk_en : 1; + uint32_t sysclk_slp_sel : 1; + uint32_t icg_slp_sel : 1; + uint32_t dig_sysclk_sel : 2; }; uint32_t val; -} pmu_hp_active_hp_ck_power_reg_t; +} pmu_hp_sysclk_reg_t; -/** Type of hp_active_bias register - * need_des - */ typedef union { struct { - uint32_t reserved_0:18; - /** hp_active_dcm_vset : R/W; bitpos: [22:18]; default: 20; - * need_des - */ - uint32_t hp_active_dcm_vset:5; - /** hp_active_dcm_mode : R/W; bitpos: [24:23]; default: 0; - * need_des - */ - uint32_t hp_active_dcm_mode:2; - /** hp_active_xpd_bias : R/W; bitpos: [25]; default: 0; - * need_des - */ - uint32_t hp_active_xpd_bias:1; - /** hp_active_dbg_atten : R/W; bitpos: [29:26]; default: 0; - * need_des - */ - uint32_t hp_active_dbg_atten:4; - /** hp_active_pd_cur : R/W; bitpos: [30]; default: 0; - * need_des - */ - uint32_t hp_active_pd_cur:1; - /** hp_active_bias_sleep : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t hp_active_bias_sleep:1; + uint32_t reserved0 : 4; /* Only HP_ACTIVE modem under hp system is valid */ + uint32_t lp_dbias_vol : 5; /* Only HP_ACTIVE modem under hp system is valid */ + uint32_t hp_dbias_vol : 5; /* Only HP_ACTIVE modem under hp system is valid */ + uint32_t dbias_sel : 1; /* Only HP_ACTIVE modem under hp system is valid */ + uint32_t dbias_init : 1; /* Only HP_ACTIVE modem under hp system is valid */ + uint32_t slp_mem_xpd : 1; + uint32_t slp_logic_xpd : 1; + uint32_t xpd : 1; + uint32_t slp_mem_dbias : 4; + uint32_t slp_logic_dbias: 4; + uint32_t dbias : 5; }; uint32_t val; -} pmu_hp_active_bias_reg_t; +} pmu_hp_regulator0_reg_t; -/** Type of hp_active_backup register - * need_des - */ typedef union { struct { - uint32_t reserved_0:4; - /** hp_sleep2active_backup_modem_clk_code : R/W; bitpos: [5:4]; default: 0; - * need_des - */ - uint32_t hp_sleep2active_backup_modem_clk_code:2; - /** hp_modem2active_backup_modem_clk_code : R/W; bitpos: [7:6]; default: 0; - * need_des - */ - uint32_t hp_modem2active_backup_modem_clk_code:2; - uint32_t reserved_8:2; - /** hp_active_retention_mode : R/W; bitpos: [10]; default: 0; - * need_des - */ - uint32_t hp_active_retention_mode:1; - /** hp_sleep2active_retention_en : R/W; bitpos: [11]; default: 0; - * need_des - */ - uint32_t hp_sleep2active_retention_en:1; - /** hp_modem2active_retention_en : R/W; bitpos: [12]; default: 0; - * need_des - */ - uint32_t hp_modem2active_retention_en:1; - uint32_t reserved_13:1; - /** hp_sleep2active_backup_clk_sel : R/W; bitpos: [15:14]; default: 0; - * need_des - */ - uint32_t hp_sleep2active_backup_clk_sel:2; - /** hp_modem2active_backup_clk_sel : R/W; bitpos: [17:16]; default: 0; - * need_des - */ - uint32_t hp_modem2active_backup_clk_sel:2; - uint32_t reserved_18:2; - /** hp_sleep2active_backup_mode : R/W; bitpos: [22:20]; default: 0; - * need_des - */ - uint32_t hp_sleep2active_backup_mode:3; - /** hp_modem2active_backup_mode : R/W; bitpos: [25:23]; default: 0; - * need_des - */ - uint32_t hp_modem2active_backup_mode:3; - uint32_t reserved_26:3; - /** hp_sleep2active_backup_en : R/W; bitpos: [29]; default: 0; - * need_des - */ - uint32_t hp_sleep2active_backup_en:1; - /** hp_modem2active_backup_en : R/W; bitpos: [30]; default: 0; - * need_des - */ - uint32_t hp_modem2active_backup_en:1; - uint32_t reserved_31:1; + uint32_t reserved0: 26; + uint32_t drv_b : 6; }; uint32_t val; -} pmu_hp_active_backup_reg_t; +} pmu_hp_regulator1_reg_t; -/** Type of hp_active_backup_clk register - * need_des - */ typedef union { struct { - /** hp_active_backup_icg_func_en : R/W; bitpos: [31:0]; default: 0; - * need_des - */ - uint32_t hp_active_backup_icg_func_en:32; + uint32_t reserved0: 31; + uint32_t xpd_xtal : 1; }; uint32_t val; -} pmu_hp_active_backup_clk_reg_t; +} pmu_hp_xtal_reg_t; -/** Type of hp_active_sysclk register - * need_des - */ +typedef struct pmu_hp_hw_regmap_t { + pmu_hp_dig_power_reg_t dig_power; + uint32_t icg_func; + uint32_t icg_apb; + pmu_hp_icg_modem_reg_t icg_modem; + pmu_hp_sys_cntl_reg_t syscntl; + pmu_hp_clk_power_reg_t clk_power; + pmu_hp_bias_reg_t bias; + pmu_hp_backup_reg_t backup; + uint32_t backup_clk; + pmu_hp_sysclk_reg_t sysclk; + pmu_hp_regulator0_reg_t regulator0; + pmu_hp_regulator1_reg_t regulator1; + pmu_hp_xtal_reg_t xtal; +} pmu_hp_hw_regmap_t; + +/** */ typedef union { struct { - uint32_t reserved_0:26; - /** hp_active_dig_sys_clk_no_div : R/W; bitpos: [26]; default: 0; - * need_des - */ - uint32_t hp_active_dig_sys_clk_no_div:1; - /** hp_active_icg_sys_clock_en : R/W; bitpos: [27]; default: 0; - * need_des - */ - uint32_t hp_active_icg_sys_clock_en:1; - /** hp_active_sys_clk_slp_sel : R/W; bitpos: [28]; default: 0; - * need_des - */ - uint32_t hp_active_sys_clk_slp_sel:1; - /** hp_active_icg_slp_sel : R/W; bitpos: [29]; default: 0; - * need_des - */ - uint32_t hp_active_icg_slp_sel:1; - /** hp_active_dig_sys_clk_sel : R/W; bitpos: [31:30]; default: 0; - * need_des - */ - uint32_t hp_active_dig_sys_clk_sel:2; + uint32_t reserved0: 21; + uint32_t slp_xpd : 1; + uint32_t xpd : 1; + uint32_t slp_dbias: 4; + uint32_t dbias : 5; }; uint32_t val; -} pmu_hp_active_sysclk_reg_t; +} pmu_lp_regulator0_reg_t; -/** Type of hp_active_hp_regulator0 register - * need_des - */ typedef union { struct { - uint32_t reserved_0:4; - /** lp_dbias_vol : RO; bitpos: [8:4]; default: 24; - * need_des - */ - uint32_t lp_dbias_vol:5; - /** hp_dbias_vol : RO; bitpos: [13:9]; default: 24; - * need_des - */ - uint32_t hp_dbias_vol:5; - /** dig_regulator0_dbias_sel : R/W; bitpos: [14]; default: 1; - * need_des - */ - uint32_t dig_regulator0_dbias_sel:1; - /** dig_dbias_init : WT; bitpos: [15]; default: 0; - * need_des - */ - uint32_t dig_dbias_init:1; - /** hp_active_hp_regulator_slp_mem_xpd : R/W; bitpos: [16]; default: 1; - * need_des - */ - uint32_t hp_active_hp_regulator_slp_mem_xpd:1; - /** hp_active_hp_regulator_slp_logic_xpd : R/W; bitpos: [17]; default: 1; - * need_des - */ - uint32_t hp_active_hp_regulator_slp_logic_xpd:1; - /** hp_active_hp_regulator_xpd : R/W; bitpos: [18]; default: 1; - * need_des - */ - uint32_t hp_active_hp_regulator_xpd:1; - /** hp_active_hp_regulator_slp_mem_dbias : R/W; bitpos: [22:19]; default: 12; - * need_des - */ - uint32_t hp_active_hp_regulator_slp_mem_dbias:4; - /** hp_active_hp_regulator_slp_logic_dbias : R/W; bitpos: [26:23]; default: 12; - * need_des - */ - uint32_t hp_active_hp_regulator_slp_logic_dbias:4; - /** hp_active_hp_regulator_dbias : R/W; bitpos: [31:27]; default: 24; - * need_des - */ - uint32_t hp_active_hp_regulator_dbias:5; + uint32_t reserved0: 28; + uint32_t drv_b : 4; }; uint32_t val; -} pmu_hp_active_hp_regulator0_reg_t; +} pmu_lp_regulator1_reg_t; -/** Type of hp_active_hp_regulator1 register - * need_des - */ typedef union { struct { - uint32_t reserved_0:26; - /** hp_active_hp_regulator_drv_b : R/W; bitpos: [31:26]; default: 0; - * need_des - */ - uint32_t hp_active_hp_regulator_drv_b:6; + uint32_t reserved0: 31; + uint32_t xpd_xtal : 1; }; uint32_t val; -} pmu_hp_active_hp_regulator1_reg_t; +} pmu_lp_xtal_reg_t; -/** Type of hp_active_xtal register - * need_des - */ typedef union { struct { - uint32_t reserved_0:31; - /** hp_active_xpd_xtal : R/W; bitpos: [31]; default: 1; - * need_des - */ - uint32_t hp_active_xpd_xtal:1; + uint32_t reserved0 : 26; + uint32_t lp_pad_slp_sel : 1; //new + uint32_t bod_source_sel : 1; //new + uint32_t vddbat_mode : 2; //new + uint32_t mem_dslp : 1; + uint32_t peri_pd_en: 1; }; uint32_t val; -} pmu_hp_active_xtal_reg_t; +} pmu_lp_dig_power_reg_t; -/** Type of hp_modem_dig_power register - * need_des - */ typedef union { struct { - uint32_t reserved_0:21; - /** hp_modem_dcdc_switch_pd_en : R/W; bitpos: [21]; default: 0; - * need_des - */ - uint32_t hp_modem_dcdc_switch_pd_en:1; - /** hp_modem_hp_mem_dslp : WT; bitpos: [22]; default: 0; - * need_des - */ - uint32_t hp_modem_hp_mem_dslp:1; - /** hp_modem_pd_hp_mem_pd_en : WT; bitpos: [26:23]; default: 0; - * need_des - */ - uint32_t hp_modem_pd_hp_mem_pd_en:4; - /** hp_modem_pd_hp_wifi_pd_en : WT; bitpos: [27]; default: 0; - * need_des - */ - uint32_t hp_modem_pd_hp_wifi_pd_en:1; - uint32_t reserved_28:1; - /** hp_modem_pd_hp_cpu_pd_en : WT; bitpos: [29]; default: 0; - * need_des - */ - uint32_t hp_modem_pd_hp_cpu_pd_en:1; - /** hp_modem_pd_cnnt_pd_en : WT; bitpos: [30]; default: 0; - * need_des - */ - uint32_t hp_modem_pd_cnnt_pd_en:1; - /** hp_modem_pd_top_pd_en : WT; bitpos: [31]; default: 0; - * need_des - */ - uint32_t hp_modem_pd_top_pd_en:1; + uint32_t reserved0 : 27; + uint32_t xpd_lppll : 1; //new + uint32_t xpd_xtal32k: 1; + uint32_t xpd_rc32k : 1; + uint32_t xpd_fosc : 1; + uint32_t pd_osc : 1; }; uint32_t val; -} pmu_hp_modem_dig_power_reg_t; +} pmu_lp_clk_power_reg_t; -/** Type of hp_modem_icg_hp_func register - * need_des - */ typedef union { struct { - /** hp_modem_dig_icg_func_en : WT; bitpos: [31:0]; default: 4294967295; - * need_des - */ - uint32_t hp_modem_dig_icg_func_en:32; + uint32_t reserved0 : 25; + uint32_t xpd_bias : 1; + uint32_t dbg_atten : 4; + uint32_t pd_cur : 1; + uint32_t bias_sleep: 1; }; uint32_t val; -} pmu_hp_modem_icg_hp_func_reg_t; +} pmu_lp_bias_reg_t; + +typedef struct pmu_lp_hw_regmap_t { + pmu_lp_regulator0_reg_t regulator0; + pmu_lp_regulator1_reg_t regulator1; + pmu_lp_xtal_reg_t xtal; /* Only LP_SLEEP mode under lp system is valid */ + pmu_lp_dig_power_reg_t dig_power; + pmu_lp_clk_power_reg_t clk_power; + pmu_lp_bias_reg_t bias; /* Only LP_SLEEP mode under lp system is valid */ +} pmu_lp_hw_regmap_t; + -/** Type of hp_modem_icg_hp_apb register - * need_des - */ typedef union { struct { - /** hp_modem_dig_icg_apb_en : WT; bitpos: [31:0]; default: 4294967295; - * need_des - */ - uint32_t hp_modem_dig_icg_apb_en:32; + uint32_t tie_low_cali_xtal_icg : 1; //new + uint32_t tie_low_global_pll_icg : 4; + uint32_t tie_low_global_xtal_icg : 1; + uint32_t tie_low_i2c_retention : 1; + // uint32_t tie_low_xpd_bb_i2c : 1; + uint32_t tie_low_xpd_pll_i2c : 4; + uint32_t tie_low_xpd_pll : 4; + uint32_t tie_low_xpd_xtal : 1; + uint32_t tie_high_cali_xtal_icg : 1; //new + uint32_t tie_high_global_pll_icg : 4; + // uint32_t tie_high_global_bbpll_icg: 1; + uint32_t tie_high_global_xtal_icg : 1; + uint32_t tie_high_i2c_retention : 1; + // uint32_t tie_high_xpd_bb_i2c : 1; + uint32_t tie_high_xpd_pll_i2c : 4; + // uint32_t tie_high_xpd_bbpll_i2c : 1; + uint32_t tie_high_xpd_pll : 4; + // uint32_t tie_high_xpd_bbpll : 1; + uint32_t tie_high_xpd_xtal : 1; }; uint32_t val; -} pmu_hp_modem_icg_hp_apb_reg_t; +} pmu_imm_hp_clk_power_reg_t; -/** Type of hp_modem_icg_modem register - * need_des - */ typedef union { struct { - uint32_t reserved_0:30; - /** hp_modem_dig_icg_modem_code : WT; bitpos: [31:30]; default: 0; - * need_des - */ - uint32_t hp_modem_dig_icg_modem_code:2; + uint32_t reserved0 : 28; + uint32_t update_dig_icg_switch: 1; + uint32_t tie_low_icg_slp_sel : 1; + uint32_t tie_high_icg_slp_sel : 1; + uint32_t update_dig_sysclk_sel: 1; }; uint32_t val; -} pmu_hp_modem_icg_modem_reg_t; +} pmu_imm_sleep_sysclk_reg_t; -/** Type of hp_modem_hp_sys_cntl register - * need_des - */ typedef union { struct { - uint32_t reserved_0:23; - /** hp_modem_hp_power_det_bypass : WT; bitpos: [23]; default: 0; - * need_des - */ - uint32_t hp_modem_hp_power_det_bypass:1; - /** hp_modem_uart_wakeup_en : WT; bitpos: [24]; default: 0; - * need_des - */ - uint32_t hp_modem_uart_wakeup_en:1; - /** hp_modem_lp_pad_hold_all : WT; bitpos: [25]; default: 0; - * need_des - */ - uint32_t hp_modem_lp_pad_hold_all:1; - /** hp_modem_hp_pad_hold_all : WT; bitpos: [26]; default: 0; - * need_des - */ - uint32_t hp_modem_hp_pad_hold_all:1; - /** hp_modem_dig_pad_slp_sel : WT; bitpos: [27]; default: 0; - * need_des - */ - uint32_t hp_modem_dig_pad_slp_sel:1; - /** hp_modem_dig_pause_wdt : WT; bitpos: [28]; default: 0; - * need_des - */ - uint32_t hp_modem_dig_pause_wdt:1; - /** hp_modem_dig_cpu_stall : WT; bitpos: [29]; default: 0; - * need_des - */ - uint32_t hp_modem_dig_cpu_stall:1; - uint32_t reserved_30:2; + uint32_t reserved0 : 31; + uint32_t update_dig_icg_func_en: 1; }; uint32_t val; -} pmu_hp_modem_hp_sys_cntl_reg_t; +} pmu_imm_hp_func_icg_reg_t; -/** Type of hp_modem_hp_ck_power register - * need_des - */ typedef union { struct { - uint32_t reserved_0:21; - /** hp_modem_i2c_iso_en : WT; bitpos: [21]; default: 0; - * need_des - */ - uint32_t hp_modem_i2c_iso_en:1; - /** hp_modem_i2c_retention : WT; bitpos: [22]; default: 0; - * need_des - */ - uint32_t hp_modem_i2c_retention:1; - /** hp_modem_xpd_pll_i2c : WT; bitpos: [26:23]; default: 0; - * need_des - */ - uint32_t hp_modem_xpd_pll_i2c:4; - /** hp_modem_xpd_pll : WT; bitpos: [30:27]; default: 0; - * need_des - */ - uint32_t hp_modem_xpd_pll:4; - uint32_t reserved_31:1; + uint32_t reserved0 : 31; + uint32_t update_dig_icg_apb_en: 1; }; uint32_t val; -} pmu_hp_modem_hp_ck_power_reg_t; +} pmu_imm_hp_apb_icg_reg_t; -/** Type of hp_modem_bias register - * need_des - */ typedef union { struct { - uint32_t reserved_0:18; - /** hp_modem_dcm_vset : WT; bitpos: [22:18]; default: 20; - * need_des - */ - uint32_t hp_modem_dcm_vset:5; - /** hp_modem_dcm_mode : WT; bitpos: [24:23]; default: 0; - * need_des - */ - uint32_t hp_modem_dcm_mode:2; - /** hp_modem_xpd_bias : WT; bitpos: [25]; default: 0; - * need_des - */ - uint32_t hp_modem_xpd_bias:1; - /** hp_modem_dbg_atten : WT; bitpos: [29:26]; default: 0; - * need_des - */ - uint32_t hp_modem_dbg_atten:4; - /** hp_modem_pd_cur : WT; bitpos: [30]; default: 0; - * need_des - */ - uint32_t hp_modem_pd_cur:1; - /** hp_modem_bias_sleep : WT; bitpos: [31]; default: 0; - * need_des - */ - uint32_t hp_modem_bias_sleep:1; + uint32_t reserved0 : 31; + uint32_t update_dig_icg_modem_en: 1; }; uint32_t val; -} pmu_hp_modem_bias_reg_t; +} pmu_imm_modem_icg_reg_t; -/** Type of hp_modem_backup register - * need_des - */ typedef union { struct { - uint32_t reserved_0:4; - /** hp_sleep2modem_backup_modem_clk_code : WT; bitpos: [5:4]; default: 0; - * need_des - */ - uint32_t hp_sleep2modem_backup_modem_clk_code:2; - uint32_t reserved_6:4; - /** hp_modem_retention_mode : WT; bitpos: [10]; default: 0; - * need_des - */ - uint32_t hp_modem_retention_mode:1; - /** hp_sleep2modem_retention_en : WT; bitpos: [11]; default: 0; - * need_des - */ - uint32_t hp_sleep2modem_retention_en:1; - uint32_t reserved_12:2; - /** hp_sleep2modem_backup_clk_sel : WT; bitpos: [15:14]; default: 0; - * need_des - */ - uint32_t hp_sleep2modem_backup_clk_sel:2; - uint32_t reserved_16:4; - /** hp_sleep2modem_backup_mode : WT; bitpos: [22:20]; default: 0; - * need_des - */ - uint32_t hp_sleep2modem_backup_mode:3; - uint32_t reserved_23:6; - /** hp_sleep2modem_backup_en : WT; bitpos: [29]; default: 0; - * need_des - */ - uint32_t hp_sleep2modem_backup_en:1; - uint32_t reserved_30:2; + uint32_t reserved0 : 30; + uint32_t tie_low_lp_rootclk_sel : 1; + uint32_t tie_high_lp_rootclk_sel: 1; }; uint32_t val; -} pmu_hp_modem_backup_reg_t; +} pmu_imm_lp_icg_reg_t; -/** Type of hp_modem_backup_clk register - * need_des - */ typedef union { struct { - /** hp_modem_backup_icg_func_en : WT; bitpos: [31:0]; default: 0; - * need_des - */ - uint32_t hp_modem_backup_icg_func_en:32; + uint32_t pad_slp_sel : 1;//new + uint32_t lp_pad_hold_all : 1;//new + uint32_t hp_pad_hold_all : 1;//new + uint32_t reserved0 : 23; + uint32_t tie_high_pad_slp_sel : 1;//new + uint32_t tie_low_pad_slp_sel : 1;//new + uint32_t tie_high_lp_pad_hold_all: 1; + uint32_t tie_low_lp_pad_hold_all : 1; + uint32_t tie_high_hp_pad_hold_all: 1; + uint32_t tie_low_hp_pad_hold_all : 1; }; uint32_t val; -} pmu_hp_modem_backup_clk_reg_t; +} pmu_imm_pad_hold_all_reg_t; -/** Type of hp_modem_sysclk register - * need_des - */ typedef union { struct { - uint32_t reserved_0:26; - /** hp_modem_dig_sys_clk_no_div : WT; bitpos: [26]; default: 0; - * need_des - */ - uint32_t hp_modem_dig_sys_clk_no_div:1; - /** hp_modem_icg_sys_clock_en : WT; bitpos: [27]; default: 0; - * need_des - */ - uint32_t hp_modem_icg_sys_clock_en:1; - /** hp_modem_sys_clk_slp_sel : WT; bitpos: [28]; default: 0; - * need_des - */ - uint32_t hp_modem_sys_clk_slp_sel:1; - /** hp_modem_icg_slp_sel : WT; bitpos: [29]; default: 0; - * need_des - */ - uint32_t hp_modem_icg_slp_sel:1; - /** hp_modem_dig_sys_clk_sel : WT; bitpos: [31:30]; default: 0; - * need_des - */ - uint32_t hp_modem_dig_sys_clk_sel:2; + uint32_t reserved0 : 30; + uint32_t tie_high_i2c_iso_en: 1; + uint32_t tie_low_i2c_iso_en : 1; }; uint32_t val; -} pmu_hp_modem_sysclk_reg_t; +} pmu_imm_i2c_isolate_reg_t; + +typedef struct pmu_imm_hw_regmap_t { + pmu_imm_hp_clk_power_reg_t clk_power; + pmu_imm_sleep_sysclk_reg_t sleep_sysclk; + pmu_imm_hp_func_icg_reg_t hp_func_icg; + pmu_imm_hp_apb_icg_reg_t hp_apb_icg; + pmu_imm_modem_icg_reg_t modem_icg; + pmu_imm_lp_icg_reg_t lp_icg; + pmu_imm_pad_hold_all_reg_t pad_hold_all; + pmu_imm_i2c_isolate_reg_t i2c_iso; +} pmu_imm_hw_regmap_t; -/** Type of hp_modem_hp_regulator0 register - * need_des - */ typedef union { struct { - uint32_t reserved_0:16; - /** hp_modem_hp_regulator_slp_mem_xpd : WT; bitpos: [16]; default: 1; - * need_des - */ - uint32_t hp_modem_hp_regulator_slp_mem_xpd:1; - /** hp_modem_hp_regulator_slp_logic_xpd : WT; bitpos: [17]; default: 1; - * need_des - */ - uint32_t hp_modem_hp_regulator_slp_logic_xpd:1; - /** hp_modem_hp_regulator_xpd : WT; bitpos: [18]; default: 1; - * need_des - */ - uint32_t hp_modem_hp_regulator_xpd:1; - /** hp_modem_hp_regulator_slp_mem_dbias : WT; bitpos: [22:19]; default: 12; - * need_des - */ - uint32_t hp_modem_hp_regulator_slp_mem_dbias:4; - /** hp_modem_hp_regulator_slp_logic_dbias : WT; bitpos: [26:23]; default: 12; - * need_des - */ - uint32_t hp_modem_hp_regulator_slp_logic_dbias:4; - /** hp_modem_hp_regulator_dbias : WT; bitpos: [31:27]; default: 24; - * need_des - */ - uint32_t hp_modem_hp_regulator_dbias:5; - }; - uint32_t val; -} pmu_hp_modem_hp_regulator0_reg_t; - -/** Type of hp_modem_hp_regulator1 register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:8; - /** hp_modem_hp_regulator_drv_b : WT; bitpos: [31:8]; default: 0; - * need_des - */ - uint32_t hp_modem_hp_regulator_drv_b:24; - }; - uint32_t val; -} pmu_hp_modem_hp_regulator1_reg_t; - -/** Type of hp_modem_xtal register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:31; - /** hp_modem_xpd_xtal : WT; bitpos: [31]; default: 1; - * need_des - */ - uint32_t hp_modem_xpd_xtal:1; - }; - uint32_t val; -} pmu_hp_modem_xtal_reg_t; - -/** Type of hp_sleep_dig_power register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:21; - /** hp_sleep_dcdc_switch_pd_en : R/W; bitpos: [21]; default: 0; - * need_des - */ - uint32_t hp_sleep_dcdc_switch_pd_en:1; - /** hp_sleep_hp_mem_dslp : R/W; bitpos: [22]; default: 0; - * need_des - */ - uint32_t hp_sleep_hp_mem_dslp:1; - /** hp_sleep_pd_hp_mem_pd_en : R/W; bitpos: [23]; default: 0; - * need_des - */ - uint32_t hp_sleep_pd_hp_mem_pd_en:1; - uint32_t reserved_24:6; - /** hp_sleep_pd_cnnt_pd_en : R/W; bitpos: [30]; default: 0; - * need_des - */ - uint32_t hp_sleep_pd_cnnt_pd_en:1; - /** hp_sleep_pd_top_pd_en : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t hp_sleep_pd_top_pd_en:1; + uint32_t reserved0 : 5; + uint32_t powerdown_timer: 9; + uint32_t powerup_timer : 9; + uint32_t wait_timer : 9; }; uint32_t val; -} pmu_hp_sleep_dig_power_reg_t; +} pmu_power_wait_timer0_reg_t; -/** Type of hp_sleep_icg_hp_func register - * need_des - */ typedef union { struct { - /** hp_sleep_dig_icg_func_en : R/W; bitpos: [31:0]; default: 4294967295; - * need_des - */ - uint32_t hp_sleep_dig_icg_func_en:32; + uint32_t reserved0 : 5; + uint32_t powerdown_timer: 9; + uint32_t powerup_timer : 9; + uint32_t wait_timer : 9; }; uint32_t val; -} pmu_hp_sleep_icg_hp_func_reg_t; +} pmu_power_wait_timer1_reg_t; -/** Type of hp_sleep_icg_hp_apb register - * need_des - */ typedef union { struct { - /** hp_sleep_dig_icg_apb_en : R/W; bitpos: [31:0]; default: 4294967295; - * need_des - */ - uint32_t hp_sleep_dig_icg_apb_en:32; + uint32_t force_reset : 1; + uint32_t force_iso : 1; + uint32_t force_pu : 1; + uint32_t force_no_reset: 1; + uint32_t force_no_iso : 1; + uint32_t force_pd : 1; + // uint32_t pd_top_mask : 5; + uint32_t reserved0 : 26; /* Invalid of lp peripherals */ + // uint32_t top_pd_mask : 5; }; uint32_t val; -} pmu_hp_sleep_icg_hp_apb_reg_t; +} pmu_power_domain_cntl_t; -/** Type of hp_sleep_icg_modem register - * need_des - */ typedef union { struct { - uint32_t reserved_0:30; - /** hp_sleep_dig_icg_modem_code : R/W; bitpos: [31:30]; default: 0; - * need_des - */ - uint32_t hp_sleep_dig_icg_modem_code:2; + uint32_t pd_top_mask : 5; + uint32_t reserved0 : 22; /* Invalid of lp peripherals */ + uint32_t top_pd_mask : 5; }; uint32_t val; -} pmu_hp_sleep_icg_modem_reg_t; +} pmu_power_domain_mask_t; -/** Type of hp_sleep_hp_sys_cntl register - * need_des - */ typedef union { struct { - uint32_t reserved_0:23; - /** hp_sleep_hp_power_det_bypass : R/W; bitpos: [23]; default: 0; - * need_des - */ - uint32_t hp_sleep_hp_power_det_bypass:1; - /** hp_sleep_uart_wakeup_en : R/W; bitpos: [24]; default: 0; - * need_des - */ - uint32_t hp_sleep_uart_wakeup_en:1; - /** hp_sleep_lp_pad_hold_all : R/W; bitpos: [25]; default: 0; - * need_des - */ - uint32_t hp_sleep_lp_pad_hold_all:1; - /** hp_sleep_hp_pad_hold_all : R/W; bitpos: [26]; default: 0; - * need_des - */ - uint32_t hp_sleep_hp_pad_hold_all:1; - /** hp_sleep_dig_pad_slp_sel : R/W; bitpos: [27]; default: 0; - * need_des - */ - uint32_t hp_sleep_dig_pad_slp_sel:1; - /** hp_sleep_dig_pause_wdt : R/W; bitpos: [28]; default: 0; - * need_des - */ - uint32_t hp_sleep_dig_pause_wdt:1; - /** hp_sleep_dig_cpu_stall : R/W; bitpos: [29]; default: 0; - * need_des - */ - uint32_t hp_sleep_dig_cpu_stall:1; - uint32_t reserved_30:2; + uint32_t force_pu : 1; /*need_des*/ + uint32_t force_pd : 1; /*need_des*/ + uint32_t reserved2 : 30; }; uint32_t val; -} pmu_hp_sleep_hp_sys_cntl_reg_t; +} pmu_power_dcdc_switch_t; +// typedef union { +// struct { +// uint32_t force_hp_mem_iso : 4; +// uint32_t force_hp_mem_pd : 4; +// uint32_t reserved0 : 16; +// uint32_t force_hp_mem_no_iso: 4; +// uint32_t force_hp_mem_pu : 4; +// }; +// uint32_t val; +// } pmu_power_memory_cntl_reg_t; -/** Type of hp_sleep_hp_ck_power register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:21; - /** hp_sleep_i2c_iso_en : R/W; bitpos: [21]; default: 0; - * need_des - */ - uint32_t hp_sleep_i2c_iso_en:1; - /** hp_sleep_i2c_retention : R/W; bitpos: [22]; default: 0; - * need_des - */ - uint32_t hp_sleep_i2c_retention:1; - /** hp_sleep_xpd_pll_i2c : R/W; bitpos: [26:23]; default: 0; - * need_des - */ - uint32_t hp_sleep_xpd_pll_i2c:4; - /** hp_sleep_xpd_pll : R/W; bitpos: [30:27]; default: 0; - * need_des - */ - uint32_t hp_sleep_xpd_pll:4; - uint32_t reserved_31:1; - }; - uint32_t val; -} pmu_hp_sleep_hp_ck_power_reg_t; +// typedef union { +// struct { +// uint32_t mem2_pd_mask: 5; +// uint32_t mem1_pd_mask: 5; +// uint32_t mem0_pd_mask: 5; +// uint32_t reserved0 : 2; +// uint32_t mem2_mask : 5; +// uint32_t mem1_mask : 5; +// uint32_t mem0_mask : 5; +// }; +// uint32_t val; +// } pmu_power_memory_mask_reg_t; -/** Type of hp_sleep_bias register - * need_des - */ typedef union { struct { - uint32_t reserved_0:18; - /** hp_sleep_dcm_vset : R/W; bitpos: [22:18]; default: 20; - * need_des - */ - uint32_t hp_sleep_dcm_vset:5; - /** hp_sleep_dcm_mode : R/W; bitpos: [24:23]; default: 0; - * need_des - */ - uint32_t hp_sleep_dcm_mode:2; - /** hp_sleep_xpd_bias : R/W; bitpos: [25]; default: 0; - * need_des - */ - uint32_t hp_sleep_xpd_bias:1; - /** hp_sleep_dbg_atten : R/W; bitpos: [29:26]; default: 0; - * need_des - */ - uint32_t hp_sleep_dbg_atten:4; - /** hp_sleep_pd_cur : R/W; bitpos: [30]; default: 0; - * need_des - */ - uint32_t hp_sleep_pd_cur:1; - /** hp_sleep_bias_sleep : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t hp_sleep_bias_sleep:1; + uint32_t force_hp_pad_no_iso_all: 1; + uint32_t force_hp_pad_iso_all : 1; + uint32_t reserved0 : 30; }; uint32_t val; -} pmu_hp_sleep_bias_reg_t; +} pmu_power_hp_pad_reg_t; -/** Type of hp_sleep_backup register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:6; - /** hp_modem2sleep_backup_modem_clk_code : R/W; bitpos: [7:6]; default: 0; - * need_des - */ - uint32_t hp_modem2sleep_backup_modem_clk_code:2; - /** hp_active2sleep_backup_modem_clk_code : R/W; bitpos: [9:8]; default: 0; - * need_des - */ - uint32_t hp_active2sleep_backup_modem_clk_code:2; - /** hp_sleep_retention_mode : R/W; bitpos: [10]; default: 0; - * need_des - */ - uint32_t hp_sleep_retention_mode:1; - uint32_t reserved_11:1; - /** hp_modem2sleep_retention_en : R/W; bitpos: [12]; default: 0; - * need_des - */ - uint32_t hp_modem2sleep_retention_en:1; - /** hp_active2sleep_retention_en : R/W; bitpos: [13]; default: 0; - * need_des - */ - uint32_t hp_active2sleep_retention_en:1; - uint32_t reserved_14:2; - /** hp_modem2sleep_backup_clk_sel : R/W; bitpos: [17:16]; default: 0; - * need_des - */ - uint32_t hp_modem2sleep_backup_clk_sel:2; - /** hp_active2sleep_backup_clk_sel : R/W; bitpos: [19:18]; default: 0; - * need_des - */ - uint32_t hp_active2sleep_backup_clk_sel:2; - uint32_t reserved_20:3; - /** hp_modem2sleep_backup_mode : R/W; bitpos: [25:23]; default: 0; - * need_des - */ - uint32_t hp_modem2sleep_backup_mode:3; - /** hp_active2sleep_backup_mode : R/W; bitpos: [28:26]; default: 0; - * need_des - */ - uint32_t hp_active2sleep_backup_mode:3; - uint32_t reserved_29:1; - /** hp_modem2sleep_backup_en : R/W; bitpos: [30]; default: 0; - * need_des - */ - uint32_t hp_modem2sleep_backup_en:1; - /** hp_active2sleep_backup_en : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t hp_active2sleep_backup_en:1; - }; - uint32_t val; -} pmu_hp_sleep_backup_reg_t; +// typedef union { +// struct { +// uint32_t reserved0 : 18; +// uint32_t pwr_wait : 11; +// uint32_t pwr_sw : 2; +// uint32_t pwr_sel_sw: 1; +// }; +// uint32_t val; +// } pmu_power_vdd_spi_cntl_reg_t; -/** Type of hp_sleep_backup_clk register - * need_des - */ typedef union { struct { - /** hp_sleep_backup_icg_func_en : R/W; bitpos: [31:0]; default: 0; - * need_des - */ - uint32_t hp_sleep_backup_icg_func_en:32; + uint32_t wait_xtal_stable: 16; + uint32_t wait_pll_stable : 16; }; uint32_t val; -} pmu_hp_sleep_backup_clk_reg_t; +} pmu_power_clk_wait_cntl_reg_t; -/** Type of hp_sleep_sysclk register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:26; - /** hp_sleep_dig_sys_clk_no_div : R/W; bitpos: [26]; default: 0; - * need_des - */ - uint32_t hp_sleep_dig_sys_clk_no_div:1; - /** hp_sleep_icg_sys_clock_en : R/W; bitpos: [27]; default: 0; - * need_des - */ - uint32_t hp_sleep_icg_sys_clock_en:1; - /** hp_sleep_sys_clk_slp_sel : R/W; bitpos: [28]; default: 0; - * need_des - */ - uint32_t hp_sleep_sys_clk_slp_sel:1; - /** hp_sleep_icg_slp_sel : R/W; bitpos: [29]; default: 0; - * need_des - */ - uint32_t hp_sleep_icg_slp_sel:1; - /** hp_sleep_dig_sys_clk_sel : R/W; bitpos: [31:30]; default: 0; - * need_des - */ - uint32_t hp_sleep_dig_sys_clk_sel:2; - }; - uint32_t val; -} pmu_hp_sleep_sysclk_reg_t; +typedef struct pmu_power_hw_regmap_t { + pmu_power_wait_timer0_reg_t wait_timer0; + pmu_power_wait_timer1_reg_t wait_timer1; + pmu_power_domain_cntl_t hp_pd[3]; + pmu_power_domain_mask_t hp_pd_mask[3]; + pmu_power_dcdc_switch_t dcdc_switch; + pmu_power_domain_cntl_t lp_peri; + pmu_power_domain_mask_t lp_peri_mask; + // pmu_power_memory_cntl_reg_t mem_cntl; + // pmu_power_memory_mask_reg_t mem_mask; + pmu_power_hp_pad_reg_t hp_pad; + // pmu_power_vdd_spi_cntl_reg_t vdd_spi; + pmu_power_clk_wait_cntl_reg_t clk_wait; +} pmu_power_hw_regmap_t; -/** Type of hp_sleep_hp_regulator0 register - * need_des - */ typedef union { struct { - uint32_t reserved_0:16; - /** hp_sleep_hp_regulator_slp_mem_xpd : R/W; bitpos: [16]; default: 1; - * need_des - */ - uint32_t hp_sleep_hp_regulator_slp_mem_xpd:1; - /** hp_sleep_hp_regulator_slp_logic_xpd : R/W; bitpos: [17]; default: 1; - * need_des - */ - uint32_t hp_sleep_hp_regulator_slp_logic_xpd:1; - /** hp_sleep_hp_regulator_xpd : R/W; bitpos: [18]; default: 1; - * need_des - */ - uint32_t hp_sleep_hp_regulator_xpd:1; - /** hp_sleep_hp_regulator_slp_mem_dbias : R/W; bitpos: [22:19]; default: 12; - * need_des - */ - uint32_t hp_sleep_hp_regulator_slp_mem_dbias:4; - /** hp_sleep_hp_regulator_slp_logic_dbias : R/W; bitpos: [26:23]; default: 12; - * need_des - */ - uint32_t hp_sleep_hp_regulator_slp_logic_dbias:4; - /** hp_sleep_hp_regulator_dbias : R/W; bitpos: [31:27]; default: 24; - * need_des - */ - uint32_t hp_sleep_hp_regulator_dbias:5; + uint32_t reserved0: 31; + uint32_t sleep_req: 1; }; uint32_t val; -} pmu_hp_sleep_hp_regulator0_reg_t; +} pmu_slp_wakeup_cntl0_reg_t; -/** Type of hp_sleep_hp_regulator1 register - * need_des - */ typedef union { struct { - uint32_t reserved_0:26; - /** hp_sleep_hp_regulator_drv_b : R/W; bitpos: [31:26]; default: 0; - * need_des - */ - uint32_t hp_sleep_hp_regulator_drv_b:6; + uint32_t sleep_reject_ena: 31; + uint32_t slp_reject_en : 1; }; uint32_t val; -} pmu_hp_sleep_hp_regulator1_reg_t; +} pmu_slp_wakeup_cntl1_reg_t; -/** Type of hp_sleep_xtal register - * need_des - */ typedef union { struct { - uint32_t reserved_0:31; - /** hp_sleep_xpd_xtal : R/W; bitpos: [31]; default: 1; - * need_des - */ - uint32_t hp_sleep_xpd_xtal:1; + uint32_t lp_min_slp_val: 8; + uint32_t hp_min_slp_val: 8; + uint32_t sleep_prt_sel : 2; + uint32_t reserved0 : 14; }; uint32_t val; -} pmu_hp_sleep_xtal_reg_t; +} pmu_slp_wakeup_cntl3_reg_t; -/** Type of hp_sleep_lp_regulator0 register - * need_des - */ typedef union { struct { - uint32_t reserved_0:21; - /** hp_sleep_lp_regulator_slp_xpd : R/W; bitpos: [21]; default: 1; - * need_des - */ - uint32_t hp_sleep_lp_regulator_slp_xpd:1; - /** hp_sleep_lp_regulator_xpd : R/W; bitpos: [22]; default: 1; - * need_des - */ - uint32_t hp_sleep_lp_regulator_xpd:1; - /** hp_sleep_lp_regulator_slp_dbias : R/W; bitpos: [26:23]; default: 12; - * need_des - */ - uint32_t hp_sleep_lp_regulator_slp_dbias:4; - /** hp_sleep_lp_regulator_dbias : R/W; bitpos: [31:27]; default: 24; - * need_des - */ - uint32_t hp_sleep_lp_regulator_dbias:5; + uint32_t reserved0 : 31; + uint32_t slp_reject_cause_clr: 1; }; uint32_t val; -} pmu_hp_sleep_lp_regulator0_reg_t; +} pmu_slp_wakeup_cntl4_reg_t; -/** Type of hp_sleep_lp_regulator1 register - * need_des - */ typedef union { struct { - uint32_t reserved_0:26; - /** hp_sleep_lp_regulator_drv_b : R/W; bitpos: [31:26]; default: 0; - * need_des - */ - uint32_t hp_sleep_lp_regulator_drv_b:6; + uint32_t modem_wait_target : 20; + uint32_t reserved0 : 4; + uint32_t lp_ana_wait_target: 8; }; uint32_t val; -} pmu_hp_sleep_lp_regulator1_reg_t; +} pmu_slp_wakeup_cntl5_reg_t; -/** Type of hp_sleep_lp_dig_power register - * need_des - */ typedef union { struct { - uint32_t reserved_0:26; - /** hp_sleep_lp_pad_slp_sel : R/W; bitpos: [26]; default: 0; - * need_des - */ - uint32_t hp_sleep_lp_pad_slp_sel:1; - /** hp_sleep_bod_source_sel : R/W; bitpos: [27]; default: 0; - * need_des - */ - uint32_t hp_sleep_bod_source_sel:1; - /** hp_sleep_vddbat_mode : R/W; bitpos: [29:28]; default: 0; - * need_des - */ - uint32_t hp_sleep_vddbat_mode:2; - /** hp_sleep_lp_mem_dslp : R/W; bitpos: [30]; default: 0; - * need_des - */ - uint32_t hp_sleep_lp_mem_dslp:1; - /** hp_sleep_pd_lp_peri_pd_en : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t hp_sleep_pd_lp_peri_pd_en:1; + uint32_t soc_wakeup_wait : 20; + uint32_t reserved0 : 10; + uint32_t soc_wakeup_wait_cfg: 2; }; uint32_t val; -} pmu_hp_sleep_lp_dig_power_reg_t; +} pmu_slp_wakeup_cntl6_reg_t; -/** Type of hp_sleep_lp_ck_power register - * need_des - */ typedef union { struct { - uint32_t reserved_0:27; - /** hp_sleep_xpd_lppll : R/W; bitpos: [27]; default: 0; - * need_des - */ - uint32_t hp_sleep_xpd_lppll:1; - /** hp_sleep_xpd_xtal32k : R/W; bitpos: [28]; default: 0; - * need_des - */ - uint32_t hp_sleep_xpd_xtal32k:1; - /** hp_sleep_xpd_rc32k : R/W; bitpos: [29]; default: 0; - * need_des - */ - uint32_t hp_sleep_xpd_rc32k:1; - /** hp_sleep_xpd_fosc_clk : R/W; bitpos: [30]; default: 1; - * need_des - */ - uint32_t hp_sleep_xpd_fosc_clk:1; - /** hp_sleep_pd_osc_clk : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t hp_sleep_pd_osc_clk:1; + uint32_t reserved0 : 16; + uint32_t ana_wait_target: 16; }; uint32_t val; -} pmu_hp_sleep_lp_ck_power_reg_t; +} pmu_slp_wakeup_cntl7_reg_t; -/** Type of lp_sleep_lp_regulator0 register - * need_des - */ typedef union { struct { - uint32_t reserved_0:21; - /** lp_sleep_lp_regulator_slp_xpd : R/W; bitpos: [21]; default: 1; - * need_des - */ - uint32_t lp_sleep_lp_regulator_slp_xpd:1; - /** lp_sleep_lp_regulator_xpd : R/W; bitpos: [22]; default: 1; - * need_des - */ - uint32_t lp_sleep_lp_regulator_xpd:1; - /** lp_sleep_lp_regulator_slp_dbias : R/W; bitpos: [26:23]; default: 12; - * need_des - */ - uint32_t lp_sleep_lp_regulator_slp_dbias:4; - /** lp_sleep_lp_regulator_dbias : R/W; bitpos: [31:27]; default: 24; - * need_des - */ - uint32_t lp_sleep_lp_regulator_dbias:5; + uint32_t reserved0 : 31; + uint32_t lp_lite_wakeup_ena: 1; }; uint32_t val; -} pmu_lp_sleep_lp_regulator0_reg_t; +} pmu_slp_wakeup_cntl8_reg_t; -/** Type of lp_sleep_lp_regulator1 register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:26; - /** lp_sleep_lp_regulator_drv_b : R/W; bitpos: [31:26]; default: 0; - * need_des - */ - uint32_t lp_sleep_lp_regulator_drv_b:6; - }; - uint32_t val; -} pmu_lp_sleep_lp_regulator1_reg_t; +typedef struct pmu_wakeup_hw_regmap_t { + pmu_slp_wakeup_cntl0_reg_t cntl0; + pmu_slp_wakeup_cntl1_reg_t cntl1; + uint32_t cntl2; + pmu_slp_wakeup_cntl3_reg_t cntl3; + pmu_slp_wakeup_cntl4_reg_t cntl4; + pmu_slp_wakeup_cntl5_reg_t cntl5; + pmu_slp_wakeup_cntl6_reg_t cntl6; + pmu_slp_wakeup_cntl7_reg_t cntl7; + pmu_slp_wakeup_cntl8_reg_t cntl8;//new + uint32_t status0; + uint32_t status1; + uint32_t status2;//new +} pmu_wakeup_hw_regmap_t; -/** Type of lp_sleep_xtal register - * need_des - */ typedef union { struct { - uint32_t reserved_0:31; - /** lp_sleep_xpd_xtal : R/W; bitpos: [31]; default: 1; - * need_des - */ - uint32_t lp_sleep_xpd_xtal:1; + uint32_t i2c_por_wait_target: 8; + uint32_t reserved0 : 24; }; uint32_t val; -} pmu_lp_sleep_xtal_reg_t; +} pmu_hp_clk_poweron_reg_t; -/** Type of lp_sleep_lp_dig_power register - * need_des - */ typedef union { struct { - uint32_t reserved_0:26; - /** lp_sleep_lp_pad_slp_sel : R/W; bitpos: [26]; default: 0; - * need_des - */ - uint32_t lp_sleep_lp_pad_slp_sel:1; - /** lp_sleep_bod_source_sel : R/W; bitpos: [27]; default: 0; - * need_des - */ - uint32_t lp_sleep_bod_source_sel:1; - /** lp_sleep_vddbat_mode : R/W; bitpos: [29:28]; default: 0; - * need_des - */ - uint32_t lp_sleep_vddbat_mode:2; - /** lp_sleep_lp_mem_dslp : R/W; bitpos: [30]; default: 0; - * need_des - */ - uint32_t lp_sleep_lp_mem_dslp:1; - /** lp_sleep_pd_lp_peri_pd_en : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t lp_sleep_pd_lp_peri_pd_en:1; + uint32_t modify_icg_cntl_wait: 8; + uint32_t switch_icg_cntl_wait: 8; + uint32_t reserved0 : 16; }; uint32_t val; -} pmu_lp_sleep_lp_dig_power_reg_t; - -/** Type of lp_sleep_lp_ck_power register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:27; - /** lp_sleep_xpd_lppll : R/W; bitpos: [27]; default: 0; - * need_des - */ - uint32_t lp_sleep_xpd_lppll:1; - /** lp_sleep_xpd_xtal32k : R/W; bitpos: [28]; default: 0; - * need_des - */ - uint32_t lp_sleep_xpd_xtal32k:1; - /** lp_sleep_xpd_rc32k : R/W; bitpos: [29]; default: 0; - * need_des - */ - uint32_t lp_sleep_xpd_rc32k:1; - /** lp_sleep_xpd_fosc_clk : R/W; bitpos: [30]; default: 1; - * need_des - */ - uint32_t lp_sleep_xpd_fosc_clk:1; - /** lp_sleep_pd_osc_clk : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t lp_sleep_pd_osc_clk:1; - }; - uint32_t val; -} pmu_lp_sleep_lp_ck_power_reg_t; - -/** Type of lp_sleep_bias register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:25; - /** lp_sleep_xpd_bias : R/W; bitpos: [25]; default: 0; - * need_des - */ - uint32_t lp_sleep_xpd_bias:1; - /** lp_sleep_dbg_atten : R/W; bitpos: [29:26]; default: 0; - * need_des - */ - uint32_t lp_sleep_dbg_atten:4; - /** lp_sleep_pd_cur : R/W; bitpos: [30]; default: 0; - * need_des - */ - uint32_t lp_sleep_pd_cur:1; - /** lp_sleep_bias_sleep : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t lp_sleep_bias_sleep:1; - }; - uint32_t val; -} pmu_lp_sleep_bias_reg_t; - -/** Type of imm_hp_ck_power register - * need_des - */ -typedef union { - struct { - /** tie_low_cali_xtal_icg : R/W; bitpos: [0]; default: 0; - * need_des - */ - uint32_t tie_low_cali_xtal_icg:1; - /** tie_low_global_pll_icg : WT; bitpos: [4:1]; default: 0; - * need_des - */ - uint32_t tie_low_global_pll_icg:4; - /** tie_low_global_xtal_icg : WT; bitpos: [5]; default: 0; - * need_des - */ - uint32_t tie_low_global_xtal_icg:1; - /** tie_low_i2c_retention : WT; bitpos: [6]; default: 0; - * need_des - */ - uint32_t tie_low_i2c_retention:1; - /** tie_low_xpd_pll_i2c : WT; bitpos: [10:7]; default: 0; - * need_des - */ - uint32_t tie_low_xpd_pll_i2c:4; - /** tie_low_xpd_pll : WT; bitpos: [14:11]; default: 0; - * need_des - */ - uint32_t tie_low_xpd_pll:4; - /** tie_low_xpd_xtal : WT; bitpos: [15]; default: 0; - * need_des - */ - uint32_t tie_low_xpd_xtal:1; - /** tie_high_cali_xtal_icg : R/W; bitpos: [16]; default: 0; - * need_des - */ - uint32_t tie_high_cali_xtal_icg:1; - /** tie_high_global_pll_icg : WT; bitpos: [20:17]; default: 0; - * need_des - */ - uint32_t tie_high_global_pll_icg:4; - /** tie_high_global_xtal_icg : WT; bitpos: [21]; default: 0; - * need_des - */ - uint32_t tie_high_global_xtal_icg:1; - /** tie_high_i2c_retention : WT; bitpos: [22]; default: 0; - * need_des - */ - uint32_t tie_high_i2c_retention:1; - /** tie_high_xpd_pll_i2c : WT; bitpos: [26:23]; default: 0; - * need_des - */ - uint32_t tie_high_xpd_pll_i2c:4; - /** tie_high_xpd_pll : WT; bitpos: [30:27]; default: 0; - * need_des - */ - uint32_t tie_high_xpd_pll:4; - /** tie_high_xpd_xtal : WT; bitpos: [31]; default: 0; - * need_des - */ - uint32_t tie_high_xpd_xtal:1; - }; - uint32_t val; -} pmu_imm_hp_ck_power_reg_t; - -/** Type of imm_sleep_sysclk register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:28; - /** update_dig_icg_switch : WT; bitpos: [28]; default: 0; - * need_des - */ - uint32_t update_dig_icg_switch:1; - /** tie_low_icg_slp_sel : WT; bitpos: [29]; default: 0; - * need_des - */ - uint32_t tie_low_icg_slp_sel:1; - /** tie_high_icg_slp_sel : WT; bitpos: [30]; default: 0; - * need_des - */ - uint32_t tie_high_icg_slp_sel:1; - /** update_dig_sys_clk_sel : WT; bitpos: [31]; default: 0; - * need_des - */ - uint32_t update_dig_sys_clk_sel:1; - }; - uint32_t val; -} pmu_imm_sleep_sysclk_reg_t; - -/** Type of imm_hp_func_icg register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:31; - /** update_dig_icg_func_en : WT; bitpos: [31]; default: 0; - * need_des - */ - uint32_t update_dig_icg_func_en:1; - }; - uint32_t val; -} pmu_imm_hp_func_icg_reg_t; - -/** Type of imm_hp_apb_icg register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:31; - /** update_dig_icg_apb_en : WT; bitpos: [31]; default: 0; - * need_des - */ - uint32_t update_dig_icg_apb_en:1; - }; - uint32_t val; -} pmu_imm_hp_apb_icg_reg_t; - -/** Type of imm_modem_icg register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:31; - /** update_dig_icg_modem_en : WT; bitpos: [31]; default: 0; - * need_des - */ - uint32_t update_dig_icg_modem_en:1; - }; - uint32_t val; -} pmu_imm_modem_icg_reg_t; - -/** Type of imm_lp_icg register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:30; - /** tie_low_lp_rootclk_sel : WT; bitpos: [30]; default: 0; - * need_des - */ - uint32_t tie_low_lp_rootclk_sel:1; - /** tie_high_lp_rootclk_sel : WT; bitpos: [31]; default: 0; - * need_des - */ - uint32_t tie_high_lp_rootclk_sel:1; - }; - uint32_t val; -} pmu_imm_lp_icg_reg_t; - -/** Type of imm_pad_hold_all register - * need_des - */ -typedef union { - struct { - /** pad_slp_sel : RO; bitpos: [0]; default: 0; - * need_des - */ - uint32_t pad_slp_sel:1; - /** lp_pad_hold_all : RO; bitpos: [1]; default: 0; - * need_des - */ - uint32_t lp_pad_hold_all:1; - /** hp_pad_hold_all : RO; bitpos: [2]; default: 0; - * need_des - */ - uint32_t hp_pad_hold_all:1; - uint32_t reserved_3:23; - /** tie_high_pad_slp_sel : WT; bitpos: [26]; default: 0; - * need_des - */ - uint32_t tie_high_pad_slp_sel:1; - /** tie_low_pad_slp_sel : WT; bitpos: [27]; default: 0; - * need_des - */ - uint32_t tie_low_pad_slp_sel:1; - /** tie_high_lp_pad_hold_all : WT; bitpos: [28]; default: 0; - * need_des - */ - uint32_t tie_high_lp_pad_hold_all:1; - /** tie_low_lp_pad_hold_all : WT; bitpos: [29]; default: 0; - * need_des - */ - uint32_t tie_low_lp_pad_hold_all:1; - /** tie_high_hp_pad_hold_all : WT; bitpos: [30]; default: 0; - * need_des - */ - uint32_t tie_high_hp_pad_hold_all:1; - /** tie_low_hp_pad_hold_all : WT; bitpos: [31]; default: 0; - * need_des - */ - uint32_t tie_low_hp_pad_hold_all:1; - }; - uint32_t val; -} pmu_imm_pad_hold_all_reg_t; - -/** Type of imm_i2c_iso register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:30; - /** tie_high_i2c_iso_en : WT; bitpos: [30]; default: 0; - * need_des - */ - uint32_t tie_high_i2c_iso_en:1; - /** tie_low_i2c_iso_en : WT; bitpos: [31]; default: 0; - * need_des - */ - uint32_t tie_low_i2c_iso_en:1; - }; - uint32_t val; -} pmu_imm_i2c_iso_reg_t; - -/** Type of power_wait_timer0 register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:5; - /** dg_hp_powerdown_timer : R/W; bitpos: [13:5]; default: 255; - * need_des - */ - uint32_t dg_hp_powerdown_timer:9; - /** dg_hp_powerup_timer : R/W; bitpos: [22:14]; default: 255; - * need_des - */ - uint32_t dg_hp_powerup_timer:9; - /** dg_hp_wait_timer : R/W; bitpos: [31:23]; default: 255; - * need_des - */ - uint32_t dg_hp_wait_timer:9; - }; - uint32_t val; -} pmu_power_wait_timer0_reg_t; - -/** Type of power_wait_timer1 register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:5; - /** dg_lp_powerdown_timer : R/W; bitpos: [13:5]; default: 255; - * need_des - */ - uint32_t dg_lp_powerdown_timer:9; - /** dg_lp_powerup_timer : R/W; bitpos: [22:14]; default: 255; - * need_des - */ - uint32_t dg_lp_powerup_timer:9; - /** dg_lp_wait_timer : R/W; bitpos: [31:23]; default: 255; - * need_des - */ - uint32_t dg_lp_wait_timer:9; - }; - uint32_t val; -} pmu_power_wait_timer1_reg_t; - -/** Type of power_pd_top_cntl register - * need_des - */ -typedef union { - struct { - /** force_top_reset : R/W; bitpos: [0]; default: 0; - * need_des - */ - uint32_t force_top_reset:1; - /** force_top_iso : R/W; bitpos: [1]; default: 0; - * need_des - */ - uint32_t force_top_iso:1; - /** force_top_pu : R/W; bitpos: [2]; default: 1; - * need_des - */ - uint32_t force_top_pu:1; - /** force_top_no_reset : R/W; bitpos: [3]; default: 1; - * need_des - */ - uint32_t force_top_no_reset:1; - /** force_top_no_iso : R/W; bitpos: [4]; default: 1; - * need_des - */ - uint32_t force_top_no_iso:1; - /** force_top_pd : R/W; bitpos: [5]; default: 0; - * need_des - */ - uint32_t force_top_pd:1; - uint32_t reserved_6:26; - }; - uint32_t val; -} pmu_power_pd_top_cntl_reg_t; - -/** Type of power_pd_cnnt_cntl register - * need_des - */ -typedef union { - struct { - /** force_cnnt_reset : R/W; bitpos: [0]; default: 0; - * need_des - */ - uint32_t force_cnnt_reset:1; - /** force_cnnt_iso : R/W; bitpos: [1]; default: 0; - * need_des - */ - uint32_t force_cnnt_iso:1; - /** force_cnnt_pu : R/W; bitpos: [2]; default: 1; - * need_des - */ - uint32_t force_cnnt_pu:1; - /** force_cnnt_no_reset : R/W; bitpos: [3]; default: 1; - * need_des - */ - uint32_t force_cnnt_no_reset:1; - /** force_cnnt_no_iso : R/W; bitpos: [4]; default: 1; - * need_des - */ - uint32_t force_cnnt_no_iso:1; - /** force_cnnt_pd : R/W; bitpos: [5]; default: 0; - * need_des - */ - uint32_t force_cnnt_pd:1; - uint32_t reserved_6:26; - }; - uint32_t val; -} pmu_power_pd_cnnt_cntl_reg_t; - -/** Type of power_pd_hpmem_cntl register - * need_des - */ -typedef union { - struct { - /** force_hp_mem_reset : R/W; bitpos: [0]; default: 0; - * need_des - */ - uint32_t force_hp_mem_reset:1; - /** force_hp_mem_iso : R/W; bitpos: [1]; default: 0; - * need_des - */ - uint32_t force_hp_mem_iso:1; - /** force_hp_mem_pu : R/W; bitpos: [2]; default: 1; - * need_des - */ - uint32_t force_hp_mem_pu:1; - /** force_hp_mem_no_reset : R/W; bitpos: [3]; default: 1; - * need_des - */ - uint32_t force_hp_mem_no_reset:1; - /** force_hp_mem_no_iso : R/W; bitpos: [4]; default: 1; - * need_des - */ - uint32_t force_hp_mem_no_iso:1; - /** force_hp_mem_pd : R/W; bitpos: [5]; default: 0; - * need_des - */ - uint32_t force_hp_mem_pd:1; - uint32_t reserved_6:26; - }; - uint32_t val; -} pmu_power_pd_hpmem_cntl_reg_t; - -/** Type of power_pd_top_mask register - * need_des - */ -typedef union { - struct { - /** xpd_top_mask : R/W; bitpos: [4:0]; default: 0; - * need_des - */ - uint32_t xpd_top_mask:5; - uint32_t reserved_5:22; - /** pd_top_mask : R/W; bitpos: [31:27]; default: 0; - * need_des - */ - uint32_t pd_top_mask:5; - }; - uint32_t val; -} pmu_power_pd_top_mask_reg_t; - -/** Type of power_pd_cnnt_mask register - * need_des - */ -typedef union { - struct { - /** xpd_cnnt_mask : R/W; bitpos: [4:0]; default: 0; - * need_des - */ - uint32_t xpd_cnnt_mask:5; - uint32_t reserved_5:22; - /** pd_cnnt_mask : R/W; bitpos: [31:27]; default: 0; - * need_des - */ - uint32_t pd_cnnt_mask:5; - }; - uint32_t val; -} pmu_power_pd_cnnt_mask_reg_t; - -/** Type of power_pd_hpmem_mask register - * need_des - */ -typedef union { - struct { - /** xpd_hp_mem_mask : R/W; bitpos: [5:0]; default: 0; - * need_des - */ - uint32_t xpd_hp_mem_mask:6; - uint32_t reserved_6:20; - /** pd_hp_mem_mask : R/W; bitpos: [31:26]; default: 0; - * need_des - */ - uint32_t pd_hp_mem_mask:6; - }; - uint32_t val; -} pmu_power_pd_hpmem_mask_reg_t; - -/** Type of power_dcdc_switch register - * need_des - */ -typedef union { - struct { - /** force_dcdc_switch_pu : R/W; bitpos: [0]; default: 1; - * need_des - */ - uint32_t force_dcdc_switch_pu:1; - /** force_dcdc_switch_pd : R/W; bitpos: [1]; default: 0; - * need_des - */ - uint32_t force_dcdc_switch_pd:1; - uint32_t reserved_2:30; - }; - uint32_t val; -} pmu_power_dcdc_switch_reg_t; - -/** Type of power_pd_lpperi_cntl register - * need_des - */ -typedef union { - struct { - /** force_lp_peri_reset : R/W; bitpos: [0]; default: 0; - * need_des - */ - uint32_t force_lp_peri_reset:1; - /** force_lp_peri_iso : R/W; bitpos: [1]; default: 0; - * need_des - */ - uint32_t force_lp_peri_iso:1; - /** force_lp_peri_pu : R/W; bitpos: [2]; default: 1; - * need_des - */ - uint32_t force_lp_peri_pu:1; - /** force_lp_peri_no_reset : R/W; bitpos: [3]; default: 1; - * need_des - */ - uint32_t force_lp_peri_no_reset:1; - /** force_lp_peri_no_iso : R/W; bitpos: [4]; default: 1; - * need_des - */ - uint32_t force_lp_peri_no_iso:1; - /** force_lp_peri_pd : R/W; bitpos: [5]; default: 0; - * need_des - */ - uint32_t force_lp_peri_pd:1; - uint32_t reserved_6:26; - }; - uint32_t val; -} pmu_power_pd_lpperi_cntl_reg_t; - -/** Type of power_pd_lpperi_mask register - * need_des - */ -typedef union { - struct { - /** xpd_lp_peri_mask : R/W; bitpos: [4:0]; default: 0; - * need_des - */ - uint32_t xpd_lp_peri_mask:5; - uint32_t reserved_5:22; - /** pd_lp_peri_mask : R/W; bitpos: [31:27]; default: 0; - * need_des - */ - uint32_t pd_lp_peri_mask:5; - }; - uint32_t val; -} pmu_power_pd_lpperi_mask_reg_t; - -/** Type of power_hp_pad register - * need_des - */ -typedef union { - struct { - /** force_hp_pad_no_iso_all : R/W; bitpos: [0]; default: 0; - * need_des - */ - uint32_t force_hp_pad_no_iso_all:1; - /** force_hp_pad_iso_all : R/W; bitpos: [1]; default: 0; - * need_des - */ - uint32_t force_hp_pad_iso_all:1; - uint32_t reserved_2:30; - }; - uint32_t val; -} pmu_power_hp_pad_reg_t; - -/** Type of power_ck_wait_cntl register - * need_des - */ -typedef union { - struct { - /** pmu_wait_xtl_stable : R/W; bitpos: [15:0]; default: 256; - * need_des - */ - uint32_t pmu_wait_xtl_stable:16; - /** pmu_wait_pll_stable : R/W; bitpos: [31:16]; default: 256; - * need_des - */ - uint32_t pmu_wait_pll_stable:16; - }; - uint32_t val; -} pmu_power_ck_wait_cntl_reg_t; - -/** Type of slp_wakeup_cntl0 register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:31; - /** sleep_req : WT; bitpos: [31]; default: 0; - * need_des - */ - uint32_t sleep_req:1; - }; - uint32_t val; -} pmu_slp_wakeup_cntl0_reg_t; - -/** Type of slp_wakeup_cntl1 register - * need_des - */ -typedef union { - struct { - /** sleep_reject_ena : R/W; bitpos: [30:0]; default: 0; - * need_des - */ - uint32_t sleep_reject_ena:31; - /** slp_reject_en : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t slp_reject_en:1; - }; - uint32_t val; -} pmu_slp_wakeup_cntl1_reg_t; - -/** Type of slp_wakeup_cntl2 register - * need_des - */ -typedef union { - struct { - /** wakeup_ena : R/W; bitpos: [30:0]; default: 0; - * need_des - */ - uint32_t wakeup_ena:31; - uint32_t reserved_31:1; - }; - uint32_t val; -} pmu_slp_wakeup_cntl2_reg_t; - -/** Type of slp_wakeup_cntl3 register - * need_des - */ -typedef union { - struct { - /** lp_min_slp_val : R/W; bitpos: [7:0]; default: 0; - * need_des - */ - uint32_t lp_min_slp_val:8; - /** hp_min_slp_val : R/W; bitpos: [15:8]; default: 0; - * need_des - */ - uint32_t hp_min_slp_val:8; - /** sleep_prt_sel : R/W; bitpos: [17:16]; default: 0; - * need_des - */ - uint32_t sleep_prt_sel:2; - uint32_t reserved_18:14; - }; - uint32_t val; -} pmu_slp_wakeup_cntl3_reg_t; - -/** Type of slp_wakeup_cntl4 register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:31; - /** slp_reject_cause_clr : WT; bitpos: [31]; default: 0; - * need_des - */ - uint32_t slp_reject_cause_clr:1; - }; - uint32_t val; -} pmu_slp_wakeup_cntl4_reg_t; - -/** Type of slp_wakeup_cntl5 register - * need_des - */ -typedef union { - struct { - /** modem_wait_target : R/W; bitpos: [19:0]; default: 128; - * need_des - */ - uint32_t modem_wait_target:20; - uint32_t reserved_20:4; - /** lp_ana_wait_target : R/W; bitpos: [31:24]; default: 1; - * need_des - */ - uint32_t lp_ana_wait_target:8; - }; - uint32_t val; -} pmu_slp_wakeup_cntl5_reg_t; - -/** Type of slp_wakeup_cntl6 register - * need_des - */ -typedef union { - struct { - /** soc_wakeup_wait : R/W; bitpos: [19:0]; default: 128; - * need_des - */ - uint32_t soc_wakeup_wait:20; - uint32_t reserved_20:10; - /** soc_wakeup_wait_cfg : R/W; bitpos: [31:30]; default: 0; - * need_des - */ - uint32_t soc_wakeup_wait_cfg:2; - }; - uint32_t val; -} pmu_slp_wakeup_cntl6_reg_t; - -/** Type of slp_wakeup_cntl7 register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:16; - /** ana_wait_target : R/W; bitpos: [31:16]; default: 1; - * need_des - */ - uint32_t ana_wait_target:16; - }; - uint32_t val; -} pmu_slp_wakeup_cntl7_reg_t; - -/** Type of slp_wakeup_cntl8 register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:31; - /** lp_lite_wakeup_ena : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t lp_lite_wakeup_ena:1; - }; - uint32_t val; -} pmu_slp_wakeup_cntl8_reg_t; - -/** Type of slp_wakeup_status0 register - * need_des - */ -typedef union { - struct { - /** wakeup_cause : RO; bitpos: [30:0]; default: 0; - * need_des - */ - uint32_t wakeup_cause:31; - uint32_t reserved_31:1; - }; - uint32_t val; -} pmu_slp_wakeup_status0_reg_t; - -/** Type of slp_wakeup_status1 register - * need_des - */ -typedef union { - struct { - /** reject_cause : RO; bitpos: [30:0]; default: 0; - * need_des - */ - uint32_t reject_cause:31; - uint32_t reserved_31:1; - }; - uint32_t val; -} pmu_slp_wakeup_status1_reg_t; - -/** Type of slp_wakeup_status2 register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:31; - /** lp_lite_wakeup_cause : RO; bitpos: [31]; default: 0; - * need_des - */ - uint32_t lp_lite_wakeup_cause:1; - }; - uint32_t val; -} pmu_slp_wakeup_status2_reg_t; - -/** Type of hp_ck_poweron register - * need_des - */ -typedef union { - struct { - /** i2c_por_wait_target : R/W; bitpos: [7:0]; default: 50; - * need_des - */ - uint32_t i2c_por_wait_target:8; - uint32_t reserved_8:24; - }; - uint32_t val; -} pmu_hp_ck_poweron_reg_t; - -/** Type of hp_ck_cntl register - * need_des - */ -typedef union { - struct { - /** modify_icg_cntl_wait : R/W; bitpos: [7:0]; default: 10; - * need_des - */ - uint32_t modify_icg_cntl_wait:8; - /** switch_icg_cntl_wait : R/W; bitpos: [15:8]; default: 10; - * need_des - */ - uint32_t switch_icg_cntl_wait:8; - uint32_t reserved_16:16; - }; - uint32_t val; -} pmu_hp_ck_cntl_reg_t; - -/** Type of por_status register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:31; - /** por_done : RO; bitpos: [31]; default: 1; - * need_des - */ - uint32_t por_done:1; - }; - uint32_t val; -} pmu_por_status_reg_t; - -/** Type of rf_pwc register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:24; - /** mspi_phy_xpd : R/W; bitpos: [24]; default: 0; - * need_des - */ - uint32_t mspi_phy_xpd:1; - /** sdio_pll_xpd : R/W; bitpos: [25]; default: 0; - * need_des - */ - uint32_t sdio_pll_xpd:1; - /** perif_i2c_rstb : R/W; bitpos: [26]; default: 0; - * need_des - */ - uint32_t perif_i2c_rstb:1; - /** xpd_perif_i2c : R/W; bitpos: [27]; default: 1; - * need_des - */ - uint32_t xpd_perif_i2c:1; - /** xpd_txrf_i2c : R/W; bitpos: [28]; default: 0; - * need_des - */ - uint32_t xpd_txrf_i2c:1; - /** xpd_rfrx_pbus : R/W; bitpos: [29]; default: 0; - * need_des - */ - uint32_t xpd_rfrx_pbus:1; - /** xpd_ckgen_i2c : R/W; bitpos: [30]; default: 0; - * need_des - */ - uint32_t xpd_ckgen_i2c:1; - uint32_t reserved_31:1; - }; - uint32_t val; -} pmu_rf_pwc_reg_t; - -/** Type of backup_cfg register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:31; - /** backup_sys_clk_no_div : R/W; bitpos: [31]; default: 1; - * need_des - */ - uint32_t backup_sys_clk_no_div:1; - }; - uint32_t val; -} pmu_backup_cfg_reg_t; - -/** Type of int_raw register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:14; - /** pmu_0p1a_cnt_target0_reach_0_hp_int_raw : R/WTC/SS; bitpos: [14]; default: 0; - * reg_pmu_0p1a_0_counter after xpd reach target0 - */ - uint32_t pmu_0p1a_cnt_target0_reach_0_hp_int_raw:1; - /** pmu_0p1a_cnt_target1_reach_0_hp_int_raw : R/WTC/SS; bitpos: [15]; default: 0; - * reg_pmu_0p1a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p1a_cnt_target1_reach_0_hp_int_raw:1; - /** pmu_0p1a_cnt_target0_reach_1_hp_int_raw : R/WTC/SS; bitpos: [16]; default: 0; - * reg_pmu_0p1a_0 counter after xpd reach target0 - */ - uint32_t pmu_0p1a_cnt_target0_reach_1_hp_int_raw:1; - /** pmu_0p1a_cnt_target1_reach_1_hp_int_raw : R/WTC/SS; bitpos: [17]; default: 0; - * reg_pmu_0p1a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p1a_cnt_target1_reach_1_hp_int_raw:1; - /** pmu_0p2a_cnt_target0_reach_0_hp_int_raw : R/WTC/SS; bitpos: [18]; default: 0; - * reg_pmu_0p2a_0 counter after xpd reach target0 - */ - uint32_t pmu_0p2a_cnt_target0_reach_0_hp_int_raw:1; - /** pmu_0p2a_cnt_target1_reach_0_hp_int_raw : R/WTC/SS; bitpos: [19]; default: 0; - * reg_pmu_0p2a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p2a_cnt_target1_reach_0_hp_int_raw:1; - /** pmu_0p2a_cnt_target0_reach_1_hp_int_raw : R/WTC/SS; bitpos: [20]; default: 0; - * reg_pmu_0p2a_0 counter after xpd reach target0 - */ - uint32_t pmu_0p2a_cnt_target0_reach_1_hp_int_raw:1; - /** pmu_0p2a_cnt_target1_reach_1_hp_int_raw : R/WTC/SS; bitpos: [21]; default: 0; - * reg_pmu_0p2a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p2a_cnt_target1_reach_1_hp_int_raw:1; - /** pmu_0p3a_cnt_target0_reach_0_hp_int_raw : R/WTC/SS; bitpos: [22]; default: 0; - * reg_pmu_0p3a_0 counter after xpd reach target0 - */ - uint32_t pmu_0p3a_cnt_target0_reach_0_hp_int_raw:1; - /** pmu_0p3a_cnt_target1_reach_0_hp_int_raw : R/WTC/SS; bitpos: [23]; default: 0; - * reg_pmu_0p3a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p3a_cnt_target1_reach_0_hp_int_raw:1; - /** pmu_0p3a_cnt_target0_reach_1_hp_int_raw : R/WTC/SS; bitpos: [24]; default: 0; - * reg_pmu_0p3a_0_counter after xpd reach target0 - */ - uint32_t pmu_0p3a_cnt_target0_reach_1_hp_int_raw:1; - /** pmu_0p3a_cnt_target1_reach_1_hp_int_raw : R/WTC/SS; bitpos: [25]; default: 0; - * reg_pmu_0p3a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p3a_cnt_target1_reach_1_hp_int_raw:1; - uint32_t reserved_26:1; - /** lp_cpu_exc_int_raw : R/WTC/SS; bitpos: [27]; default: 0; - * need_des - */ - uint32_t lp_cpu_exc_int_raw:1; - /** sdio_idle_int_raw : R/WTC/SS; bitpos: [28]; default: 0; - * need_des - */ - uint32_t sdio_idle_int_raw:1; - /** sw_int_raw : R/WTC/SS; bitpos: [29]; default: 0; - * need_des - */ - uint32_t sw_int_raw:1; - /** soc_sleep_reject_int_raw : R/WTC/SS; bitpos: [30]; default: 0; - * need_des - */ - uint32_t soc_sleep_reject_int_raw:1; - /** soc_wakeup_int_raw : R/WTC/SS; bitpos: [31]; default: 0; - * need_des - */ - uint32_t soc_wakeup_int_raw:1; - }; - uint32_t val; -} pmu_int_raw_reg_t; - -/** Type of hp_int_st register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:14; - /** pmu_0p1a_cnt_target0_reach_0_hp_int_st : RO; bitpos: [14]; default: 0; - * reg_pmu_0p1a_0_counter after xpd reach target0 - */ - uint32_t pmu_0p1a_cnt_target0_reach_0_hp_int_st:1; - /** pmu_0p1a_cnt_target1_reach_0_hp_int_st : RO; bitpos: [15]; default: 0; - * reg_pmu_0p1a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p1a_cnt_target1_reach_0_hp_int_st:1; - /** pmu_0p1a_cnt_target0_reach_1_hp_int_st : RO; bitpos: [16]; default: 0; - * reg_pmu_0p1a_0 counter after xpd reach target0 - */ - uint32_t pmu_0p1a_cnt_target0_reach_1_hp_int_st:1; - /** pmu_0p1a_cnt_target1_reach_1_hp_int_st : RO; bitpos: [17]; default: 0; - * reg_pmu_0p1a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p1a_cnt_target1_reach_1_hp_int_st:1; - /** pmu_0p2a_cnt_target0_reach_0_hp_int_st : RO; bitpos: [18]; default: 0; - * reg_pmu_0p2a_0 counter after xpd reach target0 - */ - uint32_t pmu_0p2a_cnt_target0_reach_0_hp_int_st:1; - /** pmu_0p2a_cnt_target1_reach_0_hp_int_st : RO; bitpos: [19]; default: 0; - * reg_pmu_0p2a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p2a_cnt_target1_reach_0_hp_int_st:1; - /** pmu_0p2a_cnt_target0_reach_1_hp_int_st : RO; bitpos: [20]; default: 0; - * reg_pmu_0p2a_0 counter after xpd reach target0 - */ - uint32_t pmu_0p2a_cnt_target0_reach_1_hp_int_st:1; - /** pmu_0p2a_cnt_target1_reach_1_hp_int_st : RO; bitpos: [21]; default: 0; - * reg_pmu_0p2a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p2a_cnt_target1_reach_1_hp_int_st:1; - /** pmu_0p3a_cnt_target0_reach_0_hp_int_st : RO; bitpos: [22]; default: 0; - * reg_pmu_0p3a_0 counter after xpd reach target0 - */ - uint32_t pmu_0p3a_cnt_target0_reach_0_hp_int_st:1; - /** pmu_0p3a_cnt_target1_reach_0_hp_int_st : RO; bitpos: [23]; default: 0; - * reg_pmu_0p3a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p3a_cnt_target1_reach_0_hp_int_st:1; - /** pmu_0p3a_cnt_target0_reach_1_hp_int_st : RO; bitpos: [24]; default: 0; - * reg_pmu_0p3a_0_counter after xpd reach target0 - */ - uint32_t pmu_0p3a_cnt_target0_reach_1_hp_int_st:1; - /** pmu_0p3a_cnt_target1_reach_1_hp_int_st : RO; bitpos: [25]; default: 0; - * reg_pmu_0p3a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p3a_cnt_target1_reach_1_hp_int_st:1; - uint32_t reserved_26:1; - /** lp_cpu_exc_int_st : RO; bitpos: [27]; default: 0; - * need_des - */ - uint32_t lp_cpu_exc_int_st:1; - /** sdio_idle_int_st : RO; bitpos: [28]; default: 0; - * need_des - */ - uint32_t sdio_idle_int_st:1; - /** sw_int_st : RO; bitpos: [29]; default: 0; - * need_des - */ - uint32_t sw_int_st:1; - /** soc_sleep_reject_int_st : RO; bitpos: [30]; default: 0; - * need_des - */ - uint32_t soc_sleep_reject_int_st:1; - /** soc_wakeup_int_st : RO; bitpos: [31]; default: 0; - * need_des - */ - uint32_t soc_wakeup_int_st:1; - }; - uint32_t val; -} pmu_hp_int_st_reg_t; - -/** Type of hp_int_ena register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:14; - /** pmu_0p1a_cnt_target0_reach_0_hp_int_ena : R/W; bitpos: [14]; default: 0; - * reg_pmu_0p1a_0_counter after xpd reach target0 - */ - uint32_t pmu_0p1a_cnt_target0_reach_0_hp_int_ena:1; - /** pmu_0p1a_cnt_target1_reach_0_hp_int_ena : R/W; bitpos: [15]; default: 0; - * reg_pmu_0p1a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p1a_cnt_target1_reach_0_hp_int_ena:1; - /** pmu_0p1a_cnt_target0_reach_1_hp_int_ena : R/W; bitpos: [16]; default: 0; - * reg_pmu_0p1a_0 counter after xpd reach target0 - */ - uint32_t pmu_0p1a_cnt_target0_reach_1_hp_int_ena:1; - /** pmu_0p1a_cnt_target1_reach_1_hp_int_ena : R/W; bitpos: [17]; default: 0; - * reg_pmu_0p1a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p1a_cnt_target1_reach_1_hp_int_ena:1; - /** pmu_0p2a_cnt_target0_reach_0_hp_int_ena : R/W; bitpos: [18]; default: 0; - * reg_pmu_0p2a_0 counter after xpd reach target0 - */ - uint32_t pmu_0p2a_cnt_target0_reach_0_hp_int_ena:1; - /** pmu_0p2a_cnt_target1_reach_0_hp_int_ena : R/W; bitpos: [19]; default: 0; - * reg_pmu_0p2a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p2a_cnt_target1_reach_0_hp_int_ena:1; - /** pmu_0p2a_cnt_target0_reach_1_hp_int_ena : R/W; bitpos: [20]; default: 0; - * reg_pmu_0p2a_0 counter after xpd reach target0 - */ - uint32_t pmu_0p2a_cnt_target0_reach_1_hp_int_ena:1; - /** pmu_0p2a_cnt_target1_reach_1_hp_int_ena : R/W; bitpos: [21]; default: 0; - * reg_pmu_0p2a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p2a_cnt_target1_reach_1_hp_int_ena:1; - /** pmu_0p3a_cnt_target0_reach_0_hp_int_ena : R/W; bitpos: [22]; default: 0; - * reg_pmu_0p3a_0 counter after xpd reach target0 - */ - uint32_t pmu_0p3a_cnt_target0_reach_0_hp_int_ena:1; - /** pmu_0p3a_cnt_target1_reach_0_hp_int_ena : R/W; bitpos: [23]; default: 0; - * reg_pmu_0p3a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p3a_cnt_target1_reach_0_hp_int_ena:1; - /** pmu_0p3a_cnt_target0_reach_1_hp_int_ena : R/W; bitpos: [24]; default: 0; - * reg_pmu_0p3a_0_counter after xpd reach target0 - */ - uint32_t pmu_0p3a_cnt_target0_reach_1_hp_int_ena:1; - /** pmu_0p3a_cnt_target1_reach_1_hp_int_ena : R/W; bitpos: [25]; default: 0; - * reg_pmu_0p3a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p3a_cnt_target1_reach_1_hp_int_ena:1; - uint32_t reserved_26:1; - /** lp_cpu_exc_int_ena : R/W; bitpos: [27]; default: 0; - * need_des - */ - uint32_t lp_cpu_exc_int_ena:1; - /** sdio_idle_int_ena : R/W; bitpos: [28]; default: 0; - * need_des - */ - uint32_t sdio_idle_int_ena:1; - /** sw_int_ena : R/W; bitpos: [29]; default: 0; - * need_des - */ - uint32_t sw_int_ena:1; - /** soc_sleep_reject_int_ena : R/W; bitpos: [30]; default: 0; - * need_des - */ - uint32_t soc_sleep_reject_int_ena:1; - /** soc_wakeup_int_ena : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t soc_wakeup_int_ena:1; - }; - uint32_t val; -} pmu_hp_int_ena_reg_t; - -/** Type of hp_int_clr register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:14; - /** pmu_0p1a_cnt_target0_reach_0_hp_int_clr : WT; bitpos: [14]; default: 0; - * reg_pmu_0p1a_0_counter after xpd reach target0 - */ - uint32_t pmu_0p1a_cnt_target0_reach_0_hp_int_clr:1; - /** pmu_0p1a_cnt_target1_reach_0_hp_int_clr : WT; bitpos: [15]; default: 0; - * reg_pmu_0p1a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p1a_cnt_target1_reach_0_hp_int_clr:1; - /** pmu_0p1a_cnt_target0_reach_1_hp_int_clr : WT; bitpos: [16]; default: 0; - * reg_pmu_0p1a_0 counter after xpd reach target0 - */ - uint32_t pmu_0p1a_cnt_target0_reach_1_hp_int_clr:1; - /** pmu_0p1a_cnt_target1_reach_1_hp_int_clr : WT; bitpos: [17]; default: 0; - * reg_pmu_0p1a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p1a_cnt_target1_reach_1_hp_int_clr:1; - /** pmu_0p2a_cnt_target0_reach_0_hp_int_clr : WT; bitpos: [18]; default: 0; - * reg_pmu_0p2a_0 counter after xpd reach target0 - */ - uint32_t pmu_0p2a_cnt_target0_reach_0_hp_int_clr:1; - /** pmu_0p2a_cnt_target1_reach_0_hp_int_clr : WT; bitpos: [19]; default: 0; - * reg_pmu_0p2a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p2a_cnt_target1_reach_0_hp_int_clr:1; - /** pmu_0p2a_cnt_target0_reach_1_hp_int_clr : WT; bitpos: [20]; default: 0; - * reg_pmu_0p2a_0 counter after xpd reach target0 - */ - uint32_t pmu_0p2a_cnt_target0_reach_1_hp_int_clr:1; - /** pmu_0p2a_cnt_target1_reach_1_hp_int_clr : WT; bitpos: [21]; default: 0; - * reg_pmu_0p2a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p2a_cnt_target1_reach_1_hp_int_clr:1; - /** pmu_0p3a_cnt_target0_reach_0_hp_int_clr : WT; bitpos: [22]; default: 0; - * reg_pmu_0p3a_0 counter after xpd reach target0 - */ - uint32_t pmu_0p3a_cnt_target0_reach_0_hp_int_clr:1; - /** pmu_0p3a_cnt_target1_reach_0_hp_int_clr : WT; bitpos: [23]; default: 0; - * reg_pmu_0p3a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p3a_cnt_target1_reach_0_hp_int_clr:1; - /** pmu_0p3a_cnt_target0_reach_1_hp_int_clr : WT; bitpos: [24]; default: 0; - * reg_pmu_0p3a_0_counter after xpd reach target0 - */ - uint32_t pmu_0p3a_cnt_target0_reach_1_hp_int_clr:1; - /** pmu_0p3a_cnt_target1_reach_1_hp_int_clr : WT; bitpos: [25]; default: 0; - * reg_pmu_0p3a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p3a_cnt_target1_reach_1_hp_int_clr:1; - uint32_t reserved_26:1; - /** lp_cpu_exc_int_clr : WT; bitpos: [27]; default: 0; - * need_des - */ - uint32_t lp_cpu_exc_int_clr:1; - /** sdio_idle_int_clr : WT; bitpos: [28]; default: 0; - * need_des - */ - uint32_t sdio_idle_int_clr:1; - /** sw_int_clr : WT; bitpos: [29]; default: 0; - * need_des - */ - uint32_t sw_int_clr:1; - /** soc_sleep_reject_int_clr : WT; bitpos: [30]; default: 0; - * need_des - */ - uint32_t soc_sleep_reject_int_clr:1; - /** soc_wakeup_int_clr : WT; bitpos: [31]; default: 0; - * need_des - */ - uint32_t soc_wakeup_int_clr:1; - }; - uint32_t val; -} pmu_hp_int_clr_reg_t; - -/** Type of lp_int_raw register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:13; - /** lp_cpu_sleep_reject_int_raw : R/WTC/SS; bitpos: [13]; default: 0; - * need_des - */ - uint32_t lp_cpu_sleep_reject_int_raw:1; - /** pmu_0p1a_cnt_target0_reach_0_lp_int_raw : R/WTC/SS; bitpos: [14]; default: 0; - * reg_pmu_0p1a_0_counter after xpd reach target0 - */ - uint32_t pmu_0p1a_cnt_target0_reach_0_lp_int_raw:1; - /** pmu_0p1a_cnt_target1_reach_0_lp_int_raw : R/WTC/SS; bitpos: [15]; default: 0; - * reg_pmu_0p1a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p1a_cnt_target1_reach_0_lp_int_raw:1; - /** pmu_0p1a_cnt_target0_reach_1_lp_int_raw : R/WTC/SS; bitpos: [16]; default: 0; - * reg_pmu_0p1a_0 counter after xpd reach target0 - */ - uint32_t pmu_0p1a_cnt_target0_reach_1_lp_int_raw:1; - /** pmu_0p1a_cnt_target1_reach_1_lp_int_raw : R/WTC/SS; bitpos: [17]; default: 0; - * reg_pmu_0p1a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p1a_cnt_target1_reach_1_lp_int_raw:1; - /** pmu_0p2a_cnt_target0_reach_0_lp_int_raw : R/WTC/SS; bitpos: [18]; default: 0; - * reg_pmu_0p2a_0 counter after xpd reach target0 - */ - uint32_t pmu_0p2a_cnt_target0_reach_0_lp_int_raw:1; - /** pmu_0p2a_cnt_target1_reach_0_lp_int_raw : R/WTC/SS; bitpos: [19]; default: 0; - * reg_pmu_0p2a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p2a_cnt_target1_reach_0_lp_int_raw:1; - /** pmu_0p2a_cnt_target0_reach_1_lp_int_raw : R/WTC/SS; bitpos: [20]; default: 0; - * reg_pmu_0p2a_0 counter after xpd reach target0 - */ - uint32_t pmu_0p2a_cnt_target0_reach_1_lp_int_raw:1; - /** pmu_0p2a_cnt_target1_reach_1_lp_int_raw : R/WTC/SS; bitpos: [21]; default: 0; - * reg_pmu_0p2a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p2a_cnt_target1_reach_1_lp_int_raw:1; - /** pmu_0p3a_cnt_target0_reach_0_lp_int_raw : R/WTC/SS; bitpos: [22]; default: 0; - * reg_pmu_0p3a_0 counter after xpd reach target0 - */ - uint32_t pmu_0p3a_cnt_target0_reach_0_lp_int_raw:1; - /** pmu_0p3a_cnt_target1_reach_0_lp_int_raw : R/WTC/SS; bitpos: [23]; default: 0; - * reg_pmu_0p3a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p3a_cnt_target1_reach_0_lp_int_raw:1; - /** pmu_0p3a_cnt_target0_reach_1_lp_int_raw : R/WTC/SS; bitpos: [24]; default: 0; - * reg_pmu_0p3a_0_counter after xpd reach target0 - */ - uint32_t pmu_0p3a_cnt_target0_reach_1_lp_int_raw:1; - /** pmu_0p3a_cnt_target1_reach_1_lp_int_raw : R/WTC/SS; bitpos: [25]; default: 0; - * reg_pmu_0p3a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p3a_cnt_target1_reach_1_lp_int_raw:1; - /** lp_cpu_wakeup_int_raw : R/WTC/SS; bitpos: [26]; default: 0; - * need_des - */ - uint32_t lp_cpu_wakeup_int_raw:1; - /** sleep_switch_active_end_int_raw : R/WTC/SS; bitpos: [27]; default: 0; - * need_des - */ - uint32_t sleep_switch_active_end_int_raw:1; - /** active_switch_sleep_end_int_raw : R/WTC/SS; bitpos: [28]; default: 0; - * need_des - */ - uint32_t active_switch_sleep_end_int_raw:1; - /** sleep_switch_active_start_int_raw : R/WTC/SS; bitpos: [29]; default: 0; - * need_des - */ - uint32_t sleep_switch_active_start_int_raw:1; - /** active_switch_sleep_start_int_raw : R/WTC/SS; bitpos: [30]; default: 0; - * need_des - */ - uint32_t active_switch_sleep_start_int_raw:1; - /** hp_sw_trigger_int_raw : R/WTC/SS; bitpos: [31]; default: 0; - * need_des - */ - uint32_t hp_sw_trigger_int_raw:1; - }; - uint32_t val; -} pmu_lp_int_raw_reg_t; - -/** Type of lp_int_st register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:13; - /** lp_cpu_sleep_reject_int_st : RO; bitpos: [13]; default: 0; - * need_des - */ - uint32_t lp_cpu_sleep_reject_int_st:1; - /** pmu_0p1a_cnt_target0_reach_0_lp_int_st : RO; bitpos: [14]; default: 0; - * reg_pmu_0p1a_0_counter after xpd reach target0 - */ - uint32_t pmu_0p1a_cnt_target0_reach_0_lp_int_st:1; - /** pmu_0p1a_cnt_target1_reach_0_lp_int_st : RO; bitpos: [15]; default: 0; - * reg_pmu_0p1a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p1a_cnt_target1_reach_0_lp_int_st:1; - /** pmu_0p1a_cnt_target0_reach_1_lp_int_st : RO; bitpos: [16]; default: 0; - * reg_pmu_0p1a_0 counter after xpd reach target0 - */ - uint32_t pmu_0p1a_cnt_target0_reach_1_lp_int_st:1; - /** pmu_0p1a_cnt_target1_reach_1_lp_int_st : RO; bitpos: [17]; default: 0; - * reg_pmu_0p1a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p1a_cnt_target1_reach_1_lp_int_st:1; - /** pmu_0p2a_cnt_target0_reach_0_lp_int_st : RO; bitpos: [18]; default: 0; - * reg_pmu_0p2a_0 counter after xpd reach target0 - */ - uint32_t pmu_0p2a_cnt_target0_reach_0_lp_int_st:1; - /** pmu_0p2a_cnt_target1_reach_0_lp_int_st : RO; bitpos: [19]; default: 0; - * reg_pmu_0p2a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p2a_cnt_target1_reach_0_lp_int_st:1; - /** pmu_0p2a_cnt_target0_reach_1_lp_int_st : RO; bitpos: [20]; default: 0; - * reg_pmu_0p2a_0 counter after xpd reach target0 - */ - uint32_t pmu_0p2a_cnt_target0_reach_1_lp_int_st:1; - /** pmu_0p2a_cnt_target1_reach_1_lp_int_st : RO; bitpos: [21]; default: 0; - * reg_pmu_0p2a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p2a_cnt_target1_reach_1_lp_int_st:1; - /** pmu_0p3a_cnt_target0_reach_0_lp_int_st : RO; bitpos: [22]; default: 0; - * reg_pmu_0p3a_0 counter after xpd reach target0 - */ - uint32_t pmu_0p3a_cnt_target0_reach_0_lp_int_st:1; - /** pmu_0p3a_cnt_target1_reach_0_lp_int_st : RO; bitpos: [23]; default: 0; - * reg_pmu_0p3a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p3a_cnt_target1_reach_0_lp_int_st:1; - /** pmu_0p3a_cnt_target0_reach_1_lp_int_st : RO; bitpos: [24]; default: 0; - * reg_pmu_0p3a_0_counter after xpd reach target0 - */ - uint32_t pmu_0p3a_cnt_target0_reach_1_lp_int_st:1; - /** pmu_0p3a_cnt_target1_reach_1_lp_int_st : RO; bitpos: [25]; default: 0; - * reg_pmu_0p3a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p3a_cnt_target1_reach_1_lp_int_st:1; - /** lp_cpu_wakeup_int_st : RO; bitpos: [26]; default: 0; - * need_des - */ - uint32_t lp_cpu_wakeup_int_st:1; - /** sleep_switch_active_end_int_st : RO; bitpos: [27]; default: 0; - * need_des - */ - uint32_t sleep_switch_active_end_int_st:1; - /** active_switch_sleep_end_int_st : RO; bitpos: [28]; default: 0; - * need_des - */ - uint32_t active_switch_sleep_end_int_st:1; - /** sleep_switch_active_start_int_st : RO; bitpos: [29]; default: 0; - * need_des - */ - uint32_t sleep_switch_active_start_int_st:1; - /** active_switch_sleep_start_int_st : RO; bitpos: [30]; default: 0; - * need_des - */ - uint32_t active_switch_sleep_start_int_st:1; - /** hp_sw_trigger_int_st : RO; bitpos: [31]; default: 0; - * need_des - */ - uint32_t hp_sw_trigger_int_st:1; - }; - uint32_t val; -} pmu_lp_int_st_reg_t; - -/** Type of lp_int_ena register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:13; - /** lp_cpu_sleep_reject_int_ena : R/W; bitpos: [13]; default: 0; - * need_des - */ - uint32_t lp_cpu_sleep_reject_int_ena:1; - /** pmu_0p1a_cnt_target0_reach_0_lp_int_ena : R/W; bitpos: [14]; default: 0; - * reg_pmu_0p1a_0_counter after xpd reach target0 - */ - uint32_t pmu_0p1a_cnt_target0_reach_0_lp_int_ena:1; - /** pmu_0p1a_cnt_target1_reach_0_lp_int_ena : R/W; bitpos: [15]; default: 0; - * reg_pmu_0p1a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p1a_cnt_target1_reach_0_lp_int_ena:1; - /** pmu_0p1a_cnt_target0_reach_1_lp_int_ena : R/W; bitpos: [16]; default: 0; - * reg_pmu_0p1a_0 counter after xpd reach target0 - */ - uint32_t pmu_0p1a_cnt_target0_reach_1_lp_int_ena:1; - /** pmu_0p1a_cnt_target1_reach_1_lp_int_ena : R/W; bitpos: [17]; default: 0; - * reg_pmu_0p1a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p1a_cnt_target1_reach_1_lp_int_ena:1; - /** pmu_0p2a_cnt_target0_reach_0_lp_int_ena : R/W; bitpos: [18]; default: 0; - * reg_pmu_0p2a_0 counter after xpd reach target0 - */ - uint32_t pmu_0p2a_cnt_target0_reach_0_lp_int_ena:1; - /** pmu_0p2a_cnt_target1_reach_0_lp_int_ena : R/W; bitpos: [19]; default: 0; - * reg_pmu_0p2a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p2a_cnt_target1_reach_0_lp_int_ena:1; - /** pmu_0p2a_cnt_target0_reach_1_lp_int_ena : R/W; bitpos: [20]; default: 0; - * reg_pmu_0p2a_0 counter after xpd reach target0 - */ - uint32_t pmu_0p2a_cnt_target0_reach_1_lp_int_ena:1; - /** pmu_0p2a_cnt_target1_reach_1_lp_int_ena : R/W; bitpos: [21]; default: 0; - * reg_pmu_0p2a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p2a_cnt_target1_reach_1_lp_int_ena:1; - /** pmu_0p3a_cnt_target0_reach_0_lp_int_ena : R/W; bitpos: [22]; default: 0; - * reg_pmu_0p3a_0 counter after xpd reach target0 - */ - uint32_t pmu_0p3a_cnt_target0_reach_0_lp_int_ena:1; - /** pmu_0p3a_cnt_target1_reach_0_lp_int_ena : R/W; bitpos: [23]; default: 0; - * reg_pmu_0p3a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p3a_cnt_target1_reach_0_lp_int_ena:1; - /** pmu_0p3a_cnt_target0_reach_1_lp_int_ena : R/W; bitpos: [24]; default: 0; - * reg_pmu_0p3a_0_counter after xpd reach target0 - */ - uint32_t pmu_0p3a_cnt_target0_reach_1_lp_int_ena:1; - /** pmu_0p3a_cnt_target1_reach_1_lp_int_ena : R/W; bitpos: [25]; default: 0; - * reg_pmu_0p3a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p3a_cnt_target1_reach_1_lp_int_ena:1; - /** lp_cpu_wakeup_int_ena : R/W; bitpos: [26]; default: 0; - * need_des - */ - uint32_t lp_cpu_wakeup_int_ena:1; - /** sleep_switch_active_end_int_ena : R/W; bitpos: [27]; default: 0; - * need_des - */ - uint32_t sleep_switch_active_end_int_ena:1; - /** active_switch_sleep_end_int_ena : R/W; bitpos: [28]; default: 0; - * need_des - */ - uint32_t active_switch_sleep_end_int_ena:1; - /** sleep_switch_active_start_int_ena : R/W; bitpos: [29]; default: 0; - * need_des - */ - uint32_t sleep_switch_active_start_int_ena:1; - /** active_switch_sleep_start_int_ena : R/W; bitpos: [30]; default: 0; - * need_des - */ - uint32_t active_switch_sleep_start_int_ena:1; - /** hp_sw_trigger_int_ena : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t hp_sw_trigger_int_ena:1; - }; - uint32_t val; -} pmu_lp_int_ena_reg_t; - -/** Type of lp_int_clr register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:13; - /** lp_cpu_sleep_reject_lp_int_clr : WT; bitpos: [13]; default: 0; - * need_des - */ - uint32_t lp_cpu_sleep_reject_lp_int_clr:1; - /** pmu_0p1a_cnt_target0_reach_0_lp_int_clr : WT; bitpos: [14]; default: 0; - * reg_pmu_0p1a_0_counter after xpd reach target0 - */ - uint32_t pmu_0p1a_cnt_target0_reach_0_lp_int_clr:1; - /** pmu_0p1a_cnt_target1_reach_0_lp_int_clr : WT; bitpos: [15]; default: 0; - * reg_pmu_0p1a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p1a_cnt_target1_reach_0_lp_int_clr:1; - /** pmu_0p1a_cnt_target0_reach_1_lp_int_clr : WT; bitpos: [16]; default: 0; - * reg_pmu_0p1a_0 counter after xpd reach target0 - */ - uint32_t pmu_0p1a_cnt_target0_reach_1_lp_int_clr:1; - /** pmu_0p1a_cnt_target1_reach_1_lp_int_clr : WT; bitpos: [17]; default: 0; - * reg_pmu_0p1a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p1a_cnt_target1_reach_1_lp_int_clr:1; - /** pmu_0p2a_cnt_target0_reach_0_lp_int_clr : WT; bitpos: [18]; default: 0; - * reg_pmu_0p2a_0 counter after xpd reach target0 - */ - uint32_t pmu_0p2a_cnt_target0_reach_0_lp_int_clr:1; - /** pmu_0p2a_cnt_target1_reach_0_lp_int_clr : WT; bitpos: [19]; default: 0; - * reg_pmu_0p2a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p2a_cnt_target1_reach_0_lp_int_clr:1; - /** pmu_0p2a_cnt_target0_reach_1_lp_int_clr : WT; bitpos: [20]; default: 0; - * reg_pmu_0p2a_0 counter after xpd reach target0 - */ - uint32_t pmu_0p2a_cnt_target0_reach_1_lp_int_clr:1; - /** pmu_0p2a_cnt_target1_reach_1_lp_int_clr : WT; bitpos: [21]; default: 0; - * reg_pmu_0p2a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p2a_cnt_target1_reach_1_lp_int_clr:1; - /** pmu_0p3a_cnt_target0_reach_0_lp_int_clr : WT; bitpos: [22]; default: 0; - * reg_pmu_0p3a_0 counter after xpd reach target0 - */ - uint32_t pmu_0p3a_cnt_target0_reach_0_lp_int_clr:1; - /** pmu_0p3a_cnt_target1_reach_0_lp_int_clr : WT; bitpos: [23]; default: 0; - * reg_pmu_0p3a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p3a_cnt_target1_reach_0_lp_int_clr:1; - /** pmu_0p3a_cnt_target0_reach_1_lp_int_clr : WT; bitpos: [24]; default: 0; - * reg_pmu_0p3a_0_counter after xpd reach target0 - */ - uint32_t pmu_0p3a_cnt_target0_reach_1_lp_int_clr:1; - /** pmu_0p3a_cnt_target1_reach_1_lp_int_clr : WT; bitpos: [25]; default: 0; - * reg_pmu_0p3a_1_counter after xpd reach target1 - */ - uint32_t pmu_0p3a_cnt_target1_reach_1_lp_int_clr:1; - /** lp_cpu_wakeup_int_clr : WT; bitpos: [26]; default: 0; - * need_des - */ - uint32_t lp_cpu_wakeup_int_clr:1; - /** sleep_switch_active_end_int_clr : WT; bitpos: [27]; default: 0; - * need_des - */ - uint32_t sleep_switch_active_end_int_clr:1; - /** active_switch_sleep_end_int_clr : WT; bitpos: [28]; default: 0; - * need_des - */ - uint32_t active_switch_sleep_end_int_clr:1; - /** sleep_switch_active_start_int_clr : WT; bitpos: [29]; default: 0; - * need_des - */ - uint32_t sleep_switch_active_start_int_clr:1; - /** active_switch_sleep_start_int_clr : WT; bitpos: [30]; default: 0; - * need_des - */ - uint32_t active_switch_sleep_start_int_clr:1; - /** hp_sw_trigger_int_clr : WT; bitpos: [31]; default: 0; - * need_des - */ - uint32_t hp_sw_trigger_int_clr:1; - }; - uint32_t val; -} pmu_lp_int_clr_reg_t; - -/** Type of lp_cpu_pwr0 register - * need_des - */ -typedef union { - struct { - /** lp_cpu_waiti_rdy : RO; bitpos: [0]; default: 0; - * need_des - */ - uint32_t lp_cpu_waiti_rdy:1; - /** lp_cpu_stall_rdy : RO; bitpos: [1]; default: 0; - * need_des - */ - uint32_t lp_cpu_stall_rdy:1; - uint32_t reserved_2:16; - /** lp_cpu_force_stall : R/W; bitpos: [18]; default: 0; - * need_des - */ - uint32_t lp_cpu_force_stall:1; - /** lp_cpu_slp_waiti_flag_en : R/W; bitpos: [19]; default: 0; - * need_des - */ - uint32_t lp_cpu_slp_waiti_flag_en:1; - /** lp_cpu_slp_stall_flag_en : R/W; bitpos: [20]; default: 1; - * need_des - */ - uint32_t lp_cpu_slp_stall_flag_en:1; - /** lp_cpu_slp_stall_wait : R/W; bitpos: [28:21]; default: 255; - * need_des - */ - uint32_t lp_cpu_slp_stall_wait:8; - /** lp_cpu_slp_stall_en : R/W; bitpos: [29]; default: 0; - * need_des - */ - uint32_t lp_cpu_slp_stall_en:1; - /** lp_cpu_slp_reset_en : R/W; bitpos: [30]; default: 0; - * need_des - */ - uint32_t lp_cpu_slp_reset_en:1; - /** lp_cpu_slp_bypass_intr_en : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t lp_cpu_slp_bypass_intr_en:1; - }; - uint32_t val; -} pmu_lp_cpu_pwr0_reg_t; +} pmu_hp_clk_cntl_reg_t; -/** Type of lp_cpu_pwr1 register - * need_des - */ typedef union { struct { - uint32_t reserved_0:31; - /** lp_cpu_sleep_req : WT; bitpos: [31]; default: 0; - * need_des - */ - uint32_t lp_cpu_sleep_req:1; + uint32_t reserved0: 31; + uint32_t por_done : 1; }; uint32_t val; -} pmu_lp_cpu_pwr1_reg_t; +} pmu_por_status_reg_t; -/** Type of lp_cpu_pwr2 register - * need_des - */ typedef union { struct { - /** lp_cpu_wakeup_en : R/W; bitpos: [30:0]; default: 0; - * need_des - */ - uint32_t lp_cpu_wakeup_en:31; - uint32_t reserved_31:1; + uint32_t reserved0 : 24; + uint32_t mspi_phy_xpd : 1;//new + uint32_t sdio_pll_xpd : 1;//new + uint32_t perif_i2c_rstb: 1; + uint32_t xpd_perif_i2c : 1; + uint32_t xpd_txrf_i2c : 1; + uint32_t xpd_rfrx_pbus : 1; + uint32_t xpd_ckgen_i2c : 1; + // uint32_t xpd_pll_i2c : 1; + uint32_t reserved1 : 1; }; uint32_t val; -} pmu_lp_cpu_pwr2_reg_t; +} pmu_rf_pwc_reg_t; -/** Type of lp_cpu_pwr3 register - * need_des - */ typedef union { struct { - /** lp_cpu_wakeup_cause : RO; bitpos: [30:0]; default: 0; - * need_des - */ - uint32_t lp_cpu_wakeup_cause:31; - uint32_t reserved_31:1; + uint32_t reserved0 : 31; + uint32_t backup_sysclk_nodiv: 1; }; uint32_t val; -} pmu_lp_cpu_pwr3_reg_t; +} pmu_backup_cfg_reg_t; -/** Type of lp_cpu_pwr4 register - * need_des - */ typedef union { struct { - /** lp_cpu_reject_en : R/W; bitpos: [30:0]; default: 0; - * need_des - */ - uint32_t lp_cpu_reject_en:31; - uint32_t reserved_31:1; + uint32_t reserved0 : 14; + uint32_t pmu_0p1a_cnt_target0_reach_0 : 1;//new + uint32_t pmu_0p1a_cnt_target1_reach_0 : 1;//new + uint32_t pmu_0p1a_cnt_target0_reach_1 : 1;//new + uint32_t pmu_0p1a_cnt_target1_reach_1 : 1;//new + uint32_t pmu_0p2a_cnt_target0_reach_0 : 1;//new + uint32_t pmu_0p2a_cnt_target1_reach_0 : 1;//new + uint32_t pmu_0p2a_cnt_target0_reach_1 : 1;//new + uint32_t pmu_0p2a_cnt_target1_reach_1 : 1;//new + uint32_t pmu_0p3a_cnt_target0_reach_0 : 1;//new + uint32_t pmu_0p3a_cnt_target1_reach_0 : 1;//new + uint32_t pmu_0p3a_cnt_target0_reach_1 : 1;//new + uint32_t pmu_0p3a_cnt_target1_reach_1 : 1;//new + uint32_t reserved1 : 1; + uint32_t lp_exception: 1; + uint32_t sdio_idle: 1; + uint32_t sw : 1; + uint32_t reject : 1; + uint32_t wakeup : 1; + }; + uint32_t val; +} pmu_hp_intr_reg_t; + +typedef struct pmu_hp_ext_hw_regmap_t { + pmu_hp_clk_poweron_reg_t clk_poweron; + pmu_hp_clk_cntl_reg_t clk_cntl; + pmu_por_status_reg_t por_status; + pmu_rf_pwc_reg_t rf_pwc; + pmu_backup_cfg_reg_t backup_cfg; + pmu_hp_intr_reg_t int_raw; + pmu_hp_intr_reg_t int_st; + pmu_hp_intr_reg_t int_ena; + pmu_hp_intr_reg_t int_clr; +} pmu_hp_ext_hw_regmap_t; + +typedef union { + struct { + uint32_t reserved0 : 13; + uint32_t sleep_reject : 1;//new + uint32_t pmu_0p1a_cnt_target0_reach_0 : 1;//new + uint32_t pmu_0p1a_cnt_target1_reach_0 : 1;//new + uint32_t pmu_0p1a_cnt_target0_reach_1 : 1;//new + uint32_t pmu_0p1a_cnt_target1_reach_1 : 1;//new + uint32_t pmu_0p2a_cnt_target0_reach_0 : 1;//new + uint32_t pmu_0p2a_cnt_target1_reach_0 : 1;//new + uint32_t pmu_0p2a_cnt_target0_reach_1 : 1;//new + uint32_t pmu_0p2a_cnt_target1_reach_1 : 1;//new + uint32_t pmu_0p3a_cnt_target0_reach_0 : 1;//new + uint32_t pmu_0p3a_cnt_target1_reach_0 : 1;//new + uint32_t pmu_0p3a_cnt_target0_reach_1 : 1;//new + uint32_t pmu_0p3a_cnt_target1_reach_1 : 1;//new + uint32_t lp_wakeup : 1; + // uint32_t modem_switch_active_end : 1; + uint32_t sleep_switch_active_end : 1; + // uint32_t sleep_switch_modem_end : 1; + // uint32_t modem_switch_sleep_end : 1; + uint32_t active_switch_sleep_end : 1; + // uint32_t modem_switch_active_start: 1; + uint32_t sleep_switch_active_start: 1; + // uint32_t sleep_switch_modem_start : 1; + // uint32_t modem_switch_sleep_start : 1; + uint32_t active_switch_sleep_start: 1; + uint32_t hp_sw_trigger : 1; + }; + uint32_t val; +} pmu_lp_intr_reg_t; + +typedef union { + struct { + uint32_t waiti_rdy : 1; + uint32_t stall_rdy : 1; + uint32_t reserved0 : 16; + uint32_t force_stall : 1; + uint32_t slp_waiti_flag_en : 1; + uint32_t slp_stall_flag_en : 1; + uint32_t slp_stall_wait : 8; + uint32_t slp_stall_en : 1; + uint32_t slp_reset_en : 1; + uint32_t slp_bypass_intr_en: 1; }; uint32_t val; -} pmu_lp_cpu_pwr4_reg_t; +} pmu_lp_cpu_pwr0_reg_t; -/** Type of lp_cpu_pwr5 register - * need_des - */ typedef union { struct { - /** lp_cpu_reject_cause : RO; bitpos: [30:0]; default: 0; - * need_des - */ - uint32_t lp_cpu_reject_cause:31; - uint32_t reserved_31:1; + // uint32_t wakeup_en: 16; + uint32_t reserved0: 31; + uint32_t sleep_req: 1; }; uint32_t val; -} pmu_lp_cpu_pwr5_reg_t; +} pmu_lp_cpu_pwr1_reg_t; -/** Type of hp_lp_cpu_comm register - * need_des - */ typedef union { struct { - uint32_t reserved_0:30; - /** lp_trigger_hp : WT; bitpos: [30]; default: 0; - * need_des - */ - uint32_t lp_trigger_hp:1; - /** hp_trigger_lp : WT; bitpos: [31]; default: 0; - * need_des - */ - uint32_t hp_trigger_lp:1; + uint32_t wakeup_en: 31; + uint32_t reserved0: 1; }; uint32_t val; -} pmu_hp_lp_cpu_comm_reg_t; +} pmu_lp_cpu_pwr2_reg_t; //new -/** Type of hp_regulator_cfg register - * need_des - */ typedef union { struct { - uint32_t reserved_0:31; - /** dig_regulator_en_cal : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t dig_regulator_en_cal:1; + uint32_t wakeup_cause: 31; + uint32_t reserved0: 1; }; uint32_t val; -} pmu_hp_regulator_cfg_reg_t; +} pmu_lp_cpu_pwr3_reg_t; //new -/** Type of main_state register - * need_des - */ typedef union { struct { - /** enable_cali_pmu_cntl : R/W; bitpos: [0]; default: 1; - * need_des - */ - uint32_t enable_cali_pmu_cntl:1; - uint32_t reserved_1:10; - /** pmu_main_last_st_state : RO; bitpos: [17:11]; default: 1; - * need_des - */ - uint32_t pmu_main_last_st_state:7; - /** pmu_main_tar_st_state : RO; bitpos: [24:18]; default: 4; - * need_des - */ - uint32_t pmu_main_tar_st_state:7; - /** pmu_main_cur_st_state : RO; bitpos: [31:25]; default: 4; - * need_des - */ - uint32_t pmu_main_cur_st_state:7; + uint32_t sleep_reject: 31; + uint32_t reserved0: 1; }; uint32_t val; -} pmu_main_state_reg_t; +} pmu_lp_cpu_pwr4_reg_t; //new -/** Type of pwr_state register - * need_des - */ typedef union { struct { - uint32_t reserved_0:13; - /** pmu_backup_st_state : RO; bitpos: [17:13]; default: 1; - * need_des - */ - uint32_t pmu_backup_st_state:5; - /** pmu_lp_pwr_st_state : RO; bitpos: [22:18]; default: 0; - * need_des - */ - uint32_t pmu_lp_pwr_st_state:5; - /** pmu_hp_pwr_st_state : RO; bitpos: [31:23]; default: 1; - * need_des - */ - uint32_t pmu_hp_pwr_st_state:9; + uint32_t sleep_reject_cause: 31; + uint32_t reserved0: 1; }; uint32_t val; -} pmu_pwr_state_reg_t; +} pmu_lp_cpu_pwr5_reg_t; //new + +typedef struct pmu_lp_ext_hw_regmap_t { + pmu_lp_intr_reg_t int_raw; + pmu_lp_intr_reg_t int_st; + pmu_lp_intr_reg_t int_ena; + pmu_lp_intr_reg_t int_clr; + pmu_lp_cpu_pwr0_reg_t pwr0; + pmu_lp_cpu_pwr1_reg_t pwr1; + pmu_lp_cpu_pwr2_reg_t pwr2; + pmu_lp_cpu_pwr3_reg_t pwr3; + pmu_lp_cpu_pwr4_reg_t pwr4; + pmu_lp_cpu_pwr5_reg_t pwr5; +} pmu_lp_ext_hw_regmap_t; + +typedef struct { + volatile struct { + } common; +} pmu_hp_lp_hw_regmap_t; + /** Type of pmu_ext_ldo register * need_des @@ -2996,523 +841,215 @@ typedef union { /** Type of ahb_dma_in_chn_reg_t register * need_des */ -typedef volatile struct pmu_ext_ldo_info_s { +typedef struct { volatile pmu_ext_ldo_reg_t pmu_ext_ldo; volatile pmu_ext_ldo_ana_reg_t pmu_ext_ldo_ana; } pmu_ext_ldo_info_t; -/** Type of ext_wakeup_lv register - * need_des - */ -typedef union { - struct { - /** ext_wakeup_lv : R/W; bitpos: [31:0]; default: 0; - * need_des - */ - uint32_t ext_wakeup_lv:32; - }; - uint32_t val; -} pmu_ext_wakeup_lv_reg_t; - -/** Type of ext_wakeup_sel register - * need_des - */ -typedef union { - struct { - /** ext_wakeup_sel : R/W; bitpos: [31:0]; default: 0; - * need_des - */ - uint32_t ext_wakeup_sel:32; - }; - uint32_t val; -} pmu_ext_wakeup_sel_reg_t; - -/** Type of ext_wakeup_st register - * need_des - */ -typedef union { - struct { - /** ext_wakeup_status : RO; bitpos: [31:0]; default: 0; - * need_des - */ - uint32_t ext_wakeup_status:32; - }; - uint32_t val; -} pmu_ext_wakeup_st_reg_t; - -/** Type of ext_wakeup_cntl register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:30; - /** ext_wakeup_status_clr : R/W; bitpos: [30]; default: 0; - * need_des - */ - uint32_t ext_wakeup_status_clr:1; - /** ext_wakeup_filter : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t ext_wakeup_filter:1; - }; - uint32_t val; -} pmu_ext_wakeup_cntl_reg_t; - -/** Type of sdio_wakeup_cntl register - * need_des - */ -typedef union { - struct { - /** sdio_act_dnum : R/W; bitpos: [9:0]; default: 1023; - * need_des - */ - uint32_t sdio_act_dnum:10; - uint32_t reserved_10:22; - }; - uint32_t val; -} pmu_sdio_wakeup_cntl_reg_t; - -/** Type of cpu_sw_stall register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:16; - /** hpcore1_sw_stall_code : R/W; bitpos: [23:16]; default: 0; - * need_des - */ - uint32_t hpcore1_sw_stall_code:8; - /** hpcore0_sw_stall_code : R/W; bitpos: [31:24]; default: 0; - * need_des - */ - uint32_t hpcore0_sw_stall_code:8; - }; - uint32_t val; -} pmu_cpu_sw_stall_reg_t; - -/** Type of dcm_ctrl register - * need_des - */ -typedef union { - struct { - /** dcdc_on_req : WT; bitpos: [0]; default: 0; - * SW trigger dcdc on - */ - uint32_t dcdc_on_req:1; - /** dcdc_off_req : WT; bitpos: [1]; default: 0; - * SW trigger dcdc off - */ - uint32_t dcdc_off_req:1; - /** dcdc_lightslp_req : WT; bitpos: [2]; default: 0; - * SW trigger dcdc enter lightsleep - */ - uint32_t dcdc_lightslp_req:1; - /** dcdc_deepslp_req : WT; bitpos: [3]; default: 0; - * SW trigger dcdc enter deepsleep - */ - uint32_t dcdc_deepslp_req:1; - uint32_t reserved_4:3; - /** dcdc_done_force : R/W; bitpos: [7]; default: 0; - * need_des - */ - uint32_t dcdc_done_force:1; - /** dcdc_on_force_pu : R/W; bitpos: [8]; default: 0; - * need_des - */ - uint32_t dcdc_on_force_pu:1; - /** dcdc_on_force_pd : R/W; bitpos: [9]; default: 0; - * need_des - */ - uint32_t dcdc_on_force_pd:1; - /** dcdc_fb_res_force_pu : R/W; bitpos: [10]; default: 0; - * need_des - */ - uint32_t dcdc_fb_res_force_pu:1; - /** dcdc_fb_res_force_pd : R/W; bitpos: [11]; default: 0; - * need_des - */ - uint32_t dcdc_fb_res_force_pd:1; - /** dcdc_ls_force_pu : R/W; bitpos: [12]; default: 0; - * need_des - */ - uint32_t dcdc_ls_force_pu:1; - /** dcdc_ls_force_pd : R/W; bitpos: [13]; default: 0; - * need_des - */ - uint32_t dcdc_ls_force_pd:1; - /** dcdc_ds_force_pu : R/W; bitpos: [14]; default: 0; - * need_des - */ - uint32_t dcdc_ds_force_pu:1; - /** dcdc_ds_force_pd : R/W; bitpos: [15]; default: 0; - * need_des - */ - uint32_t dcdc_ds_force_pd:1; - /** dcm_cur_st : RO; bitpos: [23:16]; default: 1; - * need_des - */ - uint32_t dcm_cur_st:8; - uint32_t reserved_24:5; - /** dcdc_en_amux_test : R/W; bitpos: [29]; default: 0; - * Enable analog mux to pull PAD TEST_DCDC voltage signal - */ - uint32_t dcdc_en_amux_test:1; - uint32_t reserved_30:2; - }; - uint32_t val; -} pmu_dcm_ctrl_reg_t; - -/** Type of dcm_wait_delay register - * need_des - */ -typedef union { - struct { - /** dcdc_pre_delay : R/W; bitpos: [7:0]; default: 5; - * DCDC pre-on/post off delay - */ - uint32_t dcdc_pre_delay:8; - /** dcdc_res_off_delay : R/W; bitpos: [15:8]; default: 2; - * DCDC fb res off delay - */ - uint32_t dcdc_res_off_delay:8; - /** dcdc_stable_delay : R/W; bitpos: [25:16]; default: 75; - * DCDC stable delay - */ - uint32_t dcdc_stable_delay:10; - uint32_t reserved_26:6; - }; - uint32_t val; -} pmu_dcm_wait_delay_reg_t; - -/** Type of vddbat_cfg register - * need_des - */ -typedef union { - struct { - /** ana_vddbat_mode : RO; bitpos: [1:0]; default: 0; - * need_des - */ - uint32_t ana_vddbat_mode:2; - uint32_t reserved_2:29; - /** vddbat_sw_update : WT; bitpos: [31]; default: 0; - * need_des - */ - uint32_t vddbat_sw_update:1; - }; - uint32_t val; -} pmu_vddbat_cfg_reg_t; - -/** Type of touch_pwr_cntl register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:5; - /** touch_wait_cycles : R/W; bitpos: [13:5]; default: 10; - * need_des - */ - uint32_t touch_wait_cycles:9; - /** touch_sleep_cycles : R/W; bitpos: [29:14]; default: 100; - * need_des - */ - uint32_t touch_sleep_cycles:16; - /** touch_force_done : R/W; bitpos: [30]; default: 0; - * need_des - */ - uint32_t touch_force_done:1; - /** touch_sleep_timer_en : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t touch_sleep_timer_en:1; - }; - uint32_t val; -} pmu_touch_pwr_cntl_reg_t; - -/** Type of rdn_eco register - * need_des - */ -typedef union { - struct { - /** pmu_rdn_eco_result : RO; bitpos: [0]; default: 0; - * need_des - */ - uint32_t pmu_rdn_eco_result:1; - uint32_t reserved_1:30; - /** pmu_rdn_eco_en : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t pmu_rdn_eco_en:1; - }; - uint32_t val; -} pmu_rdn_eco_reg_t; - -/** Type of date register - * need_des - */ -typedef union { - struct { - /** pmu_date : R/W; bitpos: [30:0]; default: 36712768; - * need_des - */ - uint32_t pmu_date:31; - /** clk_en : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t clk_en:1; - }; - uint32_t val; -} pmu_date_reg_t; - - -/** Group: status_register */ -/** Type of clk_state0 register - * need_des - */ typedef union { struct { - /** stable_xpd_pll_state : RO; bitpos: [2:0]; default: 7; - * need_des - */ - uint32_t stable_xpd_pll_state:3; - /** stable_xpd_xtal_state : RO; bitpos: [3]; default: 1; - * need_des - */ - uint32_t stable_xpd_xtal_state:1; - /** pmu_ana_xpd_pll_i2c_state : RO; bitpos: [6:4]; default: 0; - * need_des - */ - uint32_t pmu_ana_xpd_pll_i2c_state:3; - uint32_t reserved_7:3; - /** pmu_sys_clk_slp_sel_state : RO; bitpos: [10]; default: 0; - * need_des - */ - uint32_t pmu_sys_clk_slp_sel_state:1; - /** pmu_sys_clk_sel_state : RO; bitpos: [12:11]; default: 0; - * need_des - */ - uint32_t pmu_sys_clk_sel_state:2; - /** pmu_sys_clk_no_div_state : RO; bitpos: [13]; default: 0; - * need_des - */ - uint32_t pmu_sys_clk_no_div_state:1; - /** pmu_icg_sys_clk_en_state : RO; bitpos: [14]; default: 0; - * need_des - */ - uint32_t pmu_icg_sys_clk_en_state:1; - /** pmu_icg_modem_switch_state : RO; bitpos: [15]; default: 0; - * need_des - */ - uint32_t pmu_icg_modem_switch_state:1; - /** pmu_icg_modem_code_state : RO; bitpos: [17:16]; default: 0; - * need_des - */ - uint32_t pmu_icg_modem_code_state:2; - /** pmu_icg_slp_sel_state : RO; bitpos: [18]; default: 0; - * need_des - */ - uint32_t pmu_icg_slp_sel_state:1; - /** pmu_icg_global_xtal_state : RO; bitpos: [19]; default: 0; - * need_des - */ - uint32_t pmu_icg_global_xtal_state:1; - /** pmu_icg_global_pll_state : RO; bitpos: [23:20]; default: 0; - * need_des - */ - uint32_t pmu_icg_global_pll_state:4; - /** pmu_ana_i2c_iso_en_state : RO; bitpos: [24]; default: 0; - * need_des - */ - uint32_t pmu_ana_i2c_iso_en_state:1; - /** pmu_ana_i2c_retention_state : RO; bitpos: [25]; default: 0; - * need_des - */ - uint32_t pmu_ana_i2c_retention_state:1; - uint32_t reserved_26:1; - /** pmu_ana_xpd_pll_state : RO; bitpos: [30:27]; default: 0; - * need_des - */ - uint32_t pmu_ana_xpd_pll_state:4; - /** pmu_ana_xpd_xtal_state : RO; bitpos: [31]; default: 0; - * need_des - */ - uint32_t pmu_ana_xpd_xtal_state:1; + uint32_t on_req : 1; + uint32_t off_req : 1; + uint32_t lightslp_req : 1; + uint32_t deepslp_req : 1; + uint32_t reserved0 : 3; + uint32_t done_force : 1; + uint32_t on_force_pu : 1; + uint32_t on_force_pd : 1; + uint32_t fb_res_force_pu : 1; + uint32_t fb_res_force_pd : 1; + uint32_t ls_force_pu : 1; + uint32_t ls_force_pd : 1; + uint32_t ds_force_pu : 1; + uint32_t ds_force_pd : 1; + uint32_t dcm_cur_st : 8; + uint32_t reserved1 : 5; + uint32_t en_amux_test : 1; + uint32_t reserved2 : 2; }; uint32_t val; -} pmu_clk_state0_reg_t; +} pmu_dcm_ctrl_reg_t; //new -/** Type of clk_state1 register - * need_des - */ typedef union { struct { - /** pmu_icg_func_en_state : RO; bitpos: [31:0]; default: 4294967295; - * need_des - */ - uint32_t pmu_icg_func_en_state:32; + uint32_t pre_delay : 8; + uint32_t res_off_delay : 8; + uint32_t stable_delay : 10; + uint32_t reserved0 : 6; }; uint32_t val; -} pmu_clk_state1_reg_t; +} pmu_dcm_wait_delay_t; -/** Type of clk_state2 register - * need_des - */ typedef union { struct { - /** pmu_icg_apb_en_state : RO; bitpos: [31:0]; default: 4294967295; - * need_des - */ - uint32_t pmu_icg_apb_en_state:32; + uint32_t module : 2; + uint32_t reserved1 : 29; + uint32_t sw_update : 1; }; uint32_t val; -} pmu_clk_state2_reg_t; +} pmu_vddbat_cfg_t; -/** Type of xtal_slp register - * need_des - */ typedef union { struct { - uint32_t reserved_0:16; - /** xtal_slp_cnt_target : R/W; bitpos: [31:16]; default: 15; - * need_des - */ - uint32_t xtal_slp_cnt_target:16; + uint32_t reserved0 : 5; + uint32_t wait_cycles : 9; + uint32_t sleep_cycles : 16; + uint32_t force_done : 1; + uint32_t sleep_timer_en : 1; }; uint32_t val; -} pmu_xtal_slp_reg_t; - +} pmu_touch_sensor_pwr_cntl_t; typedef struct pmu_dev_t { - volatile pmu_hp_active_dig_power_reg_t hp_active_dig_power; - volatile pmu_hp_active_icg_hp_func_reg_t hp_active_icg_hp_func; - volatile pmu_hp_active_icg_hp_apb_reg_t hp_active_icg_hp_apb; - volatile pmu_hp_active_icg_modem_reg_t hp_active_icg_modem; - volatile pmu_hp_active_hp_sys_cntl_reg_t hp_active_hp_sys_cntl; - volatile pmu_hp_active_hp_ck_power_reg_t hp_active_hp_ck_power; - volatile pmu_hp_active_bias_reg_t hp_active_bias; - volatile pmu_hp_active_backup_reg_t hp_active_backup; - volatile pmu_hp_active_backup_clk_reg_t hp_active_backup_clk; - volatile pmu_hp_active_sysclk_reg_t hp_active_sysclk; - volatile pmu_hp_active_hp_regulator0_reg_t hp_active_hp_regulator0; - volatile pmu_hp_active_hp_regulator1_reg_t hp_active_hp_regulator1; - volatile pmu_hp_active_xtal_reg_t hp_active_xtal; - volatile pmu_hp_modem_dig_power_reg_t hp_modem_dig_power; - volatile pmu_hp_modem_icg_hp_func_reg_t hp_modem_icg_hp_func; - volatile pmu_hp_modem_icg_hp_apb_reg_t hp_modem_icg_hp_apb; - volatile pmu_hp_modem_icg_modem_reg_t hp_modem_icg_modem; - volatile pmu_hp_modem_hp_sys_cntl_reg_t hp_modem_hp_sys_cntl; - volatile pmu_hp_modem_hp_ck_power_reg_t hp_modem_hp_ck_power; - volatile pmu_hp_modem_bias_reg_t hp_modem_bias; - volatile pmu_hp_modem_backup_reg_t hp_modem_backup; - volatile pmu_hp_modem_backup_clk_reg_t hp_modem_backup_clk; - volatile pmu_hp_modem_sysclk_reg_t hp_modem_sysclk; - volatile pmu_hp_modem_hp_regulator0_reg_t hp_modem_hp_regulator0; - volatile pmu_hp_modem_hp_regulator1_reg_t hp_modem_hp_regulator1; - volatile pmu_hp_modem_xtal_reg_t hp_modem_xtal; - volatile pmu_hp_sleep_dig_power_reg_t hp_sleep_dig_power; - volatile pmu_hp_sleep_icg_hp_func_reg_t hp_sleep_icg_hp_func; - volatile pmu_hp_sleep_icg_hp_apb_reg_t hp_sleep_icg_hp_apb; - volatile pmu_hp_sleep_icg_modem_reg_t hp_sleep_icg_modem; - volatile pmu_hp_sleep_hp_sys_cntl_reg_t hp_sleep_hp_sys_cntl; - volatile pmu_hp_sleep_hp_ck_power_reg_t hp_sleep_hp_ck_power; - volatile pmu_hp_sleep_bias_reg_t hp_sleep_bias; - volatile pmu_hp_sleep_backup_reg_t hp_sleep_backup; - volatile pmu_hp_sleep_backup_clk_reg_t hp_sleep_backup_clk; - volatile pmu_hp_sleep_sysclk_reg_t hp_sleep_sysclk; - volatile pmu_hp_sleep_hp_regulator0_reg_t hp_sleep_hp_regulator0; - volatile pmu_hp_sleep_hp_regulator1_reg_t hp_sleep_hp_regulator1; - volatile pmu_hp_sleep_xtal_reg_t hp_sleep_xtal; - volatile pmu_hp_sleep_lp_regulator0_reg_t hp_sleep_lp_regulator0; - volatile pmu_hp_sleep_lp_regulator1_reg_t hp_sleep_lp_regulator1; - uint32_t reserved_0a4; - volatile pmu_hp_sleep_lp_dig_power_reg_t hp_sleep_lp_dig_power; - volatile pmu_hp_sleep_lp_ck_power_reg_t hp_sleep_lp_ck_power; - uint32_t reserved_0b0; - volatile pmu_lp_sleep_lp_regulator0_reg_t lp_sleep_lp_regulator0; - volatile pmu_lp_sleep_lp_regulator1_reg_t lp_sleep_lp_regulator1; - volatile pmu_lp_sleep_xtal_reg_t lp_sleep_xtal; - volatile pmu_lp_sleep_lp_dig_power_reg_t lp_sleep_lp_dig_power; - volatile pmu_lp_sleep_lp_ck_power_reg_t lp_sleep_lp_ck_power; - volatile pmu_lp_sleep_bias_reg_t lp_sleep_bias; - volatile pmu_imm_hp_ck_power_reg_t imm_hp_ck_power; - volatile pmu_imm_sleep_sysclk_reg_t imm_sleep_sysclk; - volatile pmu_imm_hp_func_icg_reg_t imm_hp_func_icg; - volatile pmu_imm_hp_apb_icg_reg_t imm_hp_apb_icg; - volatile pmu_imm_modem_icg_reg_t imm_modem_icg; - volatile pmu_imm_lp_icg_reg_t imm_lp_icg; - volatile pmu_imm_pad_hold_all_reg_t imm_pad_hold_all; - volatile pmu_imm_i2c_iso_reg_t imm_i2c_iso; - volatile pmu_power_wait_timer0_reg_t power_wait_timer0; - volatile pmu_power_wait_timer1_reg_t power_wait_timer1; - volatile pmu_power_pd_top_cntl_reg_t power_pd_top_cntl; - volatile pmu_power_pd_cnnt_cntl_reg_t power_pd_cnnt_cntl; - volatile pmu_power_pd_hpmem_cntl_reg_t power_pd_hpmem_cntl; - volatile pmu_power_pd_top_mask_reg_t power_pd_top_mask; - volatile pmu_power_pd_cnnt_mask_reg_t power_pd_cnnt_mask; - volatile pmu_power_pd_hpmem_mask_reg_t power_pd_hpmem_mask; - volatile pmu_power_dcdc_switch_reg_t power_dcdc_switch; - volatile pmu_power_pd_lpperi_cntl_reg_t power_pd_lpperi_cntl; - volatile pmu_power_pd_lpperi_mask_reg_t power_pd_lpperi_mask; - volatile pmu_power_hp_pad_reg_t power_hp_pad; - volatile pmu_power_ck_wait_cntl_reg_t power_ck_wait_cntl; - volatile pmu_slp_wakeup_cntl0_reg_t slp_wakeup_cntl0; - volatile pmu_slp_wakeup_cntl1_reg_t slp_wakeup_cntl1; - volatile pmu_slp_wakeup_cntl2_reg_t slp_wakeup_cntl2; - volatile pmu_slp_wakeup_cntl3_reg_t slp_wakeup_cntl3; - volatile pmu_slp_wakeup_cntl4_reg_t slp_wakeup_cntl4; - volatile pmu_slp_wakeup_cntl5_reg_t slp_wakeup_cntl5; - volatile pmu_slp_wakeup_cntl6_reg_t slp_wakeup_cntl6; - volatile pmu_slp_wakeup_cntl7_reg_t slp_wakeup_cntl7; - volatile pmu_slp_wakeup_cntl8_reg_t slp_wakeup_cntl8; - volatile pmu_slp_wakeup_status0_reg_t slp_wakeup_status0; - volatile pmu_slp_wakeup_status1_reg_t slp_wakeup_status1; - volatile pmu_slp_wakeup_status2_reg_t slp_wakeup_status2; - volatile pmu_hp_ck_poweron_reg_t hp_ck_poweron; - volatile pmu_hp_ck_cntl_reg_t hp_ck_cntl; - volatile pmu_por_status_reg_t por_status; - volatile pmu_rf_pwc_reg_t rf_pwc; - volatile pmu_backup_cfg_reg_t backup_cfg; - volatile pmu_int_raw_reg_t int_raw; - volatile pmu_hp_int_st_reg_t hp_int_st; - volatile pmu_hp_int_ena_reg_t hp_int_ena; - volatile pmu_hp_int_clr_reg_t hp_int_clr; - volatile pmu_lp_int_raw_reg_t lp_int_raw; - volatile pmu_lp_int_st_reg_t lp_int_st; - volatile pmu_lp_int_ena_reg_t lp_int_ena; - volatile pmu_lp_int_clr_reg_t lp_int_clr; - volatile pmu_lp_cpu_pwr0_reg_t lp_cpu_pwr0; - volatile pmu_lp_cpu_pwr1_reg_t lp_cpu_pwr1; - volatile pmu_lp_cpu_pwr2_reg_t lp_cpu_pwr2; - volatile pmu_lp_cpu_pwr3_reg_t lp_cpu_pwr3; - volatile pmu_lp_cpu_pwr4_reg_t lp_cpu_pwr4; - volatile pmu_lp_cpu_pwr5_reg_t lp_cpu_pwr5; - volatile pmu_hp_lp_cpu_comm_reg_t hp_lp_cpu_comm; - volatile pmu_hp_regulator_cfg_reg_t hp_regulator_cfg; - volatile pmu_main_state_reg_t main_state; - volatile pmu_pwr_state_reg_t pwr_state; - volatile pmu_clk_state0_reg_t clk_state0; - volatile pmu_clk_state1_reg_t clk_state1; - volatile pmu_clk_state2_reg_t clk_state2; + volatile pmu_hp_hw_regmap_t hp_sys[3]; + volatile pmu_lp_hw_regmap_t lp_sys[2]; + volatile pmu_imm_hw_regmap_t imm; + volatile pmu_power_hw_regmap_t power; + volatile pmu_wakeup_hw_regmap_t wakeup; + volatile pmu_hp_ext_hw_regmap_t hp_ext; + volatile pmu_lp_ext_hw_regmap_t lp_ext; + + union { + struct { + uint32_t reserved0 : 30; + volatile uint32_t lp_trigger_hp: 1; + volatile uint32_t hp_trigger_lp: 1; + }; + volatile uint32_t val; + } hp_lp_cpu_comm; + + union { + struct { + uint32_t reserved0 : 31; + volatile uint32_t dig_regulator_en_cal: 1; + }; + volatile uint32_t val; + } hp_regulator_cfg; + + union { + struct { + volatile uint32_t en_cali_pmu_cntl : 1;//new + uint32_t reserved0 : 10; + volatile uint32_t last_st : 7; + volatile uint32_t target_st : 7; + volatile uint32_t current_st: 7; + }; + volatile uint32_t val; + } main_state; + + union { + struct { + uint32_t reserved0: 13; + volatile uint32_t backup_st: 5; + volatile uint32_t lp_pwr_st: 5; + volatile uint32_t hp_pwr_st: 9; + }; + volatile uint32_t val; + } pwr_state; + + union { + struct { + // uint32_t stable_xpd_bbpll : 1; + volatile uint32_t stable_xpd_bbpll : 3;//new + volatile uint32_t stable_xpd_xtal : 1; + volatile uint32_t ana_xpd_pll_i2c : 3; + volatile uint32_t reserved0 : 3; + volatile uint32_t sysclk_slp_sel : 1; + volatile uint32_t sysclk_sel : 2; + volatile uint32_t sysclk_nodiv : 1; + volatile uint32_t icg_sysclk_en : 1; + volatile uint32_t icg_modem_switch : 1; + volatile uint32_t icg_modem_code : 2; + volatile uint32_t icg_slp_sel : 1; + volatile uint32_t icg_global_xtal : 1; + volatile uint32_t icg_global_pll : 4; + volatile uint32_t ana_i2c_iso_en : 1; + volatile uint32_t ana_i2c_retention: 1; + volatile uint32_t reserved1 : 1; + // uint32_t ana_xpd_bb_i2c : 1; + // uint32_t ana_xpd_bbpll_i2c: 1; + // uint32_t ana_xpd_bbpll : 1; + volatile uint32_t ana_xpd_pll : 4;//new + volatile uint32_t ana_xpd_xtal : 1; + }; + volatile uint32_t val; + } clk_state0; + + volatile uint32_t clk_state1; + volatile uint32_t clk_state2; + volatile pmu_ext_ldo_info_t ext_ldo[6]; - volatile pmu_ext_wakeup_lv_reg_t ext_wakeup_lv; - volatile pmu_ext_wakeup_sel_reg_t ext_wakeup_sel; - volatile pmu_ext_wakeup_st_reg_t ext_wakeup_st; - volatile pmu_ext_wakeup_cntl_reg_t ext_wakeup_cntl; - volatile pmu_sdio_wakeup_cntl_reg_t sdio_wakeup_cntl; - volatile pmu_xtal_slp_reg_t xtal_slp; - volatile pmu_cpu_sw_stall_reg_t cpu_sw_stall; - volatile pmu_dcm_ctrl_reg_t dcm_ctrl; - volatile pmu_dcm_wait_delay_reg_t dcm_wait_delay; - volatile pmu_vddbat_cfg_reg_t vddbat_cfg; - volatile pmu_touch_pwr_cntl_reg_t touch_pwr_cntl; - volatile pmu_rdn_eco_reg_t rdn_eco; - uint32_t reserved_218[121]; - volatile pmu_date_reg_t date; + + volatile uint32_t ext_wakeup_lv; + volatile uint32_t ext_wakeup_sel; + volatile uint32_t ext_wakeup_st; + union { + struct { + uint32_t reserved0 : 30; + volatile uint32_t status_clr : 1; + volatile uint32_t filter : 1; + }; + volatile uint32_t val; + } ext_wakeup_cntl; + + union { + struct { + volatile uint32_t act_dnum : 10; + uint32_t reserved0 : 22; + }; + volatile uint32_t val; + } sdio_wakeup_cntl; + + union { + struct { + uint32_t reserved0 : 16; + volatile uint32_t cnt_target : 16; + }; + volatile uint32_t val; + } xtal_slp; + + union { + struct { + uint32_t reserved0 : 16; + volatile uint32_t hpcore1_stall_code : 8; + volatile uint32_t hpcore0_stall_code : 8; + }; + volatile uint32_t val; + } cpu_sw_stall; + + volatile pmu_dcm_ctrl_reg_t dcm_ctrl; //new + volatile pmu_dcm_wait_delay_t dcm_delay;//new + volatile pmu_vddbat_cfg_t vbat_cfg;//new + volatile pmu_touch_sensor_pwr_cntl_t touch_pwr_cntl;//new + + union { + struct { + volatile uint32_t eco_result:1; + uint32_t reserved0 : 30; + volatile uint32_t eco_en: 1; + + }; + volatile uint32_t val; + } pmu_rdn_eco; + + + uint32_t reserved[121]; + + union { + struct { + volatile uint32_t pmu_date: 31; + volatile uint32_t clk_en : 1; + }; + volatile uint32_t val; + } date; } pmu_dev_t; extern pmu_dev_t PMU; #ifndef __cplusplus _Static_assert(sizeof(pmu_dev_t) == 0x400, "Invalid size of pmu_dev_t structure"); + +_Static_assert(offsetof(pmu_dev_t, reserved) == (PMU_RDN_ECO_REG - DR_REG_PMU_BASE) + 4, "Invalid size of pmu_dev_t structure"); #endif #ifdef __cplusplus diff --git a/components/soc/esp32p4/include/soc/reg_base.h b/components/soc/esp32p4/include/soc/reg_base.h index 91c0aa55fe0a..350906bcdeb7 100644 --- a/components/soc/esp32p4/include/soc/reg_base.h +++ b/components/soc/esp32p4/include/soc/reg_base.h @@ -124,7 +124,7 @@ #define DR_REG_LP_SYS_BASE (DR_REG_LPAON_BASE + 0x0) #define DR_REG_LP_CLKRST_BASE (DR_REG_LPAON_BASE + 0x1000) #define DR_REG_LP_TIMER_BASE (DR_REG_LPAON_BASE + 0x2000) -#define DR_REG_LP_ANAPERI_BASE (DR_REG_LPAON_BASE + 0x3000) +#define DR_REG_LP_ANALOG_PERI_BASE (DR_REG_LPAON_BASE + 0x3000) #define DR_REG_LP_HUK_BASE (DR_REG_LPAON_BASE + 0x4000) #define DR_REG_HUK_BASE (DR_REG_LP_HUK_BASE) #define DR_REG_PMU_BASE (DR_REG_LPAON_BASE + 0x5000) @@ -202,9 +202,6 @@ //TODO: IDF-7531 // #define DR_REG_PAU_BASE 0x60093000 -// #define DR_REG_LP_ANALOG_PERI_BASE 0x600B2C00 -// #define DR_REG_LP_I2C_ANA_MST_BASE 0x600B2400 -// #define DR_REG_LP_AON_BASE 0x600B1000 //TODO: IDF-7688 // #define DR_REG_TRACE_BASE 0x600C0000 diff --git a/components/soc/esp32p4/include/soc/regi2c_bbpll.h b/components/soc/esp32p4/include/soc/regi2c_bbpll.h deleted file mode 100644 index 235bca28dd27..000000000000 --- a/components/soc/esp32p4/include/soc/regi2c_bbpll.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#pragma once - -/** - * @file regi2c_bbpll.h - * @brief Register definitions for digital PLL (BBPLL) - * - * This file lists register fields of BBPLL, located on an internal configuration - * bus. These definitions are used via macros defined in regi2c_ctrl.h, by - * rtc_clk_cpu_freq_set function in rtc_clk.c. - */ diff --git a/components/soc/esp32p4/include/soc/regi2c_bias.h b/components/soc/esp32p4/include/soc/regi2c_bias.h index c3abe087e88f..cf983590749d 100644 --- a/components/soc/esp32p4/include/soc/regi2c_bias.h +++ b/components/soc/esp32p4/include/soc/regi2c_bias.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,5 +11,24 @@ * @brief Register definitions for bias * * This file lists register fields of BIAS. These definitions are used via macros defined in regi2c_ctrl.h, by - * bootloader_hardware_init function in bootloader_esp32c6.c. + * rtc_clk_init function in esp32p4/rtc_clk_init.c. */ + +#define I2C_BIAS 0x6A +#define I2C_BIAS_HOSTID 0 + +#define I2C_BIAS_OR_FORCE_XPD_CK 4 +#define I2C_BIAS_OR_FORCE_XPD_CK_MSB 0 +#define I2C_BIAS_OR_FORCE_XPD_CK_LSB 0 + +#define I2C_BIAS_OR_FORCE_XPD_REF_OUT_BUF 4 +#define I2C_BIAS_OR_FORCE_XPD_REF_OUT_BUF_MSB 1 +#define I2C_BIAS_OR_FORCE_XPD_REF_OUT_BUF_LSB 1 + +#define I2C_BIAS_OR_FORCE_XPD_IPH 4 +#define I2C_BIAS_OR_FORCE_XPD_IPH_MSB 2 +#define I2C_BIAS_OR_FORCE_XPD_IPH_LSB 2 + +#define I2C_BIAS_OR_FORCE_XPD_VGATE_BUF 4 +#define I2C_BIAS_OR_FORCE_XPD_VGATE_BUF_MSB 3 +#define I2C_BIAS_OR_FORCE_XPD_VGATE_BUF_LSB 3 diff --git a/components/soc/esp32p4/include/soc/regi2c_cpll.h b/components/soc/esp32p4/include/soc/regi2c_cpll.h new file mode 100644 index 000000000000..8f7f7f98797d --- /dev/null +++ b/components/soc/esp32p4/include/soc/regi2c_cpll.h @@ -0,0 +1,139 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +/** + * @file regi2c_cpll.h + * @brief Register definitions for CPU_PLL (CPLL) + * + * This file lists register fields of CPLL, located on an internal configuration + * bus. These definitions are used via macros defined in regi2c_ctrl.h, by + * rtc_clk_cpu_freq_set function in rtc_clk.c. + */ + +#define I2C_CPLL 0x67 +#define I2C_CPLL_HOSTID 0 + +#define I2C_CPLL_IR_CAL_DELAY 0 +#define I2C_CPLL_IR_CAL_DELAY_MSB 3 +#define I2C_CPLL_IR_CAL_DELAY_LSB 0 + +#define I2C_CPLL_IR_CAL_CK_DIV 0 +#define I2C_CPLL_IR_CAL_CK_DIV_MSB 7 +#define I2C_CPLL_IR_CAL_CK_DIV_LSB 4 + +#define I2C_CPLL_IR_CAL_EXT_CAP 1 +#define I2C_CPLL_IR_CAL_EXT_CAP_MSB 3 +#define I2C_CPLL_IR_CAL_EXT_CAP_LSB 0 + +#define I2C_CPLL_IR_CAL_ENX_CAP 1 +#define I2C_CPLL_IR_CAL_ENX_CAP_MSB 4 +#define I2C_CPLL_IR_CAL_ENX_CAP_LSB 4 + +#define I2C_CPLL_IR_CAL_RSTB 1 +#define I2C_CPLL_IR_CAL_RSTB_MSB 5 +#define I2C_CPLL_IR_CAL_RSTB_LSB 5 + +#define I2C_CPLL_IR_CAL_START 1 +#define I2C_CPLL_IR_CAL_START_MSB 6 +#define I2C_CPLL_IR_CAL_START_LSB 6 + +#define I2C_CPLL_IR_CAL_UNSTOP 1 +#define I2C_CPLL_IR_CAL_UNSTOP_MSB 7 +#define I2C_CPLL_IR_CAL_UNSTOP_LSB 7 + +#define I2C_CPLL_OC_REF_DIV 2 +#define I2C_CPLL_OC_REF_DIV_MSB 3 +#define I2C_CPLL_OC_REF_DIV_LSB 0 + +#define I2C_CPLL_OC_DCHGP 2 +#define I2C_CPLL_OC_DCHGP_MSB 6 +#define I2C_CPLL_OC_DCHGP_LSB 4 + +#define I2C_CPLL_OC_ENB_FCAL 2 +#define I2C_CPLL_OC_ENB_FCAL_MSB 7 +#define I2C_CPLL_OC_ENB_FCAL_LSB 7 + +#define I2C_CPLL_OC_DIV_7_0 3 +#define I2C_CPLL_OC_DIV_7_0_MSB 7 +#define I2C_CPLL_OC_DIV_7_0_LSB 0 + +#define I2C_CPLL_MODE_HF 4 +#define I2C_CPLL_MODE_HF_MSB 1 +#define I2C_CPLL_MODE_HF_LSB 1 + +#define I2C_CPLL_DIV_CPU 4 +#define I2C_CPLL_DIV_CPU_MSB 5 +#define I2C_CPLL_DIV_CPU_LSB 5 + +#define I2C_CPLL_OC_ENB_VCON 4 +#define I2C_CPLL_OC_ENB_VCON_MSB 6 +#define I2C_CPLL_OC_ENB_VCON_LSB 6 + +#define I2C_CPLL_OC_TSCHGP 4 +#define I2C_CPLL_OC_TSCHGP_MSB 7 +#define I2C_CPLL_OC_TSCHGP_LSB 7 + +#define I2C_CPLL_OC_DR1 5 +#define I2C_CPLL_OC_DR1_MSB 2 +#define I2C_CPLL_OC_DR1_LSB 0 + +#define I2C_CPLL_OC_DR3 5 +#define I2C_CPLL_OC_DR3_MSB 6 +#define I2C_CPLL_OC_DR3_LSB 4 + +#define I2C_CPLL_EN_USB 5 +#define I2C_CPLL_EN_USB_MSB 7 +#define I2C_CPLL_EN_USB_LSB 7 + +#define I2C_CPLL_OC_DCUR 6 +#define I2C_CPLL_OC_DCUR_MSB 2 +#define I2C_CPLL_OC_DCUR_LSB 0 + +#define I2C_CPLL_INC_CUR 6 +#define I2C_CPLL_INC_CUR_MSB 3 +#define I2C_CPLL_INC_CUR_LSB 3 + +#define I2C_CPLL_OC_DHREF_SEL 6 +#define I2C_CPLL_OC_DHREF_SEL_MSB 5 +#define I2C_CPLL_OC_DHREF_SEL_LSB 4 + +#define I2C_CPLL_OC_DLREF_SEL 6 +#define I2C_CPLL_OC_DLREF_SEL_MSB 7 +#define I2C_CPLL_OC_DLREF_SEL_LSB 6 + +#define I2C_CPLL_OR_CAL_CAP 8 +#define I2C_CPLL_OR_CAL_CAP_MSB 3 +#define I2C_CPLL_OR_CAL_CAP_LSB 0 + +#define I2C_CPLL_OR_CAL_UDF 8 +#define I2C_CPLL_OR_CAL_UDF_MSB 4 +#define I2C_CPLL_OR_CAL_UDF_LSB 4 + +#define I2C_CPLL_OR_CAL_OVF 8 +#define I2C_CPLL_OR_CAL_OVF_MSB 5 +#define I2C_CPLL_OR_CAL_OVF_LSB 5 + +#define I2C_CPLL_OR_CAL_END 8 +#define I2C_CPLL_OR_CAL_END_MSB 6 +#define I2C_CPLL_OR_CAL_END_LSB 6 + +#define I2C_CPLL_OR_LOCK 8 +#define I2C_CPLL_OR_LOCK_MSB 7 +#define I2C_CPLL_OR_LOCK_LSB 7 + +#define I2C_CPLL_OC_VCO_DBIAS 9 +#define I2C_CPLL_OC_VCO_DBIAS_MSB 1 +#define I2C_CPLL_OC_VCO_DBIAS_LSB 0 + +#define I2C_CPLL_ENT_PLL 10 +#define I2C_CPLL_ENT_PLL_MSB 3 +#define I2C_CPLL_ENT_PLL_LSB 3 + +#define I2C_CPLL_DTEST 10 +#define I2C_CPLL_DTEST_MSB 5 +#define I2C_CPLL_DTEST_LSB 4 diff --git a/components/soc/esp32p4/include/soc/regi2c_defs.h b/components/soc/esp32p4/include/soc/regi2c_defs.h index 922655c05aa5..583beb13c473 100644 --- a/components/soc/esp32p4/include/soc/regi2c_defs.h +++ b/components/soc/esp32p4/include/soc/regi2c_defs.h @@ -1,27 +1,17 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #pragma once - #include "esp_bit_defs.h" /* Analog function control register */ -#define I2C_MST_ANA_CONF0_REG 0x600AF818 -#define I2C_MST_BBPLL_STOP_FORCE_HIGH (BIT(2)) -#define I2C_MST_BBPLL_STOP_FORCE_LOW (BIT(3)) -#define I2C_MST_BBPLL_CAL_DONE (BIT(24)) - - - #define ANA_CONFIG_REG 0x5012401C -#define ANA_CONFIG_S (8) #define ANA_CONFIG_M (0x3FF) #define ANA_I2C_SAR_FORCE_PD BIT(18) -#define ANA_I2C_BBPLL_M BIT(17) /* Clear to enable BBPLL */ #define ANA_CONFIG2_REG 0x50124020 diff --git a/components/soc/esp32p4/include/soc/regi2c_dig_reg.h b/components/soc/esp32p4/include/soc/regi2c_dig_reg.h index 8b277dfcd620..aca6b3e77817 100644 --- a/components/soc/esp32p4/include/soc/regi2c_dig_reg.h +++ b/components/soc/esp32p4/include/soc/regi2c_dig_reg.h @@ -15,50 +15,58 @@ #define I2C_DIG_REG 0x6D #define I2C_DIG_REG_HOSTID 0 -#define I2C_DIG_REG_EXT_RTC_DREG 4 +#define I2C_DIG_REG_EXT_RTC_DREG 4 #define I2C_DIG_REG_EXT_RTC_DREG_MSB 4 #define I2C_DIG_REG_EXT_RTC_DREG_LSB 0 -#define I2C_DIG_REG_ENX_RTC_DREG 4 +#define I2C_DIG_REG_ENX_RTC_DREG 4 #define I2C_DIG_REG_ENX_RTC_DREG_MSB 7 #define I2C_DIG_REG_ENX_RTC_DREG_LSB 7 -#define I2C_DIG_REG_EXT_RTC_DREG_SLEEP 5 -#define I2C_DIG_REG_EXT_RTC_DREG_SLEEP_MSB 4 -#define I2C_DIG_REG_EXT_RTC_DREG_SLEEP_LSB 0 +#define I2C_DIG_REG_EXT_RTC_DREG_SLEEP 5 +#define I2C_DIG_REG_EXT_RTC_DREG_SLEEP_MSB 4 +#define I2C_DIG_REG_EXT_RTC_DREG_SLEEP_LSB 0 -#define I2C_DIG_REG_ENIF_RTC_DREG 5 -#define I2C_DIG_REG_ENIF_RTC_DREG_MSB 7 -#define I2C_DIG_REG_ENIF_RTC_DREG_LSB 7 +#define I2C_DIG_REG_ENX_RTC_DREG_SLEEP 5 +#define I2C_DIG_REG_ENX_RTC_DREG_SLEEP_MSB 7 +#define I2C_DIG_REG_ENX_RTC_DREG_SLEEP_LSB 7 -#define I2C_DIG_REG_EXT_DIG_DREG 6 +#define I2C_DIG_REG_EXT_DIG_DREG 6 #define I2C_DIG_REG_EXT_DIG_DREG_MSB 4 #define I2C_DIG_REG_EXT_DIG_DREG_LSB 0 -#define I2C_DIG_REG_ENX_DIG_DREG 6 +#define I2C_DIG_REG_ENX_DIG_DREG 6 #define I2C_DIG_REG_ENX_DIG_DREG_MSB 7 #define I2C_DIG_REG_ENX_DIG_DREG_LSB 7 -#define I2C_DIG_REG_EXT_DIG_DREG_SLEEP 7 -#define I2C_DIG_REG_EXT_DIG_DREG_SLEEP_MSB 4 -#define I2C_DIG_REG_EXT_DIG_DREG_SLEEP_LSB 0 +#define I2C_DIG_REG_EXT_DIG_DREG_SLEEP 7 +#define I2C_DIG_REG_EXT_DIG_DREG_SLEEP_MSB 4 +#define I2C_DIG_REG_EXT_DIG_DREG_SLEEP_LSB 0 -#define I2C_DIG_REG_ENIF_DIG_DREG 7 -#define I2C_DIG_REG_ENIF_DIG_DREG_MSB 7 -#define I2C_DIG_REG_ENIF_DIG_DREG_LSB 7 +#define I2C_DIG_REG_ENX_DIG_DREG_SLEEP 7 +#define I2C_DIG_REG_ENX_DIG_DREG_SLEEP 7 +#define I2C_DIG_REG_ENX_DIG_DREG_SLEEP 7 -#define I2C_DIG_REG_OR_EN_CONT_CAL 9 -#define I2C_DIG_REG_OR_EN_CONT_CAL_MSB 7 -#define I2C_DIG_REG_OR_EN_CONT_CAL_LSB 7 +#define I2C_DIG_REG_OR_EN_CONT_CAL 9 +#define I2C_DIG_REG_OR_EN_CONT_CAL_MSB 7 +#define I2C_DIG_REG_OR_EN_CONT_CAL_LSB 7 -#define I2C_DIG_REG_XPD_RTC_REG 13 +#define I2C_DIG_REG_FORCE_RTC_DREG 10 +#define I2C_DIG_REG_FORCE_RTC_DREG_MSB 0 +#define I2C_DIG_REG_FORCE_RTC_DREG_LSB 0 + +#define I2C_DIG_REG_FORCE_DIG_DREG 10 +#define I2C_DIG_REG_FORCE_DIG_DREG_MSB 1 +#define I2C_DIG_REG_FORCE_DIG_DREG_LSB 1 + +#define I2C_DIG_REG_XPD_RTC_REG 13 #define I2C_DIG_REG_XPD_RTC_REG_MSB 2 #define I2C_DIG_REG_XPD_RTC_REG_LSB 2 -#define I2C_DIG_REG_XPD_DIG_REG 13 +#define I2C_DIG_REG_XPD_DIG_REG 13 #define I2C_DIG_REG_XPD_DIG_REG_MSB 3 #define I2C_DIG_REG_XPD_DIG_REG_LSB 3 -#define I2C_DIG_REG_SCK_DCAP 14 +#define I2C_DIG_REG_SCK_DCAP 14 #define I2C_DIG_REG_SCK_DCAP_MSB 7 #define I2C_DIG_REG_SCK_DCAP_LSB 0 diff --git a/components/soc/esp32p4/include/soc/regi2c_syspll.h b/components/soc/esp32p4/include/soc/regi2c_syspll.h new file mode 100644 index 000000000000..862ec7da98a9 --- /dev/null +++ b/components/soc/esp32p4/include/soc/regi2c_syspll.h @@ -0,0 +1,138 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +/** + * @file regi2c_syspll.h + * @brief Register definitions for SYS PLL (SPLL) + * + * This file lists register fields of SPLL, located on an internal configuration + * bus. These definitions are used via macros defined in regi2c_ctrl.h. + */ + +#define I2C_SYSPLL 0x66 +#define I2C_SYSPLL_HOSTID 0 + +#define I2C_SYSPLL_IR_CAL_DELAY 0 +#define I2C_SYSPLL_IR_CAL_DELAY_MSB 3 +#define I2C_SYSPLL_IR_CAL_DELAY_LSB 0 + +#define I2C_SYSPLL_IR_CAL_CK_DIV 0 +#define I2C_SYSPLL_IR_CAL_CK_DIV_MSB 7 +#define I2C_SYSPLL_IR_CAL_CK_DIV_LSB 4 + +#define I2C_SYSPLL_IR_CAL_EXT_CAP 1 +#define I2C_SYSPLL_IR_CAL_EXT_CAP_MSB 3 +#define I2C_SYSPLL_IR_CAL_EXT_CAP_LSB 0 + +#define I2C_SYSPLL_IR_CAL_ENX_CAP 1 +#define I2C_SYSPLL_IR_CAL_ENX_CAP_MSB 4 +#define I2C_SYSPLL_IR_CAL_ENX_CAP_LSB 4 + +#define I2C_SYSPLL_IR_CAL_RSTB 1 +#define I2C_SYSPLL_IR_CAL_RSTB_MSB 5 +#define I2C_SYSPLL_IR_CAL_RSTB_LSB 5 + +#define I2C_SYSPLL_IR_CAL_START 1 +#define I2C_SYSPLL_IR_CAL_START_MSB 6 +#define I2C_SYSPLL_IR_CAL_START_LSB 6 + +#define I2C_SYSPLL_IR_CAL_UNSTOP 1 +#define I2C_SYSPLL_IR_CAL_UNSTOP_MSB 7 +#define I2C_SYSPLL_IR_CAL_UNSTOP_LSB 7 + +#define I2C_SYSPLL_OC_REF_DIV 2 +#define I2C_SYSPLL_OC_REF_DIV_MSB 3 +#define I2C_SYSPLL_OC_REF_DIV_LSB 0 + +#define I2C_SYSPLL_OC_DCHGP 2 +#define I2C_SYSPLL_OC_DCHGP_MSB 6 +#define I2C_SYSPLL_OC_DCHGP_LSB 4 + +#define I2C_SYSPLL_OC_ENB_FCAL 2 +#define I2C_SYSPLL_OC_ENB_FCAL_MSB 7 +#define I2C_SYSPLL_OC_ENB_FCAL_LSB 7 + +#define I2C_SYSPLL_OC_DIV_7_0 3 +#define I2C_SYSPLL_OC_DIV_7_0_MSB 7 +#define I2C_SYSPLL_OC_DIV_7_0_LSB 0 + +#define I2C_SYSPLL_MODE_HF 4 +#define I2C_SYSPLL_MODE_HF_MSB 1 +#define I2C_SYSPLL_MODE_HF_LSB 1 + +#define I2C_SYSPLL_DIV_CPU 4 +#define I2C_SYSPLL_DIV_CPU_MSB 5 +#define I2C_SYSPLL_DIV_CPU_LSB 5 + +#define I2C_SYSPLL_OC_ENB_VCON 4 +#define I2C_SYSPLL_OC_ENB_VCON_MSB 6 +#define I2C_SYSPLL_OC_ENB_VCON_LSB 6 + +#define I2C_SYSPLL_OC_TSCHGP 4 +#define I2C_SYSPLL_OC_TSCHGP_MSB 7 +#define I2C_SYSPLL_OC_TSCHGP_LSB 7 + +#define I2C_SYSPLL_OC_DR1 5 +#define I2C_SYSPLL_OC_DR1_MSB 2 +#define I2C_SYSPLL_OC_DR1_LSB 0 + +#define I2C_SYSPLL_OC_DR3 5 +#define I2C_SYSPLL_OC_DR3_MSB 6 +#define I2C_SYSPLL_OC_DR3_LSB 4 + +#define I2C_SYSPLL_EN_USB 5 +#define I2C_SYSPLL_EN_USB_MSB 7 +#define I2C_SYSPLL_EN_USB_LSB 7 + +#define I2C_SYSPLL_OC_DCUR 6 +#define I2C_SYSPLL_OC_DCUR_MSB 2 +#define I2C_SYSPLL_OC_DCUR_LSB 0 + +#define I2C_SYSPLL_INC_CUR 6 +#define I2C_SYSPLL_INC_CUR_MSB 3 +#define I2C_SYSPLL_INC_CUR_LSB 3 + +#define I2C_SYSPLL_OC_DHREF_SEL 6 +#define I2C_SYSPLL_OC_DHREF_SEL_MSB 5 +#define I2C_SYSPLL_OC_DHREF_SEL_LSB 4 + +#define I2C_SYSPLL_OC_DLREF_SEL 6 +#define I2C_SYSPLL_OC_DLREF_SEL_MSB 7 +#define I2C_SYSPLL_OC_DLREF_SEL_LSB 6 + +#define I2C_SYSPLL_OR_CAL_CAP 8 +#define I2C_SYSPLL_OR_CAL_CAP_MSB 3 +#define I2C_SYSPLL_OR_CAL_CAP_LSB 0 + +#define I2C_SYSPLL_OR_CAL_UDF 8 +#define I2C_SYSPLL_OR_CAL_UDF_MSB 4 +#define I2C_SYSPLL_OR_CAL_UDF_LSB 4 + +#define I2C_SYSPLL_OR_CAL_OVF 8 +#define I2C_SYSPLL_OR_CAL_OVF_MSB 5 +#define I2C_SYSPLL_OR_CAL_OVF_LSB 5 + +#define I2C_SYSPLL_OR_CAL_END 8 +#define I2C_SYSPLL_OR_CAL_END_MSB 6 +#define I2C_SYSPLL_OR_CAL_END_LSB 6 + +#define I2C_SYSPLL_OR_LOCK 8 +#define I2C_SYSPLL_OR_LOCK_MSB 7 +#define I2C_SYSPLL_OR_LOCK_LSB 7 + +#define I2C_SYSPLL_OC_VCO_DBIAS 9 +#define I2C_SYSPLL_OC_VCO_DBIAS_MSB 1 +#define I2C_SYSPLL_OC_VCO_DBIAS_LSB 0 + +#define I2C_SYSPLL_ENT_PLL 10 +#define I2C_SYSPLL_ENT_PLL_MSB 3 +#define I2C_SYSPLL_ENT_PLL_LSB 3 + +#define I2C_SYSPLL_DTEST 10 +#define I2C_SYSPLL_DTEST_MSB 5 +#define I2C_SYSPLL_DTEST_LSB 4 diff --git a/components/soc/esp32p4/include/soc/rtc.h b/components/soc/esp32p4/include/soc/rtc.h index f81d22c20564..02c39be652a4 100644 --- a/components/soc/esp32p4/include/soc/rtc.h +++ b/components/soc/esp32p4/include/soc/rtc.h @@ -10,6 +10,7 @@ #include #include "soc/soc.h" #include "soc/clk_tree_defs.h" +#include "hal/hal_utils.h" // TODO: IDF-8941 Move rtc.h to esp_hw_support, so that dependency is correct #ifdef __cplusplus extern "C" { @@ -44,10 +45,6 @@ extern "C" { #define MHZ (1000000) -#define RTC_SLOW_CLK_150K_CAL_TIMEOUT_THRES(cycles) (cycles << 10) -#define RTC_SLOW_CLK_32K_CAL_TIMEOUT_THRES(cycles) (cycles << 12) -#define RTC_FAST_CLK_20M_CAL_TIMEOUT_THRES(cycles) (TIMG_RTC_CALI_TIMEOUT_THRES_V) // Just use the max timeout thres value - #define OTHER_BLOCKS_POWERUP 1 #define OTHER_BLOCKS_WAIT 1 @@ -74,6 +71,8 @@ extern "C" { #define SOC_DELAY_RC_FAST_ENABLE 50 #define SOC_DELAY_RC_FAST_DIGI_SWITCH 5 #define SOC_DELAY_RC32K_ENABLE 300 +#define SOC_DELAY_LP_PLL_SWITCH 3 +#define SOC_DELAY_LP_PLL_ENABLE 50 /* Core voltage: // TODO: IDF-7528, TODO: IDF-7529 * Currently, ESP32C6 never adjust its wake voltage in runtime @@ -141,7 +140,7 @@ typedef enum { typedef struct rtc_cpu_freq_config_s { soc_cpu_clk_src_t source; //!< The clock from which CPU clock is derived uint32_t source_freq_mhz; //!< Source clock frequency - uint32_t div; //!< Divider, freq_mhz = SOC_ROOT_CLK freq_mhz / div + hal_utils_clk_div_t div; //!< Divider, freq_mhz = SOC_ROOT_CLK freq_mhz / div uint32_t freq_mhz; //!< CPU clock frequency } rtc_cpu_freq_config_t; @@ -153,17 +152,23 @@ typedef struct rtc_cpu_freq_config_s { /** * @brief Clock source to be calibrated using rtc_clk_cal function * - * @note On previous targets, the enum values somehow reflects the register field values of TIMG_RTC_CALI_CLK_SEL - * However, this is not true on ESP32C6. The conversion to register field values is explicitly done in - * rtc_clk_cal_internal + * @note On ESP32P4, the enum values somehow reflects the register field values of HP_SYS_CLKRST_REG_TIMERGRP0_TGRT_CLK_SRC_SEL. */ typedef enum { - RTC_CAL_RTC_MUX = -1, //!< Currently selected RTC_SLOW_CLK - RTC_CAL_RC_SLOW = SOC_RTC_SLOW_CLK_SRC_RC_SLOW, //!< Internal 150kHz RC oscillator - RTC_CAL_RC32K = SOC_RTC_SLOW_CLK_SRC_RC32K, //!< Internal 32kHz RC oscillator, as one type of 32k clock - RTC_CAL_32K_XTAL = SOC_RTC_SLOW_CLK_SRC_XTAL32K, //!< External 32kHz XTAL, as one type of 32k clock - RTC_CAL_32K_OSC_SLOW = SOC_RTC_SLOW_CLK_SRC_OSC_SLOW, //!< External slow clock signal input by lp_pad_gpio0, as one type of 32k clock - RTC_CAL_RC_FAST //!< Internal 20MHz RC oscillator + RTC_CAL_RTC_MUX = -1, //!< Currently selected RTC_SLOW_CLK + RTC_CAL_MPLL = 0, //!< 500MHz MSPI_PLL_CLK + RTC_CAL_SPLL = 1, //!< 480MHz SYS_PLL_CLK + RTC_CAL_CPLL = 2, //!< 400MHz CPU_PLL_CLK + RTC_CAL_APLL = 3, //!< AUDIO_PLL_CLK + RTC_CAL_SDIO_PLL0 = 4, //!< SDIO_PLL0_CLK + RTC_CAL_SDIO_PLL1 = 5, //!< SDIO_PLL1_CLK + RTC_CAL_SDIO_PLL2 = 6, //!< SDIO_PLL2_CLK + RTC_CAL_RC_FAST = 7, //!< Internal 20MHz RC oscillator + RTC_CAL_RC_SLOW = 8, //!< Internal 150kHz RC oscillator + RTC_CAL_RC32K = 9, //!< Internal 32kHz RC oscillator, as one type of 32k clock + RTC_CAL_32K_XTAL = 10, //!< External 32kHz XTAL, as one type of 32k clock + RTC_CAL_LP_PLL = 11, //!< 8MHz LP_PLL_CLK + RTC_CAL_INVALID_CLK, //!< Clock not available to calibrate } rtc_cal_sel_t; /** @@ -186,7 +191,7 @@ typedef struct { */ #define RTC_CLK_CONFIG_DEFAULT() { \ .xtal_freq = CONFIG_XTAL_FREQ, \ - .cpu_freq_mhz = 80, \ + .cpu_freq_mhz = 90, \ .fast_clk_src = SOC_RTC_FAST_CLK_SRC_RC_FAST, \ .slow_clk_src = SOC_RTC_SLOW_CLK_SRC_RC_SLOW, \ .clk_rtc_clk_div = 0, \ @@ -229,11 +234,6 @@ void rtc_clk_xtal_freq_update(rtc_xtal_freq_t xtal_freq); */ void rtc_clk_32k_enable(bool en); -/** - * @brief Configure 32 kHz XTAL oscillator to accept external clock signal - */ -void rtc_clk_32k_enable_external(void); - /** * @brief Get the state of 32k XTAL oscillator * @return true if 32k XTAL oscillator has been enabled @@ -289,7 +289,6 @@ soc_rtc_slow_clk_src_t rtc_clk_slow_src_get(void); * - if SOC_RTC_SLOW_CLK_SRC_RC_SLOW is selected, returns 136000 * - if SOC_RTC_SLOW_CLK_SRC_XTAL32K is selected, returns 32768 * - if SOC_RTC_SLOW_CLK_SRC_RC32K is selected, returns 32768 - * - if SOC_RTC_SLOW_CLK_SRC_OSC_SLOW is selected, returns 32768 * * rtc_clk_cal function can be used to get more precise value by comparing * RTC_SLOW_CLK frequency to the frequency of main XTAL. @@ -525,43 +524,6 @@ uint32_t rtc_clk_apll_coeff_calc(uint32_t freq, uint32_t *_o_div, uint32_t *_sdm */ void rtc_clk_apll_coeff_set(uint32_t o_div, uint32_t sdm0, uint32_t sdm1, uint32_t sdm2); -// -------------------------- CLOCK TREE DEFS ALIAS ---------------------------- -// **WARNING**: The following are only for backwards compatibility. -// Please use the declarations in soc/clk_tree_defs.h instead. -/** - * @brief CPU clock source - */ -typedef soc_cpu_clk_src_t rtc_cpu_freq_src_t; -#define RTC_CPU_FREQ_SRC_XTAL SOC_CPU_CLK_SRC_XTAL //!< XTAL -#define RTC_CPU_FREQ_SRC_PLL SOC_CPU_CLK_SRC_PLL //!< PLL (480M) -#define RTC_CPU_FREQ_SRC_8M SOC_CPU_CLK_SRC_RC_FAST //!< Internal 17.5M RTC oscillator - -/** - * @brief RTC SLOW_CLK frequency values - */ -typedef soc_rtc_slow_clk_src_t rtc_slow_freq_t; -#define RTC_SLOW_FREQ_RTC SOC_RTC_SLOW_CLK_SRC_RC_SLOW //!< Internal 150 kHz RC oscillator -#define RTC_SLOW_FREQ_32K_XTAL SOC_RTC_SLOW_CLK_SRC_XTAL32K //!< External 32 kHz XTAL - -/** - * @brief RTC FAST_CLK frequency values - */ -typedef soc_rtc_fast_clk_src_t rtc_fast_freq_t; -#define RTC_FAST_FREQ_XTALD4 SOC_RTC_FAST_CLK_SRC_XTAL_DIV //!< Main XTAL, divided by 2 -#define RTC_FAST_FREQ_8M SOC_RTC_FAST_CLK_SRC_RC_FAST //!< Internal 17.5 MHz RC oscillator - -/* Alias of frequency related macros */ -#define RTC_FAST_CLK_FREQ_APPROX SOC_CLK_RC_FAST_FREQ_APPROX -#define RTC_FAST_CLK_FREQ_8M SOC_CLK_RC_FAST_FREQ_APPROX -#define RTC_SLOW_CLK_FREQ_150K SOC_CLK_RC_SLOW_FREQ_APPROX -#define RTC_SLOW_CLK_FREQ_32K SOC_CLK_XTAL32K_FREQ_APPROX - -/* Alias of deprecated function names */ -#define rtc_clk_slow_freq_set(slow_freq) rtc_clk_slow_src_set(slow_freq) -#define rtc_clk_slow_freq_get() rtc_clk_slow_src_get() -#define rtc_clk_fast_freq_set(fast_freq) rtc_clk_fast_src_set(fast_freq) -#define rtc_clk_fast_freq_get() rtc_clk_fast_src_get() - #ifdef __cplusplus } #endif diff --git a/components/soc/esp32p4/include/soc/soc.h b/components/soc/esp32p4/include/soc/soc.h index 42a85f1f47ca..fb064f4bc88f 100644 --- a/components/soc/esp32p4/include/soc/soc.h +++ b/components/soc/esp32p4/include/soc/soc.h @@ -134,15 +134,11 @@ #endif /* !__ASSEMBLER__ */ //}} -//TODO: IDF-7526 //Periheral Clock {{ -#define APB_CLK_FREQ_ROM ( 40*1000000 ) -#define CPU_CLK_FREQ_ROM APB_CLK_FREQ_ROM -#define EFUSE_CLK_FREQ_ROM ( 20*1000000) -#define CPU_CLK_FREQ_MHZ_BTLD (80) // The cpu clock frequency (in MHz) to set at 2nd stage bootloader system clock configuration -#define CPU_CLK_FREQ APB_CLK_FREQ -#define APB_CLK_FREQ ( 40*1000000 ) -#define MODEM_REQUIRED_MIN_APB_CLK_FREQ ( 80*1000000 ) +#define APB_CLK_FREQ_ROM ( 10*1000000 ) +#define CPU_CLK_FREQ_ROM ( 40*1000000 ) +#define CPU_CLK_FREQ_MHZ_BTLD (90) // The cpu clock frequency (in MHz) to set at 2nd stage bootloader system clock configuration +#define APB_CLK_FREQ ( 90*1000000 ) #define REF_CLK_FREQ ( 1000000 ) #define XTAL_CLK_FREQ (40*1000000) #define GPIO_MATRIX_DELAY_NS 0 diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index 087f36f03fd2..6db49e7d8497 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -32,7 +32,7 @@ #define SOC_MCPWM_SUPPORTED 1 #define SOC_TWAI_SUPPORTED 1 #define SOC_ETM_SUPPORTED 1 -#define SOC_PARLIO_SUPPORTED 1 //TODO: IDF-7471 +// #define SOC_PARLIO_SUPPORTED 1 //TODO: IDF-7471 #define SOC_ASYNC_MEMCPY_SUPPORTED 1 // disable usb serial jtag for esp32p4, current image does not support // #define SOC_USB_SERIAL_JTAG_SUPPORTED 1 //TODO: IDF-7496 @@ -64,7 +64,7 @@ #define SOC_SECURE_BOOT_SUPPORTED 1 // #define SOC_BOD_SUPPORTED 1 //TODO: IDF-7519 // #define SOC_APM_SUPPORTED 1 //TODO: IDF-7542 -// #define SOC_PMU_SUPPORTED 1 //TODO: IDF-7531 +#define SOC_PMU_SUPPORTED 1 //TODO: IDF-7531 // #define SOC_PAU_SUPPORTED 1 //TODO: IDF-7531 #define SOC_LP_TIMER_SUPPORTED 1 // #define SOC_ULP_LP_UART_SUPPORTED 1 //TODO: IDF-7533 @@ -74,7 +74,7 @@ #define SOC_PSRAM_DMA_CAPABLE 1 // #define SOC_ULP_SUPPORTED 1 //TODO: IDF-7534 #define SOC_SDMMC_HOST_SUPPORTED 1 -// #define SOC_CLK_TREE_SUPPORTED 1 //TODO: IDF-7526 +#define SOC_CLK_TREE_SUPPORTED 1 // #define SOC_ASSIST_DEBUG_SUPPORTED 1 //TODO: IDF-7565 #define SOC_WDT_SUPPORTED 1 #define SOC_SPI_FLASH_SUPPORTED 1 @@ -258,7 +258,7 @@ #define SOC_I2S_NUM (3U) #define SOC_I2S_HW_VERSION_2 (1) #define SOC_I2S_SUPPORTS_XTAL (1) -#define SOC_I2S_SUPPORTS_APLL (1) +// #define SOC_I2S_SUPPORTS_APLL (1) // TODO: IDF-8884 #define SOC_I2S_SUPPORTS_PCM (1) #define SOC_I2S_SUPPORTS_PDM (1) #define SOC_I2S_SUPPORTS_PDM_TX (1) @@ -562,15 +562,16 @@ #define SOC_PSRAM_VDD_POWER_MPLL (1) /*-------------------------- CLOCK SUBSYSTEM CAPS ----------------------------------------*/ -#define SOC_CLK_RC_FAST_SUPPORT_CALIBRATION (0) +#define SOC_CLK_RC_FAST_SUPPORT_CALIBRATION (1) #define SOC_MODEM_CLOCK_IS_INDEPENDENT (0) -#define SOC_CLK_APLL_SUPPORTED (1) /*!< Support Audio PLL */ +// #define SOC_CLK_APLL_SUPPORTED (1) /*!< Support Audio PLL */ TODO: IDF-8884 #define SOC_CLK_MPLL_SUPPORTED (1) /*!< Support MSPI PLL */ #define SOC_CLK_XTAL32K_SUPPORTED (1) /*!< Support to connect an external low frequency crystal */ -#define SOC_CLK_OSC_SLOW_SUPPORTED (1) /*!< Support to connect an external oscillator, not a crystal */ #define SOC_CLK_RC32K_SUPPORTED (1) /*!< Support an internal 32kHz RC oscillator */ +#define SOC_CLK_LP_FAST_SUPPORT_LP_PLL (1) /*!< Support LP_PLL clock as the LP_FAST clock source */ + #define SOC_PERIPH_CLK_CTRL_SHARED (1) /*!< Peripheral clock control (e.g. set clock source) is shared between various peripherals */ /*-------------------------- Temperature Sensor CAPS -------------------------------------*/ diff --git a/components/soc/esp32p4/include/soc/usb_dwc_cfg.h b/components/soc/esp32p4/include/soc/usb_dwc_cfg.h new file mode 100644 index 000000000000..7d874e71c82e --- /dev/null +++ b/components/soc/esp32p4/include/soc/usb_dwc_cfg.h @@ -0,0 +1,105 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +/* +Configuration Set ID: 11 +*/ + +/* 3.1 Basic Config Parameters */ +#define OTG_MODE 0 +#define OTG_ARCHITECTURE 2 +#define OTG_SINGLE_POINT 0 +#define OTG_ENABLE_LPM 0 +#define OTG_EN_DED_TX_FIFO 1 +#define OTG_EN_DESC_DMA 1 +#define OTG_MULTI_PROC_INTRPT 1 + +/* 3.2 USB Physical Layer Interface Parameters */ +#define OTG_HSPHY_INTERFACE 3 +#define OTG_HSPHY_DWIDTH 2 +#define OTG_FSPHY_INTERFACE 2 +#define OTG_ENABLE_IC_USB 0 +#define OTG_ENABLE_HSIC 0 +#define OTG_I2C_INTERFACE 0 +#define OTG_ULPI_CARKIT 1 +#define OTG_ADP_SUPPORT 1 +#define OTG_BC_SUPPORT 0 +#define OTG_VENDOR_CTL_INTERFACE 1 + +/* 3.3 Device Endpoint Configuration Parameters */ +#define OTG_NUM_EPS 15 +#define OTG_NUM_IN_EPS 8 +#define OTG_NUM_CRL_EPS 1 + +/* 3.4 Host Endpoint Configuration Parameters */ +#define OTG_NUM_HOST_CHAN 16 +#define OTG_EN_PERIO_HOST 1 + +/* 3.5 Endpoint Channel FIFO Configuration Parameters */ +#define OTG_DFIFO_DEPTH 1024 +#define OTG_DFIFO_DYNAMIC 1 +#define OTG_RX_DFIFO_DEPTH 1024 +#define OTG_TX_HNPERIO_DFIFO_DEPTH 1024 +#define OTG_TX_HPERIO_DFIFO_DEPTH 1024 +#define OTG_NPERIO_TX_QUEUE_DEPTH 4 +#define OTG_PERIO_TX_QUEUE_DEPTH 4 + +/* 3.6 Additional Configuration Options Parameters */ +#define OTG_TRANS_COUNT_WIDTH 17 +#define OTG_PACKET_COUNT_WIDTH 8 +#define OTG_RM_OPT_FEATURES 1 +#define OTG_EN_PWROPT 1 +#define OTG_SYNC_RESET_TYPE 0 +#define OTG_EN_IDDIG_FILTER 1 +#define OTG_EN_VBUSVALID_FILTER 1 +#define OTG_EN_A_VALID_FILTER 1 +#define OTG_EN_B_VALID_FILTER 1 +#define OTG_EN_SESSIONEND_FILTER 1 +#define OTG_EXCP_CNTL_XFER_FLOW 1 +#define OTG_PWR_CLAMP 0 +#define OTG_PWR_SWITCH_POLARITY 0 + +/* 3.7 Endpoint Direction Parameters */ +#define OTG_EP_DIR_1 0 +#define OTG_EP_DIR_2 0 +#define OTG_EP_DIR_3 0 +#define OTG_EP_DIR_4 0 +#define OTG_EP_DIR_5 0 +#define OTG_EP_DIR_6 0 +#define OTG_EP_DIR_7 0 +#define OTG_EP_DIR_8 0 +#define OTG_EP_DIR_9 0 +#define OTG_EP_DIR_10 0 +#define OTG_EP_DIR_11 0 +#define OTG_EP_DIR_12 0 +#define OTG_EP_DIR_13 0 +#define OTG_EP_DIR_14 0 +#define OTG_EP_DIR_15 0 + +/* 3.8 Device Periodic FIFO Depth Parameters */ + +/* 3.9 Device IN Endpoint FIFO Depth Parameters */ +#define OTG_TX_DINEP_DFIFO_DEPTH_0 512 +#define OTG_TX_DINEP_DFIFO_DEPTH_1 512 +#define OTG_TX_DINEP_DFIFO_DEPTH_2 512 +#define OTG_TX_DINEP_DFIFO_DEPTH_3 512 +#define OTG_TX_DINEP_DFIFO_DEPTH_4 512 +#define OTG_TX_DINEP_DFIFO_DEPTH_5 512 +#define OTG_TX_DINEP_DFIFO_DEPTH_6 512 +#define OTG_TX_DINEP_DFIFO_DEPTH_7 512 + +/* 3.10 UTMI-To-UTMI Bridge Component Parameters */ +#define DWC_U2UB_EN 0 + +#ifdef __cplusplus +} +#endif diff --git a/components/soc/esp32p4/include/soc/usb_dwc_struct.h b/components/soc/esp32p4/include/soc/usb_dwc_struct.h new file mode 100644 index 000000000000..728be16b0f66 --- /dev/null +++ b/components/soc/esp32p4/include/soc/usb_dwc_struct.h @@ -0,0 +1,1374 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* +Registers and fields were generated based on a set of configuration options. +See ESP32-P4 "usb_dwc_cfg.h" for more details. +*/ + +/* ---------------------------- Register Types ------------------------------ */ + +typedef union { + struct { + uint32_t sesreqscs: 1; + uint32_t sesreq: 1; + uint32_t vbvalidoven: 1; + uint32_t vbvalidovval: 1; + uint32_t avalidoven: 1; + uint32_t avalidovval: 1; + uint32_t bvalidoven: 1; + uint32_t bvalidovval: 1; + uint32_t hstnegscs: 1; + uint32_t hnpreq: 1; + uint32_t hstsethnpen: 1; + uint32_t devhnpen: 1; + uint32_t ehen: 1; + uint32_t reserved_13: 2; + uint32_t dbncefltrbypass: 1; + uint32_t conidsts: 1; + uint32_t dbnctime: 1; + uint32_t asesvld: 1; + uint32_t bsesvld: 1; + uint32_t otgver: 1; + uint32_t curmod: 1; + uint32_t reserved_22: 5; + uint32_t reserved_27: 1; + uint32_t reserved_28: 4; + }; + uint32_t val; +} usb_dwc_gotgctl_reg_t; + +typedef union { + struct { + uint32_t reserved_0: 2; + uint32_t sesenddet: 1; + uint32_t reserved_3: 5; + uint32_t sesreqsucstschng: 1; + uint32_t hstnegsucstschng: 1; + uint32_t reserved_10: 7; + uint32_t hstnegdet: 1; + uint32_t adevtoutchg: 1; + uint32_t dbncedone: 1; + uint32_t reserved_20: 1; + uint32_t reserved_21: 11; + }; + uint32_t val; +} usb_dwc_gotgint_reg_t; + +typedef union { + struct { + uint32_t glbllntrmsk: 1; + uint32_t hbstlen: 4; + uint32_t dmaen: 1; + uint32_t reserved_6: 1; + uint32_t nptxfemplvl: 1; + uint32_t ptxfemplvl: 1; + uint32_t reserved_9: 12; + uint32_t remmemsupp: 1; + uint32_t notialldmawrit: 1; + uint32_t ahbsingle: 1; + uint32_t invdescendianess: 1; + uint32_t reserved_25: 7; + }; + uint32_t val; +} usb_dwc_gahbcfg_reg_t; + +typedef union { + struct { + uint32_t toutcal: 3; + uint32_t phyif: 1; + uint32_t ulpiutmisel: 1; + uint32_t fsintf: 1; + uint32_t physel: 1; + uint32_t ddrsel: 1; + uint32_t srpcap: 1; + uint32_t hnpcap: 1; + uint32_t usbtrdtim: 4; + uint32_t reserved_14: 1; + uint32_t phylpwrclksel: 1; + uint32_t reserved_16: 1; + uint32_t ulpifsls: 1; + uint32_t ulpiautores: 1; + uint32_t ulpiclksusm: 1; + uint32_t ulpiextvbusdrv: 1; + uint32_t ulpiextvbusindicator: 1; + uint32_t termseldlpulse: 1; + uint32_t complement: 1; + uint32_t indicator: 1; + uint32_t ulpi: 1; + uint32_t icusbcap: 1; + uint32_t reserved_27: 1; + uint32_t txenddelay: 1; + uint32_t forcehstmode: 1; + uint32_t forcedevmode: 1; + uint32_t corrupttxpkt: 1; + }; + uint32_t val; +} usb_dwc_gusbcfg_reg_t; + +typedef union { + struct { + uint32_t csftrst: 1; + uint32_t piufssftrst: 1; + uint32_t frmcntrrst: 1; + uint32_t reserved_3: 1; + uint32_t rxfflsh: 1; + uint32_t txfflsh: 1; + uint32_t txfnum: 5; + uint32_t reserved_11: 19; + uint32_t dmareq: 1; + uint32_t ahbidle: 1; + }; + uint32_t val; +} usb_dwc_grstctl_reg_t; + +typedef union { + struct { + uint32_t curmod: 1; + uint32_t modemis: 1; + uint32_t otgint: 1; + uint32_t sof: 1; + uint32_t rxflvl: 1; + uint32_t nptxfemp: 1; + uint32_t ginnakeff: 1; + uint32_t goutnakeff: 1; + uint32_t reserved_8: 1; + uint32_t reserved_9: 1; + uint32_t erlysusp: 1; + uint32_t usbsusp: 1; + uint32_t usbrst: 1; + uint32_t enumdone: 1; + uint32_t isooutdrop: 1; + uint32_t eopf: 1; + uint32_t reserved_16: 1; + uint32_t epmis: 1; + uint32_t iepint: 1; + uint32_t oepint: 1; + uint32_t incompisoin: 1; + uint32_t incompip: 1; + uint32_t fetsusp: 1; + uint32_t resetdet: 1; + uint32_t prtint: 1; + uint32_t hchint: 1; + uint32_t ptxfemp: 1; + uint32_t reserved_27: 1; + uint32_t conidstschng: 1; + uint32_t disconnint: 1; + uint32_t sessreqint: 1; + uint32_t wkupint: 1; + }; + uint32_t val; +} usb_dwc_gintsts_reg_t; + +typedef union { + struct { + uint32_t reserved_0: 1; + uint32_t modemismsk: 1; + uint32_t otgintmsk: 1; + uint32_t sofmsk: 1; + uint32_t rxflvlmsk: 1; + uint32_t nptxfempmsk: 1; + uint32_t ginnakeffmsk: 1; + uint32_t goutnackeffmsk: 1; + uint32_t reserved_8: 1; + uint32_t reserved_9: 1; + uint32_t erlysuspmsk: 1; + uint32_t usbsuspmsk: 1; + uint32_t usbrstmsk: 1; + uint32_t enumdonemsk: 1; + uint32_t isooutdropmsk: 1; + uint32_t eopfmsk: 1; + uint32_t reserved_16: 1; + uint32_t epmismsk: 1; + uint32_t iepintmsk: 1; + uint32_t oepintmsk: 1; + uint32_t incompisoinmsk: 1; + uint32_t incompipmsk: 1; + uint32_t fetsuspmsk: 1; + uint32_t resetdetmsk: 1; + uint32_t prtintmsk: 1; + uint32_t hchintmsk: 1; + uint32_t ptxfempmsk: 1; + uint32_t reserved_27: 1; + uint32_t conidstschngmsk: 1; + uint32_t disconnintmsk: 1; + uint32_t sessreqintmsk: 1; + uint32_t wkupintmsk: 1; + }; + uint32_t val; +} usb_dwc_gintmsk_reg_t; + +typedef union { + struct { + uint32_t chnum: 4; + uint32_t bcnt: 11; + uint32_t dpid: 2; + uint32_t pktsts: 4; + uint32_t fn: 4; + uint32_t reserved_25: 6; + uint32_t reserved_31: 1; + }; + uint32_t val; +} usb_dwc_grxstsr_reg_t; + +typedef union { + struct { + uint32_t chnum: 4; + uint32_t bcnt: 11; + uint32_t dpid: 2; + uint32_t pktsts: 4; + uint32_t fn: 4; + uint32_t reserved_25: 6; + uint32_t reserved_31: 1; + }; + uint32_t val; +} usb_dwc_grxstsp_reg_t; + +typedef union { + struct { + uint32_t rxfdep: 16; + uint32_t reserved_16: 16; + }; + uint32_t val; +} usb_dwc_grxfsiz_reg_t; + +typedef union { + struct { + uint32_t nptxfstaddr: 16; + uint32_t nptxfdep: 16; + }; + uint32_t val; +} usb_dwc_gnptxfsiz_reg_t; + +typedef union { + struct { + uint32_t nptxfspcavail: 16; + uint32_t nptxqspcavail: 8; + uint32_t nptxqtop: 7; + uint32_t reserved_31: 1; + }; + uint32_t val; +} usb_dwc_gnptxsts_reg_t; + +typedef union { + struct { + uint32_t regdata: 8; + uint32_t vctrl: 8; + uint32_t regaddr: 6; + uint32_t regwr: 1; + uint32_t reserved_23: 2; + uint32_t newregreq: 1; + uint32_t vstsbsy: 1; + uint32_t vstsdone: 1; + uint32_t reserved_28: 3; + uint32_t disulpidrvr: 1; + }; + uint32_t val; +} usb_dwc_gpvndctl_reg_t; + +typedef union { + struct { + uint32_t synopsysid; + }; + uint32_t val; +} usb_dwc_gsnpsid_reg_t; + +typedef union { + struct { + uint32_t epdir; + }; + uint32_t val; +} usb_dwc_ghwcfg1_reg_t; + +typedef union { + struct { + uint32_t otgmode: 3; + uint32_t otgarch: 2; + uint32_t singpnt: 1; + uint32_t hsphytype: 2; + uint32_t fsphytype: 2; + uint32_t numdeveps: 4; + uint32_t numhstchnl: 4; + uint32_t periosupport: 1; + uint32_t dynfifosizing: 1; + uint32_t multiprocintrpt: 1; + uint32_t reserved_21: 1; + uint32_t nptxqdepth: 2; + uint32_t ptxqdepth: 2; + uint32_t tknqdepth: 5; + uint32_t reserved_31: 1; + }; + uint32_t val; +} usb_dwc_ghwcfg2_reg_t; + +typedef union { + struct { + uint32_t xfersizewidth: 4; + uint32_t pktsizewidth: 3; + uint32_t otgen: 1; + uint32_t i2cintsel: 1; + uint32_t vndctlsupt: 1; + uint32_t optfeature: 1; + uint32_t rsttype: 1; + uint32_t adpsupport: 1; + uint32_t hsicmode: 1; + uint32_t bcsupport: 1; + uint32_t lpmmode: 1; + uint32_t dfifodepth: 16; + }; + uint32_t val; +} usb_dwc_ghwcfg3_reg_t; + +typedef union { + struct { + uint32_t numdevperioeps: 4; + uint32_t partialpwrdn: 1; + uint32_t ahbfreq: 1; + uint32_t hibernation: 1; + uint32_t extendedhibernation: 1; + uint32_t reserved_8: 4; + uint32_t acgsupt: 1; + uint32_t enhancedlpmsupt: 1; + uint32_t phydatawidth: 2; + uint32_t numctleps: 4; + uint32_t iddqfltr: 1; + uint32_t vbusvalidfltr: 1; + uint32_t avalidfltr: 1; + uint32_t bvalidfltr: 1; + uint32_t sessendfltr: 1; + uint32_t dedfifomode: 1; + uint32_t ineps: 4; + uint32_t descdmaenabled: 1; + uint32_t descdma: 1; + }; + uint32_t val; +} usb_dwc_ghwcfg4_reg_t; + +typedef union { + struct { + uint32_t pmuintsel: 1; + uint32_t pmuactv: 1; + uint32_t reserved_2: 1; + uint32_t pwrdnclmp: 1; + uint32_t pwrdnrst_n: 1; + uint32_t pwrdnswtch: 1; + uint32_t disablevbus: 1; + uint32_t reserved_7: 1; + uint32_t reserved_8: 1; + uint32_t reserved_9: 1; + uint32_t reserved_10: 1; + uint32_t reserved_11: 1; + uint32_t reserved_12: 1; + uint32_t reserved_13: 1; + uint32_t reserved_14: 1; + uint32_t srpdetect: 1; + uint32_t srpdetectmsk: 1; + uint32_t stschngint: 1; + uint32_t stschngintmsk: 1; + uint32_t linestate: 2; + uint32_t iddig: 1; + uint32_t bsessvld: 1; + uint32_t adpint: 1; + uint32_t reserved_24: 5; + uint32_t reserved_29: 3; + }; + uint32_t val; +} usb_dwc_gpwrdn_reg_t; + +typedef union { + struct { + uint32_t gdfifocfg: 16; + uint32_t epinfobaseaddr: 16; + + }; + uint32_t val; +} usb_dwc_gdfifocfg_reg_t; + +typedef union { + struct { + uint32_t prbdschg: 2; + uint32_t prbdelta: 2; + uint32_t prbper: 2; + uint32_t rtim: 11; + uint32_t enaprb: 1; + uint32_t enasns: 1; + uint32_t adpres: 1; + uint32_t adpen: 1; + uint32_t adpprbint: 1; + uint32_t adpsnsint: 1; + uint32_t adptoutint: 1; + uint32_t adpprbintmsk: 1; + uint32_t adpsnsintmsk: 1; + uint32_t adptoutmsk: 1; + uint32_t ar: 2; + uint32_t reserved_29: 3; + }; + uint32_t val; +} usb_dwc_gadpctl_reg_t; + +typedef union { + struct { + uint32_t ptxfstaddr: 16; + uint32_t ptxfsize: 16; + }; + uint32_t val; +} usb_dwc_hptxfsiz_reg_t; + +typedef union { + struct { + uint32_t inepntxfstaddr: 16; + uint32_t inepntxfdep: 16; + }; + uint32_t val; +} usb_dwc_dieptxfi_reg_t; + +typedef union { + struct { + uint32_t fslspclksel: 2; + uint32_t fslssupp: 1; + uint32_t reserved_3: 4; + uint32_t ena32khzs: 1; + uint32_t resvalid: 8; + uint32_t reserved_16: 1; + uint32_t reserved_17: 6; + uint32_t descdma: 1; + uint32_t frlisten: 2; + uint32_t perschedena: 1; + uint32_t reserved_27: 4; + uint32_t modechtimen: 1; + }; + uint32_t val; +} usb_dwc_hcfg_reg_t; + +typedef union { + struct { + uint32_t frint: 16; + uint32_t hfirrldctrl: 1; + uint32_t reserved_17: 15; + }; + uint32_t val; +} usb_dwc_hfir_reg_t; + +typedef union { + struct { + uint32_t frnum: 16; + uint32_t frrem: 16; + }; + uint32_t val; +} usb_dwc_hfnum_reg_t; + +typedef union { + struct { + uint32_t ptxfspcavail: 16; + uint32_t ptxqspcavail: 8; + uint32_t ptxqtop: 8; + }; + uint32_t val; +} usb_dwc_hptxsts_reg_t; + +typedef union { + struct { + uint32_t haint: 16; + uint32_t reserved_16: 16; + }; + uint32_t val; +} usb_dwc_haint_reg_t; + +typedef union { + struct { + uint32_t haintmsk: 16; + uint32_t reserved_16: 16; + }; + uint32_t val; +} usb_dwc_haintmsk_reg_t; + +typedef union { + struct { + uint32_t hflbaddr; + }; + uint32_t val; +} usb_dwc_hflbaddr_reg_t; + +typedef union { + struct { + uint32_t prtconnsts: 1; + uint32_t prtconndet: 1; + uint32_t prtena: 1; + uint32_t prtenchng: 1; + uint32_t prtovrcurract: 1; + uint32_t prtovrcurrchng: 1; + uint32_t prtres: 1; + uint32_t prtsusp: 1; + uint32_t prtrst: 1; + uint32_t reserved_9: 1; + uint32_t prtlnsts: 2; + uint32_t prtpwr: 1; + uint32_t prttstctl: 4; + uint32_t prtspd: 2; + uint32_t reserved_19: 13; + }; + uint32_t val; +} usb_dwc_hprt_reg_t; + +typedef union { + struct { + uint32_t mps: 11; + uint32_t epnum: 4; + uint32_t epdir: 1; + uint32_t reserved_16: 1; + uint32_t lspddev: 1; + uint32_t eptype: 2; + uint32_t ec: 2; + uint32_t devaddr: 7; + uint32_t oddfrm: 1; + uint32_t chdis: 1; + uint32_t chena: 1; + }; + uint32_t val; +} usb_dwc_hcchar_reg_t; + +typedef union { + struct { + uint32_t prtaddr: 7; + uint32_t hubaddr: 7; + uint32_t xactpos: 2; + uint32_t compsplt: 1; + uint32_t reserved_17: 14; + uint32_t spltena: 1; + }; + uint32_t val; +} usb_dwc_hcsplt_reg_t; + +typedef union { + struct { + uint32_t xfercompl: 1; + uint32_t chhltd: 1; + uint32_t ahberr: 1; + uint32_t stall: 1; + uint32_t nack: 1; + uint32_t ack: 1; + uint32_t nyet: 1; + uint32_t xacterr: 1; + uint32_t bblerr: 1; + uint32_t frmovrun: 1; + uint32_t datatglerr: 1; + uint32_t bnaintr: 1; + uint32_t xcs_xact_err: 1; + uint32_t desc_lst_rollintr: 1; + uint32_t reserved_14: 18; + }; + uint32_t val; +} usb_dwc_hcint_reg_t; + +typedef union { + struct { + uint32_t xfercomplmsk: 1; + uint32_t chhltdmsk: 1; + uint32_t ahberrmsk: 1; + uint32_t reserved_3: 1; + uint32_t reserved_4: 1; + uint32_t reserved_5: 1; + uint32_t reserved_6: 1; + uint32_t reserved_7: 1; + uint32_t reserved_8: 1; + uint32_t reserved_9: 1; + uint32_t reserved_10: 1; + uint32_t bnaintrmsk: 1; + uint32_t reserved_12: 1; + uint32_t desc_lst_rollintrmsk: 1; + uint32_t reserved_14: 18; + }; + uint32_t val; +} usb_dwc_hcintmsk_reg_t; + +typedef union { + struct { + uint32_t xfersize: 19; // Note: Width depends on OTG_TRANS_COUNT_WIDTH (see databook). + uint32_t pktcnt: 10; // Note: Width depends on OTG_PACKET_COUNT_WIDTH (see databook). + uint32_t pid: 2; + uint32_t dopng: 1; + }; + uint32_t val; +} usb_dwc_hctsiz_reg_t; + +typedef union { + struct { + uint32_t dmaaddr; + }; + uint32_t val; +} usb_dwc_hcdma_reg_t; + +typedef union { + struct { + uint32_t hcdmab; + }; + uint32_t val; +} usb_dwc_hcdmab_reg_t; + +typedef union { + struct { + uint32_t devspd: 2; + uint32_t nzstsouthshk: 1; + uint32_t ena32khzsusp: 1; + uint32_t devaddr: 7; + uint32_t perfrint: 2; + uint32_t endevoutnak: 1; + uint32_t xcvrdly: 1; + uint32_t erraticintmsk: 1; + uint32_t reserved_16: 2; + uint32_t reserved_18: 5; + uint32_t descdma: 1; + uint32_t perschintvl: 2; + uint32_t resvalid: 6; + }; + uint32_t val; +} usb_dwc_dcfg_reg_t; + +typedef union { + struct { + uint32_t rmtwkupsig: 1; + uint32_t sftdiscon: 1; + uint32_t gnpinnaksts: 1; + uint32_t goutnaksts: 1; + uint32_t tstctl: 3; + uint32_t sgnpinnak: 1; + uint32_t cgnpinnak: 1; + uint32_t sgoutnak: 1; + uint32_t cgoutnak: 1; + uint32_t pwronprgdone: 1; + uint32_t reserved_12: 1; + uint32_t gmc: 2; + uint32_t ignrfrmnum: 1; + uint32_t nakonbble: 1; + uint32_t encontonbna: 1; + uint32_t reserved_18: 1; + uint32_t reserved_19: 13; + }; + uint32_t val; +} usb_dwc_dctl_reg_t; + +typedef union { + struct { + uint32_t suspsts: 1; + uint32_t enumspd: 2; + uint32_t errticerr: 1; + uint32_t reserved_4: 4; + uint32_t soffn: 14; + uint32_t devlnsts: 2; + uint32_t reserved_24: 8; + }; + uint32_t val; +} usb_dwc_dsts_reg_t; + +typedef union { + struct { + uint32_t xfercomplmsk: 1; + uint32_t epdisbldmsk: 1; + uint32_t ahberrmsk: 1; + uint32_t timeoutmsk: 1; + uint32_t intkntxfempmsk: 1; + uint32_t intknepmismsk: 1; + uint32_t inepnakeffmsk: 1; + uint32_t reserved_7: 1; + uint32_t txfifoundrnmsk: 1; + uint32_t bnainintrmsk: 1; + uint32_t reserved_10: 3; + uint32_t nakmsk: 1; + uint32_t reserved_14: 18; + }; + uint32_t val; +} usb_dwc_diepmsk_reg_t; + +typedef union { + struct { + uint32_t xfercomplmsk: 1; + uint32_t epdisbldmsk: 1; + uint32_t ahberrmsk: 1; + uint32_t setupmsk: 1; + uint32_t outtknepdismsk: 1; + uint32_t stsphsercvdmsk: 1; + uint32_t back2backsetup: 1; + uint32_t reserved_7: 1; + uint32_t outpkterrmsk: 1; + uint32_t bnaoutintrmsk: 1; + uint32_t reserved_10: 2; + uint32_t bbleerrmsk: 1; + uint32_t nakmsk: 1; + uint32_t nyetmsk: 1; + uint32_t reserved_15: 17; + }; + uint32_t val; +} usb_dwc_doepmsk_reg_t; + +typedef union { + struct { + uint32_t inepint0: 1; + uint32_t inepint1: 1; + uint32_t inepint2: 1; + uint32_t inepint3: 1; + uint32_t inepint4: 1; + uint32_t inepint5: 1; + uint32_t inepint6: 1; + uint32_t inepint7: 1; + uint32_t inepint8: 1; + uint32_t inepint9: 1; + uint32_t inepint10: 1; + uint32_t inepint11: 1; + uint32_t inepint12: 1; + uint32_t inepint13: 1; + uint32_t inepint14: 1; + uint32_t inepint15: 1; + uint32_t outepint0: 1; + uint32_t outepint1: 1; + uint32_t outepint2: 1; + uint32_t outepint3: 1; + uint32_t outepint4: 1; + uint32_t outepint5: 1; + uint32_t outepint6: 1; + uint32_t outepint7: 1; + uint32_t outepint8: 1; + uint32_t outepint9: 1; + uint32_t outepint10: 1; + uint32_t outepint11: 1; + uint32_t outepint12: 1; + uint32_t outepint13: 1; + uint32_t outepint14: 1; + uint32_t outepint15: 1; + }; + uint32_t val; +} usb_dwc_daint_reg_t; + +typedef union { + struct { + uint32_t inepmsk0: 1; + uint32_t inepmsk1: 1; + uint32_t inepmsk2: 1; + uint32_t inepmsk3: 1; + uint32_t inepmsk4: 1; + uint32_t inepmsk5: 1; + uint32_t inepmsk6: 1; + uint32_t inepmsk7: 1; + uint32_t inepmsk8: 1; + uint32_t inepmsk9: 1; + uint32_t inepmsk10: 1; + uint32_t inepmsk11: 1; + uint32_t inepmsk12: 1; + uint32_t inepmsk13: 1; + uint32_t inepmsk14: 1; + uint32_t inepmsk15: 1; + uint32_t outepmsk0: 1; + uint32_t outepmsk1: 1; + uint32_t outepmsk2: 1; + uint32_t outepmsk3: 1; + uint32_t outepmsk4: 1; + uint32_t outepmsk5: 1; + uint32_t outepmsk6: 1; + uint32_t outepmsk7: 1; + uint32_t outepmsk8: 1; + uint32_t outepmsk9: 1; + uint32_t outepmsk10: 1; + uint32_t outepmsk11: 1; + uint32_t outepmsk12: 1; + uint32_t outepmsk13: 1; + uint32_t outepmsk14: 1; + uint32_t outepmsk15: 1; + }; + uint32_t val; +} usb_dwc_daintmsk_reg_t; + +typedef union { + struct { + uint32_t dvbusdis: 16; + uint32_t reserved_16: 16; + }; + uint32_t val; +} usb_dwc_dvbusdis_reg_t; + +typedef union { + struct { + uint32_t dvbuspulse: 12; + uint32_t reserved_12: 20; + }; + uint32_t val; +} usb_dwc_dvbuspulse_reg_t; + +typedef union { + struct { + uint32_t nonisothren: 1; + uint32_t isothren: 1; + uint32_t txthrlen: 9; + uint32_t ahbthrratio: 2; + uint32_t reserved_13: 3; + uint32_t rxthren: 1; + uint32_t rxthrlen: 9; + uint32_t reserved_26: 1; + uint32_t arbprken: 1; + uint32_t reserved_28: 4; + }; + uint32_t val; +} usb_dwc_dthrctl_reg_t; + +typedef union { + struct { + uint32_t ineptxfempmsk: 16; + uint32_t reserved_16: 16; + }; + uint32_t val; +} usb_dwc_diepempmsk_reg_t; + +typedef union { + struct { + uint32_t echinepint: 16; + uint32_t echoutepint: 16; + }; + uint32_t val; +} usb_dwc_deachint_reg_t; + +typedef union { + struct { + uint32_t echinepmsk0: 1; + uint32_t echinepmsk1: 1; + uint32_t echinepmsk2: 1; + uint32_t echinepmsk3: 1; + uint32_t echinepmsk4: 1; + uint32_t echinepmsk5: 1; + uint32_t echinepmsk6: 1; + uint32_t echinepmsk7: 1; + uint32_t echinepmsk8: 1; + uint32_t echinepmsk9: 1; + uint32_t echinepmsk10: 1; + uint32_t echinepmsk11: 1; + uint32_t echinepmsk12: 1; + uint32_t echinepmsk13: 1; + uint32_t echinepmsk14: 1; + uint32_t echinepmsk15: 1; + uint32_t echoutepmsk0: 1; + uint32_t echoutepmsk1: 1; + uint32_t echoutepmsk2: 1; + uint32_t echoutepmsk3: 1; + uint32_t echoutepmsk4: 1; + uint32_t echoutepmsk5: 1; + uint32_t echoutepmsk6: 1; + uint32_t echoutepmsk7: 1; + uint32_t echoutepmsk8: 1; + uint32_t echoutepmsk9: 1; + uint32_t echoutepmsk10: 1; + uint32_t echoutepmsk11: 1; + uint32_t echoutepmsk12: 1; + uint32_t echoutepmsk13: 1; + uint32_t echoutepmsk14: 1; + uint32_t echoutepmsk15: 1; + }; + uint32_t val; +} usb_dwc_deachintmsk_reg_t; + +typedef union { + struct { + uint32_t xfercomplmsl: 1; + uint32_t epdisbldmsk: 1; + uint32_t ahberrmsk: 1; + uint32_t timeoutmsk: 1; + uint32_t intkntxfempmsk: 1; + uint32_t intknepmismsk: 1; + uint32_t inepnakeffmsk: 1; + uint32_t reserved_7: 1; + uint32_t txfifoundrnmsk: 1; + uint32_t bnainintrmsk: 1; + uint32_t reserved_10: 3; + uint32_t nakmsk: 1; + uint32_t reserved_14: 18; + }; + uint32_t val; +} usb_dwc_diepeachmski_reg_t; + +typedef union { + struct { + uint32_t xfercomplmsk: 1; + uint32_t epdisbldmsk: 1; + uint32_t ahberrmsk: 1; + uint32_t setupmsk: 1; + uint32_t outtknepdismsk: 1; + uint32_t reserved_5: 1; + uint32_t back2backsetup: 1; + uint32_t reserved_7: 1; + uint32_t outpkterrmsk: 1; + uint32_t bnaoutintrmsk: 1; + uint32_t reserved_10: 2; + uint32_t bbleerrmsk: 1; + uint32_t nakmsk: 1; + uint32_t nyetmsk: 1; + uint32_t reserved_15: 17; + }; + uint32_t val; +} usb_dwc_doepeachmski_reg_t; + +typedef union { + struct { + uint32_t mps: 2; + uint32_t reserved_2: 9; + uint32_t reserved_11: 4; + uint32_t usbactep: 1; + uint32_t reserved_16: 1; + uint32_t naksts: 1; + uint32_t eptype: 2; + uint32_t reserved_20: 1; + uint32_t stall: 1; + uint32_t txfnum: 4; + uint32_t cnak: 1; + uint32_t snak: 1; + uint32_t reserved_28: 2; + uint32_t epdis: 1; + uint32_t epena: 1; + }; + uint32_t val; +} usb_dwc_diepctl0_reg_t; + +typedef union { + struct { + uint32_t xfercompl: 1; + uint32_t epdisbld: 1; + uint32_t ahberr: 1; + uint32_t timeout: 1; + uint32_t intkntxfemp: 1; + uint32_t intknepmis: 1; + uint32_t inepnakeff: 1; + uint32_t txfemp: 1; + uint32_t txfifoundrn: 1; + uint32_t bnaintr: 1; + uint32_t reserved_10: 1; + uint32_t pktdrpsts: 1; + uint32_t bbleerr: 1; + uint32_t nakintrpt: 1; + uint32_t nyetintrpt: 1; + uint32_t reserved_15: 17; + }; + uint32_t val; +} usb_dwc_diepint0_reg_t; + +typedef union { + struct { + uint32_t xfersize: 7; + uint32_t reserved_7: 12; + uint32_t pktcnt: 2; + uint32_t reserved_21: 11; + }; + uint32_t val; +} usb_dwc_dieptsiz0_reg_t; + +typedef union { + struct { + uint32_t dmaaddr; + }; + uint32_t val; +} usb_dwc_diepdma0_reg_t; + +typedef union { + struct { + uint32_t ineptxfspcavail: 16; + uint32_t reserved_16: 16; + }; + uint32_t val; +} usb_dwc_dtxfsts0_reg_t; + +typedef union { + struct { + uint32_t dmabufferaddr; + }; + uint32_t val; +} usb_dwc_diepdmab0_reg_t; + +typedef union { + struct { + uint32_t mps: 11; + uint32_t reserved_11: 4; + uint32_t usbactep: 1; + uint32_t dpid: 1; + uint32_t naksts: 1; + uint32_t eptype: 2; + uint32_t reserved_20: 1; + uint32_t stall: 1; + uint32_t txfnum: 4; + uint32_t cnak: 1; + uint32_t snak: 1; + uint32_t setd0pid: 1; + uint32_t setd1pid: 1; + uint32_t epdis: 1; + uint32_t epena: 1; + }; + uint32_t val; +} usb_dwc_diepctl_reg_t; + +typedef union { + struct { + uint32_t xfercompl: 1; + uint32_t epdisbld: 1; + uint32_t ahberr: 1; + uint32_t timeout: 1; + uint32_t intkntxfemp: 1; + uint32_t intknepmis: 1; + uint32_t inepnakeff: 1; + uint32_t txfemp: 1; + uint32_t txfifoundrn: 1; + uint32_t bnaintr: 1; + uint32_t reserved_10: 1; + uint32_t pktdrpsts: 1; + uint32_t bbleerr: 1; + uint32_t nakintrpt: 1; + uint32_t nyetintrpt: 1; + uint32_t reserved_15: 17; + }; + uint32_t val; +} usb_dwc_diepint_reg_t; + +typedef union { + struct { + uint32_t xfersize: 19; // Note: Width depends on OTG_TRANS_COUNT_WIDTH (see databook). + uint32_t pktcnt: 10; // Note: Width depends on OTG_PACKET_COUNT_WIDTH (see databook). + uint32_t mc: 2; + uint32_t reserved: 1; + }; + uint32_t val; +} usb_dwc_dieptsiz_reg_t; + +typedef union { + struct { + uint32_t dmaddr; + }; + uint32_t val; +} usb_dwc_diepdma_reg_t; + +typedef union { + struct { + uint32_t ineptxfspcavail: 16; + uint32_t reserved_16: 16; + }; + uint32_t val; +} usb_dwc_dtxfsts_reg_t; + +typedef union { + struct { + uint32_t dmabufferaddr; + }; + uint32_t val; +} usb_dwc_diepdmab_reg_t; + +typedef union { + struct { + uint32_t mps: 2; + uint32_t reserved_2: 13; + uint32_t usbactep: 1; + uint32_t reserved_16: 1; + uint32_t naksts: 1; + uint32_t eptype: 2; + uint32_t snp: 1; + uint32_t stall: 1; + uint32_t reserved_22: 4; + uint32_t cnak: 1; + uint32_t snak: 1; + uint32_t reserved_28: 2; + uint32_t epdis: 1; + uint32_t epena: 1; + }; + uint32_t val; +} usb_dwc_doepctl0_reg_t; + +typedef union { + struct { + uint32_t xfercompl: 1; + uint32_t epdisbld: 1; + uint32_t ahberr: 1; + uint32_t setup: 1; + uint32_t outtknepdis: 1; + uint32_t stsphsercvd: 1; + uint32_t back2backsetup: 1; + uint32_t reserved_7: 1; + uint32_t outpkterr: 1; + uint32_t bnaintr: 1; + uint32_t reserved_10: 1; + uint32_t pktdrpsts: 1; + uint32_t bbleerr: 1; + uint32_t nakintrpt: 1; + uint32_t nyepintrpt: 1; + uint32_t stuppktrcvd: 1; + uint32_t reserved_16: 16; + }; + uint32_t val; +} usb_dwc_doepint0_reg_t; + +typedef union { + struct { + uint32_t xfersize: 7; + uint32_t reserved_7: 12; + uint32_t pktcnt: 1; + uint32_t reserved_20: 9; + uint32_t supcnt: 2; + uint32_t reserved_31: 1; + }; + uint32_t val; +} usb_dwc_doeptsiz0_reg_t; + +typedef union { + struct { + uint32_t dmaaddr; + }; + uint32_t val; +} usb_dwc_doepdma0_reg_t; + +typedef union { + struct { + uint32_t dmabufferaddr; + }; + uint32_t val; +} usb_dwc_doepdmab0_reg_t; + +typedef union { + struct { + uint32_t mps: 11; + uint32_t reserved_11: 4; + uint32_t usbactep: 1; + uint32_t dpid: 1; + uint32_t naksts: 1; + uint32_t eptype: 2; + uint32_t snp: 1; + uint32_t stall: 1; + uint32_t reserved_22: 4; + uint32_t cnak: 1; + uint32_t snak: 1; + uint32_t setd0pid: 1; + uint32_t setd1pid: 1; + uint32_t epdis: 1; + uint32_t epena: 1; + }; + uint32_t val; +} usb_dwc_doepctl_reg_t; + +typedef union { + struct { + uint32_t xfercompl: 1; + uint32_t epdisbld: 1; + uint32_t ahberr: 1; + uint32_t setup: 1; + uint32_t outtknepdis: 1; + uint32_t stsphsercvd: 1; + uint32_t back2backsetup: 1; + uint32_t reserved_7: 1; + uint32_t outpkterr: 1; + uint32_t bnaintr: 1; + uint32_t reserved_10: 1; + uint32_t pktdrpsts: 1; + uint32_t bbleerr: 1; + uint32_t nakintrpt: 1; + uint32_t nyetintrpt: 1; + uint32_t stuppktrcvd: 1; + uint32_t reserved_16: 16; + }; + uint32_t val; +} usb_dwc_doepint_reg_t; + +typedef union { + struct { + uint32_t xfersize: 19; // Note: Width depends on OTG_TRANS_COUNT_WIDTH (see databook). + uint32_t pktcnt: 10; // Note: Width depends on OTG_PACKET_COUNT_WIDTH (see databook). + uint32_t rxdpid: 2; + uint32_t reserved_31: 1; + }; + uint32_t val; +} usb_dwc_doeptsiz_reg_t; + +typedef union { + struct { + uint32_t dmaaddr; + }; + uint32_t val; +} usb_dwc_doepdma_reg_t; + +typedef union { + struct { + uint32_t dmabufferaddr; + }; + uint32_t val; +} usb_dwc_doepdmab_reg_t; + +typedef union { + struct { + uint32_t stoppclk: 1; + uint32_t gatehclk: 1; + uint32_t pwrclmp: 1; + uint32_t rstpdwnmodule: 1; + uint32_t reserved_4: 1; + uint32_t reserved_5: 1; + uint32_t physleep: 1; + uint32_t l1suspended: 1; + uint32_t resetaftersusp: 1; + uint32_t reserved_9: 1; + uint32_t reserved_10: 1; + uint32_t reserved_11: 1; + uint32_t reserved_12: 1; + uint32_t reserved_13: 1; + uint32_t reserved_14: 18; + }; + uint32_t val; +} usb_dwc_pcgcctl_reg_t; + +/* --------------------------- Register Groups ------------------------------ */ + +typedef struct { + volatile usb_dwc_hcchar_reg_t hcchar_reg; // 0x00 + volatile usb_dwc_hcsplt_reg_t hcsplt_reg; // 0x04 + volatile usb_dwc_hcint_reg_t hcint_reg; // 0x08 + volatile usb_dwc_hcintmsk_reg_t hcintmsk_reg; // 0x0c + volatile usb_dwc_hctsiz_reg_t hctsiz_reg; // 0x10 + volatile usb_dwc_hcdma_reg_t hcdma_reg; // 0x14 + uint32_t reserved_0x18[1]; // 0x18 + volatile usb_dwc_hcdmab_reg_t hcdmab_reg; // 0x1c +} usb_dwc_host_chan_regs_t; + +typedef struct { + volatile usb_dwc_diepctl_reg_t diepctl_reg; // 0x00 + uint32_t reserved_0x04[1]; // 0x04 + volatile usb_dwc_diepint_reg_t diepint_reg; // 0x08 + uint32_t reserved_0x0c[1]; // 0x0c + volatile usb_dwc_dieptsiz_reg_t dieptsiz_reg; // 0x10 + volatile usb_dwc_diepdma_reg_t diepdma_reg; // 0x14 + volatile usb_dwc_dtxfsts_reg_t dtxfsts_reg; // 0x18 + volatile usb_dwc_diepdmab_reg_t diepdmab_reg; // 0x1c +} usb_dwc_in_ep_regs_t; + +typedef struct { + volatile usb_dwc_doepctl_reg_t doepctl_reg; // 0x00 + uint32_t reserved_0x04[1]; // 0x04 + volatile usb_dwc_doepint_reg_t doepint_reg; // 0x08 + uint32_t reserved_0x0c[1]; // 0x0c + volatile usb_dwc_doeptsiz_reg_t doeptsiz_reg; // 0x10 + volatile usb_dwc_doepdma_reg_t doepdma_reg; // 0x14 + uint32_t reserved_0x18[1]; // 0x18 + volatile usb_dwc_doepdmab_reg_t doepdmab_reg; // 0x1c +} usb_dwc_out_ep_regs_t; + +/* --------------------------- Register Layout ------------------------------ */ + +typedef struct { + // Global Registers + volatile usb_dwc_gotgctl_reg_t gotgctl_reg; // 0x0000 + volatile usb_dwc_gotgint_reg_t gotgint_reg; // 0x0004 + volatile usb_dwc_gahbcfg_reg_t gahbcfg_reg; // 0x0008 + volatile usb_dwc_gusbcfg_reg_t gusbcfg_reg; // 0x000c + volatile usb_dwc_grstctl_reg_t grstctl_reg; // 0x0010 + volatile usb_dwc_gintsts_reg_t gintsts_reg; // 0x0014 + volatile usb_dwc_gintmsk_reg_t gintmsk_reg; // 0x0018 + volatile usb_dwc_grxstsr_reg_t grxstsr_reg; // 0x001c + volatile usb_dwc_grxstsp_reg_t grxstsp_reg; // 0x0020 + volatile usb_dwc_grxfsiz_reg_t grxfsiz_reg; // 0x0024 + volatile usb_dwc_gnptxfsiz_reg_t gnptxfsiz_reg; // 0x0028 + volatile usb_dwc_gnptxsts_reg_t gnptxsts_reg; // 0x002c + uint32_t reserved_0x0030; // 0x0030 + volatile usb_dwc_gpvndctl_reg_t gpvndctl_reg; // 0x0034 + uint32_t reserved_0x0038; // 0x0038 + uint32_t reserved_0x003c; // 0x003c + volatile usb_dwc_gsnpsid_reg_t gsnpsid_reg; // 0x0040 + volatile usb_dwc_ghwcfg1_reg_t ghwcfg1_reg; // 0x0044 + volatile usb_dwc_ghwcfg2_reg_t ghwcfg2_reg; // 0x0048 + volatile usb_dwc_ghwcfg3_reg_t ghwcfg3_reg; // 0x004c + volatile usb_dwc_ghwcfg4_reg_t ghwcfg4_reg; // 0x0050 + uint32_t reserved_0x0054; // 0x0054 + volatile usb_dwc_gpwrdn_reg_t gpwrdn_reg; // 0x0058 + volatile usb_dwc_gdfifocfg_reg_t gdfifocfg_reg; // 0x005c + volatile usb_dwc_gadpctl_reg_t gadpctl_reg; // 0x0060 + uint32_t reserved_0x0064_0x0100[39]; // 0x0064 to 0x0100 + volatile usb_dwc_hptxfsiz_reg_t hptxfsiz_reg; // 0x0100 + volatile usb_dwc_dieptxfi_reg_t dieptxfi_regs[7]; // 0x0104 to 0x011c (depends on OTG_NUM_IN_EPS) + usb_dwc_dieptxfi_reg_t reserved_0x0120_0x013c[8]; // 0x0120 to 0x013c (depends on OTG_NUM_IN_EPS) + uint32_t reserved_0x140_0x3fc[176]; // 0x0140 to 0x03fc + + // Host Mode Registers + volatile usb_dwc_hcfg_reg_t hcfg_reg; // 0x0400 + volatile usb_dwc_hfir_reg_t hfir_reg; // 0x0404 + volatile usb_dwc_hfnum_reg_t hfnum_reg; // 0x0408 + uint32_t reserved_0x40c[1]; // 0x040c + volatile usb_dwc_hptxsts_reg_t hptxsts_reg; // 0x0410 + volatile usb_dwc_haint_reg_t haint_reg; // 0x0414 + volatile usb_dwc_haintmsk_reg_t haintmsk_reg; // 0x0418 + volatile usb_dwc_hflbaddr_reg_t hflbaddr_reg; // 0x041c + uint32_t reserved_0x420_0x43c[8]; // 0x0420 to 0x043c + volatile usb_dwc_hprt_reg_t hprt_reg; // 0x0440 + uint32_t reserved_0x0444_0x04fc[47]; // 0x0444 to 0x04fc + + // Host Channel Registers + usb_dwc_host_chan_regs_t host_chans[16]; // 0x0500 to 0x06fc (depends on OTG_NUM_HOST_CHAN) + uint32_t reserved_0x0704_0x07fc[64]; // 0x0700 to 0x07fc + + // Device Mode Registers + volatile usb_dwc_dcfg_reg_t dcfg_reg; // 0x0800 + volatile usb_dwc_dctl_reg_t dctl_reg; // 0x0804 + volatile usb_dwc_dsts_reg_t dsts_reg; // 0x0808 + uint32_t reserved_0x080c[1]; // 0x080c + volatile usb_dwc_diepmsk_reg_t diepmsk_reg; // 0x0810 + volatile usb_dwc_doepmsk_reg_t doepmsk_reg; // 0x0814 + volatile usb_dwc_daint_reg_t daint_reg; // 0x0818 + volatile usb_dwc_daintmsk_reg_t daintmsk_reg; // 0x081c + uint32_t reserved_0x0820; // 0x0820 + uint32_t reserved_0x0824; // 0x0824 + volatile usb_dwc_dvbusdis_reg_t dvbusdis_reg; // 0x0828 + volatile usb_dwc_dvbuspulse_reg_t dvbuspulse_reg; // 0x082c + volatile usb_dwc_dthrctl_reg_t dthrctl_reg; // 0x0830 + volatile usb_dwc_diepempmsk_reg_t diepempmsk_reg; // 0x0834 + volatile usb_dwc_deachint_reg_t deachint_reg; // 0x0838 + volatile usb_dwc_deachintmsk_reg_t deachintmsk_reg; // 0x083c + volatile usb_dwc_diepeachmski_reg_t diepeachmsk0_reg; // 0x0840 + volatile usb_dwc_diepeachmski_reg_t diepeachmsk[15]; // 0x0844 to 0x087c (depends on OTG_NUM_EPS) + volatile usb_dwc_doepeachmski_reg_t doepeachmsk0_reg; // 0x0880 + volatile usb_dwc_doepeachmski_reg_t doepeachmsk[15]; // 0x0884 to 0x08c0 (depends on OTG_NUM_EPS) + uint32_t reserved_0x08c4_0x08fc[16]; // 0x08c4 to 0x08fc + + // Device: IN EP0 registers + volatile usb_dwc_diepctl0_reg_t diepctl0_reg; // 0x0900 + uint32_t reserved_0x0904[1]; // 0x0904 + volatile usb_dwc_diepint0_reg_t diepint0_reg; // 0x0908 + uint32_t reserved_0x090c[1]; // 0x090c + volatile usb_dwc_dieptsiz0_reg_t dieptsiz0_reg; // 0x0910 + volatile usb_dwc_diepdma0_reg_t diepdma0_reg; // 0x0914 + volatile usb_dwc_dtxfsts0_reg_t dtxfsts0_reg; // 0x0918 + volatile usb_dwc_diepdmab0_reg_t diepdmab0_reg; // 0x091c + + // Device: IN EP registers + usb_dwc_in_ep_regs_t in_eps[15]; // 0x0920 to 0x0afc (depends on OTG_NUM_EPS) + + // Device: OUT EP0 registers + volatile usb_dwc_doepctl0_reg_t doepctl0_reg; // 0x0b00 + uint32_t reserved_0x0b04[1]; // 0x0b04 + volatile usb_dwc_doepint0_reg_t doepint0_reg; // 0b0b08 + uint32_t reserved_0x0b0c[1]; // 0x0b0c + volatile usb_dwc_doeptsiz0_reg_t doeptsiz0_reg; // 0x0b10 + volatile usb_dwc_doepdma0_reg_t doepdma0_reg; // 0x0b14 + uint32_t reserved_0x0b18[1]; // 0x0b18 + volatile usb_dwc_doepdmab0_reg_t doepdmab0_reg; // 0x0b1c + + // Device: OUT EP registers + usb_dwc_out_ep_regs_t out_eps[15]; // 0x0b20 to 0x0cfc + uint32_t reserved_0x0d00_0x0dfc[64]; // 0x0d00 to 0x0dfc + + // Power and Clock Gating + volatile usb_dwc_pcgcctl_reg_t pcgcctl_reg; // 0x0e00 + uint32_t reserved_0x0e04[1]; // 0x0e04 +} usb_dwc_dev_t; + +#ifndef __cplusplus +_Static_assert(sizeof(usb_dwc_dev_t) == 0xe08, "Invalid size of usb_dwc_dev_t structure"); +#endif + +extern usb_dwc_dev_t USB_DWC_HS; + +#ifdef __cplusplus +} +#endif diff --git a/components/soc/esp32p4/ld/esp32p4.peripherals.ld b/components/soc/esp32p4/ld/esp32p4.peripherals.ld index 93fa97ebd9e9..7f5ea313c918 100644 --- a/components/soc/esp32p4/ld/esp32p4.peripherals.ld +++ b/components/soc/esp32p4/ld/esp32p4.peripherals.ld @@ -104,3 +104,5 @@ PROVIDE ( DMA2D = 0x50088000 ); PROVIDE ( JPEG = 0x50086000 ); PROVIDE ( USB_WRAP = 0x50080000 ); +PROVIDE ( USB_DWC_HS = 0x50000000 ); +PROVIDE ( USB_DWC_FS = 0x50040000 ); diff --git a/components/soc/esp32s2/include/soc/soc.h b/components/soc/esp32s2/include/soc/soc.h index 6d59f4163260..091e1c77c533 100644 --- a/components/soc/esp32s2/include/soc/soc.h +++ b/components/soc/esp32s2/include/soc/soc.h @@ -144,7 +144,6 @@ #define APB_CLK_FREQ_ROM ( 40*1000000 ) #define CPU_CLK_FREQ_ROM APB_CLK_FREQ_ROM #define CPU_CLK_FREQ_MHZ_BTLD (80) // The cpu clock frequency (in MHz) to set at 2nd stage bootloader system clock configuration -#define CPU_CLK_FREQ APB_CLK_FREQ #define APB_CLK_FREQ ( 80*1000000 ) //unit: Hz #define MODEM_REQUIRED_MIN_APB_CLK_FREQ ( 80*1000000 ) #define REF_CLK_FREQ ( 1000000 ) diff --git a/components/soc/esp32s2/include/soc/usb_wrap_struct.h b/components/soc/esp32s2/include/soc/usb_wrap_struct.h index 1b891797748f..0a01ebb0e1b0 100644 --- a/components/soc/esp32s2/include/soc/usb_wrap_struct.h +++ b/components/soc/esp32s2/include/soc/usb_wrap_struct.h @@ -153,7 +153,7 @@ typedef union { * USB D- rx value in test. */ uint32_t test_rx_dm:1; - uint32_t reserved:25; + uint32_t reserved_7:25; }; uint32_t val; } usb_wrap_test_conf_reg_t; diff --git a/components/soc/esp32s3/include/soc/soc.h b/components/soc/esp32s3/include/soc/soc.h index d465da64d477..bd14326f7a08 100644 --- a/components/soc/esp32s3/include/soc/soc.h +++ b/components/soc/esp32s3/include/soc/soc.h @@ -152,9 +152,7 @@ //Periheral Clock {{ #define APB_CLK_FREQ_ROM (40*1000000) #define CPU_CLK_FREQ_ROM APB_CLK_FREQ_ROM -#define EFUSE_CLK_FREQ_ROM (20*1000000) #define CPU_CLK_FREQ_MHZ_BTLD (80) // The cpu clock frequency (in MHz) to set at 2nd stage bootloader system clock configuration -#define CPU_CLK_FREQ APB_CLK_FREQ #define APB_CLK_FREQ (80*1000000) #define MODEM_REQUIRED_MIN_APB_CLK_FREQ (80*1000000) #define REF_CLK_FREQ (1000000) diff --git a/components/soc/esp32s3/include/soc/usb_wrap_struct.h b/components/soc/esp32s3/include/soc/usb_wrap_struct.h index ac0b87103414..71013fe25f7b 100644 --- a/components/soc/esp32s3/include/soc/usb_wrap_struct.h +++ b/components/soc/esp32s3/include/soc/usb_wrap_struct.h @@ -154,7 +154,7 @@ typedef union { * USB D- rx value in test. */ uint32_t test_rx_dm:1; - uint32_t reserved7:25; + uint32_t reserved_7:25; }; uint32_t val; } usb_wrap_test_conf_reg_t; diff --git a/components/spi_flash/test_apps/.build-test-rules.yml b/components/spi_flash/test_apps/.build-test-rules.yml index 873efbdf7084..6011e396609e 100644 --- a/components/spi_flash/test_apps/.build-test-rules.yml +++ b/components/spi_flash/test_apps/.build-test-rules.yml @@ -49,6 +49,10 @@ components/spi_flash/test_apps/mspi_test: - if: CONFIG_NAME == "xip_psram" and IDF_TARGET in ["esp32p4"] temporary: true reason: not supported yet #TODO: IDF-7556 for p4 + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: test not pass, should be re-enable # TODO: IDF-8985 depends_filepatterns: - components/bootloader_support/bootloader_flash/**/* depends_components: 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 8eeed76f5cc9..53d206d9f3db 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 @@ -6,6 +6,7 @@ @pytest.mark.supported_targets +@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='esp32p4 support TBD') # TODO: IDF-8984 @pytest.mark.generic @pytest.mark.parametrize( 'config', diff --git a/components/spi_flash/test_apps/mspi_test/pytest_mspi_test.py b/components/spi_flash/test_apps/mspi_test/pytest_mspi_test.py index 267868d61647..83dfe27a74e6 100644 --- a/components/spi_flash/test_apps/mspi_test/pytest_mspi_test.py +++ b/components/spi_flash/test_apps/mspi_test/pytest_mspi_test.py @@ -5,6 +5,7 @@ from pytest_embedded import Dut +@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='esp32p4 support TBD') # TODO: IDF-8985 @pytest.mark.supported_targets @pytest.mark.generic @pytest.mark.parametrize( diff --git a/components/spiffs/host_test/.build-test-rules.yml b/components/spiffs/host_test/.build-test-rules.yml index eec002ed8a44..9de36c5b1159 100644 --- a/components/spiffs/host_test/.build-test-rules.yml +++ b/components/spiffs/host_test/.build-test-rules.yml @@ -2,3 +2,8 @@ components/spiffs/host_test: enable: - if: IDF_TARGET == "linux" reason: only test on linux + depends_components: + - spi_flash + - esp_partition + - spiffs + - vfs diff --git a/components/spiffs/test_apps/.build-test-rules.yml b/components/spiffs/test_apps/.build-test-rules.yml index 7ae25a037ae3..f3bf52966abf 100644 --- a/components/spiffs/test_apps/.build-test-rules.yml +++ b/components/spiffs/test_apps/.build-test-rules.yml @@ -2,3 +2,9 @@ components/spiffs/test_apps: disable_test: - if: IDF_TARGET not in ["esp32", "esp32c3", "esp32s3"] reason: These chips should be sufficient for test coverage (Xtensa and RISC-V, single and dual core) + + depends_components: + - spi_flash + - esp_partition + - spiffs + - vfs diff --git a/components/ulp/test_apps/.build-test-rules.yml b/components/ulp/test_apps/.build-test-rules.yml index b601d66f1431..c938f7ba11e3 100644 --- a/components/ulp/test_apps/.build-test-rules.yml +++ b/components/ulp/test_apps/.build-test-rules.yml @@ -3,6 +3,10 @@ components/ulp/test_apps/lp_core: disable: - if: SOC_LP_CORE_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET in ["esp32p4"] + temporary: true + reason: not tested yet # TODO: IDF-8986 depends_components: - ulp diff --git a/components/ulp/test_apps/lp_core/pytest_lp_core.py b/components/ulp/test_apps/lp_core/pytest_lp_core.py index f9c81c66440e..2325394b4cb1 100644 --- a/components/ulp/test_apps/lp_core/pytest_lp_core.py +++ b/components/ulp/test_apps/lp_core/pytest_lp_core.py @@ -14,11 +14,7 @@ def test_lp_core(dut: Dut) -> None: @pytest.mark.esp32c6 @pytest.mark.generic_multi_device @pytest.mark.parametrize( - 'count, config', - [ - (2, 'defaults',), - ], - indirect=True + 'count', [2], indirect=True ) def test_lp_core_multi_device(case_tester) -> None: # type: ignore for case in case_tester.test_menu: diff --git a/components/esp_hw_support/include/soc/esp32c5/.gitkeep b/components/ulp/test_apps/lp_core/sdkconfig.ci.default similarity index 100% rename from components/esp_hw_support/include/soc/esp32c5/.gitkeep rename to components/ulp/test_apps/lp_core/sdkconfig.ci.default diff --git a/components/usb/CMakeLists.txt b/components/usb/CMakeLists.txt index 84fdacccc9d9..2b72863a8816 100644 --- a/components/usb/CMakeLists.txt +++ b/components/usb/CMakeLists.txt @@ -6,13 +6,13 @@ endif() set(srcs) set(include) -set(priv_include) -# As CONFIG_USB_OTG_SUPPORTED comes from Kconfig, it is not evaluated yet +set(priv_includes) +# As CONFIG_SOC_USB_OTG_SUPPORTED comes from Kconfig, it is not evaluated yet # when components are being registered. # Thus, always add the (private) requirements, regardless of Kconfig -set(priv_require esp_driver_gpio) # usb_phy driver relies on gpio driver API +set(priv_requires esp_driver_gpio) # usb_phy driver relies on gpio driver API -if(CONFIG_USB_OTG_SUPPORTED) +if(CONFIG_SOC_USB_OTG_SUPPORTED) list(APPEND srcs "hcd_dwc.c" "hub.c" "usb_helpers.c" @@ -21,11 +21,11 @@ if(CONFIG_USB_OTG_SUPPORTED) "usbh.c" "usb_phy.c") list(APPEND include "include") - list(APPEND priv_include "private_include") + list(APPEND priv_includes "private_include") endif() idf_component_register(SRCS ${srcs} INCLUDE_DIRS ${include} - PRIV_INCLUDE_DIRS ${priv_include} - PRIV_REQUIRES ${priv_require} + PRIV_INCLUDE_DIRS ${priv_includes} + PRIV_REQUIRES ${priv_requires} ) diff --git a/components/usb/Kconfig b/components/usb/Kconfig index 993d9ccb5f3a..1b9da3889a6c 100644 --- a/components/usb/Kconfig +++ b/components/usb/Kconfig @@ -1,13 +1,7 @@ menu "USB-OTG" - visible if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 - - # Invisible item, enabled when USB_OTG peripheral does exist - config USB_OTG_SUPPORTED - bool - default y if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 + depends on SOC_USB_OTG_SUPPORTED config USB_HOST_CONTROL_TRANSFER_MAX_SIZE - depends on USB_OTG_SUPPORTED int "Largest size (in bytes) of transfers to/from default endpoints" default 256 help @@ -18,7 +12,6 @@ menu "USB-OTG" - Device's with configuration descriptors larger than this limit cannot be supported choice USB_HOST_HW_BUFFER_BIAS - depends on USB_OTG_SUPPORTED prompt "Hardware FIFO size biasing" default USB_HOST_HW_BUFFER_BIAS_BALANCED help @@ -56,7 +49,6 @@ menu "USB-OTG" menu "Root Hub configuration" config USB_HOST_DEBOUNCE_DELAY_MS - depends on USB_OTG_SUPPORTED int "Debounce delay in ms" default 250 help @@ -67,7 +59,6 @@ menu "USB-OTG" The default value is set to 250 ms to be safe. config USB_HOST_RESET_HOLD_MS - depends on USB_OTG_SUPPORTED int "Reset hold in ms" default 30 help @@ -79,7 +70,6 @@ menu "USB-OTG" The default value is set to 30 ms to be safe. config USB_HOST_RESET_RECOVERY_MS - depends on USB_OTG_SUPPORTED int "Reset recovery delay in ms" default 30 help @@ -92,7 +82,6 @@ menu "USB-OTG" config USB_HOST_SET_ADDR_RECOVERY_MS - depends on USB_OTG_SUPPORTED int "SetAddress() recovery time in ms" default 10 help @@ -107,4 +96,23 @@ menu "USB-OTG" endmenu #Root Hub configuration + config USB_HOST_ENABLE_ENUM_FILTER_CALLBACK + bool "Enable enumeration filter callback" + default n + help + The enumeration filter callback is called before enumeration of each newly attached device. This callback + allows users to control whether a device should be enumerated, and what configuration number to use when + enumerating a device. + + If enabled, the enumeration filter callback can be set via 'usb_host_config_t' when calling + 'usb_host_install()'. + + # Hidden or compatibility options + + config USB_OTG_SUPPORTED + # Invisible config kept for compatibility + # Todo: Remove in v6.0 (IDF-8936) + bool + default y + endmenu #USB-OTG diff --git a/components/usb/hub.c b/components/usb/hub.c index 7f24a60a6d9c..daf591a39a2a 100644 --- a/components/usb/hub.c +++ b/components/usb/hub.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -32,11 +32,15 @@ implement the bare minimum to control the root HCD port. #define HUB_ROOT_HCD_PORT_FIFO_BIAS HCD_PORT_FIFO_BIAS_BALANCED #endif +#ifdef CONFIG_USB_HOST_ENABLE_ENUM_FILTER_CALLBACK +#define ENABLE_ENUM_FILTER_CALLBACK +#endif // CONFIG_USB_HOST_ENABLE_ENUM_FILTER_CALLBACK + #define SET_ADDR_RECOVERY_INTERVAL_MS CONFIG_USB_HOST_SET_ADDR_RECOVERY_MS #define ENUM_CTRL_TRANSFER_MAX_DATA_LEN CONFIG_USB_HOST_CONTROL_TRANSFER_MAX_SIZE #define ENUM_DEV_ADDR 1 // Device address used in enumeration -#define ENUM_CONFIG_INDEX 0 // Index used to get the first configuration descriptor of the device +#define ENUM_CONFIG_INDEX_DEFAULT 0 // Index used to get the first configuration descriptor of the device #define ENUM_SHORT_DESC_REQ_LEN 8 // Number of bytes to request when getting a short descriptor (just enough to get bMaxPacketSize0 or wTotalLength) #define ENUM_WORST_CASE_MPS_LS 8 // The worst case MPS of EP0 for a LS device #define ENUM_WORST_CASE_MPS_FS 64 // The worst case MPS of EP0 for a FS device @@ -165,6 +169,11 @@ typedef struct { uint8_t iSerialNumber; /**< Index of the Serial Number string descriptor */ uint8_t str_desc_bLength; /**< Saved bLength from getting a short string descriptor */ uint8_t bConfigurationValue; /**< Device's current configuration number */ + uint8_t enum_config_index; /**< Configuration index used during enumeration */ +#ifdef ENABLE_ENUM_FILTER_CALLBACK + usb_host_enum_filter_cb_t enum_filter_cb; /**< Set device configuration callback */ + bool graceful_exit; /**< Exit enumeration by user's request from the callback function */ +#endif // ENABLE_ENUM_FILTER_CALLBACK } enum_ctrl_t; typedef struct { @@ -280,6 +289,11 @@ static bool enum_stage_start(enum_ctrl_t *enum_ctrl) ESP_ERROR_CHECK(hcd_pipe_update_callback(enum_dflt_pipe_hdl, enum_dflt_pipe_callback, NULL)); enum_ctrl->dev_hdl = enum_dev_hdl; enum_ctrl->pipe = enum_dflt_pipe_hdl; + + // Flag to gracefully exit the enumeration process if requested by the user in the enumeration filter cb + #ifdef ENABLE_ENUM_FILTER_CALLBACK + enum_ctrl->graceful_exit = false; + #endif // ENABLE_ENUM_FILTER_CALLBACK return true; } @@ -323,6 +337,39 @@ static void get_string_desc_index_and_langid(enum_ctrl_t *enum_ctrl, uint8_t *in } } +static bool set_config_index(enum_ctrl_t *enum_ctrl, const usb_device_desc_t *device_desc) +{ + #ifdef ENABLE_ENUM_FILTER_CALLBACK + // Callback enabled in the menuncofig, but the callback function was not defined + if (enum_ctrl->enum_filter_cb == NULL) { + enum_ctrl->enum_config_index = ENUM_CONFIG_INDEX_DEFAULT; + return true; + } + + uint8_t enum_config_index; + const bool enum_continue = enum_ctrl->enum_filter_cb(device_desc, &enum_config_index); + + // User's request NOT to enumerate the USB device + if (!enum_continue) { + ESP_LOGW(HUB_DRIVER_TAG, "USB device (PID = 0x%x, VID = 0x%x) will not be enumerated", device_desc->idProduct, device_desc->idVendor); + enum_ctrl->graceful_exit = true; + return false; + } + + // Set configuration descriptor + if ((enum_config_index == 0) || (enum_config_index > device_desc->bNumConfigurations)) { + ESP_LOGW(HUB_DRIVER_TAG, "bConfigurationValue %d provided by user, device will be configured with configuration descriptor 1", enum_config_index); + enum_ctrl->enum_config_index = ENUM_CONFIG_INDEX_DEFAULT; + } else { + enum_ctrl->enum_config_index = enum_config_index - 1; + } + #else // ENABLE_ENUM_FILTER_CALLBACK + enum_ctrl->enum_config_index = ENUM_CONFIG_INDEX_DEFAULT; + #endif // ENABLE_ENUM_FILTER_CALLBACK + + return true; +} + static bool enum_stage_transfer(enum_ctrl_t *enum_ctrl) { usb_transfer_t *transfer = &enum_ctrl->urb->transfer; @@ -351,7 +398,7 @@ static bool enum_stage_transfer(enum_ctrl_t *enum_ctrl) } case ENUM_STAGE_GET_SHORT_CONFIG_DESC: { // Get a short config descriptor at index 0 - USB_SETUP_PACKET_INIT_GET_CONFIG_DESC((usb_setup_packet_t *)transfer->data_buffer, ENUM_CONFIG_INDEX, ENUM_SHORT_DESC_REQ_LEN); + USB_SETUP_PACKET_INIT_GET_CONFIG_DESC((usb_setup_packet_t *)transfer->data_buffer, enum_ctrl->enum_config_index, ENUM_SHORT_DESC_REQ_LEN); transfer->num_bytes = sizeof(usb_setup_packet_t) + usb_round_up_to_mps(ENUM_SHORT_DESC_REQ_LEN, enum_ctrl->bMaxPacketSize0); // IN data stage should return exactly ENUM_SHORT_DESC_REQ_LEN bytes enum_ctrl->expect_num_bytes = sizeof(usb_setup_packet_t) + ENUM_SHORT_DESC_REQ_LEN; @@ -359,7 +406,7 @@ static bool enum_stage_transfer(enum_ctrl_t *enum_ctrl) } case ENUM_STAGE_GET_FULL_CONFIG_DESC: { // Get the full configuration descriptor at index 0, requesting its exact length. - USB_SETUP_PACKET_INIT_GET_CONFIG_DESC((usb_setup_packet_t *)transfer->data_buffer, ENUM_CONFIG_INDEX, enum_ctrl->wTotalLength); + USB_SETUP_PACKET_INIT_GET_CONFIG_DESC((usb_setup_packet_t *)transfer->data_buffer, enum_ctrl->enum_config_index, enum_ctrl->wTotalLength); transfer->num_bytes = sizeof(usb_setup_packet_t) + usb_round_up_to_mps(enum_ctrl->wTotalLength, enum_ctrl->bMaxPacketSize0); // IN data stage should return exactly wTotalLength bytes enum_ctrl->expect_num_bytes = sizeof(usb_setup_packet_t) + enum_ctrl->wTotalLength; @@ -497,7 +544,7 @@ static bool enum_stage_transfer_check(enum_ctrl_t *enum_ctrl) enum_ctrl->iManufacturer = device_desc->iManufacturer; enum_ctrl->iProduct = device_desc->iProduct; enum_ctrl->iSerialNumber = device_desc->iSerialNumber; - ret = true; + ret = set_config_index(enum_ctrl, device_desc); break; } case ENUM_STAGE_CHECK_SHORT_CONFIG_DESC: { @@ -924,7 +971,15 @@ static void enum_handle_events(void) if (stage_pass) { ESP_LOGD(HUB_DRIVER_TAG, "Stage done: %s", enum_stage_strings[enum_ctrl->stage]); } else { - ESP_LOGE(HUB_DRIVER_TAG, "Stage failed: %s", enum_stage_strings[enum_ctrl->stage]); + #ifdef ENABLE_ENUM_FILTER_CALLBACK + if (!enum_ctrl->graceful_exit) { + ESP_LOGE(HUB_DRIVER_TAG, "Stage failed: %s", enum_stage_strings[enum_ctrl->stage]); + } else { + ESP_LOGD(HUB_DRIVER_TAG, "Stage done: %s", enum_stage_strings[enum_ctrl->stage]); + } + #else // ENABLE_ENUM_FILTER_CALLBACK + ESP_LOGE(HUB_DRIVER_TAG, "Stage failed: %s", enum_stage_strings[enum_ctrl->stage]); + #endif // ENABLE_ENUM_FILTER_CALLBACK } enum_set_next_stage(enum_ctrl, stage_pass); } @@ -959,9 +1014,13 @@ esp_err_t hub_install(hub_config_t *hub_config) hub_driver_obj->dynamic.driver_state = HUB_DRIVER_STATE_INSTALLED; hub_driver_obj->single_thread.enum_ctrl.stage = ENUM_STAGE_NONE; hub_driver_obj->single_thread.enum_ctrl.urb = enum_urb; + #ifdef ENABLE_ENUM_FILTER_CALLBACK + hub_driver_obj->single_thread.enum_ctrl.enum_filter_cb = hub_config->enum_filter_cb; + #endif // ENABLE_ENUM_FILTER_CALLBACK hub_driver_obj->constant.root_port_hdl = port_hdl; hub_driver_obj->constant.proc_req_cb = hub_config->proc_req_cb; hub_driver_obj->constant.proc_req_cb_arg = hub_config->proc_req_cb_arg; + HUB_DRIVER_ENTER_CRITICAL(); if (p_hub_driver_obj != NULL) { HUB_DRIVER_EXIT_CRITICAL(); diff --git a/components/usb/include/usb/usb_host.h b/components/usb/include/usb/usb_host.h index 89cc88cbc9e8..ba44c584d17b 100644 --- a/components/usb/include/usb/usb_host.h +++ b/components/usb/include/usb/usb_host.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -106,6 +106,8 @@ typedef struct { set this if they want to use an external USB PHY. Otherwise, the USB Host Library will automatically configure the internal USB PHY */ int intr_flags; /**< Interrupt flags for the underlying ISR used by the USB Host stack */ + usb_host_enum_filter_cb_t enum_filter_cb; /**< Enumeration filter callback. Enable CONFIG_USB_HOST_ENABLE_ENUM_FILTER_CALLBACK + to use this feature. Set to NULL otherwise. */ } usb_host_config_t; /** diff --git a/components/usb/include/usb/usb_types_stack.h b/components/usb/include/usb/usb_types_stack.h index 00af897182cf..8b351063f4bf 100644 --- a/components/usb/include/usb/usb_types_stack.h +++ b/components/usb/include/usb/usb_types_stack.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 */ @@ -10,6 +10,7 @@ Warning: The USB Host Library API is still a beta version and may be subject to #pragma once +#include #include "usb/usb_types_ch9.h" #ifdef __cplusplus @@ -46,6 +47,29 @@ typedef enum { */ typedef struct usb_device_handle_s *usb_device_handle_t; +/** + * @brief Enumeration filter callback + * + * This callback is called at the beginning of the enumeration process for a newly attached device. + * Through this callback, users are able to: + * + * - filter which devices should be enumerated + * - select the configuration number to use when enumerating the device + * + * The device descriptor is passed to this callback to allow users to filter devices based on + * Vendor ID, Product ID, and class code. + * + * @attention This callback must be non-blocking + * @attention This callback must not submit any USB transfers + * @param[in] dev_desc Device descriptor of the device to enumerate + * @param[out] bConfigurationValue Configuration number to use when enumerating the device (starts with 1) + * + * @return bool + * - true: USB device will be enumerated + * - false: USB device will not be enumerated + */ +typedef bool (*usb_host_enum_filter_cb_t)(const usb_device_desc_t *dev_desc, uint8_t *bConfigurationValue); + /** * @brief Basic information of an enumerated device */ diff --git a/components/usb/private_include/hub.h b/components/usb/private_include/hub.h index 1a8807bf51e4..dac89b7ea738 100644 --- a/components/usb/private_include/hub.h +++ b/components/usb/private_include/hub.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -8,6 +8,7 @@ #include #include +#include "sdkconfig.h" #include "esp_err.h" #include "usb_private.h" #include "usbh.h" @@ -22,8 +23,11 @@ extern "C" { * @brief Hub driver configuration */ typedef struct { - usb_proc_req_cb_t proc_req_cb; /**< Processing request callback */ - void *proc_req_cb_arg; /**< Processing request callback argument */ + usb_proc_req_cb_t proc_req_cb; /**< Processing request callback */ + void *proc_req_cb_arg; /**< Processing request callback argument */ +#ifdef CONFIG_USB_HOST_ENABLE_ENUM_FILTER_CALLBACK + usb_host_enum_filter_cb_t enum_filter_cb; /**< Set device configuration callback */ +#endif // CONFIG_USB_HOST_ENABLE_ENUM_FILTER_CALLBACK } hub_config_t; // ---------------------------------------------- Hub Driver Functions ------------------------------------------------- diff --git a/components/usb/usb_host.c b/components/usb/usb_host.c index cfea392a4323..8328927952c8 100644 --- a/components/usb/usb_host.c +++ b/components/usb/usb_host.c @@ -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 */ @@ -10,6 +10,7 @@ Warning: The USB Host Library API is still a beta version and may be subject to #include #include +#include "sdkconfig.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/queue.h" @@ -47,6 +48,10 @@ static portMUX_TYPE host_lock = portMUX_INITIALIZER_UNLOCKED; #define PROCESS_REQUEST_PENDING_FLAG_USBH 0x01 #define PROCESS_REQUEST_PENDING_FLAG_HUB 0x02 +#ifdef CONFIG_USB_HOST_ENABLE_ENUM_FILTER_CALLBACK +#define ENABLE_ENUM_FILTER_CALLBACK +#endif // CONFIG_USB_HOST_ENABLE_ENUM_FILTER_CALLBACK + typedef struct ep_wrapper_s ep_wrapper_t; typedef struct interface_s interface_t; typedef struct client_s client_t; @@ -404,10 +409,18 @@ esp_err_t usb_host_install(const usb_host_config_t *config) goto usbh_err; } +#ifdef ENABLE_ENUM_FILTER_CALLBACK + if (config->enum_filter_cb == NULL) { + ESP_LOGW(USB_HOST_TAG, "User callback to set USB device configuration is enabled, but not used"); + } +#endif // ENABLE_ENUM_FILTER_CALLBACK // Install Hub hub_config_t hub_config = { .proc_req_cb = proc_req_callback, .proc_req_cb_arg = NULL, +#ifdef ENABLE_ENUM_FILTER_CALLBACK + .enum_filter_cb = config->enum_filter_cb, +#endif // ENABLE_ENUM_FILTER_CALLBACK }; ret = hub_install(&hub_config); if (ret != ESP_OK) { diff --git a/components/usb/usb_phy.c b/components/usb/usb_phy.c index 457769eb175e..5e546e164795 100644 --- a/components/usb/usb_phy.c +++ b/components/usb/usb_phy.c @@ -12,8 +12,8 @@ #include "esp_private/periph_ctrl.h" #include "esp_private/usb_phy.h" #include "soc/usb_otg_periph.h" -#include "hal/usb_phy_hal.h" -#include "hal/usb_phy_ll.h" +#include "hal/usb_fsls_phy_hal.h" +#include "hal/usb_fsls_phy_ll.h" #include "esp_rom_gpio.h" #include "driver/gpio.h" #include "hal/gpio_ll.h" @@ -39,7 +39,7 @@ struct phy_context_t { usb_otg_mode_t otg_mode; /**< USB OTG mode */ usb_phy_speed_t otg_speed; /**< USB speed */ usb_phy_ext_io_conf_t *iopins; /**< external PHY I/O pins */ - usb_phy_hal_context_t hal_context; /**< USB_PHY hal context */ + usb_fsls_phy_hal_context_t hal_context; /**< USB_PHY hal context */ }; typedef struct { @@ -126,7 +126,7 @@ esp_err_t usb_phy_otg_set_mode(usb_phy_handle_t handle, usb_otg_mode_t mode) esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, USB_OTG_VBUSVALID_IN_IDX, false); // receiving a valid Vbus from host esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, USB_OTG_AVALID_IN_IDX, false); // HIGH to force USB host mode if (handle->target == USB_PHY_TARGET_INT) { - usb_phy_hal_int_load_conf_host(&(handle->hal_context)); + usb_fsls_phy_hal_int_load_conf_host(&(handle->hal_context)); } } else if (mode == USB_OTG_MODE_DEVICE) { esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, USB_OTG_IDDIG_IN_IDX, false); // connected connector is mini-B side @@ -147,7 +147,7 @@ esp_err_t usb_phy_otg_dev_set_speed(usb_phy_handle_t handle, usb_phy_speed_t spe USBPHY_TAG, "set speed not supported"); handle->otg_speed = speed; - usb_phy_hal_int_load_conf_dev(&(handle->hal_context), speed); + usb_fsls_phy_hal_int_load_conf_dev(&(handle->hal_context), speed); return ESP_OK; } @@ -163,7 +163,7 @@ esp_err_t usb_phy_action(usb_phy_handle_t handle, usb_phy_action_t action) switch (action) { case USB_PHY_ACTION_HOST_ALLOW_CONN: if (handle->target == USB_PHY_TARGET_INT) { - usb_phy_hal_int_mimick_disconn(&(handle->hal_context), false); + usb_fsls_phy_hal_int_mimick_disconn(&(handle->hal_context), false); } else { if (!handle->iopins) { ret = ESP_FAIL; @@ -180,7 +180,7 @@ esp_err_t usb_phy_action(usb_phy_handle_t handle, usb_phy_action_t action) case USB_PHY_ACTION_HOST_FORCE_DISCONN: if (handle->target == USB_PHY_TARGET_INT) { - usb_phy_hal_int_mimick_disconn(&(handle->hal_context), true); + usb_fsls_phy_hal_int_mimick_disconn(&(handle->hal_context), true); } else { /* Disable connections on the external PHY by connecting the VP and VM signals to the constant LOW signal. @@ -223,8 +223,8 @@ static esp_err_t usb_phy_install(void) // Enable USB peripheral and reset the register portEXIT_CRITICAL(&phy_spinlock); USB_WRAP_RCC_ATOMIC() { - usb_phy_ll_usb_wrap_enable_bus_clock(true); - usb_phy_ll_usb_wrap_reset_register(); + usb_fsls_phy_ll_usb_wrap_enable_bus_clock(true); + usb_fsls_phy_ll_usb_wrap_reset_register(); } return ESP_OK; @@ -263,13 +263,13 @@ esp_err_t usb_new_phy(const usb_phy_config_t *config, usb_phy_handle_t *handle_r phy_context->controller = config->controller; phy_context->status = USB_PHY_STATUS_IN_USE; - usb_phy_hal_init(&(phy_context->hal_context)); + usb_fsls_phy_hal_init(&(phy_context->hal_context)); if (config->controller == USB_PHY_CTRL_OTG) { - usb_phy_hal_otg_conf(&(phy_context->hal_context), config->target == USB_PHY_TARGET_EXT); + usb_fsls_phy_hal_otg_conf(&(phy_context->hal_context), config->target == USB_PHY_TARGET_EXT); } #if SOC_USB_SERIAL_JTAG_SUPPORTED else if (config->controller == USB_PHY_CTRL_SERIAL_JTAG) { - usb_phy_hal_jtag_conf(&(phy_context->hal_context), config->target == USB_PHY_TARGET_EXT); + usb_fsls_phy_hal_jtag_conf(&(phy_context->hal_context), config->target == USB_PHY_TARGET_EXT); phy_context->otg_mode = USB_OTG_MODE_DEVICE; phy_context->otg_speed = USB_PHY_SPEED_FULL; } @@ -317,7 +317,7 @@ static void phy_uninstall(void) p_phy_ctrl_obj = NULL; USB_WRAP_RCC_ATOMIC() { // Disable USB peripheral without reset the module - usb_phy_ll_usb_wrap_enable_bus_clock(false); + usb_fsls_phy_ll_usb_wrap_enable_bus_clock(false); } } portEXIT_CRITICAL(&phy_spinlock); @@ -334,8 +334,8 @@ esp_err_t usb_del_phy(usb_phy_handle_t handle) p_phy_ctrl_obj->external_phy = NULL; } else { // Clear pullup and pulldown loads on D+ / D-, and disable the pads - usb_phy_ll_int_load_conf(handle->hal_context.wrap_dev, false, false, false, false); - usb_phy_ll_usb_wrap_pad_enable(handle->hal_context.wrap_dev, false); + usb_fsls_phy_ll_int_load_conf(handle->hal_context.wrap_dev, false, false, false, false); + usb_fsls_phy_ll_usb_wrap_pad_enable(handle->hal_context.wrap_dev, false); p_phy_ctrl_obj->internal_phy = NULL; } portEXIT_CRITICAL(&phy_spinlock); diff --git a/components/vfs/test_apps/.build-test-rules.yml b/components/vfs/test_apps/.build-test-rules.yml new file mode 100644 index 000000000000..6f8e89a2a642 --- /dev/null +++ b/components/vfs/test_apps/.build-test-rules.yml @@ -0,0 +1,12 @@ +components/vfs/test_apps: + disable_test: + - if: IDF_TARGET not in ["esp32", "esp32c2", "esp32c3", "esp32c6", "esp32h2", "esp32s3"] + temporary: true + reason: lack of runners + + depends_components: + - vfs + - fatfs + - spiffs + - console + - driver diff --git a/components/vfs/test_apps/pytest_vfs.py b/components/vfs/test_apps/pytest_vfs.py index 92c19370a3f6..5e471f1518f7 100644 --- a/components/vfs/test_apps/pytest_vfs.py +++ b/components/vfs/test_apps/pytest_vfs.py @@ -9,7 +9,6 @@ @pytest.mark.esp32c3 @pytest.mark.esp32c6 @pytest.mark.esp32h2 -@pytest.mark.generic @pytest.mark.parametrize('config', [ 'default', 'iram', ], indirect=True) @@ -18,8 +17,7 @@ def test_vfs_default(dut: Dut) -> None: @pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.generic +@pytest.mark.esp32c3 @pytest.mark.parametrize('config', [ 'ccomp', ], indirect=True) diff --git a/docs/docs_not_updated/esp32p4.txt b/docs/docs_not_updated/esp32p4.txt index 90faae64ceb0..96acd4b10cb6 100644 --- a/docs/docs_not_updated/esp32p4.txt +++ b/docs/docs_not_updated/esp32p4.txt @@ -74,7 +74,6 @@ api-reference/peripherals/lcd.rst api-reference/peripherals/ana_cmpr.rst api-reference/peripherals/temp_sensor.rst api-reference/peripherals/sdio_slave.rst -api-reference/peripherals/clk_tree.rst api-reference/peripherals/spi_flash/xip_from_psram.inc api-reference/peripherals/spi_flash/spi_flash_concurrency.rst api-reference/peripherals/spi_flash/spi_flash_override_driver.rst diff --git a/docs/doxygen/Doxyfile b/docs/doxygen/Doxyfile index d92b07e169c0..73bb40674718 100644 --- a/docs/doxygen/Doxyfile +++ b/docs/doxygen/Doxyfile @@ -73,9 +73,6 @@ INPUT = \ $(PROJECT_PATH)/components/bt/host/bluedroid/api/include/api/esp_spp_api.h \ $(PROJECT_PATH)/components/bt/host/nimble/esp-hci/include/esp_nimble_hci.h \ $(PROJECT_PATH)/components/console/esp_console.h \ - $(PROJECT_PATH)/components/driver/ledc/include/driver/ledc.h \ - $(PROJECT_PATH)/components/driver/parlio/include/driver/parlio_tx.h \ - $(PROJECT_PATH)/components/driver/parlio/include/driver/parlio_types.h \ $(PROJECT_PATH)/components/driver/touch_sensor/include/driver/touch_sensor_common.h \ $(PROJECT_PATH)/components/driver/twai/include/driver/twai.h \ $(PROJECT_PATH)/components/driver/test_apps/components/esp_serial_slave_link/include/esp_serial_slave_link/essl_sdio.h \ @@ -108,6 +105,7 @@ INPUT = \ $(PROJECT_PATH)/components/esp_driver_gptimer/include/driver/gptimer.h \ $(PROJECT_PATH)/components/esp_driver_gptimer/include/driver/gptimer_etm.h \ $(PROJECT_PATH)/components/esp_driver_gptimer/include/driver/gptimer_types.h \ + $(PROJECT_PATH)/components/esp_driver_ledc/include/driver/ledc.h \ $(PROJECT_PATH)/components/esp_driver_mcpwm/include/driver/mcpwm_cap.h \ $(PROJECT_PATH)/components/esp_driver_mcpwm/include/driver/mcpwm_cmpr.h \ $(PROJECT_PATH)/components/esp_driver_mcpwm/include/driver/mcpwm_etm.h \ @@ -117,6 +115,9 @@ INPUT = \ $(PROJECT_PATH)/components/esp_driver_mcpwm/include/driver/mcpwm_sync.h \ $(PROJECT_PATH)/components/esp_driver_mcpwm/include/driver/mcpwm_timer.h \ $(PROJECT_PATH)/components/esp_driver_mcpwm/include/driver/mcpwm_types.h \ + $(PROJECT_PATH)/components/esp_driver_parlio/include/driver/parlio_rx.h \ + $(PROJECT_PATH)/components/esp_driver_parlio/include/driver/parlio_tx.h \ + $(PROJECT_PATH)/components/esp_driver_parlio/include/driver/parlio_types.h \ $(PROJECT_PATH)/components/esp_driver_i2c/include/driver/i2c_master.h \ $(PROJECT_PATH)/components/esp_driver_i2c/include/driver/i2c_slave.h \ $(PROJECT_PATH)/components/esp_driver_i2c/include/driver/i2c_types.h \ diff --git a/docs/en/api-guides/coexist.rst b/docs/en/api-guides/coexist.rst index d0a626097a64..8ffd53f036ce 100644 --- a/docs/en/api-guides/coexist.rst +++ b/docs/en/api-guides/coexist.rst @@ -246,6 +246,7 @@ Setting Coexistence Compile-time Options #) :ref:`CONFIG_LWIP_TCP_SND_BUF_DEFAULT`: reduce the default TX buffer size for TCP sockets. #) :ref:`CONFIG_LWIP_TCP_WND_DEFAULT`: reduce the default size of the RX window for TCP sockets. #) :ref:`CONFIG_LWIP_TCP_RECVMBOX_SIZE`: reduce the size of the TCP receive mailbox. + #) :ref:`CONFIG_LWIP_TCP_ACCEPTMBOX_SIZE`: reduce the size of the TCP accept mailbox. #) :ref:`CONFIG_LWIP_UDP_RECVMBOX_SIZE`: reduce the size of the UDP receive mailbox. #) :ref:`CONFIG_LWIP_TCPIP_RECVMBOX_SIZE`: reduce the size of TCPIP task receive mailbox. diff --git a/docs/en/api-guides/external-ram.rst b/docs/en/api-guides/external-ram.rst index 5b397184ed6b..7fdaa2baeb24 100644 --- a/docs/en/api-guides/external-ram.rst +++ b/docs/en/api-guides/external-ram.rst @@ -32,8 +32,7 @@ Hardware Some PSRAM chips are 1.8 V devices and some are 3.3 V. Consult the datasheet for your PSRAM chip and {IDF_TARGET_NAME} device to find out the working voltages. - By default PSRAM is powered up by the on-chip LDO2, you can use :ref:`CONFIG_ESP_VDD_PSRAM_LDO_ID` to switch the LDO ID according. Setting this value to -1 for using external power supply, this means the on-chip LDO will not be used. - By default PSRAM connected LDO is set to correct voltage according to the used Espressif module. You can still use :ref:`CONFIG_ESP_VDD_PSRAM_LDO_VOLTAGE_MV` to select LDO output voltage if you do not use an Espressif module. When using external power supply, this option does not exist. + By default, the PSRAM is powered up by the on-chip LDO2. You can use :ref:`CONFIG_ESP_VDD_PSRAM_LDO_ID` to switch the LDO ID accordingly. Set this value to -1 to use an external power supply, which means the on-chip LDO will not be used. By default, the PSRAM connected to LDO is set to the correct voltage based on the Espressif module used. You can still use :ref:`CONFIG_ESP_VDD_PSRAM_LDO_VOLTAGE_MV` to select the LDO output voltage if you are not using an Espressif module. When using an external power supply, this option does not exist. .. note:: diff --git a/docs/en/api-guides/lwip.rst b/docs/en/api-guides/lwip.rst index 58fef8a3e01f..0691d389bc07 100644 --- a/docs/en/api-guides/lwip.rst +++ b/docs/en/api-guides/lwip.rst @@ -503,6 +503,7 @@ Most lwIP RAM usage is on-demand, as RAM is allocated from the heap as needed. T - Reducing :ref:`CONFIG_LWIP_MAX_SOCKETS` reduces the maximum number of sockets in the system. This also causes TCP sockets in the ``WAIT_CLOSE`` state to be closed and recycled more rapidly when needed to open a new socket, further reducing peak RAM usage. - Reducing :ref:`CONFIG_LWIP_TCPIP_RECVMBOX_SIZE`, :ref:`CONFIG_LWIP_TCP_RECVMBOX_SIZE` and :ref:`CONFIG_LWIP_UDP_RECVMBOX_SIZE` reduce RAM usage at the expense of throughput, depending on usage. +- Reducing :ref:`CONFIG_LWIP_TCP_ACCEPTMBOX_SIZE` reduce RAM usage by limiting concurrent accepted connections. - Reducing :ref:`CONFIG_LWIP_TCP_MSL` and :ref:`CONFIG_LWIP_TCP_FIN_WAIT_TIMEOUT` reduces the maximum segment lifetime in the system. This also causes TCP sockets in the ``TIME_WAIT`` and ``FIN_WAIT_2`` states to be closed and recycled more rapidly. - Disabling :ref:`CONFIG_LWIP_IPV6` can save about 39 KB for firmware size and 2 KB RAM when the system is powered up and 7 KB RAM when the TCP/IP stack is running. If there is no requirement for supporting IPV6, it can be disabled to save flash and RAM footprint. - Disabling :ref:`CONFIG_LWIP_IPV4` can save about 26 KB of firmware size and 600 B RAM on power up and 6 KB RAM when the TCP/IP stack is running. If the local network supports IPv6-only configuration, IPv4 can be disabled to save flash and RAM footprint. diff --git a/docs/en/api-guides/wifi.rst b/docs/en/api-guides/wifi.rst index 3146a30d4090..9c1b4d0fe853 100644 --- a/docs/en/api-guides/wifi.rst +++ b/docs/en/api-guides/wifi.rst @@ -1160,9 +1160,21 @@ Following reason codes are renamed to their shorter form to wrap the table in pa - 210 - Espressif-specific Wi-Fi reason code: NO_AP_FOUND_W_COMPATIBLE_SECURITY will be reported if an AP that fits identifying criteria (e.g. ssid) is found but the connection is rejected due to incompatible security configuration. These situations could be: - - bss offering WEP, but our password is not WEP compliant - - Encrypted AP bss but we have but no password config set - - AP is Enterprise but we haven't setup enterprise config, and vice versa + - The Access Point is offering WEP security, but our station's password is not WEP-compliant. + - The station is configured in Open mode; however, the Access Point is broadcasting in secure mode. + - The Access Point uses Enterprise security, but we haven't set up the corresponding enterprise configuration, and vice versa. + - SAE-PK is configured in the station configuration, but the Access Point does not support SAE-PK. + - SAE-H2E is configured in the station configuration; however, the AP only supports WPA3-PSK or WPA3-WPA2-PSK. + - The station is configured in secure mode (Password or Enterprise mode); however, an Open AP is found during the scan. + - SAE HnP is configured in the station configuration; however, the AP supports H2E only. + - H2E is disabled in the station configuration; however, the AP is WPA3-EXT-PSK, which requires H2E support. + - The Access Point requires PMF, but the station is not configured for PMF capable/required. + - The station configuration requires PMF, but the AP is not configured for PMF capable/required. + - The Access Point is using unsupported group management/pairwise ciphers. + - OWE is not enabled in the station configuration, but the discovered AP is using OWE only mode. + - The Access Point is broadcasting an invalid RSNXE in its beacons. + - The Access Point is in Independent BSS mode. + * - NO_AP_FOUND_AUTHMODE - 211 - Espressif-specific Wi-Fi reason code: NO_AP_FOUND_IN_AUTHMODE_THRESHOLD will be reported if an AP that fit identifying criteria (e.g. ssid) is found but the authmode threhsold set in the wifi_config_t is not met. diff --git a/docs/en/api-reference/peripherals/clk_tree.rst b/docs/en/api-reference/peripherals/clk_tree.rst index 0784c062f470..1b43c0e7c4b6 100644 --- a/docs/en/api-reference/peripherals/clk_tree.rst +++ b/docs/en/api-reference/peripherals/clk_tree.rst @@ -3,15 +3,15 @@ Clock Tree :link_to_translation:`zh_CN:[中文]` -{IDF_TARGET_RC_FAST_VAGUE_FREQ: default="8", esp32c3="17.5", esp32s3="17.5", esp32c2="17.5", esp32c6="17.5"} +{IDF_TARGET_RC_FAST_VAGUE_FREQ: default="17.5", esp32="8", esp32s2="8", esp32h2="8"} -{IDF_TARGET_RC_FAST_ADJUSTED_FREQ: default="8.5", esp32c3="17.5", esp32s3="17.5", esp32c2="17.5", esp32c6="17.5"} +{IDF_TARGET_RC_FAST_ADJUSTED_FREQ: default="17.5", esp32="8.5", esp32s2="8.5", esp32h2="8.5"} {IDF_TARGET_XTAL_FREQ: default="40", esp32="2 ~ 40", esp32c2="40/26", esp32h2="32"} {IDF_TARGET_RC_SLOW_VAGUE_FREQ: default="136", esp32="150", esp32s2="90"} -{IDF_TARGET_RC_SLOW_CLK: default="GPIO0", esp32c2="pin0 (when its frequency is no more than 136 kHz)", "esp32c6="GPIO0", esp32h2="GPIO13"} +{IDF_TARGET_OSC_SLOW_PIN: default="GPIO0", esp32c2="pin0 (when its frequency is no more than 136 kHz)", "esp32c6="GPIO0", esp32h2="GPIO13"} The clock subsystem of {IDF_TARGET_NAME} is used to source and distribute system/module clocks from a range of root clocks. The clock tree driver maintains the basic functionality of the system clock and the intricate relationship among module clocks. @@ -63,7 +63,11 @@ Root clocks generate reliable clock signals. These clock signals then pass throu The clock source for this ``XTAL32K_CLK`` can be either a 32 kHz crystal connecting to the ``32K_XP`` and ``32K_XN`` pins or a 32 kHz clock signal generated by an external circuit. The external signal must be connected to the ``32K_XN`` pin. Additionally, a 1 nF capacitor must be placed between the ``32K_XP`` pin and ground. In this case, the ``32K_XP`` pin cannot be used as a GPIO pin. - .. only:: not esp32 + .. only:: esp32p4 + + The clock source for this ``XTAL32K_CLK`` is a 32 kHz crystal connecting to the ``XTAL_32K_P`` and ``XTAL_32K_N`` pins. + + .. only:: not esp32 and not esp32p4 The clock source for this ``XTAL32K_CLK`` can be either a 32 kHz crystal connecting to the ``XTAL_32K_P`` and ``XTAL_32K_N`` pins or a 32 kHz clock signal generated by an external circuit. The external signal must be connected to the ``XTAL_32K_P`` pin. @@ -73,7 +77,7 @@ Root clocks generate reliable clock signals. These clock signals then pass throu - External Slow Clock - optional (OSC_SLOW) - A clock signal generated by an external circuit can be connected to {IDF_TARGET_RC_SLOW_CLK} to be the clock source for the ``RTC_SLOW_CLK``. This clock can also be calibrated to get its exact frequency. + A clock signal generated by an external circuit can be connected to {IDF_TARGET_OSC_SLOW_PIN} to be the clock source for the ``RTC_SLOW_CLK``. This clock can also be calibrated to get its exact frequency. .. only:: SOC_CLK_RC32K_SUPPORTED diff --git a/docs/en/api-reference/peripherals/parlio.rst b/docs/en/api-reference/peripherals/parlio.rst index cd8318e6821d..8ef04c6e950c 100644 --- a/docs/en/api-reference/peripherals/parlio.rst +++ b/docs/en/api-reference/peripherals/parlio.rst @@ -6,22 +6,21 @@ Introduction The Parallel IO peripheral is a general purpose parallel interface that can be used to connect to external devices such as LED matrix, LCD display, Printer and Camera. The peripheral has independent TX and RX units. Each unit can have up to 8 or 16 data signals plus 1 or 2 clock signals. [1]_ -.. warning:: - - At the moment, the Parallel IO driver only supports TX mode. The RX feature is still working in progress. - +The TX and RX driver of Parallel IO peripheral are designed separately, you can include ``driver/parlio_tx.h`` or ``driver/parlio_rx.h`` to use any of them. Application Examples -------------------- -* Simple REG LED Matrix with HUB75 interface: :example:`peripherals/parlio/simple_rgb_led_matrix`. +* Simple REG LED Matrix with HUB75 interface: :example:`peripherals/parlio/parlio_tx/simple_rgb_led_matrix`. +* Logic Analyzer: :example:`peripherals/parlio/parlio_rx/logic_analyzer`. API Reference ------------- .. include-build-file:: inc/parlio_tx.inc -.. include-build-file:: inc/components/driver/parlio/include/driver/parlio_types.inc +.. include-build-file:: inc/parlio_rx.inc +.. include-build-file:: inc/components/esp_driver_parlio/include/driver/parlio_types.inc .. include-build-file:: inc/components/hal/include/hal/parlio_types.inc .. [1] diff --git a/docs/en/api-reference/protocols/esp_http_client.rst b/docs/en/api-reference/protocols/esp_http_client.rst index 8a487c69a1d1..9cb1e13561dd 100644 --- a/docs/en/api-reference/protocols/esp_http_client.rst +++ b/docs/en/api-reference/protocols/esp_http_client.rst @@ -83,7 +83,7 @@ ESP HTTP client supports both **Basic** and **Digest** Authentication. * Users can provide the username and password in the ``url`` or the ``username`` and ``password`` members of the ``esp_http_client_config_t`` configuration. For ``auth_type = HTTP_AUTH_TYPE_BASIC``, the HTTP client takes only one perform operation to pass the authentication process. * If ``auth_type = HTTP_AUTH_TYPE_NONE``, but the ``username`` and ``password`` fields are present in the configuration, the HTTP client takes two perform operations. The client will receive the ``401 Unauthorized`` header in its first attempt to connect to the server. Based on this information, it decides which authentication method to choose and performs it in the second operation. * Check out the example functions ``http_auth_basic``, ``http_auth_basic_redirect`` (for Basic authentication) and ``http_auth_digest`` (for Digest authentication) in the application example for implementation details. - * Currently, only MD5 and SHA-256 algorithms are supported with Digest authentication. + * Currently, Digest authentication supports only MD5 and SHA-256 algorithms. Examples of Authentication Configuration diff --git a/docs/en/api-reference/system/freertos.rst b/docs/en/api-reference/system/freertos.rst index db18a5813161..92a5ef0932fb 100644 --- a/docs/en/api-reference/system/freertos.rst +++ b/docs/en/api-reference/system/freertos.rst @@ -49,7 +49,7 @@ Vanilla FreeRTOS requires that ports and applications configure the kernel by ad For the full list of user configurable kernel options, see :doc:`/api-reference/kconfig`. The list below highlights some commonly used kernel configuration options: -- :ref:`CONFIG_FREERTOS_UNICORE` runs FreeRTOS only on CPU0. Note that this is **not equivalent to running Vanilla FreeRTOS**. Furthermore, this option may affect behavior of components other than :component:`freertos`. For more details regarding the effects of running FreeRTOS on a single core, refer to :ref:`freertos-smp-single-core` (if using ESP-IDF FreeRTOS) or the official Amazon SMP FreeRTOS documentation. Alternatively, users can also search for occurrences of ``CONFIG_FREERTOS_UNICORE`` in the ESP-IDF components. +- :ref:`CONFIG_FREERTOS_UNICORE` runs FreeRTOS only on Core 0. Note that this is **not equivalent to running Vanilla FreeRTOS**. Furthermore, this option may affect behavior of components other than :component:`freertos`. For more details regarding the effects of running FreeRTOS on a single core, refer to :ref:`freertos-idf-single-core` (if using ESP-IDF FreeRTOS) or the official Amazon SMP FreeRTOS documentation. Alternatively, users can also search for occurrences of ``CONFIG_FREERTOS_UNICORE`` in the ESP-IDF components. .. only:: not SOC_HP_CPU_HAS_MULTIPLE_CORES @@ -95,7 +95,7 @@ During startup, ESP-IDF and the FreeRTOS kernel automatically create multiple ta - Affinity - Priority * - Idle Tasks (``IDLEx``) - - An idle task (``IDLEx``) is created for (and pinned to) each CPU core, where ``x`` is the CPU core's number. The ``x`` is dropped when single-core configuration is enabled. + - An idle task (``IDLEx``) is created for (and pinned to) each core, where ``x`` is the core's number. ``x`` is dropped when single-core configuration is enabled. - :ref:`CONFIG_FREERTOS_IDLE_TASK_STACKSIZE` - Core x - ``0`` @@ -110,7 +110,7 @@ During startup, ESP-IDF and the FreeRTOS kernel automatically create multiple ta - :ref:`CONFIG_ESP_MAIN_TASK_AFFINITY` - ``1`` * - IPC Tasks (``ipcx``) - - When :ref:`CONFIG_FREERTOS_UNICORE` is false, an IPC task (``ipcx``) is created for (and pinned to) each CPU core. IPC tasks are used to implement the Inter-processor Call (IPC) feature. + - When :ref:`CONFIG_FREERTOS_UNICORE` is false, an IPC task (``ipcx``) is created for (and pinned to) each core. IPC tasks are used to implement the Inter-processor Call (IPC) feature. - :ref:`CONFIG_ESP_IPC_TASK_STACK_SIZE` - Core x - ``24`` diff --git a/docs/en/api-reference/system/freertos_idf.rst b/docs/en/api-reference/system/freertos_idf.rst index b85a2c52bb20..6ce4cb2fc1fa 100644 --- a/docs/en/api-reference/system/freertos_idf.rst +++ b/docs/en/api-reference/system/freertos_idf.rst @@ -1,30 +1,25 @@ -FreeRTOS (ESP-IDF) -================== +FreeRTOS (IDF) +============== :link_to_translation:`zh_CN:[中文]` +This document provides information regarding the dual-core SMP implementation of FreeRTOS inside ESP-IDF. This document is split into the following sections: + +.. contents:: Sections + :depth: 2 + .. ---------------------------------------------------- Overview ------------------------------------------------------- Overview -------- -The original FreeRTOS (hereinafter referred to as Vanilla FreeRTOS) is a compact and efficient real-time operating system supported on many single-core MCUs and SoCs. However, to support numerous dual-core ESP targets, such as ESP32, ESP32-S3, and ESP32-P4, ESP-IDF provides an implementation of FreeRTOS with dual-core symmetric multiprocessing (SMP) capabilities (hereinafter referred to as ESP-IDF FreeRTOS). - -ESP-IDF FreeRTOS is based on Vanilla FreeRTOS v10.5.1 but contains significant modifications to both API and kernel behavior in order to support dual-core SMP. This document describes the API and behavioral differences between Vanilla FreeRTOS and ESP-IDF FreeRTOS. - -.. note:: +The original FreeRTOS (hereinafter referred to as **Vanilla FreeRTOS**) is a compact and efficient real-time operating system supported on numerous single-core MCUs and SoCs. However, to support dual-core ESP targets, such as ESP32, ESP32-S3, and ESP32-P4, ESP-IDF provides a unique implementation of FreeRTOS with dual-core symmetric multiprocessing (SMP) capabilities (hereinafter referred to as **IDF FreeRTOS**). - This document assumes that the reader has a requisite understanding of Vanilla FreeRTOS, i.e., its features, behavior, and API usage. Refer to the `Vanilla FreeRTOS documentation `_ for more details. +IDF FreeRTOS source code is based on Vanilla FreeRTOS v10.5.1 but contains significant modifications to both kernel behavior and API in order to support dual-core SMP. However, IDF FreeRTOS can also be configured for single-core by enabling the :ref:`CONFIG_FREERTOS_UNICORE` option (see :ref:`freertos-idf-single-core` for more details). .. note:: - ESP-IDF FreeRTOS can be built for a single core by enabling the :ref:`CONFIG_FREERTOS_UNICORE` configuration option. ESP targets that are single core always have the :ref:`CONFIG_FREERTOS_UNICORE` option enabled. However, note that building with :ref:`CONFIG_FREERTOS_UNICORE` enabled does not equate to building with Vanilla FreeRTOS, as some of the behavioral and API changes of ESP-IDF are still present. For more details, see :ref:`freertos-smp-single-core`. - -This document is split into the following parts. - -.. contents:: Contents - :depth: 2 - + This document assumes that the reader has a requisite understanding of Vanilla FreeRTOS, i.e., its features, behavior, and API usage. Refer to the `Vanilla FreeRTOS documentation `_ for more details. .. -------------------------------------------- Symmetric Multiprocessing ---------------------------------------------- @@ -34,17 +29,17 @@ Symmetric Multiprocessing Basic Concepts ^^^^^^^^^^^^^^ -Symmetric multiprocessing is a computing architecture where two or more identical CPUs (cores) are connected to a single shared main memory and controlled by a single operating system. In general, an SMP system: +Symmetric multiprocessing is a computing architecture where two or more identical CPU cores are connected to a single shared main memory and controlled by a single operating system. In general, an SMP system: - has multiple cores running independently. Each core has its own register file, interrupts, and interrupt handling. - presents an identical view of memory to each core. Thus, a piece of code that accesses a particular memory address has the same effect regardless of which core it runs on. The main advantages of an SMP system compared to single-core or asymmetric multiprocessing systems are that: -- the presence of multiple CPUs allows for multiple hardware threads, thus increasing overall processing throughput. +- the presence of multiple cores allows for multiple hardware threads, thus increasing overall processing throughput. - having symmetric memory means that threads can switch cores during execution. This, in general, can lead to better CPU utilization. -Although an SMP system allows threads to switch cores, there are scenarios where a thread must or should only run on a particular core. Therefore, threads in an SMP system also have a core affinity that specifies which particular core the thread is allowed to run on. +Although an SMP system allows threads to switch cores, there are scenarios where a thread must/should only run on a particular core. Therefore, threads in an SMP system also have a core affinity that specifies which particular core the thread is allowed to run on. - A thread that is pinned to a particular core is only able to run on that core. - A thread that is unpinned will be allowed to switch between cores during execution instead of being pinned to a particular core. @@ -54,21 +49,17 @@ SMP on an ESP Target ESP targets such as ESP32, ESP32-S3, and ESP32-P4 are dual-core SMP SoCs. These targets have the following hardware features that make them SMP-capable: -- Two identical cores are known as CPU0 and CPU1. This means that the execution of a piece of code is identical regardless of which core it runs on. +- Two identical cores are known as Core 0 and Core 1. This means that the execution of a piece of code is identical regardless of which core it runs on. - Symmetric memory (with some small exceptions). - If multiple cores access the same memory address simultaneously, their access will be serialized by the memory bus. - True atomic access to the same memory address is achieved via an atomic compare-and-swap instruction provided by the ISA. -- Cross-core interrupts that allow one CPU to trigger an interrupt on another CPU. This allows cores to signal each other. - +- Cross-core interrupts that allow one core to trigger an interrupt on the other core. This allows cores to signal events to each other (such as requesting a context switch on the other core). -.. only:: not esp32p4 - - .. note:: - - CPU0 is also known as Protocol CPU or ``PRO_CPU`` and CPU1 is also known as Application CPU or ``APP_CPU``. The ``PRO_CPU`` and ``APP_CPU`` aliases for CPU0 and CPU1 exist in ESP-IDF as they reflect how typical ESP-IDF applications utilize the two CPUs. Typically, the tasks responsible for handling wireless networking (e.g., Wi-Fi or Bluetooth) are pinned to CPU0, thus the name ``PRO_CPU``; whereas the tasks handling the remainder of the application are pinned to CPU1, thus the name ``APP_CPU``. +.. note:: + Within ESP-IDF, Core 0 and Core 1 are sometimes referred to as ``PRO_CPU`` and ``APP_CPU`` respectively. The aliases exist in ESP-IDF as they reflect how typical ESP-IDF applications utilize the two cores. Typically, the tasks responsible for handling protocol related processing such as Wi-Fi or Bluetooth are pinned to Core 0 (thus the name ``PRO_CPU``), where as the tasks handling the remainder of the application are pinned to Core 1, (thus the name ``APP_CPU``). .. ------------------------------------------------------ Tasks -------------------------------------------------------- @@ -83,27 +74,27 @@ Vanilla FreeRTOS provides the following functions to create a task: - :cpp:func:`xTaskCreate` creates a task. The task's memory is dynamically allocated. - :cpp:func:`xTaskCreateStatic` creates a task. The task's memory is statically allocated, i.e., provided by the user. -However, in an SMP system, tasks need to be assigned a particular affinity. Therefore, ESP-IDF provides a ``PinnedToCore`` version of Vanilla FreeRTOS's task creation functions: +However, in an SMP system, tasks need to be assigned a particular affinity. Therefore, ESP-IDF provides a ``...PinnedToCore()`` version of Vanilla FreeRTOS's task creation functions: - :cpp:func:`xTaskCreatePinnedToCore` creates a task with a particular core affinity. The task's memory is dynamically allocated. - :cpp:func:`xTaskCreateStaticPinnedToCore` creates a task with a particular core affinity. The task's memory is statically allocated, i.e., provided by the user. -The ``PinnedToCore`` versions of the task creation function API differ from their vanilla counterparts by having an extra ``xCoreID`` parameter that is used to specify the created task's core affinity. The valid values for core affinity are: +The ``...PinnedToCore()`` versions of the task creation function API differ from their vanilla counterparts by having an extra ``xCoreID`` parameter that is used to specify the created task's core affinity. The valid values for core affinity are: -- ``0``, which pins the created task to CPU0 -- ``1``, which pins the created task to CPU1 -- ``tskNO_AFFINITY``, which allows the task to be run on both CPUs +- ``0``, which pins the created task to Core 0 +- ``1``, which pins the created task to Core 1 +- ``tskNO_AFFINITY``, which allows the task to be run on both cores -Note that ESP-IDF FreeRTOS still supports the vanilla versions of the task creation functions. However, these standard functions have been modified to essentially invoke their respective ``PinnedToCore`` counterparts while setting the core affinity to ``tskNO_AFFINITY``. +Note that IDF FreeRTOS still supports the vanilla versions of the task creation functions. However, these standard functions have been modified to essentially invoke their respective ``...PinnedToCore()`` counterparts while setting the core affinity to ``tskNO_AFFINITY``. .. note:: - ESP-IDF FreeRTOS also changes the units of ``ulStackDepth`` in the task creation functions. Task stack sizes in Vanilla FreeRTOS are specified in a number of words, whereas in ESP-IDF FreeRTOS, the task stack sizes are specified in bytes. + IDF FreeRTOS also changes the units of ``ulStackDepth`` in the task creation functions. Task stack sizes in Vanilla FreeRTOS are specified in a number of words, whereas in IDF FreeRTOS, the task stack sizes are specified in bytes. Execution ^^^^^^^^^ -The anatomy of a task in ESP-IDF FreeRTOS is the same as in Vanilla FreeRTOS. More specifically, ESP-IDF FreeRTOS tasks: +The anatomy of a task in IDF FreeRTOS is the same as in Vanilla FreeRTOS. More specifically, IDF FreeRTOS tasks: - Can only be in one of the following states: Running, Ready, Blocked, or Suspended. - Task functions are typically implemented as an infinite loop. @@ -114,7 +105,7 @@ Deletion Task deletion in Vanilla FreeRTOS is called via :cpp:func:`vTaskDelete`. The function allows deletion of another task or the currently running task if the provided task handle is ``NULL``. The actual freeing of the task's memory is sometimes delegated to the idle task if the task being deleted is the currently running task. -ESP-IDF FreeRTOS provides the same :cpp:func:`vTaskDelete` function. However, due to the dual-core nature, there are some behavioral differences when calling :cpp:func:`vTaskDelete` in ESP-IDF FreeRTOS: +IDF FreeRTOS provides the same :cpp:func:`vTaskDelete` function. However, due to the dual-core nature, there are some behavioral differences when calling :cpp:func:`vTaskDelete` in IDF FreeRTOS: - When deleting a task that is currently running on the other core, a yield is triggered on the other core, and the task's memory is freed by one of the idle tasks. - A deleted task's memory is freed immediately if it is not running on either core. @@ -141,50 +132,50 @@ The Vanilla FreeRTOS scheduler is best described as a **fixed priority preemptiv - The scheduler can switch execution to another task without the cooperation of the currently running task. - The scheduler periodically switches execution between ready-state tasks of the same priority in a round-robin fashion. Time slicing is governed by a tick interrupt. -The ESP-IDF FreeRTOS scheduler supports the same scheduling features, i.e., Fixed Priority, Preemption, and Time Slicing, albeit with some small behavioral differences. +The IDF FreeRTOS scheduler supports the same scheduling features, i.e., Fixed Priority, Preemption, and Time Slicing, albeit with some small behavioral differences. Fixed Priority ^^^^^^^^^^^^^^ -In Vanilla FreeRTOS, when the scheduler selects a new task to run, it always selects the current highest priority ready-state task. In ESP-IDF FreeRTOS, each core independently schedules tasks to run. When a particular core selects a task, the core will select the highest priority ready-state task that can be run by the core. A task can be run by the core if: +In Vanilla FreeRTOS, when the scheduler selects a new task to run, it always selects the current highest priority ready-state task. In IDF FreeRTOS, each core independently schedules tasks to run. When a particular core selects a task, the core will select the highest priority ready-state task that can be run by the core. A task can be run by the core if: - The task has a compatible affinity, i.e., is either pinned to that core or is unpinned. - The task is not currently being run by another core. However, please do not assume that the two highest priority ready-state tasks are always run by the scheduler, as a task's core affinity must also be accounted for. For example, given the following tasks: -- Task A of priority 10 pinned to CPU0 -- Task B of priority 9 pinned to CPU0 -- Task C of priority 8 pinned to CPU1 +- Task A of priority 10 pinned to Core 0 +- Task B of priority 9 pinned to Core 0 +- Task C of priority 8 pinned to Core 1 -The resulting schedule will have Task A running on CPU0 and Task C running on CPU1. Task B is not run even though it is the second-highest priority task. +The resulting schedule will have Task A running on Core 0 and Task C running on Core 1. Task B is not run even though it is the second-highest priority task. Preemption ^^^^^^^^^^ -In Vanilla FreeRTOS, the scheduler can preempt the currently running task if a higher priority task becomes ready to execute. Likewise in ESP-IDF FreeRTOS, each core can be individually preempted by the scheduler if the scheduler determines that a higher-priority task can run on that core. +In Vanilla FreeRTOS, the scheduler can preempt the currently running task if a higher priority task becomes ready to execute. Likewise in IDF FreeRTOS, each core can be individually preempted by the scheduler if the scheduler determines that a higher-priority task can run on that core. However, there are some instances where a higher-priority task that becomes ready can be run on multiple cores. In this case, the scheduler only preempts one core. The scheduler always gives preference to the current core when multiple cores can be preempted. In other words, if the higher priority ready task is unpinned and has a higher priority than the current priority of both cores, the scheduler will always choose to preempt the current core. For example, given the following tasks: -- Task A of priority 8 currently running on CPU0 -- Task B of priority 9 currently running on CPU1 +- Task A of priority 8 currently running on Core 0 +- Task B of priority 9 currently running on Core 1 - Task C of priority 10 that is unpinned and was unblocked by Task B -The resulting schedule will have Task A running on CPU0 and Task C preempting Task B given that the scheduler always gives preference to the current core. +The resulting schedule will have Task A running on Core 0 and Task C preempting Task B given that the scheduler always gives preference to the current core. Time Slicing ^^^^^^^^^^^^ The Vanilla FreeRTOS scheduler implements time slicing, which means that if the current highest ready priority contains multiple ready tasks, the scheduler will switch between those tasks periodically in a round-robin fashion. -However, in ESP-IDF FreeRTOS, it is not possible to implement perfect Round Robin time slicing due to the fact that a particular task may not be able to run on a particular core due to the following reasons: +However, in IDF FreeRTOS, it is not possible to implement perfect Round Robin time slicing due to the fact that a particular task may not be able to run on a particular core due to the following reasons: - The task is pinned to another core. - For unpinned tasks, the task is already being run by another core. Therefore, when a core searches the ready-state task list for a task to run, the core may need to skip over a few tasks in the same priority list or drop to a lower priority in order to find a ready-state task that the core can run. -The ESP-IDF FreeRTOS scheduler implements a Best Effort Round Robin time slicing for ready-state tasks of the same priority by ensuring that tasks that have been selected to run are placed at the back of the list, thus giving unselected tasks a higher priority on the next scheduling iteration (i.e., the next tick interrupt or yield). +The IDF FreeRTOS scheduler implements a Best Effort Round Robin time slicing for ready-state tasks of the same priority by ensuring that tasks that have been selected to run are placed at the back of the list, thus giving unselected tasks a higher priority on the next scheduling iteration (i.e., the next tick interrupt or yield). The following example demonstrates the Best Effort Round Robin time slicing in action. Assume that: @@ -196,67 +187,55 @@ The following example demonstrates the Best Effort Round Robin time slicing in a - The task list is always searched from the head. -.. code-block:: none - - -------------------------------------------------------------------------------- - - 1. Starting state. None of the ready-state tasks have been selected to run. - - Head [ AX , B0 , C1 , D0 ] Tail - - -------------------------------------------------------------------------------- - - 2. Core 0 has a tick interrupt and searches for a task to run. - - Task A is selected and moved to the back of the list. - - Core0--| - Head [ AX , B0 , C1 , D0 ] Tail +1. Starting state. None of the ready-state tasks have been selected to run. - 0 - Head [ B0 , C1 , D0 , AX ] Tail + .. code-block:: none - -------------------------------------------------------------------------------- + Head [ AX , B0 , C1 , D0 ] Tail - 3. Core 1 has a tick interrupt and searches for a task to run. +2. Core 0 has a tick interrupt and searches for a task to run. Task A is selected and moved to the back of the list. - Task B cannot be run due to incompatible affinity, so core 1 skips to Task C. + .. code-block:: none - Task C is selected and moved to the back of the list. + Core 0 ─┐ + ▼ + Head [ AX , B0 , C1 , D0 ] Tail - Core1-------| 0 - Head [ B0 , C1 , D0 , AX ] Tail + [0] + Head [ B0 , C1 , D0 , AX ] Tail - 0 1 - Head [ B0 , D0 , AX , C1 ] Tail +3. Core 1 has a tick interrupt and searches for a task to run. Task B cannot be run due to incompatible affinity, so Core 1 skips to Task C. Task C is selected and moved to the back of the list. - -------------------------------------------------------------------------------- + .. code-block:: none - 4. Core 0 has another tick interrupt and searches for a task to run. + Core 1 ──────┐ + ▼ [0] + Head [ B0 , C1 , D0 , AX ] Tail - Task B is selected and moved to the back of the list. + [0] [1] + Head [ B0 , D0 , AX , C1 ] Tail +4. Core 0 has another tick interrupt and searches for a task to run. Task B is selected and moved to the back of the list. - Core0--| 1 - Head [ B0 , D0 , AX , C1 ] Tail + .. code-block:: none - 1 0 - Head [ D0 , AX , C1 , B0 ] Tail + Core 0 ─┐ + ▼ [1] + Head [ B0 , D0 , AX , C1 ] Tail - -------------------------------------------------------------------------------- + [1] [0] + Head [ D0 , AX , C1 , B0 ] Tail - 5. Core 1 has another tick and searches for a task to run. +5. Core 1 has another tick and searches for a task to run. Task D cannot be run due to incompatible affinity, so Core 1 skips to Task A. Task A is selected and moved to the back of the list. - Task D cannot be run due to incompatible affinity, so core 1 skips to Task A. + .. code-block:: none - Task A is selected and moved to the back of the list. - - Core1-------| 0 - Head [ D0 , AX , C1 , B0 ] Tail - - 0 1 - Head [ D0 , C1 , B0 , AX ] Tail + Core 1 ──────┐ + ▼ [0] + Head [ D0 , AX , C1 , B0 ] Tail + [0] [1] + Head [ D0 , C1 , B0 , AX ] Tail The implications to users regarding the Best Effort Round Robin time slicing: @@ -275,14 +254,14 @@ Vanilla FreeRTOS requires that a periodic tick interrupt occurs. The tick interr - Checking if time slicing is required, i.e., triggering a context switch - Executing the application tick hook -In ESP-IDF FreeRTOS, each core receives a periodic interrupt and independently runs the tick interrupt. The tick interrupts on each core are of the same period but can be out of phase. However, the tick responsibilities listed above are not run by all cores: +In IDF FreeRTOS, each core receives a periodic interrupt and independently runs the tick interrupt. The tick interrupts on each core are of the same period but can be out of phase. However, the tick responsibilities listed above are not run by all cores: -- CPU0 executes all of the tick interrupt responsibilities listed above -- CPU1 only checks for time slicing and executes the application tick hook +- Core 0 executes all of the tick interrupt responsibilities listed above +- Core 1 only checks for time slicing and executes the application tick hook .. note:: - CPU0 is solely responsible for keeping time in ESP-IDF FreeRTOS. Therefore, anything that prevents CPU0 from incrementing the tick count, such as suspending the scheduler on CPU0, will cause the entire scheduler's timekeeping to lag behind. + Core 0 is solely responsible for keeping time in IDF FreeRTOS. Therefore, anything that prevents Core 0 from incrementing the tick count, such as suspending the scheduler on Core 0, will cause the entire scheduler's timekeeping to lag behind. Idle Tasks ^^^^^^^^^^ @@ -292,7 +271,7 @@ Vanilla FreeRTOS will implicitly create an idle task of priority 0 when the sche - Freeing the memory of deleted tasks - Executing the application idle hook -In ESP-IDF FreeRTOS, a separate pinned idle task is created for each core. The idle tasks on each core have the same responsibilities as their vanilla counterparts. +In IDF FreeRTOS, a separate pinned idle task is created for each core. The idle tasks on each core have the same responsibilities as their vanilla counterparts. Scheduler Suspension ^^^^^^^^^^^^^^^^^^^^ @@ -305,42 +284,35 @@ Vanilla FreeRTOS allows the scheduler to be suspended/resumed by calling :cpp:fu On scheduler resumption, :cpp:func:`xTaskResumeAll` catches up all of the lost ticks and unblock any timed-out tasks. -In ESP-IDF FreeRTOS, suspending the scheduler across multiple cores is not possible. Therefore when :cpp:func:`vTaskSuspendAll` is called on a particular core (e.g., core A): +In IDF FreeRTOS, suspending the scheduler across multiple cores is not possible. Therefore when :cpp:func:`vTaskSuspendAll` is called on a particular core (e.g., core A): - Task switching is disabled only on core A but interrupts for core A are left enabled. - Calling any blocking/yielding function on core A is forbidden. Time slicing is disabled on core A. - If an interrupt on core A unblocks any tasks, tasks with affinity to core A will go into core A's own pending ready task list. Unpinned tasks or tasks with affinity to other cores can be scheduled on cores with the scheduler running. - If the scheduler is suspended on all cores, tasks unblocked by an interrupt will be directed to the pending ready task lists of their pinned cores. For unpinned tasks, they will be placed in the pending ready list of the core where the interrupt occurred. -- If core A is CPU0, the tick count is frozen, and a pended tick count is incremented instead. However, the tick interrupt will still occur in order to execute the application tick hook. +- If core A is on Core 0, the tick count is frozen, and a pended tick count is incremented instead. However, the tick interrupt will still occur in order to execute the application tick hook. When :cpp:func:`xTaskResumeAll` is called on a particular core (e.g., core A): - Any tasks added to core A's pending ready task list will be resumed. -- If core A is CPU0, the pended tick count is unwound to catch up with the lost ticks. +- If core A is Core 0, the pended tick count is unwound to catch up with the lost ticks. .. warning:: - Given that scheduler suspension on ESP-IDF FreeRTOS only suspends scheduling on a particular core, scheduler suspension is **NOT** a valid method ensuring mutual exclusion between tasks when accessing shared data. Users should use proper locking primitives such as mutexes or spinlocks if they require mutual exclusion. - -Disabling Interrupts -^^^^^^^^^^^^^^^^^^^^ - -Vanilla FreeRTOS allows interrupts to be disabled and enabled by calling :c:macro:`taskDISABLE_INTERRUPTS` and :c:macro:`taskENABLE_INTERRUPTS` respectively. - -ESP-IDF FreeRTOS provides the same API, however, interrupts are only disabled or enabled on the current core. - -.. warning:: - - Disabling interrupts is a valid method of achieving mutual exclusion in Vanilla FreeRTOS (and single-core systems in general). However, in an SMP system, disabling interrupts is **NOT** a valid method ensuring mutual exclusion. Refer to :ref:`critical-sections` for more details. - + Given that scheduler suspension on IDF FreeRTOS only suspends scheduling on a particular core, scheduler suspension is **NOT** a valid method of ensuring mutual exclusion between tasks when accessing shared data. Users should use proper locking primitives such as mutexes or spinlocks if they require mutual exclusion. .. ------------------------------------------------ Critical Sections -------------------------------------------------- -.. _critical-sections: - Critical Sections ----------------- +Disabling Interrupts +^^^^^^^^^^^^^^^^^^^^ + +Vanilla FreeRTOS allows interrupts to be disabled and enabled by calling :c:macro:`taskDISABLE_INTERRUPTS` and :c:macro:`taskENABLE_INTERRUPTS` respectively. IDF FreeRTOS provides the same API. However, interrupts are only disabled or enabled on the current core. + +Disabling interrupts is a valid method of achieving mutual exclusion in Vanilla FreeRTOS (and single-core systems in general). **However, in an SMP system, disabling interrupts is not a valid method of ensuring mutual exclusion**. Critical sections that utilize a spinlock should be used instead. + API Changes ^^^^^^^^^^^ @@ -351,7 +323,7 @@ Vanilla FreeRTOS implements critical sections by disabling interrupts, which pre - ``taskENTER_CRITICAL_FROM_ISR()`` enters a critical section from an ISR by disabling interrupt nesting - ``taskEXIT_CRITICAL_FROM_ISR()`` exits a critical section from an ISR by reenabling interrupt nesting -However, in an SMP system, merely disabling interrupts does not constitute a critical section as the presence of other cores means that a shared resource can still be concurrently accessed. Therefore, critical sections in ESP-IDF FreeRTOS are implemented using spinlocks. To accommodate the spinlocks, the ESP-IDF FreeRTOS critical section APIs contain an additional spinlock parameter as shown below: +However, in an SMP system, merely disabling interrupts does not constitute a critical section as the presence of other cores means that a shared resource can still be concurrently accessed. Therefore, critical sections in IDF FreeRTOS are implemented using spinlocks. To accommodate the spinlocks, the IDF FreeRTOS critical section APIs contain an additional spinlock parameter as shown below: - Spinlocks are of ``portMUX_TYPE`` (**not to be confused to FreeRTOS mutexes**) - ``taskENTER_CRITICAL(&spinlock)`` enters a critical from a task context @@ -361,7 +333,7 @@ However, in an SMP system, merely disabling interrupts does not constitute a cri .. note:: - The critical section API can be called recursively, i.e., nested critical sections. Entering a critical section multiple times recursively is valid so long as the critical section is exited the same number of times it was entered. However, given that critical sections can target different spinlocks, users should take care to avoid deadlocking when entering critical sections recursively. + The critical section API can be called recursively, i.e., nested critical sections. Entering a critical section multiple times recursively is valid so long as the critical section is exited the same number of times it was entered. However, given that critical sections can target different spinlocks, users should take care to avoid deadlocking when entering critical sections recursively. Spinlocks can be allocated statically or dynamically. As such, macros are provided for both static and dynamic initialization of spinlocks, as demonstrated by the following code snippets. @@ -369,35 +341,35 @@ Spinlocks can be allocated statically or dynamically. As such, macros are provid .. code:: c - // Statically allocate and initialize the spinlock - static portMUX_TYPE my_spinlock = portMUX_INITIALIZER_UNLOCKED; + // Statically allocate and initialize the spinlock + static portMUX_TYPE my_spinlock = portMUX_INITIALIZER_UNLOCKED; - void some_function(void) - { - taskENTER_CRITICAL(&my_spinlock); - // We are now in a critical section - taskEXIT_CRITICAL(&my_spinlock); - } + void some_function(void) + { + taskENTER_CRITICAL(&my_spinlock); + // We are now in a critical section + taskEXIT_CRITICAL(&my_spinlock); + } - Allocating a dynamic spinlock and initializing it using ``portMUX_INITIALIZE()``: .. code:: c - // Allocate the spinlock dynamically - portMUX_TYPE *my_spinlock = malloc(sizeof(portMUX_TYPE)); - // Initialize the spinlock dynamically - portMUX_INITIALIZE(my_spinlock); + // Allocate the spinlock dynamically + portMUX_TYPE *my_spinlock = malloc(sizeof(portMUX_TYPE)); + // Initialize the spinlock dynamically + portMUX_INITIALIZE(my_spinlock); - ... + ... - taskENTER_CRITICAL(my_spinlock); - // Access the resource - taskEXIT_CRITICAL(my_spinlock); + taskENTER_CRITICAL(my_spinlock); + // Access the resource + taskEXIT_CRITICAL(my_spinlock); Implementation ^^^^^^^^^^^^^^ -In ESP-IDF FreeRTOS, the process of a particular core entering and exiting a critical section is as follows: +In IDF FreeRTOS, the process of a particular core entering and exiting a critical section is as follows: - For ``taskENTER_CRITICAL(&spinlock)`` or ``taskENTER_CRITICAL_ISR(&spinlock)`` @@ -437,43 +409,52 @@ Misc Usually, when a context switch occurs: - - the current state of a CPU's registers is saved to the stack of the task being switched out - - the previously saved state of the CPU's registers is loaded from the stack of the task being switched in + - the current state of a core's registers are saved to the stack of the task being switched out + - the previously saved state of the core's registers is loaded from the stack of the task being switched in - However, ESP-IDF FreeRTOS implements Lazy Context Switching for the Floating Point Unit (FPU) registers of a CPU. In other words, when a context switch occurs on a particular core (e.g., CPU0), the state of the core's FPU registers is not immediately saved to the stack of the task getting switched out (e.g., Task A). The FPU registers are left untouched until: + However, IDF FreeRTOS implements Lazy Context Switching for the Floating Point Unit (FPU) registers of a core. In other words, when a context switch occurs on a particular core (e.g., Core 0), the state of the core's FPU registers is not immediately saved to the stack of the task getting switched out (e.g., Task A). The FPU registers are left untouched until: - A different task (e.g., Task B) runs on the same core and uses FPU. This will trigger an exception that saves the FPU registers to Task A's stack. - Task A gets scheduled to the same core and continues execution. Saving and restoring the FPU registers is not necessary in this case. - However, given that tasks can be unpinned and thus can be scheduled on different cores (e.g., Task A switches to CPU1), it is unfeasible to copy and restore the FPU registers across cores. Therefore, when a task utilizes FPU by using a ``float`` type in its call flow, ESP-IDF FreeRTOS will automatically pin the task to the current core it is running on. This ensures that all tasks that use FPU are always pinned to a particular core. + However, given that tasks can be unpinned and thus can be scheduled on different cores (e.g., Task A switches to Core 1), it is unfeasible to copy and restore the FPU registers across cores. Therefore, when a task utilizes FPU by using a ``float`` type in its call flow, IDF FreeRTOS will automatically pin the task to the current core it is running on. This ensures that all tasks that use FPU are always pinned to a particular core. - Furthermore, ESP-IDF FreeRTOS by default does not support the usage of FPU within an interrupt context given that the FPU register state is tied to a particular task. + Furthermore, IDF FreeRTOS by default does not support the usage of FPU within an interrupt context given that the FPU register state is tied to a particular task. - .. only: esp32 + .. only:: esp32 - .. note:: + .. note:: - Users that require the use of the ``float`` type in an ISR routine should refer to the :ref:`CONFIG_FREERTOS_FPU_IN_ISR` configuration option. + Users that require the use of the ``float`` type in an ISR routine should refer to the :ref:`CONFIG_FREERTOS_FPU_IN_ISR` configuration option. .. note:: - ESP targets that contain an FPU do not support hardware acceleration for double precision floating point arithmetic (``double``). Instead, ``double`` is implemented via software, hence the behavioral restrictions regarding the ``float`` type do not apply to ``double``. Note that due to the lack of hardware acceleration, ``double`` operations may consume significantly more CPU time in comparison to ``float``. + ESP targets that contain an FPU do not support hardware acceleration for double precision floating point arithmetic (``double``). Instead, ``double`` is implemented via software, hence the behavioral restrictions regarding the ``float`` type do not apply to ``double``. Note that due to the lack of hardware acceleration, ``double`` operations may consume significantly more CPU time in comparison to ``float``. .. -------------------------------------------------- Single Core ----------------------------------------------------- -.. _freertos-smp-single-core: +.. _freertos-idf-single-core: -ESP-IDF FreeRTOS Single Core -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Single-Core Mode +---------------- -Although ESP-IDF FreeRTOS is an SMP scheduler, some ESP targets are single-core (such as ESP32-S2 and ESP32-C3). When building ESP-IDF applications for these targets, ESP-IDF FreeRTOS is still used but the number of cores will be set to ``1`` (i.e., the :ref:`CONFIG_FREERTOS_UNICORE` will always be enabled for single-core targets). +Although IDF FreeRTOS is modified for dual-core SMP, IDF FreeRTOS can also be built for single-core by enabling the :ref:`CONFIG_FREERTOS_UNICORE` option. -For multicore targets (such as ESP32 and ESP32-S3), :ref:`CONFIG_FREERTOS_UNICORE` can also be set. This results in ESP-IDF FreeRTOS only running on CPU0, and all other cores will be inactive. +For single-core targets (such as ESP32-S2 and ESP32-C3), the :ref:`CONFIG_FREERTOS_UNICORE` option is always enabled. For multi-core targets (such as ESP32 and ESP32-S3), :ref:`CONFIG_FREERTOS_UNICORE` can also be set, but will result in the application only running Core 0. -.. note:: +When building in single-core mode, IDF FreeRTOS is designed to be identical to Vanilla FreeRTOS, thus all aforementioned SMP changes to kernel behavior are removed. As a result, building IDF FreeRTOS in single-core mode has the following characteristics: + +- All operations performed by the kernel inside critical sections are now deterministic (i.e., no walking of linked lists inside critical sections). +- Vanilla FreeRTOS scheduling algorithm is restored (including perfect Round Robin time slicing). +- All SMP specific data is removed from single-core builds. + +SMP APIs can still be called in single-core mode. These APIs remain exposed to allow source code to be built for single-core and multi-core, without needing to call a different set of APIs. However, SMP APIs will not exhibit any SMP behavior in single-core mode, thus becoming equivalent to their single-core counterparts. For example: + +- any ``...ForCore(..., BaseType_t xCoreID)`` SMP API will only accept ``0`` as a valid value for ``xCoreID``. +- ``...PinnedToCore()`` task creation APIs will simply ignore the ``xCoreID`` core affinity argument. +- Critical section APIs will still require a spinlock argument, but no spinlock will be taken and critical sections revert to simply disabling/enabling interrupts. - Users should bear in mind that enabling :ref:`CONFIG_FREERTOS_UNICORE` **is NOT equivalent to running Vanilla FreeRTOS**. The additional APIs of ESP-IDF FreeRTOS can still be called, and the behavior changes of ESP-IDF FreeRTOS incur a small amount of overhead even when compiled for only a single core. .. ------------------------------------------------- API References ---------------------------------------------------- diff --git a/docs/en/migration-guides/release-5.x/5.2/system.rst b/docs/en/migration-guides/release-5.x/5.2/system.rst index 916ad605f39a..7f2b7a8c82c9 100644 --- a/docs/en/migration-guides/release-5.x/5.2/system.rst +++ b/docs/en/migration-guides/release-5.x/5.2/system.rst @@ -6,6 +6,19 @@ System FreeRTOS -------- +IDF FreeRTOS Upgrade +^^^^^^^^^^^^^^^^^^^^ + +The IDF FreeRTOS kernel (which is a dual-core SMP implementation of FreeRTOS) has been upgraded to be based on Vanilla FreeRTOS v10.5.1. With this upgrade, the design and implementation of IDF FreeRTOS has also been changed significantly. As a result, users should take not of the following changes to kernel behavior and API: + +- When enabling single-core mode via the :ref:`CONFIG_FREERTOS_UNICORE` option, the kernel's behavior will now be identical to Vanilla FreeRTOS (see :ref:`freertos-idf-single-core` for more details). +- For SMP related APIs that were added by IDF FreeRTOS, checks on ``xCoreID`` arguments are now stricter. Providing out of range values for ``xCoreID`` arguments will now trigger an assert. +- The following SMP related APIs are now deprecated and replaced due to naming consistency reasons: + + - ``xTaskGetAffinity()`` is deprecated, call :cpp:func:`xTaskGetCoreID` instead. + - ``xTaskGetIdleTaskHandleForCPU()`` is deprecated, call :cpp:func:`xTaskGetIdleTaskHandleForCore` instead. + - ``xTaskGetCurrentTaskHandleForCPU()`` is deprecated, call :cpp:func:`xTaskGetCurrentTaskHandleForCore` instead. + Task Snapshot ^^^^^^^^^^^^^ diff --git a/docs/en/migration-guides/release-5.x/5.3/peripherals.rst b/docs/en/migration-guides/release-5.x/5.3/peripherals.rst index 1ace4952cf3e..483139b76641 100644 --- a/docs/en/migration-guides/release-5.x/5.3/peripherals.rst +++ b/docs/en/migration-guides/release-5.x/5.3/peripherals.rst @@ -24,6 +24,8 @@ In order to control the dependence of other components on drivers at a smaller g - `esp_driver_sdm` - Driver for Sigma-Delta Modulator - `esp_driver_i2c` - Driver for I2C - `esp_driver_uart` - Driver for UART +- `esp_driver_ledc` - Driver for LEDC +- `esp_driver_parlio` - Driver for Parallel IO For compatibility, the original `driver`` component is still treated as an all-in-one component by registering these `esp_driver_xyz`` components as its public dependencies. In other words, you do not need to modify the CMake file of an existing project, but you now have a way to specify the specific peripheral driver that your project depends on. diff --git a/docs/zh_CN/api-guides/external-ram.rst b/docs/zh_CN/api-guides/external-ram.rst index b0e1b434d883..72eb292bd194 100644 --- a/docs/zh_CN/api-guides/external-ram.rst +++ b/docs/zh_CN/api-guides/external-ram.rst @@ -24,7 +24,15 @@ .. note:: - PSRAM 芯片的工作电压分为 1.8 V 和 3.3 V。其工作电压必须与 flash 的工作电压匹配。请查询相应 PSRAM 芯片以及 {IDF_TARGET_NAME} 的技术规格书获取准确的工作电压。对于 1.8 V 的 PSRAM 芯片,请确保在启动时将 MTDI 管脚设置为高电平,或者将 {IDF_TARGET_NAME} 中的 eFuses 设置为始终使用 1.8 V 的 VDD_SIO 电平,否则有可能会损坏 PSRAM 和/或 flash 芯片。 + .. only:: esp32 or esp32s2 or esp32s3 + + PSRAM 芯片的工作电压分为 1.8 V 和 3.3 V。其工作电压必须与 flash 的工作电压匹配。请查询相应 PSRAM 芯片以及 {IDF_TARGET_NAME} 的技术规格书获取准确的工作电压。对于 1.8 V 的 PSRAM 芯片,请确保在启动时将 MTDI 管脚设置为高电平,或者将 {IDF_TARGET_NAME} 中的 eFuses 设置为始终使用 1.8 V 的 VDD_SIO 电平,否则有可能会损坏 PSRAM 和/或 flash 芯片。 + + .. only:: esp32p4 + + 请查询相应 PSRAM 芯片以及 {IDF_TARGET_NAME} 的技术规格书获取准确的工作电压。 + + PSRAM 默认由片上 LDO2 供电。可设置 :ref:`CONFIG_ESP_VDD_PSRAM_LDO_ID` 来切换相应的 LDO ID,将该值设为 -1 表示使用外部电源,即不使用片上 LDO。默认情况下,连接到 LDO 的 PSRAM 会基于所使用的乐鑫模组设置正确电压。如果未使用乐鑫模组,仍可设置 :ref:`CONFIG_ESP_VDD_PSRAM_LDO_VOLTAGE_MV` 来选择 LDO 输出电压。使用外部电源时,该选项不存在。 .. note:: diff --git a/docs/zh_CN/api-reference/peripherals/clk_tree.rst b/docs/zh_CN/api-reference/peripherals/clk_tree.rst index 0ef695d7a2d8..46ab9c20c813 100644 --- a/docs/zh_CN/api-reference/peripherals/clk_tree.rst +++ b/docs/zh_CN/api-reference/peripherals/clk_tree.rst @@ -3,15 +3,15 @@ :link_to_translation:`en:[English]` -{IDF_TARGET_RC_FAST_VAGUE_FREQ: default="8", esp32c3="17.5", esp32s3="17.5", esp32c2="17.5", esp32c6="17.5"} +{IDF_TARGET_RC_FAST_VAGUE_FREQ: default="17.5", esp32="8", esp32s2="8", esp32h2="8"} -{IDF_TARGET_RC_FAST_ADJUSTED_FREQ: default="8.5", esp32c3="17.5", esp32s3="17.5", esp32c2="17.5", esp32c6="17.5"} +{IDF_TARGET_RC_FAST_ADJUSTED_FREQ: default="17.5", esp32="8.5", esp32s2="8.5", esp32h2="8.5"} {IDF_TARGET_XTAL_FREQ: default="40", esp32="2 ~ 40", esp32c2="40/26", esp32h2="32"} {IDF_TARGET_RC_SLOW_VAGUE_FREQ: default="136", esp32="150", esp32s2="90"} -{IDF_TARGET_RC_SLOW_CLK: default="GPIO0", esp32c2="pin0(时钟信号频率不超过 136 kHz 时)", "esp32c6="GPIO0", esp32h2="GPIO13"} +{IDF_TARGET_OSC_SLOW_PIN: default="GPIO0", esp32c2="pin0(时钟信号频率不超过 136 kHz 时)", "esp32c6="GPIO0", esp32h2="GPIO13"} {IDF_TARGET_NAME} 的时钟子系统用于从一系列根时钟中提取并分配系统/模块时钟。时钟树驱动程序负责维护系统时钟的基本功能,并管理模块时钟间的复杂关系。 @@ -63,7 +63,11 @@ ``XTAL32K_CLK`` 的时钟源可以是连接到 ``32K_XP`` 和 ``32K_XN`` 管脚的 32 kHz 晶振,也可以是外部电路生成的 32 kHz 时钟信号。如果使用外部电路生成的时钟信号,该信号必须连接到 ``32K_XN`` 管脚,并且在 ``32K_XP`` 管脚和地之间连接一个 1 nF 的电容。此时,``32K_XP`` 管脚不能用作 GPIO 管脚。 - .. only:: not esp32 + .. only:: esp32p4 + + ``XTAL32K_CLK`` 的时钟源是连接到 ``XTAL_32K_P`` 和 ``XTAL_32K_N`` 管脚的 32 kHz 晶振。 + + .. only:: not esp32 and not esp32p4 ``XTAL32K_CLK`` 的时钟源可以是连接到 ``XTAL_32K_P`` 和 ``XTAL_32K_N`` 管脚的 32 kHz 晶振,也可以是外部电路生成的 32 kHZ 时钟信号。如果使用外部电路生成的时钟信号,该信号必须连接到 ``XTAL_32K_P`` 管脚。 @@ -73,7 +77,7 @@ - 外部慢速时钟 - 可选 (OSC_SLOW) - 将外部电路生成的时钟信号连接到 {IDF_TARGET_RC_SLOW_CLK},可作为 ``RTC_SLOW_CLK`` 的时钟源。通过校准,可以计算该时钟信号的实际频率。 + 将外部电路生成的时钟信号连接到 {IDF_TARGET_OSC_SLOW_PIN},可作为 ``RTC_SLOW_CLK`` 的时钟源。通过校准,可以计算该时钟信号的实际频率。 .. only:: SOC_CLK_RC32K_SUPPORTED diff --git a/docs/zh_CN/api-reference/protocols/esp_http_client.rst b/docs/zh_CN/api-reference/protocols/esp_http_client.rst index 21ebf032d616..72ab21fa1438 100644 --- a/docs/zh_CN/api-reference/protocols/esp_http_client.rst +++ b/docs/zh_CN/api-reference/protocols/esp_http_client.rst @@ -83,6 +83,7 @@ ESP HTTP 客户端同时支持 **基本** 和 **摘要** 认证。 * 用户可以在 ``url`` 或 ``esp_http_client_config_t`` 配置中的 ``username`` 和 ``password`` 处输入用户名和密码。对于 ``auth_type = HTTP_AUTH_TYPE_BASIC``,HTTP 客户端只需执行一项操作就可通过认证过程。 * 如果 ``auth_type = HTTP_AUTH_TYPE_NONE``,但配置中有 ``username`` 和 ``password`` 字段,HTTP 客户端需要执行两项操作。客户端在第一次尝试连接服务器时,会收到 ``401 Unauthorized`` 头,而后再根据这些信息来选择认证方法,并在第二项操作中执行。 * 如需了解实现细节,请参考应用示例中的函数 ``http_auth_basic``、 ``http_auth_basic_redirect`` (用于基本认证)和 ``http_auth_digest`` (用于摘要认证)。 + * 目前,摘要认证仅支持 MD5 和 SHA-256 算法。 认证配置示例 diff --git a/docs/zh_CN/api-reference/system/freertos.rst b/docs/zh_CN/api-reference/system/freertos.rst index f6663e237585..f1ebb9d8677c 100644 --- a/docs/zh_CN/api-reference/system/freertos.rst +++ b/docs/zh_CN/api-reference/system/freertos.rst @@ -49,7 +49,7 @@ ESP-IDF FreeRTOS 关于用户可配置内核选项的完整列表,参见 :doc:`/api-reference/kconfig`。下列为常用的内核配置选项: -- :ref:`CONFIG_FREERTOS_UNICORE`:仅在 CPU0 上运行 FreeRTOS。注意,这 **不等同于运行原生 FreeRTOS。** 另外,此选项还可能影响除 :component:`freertos` 外其他组件的行为。关于在单核上运行 FreeRTOS 的更多内容,请参考 :ref:`freertos-smp-single-core` (使用 ESP-IDF FreeRTOS 时)或参考 Amazon SMP FreeRTOS 的官方文档,还可以在 ESP-IDF 组件中搜索 ``CONFIG_FREERTOS_UNICORE``。 +- :ref:`CONFIG_FREERTOS_UNICORE`:仅在核 0 上运行 FreeRTOS。注意,这 **不等同于运行原生 FreeRTOS。** 另外,此选项还可能影响除 :component:`freertos` 外其他组件的行为。关于在单核上运行 FreeRTOS 的更多内容,请参考 :ref:`freertos-idf-single-core` (使用 ESP-IDF FreeRTOS 时)或参考 Amazon SMP FreeRTOS 的官方文档,还可以在 ESP-IDF 组件中搜索 ``CONFIG_FREERTOS_UNICORE``。 .. only:: not SOC_HP_CPU_HAS_MULTIPLE_CORES @@ -95,14 +95,14 @@ ESP-IDF FreeRTOS - 亲和性 - 优先级 * - 空闲任务 (``IDLEx``) - - 为每个 CPU 核创建并固定一个空闲任务 (``IDLEx``),其中 ``x`` 是 CPU 核的编号。 当启用单核配置时,``x`` 将被删除。 + - 为每个 CPU 核创建并分配一个空闲任务 (``IDLEx``),其中 ``x`` 是 CPU 核的编号。 当启用单核配置时,``x`` 将被删除。 - :ref:`CONFIG_FREERTOS_IDLE_TASK_STACKSIZE` - - Core x + - 核 x - ``0`` * - FreeRTOS 定时器任务 (``Tmr Svc``) - 如果应用程序调用了任何 FreeRTOS 定时器 API,FreeRTOS 会创建定时器服务或守护任务 - :ref:`CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH` - - Core 0 + - 核 0 - :ref:`CONFIG_FREERTOS_TIMER_TASK_PRIORITY` * - 主任务 (``main``) - 简单调用 ``app_main`` 的任务在 ``app_main`` 返回时会自我删除 @@ -110,14 +110,14 @@ ESP-IDF FreeRTOS - :ref:`CONFIG_ESP_MAIN_TASK_AFFINITY` - ``1`` * - IPC 任务 (``ipcx``) - - 当 :ref:`CONFIG_FREERTOS_UNICORE` 为假时,为每个 CPU 核创建并固定一个 IPC 任务 (``ipcx``)。IPC 任务用于实现处理器间调用 (IPC) 功能 + - 当 :ref:`CONFIG_FREERTOS_UNICORE` 为假时,为每个 CPU 核创建并分配一个 IPC 任务 (``ipcx``)。IPC 任务用于实现处理器间调用 (IPC) 功能 - :ref:`CONFIG_ESP_IPC_TASK_STACK_SIZE` - - Core x + - 核 x - ``24`` * - ESP 定时器任务 (``esp_timer``) - ESP-IDF 创建 ESP 定时器任务用于处理 ESP 定时器回调 - :ref:`CONFIG_ESP_TIMER_TASK_STACK_SIZE` - - Core 0 + - 核 0 - ``22`` .. note:: diff --git a/docs/zh_CN/api-reference/system/freertos_idf.rst b/docs/zh_CN/api-reference/system/freertos_idf.rst index 5d4830683d7a..116e7770f355 100644 --- a/docs/zh_CN/api-reference/system/freertos_idf.rst +++ b/docs/zh_CN/api-reference/system/freertos_idf.rst @@ -1,31 +1,26 @@ -FreeRTOS (ESP-IDF) -================== +FreeRTOS (IDF) +============== :link_to_translation:`en:[English]` +本文档介绍了 ESP-IDF 框架内的 FreeRTOS 双核 SMP 实现,包含以下小节: + +.. contents:: 目录 + :depth: 2 + .. ---------------------------------------------------- Overview ------------------------------------------------------- 概述 ---- -原始 FreeRTOS(下文称 Vanilla FreeRTOS)是一款小巧高效的实时操作系统,适用于许多单核 MCU 和 SoC。但为了支持双核 ESP 芯片,如 ESP32、ESP32-S3、ESP32-P4,ESP-IDF 提供了支持双核对称多处理 (SMP) 的 FreeRTOS 实现(下文称 ESP-IDF FreeRTOS)。 +原始 FreeRTOS(下文称 Vanilla FreeRTOS)是一款小巧高效的实时操作系统,适用于许多单核 MCU 和 SoC。但为了支持双核 ESP 芯片,如 ESP32、ESP32-S3、ESP32-P4,ESP-IDF 特别提供了支持双核对称多处理 (SMP) 的 FreeRTOS 实现(下文称 IDF FreeRTOS)。 -ESP-IDF FreeRTOS 以 Vanilla FreeRTOS v10.5.1 为基础,为支持 SMP,在 API 和内核行为上做了较大改动。本文档描述了 Vanilla FreeRTOS 与 ESP-IDF FreeRTOS 之间的 API 和内核行为差异。 +IDF FreeRTOS 源代码基于 Vanilla FreeRTOS v10.5.1,但内核行为和 API 都有重大修改,以支持双核 SMP。不过用户也可以启用 :ref:`CONFIG_FREERTOS_UNICORE` 选项,将 IDF FreeRTOS 配置为支持单核,详情请参阅 :ref:`freertos-idf-single-core`。 .. note:: 本文档假定读者已具备 Vanilla FreeRTOS 的必要背景知识,即了解其特性、行为和 API 用法。如需了解背景知识,请参阅 `Vanilla FreeRTOS 文档 `_。 -.. note:: - - 启用 :ref:`CONFIG_FREERTOS_UNICORE` 配置选项可以为单核芯片构建 ESP-IDF FreeRTOS,单核 ESP 芯片会默认启用 :ref:`CONFIG_FREERTOS_UNICORE` 配置选项。但请注意,启用 :ref:`CONFIG_FREERTOS_UNICORE` 并不等同于构建 Vanilla FreeRTOS,ESP-IDF FreeRTOS 的某些内核行为和 API 仍有所不同。更多详细信息,请参阅 :ref:`freertos-smp-single-core`。 - -本文档包含以下小节。 - -.. contents:: 目录 - :depth: 2 - - .. -------------------------------------------- Symmetric Multiprocessing ---------------------------------------------- 对称多处理 @@ -41,34 +36,30 @@ ESP-IDF FreeRTOS 以 Vanilla FreeRTOS v10.5.1 为基础,为支持 SMP,在 AP 与单核或非对称多处理系统相比,SMP 系统的主要优势在于: -- 存在多个 CPU,支持多个硬件线程,从而提高整体处理吞吐量。 +- 存在多个核,支持多个硬件线程,从而提高整体处理吞吐量。 - 对称内存支持线程在执行期间切换核,从而提高 CPU 利用率。 尽管 SMP 系统支持线程切换核,但在某些情况下,线程必须或应该仅在特定核上运行。因此,在 SMP 系统中,线程也具备核亲和性,指定线程在哪个特定核上运行。 -- 固定到特定核的线程只能在该核上运行。 -- 未固定于特定核的线程支持在执行期间切换核。 +- 分配给特定核的线程只能在该核上运行。 +- 未分配给特定核的线程支持在执行期间切换核。 ESP 芯片上的 SMP ^^^^^^^^^^^^^^^^ ESP32、ESP32-S3、ESP32-P4 等 ESP 芯片是双核 SMP SoC,具有以下硬件特性以支持 SMP: -- 具有两个完全相同的核,分别称为 CPU0 和 CPU1。代码段无论在哪个核上运行,都有相同的执行效果。 +- 具有两个完全相同的核,分别称为核 0 和核 1。代码段无论在哪个核上运行,都有相同的执行效果。 - 具有对称内存(除了少数例外情况)。 - 如果多个核同时访问相同的内存地址,它们的访问会被内存总线串行化。 - 通过 ISA 提供的原子比较和交换指令,可以实现对同一内存地址的真正原子访问。 -- 跨核中断支持由一个 CPU 触发另一个 CPU 上的中断,这使得核间可以互相发送信号。 +- 跨核中断支持由一个核触发另一个核上的中断,这使得核间可以互相发送信号,如请求在另一个核上进行上下文切换。 +.. note:: -.. only:: not esp32p4 - - .. note:: - - CPU0 又称协议 CPU 或 ``PRO_CPU``,CPU1 又称应用 CPU 或 ``APP_CPU``。在 ESP-IDF 中,CPU0 和 CPU1 的别名 ``PRO_CPU`` 和 ``APP_CPU`` 反映了典型 ESP-IDF 应用程序使用这两个 CPU 的方式。负责处理无线网络(如 Wi-Fi 或蓝牙)的任务通常会固定在 CPU0 上,因此称 CPU0 为 ``PRO_CPU``;而处理应用程序的其余部分任务会被固定在 CPU1 上,因此称 CPU1 为 ``APP_CPU``。 - + 在 ESP-IDF 中,核 0 和核 1 有时分别又被称为 ``PRO_CPU`` 和 ``APP_CPU``。别名 ``PRO_CPU`` 和 ``APP_CPU`` 反映了典型 ESP-IDF 应用程序使用这两个 CPU 的方式。负责处理 Wi-Fi 或蓝牙等协议相关处理程序的任务通常会分配给核 0,因此称核 0 为 ``PRO_CPU``;而处理应用程序其余部分的任务会分配给核 1,因此称核 1 为 ``APP_CPU``。 .. ------------------------------------------------------ Tasks -------------------------------------------------------- @@ -83,27 +74,27 @@ Vanilla FreeRTOS 提供以下用于创建任务的函数: - 使用 :cpp:func:`xTaskCreate` 创建任务时,任务内存动态分配。 - 使用 :cpp:func:`xTaskCreateStatic` 创建任务时,任务内存静态分配,即由用户提供。 -然而,在 SMP 系统中,任务需要分配到特定核。因此,ESP-IDF 提供了 Vanilla FreeRTOS 任务创建函数的 ``PinnedToCore`` 版本: +然而,在 SMP 系统中,任务需要分配到特定核。因此,ESP-IDF 提供了 Vanilla FreeRTOS 任务创建函数的 ``...PinnedToCore()`` 版本: - 使用 :cpp:func:`xTaskCreatePinnedToCore` 可以创建具有特定核亲和性的任务,任务内存动态分配。 - 使用 :cpp:func:`xTaskCreateStaticPinnedToCore` 可以创建具有特定核亲和性的任务,任务内存静态分配,即由用户提供。 -不同于普通的任务创建函数 API,``PinnedToCore`` 版本的任务创建函数 API 有额外的 ``xCoreID`` 参数,用于指定所创建任务的核亲和性。核亲和性的有效值包括: +不同于普通的任务创建函数 API,``...PinnedToCore()`` 版本的任务创建函数 API 有额外的 ``xCoreID`` 参数,用于指定所创建任务的核亲和性。核亲和性的有效值包括: -- ``0``:将创建的任务固定到 CPU0 -- ``1``:将创建的任务固定到 CPU1 -- ``tskNO_AFFINITY``:支持任务在两个 CPU 上运行 +- ``0``:将创建的任务分配给核 0 +- ``1``:将创建的任务分配给核 1 +- ``tskNO_AFFINITY``:支持任务在两个核上运行 -注意,ESP-IDF FreeRTOS 仍支持普通的任务创建函数,但这些标准函数已经过调整,会内部调用其 ``PinnedToCore`` 版本,同时将核亲和性设置为 ``tskNO_AFFINITY``。 +注意,IDF FreeRTOS 仍支持普通的任务创建函数,但这些标准函数已经过调整,会内部调用其 ``...PinnedToCore()`` 版本,同时将核亲和性设置为 ``tskNO_AFFINITY``。 .. note:: - ESP-IDF FreeRTOS 还更改了任务创建函数中的 ``ulStackDepth`` 参数。在 Vanilla FreeRTOS 中,任务堆栈的大小以字为单位指定,而在 ESP-IDF FreeRTOS 中,任务堆栈的大小以字节为单位指定。 + IDF FreeRTOS 还更改了任务创建函数中的 ``ulStackDepth`` 参数。在 Vanilla FreeRTOS 中,任务堆栈的大小以字为单位指定,而在 IDF FreeRTOS 中,任务堆栈的大小以字节为单位指定。 执行任务 ^^^^^^^^ -ESP-IDF FreeRTOS 中任务的结构与 Vanilla FreeRTOS 相同。具体而言,ESP-IDF FreeRTOS 任务: +IDF FreeRTOS 中任务的结构与 Vanilla FreeRTOS 相同。具体而言,IDF FreeRTOS 任务: - 只能处于以下任一状态:运行中、就绪、阻塞或挂起。 - 任务函数通常为无限循环。 @@ -114,7 +105,7 @@ ESP-IDF FreeRTOS 中任务的结构与 Vanilla FreeRTOS 相同。具体而言, 调用 :cpp:func:`vTaskDelete` 可以在 Vanilla FreeRTOS 中删除任务。该函数可用于删除其他任务,若任务句柄为 ``NULL`` 则删除当前运行任务。如果删除的任务是当前正在运行的任务时,任务的内存释放有时会委托给空闲任务执行。 -ESP-IDF FreeRTOS 提供了同样的 :cpp:func:`vTaskDelete` 函数。然而,ESP-IDF FreeRTOS 是一个双核系统,因此调用 :cpp:func:`vTaskDelete` 时,行为上会与 Vanilla FreeRTOS 有以下差异: +IDF FreeRTOS 提供了同样的 :cpp:func:`vTaskDelete` 函数。然而,IDF FreeRTOS 是一个双核系统,因此调用 :cpp:func:`vTaskDelete` 时,行为上会与 Vanilla FreeRTOS 有以下差异: - 删除另一个核上运行的任务时,会在另一个核上触发一次让步,任务内存由其中一个空闲任务释放。 - 如果删除的任务没有在任一核上运行,则会立即释放其内存。 @@ -141,50 +132,50 @@ SMP 调度器 - 调度器可以在不需要当前运行任务的协作下切换执行到另一个任务。 - 调度器会采用轮转方式,定期在具有相同优先级的就绪状态任务间切换执行,时间分片由时钟中断控制。 -ESP-IDF FreeRTOS 调度器支持相同的调度特性,即固定优先级、抢占和时间分片,但也存在细微的行为差异。 +IDF FreeRTOS 调度器支持相同的调度特性,即固定优先级、抢占和时间分片,但也存在细微的行为差异。 固定优先级 ^^^^^^^^^^ -在 Vanilla FreeRTOS 中,当调度器选择要运行的新任务时,往往会选择当前优先级最高的就绪任务。而在 ESP-IDF FreeRTOS 中,每个核都独立地调度要运行的任务。当特定核选择一个任务时,该核会选择优先级最高且可以在该核上运行的就绪状态任务。满足以下条件时,任务可以在核上运行: +在 Vanilla FreeRTOS 中,当调度器选择要运行的新任务时,往往会选择当前优先级最高的就绪任务。而在 IDF FreeRTOS 中,每个核都独立地调度要运行的任务。当特定核选择一个任务时,该核会选择优先级最高且可以在该核上运行的就绪状态任务。满足以下条件时,任务可以在核上运行: -- 任务亲和性兼容,即已固定或未固定到当前核上。 +- 任务亲和性兼容,即已分配或未分配给当前核。 - 该任务当前没有在其他核上运行。 但是,两个具有最高优先级的就绪任务不一定始终由调度器运行,因为还需考虑到任务的核亲和性。例如,给定以下任务: -- 优先级为 10 的任务 A,固定到 CPU0 -- 优先级为 9 的任务 B,固定到 CPU0 -- 优先级为 8 的任务 C,固定到 CPU1 +- 优先级为 10 的任务 A,分配给核 0 +- 优先级为 9 的任务 B,分配给核 0 +- 优先级为 8 的任务 C,分配给核 1 -经过调度后,任务 A 将在 CPU0 上运行,任务 C 将在 CPU1 上运行。即使任务 B 是第二优先级任务,也不会被执行。 +经过调度后,任务 A 将在核 0 上运行,任务 C 将在核 1 上运行。即使任务 B 是第二优先级任务,也不会被执行。 抢占 ^^^^ -在 Vanilla FreeRTOS 中,如果优先级更高的任务已准备好执行,调度器可以抢占当前正在运行的任务。同样,在 ESP-IDF FreeRTOS 任务中,如果调度器确定一个优先级更高的任务可以在某个核上运行,那么调度器可以单独抢占各个核。 +在 Vanilla FreeRTOS 中,如果优先级更高的任务已准备好执行,调度器可以抢占当前正在运行的任务。同样,在 IDF FreeRTOS 任务中,如果调度器确定一个优先级更高的任务可以在某个核上运行,那么调度器可以单独抢占各个核。 -但在某些情况下,一个优先级更高的就绪任务可以在多个核上运行。此时,调度器只会抢占一个核。即便当前有多个核可以抢占,调度器总是优先选择当前核。换句话说,如果优先级更高的就绪任务未固定,并且其优先级高于两个核的当前优先级,调度器将始终选择抢占当前核。例如,给定以下任务: +但在某些情况下,一个优先级更高的就绪任务可以在多个核上运行。此时,调度器只会抢占一个核。即便当前有多个核可以抢占,调度器总是优先选择当前核。换句话说,如果优先级更高的就绪任务未分配,并且其优先级高于两个核的当前优先级,调度器将始终选择抢占当前核。例如,给定以下任务: -- 优先级为 8 的任务 A 当前在 CPU0 上运行 -- 优先级为 9 的任务 B 当前在 CPU1 上运行 -- 优先级为 10 的任务 C 未固定,并由任务 B 解除了阻塞 +- 优先级为 8 的任务 A 当前在核 0 上运行 +- 优先级为 9 的任务 B 当前在核 1 上运行 +- 优先级为 10 的任务 C 未分配,并由任务 B 解除了阻塞 -经过调度后,任务 A 将在 CPU0 上运行,任务 C 将抢占任务 B,因为调度器总是优先选择当前核。 +经过调度后,任务 A 将在核 0 上运行,任务 C 将抢占任务 B,因为调度器总是优先选择当前核。 时间分片 ^^^^^^^^ Vanilla FreeRTOS 实现了时间分片,这意味着如果当前优先级最高的就绪任务包含多个就绪任务,调度器会在这些任务间轮转定期切换。 -然而,在 ESP-IDF FreeRTOS 中,由于以下原因,特定任务可能无法在特定核上运行,因此无法实现完美的轮转时间分片: +然而,在 IDF FreeRTOS 中,由于以下原因,特定任务可能无法在特定核上运行,因此无法实现完美的轮转时间分片: -- 任务固定到了另一个核。 -- 任务未固定,但已经由其他核运行。 +- 任务分配给了另一个核。 +- 任务未分配,但已经由其他核运行。 因此,当核在所有就绪状态任务中搜索寻找要运行的任务时,可能需要跳过同一优先级列表中的一些任务,或者降低优先级,以找到可以运行的就绪状态任务。 -ESP-IDF FreeRTOS 调度器会确保已选择运行的任务置于列表末尾,为同一优先级的就绪状态任务实现最佳轮转时间分片。这样,在下一次调度迭代(即,下一个滴答中断或让步)中,未经选择的任务优先级会更高。 +IDF FreeRTOS 调度器会确保已选择运行的任务置于列表末尾,为同一优先级的就绪状态任务实现最佳轮转时间分片。这样,在下一次调度迭代(即,下一个滴答中断或让步)中,未经选择的任务优先级会更高。 以下示例展示了最佳轮转时间分片的实操。假设: @@ -192,78 +183,66 @@ ESP-IDF FreeRTOS 调度器会确保已选择运行的任务置于列表末尾, - 优先级是当前具有就绪状态任务的最高优先级。 - 第一个字符代表任务名称,即 ``A``、``B``、``C``、``D``。 - - 第二个字符表示任务核的固定情况,``X`` 表示未固定。 + - 第二个字符表示任务核的分配情况,``X`` 表示未分配。 - 任务列表始终从头开始搜索 -.. code-block:: none - - -------------------------------------------------------------------------------- - - 1. 起始状态,尚未选择要运行的就绪状态任务。 - - Head [ AX , B0 , C1 , D0 ] Tail - - -------------------------------------------------------------------------------- - - 2. 核 0 有一个滴答中断,搜索要运行的任务。 - - 选择任务 A,并将其移至列表末尾。 +1. 起始状态,尚未选择要运行的就绪状态任务。 - Core0--| - Head [ AX , B0 , C1 , D0 ] Tail + .. code-block:: none - 0 - Head [ B0 , C1 , D0 , AX ] Tail + Head [ AX , B0 , C1 , D0 ] Tail - -------------------------------------------------------------------------------- +2. 核 0 有一个滴答中断,搜索要运行的任务。选择任务 A,并将其移至列表末尾。 - 3. 核 1 有一个滴答中断,搜索要运行的任务。 + .. code-block:: none - 由于亲和性不兼容,任务 B 无法运行,因此核 1 跳到任务 C。 + Core 0 ─┐ + ▼ + Head [ AX , B0 , C1 , D0 ] Tail - 选择任务 C,并将其移至列表末尾。 + [0] + Head [ B0 , C1 , D0 , AX ] Tail - Core1-------| 0 - Head [ B0 , C1 , D0 , AX ] Tail +3. 核 1 有一个滴答中断,搜索要运行的任务。由于亲和性不兼容,任务 B 无法运行,因此核 1 跳到任务 C。选择任务 C,并将其移至列表末尾。 - 0 1 - Head [ B0 , D0 , AX , C1 ] Tail + .. code-block:: none - -------------------------------------------------------------------------------- + Core 1 ──────┐ + ▼ [0] + Head [ B0 , C1 , D0 , AX ] Tail - 4. 核 0 有另一个滴答中断,搜索要运行的任务。 + [0] [1] + Head [ B0 , D0 , AX , C1 ] Tail - 选择任务 B,并将其移至列表末尾。 +4. 核 0 有另一个滴答中断,搜索要运行的任务。选择任务 B,并将其移至列表末尾。 + .. code-block:: none - Core0--| 1 - Head [ B0 , D0 , AX , C1 ] Tail + Core 0 ─┐ + ▼ [1] + Head [ B0 , D0 , AX , C1 ] Tail - 1 0 - Head [ D0 , AX , C1 , B0 ] Tail + [1] [0] + Head [ D0 , AX , C1 , B0 ] Tail - -------------------------------------------------------------------------------- +5. 核 1 有另一个滴答中断,搜索要运行的任务。由于亲和性不兼容,任务 D 无法运行,因此核 1 跳到任务 A。选择任务 A,并将其移至列表末尾。 - 5. 核 1 有另一个滴答中断,搜索要运行的任务。 + .. code-block:: none - 由于亲和性不兼容,任务 D 无法运行,因此核 1 跳到任务 A - - 选择任务 A,并将其移至列表末尾 - - Core1-------| 0 - Head [ D0 , AX , C1 , B0 ] Tail - - 0 1 - Head [ D0 , C1 , B0 , AX ] Tail + Core 1 ──────┐ + ▼ [0] + Head [ D0 , AX , C1 , B0 ] Tail + [0] [1] + Head [ D0 , C1 , B0 , AX ] Tail 在使用最佳轮转时间分片时需注意: - 相同优先级的多个就绪状态任务不一定可以像在 Vanilla FreeRTOS 中一样按顺序运行。如以上示例所示,核可能会跳过任务。 - 然而,经过足够的滴答次数,任务最终将获得一些处理时间。 - 如果核找不到优先级最高的可运行就绪任务,它将降低优先级来搜索任务。 -- 为了实现理想的轮转时间分片,应确保特定优先级的所有任务都固定到同一个核上。 +- 为了实现理想的轮转时间分片,应确保特定优先级的所有任务都分配给同一个核。 时钟中断 ^^^^^^^^ @@ -275,14 +254,14 @@ Vanilla FreeRTOS 要求定期发生滴答中断,滴答中断有以下作用: - 检查是否需要进行时间分片,即触发上下文切换 - 执行应用程序滴答函数 -在 ESP-IDF FreeRTOS 中,每个核都会接收到定期中断,并独立运行滴答中断。每个核上的滴答中断周期相同,但可能不同步。然而,上述滴答中断任务不会由所有核同时执行,具体而言: +在 IDF FreeRTOS 中,每个核都会接收到定期中断,并独立运行滴答中断。每个核上的滴答中断周期相同,但可能不同步。然而,上述滴答中断任务不会由所有核同时执行,具体而言: -- CPU0 执行上述所有滴答中断任务 -- CPU1 仅检查是否需要时间分片并执行应用程序滴答函数 +- 核 0 执行上述所有滴答中断任务 +- 核 1 仅检查是否需要时间分片并执行应用程序滴答函数 .. note:: - 在 ESP-IDF FreeRTOS 中,CPU0 是负责时间计数的唯一核。因此,任何阻止 CPU0 增加滴答计数的情况,例如暂停 CPU0 上的调度器,都会导致整个调度器的时间计数滞后。 + 在 IDF FreeRTOS 中,核 0 是负责时间计数的唯一核。因此,任何阻止核 0 增加滴答计数的情况,例如暂停核 0 上的调度器,都会导致整个调度器的时间计数滞后。 空闲任务 ^^^^^^^^ @@ -292,7 +271,7 @@ Vanilla FreeRTOS 要求定期发生滴答中断,滴答中断有以下作用: - 释放已删除任务的内存 - 执行应用程序的空闲函数 -而 ESP-IDF FreeRTOS 为每个核单独创建了一个固定的空闲任务。每个核上的空闲任务起到与其 Vanilla FreeRTOS 对应任务相同的作用。 +而 IDF FreeRTOS 为每个核单独创建了一个固定的空闲任务。每个核上的空闲任务起到与其 Vanilla FreeRTOS 对应任务相同的作用。 调度器挂起 ^^^^^^^^^^ @@ -305,42 +284,35 @@ Vanilla FreeRTOS 支持调用 :cpp:func:`vTaskSuspendAll` 挂起调度器,调 调度器恢复时,:cpp:func:`xTaskResumeAll` 会补上所有丢失的时钟计数,并解除超时任务的阻塞。 -在 ESP-IDF FreeRTOS 中,无法在多个核上同时挂起调度器。因此,在特定核上(如核 A)调用 :cpp:func:`vTaskSuspendAll` 时: +在 IDF FreeRTOS 中,无法在多个核上同时挂起调度器。因此,在特定核上(如核 A)调用 :cpp:func:`vTaskSuspendAll` 时: - 只在核 A 上禁用任务切换,但仍启用核 A 的中断。 - 禁止在核 A 上调用任何阻塞或让出函数,在核 A 上禁用时间分片。 -- 核 A 上的中断解除任务阻塞时,对核 A 亲和的任务会进入核 A 的待执行任务列表。未固定的任务或对其他核亲和的任务可以在运行调度器的核上调度。 -- 所有核上的调度器均挂起时,由中断解除阻塞的任务将进入它们固定到的核的待执行任务列表。如果任务未固定,则进入调用中断的核的待执行任务列表。 -- 如果核 A 是 CPU0,则时钟计数将被冻结,挂起的时钟计数将递增,但仍会发生时钟中断以执行应用程序时钟函数。 +- 核 A 上的中断解除任务阻塞时,对核 A 亲和的任务会进入核 A 的待执行任务列表。未分配的任务或对其他核亲和的任务可以在运行调度器的核上调度。 +- 所有核上的调度器均挂起时,由中断解除阻塞的任务将进入它们分配的核的待执行任务列表。如果任务未分配,则进入调用中断的核的待执行任务列表。 +- 如果核 A 是核 0,则时钟计数将被冻结,挂起的时钟计数将递增,但仍会发生时钟中断以执行应用程序时钟函数。 在特定核(如核 A)上调用 :cpp:func:`xTaskResumeAll` 时: - 任何添加到核 A 的待执行任务列表中的任务将恢复执行。 -- 如果核 A 是 CPU0,则挂起的时钟计数将回退,补上丢失的时钟计数。 - -.. warning:: - - ESP-IDF FreeRTOS 上的调度器挂起仅暂停特定核上的调度,因此调度器挂起 **不能** 确保访问共享数据时任务互斥。如果需要互斥,请使用适当的锁定机制,如互斥锁或自旋锁。 - -禁用中断 -^^^^^^^^ - -Vanilla FreeRTOS 支持调用 :c:macro:`taskDISABLE_INTERRUPTS` 禁用中断,调用 :c:macro:`taskENABLE_INTERRUPTS` 启用中断。 - -ESP-IDF FreeRTOS 提供相同的 API,但只能在当前核上启用或禁用中断。 +- 如果核 A 是核 0,则挂起的时钟计数将回退,补上丢失的时钟计数。 .. warning:: - 在 Vanilla FreeRTOS 和一般的单核系统中,禁用中断是实现互斥的有效方法。但在 SMP 系统中,禁用中断 **不能** 确保实现互斥。详情请参阅 :ref:`critical-sections`。 - + IDF FreeRTOS 上的调度器挂起仅暂停特定核上的调度,因此调度器挂起 **不能** 确保访问共享数据时任务互斥。如果需要互斥,请使用适当的锁定机制,如互斥锁或自旋锁。 .. ------------------------------------------------ Critical Sections -------------------------------------------------- -.. _critical-sections: - 临界区 ------ +禁用中断 +^^^^^^^^ + +Vanilla FreeRTOS 支持通过调用 :c:macro:`taskDISABLE_INTERRUPTS` 和 :c:macro:`taskENABLE_INTERRUPTS` 分别禁用和启用中断。IDF FreeRTOS 提供了相同的 API,但中断只能在当前核上禁用或启用。 + +在 Vanilla FreeRTOS 以及其他普通单核系统中,禁用中断可以有效实现互斥,**但在 SMP 系统中,禁用中断并不能确保实现互斥**,而应使用有自旋锁的临界区以实现互斥。 + API 变更 ^^^^^^^^ @@ -351,7 +323,7 @@ Vanilla FreeRTOS 通过禁用中断实现临界区 (Critical Section),以防 - ``taskENTER_CRITICAL_FROM_ISR()`` 通过禁用中断嵌套从 ISR 进入临界区 - ``taskEXIT_CRITICAL_FROM_ISR()`` 通过重新启用中断嵌套从 ISR 退出临界区 -然而,在 SMP 系统中,仅禁用中断并不能构成临界区,因为存在其他核意味着共享资源仍可以同时访问。因此,ESP-IDF FreeRTOS 中的临界区是使用自旋锁实现的。为适应自旋锁,ESP-IDF FreeRTOS 中的临界区 API 包含一个额外的自旋锁参数,具体如下: +然而,在 SMP 系统中,仅禁用中断并不能构成临界区,因为存在其他核意味着共享资源仍可以同时访问。因此,IDF FreeRTOS 中的临界区是使用自旋锁实现的。为适应自旋锁,IDF FreeRTOS 中的临界区 API 包含一个额外的自旋锁参数,具体如下: - 自旋锁为 ``portMUX_TYPE`` (**请勿与 FreeRTOS 互斥混淆**) - ``taskENTER_CRITICAL(&spinlock)`` 从任务上下文进入临界区 @@ -361,7 +333,7 @@ Vanilla FreeRTOS 通过禁用中断实现临界区 (Critical Section),以防 .. note:: - 临界区 API 可以递归调用,即可以嵌套使用临界区。只要退出临界区的次数与进入的次数相同,多次递归进入临界区就是有效的。但是,由于临界区可以针对不同的自旋锁,因此在递归进入临界区时,应注意避免死锁。 + 临界区 API 可以递归调用,即可以嵌套使用临界区。只要退出临界区的次数与进入的次数相同,多次递归进入临界区就是有效的。但是,由于临界区可以针对不同的自旋锁,因此在递归进入临界区时,应注意避免死锁。 自旋锁可以静态或动态分配。因此,提供了静态和动态初始化自旋锁的宏,如以下代码片段所示。 @@ -369,35 +341,35 @@ Vanilla FreeRTOS 通过禁用中断实现临界区 (Critical Section),以防 .. code:: c - // 静态分配并初始化自旋锁 - static portMUX_TYPE my_spinlock = portMUX_INITIALIZER_UNLOCKED; + // 静态分配并初始化自旋锁 + static portMUX_TYPE my_spinlock = portMUX_INITIALIZER_UNLOCKED; - void some_function(void) - { - taskENTER_CRITICAL(&my_spinlock); - // 此时已处于临界区 - taskEXIT_CRITICAL(&my_spinlock); - } + void some_function(void) + { + taskENTER_CRITICAL(&my_spinlock); + // 此时已处于临界区 + taskEXIT_CRITICAL(&my_spinlock); + } - 静态分配自旋锁并使用 ``portMUX_INITIALIZE()`` 初始化: .. code:: c - // 动态分配自旋锁 - portMUX_TYPE *my_spinlock = malloc(sizeof(portMUX_TYPE)); - // 动态初始化自旋锁 - portMUX_INITIALIZE(my_spinlock); + // 动态分配自旋锁 + portMUX_TYPE *my_spinlock = malloc(sizeof(portMUX_TYPE)); + // 动态初始化自旋锁 + portMUX_INITIALIZE(my_spinlock); - ... + ... - taskENTER_CRITICAL(my_spinlock); - // 访问资源 - taskEXIT_CRITICAL(my_spinlock); + taskENTER_CRITICAL(my_spinlock); + // 访问资源 + taskEXIT_CRITICAL(my_spinlock); 实现 ^^^^ -ESP-IDF FreeRTOS 中,特定核进入和退出临界区的过程如下: +IDF FreeRTOS 中,特定核进入和退出临界区的过程如下: - 对于 ``taskENTER_CRITICAL(&spinlock)`` 或 ``taskENTER_CRITICAL_ISR(&spinlock)`` @@ -437,43 +409,52 @@ ESP-IDF FreeRTOS 中,特定核进入和退出临界区的过程如下: 通常情况下,当发生上下文切换时: - - CPU 寄存器的当前状态保存到要切出的任务栈中 - - CPU 寄存器的先前保存状态从要切入的任务栈中加载 + - 核寄存器的当前状态保存到要切出的任务栈中 + - 核寄存器的先前保存状态从要切入的任务栈中加载 - 然而,ESP-IDF FreeRTOS 为 CPU 的浮点单元 (FPU) 寄存器实现了延迟上下文切换。换句话说,当在特定核上(如 CPU0)发生上下文切换时,核的 FPU 寄存器状态不会立即保存到要被切出的任务的堆栈中(如任务 A)。FPU 的寄存器在发生以下情况前将保持不变: + 然而,IDF FreeRTOS 为核的浮点运算单元 (FPU) 寄存器实现了延迟上下文切换。换句话说,当在特定核上(如核 0)发生上下文切换时,核的 FPU 寄存器状态不会立即保存到要被切出的任务的堆栈中(如任务 A)。FPU 的寄存器在发生以下情况前将保持不变: - 另一个任务(如任务 B)在同一核上运行并使用 FPU,这将触发异常,将 FPU 寄存器保存到任务 A 的堆栈中。 - 任务 A 重新调度到同一核并继续执行。在这种情况下,不需要保存和恢复 FPU 的寄存器。 - 然而,由于任务并未固定到某一核上,可以随意调度(如任务 A 切换到 CPU1),因此很难实现跨核复制和恢复 FPU 寄存器状态。因此,当任务在其执行流程中用 ``float`` 类型使用 FPU 时,ESP-IDF FreeRTOS 会自动将任务固定到当前正在运行的核上,确保所有使用 FPU 的任务始终在特定核上运行。 + 然而,由于任务并未分配给某一核,可以随意调度(如任务 A 切换到核 1),因此很难实现跨核复制和恢复 FPU 寄存器状态。因此,当任务在其执行流程中用 ``float`` 类型使用 FPU 时,IDF FreeRTOS 会自动将任务分配给当前正在运行的核,确保所有使用 FPU 的任务始终在特定核上运行。 - 此外,请注意,由于 FPU 寄存器状态与特定任务相关联,ESP-IDF FreeRTOS 默认不支持在中断上下文中使用 FPU。 + 此外,请注意,由于 FPU 寄存器状态与特定任务相关联,IDF FreeRTOS 默认不支持在中断上下文中使用 FPU。 - .. only: esp32 + .. only:: esp32 - .. note:: + .. note:: - 如需在 ISR 例程中使用 ``float`` 类型,请参考配置选项:ref:`CONFIG_FREERTOS_FPU_IN_ISR`。 + 如需在 ISR 例程中使用 ``float`` 类型,请参考配置选项:ref:`CONFIG_FREERTOS_FPU_IN_ISR`。 .. note:: - 具有 FPU 的 ESP 芯片不支持双精度浮点运算 ``double`` 的硬件加速。``double`` 通过软件实现,因此比起 ``float`` 类型,``double`` 操作可能消耗更多 CPU 时间。 + 具有 FPU 的 ESP 芯片不支持双精度浮点运算 ``double`` 的硬件加速。``double`` 通过软件实现,因此比起 ``float`` 类型,``double`` 操作可能消耗更多 CPU 时间。 .. -------------------------------------------------- Single Core ----------------------------------------------------- -.. _freertos-smp-single-core: +.. _freertos-idf-single-core: -单核 ESP-IDF FreeRTOS -^^^^^^^^^^^^^^^^^^^^^ +单核模式 +^^^^^^^^ -尽管 ESP-IDF FreeRTOS 为 SMP 调度器,仍需要考虑单核 ESP 芯片,如 ESP32-S2 和 ESP32-C3。为这些芯片构建 ESP-IDF 应用程序时,同样使用 ESP-IDF FreeRTOS,但核的数量将设置为 ``1``,即 :ref:`CONFIG_FREERTOS_UNICORE` 将始终对单核芯片启用。 +尽管 IDF FreeRTOS 是为双核 SMP 专门设计的,但也可通过启用 :ref:`CONFIG_FREERTOS_UNICORE` 选项,将 IDF FreeRTOS 配置为支持单核。 -对于 ESP32 和 ESP32-S3 等多核芯片也可以设置 :ref:`CONFIG_FREERTOS_UNICORE`,启用该选项后 ESP-IDF FreeRTOS 仅在 CPU0 上运行,其他核都将处于非活动状态。 +对于 ESP32-S2 和 ESP32-C3 等单核芯片,:ref:`CONFIG_FREERTOS_UNICORE` 选项始终启用。对于 ESP32 和 ESP32-S3 等多核芯片也可以设置 :ref:`CONFIG_FREERTOS_UNICORE`,对于多核目标(如 ESP32 和 ESP32-S3),也可以设置 :ref:`CONFIG_FREERTOS_UNICORE`,但启用该选项后应用仅在核 0 上运行。 -.. note:: +在单核模式下,IDF FreeRTOS 与 Vanilla FreeRTOS 完全相同,因此无需考虑前文提到的对内核行为的 SMP 更改。因此,在单核模式下构建 IDF FreeRTOS 具有以下特点: + +- 内核在临界区内执行的所有操作都是确定的(即在临界区内不走链表)。 +- 恢复了 Vanilla FreeRTOS 调度算法(包括完美的轮转时间分片)。 +- 移除了所有单核构建中的 SMP 专用数据。 + +在单核模式下仍可调用 SMP API,这些 API 仍然保持公开,以便为单核和多核构建源代码,而无需调用不同的 API 集。不过,SMP API 在单核模式下不会展示任何 SMP 行为,因此实际上等同于其对应的单核模式 API。例如: + +- 任何 ``...ForCore(..., BaseType_t xCoreID)`` SMP API 将只接受 ``0`` 为 ``xCoreID`` 的有效值。 +- ``...PinnedToCore()`` 任务创建 API 将直接忽略 ``xCoreID`` 核亲和参数。 +- 临界区 API 仍需要自旋锁参数,但不会使用自旋锁,临界区将恢复为仅用于禁用/启用中断。 - 请注意,开启 :ref:`CONFIG_FREERTOS_UNICORE` **不等于运行 Vanilla FreeRTOS**,此时仍然可以调用 ESP-IDF FreeRTOS 的附加 API,且即使为单核编译,ESP-IDF FreeRTOS 的行为变化仍会导致一定的性能开销。 .. ------------------------------------------------- API References ---------------------------------------------------- diff --git a/docs/zh_CN/migration-guides/release-5.x/5.3/peripherals.rst b/docs/zh_CN/migration-guides/release-5.x/5.3/peripherals.rst index 09d3f4c59c02..743db13cf865 100644 --- a/docs/zh_CN/migration-guides/release-5.x/5.3/peripherals.rst +++ b/docs/zh_CN/migration-guides/release-5.x/5.3/peripherals.rst @@ -24,6 +24,8 @@ - `esp_driver_sdm` - Sigma-Delta 调制器驱动 - `esp_driver_i2c` - I2C 驱动 - `esp_driver_uart` - UART 驱动 +- `esp_driver_ledc` - LEDC 驱动 +- `esp_driver_parlio` - 并行 IO 驱动 为了兼容性,原来的 `driver` 组件仍然存在,并作为一个 “all-in-one" 的组件,将以上这些 `esp_driver_xyz` 组件注册成自己的公共依赖。换句话说,你无需修改既有项目的 CMake 文件,但是你现在多了一个途径去指定你项目依赖的具体的外设驱动。 diff --git a/examples/README.md b/examples/README.md index 14877e8bbd41..54a00a9ed85a 100644 --- a/examples/README.md +++ b/examples/README.md @@ -14,6 +14,7 @@ The examples are grouped into subdirectories by category. Each category director - `cxx` C++ language utilization examples and experimental components. - `ethernet` Ethernet network examples. - `get-started` Simple examples with minimal functionality. Good start point for beginners. +- `ieee802154` IEEE802.15.4 examples. - `mesh` Wi-Fi Mesh examples. - `network` Examples related to general network environment, test & analysis. - `openthread` OpenThread examples. diff --git a/examples/bluetooth/bluedroid/ble/ble_compatibility_test/main/ble_compatibility_test.c b/examples/bluetooth/bluedroid/ble/ble_compatibility_test/main/ble_compatibility_test.c index 942aebb89823..31b21b0a2f76 100644 --- a/examples/bluetooth/bluedroid/ble/ble_compatibility_test/main/ble_compatibility_test.c +++ b/examples/bluetooth/bluedroid/ble/ble_compatibility_test/main/ble_compatibility_test.c @@ -247,6 +247,10 @@ static const esp_gatts_attr_db_t gatt_db[HRS_IDX_NB] = static void show_bonded_devices(void) { int dev_num = esp_ble_get_bond_device_num(); + if (dev_num == 0) { + ESP_LOGI(EXAMPLE_TAG, "Bonded devices number zero\n"); + return; + } esp_ble_bond_dev_t *dev_list = (esp_ble_bond_dev_t *)malloc(sizeof(esp_ble_bond_dev_t) * dev_num); if (!dev_list) { @@ -269,6 +273,10 @@ static void show_bonded_devices(void) static void __attribute__((unused)) remove_all_bonded_devices(void) { int dev_num = esp_ble_get_bond_device_num(); + if (dev_num == 0) { + ESP_LOGI(EXAMPLE_TAG, "Bonded devices number zero\n"); + return; + } esp_ble_bond_dev_t *dev_list = (esp_ble_bond_dev_t *)malloc(sizeof(esp_ble_bond_dev_t) * dev_num); if (!dev_list) { diff --git a/examples/bluetooth/bluedroid/ble/ble_ibeacon/main/esp_ibeacon_api.h b/examples/bluetooth/bluedroid/ble/ble_ibeacon/main/esp_ibeacon_api.h index b2bbb3213944..c4ce40945bb9 100644 --- a/examples/bluetooth/bluedroid/ble/ble_ibeacon/main/esp_ibeacon_api.h +++ b/examples/bluetooth/bluedroid/ble/ble_ibeacon/main/esp_ibeacon_api.h @@ -23,9 +23,6 @@ #include "esp_gap_ble_api.h" #include "esp_gattc_api.h" - -/* Because current ESP IDF version doesn't support scan and adv simultaneously, - * so iBeacon sender and receiver should not run simultaneously */ #define IBEACON_SENDER 0 #define IBEACON_RECEIVER 1 #define IBEACON_MODE CONFIG_IBEACON_MODE diff --git a/examples/bluetooth/bluedroid/ble/gatt_security_server/main/example_ble_sec_gatts_demo.c b/examples/bluetooth/bluedroid/ble/gatt_security_server/main/example_ble_sec_gatts_demo.c index 3371dbd69df0..4ce6dc43b5a5 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_security_server/main/example_ble_sec_gatts_demo.c +++ b/examples/bluetooth/bluedroid/ble/gatt_security_server/main/example_ble_sec_gatts_demo.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -257,6 +257,10 @@ static char *esp_auth_req_to_str(esp_ble_auth_req_t auth_req) static void show_bonded_devices(void) { int dev_num = esp_ble_get_bond_device_num(); + if (dev_num == 0) { + ESP_LOGI(GATTS_TABLE_TAG, "Bonded devices number zero\n"); + return; + } esp_ble_bond_dev_t *dev_list = (esp_ble_bond_dev_t *)malloc(sizeof(esp_ble_bond_dev_t) * dev_num); if (!dev_list) { @@ -277,6 +281,10 @@ static void show_bonded_devices(void) static void __attribute__((unused)) remove_all_bonded_devices(void) { int dev_num = esp_ble_get_bond_device_num(); + if (dev_num == 0) { + ESP_LOGI(GATTS_TABLE_TAG, "Bonded devices number zero\n"); + return; + } esp_ble_bond_dev_t *dev_list = (esp_ble_bond_dev_t *)malloc(sizeof(esp_ble_bond_dev_t) * dev_num); if (!dev_list) { diff --git a/examples/bluetooth/bluedroid/ble_50/ble50_security_server/main/ble50_sec_gatts_demo.c b/examples/bluetooth/bluedroid/ble_50/ble50_security_server/main/ble50_sec_gatts_demo.c index ecba57764b02..abd4071d126f 100644 --- a/examples/bluetooth/bluedroid/ble_50/ble50_security_server/main/ble50_sec_gatts_demo.c +++ b/examples/bluetooth/bluedroid/ble_50/ble50_security_server/main/ble50_sec_gatts_demo.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -228,6 +228,10 @@ static char *esp_auth_req_to_str(esp_ble_auth_req_t auth_req) static void show_bonded_devices(void) { int dev_num = esp_ble_get_bond_device_num(); + if (dev_num == 0) { + ESP_LOGI(GATTS_TABLE_TAG, "Bonded devices number zero\n"); + return; + } esp_ble_bond_dev_t *dev_list = (esp_ble_bond_dev_t *)malloc(sizeof(esp_ble_bond_dev_t) * dev_num); if (!dev_list) { @@ -246,6 +250,10 @@ static void show_bonded_devices(void) static void __attribute__((unused)) remove_all_bonded_devices(void) { int dev_num = esp_ble_get_bond_device_num(); + if (dev_num == 0) { + ESP_LOGI(GATTS_TABLE_TAG, "Bonded devices number zero\n"); + return; + } esp_ble_bond_dev_t *dev_list = (esp_ble_bond_dev_t *)malloc(sizeof(esp_ble_bond_dev_t) * dev_num); if (!dev_list) { diff --git a/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/main/bt_app_av.c b/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/main/bt_app_av.c index 0600992cda0e..ceb10b3b6f0e 100644 --- a/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/main/bt_app_av.c +++ b/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/main/bt_app_av.c @@ -79,7 +79,7 @@ static esp_a2d_audio_state_t s_audio_state = ESP_A2D_AUDIO_STATE_STOPPED; /* audio stream datapath state */ static const char *s_a2d_conn_state_str[] = {"Disconnected", "Connecting", "Connected", "Disconnecting"}; /* connection state in string */ -static const char *s_a2d_audio_state_str[] = {"Suspended", "Stopped", "Started"}; +static const char *s_a2d_audio_state_str[] = {"Suspended", "Started"}; /* audio stream datapath state in string */ static esp_avrc_rn_evt_cap_mask_t s_avrc_peer_rn_cap; /* AVRC target notification capability bit mask */ diff --git a/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/bt_app_av.c b/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/bt_app_av.c index 0600992cda0e..ceb10b3b6f0e 100644 --- a/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/bt_app_av.c +++ b/examples/bluetooth/bluedroid/coex/a2dp_gatts_coex/main/bt_app_av.c @@ -79,7 +79,7 @@ static esp_a2d_audio_state_t s_audio_state = ESP_A2D_AUDIO_STATE_STOPPED; /* audio stream datapath state */ static const char *s_a2d_conn_state_str[] = {"Disconnected", "Connecting", "Connected", "Disconnecting"}; /* connection state in string */ -static const char *s_a2d_audio_state_str[] = {"Suspended", "Stopped", "Started"}; +static const char *s_a2d_audio_state_str[] = {"Suspended", "Started"}; /* audio stream datapath state in string */ static esp_avrc_rn_evt_cap_mask_t s_avrc_peer_rn_cap; /* AVRC target notification capability bit mask */ diff --git a/examples/bluetooth/bluedroid/coex/gattc_gatts_coex/main/gattc_gatts_coex.c b/examples/bluetooth/bluedroid/coex/gattc_gatts_coex/main/gattc_gatts_coex.c index d7828cad85aa..573eca176d8b 100644 --- a/examples/bluetooth/bluedroid/coex/gattc_gatts_coex/main/gattc_gatts_coex.c +++ b/examples/bluetooth/bluedroid/coex/gattc_gatts_coex/main/gattc_gatts_coex.c @@ -26,7 +26,6 @@ #include "esp_system.h" #include "sdkconfig.h" - #define GATTS_SERVICE_UUID_TEST_A 0x00FF #define GATTS_CHAR_UUID_TEST_A 0xFF01 #define GATTS_NUM_HANDLE_TEST_A 4 @@ -58,6 +57,9 @@ static const char remote_device_name[] = "ESP_GATTS_DEMO"; +// record peer gatt server address +esp_bd_addr_t peer_gatts_addr = {0}; + typedef struct { uint8_t *prepare_buf; int prepare_len; @@ -244,13 +246,13 @@ static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param } break; case ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT: - ESP_LOGI(COEX_TAG, "update connection params status = %d, min_int = %d, max_int = %d,conn_int = %d,latency = %d, timeout = %d", - param->update_conn_params.status, - param->update_conn_params.min_int, - param->update_conn_params.max_int, - param->update_conn_params.conn_int, - param->update_conn_params.latency, - param->update_conn_params.timeout); + ESP_LOGI(COEX_TAG, "update connection params status = %d, min_int = %d, max_int = %d,conn_int = %d,latency = %d, timeout = %d", + param->update_conn_params.status, + param->update_conn_params.min_int, + param->update_conn_params.max_int, + param->update_conn_params.conn_int, + param->update_conn_params.latency, + param->update_conn_params.timeout); break; case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT: if (param->scan_stop_cmpl.status != ESP_BT_STATUS_SUCCESS) { @@ -285,13 +287,23 @@ static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param connect = true; ESP_LOGI(COEX_TAG, "connect to the remote device %s", remote_device_name); esp_ble_gap_stop_scanning(); - esp_ble_gattc_open(gattc_profile_tab[GATTC_PROFILE_C_APP_ID].gattc_if, scan_result->scan_rst.bda, scan_result->scan_rst.ble_addr_type, true); + + // Initiate GATT connection with the remote device, + // If ble physical connection is set up, ESP_GATTS_CONNECT_EVT and ESP_GATTC_CONNECT_EVT event will come + esp_ble_gattc_open(gattc_profile_tab[GATTC_PROFILE_C_APP_ID].gattc_if, + scan_result->scan_rst.bda, + scan_result->scan_rst.ble_addr_type, + true); + + // Update peer gatt server address + memcpy(peer_gatts_addr, scan_result->scan_rst.bda, sizeof(esp_bd_addr_t)); + esp_log_buffer_hex("the remote device addr", peer_gatts_addr, sizeof(esp_bd_addr_t)); } } } break; case ESP_GAP_SEARCH_INQ_CMPL_EVT: - ESP_LOGI(COEX_TAG, "ESP_GAP_SEARCH_INQ_CMPL_EVT, scan stop"); + ESP_LOGI(COEX_TAG, "ESP_GAP_SEARCH_INQ_CMPL_EVT, scan stop"); break; default: break; @@ -317,13 +329,16 @@ static void gattc_profile_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ break; case ESP_GATTC_CONNECT_EVT: { ESP_LOGI(COEX_TAG, "ESP_GATTC_CONNECT_EVT conn_id %d, if %d", p_data->connect.conn_id, gattc_if); - gattc_profile_tab[GATTC_PROFILE_C_APP_ID].conn_id = p_data->connect.conn_id; - memcpy(gattc_profile_tab[GATTC_PROFILE_C_APP_ID].remote_bda, p_data->connect.remote_bda, sizeof(esp_bd_addr_t)); - ESP_LOGI(COEX_TAG, "REMOTE BDA:"); - esp_log_buffer_hex(COEX_TAG, gattc_profile_tab[GATTC_PROFILE_C_APP_ID].remote_bda, sizeof(esp_bd_addr_t)); - esp_err_t mtu_ret = esp_ble_gattc_send_mtu_req (gattc_if, p_data->connect.conn_id); - if (mtu_ret) { - ESP_LOGE(COEX_TAG, "config MTU error, error code = %x", mtu_ret); + if (!memcmp(peer_gatts_addr, param->connect.remote_bda, sizeof(esp_bd_addr_t))) { + // Update gattc_profile_tab if peer device is a gatt server + gattc_profile_tab[GATTC_PROFILE_C_APP_ID].conn_id = p_data->connect.conn_id; + memcpy(gattc_profile_tab[GATTC_PROFILE_C_APP_ID].remote_bda, p_data->connect.remote_bda, sizeof(esp_bd_addr_t)); + ESP_LOGI(COEX_TAG, "REMOTE BDA:"); + esp_log_buffer_hex(COEX_TAG, gattc_profile_tab[GATTC_PROFILE_C_APP_ID].remote_bda, sizeof(esp_bd_addr_t)); + esp_err_t mtu_ret = esp_ble_gattc_send_mtu_req(gattc_if, p_data->connect.conn_id); + if (mtu_ret) { + ESP_LOGE(COEX_TAG, "config MTU error, error code = %x", mtu_ret); + } } break; } @@ -344,7 +359,7 @@ static void gattc_profile_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ break; case ESP_GATTC_CFG_MTU_EVT: if (param->cfg_mtu.status != ESP_GATT_OK) { - ESP_LOGE(COEX_TAG,"config mtu failed, error status = %x", param->cfg_mtu.status); + ESP_LOGE(COEX_TAG, "config mtu failed, error status = %x", param->cfg_mtu.status); } ESP_LOGI(COEX_TAG, "ESP_GATTC_CFG_MTU_EVT, Status %d, MTU %d, conn_id %d", param->cfg_mtu.status, param->cfg_mtu.mtu, param->cfg_mtu.conn_id); break; @@ -365,7 +380,7 @@ static void gattc_profile_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ ESP_LOGE(COEX_TAG, "search service failed, error status = %x", p_data->search_cmpl.status); break; } - if(p_data->search_cmpl.searched_service_source == ESP_GATT_SERVICE_FROM_REMOTE_DEVICE) { + if (p_data->search_cmpl.searched_service_source == ESP_GATT_SERVICE_FROM_REMOTE_DEVICE) { ESP_LOGI(COEX_TAG, "Get service information from remote device"); } else if (p_data->search_cmpl.searched_service_source == ESP_GATT_SERVICE_FROM_NVS_FLASH) { ESP_LOGI(COEX_TAG, "Get service information from flash"); @@ -375,13 +390,13 @@ static void gattc_profile_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ ESP_LOGI(COEX_TAG, "ESP_GATTC_SEARCH_CMPL_EVT"); if (get_server) { uint16_t count = 0; - esp_gatt_status_t status = esp_ble_gattc_get_attr_count( gattc_if, - p_data->search_cmpl.conn_id, - ESP_GATT_DB_CHARACTERISTIC, - gattc_profile_tab[GATTC_PROFILE_C_APP_ID].service_start_handle, - gattc_profile_tab[GATTC_PROFILE_C_APP_ID].service_end_handle, - INVALID_HANDLE, - &count); + esp_gatt_status_t status = esp_ble_gattc_get_attr_count(gattc_if, + p_data->search_cmpl.conn_id, + ESP_GATT_DB_CHARACTERISTIC, + gattc_profile_tab[GATTC_PROFILE_C_APP_ID].service_start_handle, + gattc_profile_tab[GATTC_PROFILE_C_APP_ID].service_end_handle, + INVALID_HANDLE, + &count); if (status != ESP_GATT_OK) { ESP_LOGE(COEX_TAG, "esp_ble_gattc_get_attr_count error"); } @@ -391,14 +406,14 @@ static void gattc_profile_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ if (!char_elem_result) { ESP_LOGE(COEX_TAG, "gattc no mem\n"); break; - }else { - status = esp_ble_gattc_get_char_by_uuid( gattc_if, - p_data->search_cmpl.conn_id, - gattc_profile_tab[GATTC_PROFILE_C_APP_ID].service_start_handle, - gattc_profile_tab[GATTC_PROFILE_C_APP_ID].service_end_handle, - remote_filter_char_uuid, - char_elem_result, - &count); + } else { + status = esp_ble_gattc_get_char_by_uuid(gattc_if, + p_data->search_cmpl.conn_id, + gattc_profile_tab[GATTC_PROFILE_C_APP_ID].service_start_handle, + gattc_profile_tab[GATTC_PROFILE_C_APP_ID].service_end_handle, + remote_filter_char_uuid, + char_elem_result, + &count); if (status != ESP_GATT_OK) { ESP_LOGE(COEX_TAG, "esp_ble_gattc_get_char_by_uuid error\n"); free(char_elem_result); @@ -409,7 +424,7 @@ static void gattc_profile_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ /* Every service have only one char in our 'ESP_GATTS_DEMO' demo, so we used first 'char_elem_result' */ if (count > 0 && (char_elem_result[0].properties & ESP_GATT_CHAR_PROP_BIT_NOTIFY)) { gattc_profile_tab[GATTC_PROFILE_C_APP_ID].char_handle = char_elem_result[0].char_handle; - esp_ble_gattc_register_for_notify (gattc_if, gattc_profile_tab[GATTC_PROFILE_C_APP_ID].remote_bda, char_elem_result[0].char_handle); + esp_ble_gattc_register_for_notify(gattc_if, gattc_profile_tab[GATTC_PROFILE_C_APP_ID].remote_bda, char_elem_result[0].char_handle); } } /* free char_elem_result */ @@ -419,7 +434,7 @@ static void gattc_profile_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ ESP_LOGE(COEX_TAG, "no char found\n"); } } - break; + break; case ESP_GATTC_REG_FOR_NOTIFY_EVT: { ESP_LOGI(COEX_TAG, "ESP_GATTC_REG_FOR_NOTIFY_EVT"); if (p_data->reg_for_notify.status != ESP_GATT_OK) { @@ -427,13 +442,13 @@ static void gattc_profile_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ } else { uint16_t count = 0; uint16_t notify_en = 1; - esp_gatt_status_t ret_status = esp_ble_gattc_get_attr_count( gattc_if, - gattc_profile_tab[GATTC_PROFILE_C_APP_ID].conn_id, - ESP_GATT_DB_DESCRIPTOR, - gattc_profile_tab[GATTC_PROFILE_C_APP_ID].service_start_handle, - gattc_profile_tab[GATTC_PROFILE_C_APP_ID].service_end_handle, - gattc_profile_tab[GATTC_PROFILE_C_APP_ID].char_handle, - &count); + esp_gatt_status_t ret_status = esp_ble_gattc_get_attr_count(gattc_if, + gattc_profile_tab[GATTC_PROFILE_C_APP_ID].conn_id, + ESP_GATT_DB_DESCRIPTOR, + gattc_profile_tab[GATTC_PROFILE_C_APP_ID].service_start_handle, + gattc_profile_tab[GATTC_PROFILE_C_APP_ID].service_end_handle, + gattc_profile_tab[GATTC_PROFILE_C_APP_ID].char_handle, + &count); if (ret_status != ESP_GATT_OK) { ESP_LOGE(COEX_TAG, "esp_ble_gattc_get_attr_count error"); } @@ -443,12 +458,12 @@ static void gattc_profile_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ ESP_LOGE(COEX_TAG, "malloc error, gattc no mem\n"); break; } else { - ret_status = esp_ble_gattc_get_descr_by_char_handle( gattc_if, - gattc_profile_tab[GATTC_PROFILE_C_APP_ID].conn_id, - p_data->reg_for_notify.handle, - notify_descr_uuid, - descr_elem_result, - &count); + ret_status = esp_ble_gattc_get_descr_by_char_handle(gattc_if, + gattc_profile_tab[GATTC_PROFILE_C_APP_ID].conn_id, + p_data->reg_for_notify.handle, + notify_descr_uuid, + descr_elem_result, + &count); if (ret_status != ESP_GATT_OK) { ESP_LOGE(COEX_TAG, "esp_ble_gattc_get_descr_by_char_handle error\n"); free(descr_elem_result); @@ -457,13 +472,13 @@ static void gattc_profile_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ } /* Every char has only one descriptor in our 'ESP_GATTS_DEMO' demo, so we used first 'descr_elem_result' */ if (count > 0 && descr_elem_result[0].uuid.len == ESP_UUID_LEN_16 && descr_elem_result[0].uuid.uuid.uuid16 == ESP_GATT_UUID_CHAR_CLIENT_CONFIG) { - ret_status = esp_ble_gattc_write_char_descr( gattc_if, - gattc_profile_tab[GATTC_PROFILE_C_APP_ID].conn_id, - descr_elem_result[0].handle, - sizeof(notify_en), - (uint8_t *)¬ify_en, - ESP_GATT_WRITE_TYPE_RSP, - ESP_GATT_AUTH_REQ_NONE); + ret_status = esp_ble_gattc_write_char_descr(gattc_if, + gattc_profile_tab[GATTC_PROFILE_C_APP_ID].conn_id, + descr_elem_result[0].handle, + sizeof(notify_en), + (uint8_t *)¬ify_en, + ESP_GATT_WRITE_TYPE_RSP, + ESP_GATT_AUTH_REQ_NONE); } if (ret_status != ESP_GATT_OK) { @@ -499,13 +514,13 @@ static void gattc_profile_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ for (int i = 0; i < sizeof(write_char_data); ++ i) { write_char_data[i] = i % 256; } - esp_ble_gattc_write_char( gattc_if, - gattc_profile_tab[GATTC_PROFILE_C_APP_ID].conn_id, - gattc_profile_tab[GATTC_PROFILE_C_APP_ID].char_handle, - sizeof(write_char_data), - write_char_data, - ESP_GATT_WRITE_TYPE_RSP, - ESP_GATT_AUTH_REQ_NONE); + esp_ble_gattc_write_char(gattc_if, + gattc_profile_tab[GATTC_PROFILE_C_APP_ID].conn_id, + gattc_profile_tab[GATTC_PROFILE_C_APP_ID].char_handle, + sizeof(write_char_data), + write_char_data, + ESP_GATT_WRITE_TYPE_RSP, + ESP_GATT_AUTH_REQ_NONE); break; case ESP_GATTC_SRVC_CHG_EVT: { esp_bd_addr_t bda; @@ -522,8 +537,11 @@ static void gattc_profile_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ ESP_LOGI(COEX_TAG, "write char success "); break; case ESP_GATTC_DISCONNECT_EVT: { - connect = false; - get_server = false; + if (!memcmp(peer_gatts_addr, p_data->disconnect.remote_bda, sizeof(esp_bd_addr_t))) { + // Update connect flag and get_server flag if peer device is a gatt server + connect = false; + get_server = false; + } ESP_LOGI(COEX_TAG, "ESP_GATTC_DISCONNECT_EVT, reason = %d", p_data->disconnect.reason); break; } @@ -532,7 +550,8 @@ static void gattc_profile_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ } } -static void example_write_event_env(esp_gatt_if_t gatts_if, prepare_type_env_t *prepare_write_env, esp_ble_gatts_cb_param_t *param) { +static void example_write_event_env(esp_gatt_if_t gatts_if, prepare_type_env_t *prepare_write_env, esp_ble_gatts_cb_param_t *param) +{ esp_gatt_status_t status = ESP_GATT_OK; if (param->write.need_rsp) { if (param->write.is_prep) { @@ -542,7 +561,7 @@ static void example_write_event_env(esp_gatt_if_t gatts_if, prepare_type_env_t * status = ESP_GATT_INVALID_ATTR_LEN; } if (status == ESP_GATT_OK && prepare_write_env->prepare_buf == NULL) { - prepare_write_env->prepare_buf = (uint8_t *)malloc(PREPARE_BUF_MAX_SIZE*sizeof(uint8_t)); + prepare_write_env->prepare_buf = (uint8_t *)malloc(PREPARE_BUF_MAX_SIZE * sizeof(uint8_t)); prepare_write_env->prepare_len = 0; if (prepare_write_env->prepare_buf == NULL) { ESP_LOGE(COEX_TAG, "Gatt_server prep no mem"); @@ -580,11 +599,12 @@ static void example_write_event_env(esp_gatt_if_t gatts_if, prepare_type_env_t * } } -static void example_exec_write_event_env(prepare_type_env_t *prepare_write_env, esp_ble_gatts_cb_param_t *param) { +static void example_exec_write_event_env(prepare_type_env_t *prepare_write_env, esp_ble_gatts_cb_param_t *param) +{ if (param->exec_write.exec_write_flag == ESP_GATT_PREP_WRITE_EXEC) { esp_log_buffer_hex(COEX_TAG, prepare_write_env->prepare_buf, prepare_write_env->prepare_len); } else { - ESP_LOGI(COEX_TAG,"ESP_GATT_PREP_WRITE_CANCEL"); + ESP_LOGI(COEX_TAG, "ESP_GATT_PREP_WRITE_CANCEL"); } if (prepare_write_env->prepare_buf) { free(prepare_write_env->prepare_buf); @@ -593,7 +613,8 @@ static void example_exec_write_event_env(prepare_type_env_t *prepare_write_env, prepare_write_env->prepare_len = 0; } -static void gatts_profile_a_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) { +static void gatts_profile_a_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) +{ switch (event) { case ESP_GATTS_REG_EVT: ESP_LOGI(COEX_TAG, "REGISTER_APP_EVT, status %d, app_id %d", param->reg.status, param->reg.app_id); @@ -654,24 +675,24 @@ static void gatts_profile_a_event_handler(esp_gatts_cb_event_t event, esp_gatt_i ESP_LOGI(COEX_TAG, "GATT_WRITE_EVT, value len %d, value :", param->write.len); esp_log_buffer_hex(COEX_TAG, param->write.value, param->write.len); if (gatts_profile_tab[GATTS_PROFILE_A_APP_ID].descr_handle == param->write.handle && param->write.len == 2) { - uint16_t descr_value = param->write.value[1]<<8 | param->write.value[0]; + uint16_t descr_value = param->write.value[1] << 8 | param->write.value[0]; if (descr_value == NOTIFY_ENABLE) { if (a_property & ESP_GATT_CHAR_PROP_BIT_NOTIFY) { ESP_LOGI(COEX_TAG, "notify enable"); uint8_t notify_data[15]; for (int i = 0; i < sizeof(notify_data); ++ i) { - notify_data[i] = i%0xff; + notify_data[i] = i % 0xff; } //the size of notify_data[] need less than MTU size esp_ble_gatts_send_indicate(gatts_if, param->write.conn_id, gatts_profile_tab[GATTS_PROFILE_A_APP_ID].char_handle, - sizeof(notify_data), notify_data, false); + sizeof(notify_data), notify_data, false); } } else if (descr_value == INDICATE_ENABLE) { if (a_property & ESP_GATT_CHAR_PROP_BIT_INDICATE) { ESP_LOGI(COEX_TAG, "indicate enable"); uint8_t indicate_data[15]; for (int i = 0; i < sizeof(indicate_data); ++ i) { - indicate_data[i] = i%0xff; + indicate_data[i] = i % 0xff; } //the size of indicate_data[] need less than MTU size esp_ble_gatts_send_indicate(gatts_if, param->write.conn_id, gatts_profile_tab[GATTS_PROFILE_A_APP_ID].char_handle, @@ -690,7 +711,7 @@ static void gatts_profile_a_event_handler(esp_gatts_cb_event_t event, esp_gatt_i break; } case ESP_GATTS_EXEC_WRITE_EVT: - ESP_LOGI(COEX_TAG,"ESP_GATTS_EXEC_WRITE_EVT"); + ESP_LOGI(COEX_TAG, "ESP_GATTS_EXEC_WRITE_EVT"); esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, NULL); example_exec_write_event_env(&a_prepare_write_env, param); break; @@ -710,18 +731,18 @@ static void gatts_profile_a_event_handler(esp_gatts_cb_event_t event, esp_gatt_i a_property, &gatts_demo_char1_val, NULL); if (add_char_ret) { - ESP_LOGE(COEX_TAG, "add char failed, error code =%x",add_char_ret); + ESP_LOGE(COEX_TAG, "add char failed, error code =%x", add_char_ret); } break; case ESP_GATTS_ADD_CHAR_EVT: { ESP_LOGI(COEX_TAG, "ADD_CHAR_EVT, status %d, attr_handle %d, service_handle %d", - param->add_char.status, param->add_char.attr_handle, param->add_char.service_handle); + param->add_char.status, param->add_char.attr_handle, param->add_char.service_handle); gatts_profile_tab[GATTS_PROFILE_A_APP_ID].char_handle = param->add_char.attr_handle; gatts_profile_tab[GATTS_PROFILE_A_APP_ID].descr_uuid.len = ESP_UUID_LEN_16; gatts_profile_tab[GATTS_PROFILE_A_APP_ID].descr_uuid.uuid.uuid16 = ESP_GATT_UUID_CHAR_CLIENT_CONFIG; esp_err_t add_descr_ret = esp_ble_gatts_add_char_descr(gatts_profile_tab[GATTS_PROFILE_A_APP_ID].service_handle, &gatts_profile_tab[GATTS_PROFILE_A_APP_ID].descr_uuid, - ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, NULL, NULL); + ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, NULL, NULL); if (add_descr_ret) { ESP_LOGE(COEX_TAG, "add char descr failed, error code =%x", add_descr_ret); } @@ -737,17 +758,23 @@ static void gatts_profile_a_event_handler(esp_gatts_cb_event_t event, esp_gatt_i param->start.status, param->start.service_handle); break; case ESP_GATTS_CONNECT_EVT: { - + if (memcmp(peer_gatts_addr, param->connect.remote_bda, sizeof(esp_bd_addr_t))) { + // If a BLE physical connection is established, both ESP_GATTS_CONNECT_EVT and ESP_GATTC_CONNECT_EVT events will occur. + // Update the connection ID in the gatts_profile_tab only if the peer device is a GATT client. + gatts_profile_tab[GATTS_PROFILE_A_APP_ID].conn_id = param->connect.conn_id; + } ESP_LOGI(COEX_TAG, "ESP_GATTS_CONNECT_EVT, conn_id %d, remote %02x:%02x:%02x:%02x:%02x:%02x", param->connect.conn_id, param->connect.remote_bda[0], param->connect.remote_bda[1], param->connect.remote_bda[2], param->connect.remote_bda[3], param->connect.remote_bda[4], param->connect.remote_bda[5]); - gatts_profile_tab[GATTS_PROFILE_A_APP_ID].conn_id = param->connect.conn_id; break; } case ESP_GATTS_DISCONNECT_EVT: ESP_LOGI(COEX_TAG, "ESP_GATTS_DISCONNECT_EVT, disconnect reason 0x%x", param->disconnect.reason); - esp_ble_gap_start_advertising(&adv_params); + if (memcmp(peer_gatts_addr, param->disconnect.remote_bda, sizeof(esp_bd_addr_t))) { + // If the peer device is a GATT client, restart advertising + esp_ble_gap_start_advertising(&adv_params); + } break; case ESP_GATTS_CONF_EVT: ESP_LOGI(COEX_TAG, "ESP_GATTS_CONF_EVT, status %d attr_handle %d", param->conf.status, param->conf.handle); @@ -761,7 +788,8 @@ static void gatts_profile_a_event_handler(esp_gatts_cb_event_t event, esp_gatt_i } } -static void gatts_profile_b_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) { +static void gatts_profile_b_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) +{ switch (event) { case ESP_GATTS_REG_EVT: ESP_LOGI(COEX_TAG, "REGISTER_APP_EVT, status %d, app_id %d", param->reg.status, param->reg.app_id); @@ -792,24 +820,24 @@ static void gatts_profile_b_event_handler(esp_gatts_cb_event_t event, esp_gatt_i ESP_LOGI(COEX_TAG, "GATT_WRITE_EVT, value len %d, value :", param->write.len); esp_log_buffer_hex(COEX_TAG, param->write.value, param->write.len); if (gatts_profile_tab[GATTS_PROFILE_B_APP_ID].descr_handle == param->write.handle && param->write.len == 2) { - uint16_t descr_value= param->write.value[1]<<8 | param->write.value[0]; + uint16_t descr_value = param->write.value[1] << 8 | param->write.value[0]; if (descr_value == NOTIFY_ENABLE) { if (b_property & ESP_GATT_CHAR_PROP_BIT_NOTIFY) { ESP_LOGI(COEX_TAG, "notify enable"); uint8_t notify_data[15]; for (int i = 0; i < sizeof(notify_data); ++ i) { - notify_data[i] = i%0xff; + notify_data[i] = i % 0xff; } //the size of notify_data[] need less than MTU size esp_ble_gatts_send_indicate(gatts_if, param->write.conn_id, gatts_profile_tab[GATTS_PROFILE_B_APP_ID].char_handle, - sizeof(notify_data), notify_data, false); + sizeof(notify_data), notify_data, false); } } else if (descr_value == INDICATE_ENABLE) { if (b_property & ESP_GATT_CHAR_PROP_BIT_INDICATE) { ESP_LOGI(COEX_TAG, "indicate enable"); uint8_t indicate_data[15]; for (int i = 0; i < sizeof(indicate_data); ++ i) { - indicate_data[i] = i%0xff; + indicate_data[i] = i % 0xff; } //the size of indicate_data[] need less than MTU size esp_ble_gatts_send_indicate(gatts_if, param->write.conn_id, gatts_profile_tab[GATTS_PROFILE_B_APP_ID].char_handle, @@ -827,7 +855,7 @@ static void gatts_profile_b_event_handler(esp_gatts_cb_event_t event, esp_gatt_i break; } case ESP_GATTS_EXEC_WRITE_EVT: - ESP_LOGI(COEX_TAG,"ESP_GATTS_EXEC_WRITE_EVT"); + ESP_LOGI(COEX_TAG, "ESP_GATTS_EXEC_WRITE_EVT"); esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, NULL); example_exec_write_event_env(&b_prepare_write_env, param); break; @@ -844,12 +872,12 @@ static void gatts_profile_b_event_handler(esp_gatts_cb_event_t event, esp_gatt_i esp_ble_gatts_start_service(gatts_profile_tab[GATTS_PROFILE_B_APP_ID].service_handle); b_property = ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_WRITE | ESP_GATT_CHAR_PROP_BIT_NOTIFY; - esp_err_t add_char_ret =esp_ble_gatts_add_char( gatts_profile_tab[GATTS_PROFILE_B_APP_ID].service_handle, &gatts_profile_tab[GATTS_PROFILE_B_APP_ID].char_uuid, + esp_err_t add_char_ret = esp_ble_gatts_add_char(gatts_profile_tab[GATTS_PROFILE_B_APP_ID].service_handle, &gatts_profile_tab[GATTS_PROFILE_B_APP_ID].char_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, b_property, NULL, NULL); if (add_char_ret) { - ESP_LOGE(COEX_TAG, "add char failed, error code =%x",add_char_ret); + ESP_LOGE(COEX_TAG, "add char failed, error code =%x", add_char_ret); } break; case ESP_GATTS_ADD_INCL_SRVC_EVT: @@ -883,14 +911,18 @@ static void gatts_profile_b_event_handler(esp_gatts_cb_event_t event, esp_gatt_i param->connect.conn_id, param->connect.remote_bda[0], param->connect.remote_bda[1], param->connect.remote_bda[2], param->connect.remote_bda[3], param->connect.remote_bda[4], param->connect.remote_bda[5]); - gatts_profile_tab[GATTS_PROFILE_B_APP_ID].conn_id = param->connect.conn_id; + if (memcmp(peer_gatts_addr, param->connect.remote_bda, sizeof(esp_bd_addr_t))) { + // If a BLE physical connection is established, both ESP_GATTS_CONNECT_EVT and ESP_GATTC_CONNECT_EVT events will occur. + // Update the connection ID in the gatts_profile_tab only if the peer device is a GATT client. + gatts_profile_tab[GATTS_PROFILE_B_APP_ID].conn_id = param->connect.conn_id; + } break; case ESP_GATTS_CONF_EVT: ESP_LOGI(COEX_TAG, "ESP_GATTS_CONF_EVT status %d attr_handle %d", param->conf.status, param->conf.handle); if (param->conf.status != ESP_GATT_OK) { esp_log_buffer_hex(COEX_TAG, param->conf.value, param->conf.len); } - break; + break; case ESP_GATTS_DISCONNECT_EVT: case ESP_GATTS_OPEN_EVT: default: @@ -906,8 +938,8 @@ static void esp_gattc_cb(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp gattc_profile_tab[param->reg.app_id].gattc_if = gattc_if; } else { ESP_LOGI(COEX_TAG, "reg app failed, app_id %04x, status %d", - param->reg.app_id, - param->reg.status); + param->reg.app_id, + param->reg.status); return; } } @@ -935,8 +967,8 @@ static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_ gatts_profile_tab[param->reg.app_id].gatts_if = gatts_if; } else { ESP_LOGI(COEX_TAG, "Reg app failed, app_id %04x, status %d", - param->reg.app_id, - param->reg.status); + param->reg.app_id, + param->reg.status); return; } } @@ -966,7 +998,7 @@ void app_main(void) ESP_ERROR_CHECK(nvs_flash_erase()); ret = nvs_flash_init(); } - ESP_ERROR_CHECK( ret ); + ESP_ERROR_CHECK(ret); ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT)); @@ -1023,7 +1055,7 @@ void app_main(void) // gattc regisrter ret = esp_ble_gattc_register_callback(esp_gattc_cb); - if(ret) { + if (ret) { ESP_LOGE(COEX_TAG, "%s gattc register failed, error code = %x", __func__, ret); return; } diff --git a/examples/bluetooth/esp_ble_mesh/common_components/light_driver/CMakeLists.txt b/examples/bluetooth/esp_ble_mesh/common_components/light_driver/CMakeLists.txt index fe06e61668c2..8e5cf4e70e87 100644 --- a/examples/bluetooth/esp_ble_mesh/common_components/light_driver/CMakeLists.txt +++ b/examples/bluetooth/esp_ble_mesh/common_components/light_driver/CMakeLists.txt @@ -7,6 +7,6 @@ set(COMPONENT_SRCS set(COMPONENT_ADD_INCLUDEDIRS ". include") # requirements can't depend on config -set(COMPONENT_REQUIRES example_nvs driver esp_driver_gpio) +set(COMPONENT_REQUIRES example_nvs driver esp_driver_gpio esp_driver_ledc) register_component() diff --git a/examples/build_system/.build-test-rules.yml b/examples/build_system/.build-test-rules.yml index 89bed00ded14..509db630017b 100644 --- a/examples/build_system/.build-test-rules.yml +++ b/examples/build_system/.build-test-rules.yml @@ -2,12 +2,10 @@ examples/build_system/cmake/import_lib: disable_test: - - if: IDF_TARGET in ["esp32c2", "esp32c3", "esp32s2", "esp32s3", "esp32c6", "esp32h2"] - temporary: true - reason: lack of runners + - if: IDF_TARGET not in ["esp32", "esp32c3"] + reason: Testing on two diff architectures is sufficient examples/build_system/cmake/plugins: disable_test: - if: IDF_TARGET not in ["esp32", "esp32c3"] - temporary: true - reason: lack of runners + reason: Testing on two diff architectures is sufficient diff --git a/examples/build_system/cmake/import_lib/pytest_import_lib.py b/examples/build_system/cmake/import_lib/pytest_import_lib.py index 49a450a1db0f..2bb484522432 100644 --- a/examples/build_system/cmake/import_lib/pytest_import_lib.py +++ b/examples/build_system/cmake/import_lib/pytest_import_lib.py @@ -5,7 +5,8 @@ from pytest_embedded_qemu.dut import QemuDut -@pytest.mark.esp32 # we only support qemu on esp32 for now +@pytest.mark.esp32 +@pytest.mark.esp32c3 @pytest.mark.host_test @pytest.mark.qemu def test_pytest_host(dut: QemuDut) -> None: diff --git a/examples/common_components/protocol_examples_common/CMakeLists.txt b/examples/common_components/protocol_examples_common/CMakeLists.txt index a8f9b81c0579..e2470c7efadf 100644 --- a/examples/common_components/protocol_examples_common/CMakeLists.txt +++ b/examples/common_components/protocol_examples_common/CMakeLists.txt @@ -29,7 +29,7 @@ endif() idf_component_register(SRCS "${srcs}" INCLUDE_DIRS "include" - PRIV_REQUIRES esp_netif driver esp_wifi vfs) + PRIV_REQUIRES esp_netif driver esp_wifi vfs console esp_eth) if(CONFIG_EXAMPLE_PROVIDE_WIFI_CONSOLE_CMD) idf_component_optional_requires(PRIVATE console) diff --git a/examples/get-started/blink/pytest_blink.py b/examples/get-started/blink/pytest_blink.py index b7ea802c3b3e..3c3916ed6c99 100644 --- a/examples/get-started/blink/pytest_blink.py +++ b/examples/get-started/blink/pytest_blink.py @@ -8,6 +8,7 @@ from pytest_embedded_idf.dut import IdfDut +@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='esp32p4 support TBD') # TODO: IDF-8988 @pytest.mark.supported_targets @pytest.mark.generic def test_blink(dut: IdfDut) -> None: diff --git a/examples/ieee802154/.build-test-rules.yml b/examples/ieee802154/.build-test-rules.yml new file mode 100644 index 000000000000..0af66989a00d --- /dev/null +++ b/examples/ieee802154/.build-test-rules.yml @@ -0,0 +1,19 @@ +# Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps + +.ieee802154_dependencies: &ieee802154_dependencies + depends_components: + - esp_coex + - esp_phy + - ieee802154 + depends_filepatterns: + - examples/ieee802154/**/* + - examples/system/console/advanced/components/cmd_system/**/* + +examples/ieee802154/ieee802154_cli: + enable: + - if: SOC_IEEE802154_SUPPORTED == 1 + disable_test: + - if: IDF_TARGET == "esp32h2" + temporary: true + reason: only test on esp32c6 + <<: *ieee802154_dependencies diff --git a/examples/ieee802154/README.md b/examples/ieee802154/README.md new file mode 100644 index 000000000000..dd9649b49d10 --- /dev/null +++ b/examples/ieee802154/README.md @@ -0,0 +1,9 @@ +# IEEE802.15.4 Examples + +See the [README.md](../README.md) file in the upper level [examples](../) directory for more information about examples. + +## Overview + +In this folder, it contains following IEEE802.15.4 examples: + +* [ieee802154_cli](ieee802154_cli) is an IEEE802.15.4 Command Line example, the commands it supports are listed in [README.md](./ieee802154_cli//README.md). It runs on an 802.15.4 SoC like ESP32-H2. diff --git a/components/ieee802154/test_apps/test_ieee802154/CMakeLists.txt b/examples/ieee802154/ieee802154_cli/CMakeLists.txt similarity index 91% rename from components/ieee802154/test_apps/test_ieee802154/CMakeLists.txt rename to examples/ieee802154/ieee802154_cli/CMakeLists.txt index b7ca706cb4c9..4aba22f75cf0 100644 --- a/components/ieee802154/test_apps/test_ieee802154/CMakeLists.txt +++ b/examples/ieee802154/ieee802154_cli/CMakeLists.txt @@ -6,4 +6,4 @@ include($ENV{IDF_PATH}/tools/cmake/project.cmake) # "Trim" the build. Include the minimal set of components, main, and anything it depends on. set(COMPONENTS main) -project(test_ieee802154) +project(ieee802154_cli) diff --git a/examples/ieee802154/ieee802154_cli/README.md b/examples/ieee802154/ieee802154_cli/README.md new file mode 100644 index 000000000000..584a8d4ca808 --- /dev/null +++ b/examples/ieee802154/ieee802154_cli/README.md @@ -0,0 +1,476 @@ +| Supported Targets | ESP32-C6 | ESP32-H2 | +| ----------------- | -------- | -------- | + +# IEEE802.15.4 Command Line Example + +This example demonstrates an IEEE802.15.4 Command Line. The IEEE802.15.4 CLI exposes configuration and management APIs via a command line interface. + +## How to use example + +### Hardware Required + +To run this example, a board with IEEE 802.15.4 module (for example ESP32-H2) is required. + +### Configure the project + +``` +idf.py menuconfig +``` + +The example can run with the default configuration. IEEE802.15.4 Command Line is enabled with UART as the default interface. Additionally, USB JTAG is also supported and can be activated through the menuconfig: + +``` +Component config → ESP System Settings → Channel for console output → USB Serial/JTAG Controller +``` + +### Build, Flash, and Run + +Build the project and flash it to the board, then run monitor tool to view serial output: + +``` +idf.py -p PORT build flash monitor +``` + +Now you'll get an IEEE802.15.4 command line shell. + +## IEEE802.15.4 Command List + +- [cca](#cca) +- [channel](#channel) +- [coordinator](#coordinator) +- [ed](#ed) +- [esp154](#esp154) +- [extaddr](#extaddr) +- [free](#free) +- [heap](#heap) +- [panid](#panid) +- [pending](#pending) +- [promisc](#promisc) +- [reg](#reg) +- [restart](#restart) +- [rx](#rx) +- [shortaddr](#shortaddr) +- [tx](#tx) +- [txpower](#txpower) +- [version](#version) +- [help](#help) + +## IEEE802.15.4 Command Details + +Most of the commands are available in both full and abbreviated form. +For example, to enable the receive mode, both `rx -r 1` and `rx --receive=1` are valid +```bash +> rx -r 1 +I (4227508) i154cmd: RX Start +> rx --receive=1 +I (4249898) i154cmd: RX Start +``` +Only abbreviated formats are described below. + + +### cca +#### cca -g +Get the cca cfg. + +```bash +> cca -g +I (2676818) i154cmd: threshold:-60 dB, mode: 1 +``` + +#### cca -m \ +Set the cca mode. +* 0: carrier +* 1: ED +* 2: carrier or ED +* 3: carrier and ED +```bash +> cca -m 1 +I (5047618) i154cmd: set cca mode as: 1 +``` + +#### cca -v \ +Set the cca threshold. +```bash +> cca -v 60 +I (4731648) i154cmd: set cca threshold as: 60 +``` + +### channel +#### channel -g +Get the channel number. +```bash +> channel -g +I (67238) i154cmd: current channel: 11 +``` + +#### channel -s \ +Set the channel number. +```bash +> channel -s 21 +I (220268) i154cmd: set channel: 21 +``` + +### coordinator +#### coordinator -d +Enable the coordinator. +```bash +> coordinator -d +I (438228) i154cmd: hardware coordinator is disabled +``` + +#### coordinator -e +Disable the coordinator. +```bash +> coordinator -e +I (453288) i154cmd: hardware coordinator is enabled +``` + +#### coordinator -g +Get the coordinator. +```bash +> coordinator -g +I (472398) i154cmd: hardware coordinator was enabled +``` + +### ed +#### ed -d \ +Configure the duration of energy detection. +```bash +> ed -d 2 +I (668548) i154cmd: ed start +I (668548) i154cmd: ed_scan_rss_value: -98 dB +I (472398) i154cmd: hardware coordinator was enabled +``` + +### esp154 +#### esp154 -e +Enable initialize the IEEE 802.15.4 subsystem. +```bash +> esp154 -e +I (87127) i154cmd: initialize the IEEE 802.15.4 subsystem +``` + +#### esp154 -d +Disable initialize the IEEE 802.15.4 subsystem. +```bash +> esp154 -d +I (97107) i154cmd: deinitialize the IEEE 802.15.4 subsystem +``` + +### extaddr +#### extaddr \ +Set the device extended address. +```bash +> extaddr 0xaa 0xbb 0xcc 0xdd 0x00 0x11 0x22 0x33 +I (704937) i154cmd: set extaddr: 33221100ddccbbaa +``` + +#### extaddr -g +Get the device extended address. +```bash +> extaddr -g +I (615587) i154cmd: get extaddr: 0807060504030201 +``` + +### free +Get the current size of free heap memory. +```bash +> free +235024 +``` + +### heap +Get minimum size of free heap memory that was available during program execution. +```bash +> heap +min heap size: 231076 +``` + +### panid +#### panid \ +Set the device Pan ID. +```bash +> panid 0x1234 +I (1112117) i154cmd: set panid: 0x1234 +``` + +#### panid -g +Get the device Pan ID. +```bash +> panid -g +I (1128457) i154cmd: current panid: 0x1234 +``` + +### pending +#### pending \ +Add the address to pending table (2 bytes for short address, 8 bytes for extended address). +```bash +> pending 0x34 0x12 +I (1806327) i154cmd: add pending shortaddr: 0x1234 +``` + +#### pending -m \ +Set the autopending mode. +* 0: disable +* 1: enable +* 2: enhanced +```bash +> pending -m 1 +I (1828817) i154cmd: set auto pending mode as: 1 +``` + +#### pending -g +Get the autopending mode. +```bash +> pending -g +I (2007797) i154cmd: get auto pending mode as: 1 +``` + +#### pending -r +Reset the pending address table. +```bash +> pending -r +I (2113377) i154cmd: clear the pending address table +``` + +#### pending -d +Delete the address from pending table (2 bytes for short address, 8 bytes for extended address). +```bash +> pending -d 0x34 -d 0x12 +I (2322787) i154cmd: delete pending shortaddr: 0x1234 +``` + +### promisc +#### promisc [-edg] +* e: Enable the promiscuous mode. +* d: Disable the promiscuous mode. +* g: Get the promiscuous mode. +```bash +> promisc -e +I (2599357) i154cmd: promiscuous mode is enabled +> promisc -d +I (2600977) i154cmd: promiscuous mode is disabled +> promisc -g +I (2602927) i154cmd: hardware promiscuous mode was disabled +``` + +### reg +#### reg -w \ -v \ +Write the register \ with \. +```bash +> reg -w 0x0184 -v 0x00 +I (103917) i154cmd: write reg 0x184: 0x1234 +``` + +#### reg -r \ +Read the register \. +```bash +> reg -r 0x0184 +I (220967) i154cmd: reg 0x184 value: 0x1234 +``` + +### restart +Restart the program. + +### rx +#### rx -r \ +Configure the radio receive mode. +* 0: disable +* 1: enable +```bash +> rx -r 1 +I (121977) i154cmd: RX Start +> rx -r 0 +I (127267) i154cmd: radio exit receive mode +``` + +### shortaddr +#### shortaddr \ +set the device short address. +```bash +> shortaddr 0x1234 +I (543167) i154cmd: set shortaddr: 0x1234 +``` + +#### shortaddr -g +```bash +> shortaddr -g +I (568387) i154cmd: current shortaddr: 0x1234 +``` + +### tx +#### tx \ +Transmit IEEE 802154 MAC frame. +* -C: Set cca trigging tx mode true. +```bash +> tx 0x00 0x11 0x22 0x33 0x44 0x55 0x66 0x77 +I (6399947) i154cmd: tx sfd done, Radio state: 4 +I (6399957) i154cmd: Tx Done 8 bytes +I (6399957) i154cmd: 00 11 22 33 44 55 66 77 +> tx 0x00 0x11 0x22 0x33 0x44 0x55 0x66 0x77 -C +I (6580547) i154cmd: tx sfd done, Radio state: 4 +I (6580547) i154cmd: Tx Done 8 bytes +I (6580547) i154cmd: 00 11 22 33 44 55 66 77 +``` + +#### tx -l \ +Transmit IEEE 802154 MAC frame wich has a length=\. +* -C: Set cca trigging tx mode true. +```bash +> tx -l 10 +I (6721867) i154cmd: tx sfd done, Radio state: 4 +I (6721867) i154cmd: Tx Done 10 bytes +I (6721867) i154cmd: 00 01 02 03 04 05 06 07 +I (6721867) i154cmd: 08 09 00 00 00 00 00 00 +> tx -l 10 -C +I (6726067) i154cmd: tx sfd done, Radio state: 4 +I (6726067) i154cmd: Tx Done 10 bytes +I (6726067) i154cmd: 00 01 02 03 04 05 06 07 +I (6726067) i154cmd: 08 09 00 00 00 00 00 00 +``` + +### txpower +#### txpower -g +Get the txpower. +```bash +> txpower -g +I (7100077) i154cmd: current txpower: 20 +``` + +#### txpower -s \ +Set the txpower. +```bash +> txpower -s 40 +I (7116217) i154cmd: set txpower: 40 +``` + +### version +Get version of chip and SDK. +```bash +> version +IDF Version:v5.3-dev-699-gb94f6ef680-dirty +Chip info: + model:ESP32-H2 + cores:1 + feature:/BLE/External-Flash:2 MB + revision number:1 +``` + +### help +Get the summary of all registered commands. + +```bash +> help +cca [-g] [-v ] [-m ] + cca config + -v, --value= cca threshold setting + -m, --mode= cca mode, 0: carrier; 1: ED; 2: carrier or ED; 3: carrier and ED + -g, --get get the cca cfg + +channel [-g] [-s ] + get/set the channel number + -g, --get get channel number + -s, --set= set channel number + +coordinator [-edg] + enable/disable/get the coordinator + -e, --enable enable the coordinator + -d, --disable disable the coordinator + -g, --get get the coordinator + +ed [-d ] + configure the duration + -d, --duration= configure the duration of energy detection + +esp154 [-ed] + enable/disable initialize the IEEE 802.15.4 subsystem + -e, --enable initialize the IEEE 802.15.4 subsystem + -d, --disable deinitialize the IEEE 802.15.4 subsystem + +extaddr [-g] []... + set/get the device extended address + -g, --get get the device extended address + set the device extended address + +free + Get the current size of free heap memory + +heap + Get minimum size of free heap memory that was available during program + execution + +help [] + Print the summary of all registered commands if no arguments are given, + otherwise print summary of given command. + Name of command + +log_level + Set log level for all tags or a specific tag. + Log tag to set the level for, or * to set for all tags + Log level to set. Abbreviated words are accepted. + +panid [-g] [] + get/set the device Pan ID + set the device Pan ID + -g, --get get the device Pan ID + +pending [-gr] [-m ] []... [-d ]... + configure the pending address table + -m, --mode= set the autopending mode (0: disable; 1: enable; 2: enhanced) + -g, --get get the autopending mode (0: disable; 1: enable; 2: enhanced) + -r, --reset reset the pending address table + add the address to pending table (2 bytes for short address, 8 bytes for extended address) + -d, --delete= delete the address from pending table (2 bytes for short address, 8 bytes for extended address) + +promisc [-edg] + enable/disable/get the promiscuous mode + -e, --enable enable the promiscuous mode + -d, --disable disable the promiscuous mode + -g, --get get the promiscuous mode + +reg [-r
] [-w
] [-v ] + read/write the register + -r, --read=
read the register value + -w, --write=
register address to be written + -v, --value= register value to be written + +restart + Software reset of the chip + +rx [-r ] + enable/disable the receive mode + -r, --receive= configure the radio receive mode, 0: disable; 1: enable + +shortaddr [-g] [] + get/set the device short address + set the device short address + -g, --get get the device short address + +tx [-C] [-l ] []... [-o ] + transmit IEEE 802154 MAC frame + -l, --length= frame length + -C, --cca_enable set cca trigging tx mode true + transmit raw frame + -o, --offset= tx buffer offset + +txpower [-g] [-s ] + get/set the txpower + -g, --get get txpower + -s, --set= set txpower,value range -80dBm~-10dBm + +version + Get version of chip and SDK +``` + +#### help \ +Get the summary of given command. + +```bash +> help tx +tx [-C] [-l ] []... [-o ] + transmit IEEE 802154 MAC frame + -l, --length= frame length + -C, --cca_enable set cca trigging tx mode true + transmit raw frame + -o, --offset= tx buffer offset +``` diff --git a/examples/ieee802154/ieee802154_cli/components/cmd_ieee802154/CMakeLists.txt b/examples/ieee802154/ieee802154_cli/components/cmd_ieee802154/CMakeLists.txt new file mode 100644 index 000000000000..742f87bc43f0 --- /dev/null +++ b/examples/ieee802154/ieee802154_cli/components/cmd_ieee802154/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRCS "ieee802154_cmd.c" + INCLUDE_DIRS "." + PRIV_REQUIRES ieee802154 console esp_phy) diff --git a/components/ieee802154/test_apps/test_ieee802154/main/src/ieee802154_cmd.c b/examples/ieee802154/ieee802154_cli/components/cmd_ieee802154/ieee802154_cmd.c similarity index 92% rename from components/ieee802154/test_apps/test_ieee802154/main/src/ieee802154_cmd.c rename to examples/ieee802154/ieee802154_cli/components/cmd_ieee802154/ieee802154_cmd.c index 2a56811f4776..7c4e93e43e33 100644 --- a/components/ieee802154/test_apps/test_ieee802154/main/src/ieee802154_cmd.c +++ b/examples/ieee802154/ieee802154_cli/components/cmd_ieee802154/ieee802154_cmd.c @@ -18,7 +18,7 @@ #include "soc/ieee802154_reg.h" static uint8_t s_tx_frame[131] = { 0 }; -static const char* TAG = "i154test"; +static const char* TAG = "i154cmd"; static void register_rx(void); static void register_tx(void); @@ -34,8 +34,6 @@ static void register_pending(void); static void register_cca(void); static void register_esp154(void); static void register_reg(void); -static void register_free(void); -static void register_restart(void); void register_ieee802154_cmd(void) { @@ -53,8 +51,6 @@ void register_ieee802154_cmd(void) register_cca(); register_esp154(); register_reg(); - register_free(); - register_restart(); } static struct { @@ -78,8 +74,8 @@ static int process_energy(int argc, char **argv) ESP_LOGI(TAG, "ed start"); esp_ieee802154_energy_detect(duration); } else { - ESP_LOGE(TAG, "no valid arguments"); - return 1; + ESP_LOGE(TAG, "no valid arguments"); + return 1; } } else { ESP_LOGE(TAG, "no valid arguments"); @@ -364,7 +360,7 @@ static int process_extaddr(int argc, char **argv) } else if (extaddr_args.get_extaddr->count) { esp_ieee802154_get_extended_address(extaddr); ESP_LOGI(TAG, "get extaddr: %02x%02x%02x%02x%02x%02x%02x%02x", extaddr[7], extaddr[6], extaddr[5], extaddr[4], - extaddr[3], extaddr[2], extaddr[1], extaddr[0]); + extaddr[3], extaddr[2], extaddr[1], extaddr[0]); } else { ESP_LOGE(TAG, "no valid arguments"); } @@ -640,38 +636,6 @@ static void register_esp154() ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); } -/* 'fheap' command check for memory leaks */ -static struct { - struct arg_end *end; -} free_args; - -static int process_free(int argc, char **argv) -{ - int nerrors = arg_parse(argc, argv, (void **) &free_args); - if (nerrors != 0) { - arg_print_errors(stderr, free_args.end, argv[0]); - return 1; - } - - esp_get_free_heap_size(); - ESP_LOGI(TAG, "heap size: %" PRIu32, esp_get_free_heap_size()); - return 0; -} - -static void register_free() -{ - free_args.end = arg_end(2); - - const esp_console_cmd_t cmd = { - .command = "fheap", - .help = "get the size of heap memory", - .hint = NULL, - .func = &process_free, - .argtable = &free_args - }; - ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); -} - /* 'reg' command reads/writes the registers */ static struct { struct arg_int *get_reg; @@ -766,7 +730,7 @@ static int process_tx(int argc, char **argv) if (tx_args.cca_enable->count) { cca = true; } - memcpy(s_tx_frame+offset, tx_frame, sizeof(tx_frame)); + memcpy(s_tx_frame + offset, tx_frame, sizeof(tx_frame)); esp_ieee802154_transmit(s_tx_frame, cca); return 0; } @@ -841,51 +805,30 @@ static void register_rx(void) ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); } -/* 'restart' command restarts the program */ -static int restart(int argc, char **argv) +static void esp_ieee802154_frame_print(const uint8_t *frame) { - ESP_EARLY_LOGI(TAG, "Restarting"); - esp_restart(); -} - -static void register_restart(void) -{ - const esp_console_cmd_t cmd = { - .command = "restart", - .help = "Restart the program", - .hint = NULL, - .func = &restart - }; - ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); + for (uint8_t idx = 1; idx < frame[0]; idx += 8) { + ESP_EARLY_LOGI(TAG, "%02x %02x %02x %02x %02x %02x %02x %02x", + frame[idx], frame[idx + 1], frame[idx + 2], frame[idx + 3], + frame[idx + 4], frame[idx + 5], frame[idx + 6], frame[idx + 7]); + } } void esp_ieee802154_transmit_done(const uint8_t *frame, const uint8_t *ack, esp_ieee802154_frame_info_t *ack_frame_info) { ESP_EARLY_LOGI(TAG, "Tx Done %d bytes", frame[0]); - for(uint8_t idx = 1; idx < frame[0]; idx+=8) { - ESP_EARLY_LOGI(TAG, "%02x %02x %02x %02x %02x %02x %02x %02x", - frame[idx], frame[idx+1], frame[idx+2], frame[idx+3], - frame[idx+4], frame[idx+5], frame[idx+6], frame[idx+7]); - } + esp_ieee802154_frame_print(frame); if (ack != NULL) { ESP_EARLY_LOGI(TAG, "Rx ack %d bytes", ack[0]); - for(uint8_t idx = 1; idx < ack[0]; idx+=8) { - ESP_EARLY_LOGI(TAG, "%02x %02x %02x %02x %02x %02x %02x %02x", - ack[idx], ack[idx+1], ack[idx+2], ack[idx+3], - ack[idx+4], ack[idx+5], ack[idx+6], ack[idx+7]); - } + esp_ieee802154_frame_print(ack); } } void esp_ieee802154_receive_done(uint8_t *frame, esp_ieee802154_frame_info_t *frame_info) { ESP_EARLY_LOGI(TAG, "Rx Done %d bytes", frame[0]); - for(uint8_t idx = 1; idx < frame[0]; idx+=8) { - ESP_EARLY_LOGI(TAG, "%02x %02x %02x %02x %02x %02x %02x %02x", - frame[idx], frame[idx+1], frame[idx+2], frame[idx+3], - frame[idx+4], frame[idx+5], frame[idx+6], frame[idx+7]); - } + esp_ieee802154_frame_print(frame); } void esp_ieee802154_energy_detect_done(int8_t power) diff --git a/components/ieee802154/test_apps/test_ieee802154/main/include/ieee802154_cmd.h b/examples/ieee802154/ieee802154_cli/components/cmd_ieee802154/ieee802154_cmd.h similarity index 100% rename from components/ieee802154/test_apps/test_ieee802154/main/include/ieee802154_cmd.h rename to examples/ieee802154/ieee802154_cli/components/cmd_ieee802154/ieee802154_cmd.h diff --git a/components/ieee802154/test_apps/test_ieee802154/main/CMakeLists.txt b/examples/ieee802154/ieee802154_cli/main/CMakeLists.txt similarity index 72% rename from components/ieee802154/test_apps/test_ieee802154/main/CMakeLists.txt rename to examples/ieee802154/ieee802154_cli/main/CMakeLists.txt index 625a6175c9e1..1407c219b1e4 100644 --- a/components/ieee802154/test_apps/test_ieee802154/main/CMakeLists.txt +++ b/examples/ieee802154/ieee802154_cli/main/CMakeLists.txt @@ -1,5 +1,4 @@ -set(srcs "test_app_main.c" - "src/ieee802154_cmd.c") +set(srcs "esp_ieee802154_cli.c") set(include "." "include") @@ -7,6 +6,5 @@ set(include "." # In order for the cases defined by `TEST_CASE` to be linked into the final elf, # the component can be registered as WHOLE_ARCHIVE idf_component_register(SRCS ${srcs} - INCLUDE_DIRS include - PRIV_REQUIRES ieee802154 console fatfs nvs_flash esp_phy + PRIV_REQUIRES ieee802154 console fatfs nvs_flash esp_phy cmd_ieee802154 cmd_system WHOLE_ARCHIVE) diff --git a/components/ieee802154/test_apps/test_ieee802154/main/test_app_main.c b/examples/ieee802154/ieee802154_cli/main/esp_ieee802154_cli.c similarity index 93% rename from components/ieee802154/test_apps/test_ieee802154/main/test_app_main.c rename to examples/ieee802154/ieee802154_cli/main/esp_ieee802154_cli.c index 5436e625bcc8..3ad3a546f60d 100644 --- a/components/ieee802154/test_apps/test_ieee802154/main/test_app_main.c +++ b/examples/ieee802154/ieee802154_cli/main/esp_ieee802154_cli.c @@ -5,6 +5,7 @@ */ #include #include +#include "ieee802154_cmd.h" #include "esp_system.h" #include "esp_log.h" #include "esp_console.h" @@ -14,7 +15,7 @@ #include "nvs_flash.h" #include "esp_ieee802154.h" #include "esp_phy_init.h" -#include "ieee802154_cmd.h" +#include "cmd_system.h" #define PROMPT_STR "ieee802154" @@ -22,7 +23,7 @@ static void initialize_nvs(void) { esp_err_t err = nvs_flash_init(); if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { - ESP_ERROR_CHECK( nvs_flash_erase() ); + ESP_ERROR_CHECK(nvs_flash_erase()); err = nvs_flash_init(); } ESP_ERROR_CHECK(err); @@ -44,6 +45,7 @@ void app_main(void) /* Register commands */ esp_console_register_help_command(); register_ieee802154_cmd(); + register_system_common(); esp_console_dev_uart_config_t hw_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT(); ESP_ERROR_CHECK(esp_console_new_repl_uart(&hw_config, &repl_config, &repl)); diff --git a/examples/ieee802154/ieee802154_cli/main/idf_component.yml b/examples/ieee802154/ieee802154_cli/main/idf_component.yml new file mode 100644 index 000000000000..77b231f2a7fa --- /dev/null +++ b/examples/ieee802154/ieee802154_cli/main/idf_component.yml @@ -0,0 +1,4 @@ +## IDF Component Manager Manifest File +dependencies: + cmd_system: + path: ${IDF_PATH}/examples/system/console/advanced/components/cmd_system diff --git a/components/ieee802154/test_apps/test_ieee802154/pytest_test_ieee802154.py b/examples/ieee802154/ieee802154_cli/pytest_test_ieee802154.py similarity index 97% rename from components/ieee802154/test_apps/test_ieee802154/pytest_test_ieee802154.py rename to examples/ieee802154/ieee802154_cli/pytest_test_ieee802154.py index 74b854834985..965780de69e0 100644 --- a/components/ieee802154/test_apps/test_ieee802154/pytest_test_ieee802154.py +++ b/examples/ieee802154/ieee802154_cli/pytest_test_ieee802154.py @@ -148,7 +148,7 @@ def test_based_txrx(dut: Tuple[IdfDut, IdfDut]) -> None: @pytest.mark.esp32c6 -@pytest.mark.generic +@pytest.mark.ieee802154 @pytest.mark.parametrize( 'config', ['release',], indirect=True @@ -162,7 +162,7 @@ def test_based_energy(dut: IdfDut) -> None: @pytest.mark.esp32c6 -@pytest.mark.generic +@pytest.mark.ieee802154 @pytest.mark.parametrize( 'config', ['release',], indirect=True @@ -177,7 +177,7 @@ def test_based_channel(dut: IdfDut) -> None: @pytest.mark.esp32c6 -@pytest.mark.generic +@pytest.mark.ieee802154 @pytest.mark.parametrize( 'config', ['release',], indirect=True @@ -192,7 +192,7 @@ def test_based_txpower(dut: IdfDut) -> None: @pytest.mark.esp32c6 -@pytest.mark.generic +@pytest.mark.ieee802154 @pytest.mark.parametrize( 'config', ['release',], indirect=True @@ -211,7 +211,7 @@ def test_based_promiscuous(dut: IdfDut) -> None: @pytest.mark.esp32c6 -@pytest.mark.generic +@pytest.mark.ieee802154 @pytest.mark.parametrize( 'config', ['release',], indirect=True @@ -226,7 +226,7 @@ def test_based_panid(dut: IdfDut) -> None: @pytest.mark.esp32c6 -@pytest.mark.generic +@pytest.mark.ieee802154 @pytest.mark.parametrize( 'config', ['release',], indirect=True @@ -241,7 +241,7 @@ def test_based_shortaddr(dut: IdfDut) -> None: @pytest.mark.esp32c6 -@pytest.mark.generic +@pytest.mark.ieee802154 @pytest.mark.parametrize( 'config', ['release',], indirect=True @@ -256,7 +256,7 @@ def test_based_extaddr(dut: IdfDut) -> None: @pytest.mark.esp32c6 -@pytest.mark.generic +@pytest.mark.ieee802154 @pytest.mark.parametrize( 'config', ['release',], indirect=True @@ -275,7 +275,7 @@ def test_based_coordinator(dut: IdfDut) -> None: @pytest.mark.esp32c6 -@pytest.mark.generic +@pytest.mark.ieee802154 @pytest.mark.parametrize( 'config', ['release',], indirect=True @@ -296,7 +296,7 @@ def test_based_pending(dut: IdfDut) -> None: @pytest.mark.esp32c6 -@pytest.mark.generic +@pytest.mark.ieee802154 @pytest.mark.parametrize( 'config', ['release',], indirect=True @@ -580,7 +580,7 @@ def test_based_transmit_failed(dut: IdfDut) -> None: @pytest.mark.esp32c6 -@pytest.mark.generic +@pytest.mark.ieee802154 @pytest.mark.parametrize( 'config', ['release',], indirect=True @@ -588,15 +588,15 @@ def test_based_transmit_failed(dut: IdfDut) -> None: def test_based_initialize(dut: IdfDut) -> None: transmit = dut transmit.expect('ieee802154>', timeout=10) - transmit.write('fheap') - fst_data = transmit.expect(r'heap size: [0-9]+', timeout=10)[0].decode() - fst_size = re.findall(r'heap size: ([0-9]+)', fst_data) + transmit.write('heap') + fst_data = transmit.expect(r'min heap size: [0-9]+', timeout=10)[0].decode() + fst_size = re.findall(r'min heap size: ([0-9]+)', fst_data) transmit.write('esp154 -e') transmit.expect('initialize the IEEE 802.15.4 subsystem', timeout=10) transmit.write('esp154 -d') transmit.expect('deinitialize the IEEE 802.15.4 subsystem', timeout=10) - transmit.write('fheap') - scd_data = transmit.expect(r'heap size: [0-9]+', timeout=10)[0].decode() - scd_size = re.findall(r'heap size: ([0-9]+)', scd_data) + transmit.write('heap') + scd_data = transmit.expect(r'min heap size: [0-9]+', timeout=10)[0].decode() + scd_size = re.findall(r'min heap size: ([0-9]+)', scd_data) print('first heap size: ', int(fst_size[0])) print('second heap size: ', int(scd_size[0])) diff --git a/components/ieee802154/test_apps/test_ieee802154/sdkconfig.ci.release b/examples/ieee802154/ieee802154_cli/sdkconfig.ci.release similarity index 100% rename from components/ieee802154/test_apps/test_ieee802154/sdkconfig.ci.release rename to examples/ieee802154/ieee802154_cli/sdkconfig.ci.release diff --git a/components/ulp/test_apps/lp_core/sdkconfig.ci.defaults b/examples/ieee802154/ieee802154_cli/sdkconfig.defaults similarity index 100% rename from components/ulp/test_apps/lp_core/sdkconfig.ci.defaults rename to examples/ieee802154/ieee802154_cli/sdkconfig.defaults diff --git a/examples/openthread/ot_ci_function.py b/examples/openthread/ot_ci_function.py index b29b32464f5d..3561f4ad1d9d 100644 --- a/examples/openthread/ot_ci_function.py +++ b/examples/openthread/ot_ci_function.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2024 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 diff --git a/examples/openthread/pytest_otbr.py b/examples/openthread/pytest_otbr.py index 73ba43eb4201..840fdd2e4317 100644 --- a/examples/openthread/pytest_otbr.py +++ b/examples/openthread/pytest_otbr.py @@ -1,10 +1,12 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 # !/usr/bin/env python3 +import copy import os.path import re +import secrets import subprocess import threading import time @@ -94,9 +96,9 @@ def test_thread_connect(dut:Tuple[IdfDut, IdfDut, IdfDut]) -> None: ocf.init_thread(br) for cli in cli_list: ocf.init_thread(cli) - br_ot_para = default_br_ot_para + br_ot_para = copy.copy(default_br_ot_para) ocf.joinThreadNetwork(br, br_ot_para) - cli_ot_para = default_cli_ot_para + cli_ot_para = copy.copy(default_cli_ot_para) cli_ot_para.dataset = ocf.getDataset(br) try: order = 0 @@ -127,12 +129,14 @@ def test_thread_connect(dut:Tuple[IdfDut, IdfDut, IdfDut]) -> None: def formBasicWiFiThreadNetwork(br:IdfDut, cli:IdfDut) -> None: ocf.init_thread(br) ocf.init_thread(cli) - ocf.joinWiFiNetwork(br, default_br_wifi_para) - ocf.joinThreadNetwork(br, default_br_ot_para) - ot_para = default_cli_ot_para - ot_para.dataset = ocf.getDataset(br) - ot_para.exaddr = '7766554433221101' - ocf.joinThreadNetwork(cli, ot_para) + otbr_wifi_para = copy.copy(default_br_wifi_para) + ocf.joinWiFiNetwork(br, otbr_wifi_para) + otbr_thread_para = copy.copy(default_br_ot_para) + ocf.joinThreadNetwork(br, otbr_thread_para) + otcli_thread_para = copy.copy(default_cli_ot_para) + otcli_thread_para.dataset = ocf.getDataset(br) + otcli_thread_para.exaddr = '7766554433221101' + ocf.joinThreadNetwork(cli, otcli_thread_para) ocf.wait(cli,10) @@ -670,3 +674,60 @@ def test_NAT64_DNS(Init_interface:bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> N ocf.execute_command(br, 'factoryreset') ocf.execute_command(cli, 'factoryreset') time.sleep(3) + + +# Case 13: Meshcop discovery of Border Router +@pytest.mark.supported_targets +@pytest.mark.esp32c6 +@pytest.mark.openthread_br +@pytest.mark.flaky(reruns=0, reruns_delay=1) +@pytest.mark.parametrize( + 'config, count, app_path, target', [ + ('rcp|br', 2, + f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}' + f'|{os.path.join(os.path.dirname(__file__), "ot_br")}', + 'esp32c6|esp32s3'), + ], + indirect=True, +) +def test_br_meshcop(Init_interface:bool, Init_avahi:bool, dut: Tuple[IdfDut, IdfDut]) -> None: + br = dut[1] + assert Init_interface + assert Init_avahi + dut[0].serial.stop_redirect_thread() + + result = None + output_bytes = b'' + try: + ocf.init_thread(br) + br_wifi_para = copy.copy(default_br_wifi_para) + ipv4_address = ocf.joinWiFiNetwork(br, br_wifi_para)[0] + br_thread_para = copy.copy(default_br_ot_para) + networkname = 'OTCI-' + str(secrets.token_hex(1)) + br_thread_para.setnetworkname(networkname) + ocf.joinThreadNetwork(br, br_thread_para) + ocf.wait(br, 10) + assert ocf.is_joined_wifi_network(br) + command = 'timeout 3 avahi-browse -r _meshcop._udp' + try: + result = subprocess.run(command, capture_output=True, check=True, shell=True) + if result: + output_bytes = result.stdout + except subprocess.CalledProcessError as e: + output_bytes = e.stdout + finally: + print('out_bytes: ', output_bytes) + output_str = str(output_bytes) + print('out_str: ', output_str) + + assert 'hostname = [esp-ot-br.local]' in str(output_str) + assert ('address = [' + ipv4_address + ']') in str(output_str) + assert 'dn=DefaultDomain' in str(output_str) + assert 'tv=1.3.0' in str(output_str) + assert ('nn=' + networkname) in str(output_str) + assert 'mn=BorderRouter' in str(output_str) + assert 'vn=OpenThread' in str(output_str) + assert 'rv=1' in str(output_str) + finally: + ocf.execute_command(br, 'factoryreset') + time.sleep(3) diff --git a/examples/peripherals/.build-test-rules.yml b/examples/peripherals/.build-test-rules.yml index b2ceb4fcb347..e8c91f93cf8e 100644 --- a/examples/peripherals/.build-test-rules.yml +++ b/examples/peripherals/.build-test-rules.yml @@ -169,10 +169,14 @@ examples/peripherals/lcd/tjpgd: examples/peripherals/ledc: disable: - if: SOC_LEDC_SUPPORTED != 1 + depends_components: + - esp_driver_ledc examples/peripherals/ledc/ledc_gamma_curve_fade: disable: - if: SOC_LEDC_SUPPORTED != 1 or SOC_LEDC_GAMMA_CURVE_FADE_SUPPORTED != 1 + depends_components: + - esp_driver_ledc examples/peripherals/mcpwm: disable: @@ -200,6 +204,16 @@ examples/peripherals/mcpwm/mcpwm_bldc_hall_control: temporary: true reason: lack of runners +examples/peripherals/mcpwm/mcpwm_capture_hc_sr04: + disable: + - if: SOC_MCPWM_SUPPORTED != 1 + depends_components: + - esp_driver_mcpwm + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: test not pass, should be re-enable # TODO: IDF-8963 + examples/peripherals/mcpwm/mcpwm_foc_svpwm_open_loop: disable: - if: SOC_MCPWM_SUPPORTED != 1 @@ -210,6 +224,26 @@ examples/peripherals/mcpwm/mcpwm_foc_svpwm_open_loop: temporary: true reason: lack of runners +examples/peripherals/mcpwm/mcpwm_servo_control: + disable: + - if: SOC_MCPWM_SUPPORTED != 1 + depends_components: + - esp_driver_mcpwm + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: test not pass, should be re-enable # TODO: IDF-8963 + +examples/peripherals/mcpwm/mcpwm_sync: + disable: + - if: SOC_MCPWM_SUPPORTED != 1 + depends_components: + - esp_driver_mcpwm + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: test not pass, should be re-enable # TODO: IDF-8963 + examples/peripherals/parlio: disable: - if: SOC_PARLIO_SUPPORTED != 1 @@ -217,14 +251,26 @@ examples/peripherals/parlio: - if: IDF_TARGET == "esp32p4" temporary: true reason: lack of runner + depends_components: + - esp_driver_parlio + +examples/peripherals/parlio/parlio_rx: + disable: + - if: SOC_PARLIO_SUPPORTED != 1 or IDF_TARGET == "esp32p4" + temporary: true + reason: not support esp32p4 yet (IDF-7471) + depends_components: + - esp_driver_parlio -examples/peripherals/parlio/simple_rgb_led_matrix: +examples/peripherals/parlio/parlio_tx/simple_rgb_led_matrix: disable: - if: SOC_PARLIO_SUPPORTED != 1 or SOC_DEDICATED_GPIO_SUPPORTED != 1 disable_test: - if: IDF_TARGET != "esp32c6" temporary: true reason: lack of runners + depends_components: + - esp_driver_parlio examples/peripherals/pcnt: disable: diff --git a/examples/peripherals/parlio/parlio_rx/logic_analyzer/CMakeLists.txt b/examples/peripherals/parlio/parlio_rx/logic_analyzer/CMakeLists.txt new file mode 100644 index 000000000000..7432fd34b211 --- /dev/null +++ b/examples/peripherals/parlio/parlio_rx/logic_analyzer/CMakeLists.txt @@ -0,0 +1,10 @@ +# For more information about build system see +# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html +# The following five lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +set(COMPONENTS main) + +project(logic_analyzer) diff --git a/examples/peripherals/parlio/parlio_rx/logic_analyzer/README.md b/examples/peripherals/parlio/parlio_rx/logic_analyzer/README.md new file mode 100644 index 000000000000..6f91587df245 --- /dev/null +++ b/examples/peripherals/parlio/parlio_rx/logic_analyzer/README.md @@ -0,0 +1,229 @@ +| Supported Targets | ESP32-C6 | ESP32-H2 | +| ----------------- | -------- | -------- | + +# Logic Analyzer Example + +(See the README.md file in the upper level 'examples' directory for more information about examples.) + +This example demonstrates how to implement a logic analyzer via Parallel IO RX peripheral. The main implementation is extracted as `esp_probe` component for portability. + +Parallel IO is a peripheral that can sample data on multiple GPIOs in parallel at a high rate, which in its basic form is exactly the functionality of a logic analyzer. + +This example uses the "software delimiter mode" of the Parallel IO RX driver, so that the Parallel IO RX peripheral can be driven by the internal clock and keep sampling continuously. + +## Example Overview + +Under the default configuration, this example will probe the signals on several GPIOs, meanwhile these GPIOs will generate some signals by GPIO driver. The probed raw data will be stored temporary on the heap. When the allocated heap is run out or the probing time expires, the probing will stop and output the stored raw data to the output stream. + +## How to Use Example + +### Step 0: Requirement + +#### Hardware + +* A development board which has the parlio peripheral integrated, for supported chips see the table at the top +* A USB cable for power supply and programming +* Network connection if using TCP output stream + +#### Extra Software on PC + +* [PulseView](https://sigrok.org/wiki/Downloads) for visualizing the captured signal + +### Step 1: Configure The Project + +Run `idf.py menuconfig` under this example director to configure the example. + +1. The `esp_probe` component can probe either internal signals or external signals, choose this configuration to select: + + * "Select signal source": to select where the signals come from. + + - "Probing the internal signals": the signals come from the chip itself (i.e., internal). The output signals on the GPIO will be feed back to the Parallel IO RX via GPIO matrix. This example only simulates some signals by GPIO driver, you can also modify the example code to probe the signals that produced by other peripherals (like I2C, I2S, SPI, etc). + + - "Probing the External signals": the signals come from external source that connected to the probing GPIOs. + +2. The `esp_probe` component support Flash or TCP stream to output the raw data, choose this configuration to select: + + * "Select ESP probe dump stream": to select the output stream + + - "Dump data into FLASH": the data will be dumped into the Flash, it requires you to allocate a FAT partition in the partition table. In this example, there is a `storage` partition for saving the probed raw data. Then we can use `esptool`to read this partition on the host side. Normally we read the whole `storage` partition, because we don't know the exact start address that the raw data saved. + + - "Dump data to the host using TCP": the data will be dumped to the host directly via the TCP stream. Target should support connecting to the network via WiFi or Ethernet. + +3. To change the probing GPIOs, modify the `s_probe_gpio` array in the `logic_analyzer_example_main.c` + +#### Flash Stream + +If we choose to dump into flash, please make sure the data partition label we set in the menuconfig is same as what we set in the `partition.csv` + +* "The label of the data storage partition": sets the partition label that specified in `partition.csv` file. Defaults to `storage`. + +#### TCP Stream + +If we choose to dump via TCP, please specify the WiFi or Ethernet configurations in the menu "Example Connection Configuration", and then specify the TCP server information in "ESP probe configurations > Select ESP probe dump stream" menu: + +* "TCP server IP address": the IP address that TCP server bound +* "TCP server port": the port the TCP server is listening on (default 8888) + +### Step 2: Build And Flash + +(If you're using TCP stream, please go to Step 3 first) + +Build the project and flash it to the board, then run monitor tool to view serial output: + +```bash +idf.py -p PORT build flash monitor +``` + +And then waiting until the main task finished + +``` +I (2625) main_task: Returned from app_main() +``` + +(To exit the serial monitor, type ``Ctrl-]``.) + +See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects. + +### Step 3: Convert Raw Data into VCD Format + +Before conversion, we need to know how many channels in the raw data. In this example, we probed 4 GPIOs that set in `s_probe_gpio`, so we need to specify the channel number for the conversion. + +#### Flash Stream + +1. Exit the serial monitor and use `esptool` to read the flash partition to the host: + + For the default partition in this example: + + ```bash + parttool.py -p -b 406800 -f partitions.csv read_partition -h -n storage --output probe_raw.dat + ``` +2. Convert the raw data into VCD format: + + (Run the following command under the example directory) + ```bash + python components/esp_probe/host/vcd_dumper.py -n 4 -i probe_raw.dat -o probe_vcd_data.vcd + ``` + + * `-n`: the channel number that probed + * `-i`: the the input raw data file + * `-o`: the output vcd file name (optional) + + Then you can get the VCD file on the host. + +**Note:** This example converted the whole partition into VCD file for demonstration, you can also adopt some methods to extract the saved file in this partitions like: + +- Download the whole partition into the host and mount it as FS on host by Loop Device or RAM Disk; +- Download the whole partition into the host and parse the FAT Root Directory and find the data offset of the file `/esp_probe/probe_raw.dat`; + +#### TCP Stream + +1. Start the TCP server on the host: + + (Run the following command under the example directory) + ```bash + python components/esp_probe/host/tcp_server -n 4 -p 8888 -o probe_vcd_data.vcd + ``` + + * `-n`: the channel number that probed + * `-p`: the TCP port (default 8888) + * `-o`: the output vcd file name (optional) + + Then you can see the TCP server is on, log printed like: + + ``` + TCP listening at 192.168.1.106:8888 + ``` +2. Jump back to the Step 2 to flash and monitor the target + +3. If the TCP client connected successfully, there will be data received, you can see the log like: + + ``` + Client 192.168.1.183:49626 joined + data received 1440 bytes + data received 1440 bytes + data received 2880 bytes + ... + Client 192.168.1.183:49626 left + ``` + + Then you can get the VCD data on the host. + +### Step 4: View The Signals on PulseView + +Open PulseView and import the file `probe_vcd_data.vcd` with `Value Change Dump data` option: + +![pulseview_image](./img/pulseview.jpeg) + +#### Internal Signals That Simulated by GPIOs + +![internal_gpio_signals](./img/gpio_sig.jpeg) + +#### External I2S Philips Signals with I2S Decoder + +![external_i2s_signals](./img/i2s_sig.jpeg) + +## Further More Introduction on `esp_probe` + +### Data Mode + +#### Stream Mode + +Stream mode will output the raw data via the output stream without storing. Stream mode can be selected by the helper macro `ESP_PROBE_DEFAULT_STREAM_CONFIG` (the probe GPIOs need to be set additionally). + +* Advantage is that don't need extra storage to store the raw data. +* Disadvantage is that, due to the received data must finish sending before the new data receives, the sample rate is limited by the output stream bandwidth. Normally it can only achieve a low sample rate to avoid data lost. + +#### Buffer Mode (Recommended) + +Buffer mode store the raw data on the heap storage temporary before sending them. Buffer mode can be selected by the helper macro `ESP_PROBE_DEFAULT_BUFFER_CONFIG` (the probe GPIOs need to be set additionally). + +* Advantage is that, it can support a high sample rate. +* Disadvantage is that, the sampling time is limited by the available heap size. Normally the available heap size is only several hundreds KB, which can only hold raw data for several ms when sampling with a high rate. But buffer mode is still recommended as it is more useful in most of cases. + +#### Buffer Stream Mode + +Buffer Stream mode store the raw data on the heap storage temporary but the storage will be used as Ping-Pong buffer to send the data in the storage. Buffer Stream mode can be selected by the helper macro `ESP_PROBE_DEFAULT_BUFFER_STREAM_CONFIG` (the probe GPIOs need to be set additionally). + +* Advantage is that, the sampling time is not limited. Comparing to the Stream mode, it can reach a relative higher sample rate. +* Disadvantage is that, we still need to guarantee the output stream can catch the new data generation, otherwise data will be still be dropped. + +### Output Streams + +Currently `esp_probe` supports `Flash` and `TCP` stream. + +#### Flash Stream + +Requires a built-in Flash or external Flash and a data partition in FAT format. + +* Advantages: + + 1. Support larger storage comparing to the heap; + 2. ESP modules always have Flash on it, and no additional WiFi environment required; + +* Disadvantages: + + 1. Low bandwidth. About several hundreds KB/s supported (e.g. 300+ KB/s on ESP32-H2); + 2. Have to use `esptool` to read the raw data from the partition and then dump it into VCD format additionally; + 3. This example convert the whole storage partition into VCD format, which includes some unrelated data. Or you have to get the file from the partition in some ways additionally. + +#### TCP Stream + +Requires WiFi or Ethernet supported on the target and accessible network. + +* Advantages: + + 1. High bandwidth. Nearly 30 MB/s throughput supported, which allows a higher sample rate. For example, the sample rate can reach `25MB/s` on C6 with `Buffer Mode`, and 700+ KB/s with `Stream mode` without data dropped; + 2. The TCP server can dump the raw data into VCD format directly without other operations; + +* Disadvantages: + + 1. WiFi or Ethernet is required on the target; + 2. Larger image size; + +## Troubleshooting + +* The TCP server will sometimes miss the client disconnection (i.e. no `Client 192.168.1.183:56208 left` log). + - Just quit the progress by `Ctrl + C` and wait for a while util the port is released + +For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon. + diff --git a/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/CMakeLists.txt b/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/CMakeLists.txt new file mode 100644 index 000000000000..e4812400d7ea --- /dev/null +++ b/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/CMakeLists.txt @@ -0,0 +1,12 @@ +set(src "hw_impl/esp_probe_impl_parlio.c" "esp_probe.c" + "stream/flash_fatfs.c" "stream/file_stream.c") + +if(CONFIG_SOC_WIFI_SUPPORTED OR CONFIG_SOC_EMAC_SUPPORTED) + list(APPEND src "stream/tcp_stream.c") +endif() + +idf_component_register(SRCS ${src} + INCLUDE_DIRS "./include" + PRIV_INCLUDE_DIRS "." + PRIV_REQUIRES fatfs esp_partition esp_netif + lwip esp_driver_parlio) diff --git a/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/esp_probe.c b/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/esp_probe.c new file mode 100644 index 000000000000..1c44d9a74847 --- /dev/null +++ b/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/esp_probe.c @@ -0,0 +1,288 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "freertos/idf_additions.h" +#include "sdkconfig.h" +#include "esp_probe_private.h" +#include "esp_probe.h" +#include "esp_check.h" +#include "esp_cpu.h" + +static const char *TAG = "esp_probe"; + +#define GET_US_BY_CCOUNT(t) ((float)(t)/CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ) + +static void s_esp_probe_flush_task(void *args) +{ + esp_probe_handle_t handle = (esp_probe_handle_t)args; + esp_probe_flush_data_t flush_data; + + // Suspend if not start probing yet + if (!handle->flags.is_started) { + vTaskSuspend(NULL); + } + + while (1) { + if (xQueueReceive(handle->flush_que, &flush_data, portMAX_DELAY) == pdTRUE) { + if (flush_data.size) { + fwrite(flush_data.data, flush_data.size, 1, handle->out_stream); + } + } + // If probe is stopped and no data to flush, suspend the task + if (!handle->flags.is_started && uxQueueSpacesAvailable(handle->flush_que) == 2) { + vTaskSuspend(NULL); + } + } +} + +static void s_esp_probe_push_flush_queue(esp_probe_handle_t handle, void *data, uint32_t size, bool reset_ptr) +{ + esp_probe_flush_data_t flush_data = { + .data = data, + .size = size, + }; + TickType_t timeout_tick = 0; + if (!size) { + // If no data to flush but only inform the flush task to suspend + // then wait until data flushed + timeout_tick = portMAX_DELAY; + } + if (xQueueSend(handle->flush_que, &flush_data, timeout_tick) != pdTRUE) { + esp_probe_flush_data_t dummy; + xQueueReceive(handle->flush_que, &dummy, 0); + xQueueSend(handle->flush_que, &flush_data, 0); + ESP_LOGW(TAG, "data dropped"); + } + if (reset_ptr) { + handle->w_ptr = 0; + handle->f_ptr = 0; + } else { + handle->f_ptr = handle->w_ptr; // Update the flush pointer to the current write pointer + } +} + +static void s_esp_probe_dump_task(void *args) +{ + esp_probe_handle_t handle = (esp_probe_handle_t)args; + esp_probe_recv_data_t recv_data; + bool need_suspend = false; + uint32_t byte_dump = 0; + + // Suspend if not start probing yet + if (!handle->flags.is_started) { + vTaskSuspend(NULL); + } + + while (1) { + // Receive the data that from data receive callback + if (xQueueReceive(handle->recv_que, &recv_data, portMAX_DELAY) == pdTRUE) { + if (handle->buf_size) { // Buffer mode, adopt ping-pong buffer strategy to flush data + if (unlikely(handle->w_ptr + recv_data.size > handle->max_dump_size)) { + // If the received in buffer has exceeded the max_dump_size but not reached the buffer size + // Only dump the rest piece of data + byte_dump = handle->max_dump_size - handle->w_ptr; + } else { + // If the rest buffer is not sufficient for the received data + // Flush the second half of the buffer + if (handle->w_ptr + recv_data.size > handle->buf_size) { + s_esp_probe_push_flush_queue(handle, handle->buffer + handle->f_ptr, + handle->w_ptr - handle->f_ptr, true); + } + byte_dump = recv_data.size; + } + memcpy(handle->buffer + handle->w_ptr, recv_data.data, byte_dump); + handle->w_ptr += byte_dump; + + // If the last flush pointer is 0 and the stored data has exceed the half of the buffer + // Flush the first half of the buffer + // Here minus some extra bytes to trigger the flush more timely + if (!handle->f_ptr && handle->w_ptr >= handle->buf_size / 2 - 32) { + s_esp_probe_push_flush_queue(handle, handle->buffer, handle->w_ptr, false); + } + + } else { // Stream mode, write directly + if (handle->dump_data_size + recv_data.size > handle->max_dump_size) { + byte_dump = handle->max_dump_size - handle->dump_data_size; + } else { + byte_dump = recv_data.size; + } + fwrite(recv_data.data, byte_dump, 1, handle->out_stream); + } + // Update the dump data size statistic + handle->dump_data_size += byte_dump; + } + uint32_t exceed_bytes = 0; + // If reach the max dump size, suspend the task + if (handle->dump_data_size >= handle->max_dump_size) { + ESP_LOGW(TAG, "Dump data size reached the max dump size"); + need_suspend = true; + exceed_bytes = handle->dump_data_size - handle->max_dump_size; + } + // If probe is stopped, suspend the task + need_suspend |= !handle->flags.is_started; + + if (need_suspend) { + // Flush the legacy data before suspend + if (handle->buf_size) { + s_esp_probe_push_flush_queue(handle, handle->buffer + handle->f_ptr, + handle->w_ptr - handle->f_ptr - exceed_bytes, true); + } + vTaskSuspend(NULL); + } + } +} + +static void s_esp_probe_destroy_object(esp_probe_handle_t handle) +{ + if (handle) { + if (handle->buffer) { + free(handle->buffer); + handle->buffer = NULL; + } + if (handle->recv_que) { + vQueueDeleteWithCaps(handle->recv_que); + handle->recv_que = NULL; + } + if (handle->dump_task) { + vTaskDelete(handle->dump_task); + handle->dump_task = NULL; + } + if (handle->flush_que) { + vQueueDeleteWithCaps(handle->flush_que); + handle->flush_que = NULL; + } + if (handle->flush_task) { + vTaskDelete(handle->flush_task); + handle->flush_task = NULL; + } + free(handle); + } +} + +esp_err_t esp_new_probe(esp_probe_config_t *config, esp_probe_handle_t* ret_handle) +{ + ESP_RETURN_ON_FALSE(config && ret_handle, ESP_ERR_INVALID_ARG, TAG, "input parameter is NULL"); + // Get the max channel id and check whether any gpio specified + int max_chan_id = ESP_PROBE_MAX_CHANNEL_NUM - 1; + while (config->probe_gpio[max_chan_id] < 0) { + max_chan_id--; + ESP_RETURN_ON_FALSE(max_chan_id > 0, ESP_ERR_INVALID_ARG, TAG, "no gpio to probe"); + } + // Create the probe object + esp_err_t ret = ESP_OK; + esp_probe_handle_t probe = heap_caps_calloc(1, sizeof(struct esp_probe_t), ESP_PROBE_ALLOC_CAPS); + ESP_RETURN_ON_FALSE(probe, ESP_ERR_NO_MEM, TAG, "no memory for probe object"); + probe->max_dump_size = config->max_dump_size_kb ? (config->max_dump_size_kb << 10) : UINT32_MAX; + + // Allocate the storage buffer if the data should be cached + if (config->storage_depth_kb) { + if (config->storage_depth_kb < 8) { + ESP_LOGW(TAG, "the storage depth is at least 8 KB, set to 8 KB instead"); + probe->buf_size = 8192; + } else { + probe->buf_size = config->storage_depth_kb * 1024; + } + probe->buffer = calloc(1, probe->buf_size); + ESP_GOTO_ON_FALSE(probe->buffer, ESP_ERR_NO_MEM, err, TAG, "no memory for data storage"); + // Create flush task + xTaskCreate(s_esp_probe_flush_task, "esp_probe_flush_task", 4096, probe, + (UBaseType_t)config->dump_task_priority, &(probe->flush_task)); + // Create the flush queue + probe->flush_que = xQueueCreateWithCaps(2, sizeof(esp_probe_flush_data_t), MALLOC_CAP_DEFAULT); + ESP_GOTO_ON_FALSE(probe->flush_que, ESP_ERR_NO_MEM, err, TAG, "no memory for flush queue"); + } + + // Create the receive queue + probe->recv_que = xQueueCreateWithCaps(ESP_PROBE_DEFAULT_Q_DEPTH, sizeof(esp_probe_recv_data_t), ESP_PROBE_ALLOC_CAPS); + ESP_GOTO_ON_FALSE(probe->recv_que, ESP_ERR_NO_MEM, err, TAG, "no memory for receive queue"); + + // Create the dump task and suspend it + xTaskCreate(s_esp_probe_dump_task, "esp_probe_dump_task", 4096, probe, + (UBaseType_t)config->dump_task_priority, &(probe->dump_task)); + + // Initialize the hardware peripheral + ESP_GOTO_ON_ERROR(esp_probe_priv_init_hardware(probe, config, max_chan_id), err, TAG, "fail to init the hardware peripheral"); + + *ret_handle = probe; + return ret; + +err: + s_esp_probe_destroy_object(probe); + probe = NULL; + return ret; +} + +esp_err_t esp_del_probe(esp_probe_handle_t handle) +{ + ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_ARG, TAG, "input parameter is NULL"); + ESP_RETURN_ON_FALSE(!handle->flags.is_started, ESP_ERR_INVALID_STATE, TAG, "probe is still running"); + esp_probe_priv_deinit_hardware(handle); + s_esp_probe_destroy_object(handle); + return ESP_OK; +} + +esp_err_t esp_probe_start(esp_probe_handle_t handle, FILE *out_stream) +{ + ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_ARG, TAG, "input parameter is NULL"); + ESP_RETURN_ON_FALSE(!handle->flags.is_started, ESP_ERR_INVALID_STATE, TAG, "probe is still running"); + handle->flags.is_started = true; + + esp_err_t ret = ESP_OK; + ESP_GOTO_ON_ERROR(esp_probe_priv_enable_hardware(handle), err, TAG, "enable the hardware failed"); + out_stream = out_stream ? out_stream : stdout; + if (handle->out_stream != out_stream) { + handle->out_stream = out_stream; + // io stream changed, reset timestamp and dump data size + handle->dump_data_size = 0; + } + if (handle->buf_size) { + // Reset the queue before resume the task + xQueueReset(handle->flush_que); + vTaskResume(handle->flush_task); + } + // Reset the queue before resume the task + xQueueReset(handle->recv_que); + vTaskResume(handle->dump_task); + + return ret; +err: + handle->flags.is_started = false; + return ret; +} + +esp_err_t esp_probe_stop(esp_probe_handle_t handle, uint32_t *dump_data_size) +{ + ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_ARG, TAG, "input parameter is NULL"); + if (!handle->flags.is_started) { + return ESP_OK; + } + // Set start flag to false + handle->flags.is_started = false; + + // Waiting for the dump task be suspended after detecting the start flag is cleared + while (eTaskGetState(handle->dump_task) != eSuspended) { + vTaskDelay(1); + } + ESP_RETURN_ON_ERROR(esp_probe_priv_disable_hardware(handle), TAG, "disable the hardware failed"); + // Waiting for the flush task to flush the legacy data + if (handle->buf_size) { + // Push an empty data to inform the flush task to suspend + s_esp_probe_push_flush_queue(handle, NULL, 0, true); + while (eTaskGetState(handle->flush_task) != eSuspended) { + vTaskDelay(1); + } + } + if (dump_data_size) { + *dump_data_size = handle->dump_data_size; + } + return ESP_OK; +} diff --git a/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/esp_probe_private.h b/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/esp_probe_private.h new file mode 100644 index 000000000000..77d6b4b517ee --- /dev/null +++ b/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/esp_probe_private.h @@ -0,0 +1,66 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "stdint.h" +#include "sdkconfig.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "esp_heap_caps.h" +#include "esp_probe.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ESP_PROBE_DEFAULT_Q_DEPTH 8 +#define ESP_PROBE_DEFAULT_MAX_RECV_SIZE (ESP_PROBE_DEFAULT_Q_DEPTH * 4092) +#if CONFIG_PARLIO_ISR_IRAM_SAFE +#define ESP_PROBE_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT) +#else +#define ESP_PROBE_ALLOC_CAPS MALLOC_CAP_DEFAULT +#endif + +struct esp_probe_t { + uint32_t sample_width; /*!< sample width, i.e., enabled probe channel nums */ + uint32_t sample_rate_hz; /*!< sample rate in Hz */ + FILE *out_stream; /*!< Output stream */ + TaskHandle_t dump_task; /*!< Task handle of the raw data dump task */ + TaskHandle_t flush_task; /*!< Task handle of the raw data flush task, only created in buffer mode */ + int dump_task_priority; /*!< Task priority */ + uint32_t max_dump_size; /*!< Max dump size */ + uint32_t dump_data_size; /*!< Dump data size */ + QueueHandle_t recv_que; /*!< Receive data queue */ + QueueHandle_t flush_que; /*!< Flush data queue */ + uint8_t *buffer; /*!< The storage buffer for dump data */ + uint32_t buf_size; /*!< The storage buffer size/depth */ + uint32_t w_ptr; /*!< The pointer of the current write offset of the buffer */ + uint32_t f_ptr; /*!< The pointer of the current flush offset of the buffer */ + struct { + volatile uint32_t is_started: 1; /*!< Is the sampling started */ + } flags; +}; + +typedef struct { + void *data; /*!< The pointer of the received raw data buffer */ + uint32_t size; /*!< The size of the received raw data buffer */ +} esp_probe_recv_data_t; + +typedef esp_probe_recv_data_t esp_probe_flush_data_t; + +esp_err_t esp_probe_priv_init_hardware(esp_probe_handle_t handle, esp_probe_config_t *config, int max_chan_id); + +esp_err_t esp_probe_priv_deinit_hardware(esp_probe_handle_t handle); + +esp_err_t esp_probe_priv_enable_hardware(esp_probe_handle_t handle); + +esp_err_t esp_probe_priv_disable_hardware(esp_probe_handle_t handle); + +#ifdef __cplusplus +} +#endif diff --git a/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/host/tcp_server.py b/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/host/tcp_server.py new file mode 100644 index 000000000000..e5fee66ed460 --- /dev/null +++ b/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/host/tcp_server.py @@ -0,0 +1,76 @@ +# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 + +import argparse +import socket +from io import TextIOWrapper +from typing import Any + +from vcd_dumper import VCDDumper + + +def _get_local_host_ip() -> Any: + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + s.connect(('8.8.8.8', 80)) + return s.getsockname()[0] + + +def _tcp_server(port:int, chan_num:int, vcd_out_io:TextIOWrapper) -> None: + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + host = _get_local_host_ip() + s.bind((host, port)) + s.listen(5) + print(f'TCP listening at {host}:{port}') + + try: + while True: + c, addr = s.accept() + print(f'Client {addr[0]}:{addr[1]} joined') + vcd = VCDDumper() + vcd.open_new_vcd_file(chan_num, vcd_out_io) + + while True: + recv_data = c.recv(16384) + if recv_data == b'': + break + print(f'data received {len(recv_data)} bytes') + vcd.dump_samples(recv_data) + + print(f'Client {addr[0]}:{addr[1]} left') + vcd.close_vcd_file() + c.close() + finally: + vcd.close_vcd_file() + c.close() + s.shutdown(socket.SHUT_RDWR) + s.close() + print('TCP server closed') + + +def tcp_server_main() -> None: + # Args parser + parser = argparse.ArgumentParser(description='Dump raw data to VCD format') + parser.add_argument('-n', '--chan-num', type=int, help='The channel number that probed') + parser.add_argument('-p', '--port', type=int, help='The TCP port', default=8888) + parser.add_argument('-o', '--output-file', type=argparse.FileType('w'), help='The output vcd file name (optional)', default=None) + + # Parse args + args = parser.parse_args() + chan_num = args.chan_num + port = args.port + vcd_out_io = args.output_file + if chan_num <= 0: + raise ValueError('Invalid channel number') + + # Get the actual probe channel number (round up to the nearest number that is power of 2) + p = 0 + while (1 << p) < chan_num: + p = p + 1 + chan_num = 1 << p + + _tcp_server(port, chan_num, vcd_out_io) + + +if __name__ == '__main__': + tcp_server_main() diff --git a/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/host/vcd_dumper.py b/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/host/vcd_dumper.py new file mode 100644 index 000000000000..0e7fdc0871f8 --- /dev/null +++ b/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/host/vcd_dumper.py @@ -0,0 +1,128 @@ +# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 + +# This dumper script run on the host after get the probed raw data on the host +# Usage: python vcd_dumper.py -n -f + +import argparse +import time +from io import FileIO, TextIOWrapper + + +class VCDDumper(): + def __init__(self) -> None: + pass + + def open_new_vcd_file(self, chan_num: int, vcd_out_io:TextIOWrapper) -> None: + self.ts = 0 + self.odd_samples = 0 + self.prev = 0 + self.chan_num = chan_num + self.step = 1 if chan_num <= 8 else 2 + # vcd file name + if vcd_out_io: + self.vcd = vcd_out_io + else: + dump_file = 'probe_{}.vcd'.format(time.strftime('%m-%d_%H-%M-%S')) + self.vcd = open(dump_file, 'w', encoding='utf-8') + + # Write VCD header + self.vcd.write('$date today $end\n' + '$timescale 1 ns $end\n' + '$scope module logic_analyzer $end\n') + for i in range(chan_num): + self.vcd.write(f'$var wire 1 {chr(33 + i)} chan_{i} $end\n') + self.vcd.write('$upscope $end\n' + '$enddefinitions $end\n' + '$dumpvars\n') + for i in range(chan_num): + self.vcd.write(f'0{chr(33 + i)}\n') + self.vcd.write('$end\n') + + def close_vcd_file(self) -> None: + if self.vcd: + self.vcd.close() + + def _dump_one_sample_to_vcd(self, prev:int, curr:int) -> None: + change_mask = prev ^ curr + if change_mask == 0: + return + self.vcd.write(f'#{self.ts}\n') + i = 0 + while change_mask != 0: + if change_mask & 1: + self.vcd.write(f'{(curr >> i) & 1}{chr(33 + i)}\n') + change_mask >>= 1 + i += 1 + + def dump_samples(self, raw_data:bytes) -> None: + # Parse the raw data and write VCD body + byte_cnt = 0 + # If last time is one byte left, load it + if self.odd_samples: + samples = self.odd_samples + self.odd_samples = 0 + byte_cnt = 1 + else: + samples = 0 + + # Loop the raw data and parse byte by byte + for byte in raw_data: + byte_cnt += 1 + if byte_cnt % self.step == 0: + samples = (samples & 0xff00) | byte + self.odd_samples = 0 + else: + samples = byte << 8 + self.odd_samples = samples + continue + samples = byte + + # Loop the samples in one byte + for _ in range((8 * self.step) // self.chan_num): + curr = samples & ((2 ** self.chan_num) - 1) + self._dump_one_sample_to_vcd(self.prev, curr) + samples >>= self.chan_num + self.prev = curr + self.ts += 1 + + def dump_samples_from_file(self, raw_in_io:FileIO) -> None: + data_bytes = raw_in_io.read() + self.dump_samples(data_bytes) + + +def dump_binary_raw_data_to_vcd(chan_num:int, raw_in_io:FileIO, vcd_out_io:TextIOWrapper) -> None: + vcd = VCDDumper() + vcd.open_new_vcd_file(chan_num, vcd_out_io) + vcd.dump_samples_from_file(raw_in_io) + vcd.close_vcd_file() + print('Converted successfully!') + + +def dump_vcd_main() -> None: + # Args parser + parser = argparse.ArgumentParser(description='Dump raw data to VCD format') + parser.add_argument('-n', '--chan-num', type=int, help='The channel number that probed') + parser.add_argument('-i', '--input-file', type=argparse.FileType('rb'), help='The the input raw data file') + parser.add_argument('-o', '--output-file', type=argparse.FileType('w'), help='The output vcd file name (optional)', default=None) + + # Parse args + args = parser.parse_args() + chan_num = args.chan_num + raw_in_io = args.input_file + vcd_out_io = args.output_file + if chan_num <= 0: + raise ValueError('Invalid channel number') + + # Get the actual probe channel number (round up to the nearest number that is power of 2) + p = 0 + while (1 << p) < chan_num: + p = p + 1 + chan_num = 1 << p + + # Convert the data to the VCD format and save it into the file + dump_binary_raw_data_to_vcd(chan_num, raw_in_io, vcd_out_io) + + +if __name__ == '__main__': + dump_vcd_main() diff --git a/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/hw_impl/esp_probe_impl_parlio.c b/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/hw_impl/esp_probe_impl_parlio.c new file mode 100644 index 000000000000..389687f609a2 --- /dev/null +++ b/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/hw_impl/esp_probe_impl_parlio.c @@ -0,0 +1,147 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "sdkconfig.h" +#include "driver/parlio_rx.h" +#include "esp_clk_tree.h" +#include "esp_heap_caps.h" +#include "esp_check.h" +#include "esp_probe_private.h" + +typedef struct { + parlio_rx_unit_handle_t rx_unit; + parlio_rx_delimiter_handle_t deli; + uint8_t *payload; +} esp_probe_impl_pralio_t; + +static const char *TAG = "esp_probe_impl"; +static esp_probe_impl_pralio_t *s_ephi = NULL; + +static bool s_esp_probe_on_recv_callback(parlio_rx_unit_handle_t rx_unit, const parlio_rx_event_data_t *edata, void *user_data) +{ + esp_probe_handle_t handle = (esp_probe_handle_t)user_data; + esp_probe_recv_data_t recv_data = { + .data = edata->data, + .size = edata->recv_bytes, + }; + BaseType_t need_yield; + xQueueSendFromISR(handle->recv_que, &recv_data, &need_yield); + + return need_yield == pdTRUE; +} + +esp_err_t esp_probe_priv_init_hardware(esp_probe_handle_t handle, esp_probe_config_t *config, int max_chan_id) +{ + ESP_RETURN_ON_FALSE(!s_ephi, ESP_ERR_INVALID_STATE, TAG, "parlio rx has initialized"); + ESP_RETURN_ON_FALSE(max_chan_id <= PARLIO_RX_UNIT_MAX_DATA_WIDTH, ESP_ERR_NOT_SUPPORTED, TAG, + "The target can only support upto %d channels", (int)PARLIO_RX_UNIT_MAX_DATA_WIDTH); + esp_err_t ret = ESP_OK; + s_ephi = calloc(1, sizeof(esp_probe_impl_pralio_t)); + ESP_RETURN_ON_FALSE(s_ephi, ESP_ERR_NO_MEM, TAG, "no memory for the esp probe hardware implementation"); + s_ephi->payload = heap_caps_calloc(1, ESP_PROBE_DEFAULT_MAX_RECV_SIZE, ESP_PROBE_ALLOC_CAPS); + ESP_GOTO_ON_FALSE(s_ephi->payload, ESP_ERR_NO_MEM, err, TAG, "no memory for payload"); + + // Get the channel number, the channel number can only be the power of 2 + uint32_t sample_width = 1; + while (sample_width < max_chan_id) { + sample_width <<= 1; + } + handle->sample_width = sample_width; + + // Get the sample rate + uint32_t src_freq_hz = 0; + esp_clk_tree_src_get_freq_hz(PARLIO_CLK_SRC_DEFAULT, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &src_freq_hz); + uint32_t sample_rate_hz = config->sample_rate_hz ? config->sample_rate_hz : src_freq_hz; + if (sample_rate_hz > src_freq_hz) { + ESP_LOGW(TAG, "sample rate exceed the max value, limited to %"PRIu32, src_freq_hz); + sample_rate_hz = src_freq_hz; + } + handle->sample_rate_hz = sample_rate_hz; + + // Allocate the parlio rx instance + parlio_rx_unit_config_t parlio_rx_cfg = { + .trans_queue_depth = ESP_PROBE_DEFAULT_Q_DEPTH, + .max_recv_size = ESP_PROBE_DEFAULT_MAX_RECV_SIZE, + .data_width = sample_width, + .clk_src = PARLIO_CLK_SRC_DEFAULT, + .ext_clk_freq_hz = 0, // Use the internal clock, no external clock needed + .clk_in_gpio_num = GPIO_NUM_NC, // Use the internal clock, no external clock input gpio needed + .exp_clk_freq_hz = sample_rate_hz, // Set expected clock frequency (i.e., sample rate) + .clk_out_gpio_num = GPIO_NUM_NC, // Use the internal clock for sampling and does not need to output + .valid_gpio_num = GPIO_NUM_NC, // Does not need valid gpio, all data gpio are used as sampling channel + .flags = { + .clk_gate_en = false, + .io_loop_back = true, + .io_no_init = true, + } + }; + memcpy(parlio_rx_cfg.data_gpio_nums, config->probe_gpio, PARLIO_RX_UNIT_MAX_DATA_WIDTH * sizeof(gpio_num_t)); + ESP_GOTO_ON_ERROR(parlio_new_rx_unit(&parlio_rx_cfg, &s_ephi->rx_unit), err, TAG, "Failed to allocate the parlio rx unit"); + + // Allocate the software delimiter + parlio_rx_soft_delimiter_config_t sft_deli_cfg = { + .sample_edge = PARLIO_SAMPLE_EDGE_POS, + .eof_data_len = 0xFFFF > ESP_PROBE_DEFAULT_MAX_RECV_SIZE ? ESP_PROBE_DEFAULT_MAX_RECV_SIZE : 0xFFFF, + .timeout_ticks = 0, + }; + ESP_GOTO_ON_ERROR(parlio_new_rx_soft_delimiter(&sft_deli_cfg, &s_ephi->deli), err, TAG, "Failed to allocate the delimiter"); + + // Register the data receive callback + parlio_rx_event_callbacks_t cbs = { + .on_partial_receive = s_esp_probe_on_recv_callback, + }; + ESP_GOTO_ON_ERROR(parlio_rx_unit_register_event_callbacks(s_ephi->rx_unit, &cbs, handle), err, TAG, "Failed to register the receive callback"); + + return ESP_OK; +err: + esp_probe_priv_deinit_hardware(handle); + return ret; +} + +esp_err_t esp_probe_priv_deinit_hardware(esp_probe_handle_t handle) +{ + (void)handle; + if (s_ephi) { + if (s_ephi->deli) { + ESP_RETURN_ON_ERROR(parlio_del_rx_delimiter(s_ephi->deli), TAG, "Failed to delete the parlio rx delimiter"); + s_ephi->deli = NULL; + } + if (s_ephi->rx_unit) { + ESP_RETURN_ON_ERROR(parlio_del_rx_unit(s_ephi->rx_unit), TAG, "Failed to delete the parlio rx unit"); + s_ephi->rx_unit = NULL; + } + if (s_ephi->payload) { + free(s_ephi->payload); + s_ephi->payload = NULL; + } + free(s_ephi); + s_ephi = NULL; + } + return ESP_OK; +} + +esp_err_t esp_probe_priv_enable_hardware(esp_probe_handle_t handle) +{ + (void)handle; + ESP_RETURN_ON_ERROR(parlio_rx_unit_enable(s_ephi->rx_unit, true), TAG, "Failed to enable the parlio rx unit"); + ESP_RETURN_ON_ERROR(parlio_rx_soft_delimiter_start_stop(s_ephi->rx_unit, s_ephi->deli, true), TAG, "Failed to start the soft delimiter"); + parlio_receive_config_t recv_cfg = { + .delimiter = s_ephi->deli, + .flags.partial_rx_en = true, // Infinite receiving, use callback to get received data + }; + ESP_RETURN_ON_ERROR(parlio_rx_unit_receive(s_ephi->rx_unit, s_ephi->payload, ESP_PROBE_DEFAULT_MAX_RECV_SIZE, &recv_cfg), TAG, "Failed to receive data"); + return ESP_OK; +} + +esp_err_t esp_probe_priv_disable_hardware(esp_probe_handle_t handle) +{ + (void)handle; + ESP_RETURN_ON_ERROR(parlio_rx_soft_delimiter_start_stop(s_ephi->rx_unit, s_ephi->deli, false), TAG, "Failed to stop the soft delimiter"); + ESP_RETURN_ON_ERROR(parlio_rx_unit_disable(s_ephi->rx_unit), TAG, "Failed to disable the parlio rx unit"); + return ESP_OK; +} diff --git a/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/include/esp_probe.h b/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/include/esp_probe.h new file mode 100644 index 000000000000..a6cec6f98fc7 --- /dev/null +++ b/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/include/esp_probe.h @@ -0,0 +1,147 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "driver/parlio_rx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ESP_PROBE_MAX_CHANNEL_NUM 16 /*!< Max supported probe channel number. + Note that not all targets can reach the max channel, for example, ESP32-H2 has only 8 channels */ +#define ESP_PROBE_MAX_SAMPLE_RATE 0 /*!< The maximum sample rates are different among different targets, + Set 0 to adopt the maximum sample rate of the current target */ + +/** + * @brief ESP Probe stream mode default configuration + * @note The stream mode relies heavily on the bandwidth of the output stream + * Stream mode can only achieve a relatively low sample rate to guarantee no samples are dropped, + * But it can keep sampling continuously for a long time + */ +#define ESP_PROBE_DEFAULT_STREAM_CONFIG(rate_hz) { \ + .sample_rate_hz = rate_hz, \ + .dump_task_priority = 6, \ + .storage_depth_kb = 0, \ + .max_dump_size_kb = 0, \ + .probe_gpio = { \ + [0 ... ESP_PROBE_MAX_CHANNEL_NUM - 1] = -1, \ + }, \ +} + +/** + * @brief ESP Probe buffer mode default configuration + * @note The buffer mode will store the data onto heap storage first, + * and output all of them to the stream in once. + * @note The probe will stop if run out of the given storage on heap. + * So that to guarantee a reliable data storing during the sampling period. + * However, the disadvantage is that, the probing time is limited by the available heap size, + * the higher the sample rate is, the shorter time the sampling last. + */ +#define ESP_PROBE_DEFAULT_BUFFER_CONFIG(rate_hz, depth_kb) { \ + .sample_rate_hz = rate_hz, \ + .dump_task_priority = 6, \ + .storage_depth_kb = depth_kb, \ + .max_dump_size_kb = depth_kb, \ + .probe_gpio = { \ + [0 ... ESP_PROBE_MAX_CHANNEL_NUM - 1] = -1, \ + }, \ +} + +/** + * @brief ESP Probe buffer stream mode default configuration + * @note The buffer stream mode will store the data onto heap storage first, + * and output them to the stream every half of the storage + * @note Buffer stream mode means the probe will loop to use the given storage on heap. + * So that we can also sample the data continuously for a long time. + * However, while the data outputting rate can't catch the data producing rate, + * data will still be dropped. + * The difference comparing to the stream mode is that, it sends a larger block in every output, + * i.e., it can hold more reliable samples for a time + */ +#define ESP_PROBE_DEFAULT_BUFFER_STREAM_CONFIG(rate_hz, depth_kb) { \ + .sample_rate_hz = rate_hz, \ + .dump_task_priority = 6, \ + .storage_depth_kb = depth_kb, \ + .max_dump_size_kb = 0, \ + .probe_gpio = { \ + [0 ... ESP_PROBE_MAX_CHANNEL_NUM - 1] = -1, \ + }, \ +} + +typedef struct { + uint32_t sample_rate_hz; /*!< The sample rate of the probe, unit: Hz, set '0' to use the max sample rate */ + int probe_gpio[ESP_PROBE_MAX_CHANNEL_NUM]; /*!< The GPIO of each probe channel, please set '-1' for unused channels, + some targets like ESP32-H2 only support up to 8 channels */ + uint32_t storage_depth_kb; /*!< The max heap storage depth for probed data (unit: kilobytes). + 0: the probed data won't be stored but output in realtime, i.e. stream mode; + others: the probed data will be stored in a ping-pong buffer, + The ping-pong buffer will be flushed alternately, i.e. buffer mode. + ATTENTION: storage depth at lease be 8 KB, otherwise there is no difference with stream mode. */ + uint32_t max_dump_size_kb; /*!< The max dump size for the limited storage (like flash/ram) (unit: kilobytes), + The probe will stop if the dump data size reach this value. + set 0 for no dump size limitation (like dumping to the host via UART/USB/Network), + set equals to `storage_depth_kb` to guarantee no sample lost in a short time */ + uint32_t dump_task_priority; /*!< The priority of the dump task, which used for dumping the probed data via the out stream */ +} esp_probe_config_t; + +typedef struct esp_probe_t *esp_probe_handle_t; /*!< The handle of probe instance */ + +/** + * @brief Allocate a new probe instance + * + * @param[in] config The probe configuration + * @param[out] ret_handle The returned probe handle + * @return + * - ESP_OK Success to allocate the probe instance + * - ESP_NO_MEM No memory for probe instance + * - ESP_ERR_INVALID_ARG NULL pointer or invalid configuration + * - ESP_ERR_NOT_SUPPORTED Exceed the max supported channels + */ +esp_err_t esp_new_probe(esp_probe_config_t *config, esp_probe_handle_t* ret_handle); + +/** + * @brief Delete the probe instance + * + * @param[in] handle The probe handle + * @return + * - ESP_OK Success to delete the probe instance + * - ESP_ERR_INVALID_ARG NULL pointer + * - ESP_ERR_INVALID_STATE The probe has not stopped yet + */ +esp_err_t esp_del_probe(esp_probe_handle_t handle); + +/** + * @brief Start sampling on the probe channels + * + * @param[in] handle The probe handle + * @param[in] out_stream The output stream for the VCD data, set NULL will use 'stdout' by default + * @return + * - ESP_OK Success to start the sampling on the probe channels + * - ESP_ERR_INVALID_ARG NULL pointer + * - ESP_ERR_INVALID_STATE The probe has already started + */ +esp_err_t esp_probe_start(esp_probe_handle_t handle, FILE *out_stream); + +/** + * @brief Stop sampling on the probe channels + * @note If the 'esp_probe_config_t::storage_depth_kb' is set (i.e. buffer mode), + * The data in the buffer will be popped to the out stream after this function is called + * @note This function is + * + * @param[in] handle The probe handle + * @param[out] dump_data_size The dumped data size, can be NULL if not needed + * @return + * - ESP_OK Success to stop the sampling on the probe channels + * - Others Failed to stop the sampling + */ +esp_err_t esp_probe_stop(esp_probe_handle_t handle, uint32_t *dump_data_size); + +#ifdef __cplusplus +} +#endif diff --git a/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/include/esp_probe_streams.h b/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/include/esp_probe_streams.h new file mode 100644 index 000000000000..e92b7fe185fe --- /dev/null +++ b/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/include/esp_probe_streams.h @@ -0,0 +1,74 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include "soc/soc_caps.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if SOC_WIFI_SUPPORTED || SOC_EMAC_SUPPORTED +/** + * @brief Open the output stream to the host via TCP + * + * @param[in] host_ip The host IP address + * @param[in] port The host port + * @return + * - The the output stream pointer + */ +FILE* esp_probe_open_tcp_stream(const char *host_ip, int port); + +/** + * @brief Close the output stream to the host + * + * @param[in] f The the output stream pointer + */ +void esp_probe_close_tcp_stream(FILE *f); +#endif // SOC_WIFI_SUPPORTED || SOC_EMAC_SUPPORTED + +/** + * @brief Initialize the FAT partition in SPIFlash + * + * @param[in] mount_point The mount point + * @param[in] partition_label The label of the partition that used for saving the raw probed data + * @param[out] size The size of this partition, can be NULL if not needed + * @return + * - ESP_ERR_NOT_FOUND: Not found the FAT partition with this label + * - ESP_OK: Initialize FAT partition success + * - others: Initialize failed due to other reasons + */ +esp_err_t esp_probe_init_spiflash_fatfs(const char *mount_point, const char *partition_label, uint32_t *size); + +/** + * @brief Deinitialize the FAT partition in SPIFlash + * + * @param[in] mount_point The mount point + */ +void esp_probe_deinit_spiflash_fatfs(const char *mount_point); + +/** + * @brief Open the output stream to the FAT partition in flash + * + * @param[in] file_path The file path to open + * @return + * - The the output stream pointer + */ +FILE* esp_probe_open_file_stream(const char *file_path); + +/** + * @brief Close the output stream to the FAT partition in flash + * + * @param[in] f The the output stream pointer + */ +void esp_probe_close_file_stream(FILE *f); + +#ifdef __cplusplus +} +#endif diff --git a/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/stream/file_stream.c b/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/stream/file_stream.c new file mode 100644 index 000000000000..8f46022e60b6 --- /dev/null +++ b/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/stream/file_stream.c @@ -0,0 +1,31 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include "esp_check.h" + +const static char *TAG = "file_stream"; + +FILE* esp_probe_open_file_stream(const char *file_path) +{ + esp_err_t ret = ESP_FAIL; + // Create new raw data file + FILE *f = fopen(file_path, "wb"); + ESP_GOTO_ON_FALSE(f, ESP_FAIL, err, TAG, "Failed to open file, error %s", strerror(errno)); + ESP_LOGI(TAG, "Stream opened"); + + return f; +err: + ESP_LOGE(TAG, "Open Flash stream failed with error code %s", esp_err_to_name(ret)); + return NULL; +} + +void esp_probe_close_file_stream(FILE *f) +{ + fclose(f); +} diff --git a/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/stream/flash_fatfs.c b/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/stream/flash_fatfs.c new file mode 100644 index 000000000000..7805a219f35d --- /dev/null +++ b/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/stream/flash_fatfs.c @@ -0,0 +1,41 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp_vfs_fat.h" +#include "esp_partition.h" +#include "esp_check.h" + +static const char *TAG = "flash_fat"; + +static wl_handle_t s_wlh = WL_INVALID_HANDLE; + +esp_err_t esp_probe_init_spiflash_fatfs(const char *mount_point, const char *partition_label, uint32_t *size) +{ + // Get the partition info + const esp_partition_t *part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, partition_label); + ESP_RETURN_ON_FALSE(part, ESP_ERR_NOT_FOUND, TAG, "Failed to find the partition with label %s", partition_label); + ESP_LOGI(TAG, "Probe data partition base addr: 0x%lx size: 0x%lx", part->address, part->size); + if (size) { + *size = (uint32_t)part->size; + } + + // Format and mount the partition of storage + esp_vfs_fat_mount_config_t mount_config = { + .max_files = 4, + .format_if_mount_failed = true, + .allocation_unit_size = CONFIG_WL_SECTOR_SIZE, + .disk_status_check_enable = false + }; + ESP_RETURN_ON_ERROR(esp_vfs_fat_spiflash_mount_rw_wl(mount_point, partition_label, &mount_config, &s_wlh), + TAG, "Failed to mount FATFS"); + ESP_LOGI(TAG, "flash FATFS mounted"); + return ESP_OK; +} + +void esp_probe_deinit_spiflash_fatfs(const char *mount_point) +{ + esp_vfs_fat_spiflash_unmount_rw_wl(mount_point, s_wlh); +} diff --git a/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/stream/tcp_stream.c b/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/stream/tcp_stream.c new file mode 100644 index 000000000000..a5d51fb91bc4 --- /dev/null +++ b/examples/peripherals/parlio/parlio_rx/logic_analyzer/components/esp_probe/stream/tcp_stream.c @@ -0,0 +1,84 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "lwip/sockets.h" +#include "esp_check.h" + +#define EXAMPLE_ESP_MAXIMUM_RETRY 5 + +static const char *TAG = "tcp_stream"; + +static int s_tcp_client_connect(const char *host_ip, int port) +{ + int addr_family = 0; + int ip_protocol = 0; + + struct sockaddr_in dest_addr = {}; + dest_addr.sin_addr.s_addr = inet_addr(host_ip); + dest_addr.sin_family = AF_INET; + dest_addr.sin_port = htons(port); + addr_family = AF_INET; + ip_protocol = IPPROTO_IP; + + int sock = socket(addr_family, SOCK_STREAM, ip_protocol); + if (sock < 0) { + ESP_LOGE(TAG, "Unable to create socket: errno %d", errno); + goto _exit; + } + ESP_LOGI(TAG, "Socket created, connecting to %s:%d", host_ip, port); + + int err = connect(sock, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr_in6)); + if (err != 0) { + ESP_LOGE(TAG, "Socket unable to connect: errno %d", errno); + goto _exit; + } + ESP_LOGI(TAG, "Successfully connected"); + return sock; +_exit: + if (sock > 1) { + close(sock); + } + return -1; +} + +FILE* esp_probe_open_tcp_stream(const char *host_ip, int port) +{ + esp_err_t ret = ESP_FAIL; + + // Create a TCP socket + int sock = s_tcp_client_connect(host_ip, port); + if (sock < 0) { + goto err; + } + // LWIP socket has been registered to the VFS, associate the TCP socket with the file descriptor for output stream + FILE *f = fdopen(sock, "wb"); + ESP_GOTO_ON_FALSE(f, ESP_FAIL, err, TAG, "open tcp stream failed, error %s", strerror(errno)); + return f; + +err: + ESP_LOGE(TAG, "Open TCP stream failed with error code %s", esp_err_to_name(ret)); + return NULL; +} + +void esp_probe_close_tcp_stream(FILE *f) +{ + // Get the socket by the file descriptor + int sock = fileno(f); + // Close the file stream + fclose(f); + // Shutdown explicitly to inform the server no further data will be sent + shutdown(sock, SHUT_RDWR); + // Close the socket + close(sock); + ESP_LOGI(TAG, "TCP stream closed"); +} diff --git a/examples/peripherals/parlio/parlio_rx/logic_analyzer/img/gpio_sig.jpeg b/examples/peripherals/parlio/parlio_rx/logic_analyzer/img/gpio_sig.jpeg new file mode 100644 index 000000000000..c02c745b4cc5 Binary files /dev/null and b/examples/peripherals/parlio/parlio_rx/logic_analyzer/img/gpio_sig.jpeg differ diff --git a/examples/peripherals/parlio/parlio_rx/logic_analyzer/img/i2s_sig.jpeg b/examples/peripherals/parlio/parlio_rx/logic_analyzer/img/i2s_sig.jpeg new file mode 100644 index 000000000000..12111a4a0f48 Binary files /dev/null and b/examples/peripherals/parlio/parlio_rx/logic_analyzer/img/i2s_sig.jpeg differ diff --git a/examples/peripherals/parlio/parlio_rx/logic_analyzer/img/pulseview.jpeg b/examples/peripherals/parlio/parlio_rx/logic_analyzer/img/pulseview.jpeg new file mode 100644 index 000000000000..a066a63e60bc Binary files /dev/null and b/examples/peripherals/parlio/parlio_rx/logic_analyzer/img/pulseview.jpeg differ diff --git a/examples/peripherals/parlio/parlio_rx/logic_analyzer/main/CMakeLists.txt b/examples/peripherals/parlio/parlio_rx/logic_analyzer/main/CMakeLists.txt new file mode 100644 index 000000000000..99d72f2201a8 --- /dev/null +++ b/examples/peripherals/parlio/parlio_rx/logic_analyzer/main/CMakeLists.txt @@ -0,0 +1,4 @@ +idf_component_register(SRCS "logic_analyzer_example_main.c" + PRIV_REQUIRES esp_probe nvs_flash esp_netif protocol_examples_common + esp_driver_parlio esp_driver_gpio + INCLUDE_DIRS ".") diff --git a/examples/peripherals/parlio/parlio_rx/logic_analyzer/main/Kconfig.projbuild b/examples/peripherals/parlio/parlio_rx/logic_analyzer/main/Kconfig.projbuild new file mode 100644 index 000000000000..de589fd11175 --- /dev/null +++ b/examples/peripherals/parlio/parlio_rx/logic_analyzer/main/Kconfig.projbuild @@ -0,0 +1,39 @@ +menu "ESP probe configurations" + + choice EXAMPLE_SIGNAL_SRC + prompt "Select signal source" + default EXAMPLE_INTERNAL_SIGNAL + config EXAMPLE_INTERNAL_SIGNAL + bool "Probing the internal signals" + config EXAMPLE_EXTERNAL_SIGNAL + bool "Probing the External signals" + endchoice + + choice EXAMPLE_STREAM + prompt "Select ESP probe dump stream" + default EXAMPLE_FLASH_STREAM if !SOC_WIFI_SUPPORTED && !SOC_EMAC_SUPPORTED + default EXAMPLE_TCP_STREAM if SOC_WIFI_SUPPORTED || SOC_EMAC_SUPPORTED + help + Select the dump stream for the sampled data + config EXAMPLE_FLASH_STREAM + bool "Dump data into FLASH" + config EXAMPLE_TCP_STREAM + depends on SOC_WIFI_SUPPORTED || SOC_EMAC_SUPPORTED + bool "Dump data to the host using TCP" + endchoice + + config EXAMPLE_HOST_IP_ADDR + depends on EXAMPLE_TCP_STREAM + default "192.168.1.100" + string "TCP server IP address" + config EXAMPLE_HOST_PORT + depends on EXAMPLE_TCP_STREAM + default 8888 + int "TCP server port" + + config EXAMPLE_PARTITION_LABEL + depends on EXAMPLE_FLASH_STREAM + default "storage" + string "The label of the data storage partition" + +endmenu diff --git a/examples/peripherals/parlio/parlio_rx/logic_analyzer/main/idf_component.yml b/examples/peripherals/parlio/parlio_rx/logic_analyzer/main/idf_component.yml new file mode 100644 index 000000000000..718194867b74 --- /dev/null +++ b/examples/peripherals/parlio/parlio_rx/logic_analyzer/main/idf_component.yml @@ -0,0 +1,3 @@ +dependencies: + protocol_examples_common: + path: ${IDF_PATH}/examples/common_components/protocol_examples_common diff --git a/examples/peripherals/parlio/parlio_rx/logic_analyzer/main/logic_analyzer_example_main.c b/examples/peripherals/parlio/parlio_rx/logic_analyzer/main/logic_analyzer_example_main.c new file mode 100644 index 000000000000..4f8602773930 --- /dev/null +++ b/examples/peripherals/parlio/parlio_rx/logic_analyzer/main/logic_analyzer_example_main.c @@ -0,0 +1,132 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: CC0-1.0 + */ + +#include +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "driver/gpio.h" +#include "esp_check.h" +#include "esp_probe.h" +#include "esp_probe_streams.h" + +// Alias of the Kconfig options +#if CONFIG_EXAMPLE_TCP_STREAM +#include "nvs_flash.h" +#include "protocol_examples_common.h" +#include "esp_event.h" + +#define EXAMPLE_HOST_IP_ADDR CONFIG_EXAMPLE_HOST_IP_ADDR // Host IP (string) +#define EXAMPLE_HOST_PORT CONFIG_EXAMPLE_HOST_PORT // Host port (int) +#elif CONFIG_EXAMPLE_FLASH_STREAM +#define EXAMPLE_MOUNT_POINT "/esp_probe" +#define EXAMPLE_DATA_FILE_PATH EXAMPLE_MOUNT_POINT"/probe_raw.dat" +#define EXAMPLE_PARTITION_LABEL CONFIG_EXAMPLE_PARTITION_LABEL // Flash partition label (string, see 'partitions.csv') +#endif + +#define EXAMPLE_SAMPLE_RATE_HZ (8 * 1000 * 1000) +#define EXAMPLE_STORAGE_DEPTH_KB 128 + +// GPIOs to probe +const static int s_probe_gpio[] = {2, 3, 4, 5}; +const static char *TAG = "example"; +static esp_probe_handle_t s_probe = NULL; + +#if CONFIG_EXAMPLE_INTERNAL_SIGNAL +void example_init_gpio_to_generate_internal_signal(void) +{ + gpio_config_t gpio_cfg = { + .pin_bit_mask = BIT(s_probe_gpio[0]) | + BIT(s_probe_gpio[1]) | + BIT(s_probe_gpio[2]) | + BIT(s_probe_gpio[3]), + .mode = GPIO_MODE_INPUT_OUTPUT, + }; + gpio_config(&gpio_cfg); +} +#endif + +void example_probe_function(void) +{ +#if CONFIG_EXAMPLE_INTERNAL_SIGNAL + // Simulate the internal signals + // Pulses might not spread averagely because the thread might be interrupted + for (int cnt = 0; cnt < 100; cnt++) { + for (int i = 0; i < 4; i++) { + gpio_set_level(s_probe_gpio[i], cnt & BIT(i)); + } + vTaskDelay(pdMS_TO_TICKS(1)); + } +#else // CONFIG_EXAMPLE_EXTERNAL_SIGNAL + // Probing the external signal here + vTaskDelay(pdMS_TO_TICKS(100)); +#endif // CONFIG_EXAMPLE_INTERNAL_SIGNAL +} + +FILE *example_probe_init(void) +{ + FILE *f = NULL; + // Create dump stream +#if CONFIG_EXAMPLE_TCP_STREAM + ESP_ERROR_CHECK(nvs_flash_init()); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + ESP_ERROR_CHECK(example_connect()); + f = esp_probe_open_tcp_stream(EXAMPLE_HOST_IP_ADDR, EXAMPLE_HOST_PORT); +#elif CONFIG_EXAMPLE_FLASH_STREAM + ESP_ERROR_CHECK(esp_probe_init_spiflash_fatfs(EXAMPLE_MOUNT_POINT, EXAMPLE_PARTITION_LABEL, NULL)); + f = esp_probe_open_file_stream(EXAMPLE_DATA_FILE_PATH); +#endif + assert(f); + + // Configure and allocate the ESP probe + esp_probe_config_t config = ESP_PROBE_DEFAULT_BUFFER_CONFIG(EXAMPLE_SAMPLE_RATE_HZ, EXAMPLE_STORAGE_DEPTH_KB); + // Set the GPIOs to be probed + memcpy(&config.probe_gpio, &s_probe_gpio, sizeof(s_probe_gpio)); + ESP_ERROR_CHECK(esp_new_probe(&config, &s_probe)); + return f; +} + +void example_probe_signals(FILE *f, void (*probe_func)(void)) +{ + uint32_t dump_data_size = 0; + // Probe the signals during the function, the data will be dumped via the out stream + ESP_ERROR_CHECK(esp_probe_start(s_probe, f)); + probe_func(); + ESP_ERROR_CHECK(esp_probe_stop(s_probe, &dump_data_size)); + ESP_LOGI(TAG, "Probe finished! %"PRIu32" (0x%"PRIx32") bytes dumped\n", dump_data_size, dump_data_size); +} + +void example_probe_deinit(FILE *f) +{ + // Delete the probe instance and free the resources + ESP_ERROR_CHECK(esp_del_probe(s_probe)); + s_probe = NULL; + + // Close the output stream +#if CONFIG_EXAMPLE_TCP_STREAM + esp_probe_close_tcp_stream(f); + example_disconnect(); +#elif CONFIG_EXAMPLE_FLASH_STREAM + esp_probe_close_file_stream(f); + esp_probe_deinit_spiflash_fatfs(EXAMPLE_PARTITION_LABEL); +#endif +} + +void app_main(void) +{ +#if CONFIG_EXAMPLE_INTERNAL_SIGNAL + // If choose to probe the internal signals via IO MUX, init GPIOs for simulating the internal signals + example_init_gpio_to_generate_internal_signal(); +#endif + // Initialize the probe, the probe needs an output stream to dump the raw data + FILE *f = example_probe_init(); + // Use the probe as decorator, probe the signals that generated during this function + example_probe_signals(f, example_probe_function); + // Deinitialize the probe, close the output stream + example_probe_deinit(f); +} diff --git a/examples/peripherals/parlio/parlio_rx/logic_analyzer/partitions.csv b/examples/peripherals/parlio/parlio_rx/logic_analyzer/partitions.csv new file mode 100644 index 000000000000..f8c91a89ce01 --- /dev/null +++ b/examples/peripherals/parlio/parlio_rx/logic_analyzer/partitions.csv @@ -0,0 +1,5 @@ +# Name, Type, SubType, Offset, Size, Flags +# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap +nvs, data, nvs, 0x9000, 0x6000, +factory, 0, 0, 0x10000, 1M, +storage, data, fat, , 528K, diff --git a/examples/peripherals/parlio/parlio_rx/logic_analyzer/sdkconfig.defaults b/examples/peripherals/parlio/parlio_rx/logic_analyzer/sdkconfig.defaults new file mode 100644 index 000000000000..c9861483a410 --- /dev/null +++ b/examples/peripherals/parlio/parlio_rx/logic_analyzer/sdkconfig.defaults @@ -0,0 +1,6 @@ +CONFIG_ESP_TASK_WDT_EN=n +CONFIG_FREERTOS_HZ=1000 +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_FATFS_LFN_STACK=y +CONFIG_VFS_SUPPORT_IO=y diff --git a/examples/peripherals/parlio/simple_rgb_led_matrix/CMakeLists.txt b/examples/peripherals/parlio/parlio_tx/simple_rgb_led_matrix/CMakeLists.txt similarity index 94% rename from examples/peripherals/parlio/simple_rgb_led_matrix/CMakeLists.txt rename to examples/peripherals/parlio/parlio_tx/simple_rgb_led_matrix/CMakeLists.txt index b7b9e298f5c0..943a2b7e0b56 100644 --- a/examples/peripherals/parlio/simple_rgb_led_matrix/CMakeLists.txt +++ b/examples/peripherals/parlio/parlio_tx/simple_rgb_led_matrix/CMakeLists.txt @@ -5,4 +5,6 @@ cmake_minimum_required(VERSION 3.16) include($ENV{IDF_PATH}/tools/cmake/project.cmake) +set(COMPONENTS main) + project(rgb_led_matrix) diff --git a/examples/peripherals/parlio/simple_rgb_led_matrix/README.md b/examples/peripherals/parlio/parlio_tx/simple_rgb_led_matrix/README.md similarity index 100% rename from examples/peripherals/parlio/simple_rgb_led_matrix/README.md rename to examples/peripherals/parlio/parlio_tx/simple_rgb_led_matrix/README.md diff --git a/examples/peripherals/parlio/simple_rgb_led_matrix/main/CMakeLists.txt b/examples/peripherals/parlio/parlio_tx/simple_rgb_led_matrix/main/CMakeLists.txt similarity index 56% rename from examples/peripherals/parlio/simple_rgb_led_matrix/main/CMakeLists.txt rename to examples/peripherals/parlio/parlio_tx/simple_rgb_led_matrix/main/CMakeLists.txt index d8e280c0faff..21935bb43dfd 100644 --- a/examples/peripherals/parlio/simple_rgb_led_matrix/main/CMakeLists.txt +++ b/examples/peripherals/parlio/parlio_tx/simple_rgb_led_matrix/main/CMakeLists.txt @@ -1,2 +1,3 @@ idf_component_register(SRCS "rgb_led_matrix_example_main.c" "lvgl_demo_ui.c" + PRIV_REQUIRES esp_driver_parlio esp_driver_gpio esp_driver_gptimer INCLUDE_DIRS ".") diff --git a/examples/peripherals/parlio/simple_rgb_led_matrix/main/idf_component.yml b/examples/peripherals/parlio/parlio_tx/simple_rgb_led_matrix/main/idf_component.yml similarity index 100% rename from examples/peripherals/parlio/simple_rgb_led_matrix/main/idf_component.yml rename to examples/peripherals/parlio/parlio_tx/simple_rgb_led_matrix/main/idf_component.yml diff --git a/examples/peripherals/parlio/simple_rgb_led_matrix/main/lvgl_demo_ui.c b/examples/peripherals/parlio/parlio_tx/simple_rgb_led_matrix/main/lvgl_demo_ui.c similarity index 100% rename from examples/peripherals/parlio/simple_rgb_led_matrix/main/lvgl_demo_ui.c rename to examples/peripherals/parlio/parlio_tx/simple_rgb_led_matrix/main/lvgl_demo_ui.c diff --git a/examples/peripherals/parlio/simple_rgb_led_matrix/main/rgb_led_matrix_example_main.c b/examples/peripherals/parlio/parlio_tx/simple_rgb_led_matrix/main/rgb_led_matrix_example_main.c similarity index 100% rename from examples/peripherals/parlio/simple_rgb_led_matrix/main/rgb_led_matrix_example_main.c rename to examples/peripherals/parlio/parlio_tx/simple_rgb_led_matrix/main/rgb_led_matrix_example_main.c diff --git a/examples/peripherals/parlio/simple_rgb_led_matrix/pytest_simple_rgb_led_matrix.py b/examples/peripherals/parlio/parlio_tx/simple_rgb_led_matrix/pytest_simple_rgb_led_matrix.py similarity index 100% rename from examples/peripherals/parlio/simple_rgb_led_matrix/pytest_simple_rgb_led_matrix.py rename to examples/peripherals/parlio/parlio_tx/simple_rgb_led_matrix/pytest_simple_rgb_led_matrix.py diff --git a/examples/peripherals/parlio/simple_rgb_led_matrix/sdkconfig.defaults b/examples/peripherals/parlio/parlio_tx/simple_rgb_led_matrix/sdkconfig.defaults similarity index 100% rename from examples/peripherals/parlio/simple_rgb_led_matrix/sdkconfig.defaults rename to examples/peripherals/parlio/parlio_tx/simple_rgb_led_matrix/sdkconfig.defaults diff --git a/examples/peripherals/pcnt/rotary_encoder/pytest_rotary_encoder.py b/examples/peripherals/pcnt/rotary_encoder/pytest_rotary_encoder.py index 990a6198c151..f774c175627d 100644 --- a/examples/peripherals/pcnt/rotary_encoder/pytest_rotary_encoder.py +++ b/examples/peripherals/pcnt/rotary_encoder/pytest_rotary_encoder.py @@ -10,6 +10,7 @@ @pytest.mark.esp32s3 @pytest.mark.esp32c6 @pytest.mark.esp32h2 +@pytest.mark.esp32p4 @pytest.mark.generic def test_rotary_encoder(dut: Dut) -> None: dut.expect_exact('install pcnt unit') diff --git a/examples/peripherals/rmt/dshot_esc/pytest_dshot_esc.py b/examples/peripherals/rmt/dshot_esc/pytest_dshot_esc.py index 5dce9212df94..26b863121778 100644 --- a/examples/peripherals/rmt/dshot_esc/pytest_dshot_esc.py +++ b/examples/peripherals/rmt/dshot_esc/pytest_dshot_esc.py @@ -11,6 +11,7 @@ @pytest.mark.esp32c3 @pytest.mark.esp32c6 @pytest.mark.esp32h2 +@pytest.mark.esp32p4 @pytest.mark.generic def test_dshot_esc_example(dut: Dut) -> None: dut.expect_exact('example: Create RMT TX channel') diff --git a/examples/peripherals/rmt/led_strip/pytest_led_strip.py b/examples/peripherals/rmt/led_strip/pytest_led_strip.py index 9ba19a35f2ca..afafbe5d2b24 100644 --- a/examples/peripherals/rmt/led_strip/pytest_led_strip.py +++ b/examples/peripherals/rmt/led_strip/pytest_led_strip.py @@ -11,6 +11,7 @@ @pytest.mark.esp32c3 @pytest.mark.esp32c6 @pytest.mark.esp32h2 +@pytest.mark.esp32p4 @pytest.mark.generic def test_led_strip_example(dut: Dut) -> None: dut.expect_exact('example: Create RMT TX channel') diff --git a/examples/peripherals/rmt/musical_buzzer/pytest_musical_buzzer.py b/examples/peripherals/rmt/musical_buzzer/pytest_musical_buzzer.py index 2f7d96c46d02..ce347210adb4 100644 --- a/examples/peripherals/rmt/musical_buzzer/pytest_musical_buzzer.py +++ b/examples/peripherals/rmt/musical_buzzer/pytest_musical_buzzer.py @@ -10,6 +10,7 @@ @pytest.mark.esp32c3 @pytest.mark.esp32c6 @pytest.mark.esp32h2 +@pytest.mark.esp32p4 @pytest.mark.generic def test_musical_buzzer_example(dut: Dut) -> None: dut.expect_exact('example: Create RMT TX channel') diff --git a/examples/peripherals/rmt/onewire/pytest_onewire.py b/examples/peripherals/rmt/onewire/pytest_onewire.py index fc7c045a6b34..2a6a72989814 100644 --- a/examples/peripherals/rmt/onewire/pytest_onewire.py +++ b/examples/peripherals/rmt/onewire/pytest_onewire.py @@ -10,6 +10,7 @@ @pytest.mark.esp32c3 @pytest.mark.esp32c6 @pytest.mark.esp32h2 +@pytest.mark.esp32p4 @pytest.mark.generic def test_onewire_example(dut: Dut) -> None: dut.expect_exact('example: 1-Wire bus installed on GPIO') diff --git a/examples/peripherals/rmt/stepper_motor/pytest_stepper_motor.py b/examples/peripherals/rmt/stepper_motor/pytest_stepper_motor.py index f2fba2b8ce77..fdd2629cc542 100644 --- a/examples/peripherals/rmt/stepper_motor/pytest_stepper_motor.py +++ b/examples/peripherals/rmt/stepper_motor/pytest_stepper_motor.py @@ -8,6 +8,7 @@ @pytest.mark.esp32s3 @pytest.mark.esp32c6 @pytest.mark.esp32h2 +@pytest.mark.esp32p4 @pytest.mark.generic def test_stepper_motor_example(dut: Dut) -> None: dut.expect_exact('example: Initialize EN + DIR GPIO') diff --git a/examples/peripherals/sigma_delta/sdm_dac/pytest_sdm_dac_example.py b/examples/peripherals/sigma_delta/sdm_dac/pytest_sdm_dac_example.py index 48e3c464859a..3fc75653915d 100644 --- a/examples/peripherals/sigma_delta/sdm_dac/pytest_sdm_dac_example.py +++ b/examples/peripherals/sigma_delta/sdm_dac/pytest_sdm_dac_example.py @@ -11,6 +11,7 @@ @pytest.mark.esp32c3 @pytest.mark.esp32c6 @pytest.mark.esp32h2 +@pytest.mark.esp32p4 @pytest.mark.generic def test_sdm_dac_example(dut: Dut) -> None: dut.expect(r'sdm_dac: Sigma-delta output is attached to GPIO \w+') diff --git a/examples/peripherals/sigma_delta/sdm_led/pytest_sdm_led_example.py b/examples/peripherals/sigma_delta/sdm_led/pytest_sdm_led_example.py index 3167fcf73da1..8e53f028611f 100644 --- a/examples/peripherals/sigma_delta/sdm_led/pytest_sdm_led_example.py +++ b/examples/peripherals/sigma_delta/sdm_led/pytest_sdm_led_example.py @@ -11,6 +11,7 @@ @pytest.mark.esp32c3 @pytest.mark.esp32c6 @pytest.mark.esp32h2 +@pytest.mark.esp32p4 @pytest.mark.generic def test_sdm_led_example(dut: Dut) -> None: dut.expect_exact('sdm_led: Install sigma delta channel') diff --git a/examples/peripherals/temperature_sensor/temp_sensor/pytest_temp_sensor_example.py b/examples/peripherals/temperature_sensor/temp_sensor/pytest_temp_sensor_example.py index 631634749bd9..04b13725704b 100644 --- a/examples/peripherals/temperature_sensor/temp_sensor/pytest_temp_sensor_example.py +++ b/examples/peripherals/temperature_sensor/temp_sensor/pytest_temp_sensor_example.py @@ -11,6 +11,7 @@ @pytest.mark.esp32c2 @pytest.mark.esp32c6 @pytest.mark.esp32h2 +@pytest.mark.esp32p4 @pytest.mark.generic def test_temp_sensor_example(dut: Dut) -> None: dut.expect_exact('Install temperature sensor') diff --git a/examples/peripherals/temperature_sensor/temp_sensor_monitor/pytest_temp_sensor_monitor_example.py b/examples/peripherals/temperature_sensor/temp_sensor_monitor/pytest_temp_sensor_monitor_example.py index 7ac06afa0e4b..e952831878b4 100644 --- a/examples/peripherals/temperature_sensor/temp_sensor_monitor/pytest_temp_sensor_monitor_example.py +++ b/examples/peripherals/temperature_sensor/temp_sensor_monitor/pytest_temp_sensor_monitor_example.py @@ -7,6 +7,7 @@ @pytest.mark.esp32c6 @pytest.mark.esp32h2 +@pytest.mark.esp32p4 @pytest.mark.generic def test_temp_sensor_monitor_example(dut: Dut) -> None: dut.expect_exact('Install temperature sensor') diff --git a/examples/peripherals/timer_group/gptimer_capture_hc_sr04/pytest_gptimer_capture_example.py b/examples/peripherals/timer_group/gptimer_capture_hc_sr04/pytest_gptimer_capture_example.py index fb5881052843..809c04f33616 100644 --- a/examples/peripherals/timer_group/gptimer_capture_hc_sr04/pytest_gptimer_capture_example.py +++ b/examples/peripherals/timer_group/gptimer_capture_hc_sr04/pytest_gptimer_capture_example.py @@ -7,6 +7,7 @@ @pytest.mark.esp32c6 @pytest.mark.esp32h2 +@pytest.mark.esp32p4 @pytest.mark.generic def test_gptimer_capture(dut: Dut) -> None: dut.expect_exact('Configure trig gpio') diff --git a/examples/peripherals/usb/host/cdc/cdc_acm_vcp/main/CMakeLists.txt b/examples/peripherals/usb/host/cdc/cdc_acm_vcp/main/CMakeLists.txt index e52dfe2ba87a..477ba42e45ea 100644 --- a/examples/peripherals/usb/host/cdc/cdc_acm_vcp/main/CMakeLists.txt +++ b/examples/peripherals/usb/host/cdc/cdc_acm_vcp/main/CMakeLists.txt @@ -3,3 +3,5 @@ idf_component_register( INCLUDE_DIRS "." PRIV_REQUIRES usb ) + +target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-missing-field-initializers") diff --git a/examples/peripherals/usb/host/usb_host_lib/main/usb_host_lib_main.c b/examples/peripherals/usb/host/usb_host_lib/main/usb_host_lib_main.c index db41bd326578..e6c2a8df92dd 100644 --- a/examples/peripherals/usb/host/usb_host_lib/main/usb_host_lib_main.c +++ b/examples/peripherals/usb/host/usb_host_lib/main/usb_host_lib_main.c @@ -17,6 +17,10 @@ #define CLASS_TASK_PRIORITY 3 #define APP_QUIT_PIN CONFIG_APP_QUIT_PIN +#ifdef CONFIG_USB_HOST_ENABLE_ENUM_FILTER_CALLBACK +#define ENABLE_ENUM_FILTER_CALLBACK +#endif // CONFIG_USB_HOST_ENABLE_ENUM_FILTER_CALLBACK + extern void class_driver_task(void *arg); extern void class_driver_client_deregister(void); @@ -66,6 +70,35 @@ static void gpio_cb(void *arg) } } +/** + * @brief Set configuration callback + * + * Set the USB device configuration during the enumeration process, must be enabled in the menuconfig + + * @note bConfigurationValue starts at index 1 + * + * @param[in] dev_desc device descriptor of the USB device currently being enumerated + * @param[out] bConfigurationValue configuration descriptor index, that will be user for enumeration + * + * @return bool + * - true: USB device will be enumerated + * - false: USB device will not be enumerated + */ +#ifdef ENABLE_ENUM_FILTER_CALLBACK +static bool set_config_cb(const usb_device_desc_t *dev_desc, uint8_t *bConfigurationValue) +{ + // If the USB device has more than one configuration, set the second configuration + if (dev_desc->bNumConfigurations > 1) { + *bConfigurationValue = 2; + } else { + *bConfigurationValue = 1; + } + + // Return true to enumerate the USB device + return true; +} +#endif // ENABLE_ENUM_FILTER_CALLBACK + /** * @brief Start USB Host install and handle common USB host library events while app pin not low * @@ -77,6 +110,9 @@ static void usb_host_lib_task(void *arg) usb_host_config_t host_config = { .skip_phy_setup = false, .intr_flags = ESP_INTR_FLAG_LEVEL1, +# ifdef ENABLE_ENUM_FILTER_CALLBACK + .enum_filter_cb = set_config_cb, +# endif // ENABLE_ENUM_FILTER_CALLBACK }; ESP_ERROR_CHECK(usb_host_install(&host_config)); diff --git a/examples/protocols/modbus/serial/mb_slave/main/slave.c b/examples/protocols/modbus/serial/mb_slave/main/slave.c index b25d482ae87c..db5c29784dac 100644 --- a/examples/protocols/modbus/serial/mb_slave/main/slave.c +++ b/examples/protocols/modbus/serial/mb_slave/main/slave.c @@ -175,13 +175,12 @@ void app_main(void) // incremented each access cycle reaches the CHAN_DATA_MAX_VAL value. for(;holding_reg_params.holding_data0 < MB_CHAN_DATA_MAX_VAL;) { // Check for read/write events of Modbus master for certain events - mb_event_group_t event = mbc_slave_check_event(MB_READ_WRITE_MASK); - const char* rw_str = (event & MB_READ_MASK) ? "READ" : "WRITE"; - + (void)mbc_slave_check_event(MB_READ_WRITE_MASK); + ESP_ERROR_CHECK_WITHOUT_ABORT(mbc_slave_get_param_info(®_info, MB_PAR_INFO_GET_TOUT)); + const char* rw_str = (reg_info.type & MB_READ_MASK) ? "READ" : "WRITE"; // Filter events and process them accordingly - if(event & (MB_EVENT_HOLDING_REG_WR | MB_EVENT_HOLDING_REG_RD)) { + if(reg_info.type & (MB_EVENT_HOLDING_REG_WR | MB_EVENT_HOLDING_REG_RD)) { // Get parameter information from parameter queue - ESP_ERROR_CHECK(mbc_slave_get_param_info(®_info, MB_PAR_INFO_GET_TOUT)); ESP_LOGI(TAG, "HOLDING %s (%" PRIu32 " us), ADDR:%u, TYPE:%u, INST_ADDR:0x%" PRIx32 ", SIZE:%u", rw_str, reg_info.time_stamp, @@ -198,24 +197,21 @@ void app_main(void) } portEXIT_CRITICAL(¶m_lock); } - } else if (event & MB_EVENT_INPUT_REG_RD) { - ESP_ERROR_CHECK(mbc_slave_get_param_info(®_info, MB_PAR_INFO_GET_TOUT)); + } else if (reg_info.type & MB_EVENT_INPUT_REG_RD) { ESP_LOGI(TAG, "INPUT READ (%" PRIu32 " us), ADDR:%u, TYPE:%u, INST_ADDR:0x%" PRIx32 ", SIZE:%u", reg_info.time_stamp, (unsigned)reg_info.mb_offset, (unsigned)reg_info.type, (uint32_t)reg_info.address, (unsigned)reg_info.size); - } else if (event & MB_EVENT_DISCRETE_RD) { - ESP_ERROR_CHECK(mbc_slave_get_param_info(®_info, MB_PAR_INFO_GET_TOUT)); + } else if (reg_info.type & MB_EVENT_DISCRETE_RD) { ESP_LOGI(TAG, "DISCRETE READ (%" PRIu32 " us): ADDR:%u, TYPE:%u, INST_ADDR:0x%" PRIx32 ", SIZE:%u", reg_info.time_stamp, (unsigned)reg_info.mb_offset, (unsigned)reg_info.type, (uint32_t)reg_info.address, (unsigned)reg_info.size); - } else if (event & (MB_EVENT_COILS_RD | MB_EVENT_COILS_WR)) { - ESP_ERROR_CHECK(mbc_slave_get_param_info(®_info, MB_PAR_INFO_GET_TOUT)); + } else if (reg_info.type & (MB_EVENT_COILS_RD | MB_EVENT_COILS_WR)) { ESP_LOGI(TAG, "COILS %s (%" PRIu32 " us), ADDR:%u, TYPE:%u, INST_ADDR:0x%" PRIx32 ", SIZE:%u", rw_str, reg_info.time_stamp, diff --git a/examples/protocols/modbus/tcp/mb_tcp_slave/main/tcp_slave.c b/examples/protocols/modbus/tcp/mb_tcp_slave/main/tcp_slave.c index b2a95e999912..ecdb78135903 100644 --- a/examples/protocols/modbus/tcp/mb_tcp_slave/main/tcp_slave.c +++ b/examples/protocols/modbus/tcp/mb_tcp_slave/main/tcp_slave.c @@ -169,12 +169,12 @@ static void slave_operation_func(void *arg) // incremented each access cycle reaches the CHAN_DATA_MAX_VAL value. for(;holding_reg_params.holding_data0 < MB_CHAN_DATA_MAX_VAL;) { // Check for read/write events of Modbus master for certain events - mb_event_group_t event = mbc_slave_check_event(MB_READ_WRITE_MASK); - const char* rw_str = (event & MB_READ_MASK) ? "READ" : "WRITE"; + (void)mbc_slave_check_event(MB_READ_WRITE_MASK); + ESP_ERROR_CHECK_WITHOUT_ABORT(mbc_slave_get_param_info(®_info, MB_PAR_INFO_GET_TOUT)); + const char* rw_str = (reg_info.type & MB_READ_MASK) ? "READ" : "WRITE"; // Filter events and process them accordingly - if(event & (MB_EVENT_HOLDING_REG_WR | MB_EVENT_HOLDING_REG_RD)) { + if(reg_info.type & (MB_EVENT_HOLDING_REG_WR | MB_EVENT_HOLDING_REG_RD)) { // Get parameter information from parameter queue - ESP_ERROR_CHECK(mbc_slave_get_param_info(®_info, MB_PAR_INFO_GET_TOUT)); ESP_LOGI(TAG, "HOLDING %s (%" PRIu32 " us), ADDR:%u, TYPE:%u, INST_ADDR:0x%" PRIx32 ", SIZE:%u", rw_str, reg_info.time_stamp, @@ -191,24 +191,21 @@ static void slave_operation_func(void *arg) } portEXIT_CRITICAL(¶m_lock); } - } else if (event & MB_EVENT_INPUT_REG_RD) { - ESP_ERROR_CHECK(mbc_slave_get_param_info(®_info, MB_PAR_INFO_GET_TOUT)); + } else if (reg_info.type & MB_EVENT_INPUT_REG_RD) { ESP_LOGI(TAG, "INPUT READ (%" PRIu32 " us), ADDR:%u, TYPE:%u, INST_ADDR:0x%" PRIx32 ", SIZE:%u", reg_info.time_stamp, (unsigned)reg_info.mb_offset, (unsigned)reg_info.type, (uint32_t)reg_info.address, (unsigned)reg_info.size); - } else if (event & MB_EVENT_DISCRETE_RD) { - ESP_ERROR_CHECK(mbc_slave_get_param_info(®_info, MB_PAR_INFO_GET_TOUT)); + } else if (reg_info.type & MB_EVENT_DISCRETE_RD) { ESP_LOGI(TAG, "DISCRETE READ (%" PRIu32 " us), ADDR:%u, TYPE:%u, INST_ADDR:0x%" PRIx32 ", SIZE:%u", reg_info.time_stamp, (unsigned)reg_info.mb_offset, (unsigned)reg_info.type, (uint32_t)reg_info.address, (unsigned)reg_info.size); - } else if (event & (MB_EVENT_COILS_RD | MB_EVENT_COILS_WR)) { - ESP_ERROR_CHECK(mbc_slave_get_param_info(®_info, MB_PAR_INFO_GET_TOUT)); + } else if (reg_info.type & (MB_EVENT_COILS_RD | MB_EVENT_COILS_WR)) { ESP_LOGI(TAG, "COILS %s (%" PRIu32 " us), ADDR:%u, TYPE:%u, INST_ADDR:0x%" PRIx32 ", SIZE:%u", rw_str, reg_info.time_stamp, diff --git a/examples/system/.build-test-rules.yml b/examples/system/.build-test-rules.yml index 4e89f045e8a8..9bc604cda2f7 100644 --- a/examples/system/.build-test-rules.yml +++ b/examples/system/.build-test-rules.yml @@ -2,9 +2,9 @@ examples/system/app_trace_basic: disable: - - if: IDF_TARGET == "esp32c6" or IDF_TARGET == "esp32h2" + - if: IDF_TARGET in ["esp32c6", "esp32h2", "esp32p4"] temporary: true - reason: target esp32c6, esp32h2 is not supported yet + reason: target esp32c6, esp32h2, esp32p4 is not supported yet examples/system/base_mac_address: depends_components: @@ -212,6 +212,12 @@ examples/system/select: depends_components: - vfs +examples/system/startup_time: + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: test not pass, should be re-enable # TODO: IDF-8989 + examples/system/sysview_tracing: disable: - if: SOC_GPTIMER_SUPPORTED != 1 diff --git a/examples/system/app_trace_basic/README.md b/examples/system/app_trace_basic/README.md index fa3a2c6b01f2..2da31cd059a6 100644 --- a/examples/system/app_trace_basic/README.md +++ b/examples/system/app_trace_basic/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | # Application Level Tracing Example (Basic) diff --git a/examples/system/esp_timer/pytest_esp_timer.py b/examples/system/esp_timer/pytest_esp_timer.py index 74e5fe5e412d..94b63a40c7a3 100644 --- a/examples/system/esp_timer/pytest_esp_timer.py +++ b/examples/system/esp_timer/pytest_esp_timer.py @@ -29,7 +29,7 @@ @pytest.mark.supported_targets -@pytest.mark.temp_skip_ci(targets=['esp32c6', 'esp32h2'], reason='c6/h2 support TBD') +@pytest.mark.temp_skip_ci(targets=['esp32c6', 'esp32h2', 'esp32p4'], reason='c6/h2/p4 support TBD') # TODO: IDF-8979 @pytest.mark.generic @pytest.mark.parametrize( 'config', diff --git a/examples/system/light_sleep/pytest_light_sleep.py b/examples/system/light_sleep/pytest_light_sleep.py index aee220741f87..5fa4b4514f62 100644 --- a/examples/system/light_sleep/pytest_light_sleep.py +++ b/examples/system/light_sleep/pytest_light_sleep.py @@ -8,6 +8,7 @@ from pytest_embedded import Dut +@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='esp32p4 support TBD') @pytest.mark.supported_targets @pytest.mark.generic def test_light_sleep(dut: Dut) -> None: diff --git a/examples/system/startup_time/pytest_startup_time.py b/examples/system/startup_time/pytest_startup_time.py index a2eff33822ce..4dbfe7b6fb18 100644 --- a/examples/system/startup_time/pytest_startup_time.py +++ b/examples/system/startup_time/pytest_startup_time.py @@ -6,6 +6,7 @@ from pytest_embedded import Dut +@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='esp32p4 support TBD') # TODO: IDF-8989 @pytest.mark.supported_targets @pytest.mark.generic @pytest.mark.parametrize('config', [ diff --git a/tools/ci/idf_pytest/constants.py b/tools/ci/idf_pytest/constants.py index a933333adc9d..a56cedc2dd7a 100644 --- a/tools/ci/idf_pytest/constants.py +++ b/tools/ci/idf_pytest/constants.py @@ -11,7 +11,7 @@ from _pytest.python import Function from pytest_embedded.utils import to_list -SUPPORTED_TARGETS = ['esp32', 'esp32s2', 'esp32c3', 'esp32s3', 'esp32c2', 'esp32c6', 'esp32h2'] +SUPPORTED_TARGETS = ['esp32', 'esp32s2', 'esp32c3', 'esp32s3', 'esp32c2', 'esp32c6', 'esp32h2', 'esp32p4'] PREVIEW_TARGETS: t.List[str] = [] # this PREVIEW_TARGETS excludes 'linux' target DEFAULT_SDKCONFIG = 'default' diff --git a/tools/test_apps/.build-test-rules.yml b/tools/test_apps/.build-test-rules.yml index 1d1eb33bac2e..47177fff01fe 100644 --- a/tools/test_apps/.build-test-rules.yml +++ b/tools/test_apps/.build-test-rules.yml @@ -135,6 +135,12 @@ tools/test_apps/system/eh_frame: temporary: true reason: the other targets are not tested yet +tools/test_apps/system/esp_intr_dump: + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: test not pass, should be re-enable # TODO: IDF-8991 + tools/test_apps/system/g0_components: enable: - if: INCLUDE_DEFAULT == 1 or IDF_TARGET in ["esp32p4", "esp32c5"] # preview targets @@ -185,6 +191,11 @@ tools/test_apps/system/panic: temporary: true reason: target(s) not supported yet # TODO: IDF-7511 +tools/test_apps/system/ram_loadable_app: + disable_test: + - if: IDF_TARGET in ["esp32p4"] + temporary: true + reason: TBD # TODO: IDF-8994 tools/test_apps/system/startup: disable: - if: CONFIG_NAME == "main_task_cpu1" and IDF_TARGET not in ["esp32", "esp32s3"] diff --git a/tools/test_apps/peripherals/i2c_wifi/pytest_i2c_wifi.py b/tools/test_apps/peripherals/i2c_wifi/pytest_i2c_wifi.py index 2dd9b5e2e375..cbb456562a81 100644 --- a/tools/test_apps/peripherals/i2c_wifi/pytest_i2c_wifi.py +++ b/tools/test_apps/peripherals/i2c_wifi/pytest_i2c_wifi.py @@ -6,7 +6,7 @@ @pytest.mark.supported_targets -@pytest.mark.temp_skip_ci(targets=['esp32h2'], reason='h2 does not support wifi') +@pytest.mark.temp_skip_ci(targets=['esp32h2', 'esp32p4'], reason='h2/p4 does not support wifi') @pytest.mark.generic def test_i2c_wifi_startup(dut: IdfDut) -> None: dut.expect_exact('I2C-WIFI test success') diff --git a/tools/test_apps/phy/phy_multi_init_data_test/pytest_phy_multi_init_data.py b/tools/test_apps/phy/phy_multi_init_data_test/pytest_phy_multi_init_data.py index acde0b79c65b..14c1a8fab338 100644 --- a/tools/test_apps/phy/phy_multi_init_data_test/pytest_phy_multi_init_data.py +++ b/tools/test_apps/phy/phy_multi_init_data_test/pytest_phy_multi_init_data.py @@ -6,7 +6,7 @@ @pytest.mark.supported_targets -@pytest.mark.temp_skip_ci(targets=['esp32h2'], reason='h2 not supported') +@pytest.mark.temp_skip_ci(targets=['esp32h2', 'esp32p4'], reason='h2/p4 not supported') # TODO: IDF-8990 @pytest.mark.generic @pytest.mark.parametrize('config', [ 'phy_multiple_init_data', diff --git a/tools/test_apps/system/esp_intr_dump/pytest_esp_intr_dump.py b/tools/test_apps/system/esp_intr_dump/pytest_esp_intr_dump.py index 2b807d80d2cb..aafb4775b635 100644 --- a/tools/test_apps/system/esp_intr_dump/pytest_esp_intr_dump.py +++ b/tools/test_apps/system/esp_intr_dump/pytest_esp_intr_dump.py @@ -45,6 +45,7 @@ def test_esp_intr_dump_shared(dut: Dut) -> None: dut.expect_exact(PROMPT) +@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='esp32p4 support TBD') # TODO: IDF-8991 @pytest.mark.supported_targets @pytest.mark.generic def test_esp_intr_dump_expected_output(dut: Dut) -> None: diff --git a/tools/test_apps/system/gdbstub_runtime/pytest_runtime.py b/tools/test_apps/system/gdbstub_runtime/pytest_runtime.py index fbf3fc66545a..b97fdc3b71fc 100644 --- a/tools/test_apps/system/gdbstub_runtime/pytest_runtime.py +++ b/tools/test_apps/system/gdbstub_runtime/pytest_runtime.py @@ -19,6 +19,7 @@ def get_line_number(lookup: str, offset: int = 0) -> int: return -1 +@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='esp32p4 support TBD') # TODO: IDF-8992 @pytest.mark.supported_targets @pytest.mark.generic def test_gdbstub_runtime(dut: PanicTestDut) -> None: diff --git a/tools/test_apps/system/ram_loadable_app/pytest_ram_loadable_app.py b/tools/test_apps/system/ram_loadable_app/pytest_ram_loadable_app.py index 22b6011a38e6..fa770a4c3fd2 100644 --- a/tools/test_apps/system/ram_loadable_app/pytest_ram_loadable_app.py +++ b/tools/test_apps/system/ram_loadable_app/pytest_ram_loadable_app.py @@ -5,6 +5,7 @@ from pytest_embedded_idf.dut import IdfDut +@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='esp32p4 support TBD') # TODO: IDF-8994 @pytest.mark.supported_targets @pytest.mark.generic @pytest.mark.parametrize('config', ['pure_ram',], indirect=True,) @@ -13,6 +14,7 @@ def test_pure_ram_loadable_app(dut: IdfDut) -> None: dut.expect('Time since boot: 3 seconds...', timeout=10) +@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='esp32p4 support TBD') # TODO: IDF-8994 @pytest.mark.supported_targets @pytest.mark.generic @pytest.mark.parametrize('config', ['defaults',], indirect=True,)