Commit Graph

4570 Commits

Author SHA1 Message Date
Damian Gryski aed8116b22 GNUmakefile: add context and expvar to stdlib tests 2026-04-17 09:12:32 +01:00
Damian Gryski f6c759ccbf GNUmakefile: add encoding/xml to stdlib tests on Linux 2026-04-15 22:43:04 +01:00
deadprogram 4b389b90e8 targets: add pins/setup for Arduino UNO Q board QWIIC connector
Signed-off-by: deadprogram <ron@hybridgroup.com>
2026-04-15 16:52:32 +01:00
deadprogram 4c3680635e machine/stm32: fix UART interrupt storm caused by uncleared overrun error
The UART handleInterrupt handler unconditionally read RDR on every
interrupt without checking which flag triggered it. On newer STM32
USART peripherals (U5, L4, L5, L0, G0, F7, WL), RXNEIE enables
interrupts for both RXFNE (data ready) and ORE (overrun error).
Unlike older families (F1, F4), ORE is not cleared by reading the
data register, it must be explicitly cleared via the ICR register.

When an overrun occurred (e.g. serial data arriving while ADC
busy-waits in Get()), ORE would trigger the interrupt, the handler
would fire without clearing it, and the interrupt would re-trigger
immediately, causing an infinite interrupt storm that locks up the
CPU.

Fix by:
- Checking RXFNE/RXNE (bit 5) before reading data from RDR
- Clearing ORE (bit 3) via ICR on newer peripherals when set
- Adding errClearReg field to UART struct, set to &Bus.ICR in
  setRegisters() for all ICR-capable families
- Preserving the SR+DR clearing sequence for older F1/F4 families

Signed-off-by: deadprogram <ron@hybridgroup.com>
2026-04-15 15:42:06 +01:00
Joel Wetzell 0755145824 create generic targets for esp32 boards 2026-04-15 10:28:33 +01:00
Jake Bailey eabd1ddce0 os: add UserCacheDir and UserConfigDir 2026-04-15 08:19:08 +01:00
deadprogram 0e84235f9a machine/esp32s3,esp32c3: add txStalled flag to skip USB serial spin when no host
When no USB host is reading, flushAndWait() spins 50K iterations per
FIFO-full event. With putchar calling WriteByte per byte, the cumulative
delay starves I2C and other peripherals, freezing displays.

Add a txStalled flag: the first FIFO-full triggers one flushAndWait
attempt. If it fails (no host), txStalled is set and all subsequent
writes return immediately with no spin — just a register read and a
bool check. When a host reconnects, SERIAL_IN_EP_DATA_FREE goes back
to 1, bypassing the stall path and clearing the flag automatically.
2026-04-14 18:26:30 +01:00
deadprogram 894839484c net: update to Go 1.26.2 net package
Signed-off-by: deadprogram <ron@hybridgroup.com>
2026-04-14 07:57:09 +01:00
deadprogram 1fadd0e772 builder: use target-specific -march for RISC-V library compilation
The -march flag for compiling C libraries (compiler-rt, picolibc) was
hardcoded to rv32imac for all riscv32 targets. This is incorrect for
targets that lack the atomic extension, such as ESP32-C3 (rv32imc) and
TKey (rv32iczmmul).

Extract the -march value from the target's cflags when available,
falling back to the previous defaults (rv32imac, rv64gc) for targets
that don't override it.

Fixes #5114

Signed-off-by: deadprogram <ron@hybridgroup.com>
2026-04-13 08:09:26 +01:00
deadprogram eba6e7a428 machine/esp32s3,esp32c3: make USB Serial/JTAG writes non-blocking when FIFO is full
When no USB host is reading (e.g. board not connected to a serial
monitor), WriteByte and Write would spin for up to 200k iterations
per byte waiting for the FIFO to drain. This stalled the entire
application, freezing unrelated peripherals like I2C displays.

Reduce flushTimeout from 200,000 to 50,000 iterations (~3ms) which
is enough for 2-3 USB frames when a host is connected, but short
enough that serial output won't freeze the application when no host
is reading. Serial output is best-effort; callers like putchar
already ignore write errors.

