feat: implement target configuration system for issue #1176

Add comprehensive target configuration parsing and inheritance system:

- Create internal/targets package with config structures
- Support JSON configuration loading with inheritance resolution
- Implement multi-level inheritance (e.g., rp2040 → cortex-m0plus → cortex-m)
- Add 206 target configurations from TinyGo for embedded platforms
- Support core fields: name, llvm-target, cpu, features, build-tags, goos, goarch, cflags, ldflags
- Provide high-level resolver interface for target lookup
- Include comprehensive unit tests with 100% target parsing coverage

This foundation enables future -target parameter support for cross-compilation
to diverse embedded platforms beyond current GOOS/GOARCH limitations.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Li Jie
2025-07-26 10:49:35 +10:00
parent 5eb833a984
commit b80a54eb0f
277 changed files with 8202 additions and 0 deletions

View File

@@ -0,0 +1,43 @@
package targets
// Config represents a complete target configuration after inheritance resolution
type Config struct {
// Target identification
Name string `json:"-"`
// LLVM configuration
LLVMTarget string `json:"llvm-target"`
CPU string `json:"cpu"`
Features string `json:"features"`
// Build configuration
BuildTags []string `json:"build-tags"`
GOOS string `json:"goos"`
GOARCH string `json:"goarch"`
// Compiler and linker configuration
Linker string `json:"linker"`
CFlags []string `json:"cflags"`
LDFlags []string `json:"ldflags"`
}
// RawConfig represents the raw JSON configuration before inheritance resolution
type RawConfig struct {
Inherits []string `json:"inherits"`
Config
}
// IsEmpty returns true if the config appears to be uninitialized
func (c *Config) IsEmpty() bool {
return c.Name == "" && c.LLVMTarget == "" && c.GOOS == "" && c.GOARCH == ""
}
// HasInheritance returns true if this config inherits from other configs
func (rc *RawConfig) HasInheritance() bool {
return len(rc.Inherits) > 0
}
// GetInherits returns the list of configs this config inherits from
func (rc *RawConfig) GetInherits() []string {
return rc.Inherits
}

View File

@@ -0,0 +1,73 @@
package targets_test
import (
"fmt"
"log"
"sort"
"github.com/goplus/llgo/internal/targets"
)
func ExampleResolver_Resolve() {
resolver := targets.NewDefaultResolver()
// Resolve a specific target
config, err := resolver.Resolve("rp2040")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Target: %s\n", config.Name)
fmt.Printf("LLVM Target: %s\n", config.LLVMTarget)
fmt.Printf("CPU: %s\n", config.CPU)
fmt.Printf("GOOS: %s\n", config.GOOS)
fmt.Printf("GOARCH: %s\n", config.GOARCH)
if len(config.BuildTags) > 0 {
fmt.Printf("Build Tags: %v\n", config.BuildTags)
}
if len(config.CFlags) > 0 {
fmt.Printf("C Flags: %v\n", config.CFlags)
}
if len(config.LDFlags) > 0 {
fmt.Printf("LD Flags: %v\n", config.LDFlags)
}
}
func ExampleResolver_ListAvailableTargets() {
resolver := targets.NewDefaultResolver()
targets, err := resolver.ListAvailableTargets()
if err != nil {
log.Fatal(err)
}
// Show first 10 targets
sort.Strings(targets)
fmt.Printf("Available targets (first 10 of %d):\n", len(targets))
for i, target := range targets[:10] {
fmt.Printf("%d. %s\n", i+1, target)
}
}
func ExampleResolver_ResolveAll() {
resolver := targets.NewDefaultResolver()
configs, err := resolver.ResolveAll()
if err != nil {
log.Fatal(err)
}
// Count targets by GOOS
goosCounts := make(map[string]int)
for _, config := range configs {
if config.GOOS != "" {
goosCounts[config.GOOS]++
}
}
fmt.Printf("Loaded %d target configurations\n", len(configs))
fmt.Printf("GOOS distribution:\n")
for goos, count := range goosCounts {
fmt.Printf(" %s: %d targets\n", goos, count)
}
}

176
internal/targets/loader.go Normal file
View File

@@ -0,0 +1,176 @@
package targets
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"strings"
)
// Loader handles loading and parsing target configurations
type Loader struct {
targetsDir string
cache map[string]*RawConfig
}
// NewLoader creates a new target configuration loader
func NewLoader(targetsDir string) *Loader {
return &Loader{
targetsDir: targetsDir,
cache: make(map[string]*RawConfig),
}
}
// LoadRaw loads a raw configuration without resolving inheritance
func (l *Loader) LoadRaw(name string) (*RawConfig, error) {
// Check cache first
if config, exists := l.cache[name]; exists {
return config, nil
}
// Construct file path
configPath := filepath.Join(l.targetsDir, name+".json")
// Read file
data, err := os.ReadFile(configPath)
if err != nil {
return nil, fmt.Errorf("failed to read target config %s: %w", name, err)
}
// Parse JSON
var config RawConfig
if err := json.Unmarshal(data, &config); err != nil {
return nil, fmt.Errorf("failed to parse target config %s: %w", name, err)
}
// Set the name
config.Name = name
// Cache the result
l.cache[name] = &config
return &config, nil
}
// Load loads a target configuration with inheritance resolved
func (l *Loader) Load(name string) (*Config, error) {
raw, err := l.LoadRaw(name)
if err != nil {
return nil, err
}
return l.resolveInheritance(raw)
}
// LoadAll loads all target configurations in the targets directory
func (l *Loader) LoadAll() (map[string]*Config, error) {
entries, err := os.ReadDir(l.targetsDir)
if err != nil {
return nil, fmt.Errorf("failed to read targets directory: %w", err)
}
configs := make(map[string]*Config)
for _, entry := range entries {
if entry.IsDir() || !strings.HasSuffix(entry.Name(), ".json") {
continue
}
name := strings.TrimSuffix(entry.Name(), ".json")
config, err := l.Load(name)
if err != nil {
return nil, fmt.Errorf("failed to load target %s: %w", name, err)
}
configs[name] = config
}
return configs, nil
}
// resolveInheritance resolves inheritance chain for a configuration
func (l *Loader) resolveInheritance(raw *RawConfig) (*Config, error) {
if !raw.HasInheritance() {
// No inheritance, return as-is
return &raw.Config, nil
}
// Start with base config
result := &Config{Name: raw.Name}
// Apply inheritance in order
for _, parentName := range raw.GetInherits() {
parent, err := l.Load(parentName)
if err != nil {
return nil, fmt.Errorf("failed to load parent config %s: %w", parentName, err)
}
// Merge parent into result
l.mergeConfig(result, parent)
}
// Finally, apply current config on top
l.mergeConfig(result, &raw.Config)
return result, nil
}
// mergeConfig merges source config into destination config
// Non-empty values in source override those in destination
func (l *Loader) mergeConfig(dst, src *Config) {
if src.LLVMTarget != "" {
dst.LLVMTarget = src.LLVMTarget
}
if src.CPU != "" {
dst.CPU = src.CPU
}
if src.Features != "" {
dst.Features = src.Features
}
if src.GOOS != "" {
dst.GOOS = src.GOOS
}
if src.GOARCH != "" {
dst.GOARCH = src.GOARCH
}
if src.Linker != "" {
dst.Linker = src.Linker
}
// Merge slices (append, don't replace)
if len(src.BuildTags) > 0 {
dst.BuildTags = append(dst.BuildTags, src.BuildTags...)
}
if len(src.CFlags) > 0 {
dst.CFlags = append(dst.CFlags, src.CFlags...)
}
if len(src.LDFlags) > 0 {
dst.LDFlags = append(dst.LDFlags, src.LDFlags...)
}
}
// GetTargetsDir returns the targets directory path
func (l *Loader) GetTargetsDir() string {
return l.targetsDir
}
// ListTargets returns a list of all available target names
func (l *Loader) ListTargets() ([]string, error) {
entries, err := os.ReadDir(l.targetsDir)
if err != nil {
return nil, fmt.Errorf("failed to read targets directory: %w", err)
}
var targets []string
for _, entry := range entries {
if entry.IsDir() || !strings.HasSuffix(entry.Name(), ".json") {
continue
}
name := strings.TrimSuffix(entry.Name(), ".json")
targets = append(targets, name)
}
return targets, nil
}

View File

@@ -0,0 +1,77 @@
package targets
import (
"fmt"
"path/filepath"
"runtime"
)
// Resolver provides high-level interface for target configuration resolution
type Resolver struct {
loader *Loader
}
// NewResolver creates a new target resolver
func NewResolver(targetsDir string) *Resolver {
return &Resolver{
loader: NewLoader(targetsDir),
}
}
// NewDefaultResolver creates a resolver with default targets directory
func NewDefaultResolver() *Resolver {
// Assume targets directory is relative to this package
_, filename, _, _ := runtime.Caller(0)
projectRoot := filepath.Dir(filepath.Dir(filepath.Dir(filename)))
targetsDir := filepath.Join(projectRoot, "targets")
return NewResolver(targetsDir)
}
// Resolve resolves a target configuration by name
func (r *Resolver) Resolve(targetName string) (*Config, error) {
config, err := r.loader.Load(targetName)
if err != nil {
return nil, fmt.Errorf("failed to resolve target %s: %w", targetName, err)
}
// Validate required fields
if err := r.validateConfig(config); err != nil {
return nil, fmt.Errorf("invalid target config %s: %w", targetName, err)
}
return config, nil
}
// ResolveAll resolves all available target configurations
func (r *Resolver) ResolveAll() (map[string]*Config, error) {
return r.loader.LoadAll()
}
// ListAvailableTargets returns a list of all available target names
func (r *Resolver) ListAvailableTargets() ([]string, error) {
return r.loader.ListTargets()
}
// validateConfig validates that a resolved config has required fields
func (r *Resolver) validateConfig(config *Config) error {
if config.Name == "" {
return fmt.Errorf("target name is required")
}
// For now, we don't require any specific fields since different targets
// may have different requirements. This can be extended in the future.
return nil
}
// GetTargetsDirectory returns the path to the targets directory
func (r *Resolver) GetTargetsDirectory() string {
return r.loader.GetTargetsDir()
}
// HasTarget checks if a target with the given name exists
func (r *Resolver) HasTarget(name string) bool {
_, err := r.loader.LoadRaw(name)
return err == nil
}

View File

@@ -0,0 +1,322 @@
//go:build !llgo
package targets
import (
"os"
"path/filepath"
"testing"
)
func TestConfigBasics(t *testing.T) {
config := &Config{
Name: "test",
LLVMTarget: "arm-none-eabi",
GOOS: "linux",
GOARCH: "arm",
}
if config.IsEmpty() {
t.Error("Config should not be empty when fields are set")
}
empty := &Config{}
if !empty.IsEmpty() {
t.Error("Empty config should report as empty")
}
}
func TestRawConfigInheritance(t *testing.T) {
raw := &RawConfig{
Inherits: []string{"parent1", "parent2"},
Config: Config{
Name: "child",
},
}
if !raw.HasInheritance() {
t.Error("RawConfig should report having inheritance")
}
inherits := raw.GetInherits()
if len(inherits) != 2 || inherits[0] != "parent1" || inherits[1] != "parent2" {
t.Errorf("Expected inheritance list [parent1, parent2], got %v", inherits)
}
noInherit := &RawConfig{}
if noInherit.HasInheritance() {
t.Error("RawConfig with no inherits should not report having inheritance")
}
}
func TestLoaderLoadRaw(t *testing.T) {
// Create a temporary directory for test configs
tempDir := t.TempDir()
// Create a test config file
testConfig := `{
"llvm-target": "thumbv6m-unknown-unknown-eabi",
"cpu": "cortex-m0plus",
"goos": "linux",
"goarch": "arm",
"build-tags": ["test", "embedded"],
"cflags": ["-Os", "-g"],
"ldflags": ["--gc-sections"]
}`
configPath := filepath.Join(tempDir, "test-target.json")
if err := os.WriteFile(configPath, []byte(testConfig), 0644); err != nil {
t.Fatalf("Failed to write test config: %v", err)
}
loader := NewLoader(tempDir)
config, err := loader.LoadRaw("test-target")
if err != nil {
t.Fatalf("Failed to load raw config: %v", err)
}
if config.Name != "test-target" {
t.Errorf("Expected name 'test-target', got '%s'", config.Name)
}
if config.LLVMTarget != "thumbv6m-unknown-unknown-eabi" {
t.Errorf("Expected llvm-target 'thumbv6m-unknown-unknown-eabi', got '%s'", config.LLVMTarget)
}
if config.CPU != "cortex-m0plus" {
t.Errorf("Expected cpu 'cortex-m0plus', got '%s'", config.CPU)
}
if len(config.BuildTags) != 2 || config.BuildTags[0] != "test" || config.BuildTags[1] != "embedded" {
t.Errorf("Expected build-tags [test, embedded], got %v", config.BuildTags)
}
}
func TestLoaderInheritance(t *testing.T) {
tempDir := t.TempDir()
// Create parent config
parentConfig := `{
"llvm-target": "thumbv6m-unknown-unknown-eabi",
"cpu": "cortex-m0plus",
"goos": "linux",
"goarch": "arm",
"cflags": ["-Os"],
"ldflags": ["--gc-sections"]
}`
// Create child config that inherits from parent
childConfig := `{
"inherits": ["parent"],
"cpu": "cortex-m4",
"build-tags": ["child"],
"cflags": ["-O2"],
"ldflags": ["-g"]
}`
parentPath := filepath.Join(tempDir, "parent.json")
childPath := filepath.Join(tempDir, "child.json")
if err := os.WriteFile(parentPath, []byte(parentConfig), 0644); err != nil {
t.Fatalf("Failed to write parent config: %v", err)
}
if err := os.WriteFile(childPath, []byte(childConfig), 0644); err != nil {
t.Fatalf("Failed to write child config: %v", err)
}
loader := NewLoader(tempDir)
config, err := loader.Load("child")
if err != nil {
t.Fatalf("Failed to load child config: %v", err)
}
// Check inherited values
if config.LLVMTarget != "thumbv6m-unknown-unknown-eabi" {
t.Errorf("Expected inherited llvm-target 'thumbv6m-unknown-unknown-eabi', got '%s'", config.LLVMTarget)
}
if config.GOOS != "linux" {
t.Errorf("Expected inherited goos 'linux', got '%s'", config.GOOS)
}
if config.GOARCH != "arm" {
t.Errorf("Expected inherited goarch 'arm', got '%s'", config.GOARCH)
}
// Check overridden values
if config.CPU != "cortex-m4" {
t.Errorf("Expected overridden cpu 'cortex-m4', got '%s'", config.CPU)
}
// Check merged arrays
expectedCFlags := []string{"-Os", "-O2"}
if len(config.CFlags) != 2 || config.CFlags[0] != "-Os" || config.CFlags[1] != "-O2" {
t.Errorf("Expected merged cflags %v, got %v", expectedCFlags, config.CFlags)
}
expectedLDFlags := []string{"--gc-sections", "-g"}
if len(config.LDFlags) != 2 || config.LDFlags[0] != "--gc-sections" || config.LDFlags[1] != "-g" {
t.Errorf("Expected merged ldflags %v, got %v", expectedLDFlags, config.LDFlags)
}
// Check child-specific values
if len(config.BuildTags) != 1 || config.BuildTags[0] != "child" {
t.Errorf("Expected build-tags [child], got %v", config.BuildTags)
}
}
func TestLoaderListTargets(t *testing.T) {
tempDir := t.TempDir()
// Create some test config files
configs := []string{"target1.json", "target2.json", "not-a-target.txt"}
for _, config := range configs {
configPath := filepath.Join(tempDir, config)
if err := os.WriteFile(configPath, []byte("{}"), 0644); err != nil {
t.Fatalf("Failed to write config %s: %v", config, err)
}
}
loader := NewLoader(tempDir)
targets, err := loader.ListTargets()
if err != nil {
t.Fatalf("Failed to list targets: %v", err)
}
expectedTargets := []string{"target1", "target2"}
if len(targets) != len(expectedTargets) {
t.Errorf("Expected %d targets, got %d", len(expectedTargets), len(targets))
}
for _, expected := range expectedTargets {
found := false
for _, target := range targets {
if target == expected {
found = true
break
}
}
if !found {
t.Errorf("Expected target %s not found in list %v", expected, targets)
}
}
}
func TestResolver(t *testing.T) {
tempDir := t.TempDir()
// Create a test config
testConfig := `{
"llvm-target": "wasm32-unknown-wasi",
"cpu": "generic",
"goos": "wasip1",
"goarch": "wasm"
}`
configPath := filepath.Join(tempDir, "wasi.json")
if err := os.WriteFile(configPath, []byte(testConfig), 0644); err != nil {
t.Fatalf("Failed to write test config: %v", err)
}
resolver := NewResolver(tempDir)
// Test resolve
config, err := resolver.Resolve("wasi")
if err != nil {
t.Fatalf("Failed to resolve target: %v", err)
}
if config.Name != "wasi" {
t.Errorf("Expected name 'wasi', got '%s'", config.Name)
}
// Test has target
if !resolver.HasTarget("wasi") {
t.Error("Resolver should report having 'wasi' target")
}
if resolver.HasTarget("nonexistent") {
t.Error("Resolver should not report having 'nonexistent' target")
}
// Test list available targets
targets, err := resolver.ListAvailableTargets()
if err != nil {
t.Fatalf("Failed to list available targets: %v", err)
}
if len(targets) != 1 || targets[0] != "wasi" {
t.Errorf("Expected targets [wasi], got %v", targets)
}
}
func TestResolverWithRealTargets(t *testing.T) {
// Test with actual targets directory if it exists
resolver := NewDefaultResolver()
targetsDir := resolver.GetTargetsDirectory()
// Check if targets directory exists
if _, err := os.Stat(targetsDir); os.IsNotExist(err) {
t.Skipf("Targets directory %s does not exist, skipping real targets test", targetsDir)
}
// Test listing real targets
targets, err := resolver.ListAvailableTargets()
if err != nil {
t.Fatalf("Failed to list real targets: %v", err)
}
t.Logf("Found %d targets in %s", len(targets), targetsDir)
// Test resolving some known targets
knownTargets := []string{"wasi", "cortex-m", "rp2040"}
for _, targetName := range knownTargets {
if resolver.HasTarget(targetName) {
config, err := resolver.Resolve(targetName)
if err != nil {
t.Errorf("Failed to resolve known target %s: %v", targetName, err)
continue
}
t.Logf("Resolved target %s: LLVM=%s, CPU=%s, GOOS=%s, GOARCH=%s",
targetName, config.LLVMTarget, config.CPU, config.GOOS, config.GOARCH)
}
}
}
func TestResolveAllRealTargets(t *testing.T) {
resolver := NewDefaultResolver()
targetsDir := resolver.GetTargetsDirectory()
// Check if targets directory exists
if _, err := os.Stat(targetsDir); os.IsNotExist(err) {
t.Skipf("Targets directory %s does not exist, skipping resolve all test", targetsDir)
}
// Test resolving all targets
configs, err := resolver.ResolveAll()
if err != nil {
t.Fatalf("Failed to resolve all targets: %v", err)
}
t.Logf("Successfully resolved %d targets", len(configs))
// Check that all configs have names
for name, config := range configs {
if config.Name != name {
t.Errorf("Config name mismatch: key=%s, config.Name=%s", name, config.Name)
}
if config.IsEmpty() {
t.Errorf("Config %s appears to be empty", name)
}
}
// Log some statistics
goosCounts := make(map[string]int)
goarchCounts := make(map[string]int)
for _, config := range configs {
if config.GOOS != "" {
goosCounts[config.GOOS]++
}
if config.GOARCH != "" {
goarchCounts[config.GOARCH]++
}
}
t.Logf("GOOS distribution: %v", goosCounts)
t.Logf("GOARCH distribution: %v", goarchCounts)
}

View File

@@ -0,0 +1,4 @@
{
"inherits": ["esp32"],
"build-tags": ["adafruit_esp32_feather_v2"]
}

14
targets/ae-rp2040.json Normal file
View File

@@ -0,0 +1,14 @@
{
"inherits": [
"rp2040"
],
"build-tags": ["ae_rp2040"],
"serial-port": ["2e8a:000A"],
"ldflags": [
"--defsym=__flash_size=2048K"
],
"extra-files": [
"targets/pico-boot-stage2.S"
]
}

View File

@@ -0,0 +1,10 @@
{
"inherits": ["atmega32u4"],
"build-tags": ["arduino_leonardo"],
"ldflags": [
"--defsym=_bootloader_size=512",
"--defsym=_stack_size=512"
],
"flash-command": "avrdude -c avr109 -p atmega32u4 -b 57600 -P {port} -U flash:w:{hex}:i",
"emulator": "simavr -m atmega32u4 -f 16000000 {}"
}

View File

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

View File

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

View File

@@ -0,0 +1,7 @@
{
"inherits": ["atsamd21g18a"],
"build-tags": ["arduino_mkr1000"],
"serial": "usb",
"flash-command": "bossac -i -e -w -v -R -U --port={port} --offset=0x2000 {bin}",
"flash-1200-bps-reset": "true"
}

View File

