diff --git a/README.md b/README.md index fdd1f302..3d155f09 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Serial flasher utilities for Espressif devices, based loosely on [esptool.py](https://github.com/espressif/esptool/). -Supports the **ESP32**, **ESP32-C2/C3/C6**, **ESP32-H2**, **ESP32-S2/S3**, and **ESP8266**. +Supports the **ESP32**, **ESP32-C2/C3/C6**, **ESP32-H2**, **ESP32-P4**, **ESP32-S2/S3**, and **ESP8266**. ## [cargo-espflash](./cargo-espflash/) diff --git a/cargo-espflash/README.md b/cargo-espflash/README.md index c94d6379..12335eb0 100644 --- a/cargo-espflash/README.md +++ b/cargo-espflash/README.md @@ -7,7 +7,7 @@ Cross-compiler and Cargo extension for flashing Espressif devices. -Supports the **ESP32**, **ESP32-C2/C3/C6**, **ESP32-H2**, **ESP32-S2/S3**, and **ESP8266**. +Supports the **ESP32**, **ESP32-C2/C3/C6**, **ESP32-H2**, **ESP32-P4**, **ESP32-S2/S3**, and **ESP8266**. ## Table of Contents diff --git a/espflash/README.md b/espflash/README.md index 45a43093..21da4d52 100644 --- a/espflash/README.md +++ b/espflash/README.md @@ -8,7 +8,7 @@ A library and command-line tool for flashing Espressif devices. -Supports the **ESP32**, **ESP32-C2/C3/C6**, **ESP32-H2**, **ESP32-S2/S3**, and **ESP8266**. +Supports the **ESP32**, **ESP32-C2/C3/C6**, **ESP32-H2**, **ESP32-P4**,**ESP32-S2/S3**, and **ESP8266**. ## Table of Contents diff --git a/espflash/resources/bootloaders/esp32p4-bootloader.bin b/espflash/resources/bootloaders/esp32p4-bootloader.bin new file mode 100644 index 00000000..f3355135 Binary files /dev/null and b/espflash/resources/bootloaders/esp32p4-bootloader.bin differ diff --git a/espflash/resources/stubs/stub_flasher_32p4.toml b/espflash/resources/stubs/stub_flasher_32p4.toml new file mode 100644 index 00000000..2c6ec134 --- /dev/null +++ b/espflash/resources/stubs/stub_flasher_32p4.toml @@ -0,0 +1,6 @@ +entry = 1_341_195_718 +text = "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" +text_start = 1_341_194_240 +data = "DAD1T+4I8U86CfFPkgnxT2gK8U/UCvFPggrxT7YH8U8kCvFPZArxT6YJ8U9mB/FP2gnxT2YH8U/ICPFPDAnxTzoJ8U+SCfFP2gjxTyAI8U9QCPFP1gjxTywN8U86CfFP7AvxT+AM8U+yBvFPCg3xT7IG8U+yBvFPsgbxT7IG8U+yBvFPsgbxT7IG8U+yBvFPiAvxT7IG8U8IDPFP4AzxTw==" +data_start = 1_341_533_096 +bss_start = 1_341_456_384 diff --git a/espflash/src/flasher/stubs.rs b/espflash/src/flasher/stubs.rs index 6f5191de..d0fe47a9 100644 --- a/espflash/src/flasher/stubs.rs +++ b/espflash/src/flasher/stubs.rs @@ -23,9 +23,10 @@ const STUB_32: &str = include_str!("../../resources/stubs/stub_flasher_32.toml") const STUB_32C2: &str = include_str!("../../resources/stubs/stub_flasher_32c2.toml"); const STUB_32C3: &str = include_str!("../../resources/stubs/stub_flasher_32c3.toml"); const STUB_32C6: &str = include_str!("../../resources/stubs/stub_flasher_32c6.toml"); +const STUB_32H2: &str = include_str!("../../resources/stubs/stub_flasher_32h2.toml"); +const STUB_32P4: &str = include_str!("../../resources/stubs/stub_flasher_32p4.toml"); const STUB_32S2: &str = include_str!("../../resources/stubs/stub_flasher_32s2.toml"); const STUB_32S3: &str = include_str!("../../resources/stubs/stub_flasher_32s3.toml"); -const STUB_32H2: &str = include_str!("../../resources/stubs/stub_flasher_32h2.toml"); const STUB_8266: &str = include_str!("../../resources/stubs/stub_flasher_8266.toml"); impl FlashStub { @@ -36,9 +37,10 @@ impl FlashStub { Chip::Esp32c2 => STUB_32C2, Chip::Esp32c3 => STUB_32C3, Chip::Esp32c6 => STUB_32C6, + Chip::Esp32h2 => STUB_32H2, + Chip::Esp32p4 => STUB_32P4, Chip::Esp32s2 => STUB_32S2, Chip::Esp32s3 => STUB_32S3, - Chip::Esp32h2 => STUB_32H2, Chip::Esp8266 => STUB_8266, }; diff --git a/espflash/src/targets/esp32p4.rs b/espflash/src/targets/esp32p4.rs new file mode 100644 index 00000000..4af14f84 --- /dev/null +++ b/espflash/src/targets/esp32p4.rs @@ -0,0 +1,121 @@ +use std::ops::Range; + +use esp_idf_part::PartitionTable; + +use super::{Chip, Esp32Params, ReadEFuse, SpiRegisters, Target}; +use crate::{ + connection::Connection, + elf::FirmwareImage, + error::Error, + flasher::{FlashFrequency, FlashMode, FlashSize}, + image_format::{DirectBootFormat, IdfBootloaderFormat, ImageFormat, ImageFormatKind}, +}; + +const CHIP_DETECT_MAGIC_VALUES: &[u32] = &[0x0]; + +const FLASH_RANGES: &[Range] = &[ + 0x4000_0000..0x4C00_0000, // IROM + 0x4000_0000..0x4C00_0000, // DROM +]; + +const PARAMS: Esp32Params = Esp32Params::new( + 0x2000, + 0x1_0000, + 0x3f_0000, // TODO: Update + 18, + FlashFrequency::_40Mhz, + include_bytes!("../../resources/bootloaders/esp32p4-bootloader.bin"), +); + +/// ESP32-P4 Target +pub struct Esp32p4; + +impl Esp32p4 { + pub fn has_magic_value(value: u32) -> bool { + CHIP_DETECT_MAGIC_VALUES.contains(&value) + } +} + +impl ReadEFuse for Esp32p4 { + fn efuse_reg(&self) -> u32 { + 0x5012_D000 + } +} + +impl Target for Esp32p4 { + fn addr_is_flash(&self, addr: u32) -> bool { + FLASH_RANGES.iter().any(|range| range.contains(&addr)) + } + + fn chip_features(&self, _connection: &mut Connection) -> Result, Error> { + Ok(vec!["High-Performance MCU"]) + } + + fn major_chip_version(&self, _connection: &mut Connection) -> Result { + // TODO: https://github.com/espressif/esptool/blob/master/esptool/targets/esp32p4.py#L96 + Ok(0) + } + + fn minor_chip_version(&self, _connection: &mut Connection) -> Result { + // TODO: https://github.com/espressif/esptool/blob/master/esptool/targets/esp32p4.py#L92 + + Ok(0) + } + + fn crystal_freq(&self, _connection: &mut Connection) -> Result { + // The ESP32-P4's XTAL has a fixed frequency of 40MHz. + Ok(40) + } + + fn get_flash_image<'a>( + &self, + image: &'a dyn FirmwareImage<'a>, + bootloader: Option>, + partition_table: Option, + target_app_partition: Option, + image_format: Option, + _chip_revision: Option<(u32, u32)>, + flash_mode: Option, + flash_size: Option, + flash_freq: Option, + partition_table_offset: Option, + ) -> Result + 'a>, Error> { + let image_format = image_format.unwrap_or(ImageFormatKind::EspBootloader); + + match image_format { + ImageFormatKind::EspBootloader => Ok(Box::new(IdfBootloaderFormat::new( + image, + Chip::Esp32p4, + PARAMS, + partition_table, + target_app_partition, + bootloader, + flash_mode, + flash_size, + flash_freq, + partition_table_offset, + )?)), + ImageFormatKind::DirectBoot => Ok(Box::new(DirectBootFormat::new(image, 0x0)?)), + } + } + + fn spi_registers(&self) -> SpiRegisters { + SpiRegisters { + base: 0x5008_D000, + usr_offset: 0x18, + usr1_offset: 0x1c, + usr2_offset: 0x20, + w0_offset: 0x58, + mosi_length_offset: Some(0x24), + miso_length_offset: Some(0x28), + } + } + + fn supported_image_formats(&self) -> &[ImageFormatKind] { + &[ImageFormatKind::EspBootloader, ImageFormatKind::DirectBoot] + } + + fn supported_build_targets(&self) -> &[&str] { + &["riscv32imafc-esp-espidf", "riscv32imafc-unknown-none-elf"] + } +} diff --git a/espflash/src/targets/mod.rs b/espflash/src/targets/mod.rs index 5ae72f51..6816f36a 100644 --- a/espflash/src/targets/mod.rs +++ b/espflash/src/targets/mod.rs @@ -18,6 +18,7 @@ pub use self::{ esp32c3::Esp32c3, esp32c6::Esp32c6, esp32h2::Esp32h2, + esp32p4::Esp32p4, esp32s2::Esp32s2, esp32s3::Esp32s3, esp8266::Esp8266, @@ -39,6 +40,7 @@ mod esp32c2; mod esp32c3; mod esp32c6; mod esp32h2; +mod esp32p4; mod esp32s2; mod esp32s3; mod esp8266; @@ -58,12 +60,14 @@ pub enum Chip { Esp32c3, /// ESP32-C6 Esp32c6, + /// ESP32-H2 + Esp32h2, + /// ESP32-P4 + Esp32p4, /// ESP32-S2 Esp32s2, /// ESP32-S3 Esp32s3, - /// ESP32-H2 - Esp32h2, /// ESP8266 Esp8266, } @@ -78,12 +82,14 @@ impl Chip { Ok(Chip::Esp32c3) } else if Esp32c6::has_magic_value(magic) { Ok(Chip::Esp32c6) + } else if Esp32h2::has_magic_value(magic) { + Ok(Chip::Esp32h2) + } else if Esp32p4::has_magic_value(magic) { + Ok(Chip::Esp32p4) } else if Esp32s2::has_magic_value(magic) { Ok(Chip::Esp32s2) } else if Esp32s3::has_magic_value(magic) { Ok(Chip::Esp32s3) - } else if Esp32h2::has_magic_value(magic) { - Ok(Chip::Esp32h2) } else if Esp8266::has_magic_value(magic) { Ok(Chip::Esp8266) } else { @@ -97,9 +103,10 @@ impl Chip { Chip::Esp32c2 => Box::new(Esp32c2), Chip::Esp32c3 => Box::new(Esp32c3), Chip::Esp32c6 => Box::new(Esp32c6), + Chip::Esp32h2 => Box::new(Esp32h2), + Chip::Esp32p4 => Box::new(Esp32p4), Chip::Esp32s2 => Box::new(Esp32s2), Chip::Esp32s3 => Box::new(Esp32s3), - Chip::Esp32h2 => Box::new(Esp32h2), Chip::Esp8266 => Box::new(Esp8266), } }