Skip to content

Commit 62f5caf

Browse files
authored
Easier recovery from soft bricked native USB boards (#2173)
* Force serial-port-waiting in some uploads without port * Updated upload-mock integration tests * Force 'default' protocol if no port is specified in gRPC Upload
1 parent c656fd0 commit 62f5caf

File tree

3 files changed

+44
-4
lines changed

3 files changed

+44
-4
lines changed

Diff for: arduino/serialutils/serialutils.go

+2
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ func Reset(portToTouch string, wait bool, cb *ResetProgressCallbacks, dryRun boo
106106
}
107107
if strings.HasSuffix(emulatedPort, "999") {
108108
emulatedPort += "0"
109+
} else if emulatedPort == "" {
110+
emulatedPort = "newport"
109111
}
110112
return res, nil
111113
}

Diff for: commands/upload/upload.go

+20-4
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,10 @@ func runProgramAction(pme *packagemanager.Explorer,
195195
if burnBootloader && programmerID == "" {
196196
return &arduino.MissingProgrammerError{}
197197
}
198-
198+
if port == nil {
199+
// For no-port uploads use "default" protocol
200+
port = &rpc.Port{Protocol: "default"}
201+
}
199202
logrus.WithField("port", port).Tracef("Upload port")
200203

201204
fqbn, err := cores.ParseFQBN(fqbnIn)
@@ -361,11 +364,24 @@ func runProgramAction(pme *packagemanager.Explorer,
361364
uploadProperties.Set("build.project_name", sketchName)
362365
}
363366

367+
// Force port wait to make easier to unbrick boards like the Arduino Leonardo, or similar with native USB,
368+
// when a sketch causes a crash and the native USB serial port is lost.
369+
// See https://github.com/arduino/arduino-cli/issues/1943 for the details.
370+
//
371+
// In order to trigger the forced serial-port-wait the following conditions must be met:
372+
// - No upload port specified (protocol == "default")
373+
// - "upload.wait_for_upload_port" == true (developers requested the touch + port wait)
374+
// - "upload.tool.serial" not defained, or
375+
// "upload.tool.serial" is the same as "upload.tool.default"
376+
forcedSerialPortWait := port.Protocol == "default" && // this is the value when no port is specified
377+
uploadProperties.GetBoolean("upload.wait_for_upload_port") &&
378+
(!uploadProperties.ContainsKey("upload.tool.serial") ||
379+
uploadProperties.Get("upload.tool.serial") == uploadProperties.Get("upload.tool.default"))
380+
364381
// If not using programmer perform some action required
365382
// to set the board in bootloader mode
366383
actualPort := port
367-
if programmer == nil && !burnBootloader && port.Protocol == "serial" {
368-
384+
if programmer == nil && !burnBootloader && (port.Protocol == "serial" || forcedSerialPortWait) {
369385
// Perform reset via 1200bps touch if requested and wait for upload port also if requested.
370386
touch := uploadProperties.GetBoolean("upload.use_1200bps_touch")
371387
wait := false
@@ -425,7 +441,7 @@ func runProgramAction(pme *packagemanager.Explorer,
425441
if actualPort.Address != "" {
426442
// Set serial port property
427443
uploadProperties.Set("serial.port", actualPort.Address)
428-
if actualPort.Protocol == "serial" {
444+
if actualPort.Protocol == "serial" || actualPort.Protocol == "default" {
429445
// This must be done only for serial ports
430446
portFile := strings.TrimPrefix(actualPort.Address, "/dev/")
431447
uploadProperties.Set("serial.port.file", portFile)

Diff for: internal/integrationtest/upload_mock/upload_mock_test.go

+22
Original file line numberDiff line numberDiff line change
@@ -161,12 +161,24 @@ func TestUploadSketch(t *testing.T) {
161161
Programmer: "",
162162
Output: "Performing 1200-bps touch reset on serial port /dev/ttyACM999\nWaiting for upload port...\nUpload port found on /dev/ttyACM9990\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega32u4 -cavr109 \"-P/dev/ttyACM9990\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
163163
},
164+
{
165+
Fqbn: "arduino:avr:leonardo",
166+
UploadPort: "",
167+
Programmer: "",
168+
Output: "Skipping 1200-bps touch reset: no serial port selected!\nWaiting for upload port...\nUpload port found on newport\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega32u4 -cavr109 \"-Pnewport\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
169+
},
164170
{
165171
Fqbn: "arduino:avr:micro",
166172
UploadPort: "/dev/ttyACM999",
167173
Programmer: "",
168174
Output: "Performing 1200-bps touch reset on serial port /dev/ttyACM999\nWaiting for upload port...\nUpload port found on /dev/ttyACM9990\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega32u4 -cavr109 \"-P/dev/ttyACM9990\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
169175
},
176+
{
177+
Fqbn: "arduino:avr:micro",
178+
UploadPort: "",
179+
Programmer: "",
180+
Output: "Skipping 1200-bps touch reset: no serial port selected!\nWaiting for upload port...\nUpload port found on newport\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega32u4 -cavr109 \"-Pnewport\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
181+
},
170182
{
171183
Fqbn: "arduino:avr:circuitplay32u4cat",
172184
UploadPort: "/dev/ttyACM999",
@@ -502,6 +514,16 @@ func TestUploadSketch(t *testing.T) {
502514
"win32": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
503515
},
504516
},
517+
{
518+
Fqbn: "arduino:samd:mkr1000",
519+
UploadPort: "",
520+
Programmer: "",
521+
Output: map[string]string{
522+
"darwin": "Skipping 1200-bps touch reset: no serial port selected!\nWaiting for upload port...\nUpload port found on newport\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=newport -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
523+
"linux": "Skipping 1200-bps touch reset: no serial port selected!\nWaiting for upload port...\nUpload port found on newport\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=newport -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
524+
"win32": "Skipping 1200-bps touch reset: no serial port selected!\nWaiting for upload port...\nUpload port found on newport\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe\" -i -d --port=newport -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
525+
},
526+
},
505527
{
506528
Fqbn: "arduino:samd:mkr1000",
507529
UploadPort: "/dev/ttyACM999",

0 commit comments

Comments
 (0)