@@ -0,0 +1,8 @@
{
"inherits": ["atsamd21g18a"],
"build-tags": ["arduino_mkrwifi1010", "ninafw"],
"serial": "usb",
"serial-port": ["2341:8054", "2341:0054"],
"flash-command": "bossac -i -e -w -v -R -U --port={port} --offset=0x2000 {bin}",
"flash-1200-bps-reset": "true"
}

View File

@@ -0,0 +1,4 @@
{
"inherits": ["arduino-nano"],
"flash-command": "avrdude -c arduino -p atmega328p -b 115200 -P {port} -U flash:w:{hex}:i"
}

10
targets/arduino-nano.json Normal file
View File

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

View File

@@ -0,0 +1,7 @@
{
"inherits": ["atsamd21g18a"],
"build-tags": ["arduino_nano33", "ninafw", "ninafw_machine_init"],
"flash-command": "bossac -i -e -w -v -R -U --port={port} --offset=0x2000 {bin}",
"serial-port": ["2341:8057", "2341:0057"],
"flash-1200-bps-reset": "true"
}

View File

@@ -0,0 +1,7 @@
{
"inherits": ["atsamd21g18a"],
"build-tags": ["arduino_zero"],
"serial": "usb",
"flash-command": "bossac -i -e -w -v -R -U --port={port} --offset=0x2000 {bin}",
"flash-1200-bps-reset": "true"
}

11
targets/arduino.json Normal file
View File

@@ -0,0 +1,11 @@
{
"inherits": ["atmega328p"],
"build-tags": ["arduino"],
"ldflags": [
"--defsym=_bootloader_size=512",
"--defsym=_stack_size=512"
],
"flash-command": "avrdude -c arduino -p atmega328p -P {port} -U flash:w:{hex}:i",
"serial-port": ["2341:0043", "2341:0001", "2a03:0043", "2341:0243"],
"emulator": "simavr -m atmega328p -f 16000000 {}"
}

86
targets/arm.ld Normal file
View File

@@ -0,0 +1,86 @@
/* Unused, but here to silence a linker warning. */
ENTRY(Reset_Handler)
/* define output sections */
SECTIONS
{
/* Program code and read-only data goes to FLASH_TEXT. */
.text :
{
KEEP(*(.isr_vector))
KEEP(*(.after_isr_vector)) /* for the RP2350 */
*(.text)
*(.text.*)
*(.rodata)
*(.rodata.*)
. = ALIGN(4);
} >FLASH_TEXT
.tinygo_stacksizes :
{
*(.tinygo_stacksizes)
} > FLASH_TEXT
/* Put the stack at the bottom of RAM, so that the application will
* crash on stack overflow instead of silently corrupting memory.
* See: http://blog.japaric.io/stack-overflow-protection/ */
.stack (NOLOAD) :
{
. = ALIGN(4);
. += _stack_size;
_stack_top = .;
} >RAM
/* Stack for second core (core 1), if there is one. */
.stack1 (NOLOAD) :
{
. = ALIGN(4);
. += DEFINED(__num_stacks) && __num_stacks >= 2 ? _stack_size : 0;
_stack1_top = .;
} >RAM
/* Start address (in flash) of .data, used by startup code. */
_sidata = LOADADDR(.data);
/* Globals with initial value */
.data :
{
. = ALIGN(4);
_sdata = .; /* used by startup code */
*(.data)
*(.data.*)
. = ALIGN(4);
*(.ramfuncs*) /* Functions that must execute from RAM */
. = ALIGN(4);
_edata = .; /* used by startup code */
} >RAM AT>FLASH_TEXT
/* Zero-initialized globals */
.bss :
{
. = ALIGN(4);
_sbss = .; /* used by startup code */
*(.bss)
*(.bss.*)
*(COMMON)
. = ALIGN(4);
_ebss = .; /* used by startup code */
} >RAM
/DISCARD/ :
{
*(.ARM.exidx) /* causes 'no memory region specified' error in lld */
*(.ARM.exidx.*) /* causes spurious 'undefined reference' errors */
}
}
/* For the memory allocator. */
_heap_start = _ebss;
_heap_end = ORIGIN(RAM) + LENGTH(RAM);
_globals_start = _sdata;
_globals_end = _ebss;
/* For the flash API */
__flash_data_start = LOADADDR(.data) + SIZEOF(.data);
__flash_data_end = ORIGIN(FLASH_TEXT) + LENGTH(FLASH_TEXT);

14
targets/atmega1280.json Normal file
View File

@@ -0,0 +1,14 @@
{
"inherits": ["avr"],
"cpu": "atmega1280",
"build-tags": ["atmega1280", "atmega"],
"serial": "uart",
"ldflags": [
"--defsym=_stack_size=512"
],
"linkerscript": "src/device/avr/atmega1280.ld",
"extra-files": [
"targets/avr.S",
"src/device/avr/atmega1280.s"
]
}

16
targets/atmega1284p.json Normal file
View File

@@ -0,0 +1,16 @@
{
"inherits": ["avr"],
"cpu": "atmega1284p",
"build-tags": ["atmega1284p", "atmega"],
"serial": "uart",
"ldflags": [
"--defsym=_bootloader_size=0",
"--defsym=_stack_size=512"
],
"linkerscript": "src/device/avr/atmega1284p.ld",
"extra-files": [
"targets/avr.S",
"src/device/avr/atmega1284p.s"
],
"emulator": "simavr -m atmega1284p -f 20000000 {}"
}

14
targets/atmega2560.json Normal file
View File

@@ -0,0 +1,14 @@
{
"inherits": ["avr"],
"cpu": "atmega2560",
"build-tags": ["atmega2560", "atmega"],
"serial": "uart",
"ldflags": [
"--defsym=_stack_size=512"
],
"linkerscript": "src/device/avr/atmega2560.ld",
"extra-files": [
"targets/avr.S",
"src/device/avr/atmega2560.s"
]
}

11
targets/atmega328p.json Normal file
View File

@@ -0,0 +1,11 @@
{
"inherits": ["avr"],
"cpu": "atmega328p",
"build-tags": ["atmega328p", "atmega", "avr5"],
"serial": "uart",
"linkerscript": "src/device/avr/atmega328p.ld",
"extra-files": [
"targets/avr.S",
"src/device/avr/atmega328p.s"
]
}

15
targets/atmega328pb.json Normal file
View File

@@ -0,0 +1,15 @@
{
"inherits": ["avr"],
"cpu": "atmega328pb",
"build-tags": ["atmega328pb", "atmega", "avr5"],
"ldflags": [
"--defsym=_bootloader_size=512",
"--defsym=_stack_size=512"
],
"serial": "uart",
"linkerscript": "src/device/avr/atmega328pb.ld",
"extra-files": [
"targets/avr.S",
"src/device/avr/atmega328pb.s"
]
}

11
targets/atmega32u4.json Normal file
View File

@@ -0,0 +1,11 @@
{
"inherits": ["avr"],
"cpu": "atmega32u4",
"build-tags": ["atmega32u4", "avr5"],
"serial": "none",
"linkerscript": "src/device/avr/atmega32u4.ld",
"extra-files": [
"targets/avr.S",
"src/device/avr/atmega32u4.s"
]
}

10
targets/atsamd21.ld Normal file
View File

@@ -0,0 +1,10 @@
MEMORY
{
FLASH_TEXT (rw) : ORIGIN = 0x00000000+0x2000, LENGTH = 0x00040000-0x2000 /* First 8KB used by bootloader */
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x00008000
}
_stack_size = 2K;
INCLUDE "targets/arm.ld"

11
targets/atsamd21e18a.json Normal file
View File

@@ -0,0 +1,11 @@
{
"inherits": ["cortex-m0plus"],
"build-tags": ["atsamd21e18a", "atsamd21e18", "atsamd21", "sam"],
"serial": "usb",
"linkerscript": "targets/atsamd21.ld",
"extra-files": [
"src/device/sam/atsamd21e18a.s"
],
"openocd-transport": "swd",
"openocd-target": "at91samdXX"
}

11
targets/atsamd21g18a.json Normal file
View File

@@ -0,0 +1,11 @@
{
"inherits": ["cortex-m0plus"],
"build-tags": ["atsamd21g18a", "atsamd21g18", "atsamd21", "sam"],
"serial": "usb",
"linkerscript": "targets/atsamd21.ld",
"extra-files": [
"src/device/sam/atsamd21g18a.s"
],
"openocd-transport": "swd",
"openocd-target": "at91samdXX"
}

10
targets/atsamd51.ld Normal file
View File

@@ -0,0 +1,10 @@
MEMORY
{
FLASH_TEXT (rw) : ORIGIN = 0x00000000+0x4000, LENGTH = 0x00080000-0x4000 /* First 16KB used by bootloader */
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x00030000
}
_stack_size = 4K;
INCLUDE "targets/arm.ld"

10
targets/atsamd51g19a.json Normal file
View File

@@ -0,0 +1,10 @@
{
"inherits": ["cortex-m4"],
"build-tags": ["atsamd51g19a", "atsamd51g19", "atsamd51", "sam"],
"linkerscript": "targets/atsamd51.ld",
"extra-files": [
"src/device/sam/atsamd51g19a.s"
],
"openocd-transport": "swd",
"openocd-target": "atsame5x"
}

10
targets/atsamd51j19a.json Normal file
View File

@@ -0,0 +1,10 @@
{
"inherits": ["cortex-m4"],
"build-tags": ["atsamd51j19a", "atsamd51j19", "atsamd51", "sam"],
"linkerscript": "targets/atsamd51.ld",
"extra-files": [
"src/device/sam/atsamd51j19a.s"
],
"openocd-transport": "swd",
"openocd-target": "atsame5x"
}

10
targets/atsamd51j20a.json Normal file
View File

@@ -0,0 +1,10 @@
{
"inherits": ["cortex-m4"],
"build-tags": ["sam", "atsamd51", "atsamd51j20", "atsamd51j20a"],
"linkerscript": "targets/atsamd51j20a.ld",
"extra-files": [
"src/device/sam/atsamd51j20a.s"
],
"openocd-transport": "swd",
"openocd-target": "atsame5x"
}

10
targets/atsamd51j20a.ld Normal file
View File

@@ -0,0 +1,10 @@
MEMORY
{
FLASH_TEXT (rw) : ORIGIN = 0x00000000+0x4000, LENGTH = 0x00100000-0x4000 /* First 16KB used by bootloader */
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x00040000
}
_stack_size = 4K;
INCLUDE "targets/arm.ld"

10
targets/atsamd51p19a.json Normal file
View File

@@ -0,0 +1,10 @@
{
"inherits": ["cortex-m4"],
"build-tags": ["atsamd51p19a", "atsamd51p19", "atsamd51", "sam"],
"linkerscript": "targets/atsamd51.ld",
"extra-files": [
"src/device/sam/atsamd51p19a.s"
],
"openocd-transport": "swd",
"openocd-target": "atsame5x"
}

10
targets/atsamd51p20a.json Normal file
View File

@@ -0,0 +1,10 @@
{
"inherits": ["cortex-m4"],
"build-tags": ["sam", "atsamd51", "atsamd51p20", "atsamd51p20a"],
"linkerscript": "targets/atsamd51p20a.ld",
"extra-files": [
"src/device/sam/atsamd51p20a.s"
],
"openocd-transport": "swd",
"openocd-target": "atsame5x"
}

10
targets/atsamd51p20a.ld Normal file
View File

@@ -0,0 +1,10 @@
MEMORY
{
FLASH_TEXT (rw) : ORIGIN = 0x00000000+0x4000, LENGTH = 0x00100000-0x4000 /* First 16KB used by bootloader */
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x00040000
}
_stack_size = 4K;
INCLUDE "targets/arm.ld"

10
targets/atsame51j19a.json Normal file
View File

@@ -0,0 +1,10 @@
{
"inherits": ["cortex-m4"],
"build-tags": ["atsame51j19a", "atsame51j19", "atsame51", "atsame5x", "sam"],
"linkerscript": "targets/atsame5xx19.ld",
"extra-files": [
"src/device/sam/atsame51j19a.s"
],
"openocd-transport": "swd",
"openocd-target": "atsame5x"
}

View File

@@ -0,0 +1,7 @@
{
"inherits": ["atsame54p20a"],
"build-tags": ["atsame54_xpro"],
"serial": "usb",
"flash-method": "openocd",
"openocd-interface": "cmsis-dap"
}

10
targets/atsame54p20a.json Normal file
View File

@@ -0,0 +1,10 @@
{
"inherits": ["cortex-m4"],
"build-tags": ["sam", "atsame5x", "atsame54", "atsame54p20", "atsame54p20a"],
"linkerscript": "targets/atsame5xx20-no-bootloader.ld",
"extra-files": [
"src/device/sam/atsame54p20a.s"
],
"openocd-transport": "swd",
"openocd-target": "atsame5x"
}

10
targets/atsame5xx19.ld Normal file
View File

@@ -0,0 +1,10 @@
MEMORY
{
FLASH_TEXT (rw) : ORIGIN = 0x00000000+0x4000, LENGTH = 0x00080000-0x4000 /* First 16KB used by bootloader */
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x00030000
}
_stack_size = 4K;
INCLUDE "targets/arm.ld"

View File

@@ -0,0 +1,10 @@
MEMORY
{
FLASH_TEXT (rw) : ORIGIN = 0x00000000+0x0000, LENGTH = 0x00100000-0x0000
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x00040000
}
_stack_size = 4K;
INCLUDE "targets/arm.ld"

14
targets/attiny1616.json Normal file
View File

@@ -0,0 +1,14 @@
{
"inherits": ["avrtiny"],
"cpu": "attiny1616",
"build-tags": ["attiny1616"],
"gc": "none",
"cflags": [
"-D__AVR_ARCH__=103"
],
"linkerscript": "src/device/avr/attiny1616.ld",
"extra-files": [
"src/device/avr/attiny1616.s"
],
"flash-command": "pymcuprog write -f {hex} --erase --verify -d attiny1616 -t uart -u {port}"
}

13
targets/attiny85.json Normal file
View File

@@ -0,0 +1,13 @@
{
"inherits": ["avr"],
"cpu": "attiny85",
"build-tags": ["attiny85", "attiny", "avr2", "avr25"],
"cflags": [
"-D__AVR_ARCH__=25"
],
"linkerscript": "src/device/avr/attiny85.ld",
"extra-files": [
"targets/avr.S",
"src/device/avr/attiny85.s"
]
}

84
targets/avr.S Normal file
View File

@@ -0,0 +1,84 @@
; This file provides common code across AVRs that cannot be implemented directly
; in Go.
; The reset vector is device-specific and is generated by tools/gen-device-avr.py.
; These definitions are necessary because LLVM does not yet know these register
; aliases. See: https://reviews.llvm.org/D96492
#define xl r26
#define xh r27
#define yl r28
#define yh r29
#define zl r30
#define zh r31
; Ugly hack until https://reviews.llvm.org/D137572 is merged.
#if !defined(__AVR_HAVE_ELPM__) && defined(__flash1)
#define __AVR_HAVE_ELPM__
#endif
; Startup code
.section .text.__vector_RESET
.global __vector_RESET
__vector_RESET:
clr r1 ; r1 is expected to be 0 by the C calling convention
; Set up the stack pointer.
ldi xl, lo8(_stack_top)
ldi xh, hi8(_stack_top)
out 0x3d, xl; SPL
out 0x3e, xh; SPH
; Subtract one from the stack pointer, so it doesn't point in the .data section.
push r0
; Initialize .data
init_data:
ldi xl, lo8(_sdata)
ldi xh, hi8(_sdata)
ldi yl, lo8(_edata)
ldi yh, hi8(_edata)
ldi zl, lo8(_sidata)
ldi zh, hi8(_sidata)
#ifdef __AVR_HAVE_ELPM__
ldi r16, hh8(_sidata) ; RAMPZ = hh8(_sidata)
out 0x3b, r16
#endif
init_data_loop:
cp xl, yl ; if x == y
cpc xh, yh
breq init_data_end ; goto main
#ifdef __AVR_HAVE_ELPM__
elpm r0, Z+ ; r0 = *(z++)
#else
lpm r0, Z+ ; r0 = *(z++)
#endif
st X+, r0 ; *(x++) = r0
rjmp init_data_loop ; goto init_data_loop
init_data_end:
; main will be placed right after here by the linker script so there's no
; need to jump.
; The only thing this WDT handler really does is disable itself, to get out of
; sleep mode.
.section .text.__vector_WDT
.global __vector_WDT
__vector_WDT:
push r16
clr r16
wdr ; Reset watchdog
out 0x34, r16 ; Clear reset reason (MCUSR)
; part 1: set WDCE and WDE to enable editing WDTCSR
lds r16, 0x60 ; r16 = WDTCSR
ori r16, 0x18 ; r16 |= WDCE | WDE
sts 0x60, r16 ; WDTCSR = r16
; part 2: within 4 clock cycles, set the new value for WDTCSR
clr r16
sts 0x60, r16 ; WDTCSR = 0
pop r16
reti

24
targets/avr.json Normal file
View File

@@ -0,0 +1,24 @@
{
"llvm-target": "avr",
"build-tags": ["avr", "baremetal", "linux", "arm"],
"goos": "linux",
"goarch": "arm",
"gc": "conservative",
"linker": "ld.lld",
"scheduler": "none",
"rtlib": "compiler-rt",
"libc": "picolibc",
"default-stack-size": 256,
"cflags": [
"-Werror"
],
"ldflags": [
"-T", "targets/avr.ld",
"--gc-sections"
],
"extra-files": [
"src/internal/task/task_stack_avr.S",
"src/runtime/asm_avr.S"
],
"gdb": ["avr-gdb"]
}

56
targets/avr.ld Normal file
View File

@@ -0,0 +1,56 @@
MEMORY
{
FLASH_TEXT (rw) : ORIGIN = 0, LENGTH = __flash_size - _bootloader_size
RAM (xrw) : ORIGIN = 0x800000 + __ram_start, LENGTH = __ram_size
}
ENTRY(main)
SECTIONS
{
.text :
{
KEEP(*(.vectors))
KEEP(*(.text.__vector_RESET))
KEEP(*(.text.main)) /* main must follow the reset handler */
*(.text)
*(.text.*)
*(.progmem)
*(.progmem.*)
. = ALIGN(16); /* needed with ld.lld for some reasoon */
}
.stack (NOLOAD) :
{
. += _stack_size;
_stack_top = .;
} >RAM
_sidata = LOADADDR(.data);
.data :
{
_sdata = .; /* used by startup code */
*(.rodata)
*(.rodata.*)
*(.data)
*(.data*)
_edata = .; /* used by startup code */
} >RAM AT>FLASH_TEXT
.bss :
{
_sbss = .; /* used by startup code */
*(.bss)
*(.bss*)
*(COMMON)
_ebss = .; /* used by startup code */
} >RAM
}
/* For the memory allocator. */
_heap_start = _ebss;
_heap_end = ORIGIN(RAM) + LENGTH(RAM);
_globals_start = _sdata;
_globals_end = _ebss;

43
targets/avrtiny.S Normal file
View File

@@ -0,0 +1,43 @@
#define __tmp_reg__ r16
#define __zero_reg__ r17
; Startup code
.section .text.__vector_RESET
.global __vector_RESET
__vector_RESET:
clr __zero_reg__ ; this register is expected to be 0 by the C calling convention
; Keep the stack pointer at the default location, which is RAMEND.
; Initialize .data section.
.section .text.__do_copy_data,"ax",@progbits
.global __do_copy_data
__do_copy_data:
ldi xl, lo8(__data_start)
ldi xh, hi8(__data_start)
ldi yl, lo8(__data_end)
ldi yh, hi8(__data_end)
ldi zl, lo8(__data_load_start)
ldi zh, hi8(__data_load_start)
1: ; loop
cp xl, yl ; if x == y
cpc xh, yh
breq 2f ; goto end
ld r16, Z+ ; r0 = *(z++)
st X+, r16 ; *(x++) = r0
rjmp 1b ; goto loop
2: ; end
; Initialize .bss section.
.section .text.__do_clear_bss,"ax",@progbits
.global __do_clear_bss
__do_clear_bss:
ldi xl, lo8(__bss_start)
ldi xh, hi8(__bss_start)
ldi yl, lo8(__bss_end)
1: ; loop
cp xl, yl ; if x == y
breq 2f ; goto end
st X+, __zero_reg__ ; *(x++) = 0
rjmp 1b ; goto loop
2: ; end

25
targets/avrtiny.json Normal file
View File

@@ -0,0 +1,25 @@
{
"llvm-target": "avr",
"build-tags": ["avr", "avrtiny", "baremetal", "linux", "arm"],
"goos": "linux",
"goarch": "arm",
"gc": "conservative",
"linker": "ld.lld",
"scheduler": "none",
"rtlib": "compiler-rt",
"libc": "picolibc",
"default-stack-size": 256,
"cflags": [
"-Werror"
],
"ldflags": [
"-T", "targets/avrtiny.ld",
"--gc-sections"
],
"extra-files": [
"src/internal/task/task_stack_avr.S",
"src/runtime/asm_avr.S",
"targets/avrtiny.S"
],
"gdb": ["avr-gdb"]
}

58
targets/avrtiny.ld Normal file
View File

