Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 775097c

Browse files
committedSep 24, 2020
Factored out reset/1200bps-touch subroutines and executils
Reusing the implementation available in arduino-cli
1 parent 9500a01 commit 775097c

File tree

5 files changed

+369
-334
lines changed

5 files changed

+369
-334
lines changed
 

‎go.mod

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,8 @@ go 1.14
55
// branch with support for serial timeouts
66
replace go.bug.st/serial => github.com/cmaglie/go-serial v0.0.0-20200923162623-b214c147e37e
77

8-
require go.bug.st/serial v1.1.1
8+
require (
9+
github.com/arduino/arduino-cli v0.0.0-20200924151007-69ac12c98b2b
10+
github.com/pkg/errors v0.9.1
11+
go.bug.st/serial v1.1.1
12+
)

‎go.sum

Lines changed: 313 additions & 0 deletions
Large diffs are not rendered by default.

‎modules/winc/main.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,22 +23,22 @@ import (
2323
"bytes"
2424
"errors"
2525
"fmt"
26-
"github.com/arduino/FirmwareUpdater/programmers/bossac"
27-
"github.com/arduino/FirmwareUpdater/utils/context"
2826
"io/ioutil"
2927
"log"
3028
"os"
3129
"strconv"
30+
31+
"github.com/arduino/FirmwareUpdater/programmers/bossac"
32+
"github.com/arduino/FirmwareUpdater/utils/context"
3233
)
3334

3435
var f *Flasher
3536
var payloadSize uint16
36-
var programmer context.Programmer
3737

