Closed brouwer closed 5 months ago
Can you try avrdude 7.3 release to see if it works. Thanks. If not, please go back to avrdude release 7.2 and then 7.1 to see if they work or not.
I used to issue a command like this, which always worked just fine.
... for other, non-TPI parts? Looking at the history of the usbasp_tpi_write_byte() routine, it looks like it was never able to write!
I know too little about the TPI protocol and how write byte could be implemented for USBASP in TPI mode to help here, but if you unearth some driver code somewhere that is able to write single bytes (needed for fuses) then let us know or better provide a PR.
No definitely for TPI parts. :)
I was already using avrdude 7.3, I think I inadvertently upgraded some time ago.
Couldn't find a quick way to install older versions on a Mac (Apple Silicon) but in Windows (ARM) via Parallels I was able to test different versions of avrdude, since the releases have binaries for windows in this repo.
Last version this worked was 7.0.
Now just need to find a binary for 7.0 or build it for mac, so I don't have to go the roundabout way everytime :)
Also confirmed it ACTUALLY worked. Can't reach the chip anymore after setting the fuse, which is expected behavior, would need to do high voltage programming to recover from that.
No idea what changed, I also looked at the source code, and thought it was weird that it works to begin with, but it does... somehow
PS Microsoft.PowerShell.Core\FileSystem::\\Mac\Home\Downloads\avrdude-v7.1-windows-arm64> .\avrdude.exe -c usbasp -p t10 -e -U flash:w:program.hex -U fuse:w:0xfe:m
avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1e9003 (probably t10)
avrdude: erasing chip
avrdude: reading input file program.hex for flash
with 684 bytes in 1 section within [0, 0x2ab]
using 43 pages and 4 pad bytes
avrdude: writing 684 bytes flash ...
Writing | ################################################## | 100% 2.59 s
avrdude: 684 bytes of flash written
avrdude: verifying flash memory against program.hex
Reading | ################################################## | 100% 0.30 s
avrdude: 684 bytes of flash verified
avrdude: reading input file 0xfe for fuse
with 1 byte in 1 section within [0, 14]
using 1 page and 15 pad bytes, cutting off 4 trailing 0xff bytes
avrdude: writing 1 byte fuse ...
avrdude error: usbasp_write_byte in TPI mode; all writes have to be done at page level
***failed;
avrdude: 1 byte of fuse written
avrdude: verifying fuse memory against 0xfe
avrdude warning: requested verification for 15 bytes
fuse memory region only contains 1 bytes
only 1 bytes will be verified
avrdude warning: verification mismatch
device 0xff != input 0xfe at addr 0x0000 (error)
avrdude error: verification mismatch
avrdude done. Thank you.
PS Microsoft.PowerShell.Core\FileSystem::\\Mac\Home\Downloads\avrdude-v7.1-windows-arm64> cd ..
PS Microsoft.PowerShell.Core\FileSystem::\\Mac\Home\Downloads> cd .\avrdude-v7.0-windows-arm64\
PS Microsoft.PowerShell.Core\FileSystem::\\Mac\Home\Downloads\avrdude-v7.0-windows-arm64> .\avrdude.exe -c usbasp -p t10 -e -U flash:w:program.hex -U fuse:w:0xfe:m
avrdude.exe: AVR device initialized and ready to accept instructions
Reading | ################################################## | 100% 0.00s
avrdude.exe: Device signature = 0x1e9003 (probably t10)
avrdude.exe: erasing chip
avrdude.exe: reading input file "program.hex"
avrdude.exe: input file program.hex auto detected as Intel Hex
avrdude.exe: writing flash (684 bytes):
Writing | ################################################## | 100% 2.60s
avrdude.exe: 684 bytes of flash written
avrdude.exe: verifying flash memory against program.hex:
avrdude.exe: input file program.hex auto detected as Intel Hex
Reading | ################################################## | 100% 0.29s
avrdude.exe: 684 bytes of flash verified
avrdude.exe: reading input file "0xfe"
avrdude.exe: writing fuse (1 bytes):
Writing | ################################################## | 100% 0.07s
avrdude.exe: 1 bytes of fuse written
avrdude.exe: verifying fuse memory against 0xfe:
Reading | ################################################## | 100% 0.00s
avrdude.exe: 1 bytes of fuse verified
avrdude.exe done. Thank you.
PS Microsoft.PowerShell.Core\FileSystem::\\Mac\Home\Downloads\avrdude-v7.0-windows-arm64> .\avrdude.exe -c usbasp -p t10 -v
avrdude.exe: Version 7.0
Copyright (c) Brian Dean, http://www.bdmicro.com/
Copyright (c) Joerg Wunsch
System wide configuration file is "//Mac/Home/Downloads/avrdude-v7.0-windows-arm64/avrdude.conf"
Using Port : usb
Using Programmer : usbasp
AVR Part : ATtiny10
RESET disposition : dedicated
RETRY pulse : SCK
Serial program mode : yes
Parallel program mode : yes
Memory Detail :
Block Poll Page Polled
Memory Type Alias Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack
----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
signature 0 0 0 0 no 3 16 0 0 0 0x00 0x00
fuse 0 0 4 0 no 1 16 0 0 0 0x00 0x00
calibration 0 0 0 0 no 1 16 0 0 0 0x00 0x00
lockbits 0 0 0 0 no 1 16 0 0 0 0x00 0x00
flash 0 0 128 0 no 1024 16 0 0 0 0x00 0x00
Programmer Type : usbasp
Description : USBasp, http://www.fischl.de/usbasp/
avrdude.exe: error: program enable: target doesn't answer.
avrdude.exe: initialization failed, rc=-1
Double check connections and try again, or use -F to override
this check.
avrdude.exe done. Thank you.
Blimey! So, the 7.0 code probably used a different routine than usbasp_tpi_write_byte()
for byte writes. I wonder whether
https://github.com/avrdudes/avrdude/blob/8fe729f0a26ce2da2456f05007cc13d0183bd3a1/src/usbasp.c#L268-L270
could simply be replaced by
return avr_write_byte_default(pgm, p, m, addr, data);
avr_write_byte_default() can deal with TPI. [edit, see below]
I am slowly getting an understanding for why usbasp was able to write fuses in 7.0 but no longer is. Normally, TPI programming requires a pgm->cmd_tpi()
function to be provided by the programmer; then regular avr_write_byte_default()
can handle TPI programming. The usbasp code, however, does not offer cmd_tpi()
but instead subsumes fuse writing into its paged_write()
function, which is unusual and not what paged write was meant for. This will have stopped working when AVRDUDE's logic in avr.c
restriced calling paged_write()
to memories where the size is an integer multiple of their page size (for ATtiny10's fuse, size = 1 and page size = 16, so size is not an integer multiple of page size):
https://github.com/avrdudes/avrdude/blob/8fe729f0a26ce2da2456f05007cc13d0183bd3a1/src/avr.c#L1047-L1052
Now, the right thing to do is to enable usbasp's write_byte()
function to work for TPI parts. Right now, this function dispatches to usbasp_tpi_write_byte()
which just prints the error message in the title of the issue (and always has, since 2011, as shown above). Correcting this is also useful for libavrdude
as it expects the write_byte()
function of any programmer to work for all non-paged memories.
@brouwer Are you in a position to check out and test a PR that I am going to produce? I neither have an ATtiny10 nor usbasp.
Obvs I am not expecting you to set the fuse to a non-recoverable value. Setting it to the current value is sufficient for tests.
@stefanrueger I have a working setup I can test with. If you create the PR, we can then take it from there 👍
@MCUdude Brilliant, the draft PR is ready. And remember I don't warrant the ATtiny10 will survive :wink:
The way it's written I don't expect lockbits to be written correctly. For that I suspect (but don't know) that this patch is needed
diff --git a/src/usbasp.c b/src/usbasp.c
index 872e3ce7..75e39358 100644
--- a/src/usbasp.c
+++ b/src/usbasp.c
@@ -1317,7 +1317,7 @@ static int usbasp_tpi_write_byte(const PROGRAMMER *pgm, const AVRPART *p, const
written = 0;
// Must erase fuse first, TPI parts only have one fuse
- if(mem_is_a_fuse(m)) { // What about lockbits? Should this if be removed?
+ if(1) {
// Set PR
usbasp_tpi_send_byte(pgm, TPI_OP_SSTPR(0));
usbasp_tpi_send_byte(pgm, (pr & 0xFF) | 1 );
The other thing I'd like to test is whether one has to WRITEBLOCK 16 bytes or whether one byte is enough
diff --git a/src/usbasp.c b/src/usbasp.c
index 872e3ce7..e571ea59 100644
--- a/src/usbasp.c
+++ b/src/usbasp.c
@@ -1299,7 +1299,7 @@ static int usbasp_tpi_write_byte(const PROGRAMMER *pgm, const AVRPART *p, const
// Memories left: fuse and lockbits
unsigned char cmd[4], sbuf[32] = {0}, *sptr = sbuf;
- int written, clen, n, n_bytes = m->page_size;
+ int written, clen, n, n_bytes = 1;
uint16_t pr;
if(addr != 0) {
[edit: see below]
I have now studied the data sheet and rewritten the usbasp_tpi_write_byte() routine accordingly. Although the previously used write block of 16 bytes probably worked, the data sheet only requires writing one word. @MCUdude or @mcuee could you check usbasp with a TPI part (say, ATtiny10)?
$ tools/test-avrdude -p"-c usbasp -p t10"
@brouwer Are you in a position to check out and test PR #1763 using the following line
$ tools/test-avrdude -e path_of_new_avrdude_bin -p"-c usbasp -p t10"
Thank you!
I tried but don't think it worked or that my ATtinyT10 survived the ordeal :)
# avrdude -c usbasp -p t10 -v
avrdude: Version 7.3-20240422 (2f334c90)
Copyright the AVRDUDE authors;
see https://github.com/avrdudes/avrdude/blob/main/AUTHORS
System wide configuration file is /usr/local/etc/avrdude.conf
User configuration file is /root/.avrduderc
User configuration file does not exist or is not a regular file, skipping
Using port : usb
Using programmer : usbasp
AVR Part : ATtiny10
Programming modes : TPI
Programmer Type : usbasp
Description : USBasp ISP and TPI programmer
avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1e9003 (probably t10)
avrdude done. Thank you.
Ran a little connectivity test before I ran the test script Which failed all tests:
# tools/test-avrdude -e /usr/local/bin/avrdude -p"-c usbasp -p t10"
Testing /usr/local/bin/avrdude version 7.3-20240422 (2f334c90)
Prepare "-c usbasp -p t10" and press 'enter' or 'space' to continue. Press any other key to skip
❌ 0.249 s: fuse access: clear, set and read wdton fuse bit (failed command below)
$ /usr/local/bin/avrdude -qq -c usbasp -p t10 -T "config wdton=0; config wdton=1; config wdton"
❌ 0.685 s: chip erase (failed command below)
$ /usr/local/bin/avrdude -qq -c usbasp -p t10 -e -FAU flash:w:0xff:m
❌ 0.235 s: flash -U write/verify holes_rjmp_loops_1024B.hex (failed command below)
$ /usr/local/bin/avrdude -qq -c usbasp -p t10 -Uflash:w:tools/test_files/holes_rjmp_loops_1024B.hex
❌ 0.222 s: flash -U write/verify rjmp_loops_for_bootloaders_1024B.hex (failed command below)
$ /usr/local/bin/avrdude -qq -c usbasp -p t10 -Uflash:w:tools/test_files/rjmp_loops_for_bootloaders_1024B.hex
❌ 0.236 s: flash -T write/verify holes_rjmp_loops_1024B.hex (failed command below)
$ /usr/local/bin/avrdude -qq -c usbasp -p t10 -T "write flash tools/test_files/holes_rjmp_loops_1024B.hex:a"
❌ 0.236 s: flash -T write/verify rjmp_loops_for_bootloaders_1024B.hex (failed command below)
$ /usr/local/bin/avrdude -qq -c usbasp -p t10 -T "write flash tools/test_files/rjmp_loops_for_bootloaders_1024B.hex:a"
❌ 0.690 s: chip erase and spot check flash is actually erased (failed command below)
$ /usr/local/bin/avrdude -qq -c usbasp -p t10 -e -FAU flash:w:0xff:m -U flash:v:tools/test_files/holes_flash_0xff_1024B.hex
One or more AVRDUDE "-c usbasp -p t10" tests failed. Do you want to retry this particular test? (y/n): n
And after that I could no longer get the USBASP to talk to the T10 unfortunately
Thanks for testing, @brouwer. Really sorry to hear that the t10 seems bricked! This is commensurate with @MCUdude's experience. So, the theory behind the main changes of that PR is that flash r/w should work as before and that the new fuse writing code should now do something (and I was hoping something useful and correct).
It isn't clear to me why the part appears bricked; assuming the fuse write was successful and turned on the WDT, the default for WDTO is 16 ms, so in absence of code that contains wdr
the part would be in an endless reset loop of 16 ms length. I know too little about TPI to say whether it would be able to supersede such a reset loop. SPI programming for other parts would (I think).
Maybe the testing should be done differently:
# Check version
avrdude -h |& tail -1
# Check flash r/w (should be working old code)
avrdude -qq -c usbasp -p t10 -e -FAU flash:w:0xff:m
avrdude -qq -c usbasp -p t10 -Uflash:w:tools/test_files/holes_rjmp_loops_1024B.hex
avrdude -qq -c usbasp -p t10 -T "write flash tools/test_files/holes_rjmp_loops_1024B.hex:a"
avrdude -qq -c usbasp -p t10 -T "write flash tools/test_files/rjmp_loops_for_bootloaders_1024B.hex:a"
avrdude -qq -c usbasp -p t10 -e -FAU flash:w:0xff:m -U flash:v:tools/test_files/holes_flash_0xff_1024B.hex
# Check fuse writing (0xff is factory value)
avrdude -qq -c usbasp -p t10 -U fuse:w:0xff:m
# Check fuse writing in terminal: setting PB2 to output the clock /should/ not be harmful
avrdude -qq -c usbasp -p t10 -T "config ckout=0; config ckout=1; config ckout"
No worries, I can afford to loose a few of those :) Might be able to recover it with 12V on the reset line, but then I just need to get my hands on something like ATMEL-ICE. Bit limited with the usbasp.
I have some more parts, can do some more testing coming days.
PR #1789 changes the test-avrdude program to no longer use the wdton
bit, it uses ckout
instead.
@brouwer @MCUdude I have found a bug in the tpi write fuse code after comparing the usbasp_tpi_write_byte()
code with avr_write_byte_default()
. The faulty code was mistakenly writing the fuse to an address one byte too high. So, when wanting to write the fuse byte (low byte) the high byte was actually written triggering a word write with an unknown low byte from a temporary MCU register to the fuse. Presumably reset was disabled, which will have rendered the part unresponsive.
@MCUdude: High voltage programming for TPI parts means applying +12 V throughout the programming, not just sending a pulse as is the case with HV SPI programming. You should be able to recover the part.
I have now fixed the code. If you head over to PR #1763 and catch up (git pull
) with my recent change, I predict this should now be working OK. And PR #1789 should not be needed (though it won't harm either).
Bit of a noob when it comes to programming microcontrollers. I am using an USBASP in TPI mode and unfortunately this is my only option.
I have a small program I run on an ATTiny10 For the program to work I need to set rstdisbl (external reset) to 0, so it's disabled
I used to issue a command like this, which always worked just fine. It wrote my program, and set the fuse bit (Found the correct argument using AVR Fuse Calculator) Never had any issues, this worked, my controller worked as desired etc.
avrdude -c usbasp -p t10 -e -U flash:w:my-program.hex -U fuse:w:0xfe:m
However I think I may have upgraded avrdude at some point (not that I can remember) but since then this command no longer works. I am now getting the error from the title
usbasp_write_byte in TPI mode; all writes have to be done at page level
Same thing happens in interactive mode:
Anyone with suggestions on what I can do?