The USB device is attached to the bus automatically during startup,
before user code has a chance to finish its USB configuration (device
identifiers, extra HID interfaces, ...). Composite devices such as
keyboards may therefore be enumerated by the host with an incomplete
configuration.
Attach and Detach expose the soft-connect control (DP pull-up) so that
an application or library can detach in an init function, complete its
configuration, and attach again to let the host enumerate the finished
device. They can also be used to force re-enumeration without
replugging the cable.
Implemented for atsamd21, atsamd51, nrf52840, rp2040 and rp2350.
Place espradio's RX ring buffer and WiFi-only BSS (ISR tables,
timer slots, ISR ring) in SRAM1 pool 7/6 ahead of the arena.
Frees ~14 KB of SRAM2 for the Go GC heap. The arena assertion
still guarantees ≥32 KB remains for WiFi DMA buffers.
Signed-off-by: deadprogram <ron@hybridgroup.com>
Match the Go runtime by terminating for deadlocks, stack overflows,
runtime and GC invariants, invalid lock operations, and platform
initialization failures instead of routing them through panic/recover.
Keep language-level runtime errors and unsupported user operations
recoverable. Add crash coverage that verifies fatal errors bypass deferred
recover calls.
Match the Go runtime by terminating instead of unwinding when an
allocator exhausts the heap. Recovering an OOM can leave allocator locks
held and cannot safely continue when the panic path itself needs memory.
Add compiler/testdata/go1.27.go, gated behind Go >= 1.27 (the version
that promoted generic methods out of the GenericMethods experiment),
covering both fixes from the previous two commits:
- genericMethod has a regular method and a generic method (its own
type parameter); boxing it into an interface must only include the
regular method in the runtime method set instead of panicking in
getTypeCodeName.
- onlyGenericMethod's sole method is generic, so its type code must
have hasMethodSet == false and no methodSet field at all, not an
empty one.
Verified this test panics on the pre-fix compiler/interface.go and
passes after it.
hasMethodSet was computed from the raw, unfiltered method set length
(ms.Len() != 0), before generic methods were excluded from numMethods
and the method set value. For a type whose only method is generic
(e.g. "func (t T) M[X int](n X) X"), this left hasMethodSet true even
though the actual (filtered) method set is empty, causing an
unnecessary empty method-set global and methodSet field to be emitted
for that type's type descriptor.
Compute hasMethodSet from the same filtered loop that produces
numMethods, so it's true only when at least one non-generic method
exists.
Go 1.27 promoted "generic methods" (methods with their own type
parameters, independent of any type parameters on the receiver) out
of the GenericMethods experiment, e.g.:
func (r *Rand) N[Int intType](n Int) Int
Boxing a value of a type with such a method into an interface caused
tinygo to panic while building the runtime type's method table:
getTypeCode -> getMethodSetValue -> getTypeCodeName
getTypeCodeName's type switch has no case for *types.TypeParam, and a
generic method's Signature carries the method's own type parameters
in its parameter/result types (e.g. "Int" above), so encoding it into
a type code name panicked with "unknown type: <param name>".
This affected any package using math/rand/v2.Rand.N, including much of
the math/rand/v2 test suite, since printing or otherwise boxing a
*Rand into an interface is common.
Upstream reflect deliberately excludes generic methods from
Type.NumMethod()/Type.Method() (they can't be instantiated implicitly,
and a generic method can never satisfy an interface method), so mirror
that behavior: add isGenericMethod, which checks whether a method's
Signature has its own type parameters, and skip such methods when
building the runtime method count, method set value, and method set
in compiler/interface.go.
Fixes a panic isolated to:
package main
type T struct{}
func (t T) M[X int](n X) X { return n }
func main() {
var t T
var i interface{} = t
_ = i
}
- Fix SetInterrupt error capture: use a package-level variable instead
of a named return captured by the sync.Once closure, avoiding a
closure allocation on every call.
- Extract GPIO interrupt handler from inline closure to named function
(handleGPIOInterrupt), matching the UART handler pattern.
- Unexport ESP32-specific UART fields (txrxSignal, rtsctsSignal,
parityErrorDetected, dataErrorDetected, dataOverflowDetected).
- Change UART.Configure to return error, consistent with ESP32C3/C6.
- Clarify why UART0 does not return early when pins are already wired.
Signed-off-by: deadprogram <ron@hybridgroup.com>
Remove unused cpuIntUsed and cpuIntToPeripheral variables from
interrupt_esp32.go because these were declared but never read.
Fix _globals_end in the linker script to cover .data in addition to
.bss and .wifi_bss. Previously the GC scan range ended at
_wifi_bss_end, missing any heap pointers stored in initialized
globals (.data section). Extend to _edata so the conservative
collector sees all global root pointers.
Signed-off-by: deadprogram <ron@hybridgroup.com>
Work around an lld (LLVM 22) bug where l32r PC-relative offsets are
miscalculated when auto-generated .literal.* sections are prepended to
.text.* sections by the linker script. The assembler emits .literal
entries for movi instructions whose constants exceed the 12-bit signed
range; lld then resolves the l32r relocations with incorrect offsets,
causing every l32r in the boot code to load from the wrong literal
pool entry.
The symptom was a TG0WDT_SYS_RESET boot loop: the watchdog disable
code loaded wrong register addresses via l32r and silently wrote to
the wrong peripheral registers, leaving the watchdog running.
Fix by constructing PS_WOE_MASK (0x40000) with movi+slli instead of a
single large-constant movi, eliminating all auto-generated .literal
section entries. This is compatible with both LLVM 20 and LLVM 22.
Also revert DRAM origin to 0x3FFAE000 (200K) and remove rom_phyFuns
symbols that belong in a separate WiFi commit.
Signed-off-by: deadprogram <ron@hybridgroup.com>
Add full flash XIP support for ESP32, enabling code and read-only data to
execute/load directly from flash via the MMU cache rather than consuming
precious SRAM. This increases available RAM from ~328KB to effectively
unlimited for code/rodata, while keeping ~121KB for the Go heap.
Changes:
- src/device/esp/esp32.S: Add MMU initialization in call_start_cpu0
- Call ROM bootloader mmu_init() and cache_flash_mmu_set() to map DROM/IROM
- Enable flash cache via ROM Cache_Read_Enable()
- Fix tinygo_scanCurrentStack to spill all register windows for GC
- targets/esp32-interrupts.S: Add exception diagnostics
- targets/esp32.ld: Major linker script restructure for XIP
- Add DROM (4MB @ 0x3F400000) and IROM (4MB @ 0x400D0000) regions
- Move .rodata to DROM, main .text to IROM (both flash-mapped)
- Keep boot code, vectors, and WiFi blob IRAM sections in SRAM0
- Create WiFi arena in SRAM1 pool 7/6 (64KB @ 0x3FFF0000)
- Move .bss and heap to SRAM2 (200KB @ 0x3FFAE000), avoiding ROM/MAC regions
- Add _drom_flash_addr variable (patched by builder with flash offset)
- targets/esp32.json: Add linker wrap flags for malloc/free and WiFi functions
Signed-off-by: deadprogram <ron@hybridgroup.com>
Goexit cannot run deferred functions on architectures without panic
unwinding. Query runtime.supportsRecover before calling it so unsupported
targets report an error instead of leaving the test runner blocked forever.
LLVM ComputeValueVTs recursively expands arrays and structs into one
value type per scalar leaf. SelectionDAG call lowering allocates data
structures proportional to this count, which makes very large values
exhaust memory or crash LLVM.
Count scalar leaves and use pointers for internal parameters and results
when the count exceeds 1024. A result pointer is the first parameter,
and aggregate parameters point to read-only memory. Exported function
types are unchanged.
Keep these SSA values in memory and copy them with memcpy when needed.
Handle calls, interfaces, maps, channels, selects, defers, goroutines,
phis, and multiple results. Update the expected compiler IR and re-enable
the native compress/flate tests.
Add compiler coverage for large aggregate parameters and results,
including function values, interfaces, maps, channels, selects, deferred
calls, goroutines, phis, and multiple results.
createInstruction records each LLVM value in locals, emits stack object
tracking, and constructs function returns inline.
Move these operations to setValue and createReturn. This keeps the
instruction switch from having to know how an SSA value or function
result is emitted.
createFunctionCall and createGo currently lower arguments before they
determine whether the call is direct, an interface invoke, or through a
function value.
Resolve the callee, function type, and context first, then append the
arguments in the same order as before. This does not change the
generated LLVM IR.
getFunction and getLLVMFunctionType duplicate the construction of LLVM
result types for functions with zero, one, or multiple results.
Move this code to getLLVMResultType. Also split the existing parameter
expansion code into expandDirectFormalParamType so callers can request
the current flattened parameter types directly.
Map, channel, index, and goroutine lowering each create allocas, store
SSA values into them, load results, and emit lifetime intrinsics.
Add helpers for these operations and use runtimeValueResult for runtime
calls that write a value and an optional comma-ok result. The generated
LLVM IR is unchanged.
createDefer builds an LLVM struct containing the deferred function and
its arguments. createRunDefers separately reconstructs the same struct
type before loading the fields.
Keep each LLVM value together with its type while building a deferred
call record, and load all argument fields through one helper. This
removes the duplicate lists of field types and field loads.
The shared timekeeping code assumes the TIMG0 timer counts at 40MHz,
but on the ESP32-C6 the timer clock defaults to the 40MHz XTAL, giving
a 20MHz tick with the /2 prescaler and making all delays run twice as
long. Select PLL_F80M (80MHz) and enable the timer group clock so the
25ns/tick assumption holds.
Signed-off-by: deadprogram <ron@hybridgroup.com>
Currently, calling any sync.Map method from inside the sync.Map.Range
callback f deadlocks. Moreover, Go's sync.Map explicitly permits the
Range callback to call other methods on the map ("Range does not
block other methods on the receiver; even f itself may call any
method on m").
This commit prevents the deadlock by changing sync.Map.Range to:
- copy the map's keys under the lock
- release the lock
- iterate over the key snapshot
A snapshot satisfies Go's sync.Map.Range contract, which only
requires that no key is visited more than once and may reflect any
mapping from any point during the call.
Using a snapshot keeps the implementation simple, in line with this
file's stated scope ("no more efficient than a map with a lock").
Also added TestMapRangeAndDelete regression test, which deletes map
entries from inside the map's Range callback.
Replace movi instructions with constants outside the 12-bit signed
range (-2048..2047) with movi+slli sequences. Large constants cause
the assembler to emit auto-generated .literal section entries, which
triggers an lld bug where l32r PC-relative offsets are miscalculated
when .literal.* sections are merged with .text.* sections.
Signed-off-by: deadprogram <ron@hybridgroup.com>
This fixes the builder for ESP32 (original) by separating the RAM segments loadable by the
ROM bootloader from flash-mapped segments (DROM/IROM) which require MMU setup by startup code.
These changes are needed for to allow for ESP32 to correctly flashing large programs which
as a result require XIP support.
Signed-off-by: deadprogram <ron@hybridgroup.com>
Define the board's external crystal (HSE) frequency `xtalHz` in the
respective `board_*.go` files. Per-topology PLL tables (F1, F4, F7)
will compute the register dividers from it.
Moving this parameter to the board definition level cleanly isolates
board hardware characteristics from general MCU chip configurations,
eliminating the need for custom target build tags. Targets using
HSE-clocked STM32 chips must define `xtalHz` or fail to build.
Clang on i386 mingw emits calls to _alloca (decorated as __alloca)
for stack probing. This was provided by chkstk2.S, not chkstk.S
which only provides __chkstk_ms.
Signed-off-by: deadprogram <ron@hybridgroup.com>
cc1as: change AssemblerInvocation.Triple from std::string to
llvm::Triple, matching upstream LLVM 22 and fixing deprecation warnings
for lookupTarget, createMCRegInfo, createMCAsmInfo, and
createMCSubtargetInfo.
interp: always use ConstNamedStruct in rawValue.toLLVMValue instead of
falling back to ConstStruct for unnamed structs. LLVM 22 uses anonymous
identified struct types where previous versions used literal structs;
ConstStruct creates a literal type that doesn't match, causing an
"initializer type mismatch" panic for globals like fmt.ppFree.
compileopts: add build-tag-guarded feature patching for pre-LLVM 20
(strip +bulk-memory-opt and +call-indirect-overlong from wasm features)
and restructure into three files covering all LLVM version ranges.
targets: strip redundant negative features from RISC-V target JSONs
(esp32c3, esp32c6, fe310, k210, riscv-qemu, tkey). These ~190 negative
features per target listed every extension LLVM knows about that the
target doesn't use, but LLVM disables them by default. They became stale
across LLVM versions, causing "not a recognized feature" warnings. Keep
only positive features and -relax.
Signed-off-by: deadprogram <ron@hybridgroup.com>
Builder:
- Update clang.cpp for LLVM 22 API changes: DiagnosticOptions is no
longer ref-counted, TextDiagnosticPrinter and DiagnosticsEngine take
references instead of pointers, createDiagnostics() signature changed.
- Update cc1as.cpp: clang/Driver/Options.h moved to
clang/Options/Options.h, namespace changed from clang::driver::options
to clang::options, MCInstPrinter now passed as unique_ptr.
- Add new LLVM 22 libraries to GNUmakefile: clangAnalysisLifetimeSafety,
clangOptions, LLVMDTLTO, and dtlto component.
- Add llvm22 build tag to all build/test commands.
CGo:
- Handle CXType_Unexposed in libclang.go by resolving via canonical
type. LLVM 22 reports builtin type aliases (e.g. __size_t) as
Unexposed instead of Typedef.
- Always make C typedefs into Go type aliases. LLVM 22 changed
getTypedefDeclUnderlyingType to return CXType_Enum directly instead
of wrapping in an elaborated type.
Compileopts:
- Add build-tag-guarded ClangTriple() to substitute wasm32-unknown-wasi
with wasm32-unknown-wasip1 for LLVM 22 (deprecated triple).
- Add build-tag-guarded patchFeatures() to map renamed Xtensa features
(atomctl, memctl, timerint, esp32s3) for LLVM 22.
Targets:
- Remove -zca from RISC-V target feature strings (esp32c3, esp32c6,
fe310, k210, riscv-qemu, tkey). LLVM 22 now implies +zca from +c.
- Remove -zcd from k210. LLVM 22 now implies +zcd from +c,+d.
Tests:
- Change TestClangAttributes to check individual feature flags instead
of exact string match, allowing new LLVM features without failures.
- Update TestBinarySize expected values for LLVM 22 codegen.
Signed-off-by: deadprogram <ron@hybridgroup.com>