diff --git a/README.md b/README.md index 02de8391ebe..29dbf8e2f70 100644 --- a/README.md +++ b/README.md @@ -16,8 +16,9 @@ Bare-metal (`no_std`) hardware abstraction layer for Espressif devices. Currently supports the following devices: - ESP32 Series: _ESP32_ -- ESP32-C Series: _ESP32-C2, ESP32-C3, ESP32-C6_ +- ESP32-C Series: _ESP32-C2, ESP32-C3, ESP32-C5, ESP32-C6, ESP32-C61_ - ESP32-H Series: _ESP32-H2_ +- ESP32-P Series: _ESP32-P4_ - ESP32-S Series: _ESP32-S2, ESP32-S3_ Additionally provides support for programming the low-power RISC-V cores found on the _ESP32-C6_, _ESP32-S2_, and _ESP32-S3_ via the [esp-lp-hal] package. diff --git a/esp-backtrace/CHANGELOG.md b/esp-backtrace/CHANGELOG.md index c81eb6aa5cb..80f03cc9c91 100644 --- a/esp-backtrace/CHANGELOG.md +++ b/esp-backtrace/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Initial ESP32-P4 (chip revision v3.0+) support (#5400) ### Changed diff --git a/esp-backtrace/Cargo.toml b/esp-backtrace/Cargo.toml index 77f5e6d1e67..8c5aebcb9cf 100644 --- a/esp-backtrace/Cargo.toml +++ b/esp-backtrace/Cargo.toml @@ -61,6 +61,7 @@ esp32c5 = ["esp-println?/esp32c5", "esp-metadata-generated/esp32c5"] esp32c6 = ["esp-println?/esp32c6", "esp-metadata-generated/esp32c6"] esp32c61 = ["esp-println?/esp32c61", "esp-metadata-generated/esp32c61"] esp32h2 = ["esp-println?/esp32h2", "esp-metadata-generated/esp32h2"] +esp32p4 = ["esp-println?/esp32p4", "esp-metadata-generated/esp32p4"] esp32s2 = ["esp-println?/esp32s2", "esp-metadata-generated/esp32s2", "semihosting?/openocd-semihosting"] esp32s3 = ["esp-println?/esp32s3", "esp-metadata-generated/esp32s3", "semihosting?/openocd-semihosting", "print-float-registers"] diff --git a/esp-bootloader-esp-idf/CHANGELOG.md b/esp-bootloader-esp-idf/CHANGELOG.md index 3600f31d246..f631aec2c28 100644 --- a/esp-bootloader-esp-idf/CHANGELOG.md +++ b/esp-bootloader-esp-idf/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- ESP32-P4: Use ROM CRC32 / MD5 functions instead of the software fallback (#5400) ### Fixed diff --git a/esp-bootloader-esp-idf/Cargo.toml b/esp-bootloader-esp-idf/Cargo.toml index 33cd06c8a49..f4a98750336 100644 --- a/esp-bootloader-esp-idf/Cargo.toml +++ b/esp-bootloader-esp-idf/Cargo.toml @@ -83,6 +83,8 @@ esp32c61 = ["esp-rom-sys/esp32c61", "esp-metadata-generated/esp32c61", "esp-ha ## esp32h2 = ["esp-rom-sys/esp32h2", "esp-metadata-generated/esp32h2", "esp-hal/esp32h2"] ## +esp32p4 = ["esp-rom-sys/esp32p4", "esp-metadata-generated/esp32p4", "esp-hal/esp32p4"] +## esp32 = ["esp-rom-sys/esp32", "esp-metadata-generated/esp32", "esp-hal/esp32"] ## esp32s2 = ["esp-rom-sys/esp32s2", "esp-metadata-generated/esp32s2", "esp-hal/esp32s2"] diff --git a/esp-bootloader-esp-idf/src/partitions.rs b/esp-bootloader-esp-idf/src/partitions.rs index 810c806302f..913cc217aef 100644 --- a/esp-bootloader-esp-idf/src/partitions.rs +++ b/esp-bootloader-esp-idf/src/partitions.rs @@ -336,6 +336,13 @@ impl<'a> PartitionTable<'a> { let paddr = unsafe { ((0x600c5000 as *const u32).read_volatile() & 0xff) << 16 }; + } else if #[cfg(feature = "esp32p4")] { + // DR_REG_FLASH_SPI0_BASE : 0x5008C000 = DR_REG_HPPERIPH0_BASE + 0x8C000 + // TODO: verify MSPI register for partition physical address read + let paddr = unsafe { + ((0x5008C000 + 0x380) as *mut u32).write_volatile(0); // SPI_MEM_C_MMU_ITEM_INDEX_REG + (((0x5008C000 + 0x37c) as *const u32).read_volatile() & 0xff) << 16 // SPI_MEM_C_MMU_ITEM_CONTENT_REG + }; } else if #[cfg(any(feature = "esp32c5", feature = "esp32c6", feature = "esp32c61", feature = "esp32h2"))] { let paddr = unsafe { ((0x60002000 + 0x380) as *mut u32).write_volatile(0); diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index 5660742d6a2..902605877dd 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -12,6 +12,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - C5 and C61: Enable RTC timekeeping (#5449) - C61: usb-serial-jtag and debug-assist (#5427) - C61: dedicated gpio (#5426) +- Initial ESP32-P4 (chip revision v3.0+) support (#5400) +- P4: Initial peripheral support for GPIO, UART, I2C, SPI, DMA, USB Serial/JTAG, eFuse, SYSTIMER (#5400) +- P4: AP-HEX PSRAM driver stub with configurable HP L2MEM cache/RAM split via `ESP_HAL_CONFIG_L2_CACHE_SIZE` (#5400) ### Changed diff --git a/esp-hal/Cargo.toml b/esp-hal/Cargo.toml index 5c75ae1dad4..3917c20535c 100644 --- a/esp-hal/Cargo.toml +++ b/esp-hal/Cargo.toml @@ -111,6 +111,10 @@ esp32c61 = { version = "0.3", features = ["critical-section", "rt"], optional = esp32h2 = { version = "0.19", features = ["critical-section", "rt"], optional = true } esp32s2 = { version = "0.31", features = ["critical-section", "rt"], optional = true } esp32s3 = { version = "0.35", features = ["critical-section", "rt"], optional = true } +# ESP32-P4 PAC: use git rev fc3e6d4 (matching firmware consumers) -- the +# crates.io release of esp32p4 0.2 doesn't match this revision's generated +# register layout, so we intentionally stick with the git dep here. +esp32p4 = { version = "0.2", features = ["critical-section", "rt"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "fc3e6d4" } [target.'cfg(target_arch = "riscv32")'.dependencies] riscv = { version = "0.15.0" } @@ -154,6 +158,7 @@ rt = [ "esp32c2?/rt", "esp32c3?/rt", "esp32c6?/rt", + "esp32p4?/rt", "esp32h2?/rt", "esp32s2?/rt", "esp32s3?/rt", @@ -231,6 +236,20 @@ esp32c6 = [ "esp-sync/esp32c6", "esp-metadata-generated/esp32c6", ] +## ESP32-P4 (chip revision v3.x / eco5 only, RISC-V dual-core HP + LP core) +## NOTE: This targets P4X (ESP32-P4NRW16X/32X) with chip revision >= v3.0. +## NRND variants (without X suffix) are NOT supported. +## Based on TRM v0.5 (Pre-release) and Chip Revision v3.x User Guide v1.0. +esp32p4 = [ + "dep:esp32p4", + "esp-riscv-rt/rtc-ram", + "esp-riscv-rt/clic-48", + "procmacros/rtc-fast", + "procmacros/has-lp-core", + "esp-rom-sys/esp32p4", + "esp-sync/esp32p4", + "esp-metadata-generated/esp32p4", +] ## esp32c61 = [ "dep:esp32c61", diff --git a/esp-hal/README.md b/esp-hal/README.md index 0dd435d7ec4..d5c79d30d34 100644 --- a/esp-hal/README.md +++ b/esp-hal/README.md @@ -30,6 +30,7 @@ For help getting started with this HAL, please refer to [The Rust on ESP Book] a | ESP32-C6 | [ESP32-C6][c6-datasheet] | [ESP32-C6][c6-trm] | `riscv32imac-unknown-none-elf` | | ESP32-C61| [ESP32-C61][c61-datasheet] | [ESP32-C61][c61-trm] | `riscv32imac-unknown-none-elf` | | ESP32-H2 | [ESP32-H2][h2-datasheet] | [ESP32-H2][h2-trm] | `riscv32imac-unknown-none-elf` | +| ESP32-P4 | [ESP32-P4][p4-datasheet] | [ESP32-P4][p4-trm] | `riscv32imafc-unknown-none-elf`| | ESP32-S2 | [ESP32-S2][s2-datasheet] | [ESP32-S2][s2-trm] | `xtensa-esp32s2-none-elf` | | ESP32-S3 | [ESP32-S3][s3-datasheet] | [ESP32-S3][s3-trm] | `xtensa-esp32s3-none-elf` | @@ -40,6 +41,7 @@ For help getting started with this HAL, please refer to [The Rust on ESP Book] a [c6-datasheet]: https://www.espressif.com/sites/default/files/documentation/esp32-c6_datasheet_en.pdf [c61-datasheet]: https://www.espressif.com/sites/default/files/documentation/esp32-c61_datasheet_en.pdf [h2-datasheet]: https://www.espressif.com/sites/default/files/documentation/esp32-h2_datasheet_en.pdf +[p4-datasheet]: https://www.espressif.com/sites/default/files/documentation/esp32-p4_datasheet_en.pdf [s2-datasheet]: https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf [s3-datasheet]: https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf [32-trm]: https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf @@ -49,6 +51,7 @@ For help getting started with this HAL, please refer to [The Rust on ESP Book] a [c6-trm]: https://www.espressif.com/sites/default/files/documentation/esp32-c6_technical_reference_manual_en.pdf [c61-trm]: https://www.espressif.com/sites/default/files/documentation/esp32-c61_technical_reference_manual_en.pdf [h2-trm]: https://www.espressif.com/sites/default/files/documentation/esp32-h2_technical_reference_manual_en.pdf +[p4-trm]: https://www.espressif.com/sites/default/files/documentation/esp32-p4_technical_reference_manual_en.pdf [s2-trm]: https://www.espressif.com/sites/default/files/documentation/esp32-s2_technical_reference_manual_en.pdf [s3-trm]: https://www.espressif.com/sites/default/files/documentation/esp32-s3_technical_reference_manual_en.pdf @@ -56,63 +59,63 @@ For help getting started with this HAL, please refer to [The Rust on ESP Book] a -| Driver | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S2 | ESP32-S3 | -| ------------------------- |:-----:|:--------:|:--------:|:--------:|:--------:|:---------:|:--------:|:--------:|:--------:| -| ADC | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | [❌][5422] [^1] | ⚒️ | ⚒️ | ⚒️ | -| AES | ⚒️ | | ⚒️ | ⚒️ | ⚒️ | | ⚒️ | ⚒️ | ⚒️ | -| ASSIST_DEBUG | | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | | ⚒️ | -| Analog Voltage Comparator | | | | [❌][5168] [^1] | | [❌][5423] [^1] | | | | -| Bit Scrambler | | | | [❌][5170] [^1] | | | | | | -| Bluetooth | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | | ⚒️ | -| Camera interface | ❌ | | | | | | | ❌ | ⚒️ | -| DAC | ⚒️ | | | | | | | ⚒️ | | -| Dedicated GPIO | | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | -| DMA | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | -| DS | | | [❌][884] [^1] | [❌][884] [^1] | [❌][884] [^1] | | [❌][884] [^1] | [❌][884] [^1] | [❌][884] [^1] | -| ECDSA | | | | [❌][5444] [^1] | | [❌][5444] [^1] | [❌][5444] [^1] | | | -| ECC | | ⚒️ | | ⚒️ | ⚒️ | ⚒️ | ⚒️ | | | -| Ethernet | ❌ | | | | | | | | | -| ETM | | | | [❌][5167] [^1] | ⚒️ | [❌][5419] [^1] | ⚒️ | | | -| GPIO | ✔️ | ✔️ | ✔️ | ⚒️ | ✔️ | ⚒️ | ✔️ | ✔️ | ✔️ | -| HMAC | | | ⚒️ | [❌][5166] [^1] | ⚒️ | | ⚒️ | ⚒️ | ⚒️ | -| I2C master | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | -| I2C slave | [❌][1909] [^1] | | [❌][1909] [^1] | [❌][1909] [^1] | [❌][1909] [^1] | [❌][1909] [^1] | [❌][1909] [^1] | [❌][1909] [^1] | [❌][1909] [^1] | -| I2S | ⚒️ | | ⚒️ | [❌][5172] [^1] | ⚒️ | [❌][5415] [^1] | ⚒️ | ⚒️ | ⚒️ | -| IEEE 802.15.4 | | | | ⚒️ | ⚒️ | | ⚒️ | | | -| Interrupts | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | -| IOMUX | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | -| Key Manager | | | | [❌][5171] [^1] | | | | | | -| LEDC | ⚒️ | ⚒️ | ⚒️ | [❌][5161] [^1] | ⚒️ | [❌][5418] [^1] | ⚒️ | ⚒️ | ⚒️ | -| LP I2C master | | | | ⚒️ | ⚒️ | | | | | -| LP UART | | | | [❌][5155] [^1] | ⚒️ | | | | | -| MCPWM | ⚒️ | | | [❌][5154] [^1] | ⚒️ | | ⚒️ | | ⚒️ | -| PARL_IO | | | | ⚒️ | ⚒️ | | ⚒️ | | | -| PCNT | ⚒️ | | | ⚒️ | ⚒️ | | ⚒️ | ⚒️ | ⚒️ | -| PHY | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | -| PSRAM | ⚒️ | | | ⚒️ | | ⚒️ | | ⚒️ | ⚒️ | -| RGB display | ⚒️ | | | | | | | ❌ | ⚒️ | -| RMT | ⚒️ | | ⚒️ | ⚒️ | ⚒️ | | ⚒️ | ⚒️ | ⚒️ | -| RNG | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | -| RSA | ⚒️ | | ⚒️ | ⚒️ | ⚒️ | | ⚒️ | ⚒️ | ⚒️ | -| RTC Timekeeping | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | -| SDIO host | ⚒️ | | | | | | | | ⚒️ | -| SDIO slave | ⚒️ | | | [❌][5169] [^1] | ⚒️ | [❌][5417] [^1] | | | | -| SHA | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | -| Light/deep sleep | ⚒️ | ⚒️ | ⚒️ | [❌][5165] [^1] | ⚒️ | [❌][5424] [^1] | ⚒️ | ⚒️ | ⚒️ | -| SPI master | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | -| SPI slave | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | -| SYSTIMER | | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | -| Temperature sensor | ⚒️ | ⚒️ | ⚒️ | [❌][5153] [^1] | ⚒️ | [❌][5421] [^1] | ⚒️ | ⚒️ | ⚒️ | -| Timers | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | -| Touch | ⚒️ | | | [❌][5164] [^1] | | | | [❌][1905] [^1] | [❌][1905] [^1] | -| TWAI / CAN / CANFD | ⚒️ | | ⚒️ | [❌][5163] [^1] | ⚒️ | | ⚒️ | ⚒️ | ⚒️ | -| UART | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | -| UHCI | ❌ | | ⚒️ | ⚒️ | ⚒️ | | ⚒️ | ❌ | ⚒️ | -| ULP (FSM) | ⚒️ | | | | | | | ⚒️ | ⚒️ | -| ULP (RISC-V) | | | | [❌][5160] [^1] | ⚒️ | | | ⚒️ | ⚒️ | -| USB OTG FS | | | | | | | | ⚒️ | ⚒️ | -| USB Serial/JTAG | | | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | | ⚒️ | -| WIFI | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | | ⚒️ | ⚒️ | +| Driver | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ------------------------- |:-----:|:--------:|:--------:|:--------:|:--------:|:---------:|:--------:|:--------:|:--------:|:--------:| +| ADC | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | [❌][5422] [^1] | ⚒️ | ❌ | ⚒️ | ⚒️ | +| AES | ⚒️ | | ⚒️ | ⚒️ | ⚒️ | | ⚒️ | ❌ | ⚒️ | ⚒️ | +| ASSIST_DEBUG | | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ❌ | | ⚒️ | +| Analog Voltage Comparator | | | | [❌][5168] [^1] | | [❌][5423] [^1] | | ❌ | | | +| Bit Scrambler | | | | [❌][5170] [^1] | | | | | | | +| Bluetooth | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | | | ⚒️ | +| Camera interface | ❌ | | | | | | | ❌ | ❌ | ⚒️ | +| DAC | ⚒️ | | | | | | | | ⚒️ | | +| Dedicated GPIO | | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | | ⚒️ | ⚒️ | +| DMA | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | +| DS | | | [❌][884] [^1] | [❌][884] [^1] | [❌][884] [^1] | | [❌][884] [^1] | ❌ | [❌][884] [^1] | [❌][884] [^1] | +| ECDSA | | | | [❌][5444] [^1] | | [❌][5444] [^1] | [❌][5444] [^1] | ❌ | | | +| ECC | | ⚒️ | | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ❌ | | | +| Ethernet | ❌ | | | | | | | ❌ | | | +| ETM | | | | [❌][5167] [^1] | ⚒️ | [❌][5419] [^1] | ⚒️ | ❌ | | | +| GPIO | ✔️ | ✔️ | ✔️ | ⚒️ | ✔️ | ⚒️ | ✔️ | ⚒️ | ✔️ | ✔️ | +| HMAC | | | ⚒️ | [❌][5166] [^1] | ⚒️ | | ⚒️ | ❌ | ⚒️ | ⚒️ | +| I2C master | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ⚒️ | ✔️ | ✔️ | +| I2C slave | [❌][1909] [^1] | | [❌][1909] [^1] | [❌][1909] [^1] | [❌][1909] [^1] | [❌][1909] [^1] | [❌][1909] [^1] | ❌ | [❌][1909] [^1] | [❌][1909] [^1] | +| I2S | ⚒️ | | ⚒️ | [❌][5172] [^1] | ⚒️ | [❌][5415] [^1] | ⚒️ | ❌ | ⚒️ | ⚒️ | +| IEEE 802.15.4 | | | | ⚒️ | ⚒️ | | ⚒️ | | | | +| Interrupts | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | +| IOMUX | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | | ⚒️ | ⚒️ | +| Key Manager | | | | [❌][5171] [^1] | | | | | | | +| LEDC | ⚒️ | ⚒️ | ⚒️ | [❌][5161] [^1] | ⚒️ | [❌][5418] [^1] | ⚒️ | ❌ | ⚒️ | ⚒️ | +| LP I2C master | | | | ⚒️ | ⚒️ | | | ❌ | | | +| LP UART | | | | [❌][5155] [^1] | ⚒️ | | | ❌ | | | +| MCPWM | ⚒️ | | | [❌][5154] [^1] | ⚒️ | | ⚒️ | ❌ | | ⚒️ | +| PARL_IO | | | | ⚒️ | ⚒️ | | ⚒️ | | | | +| PCNT | ⚒️ | | | ⚒️ | ⚒️ | | ⚒️ | ❌ | ⚒️ | ⚒️ | +| PHY | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | | ⚒️ | ⚒️ | +| PSRAM | ⚒️ | | | ⚒️ | | ⚒️ | | ⚒️ | ⚒️ | ⚒️ | +| RGB display | ⚒️ | | | | | | | ❌ | ❌ | ⚒️ | +| RMT | ⚒️ | | ⚒️ | ⚒️ | ⚒️ | | ⚒️ | | ⚒️ | ⚒️ | +| RNG | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ❌ | ⚒️ | ⚒️ | +| RSA | ⚒️ | | ⚒️ | ⚒️ | ⚒️ | | ⚒️ | ❌ | ⚒️ | ⚒️ | +| RTC Timekeeping | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ❌ | ⚒️ | ⚒️ | +| SDIO host | ⚒️ | | | | | | | ❌ | | ⚒️ | +| SDIO slave | ⚒️ | | | [❌][5169] [^1] | ⚒️ | [❌][5417] [^1] | | ❌ | | | +| SHA | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ❌ | ⚒️ | ⚒️ | +| Light/deep sleep | ⚒️ | ⚒️ | ⚒️ | [❌][5165] [^1] | ⚒️ | [❌][5424] [^1] | ⚒️ | ❌ | ⚒️ | ⚒️ | +| SPI master | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ⚒️ | ✔️ | ✔️ | +| SPI slave | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ❌ | ⚒️ | ⚒️ | +| SYSTIMER | | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | +| Temperature sensor | ⚒️ | ⚒️ | ⚒️ | [❌][5153] [^1] | ⚒️ | [❌][5421] [^1] | ⚒️ | ❌ | ⚒️ | ⚒️ | +| Timers | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | | ⚒️ | ⚒️ | +| Touch | ⚒️ | | | [❌][5164] [^1] | | | | ❌ | [❌][1905] [^1] | [❌][1905] [^1] | +| TWAI / CAN / CANFD | ⚒️ | | ⚒️ | [❌][5163] [^1] | ⚒️ | | ⚒️ | ❌ | ⚒️ | ⚒️ | +| UART | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ⚒️ | ✔️ | ✔️ | +| UHCI | ❌ | | ⚒️ | ⚒️ | ⚒️ | | ⚒️ | ❌ | ❌ | ⚒️ | +| ULP (FSM) | ⚒️ | | | | | | | | ⚒️ | ⚒️ | +| ULP (RISC-V) | | | | [❌][5160] [^1] | ⚒️ | | | ❌ | ⚒️ | ⚒️ | +| USB OTG FS | | | | | | | | | ⚒️ | ⚒️ | +| USB Serial/JTAG | | | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | | ⚒️ | +| WIFI | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | ⚒️ | | | ⚒️ | ⚒️ | * Empty cell: Not available * ❌: Not supported diff --git a/esp-hal/esp_config.yml b/esp-hal/esp_config.yml index 720038551fd..72189935d5c 100644 --- a/esp-hal/esp_config.yml +++ b/esp-hal/esp_config.yml @@ -168,6 +168,22 @@ options: - "8" active: 'chip == "esp32s3"' + - name: l2-cache-size + description: "ESP32-P4 L2 cache size. Must match the 2nd-stage bootloader's + `CACHE.L2_CACHE_CACHESIZE_CONF` setting (TRM L2MEM Config 0..3). Default + `256KB` matches the IDF bootloader bundled by espflash." + default: + - value: '"256KB"' + constraints: + - type: + validator: enumeration + value: + - "0KB" + - "128KB" + - "256KB" + - "512KB" + active: 'chip == "esp32p4"' + - name: min-chip-revision description: "The minimum chip revision required for the application to run, in format: major * 100 + minor." default: diff --git a/esp-hal/ld/esp32p4/esp32p4.x b/esp-hal/ld/esp32p4/esp32p4.x new file mode 100644 index 00000000000..171eedf75fc --- /dev/null +++ b/esp-hal/ld/esp32p4/esp32p4.x @@ -0,0 +1,80 @@ +ENTRY(_start) + +PROVIDE(_stext = ORIGIN(ROTEXT)); +PROVIDE(_max_hart_id = 1); + +PROVIDE(UserSoft = DefaultHandler); +PROVIDE(SupervisorSoft = DefaultHandler); +PROVIDE(MachineSoft = DefaultHandler); +PROVIDE(UserTimer = DefaultHandler); +PROVIDE(SupervisorTimer = DefaultHandler); +PROVIDE(MachineTimer = DefaultHandler); +PROVIDE(UserExternal = DefaultHandler); +PROVIDE(SupervisorExternal = DefaultHandler); +PROVIDE(MachineExternal = DefaultHandler); + +PROVIDE(ExceptionHandler = DefaultExceptionHandler); + +/* The ESP32-C2 and ESP32-C3 have interrupt IDs 1-31, while the ESP32-C6, + ESP32-H2, and ESP32-P4 have IDs 0-31, so we much define the handler for the + one additional interrupt ID: */ +PROVIDE(interrupt0 = DefaultHandler); + +/* Peripheral interrupt symbols are provided by the esp32p4 PAC's `device.x`, + which is included by `hal-defaults.x`. No need to list them here. */ + +PROVIDE(__post_init = default_post_init); + +/* A PAC/HAL defined routine that should initialize custom interrupt controller if needed. */ +PROVIDE(_setup_interrupts = default_setup_interrupts); + +/* # Multi-processing hook function + fn _mp_hook() -> bool; + This function is called from all the harts and must return true only for one hart, + which will perform memory initialization. For other harts it must return false + and implement wake-up in platform-dependent way (e.g. after waiting for a user interrupt). +*/ +PROVIDE(_mp_hook = default_mp_hook); + +/* # Start trap function override + By default uses the riscv crates default trap handler + but by providing the `_start_trap` symbol external crates can override. +*/ +PROVIDE(_start_trap = _default_start_trap); + +/* Must be called __global_pointer$ for linker relaxations to work. */ +PROVIDE(__global_pointer$ = _data_start + 0x800); + +/* NOTE: .trap section is generated by build.rs in rwtext.x, not duplicated here. */ + +SECTIONS { + /** + * Bootloader really wants to have separate segments for ROTEXT and RODATA + * It also needs to be located in a separate 64k flash segment. + */ + .text_gap (NOLOAD): { + . = ALIGN(0x10000) + 0x20; + } > ROM +} +INSERT BEFORE .rodata; + +/* Shared sections - ordering matters. + rwtext.x and rwdata.x contain bare section directives that need a SECTIONS context. + We wrap them in SECTIONS {} blocks. */ +SECTIONS { + INCLUDE "rwtext.x" +} + +SECTIONS { + INCLUDE "rwdata.x" +} + +INCLUDE "rodata.x" +INCLUDE "text.x" +INCLUDE "rtc_fast.x" +INCLUDE "stack.x" +INCLUDE "metadata.x" +INCLUDE "eh_frame.x" +/* End of Shared sections */ + +_dram_data_start = ORIGIN(RAM) + SIZEOF(.trap) + SIZEOF(.rwtext); \ No newline at end of file diff --git a/esp-hal/ld/esp32p4/linkall.x b/esp-hal/ld/esp32p4/linkall.x new file mode 100644 index 00000000000..485c40f2dd2 --- /dev/null +++ b/esp-hal/ld/esp32p4/linkall.x @@ -0,0 +1,22 @@ +INCLUDE "memory.x" + +/* esp-hal region aliases */ +REGION_ALIAS("ROTEXT", ROM); +REGION_ALIAS("RODATA", ROM); + +REGION_ALIAS("RWTEXT", RAM); +REGION_ALIAS("RWDATA", RAM); + +REGION_ALIAS("RTC_FAST_RWTEXT", RTC_FAST); +REGION_ALIAS("RTC_FAST_RWDATA", RTC_FAST); + +/* riscv-rt v0.16+ region aliases (required by upstream riscv-rt link.x) */ +REGION_ALIAS("REGION_TEXT", ROM); +REGION_ALIAS("REGION_RODATA", ROM); +REGION_ALIAS("REGION_DATA", RAM); +REGION_ALIAS("REGION_BSS", RAM); +REGION_ALIAS("REGION_HEAP", RAM); +REGION_ALIAS("REGION_STACK", RAM); + +INCLUDE "esp32p4.x" +INCLUDE "hal-defaults.x" \ No newline at end of file diff --git a/esp-hal/ld/esp32p4/memory.x b/esp-hal/ld/esp32p4/memory.x new file mode 100644 index 00000000000..f128ed2b2e9 --- /dev/null +++ b/esp-hal/ld/esp32p4/memory.x @@ -0,0 +1,41 @@ +/* The 768 KB L2MEM is shared between L2 cache (low end) and L2 RAM + (rest). The 2nd-stage bootloader programs CACHE.L2_CACHE_CACHESIZE_CONF + to one of four splits; the L2 RAM ORIGIN below must match. Top is + fixed at 0x4FFAE000 to leave the v3.x ROM BSS/stack region (top + ~72 KB of L2MEM) untouched. + + CONFIG numbers follow TRM Figure 7.3-2 (HP L2MEM Address Layout): + + CONFIG ESP_HAL_CONFIG_L2_CACHE_SIZE L2 cache L2 RAM ORIGIN + ------ ---------------------------- -------- ------------- + 0 "512KB" 512 KB 0x4FF80000 + 1 "256KB" 256 KB 0x4FF40000 + 2 "128KB" (IDF default) 128 KB 0x4FF20000 + 3 "0KB" 0 KB 0x4FF00000 +*/ + +MEMORY +{ + /* CONFIG 0 */ +#IF ESP_HAL_CONFIG_L2_CACHE_SIZE_512KB + RAM : ORIGIN = 0x4FF80000, LENGTH = 0x4FFAE000 - 0x4FF80000 +#ENDIF + /* CONFIG 1 */ +#IF ESP_HAL_CONFIG_L2_CACHE_SIZE_256KB + RAM : ORIGIN = 0x4FF40000, LENGTH = 0x4FFAE000 - 0x4FF40000 +#ENDIF + /* CONFIG 2 */ +#IF ESP_HAL_CONFIG_L2_CACHE_SIZE_128KB + RAM : ORIGIN = 0x4FF20000, LENGTH = 0x4FFAE000 - 0x4FF20000 +#ENDIF + /* CONFIG 3 */ +#IF ESP_HAL_CONFIG_L2_CACHE_SIZE_0KB + RAM : ORIGIN = 0x4FF00000, LENGTH = 0x4FFAE000 - 0x4FF00000 +#ENDIF + + /* External flash (XIP via cache); +0x20 skips the IDF app image header. */ + ROM : ORIGIN = 0x40000000 + 0x20, LENGTH = 0x400000 - 0x20 + + /* LP SRAM (32 KB, persists over deep sleep). */ + RTC_FAST : ORIGIN = 0x50108000, LENGTH = 32K +} diff --git a/esp-hal/src/analog/adc/riscv.rs b/esp-hal/src/analog/adc/riscv.rs index 96471dbdbd6..a34655dc4da 100644 --- a/esp-hal/src/analog/adc/riscv.rs +++ b/esp-hal/src/analog/adc/riscv.rs @@ -183,6 +183,17 @@ impl RegisterAccess for crate::peripherals::ADC1<'_> { regi2c::ADC_SAR1_DREF.write_field(1); } + // ESP32-P4 uses DREF value 4 (same as S2/S3) not 1. + // REGI2C_SAR_I2C (0x69) reg 2, bits [6:4] = DREF + #[cfg(esp32p4)] + fn calibration_init() { + use crate::soc::regi2c; + // REG2 bits [6:4] = ADC_SAR1_DREF; clear then set to 4 + let val = regi2c::regi2c_read(regi2c::REGI2C_SAR_I2C, 0, 2); + let new_val = (val & !(0x7 << 4)) | (4 << 4); + regi2c::regi2c_write(regi2c::REGI2C_SAR_I2C, 0, 2, new_val); + } + fn set_init_code(data: u16) { let [msb, lsb] = data.to_be_bytes(); @@ -260,6 +271,16 @@ impl RegisterAccess for crate::peripherals::ADC2<'_> { regi2c::ADC_SAR2_DREF.write_field(1); } + // ESP32-P4 uses DREF value 4 for ADC2 as well. + // REG5 bits [6:4] = ADC_SAR2_DREF + #[cfg(esp32p4)] + fn calibration_init() { + use crate::soc::regi2c; + let val = regi2c::regi2c_read(regi2c::REGI2C_SAR_I2C, 0, 5); + let new_val = (val & !(0x7 << 4)) | (4 << 4); + regi2c::regi2c_write(regi2c::REGI2C_SAR_I2C, 0, 5, new_val); + } + fn set_init_code(data: u16) { let [msb, lsb] = data.to_be_bytes(); diff --git a/esp-hal/src/clock/mod.rs b/esp-hal/src/clock/mod.rs index 7b71e71ac4f..1844b6ba573 100644 --- a/esp-hal/src/clock/mod.rs +++ b/esp-hal/src/clock/mod.rs @@ -103,6 +103,10 @@ impl CpuClock { Self::_160MHz } else if #[cfg(esp32h2)] { Self::_96MHz + } else if #[cfg(esp32p4)] { + // ESP32-P4 v3.x (eco5): max 400 MHz via CPLL + // Ref: TRM v0.5 Ch 2 -- HP CPU max frequency 400 MHz for v3.x + Self::_400MHz } else { Self::_240MHz } @@ -488,7 +492,17 @@ fn rtc_slow_cal_period() -> u64 { } } - LP_AON::regs().store1().read().bits() as u64 + // P4: LP_SYS (mapped as LP_AON in esp-hal) names its scratch registers + // `lp_store0..lp_store14`, while every other chip names them `store0..N`. + // TODO: file an esp-pacs issue/PR to rename the P4 fields to match. + // Once that lands this cfg branch can disappear. + cfg_if::cfg_if! { + if #[cfg(esp32p4)] { + LP_AON::regs().lp_store1().read().bits() as u64 + } else { + LP_AON::regs().store1().read().bits() as u64 + } + } } /// Convert RTC slow clock ticks to microseconds using the calibrated period. diff --git a/esp-hal/src/dma/gdma/ahb_v2.rs b/esp-hal/src/dma/gdma/ahb_v2.rs index 9403bca5454..6a6ff3b1b81 100644 --- a/esp-hal/src/dma/gdma/ahb_v2.rs +++ b/esp-hal/src/dma/gdma/ahb_v2.rs @@ -1,14 +1,26 @@ use super::*; use crate::RegisterToggle; +// P4 has two DMA controllers: `ahb_dma` (GDMA-AHB, GDMA v2 layout, used here) and +// `axi_dma` (GDMA-AXI, different register layout). The PAC's `dma` module maps to +// a separate block that is not GDMA-AHB, so alias `ahb_dma` as `gdma_pac` on P4. +// Other chips: PAC `dma` module is the GDMA v2 module directly. +cfg_if::cfg_if! { + if #[cfg(esp32p4)] { + use pac::ahb_dma as gdma_pac; + } else { + use pac::dma as gdma_pac; + } +} + impl AnyGdmaTxChannel<'_> { #[inline(always)] - pub(super) fn ch(&self) -> &pac::dma::ch::CH { + pub(super) fn ch(&self) -> &gdma_pac::ch::CH { DMA::regs().ch(self.channel as usize) } #[inline(always)] - pub(super) fn int(&self) -> &pac::dma::out_int_ch::OUT_INT_CH { + pub(super) fn int(&self) -> &gdma_pac::out_int_ch::OUT_INT_CH { DMA::regs().out_int_ch(self.channel as usize) } } @@ -217,12 +229,12 @@ impl InterruptAccess for AnyGdmaTxChannel<'_> { impl AnyGdmaRxChannel<'_> { #[inline(always)] - fn ch(&self) -> &pac::dma::ch::CH { + fn ch(&self) -> &gdma_pac::ch::CH { DMA::regs().ch(self.channel as usize) } #[inline(always)] - fn int(&self) -> &pac::dma::in_int_ch::IN_INT_CH { + fn int(&self) -> &gdma_pac::in_int_ch::IN_INT_CH { DMA::regs().in_int_ch(self.channel as usize) } } diff --git a/esp-hal/src/dma/gdma/mod.rs b/esp-hal/src/dma/gdma/mod.rs index 418ff7baa24..bf1c5cda06b 100644 --- a/esp-hal/src/dma/gdma/mod.rs +++ b/esp-hal/src/dma/gdma/mod.rs @@ -233,7 +233,15 @@ const CHANNEL_COUNT: usize = cfg!(soc_has_dma_ch0) as usize + cfg!(soc_has_dma_ch4) as usize; cfg_if::cfg_if! { - if #[cfg(dma_separate_in_out_interrupts)] { + // ESP32-P4: AHB_DMA interrupt names are AHB_PDMA_IN_CHn / AHB_PDMA_OUT_CHn + if #[cfg(esp32p4)] { + #[cfg(soc_has_dma_ch0)] + impl_channel!(0, AHB_PDMA_IN_CH0, AHB_PDMA_OUT_CH0); + #[cfg(soc_has_dma_ch1)] + impl_channel!(1, AHB_PDMA_IN_CH1, AHB_PDMA_OUT_CH1); + #[cfg(soc_has_dma_ch2)] + impl_channel!(2, AHB_PDMA_IN_CH2, AHB_PDMA_OUT_CH2); + } else if #[cfg(dma_separate_in_out_interrupts)] { #[cfg(soc_has_dma_ch0)] impl_channel!(0, DMA_IN_CH0, DMA_OUT_CH0); #[cfg(soc_has_dma_ch1)] diff --git a/esp-hal/src/dma/mod.rs b/esp-hal/src/dma/mod.rs index ebc0395625b..01b6fd705d7 100644 --- a/esp-hal/src/dma/mod.rs +++ b/esp-hal/src/dma/mod.rs @@ -61,7 +61,7 @@ use enumset::{EnumSet, EnumSetType}; pub use self::buffers::*; #[cfg(dma_kind = "gdma")] pub use self::gdma::*; -#[cfg(any(dma_kind = "gdma", esp32s2))] // TODO +#[cfg(all(any(dma_kind = "gdma", esp32s2), dma_supports_mem2mem))] pub use self::m2m::*; #[cfg(dma_kind = "pdma")] pub use self::pdma::*; diff --git a/esp-hal/src/efuse/esp32p4/fields.rs b/esp-hal/src/efuse/esp32p4/fields.rs new file mode 100644 index 00000000000..a2f2ae7058d --- /dev/null +++ b/esp-hal/src/efuse/esp32p4/fields.rs @@ -0,0 +1,644 @@ +//! eFuse fields for the ESP32-P4. +//! +//! This file was automatically generated, please do not edit it manually! +//! +//! For information on how to regenerate these files, please refer to the +//! `xtask` package's `README.md` file. +//! +//! Generated on: 2024-03-11 +//! ESP-IDF Commit: 0de2912f +use crate::efuse::EfuseField; + +/// Disable programming of individual eFuses +pub const WR_DIS: EfuseField = EfuseField::new(0, 0, 0, 32); +/// wr_dis of RD_DIS +pub const WR_DIS_RD_DIS: EfuseField = EfuseField::new(0, 0, 0, 1); +/// wr_dis of KM_RND_SWITCH_CYCLE +pub const WR_DIS_KM_RND_SWITCH_CYCLE: EfuseField = EfuseField::new(0, 0, 1, 1); +/// wr_dis of KM_DEPLOY_ONLY_ONCE +pub const WR_DIS_KM_DEPLOY_ONLY_ONCE: EfuseField = EfuseField::new(0, 0, 1, 1); +/// wr_dis of FORCE_USE_KEY_MANAGER_KEY +pub const WR_DIS_FORCE_USE_KEY_MANAGER_KEY: EfuseField = EfuseField::new(0, 0, 1, 1); +/// wr_dis of FORCE_DISABLE_SW_INIT_KEY +pub const WR_DIS_FORCE_DISABLE_SW_INIT_KEY: EfuseField = EfuseField::new(0, 0, 1, 1); +/// wr_dis of KM_XTS_KEY_LENGTH_256 +pub const WR_DIS_KM_XTS_KEY_LENGTH_256: EfuseField = EfuseField::new(0, 0, 1, 1); +/// wr_dis of KM_DEPLOY_ONLY_ONCE_H +pub const WR_DIS_KM_DEPLOY_ONLY_ONCE_H: EfuseField = EfuseField::new(0, 0, 1, 1); +/// wr_dis of FORCE_USE_KEY_MANAGER_KEY_H +pub const WR_DIS_FORCE_USE_KEY_MANAGER_KEY_H: EfuseField = EfuseField::new(0, 0, 1, 1); +/// wr_dis of LOCK_KM_KEY +pub const WR_DIS_LOCK_KM_KEY: EfuseField = EfuseField::new(0, 0, 1, 1); +/// wr_dis of KM_DISABLE_DEPLOY_MODE_H +pub const WR_DIS_KM_DISABLE_DEPLOY_MODE_H: EfuseField = EfuseField::new(0, 0, 1, 1); +/// wr_dis of KM_DISABLE_DEPLOY_MODE +pub const WR_DIS_KM_DISABLE_DEPLOY_MODE: EfuseField = EfuseField::new(0, 0, 1, 1); +/// wr_dis of DIS_USB_JTAG +pub const WR_DIS_DIS_USB_JTAG: EfuseField = EfuseField::new(0, 0, 2, 1); +/// wr_dis of DIS_FORCE_DOWNLOAD +pub const WR_DIS_DIS_FORCE_DOWNLOAD: EfuseField = EfuseField::new(0, 0, 2, 1); +/// wr_dis of SPI_DOWNLOAD_MSPI_DIS +pub const WR_DIS_SPI_DOWNLOAD_MSPI_DIS: EfuseField = EfuseField::new(0, 0, 2, 1); +/// wr_dis of DIS_TWAI +pub const WR_DIS_DIS_TWAI: EfuseField = EfuseField::new(0, 0, 2, 1); +/// wr_dis of JTAG_SEL_ENABLE +pub const WR_DIS_JTAG_SEL_ENABLE: EfuseField = EfuseField::new(0, 0, 2, 1); +/// wr_dis of DIS_PAD_JTAG +pub const WR_DIS_DIS_PAD_JTAG: EfuseField = EfuseField::new(0, 0, 2, 1); +/// wr_dis of DIS_DOWNLOAD_MANUAL_ENCRYPT +pub const WR_DIS_DIS_DOWNLOAD_MANUAL_ENCRYPT: EfuseField = EfuseField::new(0, 0, 2, 1); +/// wr_dis of WDT_DELAY_SEL +pub const WR_DIS_WDT_DELAY_SEL: EfuseField = EfuseField::new(0, 0, 2, 1); +/// wr_dis of HYS_EN_PAD +pub const WR_DIS_HYS_EN_PAD: EfuseField = EfuseField::new(0, 0, 2, 1); +/// wr_dis of PXA0_TIEH_SEL_0 +pub const WR_DIS_PXA0_TIEH_SEL_0: EfuseField = EfuseField::new(0, 0, 2, 1); +/// wr_dis of DIS_WDT +pub const WR_DIS_DIS_WDT: EfuseField = EfuseField::new(0, 0, 2, 1); +/// wr_dis of DIS_SWD +pub const WR_DIS_DIS_SWD: EfuseField = EfuseField::new(0, 0, 2, 1); +/// wr_dis of PVT_GLITCH_EN +pub const WR_DIS_PVT_GLITCH_EN: EfuseField = EfuseField::new(0, 0, 3, 1); +/// wr_dis of PVT_GLITCH_MODE +pub const WR_DIS_PVT_GLITCH_MODE: EfuseField = EfuseField::new(0, 0, 3, 1); +/// wr_dis of SPI_BOOT_CRYPT_CNT +pub const WR_DIS_SPI_BOOT_CRYPT_CNT: EfuseField = EfuseField::new(0, 0, 4, 1); +/// wr_dis of SECURE_BOOT_KEY_REVOKE0 +pub const WR_DIS_SECURE_BOOT_KEY_REVOKE0: EfuseField = EfuseField::new(0, 0, 5, 1); +/// wr_dis of SECURE_BOOT_KEY_REVOKE1 +pub const WR_DIS_SECURE_BOOT_KEY_REVOKE1: EfuseField = EfuseField::new(0, 0, 6, 1); +/// wr_dis of SECURE_BOOT_KEY_REVOKE2 +pub const WR_DIS_SECURE_BOOT_KEY_REVOKE2: EfuseField = EfuseField::new(0, 0, 7, 1); +/// `[WR_DIS.KEY0_PURPOSE]` wr_dis of KEY_PURPOSE_0 +pub const WR_DIS_KEY_PURPOSE_0: EfuseField = EfuseField::new(0, 0, 8, 1); +/// wr_dis of KEY_PURPOSE_0_H +pub const WR_DIS_KEY_PURPOSE_0_H: EfuseField = EfuseField::new(0, 0, 8, 1); +/// `[WR_DIS.KEY1_PURPOSE]` wr_dis of KEY_PURPOSE_1 +pub const WR_DIS_KEY_PURPOSE_1: EfuseField = EfuseField::new(0, 0, 9, 1); +/// wr_dis of KEY_PURPOSE_1_H +pub const WR_DIS_KEY_PURPOSE_1_H: EfuseField = EfuseField::new(0, 0, 9, 1); +/// `[WR_DIS.KEY2_PURPOSE]` wr_dis of KEY_PURPOSE_2 +pub const WR_DIS_KEY_PURPOSE_2: EfuseField = EfuseField::new(0, 0, 10, 1); +/// wr_dis of KEY_PURPOSE_2_H +pub const WR_DIS_KEY_PURPOSE_2_H: EfuseField = EfuseField::new(0, 0, 10, 1); +/// `[WR_DIS.KEY3_PURPOSE]` wr_dis of KEY_PURPOSE_3 +pub const WR_DIS_KEY_PURPOSE_3: EfuseField = EfuseField::new(0, 0, 11, 1); +/// wr_dis of KEY_PURPOSE_3_H +pub const WR_DIS_KEY_PURPOSE_3_H: EfuseField = EfuseField::new(0, 0, 11, 1); +/// `[WR_DIS.KEY4_PURPOSE]` wr_dis of KEY_PURPOSE_4 +pub const WR_DIS_KEY_PURPOSE_4: EfuseField = EfuseField::new(0, 0, 12, 1); +/// wr_dis of KEY_PURPOSE_4_H +pub const WR_DIS_KEY_PURPOSE_4_H: EfuseField = EfuseField::new(0, 0, 12, 1); +/// `[WR_DIS.KEY5_PURPOSE]` wr_dis of KEY_PURPOSE_5 +pub const WR_DIS_KEY_PURPOSE_5: EfuseField = EfuseField::new(0, 0, 13, 1); +/// wr_dis of KEY_PURPOSE_5_H +pub const WR_DIS_KEY_PURPOSE_5_H: EfuseField = EfuseField::new(0, 0, 13, 1); +/// wr_dis of ECC_FORCE_CONST_TIME +pub const WR_DIS_ECC_FORCE_CONST_TIME: EfuseField = EfuseField::new(0, 0, 14, 1); +/// wr_dis of SEC_DPA_LEVEL +pub const WR_DIS_SEC_DPA_LEVEL: EfuseField = EfuseField::new(0, 0, 14, 1); +/// wr_dis of XTS_DPA_CLK_ENABLE +pub const WR_DIS_XTS_DPA_CLK_ENABLE: EfuseField = EfuseField::new(0, 0, 14, 1); +/// wr_dis of XTS_DPA_PSEUDO_LEVEL +pub const WR_DIS_XTS_DPA_PSEUDO_LEVEL: EfuseField = EfuseField::new(0, 0, 14, 1); +/// wr_dis of SECURE_BOOT_EN +pub const WR_DIS_SECURE_BOOT_EN: EfuseField = EfuseField::new(0, 0, 15, 1); +/// wr_dis of SECURE_BOOT_AGGRESSIVE_REVOKE +pub const WR_DIS_SECURE_BOOT_AGGRESSIVE_REVOKE: EfuseField = EfuseField::new(0, 0, 16, 1); +/// wr_dis of HP_PWR_SRC_SEL +pub const WR_DIS_HP_PWR_SRC_SEL: EfuseField = EfuseField::new(0, 0, 17, 1); +/// wr_dis of FLASH_ECC_EN +pub const WR_DIS_FLASH_ECC_EN: EfuseField = EfuseField::new(0, 0, 18, 1); +/// wr_dis of DIS_USB_OTG_DOWNLOAD_MODE +pub const WR_DIS_DIS_USB_OTG_DOWNLOAD_MODE: EfuseField = EfuseField::new(0, 0, 18, 1); +/// wr_dis of FLASH_TPUW +pub const WR_DIS_FLASH_TPUW: EfuseField = EfuseField::new(0, 0, 18, 1); +/// wr_dis of DIS_DOWNLOAD_MODE +pub const WR_DIS_DIS_DOWNLOAD_MODE: EfuseField = EfuseField::new(0, 0, 18, 1); +/// wr_dis of DIS_DIRECT_BOOT +pub const WR_DIS_DIS_DIRECT_BOOT: EfuseField = EfuseField::new(0, 0, 18, 1); +/// wr_dis of DIS_USB_SERIAL_JTAG_ROM_PRINT +pub const WR_DIS_DIS_USB_SERIAL_JTAG_ROM_PRINT: EfuseField = EfuseField::new(0, 0, 18, 1); +/// wr_dis of DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE +pub const WR_DIS_DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE: EfuseField = EfuseField::new(0, 0, 18, 1); +/// wr_dis of ENABLE_SECURITY_DOWNLOAD +pub const WR_DIS_ENABLE_SECURITY_DOWNLOAD: EfuseField = EfuseField::new(0, 0, 18, 1); +/// wr_dis of UART_PRINT_CONTROL +pub const WR_DIS_UART_PRINT_CONTROL: EfuseField = EfuseField::new(0, 0, 18, 1); +/// wr_dis of FORCE_SEND_RESUME +pub const WR_DIS_FORCE_SEND_RESUME: EfuseField = EfuseField::new(0, 0, 18, 1); +/// wr_dis of SECURE_VERSION +pub const WR_DIS_SECURE_VERSION: EfuseField = EfuseField::new(0, 0, 18, 1); +/// wr_dis of SECURE_BOOT_DISABLE_FAST_WAKE +pub const WR_DIS_SECURE_BOOT_DISABLE_FAST_WAKE: EfuseField = EfuseField::new(0, 0, 18, 1); +/// wr_dis of HUK_GEN_STATE +pub const WR_DIS_HUK_GEN_STATE: EfuseField = EfuseField::new(0, 0, 19, 1); +/// wr_dis of BLOCK1 +pub const WR_DIS_BLK1: EfuseField = EfuseField::new(0, 0, 20, 1); +/// `[WR_DIS.MAC_FACTORY]` wr_dis of MAC +pub const WR_DIS_MAC: EfuseField = EfuseField::new(0, 0, 20, 1); +/// wr_dis of WAFER_VERSION_MINOR +pub const WR_DIS_WAFER_VERSION_MINOR: EfuseField = EfuseField::new(0, 0, 20, 1); +/// wr_dis of WAFER_VERSION_MAJOR_LO +pub const WR_DIS_WAFER_VERSION_MAJOR_LO: EfuseField = EfuseField::new(0, 0, 20, 1); +/// wr_dis of DISABLE_WAFER_VERSION_MAJOR +pub const WR_DIS_DISABLE_WAFER_VERSION_MAJOR: EfuseField = EfuseField::new(0, 0, 20, 1); +/// wr_dis of DISABLE_BLK_VERSION_MAJOR +pub const WR_DIS_DISABLE_BLK_VERSION_MAJOR: EfuseField = EfuseField::new(0, 0, 20, 1); +/// wr_dis of BLK_VERSION_MINOR +pub const WR_DIS_BLK_VERSION_MINOR: EfuseField = EfuseField::new(0, 0, 20, 1); +/// wr_dis of BLK_VERSION_MAJOR +pub const WR_DIS_BLK_VERSION_MAJOR: EfuseField = EfuseField::new(0, 0, 20, 1); +/// wr_dis of PSRAM_CAP +pub const WR_DIS_PSRAM_CAP: EfuseField = EfuseField::new(0, 0, 20, 1); +/// wr_dis of TEMP +pub const WR_DIS_TEMP: EfuseField = EfuseField::new(0, 0, 20, 1); +/// wr_dis of PSRAM_VENDOR +pub const WR_DIS_PSRAM_VENDOR: EfuseField = EfuseField::new(0, 0, 20, 1); +/// wr_dis of PKG_VERSION +pub const WR_DIS_PKG_VERSION: EfuseField = EfuseField::new(0, 0, 20, 1); +/// wr_dis of BLOCK2 +pub const WR_DIS_SYS_DATA_PART1: EfuseField = EfuseField::new(0, 0, 21, 1); +/// wr_dis of WAFER_VERSION_MAJOR_HI +pub const WR_DIS_WAFER_VERSION_MAJOR_HI: EfuseField = EfuseField::new(0, 0, 20, 1); +/// wr_dis of LDO_VO1_DREF +pub const WR_DIS_LDO_VO1_DREF: EfuseField = EfuseField::new(0, 0, 20, 1); +/// wr_dis of LDO_VO2_DREF +pub const WR_DIS_LDO_VO2_DREF: EfuseField = EfuseField::new(0, 0, 20, 1); +/// wr_dis of LDO_VO1_MUL +pub const WR_DIS_LDO_VO1_MUL: EfuseField = EfuseField::new(0, 0, 20, 1); +/// wr_dis of LDO_VO2_MUL +pub const WR_DIS_LDO_VO2_MUL: EfuseField = EfuseField::new(0, 0, 20, 1); +/// wr_dis of LDO_VO3_K +pub const WR_DIS_LDO_VO3_K: EfuseField = EfuseField::new(0, 0, 20, 1); +/// wr_dis of LDO_VO3_VOS +pub const WR_DIS_LDO_VO3_VOS: EfuseField = EfuseField::new(0, 0, 20, 1); +/// wr_dis of LDO_VO3_C +pub const WR_DIS_LDO_VO3_C: EfuseField = EfuseField::new(0, 0, 20, 1); +/// wr_dis of LDO_VO4_K +pub const WR_DIS_LDO_VO4_K: EfuseField = EfuseField::new(0, 0, 20, 1); +/// wr_dis of LDO_VO4_VOS +pub const WR_DIS_LDO_VO4_VOS: EfuseField = EfuseField::new(0, 0, 20, 1); +/// wr_dis of LDO_VO4_C +pub const WR_DIS_LDO_VO4_C: EfuseField = EfuseField::new(0, 0, 20, 1); +/// wr_dis of ACTIVE_HP_DBIAS +pub const WR_DIS_ACTIVE_HP_DBIAS: EfuseField = EfuseField::new(0, 0, 20, 1); +/// wr_dis of ACTIVE_LP_DBIAS +pub const WR_DIS_ACTIVE_LP_DBIAS: EfuseField = EfuseField::new(0, 0, 20, 1); +/// wr_dis of DSLP_DBG +pub const WR_DIS_DSLP_DBG: EfuseField = EfuseField::new(0, 0, 20, 1); +/// wr_dis of DSLP_LP_DBIAS +pub const WR_DIS_DSLP_LP_DBIAS: EfuseField = EfuseField::new(0, 0, 20, 1); +/// wr_dis of LP_DCDC_DBIAS_VOL_GAP +pub const WR_DIS_LP_DCDC_DBIAS_VOL_GAP: EfuseField = EfuseField::new(0, 0, 20, 1); +/// wr_dis of PVT_400M_BIAS +pub const WR_DIS_PVT_400M_BIAS: EfuseField = EfuseField::new(0, 0, 20, 1); +/// wr_dis of PVT_40M_BIAS +pub const WR_DIS_PVT_40M_BIAS: EfuseField = EfuseField::new(0, 0, 20, 1); +/// wr_dis of PVT_100M_BIAS +pub const WR_DIS_PVT_100M_BIAS: EfuseField = EfuseField::new(0, 0, 20, 1); +/// wr_dis of OPTIONAL_UNIQUE_ID +pub const WR_DIS_OPTIONAL_UNIQUE_ID: EfuseField = EfuseField::new(0, 0, 21, 1); +/// wr_dis of ADC1_AVE_INITCODE_ATTEN0 +pub const WR_DIS_ADC1_AVE_INITCODE_ATTEN0: EfuseField = EfuseField::new(0, 0, 21, 1); +/// wr_dis of ADC1_AVE_INITCODE_ATTEN1 +pub const WR_DIS_ADC1_AVE_INITCODE_ATTEN1: EfuseField = EfuseField::new(0, 0, 21, 1); +/// wr_dis of ADC1_AVE_INITCODE_ATTEN2 +pub const WR_DIS_ADC1_AVE_INITCODE_ATTEN2: EfuseField = EfuseField::new(0, 0, 21, 1); +/// wr_dis of ADC1_AVE_INITCODE_ATTEN3 +pub const WR_DIS_ADC1_AVE_INITCODE_ATTEN3: EfuseField = EfuseField::new(0, 0, 21, 1); +/// wr_dis of ADC2_AVE_INITCODE_ATTEN0 +pub const WR_DIS_ADC2_AVE_INITCODE_ATTEN0: EfuseField = EfuseField::new(0, 0, 21, 1); +/// wr_dis of ADC2_AVE_INITCODE_ATTEN1 +pub const WR_DIS_ADC2_AVE_INITCODE_ATTEN1: EfuseField = EfuseField::new(0, 0, 21, 1); +/// wr_dis of ADC2_AVE_INITCODE_ATTEN2 +pub const WR_DIS_ADC2_AVE_INITCODE_ATTEN2: EfuseField = EfuseField::new(0, 0, 21, 1); +/// wr_dis of ADC2_AVE_INITCODE_ATTEN3 +pub const WR_DIS_ADC2_AVE_INITCODE_ATTEN3: EfuseField = EfuseField::new(0, 0, 21, 1); +/// wr_dis of ADC1_HI_DOUT_ATTEN0 +pub const WR_DIS_ADC1_HI_DOUT_ATTEN0: EfuseField = EfuseField::new(0, 0, 21, 1); +/// wr_dis of ADC1_HI_DOUT_ATTEN1 +pub const WR_DIS_ADC1_HI_DOUT_ATTEN1: EfuseField = EfuseField::new(0, 0, 21, 1); +/// wr_dis of ADC1_HI_DOUT_ATTEN2 +pub const WR_DIS_ADC1_HI_DOUT_ATTEN2: EfuseField = EfuseField::new(0, 0, 21, 1); +/// wr_dis of ADC1_HI_DOUT_ATTEN3 +pub const WR_DIS_ADC1_HI_DOUT_ATTEN3: EfuseField = EfuseField::new(0, 0, 21, 1); +/// `[WR_DIS.USER_DATA]` wr_dis of BLOCK_USR_DATA +pub const WR_DIS_BLOCK_USR_DATA: EfuseField = EfuseField::new(0, 0, 22, 1); +/// `[WR_DIS.MAC_CUSTOM WR_DIS.USER_DATA_MAC_CUSTOM]` wr_dis of CUSTOM_MAC +pub const WR_DIS_CUSTOM_MAC: EfuseField = EfuseField::new(0, 0, 22, 1); +/// `[WR_DIS.KEY0]` wr_dis of BLOCK_KEY0 +pub const WR_DIS_BLOCK_KEY0: EfuseField = EfuseField::new(0, 0, 23, 1); +/// `[WR_DIS.KEY1]` wr_dis of BLOCK_KEY1 +pub const WR_DIS_BLOCK_KEY1: EfuseField = EfuseField::new(0, 0, 24, 1); +/// `[WR_DIS.KEY2]` wr_dis of BLOCK_KEY2 +pub const WR_DIS_BLOCK_KEY2: EfuseField = EfuseField::new(0, 0, 25, 1); +/// `[WR_DIS.KEY3]` wr_dis of BLOCK_KEY3 +pub const WR_DIS_BLOCK_KEY3: EfuseField = EfuseField::new(0, 0, 26, 1); +/// `[WR_DIS.KEY4]` wr_dis of BLOCK_KEY4 +pub const WR_DIS_BLOCK_KEY4: EfuseField = EfuseField::new(0, 0, 27, 1); +/// `[WR_DIS.KEY5]` wr_dis of BLOCK_KEY5 +pub const WR_DIS_BLOCK_KEY5: EfuseField = EfuseField::new(0, 0, 28, 1); +/// `[WR_DIS.SYS_DATA_PART2]` wr_dis of BLOCK_SYS_DATA2 +pub const WR_DIS_BLOCK_SYS_DATA2: EfuseField = EfuseField::new(0, 0, 29, 1); +/// wr_dis of ADC2_HI_DOUT_ATTEN0 +pub const WR_DIS_ADC2_HI_DOUT_ATTEN0: EfuseField = EfuseField::new(0, 0, 29, 1); +/// wr_dis of ADC2_HI_DOUT_ATTEN1 +pub const WR_DIS_ADC2_HI_DOUT_ATTEN1: EfuseField = EfuseField::new(0, 0, 29, 1); +/// wr_dis of ADC2_HI_DOUT_ATTEN2 +pub const WR_DIS_ADC2_HI_DOUT_ATTEN2: EfuseField = EfuseField::new(0, 0, 29, 1); +/// wr_dis of ADC2_HI_DOUT_ATTEN3 +pub const WR_DIS_ADC2_HI_DOUT_ATTEN3: EfuseField = EfuseField::new(0, 0, 29, 1); +/// wr_dis of ADC1_CH0_ATTEN0_INITCODE_DIFF +pub const WR_DIS_ADC1_CH0_ATTEN0_INITCODE_DIFF: EfuseField = EfuseField::new(0, 0, 29, 1); +/// wr_dis of ADC1_CH1_ATTEN0_INITCODE_DIFF +pub const WR_DIS_ADC1_CH1_ATTEN0_INITCODE_DIFF: EfuseField = EfuseField::new(0, 0, 29, 1); +/// wr_dis of ADC1_CH2_ATTEN0_INITCODE_DIFF +pub const WR_DIS_ADC1_CH2_ATTEN0_INITCODE_DIFF: EfuseField = EfuseField::new(0, 0, 29, 1); +/// wr_dis of ADC1_CH3_ATTEN0_INITCODE_DIFF +pub const WR_DIS_ADC1_CH3_ATTEN0_INITCODE_DIFF: EfuseField = EfuseField::new(0, 0, 29, 1); +/// wr_dis of ADC1_CH4_ATTEN0_INITCODE_DIFF +pub const WR_DIS_ADC1_CH4_ATTEN0_INITCODE_DIFF: EfuseField = EfuseField::new(0, 0, 29, 1); +/// wr_dis of ADC1_CH5_ATTEN0_INITCODE_DIFF +pub const WR_DIS_ADC1_CH5_ATTEN0_INITCODE_DIFF: EfuseField = EfuseField::new(0, 0, 29, 1); +/// wr_dis of ADC1_CH6_ATTEN0_INITCODE_DIFF +pub const WR_DIS_ADC1_CH6_ATTEN0_INITCODE_DIFF: EfuseField = EfuseField::new(0, 0, 29, 1); +/// wr_dis of ADC1_CH7_ATTEN0_INITCODE_DIFF +pub const WR_DIS_ADC1_CH7_ATTEN0_INITCODE_DIFF: EfuseField = EfuseField::new(0, 0, 29, 1); +/// wr_dis of ADC2_CH0_ATTEN0_INITCODE_DIFF +pub const WR_DIS_ADC2_CH0_ATTEN0_INITCODE_DIFF: EfuseField = EfuseField::new(0, 0, 29, 1); +/// wr_dis of ADC2_CH1_ATTEN0_INITCODE_DIFF +pub const WR_DIS_ADC2_CH1_ATTEN0_INITCODE_DIFF: EfuseField = EfuseField::new(0, 0, 29, 1); +/// wr_dis of ADC2_CH2_ATTEN0_INITCODE_DIFF +pub const WR_DIS_ADC2_CH2_ATTEN0_INITCODE_DIFF: EfuseField = EfuseField::new(0, 0, 29, 1); +/// wr_dis of ADC2_CH3_ATTEN0_INITCODE_DIFF +pub const WR_DIS_ADC2_CH3_ATTEN0_INITCODE_DIFF: EfuseField = EfuseField::new(0, 0, 29, 1); +/// wr_dis of ADC2_CH4_ATTEN0_INITCODE_DIFF +pub const WR_DIS_ADC2_CH4_ATTEN0_INITCODE_DIFF: EfuseField = EfuseField::new(0, 0, 29, 1); +/// wr_dis of ADC2_CH5_ATTEN0_INITCODE_DIFF +pub const WR_DIS_ADC2_CH5_ATTEN0_INITCODE_DIFF: EfuseField = EfuseField::new(0, 0, 29, 1); +/// wr_dis of TEMPERATURE_SENSOR +pub const WR_DIS_TEMPERATURE_SENSOR: EfuseField = EfuseField::new(0, 0, 29, 1); +/// wr_dis of USB_DEVICE_EXCHG_PINS +pub const WR_DIS_USB_DEVICE_EXCHG_PINS: EfuseField = EfuseField::new(0, 0, 29, 1); +/// wr_dis of USB_OTG11_EXCHG_PINS +pub const WR_DIS_USB_OTG11_EXCHG_PINS: EfuseField = EfuseField::new(0, 0, 29, 1); +/// wr_dis of SOFT_DIS_JTAG +pub const WR_DIS_SOFT_DIS_JTAG: EfuseField = EfuseField::new(0, 0, 31, 1); +/// Disable reading from BlOCK4-10 +pub const RD_DIS: EfuseField = EfuseField::new(0, 1, 32, 7); +/// `[RD_DIS.KEY0]` rd_dis of BLOCK_KEY0 +pub const RD_DIS_BLOCK_KEY0: EfuseField = EfuseField::new(0, 1, 32, 1); +/// `[RD_DIS.KEY1]` rd_dis of BLOCK_KEY1 +pub const RD_DIS_BLOCK_KEY1: EfuseField = EfuseField::new(0, 1, 33, 1); +/// `[RD_DIS.KEY2]` rd_dis of BLOCK_KEY2 +pub const RD_DIS_BLOCK_KEY2: EfuseField = EfuseField::new(0, 1, 34, 1); +/// `[RD_DIS.KEY3]` rd_dis of BLOCK_KEY3 +pub const RD_DIS_BLOCK_KEY3: EfuseField = EfuseField::new(0, 1, 35, 1); +/// `[RD_DIS.KEY4]` rd_dis of BLOCK_KEY4 +pub const RD_DIS_BLOCK_KEY4: EfuseField = EfuseField::new(0, 1, 36, 1); +/// `[RD_DIS.KEY5]` rd_dis of BLOCK_KEY5 +pub const RD_DIS_BLOCK_KEY5: EfuseField = EfuseField::new(0, 1, 37, 1); +/// `[RD_DIS.SYS_DATA_PART2]` rd_dis of BLOCK_SYS_DATA2 +pub const RD_DIS_BLOCK_SYS_DATA2: EfuseField = EfuseField::new(0, 1, 38, 1); +/// rd_dis of ADC2_HI_DOUT_ATTEN0 +pub const RD_DIS_ADC2_HI_DOUT_ATTEN0: EfuseField = EfuseField::new(0, 1, 38, 1); +/// rd_dis of ADC2_HI_DOUT_ATTEN1 +pub const RD_DIS_ADC2_HI_DOUT_ATTEN1: EfuseField = EfuseField::new(0, 1, 38, 1); +/// rd_dis of ADC2_HI_DOUT_ATTEN2 +pub const RD_DIS_ADC2_HI_DOUT_ATTEN2: EfuseField = EfuseField::new(0, 1, 38, 1); +/// rd_dis of ADC2_HI_DOUT_ATTEN3 +pub const RD_DIS_ADC2_HI_DOUT_ATTEN3: EfuseField = EfuseField::new(0, 1, 38, 1); +/// rd_dis of ADC1_CH0_ATTEN0_INITCODE_DIFF +pub const RD_DIS_ADC1_CH0_ATTEN0_INITCODE_DIFF: EfuseField = EfuseField::new(0, 1, 38, 1); +/// rd_dis of ADC1_CH1_ATTEN0_INITCODE_DIFF +pub const RD_DIS_ADC1_CH1_ATTEN0_INITCODE_DIFF: EfuseField = EfuseField::new(0, 1, 38, 1); +/// rd_dis of ADC1_CH2_ATTEN0_INITCODE_DIFF +pub const RD_DIS_ADC1_CH2_ATTEN0_INITCODE_DIFF: EfuseField = EfuseField::new(0, 1, 38, 1); +/// rd_dis of ADC1_CH3_ATTEN0_INITCODE_DIFF +pub const RD_DIS_ADC1_CH3_ATTEN0_INITCODE_DIFF: EfuseField = EfuseField::new(0, 1, 38, 1); +/// rd_dis of ADC1_CH4_ATTEN0_INITCODE_DIFF +pub const RD_DIS_ADC1_CH4_ATTEN0_INITCODE_DIFF: EfuseField = EfuseField::new(0, 1, 38, 1); +/// rd_dis of ADC1_CH5_ATTEN0_INITCODE_DIFF +pub const RD_DIS_ADC1_CH5_ATTEN0_INITCODE_DIFF: EfuseField = EfuseField::new(0, 1, 38, 1); +/// rd_dis of ADC1_CH6_ATTEN0_INITCODE_DIFF +pub const RD_DIS_ADC1_CH6_ATTEN0_INITCODE_DIFF: EfuseField = EfuseField::new(0, 1, 38, 1); +/// rd_dis of ADC1_CH7_ATTEN0_INITCODE_DIFF +pub const RD_DIS_ADC1_CH7_ATTEN0_INITCODE_DIFF: EfuseField = EfuseField::new(0, 1, 38, 1); +/// rd_dis of ADC2_CH0_ATTEN0_INITCODE_DIFF +pub const RD_DIS_ADC2_CH0_ATTEN0_INITCODE_DIFF: EfuseField = EfuseField::new(0, 1, 38, 1); +/// rd_dis of ADC2_CH1_ATTEN0_INITCODE_DIFF +pub const RD_DIS_ADC2_CH1_ATTEN0_INITCODE_DIFF: EfuseField = EfuseField::new(0, 1, 38, 1); +/// rd_dis of ADC2_CH2_ATTEN0_INITCODE_DIFF +pub const RD_DIS_ADC2_CH2_ATTEN0_INITCODE_DIFF: EfuseField = EfuseField::new(0, 1, 38, 1); +/// rd_dis of ADC2_CH3_ATTEN0_INITCODE_DIFF +pub const RD_DIS_ADC2_CH3_ATTEN0_INITCODE_DIFF: EfuseField = EfuseField::new(0, 1, 38, 1); +/// rd_dis of ADC2_CH4_ATTEN0_INITCODE_DIFF +pub const RD_DIS_ADC2_CH4_ATTEN0_INITCODE_DIFF: EfuseField = EfuseField::new(0, 1, 38, 1); +/// rd_dis of ADC2_CH5_ATTEN0_INITCODE_DIFF +pub const RD_DIS_ADC2_CH5_ATTEN0_INITCODE_DIFF: EfuseField = EfuseField::new(0, 1, 38, 1); +/// rd_dis of TEMPERATURE_SENSOR +pub const RD_DIS_TEMPERATURE_SENSOR: EfuseField = EfuseField::new(0, 1, 38, 1); +/// rd_dis of USB_DEVICE_EXCHG_PINS +pub const RD_DIS_USB_DEVICE_EXCHG_PINS: EfuseField = EfuseField::new(0, 1, 38, 1); +/// rd_dis of USB_OTG11_EXCHG_PINS +pub const RD_DIS_USB_OTG11_EXCHG_PINS: EfuseField = EfuseField::new(0, 1, 38, 1); +/// Represents the starting flash sector (flash sector size is 0x1000) of the recovery +/// bootloader used by the ROM bootloader If the primary bootloader fails. 0 and 0xFFF - this +/// feature is disabled +pub const RECOVERY_BOOTLOADER_FLASH_SECTOR_0_1: EfuseField = EfuseField::new(0, 1, 39, 2); +/// Set this bit to disable function of usb switch to jtag in module of usb device +pub const DIS_USB_JTAG: EfuseField = EfuseField::new(0, 1, 41, 1); +/// Represents the starting flash sector (flash sector size is 0x1000) of the recovery +/// bootloader used by the ROM bootloader If the primary bootloader fails. 0 and 0xFFF - this +/// feature is disabled +pub const RECOVERY_BOOTLOADER_FLASH_SECTOR_2_2: EfuseField = EfuseField::new(0, 1, 42, 1); +/// Set this bit to disable the function that forces chip into download mode +pub const DIS_FORCE_DOWNLOAD: EfuseField = EfuseField::new(0, 1, 44, 1); +/// Set this bit to disable accessing MSPI flash/MSPI ram by SYS AXI matrix during +/// boot_mode_download +pub const SPI_DOWNLOAD_MSPI_DIS: EfuseField = EfuseField::new(0, 1, 45, 1); +/// Set this bit to disable TWAI function +pub const DIS_TWAI: EfuseField = EfuseField::new(0, 1, 46, 1); +/// Set this bit to enable selection between usb_to_jtag and pad_to_jtag through strapping +/// gpio25 when both EFUSE_DIS_PAD_JTAG and EFUSE_DIS_USB_JTAG are equal to 0 +pub const JTAG_SEL_ENABLE: EfuseField = EfuseField::new(0, 1, 47, 1); +/// Set odd bits to disable JTAG in the soft way. JTAG can be enabled in HMAC module +pub const SOFT_DIS_JTAG: EfuseField = EfuseField::new(0, 1, 48, 3); +/// Set this bit to disable JTAG in the hard way. JTAG is disabled permanently +pub const DIS_PAD_JTAG: EfuseField = EfuseField::new(0, 1, 51, 1); +/// Set this bit to disable flash manual encrypt function (except in SPI boot mode) +pub const DIS_DOWNLOAD_MANUAL_ENCRYPT: EfuseField = EfuseField::new(0, 1, 52, 1); +/// Represents the starting flash sector (flash sector size is 0x1000) of the recovery +/// bootloader used by the ROM bootloader If the primary bootloader fails. 0 and 0xFFF - this +/// feature is disabled +pub const RECOVERY_BOOTLOADER_FLASH_SECTOR_3_6: EfuseField = EfuseField::new(0, 1, 53, 4); +/// 0: intphy(gpio24/25) <---> usb_device 1: intphy(26/27) <---> usb_otg11.1: intphy(gpio26/27) +/// <---> usb_device 1: intphy(24/25) <---> usb_otg11 +pub const USB_PHY_SEL: EfuseField = EfuseField::new(0, 1, 57, 1); +/// Set the bits to control validation of HUK generate mode. Odd of 1 is invalid; even of 1 is +/// valid +pub const HUK_GEN_STATE: EfuseField = EfuseField::new(0, 1, 58, 5); +/// Represents the starting flash sector (flash sector size is 0x1000) of the recovery +/// bootloader used by the ROM bootloader If the primary bootloader fails. 0 and 0xFFF - this +/// feature is disabled +pub const RECOVERY_BOOTLOADER_FLASH_SECTOR_7_7: EfuseField = EfuseField::new(0, 1, 63, 1); +/// Represents the starting flash sector (flash sector size is 0x1000) of the recovery +/// bootloader used by the ROM bootloader If the primary bootloader fails. 0 and 0xFFF - this +/// feature is disabled +pub const RECOVERY_BOOTLOADER_FLASH_SECTOR_8_10: EfuseField = EfuseField::new(0, 2, 64, 3); +/// Represents the starting flash sector (flash sector size is 0x1000) of the recovery +/// bootloader used by the ROM bootloader If the primary bootloader fails. 0 and 0xFFF - this +/// feature is disabled +pub const RECOVERY_BOOTLOADER_FLASH_SECTOR_11_11: EfuseField = EfuseField::new(0, 2, 67, 1); +/// Set the bits to control key manager random number switch cycle. 0: control by register. 1: +/// 8 km clk cycles. 2: 16 km cycles. 3: 32 km cycles +pub const KM_RND_SWITCH_CYCLE: EfuseField = EfuseField::new(0, 2, 68, 1); +/// EFUSE_KM_DEPLOY_ONLY_ONCE and EFUSE_KM_DEPLOY_ONLY_ONCE_H together form one field: +/// {EFUSE_KM_DEPLOY_ONLY_ONCE_H; EFUSE_KM_DEPLOY_ONLY_ONCE`[3:0]`}. Set each bit to control whether +/// corresponding key can only be deployed once. 1 is true; 0 is false. bit 0: ecsda; bit 1: xts; +/// bit2: hmac; bit3: ds; bit4:psram +pub const KM_DEPLOY_ONLY_ONCE: EfuseField = EfuseField::new(0, 3, 118, 5); +/// EFUSE_FORCE_USE_KEY_MANAGER_KEY and EFUSE_FORCE_USE_KEY_MANAGER_KEY_H together form one +/// field: {EFUSE_FORCE_USE_KEY_MANAGER_KEY_H; EFUSE_FORCE_USE_KEY_MANAGER_KEY`[3:0]`}. Set each bit +/// to control whether corresponding key must come from key manager. 1 is true; 0 is false. bit 0: +/// ecsda; bit 1: xts; bit2: hmac; bit3: ds; bit4:psram +pub const FORCE_USE_KEY_MANAGER_KEY: EfuseField = EfuseField::new(0, 3, 119, 5); +/// Set this bit to disable software written init key; and force use efuse_init_key +pub const FORCE_DISABLE_SW_INIT_KEY: EfuseField = EfuseField::new(0, 2, 77, 1); +/// Set this bit to config flash encryption xts-512 key; else use xts-256 key when using the +/// key manager +pub const KM_XTS_KEY_LENGTH_256: EfuseField = EfuseField::new(0, 2, 78, 1); +/// Set this bit to permanently turn on ECC const-time mode +pub const ECC_FORCE_CONST_TIME: EfuseField = EfuseField::new(0, 2, 79, 1); +/// Select lp wdt timeout threshold at startup = initial timeout value * (2 ^ +/// (EFUSE_WDT_DELAY_SEL + 1)) +pub const WDT_DELAY_SEL: EfuseField = EfuseField::new(0, 2, 81, 1); +/// Set this bit to enable SPI boot encrypt/decrypt. Odd number of 1: enable. even number of 1: +/// disable {0: "Disable"; 1: "Enable"; 3: "Disable"; 7: "Enable"} +pub const SPI_BOOT_CRYPT_CNT: EfuseField = EfuseField::new(0, 2, 82, 3); +/// Revoke 1st secure boot key +pub const SECURE_BOOT_KEY_REVOKE0: EfuseField = EfuseField::new(0, 2, 85, 1); +/// Revoke 2nd secure boot key +pub const SECURE_BOOT_KEY_REVOKE1: EfuseField = EfuseField::new(0, 2, 86, 1); +/// Revoke 3rd secure boot key +pub const SECURE_BOOT_KEY_REVOKE2: EfuseField = EfuseField::new(0, 2, 87, 1); +/// `[KEY0_PURPOSE]` Purpose of Key0 +pub const KEY_PURPOSE_0: EfuseField = EfuseField::new(0, 4, 155, 5); +/// `[KEY1_PURPOSE]` Purpose of Key1 +pub const KEY_PURPOSE_1: EfuseField = EfuseField::new(0, 4, 156, 5); +/// `[KEY2_PURPOSE]` Purpose of Key2 +pub const KEY_PURPOSE_2: EfuseField = EfuseField::new(0, 4, 157, 5); +/// `[KEY3_PURPOSE]` Purpose of Key3 +pub const KEY_PURPOSE_3: EfuseField = EfuseField::new(0, 4, 158, 5); +/// `[KEY4_PURPOSE]` Purpose of Key4 +pub const KEY_PURPOSE_4: EfuseField = EfuseField::new(0, 4, 159, 5); +/// `[KEY5_PURPOSE]` Purpose of Key5 +pub const KEY_PURPOSE_5: EfuseField = EfuseField::new(0, 5, 164, 5); +/// Configures the clock random divide mode to determine the dpa secure level +pub const SEC_DPA_LEVEL: EfuseField = EfuseField::new(0, 3, 112, 2); +/// Sets this bit to enable xts clock anti-dpa attack function +pub const XTS_DPA_CLK_ENABLE: EfuseField = EfuseField::new(0, 3, 115, 1); +/// Set this bit to enable secure boot +pub const SECURE_BOOT_EN: EfuseField = EfuseField::new(0, 3, 116, 1); +/// Set this bit to enable revoking aggressive secure boot +pub const SECURE_BOOT_AGGRESSIVE_REVOKE: EfuseField = EfuseField::new(0, 3, 117, 1); +/// Set this bit to enable ECC for flash boot +pub const FLASH_ECC_EN: EfuseField = EfuseField::new(0, 3, 122, 1); +/// Set this bit to disable download via USB-OTG +pub const DIS_USB_OTG_DOWNLOAD_MODE: EfuseField = EfuseField::new(0, 3, 123, 1); +/// Configures flash waiting time after power-up; in unit of ms. When the value less than 15; +/// the waiting time is the configurable value. Otherwise; the waiting time is 30 +pub const FLASH_TPUW: EfuseField = EfuseField::new(0, 3, 124, 4); +/// Set this bit to disable download mode (boot_mode`[3:0]` = 0; 1; 2; 4; 5; 6; 7) +pub const DIS_DOWNLOAD_MODE: EfuseField = EfuseField::new(0, 4, 128, 1); +/// Set this bit to disable direct boot mode +pub const DIS_DIRECT_BOOT: EfuseField = EfuseField::new(0, 4, 129, 1); +/// Set this bit to disable USB-Serial-JTAG print during rom boot +pub const DIS_USB_SERIAL_JTAG_ROM_PRINT: EfuseField = EfuseField::new(0, 4, 130, 1); +/// set this bit to lock the key manager key after deploy +pub const LOCK_KM_KEY: EfuseField = EfuseField::new(0, 4, 131, 1); +/// Set this bit to disable the USB-Serial-JTAG download function +pub const DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE: EfuseField = EfuseField::new(0, 4, 132, 1); +/// Set this bit to enable security download mode +pub const ENABLE_SECURITY_DOWNLOAD: EfuseField = EfuseField::new(0, 4, 133, 1); +/// Set the type of UART printing; 00: force enable printing; 01: enable printing when GPIO8 is +/// reset at low level; 10: enable printing when GPIO8 is reset at high level; 11: force disable +/// printing +pub const UART_PRINT_CONTROL: EfuseField = EfuseField::new(0, 4, 134, 2); +/// Set this bit to force ROM code to send a resume command during SPI boot +pub const FORCE_SEND_RESUME: EfuseField = EfuseField::new(0, 4, 136, 1); +/// Secure version used by ESP-IDF anti-rollback feature +pub const SECURE_VERSION: EfuseField = EfuseField::new(0, 4, 137, 16); +/// Represents whether secure boot do fast verification on wake is disabled. 0: enabled 1: +/// disabled +pub const SECURE_BOOT_DISABLE_FAST_WAKE: EfuseField = EfuseField::new(0, 4, 153, 1); +/// Set bits to enable hysteresis function of PAD0~27 +pub const HYS_EN_PAD: EfuseField = EfuseField::new(0, 4, 154, 1); +/// Output LDO VO0 tieh source select. 0: 1'b1 1: sdmmc1 2: reg 3:sdmmc0 +pub const PXA0_TIEH_SEL_0: EfuseField = EfuseField::new(0, 5, 160, 2); +/// Represents whether to enable PVT power glitch monitor function.1:Enable. 0:Disable +pub const PVT_GLITCH_EN: EfuseField = EfuseField::new(0, 5, 162, 1); +/// EFUSE_KM_DISABLE_DEPLOY_MODE and EFUSE_KM_DISABLE_DEPLOY_MODE_H together form one field: +/// {EFUSE_KM_DISABLE_DEPLOY_MODE_H; EFUSE_KM_DISABLE_DEPLOY_MODE`[3:0]`}. Set each bit to control +/// whether corresponding key's deploy mode of new value deployment is disabled. 1 is true; 0 is +/// false. bit 0: ecsda; bit 1: xts; bit2: hmac; bit3: ds; bit4:psram +pub const KM_DISABLE_DEPLOY_MODE: EfuseField = EfuseField::new(0, 5, 167, 5); +/// Sets this bit to control the xts pseudo-round anti-dpa attack function. 0: controlled by +/// register. 1-3: the higher the value is; the more pseudo-rounds are inserted to the xts-aes +/// calculation +pub const XTS_DPA_PSEUDO_LEVEL: EfuseField = EfuseField::new(0, 5, 176, 2); +/// HP system power source select. 0:LDO 1: DCDC +pub const HP_PWR_SRC_SEL: EfuseField = EfuseField::new(0, 5, 178, 1); +/// Represents whether secure boot using SHA-384 is enabled. 0: disable 1: enable +pub const SECURE_BOOT_SHA384_EN: EfuseField = EfuseField::new(0, 5, 179, 1); +/// Set this bit to disable watch dog +pub const DIS_WDT: EfuseField = EfuseField::new(0, 5, 180, 1); +/// Set bit to disable super-watchdog +pub const DIS_SWD: EfuseField = EfuseField::new(0, 5, 181, 1); +/// Use to configure glitch mode +pub const PVT_GLITCH_MODE: EfuseField = EfuseField::new(0, 5, 182, 2); +/// `[MAC_FACTORY]` MAC address (low 32 bits) +pub const MAC0: EfuseField = EfuseField::new(1, 0, 0, 32); +/// `[MAC_FACTORY]` MAC address (high 16 bits) +pub const MAC1: EfuseField = EfuseField::new(1, 0, 32, 16); +/// Minor chip version +pub const WAFER_VERSION_MINOR: EfuseField = EfuseField::new(1, 2, 64, 4); +/// Major chip version (lower 2 bits) +pub const WAFER_VERSION_MAJOR: EfuseField = EfuseField::new(1, 2, 87, 3); +/// Disables check of wafer version major +pub const DISABLE_WAFER_VERSION_MAJOR: EfuseField = EfuseField::new(1, 2, 70, 1); +/// Disables check of blk version major +pub const DISABLE_BLK_VERSION_MAJOR: EfuseField = EfuseField::new(1, 2, 71, 1); +/// BLK_VERSION_MINOR of BLOCK2 +pub const BLK_VERSION_MINOR: EfuseField = EfuseField::new(1, 2, 72, 3); +/// BLK_VERSION_MAJOR of BLOCK2 +pub const BLK_VERSION_MAJOR: EfuseField = EfuseField::new(1, 2, 75, 2); +/// PSRAM capacity +pub const PSRAM_CAP: EfuseField = EfuseField::new(1, 2, 77, 3); +/// Operating temperature of the ESP chip +pub const TEMP: EfuseField = EfuseField::new(1, 2, 80, 2); +/// PSRAM vendor +pub const PSRAM_VENDOR: EfuseField = EfuseField::new(1, 2, 82, 2); +/// Package version +pub const PKG_VERSION: EfuseField = EfuseField::new(1, 2, 84, 3); +/// Output VO1 parameter +pub const LDO_VO1_DREF: EfuseField = EfuseField::new(1, 2, 88, 4); +/// Output VO2 parameter +pub const LDO_VO2_DREF: EfuseField = EfuseField::new(1, 2, 92, 4); +/// Output VO1 parameter +pub const LDO_VO1_MUL: EfuseField = EfuseField::new(1, 3, 96, 3); +/// Output VO2 parameter +pub const LDO_VO2_MUL: EfuseField = EfuseField::new(1, 3, 99, 3); +/// Output VO3 calibration parameter +pub const LDO_VO3_K: EfuseField = EfuseField::new(1, 3, 102, 8); +/// Output VO3 calibration parameter +pub const LDO_VO3_VOS: EfuseField = EfuseField::new(1, 3, 110, 6); +/// Output VO3 calibration parameter +pub const LDO_VO3_C: EfuseField = EfuseField::new(1, 3, 116, 6); +/// Output VO4 calibration parameter +pub const LDO_VO4_K: EfuseField = EfuseField::new(1, 3, 122, 8); +/// Output VO4 calibration parameter +pub const LDO_VO4_VOS: EfuseField = EfuseField::new(1, 4, 130, 6); +/// Output VO4 calibration parameter +pub const LDO_VO4_C: EfuseField = EfuseField::new(1, 4, 136, 6); +/// Active HP DBIAS of fixed voltage +pub const ACTIVE_HP_DBIAS: EfuseField = EfuseField::new(1, 4, 144, 4); +/// Active LP DBIAS of fixed voltage +pub const ACTIVE_LP_DBIAS: EfuseField = EfuseField::new(1, 4, 148, 4); +/// DSLP BDG of fixed voltage +pub const DSLP_DBG: EfuseField = EfuseField::new(1, 4, 156, 4); +/// DSLP LP DBIAS of fixed voltage +pub const DSLP_LP_DBIAS: EfuseField = EfuseField::new(1, 5, 160, 5); +/// DBIAS gap between LP and DCDC +pub const LP_DCDC_DBIAS_VOL_GAP: EfuseField = EfuseField::new(1, 5, 165, 5); +/// PVT_DCM_VSET when the CPU is at 400M +pub const PVT_400M_BIAS: EfuseField = EfuseField::new(1, 5, 171, 5); +/// PVT_DCM_VSET corresponding to about 0.9V fixed voltage when the CPU is at 40M +pub const PVT_40M_BIAS: EfuseField = EfuseField::new(1, 5, 176, 5); +/// PVT_DCM_VSET corresponding to about 1.0V fixed voltage when the CPU is at 100M +pub const PVT_100M_BIAS: EfuseField = EfuseField::new(1, 5, 181, 5); +/// Optional unique 128-bit ID +pub const OPTIONAL_UNIQUE_ID: EfuseField = EfuseField::new(2, 0, 0, 128); +/// Average initcode of ADC1 atten0 +pub const ADC1_AVE_INITCODE_ATTEN0: EfuseField = EfuseField::new(2, 4, 128, 10); +/// Average initcode of ADC1 atten1 +pub const ADC1_AVE_INITCODE_ATTEN1: EfuseField = EfuseField::new(2, 4, 138, 10); +/// Average initcode of ADC1 atten2 +pub const ADC1_AVE_INITCODE_ATTEN2: EfuseField = EfuseField::new(2, 4, 148, 10); +/// Average initcode of ADC1 atten3 +pub const ADC1_AVE_INITCODE_ATTEN3: EfuseField = EfuseField::new(2, 4, 158, 10); +/// Average initcode of ADC2 atten0 +pub const ADC2_AVE_INITCODE_ATTEN0: EfuseField = EfuseField::new(2, 5, 168, 10); +/// Average initcode of ADC2 atten1 +pub const ADC2_AVE_INITCODE_ATTEN1: EfuseField = EfuseField::new(2, 5, 178, 10); +/// Average initcode of ADC2 atten2 +pub const ADC2_AVE_INITCODE_ATTEN2: EfuseField = EfuseField::new(2, 5, 188, 10); +/// Average initcode of ADC2 atten3 +pub const ADC2_AVE_INITCODE_ATTEN3: EfuseField = EfuseField::new(2, 6, 198, 10); +/// HI_DOUT of ADC1 atten0 +pub const ADC1_HI_DOUT_ATTEN0: EfuseField = EfuseField::new(2, 6, 208, 10); +/// HI_DOUT of ADC1 atten1 +pub const ADC1_HI_DOUT_ATTEN1: EfuseField = EfuseField::new(2, 6, 218, 10); +/// HI_DOUT of ADC1 atten2 +pub const ADC1_HI_DOUT_ATTEN2: EfuseField = EfuseField::new(2, 7, 228, 10); +/// HI_DOUT of ADC1 atten3 +pub const ADC1_HI_DOUT_ATTEN3: EfuseField = EfuseField::new(2, 7, 238, 10); +/// `[BLOCK_USR_DATA]` User data +pub const USER_DATA: EfuseField = EfuseField::new(3, 0, 0, 256); +/// `[MAC_CUSTOM CUSTOM_MAC]` Custom MAC +pub const USER_DATA_MAC_CUSTOM: EfuseField = EfuseField::new(3, 6, 200, 48); +/// `[BLOCK_KEY0]` Key0 or user data +pub const KEY0: EfuseField = EfuseField::new(4, 0, 0, 256); +/// `[BLOCK_KEY1]` Key1 or user data +pub const KEY1: EfuseField = EfuseField::new(5, 0, 0, 256); +/// `[BLOCK_KEY2]` Key2 or user data +pub const KEY2: EfuseField = EfuseField::new(6, 0, 0, 256); +/// `[BLOCK_KEY3]` Key3 or user data +pub const KEY3: EfuseField = EfuseField::new(7, 0, 0, 256); +/// `[BLOCK_KEY4]` Key4 or user data +pub const KEY4: EfuseField = EfuseField::new(8, 0, 0, 256); +/// `[BLOCK_KEY5]` Key5 or user data +pub const KEY5: EfuseField = EfuseField::new(9, 0, 0, 256); +/// HI_DOUT of ADC2 atten0 +pub const ADC2_HI_DOUT_ATTEN0: EfuseField = EfuseField::new(10, 0, 0, 10); +/// HI_DOUT of ADC2 atten1 +pub const ADC2_HI_DOUT_ATTEN1: EfuseField = EfuseField::new(10, 0, 10, 10); +/// HI_DOUT of ADC2 atten2 +pub const ADC2_HI_DOUT_ATTEN2: EfuseField = EfuseField::new(10, 0, 20, 10); +/// HI_DOUT of ADC2 atten3 +pub const ADC2_HI_DOUT_ATTEN3: EfuseField = EfuseField::new(10, 0, 30, 10); +/// Gap between ADC1_ch0 and average initcode +pub const ADC1_CH0_ATTEN0_INITCODE_DIFF: EfuseField = EfuseField::new(10, 1, 40, 4); +/// Gap between ADC1_ch1 and average initcode +pub const ADC1_CH1_ATTEN0_INITCODE_DIFF: EfuseField = EfuseField::new(10, 1, 44, 4); +/// Gap between ADC1_ch2 and average initcode +pub const ADC1_CH2_ATTEN0_INITCODE_DIFF: EfuseField = EfuseField::new(10, 1, 48, 4); +/// Gap between ADC1_ch3 and average initcode +pub const ADC1_CH3_ATTEN0_INITCODE_DIFF: EfuseField = EfuseField::new(10, 1, 52, 4); +/// Gap between ADC1_ch4 and average initcode +pub const ADC1_CH4_ATTEN0_INITCODE_DIFF: EfuseField = EfuseField::new(10, 1, 56, 4); +/// Gap between ADC1_ch5 and average initcode +pub const ADC1_CH5_ATTEN0_INITCODE_DIFF: EfuseField = EfuseField::new(10, 1, 60, 4); +/// Gap between ADC1_ch6 and average initcode +pub const ADC1_CH6_ATTEN0_INITCODE_DIFF: EfuseField = EfuseField::new(10, 2, 64, 4); +/// Gap between ADC1_ch7 and average initcode +pub const ADC1_CH7_ATTEN0_INITCODE_DIFF: EfuseField = EfuseField::new(10, 2, 68, 4); +/// Gap between ADC2_ch0 and average initcode +pub const ADC2_CH0_ATTEN0_INITCODE_DIFF: EfuseField = EfuseField::new(10, 2, 72, 4); +/// Gap between ADC2_ch1 and average initcode +pub const ADC2_CH1_ATTEN0_INITCODE_DIFF: EfuseField = EfuseField::new(10, 2, 76, 4); +/// Gap between ADC2_ch2 and average initcode +pub const ADC2_CH2_ATTEN0_INITCODE_DIFF: EfuseField = EfuseField::new(10, 2, 80, 4); +/// Gap between ADC2_ch3 and average initcode +pub const ADC2_CH3_ATTEN0_INITCODE_DIFF: EfuseField = EfuseField::new(10, 2, 84, 4); +/// Gap between ADC2_ch4 and average initcode +pub const ADC2_CH4_ATTEN0_INITCODE_DIFF: EfuseField = EfuseField::new(10, 2, 88, 4); +/// Gap between ADC2_ch5 and average initcode +pub const ADC2_CH5_ATTEN0_INITCODE_DIFF: EfuseField = EfuseField::new(10, 2, 92, 4); +/// Temperature calibration data +pub const TEMPERATURE_SENSOR: EfuseField = EfuseField::new(10, 3, 96, 10); +/// Enable usb device exchange pins of D+ and D- +pub const USB_DEVICE_EXCHG_PINS: EfuseField = EfuseField::new(10, 7, 228, 1); +/// Enable usb otg11 exchange pins of D+ and D- +pub const USB_OTG11_EXCHG_PINS: EfuseField = EfuseField::new(10, 7, 229, 1); diff --git a/esp-hal/src/efuse/esp32p4/mod.rs b/esp-hal/src/efuse/esp32p4/mod.rs new file mode 100644 index 00000000000..e519d8c9504 --- /dev/null +++ b/esp-hal/src/efuse/esp32p4/mod.rs @@ -0,0 +1,68 @@ +//! # Reading of eFuses (ESP32-P4) + +use crate::peripherals::EFUSE; + +#[cfg_attr(not(feature = "unstable"), allow(dead_code))] +mod fields; +#[instability::unstable] +pub use fields::*; + +/// Get status of SPI boot encryption. +#[instability::unstable] +pub fn flash_encryption() -> bool { + !super::read_field_le::(SPI_BOOT_CRYPT_CNT) + .count_ones() + .is_multiple_of(2) +} + +/// Get the multiplier for the timeout value of the RWDT STAGE 0 register. +#[instability::unstable] +pub fn rwdt_multiplier() -> u8 { + super::read_field_le::(WDT_DELAY_SEL) +} + +/// Returns the major hardware revision +pub(crate) fn major_chip_version() -> u8 { + super::read_field_le(WAFER_VERSION_MAJOR) +} + +/// Returns the minor hardware revision +pub(crate) fn minor_chip_version() -> u8 { + super::read_field_le(WAFER_VERSION_MINOR) +} + +#[derive(Debug, Clone, Copy, strum::FromRepr)] +#[repr(u32)] +pub(crate) enum EfuseBlock { + Block0, + Block1, + Block2, + Block3, + Block4, + Block5, + Block6, + Block7, + Block8, + Block9, + Block10, +} + +impl EfuseBlock { + pub(crate) fn address(self) -> *const u32 { + use EfuseBlock::*; + let efuse = EFUSE::regs(); + match self { + Block0 => efuse.rd_wr_dis().as_ptr(), + Block1 => efuse.rd_mac_sys_0().as_ptr(), + Block2 => efuse.rd_sys_part1_data0().as_ptr(), + Block3 => efuse.rd_usr_data0().as_ptr(), + Block4 => efuse.rd_key0_data0().as_ptr(), + Block5 => efuse.rd_key1_data0().as_ptr(), + Block6 => efuse.rd_key2_data0().as_ptr(), + Block7 => efuse.rd_key3_data0().as_ptr(), + Block8 => efuse.rd_key4_data0().as_ptr(), + Block9 => efuse.rd_key5_data0().as_ptr(), + Block10 => efuse.rd_sys_part2_data0().as_ptr(), + } + } +} diff --git a/esp-hal/src/efuse/mod.rs b/esp-hal/src/efuse/mod.rs index 35739bdf2cb..cb6b0c8b67c 100644 --- a/esp-hal/src/efuse/mod.rs +++ b/esp-hal/src/efuse/mod.rs @@ -44,6 +44,7 @@ use portable_atomic::AtomicU8; #[cfg_attr(esp32c6, path = "esp32c6/mod.rs")] #[cfg_attr(esp32c61, path = "esp32c61/mod.rs")] #[cfg_attr(esp32h2, path = "esp32h2/mod.rs")] +#[cfg_attr(esp32p4, path = "esp32p4/mod.rs")] #[cfg_attr(esp32s2, path = "esp32s2/mod.rs")] #[cfg_attr(esp32s3, path = "esp32s3/mod.rs")] pub(crate) mod implem; diff --git a/esp-hal/src/gpio/interrupt.rs b/esp-hal/src/gpio/interrupt.rs index df7c0451c3e..a63071f5698 100644 --- a/esp-hal/src/gpio/interrupt.rs +++ b/esp-hal/src/gpio/interrupt.rs @@ -231,6 +231,13 @@ impl InterruptStatusRegisterAccess { Self::Bank0 => GPIO::regs().status().read().bits(), Self::Bank1 => GPIO::regs().status1().read().bits(), } + } else if #[cfg(esp32p4)] { + // P4 PAC: intr_0() (Core0 GPIO interrupt status) + match self { + Self::Bank0 => GPIO::regs().intr_0().read().bits(), + #[cfg(gpio_has_bank_1)] + Self::Bank1 => GPIO::regs().intr1_0().read().bits(), + } } else { match self { Self::Bank0 => GPIO::regs().pcpu_int().read().bits(), diff --git a/esp-hal/src/gpio/mod.rs b/esp-hal/src/gpio/mod.rs index 3dd791380a3..d89baf910ca 100644 --- a/esp-hal/src/gpio/mod.rs +++ b/esp-hal/src/gpio/mod.rs @@ -371,7 +371,7 @@ pub trait RtcPin: Pin { fn rtc_number(&self) -> u8; /// Configure the pin - #[cfg(any(xtensa, esp32c6))] + #[cfg(any(xtensa, esp32c6, esp32p4))] #[doc(hidden)] fn rtc_set_config(&self, input_enable: bool, mux: bool, func: RtcFunction); @@ -383,7 +383,7 @@ pub trait RtcPin: Pin { /// /// The `level` argument needs to be a valid setting for the /// `rtc_cntl.gpio_wakeup.gpio_pinX_int_type`. - #[cfg(any(esp32c3, esp32c2, esp32c6))] + #[cfg(any(esp32c3, esp32c2, esp32c6, esp32p4))] #[doc(hidden)] unsafe fn apply_wakeup(&self, wakeup: bool, level: u8); } @@ -2266,7 +2266,7 @@ impl RtcPin for AnyPin<'_> { } } - #[cfg(any(xtensa, esp32c6))] + #[cfg(any(xtensa, esp32c6, esp32p4))] fn rtc_set_config(&self, input_enable: bool, mux: bool, func: RtcFunction) { for_each_rtcio_pin! { (self, target) => { RtcPin::rtc_set_config(&target, input_enable, mux, func) }; @@ -2279,7 +2279,7 @@ impl RtcPin for AnyPin<'_> { } } - #[cfg(any(esp32c2, esp32c3, esp32c6))] + #[cfg(any(esp32c2, esp32c3, esp32c6, esp32p4))] unsafe fn apply_wakeup(&self, wakeup: bool, level: u8) { for_each_rtcio_pin! { (self, target) => { unsafe { RtcPin::apply_wakeup(&target, wakeup, level) } }; diff --git a/esp-hal/src/i2c/master/mod.rs b/esp-hal/src/i2c/master/mod.rs index 67bdce1dc69..b533c1e2b41 100644 --- a/esp-hal/src/i2c/master/mod.rs +++ b/esp-hal/src/i2c/master/mod.rs @@ -3360,6 +3360,16 @@ fn write_fifo(register_block: &RegisterBlock, data: u8) { unsafe { fifo_ptr.write_volatile(data as u32); } + } else if #[cfg(esp32p4)] { + // P4: data register is read-only (RX FIFO only). TX uses txfifo_start_addr. + // PAC txfifo_start_addr is also read-only in SVD, use direct MMIO. + // TODO: file an esp-pacs issue/PR so the P4 SVD marks the TX FIFO + // port writable like other chips' I2C PAC. Once that lands, this + // branch can collapse into the general `else` arm below. + let base = register_block as *const _ as usize; + unsafe { + ((base + 0x100) as *mut u32).write_volatile(data as u32); + } } else { register_block .data() diff --git a/esp-hal/src/interrupt/mod.rs b/esp-hal/src/interrupt/mod.rs index c9f48f7dd93..d999cd860cc 100644 --- a/esp-hal/src/interrupt/mod.rs +++ b/esp-hal/src/interrupt/mod.rs @@ -52,6 +52,9 @@ cfg_if::cfg_if! { use crate::peripherals::DPORT as INTERRUPT_CORE0; use crate::peripherals::DPORT as INTERRUPT_CORE1; } else { + // P4 reads these registers via raw MMIO, not through the PAC singletons, + // so the INTERRUPT_CORE0/1 imports aren't needed there. + #[cfg(not(esp32p4))] use crate::peripherals::INTERRUPT_CORE0; #[cfg(esp32s3)] use crate::peripherals::INTERRUPT_CORE1; @@ -66,6 +69,8 @@ mod xtensa; use crate::pac; unstable_driver! { + // TODO: Remove this workaround of P4 and resolve true reason. + #[cfg(not(esp32p4))] pub mod software; } @@ -198,19 +203,42 @@ impl InterruptStatus { match Cpu::current() { Cpu::ProCpu => InterruptStatus { status: core::array::from_fn(|idx| { - INTERRUPT_CORE0::regs() - .core_0_intr_status(idx) - .read() - .bits() + // P4: Status registers at base + 0x200 (4 x 32-bit = 128 sources) + // INTERRUPT_CORE0_INTR_STATUS_REG_0_REG = base + 0x200 + // INTERRUPT_CORE0_INTR_STATUS_REG_1_REG = base + 0x204 + // INTERRUPT_CORE0_INTR_STATUS_REG_2_REG = base + 0x208 + // INTERRUPT_CORE0_INTR_STATUS_REG_3_REG = base + 0x20c + #[cfg(esp32p4)] + { + let base = crate::soc::registers::INTERRUPT_MAP_BASE + 0x200; + unsafe { ((base as *const u32).add(idx)).read_volatile() } + } + #[cfg(not(esp32p4))] + { + INTERRUPT_CORE0::regs() + .core_0_intr_status(idx) + .read() + .bits() + } }), }, #[cfg(multi_core)] Cpu::AppCpu => InterruptStatus { status: core::array::from_fn(|idx| { - INTERRUPT_CORE1::regs() - .core_1_intr_status(idx) - .read() - .bits() + // P4 Core1: base + 0x800 + 0x200 + // INTERRUPT_CORE1 = INTERRUPT_CORE0 + 0x800 + #[cfg(esp32p4)] + { + let base = crate::soc::registers::INTERRUPT_MAP_BASE_APP_CPU + 0x200; + unsafe { ((base as *const u32).add(idx)).read_volatile() } + } + #[cfg(not(esp32p4))] + { + INTERRUPT_CORE1::regs() + .core_1_intr_status(idx) + .read() + .bits() + } }), }, } @@ -352,6 +380,23 @@ pub fn disable(core: Cpu, interrupt: Interrupt) { } pub(super) fn map_raw(core: Cpu, interrupt: Interrupt, cpu_interrupt: u32) { + // P4: 120 individual INT_MAP registers at sequential 4-byte offsets from base. + // Each register has 6-bit field [5:0] for CPU interrupt line (0-63). + // Core0: base = 0x500D_6000, Core1: base = 0x500D_6800 + // LP_WDT_INT_MAP_REG at offset 0x4, etc. + #[cfg(esp32p4)] + { + let base = match core { + Cpu::ProCpu => crate::soc::registers::INTERRUPT_MAP_BASE, + #[cfg(multi_core)] + Cpu::AppCpu => crate::soc::registers::INTERRUPT_MAP_BASE_APP_CPU, + }; + unsafe { + let reg = (base as *mut u32).add(interrupt as usize); + reg.write_volatile(cpu_interrupt); + } + } + #[cfg(not(esp32p4))] match core { Cpu::ProCpu => { INTERRUPT_CORE0::regs() @@ -373,6 +418,20 @@ pub(crate) fn mapped_to(cpu: Cpu, interrupt: Interrupt) -> Option } pub(crate) fn mapped_to_raw(cpu: Cpu, interrupt: u32) -> Option { + // P4: read INT_MAP register directly. 6-bit field [5:0] = CPU interrupt line. + #[cfg(esp32p4)] + let cpu_intr = { + let base = match cpu { + Cpu::ProCpu => crate::soc::registers::INTERRUPT_MAP_BASE, + #[cfg(multi_core)] + Cpu::AppCpu => crate::soc::registers::INTERRUPT_MAP_BASE_APP_CPU, + }; + unsafe { + let reg = (base as *const u32).add(interrupt as usize); + reg.read_volatile() & 0x3F // 6-bit field + } + }; + #[cfg(not(esp32p4))] let cpu_intr = match cpu { Cpu::ProCpu => INTERRUPT_CORE0::regs() .core_0_intr_map(interrupt as usize) diff --git a/esp-hal/src/interrupt/riscv.rs b/esp-hal/src/interrupt/riscv.rs index acfba33ee2d..ac64f343d0c 100644 --- a/esp-hal/src/interrupt/riscv.rs +++ b/esp-hal/src/interrupt/riscv.rs @@ -312,6 +312,15 @@ pub fn enable_direct( let clic = unsafe { crate::soc::pac::CLIC::steal() }; // Enable hardware vectoring + #[cfg(esp32p4)] + clic.int_ctrl(cpu_interrupt as usize).modify(|_, w| unsafe { + // P4: CLIC uses consolidated int_ctrl register (not separate int_attr). + // int_ctrl contains: int_ip[0], int_ie[8], int_attr_shv[16], + // int_attr_trig[17:18], int_attr_mode[22:23], int_ctl[24:31] + w.int_attr_shv().set_bit(); + w.int_attr_trig().bits(0) // positive level + }); + #[cfg(not(esp32p4))] clic.int_attr(cpu_interrupt as usize).modify(|_, w| { w.shv().hardware(); w.trig().positive_level() @@ -409,6 +418,18 @@ fn cpu_wait_mode_on() -> bool { cfg_if::cfg_if! { if #[cfg(soc_has_pcr)] { crate::peripherals::PCR::regs().cpu_waiti_conf().read().cpu_wait_mode_force_on().bit_is_set() + } else if #[cfg(all(multi_core, soc_has_hp_sys_clkrst))] { + // AMP-aware: read this core's CORE{N}_WAITI_ICG_EN bit in + // HP_SYS_CLKRST.CPU_WAITI_CTRL0 (hw_ver3). Each core answers + // locally, so AMP setups where cores run different firmware get + // the right per-core result. + // ICG_EN = 1 -> this core's WFI may gate clock -> NOT safe + // ICG_EN = 0 -> WFI will not gate -> safe + // TODO: add HP_SYS_CLKRST.CPU_WAITI_CTRL0 (offset 0xF4) to the + // esp32p4 PAC and replace this raw MMIO with the PAC accessor. + const HP_SYS_CLKRST_CPU_WAITI_CTRL0: *const u32 = 0x500E_60F4 as *const u32; + let reg = unsafe { core::ptr::read_volatile(HP_SYS_CLKRST_CPU_WAITI_CTRL0) }; + (reg & (1 << Cpu::current() as u32)) == 0 } else { crate::peripherals::SYSTEM::regs() .cpu_per_conf() diff --git a/esp-hal/src/interrupt/riscv/clic.rs b/esp-hal/src/interrupt/riscv/clic.rs index 65fafca0c1a..ae6b5f688d9 100644 --- a/esp-hal/src/interrupt/riscv/clic.rs +++ b/esp-hal/src/interrupt/riscv/clic.rs @@ -1,3 +1,15 @@ +// CLIC v1.x and v2.x currently coexist in this file. Depending on +// ESP32-P4 mass production results and future esp-rs/esp-pacs patches, +// this file may be split into clic_v1.rs / clic_v2.rs, or kept as is. +// +// TODO: keep tracking future P4 revision to check changes of CLIC. +// +// ESP32P4 follows pulp CLIC version 1.x +// ref : https://github.com/pulp-platform/clic/blob/v1.0.1/src/gen/clic.hjson.tpl +// +// ESP32C5, C61 follow pulp CLIC version 2.x +// ref : https://github.com/pulp-platform/clic/blob/v2.0.0/src/gen/mclic.hjson + use super::{InterruptKind, Priority, RunLevel}; use crate::{interrupt::ElevatedRunLevel, soc::pac::CLIC}; @@ -5,34 +17,71 @@ use crate::{interrupt::ElevatedRunLevel, soc::pac::CLIC}; pub(super) fn init() { let clic = unsafe { CLIC::steal() }; - // Set 3 level bits = 8 priority levels - clic.int_config() - .modify(|_, w| unsafe { w.mnlbits().bits(3) }); + // 3 level bits = 8 priority levels. + cfg_if::cfg_if! { + if #[cfg(esp32p4)] { + clic.int_config() + .modify(|_, w| unsafe { w.int_config_nlbits().bits(3) }); + } else { + clic.int_config() + .modify(|_, w| unsafe { w.mnlbits().bits(3) }); + } + } - // Enable hardware vectoring - for int in clic.int_attr_iter() { - int.modify(|_, w| { - w.shv().hardware(); - w.trig().positive_level() - }); + // Enable hardware vectoring on every interrupt line. + cfg_if::cfg_if! { + if #[cfg(esp32p4)] { + for int in clic.int_ctrl_iter() { + int.modify(|_, w| unsafe { + w.int_attr_shv().set_bit(); + w.int_attr_trig().bits(0) // positive level + }); + } + } else { + for int in clic.int_attr_iter() { + int.modify(|_, w| { + w.shv().hardware(); + w.trig().positive_level() + }); + } + } } } pub(super) fn enable_cpu_interrupt_raw(cpu_interrupt: u32) { // Lower 16 interrupts are reserved for CLINT, which is currently not implemented. let clic = unsafe { CLIC::steal() }; - clic.int_ie(cpu_interrupt as usize) - .write(|w| w.int_ie().set_bit()); + cfg_if::cfg_if! { + if #[cfg(esp32p4)] { + clic.int_ctrl(cpu_interrupt as usize) + .modify(|_, w| w.int_ie().set_bit()); + } else { + clic.int_ie(cpu_interrupt as usize) + .write(|w| w.int_ie().set_bit()); + } + } } pub(super) fn set_kind_raw(cpu_interrupt: u32, kind: InterruptKind) { // Lower 16 interrupts are reserved for CLINT, which is currently not implemented. let clic = unsafe { CLIC::steal() }; - clic.int_attr(cpu_interrupt as usize) - .modify(|_, w| match kind { - InterruptKind::Level => w.trig().positive_level(), - InterruptKind::Edge => w.trig().positive_edge(), - }); + cfg_if::cfg_if! { + if #[cfg(esp32p4)] { + clic.int_ctrl(cpu_interrupt as usize) + .modify(|_, w| unsafe { + w.int_attr_trig().bits(match kind { + InterruptKind::Level => 0, // positive level + InterruptKind::Edge => 1, // positive edge + }) + }); + } else { + clic.int_attr(cpu_interrupt as usize) + .modify(|_, w| match kind { + InterruptKind::Level => w.trig().positive_level(), + InterruptKind::Edge => w.trig().positive_edge(), + }); + } + } } pub(super) fn set_priority_raw(cpu_interrupt: u32, priority: Priority) { @@ -43,21 +92,41 @@ pub(super) fn set_priority_raw(cpu_interrupt: u32, priority: Priority) { ))); // The `ctl` field would only write the 3 programmable bits, but we have the correct final // value anyway so let's write it directly. - clic.int_ctl(cpu_interrupt as usize) - .write(|w| unsafe { w.bits(prio_bits) }); + cfg_if::cfg_if! { + if #[cfg(esp32p4)] { + clic.int_ctrl(cpu_interrupt as usize) + .modify(|_, w| unsafe { w.int_ctl().bits(prio_bits) }); + } else { + clic.int_ctl(cpu_interrupt as usize) + .write(|w| unsafe { w.bits(prio_bits) }); + } + } } pub(super) fn clear_raw(cpu_interrupt: u32) { // Lower 16 interrupts are reserved for CLINT, which is currently not implemented. let clic = unsafe { CLIC::steal() }; - clic.int_ip(cpu_interrupt as usize) - .write(|w| w.int_ip().clear_bit()); + cfg_if::cfg_if! { + if #[cfg(esp32p4)] { + clic.int_ctrl(cpu_interrupt as usize) + .modify(|_, w| w.int_ip().clear_bit()); + } else { + clic.int_ip(cpu_interrupt as usize) + .write(|w| w.int_ip().clear_bit()); + } + } } pub(super) fn cpu_interrupt_priority_raw(cpu_interrupt: u32) -> u8 { // Lower 16 interrupts are reserved for CLINT, which is currently not implemented. let clic = unsafe { CLIC::steal() }; - let prio_level = clic.int_ctl(cpu_interrupt as usize).read().bits() as usize; + cfg_if::cfg_if! { + if #[cfg(esp32p4)] { + let prio_level = clic.int_ctrl(cpu_interrupt as usize).read().int_ctl().bits() as usize; + } else { + let prio_level = clic.int_ctl(cpu_interrupt as usize).read().bits() as usize; + } + } bits_to_prio(prio_level) } diff --git a/esp-hal/src/lib.rs b/esp-hal/src/lib.rs index ad327ce23b6..156792c16ff 100644 --- a/esp-hal/src/lib.rs +++ b/esp-hal/src/lib.rs @@ -197,7 +197,11 @@ fn main() -> ! { #![doc(html_logo_url = "https://avatars.githubusercontent.com/u/46717278")] #![allow(asm_sub_register, async_fn_in_trait, stable_features)] #![cfg_attr(xtensa, feature(asm_experimental_arch))] -#![deny(missing_docs, rust_2018_idioms, rustdoc::all)] +// TODO(esp32p4): fill `[device.clock_tree]` doc strings in esp32p4.toml, +// then promote back to `deny`. Until then, downgrade to warn for P4 only. +#![cfg_attr(not(esp32p4), deny(missing_docs))] +#![cfg_attr(esp32p4, warn(missing_docs))] +#![deny(rust_2018_idioms, rustdoc::all)] #![allow(rustdoc::private_doc_tests)] // compile tests are done via rustdoc #![cfg_attr(docsrs, feature(doc_cfg, custom_inner_attributes, proc_macro_hygiene))] // Don't trip up on broken/private links when running semver-checks diff --git a/esp-hal/src/psram/esp32p4.rs b/esp-hal/src/psram/esp32p4.rs new file mode 100644 index 00000000000..5d04a7c202f --- /dev/null +++ b/esp-hal/src/psram/esp32p4.rs @@ -0,0 +1,933 @@ +//! PSRAM driver for ESP32-P4X (chip revision v3.x / ECO5+). +//! +//! P4 has two PSRAM controllers wired to the same DQ pads +//! The structure is looks same with DDR controller but not same. + +// Several ROM cache helpers and MMIO wrappers are staged for follow-up +// PSRAM bring-up work (cache suspend/resume around config writes). +// They're intentionally retained so the follow-up PR can wire them in +// without re-deriving the constants. +#![allow(dead_code)] + +/// PSRAM virtual address range (cached) +pub const PSRAM_VADDR_START: usize = 0x4800_0000; + +/// MMU page size (64 KB) +const MMU_PAGE_SIZE: usize = 0x10000; + +/// PSRAM_MSPI0 base, AXI cache controller. +/// CAUTION: Missing area of TRM. +const MSPI0_BASE: u32 = 0x5008_E000; + +/// PSRAM_MSPI1 base, direct-command controller. +/// CAUTION: Missing area of TRM. +const MSPI1_BASE: u32 = 0x5008_F000; + +/// Volatile 32-bit read. +#[inline(always)] +unsafe fn mmio_read_32(addr: u32) -> u32 { + unsafe { (addr as *const u32).read_volatile() } +} + +/// Volatile 32-bit write (full overwrite). +#[inline(always)] +unsafe fn mmio_write_32(addr: u32, val: u32) { + unsafe { (addr as *mut u32).write_volatile(val) } +} + +/// Read-modify-write: set every bit of `mask`. Equivalent to +/// `*addr |= mask`. +#[inline(always)] +unsafe fn mmio_setbits_32(addr: u32, mask: u32) { + unsafe { mmio_write_32(addr, mmio_read_32(addr) | mask) } +} + +/// Read-modify-write: clear every bit of `mask`. Equivalent to +/// `*addr &= !mask`. +#[inline(always)] +unsafe fn mmio_clrbits_32(addr: u32, mask: u32) { + unsafe { mmio_write_32(addr, mmio_read_32(addr) & !mask) } +} + +/// Read-modify-write: clear `clear`-bits then set `set`-bits. +/// Equivalent to `*addr = (*addr & !clear) | set`. +#[inline(always)] +unsafe fn mmio_clrsetbits_32(addr: u32, clear: u32, set: u32) { + unsafe { mmio_write_32(addr, (mmio_read_32(addr) & !clear) | set) } +} + +/// PSRAM interface mode (line count of the data bus). Mirrors IDF's +/// `CONFIG_SPIRAM_MODE_*`. +/// +/// Only `Hex` is currently exercised by this driver; selecting `Oct` +/// requires the cache-side controller config (`mem_sdin_hex` / +/// `mem_sdout_hex` bits) and chip MR8.x16 to flip together. Wire that +/// path before exposing. +#[derive(Copy, Clone, Debug, Default, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[instability::unstable] +pub enum PsramMode { + /// 16-line DDR, AP HEX PSRAM with MR8.x16 = 1. Default. + #[default] + Hex, + /// 8-line DDR, MR8.x16 = 0. Not yet implemented in this driver. + Oct, +} + +/// PSRAM bus frequency. Choice ties together MPLL freq + bus divider +/// + chip-side read/write latency (each `SpiRamFreq` corresponds to a +/// `(MPLL, div, RL, WL, RD_dummy_bits, WR_dummy_bits)` tuple). +/// +/// Variants referenced from `CONFIG_SPIRAM_SPEED_*`. +/// +/// | Variant | MPLL | div | MR0.RL | MR4.WL | RD dummy bits | Use case | +/// |-----------|------|-----|--------|--------|---------------|----------| +/// | `Mhz20` | 400 | 20 | 2 | 2 | 18 | Low-power / debug | +/// | `Mhz80` | 320 | 4 | 2 | 2 | 18 | Conservative SI margin | +/// | `Mhz200` | 400 | 2 | 4 | 1 | 26 | IDF default | +/// | `Mhz250` | 500 | 2 | 6 | 3 | 34 | Overclock, **silicon rev v3+ only** | +#[derive(Copy, Clone, Debug, Default, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[instability::unstable] +pub enum SpiRamFreq { + /// 20 MHz bus (MPLL 400 / div 20). Lowest-power option; + /// rarely used outside debug. + Mhz20 = 20, + /// 80 MHz bus (MPLL 320 / div 4). Conservative; widest timing + /// margin. + Mhz80 = 80, + /// 200 MHz bus (MPLL 400 / div 2). IDF default for AP HEX PSRAM. + /// Validated on the EV board. + #[default] + Mhz200 = 200, + /// 250 MHz bus (MPLL 500 / div 2). Top speed, silicon rev v3+ only. + Mhz250 = 250, +} + +/// MPLL target frequency override. +/// +/// IDF only programs three discrete MPLL frequencies for the PSRAM +/// clock domain (`MSPI_TIMING_MPLL_FREQ_MHZ` in +/// `mspi_timing_tuning_configs.h`): +/// +/// - `Mhz320` -> paired with `SpiRamFreq::Mhz80` +/// - `Mhz400` -> paired with `SpiRamFreq::Mhz20` / `Mhz200` +/// - `Mhz500` -> paired with `SpiRamFreq::Mhz250` (silicon v3+) +/// +/// The MPLL itself can in principle be set to any value that satisfies +/// the formula `XTAL(40) * (div+1) / (ref_div+1)`, but only these three +/// have been silicon-validated. +#[derive(Copy, Clone, Debug, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[instability::unstable] +pub enum MpllFreq { + /// 320 MHz. IDF pairing: `SpiRamFreq::Mhz80`. + Mhz320 = 320, + /// 400 MHz. IDF pairing: `SpiRamFreq::Mhz20` or `Mhz200`. Default + /// when `core_clock = None` and `ram_frequency = Mhz200`. + Mhz400 = 400, + /// 500 MHz. IDF pairing: `SpiRamFreq::Mhz250` (silicon v3.0+). + Mhz500 = 500, +} + +/// PSRAM configuration. +#[derive(Copy, Clone, Debug, Default, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[instability::unstable] +pub struct PsramConfig { + /// PSRAM interface mode (Hex 16-line vs Oct 8-line). Default: Hex. + pub mode: PsramMode, + /// Size of PSRAM to map. Default: `AutoDetect` via MR2 density. + pub size: super::PsramSize, + /// MPLL override. `None` (default) derives the MPLL frequency + /// from `ram_frequency` per the table on `SpiRamFreq`. + pub core_clock: Option, + /// PSRAM bus frequency. Default: 200 MHz. + pub ram_frequency: SpiRamFreq, + // TODO: ECC enable. + // The MSPI0 controller has a ECC engine. + // pub ecc: bool, // or any other enum. +} + +/// Initialize PSRAM. +pub(crate) fn init_psram(config: &mut PsramConfig) -> bool { + init_psram_inner(config); + true +} + +pub(crate) fn map_psram(config: PsramConfig) -> core::ops::Range { + let size = config.size.get(); + PSRAM_VADDR_START..PSRAM_VADDR_START + size +} + +/// Per-speed timing parameters. Mirrors IDF's `#if CONFIG_SPIRAM_SPEED_*` +/// branches in `esp_psram_impl_ap_hex.c` + `mspi_timing_tuning_configs.h`. +#[derive(Copy, Clone)] +struct SpeedParams { + /// MPLL freq the analog block must run at. + mpll_mhz: u32, + /// Bus clock divider applied to MPLL. + bus_div: u32, + /// MR0.read_latency field value (cycles = 2 * value + 6). + mr0_rl: u8, + /// MR4.wr_latency field value. + mr4_wl: u8, + /// Read dummy length in bits for sync data reads (cache path). + rd_dummy_bits: u32, + /// Write dummy length in bits for sync data writes (cache path). + wr_dummy_bits: u32, + /// Register-read dummy length for direct command path (MSPI3). + reg_dummy_bits: u32, +} + +impl SpeedParams { + const fn for_freq(f: SpiRamFreq) -> Self { + match f { + SpiRamFreq::Mhz20 => Self { + mpll_mhz: 400, + bus_div: 20, + mr0_rl: 2, + mr4_wl: 2, + rd_dummy_bits: 18, // 2*(10-1) + wr_dummy_bits: 8, // 2*(5-1) + reg_dummy_bits: 8, // 2*(5-1) + }, + SpiRamFreq::Mhz80 => Self { + mpll_mhz: 320, + bus_div: 4, + mr0_rl: 2, + mr4_wl: 2, + rd_dummy_bits: 18, + wr_dummy_bits: 8, + reg_dummy_bits: 8, + }, + SpiRamFreq::Mhz200 => Self { + mpll_mhz: 400, + bus_div: 2, + mr0_rl: 4, + mr4_wl: 1, + rd_dummy_bits: 26, // 2*(14-1) + wr_dummy_bits: 12, // 2*(7-1) + reg_dummy_bits: 12, + }, + SpiRamFreq::Mhz250 => Self { + mpll_mhz: 500, + bus_div: 2, + mr0_rl: 6, + mr4_wl: 3, + rd_dummy_bits: 34, // 2*(18-1) + wr_dummy_bits: 16, // 2*(9-1) + reg_dummy_bits: 16, + }, + } + } +} + +/// CS timing constants (matches IDF AP_HEX_PSRAM_CS_*). Independent of +/// `SpiRamFreq` -- IDF uses the same values across all speed branches. +const AP_HEX_CS_SETUP_TIME: u32 = 4; +const AP_HEX_CS_HOLD_TIME: u32 = 4; +const AP_HEX_CS_HOLD_DELAY: u32 = 3; + +/// Module-scope shadow of the speed parameters set by `init_psram_inner`. +/// Read by the helper functions (`init_mr_registers`, `psram_mr_read`, +/// `configure_psram_mspi`) that need the dummy / latency values without +/// having `config` threaded through every signature. +/// +/// Initialised to `Mhz200` (IDF default, matches default of +/// `SpiRamFreq`) so the value is well-defined before +/// `init_psram_inner` runs; overwritten there based on +/// `config.ram_frequency`. Single-init, single-thread at boot, so a +/// plain `static mut` is enough. +static mut PSRAM_SPEED: SpeedParams = SpeedParams::for_freq(SpiRamFreq::Mhz200); + +/// Read the active speed parameters. Safe wrapper since we only mutate +/// this once at init before any concurrent access. +fn psram_speed() -> SpeedParams { + unsafe { PSRAM_SPEED } +} + +fn init_psram_inner(config: &mut PsramConfig) { + // Resolve the speed parameter set from `ram_frequency`. The MPLL + // override (`config.core_clock`) lets the caller bypass the default + // pairing (e.g. force 400 MHz MPLL with `Mhz20` bus); `None` + // selects the table-default for the chosen `ram_frequency`. + let mut params = SpeedParams::for_freq(config.ram_frequency); + if let Some(mpll) = config.core_clock { + params.mpll_mhz = mpll as u32; + } + unsafe { PSRAM_SPEED = params }; + + psram_phy_ldo_init(); // PMU EXT_LDO regulator setup for the MSPI PHY analog block. + configure_mpll(params.mpll_mhz); + + // Module clock + clock source + let clkrst = crate::peripherals::HP_SYS_CLKRST::regs(); + clkrst + .soc_clk_ctrl0() + .modify(|_, w| w.psram_sys_clk_en().set_bit()); + clkrst.peri_clk_ctrl00().modify(|_, w| unsafe { + w.psram_pll_clk_en().set_bit(); + w.psram_core_clk_en().set_bit(); + w.psram_clk_src_sel().bits(1) // 1 = MPLL + }); + + // Controller + PHY pad bring-up. + set_bus_clock(params.bus_div); + enable_dll(); + psram_pad_init(); // required for DDR strobe latch + set_cs_timing(); + + // SoC MR init (via MSPI3 SPI direct) + init_mr_registers(); + let psram_size = match config.size { + super::PsramSize::AutoDetect => psram_detect_size(), + super::PsramSize::Size(s) => s, + }; + + config.size = super::PsramSize::Size(psram_size); + + configure_psram_mspi(MSPI0_BASE); // basic AXI configuration here + mmu_map_psram(MSPI0_BASE, *config); // MMU mapping here + + if psram_size > 0 { + let start = PSRAM_VADDR_START; + let end = start + psram_size; + unsafe { super::set_psram_range(start..end) }; + } +} + +/// Set bus-clock divider for both PSRAM_MSPI0 (SRAM_CLK at 0x50) and +/// PSRAM_MSPI1 (CLOCK at 0x14). For divider=2 the value is +/// (N=1)<<16 | (H=0)<<8 | (L=1)<<0 = 0x00010001. For divider=1 the +/// fast path bit `CLK_EQU_SYSCLK` (bit 31) is set instead. +fn set_bus_clock(div: u32) { + const MSPI0_SRAM_CLK: u32 = MSPI0_BASE + 0x50; + const MSPI1_CLOCK: u32 = MSPI1_BASE + 0x14; + + let val = if div == 1 { + 1u32 << 31 + } else { + ((div - 1) << 16) | ((div / 2 - 1) << 8) | (div - 1) + }; + unsafe { + mmio_write_32(MSPI0_SRAM_CLK, val); + mmio_write_32(MSPI1_CLOCK, val); + } +} + +/// Enable DLL timing calibration for both controllers. Both DLL bits +/// live in MSPI0's register space (per IDF `psram_ctrlr_ll_enable_dll`): +fn enable_dll() { + /// MSPI3 DLL (0x5008_E180), bit 5 + const MEM_TIMING_CALI: u32 = MSPI0_BASE + 0x180; + /// MSPI2 DLL (0x5008_E190), bit 5 + const SMEM_TIMING_CALI: u32 = MSPI0_BASE + 0x190; + const DLL_BIT: u32 = 1 << 5; + unsafe { + mmio_setbits_32(MEM_TIMING_CALI, DLL_BIT); + mmio_setbits_32(SMEM_TIMING_CALI, DLL_BIT); + } +} + +/// IOMUX_MSPI_PIN base. Each PSRAM pad has a `..._PIN0_REG` at this base +/// plus the pad-specific offset given by `PsramPad`. +const IOMUX_MSPI_BASE: u32 = 0x500E_1200; + +/// PSRAM IOMUX pads. Discriminant = byte offset from `IOMUX_MSPI_BASE` +/// to that pad's `IOMUX_MSPI_PIN_PSRAM__PIN0_REG`. Per-pad DRV +/// field is bits [13:12]; DQS0 and DQS1 additionally have an XPD enable +/// at bit 0. +#[repr(u32)] +#[derive(Copy, Clone)] +enum PsramPad { + /// DQ0. Matches IDF `IOMUX_MSPI_PIN_PSRAM_D_PIN0_REG` (legacy SPI + /// MOSI naming retained on the IOMUX register itself). + Dq0 = 0x1C, + /// DQ1. IDF `IOMUX_MSPI_PIN_PSRAM_Q_PIN0_REG` (legacy SPI MISO). + Dq1 = 0x20, + /// DQ2. IDF `IOMUX_MSPI_PIN_PSRAM_WP_PIN0_REG` (legacy WP). + Dq2 = 0x24, + /// DQ3. IDF `IOMUX_MSPI_PIN_PSRAM_HOLD_PIN0_REG` (legacy HOLD). + /// In OPI/HEX DDR mode the controller does not treat this as a + /// hold/freeze input -- it is a plain data line. + Dq3 = 0x28, + Dq4 = 0x2C, + Dq5 = 0x30, + Dq6 = 0x34, + Dq7 = 0x38, + Dqs0 = 0x3C, + Dq8 = 0x40, + Dq9 = 0x44, + Dq10 = 0x48, + Dq11 = 0x4C, + Dq12 = 0x50, + Dq13 = 0x54, + Dq14 = 0x58, + Dq15 = 0x5C, + Ck = 0x60, + Cs = 0x64, + Dqs1 = 0x68, +} + +impl PsramPad { + /// Iteration order matches IDF `mspi_timing_ll_pin_drv_set` (all + /// 20 DDR-ish pads in numeric offset order). Add a new variant above + /// and append it here; `set_drv_all` will then cover it + /// automatically. + const ALL: [Self; 20] = [ + // DQ0 ~ DQ7 + Self::Dq0, + Self::Dq1, + Self::Dq2, + Self::Dq3, + Self::Dq4, + Self::Dq5, + Self::Dq6, + Self::Dq7, + // Strobe0 + Self::Dqs0, + // DQ8 ~ DQ15 + Self::Dq8, + Self::Dq9, + Self::Dq10, + Self::Dq11, + Self::Dq12, + Self::Dq13, + Self::Dq14, + Self::Dq15, + // Ck and Cs + Self::Ck, + Self::Cs, + // Strobe1 + Self::Dqs1, + ]; + + /// Absolute MMIO address of this pad's `~_PIN0_REG`. + fn reg_addr(self) -> u32 { + IOMUX_MSPI_BASE + self as u32 + } + + /// Set this pad's drive-strength field (bits [13:12]) to `drv`, + /// preserving the other bits. + unsafe fn set_drv(self, drv: u32) { + unsafe { mmio_clrsetbits_32(self.reg_addr(), 0x3 << 12, (drv & 0x3) << 12) }; + } + + /// Set drive strength on every pad in `Self::ALL`. + unsafe fn set_drv_all(drv: u32) { + for pad in Self::ALL { + unsafe { pad.set_drv(drv) }; + } + } + + /// Set bit 0 (XPD power-up enable) of this pad's PIN0 register. + /// Used on strobe to power on the strobe input buffer needed. + unsafe fn enable_xpd(self) { + unsafe { mmio_setbits_32(self.reg_addr(), 1) }; + } +} + +/// Configure PSRAM PHY pads. +/// +/// Mirrors IDF `mspi_timing_ll_pin_drv_set(2)` + +/// `mspi_timing_ll_enable_dqs(true)`. Both DQS XPD bits must be on for +/// DDR reads to latch data; drive strength = 2 matches IDF default for +/// AP HEX PSRAM at 200 MHz. +fn psram_pad_init() { + unsafe { + PsramPad::set_drv_all(2); + PsramPad::Dqs0.enable_xpd(); + PsramPad::Dqs1.enable_xpd(); + } +} + +/// Set PSRAM CS timing on the AXI controller's SMEM_AC register +/// (0x5008_E1A0). SMEM_CS_SETUP=1, SMEM_CS_HOLD=1, setup_time=N-1, +/// hold_time=N-1, hold_delay=N-1, split_trans_en=1. +fn set_cs_timing() { + const SMEM_AC: u32 = MSPI0_BASE + 0x1A0; + unsafe { + let mut val = mmio_read_32(SMEM_AC); + // bit 0 SMEM_CS_SETUP + // bit 1 SMEM_CS_HOLD + // bit 31 SPLIT_TRANS_EN + val |= (1u32 << 31) | 0b11; + // bits 6..2 SETUP_TIME (5-bit, N-1) + // bits 11..7 HOLD_TIME (5-bit, N-1) + // bits 30..25 HOLD_DELAY (6-bit, N-1) + val = (val & !(0x1F << 2)) | ((AP_HEX_CS_SETUP_TIME - 1) << 2); + val = (val & !(0x1F << 7)) | ((AP_HEX_CS_HOLD_TIME - 1) << 7); + val = (val & !(0x3F << 25)) | ((AP_HEX_CS_HOLD_DELAY - 1) << 25); + mmio_write_32(SMEM_AC, val); + } +} + +// MR (a.k.a Mode Register with single byte inside the AP HEX PSRAM chip. + +const MR_ADDR_MR0_MR1: u32 = 0x0; +const MR_ADDR_MR2_MR3: u32 = 0x2; +const MR_ADDR_MR4_MR5: u32 = 0x4; + +/// MR6 only used in current state, MR7 is unused or reserved. +#[allow(dead_code)] // half-sleep trigger; kept for future power-down support +const MR_ADDR_MR6_MR7: u32 = 0x6; +/// MR8 only used in current state, MR9 is unused or reserved. +const MR_ADDR_MR8_MR9: u32 = 0x8; + +/// Read an 8-bit mode-register pair from the AP HEX PSRAM chip. +/// +/// Returns `(low, high)` where: +/// - `low` = the MR at `mr_addr` +/// - `high` = the MR at `mr_addr + 1` +/// +/// For pair addresses where the high byte is a reserved slot +/// (MR_ADDR_MR4_MR5 / MR_ADDR_MR6 / MR_ADDR_MR8_MR9 — see the table at the +/// `MR_ADDR_*` constants), the `high` value is don't-care and the +/// caller should ignore it. +fn psram_mr_read(mr_addr: u32) -> (u8, u8) { + let pair = mspi1_reg_read16(mr_addr); + ((pair & 0xFF) as u8, ((pair >> 8) & 0xFF) as u8) +} + +/// Write an 8-bit mode-register pair to the AP HEX PSRAM chip. +/// +/// `low` goes to the MR at `mr_addr`, `high` goes to the MR at +/// `mr_addr + 1`. For pair addresses whose high slot is reserved, pass +/// the value previously read back (read-modify-write) to keep the chip +/// state consistent. +fn psram_mr_write(mr_addr: u32, low: u8, high: u8) { + let pair = (low as u16) | ((high as u16) << 8); + mspi1_reg_write16(mr_addr, pair) +} + +/// Initialize AP HEX PSRAM mode registers via PSRAM_MSPI1 OPI DTR +/// referenced IDF `hex_psram_mode_reg_t`), missing on TRM +/// MR0: drive_str[1:0], read_latency[4:2], lt[5] +/// MR4: wr_latency[7:5] +/// MR8: bl[1:0], bt[2], rbx[3], x16[6] +fn init_mr_registers() { + // Read+modify+write MR0 (preserve MR1 high byte). + let (mut mr0, mr1) = psram_mr_read(MR_ADDR_MR0_MR1); + mr0 &= !(0x3 | (0x7 << 2) | (1 << 5)); + mr0 |= ((psram_speed().mr0_rl & 0x7) << 2) | (1 << 5); + psram_mr_write(MR_ADDR_MR0_MR1, mr0, mr1); + + // Read+modify+write MR4 (preserve MR5 reserved high byte). + let (mut mr4, mr5) = psram_mr_read(MR_ADDR_MR4_MR5); + mr4 &= !(0x7 << 5); + mr4 |= (psram_speed().mr4_wl & 0x7) << 5; + psram_mr_write(MR_ADDR_MR4_MR5, mr4, mr5); + + // do nothing for MR6 and MR7 + + // Read+modify+write MR8 (high byte is reserved/absent — pass 0). + let (mut mr8, mr9) = psram_mr_read(MR_ADDR_MR8_MR9); // MR9 is unused + mr8 &= !(0x3 | (1 << 2) | (1 << 3) | (1 << 6)); + mr8 |= 3 // bt = 0 + | (1 << 3) // rbx = 1 + | (1 << 6); // x16 = 1 + psram_mr_write(MR_ADDR_MR8_MR9, mr8, mr9); // keep previous MR9 +} + +/// Mirror of IDF's `esp_rom_spi_cmd_t` (rom/opi_flash.h). Layout must match +/// the C struct exactly; the ROM driver reads it via the pointer. +#[repr(C)] +struct EspRomSpiCmd { + cmd: u16, + cmd_bit_len: u16, + addr: *mut u32, + addr_bit_len: u32, + tx_data: *mut u32, + tx_data_bit_len: u32, + rx_data: *mut u32, + rx_data_bit_len: u32, + dummy_bit_len: u32, +} + +/// `esp_rom_spiflash_read_mode_t`. Only OPI_DTR is used here. +const ESP_ROM_SPIFLASH_OPI_DTR_MODE: u32 = 7; +/// MSPI controller index used for direct (non-cache) PSRAM commands. +/// Maps to `PSRAM_CTRLR_LL_MSPI_ID_3` in IDF (`PSRAM_MSPI1` = 0x5008_F000). +const ROM_SPI_PSRAM_CMD_NUM: i32 = 3; +/// CS mask: PSRAM lives on CS1 (bit 1). Flash on CS0. +const ROM_SPI_PSRAM_CS_MASK: u8 = 1 << 1; + +unsafe extern "C" { + /// Set the controller's read mode (e.g. OPI-DTR). Configures cmd/addr/ + /// data line counts (8-line for OPI) and DDR mode bits in one call. + /// Linked from `esp32p4.rom.ld`: `esp_rom_spi_set_op_mode = 0x4fc00110`. + fn esp_rom_spi_set_op_mode(spi_num: i32, mode: u32); + /// Configure command/addr/dummy/data phases for next transaction. + /// Writes USR / USER1 / USER2 / ADDR / MOSI_DLEN / MISO_DLEN / W0.. + /// Linked from `esp32p4.rom.ld`: `esp_rom_spi_cmd_config = 0x4fc00108`. + fn esp_rom_spi_cmd_config(spi_num: i32, pcmd: *mut EspRomSpiCmd); + + /// `Cache_Invalidate_All = 0x4fc00404`. Invalidates all cache levels. + fn Cache_Invalidate_All(); +} + +unsafe fn rom_cache_invalidate_all() { + unsafe { Cache_Invalidate_All() } +} + +/// Kick the controller (set `SPI_USR` bit 18 in CMD_REG) and poll +/// bounded for completion. Replacement for ROM `esp_rom_spi_cmd_start`, +/// which polls forever; a hang there gives no diagnostic, while the +/// bounded variant surfaces a real failure as a returned error. After +/// the bit clears, copies MISO bytes from W0..W{N} into `rx_buf`. +fn mspi1_kick_and_collect(rx: &mut [u8]) -> Result<(), ()> { + const SPI_CMD: u32 = MSPI1_BASE; + const SPI_W0: u32 = MSPI1_BASE + 0x58; + const SPI_USR_TRIGGER: u32 = 1 << 18; + const MAX_ITERS: u32 = 1_000_000; + + // Select CS1 (PSRAM); leave CS0 (flash) disabled. + // bit 0 CS0_DIS = 1 (disable flash CS) + // bit 1 CS1_DIS = 0 (enable PSRAM CS) + const MISC: u32 = MSPI1_BASE + 0x34; + unsafe { mmio_clrsetbits_32(MISC, 0b10, 0b01) }; + + // Kick. + unsafe { mmio_write_32(SPI_CMD, SPI_USR_TRIGGER) }; + let mut t = MAX_ITERS; + while unsafe { mmio_read_32(SPI_CMD) } & SPI_USR_TRIGGER != 0 { + t -= 1; + if t == 0 { + return Err(()); + } + core::hint::spin_loop(); + } + + // Copy MISO bytes from W0..W{N}. + if !rx.is_empty() { + let n_bytes = rx.len(); + let n_words = n_bytes.div_ceil(4); + for i in 0..n_words { + let word = unsafe { mmio_read_32(SPI_W0 + (i as u32) * 4) }; + for b in 0..4 { + let off = i * 4 + b; + if off >= n_bytes { + break; + } + rx[off] = ((word >> (b * 8)) & 0xFF) as u8; + } + } + } + Ok(()) +} + +/// Issue an AP HEX PSRAM register-read command (0x4040, 16-bit cmd, +/// 32-bit address, 16-bit MISO) through `PSRAM_MSPI1`. Setup via ROM +/// helpers (`set_op_mode` + `cmd_config`); kick + poll done manually +/// with a timeout (avoids ROM `cmd_start` poll-forever pitfall). +fn mspi1_reg_read16(addr: u32) -> u16 { + const REG_READ_CMD: u16 = 0x4040; + const CMD_BITLEN: u16 = 16; + const ADDR_BITLEN: u32 = 32; + const DATA_BITLEN: u32 = 16; + + let mut addr_local = addr; + let mut rx: [u8; 2] = [0; 2]; + let mut conf = EspRomSpiCmd { + cmd: REG_READ_CMD, + cmd_bit_len: CMD_BITLEN, + addr: &mut addr_local as *mut u32, + addr_bit_len: ADDR_BITLEN, + tx_data: core::ptr::null_mut(), + tx_data_bit_len: 0, + rx_data: rx.as_mut_ptr() as *mut u32, + rx_data_bit_len: DATA_BITLEN, + dummy_bit_len: psram_speed().reg_dummy_bits, + }; + + unsafe { + esp_rom_spi_set_op_mode(ROM_SPI_PSRAM_CMD_NUM, ESP_ROM_SPIFLASH_OPI_DTR_MODE); + esp_rom_spi_cmd_config(ROM_SPI_PSRAM_CMD_NUM, &mut conf as *mut EspRomSpiCmd); + } + let _ = mspi1_kick_and_collect(&mut rx); + u16::from_le_bytes(rx) +} + +/// Issue an AP HEX PSRAM register-write command (0xC0C0) with 16-bit +/// data through `PSRAM_MSPI1`. Same setup-via-ROM + manual-kick pattern +/// as `mspi1_reg_read16`. +fn mspi1_reg_write16(addr: u32, data: u16) { + const REG_WRITE_CMD: u16 = 0xC0C0; + const CMD_BITLEN: u16 = 16; + const ADDR_BITLEN: u32 = 32; + const DATA_BITLEN: u32 = 16; + + let mut addr_local = addr; + let mut tx = data.to_le_bytes(); + let mut conf = EspRomSpiCmd { + cmd: REG_WRITE_CMD, + cmd_bit_len: CMD_BITLEN, + addr: &mut addr_local as *mut u32, + addr_bit_len: ADDR_BITLEN, + tx_data: tx.as_mut_ptr() as *mut u32, + tx_data_bit_len: DATA_BITLEN, + rx_data: core::ptr::null_mut(), + rx_data_bit_len: 0, + dummy_bit_len: 0, + }; + + unsafe { + esp_rom_spi_set_op_mode(ROM_SPI_PSRAM_CMD_NUM, ESP_ROM_SPIFLASH_OPI_DTR_MODE); + esp_rom_spi_cmd_config(ROM_SPI_PSRAM_CMD_NUM, &mut conf as *mut EspRomSpiCmd); + } + let mut empty: [u8; 0] = []; + let _ = mspi1_kick_and_collect(&mut empty); +} + +/// Detect PSRAM size by reading mode register MR2 via MSPI1. +fn psram_detect_size() -> usize { + let (mr2, _mr3) = psram_mr_read(MR_ADDR_MR2_MR3); + match mr2 & 0x7 { + 0x1 => 4 * 1024 * 1024, // 32 Mbit + 0x3 => 8 * 1024 * 1024, // 64 Mbit + 0x5 => 16 * 1024 * 1024, // 128 Mbit + 0x6 => 64 * 1024 * 1024, // 512 Mbit + 0x7 => 32 * 1024 * 1024, // 256 Mbit + _ => 32 * 1024 * 1024, // unknown -> EV Board default + } +} + +/// Map PSRAM physical pages into the virtual address space via MMU. +/// +/// ESP32-P4 has TWO independent MMUs: +/// - Flash MMU (id 0): registers in `SPI_MEM_C` (FLASH_SPI0) +/// - PSRAM MMU (id 1): registers in `SPI_MEM_S` (PSRAM_MSPI0) at the `MMU_ITEM_INDEX_REG` / +/// `MMU_ITEM_CONTENT_REG` offsets we use here. +/// +/// Each PSRAM MMU entry is a 32-bit word: +/// - bits [9:0] : physical page number (`SOC_MMU_PSRAM_VALID_VAL_MASK = 0x3FF`) +/// - bit 10 : `SOC_MMU_ACCESS_PSRAM` (selects PSRAM vs flash) +/// - bit 11 : `SOC_MMU_PSRAM_VALID` +/// - bit 12 : `SOC_MMU_PSRAM_SENSITIVE` (set only when cache encryption is on) +/// +/// Virtual base: `SOC_MMU_PSRAM_VADDR_BASE = 0x4800_0000`. The PSRAM MMU +/// is a separate table from the flash MMU, so PSRAM entries start at +/// **entry index 0**, not at some offset relative to the flash range. +/// `entry_id = (vaddr - 0x4800_0000) / 0x10000`. +fn mmu_map_psram(mspi_base: u32, config: PsramConfig) { + const MMU_ITEM_CONTENT: u32 = 0x37C; + const MMU_ITEM_INDEX: u32 = 0x380; + const MMU_PSRAM_VALID: u32 = 1 << 11; + const MMU_ACCESS_PSRAM: u32 = 1 << 10; + const MMU_PADDR_MASK: u32 = 0x3FF; // 10 bits of physical page number + + let psram_size = match config.size { + super::PsramSize::AutoDetect => 32 * 1024 * 1024, + super::PsramSize::Size(s) => s, + }; + let page_count = psram_size / MMU_PAGE_SIZE; + + // Note: we do NOT call Cache_Suspend_*. The ROM helpers expect + // interrupts/scheduler state we can't guarantee in init context, and + // hang. Since at init time nothing else is reading PSRAM via cache + // yet, we can write the MMU entries unsynchronized and then + // invalidate to drop any stale prefetched lines. + unsafe { + let index_reg = mspi_base + MMU_ITEM_INDEX; + let content_reg = mspi_base + MMU_ITEM_CONTENT; + for page in 0..page_count { + let entry_id = page as u32; // PSRAM table starts at entry 0 + let content = MMU_PSRAM_VALID | MMU_ACCESS_PSRAM | (page as u32 & MMU_PADDR_MASK); + mmio_write_32(index_reg, entry_id); + mmio_write_32(content_reg, content); + } + rom_cache_invalidate_all(); + } +} + +#[allow(dead_code)] +pub(crate) fn cache_invalidate(addr: u32, size: u32) { + let cache = unsafe { &*crate::pac::CACHE::PTR }; + cache.sync_addr().write(|w| unsafe { w.bits(addr) }); + cache.sync_size().write(|w| unsafe { w.bits(size) }); + cache + .sync_ctrl() + .modify(|_, w| w.invalidate_ena().set_bit()); + while !cache.sync_ctrl().read().sync_done().bit_is_set() { + core::hint::spin_loop(); + } +} + +#[allow(dead_code)] +pub(crate) fn cache_writeback(addr: u32, size: u32) { + let cache = unsafe { &*crate::pac::CACHE::PTR }; + cache.sync_addr().write(|w| unsafe { w.bits(addr) }); + cache.sync_size().write(|w| unsafe { w.bits(size) }); + cache.sync_ctrl().modify(|_, w| w.writeback_ena().set_bit()); + while !cache.sync_ctrl().read().sync_done().bit_is_set() { + core::hint::spin_loop(); + } +} + +/// Program the PMU external LDO regulators for the MSPI PHY +fn psram_phy_ldo_init() { + const PMU_BASE: u32 = 0x5011_5000; + unsafe { + // P0 power-rail LDOs (general analog). + mmio_write_32(PMU_BASE + 0x1B8, 0x4020_0100); // EXT_LDO_P0_0P1A + mmio_write_32(PMU_BASE + 0x1BC, 0xB100_0000); // EXT_LDO_P0_0P1A_ANA + mmio_write_32(PMU_BASE + 0x1C0, 0x4020_0000); // EXT_LDO_P0_0P2A + mmio_write_32(PMU_BASE + 0x1C4, 0xA000_0000); // EXT_LDO_P0_0P2A_ANA + mmio_write_32(PMU_BASE + 0x1C8, 0x4020_0000); // EXT_LDO_P0_0P3A + mmio_write_32(PMU_BASE + 0x1CC, 0xA000_0000); // EXT_LDO_P0_0P3A_ANA + // P1 power-rail LDOs (MSPI PHY domain). + mmio_write_32(PMU_BASE + 0x1D0, 0x4020_0180); // EXT_LDO_P1_0P1A XPD + current limit + mmio_write_32(PMU_BASE + 0x1D4, 0x5700_0000); // EXT_LDO_P1_0P1A_ANA analog tune (THE one for PSRAM) + mmio_write_32(PMU_BASE + 0x1D8, 0x4020_0000); // EXT_LDO_P1_0P2A + mmio_write_32(PMU_BASE + 0x1DC, 0xA000_0000); // EXT_LDO_P1_0P2A_ANA + mmio_write_32(PMU_BASE + 0x1E0, 0x4020_0000); // EXT_LDO_P1_0P3A + mmio_write_32(PMU_BASE + 0x1E4, 0xA000_0000); // EXT_LDO_P1_0P3A_ANA + } + // Allow LDO output to settle before the MSPI PHY is exercised. + crate::rom::ets_delay_us(50); +} + +/// Configure MPLL to target frequency for PSRAM clock. +fn configure_mpll(freq_mhz: u32) { + use crate::soc::regi2c; + + const I2C_MPLL: u8 = 0x63; + const I2C_MPLL_DIV_REG_ADDR: u8 = 2; + const I2C_MPLL_DHREF: u8 = 3; + const I2C_MPLL_IR_CAL_RSTB: u8 = 5; + + // Power up the MPLL analog block. + let pmu = crate::peripherals::PMU::regs(); + pmu.rf_pwc().modify(|_, w| w.mspi_phy_xpd().set_bit()); + let lp_clkrst = crate::peripherals::LP_AON_CLKRST::regs(); + lp_clkrst + .lp_aonclkrst_hp_clk_ctrl() + .modify(|_, w| w.lp_aonclkrst_hp_mpll_500m_clk_en().set_bit()); + + // div = freq_mhz/20 - 1, ref_div = 1 -> MPLL = XTAL(40) * (div+1) / (ref_div+1) + let ref_div: u8 = 1; + let div: u8 = (freq_mhz / 20).saturating_sub(1) as u8; + let div_val: u8 = (div << 3) | ref_div; + + let dhref = regi2c::regi2c_read(I2C_MPLL, 0, I2C_MPLL_DHREF); + regi2c::regi2c_write(I2C_MPLL, 0, I2C_MPLL_DHREF, dhref | (3 << 4)); + + let rstb = regi2c::regi2c_read(I2C_MPLL, 0, I2C_MPLL_IR_CAL_RSTB); + regi2c::regi2c_write(I2C_MPLL, 0, I2C_MPLL_IR_CAL_RSTB, rstb & 0xDF); + regi2c::regi2c_write(I2C_MPLL, 0, I2C_MPLL_IR_CAL_RSTB, rstb | (1 << 5)); + + regi2c::regi2c_write(I2C_MPLL, 0, I2C_MPLL_DIV_REG_ADDR, div_val); + + let clkrst = crate::peripherals::HP_SYS_CLKRST::regs(); + clkrst + .ana_pll_ctrl0() + .modify(|_, w| w.mspi_cal_stop().clear_bit()); + let mut t = 1_000_000_u32; + while !clkrst.ana_pll_ctrl0().read().mspi_cal_end().bit_is_set() { + t = t.saturating_sub(1); + if t == 0 { + break; + } + core::hint::spin_loop(); + } + clkrst + .ana_pll_ctrl0() + .modify(|_, w| w.mspi_cal_stop().set_bit()); + // cal_end timeout (t == 0): surfaces later via `psram_detect_size` fallback. + let _ = t; // if need print this for debug + crate::rom::ets_delay_us(10); +} + +/// Configure PSRAM_MSPI0 (AXI cache) for HEX/DDR access at 0x4800_0000. +/// +/// Faithful port of IDF `s_config_mspi_for_psram` from +/// `esp_psram_impl_ap_hex.c`. Each register field is named after its +/// `psram_ctrlr_ll_*` setter so the mapping is straightforward to verify. +/// +/// Field layout (PSRAM_MSPI0 / SPIMEM2 register bit positions): +/// +/// `CACHE_SCTRL` (0x40): +/// - bit 0: `cache_usr_saddr_4byte` +/// - bit 3: `usr_wr_sram_dummy` +/// - bit 4: `usr_rd_sram_dummy` +/// - bit 5: `cache_sram_usr_rcmd` +/// - bits 11:6: `sram_rdummy_cyclelen` +/// - bits 19:14: `sram_addr_bitlen` +/// - bit 20: `cache_sram_usr_wcmd` +/// - bit 21: `sram_oct` +/// - bits 27:22: `sram_wdummy_cyclelen` +/// +/// `SRAM_CMD` (0x44): +/// - bit 18: `sdin_oct` +/// - bit 19: `sdout_oct` +/// - bit 20: `saddr_oct` +/// - bit 21: `scmd_oct` +/// - bit 22: `sdummy_rin` +/// - bit 23: `sdummy_wout` +/// - bit 26: `sdin_hex` +/// - bit 27: `sdout_hex` +/// +/// `MEM_CTRL1` (0x70): `ar_splice_en` bit 25, `aw_splice_en` bit 26. +/// +/// `SMEM_DDR` (0xD8): bit 0 `smem_ddr_en`, bit 1 `smem_var_dummy`, +/// bit 2 `smem_ddr_rdat_swp`, bit 3 `smem_ddr_wdat_swp`. +/// +/// `CACHE_FCTRL` (0x3C): bit 0 `mem_axi_req_en`, bit 1 `close_axi_inf_en`. +fn configure_psram_mspi(base: u32) { + // Dummy bit-counts come from the active speed parameter table. + let rd_dummy_n = psram_speed().rd_dummy_bits; + let wr_dummy_n = psram_speed().wr_dummy_bits; + + unsafe { + // CACHE_SCTRL. + // bit 0 cache_usr_saddr_4byte + // bit 3 usr_wr_sram_dummy + // bit 4 usr_rd_sram_dummy + // bit 5 cache_sram_usr_rcmd + let sctrl_addr = base + 0x40; + let mut val = mmio_read_32(sctrl_addr); + val |= 0b011_1001; + // bits 11..6 sram_rdummy_cyclelen + // bits 19..14 sram_addr_bitlen (N-1 form, here 32-bit addr) + // bits 27..22 sram_wdummy_cyclelen + val = (val & !(0x3F << 6)) | ((rd_dummy_n - 1) << 6); + val = (val & !(0x3F << 14)) | ((32 - 1) << 14); + val = (val & !(0x3F << 22)) | ((wr_dummy_n - 1) << 22); + // bit 20 cache_sram_usr_wcmd + // bit 21 sram_oct (octal mode for cache transactions) + val |= 0b11 << 20; + mmio_write_32(sctrl_addr, val); + + // SRAM_CMD: octal-line + hex-data + dummy-level control. + // bit 18 sdin_oct + // bit 19 sdout_oct + // bit 20 saddr_oct + // bit 21 scmd_oct + // bit 23 sdummy_wout (write-dummy level control enable) + // bit 26 sdin_hex (16-line read data) + // bit 27 sdout_hex (16-line write data) + mmio_setbits_32(base + 0x44, 0b1100_1011_1100 << 16); // bits 27, 26, 23, 21..18 + + // SRAM_DRD_CMD / SRAM_DWR_CMD: 16-bit sync read/write commands. + mmio_write_32(base + 0x48, (16 - 1) << 28); // sync read 0x0000 + mmio_write_32(base + 0x4C, ((16 - 1) << 28) | 0x8080); // sync write 0x8080 + + // MEM_CTRL1: splice enables (AXI burst optimization). + // bit 25 ar_splice_en + // bit 26 aw_splice_en + mmio_setbits_32(base + 0x70, 0b11 << 25); + + // SMEM_DDR: DDR mode + variable dummy. + // bit 0 smem_ddr_en set + // bit 1 smem_var_dummy set + // bit 2 smem_ddr_rdat_swp clear (default off) + // bit 3 smem_ddr_wdat_swp clear (default off) + mmio_clrsetbits_32(base + 0xD8, 0b1100, 0b0011); + + // CACHE_FCTRL: enable AXI access. + // bit 0 : MEM_AXI_REQ_EN = 1 (set) + // bit 31 : CLOSE_AXI_INF_EN = 0 (clear -> open the AXI iface) + mmio_clrsetbits_32(base + 0x3C, 1u32 << 31, 1); + } +} diff --git a/esp-hal/src/psram/mod.rs b/esp-hal/src/psram/mod.rs index 9b34efb1176..adccd9dc836 100644 --- a/esp-hal/src/psram/mod.rs +++ b/esp-hal/src/psram/mod.rs @@ -47,6 +47,7 @@ use core::ops::Range; #[cfg_attr(esp32s2, path = "esp32s2.rs")] #[cfg_attr(esp32s3, path = "esp32s3.rs")] #[cfg_attr(any(esp32c5, esp32c61), path = "esp32c5_c61.rs")] +#[cfg_attr(esp32p4, path = "esp32p4.rs")] pub(crate) mod implem; pub use implem::*; diff --git a/esp-hal/src/rtc_cntl/mod.rs b/esp-hal/src/rtc_cntl/mod.rs index 6c007c5e7c0..2d4ea32cb81 100644 --- a/esp-hal/src/rtc_cntl/mod.rs +++ b/esp-hal/src/rtc_cntl/mod.rs @@ -136,6 +136,7 @@ pub mod sleep; #[cfg_attr(esp32c6, path = "rtc/esp32c6.rs")] #[cfg_attr(esp32c61, path = "rtc/esp32c61.rs")] #[cfg_attr(esp32h2, path = "rtc/esp32h2.rs")] +#[cfg_attr(esp32p4, path = "rtc/esp32p4.rs")] #[cfg_attr(esp32s2, path = "rtc/esp32s2.rs")] #[cfg_attr(esp32s3, path = "rtc/esp32s3.rs")] pub(crate) mod rtc; @@ -414,9 +415,23 @@ impl<'d> Rtc<'d> { // ESP32-S3: TRM v1.5 chapter 8.3 // ESP32-H2: TRM v0.5 chapter 8.2.3 - LP_AON::regs() - .store4() - .modify(|r, w| unsafe { w.bits(r.bits() | Self::RTC_DISABLE_ROM_LOG) }); + // P4: LP_SYS (mapped as LP_AON) names its scratch registers + // `lp_store0..lp_store14`, while every other chip names them + // `store0..N`. esp-idf's `rtc_suppress_rom_log()` writes + // RTC_DISABLE_ROM_LOG = (1<<0) | (1<<16) to STORE4. + // TODO: file an esp-pacs issue/PR to rename the P4 fields to match; + // once that lands this cfg branch can collapse to a single line. + cfg_if::cfg_if! { + if #[cfg(esp32p4)] { + LP_AON::regs() + .lp_store4() + .modify(|r, w| unsafe { w.bits(r.bits() | Self::RTC_DISABLE_ROM_LOG) }); + } else { + LP_AON::regs() + .store4() + .modify(|r, w| unsafe { w.bits(r.bits() | Self::RTC_DISABLE_ROM_LOG) }); + } + } } /// Register an interrupt handler for the RTC. @@ -487,6 +502,10 @@ pub enum RwdtStage { pub struct Rwdt(()); /// RTC Watchdog Timer driver. +/// +/// ESP32-P4 LP_WDT PAC uses different register names (config0 vs wdtconfig0, +/// lp_wdt vs wdt, etc.). P4-specific implementation is a TODO. +#[cfg(not(esp32p4))] impl Rwdt { /// Enable the watchdog timer instance. /// Watchdog starts with default settings (`stage 0` resets the system, the @@ -635,6 +654,141 @@ impl Rwdt { } } +/// ESP32-P4 LP_WDT implementation. +/// P4 PAC uses config0/config1/.../feed/wprotect (no "wdt" prefix), +/// and interrupt field is `lp_wdt` (not `wdt`). +/// Ref: TRM v0.5 Ch 19 (Watchdog Timers) +/// Write protection key: 0x50D8_3AA1 (same as other chips) +#[cfg(esp32p4)] +impl Rwdt { + /// Enable the watchdog timer instance. + pub fn enable(&mut self) { + self.set_enabled(true); + } + + /// Disable the watchdog timer instance. + pub fn disable(&mut self) { + self.set_enabled(false); + } + + /// Listen for interrupts on stage 0. + pub fn listen(&mut self) { + let rtc_cntl = LP_WDT::regs(); + self.set_write_protection(false); + rtc_cntl + .config0() + .modify(|_, w| unsafe { w.wdt_stg0().bits(RwdtStageAction::Interrupt as u8) }); + // P4 PAC: int_ena().lp_wdt() (not .wdt()) + rtc_cntl.int_ena().modify(|_, w| w.lp_wdt().set_bit()); + self.set_write_protection(true); + } + + /// Stop listening for interrupts on stage 0. + pub fn unlisten(&mut self) { + let rtc_cntl = LP_WDT::regs(); + self.set_write_protection(false); + rtc_cntl + .config0() + .modify(|_, w| unsafe { w.wdt_stg0().bits(RwdtStageAction::ResetSystem as u8) }); + rtc_cntl.int_ena().modify(|_, w| w.lp_wdt().clear_bit()); + self.set_write_protection(true); + } + + /// Clear interrupt. + pub fn clear_interrupt(&mut self) { + self.set_write_protection(false); + LP_WDT::regs() + .int_clr() + .write(|w| w.lp_wdt().clear_bit_by_one()); + self.set_write_protection(true); + } + + /// Check if the interrupt is set. + pub fn is_interrupt_set(&self) -> bool { + LP_WDT::regs().int_st().read().lp_wdt().bit_is_set() + } + + /// Feed the watchdog timer. + pub fn feed(&mut self) { + self.set_write_protection(false); + // P4 PAC: feed().feed() (not wdtfeed().wdt_feed()) + LP_WDT::regs().feed().write(|w| w.feed().set_bit()); + self.set_write_protection(true); + } + + fn set_write_protection(&mut self, enable: bool) { + let wkey = if enable { 0u32 } else { 0x50D8_3AA1 }; + LP_WDT::regs().wprotect().write(|w| unsafe { w.bits(wkey) }); + } + + fn set_enabled(&mut self, enable: bool) { + let rtc_cntl = LP_WDT::regs(); + self.set_write_protection(false); + + if !enable { + rtc_cntl.config0().modify(|_, w| unsafe { w.bits(0) }); + } else { + rtc_cntl + .config0() + .write(|w| w.wdt_flashboot_mod_en().bit(false)); + rtc_cntl + .config0() + .modify(|_, w| w.wdt_en().bit(enable).wdt_pause_in_slp().bit(enable)); + unsafe { + rtc_cntl.config0().modify(|_, w| { + w.wdt_stg0().bits(RwdtStageAction::ResetSystem as u8); + w.wdt_cpu_reset_length().bits(7); + w.wdt_sys_reset_length().bits(7); + w.wdt_stg1().bits(RwdtStageAction::Off as u8); + w.wdt_stg2().bits(RwdtStageAction::Off as u8); + w.wdt_stg3().bits(RwdtStageAction::Off as u8); + w.wdt_en().set_bit() + }); + } + } + self.set_write_protection(true); + } + + /// Configure timeout value for the selected stage. + pub fn set_timeout(&mut self, stage: RwdtStage, timeout: Duration) { + let rtc_cntl = LP_WDT::regs(); + let timeout_raw = crate::clock::us_to_rtc_ticks(timeout.as_micros()) as u32; + self.set_write_protection(false); + + // P4 PAC: config1().wdt_stg0_hold(), config2().wdt_stg1_hold(), etc. + let timeout_raw = timeout_raw >> (1 + crate::efuse::rwdt_multiplier()); + match stage { + RwdtStage::Stage0 => rtc_cntl + .config1() + .modify(|_, w| unsafe { w.wdt_stg0_hold().bits(timeout_raw) }), + RwdtStage::Stage1 => rtc_cntl + .config2() + .modify(|_, w| unsafe { w.bits(timeout_raw) }), + RwdtStage::Stage2 => rtc_cntl + .config3() + .modify(|_, w| unsafe { w.bits(timeout_raw) }), + RwdtStage::Stage3 => rtc_cntl + .config4() + .modify(|_, w| unsafe { w.bits(timeout_raw) }), + }; + self.set_write_protection(true); + } + + /// Set the action for a specific stage. + pub fn set_stage_action(&mut self, stage: RwdtStage, action: RwdtStageAction) { + self.set_write_protection(false); + LP_WDT::regs().config0().modify(|_, w| unsafe { + match stage { + RwdtStage::Stage0 => w.wdt_stg0().bits(action as u8), + RwdtStage::Stage1 => w.wdt_stg1().bits(action as u8), + RwdtStage::Stage2 => w.wdt_stg2().bits(action as u8), + RwdtStage::Stage3 => w.wdt_stg3().bits(action as u8), + } + }); + self.set_write_protection(true); + } +} + /// Super Watchdog #[cfg(swd)] pub struct Swd(()); @@ -691,7 +845,8 @@ pub fn wakeup_cause() -> SleepSource { cfg_if::cfg_if! { if #[cfg(esp32)] { let wakeup_cause_bits = LPWR::regs().wakeup_state().read().wakeup_cause().bits() as u32; - } else if #[cfg(soc_has_intpri)] { + } else if #[cfg(soc_has_pmu)] { + // C5/C6/C61/H2/P4: PMU.slp_wakeup_status0.wakeup_cause let wakeup_cause_bits = crate::peripherals::PMU::regs() .slp_wakeup_status0() .read() diff --git a/esp-hal/src/rtc_cntl/rtc/esp32p4.rs b/esp-hal/src/rtc_cntl/rtc/esp32p4.rs new file mode 100644 index 00000000000..5f0b0c1091d --- /dev/null +++ b/esp-hal/src/rtc_cntl/rtc/esp32p4.rs @@ -0,0 +1,310 @@ +//! RTC control for ESP32-P4X (chip revision v3.x / eco5). +//! +//! PMU power domain init and WDT disable for bare-metal boot. +//! +//! Register names validated against esp32p4 PAC (eco5) and: +//! - TRM v0.5 Ch 16 (Low-Power Management) +//! - TRM v0.5 Ch 19 (Watchdog Timers) +//! +//! eco4 vs eco5 PMU difference: +//! eco4: power_pd_hpaon_cntl, power_pd_hpcpu_cntl, power_pd_hpwifi_cntl +//! eco5: power_pd_cnnt_cntl, power_pd_lpperi_cntl (hpaon/hpcpu/hpwifi removed) +//! Both: power_pd_top_cntl, power_pd_hpmem_cntl + +// TODO: REMOVE me when validate well +// reference florianL21's original eco4 PMU code + +use strum::FromRepr; + +use crate::peripherals::{LP_WDT, PMU, TIMG0, TIMG1}; + +/// SOC Reset Reason. +#[derive(Debug, Clone, Copy, PartialEq, Eq, FromRepr)] +#[repr(usize)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum SocResetReason { + /// Power on reset + ChipPowerOn = 0x01, + /// Software resets the digital core + CoreSw = 0x03, + /// Deep sleep reset the digital core + CoreDeepSleep = 0x05, + /// SDIO Core reset + CoreSDIO = 0x06, + /// Main watch dog 0 resets digital core + CoreMwdt0 = 0x07, + /// Main watch dog 1 resets digital core + CoreMwdt1 = 0x08, + /// RTC watch dog resets digital core + CoreRtcWdt = 0x09, + /// Main watch dog 0 resets CPU 0 + Cpu0Mwdt0 = 0x0B, + /// Software resets CPU 0 + Cpu0Sw = 0x0C, + /// RTC watch dog resets CPU 0 + Cpu0RtcWdt = 0x0D, + /// VDD voltage is not stable and resets the digital core + SysBrownOut = 0x0F, + /// RTC watch dog resets digital core and rtc module + SysRtcWdt = 0x10, + /// Main watch dog 1 resets CPU 0 + Cpu0Mwdt1 = 0x11, + /// Super watch dog resets the digital core and rtc module + SysSuperWdt = 0x12, + /// eFuse CRC error resets the digital core + CoreEfuseCrc = 0x14, + /// USB UART resets the digital core + CoreUsbUart = 0x15, + /// USB JTAG resets the digital core + CoreUsbJtag = 0x16, + /// JTAG resets CPU + Cpu0JtagCpu = 0x18, +} + +/// Clear all force flags on PMU power domains to allow normal power management. +/// +/// eco5 power domains (verified against PAC): +/// - TOP: power_pd_top_cntl (system top-level) +/// - CNNT: power_pd_cnnt_cntl (connectivity, eco5 new -- replaces hpaon/hpcpu/hpwifi) +/// - HPMEM: power_pd_hpmem_cntl (HP memory) +/// - LPPERI: power_pd_lpperi_cntl (LP peripherals, eco5 new) +fn pmu_power_domain_force_default() { + let pmu = PMU::regs(); + + // PMU_HP_PD_TOP + pmu.power_pd_top_cntl().modify(|_, w| { + w.force_top_reset().bit(false); + w.force_top_iso().bit(false); + w.force_top_pu().bit(false); + w.force_top_no_reset().bit(false); + w.force_top_no_iso().bit(false); + w.force_top_pd().bit(false) + }); + + // PMU_HP_PD_CNNT (eco5: replaces hpaon + hpcpu + hpwifi from eco4) + pmu.power_pd_cnnt_cntl().modify(|_, w| { + w.force_cnnt_reset().bit(false); + w.force_cnnt_iso().bit(false); + w.force_cnnt_pu().bit(false); + w.force_cnnt_no_reset().bit(false); + w.force_cnnt_no_iso().bit(false); + w.force_cnnt_pd().bit(false) + }); + + // PMU_HP_PD_HPMEM + pmu.power_pd_hpmem_cntl().modify(|_, w| { + w.force_hp_mem_reset().bit(false); + w.force_hp_mem_iso().bit(false); + w.force_hp_mem_pu().bit(false); + w.force_hp_mem_no_reset().bit(false); + w.force_hp_mem_no_iso().bit(false); + w.force_hp_mem_pd().bit(false) + }); + + // PMU_LP_PD_LPPERI (eco5 new) + pmu.power_pd_lpperi_cntl().modify(|_, w| { + w.force_lp_peri_reset().bit(false); + w.force_lp_peri_iso().bit(false); + w.force_lp_peri_pu().bit(false); + w.force_lp_peri_no_reset().bit(false); + w.force_lp_peri_no_iso().bit(false); + w.force_lp_peri_pd().bit(false) + }); +} + +/// Minimal init for bare-metal boot: disable all watchdogs and set power domains. +/// +/// This is the minimum needed for the chip to not reset itself during startup. +/// Full clock configuration (PLL, CPU freq) is handled separately. +/// +/// Ref: TRM v0.5 Ch 19 (WDT), Ch 16 (Power Management) +pub(crate) fn init() { + // 1. Clear all PMU power domain force flags + pmu_power_domain_force_default(); + + // 2. Disable TIMG0 watchdog TIMG WDT write protect key: 0x50D8_3AA1 + let tg0 = TIMG0::regs(); + tg0.wdtwprotect().write(|w| unsafe { w.bits(0x50D8_3AA1) }); + tg0.wdtconfig0().modify(|_, w| w.wdt_en().clear_bit()); + tg0.wdtwprotect().write(|w| unsafe { w.bits(0) }); + + // 3. Disable TIMG1 watchdog + let tg1 = TIMG1::regs(); + tg1.wdtwprotect().write(|w| unsafe { w.bits(0x50D8_3AA1) }); + tg1.wdtconfig0().modify(|_, w| w.wdt_en().clear_bit()); + tg1.wdtwprotect().write(|w| unsafe { w.bits(0) }); + + // 4. Disable LP_WDT (Low-Power Watchdog) P4 PAC: config0() (not wdtconfig0()), wprotect() (not + // wdtwprotect()) + let lp_wdt = LP_WDT::regs(); + lp_wdt.wprotect().write(|w| unsafe { w.bits(0x50D8_3AA1) }); + lp_wdt.config0().modify(|_, w| unsafe { w.bits(0) }); + lp_wdt.wprotect().write(|w| unsafe { w.bits(0) }); + + // 5. Disable SWD (Super Watchdog) by enabling auto-feed LP_WDT SWD write protect key: + // 0x50D8_3AA1 (same key) + lp_wdt + .swd_wprotect() + .write(|w| unsafe { w.bits(0x50D8_3AA1) }); + lp_wdt + .swd_config() + .modify(|_, w| w.swd_auto_feed_en().set_bit()); + lp_wdt.swd_wprotect().write(|w| unsafe { w.bits(0) }); + + // 6. Clear DCDC switch force flags PMU_POWER_DCDC_SWITCH_REG (offset 0x10c) + let pmu = PMU::regs(); + pmu.power_dcdc_switch().modify(|_, w| { + w.force_dcdc_switch_pu().bit(false); + w.force_dcdc_switch_pd().bit(false) + }); + + // 7. Enable CPLL (400 MHz) and SPLL (480 MHz) + cpll_configure(400); + spll_configure(480); + + // 8. Set CPU divider to 1 (400 MHz CPU), MEM divider 2, APB divider 2 + let clkrst = crate::peripherals::HP_SYS_CLKRST::regs(); + + // Set CPU divider: cpu_clk_div_num = divider - 1 = 0 + // Ref: HP_SYS_CLKRST.root_clk_ctrl0.reg_cpu_clk_div_num + clkrst.root_clk_ctrl0().modify(|_, w| unsafe { + w.cpu_clk_div_num().bits(0); // CPU: /1 = 400 MHz + w.cpu_clk_div_numerator().bits(0); + w.cpu_clk_div_denominator().bits(0) + }); + // Trigger clock divider update + clkrst + .root_clk_ctrl0() + .modify(|_, w| w.soc_clk_div_update().set_bit()); + while clkrst + .root_clk_ctrl0() + .read() + .soc_clk_div_update() + .bit_is_set() + { + core::hint::spin_loop(); + } + + // 9. Switch CPU clock source from XTAL to CPLL LP_AON_CLKRST.hp_clk_ctrl.hp_root_clk_src_sel: + // 0=XTAL, 1=CPLL, 2=RC_FAST + crate::peripherals::LP_AON_CLKRST::regs() + .lp_aonclkrst_hp_clk_ctrl() + .modify(|_, w| unsafe { w.lp_aonclkrst_hp_root_clk_src_sel().bits(1) }); // 1 = CPLL +} + +/// Configure CPLL for the given frequency (360 or 400 MHz). +/// +/// eco5 (v3.x) uses different I2C register values than eco4 (v1.x). +/// Ref: TRM v0.5 Ch 12 -- CPLL configuration +fn cpll_configure(freq_mhz: u32) { + use crate::soc::regi2c; + + // I2C CPLL register addresses + const I2C_CPLL: u8 = 0x67; // CPLL slave address + const I2C_CPLL_OC_REF_DIV: u8 = 2; + const I2C_CPLL_OC_DIV_7_0: u8 = 3; + const I2C_CPLL_OC_DCUR: u8 = 6; + + // 1. Enable CPLL power PMU.imm_hp_ck_power: tie_high_xpd_pll, tie_high_xpd_pll_i2c Note: PAC + // uses "pll" not "cpll" (eco4 PAC, single PLL) + let pmu = PMU::regs(); + // PAC: tie_high_xpd_pll is 4-bit field (one bit per PLL: CPLL/SPLL/MPLL/PLLA). + // Set all bits to enable all PLLs. Same for pll_i2c. + pmu.imm_hp_ck_power().write(|w| unsafe { + w.tie_high_xpd_pll().bits(0xF); + w.tie_high_xpd_pll_i2c().bits(0xF) + }); + // Enable global CPLL ICG (clock gating) + // Ref: PMU.imm_hp_ck_power.tie_high_global_cpll_icg + // Note: this field may not exist in eco4 PAC; use direct bit write if needed + // For now, the PLL is enabled via xpd_pll above. + + // 2. Configure CPLL via I2C analog registers + // eco5 values (v3.x): div7_0 = 10 (400MHz), 9 (360MHz) with 40MHz XTAL + let div7_0: u8 = match freq_mhz { + 400 => 10, // eco5: 400 MHz + 360 => 9, // eco5: 360 MHz + _ => 10, // default to 400 MHz + }; + + // OC_REF_DIV + DCHGP: (oc_enb_fcal << 7) | (dchgp << 4) | div_ref = 0x50 + let lref: u8 = 0x50; // dchgp=5, div_ref=0, oc_enb_fcal=0 + + // OC_DCUR: (dlref_sel << 6) | (dhref_sel << 4) | dcur = 0x73 + let dcur: u8 = 0x73; // dlref_sel=1, dhref_sel=3, dcur=3 + + regi2c::regi2c_write(I2C_CPLL, 0, I2C_CPLL_OC_REF_DIV, lref); + regi2c::regi2c_write(I2C_CPLL, 0, I2C_CPLL_OC_DIV_7_0, div7_0); + regi2c::regi2c_write(I2C_CPLL, 0, I2C_CPLL_OC_DCUR, dcur); + + // 3. Run CPLL calibration HP_SYS_CLKRST.ana_pll_ctrl0.cpu_pll_cal_stop + let clkrst = crate::peripherals::HP_SYS_CLKRST::regs(); + + // Start calibration: set cpu_pll_cal_stop = 0 + clkrst + .ana_pll_ctrl0() + .modify(|_, w| w.cpu_pll_cal_stop().clear_bit()); + + // Wait for calibration to complete + while !clkrst.ana_pll_ctrl0().read().cpu_pll_cal_end().bit_is_set() { + core::hint::spin_loop(); + } + + // Stop calibration: set cpu_pll_cal_stop = 1 + clkrst + .ana_pll_ctrl0() + .modify(|_, w| w.cpu_pll_cal_stop().set_bit()); + + // Small delay for PLL to stabilize + crate::rom::ets_delay_us(10); +} + +/// Configure SPLL (System PLL) for the given frequency (480 MHz typical). +/// +/// SPLL provides peripheral clocks: PLL_F240M/160M/120M/80M/20M. +/// Ref: TRM v0.5 Ch 12 -- SPLL configuration +fn spll_configure(freq_mhz: u32) { + use crate::soc::regi2c; + + // I2C SPLL register addresses + const I2C_SPLL: u8 = regi2c::REGI2C_SYS_PLL; + const I2C_SPLL_OC_REF_DIV: u8 = 2; + const I2C_SPLL_OC_DIV_7_0: u8 = 3; + const I2C_SPLL_OC_DCUR: u8 = 6; + + // PLL power already enabled in cpll_configure (PMU xpd_pll bits(0xF) enables all PLLs) + + // Configure SPLL via I2C analog registers + // eco5 values: div7_0 = (freq_mhz / 40) - 1, same formula as CPLL + let div7_0: u8 = match freq_mhz { + 480 => 11, // 480 MHz: (480/40) - 1 = 11 + 240 => 5, // 240 MHz: (240/40) - 1 = 5 + _ => 11, // default to 480 MHz + }; + + // Same OC_REF_DIV and OC_DCUR values as CPLL + let lref: u8 = 0x50; // dchgp=5, div_ref=0, oc_enb_fcal=0 + let dcur: u8 = 0x73; // dlref_sel=1, dhref_sel=3, dcur=3 + + regi2c::regi2c_write(I2C_SPLL, 0, I2C_SPLL_OC_REF_DIV, lref); + regi2c::regi2c_write(I2C_SPLL, 0, I2C_SPLL_OC_DIV_7_0, div7_0); + regi2c::regi2c_write(I2C_SPLL, 0, I2C_SPLL_OC_DCUR, dcur); + + // Run SPLL calibration + // HP_SYS_CLKRST.ana_pll_ctrl0.sys_pll_cal_stop + let clkrst = crate::peripherals::HP_SYS_CLKRST::regs(); + + clkrst + .ana_pll_ctrl0() + .modify(|_, w| w.sys_pll_cal_stop().clear_bit()); + + while !clkrst.ana_pll_ctrl0().read().sys_pll_cal_end().bit_is_set() { + core::hint::spin_loop(); + } + + clkrst + .ana_pll_ctrl0() + .modify(|_, w| w.sys_pll_cal_stop().set_bit()); + + crate::rom::ets_delay_us(10); +} diff --git a/esp-hal/src/rtc_cntl/sleep/esp32p4.rs b/esp-hal/src/rtc_cntl/sleep/esp32p4.rs new file mode 100644 index 00000000000..28667a723af --- /dev/null +++ b/esp-hal/src/rtc_cntl/sleep/esp32p4.rs @@ -0,0 +1,12 @@ +//! Sleep mode for ESP32-P4X (chip revision v3.x / eco5). +//! +//! Current status: Not implemented. Sleep mode requires PMU eco5 registers +//! which have different layouts from eco4. +//! +//! The original florianL21 sleep code +//! It references types and PMU registers that don't exist in current PAC: +//! - crate::clock::Clock, crate::efuse::Efuse (old API pattern) +//! - PMU hp_active/hp_modem/hp_sleep register groups + +// TODO: Implement sleep mode once PMU eco5 registers are validated. +// TODO: reference florianL21's implementation diff --git a/esp-hal/src/rtc_cntl/sleep/mod.rs b/esp-hal/src/rtc_cntl/sleep/mod.rs index d6b455131ee..3381759edaf 100644 --- a/esp-hal/src/rtc_cntl/sleep/mod.rs +++ b/esp-hal/src/rtc_cntl/sleep/mod.rs @@ -31,6 +31,7 @@ use crate::rtc_cntl::Rtc; #[cfg_attr(esp32c6, path = "esp32c6.rs")] #[cfg_attr(esp32c2, path = "esp32c2.rs")] #[cfg_attr(esp32h2, path = "esp32h2.rs")] +#[cfg_attr(esp32p4, path = "esp32p4.rs")] mod sleep_impl; pub use sleep_impl::*; diff --git a/esp-hal/src/soc/esp32p4/clocks.rs b/esp-hal/src/soc/esp32p4/clocks.rs new file mode 100644 index 00000000000..dc4297358e6 --- /dev/null +++ b/esp-hal/src/soc/esp32p4/clocks.rs @@ -0,0 +1,288 @@ +//! Clock tree for ESP32-P4X (chip revision v3.x / eco5). +//! +//! CPLL: 400 MHz (eco5 default), 360 MHz (conservative) +//! SPLL: 480 MHz (peripheral clocks) +//! MPLL: 400 MHz (PSRAM, media) +//! XTAL: 40 MHz +//! +//! Clock hierarchy: XTAL -> CPLL -> CPU_ROOT -> CPU/APB dividers +//! SPLL -> PLL_F240M/160M/120M/80M/20M (peripheral clocks) +#![allow(dead_code, reason = "Clock functions called from generated macro code")] +#![allow( + missing_docs, + reason = "Clock-tree types come from a generated macro that does not emit doc strings" +)] +#![allow( + clippy::enum_variant_names, + reason = "CPU frequency variant names follow the chip-spec MHz convention" +)] + +define_clock_tree_types!(); + +/// CPU clock frequency presets for ESP32-P4X (eco5 / chip revision v3.x). +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[non_exhaustive] +pub enum CpuClock { + /// 400 MHz CPU clock (eco5 / v3.x maximum) + /// CPLL -> CPU_ROOT -> CPU/1, APB divider /4 = 100MHz + #[default] + _400MHz = 400, + + /// 360 MHz CPU clock (conservative) + _360MHz = 360, + + /// 200 MHz CPU clock (low power) + /// CPLL -> CPU_ROOT -> CPU/2, APB /2 = 100MHz + _200MHz = 200, + + /// 100 MHz CPU clock (ultra low power) + /// CPLL -> CPU_ROOT -> CPU/4, APB /1 = 100MHz + _100MHz = 100, +} + +impl CpuClock { + // Preset: 400 MHz CPU, 100 MHz APB + const PRESET_400: ClockConfig = ClockConfig { + cpu_root_clk: Some(CpuRootClkConfig::Cpll), + cpu_clk: Some(CpuClkConfig::new(0)), // /1 = 400 MHz + apb_clk: Some(ApbClkConfig::new(3)), // /4 = 100 MHz + lp_fast_clk: Some(LpFastClkConfig::RcFast), + lp_slow_clk: Some(LpSlowClkConfig::RcSlow), + }; + + const PRESET_360: ClockConfig = ClockConfig { + cpu_root_clk: Some(CpuRootClkConfig::Cpll), + cpu_clk: Some(CpuClkConfig::new(0)), // /1 = 360 MHz (CPLL at 360) + apb_clk: Some(ApbClkConfig::new(3)), // /4 = 90 MHz + lp_fast_clk: Some(LpFastClkConfig::RcFast), + lp_slow_clk: Some(LpSlowClkConfig::RcSlow), + }; + + const PRESET_200: ClockConfig = ClockConfig { + cpu_root_clk: Some(CpuRootClkConfig::Cpll), + cpu_clk: Some(CpuClkConfig::new(1)), // /2 = 200 MHz + apb_clk: Some(ApbClkConfig::new(1)), // /2 = 100 MHz + lp_fast_clk: Some(LpFastClkConfig::RcFast), + lp_slow_clk: Some(LpSlowClkConfig::RcSlow), + }; + + const PRESET_100: ClockConfig = ClockConfig { + cpu_root_clk: Some(CpuRootClkConfig::Cpll), + cpu_clk: Some(CpuClkConfig::new(3)), // /4 = 100 MHz + apb_clk: Some(ApbClkConfig::new(0)), // /1 = 100 MHz + lp_fast_clk: Some(LpFastClkConfig::RcFast), + lp_slow_clk: Some(LpSlowClkConfig::RcSlow), + }; +} + +impl From for ClockConfig { + fn from(value: CpuClock) -> ClockConfig { + match value { + CpuClock::_400MHz => CpuClock::PRESET_400, + CpuClock::_360MHz => CpuClock::PRESET_360, + CpuClock::_200MHz => CpuClock::PRESET_200, + CpuClock::_100MHz => CpuClock::PRESET_100, + } + } +} + +impl Default for ClockConfig { + fn default() -> Self { + Self::from(CpuClock::default()) + } +} + +impl ClockConfig { + pub(crate) fn try_get_preset(self) -> Option { + match self { + v if v == CpuClock::PRESET_400 => Some(CpuClock::_400MHz), + v if v == CpuClock::PRESET_360 => Some(CpuClock::_360MHz), + v if v == CpuClock::PRESET_200 => Some(CpuClock::_200MHz), + v if v == CpuClock::PRESET_100 => Some(CpuClock::_100MHz), + _ => None, + } + } + + pub(crate) fn configure(self, clocks: &mut ClockTree) { + self.apply(clocks); + } +} + +// Clock node implementation functions (called from generated macro) +// These must match the function names that define_clock_tree_types!() expects. + +// CPU_ROOT_CLK (mux: XTAL / CPLL / RC_FAST) +fn configure_cpu_root_clk_impl( + _clocks: &mut ClockTree, + _old_selector: Option, + new_selector: CpuRootClkConfig, +) { + // LP_AON_CLKRST.hp_clk_ctrl.hp_root_clk_src_sel: 0=XTAL, 1=CPLL, 2=RC_FAST + let sel = match new_selector { + CpuRootClkConfig::Xtal => 0, + CpuRootClkConfig::Cpll => 1, + CpuRootClkConfig::RcFast => 2, + }; + crate::peripherals::LP_AON_CLKRST::regs() + .lp_aonclkrst_hp_clk_ctrl() + .modify(|_, w| unsafe { w.lp_aonclkrst_hp_root_clk_src_sel().bits(sel) }); +} + +// CPU_CLK divider +fn enable_cpu_clk_impl(_clocks: &mut ClockTree, _en: bool) {} +fn configure_cpu_clk_impl( + _clocks: &mut ClockTree, + _old_config: Option, + new_config: CpuClkConfig, +) { + // HP_SYS_CLKRST.root_clk_ctrl0.cpu_clk_div_num = divider - 1 + let clkrst = crate::peripherals::HP_SYS_CLKRST::regs(); + clkrst.root_clk_ctrl0().modify(|_, w| unsafe { + w.cpu_clk_div_num().bits(new_config.divisor as u8); + w.cpu_clk_div_numerator().bits(0); + w.cpu_clk_div_denominator().bits(0) + }); + // Trigger divider update + clkrst + .root_clk_ctrl0() + .modify(|_, w| w.soc_clk_div_update().set_bit()); + while clkrst + .root_clk_ctrl0() + .read() + .soc_clk_div_update() + .bit_is_set() + { + core::hint::spin_loop(); + } +} + +// APB_CLK divider +fn enable_apb_clk_impl(_clocks: &mut ClockTree, _en: bool) {} +fn configure_apb_clk_impl( + _clocks: &mut ClockTree, + _old_config: Option, + _new_config: ApbClkConfig, +) { + // TODO: APB divider register in HP_SYS_CLKRST + // For now, APB freq is derived from CPU freq via divider +} + +// LP_FAST_CLK mux +fn configure_lp_fast_clk_impl( + _clocks: &mut ClockTree, + _old_selector: Option, + new_selector: LpFastClkConfig, +) { + crate::peripherals::LP_AON_CLKRST::regs() + .lp_aonclkrst_lp_clk_conf() + .modify(|_, w| unsafe { + w.lp_aonclkrst_fast_clk_sel().bits(match new_selector { + LpFastClkConfig::RcFast => 0, + LpFastClkConfig::XtalD2 => 1, + }) + }); +} + +// LP_SLOW_CLK mux +fn configure_lp_slow_clk_impl( + _clocks: &mut ClockTree, + _old_selector: Option, + new_selector: LpSlowClkConfig, +) { + crate::peripherals::LP_AON_CLKRST::regs() + .lp_aonclkrst_lp_clk_conf() + .modify(|_, w| unsafe { + w.lp_aonclkrst_slow_clk_sel().bits(match new_selector { + LpSlowClkConfig::RcSlow => 0, + LpSlowClkConfig::Xtal32k => 1, + LpSlowClkConfig::Rc32k => 2, + LpSlowClkConfig::OscSlow => 3, + }) + }); +} + +// Per-instance clock impl for UART (called on UartInstance enum) + +impl UartInstance { + fn enable_function_clock_impl(self, _clocks: &mut ClockTree, _en: bool) { + // UART function clock enable is handled by peripheral clock gates in system.rs + } + + fn configure_function_clock_impl( + self, + _clocks: &mut ClockTree, + _old_config: Option, + _new_config: UartFunctionClockConfig, + ) { + // TODO: Configure UART clock source selection + // HP_SYS_CLKRST PERI_CLK_CTRL110-114 for UART0-4 + } + + fn enable_baud_rate_generator_impl(self, _clocks: &mut ClockTree, _en: bool) { + // Baud rate generator is always on when UART is enabled + } + + fn configure_baud_rate_generator_impl( + self, + _clocks: &mut ClockTree, + _old_config: Option, + _new_config: UartBaudRateGeneratorConfig, + ) { + // Baud rate is configured directly in UART registers, not here + } +} + +// Per-instance clock impl for TIMG + +impl TimgInstance { + fn enable_function_clock_impl(self, _clocks: &mut ClockTree, _en: bool) { + // TIMG function clock is managed by peripheral clock gates + } + + fn configure_function_clock_impl( + self, + _clocks: &mut ClockTree, + _old_config: Option, + _new_config: TimgFunctionClockConfig, + ) { + // TODO: Configure TIMG clock source + // HP_SYS_CLKRST PERI_CLK_CTRL20/21 + } + + fn enable_wdt_clock_impl(self, _clocks: &mut ClockTree, _en: bool) {} + + fn configure_wdt_clock_impl( + self, + _clocks: &mut ClockTree, + _old_config: Option, + _new_config: TimgWdtClockConfig, + ) { + // TODO: Configure TIMG WDT clock source + } +} + +// System clock impl functions + +// Mux enable stubs (mux nodes need enable functions too) +fn enable_cpu_root_clk_impl(_clocks: &mut ClockTree, _en: bool) {} +fn enable_lp_fast_clk_impl(_clocks: &mut ClockTree, _en: bool) {} +fn enable_lp_slow_clk_impl(_clocks: &mut ClockTree, _en: bool) {} + +// Source clock enable/disable stubs (PLLs, oscillators) +fn enable_cpll_clk_impl(_clocks: &mut ClockTree, _en: bool) {} +fn enable_spll_clk_impl(_clocks: &mut ClockTree, _en: bool) {} +fn enable_mpll_clk_impl(_clocks: &mut ClockTree, _en: bool) {} +fn enable_rc_fast_clk_impl(_clocks: &mut ClockTree, _en: bool) {} +fn enable_xtal32k_clk_impl(_clocks: &mut ClockTree, _en: bool) {} +fn enable_osc_slow_clk_impl(_clocks: &mut ClockTree, _en: bool) {} +fn enable_rc_slow_clk_impl(_clocks: &mut ClockTree, _en: bool) {} +fn enable_rc32k_clk_impl(_clocks: &mut ClockTree, _en: bool) {} +fn enable_pll_f20m_impl(_clocks: &mut ClockTree, _en: bool) {} +fn enable_pll_f80m_impl(_clocks: &mut ClockTree, _en: bool) {} +fn enable_pll_f120m_impl(_clocks: &mut ClockTree, _en: bool) {} +fn enable_pll_f160m_impl(_clocks: &mut ClockTree, _en: bool) {} +fn enable_pll_f240m_impl(_clocks: &mut ClockTree, _en: bool) {} +fn enable_pll_f25m_impl(_clocks: &mut ClockTree, _en: bool) {} +fn enable_pll_f50m_impl(_clocks: &mut ClockTree, _en: bool) {} +fn enable_xtal_d2_clk_impl(_clocks: &mut ClockTree, _en: bool) {} diff --git a/esp-hal/src/soc/esp32p4/gpio.rs b/esp-hal/src/soc/esp32p4/gpio.rs new file mode 100644 index 00000000000..af943df6b63 --- /dev/null +++ b/esp-hal/src/soc/esp32p4/gpio.rs @@ -0,0 +1,137 @@ +//! ESP32-P4 LP GPIO (RtcPin) implementation. +//! +//! P4 LP GPIO uses named registers (pin0, pin1, ...) instead of indexed pin(n). +//! LP_IO_MUX uses pad0, pad1, ... with different field names from other chips. +//! +//! LP pins: GPIO0-5, GPIO12-23 (16 pins total, mapped to LP_GPIO pin0-pin15) +//! GPIO0-5 -> LP pin 0-5 +//! GPIO12-23 -> LP pin 6-17 (offset by 6) +//! +//! Ref: TRM v0.5 Ch 11 (GPIO) -- LP_IO_MUX section +//! P4 PAC: lp_gpio (0x5012_A000), lp_io_mux (0x5012_B000) + +/// LP GPIO base address (from PAC) +const LP_GPIO_BASE: u32 = 0x5012_A000; +/// LP IO MUX base address (from PAC) +const LP_IO_MUX_BASE: u32 = 0x5012_B000; + +/// Convert GPIO number to LP pin index. +/// GPIO0-5 -> LP pin 0-5 +/// GPIO12-23 -> LP pin 6-17 +#[allow(dead_code)] // used by p4_rtc_pin! macro expansions and future LP wakeup code +const fn gpio_to_lp_pin(gpio: u8) -> Option { + match gpio { + 0..=5 => Some(gpio), + 12..=23 => Some(gpio - 6), + _ => None, + } +} + +/// Implement RtcPin for a P4 LP-capable GPIO. +/// Uses direct MMIO because P4 LP_GPIO PAC has named registers (pin0, pin1, ...) +/// and LP_IO_MUX has different field names from other chips. +macro_rules! p4_rtc_pin { + ($($gpio_num:literal => $lp_pin:literal),+ $(,)?) => { + $( + impl $crate::gpio::RtcPin for paste::paste!($crate::peripherals::[]<'_>) { + unsafe fn apply_wakeup(&self, wakeup: bool, level: u8) { + // LP_GPIO.PINn register: wakeup_enable + int_type + // Ref: P4 PAC lp_gpio/pin0.rs -- reg_gpio_pin0_wakeup_enable, int_type + // Each PINn register is at LP_GPIO_BASE + 0x20 + n*4 + unsafe { + let pin_reg = (LP_GPIO_BASE + 0x20 + $lp_pin * 4) as *mut u32; + let val = pin_reg.read_volatile(); + let val = (val & !(0x7 << 7)) | ((level as u32 & 0x7) << 7); + let val = if wakeup { val | (1 << 10) } else { val & !(1 << 10) }; + pin_reg.write_volatile(val); + } + } + + fn rtcio_pad_hold(&self, enable: bool) { + // LP_AON (LP_SYS) doesn't have gpio_hold for P4. + // P4 uses LP_IO_MUX pad hold instead. + // TODO: implement LP pad hold + // For now, no-op. + let _ = enable; + } + + fn rtc_set_config(&self, input_enable: bool, mux: bool, func: $crate::gpio::RtcFunction) { + unsafe { + // LP_IO_MUX.PADn register + // pad0 at offset 0x08, pad1 at 0x0C, etc. + let pad_reg = (LP_IO_MUX_BASE + 0x08 + $lp_pin * 4) as *mut u32; + let mut val = pad_reg.read_volatile(); + + // reg_padN_mux_sel: bit 3 (1=LP mode, 0=IO MUX mode) + if mux { val |= 1 << 3; } else { val &= !(1 << 3); } + + // reg_padN_fun_ie: bit 8 (input enable) + if input_enable { val |= 1 << 8; } else { val &= !(1 << 8); } + + // reg_padN_fun_sel: bits [5:4] (function select) + val = (val & !(0x3 << 4)) | (((func as u32) & 0x3) << 4); + + // reg_padN_slp_sel: bit 6 (0=normal operation) + val &= !(1 << 6); + + pad_reg.write_volatile(val); + } + } + } + + impl $crate::gpio::RtcPinWithResistors for paste::paste!($crate::peripherals::[]<'_>) { + fn rtcio_pullup(&self, enable: bool) { + unsafe { + let pad_reg = (LP_IO_MUX_BASE + 0x08 + $lp_pin * 4) as *mut u32; + let val = pad_reg.read_volatile(); + // reg_padN_rue: bit 2 (pullup enable) + if enable { + pad_reg.write_volatile(val | (1 << 2)); + } else { + pad_reg.write_volatile(val & !(1 << 2)); + } + } + } + + fn rtcio_pulldown(&self, enable: bool) { + unsafe { + let pad_reg = (LP_IO_MUX_BASE + 0x08 + $lp_pin * 4) as *mut u32; + let val = pad_reg.read_volatile(); + // reg_padN_rde: bit 1 (pulldown enable) + if enable { + pad_reg.write_volatile(val | (1 << 1)); + } else { + pad_reg.write_volatile(val & !(1 << 1)); + } + } + } + } + )+ + }; +} + +// GPIO0-5 -> LP pin 0-5 +p4_rtc_pin! { + 0 => 0, + 1 => 1, + 2 => 2, + 3 => 3, + 4 => 4, + 5 => 5, +} + +// GPIO12-23 -> LP pin 6-17 +p4_rtc_pin! { + 12 => 6, + 13 => 7, + 14 => 8, + 15 => 9, + 16 => 10, + 17 => 11, + 18 => 12, + 19 => 13, + 20 => 14, + 21 => 15, + 22 => 16, + 23 => 17, +} diff --git a/esp-hal/src/soc/esp32p4/mod.rs b/esp-hal/src/soc/esp32p4/mod.rs new file mode 100644 index 00000000000..439e719d6d8 --- /dev/null +++ b/esp-hal/src/soc/esp32p4/mod.rs @@ -0,0 +1,35 @@ +// pub mod efuse; +pub mod gpio; +// pub mod peripherals; + +crate::unstable_module! { + pub mod clocks; +} + +pub(crate) mod regi2c; + +pub(crate) use esp32p4 as pac; + +// P4 DMA module alias: the esp-hal GDMA driver expects the GDMA-AHB (`ahb_dma`) +// register layout. The PAC's `dma` module maps to a different block (see +// SOC_DW_GDMA_SUPPORTED), so alias `ahb_dma` to keep ahb_v2.rs type paths working. +#[allow(unused)] +pub(crate) mod dma_compat { + pub use super::pac::ahb_dma::*; +} + +pub(crate) mod registers { + pub const INTERRUPT_MAP_BASE: u32 = 0x500D_6000; + pub const INTERRUPT_MAP_BASE_APP_CPU: u32 = 0x500D_6800; +} + +pub(crate) mod constants { + #[allow(dead_code)] // used by other chips; reserved for future P4 DRAM boundary checks + pub const SOC_DRAM_LOW: u32 = 0x4FF0_0000; + #[allow(dead_code)] + pub const SOC_DRAM_HIGH: u32 = 0x4FFC_0000; +} + +pub(crate) fn pre_init() { + // TODO: Check if anything needs to be done here +} diff --git a/esp-hal/src/soc/esp32p4/regi2c.rs b/esp-hal/src/soc/esp32p4/regi2c.rs new file mode 100644 index 00000000000..63062f91779 --- /dev/null +++ b/esp-hal/src/soc/esp32p4/regi2c.rs @@ -0,0 +1,131 @@ +//! I2C analog register access for ESP32-P4. +//! +//! Used for PLL configuration (CPLL, SPLL, MPLL) and other analog peripherals. +//! Accesses the LP_I2C_ANA_MST peripheral which bridges to internal analog I2C bus. +//! +//! Ref: TRM v0.5 Ch 49 (Analog I2C Controller) + +// I2C slave addresses for analog blocks +#[allow(dead_code)] +pub(crate) const REGI2C_DIG_REG: u8 = 0x6d; +#[allow(dead_code)] +pub(crate) const REGI2C_CPU_PLL: u8 = 0x67; +#[allow(dead_code)] +pub(crate) const REGI2C_SDIO_PLL: u8 = 0x62; +#[allow(dead_code)] +pub(crate) const REGI2C_BIAS: u8 = 0x6a; +#[allow(dead_code)] +pub(crate) const REGI2C_MSPI: u8 = 0x63; +#[allow(dead_code)] +pub(crate) const REGI2C_SYS_PLL: u8 = 0x66; +#[allow(dead_code)] +pub(crate) const REGI2C_PLLA: u8 = 0x6f; +#[allow(dead_code)] +pub(crate) const REGI2C_SAR_I2C: u8 = 0x69; + +// Master select bits in ANA_CONF2 register +const REGI2C_DIG_REG_MST_SEL: u16 = 1 << 10; +const REGI2C_PLL_CPU_MST_SEL: u16 = 1 << 11; +#[allow(dead_code)] +const REGI2C_PLL_SDIO_MST_SEL: u16 = 1 << 6; +#[allow(dead_code)] +const REGI2C_BIAS_MST_SEL: u16 = 1 << 12; +#[allow(dead_code)] +const REGI2C_MSPI_XTAL_MST_SEL: u16 = 1 << 9; +#[allow(dead_code)] +const REGI2C_PLL_SYS_MST_SEL: u16 = 1 << 5; +#[allow(dead_code)] +const REGI2C_PLLA_MST_SEL: u16 = 1 << 8; +#[allow(dead_code)] +const REGI2C_SAR_I2C_MST_SEL: u16 = 1 << 7; + +/// I2C control register bit fields +const REGI2C_RTC_BUSY_BIT: u32 = 1 << 25; +const REGI2C_RTC_WR_CNTL_BIT: u32 = 1 << 24; +const REGI2C_RTC_DATA_SHIFT: u32 = 16; +const REGI2C_RTC_DATA_MASK: u32 = 0xFF; +const REGI2C_RTC_ADDR_SHIFT: u32 = 8; +const REGI2C_RTC_ADDR_MASK: u32 = 0xFF; +const REGI2C_RTC_SLAVE_ID_SHIFT: u32 = 0; +const REGI2C_RTC_SLAVE_ID_MASK: u32 = 0xFF; + +/// LP_I2C_ANA_MST base address (from PAC: 0x5012_4000) +/// I2C0_CTRL_REG is at offset 0x14 +const LP_I2C_ANA_MST_BASE: u32 = 0x5012_4000; +const LP_I2C_ANA_MST_I2C0_CTRL_REG: u32 = LP_I2C_ANA_MST_BASE + 0x14; +const LP_I2C_ANA_MST_ANA_CONF1_REG: u32 = LP_I2C_ANA_MST_BASE + 0x04; +const LP_I2C_ANA_MST_ANA_CONF2_REG: u32 = LP_I2C_ANA_MST_BASE + 0x08; + +/// Select the I2C master for the given analog block. +fn regi2c_enable_block(block: u8) { + // Clear both conf registers first + unsafe { + (LP_I2C_ANA_MST_ANA_CONF2_REG as *mut u32).write_volatile(0); + (LP_I2C_ANA_MST_ANA_CONF1_REG as *mut u32).write_volatile(0); + } + + // Set the master select bit for this block + let sel_bit: u32 = match block { + REGI2C_DIG_REG => REGI2C_DIG_REG_MST_SEL as u32, + REGI2C_CPU_PLL => REGI2C_PLL_CPU_MST_SEL as u32, + REGI2C_SDIO_PLL => REGI2C_PLL_SDIO_MST_SEL as u32, + REGI2C_BIAS => REGI2C_BIAS_MST_SEL as u32, + REGI2C_MSPI => REGI2C_MSPI_XTAL_MST_SEL as u32, + REGI2C_SYS_PLL => REGI2C_PLL_SYS_MST_SEL as u32, + REGI2C_PLLA => REGI2C_PLLA_MST_SEL as u32, + REGI2C_SAR_I2C => REGI2C_SAR_I2C_MST_SEL as u32, + _ => return, + }; + + unsafe { + let reg = LP_I2C_ANA_MST_ANA_CONF2_REG as *mut u32; + reg.write_volatile(reg.read_volatile() | sel_bit); + } +} + +/// Wait for I2C bus to become idle. +#[inline] +fn wait_i2c_idle() { + unsafe { + let reg = LP_I2C_ANA_MST_I2C0_CTRL_REG as *const u32; + while reg.read_volatile() & REGI2C_RTC_BUSY_BIT != 0 { + core::hint::spin_loop(); + } + } +} + +/// Read an analog I2C register. +pub(crate) fn regi2c_read(block: u8, _host_id: u8, reg_add: u8) -> u8 { + regi2c_enable_block(block); + wait_i2c_idle(); + + // Build read command: slave_id[7:0] | addr[15:8] + let cmd = ((block as u32 & REGI2C_RTC_SLAVE_ID_MASK) << REGI2C_RTC_SLAVE_ID_SHIFT) + | ((reg_add as u32 & REGI2C_RTC_ADDR_MASK) << REGI2C_RTC_ADDR_SHIFT); + + unsafe { + (LP_I2C_ANA_MST_I2C0_CTRL_REG as *mut u32).write_volatile(cmd); + } + wait_i2c_idle(); + + // Read data from bits [23:16] + let val = unsafe { (LP_I2C_ANA_MST_I2C0_CTRL_REG as *const u32).read_volatile() }; + ((val >> REGI2C_RTC_DATA_SHIFT) & REGI2C_RTC_DATA_MASK) as u8 +} + +/// Write an analog I2C register. +pub(crate) fn regi2c_write(block: u8, _host_id: u8, reg_add: u8, data: u8) { + regi2c_enable_block(block); + wait_i2c_idle(); + + // Build write command: slave_id[7:0] | addr[15:8] | data[23:16] | wr_cntl[24] + let cmd = ((block as u32 & REGI2C_RTC_SLAVE_ID_MASK) << REGI2C_RTC_SLAVE_ID_SHIFT) + | ((reg_add as u32 & REGI2C_RTC_ADDR_MASK) << REGI2C_RTC_ADDR_SHIFT) + | REGI2C_RTC_WR_CNTL_BIT + | ((data as u32 & REGI2C_RTC_DATA_MASK) << REGI2C_RTC_DATA_SHIFT); + + unsafe { + (LP_I2C_ANA_MST_I2C0_CTRL_REG as *mut u32).write_volatile(cmd); + } + wait_i2c_idle(); +} diff --git a/esp-hal/src/soc/mod.rs b/esp-hal/src/soc/mod.rs index dbc7597acad..08ab358f810 100644 --- a/esp-hal/src/soc/mod.rs +++ b/esp-hal/src/soc/mod.rs @@ -15,6 +15,7 @@ use crate::efuse::ChipRevision; #[cfg_attr(esp32c6, path = "esp32c6/mod.rs")] #[cfg_attr(esp32c61, path = "esp32c61/mod.rs")] #[cfg_attr(esp32h2, path = "esp32h2/mod.rs")] +#[cfg_attr(esp32p4, path = "esp32p4/mod.rs")] #[cfg_attr(esp32s2, path = "esp32s2/mod.rs")] #[cfg_attr(esp32s3, path = "esp32s3/mod.rs")] mod implementation; diff --git a/esp-hal/src/spi/master/mod.rs b/esp-hal/src/spi/master/mod.rs index eff2904678f..7e68365f074 100644 --- a/esp-hal/src/spi/master/mod.rs +++ b/esp-hal/src/spi/master/mod.rs @@ -2389,7 +2389,17 @@ impl Driver { fn update(&self) { cfg_if::cfg_if! { - if #[cfg(not(any(esp32, esp32s2)))] { + if #[cfg(esp32p4)] { + // P4 PAC: cmd().update() is write-only -- no `read()` accessor, + // so we can't poll for the bit clearing like the other chips. + // Spin for ~10 cycles to let the hardware latch instead. + // TODO: file an esp-pacs issue/PR so the P4 SVD marks the SPI + // cmd().update field readable like other chips. Once that lands + // this branch can collapse into the general `else` arm below. + let reg_block = self.regs(); + reg_block.cmd().modify(|_, w| w.update().set_bit()); + for _ in 0..10 { core::hint::spin_loop(); } + } else if #[cfg(not(any(esp32, esp32s2)))] { let reg_block = self.regs(); reg_block.cmd().modify(|_, w| w.update().set_bit()); diff --git a/esp-hal/src/uart/mod.rs b/esp-hal/src/uart/mod.rs index f67789f67b8..de5c522016b 100644 --- a/esp-hal/src/uart/mod.rs +++ b/esp-hal/src/uart/mod.rs @@ -2043,7 +2043,8 @@ where /// Configures the AT-CMD detection settings #[instability::unstable] pub fn set_at_cmd(&mut self, config: AtCmdConfig) { - #[cfg(not(any(esp32, esp32s2)))] + // P4: sclk_en is controlled by HP_SYS_CLKRST, not UART clk_conf register + #[cfg(not(any(esp32, esp32s2, esp32p4)))] self.regs() .clk_conf() .modify(|_, w| w.sclk_en().clear_bit()); @@ -2071,7 +2072,7 @@ where .write(|w| unsafe { w.rx_gap_tout().bits(gap_timeout as _) }); } - #[cfg(not(any(esp32, esp32s2)))] + #[cfg(not(any(esp32, esp32s2, esp32p4)))] self.regs().clk_conf().modify(|_, w| w.sclk_en().set_bit()); sync_regs(self.regs()); @@ -3344,7 +3345,7 @@ impl Info { let source_config = ClockConfig::new( config.clock_source, - #[cfg(any(uart_has_sclk_divider, soc_has_pcr))] + #[cfg(any(uart_has_sclk_divider, soc_has_pcr, esp32p4))] 0, ); let clk = clock.function_clock_config_frequency(clocks, source_config); @@ -3362,7 +3363,7 @@ impl Info { // TODO: this block should only prepare the new clock config, and it should // be applied only after validating the resulting baud rate. cfg_if::cfg_if! { - if #[cfg(any(uart_has_sclk_divider, soc_has_pcr))] { + if #[cfg(any(uart_has_sclk_divider, soc_has_pcr, esp32p4))] { const MAX_DIV: u32 = property!("clock_tree.uart.baud_rate_generator.integral").1; let clk_div = clk.div_ceil(MAX_DIV).div_ceil(config.baudrate); debug!("SCLK: {} divider: {}", clk, clk_div); @@ -3754,6 +3755,10 @@ crate::any_peripheral! { Uart1(crate::peripherals::UART1<'d>), #[cfg(soc_has_uart2)] Uart2(crate::peripherals::UART2<'d>), + #[cfg(soc_has_uart3)] + Uart3(crate::peripherals::UART3<'d>), + #[cfg(soc_has_uart4)] + Uart4(crate::peripherals::UART4<'d>), } } @@ -3795,7 +3800,7 @@ impl<'t> UartClockGuard<'t> { // Apply default SCLK configuration let sclk_config = ClockConfig::new( Default::default(), - #[cfg(any(uart_has_sclk_divider, soc_has_pcr))] + #[cfg(any(uart_has_sclk_divider, soc_has_pcr, esp32p4))] 0, ); clock.configure_function_clock(clocks, sclk_config); diff --git a/esp-metadata-generated/Cargo.toml b/esp-metadata-generated/Cargo.toml index 2d4074c3009..a582b9058c5 100644 --- a/esp-metadata-generated/Cargo.toml +++ b/esp-metadata-generated/Cargo.toml @@ -27,5 +27,6 @@ esp32c5 = ["_device-selected"] esp32c6 = ["_device-selected"] esp32c61 = ["_device-selected"] esp32h2 = ["_device-selected"] +esp32p4 = ["_device-selected"] esp32s2 = ["_device-selected"] esp32s3 = ["_device-selected"] diff --git a/esp-metadata-generated/src/_build_script_utils.rs b/esp-metadata-generated/src/_build_script_utils.rs index 223f87a0c89..a8e09dc239d 100644 --- a/esp-metadata-generated/src/_build_script_utils.rs +++ b/esp-metadata-generated/src/_build_script_utils.rs @@ -43,6 +43,7 @@ pub enum Chip { Esp32c6, Esp32c61, Esp32h2, + Esp32p4, Esp32s2, Esp32s3, } @@ -57,11 +58,12 @@ impl core::str::FromStr for Chip { "esp32c6" => Ok(Self::Esp32c6), "esp32c61" => Ok(Self::Esp32c61), "esp32h2" => Ok(Self::Esp32h2), + "esp32p4" => Ok(Self::Esp32p4), "esp32s2" => Ok(Self::Esp32s2), "esp32s3" => Ok(Self::Esp32s3), _ => Err(alloc::format!( "Unknown chip {s}. Possible options: esp32, esp32c2, esp32c3, esp32c5, esp32c6, \ - esp32c61, esp32h2, esp32s2, esp32s3" + esp32c61, esp32h2, esp32p4, esp32s2, esp32s3" )), } } @@ -79,6 +81,7 @@ impl Chip { ("CARGO_FEATURE_ESP32C6", Self::Esp32c6), ("CARGO_FEATURE_ESP32C61", Self::Esp32c61), ("CARGO_FEATURE_ESP32H2", Self::Esp32h2), + ("CARGO_FEATURE_ESP32P4", Self::Esp32p4), ("CARGO_FEATURE_ESP32S2", Self::Esp32s2), ("CARGO_FEATURE_ESP32S3", Self::Esp32s3), ]; @@ -88,7 +91,8 @@ impl Chip { if chip.is_some() { return Err( "Expected exactly one of the following features to be enabled: esp32, \ - esp32c2, esp32c3, esp32c5, esp32c6, esp32c61, esp32h2, esp32s2, esp32s3", + esp32c2, esp32c3, esp32c5, esp32c6, esp32c61, esp32h2, esp32p4, esp32s2, \ + esp32s3", ); } chip = Some(c); @@ -98,7 +102,7 @@ impl Chip { Some(chip) => Ok(chip), None => Err( "Expected exactly one of the following features to be enabled: esp32, esp32c2, \ - esp32c3, esp32c5, esp32c6, esp32c61, esp32h2, esp32s2, esp32s3", + esp32c3, esp32c5, esp32c6, esp32c61, esp32h2, esp32p4, esp32s2, esp32s3", ), } } @@ -126,6 +130,7 @@ impl Chip { Self::Esp32c6 => "esp32c6", Self::Esp32c61 => "esp32c61", Self::Esp32h2 => "esp32h2", + Self::Esp32p4 => "esp32p4", Self::Esp32s2 => "esp32s2", Self::Esp32s3 => "esp32s3", } @@ -180,6 +185,7 @@ impl Chip { Self::Esp32c6, Self::Esp32c61, Self::Esp32h2, + Self::Esp32p4, Self::Esp32s2, Self::Esp32s3, ] @@ -4139,6 +4145,542 @@ impl Chip { }, ], }, + Self::Esp32p4 => Config { + architecture: "riscv", + target: "riscv32imafc-unknown-none-elf", + symbols: &[ + "esp32p4", + "riscv", + "multi_core", + "soc_has_efuse", + "soc_has_gpio", + "soc_has_hp_sys", + "soc_has_hp_sys_clkrst", + "soc_has_interrupt_core0", + "soc_has_interrupt_core1", + "soc_has_clic", + "soc_has_io_mux", + "soc_has_lp_aon", + "soc_has_lp_aon_clkrst", + "soc_has_lp_sys", + "soc_has_lp_wdt", + "soc_has_lpwr", + "soc_has_pmu", + "soc_has_systimer", + "soc_has_timg0", + "soc_has_timg1", + "soc_has_uart0", + "soc_has_uart1", + "soc_has_uart2", + "soc_has_uart3", + "soc_has_uart4", + "soc_has_spi2", + "soc_has_spi3", + "soc_has_i2c0", + "soc_has_i2c1", + "soc_has_twai0", + "soc_has_twai1", + "soc_has_twai2", + "soc_has_psram", + "soc_has_dma", + "soc_has_dma_ch0", + "soc_has_dma_ch1", + "soc_has_dma_ch2", + "soc_has_usb_device", + "soc_has_sdhost", + "soc_has_ledc", + "soc_has_mcpwm0", + "soc_has_mcpwm1", + "soc_has_pcnt", + "soc_has_rmt", + "soc_has_adc", + "soc_has_aes", + "soc_has_sha", + "soc_has_rsa", + "soc_has_ecc", + "very_large_intr_status", + "spi_octal", + "rom_crc_le", + "rom_crc_be", + "rom_md5_bsd", + "pm_support_ext1_wakeup", + "pm_support_touch_sensor_wakeup", + "dma_driver_supported", + "gpio_driver_supported", + "i2c_master_driver_supported", + "interrupts_driver_supported", + "psram_driver_supported", + "soc_driver_supported", + "spi_master_driver_supported", + "systimer_driver_supported", + "uart_driver_supported", + "usb_serial_jtag_driver_supported", + "i2c_master_i2c0", + "i2c_master_i2c1", + "spi_master_spi2", + "spi_master_spi3", + "uart_uart0", + "uart_uart1", + "uart_uart2", + "uart_uart3", + "uart_uart4", + "aes_dma", + "aes_has_split_text_registers", + "dma_kind=\"gdma\"", + "dma_separate_in_out_interrupts", + "dma_max_priority=\"5\"", + "dma_max_priority_is_set", + "dma_gdma_version=\"2\"", + "dma_gdma_version_is_set", + "ecc_separate_jacobian_point_memory", + "ecc_has_modular_arithmetic", + "ecc_has_point_addition", + "ecc_has_curve_p192", + "ecc_has_curve_p256", + "ecc_has_curve_p384", + "gpio_has_bank_1", + "gpio_gpio_function=\"1\"", + "gpio_constant_0_input=\"62\"", + "gpio_constant_1_input=\"63\"", + "gpio_func_in_sel_offset=\"0\"", + "gpio_input_signal_max=\"203\"", + "gpio_output_signal_max=\"256\"", + "i2c_master_has_fsm_timeouts", + "i2c_master_has_hw_bus_clear", + "i2c_master_has_bus_timeout_enable", + "i2c_master_max_bus_timeout=\"31\"", + "i2c_master_ll_intr_mask=\"262143\"", + "i2c_master_fifo_size=\"32\"", + "interrupts_status_registers=\"3\"", + "interrupt_controller=\"clic\"", + "lp_i2c_master_fifo_size=\"32\"", + "lp_uart_ram_size=\"32\"", + "psram_extmem_origin=\"1207959552\"", + "rng_apb_cycle_wait_num=\"16\"", + "rsa_size_increment=\"32\"", + "rsa_memory_size_bytes=\"384\"", + "sha_dma", + "soc_cpu_has_csr_pc", + "soc_rc_fast_clk_default=\"20000000\"", + "soc_rc_fast_clk_default_is_set", + "soc_has_clock_node_xtal_clk", + "soc_has_clock_node_cpll_clk", + "soc_has_clock_node_spll_clk", + "soc_has_clock_node_mpll_clk", + "soc_has_clock_node_rc_fast_clk", + "soc_has_clock_node_xtal32k_clk", + "soc_has_clock_node_osc_slow_clk", + "soc_has_clock_node_rc_slow_clk", + "soc_has_clock_node_rc32k_clk", + "soc_has_clock_node_pll_f20m", + "soc_has_clock_node_pll_f80m", + "soc_has_clock_node_pll_f120m", + "soc_has_clock_node_pll_f160m", + "soc_has_clock_node_pll_f240m", + "soc_has_clock_node_pll_f25m", + "soc_has_clock_node_pll_f50m", + "soc_has_clock_node_xtal_d2_clk", + "soc_has_clock_node_cpu_root_clk", + "soc_has_clock_node_cpu_clk", + "soc_has_clock_node_apb_clk", + "soc_has_clock_node_lp_fast_clk", + "soc_has_clock_node_lp_slow_clk", + "soc_has_clock_node_uart_function_clock", + "soc_has_clock_node_uart_baud_rate_generator", + "soc_has_clock_node_timg_function_clock", + "soc_has_clock_node_timg_wdt_clock", + "has_dram_region", + "has_dram2_uninit_region", + "spi_master_supports_dma", + "uart_ram_size=\"128\"", + "uart_version=\"2\"", + ], + cfgs: &[ + "cargo:rustc-cfg=esp32p4", + "cargo:rustc-cfg=riscv", + "cargo:rustc-cfg=multi_core", + "cargo:rustc-cfg=soc_has_efuse", + "cargo:rustc-cfg=soc_has_gpio", + "cargo:rustc-cfg=soc_has_hp_sys", + "cargo:rustc-cfg=soc_has_hp_sys_clkrst", + "cargo:rustc-cfg=soc_has_interrupt_core0", + "cargo:rustc-cfg=soc_has_interrupt_core1", + "cargo:rustc-cfg=soc_has_clic", + "cargo:rustc-cfg=soc_has_io_mux", + "cargo:rustc-cfg=soc_has_lp_aon", + "cargo:rustc-cfg=soc_has_lp_aon_clkrst", + "cargo:rustc-cfg=soc_has_lp_sys", + "cargo:rustc-cfg=soc_has_lp_wdt", + "cargo:rustc-cfg=soc_has_lpwr", + "cargo:rustc-cfg=soc_has_pmu", + "cargo:rustc-cfg=soc_has_systimer", + "cargo:rustc-cfg=soc_has_timg0", + "cargo:rustc-cfg=soc_has_timg1", + "cargo:rustc-cfg=soc_has_uart0", + "cargo:rustc-cfg=soc_has_uart1", + "cargo:rustc-cfg=soc_has_uart2", + "cargo:rustc-cfg=soc_has_uart3", + "cargo:rustc-cfg=soc_has_uart4", + "cargo:rustc-cfg=soc_has_spi2", + "cargo:rustc-cfg=soc_has_spi3", + "cargo:rustc-cfg=soc_has_i2c0", + "cargo:rustc-cfg=soc_has_i2c1", + "cargo:rustc-cfg=soc_has_twai0", + "cargo:rustc-cfg=soc_has_twai1", + "cargo:rustc-cfg=soc_has_twai2", + "cargo:rustc-cfg=soc_has_psram", + "cargo:rustc-cfg=soc_has_dma", + "cargo:rustc-cfg=soc_has_dma_ch0", + "cargo:rustc-cfg=soc_has_dma_ch1", + "cargo:rustc-cfg=soc_has_dma_ch2", + "cargo:rustc-cfg=soc_has_usb_device", + "cargo:rustc-cfg=soc_has_sdhost", + "cargo:rustc-cfg=soc_has_ledc", + "cargo:rustc-cfg=soc_has_mcpwm0", + "cargo:rustc-cfg=soc_has_mcpwm1", + "cargo:rustc-cfg=soc_has_pcnt", + "cargo:rustc-cfg=soc_has_rmt", + "cargo:rustc-cfg=soc_has_adc", + "cargo:rustc-cfg=soc_has_aes", + "cargo:rustc-cfg=soc_has_sha", + "cargo:rustc-cfg=soc_has_rsa", + "cargo:rustc-cfg=soc_has_ecc", + "cargo:rustc-cfg=very_large_intr_status", + "cargo:rustc-cfg=spi_octal", + "cargo:rustc-cfg=rom_crc_le", + "cargo:rustc-cfg=rom_crc_be", + "cargo:rustc-cfg=rom_md5_bsd", + "cargo:rustc-cfg=pm_support_ext1_wakeup", + "cargo:rustc-cfg=pm_support_touch_sensor_wakeup", + "cargo:rustc-cfg=dma_driver_supported", + "cargo:rustc-cfg=gpio_driver_supported", + "cargo:rustc-cfg=i2c_master_driver_supported", + "cargo:rustc-cfg=interrupts_driver_supported", + "cargo:rustc-cfg=psram_driver_supported", + "cargo:rustc-cfg=soc_driver_supported", + "cargo:rustc-cfg=spi_master_driver_supported", + "cargo:rustc-cfg=systimer_driver_supported", + "cargo:rustc-cfg=uart_driver_supported", + "cargo:rustc-cfg=usb_serial_jtag_driver_supported", + "cargo:rustc-cfg=i2c_master_i2c0", + "cargo:rustc-cfg=i2c_master_i2c1", + "cargo:rustc-cfg=spi_master_spi2", + "cargo:rustc-cfg=spi_master_spi3", + "cargo:rustc-cfg=uart_uart0", + "cargo:rustc-cfg=uart_uart1", + "cargo:rustc-cfg=uart_uart2", + "cargo:rustc-cfg=uart_uart3", + "cargo:rustc-cfg=uart_uart4", + "cargo:rustc-cfg=aes_dma", + "cargo:rustc-cfg=aes_has_split_text_registers", + "cargo:rustc-cfg=dma_kind=\"gdma\"", + "cargo:rustc-cfg=dma_separate_in_out_interrupts", + "cargo:rustc-cfg=dma_max_priority=\"5\"", + "cargo:rustc-cfg=dma_max_priority_is_set", + "cargo:rustc-cfg=dma_gdma_version=\"2\"", + "cargo:rustc-cfg=dma_gdma_version_is_set", + "cargo:rustc-cfg=ecc_separate_jacobian_point_memory", + "cargo:rustc-cfg=ecc_has_modular_arithmetic", + "cargo:rustc-cfg=ecc_has_point_addition", + "cargo:rustc-cfg=ecc_has_curve_p192", + "cargo:rustc-cfg=ecc_has_curve_p256", + "cargo:rustc-cfg=ecc_has_curve_p384", + "cargo:rustc-cfg=gpio_has_bank_1", + "cargo:rustc-cfg=gpio_gpio_function=\"1\"", + "cargo:rustc-cfg=gpio_constant_0_input=\"62\"", + "cargo:rustc-cfg=gpio_constant_1_input=\"63\"", + "cargo:rustc-cfg=gpio_func_in_sel_offset=\"0\"", + "cargo:rustc-cfg=gpio_input_signal_max=\"203\"", + "cargo:rustc-cfg=gpio_output_signal_max=\"256\"", + "cargo:rustc-cfg=i2c_master_has_fsm_timeouts", + "cargo:rustc-cfg=i2c_master_has_hw_bus_clear", + "cargo:rustc-cfg=i2c_master_has_bus_timeout_enable", + "cargo:rustc-cfg=i2c_master_max_bus_timeout=\"31\"", + "cargo:rustc-cfg=i2c_master_ll_intr_mask=\"262143\"", + "cargo:rustc-cfg=i2c_master_fifo_size=\"32\"", + "cargo:rustc-cfg=interrupts_status_registers=\"3\"", + "cargo:rustc-cfg=interrupt_controller=\"clic\"", + "cargo:rustc-cfg=lp_i2c_master_fifo_size=\"32\"", + "cargo:rustc-cfg=lp_uart_ram_size=\"32\"", + "cargo:rustc-cfg=psram_extmem_origin=\"1207959552\"", + "cargo:rustc-cfg=rng_apb_cycle_wait_num=\"16\"", + "cargo:rustc-cfg=rsa_size_increment=\"32\"", + "cargo:rustc-cfg=rsa_memory_size_bytes=\"384\"", + "cargo:rustc-cfg=sha_dma", + "cargo:rustc-cfg=soc_cpu_has_csr_pc", + "cargo:rustc-cfg=soc_rc_fast_clk_default=\"20000000\"", + "cargo:rustc-cfg=soc_rc_fast_clk_default_is_set", + "cargo:rustc-cfg=soc_has_clock_node_xtal_clk", + "cargo:rustc-cfg=soc_has_clock_node_cpll_clk", + "cargo:rustc-cfg=soc_has_clock_node_spll_clk", + "cargo:rustc-cfg=soc_has_clock_node_mpll_clk", + "cargo:rustc-cfg=soc_has_clock_node_rc_fast_clk", + "cargo:rustc-cfg=soc_has_clock_node_xtal32k_clk", + "cargo:rustc-cfg=soc_has_clock_node_osc_slow_clk", + "cargo:rustc-cfg=soc_has_clock_node_rc_slow_clk", + "cargo:rustc-cfg=soc_has_clock_node_rc32k_clk", + "cargo:rustc-cfg=soc_has_clock_node_pll_f20m", + "cargo:rustc-cfg=soc_has_clock_node_pll_f80m", + "cargo:rustc-cfg=soc_has_clock_node_pll_f120m", + "cargo:rustc-cfg=soc_has_clock_node_pll_f160m", + "cargo:rustc-cfg=soc_has_clock_node_pll_f240m", + "cargo:rustc-cfg=soc_has_clock_node_pll_f25m", + "cargo:rustc-cfg=soc_has_clock_node_pll_f50m", + "cargo:rustc-cfg=soc_has_clock_node_xtal_d2_clk", + "cargo:rustc-cfg=soc_has_clock_node_cpu_root_clk", + "cargo:rustc-cfg=soc_has_clock_node_cpu_clk", + "cargo:rustc-cfg=soc_has_clock_node_apb_clk", + "cargo:rustc-cfg=soc_has_clock_node_lp_fast_clk", + "cargo:rustc-cfg=soc_has_clock_node_lp_slow_clk", + "cargo:rustc-cfg=soc_has_clock_node_uart_function_clock", + "cargo:rustc-cfg=soc_has_clock_node_uart_baud_rate_generator", + "cargo:rustc-cfg=soc_has_clock_node_timg_function_clock", + "cargo:rustc-cfg=soc_has_clock_node_timg_wdt_clock", + "cargo:rustc-cfg=has_dram_region", + "cargo:rustc-cfg=has_dram2_uninit_region", + "cargo:rustc-cfg=spi_master_supports_dma", + "cargo:rustc-cfg=uart_ram_size=\"128\"", + "cargo:rustc-cfg=uart_version=\"2\"", + ], + memory_layout: &MemoryLayout { + regions: &[ + ( + "dram", + MemoryRegion { + address_range: 0x4FF40000..0x4FFC0000, + }, + ), + ( + "dram2_uninit", + MemoryRegion { + address_range: 0x4FF00000..0x4FF40000, + }, + ), + ], + }, + pins: &[ + PinInfo { + pin: 0, + limitations: &[], + }, + PinInfo { + pin: 1, + limitations: &[], + }, + PinInfo { + pin: 2, + limitations: &["jtag"], + }, + PinInfo { + pin: 3, + limitations: &["jtag"], + }, + PinInfo { + pin: 4, + limitations: &["jtag"], + }, + PinInfo { + pin: 5, + limitations: &["jtag"], + }, + PinInfo { + pin: 6, + limitations: &[], + }, + PinInfo { + pin: 7, + limitations: &[], + }, + PinInfo { + pin: 8, + limitations: &[], + }, + PinInfo { + pin: 9, + limitations: &[], + }, + PinInfo { + pin: 10, + limitations: &[], + }, + PinInfo { + pin: 11, + limitations: &[], + }, + PinInfo { + pin: 12, + limitations: &[], + }, + PinInfo { + pin: 13, + limitations: &[], + }, + PinInfo { + pin: 14, + limitations: &[], + }, + PinInfo { + pin: 15, + limitations: &[], + }, + PinInfo { + pin: 16, + limitations: &[], + }, + PinInfo { + pin: 17, + limitations: &[], + }, + PinInfo { + pin: 18, + limitations: &[], + }, + PinInfo { + pin: 19, + limitations: &[], + }, + PinInfo { + pin: 20, + limitations: &[], + }, + PinInfo { + pin: 21, + limitations: &[], + }, + PinInfo { + pin: 22, + limitations: &[], + }, + PinInfo { + pin: 23, + limitations: &[], + }, + PinInfo { + pin: 24, + limitations: &["usb_jtag"], + }, + PinInfo { + pin: 25, + limitations: &["usb_jtag"], + }, + PinInfo { + pin: 26, + limitations: &["usb_jtag"], + }, + PinInfo { + pin: 27, + limitations: &["usb_jtag"], + }, + PinInfo { + pin: 28, + limitations: &[], + }, + PinInfo { + pin: 29, + limitations: &[], + }, + PinInfo { + pin: 30, + limitations: &[], + }, + PinInfo { + pin: 31, + limitations: &[], + }, + PinInfo { + pin: 32, + limitations: &["strapping"], + }, + PinInfo { + pin: 33, + limitations: &["strapping"], + }, + PinInfo { + pin: 34, + limitations: &["strapping"], + }, + PinInfo { + pin: 35, + limitations: &["strapping"], + }, + PinInfo { + pin: 36, + limitations: &["strapping"], + }, + PinInfo { + pin: 37, + limitations: &["strapping"], + }, + PinInfo { + pin: 38, + limitations: &["strapping"], + }, + PinInfo { + pin: 39, + limitations: &[], + }, + PinInfo { + pin: 40, + limitations: &[], + }, + PinInfo { + pin: 41, + limitations: &[], + }, + PinInfo { + pin: 42, + limitations: &[], + }, + PinInfo { + pin: 43, + limitations: &[], + }, + PinInfo { + pin: 44, + limitations: &[], + }, + PinInfo { + pin: 45, + limitations: &[], + }, + PinInfo { + pin: 46, + limitations: &[], + }, + PinInfo { + pin: 47, + limitations: &[], + }, + PinInfo { + pin: 48, + limitations: &[], + }, + PinInfo { + pin: 49, + limitations: &[], + }, + PinInfo { + pin: 50, + limitations: &[], + }, + PinInfo { + pin: 51, + limitations: &[], + }, + PinInfo { + pin: 52, + limitations: &[], + }, + PinInfo { + pin: 53, + limitations: &[], + }, + PinInfo { + pin: 54, + limitations: &[], + }, + ], + }, Self::Esp32s2 => Config { architecture: "xtensa", target: "xtensa-esp32s2-none-elf", @@ -5905,6 +6447,27 @@ pub fn emit_check_cfg_directives() { println!("cargo:rustc-check-cfg=cfg(soc_has_clock_node_pll_f48m_clk)"); println!("cargo:rustc-check-cfg=cfg(soc_has_clock_node_pll_lp_clk)"); println!("cargo:rustc-check-cfg=cfg(timergroup_rc_fast_calibration_tick_enable)"); + println!("cargo:rustc-check-cfg=cfg(esp32p4)"); + println!("cargo:rustc-check-cfg=cfg(soc_has_hp_sys_clkrst)"); + println!("cargo:rustc-check-cfg=cfg(soc_has_interrupt_core1)"); + println!("cargo:rustc-check-cfg=cfg(soc_has_clic)"); + println!("cargo:rustc-check-cfg=cfg(soc_has_lp_aon_clkrst)"); + println!("cargo:rustc-check-cfg=cfg(soc_has_lp_sys)"); + println!("cargo:rustc-check-cfg=cfg(soc_has_uart3)"); + println!("cargo:rustc-check-cfg=cfg(soc_has_uart4)"); + println!("cargo:rustc-check-cfg=cfg(soc_has_twai2)"); + println!("cargo:rustc-check-cfg=cfg(soc_has_adc)"); + println!("cargo:rustc-check-cfg=cfg(very_large_intr_status)"); + println!("cargo:rustc-check-cfg=cfg(spi_octal)"); + println!("cargo:rustc-check-cfg=cfg(uart_uart3)"); + println!("cargo:rustc-check-cfg=cfg(uart_uart4)"); + println!("cargo:rustc-check-cfg=cfg(soc_has_clock_node_cpll_clk)"); + println!("cargo:rustc-check-cfg=cfg(soc_has_clock_node_spll_clk)"); + println!("cargo:rustc-check-cfg=cfg(soc_has_clock_node_mpll_clk)"); + println!("cargo:rustc-check-cfg=cfg(soc_has_clock_node_rc32k_clk)"); + println!("cargo:rustc-check-cfg=cfg(soc_has_clock_node_pll_f25m)"); + println!("cargo:rustc-check-cfg=cfg(soc_has_clock_node_pll_f50m)"); + println!("cargo:rustc-check-cfg=cfg(soc_has_clock_node_cpu_root_clk)"); println!("cargo:rustc-check-cfg=cfg(esp32s2)"); println!("cargo:rustc-check-cfg=cfg(soc_has_dedicated_gpio)"); println!("cargo:rustc-check-cfg=cfg(soc_has_pms)"); @@ -5923,7 +6486,6 @@ pub fn emit_check_cfg_directives() { println!("cargo:rustc-check-cfg=cfg(soc_has_clock_node_ref_tick_ck8m)"); println!("cargo:rustc-check-cfg=cfg(spi_master_has_octal)"); println!("cargo:rustc-check-cfg=cfg(esp32s3)"); - println!("cargo:rustc-check-cfg=cfg(soc_has_interrupt_core1)"); println!("cargo:rustc-check-cfg=cfg(soc_has_lcd_cam)"); println!("cargo:rustc-check-cfg=cfg(soc_has_peri_backup)"); println!("cargo:rustc-check-cfg=cfg(soc_has_rtc_cntl)"); @@ -5940,13 +6502,16 @@ pub fn emit_check_cfg_directives() { println!("cargo:rustc-check-cfg=cfg(dma_kind, values(\"pdma\",\"gdma\"))"); println!("cargo:rustc-check-cfg=cfg(gpio_gpio_function, values(\"2\",\"1\"))"); println!( - "cargo:rustc-check-cfg=cfg(gpio_constant_0_input, values(\"48\",\"31\",\"96\",\"60\"))" + "cargo:rustc-check-cfg=cfg(gpio_constant_0_input, \ + values(\"48\",\"31\",\"96\",\"60\",\"62\"))" + ); + println!( + "cargo:rustc-check-cfg=cfg(gpio_constant_1_input, values(\"56\",\"30\",\"64\",\"63\"))" ); - println!("cargo:rustc-check-cfg=cfg(gpio_constant_1_input, values(\"56\",\"30\",\"64\"))"); println!("cargo:rustc-check-cfg=cfg(gpio_func_in_sel_offset, values(\"0\"))"); println!( "cargo:rustc-check-cfg=cfg(gpio_input_signal_max, \ - values(\"206\",\"100\",\"116\",\"124\",\"242\",\"255\"))" + values(\"206\",\"100\",\"116\",\"124\",\"203\",\"242\",\"255\"))" ); println!("cargo:rustc-check-cfg=cfg(gpio_output_signal_max, values(\"256\",\"128\"))"); println!( @@ -5966,7 +6531,7 @@ pub fn emit_check_cfg_directives() { ); println!( "cargo:rustc-check-cfg=cfg(psram_extmem_origin, \ - values(\"1065353216\",\"1107296256\",\"1062207488\",\"1006632960\"))" + values(\"1065353216\",\"1107296256\",\"1207959552\",\"1062207488\",\"1006632960\"))" ); println!( "cargo:rustc-check-cfg=cfg(rmt_ram_start, \ @@ -5978,7 +6543,8 @@ pub fn emit_check_cfg_directives() { println!("cargo:rustc-check-cfg=cfg(rsa_size_increment, values(\"512\",\"32\"))"); println!("cargo:rustc-check-cfg=cfg(rsa_memory_size_bytes, values(\"512\",\"384\"))"); println!( - "cargo:rustc-check-cfg=cfg(soc_rc_fast_clk_default, values(\"8500000\",\"17500000\"))" + "cargo:rustc-check-cfg=cfg(soc_rc_fast_clk_default, \ + values(\"8500000\",\"17500000\",\"20000000\"))" ); println!("cargo:rustc-check-cfg=cfg(uart_ram_size, values(\"128\"))"); println!("cargo:rustc-check-cfg=cfg(uart_version, values(\"1\",\"2\"))"); @@ -5986,7 +6552,7 @@ pub fn emit_check_cfg_directives() { println!("cargo:rustc-check-cfg=cfg(dma_max_priority, values(\"9\",\"5\"))"); println!("cargo:rustc-check-cfg=cfg(dma_gdma_version, values(\"1\",\"2\"))"); println!("cargo:rustc-check-cfg=cfg(phy_backed_up_digital_register_count, values(\"21\"))"); - println!("cargo:rustc-check-cfg=cfg(lp_i2c_master_fifo_size, values(\"16\"))"); + println!("cargo:rustc-check-cfg=cfg(lp_i2c_master_fifo_size, values(\"16\",\"32\"))"); println!("cargo:rustc-check-cfg=cfg(lp_uart_ram_size, values(\"32\"))"); println!("cargo:rustc-check-cfg=cfg(parl_io_version, values(\"2\",\"1\"))"); println!("cargo:rustc-check-cfg=cfg(soc_cpu_csr_prv_mode, values(\"2064\",\"3088\"))"); diff --git a/esp-metadata-generated/src/_generated_esp32p4.rs b/esp-metadata-generated/src/_generated_esp32p4.rs new file mode 100644 index 00000000000..669df1e3d22 --- /dev/null +++ b/esp-metadata-generated/src/_generated_esp32p4.rs @@ -0,0 +1,4382 @@ +// Do NOT edit this file directly. Make your changes to esp-metadata, +// then run `cargo xtask update-metadata`. + +/// The name of the chip as `&str` +/// +/// # Example +/// +/// ```rust, no_run +/// use esp_hal::chip; +/// let chip_name = chip!(); +#[doc = concat!("assert_eq!(chip_name, ", chip!(), ")")] +/// ``` +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! chip { + () => { + "esp32p4" + }; +} +/// The pretty name of the chip as `&str` +/// +/// # Example +/// +/// ```rust, no_run +/// use esp_hal::chip; +/// let chip_name = chip_pretty!(); +#[doc = concat!("assert_eq!(chip_name, ", chip_pretty!(), ")")] +/// ``` +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! chip_pretty { + () => { + "ESP32-P4" + }; +} +/// The properties of this chip and its drivers. +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! property { + ("chip") => { + "esp32p4" + }; + ("arch") => { + "riscv" + }; + ("cores") => { + 2 + }; + ("cores", str) => { + stringify!(2) + }; + ("trm") => { + "https://www.espressif.com/sites/default/files/documentation/esp32-p4_technical_reference_manual_en.pdf" + }; + ("aes.dma") => { + true + }; + ("aes.has_split_text_registers") => { + true + }; + ("aes.endianness_configurable") => { + false + }; + ("assist_debug.has_sp_monitor") => { + false + }; + ("assist_debug.has_region_monitor") => { + false + }; + ("dma.kind") => { + "gdma" + }; + ("dma.supports_mem2mem") => { + false + }; + ("dma.can_access_psram") => { + false + }; + ("dma.ext_mem_configurable_block_size") => { + false + }; + ("dma.separate_in_out_interrupts") => { + true + }; + ("dma.max_priority") => { + 5 + }; + ("dma.max_priority", str) => { + stringify!(5) + }; + ("dma.gdma_version") => { + 2 + }; + ("dma.gdma_version", str) => { + stringify!(2) + }; + ("ecc.zero_extend_writes") => { + false + }; + ("ecc.separate_jacobian_point_memory") => { + true + }; + ("ecc.has_memory_clock_gate") => { + false + }; + ("ecc.supports_enhanced_security") => { + false + }; + ("ecc.mem_block_size") => { + 48 + }; + ("gpio.has_bank_1") => { + true + }; + ("gpio.gpio_function") => { + 1 + }; + ("gpio.gpio_function", str) => { + stringify!(1) + }; + ("gpio.constant_0_input") => { + 62 + }; + ("gpio.constant_0_input", str) => { + stringify!(62) + }; + ("gpio.constant_1_input") => { + 63 + }; + ("gpio.constant_1_input", str) => { + stringify!(63) + }; + ("gpio.remap_iomux_pin_registers") => { + false + }; + ("gpio.func_in_sel_offset") => { + 0 + }; + ("gpio.func_in_sel_offset", str) => { + stringify!(0) + }; + ("gpio.input_signal_max") => { + 203 + }; + ("gpio.input_signal_max", str) => { + stringify!(203) + }; + ("gpio.output_signal_max") => { + 256 + }; + ("gpio.output_signal_max", str) => { + stringify!(256) + }; + ("i2c_master.has_fsm_timeouts") => { + true + }; + ("i2c_master.has_hw_bus_clear") => { + true + }; + ("i2c_master.has_bus_timeout_enable") => { + true + }; + ("i2c_master.separate_filter_config_registers") => { + false + }; + ("i2c_master.can_estimate_nack_reason") => { + false + }; + ("i2c_master.has_conf_update") => { + false + }; + ("i2c_master.has_reliable_fsm_reset") => { + false + }; + ("i2c_master.has_arbitration_en") => { + false + }; + ("i2c_master.has_tx_fifo_watermark") => { + false + }; + ("i2c_master.bus_timeout_is_exponential") => { + false + }; + ("i2c_master.max_bus_timeout") => { + 31 + }; + ("i2c_master.max_bus_timeout", str) => { + stringify!(31) + }; + ("i2c_master.ll_intr_mask") => { + 262143 + }; + ("i2c_master.ll_intr_mask", str) => { + stringify!(262143) + }; + ("i2c_master.fifo_size") => { + 32 + }; + ("i2c_master.fifo_size", str) => { + stringify!(32) + }; + ("interrupts.status_registers") => { + 3 + }; + ("interrupts.status_registers", str) => { + stringify!(3) + }; + ("interrupts.disabled_interrupt") => { + 0 + }; + ("lp_i2c_master.fifo_size") => { + 32 + }; + ("lp_i2c_master.fifo_size", str) => { + stringify!(32) + }; + ("lp_uart.ram_size") => { + 32 + }; + ("lp_uart.ram_size", str) => { + stringify!(32) + }; + ("psram.octal_spi") => { + false + }; + ("psram.extmem_origin") => { + 1207959552 + }; + ("psram.extmem_origin", str) => { + stringify!(1207959552) + }; + ("rng.apb_cycle_wait_num") => { + 16 + }; + ("rng.apb_cycle_wait_num", str) => { + stringify!(16) + }; + ("rng.trng_supported") => { + false + }; + ("rsa.size_increment") => { + 32 + }; + ("rsa.size_increment", str) => { + stringify!(32) + }; + ("rsa.memory_size_bytes") => { + 384 + }; + ("rsa.memory_size_bytes", str) => { + stringify!(384) + }; + ("sha.dma") => { + true + }; + ("sleep.light_sleep") => { + false + }; + ("sleep.deep_sleep") => { + false + }; + ("soc.cpu_has_branch_predictor") => { + false + }; + ("soc.cpu_has_csr_pc") => { + true + }; + ("soc.multi_core_enabled") => { + false + }; + ("soc.rc_fast_clk_default") => { + 20000000 + }; + ("soc.rc_fast_clk_default", str) => { + stringify!(20000000) + }; + ("clock_tree.cpu_clk.divisor") => { + (0, 255) + }; + ("clock_tree.apb_clk.divisor") => { + (0, 255) + }; + ("clock_tree.uart.function_clock.div_num") => { + (0, 255) + }; + ("clock_tree.uart.baud_rate_generator.fractional") => { + (0, 15) + }; + ("clock_tree.uart.baud_rate_generator.integral") => { + (0, 4095) + }; + ("spi_master.supports_dma") => { + true + }; + ("spi_master.has_octal") => { + false + }; + ("spi_master.has_app_interrupts") => { + false + }; + ("spi_master.has_dma_segmented_transfer") => { + false + }; + ("spi_master.has_clk_pre_div") => { + false + }; + ("spi_slave.supports_dma") => { + false + }; + ("uart.ram_size") => { + 128 + }; + ("uart.ram_size", str) => { + stringify!(128) + }; + ("uart.version") => { + 2 + }; + ("uart.version", str) => { + stringify!(2) + }; + ("uart.peripheral_controls_mem_clk") => { + false + }; + ("uart.has_sclk_divider") => { + false + }; + ("uhci.combined_uart_selector_field") => { + false + }; +} +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! for_each_aes_key_length { + ($($pattern:tt => $code:tt;)*) => { + macro_rules! _for_each_inner_aes_key_length { $(($pattern) => $code;)* ($other : + tt) => {} } _for_each_inner_aes_key_length!((128)); + _for_each_inner_aes_key_length!((256)); _for_each_inner_aes_key_length!((128, 0, + 4)); _for_each_inner_aes_key_length!((256, 2, 6)); + _for_each_inner_aes_key_length!((bits(128), (256))); + _for_each_inner_aes_key_length!((modes(128, 0, 4), (256, 2, 6))); + }; +} +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! for_each_ecc_working_mode { + ($($pattern:tt => $code:tt;)*) => { + macro_rules! _for_each_inner_ecc_working_mode { $(($pattern) => $code;)* ($other + : tt) => {} } _for_each_inner_ecc_working_mode!((0, AffinePointMultiplication)); + _for_each_inner_ecc_working_mode!((2, AffinePointVerification)); + _for_each_inner_ecc_working_mode!((3, AffinePointVerificationAndMultiplication)); + _for_each_inner_ecc_working_mode!((4, JacobianPointMultiplication)); + _for_each_inner_ecc_working_mode!((5, AffinePointAddition)); + _for_each_inner_ecc_working_mode!((6, JacobianPointVerification)); + _for_each_inner_ecc_working_mode!((7, + AffinePointVerificationAndJacobianPointMultiplication)); + _for_each_inner_ecc_working_mode!((8, ModularAddition)); + _for_each_inner_ecc_working_mode!((all(0, AffinePointMultiplication), (2, + AffinePointVerification), (3, AffinePointVerificationAndMultiplication), (4, + JacobianPointMultiplication), (5, AffinePointAddition), (6, + JacobianPointVerification), (7, + AffinePointVerificationAndJacobianPointMultiplication), (8, ModularAddition))); + }; +} +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! for_each_ecc_curve { + ($($pattern:tt => $code:tt;)*) => { + macro_rules! _for_each_inner_ecc_curve { $(($pattern) => $code;)* ($other : tt) + => {} } _for_each_inner_ecc_curve!((0, P192, 192)); + _for_each_inner_ecc_curve!((1, P256, 256)); _for_each_inner_ecc_curve!((2, P384, + 384)); _for_each_inner_ecc_curve!((all(0, P192, 192), (1, P256, 256), (2, P384, + 384))); + }; +} +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! for_each_interrupt { + ($($pattern:tt => $code:tt;)*) => { + macro_rules! _for_each_inner_interrupt { $(($pattern) => $code;)* ($other : tt) + => {} } _for_each_inner_interrupt!(([disabled 0] 0)); + _for_each_inner_interrupt!(([reserved 0] 1)); + _for_each_inner_interrupt!(([reserved 1] 2)); + _for_each_inner_interrupt!(([reserved 2] 3)); + _for_each_inner_interrupt!(([reserved 3] 4)); + _for_each_inner_interrupt!(([reserved 4] 5)); + _for_each_inner_interrupt!(([reserved 5] 6)); + _for_each_inner_interrupt!(([reserved 6] 7)); + _for_each_inner_interrupt!(([reserved 7] 8)); + _for_each_inner_interrupt!(([reserved 8] 9)); + _for_each_inner_interrupt!(([reserved 9] 10)); + _for_each_inner_interrupt!(([reserved 10] 11)); + _for_each_inner_interrupt!(([reserved 11] 12)); + _for_each_inner_interrupt!(([reserved 12] 13)); + _for_each_inner_interrupt!(([reserved 13] 14)); + _for_each_inner_interrupt!(([reserved 14] 15)); + _for_each_inner_interrupt!(([vector 0] 16)); _for_each_inner_interrupt!(([vector + 1] 17)); _for_each_inner_interrupt!(([vector 2] 18)); + _for_each_inner_interrupt!(([vector 3] 19)); _for_each_inner_interrupt!(([vector + 4] 20)); _for_each_inner_interrupt!(([vector 5] 21)); + _for_each_inner_interrupt!(([vector 6] 22)); _for_each_inner_interrupt!(([vector + 7] 23)); _for_each_inner_interrupt!(([direct_bindable 0] 24)); + _for_each_inner_interrupt!(([direct_bindable 1] 25)); + _for_each_inner_interrupt!(([direct_bindable 2] 26)); + _for_each_inner_interrupt!(([direct_bindable 3] 27)); + _for_each_inner_interrupt!(([direct_bindable 4] 28)); + _for_each_inner_interrupt!(([direct_bindable 5] 29)); + _for_each_inner_interrupt!(([direct_bindable 6] 30)); + _for_each_inner_interrupt!(([direct_bindable 7] 31)); + _for_each_inner_interrupt!(([direct_bindable 8] 32)); + _for_each_inner_interrupt!(([direct_bindable 9] 33)); + _for_each_inner_interrupt!(([direct_bindable 10] 34)); + _for_each_inner_interrupt!(([direct_bindable 11] 35)); + _for_each_inner_interrupt!(([direct_bindable 12] 36)); + _for_each_inner_interrupt!(([direct_bindable 13] 37)); + _for_each_inner_interrupt!(([direct_bindable 14] 38)); + _for_each_inner_interrupt!(([direct_bindable 15] 39)); + _for_each_inner_interrupt!(([direct_bindable 16] 40)); + _for_each_inner_interrupt!(([direct_bindable 17] 41)); + _for_each_inner_interrupt!(([direct_bindable 18] 42)); + _for_each_inner_interrupt!(([direct_bindable 19] 43)); + _for_each_inner_interrupt!(([direct_bindable 20] 44)); + _for_each_inner_interrupt!(([direct_bindable 21] 45)); + _for_each_inner_interrupt!(([direct_bindable 22] 46)); + _for_each_inner_interrupt!(([direct_bindable 23] 47)); + _for_each_inner_interrupt!((all([disabled 0] 0), ([reserved 0] 1), ([reserved 1] + 2), ([reserved 2] 3), ([reserved 3] 4), ([reserved 4] 5), ([reserved 5] 6), + ([reserved 6] 7), ([reserved 7] 8), ([reserved 8] 9), ([reserved 9] 10), + ([reserved 10] 11), ([reserved 11] 12), ([reserved 12] 13), ([reserved 13] 14), + ([reserved 14] 15), ([vector 0] 16), ([vector 1] 17), ([vector 2] 18), ([vector + 3] 19), ([vector 4] 20), ([vector 5] 21), ([vector 6] 22), ([vector 7] 23), + ([direct_bindable 0] 24), ([direct_bindable 1] 25), ([direct_bindable 2] 26), + ([direct_bindable 3] 27), ([direct_bindable 4] 28), ([direct_bindable 5] 29), + ([direct_bindable 6] 30), ([direct_bindable 7] 31), ([direct_bindable 8] 32), + ([direct_bindable 9] 33), ([direct_bindable 10] 34), ([direct_bindable 11] 35), + ([direct_bindable 12] 36), ([direct_bindable 13] 37), ([direct_bindable 14] 38), + ([direct_bindable 15] 39), ([direct_bindable 16] 40), ([direct_bindable 17] 41), + ([direct_bindable 18] 42), ([direct_bindable 19] 43), ([direct_bindable 20] 44), + ([direct_bindable 21] 45), ([direct_bindable 22] 46), ([direct_bindable 23] + 47))); + }; +} +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! for_each_classified_interrupt { + ($($pattern:tt => $code:tt;)*) => { + macro_rules! _for_each_inner_classified_interrupt { $(($pattern) => $code;)* + ($other : tt) => {} } _for_each_inner_classified_interrupt!(([direct_bindable 0] + 24)); _for_each_inner_classified_interrupt!(([direct_bindable 1] 25)); + _for_each_inner_classified_interrupt!(([direct_bindable 2] 26)); + _for_each_inner_classified_interrupt!(([direct_bindable 3] 27)); + _for_each_inner_classified_interrupt!(([direct_bindable 4] 28)); + _for_each_inner_classified_interrupt!(([direct_bindable 5] 29)); + _for_each_inner_classified_interrupt!(([direct_bindable 6] 30)); + _for_each_inner_classified_interrupt!(([direct_bindable 7] 31)); + _for_each_inner_classified_interrupt!(([direct_bindable 8] 32)); + _for_each_inner_classified_interrupt!(([direct_bindable 9] 33)); + _for_each_inner_classified_interrupt!(([direct_bindable 10] 34)); + _for_each_inner_classified_interrupt!(([direct_bindable 11] 35)); + _for_each_inner_classified_interrupt!(([direct_bindable 12] 36)); + _for_each_inner_classified_interrupt!(([direct_bindable 13] 37)); + _for_each_inner_classified_interrupt!(([direct_bindable 14] 38)); + _for_each_inner_classified_interrupt!(([direct_bindable 15] 39)); + _for_each_inner_classified_interrupt!(([direct_bindable 16] 40)); + _for_each_inner_classified_interrupt!(([direct_bindable 17] 41)); + _for_each_inner_classified_interrupt!(([direct_bindable 18] 42)); + _for_each_inner_classified_interrupt!(([direct_bindable 19] 43)); + _for_each_inner_classified_interrupt!(([direct_bindable 20] 44)); + _for_each_inner_classified_interrupt!(([direct_bindable 21] 45)); + _for_each_inner_classified_interrupt!(([direct_bindable 22] 46)); + _for_each_inner_classified_interrupt!(([direct_bindable 23] 47)); + _for_each_inner_classified_interrupt!(([vector 0] 16)); + _for_each_inner_classified_interrupt!(([vector 1] 17)); + _for_each_inner_classified_interrupt!(([vector 2] 18)); + _for_each_inner_classified_interrupt!(([vector 3] 19)); + _for_each_inner_classified_interrupt!(([vector 4] 20)); + _for_each_inner_classified_interrupt!(([vector 5] 21)); + _for_each_inner_classified_interrupt!(([vector 6] 22)); + _for_each_inner_classified_interrupt!(([vector 7] 23)); + _for_each_inner_classified_interrupt!(([reserved 0] 1)); + _for_each_inner_classified_interrupt!(([reserved 1] 2)); + _for_each_inner_classified_interrupt!(([reserved 2] 3)); + _for_each_inner_classified_interrupt!(([reserved 3] 4)); + _for_each_inner_classified_interrupt!(([reserved 4] 5)); + _for_each_inner_classified_interrupt!(([reserved 5] 6)); + _for_each_inner_classified_interrupt!(([reserved 6] 7)); + _for_each_inner_classified_interrupt!(([reserved 7] 8)); + _for_each_inner_classified_interrupt!(([reserved 8] 9)); + _for_each_inner_classified_interrupt!(([reserved 9] 10)); + _for_each_inner_classified_interrupt!(([reserved 10] 11)); + _for_each_inner_classified_interrupt!(([reserved 11] 12)); + _for_each_inner_classified_interrupt!(([reserved 12] 13)); + _for_each_inner_classified_interrupt!(([reserved 13] 14)); + _for_each_inner_classified_interrupt!(([reserved 14] 15)); + _for_each_inner_classified_interrupt!((direct_bindable([direct_bindable 0] 24), + ([direct_bindable 1] 25), ([direct_bindable 2] 26), ([direct_bindable 3] 27), + ([direct_bindable 4] 28), ([direct_bindable 5] 29), ([direct_bindable 6] 30), + ([direct_bindable 7] 31), ([direct_bindable 8] 32), ([direct_bindable 9] 33), + ([direct_bindable 10] 34), ([direct_bindable 11] 35), ([direct_bindable 12] 36), + ([direct_bindable 13] 37), ([direct_bindable 14] 38), ([direct_bindable 15] 39), + ([direct_bindable 16] 40), ([direct_bindable 17] 41), ([direct_bindable 18] 42), + ([direct_bindable 19] 43), ([direct_bindable 20] 44), ([direct_bindable 21] 45), + ([direct_bindable 22] 46), ([direct_bindable 23] 47))); + _for_each_inner_classified_interrupt!((vector([vector 0] 16), ([vector 1] 17), + ([vector 2] 18), ([vector 3] 19), ([vector 4] 20), ([vector 5] 21), ([vector 6] + 22), ([vector 7] 23))); _for_each_inner_classified_interrupt!((reserved([reserved + 0] 1), ([reserved 1] 2), ([reserved 2] 3), ([reserved 3] 4), ([reserved 4] 5), + ([reserved 5] 6), ([reserved 6] 7), ([reserved 7] 8), ([reserved 8] 9), + ([reserved 9] 10), ([reserved 10] 11), ([reserved 11] 12), ([reserved 12] 13), + ([reserved 13] 14), ([reserved 14] 15))); + }; +} +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! for_each_interrupt_priority { + ($($pattern:tt => $code:tt;)*) => { + macro_rules! _for_each_inner_interrupt_priority { $(($pattern) => $code;)* + ($other : tt) => {} } _for_each_inner_interrupt_priority!((0, 1, Priority1, + Level1)); _for_each_inner_interrupt_priority!((1, 2, Priority2, Level2)); + _for_each_inner_interrupt_priority!((2, 3, Priority3, Level3)); + _for_each_inner_interrupt_priority!((3, 4, Priority4, Level4)); + _for_each_inner_interrupt_priority!((4, 5, Priority5, Level5)); + _for_each_inner_interrupt_priority!((5, 6, Priority6, Level6)); + _for_each_inner_interrupt_priority!((6, 7, Priority7, Level7)); + _for_each_inner_interrupt_priority!((7, 8, Priority8, Level8)); + _for_each_inner_interrupt_priority!((all(0, 1, Priority1, Level1), (1, 2, + Priority2, Level2), (2, 3, Priority3, Level3), (3, 4, Priority4, Level4), (4, 5, + Priority5, Level5), (5, 6, Priority6, Level6), (6, 7, Priority7, Level7), (7, 8, + Priority8, Level8))); + }; +} +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! for_each_sw_interrupt { + ($($pattern:tt => $code:tt;)*) => { + macro_rules! _for_each_inner_sw_interrupt { $(($pattern) => $code;)* ($other : + tt) => {} } _for_each_inner_sw_interrupt!((0, FROM_CPU_INTR0, + software_interrupt0)); _for_each_inner_sw_interrupt!((1, FROM_CPU_INTR1, + software_interrupt1)); _for_each_inner_sw_interrupt!((2, FROM_CPU_INTR2, + software_interrupt2)); _for_each_inner_sw_interrupt!((3, FROM_CPU_INTR3, + software_interrupt3)); _for_each_inner_sw_interrupt!((all(0, FROM_CPU_INTR0, + software_interrupt0), (1, FROM_CPU_INTR1, software_interrupt1), (2, + FROM_CPU_INTR2, software_interrupt2), (3, FROM_CPU_INTR3, software_interrupt3))); + }; +} +#[macro_export] +macro_rules! sw_interrupt_delay { + () => { + unsafe { + ::core::arch::asm!("nop"); + ::core::arch::asm!("nop"); + ::core::arch::asm!("nop"); + ::core::arch::asm!("nop"); + ::core::arch::asm!("nop"); + ::core::arch::asm!("nop"); + ::core::arch::asm!("nop"); + ::core::arch::asm!("nop"); + ::core::arch::asm!("nop"); + ::core::arch::asm!("nop"); + ::core::arch::asm!("nop"); + ::core::arch::asm!("nop"); + ::core::arch::asm!("nop"); + ::core::arch::asm!("nop"); + ::core::arch::asm!("nop"); + ::core::arch::asm!("nop"); + ::core::arch::asm!("nop"); + ::core::arch::asm!("nop"); + ::core::arch::asm!("nop"); + ::core::arch::asm!("nop"); + ::core::arch::asm!("nop"); + ::core::arch::asm!("nop"); + ::core::arch::asm!("nop"); + ::core::arch::asm!("nop"); + } + }; +} +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! for_each_rsa_exponentiation { + ($($pattern:tt => $code:tt;)*) => { + macro_rules! _for_each_inner_rsa_exponentiation { $(($pattern) => $code;)* + ($other : tt) => {} } _for_each_inner_rsa_exponentiation!((32)); + _for_each_inner_rsa_exponentiation!((64)); + _for_each_inner_rsa_exponentiation!((96)); + _for_each_inner_rsa_exponentiation!((128)); + _for_each_inner_rsa_exponentiation!((160)); + _for_each_inner_rsa_exponentiation!((192)); + _for_each_inner_rsa_exponentiation!((224)); + _for_each_inner_rsa_exponentiation!((256)); + _for_each_inner_rsa_exponentiation!((288)); + _for_each_inner_rsa_exponentiation!((320)); + _for_each_inner_rsa_exponentiation!((352)); + _for_each_inner_rsa_exponentiation!((384)); + _for_each_inner_rsa_exponentiation!((416)); + _for_each_inner_rsa_exponentiation!((448)); + _for_each_inner_rsa_exponentiation!((480)); + _for_each_inner_rsa_exponentiation!((512)); + _for_each_inner_rsa_exponentiation!((544)); + _for_each_inner_rsa_exponentiation!((576)); + _for_each_inner_rsa_exponentiation!((608)); + _for_each_inner_rsa_exponentiation!((640)); + _for_each_inner_rsa_exponentiation!((672)); + _for_each_inner_rsa_exponentiation!((704)); + _for_each_inner_rsa_exponentiation!((736)); + _for_each_inner_rsa_exponentiation!((768)); + _for_each_inner_rsa_exponentiation!((800)); + _for_each_inner_rsa_exponentiation!((832)); + _for_each_inner_rsa_exponentiation!((864)); + _for_each_inner_rsa_exponentiation!((896)); + _for_each_inner_rsa_exponentiation!((928)); + _for_each_inner_rsa_exponentiation!((960)); + _for_each_inner_rsa_exponentiation!((992)); + _for_each_inner_rsa_exponentiation!((1024)); + _for_each_inner_rsa_exponentiation!((1056)); + _for_each_inner_rsa_exponentiation!((1088)); + _for_each_inner_rsa_exponentiation!((1120)); + _for_each_inner_rsa_exponentiation!((1152)); + _for_each_inner_rsa_exponentiation!((1184)); + _for_each_inner_rsa_exponentiation!((1216)); + _for_each_inner_rsa_exponentiation!((1248)); + _for_each_inner_rsa_exponentiation!((1280)); + _for_each_inner_rsa_exponentiation!((1312)); + _for_each_inner_rsa_exponentiation!((1344)); + _for_each_inner_rsa_exponentiation!((1376)); + _for_each_inner_rsa_exponentiation!((1408)); + _for_each_inner_rsa_exponentiation!((1440)); + _for_each_inner_rsa_exponentiation!((1472)); + _for_each_inner_rsa_exponentiation!((1504)); + _for_each_inner_rsa_exponentiation!((1536)); + _for_each_inner_rsa_exponentiation!((1568)); + _for_each_inner_rsa_exponentiation!((1600)); + _for_each_inner_rsa_exponentiation!((1632)); + _for_each_inner_rsa_exponentiation!((1664)); + _for_each_inner_rsa_exponentiation!((1696)); + _for_each_inner_rsa_exponentiation!((1728)); + _for_each_inner_rsa_exponentiation!((1760)); + _for_each_inner_rsa_exponentiation!((1792)); + _for_each_inner_rsa_exponentiation!((1824)); + _for_each_inner_rsa_exponentiation!((1856)); + _for_each_inner_rsa_exponentiation!((1888)); + _for_each_inner_rsa_exponentiation!((1920)); + _for_each_inner_rsa_exponentiation!((1952)); + _for_each_inner_rsa_exponentiation!((1984)); + _for_each_inner_rsa_exponentiation!((2016)); + _for_each_inner_rsa_exponentiation!((2048)); + _for_each_inner_rsa_exponentiation!((2080)); + _for_each_inner_rsa_exponentiation!((2112)); + _for_each_inner_rsa_exponentiation!((2144)); + _for_each_inner_rsa_exponentiation!((2176)); + _for_each_inner_rsa_exponentiation!((2208)); + _for_each_inner_rsa_exponentiation!((2240)); + _for_each_inner_rsa_exponentiation!((2272)); + _for_each_inner_rsa_exponentiation!((2304)); + _for_each_inner_rsa_exponentiation!((2336)); + _for_each_inner_rsa_exponentiation!((2368)); + _for_each_inner_rsa_exponentiation!((2400)); + _for_each_inner_rsa_exponentiation!((2432)); + _for_each_inner_rsa_exponentiation!((2464)); + _for_each_inner_rsa_exponentiation!((2496)); + _for_each_inner_rsa_exponentiation!((2528)); + _for_each_inner_rsa_exponentiation!((2560)); + _for_each_inner_rsa_exponentiation!((2592)); + _for_each_inner_rsa_exponentiation!((2624)); + _for_each_inner_rsa_exponentiation!((2656)); + _for_each_inner_rsa_exponentiation!((2688)); + _for_each_inner_rsa_exponentiation!((2720)); + _for_each_inner_rsa_exponentiation!((2752)); + _for_each_inner_rsa_exponentiation!((2784)); + _for_each_inner_rsa_exponentiation!((2816)); + _for_each_inner_rsa_exponentiation!((2848)); + _for_each_inner_rsa_exponentiation!((2880)); + _for_each_inner_rsa_exponentiation!((2912)); + _for_each_inner_rsa_exponentiation!((2944)); + _for_each_inner_rsa_exponentiation!((2976)); + _for_each_inner_rsa_exponentiation!((3008)); + _for_each_inner_rsa_exponentiation!((3040)); + _for_each_inner_rsa_exponentiation!((3072)); + _for_each_inner_rsa_exponentiation!((all(32), (64), (96), (128), (160), (192), + (224), (256), (288), (320), (352), (384), (416), (448), (480), (512), (544), + (576), (608), (640), (672), (704), (736), (768), (800), (832), (864), (896), + (928), (960), (992), (1024), (1056), (1088), (1120), (1152), (1184), (1216), + (1248), (1280), (1312), (1344), (1376), (1408), (1440), (1472), (1504), (1536), + (1568), (1600), (1632), (1664), (1696), (1728), (1760), (1792), (1824), (1856), + (1888), (1920), (1952), (1984), (2016), (2048), (2080), (2112), (2144), (2176), + (2208), (2240), (2272), (2304), (2336), (2368), (2400), (2432), (2464), (2496), + (2528), (2560), (2592), (2624), (2656), (2688), (2720), (2752), (2784), (2816), + (2848), (2880), (2912), (2944), (2976), (3008), (3040), (3072))); + }; +} +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! for_each_rsa_multiplication { + ($($pattern:tt => $code:tt;)*) => { + macro_rules! _for_each_inner_rsa_multiplication { $(($pattern) => $code;)* + ($other : tt) => {} } _for_each_inner_rsa_multiplication!((32)); + _for_each_inner_rsa_multiplication!((64)); + _for_each_inner_rsa_multiplication!((96)); + _for_each_inner_rsa_multiplication!((128)); + _for_each_inner_rsa_multiplication!((160)); + _for_each_inner_rsa_multiplication!((192)); + _for_each_inner_rsa_multiplication!((224)); + _for_each_inner_rsa_multiplication!((256)); + _for_each_inner_rsa_multiplication!((288)); + _for_each_inner_rsa_multiplication!((320)); + _for_each_inner_rsa_multiplication!((352)); + _for_each_inner_rsa_multiplication!((384)); + _for_each_inner_rsa_multiplication!((416)); + _for_each_inner_rsa_multiplication!((448)); + _for_each_inner_rsa_multiplication!((480)); + _for_each_inner_rsa_multiplication!((512)); + _for_each_inner_rsa_multiplication!((544)); + _for_each_inner_rsa_multiplication!((576)); + _for_each_inner_rsa_multiplication!((608)); + _for_each_inner_rsa_multiplication!((640)); + _for_each_inner_rsa_multiplication!((672)); + _for_each_inner_rsa_multiplication!((704)); + _for_each_inner_rsa_multiplication!((736)); + _for_each_inner_rsa_multiplication!((768)); + _for_each_inner_rsa_multiplication!((800)); + _for_each_inner_rsa_multiplication!((832)); + _for_each_inner_rsa_multiplication!((864)); + _for_each_inner_rsa_multiplication!((896)); + _for_each_inner_rsa_multiplication!((928)); + _for_each_inner_rsa_multiplication!((960)); + _for_each_inner_rsa_multiplication!((992)); + _for_each_inner_rsa_multiplication!((1024)); + _for_each_inner_rsa_multiplication!((1056)); + _for_each_inner_rsa_multiplication!((1088)); + _for_each_inner_rsa_multiplication!((1120)); + _for_each_inner_rsa_multiplication!((1152)); + _for_each_inner_rsa_multiplication!((1184)); + _for_each_inner_rsa_multiplication!((1216)); + _for_each_inner_rsa_multiplication!((1248)); + _for_each_inner_rsa_multiplication!((1280)); + _for_each_inner_rsa_multiplication!((1312)); + _for_each_inner_rsa_multiplication!((1344)); + _for_each_inner_rsa_multiplication!((1376)); + _for_each_inner_rsa_multiplication!((1408)); + _for_each_inner_rsa_multiplication!((1440)); + _for_each_inner_rsa_multiplication!((1472)); + _for_each_inner_rsa_multiplication!((1504)); + _for_each_inner_rsa_multiplication!((1536)); + _for_each_inner_rsa_multiplication!((all(32), (64), (96), (128), (160), (192), + (224), (256), (288), (320), (352), (384), (416), (448), (480), (512), (544), + (576), (608), (640), (672), (704), (736), (768), (800), (832), (864), (896), + (928), (960), (992), (1024), (1056), (1088), (1120), (1152), (1184), (1216), + (1248), (1280), (1312), (1344), (1376), (1408), (1440), (1472), (1504), (1536))); + }; +} +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! for_each_sha_algorithm { + ($($pattern:tt => $code:tt;)*) => { + macro_rules! _for_each_inner_sha_algorithm { $(($pattern) => $code;)* ($other : + tt) => {} } _for_each_inner_sha_algorithm!((Sha1, "SHA-1"(sizes : 64, 20, 8) + (insecure_against : "collision", "length extension"), 0)); + _for_each_inner_sha_algorithm!((Sha224, "SHA-224"(sizes : 64, 28, 8) + (insecure_against : "length extension"), 1)); + _for_each_inner_sha_algorithm!((Sha256, "SHA-256"(sizes : 64, 32, 8) + (insecure_against : "length extension"), 2)); + _for_each_inner_sha_algorithm!((algos(Sha1, "SHA-1"(sizes : 64, 20, 8) + (insecure_against : "collision", "length extension"), 0), (Sha224, + "SHA-224"(sizes : 64, 28, 8) (insecure_against : "length extension"), 1), + (Sha256, "SHA-256"(sizes : 64, 32, 8) (insecure_against : "length extension"), + 2))); + }; +} +#[macro_export] +/// ESP-HAL must provide implementation for the following functions: +/// ```rust, no_run +/// // XTAL_CLK +/// +/// // CPLL_CLK +/// +/// fn enable_cpll_clk_impl(_clocks: &mut ClockTree, _en: bool) { +/// todo!() +/// } +/// +/// // SPLL_CLK +/// +/// fn enable_spll_clk_impl(_clocks: &mut ClockTree, _en: bool) { +/// todo!() +/// } +/// +/// // MPLL_CLK +/// +/// fn enable_mpll_clk_impl(_clocks: &mut ClockTree, _en: bool) { +/// todo!() +/// } +/// +/// // RC_FAST_CLK +/// +/// fn enable_rc_fast_clk_impl(_clocks: &mut ClockTree, _en: bool) { +/// todo!() +/// } +/// +/// // XTAL32K_CLK +/// +/// fn enable_xtal32k_clk_impl(_clocks: &mut ClockTree, _en: bool) { +/// todo!() +/// } +/// +/// // OSC_SLOW_CLK +/// +/// fn enable_osc_slow_clk_impl(_clocks: &mut ClockTree, _en: bool) { +/// todo!() +/// } +/// +/// // RC_SLOW_CLK +/// +/// fn enable_rc_slow_clk_impl(_clocks: &mut ClockTree, _en: bool) { +/// todo!() +/// } +/// +/// // RC32K_CLK +/// +/// fn enable_rc32k_clk_impl(_clocks: &mut ClockTree, _en: bool) { +/// todo!() +/// } +/// +/// // PLL_F20M +/// +/// fn enable_pll_f20m_impl(_clocks: &mut ClockTree, _en: bool) { +/// todo!() +/// } +/// +/// // PLL_F80M +/// +/// fn enable_pll_f80m_impl(_clocks: &mut ClockTree, _en: bool) { +/// todo!() +/// } +/// +/// // PLL_F120M +/// +/// fn enable_pll_f120m_impl(_clocks: &mut ClockTree, _en: bool) { +/// todo!() +/// } +/// +/// // PLL_F160M +/// +/// fn enable_pll_f160m_impl(_clocks: &mut ClockTree, _en: bool) { +/// todo!() +/// } +/// +/// // PLL_F240M +/// +/// fn enable_pll_f240m_impl(_clocks: &mut ClockTree, _en: bool) { +/// todo!() +/// } +/// +/// // PLL_F25M +/// +/// fn enable_pll_f25m_impl(_clocks: &mut ClockTree, _en: bool) { +/// todo!() +/// } +/// +/// // PLL_F50M +/// +/// fn enable_pll_f50m_impl(_clocks: &mut ClockTree, _en: bool) { +/// todo!() +/// } +/// +/// // XTAL_D2_CLK +/// +/// fn enable_xtal_d2_clk_impl(_clocks: &mut ClockTree, _en: bool) { +/// todo!() +/// } +/// +/// // CPU_ROOT_CLK +/// +/// fn enable_cpu_root_clk_impl(_clocks: &mut ClockTree, _en: bool) { +/// todo!() +/// } +/// +/// fn configure_cpu_root_clk_impl( +/// _clocks: &mut ClockTree, +/// _old_config: Option, +/// _new_config: CpuRootClkConfig, +/// ) { +/// todo!() +/// } +/// +/// // CPU_CLK +/// +/// fn enable_cpu_clk_impl(_clocks: &mut ClockTree, _en: bool) { +/// todo!() +/// } +/// +/// fn configure_cpu_clk_impl( +/// _clocks: &mut ClockTree, +/// _old_config: Option, +/// _new_config: CpuClkConfig, +/// ) { +/// todo!() +/// } +/// +/// // APB_CLK +/// +/// fn enable_apb_clk_impl(_clocks: &mut ClockTree, _en: bool) { +/// todo!() +/// } +/// +/// fn configure_apb_clk_impl( +/// _clocks: &mut ClockTree, +/// _old_config: Option, +/// _new_config: ApbClkConfig, +/// ) { +/// todo!() +/// } +/// +/// // LP_FAST_CLK +/// +/// fn enable_lp_fast_clk_impl(_clocks: &mut ClockTree, _en: bool) { +/// todo!() +/// } +/// +/// fn configure_lp_fast_clk_impl( +/// _clocks: &mut ClockTree, +/// _old_config: Option, +/// _new_config: LpFastClkConfig, +/// ) { +/// todo!() +/// } +/// +/// // LP_SLOW_CLK +/// +/// fn enable_lp_slow_clk_impl(_clocks: &mut ClockTree, _en: bool) { +/// todo!() +/// } +/// +/// fn configure_lp_slow_clk_impl( +/// _clocks: &mut ClockTree, +/// _old_config: Option, +/// _new_config: LpSlowClkConfig, +/// ) { +/// todo!() +/// } +/// +/// impl TimgInstance { +/// // TIMG_FUNCTION_CLOCK +/// +/// fn enable_function_clock_impl(self, _clocks: &mut ClockTree, _en: bool) { +/// todo!() +/// } +/// +/// fn configure_function_clock_impl( +/// self, +/// _clocks: &mut ClockTree, +/// _old_config: Option, +/// _new_config: TimgFunctionClockConfig, +/// ) { +/// todo!() +/// } +/// +/// // TIMG_WDT_CLOCK +/// +/// fn enable_wdt_clock_impl(self, _clocks: &mut ClockTree, _en: bool) { +/// todo!() +/// } +/// +/// fn configure_wdt_clock_impl( +/// self, +/// _clocks: &mut ClockTree, +/// _old_config: Option, +/// _new_config: TimgWdtClockConfig, +/// ) { +/// todo!() +/// } +/// } +/// impl UartInstance { +/// // UART_FUNCTION_CLOCK +/// +/// fn enable_function_clock_impl(self, _clocks: &mut ClockTree, _en: bool) { +/// todo!() +/// } +/// +/// fn configure_function_clock_impl( +/// self, +/// _clocks: &mut ClockTree, +/// _old_config: Option, +/// _new_config: UartFunctionClockConfig, +/// ) { +/// todo!() +/// } +/// +/// // UART_BAUD_RATE_GENERATOR +/// +/// fn enable_baud_rate_generator_impl(self, _clocks: &mut ClockTree, _en: bool) { +/// todo!() +/// } +/// +/// fn configure_baud_rate_generator_impl( +/// self, +/// _clocks: &mut ClockTree, +/// _old_config: Option, +/// _new_config: UartBaudRateGeneratorConfig, +/// ) { +/// todo!() +/// } +/// } +/// ``` +macro_rules! define_clock_tree_types { + () => { + #[derive(Clone, Copy, PartialEq, Eq, Debug)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] + pub enum TimgInstance { + Timg0 = 0, + Timg1 = 1, + } + #[derive(Clone, Copy, PartialEq, Eq, Debug)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] + pub enum UartInstance { + Uart0 = 0, + Uart1 = 1, + Uart2 = 2, + Uart3 = 3, + Uart4 = 4, + } + /// The list of clock signals that the `CPU_ROOT_CLK` multiplexer can output. + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] + pub enum CpuRootClkConfig { + /// Selects `XTAL_CLK`. + Xtal, + /// Selects `CPLL_CLK`. + Cpll, + /// Selects `RC_FAST_CLK`. + RcFast, + } + /// Configures the `CPU_CLK` clock node. + /// + /// The output is calculated as `OUTPUT = CPU_ROOT_CLK / (divisor + 1)`. + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] + pub struct CpuClkConfig { + divisor: u32, + } + impl CpuClkConfig { + /// Creates a new configuration for the CPU_CLK clock node. + /// + /// ## Panics + /// + /// Panics if the divisor value is outside the + /// valid range (0 ..= 255). + pub const fn new(divisor: u32) -> Self { + ::core::assert!( + divisor <= 255, + "`CPU_CLK` divisor must be between 0 and 255 (inclusive)." + ); + Self { divisor } + } + fn divisor(self) -> u32 { + self.divisor as u32 + } + } + /// Configures the `APB_CLK` clock node. + /// + /// The output is calculated as `OUTPUT = CPU_CLK / (divisor + 1)`. + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] + pub struct ApbClkConfig { + divisor: u32, + } + impl ApbClkConfig { + /// Creates a new configuration for the APB_CLK clock node. + /// + /// ## Panics + /// + /// Panics if the divisor value is outside the + /// valid range (0 ..= 255). + pub const fn new(divisor: u32) -> Self { + ::core::assert!( + divisor <= 255, + "`APB_CLK` divisor must be between 0 and 255 (inclusive)." + ); + Self { divisor } + } + fn divisor(self) -> u32 { + self.divisor as u32 + } + } + /// The list of clock signals that the `LP_FAST_CLK` multiplexer can output. + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] + pub enum LpFastClkConfig { + /// Selects `RC_FAST_CLK`. + RcFast, + /// Selects `XTAL_D2_CLK`. + XtalD2, + } + /// The list of clock signals that the `LP_SLOW_CLK` multiplexer can output. + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] + pub enum LpSlowClkConfig { + /// Selects `RC_SLOW_CLK`. + RcSlow, + /// Selects `XTAL32K_CLK`. + Xtal32k, + /// Selects `RC32K_CLK`. + Rc32k, + /// Selects `OSC_SLOW_CLK`. + OscSlow, + } + /// The list of clock signals that the `TIMG0_FUNCTION_CLOCK` multiplexer can output. + #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] + pub enum TimgFunctionClockConfig { + #[default] + /// Selects `XTAL_CLK`. + XtalClk, + /// Selects `RC_FAST_CLK`. + RcFastClk, + /// Selects `PLL_F80M`. + PllF80m, + } + /// The list of clock signals that the `TIMG0_WDT_CLOCK` multiplexer can output. + #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] + pub enum TimgWdtClockConfig { + #[default] + /// Selects `XTAL_CLK`. + XtalClk, + /// Selects `PLL_F80M`. + PllF80m, + /// Selects `RC_FAST_CLK`. + RcFastClk, + } + #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] + pub enum UartFunctionClockSclk { + #[default] + /// Selects `XTAL_CLK`. + Xtal, + /// Selects `PLL_F80M`. + PllF80m, + /// Selects `RC_FAST_CLK`. + RcFast, + } + /// Configures the `UART0_FUNCTION_CLOCK` clock node. + /// + /// The output is calculated as `OUTPUT = sclk / (div_num + 1)`. + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] + pub struct UartFunctionClockConfig { + sclk: UartFunctionClockSclk, + div_num: u32, + } + impl UartFunctionClockConfig { + /// Creates a new configuration for the FUNCTION_CLOCK clock node. + /// + /// ## Panics + /// + /// Panics if the div_num value is outside the + /// valid range (0 ..= 255). + pub const fn new(sclk: UartFunctionClockSclk, div_num: u32) -> Self { + ::core::assert!( + div_num <= 255, + "`UART0_FUNCTION_CLOCK` div_num must be between 0 and 255 (inclusive)." + ); + Self { sclk, div_num } + } + fn sclk(self) -> UartFunctionClockSclk { + self.sclk + } + fn div_num(self) -> u32 { + self.div_num as u32 + } + } + /// Configures the `UART0_BAUD_RATE_GENERATOR` clock node. + /// + /// The output is calculated as `OUTPUT = (FUNCTION_CLOCK * 16) / (integral * 16 + + /// fractional)`. + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] + pub struct UartBaudRateGeneratorConfig { + fractional: u32, + integral: u32, + } + impl UartBaudRateGeneratorConfig { + /// Creates a new configuration for the BAUD_RATE_GENERATOR clock node. + /// + /// ## Panics + /// + /// Panics if the fractional value is outside the + /// valid range (0 ..= 15). + /// + /// Panics if the integral value is outside the + /// valid range (0 ..= 4095). + pub const fn new(fractional: u32, integral: u32) -> Self { + ::core::assert!( + fractional <= 15, + "`UART0_BAUD_RATE_GENERATOR` fractional must be between 0 and 15 (inclusive)." + ); + ::core::assert!( + integral <= 4095, + "`UART0_BAUD_RATE_GENERATOR` integral must be between 0 and 4095 (inclusive)." + ); + Self { + fractional, + integral, + } + } + fn fractional(self) -> u32 { + self.fractional as u32 + } + fn integral(self) -> u32 { + self.integral as u32 + } + } + /// Represents the device's clock tree. + pub struct ClockTree { + cpu_root_clk: Option, + cpu_clk: Option, + apb_clk: Option, + lp_fast_clk: Option, + lp_slow_clk: Option, + timg_function_clock: [Option; 2], + timg_wdt_clock: [Option; 2], + uart_function_clock: [Option; 5], + uart_baud_rate_generator: [Option; 5], + spll_clk_refcount: u32, + mpll_clk_refcount: u32, + rc_fast_clk_refcount: u32, + pll_f20m_refcount: u32, + pll_f80m_refcount: u32, + pll_f120m_refcount: u32, + pll_f160m_refcount: u32, + pll_f240m_refcount: u32, + pll_f25m_refcount: u32, + pll_f50m_refcount: u32, + apb_clk_refcount: u32, + lp_fast_clk_refcount: u32, + lp_slow_clk_refcount: u32, + timg_function_clock_refcount: [u32; 2], + timg_wdt_clock_refcount: [u32; 2], + uart_function_clock_refcount: [u32; 5], + uart_baud_rate_generator_refcount: [u32; 5], + } + impl ClockTree { + /// Locks the clock tree for exclusive access. + pub fn with(f: impl FnOnce(&mut ClockTree) -> R) -> R { + CLOCK_TREE.with(f) + } + /// Returns the current configuration of the CPU_ROOT_CLK clock tree node + pub fn cpu_root_clk(&self) -> Option { + self.cpu_root_clk + } + /// Returns the current configuration of the CPU_CLK clock tree node + pub fn cpu_clk(&self) -> Option { + self.cpu_clk + } + /// Returns the current configuration of the APB_CLK clock tree node + pub fn apb_clk(&self) -> Option { + self.apb_clk + } + /// Returns the current configuration of the LP_FAST_CLK clock tree node + pub fn lp_fast_clk(&self) -> Option { + self.lp_fast_clk + } + /// Returns the current configuration of the LP_SLOW_CLK clock tree node + pub fn lp_slow_clk(&self) -> Option { + self.lp_slow_clk + } + /// Returns the current configuration of the TIMG0_FUNCTION_CLOCK clock tree node + pub fn timg0_function_clock(&self) -> Option { + self.timg_function_clock[TimgInstance::Timg0 as usize] + } + /// Returns the current configuration of the TIMG0_WDT_CLOCK clock tree node + pub fn timg0_wdt_clock(&self) -> Option { + self.timg_wdt_clock[TimgInstance::Timg0 as usize] + } + /// Returns the current configuration of the TIMG1_FUNCTION_CLOCK clock tree node + pub fn timg1_function_clock(&self) -> Option { + self.timg_function_clock[TimgInstance::Timg1 as usize] + } + /// Returns the current configuration of the TIMG1_WDT_CLOCK clock tree node + pub fn timg1_wdt_clock(&self) -> Option { + self.timg_wdt_clock[TimgInstance::Timg1 as usize] + } + /// Returns the current configuration of the UART0_FUNCTION_CLOCK clock tree node + pub fn uart0_function_clock(&self) -> Option { + self.uart_function_clock[UartInstance::Uart0 as usize] + } + /// Returns the current configuration of the UART0_BAUD_RATE_GENERATOR clock tree node + pub fn uart0_baud_rate_generator(&self) -> Option { + self.uart_baud_rate_generator[UartInstance::Uart0 as usize] + } + /// Returns the current configuration of the UART1_FUNCTION_CLOCK clock tree node + pub fn uart1_function_clock(&self) -> Option { + self.uart_function_clock[UartInstance::Uart1 as usize] + } + /// Returns the current configuration of the UART1_BAUD_RATE_GENERATOR clock tree node + pub fn uart1_baud_rate_generator(&self) -> Option { + self.uart_baud_rate_generator[UartInstance::Uart1 as usize] + } + /// Returns the current configuration of the UART2_FUNCTION_CLOCK clock tree node + pub fn uart2_function_clock(&self) -> Option { + self.uart_function_clock[UartInstance::Uart2 as usize] + } + /// Returns the current configuration of the UART2_BAUD_RATE_GENERATOR clock tree node + pub fn uart2_baud_rate_generator(&self) -> Option { + self.uart_baud_rate_generator[UartInstance::Uart2 as usize] + } + /// Returns the current configuration of the UART3_FUNCTION_CLOCK clock tree node + pub fn uart3_function_clock(&self) -> Option { + self.uart_function_clock[UartInstance::Uart3 as usize] + } + /// Returns the current configuration of the UART3_BAUD_RATE_GENERATOR clock tree node + pub fn uart3_baud_rate_generator(&self) -> Option { + self.uart_baud_rate_generator[UartInstance::Uart3 as usize] + } + /// Returns the current configuration of the UART4_FUNCTION_CLOCK clock tree node + pub fn uart4_function_clock(&self) -> Option { + self.uart_function_clock[UartInstance::Uart4 as usize] + } + /// Returns the current configuration of the UART4_BAUD_RATE_GENERATOR clock tree node + pub fn uart4_baud_rate_generator(&self) -> Option { + self.uart_baud_rate_generator[UartInstance::Uart4 as usize] + } + } + static CLOCK_TREE: ::esp_sync::NonReentrantMutex = + ::esp_sync::NonReentrantMutex::new(ClockTree { + cpu_root_clk: None, + cpu_clk: None, + apb_clk: None, + lp_fast_clk: None, + lp_slow_clk: None, + timg_function_clock: [None; 2], + timg_wdt_clock: [None; 2], + uart_function_clock: [None; 5], + uart_baud_rate_generator: [None; 5], + spll_clk_refcount: 0, + mpll_clk_refcount: 0, + rc_fast_clk_refcount: 0, + pll_f20m_refcount: 0, + pll_f80m_refcount: 0, + pll_f120m_refcount: 0, + pll_f160m_refcount: 0, + pll_f240m_refcount: 0, + pll_f25m_refcount: 0, + pll_f50m_refcount: 0, + apb_clk_refcount: 0, + lp_fast_clk_refcount: 0, + lp_slow_clk_refcount: 0, + timg_function_clock_refcount: [0; 2], + timg_wdt_clock_refcount: [0; 2], + uart_function_clock_refcount: [0; 5], + uart_baud_rate_generator_refcount: [0; 5], + }); + static CPU_ROOT_CLK_FREQ_CACHE: ::core::sync::atomic::AtomicU32 = + ::core::sync::atomic::AtomicU32::new(0); + static CPU_CLK_FREQ_CACHE: ::core::sync::atomic::AtomicU32 = + ::core::sync::atomic::AtomicU32::new(0); + static APB_CLK_FREQ_CACHE: ::core::sync::atomic::AtomicU32 = + ::core::sync::atomic::AtomicU32::new(0); + static LP_FAST_CLK_FREQ_CACHE: ::core::sync::atomic::AtomicU32 = + ::core::sync::atomic::AtomicU32::new(0); + static LP_SLOW_CLK_FREQ_CACHE: ::core::sync::atomic::AtomicU32 = + ::core::sync::atomic::AtomicU32::new(0); + static TIMG_FUNCTION_CLOCK_FREQ_CACHE: [::core::sync::atomic::AtomicU32; 2] = + [const { ::core::sync::atomic::AtomicU32::new(0) }; 2]; + static TIMG_WDT_CLOCK_FREQ_CACHE: [::core::sync::atomic::AtomicU32; 2] = + [const { ::core::sync::atomic::AtomicU32::new(0) }; 2]; + static UART_FUNCTION_CLOCK_FREQ_CACHE: [::core::sync::atomic::AtomicU32; 5] = + [const { ::core::sync::atomic::AtomicU32::new(0) }; 5]; + static UART_BAUD_RATE_GENERATOR_FREQ_CACHE: [::core::sync::atomic::AtomicU32; 5] = + [const { ::core::sync::atomic::AtomicU32::new(0) }; 5]; + fn request_xtal_clk(_clocks: &mut ClockTree) {} + fn release_xtal_clk(_clocks: &mut ClockTree) {} + pub fn xtal_clk_frequency() -> u32 { + 40000000 + } + pub fn request_cpll_clk(clocks: &mut ClockTree) { + trace!("Requesting CPLL_CLK"); + trace!("Enabling CPLL_CLK"); + request_xtal_clk(clocks); + enable_cpll_clk_impl(clocks, true); + } + pub fn release_cpll_clk(clocks: &mut ClockTree) { + trace!("Releasing CPLL_CLK"); + trace!("Disabling CPLL_CLK"); + enable_cpll_clk_impl(clocks, false); + release_xtal_clk(clocks); + } + pub fn cpll_clk_frequency() -> u32 { + 400000000 + } + pub fn request_spll_clk(clocks: &mut ClockTree) { + trace!("Requesting SPLL_CLK"); + if increment_reference_count(&mut clocks.spll_clk_refcount) { + trace!("Enabling SPLL_CLK"); + request_xtal_clk(clocks); + enable_spll_clk_impl(clocks, true); + } + } + pub fn release_spll_clk(clocks: &mut ClockTree) { + trace!("Releasing SPLL_CLK"); + if decrement_reference_count(&mut clocks.spll_clk_refcount) { + trace!("Disabling SPLL_CLK"); + enable_spll_clk_impl(clocks, false); + release_xtal_clk(clocks); + } + } + pub fn spll_clk_frequency() -> u32 { + 480000000 + } + pub fn request_mpll_clk(clocks: &mut ClockTree) { + trace!("Requesting MPLL_CLK"); + if increment_reference_count(&mut clocks.mpll_clk_refcount) { + trace!("Enabling MPLL_CLK"); + request_xtal_clk(clocks); + enable_mpll_clk_impl(clocks, true); + } + } + pub fn release_mpll_clk(clocks: &mut ClockTree) { + trace!("Releasing MPLL_CLK"); + if decrement_reference_count(&mut clocks.mpll_clk_refcount) { + trace!("Disabling MPLL_CLK"); + enable_mpll_clk_impl(clocks, false); + release_xtal_clk(clocks); + } + } + pub fn mpll_clk_frequency() -> u32 { + 400000000 + } + pub fn request_rc_fast_clk(clocks: &mut ClockTree) { + trace!("Requesting RC_FAST_CLK"); + if increment_reference_count(&mut clocks.rc_fast_clk_refcount) { + trace!("Enabling RC_FAST_CLK"); + enable_rc_fast_clk_impl(clocks, true); + } + } + pub fn release_rc_fast_clk(clocks: &mut ClockTree) { + trace!("Releasing RC_FAST_CLK"); + if decrement_reference_count(&mut clocks.rc_fast_clk_refcount) { + trace!("Disabling RC_FAST_CLK"); + enable_rc_fast_clk_impl(clocks, false); + } + } + pub fn rc_fast_clk_frequency() -> u32 { + 20000000 + } + pub fn request_xtal32k_clk(clocks: &mut ClockTree) { + trace!("Requesting XTAL32K_CLK"); + trace!("Enabling XTAL32K_CLK"); + enable_xtal32k_clk_impl(clocks, true); + } + pub fn release_xtal32k_clk(clocks: &mut ClockTree) { + trace!("Releasing XTAL32K_CLK"); + trace!("Disabling XTAL32K_CLK"); + enable_xtal32k_clk_impl(clocks, false); + } + pub fn xtal32k_clk_frequency() -> u32 { + 32768 + } + pub fn request_osc_slow_clk(clocks: &mut ClockTree) { + trace!("Requesting OSC_SLOW_CLK"); + trace!("Enabling OSC_SLOW_CLK"); + enable_osc_slow_clk_impl(clocks, true); + } + pub fn release_osc_slow_clk(clocks: &mut ClockTree) { + trace!("Releasing OSC_SLOW_CLK"); + trace!("Disabling OSC_SLOW_CLK"); + enable_osc_slow_clk_impl(clocks, false); + } + pub fn osc_slow_clk_frequency() -> u32 { + 32768 + } + pub fn request_rc_slow_clk(clocks: &mut ClockTree) { + trace!("Requesting RC_SLOW_CLK"); + trace!("Enabling RC_SLOW_CLK"); + enable_rc_slow_clk_impl(clocks, true); + } + pub fn release_rc_slow_clk(clocks: &mut ClockTree) { + trace!("Releasing RC_SLOW_CLK"); + trace!("Disabling RC_SLOW_CLK"); + enable_rc_slow_clk_impl(clocks, false); + } + pub fn rc_slow_clk_frequency() -> u32 { + 136000 + } + pub fn request_rc32k_clk(clocks: &mut ClockTree) { + trace!("Requesting RC32K_CLK"); + trace!("Enabling RC32K_CLK"); + enable_rc32k_clk_impl(clocks, true); + } + pub fn release_rc32k_clk(clocks: &mut ClockTree) { + trace!("Releasing RC32K_CLK"); + trace!("Disabling RC32K_CLK"); + enable_rc32k_clk_impl(clocks, false); + } + pub fn rc32k_clk_frequency() -> u32 { + 32768 + } + pub fn request_pll_f20m(clocks: &mut ClockTree) { + trace!("Requesting PLL_F20M"); + if increment_reference_count(&mut clocks.pll_f20m_refcount) { + trace!("Enabling PLL_F20M"); + request_spll_clk(clocks); + enable_pll_f20m_impl(clocks, true); + } + } + pub fn release_pll_f20m(clocks: &mut ClockTree) { + trace!("Releasing PLL_F20M"); + if decrement_reference_count(&mut clocks.pll_f20m_refcount) { + trace!("Disabling PLL_F20M"); + enable_pll_f20m_impl(clocks, false); + release_spll_clk(clocks); + } + } + pub fn pll_f20m_frequency() -> u32 { + (spll_clk_frequency() / 24) + } + pub fn request_pll_f80m(clocks: &mut ClockTree) { + trace!("Requesting PLL_F80M"); + if increment_reference_count(&mut clocks.pll_f80m_refcount) { + trace!("Enabling PLL_F80M"); + request_spll_clk(clocks); + enable_pll_f80m_impl(clocks, true); + } + } + pub fn release_pll_f80m(clocks: &mut ClockTree) { + trace!("Releasing PLL_F80M"); + if decrement_reference_count(&mut clocks.pll_f80m_refcount) { + trace!("Disabling PLL_F80M"); + enable_pll_f80m_impl(clocks, false); + release_spll_clk(clocks); + } + } + pub fn pll_f80m_frequency() -> u32 { + (spll_clk_frequency() / 6) + } + pub fn request_pll_f120m(clocks: &mut ClockTree) { + trace!("Requesting PLL_F120M"); + if increment_reference_count(&mut clocks.pll_f120m_refcount) { + trace!("Enabling PLL_F120M"); + request_spll_clk(clocks); + enable_pll_f120m_impl(clocks, true); + } + } + pub fn release_pll_f120m(clocks: &mut ClockTree) { + trace!("Releasing PLL_F120M"); + if decrement_reference_count(&mut clocks.pll_f120m_refcount) { + trace!("Disabling PLL_F120M"); + enable_pll_f120m_impl(clocks, false); + release_spll_clk(clocks); + } + } + pub fn pll_f120m_frequency() -> u32 { + (spll_clk_frequency() / 4) + } + pub fn request_pll_f160m(clocks: &mut ClockTree) { + trace!("Requesting PLL_F160M"); + if increment_reference_count(&mut clocks.pll_f160m_refcount) { + trace!("Enabling PLL_F160M"); + request_spll_clk(clocks); + enable_pll_f160m_impl(clocks, true); + } + } + pub fn release_pll_f160m(clocks: &mut ClockTree) { + trace!("Releasing PLL_F160M"); + if decrement_reference_count(&mut clocks.pll_f160m_refcount) { + trace!("Disabling PLL_F160M"); + enable_pll_f160m_impl(clocks, false); + release_spll_clk(clocks); + } + } + pub fn pll_f160m_frequency() -> u32 { + (spll_clk_frequency() / 3) + } + pub fn request_pll_f240m(clocks: &mut ClockTree) { + trace!("Requesting PLL_F240M"); + if increment_reference_count(&mut clocks.pll_f240m_refcount) { + trace!("Enabling PLL_F240M"); + request_spll_clk(clocks); + enable_pll_f240m_impl(clocks, true); + } + } + pub fn release_pll_f240m(clocks: &mut ClockTree) { + trace!("Releasing PLL_F240M"); + if decrement_reference_count(&mut clocks.pll_f240m_refcount) { + trace!("Disabling PLL_F240M"); + enable_pll_f240m_impl(clocks, false); + release_spll_clk(clocks); + } + } + pub fn pll_f240m_frequency() -> u32 { + (spll_clk_frequency() / 2) + } + pub fn request_pll_f25m(clocks: &mut ClockTree) { + trace!("Requesting PLL_F25M"); + if increment_reference_count(&mut clocks.pll_f25m_refcount) { + trace!("Enabling PLL_F25M"); + request_mpll_clk(clocks); + enable_pll_f25m_impl(clocks, true); + } + } + pub fn release_pll_f25m(clocks: &mut ClockTree) { + trace!("Releasing PLL_F25M"); + if decrement_reference_count(&mut clocks.pll_f25m_refcount) { + trace!("Disabling PLL_F25M"); + enable_pll_f25m_impl(clocks, false); + release_mpll_clk(clocks); + } + } + pub fn pll_f25m_frequency() -> u32 { + (mpll_clk_frequency() / 16) + } + pub fn request_pll_f50m(clocks: &mut ClockTree) { + trace!("Requesting PLL_F50M"); + if increment_reference_count(&mut clocks.pll_f50m_refcount) { + trace!("Enabling PLL_F50M"); + request_mpll_clk(clocks); + enable_pll_f50m_impl(clocks, true); + } + } + pub fn release_pll_f50m(clocks: &mut ClockTree) { + trace!("Releasing PLL_F50M"); + if decrement_reference_count(&mut clocks.pll_f50m_refcount) { + trace!("Disabling PLL_F50M"); + enable_pll_f50m_impl(clocks, false); + release_mpll_clk(clocks); + } + } + pub fn pll_f50m_frequency() -> u32 { + (mpll_clk_frequency() / 8) + } + pub fn request_xtal_d2_clk(clocks: &mut ClockTree) { + trace!("Requesting XTAL_D2_CLK"); + trace!("Enabling XTAL_D2_CLK"); + request_xtal_clk(clocks); + enable_xtal_d2_clk_impl(clocks, true); + } + pub fn release_xtal_d2_clk(clocks: &mut ClockTree) { + trace!("Releasing XTAL_D2_CLK"); + trace!("Disabling XTAL_D2_CLK"); + enable_xtal_d2_clk_impl(clocks, false); + release_xtal_clk(clocks); + } + pub fn xtal_d2_clk_frequency() -> u32 { + (xtal_clk_frequency() / 2) + } + pub fn configure_cpu_root_clk(clocks: &mut ClockTree, new_selector: CpuRootClkConfig) { + let old_selector = clocks.cpu_root_clk.replace(new_selector); + refresh_cpu_root_clk_downstream(clocks); + match new_selector { + CpuRootClkConfig::Xtal => request_xtal_clk(clocks), + CpuRootClkConfig::Cpll => request_cpll_clk(clocks), + CpuRootClkConfig::RcFast => request_rc_fast_clk(clocks), + } + configure_cpu_root_clk_impl(clocks, old_selector, new_selector); + if let Some(old_selector) = old_selector { + match old_selector { + CpuRootClkConfig::Xtal => release_xtal_clk(clocks), + CpuRootClkConfig::Cpll => release_cpll_clk(clocks), + CpuRootClkConfig::RcFast => release_rc_fast_clk(clocks), + } + } + } + pub fn cpu_root_clk_config(clocks: &mut ClockTree) -> Option { + clocks.cpu_root_clk + } + pub fn request_cpu_root_clk(clocks: &mut ClockTree) { + trace!("Requesting CPU_ROOT_CLK"); + trace!("Enabling CPU_ROOT_CLK"); + match unwrap!(clocks.cpu_root_clk) { + CpuRootClkConfig::Xtal => request_xtal_clk(clocks), + CpuRootClkConfig::Cpll => request_cpll_clk(clocks), + CpuRootClkConfig::RcFast => request_rc_fast_clk(clocks), + } + enable_cpu_root_clk_impl(clocks, true); + } + pub fn release_cpu_root_clk(clocks: &mut ClockTree) { + trace!("Releasing CPU_ROOT_CLK"); + trace!("Disabling CPU_ROOT_CLK"); + enable_cpu_root_clk_impl(clocks, false); + match unwrap!(clocks.cpu_root_clk) { + CpuRootClkConfig::Xtal => release_xtal_clk(clocks), + CpuRootClkConfig::Cpll => release_cpll_clk(clocks), + CpuRootClkConfig::RcFast => release_rc_fast_clk(clocks), + } + } + #[allow(unused_variables)] + pub fn cpu_root_clk_config_frequency( + clocks: &mut ClockTree, + config: CpuRootClkConfig, + ) -> u32 { + match config { + CpuRootClkConfig::Xtal => xtal_clk_frequency(), + CpuRootClkConfig::Cpll => cpll_clk_frequency(), + CpuRootClkConfig::RcFast => rc_fast_clk_frequency(), + } + } + pub fn cpu_root_clk_frequency() -> u32 { + CPU_ROOT_CLK_FREQ_CACHE.load(::core::sync::atomic::Ordering::Acquire) + } + pub fn configure_cpu_clk(clocks: &mut ClockTree, config: CpuClkConfig) { + let old_config = clocks.cpu_clk.replace(config); + refresh_cpu_clk_downstream(clocks); + configure_cpu_clk_impl(clocks, old_config, config); + } + pub fn cpu_clk_config(clocks: &mut ClockTree) -> Option { + clocks.cpu_clk + } + pub fn request_cpu_clk(clocks: &mut ClockTree) { + trace!("Requesting CPU_CLK"); + trace!("Enabling CPU_CLK"); + request_cpu_root_clk(clocks); + enable_cpu_clk_impl(clocks, true); + } + pub fn release_cpu_clk(clocks: &mut ClockTree) { + trace!("Releasing CPU_CLK"); + trace!("Disabling CPU_CLK"); + enable_cpu_clk_impl(clocks, false); + release_cpu_root_clk(clocks); + } + #[allow(unused_variables)] + pub fn cpu_clk_config_frequency(clocks: &mut ClockTree, config: CpuClkConfig) -> u32 { + (cpu_root_clk_frequency() / (config.divisor() + 1)) + } + pub fn cpu_clk_frequency() -> u32 { + CPU_CLK_FREQ_CACHE.load(::core::sync::atomic::Ordering::Acquire) + } + pub fn configure_apb_clk(clocks: &mut ClockTree, config: ApbClkConfig) { + let old_config = clocks.apb_clk.replace(config); + refresh_apb_clk_downstream(clocks); + configure_apb_clk_impl(clocks, old_config, config); + } + pub fn apb_clk_config(clocks: &mut ClockTree) -> Option { + clocks.apb_clk + } + pub fn request_apb_clk(clocks: &mut ClockTree) { + trace!("Requesting APB_CLK"); + if increment_reference_count(&mut clocks.apb_clk_refcount) { + trace!("Enabling APB_CLK"); + request_cpu_clk(clocks); + enable_apb_clk_impl(clocks, true); + } + } + pub fn release_apb_clk(clocks: &mut ClockTree) { + trace!("Releasing APB_CLK"); + if decrement_reference_count(&mut clocks.apb_clk_refcount) { + trace!("Disabling APB_CLK"); + enable_apb_clk_impl(clocks, false); + release_cpu_clk(clocks); + } + } + #[allow(unused_variables)] + pub fn apb_clk_config_frequency(clocks: &mut ClockTree, config: ApbClkConfig) -> u32 { + (cpu_clk_frequency() / (config.divisor() + 1)) + } + pub fn apb_clk_frequency() -> u32 { + APB_CLK_FREQ_CACHE.load(::core::sync::atomic::Ordering::Acquire) + } + pub fn configure_lp_fast_clk(clocks: &mut ClockTree, new_selector: LpFastClkConfig) { + let old_selector = clocks.lp_fast_clk.replace(new_selector); + refresh_lp_fast_clk_downstream(clocks); + if clocks.lp_fast_clk_refcount > 0 { + match new_selector { + LpFastClkConfig::RcFast => request_rc_fast_clk(clocks), + LpFastClkConfig::XtalD2 => request_xtal_d2_clk(clocks), + } + configure_lp_fast_clk_impl(clocks, old_selector, new_selector); + if let Some(old_selector) = old_selector { + match old_selector { + LpFastClkConfig::RcFast => release_rc_fast_clk(clocks), + LpFastClkConfig::XtalD2 => release_xtal_d2_clk(clocks), + } + } + } else { + configure_lp_fast_clk_impl(clocks, old_selector, new_selector); + } + } + pub fn lp_fast_clk_config(clocks: &mut ClockTree) -> Option { + clocks.lp_fast_clk + } + pub fn request_lp_fast_clk(clocks: &mut ClockTree) { + trace!("Requesting LP_FAST_CLK"); + if increment_reference_count(&mut clocks.lp_fast_clk_refcount) { + trace!("Enabling LP_FAST_CLK"); + match unwrap!(clocks.lp_fast_clk) { + LpFastClkConfig::RcFast => request_rc_fast_clk(clocks), + LpFastClkConfig::XtalD2 => request_xtal_d2_clk(clocks), + } + enable_lp_fast_clk_impl(clocks, true); + } + } + pub fn release_lp_fast_clk(clocks: &mut ClockTree) { + trace!("Releasing LP_FAST_CLK"); + if decrement_reference_count(&mut clocks.lp_fast_clk_refcount) { + trace!("Disabling LP_FAST_CLK"); + enable_lp_fast_clk_impl(clocks, false); + match unwrap!(clocks.lp_fast_clk) { + LpFastClkConfig::RcFast => release_rc_fast_clk(clocks), + LpFastClkConfig::XtalD2 => release_xtal_d2_clk(clocks), + } + } + } + #[allow(unused_variables)] + pub fn lp_fast_clk_config_frequency( + clocks: &mut ClockTree, + config: LpFastClkConfig, + ) -> u32 { + match config { + LpFastClkConfig::RcFast => rc_fast_clk_frequency(), + LpFastClkConfig::XtalD2 => xtal_d2_clk_frequency(), + } + } + pub fn lp_fast_clk_frequency() -> u32 { + LP_FAST_CLK_FREQ_CACHE.load(::core::sync::atomic::Ordering::Acquire) + } + pub fn configure_lp_slow_clk(clocks: &mut ClockTree, new_selector: LpSlowClkConfig) { + let old_selector = clocks.lp_slow_clk.replace(new_selector); + refresh_lp_slow_clk_downstream(clocks); + if clocks.lp_slow_clk_refcount > 0 { + match new_selector { + LpSlowClkConfig::RcSlow => request_rc_slow_clk(clocks), + LpSlowClkConfig::Xtal32k => request_xtal32k_clk(clocks), + LpSlowClkConfig::Rc32k => request_rc32k_clk(clocks), + LpSlowClkConfig::OscSlow => request_osc_slow_clk(clocks), + } + configure_lp_slow_clk_impl(clocks, old_selector, new_selector); + if let Some(old_selector) = old_selector { + match old_selector { + LpSlowClkConfig::RcSlow => release_rc_slow_clk(clocks), + LpSlowClkConfig::Xtal32k => release_xtal32k_clk(clocks), + LpSlowClkConfig::Rc32k => release_rc32k_clk(clocks), + LpSlowClkConfig::OscSlow => release_osc_slow_clk(clocks), + } + } + } else { + configure_lp_slow_clk_impl(clocks, old_selector, new_selector); + } + } + pub fn lp_slow_clk_config(clocks: &mut ClockTree) -> Option { + clocks.lp_slow_clk + } + pub fn request_lp_slow_clk(clocks: &mut ClockTree) { + trace!("Requesting LP_SLOW_CLK"); + if increment_reference_count(&mut clocks.lp_slow_clk_refcount) { + trace!("Enabling LP_SLOW_CLK"); + match unwrap!(clocks.lp_slow_clk) { + LpSlowClkConfig::RcSlow => request_rc_slow_clk(clocks), + LpSlowClkConfig::Xtal32k => request_xtal32k_clk(clocks), + LpSlowClkConfig::Rc32k => request_rc32k_clk(clocks), + LpSlowClkConfig::OscSlow => request_osc_slow_clk(clocks), + } + enable_lp_slow_clk_impl(clocks, true); + } + } + pub fn release_lp_slow_clk(clocks: &mut ClockTree) { + trace!("Releasing LP_SLOW_CLK"); + if decrement_reference_count(&mut clocks.lp_slow_clk_refcount) { + trace!("Disabling LP_SLOW_CLK"); + enable_lp_slow_clk_impl(clocks, false); + match unwrap!(clocks.lp_slow_clk) { + LpSlowClkConfig::RcSlow => release_rc_slow_clk(clocks), + LpSlowClkConfig::Xtal32k => release_xtal32k_clk(clocks), + LpSlowClkConfig::Rc32k => release_rc32k_clk(clocks), + LpSlowClkConfig::OscSlow => release_osc_slow_clk(clocks), + } + } + } + #[allow(unused_variables)] + pub fn lp_slow_clk_config_frequency( + clocks: &mut ClockTree, + config: LpSlowClkConfig, + ) -> u32 { + match config { + LpSlowClkConfig::RcSlow => rc_slow_clk_frequency(), + LpSlowClkConfig::Xtal32k => xtal32k_clk_frequency(), + LpSlowClkConfig::Rc32k => rc32k_clk_frequency(), + LpSlowClkConfig::OscSlow => osc_slow_clk_frequency(), + } + } + pub fn lp_slow_clk_frequency() -> u32 { + LP_SLOW_CLK_FREQ_CACHE.load(::core::sync::atomic::Ordering::Acquire) + } + impl TimgInstance { + pub fn configure_function_clock( + self, + clocks: &mut ClockTree, + new_selector: TimgFunctionClockConfig, + ) { + let old_selector = clocks.timg_function_clock[self as usize].replace(new_selector); + refresh_timg_function_clock_downstream(clocks, self); + if clocks.timg_function_clock_refcount[self as usize] > 0 { + match new_selector { + TimgFunctionClockConfig::XtalClk => request_xtal_clk(clocks), + TimgFunctionClockConfig::RcFastClk => request_rc_fast_clk(clocks), + TimgFunctionClockConfig::PllF80m => request_pll_f80m(clocks), + } + self.configure_function_clock_impl(clocks, old_selector, new_selector); + if let Some(old_selector) = old_selector { + match old_selector { + TimgFunctionClockConfig::XtalClk => release_xtal_clk(clocks), + TimgFunctionClockConfig::RcFastClk => release_rc_fast_clk(clocks), + TimgFunctionClockConfig::PllF80m => release_pll_f80m(clocks), + } + } + } else { + self.configure_function_clock_impl(clocks, old_selector, new_selector); + } + } + pub fn function_clock_config( + self, + clocks: &mut ClockTree, + ) -> Option { + clocks.timg_function_clock[self as usize] + } + pub fn request_function_clock(self, clocks: &mut ClockTree) { + trace!("Requesting {:?}::FUNCTION_CLOCK", self); + if increment_reference_count( + &mut clocks.timg_function_clock_refcount[self as usize], + ) { + trace!("Enabling {:?}::FUNCTION_CLOCK", self); + match unwrap!(clocks.timg_function_clock[self as usize]) { + TimgFunctionClockConfig::XtalClk => request_xtal_clk(clocks), + TimgFunctionClockConfig::RcFastClk => request_rc_fast_clk(clocks), + TimgFunctionClockConfig::PllF80m => request_pll_f80m(clocks), + } + self.enable_function_clock_impl(clocks, true); + } + } + pub fn release_function_clock(self, clocks: &mut ClockTree) { + trace!("Releasing {:?}::FUNCTION_CLOCK", self); + if decrement_reference_count( + &mut clocks.timg_function_clock_refcount[self as usize], + ) { + trace!("Disabling {:?}::FUNCTION_CLOCK", self); + self.enable_function_clock_impl(clocks, false); + match unwrap!(clocks.timg_function_clock[self as usize]) { + TimgFunctionClockConfig::XtalClk => release_xtal_clk(clocks), + TimgFunctionClockConfig::RcFastClk => release_rc_fast_clk(clocks), + TimgFunctionClockConfig::PllF80m => release_pll_f80m(clocks), + } + } + } + #[allow(unused_variables)] + pub fn function_clock_config_frequency( + self, + clocks: &mut ClockTree, + config: TimgFunctionClockConfig, + ) -> u32 { + match config { + TimgFunctionClockConfig::XtalClk => xtal_clk_frequency(), + TimgFunctionClockConfig::RcFastClk => rc_fast_clk_frequency(), + TimgFunctionClockConfig::PllF80m => pll_f80m_frequency(), + } + } + pub fn function_clock_frequency(self) -> u32 { + TIMG_FUNCTION_CLOCK_FREQ_CACHE[self as usize] + .load(::core::sync::atomic::Ordering::Acquire) + } + pub fn configure_wdt_clock( + self, + clocks: &mut ClockTree, + new_selector: TimgWdtClockConfig, + ) { + let old_selector = clocks.timg_wdt_clock[self as usize].replace(new_selector); + refresh_timg_wdt_clock_downstream(clocks, self); + if clocks.timg_wdt_clock_refcount[self as usize] > 0 { + match new_selector { + TimgWdtClockConfig::XtalClk => request_xtal_clk(clocks), + TimgWdtClockConfig::PllF80m => request_pll_f80m(clocks), + TimgWdtClockConfig::RcFastClk => request_rc_fast_clk(clocks), + } + self.configure_wdt_clock_impl(clocks, old_selector, new_selector); + if let Some(old_selector) = old_selector { + match old_selector { + TimgWdtClockConfig::XtalClk => release_xtal_clk(clocks), + TimgWdtClockConfig::PllF80m => release_pll_f80m(clocks), + TimgWdtClockConfig::RcFastClk => release_rc_fast_clk(clocks), + } + } + } else { + self.configure_wdt_clock_impl(clocks, old_selector, new_selector); + } + } + pub fn wdt_clock_config(self, clocks: &mut ClockTree) -> Option { + clocks.timg_wdt_clock[self as usize] + } + pub fn request_wdt_clock(self, clocks: &mut ClockTree) { + trace!("Requesting {:?}::WDT_CLOCK", self); + if increment_reference_count(&mut clocks.timg_wdt_clock_refcount[self as usize]) { + trace!("Enabling {:?}::WDT_CLOCK", self); + match unwrap!(clocks.timg_wdt_clock[self as usize]) { + TimgWdtClockConfig::XtalClk => request_xtal_clk(clocks), + TimgWdtClockConfig::PllF80m => request_pll_f80m(clocks), + TimgWdtClockConfig::RcFastClk => request_rc_fast_clk(clocks), + } + self.enable_wdt_clock_impl(clocks, true); + } + } + pub fn release_wdt_clock(self, clocks: &mut ClockTree) { + trace!("Releasing {:?}::WDT_CLOCK", self); + if decrement_reference_count(&mut clocks.timg_wdt_clock_refcount[self as usize]) { + trace!("Disabling {:?}::WDT_CLOCK", self); + self.enable_wdt_clock_impl(clocks, false); + match unwrap!(clocks.timg_wdt_clock[self as usize]) { + TimgWdtClockConfig::XtalClk => release_xtal_clk(clocks), + TimgWdtClockConfig::PllF80m => release_pll_f80m(clocks), + TimgWdtClockConfig::RcFastClk => release_rc_fast_clk(clocks), + } + } + } + #[allow(unused_variables)] + pub fn wdt_clock_config_frequency( + self, + clocks: &mut ClockTree, + config: TimgWdtClockConfig, + ) -> u32 { + match config { + TimgWdtClockConfig::XtalClk => xtal_clk_frequency(), + TimgWdtClockConfig::PllF80m => pll_f80m_frequency(), + TimgWdtClockConfig::RcFastClk => rc_fast_clk_frequency(), + } + } + pub fn wdt_clock_frequency(self) -> u32 { + TIMG_WDT_CLOCK_FREQ_CACHE[self as usize] + .load(::core::sync::atomic::Ordering::Acquire) + } + } + impl UartInstance { + pub fn configure_function_clock( + self, + clocks: &mut ClockTree, + config: UartFunctionClockConfig, + ) { + let old_config = clocks.uart_function_clock[self as usize].replace(config); + refresh_uart_function_clock_downstream(clocks, self); + if clocks.uart_function_clock_refcount[self as usize] > 0 { + match config.sclk { + UartFunctionClockSclk::Xtal => request_xtal_clk(clocks), + UartFunctionClockSclk::PllF80m => request_pll_f80m(clocks), + UartFunctionClockSclk::RcFast => request_rc_fast_clk(clocks), + } + self.configure_function_clock_impl(clocks, old_config, config); + if let Some(old_config) = old_config { + match old_config.sclk { + UartFunctionClockSclk::Xtal => release_xtal_clk(clocks), + UartFunctionClockSclk::PllF80m => release_pll_f80m(clocks), + UartFunctionClockSclk::RcFast => release_rc_fast_clk(clocks), + } + } + } else { + self.configure_function_clock_impl(clocks, old_config, config); + } + } + pub fn function_clock_config( + self, + clocks: &mut ClockTree, + ) -> Option { + clocks.uart_function_clock[self as usize] + } + pub fn request_function_clock(self, clocks: &mut ClockTree) { + trace!("Requesting {:?}::FUNCTION_CLOCK", self); + if increment_reference_count( + &mut clocks.uart_function_clock_refcount[self as usize], + ) { + trace!("Enabling {:?}::FUNCTION_CLOCK", self); + match unwrap!(clocks.uart_function_clock[self as usize]).sclk { + UartFunctionClockSclk::Xtal => request_xtal_clk(clocks), + UartFunctionClockSclk::PllF80m => request_pll_f80m(clocks), + UartFunctionClockSclk::RcFast => request_rc_fast_clk(clocks), + } + self.enable_function_clock_impl(clocks, true); + } + } + pub fn release_function_clock(self, clocks: &mut ClockTree) { + trace!("Releasing {:?}::FUNCTION_CLOCK", self); + if decrement_reference_count( + &mut clocks.uart_function_clock_refcount[self as usize], + ) { + trace!("Disabling {:?}::FUNCTION_CLOCK", self); + self.enable_function_clock_impl(clocks, false); + match unwrap!(clocks.uart_function_clock[self as usize]).sclk { + UartFunctionClockSclk::Xtal => release_xtal_clk(clocks), + UartFunctionClockSclk::PllF80m => release_pll_f80m(clocks), + UartFunctionClockSclk::RcFast => release_rc_fast_clk(clocks), + } + } + } + #[allow(unused_variables)] + pub fn function_clock_config_frequency( + self, + clocks: &mut ClockTree, + config: UartFunctionClockConfig, + ) -> u32 { + (match config.sclk { + UartFunctionClockSclk::Xtal => xtal_clk_frequency(), + UartFunctionClockSclk::PllF80m => pll_f80m_frequency(), + UartFunctionClockSclk::RcFast => rc_fast_clk_frequency(), + } / (config.div_num() + 1)) + } + pub fn function_clock_frequency(self) -> u32 { + UART_FUNCTION_CLOCK_FREQ_CACHE[self as usize] + .load(::core::sync::atomic::Ordering::Acquire) + } + pub fn configure_baud_rate_generator( + self, + clocks: &mut ClockTree, + config: UartBaudRateGeneratorConfig, + ) { + let old_config = clocks.uart_baud_rate_generator[self as usize].replace(config); + refresh_uart_baud_rate_generator_downstream(clocks, self); + self.configure_baud_rate_generator_impl(clocks, old_config, config); + } + pub fn baud_rate_generator_config( + self, + clocks: &mut ClockTree, + ) -> Option { + clocks.uart_baud_rate_generator[self as usize] + } + pub fn request_baud_rate_generator(self, clocks: &mut ClockTree) { + trace!("Requesting {:?}::BAUD_RATE_GENERATOR", self); + if increment_reference_count( + &mut clocks.uart_baud_rate_generator_refcount[self as usize], + ) { + trace!("Enabling {:?}::BAUD_RATE_GENERATOR", self); + self.request_function_clock(clocks); + self.enable_baud_rate_generator_impl(clocks, true); + } + } + pub fn release_baud_rate_generator(self, clocks: &mut ClockTree) { + trace!("Releasing {:?}::BAUD_RATE_GENERATOR", self); + if decrement_reference_count( + &mut clocks.uart_baud_rate_generator_refcount[self as usize], + ) { + trace!("Disabling {:?}::BAUD_RATE_GENERATOR", self); + self.enable_baud_rate_generator_impl(clocks, false); + self.release_function_clock(clocks); + } + } + #[allow(unused_variables)] + pub fn baud_rate_generator_config_frequency( + self, + clocks: &mut ClockTree, + config: UartBaudRateGeneratorConfig, + ) -> u32 { + ((self.function_clock_frequency() * 16) + / ((config.integral() * 16) + config.fractional())) + } + pub fn baud_rate_generator_frequency(self) -> u32 { + UART_BAUD_RATE_GENERATOR_FREQ_CACHE[self as usize] + .load(::core::sync::atomic::Ordering::Acquire) + } + } + /// Clock tree configuration. + /// + /// The fields of this struct are optional, with the following caveats: + /// - If `XTAL_CLK` is not specified, the crystal frequency will be automatically detected + /// if possible. + /// - The CPU and its upstream clock nodes will be set to a default configuration. + /// - Other unspecified clock sources will not be useable by peripherals. + #[derive(Debug, Clone, Copy, PartialEq, Eq)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] + #[instability::unstable] + pub struct ClockConfig { + /// `CPU_ROOT_CLK` configuration. + pub cpu_root_clk: Option, + /// `CPU_CLK` configuration. + pub cpu_clk: Option, + /// `APB_CLK` configuration. + pub apb_clk: Option, + /// `LP_FAST_CLK` configuration. + pub lp_fast_clk: Option, + /// `LP_SLOW_CLK` configuration. + pub lp_slow_clk: Option, + } + impl ClockConfig { + fn apply(&self, clocks: &mut ClockTree) { + if let Some(config) = self.cpu_root_clk { + configure_cpu_root_clk(clocks, config); + } + if let Some(config) = self.cpu_clk { + configure_cpu_clk(clocks, config); + } + if let Some(config) = self.apb_clk { + configure_apb_clk(clocks, config); + } + if let Some(config) = self.lp_fast_clk { + configure_lp_fast_clk(clocks, config); + } + if let Some(config) = self.lp_slow_clk { + configure_lp_slow_clk(clocks, config); + } + } + } + fn increment_reference_count(refcount: &mut u32) -> bool { + let first = *refcount == 0; + *refcount = unwrap!(refcount.checked_add(1), "Reference count overflow"); + first + } + fn decrement_reference_count(refcount: &mut u32) -> bool { + *refcount = refcount.saturating_sub(1); + let last = *refcount == 0; + last + } + fn refresh_cpu_root_clk_downstream(clocks: &mut ClockTree) { + if let Some(config) = clocks.cpu_root_clk { + CPU_ROOT_CLK_FREQ_CACHE.store( + cpu_root_clk_config_frequency(clocks, config), + ::core::sync::atomic::Ordering::Release, + ); + } + refresh_cpu_clk_downstream(clocks); + } + fn refresh_cpu_clk_downstream(clocks: &mut ClockTree) { + if let Some(config) = clocks.cpu_clk { + CPU_CLK_FREQ_CACHE.store( + cpu_clk_config_frequency(clocks, config), + ::core::sync::atomic::Ordering::Release, + ); + } + refresh_apb_clk_downstream(clocks); + } + fn refresh_apb_clk_downstream(clocks: &mut ClockTree) { + if let Some(config) = clocks.apb_clk { + APB_CLK_FREQ_CACHE.store( + apb_clk_config_frequency(clocks, config), + ::core::sync::atomic::Ordering::Release, + ); + } + } + fn refresh_lp_fast_clk_downstream(clocks: &mut ClockTree) { + if let Some(config) = clocks.lp_fast_clk { + LP_FAST_CLK_FREQ_CACHE.store( + lp_fast_clk_config_frequency(clocks, config), + ::core::sync::atomic::Ordering::Release, + ); + } + } + fn refresh_lp_slow_clk_downstream(clocks: &mut ClockTree) { + if let Some(config) = clocks.lp_slow_clk { + LP_SLOW_CLK_FREQ_CACHE.store( + lp_slow_clk_config_frequency(clocks, config), + ::core::sync::atomic::Ordering::Release, + ); + } + } + fn refresh_timg_function_clock_downstream(clocks: &mut ClockTree, instance: TimgInstance) { + if let Some(config) = clocks.timg_function_clock[instance as usize] { + TIMG_FUNCTION_CLOCK_FREQ_CACHE[instance as usize].store( + instance.function_clock_config_frequency(clocks, config), + ::core::sync::atomic::Ordering::Release, + ); + } + } + fn refresh_timg_wdt_clock_downstream(clocks: &mut ClockTree, instance: TimgInstance) { + if let Some(config) = clocks.timg_wdt_clock[instance as usize] { + TIMG_WDT_CLOCK_FREQ_CACHE[instance as usize].store( + instance.wdt_clock_config_frequency(clocks, config), + ::core::sync::atomic::Ordering::Release, + ); + } + } + fn refresh_uart_function_clock_downstream(clocks: &mut ClockTree, instance: UartInstance) { + if let Some(config) = clocks.uart_function_clock[instance as usize] { + UART_FUNCTION_CLOCK_FREQ_CACHE[instance as usize].store( + instance.function_clock_config_frequency(clocks, config), + ::core::sync::atomic::Ordering::Release, + ); + } + refresh_uart_baud_rate_generator_downstream(clocks, instance); + } + fn refresh_uart_baud_rate_generator_downstream( + clocks: &mut ClockTree, + instance: UartInstance, + ) { + if let Some(config) = clocks.uart_baud_rate_generator[instance as usize] { + UART_BAUD_RATE_GENERATOR_FREQ_CACHE[instance as usize].store( + instance.baud_rate_generator_config_frequency(clocks, config), + ::core::sync::atomic::Ordering::Release, + ); + } + } + }; +} +/// Implement the `Peripheral` enum and enable/disable/reset functions. +/// +/// This macro is intended to be placed in `esp_hal::system`. +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! implement_peripheral_clocks { + () => { + #[doc(hidden)] + #[derive(Debug, Clone, Copy, PartialEq, Eq)] + #[repr(u8)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] + pub enum Peripheral { + /// ADC peripheral clock signal + Adc, + /// AES peripheral clock signal + Aes, + /// AHB_PDMA peripheral clock signal + AhbPdma, + /// AXI_PDMA peripheral clock signal + AxiPdma, + /// DMA peripheral clock signal + Dma, + /// DS peripheral clock signal + Ds, + /// ECC peripheral clock signal + Ecc, + /// ECDSA peripheral clock signal + Ecdsa, + /// EMAC peripheral clock signal + Emac, + /// GDMA peripheral clock signal + Gdma, + /// HMAC peripheral clock signal + Hmac, + /// I2C0 peripheral clock signal + I2c0, + /// I2C1 peripheral clock signal + I2c1, + /// I2S0 peripheral clock signal + I2s0, + /// I2S1 peripheral clock signal + I2s1, + /// I2S2 peripheral clock signal + I2s2, + /// IOMUX peripheral clock signal + Iomux, + /// LCD_CAM peripheral clock signal + LcdCam, + /// LEDC peripheral clock signal + Ledc, + /// MCPWM0 peripheral clock signal + Mcpwm0, + /// MCPWM1 peripheral clock signal + Mcpwm1, + /// PARL_IO peripheral clock signal + ParlIo, + /// PCNT peripheral clock signal + Pcnt, + /// RMT peripheral clock signal + Rmt, + /// RSA peripheral clock signal + Rsa, + /// SDMMC peripheral clock signal + Sdmmc, + /// SHA peripheral clock signal + Sha, + /// SPI2 peripheral clock signal + Spi2, + /// SPI3 peripheral clock signal + Spi3, + /// SYSTIMER peripheral clock signal + Systimer, + /// TIMG0 peripheral clock signal + Timg0, + /// TIMG1 peripheral clock signal + Timg1, + /// TWAI0 peripheral clock signal + Twai0, + /// TWAI1 peripheral clock signal + Twai1, + /// TWAI2 peripheral clock signal + Twai2, + /// UART0 peripheral clock signal + Uart0, + /// UART1 peripheral clock signal + Uart1, + /// UART2 peripheral clock signal + Uart2, + /// UART3 peripheral clock signal + Uart3, + /// UART4 peripheral clock signal + Uart4, + /// UHCI peripheral clock signal + Uhci, + /// USB_DEVICE peripheral clock signal + UsbDevice, + /// USB_OTG11 peripheral clock signal + UsbOtg11, + /// USB_OTG20 peripheral clock signal + UsbOtg20, + } + impl Peripheral { + const KEEP_ENABLED: &[Peripheral] = + &[Self::Iomux, Self::Systimer, Self::Uart0, Self::UsbDevice]; + const COUNT: usize = Self::ALL.len(); + const ALL: &[Self] = &[ + Self::Adc, + Self::Aes, + Self::AhbPdma, + Self::AxiPdma, + Self::Dma, + Self::Ds, + Self::Ecc, + Self::Ecdsa, + Self::Emac, + Self::Gdma, + Self::Hmac, + Self::I2c0, + Self::I2c1, + Self::I2s0, + Self::I2s1, + Self::I2s2, + Self::Iomux, + Self::LcdCam, + Self::Ledc, + Self::Mcpwm0, + Self::Mcpwm1, + Self::ParlIo, + Self::Pcnt, + Self::Rmt, + Self::Rsa, + Self::Sdmmc, + Self::Sha, + Self::Spi2, + Self::Spi3, + Self::Systimer, + Self::Timg0, + Self::Timg1, + Self::Twai0, + Self::Twai1, + Self::Twai2, + Self::Uart0, + Self::Uart1, + Self::Uart2, + Self::Uart3, + Self::Uart4, + Self::Uhci, + Self::UsbDevice, + Self::UsbOtg11, + Self::UsbOtg20, + ]; + } + unsafe fn enable_internal_racey(peripheral: Peripheral, enable: bool) { + match peripheral { + Peripheral::Adc => { + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl2() + .modify(|_, w| w.adc_apb_clk_en().bit(enable)); + } + Peripheral::Aes => { + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl1() + .modify(|_, w| w.crypto_sys_clk_en().bit(enable)); + } + Peripheral::AhbPdma => { + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl1() + .modify(|_, w| w.ahb_pdma_sys_clk_en().bit(enable)); + } + Peripheral::AxiPdma => { + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl1() + .modify(|_, w| w.axi_pdma_sys_clk_en().bit(enable)); + } + Peripheral::Dma => { + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl1() + .modify(|_, w| w.ahb_pdma_sys_clk_en().bit(enable)); + } + Peripheral::Ds => { + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl1() + .modify(|_, w| w.crypto_sys_clk_en().bit(enable)); + } + Peripheral::Ecc => { + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl1() + .modify(|_, w| w.crypto_sys_clk_en().bit(enable)); + } + Peripheral::Ecdsa => { + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl1() + .modify(|_, w| w.crypto_sys_clk_en().bit(enable)); + } + Peripheral::Emac => { + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl1() + .modify(|_, w| w.emac_sys_clk_en().bit(enable)); + } + Peripheral::Gdma => { + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl1() + .modify(|_, w| w.gdma_sys_clk_en().bit(enable)); + } + Peripheral::Hmac => { + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl1() + .modify(|_, w| w.crypto_sys_clk_en().bit(enable)); + } + Peripheral::I2c0 => { + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl2() + .modify(|_, w| w.i2c0_apb_clk_en().bit(enable)); + } + Peripheral::I2c1 => { + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl2() + .modify(|_, w| w.i2c1_apb_clk_en().bit(enable)); + } + Peripheral::I2s0 => { + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl2() + .modify(|_, w| w.i2s0_apb_clk_en().bit(enable)); + } + Peripheral::I2s1 => { + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl2() + .modify(|_, w| w.i2s1_apb_clk_en().bit(enable)); + } + Peripheral::I2s2 => { + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl2() + .modify(|_, w| w.i2s2_apb_clk_en().bit(enable)); + } + Peripheral::Iomux => { + crate::peripherals::HP_SYS_CLKRST::regs() + .peri_clk_ctrl26() + .modify(|_, w| w.iomux_clk_en().bit(enable)); + } + Peripheral::LcdCam => { + let _ = enable; + } + Peripheral::Ledc => { + let _ = enable; + } + Peripheral::Mcpwm0 => { + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl2() + .modify(|_, w| w.mcpwm0_apb_clk_en().bit(enable)); + } + Peripheral::Mcpwm1 => { + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl2() + .modify(|_, w| w.mcpwm1_apb_clk_en().bit(enable)); + } + Peripheral::ParlIo => { + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl1() + .modify(|_, w| w.parlio_sys_clk_en().bit(enable)); + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl2() + .modify(|_, w| w.parlio_apb_clk_en().bit(enable)); + } + Peripheral::Pcnt => { + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl2() + .modify(|_, w| w.pcnt_apb_clk_en().bit(enable)); + } + Peripheral::Rmt => { + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl2() + .modify(|_, w| w.rmt_sys_clk_en().bit(enable)); + } + Peripheral::Rsa => { + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl1() + .modify(|_, w| w.crypto_sys_clk_en().bit(enable)); + } + Peripheral::Sdmmc => { + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl1() + .modify(|_, w| w.sdmmc_sys_clk_en().bit(enable)); + } + Peripheral::Sha => { + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl1() + .modify(|_, w| w.crypto_sys_clk_en().bit(enable)); + } + Peripheral::Spi2 => { + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl1() + .modify(|_, w| w.gpspi2_sys_clk_en().bit(enable)); + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl2() + .modify(|_, w| w.gpspi2_apb_clk_en().bit(enable)); + } + Peripheral::Spi3 => { + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl1() + .modify(|_, w| w.gpspi3_sys_clk_en().bit(enable)); + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl2() + .modify(|_, w| w.gpspi3_apb_clk_en().bit(enable)); + } + Peripheral::Systimer => { + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl2() + .modify(|_, w| w.systimer_apb_clk_en().bit(enable)); + crate::peripherals::HP_SYS_CLKRST::regs() + .peri_clk_ctrl21() + .modify(|_, w| w.systimer_clk_en().bit(enable)); + } + Peripheral::Timg0 => { + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl2() + .modify(|_, w| w.timergrp0_apb_clk_en().bit(enable)); + } + Peripheral::Timg1 => { + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl2() + .modify(|_, w| w.timergrp1_apb_clk_en().bit(enable)); + } + Peripheral::Twai0 => { + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl2() + .modify(|_, w| w.twai0_apb_clk_en().bit(enable)); + } + Peripheral::Twai1 => { + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl2() + .modify(|_, w| w.twai1_apb_clk_en().bit(enable)); + } + Peripheral::Twai2 => { + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl2() + .modify(|_, w| w.twai2_apb_clk_en().bit(enable)); + } + Peripheral::Uart0 => { + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl1() + .modify(|_, w| w.uart0_sys_clk_en().bit(enable)); + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl2() + .modify(|_, w| w.uart0_apb_clk_en().bit(enable)); + } + Peripheral::Uart1 => { + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl1() + .modify(|_, w| w.uart1_sys_clk_en().bit(enable)); + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl2() + .modify(|_, w| w.uart1_apb_clk_en().bit(enable)); + } + Peripheral::Uart2 => { + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl1() + .modify(|_, w| w.uart2_sys_clk_en().bit(enable)); + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl2() + .modify(|_, w| w.uart2_apb_clk_en().bit(enable)); + } + Peripheral::Uart3 => { + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl1() + .modify(|_, w| w.uart3_sys_clk_en().bit(enable)); + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl2() + .modify(|_, w| w.uart3_apb_clk_en().bit(enable)); + } + Peripheral::Uart4 => { + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl1() + .modify(|_, w| w.uart4_sys_clk_en().bit(enable)); + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl2() + .modify(|_, w| w.uart4_apb_clk_en().bit(enable)); + } + Peripheral::Uhci => { + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl1() + .modify(|_, w| w.uhci_sys_clk_en().bit(enable)); + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl2() + .modify(|_, w| w.uhci_apb_clk_en().bit(enable)); + } + Peripheral::UsbDevice => { + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl2() + .modify(|_, w| w.usb_device_apb_clk_en().bit(enable)); + } + Peripheral::UsbOtg11 => { + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl1() + .modify(|_, w| w.usb_otg11_sys_clk_en().bit(enable)); + } + Peripheral::UsbOtg20 => { + crate::peripherals::HP_SYS_CLKRST::regs() + .soc_clk_ctrl1() + .modify(|_, w| w.usb_otg20_sys_clk_en().bit(enable)); + } + } + } + unsafe fn assert_peri_reset_racey(peripheral: Peripheral, reset: bool) { + match peripheral { + Peripheral::Adc => { + crate::peripherals::HP_SYS_CLKRST::regs() + .hp_rst_en2() + .modify(|_, w| w.rst_en_adc().bit(reset)); + } + Peripheral::Aes => { + crate::peripherals::HP_SYS_CLKRST::regs() + .hp_rst_en2() + .modify(|_, w| w.rst_en_aes().bit(reset)); + } + Peripheral::AhbPdma => { + crate::peripherals::HP_SYS_CLKRST::regs() + .hp_rst_en1() + .modify(|_, w| w.rst_en_ahb_pdma().bit(reset)); + } + Peripheral::AxiPdma => { + crate::peripherals::HP_SYS_CLKRST::regs() + .hp_rst_en1() + .modify(|_, w| w.rst_en_axi_pdma().bit(reset)); + } + Peripheral::Dma => { + crate::peripherals::HP_SYS_CLKRST::regs() + .hp_rst_en1() + .modify(|_, w| w.rst_en_ahb_pdma().bit(reset)); + } + Peripheral::Ds => { + crate::peripherals::HP_SYS_CLKRST::regs() + .hp_rst_en2() + .modify(|_, w| w.rst_en_ds().bit(reset)); + } + Peripheral::Ecc => { + crate::peripherals::HP_SYS_CLKRST::regs() + .hp_rst_en2() + .modify(|_, w| w.rst_en_ecc().bit(reset)); + } + Peripheral::Ecdsa => { + crate::peripherals::HP_SYS_CLKRST::regs() + .hp_rst_en2() + .modify(|_, w| w.rst_en_ecdsa().bit(reset)); + } + Peripheral::Emac => { + let _ = reset; + } + Peripheral::Gdma => { + crate::peripherals::HP_SYS_CLKRST::regs() + .hp_rst_en0() + .modify(|_, w| w.rst_en_gdma().bit(reset)); + } + Peripheral::Hmac => { + crate::peripherals::HP_SYS_CLKRST::regs() + .hp_rst_en2() + .modify(|_, w| w.rst_en_hmac().bit(reset)); + } + Peripheral::I2c0 => { + crate::peripherals::HP_SYS_CLKRST::regs() + .hp_rst_en1() + .modify(|_, w| w.rst_en_i2c0().bit(reset)); + } + Peripheral::I2c1 => { + crate::peripherals::HP_SYS_CLKRST::regs() + .hp_rst_en1() + .modify(|_, w| w.rst_en_i2c1().bit(reset)); + } + Peripheral::I2s0 => { + crate::peripherals::HP_SYS_CLKRST::regs() + .hp_rst_en2() + .modify(|_, w| w.rst_en_i2s0_apb().bit(reset)); + } + Peripheral::I2s1 => { + crate::peripherals::HP_SYS_CLKRST::regs() + .hp_rst_en2() + .modify(|_, w| w.rst_en_i2s1_apb().bit(reset)); + } + Peripheral::I2s2 => { + crate::peripherals::HP_SYS_CLKRST::regs() + .hp_rst_en2() + .modify(|_, w| w.rst_en_i2s2_apb().bit(reset)); + } + Peripheral::Iomux => { + crate::peripherals::HP_SYS_CLKRST::regs() + .hp_rst_en1() + .modify(|_, w| w.rst_en_iomux().bit(reset)); + } + Peripheral::LcdCam => { + crate::peripherals::HP_SYS_CLKRST::regs() + .hp_rst_en2() + .modify(|_, w| w.rst_en_lcdcam().bit(reset)); + } + Peripheral::Ledc => { + crate::peripherals::HP_SYS_CLKRST::regs() + .hp_rst_en1() + .modify(|_, w| w.rst_en_ledc().bit(reset)); + } + Peripheral::Mcpwm0 => { + crate::peripherals::HP_SYS_CLKRST::regs() + .hp_rst_en1() + .modify(|_, w| w.rst_en_pwm0().bit(reset)); + } + Peripheral::Mcpwm1 => { + crate::peripherals::HP_SYS_CLKRST::regs() + .hp_rst_en1() + .modify(|_, w| w.rst_en_pwm1().bit(reset)); + } + Peripheral::ParlIo => { + crate::peripherals::HP_SYS_CLKRST::regs() + .hp_rst_en2() + .modify(|_, w| { + w.rst_en_parlio() + .bit(reset) + .rst_en_parlio_rx() + .bit(reset) + .rst_en_parlio_tx() + .bit(reset) + }); + } + Peripheral::Pcnt => { + crate::peripherals::HP_SYS_CLKRST::regs() + .hp_rst_en1() + .modify(|_, w| w.rst_en_pcnt().bit(reset)); + } + Peripheral::Rmt => { + crate::peripherals::HP_SYS_CLKRST::regs() + .hp_rst_en1() + .modify(|_, w| w.rst_en_rmt().bit(reset)); + } + Peripheral::Rsa => { + crate::peripherals::HP_SYS_CLKRST::regs() + .hp_rst_en2() + .modify(|_, w| w.rst_en_rsa().bit(reset)); + } + Peripheral::Sdmmc => { + let _ = reset; + } + Peripheral::Sha => { + crate::peripherals::HP_SYS_CLKRST::regs() + .hp_rst_en2() + .modify(|_, w| w.rst_en_sha().bit(reset)); + } + Peripheral::Spi2 => { + crate::peripherals::HP_SYS_CLKRST::regs() + .hp_rst_en2() + .modify(|_, w| w.rst_en_spi2().bit(reset)); + } + Peripheral::Spi3 => { + crate::peripherals::HP_SYS_CLKRST::regs() + .hp_rst_en2() + .modify(|_, w| w.rst_en_spi3().bit(reset)); + } + Peripheral::Systimer => { + crate::peripherals::HP_SYS_CLKRST::regs() + .hp_rst_en1() + .modify(|_, w| w.rst_en_stimer().bit(reset)); + } + Peripheral::Timg0 => { + crate::peripherals::HP_SYS_CLKRST::regs() + .hp_rst_en1() + .modify(|_, w| w.rst_en_timergrp0().bit(reset)); + } + Peripheral::Timg1 => { + crate::peripherals::HP_SYS_CLKRST::regs() + .hp_rst_en1() + .modify(|_, w| w.rst_en_timergrp1().bit(reset)); + } + Peripheral::Twai0 => { + crate::peripherals::HP_SYS_CLKRST::regs() + .hp_rst_en1() + .modify(|_, w| w.rst_en_can0().bit(reset)); + } + Peripheral::Twai1 => { + crate::peripherals::HP_SYS_CLKRST::regs() + .hp_rst_en1() + .modify(|_, w| w.rst_en_can1().bit(reset)); + } + Peripheral::Twai2 => { + crate::peripherals::HP_SYS_CLKRST::regs() + .hp_rst_en1() + .modify(|_, w| w.rst_en_can2().bit(reset)); + } + Peripheral::Uart0 => { + crate::peripherals::HP_SYS_CLKRST::regs() + .hp_rst_en1() + .modify(|_, w| { + w.rst_en_uart0_core() + .bit(reset) + .rst_en_uart0_apb() + .bit(reset) + }); + } + Peripheral::Uart1 => { + crate::peripherals::HP_SYS_CLKRST::regs() + .hp_rst_en1() + .modify(|_, w| { + w.rst_en_uart1_core() + .bit(reset) + .rst_en_uart1_apb() + .bit(reset) + }); + } + Peripheral::Uart2 => { + crate::peripherals::HP_SYS_CLKRST::regs() + .hp_rst_en1() + .modify(|_, w| { + w.rst_en_uart2_core() + .bit(reset) + .rst_en_uart2_apb() + .bit(reset) + }); + } + Peripheral::Uart3 => { + crate::peripherals::HP_SYS_CLKRST::regs() + .hp_rst_en1() + .modify(|_, w| { + w.rst_en_uart3_core() + .bit(reset) + .rst_en_uart3_apb() + .bit(reset) + }); + } + Peripheral::Uart4 => { + crate::peripherals::HP_SYS_CLKRST::regs() + .hp_rst_en1() + .modify(|_, w| { + w.rst_en_uart4_core() + .bit(reset) + .rst_en_uart4_apb() + .bit(reset) + }); + } + Peripheral::Uhci => { + crate::peripherals::HP_SYS_CLKRST::regs() + .hp_rst_en1() + .modify(|_, w| w.rst_en_uhci().bit(reset)); + } + Peripheral::UsbDevice => { + let _ = reset; + } + Peripheral::UsbOtg11 => { + let _ = reset; + } + Peripheral::UsbOtg20 => { + let _ = reset; + } + } + } + }; +} +/// Macro to get the address range of the given memory region. +/// +/// This macro provides two syntax options for each memory region: +/// +/// - `memory_range!("region_name")` returns the address range as a range expression (`start..end`). +/// - `memory_range!(size as str, "region_name")` returns the size of the region as a string +/// literal. +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! memory_range { + ("DRAM") => { + 0x4FF40000..0x4FFC0000 + }; + (size as str, "DRAM") => { + "524288" + }; + ("DRAM2_UNINIT") => { + 0x4FF00000..0x4FF40000 + }; + (size as str, "DRAM2_UNINIT") => { + "262144" + }; +} +/// This macro can be used to generate code for each peripheral instance of the I2C master driver. +/// +/// For an explanation on the general syntax, as well as usage of individual/repeated +/// matchers, refer to [the crate-level documentation][crate#for_each-macros]. +/// +/// This macro has one option for its "Individual matcher" case: +/// +/// Syntax: `($id:literal, $instance:ident, $sys:ident, $scl:ident, $sda:ident)` +/// +/// Macro fragments: +/// - `$id`: the index of the I2C instance +/// - `$instance`: the name of the I2C instance +/// - `$sys`: the name of the instance as it is in the `esp_hal::system::Peripheral` enum. +/// - `$scl`, `$sda`: peripheral signal names. +/// +/// Example data: `(0, I2C0, I2cExt0, I2CEXT0_SCL, I2CEXT0_SDA)` +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! for_each_i2c_master { + ($($pattern:tt => $code:tt;)*) => { + macro_rules! _for_each_inner_i2c_master { $(($pattern) => $code;)* ($other : tt) + => {} } _for_each_inner_i2c_master!((0, I2C0, I2c0, I2C0_SCL, I2C0_SDA)); + _for_each_inner_i2c_master!((1, I2C1, I2c1, I2C1_SCL, I2C1_SDA)); + _for_each_inner_i2c_master!((all(0, I2C0, I2c0, I2C0_SCL, I2C0_SDA), (1, I2C1, + I2c1, I2C1_SCL, I2C1_SDA))); + }; +} +/// This macro can be used to generate code for each peripheral instance of the UART driver. +/// +/// For an explanation on the general syntax, as well as usage of individual/repeated +/// matchers, refer to [the crate-level documentation][crate#for_each-macros]. +/// +/// This macro has one option for its "Individual matcher" case: +/// +/// Syntax: `($id:literal, $instance:ident, $sys:ident, $rx:ident, $tx:ident, $cts:ident, +/// $rts:ident)` +/// +/// Macro fragments: +/// +/// - `$id`: the index of the UART instance +/// - `$instance`: the name of the UART instance +/// - `$sys`: the name of the instance as it is in the `esp_hal::system::Peripheral` enum. +/// - `$rx`, `$tx`, `$cts`, `$rts`: signal names. +/// +/// Example data: `(0, UART0, Uart0, U0RXD, U0TXD, U0CTS, U0RTS)` +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! for_each_uart { + ($($pattern:tt => $code:tt;)*) => { + macro_rules! _for_each_inner_uart { $(($pattern) => $code;)* ($other : tt) => {} + } _for_each_inner_uart!((0, UART0, Uart0, UART0_RXD, UART0_TXD, UART0_CTS, + UART0_RTS)); _for_each_inner_uart!((1, UART1, Uart1, UART1_RXD, UART1_TXD, + UART1_CTS, UART1_RTS)); _for_each_inner_uart!((2, UART2, Uart2, UART2_RXD, + UART2_TXD, UART2_CTS, UART2_RTS)); _for_each_inner_uart!((3, UART3, Uart3, + UART3_RXD, UART3_TXD, UART3_CTS, UART3_RTS)); _for_each_inner_uart!((4, UART4, + Uart4, UART4_RXD, UART4_TXD, UART4_CTS, UART4_RTS)); + _for_each_inner_uart!((all(0, UART0, Uart0, UART0_RXD, UART0_TXD, UART0_CTS, + UART0_RTS), (1, UART1, Uart1, UART1_RXD, UART1_TXD, UART1_CTS, UART1_RTS), (2, + UART2, Uart2, UART2_RXD, UART2_TXD, UART2_CTS, UART2_RTS), (3, UART3, Uart3, + UART3_RXD, UART3_TXD, UART3_CTS, UART3_RTS), (4, UART4, Uart4, UART4_RXD, + UART4_TXD, UART4_CTS, UART4_RTS))); + }; +} +/// This macro can be used to generate code for each peripheral instance of the SPI master driver. +/// +/// For an explanation on the general syntax, as well as usage of individual/repeated +/// matchers, refer to [the crate-level documentation][crate#for_each-macros]. +/// +/// This macro has one option for its "Individual matcher" case: +/// +/// Syntax: `($instance:ident, $sys:ident, $sclk:ident [$($cs:ident),*] [$($sio:ident),*] +/// $($is_qspi:literal)?)` +/// +/// Macro fragments: +/// +/// - `$instance`: the name of the SPI instance +/// - `$sys`: the name of the instance as it is in the `esp_hal::system::Peripheral` enum. +/// - `$cs`, `$sio`: chip select and SIO signal names. +/// - `$is_qspi`: a `true` literal present if the SPI instance supports QSPI. +/// +/// Example data: +/// - `(SPI2, Spi2, FSPICLK [FSPICS0, FSPICS1, FSPICS2, FSPICS3, FSPICS4, FSPICS5] [FSPID, FSPIQ, +/// FSPIWP, FSPIHD, FSPIIO4, FSPIIO5, FSPIIO6, FSPIIO7], true)` +/// - `(SPI3, Spi3, SPI3_CLK [SPI3_CS0, SPI3_CS1, SPI3_CS2] [SPI3_D, SPI3_Q])` +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! for_each_spi_master { + ($($pattern:tt => $code:tt;)*) => { + macro_rules! _for_each_inner_spi_master { $(($pattern) => $code;)* ($other : tt) + => {} } _for_each_inner_spi_master!((SPI2, Spi2, SPI2_CK[SPI2_CS] [SPI2_D, + SPI2_Q, SPI2_WP, SPI2_HOLD], true)); _for_each_inner_spi_master!((SPI3, Spi3, + SPI3_CK[SPI3_CS, SPI3_CS1, SPI3_CS2] [SPI3_D, SPI3_Q, SPI3_WP, SPI3_HOLD], + true)); _for_each_inner_spi_master!((all(SPI2, Spi2, SPI2_CK[SPI2_CS] [SPI2_D, + SPI2_Q, SPI2_WP, SPI2_HOLD], true), (SPI3, Spi3, SPI3_CK[SPI3_CS, SPI3_CS1, + SPI3_CS2] [SPI3_D, SPI3_Q, SPI3_WP, SPI3_HOLD], true))); + }; +} +/// This macro can be used to generate code for each peripheral instance of the SPI slave driver. +/// +/// For an explanation on the general syntax, as well as usage of individual/repeated +/// matchers, refer to [the crate-level documentation][crate#for_each-macros]. +/// +/// This macro has one option for its "Individual matcher" case: +/// +/// Syntax: `($instance:ident, $sys:ident, $sclk:ident, $mosi:ident, $miso:ident, $cs:ident)` +/// +/// Macro fragments: +/// +/// - `$instance`: the name of the SPI instance +/// - `$sys`: the name of the instance as it is in the `esp_hal::system::Peripheral` enum. +/// - `$sclk`, `$mosi`, `$miso`, `$cs`: signal names. +/// +/// Example data: `(SPI2, Spi2, FSPICLK, FSPID, FSPIQ, FSPICS0)` +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! for_each_spi_slave { + ($($pattern:tt => $code:tt;)*) => { + macro_rules! _for_each_inner_spi_slave { $(($pattern) => $code;)* ($other : tt) + => {} } _for_each_inner_spi_slave!((all)); + }; +} +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! for_each_peripheral { + ($($pattern:tt => $code:tt;)*) => { + macro_rules! _for_each_inner_peripheral { $(($pattern) => $code;)* ($other : tt) + => {} } _for_each_inner_peripheral!((@ peri_type #[doc = + "GPIO0 peripheral singleton"] GPIO0 <= virtual())); + _for_each_inner_peripheral!((@ peri_type #[doc = "GPIO1 peripheral singleton"] + GPIO1 <= virtual())); _for_each_inner_peripheral!((@ peri_type #[doc = + "GPIO2 peripheral singleton (Limitations exist)"] #[doc = ""] #[doc = + "
"] #[doc = + "This pin may be available with certain limitations. Check your hardware to make sure whether you can use it."] + #[doc = "
    "] #[doc = + "
  • These pins may be used to debug the chip using an external JTAG debugger.
  • "] + #[doc = "
"] #[doc = "
"] GPIO2 <= virtual())); + _for_each_inner_peripheral!((@ peri_type #[doc = + "GPIO3 peripheral singleton (Limitations exist)"] #[doc = ""] #[doc = + "
"] #[doc = + "This pin may be available with certain limitations. Check your hardware to make sure whether you can use it."] + #[doc = "
    "] #[doc = + "
  • These pins may be used to debug the chip using an external JTAG debugger.
  • "] + #[doc = "
"] #[doc = "
"] GPIO3 <= virtual())); + _for_each_inner_peripheral!((@ peri_type #[doc = + "GPIO4 peripheral singleton (Limitations exist)"] #[doc = ""] #[doc = + "
"] #[doc = + "This pin may be available with certain limitations. Check your hardware to make sure whether you can use it."] + #[doc = "
    "] #[doc = + "
  • These pins may be used to debug the chip using an external JTAG debugger.
  • "] + #[doc = "
"] #[doc = "
"] GPIO4 <= virtual())); + _for_each_inner_peripheral!((@ peri_type #[doc = + "GPIO5 peripheral singleton (Limitations exist)"] #[doc = ""] #[doc = + "
"] #[doc = + "This pin may be available with certain limitations. Check your hardware to make sure whether you can use it."] + #[doc = "
    "] #[doc = + "
  • These pins may be used to debug the chip using an external JTAG debugger.
  • "] + #[doc = "
"] #[doc = "
"] GPIO5 <= virtual())); + _for_each_inner_peripheral!((@ peri_type #[doc = "GPIO6 peripheral singleton"] + GPIO6 <= virtual())); _for_each_inner_peripheral!((@ peri_type #[doc = + "GPIO7 peripheral singleton"] GPIO7 <= virtual())); + _for_each_inner_peripheral!((@ peri_type #[doc = "GPIO8 peripheral singleton"] + GPIO8 <= virtual())); _for_each_inner_peripheral!((@ peri_type #[doc = + "GPIO9 peripheral singleton"] GPIO9 <= virtual())); + _for_each_inner_peripheral!((@ peri_type #[doc = "GPIO10 peripheral singleton"] + GPIO10 <= virtual())); _for_each_inner_peripheral!((@ peri_type #[doc = + "GPIO11 peripheral singleton"] GPIO11 <= virtual())); + _for_each_inner_peripheral!((@ peri_type #[doc = "GPIO12 peripheral singleton"] + GPIO12 <= virtual())); _for_each_inner_peripheral!((@ peri_type #[doc = + "GPIO13 peripheral singleton"] GPIO13 <= virtual())); + _for_each_inner_peripheral!((@ peri_type #[doc = "GPIO14 peripheral singleton"] + GPIO14 <= virtual())); _for_each_inner_peripheral!((@ peri_type #[doc = + "GPIO15 peripheral singleton"] GPIO15 <= virtual())); + _for_each_inner_peripheral!((@ peri_type #[doc = "GPIO16 peripheral singleton"] + GPIO16 <= virtual())); _for_each_inner_peripheral!((@ peri_type #[doc = + "GPIO17 peripheral singleton"] GPIO17 <= virtual())); + _for_each_inner_peripheral!((@ peri_type #[doc = "GPIO18 peripheral singleton"] + GPIO18 <= virtual())); _for_each_inner_peripheral!((@ peri_type #[doc = + "GPIO19 peripheral singleton"] GPIO19 <= virtual())); + _for_each_inner_peripheral!((@ peri_type #[doc = "GPIO20 peripheral singleton"] + GPIO20 <= virtual())); _for_each_inner_peripheral!((@ peri_type #[doc = + "GPIO21 peripheral singleton"] GPIO21 <= virtual())); + _for_each_inner_peripheral!((@ peri_type #[doc = "GPIO22 peripheral singleton"] + GPIO22 <= virtual())); _for_each_inner_peripheral!((@ peri_type #[doc = + "GPIO23 peripheral singleton"] GPIO23 <= virtual())); + _for_each_inner_peripheral!((@ peri_type #[doc = + "GPIO24 peripheral singleton (Limitations exist)"] #[doc = ""] #[doc = + "
"] #[doc = + "This pin may be available with certain limitations. Check your hardware to make sure whether you can use it."] + #[doc = "
    "] #[doc = + "
  • These pins may be used to debug the chip using USB.
  • "] #[doc = "
"] + #[doc = "
"] GPIO24 <= virtual())); _for_each_inner_peripheral!((@ + peri_type #[doc = "GPIO25 peripheral singleton (Limitations exist)"] #[doc = ""] + #[doc = "
"] #[doc = + "This pin may be available with certain limitations. Check your hardware to make sure whether you can use it."] + #[doc = "
    "] #[doc = + "
  • These pins may be used to debug the chip using USB.
  • "] #[doc = "
"] + #[doc = "
"] GPIO25 <= virtual())); _for_each_inner_peripheral!((@ + peri_type #[doc = "GPIO26 peripheral singleton (Limitations exist)"] #[doc = ""] + #[doc = "
"] #[doc = + "This pin may be available with certain limitations. Check your hardware to make sure whether you can use it."] + #[doc = "
    "] #[doc = + "
  • These pins may be used to debug the chip using USB.
  • "] #[doc = "
"] + #[doc = "
"] GPIO26 <= virtual())); _for_each_inner_peripheral!((@ + peri_type #[doc = "GPIO27 peripheral singleton (Limitations exist)"] #[doc = ""] + #[doc = "
"] #[doc = + "This pin may be available with certain limitations. Check your hardware to make sure whether you can use it."] + #[doc = "
    "] #[doc = + "
  • These pins may be used to debug the chip using USB.
  • "] #[doc = "
"] + #[doc = "
"] GPIO27 <= virtual())); _for_each_inner_peripheral!((@ + peri_type #[doc = "GPIO28 peripheral singleton"] GPIO28 <= virtual())); + _for_each_inner_peripheral!((@ peri_type #[doc = "GPIO29 peripheral singleton"] + GPIO29 <= virtual())); _for_each_inner_peripheral!((@ peri_type #[doc = + "GPIO30 peripheral singleton"] GPIO30 <= virtual())); + _for_each_inner_peripheral!((@ peri_type #[doc = "GPIO31 peripheral singleton"] + GPIO31 <= virtual())); _for_each_inner_peripheral!((@ peri_type #[doc = + "GPIO32 peripheral singleton (Limitations exist)"] #[doc = ""] #[doc = + "
"] #[doc = + "This pin may be available with certain limitations. Check your hardware to make sure whether you can use it."] + #[doc = "
    "] #[doc = + "
  • This pin is a strapping pin, it determines how the chip boots.
  • "] #[doc + = "
"] #[doc = "
"] GPIO32 <= virtual())); + _for_each_inner_peripheral!((@ peri_type #[doc = + "GPIO33 peripheral singleton (Limitations exist)"] #[doc = ""] #[doc = + "
"] #[doc = + "This pin may be available with certain limitations. Check your hardware to make sure whether you can use it."] + #[doc = "
    "] #[doc = + "
  • This pin is a strapping pin, it determines how the chip boots.
  • "] #[doc + = "
"] #[doc = "
"] GPIO33 <= virtual())); + _for_each_inner_peripheral!((@ peri_type #[doc = + "GPIO34 peripheral singleton (Limitations exist)"] #[doc = ""] #[doc = + "
"] #[doc = + "This pin may be available with certain limitations. Check your hardware to make sure whether you can use it."] + #[doc = "
    "] #[doc = + "
  • This pin is a strapping pin, it determines how the chip boots.
  • "] #[doc + = "
"] #[doc = "
"] GPIO34 <= virtual())); + _for_each_inner_peripheral!((@ peri_type #[doc = + "GPIO35 peripheral singleton (Limitations exist)"] #[doc = ""] #[doc = + "
"] #[doc = + "This pin may be available with certain limitations. Check your hardware to make sure whether you can use it."] + #[doc = "
    "] #[doc = + "
  • This pin is a strapping pin, it determines how the chip boots.
  • "] #[doc + = "
"] #[doc = "
"] GPIO35 <= virtual())); + _for_each_inner_peripheral!((@ peri_type #[doc = + "GPIO36 peripheral singleton (Limitations exist)"] #[doc = ""] #[doc = + "
"] #[doc = + "This pin may be available with certain limitations. Check your hardware to make sure whether you can use it."] + #[doc = "
    "] #[doc = + "
  • This pin is a strapping pin, it determines how the chip boots.
  • "] #[doc + = "
"] #[doc = "
"] GPIO36 <= virtual())); + _for_each_inner_peripheral!((@ peri_type #[doc = + "GPIO37 peripheral singleton (Limitations exist)"] #[doc = ""] #[doc = + "
"] #[doc = + "This pin may be available with certain limitations. Check your hardware to make sure whether you can use it."] + #[doc = "
    "] #[doc = + "
  • This pin is a strapping pin, it determines how the chip boots.
  • "] #[doc + = "
"] #[doc = "
"] GPIO37 <= virtual())); + _for_each_inner_peripheral!((@ peri_type #[doc = + "GPIO38 peripheral singleton (Limitations exist)"] #[doc = ""] #[doc = + "
"] #[doc = + "This pin may be available with certain limitations. Check your hardware to make sure whether you can use it."] + #[doc = "
    "] #[doc = + "
  • This pin is a strapping pin, it determines how the chip boots.
  • "] #[doc + = "
"] #[doc = "
"] GPIO38 <= virtual())); + _for_each_inner_peripheral!((@ peri_type #[doc = "GPIO39 peripheral singleton"] + GPIO39 <= virtual())); _for_each_inner_peripheral!((@ peri_type #[doc = + "GPIO40 peripheral singleton"] GPIO40 <= virtual())); + _for_each_inner_peripheral!((@ peri_type #[doc = "GPIO41 peripheral singleton"] + GPIO41 <= virtual())); _for_each_inner_peripheral!((@ peri_type #[doc = + "GPIO42 peripheral singleton"] GPIO42 <= virtual())); + _for_each_inner_peripheral!((@ peri_type #[doc = "GPIO43 peripheral singleton"] + GPIO43 <= virtual())); _for_each_inner_peripheral!((@ peri_type #[doc = + "GPIO44 peripheral singleton"] GPIO44 <= virtual())); + _for_each_inner_peripheral!((@ peri_type #[doc = "GPIO45 peripheral singleton"] + GPIO45 <= virtual())); _for_each_inner_peripheral!((@ peri_type #[doc = + "GPIO46 peripheral singleton"] GPIO46 <= virtual())); + _for_each_inner_peripheral!((@ peri_type #[doc = "GPIO47 peripheral singleton"] + GPIO47 <= virtual())); _for_each_inner_peripheral!((@ peri_type #[doc = + "GPIO48 peripheral singleton"] GPIO48 <= virtual())); + _for_each_inner_peripheral!((@ peri_type #[doc = "GPIO49 peripheral singleton"] + GPIO49 <= virtual())); _for_each_inner_peripheral!((@ peri_type #[doc = + "GPIO50 peripheral singleton"] GPIO50 <= virtual())); + _for_each_inner_peripheral!((@ peri_type #[doc = "GPIO51 peripheral singleton"] + GPIO51 <= virtual())); _for_each_inner_peripheral!((@ peri_type #[doc = + "GPIO52 peripheral singleton"] GPIO52 <= virtual())); + _for_each_inner_peripheral!((@ peri_type #[doc = "GPIO53 peripheral singleton"] + GPIO53 <= virtual())); _for_each_inner_peripheral!((@ peri_type #[doc = + "GPIO54 peripheral singleton"] GPIO54 <= virtual())); + _for_each_inner_peripheral!((@ peri_type #[doc = "EFUSE peripheral singleton"] + EFUSE <= EFUSE() (unstable))); _for_each_inner_peripheral!((@ peri_type #[doc = + "GPIO peripheral singleton"] GPIO <= GPIO() (unstable))); + _for_each_inner_peripheral!((@ peri_type #[doc = "HP_SYS peripheral singleton"] + HP_SYS <= HP_SYS() (unstable))); _for_each_inner_peripheral!((@ peri_type #[doc = + "HP_SYS_CLKRST peripheral singleton"] HP_SYS_CLKRST <= HP_SYS_CLKRST() + (unstable))); _for_each_inner_peripheral!((@ peri_type #[doc = + "INTERRUPT_CORE0 peripheral singleton"] INTERRUPT_CORE0 <= INTERRUPT_CORE0() + (unstable))); _for_each_inner_peripheral!((@ peri_type #[doc = + "INTERRUPT_CORE1 peripheral singleton"] INTERRUPT_CORE1 <= INTERRUPT_CORE1() + (unstable))); _for_each_inner_peripheral!((@ peri_type #[doc = + "CLIC peripheral singleton"] CLIC <= CLIC() (unstable))); + _for_each_inner_peripheral!((@ peri_type #[doc = "IO_MUX peripheral singleton"] + IO_MUX <= IO_MUX() (unstable))); _for_each_inner_peripheral!((@ peri_type #[doc = + "LP_AON peripheral singleton"] LP_AON <= LP_SYS() (unstable))); + _for_each_inner_peripheral!((@ peri_type #[doc = + "LP_AON_CLKRST peripheral singleton"] LP_AON_CLKRST <= LP_AON_CLKRST() + (unstable))); _for_each_inner_peripheral!((@ peri_type #[doc = + "LP_SYS peripheral singleton"] LP_SYS <= LP_SYS() (unstable))); + _for_each_inner_peripheral!((@ peri_type #[doc = "LP_WDT peripheral singleton"] + LP_WDT <= LP_WDT() (unstable))); _for_each_inner_peripheral!((@ peri_type #[doc = + "LPWR peripheral singleton"] LPWR <= LP_SYS() (unstable))); + _for_each_inner_peripheral!((@ peri_type #[doc = "PMU peripheral singleton"] PMU + <= PMU() (unstable))); _for_each_inner_peripheral!((@ peri_type #[doc = + "SYSTIMER peripheral singleton"] SYSTIMER <= SYSTIMER() (unstable))); + _for_each_inner_peripheral!((@ peri_type #[doc = "TIMG0 peripheral singleton"] + TIMG0 <= TIMG0() (unstable))); _for_each_inner_peripheral!((@ peri_type #[doc = + "TIMG1 peripheral singleton"] TIMG1 <= TIMG1() (unstable))); + _for_each_inner_peripheral!((@ peri_type #[doc = "UART0 peripheral singleton"] + UART0 <= UART0(UART0 : { bind_peri_interrupt, enable_peri_interrupt, + disable_peri_interrupt }) (unstable))); _for_each_inner_peripheral!((@ peri_type + #[doc = "UART1 peripheral singleton"] UART1 <= UART1(UART1 : { + bind_peri_interrupt, enable_peri_interrupt, disable_peri_interrupt }) + (unstable))); _for_each_inner_peripheral!((@ peri_type #[doc = + "UART2 peripheral singleton"] UART2 <= UART2(UART2 : { bind_peri_interrupt, + enable_peri_interrupt, disable_peri_interrupt }) (unstable))); + _for_each_inner_peripheral!((@ peri_type #[doc = "UART3 peripheral singleton"] + UART3 <= UART3(UART3 : { bind_peri_interrupt, enable_peri_interrupt, + disable_peri_interrupt }) (unstable))); _for_each_inner_peripheral!((@ peri_type + #[doc = "UART4 peripheral singleton"] UART4 <= UART4(UART4 : { + bind_peri_interrupt, enable_peri_interrupt, disable_peri_interrupt }) + (unstable))); _for_each_inner_peripheral!((@ peri_type #[doc = + "SPI2 peripheral singleton"] SPI2 <= SPI2(SPI2 : { bind_peri_interrupt, + enable_peri_interrupt, disable_peri_interrupt }) (unstable))); + _for_each_inner_peripheral!((@ peri_type #[doc = "SPI3 peripheral singleton"] + SPI3 <= SPI2(SPI3 : { bind_peri_interrupt, enable_peri_interrupt, + disable_peri_interrupt }) (unstable))); _for_each_inner_peripheral!((@ peri_type + #[doc = "I2C0 peripheral singleton"] I2C0 <= I2C0(I2C0 : { bind_peri_interrupt, + enable_peri_interrupt, disable_peri_interrupt }) (unstable))); + _for_each_inner_peripheral!((@ peri_type #[doc = "I2C1 peripheral singleton"] + I2C1 <= I2C1(I2C1 : { bind_peri_interrupt, enable_peri_interrupt, + disable_peri_interrupt }) (unstable))); _for_each_inner_peripheral!((@ peri_type + #[doc = "TWAI0 peripheral singleton"] TWAI0 <= TWAI0(TWAI0 : { + bind_peri_interrupt, enable_peri_interrupt, disable_peri_interrupt }) + (unstable))); _for_each_inner_peripheral!((@ peri_type #[doc = + "TWAI1 peripheral singleton"] TWAI1 <= TWAI1(TWAI1 : { bind_peri_interrupt, + enable_peri_interrupt, disable_peri_interrupt }) (unstable))); + _for_each_inner_peripheral!((@ peri_type #[doc = "TWAI2 peripheral singleton"] + TWAI2 <= TWAI2(TWAI2 : { bind_peri_interrupt, enable_peri_interrupt, + disable_peri_interrupt }) (unstable))); _for_each_inner_peripheral!((@ peri_type + #[doc = "PSRAM peripheral singleton"] PSRAM <= virtual() (unstable))); + _for_each_inner_peripheral!((@ peri_type #[doc = "DMA peripheral singleton"] DMA + <= AHB_DMA() (unstable))); _for_each_inner_peripheral!((@ peri_type #[doc = + "DMA_CH0 peripheral singleton"] DMA_CH0 <= virtual() (unstable))); + _for_each_inner_peripheral!((@ peri_type #[doc = "DMA_CH1 peripheral singleton"] + DMA_CH1 <= virtual() (unstable))); _for_each_inner_peripheral!((@ peri_type #[doc + = "DMA_CH2 peripheral singleton"] DMA_CH2 <= virtual() (unstable))); + _for_each_inner_peripheral!((@ peri_type #[doc = + "USB_DEVICE peripheral singleton"] USB_DEVICE <= USB_DEVICE(USB_DEVICE : { + bind_peri_interrupt, enable_peri_interrupt, disable_peri_interrupt }) + (unstable))); _for_each_inner_peripheral!((@ peri_type #[doc = + "SDHOST peripheral singleton"] SDHOST <= SDHOST() (unstable))); + _for_each_inner_peripheral!((@ peri_type #[doc = "LEDC peripheral singleton"] + LEDC <= LEDC(LEDC : { bind_peri_interrupt, enable_peri_interrupt, + disable_peri_interrupt }) (unstable))); _for_each_inner_peripheral!((@ peri_type + #[doc = "MCPWM0 peripheral singleton"] MCPWM0 <= MCPWM0(PWM0 : { + bind_peri_interrupt, enable_peri_interrupt, disable_peri_interrupt }) + (unstable))); _for_each_inner_peripheral!((@ peri_type #[doc = + "MCPWM1 peripheral singleton"] MCPWM1 <= MCPWM1(PWM1 : { bind_peri_interrupt, + enable_peri_interrupt, disable_peri_interrupt }) (unstable))); + _for_each_inner_peripheral!((@ peri_type #[doc = "PCNT peripheral singleton"] + PCNT <= PCNT(PCNT : { bind_peri_interrupt, enable_peri_interrupt, + disable_peri_interrupt }) (unstable))); _for_each_inner_peripheral!((@ peri_type + #[doc = "RMT peripheral singleton"] RMT <= RMT(RMT : { bind_peri_interrupt, + enable_peri_interrupt, disable_peri_interrupt }) (unstable))); + _for_each_inner_peripheral!((@ peri_type #[doc = "ADC peripheral singleton"] ADC + <= ADC() (unstable))); _for_each_inner_peripheral!((@ peri_type #[doc = + "AES peripheral singleton"] AES <= AES(AES : { bind_peri_interrupt, + enable_peri_interrupt, disable_peri_interrupt }) (unstable))); + _for_each_inner_peripheral!((@ peri_type #[doc = "SHA peripheral singleton"] SHA + <= SHA(SHA : { bind_peri_interrupt, enable_peri_interrupt, disable_peri_interrupt + }) (unstable))); _for_each_inner_peripheral!((@ peri_type #[doc = + "RSA peripheral singleton"] RSA <= RSA(RSA : { bind_peri_interrupt, + enable_peri_interrupt, disable_peri_interrupt }) (unstable))); + _for_each_inner_peripheral!((@ peri_type #[doc = "ECC peripheral singleton"] ECC + <= ECC(ECC : { bind_peri_interrupt, enable_peri_interrupt, disable_peri_interrupt + }) (unstable))); _for_each_inner_peripheral!((GPIO0)); + _for_each_inner_peripheral!((GPIO1)); _for_each_inner_peripheral!((GPIO2)); + _for_each_inner_peripheral!((GPIO3)); _for_each_inner_peripheral!((GPIO4)); + _for_each_inner_peripheral!((GPIO5)); _for_each_inner_peripheral!((GPIO6)); + _for_each_inner_peripheral!((GPIO7)); _for_each_inner_peripheral!((GPIO8)); + _for_each_inner_peripheral!((GPIO9)); _for_each_inner_peripheral!((GPIO10)); + _for_each_inner_peripheral!((GPIO11)); _for_each_inner_peripheral!((GPIO12)); + _for_each_inner_peripheral!((GPIO13)); _for_each_inner_peripheral!((GPIO14)); + _for_each_inner_peripheral!((GPIO15)); _for_each_inner_peripheral!((GPIO16)); + _for_each_inner_peripheral!((GPIO17)); _for_each_inner_peripheral!((GPIO18)); + _for_each_inner_peripheral!((GPIO19)); _for_each_inner_peripheral!((GPIO20)); + _for_each_inner_peripheral!((GPIO21)); _for_each_inner_peripheral!((GPIO22)); + _for_each_inner_peripheral!((GPIO23)); _for_each_inner_peripheral!((GPIO24)); + _for_each_inner_peripheral!((GPIO25)); _for_each_inner_peripheral!((GPIO26)); + _for_each_inner_peripheral!((GPIO27)); _for_each_inner_peripheral!((GPIO28)); + _for_each_inner_peripheral!((GPIO29)); _for_each_inner_peripheral!((GPIO30)); + _for_each_inner_peripheral!((GPIO31)); _for_each_inner_peripheral!((GPIO32)); + _for_each_inner_peripheral!((GPIO33)); _for_each_inner_peripheral!((GPIO34)); + _for_each_inner_peripheral!((GPIO35)); _for_each_inner_peripheral!((GPIO36)); + _for_each_inner_peripheral!((GPIO37)); _for_each_inner_peripheral!((GPIO38)); + _for_each_inner_peripheral!((GPIO39)); _for_each_inner_peripheral!((GPIO40)); + _for_each_inner_peripheral!((GPIO41)); _for_each_inner_peripheral!((GPIO42)); + _for_each_inner_peripheral!((GPIO43)); _for_each_inner_peripheral!((GPIO44)); + _for_each_inner_peripheral!((GPIO45)); _for_each_inner_peripheral!((GPIO46)); + _for_each_inner_peripheral!((GPIO47)); _for_each_inner_peripheral!((GPIO48)); + _for_each_inner_peripheral!((GPIO49)); _for_each_inner_peripheral!((GPIO50)); + _for_each_inner_peripheral!((GPIO51)); _for_each_inner_peripheral!((GPIO52)); + _for_each_inner_peripheral!((GPIO53)); _for_each_inner_peripheral!((GPIO54)); + _for_each_inner_peripheral!((GPIO(unstable))); + _for_each_inner_peripheral!((HP_SYS(unstable))); + _for_each_inner_peripheral!((HP_SYS_CLKRST(unstable))); + _for_each_inner_peripheral!((INTERRUPT_CORE0(unstable))); + _for_each_inner_peripheral!((INTERRUPT_CORE1(unstable))); + _for_each_inner_peripheral!((CLIC(unstable))); + _for_each_inner_peripheral!((IO_MUX(unstable))); + _for_each_inner_peripheral!((LP_AON(unstable))); + _for_each_inner_peripheral!((LP_AON_CLKRST(unstable))); + _for_each_inner_peripheral!((LP_SYS(unstable))); + _for_each_inner_peripheral!((LP_WDT(unstable))); + _for_each_inner_peripheral!((LPWR(unstable))); + _for_each_inner_peripheral!((PMU(unstable))); + _for_each_inner_peripheral!((SYSTIMER(unstable))); + _for_each_inner_peripheral!((TIMG0(unstable))); + _for_each_inner_peripheral!((TIMG1(unstable))); + _for_each_inner_peripheral!((UART0(unstable))); + _for_each_inner_peripheral!((UART1(unstable))); + _for_each_inner_peripheral!((UART2(unstable))); + _for_each_inner_peripheral!((UART3(unstable))); + _for_each_inner_peripheral!((UART4(unstable))); + _for_each_inner_peripheral!((SPI2(unstable))); + _for_each_inner_peripheral!((SPI3(unstable))); + _for_each_inner_peripheral!((I2C0(unstable))); + _for_each_inner_peripheral!((I2C1(unstable))); + _for_each_inner_peripheral!((TWAI0(unstable))); + _for_each_inner_peripheral!((TWAI1(unstable))); + _for_each_inner_peripheral!((TWAI2(unstable))); + _for_each_inner_peripheral!((PSRAM(unstable))); + _for_each_inner_peripheral!((DMA(unstable))); + _for_each_inner_peripheral!((DMA_CH0(unstable))); + _for_each_inner_peripheral!((DMA_CH1(unstable))); + _for_each_inner_peripheral!((DMA_CH2(unstable))); + _for_each_inner_peripheral!((USB_DEVICE(unstable))); + _for_each_inner_peripheral!((SDHOST(unstable))); + _for_each_inner_peripheral!((LEDC(unstable))); + _for_each_inner_peripheral!((MCPWM0(unstable))); + _for_each_inner_peripheral!((MCPWM1(unstable))); + _for_each_inner_peripheral!((PCNT(unstable))); + _for_each_inner_peripheral!((RMT(unstable))); + _for_each_inner_peripheral!((ADC(unstable))); + _for_each_inner_peripheral!((AES(unstable))); + _for_each_inner_peripheral!((SHA(unstable))); + _for_each_inner_peripheral!((RSA(unstable))); + _for_each_inner_peripheral!((ECC(unstable))); _for_each_inner_peripheral!((SPI2, + Spi2, 1)); _for_each_inner_peripheral!((SPI3, Spi3, 2)); + _for_each_inner_peripheral!((AES, Aes, 4)); _for_each_inner_peripheral!((SHA, + Sha, 5)); _for_each_inner_peripheral!((all(@ peri_type #[doc = + "GPIO0 peripheral singleton"] GPIO0 <= virtual()), (@ peri_type #[doc = + "GPIO1 peripheral singleton"] GPIO1 <= virtual()), (@ peri_type #[doc = + "GPIO2 peripheral singleton (Limitations exist)"] #[doc = ""] #[doc = + "
"] #[doc = + "This pin may be available with certain limitations. Check your hardware to make sure whether you can use it."] + #[doc = "
    "] #[doc = + "
  • These pins may be used to debug the chip using an external JTAG debugger.
  • "] + #[doc = "
"] #[doc = "
"] GPIO2 <= virtual()), (@ peri_type #[doc = + "GPIO3 peripheral singleton (Limitations exist)"] #[doc = ""] #[doc = + "
"] #[doc = + "This pin may be available with certain limitations. Check your hardware to make sure whether you can use it."] + #[doc = "
    "] #[doc = + "
  • These pins may be used to debug the chip using an external JTAG debugger.
  • "] + #[doc = "
"] #[doc = "
"] GPIO3 <= virtual()), (@ peri_type #[doc = + "GPIO4 peripheral singleton (Limitations exist)"] #[doc = ""] #[doc = + "
"] #[doc = + "This pin may be available with certain limitations. Check your hardware to make sure whether you can use it."] + #[doc = "
    "] #[doc = + "
  • These pins may be used to debug the chip using an external JTAG debugger.
  • "] + #[doc = "
"] #[doc = "
"] GPIO4 <= virtual()), (@ peri_type #[doc = + "GPIO5 peripheral singleton (Limitations exist)"] #[doc = ""] #[doc = + "
"] #[doc = + "This pin may be available with certain limitations. Check your hardware to make sure whether you can use it."] + #[doc = "
    "] #[doc = + "
  • These pins may be used to debug the chip using an external JTAG debugger.
  • "] + #[doc = "
"] #[doc = "
"] GPIO5 <= virtual()), (@ peri_type #[doc = + "GPIO6 peripheral singleton"] GPIO6 <= virtual()), (@ peri_type #[doc = + "GPIO7 peripheral singleton"] GPIO7 <= virtual()), (@ peri_type #[doc = + "GPIO8 peripheral singleton"] GPIO8 <= virtual()), (@ peri_type #[doc = + "GPIO9 peripheral singleton"] GPIO9 <= virtual()), (@ peri_type #[doc = + "GPIO10 peripheral singleton"] GPIO10 <= virtual()), (@ peri_type #[doc = + "GPIO11 peripheral singleton"] GPIO11 <= virtual()), (@ peri_type #[doc = + "GPIO12 peripheral singleton"] GPIO12 <= virtual()), (@ peri_type #[doc = + "GPIO13 peripheral singleton"] GPIO13 <= virtual()), (@ peri_type #[doc = + "GPIO14 peripheral singleton"] GPIO14 <= virtual()), (@ peri_type #[doc = + "GPIO15 peripheral singleton"] GPIO15 <= virtual()), (@ peri_type #[doc = + "GPIO16 peripheral singleton"] GPIO16 <= virtual()), (@ peri_type #[doc = + "GPIO17 peripheral singleton"] GPIO17 <= virtual()), (@ peri_type #[doc = + "GPIO18 peripheral singleton"] GPIO18 <= virtual()), (@ peri_type #[doc = + "GPIO19 peripheral singleton"] GPIO19 <= virtual()), (@ peri_type #[doc = + "GPIO20 peripheral singleton"] GPIO20 <= virtual()), (@ peri_type #[doc = + "GPIO21 peripheral singleton"] GPIO21 <= virtual()), (@ peri_type #[doc = + "GPIO22 peripheral singleton"] GPIO22 <= virtual()), (@ peri_type #[doc = + "GPIO23 peripheral singleton"] GPIO23 <= virtual()), (@ peri_type #[doc = + "GPIO24 peripheral singleton (Limitations exist)"] #[doc = ""] #[doc = + "
"] #[doc = + "This pin may be available with certain limitations. Check your hardware to make sure whether you can use it."] + #[doc = "
    "] #[doc = + "
  • These pins may be used to debug the chip using USB.
  • "] #[doc = "
"] + #[doc = "
"] GPIO24 <= virtual()), (@ peri_type #[doc = + "GPIO25 peripheral singleton (Limitations exist)"] #[doc = ""] #[doc = + "
"] #[doc = + "This pin may be available with certain limitations. Check your hardware to make sure whether you can use it."] + #[doc = "
    "] #[doc = + "
  • These pins may be used to debug the chip using USB.
  • "] #[doc = "
"] + #[doc = "
"] GPIO25 <= virtual()), (@ peri_type #[doc = + "GPIO26 peripheral singleton (Limitations exist)"] #[doc = ""] #[doc = + "
"] #[doc = + "This pin may be available with certain limitations. Check your hardware to make sure whether you can use it."] + #[doc = "
    "] #[doc = + "
  • These pins may be used to debug the chip using USB.
  • "] #[doc = "
"] + #[doc = "
"] GPIO26 <= virtual()), (@ peri_type #[doc = + "GPIO27 peripheral singleton (Limitations exist)"] #[doc = ""] #[doc = + "
"] #[doc = + "This pin may be available with certain limitations. Check your hardware to make sure whether you can use it."] + #[doc = "
    "] #[doc = + "
  • These pins may be used to debug the chip using USB.
  • "] #[doc = "
"] + #[doc = "
"] GPIO27 <= virtual()), (@ peri_type #[doc = + "GPIO28 peripheral singleton"] GPIO28 <= virtual()), (@ peri_type #[doc = + "GPIO29 peripheral singleton"] GPIO29 <= virtual()), (@ peri_type #[doc = + "GPIO30 peripheral singleton"] GPIO30 <= virtual()), (@ peri_type #[doc = + "GPIO31 peripheral singleton"] GPIO31 <= virtual()), (@ peri_type #[doc = + "GPIO32 peripheral singleton (Limitations exist)"] #[doc = ""] #[doc = + "
"] #[doc = + "This pin may be available with certain limitations. Check your hardware to make sure whether you can use it."] + #[doc = "
    "] #[doc = + "
  • This pin is a strapping pin, it determines how the chip boots.
  • "] #[doc + = "
"] #[doc = "
"] GPIO32 <= virtual()), (@ peri_type #[doc = + "GPIO33 peripheral singleton (Limitations exist)"] #[doc = ""] #[doc = + "
"] #[doc = + "This pin may be available with certain limitations. Check your hardware to make sure whether you can use it."] + #[doc = "
    "] #[doc = + "
  • This pin is a strapping pin, it determines how the chip boots.
  • "] #[doc + = "
"] #[doc = "
"] GPIO33 <= virtual()), (@ peri_type #[doc = + "GPIO34 peripheral singleton (Limitations exist)"] #[doc = ""] #[doc = + "
"] #[doc = + "This pin may be available with certain limitations. Check your hardware to make sure whether you can use it."] + #[doc = "
    "] #[doc = + "
  • This pin is a strapping pin, it determines how the chip boots.
  • "] #[doc + = "
"] #[doc = "
"] GPIO34 <= virtual()), (@ peri_type #[doc = + "GPIO35 peripheral singleton (Limitations exist)"] #[doc = ""] #[doc = + "
"] #[doc = + "This pin may be available with certain limitations. Check your hardware to make sure whether you can use it."] + #[doc = "
    "] #[doc = + "
  • This pin is a strapping pin, it determines how the chip boots.
  • "] #[doc + = "
"] #[doc = "
"] GPIO35 <= virtual()), (@ peri_type #[doc = + "GPIO36 peripheral singleton (Limitations exist)"] #[doc = ""] #[doc = + "
"] #[doc = + "This pin may be available with certain limitations. Check your hardware to make sure whether you can use it."] + #[doc = "
    "] #[doc = + "
  • This pin is a strapping pin, it determines how the chip boots.
  • "] #[doc + = "
"] #[doc = "
"] GPIO36 <= virtual()), (@ peri_type #[doc = + "GPIO37 peripheral singleton (Limitations exist)"] #[doc = ""] #[doc = + "
"] #[doc = + "This pin may be available with certain limitations. Check your hardware to make sure whether you can use it."] + #[doc = "
    "] #[doc = + "
  • This pin is a strapping pin, it determines how the chip boots.
  • "] #[doc + = "
"] #[doc = "
"] GPIO37 <= virtual()), (@ peri_type #[doc = + "GPIO38 peripheral singleton (Limitations exist)"] #[doc = ""] #[doc = + "
"] #[doc = + "This pin may be available with certain limitations. Check your hardware to make sure whether you can use it."] + #[doc = "
    "] #[doc = + "
  • This pin is a strapping pin, it determines how the chip boots.
  • "] #[doc + = "
"] #[doc = "
"] GPIO38 <= virtual()), (@ peri_type #[doc = + "GPIO39 peripheral singleton"] GPIO39 <= virtual()), (@ peri_type #[doc = + "GPIO40 peripheral singleton"] GPIO40 <= virtual()), (@ peri_type #[doc = + "GPIO41 peripheral singleton"] GPIO41 <= virtual()), (@ peri_type #[doc = + "GPIO42 peripheral singleton"] GPIO42 <= virtual()), (@ peri_type #[doc = + "GPIO43 peripheral singleton"] GPIO43 <= virtual()), (@ peri_type #[doc = + "GPIO44 peripheral singleton"] GPIO44 <= virtual()), (@ peri_type #[doc = + "GPIO45 peripheral singleton"] GPIO45 <= virtual()), (@ peri_type #[doc = + "GPIO46 peripheral singleton"] GPIO46 <= virtual()), (@ peri_type #[doc = + "GPIO47 peripheral singleton"] GPIO47 <= virtual()), (@ peri_type #[doc = + "GPIO48 peripheral singleton"] GPIO48 <= virtual()), (@ peri_type #[doc = + "GPIO49 peripheral singleton"] GPIO49 <= virtual()), (@ peri_type #[doc = + "GPIO50 peripheral singleton"] GPIO50 <= virtual()), (@ peri_type #[doc = + "GPIO51 peripheral singleton"] GPIO51 <= virtual()), (@ peri_type #[doc = + "GPIO52 peripheral singleton"] GPIO52 <= virtual()), (@ peri_type #[doc = + "GPIO53 peripheral singleton"] GPIO53 <= virtual()), (@ peri_type #[doc = + "GPIO54 peripheral singleton"] GPIO54 <= virtual()), (@ peri_type #[doc = + "EFUSE peripheral singleton"] EFUSE <= EFUSE() (unstable)), (@ peri_type #[doc = + "GPIO peripheral singleton"] GPIO <= GPIO() (unstable)), (@ peri_type #[doc = + "HP_SYS peripheral singleton"] HP_SYS <= HP_SYS() (unstable)), (@ peri_type #[doc + = "HP_SYS_CLKRST peripheral singleton"] HP_SYS_CLKRST <= HP_SYS_CLKRST() + (unstable)), (@ peri_type #[doc = "INTERRUPT_CORE0 peripheral singleton"] + INTERRUPT_CORE0 <= INTERRUPT_CORE0() (unstable)), (@ peri_type #[doc = + "INTERRUPT_CORE1 peripheral singleton"] INTERRUPT_CORE1 <= INTERRUPT_CORE1() + (unstable)), (@ peri_type #[doc = "CLIC peripheral singleton"] CLIC <= CLIC() + (unstable)), (@ peri_type #[doc = "IO_MUX peripheral singleton"] IO_MUX <= + IO_MUX() (unstable)), (@ peri_type #[doc = "LP_AON peripheral singleton"] LP_AON + <= LP_SYS() (unstable)), (@ peri_type #[doc = + "LP_AON_CLKRST peripheral singleton"] LP_AON_CLKRST <= LP_AON_CLKRST() + (unstable)), (@ peri_type #[doc = "LP_SYS peripheral singleton"] LP_SYS <= + LP_SYS() (unstable)), (@ peri_type #[doc = "LP_WDT peripheral singleton"] LP_WDT + <= LP_WDT() (unstable)), (@ peri_type #[doc = "LPWR peripheral singleton"] LPWR + <= LP_SYS() (unstable)), (@ peri_type #[doc = "PMU peripheral singleton"] PMU <= + PMU() (unstable)), (@ peri_type #[doc = "SYSTIMER peripheral singleton"] SYSTIMER + <= SYSTIMER() (unstable)), (@ peri_type #[doc = "TIMG0 peripheral singleton"] + TIMG0 <= TIMG0() (unstable)), (@ peri_type #[doc = "TIMG1 peripheral singleton"] + TIMG1 <= TIMG1() (unstable)), (@ peri_type #[doc = "UART0 peripheral singleton"] + UART0 <= UART0(UART0 : { bind_peri_interrupt, enable_peri_interrupt, + disable_peri_interrupt }) (unstable)), (@ peri_type #[doc = + "UART1 peripheral singleton"] UART1 <= UART1(UART1 : { bind_peri_interrupt, + enable_peri_interrupt, disable_peri_interrupt }) (unstable)), (@ peri_type #[doc + = "UART2 peripheral singleton"] UART2 <= UART2(UART2 : { bind_peri_interrupt, + enable_peri_interrupt, disable_peri_interrupt }) (unstable)), (@ peri_type #[doc + = "UART3 peripheral singleton"] UART3 <= UART3(UART3 : { bind_peri_interrupt, + enable_peri_interrupt, disable_peri_interrupt }) (unstable)), (@ peri_type #[doc + = "UART4 peripheral singleton"] UART4 <= UART4(UART4 : { bind_peri_interrupt, + enable_peri_interrupt, disable_peri_interrupt }) (unstable)), (@ peri_type #[doc + = "SPI2 peripheral singleton"] SPI2 <= SPI2(SPI2 : { bind_peri_interrupt, + enable_peri_interrupt, disable_peri_interrupt }) (unstable)), (@ peri_type #[doc + = "SPI3 peripheral singleton"] SPI3 <= SPI2(SPI3 : { bind_peri_interrupt, + enable_peri_interrupt, disable_peri_interrupt }) (unstable)), (@ peri_type #[doc + = "I2C0 peripheral singleton"] I2C0 <= I2C0(I2C0 : { bind_peri_interrupt, + enable_peri_interrupt, disable_peri_interrupt }) (unstable)), (@ peri_type #[doc + = "I2C1 peripheral singleton"] I2C1 <= I2C1(I2C1 : { bind_peri_interrupt, + enable_peri_interrupt, disable_peri_interrupt }) (unstable)), (@ peri_type #[doc + = "TWAI0 peripheral singleton"] TWAI0 <= TWAI0(TWAI0 : { bind_peri_interrupt, + enable_peri_interrupt, disable_peri_interrupt }) (unstable)), (@ peri_type #[doc + = "TWAI1 peripheral singleton"] TWAI1 <= TWAI1(TWAI1 : { bind_peri_interrupt, + enable_peri_interrupt, disable_peri_interrupt }) (unstable)), (@ peri_type #[doc + = "TWAI2 peripheral singleton"] TWAI2 <= TWAI2(TWAI2 : { bind_peri_interrupt, + enable_peri_interrupt, disable_peri_interrupt }) (unstable)), (@ peri_type #[doc + = "PSRAM peripheral singleton"] PSRAM <= virtual() (unstable)), (@ peri_type + #[doc = "DMA peripheral singleton"] DMA <= AHB_DMA() (unstable)), (@ peri_type + #[doc = "DMA_CH0 peripheral singleton"] DMA_CH0 <= virtual() (unstable)), (@ + peri_type #[doc = "DMA_CH1 peripheral singleton"] DMA_CH1 <= virtual() + (unstable)), (@ peri_type #[doc = "DMA_CH2 peripheral singleton"] DMA_CH2 <= + virtual() (unstable)), (@ peri_type #[doc = "USB_DEVICE peripheral singleton"] + USB_DEVICE <= USB_DEVICE(USB_DEVICE : { bind_peri_interrupt, + enable_peri_interrupt, disable_peri_interrupt }) (unstable)), (@ peri_type #[doc + = "SDHOST peripheral singleton"] SDHOST <= SDHOST() (unstable)), (@ peri_type + #[doc = "LEDC peripheral singleton"] LEDC <= LEDC(LEDC : { bind_peri_interrupt, + enable_peri_interrupt, disable_peri_interrupt }) (unstable)), (@ peri_type #[doc + = "MCPWM0 peripheral singleton"] MCPWM0 <= MCPWM0(PWM0 : { bind_peri_interrupt, + enable_peri_interrupt, disable_peri_interrupt }) (unstable)), (@ peri_type #[doc + = "MCPWM1 peripheral singleton"] MCPWM1 <= MCPWM1(PWM1 : { bind_peri_interrupt, + enable_peri_interrupt, disable_peri_interrupt }) (unstable)), (@ peri_type #[doc + = "PCNT peripheral singleton"] PCNT <= PCNT(PCNT : { bind_peri_interrupt, + enable_peri_interrupt, disable_peri_interrupt }) (unstable)), (@ peri_type #[doc + = "RMT peripheral singleton"] RMT <= RMT(RMT : { bind_peri_interrupt, + enable_peri_interrupt, disable_peri_interrupt }) (unstable)), (@ peri_type #[doc + = "ADC peripheral singleton"] ADC <= ADC() (unstable)), (@ peri_type #[doc = + "AES peripheral singleton"] AES <= AES(AES : { bind_peri_interrupt, + enable_peri_interrupt, disable_peri_interrupt }) (unstable)), (@ peri_type #[doc + = "SHA peripheral singleton"] SHA <= SHA(SHA : { bind_peri_interrupt, + enable_peri_interrupt, disable_peri_interrupt }) (unstable)), (@ peri_type #[doc + = "RSA peripheral singleton"] RSA <= RSA(RSA : { bind_peri_interrupt, + enable_peri_interrupt, disable_peri_interrupt }) (unstable)), (@ peri_type #[doc + = "ECC peripheral singleton"] ECC <= ECC(ECC : { bind_peri_interrupt, + enable_peri_interrupt, disable_peri_interrupt }) (unstable)))); + _for_each_inner_peripheral!((singletons(GPIO0), (GPIO1), (GPIO2), (GPIO3), + (GPIO4), (GPIO5), (GPIO6), (GPIO7), (GPIO8), (GPIO9), (GPIO10), (GPIO11), + (GPIO12), (GPIO13), (GPIO14), (GPIO15), (GPIO16), (GPIO17), (GPIO18), (GPIO19), + (GPIO20), (GPIO21), (GPIO22), (GPIO23), (GPIO24), (GPIO25), (GPIO26), (GPIO27), + (GPIO28), (GPIO29), (GPIO30), (GPIO31), (GPIO32), (GPIO33), (GPIO34), (GPIO35), + (GPIO36), (GPIO37), (GPIO38), (GPIO39), (GPIO40), (GPIO41), (GPIO42), (GPIO43), + (GPIO44), (GPIO45), (GPIO46), (GPIO47), (GPIO48), (GPIO49), (GPIO50), (GPIO51), + (GPIO52), (GPIO53), (GPIO54), (GPIO(unstable)), (HP_SYS(unstable)), + (HP_SYS_CLKRST(unstable)), (INTERRUPT_CORE0(unstable)), + (INTERRUPT_CORE1(unstable)), (CLIC(unstable)), (IO_MUX(unstable)), + (LP_AON(unstable)), (LP_AON_CLKRST(unstable)), (LP_SYS(unstable)), + (LP_WDT(unstable)), (LPWR(unstable)), (PMU(unstable)), (SYSTIMER(unstable)), + (TIMG0(unstable)), (TIMG1(unstable)), (UART0(unstable)), (UART1(unstable)), + (UART2(unstable)), (UART3(unstable)), (UART4(unstable)), (SPI2(unstable)), + (SPI3(unstable)), (I2C0(unstable)), (I2C1(unstable)), (TWAI0(unstable)), + (TWAI1(unstable)), (TWAI2(unstable)), (PSRAM(unstable)), (DMA(unstable)), + (DMA_CH0(unstable)), (DMA_CH1(unstable)), (DMA_CH2(unstable)), + (USB_DEVICE(unstable)), (SDHOST(unstable)), (LEDC(unstable)), (MCPWM0(unstable)), + (MCPWM1(unstable)), (PCNT(unstable)), (RMT(unstable)), (ADC(unstable)), + (AES(unstable)), (SHA(unstable)), (RSA(unstable)), (ECC(unstable)))); + _for_each_inner_peripheral!((dma_eligible(SPI2, Spi2, 1), (SPI3, Spi3, 2), (AES, + Aes, 4), (SHA, Sha, 5))); + }; +} +/// This macro can be used to generate code for each `GPIOn` instance. +/// +/// For an explanation on the general syntax, as well as usage of individual/repeated +/// matchers, refer to [the crate-level documentation][crate#for_each-macros]. +/// +/// This macro has one option for its "Individual matcher" case: +/// +/// Syntax: `($n:literal, $gpio:ident ($($digital_input_function:ident => +/// $digital_input_signal:ident)*) ($($digital_output_function:ident => +/// $digital_output_signal:ident)*) ($([$pin_attribute:ident])*))` +/// +/// Macro fragments: +/// +/// - `$n`: the number of the GPIO. For `GPIO0`, `$n` is 0. +/// - `$gpio`: the name of the GPIO. +/// - `$digital_input_function`: the number of the digital function, as an identifier (i.e. for +/// function 0 this is `_0`). +/// - `$digital_input_function`: the name of the digital function, as an identifier. +/// - `$digital_output_function`: the number of the digital function, as an identifier (i.e. for +/// function 0 this is `_0`). +/// - `$digital_output_function`: the name of the digital function, as an identifier. +/// - `$pin_attribute`: `Input` and/or `Output`, marks the possible directions of the GPIO. +/// Bracketed so that they can also be matched as optional fragments. Order is always Input first. +/// +/// Example data: `(0, GPIO0 (_5 => EMAC_TX_CLK) (_1 => CLK_OUT1 _5 => EMAC_TX_CLK) ([Input] +/// [Output]))` +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! for_each_gpio { + ($($pattern:tt => $code:tt;)*) => { + macro_rules! _for_each_inner_gpio { $(($pattern) => $code;)* ($other : tt) => {} + } _for_each_inner_gpio!((0, GPIO0() () ([Input] [Output]))); + _for_each_inner_gpio!((1, GPIO1() () ([Input] [Output]))); + _for_each_inner_gpio!((2, GPIO2(_0 => MTCK) (_0 => MTCK) ([Input] [Output]))); + _for_each_inner_gpio!((3, GPIO3(_0 => MTDI) (_0 => MTDI) ([Input] [Output]))); + _for_each_inner_gpio!((4, GPIO4(_0 => MTMS) (_0 => MTMS) ([Input] [Output]))); + _for_each_inner_gpio!((5, GPIO5(_0 => MTDO) (_0 => MTDO) ([Input] [Output]))); + _for_each_inner_gpio!((6, GPIO6(_3 => SPI2_HOLD) (_3 => SPI2_HOLD) ([Input] + [Output]))); _for_each_inner_gpio!((7, GPIO7(_3 => SPI2_CS) (_3 => SPI2_CS) + ([Input] [Output]))); _for_each_inner_gpio!((8, GPIO8(_3 => SPI2_D) (_2 => + UART0_RTS _3 => SPI2_D) ([Input] [Output]))); _for_each_inner_gpio!((9, GPIO9(_2 + => UART0_CTS _3 => SPI2_CK) (_3 => SPI2_CK) ([Input] [Output]))); + _for_each_inner_gpio!((10, GPIO10(_3 => SPI2_Q) (_2 => UART1_TXD _3 => SPI2_Q) + ([Input] [Output]))); _for_each_inner_gpio!((11, GPIO11(_2 => UART1_RXD _3 => + SPI2_WP) (_3 => SPI2_WP) ([Input] [Output]))); _for_each_inner_gpio!((12, + GPIO12() (_2 => UART1_RTS) ([Input] [Output]))); _for_each_inner_gpio!((13, + GPIO13(_2 => UART1_CTS) () ([Input] [Output]))); _for_each_inner_gpio!((14, + GPIO14() () ([Input] [Output]))); _for_each_inner_gpio!((15, GPIO15() () ([Input] + [Output]))); _for_each_inner_gpio!((16, GPIO16() () ([Input] [Output]))); + _for_each_inner_gpio!((17, GPIO17() () ([Input] [Output]))); + _for_each_inner_gpio!((18, GPIO18() () ([Input] [Output]))); + _for_each_inner_gpio!((19, GPIO19() () ([Input] [Output]))); + _for_each_inner_gpio!((20, GPIO20() () ([Input] [Output]))); + _for_each_inner_gpio!((21, GPIO21() () ([Input] [Output]))); + _for_each_inner_gpio!((22, GPIO22(_4 => DBG_PSRAM_CK) (_4 => DBG_PSRAM_CK) + ([Input] [Output]))); _for_each_inner_gpio!((23, GPIO23(_3 => REF_50M_CLK _4 => + DBG_PSRAM_CS) (_3 => REF_50M_CLK _4 => DBG_PSRAM_CS) ([Input] [Output]))); + _for_each_inner_gpio!((24, GPIO24() () ([Input] [Output]))); + _for_each_inner_gpio!((25, GPIO25() () ([Input] [Output]))); + _for_each_inner_gpio!((26, GPIO26() () ([Input] [Output]))); + _for_each_inner_gpio!((27, GPIO27() () ([Input] [Output]))); + _for_each_inner_gpio!((28, GPIO28(_2 => SPI2_CS _3 => EMAC_PHY_RXDV _4 => + DBG_PSRAM_D) (_2 => SPI2_CS _4 => DBG_PSRAM_D) ([Input] [Output]))); + _for_each_inner_gpio!((29, GPIO29(_2 => SPI2_D _3 => EMAC_PHY_RXD0 _4 => + DBG_PSRAM_Q) (_2 => SPI2_D _4 => DBG_PSRAM_Q) ([Input] [Output]))); + _for_each_inner_gpio!((30, GPIO30(_2 => SPI2_CK _3 => EMAC_PHY_RXD1 _4 => + DBG_PSRAM_WP) (_2 => SPI2_CK _4 => DBG_PSRAM_WP) ([Input] [Output]))); + _for_each_inner_gpio!((31, GPIO31(_2 => SPI2_Q _3 => EMAC_PHY_RXER _4 => + DBG_PSRAM_HOLD) (_2 => SPI2_Q _4 => DBG_PSRAM_HOLD) ([Input] [Output]))); + _for_each_inner_gpio!((32, GPIO32(_2 => SPI2_HOLD _3 => EMAC_RMII_CLK _4 => + DBG_PSRAM_DQ4) (_2 => SPI2_HOLD _3 => EMAC_RMII_CLK _4 => DBG_PSRAM_DQ4) ([Input] + [Output]))); _for_each_inner_gpio!((33, GPIO33(_2 => SPI2_WP _4 => DBG_PSRAM_DQ5) + (_2 => SPI2_WP _3 => EMAC_PHY_TXEN _4 => DBG_PSRAM_DQ5) ([Input] [Output]))); + _for_each_inner_gpio!((34, GPIO34(_2 => SPI2_IO4 _4 => DBG_PSRAM_DQ6) (_2 => + SPI2_IO4 _3 => EMAC_PHY_TXD0 _4 => DBG_PSRAM_DQ6) ([Input] [Output]))); + _for_each_inner_gpio!((35, GPIO35(_2 => SPI2_IO5 _4 => DBG_PSRAM_DQ7) (_2 => + SPI2_IO5 _3 => EMAC_PHY_TXD1 _4 => DBG_PSRAM_DQ7) ([Input] [Output]))); + _for_each_inner_gpio!((36, GPIO36(_2 => SPI2_IO6 _4 => DBG_PSRAM_DQS_0) (_2 => + SPI2_IO6 _3 => EMAC_PHY_TXER _4 => DBG_PSRAM_DQS_0) ([Input] [Output]))); + _for_each_inner_gpio!((37, GPIO37(_2 => SPI2_IO7) (_0 => UART0_TXD _2 => + SPI2_IO7) ([Input] [Output]))); _for_each_inner_gpio!((38, GPIO38(_0 => UART0_RXD + _2 => SPI2_DQS) (_2 => SPI2_DQS) ([Input] [Output]))); _for_each_inner_gpio!((39, + GPIO39(_0 => SD1_CDATA0 _2 => BIST _3 => REF_50M_CLK _4 => DBG_PSRAM_DQ8) (_0 => + SD1_CDATA0 _2 => BIST _3 => REF_50M_CLK _4 => DBG_PSRAM_DQ8) ([Input] + [Output]))); _for_each_inner_gpio!((40, GPIO40(_0 => SD1_CDATA1 _2 => BIST _4 => + DBG_PSRAM_DQ9) (_0 => SD1_CDATA1 _2 => BIST _3 => EMAC_PHY_TXEN _4 => + DBG_PSRAM_DQ9) ([Input] [Output]))); _for_each_inner_gpio!((41, GPIO41(_0 => + SD1_CDATA2 _2 => BIST _4 => DBG_PSRAM_DQ10) (_0 => SD1_CDATA2 _2 => BIST _3 => + EMAC_PHY_TXD0 _4 => DBG_PSRAM_DQ10) ([Input] [Output]))); + _for_each_inner_gpio!((42, GPIO42(_0 => SD1_CDATA3 _2 => BIST _4 => + DBG_PSRAM_DQ11) (_0 => SD1_CDATA3 _2 => BIST _3 => EMAC_PHY_TXD1 _4 => + DBG_PSRAM_DQ11) ([Input] [Output]))); _for_each_inner_gpio!((43, GPIO43(_0 => + SD1_CCLK _2 => BIST _4 => DBG_PSRAM_DQ12) (_0 => SD1_CCLK _2 => BIST _3 => + EMAC_PHY_TXER _4 => DBG_PSRAM_DQ12) ([Input] [Output]))); + _for_each_inner_gpio!((44, GPIO44(_0 => SD1_CCMD _2 => BIST _3 => EMAC_RMII_CLK + _4 => DBG_PSRAM_DQ13) (_0 => SD1_CCMD _2 => BIST _3 => EMAC_RMII_CLK _4 => + DBG_PSRAM_DQ13) ([Input] [Output]))); _for_each_inner_gpio!((45, GPIO45(_0 => + SD1_CDATA4 _2 => BIST _3 => EMAC_PHY_RXDV _4 => DBG_PSRAM_DQ14) (_0 => SD1_CDATA4 + _2 => BIST _4 => DBG_PSRAM_DQ14) ([Input] [Output]))); _for_each_inner_gpio!((46, + GPIO46(_0 => SD1_CDATA5 _2 => BIST _3 => EMAC_PHY_RXD0 _4 => DBG_PSRAM_DQ15) (_0 + => SD1_CDATA5 _2 => BIST _4 => DBG_PSRAM_DQ15) ([Input] [Output]))); + _for_each_inner_gpio!((47, GPIO47(_0 => SD1_CDATA6 _2 => BIST _3 => EMAC_PHY_RXD1 + _4 => DBG_PSRAM_DQS_1) (_0 => SD1_CDATA6 _2 => BIST _4 => DBG_PSRAM_DQS_1) + ([Input] [Output]))); _for_each_inner_gpio!((48, GPIO48(_0 => SD1_CDATA7 _2 => + BIST _3 => EMAC_PHY_RXER) (_0 => SD1_CDATA7 _2 => BIST) ([Input] [Output]))); + _for_each_inner_gpio!((49, GPIO49(_4 => DBG_FLASH_CS) (_3 => EMAC_PHY_TXEN _4 => + DBG_FLASH_CS) ([Input] [Output]))); _for_each_inner_gpio!((50, GPIO50(_3 => + EMAC_RMII_CLK _4 => DBG_FLASH_Q) (_3 => EMAC_RMII_CLK _4 => DBG_FLASH_Q) ([Input] + [Output]))); _for_each_inner_gpio!((51, GPIO51(_3 => EMAC_PHY_RXDV _4 => + DBG_FLASH_WP) (_4 => DBG_FLASH_WP) ([Input] [Output]))); + _for_each_inner_gpio!((52, GPIO52(_3 => EMAC_PHY_RXD0 _4 => DBG_FLASH_HOLD) (_4 + => DBG_FLASH_HOLD) ([Input] [Output]))); _for_each_inner_gpio!((53, GPIO53(_3 => + EMAC_PHY_RXD1 _4 => DBG_FLASH_CK) (_4 => DBG_FLASH_CK) ([Input] [Output]))); + _for_each_inner_gpio!((54, GPIO54(_3 => EMAC_PHY_RXER _4 => DBG_FLASH_D) (_4 => + DBG_FLASH_D) ([Input] [Output]))); _for_each_inner_gpio!((all(0, GPIO0() () + ([Input] [Output])), (1, GPIO1() () ([Input] [Output])), (2, GPIO2(_0 => MTCK) + (_0 => MTCK) ([Input] [Output])), (3, GPIO3(_0 => MTDI) (_0 => MTDI) ([Input] + [Output])), (4, GPIO4(_0 => MTMS) (_0 => MTMS) ([Input] [Output])), (5, GPIO5(_0 + => MTDO) (_0 => MTDO) ([Input] [Output])), (6, GPIO6(_3 => SPI2_HOLD) (_3 => + SPI2_HOLD) ([Input] [Output])), (7, GPIO7(_3 => SPI2_CS) (_3 => SPI2_CS) ([Input] + [Output])), (8, GPIO8(_3 => SPI2_D) (_2 => UART0_RTS _3 => SPI2_D) ([Input] + [Output])), (9, GPIO9(_2 => UART0_CTS _3 => SPI2_CK) (_3 => SPI2_CK) ([Input] + [Output])), (10, GPIO10(_3 => SPI2_Q) (_2 => UART1_TXD _3 => SPI2_Q) ([Input] + [Output])), (11, GPIO11(_2 => UART1_RXD _3 => SPI2_WP) (_3 => SPI2_WP) ([Input] + [Output])), (12, GPIO12() (_2 => UART1_RTS) ([Input] [Output])), (13, GPIO13(_2 + => UART1_CTS) () ([Input] [Output])), (14, GPIO14() () ([Input] [Output])), (15, + GPIO15() () ([Input] [Output])), (16, GPIO16() () ([Input] [Output])), (17, + GPIO17() () ([Input] [Output])), (18, GPIO18() () ([Input] [Output])), (19, + GPIO19() () ([Input] [Output])), (20, GPIO20() () ([Input] [Output])), (21, + GPIO21() () ([Input] [Output])), (22, GPIO22(_4 => DBG_PSRAM_CK) (_4 => + DBG_PSRAM_CK) ([Input] [Output])), (23, GPIO23(_3 => REF_50M_CLK _4 => + DBG_PSRAM_CS) (_3 => REF_50M_CLK _4 => DBG_PSRAM_CS) ([Input] [Output])), (24, + GPIO24() () ([Input] [Output])), (25, GPIO25() () ([Input] [Output])), (26, + GPIO26() () ([Input] [Output])), (27, GPIO27() () ([Input] [Output])), (28, + GPIO28(_2 => SPI2_CS _3 => EMAC_PHY_RXDV _4 => DBG_PSRAM_D) (_2 => SPI2_CS _4 => + DBG_PSRAM_D) ([Input] [Output])), (29, GPIO29(_2 => SPI2_D _3 => EMAC_PHY_RXD0 _4 + => DBG_PSRAM_Q) (_2 => SPI2_D _4 => DBG_PSRAM_Q) ([Input] [Output])), (30, + GPIO30(_2 => SPI2_CK _3 => EMAC_PHY_RXD1 _4 => DBG_PSRAM_WP) (_2 => SPI2_CK _4 => + DBG_PSRAM_WP) ([Input] [Output])), (31, GPIO31(_2 => SPI2_Q _3 => EMAC_PHY_RXER + _4 => DBG_PSRAM_HOLD) (_2 => SPI2_Q _4 => DBG_PSRAM_HOLD) ([Input] [Output])), + (32, GPIO32(_2 => SPI2_HOLD _3 => EMAC_RMII_CLK _4 => DBG_PSRAM_DQ4) (_2 => + SPI2_HOLD _3 => EMAC_RMII_CLK _4 => DBG_PSRAM_DQ4) ([Input] [Output])), (33, + GPIO33(_2 => SPI2_WP _4 => DBG_PSRAM_DQ5) (_2 => SPI2_WP _3 => EMAC_PHY_TXEN _4 + => DBG_PSRAM_DQ5) ([Input] [Output])), (34, GPIO34(_2 => SPI2_IO4 _4 => + DBG_PSRAM_DQ6) (_2 => SPI2_IO4 _3 => EMAC_PHY_TXD0 _4 => DBG_PSRAM_DQ6) ([Input] + [Output])), (35, GPIO35(_2 => SPI2_IO5 _4 => DBG_PSRAM_DQ7) (_2 => SPI2_IO5 _3 => + EMAC_PHY_TXD1 _4 => DBG_PSRAM_DQ7) ([Input] [Output])), (36, GPIO36(_2 => + SPI2_IO6 _4 => DBG_PSRAM_DQS_0) (_2 => SPI2_IO6 _3 => EMAC_PHY_TXER _4 => + DBG_PSRAM_DQS_0) ([Input] [Output])), (37, GPIO37(_2 => SPI2_IO7) (_0 => + UART0_TXD _2 => SPI2_IO7) ([Input] [Output])), (38, GPIO38(_0 => UART0_RXD _2 => + SPI2_DQS) (_2 => SPI2_DQS) ([Input] [Output])), (39, GPIO39(_0 => SD1_CDATA0 _2 + => BIST _3 => REF_50M_CLK _4 => DBG_PSRAM_DQ8) (_0 => SD1_CDATA0 _2 => BIST _3 => + REF_50M_CLK _4 => DBG_PSRAM_DQ8) ([Input] [Output])), (40, GPIO40(_0 => + SD1_CDATA1 _2 => BIST _4 => DBG_PSRAM_DQ9) (_0 => SD1_CDATA1 _2 => BIST _3 => + EMAC_PHY_TXEN _4 => DBG_PSRAM_DQ9) ([Input] [Output])), (41, GPIO41(_0 => + SD1_CDATA2 _2 => BIST _4 => DBG_PSRAM_DQ10) (_0 => SD1_CDATA2 _2 => BIST _3 => + EMAC_PHY_TXD0 _4 => DBG_PSRAM_DQ10) ([Input] [Output])), (42, GPIO42(_0 => + SD1_CDATA3 _2 => BIST _4 => DBG_PSRAM_DQ11) (_0 => SD1_CDATA3 _2 => BIST _3 => + EMAC_PHY_TXD1 _4 => DBG_PSRAM_DQ11) ([Input] [Output])), (43, GPIO43(_0 => + SD1_CCLK _2 => BIST _4 => DBG_PSRAM_DQ12) (_0 => SD1_CCLK _2 => BIST _3 => + EMAC_PHY_TXER _4 => DBG_PSRAM_DQ12) ([Input] [Output])), (44, GPIO44(_0 => + SD1_CCMD _2 => BIST _3 => EMAC_RMII_CLK _4 => DBG_PSRAM_DQ13) (_0 => SD1_CCMD _2 + => BIST _3 => EMAC_RMII_CLK _4 => DBG_PSRAM_DQ13) ([Input] [Output])), (45, + GPIO45(_0 => SD1_CDATA4 _2 => BIST _3 => EMAC_PHY_RXDV _4 => DBG_PSRAM_DQ14) (_0 + => SD1_CDATA4 _2 => BIST _4 => DBG_PSRAM_DQ14) ([Input] [Output])), (46, + GPIO46(_0 => SD1_CDATA5 _2 => BIST _3 => EMAC_PHY_RXD0 _4 => DBG_PSRAM_DQ15) (_0 + => SD1_CDATA5 _2 => BIST _4 => DBG_PSRAM_DQ15) ([Input] [Output])), (47, + GPIO47(_0 => SD1_CDATA6 _2 => BIST _3 => EMAC_PHY_RXD1 _4 => DBG_PSRAM_DQS_1) (_0 + => SD1_CDATA6 _2 => BIST _4 => DBG_PSRAM_DQS_1) ([Input] [Output])), (48, + GPIO48(_0 => SD1_CDATA7 _2 => BIST _3 => EMAC_PHY_RXER) (_0 => SD1_CDATA7 _2 => + BIST) ([Input] [Output])), (49, GPIO49(_4 => DBG_FLASH_CS) (_3 => EMAC_PHY_TXEN + _4 => DBG_FLASH_CS) ([Input] [Output])), (50, GPIO50(_3 => EMAC_RMII_CLK _4 => + DBG_FLASH_Q) (_3 => EMAC_RMII_CLK _4 => DBG_FLASH_Q) ([Input] [Output])), (51, + GPIO51(_3 => EMAC_PHY_RXDV _4 => DBG_FLASH_WP) (_4 => DBG_FLASH_WP) ([Input] + [Output])), (52, GPIO52(_3 => EMAC_PHY_RXD0 _4 => DBG_FLASH_HOLD) (_4 => + DBG_FLASH_HOLD) ([Input] [Output])), (53, GPIO53(_3 => EMAC_PHY_RXD1 _4 => + DBG_FLASH_CK) (_4 => DBG_FLASH_CK) ([Input] [Output])), (54, GPIO54(_3 => + EMAC_PHY_RXER _4 => DBG_FLASH_D) (_4 => DBG_FLASH_D) ([Input] [Output])))); + }; +} +/// This macro can be used to generate code for each analog function of each GPIO. +/// +/// For an explanation on the general syntax, as well as usage of individual/repeated +/// matchers, refer to [the crate-level documentation][crate#for_each-macros]. +/// +/// This macro has two options for its "Individual matcher" case: +/// +/// - `all`: `($signal:ident, $gpio:ident)` - simple case where you only need identifiers +/// - `all_expanded`: `(($signal:ident, $group:ident $(, $number:literal)+), $gpio:ident)` - +/// expanded signal case, where you need the number(s) of a signal, or the general group to which +/// the signal belongs. For example, in case of `ADC2_CH3` the expanded form looks like +/// `(ADC2_CH3, ADCn_CHm, 2, 3)`. +/// +/// Macro fragments: +/// +/// - `$signal`: the name of the signal. +/// - `$group`: the name of the signal, with numbers replaced by placeholders. For `ADC2_CH3` this +/// is `ADCn_CHm`. +/// - `$number`: the numbers extracted from `$signal`. +/// - `$gpio`: the name of the GPIO. +/// +/// Example data: +/// - `(ADC2_CH5, GPIO12)` +/// - `((ADC2_CH5, ADCn_CHm, 2, 5), GPIO12)` +/// +/// The expanded syntax is only available when the signal has at least one numbered component. +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! for_each_analog_function { + ($($pattern:tt => $code:tt;)*) => { + macro_rules! _for_each_inner_analog_function { $(($pattern) => $code;)* ($other : + tt) => {} } _for_each_inner_analog_function!((ADC1_CH0, GPIO16)); + _for_each_inner_analog_function!((ADC1_CH1, GPIO17)); + _for_each_inner_analog_function!((ADC1_CH2, GPIO18)); + _for_each_inner_analog_function!((ADC1_CH3, GPIO19)); + _for_each_inner_analog_function!((ADC1_CH4, GPIO20)); + _for_each_inner_analog_function!((ADC1_CH5, GPIO21)); + _for_each_inner_analog_function!((ADC1_CH6, GPIO22)); + _for_each_inner_analog_function!((ADC1_CH7, GPIO23)); + _for_each_inner_analog_function!((USB_DM, GPIO24)); + _for_each_inner_analog_function!((USB_DP, GPIO25)); + _for_each_inner_analog_function!((USB_PHY1_DM, GPIO26)); + _for_each_inner_analog_function!((USB_PHY1_DP, GPIO27)); + _for_each_inner_analog_function!((ADC2_CH0, GPIO49)); + _for_each_inner_analog_function!((ADC2_CH1, GPIO50)); + _for_each_inner_analog_function!((ADC2_CH2, GPIO51)); + _for_each_inner_analog_function!((ADC2_CH3, GPIO52)); + _for_each_inner_analog_function!((ADC2_CH4, GPIO53)); + _for_each_inner_analog_function!((ADC2_CH5, GPIO54)); + _for_each_inner_analog_function!(((ADC1_CH0, ADCn_CHm, 1, 0), GPIO16)); + _for_each_inner_analog_function!(((ADC1_CH1, ADCn_CHm, 1, 1), GPIO17)); + _for_each_inner_analog_function!(((ADC1_CH2, ADCn_CHm, 1, 2), GPIO18)); + _for_each_inner_analog_function!(((ADC1_CH3, ADCn_CHm, 1, 3), GPIO19)); + _for_each_inner_analog_function!(((ADC1_CH4, ADCn_CHm, 1, 4), GPIO20)); + _for_each_inner_analog_function!(((ADC1_CH5, ADCn_CHm, 1, 5), GPIO21)); + _for_each_inner_analog_function!(((ADC1_CH6, ADCn_CHm, 1, 6), GPIO22)); + _for_each_inner_analog_function!(((ADC1_CH7, ADCn_CHm, 1, 7), GPIO23)); + _for_each_inner_analog_function!(((USB_PHY1_DM, USB_PHYn_DM, 1), GPIO26)); + _for_each_inner_analog_function!(((USB_PHY1_DP, USB_PHYn_DP, 1), GPIO27)); + _for_each_inner_analog_function!(((ADC2_CH0, ADCn_CHm, 2, 0), GPIO49)); + _for_each_inner_analog_function!(((ADC2_CH1, ADCn_CHm, 2, 1), GPIO50)); + _for_each_inner_analog_function!(((ADC2_CH2, ADCn_CHm, 2, 2), GPIO51)); + _for_each_inner_analog_function!(((ADC2_CH3, ADCn_CHm, 2, 3), GPIO52)); + _for_each_inner_analog_function!(((ADC2_CH4, ADCn_CHm, 2, 4), GPIO53)); + _for_each_inner_analog_function!(((ADC2_CH5, ADCn_CHm, 2, 5), GPIO54)); + _for_each_inner_analog_function!((all(ADC1_CH0, GPIO16), (ADC1_CH1, GPIO17), + (ADC1_CH2, GPIO18), (ADC1_CH3, GPIO19), (ADC1_CH4, GPIO20), (ADC1_CH5, GPIO21), + (ADC1_CH6, GPIO22), (ADC1_CH7, GPIO23), (USB_DM, GPIO24), (USB_DP, GPIO25), + (USB_PHY1_DM, GPIO26), (USB_PHY1_DP, GPIO27), (ADC2_CH0, GPIO49), (ADC2_CH1, + GPIO50), (ADC2_CH2, GPIO51), (ADC2_CH3, GPIO52), (ADC2_CH4, GPIO53), (ADC2_CH5, + GPIO54))); _for_each_inner_analog_function!((all_expanded((ADC1_CH0, ADCn_CHm, 1, + 0), GPIO16), ((ADC1_CH1, ADCn_CHm, 1, 1), GPIO17), ((ADC1_CH2, ADCn_CHm, 1, 2), + GPIO18), ((ADC1_CH3, ADCn_CHm, 1, 3), GPIO19), ((ADC1_CH4, ADCn_CHm, 1, 4), + GPIO20), ((ADC1_CH5, ADCn_CHm, 1, 5), GPIO21), ((ADC1_CH6, ADCn_CHm, 1, 6), + GPIO22), ((ADC1_CH7, ADCn_CHm, 1, 7), GPIO23), ((USB_PHY1_DM, USB_PHYn_DM, 1), + GPIO26), ((USB_PHY1_DP, USB_PHYn_DP, 1), GPIO27), ((ADC2_CH0, ADCn_CHm, 2, 0), + GPIO49), ((ADC2_CH1, ADCn_CHm, 2, 1), GPIO50), ((ADC2_CH2, ADCn_CHm, 2, 2), + GPIO51), ((ADC2_CH3, ADCn_CHm, 2, 3), GPIO52), ((ADC2_CH4, ADCn_CHm, 2, 4), + GPIO53), ((ADC2_CH5, ADCn_CHm, 2, 5), GPIO54))); + }; +} +/// This macro can be used to generate code for each LP/RTC function of each GPIO. +/// +/// For an explanation on the general syntax, as well as usage of individual/repeated +/// matchers, refer to [the crate-level documentation][crate#for_each-macros]. +/// +/// This macro has two options for its "Individual matcher" case: +/// +/// - `all`: `($signal:ident, $gpio:ident)` - simple case where you only need identifiers +/// - `all_expanded`: `(($signal:ident, $group:ident $(, $number:literal)+), $gpio:ident)` - +/// expanded signal case, where you need the number(s) of a signal, or the general group to which +/// the signal belongs. For example, in case of `SAR_I2C_SCL_1` the expanded form looks like +/// `(SAR_I2C_SCL_1, SAR_I2C_SCL_n, 1)`. +/// +/// Macro fragments: +/// +/// - `$signal`: the name of the signal. +/// - `$group`: the name of the signal, with numbers replaced by placeholders. For `ADC2_CH3` this +/// is `ADCn_CHm`. +/// - `$number`: the numbers extracted from `$signal`. +/// - `$gpio`: the name of the GPIO. +/// +/// Example data: +/// - `(RTC_GPIO15, GPIO12)` +/// - `((RTC_GPIO15, RTC_GPIOn, 15), GPIO12)` +/// +/// The expanded syntax is only available when the signal has at least one numbered component. +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! for_each_lp_function { + ($($pattern:tt => $code:tt;)*) => { + macro_rules! _for_each_inner_lp_function { $(($pattern) => $code;)* ($other : tt) + => {} } _for_each_inner_lp_function!((LP_GPIO0, GPIO0)); + _for_each_inner_lp_function!((LP_GPIO1, GPIO1)); + _for_each_inner_lp_function!((LP_GPIO14, GPIO14)); + _for_each_inner_lp_function!((LP_GPIO15, GPIO15)); + _for_each_inner_lp_function!(((LP_GPIO0, LP_GPIOn, 0), GPIO0)); + _for_each_inner_lp_function!(((LP_GPIO1, LP_GPIOn, 1), GPIO1)); + _for_each_inner_lp_function!(((LP_GPIO14, LP_GPIOn, 14), GPIO14)); + _for_each_inner_lp_function!(((LP_GPIO15, LP_GPIOn, 15), GPIO15)); + _for_each_inner_lp_function!((all(LP_GPIO0, GPIO0), (LP_GPIO1, GPIO1), + (LP_GPIO14, GPIO14), (LP_GPIO15, GPIO15))); + _for_each_inner_lp_function!((all_expanded((LP_GPIO0, LP_GPIOn, 0), GPIO0), + ((LP_GPIO1, LP_GPIOn, 1), GPIO1), ((LP_GPIO14, LP_GPIOn, 14), GPIO14), + ((LP_GPIO15, LP_GPIOn, 15), GPIO15))); + }; +} +/// Defines the `InputSignal` and `OutputSignal` enums. +/// +/// This macro is intended to be called in esp-hal only. +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! define_io_mux_signals { + () => { + #[allow(non_camel_case_types, clippy::upper_case_acronyms)] + #[derive(Debug, PartialEq, Copy, Clone)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] + #[doc(hidden)] + pub enum InputSignal { + SD_CARD_CCMD_2 = 1, + SD_CARD_CDATA0_2 = 2, + SD_CARD_CDATA1_2 = 3, + SD_CARD_CDATA2_2 = 4, + SD_CARD_CDATA3_2 = 5, + SD_CARD_CDATA4_2 = 6, + SD_CARD_CDATA5_2 = 7, + SD_CARD_CDATA6_2 = 8, + SD_CARD_CDATA7_2 = 9, + UART0_RXD = 10, + UART0_CTS = 11, + UART0_DSR = 12, + UART1_RXD = 13, + UART1_CTS = 14, + UART1_DSR = 15, + UART2_RXD = 16, + UART2_CTS = 17, + UART2_DSR = 18, + UART3_RXD = 19, + UART3_CTS = 20, + UART3_DSR = 21, + UART4_RXD = 22, + UART4_CTS = 23, + UART4_DSR = 24, + I2S0_O_BCK = 25, + I2S0_MCLK = 26, + I2S0_O_WS = 27, + I2S0_I_SD = 28, + I2S0_I_BCK = 29, + I2S0_I_WS = 30, + I2S1_O_BCK = 31, + I2S1_MCLK = 32, + I2S1_O_WS = 33, + I2S1_I_SD = 34, + I2S1_I_BCK = 35, + I2S1_I_WS = 36, + I2S2_O_BCK = 37, + I2S2_MCLK = 38, + I2S2_O_WS = 39, + I2S2_I_SD = 40, + I2S2_I_BCK = 41, + I2S2_I_WS = 42, + I2S0_I_SD1 = 43, + I2S0_I_SD2 = 44, + I2S0_I_SD3 = 45, + SPI3_CK = 47, + SPI3_Q = 48, + SPI3_D = 49, + SPI3_HOLD = 50, + SPI3_WP = 51, + SPI3_CS = 52, + SPI2_CK = 53, + SPI2_Q = 54, + SPI2_D = 55, + SPI2_HOLD = 56, + SPI2_WP = 57, + SPI2_IO4 = 58, + SPI2_IO5 = 59, + SPI2_IO6 = 60, + SPI2_IO7 = 61, + SPI2_CS = 62, + I2C0_SCL = 68, + I2C0_SDA = 69, + I2C1_SCL = 70, + I2C1_SDA = 71, + UART0_SLP_CLK = 74, + UART1_SLP_CLK = 75, + UART2_SLP_CLK = 76, + UART3_SLP_CLK = 77, + UART4_SLP_CLK = 78, + TWAI0_RX = 80, + TWAI1_RX = 83, + TWAI2_RX = 86, + PWM0_SYNC0 = 89, + PWM0_SYNC1 = 90, + PWM0_SYNC2 = 91, + PWM0_F0 = 92, + PWM0_F1 = 93, + PWM0_F2 = 94, + PWM0_CAP0 = 95, + PWM0_CAP1 = 96, + PWM0_CAP2 = 97, + PWM1_SYNC0 = 98, + PWM1_SYNC1 = 99, + PWM1_SYNC2 = 100, + PWM1_F0 = 101, + PWM1_F1 = 102, + PWM1_F2 = 103, + PWM1_CAP0 = 104, + PWM1_CAP1 = 105, + PWM1_CAP2 = 106, + MII_MDI = 107, + EMAC_PHY_COL = 108, + EMAC_PHY_CRS = 109, + USB_OTG11_IDDIG = 110, + USB_OTG11_AVALID = 111, + USB_SRP_BVALID = 112, + USB_OTG11_VBUSVALID = 113, + USB_SRP_SESSEND = 114, + ULPI_CLK = 117, + USB_HSPHY_REFCLK = 118, + SD_CARD_DETECT_N_1 = 126, + SD_CARD_DETECT_N_2 = 127, + SD_CARD_INT_N_1 = 128, + SD_CARD_INT_N_2 = 129, + SD_CARD_WRITE_PRT_1 = 130, + SD_CARD_WRITE_PRT_2 = 131, + SD_DATA_STROBE_1 = 132, + SD_DATA_STROBE_2 = 133, + I3C_MST_SCL = 134, + I3C_MST_SDA = 135, + I3C_SLV_SCL = 136, + I3C_SLV_SDA = 137, + USB_JTAG_TDO_BRIDGE = 140, + CAM_PCLK = 158, + CAM_H_ENABLE = 159, + CAM_H_SYNC = 160, + CAM_V_SYNC = 161, + EMAC_PHY_RXDV = 178, + EMAC_PHY_RXD0 = 179, + EMAC_PHY_RXD1 = 180, + EMAC_PHY_RXD2 = 181, + EMAC_PHY_RXD3 = 182, + EMAC_PHY_RXER = 183, + EMAC_RX_CLK = 184, + EMAC_TX_CLK = 185, + PARLIO_RX_CLK = 186, + PARLIO_TX_CLK = 187, + PARLIO_RX_DATA0 = 188, + PARLIO_RX_DATA1 = 189, + PARLIO_RX_DATA2 = 190, + PARLIO_RX_DATA3 = 191, + PARLIO_RX_DATA4 = 192, + PARLIO_RX_DATA5 = 193, + PARLIO_RX_DATA6 = 194, + PARLIO_RX_DATA7 = 195, + PARLIO_RX_DATA8 = 196, + PARLIO_RX_DATA9 = 197, + PARLIO_RX_DATA10 = 198, + PARLIO_RX_DATA11 = 199, + PARLIO_RX_DATA12 = 200, + PARLIO_RX_DATA13 = 201, + PARLIO_RX_DATA14 = 202, + PARLIO_RX_DATA15 = 203, + MTCK, + MTDI, + MTMS, + MTDO, + SD1_CDATA0, + SD1_CDATA1, + SD1_CDATA2, + SD1_CDATA3, + SD1_CCLK, + SD1_CCMD, + SD1_CDATA4, + SD1_CDATA5, + SD1_CDATA6, + SD1_CDATA7, + EMAC_RMII_CLK, + REF_50M_CLK, + BIST, + DBG_PSRAM_CK, + DBG_PSRAM_CS, + DBG_PSRAM_D, + DBG_PSRAM_Q, + DBG_PSRAM_WP, + DBG_PSRAM_HOLD, + DBG_PSRAM_DQ4, + DBG_PSRAM_DQ5, + DBG_PSRAM_DQ6, + DBG_PSRAM_DQ7, + DBG_PSRAM_DQS_0, + DBG_PSRAM_DQ8, + DBG_PSRAM_DQ9, + DBG_PSRAM_DQ10, + DBG_PSRAM_DQ11, + DBG_PSRAM_DQ12, + DBG_PSRAM_DQ13, + DBG_PSRAM_DQ14, + DBG_PSRAM_DQ15, + DBG_PSRAM_DQS_1, + DBG_FLASH_CS, + DBG_FLASH_Q, + DBG_FLASH_WP, + DBG_FLASH_HOLD, + DBG_FLASH_CK, + DBG_FLASH_D, + SPI2_DQS, + } + #[allow(non_camel_case_types, clippy::upper_case_acronyms)] + #[derive(Debug, PartialEq, Copy, Clone)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] + #[doc(hidden)] + pub enum OutputSignal { + SD_CARD_CCLK_2 = 0, + SD_CARD_CCMD_2 = 1, + SD_CARD_CDATA0_2 = 2, + SD_CARD_CDATA1_2 = 3, + SD_CARD_CDATA2_2 = 4, + SD_CARD_CDATA3_2 = 5, + SD_CARD_CDATA4_2 = 6, + SD_CARD_CDATA5_2 = 7, + SD_CARD_CDATA6_2 = 8, + SD_CARD_CDATA7_2 = 9, + UART0_TXD = 10, + UART0_RTS = 11, + UART0_DTR = 12, + UART1_TXD = 13, + UART1_RTS = 14, + UART1_DTR = 15, + UART2_TXD = 16, + UART2_RTS = 17, + UART2_DTR = 18, + UART3_TXD = 19, + UART3_RTS = 20, + UART3_DTR = 21, + UART4_TXD = 22, + UART4_RTS = 23, + UART4_DTR = 24, + I2S0_O_BCK = 25, + I2S0_MCLK = 26, + I2S0_O_WS = 27, + I2S0_O_SD = 28, + I2S0_I_BCK = 29, + I2S0_I_WS = 30, + I2S1_O_BCK = 31, + I2S1_MCLK = 32, + I2S1_O_WS = 33, + I2S1_O_SD = 34, + I2S1_I_BCK = 35, + I2S1_I_WS = 36, + I2S2_O_BCK = 37, + I2S2_MCLK = 38, + I2S2_O_WS = 39, + I2S2_O_SD = 40, + I2S2_I_BCK = 41, + I2S2_I_WS = 42, + I2S0_O_SD1 = 43, + SPI2_DQS = 44, + SPI3_CS2 = 45, + SPI3_CS1 = 46, + SPI3_CK = 47, + SPI3_Q = 48, + SPI3_D = 49, + SPI3_HOLD = 50, + SPI3_WP = 51, + SPI3_CS = 52, + SPI2_CK = 53, + SPI2_Q = 54, + SPI2_D = 55, + SPI2_HOLD = 56, + SPI2_WP = 57, + SPI2_IO4 = 58, + SPI2_IO5 = 59, + SPI2_IO6 = 60, + SPI2_IO7 = 61, + SPI2_CS = 62, + SPI2_CS1 = 63, + SPI2_CS2 = 64, + SPI2_CS3 = 65, + SPI2_CS4 = 66, + SPI2_CS5 = 67, + I2C0_SCL = 68, + I2C0_SDA = 69, + I2C1_SCL = 70, + I2C1_SDA = 71, + GPIO_SD0 = 72, + GPIO_SD1 = 73, + GPIO_SD2 = 74, + GPIO_SD3 = 75, + GPIO_SD4 = 76, + GPIO_SD5 = 77, + GPIO_SD6 = 78, + GPIO_SD7 = 79, + TWAI0_TX = 80, + TWAI0_BUS_OFF_ON = 81, + TWAI0_CLKOUT = 82, + TWAI1_TX = 83, + TWAI1_BUS_OFF_ON = 84, + TWAI1_CLKOUT = 85, + TWAI2_TX = 86, + TWAI2_BUS_OFF_ON = 87, + TWAI2_CLKOUT = 88, + PWM0_CH0_A = 89, + PWM0_CH0_B = 90, + PWM0_CH1_A = 91, + PWM0_CH1_B = 92, + PWM0_CH2_A = 93, + PWM0_CH2_B = 94, + PWM1_CH0_A = 95, + PWM1_CH0_B = 96, + PWM1_CH1_A = 97, + PWM1_CH1_B = 98, + PWM1_CH2_A = 99, + PWM1_CH2_B = 100, + TWAI0_STANDBY = 105, + TWAI1_STANDBY = 106, + TWAI2_STANDBY = 107, + MII_MDC = 108, + MII_MDO = 109, + USB_SRP_DISCHRGVBUS = 110, + USB_OTG11_IDPULLUP = 111, + USB_OTG11_DPPULLDOWN = 112, + USB_OTG11_DMPULLDOWN = 113, + USB_OTG11_DRVVBUS = 114, + USB_SRP_CHRGVBUS = 115, + RNG_CHAIN_CLK = 117, + I3C_MST_SCL = 134, + I3C_MST_SDA = 135, + I3C_SLV_SCL = 136, + I3C_SLV_SDA = 137, + I3C_MST_SCL_PULLUP_EN = 138, + I3C_MST_SDA_PULLUP_EN = 139, + USB_JTAG_TDI_BRIDGE = 140, + USB_JTAG_TMS_BRIDGE = 141, + USB_JTAG_TCK_BRIDGE = 142, + USB_JTAG_TRST_BRIDGE = 143, + LCD_CS = 144, + LCD_DC = 145, + SD_RST_N_1 = 146, + SD_RST_N_2 = 147, + SD_CCMD_OD_PULLUP_EN_N = 148, + LCD_PCLK = 149, + CAM_CLK = 150, + LCD_H_ENABLE = 151, + LCD_H_SYNC = 152, + LCD_V_SYNC = 153, + EMAC_PHY_TXEN = 178, + EMAC_PHY_TXD0 = 179, + EMAC_PHY_TXD1 = 180, + EMAC_PHY_TXD2 = 181, + EMAC_PHY_TXD3 = 182, + EMAC_PHY_TXER = 183, + PARLIO_RX_CLK = 186, + PARLIO_TX_CLK = 187, + PARLIO_TX_DATA0 = 188, + PARLIO_TX_DATA1 = 189, + PARLIO_TX_DATA2 = 190, + PARLIO_TX_DATA3 = 191, + PARLIO_TX_DATA4 = 192, + PARLIO_TX_DATA5 = 193, + PARLIO_TX_DATA6 = 194, + PARLIO_TX_DATA7 = 195, + PARLIO_TX_DATA8 = 196, + PARLIO_TX_DATA9 = 197, + PARLIO_TX_DATA10 = 198, + PARLIO_TX_DATA11 = 199, + PARLIO_TX_DATA12 = 200, + PARLIO_TX_DATA13 = 201, + PARLIO_TX_DATA14 = 202, + PARLIO_TX_DATA15 = 203, + CONSTANT0 = 212, + CONSTANT1 = 213, + PARLIO_TX_CS = 242, + EMAC_PTP_PPS = 243, + ANA_COMP0 = 244, + ANA_COMP1 = 245, + GPIO = 256, + MTCK, + MTDI, + MTMS, + MTDO, + SD1_CDATA0, + SD1_CDATA1, + SD1_CDATA2, + SD1_CDATA3, + SD1_CCLK, + SD1_CCMD, + SD1_CDATA4, + SD1_CDATA5, + SD1_CDATA6, + SD1_CDATA7, + EMAC_RMII_CLK, + REF_50M_CLK, + BIST, + DBG_PSRAM_CK, + DBG_PSRAM_CS, + DBG_PSRAM_D, + DBG_PSRAM_Q, + DBG_PSRAM_WP, + DBG_PSRAM_HOLD, + DBG_PSRAM_DQ4, + DBG_PSRAM_DQ5, + DBG_PSRAM_DQ6, + DBG_PSRAM_DQ7, + DBG_PSRAM_DQS_0, + DBG_PSRAM_DQ8, + DBG_PSRAM_DQ9, + DBG_PSRAM_DQ10, + DBG_PSRAM_DQ11, + DBG_PSRAM_DQ12, + DBG_PSRAM_DQ13, + DBG_PSRAM_DQ14, + DBG_PSRAM_DQ15, + DBG_PSRAM_DQS_1, + DBG_FLASH_CS, + DBG_FLASH_Q, + DBG_FLASH_WP, + DBG_FLASH_HOLD, + DBG_FLASH_CK, + DBG_FLASH_D, + } + }; +} +/// Defines and implements the `io_mux_reg` function. +/// +/// The generated function has the following signature: +/// +/// ```rust,ignore +/// pub(crate) fn io_mux_reg(gpio_num: u8) -> &'static crate::pac::io_mux::GPIO0 { +/// // ... +/// # unimplemented!() +/// } +/// ``` +/// +/// This macro is intended to be called in esp-hal only. +#[macro_export] +#[expect(clippy::crate_in_macro_def)] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! define_io_mux_reg { + () => { + pub(crate) fn io_mux_reg(gpio_num: u8) -> &'static crate::pac::io_mux::GPIO { + crate::peripherals::IO_MUX::regs().gpio(gpio_num as usize) + } + }; +} diff --git a/esp-metadata-generated/src/lib.rs b/esp-metadata-generated/src/lib.rs index 7eb6d3a6389..533e8f4d33e 100644 --- a/esp-metadata-generated/src/lib.rs +++ b/esp-metadata-generated/src/lib.rs @@ -113,6 +113,8 @@ include!("_generated_esp32c6.rs"); include!("_generated_esp32c61.rs"); #[cfg(feature = "esp32h2")] include!("_generated_esp32h2.rs"); +#[cfg(feature = "esp32p4")] +include!("_generated_esp32p4.rs"); #[cfg(feature = "esp32s2")] include!("_generated_esp32s2.rs"); #[cfg(feature = "esp32s3")] diff --git a/esp-metadata/CHANGELOG.md b/esp-metadata/CHANGELOG.md index 2546e19971b..490833fef81 100644 --- a/esp-metadata/CHANGELOG.md +++ b/esp-metadata/CHANGELOG.md @@ -10,6 +10,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - C5 and C61: Enable RTC timekeeping (#5449) +- ESP32-P4: emit `rom_crc_le`, `rom_crc_be`, `rom_md5_bsd` cfg flags (#5400) +- ESP32-P4: emit `pm_support_ext1_wakeup` and `pm_support_touch_sensor_wakeup` (#5400) ### Changed diff --git a/esp-metadata/devices/esp32p4.toml b/esp-metadata/devices/esp32p4.toml index c8ac63be2c4..55b026ed1e2 100644 --- a/esp-metadata/devices/esp32p4.toml +++ b/esp-metadata/devices/esp32p4.toml @@ -6,106 +6,948 @@ # update the table in the esp-hal README. [device] -name = "esp32p4" -arch = "riscv" -cores = 2 +name = "esp32p4" +arch = "riscv" +target = "riscv32imafc-unknown-none-elf" +cores = 2 trm = "https://www.espressif.com/sites/default/files/documentation/esp32-p4_technical_reference_manual_en.pdf" -peripherals = [ - # Peripherals available in the PAC: - # "adc", - # "aes", - # "assist_debug", - # "axi_dma", - # "axi_icm", - # "bitscrambler", - # "cache", - # "dma", - # "ds", - # "ecc", - # "ecdsa", - "efuse", - # "gpio_sd", - "gpio", - # "h264_dma", - # "h264", - # "hmac", - # "hp_sys_clkrst", - "hp_sys", - # "i2c0", - # "i2c1", - # "i2s0", - # "i2s1", - # "i2s2", - # "i3c_mst_mem", - # "i3c_mst", - # "i3c_slv", - "interrupt_core0", - "interrupt_core1", - "io_mux", - # "isp", - # "jpeg", - # "lcd_cam", - # "ledc", - # "lp_adc", - # "lp_ana_peri", - # "lp_aon_clkrst", - # "lp_gpio", - # "lp_huk", - # "lp_i2c_ana_mst", - # "lp_i2c0", - # "lp_i2s0", - # "lp_intr", - # "lp_io_mux", - # "lp_peri", - # "lp_sys", - # "lp_timer", - # "lp_touch", - # "lp_tsens", - # "lp_uart", - # "lp_wdt", - # "mcpwm0", - # "mcpwm1", - # "mipi_csi_bridge", - # "mipi_csi_host", - # "mipi_dsi_bridge", - # "mipi_dsi_host", - # "parl_io", - # "pau", - # "pcnt", - # "pmu", - # "ppa", - # "pvt", - # "rmt", - # "rsa", - # "sdhost", - # "sha", - # "soc_etm", - # "spi0", - # "spi1", - # "spi2", - # "spi3", - # "systimer", - # "timg0", - # "timg1", - # "trace0", - # "trace1", - # "twai0", - # "twai1", - # "twai2", - # "uart0", - # "uhci0", - # "usb_device", - # "usb_wrap", -] - symbols = [ # Additional peripherals defined by us (the developers): - # "adc1", - # "adc2", "very_large_intr_status", - "gpio_bank_1", "spi_octal", + + # ROM capabilities + "rom_crc_le", + "rom_crc_be", + "rom_md5_bsd", + + # Wakeup SOC based on ESP-IDF: + "pm_support_ext1_wakeup", + "pm_support_touch_sensor_wakeup", + + # TODO: add the following symbols when investigation and getting ready + # - "lp_core" + # - "swd" + # - "gpio_support_deepsleep_wakeup" + # - "uart_support_wakeup_int" +] + +[device.interrupts] +support_status = "partial" +# ESP32-P4 uses CLIC with 48 interrupt lines (TRM v0.5, Ch 14) +# "very_large_intr_status" uses 3 status registers (same as C5/C61) +status_registers = 3 +software_interrupt_count = 4 +software_interrupt_delay = 24 +controller = { Riscv = { flavour = "clic", interrupts = 48, priority_levels = 8 } } + +# TODO: align with newer TRM revisions after v0.5. The v0.5 TRM still has +# the following sections incomplete: +# - Bus Architecture +# - Processor Instruction Extensions +# - AXI Performance Monitor +# - MIPI DSI (CAM) +# - I3C + +[device.soc] +cpu_has_csr_pc = true +# ESP32-P4 v3.x: 20 MHz RC_FAST default (TRM v0.5, Ch 12) +rc_fast_clk_default = 20_000_000 + +# Clock tree for ESP32-P4X (eco5 / chip revision v3.x) +# 3 PLLs: CPLL (CPU, 360/400MHz), SPLL (480MHz, peripherals), MPLL (400MHz, PSRAM/media) +clocks = { system_clocks = { clock_tree = [ + # High-speed clock sources + { name = "XTAL_CLK", type = "source", output = "40_000_000", always_on = true }, + { name = "CPLL_CLK", type = "derived", from = "XTAL_CLK", output = "400_000_000" }, # eco5 default 400MHz + { name = "SPLL_CLK", type = "derived", from = "XTAL_CLK", output = "480_000_000" }, # System PLL + { name = "MPLL_CLK", type = "derived", from = "XTAL_CLK", output = "400_000_000" }, # Media PLL + { name = "RC_FAST_CLK", type = "source", output = "20_000_000" }, + + # Low-speed clocks + { name = "XTAL32K_CLK", type = "source", output = "32768" }, + { name = "OSC_SLOW_CLK", type = "source", output = "32768" }, + { name = "RC_SLOW_CLK", type = "source", output = "136_000" }, + { name = "RC32K_CLK", type = "source", output = "32768" }, + + # SPLL divider taps (from 480 MHz SPLL) + { name = "PLL_F20M", type = "generic", output = "SPLL_CLK / 24" }, + { name = "PLL_F80M", type = "generic", output = "SPLL_CLK / 6" }, + { name = "PLL_F120M", type = "generic", output = "SPLL_CLK / 4" }, + { name = "PLL_F160M", type = "generic", output = "SPLL_CLK / 3" }, + { name = "PLL_F240M", type = "generic", output = "SPLL_CLK / 2" }, + + # MPLL divider taps (from 400 MHz MPLL) + { name = "PLL_F25M", type = "generic", output = "MPLL_CLK / 16" }, + { name = "PLL_F50M", type = "generic", output = "MPLL_CLK / 8" }, + + # XTAL half + { name = "XTAL_D2_CLK", type = "generic", output = "XTAL_CLK / 2" }, + + # CPU root clock (LP_AON_CLKRST.hp_clk_ctrl.hp_root_clk_src_sel) + { name = "CPU_ROOT_CLK", type = "mux", variants = [ + { name = "XTAL", outputs = "XTAL_CLK" }, + { name = "CPLL", outputs = "CPLL_CLK" }, + { name = "RC_FAST", outputs = "RC_FAST_CLK" }, + ] }, + + # CPU_CLK divider (HP_SYS_CLKRST.root_clk_ctrl0.cpu_clk_div_num) + { name = "CPU_CLK", type = "generic", params = { divisor = "0..256" }, output = "CPU_ROOT_CLK / (divisor + 1)" }, + # APB_CLK divider + { name = "APB_CLK", type = "generic", params = { divisor = "0..256" }, output = "CPU_CLK / (divisor + 1)" }, + + # LP clocks + { name = "LP_FAST_CLK", type = "mux", variants = [ + { name = "RC_FAST", outputs = "RC_FAST_CLK" }, + { name = "XTAL_D2", outputs = "XTAL_D2_CLK" }, + ] }, + { name = "LP_SLOW_CLK", type = "mux", variants = [ + { name = "RC_SLOW", outputs = "RC_SLOW_CLK" }, + { name = "XTAL32K", outputs = "XTAL32K_CLK" }, + { name = "RC32K", outputs = "RC32K_CLK" }, + { name = "OSC_SLOW", outputs = "OSC_SLOW_CLK" }, + ] }, +], template_groups = [ + { group = "UART", clocks = [ + { name = "FUNCTION_CLOCK", type = "generic", output = "sclk / (div_num + 1)", params = { sclk = [ + { name = "XTAL", outputs = "XTAL_CLK", default = true }, + { name = "PLL_F80M", outputs = "PLL_F80M" }, + { name = "RC_FAST", outputs = "RC_FAST_CLK" }, + ], div_num = "0 .. 0x100" } }, + { name = "BAUD_RATE_GENERATOR", type = "generic", output = "(FUNCTION_CLOCK * 16) / (integral * 16 + fractional)", params = { fractional = "0..16", integral = "0..0x1000" } }, + ] }, + { group = "TIMG", clocks = [ + { name = "FUNCTION_CLOCK", type = "mux", variants = [ + { name = "XTAL_CLK", outputs = "XTAL_CLK", default = true }, + { name = "RC_FAST_CLK", outputs = "RC_FAST_CLK" }, + { name = "PLL_F80M", outputs = "PLL_F80M" }, + ] }, + { name = "WDT_CLOCK", type = "mux", variants = [ + { name = "XTAL_CLK", outputs = "XTAL_CLK", default = true }, + { name = "PLL_F80M", outputs = "PLL_F80M" }, + { name = "RC_FAST_CLK", outputs = "RC_FAST_CLK" }, + ] }, + ] }, +] }, peripheral_clocks = { templates = [ + # ESP32-P4 peripheral clock and reset gates -- all live in HP_SYS_CLKRST. + # Clock enables: SOC_CLK_CTRL0/1/2 + PERI_CLK_CTRL{21,26}. + # Resets: HP_RST_EN0/1/2. + # Each peripheral overrides {{default_clk_en_template}} / {{default_rst_template}} + # to select the right shared register + bit field. + { name = "clk_en_template", value = "{{default_clk_en_template}}" }, + { name = "rst_template", value = "{{default_rst_template}}" }, + { name = "default_clk_en_template", value = "let _ = enable;" }, + { name = "default_rst_template", value = "let _ = reset;" }, + # Reusable clock-enable building blocks (composed via {{default_clk_en_template}} = "{{X}}"). + { name = "sys_clk_template", value = "{{control}}::regs().soc_clk_ctrl1().modify(|_, w| w.{{sys_field}}().bit(enable));" }, + { name = "apb_clk_template", value = "{{control}}::regs().soc_clk_ctrl2().modify(|_, w| w.{{apb_field}}().bit(enable));" }, + { name = "sys_apb_clk_template", value = "{{sys_clk_template}} {{apb_clk_template}}" }, + { name = "crypto_clk_template", value = "{{control}}::regs().soc_clk_ctrl1().modify(|_, w| w.crypto_sys_clk_en().bit(enable));" }, + # Reusable reset building blocks. Reset bit name is supplied via {{rst_field}}. + { name = "rst_en0_template", value = "{{control}}::regs().hp_rst_en0().modify(|_, w| w.{{rst_field}}().bit(reset));" }, + { name = "rst_en1_template", value = "{{control}}::regs().hp_rst_en1().modify(|_, w| w.{{rst_field}}().bit(reset));" }, + { name = "rst_en2_template", value = "{{control}}::regs().hp_rst_en2().modify(|_, w| w.{{rst_field}}().bit(reset));" }, + { name = "control", value = "crate::peripherals::HP_SYS_CLKRST" }, +], peripheral_clocks = [ + # Ref: TRM v0.5 Ch 12 (Reset and Clock), Ch 22 (System Registers). + # UARTs -- sys_clk + apb_clk; reset asserts both core+apb together. + { name = "Uart0", template_params = { default_clk_en_template = "{{sys_apb_clk_template}}", sys_field = "uart0_sys_clk_en", apb_field = "uart0_apb_clk_en", default_rst_template = "{{control}}::regs().hp_rst_en1().modify(|_, w| w.rst_en_uart0_core().bit(reset).rst_en_uart0_apb().bit(reset));" }, keep_enabled = true }, + { name = "Uart1", template_params = { default_clk_en_template = "{{sys_apb_clk_template}}", sys_field = "uart1_sys_clk_en", apb_field = "uart1_apb_clk_en", default_rst_template = "{{control}}::regs().hp_rst_en1().modify(|_, w| w.rst_en_uart1_core().bit(reset).rst_en_uart1_apb().bit(reset));" } }, + { name = "Uart2", template_params = { default_clk_en_template = "{{sys_apb_clk_template}}", sys_field = "uart2_sys_clk_en", apb_field = "uart2_apb_clk_en", default_rst_template = "{{control}}::regs().hp_rst_en1().modify(|_, w| w.rst_en_uart2_core().bit(reset).rst_en_uart2_apb().bit(reset));" } }, + { name = "Uart3", template_params = { default_clk_en_template = "{{sys_apb_clk_template}}", sys_field = "uart3_sys_clk_en", apb_field = "uart3_apb_clk_en", default_rst_template = "{{control}}::regs().hp_rst_en1().modify(|_, w| w.rst_en_uart3_core().bit(reset).rst_en_uart3_apb().bit(reset));" } }, + { name = "Uart4", template_params = { default_clk_en_template = "{{sys_apb_clk_template}}", sys_field = "uart4_sys_clk_en", apb_field = "uart4_apb_clk_en", default_rst_template = "{{control}}::regs().hp_rst_en1().modify(|_, w| w.rst_en_uart4_core().bit(reset).rst_en_uart4_apb().bit(reset));" } }, + # SPI -- sys_clk + apb_clk; reset in HP_RST_EN2. + { name = "Spi2", template_params = { default_clk_en_template = "{{sys_apb_clk_template}}", sys_field = "gpspi2_sys_clk_en", apb_field = "gpspi2_apb_clk_en", default_rst_template = "{{rst_en2_template}}", rst_field = "rst_en_spi2" } }, + { name = "Spi3", template_params = { default_clk_en_template = "{{sys_apb_clk_template}}", sys_field = "gpspi3_sys_clk_en", apb_field = "gpspi3_apb_clk_en", default_rst_template = "{{rst_en2_template}}", rst_field = "rst_en_spi3" } }, + # I2C master -- apb_clk only; reset in HP_RST_EN1. + { name = "I2c0", template_params = { default_clk_en_template = "{{apb_clk_template}}", apb_field = "i2c0_apb_clk_en", default_rst_template = "{{rst_en1_template}}", rst_field = "rst_en_i2c0" } }, + { name = "I2c1", template_params = { default_clk_en_template = "{{apb_clk_template}}", apb_field = "i2c1_apb_clk_en", default_rst_template = "{{rst_en1_template}}", rst_field = "rst_en_i2c1" } }, + # I2S -- apb_clk; reset in HP_RST_EN2. + { name = "I2s0", template_params = { default_clk_en_template = "{{apb_clk_template}}", apb_field = "i2s0_apb_clk_en", default_rst_template = "{{rst_en2_template}}", rst_field = "rst_en_i2s0_apb" } }, + { name = "I2s1", template_params = { default_clk_en_template = "{{apb_clk_template}}", apb_field = "i2s1_apb_clk_en", default_rst_template = "{{rst_en2_template}}", rst_field = "rst_en_i2s1_apb" } }, + { name = "I2s2", template_params = { default_clk_en_template = "{{apb_clk_template}}", apb_field = "i2s2_apb_clk_en", default_rst_template = "{{rst_en2_template}}", rst_field = "rst_en_i2s2_apb" } }, + # Timers -- Systimer also needs PERI_CLK_CTRL21.systimer_clk_en gate. + { name = "Systimer", template_params = { default_clk_en_template = "{{control}}::regs().soc_clk_ctrl2().modify(|_, w| w.systimer_apb_clk_en().bit(enable)); {{control}}::regs().peri_clk_ctrl21().modify(|_, w| w.systimer_clk_en().bit(enable));", default_rst_template = "{{rst_en1_template}}", rst_field = "rst_en_stimer" }, keep_enabled = true }, + { name = "Timg0", template_params = { default_clk_en_template = "{{apb_clk_template}}", apb_field = "timergrp0_apb_clk_en", default_rst_template = "{{rst_en1_template}}", rst_field = "rst_en_timergrp0" } }, + { name = "Timg1", template_params = { default_clk_en_template = "{{apb_clk_template}}", apb_field = "timergrp1_apb_clk_en", default_rst_template = "{{rst_en1_template}}", rst_field = "rst_en_timergrp1" } }, + # IO MUX -- gated via PERI_CLK_CTRL26; KEEP_ENABLED because GPIO depends on it. + { name = "Iomux", template_params = { default_clk_en_template = "{{control}}::regs().peri_clk_ctrl26().modify(|_, w| w.iomux_clk_en().bit(enable));", default_rst_template = "{{rst_en1_template}}", rst_field = "rst_en_iomux" }, keep_enabled = true }, + # PWM/Counter/RMT -- LCD/CAM clock gate lives in SOC_CLK_CTRL3 (not modelled in current PAC), keep stub. + { name = "Ledc", template_params = { default_rst_template = "{{rst_en1_template}}", rst_field = "rst_en_ledc" } }, + { name = "Pcnt", template_params = { default_clk_en_template = "{{apb_clk_template}}", apb_field = "pcnt_apb_clk_en", default_rst_template = "{{rst_en1_template}}", rst_field = "rst_en_pcnt" } }, + { name = "Mcpwm0", template_params = { default_clk_en_template = "{{apb_clk_template}}", apb_field = "mcpwm0_apb_clk_en", default_rst_template = "{{rst_en1_template}}", rst_field = "rst_en_pwm0" } }, + { name = "Mcpwm1", template_params = { default_clk_en_template = "{{apb_clk_template}}", apb_field = "mcpwm1_apb_clk_en", default_rst_template = "{{rst_en1_template}}", rst_field = "rst_en_pwm1" } }, + # NOTE: `rmt_sys_clk_en` despite the name lives on SOC_CLK_CTRL2, not CTRL1. + { name = "Rmt", template_params = { default_clk_en_template = "{{apb_clk_template}}", apb_field = "rmt_sys_clk_en", default_rst_template = "{{rst_en1_template}}", rst_field = "rst_en_rmt" } }, + # TWAI (CAN) -- reset bits named can0/can1/can2 in PAC. + { name = "Twai0", template_params = { default_clk_en_template = "{{apb_clk_template}}", apb_field = "twai0_apb_clk_en", default_rst_template = "{{rst_en1_template}}", rst_field = "rst_en_can0" } }, + { name = "Twai1", template_params = { default_clk_en_template = "{{apb_clk_template}}", apb_field = "twai1_apb_clk_en", default_rst_template = "{{rst_en1_template}}", rst_field = "rst_en_can1" } }, + { name = "Twai2", template_params = { default_clk_en_template = "{{apb_clk_template}}", apb_field = "twai2_apb_clk_en", default_rst_template = "{{rst_en1_template}}", rst_field = "rst_en_can2" } }, + # USB -- reset is via LP-domain registers, leave rst as no-op here. + { name = "UsbOtg11", template_params = { default_clk_en_template = "{{sys_clk_template}}", sys_field = "usb_otg11_sys_clk_en" } }, + { name = "UsbOtg20", template_params = { default_clk_en_template = "{{sys_clk_template}}", sys_field = "usb_otg20_sys_clk_en" } }, + { name = "UsbDevice", template_params = { default_clk_en_template = "{{apb_clk_template}}", apb_field = "usb_device_apb_clk_en" }, keep_enabled = true }, + # Connectivity -- EMAC and SDMMC reset live in dedicated registers, no HP_RST_EN gate. + { name = "Emac", template_params = { default_clk_en_template = "{{sys_clk_template}}", sys_field = "emac_sys_clk_en" } }, + { name = "Sdmmc", template_params = { default_clk_en_template = "{{sys_clk_template}}", sys_field = "sdmmc_sys_clk_en" } }, + { name = "Uhci", template_params = { default_clk_en_template = "{{sys_apb_clk_template}}", sys_field = "uhci_sys_clk_en", apb_field = "uhci_apb_clk_en", default_rst_template = "{{rst_en1_template}}", rst_field = "rst_en_uhci" } }, + # Crypto -- shared crypto_sys_clk_en bit; each peripheral has its own reset bit. + { name = "Aes", template_params = { default_clk_en_template = "{{crypto_clk_template}}", default_rst_template = "{{rst_en2_template}}", rst_field = "rst_en_aes" } }, + { name = "Sha", template_params = { default_clk_en_template = "{{crypto_clk_template}}", default_rst_template = "{{rst_en2_template}}", rst_field = "rst_en_sha" } }, + { name = "Rsa", template_params = { default_clk_en_template = "{{crypto_clk_template}}", default_rst_template = "{{rst_en2_template}}", rst_field = "rst_en_rsa" } }, + { name = "Ecc", template_params = { default_clk_en_template = "{{crypto_clk_template}}", default_rst_template = "{{rst_en2_template}}", rst_field = "rst_en_ecc" } }, + { name = "Ecdsa", template_params = { default_clk_en_template = "{{crypto_clk_template}}", default_rst_template = "{{rst_en2_template}}", rst_field = "rst_en_ecdsa" } }, + { name = "Hmac", template_params = { default_clk_en_template = "{{crypto_clk_template}}", default_rst_template = "{{rst_en2_template}}", rst_field = "rst_en_hmac" } }, + { name = "Ds", template_params = { default_clk_en_template = "{{crypto_clk_template}}", default_rst_template = "{{rst_en2_template}}", rst_field = "rst_en_ds" } }, + # DMA -- P4 has multiple controllers (AHB-PDMA / AXI-PDMA / GDMA-DW). `Dma` is the GDMA-AHB + # variant esp-hal's DMA driver targets. `Gdma` covers the DW block at 0x5008_1000. + { name = "Dma", template_params = { default_clk_en_template = "{{sys_clk_template}}", sys_field = "ahb_pdma_sys_clk_en", default_rst_template = "{{rst_en1_template}}", rst_field = "rst_en_ahb_pdma" } }, + { name = "Gdma", template_params = { default_clk_en_template = "{{sys_clk_template}}", sys_field = "gdma_sys_clk_en", default_rst_template = "{{rst_en0_template}}", rst_field = "rst_en_gdma" } }, + { name = "AhbPdma", template_params = { default_clk_en_template = "{{sys_clk_template}}", sys_field = "ahb_pdma_sys_clk_en", default_rst_template = "{{rst_en1_template}}", rst_field = "rst_en_ahb_pdma" } }, + { name = "AxiPdma", template_params = { default_clk_en_template = "{{sys_clk_template}}", sys_field = "axi_pdma_sys_clk_en", default_rst_template = "{{rst_en1_template}}", rst_field = "rst_en_axi_pdma" } }, + # ADC. + { name = "Adc", template_params = { default_clk_en_template = "{{apb_clk_template}}", apb_field = "adc_apb_clk_en", default_rst_template = "{{rst_en2_template}}", rst_field = "rst_en_adc" } }, + # Parallel IO -- reset asserts the parlio block plus its rx/tx subreset bits in one write. + { name = "ParlIo", template_params = { default_clk_en_template = "{{sys_apb_clk_template}}", sys_field = "parlio_sys_clk_en", apb_field = "parlio_apb_clk_en", default_rst_template = "{{control}}::regs().hp_rst_en2().modify(|_, w| w.rst_en_parlio().bit(reset).rst_en_parlio_rx().bit(reset).rst_en_parlio_tx().bit(reset));" } }, + # LCD/CAM -- clock gate lives in SOC_CLK_CTRL3 (not modelled), only reset is wired up. + { name = "LcdCam", template_params = { default_rst_template = "{{rst_en2_template}}", rst_field = "rst_en_lcdcam" } }, +] } } + +# HP L2MEM: 0x4FF0_0000 - 0x4FFC_0000 (768 KB) +# ROM bootloader reserves 0x4FF0_0000 - 0x4FF4_0000 (256 KB) +# dram: usable application RAM (after ROM reserved region) +# dram2_uninit: ROM reserved area, reclaimable after 2nd-stage bootloader +memory_map = { ranges = [ + { name = "dram", start = 0x4FF4_0000, end = 0x4FFC_0000 }, + { name = "dram2_uninit", start = 0x4FF0_0000, end = 0x4FF4_0000 }, +] } + +peripherals = [ + # Minimal set for esp-hal compilation + { name = "EFUSE", hidden = true }, + { name = "GPIO" }, + { name = "HP_SYS" }, + { name = "HP_SYS_CLKRST" }, + { name = "INTERRUPT_CORE0" }, + { name = "INTERRUPT_CORE1" }, + { name = "CLIC" }, + { name = "IO_MUX" }, + # LP_AON / LPWR: compatibility aliases -- other chips expose an `LP_AON` + # (and the `LPWR` alias) register block; on P4 the same registers live in + # `LP_SYS` in the PAC, so we point the esp-hal `LP_AON` / `LPWR` singletons + # at the `LP_SYS` PAC type. + { name = "LP_AON", pac = "LP_SYS" }, + { name = "LP_AON_CLKRST" }, + { name = "LP_SYS" }, + { name = "LP_WDT" }, + { name = "LPWR", pac = "LP_SYS" }, + { name = "PMU" }, + { name = "SYSTIMER" }, + { name = "TIMG0", clock_group = "TIMG" }, + { name = "TIMG1", clock_group = "TIMG" }, + { name = "UART0", interrupts = { peri = "UART0" }, clock_group = "UART" }, + { name = "UART1", interrupts = { peri = "UART1" }, clock_group = "UART" }, + { name = "UART2", interrupts = { peri = "UART2" }, clock_group = "UART" }, + { name = "UART3", interrupts = { peri = "UART3" }, clock_group = "UART" }, + { name = "UART4", interrupts = { peri = "UART4" }, clock_group = "UART" }, + { name = "SPI2", interrupts = { peri = "SPI2" }, dma_peripheral = 1 }, + # SPI3 has the same RegisterBlock layout as SPI2 but the PAC exposes it as + # a distinct type. Map to SPI2 so the SPI master driver can reuse its + # register accessors directly. Verified field-compatible against the + # upstream esp32p4 PAC at the time of this port. + { name = "SPI3", pac = "SPI2", interrupts = { peri = "SPI3" }, dma_peripheral = 2 }, + { name = "I2C0", interrupts = { peri = "I2C0" } }, + { name = "I2C1", interrupts = { peri = "I2C1" } }, + { name = "TWAI0", interrupts = { peri = "TWAI0" } }, + { name = "TWAI1", interrupts = { peri = "TWAI1" } }, + { name = "TWAI2", interrupts = { peri = "TWAI2" } }, + { name = "PSRAM", virtual = true }, + # DMA: P4 has three DMA blocks; see [device.dma] below for the table. + # esp-hal's `Dma` singleton needs the GDMA v2 layout, so map it to AHB_DMA. + { name = "DMA", pac = "AHB_DMA" }, + { name = "DMA_CH0", virtual = true }, + { name = "DMA_CH1", virtual = true }, + { name = "DMA_CH2", virtual = true }, + + { name = "USB_DEVICE", interrupts = { peri = "USB_DEVICE" } }, + { name = "SDHOST" }, + # TODO: clarify EMAC <-> PAC mapping before exposing it. + # but the esp32p4 PAC has not been generated with a matching peripheral yet. + # { name = "EMAC" }, + { name = "LEDC", interrupts = { peri = "LEDC" } }, + { name = "MCPWM0", interrupts = { peri = "PWM0" } }, + { name = "MCPWM1", interrupts = { peri = "PWM1" } }, + { name = "PCNT", interrupts = { peri = "PCNT" } }, + { name = "RMT", interrupts = { peri = "RMT" } }, + { name = "ADC" }, + { name = "AES", interrupts = { peri = "AES" }, dma_peripheral = 4 }, + { name = "SHA", interrupts = { peri = "SHA" }, dma_peripheral = 5 }, + { name = "RSA", interrupts = { peri = "RSA" } }, + { name = "ECC", interrupts = { peri = "ECC" } }, +] + +# UART: 5 instances (UART0-4), 128-byte FIFO +[device.uart] +support_status = "partial" +instances = [ + { name = "uart0", sys_instance = "Uart0", tx = "UART0_TXD", rx = "UART0_RXD", cts = "UART0_CTS", rts = "UART0_RTS" }, + { name = "uart1", sys_instance = "Uart1", tx = "UART1_TXD", rx = "UART1_RXD", cts = "UART1_CTS", rts = "UART1_RTS" }, + { name = "uart2", sys_instance = "Uart2", tx = "UART2_TXD", rx = "UART2_RXD", cts = "UART2_CTS", rts = "UART2_RTS" }, + { name = "uart3", sys_instance = "Uart3", tx = "UART3_TXD", rx = "UART3_RXD", cts = "UART3_CTS", rts = "UART3_RTS" }, + { name = "uart4", sys_instance = "Uart4", tx = "UART4_TXD", rx = "UART4_RXD", cts = "UART4_CTS", rts = "UART4_RTS" }, ] +ram_size = 128 +version = 2 -memory = [{ name = "dram", start = 0x4FF0_0000, end = 0x4FFC_0000 }] +# SYSTIMER: 2 counter units, 3 alarm comparators, 16 MHz (XTAL/2.5) +# PAC register names verified: unit_op(n), unit_value(n), target_conf(n), +# trgt(n), comp_load(n) all match esp-hal systimer module expectations. +[device.systimer] + +# GP Timer (TIMG): 2 groups, each with 2 timers + WDT +[device.gp_timer] +support_status = "partial" +instances = [ + { name = "timg0", sys_instance = "Timg0", interrupt = "TG0_T0_LEVEL" }, + { name = "timg1", sys_instance = "Timg1", interrupt = "TG1_T0_LEVEL" }, +] + +# SPI Master: 2 instances (GPSPI2, GPSPI3) +# SPI Master: SPI2 only (SPI2 and SPI3 have different PAC RegisterBlock types) +[device.spi_master] +support_status = "partial" +supports_dma = true +instances = [ + { name = "spi2", sys_instance = "Spi2", sclk = "SPI2_CK", sio = ["SPI2_D", "SPI2_Q", "SPI2_WP", "SPI2_HOLD"], cs = ["SPI2_CS"] }, + { name = "spi3", sys_instance = "Spi3", sclk = "SPI3_CK", sio = ["SPI3_D", "SPI3_Q", "SPI3_WP", "SPI3_HOLD"], cs = ["SPI3_CS", "SPI3_CS1", "SPI3_CS2"] }, +] + +# I2C Master: 2 instances +# P4 PAC: data register is read-only, TX uses txfifo_start_addr (fixed in i2c/master/mod.rs) +[device.i2c_master] +support_status = "partial" +instances = [ + { name = "i2c0", sys_instance = "I2c0", scl = "I2C0_SCL", sda = "I2C0_SDA" }, + { name = "i2c1", sys_instance = "I2c1", scl = "I2C1_SCL", sda = "I2C1_SDA" }, +] +has_fsm_timeouts = true +has_hw_bus_clear = true +ll_intr_mask = 0x3ffff +fifo_size = 32 +has_bus_timeout_enable = true +max_bus_timeout = 0x1F + +# DMA: P4 exposes three DMA controllers. IDF public docs +# (https://docs.espressif.com/projects/esp-idf/en/stable/esp32p4/api-reference/system/async_memcpy.html) +# refer to them as GDMA-AHB and GDMA-AXI: +# AHB_DMA / GDMA-AHB (0x50085000): GDMA v2 layout -- used by esp-hal as `Dma` +# AXI_DMA / GDMA-AXI (0x5008A000): AXI-bus DMA, different layout +# DMA (separate block at 0x50081000, SOC_DW_GDMA_SUPPORTED): +# another register layout, not used by esp-hal +# esp-hal's `Dma` singleton must be GDMA v2 compatible, hence PAC alias AHB_DMA above. +# Ref: IDF linker esp32p4.peripherals.ld (AHB_DMA, AXI_DMA, DW_GDMA symbols). +[device.dma] +support_status = "partial" +kind = "gdma" +gdma_version = 2 +separate_in_out_interrupts = true +max_priority = 5 + +# TODO: Check later with PAC and TRM both +[device.twai] +support_status = "not_supported" +# TODO: Check later with PAC and TRM both +[device.adc] +support_status = "not_supported" +# Below: peripherals P4 silicon physically has, but no esp-hal driver +# is wired up in this PR. All marked `not_supported` so the README's +# chip-support table accurately shows ❌ rather than empty cells. +# When the upstream driver lands or our local code path is added, +# flip the relevant entry to `partial`. +# Refs: +# .investigation/PERIPHERAL_TESTABILITY_w_logicpro.md +# .investigation/README_TABLE_AUDIT_P4.md + +[device.assist_debug] +support_status = "not_supported" +[device.avc] +support_status = "not_supported" # P4 ANA_CMPR (CH0/CH1) +[device.camera] +support_status = "not_supported" # LCD_CAM block, camera path +# [device.dedicated_gpio] requires a `channels` table -- skip for now +# until we map the P4 CPU GPIO instance list. README will show this row +# blank for P4, accurate to the current driver state. +[device.ds] +support_status = "not_supported" # Digital Signature +[device.ecdsa] +support_status = "not_supported" +[device.ethernet] +support_status = "not_supported" # EMAC, RMII via GPIO 30/47/53 etc. +[device.etm] +support_status = "not_supported" # Event Task Matrix +[device.hmac] +support_status = "not_supported" +[device.i2c_slave] +support_status = "not_supported" +[device.i2s] +support_status = "not_supported" # 3 instances (I2S0/1/2) +[device.ledc] +support_status = "not_supported" +[device.lp_i2c_master] +support_status = "not_supported" +fifo_size = 32 # placeholder until LP I2C driver lands; from c6 reference +[device.lp_uart] +support_status = "not_supported" +ram_size = 32 # placeholder; LP UART RAM size on P4 needs verification +[device.mcpwm] +support_status = "not_supported" # 2 instances (MCPWM0/1) +[device.pcnt] +support_status = "not_supported" +[device.rgb_display] +support_status = "not_supported" # LCD path of LCD_CAM block +# [device.rmt] requires ram_start / channel_ram_size / channels config - +# left out until those are mapped from P4 TRM. README row stays blank. +[device.rng] +support_status = "not_supported" # TRNG +apb_cycle_wait_num = 16 # placeholder +[device.lp_timer] +support_status = "not_supported" # RTC Timekeeping +[device.sd_host] +support_status = "not_supported" # SDIO host +[device.sd_slave] +support_status = "not_supported" +[device.sleep] +support_status = "not_supported" # PMU eco5 sleep -- placeholder TODO in esp-hal +[device.spi_slave] +support_status = "not_supported" +[device.temp_sensor] +support_status = "not_supported" # LP_TSENS +[device.touch] +support_status = "not_supported" # LP_TOUCH 14ch +[device.uhci] +support_status = "not_supported" +[device.ulp_riscv] +support_status = "not_supported" # LP-core RISC-V (formerly "swd"/"lp_core") + +[device.aes] +support_status = "not_supported" +has_split_text_registers = true +endianness_configurable = false +dma = true +key_length = { options = [ + { bits = 128, encrypt_mode = 0, decrypt_mode = 4 }, + { bits = 256, encrypt_mode = 2, decrypt_mode = 6 }, +] } + +[device.sha] +support_status = "not_supported" +dma = true +algo = { sha1 = 0, sha224 = 1, sha256 = 2 } + +[device.psram] +extmem_origin = 0x48000000 + +[device.rsa] +support_status = "not_supported" +size_increment = 32 +memory_size_bytes = 384 +# TODO: complete with esp-idf ecc_ll.h and later version of TRM 0.5 + +[device.usb_serial_jtag] + +# ECC: hardware accelerator (eco5+ supported) +[device.ecc] +support_status = "not_supported" + +working_modes = [ + { id = 0, mode = "affine_point_multiplication" }, + { id = 2, mode = "affine_point_verification" }, + { id = 3, mode = "affine_point_verification_and_multiplication" }, + { id = 4, mode = "jacobian_point_multiplication" }, + { id = 5, mode = "affine_point_addition" }, + { id = 6, mode = "jacobian_point_verification" }, + { id = 7, mode = "affine_point_verification_and_jacobian_point_multiplication" }, + { id = 8, mode = "modular_addition" }, +] +curves = [ + { id = 0, curve = 192 }, + { id = 1, curve = 256 }, + { id = 2, curve = 384 }, +] +separate_jacobian_point_memory = true + +[device.gpio] +support_status = "partial" +has_bank_1 = true +separate_in_out_interrupts = true +gpio_function = 1 +constant_0_input = 0x3E +constant_1_input = 0x3F +input_signals = [ + { name = "SD_CARD_CCMD_2", id = 1 }, + { name = "SD_CARD_CDATA0_2", id = 2 }, + { name = "SD_CARD_CDATA1_2", id = 3 }, + { name = "SD_CARD_CDATA2_2", id = 4 }, + { name = "SD_CARD_CDATA3_2", id = 5 }, + { name = "SD_CARD_CDATA4_2", id = 6 }, + { name = "SD_CARD_CDATA5_2", id = 7 }, + { name = "SD_CARD_CDATA6_2", id = 8 }, + { name = "SD_CARD_CDATA7_2", id = 9 }, + { name = "UART0_RXD", id = 10 }, + { name = "UART0_CTS", id = 11 }, + { name = "UART0_DSR", id = 12 }, + { name = "UART1_RXD", id = 13 }, + { name = "UART1_CTS", id = 14 }, + { name = "UART1_DSR", id = 15 }, + { name = "UART2_RXD", id = 16 }, + { name = "UART2_CTS", id = 17 }, + { name = "UART2_DSR", id = 18 }, + { name = "UART3_RXD", id = 19 }, + { name = "UART3_CTS", id = 20 }, + { name = "UART3_DSR", id = 21 }, + { name = "UART4_RXD", id = 22 }, + { name = "UART4_CTS", id = 23 }, + { name = "UART4_DSR", id = 24 }, + { name = "I2S0_O_BCK", id = 25 }, + { name = "I2S0_MCLK", id = 26 }, + { name = "I2S0_O_WS", id = 27 }, + { name = "I2S0_I_SD", id = 28 }, + { name = "I2S0_I_BCK", id = 29 }, + { name = "I2S0_I_WS", id = 30 }, + { name = "I2S1_O_BCK", id = 31 }, + { name = "I2S1_MCLK", id = 32 }, + { name = "I2S1_O_WS", id = 33 }, + { name = "I2S1_I_SD", id = 34 }, + { name = "I2S1_I_BCK", id = 35 }, + { name = "I2S1_I_WS", id = 36 }, + { name = "I2S2_O_BCK", id = 37 }, + { name = "I2S2_MCLK", id = 38 }, + { name = "I2S2_O_WS", id = 39 }, + { name = "I2S2_I_SD", id = 40 }, + { name = "I2S2_I_BCK", id = 41 }, + { name = "I2S2_I_WS", id = 42 }, + { name = "I2S0_I_SD1", id = 43 }, + { name = "I2S0_I_SD2", id = 44 }, + { name = "I2S0_I_SD3", id = 45 }, + { name = "SPI3_CK", id = 47 }, + { name = "SPI3_Q", id = 48 }, + { name = "SPI3_D", id = 49 }, + { name = "SPI3_HOLD", id = 50 }, + { name = "SPI3_WP", id = 51 }, + { name = "SPI3_CS", id = 52 }, + { name = "SPI2_CK", id = 53 }, + { name = "SPI2_Q", id = 54 }, + { name = "SPI2_D", id = 55 }, + { name = "SPI2_HOLD", id = 56 }, + { name = "SPI2_WP", id = 57 }, + { name = "SPI2_IO4", id = 58 }, + { name = "SPI2_IO5", id = 59 }, + { name = "SPI2_IO6", id = 60 }, + { name = "SPI2_IO7", id = 61 }, + { name = "SPI2_CS", id = 62 }, + { name = "I2C0_SCL", id = 68 }, + { name = "I2C0_SDA", id = 69 }, + { name = "I2C1_SCL", id = 70 }, + { name = "I2C1_SDA", id = 71 }, + { name = "UART0_SLP_CLK", id = 74 }, + { name = "UART1_SLP_CLK", id = 75 }, + { name = "UART2_SLP_CLK", id = 76 }, + { name = "UART3_SLP_CLK", id = 77 }, + { name = "UART4_SLP_CLK", id = 78 }, + { name = "TWAI0_RX", id = 80 }, + { name = "TWAI1_RX", id = 83 }, + { name = "TWAI2_RX", id = 86 }, + { name = "PWM0_SYNC0", id = 89 }, + { name = "PWM0_SYNC1", id = 90 }, + { name = "PWM0_SYNC2", id = 91 }, + { name = "PWM0_F0", id = 92 }, + { name = "PWM0_F1", id = 93 }, + { name = "PWM0_F2", id = 94 }, + { name = "PWM0_CAP0", id = 95 }, + { name = "PWM0_CAP1", id = 96 }, + { name = "PWM0_CAP2", id = 97 }, + { name = "PWM1_SYNC0", id = 98 }, + { name = "PWM1_SYNC1", id = 99 }, + { name = "PWM1_SYNC2", id = 100 }, + { name = "PWM1_F0", id = 101 }, + { name = "PWM1_F1", id = 102 }, + { name = "PWM1_F2", id = 103 }, + { name = "PWM1_CAP0", id = 104 }, + { name = "PWM1_CAP1", id = 105 }, + { name = "PWM1_CAP2", id = 106 }, + { name = "MII_MDI", id = 107 }, + { name = "EMAC_PHY_COL", id = 108 }, + { name = "EMAC_PHY_CRS", id = 109 }, + { name = "USB_OTG11_IDDIG", id = 110 }, + { name = "USB_OTG11_AVALID", id = 111 }, + { name = "USB_SRP_BVALID", id = 112 }, + { name = "USB_OTG11_VBUSVALID", id = 113 }, + { name = "USB_SRP_SESSEND", id = 114 }, + { name = "ULPI_CLK", id = 117 }, + { name = "USB_HSPHY_REFCLK", id = 118 }, + { name = "SD_CARD_DETECT_N_1", id = 126 }, + { name = "SD_CARD_DETECT_N_2", id = 127 }, + { name = "SD_CARD_INT_N_1", id = 128 }, + { name = "SD_CARD_INT_N_2", id = 129 }, + { name = "SD_CARD_WRITE_PRT_1", id = 130 }, + { name = "SD_CARD_WRITE_PRT_2", id = 131 }, + { name = "SD_DATA_STROBE_1", id = 132 }, + { name = "SD_DATA_STROBE_2", id = 133 }, + { name = "I3C_MST_SCL", id = 134 }, + { name = "I3C_MST_SDA", id = 135 }, + { name = "I3C_SLV_SCL", id = 136 }, + { name = "I3C_SLV_SDA", id = 137 }, + { name = "USB_JTAG_TDO_BRIDGE", id = 140 }, + { name = "CAM_PCLK", id = 158 }, + { name = "CAM_H_ENABLE", id = 159 }, + { name = "CAM_H_SYNC", id = 160 }, + { name = "CAM_V_SYNC", id = 161 }, + { name = "EMAC_PHY_RXDV", id = 178 }, + { name = "EMAC_PHY_RXD0", id = 179 }, + { name = "EMAC_PHY_RXD1", id = 180 }, + { name = "EMAC_PHY_RXD2", id = 181 }, + { name = "EMAC_PHY_RXD3", id = 182 }, + { name = "EMAC_PHY_RXER", id = 183 }, + { name = "EMAC_RX_CLK", id = 184 }, + { name = "EMAC_TX_CLK", id = 185 }, + { name = "PARLIO_RX_CLK", id = 186 }, + { name = "PARLIO_TX_CLK", id = 187 }, + { name = "PARLIO_RX_DATA0", id = 188 }, + { name = "PARLIO_RX_DATA1", id = 189 }, + { name = "PARLIO_RX_DATA2", id = 190 }, + { name = "PARLIO_RX_DATA3", id = 191 }, + { name = "PARLIO_RX_DATA4", id = 192 }, + { name = "PARLIO_RX_DATA5", id = 193 }, + { name = "PARLIO_RX_DATA6", id = 194 }, + { name = "PARLIO_RX_DATA7", id = 195 }, + { name = "PARLIO_RX_DATA8", id = 196 }, + { name = "PARLIO_RX_DATA9", id = 197 }, + { name = "PARLIO_RX_DATA10", id = 198 }, + { name = "PARLIO_RX_DATA11", id = 199 }, + { name = "PARLIO_RX_DATA12", id = 200 }, + { name = "PARLIO_RX_DATA13", id = 201 }, + { name = "PARLIO_RX_DATA14", id = 202 }, + { name = "PARLIO_RX_DATA15", id = 203 }, + { name = "MTCK" }, + { name = "MTDI" }, + { name = "MTMS" }, + { name = "MTDO" }, + { name = "SD1_CDATA0" }, + { name = "SD1_CDATA1" }, + { name = "SD1_CDATA2" }, + { name = "SD1_CDATA3" }, + { name = "SD1_CCLK" }, + { name = "SD1_CCMD" }, + { name = "SD1_CDATA4" }, + { name = "SD1_CDATA5" }, + { name = "SD1_CDATA6" }, + { name = "SD1_CDATA7" }, + { name = "EMAC_RMII_CLK" }, + { name = "REF_50M_CLK" }, + { name = "BIST" }, + { name = "DBG_PSRAM_CK" }, + { name = "DBG_PSRAM_CS" }, + { name = "DBG_PSRAM_D" }, + { name = "DBG_PSRAM_Q" }, + { name = "DBG_PSRAM_WP" }, + { name = "DBG_PSRAM_HOLD" }, + { name = "DBG_PSRAM_DQ4" }, + { name = "DBG_PSRAM_DQ5" }, + { name = "DBG_PSRAM_DQ6" }, + { name = "DBG_PSRAM_DQ7" }, + { name = "DBG_PSRAM_DQS_0" }, + { name = "DBG_PSRAM_DQ8" }, + { name = "DBG_PSRAM_DQ9" }, + { name = "DBG_PSRAM_DQ10" }, + { name = "DBG_PSRAM_DQ11" }, + { name = "DBG_PSRAM_DQ12" }, + { name = "DBG_PSRAM_DQ13" }, + { name = "DBG_PSRAM_DQ14" }, + { name = "DBG_PSRAM_DQ15" }, + { name = "DBG_PSRAM_DQS_1" }, + { name = "DBG_FLASH_CS" }, + { name = "DBG_FLASH_Q" }, + { name = "DBG_FLASH_WP" }, + { name = "DBG_FLASH_HOLD" }, + { name = "DBG_FLASH_CK" }, + { name = "DBG_FLASH_D" }, + { name = "SPI2_DQS" }, +] + +output_signals = [ + { name = "SD_CARD_CCLK_2", id = 0 }, + { name = "SD_CARD_CCMD_2", id = 1 }, + { name = "SD_CARD_CDATA0_2", id = 2 }, + { name = "SD_CARD_CDATA1_2", id = 3 }, + { name = "SD_CARD_CDATA2_2", id = 4 }, + { name = "SD_CARD_CDATA3_2", id = 5 }, + { name = "SD_CARD_CDATA4_2", id = 6 }, + { name = "SD_CARD_CDATA5_2", id = 7 }, + { name = "SD_CARD_CDATA6_2", id = 8 }, + { name = "SD_CARD_CDATA7_2", id = 9 }, + { name = "UART0_TXD", id = 10 }, + { name = "UART0_RTS", id = 11 }, + { name = "UART0_DTR", id = 12 }, + { name = "UART1_TXD", id = 13 }, + { name = "UART1_RTS", id = 14 }, + { name = "UART1_DTR", id = 15 }, + { name = "UART2_TXD", id = 16 }, + { name = "UART2_RTS", id = 17 }, + { name = "UART2_DTR", id = 18 }, + { name = "UART3_TXD", id = 19 }, + { name = "UART3_RTS", id = 20 }, + { name = "UART3_DTR", id = 21 }, + { name = "UART4_TXD", id = 22 }, + { name = "UART4_RTS", id = 23 }, + { name = "UART4_DTR", id = 24 }, + { name = "I2S0_O_BCK", id = 25 }, + { name = "I2S0_MCLK", id = 26 }, + { name = "I2S0_O_WS", id = 27 }, + { name = "I2S0_O_SD", id = 28 }, + { name = "I2S0_I_BCK", id = 29 }, + { name = "I2S0_I_WS", id = 30 }, + { name = "I2S1_O_BCK", id = 31 }, + { name = "I2S1_MCLK", id = 32 }, + { name = "I2S1_O_WS", id = 33 }, + { name = "I2S1_O_SD", id = 34 }, + { name = "I2S1_I_BCK", id = 35 }, + { name = "I2S1_I_WS", id = 36 }, + { name = "I2S2_O_BCK", id = 37 }, + { name = "I2S2_MCLK", id = 38 }, + { name = "I2S2_O_WS", id = 39 }, + { name = "I2S2_O_SD", id = 40 }, + { name = "I2S2_I_BCK", id = 41 }, + { name = "I2S2_I_WS", id = 42 }, + { name = "I2S0_O_SD1", id = 43 }, + { name = "SPI2_DQS", id = 44 }, + { name = "SPI3_CS2", id = 45 }, + { name = "SPI3_CS1", id = 46 }, + { name = "SPI3_CK", id = 47 }, + { name = "SPI3_Q", id = 48 }, # PAC: SPI3_QO_PAD_OUT_IDX, renamed to match input signal + { name = "SPI3_D", id = 49 }, + { name = "SPI3_HOLD", id = 50 }, + { name = "SPI3_WP", id = 51 }, + { name = "SPI3_CS", id = 52 }, + { name = "SPI2_CK", id = 53 }, + { name = "SPI2_Q", id = 54 }, + { name = "SPI2_D", id = 55 }, + { name = "SPI2_HOLD", id = 56 }, + { name = "SPI2_WP", id = 57 }, + { name = "SPI2_IO4", id = 58 }, + { name = "SPI2_IO5", id = 59 }, + { name = "SPI2_IO6", id = 60 }, + { name = "SPI2_IO7", id = 61 }, + { name = "SPI2_CS", id = 62 }, + { name = "SPI2_CS1", id = 63 }, + { name = "SPI2_CS2", id = 64 }, + { name = "SPI2_CS3", id = 65 }, + { name = "SPI2_CS4", id = 66 }, + { name = "SPI2_CS5", id = 67 }, + { name = "I2C0_SCL", id = 68 }, + { name = "I2C0_SDA", id = 69 }, + { name = "I2C1_SCL", id = 70 }, + { name = "I2C1_SDA", id = 71 }, + { name = "GPIO_SD0", id = 72 }, + { name = "GPIO_SD1", id = 73 }, + { name = "GPIO_SD2", id = 74 }, + { name = "GPIO_SD3", id = 75 }, + { name = "GPIO_SD4", id = 76 }, + { name = "GPIO_SD5", id = 77 }, + { name = "GPIO_SD6", id = 78 }, + { name = "GPIO_SD7", id = 79 }, + { name = "TWAI0_TX", id = 80 }, + { name = "TWAI0_BUS_OFF_ON", id = 81 }, + { name = "TWAI0_CLKOUT", id = 82 }, + { name = "TWAI1_TX", id = 83 }, + { name = "TWAI1_BUS_OFF_ON", id = 84 }, + { name = "TWAI1_CLKOUT", id = 85 }, + { name = "TWAI2_TX", id = 86 }, + { name = "TWAI2_BUS_OFF_ON", id = 87 }, + { name = "TWAI2_CLKOUT", id = 88 }, + { name = "PWM0_CH0_A", id = 89 }, + { name = "PWM0_CH0_B", id = 90 }, + { name = "PWM0_CH1_A", id = 91 }, + { name = "PWM0_CH1_B", id = 92 }, + { name = "PWM0_CH2_A", id = 93 }, + { name = "PWM0_CH2_B", id = 94 }, + { name = "PWM1_CH0_A", id = 95 }, + { name = "PWM1_CH0_B", id = 96 }, + { name = "PWM1_CH1_A", id = 97 }, + { name = "PWM1_CH1_B", id = 98 }, + { name = "PWM1_CH2_A", id = 99 }, + { name = "PWM1_CH2_B", id = 100 }, + { name = "TWAI0_STANDBY", id = 105 }, + { name = "TWAI1_STANDBY", id = 106 }, + { name = "TWAI2_STANDBY", id = 107 }, + { name = "MII_MDC", id = 108 }, + { name = "MII_MDO", id = 109 }, + { name = "USB_SRP_DISCHRGVBUS", id = 110 }, + { name = "USB_OTG11_IDPULLUP", id = 111 }, + { name = "USB_OTG11_DPPULLDOWN", id = 112 }, + { name = "USB_OTG11_DMPULLDOWN", id = 113 }, + { name = "USB_OTG11_DRVVBUS", id = 114 }, + { name = "USB_SRP_CHRGVBUS", id = 115 }, + { name = "RNG_CHAIN_CLK", id = 117 }, + { name = "I3C_MST_SCL", id = 134 }, + { name = "I3C_MST_SDA", id = 135 }, + { name = "I3C_SLV_SCL", id = 136 }, + { name = "I3C_SLV_SDA", id = 137 }, + { name = "I3C_MST_SCL_PULLUP_EN", id = 138 }, + { name = "I3C_MST_SDA_PULLUP_EN", id = 139 }, + { name = "USB_JTAG_TDI_BRIDGE", id = 140 }, + { name = "USB_JTAG_TMS_BRIDGE", id = 141 }, + { name = "USB_JTAG_TCK_BRIDGE", id = 142 }, + { name = "USB_JTAG_TRST_BRIDGE", id = 143 }, + { name = "LCD_CS", id = 144 }, + { name = "LCD_DC", id = 145 }, + { name = "SD_RST_N_1", id = 146 }, + { name = "SD_RST_N_2", id = 147 }, + { name = "SD_CCMD_OD_PULLUP_EN_N", id = 148 }, + { name = "LCD_PCLK", id = 149 }, + { name = "CAM_CLK", id = 150 }, + { name = "LCD_H_ENABLE", id = 151 }, + { name = "LCD_H_SYNC", id = 152 }, + { name = "LCD_V_SYNC", id = 153 }, + { name = "EMAC_PHY_TXEN", id = 178 }, + { name = "EMAC_PHY_TXD0", id = 179 }, + { name = "EMAC_PHY_TXD1", id = 180 }, + { name = "EMAC_PHY_TXD2", id = 181 }, + { name = "EMAC_PHY_TXD3", id = 182 }, + { name = "EMAC_PHY_TXER", id = 183 }, + { name = "PARLIO_RX_CLK", id = 186 }, + { name = "PARLIO_TX_CLK", id = 187 }, + { name = "PARLIO_TX_DATA0", id = 188 }, + { name = "PARLIO_TX_DATA1", id = 189 }, + { name = "PARLIO_TX_DATA2", id = 190 }, + { name = "PARLIO_TX_DATA3", id = 191 }, + { name = "PARLIO_TX_DATA4", id = 192 }, + { name = "PARLIO_TX_DATA5", id = 193 }, + { name = "PARLIO_TX_DATA6", id = 194 }, + { name = "PARLIO_TX_DATA7", id = 195 }, + { name = "PARLIO_TX_DATA8", id = 196 }, + { name = "PARLIO_TX_DATA9", id = 197 }, + { name = "PARLIO_TX_DATA10", id = 198 }, + { name = "PARLIO_TX_DATA11", id = 199 }, + { name = "PARLIO_TX_DATA12", id = 200 }, + { name = "PARLIO_TX_DATA13", id = 201 }, + { name = "PARLIO_TX_DATA14", id = 202 }, + { name = "PARLIO_TX_DATA15", id = 203 }, + { name = "CONSTANT0", id = 212 }, + { name = "CONSTANT1", id = 213 }, + { name = "PARLIO_TX_CS", id = 242 }, + { name = "EMAC_PTP_PPS", id = 243 }, + { name = "ANA_COMP0", id = 244 }, + { name = "ANA_COMP1", id = 245 }, + { name = "GPIO", id = 256 }, + { name = "MTCK" }, + { name = "MTDI" }, + { name = "MTMS" }, + { name = "MTDO" }, + { name = "SD1_CDATA0" }, + { name = "SD1_CDATA1" }, + { name = "SD1_CDATA2" }, + { name = "SD1_CDATA3" }, + { name = "SD1_CCLK" }, + { name = "SD1_CCMD" }, + { name = "SD1_CDATA4" }, + { name = "SD1_CDATA5" }, + { name = "SD1_CDATA6" }, + { name = "SD1_CDATA7" }, + { name = "EMAC_RMII_CLK" }, + { name = "REF_50M_CLK" }, + { name = "BIST" }, + { name = "DBG_PSRAM_CK" }, + { name = "DBG_PSRAM_CS" }, + { name = "DBG_PSRAM_D" }, + { name = "DBG_PSRAM_Q" }, + { name = "DBG_PSRAM_WP" }, + { name = "DBG_PSRAM_HOLD" }, + { name = "DBG_PSRAM_DQ4" }, + { name = "DBG_PSRAM_DQ5" }, + { name = "DBG_PSRAM_DQ6" }, + { name = "DBG_PSRAM_DQ7" }, + { name = "DBG_PSRAM_DQS_0" }, + { name = "DBG_PSRAM_DQ8" }, + { name = "DBG_PSRAM_DQ9" }, + { name = "DBG_PSRAM_DQ10" }, + { name = "DBG_PSRAM_DQ11" }, + { name = "DBG_PSRAM_DQ12" }, + { name = "DBG_PSRAM_DQ13" }, + { name = "DBG_PSRAM_DQ14" }, + { name = "DBG_PSRAM_DQ15" }, + { name = "DBG_PSRAM_DQS_1" }, + { name = "DBG_FLASH_CS" }, + { name = "DBG_FLASH_Q" }, + { name = "DBG_FLASH_WP" }, + { name = "DBG_FLASH_HOLD" }, + { name = "DBG_FLASH_CK" }, + { name = "DBG_FLASH_D" }, +] + +# 55 GPIO pins (0-54) +# LP pins: GPIO0-5, GPIO12-23 (RTCIO capable) +pins = [ + { pin = 0, lp = { 0 = "LP_GPIO0" } }, + { pin = 1, lp = { 0 = "LP_GPIO1" } }, + { pin = 2, functions = { 0 = "MTCK", lp = { 0 = "LP_GPIO2" } }, limitations = ["jtag"] }, + { pin = 3, functions = { 0 = "MTDI", lp = { 0 = "LP_GPIO3" } }, limitations = ["jtag"] }, + { pin = 4, functions = { 0 = "MTMS", lp = { 0 = "LP_GPIO4" } }, limitations = ["jtag"] }, + { pin = 5, functions = { 0 = "MTDO", lp = { 0 = "LP_GPIO5" } }, limitations = ["jtag"] }, + { pin = 6, functions = { 3 = "SPI2_HOLD" } }, + { pin = 7, functions = { 3 = "SPI2_CS" } }, + { pin = 8, functions = { 2 = "UART0_RTS", 3 = "SPI2_D" } }, + { pin = 9, functions = { 2 = "UART0_CTS", 3 = "SPI2_CK" } }, + { pin = 10, functions = { 2 = "UART1_TXD", 3 = "SPI2_Q" } }, + { pin = 11, functions = { 2 = "UART1_RXD", 3 = "SPI2_WP" } }, + { pin = 12, functions = { 2 = "UART1_RTS", lp = { 0 = "LP_GPIO12" } } }, + { pin = 13, functions = { 2 = "UART1_CTS", lp = { 0 = "LP_GPIO13" } } }, + { pin = 14, lp = { 0 = "LP_GPIO14" } }, + { pin = 15, lp = { 0 = "LP_GPIO15" } }, + { pin = 16, analog = { 1 = "ADC1_CH0", lp = { 0 = "LP_GPIO16" } } }, + { pin = 17, analog = { 1 = "ADC1_CH1", lp = { 0 = "LP_GPIO17" } } }, + { pin = 18, analog = { 1 = "ADC1_CH2", lp = { 0 = "LP_GPIO18" } } }, + { pin = 19, analog = { 1 = "ADC1_CH3", lp = { 0 = "LP_GPIO19" } } }, + { pin = 20, analog = { 1 = "ADC1_CH4", lp = { 0 = "LP_GPIO20" } } }, + { pin = 21, analog = { 1 = "ADC1_CH5", lp = { 0 = "LP_GPIO21" } } }, + { pin = 22, functions = { 4 = "DBG_PSRAM_CK", lp = { 0 = "LP_GPIO22" } }, analog = { 1 = "ADC1_CH6" } }, + { pin = 23, functions = { 3 = "REF_50M_CLK", 4 = "DBG_PSRAM_CS", lp = { 0 = "LP_GPIO23" } }, analog = { 1 = "ADC1_CH7" } }, + # Pins 24/25 are the default USB-Serial/JTAG pair (PHY0). Use the canonical + # `USB_DM`/`USB_DP` names so `disable_usb_pads!` (see esp-hal gpio/mod.rs) + # and the `UsbJtag` pin-limitation auto-derive pick them up like on every + # other chip. `usb_jtag` limitation is set automatically via the names. + { pin = 24, analog = { 0 = "USB_DM" } }, + { pin = 25, analog = { 0 = "USB_DP" } }, + # Pins 26/27 are the USB OTG FS (PHY1) pair. Kept under the PHY1 names + # until the P4 OTG FS driver lands -- at that point consider whether to + # rename to USB_DM/USB_DP so the same helpers fire here too. + { pin = 26, limitations = ["usb_jtag"], analog = { 0 = "USB_PHY1_DM" } }, + { pin = 27, limitations = ["usb_jtag"], analog = { 0 = "USB_PHY1_DP" } }, + { pin = 28, functions = { 2 = "SPI2_CS", 3 = "EMAC_PHY_RXDV", 4 = "DBG_PSRAM_D" } }, + { pin = 29, functions = { 2 = "SPI2_D", 3 = "EMAC_PHY_RXD0", 4 = "DBG_PSRAM_Q" } }, + { pin = 30, functions = { 2 = "SPI2_CK", 3 = "EMAC_PHY_RXD1", 4 = "DBG_PSRAM_WP" } }, + { pin = 31, functions = { 2 = "SPI2_Q", 3 = "EMAC_PHY_RXER", 4 = "DBG_PSRAM_HOLD" } }, + { pin = 32, functions = { 2 = "SPI2_HOLD", 3 = "EMAC_RMII_CLK", 4 = "DBG_PSRAM_DQ4" }, limitations = ["strapping"] }, + { pin = 33, functions = { 2 = "SPI2_WP", 3 = "EMAC_PHY_TXEN", 4 = "DBG_PSRAM_DQ5" }, limitations = ["strapping"] }, + { pin = 34, functions = { 2 = "SPI2_IO4", 3 = "EMAC_PHY_TXD0", 4 = "DBG_PSRAM_DQ6" }, limitations = ["strapping"] }, + { pin = 35, functions = { 2 = "SPI2_IO5", 3 = "EMAC_PHY_TXD1", 4 = "DBG_PSRAM_DQ7" }, limitations = ["strapping"] }, + { pin = 36, functions = { 2 = "SPI2_IO6", 3 = "EMAC_PHY_TXER", 4 = "DBG_PSRAM_DQS_0" }, limitations = ["strapping"] }, + { pin = 37, functions = { 0 = "UART0_TXD", 2 = "SPI2_IO7" }, limitations = ["strapping"] }, + { pin = 38, functions = { 0 = "UART0_RXD", 2 = "SPI2_DQS" }, limitations = ["strapping"] }, + { pin = 39, functions = { 0 = "SD1_CDATA0", 2 = "BIST", 3 = "REF_50M_CLK", 4 = "DBG_PSRAM_DQ8" } }, + { pin = 40, functions = { 0 = "SD1_CDATA1", 2 = "BIST", 3 = "EMAC_PHY_TXEN", 4 = "DBG_PSRAM_DQ9" } }, + { pin = 41, functions = { 0 = "SD1_CDATA2", 2 = "BIST", 3 = "EMAC_PHY_TXD0", 4 = "DBG_PSRAM_DQ10" } }, + { pin = 42, functions = { 0 = "SD1_CDATA3", 2 = "BIST", 3 = "EMAC_PHY_TXD1", 4 = "DBG_PSRAM_DQ11" } }, + { pin = 43, functions = { 0 = "SD1_CCLK", 2 = "BIST", 3 = "EMAC_PHY_TXER", 4 = "DBG_PSRAM_DQ12" } }, + { pin = 44, functions = { 0 = "SD1_CCMD", 2 = "BIST", 3 = "EMAC_RMII_CLK", 4 = "DBG_PSRAM_DQ13" } }, + { pin = 45, functions = { 0 = "SD1_CDATA4", 2 = "BIST", 3 = "EMAC_PHY_RXDV", 4 = "DBG_PSRAM_DQ14" } }, + { pin = 46, functions = { 0 = "SD1_CDATA5", 2 = "BIST", 3 = "EMAC_PHY_RXD0", 4 = "DBG_PSRAM_DQ15" } }, + { pin = 47, functions = { 0 = "SD1_CDATA6", 2 = "BIST", 3 = "EMAC_PHY_RXD1", 4 = "DBG_PSRAM_DQS_1" } }, + { pin = 48, functions = { 0 = "SD1_CDATA7", 2 = "BIST", 3 = "EMAC_PHY_RXER" } }, + { pin = 49, functions = { 3 = "EMAC_PHY_TXEN", 4 = "DBG_FLASH_CS" }, analog = { 1 = "ADC2_CH0" } }, + { pin = 50, functions = { 3 = "EMAC_RMII_CLK", 4 = "DBG_FLASH_Q" }, analog = { 1 = "ADC2_CH1" } }, + { pin = 51, functions = { 3 = "EMAC_PHY_RXDV", 4 = "DBG_FLASH_WP" }, analog = { 1 = "ADC2_CH2" } }, + { pin = 52, functions = { 3 = "EMAC_PHY_RXD0", 4 = "DBG_FLASH_HOLD" }, analog = { 1 = "ADC2_CH3" } }, + { pin = 53, functions = { 3 = "EMAC_PHY_RXD1", 4 = "DBG_FLASH_CK" }, analog = { 1 = "ADC2_CH4" } }, + { pin = 54, functions = { 3 = "EMAC_PHY_RXER", 4 = "DBG_FLASH_D" }, analog = { 1 = "ADC2_CH5" } }, +] diff --git a/esp-metadata/src/lib.rs b/esp-metadata/src/lib.rs index f9d8d369834..212cbbf629c 100644 --- a/esp-metadata/src/lib.rs +++ b/esp-metadata/src/lib.rs @@ -123,6 +123,8 @@ pub enum Chip { Esp32c61, /// ESP32-H2 Esp32h2, + /// ESP32-P4 (chip revision v3.x / eco5 only) + Esp32p4, /// ESP32-S2 Esp32s2, /// ESP32-S3 @@ -183,6 +185,7 @@ impl Chip { Chip::Esp32c6 => "Esp32c6", Chip::Esp32c61 => "Esp32c61", Chip::Esp32h2 => "Esp32h2", + Chip::Esp32p4 => "Esp32p4", Chip::Esp32s2 => "Esp32s2", Chip::Esp32s3 => "Esp32s3", } @@ -197,6 +200,7 @@ impl Chip { Chip::Esp32c6 => "ESP32-C6", Chip::Esp32c61 => "ESP32-C61", Chip::Esp32h2 => "ESP32-H2", + Chip::Esp32p4 => "ESP32-P4", Chip::Esp32s2 => "ESP32-S2", Chip::Esp32s3 => "ESP32-S3", } @@ -355,6 +359,7 @@ impl Config { Chip::Esp32c6 => include_toml!(Config, "../devices/esp32c6.toml"), Chip::Esp32c61 => include_toml!(Config, "../devices/esp32c61.toml"), Chip::Esp32h2 => include_toml!(Config, "../devices/esp32h2.toml"), + Chip::Esp32p4 => include_toml!(Config, "../devices/esp32p4.toml"), Chip::Esp32s2 => include_toml!(Config, "../devices/esp32s2.toml"), Chip::Esp32s3 => include_toml!(Config, "../devices/esp32s3.toml"), } diff --git a/esp-println/CHANGELOG.md b/esp-println/CHANGELOG.md index fec3ea0daf6..112e746d745 100644 --- a/esp-println/CHANGELOG.md +++ b/esp-println/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Initial ESP32-P4 (chip revision v3.0+) support (#5400) ### Changed diff --git a/esp-println/Cargo.toml b/esp-println/Cargo.toml index 97dbb216574..572a8a4cf75 100644 --- a/esp-println/Cargo.toml +++ b/esp-println/Cargo.toml @@ -62,6 +62,7 @@ esp32c5 = ["esp-metadata-generated/esp32c5", "esp-sync?/esp32c5"] esp32c6 = ["esp-metadata-generated/esp32c6", "esp-sync?/esp32c6"] esp32c61 = ["esp-metadata-generated/esp32c61", "esp-sync?/esp32c61"] esp32h2 = ["esp-metadata-generated/esp32h2", "esp-sync?/esp32h2"] +esp32p4 = ["esp-metadata-generated/esp32p4", "esp-sync?/esp32p4"] esp32s2 = ["esp-metadata-generated/esp32s2", "esp-sync?/esp32s2"] esp32s3 = ["esp-metadata-generated/esp32s3", "esp-sync?/esp32s3"] diff --git a/esp-println/src/lib.rs b/esp-println/src/lib.rs index 33b5ad583a9..e31d23168b4 100644 --- a/esp-println/src/lib.rs +++ b/esp-println/src/lib.rs @@ -151,6 +151,7 @@ type PrinterImpl = noop::Printer; feature = "esp32c6", feature = "esp32c61", feature = "esp32h2", + feature = "esp32p4", feature = "esp32s3" ) ))] @@ -181,6 +182,8 @@ mod auto_printer { const USB_DEVICE_INT_RAW: *const u32 = 0x6000f008 as *const u32; #[cfg(feature = "esp32s3")] const USB_DEVICE_INT_RAW: *const u32 = 0x60038000 as *const u32; + #[cfg(feature = "esp32p4")] + const USB_DEVICE_INT_RAW: *const u32 = 0x500D2008 as *const u32; const SOF_INT_MASK: u32 = 0b10; @@ -213,6 +216,7 @@ mod auto_printer { feature = "esp32c6", feature = "esp32c61", feature = "esp32h2", + feature = "esp32p4", feature = "esp32s3" )) ))] @@ -229,6 +233,7 @@ mod auto_printer { feature = "esp32c6", feature = "esp32c61", feature = "esp32h2", + feature = "esp32p4", feature = "esp32s3" ) ))] @@ -263,6 +268,12 @@ mod serial_jtag_printer { #[cfg(feature = "esp32s3")] const SERIAL_JTAG_CONF_REG: usize = 0x6003_8004; + // ESP32-P4: USB_DEVICE peripheral at 0x500D_2000 per PAC. + #[cfg(feature = "esp32p4")] + const SERIAL_JTAG_FIFO_REG: usize = 0x500D_2000; + #[cfg(feature = "esp32p4")] + const SERIAL_JTAG_CONF_REG: usize = 0x500D_2004; + /// A previous wait has timed out. We use this flag to avoid blocking /// forever if there is no host attached. static TIMED_OUT: AtomicBool = AtomicBool::new(false); @@ -410,6 +421,29 @@ mod uart_printer { struct Device; + // ESP32-P4: resolve through the linker-provided ROM symbol + // (`esp_rom_uart_tx_one_char` -> `uart_tx_one_char2 = 0x4fc0_0058`, + // see esp-rom-sys/ld/esp32p4/rom/esp32p4.rom.api.ld) instead of + // hardcoding the address. Matches the c5/c6/c61/h2 channel-aware path. + #[cfg(feature = "esp32p4")] + impl Functions for Device { + // Unused -- tx_byte() below resolves through the linker. + const TX_ONE_CHAR: usize = 0; + + fn tx_byte(b: u8) { + unsafe extern "C" { + fn esp_rom_uart_tx_one_char(c: u8) -> i32; + } + unsafe { + esp_rom_uart_tx_one_char(b); + } + } + + fn flush() { + // tx_one_char waits for TX FIFO space + } + } + #[cfg(feature = "esp32c2")] impl Functions for Device { const TX_ONE_CHAR: usize = 0x4000_005C; diff --git a/esp-rom-sys/CHANGELOG.md b/esp-rom-sys/CHANGELOG.md index 3332578819c..2a787d81aa5 100644 --- a/esp-rom-sys/CHANGELOG.md +++ b/esp-rom-sys/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- ESP32-P4: replace the pre-ECO5 ROM linker scripts with ECO5+ symbol addresses sourced from ESP-IDF v6.0.1 (#5400) ### Fixed diff --git a/esp-rom-sys/Cargo.toml b/esp-rom-sys/Cargo.toml index 86f53ea16b3..0a2ebc32648 100644 --- a/esp-rom-sys/Cargo.toml +++ b/esp-rom-sys/Cargo.toml @@ -38,6 +38,8 @@ esp32c61 = { version = "0.3", features = ["critical-section"], optional = true } esp32h2 = { version = "0.19", features = ["critical-section"], optional = true } esp32s2 = { version = "0.31", features = ["critical-section"], optional = true } esp32s3 = { version = "0.35", features = ["critical-section"], optional = true } +# ESP32-P4 PAC: git rev fc3e6d4 (see note in esp-hal/Cargo.toml). +esp32p4 = { version = "0.2", features = ["critical-section"], optional = true, git = "https://github.com/esp-rs/esp-pacs", rev = "fc3e6d4" } [build-dependencies] esp-metadata-generated = { version = "0.4.0", path = "../esp-metadata-generated", features = ["build-script"] } @@ -63,6 +65,8 @@ esp32c61 = [ "dep:esp32c61" ] ## esp32h2 = [ "dep:esp32h2" ] ## +esp32p4 = [ "dep:esp32p4" ] +## esp32s2 = [ "dep:esp32s2" ] ## esp32s3 = [ "dep:esp32s3" ] diff --git a/esp-rom-sys/ld/esp32p4/libesp_rom_sys.a b/esp-rom-sys/ld/esp32p4/libesp_rom_sys.a new file mode 100644 index 00000000000..aff08cf6348 --- /dev/null +++ b/esp-rom-sys/ld/esp32p4/libesp_rom_sys.a @@ -0,0 +1 @@ +INCLUDE "rom-functions.x" diff --git a/esp-rom-sys/ld/esp32p4/rom-functions.x b/esp-rom-sys/ld/esp32p4/rom-functions.x new file mode 100644 index 00000000000..02a91bc7deb --- /dev/null +++ b/esp-rom-sys/ld/esp32p4/rom-functions.x @@ -0,0 +1,7 @@ +INCLUDE "rom/esp32p4.rom.api.ld" +INCLUDE "rom/esp32p4.rom.ld" +INCLUDE "rom/esp32p4.rom.libgcc.ld" +INCLUDE "rom/esp32p4.rom.rvfp.ld" +INCLUDE "rom/esp32p4.rom.version.ld" + +INCLUDE "rom/additional.ld" diff --git a/esp-rom-sys/ld/esp32p4/rom/additional.ld b/esp-rom-sys/ld/esp32p4/rom/additional.ld new file mode 100644 index 00000000000..e1181631cd9 --- /dev/null +++ b/esp-rom-sys/ld/esp32p4/rom/additional.ld @@ -0,0 +1,14 @@ +/* Ref: esp-idf esp32p4.rom.libc.ld (eco5) */ +syscall_table_ptr = 0x4ffbffe4; +ets_update_cpu_frequency = 0x4fc00044; +ets_printf = 0x4fc00024; +PROVIDE(ets_delay_us = 0x4fc0003c); + +memset = 0x4fc00268; +memcpy = 0x4fc0026c; +memmove = 0x4fc00270; +memcmp = 0x4fc00274; +strcpy = 0x4fc00278; +strncpy = 0x4fc0027c; +strcmp = 0x4fc00280; +strncmp = 0x4fc00284; diff --git a/esp-rom-sys/ld/esp32p4/rom/esp32p4.rom.api.ld b/esp-rom-sys/ld/esp32p4/rom/esp32p4.rom.api.ld new file mode 100644 index 00000000000..77409b31985 --- /dev/null +++ b/esp-rom-sys/ld/esp32p4/rom/esp32p4.rom.api.ld @@ -0,0 +1,67 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +/** ROM APIs + */ + +PROVIDE ( esp_rom_crc32_le = crc32_le ); +PROVIDE ( esp_rom_crc16_le = crc16_le ); +PROVIDE ( esp_rom_crc8_le = crc8_le ); +PROVIDE ( esp_rom_crc32_be = crc32_be ); +PROVIDE ( esp_rom_crc16_be = crc16_be ); +PROVIDE ( esp_rom_crc8_be = crc8_be ); + +PROVIDE ( esp_rom_gpio_pad_select_gpio = gpio_pad_select_gpio ); +PROVIDE ( esp_rom_gpio_pad_pullup_only = gpio_pad_pullup ); +PROVIDE ( esp_rom_gpio_pad_set_drv = gpio_pad_set_drv ); +PROVIDE ( esp_rom_gpio_pad_unhold = gpio_pad_unhold ); +PROVIDE ( esp_rom_gpio_connect_in_signal = gpio_matrix_in ); +PROVIDE ( esp_rom_gpio_connect_out_signal = gpio_matrix_out ); + +PROVIDE ( esp_rom_efuse_mac_address_crc8 = esp_crc8 ); +PROVIDE ( esp_rom_efuse_is_secure_boot_enabled = ets_efuse_secure_boot_enabled ); + +PROVIDE ( esp_rom_uart_flush_tx = uart_tx_flush ); +PROVIDE ( esp_rom_uart_tx_one_char = uart_tx_one_char2 ); +PROVIDE ( esp_rom_uart_tx_wait_idle = uart_tx_wait_idle ); +PROVIDE ( esp_rom_uart_rx_one_char = uart_rx_one_char ); +PROVIDE ( esp_rom_uart_rx_string = UartRxString ); +PROVIDE ( esp_rom_uart_set_as_console = uart_tx_switch ); +PROVIDE ( esp_rom_uart_putc = ets_write_char_uart ); + +PROVIDE ( esp_rom_usb_serial_putc = uart_tx_one_char3 ); + +PROVIDE ( esp_rom_output_flush_tx = uart_tx_flush ); +PROVIDE ( esp_rom_output_tx_one_char = uart_tx_one_char ); +PROVIDE ( esp_rom_output_tx_wait_idle = uart_tx_wait_idle ); +PROVIDE ( esp_rom_output_rx_one_char = uart_rx_one_char ); +PROVIDE ( esp_rom_output_rx_string = UartRxString ); +PROVIDE ( esp_rom_output_set_as_console = uart_tx_switch ); +PROVIDE ( esp_rom_output_putc = ets_write_char_uart ); + +PROVIDE ( esp_rom_md5_init = MD5Init ); +PROVIDE ( esp_rom_md5_update = MD5Update ); +PROVIDE ( esp_rom_md5_final = MD5Final ); + +PROVIDE ( esp_rom_software_reset_system = software_reset ); +PROVIDE ( esp_rom_software_reset_cpu = software_reset_cpu ); + +PROVIDE ( esp_rom_printf = ets_printf ); +PROVIDE ( esp_rom_install_uart_printf = ets_install_uart_printf ); +PROVIDE ( esp_rom_delay_us = ets_delay_us ); +PROVIDE ( esp_rom_get_reset_reason = rtc_get_reset_reason ); +PROVIDE ( esp_rom_route_intr_matrix = intr_matrix_set ); +PROVIDE ( esp_rom_get_cpu_ticks_per_us = ets_get_cpu_frequency ); +PROVIDE ( esp_rom_set_cpu_ticks_per_us = ets_update_cpu_frequency ); + +PROVIDE ( esp_rom_spiflash_attach = spi_flash_attach ); +PROVIDE ( esp_rom_spiflash_clear_bp = esp_rom_spiflash_unlock ); +PROVIDE ( esp_rom_spiflash_write_enable = SPI_write_enable ); +PROVIDE ( esp_rom_spiflash_erase_area = SPIEraseArea ); + +PROVIDE ( esp_rom_spiflash_fix_dummylen = spi_dummy_len_fix ); +PROVIDE ( esp_rom_spiflash_set_drvs = SetSpiDrvs); +PROVIDE ( esp_rom_spiflash_select_padsfunc = SelectSpiFunction ); +PROVIDE ( esp_rom_spiflash_common_cmd = SPI_Common_Command ); diff --git a/esp-rom-sys/ld/esp32p4/rom/esp32p4.rom.ld b/esp-rom-sys/ld/esp32p4/rom/esp32p4.rom.ld new file mode 100644 index 00000000000..46d1f3c012f --- /dev/null +++ b/esp-rom-sys/ld/esp32p4/rom/esp32p4.rom.ld @@ -0,0 +1,592 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +/* ROM function interface esp32p4.rom.ld for esp32p4 + * + * + * Generated from ./target/esp32p4/interface-esp32p4.yml md5sum 56d78222be1daa0502090a078288f4d5 + * + * Compatible with ROM where ECO version equal or greater to 5. + * + * THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT. + */ + +/*************************************** + Group common + ***************************************/ + +/* Functions */ +rtc_get_reset_reason = 0x4fc00018; +rtc_get_wakeup_cause = 0x4fc0001c; +pmu_enable_unhold_pads = 0x4fc00020; +ets_printf = 0x4fc00024; +ets_install_putc1 = 0x4fc00028; +ets_install_putc2 = 0x4fc0002c; +ets_install_uart_printf = 0x4fc00030; +ets_install_usb_printf = 0x4fc00034; +ets_get_printf_channel = 0x4fc00038; +ets_delay_us = 0x4fc0003c; +ets_get_cpu_frequency = 0x4fc00040; +ets_update_cpu_frequency = 0x4fc00044; +ets_install_lock = 0x4fc00048; +UartRxString = 0x4fc0004c; +UartGetCmdLn = 0x4fc00050; +uart_tx_one_char = 0x4fc00054; +uart_tx_one_char2 = 0x4fc00058; +uart_tx_one_char3 = 0x4fc0005c; +uart_rx_one_char = 0x4fc00060; +uart_rx_one_char_block = 0x4fc00064; +uart_rx_intr_handler = 0x4fc00068; +uart_rx_readbuff = 0x4fc0006c; +uartAttach = 0x4fc00070; +uart_tx_flush = 0x4fc00074; +uart_tx_wait_idle = 0x4fc00078; +uart_div_modify = 0x4fc0007c; +ets_write_char_uart = 0x4fc00080; +uart_tx_switch = 0x4fc00084; +uart_buff_switch = 0x4fc00088; +roundup2 = 0x4fc0008c; +multofup = 0x4fc00090; +software_reset = 0x4fc00094; +software_reset_cpu = 0x4fc00098; +ets_clk_assist_debug_clock_enable = 0x4fc0009c; +clear_super_wdt_reset_flag = 0x4fc000a0; +disable_default_watchdog = 0x4fc000a4; +ets_set_appcpu_boot_addr = 0x4fc000a8; +send_packet = 0x4fc000ac; +recv_packet = 0x4fc000b0; +GetUartDevice = 0x4fc000b4; +UartDwnLdProc = 0x4fc000b8; +GetSecurityInfoProc = 0x4fc000bc; +Uart_Init = 0x4fc000c0; +ets_set_user_start = 0x4fc000c4; +/* Data (.data, .bss, .rodata) */ +ets_rom_layout_p = 0x4fc1fffc; +ets_ops_table_ptr = 0x4ffbfff4; +g_saved_pc = 0x4ffbfff8; + + +/*************************************** + Group miniz + ***************************************/ + +/* Functions */ +mz_adler32 = 0x4fc000c8; +mz_free = 0x4fc000cc; +tdefl_compress = 0x4fc000d0; +tdefl_compress_buffer = 0x4fc000d4; +tdefl_compress_mem_to_heap = 0x4fc000d8; +tdefl_compress_mem_to_mem = 0x4fc000dc; +tdefl_compress_mem_to_output = 0x4fc000e0; +tdefl_get_adler32 = 0x4fc000e4; +tdefl_get_prev_return_status = 0x4fc000e8; +tdefl_init = 0x4fc000ec; +tdefl_write_image_to_png_file_in_memory = 0x4fc000f0; +tdefl_write_image_to_png_file_in_memory_ex = 0x4fc000f4; +tinfl_decompress = 0x4fc000f8; +tinfl_decompress_mem_to_callback = 0x4fc000fc; +tinfl_decompress_mem_to_heap = 0x4fc00100; +tinfl_decompress_mem_to_mem = 0x4fc00104; + + +/*************************************** + Group spi_extmem_common + ***************************************/ + +/* Functions */ +esp_rom_spi_cmd_config = 0x4fc00108; +esp_rom_spi_cmd_start = 0x4fc0010c; +esp_rom_spi_set_op_mode = 0x4fc00110; +esp_rom_spi_set_dtr_swap_mode = 0x4fc00114; + + +/*************************************** + Group spiflash_legacy + ***************************************/ + +/* Functions */ +esp_rom_spiflash_wait_idle = 0x4fc00118; +esp_rom_spiflash_write_encrypted = 0x4fc0011c; +esp_rom_spiflash_write_encrypted_dest = 0x4fc00120; +esp_rom_spiflash_write_encrypted_enable = 0x4fc00124; +esp_rom_spiflash_write_encrypted_disable = 0x4fc00128; +esp_rom_spiflash_erase_chip = 0x4fc0012c; +_esp_rom_spiflash_erase_sector = 0x4fc00130; +_esp_rom_spiflash_erase_block = 0x4fc00134; +_esp_rom_spiflash_write = 0x4fc00138; +_esp_rom_spiflash_read = 0x4fc0013c; +_esp_rom_spiflash_unlock = 0x4fc00140; +_SPIEraseArea = 0x4fc00144; +_SPI_write_enable = 0x4fc00148; +esp_rom_spiflash_erase_sector = 0x4fc0014c; +esp_rom_spiflash_erase_block = 0x4fc00150; +esp_rom_spiflash_write = 0x4fc00154; +esp_rom_spiflash_read = 0x4fc00158; +esp_rom_spiflash_unlock = 0x4fc0015c; +SPIEraseArea = 0x4fc00160; +SPI_write_enable = 0x4fc00164; +esp_rom_spiflash_config_param = 0x4fc00168; +esp_rom_spiflash_read_user_cmd = 0x4fc0016c; +esp_rom_spiflash_select_qio_pins = 0x4fc00170; +esp_rom_spi_flash_auto_sus_res = 0x4fc00174; +esp_rom_spi_flash_send_resume = 0x4fc00178; +esp_rom_spi_flash_update_id = 0x4fc0017c; +esp_rom_spiflash_config_clk = 0x4fc00180; +esp_rom_spiflash_config_readmode = 0x4fc00184; +esp_rom_spiflash_read_status = 0x4fc00188; +esp_rom_spiflash_read_statushigh = 0x4fc0018c; +esp_rom_spiflash_write_status = 0x4fc00190; +esp_rom_spiflash_write_disable = 0x4fc00194; +spi_cache_mode_switch = 0x4fc00198; +spi_common_set_dummy_output = 0x4fc0019c; +spi_common_set_flash_cs_timing = 0x4fc001a0; +esp_rom_spi_set_address_bit_len = 0x4fc001a4; +SPILock = 0x4fc001a8; +SPIMasterReadModeCnfig = 0x4fc001ac; +SPI_Common_Command = 0x4fc001b0; +SPI_WakeUp = 0x4fc001b4; +SPI_block_erase = 0x4fc001b8; +SPI_chip_erase = 0x4fc001bc; +SPI_init = 0x4fc001c0; +SPI_page_program = 0x4fc001c4; +SPI_read_data = 0x4fc001c8; +SPI_sector_erase = 0x4fc001cc; +SelectSpiFunction = 0x4fc001d0; +SetSpiDrvs = 0x4fc001d4; +Wait_SPI_Idle = 0x4fc001d8; +spi_dummy_len_fix = 0x4fc001dc; +Disable_QMode = 0x4fc001e0; +Enable_QMode = 0x4fc001e4; +spi_flash_attach = 0x4fc001e8; +spi_flash_get_chip_size = 0x4fc001ec; +spi_flash_guard_set = 0x4fc001f0; +spi_flash_guard_get = 0x4fc001f4; +spi_flash_read_encrypted = 0x4fc001f8; +/* Data (.data, .bss, .rodata) */ +rom_spiflash_legacy_funcs = 0x4ffbffec; +rom_spiflash_legacy_data = 0x4ffbffe8; +g_flash_guard_ops = 0x4ffbfff0; + + +/*************************************** + Group cache + ***************************************/ + +/* Functions */ +Cache_Get_L1_ICache_Line_Size = 0x4fc003c4; +Cache_Get_L1_DCache_Line_Size = 0x4fc003c8; +Cache_Get_L2_Cache_Line_Size = 0x4fc003cc; +Cache_Get_Mode = 0x4fc003d0; +Cache_Set_L2_Cache_Mode = 0x4fc003d4; +Cache_Address_Through_Cache = 0x4fc003d8; +ROM_Boot_Cache_Init = 0x4fc003dc; +Cache_Sync_Addr = 0x4fc003e0; +Cache_Invalidate_Addr = 0x4fc003e4; +Cache_Invalidate_Addr_Gid = 0x4fc003e8; +Cache_Clean_Addr = 0x4fc003ec; +Cache_Clean_Addr_Gid = 0x4fc003f0; +Cache_WriteBack_Addr = 0x4fc003f4; +Cache_WriteBack_Addr_Gid = 0x4fc003f8; +Cache_WriteBack_Invalidate_Addr = 0x4fc003fc; +Cache_WriteBack_Invalidate_Addr_Gid = 0x4fc00400; +Cache_Invalidate_All = 0x4fc00404; +Cache_Invalidate_All_Gid = 0x4fc00408; +Cache_Clean_All = 0x4fc0040c; +Cache_Clean_All_Gid = 0x4fc00410; +Cache_WriteBack_All = 0x4fc00414; +Cache_WriteBack_All_Gid = 0x4fc00418; +Cache_WriteBack_Invalidate_All = 0x4fc0041c; +Cache_WriteBack_Invalidate_All_Gid = 0x4fc00420; +Cache_Mask_All = 0x4fc00424; +Cache_Suspend_L1_CORE0_ICache_Autoload = 0x4fc00428; +Cache_Resume_L1_CORE0_ICache_Autoload = 0x4fc0042c; +Cache_Suspend_L1_CORE1_ICache_Autoload = 0x4fc00430; +Cache_Resume_L1_CORE1_ICache_Autoload = 0x4fc00434; +Cache_Suspend_L1_DCache_Autoload = 0x4fc00438; +Cache_Resume_L1_DCache_Autoload = 0x4fc0043c; +Cache_Suspend_L2_Cache_Autoload = 0x4fc00440; +Cache_Resume_L2_Cache_Autoload = 0x4fc00444; +Cache_Start_L1_CORE0_ICache_Preload = 0x4fc00448; +Cache_L1_CORE0_ICache_Preload_Done = 0x4fc0044c; +Cache_End_L1_CORE0_ICache_Preload = 0x4fc00450; +Cache_Start_L1_CORE1_ICache_Preload = 0x4fc00454; +Cache_L1_CORE1_ICache_Preload_Done = 0x4fc00458; +Cache_End_L1_CORE1_ICache_Preload = 0x4fc0045c; +Cache_Start_L1_DCache_Preload = 0x4fc00460; +Cache_L1_DCache_Preload_Done = 0x4fc00464; +Cache_End_L1_DCache_Preload = 0x4fc00468; +Cache_Start_L2_Cache_Preload = 0x4fc0046c; +Cache_L2_Cache_Preload_Done = 0x4fc00470; +Cache_End_L2_Cache_Preload = 0x4fc00474; +Cache_Config_L1_CORE0_ICache_Autoload = 0x4fc00478; +Cache_Enable_L1_CORE0_ICache_Autoload = 0x4fc0047c; +Cache_Disable_L1_CORE0_ICache_Autoload = 0x4fc00480; +Cache_Config_L1_CORE1_ICache_Autoload = 0x4fc00484; +Cache_Enable_L1_CORE1_ICache_Autoload = 0x4fc00488; +Cache_Disable_L1_CORE1_ICache_Autoload = 0x4fc0048c; +Cache_Config_L1_DCache_Autoload = 0x4fc00490; +Cache_Enable_L1_DCache_Autoload = 0x4fc00494; +Cache_Disable_L1_DCache_Autoload = 0x4fc00498; +Cache_Config_L2_Cache_Autoload = 0x4fc0049c; +Cache_Enable_L2_Cache_Autoload = 0x4fc004a0; +Cache_Disable_L2_Cache_Autoload = 0x4fc004a4; +Cache_Enable_L1_CORE0_ICache_PreLock = 0x4fc004a8; +Cache_Disable_L1_CORE0_ICache_PreLock = 0x4fc004ac; +Cache_Enable_L1_CORE1_ICache_PreLock = 0x4fc004b0; +Cache_Disable_L1_CORE1_ICache_PreLock = 0x4fc004b4; +Cache_Enable_L1_DCache_PreLock = 0x4fc004b8; +Cache_Disable_L1_DCache_PreLock = 0x4fc004bc; +Cache_Enable_L2_Cache_PreLock = 0x4fc004c0; +Cache_Disable_L2_Cache_PreLock = 0x4fc004c4; +Cache_Lock_Addr = 0x4fc004c8; +Cache_Unlock_Addr = 0x4fc004cc; +Cache_Disable_L1_CORE0_ICache = 0x4fc004d0; +Cache_Enable_L1_CORE0_ICache = 0x4fc004d4; +Cache_Suspend_L1_CORE0_ICache = 0x4fc004d8; +Cache_Resume_L1_CORE0_ICache = 0x4fc004dc; +Cache_Disable_L1_CORE1_ICache = 0x4fc004e0; +Cache_Enable_L1_CORE1_ICache = 0x4fc004e4; +Cache_Suspend_L1_CORE1_ICache = 0x4fc004e8; +Cache_Resume_L1_CORE1_ICache = 0x4fc004ec; +Cache_Disable_L1_DCache = 0x4fc004f0; +Cache_Enable_L1_DCache = 0x4fc004f4; +Cache_Suspend_L1_DCache = 0x4fc004f8; +Cache_Resume_L1_DCache = 0x4fc004fc; +Cache_Disable_L2_Cache = 0x4fc00500; +Cache_Enable_L2_Cache = 0x4fc00504; +Cache_Suspend_L2_Cache = 0x4fc00508; +Cache_Resume_L2_Cache = 0x4fc0050c; +Cache_FLASH_MMU_Init = 0x4fc00510; +Cache_PSRAM_MMU_Init = 0x4fc00514; +Cache_FLASH_MMU_Set = 0x4fc00518; +Cache_FLASH_MMU_Set_Secure = 0x4fc0051c; +Cache_PSRAM_MMU_Set = 0x4fc00520; +Cache_PSRAM_MMU_Set_Secure = 0x4fc00524; +Cache_Count_Flash_Pages = 0x4fc00528; +Cache_Flash_To_SPIRAM_Copy = 0x4fc0052c; +Cache_Set_IDROM_MMU_Size = 0x4fc00530; +flash2spiram_instruction_offset = 0x4fc00534; +flash2spiram_rodata_offset = 0x4fc00538; +flash_instr_rodata_start_page = 0x4fc0053c; +flash_instr_rodata_end_page = 0x4fc00540; +Cache_Set_IDROM_MMU_Info = 0x4fc00544; +Cache_Get_IROM_MMU_End = 0x4fc00548; +Cache_Get_DROM_MMU_End = 0x4fc0054c; +/* Data (.data, .bss, .rodata) */ +rom_cache_op_cb = 0x4ffbffdc; +rom_cache_internal_table_ptr = 0x4ffbffd8; + + +/*************************************** + Group clock + ***************************************/ + +/* Functions */ +ets_clk_get_xtal_freq = 0x4fc00550; +ets_clk_get_cpu_freq = 0x4fc00554; + + +/*************************************** + Group gpio + ***************************************/ + +/* Functions */ +rom_gpio_set_output_level = 0x4fc00558; +rom_gpio_get_input_level = 0x4fc0055c; +rom_gpio_matrix_in = 0x4fc00560; +rom_gpio_matrix_out = 0x4fc00564; +rom_gpio_bypass_matrix_in = 0x4fc00568; +rom_gpio_output_disable = 0x4fc0056c; +rom_gpio_output_enable = 0x4fc00570; +rom_gpio_pad_input_disable = 0x4fc00574; +rom_gpio_pad_input_enable = 0x4fc00578; +rom_gpio_pad_pulldown = 0x4fc0057c; +rom_gpio_pad_pullup = 0x4fc00580; +rom_gpio_pad_select_gpio = 0x4fc00584; +rom_gpio_pad_set_drv = 0x4fc00588; +rom_gpio_pad_unhold = 0x4fc0058c; +rom_gpio_pad_hold = 0x4fc00590; +rom_gpio_lppad_select_mux = 0x4fc00594; +rom_gpio_ded_pad_set_drv = 0x4fc00598; +rom_gpio_ded_pad_pullup = 0x4fc0059c; +rom_gpio_ded_pad_pulldown = 0x4fc005a0; +rom_gpio_ded_pad_hold = 0x4fc005a4; +rom_gpio_ded_pad_unhold = 0x4fc005a8; + + +/*************************************** + Group interrupts + ***************************************/ + +/* Functions */ +esprv_intc_int_set_priority = 0x4fc005ac; +esprv_intc_int_set_threshold = 0x4fc005b0; +esprv_intc_int_enable = 0x4fc005b4; +esprv_intc_int_disable = 0x4fc005b8; +esprv_intc_int_set_type = 0x4fc005bc; +PROVIDE( intr_handler_set = 0x4fc005c0 ); +intr_matrix_set = 0x4fc005c4; +ets_intr_lock = 0x4fc005c8; +ets_intr_unlock = 0x4fc005cc; +ets_isr_attach = 0x4fc005d0; +ets_isr_mask = 0x4fc005d4; +ets_isr_unmask = 0x4fc005d8; + + +/*************************************** + Group crypto + ***************************************/ + +/* Functions */ +md5_vector = 0x4fc005dc; +MD5Init = 0x4fc005e0; +MD5Update = 0x4fc005e4; +MD5Final = 0x4fc005e8; +crc32_le = 0x4fc005ec; +crc16_le = 0x4fc005f0; +crc8_le = 0x4fc005f4; +crc32_be = 0x4fc005f8; +crc16_be = 0x4fc005fc; +crc8_be = 0x4fc00600; +esp_crc8 = 0x4fc00604; +ets_sha_enable = 0x4fc00608; +ets_sha_disable = 0x4fc0060c; +ets_sha_get_state = 0x4fc00610; +ets_sha_init = 0x4fc00614; +ets_sha_process = 0x4fc00618; +ets_sha_starts = 0x4fc0061c; +ets_sha_update = 0x4fc00620; +ets_sha_finish = 0x4fc00624; +ets_sha_clone = 0x4fc00628; +ets_hmac_enable = 0x4fc0062c; +ets_hmac_disable = 0x4fc00630; +ets_hmac_calculate_message = 0x4fc00634; +ets_hmac_calculate_downstream = 0x4fc00638; +ets_hmac_invalidate_downstream = 0x4fc0063c; +ets_jtag_enable_temporarily = 0x4fc00640; +ets_aes_enable = 0x4fc00644; +ets_aes_disable = 0x4fc00648; +ets_aes_setkey = 0x4fc0064c; +ets_aes_block = 0x4fc00650; +ets_aes_setkey_dec = 0x4fc00654; +ets_aes_setkey_enc = 0x4fc00658; +ets_bigint_enable = 0x4fc0065c; +ets_bigint_disable = 0x4fc00660; +ets_bigint_multiply = 0x4fc00664; +ets_bigint_modmult = 0x4fc00668; +ets_bigint_modexp = 0x4fc0066c; +ets_bigint_wait_finish = 0x4fc00670; +ets_bigint_getz = 0x4fc00674; +ets_ds_enable = 0x4fc00678; +ets_ds_disable = 0x4fc0067c; +ets_ds_start_sign = 0x4fc00680; +ets_ds_is_busy = 0x4fc00684; +ets_ds_finish_sign = 0x4fc00688; +ets_ds_encrypt_params = 0x4fc0068c; +ets_mgf1_sha256 = 0x4fc00690; +/* Data (.data, .bss, .rodata) */ +crc32_le_table_ptr = 0x4fc1fff8; +crc16_le_table_ptr = 0x4fc1fff4; +crc8_le_table_ptr = 0x4fc1fff0; +crc32_be_table_ptr = 0x4fc1ffec; +crc16_be_table_ptr = 0x4fc1ffe8; +crc8_be_table_ptr = 0x4fc1ffe4; + + +/*************************************** + Group efuse + ***************************************/ + +/* Functions */ +ets_efuse_read = 0x4fc00694; +ets_efuse_program = 0x4fc00698; +ets_efuse_clear_program_registers = 0x4fc0069c; +ets_efuse_write_key = 0x4fc006a0; +ets_efuse_get_read_register_address = 0x4fc006a4; +ets_efuse_get_key_purpose = 0x4fc006a8; +ets_efuse_key_block_unused = 0x4fc006ac; +ets_efuse_find_unused_key_block = 0x4fc006b0; +ets_efuse_rs_calculate = 0x4fc006b4; +ets_efuse_count_unused_key_blocks = 0x4fc006b8; +ets_efuse_secure_boot_enabled = 0x4fc006bc; +ets_efuse_secure_boot_aggressive_revoke_enabled = 0x4fc006c0; +ets_efuse_cache_encryption_enabled = 0x4fc006c4; +ets_efuse_download_modes_disabled = 0x4fc006c8; +ets_efuse_find_purpose = 0x4fc006cc; +ets_efuse_force_send_resume = 0x4fc006d0; +ets_efuse_get_flash_delay_us = 0x4fc006d4; +ets_efuse_get_uart_print_control = 0x4fc006d8; +ets_efuse_direct_boot_mode_disabled = 0x4fc006dc; +ets_efuse_security_download_modes_enabled = 0x4fc006e0; +ets_efuse_jtag_disabled = 0x4fc006e4; +ets_efuse_usb_print_is_disabled = 0x4fc006e8; +ets_efuse_usb_download_mode_disabled = 0x4fc006ec; +ets_efuse_usb_device_disabled = 0x4fc006f0; +ets_efuse_get_km_huk_gen_state = 0x4fc006f4; +ets_efuse_get_km_deploy_only_once = 0x4fc006f8; +ets_efuse_get_force_use_km_key = 0x4fc006fc; +ets_efuse_xts_key_length_256 = 0x4fc00700; +ets_efuse_get_km_key_lock = 0x4fc00704; + + +/*************************************** + Group key_mgr + ***************************************/ + +/* Functions */ +esp_rom_check_recover_key = 0x4fc00708; +esp_rom_km_huk_conf = 0x4fc0070c; +esp_rom_km_huk_risk = 0x4fc00710; + + +/*************************************** + Group secureboot + ***************************************/ + +/* Functions */ +ets_emsa_pss_verify = 0x4fc00714; +ets_rsa_pss_verify = 0x4fc00718; +ets_ecdsa_verify = 0x4fc0071c; +ets_secure_boot_verify_bootloader_with_keys = 0x4fc00720; +ets_secure_boot_verify_signature = 0x4fc00724; +ets_secure_boot_read_key_digests = 0x4fc00728; +ets_secure_boot_revoke_public_key_digest = 0x4fc0072c; + + +/*************************************** + Group usb_device_uart + ***************************************/ + +/* Functions */ +usb_serial_device_rx_one_char = 0x4fc008a4; +usb_serial_device_rx_one_char_block = 0x4fc008a8; +usb_serial_device_tx_flush = 0x4fc008ac; +usb_serial_device_tx_one_char = 0x4fc008b0; + + +/*************************************** + Group usb_dwcotg_uart + ***************************************/ + +/* Functions */ +Uart_Init_USB = 0x4fc008b4; +usb_serial_otg_rx_one_char = 0x4fc008b8; +usb_serial_otg_rx_one_char_block = 0x4fc008bc; +usb_serial_otg_tx_flush = 0x4fc008c0; +usb_serial_otg_tx_one_char = 0x4fc008c4; +/* Data (.data, .bss, .rodata) */ +uart_acm_dev = 0x4ffbffd4; + + +/*************************************** + Group usb_dwcotg_module + ***************************************/ + +/* Functions */ +cdc_acm_class_handle_req = 0x4fc008c8; +cdc_acm_init = 0x4fc008cc; +cdc_acm_fifo_fill = 0x4fc008d0; +cdc_acm_rx_fifo_cnt = 0x4fc008d4; +cdc_acm_fifo_read = 0x4fc008d8; +cdc_acm_irq_tx_enable = 0x4fc008dc; +cdc_acm_irq_tx_disable = 0x4fc008e0; +cdc_acm_irq_state_enable = 0x4fc008e4; +cdc_acm_irq_state_disable = 0x4fc008e8; +cdc_acm_irq_tx_ready = 0x4fc008ec; +cdc_acm_irq_rx_enable = 0x4fc008f0; +cdc_acm_irq_rx_disable = 0x4fc008f4; +cdc_acm_irq_rx_ready = 0x4fc008f8; +cdc_acm_irq_is_pending = 0x4fc008fc; +cdc_acm_irq_callback_set = 0x4fc00900; +cdc_acm_line_ctrl_set = 0x4fc00904; +cdc_acm_line_ctrl_get = 0x4fc00908; +cdc_acm_poll_out = 0x4fc0090c; +chip_usb_dw_did_persist = 0x4fc00910; +chip_usb_dw_init = 0x4fc00914; +chip_usb_detach = 0x4fc00918; +chip_usb_dw_prepare_persist = 0x4fc0091c; +chip_usb_get_persist_flags = 0x4fc00920; +chip_usb_set_persist_flags = 0x4fc00924; +cpio_start = 0x4fc00928; +cpio_feed = 0x4fc0092c; +cpio_done = 0x4fc00930; +cpio_destroy = 0x4fc00934; +dfu_flash_init = 0x4fc00938; +dfu_flash_erase = 0x4fc0093c; +dfu_flash_program = 0x4fc00940; +dfu_flash_read = 0x4fc00944; +dfu_flash_attach = 0x4fc00948; +dfu_cpio_callback = 0x4fc0094c; +dfu_updater_get_err = 0x4fc00950; +dfu_updater_clear_err = 0x4fc00954; +dfu_updater_enable = 0x4fc00958; +dfu_updater_begin = 0x4fc0095c; +dfu_updater_feed = 0x4fc00960; +dfu_updater_end = 0x4fc00964; +dfu_updater_set_raw_addr = 0x4fc00968; +dfu_updater_flash_read = 0x4fc0096c; +usb_dc_prepare_persist = 0x4fc00970; +usb_dw_isr_handler = 0x4fc00974; +usb_dc_attach = 0x4fc00978; +usb_dc_detach = 0x4fc0097c; +usb_dc_reset = 0x4fc00980; +usb_dc_set_address = 0x4fc00984; +usb_dc_ep_check_cap = 0x4fc00988; +usb_dc_ep_configure = 0x4fc0098c; +usb_dc_ep_set_stall = 0x4fc00990; +usb_dc_ep_clear_stall = 0x4fc00994; +usb_dc_ep_halt = 0x4fc00998; +usb_dc_ep_is_stalled = 0x4fc0099c; +usb_dc_ep_enable = 0x4fc009a0; +usb_dc_ep_disable = 0x4fc009a4; +usb_dc_ep_flush = 0x4fc009a8; +usb_dc_ep_write_would_block = 0x4fc009ac; +usb_dc_ep_write = 0x4fc009b0; +usb_dc_ep_read_wait = 0x4fc009b4; +usb_dc_ep_read_continue = 0x4fc009b8; +usb_dc_ep_read = 0x4fc009bc; +usb_dc_ep_set_callback = 0x4fc009c0; +usb_dc_set_status_callback = 0x4fc009c4; +usb_dc_ep_mps = 0x4fc009c8; +usb_dc_check_poll_for_interrupts = 0x4fc009cc; +mac_addr_to_serial_str_desc = 0x4fc009d0; +usb_set_current_descriptor = 0x4fc009d4; +usb_get_descriptor = 0x4fc009d8; +usb_dev_resume = 0x4fc009dc; +usb_dev_get_configuration = 0x4fc009e0; +usb_set_config = 0x4fc009e4; +usb_deconfig = 0x4fc009e8; +usb_enable = 0x4fc009ec; +usb_disable = 0x4fc009f0; +usb_write_would_block = 0x4fc009f4; +usb_write = 0x4fc009f8; +usb_read = 0x4fc009fc; +usb_ep_set_stall = 0x4fc00a00; +usb_ep_clear_stall = 0x4fc00a04; +usb_ep_read_wait = 0x4fc00a08; +usb_ep_read_continue = 0x4fc00a0c; +usb_transfer_ep_callback = 0x4fc00a10; +usb_transfer = 0x4fc00a14; +usb_cancel_transfer = 0x4fc00a18; +usb_transfer_sync = 0x4fc00a1c; +usb_dfu_set_detach_cb = 0x4fc00a20; +dfu_class_handle_req = 0x4fc00a24; +dfu_status_cb = 0x4fc00a28; +dfu_custom_handle_req = 0x4fc00a2c; +usb_dfu_init = 0x4fc00a30; +usb_dfu_force_detach = 0x4fc00a34; +usb_dev_deinit = 0x4fc00a38; +usb_dw_ctrl_deinit = 0x4fc00a3c; +/* Data (.data, .bss, .rodata) */ +s_usb_osglue = 0x4ffbffc8; + + +/*************************************** + Group recovery_bootloader + ***************************************/ + +/* Functions */ +ets_get_bootloader_offset = 0x4fc00a40; +ets_set_bootloader_offset = 0x4fc00a44; diff --git a/esp-rom-sys/ld/esp32p4/rom/esp32p4.rom.libgcc.ld b/esp-rom-sys/ld/esp32p4/rom/esp32p4.rom.libgcc.ld new file mode 100644 index 00000000000..308bb0c1a19 --- /dev/null +++ b/esp-rom-sys/ld/esp32p4/rom/esp32p4.rom.libgcc.ld @@ -0,0 +1,95 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +/* ROM function interface esp32p4.rom.libgcc.ld for esp32p4 + * + * + * Generated from ./target/esp32p4/interface-esp32p4.yml md5sum 56d78222be1daa0502090a078288f4d5 + * + * Compatible with ROM where ECO version equal or greater to 5. + * + * THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT. + */ + +/*************************************** + Group libgccdf + ***************************************/ + +/* Functions */ +__absvdi2 = 0x4fc00730; +__absvsi2 = 0x4fc00734; +__adddf3 = 0x4fc00738; +__addvdi3 = 0x4fc0073c; +__addvsi3 = 0x4fc00740; +__ashldi3 = 0x4fc00744; +__ashrdi3 = 0x4fc00748; +__bswapdi2 = 0x4fc0074c; +__bswapsi2 = 0x4fc00750; +__clear_cache = 0x4fc00754; +__clrsbdi2 = 0x4fc00758; +__clrsbsi2 = 0x4fc0075c; +__clzdi2 = 0x4fc00760; +__clzsi2 = 0x4fc00764; +__cmpdi2 = 0x4fc00768; +__ctzdi2 = 0x4fc0076c; +__ctzsi2 = 0x4fc00770; +__divdc3 = 0x4fc00774; +__divdf3 = 0x4fc00778; +__divdi3 = 0x4fc0077c; +__divsc3 = 0x4fc00780; +__divsi3 = 0x4fc00784; +__eqdf2 = 0x4fc00788; +__extendsfdf2 = 0x4fc0078c; +__ffsdi2 = 0x4fc00790; +__ffssi2 = 0x4fc00794; +__fixdfdi = 0x4fc00798; +__fixdfsi = 0x4fc0079c; +__fixsfdi = 0x4fc007a0; +__fixunsdfsi = 0x4fc007a4; +__fixunssfdi = 0x4fc007a8; +__fixunssfsi = 0x4fc007ac; +__floatdidf = 0x4fc007b0; +__floatdisf = 0x4fc007b4; +__floatsidf = 0x4fc007b8; +__floatundidf = 0x4fc007bc; +__floatundisf = 0x4fc007c0; +__floatunsidf = 0x4fc007c4; +__gcc_bcmp = 0x4fc007c8; +__gedf2 = 0x4fc007cc; +__gtdf2 = 0x4fc007d0; +__ledf2 = 0x4fc007d4; +__lshrdi3 = 0x4fc007d8; +__ltdf2 = 0x4fc007dc; +__moddi3 = 0x4fc007e0; +__modsi3 = 0x4fc007e4; +__muldc3 = 0x4fc007e8; +__muldf3 = 0x4fc007ec; +__muldi3 = 0x4fc007f0; +__mulsc3 = 0x4fc007f4; +__mulsi3 = 0x4fc007f8; +__mulvdi3 = 0x4fc007fc; +__mulvsi3 = 0x4fc00800; +__nedf2 = 0x4fc00804; +__negdf2 = 0x4fc00808; +__negdi2 = 0x4fc0080c; +__negvdi2 = 0x4fc00810; +__negvsi2 = 0x4fc00814; +__paritysi2 = 0x4fc00818; +__popcountdi2 = 0x4fc0081c; +__popcountsi2 = 0x4fc00820; +__powidf2 = 0x4fc00824; +__subdf3 = 0x4fc00828; +__subvdi3 = 0x4fc0082c; +__subvsi3 = 0x4fc00830; +__ucmpdi2 = 0x4fc00834; +__udivdi3 = 0x4fc00838; +__udivmoddi4 = 0x4fc0083c; +__udivsi3 = 0x4fc00840; +__udiv_w_sdiv = 0x4fc00844; +__umoddi3 = 0x4fc00848; +__umodsi3 = 0x4fc0084c; +__unorddf2 = 0x4fc00850; +__extenddftf2 = 0x4fc00854; +__trunctfdf2 = 0x4fc00858; diff --git a/esp-rom-sys/ld/esp32p4/rom/esp32p4.rom.rvfp.ld b/esp-rom-sys/ld/esp32p4/rom/esp32p4.rom.rvfp.ld new file mode 100644 index 00000000000..28efe7209fd --- /dev/null +++ b/esp-rom-sys/ld/esp32p4/rom/esp32p4.rom.rvfp.ld @@ -0,0 +1,101 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +/* ROM function interface esp32p4.rom.rvfp.ld for esp32p4 + * + * + * Generated from ./target/esp32p4/interface-esp32p4.yml md5sum 56d78222be1daa0502090a078288f4d5 + * + * Compatible with ROM where ECO version equal or greater to 5. + * + * THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT. + */ + +/*************************************** + Group rvfplibdf + ***************************************/ + +/* Functions */ +__adddf3 = 0x4fc0085c; +__eqdf2 = 0x4fc00860; +__fixdfdi = 0x4fc00864; +__fixdfsi = 0x4fc00868; +__fixunsdfsi = 0x4fc00870; +__floatdidf = 0x4fc00878; +__floatsidf = 0x4fc0087c; +__floatundidf = 0x4fc00880; +__floatunsidf = 0x4fc00884; +__gedf2 = 0x4fc00888; +__gtdf2 = 0x4fc0088c; +__ledf2 = 0x4fc00890; +__ltdf2 = 0x4fc00894; +__muldf3 = 0x4fc00898; +__nedf2 = 0x4fc0089c; +__subdf3 = 0x4fc008a0; + +/*************************************** + Group libgcc +***************************************/ + +/* Functions */ +__absvdi2 = 0x4fc00730; +__absvsi2 = 0x4fc00734; +__addvdi3 = 0x4fc0073c; +__addvsi3 = 0x4fc00740; +__ashldi3 = 0x4fc00744; +__ashrdi3 = 0x4fc00748; +__bswapdi2 = 0x4fc0074c; +__bswapsi2 = 0x4fc00750; +__clear_cache = 0x4fc00754; +__clrsbdi2 = 0x4fc00758; +__clrsbsi2 = 0x4fc0075c; +__clzdi2 = 0x4fc00760; +__clzsi2 = 0x4fc00764; +__cmpdi2 = 0x4fc00768; +__ctzdi2 = 0x4fc0076c; +__ctzsi2 = 0x4fc00770; +__divdc3 = 0x4fc00774; +__divdf3 = 0x4fc00778; +__divdi3 = 0x4fc0077c; +__divsc3 = 0x4fc00780; +__divsi3 = 0x4fc00784; +__extendsfdf2 = 0x4fc0078c; +__ffsdi2 = 0x4fc00790; +__ffssi2 = 0x4fc00794; +__fixsfdi = 0x4fc007a0; +__fixunssfdi = 0x4fc007a8; +__fixunssfsi = 0x4fc007ac; +__floatdisf = 0x4fc007b4; +__floatundisf = 0x4fc007c0; +__gcc_bcmp = 0x4fc007c8; +__lshrdi3 = 0x4fc007d8; +__moddi3 = 0x4fc007e0; +__modsi3 = 0x4fc007e4; +__muldc3 = 0x4fc007e8; +__muldi3 = 0x4fc007f0; +__mulsc3 = 0x4fc007f4; +__mulsi3 = 0x4fc007f8; +__mulvdi3 = 0x4fc007fc; +__mulvsi3 = 0x4fc00800; +__negdf2 = 0x4fc00808; +__negdi2 = 0x4fc0080c; +__negvdi2 = 0x4fc00810; +__negvsi2 = 0x4fc00814; +__paritysi2 = 0x4fc00818; +__popcountdi2 = 0x4fc0081c; +__popcountsi2 = 0x4fc00820; +__powidf2 = 0x4fc00824; +__subvdi3 = 0x4fc0082c; +__subvsi3 = 0x4fc00830; +__ucmpdi2 = 0x4fc00834; +__udivdi3 = 0x4fc00838; +__udivmoddi4 = 0x4fc0083c; +__udivsi3 = 0x4fc00840; +__udiv_w_sdiv = 0x4fc00844; +__umoddi3 = 0x4fc00848; +__umodsi3 = 0x4fc0084c; +__unorddf2 = 0x4fc00850; +__extenddftf2 = 0x4fc00854; +__trunctfdf2 = 0x4fc00858; diff --git a/esp-rom-sys/ld/esp32p4/rom/esp32p4.rom.version.ld b/esp-rom-sys/ld/esp32p4/rom/esp32p4.rom.version.ld new file mode 100644 index 00000000000..6a0c65c2702 --- /dev/null +++ b/esp-rom-sys/ld/esp32p4/rom/esp32p4.rom.version.ld @@ -0,0 +1,14 @@ +/* + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* ROM version variables for esp32p4 + * + * These addresses should be compatible with any ROM version for this chip. + * + * THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT. + */ +_rom_chip_id = 0x4fc00010; +_rom_eco_version = 0x4fc00014; diff --git a/esp-rom-sys/libs/esp32p4/unused b/esp-rom-sys/libs/esp32p4/unused new file mode 100644 index 00000000000..e69de29bb2d diff --git a/esp-rom-sys/src/reg_access.rs b/esp-rom-sys/src/reg_access.rs index 96b1c45d085..cd5c1dbcab9 100644 --- a/esp-rom-sys/src/reg_access.rs +++ b/esp-rom-sys/src/reg_access.rs @@ -20,6 +20,9 @@ pub(crate) use esp32c61 as pac; #[cfg(esp32h2)] #[expect(unused)] pub(crate) use esp32h2 as pac; +#[cfg(esp32p4)] +#[expect(unused)] +pub(crate) use esp32p4 as pac; #[cfg(esp32s2)] #[expect(unused)] pub(crate) use esp32s2 as pac; diff --git a/esp-rom-sys/src/rom/mod.rs b/esp-rom-sys/src/rom/mod.rs index 5dc90ca3bda..b8f3693db51 100644 --- a/esp-rom-sys/src/rom/mod.rs +++ b/esp-rom-sys/src/rom/mod.rs @@ -77,7 +77,7 @@ pub fn ets_set_appcpu_boot_addr(boot_addr: u32) { #[unsafe(no_mangle)] extern "C" fn rtc_clk_xtal_freq_get() -> i32 { cfg_if::cfg_if! { - if #[cfg(any(esp32c6, esp32h2))] { + if #[cfg(any(esp32c6, esp32h2, esp32p4))] { unsafe extern "C" { fn ets_clk_get_xtal_freq() -> i32; } diff --git a/esp-rom-sys/src/syscall/mod.rs b/esp-rom-sys/src/syscall/mod.rs index e8261b5a51d..93de758f8f7 100644 --- a/esp-rom-sys/src/syscall/mod.rs +++ b/esp-rom-sys/src/syscall/mod.rs @@ -5,7 +5,7 @@ use core::ffi::{c_char, c_int, c_long, c_void}; // future chips or ECOs _might_ be different - at least ESP-IDF defines the struct per chip #[cfg_attr( any( - esp32, esp32s2, esp32s3, esp32c2, esp32c3, esp32c5, esp32c6, esp32c61, esp32h2 + esp32, esp32s2, esp32s3, esp32c2, esp32c3, esp32c5, esp32c6, esp32c61, esp32h2, esp32p4 ), path = "v1.rs" )] diff --git a/esp-sync/CHANGELOG.md b/esp-sync/CHANGELOG.md index 42847ee4654..959d52ecfe2 100644 --- a/esp-sync/CHANGELOG.md +++ b/esp-sync/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Initial ESP32-P4 (chip revision v3.0+) support (#5400) ### Changed diff --git a/esp-sync/Cargo.toml b/esp-sync/Cargo.toml index 722823cbd26..feb9f2f6a82 100644 --- a/esp-sync/Cargo.toml +++ b/esp-sync/Cargo.toml @@ -55,6 +55,8 @@ esp32c6 = ["esp-metadata-generated/esp32c6"] esp32c61 = ["esp-metadata-generated/esp32c61"] ## Target the ESP32-H2. esp32h2 = ["esp-metadata-generated/esp32h2"] +## Target the ESP32-P4. +esp32p4 = ["esp-metadata-generated/esp32p4"] ## Target the ESP32-S2. esp32s2 = ["esp-metadata-generated/esp32s2"] ## Target the ESP32-S3. diff --git a/esp-sync/src/raw.rs b/esp-sync/src/raw.rs index 4d6551031c5..44ee2612788 100644 --- a/esp-sync/src/raw.rs +++ b/esp-sync/src/raw.rs @@ -36,9 +36,31 @@ impl RawLock for SingleCoreInterruptLock { unsafe fn enter(&self) -> RestoreState { cfg_if::cfg_if! { if #[cfg(riscv)] { + // ESP32-P4 (v3.2/ECO7 etc.) Zcmp hardware bug workaround (IDF-14279 / DIG-661): + // Clearing mstatus.mie alone does not fully mask CLIC interrupts -- an + // interrupt can still fire mid-instruction on cm.push (and possibly on + // other multi-cycle sequences). Fix: raise mintthresh (CSR 0x347) to 0xFF + // while mie is cleared, then restore the previous mintthresh on exit. + // Ref: esp-idf commit c27c33a83 "fix(riscv): implement a workaround for + // Zcmp hardware bug". + #[cfg(esp32p4)] + let old_mintthresh: u32; + #[cfg(esp32p4)] + unsafe { + core::arch::asm!( + "li t0, 0xff", + "csrrw {0}, 0x347, t0", + out(reg) old_mintthresh, + out("t0") _, + ); + } let mut mstatus = 0u32; unsafe { core::arch::asm!("csrrci {0}, mstatus, 8", inout(reg) mstatus); } - let token = mstatus & 0b1000; + let mie_bit = mstatus & 0b1000; + #[cfg(esp32p4)] + let token = mie_bit | ((old_mintthresh & 0xff) << 8); + #[cfg(not(esp32p4))] + let token = mie_bit; } else if #[cfg(xtensa)] { let token: u32; unsafe { core::arch::asm!("rsil {0}, 5", out(reg) token); } @@ -66,11 +88,22 @@ impl RawLock for SingleCoreInterruptLock { cfg_if::cfg_if! { if #[cfg(riscv)] { - if token != 0 { + if (token & 0b1000) != 0 { unsafe { riscv::interrupt::enable(); } } + // Restore mintthresh AFTER re-enabling mie (P4 Zcmp workaround, see enter()). + #[cfg(esp32p4)] + { + let old_mintthresh = (token >> 8) & 0xff; + unsafe { + core::arch::asm!( + "csrw 0x347, {0}", + in(reg) old_mintthresh, + ); + } + } } else if #[cfg(xtensa)] { #[cfg(debug_assertions)] if token & RESERVED_MASK != 0 { diff --git a/examples/hello_world/Cargo.toml b/examples/hello_world/Cargo.toml index 4e1abf6f4e0..96051ccbcea 100644 --- a/examples/hello_world/Cargo.toml +++ b/examples/hello_world/Cargo.toml @@ -49,6 +49,11 @@ esp32h2 = [ "esp-bootloader-esp-idf/esp32h2", "esp-hal/esp32h2", ] +esp32p4 = [ + "esp-backtrace/esp32p4", + "esp-bootloader-esp-idf/esp32p4", + "esp-hal/esp32p4", +] esp32s2 = [ "esp-backtrace/esp32s2", "esp-bootloader-esp-idf/esp32s2", diff --git a/examples/interrupt/gpio/Cargo.toml b/examples/interrupt/gpio/Cargo.toml index fc1d1b35199..c1ab1ee0b70 100644 --- a/examples/interrupt/gpio/Cargo.toml +++ b/examples/interrupt/gpio/Cargo.toml @@ -47,6 +47,11 @@ esp32h2 = [ "esp-bootloader-esp-idf/esp32h2", "esp-hal/esp32h2", ] +esp32p4 = [ + "esp-backtrace/esp32p4", + "esp-bootloader-esp-idf/esp32p4", + "esp-hal/esp32p4", +] esp32s2 = [ "esp-backtrace/esp32s2", "esp-bootloader-esp-idf/esp32s2", diff --git a/examples/interrupt/gpio/src/main.rs b/examples/interrupt/gpio/src/main.rs index 5ad4d6c37ee..4f726071447 100644 --- a/examples/interrupt/gpio/src/main.rs +++ b/examples/interrupt/gpio/src/main.rs @@ -5,7 +5,11 @@ //! //! The following wiring is assumed: //! - LED => GPIO2 -//! - BUTTON => GPIO0 (ESP32, ESP32-S2, ESP32-S3) / GPIO28 (ESP32-C5) / GPIO9 +//! - BUTTON: +//! - ESP32, ESP32-S2, ESP32-S3: GPIO0 +//! - ESP32-C5: GPIO28 +//! - ESP32-P4: GPIO35 +//! - Others: GPIO9 #![no_std] #![no_main] @@ -42,7 +46,9 @@ fn main() -> ! { let button = peripherals.GPIO0; } else if #[cfg(any(feature = "esp32c5"))] { let button = peripherals.GPIO28; - }else { + } else if #[cfg(any(feature = "esp32p4"))] { + let button = peripherals.GPIO35; + } else { let button = peripherals.GPIO9; } }