a9183756-gh / Arduino-CMake-Toolchain

CMake toolchain for all Arduino compatible boards
MIT License
135 stars 40 forks source link

Arduino Due upload failure: No device found on ... #33

Open RobertWilbrandt opened 4 years ago

RobertWilbrandt commented 4 years ago

As discussed at the end of #25, the arduino due currently suffers from a problem in the uploading stage (carrying this over to this issue for better overview, sorry for the long delay):

$ cmake --build . --target upload -- TARGET=hello_world SERIAL_PORT_FILE=ttyACM0          
[100%] Uploading
[  3%] Built target _arduino_lib_core_vobjects_
[ 90%] Built target _arduino_lib_core_cobjects_
[ 93%] Built target _arduino_lib_core
[100%] Built target hello_world
Send auto-baud
Set binary mode
No device found on ttyACM0
CMake Error at .scripts/upload.cmake:374 (message):
  *** upload failed!

This is caused by a missing 1200bps reset in this toolchain. A current workaround on linux systems is to use

stty -F /dev/ttyACM0 speed 1200 && cmake --build . --target upload -- TARGET=hello_world SERIAL_PORT_FILE=ttyACM0
a9183756-gh commented 4 years ago

As a workaround to be usable from any IDE, you can modify platform.txt (e.g. path => ~/.arduino15/packages/arduino/hardware/sam/1.6.12/platform.txt) to include stty as well, like shown below.

tools.bossac.upload.pattern=bash -c "stty -F /dev/{serial.port.file} speed 1200 && {path}/{cmd} {upload.verbose} --port={serial.port.file} -U {upload.native_usb} -e -w {upload.verify} -b {build.path}/{build.project_name}.bin -R"

With this workaround, the follow points are to be noted.

  1. Intermediate quotes are removed in the above upload pattern, otherwise which it will give errors due to the way Arduino quoting works. Hopefully the paths that you use do not contain space.
  2. Arduino IDE will give error when uploading. Need to switch back to original pattern before using Arduino IDE.

Will plan to include the feature as part of serial monitor feature. May be in 1.2 release target.

gibwar commented 3 years ago

Just wanted to add to this for helping the Windows side of things. I'm working on a PR to add basic support for the official arduino-cli project. In covering my bases, I wanted to confirm that the upload facility worked in that scenario too. Here are my findings that we may be able to use for a partial Windows-based solution.

In trying to upload the program directly through CMake, targeting COM3, the process would hang indefinitely after build, and pressing Ctrl+C shows some scrambled output but never succeeds. I confirmed that the arduino-cli program could build the same program and upload it successfully, and looking at the verbose output I saw the trigger before running the bossac command.

Looking at the repository, I found their serialutils.go file and saw how they reset it before running bossac. (It was recently refactored in to its own file, the current stable version had it intermingled in upload.go.)

Windows PowerShell 5 and PowerShell Core 7 are able to access the full .Net libraries on the system, which includes access to the SerialPort API. All modern versions of Windows that these tools support should have PowerShell v5 preinstalled. I've confirmed the following snippet works fine in putting my Arduino Nano 33 IoT in to bootloader mode:

$port = new-object System.IO.Ports.SerialPort COM3,1200
$port.Open()
$port.DtrEnable=$false
$port.Close()

Putting it in one line that CMake may be able to execute would look like:

powershell.exe -NoProfile -Command "$port = new-object System.IO.Ports.SerialPort COM3,1200;$port.Open();$port.DtrEnable=$false;$port.Close()"

However, on Windows I observed that, for the upload from CMake to work, I needed to target the new COM port it uses to upload (shows up as a new COM port and goes back after upload succeeds):

$ cmake --build . --target upload -- TARGET=morse SERIAL_PORT_FILE=COM4
[100%] Uploading
[ 88%] Built target _arduino_lib_core_cobjects_
[ 91%] Built target _arduino_lib_core_vobjects_
[ 94%] Built target _arduino_lib_core
[100%] Built target morse
Set binary mode
readWord(addr=0)=0x20007ffc
...

We should be able to write the same "new port" detection loop in PowerShell as well, which I am willing to help look in to if this is a viable solution.


I also confirmed that the above trick also works in WSL1 running Debian Buster, though the same COM3->COM4 change is observed. WSL2 won't work since the VM it runs in currently cannot access the COM ports of the host. It also had to be run under sudo because of the default permissions WSL has on the device files crw-rw---- 1 root dialout 4, 67 Dec 1 22:57 /dev/ttyS3, though I could add my user to dialout if I was going to use WSL long term)

$ stty -F /dev/ttyS3 speed 1200 && make upload TARGET=morse SERIAL_PORT_FILE=/dev/ttyS4
115200
[100%] Uploading
[ 88%] Built target _arduino_lib_core_cobjects_
[ 91%] Built target _arduino_lib_core_vobjects_
[ 94%] Built target _arduino_lib_core
[100%] Built target morse
Set binary mode
readWord(addr=0)=0x20007ffc
...