From c2920b23b8a623d8ba9755c8f3240e8018eccaee Mon Sep 17 00:00:00 2001 From: deadprogram Date: Sat, 26 Sep 2026 15:07:12 +0200 Subject: [PATCH 1/2] machine/esp32c6: move the UART interrupt off CPU interrupt 7 CPU interrupts 3, 4 and 7 are bound to the CLINT on the ESP32-C6, so the UART RX interrupt was mapped to a line that is not usable. Use CPU interrupt 13, the same as the ESP32-H2. See ESP-IDF components/esp_hw_support/port/esp32c6/esp_cpu_intr.c. --- src/machine/machine_esp32c6.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/machine/machine_esp32c6.go b/src/machine/machine_esp32c6.go index 683de1f7c4..e6b7988dd7 100644 --- a/src/machine/machine_esp32c6.go +++ b/src/machine/machine_esp32c6.go @@ -16,6 +16,10 @@ const deviceName = esp.Device const maxPin = 31 const cpuInterruptFromPin = 6 +// CPU interrupts 3, 4 and 7 are bound to the CLINT and cannot be used. +// See ESP-IDF esp_hw_support/port/esp32c6/esp_cpu_intr.c. +const cpuInterruptFromUART = 13 + // CPUFrequency returns the current CPU frequency of the chip. // Currently it is a fixed frequency but it may allow changing in the future. func CPUFrequency() uint32 { @@ -477,9 +481,9 @@ func (uart *UART) configureInterrupt(intrMapReg *volatile.Register32) { // Disable all UART interrupts uart.Bus.INT_ENA.ClearBits(0x0ffff) - intrMapReg.Set(7) + intrMapReg.Set(cpuInterruptFromUART) onceUart.Do(func() { - _ = interrupt.New(7, func(i interrupt.Interrupt) { + _ = interrupt.New(cpuInterruptFromUART, func(i interrupt.Interrupt) { UART0.serveInterrupt(0) UART1.serveInterrupt(1) }).Enable() From 87a9f04a75a5476773ee42ee10f9b67dcb289406 Mon Sep 17 00:00:00 2001 From: deadprogram Date: Sat, 26 Sep 2026 15:13:23 +0200 Subject: [PATCH 2/2] targets/esp32c6: align .rodata to its flash offset .rodata can need 16-byte alignment. The linker then moves it past the end of .rodata_dummy, so its address no longer matches its offset in the image and every constant is read from the wrong place. Pad the end of .text the same way as the ESP32-H2 linker script, and add ASSERTs so this fails at link time. --- targets/esp32c6.ld | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/targets/esp32c6.ld b/targets/esp32c6.ld index d33edb256b..f98f98b612 100644 --- a/targets/esp32c6.ld +++ b/targets/esp32c6.ld @@ -125,6 +125,8 @@ SECTIONS .text : ALIGN(4) { *(.text .text.*) + /* Put the .rodata data at a 16-byte aligned flash offset, the same as its address. */ + . = ALIGN(. + 0x8, 16) - 0x8; } > IROM /* === DROM sections (flash-mapped read-only data) === */ @@ -151,6 +153,9 @@ SECTIONS . = ALIGN (4); } >DROM + ASSERT(ADDR(.text) == ADDR(.irom_dummy) + SIZEOF(.irom_dummy), ".text address does not match its flash offset") + ASSERT(ADDR(.rodata) == ADDR(.rodata_dummy) + SIZEOF(.rodata_dummy), ".rodata address does not match its flash offset") + /DISCARD/ : { *(.eh_frame) /* we don't do exception handling in C */