@@ -0,0 +1,58 @@
/* Linker script for AVRs with a unified flash and RAM address space. This
* includes the ATtiny10 and the ATtiny1616.
*/
MEMORY
{
FLASH_TEXT (x) : ORIGIN = 0, LENGTH = __flash_size
FLASH_DATA (r) : ORIGIN = __mapped_flash_start, LENGTH = __flash_size
RAM (xrw) : ORIGIN = __ram_start, LENGTH = __ram_size
}
ENTRY(main)
SECTIONS
{
.text :
{
KEEP(*(.vectors))
*(.text.__vector_RESET)
KEEP(*(.text.__do_copy_data)) /* TODO: only use when __do_copy_data is requested */
KEEP(*(.text.__do_clear_bss))
KEEP(*(.text.main)) /* main must follow the reset handler */
*(.text)
*(.text.*)
} > FLASH_TEXT
/* Read-only data is stored in flash, but is read from an offset (0x4000 or
* 0x8000 depending on the chip). This requires some weird math to get it in
* the right place.
*/
.rodata ORIGIN(FLASH_DATA) + ADDR(.text) + SIZEOF(.text):
{
*(.rodata)
*(.rodata.*)
} AT>FLASH_TEXT
/* The address to which the data section should be copied by the startup
* code.
*/
__data_load_start = ORIGIN(FLASH_DATA) + LOADADDR(.data);
.data :
{
__data_start = .; /* used by startup code */
*(.data)
*(.data*)
__data_end = .; /* used by startup code */
} >RAM AT>FLASH_TEXT
.bss :
{
__bss_start = .; /* used by startup code */
*(.bss)
*(.bss*)
*(COMMON)
__bss_end = .; /* used by startup code */
} >RAM
}

13
targets/badger2040-w.json Normal file
View File

@@ -0,0 +1,13 @@
{
"inherits": [
"rp2040"
],
"serial-port": ["2e8a:0003"],
"build-tags": ["badger2040_w", "cyw43439"],
"ldflags": [
"--defsym=__flash_size=1020K"
],
"extra-files": [
"targets/pico-boot-stage2.S"
]
}

13
targets/badger2040.json Normal file
View File

@@ -0,0 +1,13 @@
{
"inherits": [
"rp2040"
],
"serial-port": ["2e8a:0003"],
"build-tags": ["badger2040"],
"ldflags": [
"--defsym=__flash_size=1020K"
],
"extra-files": [
"targets/pico-boot-stage2.S"
]
}

View File

@@ -0,0 +1,6 @@
{
"inherits": ["nrf52840", "nrf52840-s140v6-uf2"],
"build-tags": ["bluemicro840"],
"serial-port": ["1d50:6161"],
"msd-volume-name": ["BLUEMICRO"]
}

View File

@@ -0,0 +1,4 @@
{
"inherits": ["bluepill"],
"openocd-commands": ["set CPUTAPID 0x2ba01477"]
}

12
targets/bluepill.json Normal file
View File

@@ -0,0 +1,12 @@
{
"inherits": ["cortex-m3"],
"build-tags": ["bluepill", "stm32f103", "stm32f1", "stm32"],
"serial": "uart",
"linkerscript": "targets/stm32.ld",
"extra-files": [
"src/device/stm32/stm32f103.s"
],
"flash-method": "openocd",
"openocd-interface": "stlink-v2",
"openocd-target": "stm32f1x"
}

13
targets/btt-skr-pico.json Normal file
View File

@@ -0,0 +1,13 @@
{
"inherits": [
"rp2040"
],
"build-tags": ["btt_skr_pico"],
"serial-port": ["2e8a:000A"],
"ldflags": [
"--defsym=__flash_size=16M"
],
"extra-files": [
"targets/pico-boot-stage2.S"
]
}

View File

@@ -0,0 +1,13 @@
{
"inherits": [
"rp2040"
],
"serial-port": ["2e8a:1023"],
"build-tags": ["challenger_rp2040"],
"ldflags": [
"--defsym=__flash_size=8M"
],
"extra-files": [
"targets/feather-rp2040-boot-stage2.S"
]
}

View File

@@ -0,0 +1,6 @@
{
"inherits": ["nrf52840", "nrf52840-s140v6-uf2"],
"build-tags": ["circuitplay_bluefruit"],
"serial-port": ["239a:8045"],
"msd-volume-name": ["CPLAYBTBOOT"]
}

View File

@@ -0,0 +1,9 @@
{
"inherits": ["atsamd21g18a"],
"build-tags": ["circuitplay_express"],
"flash-1200-bps-reset": "true",
"flash-method": "msd",
"serial-port": ["239a:8018"],
"msd-volume-name": ["CPLAYBOOT"],
"msd-firmware-name": "firmware.uf2"
}

6
targets/clue-alpha.json Normal file
View File

@@ -0,0 +1,6 @@
{
"inherits": ["nrf52840", "nrf52840-s140v6-uf2"],
"build-tags": ["clue_alpha"],
"serial-port": ["239a:8072", "239a:8071"],
"msd-volume-name": ["CLUEBOOT"]
}

3
targets/clue.json Normal file
View File

@@ -0,0 +1,3 @@
{
"inherits": ["clue-alpha"]
}

View File

@@ -0,0 +1,10 @@
{
"inherits": ["cortex-m3"],
"build-tags": ["qemu", "lm3s6965"],
"linkerscript": "targets/lm3s6965.ld",
"default-stack-size": 4096,
"extra-files": [
"targets/cortex-m-qemu.s"
],
"emulator": "qemu-system-arm -machine lm3s6965evb -semihosting -nographic -kernel {}"
}

59
targets/cortex-m-qemu.s Normal file
View File

@@ -0,0 +1,59 @@
// Generic Cortex-M interrupt vector.
// This vector is used by the Cortex-M QEMU target.
.cfi_sections .debug_frame
.syntax unified
// This is the default handler for interrupts, if triggered but not defined.
.section .text.Default_Handler
.global Default_Handler
.type Default_Handler, %function
Default_Handler:
.cfi_startproc
wfe
b Default_Handler
.cfi_endproc
.size Default_Handler, .-Default_Handler
// Avoid the need for repeated .weak and .set instructions.
.macro IRQ handler
.weak \handler
.set \handler, Default_Handler
.endm
.section .isr_vector, "a", %progbits
.global __isr_vector
__isr_vector:
// Interrupt vector as defined by Cortex-M, starting with the stack top.
// On reset, SP is initialized with *0x0 and PC is loaded with *0x4, loading
// _stack_top and Reset_Handler.
.long _stack_top
.long Reset_Handler
.long NMI_Handler
.long HardFault_Handler
.long MemoryManagement_Handler
.long BusFault_Handler
.long UsageFault_Handler
.long 0
.long 0
.long 0
.long 0
.long SVC_Handler
.long DebugMon_Handler
.long 0
.long PendSV_Handler
.long SysTick_Handler
// Define default implementations for interrupts, redirecting to
// Default_Handler when not implemented.
IRQ NMI_Handler
IRQ HardFault_Handler
IRQ MemoryManagement_Handler
IRQ BusFault_Handler
IRQ UsageFault_Handler
IRQ SVC_Handler
IRQ DebugMon_Handler
IRQ PendSV_Handler
IRQ SysTick_Handler
.size __isr_vector, .-__isr_vector

30
targets/cortex-m.json Normal file
View File

@@ -0,0 +1,30 @@
{
"build-tags": ["cortexm", "baremetal", "linux", "arm"],
"goos": "linux",
"goarch": "arm",
"gc": "conservative",
"scheduler": "tasks",
"linker": "ld.lld",
"rtlib": "compiler-rt",
"libc": "picolibc",
"automatic-stack-size": true,
"default-stack-size": 2048,
"cflags": [
"-Werror",
"-fshort-enums",
"-fomit-frame-pointer",
"-mfloat-abi=soft",
"-fno-exceptions", "-fno-unwind-tables", "-fno-asynchronous-unwind-tables",
"-ffunction-sections", "-fdata-sections"
],
"ldflags": [
"--emit-relocs",
"--gc-sections"
],
"extra-files": [
"src/device/arm/cortexm.S",
"src/internal/task/task_stack_cortexm.S",
"src/runtime/asm_arm.S"
],
"gdb": ["gdb-multiarch", "arm-none-eabi-gdb", "gdb"]
}

6
targets/cortex-m0.json Normal file
View File

@@ -0,0 +1,6 @@
{
"inherits": ["cortex-m"],
"llvm-target": "thumbv6m-unknown-unknown-eabi",
"cpu": "cortex-m0",
"features": "+armv6-m,+soft-float,+strict-align,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp"
}

View File

@@ -0,0 +1,6 @@
{
"inherits": ["cortex-m"],
"llvm-target": "thumbv6m-unknown-unknown-eabi",
"cpu": "cortex-m0plus",
"features": "+armv6-m,+soft-float,+strict-align,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp"
}

6
targets/cortex-m3.json Normal file
View File

@@ -0,0 +1,6 @@
{
"inherits": ["cortex-m"],
"llvm-target": "thumbv7m-unknown-unknown-eabi",
"cpu": "cortex-m3",
"features": "+armv7-m,+hwdiv,+soft-float,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp"
}

6
targets/cortex-m33.json Normal file
View File

@@ -0,0 +1,6 @@
{
"inherits": ["cortex-m"],
"llvm-target": "thumbv8m.main-unknown-unknown-eabi",
"cpu": "cortex-m33",
"features": "+armv8-m.main,+dsp,+hwdiv,+soft-float,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp"
}

6
targets/cortex-m4.json Normal file
View File

@@ -0,0 +1,6 @@
{
"inherits": ["cortex-m"],
"llvm-target": "thumbv7em-unknown-unknown-eabi",
"cpu": "cortex-m4",
"features": "+armv7e-m,+dsp,+hwdiv,+soft-float,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp"
}

6
targets/cortex-m7.json Normal file
View File

@@ -0,0 +1,6 @@
{
"inherits": ["cortex-m"],
"llvm-target": "thumbv7em-unknown-unknown-eabi",
"cpu": "cortex-m7",
"features": "+armv7e-m,+dsp,+hwdiv,+soft-float,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp"
}

3
targets/d1mini.json Normal file
View File

@@ -0,0 +1,3 @@
{
"inherits": ["nodemcu"]
}

10
targets/digispark.json Normal file
View File

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

View File

@@ -0,0 +1,12 @@
{
"inherits": ["rp2040"],
"build-tags": ["elecrow_rp2040", "comboat_fw"],
"serial-port": ["2e8a:000a"],
"default-stack-size": 8192,
"ldflags": [
"--defsym=__flash_size=8M"
],
"extra-files": [
"targets/pico-boot-stage2.S"
]
}

View File

@@ -0,0 +1,12 @@
{
"inherits": ["rp2350"],
"build-tags": ["elecrow_rp2350", "comboat_fw"],
"serial-port": ["2e8a:000f"],
"default-stack-size": 8192,
"ldflags": [
"--defsym=__flash_size=8M"
],
"extra-files": [
"targets/pico-boot-stage2.S"
]
}

View File

@@ -0,0 +1,5 @@
{
"inherits": ["esp32c3"],
"build-tags": ["esp_c3_32s_kit"],
"serial-port": ["1a86:7523"]
}

View File

@@ -0,0 +1,4 @@
{
"inherits": ["esp32c3"],
"build-tags": ["esp32_c3_devkit_rust_1"]
}

View File

@@ -0,0 +1,4 @@
{
"inherits": ["esp32"],
"build-tags": ["esp32_coreboard_v2"]
}

View File

@@ -0,0 +1,3 @@
{
"inherits": ["esp32-coreboard-v2"]
}

21
targets/esp32.json Normal file
View File

@@ -0,0 +1,21 @@
{
"inherits": ["xtensa"],
"cpu": "esp32",
"features": "+atomctl,+bool,+clamps,+coprocessor,+debug,+density,+dfpaccel,+div32,+exception,+fp,+highpriinterrupts,+interrupt,+loop,+mac16,+memctl,+minmax,+miscsr,+mul32,+mul32high,+nsa,+prid,+regprotect,+rvector,+s32c1i,+sext,+threadptr,+timerint,+windowed",
"build-tags": ["esp32", "esp"],
"scheduler": "tasks",
"serial": "uart",
"linker": "ld.lld",
"default-stack-size": 2048,
"rtlib": "compiler-rt",
"libc": "picolibc",
"linkerscript": "targets/esp32.ld",
"extra-files": [
"src/device/esp/esp32.S",
"src/internal/task/task_stack_esp32.S"
],
"binary-format": "esp32",
"flash-command": "esptool.py --chip=esp32 --port {port} write_flash 0x1000 {bin} -ff 80m -fm dout",
"emulator": "qemu-system-xtensa -machine esp32 -nographic -drive file={img},if=mtd,format=raw",
"gdb": ["xtensa-esp32-elf-gdb"]
}

202
targets/esp32.ld Normal file
View File

@@ -0,0 +1,202 @@
/* Linker script for the ESP32 */
MEMORY
{
/* Data RAM. Allows byte access.
* There are various data RAM regions:
* SRAM2: 0x3FFA_E000..0x3FFD_FFFF (72 + 128 = 200K)
* SRAM1: 0x3FFE_0000..0x3FFF_FFFF (128K)
* This gives us 328K of contiguous RAM, which is the largest span possible.
* SRAM1 has other addresses as well but the datasheet seems to indicate
* these are aliases.
*/
DRAM (rw) : ORIGIN = 0x3FFAE000, LENGTH = 200K + 128K /* Internal SRAM 1 + 2 */
/* Instruction RAM. */
IRAM (x) : ORIGIN = 0x40080000, LENGTH = 128K /* Internal SRAM 0 */
}
/* The entry point. It is set in the image flashed to the chip, so must be
* defined.
*/
ENTRY(call_start_cpu0)
SECTIONS
{
/* Constant literals and code. Loaded into IRAM for now. Eventually, most
* code should be executed directly from flash.
* Note that literals must be before code for the l32r instruction to work.
*/
.text : ALIGN(4)
{
*(.literal.call_start_cpu0)
*(.text.call_start_cpu0)
*(.literal .text)
*(.literal.* .text.*)
} >IRAM
/* Put the stack at the bottom of DRAM, so that the application will
* crash on stack overflow instead of silently corrupting memory.
* See: http://blog.japaric.io/stack-overflow-protection/ */
.stack (NOLOAD) :
{
. = ALIGN(16);
. += _stack_size;
_stack_top = .;
} >DRAM
/* Constant global variables.
* They are loaded in DRAM for ease of use. Eventually they should be stored
* in flash and loaded directly from there but they're kept in RAM to make
* sure they can always be accessed (even in interrupts).
*/
.rodata : ALIGN(4)
{
*(.rodata)
*(.rodata.*)
} >DRAM
/* Mutable global variables.
*/
.data : ALIGN(4)
{
_sdata = ABSOLUTE(.);
*(.data)
*(.data.*)
_edata = ABSOLUTE(.);
} >DRAM
/* Check that the boot ROM stack (for the APP CPU) does not overlap with the
* data that is loaded by the boot ROM. There may be ways to avoid this
* issue if it occurs in practice.
* The magic value here is _stack_sentry in the boot ROM ELF file.
*/
ASSERT(_edata < 0x3ffe1320, "the .data section overlaps with the stack used by the boot ROM, possibly causing corruption at startup")
/* Global variables that are mutable and zero-initialized.
* These must be zeroed at startup (unlike data, which is loaded by the
* bootloader).
*/
.bss (NOLOAD) : ALIGN(4)
{
. = ALIGN (4);
_sbss = ABSOLUTE(.);
*(.bss)
*(.bss.*)
. = ALIGN (4);
_ebss = ABSOLUTE(.);
} >DRAM
}
/* For the garbage collector.
*/
_globals_start = _sdata;
_globals_end = _ebss;
_heap_start = _ebss;
_heap_end = ORIGIN(DRAM) + LENGTH(DRAM);
_stack_size = 4K;
/* From ESP-IDF:
* components/esp_rom/esp32/ld/esp32.rom.newlib-funcs.ld
* This is the subset that is sometimes used by LLVM during codegen, and thus
* must always be present.
*/
memcpy = 0x4000c2c8;
memmove = 0x4000c3c0;
memset = 0x4000c44c;
/* From ESP-IDF:
* components/esp_rom/esp32/ld/esp32.rom.libgcc.ld
* These are called from LLVM during codegen. The original license is Apache
* 2.0, but I believe that a list of function names and addresses can't really
* be copyrighted.
*/
__absvdi2 = 0x4006387c;
__absvsi2 = 0x40063868;
__adddf3 = 0x40002590;
__addsf3 = 0x400020e8;
__addvdi3 = 0x40002cbc;
__addvsi3 = 0x40002c98;
__ashldi3 = 0x4000c818;
__ashrdi3 = 0x4000c830;
__bswapdi2 = 0x40064b08;
__bswapsi2 = 0x40064ae0;
__clrsbdi2 = 0x40064b7c;
__clrsbsi2 = 0x40064b64;
__clzdi2 = 0x4000ca50;
__clzsi2 = 0x4000c7e8;
__cmpdi2 = 0x40063820;
__ctzdi2 = 0x4000ca64;
__ctzsi2 = 0x4000c7f0;
__divdc3 = 0x400645a4;
__divdf3 = 0x40002954;
__divdi3 = 0x4000ca84;
__divsi3 = 0x4000c7b8;
__eqdf2 = 0x400636a8;
__eqsf2 = 0x40063374;
__extendsfdf2 = 0x40002c34;
__ffsdi2 = 0x4000ca2c;
__ffssi2 = 0x4000c804;
__fixdfdi = 0x40002ac4;
__fixdfsi = 0x40002a78;
__fixsfdi = 0x4000244c;
__fixsfsi = 0x4000240c;
__fixunsdfsi = 0x40002b30;
__fixunssfdi = 0x40002504;
__fixunssfsi = 0x400024ac;
__floatdidf = 0x4000c988;
__floatdisf = 0x4000c8c0;
__floatsidf = 0x4000c944;
__floatsisf = 0x4000c870;
__floatundidf = 0x4000c978;
__floatundisf = 0x4000c8b0;
__floatunsidf = 0x4000c938;
__floatunsisf = 0x4000c864;
__gcc_bcmp = 0x40064a70;
__gedf2 = 0x40063768;
__gesf2 = 0x4006340c;
__gtdf2 = 0x400636dc;
__gtsf2 = 0x400633a0;
__ledf2 = 0x40063704;
__lesf2 = 0x400633c0;
__lshrdi3 = 0x4000c84c;
__ltdf2 = 0x40063790;
__ltsf2 = 0x4006342c;
__moddi3 = 0x4000cd4c;
__modsi3 = 0x4000c7c0;
__muldc3 = 0x40063c90;
__muldf3 = 0x4006358c;
__muldi3 = 0x4000c9fc;
__mulsf3 = 0x400632c8;
__mulsi3 = 0x4000c7b0;
__mulvdi3 = 0x40002d78;
__mulvsi3 = 0x40002d60;
__nedf2 = 0x400636a8;
__negdf2 = 0x400634a0;
__negdi2 = 0x4000ca14;
__negsf2 = 0x400020c0;
__negvdi2 = 0x40002e98;
__negvsi2 = 0x40002e78;
__nesf2 = 0x40063374;
__nsau_data = 0x3ff96544;
__paritysi2 = 0x40002f3c;
__popcount_tab = 0x3ff96544;
__popcountdi2 = 0x40002ef8;
__popcountsi2 = 0x40002ed0;
__powidf2 = 0x400638e4;
__subdf3 = 0x400026e4;
__subsf3 = 0x400021d0;
__subvdi3 = 0x40002d20;
__subvsi3 = 0x40002cf8;
__truncdfsf2 = 0x40002b90;
__ucmpdi2 = 0x40063840;
__udiv_w_sdiv = 0x40064bec;
__udivdi3 = 0x4000cff8;
__udivmoddi4 = 0x40064bf4;
__udivsi3 = 0x4000c7c8;
__umoddi3 = 0x4000d280;
__umodsi3 = 0x4000c7d0;
__umulsidi3 = 0x4000c7d8;
__unorddf2 = 0x400637f4;
__unordsf2 = 0x40063478;

5
targets/esp32c3-12f.json Normal file
View File

@@ -0,0 +1,5 @@
{
"inherits": ["esp32c3"],
"build-tags": ["esp32c312f"]
}

View File

@@ -0,0 +1,4 @@
{
"inherits": ["esp32c3"],
"build-tags": ["esp32c3_supermini"]
}

23
targets/esp32c3.json Normal file
View File

@@ -0,0 +1,23 @@
{
"inherits": ["riscv32"],
"features": "+32bit,+c,+m,+zmmul,-a,-b,-d,-e,-experimental-smmpm,-experimental-smnpm,-experimental-ssnpm,-experimental-sspm,-experimental-ssqosid,-experimental-supm,-experimental-zacas,-experimental-zalasr,-experimental-zicfilp,-experimental-zicfiss,-f,-h,-relax,-shcounterenw,-shgatpa,-shtvala,-shvsatpa,-shvstvala,-shvstvecd,-smaia,-smcdeleg,-smcsrind,-smepmp,-smstateen,-ssaia,-ssccfg,-ssccptr,-sscofpmf,-sscounterenw,-sscsrind,-ssstateen,-ssstrict,-sstc,-sstvala,-sstvecd,-ssu64xl,-svade,-svadu,-svbare,-svinval,-svnapot,-svpbmt,-v,-xcvalu,-xcvbi,-xcvbitmanip,-xcvelw,-xcvmac,-xcvmem,-xcvsimd,-xesppie,-xsfcease,-xsfvcp,-xsfvfnrclipxfqf,-xsfvfwmaccqqq,-xsfvqmaccdod,-xsfvqmaccqoq,-xsifivecdiscarddlone,-xsifivecflushdlone,-xtheadba,-xtheadbb,-xtheadbs,-xtheadcmo,-xtheadcondmov,-xtheadfmemidx,-xtheadmac,-xtheadmemidx,-xtheadmempair,-xtheadsync,-xtheadvdot,-xventanacondops,-xwchc,-za128rs,-za64rs,-zaamo,-zabha,-zalrsc,-zama16b,-zawrs,-zba,-zbb,-zbc,-zbkb,-zbkc,-zbkx,-zbs,-zca,-zcb,-zcd,-zce,-zcf,-zcmop,-zcmp,-zcmt,-zdinx,-zfa,-zfbfmin,-zfh,-zfhmin,-zfinx,-zhinx,-zhinxmin,-zic64b,-zicbom,-zicbop,-zicboz,-ziccamoa,-ziccif,-zicclsm,-ziccrse,-zicntr,-zicond,-zicsr,-zifencei,-zihintntl,-zihintpause,-zihpm,-zimop,-zk,-zkn,-zknd,-zkne,-zknh,-zkr,-zks,-zksed,-zksh,-zkt,-ztso,-zvbb,-zvbc,-zve32f,-zve32x,-zve64d,-zve64f,-zve64x,-zvfbfmin,-zvfbfwma,-zvfh,-zvfhmin,-zvkb,-zvkg,-zvkn,-zvknc,-zvkned,-zvkng,-zvknha,-zvknhb,-zvks,-zvksc,-zvksed,-zvksg,-zvksh,-zvkt,-zvl1024b,-zvl128b,-zvl16384b,-zvl2048b,-zvl256b,-zvl32768b,-zvl32b,-zvl4096b,-zvl512b,-zvl64b,-zvl65536b,-zvl8192b",
"build-tags": ["esp32c3", "esp"],
"serial": "usb",
"rtlib": "compiler-rt",
"libc": "picolibc",
"cflags": [
"-march=rv32imc"
],
"linkerscript": "targets/esp32c3.ld",
"extra-files": [
"src/device/esp/esp32c3.S"
],
"binary-format": "esp32c3",
"flash-command": "esptool.py --chip=esp32c3 --port {port} write_flash 0x0 {bin}",
"serial-port": ["303a:1001"],
"openocd-interface": "esp_usb_jtag",
"openocd-target": "esp32c3",
"openocd-commands": ["gdb_memory_map disable"],
"gdb": ["riscv32-esp-elf-gdb"]
}

2238
targets/esp32c3.ld Normal file

File diff suppressed because it is too large Load Diff

18
targets/esp8266.json Normal file
View File

@@ -0,0 +1,18 @@
{
"inherits": ["xtensa"],
"cpu": "esp8266",
"features": "+debug,+density,+exception,+extendedl32r,+highpriinterrupts,+interrupt,+mul32,+nsa,+prid,+regprotect,+rvector,+timerint",
"build-tags": ["esp8266", "esp"],
"scheduler": "tasks",
"linker": "ld.lld",
"default-stack-size": 2048,
"rtlib": "compiler-rt",
"libc": "picolibc",
"linkerscript": "targets/esp8266.ld",
"extra-files": [
"src/device/esp/esp8266.S",
"src/internal/task/task_stack_esp8266.S"
],
"binary-format": "esp8266",
"flash-command": "esptool.py --chip=esp8266 --port {port} write_flash 0x00000 {bin} -fm qio"
}

109
targets/esp8266.ld Normal file
View File

@@ -0,0 +1,109 @@
/* Linker script for the ESP8266 */
MEMORY
{
/* Data RAM. Allows byte access. */
DRAM (rw) : ORIGIN = 0x3FFE8000, LENGTH = 80K
/* Instruction RAM. */
IRAM (x) : ORIGIN = 0x40100000, LENGTH = 32K
}
/* The entry point. It is set in the image flashed to the chip, so must be
* defined.
*/
ENTRY(main)
SECTIONS
{
/* Mutable global variables.
*/
.data : ALIGN(4)
{
_sdata = ABSOLUTE(.);
*(.data)
*(.data.*)
} >DRAM
/* Constant global variables.
* Note that they still need to be loaded in RAM because the ESP8266 doesn't
* allow byte access to flash.
*/
.rodata : ALIGN(4)
{
*(.rodata)
*(.rodata.*)
} >DRAM
/* Global variables that are mutable and zero-initialized.
*/
.bss (NOLOAD) : ALIGN(4)
{
. = ALIGN (4);
_sbss = ABSOLUTE(.);
*(.bss)
*(.bss.*)
. = ALIGN (4);
_ebss = ABSOLUTE(.);
} >DRAM
/* Constant literals and code. Loaded into IRAM for now. Eventually, most
* code should be executed directly from flash.
* Note that literals must be before code for the l32r instruction to work.
*/
.text : ALIGN(4)
{
*(.literal .text)
*(.literal.* .text.*)
} >IRAM
}
_globals_start = _sdata;
_globals_end = _ebss;
_heap_start = _ebss;
_heap_end = ORIGIN(DRAM) + LENGTH(DRAM);
/* It appears that the stack is set to 0x3ffffff0 when main is called.
* Be conservative and scan all the way up to the end of the RAM.
*/
_stack_top = 0x40000000;
/* Functions normally provided by a libc.
* Source:
* https://github.com/espressif/ESP8266_NONOS_SDK/blob/master/ld/eagle.rom.addr.v6.ld
*/
memcpy = 0x4000df48;
memmove = 0x4000e04c;
memset = 0x4000e190;
/* Compiler runtime functions provided by the ROM.
* Source:
* https://github.com/espressif/ESP8266_NONOS_SDK/blob/master/ld/eagle.rom.addr.v6.ld
*/
__adddf3 = 0x4000c538;
__addsf3 = 0x4000c180;
__divdf3 = 0x4000cb94;
__divdi3 = 0x4000ce60;
__divsi3 = 0x4000dc88;
__extendsfdf2 = 0x4000cdfc;
__fixdfsi = 0x4000ccb8;
__fixunsdfsi = 0x4000cd00;
__fixunssfsi = 0x4000c4c4;
__floatsidf = 0x4000e2f0;
__floatsisf = 0x4000e2ac;
__floatunsidf = 0x4000e2e8;
__floatunsisf = 0x4000e2a4;
__muldf3 = 0x4000c8f0;
__muldi3 = 0x40000650;
__mulsf3 = 0x4000c3dc;
__subdf3 = 0x4000c688;
__subsf3 = 0x4000c268;
__truncdfsf2 = 0x4000cd5c;
__udivdi3 = 0x4000d310;
__udivsi3 = 0x4000e21c;
__umoddi3 = 0x4000d770;
__umodsi3 = 0x4000e268;
__umulsidi3 = 0x4000dcf0;
/* Proprietary ROM function needed for proper clock configuration.
*/
rom_i2c_writeReg = 0x400072d8;

6
targets/fe310.json Normal file
View File

@@ -0,0 +1,6 @@
{
"inherits": ["riscv32"],
"cpu": "sifive-e31",
"features": "+32bit,+a,+c,+m,+zmmul,-b,-d,-e,-experimental-smmpm,-experimental-smnpm,-experimental-ssnpm,-experimental-sspm,-experimental-ssqosid,-experimental-supm,-experimental-zacas,-experimental-zalasr,-experimental-zicfilp,-experimental-zicfiss,-f,-h,-relax,-shcounterenw,-shgatpa,-shtvala,-shvsatpa,-shvstvala,-shvstvecd,-smaia,-smcdeleg,-smcsrind,-smepmp,-smstateen,-ssaia,-ssccfg,-ssccptr,-sscofpmf,-sscounterenw,-sscsrind,-ssstateen,-ssstrict,-sstc,-sstvala,-sstvecd,-ssu64xl,-svade,-svadu,-svbare,-svinval,-svnapot,-svpbmt,-v,-xcvalu,-xcvbi,-xcvbitmanip,-xcvelw,-xcvmac,-xcvmem,-xcvsimd,-xesppie,-xsfcease,-xsfvcp,-xsfvfnrclipxfqf,-xsfvfwmaccqqq,-xsfvqmaccdod,-xsfvqmaccqoq,-xsifivecdiscarddlone,-xsifivecflushdlone,-xtheadba,-xtheadbb,-xtheadbs,-xtheadcmo,-xtheadcondmov,-xtheadfmemidx,-xtheadmac,-xtheadmemidx,-xtheadmempair,-xtheadsync,-xtheadvdot,-xventanacondops,-xwchc,-za128rs,-za64rs,-zaamo,-zabha,-zalrsc,-zama16b,-zawrs,-zba,-zbb,-zbc,-zbkb,-zbkc,-zbkx,-zbs,-zca,-zcb,-zcd,-zce,-zcf,-zcmop,-zcmp,-zcmt,-zdinx,-zfa,-zfbfmin,-zfh,-zfhmin,-zfinx,-zhinx,-zhinxmin,-zic64b,-zicbom,-zicbop,-zicboz,-ziccamoa,-ziccif,-zicclsm,-ziccrse,-zicntr,-zicond,-zicsr,-zifencei,-zihintntl,-zihintpause,-zihpm,-zimop,-zk,-zkn,-zknd,-zkne,-zknh,-zkr,-zks,-zksed,-zksh,-zkt,-ztso,-zvbb,-zvbc,-zve32f,-zve32x,-zve64d,-zve64f,-zve64x,-zvfbfmin,-zvfbfwma,-zvfh,-zvfhmin,-zvkb,-zvkg,-zvkn,-zvknc,-zvkned,-zvkng,-zvknha,-zvknhb,-zvks,-zvksc,-zvksed,-zvksg,-zvksh,-zvkt,-zvl1024b,-zvl128b,-zvl16384b,-zvl2048b,-zvl256b,-zvl32768b,-zvl32b,-zvl4096b,-zvl512b,-zvl64b,-zvl65536b,-zvl8192b",
"build-tags": ["fe310", "sifive"]
}

View File

@@ -0,0 +1,10 @@
{
"inherits": ["atsamd21g18a"],
"build-tags": ["feather_m0_express"],
"serial": "usb",
"serial-port": ["239a:801b"],
"flash-1200-bps-reset": "true",
"flash-method": "msd",
"msd-volume-name": ["FEATHERBOOT"],
"msd-firmware-name": "firmware.uf2"
}

10
targets/feather-m0.json Normal file
View File

@@ -0,0 +1,10 @@
{
"inherits": ["atsamd21g18a"],
"build-tags": ["feather_m0"],
"serial": "usb",
"serial-port": ["239a:801b", "239a:800b"],
"flash-1200-bps-reset": "true",
"flash-method": "msd",
"msd-volume-name": ["FEATHERBOOT"],
"msd-firmware-name": "firmware.uf2"
}

View File

@@ -0,0 +1,10 @@
{
"inherits": ["atsame51j19a"],
"build-tags": ["feather_m4_can"],
"serial": "usb",
"serial-port": ["239a:80cd"],
"flash-1200-bps-reset": "true",
"flash-method": "msd",
"msd-volume-name": ["FTHRCANBOOT"],
"msd-firmware-name": "firmware.uf2"
}

10
targets/feather-m4.json Normal file
View File

@@ -0,0 +1,10 @@
{
"inherits": ["atsamd51j19a"],
"build-tags": ["feather_m4"],
"serial": "usb",
"serial-port": ["239a:8022"],
"flash-1200-bps-reset": "true",
"flash-method": "msd",
"msd-volume-name": ["FEATHERBOOT"],
"msd-firmware-name": "firmware.uf2"
}

View File

@@ -0,0 +1,6 @@
{
"inherits": ["nrf52840", "nrf52840-s140v6-uf2"],
"build-tags": ["feather_nrf52840_sense"],
"serial-port": ["239a:8087", "239a:8088"],
"msd-volume-name": ["FTHRSNSBOOT"]
}

View File

@@ -0,0 +1,6 @@
{
"inherits": ["nrf52840", "nrf52840-s140v6-uf2"],
"build-tags": ["feather_nrf52840"],
"serial-port": ["239a:8029", "239a:802a"],
"msd-volume-name": ["FTHR840BOOT"]
}

View File

@@ -0,0 +1,17 @@
// Adafruit Feather RP2040 Stage 2 Bootloader
//
// This file defines the parameters specific to the flash-chip found
// on the Adafruit Feather RP2040. The generic implementation is in
// rp2040-boot-stage2.S
//
#define BOARD_PICO_FLASH_SPI_CLKDIV 4
#define BOARD_CMD_READ 0xe7
#define BOARD_QUAD_OK 1
#define BOARD_QUAD_ENABLE_STATUS_BYTE 2
#define BOARD_QUAD_ENABLE_BIT_MASK 2
#define BOARD_SPLIT_STATUS_WRITE 1
#define BOARD_WAIT_CYCLES 2
#include "rp2040-boot-stage2.S"

View File

@@ -0,0 +1,13 @@
{
"inherits": [
"rp2040"
],
"serial-port": ["239a:80f1"],
"build-tags": ["feather_rp2040"],
"ldflags": [
"--defsym=__flash_size=8192K"
],
"extra-files": [
"targets/feather-rp2040-boot-stage2.S"
]
}

View File

@@ -0,0 +1,15 @@
{
"inherits": ["cortex-m4"],
"build-tags": ["feather_stm32f405", "stm32f405", "stm32f4", "stm32"],
"serial": "uart",
"automatic-stack-size": false,
"linkerscript": "targets/stm32f405.ld",
"extra-files": [
"src/device/stm32/stm32f405.s"
],
"flash-method": "command",
"flash-command": "dfu-util --alt 0 --dfuse-address 0x08000000 --download {bin}",
"openocd-transport": "swd",
"openocd-interface": "jlink",
"openocd-target": "stm32f4x"
}

View File

@@ -0,0 +1,28 @@
{
"llvm-target": "armv4t-unknown-unknown-eabi",
"cpu": "arm7tdmi",
"features": "+armv4t,+strict-align,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-thumb-mode,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp",
"build-tags": ["gameboyadvance", "arm7tdmi", "baremetal", "linux", "arm"],
"goos": "linux",
"goarch": "arm",
"linker": "ld.lld",
"rtlib": "compiler-rt",
"libc": "picolibc",
"cflags": [
"-Werror",
"-fshort-enums",
"-fomit-frame-pointer",
"-fno-exceptions", "-fno-unwind-tables", "-fno-asynchronous-unwind-tables",
"-ffunction-sections", "-fdata-sections"
],
"ldflags": [
"--gc-sections"
],
"linkerscript": "targets/gameboy-advance.ld",
"extra-files": [
"targets/gameboy-advance.s",
"src/runtime/asm_arm.S"
],
"gdb": ["gdb-multiarch"],
"emulator": "mgba -3 {}"
}

View File

@@ -0,0 +1,84 @@
OUTPUT_ARCH(arm)
ENTRY(_start)
/* Note: iwram is reduced by 96 bytes because the last part of that RAM
* (starting at 0x03007FA0) is used for interrupt handling.
*/
MEMORY {
ewram : ORIGIN = 0x02000000, LENGTH = 256K /* on-board work RAM (2 wait states) */
iwram : ORIGIN = 0x03000000, LENGTH = 32K-96 /* in-chip work RAM (faster) */
rom : ORIGIN = 0x08000000, LENGTH = 32M /* flash ROM */
}
__stack_size_irq = 1K;
__stack_size_usr = 2K;
SECTIONS
{
.text :
{
KEEP (*(.init))
*(.text)
*(.text.*)
. = ALIGN(4);
} >rom
.rodata :
{
. = ALIGN(4);
*(.rodata)
*(.rodata.*)
. = ALIGN(4);
} >rom
/* Put the stack at the bottom of RAM, so that the application will
* crash on stack overflow instead of silently corrupting memory.
* See: http://blog.japaric.io/stack-overflow-protection/ */
.stack (NOLOAD) :
{
. = ALIGN(4);
_stack_top_irq = .;
. += __stack_size_irq;
_stack_top = .;
. += __stack_size_usr;
} >iwram
/* Start address (in flash) of .data, used by startup code. */
_sidata = LOADADDR(.data);
/* Globals with initial value */
.data :
{
. = ALIGN(4);
_sdata = .; /* used by startup code */
*(.data)
*(.data.*)
*(.iwram .iwram.*)
. = ALIGN(4);
_edata = .; /* used by startup code */
} >iwram AT>rom
/* Zero-initialized globals */
.bss :
{
. = ALIGN(4);
_sbss = .; /* used by startup code */
*(.bss)
*(.bss.*)
*(COMMON)
. = ALIGN(4);
_ebss = .; /* used by startup code */
} >iwram
/DISCARD/ :
{
*(.ARM.exidx) /* causes 'no memory region specified' error in lld */
*(.ARM.exidx.*) /* causes spurious 'undefined reference' errors */
}
}
/* For the memory allocator. */
_heap_start = ORIGIN(ewram);
_heap_end = ORIGIN(ewram) + LENGTH(ewram);
_globals_start = _sdata;
_globals_end = _ebss;

77
targets/gameboy-advance.s Normal file
View File

@@ -0,0 +1,77 @@
.section .init
.global _start
.align
.arm
_start:
b start_vector
// ROM header
.byte 0x24,0xff,0xae,0x51,0x69,0x9a,0xa2,0x21,0x3d,0x84,0x82,0x0a,0x84,0xe4,0x09,0xad
.byte 0x11,0x24,0x8b,0x98,0xc0,0x81,0x7f,0x21,0xa3,0x52,0xbe,0x19,0x93,0x09,0xce,0x20
.byte 0x10,0x46,0x4a,0x4a,0xf8,0x27,0x31,0xec,0x58,0xc7,0xe8,0x33,0x82,0xe3,0xce,0xbf
.byte 0x85,0xf4,0xdf,0x94,0xce,0x4b,0x09,0xc1,0x94,0x56,0x8a,0xc0,0x13,0x72,0xa7,0xfc
.byte 0x9f,0x84,0x4d,0x73,0xa3,0xca,0x9a,0x61,0x58,0x97,0xa3,0x27,0xfc,0x03,0x98,0x76
.byte 0x23,0x1d,0xc7,0x61,0x03,0x04,0xae,0x56,0xbf,0x38,0x84,0x00,0x40,0xa7,0x0e,0xfd
.byte 0xff,0x52,0xfe,0x03,0x6f,0x95,0x30,0xf1,0x97,0xfb,0xc0,0x85,0x60,0xd6,0x80,0x25
.byte 0xa9,0x63,0xbe,0x03,0x01,0x4e,0x38,0xe2,0xf9,0xa2,0x34,0xff,0xbb,0x3e,0x03,0x44
.byte 0x78,0x00,0x90,0xcb,0x88,0x11,0x3a,0x94,0x65,0xc0,0x7c,0x63,0x87,0xf0,0x3c,0xaf
.byte 0xd6,0x25,0xe4,0x8b,0x38,0x0a,0xac,0x72,0x21,0xd4,0xf8,0x07
// Game title
.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
// Game code
.byte 0x00,0x00,0x00,0x00
// Maker code
.byte 0x00,0x00
// Fixed value
.byte 0x96
// Main unit code
.byte 0x00
// Device type (0x00 retail, 0x80 debug)
.byte 0x00
// Reserved
.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00
// Software version
.byte 0x00
// Complement check
.byte 0x51
// Reserved area
.space 98
start_vector:
// Configure stacks
mov r0, #0x12 // Switch to IRQ Mode
msr cpsr, r0
ldr sp, =_stack_top_irq // Set IRQ stack
mov r0, #0x1f // Switch to System Mode
msr cpsr, r0
ldr sp, =_stack_top // Set user stack
// Configure interrupt handler
mov r0, #0x4000000 // REG_BASE
ldr r1, =handleInterruptARM
str r1, [r0, #-4] // actually storing to 0x03007FFC due to mirroring
// Enable interrupts
mov r1, #1
str r1, [r0, #0x208] // 0x04000208 Interrupt Master Enable
// Jump to user code (switching to Thumb mode)
ldr r3, =main
bx r3
// Small interrupt handler that immediately jumps to a function defined in the
// program (in Thumb) for further processing.
handleInterruptARM:
ldr r0, =handleInterrupt
bx r0

10
targets/gemma-m0.json Normal file
View File

@@ -0,0 +1,10 @@
{
"inherits": ["atsamd21e18a"],
"build-tags": ["gemma_m0"],
"serial": "usb",
"serial-port": ["239a:801e"],
"flash-1200-bps-reset": "true",
"flash-method": "msd",
"msd-volume-name": ["GEMMABOOT"],
"msd-firmware-name": "firmware.uf2"
}

12
targets/gnse.json Normal file
View File

@@ -0,0 +1,12 @@
{
"inherits": [
"stm32wl5x_cm4"
],
"build-tags": [
"gnse"
],
"serial": "uart",
"flash-method": "openocd",
"openocd-interface": "stlink",
"openocd-target": "stm32wlx"
}

3
targets/gobadge.json Normal file
View File

@@ -0,0 +1,3 @@
{
"inherits": ["pybadge"]
}

Some files were not shown because too many files have changed in this diff Show More