Skip to content

Commit f43acbb

Browse files
committed
Implemented plugin-based firmware upload
1 parent d4e105b commit f43acbb

File tree

2 files changed

+82
-12
lines changed

2 files changed

+82
-12
lines changed

cli/firmware/flash.go

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ package firmware
2121
import (
2222
"bytes"
2323
"fmt"
24+
"io"
2425
"os"
2526
"strings"
2627
"time"
@@ -32,6 +33,7 @@ import (
3233
"github.com/arduino/arduino-fwuploader/flasher"
3334
"github.com/arduino/arduino-fwuploader/indexes/download"
3435
"github.com/arduino/arduino-fwuploader/indexes/firmwareindex"
36+
"github.com/arduino/arduino-fwuploader/plugin"
3537
"github.com/arduino/go-paths-helper"
3638
"github.com/sirupsen/logrus"
3739
"github.com/spf13/cobra"
@@ -69,6 +71,10 @@ func runFlash(cmd *cobra.Command, args []string) {
6971
// at the end cleanup the fwuploader temp dir
7072
defer globals.FwUploaderPath.RemoveAll()
7173

74+
if retries < 1 {
75+
feedback.Fatal("Number of retries should be at least 1", feedback.ErrBadArgument)
76+
}
77+
7278
common.CheckFlags(commonFlags.Fqbn, commonFlags.Address)
7379
packageIndex, firmwareIndex := common.InitIndexes()
7480
board := common.GetBoard(firmwareIndex, commonFlags.Fqbn)
@@ -115,6 +121,7 @@ func runFlash(cmd *cobra.Command, args []string) {
115121
}
116122

117123
loaderSketch := ""
124+
var uploader *plugin.FwUploader
118125
if !board.IsPlugin() {
119126
loaderSketchPath, err := download.DownloadSketch(board.LoaderSketch)
120127
if err != nil {
@@ -123,34 +130,63 @@ func runFlash(cmd *cobra.Command, args []string) {
123130
logrus.Debugf("loader sketch downloaded in %s", loaderSketchPath.String())
124131
loaderSketch = strings.ReplaceAll(loaderSketchPath.String(), loaderSketchPath.Ext(), "")
125132
} else {
126-
// TODO...
133+
var err error
134+
uploader, err = plugin.NewFWUploaderPlugin(uploadToolDir)
135+
if err != nil {
136+
feedback.Fatal(fmt.Sprintf("Could not open uploader plugin: %s", err), feedback.ErrGeneric)
137+
}
127138
}
128139

129-
for retry := 1; retry <= retries; retry++ {
140+
retry := 0
141+
for {
142+
retry++
143+
logrus.Infof("Uploading firmware (try %d of %d)", retry, retries)
144+
145+
var res *flasher.FlashResult
130146
var err error
131147
if !board.IsPlugin() {
132-
err = updateFirmware(board, loaderSketch, moduleName, uploadToolDir, firmwareFilePath)
148+
res, err = updateFirmware(board, loaderSketch, moduleName, uploadToolDir, firmwareFilePath)
133149
} else {
134-
err = nil // TODO...
150+
res, err = updateFirmwareWithPlugin(uploader, firmwareFilePath)
135151
}
136152
if err == nil {
153+
feedback.PrintResult(res)
137154
logrus.Info("Operation completed: success! :-)")
138155
break
139156
}
140157
logrus.Error(err)
158+
141159
if retry == retries {
142160
logrus.Fatal("Operation failed. :-(")
143161
}
162+
144163
logrus.Info("Waiting 1 second before retrying...")
145164
time.Sleep(time.Second)
146-
logrus.Infof("Retrying upload (%d of %d)", retry, retries)
147165
}
148166
}
149167

150-
func updateFirmware(board *firmwareindex.IndexBoard, loaderSketch, moduleName string, uploadToolDir, firmwareFile *paths.Path) error {
168+
func updateFirmwareWithPlugin(uploader *plugin.FwUploader, fwPath *paths.Path) (*flasher.FlashResult, error) {
169+
var stdout, stderr io.Writer
170+
if feedback.GetFormat() == feedback.Text {
171+
stdout = os.Stdout
172+
stderr = os.Stderr
173+
}
174+
res, err := uploader.FlashFirmware(commonFlags.Address, fwPath, stdout, stderr)
175+
if err != nil {
176+
return nil, fmt.Errorf("couldn't update firmware: %s", err)
177+
}
178+
return &flasher.FlashResult{
179+
Programmer: &flasher.ExecOutput{
180+
Stdout: string(res.Stdout),
181+
Stderr: string(res.Stderr),
182+
},
183+
}, nil
184+
}
185+
186+
func updateFirmware(board *firmwareindex.IndexBoard, loaderSketch, moduleName string, uploadToolDir, firmwareFile *paths.Path) (*flasher.FlashResult, error) {
151187
programmerOut, programmerErr, err := common.FlashSketch(board, loaderSketch, uploadToolDir, commonFlags.Address)
152188
if err != nil {
153-
return err
189+
return nil, err
154190
}
155191
// Wait a bit after flashing the loader sketch for the board to become
156192
// available again.
@@ -174,7 +210,7 @@ func updateFirmware(board *firmwareindex.IndexBoard, loaderSketch, moduleName st
174210
feedback.Fatal(fmt.Sprintf("Error during firmware flashing: %s", err), feedback.ErrGeneric)
175211
}
176212
if err != nil {
177-
return fmt.Errorf("error during firmware flashing: %s", err)
213+
return nil, fmt.Errorf("error during firmware flashing: %s", err)
178214
}
179215
defer f.Close()
180216

@@ -189,11 +225,11 @@ func updateFirmware(board *firmwareindex.IndexBoard, loaderSketch, moduleName st
189225
}
190226
if err != nil {
191227
flasherErr.Write([]byte(fmt.Sprintf("Error during firmware flashing: %s", err)))
192-
return err
228+
return nil, err
193229
}
194230

195231
// Print the results
196-
feedback.PrintResult(&flasher.FlashResult{
232+
return &flasher.FlashResult{
197233
Programmer: (&flasher.ExecOutput{
198234
Stdout: programmerOut.String(),
199235
Stderr: programmerErr.String(),
@@ -202,8 +238,7 @@ func updateFirmware(board *firmwareindex.IndexBoard, loaderSketch, moduleName st
202238
Stdout: flasherOut.String(),
203239
Stderr: flasherErr.String(),
204240
}),
205-
})
206-
return nil
241+
}, nil
207242
}
208243

209244
// callback used to print the progress

plugin/plugin.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,41 @@ type GetFirmwareVersionResult struct {
120120
Error string
121121
}
122122

123+
// FlashFirmware runs the plugin to flash the selected firmware
124+
func (uploader *FwUploader) FlashFirmware(portAddress string, firmwarePath *paths.Path, stdout, stderr io.Writer) (*FlashFirmwareResult, error) {
125+
args := []string{"firmware", "flash", firmwarePath.String()}
126+
if portAddress != "" {
127+
args = append(args, "-p", portAddress)
128+
}
129+
execStdout, execStderr, execErr := uploader.exec(stdout, stderr, args...)
130+
131+
res := &FlashFirmwareResult{
132+
Stdout: execStdout.Bytes(),
133+
Stderr: execStderr.Bytes(),
134+
}
135+
fwErrorPrefix := "FLASH-FIRMWARE-ERROR: "
136+
for _, line := range strings.Split(execStdout.String(), "\n") {
137+
if strings.HasPrefix(line, fwErrorPrefix) {
138+
res.Error = strings.TrimPrefix(line, fwErrorPrefix)
139+
}
140+
}
141+
if res.Error != "" {
142+
if execErr != nil {
143+
execErr = fmt.Errorf("%s: %w", res.Error, execErr)
144+
} else {
145+
execErr = errors.New(res.Error)
146+
}
147+
}
148+
return res, execErr
149+
}
150+
151+
// GetFirmwareVersionResult contains the result of GetFirmwareVersion command
152+
type FlashFirmwareResult struct {
153+
Error string
154+
Stdout []byte
155+
Stderr []byte
156+
}
157+
123158
func (uploader *FwUploader) exec(stdout, stderr io.Writer, args ...string) (*bytes.Buffer, *bytes.Buffer, error) {
124159
stdoutBuffer := &bytes.Buffer{}
125160
stderrBuffer := &bytes.Buffer{}

0 commit comments

Comments
 (0)