Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion builder/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
defer unlock()
libcDependencies = append(libcDependencies, libcJob)
libcDependencies = append(libcDependencies, makeMinGWExtraLibs(tmpdir, config.GOARCH())...)
case "":
case "", "none":
// no library specified, so nothing to do
default:
return BuildResult{}, fmt.Errorf("unknown libc: %s", config.Target.Libc)
Expand Down
2 changes: 1 addition & 1 deletion compileopts/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ func (c *Config) LibcCFlags() []string {
)
}
return cflags
case "":
case "", "none":
// No libc specified, nothing to add.
return nil
default:
Expand Down
2 changes: 2 additions & 0 deletions goenv/goenv.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ func Get(name string) string {
panic("could not find cache dir: " + err.Error())
}
return filepath.Join(dir, "tinygo")
case "CGO_CFLAGS":
return os.Getenv("CGO_CFLAGS")
case "CGO_ENABLED":
// Always enable CGo. It is required by a number of targets, including
// macOS and the rp2040.
Expand Down
1 change: 1 addition & 0 deletions loader/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,7 @@ func (p *Package) parseFiles() ([]*ast.File, error) {
var initialCFlags []string
initialCFlags = append(initialCFlags, p.program.config.CFlags(true)...)
initialCFlags = append(initialCFlags, "-I"+p.Dir)
initialCFlags = append(initialCFlags, goenv.Get("CGO_CFLAGS"))
generated, headerCode, cflags, ldflags, accessedFiles, errs := cgo.Process(files, p.program.workingDir, p.ImportPath, p.program.fset, initialCFlags, p.program.config.GOOS())
p.CFlags = append(initialCFlags, cflags...)
p.CGoHeaders = headerCode
Expand Down
22 changes: 22 additions & 0 deletions src/crypto/rand/rand_espidf.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//go:build espidf

package rand

import "unsafe"

func init() {
Reader = &reader{}
}

type reader struct{}

//export esp_fill_random
func esp_fill_random(buf unsafe.Pointer, len uintptr)

func (r *reader) Read(b []byte) (n int, err error) {
if len(b) == 0 {
return
}
esp_fill_random(unsafe.Pointer(&b[0]), uintptr(len(b)))
return len(b), nil
}
52 changes: 52 additions & 0 deletions src/device/esp/esp32s3-stack.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// -----------------------------------------------------------------------
// tinygo_scanCurrentStack — Spill all Xtensa register windows to the
// stack, then call tinygo_scanstack(sp) so the conservative GC can
// discover live heap pointers that are currently in physical registers.
//
// On RISC-V / ARM the equivalent function pushes callee-saved registers
// before the call. On Xtensa windowed ABI the same effect is achieved
// by forcing hardware window-overflow for every occupied pane: each
// overflow saves the four registers in that pane to the stack frame
// pointed to by the pane's a1 (sp). After all panes are flushed, a
// scan from the current sp to stackTop covers every live value.
// -----------------------------------------------------------------------
.section .text.tinygo_scanstack

.global tinygo_scanCurrentStack
tinygo_scanCurrentStack:
entry a1, 48

// Disable interrupts while flushing register windows.
rsr a4, PS
s32i a4, a1, 0 // save PS for later restore
rsil a4, 3 // XCHAL_EXCM_LEVEL

// Flush all register windows using recursive call4.
// For NAREG=64 (16 panes), 15 recursive levels cover all panes
// except the current one (which is kept active).
movi a6, 15
call4 .Lscan_spill

// Restore interrupts.
l32i a4, a1, 0
wsr.ps a4
rsync

// Pass current sp to tinygo_scanstack.
// call4 maps caller's a5→callee's a1 (stack ptr for callee's entry)
// and caller's a6→callee's a2 (first argument = sp).
mov a5, a1 // callee's a1 = valid stack pointer
mov a6, a1 // callee's a2 = sp argument
call4 tinygo_scanstack

retw

.balign 4
.Lscan_spill:
entry a1, 16
beqz a2, .Lscan_spill_done
addi a2, a2, -1
mov a6, a2
call4 .Lscan_spill
.Lscan_spill_done:
retw
53 changes: 0 additions & 53 deletions src/device/esp/esp32s3.S
Original file line number Diff line number Diff line change
Expand Up @@ -342,56 +342,3 @@ call_start_cpu0:

// If main returns, loop forever.
1: j 1b

// -----------------------------------------------------------------------
// tinygo_scanCurrentStack — Spill all Xtensa register windows to the
// stack, then call tinygo_scanstack(sp) so the conservative GC can
// discover live heap pointers that are currently in physical registers.
//
// On RISC-V / ARM the equivalent function pushes callee-saved registers
// before the call. On Xtensa windowed ABI the same effect is achieved
// by forcing hardware window-overflow for every occupied pane: each
// overflow saves the four registers in that pane to the stack frame
// pointed to by the pane's a1 (sp). After all panes are flushed, a
// scan from the current sp to stackTop covers every live value.
// -----------------------------------------------------------------------
.section .text.tinygo_scanCurrentStack

.global tinygo_scanCurrentStack
tinygo_scanCurrentStack:
entry a1, 48

// Disable interrupts while flushing register windows.
rsr a4, PS
s32i a4, a1, 0 // save PS for later restore
rsil a4, 3 // XCHAL_EXCM_LEVEL

// Flush all register windows using recursive call4.
// For NAREG=64 (16 panes), 15 recursive levels cover all panes
// except the current one (which is kept active).
movi a6, 15
call4 .Lscan_spill

// Restore interrupts.
l32i a4, a1, 0
wsr.ps a4
rsync

// Pass current sp to tinygo_scanstack.
// call4 maps caller's a5→callee's a1 (stack ptr for callee's entry)
// and caller's a6→callee's a2 (first argument = sp).
mov a5, a1 // callee's a1 = valid stack pointer
mov a6, a1 // callee's a2 = sp argument
call4 tinygo_scanstack

retw

.balign 4
.Lscan_spill:
entry a1, 16
beqz a2, .Lscan_spill_done
addi a2, a2, -1
mov a6, a2
call4 .Lscan_spill
.Lscan_spill_done:
retw
2 changes: 1 addition & 1 deletion src/runtime/atomics_critical.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:build baremetal && !tinygo.wasm
//go:build baremetal && !tinygo.wasm && !espidf

// Automatically generated file. DO NOT EDIT.
// This file implements standins for non-native atomics using critical sections.
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/baremetal.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:build baremetal
//go:build baremetal && !espidf

package runtime

Expand Down
2 changes: 1 addition & 1 deletion src/runtime/interrupt/interrupt_none.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:build !baremetal || tkey
//go:build !baremetal || tkey || espidf

package interrupt

Expand Down
2 changes: 1 addition & 1 deletion src/runtime/interrupt/interrupt_tinygoriscv.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:build tinygo.riscv && !tkey
//go:build tinygo.riscv && !tkey && !espidf

package interrupt

Expand Down
2 changes: 1 addition & 1 deletion src/runtime/interrupt/interrupt_xtensa.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:build xtensa && !esp32s3
//go:build xtensa && !esp32s3 && !espidf

package interrupt

Expand Down
2 changes: 1 addition & 1 deletion src/runtime/rand_norng.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:build baremetal && !(nrf || (stm32 && !(stm32f103 || stm32l0x1 || stm32g0)) || (sam && atsamd51) || (sam && atsame5x) || esp32c3 || esp32s3 || tkey || (tinygo.riscv32 && virt) || rp2040 || rp2350)
//go:build baremetal && !(nrf || (stm32 && !(stm32f103 || stm32l0x1 || stm32g0)) || (sam && atsamd51) || (sam && atsame5x) || esp32c3 || esp32s3 || espidf || tkey || (tinygo.riscv32 && virt) || rp2040 || rp2350)

package runtime

Expand Down
128 changes: 128 additions & 0 deletions src/runtime/runtime_espidf.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
//go:build espidf

package runtime

import "unsafe"

var (
heapStart uintptr
heapEnd uintptr
globalsStart uintptr
globalsEnd uintptr
stackTop uintptr
)

// Allows C consumers of the library to set the GC variables.
//
//export tinygo_init
func tinygo_init(heap, heapSize, glob, globEnd, stack uintptr) {
heapStart, heapEnd = heap, heap+heapSize
globalsStart, globalsEnd = glob, globEnd
stackTop = stack
initRand()
initHeap()
initAll()
}

func growHeap() bool {
return false
}

//export abort
func abort()

//export exit
func exit(code int)

//export putchar
func libc_putchar(c byte)

func putchar(c byte) {
libc_putchar(c)
}

//export getchar
func libc_getchar() byte

func getchar() byte {
return libc_getchar()
}

func buffered() int {
return 0
}

const (
clock_REALTIME = 1
clock_MONOTONIC = 4
)

type timespec struct {
tv_sec int64
tv_nsec int32
}

//export clock_gettime
func clock_gettime(clock int32, ts *timespec)

func getTime(clock int32) uint64 {
var ts timespec
clock_gettime(clock, &ts)
return uint64(ts.tv_sec)*1e9 + uint64(ts.tv_nsec)
}

func monotime() uint64 {
return getTime(clock_MONOTONIC)
}

func ticks() timeUnit {
return timeUnit(monotime())
}

func ticksToNanoseconds(ticks timeUnit) int64 {
return int64(ticks)
}

func nanosecondsToTicks(ns int64) timeUnit {
return timeUnit(ns)
}

//export usleep
func usleep(usec uint) int

func sleepTicks(d timeUnit) {
usleep(uint(d / 1e3))
}

const baremetal = true

//go:linkname now time.now
func now() (sec int64, nsec int32, mono int64) {
var ts timespec
clock_gettime(clock_REALTIME, &ts)
sec = ts.tv_sec
nsec = ts.tv_nsec
mono = nanotime()
return
}

// Picolibc is not configured to define its own errno value, instead it calls
// __errno_location.
// TODO: a global works well enough for now (same as errno on Linux with
// -scheduler=tasks), but this should ideally be a thread-local variable stored
// in task.Task.
// Especially when we add multicore support for microcontrollers.
var errno int32

//export __errno_location
func libc_errno_location() *int32 {
return &errno
}

//export esp_fill_random
func esp_fill_random(buf unsafe.Pointer, len uintptr)

func hardwareRand() (n uint64, ok bool) {
esp_fill_random(unsafe.Pointer(&n), 8)
return n, true
}
15 changes: 15 additions & 0 deletions targets/esp32c3-idf.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"inherits": ["riscv32"],
"features": "+32bit,+c,+m,+zmmul,-a,-b,-d,-e,-experimental-sdext,-experimental-sdtrig,-experimental-smctr,-experimental-ssctr,-experimental-svukte,-experimental-xqcia,-experimental-xqciac,-experimental-xqcicli,-experimental-xqcicm,-experimental-xqcics,-experimental-xqcicsr,-experimental-xqciint,-experimental-xqcilo,-experimental-xqcilsm,-experimental-xqcisls,-experimental-zalasr,-experimental-zicfilp,-experimental-zicfiss,-experimental-zvbc32e,-experimental-zvkgs,-f,-h,-relax,-sha,-shcounterenw,-shgatpa,-shtvala,-shvsatpa,-shvstvala,-shvstvecd,-smaia,-smcdeleg,-smcsrind,-smdbltrp,-smepmp,-smmpm,-smnpm,-smrnmi,-smstateen,-ssaia,-ssccfg,-ssccptr,-sscofpmf,-sscounterenw,-sscsrind,-ssdbltrp,-ssnpm,-sspm,-ssqosid,-ssstateen,-ssstrict,-sstc,-sstvala,-sstvecd,-ssu64xl,-supm,-svade,-svadu,-svbare,-svinval,-svnapot,-svpbmt,-svvptc,-v,-xcvalu,-xcvbi,-xcvbitmanip,-xcvelw,-xcvmac,-xcvmem,-xcvsimd,-xesppie,-xmipscmove,-xmipslsp,-xsfcease,-xsfvcp,-xsfvfnrclipxfqf,-xsfvfwmaccqqq,-xsfvqmaccdod,-xsfvqmaccqoq,-xsifivecdiscarddlone,-xsifivecflushdlone,-xtheadba,-xtheadbb,-xtheadbs,-xtheadcmo,-xtheadcondmov,-xtheadfmemidx,-xtheadmac,-xtheadmemidx,-xtheadmempair,-xtheadsync,-xtheadvdot,-xventanacondops,-xwchc,-za128rs,-za64rs,-zaamo,-zabha,-zacas,-zalrsc,-zama16b,-zawrs,-zba,-zbb,-zbc,-zbkb,-zbkc,-zbkx,-zbs,-zca,-zcb,-zcd,-zce,-zcf,-zcmop,-zcmp,-zcmt,-zdinx,-zfa,-zfbfmin,-zfh,-zfhmin,-zfinx,-zhinx,-zhinxmin,-zic64b,-zicbom,-zicbop,-zicboz,-ziccamoa,-ziccif,-zicclsm,-ziccrse,-zicntr,-zicond,-zicsr,-zifencei,-zihintntl,-zihintpause,-zihpm,-zimop,-zk,-zkn,-zknd,-zkne,-zknh,-zkr,-zks,-zksed,-zksh,-zkt,-ztso,-zvbb,-zvbc,-zve32f,-zve32x,-zve64d,-zve64f,-zve64x,-zvfbfmin,-zvfbfwma,-zvfh,-zvfhmin,-zvkb,-zvkg,-zvkn,-zvknc,-zvkned,-zvkng,-zvknha,-zvknhb,-zvks,-zvksc,-zvksed,-zvksg,-zvksh,-zvkt,-zvl1024b,-zvl128b,-zvl16384b,-zvl2048b,-zvl256b,-zvl32768b,-zvl32b,-zvl4096b,-zvl512b,-zvl64b,-zvl65536b,-zvl8192b",
"build-tags": ["espidf", "esp"],
"scheduler": "none",
"rtlib": "none",
"libc": "none",
"cflags": [
"-march=rv32imc"
],
"ldflags": [
"-r",
"--no-gc-sections"
]
}
14 changes: 14 additions & 0 deletions targets/esp32s3-idf.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"inherits": ["xtensa"],
"cpu": "esp32s3",
"features": "+atomctl,+bool,+clamps,+coprocessor,+debug,+density,+div32,+esp32s3,+exception,+fp,+highpriinterrupts,+interrupt,+loop,+mac16,+memctl,+minmax,+miscsr,+mul32,+mul32high,+nsa,+prid,+regprotect,+rvector,+s32c1i,+sext,+threadptr,+timerint,+windowed",
"build-tags": ["espidf", "esp"],
"linker": "ld.lld",
"ldflags": [
"-r",
"--no-gc-sections"
],
"extra-files": [
"src/device/esp/esp32s3-stack.S"
]
}
1 change: 1 addition & 0 deletions targets/esp32s3.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"linkerscript": "targets/esp32s3.ld",
"extra-files": [
"src/device/esp/esp32s3.S",
"src/device/esp/esp32s3-stack.S",
"targets/esp32s3-interrupts.S",
"src/internal/task/task_stack_esp32.S"
],
Expand Down
2 changes: 1 addition & 1 deletion tools/gen-critical-atomics/gen-critical-atomics.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ var tmpl = template.Must(template.New("go").Funcs(template.FuncMap{
return v
},
"title": strings.Title,
}).Parse(`//go:build baremetal && !tinygo.wasm
}).Parse(`//go:build baremetal && !tinygo.wasm && !espidf

// Automatically generated file. DO NOT EDIT.
// This file implements standins for non-native atomics using critical sections.
Expand Down