Applies to both ESP32-S3 and ESP32-C3 which share the same USB
Serial/JTAG controller design.
2026-04-13 06:23:23 +01:00
deadprogram f4a6e0373b main: update espflasher and auto-use best available flashing options on esp32
Signed-off-by: deadprogram <ron@hybridgroup.com>
2026-04-11 20:31:21 +01:00
deadprogram d274545e63 targets: add "adb" flash method using Android Debug Bridge
Add a new flash method that uses adb to flash boards over Android Debug
Bridge. The method supports running pre-flash shell commands via
"adb shell", pushing the firmware binary via "adb push", and running
post-flash shell commands with a {remote} token for the remote path.

New target JSON fields:
- adb-pre-commands: shell commands to run before pushing firmware
- adb-push-remote: remote device path for adb push
- adb-post-commands: shell commands to run after pushing firmware

Switch arduino-uno-q target to use the new adb flash method with
openocd running on the remote device.

Signed-off-by: deadprogram <ron@hybridgroup.com>
2026-04-11 17:19:46 +01:00
deadprogram f74d25c882 build: use Golang 1.26 for all builds
Signed-off-by: deadprogram <ron@hybridgroup.com>
2026-04-11 12:38:36 +01:00
deadprogram 618c689246 runtime: fix Darwin syscall return value truncation and lost arguments
Go 1.26 replaced the individual Darwin syscall entry points (syscall,
syscallX, syscallPtr, syscall6, syscall6X) with two variadic functions:
syscalln and rawsyscalln. The old wrappers now have Go bodies that call
these, then use errno/errnoX/errnoPtr to interpret the result.

This caused two bugs in our rawsyscalln implementation:

1. Return value truncation: We used call_syscall/call_syscall6 which
   return int32, truncating 64-bit results (pointers from fdopendir,
   offsets from lseek, addresses from mmap). For example, a DIR* pointer
   returned by fdopendir would lose its upper 32 bits on arm64, causing
   SIGSEGV when later accessed.

2. Lost 4th argument: The case 4/5/6 fallthrough had 'a3 = args[3]'
   instead of 'a4 = args[3]', and a3 was immediately overwritten by
   'a1, a2, a3 = args[0], args[1], args[2]'. This lost the 4th syscall
   argument entirely, breaking pread (offset=0) and causing wrong data
   to be read from files.

Fix by using call_syscallX/call_syscall6X (returning full uintptr),
always reading errno (letting the Go wrappers decide what to do with
it), and correcting the argument assignment.
2026-04-11 12:38:36 +01:00
deadprogram 9d29971755 interp: make ptrtoint size mismatch a recoverable error
Go 1.26 changed Darwin's rawSyscall/Syscall from assembly stubs to Go
wrappers that call variadic rawsyscalln/syscalln. When the interp tries
to evaluate syscall.init() at compile time (which calls Getrlimit →
rawSyscall → rawsyscalln), it encounters a ptrtoint of a function
pointer and fails with 'ptrtoint integer size does not equal pointer
size'.

Make this a recoverable error so the interp reverts the init
interpretation and defers it to runtime, matching the behavior for other
uninterpretable init functions.
2026-04-11 12:38:36 +01:00
deadprogram 451c57af92 runtime: add syscall.runtimeClearenv for Go 1.26
Go 1.26 added syscall.runtimeClearenv (called by syscall.Clearenv) which
must be provided by the runtime via go:linkname. Without it, the os
package fails to link.
2026-04-11 12:38:36 +01:00
deadprogram 59feac28b9 internal/syscall/unix: implement GetRandom for WASI targets
Go 1.26's crypto/internal/sysrand uses internal/syscall/unix.GetRandom
on Linux-like targets (including wasip2 which sets GOOS=linux). The
existing stub panicked with 'todo: unix.GetRandom', causing crypto/ecdsa
tests to fail on wasip2.

