Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

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

Flashing an Arduino Leonardo with AVRDUDE is troublesome #788

Closed
kristofmulier opened this issue Dec 29, 2021 · 51 comments
Closed

Flashing an Arduino Leonardo with AVRDUDE is troublesome #788

kristofmulier opened this issue Dec 29, 2021 · 51 comments
Labels
documentation Improvements or additions to documentation

Comments

@kristofmulier
Copy link
Contributor

kristofmulier commented Dec 29, 2021

The ATmega32u4 microcontroller is present on a couple of Arduino boards, such as the Arduino Leonardo and Arduino Micro. The flash procedure for these boards is quite complicated. I'll first review how it works precisely, then I'll explain why this is a problem for many users of AVRDUDE. Finally we can look into potential solutions.

1. The flash procedure explained

Unlike others, the Arduino Leonardo and Arduino Micro boards identify themselves through one port (eg. COM9) while you need to flash them through another (eg. COM10) which is only available for a couple of seconds just after a reset. I observed how the Arduino IDE deals with this case:

  1. Open the serial port through which the board has identified itself (eg. COM9) at baudrate 1200 and close it immediately thereafter. This basically triggers a board reset.

  2. Observe the serial ports from the OS (Windows/Linux). As soon as the board has completed the reset, it should present itself with the serial port for flashing (eg. COM10). Store that port name and go on to the next step.

  3. Flash the firmware through the new port (eg. COM10) with AVRDUDE. Do it quickly, because this serial port is only active for a couple of seconds.

Arduino IDE does it this way. PlatformIO also.

 

2. What is the problem?

The flash procedure explained above consists of three steps. I know how to put the third step in a makefile, but I have no idea how to implement the first two.

I could just hardcode the first two steps in Embeetle IDE and run them behind the scenes before launching the third step. I actually just did that, and it works. But it feels wrong. At Embeetle, we have the desire to keep our users informed and free. In other words: if one of our users decides to work on a project outside Embeetle IDE, he/she is free to do so. We achieve that in two ways:

  • All Embeetle projects are makefile-based. The user simply needs to invoke clean, build and flash targets to do all the magic.

  • We provide a makefile to each sample project our users can download, but it is not touched thereafter. The makefile is well-explained, with plenty of comments.

Hardcoding (part of) the flash procedure in the IDE itself defeats this goal. The user cannot run his project outside our IDE anymore.

 

3. Potential solutions

I see two solutions to this dilemma:

  1. We find a way to implement the first two steps in the makefile anyhow. I looked into this with my colleague Johan - who is a true makefile wizard - but we couldn't figure it out. If you have an idea, please let me know.

  2. We improve the AVRDUDE software such that it can handle this particular situation.

I believe the second solution is the cleanest and will help most AVRDUDE users - also those that have nothing to do with Embeetle IDE. I would love to help with the implementation, but I'm afraid I need a little help and guidance, as I'm not familiar with the source code.

Kind regards,
Kristof Mulier

@dl8dtl dl8dtl added enhancement New feature or request question Further information is requested labels Dec 29, 2021
@dl8dtl
Copy link
Contributor

dl8dtl commented Dec 29, 2021

The way the second device comes up is very OS-specific. I'd like to avoid that kind of OS hacks in AVRDUDE itself, as it opens a can of worms. So far, AVRDUDE suffers only from very few (low-level) things that are really OS specific, as for most of the required abstractions, it can sit on top of the respective backend libraries (libusb, hidapi and such).
Ideally, there ought to be a kind of OS service you can attach to that tells you when a new device arrives. You can then write a script that does:

  • register at that OS service
  • issue a reset
  • wait until the new device came up though that OS service
  • start AVRDUDE on it

Obviously, that script is inherently OS specific.

@kristofmulier
Copy link
Contributor Author

kristofmulier commented Dec 30, 2021

Hi @dl8dtl ,

You basically suggest to defer the first two steps (1. resetting device and 2. waiting for it to return with a new serial port) to an OS-specific script outside AVRDUDE. A good idea, as this keeps AVRDUDE clean from OS-specific stuff.

A few questions come to my mind:

  • In what language should the script be written?
    Personally, I think it should be a script that just runs on the user's computer without requiring anything in particular to be installed. Therefore, I would not do it in Python. Perhaps a shell script? I suppose it's doable in a Linux shell script, but quite horrific to achieve in a Windows .bat file. What about doing it in a small, separate little C program?

  • How will this script be distributed with AVRDUDE?
    The typical AVRDUDE installation on Linux is very clean right now - just two files:

    📁 avrdude_6.3.0
    ├─ 📁 bin
    │  └─ avrdude
    └─ 📁 etc
       └─ avrdude.conf
    

    Maybe the script should be added in the bin/ folder. Or an extra folder scripts/ should be introduced?

  • How will the script be invoked?
    I suppose AVRDUDE should invoke the script in the first place. Eventually, the script invokes AVRDUDE again in the end (see step 3 in the flash procedure). This way, the user doesn't even realize the first two steps are being deferred to a script outside AVRDUDE. Looks like the best user-experience to me.

Kind regards,
Kristof

@mariusgreuel
Copy link
Contributor

Hi Kristof,

while I agree that it would be a nice addition to AVRDUDE, it is not quite trivial to do this cross-platform. I did this for Windows, check out
https://github.com/mariusgreuel/avrdude

The code for doing the auto-reset is here, it is just about 1k lines of non-portable code:
https://github.com/mariusgreuel/avrdude/blob/windows/src/msvc/usb_com_locator.h

@kristofmulier
Copy link
Contributor Author

Hi @mariusgreuel ,
It's awesome you already did it for Windows! That means most of the work is already done. Usually such things are much harder to achieve on Windows than on Linux.

@dl8dtl
Copy link
Contributor

dl8dtl commented Dec 30, 2021

it is just about 1k lines of non-portable code

Puh. I'm not sure whether I'd like to have that in a supposed-to-be portable application.

@mariusgreuel mariusgreuel changed the title Flashing the ATmega32u4 with AVRDUDE is troublesome Flashing an Arduino Leonardo with AVRDUDE is troublesome Jan 11, 2022
@MCUdude
Copy link
Collaborator

MCUdude commented Mar 21, 2022

As a compromise, would it be an idea to create a separate "1200 bps touch" handler that would contain all the non-portable code one could call along with avrdude?

The boards I know of that are currently "impossible" to flash directly using Avrdude because of this is the Arduino Leonardo, Arduino Micro/Pro Micro, and the Arduino Nano Every.

I believe making this work on Windows is the most difficult part, but @mariusgreuel has already figured out this part. At least on my mac, the serial port always has the same name after a disconnect. The only time the name changes is when I use a different USB port.

The command below is just to illustrate what I mean. The idea1200bps_touch returns the serial port that "appears" after disconnecting at 1200 baud, and that the output is passed to avrdude as an argument. Clearly not that elegant, but it would be nice to have something we can utilize (except for uploading through Arduino IDE) when working with a board that requires this logic to work.

1200bps_touch -P /dev/cu.usbmodem14101 | xargs avrdude -Cavrdude.conf -cjtag2updi -patmega4809 -b115200

Here's the python based logic PlatformIO uses:

        before_ports = get_serial_ports()

        if upload_options.get("use_1200bps_touch", False):
            env.TouchSerialPort("$UPLOAD_PORT", 1200)

        if upload_options.get("wait_for_upload_port", False):
            env.Replace(UPLOAD_PORT=env.WaitForNewSerialPort(before_ports))


def TouchSerialPort(env, port, baudrate):
    port = env.subst(port)
    print("Forcing reset using %dbps open/close on port %s" % (baudrate, port))
    try:
        s = Serial(port=port, baudrate=baudrate)
        s.setDTR(False)
        s.close()
    except:  # pylint: disable=bare-except
        pass
    sleep(0.4)  # DO NOT REMOVE THAT (required by SAM-BA based boards)


