No Serial Port After Flashing Leonardo on Linux
I have an Arduino Leonardo and I have not been able to get it to run a tinygo program successfully.
I'm using arch-based Manjaro linux.
After lots of trial and error, I can build the project with tinygo and flash it with the latest source build of avrdude using the new -r flag to send a reset using 1200 baud.
No matter what I do, after a successful flash of the tinygo binary, the arduino serial port is gone and I can never get it back. I have used the reset button, I have unplugged/replugged the device, I have rebooted, but the serial port ttyACM0 never comes back.
The only thing I can do is re-flash it with a C++ hex. I can do this using the same avrdude command (with a different hex path) while pressing the reset button. This is what leads me to believe it's a tinygo issue and not an avrdude/flash issue
Not sure what to do at this point.
The tinygo code is:
//go:build arduino_leonardo
package main
import (
"machine"
"time"
)
// Take input from a machine pin
func main() {
button := machine.D2
button.Configure(machine.PinConfig{Mode: machine.PinInput})
for {
if button.Get() {
println("button ^") // pew pew pew!
} else {
println("button v")
}
time.Sleep(time.Millisecond * 10)
}
}
The build command:
tinygo build -o=./main.hex -target=arduino-leonardo -tags "avr baremetal linux arm atmega32u4 avr5 arduino_leonardo tinygo math_big_pure_go gc.conservative scheduler.none serial.none"
The avrdude flash output:
/usr/local/bin/avrdude -v -V -p m32u4 -c avr109 -P "/dev/ttyACM0" -D -U "flash:w:/home/jonathan/data/tinygotest/main.hex:i" -r ✔
avrdude: Version 7.2-20240104 (03d786e8)
Copyright the AVRDUDE authors;
see https://github.com/avrdudes/avrdude/blob/main/AUTHORS
System wide configuration file is /usr/local/etc/avrdude.conf
User configuration file is /home/$USER/.avrduderc
User configuration file does not exist or is not a regular file, skipping
avrdude: touching serial port /dev/ttyACM0 at 1200 baud
avrdude: waiting for new port...
avrdude: new port /dev/ttyACM0 discovered
750 ms: using new port /dev/ttyACM0
Using port : /dev/ttyACM0
Using programmer : avr109
AVR Part : ATmega32U4
Programming modes : ISP, HVPP, JTAG, SPM
Programmer Type : butterfly
Description : Atmel for bootloader using AppNote AVR109
connecting to programmer: .
Programmer id = CATERIN; type = S
Software version = 1.0; no hardware version given
programmer supports auto addr increment
programmer supports buffered memory access with buffersize=128 bytes
avrdude: devcode selected: 0x44
avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1e9587 (probably m32u4)
avrdude: processing -U flash:w:/home/$USER/data/tinygotest/main.hex:i
avrdude: reading input file /home/$USER/data/tinygotest/main.hex for flash
with 768 bytes in 1 section within [0, 0x2ff]
using 6 pages and 0 pad bytes
avrdude: writing 768 bytes flash ...
Writing | ################################################## | 100% 0.06 s
avrdude: 768 bytes of flash written
avrdude done. Thank you.
$ tinygo env
GOOS="linux"
GOARCH="amd64"
GOROOT="/usr/local/go"
GOPATH="/home/$USER/go"
GOCACHE="/home/$USER/.cache/tinygo"
CGO_ENABLED="1"
TINYGOROOT="/usr/lib/tinygo"
It's probably the same issue as the following. The reason is that TinyGo does not have an implementation for USB Device of ATmega32u4 .
https://x.com/nobonobo/status/1723857164941336854?s=20
After some searching, I discovered that the tinyogo src for the leonardo board uses a NullSerial for machine.Serial, however, the Leonardo uses a virtual CDC (unlike other arduinos). Maybe the leonardo need the ability to compile with -serial=usb ?
I'm not sure how to get that to work though.
Here are some excerpts from: https://docs.arduino.cc/retired/getting-started-guides/ArduinoLeonardoMicro
Serial re-enumeration on reset. Since the boards do not have a dedicated chip to handle serial communication, it means that the serial port is virtual -- it's a software routine, both on your operating system, and on the board itself. Just as your computer creates an instance of the serial port driver when you plug in any Arduino, the Leonardo/Micro creates a serial instance whenever it runs its bootloader. The board is an instance of USB's Connected Device Class (CDC) driver.
This means that every time you reset the board, the USB serial connection will be broken and re-established. The board will disappear from the list of serial ports, and the list will re-enumerate. Any program that has an open serial connection to the Leonardo will lose its connection. This is in contrast to the Arduino Uno, with which you can reset the main processor (the ATmega328P) without closing the USB connection (which is maintained by the secondary ATmega8U2 or ATmega16U2 processor). This difference has implications for driver installation, uploading, and communication; these are discussed below.
@sago35 I think we came to the same conclusion. There's no serial usb support in tinygo for the ATmega32u4, which basically means Leonardo support doesn't work in tinygo.
There's some CDC stuff in the Arduino core code, but I don't know enough about C++ or how tinygo implements the CDC stuff to be able to PR this or anything.
for reference: https://github.com/arduino/ArduinoCore-avr/blob/63092126a406402022f943ac048fa195ed7e944b/cores/arduino/USBCore.cpp#L73
Basically, you would need to create an ATmega32u4 version of the following source code. I don't have an ATmega32u4, so it would be difficult for me to work on this.
https://github.com/tinygo-org/tinygo/blob/v0.30.0/src/machine/machine_rp2040_usb.go
Yeah, that's a little beyond my comprehension of how the board works.
I don't have an ATmega32u4, so it would be difficult for me to work on this.
I could send you one ;)