Implement GetRandom on WASI targets (wasip1, wasip2) by calling the
arc4random_buf libc function that TinyGo's runtime already provides.
For other TinyGo targets, return ENOSYS so sysrand can fall back to
/dev/urandom.
2026-04-11 12:38:36 +01:00
deadprogram c1f48fc79a loader, crypto/internal/entropy: fix 32 MiB RAM overflow on microcontrollers
Go 1.26 added a CPU jitter-based SP 800-90B entropy source for FIPS 140-3
compliance (crypto/internal/entropy/v1.0.0). It declares a 32 MiB global
ScratchBuffer ([1<<25]byte) used for memory access timing noise. On systems
with virtual memory this stays in .noptrbss and is lazily paged, but on
baremetal targets it becomes static RAM, causing fatal overflow (e.g.
pybadge with 192 KB SRAM reports 33 MB overflow).

Since FIPS jitter entropy is never used on TinyGo targets (fips140.Enabled
is always false, so drbg.Read falls through to sysrand.Read), provide a
TinyGo overlay that replaces ScratchBuffer with [0]byte and stubs out all
entropy functions with panics.
2026-04-11 12:38:36 +01:00
deadprogram 3c07a36e95 loader, unicode/utf8: fix hiBits overflow on 16-bit AVR targets
Go 1.26 added SWAR optimizations to unicode/utf8 that use:

  const ptrSize = 4 << (^uintptr(0) >> 63)
  const hiBits = 0x8080808080808080 >> (64 - 8*ptrSize)

This formula only distinguishes 32-bit and 64-bit architectures.
On AVR (16-bit uintptr), ptrSize computes as 4, and hiBits becomes
0x80808080 (2155905152) which overflows the 16-bit uintptr type.

Fix by providing a patched unicode/utf8 overlay for Go 1.26+ that
uses a ptrSize formula handling all three sizes (16/32/64-bit):

  const ptrSize = 1 << (^uintptr(0)>>15&1 + ^uintptr(0)>>31&1 + ^uintptr(0)>>63&1)

This evaluates to 2 on AVR, 4 on 32-bit, and 8 on 64-bit. The
word() helper also gains a ptrSize==2 case for 16-bit loads.
2026-04-11 12:38:36 +01:00
deadprogram 98b3c27c76 builder: fix SIGSEGV when stripping duplicate function definitions
The previous approach of erasing basic blocks one-by-one from
duplicate function definitions could crash with a segfault. When
a function has complex control flow (branches, switches, PHI nodes),
deleting a basic block that is still referenced by instructions in
other blocks of the same function causes use-after-free in LLVM.

LLVM's C++ Function::deleteBody() avoids this by calling
dropAllReferences() on all blocks first, but that API is not
exposed in the Go LLVM bindings.

Fix this by using a completely different approach: instead of
manually deleting the function body, set the duplicate function's
linkage to LinkOnceODRLinkage. This tells the LLVM linker that the
definition can be merged with another copy, causing it to prefer
the already-linked ExternalLinkage definition in the destination
module. The result is the same (the runtime's definition wins) but
without any unsafe block manipulation.
2026-04-11 12:38:36 +01:00
deadprogram ddacdfacd5 compiler, runtime: fix SyscallN handling for Windows on Go 1.26+
Go 1.26 changed all Windows syscall wrappers in zsyscall_windows.go
to use SyscallN instead of fixed-argument Syscall/Syscall6/etc. The
SyscallN function now has a body that calls an unexported syscalln
function (provided by runtime via //go:linkname).

TinyGo's existing createSyscall compiler builtin used call.Args[2:]
to extract syscall arguments, but for variadic SyscallN the SSA
representation passes args as a slice value (not individual args),
causing call.Args[2:] to be empty -- resulting in zero arguments
being passed to Windows API calls and 0xc0000005 access violations.

Fix this by:
1. Excluding syscall.SyscallN from builtin interception, letting
   Go 1.26's function body compile normally (it calls syscalln)
2. Adding a new createSyscalln compiler builtin that intercepts
   syscall.syscalln and correctly handles the variadic slice:
   - Generates a switch on the arg count n (0-18 cases)
   - Each case loads args from the slice via GEP/Load
   - Wraps calls with SetLastError(0)/GetLastError() as before
   - Handles i386 stdcall conventions
3. Adding runtime stubs for both Go versions:
   - go1.26: syscall.syscalln stub (body intercepted by compiler)
   - pre-go1.26: syscall.SyscallN stub (linker satisfaction)
2026-04-11 12:38:36 +01:00
deadprogram 2d477e069d builder, runtime: fix duplicate symbol error with Go 1.26+ on Windows
Go 1.26 changed syscall.loadlibrary, syscall.loadsystemlibrary, and
syscall.getprocaddress from declarations to definitions in
syscall/dll_windows.go. TinyGo's runtime also defines these via
//go:linkname, causing "symbol multiply defined!" during LLVM module
linking.

Resolve this by detecting duplicate function definitions before calling
llvm.LinkModules and turning the incoming duplicate into a declaration,
so the runtime's version wins. TinyGo's implementations must take
precedence because Go 1.26's versions depend on //go:cgo_import_dynamic,
which TinyGo does not support.

Also fix the signature of syscall_loadsystemlibrary to match the
standard library (remove unused absoluteFilepath parameter).

Signed-off-by: deadprogram <ron@hybridgroup.com>
2026-04-11 12:38:36 +01:00
Damian Gryski ed1a56785a internal, runtime: add internal fips bool 2026-04-11 12:38:36 +01:00
Damian Gryski f496571747 compiler: add instrinsic for crypto/internal/constanttime.boolToUint8 2026-04-11 12:38:36 +01:00
Damian Gryski 17fed5980b internal/abi: add EscapeNonString, EscapeToResultNonString 2026-04-11 12:38:36 +01:00
Damian Gryski 2ff04f1a87 runtime: split syscall functions for darwin changes for 1.26 2026-04-11 12:38:36 +01:00
Damian Gryski f763865c5c src/internal/itoa: resurrect from Go stdlib
We use this a bunch. Upstream switched to `internal/strconv` which is much heavier.
2026-04-11 12:38:36 +01:00
Damian Gryski 52edf52245 builder: claim we support 1.26 now 2026-04-11 12:38:36 +01:00
Patricio Whittingslow 8161b766d3 add soypat/lneto to corpus 2026-04-09 16:19:33 +01:00
deadprogram 709349e24b device/esp: fix tinygo_scanCurrentStack to spill register windows
The previous implementation was a bare tail-jump to tinygo_scanstack
without spilling any registers or passing an sp argument.  On Xtensa
windowed ABI, heap pointers held in physical registers were invisible
to the conservative GC, causing it to collect live objects and leading
to nil pointer dereferences under allocation pressure.

Flush all register windows to the stack using recursive call4 (15
levels for NAREG=64), then pass the current sp to tinygo_scanstack so
the GC scan from sp to stackTop covers every live value.  Interrupts
are briefly masked during the spill to prevent window-overflow
exceptions from interfering.

Fixes crashes on ESP32-S3 observed when serving concurrent HTTP
requests.

Signed-off-by: deadprogram <ron@hybridgroup.com>
2026-04-08 18:51:42 +01:00
MaximAL 5fd4878574 Fix grammar in quote 2026-04-07 10:39:41 -07:00
deadprogram a24dc8c543 esp32s3: improve exception handlers, add procPin/procUnpin, and linker wrap flags
Rewrite kernel and double exception handlers to save EXCCAUSE/EPC1 to
RTC STORE registers before triggering a software reset, replacing the
LED-blink diagnostic with post-mortem debug info that survives reset.

Add user exception dispatch in the level-1 handler with a weak
espradio_user_exception symbol so programs without espradio still link.

Implement procPin/procUnpin for Xtensa using RSIL/WSR PS to properly
disable interrupts during atomic operations. Fix abort() to use a
waiti loop instead of bare spin.

Add --wrap ldflags for malloc/calloc/free/realloc/ppCheckTxConnTrafficIdle
to support espradio WiFi blob integration.

Signed-off-by: deadprogram <ron@hybridgroup.com>
2026-04-07 16:27:02 +02:00
deadprogram c3d514a751 esp32s3: fix Xtensa register window spill using recursive call4 in task switching
Replace the ROTW-based register flush with a recursive call4 approach
that properly triggers hardware window-overflow exceptions. ROTW only
modifies WindowBase without saving registers, causing corruption when
switching goroutines. The recursive call4 correctly spills all 15 window
panes. Also clear WindowStart after the stack switch to prevent stale
overflow of garbage register values.

Add tinygo_task_current export for C interop.

Signed-off-by: deadprogram <ron@hybridgroup.com>
2026-04-07 16:27:02 +02:00
deadprogram 5b7a2c73db esp32s3: update linker script and boot assembly for multi-page flash XIP mapping
Extend the linker script with proper IROM/DROM section layout for flash
execute-in-place. Update the boot assembly MMU init to dynamically map
all required flash pages based on _irom_end/_drom_end symbols instead
of hardcoding a single page.

Signed-off-by: deadprogram <ron@hybridgroup.com>
2026-04-07 16:27:02 +02:00
deadprogram aaf6a36c55 esp32s3: add flash XIP boot assembly with cache/MMU init
The ESP32-S3 ROM bootloader loads IRAM/DRAM into SRAM but does not
configure the flash cache or MMU. Previously the target incorrectly
reused the ESP32 boot assembly (esp32.S) which lacks flash XIP support.

Add a dedicated esp32s3.S boot assembly that:
- Sets up windowed-ABI registers, stack, and FPU
- Disables all watchdog timers (RTC, TIMG0, TIMG1, Super WDT)
- Configures VECBASE and clears PS.EXCM before any callx4
- Calls ROM functions to configure cache modes:
  rom_config_instruction_cache_mode (16KB, 8-way, 32B line)
  rom_config_data_cache_mode (32KB, 8-way, 32B line)
- Initializes MMU, maps flash page 0 for IROM and DROM,
  clears bus-shut bits, and enables both caches
- Jumps to runtime.main in IROM (flash)

Update the linker script (esp32s3.ld) to place .text and .rodata in
flash-mapped regions (IROM/DROM) with proper alignment for the MMU
page size. Update esp32s3-interrupts.S with proper exception vector
handlers. Point esp32s3.json at the new esp32s3.S instead of esp32.S.

Signed-off-by: deadprogram <ron@hybridgroup.com>
2026-04-07 16:27:02 +02:00
deadprogram dc6e0e23b9 cgo: allow for changes to 'short-enums' flag
This allows for changes to the 'short-enums' flag when
using CGo since TinyGo already does this, and it is
needed for the esp32s3 processor.

Signed-off-by: deadprogram <ron@hybridgroup.com>
2026-04-07 16:27:02 +02:00
Abhishek Goyal 44b0c79eaf loader: support "all:" prefix in //go:embed patterns
The "all:" prefix in //go:embed directives instructs the compiler to
  include hidden files (starting with "." or "_") when embedding a
  directory. Previously, the prefix was passed literally to path.Match,
  which would never match.

  Introduce an embedPattern struct that parses and validates the pattern
  at construction time via newEmbedPattern(). The "all:" prefix is
  stripped once and stored along with the glob pattern, avoiding repeated
  string prefix checks. Pattern validation is absorbed into the
  constructor, guaranteeing that any embedPattern value is valid and
  eliminating the need for separate validation loops.

  Fixes embedding with patterns like "//go:embed all:static".
2026-04-05 14:15:40 +02:00
deadprogram 27e5baeb57 esp32s3: use TIMG0 alarm interrupt for sleepTicks
Replace the busy-wait sleepTicks with an interrupt-driven version that
sets a TIMG0 timer alarm and waits for the interrupt to fire. The timer
alarm handler disables INT_ENA at the peripheral level to prevent
level-triggered re-assertion; sleepTicks re-enables it after each wake.

This avoids burning CPU cycles during time.Sleep and similar delays.
2026-04-05 14:15:40 +02:00
deadprogram a6a4f85e61 esp32s3: replace inline ISR with full interrupt vector handler
Replace the minimal inline ISR (which only disabled INTENABLE) with a
full level-1 interrupt handler that saves/restores the interrupted
context and dispatches to Go's handleInterrupt.

The handler uses callx4 (not callx0) to call into Go code because:
- callx0 does not set PS.CALLINC, so the Go function's entry
  instruction uses stale CALLINC from the interrupted code, causing
  wrong window rotation and a garbage stack pointer.
- callx4 explicitly sets CALLINC=1, and our frame pointer (a1) is
  outside the callee's register window so it is preserved.

Also updates the USB Serial/JTAG ISR to disable INT_ENA (peripheral
level) instead of relying on INTENABLE, and adds signalInterrupt to
the dispatcher so sleepTicks can be woken by any interrupt.
2026-04-05 14:15:40 +02:00
Carlos Henrique Guardão Gandarez 3386316b9f targets: add esp32s3-supermini 2026-04-05 14:15:40 +02:00
Carlos Henrique Guardão Gandarez 410bb9c103 feat: add inheritable-only field to filter processor-level targets (#5270)
* feat: add inheritable-only field to hide processor-level targets from listing

Processor-level targets like esp32, rp2040, etc. have flash-method set
so they leak through the existing heuristic filter in GetTargetSpecs and
appear in `tinygo targets` output. Add an "inheritable-only" JSON field
that is checked on raw JSON before inheritance resolution, preventing
these non-board targets from being listed while keeping them loadable
for direct builds and inheritance.

Ref: tinygo-org/tinygo#5178

* fix: prevent inheritable-only from propagating to child targets

The InheritableOnly bool field was propagating from parent to child
targets through overrideProperties, which would hide board targets
from GetTargetSpecs. Fix by preserving/restoring the field across
resolveInherits. Also simplify GetTargetSpecs by removing the raw
JSON pre-check workaround and remove nonexistent esp32c6 from tests.

* prevent build commands to use inheritable only targets
2026-04-05 14:15:40 +02:00
deadprogram f176b3a480 esp32s3: switch USB implementation to use interrupts instead of polling
The previous implementation for USB was using polling instead of using
interrupts. This changes that.

Signed-off-by: deadprogram <ron@hybridgroup.com>
2026-04-05 14:15:40 +02:00
Ron Evans 9b1a3a2236 esp32s3: add interrupt support (#5244)
* esp32s3: add interrupt support

This finally adds the long awaited support for interrupts on the
Xtensa arch. Initially just for the ESP32-S3 but then others.

Signed-off-by: deadprogram <ron@hybridgroup.com>

* esp32s3: get interrupts working correctly

There were a number of needed changes in order to get interrupts correctly working
on the esp32s3 processor:

- PS.UM=1 in interruptInit() - routed interrupts to user exception vector (0x340)
instead of kernel (0x300)
- Inline ISR in the vector slot - external handlers via j/call0 crashed (likely
clang Xtensa literal pool issue with large movi constants in separate sections)
- Disable INTENABLE (not just INT_CLR) - the USB RX interrupt is level-triggered;
clearing INT_CLR alone causes infinite re-entry since data is still in the FIFO
- Buffered() re-enables INTENABLE after draining the hardware FIFO

Signed-off-by: deadprogram <ron@hybridgroup.com>

---------

Signed-off-by: deadprogram <ron@hybridgroup.com>
2026-04-05 14:15:40 +02:00
Damian Gryski b29edadf48 reflect: fix reflect.TyepAssert for structs 2026-04-05 14:15:40 +02:00
deadprogram d04332d688 fix: use external 7zip for scoop installs on Windows
Signed-off-by: deadprogram <ron@hybridgroup.com>
2026-04-05 14:15:40 +02:00
deadprogram 547288529c chore: update all github actions to latest versions
Signed-off-by: deadprogram <ron@hybridgroup.com>
2026-04-05 14:15:40 +02:00
deadprogram bd8de8719f interrupt/esp32c3: add Enable stub for QEMU test target
Signed-off-by: deadprogram <ron@hybridgroup.com>
2026-04-05 14:15:40 +02:00
deadprogram 2fd44ac341 build: let scoop run updates to resolve binaryen install failures on Windows
Signed-off-by: deadprogram <ron@hybridgroup.com>
2026-04-05 14:15:40 +02:00
deadprogram dc30aef687 builder: fix panic in findPackagePath when using -size short
This fixes an "index out of range" panic that occurs when calculating
binary sizes. The strings.SplitN operation in findPackagePath can sometimes
return a slice with only one element, so we now verify the length of the
slice before attempting to access the second element.

Signed-off-by: deadprogram <ron@hybridgroup.com>
2026-04-05 14:15:40 +02:00
deadprogram 29cadaa23b main: add extra second of delay when flashing esp32 boards before reset
Signed-off-by: deadprogram <ron@hybridgroup.com>
2026-04-05 14:15:40 +02:00