main: add -info option to tinygo monitor
Этот коммит содержится в:
родитель
938ce22307
коммит
24ae6fdf29
2 изменённых файлов: 111 добавлений и 29 удалений
47
main.go
47
main.go
|
@ -1436,6 +1436,7 @@ func main() {
|
||||||
llvmFeatures := flag.String("llvm-features", "", "comma separated LLVM features to enable")
|
llvmFeatures := flag.String("llvm-features", "", "comma separated LLVM features to enable")
|
||||||
cpuprofile := flag.String("cpuprofile", "", "cpuprofile output")
|
cpuprofile := flag.String("cpuprofile", "", "cpuprofile output")
|
||||||
monitor := flag.Bool("monitor", false, "enable serial monitor")
|
monitor := flag.Bool("monitor", false, "enable serial monitor")
|
||||||
|
info := flag.Bool("info", false, "print information")
|
||||||
baudrate := flag.Int("baudrate", 115200, "baudrate of serial monitor")
|
baudrate := flag.Int("baudrate", 115200, "baudrate of serial monitor")
|
||||||
|
|
||||||
// Internal flags, that are only intended for TinyGo development.
|
// Internal flags, that are only intended for TinyGo development.
|
||||||
|
@ -1731,41 +1732,29 @@ func main() {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
case "monitor":
|
case "monitor":
|
||||||
err := Monitor("", *port, options)
|
if *info {
|
||||||
handleCompilerError(err)
|
serialPortInfo, err := ListSerialPorts()
|
||||||
|
handleCompilerError(err)
|
||||||
|
for _, s := range serialPortInfo {
|
||||||
|
fmt.Printf("%s %4s %4s %s\n", s.Name, s.VID, s.PID, s.Target)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err := Monitor("", *port, options)
|
||||||
|
handleCompilerError(err)
|
||||||
|
}
|
||||||
case "targets":
|
case "targets":
|
||||||
dir := filepath.Join(goenv.Get("TINYGOROOT"), "targets")
|
specs, err := GetTargetSpecs()
|
||||||
entries, err := os.ReadDir(dir)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintln(os.Stderr, "could not list targets:", err)
|
fmt.Fprintln(os.Stderr, "could not list targets:", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for _, entry := range entries {
|
names := []string{}
|
||||||
entryInfo, err := entry.Info()
|
for key := range specs {
|
||||||
if err != nil {
|
names = append(names, key)
|
||||||
fmt.Fprintln(os.Stderr, "could not get entry info:", err)
|
}
|
||||||
os.Exit(1)
|
sort.Strings(names)
|
||||||
return
|
for _, name := range names {
|
||||||
}
|
|
||||||
if !entryInfo.Mode().IsRegular() || !strings.HasSuffix(entry.Name(), ".json") {
|
|
||||||
// Only inspect JSON files.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
path := filepath.Join(dir, entry.Name())
|
|
||||||
spec, err := compileopts.LoadTarget(&compileopts.Options{Target: path})
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintln(os.Stderr, "could not list target:", err)
|
|
||||||
os.Exit(1)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if spec.FlashMethod == "" && spec.FlashCommand == "" && spec.Emulator == "" {
|
|
||||||
// This doesn't look like a regular target file, but rather like
|
|
||||||
// a parent target (such as targets/cortex-m.json).
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
name := entry.Name()
|
|
||||||
name = name[:len(name)-5]
|
|
||||||
fmt.Println(name)
|
fmt.Println(name)
|
||||||
}
|
}
|
||||||
case "info":
|
case "info":
|
||||||
|
|
93
monitor.go
93
monitor.go
|
@ -11,14 +11,19 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/mattn/go-tty"
|
"github.com/mattn/go-tty"
|
||||||
"github.com/tinygo-org/tinygo/builder"
|
"github.com/tinygo-org/tinygo/builder"
|
||||||
"github.com/tinygo-org/tinygo/compileopts"
|
"github.com/tinygo-org/tinygo/compileopts"
|
||||||
|
"github.com/tinygo-org/tinygo/goenv"
|
||||||
|
|
||||||
"go.bug.st/serial"
|
"go.bug.st/serial"
|
||||||
|
"go.bug.st/serial/enumerator"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Monitor connects to the given port and reads/writes the serial port.
|
// Monitor connects to the given port and reads/writes the serial port.
|
||||||
|
@ -128,6 +133,94 @@ func Monitor(executable, port string, options *compileopts.Options) error {
|
||||||
return <-errCh
|
return <-errCh
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SerialPortInfo is a structure that holds information about the port and its
|
||||||
|
// associated TargetSpec.
|
||||||
|
type SerialPortInfo struct {
|
||||||
|
Name string
|
||||||
|
IsUSB bool
|
||||||
|
VID string
|
||||||
|
PID string
|
||||||
|
Target string
|
||||||
|
Spec *compileopts.TargetSpec
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListSerialPort returns serial port information and any detected TinyGo
|
||||||
|
// target
|
||||||
|
func ListSerialPorts() ([]SerialPortInfo, error) {
|
||||||
|
maps, err := GetTargetSpecs()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
portsList, err := enumerator.GetDetailedPortsList()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
serialPortInfo := []SerialPortInfo{}
|
||||||
|
for _, p := range portsList {
|
||||||
|
info := SerialPortInfo{
|
||||||
|
Name: p.Name,
|
||||||
|
IsUSB: p.IsUSB,
|
||||||
|
VID: p.VID,
|
||||||
|
PID: p.PID,
|
||||||
|
}
|
||||||
|
vid := strings.ToLower(p.VID)
|
||||||
|
pid := strings.ToLower(p.PID)
|
||||||
|
for k, v := range maps {
|
||||||
|
usbInterfaces := v.SerialPort
|
||||||
|
for _, s := range usbInterfaces {
|
||||||
|
parts := strings.Split(s, ":")
|
||||||
|
if len(parts) != 2 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if vid == strings.ToLower(parts[0]) && pid == strings.ToLower(parts[1]) {
|
||||||
|
info.Target = k
|
||||||
|
info.Spec = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
serialPortInfo = append(serialPortInfo, info)
|
||||||
|
}
|
||||||
|
|
||||||
|
return serialPortInfo, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetTargetSpecs() (map[string]*compileopts.TargetSpec, error) {
|
||||||
|
dir := filepath.Join(goenv.Get("TINYGOROOT"), "targets")
|
||||||
|
entries, err := os.ReadDir(dir)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("could not list targets: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
maps := map[string]*compileopts.TargetSpec{}
|
||||||
|
for _, entry := range entries {
|
||||||
|
entryInfo, err := entry.Info()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("could not get entry info: %w", err)
|
||||||
|
}
|
||||||
|
if !entryInfo.Mode().IsRegular() || !strings.HasSuffix(entry.Name(), ".json") {
|
||||||
|
// Only inspect JSON files.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
path := filepath.Join(dir, entry.Name())
|
||||||
|
spec, err := compileopts.LoadTarget(&compileopts.Options{Target: path})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("cnuld not list target: %w", err)
|
||||||
|
}
|
||||||
|
if spec.FlashMethod == "" && spec.FlashCommand == "" && spec.Emulator == "" {
|
||||||
|
// This doesn't look like a regular target file, but rather like
|
||||||
|
// a parent target (such as targets/cortex-m.json).
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
name := entry.Name()
|
||||||
|
name = name[:len(name)-5]
|
||||||
|
//fmt.Println(name)
|
||||||
|
maps[name] = spec
|
||||||
|
}
|
||||||
|
return maps, nil
|
||||||
|
}
|
||||||
|
|
||||||
var addressMatch = regexp.MustCompile(`^panic: runtime error at 0x([0-9a-f]+): `)
|
var addressMatch = regexp.MustCompile(`^panic: runtime error at 0x([0-9a-f]+): `)
|
||||||
|
|
||||||
// Extract the address from the "panic: runtime error at" message.
|
// Extract the address from the "panic: runtime error at" message.
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче