diff --git a/GNUmakefile b/GNUmakefile index ef6af6f2d3..d9a95b00a7 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -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) diff --git a/src/device/kendryte/.gitignore b/src/device/kendryte/.gitignore new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/device/sifive/.gitignore b/src/device/sifive/.gitignore new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/device/stm32/.gitignore b/src/device/stm32/.gitignore new file mode 100644 index 0000000000..e69de29bb2 diff --git a/targets/teensy36.json b/targets/teensy36.json index 253e397043..1d6f9c673a 100644 --- a/targets/teensy36.json +++ b/targets/teensy36.json @@ -9,4 +9,3 @@ ], "flash-command": "teensy_loader_cli -mmcu=mk66fx1m0 -v -w {hex}" } - diff --git a/tools/gen-device-avr/gen-device-avr.go b/tools/gen-device-avr/gen-device-avr.go index de32e3ed95..0fc01d04a4 100755 --- a/tools/gen-device-avr/gen-device-avr.go +++ b/tools/gen-device-avr/gen-device-avr.go @@ -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 { @@ -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 { @@ -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, @@ -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 } @@ -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 } @@ -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) diff --git a/tools/gen-device-svd/gen-device-svd.go b/tools/gen-device-svd/gen-device-svd.go index ef9dedff97..5b5d73e211 100755 --- a/tools/gen-device-svd/gen-device-svd.go +++ b/tools/gen-device-svd/gen-device-svd.go @@ -2,11 +2,11 @@ package main import ( "bufio" + "bytes" "encoding/xml" - "errors" "flag" "fmt" - "io/fs" + "go/format" "os" "path/filepath" "regexp" @@ -1215,14 +1215,7 @@ func parseRegister(groupName string, regEl *SVDRegister, baseAddress uint64, bit } // The Go module for this device. -func writeGo(outdir string, device *Device, interruptSystem string) error { - outf, err := os.Create(filepath.Join(outdir, device.Metadata.NameLower+".go")) - if err != nil { - return err - } - defer outf.Close() - w := bufio.NewWriter(outf) - +func writeGo(dst string, device *Device, interruptSystem string) error { maxInterruptValue := 0 for _, intr := range device.Interrupts { if intr.Value > maxInterruptValue { @@ -1326,10 +1319,12 @@ var ( ) `)) - pkgName := filepath.Base(strings.TrimRight(outdir, "/")) + pkgName := filepath.Base(filepath.Dir(dst)) tweakDevice(device, pkgName) - err = t.Execute(w, map[string]interface{}{ + var buf bytes.Buffer + w := &buf + err := t.Execute(w, map[string]interface{}{ "device": device, "pkgName": pkgName, "interruptMax": maxInterruptValue, @@ -1594,10 +1589,17 @@ var ( w.WriteString(")\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 writeGoRegisterConstants(w *bufio.Writer, register *PeripheralField, name string) { +func writeGoRegisterConstants(w *bytes.Buffer, register *PeripheralField, name string) { w.WriteString("\n\t// " + name) if register.Description != "" { if isMultiline(register.Description) { @@ -1619,7 +1621,7 @@ func writeGoRegisterConstants(w *bufio.Writer, register *PeripheralField, name s } } -func writeGoRegisterBitfieldType(w *bufio.Writer, register *PeripheralField, peripheralName, registerName string) { +func writeGoRegisterBitfieldType(w *bytes.Buffer, register *PeripheralField, peripheralName, registerName string) { if len(register.Bitfields) == 0 { return } @@ -1692,8 +1694,8 @@ func writeGoRegisterBitfieldType(w *bufio.Writer, register *PeripheralField, per } // The interrupt vector, which is hard to write directly in Go. -func writeAsm(outdir string, device *Device) error { - outf, err := os.Create(filepath.Join(outdir, device.Metadata.NameLower+".s")) +func writeAsm(dst string, device *Device) error { + outf, err := os.Create(dst) if err != nil { return err } @@ -1796,58 +1798,33 @@ __isr_vector: return w.Flush() } -func generate(indir, outdir, sourceURL, interruptSystem string) error { - if _, err := os.Stat(indir); errors.Is(err, fs.ErrNotExist) { - fmt.Fprintln(os.Stderr, "cannot find input directory:", indir) - os.Exit(1) - } - os.MkdirAll(outdir, 0777) - - infiles, err := filepath.Glob(filepath.Join(indir, "*.svd")) - if err != nil { - fmt.Fprintln(os.Stderr, "could not read .svd files:", err) - os.Exit(1) - } - sort.Strings(infiles) - for _, infile := range infiles { - fmt.Println(infile) - device, err := readSVD(infile, sourceURL) - if err != nil { - return fmt.Errorf("failed to read: %w", err) - } - err = writeGo(outdir, device, interruptSystem) - if err != nil { - return fmt.Errorf("failed to write Go file: %w", err) - } - switch interruptSystem { - case "software": - // Nothing to do. - case "hardware": - err = writeAsm(outdir, device) - if err != nil { - return fmt.Errorf("failed to write assembly file: %w", err) - } - default: - return fmt.Errorf("unknown interrupt system: %s", interruptSystem) - } - } - return nil -} - func main() { - sourceURL := flag.String("source", "", "source SVD file") + sourceURL := flag.String("url", "", "URL of source SVD repository") interruptSystem := flag.String("interrupts", "hardware", "interrupt system in use (software, hardware)") + asmDst := flag.String("asm", "", "destination path for assembly") flag.Parse() if flag.NArg() != 2 { - fmt.Fprintln(os.Stderr, "provide exactly two arguments: input directory (with .svd files) and output directory for generated files") + fmt.Fprintln(os.Stderr, "provide exactly two arguments: input path (.svd) and output path (.go)") flag.PrintDefaults() return } - indir := flag.Arg(0) - outdir := flag.Arg(1) - err := generate(indir, outdir, *sourceURL, *interruptSystem) + src := flag.Arg(0) + dst := flag.Arg(1) + device, err := readSVD(src, *sourceURL) + if err != nil { + fmt.Fprintf(os.Stderr, "failed to read: %s\n", err) + os.Exit(1) + } + err = writeGo(dst, device, *interruptSystem) if err != nil { - fmt.Fprintln(os.Stderr, err) + fmt.Fprintf(os.Stderr, "failed to write Go file: %s\n", err) os.Exit(1) } + if asm := *asmDst; asm != "" { + err = writeAsm(asm, device) + if err != nil { + fmt.Fprintf(os.Stderr, "failed to write assembly file: %s\n", err) + os.Exit(1) + } + } }