Commit Graph

2137 Commits

Author SHA1 Message Date
deadprogram 934d5f41bf fix: init heap before random number seed on wasm platforms
This changes the order for initialization of the random number
seed generation on wasm platforms until after the heap has been
initialized. Should fix #5198

Signed-off-by: deadprogram <ron@hybridgroup.com>
2026-02-16 08:38:17 +01:00
Dima 4b0e858964 Esp32s3 implement spi (#5169)
* esp32s3 spi

* stabilization freq cpu

* cheange clacl freq for spi

* fix linters

* esp32s3-spi: change default pins for esp32s3 xiao

* set default configuration

* esp32s3-spi: extends smoketests for esp32s3
2026-02-15 14:50:39 +01:00
Matthew Hiles bef0dc5d21 Add per-byte timeout budget for rp2 I2C (#5189)
* Add per-byte timeout budget for rp2 I2C

* run goimports
2026-02-02 14:09:34 +01:00
Yaj e79cdc1122 targets: Add Shrike Lite board (#5170)
* feat: Add Vicharak Shrike Lite

* Add shrike-lite to smoketest
2026-01-24 08:04:22 +01:00
Jesús Espino 5d8e071bfb machine/attiny85: add USI-based SPI support (#5181)
* machine/attiny85: add USI-based SPI support

Implement SPI communication for ATTiny85 using the USI (Universal Serial
Interface) hardware in three-wire mode. The ATTiny85 lacks dedicated SPI
hardware but can emulate SPI using the USI module with software clock
strobing.

Implementation details:
- Configure USI in three-wire mode for SPI operation
- Use clock strobing technique to shift data in/out
- Pin mapping: PB2 (SCK), PB1 (MOSI/DO), PB0 (MISO/DI)
- Support both Transfer() and Tx() methods

The implementation uses the USI control register (USICR) to toggle the
clock pin, which triggers automatic bit shifting in hardware. This is
more efficient than pure software bit-banging.

Current limitations:
- Frequency configuration not yet implemented (runs at max software speed)
- Only SPI Mode 0 (CPOL=0, CPHA=0) supported
- Only MSB-first bit order supported

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

Co-authored-by: Ona <no-reply@ona.com>

* machine/attiny85: add SPI frequency configuration support

Add software-based frequency control for USI SPI. The ATtiny85 USI lacks
hardware prescalers, so frequency is controlled via delay loops between
clock toggles.

- Calculate delay cycles based on requested frequency and CPU clock
- Fast path (no delay) when frequency is 0 or max speed requested
- Delay loop uses nop instructions for timing control

Co-authored-by: Ona <no-reply@ona.com>

* machine/attiny85: add SPI mode configuration support

Add support for all 4 SPI modes (Mode 0-3) using USI hardware:
- Mode 0 (CPOL=0, CPHA=0): Clock idle low, sample on rising edge
- Mode 1 (CPOL=0, CPHA=1): Clock idle low, sample on falling edge
- Mode 2 (CPOL=1, CPHA=0): Clock idle high, sample on falling edge
- Mode 3 (CPOL=1, CPHA=1): Clock idle high, sample on rising edge

CPOL is controlled by setting the clock pin idle state.
CPHA is controlled via the USICS0 bit in USICR.

Co-authored-by: Ona <no-reply@ona.com>

* machine/attiny85: add LSB-first bit order support

Add software-based LSB-first support for USI SPI. The USI hardware only
supports MSB-first, so bit reversal is done in software before sending
and after receiving.

Uses an efficient parallel bit swap algorithm (3 operations) to reverse
the byte.

Co-authored-by: Ona <no-reply@ona.com>

* GNUmakefile: add mcp3008 SPI example to digispark smoketest

Test the USI-based SPI implementation for ATtiny85/digispark.

Co-authored-by: Ona <no-reply@ona.com>

* machine/attiny85: minimize SPI RAM footprint

Reduce SPI struct from ~14 bytes to 1 byte to fit in ATtiny85's limited
512 bytes of RAM.

Changes:
- Remove register pointers (use avr.USIDR/USISR/USICR directly)
- Remove pin fields (USI pins are fixed: PB0/PB1/PB2)
- Remove CS pin management (user must handle CS)
- Remove frequency control (runs at max speed)
- Remove LSBFirst support

The SPI struct now only stores the USICR configuration byte.

Co-authored-by: Ona <no-reply@ona.com>

* Revert "machine/attiny85: minimize SPI RAM footprint"

This reverts commit 387ccad494.

Co-authored-by: Ona <no-reply@ona.com>

* machine/attiny85: reduce SPI RAM usage by 10 bytes

Remove unnecessary fields from SPI struct while keeping all functionality:
- Remove register pointers (use avr.USIDR/USISR/USICR directly)
- Remove pin fields (USI pins are fixed: PB0/PB1/PB2)
- Remove CS pin (user must manage it, standard practice)

Kept functional fields:
- delayCycles for frequency control
- usicrValue for SPI mode support
- lsbFirst for bit order support

SPI struct reduced from 14 bytes to 4 bytes.

Co-authored-by: Ona <no-reply@ona.com>

---------

Co-authored-by: Ona <no-reply@ona.com>
2026-01-17 21:22:15 +01:00
deadprogram 1fe934e8a8 machine/rp: add Close function to UART to allow for removing all system resources/power usage
Signed-off-by: deadprogram <ron@hybridgroup.com>
2026-01-13 22:58:37 +00:00
deadprogram 8bd2233b57 machine/rp: use the blockReset() and unresetBlockWait() helper functions for all peripheral reset/unreset operations
Signed-off-by: deadprogram <ron@hybridgroup.com>
2026-01-13 08:55:10 +00:00
Jesús Espino ff58c50118 machine: add attiny85 pwm support (#5171)
* machine/attiny85: add PWM support for Timer0 and Timer1

Add complete PWM implementation for ATtiny85, supporting both Timer0
and Timer1 with their respective output channels:
- Timer0: 8-bit timer for pins PB0 (OC0A) and PB1 (OC0B)
- Timer1: 8-bit high-speed timer for pins PB1 (OC1A) and PB4 (OC1B)

Timer1 provides more flexible period control with configurable top value
(OCR1C) and extended prescaler options (1-16384), making it well-suited
for LED PWM control and other applications requiring variable frequencies.

Implements full PWM interface including Configure, SetPeriod, Channel,
Set, SetInverting, Top, Counter, and Period methods.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* machine/digispark: document PWM support on pins

Add documentation to the Digispark board file indicating which pins
support PWM output:
- P0 (PB0): Timer0 channel A
- P1 (PB1): Timer0 channel B or Timer1 channel A
- P4 (PB4): Timer1 channel B

Includes package comment explaining Timer0 vs Timer1 capabilities,
with Timer1 recommended for more flexible frequency control.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* machine/attiny85: optimize PWM prescaler lookups

Replace verbose switch statements with more efficient implementations:

- SetPeriod: Use bit shift (top >>= prescaler-1) instead of 15-case
  switch for dividing uint64 by power-of-2 prescaler values

- Period: Replace switch statements with compact uint16 lookup tables
  for both Timer0 and Timer1, casting to uint64 only when needed

This addresses review feedback about inefficient switch-based lookups.
On AVR, this approach is significantly smaller:
- Bit shifts for uint64 division: ~34 bytes vs ~140 bytes
- uint16 tables: 22 bytes code + 32/16 bytes data vs ~140 bytes
- Total savings: ~190 bytes (68% reduction)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* examples/pwm: add digispark support and smoketest

Add digispark.go configuration for PWM example using Timer1 with pins P1 (LED) and P4. Also add digispark PWM example to GNUmakefile smoketests.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-12 13:38:20 +01:00
Itxaka ca36fba7e4 feat: Implement Lchown function for changing file ownership (#5161)
* feat: Implement Lchown function for changing file ownership

- Added Lchown function to change the numeric uid and gid of a file or symbolic link.
- Included error handling to return *PathError for failed operations.
- Added unit tests for Lchown to verify behavior on different error scenarios.

* fix: fix chmod tests
2026-01-10 09:31:22 +01:00
deadprogram 743bf45e00 runtime: make timeoffset atomic
Make timeoffset atomic to be able to handle changing the system
time. Otherwise the scheduler can gets rather confused if you call
AdjustTimeOffset when there are multiple goroutines already running.

Signed-off-by: deadprogram <ron@hybridgroup.com>
2026-01-09 23:20:47 +00:00
Damian Gryski 9bc5d21185 src/runtime: add MemStats.HeapObjects 2026-01-09 13:46:28 +00:00
Damian Gryski c8b56bd161 src/testing: add b.ReportMetric() 2026-01-09 11:17:53 +00:00
soypat fe20079300 rp2: prevent pwm Period method overflow 2026-01-09 09:36:32 +00:00
Jake Bailey 068d7c1b44 reflect: add TypeAssert 2026-01-08 21:40:42 +00:00
Ayke van Laethem 42fed60e61 stm32l0: add flash support
Flash on the STM32L0 series of chips works a bit different and needs a
slightly different implementation compared to other STM32 chips.
2026-01-08 16:09:11 +00:00
Amken USA 53c1ccaa42 STM32G0B1 Watchdog + ADC Support (#5158)
* - Fix SPI initialization by disabling interface before configuration.
- Ensure proper 8-bit configuration for STM32G0 SPI data register access.
- Add default pin initialization for SPI.

* Add Window Watchdog (WWDG) and ADC support for STM32G0

* Comment cleanup

* Refactored STM32G0 ADC sampling time configuration to use `switch` for improved readability
2026-01-08 14:52:14 +01:00
Jake Bailey 4fff472808 sync: add WaitGroup.Go 2026-01-07 20:01:42 +00:00
Amken USA cfd74c2954 Add stm32g0b1 support (#5150)
* Add STM32G0B1 target support

Introduce support for STM32G0B1 microcontrollers, including target-specific JSON files, linker scripts, and runtime initialization. This update adds hardware support for GPIO, UART, SPI, I2C, timers, and additional board-specific configurations like Nucleo-G0B1RE.

* Update STM32G0 clock initialization to 64MHz and adjust related configurations

Reconfigure STM32G0 to use a 64MHz system clock via PLL with HSI16 as the source. Update flash latency, prescaler settings, and I2C timing values to reflect the new frequency.

* Cleanup

* Cleanup

* Add STM32G0-specific UART implementation

Introduce a new UART implementation for the STM32G0 series with chip-specific setup and configuration methods. Update the generic STM32 UART code to exclude STM32G0.

* Refactor STM32G0 runtime and machine code to utilize chip-specific register access functions

Simplify and standardize register operations with dedicated setter methods in the STM32G0 runtime and machine code and cleanup redundant syntax.

* Remove redundant commented-out APBENR1 register operations in STM32G0 machine code

* Introduce FDCAN support for STM32G0B1 series

Add FDCAN peripheral implementation targeting STM32G0B1, including support for standard, extended identifiers, and bit rate configuration. Update board files to include FDCAN pins, instances, and clock configuration for Nucleo-G0B1RE and Amken Trio boards.
2026-01-06 23:12:02 +01:00
Nia Waldvogel 9bcca974ba internal/gclayout: use correct lengths
The GC bitmap length is measured in multiples of the pointer alignment.
This is equal to the pointer size on all architectures except AVR.
Replace the hardcoded lengths with lengths that are computed naturally.
2026-01-05 21:12:31 +00:00
Nia Waldvogel a40586d092 compiler: implement copy directly
The compiler now implements the copy builtin directly instead of calling sliceCopy.
The length is calculated with the llvm.umax.* intrinsics, and the move is performed by llvm.memmove.*.
Both of these operations are easily understood by LLVM's optimization passes.
The type's alignment is also provided to llvm.memmove.*, which is useful when rewriting the move.

Interp no longer needs to reimplement sliceCopy.
Some edge case handling was implemented by sliceCopy but not llvm.memmove.*/llvm.memcpy.*.
I copied this over, so copies of external slices should work now.
Volatile moves/copies are now run at runtime by interp.

There is a 4-byte size increase due to some confusing length logic in sendUSBPacket.
I will look at sendUSBPacket in a future PR.
2026-01-05 15:10:31 -05:00
Nia Waldvogel 8ef36ed939 machine: fix usb truncation?
Remove the sendUSBPacket maxLen param because this greatly confused the compiler.
It also fixes a bug where the length provided to the hardware may not match the length of the packet.
sendUSBPacket now panics if the sent packet is too big.

I also fixed some of the string descriptor logic where we could create a packet without fully populating it.

RP2* systems might require some more work since they are implemented very differently?
I don't have any of those to test with yet, so maybe someone can deal with them in a seperate PR?
2026-01-03 10:59:50 +00:00
Nia Waldvogel 266d70816f compiler/runtime: add element layout to sliceAppend
Attach the memory layout of the element type to newly created slices via append when using the precise collector.
2025-12-26 21:27:24 -05:00
MakKi (makki_d) f7fd5cf2d8 runtime: use rand_hwrng hardwareRand for RP2040/RP2350 (#5135)
* runtime: use rand_hwrng hardwareRand for RP2040/RP2350

* add a comment

* insert 'implementations'
2025-12-18 20:52:12 +01:00
deadprogram 82deccac40 runtime: call initRand() before initHeap() during initialization.
The reason is that allocating without a heap is usually more visible
than using an uninitialized random generator which is subtle and may
lead to security vulnerabilities.

Based on suggestion from @eliasnaur

Signed-off-by: deadprogram <ron@hybridgroup.com>
2025-12-18 16:42:46 +00:00
deadprogram 0e540dc3da runtime: add calls to initRand() during run() for all schedulers.
Intended to ensure that the random number seed used is always initialized on startup.

Signed-off-by: deadprogram <ron@hybridgroup.com>
2025-12-18 16:42:46 +00:00
MakKi (makki_d) 897f2bc5fd runtime: avoid fixed math/rand sequence on RP2040/RP2350 (#5124)
* runtime: avoid fixed math/rand sequence on RP2040/RP2350

* fix typo
2025-12-17 20:05:43 +01:00
Ayke van Laethem 750b0e5c18 nrf: fix flash writes when SoftDevice is enabled
The data to write is specififed in words, not in bytes.

This fix is needed for correctness. Without it, a
`machine.Flash.WriteAt` call can result in **data loss** since it will
overwrite more data than it should.
2025-12-17 14:58:40 +00:00
Damian Gryski e356daa229 internal/task: prevent semaphore resource leak for threads scheduler 2025-12-13 00:40:54 -08:00
Nia Waldvogel d01d0bb358 runtime (gc_blocks.go): make sweep branchless
Instead of looping over each block, we can use bit hacks to operate on an entire state byte.
I deinterleaved the state bits in order to enable these tricks.

Sweep used to count free/freed allocations/blocks.
I managed to move/remove all of these counters:
- The free space is now calculated in buildFreeRanges by adding the range lengths.
- ReadMemStats counts freed objects by subtracting live objects from allocated objects.
- gcFreedBlocks was never necessary because MemStats.HeapAlloc is the same as MemStats.HeapInUse.
2025-12-10 18:39:50 -05:00
Nia Waldvogel 8fcf3658b1 runtime (gc_blocks.go): use best-fit allocation
The allocator originally just looped through the blocks until it found a sufficiently-long range.
This is simple, but it fragments very easily and can degrade to a full heap scan for long requests.

Instead, we now maintain a sorted nested list of free ranges by size.
The allocator will select the shortest sufficient-length range, generally reducing fragmentation.
This data structure can find a range in time directly proportional to the requested length.
2025-12-10 06:58:07 +00:00
Nia Waldvogel ee0a10ec51 runtime (wasm): scan the system stack
This saves the system stack pointer into a global and uses it to scan.
It should fix some use-after-free issues?
2025-12-08 17:27:20 +00:00
Michael Smith 39e0333663 fix: don't hardcode success return state
fix: validate bmRequestType\nfix: mimic tinyusb behavior in mscStateNeedReset\nfix: CLEAR_FEATURE requests to iface addr are against spec
2025-12-06 06:34:32 +00:00
Michael Smith 3afd2c3597 fix: update m.queuedBytes when clamping output to avoid corrupting sentBytes 2025-12-06 06:34:32 +00:00
Michael Smith bd19f3baa3 fix: separate host expected bytes from device intended bytes 2025-12-06 06:34:32 +00:00
Ayke van Laethem 908fa84d49 runtime: remove copied code for nrf52840
We really shouldn't have copies around like that, instead the code
should be factored out.
In this case, it's a single import that's needed.
2025-12-05 20:50:06 +00:00
Ayke van Laethem 571f34e0e6 machine: only enable USB-CDC when needed
Enabling USB consumes a lot of power. So it's better to keep it disabled
by default when the serial port is set to something other than "usb"
(USB-CDC).

On my nice!nano clone, it reduces current consumption from 1mA to
0.13mA (and most of the rest is probably consumed by a connected SCD41
sensor).

This change might break some expectations, when a board uses USB but not
USB-CDC (I think this is rare, but I didn't check specifically).
2025-12-05 20:50:06 +00:00
Nia Waldvogel 01723025d7 runtime (avr): fix infinite longjmp loop if stack is aligned to 256 bytes
The setjmp code sets r24 to 0 and checks if it is still 0 when it finishes.
This usually works because tinygo_longjmp stores the lower half of the stack pointer into r24.
However, r24 will be set to 0 if the stack is aligned to 256 bytes when entering the setjmp.

Manually set r24 to 1 in tinygo_longjmp to fix this issue.
2025-12-05 13:22:37 -05:00
Nia Waldvogel 26ac03a3f6 runtime (gc_blocks.go): simplify scanning logic
Loop over valid pointer locations in heap objects instead of checking if each location is valid.
The conservative scanning code is now shared between markRoots and the heap scan.

This also removes the ending alignment requirement from markRoots, since the new scan* functions do not require an aligned length.
This requirement was occasionally violated by the linux global marking code.

This saves some code space and has negligible impact on performance.
2025-12-05 10:16:38 +00:00
Nia Waldvogel c9aa88b8ef runtime (gc_blocks.go): use a linked stack to scan marked objects
The blocks GC originally used a fixed-size stack to hold objects to scan.
When this stack overflowed, the GC would fully rescan all marked objects.
This could cause the GC to degrade to O(n^2) when scanning large linked data structures.

Instead of using a fixed-size stack, we now add a pointer field to the start of each object.
This pointer field is used to implement an unbounded linked stack.
This also consolidates the heap object scanning into one place, which simplifies the process.

This comes at the cost of introducing a pointer field to the start of the object, plus the cost of aligning the result.
This translates to:
- 16 bytes of overhead on x86/arm64 with the conservative collector
- 0 bytes of overhead on x86/arm64 with the precise collector (the layout field cost gets aligned up to 16 bytes anyway)
- 8 bytes of overhead on other 64-bit systems
- 4 bytes of overhead on 32-bit systems
- 2 bytes of overhead on AVR
2025-12-05 10:16:38 +00:00
Ayke van Laethem 887ac286ff nrf: add ADC_VDDH which is an ADC pin for VDDH
VDDH is typically connected to USB (~5V) or directly to a battery.
Measuring the voltage on VDDH is a way to measure the current battery
voltage, which in turn can be useful to determine how much power is left
in the battery.

I've special cased the nrf52840 in a somewhat unusual way, maybe there
is a better way, feel free to comment!
2025-12-04 18:48:22 +00:00
Ayke van Laethem b1083d78c7 nrf: rename pwmPin to adcPin
Just a small refactor, to fix the naming.
2025-12-04 18:48:22 +00:00
Ayke van Laethem 7863bdb484 nrf: don't set PSELN, it's ignored in single ended mode anyway
We use single ended mode, so according to the datasheet PSELN is
ignored.
2025-12-04 18:48:22 +00:00
Ayke van Laethem 5c3363bf25 nrf: fix typo in ADC configuration
This shouldn't change behavior (both values are 0), but it's a bit more
correct.
2025-12-04 18:48:22 +00:00
Nia Waldvogel 9404bb8712 internal/task (threads): save stack bounds instead of scanning under a lock
In order to scan stacks, the GC preempts all other threads and has them scan their own stack.
This is somewhat expensive since all of these threads have to fight over a single lock.
Instead, save the stack bounds and let the GC thread perform the scan.

This also fixes a few other bugs I ran into:
1. The GC starts scanning before the world stops. This can cause it to miss some objects (and mistakenly free them) if memory is modified while stopping.
2. The GC does not wait for threads to resume. This can cause notifications to be misinterpreted due to signal nesting if the GC is re-run before all threads wake.
2025-12-04 11:22:46 +00:00
Nia Waldvogel 20e22d4507 runtime (gc_blocks.go): clear full size of allocation
This fixes a bug where runtime.alloc would not clear the padding from rounding the allocation up to a multiple of the block size.
The GC still has to scan this, and this could result in permanent false positives (and therefore memory leaks).

It also handles overflow in the size calculation.
2025-11-30 08:46:20 +00:00
deadprogram 9118e91b72 target: add xiao-esp32s3 board target
Signed-off-by: deadprogram <ron@hybridgroup.com>
2025-11-24 14:30:50 +00:00
cjpeterson fbbaa5e580 Add ESP32-S3 support (#5091)
* feat: add initial support for ESP32-S3 (#3442)

* feat: add initial support for esp32-s3

* esp32s3: fix merge errors

* esp32s3: Fix Watchdog registers bad names

* esp32s3: fix linker relocation errors and support for ESP binary

* esp32s3: fix memory section overlap

* esp32s3: correct clock frequencies

* esp32s3: more stable cpu

* esp32s3: enable basic gpio support

* esp32s3: simplify loading and check extensions

* esp32s3: synchronize cpu features with clang

* esp32s3: correct iram origin

---------

Co-authored-by: Denys Vitali <denys@denv.it>
Co-authored-by: Olivier Fauchon <ofauchon2204@gmail.com>
2025-11-24 12:11:47 +01:00
Ayke van Laethem 6dee98c3a1 nrf: support flash operations while the SoftDevice is enabled
Flash operations must go through the SoftDevice if it is enabled,
otherwise they will crash the chip. (And even then the SoftDevice
doesn't guarantee they'll succeed, depending on advertisement frequency
etc). But this patch makes sure to call the appropriate APIs so that
flash is usable while using Bluetooth.
2025-11-16 19:25:14 +01:00
Ayke van Laethem 484ccf830a nrf: refactor SoftDevice enabled check
Share the code with the runtime.
2025-11-16 19:25:14 +01:00
Ayke van Laethem 5690204224 nrf: don't block SPI transfer
Ideally we'd use something like
https://github.com/tinygo-org/tinygo/pull/5016 but that's a bit more
involved. As a quick improvement, call gosched() instead.

Example where I use this: a custom WS2812 driver that uses SPI to
transfer the data. It's useful to be able to switch back to the main
goroutine during the transfer to render the next LED update.
2025-11-16 11:24:32 +01:00