Merge pull request #1203 from cpunion/esp-llvm
Build Target Task 2: Multi-Platform LLVM Support and Bootable Code Generation
This commit is contained in:
1
.github/codecov.yml
vendored
1
.github/codecov.yml
vendored
@@ -9,4 +9,5 @@ coverage:
|
|||||||
- "internal/packages"
|
- "internal/packages"
|
||||||
- "internal/typepatch"
|
- "internal/typepatch"
|
||||||
- "internal/github"
|
- "internal/github"
|
||||||
|
- "internal/firmware"
|
||||||
- "xtool"
|
- "xtool"
|
||||||
|
|||||||
144
.github/workflows/targets.yml
vendored
144
.github/workflows/targets.yml
vendored
@@ -36,145 +36,5 @@ jobs:
|
|||||||
|
|
||||||
- name: Build targets
|
- name: Build targets
|
||||||
run: |
|
run: |
|
||||||
cd _demo/empty
|
cd _demo/targetsbuild
|
||||||
for target in \
|
bash build.sh
|
||||||
ae-rp2040 \
|
|
||||||
arduino-leonardo \
|
|
||||||
arduino-mega1280 \
|
|
||||||
arduino-mega2560 \
|
|
||||||
arduino-mkr1000 \
|
|
||||||
arduino-mkrwifi1010 \
|
|
||||||
arduino-nano-new \
|
|
||||||
arduino-nano \
|
|
||||||
arduino-nano33 \
|
|
||||||
arduino-zero \
|
|
||||||
arduino \
|
|
||||||
atmega1280 \
|
|
||||||
atmega1284p \
|
|
||||||
atmega2560 \
|
|
||||||
atmega328p \
|
|
||||||
atmega328pb \
|
|
||||||
atmega32u4 \
|
|
||||||
atsamd21e18a \
|
|
||||||
atsamd21g18a \
|
|
||||||
atsamd51g19a \
|
|
||||||
atsamd51j19a \
|
|
||||||
atsamd51j20a \
|
|
||||||
atsamd51p19a \
|
|
||||||
atsamd51p20a \
|
|
||||||
atsame51j19a \
|
|
||||||
atsame54-xpro \
|
|
||||||
atsame54p20a \
|
|
||||||
attiny1616 \
|
|
||||||
attiny85 \
|
|
||||||
badger2040-w \
|
|
||||||
badger2040 \
|
|
||||||
bluepill-clone \
|
|
||||||
bluepill \
|
|
||||||
btt-skr-pico \
|
|
||||||
challenger-rp2040 \
|
|
||||||
circuitplay-express \
|
|
||||||
cortex-m-qemu \
|
|
||||||
cortex-m0 \
|
|
||||||
cortex-m0plus \
|
|
||||||
cortex-m3 \
|
|
||||||
cortex-m33 \
|
|
||||||
cortex-m4 \
|
|
||||||
cortex-m7 \
|
|
||||||
digispark \
|
|
||||||
elecrow-rp2040 \
|
|
||||||
elecrow-rp2350 \
|
|
||||||
esp-c3-32s-kit \
|
|
||||||
esp32-c3-devkit-rust-1 \
|
|
||||||
esp32c3-12f \
|
|
||||||
esp32c3-supermini \
|
|
||||||
esp32c3 \
|
|
||||||
fe310 \
|
|
||||||
feather-m0-express \
|
|
||||||
feather-m0 \
|
|
||||||
feather-m4-can \
|
|
||||||
feather-m4 \
|
|
||||||
feather-rp2040 \
|
|
||||||
feather-stm32f405 \
|
|
||||||
gameboy-advance \
|
|
||||||
gemma-m0 \
|
|
||||||
gnse \
|
|
||||||
gobadge \
|
|
||||||
gopher-badge \
|
|
||||||
gopherbot \
|
|
||||||
grandcentral-m4 \
|
|
||||||
hifive1b \
|
|
||||||
itsybitsy-m0 \
|
|
||||||
itsybitsy-m4 \
|
|
||||||
k210 \
|
|
||||||
kb2040 \
|
|
||||||
lgt92 \
|
|
||||||
lorae5 \
|
|
||||||
m5stamp-c3 \
|
|
||||||
macropad-rp2040 \
|
|
||||||
maixbit \
|
|
||||||
makerfabs-esp32c3spi35 \
|
|
||||||
matrixportal-m4 \
|
|
||||||
metro-m4-airlift \
|
|
||||||
mksnanov3 \
|
|
||||||
nano-rp2040 \
|
|
||||||
nintendoswitch \
|
|
||||||
nucleo-f103rb \
|
|
||||||
nucleo-f722ze \
|
|
||||||
nucleo-l031k6 \
|
|
||||||
nucleo-l432kc \
|
|
||||||
nucleo-l476rg \
|
|
||||||
nucleo-l552ze \
|
|
||||||
nucleo-wl55jc \
|
|
||||||
p1am-100 \
|
|
||||||
pga2350 \
|
|
||||||
pico-plus2 \
|
|
||||||
pico-w \
|
|
||||||
pico \
|
|
||||||
pico2-w \
|
|
||||||
pico2 \
|
|
||||||
pybadge \
|
|
||||||
pygamer \
|
|
||||||
pyportal \
|
|
||||||
qtpy-esp32c3 \
|
|
||||||
qtpy-rp2040 \
|
|
||||||
qtpy \
|
|
||||||
riscv-qemu \
|
|
||||||
riscv32 \
|
|
||||||
riscv64 \
|
|
||||||
rp2040 \
|
|
||||||
rp2350 \
|
|
||||||
rp2350b \
|
|
||||||
simavr \
|
|
||||||
stm32f469disco \
|
|
||||||
stm32f4disco-1 \
|
|
||||||
stm32f4disco \
|
|
||||||
stm32l0x2 \
|
|
||||||
stm32wl5x_cm4 \
|
|
||||||
stm32wle5 \
|
|
||||||
swan \
|
|
||||||
teensy36 \
|
|
||||||
teensy40 \
|
|
||||||
teensy41 \
|
|
||||||
thingplus-rp2040 \
|
|
||||||
thumby \
|
|
||||||
tiny2350 \
|
|
||||||
tkey \
|
|
||||||
trinket-m0 \
|
|
||||||
trinkey-qt2040 \
|
|
||||||
tufty2040 \
|
|
||||||
wasip2 \
|
|
||||||
wasm-unknown \
|
|
||||||
waveshare-rp2040-tiny \
|
|
||||||
waveshare-rp2040-zero \
|
|
||||||
wioterminal \
|
|
||||||
xiao-esp32c3 \
|
|
||||||
xiao-rp2040 \
|
|
||||||
xiao; do
|
|
||||||
../../llgo.sh build -v -target $target -o hello.out . >/dev/null 2>&1
|
|
||||||
if [ $? -eq 0 ]; then
|
|
||||||
echo ✅ $target `file hello.out`
|
|
||||||
else
|
|
||||||
echo ❌ $target
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
}
|
|
||||||
21
_demo/targetsbuild/C/c.go
Normal file
21
_demo/targetsbuild/C/c.go
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
package C
|
||||||
|
|
||||||
|
func XhandleHardFault() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func Reset_Handler() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func XhandleInterrupt() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
type dyn64 struct {
|
||||||
|
// Fields for dynamic loader
|
||||||
|
}
|
||||||
|
|
||||||
|
// For nintendo switch
|
||||||
|
func X__dynamic_loader(base uintptr, dyn *dyn64) {
|
||||||
|
}
|
||||||
180
_demo/targetsbuild/build.sh
Normal file
180
_demo/targetsbuild/build.sh
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Function to display usage information
|
||||||
|
show_usage() {
|
||||||
|
cat << EOF
|
||||||
|
Usage: $(basename "$0") [OPTIONS] [TARGET_FILE]
|
||||||
|
|
||||||
|
Build targets for llgo across multiple platforms.
|
||||||
|
|
||||||
|
OPTIONS:
|
||||||
|
-h, --help Show this help message and exit
|
||||||
|
|
||||||
|
ARGUMENTS:
|
||||||
|
TARGET_FILE Optional. A text file containing target names, one per line.
|
||||||
|
Lines starting with # are treated as comments and ignored.
|
||||||
|
Empty lines are also ignored.
|
||||||
|
|
||||||
|
BEHAVIOR:
|
||||||
|
Without TARGET_FILE:
|
||||||
|
- Automatically discovers all targets from ../../targets/*.json files
|
||||||
|
- Extracts target names from JSON filenames
|
||||||
|
|
||||||
|
With TARGET_FILE:
|
||||||
|
- Reads target names from the specified file
|
||||||
|
- Supports comments (lines starting with #)
|
||||||
|
- Ignores empty lines and whitespace
|
||||||
|
|
||||||
|
IGNORED TARGETS:
|
||||||
|
The following targets are automatically ignored and not built:
|
||||||
|
atmega1280, atmega2560, atmega328p, atmega32u4, attiny85,
|
||||||
|
fe310, k210, riscv32, riscv64, rp2040
|
||||||
|
|
||||||
|
RESULT CATEGORIES:
|
||||||
|
✅ Successful: Build completed successfully
|
||||||
|
🔕 Ignored: Target is in the ignore list
|
||||||
|
⚠️ Warned: Build failed with configuration warnings
|
||||||
|
❌ Failed: Build failed with errors
|
||||||
|
|
||||||
|
EXIT CODES:
|
||||||
|
0 All builds successful, ignored, or warned only
|
||||||
|
1 One or more builds failed with errors
|
||||||
|
|
||||||
|
EXAMPLES:
|
||||||
|
$(basename "$0") # Build all targets from JSON files
|
||||||
|
$(basename "$0") my-targets.txt # Build targets from file
|
||||||
|
$(basename "$0") --help # Show this help
|
||||||
|
|
||||||
|
TARGET FILE FORMAT:
|
||||||
|
# This is a comment
|
||||||
|
esp32
|
||||||
|
cortex-m4
|
||||||
|
|
||||||
|
# Another comment
|
||||||
|
riscv64
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check for help flag
|
||||||
|
if [[ "$1" == "-h" || "$1" == "--help" ]]; then
|
||||||
|
show_usage
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check for invalid number of arguments
|
||||||
|
if [ $# -gt 1 ]; then
|
||||||
|
echo "Error: Too many arguments."
|
||||||
|
echo "Use '$(basename "$0") --help' for usage information."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Initialize arrays to store results
|
||||||
|
successful_targets=()
|
||||||
|
ignored_targets=()
|
||||||
|
warned_targets=()
|
||||||
|
failed_targets=()
|
||||||
|
targets_to_build=()
|
||||||
|
|
||||||
|
# Define ignore list
|
||||||
|
ignore_list=(
|
||||||
|
"atmega1280"
|
||||||
|
"atmega2560"
|
||||||
|
"atmega328p"
|
||||||
|
"atmega32u4"
|
||||||
|
"attiny85"
|
||||||
|
"fe310"
|
||||||
|
"k210"
|
||||||
|
"riscv32"
|
||||||
|
"riscv64"
|
||||||
|
"rp2040"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Build the targets list based on input method
|
||||||
|
if [ $# -eq 1 ]; then
|
||||||
|
# Read targets from file
|
||||||
|
target_file="$1"
|
||||||
|
if [ ! -f "$target_file" ]; then
|
||||||
|
echo "Error: Target file '$target_file' not found."
|
||||||
|
echo "Use '$(basename "$0") --help' for usage information."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
while IFS= read -r target || [[ -n "$target" ]]; do
|
||||||
|
# Skip empty lines and comments
|
||||||
|
if [[ -z "$target" || "$target" =~ ^[[:space:]]*# ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Trim whitespace
|
||||||
|
target=$(echo "$target" | xargs)
|
||||||
|
targets_to_build+=("$target")
|
||||||
|
done < "$target_file"
|
||||||
|
else
|
||||||
|
# Use targets from *.json files
|
||||||
|
for target_file in ../../targets/*.json; do
|
||||||
|
# Extract target name from filename (remove path and .json extension)
|
||||||
|
target=$(basename "$target_file" .json)
|
||||||
|
targets_to_build+=("$target")
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Process each target
|
||||||
|
for target in "${targets_to_build[@]}"; do
|
||||||
|
# Check if target is in ignore list
|
||||||
|
if [[ " ${ignore_list[@]} " =~ " ${target} " ]]; then
|
||||||
|
echo 🔕 $target "(ignored)"
|
||||||
|
ignored_targets+=("$target")
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
output=$(../../llgo.sh build -target $target -o hello.out . 2>&1)
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
echo ✅ $target `file hello.out`
|
||||||
|
successful_targets+=("$target")
|
||||||
|
else
|
||||||
|
# Check if output contains warning messages
|
||||||
|
if echo "$output" | grep -q "does not have a valid LLVM target triple\|does not have a valid CPU configuration"; then
|
||||||
|
echo ⚠️ $target
|
||||||
|
echo "$output"
|
||||||
|
warned_targets+=("$target")
|
||||||
|
else
|
||||||
|
echo ❌ $target
|
||||||
|
echo "$output"
|
||||||
|
failed_targets+=("$target")
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "----------------------------------------"
|
||||||
|
|
||||||
|
# Output successful targets
|
||||||
|
echo "Successful targets (${#successful_targets[@]} total):"
|
||||||
|
for target in "${successful_targets[@]}"; do
|
||||||
|
echo "$target"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Ignored targets (${#ignored_targets[@]} total):"
|
||||||
|
for target in "${ignored_targets[@]}"; do
|
||||||
|
echo "$target"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Warned targets (${#warned_targets[@]} total):"
|
||||||
|
for target in "${warned_targets[@]}"; do
|
||||||
|
echo "$target"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Failed targets (${#failed_targets[@]} total):"
|
||||||
|
for target in "${failed_targets[@]}"; do
|
||||||
|
echo "$target"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Exit with error code if there are any failed targets
|
||||||
|
if [ ${#failed_targets[@]} -gt 0 ]; then
|
||||||
|
echo ""
|
||||||
|
echo "Build failed with ${#failed_targets[@]} failed targets."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
6
_demo/targetsbuild/empty.go
Normal file
6
_demo/targetsbuild/empty.go
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import _ "github.com/goplus/llgo/_demo/targetsbuild/C"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
}
|
||||||
2
go.mod
2
go.mod
@@ -15,6 +15,8 @@ require (
|
|||||||
golang.org/x/tools v0.36.0
|
golang.org/x/tools v0.36.0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
require github.com/sigurn/crc16 v0.0.0-20240131213347-83fcde1e29d1
|
||||||
|
|
||||||
require (
|
require (
|
||||||
golang.org/x/mod v0.27.0 // indirect
|
golang.org/x/mod v0.27.0 // indirect
|
||||||
golang.org/x/sync v0.16.0 // indirect
|
golang.org/x/sync v0.16.0 // indirect
|
||||||
|
|||||||
2
go.sum
2
go.sum
@@ -12,6 +12,8 @@ github.com/goplus/mod v0.17.1 h1:ITovxDcc5zbURV/Wrp3/SBsYLgC1KrxY6pq1zMM2V94=
|
|||||||
github.com/goplus/mod v0.17.1/go.mod h1:iXEszBKqi38BAyQApBPyQeurLHmQN34YMgC2ZNdap50=
|
github.com/goplus/mod v0.17.1/go.mod h1:iXEszBKqi38BAyQApBPyQeurLHmQN34YMgC2ZNdap50=
|
||||||
github.com/qiniu/x v1.15.1 h1:avE+YQaowp8ZExjylOeSM73rUo3MQKBAYVxh4NJ8dY8=
|
github.com/qiniu/x v1.15.1 h1:avE+YQaowp8ZExjylOeSM73rUo3MQKBAYVxh4NJ8dY8=
|
||||||
github.com/qiniu/x v1.15.1/go.mod h1:AiovSOCaRijaf3fj+0CBOpR1457pn24b0Vdb1JpwhII=
|
github.com/qiniu/x v1.15.1/go.mod h1:AiovSOCaRijaf3fj+0CBOpR1457pn24b0Vdb1JpwhII=
|
||||||
|
github.com/sigurn/crc16 v0.0.0-20240131213347-83fcde1e29d1 h1:NVK+OqnavpyFmUiKfUMHrpvbCi2VFoWTrcpI7aDaJ2I=
|
||||||
|
github.com/sigurn/crc16 v0.0.0-20240131213347-83fcde1e29d1/go.mod h1:9/etS5gpQq9BJsJMWg1wpLbfuSnkm8dPF6FdW2JXVhA=
|
||||||
golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
|
golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
|
||||||
golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
|
golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
|
||||||
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
|
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
|
||||||
|
|||||||
@@ -39,13 +39,14 @@ import (
|
|||||||
|
|
||||||
"github.com/goplus/llgo/cl"
|
"github.com/goplus/llgo/cl"
|
||||||
"github.com/goplus/llgo/internal/cabi"
|
"github.com/goplus/llgo/internal/cabi"
|
||||||
|
"github.com/goplus/llgo/internal/clang"
|
||||||
"github.com/goplus/llgo/internal/crosscompile"
|
"github.com/goplus/llgo/internal/crosscompile"
|
||||||
"github.com/goplus/llgo/internal/env"
|
"github.com/goplus/llgo/internal/env"
|
||||||
|
"github.com/goplus/llgo/internal/firmware"
|
||||||
"github.com/goplus/llgo/internal/mockable"
|
"github.com/goplus/llgo/internal/mockable"
|
||||||
"github.com/goplus/llgo/internal/packages"
|
"github.com/goplus/llgo/internal/packages"
|
||||||
"github.com/goplus/llgo/internal/typepatch"
|
"github.com/goplus/llgo/internal/typepatch"
|
||||||
"github.com/goplus/llgo/ssa/abi"
|
"github.com/goplus/llgo/ssa/abi"
|
||||||
"github.com/goplus/llgo/xtool/clang"
|
|
||||||
xenv "github.com/goplus/llgo/xtool/env"
|
xenv "github.com/goplus/llgo/xtool/env"
|
||||||
"github.com/goplus/llgo/xtool/env/llvm"
|
"github.com/goplus/llgo/xtool/env/llvm"
|
||||||
|
|
||||||
@@ -156,7 +157,7 @@ func Do(args []string, conf *Config) ([]Package, error) {
|
|||||||
conf.Goarch = runtime.GOARCH
|
conf.Goarch = runtime.GOARCH
|
||||||
}
|
}
|
||||||
// Handle crosscompile configuration first to set correct GOOS/GOARCH
|
// Handle crosscompile configuration first to set correct GOOS/GOARCH
|
||||||
export, err := crosscompile.UseWithTarget(conf.Goos, conf.Goarch, IsWasiThreadsEnabled(), conf.Target)
|
export, err := crosscompile.Use(conf.Goos, conf.Goarch, IsWasiThreadsEnabled(), conf.Target)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to setup crosscompile: %w", err)
|
return nil, fmt.Errorf("failed to setup crosscompile: %w", err)
|
||||||
}
|
}
|
||||||
@@ -389,19 +390,27 @@ type context struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) compiler() *clang.Cmd {
|
func (c *context) compiler() *clang.Cmd {
|
||||||
cmd := c.env.Clang()
|
config := clang.NewConfig(
|
||||||
if c.crossCompile.CC != "" {
|
c.crossCompile.CC,
|
||||||
cmd = clang.New(c.crossCompile.CC)
|
c.crossCompile.CCFLAGS,
|
||||||
}
|
c.crossCompile.CFLAGS,
|
||||||
|
c.crossCompile.LDFLAGS,
|
||||||
|
c.crossCompile.Linker,
|
||||||
|
)
|
||||||
|
cmd := clang.NewCompiler(config)
|
||||||
cmd.Verbose = c.buildConf.Verbose
|
cmd.Verbose = c.buildConf.Verbose
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) linker() *clang.Cmd {
|
func (c *context) linker() *clang.Cmd {
|
||||||
cmd := c.env.Clang()
|
config := clang.NewConfig(
|
||||||
if c.crossCompile.Linker != "" {
|
c.crossCompile.CC,
|
||||||
cmd = clang.New(c.crossCompile.Linker)
|
c.crossCompile.CCFLAGS,
|
||||||
}
|
c.crossCompile.CFLAGS,
|
||||||
|
c.crossCompile.LDFLAGS,
|
||||||
|
c.crossCompile.Linker,
|
||||||
|
)
|
||||||
|
cmd := clang.NewLinker(config)
|
||||||
cmd.Verbose = c.buildConf.Verbose
|
cmd.Verbose = c.buildConf.Verbose
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
@@ -552,23 +561,145 @@ func createGlobals(ctx *context, prog llssa.Program, pkgs []*aPackage) (llssa.Pa
|
|||||||
return global, nil
|
return global, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, global llssa.Package, conf *Config, mode Mode, verbose bool) {
|
// compileExtraFiles compiles extra files (.s/.c) from target configuration and returns object files
|
||||||
pkgPath := pkg.PkgPath
|
func compileExtraFiles(ctx *context, verbose bool) ([]string, error) {
|
||||||
name := path.Base(pkgPath)
|
if len(ctx.crossCompile.ExtraFiles) == 0 {
|
||||||
app := conf.OutFile
|
return nil, nil
|
||||||
if app == "" {
|
}
|
||||||
if mode == ModeBuild && len(ctx.initial) > 1 {
|
|
||||||
|
var objFiles []string
|
||||||
|
llgoRoot := env.LLGoROOT()
|
||||||
|
|
||||||
|
for _, extraFile := range ctx.crossCompile.ExtraFiles {
|
||||||
|
// Resolve the file path relative to llgo root
|
||||||
|
srcFile := filepath.Join(llgoRoot, extraFile)
|
||||||
|
|
||||||
|
// Check if file exists
|
||||||
|
if _, err := os.Stat(srcFile); os.IsNotExist(err) {
|
||||||
|
return nil, fmt.Errorf("extra file not found: %s", srcFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate output file name
|
||||||
|
objFile, err := os.CreateTemp("", "extra-*"+filepath.Base(extraFile))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to create temp file for %s: %w", extraFile, err)
|
||||||
|
}
|
||||||
|
objFile.Close()
|
||||||
|
|
||||||
|
var outputFile string
|
||||||
|
ext := filepath.Ext(srcFile)
|
||||||
|
|
||||||
|
if ctx.buildConf.GenLL {
|
||||||
|
outputFile = objFile.Name() + ".ll"
|
||||||
|
} else {
|
||||||
|
outputFile = objFile.Name() + ".o"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare compilation arguments
|
||||||
|
var args []string
|
||||||
|
|
||||||
|
// Handle different file types
|
||||||
|
switch ext {
|
||||||
|
case ".c":
|
||||||
|
args = append(args, "-x", "c")
|
||||||
|
case ".S", ".s":
|
||||||
|
args = append(args, "-x", "assembler-with-cpp")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add output flags
|
||||||
|
if ctx.buildConf.GenLL {
|
||||||
|
args = append(args, "-emit-llvm", "-S", "-o", outputFile, "-c", srcFile)
|
||||||
|
} else {
|
||||||
|
args = append(args, "-o", outputFile, "-c", srcFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
if verbose {
|
||||||
|
fmt.Fprintf(os.Stderr, "Compiling extra file: clang %s\n", strings.Join(args, " "))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compile the file
|
||||||
|
cmd := ctx.compiler()
|
||||||
|
if err := cmd.Compile(args...); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to compile extra file %s: %w", srcFile, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
objFiles = append(objFiles, outputFile)
|
||||||
|
os.Remove(objFile.Name()) // Remove the temp file we created for naming
|
||||||
|
}
|
||||||
|
|
||||||
|
return objFiles, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// generateOutputFilenames generates the final output filename (app) and intermediate filename (orgApp)
|
||||||
|
// based on configuration and build context.
|
||||||
|
func generateOutputFilenames(outFile, binPath, appExt, binExt, pkgName string, mode Mode, isMultiplePkgs bool) (app, orgApp string, err error) {
|
||||||
|
if outFile == "" {
|
||||||
|
if mode == ModeBuild && isMultiplePkgs {
|
||||||
// For multiple packages in ModeBuild mode, use temporary file
|
// For multiple packages in ModeBuild mode, use temporary file
|
||||||
tmpFile, err := os.CreateTemp("", name+"*"+conf.AppExt)
|
name := pkgName
|
||||||
check(err)
|
if binExt != "" {
|
||||||
|
name += "*" + binExt
|
||||||
|
} else {
|
||||||
|
name += "*" + appExt
|
||||||
|
}
|
||||||
|
tmpFile, err := os.CreateTemp("", name)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
app = tmpFile.Name()
|
app = tmpFile.Name()
|
||||||
tmpFile.Close()
|
tmpFile.Close()
|
||||||
} else {
|
} else {
|
||||||
app = filepath.Join(conf.BinPath, name+conf.AppExt)
|
app = filepath.Join(binPath, pkgName+appExt)
|
||||||
|
}
|
||||||
|
orgApp = app
|
||||||
|
} else {
|
||||||
|
// outFile is not empty, use it as base part
|
||||||
|
base := outFile
|
||||||
|
if binExt != "" {
|
||||||
|
// If binExt has value, use temporary file as orgApp for firmware conversion
|
||||||
|
tmpFile, err := os.CreateTemp("", "llgo-*"+appExt)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
orgApp = tmpFile.Name()
|
||||||
|
tmpFile.Close()
|
||||||
|
// Check if base already ends with binExt, if so, don't add it again
|
||||||
|
if strings.HasSuffix(base, binExt) {
|
||||||
|
app = base
|
||||||
|
} else {
|
||||||
|
app = base + binExt
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// No binExt, use base + AppExt directly
|
||||||
|
if filepath.Ext(base) == "" {
|
||||||
|
app = base + appExt
|
||||||
|
} else {
|
||||||
|
app = base
|
||||||
|
}
|
||||||
|
orgApp = app
|
||||||
}
|
}
|
||||||
} else if filepath.Ext(app) == "" {
|
|
||||||
app += conf.AppExt
|
|
||||||
}
|
}
|
||||||
|
return app, orgApp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, global llssa.Package, conf *Config, mode Mode, verbose bool) {
|
||||||
|
pkgPath := pkg.PkgPath
|
||||||
|
name := path.Base(pkgPath)
|
||||||
|
binFmt := ctx.crossCompile.BinaryFormat
|
||||||
|
binExt := firmware.BinaryExt(binFmt)
|
||||||
|
|
||||||
|
// app: converted firmware output file or executable file
|
||||||
|
// orgApp: before converted output file
|
||||||
|
app, orgApp, err := generateOutputFilenames(
|
||||||
|
conf.OutFile,
|
||||||
|
conf.BinPath,
|
||||||
|
conf.AppExt,
|
||||||
|
binExt,
|
||||||
|
name,
|
||||||
|
mode,
|
||||||
|
len(ctx.initial) > 1,
|
||||||
|
)
|
||||||
|
check(err)
|
||||||
|
|
||||||
needRuntime := false
|
needRuntime := false
|
||||||
needPyInit := false
|
needPyInit := false
|
||||||
@@ -600,6 +731,11 @@ func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, global l
|
|||||||
// defer os.Remove(entryLLFile)
|
// defer os.Remove(entryLLFile)
|
||||||
objFiles = append(objFiles, entryObjFile)
|
objFiles = append(objFiles, entryObjFile)
|
||||||
|
|
||||||
|
// Compile extra files from target configuration
|
||||||
|
extraObjFiles, err := compileExtraFiles(ctx, verbose)
|
||||||
|
check(err)
|
||||||
|
objFiles = append(objFiles, extraObjFiles...)
|
||||||
|
|
||||||
if global != nil {
|
if global != nil {
|
||||||
export, err := exportObject(ctx, pkg.PkgPath+".global", pkg.ExportFile+"-global", []byte(global.String()))
|
export, err := exportObject(ctx, pkg.PkgPath+".global", pkg.ExportFile+"-global", []byte(global.String()))
|
||||||
check(err)
|
check(err)
|
||||||
@@ -619,9 +755,15 @@ func linkMainPkg(ctx *context, pkg *packages.Package, pkgs []*aPackage, global l
|
|||||||
linkArgs = append(linkArgs, exargs...)
|
linkArgs = append(linkArgs, exargs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = linkObjFiles(ctx, app, objFiles, linkArgs, verbose)
|
err = linkObjFiles(ctx, orgApp, objFiles, linkArgs, verbose)
|
||||||
check(err)
|
check(err)
|
||||||
|
|
||||||
|
if orgApp != app {
|
||||||
|
fmt.Printf("cross compile: %#v\n", ctx.crossCompile)
|
||||||
|
err = firmware.MakeFirmwareImage(orgApp, app, ctx.crossCompile.BinaryFormat, ctx.crossCompile.FormatDetail)
|
||||||
|
check(err)
|
||||||
|
}
|
||||||
|
|
||||||
switch mode {
|
switch mode {
|
||||||
case ModeTest:
|
case ModeTest:
|
||||||
cmd := exec.Command(app, conf.RunArgs...)
|
cmd := exec.Command(app, conf.RunArgs...)
|
||||||
@@ -685,8 +827,6 @@ func linkObjFiles(ctx *context, app string, objFiles, linkArgs []string, verbose
|
|||||||
buildArgs = append(buildArgs, "-gdwarf-4")
|
buildArgs = append(buildArgs, "-gdwarf-4")
|
||||||
}
|
}
|
||||||
|
|
||||||
buildArgs = append(buildArgs, ctx.crossCompile.LDFLAGS...)
|
|
||||||
buildArgs = append(buildArgs, ctx.crossCompile.EXTRAFLAGS...)
|
|
||||||
buildArgs = append(buildArgs, objFiles...)
|
buildArgs = append(buildArgs, objFiles...)
|
||||||
|
|
||||||
cmd := ctx.linker()
|
cmd := ctx.linker()
|
||||||
@@ -698,6 +838,18 @@ func isWasmTarget(goos string) bool {
|
|||||||
return slices.Contains([]string{"wasi", "js", "wasip1"}, goos)
|
return slices.Contains([]string{"wasi", "js", "wasip1"}, goos)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func needStart(conf *Config) bool {
|
||||||
|
if conf.Target == "" {
|
||||||
|
return !isWasmTarget(conf.Goos)
|
||||||
|
}
|
||||||
|
switch conf.Target {
|
||||||
|
case "wasip2":
|
||||||
|
return false
|
||||||
|
default:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func genMainModuleFile(ctx *context, rtPkgPath string, pkg *packages.Package, needRuntime, needPyInit bool) (path string, err error) {
|
func genMainModuleFile(ctx *context, rtPkgPath string, pkg *packages.Package, needRuntime, needPyInit bool) (path string, err error) {
|
||||||
var (
|
var (
|
||||||
pyInitDecl string
|
pyInitDecl string
|
||||||
@@ -751,8 +903,10 @@ define weak void @_start() {
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
mainDefine := "define i32 @main(i32 noundef %0, ptr nocapture noundef readnone %1) local_unnamed_addr"
|
mainDefine := "define i32 @main(i32 noundef %0, ptr nocapture noundef readnone %1) local_unnamed_addr"
|
||||||
if isWasmTarget(ctx.buildConf.Goos) {
|
if !needStart(ctx.buildConf) && isWasmTarget(ctx.buildConf.Goos) {
|
||||||
mainDefine = "define hidden noundef i32 @__main_argc_argv(i32 noundef %0, ptr nocapture noundef readnone %1) local_unnamed_addr"
|
mainDefine = "define hidden noundef i32 @__main_argc_argv(i32 noundef %0, ptr nocapture noundef readnone %1) local_unnamed_addr"
|
||||||
|
}
|
||||||
|
if !needStart(ctx.buildConf) {
|
||||||
startDefine = ""
|
startDefine = ""
|
||||||
}
|
}
|
||||||
mainCode := fmt.Sprintf(`; ModuleID = 'main'
|
mainCode := fmt.Sprintf(`; ModuleID = 'main'
|
||||||
@@ -883,8 +1037,6 @@ func exportObject(ctx *context, pkgPath string, exportFile string, data []byte)
|
|||||||
}
|
}
|
||||||
exportFile += ".o"
|
exportFile += ".o"
|
||||||
args := []string{"-o", exportFile, "-c", f.Name(), "-Wno-override-module"}
|
args := []string{"-o", exportFile, "-c", f.Name(), "-Wno-override-module"}
|
||||||
args = append(args, ctx.crossCompile.CCFLAGS...)
|
|
||||||
args = append(args, ctx.crossCompile.CFLAGS...)
|
|
||||||
if ctx.buildConf.Verbose {
|
if ctx.buildConf.Verbose {
|
||||||
fmt.Fprintln(os.Stderr, "clang", args)
|
fmt.Fprintln(os.Stderr, "clang", args)
|
||||||
}
|
}
|
||||||
@@ -1126,8 +1278,6 @@ func clFile(ctx *context, args []string, cFile, expFile string, procFile func(li
|
|||||||
llFile += ".o"
|
llFile += ".o"
|
||||||
args = append(args, "-o", llFile, "-c", cFile)
|
args = append(args, "-o", llFile, "-c", cFile)
|
||||||
}
|
}
|
||||||
args = append(args, ctx.crossCompile.CCFLAGS...)
|
|
||||||
args = append(args, ctx.crossCompile.CFLAGS...)
|
|
||||||
if verbose {
|
if verbose {
|
||||||
fmt.Fprintln(os.Stderr, "clang", args)
|
fmt.Fprintln(os.Stderr, "clang", args)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/goplus/llgo/internal/mockable"
|
"github.com/goplus/llgo/internal/mockable"
|
||||||
@@ -93,3 +94,173 @@ func TestExtest(t *testing.T) {
|
|||||||
func TestCmpTest(t *testing.T) {
|
func TestCmpTest(t *testing.T) {
|
||||||
mockRun([]string{"../../cl/_testgo/runtest"}, &Config{Mode: ModeCmpTest})
|
mockRun([]string{"../../cl/_testgo/runtest"}, &Config{Mode: ModeCmpTest})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGenerateOutputFilenames(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
outFile string
|
||||||
|
binPath string
|
||||||
|
appExt string
|
||||||
|
binExt string
|
||||||
|
pkgName string
|
||||||
|
mode Mode
|
||||||
|
isMultiplePkgs bool
|
||||||
|
wantAppSuffix string
|
||||||
|
wantOrgAppDiff bool // true if orgApp should be different from app
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "empty outFile, single package",
|
||||||
|
outFile: "",
|
||||||
|
binPath: "/usr/local/bin",
|
||||||
|
appExt: "",
|
||||||
|
binExt: "",
|
||||||
|
pkgName: "hello",
|
||||||
|
mode: ModeBuild,
|
||||||
|
isMultiplePkgs: false,
|
||||||
|
wantAppSuffix: "/usr/local/bin/hello",
|
||||||
|
wantOrgAppDiff: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "empty outFile with appExt",
|
||||||
|
outFile: "",
|
||||||
|
binPath: "/usr/local/bin",
|
||||||
|
appExt: ".exe",
|
||||||
|
binExt: "",
|
||||||
|
pkgName: "hello",
|
||||||
|
mode: ModeBuild,
|
||||||
|
isMultiplePkgs: false,
|
||||||
|
wantAppSuffix: "/usr/local/bin/hello.exe",
|
||||||
|
wantOrgAppDiff: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "outFile without binExt",
|
||||||
|
outFile: "myapp",
|
||||||
|
binPath: "/usr/local/bin",
|
||||||
|
appExt: ".exe",
|
||||||
|
binExt: "",
|
||||||
|
pkgName: "hello",
|
||||||
|
mode: ModeBuild,
|
||||||
|
isMultiplePkgs: false,
|
||||||
|
wantAppSuffix: "myapp.exe",
|
||||||
|
wantOrgAppDiff: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "outFile with existing extension, no binExt",
|
||||||
|
outFile: "myapp.exe",
|
||||||
|
binPath: "/usr/local/bin",
|
||||||
|
appExt: ".exe",
|
||||||
|
binExt: "",
|
||||||
|
pkgName: "hello",
|
||||||
|
mode: ModeBuild,
|
||||||
|
isMultiplePkgs: false,
|
||||||
|
wantAppSuffix: "myapp.exe",
|
||||||
|
wantOrgAppDiff: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "outFile with binExt, different from existing extension",
|
||||||
|
outFile: "myapp",
|
||||||
|
binPath: "/usr/local/bin",
|
||||||
|
appExt: ".exe",
|
||||||
|
binExt: ".bin",
|
||||||
|
pkgName: "hello",
|
||||||
|
mode: ModeBuild,
|
||||||
|
isMultiplePkgs: false,
|
||||||
|
wantAppSuffix: "myapp.bin",
|
||||||
|
wantOrgAppDiff: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "outFile already ends with binExt",
|
||||||
|
outFile: "t.bin",
|
||||||
|
binPath: "/usr/local/bin",
|
||||||
|
appExt: ".exe",
|
||||||
|
binExt: ".bin",
|
||||||
|
pkgName: "hello",
|
||||||
|
mode: ModeBuild,
|
||||||
|
isMultiplePkgs: false,
|
||||||
|
wantAppSuffix: "t.bin",
|
||||||
|
wantOrgAppDiff: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "outFile with full path already ends with binExt",
|
||||||
|
outFile: "/path/to/t.bin",
|
||||||
|
binPath: "/usr/local/bin",
|
||||||
|
appExt: ".exe",
|
||||||
|
binExt: ".bin",
|
||||||
|
pkgName: "hello",
|
||||||
|
mode: ModeBuild,
|
||||||
|
isMultiplePkgs: false,
|
||||||
|
wantAppSuffix: "/path/to/t.bin",
|
||||||
|
wantOrgAppDiff: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
app, orgApp, err := generateOutputFilenames(
|
||||||
|
tt.outFile,
|
||||||
|
tt.binPath,
|
||||||
|
tt.appExt,
|
||||||
|
tt.binExt,
|
||||||
|
tt.pkgName,
|
||||||
|
tt.mode,
|
||||||
|
tt.isMultiplePkgs,
|
||||||
|
)
|
||||||
|
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("generateOutputFilenames() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if tt.wantAppSuffix != "" {
|
||||||
|
if app != tt.wantAppSuffix {
|
||||||
|
t.Errorf("generateOutputFilenames() app = %v, want %v", app, tt.wantAppSuffix)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if tt.wantOrgAppDiff {
|
||||||
|
if app == orgApp {
|
||||||
|
t.Errorf("generateOutputFilenames() orgApp should be different from app, but both are %v", app)
|
||||||
|
}
|
||||||
|
// Clean up temp file
|
||||||
|
if orgApp != "" && strings.Contains(orgApp, "llgo-") {
|
||||||
|
os.Remove(orgApp)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if app != orgApp {
|
||||||
|
t.Errorf("generateOutputFilenames() orgApp = %v, want %v (same as app)", orgApp, app)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGenerateOutputFilenames_EdgeCases(t *testing.T) {
|
||||||
|
// Test case where outFile has same extension as binExt
|
||||||
|
app, orgApp, err := generateOutputFilenames(
|
||||||
|
"firmware.bin",
|
||||||
|
"/usr/local/bin",
|
||||||
|
".exe",
|
||||||
|
".bin",
|
||||||
|
"esp32app",
|
||||||
|
ModeBuild,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if app != "firmware.bin" {
|
||||||
|
t.Errorf("Expected app to be 'firmware.bin', got '%s'", app)
|
||||||
|
}
|
||||||
|
|
||||||
|
if app == orgApp {
|
||||||
|
t.Errorf("Expected orgApp to be different from app when binExt is present, but both are '%s'", app)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up temp file
|
||||||
|
if orgApp != "" && strings.Contains(orgApp, "llgo-") {
|
||||||
|
os.Remove(orgApp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
202
internal/clang/clang.go
Normal file
202
internal/clang/clang.go
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package clang
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/xtool/safesplit"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Config represents clang configuration parameters.
|
||||||
|
type Config struct {
|
||||||
|
CC string // Compiler to use (e.g., "clang", "clang++")
|
||||||
|
CCFLAGS []string // Compiler flags for C/C++ compilation
|
||||||
|
CFLAGS []string // C-specific flags
|
||||||
|
LDFLAGS []string // Linker flags
|
||||||
|
Linker string // Linker to use (e.g., "ld.lld", "avr-ld")
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewConfig creates a new Config with the specified parameters.
|
||||||
|
func NewConfig(cc string, ccflags, cflags, ldflags []string, linker string) Config {
|
||||||
|
return Config{
|
||||||
|
CC: cc,
|
||||||
|
CCFLAGS: ccflags,
|
||||||
|
CFLAGS: cflags,
|
||||||
|
LDFLAGS: ldflags,
|
||||||
|
Linker: linker,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cmd represents a clang command with environment and configuration support.
|
||||||
|
type Cmd struct {
|
||||||
|
app string
|
||||||
|
config Config
|
||||||
|
Env []string
|
||||||
|
Verbose bool
|
||||||
|
Stdin io.Reader
|
||||||
|
Stdout io.Writer
|
||||||
|
Stderr io.Writer
|
||||||
|
}
|
||||||
|
|
||||||
|
// New creates a new clang command with configuration.
|
||||||
|
func New(app string, config Config) *Cmd {
|
||||||
|
if app == "" {
|
||||||
|
app = "clang"
|
||||||
|
}
|
||||||
|
return &Cmd{
|
||||||
|
app: app,
|
||||||
|
config: config,
|
||||||
|
Env: nil,
|
||||||
|
Verbose: false,
|
||||||
|
Stdin: nil,
|
||||||
|
Stdout: os.Stdout,
|
||||||
|
Stderr: os.Stderr,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewCompiler creates a compiler command with proper flag merging.
|
||||||
|
func NewCompiler(config Config) *Cmd {
|
||||||
|
app := "clang"
|
||||||
|
if config.CC != "" {
|
||||||
|
app = config.CC
|
||||||
|
}
|
||||||
|
return New(app, config)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewLinker creates a linker command with proper flag merging.
|
||||||
|
func NewLinker(config Config) *Cmd {
|
||||||
|
app := "clang"
|
||||||
|
if config.Linker != "" {
|
||||||
|
app = config.Linker
|
||||||
|
} else if config.CC != "" {
|
||||||
|
app = config.CC
|
||||||
|
}
|
||||||
|
return New(app, config)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compile executes a compilation command with merged flags.
|
||||||
|
func (c *Cmd) Compile(args ...string) error {
|
||||||
|
flags := c.mergeCompilerFlags()
|
||||||
|
allArgs := make([]string, 0, len(flags)+len(args))
|
||||||
|
allArgs = append(allArgs, flags...)
|
||||||
|
allArgs = append(allArgs, args...)
|
||||||
|
return c.exec(allArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Link executes a linking command with merged flags.
|
||||||
|
func (c *Cmd) Link(args ...string) error {
|
||||||
|
flags := c.mergeLinkerFlags()
|
||||||
|
allArgs := make([]string, 0, len(flags)+len(args))
|
||||||
|
allArgs = append(allArgs, flags...)
|
||||||
|
allArgs = append(allArgs, args...)
|
||||||
|
return c.exec(allArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// mergeCompilerFlags merges environment CCFLAGS/CFLAGS with config flags.
|
||||||
|
func (c *Cmd) mergeCompilerFlags() []string {
|
||||||
|
var flags []string
|
||||||
|
|
||||||
|
// Add environment CCFLAGS
|
||||||
|
if envCCFlags := os.Getenv("CCFLAGS"); envCCFlags != "" {
|
||||||
|
flags = append(flags, safesplit.SplitPkgConfigFlags(envCCFlags)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add environment CFLAGS
|
||||||
|
if envCFlags := os.Getenv("CFLAGS"); envCFlags != "" {
|
||||||
|
flags = append(flags, safesplit.SplitPkgConfigFlags(envCFlags)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add config CCFLAGS
|
||||||
|
flags = append(flags, c.config.CCFLAGS...)
|
||||||
|
|
||||||
|
// Add config CFLAGS
|
||||||
|
flags = append(flags, c.config.CFLAGS...)
|
||||||
|
|
||||||
|
return flags
|
||||||
|
}
|
||||||
|
|
||||||
|
// mergeLinkerFlags merges environment CCFLAGS/LDFLAGS with config flags.
|
||||||
|
func (c *Cmd) mergeLinkerFlags() []string {
|
||||||
|
var flags []string
|
||||||
|
|
||||||
|
// Add environment CCFLAGS (for linker)
|
||||||
|
if envCCFlags := os.Getenv("CCFLAGS"); envCCFlags != "" {
|
||||||
|
flags = append(flags, safesplit.SplitPkgConfigFlags(envCCFlags)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add environment LDFLAGS
|
||||||
|
if envLDFlags := os.Getenv("LDFLAGS"); envLDFlags != "" {
|
||||||
|
flags = append(flags, safesplit.SplitPkgConfigFlags(envLDFlags)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add config LDFLAGS
|
||||||
|
flags = append(flags, c.config.LDFLAGS...)
|
||||||
|
|
||||||
|
return flags
|
||||||
|
}
|
||||||
|
|
||||||
|
// exec executes the clang command with given arguments.
|
||||||
|
func (c *Cmd) exec(args ...string) error {
|
||||||
|
cmd := exec.Command(c.app, args...)
|
||||||
|
if c.Verbose {
|
||||||
|
fmt.Fprintf(os.Stderr, "%v\n", cmd)
|
||||||
|
}
|
||||||
|
cmd.Stdin = c.Stdin
|
||||||
|
cmd.Stdout = c.Stdout
|
||||||
|
cmd.Stderr = c.Stderr
|
||||||
|
if c.Env != nil {
|
||||||
|
cmd.Env = c.Env
|
||||||
|
}
|
||||||
|
return cmd.Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckLinkArgs validates linking arguments by attempting a test compile.
|
||||||
|
func (c *Cmd) CheckLinkArgs(cmdArgs []string, wasm bool) error {
|
||||||
|
// Create a temporary file with appropriate extension
|
||||||
|
extension := ""
|
||||||
|
if wasm {
|
||||||
|
extension = ".wasm"
|
||||||
|
} else if runtime.GOOS == "windows" {
|
||||||
|
extension = ".exe"
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpFile, err := os.CreateTemp("", "llgo_check*"+extension)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create temporary file: %w", err)
|
||||||
|
}
|
||||||
|
tmpFile.Close()
|
||||||
|
tmpPath := tmpFile.Name()
|
||||||
|
|
||||||
|
// Make sure to delete the temporary file when done
|
||||||
|
defer os.Remove(tmpPath)
|
||||||
|
|
||||||
|
// Set up compilation arguments
|
||||||
|
args := append([]string{}, cmdArgs...)
|
||||||
|
args = append(args, []string{"-x", "c", "-o", tmpPath, "-"}...)
|
||||||
|
src := "int main() {return 0;}"
|
||||||
|
srcIn := strings.NewReader(src)
|
||||||
|
c.Stdin = srcIn
|
||||||
|
|
||||||
|
// Execute the command with linker flags
|
||||||
|
return c.Link(args...)
|
||||||
|
}
|
||||||
513
internal/clang/clang_test.go
Normal file
513
internal/clang/clang_test.go
Normal file
@@ -0,0 +1,513 @@
|
|||||||
|
//go:build !llgo
|
||||||
|
// +build !llgo
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package clang
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"os"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestConfig(t *testing.T) {
|
||||||
|
t.Run("NewConfig", func(t *testing.T) {
|
||||||
|
ccflags := []string{"-O2", "-g"}
|
||||||
|
cflags := []string{"-std=c99"}
|
||||||
|
ldflags := []string{"-lm"}
|
||||||
|
|
||||||
|
config := NewConfig("clang++", ccflags, cflags, ldflags, "ld.lld")
|
||||||
|
|
||||||
|
if config.CC != "clang++" {
|
||||||
|
t.Errorf("Expected CC to be 'clang++', got %q", config.CC)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(config.CCFLAGS, ccflags) {
|
||||||
|
t.Errorf("Expected CCFLAGS %v, got %v", ccflags, config.CCFLAGS)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(config.CFLAGS, cflags) {
|
||||||
|
t.Errorf("Expected CFLAGS %v, got %v", cflags, config.CFLAGS)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(config.LDFLAGS, ldflags) {
|
||||||
|
t.Errorf("Expected LDFLAGS %v, got %v", ldflags, config.LDFLAGS)
|
||||||
|
}
|
||||||
|
if config.Linker != "ld.lld" {
|
||||||
|
t.Errorf("Expected Linker to be 'ld.lld', got %q", config.Linker)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNew(t *testing.T) {
|
||||||
|
t.Run("WithApp", func(t *testing.T) {
|
||||||
|
config := Config{CC: "gcc"}
|
||||||
|
cmd := New("clang++", config)
|
||||||
|
|
||||||
|
if cmd.app != "clang++" {
|
||||||
|
t.Errorf("Expected app to be 'clang++', got %q", cmd.app)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(cmd.config, config) {
|
||||||
|
t.Errorf("Expected config %+v, got %+v", config, cmd.config)
|
||||||
|
}
|
||||||
|
if cmd.Stdout != os.Stdout {
|
||||||
|
t.Error("Expected Stdout to be os.Stdout")
|
||||||
|
}
|
||||||
|
if cmd.Stderr != os.Stderr {
|
||||||
|
t.Error("Expected Stderr to be os.Stderr")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("WithoutApp", func(t *testing.T) {
|
||||||
|
config := Config{}
|
||||||
|
cmd := New("", config)
|
||||||
|
|
||||||
|
if cmd.app != "clang" {
|
||||||
|
t.Errorf("Expected app to be 'clang', got %q", cmd.app)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewCompiler(t *testing.T) {
|
||||||
|
t.Run("WithCC", func(t *testing.T) {
|
||||||
|
config := Config{CC: "gcc"}
|
||||||
|
cmd := NewCompiler(config)
|
||||||
|
|
||||||
|
if cmd.app != "gcc" {
|
||||||
|
t.Errorf("Expected app to be 'gcc', got %q", cmd.app)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("WithoutCC", func(t *testing.T) {
|
||||||
|
config := Config{}
|
||||||
|
cmd := NewCompiler(config)
|
||||||
|
|
||||||
|
if cmd.app != "clang" {
|
||||||
|
t.Errorf("Expected app to be 'clang', got %q", cmd.app)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewLinker(t *testing.T) {
|
||||||
|
t.Run("WithLinker", func(t *testing.T) {
|
||||||
|
config := Config{Linker: "ld.lld"}
|
||||||
|
cmd := NewLinker(config)
|
||||||
|
|
||||||
|
if cmd.app != "ld.lld" {
|
||||||
|
t.Errorf("Expected app to be 'ld.lld', got %q", cmd.app)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("WithoutLinkerButWithCC", func(t *testing.T) {
|
||||||
|
config := Config{CC: "gcc"}
|
||||||
|
cmd := NewLinker(config)
|
||||||
|
|
||||||
|
if cmd.app != "gcc" {
|
||||||
|
t.Errorf("Expected app to be 'gcc', got %q", cmd.app)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("WithoutLinkerAndCC", func(t *testing.T) {
|
||||||
|
config := Config{}
|
||||||
|
cmd := NewLinker(config)
|
||||||
|
|
||||||
|
if cmd.app != "clang" {
|
||||||
|
t.Errorf("Expected app to be 'clang', got %q", cmd.app)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMergeCompilerFlags(t *testing.T) {
|
||||||
|
// Save original environment
|
||||||
|
origCCFlags := os.Getenv("CCFLAGS")
|
||||||
|
origCFlags := os.Getenv("CFLAGS")
|
||||||
|
defer func() {
|
||||||
|
os.Setenv("CCFLAGS", origCCFlags)
|
||||||
|
os.Setenv("CFLAGS", origCFlags)
|
||||||
|
}()
|
||||||
|
|
||||||
|
t.Run("WithEnvironmentAndConfig", func(t *testing.T) {
|
||||||
|
os.Setenv("CCFLAGS", "-O2 -g")
|
||||||
|
os.Setenv("CFLAGS", "-std=c99")
|
||||||
|
|
||||||
|
config := Config{
|
||||||
|
CCFLAGS: []string{"-Wall"},
|
||||||
|
CFLAGS: []string{"-pedantic"},
|
||||||
|
}
|
||||||
|
cmd := New("clang", config)
|
||||||
|
|
||||||
|
flags := cmd.mergeCompilerFlags()
|
||||||
|
expected := []string{"-O2", "-g", "-std=c99", "-Wall", "-pedantic"}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(flags, expected) {
|
||||||
|
t.Errorf("Expected flags %v, got %v", expected, flags)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("WithOnlyConfig", func(t *testing.T) {
|
||||||
|
os.Unsetenv("CCFLAGS")
|
||||||
|
os.Unsetenv("CFLAGS")
|
||||||
|
|
||||||
|
config := Config{
|
||||||
|
CCFLAGS: []string{"-Wall"},
|
||||||
|
CFLAGS: []string{"-pedantic"},
|
||||||
|
}
|
||||||
|
cmd := New("clang", config)
|
||||||
|
|
||||||
|
flags := cmd.mergeCompilerFlags()
|
||||||
|
expected := []string{"-Wall", "-pedantic"}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(flags, expected) {
|
||||||
|
t.Errorf("Expected flags %v, got %v", expected, flags)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("WithOnlyEnvironment", func(t *testing.T) {
|
||||||
|
os.Setenv("CCFLAGS", "-O3")
|
||||||
|
os.Setenv("CFLAGS", "-fPIC")
|
||||||
|
|
||||||
|
config := Config{}
|
||||||
|
cmd := New("clang", config)
|
||||||
|
|
||||||
|
flags := cmd.mergeCompilerFlags()
|
||||||
|
expected := []string{"-O3", "-fPIC"}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(flags, expected) {
|
||||||
|
t.Errorf("Expected flags %v, got %v", expected, flags)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Empty", func(t *testing.T) {
|
||||||
|
os.Unsetenv("CCFLAGS")
|
||||||
|
os.Unsetenv("CFLAGS")
|
||||||
|
|
||||||
|
config := Config{}
|
||||||
|
cmd := New("clang", config)
|
||||||
|
|
||||||
|
flags := cmd.mergeCompilerFlags()
|
||||||
|
|
||||||
|
if len(flags) != 0 {
|
||||||
|
t.Errorf("Expected empty flags, got %v", flags)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMergeLinkerFlags(t *testing.T) {
|
||||||
|
// Save original environment
|
||||||
|
origCCFlags := os.Getenv("CCFLAGS")
|
||||||
|
origLDFlags := os.Getenv("LDFLAGS")
|
||||||
|
defer func() {
|
||||||
|
os.Setenv("CCFLAGS", origCCFlags)
|
||||||
|
os.Setenv("LDFLAGS", origLDFlags)
|
||||||
|
}()
|
||||||
|
|
||||||
|
t.Run("WithEnvironmentAndConfig", func(t *testing.T) {
|
||||||
|
os.Setenv("CCFLAGS", "-O2")
|
||||||
|
os.Setenv("LDFLAGS", "-lm -lpthread")
|
||||||
|
|
||||||
|
config := Config{
|
||||||
|
LDFLAGS: []string{"-static"},
|
||||||
|
}
|
||||||
|
cmd := New("clang", config)
|
||||||
|
|
||||||
|
flags := cmd.mergeLinkerFlags()
|
||||||
|
expected := []string{"-O2", "-lm", "-lpthread", "-static"}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(flags, expected) {
|
||||||
|
t.Errorf("Expected flags %v, got %v", expected, flags)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("WithOnlyConfig", func(t *testing.T) {
|
||||||
|
os.Unsetenv("CCFLAGS")
|
||||||
|
os.Unsetenv("LDFLAGS")
|
||||||
|
|
||||||
|
config := Config{
|
||||||
|
LDFLAGS: []string{"-static", "-lm"},
|
||||||
|
}
|
||||||
|
cmd := New("clang", config)
|
||||||
|
|
||||||
|
flags := cmd.mergeLinkerFlags()
|
||||||
|
expected := []string{"-static", "-lm"}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(flags, expected) {
|
||||||
|
t.Errorf("Expected flags %v, got %v", expected, flags)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCompile(t *testing.T) {
|
||||||
|
// This test uses echo instead of clang to avoid dependency on clang installation
|
||||||
|
config := Config{
|
||||||
|
CCFLAGS: []string{"-Wall"},
|
||||||
|
CFLAGS: []string{"-std=c99"},
|
||||||
|
}
|
||||||
|
cmd := New("echo", config)
|
||||||
|
|
||||||
|
var stdout bytes.Buffer
|
||||||
|
cmd.Stdout = &stdout
|
||||||
|
|
||||||
|
err := cmd.Compile("-c", "test.c")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Compile failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
output := strings.TrimSpace(stdout.String())
|
||||||
|
expectedArgs := "-Wall -std=c99 -c test.c"
|
||||||
|
if output != expectedArgs {
|
||||||
|
t.Errorf("Expected output %q, got %q", expectedArgs, output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLink(t *testing.T) {
|
||||||
|
// This test uses echo instead of clang to avoid dependency on clang installation
|
||||||
|
config := Config{
|
||||||
|
LDFLAGS: []string{"-lm"},
|
||||||
|
}
|
||||||
|
cmd := New("echo", config)
|
||||||
|
|
||||||
|
var stdout bytes.Buffer
|
||||||
|
cmd.Stdout = &stdout
|
||||||
|
|
||||||
|
err := cmd.Link("test.o", "-o", "test")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Link failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
output := strings.TrimSpace(stdout.String())
|
||||||
|
expectedArgs := "-lm test.o -o test"
|
||||||
|
if output != expectedArgs {
|
||||||
|
t.Errorf("Expected output %q, got %q", expectedArgs, output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVerboseMode(t *testing.T) {
|
||||||
|
config := Config{}
|
||||||
|
cmd := New("echo", config)
|
||||||
|
cmd.Verbose = true
|
||||||
|
|
||||||
|
// Since verbose output goes to os.Stderr directly, we'll test
|
||||||
|
// that verbose flag is set and command executes successfully
|
||||||
|
var stderr bytes.Buffer
|
||||||
|
cmd.Stderr = &stderr
|
||||||
|
cmd.Stdout = &bytes.Buffer{} // Suppress stdout
|
||||||
|
|
||||||
|
err := cmd.Compile("-c", "test.c")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Compile failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The test passes if verbose is set and no error occurred
|
||||||
|
if !cmd.Verbose {
|
||||||
|
t.Error("Expected Verbose to be true")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCmdEnvironment(t *testing.T) {
|
||||||
|
config := Config{}
|
||||||
|
cmd := New("echo", config)
|
||||||
|
cmd.Env = []string{"TEST_VAR=test_value"}
|
||||||
|
|
||||||
|
var stdout bytes.Buffer
|
||||||
|
cmd.Stdout = &stdout
|
||||||
|
|
||||||
|
// Use a command that will show environment variables
|
||||||
|
// Note: This is a simplified test that just ensures the Env field is set
|
||||||
|
err := cmd.Compile("-c", "test.c")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Compile failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(cmd.Env) != 1 || cmd.Env[0] != "TEST_VAR=test_value" {
|
||||||
|
t.Errorf("Expected environment to be set correctly")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCmdIO(t *testing.T) {
|
||||||
|
config := Config{}
|
||||||
|
cmd := New("cat", config) // Use cat to test stdin/stdout
|
||||||
|
|
||||||
|
input := "test input"
|
||||||
|
cmd.Stdin = strings.NewReader(input)
|
||||||
|
|
||||||
|
var stdout bytes.Buffer
|
||||||
|
cmd.Stdout = &stdout
|
||||||
|
|
||||||
|
// cat will read from stdin and write to stdout
|
||||||
|
err := cmd.exec() // Call exec directly with no args
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("exec failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
output := stdout.String()
|
||||||
|
if output != input {
|
||||||
|
t.Errorf("Expected output %q, got %q", input, output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCheckLinkArgs(t *testing.T) {
|
||||||
|
t.Run("BasicTest", func(t *testing.T) {
|
||||||
|
// Use echo instead of clang to avoid dependency
|
||||||
|
config := Config{}
|
||||||
|
cmd := New("echo", config)
|
||||||
|
|
||||||
|
// Redirect output to avoid clutter
|
||||||
|
cmd.Stdout = &bytes.Buffer{}
|
||||||
|
cmd.Stderr = &bytes.Buffer{}
|
||||||
|
|
||||||
|
// This should succeed with echo
|
||||||
|
err := cmd.CheckLinkArgs([]string{"-o"}, false)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("CheckLinkArgs failed: %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("WasmExtension", func(t *testing.T) {
|
||||||
|
config := Config{}
|
||||||
|
cmd := New("echo", config)
|
||||||
|
|
||||||
|
cmd.Stdout = &bytes.Buffer{}
|
||||||
|
cmd.Stderr = &bytes.Buffer{}
|
||||||
|
|
||||||
|
// Test with wasm=true
|
||||||
|
err := cmd.CheckLinkArgs([]string{"-o"}, true)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("CheckLinkArgs with wasm failed: %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Additional table-driven test for flag merging scenarios
|
||||||
|
func TestFlagMergingScenarios(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
envCCFlags string
|
||||||
|
envCFlags string
|
||||||
|
envLDFlags string
|
||||||
|
config Config
|
||||||
|
expectComp []string
|
||||||
|
expectLink []string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "empty everything",
|
||||||
|
envCCFlags: "",
|
||||||
|
envCFlags: "",
|
||||||
|
envLDFlags: "",
|
||||||
|
config: Config{},
|
||||||
|
expectComp: []string{},
|
||||||
|
expectLink: []string{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "only environment flags",
|
||||||
|
envCCFlags: "-O2",
|
||||||
|
envCFlags: "-std=c99",
|
||||||
|
envLDFlags: "-lm",
|
||||||
|
config: Config{},
|
||||||
|
expectComp: []string{"-O2", "-std=c99"},
|
||||||
|
expectLink: []string{"-O2", "-lm"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "only config flags",
|
||||||
|
envCCFlags: "",
|
||||||
|
envCFlags: "",
|
||||||
|
envLDFlags: "",
|
||||||
|
config: Config{
|
||||||
|
CCFLAGS: []string{"-Wall"},
|
||||||
|
CFLAGS: []string{"-pedantic"},
|
||||||
|
LDFLAGS: []string{"-static"},
|
||||||
|
},
|
||||||
|
expectComp: []string{"-Wall", "-pedantic"},
|
||||||
|
expectLink: []string{"-static"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "mixed environment and config",
|
||||||
|
envCCFlags: "-O3",
|
||||||
|
envCFlags: "-fPIC",
|
||||||
|
envLDFlags: "-lm -lpthread",
|
||||||
|
config: Config{
|
||||||
|
CCFLAGS: []string{"-Wall", "-Wextra"},
|
||||||
|
CFLAGS: []string{"-std=c11"},
|
||||||
|
LDFLAGS: []string{"-static"},
|
||||||
|
},
|
||||||
|
expectComp: []string{"-O3", "-fPIC", "-Wall", "-Wextra", "-std=c11"},
|
||||||
|
expectLink: []string{"-O3", "-lm", "-lpthread", "-static"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save original environment
|
||||||
|
origCCFlags := os.Getenv("CCFLAGS")
|
||||||
|
origCFlags := os.Getenv("CFLAGS")
|
||||||
|
origLDFlags := os.Getenv("LDFLAGS")
|
||||||
|
defer func() {
|
||||||
|
os.Setenv("CCFLAGS", origCCFlags)
|
||||||
|
os.Setenv("CFLAGS", origCFlags)
|
||||||
|
os.Setenv("LDFLAGS", origLDFlags)
|
||||||
|
}()
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
// Set environment variables
|
||||||
|
os.Setenv("CCFLAGS", tt.envCCFlags)
|
||||||
|
os.Setenv("CFLAGS", tt.envCFlags)
|
||||||
|
os.Setenv("LDFLAGS", tt.envLDFlags)
|
||||||
|
|
||||||
|
cmd := New("clang", tt.config)
|
||||||
|
|
||||||
|
// Test compiler flags
|
||||||
|
compFlags := cmd.mergeCompilerFlags()
|
||||||
|
if len(tt.expectComp) == 0 && len(compFlags) == 0 {
|
||||||
|
// Both are empty, consider them equal
|
||||||
|
} else if !reflect.DeepEqual(compFlags, tt.expectComp) {
|
||||||
|
t.Errorf("mergeCompilerFlags() = %v, want %v", compFlags, tt.expectComp)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test linker flags
|
||||||
|
linkFlags := cmd.mergeLinkerFlags()
|
||||||
|
if len(tt.expectLink) == 0 && len(linkFlags) == 0 {
|
||||||
|
// Both are empty, consider them equal
|
||||||
|
} else if !reflect.DeepEqual(linkFlags, tt.expectLink) {
|
||||||
|
t.Errorf("mergeLinkerFlags() = %v, want %v", linkFlags, tt.expectLink)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Benchmark tests
|
||||||
|
func BenchmarkMergeCompilerFlags(b *testing.B) {
|
||||||
|
config := Config{
|
||||||
|
CCFLAGS: []string{"-Wall", "-O2"},
|
||||||
|
CFLAGS: []string{"-std=c99", "-pedantic"},
|
||||||
|
}
|
||||||
|
cmd := New("clang", config)
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
_ = cmd.mergeCompilerFlags()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkMergeLinkerFlags(b *testing.B) {
|
||||||
|
config := Config{
|
||||||
|
LDFLAGS: []string{"-lm", "-lpthread", "-static"},
|
||||||
|
}
|
||||||
|
cmd := New("clang", config)
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
_ = cmd.mergeLinkerFlags()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -15,40 +16,261 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Export struct {
|
type Export struct {
|
||||||
CC string // Compiler to use
|
CC string // Compiler to use
|
||||||
CCFLAGS []string
|
CCFLAGS []string
|
||||||
CFLAGS []string
|
CFLAGS []string
|
||||||
LDFLAGS []string
|
LDFLAGS []string
|
||||||
EXTRAFLAGS []string
|
|
||||||
|
|
||||||
// Additional fields from target configuration
|
// Additional fields from target configuration
|
||||||
LLVMTarget string
|
BuildTags []string
|
||||||
CPU string
|
GOOS string
|
||||||
Features string
|
GOARCH string
|
||||||
BuildTags []string
|
Linker string // Linker to use (e.g., "ld.lld", "avr-ld")
|
||||||
GOOS string
|
ExtraFiles []string // Extra files to compile and link (e.g., .s, .c files)
|
||||||
GOARCH string
|
ClangRoot string // Root directory of custom clang installation
|
||||||
Linker string // Linker to use (e.g., "ld.lld", "avr-ld")
|
ClangBinPath string // Path to clang binary directory
|
||||||
|
|
||||||
|
BinaryFormat string // Binary format (e.g., "elf", "esp", "uf2")
|
||||||
|
FormatDetail string // For uf2, it's uf2FamilyID
|
||||||
}
|
}
|
||||||
|
|
||||||
const wasiSdkUrl = "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-25/wasi-sdk-25.0-x86_64-macos.tar.gz"
|
// URLs and configuration that can be overridden for testing
|
||||||
|
var (
|
||||||
|
wasiSdkUrl = "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-25/wasi-sdk-25.0-x86_64-macos.tar.gz"
|
||||||
|
wasiMacosSubdir = "wasi-sdk-25.0-x86_64-macos"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
espClangBaseUrl = "https://github.com/goplus/espressif-llvm-project-prebuilt/releases/download/19.1.2_20250820"
|
||||||
|
espClangVersion = "19.1.2_20250820"
|
||||||
|
)
|
||||||
|
|
||||||
|
// cacheRoot can be overridden for testing
|
||||||
|
var cacheRoot = env.LLGoCacheDir
|
||||||
|
|
||||||
func cacheDir() string {
|
func cacheDir() string {
|
||||||
return filepath.Join(env.LLGoCacheDir(), "crosscompile")
|
return filepath.Join(cacheRoot(), "crosscompile")
|
||||||
}
|
}
|
||||||
|
|
||||||
func Use(goos, goarch string, wasiThreads bool) (export Export, err error) {
|
// expandEnv expands template variables in a string
|
||||||
|
// Supports variables like {port}, {hex}, {bin}, {root}, {tmpDir}, etc.
|
||||||
|
// Special case: {} expands to the first available file variable (hex, bin, img, zip)
|
||||||
|
func expandEnv(template string, envs map[string]string) string {
|
||||||
|
return expandEnvWithDefault(template, envs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// expandEnvWithDefault expands template variables with optional default for {}
|
||||||
|
func expandEnvWithDefault(template string, envs map[string]string, defaultValue ...string) string {
|
||||||
|
if template == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
result := template
|
||||||
|
|
||||||
|
// Handle special case of {} - use provided default or first available file variable
|
||||||
|
if strings.Contains(result, "{}") {
|
||||||
|
defaultVal := ""
|
||||||
|
if len(defaultValue) > 0 && defaultValue[0] != "" {
|
||||||
|
defaultVal = defaultValue[0]
|
||||||
|
} else {
|
||||||
|
// Priority order: hex, bin, img, zip
|
||||||
|
for _, key := range []string{"hex", "bin", "img", "zip"} {
|
||||||
|
if value, exists := envs[key]; exists && value != "" {
|
||||||
|
defaultVal = value
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = strings.ReplaceAll(result, "{}", defaultVal)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace named variables
|
||||||
|
for key, value := range envs {
|
||||||
|
if key != "" { // Skip empty key used for {} default
|
||||||
|
result = strings.ReplaceAll(result, "{"+key+"}", value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// expandEnvSlice expands template variables in a slice of strings
|
||||||
|
func expandEnvSlice(templates []string, envs map[string]string) []string {
|
||||||
|
return expandEnvSliceWithDefault(templates, envs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// expandEnvSliceWithDefault expands template variables in a slice with optional default for {}
|
||||||
|
func expandEnvSliceWithDefault(templates []string, envs map[string]string, defaultValue ...string) []string {
|
||||||
|
if len(templates) == 0 {
|
||||||
|
return templates
|
||||||
|
}
|
||||||
|
|
||||||
|
result := make([]string, len(templates))
|
||||||
|
for i, template := range templates {
|
||||||
|
result[i] = expandEnvWithDefault(template, envs, defaultValue...)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// buildEnvMap creates a map of template variables for the current context
|
||||||
|
func buildEnvMap(llgoRoot string) map[string]string {
|
||||||
|
envs := make(map[string]string)
|
||||||
|
|
||||||
|
// Basic paths
|
||||||
|
envs["root"] = llgoRoot
|
||||||
|
envs["tmpDir"] = os.TempDir()
|
||||||
|
|
||||||
|
// These will typically be set by calling code when actual values are known
|
||||||
|
// envs["port"] = "" // Serial port (e.g., "/dev/ttyUSB0", "COM3")
|
||||||
|
// envs["hex"] = "" // Path to hex file
|
||||||
|
// envs["bin"] = "" // Path to binary file
|
||||||
|
// envs["img"] = "" // Path to image file
|
||||||
|
// envs["zip"] = "" // Path to zip file
|
||||||
|
|
||||||
|
return envs
|
||||||
|
}
|
||||||
|
|
||||||
|
// getCanonicalArchName returns the canonical architecture name for a target triple
|
||||||
|
func getCanonicalArchName(triple string) string {
|
||||||
|
arch := strings.Split(triple, "-")[0]
|
||||||
|
if arch == "arm64" {
|
||||||
|
return "aarch64"
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(arch, "arm") || strings.HasPrefix(arch, "thumb") {
|
||||||
|
return "arm"
|
||||||
|
}
|
||||||
|
if arch == "mipsel" {
|
||||||
|
return "mips"
|
||||||
|
}
|
||||||
|
return arch
|
||||||
|
}
|
||||||
|
|
||||||
|
// getMacOSSysroot returns the macOS SDK path using xcrun
|
||||||
|
func getMacOSSysroot() (string, error) {
|
||||||
|
cmd := exec.Command("xcrun", "--sdk", "macosx", "--show-sdk-path")
|
||||||
|
output, err := cmd.Output()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return strings.TrimSpace(string(output)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getESPClangRoot returns the ESP Clang root directory, checking LLGoROOT first,
|
||||||
|
// then downloading if needed and platform is supported
|
||||||
|
func getESPClangRoot() (clangRoot string, err error) {
|
||||||
|
llgoRoot := env.LLGoROOT()
|
||||||
|
|
||||||
|
// First check if clang exists in LLGoROOT
|
||||||
|
espClangRoot := filepath.Join(llgoRoot, "crosscompile", "clang")
|
||||||
|
if _, err = os.Stat(espClangRoot); err == nil {
|
||||||
|
clangRoot = espClangRoot
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to download ESP Clang if platform is supported
|
||||||
|
platformSuffix := getESPClangPlatform(runtime.GOOS, runtime.GOARCH)
|
||||||
|
if platformSuffix != "" {
|
||||||
|
cacheClangDir := filepath.Join(cacheRoot(), "crosscompile", "esp-clang-"+espClangVersion)
|
||||||
|
if _, err = os.Stat(cacheClangDir); err != nil {
|
||||||
|
if !errors.Is(err, fs.ErrNotExist) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Fprintln(os.Stderr, "ESP Clang not found in LLGO_ROOT or cache, will download.")
|
||||||
|
if err = checkDownloadAndExtractESPClang(platformSuffix, cacheClangDir); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clangRoot = cacheClangDir
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = fmt.Errorf("ESP Clang not found in LLGoROOT and platform %s/%s is not supported for download", runtime.GOOS, runtime.GOARCH)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// getESPClangPlatform returns the platform suffix for ESP Clang downloads
|
||||||
|
func getESPClangPlatform(goos, goarch string) string {
|
||||||
|
switch goos {
|
||||||
|
case "darwin":
|
||||||
|
switch goarch {
|
||||||
|
case "amd64":
|
||||||
|
return "x86_64-apple-darwin"
|
||||||
|
case "arm64":
|
||||||
|
return "aarch64-apple-darwin"
|
||||||
|
}
|
||||||
|
case "linux":
|
||||||
|
switch goarch {
|
||||||
|
case "amd64":
|
||||||
|
return "x86_64-linux-gnu"
|
||||||
|
case "arm64":
|
||||||
|
return "aarch64-linux-gnu"
|
||||||
|
case "arm":
|
||||||
|
return "arm-linux-gnueabihf"
|
||||||
|
}
|
||||||
|
case "windows":
|
||||||
|
switch goarch {
|
||||||
|
case "amd64":
|
||||||
|
return "x86_64-w64-mingw32"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func use(goos, goarch string, wasiThreads bool) (export Export, err error) {
|
||||||
targetTriple := llvm.GetTargetTriple(goos, goarch)
|
targetTriple := llvm.GetTargetTriple(goos, goarch)
|
||||||
|
llgoRoot := env.LLGoROOT()
|
||||||
|
|
||||||
|
// Check for ESP Clang support for target-based builds
|
||||||
|
clangRoot, err := getESPClangRoot()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set ClangRoot and CC if clang is available
|
||||||
|
export.ClangRoot = clangRoot
|
||||||
|
export.CC = filepath.Join(clangRoot, "bin", "clang++")
|
||||||
|
|
||||||
if runtime.GOOS == goos && runtime.GOARCH == goarch {
|
if runtime.GOOS == goos && runtime.GOARCH == goarch {
|
||||||
|
clangLib := filepath.Join(clangRoot, "lib")
|
||||||
|
clangInc := filepath.Join(clangRoot, "include")
|
||||||
// not cross compile
|
// not cross compile
|
||||||
// Set up basic flags for non-cross-compile
|
// Set up basic flags for non-cross-compile
|
||||||
export.LDFLAGS = []string{
|
export.LDFLAGS = []string{
|
||||||
|
"-L" + clangLib,
|
||||||
"-target", targetTriple,
|
"-target", targetTriple,
|
||||||
"-Wno-override-module",
|
"-Qunused-arguments",
|
||||||
|
"-Wno-unused-command-line-argument",
|
||||||
"-Wl,--error-limit=0",
|
"-Wl,--error-limit=0",
|
||||||
"-fuse-ld=lld",
|
"-fuse-ld=lld",
|
||||||
}
|
}
|
||||||
|
export.CFLAGS = append(export.CFLAGS, "-I"+clangInc)
|
||||||
|
export.CCFLAGS = []string{
|
||||||
|
"-Qunused-arguments",
|
||||||
|
"-Wno-unused-command-line-argument",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add platform-specific rpath flags
|
||||||
|
switch goos {
|
||||||
|
case "darwin":
|
||||||
|
export.LDFLAGS = append(export.LDFLAGS, "-Wl,-rpath,"+clangLib)
|
||||||
|
case "linux":
|
||||||
|
export.LDFLAGS = append(export.LDFLAGS, "-Wl,-rpath,"+clangLib)
|
||||||
|
case "windows":
|
||||||
|
// Windows doesn't support rpath, DLLs should be in PATH or same directory
|
||||||
|
default:
|
||||||
|
// For other Unix-like systems, try the generic rpath
|
||||||
|
export.LDFLAGS = append(export.LDFLAGS, "-Wl,-rpath,"+clangLib)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add sysroot for macOS only
|
||||||
|
if goos == "darwin" {
|
||||||
|
sysrootPath, sysrootErr := getMacOSSysroot()
|
||||||
|
if sysrootErr != nil {
|
||||||
|
err = fmt.Errorf("failed to get macOS SDK path: %w", sysrootErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
export.CCFLAGS = append(export.CCFLAGS, []string{"--sysroot=" + sysrootPath}...)
|
||||||
|
export.LDFLAGS = append(export.LDFLAGS, []string{"--sysroot=" + sysrootPath}...)
|
||||||
|
}
|
||||||
|
|
||||||
// Add OS-specific flags
|
// Add OS-specific flags
|
||||||
switch goos {
|
switch goos {
|
||||||
@@ -85,13 +307,13 @@ func Use(goos, goarch string, wasiThreads bool) (export Export, err error) {
|
|||||||
// Configure based on GOOS
|
// Configure based on GOOS
|
||||||
switch goos {
|
switch goos {
|
||||||
case "wasip1":
|
case "wasip1":
|
||||||
sdkDir := filepath.Join(cacheDir(), llvm.GetTargetTriple(goos, goarch))
|
// Set wasiSdkRoot path
|
||||||
if _, err = os.Stat(sdkDir); err != nil {
|
wasiSdkRoot := filepath.Join(llgoRoot, "crosscompile", "wasi-libc")
|
||||||
if !errors.Is(err, fs.ErrNotExist) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = downloadAndExtract(wasiSdkUrl, sdkDir); err != nil {
|
// If not exists in LLGoROOT, download and use cached wasiSdkRoot
|
||||||
|
if _, err = os.Stat(wasiSdkRoot); err != nil {
|
||||||
|
sdkDir := filepath.Join(cacheDir(), llvm.GetTargetTriple(goos, goarch))
|
||||||
|
if wasiSdkRoot, err = checkDownloadAndExtractWasiSDK(sdkDir); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -101,8 +323,7 @@ func Use(goos, goarch string, wasiThreads bool) (export Export, err error) {
|
|||||||
triple = "wasm32-wasip1-threads"
|
triple = "wasm32-wasip1-threads"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up flags for the WASI-SDK
|
// Set up flags for the WASI-SDK or wasi-libc
|
||||||
wasiSdkRoot := filepath.Join(sdkDir, "wasi-sdk-25.0-x86_64-macos")
|
|
||||||
sysrootDir := filepath.Join(wasiSdkRoot, "share", "wasi-sysroot")
|
sysrootDir := filepath.Join(wasiSdkRoot, "share", "wasi-sysroot")
|
||||||
libclangDir := filepath.Join(wasiSdkRoot, "lib", "clang", "19")
|
libclangDir := filepath.Join(wasiSdkRoot, "lib", "clang", "19")
|
||||||
includeDir := filepath.Join(sysrootDir, "include", triple)
|
includeDir := filepath.Join(sysrootDir, "include", triple)
|
||||||
@@ -119,6 +340,8 @@ func Use(goos, goarch string, wasiThreads bool) (export Export, err error) {
|
|||||||
}
|
}
|
||||||
export.CFLAGS = []string{
|
export.CFLAGS = []string{
|
||||||
"-I" + includeDir,
|
"-I" + includeDir,
|
||||||
|
"-Qunused-arguments",
|
||||||
|
"-Wno-unused-command-line-argument",
|
||||||
}
|
}
|
||||||
// Add WebAssembly linker flags
|
// Add WebAssembly linker flags
|
||||||
export.LDFLAGS = append(export.LDFLAGS, export.CCFLAGS...)
|
export.LDFLAGS = append(export.LDFLAGS, export.CCFLAGS...)
|
||||||
@@ -169,6 +392,8 @@ func Use(goos, goarch string, wasiThreads bool) (export Export, err error) {
|
|||||||
// Add compiler flags
|
// Add compiler flags
|
||||||
export.CCFLAGS = []string{
|
export.CCFLAGS = []string{
|
||||||
"-target", targetTriple,
|
"-target", targetTriple,
|
||||||
|
"-Qunused-arguments",
|
||||||
|
"-Wno-unused-command-line-argument",
|
||||||
}
|
}
|
||||||
export.CFLAGS = []string{}
|
export.CFLAGS = []string{}
|
||||||
// Add WebAssembly linker flags for Emscripten
|
// Add WebAssembly linker flags for Emscripten
|
||||||
@@ -186,7 +411,7 @@ func Use(goos, goarch string, wasiThreads bool) (export Export, err error) {
|
|||||||
// "-z", "stack-size=10485760", // 10MB
|
// "-z", "stack-size=10485760", // 10MB
|
||||||
// "-Wl,--export=malloc", "-Wl,--export=free",
|
// "-Wl,--export=malloc", "-Wl,--export=free",
|
||||||
}
|
}
|
||||||
export.EXTRAFLAGS = []string{
|
export.LDFLAGS = append(export.LDFLAGS, []string{
|
||||||
"-sENVIRONMENT=web,worker",
|
"-sENVIRONMENT=web,worker",
|
||||||
"-DPLATFORM_WEB",
|
"-DPLATFORM_WEB",
|
||||||
"-sEXPORT_KEEPALIVE=1",
|
"-sEXPORT_KEEPALIVE=1",
|
||||||
@@ -198,7 +423,7 @@ func Use(goos, goarch string, wasiThreads bool) (export Export, err error) {
|
|||||||
"-sEXPORT_ALL=1",
|
"-sEXPORT_ALL=1",
|
||||||
"-sASYNCIFY=1",
|
"-sASYNCIFY=1",
|
||||||
"-sSTACK_SIZE=5242880", // 50MB
|
"-sSTACK_SIZE=5242880", // 50MB
|
||||||
}
|
}...)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
err = errors.New("unsupported GOOS for WebAssembly: " + goos)
|
err = errors.New("unsupported GOOS for WebAssembly: " + goos)
|
||||||
@@ -216,25 +441,55 @@ func useTarget(targetName string) (export Export, err error) {
|
|||||||
return export, fmt.Errorf("failed to resolve target %s: %w", targetName, err)
|
return export, fmt.Errorf("failed to resolve target %s: %w", targetName, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
target := config.LLVMTarget
|
||||||
|
if target == "" {
|
||||||
|
return export, fmt.Errorf("target '%s' does not have a valid LLVM target triple", targetName)
|
||||||
|
}
|
||||||
|
|
||||||
|
cpu := config.CPU
|
||||||
|
if cpu == "" {
|
||||||
|
return export, fmt.Errorf("target '%s' does not have a valid CPU configuration", targetName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for ESP Clang support for target-based builds
|
||||||
|
clangRoot, err := getESPClangRoot()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set ClangRoot and CC if clang is available
|
||||||
|
export.ClangRoot = clangRoot
|
||||||
|
export.CC = filepath.Join(clangRoot, "bin", "clang++")
|
||||||
|
|
||||||
// Convert target config to Export - only export necessary fields
|
// Convert target config to Export - only export necessary fields
|
||||||
export.BuildTags = config.BuildTags
|
export.BuildTags = config.BuildTags
|
||||||
export.GOOS = config.GOOS
|
export.GOOS = config.GOOS
|
||||||
export.GOARCH = config.GOARCH
|
export.GOARCH = config.GOARCH
|
||||||
|
export.ExtraFiles = config.ExtraFiles
|
||||||
|
export.BinaryFormat = config.BinaryFormat
|
||||||
|
export.FormatDetail = config.FormatDetail()
|
||||||
|
|
||||||
|
// Build environment map for template variable expansion
|
||||||
|
envs := buildEnvMap(env.LLGoROOT())
|
||||||
|
|
||||||
// Convert LLVMTarget, CPU, Features to CCFLAGS/LDFLAGS
|
// Convert LLVMTarget, CPU, Features to CCFLAGS/LDFLAGS
|
||||||
var ccflags []string
|
var ccflags []string
|
||||||
var ldflags []string
|
var ldflags []string
|
||||||
|
|
||||||
target := config.LLVMTarget
|
cflags := []string{"-Wno-override-module", "-Qunused-arguments", "-Wno-unused-command-line-argument"}
|
||||||
if target == "" {
|
if config.LLVMTarget != "" {
|
||||||
target = llvm.GetTargetTriple(config.GOOS, config.GOARCH)
|
cflags = append(cflags, "--target="+config.LLVMTarget)
|
||||||
|
ccflags = append(ccflags, "--target="+config.LLVMTarget)
|
||||||
}
|
}
|
||||||
|
// Expand template variables in cflags
|
||||||
|
expandedCFlags := expandEnvSlice(config.CFlags, envs)
|
||||||
|
cflags = append(cflags, expandedCFlags...)
|
||||||
|
|
||||||
ccflags = append(ccflags, "-Wno-override-module", "--target="+config.LLVMTarget)
|
// The following parameters are inspired by tinygo/builder/library.go
|
||||||
|
// Handle CPU configuration
|
||||||
// Inspired by tinygo
|
|
||||||
cpu := config.CPU
|
|
||||||
if cpu != "" {
|
if cpu != "" {
|
||||||
|
// X86 has deprecated the -mcpu flag, so we need to use -march instead.
|
||||||
|
// However, ARM has not done this.
|
||||||
if strings.HasPrefix(target, "i386") || strings.HasPrefix(target, "x86_64") {
|
if strings.HasPrefix(target, "i386") || strings.HasPrefix(target, "x86_64") {
|
||||||
ccflags = append(ccflags, "-march="+cpu)
|
ccflags = append(ccflags, "-march="+cpu)
|
||||||
} else if strings.HasPrefix(target, "avr") {
|
} else if strings.HasPrefix(target, "avr") {
|
||||||
@@ -242,12 +497,50 @@ func useTarget(targetName string) (export Export, err error) {
|
|||||||
} else {
|
} else {
|
||||||
ccflags = append(ccflags, "-mcpu="+cpu)
|
ccflags = append(ccflags, "-mcpu="+cpu)
|
||||||
}
|
}
|
||||||
// Only add -mllvm flags for non-WebAssembly linkers
|
|
||||||
|
// For ld.lld linker, also add CPU info to linker flags
|
||||||
if config.Linker == "ld.lld" {
|
if config.Linker == "ld.lld" {
|
||||||
ldflags = append(ldflags, "-mllvm", "-mcpu="+cpu)
|
ldflags = append(ldflags, "-mllvm", "-mcpu="+cpu)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle architecture-specific flags
|
||||||
|
canonicalArch := getCanonicalArchName(target)
|
||||||
|
switch canonicalArch {
|
||||||
|
case "arm":
|
||||||
|
if strings.Split(target, "-")[2] == "linux" {
|
||||||
|
ccflags = append(ccflags, "-fno-unwind-tables", "-fno-asynchronous-unwind-tables")
|
||||||
|
} else {
|
||||||
|
ccflags = append(ccflags, "-fshort-enums", "-fomit-frame-pointer", "-mfloat-abi=soft", "-fno-unwind-tables", "-fno-asynchronous-unwind-tables")
|
||||||
|
}
|
||||||
|
case "avr":
|
||||||
|
// AVR defaults to C float and double both being 32-bit. This deviates
|
||||||
|
// from what most code (and certainly compiler-rt) expects. So we need
|
||||||
|
// to force the compiler to use 64-bit floating point numbers for
|
||||||
|
// double.
|
||||||
|
ccflags = append(ccflags, "-mdouble=64")
|
||||||
|
case "riscv32":
|
||||||
|
ccflags = append(ccflags, "-march=rv32imac", "-fforce-enable-int128")
|
||||||
|
case "riscv64":
|
||||||
|
ccflags = append(ccflags, "-march=rv64gc")
|
||||||
|
case "mips":
|
||||||
|
ccflags = append(ccflags, "-fno-pic")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle soft float
|
||||||
|
if strings.Contains(config.Features, "soft-float") || strings.Contains(strings.Join(config.CFlags, " "), "soft-float") {
|
||||||
|
// Use softfloat instead of floating point instructions. This is
|
||||||
|
// supported on many architectures.
|
||||||
|
ccflags = append(ccflags, "-msoft-float")
|
||||||
|
} else {
|
||||||
|
if strings.HasPrefix(target, "armv5") {
|
||||||
|
// On ARMv5 we need to explicitly enable hardware floating point
|
||||||
|
// instructions: Clang appears to assume the hardware doesn't have a
|
||||||
|
// FPU otherwise.
|
||||||
|
ccflags = append(ccflags, "-mfpu=vfpv2")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Handle Features
|
// Handle Features
|
||||||
if config.Features != "" {
|
if config.Features != "" {
|
||||||
// Only add -mllvm flags for non-WebAssembly linkers
|
// Only add -mllvm flags for non-WebAssembly linkers
|
||||||
@@ -256,64 +549,45 @@ func useTarget(targetName string) (export Export, err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle Linker - keep it for external usage
|
// Handle code generation configuration
|
||||||
export.Linker = config.Linker
|
if config.CodeModel != "" {
|
||||||
|
ccflags = append(ccflags, "-mcmodel="+config.CodeModel)
|
||||||
|
}
|
||||||
|
if config.TargetABI != "" {
|
||||||
|
ccflags = append(ccflags, "-mabi="+config.TargetABI)
|
||||||
|
}
|
||||||
|
if config.RelocationModel != "" {
|
||||||
|
switch config.RelocationModel {
|
||||||
|
case "pic":
|
||||||
|
ccflags = append(ccflags, "-fPIC")
|
||||||
|
case "static":
|
||||||
|
ccflags = append(ccflags, "-fno-pic")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Combine with config flags
|
// Handle Linker - keep it for external usage
|
||||||
export.CFLAGS = config.CFlags
|
if config.Linker != "" {
|
||||||
|
export.Linker = filepath.Join(clangRoot, "bin", config.Linker)
|
||||||
|
}
|
||||||
|
if config.LinkerScript != "" {
|
||||||
|
ldflags = append(ldflags, "-T", config.LinkerScript)
|
||||||
|
}
|
||||||
|
ldflags = append(ldflags, "-L", env.LLGoROOT()) // search targets/*.ld
|
||||||
|
|
||||||
|
// Combine with config flags and expand template variables
|
||||||
|
export.CFLAGS = cflags
|
||||||
export.CCFLAGS = ccflags
|
export.CCFLAGS = ccflags
|
||||||
export.LDFLAGS = append(ldflags, filterCompatibleLDFlags(config.LDFlags)...)
|
expandedLDFlags := expandEnvSlice(config.LDFlags, envs)
|
||||||
export.EXTRAFLAGS = []string{}
|
export.LDFLAGS = append(ldflags, expandedLDFlags...)
|
||||||
|
|
||||||
return export, nil
|
return export, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UseWithTarget extends the original Use function to support target-based configuration
|
// Use extends the original Use function to support target-based configuration
|
||||||
// If targetName is provided, it takes precedence over goos/goarch
|
// If targetName is provided, it takes precedence over goos/goarch
|
||||||
func UseWithTarget(goos, goarch string, wasiThreads bool, targetName string) (export Export, err error) {
|
func Use(goos, goarch string, wasiThreads bool, targetName string) (export Export, err error) {
|
||||||
if targetName != "" {
|
if targetName != "" {
|
||||||
return useTarget(targetName)
|
return useTarget(targetName)
|
||||||
}
|
}
|
||||||
return Use(goos, goarch, wasiThreads)
|
return use(goos, goarch, wasiThreads)
|
||||||
}
|
|
||||||
|
|
||||||
// filterCompatibleLDFlags filters out linker flags that are incompatible with clang/lld
|
|
||||||
func filterCompatibleLDFlags(ldflags []string) []string {
|
|
||||||
if len(ldflags) == 0 {
|
|
||||||
return ldflags
|
|
||||||
}
|
|
||||||
|
|
||||||
var filtered []string
|
|
||||||
|
|
||||||
incompatiblePrefixes := []string{
|
|
||||||
"--defsym=", // Use -Wl,--defsym= instead
|
|
||||||
"-T", // Linker script, needs special handling
|
|
||||||
}
|
|
||||||
|
|
||||||
i := 0
|
|
||||||
for i < len(ldflags) {
|
|
||||||
flag := ldflags[i]
|
|
||||||
|
|
||||||
// Check incompatible prefixes
|
|
||||||
skip := false
|
|
||||||
for _, prefix := range incompatiblePrefixes {
|
|
||||||
if strings.HasPrefix(flag, prefix) {
|
|
||||||
skip = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if skip {
|
|
||||||
// Skip -T and its argument if separate
|
|
||||||
if flag == "-T" && i+1 < len(ldflags) {
|
|
||||||
i += 2 // Skip both -T and the script path
|
|
||||||
} else {
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
filtered = append(filtered, flag)
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
|
|
||||||
return filtered
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,10 +37,10 @@ func TestUseCrossCompileSDK(t *testing.T) {
|
|||||||
name: "Same Platform",
|
name: "Same Platform",
|
||||||
goos: runtime.GOOS,
|
goos: runtime.GOOS,
|
||||||
goarch: runtime.GOARCH,
|
goarch: runtime.GOARCH,
|
||||||
expectSDK: false,
|
expectSDK: true, // Changed: now we expect flags even for same platform
|
||||||
expectCCFlags: false,
|
expectCCFlags: true, // Changed: CCFLAGS will contain sysroot
|
||||||
expectCFlags: false,
|
expectCFlags: true, // Changed: CFLAGS will contain include paths
|
||||||
expectLDFlags: false,
|
expectLDFlags: true, // Changed: LDFLAGS will contain library paths
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "WASM Target",
|
name: "WASM Target",
|
||||||
@@ -55,10 +55,10 @@ func TestUseCrossCompileSDK(t *testing.T) {
|
|||||||
name: "Unsupported Target",
|
name: "Unsupported Target",
|
||||||
goos: "windows",
|
goos: "windows",
|
||||||
goarch: "amd64",
|
goarch: "amd64",
|
||||||
expectSDK: false,
|
expectSDK: false, // Still false as it won't set up specific SDK
|
||||||
expectCCFlags: false,
|
expectCCFlags: false, // No cross-compile specific flags
|
||||||
expectCFlags: false,
|
expectCFlags: false, // No cross-compile specific flags
|
||||||
expectLDFlags: false,
|
expectLDFlags: false, // No cross-compile specific flags
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,7 +76,7 @@ func TestUseCrossCompileSDK(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
export, err := Use(tc.goos, tc.goarch, false)
|
export, err := use(tc.goos, tc.goarch, false)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Unexpected error: %v", err)
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
@@ -111,11 +111,20 @@ func TestUseCrossCompileSDK(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !hasSysroot {
|
// For WASM target, both sysroot and resource-dir are expected
|
||||||
t.Error("Missing --sysroot flag in CCFLAGS")
|
if tc.name == "WASM Target" {
|
||||||
}
|
if !hasSysroot {
|
||||||
if !hasResourceDir {
|
t.Error("Missing --sysroot flag in CCFLAGS")
|
||||||
t.Error("Missing -resource-dir flag in CCFLAGS")
|
}
|
||||||
|
if !hasResourceDir {
|
||||||
|
t.Error("Missing -resource-dir flag in CCFLAGS")
|
||||||
|
}
|
||||||
|
} else if tc.name == "Same Platform" {
|
||||||
|
// For same platform, we expect sysroot only on macOS
|
||||||
|
if runtime.GOOS == "darwin" && !hasSysroot {
|
||||||
|
t.Error("Missing --sysroot flag in CCFLAGS on macOS")
|
||||||
|
}
|
||||||
|
// On Linux and other platforms, sysroot is not necessarily required
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,9 +156,11 @@ func TestUseCrossCompileSDK(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if /*len(export.CCFLAGS) != 0 ||*/ len(export.CFLAGS) != 0 {
|
// For unsupported targets, we still expect some basic flags to be set
|
||||||
t.Errorf("Expected empty export, got CCFLAGS=%v, CFLAGS=%v, LDFLAGS=%v",
|
// since the implementation now always sets up ESP Clang environment
|
||||||
export.CCFLAGS, export.CFLAGS, export.LDFLAGS)
|
// Only check that we don't have specific SDK-related flags for unsupported targets
|
||||||
|
if tc.name == "Unsupported Target" && len(export.CFLAGS) != 0 {
|
||||||
|
t.Errorf("Expected empty CFLAGS for unsupported target, got CFLAGS=%v", export.CFLAGS)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -182,7 +193,7 @@ func TestUseTarget(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "Cortex-M Target",
|
name: "Cortex-M Target",
|
||||||
targetName: "cortex-m",
|
targetName: "cortex-m",
|
||||||
expectError: false,
|
expectError: true,
|
||||||
expectLLVM: "",
|
expectLLVM: "",
|
||||||
expectCPU: "",
|
expectCPU: "",
|
||||||
},
|
},
|
||||||
@@ -230,20 +241,33 @@ func TestUseTarget(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if CPU is in CCFLAGS
|
// Check if CPU is in LDFLAGS (for ld.lld linker) or CCFLAGS (for other cases)
|
||||||
if tc.expectCPU != "" {
|
if tc.expectCPU != "" {
|
||||||
found := false
|
found := false
|
||||||
expectedFlags := []string{"-mmcu=" + tc.expectCPU, "-mcpu=" + tc.expectCPU}
|
// First check LDFLAGS for -mllvm -mcpu= pattern
|
||||||
for _, flag := range export.CCFLAGS {
|
for i, flag := range export.LDFLAGS {
|
||||||
for _, expectedFlag := range expectedFlags {
|
if flag == "-mllvm" && i+1 < len(export.LDFLAGS) {
|
||||||
if flag == expectedFlag {
|
nextFlag := export.LDFLAGS[i+1]
|
||||||
|
if nextFlag == "-mcpu="+tc.expectCPU {
|
||||||
found = true
|
found = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// If not found in LDFLAGS, check CCFLAGS for direct CPU flags
|
||||||
if !found {
|
if !found {
|
||||||
t.Errorf("Expected CPU %s in CCFLAGS, got %v", tc.expectCPU, export.CCFLAGS)
|
expectedFlags := []string{"-mmcu=" + tc.expectCPU, "-mcpu=" + tc.expectCPU}
|
||||||
|
for _, flag := range export.CCFLAGS {
|
||||||
|
for _, expectedFlag := range expectedFlags {
|
||||||
|
if flag == expectedFlag {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
t.Errorf("Expected CPU %s in LDFLAGS or CCFLAGS, got LDFLAGS=%v, CCFLAGS=%v", tc.expectCPU, export.LDFLAGS, export.CCFLAGS)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,7 +279,7 @@ func TestUseTarget(t *testing.T) {
|
|||||||
|
|
||||||
func TestUseWithTarget(t *testing.T) {
|
func TestUseWithTarget(t *testing.T) {
|
||||||
// Test target-based configuration takes precedence
|
// Test target-based configuration takes precedence
|
||||||
export, err := UseWithTarget("linux", "amd64", false, "wasi")
|
export, err := Use("linux", "amd64", false, "wasi")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Unexpected error: %v", err)
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@@ -267,7 +291,7 @@ func TestUseWithTarget(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Test fallback to goos/goarch when no target specified
|
// Test fallback to goos/goarch when no target specified
|
||||||
export, err = UseWithTarget(runtime.GOOS, runtime.GOARCH, false, "")
|
export, err = Use(runtime.GOOS, runtime.GOARCH, false, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Unexpected error: %v", err)
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@@ -278,58 +302,125 @@ func TestUseWithTarget(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFilterCompatibleLDFlags(t *testing.T) {
|
func TestExpandEnv(t *testing.T) {
|
||||||
testCases := []struct {
|
envs := map[string]string{
|
||||||
name string
|
"port": "/dev/ttyUSB0",
|
||||||
input []string
|
"hex": "firmware.hex",
|
||||||
expected []string
|
"bin": "firmware.bin",
|
||||||
|
"root": "/usr/local/llgo",
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
template string
|
||||||
|
expected string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "Empty flags",
|
"avrdude -c arduino -p atmega328p -P {port} -U flash:w:{hex}:i",
|
||||||
input: []string{},
|
"avrdude -c arduino -p atmega328p -P /dev/ttyUSB0 -U flash:w:firmware.hex:i",
|
||||||
expected: []string{},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Compatible flags only",
|
"simavr -m atmega328p -f 16000000 {}",
|
||||||
input: []string{"-lm", "-lpthread"},
|
"simavr -m atmega328p -f 16000000 firmware.hex", // {} expands to hex (first priority)
|
||||||
expected: []string{"-lm", "-lpthread"},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Incompatible flags filtered",
|
"-I{root}/lib/CMSIS/CMSIS/Include",
|
||||||
input: []string{"--gc-sections", "-lm", "--emit-relocs", "-lpthread"},
|
"-I/usr/local/llgo/lib/CMSIS/CMSIS/Include",
|
||||||
expected: []string{"--gc-sections", "-lm", "--emit-relocs", "-lpthread"},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Defsym flags filtered",
|
"no variables here",
|
||||||
input: []string{"--defsym=_stack_size=512", "-lm", "--defsym=_bootloader_size=512"},
|
"no variables here",
|
||||||
expected: []string{"-lm"},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Linker script flags filtered",
|
"",
|
||||||
input: []string{"-T", "script.ld", "-lm"},
|
"",
|
||||||
expected: []string{"-lm"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Mixed compatible and incompatible",
|
|
||||||
input: []string{"-lm", "--gc-sections", "--defsym=test=1", "-lpthread", "--no-demangle"},
|
|
||||||
expected: []string{"-lm", "--gc-sections", "-lpthread", "--no-demangle"},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, test := range tests {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
result := expandEnv(test.template, envs)
|
||||||
result := filterCompatibleLDFlags(tc.input)
|
if result != test.expected {
|
||||||
|
t.Errorf("expandEnv(%q) = %q, want %q", test.template, result, test.expected)
|
||||||
if len(result) != len(tc.expected) {
|
}
|
||||||
t.Errorf("Expected %d flags, got %d: %v", len(tc.expected), len(result), result)
|
}
|
||||||
return
|
}
|
||||||
}
|
|
||||||
|
func TestExpandEnvSlice(t *testing.T) {
|
||||||
for i, expected := range tc.expected {
|
envs := map[string]string{
|
||||||
if result[i] != expected {
|
"root": "/usr/local/llgo",
|
||||||
t.Errorf("Expected flag[%d] = %s, got %s", i, expected, result[i])
|
"port": "/dev/ttyUSB0",
|
||||||
}
|
}
|
||||||
}
|
|
||||||
})
|
input := []string{
|
||||||
|
"-I{root}/include",
|
||||||
|
"-DPORT={port}",
|
||||||
|
"static-flag",
|
||||||
|
}
|
||||||
|
|
||||||
|
expected := []string{
|
||||||
|
"-I/usr/local/llgo/include",
|
||||||
|
"-DPORT=/dev/ttyUSB0",
|
||||||
|
"static-flag",
|
||||||
|
}
|
||||||
|
|
||||||
|
result := expandEnvSlice(input, envs)
|
||||||
|
|
||||||
|
if len(result) != len(expected) {
|
||||||
|
t.Fatalf("expandEnvSlice length mismatch: got %d, want %d", len(result), len(expected))
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, exp := range expected {
|
||||||
|
if result[i] != exp {
|
||||||
|
t.Errorf("expandEnvSlice[%d] = %q, want %q", i, result[i], exp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestExpandEnvWithDefault(t *testing.T) {
|
||||||
|
envs := map[string]string{
|
||||||
|
"port": "/dev/ttyUSB0",
|
||||||
|
"hex": "firmware.hex",
|
||||||
|
"bin": "firmware.bin",
|
||||||
|
"img": "image.img",
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
template string
|
||||||
|
defaultValue string
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"simavr {}",
|
||||||
|
"", // No default - should use hex (priority)
|
||||||
|
"simavr firmware.hex",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"simavr {}",
|
||||||
|
"custom.elf", // Explicit default
|
||||||
|
"simavr custom.elf",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"qemu -kernel {}",
|
||||||
|
"vmlinux", // Custom kernel
|
||||||
|
"qemu -kernel vmlinux",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"no braces here",
|
||||||
|
"ignored",
|
||||||
|
"no braces here",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, test := range tests {
|
||||||
|
var result string
|
||||||
|
if test.defaultValue == "" {
|
||||||
|
result = expandEnvWithDefault(test.template, envs)
|
||||||
|
} else {
|
||||||
|
result = expandEnvWithDefault(test.template, envs, test.defaultValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
if result != test.expected {
|
||||||
|
t.Errorf("Test %d: expandEnvWithDefault(%q, envs, %q) = %q, want %q",
|
||||||
|
i, test.template, test.defaultValue, result, test.expected)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,39 +7,149 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
func downloadAndExtract(url, dir string) (err error) {
|
// checkDownloadAndExtractWasiSDK downloads and extracts WASI SDK
|
||||||
if _, err = os.Stat(dir); err == nil {
|
func checkDownloadAndExtractWasiSDK(dir string) (wasiSdkRoot string, err error) {
|
||||||
os.RemoveAll(dir)
|
wasiSdkRoot = filepath.Join(dir, wasiMacosSubdir)
|
||||||
}
|
|
||||||
tempDir := dir + ".temp"
|
// Check if already exists
|
||||||
os.RemoveAll(tempDir)
|
if _, err := os.Stat(wasiSdkRoot); err == nil {
|
||||||
if err = os.MkdirAll(tempDir, 0755); err != nil {
|
return wasiSdkRoot, nil
|
||||||
return fmt.Errorf("failed to create temporary directory: %w", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create lock file path for the parent directory (dir) since that's what we're operating on
|
||||||
|
lockPath := dir + ".lock"
|
||||||
|
lockFile, err := acquireLock(lockPath)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("failed to acquire lock: %w", err)
|
||||||
|
}
|
||||||
|
defer releaseLock(lockFile)
|
||||||
|
|
||||||
|
// Double-check after acquiring lock
|
||||||
|
if _, err := os.Stat(wasiSdkRoot); err == nil {
|
||||||
|
return wasiSdkRoot, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
err = downloadAndExtractArchive(wasiSdkUrl, dir, "WASI SDK")
|
||||||
|
return wasiSdkRoot, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// checkDownloadAndExtractESPClang downloads and extracts ESP Clang binaries and libraries
|
||||||
|
func checkDownloadAndExtractESPClang(platformSuffix, dir string) error {
|
||||||
|
// Check if already exists
|
||||||
|
if _, err := os.Stat(dir); err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create lock file path for the final destination
|
||||||
|
lockPath := dir + ".lock"
|
||||||
|
lockFile, err := acquireLock(lockPath)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to acquire lock: %w", err)
|
||||||
|
}
|
||||||
|
defer releaseLock(lockFile)
|
||||||
|
|
||||||
|
// Double-check after acquiring lock
|
||||||
|
if _, err := os.Stat(dir); err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
clangUrl := fmt.Sprintf("%s/clang-esp-%s-%s.tar.xz", espClangBaseUrl, espClangVersion, platformSuffix)
|
||||||
|
description := fmt.Sprintf("ESP Clang %s-%s", espClangVersion, platformSuffix)
|
||||||
|
|
||||||
|
// Use temporary extraction directory for ESP Clang special handling
|
||||||
|
tempExtractDir := dir + ".extract"
|
||||||
|
if err := downloadAndExtractArchive(clangUrl, tempExtractDir, description); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(tempExtractDir)
|
||||||
|
|
||||||
|
// ESP Clang needs special handling: move esp-clang subdirectory to final destination
|
||||||
|
espClangDir := filepath.Join(tempExtractDir, "esp-clang")
|
||||||
|
if err := os.Rename(espClangDir, dir); err != nil {
|
||||||
|
return fmt.Errorf("failed to rename esp-clang directory: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// acquireLock creates and locks a file to prevent concurrent operations
|
||||||
|
func acquireLock(lockPath string) (*os.File, error) {
|
||||||
|
// Ensure the parent directory exists
|
||||||
|
if err := os.MkdirAll(filepath.Dir(lockPath), 0755); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to create lock directory: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
lockFile, err := os.OpenFile(lockPath, os.O_CREATE|os.O_WRONLY, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to create lock file: %w", err)
|
||||||
|
}
|
||||||
|
if err := syscall.Flock(int(lockFile.Fd()), syscall.LOCK_EX); err != nil {
|
||||||
|
lockFile.Close()
|
||||||
|
return nil, fmt.Errorf("failed to acquire lock: %w", err)
|
||||||
|
}
|
||||||
|
return lockFile, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// releaseLock unlocks and removes the lock file
|
||||||
|
func releaseLock(lockFile *os.File) error {
|
||||||
|
if lockFile == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
lockPath := lockFile.Name()
|
||||||
|
syscall.Flock(int(lockFile.Fd()), syscall.LOCK_UN)
|
||||||
|
lockFile.Close()
|
||||||
|
os.Remove(lockPath)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// downloadAndExtractArchive downloads and extracts an archive to the destination directory (without locking)
|
||||||
|
func downloadAndExtractArchive(url, destDir, description string) error {
|
||||||
|
fmt.Fprintf(os.Stderr, "Downloading %s...\n", description)
|
||||||
|
|
||||||
|
// Use temporary extraction directory
|
||||||
|
tempDir := destDir + ".temp"
|
||||||
|
os.RemoveAll(tempDir)
|
||||||
|
if err := os.MkdirAll(tempDir, 0755); err != nil {
|
||||||
|
return fmt.Errorf("failed to create temporary directory: %w", err)
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(tempDir)
|
||||||
|
|
||||||
|
// Download the archive
|
||||||
urlPath := strings.Split(url, "/")
|
urlPath := strings.Split(url, "/")
|
||||||
filename := urlPath[len(urlPath)-1]
|
filename := urlPath[len(urlPath)-1]
|
||||||
localFile := filepath.Join(tempDir, filename)
|
localFile := filepath.Join(tempDir, filename)
|
||||||
if err = downloadFile(url, localFile); err != nil {
|
if err := downloadFile(url, localFile); err != nil {
|
||||||
return fmt.Errorf("failed to download file: %w", err)
|
return fmt.Errorf("failed to download %s from %s: %w", description, url, err)
|
||||||
}
|
}
|
||||||
defer os.Remove(localFile)
|
|
||||||
|
|
||||||
|
// Extract the archive
|
||||||
|
fmt.Fprintf(os.Stderr, "Extracting %s...\n", description)
|
||||||
if strings.HasSuffix(filename, ".tar.gz") || strings.HasSuffix(filename, ".tgz") {
|
if strings.HasSuffix(filename, ".tar.gz") || strings.HasSuffix(filename, ".tgz") {
|
||||||
err = extractTarGz(localFile, tempDir)
|
err := extractTarGz(localFile, tempDir)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to extract %s archive: %w", description, err)
|
||||||
|
}
|
||||||
|
} else if strings.HasSuffix(filename, ".tar.xz") {
|
||||||
|
err := extractTarXz(localFile, tempDir)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to extract %s archive: %w", description, err)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return fmt.Errorf("unsupported archive format: %s", filename)
|
return fmt.Errorf("unsupported archive format: %s", filename)
|
||||||
}
|
}
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to extract archive: %w", err)
|
// Rename temp directory to target directory
|
||||||
}
|
if err := os.Rename(tempDir, destDir); err != nil {
|
||||||
if err = os.Rename(tempDir, dir); err != nil {
|
|
||||||
return fmt.Errorf("failed to rename directory: %w", err)
|
return fmt.Errorf("failed to rename directory: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fmt.Fprintf(os.Stderr, "%s downloaded and extracted successfully.\n", description)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,3 +217,9 @@ func extractTarGz(tarGzFile, dest string) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func extractTarXz(tarXzFile, dest string) error {
|
||||||
|
// Use external tar command to extract .tar.xz files
|
||||||
|
cmd := exec.Command("tar", "-xf", tarXzFile, "-C", dest)
|
||||||
|
return cmd.Run()
|
||||||
|
}
|
||||||
|
|||||||
492
internal/crosscompile/fetch_test.go
Normal file
492
internal/crosscompile/fetch_test.go
Normal file
@@ -0,0 +1,492 @@
|
|||||||
|
//go:build !llgo
|
||||||
|
// +build !llgo
|
||||||
|
|
||||||
|
package crosscompile
|
||||||
|
|
||||||
|
import (
|
||||||
|
"archive/tar"
|
||||||
|
"compress/gzip"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Helper function to create a test tar.gz archive
|
||||||
|
func createTestTarGz(t *testing.T, files map[string]string) string {
|
||||||
|
tempFile, err := os.CreateTemp("", "test*.tar.gz")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create temp file: %v", err)
|
||||||
|
}
|
||||||
|
defer tempFile.Close()
|
||||||
|
|
||||||
|
gzw := gzip.NewWriter(tempFile)
|
||||||
|
defer gzw.Close()
|
||||||
|
|
||||||
|
tw := tar.NewWriter(gzw)
|
||||||
|
defer tw.Close()
|
||||||
|
|
||||||
|
for name, content := range files {
|
||||||
|
hdr := &tar.Header{
|
||||||
|
Name: name,
|
||||||
|
Mode: 0644,
|
||||||
|
Size: int64(len(content)),
|
||||||
|
}
|
||||||
|
if err := tw.WriteHeader(hdr); err != nil {
|
||||||
|
t.Fatalf("Failed to write tar header: %v", err)
|
||||||
|
}
|
||||||
|
if _, err := tw.Write([]byte(content)); err != nil {
|
||||||
|
t.Fatalf("Failed to write tar content: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tempFile.Name()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to create a test HTTP server
|
||||||
|
func createTestServer(t *testing.T, files map[string]string) *httptest.Server {
|
||||||
|
return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
path := strings.TrimPrefix(r.URL.Path, "/")
|
||||||
|
if content, exists := files[path]; exists {
|
||||||
|
w.Header().Set("Content-Type", "application/octet-stream")
|
||||||
|
w.Write([]byte(content))
|
||||||
|
} else {
|
||||||
|
w.WriteHeader(http.StatusNotFound)
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAcquireAndReleaseLock(t *testing.T) {
|
||||||
|
tempDir := t.TempDir()
|
||||||
|
lockPath := filepath.Join(tempDir, "test.lock")
|
||||||
|
|
||||||
|
// Test acquiring lock
|
||||||
|
lockFile, err := acquireLock(lockPath)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to acquire lock: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check lock file exists
|
||||||
|
if _, err := os.Stat(lockPath); os.IsNotExist(err) {
|
||||||
|
t.Error("Lock file should exist")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test releasing lock
|
||||||
|
if err := releaseLock(lockFile); err != nil {
|
||||||
|
t.Errorf("Failed to release lock: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check lock file is removed
|
||||||
|
if _, err := os.Stat(lockPath); !os.IsNotExist(err) {
|
||||||
|
t.Error("Lock file should be removed after release")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAcquireLockConcurrency(t *testing.T) {
|
||||||
|
tempDir := t.TempDir()
|
||||||
|
lockPath := filepath.Join(tempDir, "concurrent.lock")
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
var results []int
|
||||||
|
var resultsMu sync.Mutex
|
||||||
|
|
||||||
|
// Start multiple goroutines trying to acquire the same lock
|
||||||
|
for i := 0; i < 5; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go func(id int) {
|
||||||
|
defer wg.Done()
|
||||||
|
|
||||||
|
lockFile, err := acquireLock(lockPath)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Goroutine %d failed to acquire lock: %v", id, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hold the lock for a short time
|
||||||
|
resultsMu.Lock()
|
||||||
|
results = append(results, id)
|
||||||
|
resultsMu.Unlock()
|
||||||
|
|
||||||
|
time.Sleep(10 * time.Millisecond)
|
||||||
|
|
||||||
|
if err := releaseLock(lockFile); err != nil {
|
||||||
|
t.Errorf("Goroutine %d failed to release lock: %v", id, err)
|
||||||
|
}
|
||||||
|
}(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
// All goroutines should have successfully acquired and released the lock
|
||||||
|
if len(results) != 5 {
|
||||||
|
t.Errorf("Expected 5 successful lock acquisitions, got %d", len(results))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDownloadFile(t *testing.T) {
|
||||||
|
// Create test server
|
||||||
|
testContent := "test file content"
|
||||||
|
server := createTestServer(t, map[string]string{
|
||||||
|
"test.txt": testContent,
|
||||||
|
})
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
tempDir := t.TempDir()
|
||||||
|
targetFile := filepath.Join(tempDir, "downloaded.txt")
|
||||||
|
|
||||||
|
// Test successful download
|
||||||
|
err := downloadFile(server.URL+"/test.txt", targetFile)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to download file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check file content
|
||||||
|
content, err := os.ReadFile(targetFile)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to read downloaded file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if string(content) != testContent {
|
||||||
|
t.Errorf("Expected content %q, got %q", testContent, string(content))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test download failure (404)
|
||||||
|
err = downloadFile(server.URL+"/nonexistent.txt", targetFile)
|
||||||
|
if err == nil {
|
||||||
|
t.Error("Expected error for non-existent file, got nil")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestExtractTarGz(t *testing.T) {
|
||||||
|
// Create test archive
|
||||||
|
files := map[string]string{
|
||||||
|
"test-dir/file1.txt": "content of file1",
|
||||||
|
"test-dir/file2.txt": "content of file2",
|
||||||
|
"file3.txt": "content of file3",
|
||||||
|
}
|
||||||
|
|
||||||
|
archivePath := createTestTarGz(t, files)
|
||||||
|
defer os.Remove(archivePath)
|
||||||
|
|
||||||
|
// Extract to temp directory
|
||||||
|
tempDir := t.TempDir()
|
||||||
|
err := extractTarGz(archivePath, tempDir)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to extract tar.gz: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check extracted files
|
||||||
|
for name, expectedContent := range files {
|
||||||
|
filePath := filepath.Join(tempDir, name)
|
||||||
|
content, err := os.ReadFile(filePath)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Failed to read extracted file %s: %v", name, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if string(content) != expectedContent {
|
||||||
|
t.Errorf("File %s: expected content %q, got %q", name, expectedContent, string(content))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestExtractTarGzPathTraversal(t *testing.T) {
|
||||||
|
// Create a malicious archive with path traversal
|
||||||
|
tempFile, err := os.CreateTemp("", "malicious*.tar.gz")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create temp file: %v", err)
|
||||||
|
}
|
||||||
|
defer tempFile.Close()
|
||||||
|
defer os.Remove(tempFile.Name())
|
||||||
|
|
||||||
|
gzw := gzip.NewWriter(tempFile)
|
||||||
|
tw := tar.NewWriter(gzw)
|
||||||
|
|
||||||
|
// Add a file with path traversal attack
|
||||||
|
hdr := &tar.Header{
|
||||||
|
Name: "../../../etc/passwd",
|
||||||
|
Mode: 0644,
|
||||||
|
Size: 5,
|
||||||
|
Typeflag: tar.TypeReg,
|
||||||
|
}
|
||||||
|
if err := tw.WriteHeader(hdr); err != nil {
|
||||||
|
t.Fatalf("Failed to write tar header: %v", err)
|
||||||
|
}
|
||||||
|
if _, err := tw.Write([]byte("pwned")); err != nil {
|
||||||
|
t.Fatalf("Failed to write tar content: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close writers to flush all data
|
||||||
|
if err := tw.Close(); err != nil {
|
||||||
|
t.Fatalf("Failed to close tar writer: %v", err)
|
||||||
|
}
|
||||||
|
if err := gzw.Close(); err != nil {
|
||||||
|
t.Fatalf("Failed to close gzip writer: %v", err)
|
||||||
|
}
|
||||||
|
if err := tempFile.Close(); err != nil {
|
||||||
|
t.Fatalf("Failed to close temp file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tempDir := t.TempDir()
|
||||||
|
err = extractTarGz(tempFile.Name(), tempDir)
|
||||||
|
if err == nil {
|
||||||
|
t.Error("Expected error for path traversal attack, got nil")
|
||||||
|
}
|
||||||
|
if !strings.Contains(err.Error(), "illegal file path") {
|
||||||
|
t.Errorf("Expected 'illegal file path' error, got: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDownloadAndExtractArchive(t *testing.T) {
|
||||||
|
// Create test archive
|
||||||
|
files := map[string]string{
|
||||||
|
"test-app/bin/app": "#!/bin/bash\necho hello",
|
||||||
|
"test-app/lib/lib.so": "fake library content",
|
||||||
|
"test-app/README": "This is a test application",
|
||||||
|
}
|
||||||
|
|
||||||
|
archivePath := createTestTarGz(t, files)
|
||||||
|
defer os.Remove(archivePath)
|
||||||
|
|
||||||
|
// Create test server to serve the archive
|
||||||
|
archiveContent, err := os.ReadFile(archivePath)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to read test archive: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
server := createTestServer(t, map[string]string{
|
||||||
|
"test-app.tar.gz": string(archiveContent),
|
||||||
|
})
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
// Test download and extract
|
||||||
|
tempDir := t.TempDir()
|
||||||
|
destDir := filepath.Join(tempDir, "extracted")
|
||||||
|
|
||||||
|
err = downloadAndExtractArchive(server.URL+"/test-app.tar.gz", destDir, "Test App")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to download and extract: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check extracted files
|
||||||
|
for name, expectedContent := range files {
|
||||||
|
filePath := filepath.Join(destDir, name)
|
||||||
|
content, err := os.ReadFile(filePath)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Failed to read extracted file %s: %v", name, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if string(content) != expectedContent {
|
||||||
|
t.Errorf("File %s: expected content %q, got %q", name, expectedContent, string(content))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDownloadAndExtractArchiveUnsupportedFormat(t *testing.T) {
|
||||||
|
server := createTestServer(t, map[string]string{
|
||||||
|
"test.zip": "fake zip content",
|
||||||
|
})
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
tempDir := t.TempDir()
|
||||||
|
destDir := filepath.Join(tempDir, "extracted")
|
||||||
|
|
||||||
|
err := downloadAndExtractArchive(server.URL+"/test.zip", destDir, "Test Archive")
|
||||||
|
if err == nil {
|
||||||
|
t.Error("Expected error for unsupported format, got nil")
|
||||||
|
}
|
||||||
|
if !strings.Contains(err.Error(), "unsupported archive format") {
|
||||||
|
t.Errorf("Expected 'unsupported archive format' error, got: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mock test for WASI SDK (without actual download)
|
||||||
|
func TestWasiSDKExtractionLogic(t *testing.T) {
|
||||||
|
tempDir := t.TempDir()
|
||||||
|
|
||||||
|
// Create fake WASI SDK directory structure
|
||||||
|
wasiSdkDir := filepath.Join(tempDir, wasiMacosSubdir)
|
||||||
|
binDir := filepath.Join(wasiSdkDir, "bin")
|
||||||
|
err := os.MkdirAll(binDir, 0755)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create fake WASI SDK structure: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create fake clang binary
|
||||||
|
clangPath := filepath.Join(binDir, "clang")
|
||||||
|
err = os.WriteFile(clangPath, []byte("fake clang"), 0755)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create fake clang: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that function returns correct path for existing SDK
|
||||||
|
sdkRoot, err := checkDownloadAndExtractWasiSDK(tempDir)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("checkDownloadAndExtractWasiSDK failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedRoot := filepath.Join(tempDir, wasiMacosSubdir)
|
||||||
|
if sdkRoot != expectedRoot {
|
||||||
|
t.Errorf("Expected SDK root %q, got %q", expectedRoot, sdkRoot)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test ESP Clang extraction logic with existing directory
|
||||||
|
func TestESPClangExtractionLogic(t *testing.T) {
|
||||||
|
tempDir := t.TempDir()
|
||||||
|
espClangDir := filepath.Join(tempDir, "esp-clang")
|
||||||
|
|
||||||
|
// Create fake ESP Clang directory structure
|
||||||
|
binDir := filepath.Join(espClangDir, "bin")
|
||||||
|
err := os.MkdirAll(binDir, 0755)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create fake ESP Clang structure: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create fake clang binary
|
||||||
|
clangPath := filepath.Join(binDir, "clang")
|
||||||
|
err = os.WriteFile(clangPath, []byte("fake esp clang"), 0755)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create fake esp clang: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that function skips download for existing directory
|
||||||
|
err = checkDownloadAndExtractESPClang("linux", espClangDir)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("checkDownloadAndExtractESPClang failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that the directory still exists and has the right content
|
||||||
|
if _, err := os.Stat(clangPath); os.IsNotExist(err) {
|
||||||
|
t.Error("ESP Clang binary should exist")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test WASI SDK download and extraction when directory doesn't exist
|
||||||
|
func TestWasiSDKDownloadWhenNotExists(t *testing.T) {
|
||||||
|
// Create fake WASI SDK archive with proper structure
|
||||||
|
files := map[string]string{
|
||||||
|
"wasi-sdk-25.0-x86_64-macos/bin/clang": "fake wasi clang binary",
|
||||||
|
"wasi-sdk-25.0-x86_64-macos/lib/libm.a": "fake math library",
|
||||||
|
"wasi-sdk-25.0-x86_64-macos/include/stdio.h": "#include <stdio.h>",
|
||||||
|
}
|
||||||
|
|
||||||
|
archivePath := createTestTarGz(t, files)
|
||||||
|
defer os.Remove(archivePath)
|
||||||
|
|
||||||
|
// Create test server to serve the archive
|
||||||
|
archiveContent, err := os.ReadFile(archivePath)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to read test archive: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
server := createTestServer(t, map[string]string{
|
||||||
|
"wasi-sdk-25.0-x86_64-macos.tar.gz": string(archiveContent),
|
||||||
|
})
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
// Override cacheRoot to use a temporary directory
|
||||||
|
tempCacheRoot := t.TempDir()
|
||||||
|
originalCacheRoot := cacheRoot
|
||||||
|
cacheRoot = func() string { return tempCacheRoot }
|
||||||
|
defer func() { cacheRoot = originalCacheRoot }()
|
||||||
|
|
||||||
|
// Override wasiSdkUrl to use our test server
|
||||||
|
originalWasiSdkUrl := wasiSdkUrl
|
||||||
|
wasiSdkUrl = server.URL + "/wasi-sdk-25.0-x86_64-macos.tar.gz"
|
||||||
|
defer func() { wasiSdkUrl = originalWasiSdkUrl }()
|
||||||
|
|
||||||
|
// Use the cache directory structure
|
||||||
|
extractDir := filepath.Join(tempCacheRoot, "crosscompile", "wasi")
|
||||||
|
|
||||||
|
// Test download and extract when directory doesn't exist
|
||||||
|
sdkRoot, err := checkDownloadAndExtractWasiSDK(extractDir)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("checkDownloadAndExtractWasiSDK failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedRoot := filepath.Join(extractDir, wasiMacosSubdir)
|
||||||
|
if sdkRoot != expectedRoot {
|
||||||
|
t.Errorf("Expected SDK root %q, got %q", expectedRoot, sdkRoot)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that files were extracted correctly
|
||||||
|
for name, expectedContent := range files {
|
||||||
|
filePath := filepath.Join(extractDir, name)
|
||||||
|
content, err := os.ReadFile(filePath)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Failed to read extracted file %s: %v", name, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if string(content) != expectedContent {
|
||||||
|
t.Errorf("File %s: expected content %q, got %q", name, expectedContent, string(content))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test ESP Clang download and extraction when directory doesn't exist
|
||||||
|
func TestESPClangDownloadWhenNotExists(t *testing.T) {
|
||||||
|
// Create fake ESP Clang archive with proper structure
|
||||||
|
files := map[string]string{
|
||||||
|
"esp-clang/bin/clang": "fake esp clang binary",
|
||||||
|
"esp-clang/lib/libc.a": "fake c library",
|
||||||
|
"esp-clang/include/esp32.h": "#define ESP32 1",
|
||||||
|
}
|
||||||
|
|
||||||
|
archivePath := createTestTarGz(t, files)
|
||||||
|
defer os.Remove(archivePath)
|
||||||
|
|
||||||
|
// Read the archive content
|
||||||
|
archiveContent, err := os.ReadFile(archivePath)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to read test archive: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
server := createTestServer(t, map[string]string{
|
||||||
|
"clang-esp-19.1.2_20250820-linux.tar.xz": string(archiveContent),
|
||||||
|
})
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
// Override cacheRoot to use a temporary directory
|
||||||
|
tempCacheRoot := t.TempDir()
|
||||||
|
originalCacheRoot := cacheRoot
|
||||||
|
cacheRoot = func() string { return tempCacheRoot }
|
||||||
|
defer func() { cacheRoot = originalCacheRoot }()
|
||||||
|
|
||||||
|
// Override espClangBaseUrl to use our test server
|
||||||
|
originalEspClangBaseUrl := espClangBaseUrl
|
||||||
|
espClangBaseUrl = server.URL
|
||||||
|
defer func() { espClangBaseUrl = originalEspClangBaseUrl }()
|
||||||
|
|
||||||
|
// Use a fresh temp directory that doesn't have ESP Clang
|
||||||
|
espClangDir := filepath.Join(tempCacheRoot, "esp-clang-test")
|
||||||
|
|
||||||
|
// Test download and extract when directory doesn't exist
|
||||||
|
err = checkDownloadAndExtractESPClang("linux", espClangDir)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("checkDownloadAndExtractESPClang failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that the target directory exists
|
||||||
|
if _, err := os.Stat(espClangDir); os.IsNotExist(err) {
|
||||||
|
t.Error("ESP Clang directory should exist after extraction")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that files were extracted correctly to the final destination
|
||||||
|
for name, expectedContent := range files {
|
||||||
|
// Remove "esp-clang/" prefix since it gets moved to the final destination
|
||||||
|
relativePath := strings.TrimPrefix(name, "esp-clang/")
|
||||||
|
filePath := filepath.Join(espClangDir, relativePath)
|
||||||
|
content, err := os.ReadFile(filePath)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Failed to read extracted file %s: %v", relativePath, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if string(content) != expectedContent {
|
||||||
|
t.Errorf("File %s: expected content %q, got %q", relativePath, expectedContent, string(content))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
188
internal/firmware/esp.go
Normal file
188
internal/firmware/esp.go
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
// From tinygo/builder/esp.go
|
||||||
|
|
||||||
|
package firmware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/sha256"
|
||||||
|
"debug/elf"
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type espImageSegment struct {
|
||||||
|
addr uint32
|
||||||
|
data []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// makeESPFirmareImage converts an input ELF file to an image file for an ESP32 or
|
||||||
|
// ESP8266 chip. This is a special purpose image format just for the ESP chip
|
||||||
|
// family, and is parsed by the on-chip mask ROM bootloader.
|
||||||
|
//
|
||||||
|
// The following documentation has been used:
|
||||||
|
// https://github.com/espressif/esptool/wiki/Firmware-Image-Format
|
||||||
|
// https://github.com/espressif/esp-idf/blob/8fbb63c2a701c22ccf4ce249f43aded73e134a34/components/bootloader_support/include/esp_image_format.h#L58
|
||||||
|
// https://github.com/espressif/esptool/blob/master/esptool.py
|
||||||
|
func makeESPFirmareImage(infile, outfile, format string) error {
|
||||||
|
inf, err := elf.Open(infile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer inf.Close()
|
||||||
|
|
||||||
|
// Load all segments to be written to the image. These are actually ELF
|
||||||
|
// sections, not true ELF segments (similar to how esptool does it).
|
||||||
|
var segments []*espImageSegment
|
||||||
|
for _, section := range inf.Sections {
|
||||||
|
if section.Type != elf.SHT_PROGBITS || section.Size == 0 || section.Flags&elf.SHF_ALLOC == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
data, err := section.Data()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to read section data: %w", err)
|
||||||
|
}
|
||||||
|
for len(data)%4 != 0 {
|
||||||
|
// Align segment to 4 bytes.
|
||||||
|
data = append(data, 0)
|
||||||
|
}
|
||||||
|
if uint64(uint32(section.Addr)) != section.Addr {
|
||||||
|
return fmt.Errorf("section address too big: 0x%x", section.Addr)
|
||||||
|
}
|
||||||
|
segments = append(segments, &espImageSegment{
|
||||||
|
addr: uint32(section.Addr),
|
||||||
|
data: data,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort the segments by address. This is what esptool does too.
|
||||||
|
sort.SliceStable(segments, func(i, j int) bool { return segments[i].addr < segments[j].addr })
|
||||||
|
|
||||||
|
// Calculate checksum over the segment data. This is used in the image
|
||||||
|
// footer.
|
||||||
|
checksum := uint8(0xef)
|
||||||
|
for _, segment := range segments {
|
||||||
|
for _, b := range segment.data {
|
||||||
|
checksum ^= b
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write first to an in-memory buffer, primarily so that we can easily
|
||||||
|
// calculate a hash over the entire image.
|
||||||
|
// An added benefit is that we don't need to check for errors all the time.
|
||||||
|
outf := &bytes.Buffer{}
|
||||||
|
|
||||||
|
// Separate esp32 and esp32-img. The -img suffix indicates we should make an
|
||||||
|
// image, not just a binary to be flashed at 0x1000 for example.
|
||||||
|
chip := format
|
||||||
|
makeImage := false
|
||||||
|
if strings.HasSuffix(format, "-img") {
|
||||||
|
makeImage = true
|
||||||
|
chip = format[:len(format)-len("-img")]
|
||||||
|
}
|
||||||
|
|
||||||
|
if makeImage {
|
||||||
|
// The bootloader starts at 0x1000, or 4096.
|
||||||
|
// TinyGo doesn't use a separate bootloader and runs the entire
|
||||||
|
// application in the bootloader location.
|
||||||
|
outf.Write(make([]byte, 4096))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Chip IDs. Source:
|
||||||
|
// https://github.com/espressif/esp-idf/blob/v4.3/components/bootloader_support/include/esp_app_format.h#L22
|
||||||
|
chip_id := map[string]uint16{
|
||||||
|
"esp32": 0x0000,
|
||||||
|
"esp32c3": 0x0005,
|
||||||
|
}[chip]
|
||||||
|
|
||||||
|
// Image header.
|
||||||
|
switch chip {
|
||||||
|
case "esp32", "esp32c3":
|
||||||
|
// Header format:
|
||||||
|
// https://github.com/espressif/esp-idf/blob/v4.3/components/bootloader_support/include/esp_app_format.h#L71
|
||||||
|
// Note: not adding a SHA256 hash as the binary is modified by
|
||||||
|
// esptool.py while flashing and therefore the hash won't be valid
|
||||||
|
// anymore.
|
||||||
|
binary.Write(outf, binary.LittleEndian, struct {
|
||||||
|
magic uint8
|
||||||
|
segment_count uint8
|
||||||
|
spi_mode uint8
|
||||||
|
spi_speed_size uint8
|
||||||
|
entry_addr uint32
|
||||||
|
wp_pin uint8
|
||||||
|
spi_pin_drv [3]uint8
|
||||||
|
chip_id uint16
|
||||||
|
min_chip_rev uint8
|
||||||
|
reserved [8]uint8
|
||||||
|
hash_appended bool
|
||||||
|
}{
|
||||||
|
magic: 0xE9,
|
||||||
|
segment_count: byte(len(segments)),
|
||||||
|
spi_mode: 2, // ESP_IMAGE_SPI_MODE_DIO
|
||||||
|
spi_speed_size: 0x1f, // ESP_IMAGE_SPI_SPEED_80M, ESP_IMAGE_FLASH_SIZE_2MB
|
||||||
|
entry_addr: uint32(inf.Entry),
|
||||||
|
wp_pin: 0xEE, // disable WP pin
|
||||||
|
chip_id: chip_id,
|
||||||
|
hash_appended: true, // add a SHA256 hash
|
||||||
|
})
|
||||||
|
case "esp8266":
|
||||||
|
// Header format:
|
||||||
|
// https://github.com/espressif/esptool/wiki/Firmware-Image-Format
|
||||||
|
// Basically a truncated version of the ESP32 header.
|
||||||
|
binary.Write(outf, binary.LittleEndian, struct {
|
||||||
|
magic uint8
|
||||||
|
segment_count uint8
|
||||||
|
spi_mode uint8
|
||||||
|
spi_speed_size uint8
|
||||||
|
entry_addr uint32
|
||||||
|
}{
|
||||||
|
magic: 0xE9,
|
||||||
|
segment_count: byte(len(segments)),
|
||||||
|
spi_mode: 0, // irrelevant, replaced by esptool when flashing
|
||||||
|
spi_speed_size: 0x20, // spi_speed, spi_size: replaced by esptool when flashing
|
||||||
|
entry_addr: uint32(inf.Entry),
|
||||||
|
})
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("builder: unknown binary format %#v, expected esp32 or esp8266", format)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write all segments to the image.
|
||||||
|
// https://github.com/espressif/esptool/wiki/Firmware-Image-Format#segment
|
||||||
|
for _, segment := range segments {
|
||||||
|
binary.Write(outf, binary.LittleEndian, struct {
|
||||||
|
addr uint32
|
||||||
|
length uint32
|
||||||
|
}{
|
||||||
|
addr: segment.addr,
|
||||||
|
length: uint32(len(segment.data)),
|
||||||
|
})
|
||||||
|
outf.Write(segment.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Footer, including checksum.
|
||||||
|
// The entire image size must be a multiple of 16, so pad the image to one
|
||||||
|
// byte less than that before writing the checksum.
|
||||||
|
outf.Write(make([]byte, 15-outf.Len()%16))
|
||||||
|
outf.WriteByte(checksum)
|
||||||
|
|
||||||
|
if chip != "esp8266" {
|
||||||
|
// SHA256 hash (to protect against image corruption, not for security).
|
||||||
|
hash := sha256.Sum256(outf.Bytes())
|
||||||
|
outf.Write(hash[:])
|
||||||
|
}
|
||||||
|
|
||||||
|
// QEMU (or more precisely, qemu-system-xtensa from Espressif) expects the
|
||||||
|
// image to be a certain size.
|
||||||
|
if makeImage {
|
||||||
|
// Use a default image size of 4MB.
|
||||||
|
grow := 4096*1024 - outf.Len()
|
||||||
|
if grow > 0 {
|
||||||
|
outf.Write(make([]byte, grow))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the image to the output file.
|
||||||
|
return os.WriteFile(outfile, outf.Bytes(), 0666)
|
||||||
|
}
|
||||||
16
internal/firmware/ext.go
Normal file
16
internal/firmware/ext.go
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package firmware
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
|
// BinaryExt returns the binary file extension based on the binary format
|
||||||
|
// Returns ".bin" for ESP-based formats, "" for others
|
||||||
|
func BinaryExt(binaryFormat string) string {
|
||||||
|
if strings.HasPrefix(binaryFormat, "esp") {
|
||||||
|
return ".bin"
|
||||||
|
} else if strings.HasPrefix(binaryFormat, "uf2") {
|
||||||
|
return ".uf2"
|
||||||
|
} else if strings.HasPrefix(binaryFormat, "nrf-dfu") {
|
||||||
|
return ".zip"
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
31
internal/firmware/ext_test.go
Normal file
31
internal/firmware/ext_test.go
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
//go:build !llgo
|
||||||
|
// +build !llgo
|
||||||
|
|
||||||
|
package firmware
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestBinaryExt(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
binaryFormat string
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{"ESP32", "esp32", ".bin"},
|
||||||
|
{"ESP8266", "esp8266", ".bin"},
|
||||||
|
{"ESP32C3", "esp32c3", ".bin"},
|
||||||
|
{"UF2", "uf2", ".uf2"},
|
||||||
|
{"ELF", "elf", ""},
|
||||||
|
{"Empty", "", ""},
|
||||||
|
{"NRF-DFU", "nrf-dfu", ".zip"},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
result := BinaryExt(tt.binaryFormat)
|
||||||
|
if result != tt.expected {
|
||||||
|
t.Errorf("BinaryExt() = %q, want %q", result, tt.expected)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
19
internal/firmware/firmware.go
Normal file
19
internal/firmware/firmware.go
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package firmware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MakeFirmwareImage creates a firmware image from the given input file.
|
||||||
|
func MakeFirmwareImage(infile, outfile, format, fmtDetail string) error {
|
||||||
|
if strings.HasPrefix(format, "esp") {
|
||||||
|
return makeESPFirmareImage(infile, outfile, format)
|
||||||
|
} else if format == "uf2" {
|
||||||
|
uf2Family := fmtDetail
|
||||||
|
return convertELFFileToUF2File(infile, outfile, uf2Family)
|
||||||
|
} else if format == "nrf-dfu" {
|
||||||
|
return makeDFUFirmwareImage(infile, outfile)
|
||||||
|
}
|
||||||
|
return fmt.Errorf("unsupported firmware format: %s", format)
|
||||||
|
}
|
||||||
118
internal/firmware/nrfutil.go
Normal file
118
internal/firmware/nrfutil.go
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
// From tinygo/builder/nrfutil.go
|
||||||
|
|
||||||
|
package firmware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"archive/zip"
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"encoding/json"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/sigurn/crc16"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Structure of the manifest.json file.
|
||||||
|
type jsonManifest struct {
|
||||||
|
Manifest struct {
|
||||||
|
Application struct {
|
||||||
|
BinaryFile string `json:"bin_file"`
|
||||||
|
DataFile string `json:"dat_file"`
|
||||||
|
InitPacketData nrfInitPacket `json:"init_packet_data"`
|
||||||
|
} `json:"application"`
|
||||||
|
DFUVersion float64 `json:"dfu_version"` // yes, this is a JSON number, not a string
|
||||||
|
} `json:"manifest"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Structure of the init packet.
|
||||||
|
// Source:
|
||||||
|
// https://github.com/adafruit/Adafruit_nRF52_Bootloader/blob/master/lib/sdk11/components/libraries/bootloader_dfu/dfu_init.h#L47-L57
|
||||||
|
type nrfInitPacket struct {
|
||||||
|
ApplicationVersion uint32 `json:"application_version"`
|
||||||
|
DeviceRevision uint16 `json:"device_revision"`
|
||||||
|
DeviceType uint16 `json:"device_type"`
|
||||||
|
FirmwareCRC16 uint16 `json:"firmware_crc16"`
|
||||||
|
SoftDeviceRequired []uint16 `json:"softdevice_req"` // this is actually a variable length array
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the init packet (the contents of application.dat).
|
||||||
|
func (p nrfInitPacket) createInitPacket() []byte {
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
binary.Write(buf, binary.LittleEndian, p.DeviceType) // uint16_t device_type;
|
||||||
|
binary.Write(buf, binary.LittleEndian, p.DeviceRevision) // uint16_t device_rev;
|
||||||
|
binary.Write(buf, binary.LittleEndian, p.ApplicationVersion) // uint32_t app_version;
|
||||||
|
binary.Write(buf, binary.LittleEndian, uint16(len(p.SoftDeviceRequired))) // uint16_t softdevice_len;
|
||||||
|
binary.Write(buf, binary.LittleEndian, p.SoftDeviceRequired) // uint16_t softdevice[1];
|
||||||
|
binary.Write(buf, binary.LittleEndian, p.FirmwareCRC16)
|
||||||
|
return buf.Bytes()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make a Nordic DFU firmware image from an ELF file.
|
||||||
|
func makeDFUFirmwareImage(infile, outfile string) error {
|
||||||
|
// Read ELF file as input and convert it to a binary image file.
|
||||||
|
_, data, err := extractROM(infile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the zip file in memory.
|
||||||
|
// It won't be very large anyway.
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
w := zip.NewWriter(buf)
|
||||||
|
|
||||||
|
// Write the application binary to the zip file.
|
||||||
|
binw, err := w.Create("application.bin")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = binw.Write(data)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the init packet.
|
||||||
|
initPacket := nrfInitPacket{
|
||||||
|
ApplicationVersion: 0xffff_ffff, // appears to be unused by the Adafruit bootloader
|
||||||
|
DeviceRevision: 0xffff, // DFU_DEVICE_REVISION_EMPTY
|
||||||
|
DeviceType: 0x0052, // ADAFRUIT_DEVICE_TYPE
|
||||||
|
FirmwareCRC16: crc16.Checksum(data, crc16.MakeTable(crc16.CRC16_CCITT_FALSE)),
|
||||||
|
SoftDeviceRequired: []uint16{0xfffe}, // DFU_SOFTDEVICE_ANY
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the init packet to the zip file.
|
||||||
|
datw, err := w.Create("application.dat")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = datw.Write(initPacket.createInitPacket())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the JSON manifest.
|
||||||
|
manifest := &jsonManifest{}
|
||||||
|
manifest.Manifest.Application.BinaryFile = "application.bin"
|
||||||
|
manifest.Manifest.Application.DataFile = "application.dat"
|
||||||
|
manifest.Manifest.Application.InitPacketData = initPacket
|
||||||
|
manifest.Manifest.DFUVersion = 0.5
|
||||||
|
|
||||||
|
// Write the JSON manifest to the file.
|
||||||
|
jsonw, err := w.Create("manifest.json")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
enc := json.NewEncoder(jsonw)
|
||||||
|
enc.SetIndent("", " ")
|
||||||
|
err = enc.Encode(manifest)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finish the zip file.
|
||||||
|
err = w.Close()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return os.WriteFile(outfile, buf.Bytes(), 0o666)
|
||||||
|
}
|
||||||
133
internal/firmware/objcopy.go
Normal file
133
internal/firmware/objcopy.go
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
// From tinygo/builder/objcopy.go
|
||||||
|
|
||||||
|
package firmware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"debug/elf"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"sort"
|
||||||
|
)
|
||||||
|
|
||||||
|
// maxPadBytes is the maximum allowed bytes to be padded in a rom extraction
|
||||||
|
// this value is currently defined by Nintendo Switch Page Alignment (4096 bytes)
|
||||||
|
const maxPadBytes = 4095
|
||||||
|
|
||||||
|
// objcopyError is an error returned by functions that act like objcopy.
|
||||||
|
type objcopyError struct {
|
||||||
|
Op string
|
||||||
|
Err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e objcopyError) Error() string {
|
||||||
|
if e.Err == nil {
|
||||||
|
return e.Op
|
||||||
|
}
|
||||||
|
return e.Op + ": " + e.Err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
type progSlice []*elf.Prog
|
||||||
|
|
||||||
|
func (s progSlice) Len() int { return len(s) }
|
||||||
|
func (s progSlice) Less(i, j int) bool { return s[i].Paddr < s[j].Paddr }
|
||||||
|
func (s progSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||||
|
|
||||||
|
// extractROM extracts a firmware image and the first load address from the
|
||||||
|
// given ELF file. It tries to emulate the behavior of objcopy.
|
||||||
|
func extractROM(path string) (uint64, []byte, error) {
|
||||||
|
f, err := elf.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return 0, nil, objcopyError{"failed to open ELF file to extract text segment", err}
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
// The GNU objcopy command does the following for firmware extraction (from
|
||||||
|
// the man page):
|
||||||
|
// > When objcopy generates a raw binary file, it will essentially produce a
|
||||||
|
// > memory dump of the contents of the input object file. All symbols and
|
||||||
|
// > relocation information will be discarded. The memory dump will start at
|
||||||
|
// > the load address of the lowest section copied into the output file.
|
||||||
|
|
||||||
|
// Find the lowest section address.
|
||||||
|
startAddr := ^uint64(0)
|
||||||
|
for _, section := range f.Sections {
|
||||||
|
if section.Type != elf.SHT_PROGBITS || section.Flags&elf.SHF_ALLOC == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if section.Addr < startAddr {
|
||||||
|
startAddr = section.Addr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
progs := make(progSlice, 0, 2)
|
||||||
|
for _, prog := range f.Progs {
|
||||||
|
if prog.Type != elf.PT_LOAD || prog.Filesz == 0 || prog.Off == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
progs = append(progs, prog)
|
||||||
|
}
|
||||||
|
if len(progs) == 0 {
|
||||||
|
return 0, nil, objcopyError{"file does not contain ROM segments: " + path, nil}
|
||||||
|
}
|
||||||
|
sort.Sort(progs)
|
||||||
|
|
||||||
|
var rom []byte
|
||||||
|
for _, prog := range progs {
|
||||||
|
romEnd := progs[0].Paddr + uint64(len(rom))
|
||||||
|
if prog.Paddr > romEnd && prog.Paddr < romEnd+16 {
|
||||||
|
// Sometimes, the linker seems to insert a bit of padding between
|
||||||
|
// segments. Simply zero-fill these parts.
|
||||||
|
rom = append(rom, make([]byte, prog.Paddr-romEnd)...)
|
||||||
|
}
|
||||||
|
if prog.Paddr != progs[0].Paddr+uint64(len(rom)) {
|
||||||
|
diff := prog.Paddr - (progs[0].Paddr + uint64(len(rom)))
|
||||||
|
if diff > maxPadBytes {
|
||||||
|
return 0, nil, objcopyError{"ROM segments are non-contiguous: " + path, nil}
|
||||||
|
}
|
||||||
|
// Pad the difference
|
||||||
|
rom = append(rom, make([]byte, diff)...)
|
||||||
|
}
|
||||||
|
data, err := io.ReadAll(prog.Open())
|
||||||
|
if err != nil {
|
||||||
|
return 0, nil, objcopyError{"failed to extract segment from ELF file: " + path, err}
|
||||||
|
}
|
||||||
|
rom = append(rom, data...)
|
||||||
|
}
|
||||||
|
if progs[0].Paddr < startAddr {
|
||||||
|
// The lowest memory address is before the first section. This means
|
||||||
|
// that there is some extra data loaded at the start of the image that
|
||||||
|
// should be discarded.
|
||||||
|
// Example: ELF files where .text doesn't start at address 0 because
|
||||||
|
// there is a bootloader at the start.
|
||||||
|
return startAddr, rom[startAddr-progs[0].Paddr:], nil
|
||||||
|
} else {
|
||||||
|
return progs[0].Paddr, rom, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// objcopy converts an ELF file to a different (simpler) output file format:
|
||||||
|
// .bin or .hex. It extracts only the .text section.
|
||||||
|
func objcopy(infile, outfile, binaryFormat string) error {
|
||||||
|
f, err := os.OpenFile(outfile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
// Read the .text segment.
|
||||||
|
_, data, err := extractROM(infile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write to the file, in the correct format.
|
||||||
|
switch binaryFormat {
|
||||||
|
case "bin":
|
||||||
|
// The start address is not stored in raw firmware files (therefore you
|
||||||
|
// should use .hex files in most cases).
|
||||||
|
_, err := f.Write(data)
|
||||||
|
return err
|
||||||
|
default:
|
||||||
|
panic("unreachable")
|
||||||
|
}
|
||||||
|
}
|
||||||
155
internal/firmware/uf2.go
Normal file
155
internal/firmware/uf2.go
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
// From tinygo/builder/uf2.go
|
||||||
|
|
||||||
|
package firmware
|
||||||
|
|
||||||
|
// This file converts firmware files from BIN to UF2 format before flashing.
|
||||||
|
//
|
||||||
|
// For more information about the UF2 firmware file format, please see:
|
||||||
|
// https://github.com/Microsoft/uf2
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
// convertELFFileToUF2File converts an ELF file to a UF2 file.
|
||||||
|
func convertELFFileToUF2File(infile, outfile string, uf2FamilyID string) error {
|
||||||
|
// Read the .text segment.
|
||||||
|
targetAddress, data, err := extractROM(infile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
output, _, err := convertBinToUF2(data, uint32(targetAddress), uf2FamilyID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return os.WriteFile(outfile, output, 0644)
|
||||||
|
}
|
||||||
|
|
||||||
|
// convertBinToUF2 converts the binary bytes in input to UF2 formatted data.
|
||||||
|
func convertBinToUF2(input []byte, targetAddr uint32, uf2FamilyID string) ([]byte, int, error) {
|
||||||
|
blocks := split(input, 256)
|
||||||
|
output := make([]byte, 0)
|
||||||
|
|
||||||
|
bl, err := newUF2Block(targetAddr, uf2FamilyID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
bl.SetNumBlocks(len(blocks))
|
||||||
|
|
||||||
|
for i := 0; i < len(blocks); i++ {
|
||||||
|
bl.SetBlockNo(i)
|
||||||
|
bl.SetData(blocks[i])
|
||||||
|
|
||||||
|
output = append(output, bl.Bytes()...)
|
||||||
|
bl.IncrementAddress(bl.payloadSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
return output, len(blocks), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
uf2MagicStart0 = 0x0A324655 // "UF2\n"
|
||||||
|
uf2MagicStart1 = 0x9E5D5157 // Randomly selected
|
||||||
|
uf2MagicEnd = 0x0AB16F30 // Ditto
|
||||||
|
)
|
||||||
|
|
||||||
|
// uf2Block is the structure used for each UF2 code block sent to device.
|
||||||
|
type uf2Block struct {
|
||||||
|
magicStart0 uint32
|
||||||
|
magicStart1 uint32
|
||||||
|
flags uint32
|
||||||
|
targetAddr uint32
|
||||||
|
payloadSize uint32
|
||||||
|
blockNo uint32
|
||||||
|
numBlocks uint32
|
||||||
|
familyID uint32
|
||||||
|
data []uint8
|
||||||
|
magicEnd uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// newUF2Block returns a new uf2Block struct that has been correctly populated
|
||||||
|
func newUF2Block(targetAddr uint32, uf2FamilyID string) (*uf2Block, error) {
|
||||||
|
var flags uint32
|
||||||
|
var familyID uint32
|
||||||
|
if uf2FamilyID != "" {
|
||||||
|
flags |= flagFamilyIDPresent
|
||||||
|
v, err := strconv.ParseUint(uf2FamilyID, 0, 32)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
familyID = uint32(v)
|
||||||
|
}
|
||||||
|
return &uf2Block{magicStart0: uf2MagicStart0,
|
||||||
|
magicStart1: uf2MagicStart1,
|
||||||
|
magicEnd: uf2MagicEnd,
|
||||||
|
targetAddr: targetAddr,
|
||||||
|
flags: flags,
|
||||||
|
familyID: familyID,
|
||||||
|
payloadSize: 256,
|
||||||
|
data: make([]byte, 476),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
flagFamilyIDPresent = 0x00002000
|
||||||
|
)
|
||||||
|
|
||||||
|
// Bytes converts the uf2Block to a slice of bytes that can be written to file.
|
||||||
|
func (b *uf2Block) Bytes() []byte {
|
||||||
|
buf := bytes.NewBuffer(make([]byte, 0, 512))
|
||||||
|
binary.Write(buf, binary.LittleEndian, b.magicStart0)
|
||||||
|
binary.Write(buf, binary.LittleEndian, b.magicStart1)
|
||||||
|
binary.Write(buf, binary.LittleEndian, b.flags)
|
||||||
|
binary.Write(buf, binary.LittleEndian, b.targetAddr)
|
||||||
|
binary.Write(buf, binary.LittleEndian, b.payloadSize)
|
||||||
|
binary.Write(buf, binary.LittleEndian, b.blockNo)
|
||||||
|
binary.Write(buf, binary.LittleEndian, b.numBlocks)
|
||||||
|
binary.Write(buf, binary.LittleEndian, b.familyID)
|
||||||
|
binary.Write(buf, binary.LittleEndian, b.data)
|
||||||
|
binary.Write(buf, binary.LittleEndian, b.magicEnd)
|
||||||
|
|
||||||
|
return buf.Bytes()
|
||||||
|
}
|
||||||
|
|
||||||
|
// IncrementAddress moves the target address pointer forward by count bytes.
|
||||||
|
func (b *uf2Block) IncrementAddress(count uint32) {
|
||||||
|
b.targetAddr += b.payloadSize
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetData sets the data to be used for the current block.
|
||||||
|
func (b *uf2Block) SetData(d []byte) {
|
||||||
|
b.data = make([]byte, 476)
|
||||||
|
copy(b.data[:], d)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetBlockNo sets the current block number to be used.
|
||||||
|
func (b *uf2Block) SetBlockNo(bn int) {
|
||||||
|
b.blockNo = uint32(bn)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNumBlocks sets the total number of blocks for this UF2 file.
|
||||||
|
func (b *uf2Block) SetNumBlocks(total int) {
|
||||||
|
b.numBlocks = uint32(total)
|
||||||
|
}
|
||||||
|
|
||||||
|
// split splits a slice of bytes into a slice of byte slices of a specific size limit.
|
||||||
|
func split(input []byte, limit int) [][]byte {
|
||||||
|
var block []byte
|
||||||
|
output := make([][]byte, 0, len(input)/limit+1)
|
||||||
|
for len(input) >= limit {
|
||||||
|
// add all blocks
|
||||||
|
block, input = input[:limit], input[limit:]
|
||||||
|
output = append(output, block)
|
||||||
|
}
|
||||||
|
if len(input) > 0 {
|
||||||
|
// add remaining block (that isn't full sized)
|
||||||
|
output = append(output, input)
|
||||||
|
}
|
||||||
|
return output
|
||||||
|
}
|
||||||
@@ -16,9 +16,42 @@ type Config struct {
|
|||||||
GOARCH string `json:"goarch"`
|
GOARCH string `json:"goarch"`
|
||||||
|
|
||||||
// Compiler and linker configuration
|
// Compiler and linker configuration
|
||||||
Linker string `json:"linker"`
|
Linker string `json:"linker"`
|
||||||
CFlags []string `json:"cflags"`
|
LinkerScript string `json:"linkerscript"`
|
||||||
LDFlags []string `json:"ldflags"`
|
CFlags []string `json:"cflags"`
|
||||||
|
LDFlags []string `json:"ldflags"`
|
||||||
|
ExtraFiles []string `json:"extra-files"`
|
||||||
|
|
||||||
|
// Code generation configuration
|
||||||
|
CodeModel string `json:"code-model"`
|
||||||
|
TargetABI string `json:"target-abi"`
|
||||||
|
RelocationModel string `json:"relocation-model"`
|
||||||
|
|
||||||
|
// Binary and firmware configuration
|
||||||
|
BinaryFormat string `json:"binary-format"`
|
||||||
|
// UF2 configuration
|
||||||
|
UF2FamilyID string `json:"uf2-family-id"`
|
||||||
|
|
||||||
|
// Flash and deployment configuration
|
||||||
|
FlashCommand string `json:"flash-command"`
|
||||||
|
FlashMethod string `json:"flash-method"`
|
||||||
|
Flash1200BpsReset string `json:"flash-1200-bps-reset"`
|
||||||
|
|
||||||
|
// Mass storage device configuration
|
||||||
|
MSDVolumeName []string `json:"msd-volume-name"`
|
||||||
|
MSDFirmwareName string `json:"msd-firmware-name"`
|
||||||
|
|
||||||
|
// Device-specific configuration
|
||||||
|
RP2040BootPatch bool `json:"rp2040-boot-patch"`
|
||||||
|
|
||||||
|
// Debug and emulation configuration
|
||||||
|
Emulator string `json:"emulator"`
|
||||||
|
GDB []string `json:"gdb"`
|
||||||
|
|
||||||
|
// OpenOCD configuration
|
||||||
|
OpenOCDInterface string `json:"openocd-interface"`
|
||||||
|
OpenOCDTransport string `json:"openocd-transport"`
|
||||||
|
OpenOCDTarget string `json:"openocd-target"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// RawConfig represents the raw JSON configuration before inheritance resolution
|
// RawConfig represents the raw JSON configuration before inheritance resolution
|
||||||
@@ -32,6 +65,13 @@ func (c *Config) IsEmpty() bool {
|
|||||||
return c.Name == "" && c.LLVMTarget == "" && c.GOOS == "" && c.GOARCH == ""
|
return c.Name == "" && c.LLVMTarget == "" && c.GOOS == "" && c.GOARCH == ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Config) FormatDetail() string {
|
||||||
|
if c.BinaryFormat == "uf2" {
|
||||||
|
return c.UF2FamilyID
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
// HasInheritance returns true if this config inherits from other configs
|
// HasInheritance returns true if this config inherits from other configs
|
||||||
func (rc *RawConfig) HasInheritance() bool {
|
func (rc *RawConfig) HasInheritance() bool {
|
||||||
return len(rc.Inherits) > 0
|
return len(rc.Inherits) > 0
|
||||||
|
|||||||
@@ -137,6 +137,51 @@ func (l *Loader) mergeConfig(dst, src *Config) {
|
|||||||
if src.Linker != "" {
|
if src.Linker != "" {
|
||||||
dst.Linker = src.Linker
|
dst.Linker = src.Linker
|
||||||
}
|
}
|
||||||
|
if src.LinkerScript != "" {
|
||||||
|
dst.LinkerScript = src.LinkerScript
|
||||||
|
}
|
||||||
|
if src.CodeModel != "" {
|
||||||
|
dst.CodeModel = src.CodeModel
|
||||||
|
}
|
||||||
|
if src.TargetABI != "" {
|
||||||
|
dst.TargetABI = src.TargetABI
|
||||||
|
}
|
||||||
|
if src.RelocationModel != "" {
|
||||||
|
dst.RelocationModel = src.RelocationModel
|
||||||
|
}
|
||||||
|
if src.BinaryFormat != "" {
|
||||||
|
dst.BinaryFormat = src.BinaryFormat
|
||||||
|
}
|
||||||
|
if src.FlashCommand != "" {
|
||||||
|
dst.FlashCommand = src.FlashCommand
|
||||||
|
}
|
||||||
|
if src.FlashMethod != "" {
|
||||||
|
dst.FlashMethod = src.FlashMethod
|
||||||
|
}
|
||||||
|
if src.Flash1200BpsReset != "" {
|
||||||
|
dst.Flash1200BpsReset = src.Flash1200BpsReset
|
||||||
|
}
|
||||||
|
if src.MSDFirmwareName != "" {
|
||||||
|
dst.MSDFirmwareName = src.MSDFirmwareName
|
||||||
|
}
|
||||||
|
if src.UF2FamilyID != "" {
|
||||||
|
dst.UF2FamilyID = src.UF2FamilyID
|
||||||
|
}
|
||||||
|
if src.RP2040BootPatch {
|
||||||
|
dst.RP2040BootPatch = src.RP2040BootPatch
|
||||||
|
}
|
||||||
|
if src.Emulator != "" {
|
||||||
|
dst.Emulator = src.Emulator
|
||||||
|
}
|
||||||
|
if src.OpenOCDInterface != "" {
|
||||||
|
dst.OpenOCDInterface = src.OpenOCDInterface
|
||||||
|
}
|
||||||
|
if src.OpenOCDTransport != "" {
|
||||||
|
dst.OpenOCDTransport = src.OpenOCDTransport
|
||||||
|
}
|
||||||
|
if src.OpenOCDTarget != "" {
|
||||||
|
dst.OpenOCDTarget = src.OpenOCDTarget
|
||||||
|
}
|
||||||
|
|
||||||
// Merge slices (append, don't replace)
|
// Merge slices (append, don't replace)
|
||||||
if len(src.BuildTags) > 0 {
|
if len(src.BuildTags) > 0 {
|
||||||
@@ -148,6 +193,15 @@ func (l *Loader) mergeConfig(dst, src *Config) {
|
|||||||
if len(src.LDFlags) > 0 {
|
if len(src.LDFlags) > 0 {
|
||||||
dst.LDFlags = append(dst.LDFlags, src.LDFlags...)
|
dst.LDFlags = append(dst.LDFlags, src.LDFlags...)
|
||||||
}
|
}
|
||||||
|
if len(src.ExtraFiles) > 0 {
|
||||||
|
dst.ExtraFiles = append(dst.ExtraFiles, src.ExtraFiles...)
|
||||||
|
}
|
||||||
|
if len(src.MSDVolumeName) > 0 {
|
||||||
|
dst.MSDVolumeName = append(dst.MSDVolumeName, src.MSDVolumeName...)
|
||||||
|
}
|
||||||
|
if len(src.GDB) > 0 {
|
||||||
|
dst.GDB = append(dst.GDB, src.GDB...)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTargetsDir returns the targets directory path
|
// GetTargetsDir returns the targets directory path
|
||||||
|
|||||||
@@ -61,7 +61,8 @@ func TestLoaderLoadRaw(t *testing.T) {
|
|||||||
"goarch": "arm",
|
"goarch": "arm",
|
||||||
"build-tags": ["test", "embedded"],
|
"build-tags": ["test", "embedded"],
|
||||||
"cflags": ["-Os", "-g"],
|
"cflags": ["-Os", "-g"],
|
||||||
"ldflags": ["--gc-sections"]
|
"ldflags": ["--gc-sections"],
|
||||||
|
"binary-format": "uf2"
|
||||||
}`
|
}`
|
||||||
|
|
||||||
configPath := filepath.Join(tempDir, "test-target.json")
|
configPath := filepath.Join(tempDir, "test-target.json")
|
||||||
@@ -87,6 +88,9 @@ func TestLoaderLoadRaw(t *testing.T) {
|
|||||||
if len(config.BuildTags) != 2 || config.BuildTags[0] != "test" || config.BuildTags[1] != "embedded" {
|
if len(config.BuildTags) != 2 || config.BuildTags[0] != "test" || config.BuildTags[1] != "embedded" {
|
||||||
t.Errorf("Expected build-tags [test, embedded], got %v", config.BuildTags)
|
t.Errorf("Expected build-tags [test, embedded], got %v", config.BuildTags)
|
||||||
}
|
}
|
||||||
|
if config.BinaryFormat != "uf2" {
|
||||||
|
t.Errorf("Expected binary-format 'uf2', got '%s'", config.BinaryFormat)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLoaderInheritance(t *testing.T) {
|
func TestLoaderInheritance(t *testing.T) {
|
||||||
@@ -99,7 +103,8 @@ func TestLoaderInheritance(t *testing.T) {
|
|||||||
"goos": "linux",
|
"goos": "linux",
|
||||||
"goarch": "arm",
|
"goarch": "arm",
|
||||||
"cflags": ["-Os"],
|
"cflags": ["-Os"],
|
||||||
"ldflags": ["--gc-sections"]
|
"ldflags": ["--gc-sections"],
|
||||||
|
"binary-format": "elf"
|
||||||
}`
|
}`
|
||||||
|
|
||||||
// Create child config that inherits from parent
|
// Create child config that inherits from parent
|
||||||
@@ -108,7 +113,8 @@ func TestLoaderInheritance(t *testing.T) {
|
|||||||
"cpu": "cortex-m4",
|
"cpu": "cortex-m4",
|
||||||
"build-tags": ["child"],
|
"build-tags": ["child"],
|
||||||
"cflags": ["-O2"],
|
"cflags": ["-O2"],
|
||||||
"ldflags": ["-g"]
|
"ldflags": ["-g"],
|
||||||
|
"binary-format": "uf2"
|
||||||
}`
|
}`
|
||||||
|
|
||||||
parentPath := filepath.Join(tempDir, "parent.json")
|
parentPath := filepath.Join(tempDir, "parent.json")
|
||||||
@@ -143,6 +149,11 @@ func TestLoaderInheritance(t *testing.T) {
|
|||||||
t.Errorf("Expected overridden cpu 'cortex-m4', got '%s'", config.CPU)
|
t.Errorf("Expected overridden cpu 'cortex-m4', got '%s'", config.CPU)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check binary-format override
|
||||||
|
if config.BinaryFormat != "uf2" {
|
||||||
|
t.Errorf("Expected overridden binary-format 'uf2', got '%s'", config.BinaryFormat)
|
||||||
|
}
|
||||||
|
|
||||||
// Check merged arrays
|
// Check merged arrays
|
||||||
expectedCFlags := []string{"-Os", "-O2"}
|
expectedCFlags := []string{"-Os", "-O2"}
|
||||||
if len(config.CFlags) != 2 || config.CFlags[0] != "-Os" || config.CFlags[1] != "-O2" {
|
if len(config.CFlags) != 2 || config.CFlags[0] != "-Os" || config.CFlags[1] != "-O2" {
|
||||||
|
|||||||
@@ -6,9 +6,9 @@
|
|||||||
"ldflags": [
|
"ldflags": [
|
||||||
"--defsym=_stack_size=512"
|
"--defsym=_stack_size=512"
|
||||||
],
|
],
|
||||||
"linkerscript": "src/device/avr/atmega1280.ld",
|
"linkerscript": "targets/device/avr/atmega1280.ld",
|
||||||
"extra-files": [
|
"extra-files": [
|
||||||
"targets/avr.S",
|
"targets/avr.S",
|
||||||
"src/device/avr/atmega1280.s"
|
"targets/device/avr/atmega1280.s"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,10 +7,10 @@
|
|||||||
"--defsym=_bootloader_size=0",
|
"--defsym=_bootloader_size=0",
|
||||||
"--defsym=_stack_size=512"
|
"--defsym=_stack_size=512"
|
||||||
],
|
],
|
||||||
"linkerscript": "src/device/avr/atmega1284p.ld",
|
"linkerscript": "targets/device/avr/atmega1284p.ld",
|
||||||
"extra-files": [
|
"extra-files": [
|
||||||
"targets/avr.S",
|
"targets/avr.S",
|
||||||
"src/device/avr/atmega1284p.s"
|
"targets/device/avr/atmega1284p.s"
|
||||||
],
|
],
|
||||||
"emulator": "simavr -m atmega1284p -f 20000000 {}"
|
"emulator": "simavr -m atmega1284p -f 20000000 {}"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,9 +6,9 @@
|
|||||||
"ldflags": [
|
"ldflags": [
|
||||||
"--defsym=_stack_size=512"
|
"--defsym=_stack_size=512"
|
||||||
],
|
],
|
||||||
"linkerscript": "src/device/avr/atmega2560.ld",
|
"linkerscript": "targets/device/avr/atmega2560.ld",
|
||||||
"extra-files": [
|
"extra-files": [
|
||||||
"targets/avr.S",
|
"targets/avr.S",
|
||||||
"src/device/avr/atmega2560.s"
|
"targets/device/avr/atmega2560.s"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
"cpu": "atmega328p",
|
"cpu": "atmega328p",
|
||||||
"build-tags": ["atmega328p", "atmega", "avr5"],
|
"build-tags": ["atmega328p", "atmega", "avr5"],
|
||||||
"serial": "uart",
|
"serial": "uart",
|
||||||
"linkerscript": "src/device/avr/atmega328p.ld",
|
"linkerscript": "targets/device/avr/atmega328p.ld",
|
||||||
"extra-files": [
|
"extra-files": [
|
||||||
"targets/avr.S",
|
"targets/avr.S",
|
||||||
"src/device/avr/atmega328p.s"
|
"targets/device/avr/atmega328p.s"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,9 +7,9 @@
|
|||||||
"--defsym=_stack_size=512"
|
"--defsym=_stack_size=512"
|
||||||
],
|
],
|
||||||
"serial": "uart",
|
"serial": "uart",
|
||||||
"linkerscript": "src/device/avr/atmega328pb.ld",
|
"linkerscript": "targets/device/avr/atmega328pb.ld",
|
||||||
"extra-files": [
|
"extra-files": [
|
||||||
"targets/avr.S",
|
"targets/avr.S",
|
||||||
"src/device/avr/atmega328pb.s"
|
"targets/device/avr/atmega328pb.s"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
"cpu": "atmega32u4",
|
"cpu": "atmega32u4",
|
||||||
"build-tags": ["atmega32u4", "avr5"],
|
"build-tags": ["atmega32u4", "avr5"],
|
||||||
"serial": "none",
|
"serial": "none",
|
||||||
"linkerscript": "src/device/avr/atmega32u4.ld",
|
"linkerscript": "targets/device/avr/atmega32u4.ld",
|
||||||
"extra-files": [
|
"extra-files": [
|
||||||
"targets/avr.S",
|
"targets/avr.S",
|
||||||
"src/device/avr/atmega32u4.s"
|
"targets/device/avr/atmega32u4.s"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"serial": "usb",
|
"serial": "usb",
|
||||||
"linkerscript": "targets/atsamd21.ld",
|
"linkerscript": "targets/atsamd21.ld",
|
||||||
"extra-files": [
|
"extra-files": [
|
||||||
"src/device/sam/atsamd21e18a.s"
|
"targets/device/sam/atsamd21e18a.s"
|
||||||
],
|
],
|
||||||
"openocd-transport": "swd",
|
"openocd-transport": "swd",
|
||||||
"openocd-target": "at91samdXX"
|
"openocd-target": "at91samdXX"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"serial": "usb",
|
"serial": "usb",
|
||||||
"linkerscript": "targets/atsamd21.ld",
|
"linkerscript": "targets/atsamd21.ld",
|
||||||
"extra-files": [
|
"extra-files": [
|
||||||
"src/device/sam/atsamd21g18a.s"
|
"targets/device/sam/atsamd21g18a.s"
|
||||||
],
|
],
|
||||||
"openocd-transport": "swd",
|
"openocd-transport": "swd",
|
||||||
"openocd-target": "at91samdXX"
|
"openocd-target": "at91samdXX"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"build-tags": ["atsamd51g19a", "atsamd51g19", "atsamd51", "sam"],
|
"build-tags": ["atsamd51g19a", "atsamd51g19", "atsamd51", "sam"],
|
||||||
"linkerscript": "targets/atsamd51.ld",
|
"linkerscript": "targets/atsamd51.ld",
|
||||||
"extra-files": [
|
"extra-files": [
|
||||||
"src/device/sam/atsamd51g19a.s"
|
"targets/device/sam/atsamd51g19a.s"
|
||||||
],
|
],
|
||||||
"openocd-transport": "swd",
|
"openocd-transport": "swd",
|
||||||
"openocd-target": "atsame5x"
|
"openocd-target": "atsame5x"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"build-tags": ["atsamd51j19a", "atsamd51j19", "atsamd51", "sam"],
|
"build-tags": ["atsamd51j19a", "atsamd51j19", "atsamd51", "sam"],
|
||||||
"linkerscript": "targets/atsamd51.ld",
|
"linkerscript": "targets/atsamd51.ld",
|
||||||
"extra-files": [
|
"extra-files": [
|
||||||
"src/device/sam/atsamd51j19a.s"
|
"targets/device/sam/atsamd51j19a.s"
|
||||||
],
|
],
|
||||||
"openocd-transport": "swd",
|
"openocd-transport": "swd",
|
||||||
"openocd-target": "atsame5x"
|
"openocd-target": "atsame5x"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"build-tags": ["sam", "atsamd51", "atsamd51j20", "atsamd51j20a"],
|
"build-tags": ["sam", "atsamd51", "atsamd51j20", "atsamd51j20a"],
|
||||||
"linkerscript": "targets/atsamd51j20a.ld",
|
"linkerscript": "targets/atsamd51j20a.ld",
|
||||||
"extra-files": [
|
"extra-files": [
|
||||||
"src/device/sam/atsamd51j20a.s"
|
"targets/device/sam/atsamd51j20a.s"
|
||||||
],
|
],
|
||||||
"openocd-transport": "swd",
|
"openocd-transport": "swd",
|
||||||
"openocd-target": "atsame5x"
|
"openocd-target": "atsame5x"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"build-tags": ["atsamd51p19a", "atsamd51p19", "atsamd51", "sam"],
|
"build-tags": ["atsamd51p19a", "atsamd51p19", "atsamd51", "sam"],
|
||||||
"linkerscript": "targets/atsamd51.ld",
|
"linkerscript": "targets/atsamd51.ld",
|
||||||
"extra-files": [
|
"extra-files": [
|
||||||
"src/device/sam/atsamd51p19a.s"
|
"targets/device/sam/atsamd51p19a.s"
|
||||||
],
|
],
|
||||||
"openocd-transport": "swd",
|
"openocd-transport": "swd",
|
||||||
"openocd-target": "atsame5x"
|
"openocd-target": "atsame5x"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"build-tags": ["sam", "atsamd51", "atsamd51p20", "atsamd51p20a"],
|
"build-tags": ["sam", "atsamd51", "atsamd51p20", "atsamd51p20a"],
|
||||||
"linkerscript": "targets/atsamd51p20a.ld",
|
"linkerscript": "targets/atsamd51p20a.ld",
|
||||||
"extra-files": [
|
"extra-files": [
|
||||||
"src/device/sam/atsamd51p20a.s"
|
"targets/device/sam/atsamd51p20a.s"
|
||||||
],
|
],
|
||||||
"openocd-transport": "swd",
|
"openocd-transport": "swd",
|
||||||
"openocd-target": "atsame5x"
|
"openocd-target": "atsame5x"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"build-tags": ["atsame51j19a", "atsame51j19", "atsame51", "atsame5x", "sam"],
|
"build-tags": ["atsame51j19a", "atsame51j19", "atsame51", "atsame5x", "sam"],
|
||||||
"linkerscript": "targets/atsame5xx19.ld",
|
"linkerscript": "targets/atsame5xx19.ld",
|
||||||
"extra-files": [
|
"extra-files": [
|
||||||
"src/device/sam/atsame51j19a.s"
|
"targets/device/sam/atsame51j19a.s"
|
||||||
],
|
],
|
||||||
"openocd-transport": "swd",
|
"openocd-transport": "swd",
|
||||||
"openocd-target": "atsame5x"
|
"openocd-target": "atsame5x"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"build-tags": ["sam", "atsame5x", "atsame54", "atsame54p20", "atsame54p20a"],
|
"build-tags": ["sam", "atsame5x", "atsame54", "atsame54p20", "atsame54p20a"],
|
||||||
"linkerscript": "targets/atsame5xx20-no-bootloader.ld",
|
"linkerscript": "targets/atsame5xx20-no-bootloader.ld",
|
||||||
"extra-files": [
|
"extra-files": [
|
||||||
"src/device/sam/atsame54p20a.s"
|
"targets/device/sam/atsame54p20a.s"
|
||||||
],
|
],
|
||||||
"openocd-transport": "swd",
|
"openocd-transport": "swd",
|
||||||
"openocd-target": "atsame5x"
|
"openocd-target": "atsame5x"
|
||||||
|
|||||||
@@ -6,9 +6,9 @@
|
|||||||
"cflags": [
|
"cflags": [
|
||||||
"-D__AVR_ARCH__=103"
|
"-D__AVR_ARCH__=103"
|
||||||
],
|
],
|
||||||
"linkerscript": "src/device/avr/attiny1616.ld",
|
"linkerscript": "targets/device/avr/attiny1616.ld",
|
||||||
"extra-files": [
|
"extra-files": [
|
||||||
"src/device/avr/attiny1616.s"
|
"targets/device/avr/attiny1616.s"
|
||||||
],
|
],
|
||||||
"flash-command": "pymcuprog write -f {hex} --erase --verify -d attiny1616 -t uart -u {port}"
|
"flash-command": "pymcuprog write -f {hex} --erase --verify -d attiny1616 -t uart -u {port}"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,9 +5,9 @@
|
|||||||
"cflags": [
|
"cflags": [
|
||||||
"-D__AVR_ARCH__=25"
|
"-D__AVR_ARCH__=25"
|
||||||
],
|
],
|
||||||
"linkerscript": "src/device/avr/attiny85.ld",
|
"linkerscript": "targets/device/avr/attiny85.ld",
|
||||||
"extra-files": [
|
"extra-files": [
|
||||||
"targets/avr.S",
|
"targets/avr.S",
|
||||||
"src/device/avr/attiny85.s"
|
"targets/device/avr/attiny85.s"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,9 +16,5 @@
|
|||||||
"-T", "targets/avr.ld",
|
"-T", "targets/avr.ld",
|
||||||
"--gc-sections"
|
"--gc-sections"
|
||||||
],
|
],
|
||||||
"extra-files": [
|
|
||||||
"src/internal/task/task_stack_avr.S",
|
|
||||||
"src/runtime/asm_avr.S"
|
|
||||||
],
|
|
||||||
"gdb": ["avr-gdb"]
|
"gdb": ["avr-gdb"]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,8 +17,6 @@
|
|||||||
"--gc-sections"
|
"--gc-sections"
|
||||||
],
|
],
|
||||||
"extra-files": [
|
"extra-files": [
|
||||||
"src/internal/task/task_stack_avr.S",
|
|
||||||
"src/runtime/asm_avr.S",
|
|
||||||
"targets/avrtiny.S"
|
"targets/avrtiny.S"
|
||||||
],
|
],
|
||||||
"gdb": ["avr-gdb"]
|
"gdb": ["avr-gdb"]
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"serial": "uart",
|
"serial": "uart",
|
||||||
"linkerscript": "targets/stm32.ld",
|
"linkerscript": "targets/stm32.ld",
|
||||||
"extra-files": [
|
"extra-files": [
|
||||||
"src/device/stm32/stm32f103.s"
|
"targets/device/stm32/stm32f103.s"
|
||||||
],
|
],
|
||||||
"flash-method": "openocd",
|
"flash-method": "openocd",
|
||||||
"openocd-interface": "stlink-v2",
|
"openocd-interface": "stlink-v2",
|
||||||
|
|||||||
@@ -22,9 +22,7 @@
|
|||||||
"--gc-sections"
|
"--gc-sections"
|
||||||
],
|
],
|
||||||
"extra-files": [
|
"extra-files": [
|
||||||
"src/device/arm/cortexm.S",
|
"targets/device/arm/cortexm.S"
|
||||||
"src/internal/task/task_stack_cortexm.S",
|
|
||||||
"src/runtime/asm_arm.S"
|
|
||||||
],
|
],
|
||||||
"gdb": ["gdb-multiarch", "arm-none-eabi-gdb", "gdb"]
|
"gdb": ["gdb-multiarch", "arm-none-eabi-gdb", "gdb"]
|
||||||
}
|
}
|
||||||
|
|||||||
37
targets/device/arm/cortexm.S
Normal file
37
targets/device/arm/cortexm.S
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
.syntax unified
|
||||||
|
.cfi_sections .debug_frame
|
||||||
|
|
||||||
|
.section .text.HardFault_Handler
|
||||||
|
.global HardFault_Handler
|
||||||
|
.type HardFault_Handler, %function
|
||||||
|
HardFault_Handler:
|
||||||
|
.cfi_startproc
|
||||||
|
// Put the old stack pointer in the first argument, for easy debugging. This
|
||||||
|
// is especially useful on Cortex-M0, which supports far fewer debug
|
||||||
|
// facilities.
|
||||||
|
mov r0, sp
|
||||||
|
|
||||||
|
// Load the default stack pointer from address 0 so that we can call normal
|
||||||
|
// functions again that expect a working stack. However, it will corrupt the
|
||||||
|
// old stack so the function below must not attempt to recover from this
|
||||||
|
// fault.
|
||||||
|
movs r3, #0
|
||||||
|
ldr r3, [r3]
|
||||||
|
mov sp, r3
|
||||||
|
|
||||||
|
// Continue handling this error in Go.
|
||||||
|
bl handleHardFault
|
||||||
|
.cfi_endproc
|
||||||
|
.size HardFault_Handler, .-HardFault_Handler
|
||||||
|
|
||||||
|
// This is a convenience function for semihosting support.
|
||||||
|
// At some point, this should be replaced by inline assembly.
|
||||||
|
.section .text.SemihostingCall
|
||||||
|
.global SemihostingCall
|
||||||
|
.type SemihostingCall, %function
|
||||||
|
SemihostingCall:
|
||||||
|
.cfi_startproc
|
||||||
|
bkpt 0xab
|
||||||
|
bx lr
|
||||||
|
.cfi_endproc
|
||||||
|
.size SemihostingCall, .-SemihostingCall
|
||||||
22
targets/device/arm/interrupts.c
Normal file
22
targets/device/arm/interrupts.c
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
void EnableInterrupts(uintptr_t mask) {
|
||||||
|
asm volatile(
|
||||||
|
"msr PRIMASK, %0"
|
||||||
|
:
|
||||||
|
: "r"(mask)
|
||||||
|
: "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t DisableInterrupts() {
|
||||||
|
uintptr_t mask;
|
||||||
|
asm volatile(
|
||||||
|
"mrs %0, PRIMASK\n\t"
|
||||||
|
"cpsid i"
|
||||||
|
: "=r"(mask)
|
||||||
|
:
|
||||||
|
: "memory"
|
||||||
|
);
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
7
targets/device/avr/at90can128.ld
Normal file
7
targets/device/avr/at90can128.ld
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
/* Automatically generated file. DO NOT EDIT. */
|
||||||
|
/* Generated by gen-device-avr.go from AT90CAN128.atdf, see http://packs.download.atmel.com/ */
|
||||||
|
|
||||||
|
__flash_size = 0x20000;
|
||||||
|
__ram_start = 0x100;
|
||||||
|
__ram_size = 0x1000;
|
||||||
|
__num_isrs = 37;
|
||||||
98
targets/device/avr/at90can128.s
Normal file
98
targets/device/avr/at90can128.s
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
; Automatically generated file. DO NOT EDIT.
|
||||||
|
; Generated by gen-device-avr.go from AT90CAN128.atdf, see http://packs.download.atmel.com/
|
||||||
|
|
||||||
|
; This is the default handler for interrupts, if triggered but not defined.
|
||||||
|
; Sleep inside so that an accidentally triggered interrupt won't drain the
|
||||||
|
; battery of a battery-powered device.
|
||||||
|
.section .text.__vector_default
|
||||||
|
.global __vector_default
|
||||||
|
__vector_default:
|
||||||
|
sleep
|
||||||
|
rjmp __vector_default
|
||||||
|
|
||||||
|
; Avoid the need for repeated .weak and .set instructions.
|
||||||
|
.macro IRQ handler
|
||||||
|
.weak \handler
|
||||||
|
.set \handler, __vector_default
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; The interrupt vector of this device. Must be placed at address 0 by the linker.
|
||||||
|
.section .vectors, "a", %progbits
|
||||||
|
.global __vectors
|
||||||
|
jmp __vector_RESET
|
||||||
|
jmp __vector_INT0
|
||||||
|
jmp __vector_INT1
|
||||||
|
jmp __vector_INT2
|
||||||
|
jmp __vector_INT3
|
||||||
|
jmp __vector_INT4
|
||||||
|
jmp __vector_INT5
|
||||||
|
jmp __vector_INT6
|
||||||
|
jmp __vector_INT7
|
||||||
|
jmp __vector_TIMER2_COMP
|
||||||
|
jmp __vector_TIMER2_OVF
|
||||||
|
jmp __vector_TIMER1_CAPT
|
||||||
|
jmp __vector_TIMER1_COMPA
|
||||||
|
jmp __vector_TIMER1_COMPB
|
||||||
|
jmp __vector_TIMER1_COMPC
|
||||||
|
jmp __vector_TIMER1_OVF
|
||||||
|
jmp __vector_TIMER0_COMP
|
||||||
|
jmp __vector_TIMER0_OVF
|
||||||
|
jmp __vector_CANIT
|
||||||
|
jmp __vector_OVRIT
|
||||||
|
jmp __vector_SPI_STC
|
||||||
|
jmp __vector_USART0_RX
|
||||||
|
jmp __vector_USART0_UDRE
|
||||||
|
jmp __vector_USART0_TX
|
||||||
|
jmp __vector_ANALOG_COMP
|
||||||
|
jmp __vector_ADC
|
||||||
|
jmp __vector_EE_READY
|
||||||
|
jmp __vector_TIMER3_CAPT
|
||||||
|
jmp __vector_TIMER3_COMPA
|
||||||
|
jmp __vector_TIMER3_COMPB
|
||||||
|
jmp __vector_TIMER3_COMPC
|
||||||
|
jmp __vector_TIMER3_OVF
|
||||||
|
jmp __vector_USART1_RX
|
||||||
|
jmp __vector_USART1_UDRE
|
||||||
|
jmp __vector_USART1_TX
|
||||||
|
jmp __vector_TWI
|
||||||
|
jmp __vector_SPM_READY
|
||||||
|
|
||||||
|
; Define default implementations for interrupts, redirecting to
|
||||||
|
; __vector_default when not implemented.
|
||||||
|
IRQ __vector_RESET
|
||||||
|
IRQ __vector_INT0
|
||||||
|
IRQ __vector_INT1
|
||||||
|
IRQ __vector_INT2
|
||||||
|
IRQ __vector_INT3
|
||||||
|
IRQ __vector_INT4
|
||||||
|
IRQ __vector_INT5
|
||||||
|
IRQ __vector_INT6
|
||||||
|
IRQ __vector_INT7
|
||||||
|
IRQ __vector_TIMER2_COMP
|
||||||
|
IRQ __vector_TIMER2_OVF
|
||||||
|
IRQ __vector_TIMER1_CAPT
|
||||||
|
IRQ __vector_TIMER1_COMPA
|
||||||
|
IRQ __vector_TIMER1_COMPB
|
||||||
|
IRQ __vector_TIMER1_COMPC
|
||||||
|
IRQ __vector_TIMER1_OVF
|
||||||
|
IRQ __vector_TIMER0_COMP
|
||||||
|
IRQ __vector_TIMER0_OVF
|
||||||
|
IRQ __vector_CANIT
|
||||||
|
IRQ __vector_OVRIT
|
||||||
|
IRQ __vector_SPI_STC
|
||||||
|
IRQ __vector_USART0_RX
|
||||||
|
IRQ __vector_USART0_UDRE
|
||||||
|
IRQ __vector_USART0_TX
|
||||||
|
IRQ __vector_ANALOG_COMP
|
||||||
|
IRQ __vector_ADC
|
||||||
|
IRQ __vector_EE_READY
|
||||||
|
IRQ __vector_TIMER3_CAPT
|
||||||
|
IRQ __vector_TIMER3_COMPA
|
||||||
|
IRQ __vector_TIMER3_COMPB
|
||||||
|
IRQ __vector_TIMER3_COMPC
|
||||||
|
IRQ __vector_TIMER3_OVF
|
||||||
|
IRQ __vector_USART1_RX
|
||||||
|
IRQ __vector_USART1_UDRE
|
||||||
|
IRQ __vector_USART1_TX
|
||||||
|
IRQ __vector_TWI
|
||||||
|
IRQ __vector_SPM_READY
|
||||||
7
targets/device/avr/at90can32.ld
Normal file
7
targets/device/avr/at90can32.ld
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
/* Automatically generated file. DO NOT EDIT. */
|
||||||
|
/* Generated by gen-device-avr.go from AT90CAN32.atdf, see http://packs.download.atmel.com/ */
|
||||||
|
|
||||||
|
__flash_size = 0x8000;
|
||||||
|
__ram_start = 0x100;
|
||||||
|
__ram_size = 0x800;
|
||||||
|
__num_isrs = 37;
|
||||||
98
targets/device/avr/at90can32.s
Normal file
98
targets/device/avr/at90can32.s
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
; Automatically generated file. DO NOT EDIT.
|
||||||
|
; Generated by gen-device-avr.go from AT90CAN32.atdf, see http://packs.download.atmel.com/
|
||||||
|
|
||||||
|
; This is the default handler for interrupts, if triggered but not defined.
|
||||||
|
; Sleep inside so that an accidentally triggered interrupt won't drain the
|
||||||
|
; battery of a battery-powered device.
|
||||||
|
.section .text.__vector_default
|
||||||
|
.global __vector_default
|
||||||
|
__vector_default:
|
||||||
|
sleep
|
||||||
|
rjmp __vector_default
|
||||||
|
|
||||||
|
; Avoid the need for repeated .weak and .set instructions.
|
||||||
|
.macro IRQ handler
|
||||||
|
.weak \handler
|
||||||
|
.set \handler, __vector_default
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; The interrupt vector of this device. Must be placed at address 0 by the linker.
|
||||||
|
.section .vectors, "a", %progbits
|
||||||
|
.global __vectors
|
||||||
|
jmp __vector_RESET
|
||||||
|
jmp __vector_INT0
|
||||||
|
jmp __vector_INT1
|
||||||
|
jmp __vector_INT2
|
||||||
|
jmp __vector_INT3
|
||||||
|
jmp __vector_INT4
|
||||||
|
jmp __vector_INT5
|
||||||
|
jmp __vector_INT6
|
||||||
|
jmp __vector_INT7
|
||||||
|
jmp __vector_TIMER2_COMP
|
||||||
|
jmp __vector_TIMER2_OVF
|
||||||
|
jmp __vector_TIMER1_CAPT
|
||||||
|
jmp __vector_TIMER1_COMPA
|
||||||
|
jmp __vector_TIMER1_COMPB
|
||||||
|
jmp __vector_TIMER1_COMPC
|
||||||
|
jmp __vector_TIMER1_OVF
|
||||||
|
jmp __vector_TIMER0_COMP
|
||||||
|
jmp __vector_TIMER0_OVF
|
||||||
|
jmp __vector_CANIT
|
||||||
|
jmp __vector_OVRIT
|
||||||
|
jmp __vector_SPI_STC
|
||||||
|
jmp __vector_USART0_RX
|
||||||
|
jmp __vector_USART0_UDRE
|
||||||
|
jmp __vector_USART0_TX
|
||||||
|
jmp __vector_ANALOG_COMP
|
||||||
|
jmp __vector_ADC
|
||||||
|
jmp __vector_EE_READY
|
||||||
|
jmp __vector_TIMER3_CAPT
|
||||||
|
jmp __vector_TIMER3_COMPA
|
||||||
|
jmp __vector_TIMER3_COMPB
|
||||||
|
jmp __vector_TIMER3_COMPC
|
||||||
|
jmp __vector_TIMER3_OVF
|
||||||
|
jmp __vector_USART1_RX
|
||||||
|
jmp __vector_USART1_UDRE
|
||||||
|
jmp __vector_USART1_TX
|
||||||
|
jmp __vector_TWI
|
||||||
|
jmp __vector_SPM_READY
|
||||||
|
|
||||||
|
; Define default implementations for interrupts, redirecting to
|
||||||
|
; __vector_default when not implemented.
|
||||||
|
IRQ __vector_RESET
|
||||||
|
IRQ __vector_INT0
|
||||||
|
IRQ __vector_INT1
|
||||||
|
IRQ __vector_INT2
|
||||||
|
IRQ __vector_INT3
|
||||||
|
IRQ __vector_INT4
|
||||||
|
IRQ __vector_INT5
|
||||||
|
IRQ __vector_INT6
|
||||||
|
IRQ __vector_INT7
|
||||||
|
IRQ __vector_TIMER2_COMP
|
||||||
|
IRQ __vector_TIMER2_OVF
|
||||||
|
IRQ __vector_TIMER1_CAPT
|
||||||
|
IRQ __vector_TIMER1_COMPA
|
||||||
|
IRQ __vector_TIMER1_COMPB
|
||||||
|
IRQ __vector_TIMER1_COMPC
|
||||||
|
IRQ __vector_TIMER1_OVF
|
||||||
|
IRQ __vector_TIMER0_COMP
|
||||||
|
IRQ __vector_TIMER0_OVF
|
||||||
|
IRQ __vector_CANIT
|
||||||
|
IRQ __vector_OVRIT
|
||||||
|
IRQ __vector_SPI_STC
|
||||||
|
IRQ __vector_USART0_RX
|
||||||
|
IRQ __vector_USART0_UDRE
|
||||||
|
IRQ __vector_USART0_TX
|
||||||
|
IRQ __vector_ANALOG_COMP
|
||||||
|
IRQ __vector_ADC
|
||||||
|
IRQ __vector_EE_READY
|
||||||
|
IRQ __vector_TIMER3_CAPT
|
||||||
|
IRQ __vector_TIMER3_COMPA
|
||||||
|
IRQ __vector_TIMER3_COMPB
|
||||||
|
IRQ __vector_TIMER3_COMPC
|
||||||
|
IRQ __vector_TIMER3_OVF
|
||||||
|
IRQ __vector_USART1_RX
|
||||||
|
IRQ __vector_USART1_UDRE
|
||||||
|
IRQ __vector_USART1_TX
|
||||||
|
IRQ __vector_TWI
|
||||||
|
IRQ __vector_SPM_READY
|
||||||
7
targets/device/avr/at90can64.ld
Normal file
7
targets/device/avr/at90can64.ld
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
/* Automatically generated file. DO NOT EDIT. */
|
||||||
|
/* Generated by gen-device-avr.go from AT90CAN64.atdf, see http://packs.download.atmel.com/ */
|
||||||
|
|
||||||
|
__flash_size = 0x10000;
|
||||||
|
__ram_start = 0x100;
|
||||||
|
__ram_size = 0x1000;
|
||||||
|
__num_isrs = 37;
|
||||||
98
targets/device/avr/at90can64.s
Normal file
98
targets/device/avr/at90can64.s
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
; Automatically generated file. DO NOT EDIT.
|
||||||
|
; Generated by gen-device-avr.go from AT90CAN64.atdf, see http://packs.download.atmel.com/
|
||||||
|
|
||||||
|
; This is the default handler for interrupts, if triggered but not defined.
|
||||||
|
; Sleep inside so that an accidentally triggered interrupt won't drain the
|
||||||
|
; battery of a battery-powered device.
|
||||||
|
.section .text.__vector_default
|
||||||
|
.global __vector_default
|
||||||
|
__vector_default:
|
||||||
|
sleep
|
||||||
|
rjmp __vector_default
|
||||||
|
|
||||||
|
; Avoid the need for repeated .weak and .set instructions.
|
||||||
|
.macro IRQ handler
|
||||||
|
.weak \handler
|
||||||
|
.set \handler, __vector_default
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; The interrupt vector of this device. Must be placed at address 0 by the linker.
|
||||||
|
.section .vectors, "a", %progbits
|
||||||
|
.global __vectors
|
||||||
|
jmp __vector_RESET
|
||||||
|
jmp __vector_INT0
|
||||||
|
jmp __vector_INT1
|
||||||
|
jmp __vector_INT2
|
||||||
|
jmp __vector_INT3
|
||||||
|
jmp __vector_INT4
|
||||||
|
jmp __vector_INT5
|
||||||
|
jmp __vector_INT6
|
||||||
|
jmp __vector_INT7
|
||||||
|
jmp __vector_TIMER2_COMP
|
||||||
|
jmp __vector_TIMER2_OVF
|
||||||
|
jmp __vector_TIMER1_CAPT
|
||||||
|
jmp __vector_TIMER1_COMPA
|
||||||
|
jmp __vector_TIMER1_COMPB
|
||||||
|
jmp __vector_TIMER1_COMPC
|
||||||
|
jmp __vector_TIMER1_OVF
|
||||||
|
jmp __vector_TIMER0_COMP
|
||||||
|
jmp __vector_TIMER0_OVF
|
||||||
|
jmp __vector_CANIT
|
||||||
|
jmp __vector_OVRIT
|
||||||
|
jmp __vector_SPI_STC
|
||||||
|
jmp __vector_USART0_RX
|
||||||
|
jmp __vector_USART0_UDRE
|
||||||
|
jmp __vector_USART0_TX
|
||||||
|
jmp __vector_ANALOG_COMP
|
||||||
|
jmp __vector_ADC
|
||||||
|
jmp __vector_EE_READY
|
||||||
|
jmp __vector_TIMER3_CAPT
|
||||||
|
jmp __vector_TIMER3_COMPA
|
||||||
|
jmp __vector_TIMER3_COMPB
|
||||||
|
jmp __vector_TIMER3_COMPC
|
||||||
|
jmp __vector_TIMER3_OVF
|
||||||
|
jmp __vector_USART1_RX
|
||||||
|
jmp __vector_USART1_UDRE
|
||||||
|
jmp __vector_USART1_TX
|
||||||
|
jmp __vector_TWI
|
||||||
|
jmp __vector_SPM_READY
|
||||||
|
|
||||||
|
; Define default implementations for interrupts, redirecting to
|
||||||
|
; __vector_default when not implemented.
|
||||||
|
IRQ __vector_RESET
|
||||||
|
IRQ __vector_INT0
|
||||||
|
IRQ __vector_INT1
|
||||||
|
IRQ __vector_INT2
|
||||||
|
IRQ __vector_INT3
|
||||||
|
IRQ __vector_INT4
|
||||||
|
IRQ __vector_INT5
|
||||||
|
IRQ __vector_INT6
|
||||||
|
IRQ __vector_INT7
|
||||||
|
IRQ __vector_TIMER2_COMP
|
||||||
|
IRQ __vector_TIMER2_OVF
|
||||||
|
IRQ __vector_TIMER1_CAPT
|
||||||
|
IRQ __vector_TIMER1_COMPA
|
||||||
|
IRQ __vector_TIMER1_COMPB
|
||||||
|
IRQ __vector_TIMER1_COMPC
|
||||||
|
IRQ __vector_TIMER1_OVF
|
||||||
|
IRQ __vector_TIMER0_COMP
|
||||||
|
IRQ __vector_TIMER0_OVF
|
||||||
|
IRQ __vector_CANIT
|
||||||
|
IRQ __vector_OVRIT
|
||||||
|
IRQ __vector_SPI_STC
|
||||||
|
IRQ __vector_USART0_RX
|
||||||
|
IRQ __vector_USART0_UDRE
|
||||||
|
IRQ __vector_USART0_TX
|
||||||
|
IRQ __vector_ANALOG_COMP
|
||||||
|
IRQ __vector_ADC
|
||||||
|
IRQ __vector_EE_READY
|
||||||
|
IRQ __vector_TIMER3_CAPT
|
||||||
|
IRQ __vector_TIMER3_COMPA
|
||||||
|
IRQ __vector_TIMER3_COMPB
|
||||||
|
IRQ __vector_TIMER3_COMPC
|
||||||
|
IRQ __vector_TIMER3_OVF
|
||||||
|
IRQ __vector_USART1_RX
|
||||||
|
IRQ __vector_USART1_UDRE
|
||||||
|
IRQ __vector_USART1_TX
|
||||||
|
IRQ __vector_TWI
|
||||||
|
IRQ __vector_SPM_READY
|
||||||
7
targets/device/avr/at90pwm1.ld
Normal file
7
targets/device/avr/at90pwm1.ld
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
/* Automatically generated file. DO NOT EDIT. */
|
||||||
|
/* Generated by gen-device-avr.go from AT90PWM1.atdf, see http://packs.download.atmel.com/ */
|
||||||
|
|
||||||
|
__flash_size = 0x2000;
|
||||||
|
__ram_start = 0x100;
|
||||||
|
__ram_size = 0x200;
|
||||||
|
__num_isrs = 32;
|
||||||
88
targets/device/avr/at90pwm1.s
Normal file
88
targets/device/avr/at90pwm1.s
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
; Automatically generated file. DO NOT EDIT.
|
||||||
|
; Generated by gen-device-avr.go from AT90PWM1.atdf, see http://packs.download.atmel.com/
|
||||||
|
|
||||||
|
; This is the default handler for interrupts, if triggered but not defined.
|
||||||
|
; Sleep inside so that an accidentally triggered interrupt won't drain the
|
||||||
|
; battery of a battery-powered device.
|
||||||
|
.section .text.__vector_default
|
||||||
|
.global __vector_default
|
||||||
|
__vector_default:
|
||||||
|
sleep
|
||||||
|
rjmp __vector_default
|
||||||
|
|
||||||
|
; Avoid the need for repeated .weak and .set instructions.
|
||||||
|
.macro IRQ handler
|
||||||
|
.weak \handler
|
||||||
|
.set \handler, __vector_default
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; The interrupt vector of this device. Must be placed at address 0 by the linker.
|
||||||
|
.section .vectors, "a", %progbits
|
||||||
|
.global __vectors
|
||||||
|
rjmp __vector_RESET
|
||||||
|
rjmp __vector_PSC2_CAPT
|
||||||
|
rjmp __vector_PSC2_EC
|
||||||
|
rjmp __vector_PSC1_CAPT
|
||||||
|
rjmp __vector_PSC1_EC
|
||||||
|
rjmp __vector_PSC0_CAPT
|
||||||
|
rjmp __vector_PSC0_EC
|
||||||
|
rjmp __vector_ANALOG_COMP_0
|
||||||
|
rjmp __vector_ANALOG_COMP_1
|
||||||
|
rjmp __vector_ANALOG_COMP_2
|
||||||
|
rjmp __vector_INT0
|
||||||
|
rjmp __vector_TIMER1_CAPT
|
||||||
|
rjmp __vector_TIMER1_COMPA
|
||||||
|
rjmp __vector_TIMER1_COMPB
|
||||||
|
rjmp __vector_RESERVED15
|
||||||
|
rjmp __vector_TIMER1_OVF
|
||||||
|
rjmp __vector_TIMER0_COMP_A
|
||||||
|
rjmp __vector_TIMER0_OVF
|
||||||
|
rjmp __vector_ADC
|
||||||
|
rjmp __vector_INT1
|
||||||
|
rjmp __vector_SPI_STC
|
||||||
|
rjmp __vector_USART_RX
|
||||||
|
rjmp __vector_USART_UDRE
|
||||||
|
rjmp __vector_USART_TX
|
||||||
|
rjmp __vector_INT2
|
||||||
|
rjmp __vector_WDT
|
||||||
|
rjmp __vector_EE_READY
|
||||||
|
rjmp __vector_TIMER0_COMPB
|
||||||
|
rjmp __vector_INT3
|
||||||
|
rjmp __vector_RESERVED30
|
||||||
|
rjmp __vector_RESERVED31
|
||||||
|
rjmp __vector_SPM_READY
|
||||||
|
|
||||||
|
; Define default implementations for interrupts, redirecting to
|
||||||
|
; __vector_default when not implemented.
|
||||||
|
IRQ __vector_RESET
|
||||||
|
IRQ __vector_PSC2_CAPT
|
||||||
|
IRQ __vector_PSC2_EC
|
||||||
|
IRQ __vector_PSC1_CAPT
|
||||||
|
IRQ __vector_PSC1_EC
|
||||||
|
IRQ __vector_PSC0_CAPT
|
||||||
|
IRQ __vector_PSC0_EC
|
||||||
|
IRQ __vector_ANALOG_COMP_0
|
||||||
|
IRQ __vector_ANALOG_COMP_1
|
||||||
|
IRQ __vector_ANALOG_COMP_2
|
||||||
|
IRQ __vector_INT0
|
||||||
|
IRQ __vector_TIMER1_CAPT
|
||||||
|
IRQ __vector_TIMER1_COMPA
|
||||||
|
IRQ __vector_TIMER1_COMPB
|
||||||
|
IRQ __vector_RESERVED15
|
||||||
|
IRQ __vector_TIMER1_OVF
|
||||||
|
IRQ __vector_TIMER0_COMP_A
|
||||||
|
IRQ __vector_TIMER0_OVF
|
||||||
|
IRQ __vector_ADC
|
||||||
|
IRQ __vector_INT1
|
||||||
|
IRQ __vector_SPI_STC
|
||||||
|
IRQ __vector_USART_RX
|
||||||
|
IRQ __vector_USART_UDRE
|
||||||
|
IRQ __vector_USART_TX
|
||||||
|
IRQ __vector_INT2
|
||||||
|
IRQ __vector_WDT
|
||||||
|
IRQ __vector_EE_READY
|
||||||
|
IRQ __vector_TIMER0_COMPB
|
||||||
|
IRQ __vector_INT3
|
||||||
|
IRQ __vector_RESERVED30
|
||||||
|
IRQ __vector_RESERVED31
|
||||||
|
IRQ __vector_SPM_READY
|
||||||
7
targets/device/avr/at90pwm161.ld
Normal file
7
targets/device/avr/at90pwm161.ld
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
/* Automatically generated file. DO NOT EDIT. */
|
||||||
|
/* Generated by gen-device-avr.go from AT90PWM161.atdf, see http://packs.download.atmel.com/ */
|
||||||
|
|
||||||
|
__flash_size = 0x4000;
|
||||||
|
__ram_start = 0x100;
|
||||||
|
__ram_size = 0x400;
|
||||||
|
__num_isrs = 20;
|
||||||
64
targets/device/avr/at90pwm161.s
Normal file
64
targets/device/avr/at90pwm161.s
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
; Automatically generated file. DO NOT EDIT.
|
||||||
|
; Generated by gen-device-avr.go from AT90PWM161.atdf, see http://packs.download.atmel.com/
|
||||||
|
|
||||||
|
; This is the default handler for interrupts, if triggered but not defined.
|
||||||
|
; Sleep inside so that an accidentally triggered interrupt won't drain the
|
||||||
|
; battery of a battery-powered device.
|
||||||
|
.section .text.__vector_default
|
||||||
|
.global __vector_default
|
||||||
|
__vector_default:
|
||||||
|
sleep
|
||||||
|
rjmp __vector_default
|
||||||
|
|
||||||
|
; Avoid the need for repeated .weak and .set instructions.
|
||||||
|
.macro IRQ handler
|
||||||
|
.weak \handler
|
||||||
|
.set \handler, __vector_default
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; The interrupt vector of this device. Must be placed at address 0 by the linker.
|
||||||
|
.section .vectors, "a", %progbits
|
||||||
|
.global __vectors
|
||||||
|
jmp __vector_RESET
|
||||||
|
jmp __vector_PSC2_CAPT
|
||||||
|
jmp __vector_PSC2_EC
|
||||||
|
jmp __vector_PSC2_EEC
|
||||||
|
jmp __vector_PSC0_CAPT
|
||||||
|
jmp __vector_PSC0_EC
|
||||||
|
jmp __vector_PSC0_EEC
|
||||||
|
jmp __vector_ANALOG_COMP_1
|
||||||
|
jmp __vector_ANALOG_COMP_2
|
||||||
|
jmp __vector_ANALOG_COMP_3
|
||||||
|
jmp __vector_INT0
|
||||||
|
jmp __vector_TIMER1_CAPT
|
||||||
|
jmp __vector_TIMER1_OVF
|
||||||
|
jmp __vector_ADC
|
||||||
|
jmp __vector_INT1
|
||||||
|
jmp __vector_SPI_STC
|
||||||
|
jmp __vector_INT2
|
||||||
|
jmp __vector_WDT
|
||||||
|
jmp __vector_EE_READY
|
||||||
|
jmp __vector_SPM_READY
|
||||||
|
|
||||||
|
; Define default implementations for interrupts, redirecting to
|
||||||
|
; __vector_default when not implemented.
|
||||||
|
IRQ __vector_RESET
|
||||||
|
IRQ __vector_PSC2_CAPT
|
||||||
|
IRQ __vector_PSC2_EC
|
||||||
|
IRQ __vector_PSC2_EEC
|
||||||
|
IRQ __vector_PSC0_CAPT
|
||||||
|
IRQ __vector_PSC0_EC
|
||||||
|
IRQ __vector_PSC0_EEC
|
||||||
|
IRQ __vector_ANALOG_COMP_1
|
||||||
|
IRQ __vector_ANALOG_COMP_2
|
||||||
|
IRQ __vector_ANALOG_COMP_3
|
||||||
|
IRQ __vector_INT0
|
||||||
|
IRQ __vector_TIMER1_CAPT
|
||||||
|
IRQ __vector_TIMER1_OVF
|
||||||
|
IRQ __vector_ADC
|
||||||
|
IRQ __vector_INT1
|
||||||
|
IRQ __vector_SPI_STC
|
||||||
|
IRQ __vector_INT2
|
||||||
|
IRQ __vector_WDT
|
||||||
|
IRQ __vector_EE_READY
|
||||||
|
IRQ __vector_SPM_READY
|
||||||
7
targets/device/avr/at90pwm216.ld
Normal file
7
targets/device/avr/at90pwm216.ld
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
/* Automatically generated file. DO NOT EDIT. */
|
||||||
|
/* Generated by gen-device-avr.go from AT90PWM216.atdf, see http://packs.download.atmel.com/ */
|
||||||
|
|
||||||
|
__flash_size = 0x4000;
|
||||||
|
__ram_start = 0x100;
|
||||||
|
__ram_size = 0x400;
|
||||||
|
__num_isrs = 32;
|
||||||
88
targets/device/avr/at90pwm216.s
Normal file
88
targets/device/avr/at90pwm216.s
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
; Automatically generated file. DO NOT EDIT.
|
||||||
|
; Generated by gen-device-avr.go from AT90PWM216.atdf, see http://packs.download.atmel.com/
|
||||||
|
|
||||||
|
; This is the default handler for interrupts, if triggered but not defined.
|
||||||
|
; Sleep inside so that an accidentally triggered interrupt won't drain the
|
||||||
|
; battery of a battery-powered device.
|
||||||
|
.section .text.__vector_default
|
||||||
|
.global __vector_default
|
||||||
|
__vector_default:
|
||||||
|
sleep
|
||||||
|
rjmp __vector_default
|
||||||
|
|
||||||
|
; Avoid the need for repeated .weak and .set instructions.
|
||||||
|
.macro IRQ handler
|
||||||
|
.weak \handler
|
||||||
|
.set \handler, __vector_default
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; The interrupt vector of this device. Must be placed at address 0 by the linker.
|
||||||
|
.section .vectors, "a", %progbits
|
||||||
|
.global __vectors
|
||||||
|
jmp __vector_RESET
|
||||||
|
jmp __vector_PSC2_CAPT
|
||||||
|
jmp __vector_PSC2_EC
|
||||||
|
jmp __vector_PSC1_CAPT
|
||||||
|
jmp __vector_PSC1_EC
|
||||||
|
jmp __vector_PSC0_CAPT
|
||||||
|
jmp __vector_PSC0_EC
|
||||||
|
jmp __vector_ANALOG_COMP_0
|
||||||
|
jmp __vector_ANALOG_COMP_1
|
||||||
|
jmp __vector_ANALOG_COMP_2
|
||||||
|
jmp __vector_INT0
|
||||||
|
jmp __vector_TIMER1_CAPT
|
||||||
|
jmp __vector_TIMER1_COMPA
|
||||||
|
jmp __vector_TIMER1_COMPB
|
||||||
|
jmp __vector_RESERVED15
|
||||||
|
jmp __vector_TIMER1_OVF
|
||||||
|
jmp __vector_TIMER0_COMP_A
|
||||||
|
jmp __vector_TIMER0_OVF
|
||||||
|
jmp __vector_ADC
|
||||||
|
jmp __vector_INT1
|
||||||
|
jmp __vector_SPI_STC
|
||||||
|
jmp __vector_USART_RX
|
||||||
|
jmp __vector_USART_UDRE
|
||||||
|
jmp __vector_USART_TX
|
||||||
|
jmp __vector_INT2
|
||||||
|
jmp __vector_WDT
|
||||||
|
jmp __vector_EE_READY
|
||||||
|
jmp __vector_TIMER0_COMPB
|
||||||
|
jmp __vector_INT3
|
||||||
|
jmp __vector_RESERVED30
|
||||||
|
jmp __vector_RESERVED31
|
||||||
|
jmp __vector_SPM_READY
|
||||||
|
|
||||||
|
; Define default implementations for interrupts, redirecting to
|
||||||
|
; __vector_default when not implemented.
|
||||||
|
IRQ __vector_RESET
|
||||||
|
IRQ __vector_PSC2_CAPT
|
||||||
|
IRQ __vector_PSC2_EC
|
||||||
|
IRQ __vector_PSC1_CAPT
|
||||||
|
IRQ __vector_PSC1_EC
|
||||||
|
IRQ __vector_PSC0_CAPT
|
||||||
|
IRQ __vector_PSC0_EC
|
||||||
|
IRQ __vector_ANALOG_COMP_0
|
||||||
|
IRQ __vector_ANALOG_COMP_1
|
||||||
|
IRQ __vector_ANALOG_COMP_2
|
||||||
|
IRQ __vector_INT0
|
||||||
|
IRQ __vector_TIMER1_CAPT
|
||||||
|
IRQ __vector_TIMER1_COMPA
|
||||||
|
IRQ __vector_TIMER1_COMPB
|
||||||
|
IRQ __vector_RESERVED15
|
||||||
|
IRQ __vector_TIMER1_OVF
|
||||||
|
IRQ __vector_TIMER0_COMP_A
|
||||||
|
IRQ __vector_TIMER0_OVF
|
||||||
|
IRQ __vector_ADC
|
||||||
|
IRQ __vector_INT1
|
||||||
|
IRQ __vector_SPI_STC
|
||||||
|
IRQ __vector_USART_RX
|
||||||
|
IRQ __vector_USART_UDRE
|
||||||
|
IRQ __vector_USART_TX
|
||||||
|
IRQ __vector_INT2
|
||||||
|
IRQ __vector_WDT
|
||||||
|
IRQ __vector_EE_READY
|
||||||
|
IRQ __vector_TIMER0_COMPB
|
||||||
|
IRQ __vector_INT3
|
||||||
|
IRQ __vector_RESERVED30
|
||||||
|
IRQ __vector_RESERVED31
|
||||||
|
IRQ __vector_SPM_READY
|
||||||
7
targets/device/avr/at90pwm2b.ld
Normal file
7
targets/device/avr/at90pwm2b.ld
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
/* Automatically generated file. DO NOT EDIT. */
|
||||||
|
/* Generated by gen-device-avr.go from AT90PWM2B.atdf, see http://packs.download.atmel.com/ */
|
||||||
|
|
||||||
|
__flash_size = 0x2000;
|
||||||
|
__ram_start = 0x100;
|
||||||
|
__ram_size = 0x200;
|
||||||
|
__num_isrs = 32;
|
||||||
88
targets/device/avr/at90pwm2b.s
Normal file
88
targets/device/avr/at90pwm2b.s
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
; Automatically generated file. DO NOT EDIT.
|
||||||
|
; Generated by gen-device-avr.go from AT90PWM2B.atdf, see http://packs.download.atmel.com/
|
||||||
|
|
||||||
|
; This is the default handler for interrupts, if triggered but not defined.
|
||||||
|
; Sleep inside so that an accidentally triggered interrupt won't drain the
|
||||||
|
; battery of a battery-powered device.
|
||||||
|
.section .text.__vector_default
|
||||||
|
.global __vector_default
|
||||||
|
__vector_default:
|
||||||
|
sleep
|
||||||
|
rjmp __vector_default
|
||||||
|
|
||||||
|
; Avoid the need for repeated .weak and .set instructions.
|
||||||
|
.macro IRQ handler
|
||||||
|
.weak \handler
|
||||||
|
.set \handler, __vector_default
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; The interrupt vector of this device. Must be placed at address 0 by the linker.
|
||||||
|
.section .vectors, "a", %progbits
|
||||||
|
.global __vectors
|
||||||
|
rjmp __vector_RESET
|
||||||
|
rjmp __vector_PSC2_CAPT
|
||||||
|
rjmp __vector_PSC2_EC
|
||||||
|
rjmp __vector_PSC1_CAPT
|
||||||
|
rjmp __vector_PSC1_EC
|
||||||
|
rjmp __vector_PSC0_CAPT
|
||||||
|
rjmp __vector_PSC0_EC
|
||||||
|
rjmp __vector_ANALOG_COMP_0
|
||||||
|
rjmp __vector_ANALOG_COMP_1
|
||||||
|
rjmp __vector_ANALOG_COMP_2
|
||||||
|
rjmp __vector_INT0
|
||||||
|
rjmp __vector_TIMER1_CAPT
|
||||||
|
rjmp __vector_TIMER1_COMPA
|
||||||
|
rjmp __vector_TIMER1_COMPB
|
||||||
|
rjmp __vector_RESERVED15
|
||||||
|
rjmp __vector_TIMER1_OVF
|
||||||
|
rjmp __vector_TIMER0_COMPA
|
||||||
|
rjmp __vector_TIMER0_OVF
|
||||||
|
rjmp __vector_ADC
|
||||||
|
rjmp __vector_INT1
|
||||||
|
rjmp __vector_SPI_STC
|
||||||
|
rjmp __vector_USART_RX
|
||||||
|
rjmp __vector_USART_UDRE
|
||||||
|
rjmp __vector_USART_TX
|
||||||
|
rjmp __vector_INT2
|
||||||
|
rjmp __vector_WDT
|
||||||
|
rjmp __vector_EE_READY
|
||||||
|
rjmp __vector_TIMER0_COMPB
|
||||||
|
rjmp __vector_INT3
|
||||||
|
rjmp __vector_RESERVED30
|
||||||
|
rjmp __vector_RESERVED31
|
||||||
|
rjmp __vector_SPM_READY
|
||||||
|
|
||||||
|
; Define default implementations for interrupts, redirecting to
|
||||||
|
; __vector_default when not implemented.
|
||||||
|
IRQ __vector_RESET
|
||||||
|
IRQ __vector_PSC2_CAPT
|
||||||
|
IRQ __vector_PSC2_EC
|
||||||
|
IRQ __vector_PSC1_CAPT
|
||||||
|
IRQ __vector_PSC1_EC
|
||||||
|
IRQ __vector_PSC0_CAPT
|
||||||
|
IRQ __vector_PSC0_EC
|
||||||
|
IRQ __vector_ANALOG_COMP_0
|
||||||
|
IRQ __vector_ANALOG_COMP_1
|
||||||
|
IRQ __vector_ANALOG_COMP_2
|
||||||
|
IRQ __vector_INT0
|
||||||
|
IRQ __vector_TIMER1_CAPT
|
||||||
|
IRQ __vector_TIMER1_COMPA
|
||||||
|
IRQ __vector_TIMER1_COMPB
|
||||||
|
IRQ __vector_RESERVED15
|
||||||
|
IRQ __vector_TIMER1_OVF
|
||||||
|
IRQ __vector_TIMER0_COMPA
|
||||||
|
IRQ __vector_TIMER0_OVF
|
||||||
|
IRQ __vector_ADC
|
||||||
|
IRQ __vector_INT1
|
||||||
|
IRQ __vector_SPI_STC
|
||||||
|
IRQ __vector_USART_RX
|
||||||
|
IRQ __vector_USART_UDRE
|
||||||
|
IRQ __vector_USART_TX
|
||||||
|
IRQ __vector_INT2
|
||||||
|
IRQ __vector_WDT
|
||||||
|
IRQ __vector_EE_READY
|
||||||
|
IRQ __vector_TIMER0_COMPB
|
||||||
|
IRQ __vector_INT3
|
||||||
|
IRQ __vector_RESERVED30
|
||||||
|
IRQ __vector_RESERVED31
|
||||||
|
IRQ __vector_SPM_READY
|
||||||
7
targets/device/avr/at90pwm316.ld
Normal file
7
targets/device/avr/at90pwm316.ld
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
/* Automatically generated file. DO NOT EDIT. */
|
||||||
|
/* Generated by gen-device-avr.go from AT90PWM316.atdf, see http://packs.download.atmel.com/ */
|
||||||
|
|
||||||
|
__flash_size = 0x4000;
|
||||||
|
__ram_start = 0x100;
|
||||||
|
__ram_size = 0x400;
|
||||||
|
__num_isrs = 32;
|
||||||
88
targets/device/avr/at90pwm316.s
Normal file
88
targets/device/avr/at90pwm316.s
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
; Automatically generated file. DO NOT EDIT.
|
||||||
|
; Generated by gen-device-avr.go from AT90PWM316.atdf, see http://packs.download.atmel.com/
|
||||||
|
|
||||||
|
; This is the default handler for interrupts, if triggered but not defined.
|
||||||
|
; Sleep inside so that an accidentally triggered interrupt won't drain the
|
||||||
|
; battery of a battery-powered device.
|
||||||
|
.section .text.__vector_default
|
||||||
|
.global __vector_default
|
||||||
|
__vector_default:
|
||||||
|
sleep
|
||||||
|
rjmp __vector_default
|
||||||
|
|
||||||
|
; Avoid the need for repeated .weak and .set instructions.
|
||||||
|
.macro IRQ handler
|
||||||
|
.weak \handler
|
||||||
|
.set \handler, __vector_default
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; The interrupt vector of this device. Must be placed at address 0 by the linker.
|
||||||
|
.section .vectors, "a", %progbits
|
||||||
|
.global __vectors
|
||||||
|
jmp __vector_RESET
|
||||||
|
jmp __vector_PSC2_CAPT
|
||||||
|
jmp __vector_PSC2_EC
|
||||||
|
jmp __vector_PSC1_CAPT
|
||||||
|
jmp __vector_PSC1_EC
|
||||||
|
jmp __vector_PSC0_CAPT
|
||||||
|
jmp __vector_PSC0_EC
|
||||||
|
jmp __vector_ANALOG_COMP_0
|
||||||
|
jmp __vector_ANALOG_COMP_1
|
||||||
|
jmp __vector_ANALOG_COMP_2
|
||||||
|
jmp __vector_INT0
|
||||||
|
jmp __vector_TIMER1_CAPT
|
||||||
|
jmp __vector_TIMER1_COMPA
|
||||||
|
jmp __vector_TIMER1_COMPB
|
||||||
|
jmp __vector_RESERVED15
|
||||||
|
jmp __vector_TIMER1_OVF
|
||||||
|
jmp __vector_TIMER0_COMP_A
|
||||||
|
jmp __vector_TIMER0_OVF
|
||||||
|
jmp __vector_ADC
|
||||||
|
jmp __vector_INT1
|
||||||
|
jmp __vector_SPI_STC
|
||||||
|
jmp __vector_USART_RX
|
||||||
|
jmp __vector_USART_UDRE
|
||||||
|
jmp __vector_USART_TX
|
||||||
|
jmp __vector_INT2
|
||||||
|
jmp __vector_WDT
|
||||||
|
jmp __vector_EE_READY
|
||||||
|
jmp __vector_TIMER0_COMPB
|
||||||
|
jmp __vector_INT3
|
||||||
|
jmp __vector_RESERVED30
|
||||||
|
jmp __vector_RESERVED31
|
||||||
|
jmp __vector_SPM_READY
|
||||||
|
|
||||||
|
; Define default implementations for interrupts, redirecting to
|
||||||
|
; __vector_default when not implemented.
|
||||||
|
IRQ __vector_RESET
|
||||||
|
IRQ __vector_PSC2_CAPT
|
||||||
|
IRQ __vector_PSC2_EC
|
||||||
|
IRQ __vector_PSC1_CAPT
|
||||||
|
IRQ __vector_PSC1_EC
|
||||||
|
IRQ __vector_PSC0_CAPT
|
||||||
|
IRQ __vector_PSC0_EC
|
||||||
|
IRQ __vector_ANALOG_COMP_0
|
||||||
|
IRQ __vector_ANALOG_COMP_1
|
||||||
|
IRQ __vector_ANALOG_COMP_2
|
||||||
|
IRQ __vector_INT0
|
||||||
|
IRQ __vector_TIMER1_CAPT
|
||||||
|
IRQ __vector_TIMER1_COMPA
|
||||||
|
IRQ __vector_TIMER1_COMPB
|
||||||
|
IRQ __vector_RESERVED15
|
||||||
|
IRQ __vector_TIMER1_OVF
|
||||||
|
IRQ __vector_TIMER0_COMP_A
|
||||||
|
IRQ __vector_TIMER0_OVF
|
||||||
|
IRQ __vector_ADC
|
||||||
|
IRQ __vector_INT1
|
||||||
|
IRQ __vector_SPI_STC
|
||||||
|
IRQ __vector_USART_RX
|
||||||
|
IRQ __vector_USART_UDRE
|
||||||
|
IRQ __vector_USART_TX
|
||||||
|
IRQ __vector_INT2
|
||||||
|
IRQ __vector_WDT
|
||||||
|
IRQ __vector_EE_READY
|
||||||
|
IRQ __vector_TIMER0_COMPB
|
||||||
|
IRQ __vector_INT3
|
||||||
|
IRQ __vector_RESERVED30
|
||||||
|
IRQ __vector_RESERVED31
|
||||||
|
IRQ __vector_SPM_READY
|
||||||
7
targets/device/avr/at90pwm3b.ld
Normal file
7
targets/device/avr/at90pwm3b.ld
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
/* Automatically generated file. DO NOT EDIT. */
|
||||||
|
/* Generated by gen-device-avr.go from AT90PWM3B.atdf, see http://packs.download.atmel.com/ */
|
||||||
|
|
||||||
|
__flash_size = 0x2000;
|
||||||
|
__ram_start = 0x100;
|
||||||
|
__ram_size = 0x200;
|
||||||
|
__num_isrs = 32;
|
||||||
88
targets/device/avr/at90pwm3b.s
Normal file
88
targets/device/avr/at90pwm3b.s
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
; Automatically generated file. DO NOT EDIT.
|
||||||
|
; Generated by gen-device-avr.go from AT90PWM3B.atdf, see http://packs.download.atmel.com/
|
||||||
|
|
||||||
|
; This is the default handler for interrupts, if triggered but not defined.
|
||||||
|
; Sleep inside so that an accidentally triggered interrupt won't drain the
|
||||||
|
; battery of a battery-powered device.
|
||||||
|
.section .text.__vector_default
|
||||||
|
.global __vector_default
|
||||||
|
__vector_default:
|
||||||
|
sleep
|
||||||
|
rjmp __vector_default
|
||||||
|
|
||||||
|
; Avoid the need for repeated .weak and .set instructions.
|
||||||
|
.macro IRQ handler
|
||||||
|
.weak \handler
|
||||||
|
.set \handler, __vector_default
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; The interrupt vector of this device. Must be placed at address 0 by the linker.
|
||||||
|
.section .vectors, "a", %progbits
|
||||||
|
.global __vectors
|
||||||
|
rjmp __vector_RESET
|
||||||
|
rjmp __vector_PSC2_CAPT
|
||||||
|
rjmp __vector_PSC2_EC
|
||||||
|
rjmp __vector_PSC1_CAPT
|
||||||
|
rjmp __vector_PSC1_EC
|
||||||
|
rjmp __vector_PSC0_CAPT
|
||||||
|
rjmp __vector_PSC0_EC
|
||||||
|
rjmp __vector_ANALOG_COMP_0
|
||||||
|
rjmp __vector_ANALOG_COMP_1
|
||||||
|
rjmp __vector_ANALOG_COMP_2
|
||||||
|
rjmp __vector_INT0
|
||||||
|
rjmp __vector_TIMER1_CAPT
|
||||||
|
rjmp __vector_TIMER1_COMPA
|
||||||
|
rjmp __vector_TIMER1_COMPB
|
||||||
|
rjmp __vector_RESERVED15
|
||||||
|
rjmp __vector_TIMER1_OVF
|
||||||
|
rjmp __vector_TIMER0_COMPA
|
||||||
|
rjmp __vector_TIMER0_OVF
|
||||||
|
rjmp __vector_ADC
|
||||||
|
rjmp __vector_INT1
|
||||||
|
rjmp __vector_SPI_STC
|
||||||
|
rjmp __vector_USART_RX
|
||||||
|
rjmp __vector_USART_UDRE
|
||||||
|
rjmp __vector_USART_TX
|
||||||
|
rjmp __vector_INT2
|
||||||
|
rjmp __vector_WDT
|
||||||
|
rjmp __vector_EE_READY
|
||||||
|
rjmp __vector_TIMER0_COMPB
|
||||||
|
rjmp __vector_INT3
|
||||||
|
rjmp __vector_RESERVED30
|
||||||
|
rjmp __vector_RESERVED31
|
||||||
|
rjmp __vector_SPM_READY
|
||||||
|
|
||||||
|
; Define default implementations for interrupts, redirecting to
|
||||||
|
; __vector_default when not implemented.
|
||||||
|
IRQ __vector_RESET
|
||||||
|
IRQ __vector_PSC2_CAPT
|
||||||
|
IRQ __vector_PSC2_EC
|
||||||
|
IRQ __vector_PSC1_CAPT
|
||||||
|
IRQ __vector_PSC1_EC
|
||||||
|
IRQ __vector_PSC0_CAPT
|
||||||
|
IRQ __vector_PSC0_EC
|
||||||
|
IRQ __vector_ANALOG_COMP_0
|
||||||
|
IRQ __vector_ANALOG_COMP_1
|
||||||
|
IRQ __vector_ANALOG_COMP_2
|
||||||
|
IRQ __vector_INT0
|
||||||
|
IRQ __vector_TIMER1_CAPT
|
||||||
|
IRQ __vector_TIMER1_COMPA
|
||||||
|
IRQ __vector_TIMER1_COMPB
|
||||||
|
IRQ __vector_RESERVED15
|
||||||
|
IRQ __vector_TIMER1_OVF
|
||||||
|
IRQ __vector_TIMER0_COMPA
|
||||||
|
IRQ __vector_TIMER0_OVF
|
||||||
|
IRQ __vector_ADC
|
||||||
|
IRQ __vector_INT1
|
||||||
|
IRQ __vector_SPI_STC
|
||||||
|
IRQ __vector_USART_RX
|
||||||
|
IRQ __vector_USART_UDRE
|
||||||
|
IRQ __vector_USART_TX
|
||||||
|
IRQ __vector_INT2
|
||||||
|
IRQ __vector_WDT
|
||||||
|
IRQ __vector_EE_READY
|
||||||
|
IRQ __vector_TIMER0_COMPB
|
||||||
|
IRQ __vector_INT3
|
||||||
|
IRQ __vector_RESERVED30
|
||||||
|
IRQ __vector_RESERVED31
|
||||||
|
IRQ __vector_SPM_READY
|
||||||
7
targets/device/avr/at90pwm81.ld
Normal file
7
targets/device/avr/at90pwm81.ld
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
/* Automatically generated file. DO NOT EDIT. */
|
||||||
|
/* Generated by gen-device-avr.go from AT90PWM81.atdf, see http://packs.download.atmel.com/ */
|
||||||
|
|
||||||
|
__flash_size = 0x2000;
|
||||||
|
__ram_start = 0x100;
|
||||||
|
__ram_size = 0x100;
|
||||||
|
__num_isrs = 20;
|
||||||
64
targets/device/avr/at90pwm81.s
Normal file
64
targets/device/avr/at90pwm81.s
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
; Automatically generated file. DO NOT EDIT.
|
||||||
|
; Generated by gen-device-avr.go from AT90PWM81.atdf, see http://packs.download.atmel.com/
|
||||||
|
|
||||||
|
; This is the default handler for interrupts, if triggered but not defined.
|
||||||
|
; Sleep inside so that an accidentally triggered interrupt won't drain the
|
||||||
|
; battery of a battery-powered device.
|
||||||
|
.section .text.__vector_default
|
||||||
|
.global __vector_default
|
||||||
|
__vector_default:
|
||||||
|
sleep
|
||||||
|
rjmp __vector_default
|
||||||
|
|
||||||
|
; Avoid the need for repeated .weak and .set instructions.
|
||||||
|
.macro IRQ handler
|
||||||
|
.weak \handler
|
||||||
|
.set \handler, __vector_default
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; The interrupt vector of this device. Must be placed at address 0 by the linker.
|
||||||
|
.section .vectors, "a", %progbits
|
||||||
|
.global __vectors
|
||||||
|
rjmp __vector_RESET
|
||||||
|
rjmp __vector_PSC2_CAPT
|
||||||
|
rjmp __vector_PSC2_EC
|
||||||
|
rjmp __vector_PSC2_EEC
|
||||||
|
rjmp __vector_PSC0_CAPT
|
||||||
|
rjmp __vector_PSC0_EC
|
||||||
|
rjmp __vector_PSC0_EEC
|
||||||
|
rjmp __vector_ANALOG_COMP_1
|
||||||
|
rjmp __vector_ANALOG_COMP_2
|
||||||
|
rjmp __vector_ANALOG_COMP_3
|
||||||
|
rjmp __vector_INT0
|
||||||
|
rjmp __vector_TIMER1_CAPT
|
||||||
|
rjmp __vector_TIMER1_OVF
|
||||||
|
rjmp __vector_ADC
|
||||||
|
rjmp __vector_INT1
|
||||||
|
rjmp __vector_SPI_STC
|
||||||
|
rjmp __vector_INT2
|
||||||
|
rjmp __vector_WDT
|
||||||
|
rjmp __vector_EE_READY
|
||||||
|
rjmp __vector_SPM_READY
|
||||||
|
|
||||||
|
; Define default implementations for interrupts, redirecting to
|
||||||
|
; __vector_default when not implemented.
|
||||||
|
IRQ __vector_RESET
|
||||||
|
IRQ __vector_PSC2_CAPT
|
||||||
|
IRQ __vector_PSC2_EC
|
||||||
|
IRQ __vector_PSC2_EEC
|
||||||
|
IRQ __vector_PSC0_CAPT
|
||||||
|
IRQ __vector_PSC0_EC
|
||||||
|
IRQ __vector_PSC0_EEC
|
||||||
|
IRQ __vector_ANALOG_COMP_1
|
||||||
|
IRQ __vector_ANALOG_COMP_2
|
||||||
|
IRQ __vector_ANALOG_COMP_3
|
||||||
|
IRQ __vector_INT0
|
||||||
|
IRQ __vector_TIMER1_CAPT
|
||||||
|
IRQ __vector_TIMER1_OVF
|
||||||
|
IRQ __vector_ADC
|
||||||
|
IRQ __vector_INT1
|
||||||
|
IRQ __vector_SPI_STC
|
||||||
|
IRQ __vector_INT2
|
||||||
|
IRQ __vector_WDT
|
||||||
|
IRQ __vector_EE_READY
|
||||||
|
IRQ __vector_SPM_READY
|
||||||
7
targets/device/avr/at90usb1286.ld
Normal file
7
targets/device/avr/at90usb1286.ld
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
/* Automatically generated file. DO NOT EDIT. */
|
||||||
|
/* Generated by gen-device-avr.go from AT90USB1286.atdf, see http://packs.download.atmel.com/ */
|
||||||
|
|
||||||
|
__flash_size = 0x20000;
|
||||||
|
__ram_start = 0x100;
|
||||||
|
__ram_size = 0x2000;
|
||||||
|
__num_isrs = 38;
|
||||||
100
targets/device/avr/at90usb1286.s
Normal file
100
targets/device/avr/at90usb1286.s
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
; Automatically generated file. DO NOT EDIT.
|
||||||
|
; Generated by gen-device-avr.go from AT90USB1286.atdf, see http://packs.download.atmel.com/
|
||||||
|
|
||||||
|
; This is the default handler for interrupts, if triggered but not defined.
|
||||||
|
; Sleep inside so that an accidentally triggered interrupt won't drain the
|
||||||
|
; battery of a battery-powered device.
|
||||||
|
.section .text.__vector_default
|
||||||
|
.global __vector_default
|
||||||
|
__vector_default:
|
||||||
|
sleep
|
||||||
|
rjmp __vector_default
|
||||||
|
|
||||||
|
; Avoid the need for repeated .weak and .set instructions.
|
||||||
|
.macro IRQ handler
|
||||||
|
.weak \handler
|
||||||
|
.set \handler, __vector_default
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; The interrupt vector of this device. Must be placed at address 0 by the linker.
|
||||||
|
.section .vectors, "a", %progbits
|
||||||
|
.global __vectors
|
||||||
|
jmp __vector_RESET
|
||||||
|
jmp __vector_INT0
|
||||||
|
jmp __vector_INT1
|
||||||
|
jmp __vector_INT2
|
||||||
|
jmp __vector_INT3
|
||||||
|
jmp __vector_INT4
|
||||||
|
jmp __vector_INT5
|
||||||
|
jmp __vector_INT6
|
||||||
|
jmp __vector_INT7
|
||||||
|
jmp __vector_PCINT0
|
||||||
|
jmp __vector_USB_GEN
|
||||||
|
jmp __vector_USB_COM
|
||||||
|
jmp __vector_WDT
|
||||||
|
jmp __vector_TIMER2_COMPA
|
||||||
|
jmp __vector_TIMER2_COMPB
|
||||||
|
jmp __vector_TIMER2_OVF
|
||||||
|
jmp __vector_TIMER1_CAPT
|
||||||
|
jmp __vector_TIMER1_COMPA
|
||||||
|
jmp __vector_TIMER1_COMPB
|
||||||
|
jmp __vector_TIMER1_COMPC
|
||||||
|
jmp __vector_TIMER1_OVF
|
||||||
|
jmp __vector_TIMER0_COMPA
|
||||||
|
jmp __vector_TIMER0_COMPB
|
||||||
|
jmp __vector_TIMER0_OVF
|
||||||
|
jmp __vector_SPI_STC
|
||||||
|
jmp __vector_USART1_RX
|
||||||
|
jmp __vector_USART1_UDRE
|
||||||
|
jmp __vector_USART1_TX
|
||||||
|
jmp __vector_ANALOG_COMP
|
||||||
|
jmp __vector_ADC
|
||||||
|
jmp __vector_EE_READY
|
||||||
|
jmp __vector_TIMER3_CAPT
|
||||||
|
jmp __vector_TIMER3_COMPA
|
||||||
|
jmp __vector_TIMER3_COMPB
|
||||||
|
jmp __vector_TIMER3_COMPC
|
||||||
|
jmp __vector_TIMER3_OVF
|
||||||
|
jmp __vector_TWI
|
||||||
|
jmp __vector_SPM_READY
|
||||||
|
|
||||||
|
; Define default implementations for interrupts, redirecting to
|
||||||
|
; __vector_default when not implemented.
|
||||||
|
IRQ __vector_RESET
|
||||||
|
IRQ __vector_INT0
|
||||||
|
IRQ __vector_INT1
|
||||||
|
IRQ __vector_INT2
|
||||||
|
IRQ __vector_INT3
|
||||||
|
IRQ __vector_INT4
|
||||||
|
IRQ __vector_INT5
|
||||||
|
IRQ __vector_INT6
|
||||||
|
IRQ __vector_INT7
|
||||||
|
IRQ __vector_PCINT0
|
||||||
|
IRQ __vector_USB_GEN
|
||||||
|
IRQ __vector_USB_COM
|
||||||
|
IRQ __vector_WDT
|
||||||
|
IRQ __vector_TIMER2_COMPA
|
||||||
|
IRQ __vector_TIMER2_COMPB
|
||||||
|
IRQ __vector_TIMER2_OVF
|
||||||
|
IRQ __vector_TIMER1_CAPT
|
||||||
|
IRQ __vector_TIMER1_COMPA
|
||||||
|
IRQ __vector_TIMER1_COMPB
|
||||||
|
IRQ __vector_TIMER1_COMPC
|
||||||
|
IRQ __vector_TIMER1_OVF
|
||||||
|
IRQ __vector_TIMER0_COMPA
|
||||||
|
IRQ __vector_TIMER0_COMPB
|
||||||
|
IRQ __vector_TIMER0_OVF
|
||||||
|
IRQ __vector_SPI_STC
|
||||||
|
IRQ __vector_USART1_RX
|
||||||
|
IRQ __vector_USART1_UDRE
|
||||||
|
IRQ __vector_USART1_TX
|
||||||
|
IRQ __vector_ANALOG_COMP
|
||||||
|
IRQ __vector_ADC
|
||||||
|
IRQ __vector_EE_READY
|
||||||
|
IRQ __vector_TIMER3_CAPT
|
||||||
|
IRQ __vector_TIMER3_COMPA
|
||||||
|
IRQ __vector_TIMER3_COMPB
|
||||||
|
IRQ __vector_TIMER3_COMPC
|
||||||
|
IRQ __vector_TIMER3_OVF
|
||||||
|
IRQ __vector_TWI
|
||||||
|
IRQ __vector_SPM_READY
|
||||||
7
targets/device/avr/at90usb1287.ld
Normal file
7
targets/device/avr/at90usb1287.ld
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
/* Automatically generated file. DO NOT EDIT. */
|
||||||
|
/* Generated by gen-device-avr.go from AT90USB1287.atdf, see http://packs.download.atmel.com/ */
|
||||||
|
|
||||||
|
__flash_size = 0x20000;
|
||||||
|
__ram_start = 0x100;
|
||||||
|
__ram_size = 0x2000;
|
||||||
|
__num_isrs = 38;
|
||||||
100
targets/device/avr/at90usb1287.s
Normal file
100
targets/device/avr/at90usb1287.s
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
; Automatically generated file. DO NOT EDIT.
|
||||||
|
; Generated by gen-device-avr.go from AT90USB1287.atdf, see http://packs.download.atmel.com/
|
||||||
|
|
||||||
|
; This is the default handler for interrupts, if triggered but not defined.
|
||||||
|
; Sleep inside so that an accidentally triggered interrupt won't drain the
|
||||||
|
; battery of a battery-powered device.
|
||||||
|
.section .text.__vector_default
|
||||||
|
.global __vector_default
|
||||||
|
__vector_default:
|
||||||
|
sleep
|
||||||
|
rjmp __vector_default
|
||||||
|
|
||||||
|
; Avoid the need for repeated .weak and .set instructions.
|
||||||
|
.macro IRQ handler
|
||||||
|
.weak \handler
|
||||||
|
.set \handler, __vector_default
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; The interrupt vector of this device. Must be placed at address 0 by the linker.
|
||||||
|
.section .vectors, "a", %progbits
|
||||||
|
.global __vectors
|
||||||
|
jmp __vector_RESET
|
||||||
|
jmp __vector_INT0
|
||||||
|
jmp __vector_INT1
|
||||||
|
jmp __vector_INT2
|
||||||
|
jmp __vector_INT3
|
||||||
|
jmp __vector_INT4
|
||||||
|
jmp __vector_INT5
|
||||||
|
jmp __vector_INT6
|
||||||
|
jmp __vector_INT7
|
||||||
|
jmp __vector_PCINT0
|
||||||
|
jmp __vector_USB_GEN
|
||||||
|
jmp __vector_USB_COM
|
||||||
|
jmp __vector_WDT
|
||||||
|
jmp __vector_TIMER2_COMPA
|
||||||
|
jmp __vector_TIMER2_COMPB
|
||||||
|
jmp __vector_TIMER2_OVF
|
||||||
|
jmp __vector_TIMER1_CAPT
|
||||||
|
jmp __vector_TIMER1_COMPA
|
||||||
|
jmp __vector_TIMER1_COMPB
|
||||||
|
jmp __vector_TIMER1_COMPC
|
||||||
|
jmp __vector_TIMER1_OVF
|
||||||
|
jmp __vector_TIMER0_COMPA
|
||||||
|
jmp __vector_TIMER0_COMPB
|
||||||
|
jmp __vector_TIMER0_OVF
|
||||||
|
jmp __vector_SPI_STC
|
||||||
|
jmp __vector_USART1_RX
|
||||||
|
jmp __vector_USART1_UDRE
|
||||||
|
jmp __vector_USART1_TX
|
||||||
|
jmp __vector_ANALOG_COMP
|
||||||
|
jmp __vector_ADC
|
||||||
|
jmp __vector_EE_READY
|
||||||
|
jmp __vector_TIMER3_CAPT
|
||||||
|
jmp __vector_TIMER3_COMPA
|
||||||
|
jmp __vector_TIMER3_COMPB
|
||||||
|
jmp __vector_TIMER3_COMPC
|
||||||
|
jmp __vector_TIMER3_OVF
|
||||||
|
jmp __vector_TWI
|
||||||
|
jmp __vector_SPM_READY
|
||||||
|
|
||||||
|
; Define default implementations for interrupts, redirecting to
|
||||||
|
; __vector_default when not implemented.
|
||||||
|
IRQ __vector_RESET
|
||||||
|
IRQ __vector_INT0
|
||||||
|
IRQ __vector_INT1
|
||||||
|
IRQ __vector_INT2
|
||||||
|
IRQ __vector_INT3
|
||||||
|
IRQ __vector_INT4
|
||||||
|
IRQ __vector_INT5
|
||||||
|
IRQ __vector_INT6
|
||||||
|
IRQ __vector_INT7
|
||||||
|
IRQ __vector_PCINT0
|
||||||
|
IRQ __vector_USB_GEN
|
||||||
|
IRQ __vector_USB_COM
|
||||||
|
IRQ __vector_WDT
|
||||||
|
IRQ __vector_TIMER2_COMPA
|
||||||
|
IRQ __vector_TIMER2_COMPB
|
||||||
|
IRQ __vector_TIMER2_OVF
|
||||||
|
IRQ __vector_TIMER1_CAPT
|
||||||
|
IRQ __vector_TIMER1_COMPA
|
||||||
|
IRQ __vector_TIMER1_COMPB
|
||||||
|
IRQ __vector_TIMER1_COMPC
|
||||||
|
IRQ __vector_TIMER1_OVF
|
||||||
|
IRQ __vector_TIMER0_COMPA
|
||||||
|
IRQ __vector_TIMER0_COMPB
|
||||||
|
IRQ __vector_TIMER0_OVF
|
||||||
|
IRQ __vector_SPI_STC
|
||||||
|
IRQ __vector_USART1_RX
|
||||||
|
IRQ __vector_USART1_UDRE
|
||||||
|
IRQ __vector_USART1_TX
|
||||||
|
IRQ __vector_ANALOG_COMP
|
||||||
|
IRQ __vector_ADC
|
||||||
|
IRQ __vector_EE_READY
|
||||||
|
IRQ __vector_TIMER3_CAPT
|
||||||
|
IRQ __vector_TIMER3_COMPA
|
||||||
|
IRQ __vector_TIMER3_COMPB
|
||||||
|
IRQ __vector_TIMER3_COMPC
|
||||||
|
IRQ __vector_TIMER3_OVF
|
||||||
|
IRQ __vector_TWI
|
||||||
|
IRQ __vector_SPM_READY
|
||||||
7
targets/device/avr/at90usb162.ld
Normal file
7
targets/device/avr/at90usb162.ld
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
/* Automatically generated file. DO NOT EDIT. */
|
||||||
|
/* Generated by gen-device-avr.go from AT90USB162.atdf, see http://packs.download.atmel.com/ */
|
||||||
|
|
||||||
|
__flash_size = 0x4000;
|
||||||
|
__ram_start = 0x100;
|
||||||
|
__ram_size = 0x200;
|
||||||
|
__num_isrs = 29;
|
||||||
82
targets/device/avr/at90usb162.s
Normal file
82
targets/device/avr/at90usb162.s
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
; Automatically generated file. DO NOT EDIT.
|
||||||
|
; Generated by gen-device-avr.go from AT90USB162.atdf, see http://packs.download.atmel.com/
|
||||||
|
|
||||||
|
; This is the default handler for interrupts, if triggered but not defined.
|
||||||
|
; Sleep inside so that an accidentally triggered interrupt won't drain the
|
||||||
|
; battery of a battery-powered device.
|
||||||
|
.section .text.__vector_default
|
||||||
|
.global __vector_default
|
||||||
|
__vector_default:
|
||||||
|
sleep
|
||||||
|
rjmp __vector_default
|
||||||
|
|
||||||
|
; Avoid the need for repeated .weak and .set instructions.
|
||||||
|
.macro IRQ handler
|
||||||
|
.weak \handler
|
||||||
|
.set \handler, __vector_default
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; The interrupt vector of this device. Must be placed at address 0 by the linker.
|
||||||
|
.section .vectors, "a", %progbits
|
||||||
|
.global __vectors
|
||||||
|
jmp __vector_RESET
|
||||||
|
jmp __vector_INT0
|
||||||
|
jmp __vector_INT1
|
||||||
|
jmp __vector_INT2
|
||||||
|
jmp __vector_INT3
|
||||||
|
jmp __vector_INT4
|
||||||
|
jmp __vector_INT5
|
||||||
|
jmp __vector_INT6
|
||||||
|
jmp __vector_INT7
|
||||||
|
jmp __vector_PCINT0
|
||||||
|
jmp __vector_PCINT1
|
||||||
|
jmp __vector_USB_GEN
|
||||||
|
jmp __vector_USB_COM
|
||||||
|
jmp __vector_WDT
|
||||||
|
jmp __vector_TIMER1_CAPT
|
||||||
|
jmp __vector_TIMER1_COMPA
|
||||||
|
jmp __vector_TIMER1_COMPB
|
||||||
|
jmp __vector_TIMER1_COMPC
|
||||||
|
jmp __vector_TIMER1_OVF
|
||||||
|
jmp __vector_TIMER0_COMPA
|
||||||
|
jmp __vector_TIMER0_COMPB
|
||||||
|
jmp __vector_TIMER0_OVF
|
||||||
|
jmp __vector_SPI_STC
|
||||||
|
jmp __vector_USART1_RX
|
||||||
|
jmp __vector_USART1_UDRE
|
||||||
|
jmp __vector_USART1_TX
|
||||||
|
jmp __vector_ANALOG_COMP
|
||||||
|
jmp __vector_EE_READY
|
||||||
|
jmp __vector_SPM_READY
|
||||||
|
|
||||||
|
; Define default implementations for interrupts, redirecting to
|
||||||
|
; __vector_default when not implemented.
|
||||||
|
IRQ __vector_RESET
|
||||||
|
IRQ __vector_INT0
|
||||||
|
IRQ __vector_INT1
|
||||||
|
IRQ __vector_INT2
|
||||||
|
IRQ __vector_INT3
|
||||||
|
IRQ __vector_INT4
|
||||||
|
IRQ __vector_INT5
|
||||||
|
IRQ __vector_INT6
|
||||||
|
IRQ __vector_INT7
|
||||||
|
IRQ __vector_PCINT0
|
||||||
|
IRQ __vector_PCINT1
|
||||||
|
IRQ __vector_USB_GEN
|
||||||
|
IRQ __vector_USB_COM
|
||||||
|
IRQ __vector_WDT
|
||||||
|
IRQ __vector_TIMER1_CAPT
|
||||||
|
IRQ __vector_TIMER1_COMPA
|
||||||
|
IRQ __vector_TIMER1_COMPB
|
||||||
|
IRQ __vector_TIMER1_COMPC
|
||||||
|
IRQ __vector_TIMER1_OVF
|
||||||
|
IRQ __vector_TIMER0_COMPA
|
||||||
|
IRQ __vector_TIMER0_COMPB
|
||||||
|
IRQ __vector_TIMER0_OVF
|
||||||
|
IRQ __vector_SPI_STC
|
||||||
|
IRQ __vector_USART1_RX
|
||||||
|
IRQ __vector_USART1_UDRE
|
||||||
|
IRQ __vector_USART1_TX
|
||||||
|
IRQ __vector_ANALOG_COMP
|
||||||
|
IRQ __vector_EE_READY
|
||||||
|
IRQ __vector_SPM_READY
|
||||||
7
targets/device/avr/at90usb646.ld
Normal file
7
targets/device/avr/at90usb646.ld
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
/* Automatically generated file. DO NOT EDIT. */
|
||||||
|
/* Generated by gen-device-avr.go from AT90USB646.atdf, see http://packs.download.atmel.com/ */
|
||||||
|
|
||||||
|
__flash_size = 0x10000;
|
||||||
|
__ram_start = 0x100;
|
||||||
|
__ram_size = 0x1000;
|
||||||
|
__num_isrs = 38;
|
||||||
100
targets/device/avr/at90usb646.s
Normal file
100
targets/device/avr/at90usb646.s
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
; Automatically generated file. DO NOT EDIT.
|
||||||
|
; Generated by gen-device-avr.go from AT90USB646.atdf, see http://packs.download.atmel.com/
|
||||||
|
|
||||||
|
; This is the default handler for interrupts, if triggered but not defined.
|
||||||
|
; Sleep inside so that an accidentally triggered interrupt won't drain the
|
||||||
|
; battery of a battery-powered device.
|
||||||
|
.section .text.__vector_default
|
||||||
|
.global __vector_default
|
||||||
|
__vector_default:
|
||||||
|
sleep
|
||||||
|
rjmp __vector_default
|
||||||
|
|
||||||
|
; Avoid the need for repeated .weak and .set instructions.
|
||||||
|
.macro IRQ handler
|
||||||
|
.weak \handler
|
||||||
|
.set \handler, __vector_default
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; The interrupt vector of this device. Must be placed at address 0 by the linker.
|
||||||
|
.section .vectors, "a", %progbits
|
||||||
|
.global __vectors
|
||||||
|
jmp __vector_RESET
|
||||||
|
jmp __vector_INT0
|
||||||
|
jmp __vector_INT1
|
||||||
|
jmp __vector_INT2
|
||||||
|
jmp __vector_INT3
|
||||||
|
jmp __vector_INT4
|
||||||
|
jmp __vector_INT5
|
||||||
|
jmp __vector_INT6
|
||||||
|
jmp __vector_INT7
|
||||||
|
jmp __vector_PCINT0
|
||||||
|
jmp __vector_USB_GEN
|
||||||
|
jmp __vector_USB_COM
|
||||||
|
jmp __vector_WDT
|
||||||
|
jmp __vector_TIMER2_COMPA
|
||||||
|
jmp __vector_TIMER2_COMPB
|
||||||
|
jmp __vector_TIMER2_OVF
|
||||||
|
jmp __vector_TIMER1_CAPT
|
||||||
|
jmp __vector_TIMER1_COMPA
|
||||||
|
jmp __vector_TIMER1_COMPB
|
||||||
|
jmp __vector_TIMER1_COMPC
|
||||||
|
jmp __vector_TIMER1_OVF
|
||||||
|
jmp __vector_TIMER0_COMPA
|
||||||
|
jmp __vector_TIMER0_COMPB
|
||||||
|
jmp __vector_TIMER0_OVF
|
||||||
|
jmp __vector_SPI_STC
|
||||||
|
jmp __vector_USART1_RX
|
||||||
|
jmp __vector_USART1_UDRE
|
||||||
|
jmp __vector_USART1_TX
|
||||||
|
jmp __vector_ANALOG_COMP
|
||||||
|
jmp __vector_ADC
|
||||||
|
jmp __vector_EE_READY
|
||||||
|
jmp __vector_TIMER3_CAPT
|
||||||
|
jmp __vector_TIMER3_COMPA
|
||||||
|
jmp __vector_TIMER3_COMPB
|
||||||
|
jmp __vector_TIMER3_COMPC
|
||||||
|
jmp __vector_TIMER3_OVF
|
||||||
|
jmp __vector_TWI
|
||||||
|
jmp __vector_SPM_READY
|
||||||
|
|
||||||
|
; Define default implementations for interrupts, redirecting to
|
||||||
|
; __vector_default when not implemented.
|
||||||
|
IRQ __vector_RESET
|
||||||
|
IRQ __vector_INT0
|
||||||
|
IRQ __vector_INT1
|
||||||
|
IRQ __vector_INT2
|
||||||
|
IRQ __vector_INT3
|
||||||
|
IRQ __vector_INT4
|
||||||
|
IRQ __vector_INT5
|
||||||
|
IRQ __vector_INT6
|
||||||
|
IRQ __vector_INT7
|
||||||
|
IRQ __vector_PCINT0
|
||||||
|
IRQ __vector_USB_GEN
|
||||||
|
IRQ __vector_USB_COM
|
||||||
|
IRQ __vector_WDT
|
||||||
|
IRQ __vector_TIMER2_COMPA
|
||||||
|
IRQ __vector_TIMER2_COMPB
|
||||||
|
IRQ __vector_TIMER2_OVF
|
||||||
|
IRQ __vector_TIMER1_CAPT
|
||||||
|
IRQ __vector_TIMER1_COMPA
|
||||||
|
IRQ __vector_TIMER1_COMPB
|
||||||
|
IRQ __vector_TIMER1_COMPC
|
||||||
|
IRQ __vector_TIMER1_OVF
|
||||||
|
IRQ __vector_TIMER0_COMPA
|
||||||
|
IRQ __vector_TIMER0_COMPB
|
||||||
|
IRQ __vector_TIMER0_OVF
|
||||||
|
IRQ __vector_SPI_STC
|
||||||
|
IRQ __vector_USART1_RX
|
||||||
|
IRQ __vector_USART1_UDRE
|
||||||
|
IRQ __vector_USART1_TX
|
||||||
|
IRQ __vector_ANALOG_COMP
|
||||||
|
IRQ __vector_ADC
|
||||||
|
IRQ __vector_EE_READY
|
||||||
|
IRQ __vector_TIMER3_CAPT
|
||||||
|
IRQ __vector_TIMER3_COMPA
|
||||||
|
IRQ __vector_TIMER3_COMPB
|
||||||
|
IRQ __vector_TIMER3_COMPC
|
||||||
|
IRQ __vector_TIMER3_OVF
|
||||||
|
IRQ __vector_TWI
|
||||||
|
IRQ __vector_SPM_READY
|
||||||
7
targets/device/avr/at90usb647.ld
Normal file
7
targets/device/avr/at90usb647.ld
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
/* Automatically generated file. DO NOT EDIT. */
|
||||||
|
/* Generated by gen-device-avr.go from AT90USB647.atdf, see http://packs.download.atmel.com/ */
|
||||||
|
|
||||||
|
__flash_size = 0x10000;
|
||||||
|
__ram_start = 0x100;
|
||||||
|
__ram_size = 0x1000;
|
||||||
|
__num_isrs = 38;
|
||||||
100
targets/device/avr/at90usb647.s
Normal file
100
targets/device/avr/at90usb647.s
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
; Automatically generated file. DO NOT EDIT.
|
||||||
|
; Generated by gen-device-avr.go from AT90USB647.atdf, see http://packs.download.atmel.com/
|
||||||
|
|
||||||
|
; This is the default handler for interrupts, if triggered but not defined.
|
||||||
|
; Sleep inside so that an accidentally triggered interrupt won't drain the
|
||||||
|
; battery of a battery-powered device.
|
||||||
|
.section .text.__vector_default
|
||||||
|
.global __vector_default
|
||||||
|
__vector_default:
|
||||||
|
sleep
|
||||||
|
rjmp __vector_default
|
||||||
|
|
||||||
|
; Avoid the need for repeated .weak and .set instructions.
|
||||||
|
.macro IRQ handler
|
||||||
|
.weak \handler
|
||||||
|
.set \handler, __vector_default
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; The interrupt vector of this device. Must be placed at address 0 by the linker.
|
||||||
|
.section .vectors, "a", %progbits
|
||||||
|
.global __vectors
|
||||||
|
jmp __vector_RESET
|
||||||
|
jmp __vector_INT0
|
||||||
|
jmp __vector_INT1
|
||||||
|
jmp __vector_INT2
|
||||||
|
jmp __vector_INT3
|
||||||
|
jmp __vector_INT4
|
||||||
|
jmp __vector_INT5
|
||||||
|
jmp __vector_INT6
|
||||||
|
jmp __vector_INT7
|
||||||
|
jmp __vector_PCINT0
|
||||||
|
jmp __vector_USB_GEN
|
||||||
|
jmp __vector_USB_COM
|
||||||
|
jmp __vector_WDT
|
||||||
|
jmp __vector_TIMER2_COMPA
|
||||||
|
jmp __vector_TIMER2_COMPB
|
||||||
|
jmp __vector_TIMER2_OVF
|
||||||
|
jmp __vector_TIMER1_CAPT
|
||||||
|
jmp __vector_TIMER1_COMPA
|
||||||
|
jmp __vector_TIMER1_COMPB
|
||||||
|
jmp __vector_TIMER1_COMPC
|
||||||
|
jmp __vector_TIMER1_OVF
|
||||||
|
jmp __vector_TIMER0_COMPA
|
||||||
|
jmp __vector_TIMER0_COMPB
|
||||||
|
jmp __vector_TIMER0_OVF
|
||||||
|
jmp __vector_SPI_STC
|
||||||
|
jmp __vector_USART1_RX
|
||||||
|
jmp __vector_USART1_UDRE
|
||||||
|
jmp __vector_USART1_TX
|
||||||
|
jmp __vector_ANALOG_COMP
|
||||||
|
jmp __vector_ADC
|
||||||
|
jmp __vector_EE_READY
|
||||||
|
jmp __vector_TIMER3_CAPT
|
||||||
|
jmp __vector_TIMER3_COMPA
|
||||||
|
jmp __vector_TIMER3_COMPB
|
||||||
|
jmp __vector_TIMER3_COMPC
|
||||||
|
jmp __vector_TIMER3_OVF
|
||||||
|
jmp __vector_TWI
|
||||||
|
jmp __vector_SPM_READY
|
||||||
|
|
||||||
|
; Define default implementations for interrupts, redirecting to
|
||||||
|
; __vector_default when not implemented.
|
||||||
|
IRQ __vector_RESET
|
||||||
|
IRQ __vector_INT0
|
||||||
|
IRQ __vector_INT1
|
||||||
|
IRQ __vector_INT2
|
||||||
|
IRQ __vector_INT3
|
||||||
|
IRQ __vector_INT4
|
||||||
|
IRQ __vector_INT5
|
||||||
|
IRQ __vector_INT6
|
||||||
|
IRQ __vector_INT7
|
||||||
|
IRQ __vector_PCINT0
|
||||||
|
IRQ __vector_USB_GEN
|
||||||
|
IRQ __vector_USB_COM
|
||||||
|
IRQ __vector_WDT
|
||||||
|
IRQ __vector_TIMER2_COMPA
|
||||||
|
IRQ __vector_TIMER2_COMPB
|
||||||
|
IRQ __vector_TIMER2_OVF
|
||||||
|
IRQ __vector_TIMER1_CAPT
|
||||||
|
IRQ __vector_TIMER1_COMPA
|
||||||
|
IRQ __vector_TIMER1_COMPB
|
||||||
|
IRQ __vector_TIMER1_COMPC
|
||||||
|
IRQ __vector_TIMER1_OVF
|
||||||
|
IRQ __vector_TIMER0_COMPA
|
||||||
|
IRQ __vector_TIMER0_COMPB
|
||||||
|
IRQ __vector_TIMER0_OVF
|
||||||
|
IRQ __vector_SPI_STC
|
||||||
|
IRQ __vector_USART1_RX
|
||||||
|
IRQ __vector_USART1_UDRE
|
||||||
|
IRQ __vector_USART1_TX
|
||||||
|
IRQ __vector_ANALOG_COMP
|
||||||
|
IRQ __vector_ADC
|
||||||
|
IRQ __vector_EE_READY
|
||||||
|
IRQ __vector_TIMER3_CAPT
|
||||||
|
IRQ __vector_TIMER3_COMPA
|
||||||
|
IRQ __vector_TIMER3_COMPB
|
||||||
|
IRQ __vector_TIMER3_COMPC
|
||||||
|
IRQ __vector_TIMER3_OVF
|
||||||
|
IRQ __vector_TWI
|
||||||
|
IRQ __vector_SPM_READY
|
||||||
7
targets/device/avr/at90usb82.ld
Normal file
7
targets/device/avr/at90usb82.ld
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
/* Automatically generated file. DO NOT EDIT. */
|
||||||
|
/* Generated by gen-device-avr.go from AT90USB82.atdf, see http://packs.download.atmel.com/ */
|
||||||
|
|
||||||
|
__flash_size = 0x2000;
|
||||||
|
__ram_start = 0x100;
|
||||||
|
__ram_size = 0x200;
|
||||||
|
__num_isrs = 29;
|
||||||
82
targets/device/avr/at90usb82.s
Normal file
82
targets/device/avr/at90usb82.s
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
; Automatically generated file. DO NOT EDIT.
|
||||||
|
; Generated by gen-device-avr.go from AT90USB82.atdf, see http://packs.download.atmel.com/
|
||||||
|
|
||||||
|
; This is the default handler for interrupts, if triggered but not defined.
|
||||||
|
; Sleep inside so that an accidentally triggered interrupt won't drain the
|
||||||
|
; battery of a battery-powered device.
|
||||||
|
.section .text.__vector_default
|
||||||
|
.global __vector_default
|
||||||
|
__vector_default:
|
||||||
|
sleep
|
||||||
|
rjmp __vector_default
|
||||||
|
|
||||||
|
; Avoid the need for repeated .weak and .set instructions.
|
||||||
|
.macro IRQ handler
|
||||||
|
.weak \handler
|
||||||
|
.set \handler, __vector_default
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; The interrupt vector of this device. Must be placed at address 0 by the linker.
|
||||||
|
.section .vectors, "a", %progbits
|
||||||
|
.global __vectors
|
||||||
|
rjmp __vector_RESET
|
||||||
|
rjmp __vector_INT0
|
||||||
|
rjmp __vector_INT1
|
||||||
|
rjmp __vector_INT2
|
||||||
|
rjmp __vector_INT3
|
||||||
|
rjmp __vector_INT4
|
||||||
|
rjmp __vector_INT5
|
||||||
|
rjmp __vector_INT6
|
||||||
|
rjmp __vector_INT7
|
||||||
|
rjmp __vector_PCINT0
|
||||||
|
rjmp __vector_PCINT1
|
||||||
|
rjmp __vector_USB_GEN
|
||||||
|
rjmp __vector_USB_COM
|
||||||
|
rjmp __vector_WDT
|
||||||
|
rjmp __vector_TIMER1_CAPT
|
||||||
|
rjmp __vector_TIMER1_COMPA
|
||||||
|
rjmp __vector_TIMER1_COMPB
|
||||||
|
rjmp __vector_TIMER1_COMPC
|
||||||
|
rjmp __vector_TIMER1_OVF
|
||||||
|
rjmp __vector_TIMER0_COMPA
|
||||||
|
rjmp __vector_TIMER0_COMPB
|
||||||
|
rjmp __vector_TIMER0_OVF
|
||||||
|
rjmp __vector_SPI_STC
|
||||||
|
rjmp __vector_USART1_RX
|
||||||
|
rjmp __vector_USART1_UDRE
|
||||||
|
rjmp __vector_USART1_TX
|
||||||
|
rjmp __vector_ANALOG_COMP
|
||||||
|
rjmp __vector_EE_READY
|
||||||
|
rjmp __vector_SPM_READY
|
||||||
|
|
||||||
|
; Define default implementations for interrupts, redirecting to
|
||||||
|
; __vector_default when not implemented.
|
||||||
|
IRQ __vector_RESET
|
||||||
|
IRQ __vector_INT0
|
||||||
|
IRQ __vector_INT1
|
||||||
|
IRQ __vector_INT2
|
||||||
|
IRQ __vector_INT3
|
||||||
|
IRQ __vector_INT4
|
||||||
|
IRQ __vector_INT5
|
||||||
|
IRQ __vector_INT6
|
||||||
|
IRQ __vector_INT7
|
||||||
|
IRQ __vector_PCINT0
|
||||||
|
IRQ __vector_PCINT1
|
||||||
|
IRQ __vector_USB_GEN
|
||||||
|
IRQ __vector_USB_COM
|
||||||
|
IRQ __vector_WDT
|
||||||
|
IRQ __vector_TIMER1_CAPT
|
||||||
|
IRQ __vector_TIMER1_COMPA
|
||||||
|
IRQ __vector_TIMER1_COMPB
|
||||||
|
IRQ __vector_TIMER1_COMPC
|
||||||
|
IRQ __vector_TIMER1_OVF
|
||||||
|
IRQ __vector_TIMER0_COMPA
|
||||||
|
IRQ __vector_TIMER0_COMPB
|
||||||
|
IRQ __vector_TIMER0_OVF
|
||||||
|
IRQ __vector_SPI_STC
|
||||||
|
IRQ __vector_USART1_RX
|
||||||
|
IRQ __vector_USART1_UDRE
|
||||||
|
IRQ __vector_USART1_TX
|
||||||
|
IRQ __vector_ANALOG_COMP
|
||||||
|
IRQ __vector_EE_READY
|
||||||
|
IRQ __vector_SPM_READY
|
||||||
7
targets/device/avr/atmega128.ld
Normal file
7
targets/device/avr/atmega128.ld
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
/* Automatically generated file. DO NOT EDIT. */
|
||||||
|
/* Generated by gen-device-avr.go from ATmega128.atdf, see http://packs.download.atmel.com/ */
|
||||||
|
|
||||||
|
__flash_size = 0x20000;
|
||||||
|
__ram_start = 0x100;
|
||||||
|
__ram_size = 0x1000;
|
||||||
|
__num_isrs = 35;
|
||||||
94
targets/device/avr/atmega128.s
Normal file
94
targets/device/avr/atmega128.s
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
; Automatically generated file. DO NOT EDIT.
|
||||||
|
; Generated by gen-device-avr.go from ATmega128.atdf, see http://packs.download.atmel.com/
|
||||||
|
|
||||||
|
; This is the default handler for interrupts, if triggered but not defined.
|
||||||
|
; Sleep inside so that an accidentally triggered interrupt won't drain the
|
||||||
|
; battery of a battery-powered device.
|
||||||
|
.section .text.__vector_default
|
||||||
|
.global __vector_default
|
||||||
|
__vector_default:
|
||||||
|
sleep
|
||||||
|
rjmp __vector_default
|
||||||
|
|
||||||
|
; Avoid the need for repeated .weak and .set instructions.
|
||||||
|
.macro IRQ handler
|
||||||
|
.weak \handler
|
||||||
|
.set \handler, __vector_default
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; The interrupt vector of this device. Must be placed at address 0 by the linker.
|
||||||
|
.section .vectors, "a", %progbits
|
||||||
|
.global __vectors
|
||||||
|
jmp __vector_RESET
|
||||||
|
jmp __vector_INT0
|
||||||
|
jmp __vector_INT1
|
||||||
|
jmp __vector_INT2
|
||||||
|
jmp __vector_INT3
|
||||||
|
jmp __vector_INT4
|
||||||
|
jmp __vector_INT5
|
||||||
|
jmp __vector_INT6
|
||||||
|
jmp __vector_INT7
|
||||||
|
jmp __vector_TIMER2_COMP
|
||||||
|
jmp __vector_TIMER2_OVF
|
||||||
|
jmp __vector_TIMER1_CAPT
|
||||||
|
jmp __vector_TIMER1_COMPA
|
||||||
|
jmp __vector_TIMER1_COMPB
|
||||||
|
jmp __vector_TIMER1_OVF
|
||||||
|
jmp __vector_TIMER0_COMP
|
||||||
|
jmp __vector_TIMER0_OVF
|
||||||
|
jmp __vector_SPI_STC
|
||||||
|
jmp __vector_USART0_RX
|
||||||
|
jmp __vector_USART0_UDRE
|
||||||
|
jmp __vector_USART0_TX
|
||||||
|
jmp __vector_ADC
|
||||||
|
jmp __vector_EE_READY
|
||||||
|
jmp __vector_ANALOG_COMP
|
||||||
|
jmp __vector_TIMER1_COMPC
|
||||||
|
jmp __vector_TIMER3_CAPT
|
||||||
|
jmp __vector_TIMER3_COMPA
|
||||||
|
jmp __vector_TIMER3_COMPB
|
||||||
|
jmp __vector_TIMER3_COMPC
|
||||||
|
jmp __vector_TIMER3_OVF
|
||||||
|
jmp __vector_USART1_RX
|
||||||
|
jmp __vector_USART1_UDRE
|
||||||
|
jmp __vector_USART1_TX
|
||||||
|
jmp __vector_TWI
|
||||||
|
jmp __vector_SPM_READY
|
||||||
|
|
||||||
|
; Define default implementations for interrupts, redirecting to
|
||||||
|
; __vector_default when not implemented.
|
||||||
|
IRQ __vector_RESET
|
||||||
|
IRQ __vector_INT0
|
||||||
|
IRQ __vector_INT1
|
||||||
|
IRQ __vector_INT2
|
||||||
|
IRQ __vector_INT3
|
||||||
|
IRQ __vector_INT4
|
||||||
|
IRQ __vector_INT5
|
||||||
|
IRQ __vector_INT6
|
||||||
|
IRQ __vector_INT7
|
||||||
|
IRQ __vector_TIMER2_COMP
|
||||||
|
IRQ __vector_TIMER2_OVF
|
||||||
|
IRQ __vector_TIMER1_CAPT
|
||||||
|
IRQ __vector_TIMER1_COMPA
|
||||||
|
IRQ __vector_TIMER1_COMPB
|
||||||
|
IRQ __vector_TIMER1_OVF
|
||||||
|
IRQ __vector_TIMER0_COMP
|
||||||
|
IRQ __vector_TIMER0_OVF
|
||||||
|
IRQ __vector_SPI_STC
|
||||||
|
IRQ __vector_USART0_RX
|
||||||
|
IRQ __vector_USART0_UDRE
|
||||||
|
IRQ __vector_USART0_TX
|
||||||
|
IRQ __vector_ADC
|
||||||
|
IRQ __vector_EE_READY
|
||||||
|
IRQ __vector_ANALOG_COMP
|
||||||
|
IRQ __vector_TIMER1_COMPC
|
||||||
|
IRQ __vector_TIMER3_CAPT
|
||||||
|
IRQ __vector_TIMER3_COMPA
|
||||||
|
IRQ __vector_TIMER3_COMPB
|
||||||
|
IRQ __vector_TIMER3_COMPC
|
||||||
|
IRQ __vector_TIMER3_OVF
|
||||||
|
IRQ __vector_USART1_RX
|
||||||
|
IRQ __vector_USART1_UDRE
|
||||||
|
IRQ __vector_USART1_TX
|
||||||
|
IRQ __vector_TWI
|
||||||
|
IRQ __vector_SPM_READY
|
||||||
7
targets/device/avr/atmega1280.ld
Normal file
7
targets/device/avr/atmega1280.ld
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
/* Automatically generated file. DO NOT EDIT. */
|
||||||
|
/* Generated by gen-device-avr.go from ATmega1280.atdf, see http://packs.download.atmel.com/ */
|
||||||
|
|
||||||
|
__flash_size = 0x20000;
|
||||||
|
__ram_start = 0x200;
|
||||||
|
__ram_size = 0x2000;
|
||||||
|
__num_isrs = 57;
|
||||||
138
targets/device/avr/atmega1280.s
Normal file
138
targets/device/avr/atmega1280.s
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
; Automatically generated file. DO NOT EDIT.
|
||||||
|
; Generated by gen-device-avr.go from ATmega1280.atdf, see http://packs.download.atmel.com/
|
||||||
|
|
||||||
|
; This is the default handler for interrupts, if triggered but not defined.
|
||||||
|
; Sleep inside so that an accidentally triggered interrupt won't drain the
|
||||||
|
; battery of a battery-powered device.
|
||||||
|
.section .text.__vector_default
|
||||||
|
.global __vector_default
|
||||||
|
__vector_default:
|
||||||
|
sleep
|
||||||
|
rjmp __vector_default
|
||||||
|
|
||||||
|
; Avoid the need for repeated .weak and .set instructions.
|
||||||
|
.macro IRQ handler
|
||||||
|
.weak \handler
|
||||||
|
.set \handler, __vector_default
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; The interrupt vector of this device. Must be placed at address 0 by the linker.
|
||||||
|
.section .vectors, "a", %progbits
|
||||||
|
.global __vectors
|
||||||
|
jmp __vector_RESET
|
||||||
|
jmp __vector_INT0
|
||||||
|
jmp __vector_INT1
|
||||||
|
jmp __vector_INT2
|
||||||
|
jmp __vector_INT3
|
||||||
|
jmp __vector_INT4
|
||||||
|
jmp __vector_INT5
|
||||||
|
jmp __vector_INT6
|
||||||
|
jmp __vector_INT7
|
||||||
|
jmp __vector_PCINT0
|
||||||
|
jmp __vector_PCINT1
|
||||||
|
jmp __vector_PCINT2
|
||||||
|
jmp __vector_WDT
|
||||||
|
jmp __vector_TIMER2_COMPA
|
||||||
|
jmp __vector_TIMER2_COMPB
|
||||||
|
jmp __vector_TIMER2_OVF
|
||||||
|
jmp __vector_TIMER1_CAPT
|
||||||
|
jmp __vector_TIMER1_COMPA
|
||||||
|
jmp __vector_TIMER1_COMPB
|
||||||
|
jmp __vector_TIMER1_COMPC
|
||||||
|
jmp __vector_TIMER1_OVF
|
||||||
|
jmp __vector_TIMER0_COMPA
|
||||||
|
jmp __vector_TIMER0_COMPB
|
||||||
|
jmp __vector_TIMER0_OVF
|
||||||
|
jmp __vector_SPI_STC
|
||||||
|
jmp __vector_USART0_RX
|
||||||
|
jmp __vector_USART0_UDRE
|
||||||
|
jmp __vector_USART0_TX
|
||||||
|
jmp __vector_ANALOG_COMP
|
||||||
|
jmp __vector_ADC
|
||||||
|
jmp __vector_EE_READY
|
||||||
|
jmp __vector_TIMER3_CAPT
|
||||||
|
jmp __vector_TIMER3_COMPA
|
||||||
|
jmp __vector_TIMER3_COMPB
|
||||||
|
jmp __vector_TIMER3_COMPC
|
||||||
|
jmp __vector_TIMER3_OVF
|
||||||
|
jmp __vector_USART1_RX
|
||||||
|
jmp __vector_USART1_UDRE
|
||||||
|
jmp __vector_USART1_TX
|
||||||
|
jmp __vector_TWI
|
||||||
|
jmp __vector_SPM_READY
|
||||||
|
jmp __vector_TIMER4_CAPT
|
||||||
|
jmp __vector_TIMER4_COMPA
|
||||||
|
jmp __vector_TIMER4_COMPB
|
||||||
|
jmp __vector_TIMER4_COMPC
|
||||||
|
jmp __vector_TIMER4_OVF
|
||||||
|
jmp __vector_TIMER5_CAPT
|
||||||
|
jmp __vector_TIMER5_COMPA
|
||||||
|
jmp __vector_TIMER5_COMPB
|
||||||
|
jmp __vector_TIMER5_COMPC
|
||||||
|
jmp __vector_TIMER5_OVF
|
||||||
|
jmp __vector_USART2_RX
|
||||||
|
jmp __vector_USART2_UDRE
|
||||||
|
jmp __vector_USART2_TX
|
||||||
|
jmp __vector_USART3_RX
|
||||||
|
jmp __vector_USART3_UDRE
|
||||||
|
jmp __vector_USART3_TX
|
||||||
|
|
||||||
|
; Define default implementations for interrupts, redirecting to
|
||||||
|
; __vector_default when not implemented.
|
||||||
|
IRQ __vector_RESET
|
||||||
|
IRQ __vector_INT0
|
||||||
|
IRQ __vector_INT1
|
||||||
|
IRQ __vector_INT2
|
||||||
|
IRQ __vector_INT3
|
||||||
|
IRQ __vector_INT4
|
||||||
|
IRQ __vector_INT5
|
||||||
|
IRQ __vector_INT6
|
||||||
|
IRQ __vector_INT7
|
||||||
|
IRQ __vector_PCINT0
|
||||||
|
IRQ __vector_PCINT1
|
||||||
|
IRQ __vector_PCINT2
|
||||||
|
IRQ __vector_WDT
|
||||||
|
IRQ __vector_TIMER2_COMPA
|
||||||
|
IRQ __vector_TIMER2_COMPB
|
||||||
|
IRQ __vector_TIMER2_OVF
|
||||||
|
IRQ __vector_TIMER1_CAPT
|
||||||
|
IRQ __vector_TIMER1_COMPA
|
||||||
|
IRQ __vector_TIMER1_COMPB
|
||||||
|
IRQ __vector_TIMER1_COMPC
|
||||||
|
IRQ __vector_TIMER1_OVF
|
||||||
|
IRQ __vector_TIMER0_COMPA
|
||||||
|
IRQ __vector_TIMER0_COMPB
|
||||||
|
IRQ __vector_TIMER0_OVF
|
||||||
|
IRQ __vector_SPI_STC
|
||||||
|
IRQ __vector_USART0_RX
|
||||||
|
IRQ __vector_USART0_UDRE
|
||||||
|
IRQ __vector_USART0_TX
|
||||||
|
IRQ __vector_ANALOG_COMP
|
||||||
|
IRQ __vector_ADC
|
||||||
|
IRQ __vector_EE_READY
|
||||||
|
IRQ __vector_TIMER3_CAPT
|
||||||
|
IRQ __vector_TIMER3_COMPA
|
||||||
|
IRQ __vector_TIMER3_COMPB
|
||||||
|
IRQ __vector_TIMER3_COMPC
|
||||||
|
IRQ __vector_TIMER3_OVF
|
||||||
|
IRQ __vector_USART1_RX
|
||||||
|
IRQ __vector_USART1_UDRE
|
||||||
|
IRQ __vector_USART1_TX
|
||||||
|
IRQ __vector_TWI
|
||||||
|
IRQ __vector_SPM_READY
|
||||||
|
IRQ __vector_TIMER4_CAPT
|
||||||
|
IRQ __vector_TIMER4_COMPA
|
||||||
|
IRQ __vector_TIMER4_COMPB
|
||||||
|
IRQ __vector_TIMER4_COMPC
|
||||||
|
IRQ __vector_TIMER4_OVF
|
||||||
|
IRQ __vector_TIMER5_CAPT
|
||||||
|
IRQ __vector_TIMER5_COMPA
|
||||||
|
IRQ __vector_TIMER5_COMPB
|
||||||
|
IRQ __vector_TIMER5_COMPC
|
||||||
|
IRQ __vector_TIMER5_OVF
|
||||||
|
IRQ __vector_USART2_RX
|
||||||
|
IRQ __vector_USART2_UDRE
|
||||||
|
IRQ __vector_USART2_TX
|
||||||
|
IRQ __vector_USART3_RX
|
||||||
|
IRQ __vector_USART3_UDRE
|
||||||
|
IRQ __vector_USART3_TX
|
||||||
7
targets/device/avr/atmega1281.ld
Normal file
7
targets/device/avr/atmega1281.ld
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
/* Automatically generated file. DO NOT EDIT. */
|
||||||
|
/* Generated by gen-device-avr.go from ATmega1281.atdf, see http://packs.download.atmel.com/ */
|
||||||
|
|
||||||
|
__flash_size = 0x20000;
|
||||||
|
__ram_start = 0x200;
|
||||||
|
__ram_size = 0x2000;
|
||||||
|
__num_isrs = 57;
|
||||||
138
targets/device/avr/atmega1281.s
Normal file
138
targets/device/avr/atmega1281.s
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
; Automatically generated file. DO NOT EDIT.
|
||||||
|
; Generated by gen-device-avr.go from ATmega1281.atdf, see http://packs.download.atmel.com/
|
||||||
|
|
||||||
|
; This is the default handler for interrupts, if triggered but not defined.
|
||||||
|
; Sleep inside so that an accidentally triggered interrupt won't drain the
|
||||||
|
; battery of a battery-powered device.
|
||||||
|
.section .text.__vector_default
|
||||||
|
.global __vector_default
|
||||||
|
__vector_default:
|
||||||
|
sleep
|
||||||
|
rjmp __vector_default
|
||||||
|
|
||||||
|
; Avoid the need for repeated .weak and .set instructions.
|
||||||
|
.macro IRQ handler
|
||||||
|
.weak \handler
|
||||||
|
.set \handler, __vector_default
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; The interrupt vector of this device. Must be placed at address 0 by the linker.
|
||||||
|
.section .vectors, "a", %progbits
|
||||||
|
.global __vectors
|
||||||
|
jmp __vector_RESET
|
||||||
|
jmp __vector_INT0
|
||||||
|
jmp __vector_INT1
|
||||||
|
jmp __vector_INT2
|
||||||
|
jmp __vector_INT3
|
||||||
|
jmp __vector_INT4
|
||||||
|
jmp __vector_INT5
|
||||||
|
jmp __vector_INT6
|
||||||
|
jmp __vector_INT7
|
||||||
|
jmp __vector_PCINT0
|
||||||
|
jmp __vector_PCINT1
|
||||||
|
jmp __vector_PCINT2
|
||||||
|
jmp __vector_WDT
|
||||||
|
jmp __vector_TIMER2_COMPA
|
||||||
|
jmp __vector_TIMER2_COMPB
|
||||||
|
jmp __vector_TIMER2_OVF
|
||||||
|
jmp __vector_TIMER1_CAPT
|
||||||
|
jmp __vector_TIMER1_COMPA
|
||||||
|
jmp __vector_TIMER1_COMPB
|
||||||
|
jmp __vector_TIMER1_COMPC
|
||||||
|
jmp __vector_TIMER1_OVF
|
||||||
|
jmp __vector_TIMER0_COMPA
|
||||||
|
jmp __vector_TIMER0_COMPB
|
||||||
|
jmp __vector_TIMER0_OVF
|
||||||
|
jmp __vector_SPI_STC
|
||||||
|
jmp __vector_USART0_RX
|
||||||
|
jmp __vector_USART0_UDRE
|
||||||
|
jmp __vector_USART0_TX
|
||||||
|
jmp __vector_ANALOG_COMP
|
||||||
|
jmp __vector_ADC
|
||||||
|
jmp __vector_EE_READY
|
||||||
|
jmp __vector_TIMER3_CAPT
|
||||||
|
jmp __vector_TIMER3_COMPA
|
||||||
|
jmp __vector_TIMER3_COMPB
|
||||||
|
jmp __vector_TIMER3_COMPC
|
||||||
|
jmp __vector_TIMER3_OVF
|
||||||
|
jmp __vector_USART1_RX
|
||||||
|
jmp __vector_USART1_UDRE
|
||||||
|
jmp __vector_USART1_TX
|
||||||
|
jmp __vector_TWI
|
||||||
|
jmp __vector_SPM_READY
|
||||||
|
jmp __vector_TIMER4_CAPT
|
||||||
|
jmp __vector_TIMER4_COMPA
|
||||||
|
jmp __vector_TIMER4_COMPB
|
||||||
|
jmp __vector_TIMER4_COMPC
|
||||||
|
jmp __vector_TIMER4_OVF
|
||||||
|
jmp __vector_TIMER5_CAPT
|
||||||
|
jmp __vector_TIMER5_COMPA
|
||||||
|
jmp __vector_TIMER5_COMPB
|
||||||
|
jmp __vector_TIMER5_COMPC
|
||||||
|
jmp __vector_TIMER5_OVF
|
||||||
|
jmp __vector_USART2_RX
|
||||||
|
jmp __vector_USART2_UDRE
|
||||||
|
jmp __vector_USART2_TX
|
||||||
|
jmp __vector_USART3_RX
|
||||||
|
jmp __vector_USART3_UDRE
|
||||||
|
jmp __vector_USART3_TX
|
||||||
|
|
||||||
|
; Define default implementations for interrupts, redirecting to
|
||||||
|
; __vector_default when not implemented.
|
||||||
|
IRQ __vector_RESET
|
||||||
|
IRQ __vector_INT0
|
||||||
|
IRQ __vector_INT1
|
||||||
|
IRQ __vector_INT2
|
||||||
|
IRQ __vector_INT3
|
||||||
|
IRQ __vector_INT4
|
||||||
|
IRQ __vector_INT5
|
||||||
|
IRQ __vector_INT6
|
||||||
|
IRQ __vector_INT7
|
||||||
|
IRQ __vector_PCINT0
|
||||||
|
IRQ __vector_PCINT1
|
||||||
|
IRQ __vector_PCINT2
|
||||||
|
IRQ __vector_WDT
|
||||||
|
IRQ __vector_TIMER2_COMPA
|
||||||
|
IRQ __vector_TIMER2_COMPB
|
||||||
|
IRQ __vector_TIMER2_OVF
|
||||||
|
IRQ __vector_TIMER1_CAPT
|
||||||
|
IRQ __vector_TIMER1_COMPA
|
||||||
|
IRQ __vector_TIMER1_COMPB
|
||||||
|
IRQ __vector_TIMER1_COMPC
|
||||||
|
IRQ __vector_TIMER1_OVF
|
||||||
|
IRQ __vector_TIMER0_COMPA
|
||||||
|
IRQ __vector_TIMER0_COMPB
|
||||||
|
IRQ __vector_TIMER0_OVF
|
||||||
|
IRQ __vector_SPI_STC
|
||||||
|
IRQ __vector_USART0_RX
|
||||||
|
IRQ __vector_USART0_UDRE
|
||||||
|
IRQ __vector_USART0_TX
|
||||||
|
IRQ __vector_ANALOG_COMP
|
||||||
|
IRQ __vector_ADC
|
||||||
|
IRQ __vector_EE_READY
|
||||||
|
IRQ __vector_TIMER3_CAPT
|
||||||
|
IRQ __vector_TIMER3_COMPA
|
||||||
|
IRQ __vector_TIMER3_COMPB
|
||||||
|
IRQ __vector_TIMER3_COMPC
|
||||||
|
IRQ __vector_TIMER3_OVF
|
||||||
|
IRQ __vector_USART1_RX
|
||||||
|
IRQ __vector_USART1_UDRE
|
||||||
|
IRQ __vector_USART1_TX
|
||||||
|
IRQ __vector_TWI
|
||||||
|
IRQ __vector_SPM_READY
|
||||||
|
IRQ __vector_TIMER4_CAPT
|
||||||
|
IRQ __vector_TIMER4_COMPA
|
||||||
|
IRQ __vector_TIMER4_COMPB
|
||||||
|
IRQ __vector_TIMER4_COMPC
|
||||||
|
IRQ __vector_TIMER4_OVF
|
||||||
|
IRQ __vector_TIMER5_CAPT
|
||||||
|
IRQ __vector_TIMER5_COMPA
|
||||||
|
IRQ __vector_TIMER5_COMPB
|
||||||
|
IRQ __vector_TIMER5_COMPC
|
||||||
|
IRQ __vector_TIMER5_OVF
|
||||||
|
IRQ __vector_USART2_RX
|
||||||
|
IRQ __vector_USART2_UDRE
|
||||||
|
IRQ __vector_USART2_TX
|
||||||
|
IRQ __vector_USART3_RX
|
||||||
|
IRQ __vector_USART3_UDRE
|
||||||
|
IRQ __vector_USART3_TX
|
||||||
7
targets/device/avr/atmega1284.ld
Normal file
7
targets/device/avr/atmega1284.ld
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
/* Automatically generated file. DO NOT EDIT. */
|
||||||
|
/* Generated by gen-device-avr.go from ATmega1284.atdf, see http://packs.download.atmel.com/ */
|
||||||
|
|
||||||
|
__flash_size = 0x20000;
|
||||||
|
__ram_start = 0x100;
|
||||||
|
__ram_size = 0x4000;
|
||||||
|
__num_isrs = 35;
|
||||||
94
targets/device/avr/atmega1284.s
Normal file
94
targets/device/avr/atmega1284.s
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
; Automatically generated file. DO NOT EDIT.
|
||||||
|
; Generated by gen-device-avr.go from ATmega1284.atdf, see http://packs.download.atmel.com/
|
||||||
|
|
||||||
|
; This is the default handler for interrupts, if triggered but not defined.
|
||||||
|
; Sleep inside so that an accidentally triggered interrupt won't drain the
|
||||||
|
; battery of a battery-powered device.
|
||||||
|
.section .text.__vector_default
|
||||||
|
.global __vector_default
|
||||||
|
__vector_default:
|
||||||
|
sleep
|
||||||
|
rjmp __vector_default
|
||||||
|
|
||||||
|
; Avoid the need for repeated .weak and .set instructions.
|
||||||
|
.macro IRQ handler
|
||||||
|
.weak \handler
|
||||||
|
.set \handler, __vector_default
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; The interrupt vector of this device. Must be placed at address 0 by the linker.
|
||||||
|
.section .vectors, "a", %progbits
|
||||||
|
.global __vectors
|
||||||
|
jmp __vector_RESET
|
||||||
|
jmp __vector_INT0
|
||||||
|
jmp __vector_INT1
|
||||||
|
jmp __vector_INT2
|
||||||
|
jmp __vector_PCINT0
|
||||||
|
jmp __vector_PCINT1
|
||||||
|
jmp __vector_PCINT2
|
||||||
|
jmp __vector_PCINT3
|
||||||
|
jmp __vector_WDT
|
||||||
|
jmp __vector_TIMER2_COMPA
|
||||||
|
jmp __vector_TIMER2_COMPB
|
||||||
|
jmp __vector_TIMER2_OVF
|
||||||
|
jmp __vector_TIMER1_CAPT
|
||||||
|
jmp __vector_TIMER1_COMPA
|
||||||
|
jmp __vector_TIMER1_COMPB
|
||||||
|
jmp __vector_TIMER1_OVF
|
||||||
|
jmp __vector_TIMER0_COMPA
|
||||||
|
jmp __vector_TIMER0_COMPB
|
||||||
|
jmp __vector_TIMER0_OVF
|
||||||
|
jmp __vector_SPI_STC
|
||||||
|
jmp __vector_USART0_RX
|
||||||
|
jmp __vector_USART0_UDRE
|
||||||
|
jmp __vector_USART0_TX
|
||||||
|
jmp __vector_ANALOG_COMP
|
||||||
|
jmp __vector_ADC
|
||||||
|
jmp __vector_EE_READY
|
||||||
|
jmp __vector_TWI
|
||||||
|
jmp __vector_SPM_READY
|
||||||
|
jmp __vector_USART1_RX
|
||||||
|
jmp __vector_USART1_UDRE
|
||||||
|
jmp __vector_USART1_TX
|
||||||
|
jmp __vector_TIMER3_CAPT
|
||||||
|
jmp __vector_TIMER3_COMPA
|
||||||
|
jmp __vector_TIMER3_COMPB
|
||||||
|
jmp __vector_TIMER3_OVF
|
||||||
|
|
||||||
|
; Define default implementations for interrupts, redirecting to
|
||||||
|
; __vector_default when not implemented.
|
||||||
|
IRQ __vector_RESET
|
||||||
|
IRQ __vector_INT0
|
||||||
|
IRQ __vector_INT1
|
||||||
|
IRQ __vector_INT2
|
||||||
|
IRQ __vector_PCINT0
|
||||||
|
IRQ __vector_PCINT1
|
||||||
|
IRQ __vector_PCINT2
|
||||||
|
IRQ __vector_PCINT3
|
||||||
|
IRQ __vector_WDT
|
||||||
|
IRQ __vector_TIMER2_COMPA
|
||||||
|
IRQ __vector_TIMER2_COMPB
|
||||||
|
IRQ __vector_TIMER2_OVF
|
||||||
|
IRQ __vector_TIMER1_CAPT
|
||||||
|
IRQ __vector_TIMER1_COMPA
|
||||||
|
IRQ __vector_TIMER1_COMPB
|
||||||
|
IRQ __vector_TIMER1_OVF
|
||||||
|
IRQ __vector_TIMER0_COMPA
|
||||||
|
IRQ __vector_TIMER0_COMPB
|
||||||
|
IRQ __vector_TIMER0_OVF
|
||||||
|
IRQ __vector_SPI_STC
|
||||||
|
IRQ __vector_USART0_RX
|
||||||
|
IRQ __vector_USART0_UDRE
|
||||||
|
IRQ __vector_USART0_TX
|
||||||
|
IRQ __vector_ANALOG_COMP
|
||||||
|
IRQ __vector_ADC
|
||||||
|
IRQ __vector_EE_READY
|
||||||
|
IRQ __vector_TWI
|
||||||
|
IRQ __vector_SPM_READY
|
||||||
|
IRQ __vector_USART1_RX
|
||||||
|
IRQ __vector_USART1_UDRE
|
||||||
|
IRQ __vector_USART1_TX
|
||||||
|
IRQ __vector_TIMER3_CAPT
|
||||||
|
IRQ __vector_TIMER3_COMPA
|
||||||
|
IRQ __vector_TIMER3_COMPB
|
||||||
|
IRQ __vector_TIMER3_OVF
|
||||||
7
targets/device/avr/atmega1284p.ld
Normal file
7
targets/device/avr/atmega1284p.ld
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
/* Automatically generated file. DO NOT EDIT. */
|
||||||
|
/* Generated by gen-device-avr.go from ATmega1284P.atdf, see http://packs.download.atmel.com/ */
|
||||||
|
|
||||||
|
__flash_size = 0x20000;
|
||||||
|
__ram_start = 0x100;
|
||||||
|
__ram_size = 0x4000;
|
||||||
|
__num_isrs = 35;
|
||||||
94
targets/device/avr/atmega1284p.s
Normal file
94
targets/device/avr/atmega1284p.s
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
; Automatically generated file. DO NOT EDIT.
|
||||||
|
; Generated by gen-device-avr.go from ATmega1284P.atdf, see http://packs.download.atmel.com/
|
||||||
|
|
||||||
|
; This is the default handler for interrupts, if triggered but not defined.
|
||||||
|
; Sleep inside so that an accidentally triggered interrupt won't drain the
|
||||||
|
; battery of a battery-powered device.
|
||||||
|
.section .text.__vector_default
|
||||||
|
.global __vector_default
|
||||||
|
__vector_default:
|
||||||
|
sleep
|
||||||
|
rjmp __vector_default
|
||||||
|
|
||||||
|
; Avoid the need for repeated .weak and .set instructions.
|
||||||
|
.macro IRQ handler
|
||||||
|
.weak \handler
|
||||||
|
.set \handler, __vector_default
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; The interrupt vector of this device. Must be placed at address 0 by the linker.
|
||||||
|
.section .vectors, "a", %progbits
|
||||||
|
.global __vectors
|
||||||
|
jmp __vector_RESET
|
||||||
|
jmp __vector_INT0
|
||||||
|
jmp __vector_INT1
|
||||||
|
jmp __vector_INT2
|
||||||
|
jmp __vector_PCINT0
|
||||||
|
jmp __vector_PCINT1
|
||||||
|
jmp __vector_PCINT2
|
||||||
|
jmp __vector_PCINT3
|
||||||
|
jmp __vector_WDT
|
||||||
|
jmp __vector_TIMER2_COMPA
|
||||||
|
jmp __vector_TIMER2_COMPB
|
||||||
|
jmp __vector_TIMER2_OVF
|
||||||
|
jmp __vector_TIMER1_CAPT
|
||||||
|
jmp __vector_TIMER1_COMPA
|
||||||
|
jmp __vector_TIMER1_COMPB
|
||||||
|
jmp __vector_TIMER1_OVF
|
||||||
|
jmp __vector_TIMER0_COMPA
|
||||||
|
jmp __vector_TIMER0_COMPB
|
||||||
|
jmp __vector_TIMER0_OVF
|
||||||
|
jmp __vector_SPI_STC
|
||||||
|
jmp __vector_USART0_RX
|
||||||
|
jmp __vector_USART0_UDRE
|
||||||
|
jmp __vector_USART0_TX
|
||||||
|
jmp __vector_ANALOG_COMP
|
||||||
|
jmp __vector_ADC
|
||||||
|
jmp __vector_EE_READY
|
||||||
|
jmp __vector_TWI
|
||||||
|
jmp __vector_SPM_READY
|
||||||
|
jmp __vector_USART1_RX
|
||||||
|
jmp __vector_USART1_UDRE
|
||||||
|
jmp __vector_USART1_TX
|
||||||
|
jmp __vector_TIMER3_CAPT
|
||||||
|
jmp __vector_TIMER3_COMPA
|
||||||
|
jmp __vector_TIMER3_COMPB
|
||||||
|
jmp __vector_TIMER3_OVF
|
||||||
|
|
||||||
|
; Define default implementations for interrupts, redirecting to
|
||||||
|
; __vector_default when not implemented.
|
||||||
|
IRQ __vector_RESET
|
||||||
|
IRQ __vector_INT0
|
||||||
|
IRQ __vector_INT1
|
||||||
|
IRQ __vector_INT2
|
||||||
|
IRQ __vector_PCINT0
|
||||||
|
IRQ __vector_PCINT1
|
||||||
|
IRQ __vector_PCINT2
|
||||||
|
IRQ __vector_PCINT3
|
||||||
|
IRQ __vector_WDT
|
||||||
|
IRQ __vector_TIMER2_COMPA
|
||||||
|
IRQ __vector_TIMER2_COMPB
|
||||||
|
IRQ __vector_TIMER2_OVF
|
||||||
|
IRQ __vector_TIMER1_CAPT
|
||||||
|
IRQ __vector_TIMER1_COMPA
|
||||||
|
IRQ __vector_TIMER1_COMPB
|
||||||
|
IRQ __vector_TIMER1_OVF
|
||||||
|
IRQ __vector_TIMER0_COMPA
|
||||||
|
IRQ __vector_TIMER0_COMPB
|
||||||
|
IRQ __vector_TIMER0_OVF
|
||||||
|
IRQ __vector_SPI_STC
|
||||||
|
IRQ __vector_USART0_RX
|
||||||
|
IRQ __vector_USART0_UDRE
|
||||||
|
IRQ __vector_USART0_TX
|
||||||
|
IRQ __vector_ANALOG_COMP
|
||||||
|
IRQ __vector_ADC
|
||||||
|
IRQ __vector_EE_READY
|
||||||
|
IRQ __vector_TWI
|
||||||
|
IRQ __vector_SPM_READY
|
||||||
|
IRQ __vector_USART1_RX
|
||||||
|
IRQ __vector_USART1_UDRE
|
||||||
|
IRQ __vector_USART1_TX
|
||||||
|
IRQ __vector_TIMER3_CAPT
|
||||||
|
IRQ __vector_TIMER3_COMPA
|
||||||
|
IRQ __vector_TIMER3_COMPB
|
||||||
|
IRQ __vector_TIMER3_OVF
|
||||||
7
targets/device/avr/atmega1284rfr2.ld
Normal file
7
targets/device/avr/atmega1284rfr2.ld
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
/* Automatically generated file. DO NOT EDIT. */
|
||||||
|
/* Generated by gen-device-avr.go from ATmega1284RFR2.atdf, see http://packs.download.atmel.com/ */
|
||||||
|
|
||||||
|
__flash_size = 0x20000;
|
||||||
|
__ram_start = 0x200;
|
||||||
|
__ram_size = 0x4000;
|
||||||
|
__num_isrs = 71;
|
||||||
172
targets/device/avr/atmega1284rfr2.s
Normal file
172
targets/device/avr/atmega1284rfr2.s
Normal file
@@ -0,0 +1,172 @@
|
|||||||
|
; Automatically generated file. DO NOT EDIT.
|
||||||
|
; Generated by gen-device-avr.go from ATmega1284RFR2.atdf, see http://packs.download.atmel.com/
|
||||||
|
|
||||||
|
; This is the default handler for interrupts, if triggered but not defined.
|
||||||
|
; Sleep inside so that an accidentally triggered interrupt won't drain the
|
||||||
|
; battery of a battery-powered device.
|
||||||
|
.section .text.__vector_default
|
||||||
|
.global __vector_default
|
||||||
|
__vector_default:
|
||||||
|
sleep
|
||||||
|
rjmp __vector_default
|
||||||
|
|
||||||
|
; Avoid the need for repeated .weak and .set instructions.
|
||||||
|
.macro IRQ handler
|
||||||
|
.weak \handler
|
||||||
|
.set \handler, __vector_default
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; The interrupt vector of this device. Must be placed at address 0 by the linker.
|
||||||
|
.section .vectors, "a", %progbits
|
||||||
|
.global __vectors
|
||||||
|
jmp __vector_RESET
|
||||||
|
jmp __vector_INT0
|
||||||
|
jmp __vector_INT1
|
||||||
|
jmp __vector_INT2
|
||||||
|
jmp __vector_INT3
|
||||||
|
jmp __vector_INT4
|
||||||
|
jmp __vector_INT5
|
||||||
|
jmp __vector_INT6
|
||||||
|
jmp __vector_INT7
|
||||||
|
jmp __vector_PCINT0
|
||||||
|
jmp __vector_PCINT1
|
||||||
|
jmp __vector_PCINT2
|
||||||
|
jmp __vector_WDT
|
||||||
|
jmp __vector_TIMER2_COMPA
|
||||||
|
jmp __vector_TIMER2_COMPB
|
||||||
|
jmp __vector_TIMER2_OVF
|
||||||
|
jmp __vector_TIMER1_CAPT
|
||||||
|
jmp __vector_TIMER1_COMPA
|
||||||
|
jmp __vector_TIMER1_COMPB
|
||||||
|
jmp __vector_TIMER1_COMPC
|
||||||
|
jmp __vector_TIMER1_OVF
|
||||||
|
jmp __vector_TIMER0_COMPA
|
||||||
|
jmp __vector_TIMER0_COMPB
|
||||||
|
jmp __vector_TIMER0_OVF
|
||||||
|
jmp __vector_SPI_STC
|
||||||
|
jmp __vector_USART0_RX
|
||||||
|
jmp __vector_USART0_UDRE
|
||||||
|
jmp __vector_USART0_TX
|
||||||
|
jmp __vector_ANALOG_COMP
|
||||||
|
jmp __vector_ADC
|
||||||
|
jmp __vector_EE_READY
|
||||||
|
jmp __vector_TIMER3_CAPT
|
||||||
|
jmp __vector_TIMER3_COMPA
|
||||||
|
jmp __vector_TIMER3_COMPB
|
||||||
|
jmp __vector_TIMER3_COMPC
|
||||||
|
jmp __vector_TIMER3_OVF
|
||||||
|
jmp __vector_USART1_RX
|
||||||
|
jmp __vector_USART1_UDRE
|
||||||
|
jmp __vector_USART1_TX
|
||||||
|
jmp __vector_TWI
|
||||||
|
jmp __vector_SPM_READY
|
||||||
|
jmp __vector_TIMER4_CAPT
|
||||||
|
jmp __vector_TIMER4_COMPA
|
||||||
|
jmp __vector_TIMER4_COMPB
|
||||||
|
jmp __vector_TIMER4_COMPC
|
||||||
|
jmp __vector_TIMER4_OVF
|
||||||
|
jmp __vector_TIMER5_CAPT
|
||||||
|
jmp __vector_TIMER5_COMPA
|
||||||
|
jmp __vector_TIMER5_COMPB
|
||||||
|
jmp __vector_TIMER5_COMPC
|
||||||
|
jmp __vector_TIMER5_OVF
|
||||||
|
jmp __vector_default
|
||||||
|
jmp __vector_default
|
||||||
|
jmp __vector_default
|
||||||
|
jmp __vector_default
|
||||||
|
jmp __vector_default
|
||||||
|
jmp __vector_default
|
||||||
|
jmp __vector_TRX24_PLL_LOCK
|
||||||
|
jmp __vector_TRX24_PLL_UNLOCK
|
||||||
|
jmp __vector_TRX24_RX_START
|
||||||
|
jmp __vector_TRX24_RX_END
|
||||||
|
jmp __vector_TRX24_CCA_ED_DONE
|
||||||
|
jmp __vector_TRX24_XAH_AMI
|
||||||
|
jmp __vector_TRX24_TX_END
|
||||||
|
jmp __vector_TRX24_AWAKE
|
||||||
|
jmp __vector_SCNT_CMP1
|
||||||
|
jmp __vector_SCNT_CMP2
|
||||||
|
jmp __vector_SCNT_CMP3
|
||||||
|
jmp __vector_SCNT_OVFL
|
||||||
|
jmp __vector_SCNT_BACKOFF
|
||||||
|
jmp __vector_AES_READY
|
||||||
|
jmp __vector_BAT_LOW
|
||||||
|
jmp __vector_TRX24_TX_START
|
||||||
|
jmp __vector_TRX24_AMI0
|
||||||
|
jmp __vector_TRX24_AMI1
|
||||||
|
jmp __vector_TRX24_AMI2
|
||||||
|
jmp __vector_TRX24_AMI3
|
||||||
|
|
||||||
|
; Define default implementations for interrupts, redirecting to
|
||||||
|
; __vector_default when not implemented.
|
||||||
|
IRQ __vector_RESET
|
||||||
|
IRQ __vector_INT0
|
||||||
|
IRQ __vector_INT1
|
||||||
|
IRQ __vector_INT2
|
||||||
|
IRQ __vector_INT3
|
||||||
|
IRQ __vector_INT4
|
||||||
|
IRQ __vector_INT5
|
||||||
|
IRQ __vector_INT6
|
||||||
|
IRQ __vector_INT7
|
||||||
|
IRQ __vector_PCINT0
|
||||||
|
IRQ __vector_PCINT1
|
||||||
|
IRQ __vector_PCINT2
|
||||||
|
IRQ __vector_WDT
|
||||||
|
IRQ __vector_TIMER2_COMPA
|
||||||
|
IRQ __vector_TIMER2_COMPB
|
||||||
|
IRQ __vector_TIMER2_OVF
|
||||||
|
IRQ __vector_TIMER1_CAPT
|
||||||
|
IRQ __vector_TIMER1_COMPA
|
||||||
|
IRQ __vector_TIMER1_COMPB
|
||||||
|
IRQ __vector_TIMER1_COMPC
|
||||||
|
IRQ __vector_TIMER1_OVF
|
||||||
|
IRQ __vector_TIMER0_COMPA
|
||||||
|
IRQ __vector_TIMER0_COMPB
|
||||||
|
IRQ __vector_TIMER0_OVF
|
||||||
|
IRQ __vector_SPI_STC
|
||||||
|
IRQ __vector_USART0_RX
|
||||||
|
IRQ __vector_USART0_UDRE
|
||||||
|
IRQ __vector_USART0_TX
|
||||||
|
IRQ __vector_ANALOG_COMP
|
||||||
|
IRQ __vector_ADC
|
||||||
|
IRQ __vector_EE_READY
|
||||||
|
IRQ __vector_TIMER3_CAPT
|
||||||
|
IRQ __vector_TIMER3_COMPA
|
||||||
|
IRQ __vector_TIMER3_COMPB
|
||||||
|
IRQ __vector_TIMER3_COMPC
|
||||||
|
IRQ __vector_TIMER3_OVF
|
||||||
|
IRQ __vector_USART1_RX
|
||||||
|
IRQ __vector_USART1_UDRE
|
||||||
|
IRQ __vector_USART1_TX
|
||||||
|
IRQ __vector_TWI
|
||||||
|
IRQ __vector_SPM_READY
|
||||||
|
IRQ __vector_TIMER4_CAPT
|
||||||
|
IRQ __vector_TIMER4_COMPA
|
||||||
|
IRQ __vector_TIMER4_COMPB
|
||||||
|
IRQ __vector_TIMER4_COMPC
|
||||||
|
IRQ __vector_TIMER4_OVF
|
||||||
|
IRQ __vector_TIMER5_CAPT
|
||||||
|
IRQ __vector_TIMER5_COMPA
|
||||||
|
IRQ __vector_TIMER5_COMPB
|
||||||
|
IRQ __vector_TIMER5_COMPC
|
||||||
|
IRQ __vector_TIMER5_OVF
|
||||||
|
IRQ __vector_TRX24_PLL_LOCK
|
||||||
|
IRQ __vector_TRX24_PLL_UNLOCK
|
||||||
|
IRQ __vector_TRX24_RX_START
|
||||||
|
IRQ __vector_TRX24_RX_END
|
||||||
|
IRQ __vector_TRX24_CCA_ED_DONE
|
||||||
|
IRQ __vector_TRX24_XAH_AMI
|
||||||
|
IRQ __vector_TRX24_TX_END
|
||||||
|
IRQ __vector_TRX24_AWAKE
|
||||||
|
IRQ __vector_SCNT_CMP1
|
||||||
|
IRQ __vector_SCNT_CMP2
|
||||||
|
IRQ __vector_SCNT_CMP3
|
||||||
|
IRQ __vector_SCNT_OVFL
|
||||||
|
IRQ __vector_SCNT_BACKOFF
|
||||||
|
IRQ __vector_AES_READY
|
||||||
|
IRQ __vector_BAT_LOW
|
||||||
|
IRQ __vector_TRX24_TX_START
|
||||||
|
IRQ __vector_TRX24_AMI0
|
||||||
|
IRQ __vector_TRX24_AMI1
|
||||||
|
IRQ __vector_TRX24_AMI2
|
||||||
|
IRQ __vector_TRX24_AMI3
|
||||||
7
targets/device/avr/atmega128a.ld
Normal file
7
targets/device/avr/atmega128a.ld
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
/* Automatically generated file. DO NOT EDIT. */
|
||||||
|
/* Generated by gen-device-avr.go from ATmega128A.atdf, see http://packs.download.atmel.com/ */
|
||||||
|
|
||||||
|
__flash_size = 0x20000;
|
||||||
|
__ram_start = 0x100;
|
||||||
|
__ram_size = 0x1000;
|
||||||
|
__num_isrs = 35;
|
||||||
94
targets/device/avr/atmega128a.s
Normal file
94
targets/device/avr/atmega128a.s
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
; Automatically generated file. DO NOT EDIT.
|
||||||
|
; Generated by gen-device-avr.go from ATmega128A.atdf, see http://packs.download.atmel.com/
|
||||||
|
|
||||||
|
; This is the default handler for interrupts, if triggered but not defined.
|
||||||
|
; Sleep inside so that an accidentally triggered interrupt won't drain the
|
||||||
|
; battery of a battery-powered device.
|
||||||
|
.section .text.__vector_default
|
||||||
|
.global __vector_default
|
||||||
|
__vector_default:
|
||||||
|
sleep
|
||||||
|
rjmp __vector_default
|
||||||
|
|
||||||
|
; Avoid the need for repeated .weak and .set instructions.
|
||||||
|
.macro IRQ handler
|
||||||
|
.weak \handler
|
||||||
|
.set \handler, __vector_default
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; The interrupt vector of this device. Must be placed at address 0 by the linker.
|
||||||
|
.section .vectors, "a", %progbits
|
||||||
|
.global __vectors
|
||||||
|
jmp __vector_RESET
|
||||||
|
jmp __vector_INT0
|
||||||
|
jmp __vector_INT1
|
||||||
|
jmp __vector_INT2
|
||||||
|
jmp __vector_INT3
|
||||||
|
jmp __vector_INT4
|
||||||
|
jmp __vector_INT5
|
||||||
|
jmp __vector_INT6
|
||||||
|
jmp __vector_INT7
|
||||||
|
jmp __vector_TIMER2_COMP
|
||||||
|
jmp __vector_TIMER2_OVF
|
||||||
|
jmp __vector_TIMER1_CAPT
|
||||||
|
jmp __vector_TIMER1_COMPA
|
||||||
|
jmp __vector_TIMER1_COMPB
|
||||||
|
jmp __vector_TIMER1_OVF
|
||||||
|
jmp __vector_TIMER0_COMP
|
||||||
|
jmp __vector_TIMER0_OVF
|
||||||
|
jmp __vector_SPI_STC
|
||||||
|
jmp __vector_USART0_RX
|
||||||
|
jmp __vector_USART0_UDRE
|
||||||
|
jmp __vector_USART0_TX
|
||||||
|
jmp __vector_ADC
|
||||||
|
jmp __vector_EE_READY
|
||||||
|
jmp __vector_ANALOG_COMP
|
||||||
|
jmp __vector_TIMER1_COMPC
|
||||||
|
jmp __vector_TIMER3_CAPT
|
||||||
|
jmp __vector_TIMER3_COMPA
|
||||||
|
jmp __vector_TIMER3_COMPB
|
||||||
|
jmp __vector_TIMER3_COMPC
|
||||||
|
jmp __vector_TIMER3_OVF
|
||||||
|
jmp __vector_USART1_RX
|
||||||
|
jmp __vector_USART1_UDRE
|
||||||
|
jmp __vector_USART1_TX
|
||||||
|
jmp __vector_TWI
|
||||||
|
jmp __vector_SPM_READY
|
||||||
|
|
||||||
|
; Define default implementations for interrupts, redirecting to
|
||||||
|
; __vector_default when not implemented.
|
||||||
|
IRQ __vector_RESET
|
||||||
|
IRQ __vector_INT0
|
||||||
|
IRQ __vector_INT1
|
||||||
|
IRQ __vector_INT2
|
||||||
|
IRQ __vector_INT3
|
||||||
|
IRQ __vector_INT4
|
||||||
|
IRQ __vector_INT5
|
||||||
|
IRQ __vector_INT6
|
||||||
|
IRQ __vector_INT7
|
||||||
|
IRQ __vector_TIMER2_COMP
|
||||||
|
IRQ __vector_TIMER2_OVF
|
||||||
|
IRQ __vector_TIMER1_CAPT
|
||||||
|
IRQ __vector_TIMER1_COMPA
|
||||||
|
IRQ __vector_TIMER1_COMPB
|
||||||
|
IRQ __vector_TIMER1_OVF
|
||||||
|
IRQ __vector_TIMER0_COMP
|
||||||
|
IRQ __vector_TIMER0_OVF
|
||||||
|
IRQ __vector_SPI_STC
|
||||||
|
IRQ __vector_USART0_RX
|
||||||
|
IRQ __vector_USART0_UDRE
|
||||||
|
IRQ __vector_USART0_TX
|
||||||
|
IRQ __vector_ADC
|
||||||
|
IRQ __vector_EE_READY
|
||||||
|
IRQ __vector_ANALOG_COMP
|
||||||
|
IRQ __vector_TIMER1_COMPC
|
||||||
|
IRQ __vector_TIMER3_CAPT
|
||||||
|
IRQ __vector_TIMER3_COMPA
|
||||||
|
IRQ __vector_TIMER3_COMPB
|
||||||
|
IRQ __vector_TIMER3_COMPC
|
||||||
|
IRQ __vector_TIMER3_OVF
|
||||||
|
IRQ __vector_USART1_RX
|
||||||
|
IRQ __vector_USART1_UDRE
|
||||||
|
IRQ __vector_USART1_TX
|
||||||
|
IRQ __vector_TWI
|
||||||
|
IRQ __vector_SPM_READY
|
||||||
7
targets/device/avr/atmega128rfa1.ld
Normal file
7
targets/device/avr/atmega128rfa1.ld
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
/* Automatically generated file. DO NOT EDIT. */
|
||||||
|
/* Generated by gen-device-avr.go from ATmega128RFA1.atdf, see http://packs.download.atmel.com/ */
|
||||||
|
|
||||||
|
__flash_size = 0x20000;
|
||||||
|
__ram_start = 0x200;
|
||||||
|
__ram_size = 0x4000;
|
||||||
|
__num_isrs = 72;
|
||||||
168
targets/device/avr/atmega128rfa1.s
Normal file
168
targets/device/avr/atmega128rfa1.s
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
; Automatically generated file. DO NOT EDIT.
|
||||||
|
; Generated by gen-device-avr.go from ATmega128RFA1.atdf, see http://packs.download.atmel.com/
|
||||||
|
|
||||||
|
; This is the default handler for interrupts, if triggered but not defined.
|
||||||
|
; Sleep inside so that an accidentally triggered interrupt won't drain the
|
||||||
|
; battery of a battery-powered device.
|
||||||
|
.section .text.__vector_default
|
||||||
|
.global __vector_default
|
||||||
|
__vector_default:
|
||||||
|
sleep
|
||||||
|
rjmp __vector_default
|
||||||
|
|
||||||
|
; Avoid the need for repeated .weak and .set instructions.
|
||||||
|
.macro IRQ handler
|
||||||
|
.weak \handler
|
||||||
|
.set \handler, __vector_default
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; The interrupt vector of this device. Must be placed at address 0 by the linker.
|
||||||
|
.section .vectors, "a", %progbits
|
||||||
|
.global __vectors
|
||||||
|
jmp __vector_RESET
|
||||||
|
jmp __vector_INT0
|
||||||
|
jmp __vector_INT1
|
||||||
|
jmp __vector_INT2
|
||||||
|
jmp __vector_INT3
|
||||||
|
jmp __vector_INT4
|
||||||
|
jmp __vector_INT5
|
||||||
|
jmp __vector_INT6
|
||||||
|
jmp __vector_INT7
|
||||||
|
jmp __vector_PCINT0
|
||||||
|
jmp __vector_PCINT1
|
||||||
|
jmp __vector_PCINT2
|
||||||
|
jmp __vector_WDT
|
||||||
|
jmp __vector_TIMER2_COMPA
|
||||||
|
jmp __vector_TIMER2_COMPB
|
||||||
|
jmp __vector_TIMER2_OVF
|
||||||
|
jmp __vector_TIMER1_CAPT
|
||||||
|
jmp __vector_TIMER1_COMPA
|
||||||
|
jmp __vector_TIMER1_COMPB
|
||||||
|
jmp __vector_TIMER1_COMPC
|
||||||
|
jmp __vector_TIMER1_OVF
|
||||||
|
jmp __vector_TIMER0_COMPA
|
||||||
|
jmp __vector_TIMER0_COMPB
|
||||||
|
jmp __vector_TIMER0_OVF
|
||||||
|
jmp __vector_SPI_STC
|
||||||
|
jmp __vector_USART0_RX
|
||||||
|
jmp __vector_USART0_UDRE
|
||||||
|
jmp __vector_USART0_TX
|
||||||
|
jmp __vector_ANALOG_COMP
|
||||||
|
jmp __vector_ADC
|
||||||
|
jmp __vector_EE_READY
|
||||||
|
jmp __vector_TIMER3_CAPT
|
||||||
|
jmp __vector_TIMER3_COMPA
|
||||||
|
jmp __vector_TIMER3_COMPB
|
||||||
|
jmp __vector_TIMER3_COMPC
|
||||||
|
jmp __vector_TIMER3_OVF
|
||||||
|
jmp __vector_USART1_RX
|
||||||
|
jmp __vector_USART1_UDRE
|
||||||
|
jmp __vector_USART1_TX
|
||||||
|
jmp __vector_TWI
|
||||||
|
jmp __vector_SPM_READY
|
||||||
|
jmp __vector_TIMER4_CAPT
|
||||||
|
jmp __vector_TIMER4_COMPA
|
||||||
|
jmp __vector_TIMER4_COMPB
|
||||||
|
jmp __vector_TIMER4_COMPC
|
||||||
|
jmp __vector_TIMER4_OVF
|
||||||
|
jmp __vector_TIMER5_CAPT
|
||||||
|
jmp __vector_TIMER5_COMPA
|
||||||
|
jmp __vector_TIMER5_COMPB
|
||||||
|
jmp __vector_TIMER5_COMPC
|
||||||
|
jmp __vector_TIMER5_OVF
|
||||||
|
jmp __vector_USART2_RX
|
||||||
|
jmp __vector_USART2_UDRE
|
||||||
|
jmp __vector_USART2_TX
|
||||||
|
jmp __vector_USART3_RX
|
||||||
|
jmp __vector_USART3_UDRE
|
||||||
|
jmp __vector_USART3_TX
|
||||||
|
jmp __vector_TRX24_PLL_LOCK
|
||||||
|
jmp __vector_TRX24_PLL_UNLOCK
|
||||||
|
jmp __vector_TRX24_RX_START
|
||||||
|
jmp __vector_TRX24_RX_END
|
||||||
|
jmp __vector_TRX24_CCA_ED_DONE
|
||||||
|
jmp __vector_TRX24_XAH_AMI
|
||||||
|
jmp __vector_TRX24_TX_END
|
||||||
|
jmp __vector_TRX24_AWAKE
|
||||||
|
jmp __vector_SCNT_CMP1
|
||||||
|
jmp __vector_SCNT_CMP2
|
||||||
|
jmp __vector_SCNT_CMP3
|
||||||
|
jmp __vector_SCNT_OVFL
|
||||||
|
jmp __vector_SCNT_BACKOFF
|
||||||
|
jmp __vector_AES_READY
|
||||||
|
jmp __vector_BAT_LOW
|
||||||
|
|
||||||
|
; Define default implementations for interrupts, redirecting to
|
||||||
|
; __vector_default when not implemented.
|
||||||
|
IRQ __vector_RESET
|
||||||
|
IRQ __vector_INT0
|
||||||
|
IRQ __vector_INT1
|
||||||
|
IRQ __vector_INT2
|
||||||
|
IRQ __vector_INT3
|
||||||
|
IRQ __vector_INT4
|
||||||
|
IRQ __vector_INT5
|
||||||
|
IRQ __vector_INT6
|
||||||
|
IRQ __vector_INT7
|
||||||
|
IRQ __vector_PCINT0
|
||||||
|
IRQ __vector_PCINT1
|
||||||
|
IRQ __vector_PCINT2
|
||||||
|
IRQ __vector_WDT
|
||||||
|
IRQ __vector_TIMER2_COMPA
|
||||||
|
IRQ __vector_TIMER2_COMPB
|
||||||
|
IRQ __vector_TIMER2_OVF
|
||||||
|
IRQ __vector_TIMER1_CAPT
|
||||||
|
IRQ __vector_TIMER1_COMPA
|
||||||
|
IRQ __vector_TIMER1_COMPB
|
||||||
|
IRQ __vector_TIMER1_COMPC
|
||||||
|
IRQ __vector_TIMER1_OVF
|
||||||
|
IRQ __vector_TIMER0_COMPA
|
||||||
|
IRQ __vector_TIMER0_COMPB
|
||||||
|
IRQ __vector_TIMER0_OVF
|
||||||
|
IRQ __vector_SPI_STC
|
||||||
|
IRQ __vector_USART0_RX
|
||||||
|
IRQ __vector_USART0_UDRE
|
||||||
|
IRQ __vector_USART0_TX
|
||||||
|
IRQ __vector_ANALOG_COMP
|
||||||
|
IRQ __vector_ADC
|
||||||
|
IRQ __vector_EE_READY
|
||||||
|
IRQ __vector_TIMER3_CAPT
|
||||||
|
IRQ __vector_TIMER3_COMPA
|
||||||
|
IRQ __vector_TIMER3_COMPB
|
||||||
|
IRQ __vector_TIMER3_COMPC
|
||||||
|
IRQ __vector_TIMER3_OVF
|
||||||
|
IRQ __vector_USART1_RX
|
||||||
|
IRQ __vector_USART1_UDRE
|
||||||
|
IRQ __vector_USART1_TX
|
||||||
|
IRQ __vector_TWI
|
||||||
|
IRQ __vector_SPM_READY
|
||||||
|
IRQ __vector_TIMER4_CAPT
|
||||||
|
IRQ __vector_TIMER4_COMPA
|
||||||
|
IRQ __vector_TIMER4_COMPB
|
||||||
|
IRQ __vector_TIMER4_COMPC
|
||||||
|
IRQ __vector_TIMER4_OVF
|
||||||
|
IRQ __vector_TIMER5_CAPT
|
||||||
|
IRQ __vector_TIMER5_COMPA
|
||||||
|
IRQ __vector_TIMER5_COMPB
|
||||||
|
IRQ __vector_TIMER5_COMPC
|
||||||
|
IRQ __vector_TIMER5_OVF
|
||||||
|
IRQ __vector_USART2_RX
|
||||||
|
IRQ __vector_USART2_UDRE
|
||||||
|
IRQ __vector_USART2_TX
|
||||||
|
IRQ __vector_USART3_RX
|
||||||
|
IRQ __vector_USART3_UDRE
|
||||||
|
IRQ __vector_USART3_TX
|
||||||
|
IRQ __vector_TRX24_PLL_LOCK
|
||||||
|
IRQ __vector_TRX24_PLL_UNLOCK
|
||||||
|
IRQ __vector_TRX24_RX_START
|
||||||
|
IRQ __vector_TRX24_RX_END
|
||||||
|
IRQ __vector_TRX24_CCA_ED_DONE
|
||||||
|
IRQ __vector_TRX24_XAH_AMI
|
||||||
|
IRQ __vector_TRX24_TX_END
|
||||||
|
IRQ __vector_TRX24_AWAKE
|
||||||
|
IRQ __vector_SCNT_CMP1
|
||||||
|
IRQ __vector_SCNT_CMP2
|
||||||
|
IRQ __vector_SCNT_CMP3
|
||||||
|
IRQ __vector_SCNT_OVFL
|
||||||
|
IRQ __vector_SCNT_BACKOFF
|
||||||
|
IRQ __vector_AES_READY
|
||||||
|
IRQ __vector_BAT_LOW
|
||||||
7
targets/device/avr/atmega128rfr2.ld
Normal file
7
targets/device/avr/atmega128rfr2.ld
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
/* Automatically generated file. DO NOT EDIT. */
|
||||||
|
/* Generated by gen-device-avr.go from ATmega128RFR2.atdf, see http://packs.download.atmel.com/ */
|
||||||
|
|
||||||
|
__flash_size = 0x20000;
|
||||||
|
__ram_start = 0x200;
|
||||||
|
__ram_size = 0x4000;
|
||||||
|
__num_isrs = 71;
|
||||||
172
targets/device/avr/atmega128rfr2.s
Normal file
172
targets/device/avr/atmega128rfr2.s
Normal file
@@ -0,0 +1,172 @@
|
|||||||
|
; Automatically generated file. DO NOT EDIT.
|
||||||
|
; Generated by gen-device-avr.go from ATmega128RFR2.atdf, see http://packs.download.atmel.com/
|
||||||
|
|
||||||
|
; This is the default handler for interrupts, if triggered but not defined.
|
||||||
|
; Sleep inside so that an accidentally triggered interrupt won't drain the
|
||||||
|
; battery of a battery-powered device.
|
||||||
|
.section .text.__vector_default
|
||||||
|
.global __vector_default
|
||||||
|
__vector_default:
|
||||||
|
sleep
|
||||||
|
rjmp __vector_default
|
||||||
|
|
||||||
|
; Avoid the need for repeated .weak and .set instructions.
|
||||||
|
.macro IRQ handler
|
||||||
|
.weak \handler
|
||||||
|
.set \handler, __vector_default
|
||||||
|
.endm
|
||||||
|
|
||||||
|
; The interrupt vector of this device. Must be placed at address 0 by the linker.
|
||||||
|
.section .vectors, "a", %progbits
|
||||||
|
.global __vectors
|
||||||
|
jmp __vector_RESET
|
||||||
|
jmp __vector_INT0
|
||||||
|
jmp __vector_INT1
|
||||||
|
jmp __vector_INT2
|
||||||
|
jmp __vector_INT3
|
||||||
|
jmp __vector_INT4
|
||||||
|
jmp __vector_INT5
|
||||||
|
jmp __vector_INT6
|
||||||
|
jmp __vector_INT7
|
||||||
|
jmp __vector_PCINT0
|
||||||
|
jmp __vector_PCINT1
|
||||||
|
jmp __vector_PCINT2
|
||||||
|
jmp __vector_WDT
|
||||||
|
jmp __vector_TIMER2_COMPA
|
||||||
|
jmp __vector_TIMER2_COMPB
|
||||||
|
jmp __vector_TIMER2_OVF
|
||||||
|
jmp __vector_TIMER1_CAPT
|
||||||
|
jmp __vector_TIMER1_COMPA
|
||||||
|
jmp __vector_TIMER1_COMPB
|
||||||
|
jmp __vector_TIMER1_COMPC
|
||||||
|
jmp __vector_TIMER1_OVF
|
||||||
|
jmp __vector_TIMER0_COMPA
|
||||||
|
jmp __vector_TIMER0_COMPB
|
||||||
|
jmp __vector_TIMER0_OVF
|
||||||
|
jmp __vector_SPI_STC
|
||||||
|
jmp __vector_USART0_RX
|
||||||
|
jmp __vector_USART0_UDRE
|
||||||
|
jmp __vector_USART0_TX
|
||||||
|
jmp __vector_ANALOG_COMP
|
||||||
|
jmp __vector_ADC
|
||||||
|
jmp __vector_EE_READY
|
||||||
|
jmp __vector_TIMER3_CAPT
|
||||||
|
jmp __vector_TIMER3_COMPA
|
||||||
|
jmp __vector_TIMER3_COMPB
|
||||||
|
jmp __vector_TIMER3_COMPC
|
||||||
|
jmp __vector_TIMER3_OVF
|
||||||
|
jmp __vector_USART1_RX
|
||||||
|
jmp __vector_USART1_UDRE
|
||||||
|
jmp __vector_USART1_TX
|
||||||
|
jmp __vector_TWI
|
||||||
|
jmp __vector_SPM_READY
|
||||||
|
jmp __vector_TIMER4_CAPT
|
||||||
|
jmp __vector_TIMER4_COMPA
|
||||||
|
jmp __vector_TIMER4_COMPB
|
||||||
|
jmp __vector_TIMER4_COMPC
|
||||||
|
jmp __vector_TIMER4_OVF
|
||||||
|
jmp __vector_TIMER5_CAPT
|
||||||
|
jmp __vector_TIMER5_COMPA
|
||||||
|
jmp __vector_TIMER5_COMPB
|
||||||
|
jmp __vector_TIMER5_COMPC
|
||||||
|
jmp __vector_TIMER5_OVF
|
||||||
|
jmp __vector_default
|
||||||
|
jmp __vector_default
|
||||||
|
jmp __vector_default
|
||||||
|
jmp __vector_default
|
||||||
|
jmp __vector_default
|
||||||
|
jmp __vector_default
|
||||||
|
jmp __vector_TRX24_PLL_LOCK
|
||||||
|
jmp __vector_TRX24_PLL_UNLOCK
|
||||||
|
jmp __vector_TRX24_RX_START
|
||||||
|
jmp __vector_TRX24_RX_END
|
||||||
|
jmp __vector_TRX24_CCA_ED_DONE
|
||||||
|
jmp __vector_TRX24_XAH_AMI
|
||||||
|
jmp __vector_TRX24_TX_END
|
||||||
|
jmp __vector_TRX24_AWAKE
|
||||||
|
jmp __vector_SCNT_CMP1
|
||||||
|
jmp __vector_SCNT_CMP2
|
||||||
|
jmp __vector_SCNT_CMP3
|
||||||
|
jmp __vector_SCNT_OVFL
|
||||||
|
jmp __vector_SCNT_BACKOFF
|
||||||
|
jmp __vector_AES_READY
|
||||||
|
jmp __vector_BAT_LOW
|
||||||
|
jmp __vector_TRX24_TX_START
|
||||||
|
jmp __vector_TRX24_AMI0
|
||||||
|
jmp __vector_TRX24_AMI1
|
||||||
|
jmp __vector_TRX24_AMI2
|
||||||
|
jmp __vector_TRX24_AMI3
|
||||||
|
|
||||||
|
; Define default implementations for interrupts, redirecting to
|
||||||
|
; __vector_default when not implemented.
|
||||||
|
IRQ __vector_RESET
|
||||||
|
IRQ __vector_INT0
|
||||||
|
IRQ __vector_INT1
|
||||||
|
IRQ __vector_INT2
|
||||||
|
IRQ __vector_INT3
|
||||||
|
IRQ __vector_INT4
|
||||||
|
IRQ __vector_INT5
|
||||||
|
IRQ __vector_INT6
|
||||||
|
IRQ __vector_INT7
|
||||||
|
IRQ __vector_PCINT0
|
||||||
|
IRQ __vector_PCINT1
|
||||||
|
IRQ __vector_PCINT2
|
||||||
|
IRQ __vector_WDT
|
||||||
|
IRQ __vector_TIMER2_COMPA
|
||||||
|
IRQ __vector_TIMER2_COMPB
|
||||||
|
IRQ __vector_TIMER2_OVF
|
||||||
|
IRQ __vector_TIMER1_CAPT
|
||||||
|
IRQ __vector_TIMER1_COMPA
|
||||||
|
IRQ __vector_TIMER1_COMPB
|
||||||
|
IRQ __vector_TIMER1_COMPC
|
||||||
|
IRQ __vector_TIMER1_OVF
|
||||||
|
IRQ __vector_TIMER0_COMPA
|
||||||
|
IRQ __vector_TIMER0_COMPB
|
||||||
|
IRQ __vector_TIMER0_OVF
|
||||||
|
IRQ __vector_SPI_STC
|
||||||
|
IRQ __vector_USART0_RX
|
||||||
|
IRQ __vector_USART0_UDRE
|
||||||
|
IRQ __vector_USART0_TX
|
||||||
|
IRQ __vector_ANALOG_COMP
|
||||||
|
IRQ __vector_ADC
|
||||||
|
IRQ __vector_EE_READY
|
||||||
|
IRQ __vector_TIMER3_CAPT
|
||||||
|
IRQ __vector_TIMER3_COMPA
|
||||||
|
IRQ __vector_TIMER3_COMPB
|
||||||
|
IRQ __vector_TIMER3_COMPC
|
||||||
|
IRQ __vector_TIMER3_OVF
|
||||||
|
IRQ __vector_USART1_RX
|
||||||
|
IRQ __vector_USART1_UDRE
|
||||||
|
IRQ __vector_USART1_TX
|
||||||
|
IRQ __vector_TWI
|
||||||
|
IRQ __vector_SPM_READY
|
||||||
|
IRQ __vector_TIMER4_CAPT
|
||||||
|
IRQ __vector_TIMER4_COMPA
|
||||||
|
IRQ __vector_TIMER4_COMPB
|
||||||
|
IRQ __vector_TIMER4_COMPC
|
||||||
|
IRQ __vector_TIMER4_OVF
|
||||||
|
IRQ __vector_TIMER5_CAPT
|
||||||
|
IRQ __vector_TIMER5_COMPA
|
||||||
|
IRQ __vector_TIMER5_COMPB
|
||||||
|
IRQ __vector_TIMER5_COMPC
|
||||||
|
IRQ __vector_TIMER5_OVF
|
||||||
|
IRQ __vector_TRX24_PLL_LOCK
|
||||||
|
IRQ __vector_TRX24_PLL_UNLOCK
|
||||||
|
IRQ __vector_TRX24_RX_START
|
||||||
|
IRQ __vector_TRX24_RX_END
|
||||||
|
IRQ __vector_TRX24_CCA_ED_DONE
|
||||||
|
IRQ __vector_TRX24_XAH_AMI
|
||||||
|
IRQ __vector_TRX24_TX_END
|
||||||
|
IRQ __vector_TRX24_AWAKE
|
||||||
|
IRQ __vector_SCNT_CMP1
|
||||||
|
IRQ __vector_SCNT_CMP2
|
||||||
|
IRQ __vector_SCNT_CMP3
|
||||||
|
IRQ __vector_SCNT_OVFL
|
||||||
|
IRQ __vector_SCNT_BACKOFF
|
||||||
|
IRQ __vector_AES_READY
|
||||||
|
IRQ __vector_BAT_LOW
|
||||||
|
IRQ __vector_TRX24_TX_START
|
||||||
|
IRQ __vector_TRX24_AMI0
|
||||||
|
IRQ __vector_TRX24_AMI1
|
||||||
|
IRQ __vector_TRX24_AMI2
|
||||||
|
IRQ __vector_TRX24_AMI3
|
||||||
7
targets/device/avr/atmega16.ld
Normal file
7
targets/device/avr/atmega16.ld
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
/* Automatically generated file. DO NOT EDIT. */
|
||||||
|
/* Generated by gen-device-avr.go from ATmega16.atdf, see http://packs.download.atmel.com/ */
|
||||||
|
|
||||||
|
__flash_size = 0x4000;
|
||||||
|
__ram_start = 0x60;
|
||||||
|
__ram_size = 0x400;
|
||||||
|
__num_isrs = 21;
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user