diff --git a/main.go b/main.go index 512cbbc8..ded05ac6 100644 --- a/main.go +++ b/main.go @@ -16,9 +16,7 @@ import ( ) // Helper function for Compiler object. -func Compile(pkgName, outpath, target string, printIR, dumpSSA bool) error { - spec, err := LoadTarget(target) - +func Compile(pkgName, outpath string, spec *TargetSpec, printIR, dumpSSA bool, action func(string) error) error { c, err := NewCompiler(pkgName, spec.Triple, dumpSSA) if err != nil { return err @@ -98,7 +96,17 @@ func Compile(pkgName, outpath, target string, printIR, dumpSSA bool) error { return err } } + return action(tmppath) + } +} +func Build(pkgName, outpath, target string, printIR, dumpSSA bool) error { + spec, err := LoadTarget(target) + if err != nil { + return err + } + + return Compile(pkgName, outpath, spec, printIR, dumpSSA, func(tmppath string) error { if err := os.Rename(tmppath, outpath); err != nil { // Moving failed. Do a file copy. inf, err := os.Open(tmppath) @@ -123,7 +131,31 @@ func Compile(pkgName, outpath, target string, printIR, dumpSSA bool) error { // Move was successful. return nil } + }) +} + +func Flash(pkgName, target, port string, printIR, dumpSSA bool) error { + spec, err := LoadTarget(target) + if err != nil { + return err } + + return Compile(pkgName, ".hex", spec, printIR, dumpSSA, func(tmppath string) error { + // Create the command. + flashCmd := spec.Flasher + parts := strings.Split(flashCmd, " ") // TODO: this should be a real shell split + for i, part := range parts { + part = strings.Replace(part, "{hex}", tmppath, -1) + part = strings.Replace(part, "{port}", port, -1) + parts[i] = part + } + + // Execute the command. + cmd := exec.Command(parts[0], parts[1:]...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + return cmd.Run() + }) } // Run the specified package directly (using JIT or interpretation). @@ -160,6 +192,7 @@ func usage() { fmt.Fprintf(os.Stderr, "usage: %s command [-printir] [-target=] -o \n", os.Args[0]) fmt.Fprintln(os.Stderr, "\ncommands:") fmt.Fprintln(os.Stderr, " build: compile packages and dependencies") + fmt.Fprintln(os.Stderr, " flash: compile and flash to the device") fmt.Fprintln(os.Stderr, " help: print this help text") fmt.Fprintln(os.Stderr, " run: run package in an interpreter") fmt.Fprintln(os.Stderr, "\nflags:") @@ -171,6 +204,7 @@ func main() { printIR := flag.Bool("printir", false, "print LLVM IR") dumpSSA := flag.Bool("dumpssa", false, "dump internal Go SSA") target := flag.String("target", llvm.DefaultTargetTriple(), "LLVM target") + port := flag.String("port", "/dev/ttyACM0", "flash port") if len(os.Args) < 2 { fmt.Fprintln(os.Stderr, "No command-line arguments supplied.") @@ -195,7 +229,18 @@ func main() { usage() os.Exit(1) } - err := Compile(flag.Arg(0), *outpath, *target, *printIR, *dumpSSA) + err := Build(flag.Arg(0), *outpath, *target, *printIR, *dumpSSA) + if err != nil { + fmt.Fprintln(os.Stderr, "error:", err) + os.Exit(1) + } + case "flash": + if *outpath != "" { + fmt.Fprintln(os.Stderr, "Output cannot be specified with the flash command.") + usage() + os.Exit(1) + } + err := Flash(flag.Arg(0), *target, *port, *printIR, *dumpSSA) if err != nil { fmt.Fprintln(os.Stderr, "error:", err) os.Exit(1) diff --git a/target.go b/target.go index 1240fea7..5a1b3d7c 100644 --- a/target.go +++ b/target.go @@ -19,6 +19,7 @@ type TargetSpec struct { Linker string `json:"linker"` PreLinkArgs []string `json:"pre-link-args"` Objcopy string `json:"objcopy"` + Flasher string `json:"flash"` } // Load a target specification diff --git a/targets/arduino.json b/targets/arduino.json index 2be51759..39d5f44f 100644 --- a/targets/arduino.json +++ b/targets/arduino.json @@ -3,5 +3,6 @@ "build-tags": ["avr", "avr8", "atmega", "atmega328p", "js", "wasm"], "linker": "avr-gcc", "pre-link-args": ["-nostdlib", "-T", "targets/avr.ld", "-Wl,--gc-sections", "targets/avr.S"], - "objcopy": "avr-objcopy" + "objcopy": "avr-objcopy", + "flash": "avrdude -c arduino -p atmega328p -P {port} -U flash:w:{hex}" } diff --git a/targets/pca10040.json b/targets/pca10040.json index 6ec3d33c..d8215d6b 100644 --- a/targets/pca10040.json +++ b/targets/pca10040.json @@ -3,5 +3,6 @@ "build-tags": ["nrf", "nrf52", "nrf52832", "js", "wasm"], "linker": "arm-none-eabi-gcc", "pre-link-args": ["-nostdlib", "-nostartfiles", "-mcpu=cortex-m4", "-mthumb", "-T", "targets/arm.ld", "-Wl,--gc-sections", "-fno-exceptions", "-fno-unwind-tables", "-ffunction-sections", "-fdata-sections", "-Os", "-DNRF52832_XXAA", "-D__STARTUP_CLEAR_BSS", "-Ilib/CMSIS/CMSIS/Include", "lib/nrfx/mdk/gcc_startup_nrf51.S", "lib/nrfx/mdk/system_nrf52.c"], - "objcopy": "arm-none-eabi-objcopy" + "objcopy": "arm-none-eabi-objcopy", + "flash": "nrfjprog -f nrf52 --sectorerase --program {hex} --reset" }