targets: refactor flash/gdb target configuration

Instead of specifying explicit commands, most of these commands have
been replaced by more specific properties.

This is work that will be necessary for an eventual -programmer flag to
the compiler, with which it is possible to select which programmer to
use to flash or debug a chip. That's not very useful for boards that
already include a programmer or bootloader for that purpose, but is very
useful for novel boards or single-purpose boards that are not already
included in TinyGo.
This commit is contained in:
Ayke van Laethem
2019-10-14 00:29:52 +02:00
committed by Ron Evans
parent 52bac4d75b
commit 2a71aa90bc
23 changed files with 208 additions and 112 deletions
+91 -36
View File
@@ -403,24 +403,34 @@ func Flash(pkgName, target, port string, config *BuildConfig) error {
// determine the type of file to compile
var fileExt string
switch {
case strings.Contains(spec.Flasher, "{hex}"):
switch spec.FlashMethod {
case "command", "":
switch {
case strings.Contains(spec.FlashCommand, "{hex}"):
fileExt = ".hex"
case strings.Contains(spec.FlashCommand, "{elf}"):
fileExt = ".elf"
case strings.Contains(spec.FlashCommand, "{bin}"):
fileExt = ".bin"
case strings.Contains(spec.FlashCommand, "{uf2}"):
fileExt = ".uf2"
default:
return errors.New("invalid target file - did you forget the {hex} token in the 'flash-command' section?")
}
case "msd":
if spec.FlashFilename == "" {
return errors.New("invalid target file: flash-method was set to \"msd\" but no msd-firmware-name was set")
}
fileExt = filepath.Ext(spec.FlashFilename)
case "openocd":
fileExt = ".hex"
case strings.Contains(spec.Flasher, "{elf}"):
fileExt = ".elf"
case strings.Contains(spec.Flasher, "{bin}"):
fileExt = ".bin"
case strings.Contains(spec.Flasher, "{uf2}"):
fileExt = ".uf2"
case "native":
return errors.New("unknown flash method \"native\" - did you miss a -target flag?")
default:
return errors.New("invalid target file - did you forget the {hex} token in the 'flash' section?")
return errors.New("unknown flash method: " + spec.FlashMethod)
}
return Compile(pkgName, fileExt, spec, config, func(tmppath string) error {
if spec.Flasher == "" {
return errors.New("no flash command specified - did you miss a -target flag?")
}
// do we need port reset to put MCU into bootloader mode?
if spec.PortReset == "true" {
err := touchSerialPortAt1200bps(port)
@@ -432,7 +442,25 @@ func Flash(pkgName, target, port string, config *BuildConfig) error {
}
// this flashing method copies the binary data to a Mass Storage Device (msd)
if spec.FlashMethod == "msd" {
switch spec.FlashMethod {
case "", "command":
// Create the command.
flashCmd := spec.FlashCommand
fileToken := "{" + fileExt[1:] + "}"
flashCmd = strings.Replace(flashCmd, fileToken, tmppath, -1)
flashCmd = strings.Replace(flashCmd, "{port}", port, -1)
// Execute the command.
cmd := exec.Command("/bin/sh", "-c", flashCmd)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Dir = sourceDir()
err := cmd.Run()
if err != nil {
return &commandError{"failed to flash", tmppath, err}
}
return nil
case "msd":
switch fileExt {
case ".uf2":
err := flashUF2UsingMSD(spec.FlashVolume, tmppath)
@@ -449,24 +477,23 @@ func Flash(pkgName, target, port string, config *BuildConfig) error {
default:
return errors.New("mass storage device flashing currently only supports uf2 and hex")
}
case "openocd":
args, err := spec.OpenOCDConfiguration()
if err != nil {
return err
}
args = append(args, "-c", "program "+tmppath+" reset exit")
cmd := exec.Command("openocd", args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err = cmd.Run()
if err != nil {
return &commandError{"failed to flash", tmppath, err}
}
return nil
default:
return fmt.Errorf("unknown flash method: %s", spec.FlashMethod)
}
// Create the command.
flashCmd := spec.Flasher
fileToken := "{" + fileExt[1:] + "}"
flashCmd = strings.Replace(flashCmd, fileToken, tmppath, -1)
flashCmd = strings.Replace(flashCmd, "{port}", port, -1)
// Execute the command.
cmd := exec.Command("/bin/sh", "-c", flashCmd)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Dir = sourceDir()
err := cmd.Run()
if err != nil {
return &commandError{"failed to flash", tmppath, err}
}
return nil
})
}
@@ -485,9 +512,33 @@ func FlashGDB(pkgName, target, port string, ocdOutput bool, config *BuildConfig)
}
return Compile(pkgName, "", spec, config, func(tmppath string) error {
if len(spec.OCDDaemon) != 0 {
// Find a good way to run GDB.
gdbInterface := spec.FlashMethod
switch gdbInterface {
case "msd", "command", "":
if gdbInterface == "" {
gdbInterface = "command"
}
if spec.OpenOCDInterface != "" && spec.OpenOCDTarget != "" {
gdbInterface = "openocd"
}
}
// Run the GDB server, if necessary.
var gdbCommands []string
switch gdbInterface {
case "native":
// Run GDB directly.
gdbCommands = append(gdbCommands, "run")
case "openocd":
gdbCommands = append(gdbCommands, "target remote :3333", "monitor halt", "load", "monitor reset", "c")
// We need a separate debugging daemon for on-chip debugging.
daemon := exec.Command(spec.OCDDaemon[0], spec.OCDDaemon[1:]...)
args, err := spec.OpenOCDConfiguration()
if err != nil {
return err
}
daemon := exec.Command("openocd", args...)
if ocdOutput {
// Make it clear which output is from the daemon.
w := &ColorWriter{
@@ -512,6 +563,10 @@ func FlashGDB(pkgName, target, port string, ocdOutput bool, config *BuildConfig)
// Maybe we should send a .Kill() after x seconds?
daemon.Wait()
}()
case "msd":
return errors.New("gdb is not supported for drag-and-drop programmable devices")
default:
return fmt.Errorf("gdb is not supported with interface %#v", gdbInterface)
}
// Ignore Ctrl-C, it must be passed on to GDB.
@@ -526,7 +581,7 @@ func FlashGDB(pkgName, target, port string, ocdOutput bool, config *BuildConfig)
// By default: gdb -ex run <binary>
// Exit GDB with Ctrl-D.
params := []string{tmppath}
for _, cmd := range spec.GDBCmds {
for _, cmd := range gdbCommands {
params = append(params, "-ex", cmd)
}
cmd := exec.Command(spec.GDB, params...)
@@ -606,7 +661,7 @@ func flashUF2UsingMSD(volume, tmppath string) error {
return err
}
if d == nil {
return errors.New("unable to locate UF2 device:" + volume)
return errors.New("unable to locate UF2 device: " + volume)
}
return moveFile(tmppath, filepath.Dir(d[0])+"/flash.uf2")
@@ -624,7 +679,7 @@ func flashHexUsingMSD(volume, tmppath string) error {
return err
}
if d == nil {
return errors.New("unable to locate device:" + volume)
return errors.New("unable to locate device: " + volume)
}
return moveFile(tmppath, d[0]+"/flash.hex")