Skip to content
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

Recovery of soft bricked native USB boards w/o double-tap impossible without port selection #2089

Closed
3 tasks done
per1234 opened this issue Jun 6, 2023 · 0 comments · Fixed by #2090
Closed
3 tasks done
Assignees
Labels
conclusion: resolved Issue was resolved topic: CLI Related to Arduino CLI topic: code Related to content of the project itself type: imperfection Perceived defect in any part of project

Comments

@per1234
Copy link
Contributor

per1234 commented Jun 6, 2023

Describe the problem

The primary microcontrollers of many Arduino boards have USB capabilities (e.g., Leonardo, Micro, MKR). These boards communicate directly between the primary microcontroller and PC rather than having a separate "bridge" interface chip that provides the USB capability needed to communicate with the computer (as is the case with the boards like Uno and Mega).

Because the USB capabilities are implemented as part of the same program as the user's sketch code on these "native USB" boards, it is possible for the user's code to disable, interfere with, or break the USB communication with the computer. This is a common occurrence that should be expected as part of the experience of developing firmware for this type of board. That may be the expected outcome (e.g., putting the microcontroller to sleep) or an unintended result of a bug. When this happens, the board no longer produces a USB CDC serial port. This can make it difficult to upload to the board since that port is used in the upload process (e.g., "1200 bps touch").

In order to facilitate the recovery from this "soft bricked" state, some bootloaders have a feature where they run indefinitely on the second of two resets in quick succession (sometimes referred to as "double-tap"). However, not all bootloaders have this capability. On the bootloaders without support for the "double-tap" mode, the bootloader runs for only a short time after a reset before timing out and exiting to the application. In this case it is necessary for the user to time the manual reset so that the upload process occurs while the bootloader is running. Since Arduino IDE compiles the sketch before initiating the actual upload process, this is a bit tricky since the bootloader might time out during the compilation phase if the reset was done before starting the operation.

The standard recovery procedure for these boards, as documented here, is:

  1. Click the "Upload" button in Arduino IDE.
  2. Watch the "Output" view until you see the text that indicates the compilation step of the upload operation is complete.
  3. Immediately manually reset the board.

This procedure works fine in Arduino IDE 1.x because the "wait for upload port" phase is triggered even when no port is selected. The appearance of the port produced by the bootloader running after the manual reset is detected during that phase and that port is automatically used for the upload. However, that "wait for upload port" phase is skipped entirely when attempting to perform the procedure in Arduino IDE, causing the upload to fail with a "no upload port provided" error.

The only way for Arduino IDE 2.x users to recover their boards is via the modified procedure:

  1. Select any arbitrary port from the Arduino IDE Tools > Port menu.
  2. Click the "Upload" button.
  3. Watch the "Output" view until you see the text that indicates the compilation step of the upload operation is complete.
  4. Immediately manually reset the board.

Some users may not have an available port to use for the workaround, and even for those who do have a port this undocumented procedure is very unintuitive and hacky.

The final recourse would be to do a "Burn Bootloader" operation, not because there is any need to re-flash the bootloader, but because the operation also erases the problematic sketch application from the board. However, that is very complicated for the average user and also requires additional hardware they might not possess.

🐛 It is difficult or impossible for users to recover boards from a "soft bricked" state.

To reproduce

Equipment

Native USB board that uses a bootloader without "double-tap" support:

Steps

  1. "Soft brick" your board by uploading this sketch:
    ⚠ This will put the board into a state that is slightly difficult to recover from.
    void setup() {
      noInterrupts();
    }
    void loop() {}
  2. Upload any sketch to the board without having a port selected.
  3. Watch the "Output" view until you see the memory usage report that indicates the compilation step is finished.
    The report has this form:
    Sketch uses 3464 bytes (12%) of program storage space. Maximum is 28672 bytes.
    Global variables use 149 bytes (5%) of dynamic memory, leaving 2411 bytes for local variables. Maximum is 2560 bytes.
    
  4. Immediately press and release the reset button on the board.

🐛 The upload fails:

Error during Upload: Failed uploading: no upload port provided

Expected behavior

It is possible for users to easily recover their boards from the "soft brick" state by following the standard recovery procedure.

Arduino IDE version

e47fb2e

Operating system

All

Operating system version

Any

Additional context

A change was made to Arduino CLI to allow uploading to these boards without specifying a port as is required to perform the recovery procedure:

arduino/arduino-cli#2173

That change is introduced into Arduino IDE by #2083. However, the upload still fails when performing the restoration procedure in Arduino IDE even with the updated Arduino CLI.

The reason is that Arduino CLI uses a null value for the port field of the cc.arduino.cli.commands.v1.Upload request as the condition:

https://github.com/arduino/arduino-cli/blob/0.33.0/commands/upload/upload.go#L198

while Arduino IDE sets the port field to an empty object when an upload is done without a port selected:

2023-06-06 00:32:40 2023-06-06T07:32:40.884Z daemon INFO 107 CALLED: /cc.arduino.cli.commands.v1.ArduinoCoreService/Upload STREAM_RESP

2023-06-06 00:32:40 2023-06-06T07:32:40.885Z daemon INFO 107 |  REQ:  {
107 |    "instance": {
107 |      "id": 1
107 |    },
107 |    "fqbn": "arduino:avr:leonardo",
107 |    "sketch_path": "c:\\Users\\per\\Documents\\Arduino\\arduino_arduino-ide_2083\\RecoverSoftBrickedBoard",
107 |    "port": {},
107 |    "verbose": true
107 |  }

Originally reported at https://forum.arduino.cc/t/ide-2-0-wont-program-arduinos-that-need-to-be-put-into-bootloader-mode/1044198

Additional reports

Related

Issue checklist

  • I searched for previous reports in the issue tracker
  • I verified the problem still occurs when using the latest nightly build
  • My report contains all necessary details
@per1234 per1234 added topic: code Related to content of the project itself type: imperfection Perceived defect in any part of project topic: CLI Related to Arduino CLI labels Jun 6, 2023
@kittaakos kittaakos self-assigned this Jun 6, 2023
kittaakos pushed a commit that referenced this issue Jun 6, 2023
Previously, if the `port` was not set in IDE2, the compile request
object has been created with an empty port object (`{}`). From now on,
if the port is not specified, IDE2 will create a compile request with
the default `null` `port` value.

Closes #2089

Signed-off-by: Akos Kitta <[email protected]>
kittaakos pushed a commit that referenced this issue Jun 6, 2023
Previously, if the `port` was not set in IDE2, the compile request
object has been created with an empty port object (`{}`). From now on,
if the port is not specified, IDE2 will create a compile request with
the default `null` `port` value.

Closes #2089

Signed-off-by: Akos Kitta <[email protected]>
@per1234 per1234 added the conclusion: resolved Issue was resolved label Jun 6, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
conclusion: resolved Issue was resolved topic: CLI Related to Arduino CLI topic: code Related to content of the project itself type: imperfection Perceived defect in any part of project
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants