Skip to content

Commit 9c190d2

Browse files
matteosuppofacchinm
authored andcommitted
Add functions to reset the port
1 parent 483c1e0 commit 9c190d2

File tree

5 files changed

+656
-2
lines changed

5 files changed

+656
-2
lines changed

programmer/programmer.go

Lines changed: 125 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,27 @@
11
package programmer
22

3+
import (
4+
"time"
5+
6+
"github.com/facchinm/go-serial"
7+
"github.com/pkg/errors"
8+
)
9+
310
type logger interface {
4-
Info()
5-
Debug()
11+
Debug(args ...interface{})
12+
Info(args ...interface{})
13+
}
14+
15+
func debug(l logger, args ...interface{}) {
16+
if l != nil {
17+
l.Debug(args...)
18+
}
19+
}
20+
21+
func info(l logger, args ...interface{}) {
22+
if l != nil {
23+
l.Info(args...)
24+
}
625
}
726

827
// Auth contains username and password used for a network upload
@@ -24,5 +43,109 @@ type Extra struct {
2443

2544
// Do performs a command on a port with a board attached to it
2645
func Do(port, board, path, commandline string, extra Extra, l logger) {
46+
debug(l, port, board, path, commandline)
47+
if extra.Network {
48+
doNetwork()
49+
} else {
50+
doSerial(port, extra, l)
51+
}
52+
}
53+
54+
func doNetwork() {}
55+
56+
func doSerial(port string, extra Extra, l logger) {
57+
// some boards needs to be resetted
58+
if extra.Use1200bpsTouch {
59+
port, _ = reset(port, extra.WaitForUploadPort, l)
60+
}
61+
}
62+
63+
// reset opens the port at 1200bps. It returns the new port name (which could change
64+
// sometimes) and an error (usually because the port listing failed)
65+
func reset(port string, wait bool, l logger) (string, error) {
66+
info(l, "Restarting in bootloader mode")
67+
68+
// Get port list before reset
69+
ports, err := serial.GetPortsList()
70+
debug(l, "Get port list before reset")
71+
debug(l, ports, err)
72+
if err != nil {
73+
return "", errors.Wrapf(err, "Get port list before reset")
74+
}
75+
76+
// Open port
77+
mode := &serial.Mode{
78+
BaudRate: 1200,
79+
Vmin: 0,
80+
Vtimeout: 1,
81+
}
82+
p, err := serial.OpenPort(port, mode)
83+
debug(l, "Open port", port)
84+
debug(l, p, err)
85+
if err != nil {
86+
return "", errors.Wrapf(err, "Open port %s", port)
87+
}
88+
89+
// Set DTR
90+
err = p.SetDTR(false)
91+
debug(l, "Set DTR")
92+
debug(l, err)
93+
p.Close()
94+
95+
// Wait for port to disappear and reappear
96+
if wait {
97+
port = waitReset(ports, l)
98+
}
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, l logger) string {
107+
var port string
108+
timeout := false
109+
110+
go func() {
111+
time.Sleep(10 * time.Second)
112+
timeout = true
113+
}()
114+
115+
// Wait for the port to disappear
116+
debug(l, "Wait for the port to disappear")
117+
for {
118+
ports, err := serial.GetPortsList()
119+
port = differ(ports, beforeReset)
120+
debug(l, "..", ports, beforeReset, err, port)
121+
122+
if port != "" {
123+
break
124+
}
125+
if timeout {
126+
debug(l, ports, err, port)
127+
break
128+
}
129+
time.Sleep(time.Millisecond * 100)
130+
}
131+
132+
// Wait for the port to reappear
133+
debug(l, "Wait for the port to reappear")
134+
afterReset, _ := serial.GetPortsList()
135+
for {
136+
ports, err := serial.GetPortsList()
137+
port = differ(ports, afterReset)
138+
debug(l, "..", ports, afterReset, err, port)
139+
if port != "" {
140+
time.Sleep(time.Millisecond * 500)
141+
break
142+
}
143+
if timeout {
144+
debug(l, "timeout")
145+
break
146+
}
147+
time.Sleep(time.Millisecond * 100)
148+
}
27149

150+
return port
28151
}

programmer/programmer_test.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package programmer_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/Sirupsen/logrus"
7+
"github.com/arduino/arduino-create-agent/programmer"
8+
"github.com/stretchr/testify/suite"
9+
)
10+
11+
type ProgrammerTestSuite struct {
12+
suite.Suite
13+
}
14+
15+
func TestProgrammer(t *testing.T) {
16+
suite.Run(t, new(ProgrammerTestSuite))
17+
}
18+
19+
var TestSerialData = []struct {
20+
Name string
21+
Port string
22+
Board string
23+
File string
24+
Commandline string
25+
Extra programmer.Extra
26+
}{
27+
{"leonardo", "/dev/ttyACM0", "arduino:avr:leonardo", "./programmer_test.hex",
28+
`"{runtime.tools.avrdude.path}/bin/avrdude" "-C{runtime.tools.avrdude.path}/etc/avrdude.conf" {upload.verbose} {upload.verify} -patmega32u4 -cavr109 -P{serial.port} -b57600 -D "-Uflash:w:{build.path}/{build.project_name}.hex:i"`, programmer.Extra{Use1200bpsTouch: true, WaitForUploadPort: true}},
29+
}
30+
31+
func (t *ProgrammerTestSuite) TestSerial() {
32+
logger := logrus.New()
33+
logger.Level = logrus.DebugLevel
34+
35+
for _, test := range TestSerialData {
36+
programmer.Do(test.Port, test.Board, test.File, test.Commandline, test.Extra, logger)
37+
}
38+
t.Fail("")
39+
}

0 commit comments

Comments
 (0)