Skip to content

Easier recovery from soft bricked native USB boards #2173

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions arduino/serialutils/serialutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ func Reset(portToTouch string, wait bool, cb *ResetProgressCallbacks, dryRun boo
}
if strings.HasSuffix(emulatedPort, "999") {
emulatedPort += "0"
} else if emulatedPort == "" {
emulatedPort = "newport"
}
return res, nil
}
Expand Down
24 changes: 20 additions & 4 deletions commands/upload/upload.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,10 @@ func runProgramAction(pme *packagemanager.Explorer,
if burnBootloader && programmerID == "" {
return &arduino.MissingProgrammerError{}
}

if port == nil {
// For no-port uploads use "default" protocol
port = &rpc.Port{Protocol: "default"}
}
logrus.WithField("port", port).Tracef("Upload port")

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

// Force port wait to make easier to unbrick boards like the Arduino Leonardo, or similar with native USB,
// when a sketch causes a crash and the native USB serial port is lost.
// See https://github.com/arduino/arduino-cli/issues/1943 for the details.
//
// In order to trigger the forced serial-port-wait the following conditions must be met:
// - No upload port specified (protocol == "default")
// - "upload.wait_for_upload_port" == true (developers requested the touch + port wait)
// - "upload.tool.serial" not defained, or
// "upload.tool.serial" is the same as "upload.tool.default"
forcedSerialPortWait := port.Protocol == "default" && // this is the value when no port is specified
uploadProperties.GetBoolean("upload.wait_for_upload_port") &&
(!uploadProperties.ContainsKey("upload.tool.serial") ||
uploadProperties.Get("upload.tool.serial") == uploadProperties.Get("upload.tool.default"))

// If not using programmer perform some action required
// to set the board in bootloader mode
actualPort := port
if programmer == nil && !burnBootloader && port.Protocol == "serial" {

if programmer == nil && !burnBootloader && (port.Protocol == "serial" || forcedSerialPortWait) {
// Perform reset via 1200bps touch if requested and wait for upload port also if requested.
touch := uploadProperties.GetBoolean("upload.use_1200bps_touch")
wait := false
Expand Down Expand Up @@ -425,7 +441,7 @@ func runProgramAction(pme *packagemanager.Explorer,
if actualPort.Address != "" {
// Set serial port property
uploadProperties.Set("serial.port", actualPort.Address)
if actualPort.Protocol == "serial" {
if actualPort.Protocol == "serial" || actualPort.Protocol == "default" {
// This must be done only for serial ports
portFile := strings.TrimPrefix(actualPort.Address, "/dev/")
uploadProperties.Set("serial.port.file", portFile)
Expand Down
22 changes: 22 additions & 0 deletions internal/integrationtest/upload_mock/upload_mock_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,12 +161,24 @@ func TestUploadSketch(t *testing.T) {
Programmer: "",
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",
},
{
Fqbn: "arduino:avr:leonardo",
UploadPort: "",
Programmer: "",
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",
},
{
Fqbn: "arduino:avr:micro",
UploadPort: "/dev/ttyACM999",
Programmer: "",
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",
},
{
Fqbn: "arduino:avr:micro",
UploadPort: "",
Programmer: "",
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",
},
{
Fqbn: "arduino:avr:circuitplay32u4cat",
UploadPort: "/dev/ttyACM999",
Expand Down Expand Up @@ -502,6 +514,16 @@ func TestUploadSketch(t *testing.T) {
"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",
},
},
{
Fqbn: "arduino:samd:mkr1000",
UploadPort: "",
Programmer: "",
Output: map[string]string{
"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",
"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",
"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",
},
},
{
Fqbn: "arduino:samd:mkr1000",
UploadPort: "/dev/ttyACM999",
Expand Down