avr: drop GNU toolchain dependency

- Use compiler-rt and picolibc instead of avr-libc.
  - Use ld.lld instead of avr-ld (or avr-gcc).

This makes it much easier to get started with TinyGo on AVR because
installing these extra tools (gcc-avr, avr-libc) can be a hassle.
It also opens the door for future improvements such as ThinLTO.

There is a code size increase but I think it's worth it in the long run.
The code size increase can hopefully be reduced with improvements to the
LLVM AVR backend and to compiler-rt.
Этот коммит содержится в:
Ayke van Laethem 2022-11-04 14:50:26 +01:00 коммит произвёл Ron Evans
родитель b9bb605257
коммит df888acd5e
22 изменённых файлов: 74 добавлений и 41 удалений

Просмотреть файл

@ -63,8 +63,6 @@ commands:
clang-<<parameters.llvm>> \ clang-<<parameters.llvm>> \
libclang-<<parameters.llvm>>-dev \ libclang-<<parameters.llvm>>-dev \
lld-<<parameters.llvm>> \ lld-<<parameters.llvm>> \
gcc-avr \
avr-libc \
cmake \ cmake \
ninja-build ninja-build
- hack-ninja-jobs - hack-ninja-jobs

2
.github/workflows/build-macos.yml предоставленный
Просмотреть файл

@ -93,7 +93,7 @@ jobs:
path: build/tinygo.darwin-amd64.tar.gz path: build/tinygo.darwin-amd64.tar.gz
- name: Smoke tests - name: Smoke tests
shell: bash shell: bash
run: make smoketest TINYGO=$(PWD)/build/tinygo AVR=0 run: make smoketest TINYGO=$(PWD)/build/tinygo
test-macos-homebrew: test-macos-homebrew:
name: homebrew-install name: homebrew-install
runs-on: macos-latest runs-on: macos-latest

7
.github/workflows/linux.yml предоставленный
Просмотреть файл

@ -133,11 +133,6 @@ jobs:
mkdir -p ~/lib mkdir -p ~/lib
tar -C ~/lib -xf tinygo.linux-amd64.tar.gz tar -C ~/lib -xf tinygo.linux-amd64.tar.gz
ln -s ~/lib/tinygo/bin/tinygo ~/go/bin/tinygo ln -s ~/lib/tinygo/bin/tinygo ~/go/bin/tinygo
- name: Install apt dependencies
run: |
sudo apt-get install --no-install-recommends \
gcc-avr \
avr-libc
- run: make tinygo-test-wasi-fast - run: make tinygo-test-wasi-fast
- run: make smoketest - run: make smoketest
assert-test-linux: assert-test-linux:
@ -158,8 +153,6 @@ jobs:
qemu-system-arm \ qemu-system-arm \
qemu-system-riscv32 \ qemu-system-riscv32 \
qemu-user \ qemu-user \
gcc-avr \
avr-libc \
simavr \ simavr \
ninja-build ninja-build
- name: Install Go - name: Install Go

2
.github/workflows/windows.yml предоставленный
Просмотреть файл

@ -125,7 +125,7 @@ jobs:
run: 7z x release.zip -r run: 7z x release.zip -r
- name: Smoke tests - name: Smoke tests
shell: bash shell: bash
run: make smoketest TINYGO=$(PWD)/build/tinygo/bin/tinygo AVR=0 run: make smoketest TINYGO=$(PWD)/build/tinygo/bin/tinygo
stdlib-test-windows: stdlib-test-windows:
runs-on: windows-2022 runs-on: windows-2022

Просмотреть файл

@ -2,7 +2,7 @@
FROM golang:1.19 AS tinygo-llvm FROM golang:1.19 AS tinygo-llvm
RUN apt-get update && \ RUN apt-get update && \
apt-get install -y apt-utils make cmake clang-11 binutils-avr gcc-avr avr-libc ninja-build apt-get install -y apt-utils make cmake clang-11 ninja-build
COPY ./Makefile /tinygo/Makefile COPY ./Makefile /tinygo/Makefile

Просмотреть файл

@ -674,7 +674,6 @@ ifneq ($(STM32), 0)
$(TINYGO) build -size short -o test.hex -target=swan examples/blinky1 $(TINYGO) build -size short -o test.hex -target=swan examples/blinky1
@$(MD5SUM) test.hex @$(MD5SUM) test.hex
endif endif
ifneq ($(AVR), 0)
$(TINYGO) build -size short -o test.hex -target=atmega1284p examples/serial $(TINYGO) build -size short -o test.hex -target=atmega1284p examples/serial
@$(MD5SUM) test.hex @$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=arduino examples/blinky1 $(TINYGO) build -size short -o test.hex -target=arduino examples/blinky1
@ -693,7 +692,6 @@ ifneq ($(AVR), 0)
@$(MD5SUM) test.hex @$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=digispark -gc=leaking examples/blinky1 $(TINYGO) build -size short -o test.hex -target=digispark -gc=leaking examples/blinky1
@$(MD5SUM) test.hex @$(MD5SUM) test.hex
endif
ifneq ($(XTENSA), 0) ifneq ($(XTENSA), 0)
$(TINYGO) build -size short -o test.bin -target=esp32-mini32 examples/blinky1 $(TINYGO) build -size short -o test.bin -target=esp32-mini32 examples/blinky1
@$(MD5SUM) test.bin @$(MD5SUM) test.bin

Просмотреть файл

@ -162,6 +162,15 @@ var aeabiBuiltins = []string{
"udivmodsi4.c", "udivmodsi4.c",
} }
var avrBuiltins = []string{
"avr/divmodhi4.S",
"avr/divmodqi4.S",
"avr/mulhi3.S",
"avr/mulqi3.S",
"avr/udivmodhi4.S",
"avr/udivmodqi4.S",
}
// CompilerRT is a library with symbols required by programs compiled with LLVM. // CompilerRT is a library with symbols required by programs compiled with LLVM.
// These symbols are for operations that cannot be emitted with a single // These symbols are for operations that cannot be emitted with a single
// instruction or a short sequence of instructions for that target. // instruction or a short sequence of instructions for that target.
@ -186,6 +195,9 @@ var CompilerRT = Library{
if strings.HasPrefix(target, "arm") || strings.HasPrefix(target, "thumb") { if strings.HasPrefix(target, "arm") || strings.HasPrefix(target, "thumb") {
builtins = append(builtins, aeabiBuiltins...) builtins = append(builtins, aeabiBuiltins...)
} }
if strings.HasPrefix(target, "avr") {
builtins = append(builtins, avrBuiltins...)
}
return builtins, nil return builtins, nil
}, },
} }

Просмотреть файл

@ -78,7 +78,7 @@ var picolibcSources = []string{
"libc/tinystdio/fputc.c", "libc/tinystdio/fputc.c",
"libc/tinystdio/fputs.c", "libc/tinystdio/fputs.c",
"libc/tinystdio/fread.c", "libc/tinystdio/fread.c",
"libc/tinystdio/freopen.c", //"libc/tinystdio/freopen.c", // crashes with AVR, see: https://github.com/picolibc/picolibc/pull/369
"libc/tinystdio/fscanf.c", "libc/tinystdio/fscanf.c",
"libc/tinystdio/fseek.c", "libc/tinystdio/fseek.c",
"libc/tinystdio/fseeko.c", "libc/tinystdio/fseeko.c",

Просмотреть файл

@ -37,3 +37,39 @@ func procPin() {
func procUnpin() { func procUnpin() {
interrupt.Restore(procPinnedMask) interrupt.Restore(procPinnedMask)
} }
// The following functions are workarounds for things missing in compiler-rt.
// They will likely need special assembly implementations.
//export __mulsi3
func __mulsi3(a, b uint32) uint32 {
var r uint32
for a != 0 {
if a&1 != 0 {
r += b
}
a >>= 1
b <<= 1
}
return r
}
//export __divsi3
func __divsi3(a, b int32) int32
//export __udivsi3
func __udivsi3(a, b uint32) uint32
//export __divmodsi4
func __divmodsi4(a, b int32) uint64 {
d := __divsi3(a, b)
rem := a - (d * b)
return uint64(uint32(d)) | uint64(uint32(rem))<<32
}
//export __udivmodsi4
func __udivmodsi4(a, b uint32) uint64 {
d := __udivsi3(a, b)
rem := a - (d * b)
return uint64(d) | uint64(rem)<<32
}

Просмотреть файл

@ -2,7 +2,7 @@
"inherits": ["atmega1280"], "inherits": ["atmega1280"],
"build-tags": ["arduino_mega1280"], "build-tags": ["arduino_mega1280"],
"ldflags": [ "ldflags": [
"-Wl,--defsym=_bootloader_size=4096" "--defsym=_bootloader_size=4096"
], ],
"flash-command":"avrdude -c arduino -b 57600 -p atmega1280 -P {port} -U flash:w:{hex}:i -v -D" "flash-command":"avrdude -c arduino -b 57600 -p atmega1280 -P {port} -U flash:w:{hex}:i -v -D"
} }

