AVRDUDESS Flash dump error

I think it needs to be updated on the bus pirate driver side in avr dude and then maybe on the bus pirate.

Assume there should be some kind of logic on avrdude driver is address >0xffff then configure the two Z bit. Whether the Bus Pirate needs an additional command to do that, or if it’s just a step blasted through SPI or whatever is beyond my knowledge.

This is from the data sheet :slight_smile:

See item 6 - perform 0x4d first to set extended byte, then do 0x20/0x28 to read low/high byte.

I don’t think dude has to change; just mask off 3rd address byte for the 0x4d command

2 Likes

@mbrugman Can you generate a .uf2 POC with that test idea and have @chickendipper tell us if it works?

1 Like

Give me a bit, I need to get to a real computer

2 Likes

So the way I believe it works is the bus pirate is just an spi interface and avr dude send s the stream of commands. The bus pirate is ignorant of what is actually sent.

I could be totally wrong. But I think the bus pirate driver in avr dude need s to test the upper bits of the address range and send the 40 00 ZZ 00 as needed.

Hum, there seem to be some avr specific extensions, so then we need to know the width of the address passed on the “intermediate” layer.

I think I can just add the extended high byte set in this hunk of code from legacy4third.c - looks like we’re getting a 32-bit address, so it’s just a matter of pulling out the right (3rd) byte for that:

                    case 0x02:
                        if (binmode_debug) {
                            printf("\r\nAVR BULK READ");
                        }

                        memset(tmpbuf, 0, TMPBUFF_SIZE);

                        while (!read_buff(tmpbuf, 8, DEFAULT_MAX_TRIES))
                        {
                            if (button_get(0)) {
                                return;
                            }
                        }

                        uint32_t addr = (tmpbuf[0] << 24) | (tmpbuf[1] << 16) | (tmpbuf[2] << 8) | tmpbuf[3];
                        uint32_t len = (tmpbuf[4] << 24) | (tmpbuf[5] << 16) | (tmpbuf[6] << 8) | tmpbuf[7];

                        if (binmode_debug) {
                            printf("\r\naddr: 0x%08X, len: 0x%08X", addr, len);
                        }

                        if ((addr > 0xFFFF) || (len > 0xFFFF) || ((addr + len) > 0xFFFF)) {
                            // error
                            CDC_SEND_STR(1, "\x00");
                            break;
                        }
                        CDC_SEND_STR(1, "\x01");

                        if (binmode_debug) {
                            printf("\r\n>> ");
                        }
                        while (len > 0) {
                            if (button_get(0)) {
                                return;
                            }
                            hwspi_write_read(0x20); // AVR_FETCH_LOW_BYTE_COMMAND
                            hwspi_write_read((addr >> 8) & 0xFF);
                            hwspi_write_read(addr & 0xFF);
                            uint8_t byte_flash = hwspi_write_read(0x00);
                            if (binmode_debug) {
                                printf("\r\n0x%02X", byte_flash);
                            }
                            tud_cdc_n_write_char(1, byte_flash); // Send the readed byte
                            tud_cdc_n_write_flush(1);
                            len--;
                            if (len > 0) {
                                hwspi_write_read(0x28); // AVR_FETCH_HIGH_BYTE_COMMAND
                                hwspi_write_read((addr >> 8) & 0xFF);
                                hwspi_write_read(addr & 0xFF);
                                uint8_t byte_flash = hwspi_write_read(0x00);
                                if (binmode_debug) {
                                    printf("\r\n0x%02X", byte_flash);
                                }
                                tud_cdc_n_write_char(1, byte_flash); // Send the readed byte
                                tud_cdc_n_write_flush(1);
                                len--;
                            }
                            addr++;
                        }
                        if (binmode_debug) {
                            printf("\r\n");
                        }
                        break;
1 Like

bulding a .uf2 for BP5 with just these changes:

  • updating range tests from 0xffff to 0x2ffff
  • setting extended high address bits (command 0x4d

                        if ((addr > 0x2FFFF) || (len > 0x2FFFF) || ((addr + len) > 0x2FFFF)) {
                            // error
                            CDC_SEND_STR(1, "\x00");
                            break;
                        }
                        CDC_SEND_STR(1, "\x01");

                        if (binmode_debug) {
                            printf("\r\n>> ");
                        }
                        while (len > 0) {
                            if (button_get(0)) {
                                return;
                            }
                            hwspi_write_read(0x4d); // AVR_LOAD_ADDRESS_EXTENDED_HIGH_BYTE_COMMAND
                            hwspi_write_read(0x00);
                            hwspi_write_read((addr >> 16) & 0x03);  // just the two lowest bits
                            hwspi_write_read(0x00);

                            hwspi_write_read(0x20); // AVR_FETCH_LOW_BYTE_COMMAND
                            hwspi_write_read((addr >> 8) & 0xFF);
                            hwspi_write_read(addr & 0xFF);
                            uint8_t byte_flash = hwspi_write_read(0x00);
                            if (binmode_debug) {
                                printf("\r\n0x%02X", byte_flash);
                            }
1 Like

Ok, here we go…

.uf2 file is here:
bus_pirate5_rev10.uf2.zip (349.3 KB)
NOTE - it is for a rev 10 Bus Pirate 5! Let me know if you need something else

Here’s the changes (I can make a PR if this works): GitHub - mbrugman67/BusPirate5-firmware at binmode_dude_readfix

@chickendipper - please take a look and let me know if this works :slight_smile:

2 Likes

Nicely done!

I have also been on mobile so digging in was a bit unproductive.

1 Like

I’m using the Bus Pirate 6. I will be able to test it on that new board I ordered hopefully arriving in a day or two

1 Like

Oh sorry!! Let me go build that version

1 Like

@chickendipper - here’s a link to build artifacts (I decided to just let github do it for me :)): https://github.com/mbrugman67/BusPirate5-firmware/actions/runs/16175175937/artifacts/3497388083

1 Like

The link doesn’t work I get a 404 error when clicking on it

1 Like

Sorry @chickendipper here it is:
firmware-rp2350-ubuntu-latest.zip (6.8 MB)

2 Likes

@chickendipper - did you get a chance to try it?

1 Like

I wanted to test it on a dev board first but unfortunately it hasn’t arrived yet and I’m away for a few days now so will have to test it next week.

1 Like

tl;dr - adding the command which hopefully fixes reading large flash parts doesn’t appear to affect reading smaller parts

Did a little experiment with this today. I only have one device with an ATMega128, but the board doesn’t have the ISP pins pulled out. I only have one of the devices, so I don’t want to go hacking on it too much - it’s something I can’t replace.

Anyway, on re-reading the datasheet, I saw that the note that says: Not all instructions are applicable for all parts. My concern was that adding instruction 0x4d - Load Address Extended High Byte could cause problems on AVR parts that have flash sizes less that 128K. Maybe even cause it to error out of SPI programming mode.

Just to be sure, I loaded the latest onto my BP5 and did an avrdude command:

┌──(matty💊s76)-[~/data/tmp/binmode]
└─$ avrdude -c buspirate -P /dev/ttyACM1 -p m328p -U flash:r:dmp.bin:r

attempting to initiate BusPirate binary mode ...
avrdude: paged flash write enabled
avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1e950f (probably m328p)
avrdude: reading flash memory ...

Reading | ################################################## | 100% 60.42 s 

avrdude: writing output file dmp.bin

avrdude done.  Thank you.

I checked the binary to be sure it was the correct image of what I expected to be on that particular chip. I then loaded my test build with the additional SPI write for extended high byte (at line 699 of src/binmode/legacy4third.c):

hwspi_write_read(0x4d); // AVR_LOAD_ADDRESS_EXTENDED_HIGH_BYTE_COMMAND
hwspi_write_read(0x00);
hwspi_write_read((addr >> 16) & 0x03);  // just the two lowest bits
hwspi_write_read(0x00);

and then ran the avrdude command again:

$ avrdude -c buspirate -P /dev/ttyACM1 -p m328p -U flash:r:dmp_new.bin:r

which completed with no errors. I compared the two files:

┌──(matty💊s76)-[~/data/tmp/binmode]
└─$ cmp dmp.bin dmp_new.bin 
                                                                                                                        
┌──(matty💊s76)-[~/data/tmp/binmode]
└─$ 

So, this tells me that adding the command doesn’t cause any problems with smaller parts, well at least the 32K flash ATMega328p, which is good news! I was concerned that I’d have to add some logic to only do the ‘0x4d’ on larger addresses. Not a big deal, but I’d rather make the fewest changes necessary.

I wanted to document this, because sooner or later someone else will think of it :slight_smile:

1 Like

Let’s see what the AVRDude devs propose…

I’m pretty confident that the problem is in the BP implementation. AVRDude does send the address/length as a 32-bit integer; it’s just that binmode never did anything to set the extended high address byte.

The real test is when someone can try to read a ATMega128 or 256.

2 Likes

image


@mbrugman you’re awesome! Incredible! It worked on the first try and you did it blind—so cool!

Could you mention what you did and what you think of it as a fix here?

Maybe they’ll spot something we didn’t, and that would give me more peace of mind… and most importantly, it’ll help us know whether this now supports everything. If you can’t or don’t feel like doing it, I can take care of it—just let me know (please tag @MCUdude @mcuee and @stefanrueger).

If this alone is enough, it would be a perfect solution!

Thank you so much—this is something I use a lot!

2 Likes