def WaitForNewSerialPort(env, before):
    print("Waiting for the new upload port...")
    prev_port = env.subst("$UPLOAD_PORT")
    new_port = None
    elapsed = 0
    before = [p["port"] for p in before]
    while elapsed < 5 and new_port is None:
        now = [p["port"] for p in util.get_serial_ports()]
        for p in now:
            if p not in before:
                new_port = p
                break
        before = now
        sleep(0.25)
        elapsed += 0.25

    if not new_port:
        for p in now:
            if prev_port == p:
                new_port = p
                break

    try:
        s = Serial(new_port)
        s.close()
    except SerialException:
        sleep(1)

    if not new_port:
        sys.stderr.write(
            "Error: Couldn't find a board on the selected port. "
            "Check that you have the correct port selected. "
            "If it is correct, try pressing the board's reset "
            "button after initiating the upload.\n"
        )
        env.Exit(1)

    return new_port

@mcuee
Copy link
Collaborator

mcuee commented May 9, 2022

The boards I know of that are currently "impossible" to flash directly using Avrdude because of this is the Arduino Leonardo, Arduino Micro/Pro Micro, and the Arduino Nano Every.

I have the Arduino Leonardo and I am getting the Arduino Pro Micro and Arduino Nano Every soon. So this is interesting.

@mcuee
Copy link
Collaborator

mcuee commented May 30, 2022

This is what Arduino is doing: run log under Windows with a clone Pro Micro with ATmega32U4.

Forcing reset using 1200bps open/close on port COM18
PORTS {COM18, } / {} => {}
PORTS {} / {} => {}
PORTS {} / {COM8, } => {COM8, }
Found upload port: COM8
C:\Users\xiaof\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17/bin/avrdude -CC:\Users\xiaof\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17/etc/avrdude.conf -v -patmega32u4 -cavr109 -PCOM8 -b57600 -D -Uflash:w:C:\Users\xiaof\AppData\Local\Temp\arduino_build_628741/Blink_Every.ino.hex:i 

avrdude: Version 6.3-20190619
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "C:\Users\xiaof\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17/etc/avrdude.conf"

         Using Port                    : COM8
         Using Programmer              : avr109
         Overriding Baud Rate          : 57600
         AVR Part                      : ATmega32U4
         Chip Erase delay              : 9000 us
         PAGEL                         : PD7
         BS2                           : PA0
         RESET disposition             : dedicated
         RETRY pulse                   : SCK
         serial program mode           : yes
         parallel program mode         : yes
         Timeout                       : 200
         StabDelay                     : 100
         CmdexeDelay                   : 25
         SyncLoops                     : 32
         ByteDelay                     : 0
         PollIndex                     : 3
         PollValue                     : 0x53
         Memory Detail                 :

                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           eeprom        65    20     4    0 no       1024    4      0  9000  9000 0x00 0x00
           flash         65     6   128    0 yes     32768  128    256  4500  4500 0x00 0x00
           lfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           hfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           efuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           lock           0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
           signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

         Programmer Type : butterfly
         Description     : Atmel AppNote AVR109 Boot Loader

Connecting to programmer: .
Found 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.

Programmer supports the following devices:
    Device code: 0x44

avrdude: devcode selected: 0x44
avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% -0.00s

avrdude: Device signature = 0x1e9587 (probably m32u4)
avrdude: reading input file "C:\Users\xiaof\AppData\Local\Temp\arduino_build_628741/Blink_Every.ino.hex"
avrdude: writing flash (3956 bytes):

Writing | ################################################## | 100% 0.31s

avrdude: 3956 bytes of flash written
avrdude: verifying flash memory against C:\Users\xiaof\AppData\Local\Temp\arduino_build_628741/Blink_Every.ino.hex:
avrdude: load data flash data from input file C:\Users\xiaof\AppData\Local\Temp\arduino_build_628741/Blink_Every.ino.hex:
avrdude: input file C:\Users\xiaof\AppData\Local\Temp\arduino_build_628741/Blink_Every.ino.hex contains 3956 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.05s

avrdude: verifying ...
avrdude: 3956 bytes of flash verified

avrdude done.  Thank you.

@mcuee
Copy link
Collaborator

mcuee commented May 30, 2022

Ref: https://www.avrfreaks.net/forum/uploading-code-new-arduino-nano-every
Trick under Windows using a batch file to use with Arduino Nano Every.

mode %COMPORT% baud=12 dtr=on > nul
mode %COMPORT% baud=12 dtr=off > nul

More details here:

@mcuee
Copy link
Collaborator

mcuee commented May 30, 2022

@mariusgreuel I tried your branch ( https://github.com/mariusgreuel/avrdude) and it seems to work for me for the Pro Micro clone.

Run log with a Pro Micro clone.

PS C:\work\avr\avrdude_test\avrdude_win\out\build\x64-Debug\src\Debug> .\avrdude.exe -patmega32u4 -c avr109 -PCOM14 -v

avrdude.exe: Version 7.0
             Copyright (c) Brian Dean, http://www.bdmicro.com/
             Copyright (c) Joerg Wunsch

             System wide configuration file is "C:/work/avr/avrdude_test/avrdude_win/out/build/x64-Debug/src/Debug/avrdude.conf"

             Using Port                    : COM14
             Using Programmer              : avr109
avrdude.exe: Found device at port 'COM14'
avrdude.exe: Entering bootloader mode...
avrdude.exe: Found device at port 'COM10'
             AVR Part                      : ATmega32U4
             Chip Erase delay              : 9000 us
             PAGEL                         : PD7
             BS2                           : PA0
             RESET disposition             : dedicated
             RETRY pulse                   : SCK
             Serial program mode           : yes
             Parallel program mode         : yes
             Timeout                       : 200
             StabDelay                     : 100
             CmdexeDelay                   : 25
             SyncLoops                     : 32
             PollIndex                     : 3
             PollValue                     : 0x53
             Memory Detail                 :

                                               Block Poll               Page                       Polled
               Memory Type Alias    Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
               ----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
               eeprom                 65    20     4    0 no       1024    4      0  9000  9000 0x00 0x00
               flash                  65     6   128    0 yes     32768  128    256  4500  4500 0x00 0x00
               lfuse                   0     0     0    0 no          1    1      0  9000  9000 0x00 0x00
               hfuse                   0     0     0    0 no          1    1      0  9000  9000 0x00 0x00
               efuse                   0     0     0    0 no          1    1      0  9000  9000 0x00 0x00
               lock                    0     0     0    0 no          1    1      0  9000  9000 0x00 0x00
               calibration             0     0     0    0 no          1    1      0     0     0 0x00 0x00
               signature               0     0     0    0 no          3    1      0     0     0 0x00 0x00

             Programmer Type : butterfly
             Description     : Atmel AppNote AVR109 Boot Loader

Connecting to programmer: .
Found 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.

Programmer supports the following devices:
    Device code: 0x44

avrdude.exe: devcode selected: 0x44
avrdude.exe: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude.exe: Device signature = 0x1e9587 (probably m32u4)

avrdude.exe done.  Thank you.

@mcuee
Copy link
Collaborator

mcuee commented May 30, 2022

@mariusgreuel I tried your branch ( https://github.com/mariusgreuel/avrdude) under Windows but somehow it does not work for my official Arduino Leonardo as it stuck there forever.

PS C:\work\avr\avrdude_test\avrdude_win\out\build\x64-Debug\src\Debug> .\avrdude.exe -patmega32u4 -c avr109 -PCOM14 -vvvv
executable_abspath = C:/work/avr/avrdude_test/avrdude_win/out/build/x64-Debug/src/Debug/avrdude.exe
executable_abspath_len = 78
executable_dirpath = C:/work/avr/avrdude_test/avrdude_win/out/build/x64-Debug/src/Debug
executable_dirpath_len = 66
sys_config = C:/work/avr/avrdude_test/avrdude_win/out/build/x64-Debug/src/Debug/avrdude.conf
sys_config_found = true


avrdude.exe: Version 7.0
             Copyright (c) Brian Dean, http://www.bdmicro.com/
             Copyright (c) Joerg Wunsch

             System wide configuration file is "C:/work/avr/avrdude_test/avrdude_win/out/build/x64-Debug/src/Debug/avrdude.conf"

             Using Port                    : COM14
             Using Programmer              : avr109
avrdude.exe: Found device at port 'COM14'
avrdude.exe: - InstanceId: USB\VID_2341&PID_8036&MI_00\6&22A06EED&0&0000
avrdude.exe: - Port: COM14
avrdude.exe: - Location: Port_#0001.Hub_#0002
avrdude.exe: - ProductName: Arduino Leonardo
avrdude.exe: - IsPresent: true
avrdude.exe: - IsCompositeDevice: true
avrdude.exe: Entering bootloader mode... 
(stuck here even after WIndows changes to COM15)

It does work under Arduino.

Forcing reset using 1200bps open/close on port COM14
PORTS {COM14, } / {} => {}
PORTS {} / {COM15, } => {COM15, }
Found upload port: COM15
C:\Users\xiaof\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17/bin/avrdude -CC:\Users\xiaof\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17/etc/avrdude.conf -v -patmega32u4 -cavr109 -PCOM15 -b57600 -D -Uflash:w:C:\Users\xiaof\AppData\Local\Temp\arduino_build_926279/Blink_Every.ino.hex:i 

avrdude: Version 6.3-20190619
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "C:\Users\xiaof\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17/etc/avrdude.conf"

         Using Port                    : COM15
         Using Programmer              : avr109
         Overriding Baud Rate          : 57600
         AVR Part                      : ATmega32U4
         Chip Erase delay              : 9000 us
         PAGEL                         : PD7
         BS2                           : PA0
         RESET disposition             : dedicated
         RETRY pulse                   : SCK
         serial program mode           : yes
         parallel program mode         : yes
         Timeout                       : 200
         StabDelay                     : 100
         CmdexeDelay                   : 25
         SyncLoops                     : 32
         ByteDelay                     : 0
         PollIndex                     : 3
         PollValue                     : 0x53
         Memory Detail                 :

                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           eeprom        65    20     4    0 no       1024    4      0  9000  9000 0x00 0x00
           flash         65     6   128    0 yes     32768  128    256  4500  4500 0x00 0x00
           lfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           hfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           efuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           lock           0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
           signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

         Programmer Type : butterfly
         Description     : Atmel AppNote AVR109 Boot Loader

Connecting to programmer: .
Found 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.

Programmer supports the following devices:
    Device code: 0x44

avrdude: devcode selected: 0x44
avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% -0.00s

avrdude: Device signature = 0x1e9587 (probably m32u4)
avrdude: reading input file "C:\Users\xiaof\AppData\Local\Temp\arduino_build_926279/Blink_Every.ino.hex"
avrdude: writing flash (3956 bytes):

Writing | ################################################## | 100% 0.31s

avrdude: 3956 bytes of flash written
avrdude: verifying flash memory against C:\Users\xiaof\AppData\Local\Temp\arduino_build_926279/Blink_Every.ino.hex:
avrdude: load data flash data from input file C:\Users\xiaof\AppData\Local\Temp\arduino_build_926279/Blink_Every.ino.hex:
avrdude: input file C:\Users\xiaof\AppData\Local\Temp\arduino_build_926279/Blink_Every.ino.hex contains 3956 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.04s

avrdude: verifying ...
avrdude: 3956 bytes of flash verified

avrdude done.  Thank you.



@mcuee
Copy link
Collaborator

mcuee commented May 30, 2022

@MCUdude It seems that Arduino does more things for Arduino Leonardo than to the Arduino Nano Every. The reason is to switch COM port, that is not necessary for Arduino Nano Every.

But you are right, macOS will not change the serial port number name.

Arduino Nano Every (official version):

Forcing reset using 1200bps open/close on port COM7

Arduino Leonardo (official version)

Forcing reset using 1200bps open/close on port COM18
PORTS {COM18, } / {} => {}
PORTS {} / {} => {}
PORTS {} / {COM8, } => {COM8, }
Found upload port: COM8

@mcuee
Copy link
Collaborator

mcuee commented May 31, 2022

This is Arduino is doing under macOS (Mac Mini M1).

Forcing reset using 1200bps open/close on port /dev/cu.usbmodem2212401
PORTS {/dev/cu.Bluetooth-Incoming-Port, /dev/cu.usbmodem2212401, /dev/cu.wlan-debug, /dev/tty.Bluetooth-Incoming-Port, /dev/tty.usbmodem2212401, /dev/tty.wlan-debug, } / {/dev/cu.Bluetooth-Incoming-Port, /dev/cu.usbmodem2212401, /dev/cu.wlan-debug, /dev/tty.Bluetooth-Incoming-Port, /dev/tty.usbmodem2212401, /dev/tty.wlan-debug, } => {}
PORTS {/dev/cu.Bluetooth-Incoming-Port, /dev/cu.usbmodem2212401, /dev/cu.wlan-debug, /dev/tty.Bluetooth-Incoming-Port, /dev/tty.usbmodem2212401, /dev/tty.wlan-debug, } / {/dev/cu.Bluetooth-Incoming-Port, /dev/cu.usbmodem2212401, /dev/cu.wlan-debug, /dev/tty.Bluetooth-Incoming-Port, /dev/tty.usbmodem2212401, /dev/tty.wlan-debug, } => {}
PORTS {/dev/cu.Bluetooth-Incoming-Port, /dev/cu.usbmodem2212401, /dev/cu.wlan-debug, /dev/tty.Bluetooth-Incoming-Port, /dev/tty.usbmodem2212401, /dev/tty.wlan-debug, } / {/dev/cu.Bluetooth-Incoming-Port, /dev/cu.usbmodem2212401, /dev/cu.wlan-debug, /dev/tty.Bluetooth-Incoming-Port, /dev/tty.usbmodem2212401, /dev/tty.wlan-debug, } => {}
PORTS {/dev/cu.Bluetooth-Incoming-Port, /dev/cu.usbmodem2212401, /dev/cu.wlan-debug, /dev/tty.Bluetooth-Incoming-Port, /dev/tty.usbmodem2212401, /dev/tty.wlan-debug, } / {/dev/cu.Bluetooth-Incoming-Port, /dev/cu.usbmodem2212401, /dev/cu.wlan-debug, /dev/tty.Bluetooth-Incoming-Port, /dev/tty.usbmodem2212401, /dev/tty.wlan-debug, } => {}
PORTS {/dev/cu.Bluetooth-Incoming-Port, /dev/cu.usbmodem2212401, /dev/cu.wlan-debug, /dev/tty.Bluetooth-Incoming-Port, /dev/tty.usbmodem2212401, /dev/tty.wlan-debug, } / {/dev/cu.Bluetooth-Incoming-Port, /dev/cu.usbmodem2212401, /dev/cu.wlan-debug, /dev/tty.Bluetooth-Incoming-Port, /dev/tty.usbmodem2212401, /dev/tty.wlan-debug, } => {}
PORTS {/dev/cu.Bluetooth-Incoming-Port, /dev/cu.usbmodem2212401, /dev/cu.wlan-debug, /dev/tty.Bluetooth-Incoming-Port, /dev/tty.usbmodem2212401, /dev/tty.wlan-debug, } / {/dev/cu.Bluetooth-Incoming-Port, /dev/cu.usbmodem2212401, /dev/cu.wlan-debug, /dev/tty.Bluetooth-Incoming-Port, /dev/tty.usbmodem2212401, /dev/tty.wlan-debug, } => {}
PORTS {/dev/cu.Bluetooth-Incoming-Port, /dev/cu.usbmodem2212401, /dev/cu.wlan-debug, /dev/tty.Bluetooth-Incoming-Port, /dev/tty.usbmodem2212401, /dev/tty.wlan-debug, } / {/dev/cu.Bluetooth-Incoming-Port, /dev/cu.usbmodem2212401, /dev/cu.wlan-debug, /dev/tty.Bluetooth-Incoming-Port, /dev/tty.usbmodem2212401, /dev/tty.wlan-debug, } => {}
PORTS {/dev/cu.Bluetooth-Incoming-Port, /dev/cu.usbmodem2212401, /dev/cu.wlan-debug, /dev/tty.Bluetooth-Incoming-Port, /dev/tty.usbmodem2212401, /dev/tty.wlan-debug, } / {/dev/cu.Bluetooth-Incoming-Port, /dev/cu.usbmodem2212401, /dev/cu.wlan-debug, /dev/tty.Bluetooth-Incoming-Port, /dev/tty.usbmodem2212401, /dev/tty.wlan-debug, } => {}
PORTS {/dev/cu.Bluetooth-Incoming-Port, /dev/cu.usbmodem2212401, /dev/cu.wlan-debug, /dev/tty.Bluetooth-Incoming-Port, /dev/tty.usbmodem2212401, /dev/tty.wlan-debug, } / {/dev/cu.Bluetooth-Incoming-Port, /dev/cu.usbmodem2212401, /dev/cu.wlan-debug, /dev/tty.Bluetooth-Incoming-Port, /dev/tty.usbmodem2212401, /dev/tty.wlan-debug, } => {}
PORTS {/dev/cu.Bluetooth-Incoming-Port, /dev/cu.usbmodem2212401, /dev/cu.wlan-debug, /dev/tty.Bluetooth-Incoming-Port, /dev/tty.usbmodem2212401, /dev/tty.wlan-debug, } / {/dev/cu.Bluetooth-Incoming-Port, /dev/cu.usbmodem2212401, /dev/cu.wlan-debug, /dev/tty.Bluetooth-Incoming-Port, /dev/tty.usbmodem2212401, /dev/tty.wlan-debug, } => {}
PORTS {/dev/cu.Bluetooth-Incoming-Port, /dev/cu.usbmodem2212401, /dev/cu.wlan-debug, /dev/tty.Bluetooth-Incoming-Port, /dev/tty.usbmodem2212401, /dev/tty.wlan-debug, } / {/dev/cu.Bluetooth-Incoming-Port, /dev/cu.usbmodem2212401, /dev/cu.wlan-debug, /dev/tty.Bluetooth-Incoming-Port, /dev/tty.usbmodem2212401, /dev/tty.wlan-debug, } => {}
PORTS {/dev/cu.Bluetooth-Incoming-Port, /dev/cu.usbmodem2212401, /dev/cu.wlan-debug, /dev/tty.Bluetooth-Incoming-Port, /dev/tty.usbmodem2212401, /dev/tty.wlan-debug, } / {/dev/cu.Bluetooth-Incoming-Port, /dev/cu.usbmodem2212401, /dev/cu.wlan-debug, /dev/tty.Bluetooth-Incoming-Port, /dev/tty.usbmodem2212401, /dev/tty.wlan-debug, } => {}
PORTS {/dev/cu.Bluetooth-Incoming-Port, /dev/cu.usbmodem2212401, /dev/cu.wlan-debug, /dev/tty.Bluetooth-Incoming-Port, /dev/tty.usbmodem2212401, /dev/tty.wlan-debug, } / {/dev/cu.Bluetooth-Incoming-Port, /dev/cu.usbmodem2212401, /dev/cu.wlan-debug, /dev/tty.Bluetooth-Incoming-Port, /dev/tty.usbmodem2212401, /dev/tty.wlan-debug, } => {}
PORTS {/dev/cu.Bluetooth-Incoming-Port, /dev/cu.usbmodem2212401, /dev/cu.wlan-debug, /dev/tty.Bluetooth-Incoming-Port, /dev/tty.usbmodem2212401, /dev/tty.wlan-debug, } / {/dev/cu.Bluetooth-Incoming-Port, /dev/cu.usbmodem2212401, /dev/cu.wlan-debug, /dev/tty.Bluetooth-Incoming-Port, /dev/tty.usbmodem2212401, /dev/tty.wlan-debug, } => {}
PORTS {/dev/cu.Bluetooth-Incoming-Port, /dev/cu.usbmodem2212401, /dev/cu.wlan-debug, /dev/tty.Bluetooth-Incoming-Port, /dev/tty.usbmodem2212401, /dev/tty.wlan-debug, } / {/dev/cu.Bluetooth-Incoming-Port, /dev/cu.usbmodem2212401, /dev/cu.wlan-debug, /dev/tty.Bluetooth-Incoming-Port, /dev/tty.usbmodem2212401, /dev/tty.wlan-debug, } => {}
PORTS {/dev/cu.Bluetooth-Incoming-Port, /dev/cu.usbmodem2212401, /dev/cu.wlan-debug, /dev/tty.Bluetooth-Incoming-Port, /dev/tty.usbmodem2212401, /dev/tty.wlan-debug, } / {/dev/cu.Bluetooth-Incoming-Port, /dev/cu.usbmodem2212401, /dev/cu.wlan-debug, /dev/tty.Bluetooth-Incoming-Port, /dev/tty.usbmodem2212401, /dev/tty.wlan-debug, } => {}
PORTS {/dev/cu.Bluetooth-Incoming-Port, /dev/cu.usbmodem2212401, /dev/cu.wlan-debug, /dev/tty.Bluetooth-Incoming-Port, /dev/tty.usbmodem2212401, /dev/tty.wlan-debug, } / {/dev/cu.Bluetooth-Incoming-Port, /dev/cu.usbmodem2212401, /dev/cu.wlan-debug, /dev/tty.Bluetooth-Incoming-Port, /dev/tty.usbmodem2212401, /dev/tty.wlan-debug, } => {}
PORTS {/dev/cu.Bluetooth-Incoming-Port, /dev/cu.usbmodem2212401, /dev/cu.wlan-debug, /dev/tty.Bluetooth-Incoming-Port, /dev/tty.usbmodem2212401, /dev/tty.wlan-debug, } / {/dev/cu.Bluetooth-Incoming-Port, /dev/cu.usbmodem2212401, /dev/cu.wlan-debug, /dev/tty.Bluetooth-Incoming-Port, /dev/tty.usbmodem2212401, /dev/tty.wlan-debug, } => {}
PORTS {/dev/cu.Bluetooth-Incoming-Port, /dev/cu.usbmodem2212401, /dev/cu.wlan-debug, /dev/tty.Bluetooth-Incoming-Port, /dev/tty.usbmodem2212401, /dev/tty.wlan-debug, } / {/dev/cu.Bluetooth-Incoming-Port, /dev/cu.usbmodem2212401, /dev/cu.wlan-debug, /dev/tty.Bluetooth-Incoming-Port, /dev/tty.usbmodem2212401, /dev/tty.wlan-debug, } => {}
PORTS {/dev/cu.Bluetooth-Incoming-Port, /dev/cu.usbmodem2212401, /dev/cu.wlan-debug, /dev/tty.Bluetooth-Incoming-Port, /dev/tty.usbmodem2212401, /dev/tty.wlan-debug, } / {/dev/cu.Bluetooth-Incoming-Port, /dev/cu.usbmodem2212401, /dev/cu.wlan-debug, /dev/tty.Bluetooth-Incoming-Port, /dev/tty.usbmodem2212401, /dev/tty.wlan-debug, } => {}
Uploading using selected port: /dev/cu.usbmodem2212401
/Users/mcuee/Library/Arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude -C/Users/mcuee/Library/Arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf -v -patmega32u4 -cavr109 -P/dev/cu.usbmodem2212401 -b57600 -D -Uflash:w:/var/folders/zf/457r6vn50knfpnjgy1156llr0000gn/T/arduino_build_937693/Blink.ino.hex:i 

avrdude: Version 6.3-20190619
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "/Users/mcuee/Library/Arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf"
         User configuration file is "/Users/mcuee/.avrduderc"
         User configuration file does not exist or is not a regular file, skipping

         Using Port                    : /dev/cu.usbmodem2212401
         Using Programmer              : avr109
         Overriding Baud Rate          : 57600
         AVR Part                      : ATmega32U4
         Chip Erase delay              : 9000 us
         PAGEL                         : PD7
         BS2                           : PA0
         RESET disposition             : dedicated
         RETRY pulse                   : SCK
         serial program mode           : yes
         parallel program mode         : yes
         Timeout                       : 200
         StabDelay                     : 100
         CmdexeDelay                   : 25
         SyncLoops                     : 32
         ByteDelay                     : 0
         PollIndex                     : 3
         PollValue                     : 0x53
         Memory Detail                 :

                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           eeprom        65    20     4    0 no       1024    4      0  9000  9000 0x00 0x00
           flash         65     6   128    0 yes     32768  128    256  4500  4500 0x00 0x00
           lfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           hfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           efuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           lock           0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
           signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

         Programmer Type : butterfly
         Description     : Atmel AppNote AVR109 Boot Loader

Connecting to programmer: .
Found 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.

Programmer supports the following devices:
    Device code: 0x44

avrdude: devcode selected: 0x44
avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e9587 (probably m32u4)
avrdude: reading input file "/var/folders/zf/457r6vn50knfpnjgy1156llr0000gn/T/arduino_build_937693/Blink.ino.hex"
avrdude: writing flash (3956 bytes):

Writing | ################################################## | 100% 0.30s

avrdude: 3956 bytes of flash written
avrdude: verifying flash memory against /var/folders/zf/457r6vn50knfpnjgy1156llr0000gn/T/arduino_build_937693/Blink.ino.hex:
avrdude: load data flash data from input file /var/folders/zf/457r6vn50knfpnjgy1156llr0000gn/T/arduino_build_937693/Blink.ino.hex:
avrdude: input file /var/folders/zf/457r6vn50knfpnjgy1156llr0000gn/T/arduino_build_937693/Blink.ino.hex contains 3956 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.04s

avrdude: verifying ...
avrdude: 3956 bytes of flash verified

avrdude done.  Thank you.


@mcuee
Copy link
Collaborator

mcuee commented May 31, 2022

Ref: this one seems to offer different solutions for different OS.
https://stackoverflow.com/questions/43016993/how-can-i-force-an-arduino-leonardo-to-reset-with-avrdude

Under macOS, the following shell script file works for me.
https://github.com/gibatronic/sesame/blob/master/tsk/upload

# Find the Arduino port
ARDUINO_UPLOAD_PORT="$(find /dev/cu.usbmodem* | head -n 1)"

# Reset the Arduino
stty -f "${ARDUINO_UPLOAD_PORT}" 1200

# Wait for it...
while :; do
  sleep 0.5
  [ -c "${ARDUINO_UPLOAD_PORT}" ] && break
done

# ...upload!
avrdude "${OPTIONS[@]}"

It also has the script for Linux using Python/pyserial. This does not seem to work for me under macOS.

#! /usr/bin/python

import sys
import serial

com = serial.Serial(sys.argv[1], 1200)
com.dtr=False
com.close()

# python ./reset.py "/dev/ttyACM0"

Minor modification makes the above work under both macOS (Mac Mini M1) and Linux (Ubuntu 20.04 x86_64)..

#! /usr/bin/env python3

import sys
import serial

com = serial.Serial(sys.argv[1], 1200)
com.dtr=True
com.dtr=False
com.close()

# python ./reset.py "/dev/ttyACM0"

Windows batch file using WMIC -- not working for me yet, need to try again.
https://github.com/p1ne/arduino-leonardo-uploader/blob/master/windows/upload.bat

@echo off
setlocal

for /f "tokens=1* delims==" %%I in ('wmic path win32_pnpentity get caption  /format:list ^| find "SparkFun Pro Micro"') do (
    call :resetCOM "%%~J"
)

:continue

:: wmic /format:list strips trailing spaces (at least for path win32_pnpentity)
for /f "tokens=1* delims==" %%I in ('wmic path win32_pnpentity get caption  /format:list ^| find "Arduino Leonardo bootloader"') do (
    call :setCOM "%%~J"
)

:: end main batch
goto :EOF

:resetCOM <WMIC_output_line>
:: sets _COM#=line
setlocal
set "str=%~1"
set "num=%str:*(COM=%"
set "num=%num:)=%"
set port=COM%num%
echo %port%
mode %port%: BAUD=1200 parity=N data=8 stop=1
goto :continue

:setCOM <WMIC_output_line>
:: sets _COM#=line
setlocal
set "str=%~1"
set "num=%str:*(COM=%"
set "num=%num:)=%"
set port=COM%num%
echo %port%
goto :flash

:flash
avrdude -v -C./avrdude.conf -patmega32u4 -cavr109 -P%port% -b57600 -D -V -Uflash:w:./firmware.hex:i

@MCUdude
Copy link
Collaborator

MCUdude commented May 31, 2022

It would be really nice if we somehow could find a way to implement the whole 1200bps_touch, in C, that would work reliably on all platforms. Perhaps 1200bps_touch could be implemented as a separate flag, -T [baudrate]?

avrdude -C avrdude.conf -p atmega32u4 -c avr109 -P /dev/cu.usbmodem-1410 -b 57600 -T 1200

@mcuee
Copy link
Collaborator

mcuee commented May 31, 2022

It would be really nice if we somehow could find a way to implement the whole 1200bps_touch, in C, that would work reliably on all platforms. Perhaps 1200bps_touch could be implemented as a separate flag, -T [baudrate]?

avrdude -C avrdude.conf -p atmega32u4 -c avr109 -P /dev/cu.usbmodem-1410 -b 57600 -T 1200

Nice idea. Not so sure if extra dependancies like libserialport can be useful here..
Ref: https://github.com/sigrokproject/libserialport

If this is not acceptable, another way is do document the scripts or application to be used to get avrdude to work under different OS like Windows, Linux, macOS and FreeBSD.

@mcuee
Copy link
Collaborator

mcuee commented Jun 7, 2022

The following mod of the Windows batch file below seems to work. The trick is to add a delay to wait for Windows to re-enumerate the new bootloader COM port.
https://raw.githubusercontent.com/p1ne/arduino-leonardo-uploader/master/windows/upload.bat

@echo off
setlocal

for /f "tokens=1* delims==" %%I in ('wmic path win32_pnpentity get caption  /format:list ^| find "Arduino Leonardo"') do (
    call :resetCOM "%%~J"
)

:continue

:: wmic /format:list strips trailing spaces (at least for path win32_pnpentity)
for /f "tokens=1* delims==" %%I in ('wmic path win32_pnpentity get caption  /format:list ^| find "Arduino Leonardo bootloader"') do (
    call :setCOM "%%~J"
)

:: end main batch
goto :end

:resetCOM <WMIC_output_line>
:: sets _COM#=line
setlocal
set "str=%~1"
set "num=%str:*(COM=%"
set "num=%num:)=%"
set port=COM%num%
echo %port%
:: mode %port%: BAUD=1200 parity=N data=8 stop=1 dtr=on
:: mode %port%: BAUD=1200 parity=N data=8 stop=1 dtr=off
mode %port%: BAUD=1200 parity=N data=8 stop=1
:: need to wait for Windows to re-enumerate the new bootloader COM port, 3 seconds should be fine. If not, please adjust this delay time.
timeout 3 > NUL
goto :continue

:setCOM <WMIC_output_line>
:: sets _COM#=line
setlocal
set "str=%~1"
set "num=%str:*(COM=%"
set "num=%num:)=%"
set port=COM%num%
echo %port%
mode %port%: BAUD=57600 parity=N data=8

@echo on
.\avrdude -p atmega32u4 -c avr109 -P %port% -b 57600 -D -V -U flash:w:./blinky_leonardo.ino.leonardo.hex:i -v

:end
exit

@mcuee
Copy link
Collaborator

mcuee commented Jun 7, 2022

RUN log using the above modified batch file.

PS C:\work\avr\avrdude_test\avrdude-v7.0-windows-x64> .\leonardo_write.bat
COM5

Status for device COM5:
-----------------------
    Baud:            1200
    Parity:          None
    Data Bits:       8
    Stop Bits:       1
    Timeout:         OFF
    XON/XOFF:        OFF
    CTS handshaking: OFF
    DSR handshaking: OFF
    DSR sensitivity: OFF
    DTR circuit:     OFF
    RTS circuit:     ON

COM30

Status for device COM30:
------------------------
    Baud:            57600
    Parity:          None
    Data Bits:       8
    Stop Bits:       1
    Timeout:         OFF
    XON/XOFF:        OFF
    CTS handshaking: OFF
    DSR handshaking: OFF
    DSR sensitivity: OFF
    DTR circuit:     OFF
    RTS circuit:     ON


C:\work\avr\avrdude_test\avrdude-v7.0-windows-x64>.\avrdude -p atmega32u4 -c avr109 -P COM30 -b 57600 -D -V -U flash:w:./blinky_leonardo.ino.leonardo.hex:i -v

avrdude: Version 7.0
         Copyright (c) Brian Dean, http://www.bdmicro.com/
         Copyright (c) Joerg Wunsch

         System wide configuration file is "C:/work/avr/avrdude_test/avrdude-v7.0-windows-x64/avrdude.conf"

         Using Port                    : COM30
         Using Programmer              : avr109
         Overriding Baud Rate          : 57600
         AVR Part                      : ATmega32U4
         Chip Erase delay              : 9000 us
         PAGEL                         : PD7
         BS2                           : PA0
         RESET disposition             : dedicated
         RETRY pulse                   : SCK
         Serial program mode           : yes
         Parallel program mode         : yes
         Timeout                       : 200
         StabDelay                     : 100
         CmdexeDelay                   : 25
         SyncLoops                     : 32
         PollIndex                     : 3
         PollValue                     : 0x53
         Memory Detail                 :

                                           Block Poll               Page                       Polled
           Memory Type Alias    Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           eeprom                 65    20     4    0 no       1024    4      0  9000  9000 0x00 0x00
           flash                  65     6   128    0 yes     32768  128    256  4500  4500 0x00 0x00
           lfuse                   0     0     0    0 no          1    1      0  9000  9000 0x00 0x00
           hfuse                   0     0     0    0 no          1    1      0  9000  9000 0x00 0x00
           efuse                   0     0     0    0 no          1    1      0  9000  9000 0x00 0x00
           lock                    0     0     0    0 no          1    1      0  9000  9000 0x00 0x00
           calibration             0     0     0    0 no          1    1      0     0     0 0x00 0x00
           signature               0     0     0    0 no          3    1      0     0     0 0x00 0x00

         Programmer Type : butterfly
         Description     : Atmel AppNote AVR109 Boot Loader

Connecting to programmer: .
Found 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.

Programmer supports the following devices:
    Device code: 0x44

avrdude: devcode selected: 0x44
avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e9587 (probably m32u4)
avrdude: reading input file "./blinky_leonardo.ino.leonardo.hex"
avrdude: writing flash (3956 bytes):

Writing | ################################################## | 100% 0.33s

avrdude: 3956 bytes of flash written

avrdude done.  Thank you.


C:\work\avr\avrdude_test\avrdude-v7.0-windows-x64>exit

@mcuee
Copy link
Collaborator

mcuee commented Jun 7, 2022

Found another batch file which may work better.
p1ne/arduino-leonardo-uploader#5

@echo off
echo Upgrade procedure starting.
if %1.==. goto error
set hexfile=%1
set comportA=NONE
set comportB=NONE
if not exist %hexfile% goto error
for /f "usebackq" %%B in (`wmic path Win32_SerialPort Where "Caption LIKE '%%COM%%'" Get DeviceID ^| findstr "COM"`) do set comportA=%%B
if %comportA%==NONE goto nodevice
echo Com Port for Arduino device is detected as %comportA%.
echo Reset Arduino into bootloader
mode %comportA%: baud=12 > nul
timeout 2 > nul
for /f "usebackq" %%B in (`wmic path Win32_SerialPort Where "Caption LIKE '%%COM%%'" Get DeviceID ^| findstr "COM"`) do set comportB=%%B
if %comportB%==NONE goto nobldevice
echo Com Port for Arduino bootloader device is detected as %comportB%.
echo.
echo Starting AVR Downloader/UploaDEr.....
avrdude -pm32u4 -cavr109 -D -P%comportB% -b57600 -Uflash:w:%hexfile%
goto upgradedone
:nodevice
echo No matching module found, you should connect the module you want to upgrade.
goto end
:nobldevice
echo Reset into bootloader failed, please try again...
goto end
:error
Echo Missing parameter or file, you should provide the full filename of an existing .hex file you want to use.
goto end
:upgradedone
echo.
echo Upgrade done!
:end

Run log:

PS C:\work\avr\avrdude_test\avrdude-v7.0-windows-x64> .\leonardo_upload.bat .\blinky_leonardo.ino.leonardo.hex
Upgrade procedure starting.
Com Port for Arduino device is detected as COM5.
Reset Arduino into bootloader
Com Port for Arduino bootloader device is detected as COM30.

Starting AVR Downloader/UploaDEr.....

Connecting to programmer: .
Found 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.

Programmer supports the following devices:
    Device code: 0x44

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e9587 (probably m32u4)
avrdude: reading input file ".\blinky_leonardo.ino.leonardo.hex"
avrdude: input file .\blinky_leonardo.ino.leonardo.hex auto detected as Intel Hex
avrdude: writing flash (3956 bytes):

Writing | ################################################## | 100% 0.32s

avrdude: 3956 bytes of flash written
avrdude: verifying flash memory against .\blinky_leonardo.ino.leonardo.hex:
avrdude: input file .\blinky_leonardo.ino.leonardo.hex auto detected as Intel Hex

Reading | ################################################## | 100% 0.06s

avrdude: 3956 bytes of flash verified

avrdude done.  Thank you.


Upgrade done!

@mcuee
Copy link
Collaborator

mcuee commented Jun 7, 2022

@mariusgreuel I tried your branch ( https://github.com/mariusgreuel/avrdude) under Windows but somehow it does not work for my official Arduino Leonardo as it stuck there forever.

@mariusgreuel Maybe the above a false alarm. I tried again today under Windows 11 and your repo works fine.

PS C:\work\avr\avrdude_test\avrdude_win\out\build\x64-Debug\src\Debug> .\avrdude -pm32u4 
-cavr109 -D -P COM5 -b57600 -U.\blinky_leonardo.ino.leonardo.hex -v

avrdude.exe: Version 7.0
             Copyright (c) Brian Dean, http://www.bdmicro.com/
             Copyright (c) Joerg Wunsch

             System wide configuration file is 
"C:/work/avr/avrdude_test/avrdude_win/out/build/x64-Debug/src/Debug/avrdude.conf"

             Using Port                    : COM5
             Using Programmer              : avr109
             Overriding Baud Rate          : 57600
avrdude.exe: Found device at port 'COM5'
avrdude.exe: Entering bootloader mode...
avrdude.exe: Found device at port 'COM30'
             AVR Part                      : ATmega32U4
             Chip Erase delay              : 9000 us
             PAGEL                         : PD7
             BS2                           : PA0
             RESET disposition             : dedicated
             RETRY pulse                   : SCK
             Serial program mode           : yes
             Parallel program mode         : yes
             Timeout                       : 200
             StabDelay                     : 100
             CmdexeDelay                   : 25
             SyncLoops                     : 32
             PollIndex                     : 3
             PollValue                     : 0x53
             Memory Detail                 :

                                               Block Poll               Page                       Polled
               Memory Type Alias    Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
               ----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
               eeprom                 65    20     4    0 no       1024    4      0  9000  9000 0x00 0x00
               flash                  65     6   128    0 yes     32768  128    256  4500  4500 0x00 0x00
               lfuse                   0     0     0    0 no          1    1      0  9000  9000 0x00 0x00
               hfuse                   0     0     0    0 no          1    1      0  9000  9000 0x00 0x00
               efuse                   0     0     0    0 no          1    1      0  9000  9000 0x00 0x00
               lock                    0     0     0    0 no          1    1      0  9000  9000 0x00 0x00
               calibration             0     0     0    0 no          1    1      0     0     0 0x00 0x00
               signature               0     0     0    0 no          3    1      0     0     0 0x00 0x00

             Programmer Type : butterfly
             Description     : Atmel AppNote AVR109 Boot Loader

Connecting to programmer: .
Found 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.

Programmer supports the following devices:
    Device code: 0x44

avrdude.exe: devcode selected: 0x44
avrdude.exe: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude.exe: Device signature = 0x1e9587 (probably m32u4)
avrdude.exe: reading input file ".\blinky_leonardo.ino.leonardo.hex"
avrdude.exe: input file .\blinky_leonardo.ino.leonardo.hex auto detected as Intel Hex
avrdude.exe: writing flash (3956 bytes):

Writing | ################################################## | 100% 0.32s

avrdude.exe: 3956 bytes of flash written
avrdude.exe: verifying flash memory against .\blinky_leonardo.ino.leonardo.hex:
avrdude.exe: input file .\blinky_leonardo.ino.leonardo.hex auto detected as Intel Hex

Reading | ################################################## | 100% 0.06s

avrdude.exe: 3956 bytes of flash verified

avrdude.exe done.  Thank you.

@mcuee
Copy link
Collaborator

mcuee commented Jul 24, 2022

c/c++ based 1200bps helper for Windows and Linux
https://github.com/vanbwodonk/leonardoUploader.git

@mariusgreuel
Copy link
Contributor

c/c++ based 1200bps helper for Windows and Linux

I looked at the Windows implementation, and I have to say it is a very poor one: It is simply looking at the available COM ports, and not trying to find a matching one, not even looking at the VID/PID. For instance, on my PC I have a serial port on my motherboard, so when plugging in a Leonardo I would have two COM ports, which breaks the whole thing...

@dl8dtl
Copy link
Contributor

dl8dtl commented Jul 24, 2022

Curious, I'm quite a bit away from these Arduinos …

Would it somehow help to have a hook in AVRDUDE that allows for calling an external program (in the background?) right before AVRDUDE is going to take over the device? That could then e.g. be a Python script, which is not strictly a part of AVRDUDE, but we could ship it along if needed.

@dl8dtl
Copy link
Contributor

dl8dtl commented Jul 25, 2022

In my opinion, it would be most convenient if Avrdude supported 1200bps touch out of the box

I am a little reluctant to add device-specific hacks like that. I'm somewhat afraid of running into a maintenance mess, because each supported target board would then have the same right to get whatever is needed for it added.

That's why my idea of an external program, that's at least generic enough to handle whatever prerequisite any environment would need. However, I realize that a simple shell script / batch file cannot handle serial ports very well.

@kristofmulier
Copy link
Contributor Author

That's why my idea of an external program, that's at least generic enough to handle whatever prerequisite any environment would need. However, I realize that a simple shell script / batch file cannot handle serial ports very well.

What about a small, external C program?

@dl8dtl
Copy link
Contributor

dl8dtl commented Jul 25, 2022

What about a small, external C program?

Certainly a good idea, and it can easily be made a different one for Windows vs. Posix APIs. If I understand it correctly, some USB stuff is needed, so for the Posix world, it's easy enough to use libusb, while for Windows, I think Marius has already the needed bits and pieces together.

@MCUdude
Copy link
Collaborator

MCUdude commented Jul 25, 2022

I'd vote for a small program, written in C or similar.

(I've no experience with the Go language, but it looks like there's a serialutils package that does exactly what we want to achieve. This is what the Arduino CLI uses).

@mariusgreuel
Copy link
Contributor

I think Marius has already the needed bits and pieces together

The Windows implementation in my repo may be a little overly complicated, because I tried to not change the avrdude codebase too much, plus I reused some C++ code I had written previously.

so for the Posix world, it's easy enough to use libusb

I guess it depends on what implementation we pick. I might be jumping ahead here, but I can think of various implementations to do the 1200 baud reset-to-bootloader trick:

A)

  • You start off with the serial device X from the -P option (say /dev/ttyACM0)
  • Figure out the USB VID/PID and USB port location if device X (say 2341:8037 and 1-1.1:1.0)
  • Open device X with 1200 baud
  • Wait for device X to disconnect
  • Wait for a new USB device on the same USB port location, possibly with the same VID but a different PID (say 2341:0037)
  • Figure out the new serial device Y of the new USB device
  • Flash the device using the device Y

This requires getting the link between serial devices and USB devices. I think libusb is of limited help here, not sure.

B)

  • You start off with the serial device X from the -P option (say /dev/ttyACM0)
  • Open device X with 1200 baud
  • Periodically enumerate all serial devices and wait for X to disappear and some other device Y to appear.
  • Flash the device using the device Y

In my avrdude repo, I picked A, plus I used a heuristic that tries to infer whether the reset-to-bootloader is needed, based on the fact whether its a composite device (sketch) or not (bootloader). @mcuee did break the heuristic when he used a sketch as an ISP programmer, where you do not want to reset the device, but my heuristic did. So, an explicit option is needed here.

B is probably easier to implement and still sufficiently robust. I think finding the serial devices requires a bit of thought, because it requires implicit knowledge of all possible device names. Again, libusb is of limited help here (I think).

@mcuee Does libusb provide properties about the USB device that would help getting the mapping between serial devices and the corresponding USB ACM devices? Can libusb provide USB location properties, and if so, for which systems?

@mcuee
Copy link
Collaborator

mcuee commented Jul 27, 2022

@mariusgreuel
Yes I agree with you that libusb is not the right tool.

Personally I like cross-platform stuff and so far I found that pyserial to be the best for this task. The next one is probably libusbp (which may not support FreeBSD and may need some work for MSVC).
Ref: https://github.com/pololu/libusbp
Ref: https://github.com/pololu/libusbp/tree/master/examples

I do not know if libserial and libserialport can do the job or not.
https://github.com/crayzeewulf/libserial
https://github.com/sigrokproject/libserialport

I think maybe we still need two implementation if we do not want to use pyserial, one for Posix and one for Windows. As for Option A, at least under Linux, we may be able to utilize libudev. In the end, Option B may be a simpler approach.

@mcuee
Copy link
Collaborator

mcuee commented Jul 27, 2022

Sigrok libserialport example output. Looks like it can do the job and it support msvc (better than libusbp). It supports Windows, Linux, macOS and FreeBSD.

$ ./port_info.exe COM4
Looking for port COM4.
Port name: COM4
Description: Arduino Leonardo (COM4)
Type: USB
Manufacturer: Arduino LLC
Product: Arduino Leonardo
Serial:
VID: 2341 PID: 8036
Bus: 3 Address: 19
Freeing port.

$ ./port_config.exe COM4
Looking for port COM4.
Port name: COM4
Description: Arduino Leonardo (COM4)
Opening port.
Setting port to 115200 8N1, no flow control.
Baudrate: 115200, data bits: 8, parity: None, stop bits: 1
Creating new config for 9600 7E2, XON/XOFF flow control.
Applying new configuration.
Setting port back to previous config.

@mcuee
Copy link
Collaborator

mcuee commented Jul 27, 2022

I'd vote for a small program, written in C or similar.

Yes.

(I've no experience with the Go language, but it looks like there's a serialutils package that does exactly what we want to achieve. This is what the Arduino CLI uses).

That seems to be nice but I think C/C++ is probably more preferred than Go. Even Python is more preferred than Go if you asked me. Still it is pretty good as the Go serial library is cross platform (Windows, Linux, macOS, FreeBSD and OpenBSD).

@per1234
Copy link
Contributor

per1234 commented Jul 27, 2022

The github.com/arduino/arduino-cli/arduino/serialutils package seems the obvious choice.

You already have something written for this exact purpose, actively maintained by the primary manufacturer of the boards that use it and the primary consumer of the package, which is used by Arduino IDE 2.x, and Arduino Create Agent (the local tool used by Arduino Web Editor for facilitating uploads). Why would you want to reinvent the wheel and then maintain it?

Go is well suited for this type of application. The amount of wrapper code required to make an application around this package is likely very minimal.

@mariusgreuel
Copy link
Contributor

Go is well suited for this type of application

I vote against using Go, primarily because that would exclude many of us (including me) from being able to work with this code.

The github.com/arduino/arduino-cli/arduino/serialutils package seems the obvious choice.

Seems like the Arduino people implemented B. Note all the Sleeps() :-).

Personally, I think this functionality should be integrated in avrdude. If we are talking external application, we might ditch the entire idea and say 'go and use the Arduino CLI instead'.

If we do B, the avrdude codebase already includes most of the code. The only issue left is being able to enumerate all serial devices. I think that is doable.

@MCUdude
Copy link
Collaborator

MCUdude commented Jul 27, 2022

@mariusgreuel I agree. Even though Go might provide what we need, I'l have to learn Go before being able to contribute.

The only issue left is being able to enumerate all serial devices. I think that is doable.

I'll assume resolving/implementing the feature mentioned in #907 is a part of this task?

@per1234
Copy link
Contributor

per1234 commented Jul 27, 2022

My previous comment was specific to the proposal of creating a standalone "1200 bps touch" tool.

Obviously it is not relevant to the proposal of providing this capability in AVRDUDE itself.

I'l have to learn Go before being able to contribute

Is it really more effort than what would be required to reinvent the wheel?

@mcuee
Copy link
Collaborator

mcuee commented Jul 27, 2022

If we do B, the avrdude codebase already includes most of the code. The only issue left is being able to enumerate all serial devices. I think that is doable.

I think B is good enough.

I tend to think sigrok libserialport has all the things we need (to combine the following three examples, for example). The question is whether we want to add one more dependency.

C:\work\avr\avrdude_test\libserialport\examples [master ≡ +6 ~0 -0 !]> .\list_ports.exe
Getting port list.
Found port: COM3
Found port: COM4
Found port: COM5
Found 3 ports.
Freeing port list.

C:\work\avr\avrdude_test\libserialport\examples [master ≡ +7 ~0 -0 !]> .\port_config.exe COM4
Looking for port COM4.
Port name: COM4
Description: Arduino Leonardo (COM4)
Opening port.
Setting port to 115200 8N1, no flow control.
Baudrate: 115200, data bits: 8, parity: None, stop bits: 1
Creating new config for 9600 7E2, XON/XOFF flow control.
Applying new configuration.
Setting port back to previous config.

C:\work\avr\avrdude_test\libserialport\examples [master ≡ +7 ~0 -0 !]> .\port_config.exe COM5
Looking for port COM5.
Port name: COM5
Description: USB Serial Device (COM5)
Opening port.
Setting port to 115200 8N1, no flow control.
Baudrate: 115200, data bits: 8, parity: None, stop bits: 1
Creating new config for 9600 7E2, XON/XOFF flow control.
Applying new configuration.
Setting port back to previous config.

C:\work\avr\avrdude_test\libserialport\examples [master ≡ +7 ~0 -0 !]> .\port_info.exe COM4
Looking for port COM4.
Port name: COM4
Description: Arduino Leonardo (COM4)
Type: USB
Manufacturer: Arduino LLC
Product: Arduino Leonardo
Serial:
VID: 2341 PID: 8036
Bus: 3 Address: 16
Freeing port.

C:\work\avr\avrdude_test\libserialport\examples [master ≡ +7 ~0 -0 !]> .\port_info.exe COM5
Looking for port COM5.
Port name: COM5
Description: USB Serial Device (COM5)
Type: USB
Manufacturer: Arduino (www.arduino.cc)
Product: Arduino Uno
Serial: 75133303232351409162
VID: 03EB PID: 204B
Bus: 3 Address: 17
Freeing port.

@dl8dtl
Copy link
Contributor

dl8dtl commented Jul 27, 2022

My previous comment was specific to the proposal of creating a standalone "1200 bps touch" tool.

For that purpose, I'd be fine with it.

If we are talking external application, we might ditch the entire idea and say 'go and use the Arduino CLI instead'.

Which is not all that of a bad idea, given that this hack is only required for one (or just a few) Arduinos.

The "use an external tool" option has the merit that people with specific requirements for activating their own bootloaders could benefit from that as well, so it's not just targeting one Arduino platform only.

@mcuee
Copy link
Collaborator

mcuee commented Jul 27, 2022

arduino-cli is kind of interesting. I have never used it before.

I can see from Windows Device Manager that the port changed from COM5 --> COM8 --> COM5.

PS C:\work\arduino\arduino-cli_0.25.1_Windows_64bit> .\arduino-cli.exe board list
Port Protocol Type              Board Name       FQBN                 Core
COM5 serial   Serial Port (USB) Arduino Leonardo arduino:avr:leonardo arduino:avr

PS C:\work\arduino\arduino-cli_0.25.1_Windows_64bit> .\arduino-cli.exe compile 
--fqbn arduino:avr:leonardo .\MyFirstSketch\
    (promot skipped)

PS C:\work\arduino\arduino-cli_0.25.1_Windows_64bit> .\arduino-cli.exe upload -p COM5 
--fqbn arduino:avr:leonardo .\MyFirstSketch\
Connecting to programmer: .
Found 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.

Programmer supports the following devices:
    Device code: 0x44

@MCUdude
Copy link
Collaborator

MCUdude commented Mar 28, 2023

I'm leaving this here in case I ever forget. For those of you that just need a simple 1200bps touch command that will work on macOS and other *nix systems, stty works great. I'm able to upload to an Arduino Nano Every using the following sequence:

stty -f /dev/cu.usbmodem14101 1200 && avrdude -cjtag2updi -P/dev/cu.usbmodem14101 -patmega4809 -Uflash:w:prog.hex:i

EDIT:

Or perhaps even better:

$ PORT=/dev/cu.usbmodem14101; stty -f $PORT 1200 && /avrdude -patmega4809 -cjtag2updi -P$PORT -Uflash:w:prog.hex:i

@mcuee
Copy link
Collaborator

mcuee commented May 2, 2023

Another discussion here:

PORT=/dev/ttyACM0; stty -F $PORT 1200 && avrdude -pm4809 -cjtag2updi -P$PORT -Uflash:r:out.hex:r

Interesting stty -F under Linux and stty -f under macOS.
https://man7.org/linux/man-pages/man1/stty.1.html
https://www.unix.com/man-page/osx/1/stty/

@mcuee
Copy link
Collaborator

mcuee commented Jun 4, 2023

@mcuee
Copy link
Collaborator

mcuee commented Jun 4, 2023

Not exactly related to this issue but for those who are using Uno WiFi Rev2 (with Arduino custom FW xplainedmini_udpi) due to FW bug.

@mcuee mcuee added the documentation Improvements or additions to documentation label Jun 21, 2023
@mcuee
Copy link
Collaborator

mcuee commented Jun 24, 2023

In the end, I think we will not include this in avrdude. Therefore I will only keep the documentation label.

@mcuee mcuee removed the enhancement New feature or request label Jun 24, 2023
@mcuee
Copy link
Collaborator

mcuee commented Jun 25, 2023

As for the documentation, since this is very specific to a paticular board, I am thinking that Wiki entry is good enough. I will close this as an avrdude issue and move this to discussion.

@avrdudes avrdudes locked and limited conversation to collaborators Jun 25, 2023
@mcuee mcuee converted this issue into discussion #1443 Jun 25, 2023

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests

6 participants