avrdude icon indicating copy to clipboard operation
avrdude copied to clipboard

Attiny85: increase delay

Open umbynos opened this issue 2 years ago • 43 comments

More details at https://forum.arduino.cc/t/usbtinyisp-from-ide/263885

Related conversation with @MCUdude https://github.com/umbynos/avrdude/commit/7c18d4bdfc69bb576bdee0e8e56da91ecaf361f4#commitcomment-73300758

Co-authored-by: Martino Facchin [email protected]

umbynos avatar May 31 '22 14:05 umbynos

Well, all these proposed values look pretty arbitrary to me.

The values that are currently in avrdude.conf reflect the numbers from the datasheet (or .atdf file), and they are pretty much the same (4 ms / 4.5 ms) for almost all newer AVRs. The chiperasetime value is documented to only affect HVSP programming, which is completely irrelevant to the USBtinyISP device. (In fact, it's always 0 for all entries anyway, and stk500v2.c is the only consumer of that value.) The EEPROM "delay" value (6 in the original, 12 in the patch, 5 in the current .atdf file) is again only used in the stk500v2.c parameter block, not affecting USBtinyISP in any way.

Finally, the patch only affects the ATtiny85, but what about its smaller siblings (ATtiny45, ATtiny25)?

While I have no doubt that these changes might have cured the symptoms of the person once submitting them, I think the actual issue must be somewhere else.

dl8dtl avatar Jun 15 '22 20:06 dl8dtl

For reference, delays similar to this PR are already present in the current avrdude.conf file.

Here's a few: ATmega324P ATmega644 ATmega1284 ATmega64RFR2 ATmega128RFA1

MCUdude avatar Jun 20 '22 10:06 MCUdude

Maybe we can ask the users whether they also encounter issues with similar chips like ATtiny45 and ATtiny25, Probably they will have the same issue and it is just because ATtiny85 is much more popular than the other two.

mcuee avatar Jun 20 '22 10:06 mcuee

Maybe we can ask the users

@mcuee Where should this action take place? If you mean here, that post is from 2014.

BTW here's another report https://learn.adafruit.com/introducing-trinket/programming-with-avrdude

umbynos avatar Jun 20 '22 13:06 umbynos

@mcuee Where should this action take place? If you mean here, that post is from 2014.

I mean in the general Arduino forum -- probably a new post to ask about ATtiny45 and ATtiny25 to see if they have the same problem like the ATtiny85 or not.

mcuee avatar Jun 20 '22 13:06 mcuee

Can anyone here even reproduce the problem with the ATtiny85?

I can't, even using the same version of AVRDUDE and avrdude.conf bundled with the Arduino IDE 1.0.5-r2 installation, on Windows 7, using the drivers provided by Adafruit in that Trinket tutorial. I don't have a Trinket so I'm using a USBtinyISP connected to an ATtiny85 running on the 8 MHz internal oscillator (the clock configuration of the Trinket), as was done by the user at https://forum.arduino.cc/t/usbtinyisp-from-ide/263885.

per1234 avatar Jun 21 '22 02:06 per1234

For reference, delays similar to this PR are already present in the current avrdude.conf file.

These are different families, which have indeed different delays described in their datasheet.

As argued above, the delays in this proposal look completely arbitrary, and most of them don't even affect the programming tool used. That's why I question the complete proposal, unless someone can describe a scenario how to reproduce a problem with the ATtinyX5. Personally, I have been using these ATtinys quite a bit in the past, and never encountered problems with them.

dl8dtl avatar Jun 21 '22 06:06 dl8dtl

@ladyada would you or someone else from Adafruit mind checking whether this patch is still needed with the latest AVRDUDE from this repository to reliably upload to the Trinket and Gemma?

This patch originated from Adafruit: https://github.com/arduino/toolchain-avr/pull/21

per1234 avatar Jun 21 '22 07:06 per1234

Can anyone here even reproduce the problem with the ATtiny85?

I haven't used the ATtiny85 that much, but I've used the USBtinyISP programmer a lot with the ATtiny13, which was reported to have similar issues. I've never had any issues with the USBtinyISP when using the ATtiny13, and that's with "sensible" delay values.

It may be that @ladyada knows why the original ATtiny85-based Adafruit Trinket needs such large delays, and if this somehow has later been fixed. BTW does anyone know where I can find the source code for the Trinket bootloader?

MCUdude avatar Jun 21 '22 07:06 MCUdude

does anyone know where I can find the source code for the Trinket bootloader?

Here it is: https://github.com/adafruit/Adafruit-Trinket-Gemma-Bootloader

per1234 avatar Jun 21 '22 07:06 per1234

our notes say

Because the USB bootloader is a little different than an off-the-shelf programmer, we have to update the configuration file to have a longer erase delay. This does not affect programming bare Attiny85 chips, so you can use this configuration file with Trinkets or raw chips without any problems.

probably this is due to USB transmission delays, we had timeout errors otherwise

ladyada avatar Jun 28 '22 22:06 ladyada

But see my analysis above:

https://github.com/avrdudes/avrdude/pull/983#issuecomment-1156876317

dl8dtl avatar Jun 29 '22 20:06 dl8dtl

Hi @dl8dtl, sorry for the delay, finally I had some time to carry on some tests.

I tried uploading to an Arduino Gemma with our patched version of the avrdude.conf (which includes the patch we are trying to upstream with this PR). This is the result:

"/home/umberto/.arduino15/packages/arduino/tools/avrdude/7.0-arduino.3/bin/avrdude" "-C/home/umberto/.arduino15/packages/arduino/hardware/avr/1.8.99/bootloaders/gemma/avrdude.conf" -v -V -pattiny85 -carduinogemma  "-Uflash:w:/tmp/arduino-sketch-61D4583461DF5011988F3D93F494BD0B/Blink.ino.hex:i"

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

         System wide configuration file is "/home/umberto/.arduino15/packages/arduino/hardware/avr/1.8.99/bootloaders/gemma/avrdude.conf"
         User configuration file is "/home/umberto/.avrduderc"
         User configuration file does not exist or is not a regular file, skipping

         Using Port                    : usb
         Using Programmer              : arduinogemma
avrdude: usbdev_open(): Found USBtinyISP, bus:device: 001:019
         AVR Part                      : ATtiny85
         Chip Erase delay              : 400000 us
         RESET disposition             : possible i/o
         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    12     4    0 no        512    4      0  4000  4500 0xff 0xff
           flash                  65     6    32    0 yes      8192   64    128 30000 30000 0xff 0xff
           signature               0     0     0    0 no          3    0      0     0     0 0x00 0x00
           lock                    0     0     0    0 no          1    0      0  9000  9000 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
           calibration             0     0     0    0 no          2    0      0     0     0 0x00 0x00

         Programmer Type : USBtiny
         Description     : Arduino Gemma. Based on USBtiny
avrdude: programmer operation not supported

avrdude: Using SCK period of 10 usec
avrdude: AVR device initialized and ready to accept instructions

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

avrdude: Device signature = 0x1e930b (probably t85)
avrdude: NOTE: "flash" memory has been specified, an erase cycle will be performed
         To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: 7 retries during SPI command
avrdude: Using SCK period of 10 usec
avrdude: reading input file "/tmp/arduino-sketch-61D4583461DF5011988F3D93F494BD0B/Blink.ino.hex"
avrdude: writing flash (682 bytes):

Writing | #####                                              | 9% 0.03savrdude: 8 retries during SPI command
Writing | #########                                          | 18% 0.07savrdude: 7 retries during SPI command
Writing | ##############                                     | 27% 0.11savrdude: 8 retries during SPI command
Writing | ##################                                 | 36% 0.14savrdude: 8 retries during SPI command
Writing | #######################                            | 45% 0.18savrdude: 8 retries during SPI command
Writing | ################################                   | 63% 0.25savrdude: 8 retries during SPI command
Writing | ####################################               | 72% 0.29savrdude: 8 retries during SPI command
Writing | #########################################          | 81% 0.33savrdude: 8 retries during SPI command
Writing | #############################################      | 90% 0.36savrdude: 8 retries during SPI command
Writing | ################################################## | 100% 0.40s

avrdude: 682 bytes of flash written

avrdude done.  Thank you.

And the uploaded code seems to work just fine on the board.

By only setting chip_erase_delay back to 4500, just like in the avrdude.conf file in this repo, I get this:

"/home/umberto/.arduino15/packages/arduino/tools/avrdude/7.0-arduino.3/bin/avrdude" "-C/home/umberto/.arduino15/packages/arduino/hardware/avr/1.8.99/bootloaders/gemma/avrdude.conf" -v -V -pattiny85 -carduinogemma  "-Uflash:w:/tmp/arduino-sketch-61D4583461DF5011988F3D93F494BD0B/Blink.ino.hex:i"

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

         System wide configuration file is "/home/umberto/.arduino15/packages/arduino/hardware/avr/1.8.99/bootloaders/gemma/avrdude.conf"
         User configuration file is "/home/umberto/.avrduderc"
         User configuration file does not exist or is not a regular file, skipping

         Using Port                    : usb
         Using Programmer              : arduinogemma
avrdude: usbdev_open(): Found USBtinyISP, bus:device: 001:017
         AVR Part                      : ATtiny85
         Chip Erase delay              : 4500 us
         RESET disposition             : possible i/o
         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    12     4    0 no        512    4      0  4000  4500 0xff 0xff
           flash                  65     6    32    0 yes      8192   64    128 30000 30000 0xff 0xff
           signature               0     0     0    0 no          3    0      0     0     0 0x00 0x00
           lock                    0     0     0    0 no          1    0      0  9000  9000 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
           calibration             0     0     0    0 no          2    0      0     0     0 0x00 0x00

         Programmer Type : USBtiny
         Description     : Arduino Gemma. Based on USBtiny
avrdude: programmer operation not supported

avrdude: Using SCK period of 10 usec
avrdude: AVR device initialized and ready to accept instructions

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

avrdude: Device signature = 0x1e930b (probably t85)
avrdude: NOTE: "flash" memory has been specified, an erase cycle will be performed
         To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: Using SCK period of 10 usec

avrdude: error: usbtiny_transmit: Broken pipe
avrdude: reading input file "/tmp/arduino-sketch-61D4583461DF5011988F3D93F494BD0B/Blink.ino.hex"
avrdude: writing flash (682 bytes):

Writing |                                                    | 0% 0.00s
avrdude: error: usbtiny_send: Broken pipe (expected 64, got -32)
Writing | #####                                              | 9% 0.00s
avrdude: error: usbtiny_receive: Broken pipe (expected 4, got -32)
avrdude: 11 retries during SPI command
avrdude: 8 retries during SPI command

avrdude: error: usbtiny_receive: Broken pipe (expected 4, got -32)

avrdude: error: usbtiny_receive: Broken pipe (expected 4, got -32)

avrdude: error: usbtiny_receive: Broken pipe (expected 4, got -32)
avrdude: 34 retries during SPI command
avrdude: 8 retries during SPI command
avrdude: 8 retries during SPI command
avrdude: 8 retries during SPI command
avrdude: 8 retries during SPI command

avrdude: error: usbtiny_receive: Broken pipe (expected 4, got -32)

avrdude: error: usbtiny_receive: Broken pipe (expected 4, got -32)
avrdude: 26 retries during SPI command
avrdude: 8 retries during SPI command

avrdude: error: usbtiny_receive: Broken pipe (expected 4, got -32)
avrdude: 16 retries during SPI command
avrdude: 9 retries during SPI command
avrdude: 8 retries during SPI command
avrdude: 8 retries during SPI command
avrdude: 8 retries during SPI command
avrdude: 8 retries during SPI command
avrdude: 8 retries during SPI command
avrdude: 9 retries during SPI command
avrdude: 8 retries during SPI command

avrdude: error: usbtiny_receive: Broken pipe (expected 4, got -32)

avrdude: error: usbtiny_receive: Broken pipe (expected 4, got -32)

avrdude: error: usbtiny_receive: Broken pipe (expected 4, got -32)
avrdude: 34 retries during SPI command
avrdude: 8 retries during SPI command
avrdude: 8 retries during SPI command
avrdude: 8 retries during SPI command
avrdude: 8 retries during SPI command
avrdude: 8 retries during SPI command

avrdude: error: usbtiny_receive: Broken pipe (expected 4, got -32)

avrdude: error: usbtiny_receive: Broken pipe (expected 4, got -32)
avrdude: 27 retries during SPI command
avrdude: 9 retries during SPI command
avrdude: 8 retries during SPI command

avrdude: error: usbtiny_receive: Broken pipe (expected 4, got -32)
avrdude: 17 retries during SPI command
avrdude: 8 retries during SPI command
avrdude: 8 retries during SPI command
avrdude: 9 retries during SPI command
avrdude: 8 retries during SPI command

avrdude: error: usbtiny_receive: Broken pipe (expected 4, got -32)

avrdude: error: usbtiny_receive: Broken pipe (expected 4, got -32)
avrdude: 27 retries during SPI command
avrdude: 8 retries during SPI command

avrdude: error: usbtiny_receive: Broken pipe (expected 4, got -32)
avrdude: 17 retries during SPI command
avrdude: 8 retries during SPI command

avrdude: error: usbtiny_receive: Broken pipe (expected 4, got -32)
avrdude: 17 retries during SPI command

avrdude: error: usbtiny_receive: Broken pipe (expected 4, got -32)
avrdude: 16 retries during SPI command
avrdude: 8 retries during SPI command

avrdude: error: usbtiny_receive: Broken pipe (expected 4, got -32)

avrdude: error: usbtiny_receive: Broken pipe (expected 4, got -32)
avrdude: 25 retries during SPI command

avrdude: error: usbtiny_receive: Broken pipe (expected 4, got -32)
avrdude: 14 retries during SPI command

avrdude: error: usbtiny_receive: Broken pipe (expected 4, got -32)
avrdude: 16 retries during SPI command
Writing | #####                                              | 10% 0.33savrdude: 8 retries during SPI command

avrdude: error: usbtiny_receive: Broken pipe (expected 4, got -32)
avrdude: 17 retries during SPI command
avrdude: 9 retries during SPI command

avrdude: error: usbtiny_receive: Broken pipe (expected 4, got -32)

avrdude: error: usbtiny_receive: Broken pipe (expected 4, got -32)

avrdude: error: usbtiny_receive: Broken pipe (expected 4, got -32)
Writing | ######                                             | 11% 0.36savrdude: 35 retries during SPI command
avrdude: 8 retries during SPI command
avrdude: 9 retries during SPI command
Writing | ################################################## | 100% 1.04s

avrdude: 682 bytes of flash written

avrdude done.  Thank you.

and the board does not seems to work.

The interesting part is this one: If I try to use the default avrdude.conf present on this repo, with only this small addition:

programmer
  id    = "arduinogemma";
  desc  = "Arduino Gemma. Based on USBtiny";
  type  = "usbtiny";
  connection_type = usb;
  usbvid     = 0x2341;
  usbpid     = 0x0c9f;
;

I get the exact same error.

This experiment led me to think that indeed we need that delay.

As @ladyada explained this is because that board do not use a programmer but instead when the mcu is powered on acts as a programmer itself for a few seconds using bit banging, after that runs the user program. Infact the avrdude: 8 retries during SPI command could be caused by this. I'm not knowledged enough about this topic. But at this point I think that that delay is required for that board to work properly.

Well, all these proposed values look pretty arbitrary to me.

Probably you are right about this, and I don't know all the back-story since I was not part of Arduino at that point.

Finally, the patch only affects the ATtiny85, but what about its smaller siblings (ATtiny45, ATtiny25)?

Probably yes, if they use the same kind of bootloader. Unfortunately I do not have these MCU to test things out.

Maybe a viable solution would be to add another entry in the avrdude.conf to cover this use-case? Just like the guys from adafruit suggests: https://github.com/adafruit/Adafruit-Trinket-Gemma-Bootloader/blob/master/avrdude.conf.addition.txt Of course I don't know if such thing would be accepted.

umbynos avatar Jul 13 '22 15:07 umbynos

Thanks for the feedback, it's welcome.

My problem with changing any of that: these parameters are obtained from the Atmel definitions, and they are meant to apply to certain (Atmel-origin) programmers.

If any particular implementation cloning that protocol needs more time, in my opinion, it's the responsibility of that implementation to adapt the timing accordingly. So if a bootloader needs 200 ms instead of the 4.5 ms defined by the datasheet, they are free to simply implement a longer timeout (and/or completely ignoring the incoming parameter). If you attach it to an Atmel/Microchip Studio, and declare it being an STK500, they are passing the exact same values down *) as AVRDUDE does.

*) If not, it's indeed a bug in AVRDUDE. They are supposed to be the same.

dl8dtl avatar Jul 13 '22 20:07 dl8dtl

It seems to me the right solution is to create a new programmer type called arduino-gemma or (adafruti-gemma) and then deal with it in usbtiny code as usbtiny is the parent. Hopefully it is possible to differentiate usbtiny with the gemma bootloader.

Ref: https://github.com/adafruit/Adafruit-Trinket-Gemma-Bootloader/blob/master/avrdude.conf.addition.txt

mcuee avatar Jul 14 '22 03:07 mcuee

Or just have the USBtiny code not use STK500 values at all, instead use fixed values inside. It seems the critical value is the chip erase delay here.

dl8dtl avatar Jul 14 '22 05:07 dl8dtl

Or just have the USBtiny code not use STK500 values at all, instead use fixed values inside. It seems the critical value is the chip erase delay here.

Good idea.

mcuee avatar Jul 14 '22 05:07 mcuee

usbtiny_chip_erase() has:

usleep( p->chip_erase_delay );

Just use any larger value there. @umbynos can you give it a try whether 100000 (µs) is already sufficient, or does it really have to wait for 400 ms?

dl8dtl avatar Jul 14 '22 05:07 dl8dtl

Nope, with hip_erase_delay = 100000; won't work, it seems to be the same error as with the default unpatched avrdude config: out.txt

umbynos avatar Jul 14 '22 16:07 umbynos

OK, then I suggest we simply change the wait time in the USBtiny implementation to 400 ms. There's no point for it to reuse the STK500 value if it just doesn't work for some implementations.

dl8dtl avatar Jul 14 '22 18:07 dl8dtl

@umbynos Do you want to change your PR that way, or do you want me to suggest a new one instead?

dl8dtl avatar Jul 14 '22 18:07 dl8dtl

@ladyada Is there any way to tell this bootloader apart from a real USBtiny programmer?

If so, the extension of the wait time could be made dependant on that.

dl8dtl avatar Jul 14 '22 20:07 dl8dtl

@umbynos Do you want to change your PR that way, or do you want me to suggest a new one instead?

Since I don't know the codebase that well, maybe it would be better if you could suggest a new one instead.

umbynos avatar Jul 18 '22 13:07 umbynos

So, the affected boards' bootloaders latch on to the -c usbtiny protocol, which I believe has no handshake. For this to work, AVRDUDE would need to wait for the requests to have been processed on the board. A reasonable estimate for the time that a bootloader needs to emulate chip erase will probably be flash->num_pages * part->chip_erase_delay. This assumes that an SPM page erase does not take longer than an SPI programming chip erase. BTW (as a side note) I wonder why the -c usbtiny programmer gets initialised after the chip erase. Is that really necessary?

https://github.com/avrdudes/avrdude/blob/a5552f64cf0bea2a4f72e3a0dc90672d1bc2a18a/src/usbtiny.c#L636-L639

Going down the route of a computed chip erase time penalises large parts, eg, ATmega2560, when programmed with a proper usbtiny physical programmer, as the chip erase time would then be 10 s rather than the necessary 10 ms (or so). Maybe best to estimate needed delays with the target parts/boards, try them out and then use one fixed value that suits all target boards.

stefanrueger avatar Jul 18 '22 14:07 stefanrueger

And also, have a look at the proposed urprotocol https://github.com/avrdudes/avrdude/discussions/940#discussioncomment-3017328, which is meant to help establish exactly what the bootloader is capable of. This should, if/once implemented into future AVRDUDE releases, enable boards like trinket to carry out happy bootloading with small resources (the corresponding prototype ATmega85 bootloader is 256 bytes albeit without EEPROM support).

stefanrueger avatar Jul 18 '22 14:07 stefanrueger

flash->num_pages * part->chip_erase_delay

We now know that the ATtiny85 works with 400 ms delay, while it fails with 100 ms. Does that somewhat fit into this formula?

dl8dtl avatar Jul 19 '22 21:07 dl8dtl

flash->num_pages * part->chip_erase_delay

We now know that the ATtiny85 works with 400 ms delay, while it fails with 100 ms. Does that somewhat fit into this formula?

128*4500 µs, so 576 ms. Considering it's an upper estimate and that the subsequent pgm->initialize(pgm, p) will burn through one or more(?) 50 ms periods, the 400 ms look like it fits with the formula.

Future release fun: expr $(avrdude -p ATtiny85/st | grep num_pages | cut -f5 ) \* $(avrdude -p ATtiny85/st | grep chip_erase_delay | cut -f4 ) (this is how I actually found out)

stefanrueger avatar Jul 20 '22 00:07 stefanrueger

But I wouldn't just use the formula. I would cap it somehow. For an ATmega2560 this results in a 9.2 s pause that is hard to explain to users that use an actual (physical) programmer that can do the job in that many ms.

stefanrueger avatar Jul 20 '22 00:07 stefanrueger

I wish there were a method to tell a real USBtinyISP apart from a bootloader.

I suggest a solution that uses extended arguments (-x) for larger delays than 400 ms, so any user who does use such a bootloader on a large device has a way to override it appropriately.

dl8dtl avatar Jul 20 '22 06:07 dl8dtl

I wish there were a method to tell a real USBtinyISP apart from a bootloader.

@dl8dtl and @umbynos

If we just need to differentiate USBtinyISP and the Arduino Gemma bootloader, then there is a simple way -- to use different USB VID/PID.

USBtinyISP: https://github.com/avrdudes/avrdude/blob/main/src/usbdevs.h#L51-L55

// these are specifically assigned to USBtiny,
// if you need your own VID and PIDs you can get them for cheap from
// www.mecanique.co.uk so please don't reuse these. Thanks!
#define USBTINY_VENDOR_DEFAULT  0x1781
#define USBTINY_PRODUCT_DEFAULT 0x0C9F

Arduino Gemma Bootloader

programmer
  id    = "arduinogemma";
  desc  = "Arduino Gemma. Based on USBtiny";
  type  = "usbtiny";
  connection_type = usb;
  usbvid     = 0x2341;
  usbpid     = 0x0c9f;
;

mcuee avatar Aug 01 '22 11:08 mcuee