From f29abe7a0e84e3194a1d1b8f7f67d4a0b6a5efb0 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Tue, 27 Apr 2021 11:01:58 +0200 Subject: [PATCH] Added retries flag, that defaults to 2 (3 tries in total) --- main.go | 35 ++++++++++++++++++++++++++++------- modules/nina/main.go | 35 +++++++++++++++++++---------------- modules/sara/main.go | 23 +++++++++++++---------- modules/winc/main.go | 26 ++++++++++++++------------ utils/context/context.go | 1 + 5 files changed, 75 insertions(+), 45 deletions(-) diff --git a/main.go b/main.go index 498c65b5..fd68e44c 100644 --- a/main.go +++ b/main.go @@ -7,6 +7,7 @@ import ( "log" "os" "strings" + "time" "github.com/arduino/FirmwareUploader/modules/nina" "github.com/arduino/FirmwareUploader/modules/sara" @@ -28,11 +29,11 @@ func init() { flag.StringVar(&ctx.ProgrammerPath, "programmer", "", "path of programmer in use (avrdude/bossac)") flag.StringVar(&ctx.Model, "model", "", "module model (winc, nina or sara)") flag.StringVar(&ctx.Compatible, "get_available_for", "", "Ask for available firmwares matching a given board") + flag.IntVar(&ctx.Retries, "retries", 2, "Number of retries in case of upload failure") } func main() { flag.Parse() - if ctx.Compatible != "" { el, _ := json.Marshal(utils.GetCompatibleWith(ctx.Compatible, "")) fmt.Println(string(el)) @@ -43,11 +44,31 @@ func main() { log.Fatal("Please specify a serial port") } - if ctx.Model == "nina" || strings.Contains(ctx.FirmwareFile, "NINA") || strings.Contains(ctx.FWUploaderBinary, "NINA") { - nina.Run(ctx) - } else if ctx.Model == "winc" || strings.Contains(ctx.FirmwareFile, "WINC") || strings.Contains(ctx.FWUploaderBinary, "WINC") { - winc.Run(ctx) - } else { - sara.Run(ctx) + retry := 0 + for { + var ctxCopy context.Context + ctxCopy = *ctx + var err error + if ctx.Model == "nina" || strings.Contains(ctx.FirmwareFile, "NINA") || strings.Contains(ctx.FWUploaderBinary, "NINA") { + err = nina.Run(&ctxCopy) + } else if ctx.Model == "winc" || strings.Contains(ctx.FirmwareFile, "WINC") || strings.Contains(ctx.FWUploaderBinary, "WINC") { + err = winc.Run(&ctxCopy) + } else { + err = sara.Run(&ctxCopy) + } + if err == nil { + log.Println("Operation completed: success! :-)") + break + } + log.Println("Error: " + err.Error()) + + if retry >= ctx.Retries { + log.Fatal("Operation failed. :-(") + } + + retry++ + log.Println("Waiting 1 second before retrying...") + time.Sleep(time.Second) + log.Printf("Retrying upload (%d of %d)", retry, ctx.Retries) } } diff --git a/modules/nina/main.go b/modules/nina/main.go index b2121b0f..99343482 100644 --- a/modules/nina/main.go +++ b/modules/nina/main.go @@ -28,17 +28,18 @@ import ( "strconv" "strings" - "github.com/arduino/FirmwareUploader/programmers/rp2040load" "github.com/arduino/FirmwareUploader/programmers/avrdude" "github.com/arduino/FirmwareUploader/programmers/bossac" + "github.com/arduino/FirmwareUploader/programmers/rp2040load" "github.com/arduino/FirmwareUploader/utils/context" + "github.com/pkg/errors" ) var flasher *Flasher var payloadSize uint16 var programmer context.Programmer -func Run(ctx *context.Context) { +func Run(ctx *context.Context) error { if ctx.ProgrammerPath != "" { if strings.Contains(filepath.Base(ctx.ProgrammerPath), "bossac") { @@ -48,60 +49,61 @@ func Run(ctx *context.Context) { } else if strings.Contains(filepath.Base(ctx.ProgrammerPath), "rp2040load") { programmer = rp2040load.NewRP2040Load(ctx) } else { - log.Fatal("Programmer path not specified correctly, programmer path set to: " + ctx.ProgrammerPath) + return errors.New("Programmer path not specified correctly, programmer path set to: " + ctx.ProgrammerPath) } } if ctx.FWUploaderBinary != "" { log.Println("Flashing firmware uploader nina") if programmer == nil { - log.Fatal("ERROR: You must specify a programmer!") + return errors.New("ERROR: You must specify a programmer!") } if err := programmer.Flash(ctx.FWUploaderBinary, nil); err != nil { - log.Fatal(err) + return err } } log.Println("Connecting to programmer") if f, err := OpenFlasher(ctx.PortName); err != nil { - log.Fatal(err) + return err } else { flasher = f } + defer flasher.Close() // Synchronize with programmer log.Println("Sync with programmer") if err := flasher.Hello(); err != nil { - log.Fatal(err) + return err } // Check maximum supported payload size log.Println("Reading max payload size") if _payloadSize, err := flasher.GetMaximumPayloadSize(); err != nil { - log.Fatal(err) + return err } else { payloadSize = _payloadSize } if payloadSize < 1024 { - log.Fatalf("Programmer reports %d as maximum payload size (1024 is needed)", payloadSize) + return errors.Errorf("Programmer reports %d as maximum payload size (1024 is needed)", payloadSize) } if ctx.FirmwareFile != "" { if err := flashFirmware(ctx); err != nil { - log.Fatal(err) + return err } } if ctx.RootCertDir != "" || len(ctx.Addresses) != 0 { if err := flashCerts(ctx); err != nil { - log.Fatal(err) + return err } } if ctx.ReadAll { log.Println("Reading all flash") if err := readAllFlash(); err != nil { - log.Fatal(err) + return err } } @@ -110,18 +112,19 @@ func Run(ctx *context.Context) { if ctx.BinaryToRestore != "" { log.Println("Restoring binary") if programmer == nil { - log.Fatal("ERROR: You must specify a programmer!") + errors.New("ERROR: You must specify a programmer!") } if err := programmer.Flash(ctx.BinaryToRestore, nil); err != nil { - log.Fatal(err) + return err } } + return nil } func readAllFlash() error { for i := 0; i < 256; i++ { if data, err := flasher.Read(uint32(i*1024), 1024); err != nil { - log.Fatal(err) + return err } else { os.Stdout.Write(data) } @@ -142,7 +145,7 @@ func flashCerts(ctx *context.Context) error { } if len(certificatesData) > 0x20000 { - log.Fatal("Too many certificates! Aborting") + errors.New("Too many certificates! Aborting") } // pad certificatesData to flash page diff --git a/modules/sara/main.go b/modules/sara/main.go index 54713c52..1d7e33c8 100644 --- a/modules/sara/main.go +++ b/modules/sara/main.go @@ -21,48 +21,50 @@ package sara import ( "fmt" - "github.com/arduino/FirmwareUploader/programmers/bossac" - "github.com/arduino/FirmwareUploader/utils/context" "io/ioutil" "log" "strconv" "time" + + "github.com/arduino/FirmwareUploader/programmers/bossac" + "github.com/arduino/FirmwareUploader/utils/context" ) var f *Flasher var payloadSize uint16 var programmer context.Programmer -func Run(ctx *context.Context) { +func Run(ctx *context.Context) error { programmer := bossac.NewBossac(ctx) if ctx.FWUploaderBinary != "" { log.Println("Flashing firmware uploader sara") if err := programmer.Flash(ctx.FWUploaderBinary, nil); err != nil { - log.Fatal(err) + return err } } log.Println("Connecting to programmer") if _f, err := OpenFlasher(ctx.PortName); err != nil { - log.Fatal(err) + return err } else { f = _f } + defer f.Close() time.Sleep(2 * time.Second) // Synchronize with programmer log.Println("Sync with programmer") if err := f.Hello(); err != nil { - log.Fatal(err) + return err } // Check maximum supported payload size log.Println("Reading actual firmware version") if fwVersion, err := f.GetFwVersion(); err != nil { - log.Fatal(err) + return err } else { log.Println("Initial firmware version: " + fwVersion) } @@ -71,12 +73,12 @@ func Run(ctx *context.Context) { if ctx.FirmwareFile != "" { if err := flashFirmware(ctx); err != nil { - log.Fatal(err) + return err } } if fwVersion, err := f.GetFwVersion(); err != nil { - log.Fatal(err) + return err } else { log.Println("After applying update firmware version: " + fwVersion) } @@ -87,9 +89,10 @@ func Run(ctx *context.Context) { log.Println("Restoring previous sketch") if err := programmer.Flash(ctx.BinaryToRestore, nil); err != nil { - log.Fatal(err) + return err } } + return nil } func flashFirmware(ctx *context.Context) error { diff --git a/modules/winc/main.go b/modules/winc/main.go index 61b4360b..f50df35b 100644 --- a/modules/winc/main.go +++ b/modules/winc/main.go @@ -21,7 +21,6 @@ package winc import ( "bytes" - "errors" "fmt" "io/ioutil" "log" @@ -30,63 +29,65 @@ import ( "github.com/arduino/FirmwareUploader/programmers/bossac" "github.com/arduino/FirmwareUploader/utils/context" + "github.com/pkg/errors" ) var f *Flasher var payloadSize uint16 -func Run(ctx *context.Context) { +func Run(ctx *context.Context) error { programmer := bossac.NewBossac(ctx) if ctx.FWUploaderBinary != "" { log.Println("Flashing firmware uploader winc") if err := programmer.Flash(ctx.FWUploaderBinary, nil); err != nil { - log.Fatal(err) + return err } } log.Println("Connecting to programmer") if _f, err := OpenFlasher(ctx.PortName); err != nil { - log.Fatal(err) + return err } else { f = _f } + defer f.Close() // Synchronize with programmer log.Println("Sync with programmer") if err := f.Hello(); err != nil { - log.Fatal(err) + return err } // Check maximum supported payload size log.Println("Reading max payload size") _payloadSize, err := f.GetMaximumPayloadSize() if err != nil { - log.Fatal(err) + return err } else { payloadSize = _payloadSize } if payloadSize < 1024 { - log.Fatalf("Programmer reports %d as maximum payload size (1024 is needed)", payloadSize) + return errors.Errorf("Programmer reports %d as maximum payload size (1024 is needed)", payloadSize) } if ctx.FirmwareFile != "" { if err := flashFirmware(ctx); err != nil { - log.Fatal(err) + return err } } if ctx.RootCertDir != "" || len(ctx.Addresses) != 0 { if err := flashCerts(ctx); err != nil { - log.Fatal(err) + return err } } if ctx.ReadAll { log.Println("Reading all flash") if err := readAllFlash(); err != nil { - log.Fatal(err) + return err } } @@ -96,15 +97,16 @@ func Run(ctx *context.Context) { log.Println("Restoring previous sketch") if err := programmer.Flash(ctx.BinaryToRestore, nil); err != nil { - log.Fatal(err) + return err } } + return nil } func readAllFlash() error { for i := 0; i < 256; i++ { if data, err := f.Read(uint32(i*1024), 1024); err != nil { - log.Fatal(err) + return err } else { os.Stdout.Write(data) } diff --git a/utils/context/context.go b/utils/context/context.go index 5490f4f5..2c52562f 100644 --- a/utils/context/context.go +++ b/utils/context/context.go @@ -28,6 +28,7 @@ type Context struct { ProgrammerPath string Model string Compatible string + Retries int } type Programmer interface {