diff --git a/main.go b/main.go index 16bf5f9..2daf295 100644 --- a/main.go +++ b/main.go @@ -26,7 +26,7 @@ func main() { port := flag.String("port", "", "Serial port (e.g. /dev/ttyUSB0, COM3)") baud := flag.Int("baud", 460800, "Flash baud rate") offset := flag.String("offset", "0x0", "Flash offset for single binary mode") - chip := flag.String("chip", "auto", "Chip type: auto, esp8266, esp32, esp32s2, esp32s3, esp32c2, esp32c3, esp32c5, esp32c6, esp32h2") + chip := flag.String("chip", "auto", "Chip type: auto, esp8266, esp32, esp32s2, esp32s3, esp32c2, esp32c3, esp32c5, esp32c6, esp32h2, esp32p4-rev1") noCompress := flag.Bool("no-compress", false, "Disable compression") eraseAll := flag.Bool("erase-all", false, "Erase entire flash before writing") flashMode := flag.String("fm", "keep", "Flash mode: keep, qio, qout, dio, dout") @@ -232,6 +232,8 @@ func parseChipType(s string) espflasher.ChipType { return espflasher.ChipESP32C6 case "esp32h2", "esp32-h2": return espflasher.ChipESP32H2 + case "esp32p4-rev1", "esp32-p4-rev1": + return espflasher.ChipESP32P4Rev1 default: log.Fatalf("Unknown chip type: %s", s) return espflasher.ChipAuto diff --git a/pkg/espflasher/chip.go b/pkg/espflasher/chip.go index e62eccf..37b809b 100644 --- a/pkg/espflasher/chip.go +++ b/pkg/espflasher/chip.go @@ -15,6 +15,7 @@ const ( ChipESP32C5 ChipESP32C6 ChipESP32H2 + ChipESP32P4Rev1 ChipAuto // Auto-detect chip type ) @@ -39,6 +40,8 @@ func (c ChipType) String() string { return "ESP32-C6" case ChipESP32H2: return "ESP32-H2" + case ChipESP32P4Rev1: + return "ESP32-P4-Rev1" case ChipAuto: return "Auto" default: @@ -130,15 +133,16 @@ const chipDetectMagicRegAddr uint32 = 0x40001000 // All known chip definitions. var chipDefs = map[ChipType]*chipDef{ - ChipESP8266: defESP8266, - ChipESP32: defESP32, - ChipESP32S2: defESP32S2, - ChipESP32S3: defESP32S3, - ChipESP32C2: defESP32C2, - ChipESP32C3: defESP32C3, - ChipESP32C5: defESP32C5, - ChipESP32C6: defESP32C6, - ChipESP32H2: defESP32H2, + ChipESP8266: defESP8266, + ChipESP32: defESP32, + ChipESP32S2: defESP32S2, + ChipESP32S3: defESP32S3, + ChipESP32C2: defESP32C2, + ChipESP32C3: defESP32C3, + ChipESP32C5: defESP32C5, + ChipESP32C6: defESP32C6, + ChipESP32H2: defESP32H2, + ChipESP32P4Rev1: defESP32P4Rev1, } // detectChipByMagic returns the chip definition matching the given magic value, diff --git a/pkg/espflasher/doc.go b/pkg/espflasher/doc.go index e9893ec..d5e03b0 100644 --- a/pkg/espflasher/doc.go +++ b/pkg/espflasher/doc.go @@ -12,6 +12,7 @@ // - ESP32-C5 // - ESP32-C6 // - ESP32-H2 +// - ESP32-P4 (rev 1 / ECO2) // // # Quick Start // diff --git a/pkg/espflasher/stub.go b/pkg/espflasher/stub.go index d8f0901..270225b 100644 --- a/pkg/espflasher/stub.go +++ b/pkg/espflasher/stub.go @@ -13,15 +13,16 @@ var stubFS embed.FS // chipStubName maps each supported chip type to its stub JSON filename stem. var chipStubName = map[ChipType]string{ - ChipESP8266: "esp8266", - ChipESP32: "esp32", - ChipESP32S2: "esp32s2", - ChipESP32S3: "esp32s3", - ChipESP32C2: "esp32c2", - ChipESP32C3: "esp32c3", - ChipESP32C5: "esp32c5", - ChipESP32C6: "esp32c6", - ChipESP32H2: "esp32h2", + ChipESP8266: "esp8266", + ChipESP32: "esp32", + ChipESP32S2: "esp32s2", + ChipESP32S3: "esp32s3", + ChipESP32C2: "esp32c2", + ChipESP32C3: "esp32c3", + ChipESP32C5: "esp32c5", + ChipESP32C6: "esp32c6", + ChipESP32H2: "esp32h2", + ChipESP32P4Rev1: "esp32p4-rev1", } // stubJSON mirrors the JSON structure of the esptool stub flasher files. diff --git a/pkg/espflasher/stubs/esp32p4-rev1.json b/pkg/espflasher/stubs/esp32p4-rev1.json new file mode 100644 index 0000000..ef5e338 --- /dev/null +++ b/pkg/espflasher/stubs/esp32p4-rev1.json @@ -0,0 +1,8 @@ +{ + "entry": 1341194240, + "text": "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", + "text_start": 1341194240, + "data": "ChLxT0yC9U+QA/FPkAPxT5AD8U+QA/FPkAPxT5AD8U+QA/FPkAPxT5AD8U+QA/FPkAPxT5AD8U+QA/FPkAPxT5AD8U+QA/FPkAPxT5AD8U+QA/FPkAPxT5AD8U+QA/FPkAPxT5AD8U+QA/FPkAPxT5AD8U+iCvFPrgrxT/oK8U8mC/FPsAvxT1oL8U+ECvFP8gvxT24M8U+UDPFPRArxT4IM8U9ECvFP+gzxTwoN8U8ODfFP+grxT2YN8U96DfFP", + "data_start": 1341533624, + "bss_start": 1341456384 +} \ No newline at end of file diff --git a/pkg/espflasher/target_esp32p4_rev1.go b/pkg/espflasher/target_esp32p4_rev1.go new file mode 100644 index 0000000..3510667 --- /dev/null +++ b/pkg/espflasher/target_esp32p4_rev1.go @@ -0,0 +1,80 @@ +package espflasher + +// ESP32-P4 Rev1 (ECO2, chip revision < 3.0) register addresses for USB +// interface detection and watchdog control. +// Reference: esptool/targets/esp32p4.py (P4-specific values) and +// esptool/targets/esp32.py (ESP32ROM base-class SPI defaults P4 inherits). +// +// UARTDEV_BUF_NO is revision-dependent in esptool: +// rev < 3.0 (ECO2, this target): 0x4FF3FEB0 + 24 = 0x4FF3FEC8 +// rev >= 3.0 (production, future): 0x4FFBFEB0 + 24 = 0x4FFBFEC8 +// The USB-JTAG/Serial sentinel is 6 on P4 (not 3 like C5/C6/H2). +const ( + esp32p4Rev1UARTDevBufNo uint32 = 0x4FF3FEC8 + esp32p4UARTDevBufNoUSBJTAGSerial uint32 = 6 + + esp32p4LPWDTConfig0 uint32 = 0x50116000 + esp32p4LPWDTWProtect uint32 = 0x50116018 + esp32p4LPWDTSWDConf uint32 = 0x5011601C + esp32p4LPWDTSWDWProtect uint32 = 0x50116020 +) + +// ESP32-P4 Rev1 target definition. +// Reference: https://github.com/espressif/esptool/blob/master/esptool/targets/esp32p4.py +// Production silicon (rev >= 3.0) uses a different UARTDEV_BUF_NO address and +// the esp32p4.json stub; it will land as a separate target when we have that hardware. + +var defESP32P4Rev1 = &chipDef{ + ChipType: ChipESP32P4Rev1, + Name: "ESP32-P4-Rev1", + ImageChipID: 18, + UsesMagicValue: false, + + SPIRegBase: 0x5008D000, + SPIUSROffs: 0x18, + SPIUSR1Offs: 0x1C, + SPIUSR2Offs: 0x20, + SPIMOSIOffs: 0x24, + SPIMISOOffs: 0x98, + SPIW0Offs: 0x58, + + SPIMISODLenOffs: 0x28, + SPIMOSIDLenOffs: 0x24, + + SPIAddrRegMSB: false, + + UARTDateReg: 0x500CA08C, + UARTClkDiv: 0x500CA014, + XTALClkDiv: 1, + + BootloaderFlashOffset: 0x2000, + + SupportsEncryptedFlash: true, + ROMHasCompressedFlash: true, + ROMHasChangeBaud: true, + + FlashFrequency: map[string]byte{ + "80m": 0xF, + "40m": 0x0, + "20m": 0x2, + }, + + FlashSizes: defaultFlashSizes(), + + PostConnect: esp32p4Rev1PostConnect, +} + +func esp32p4Rev1PostConnect(f *Flasher) error { + uartDev, err := f.ReadRegister(esp32p4Rev1UARTDevBufNo) + if err != nil { + return nil + } + + if uartDev == esp32p4UARTDevBufNoUSBJTAGSerial { + f.usesUSB = true + f.logf("USB-JTAG/Serial interface detected (ESP32-P4 rev1), disabling watchdogs") + return disableWatchdogsLP(f, esp32p4LPWDTConfig0, esp32p4LPWDTWProtect, esp32p4LPWDTSWDConf, esp32p4LPWDTSWDWProtect) + } + + return nil +} diff --git a/pkg/espflasher/target_esp32p4_rev1_test.go b/pkg/espflasher/target_esp32p4_rev1_test.go new file mode 100644 index 0000000..bc98c24 --- /dev/null +++ b/pkg/espflasher/target_esp32p4_rev1_test.go @@ -0,0 +1,71 @@ +package espflasher + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestESP32P4Rev1PostConnectUSBJTAG(t *testing.T) { + writeCount := 0 + readCount := 0 + + mc := &mockConnection{ + readRegFunc: func(addr uint32) (uint32, error) { + readCount++ + if addr == esp32p4Rev1UARTDevBufNo { + return esp32p4UARTDevBufNoUSBJTAGSerial, nil + } + // Return 0 for SWD conf read + return 0, nil + }, + writeRegFunc: func(addr, value, mask, delayUS uint32) error { + writeCount++ + return nil + }, + } + f := &Flasher{ + conn: mc, + opts: &FlasherOptions{}, + } + + err := esp32p4Rev1PostConnect(f) + require.NoError(t, err) + assert.True(t, f.usesUSB, "usesUSB should be true for USB-JTAG/Serial") + assert.Greater(t, writeCount, 0, "should have written registers to disable watchdog") +} + +func TestESP32P4Rev1PostConnectUART(t *testing.T) { + mc := &mockConnection{ + readRegFunc: func(addr uint32) (uint32, error) { + return 0, nil // Not USB, return UART value + }, + } + f := &Flasher{ + conn: mc, + opts: &FlasherOptions{}, + } + + err := esp32p4Rev1PostConnect(f) + require.NoError(t, err) + assert.False(t, f.usesUSB, "usesUSB should be false for UART") +} + +func TestESP32P4Rev1PostConnectSecureMode(t *testing.T) { + // Simulate read error (secure download mode) + mc := &mockConnection{ + readRegFunc: func(addr uint32) (uint32, error) { + return 0, errors.New("register not readable") // Simulate unreadable register + }, + } + f := &Flasher{ + conn: mc, + opts: &FlasherOptions{}, + } + + err := esp32p4Rev1PostConnect(f) + require.NoError(t, err, "should gracefully handle read error") + assert.False(t, f.usesUSB, "should default to non-USB on read error") +} diff --git a/tools/update-stubs.go b/tools/update-stubs.go index ccde755..1f11151 100644 --- a/tools/update-stubs.go +++ b/tools/update-stubs.go @@ -25,6 +25,7 @@ var chips = []string{ "esp32c5", "esp32c6", "esp32h2", + "esp32p4-rev1", } func main() {