* pinout yamls removed
* machine: implement default UART pin configuration for Embedfire boards
* flash command moved to chip level so VS Code plugin can select bare chip
* machine: add support for alternate pin mode configuration
* add build targets for embedfire on py32
* add support for embedfire target in GNUmakefile for py32
* lib/py32-svd: remove duplicate DBGMCU.IDCODE CODE field
Update submodule to fix duplicate SetIDCODE/GetIDCODE method
declarations in the generated py32f002bxx.go device file.
* update subproject commit reference in py32-svd
* refactor: update CPU frequency handling in machine and runtime packages
* refactor: replace ConfigureUARTPin function with direct pin configuration in UART setup
* SetAltFunc documentation for GPIO pin alternate functions
* refactor: improve UART write and flush error handling with timeout
* machine/py32: generalize UART driver to any USART
Add a per-instance setup func to the UART type so the driver is no longer
hardwired to USART1. DefaultUART stays USART1; add UART2 (USART2) in a
separately build-tagged file since py32f002x parts lack USART2. RX IRQ
handlers reference runtime-assigned vars to break the init cycle, and setup
is assigned in the var initializer so it runs before InitSerial.
Add the py32f003_32k_4k target (32K flash / 4K RAM).
* Add canonical PY32F002, F003, and F030 density targets
Use CMSIS/pyocd device names for target files and build tags. Add all F003 and F030 densities plus F002A/B, correct F002B to 24K flash and its own startup file, fix the F030x8 pyocd target, and update Embedfire inheritance.
* Add targets for all PY32 CMSIS devices
* Support all PY32 register layout variants
* machine/py32: use generated register definitions
* machine/py32: fix alternate-function documentation
* machine/py32: report the configured CPU frequency
* machine/py32: use unsafe.Add for GPIO ports
* machine/py32: bound and yield UART polling
* machine/py32: configure UART pins from UARTConfig
* build: use the current PY32 SVD repository URL
* test: cover PY32 UART register layouts
* machine/py32: restore dynamic CPU frequency tracking
* machine/py32: share the USART TX-ready bit
* targets/py32: scale system stacks with RAM
* machine/py32: keep clock state internal
* targets/py32: normalize generated metadata
* machine/py32: normalize GPIO configuration
* machine/py32: fix T020 UART setup
* machine/py32: reduce clock variant files
* machine/py32: clean up UART variants
* machine/py32: decouple UART clock capability
* lib/py32-svd: use organization repository
* runtime/py32: name 24MHz HSI encodings
* machine/py32: derive startup clock from capability
* machine/py32: use generated USART clock mask
* machine/py32: name T020 8-bit UART mode
* ci: include PY32 in sharded smoke tests
* runtime: remove PY32 HSI frequency workaround
* add support for UEFI time and UEFI events; fix STOP \n -> \r\n conversion
* make it so both scheduler=none and scheduler=tasks works
* address pr comments
- Renamed/shared the amd64 Win64 ABI task stack Go file for both Windows and UEFI.
- Deleted the duplicate UEFI task stack Go file and old Windows-suffixed Go file.
- Added task_stack_amd64_windows.S unconditionally to targets/uefi-amd64.json.
- Removed the UEFI ExtraFiles() special case from compileopts/config.go.
- Added a scheduler.none tinygo_task_exit stub.
- Removed the custom UEFI sleep override so normal scheduler sleep queue is used.
* revert back to simpler return value for ExtraFiles()
* create uefi specific tasks_none file
* remove unused sleepSchedulerCustom stuff
* add back the uefi tag
* lib: restore macos-minimal-sdk pointer
* runtime: run syscall/js finalizers on wasm without a manual GC
* runtime: address review feedback on finalizer idle GC
* runtime: clear a finished task's args pointer so its arguments are collectable
* runtime: skip the finalizer scan with a per-block registration bit
* runtime: guard the finalizer registration bitmap with gcLock
* testdata: cover finalizer invariants on every scheduler
* main_test: limit the finalizer scheduler variants to linux and darwin
* testdata: wait for the finalizer queue to drain before asserting
* testdata: make the finalizer counters atomic and wait for a known drain count
* runtime: add finalizer bookkeeping asserts under runtime_asserts
* runtime: address finalizer GC review feedback
* testdata: strengthen blocked stack finalizer test
* runtime: fix finalizer cleanup edge cases
* runtime: decouple wasm export scheduling from finalizers
* runtime: avoid redundant wakeups for re-entrant wasm exports
* runtime: simplify finalizer comments
* machine/esp32: add ADC driver
Implements ADC1 on the Xtensa ESP32: InitADC, Configure and Get for
GPIO36, GPIO37, GPIO38, GPIO39, GPIO32, GPIO33, GPIO34 and GPIO35
(channels 0-7). The ADC pins are not contiguous on this chip, so the
pin to channel mapping is a lookup rather than arithmetic as on the
ESP32-S3.
Conversions are driven by the RTC controller under software control,
and Get returns the 12-bit sample scaled to 0..65520 to match the
other ESP ADC drivers.
The analog pads are spread over three unrelated RTC_IO registers
(SENSOR_PADS, XTAL_32K_PAD and ADC_PAD), so pad setup is kept local to
this file rather than adding a PinAnalog mode to machine_esp32.go.
That keeps the change to a single file.
Values are raw and uncalibrated. Unlike the ESP32-C3, S3 and C6
drivers there is no eFuse or self-calibration step; accurate voltage
mapping should be done with a two-point calibration in user code.
ADC2 is not implemented. On the ESP32 it is shared with the Wi-Fi
radio and cannot be used reliably while the radio is active.
Tested on an ESP32 Coreboard V2 with a photoresistor divider on
GPIO36. Readings swept 5056..59824 over the light range, all eight
channels returned independent values, and an invalid pin returned an
error from Configure and 0 from Get.
Signed-off-by: zombieleet <osikwemhev@gmail.com>
* fix: use package level err definiition and return (uint32, bool) from adcRTCGPIO
---------
Signed-off-by: zombieleet <osikwemhev@gmail.com>
Remove the C3 bluetooth hook addresses from esp32s3.ld (on the S3 they
point into the ROM md5/crc thunk table, and being bare assignments they
also shadowed the blob's own definitions), keep the interrupt frame clear
of the 16-byte windowed-ABI save area below SP, and make tinygo_swapTask
hold INTLEVEL across the stack switch while keeping the running frame's
WINDOWSTART bit set.
Signed-off-by: deadprogram <ron@hybridgroup.com>
The guard was on runtime.GOOS == "wasip1", so under wasip2 the three cases that
rely on recover ran anyway. recover does not work on wasm yet, so the panic
escaped and trapped the test binary — which is the tinygo-test-wasip2-fast
failure on this PR.
Checked on runtime.GOARCH instead, since the limitation is wasm's rather than
any one platform's. wasip1, wasip2 and js/wasm all set the tinygo.wasm build
tag, and arch_tinygowasm.go defines GOARCH as wasm for it, so one condition
covers all three of the wasm test targets.
Worth noting for anyone reading targets/wasip2.json: the goarch there is arm,
but that is what is handed to the Go toolchain for package selection —
runtime.GOARCH is the one above.
TinyGo had MakeMap/MakeSlice but not MakeChan. Implement it via the runtime
chanMake primitive (mirroring MakeMap), so packages that call reflect.MakeChan
(e.g. github.com/ugorji/go/codec used by gin) compile and work.
* machine: add USBDevice.Attach and USBDevice.Detach
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.
* machine: make USB Detach sticky on nrf52840
The USB IRQ handler re-enables the DP pull-up on every power-ready
event, silently undoing an earlier Detach. Guard the pull-up write with
a detached flag so the device stays off the bus until Attach is called.
* machine: add USB Attach and Detach to stm32 and esp32 targets
- stm32f4, stm32f7, stm32h7: implement Attach and Detach using the
DCTL soft-disconnect bit that Configure already toggles.
- esp32c3, esp32c6, esp32s3: add no-op stubs to keep user code
portable; the fixed-function USB Serial/JTAG controller has no
software-controlled soft-connect.
* machine: use Attach and Detach in USB Configure
Replace the direct soft-connect register writes in Configure with the
equivalent Attach and Detach calls on atsamd21, atsamd51, rp2040,
rp2350, stm32f4, stm32f7 and stm32h7.
file_unix.go (darwin/linux/wasip) was missing the exported (*File).Chown method
that file_other.go (baremetal/wasm) already has, so callers requiring the full
os.File surface — e.g. github.com/pkg/sftp — failed to compile for the
linux/amd64 TinyGo target. Delegates to the package-level Chown, mirroring
(*File).Truncate.
Reading runtime.MemStats.NumGC is common enough in dependency code that its
absence is a compile error for programs that never look at the value. Rather
than add the field as a constant zero, track it:
- gc_blocks: count completed cycles in runGC, so collections triggered by an
allocation are counted as well as explicit runtime.GC() calls. The counter is
read and written under gcLock, like the other counters beside it.
- gc_boehm: report bdwgc's own gc_no from the prof_stats struct.
- gc_leaking: always 0, since that collector never completes a cycle.
In gcMarkReachable, busy-wait for other cores to enter the interrupt handler and pause before scanning the GC core's stack or globals. Prevents data race where a running core relocates heap references to globals during mark phase.
Using blocksPerStateByte instead of bytesPerBlock caused the old size to be underestimated for multi-block allocations, leading to data truncation on growing reallocations.
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.
- 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.
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>
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.
* feat(machine): add UART line inversion support.
Add InvertTX and InvertRX to UARTConfig to allow enabling hardware
line inversion on supported targets. Added hardware implementation for
RP2 (RP2040, RP2350), STM32 (newer families), SAM (SAMD51, SAME5x),
and ESP (ESP32, ESP32-C3, ESP32-C6).
* refactor(machine): Refactor UART inversion with pin setter helpers.
RP2: Extract setOutOver/setInOver methods on Pin, removing inline
IO control register manipulation from UART configure.
SAM: Switch to SetCTRLA_TXINV/SetCTRLA_RXINV methods, dropping
the unused device/sam import and raw SetBits/ClearBits calls.
---------
Co-authored-by: Konstantin Sharlaimov <ksharlaimov@inavflight.com>
STM32F4 and F7 share the same OTG FS IP but have no USB driver in
TinyGo. This adds a full device-mode driver covering CDC, HID, and
MSC with working examples.
- OTG FS has 4 physical EPs (0–3); virtual indices 4–7 fold onto
them via physEP() so the existing machine/usb API is unchanged
- F4 bypasses VBUS sensing via GCCFG.NOVBUSSENS; F7 uses the USB
voltage regulator + GOTGCTL B-valid override instead
- STM32F7 PLL_Q changed 2→9 to produce the 48 MHz clock required
by USB/RNG/SDMMC; CK48MSEL cleared to select main PLL as source
- HID and MSC descriptors remapped at init() to physical endpoint
addresses (EP2/EP1 for HID, EP2/EP3 for MSC)
- usb-storage example replaced machine.Flash with a FAT12 RAM disk
so the host mounts without reformatting
- MSC sendCSW sets queuedBytes before state transition to fix a
missed byte-count on the status phase
Treat panicState as a bitmask so a recovered panic during Goexit
can clear the panic bit while preserving the pending Goexit bit.
This removes the separate deferFrame Goexit field and restores the
previous defer frame size.
The threads scheduler handled runtime.Goexit using the generic deadlock
path, which parked the current pthread forever. Add a scheduler-specific
goexit hook so it can remove the current task and exit the pthread while
ordinary blocking deadlocks still block.
Track main goroutine Goexit so the last remaining goroutine reports the
expected deadlock instead of letting the process exit successfully.
Expand the crash coverage with the Goexit cases covered by Big Go's
runtime tests.
Keep a pending Goexit separate from the active panic state so recovered
deferred panics do not cancel the original Goexit unwind. Goexit should
also ignore -panic=trap, since it is not a panic.
Wire testing.FailNow and SkipNow through runtime.Goexit, and run tests
and benchmarks in goroutines. This lets Goexit terminate the user
function without skipping test bookkeeping. Add Goexit/recover coverage
and enable crypto/ecdh in the Linux stdlib test list.