Description
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:
- Click the "Upload" button in Arduino IDE.
- Watch the "Output" view until you see the text that indicates the compilation step of the upload operation is complete.
- 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:
- Select any arbitrary port from the Arduino IDE Tools > Port menu.
- Click the "Upload" button.
- Watch the "Output" view until you see the text that indicates the compilation step of the upload operation is complete.
- 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:
- Leonardo
- Micro
- Yun
- I would guess any of the other boards that use Arduino's "caterina" bootloader, but I haven't checked others.
Steps
- "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() {}
- Upload any sketch to the board without having a port selected.
- 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.
- 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
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:
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
- Recovery of soft bricked native USB boards w/o double-tap impossible without port selection arduino-cli#1943 / Easier recovery from soft bricked native USB boards arduino-cli#2173
- Interpret "empty" gRPC Port object as no-port in upload arduino-cli#2202
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