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

ravedude: Add support for USBtiny #278

Open
jwillikers opened this issue Jun 4, 2022 · 11 comments
Open

ravedude: Add support for USBtiny #278

jwillikers opened this issue Jun 4, 2022 · 11 comments
Labels

Comments

@jwillikers
Copy link

Would it be possible to add support for flashing via a USBtiny programmer? There's built-in support in avrdude, but it requires using the -c usbtiny command-line flag instead of specifying a serial port.

@dalpil
Copy link
Contributor

dalpil commented Jun 5, 2022

The programmer is specified per board in ravedude, and there's already two boards that use the usbtiny programmer; the Trinket and Trinket Pro.

If you're using some other board you might have to add a definition for it in ravedude/src/board.rs, and specify that the usbtiny programmer should be used in the avrdude_options method.

@jwillikers
Copy link
Author

Thanks! I'm using an atmega328p on a breadboard, so I'd have to add a board definition for it.

@dalpil
Copy link
Contributor

dalpil commented Jun 6, 2022

Oh, in that case I misunderstood what you were trying to accomplish.

Adding a "bare atmega328p" board definition might work, but it's probably not the right way to go about this.

If programming bare microcontrollers is something that's within the intended scope of ravedude it should probably be implemented in another way; maybe by adding a bunch of new arguments (in main.rs) where all the required parameters can be specified(?).

Let's see if Rahix can chime in on this.

@Rahix
Copy link
Owner

Rahix commented Jun 6, 2022

Honestly the architecture of ravedude is not well thought out - I just hacked something together quickly so people using the well known AVR boards have something to run their programs with. Before ravedude was a thing, we were all just using a shell-script which did the same thing: Call avrdude to flash the program and then some console emulator like picocom to interact with the serial console.

Of course in the long run it would be nice to make ravedude a generic tool for running rust programs on any AVR board, not just the "well known" ones. One step in that direction would be to drop board.rs and instead add all its contents into a configuration file. ravedude would then ship with a default config and people like you, @jwillikers, could use their own config file instead... I even started working on that but didn't finish it yet unfortunately :/

Here is a mock-up of what I was thinking the config file could look like:

[uno]
    name = "Arduino Uno"

    [uno.reset]
    automatic = true

    [uno.avrdude]
    programmer = "arduino"
    partno = "atmega328p"
    baudrate = -1
    do_chip_erase = true

    [uno.usb-info]
    port-ids = [
        { vid = 0x2341, pid = 0x0043 },
        { vid = 0x2341, pid = 0x0001 },
        { vid = 0x2A03, pid = 0x0043 },
        { vid = 0x2341, pid = 0x0243 },
    ]

[micro]
    name = "Arduino Micro"

    [micro.reset]
    automatic = false
    message = "Reset the board by pressing the reset button once."

    [micro.avrdude]
    programmer = "avr109"
    partno = "atmega32u4"
    baudrate = 115200
    do_chip_erase = true

    [micro.usb-info]
    port-ids = [
        { vid = 0x2341, pid = 0x0037 },
        { vid = 0x2341, pid = 0x8037 },
        { vid = 0x2A03, pid = 0x0037 },
        { vid = 0x2A03, pid = 0x8037 },
        { vid = 0x2341, pid = 0x0237 },
        { vid = 0x2341, pid = 0x8237 },
    ]

[nano]
    name = "Arduino Nano"

    [nano.reset]
    automatic = true

    [nano.avrdude]
    programmer = "arduino"
    partno = "atmega328p"
    baudrate = 57600
    do_chip_erase = true

    [nano.usb-info]
    # No IDs here because the Nano uses a generic USB-Serial chip.

[leonardo]
    name = "Arduino Leonardo"

    [leonardo.reset]
    automatic = false
    message = "Reset the board by pressing the reset button once."

    [leonardo.avrdude]
    programmer = "avr109"
    partno = "atmega32u4"
    baudrate = -1
    do_chip_erase = true

    [leonardo.usb-info]
    port-ids = [
        { vid = 0x2341, pid = 0x0036 },
        { vid = 0x2341, pid = 0x8036 },
        { vid = 0x2A03, pid = 0x0036 },
        { vid = 0x2A03, pid = 0x8036 },
    ]

[mega2560]
    name = "Arduino Mega 2560"

    [mega2560.reset]
    automatic = true

    [mega2560.avrdude]
    programmer = "wiring"
    partno = "atmega2560"
    baudrate = 115200
    do_chip_erase = false

    [mega2560.usb-info]
    port-ids = [
        { vid = 0x2341, pid = 0x0010 },
        { vid = 0x2341, pid = 0x0042 },
        { vid = 0x2A03, pid = 0x0010 },
        { vid = 0x2A03, pid = 0x0042 },
        { vid = 0x2341, pid = 0x0210 },
        { vid = 0x2341, pid = 0x0242 },
    ]

[diecimila]
    name = "Arduino Diecimila"

    [diecimila.reset]
    automatic = true

    [diecimila.avrdude]
    programmer = "arduino"
    partno = "atmega168"
    baudrate = 19200
    do_chip_erase = false

    [diecimila.usb-info]
    # No IDs known.

