diff options
-rw-r--r-- | compileopts/options.go | 1 | ||||
-rw-r--r-- | go.mod | 2 | ||||
-rw-r--r-- | go.sum | 10 | ||||
-rw-r--r-- | main.go | 19 | ||||
-rw-r--r-- | monitor.go | 101 |
5 files changed, 125 insertions, 8 deletions
diff --git a/compileopts/options.go b/compileopts/options.go index 242884abb..d70c4c051 100644 --- a/compileopts/options.go +++ b/compileopts/options.go @@ -50,6 +50,7 @@ type Options struct { LLVMFeatures string Directory string PrintJSON bool + Monitor bool } // Verify performs a validation on the given options, raising an error if options are not valid. @@ -12,6 +12,7 @@ require ( github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf github.com/marcinbor85/gohex v0.0.0-20200531091804-343a4b548892 github.com/mattn/go-colorable v0.1.8 + github.com/mattn/go-tty v0.0.4 go.bug.st/serial v1.3.5 golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 golang.org/x/tools v0.1.11 @@ -28,5 +29,4 @@ require ( github.com/josharian/intern v1.0.0 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-isatty v0.0.12 // indirect - golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect ) @@ -30,10 +30,16 @@ github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0 github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/marcinbor85/gohex v0.0.0-20200531091804-343a4b548892 h1:6J+qramlHVLmiBOgRiBOnQkno8uprqG6YFFQTt6uYIw= github.com/marcinbor85/gohex v0.0.0-20200531091804-343a4b548892/go.mod h1:Pb6XcsXyropB9LNHhnqaknG/vEwYztLkQzVCHv8sQ3M= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-tty v0.0.4 h1:NVikla9X8MN0SQAqCYzpGyXv0jY7MNl3HOWD2dkle7E= +github.com/mattn/go-tty v0.0.4/go.mod h1:u5GGXBtZU6RQoKV8gY5W6UhMudbR5vXnUe7j3pxse28= github.com/orisano/pixelmatch v0.0.0-20210112091706-4fa4c7ba91d5 h1:1SoBaSPudixRecmlHXb/GxmaD3fLMtHIDN13QujwQuc= github.com/orisano/pixelmatch v0.0.0-20210112091706-4fa4c7ba91d5/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -41,7 +47,9 @@ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5Cc go.bug.st/serial v1.3.5 h1:k50SqGZCnHZ2MiBQgzccXWG+kd/XpOs1jUljpDDKzaE= go.bug.st/serial v1.3.5/go.mod h1:z8CesKorE90Qr/oRSJiEuvzYRKol9r/anJZEb5kt304= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -423,7 +423,6 @@ func Flash(pkgName, port string, options *compileopts.Options) error { if err != nil { return &commandError{"failed to flash", result.Binary, err} } - return nil case "msd": switch fileExt { case ".uf2": @@ -431,13 +430,11 @@ func Flash(pkgName, port string, options *compileopts.Options) error { if err != nil { return &commandError{"failed to flash", result.Binary, err} } - return nil case ".hex": err := flashHexUsingMSD(config.Target.FlashVolume, result.Binary, config.Options) if err != nil { return &commandError{"failed to flash", result.Binary, err} } - return nil default: return errors.New("mass storage device flashing currently only supports uf2 and hex") } @@ -458,7 +455,6 @@ func Flash(pkgName, port string, options *compileopts.Options) error { if err != nil { return &commandError{"failed to flash", result.Binary, err} } - return nil case "bmp": gdb, err := config.Target.LookupGDB() if err != nil { @@ -477,10 +473,13 @@ func Flash(pkgName, port string, options *compileopts.Options) error { if err != nil { return &commandError{"failed to flash", result.Binary, err} } - return nil default: return fmt.Errorf("unknown flash method: %s", flashMethod) } + if options.Monitor { + return Monitor("", options) + } + return nil }) } @@ -1058,7 +1057,9 @@ func getDefaultPort(portFlag string, usbInterfaces []string) (port string, err e } if len(portCandidates) == 0 { - if len(ports) == 1 { + if len(usbInterfaces) > 0 { + return "", errors.New("unable to search for a default USB device - use -port flag, available ports are " + strings.Join(ports, ", ")) + } else if len(ports) == 1 { return ports[0], nil } else { return "", errors.New("multiple serial ports available - use -port flag, available ports are " + strings.Join(ports, ", ")) @@ -1123,6 +1124,7 @@ func usage(command string) { fmt.Fprintln(os.Stderr, " flash: compile and flash to the device") fmt.Fprintln(os.Stderr, " gdb: run/flash and immediately enter GDB") fmt.Fprintln(os.Stderr, " lldb: run/flash and immediately enter LLDB") + fmt.Fprintln(os.Stderr, " monitor: open communication port") fmt.Fprintln(os.Stderr, " env: list environment variables used during build") fmt.Fprintln(os.Stderr, " list: run go list using the TinyGo root") fmt.Fprintln(os.Stderr, " clean: empty cache directory ("+goenv.Get("GOCACHE")+")") @@ -1339,6 +1341,7 @@ func main() { wasmAbi := flag.String("wasm-abi", "", "WebAssembly ABI conventions: js (no i64 params) or generic") llvmFeatures := flag.String("llvm-features", "", "comma separated LLVM features to enable") cpuprofile := flag.String("cpuprofile", "", "cpuprofile output") + monitor := flag.Bool("monitor", false, "enable serial monitor") var flagJSON, flagDeps, flagTest bool if command == "help" || command == "list" || command == "info" || command == "build" { @@ -1428,6 +1431,7 @@ func main() { OpenOCDCommands: ocdCommands, LLVMFeatures: *llvmFeatures, PrintJSON: flagJSON, + Monitor: *monitor, } if *printCommands { options.PrintCommands = printCommand @@ -1618,6 +1622,9 @@ func main() { fmt.Println("FAIL") os.Exit(1) } + case "monitor": + err := Monitor(*port, options) + handleCompilerError(err) case "targets": dir := filepath.Join(goenv.Get("TINYGOROOT"), "targets") entries, err := ioutil.ReadDir(dir) diff --git a/monitor.go b/monitor.go new file mode 100644 index 000000000..ec433bb7a --- /dev/null +++ b/monitor.go @@ -0,0 +1,101 @@ +package main + +import ( + "fmt" + "os" + "os/signal" + "time" + + "github.com/mattn/go-tty" + "github.com/tinygo-org/tinygo/builder" + "github.com/tinygo-org/tinygo/compileopts" + "go.bug.st/serial" +) + +// Monitor connects to the given port and reads/writes the serial port. +func Monitor(port string, options *compileopts.Options) error { + config, err := builder.NewConfig(options) + if err != nil { + return err + } + + wait := 300 + for i := 0; i <= wait; i++ { + port, err = getDefaultPort(port, config.Target.SerialPort) + if err != nil { + if i < wait { + time.Sleep(10 * time.Millisecond) + continue + } + return err + } + break + } + + wait = 300 + var p serial.Port + for i := 0; i <= wait; i++ { + p, err = serial.Open(port, &serial.Mode{}) + if err != nil { + if i < wait { + time.Sleep(10 * time.Millisecond) + continue + } + return err + } + break + } + defer p.Close() + + tty, err := tty.Open() + if err != nil { + return err + } + defer tty.Close() + + sig := make(chan os.Signal, 1) + signal.Notify(sig, os.Interrupt) + defer signal.Stop(sig) + + go func() { + <-sig + tty.Close() + os.Exit(0) + }() + + fmt.Printf("Connected to %s. Press Ctrl-C to exit.\n", port) + + errCh := make(chan error, 1) + + go func() { + buf := make([]byte, 100*1024) + for { + n, err := p.Read(buf) + if err != nil { + errCh <- fmt.Errorf("read error: %w", err) + return + } + + if n == 0 { + continue + } + fmt.Printf("%v", string(buf[:n])) + } + }() + + go func() { + for { + r, err := tty.ReadRune() + if err != nil { + errCh <- err + return + } + if r == 0 { + continue + } + p.Write([]byte(string(r))) + } + }() + + return <-errCh +} |