Просмотреть файл

@ -2,7 +2,7 @@
"inherits": ["atmega2560"], "inherits": ["atmega2560"],
"build-tags": ["arduino_mega2560"], "build-tags": ["arduino_mega2560"],
"ldflags": [ "ldflags": [
"-Wl,--defsym=_bootloader_size=8192" "--defsym=_bootloader_size=8192"
], ],
"flash-command":"avrdude -c wiring -b 115200 -p atmega2560 -P {port} -U flash:w:{hex}:i -v -D" "flash-command":"avrdude -c wiring -b 115200 -p atmega2560 -P {port} -U flash:w:{hex}:i -v -D"
} }

Просмотреть файл

@ -2,8 +2,8 @@
"inherits": ["atmega328p"], "inherits": ["atmega328p"],
"build-tags": ["arduino_nano"], "build-tags": ["arduino_nano"],
"ldflags": [ "ldflags": [
"-Wl,--defsym=_bootloader_size=512", "--defsym=_bootloader_size=512",
"-Wl,--defsym=_stack_size=512" "--defsym=_stack_size=512"
], ],
"flash-command": "avrdude -c arduino -p atmega328p -b 57600 -P {port} -U flash:w:{hex}:i", "flash-command": "avrdude -c arduino -p atmega328p -b 57600 -P {port} -U flash:w:{hex}:i",
"emulator": "simavr -m atmega328p -f 16000000 {}" "emulator": "simavr -m atmega328p -f 16000000 {}"

Просмотреть файл

@ -2,8 +2,8 @@
"inherits": ["atmega328p"], "inherits": ["atmega328p"],
"build-tags": ["arduino"], "build-tags": ["arduino"],
"ldflags": [ "ldflags": [
"-Wl,--defsym=_bootloader_size=512", "--defsym=_bootloader_size=512",
"-Wl,--defsym=_stack_size=512" "--defsym=_stack_size=512"
], ],
"flash-command": "avrdude -c arduino -p atmega328p -P {port} -U flash:w:{hex}:i", "flash-command": "avrdude -c arduino -p atmega328p -P {port} -U flash:w:{hex}:i",
"serial-port": ["2341:0043", "2341:0001", "2a03:0043", "2341:0243"], "serial-port": ["2341:0043", "2341:0001", "2a03:0043", "2341:0243"],

Просмотреть файл

@ -4,8 +4,7 @@
"build-tags": ["atmega1280", "atmega"], "build-tags": ["atmega1280", "atmega"],
"serial": "uart", "serial": "uart",
"ldflags": [ "ldflags": [
"-mmcu=avr51", "--defsym=_stack_size=512"
"-Wl,--defsym=_stack_size=512"
], ],
"linkerscript": "src/device/avr/atmega1280.ld", "linkerscript": "src/device/avr/atmega1280.ld",
"extra-files": [ "extra-files": [

Просмотреть файл

@ -4,9 +4,8 @@
"build-tags": ["atmega1284p", "atmega"], "build-tags": ["atmega1284p", "atmega"],
"serial": "uart", "serial": "uart",
"ldflags": [ "ldflags": [
"-mmcu=avr51", "--defsym=_bootloader_size=0",
"-Wl,--defsym=_bootloader_size=0", "--defsym=_stack_size=512"
"-Wl,--defsym=_stack_size=512"
], ],
"linkerscript": "src/device/avr/atmega1284p.ld", "linkerscript": "src/device/avr/atmega1284p.ld",
"extra-files": [ "extra-files": [

Просмотреть файл

@ -4,8 +4,7 @@
"build-tags": ["atmega2560", "atmega"], "build-tags": ["atmega2560", "atmega"],
"serial": "uart", "serial": "uart",
"ldflags": [ "ldflags": [
"-mmcu=avr6", "--defsym=_stack_size=512"
"-Wl,--defsym=_stack_size=512"
], ],
"linkerscript": "src/device/avr/atmega2560.ld", "linkerscript": "src/device/avr/atmega2560.ld",
"extra-files": [ "extra-files": [

Просмотреть файл

@ -3,9 +3,6 @@
"cpu": "atmega328p", "cpu": "atmega328p",
"build-tags": ["atmega328p", "atmega", "avr5"], "build-tags": ["atmega328p", "atmega", "avr5"],
"serial": "uart", "serial": "uart",
"ldflags": [
"-mmcu=avr5"
],
"linkerscript": "src/device/avr/atmega328p.ld", "linkerscript": "src/device/avr/atmega328p.ld",
"extra-files": [ "extra-files": [
"targets/avr.S", "targets/avr.S",

Просмотреть файл

@ -5,9 +5,6 @@
"cflags": [ "cflags": [
"-D__AVR_ARCH__=25" "-D__AVR_ARCH__=25"
], ],
"ldflags": [
"-mmcu=avr25"
],
"linkerscript": "src/device/avr/attiny85.ld", "linkerscript": "src/device/avr/attiny85.ld",
"extra-files": [ "extra-files": [
"targets/avr.S", "targets/avr.S",

Просмотреть файл

@ -4,16 +4,17 @@
"goos": "linux", "goos": "linux",
"goarch": "arm", "goarch": "arm",
"gc": "conservative", "gc": "conservative",
"linker": "avr-gcc", "linker": "ld.lld",
"scheduler": "none", "scheduler": "none",
"rtlib": "compiler-rt", "rtlib": "compiler-rt",
"libc": "picolibc",
"default-stack-size": 256, "default-stack-size": 256,
"cflags": [ "cflags": [
"-Werror" "-Werror"
], ],
"ldflags": [ "ldflags": [
"-T", "targets/avr.ld", "-T", "targets/avr.ld",
"-Wl,--gc-sections" "--gc-sections"
], ],
"extra-files": [ "extra-files": [
"src/internal/task/task_stack_avr.S", "src/internal/task/task_stack_avr.S",

Просмотреть файл

@ -5,6 +5,8 @@ MEMORY
RAM (xrw) : ORIGIN = 0x800000 + __ram_start, LENGTH = __ram_size RAM (xrw) : ORIGIN = 0x800000 + __ram_start, LENGTH = __ram_size
} }
ENTRY(__vector_RESET)
SECTIONS SECTIONS
{ {
.text : .text :
@ -12,9 +14,11 @@ SECTIONS
KEEP(*(.vectors)) KEEP(*(.vectors))
KEEP(*(.text.__vector_RESET)) KEEP(*(.text.__vector_RESET))
KEEP(*(.text.main)) /* main must follow the reset handler */ KEEP(*(.text.main)) /* main must follow the reset handler */
*(.text)
*(.text.*) *(.text.*)
*(.progmem) *(.progmem)
*(.progmem.*) *(.progmem.*)
. = ALIGN(16); /* needed with ld.lld for some reasoon */
} }
.stack (NOLOAD) : .stack (NOLOAD) :

Просмотреть файл

@ -2,8 +2,8 @@
"inherits": ["attiny85"], "inherits": ["attiny85"],
"build-tags": ["digispark"], "build-tags": ["digispark"],
"ldflags": [ "ldflags": [
"-Wl,--defsym=_bootloader_size=2180", "--defsym=_bootloader_size=2180",
"-Wl,--defsym=_stack_size=128" "--defsym=_stack_size=128"
], ],
"flash-command": "micronucleus --run {hex}", "flash-command": "micronucleus --run {hex}",
"emulator": "simavr -m attiny85 -f 16000000 {}" "emulator": "simavr -m attiny85 -f 16000000 {}"

Просмотреть файл

@ -60,7 +60,7 @@ type Device struct {
// AddressSpace is the Go version of an XML element like the following: // AddressSpace is the Go version of an XML element like the following:
// //
// <address-space endianness="little" name="data" id="data" start="0x0000" size="0x0900"> // <address-space endianness="little" name="data" id="data" start="0x0000" size="0x0900">
// //
// It describes one address space in an AVR microcontroller. One address space // It describes one address space in an AVR microcontroller. One address space
// may have multiple memory segments. // may have multiple memory segments.
@ -71,7 +71,7 @@ type AddressSpace struct {
// MemorySegment is the Go version of an XML element like the following: // MemorySegment is the Go version of an XML element like the following:
// //
// <memory-segment name="IRAM" start="0x0100" size="0x0800" type="ram" external="false"/> // <memory-segment name="IRAM" start="0x0100" size="0x0800" type="ram" external="false"/>
// //
// It describes a single contiguous area of memory in a particular address space // It describes a single contiguous area of memory in a particular address space
// (see AddressSpace). // (see AddressSpace).
@ -432,7 +432,7 @@ __vector_default:
.endm .endm
; The interrupt vector of this device. Must be placed at address 0 by the linker. ; The interrupt vector of this device. Must be placed at address 0 by the linker.
.section .vectors .section .vectors, "a", %progbits
.global __vectors .global __vectors
`)) `))
err = t.Execute(out, device.metadata) err = t.Execute(out, device.metadata)