[promicro]
    name = "SparkFun Pro Micro"

    [promicro.reset]
    automatic = false
    message = "Reset the board by quickly pressing the reset button **twice**."

    [promicro.avrdude]
    programmer = "avr109"
    partno = "atmega32u4"
    baudrate = -1
    do_chip_erase = true

    [promicro.usb-info]
    port-ids = [
        { vid = 0x1B4F, pid = 0x9205 }, # 5V
        { vid = 0x1B4F, pid = 0x9206 }, # 5V
        { vid = 0x1B4F, pid = 0x9203 }, # 3.3V
        { vid = 0x1B4F, pid = 0x9204 }, # 3.3V
    ]

[trinket-pro]
    name = "Trinket Pro"

    [trinket-pro.reset]
    automatic = false
    message = "Reset the board by pressing the reset button once."

    [trinket-pro.avrdude]
    programmer = "usbtiny"
    partno = "atmega328p"
    baudrate = -1
    do_chip_erase = false

    [trinket-pro.usb-info]
    # The Trinket Pro does not have USB-Serial, thus no port is known or needed.

[nano168]
    name = "Nano Clone (ATmega168)"

    [nano168.reset]
    automatic = true

    [nano168.avrdude]
    programmer = "arduino"
    partno = "atmega168"
    baudrate = 19200
    do_chip_erase = false

    [nano168.usb-info]
    # No IDs here because the Nano 168 uses a generic USB-Serial chip.

@Rahix Rahix added the ravedude label Jun 6, 2022
@ewrogers
Copy link

ewrogers commented Oct 8, 2022

Any word on this? I would say adding this -c usbtiny syntax as a small patch is a good solution until a proper refactor can be made for the entire board.rs re-write.

My situation is that using a M1 Mac (Studio) I am unable to connect to the Arduino Nano directly. I get a constant avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x00 error with a direct connection. I have tried everything imaginable to remedy this but... it simply does not want to allow me to upload directly either in Arduino IDE 2.x or avrdude directly.

So, I started using an ISP from Spark Fun. With that, I am able to program the Arduino Nano using the same exact cable. I don't know why this works and why the other method does not, but it does. My suspicion is Apple Silicon and the UART driver has some wonky behavior together (/dev/cu.usbserial-AB0JQVPN).

Using the Rust template project, I have the following .cargo/config.toml:

[target.'cfg(target_arch = "avr")']
runner = "./flash.sh"

Then in my flash.sh script I use this:

#!/bin/zsh

avrdude -c usbtiny -p atmega328p -b 57600 -U "flash:w:$1"

Works beautifully with cargo run. I'd just love to remove the hacky shell script and be able to specify this directly in ravedude.

@Rahix
Copy link
Owner

Rahix commented Oct 8, 2022

I would say adding this -c usbtiny syntax as a small patch is a good solution until a proper refactor can be made for the entire board.rs re-write.

I'm not quite following... What would you suggest to do as a "quickfix" for now?

@ewrogers
Copy link

ewrogers commented Oct 8, 2022

What I would like to be able to do is pass the -c usbtiny flag to ravedude and it would then be passed to the avrdude command as a passthrough and allow the omission of the -P <port>.

@Rahix
Copy link
Owner

Rahix commented Oct 9, 2022

I see. I'm not a fan of adding such specific options here because supporting them in the long run will be painful... I think what I'd prefer would be adding a mode to ravedude where all avrdude options are explicitly passed on the commandline. A sort of "custom" board for people like you. But this will also become superfluous as soon as there is a proper config file...

Maybe we can just add a fake "board" for your configuration for now which just uses the right settings? Or, from looking at the boards we have, maybe the existing trinket-pro already has the configuration you need? Can you try whether it works for your setup? Otherwise I'd be fine with adding a custom board just for your environment for now.

@ewrogers
Copy link

ewrogers commented Oct 9, 2022

Sorry, I'm not the original reporter so maybe this seemed confusing between me and them. I just added on to this discussion because of the title and I figured it was better than creating a separate issue for my need.

I see two separate issues here:

  1. Supporting an ISP like usbtiny for uploading to supported boards
  2. Using usbtiny to upload to custom boards that are not already supported

I can understand that the second point is complicated and not the scope of this. My point is that using an ISP to flash an already supported board seems like a possible use case and only requires a simple pass through of the -c param to avrdude.

For example, I am using an Arduino Nano. This is something that is already supported and defined in the 328p family of boards. I just want to deploy my code using an ISP instead of direct upload to the device. There should not be any additional configuration required since it is eventually running on the same device, it's a matter of how it gets sent via avrdude.

Ex: PC -> Arduino vs PC -> ISP -> Arduino should not require any board config changes, and avrdude already supports this via -c usbtiny.

Consider this use case: I am using a Nano or Uno R3 as a development board for my Rust embedded project. I get my prototype working and finalized, so then I develop a custom PCB that will use the Atmega 328p IC and no USB or UART (as it is a 'production' board). I still need a way to upload my code to the microcontroller, so a ISP of some kind will be necessary. And it seems I cannot do this with ravedude today.

Of course I can use my shell script and use avrdude directly but I think this is something that should be supported for production builds and deployments to real hardware.

@jwillikers
Copy link
Author

@ewrogers Your discussing your issue on the right thread. I believe @Rahix has proposed an adequate solution via a new configuration file to solve both your problems, though not how you'd like, right? It sounds like you'd still prefer the command-line option or perhaps a config file section separate from the board which describes the programmer to use?

@ewrogers
Copy link

ewrogers commented Oct 13, 2022

Yes, I think it can be useful for people who are in this situation and using an already supported board. It seems like it should be doable via a simple passthrough.

I like to avoid additional files when possible and not overly complex.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants