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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 57 additions & 46 deletions GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -215,58 +215,69 @@ fmt-check: ## Warn if any source needs reformatting

gen-device: gen-device-avr gen-device-esp gen-device-nrf gen-device-sam gen-device-sifive gen-device-kendryte gen-device-nxp gen-device-rp ## Generate microcontroller-specific sources
ifneq ($(RENESAS), 0)
gen-device: gen-device-renesas
# Renesas is currently unused
#gen-device: gen-device-renesas
endif
ifneq ($(STM32), 0)
gen-device: gen-device-stm32
endif

gen-device-avr:
@if [ ! -e lib/avr/README.md ]; then echo "Submodules have not been downloaded. Please download them using:\n git submodule update --init"; exit 1; fi
$(GO) build -o ./build/gen-device-avr ./tools/gen-device-avr/
./build/gen-device-avr lib/avr/packs/atmega src/device/avr/
./build/gen-device-avr lib/avr/packs/tiny src/device/avr/
@GO111MODULE=off $(GO) fmt ./src/device/avr
build/gen-device-%: ./tools/gen-device-%/*.go
$(GO) build -o $@ ./tools/gen-device-$*/

toUpper = $(shell echo $(1) | tr '[a-z0-9]' '[A-Z0-9]')
toLower = $(shell echo $(1) | tr '[A-Z0-9]' '[a-z0-9]')

define avr_gen_rule
gen-device-avr: $(1).go $(1).s $(1).ld

$(1).go $(1).s $(1).ld &: $(2) build/gen-device-avr
build/gen-device-avr $$< $(1).go $(1).s $(1).ld

endef
define gen_device_software_rule
gen-device-$(1): $(2).go

$(2).go: $(3) build/gen-device-svd
build/gen-device-svd -url=$(4) -interrupts=software $$< $$@

endef
define gen_device_rule
gen-device-$(1): $(2).go $(2).s

$(2).go $(2).s &: $(3) build/gen-device-svd
build/gen-device-svd -url=$(4) -asm=$(2).s $$< $(2).go

endef

avr_gen_group = $(foreach m,$(3),$(call avr_gen_rule,src/device/avr/$(1)$(m),lib/avr/packs/$(2)$(call toUpper,$(m)).atdf))
gen_device_software_group = $(foreach m,$(4),$(call gen_device_software_rule,$(1),src/device/$(1)/$(call toLower,$(m)),$(2)/$(m).svd,$(3)))
gen_device_group = $(foreach m,$(4),$(call gen_device_rule,$(1),src/device/$(1)/$(call toLower,$(m)),$(2)/$(m).svd,$(3)))

DEVICES_ATMEGA = 1280 1284p 2560 328pb 328p 32u4
DEVICES_ATTINY = 1616 85
DEVICES_ESP = esp32 esp32c3 esp32s3
DEVICES_ESP_COMMUNITY = esp8266
DEVICES_NRF = nrf51 nrf52 nrf52833 nrf52840
DEVICES_NXP = MIMXRT1062 MK66F18
DEVICES_SAM = ATSAMD21E18A ATSAMD21G18A ATSAMD51G19A ATSAMD51J19A ATSAMD51J20A ATSAMD51P19A ATSAMD51P20A ATSAME51J19A ATSAME54P20A
DEVICES_SIFIVE = e310x
DEVICES_KENDRYTE = k210
DEVICES_STM32 = stm32f103 stm32f405 stm32f407 stm32f469 stm32f722 stm32g0b1 stm32l4r5 stm32l0x1 stm32l0x2 stm32l4x2 stm32l4x5 stm32l4x6 stm32l552 stm32u585 stm32wl5x_cm4 stm32wle5
DEVICES_RP = rp2040 rp2350

$(eval $(call avr_gen_group,atmega,atmega/ATmega,$(DEVICES_ATMEGA)))
$(eval $(call avr_gen_group,attiny,tiny/ATtiny,$(DEVICES_ATTINY)))
$(eval $(call gen_device_software_group,esp,lib/cmsis-svd/data/Espressif,https://github.com/posborne/cmsis-svd/tree/master/data/Espressif,$(DEVICES_ESP)))
$(eval $(call gen_device_software_group,esp,lib/cmsis-svd/data/Espressif-Community,https://github.com/posborne/cmsis-svd/tree/master/data/Espressif-Community,$(DEVICES_ESP_COMMUNITY)))
$(eval $(call gen_device_group,nrf,lib/nrfx/mdk,https://github.com/NordicSemiconductor/nrfx/tree/master/mdk,$(DEVICES_NRF)))
$(eval $(call gen_device_group,nxp,lib/cmsis-svd/data/NXP,https://github.com/posborne/cmsis-svd/tree/master/data/NXP,MIMXRT1062 MK66F18))
$(eval $(call gen_device_group,sam,lib/cmsis-svd/data/Atmel,https://github.com/posborne/cmsis-svd/tree/master/data/Atmel,$(DEVICES_SAM)))
$(eval $(call gen_device_software_group,sifive,lib/cmsis-svd/data/SiFive-Community,https://github.com/posborne/cmsis-svd/tree/master/data/SiFive-Community,$(DEVICES_SIFIVE)))
$(eval $(call gen_device_software_group,kendryte,lib/cmsis-svd/data/Kendryte-Community,https://github.com/posborne/cmsis-svd/tree/master/data/Kendryte-Community,$(DEVICES_KENDRYTE)))
$(eval $(call gen_device_group,stm32,lib/stm32-svd/svd,https://github.com/tinygo-org/stm32-svd,$(DEVICES_STM32)))
$(eval $(call gen_device_group,rp,lib/cmsis-svd/data/RaspberryPi,https://github.com/posborne/cmsis-svd/tree/master/data/RaspberryPi,$(DEVICES_RP)))

build/gen-device-svd: ./tools/gen-device-svd/*.go
$(GO) build -o $@ ./tools/gen-device-svd/

gen-device-esp: build/gen-device-svd
./build/gen-device-svd -source=https://github.com/posborne/cmsis-svd/tree/master/data/Espressif-Community -interrupts=software lib/cmsis-svd/data/Espressif-Community/ src/device/esp/
./build/gen-device-svd -source=https://github.com/posborne/cmsis-svd/tree/master/data/Espressif -interrupts=software lib/cmsis-svd/data/Espressif/ src/device/esp/
GO111MODULE=off $(GO) fmt ./src/device/esp

gen-device-nrf: build/gen-device-svd
./build/gen-device-svd -source=https://github.com/NordicSemiconductor/nrfx/tree/master/mdk lib/nrfx/mdk/ src/device/nrf/
GO111MODULE=off $(GO) fmt ./src/device/nrf

gen-device-nxp: build/gen-device-svd
./build/gen-device-svd -source=https://github.com/posborne/cmsis-svd/tree/master/data/NXP lib/cmsis-svd/data/NXP/ src/device/nxp/
GO111MODULE=off $(GO) fmt ./src/device/nxp

gen-device-sam: build/gen-device-svd
./build/gen-device-svd -source=https://github.com/posborne/cmsis-svd/tree/master/data/Atmel lib/cmsis-svd/data/Atmel/ src/device/sam/
GO111MODULE=off $(GO) fmt ./src/device/sam

gen-device-sifive: build/gen-device-svd
./build/gen-device-svd -source=https://github.com/posborne/cmsis-svd/tree/master/data/SiFive-Community -interrupts=software lib/cmsis-svd/data/SiFive-Community/ src/device/sifive/
GO111MODULE=off $(GO) fmt ./src/device/sifive

gen-device-kendryte: build/gen-device-svd
./build/gen-device-svd -source=https://github.com/posborne/cmsis-svd/tree/master/data/Kendryte-Community -interrupts=software lib/cmsis-svd/data/Kendryte-Community/ src/device/kendryte/
GO111MODULE=off $(GO) fmt ./src/device/kendryte

gen-device-stm32: build/gen-device-svd
./build/gen-device-svd -source=https://github.com/tinygo-org/stm32-svd lib/stm32-svd/svd src/device/stm32/
GO111MODULE=off $(GO) fmt ./src/device/stm32

gen-device-rp: build/gen-device-svd
./build/gen-device-svd -source=https://github.com/posborne/cmsis-svd/tree/master/data/RaspberryPi lib/cmsis-svd/data/RaspberryPi/ src/device/rp/
GO111MODULE=off $(GO) fmt ./src/device/rp

gen-device-renesas: build/gen-device-svd
./build/gen-device-svd -source=https://github.com/cmsis-svd/cmsis-svd-data/tree/master/data/Renesas lib/cmsis-svd/data/Renesas/ src/device/renesas/
GO111MODULE=off $(GO) fmt ./src/device/renesas

$(LLVM_PROJECTDIR)/llvm:
git clone -b tinygo_20.x --depth=1 https://github.com/tinygo-org/llvm-project $(LLVM_PROJECTDIR)
Expand Down
Empty file added src/device/kendryte/.gitignore
Empty file.
Empty file added src/device/sifive/.gitignore
Empty file.
Empty file added src/device/stm32/.gitignore
Empty file.
1 change: 0 additions & 1 deletion targets/teensy36.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,3 @@
],
"flash-command": "teensy_loader_cli -mmcu=mk66fx1m0 -v -w {hex}"
}

114 changes: 36 additions & 78 deletions tools/gen-device-avr/gen-device-avr.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
package main

import (
"bufio"
"bytes"
"encoding/xml"
"fmt"
"go/format"
"html/template"
"math/bits"
"os"
"path/filepath"
"runtime"
"sort"
"strconv"
"strings"
"sync"
)

type AVRToolsDeviceFile struct {
Expand Down Expand Up @@ -398,14 +397,8 @@ func readATDF(path string) (*Device, error) {
}, nil
}

func writeGo(outdir string, device *Device) error {
func writeGo(dst string, device *Device) error {
// The Go module for this device.
outf, err := os.Create(outdir + "/" + device.metadata["nameLower"].(string) + ".go")
if err != nil {
return err
}
defer outf.Close()
w := bufio.NewWriter(outf)

maxInterruptNum := 0
for _, intr := range device.interrupts {
Expand Down Expand Up @@ -484,9 +477,11 @@ type {{.Name}}_Type struct {
{{end}}
{{end}}
`))
err = t.Execute(w, map[string]interface{}{
var buf bytes.Buffer
w := &buf
err := t.Execute(w, map[string]interface{}{
"metadata": device.metadata,
"pkgName": filepath.Base(strings.TrimRight(outdir, "/")),
"pkgName": filepath.Base(filepath.Dir(dst)),
"interrupts": device.interrupts,
"interruptMax": maxInterruptNum,
"instances": device.instances,
Expand Down Expand Up @@ -559,12 +554,20 @@ type {{.Name}}_Type struct {
}
fmt.Fprintf(w, ")\n")
}
return w.Flush()

// Format the source.
formatted, err := format.Source(buf.Bytes())
if err != nil {
return err
}

// Save the file.
return os.WriteFile(dst, formatted, 0666)
}

func writeAsm(outdir string, device *Device) error {
func writeAsm(dst string, device *Device) error {
// The interrupt vector, which is hard to write directly in Go.
out, err := os.Create(outdir + "/" + device.metadata["nameLower"].(string) + ".s")
out, err := os.Create(dst)
if err != nil {
return err
}
Expand Down Expand Up @@ -628,9 +631,9 @@ __vector_default:
return nil
}

func writeLD(outdir string, device *Device) error {
func writeLD(dst string, device *Device) error {
// Variables for the linker script.
out, err := os.Create(outdir + "/" + device.metadata["nameLower"].(string) + ".ld")
out, err := os.Create(dst)
if err != nil {
return err
}
Expand All @@ -649,73 +652,28 @@ __num_isrs = {{.numInterrupts}};
return t.Execute(out, device.metadata)
}

func processFile(filepath, outdir string) error {
device, err := readATDF(filepath)
func main() {
src := os.Args[1]
dstGo := os.Args[2]
dstASM := os.Args[3]
dstLD := os.Args[4]

device, err := readATDF(src)
if err != nil {
return err
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
err = writeGo(outdir, device)
err = writeGo(dstGo, device)
if err != nil {
return err
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
err = writeAsm(outdir, device)
err = writeAsm(dstASM, device)
if err != nil {
return err
}
return writeLD(outdir, device)
}

func generate(indir, outdir string) error {
// Read list of ATDF files to process.
matches, err := filepath.Glob(indir + "/*.atdf")
if err != nil {
return err
}

// Start worker goroutines.
var wg sync.WaitGroup
workChan := make(chan string)
errChan := make(chan error, 1)
for i := 0; i < runtime.NumCPU(); i++ {
go func() {
for filepath := range workChan {
err := processFile(filepath, outdir)
wg.Done()
if err != nil {
// Store error to errChan if no error was stored before.
select {
case errChan <- err:
default:
}
}
}
}()
}

// Submit all jobs to the goroutines.
wg.Add(len(matches))
for _, filepath := range matches {
fmt.Println(filepath)
workChan <- filepath
}
close(workChan)

// Wait until all workers have finished.
wg.Wait()

// Check for an error.
select {
case err := <-errChan:
return err
default:
return nil
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}

func main() {
indir := os.Args[1] // directory with register descriptor files (*.atdf)
outdir := os.Args[2] // output directory
err := generate(indir, outdir)
err = writeLD(dstLD, device)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
Expand Down
Loading
Loading