3838
func Run(ctx context.Context) {
3939

4040
var err error
41-
programmer = &bossac.Bossac{}
41+
programmer := &bossac.Bossac{}
4242

4343
if ctx.FWUploaderBinary != "" {
4444
log.Println("Flashing firmware uploader winc")

‎programmers/avrdude/avrdude.go

Lines changed: 18 additions & 162 deletions
Original file line numberDiff line numberDiff line change
@@ -1,200 +1,56 @@
11
package avrdude
22

33
import (
4-
"bytes"
5-
"errors"
64
"io/ioutil"
75
"log"
8-
"os/exec"
6+
"os"
97
"path/filepath"
108
"time"
119

1210
"github.com/arduino/FirmwareUpdater/utils/context"
13-
"go.bug.st/serial"
11+
"github.com/arduino/arduino-cli/executils"
12+
"github.com/pkg/errors"
1413
)
1514

1615
type Avrdude struct {
1716
}
1817

1918
func (b *Avrdude) Flash(ctx *context.Context, filename string) error {
2019
log.Println("Flashing " + filename)
21-
2220
err := invokeAvrdude([]string{ctx.ProgrammerPath, "-C" + filepath.Join(filepath.Dir(ctx.ProgrammerPath), "..", "etc/avrdude.conf"), "-v", "-patmega4809", "-cxplainedmini_updi", "-Pusb", "-b115200", "-e", "-D", "-Uflash:w:" + filename + ":i", "-Ufuse8:w:0x00:m"})
2321

2422
time.Sleep(3 * time.Second)
23+
2524
return err
2625
}
2726

2827
func (b *Avrdude) DumpAndFlash(ctx *context.Context, filename string) (string, error) {
29-
log.Println("Flashing " + filename)
3028
dir, err := ioutil.TempDir("", "wifiFlasher_dump")
29+
if err != nil {
30+
return "", errors.WithMessage(err, "creating temp dir to store current sketch")
31+
}
32+
33+
log.Println("Reading existing sketch from the baord, to restore it later")
3134
err = invokeAvrdude([]string{ctx.ProgrammerPath, "-C" + filepath.Join(filepath.Dir(ctx.ProgrammerPath), "..", "etc/avrdude.conf"), "-v", "-patmega4809", "-cxplainedmini_updi", "-Pusb", "-b115200", "-D", "-Uflash:r:" + filepath.Join(dir, "dump.bin") + ":i"})
32-
log.Println("Original sketch saved at " + filepath.Join(dir, "dump.bin"))
3335
if err != nil {
3436
return "", err
3537
}
38+
log.Println("Original sketch saved at " + filepath.Join(dir, "dump.bin"))
39+
40+
log.Println("Flashing " + filename)
3641
err = invokeAvrdude([]string{ctx.ProgrammerPath, "-C" + filepath.Join(filepath.Dir(ctx.ProgrammerPath), "..", "etc/avrdude.conf"), "-v", "-patmega4809", "-cxplainedmini_updi", "-Pusb", "-b115200", "-e", "-D", "-Uflash:w:" + filename + ":i", "-Ufuse8:w:0x00:m"})
42+
3743
time.Sleep(3 * time.Second)
3844

3945
return filepath.Join(dir, "dump.bin"), err
4046
}
4147

4248
func invokeAvrdude(args []string) error {
43-
cmd := exec.Command(args[0], args[1:]...)
44-
var out bytes.Buffer
45-
var stderr bytes.Buffer
46-
cmd.Stdout = &out
47-
cmd.Stderr = &stderr
48-
err := cmd.Run()
49-
log.Println(out.String())
50-
log.Println(stderr.String())
51-
return err
52-
}
53-
54-
func touchSerialPortAt1200bps(port string) error {
55-
log.Println("Touching port " + port + " at 1200bps")
56-
57-
// Open port
58-
p, err := serial.Open(port, &serial.Mode{BaudRate: 1200})
49+
cmd, err := executils.NewProcess(args...)
5950
if err != nil {
60-
return errors.New("Open port " + port)
61-
}
62-
defer p.Close()
63-
64-
// Set DTR
65-
err = p.SetDTR(false)
66-
log.Println("Set DTR off")
67-
if err != nil {
68-
return errors.New("Can't set DTR")
69-
}
70-
71-
// Wait a bit to allow restart of the board
72-
time.Sleep(200 * time.Millisecond)
73-
74-
return nil
75-
}
76-
77-
// reset opens the port at 1200bps. It returns the new port name (which could change
78-
// sometimes) and an error (usually because the port listing failed)
79-
func reset(port string, wait bool) (string, error) {
80-
log.Println("Restarting in bootloader mode")
81-
82-
// Get port list before reset
83-
ports, err := serial.GetPortsList()
84-
log.Println("Get port list before reset")
85-
if err != nil {
86-
return "", errors.New("Get port list before reset")
87-
}
88-
89-
// Touch port at 1200bps
90-
err = touchSerialPortAt1200bps(port)
91-
if err != nil {
92-
return "", errors.New("1200bps Touch")
93-
}
94-
95-
// Wait for port to disappear and reappear
96-
if wait {
97-
port = waitReset(ports, port)
51+
return err
9852
}
99-
100-
return port, nil
101-
}
102-
103-
// waitReset is meant to be called just after a reset. It watches the ports connected
104-
// to the machine until a port disappears and reappears. The port name could be different
105-
// so it returns the name of the new port.
106-
func waitReset(beforeReset []string, originalPort string) string {
107-
var port string
108-
timeout := false
109-
110-
go func() {
111-
time.Sleep(10 * time.Second)
112-
timeout = true
113-
}()
114-
115-
for {
116-
ports, _ := serial.GetPortsList()
117-
port = differ(ports, beforeReset)
118-
119-
if port != "" {
120-
break
121-
}
122-
if timeout {
123-
break
124-
}
125-
time.Sleep(time.Millisecond * 100)
126-
}
127-
128-
// Wait for the port to reappear
129-
log.Println("Wait for the port to reappear")
130-
afterReset, _ := serial.GetPortsList()
131-
for {
132-
ports, _ := serial.GetPortsList()
133-
port = differ(ports, afterReset)
134-
if port != "" {
135-
time.Sleep(time.Millisecond * 500)
136-
break
137-
}
138-
if timeout {
139-
break
140-
}
141-
time.Sleep(time.Millisecond * 100)
142-
}
143-
144-
// try to upload on the existing port if the touch was ineffective
145-
if port == "" {
146-
port = originalPort
147-
}
148-
149-
return port
150-
}
151-
152-
func waitPort(beforeReset []string, originalPort string) string {
153-
var port string
154-
timeout := false
155-
156-
go func() {
157-
time.Sleep(10 * time.Second)
158-
timeout = true
159-
}()
160-
161-
for {
162-
ports, _ := serial.GetPortsList()
163-
port = differ(ports, beforeReset)
164-
165-
if port != "" {
166-
break
167-
}
168-
if timeout {
169-
break
170-
}
171-
time.Sleep(time.Millisecond * 100)
172-
}
173-
174-
// try to upload on the existing port if the touch was ineffective
175-
if port == "" {
176-
port = originalPort
177-
}
178-
179-
return port
180-
}
181-
182-
// differ returns the first item that differ between the two input slices
183-
func differ(slice1 []string, slice2 []string) string {
184-
m := map[string]int{}
185-
186-
for _, s1Val := range slice1 {
187-
m[s1Val] = 1
188-
}
189-
for _, s2Val := range slice2 {
190-
m[s2Val] = m[s2Val] + 1
191-
}
192-
193-
for mKey, mVal := range m {
194-
if mVal == 1 {
195-
return mKey
196-
}
197-
}
198-
199-
return ""
53+
cmd.RedirectStdoutTo(os.Stdout)
54+
cmd.RedirectStderrTo(os.Stderr)
55+
return cmd.Run()
20056
}

‎programmers/bossac/bossac.go

Lines changed: 29 additions & 167 deletions
Original file line numberDiff line numberDiff line change
@@ -1,212 +1,74 @@
11
package bossac
22

33
import (
4-
"bytes"
5-
"errors"
64
"io/ioutil"
75
"log"
8-
"os/exec"
6+
"os"
97
"path/filepath"
108
"time"
119

1210
"github.com/arduino/FirmwareUpdater/utils/context"
13-
"go.bug.st/serial"
11+
"github.com/arduino/arduino-cli/arduino/serialutils"
12+
"github.com/arduino/arduino-cli/executils"
13+
"github.com/pkg/errors"
1414
)
1515

1616
type Bossac struct {
1717
}
1818

1919
func (b *Bossac) Flash(ctx *context.Context, filename string) error {
20-
log.Println("Flashing " + filename)
21-
22-
port, err := reset(ctx.PortName, true)
20+
log.Println("Entering board into bootloader mode")
21+
port, err := serialutils.Reset(ctx.PortName, true)
2322
if err != nil {
2423
return err
2524
}
26-
err = invokeBossac([]string{ctx.ProgrammerPath, "-e", "-R", "-p", port, "-w", filename})
2725

28-
ports, err := serial.GetPortsList()
29-
ctx.PortName = waitPort(ports, port)
26+
log.Println("Flashing " + filename)
27+
err = invokeBossac([]string{ctx.ProgrammerPath, "-e", "-R", "-p", port, "-w", filename})
3028

31-
log.Println("Port is online " + ctx.PortName)
29+
ctx.PortName, err = serialutils.WaitForNewSerialPortOrDefaultTo(port)
30+
log.Println("Board is back online " + ctx.PortName)
3231
time.Sleep(1 * time.Second)
3332

3433
return err
3534
}
3635

3736
func (b *Bossac) DumpAndFlash(ctx *context.Context, filename string) (string, error) {
38-
log.Println("Flashing " + filename)
3937
dir, err := ioutil.TempDir("", "wifiFlasher_dump")
40-
port, err := reset(ctx.PortName, true)
38+
if err != nil {
39+
return "", errors.WithMessage(err, "creating temp dir to store current sketch")
40+
}
41+
42+
log.Println("Entering board into bootloader mode")
43+
port, err := serialutils.Reset(ctx.PortName, true)
4144
if err != nil {
4245
return "", err
4346
}
47+
48+
log.Println("Reading existing sketch from the baord, to restore it later")
4449
err = invokeBossac([]string{ctx.ProgrammerPath, "-u", "-r", "-p", port, filepath.Join(dir, "dump.bin")})
50+
4551
log.Println("Original sketch saved at " + filepath.Join(dir, "dump.bin"))
4652
if err != nil {
4753
return "", err
4854
}
55+
56+
log.Println("Flashing " + filename)
4957
err = invokeBossac([]string{ctx.ProgrammerPath, "-e", "-R", "-p", port, "-w", filename})
5058

51-
ports, err := serial.GetPortsList()
52-
ctx.PortName = waitPort(ports, port)
59+
ctx.PortName, err = serialutils.WaitForNewSerialPortOrDefaultTo(port)
60+
log.Println("Board is back online " + ctx.PortName)
61+
time.Sleep(1 * time.Second)
5362

5463
return filepath.Join(dir, "dump.bin"), err
5564
}
5665

5766
func invokeBossac(args []string) error {
58-
cmd := exec.Command(args[0], args[1:]...)
59-
var out bytes.Buffer
60-
cmd.Stdout = &out
61-
err := cmd.Run()
62-
log.Println(out.String())
63-
return err
64-
}
65-
66-
func touchSerialPortAt1200bps(port string) error {
67-
log.Println("Touching port " + port + " at 1200bps")
68-
69-
// Open port
70-
p, err := serial.Open(port, &serial.Mode{BaudRate: 1200})
71-
if err != nil {
72-
return errors.New("Open port " + port)
73-
}
74-
defer p.Close()
75-
76-
// Set DTR
77-
err = p.SetDTR(false)
78-
log.Println("Set DTR off")
79-
if err != nil {
80-
return errors.New("Can't set DTR")
81-
}
82-
83-
// Wait a bit to allow restart of the board
84-
time.Sleep(200 * time.Millisecond)
85-
86-
return nil
87-
}
88-
89-
// reset opens the port at 1200bps. It returns the new port name (which could change
90-
// sometimes) and an error (usually because the port listing failed)
91-
func reset(port string, wait bool) (string, error) {
92-
log.Println("Restarting in bootloader mode")
93-
94-
// Get port list before reset
95-
ports, err := serial.GetPortsList()
96-
log.Println("Get port list before reset")
67+
cmd, err := executils.NewProcess(args...)
9768
if err != nil {
98-
return "", errors.New("Get port list before reset")
99-
}
100-
101-
// Touch port at 1200bps
102-
err = touchSerialPortAt1200bps(port)
103-
if err != nil {
104-
return "", errors.New("1200bps Touch")
105-
}
106-
107-
// Wait for port to disappear and reappear
108-
if wait {
109-
port = waitReset(ports, port)
110-
}
111-
112-
return port, nil
113-
}
114-
115-
// waitReset is meant to be called just after a reset. It watches the ports connected
116-
// to the machine until a port disappears and reappears. The port name could be different
117-
// so it returns the name of the new port.
118-
func waitReset(beforeReset []string, originalPort string) string {
119-
var port string
120-
timeout := false
121-
122-
go func() {
123-
time.Sleep(10 * time.Second)
124-
timeout = true
125-
}()
126-
127-
for {
128-
ports, _ := serial.GetPortsList()
129-
port = differ(ports, beforeReset)
130-
131-
if port != "" {
132-
break
133-
}
134-
if timeout {
135-
break
136-
}
137-
time.Sleep(time.Millisecond * 100)
138-
}
139-
140-
// Wait for the port to reappear
141-
log.Println("Wait for the port to reappear")
142-
afterReset, _ := serial.GetPortsList()
143-
for {
144-
ports, _ := serial.GetPortsList()
145-
port = differ(ports, afterReset)
146-
if port != "" {
147-
time.Sleep(time.Millisecond * 500)
148-
break
149-
}
150-
if timeout {
151-
break
152-
}
153-
time.Sleep(time.Millisecond * 100)
154-
}
155-
156-
// try to upload on the existing port if the touch was ineffective
157-
if port == "" {
158-
port = originalPort
159-
}
160-
161-
return port
162-
}
163-
164-
func waitPort(beforeReset []string, originalPort string) string {
165-
var port string
166-
timeout := false
167-
168-
go func() {
169-
time.Sleep(10 * time.Second)
170-
timeout = true
171-
}()
172-
173-
for {
174-
ports, _ := serial.GetPortsList()
175-
port = differ(ports, beforeReset)
176-
177-
if port != "" {
178-
break
179-
}
180-
if timeout {
181-
break
182-
}
183-
time.Sleep(time.Millisecond * 100)
184-
}
185-
186-
// try to upload on the existing port if the touch was ineffective
187-
if port == "" {
188-
port = originalPort
189-
}
190-
191-
return port
192-
}
193-
194-
// differ returns the first item that differ between the two input slices
195-
func differ(slice1 []string, slice2 []string) string {
196-
m := map[string]int{}
197-
198-
for _, s1Val := range slice1 {
199-
m[s1Val] = 1
200-
}
201-
for _, s2Val := range slice2 {
202-
m[s2Val] = m[s2Val] + 1
203-
}
204-
205-
for mKey, mVal := range m {
206-
if mVal == 1 {
207-
return mKey
208-
}
69+
return err
20970
}
210-
211-
return ""
71+
cmd.RedirectStdoutTo(os.Stdout)
72+
cmd.RedirectStderrTo(os.Stderr)
73+
return cmd.Run()
21274
}

0 commit comments

Comments
 (0)
Please sign in to comment.