avrdudes / avrdude

AVRDUDE is a utility to program AVR microcontrollers
GNU General Public License v2.0
756 stars 139 forks source link

AVR EB support issue #1546

Closed mcuee closed 1 year ago

mcuee commented 1 year ago

From here

@MCUdude found an issue with AVR EB support.

$ ./avrdude -cpkobn_updi -pavr16eb32 -qq -t
avrdude> read fusea
0000  03 00                                             |..              |

avrdude> write fusea 0 0x02 0x00
avrdude error: (write) verification error writing 0x02 at 0x00000 cell=0x03 using bit mask 0xf3

avrdude> read fusea
0000  03 00                                             |..              |

avrdude> q
askn37 commented 1 year ago

be careful...

AVR_EB has many different memory maps than other products. In particular, various problems will occur if "signature=0x1080" is overlooked.

recommendation. Create a completely new part. part; id = ".avreb";

BAN. If "lock=0x1040" and "fusea:pdicfg=0x105a" are set to a specific state at the same time, UPDI control will not return even if HV control is performed. It should be.

stefanrueger commented 1 year ago

I wonder whether the observed behaviour is a specific property of how the 2-byte pdicfg fuse works. One is supposed to unlock it first with a key:

Screenshot from 2023-10-30 00-45-06

stefanrueger commented 1 year ago

| AVR_EB has many different memory maps than other products.

True. I believe the avrdude.conf entries to be correct:

$ avrdude -c dryrun -p avr16eb*/At | grep offset | cut -f3- | sort | uniq -c
      4 bootrow offset  0x1100
      4 data    offset  0x1000000
      4 eeprom  offset  0x1400
      4 flash   offset  0x800000
      4 fuse0   offset  0x1050
      4 fuse1   offset  0x1051
      4 fuse2   offset  0x1052
      4 fuse5   offset  0x1055
      4 fuse6   offset  0x1056
      4 fuse7   offset  0x1057
      4 fuse8   offset  0x1058
      4 fusea   offset  0x105a
      4 fuses   offset  0x1050
      4 io  offset  0x0
      4 lock    offset  0x1040
      4 prodsig offset  0x1080
      4 sernum  offset  0x1090
      4 sib offset  0x0
      4 signature   offset  0x1080
      4 tempsense   offset  0x1084
      4 userrow offset  0x1200
askn37 commented 1 year ago

@stefanrueger

DS40002522A - 58P

8.10.2.8 UPDI Protection - Bits 1:0 – LEVEL[1:0] UPDI Protection Level

NVMACCDIS : NVM access through UPDI disabled. Chip Erase and USERROW write are also disabled.

Even if this is effective, it does not seem to be written yet whether UPDI access rights can be regained using HV control.

stefanrueger commented 1 year ago

@MCUdude Please try writing 0x2 to the 2-byte pdicfg fuse following the procedure in the datasheet and see whether that works.

MCUdude commented 1 year ago

I'll see what I can do. I really don't want to mess this chip up, because this is the only one I got (donated by Microchip Norway), and even though I have samples from Microchip Direct on order, they won't arrive until late December.

Please try writing 0x2 to the 2-byte pdicfg fuse

But doesn't this result in a "bricked chip", as I don't have a functioning bootloader present? And even if there is a bootloader present, would it be possible to re-enable UPDI?

mcuee commented 1 year ago

@MCUdude

Better play safe in this case.

askn37 commented 1 year ago

@MCUdude

But doesn't this result in a "bricked chip", as I don't have a functioning bootloader present? And even if there is a bootloader present, would it be possible to re-enable UPDI?

I've already written an optiboot compatible bootloader that "supposedly" works, but I haven't received the chip yet so I can't test it, so it's pending. (Of course, FUSE changes, HV control, etc. have not been verified)

https://github.com/askn37/multix-zinnia-sdk-modernAVR/tree/main/bootloaders

And it is ''certainly'' irreversible. PDICFG will not take effect unless LOCK is also executed at the same time. However, without Chip Erase he cannot release the LOCK even with HV control, but with PDICFG he rejects both UPDI and Chip Erase. As a logical consequence, HV control is also rejected.

So I just warn you to be very careful in this matter. . .

MCUdude commented 1 year ago

I should probably wait until I at least have one AVR-EA replacement chip.

@xedbg do you have an AVR-EB you can sacrifice for the sake of science? 😄 We want to verify that we can write to that PDICFG fuse, which is the first two-byte fuse I've encountered in an AVR.

stefanrueger commented 1 year ago

OK, understood; easy for me to make suggestions that might brick other people's parts :open_mouth:

My reading of the data sheet is that the key mechanism for pdicfg is exactly here to prevent people from inadvertently writing 0x0002 to pdicfg. Hence, I am not convinced the observed behaviour is a bug!

You could try -c dryrun to see whether the logic of reading/writing the two-byte fuse pdicfg works in principle. This fuse is supposed to have a bitmask of 0xfff3. For AVRDUDE this means that Bits 2:3 will not be verified. Note that AVRDUDE will not prevent the terminal nor the command line -U from setting these bits to any value the user likes. This is because sometimes the data sheet says unused bits must be written as 1 and sometimes it says they must be written as 0. AVRDUDE does not have that deep understanding of the 4607 memories of the 355 parts it knows about (and I doubt the ATDF files model this).

Also note that -c dryrun does not closely emulate the chip. So you will be able to write 0xffff and read back 0xffff in -c dryrun:

$ (memory-types) avrdude -qqc dryrun -p avr16eb28 -t
avrdude> r pdicfg
0000  03 00                                             |..              |
avrdude> w pdicfg 0 0xffff
avrdude> r pdicfg
0000  ff ff                                             |..              |

Best to test this in the branch of PR #1538: This is the next one to merge (and alters how memories are located, read or written).

askn37 commented 1 year ago

This is my personal opinion, but this is how I write it in my configuration file.

    # *** CAUTION ***
    # The 'fuses' of the AVR_EB series is originally 11 bytes, 
    # but is limited to 9 bytes here to avoid irrecoverable failures. 
    # To overwrite the last two bytes added, 
    # explicitly specify 'fusea' or 'pdicfg'.
    memory "fuses"
        size               = 9;
        page_size          = 16;
        offset             = 0x1050;
        readsize           = 16;
    ;

This prevents you from accidentally touching the two bytes in question when you back up the "fuse" to a file and write it back. Regarding handling, we have clarified that, like LOCK_BITS, they are parameters that should be managed individually depending on the purpose (although they are consecutive in position).

MCUdude commented 1 year ago

I can't get SerialUPDI to work with the AVR16EB32. I also tested using PR #1543, but I'm getting the same result. I don't know enough about the UPDI protocol and the difference between the different NVM versions (@dbuchwald):

$ ./avrdude -cserialupdi -pavr16eb32 -P ch340 -Uflash:r:-:I
avrdude warning: unsupported NVM type: 5, please update software
avrdude error: decode SIB_INFO failed
avrdude error: initialization failed, rc=-1
        - double check the connections and try again
        - use -b to set lower baud rate, e.g. -b 57600
        - use -F to override this check

avrdude done.  Thank you.
Verbose output: ``` $ ./avrdude -cserialupdi -pavr16eb32 -P ch340 -vvvv avrdude: Version 7.2-20230720 Copyright the AVRDUDE authors; see https://github.com/avrdudes/avrdude/blob/main/AUTHORS System wide configuration file is /Users/hans/Downloads/avrdude-terminal/src/avrdude.conf User configuration file is /Users/hans/.avrduderc Using Port : /dev/cu.usbserial-1410 Using Programmer : serialupdi avrdude: opening serial port ... avrdude: sending 1 bytes [0x00] avrdude: send: . [00] avrdude: recv: . [00] AVR Part : AVR16EB32 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 ----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- --------- fuse0 wdtcfg 0 0 0 0 no 1 1 0 0 0 0x00 0x00 Block Poll Page Polled Memory Type Alias Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack ----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- --------- fuse1 bodcfg 0 0 0 0 no 1 1 0 0 0 0x00 0x00 Block Poll Page Polled Memory Type Alias Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack ----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- --------- fuse2 osccfg 0 0 0 0 no 1 1 0 0 0 0x00 0x00 Block Poll Page Polled Memory Type Alias Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack ----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- --------- fuse5 syscfg0 0 0 0 0 no 1 1 0 0 0 0x00 0x00 Block Poll Page Polled Memory Type Alias Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack ----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- --------- fuse6 syscfg1 0 0 0 0 no 1 1 0 0 0 0x00 0x00 Block Poll Page Polled Memory Type Alias Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack ----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- --------- fuse7 codesize 0 0 0 0 no 1 1 0 0 0 0x00 0x00 Block Poll Page Polled Memory Type Alias Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack ----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- --------- fuse8 bootsize 0 0 0 0 no 1 1 0 0 0 0x00 0x00 Block Poll Page Polled Memory Type Alias Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack ----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- --------- fuses 0 0 0 0 no 16 16 0 0 0 0x00 0x00 Block Poll Page Polled Memory Type Alias Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack ----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- --------- lock 0 0 0 0 no 4 1 0 0 0 0x00 0x00 Block Poll Page Polled Memory Type Alias Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack ----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- --------- prodsig sigrow 0 0 0 0 no 128 128 0 0 0 0x00 0x00 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 1 0 0 0 0x00 0x00 Block Poll Page Polled Memory Type Alias Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack ----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- --------- tempsense 0 0 0 0 no 4 1 0 0 0 0x00 0x00 Block Poll Page Polled Memory Type Alias Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack ----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- --------- sernum 0 0 0 0 no 16 1 0 0 0 0x00 0x00 Block Poll Page Polled Memory Type Alias Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack ----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- --------- userrow usersig 0 0 0 0 no 64 64 0 0 0 0x00 0x00 Block Poll Page Polled Memory Type Alias Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack ----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- --------- data 0 0 0 0 no 0 1 0 0 0 0x00 0x00 Block Poll Page Polled Memory Type Alias Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack ----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- --------- io 0 0 0 0 no 4160 1 0 0 0 0x00 0x00 Block Poll Page Polled Memory Type Alias Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack ----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- --------- sib 0 0 0 0 no 32 1 0 0 0 0x00 0x00 Block Poll Page Polled Memory Type Alias Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack ----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- --------- eeprom 0 0 0 0 no 512 8 0 0 0 0x00 0x00 Block Poll Page Polled Memory Type Alias Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack ----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- --------- flash 0 0 0 0 no 16384 64 0 0 0 0x00 0x00 Block Poll Page Polled Memory Type Alias Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack ----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- --------- fusea pdicfg 0 0 0 0 no 2 1 0 0 0 0x00 0x00 Block Poll Page Polled Memory Type Alias Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack ----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- --------- bootrow 0 0 0 0 no 64 64 0 0 0 0x00 0x00 Programmer Type : serialupdi Description : SerialUPDI avrdude: STCS 0x08 to address 0x03 avrdude: sending 3 bytes [0x55, 0xc3, 0x08] avrdude: send: U [55] . [c3] . [08] avrdude: recv: U [55] . [c3] . [08] avrdude: STCS 0x80 to address 0x02 avrdude: sending 3 bytes [0x55, 0xc2, 0x80] avrdude: send: U [55] . [c2] . [80] avrdude: recv: U [55] . [c2] . [80] avrdude: LDCS from 0x00 avrdude: sending 2 bytes [0x55, 0x80] avrdude: send: U [55] . [80] avrdude: recv: U [55] . [80] avrdude: recv: 0 [30] avrdude: received 1 bytes [0x30] avrdude: UDPI init OK avrdude: UPDI link initialization OK avrdude: LDCS from 0x0B avrdude: sending 2 bytes [0x55, 0x8b] avrdude: send: U [55] . [8b] avrdude: recv: U [55] . [8b] avrdude: recv: . [82] avrdude: received 1 bytes [0x82] avrdude: sending 2 bytes [0x55, 0xe6] avrdude: send: U [55] . [e6] avrdude: recv: U [55] . [e6] avrdude: recv: A [41] V [56] R [52] [20] [20] [20] [20] [20] P [50] : [3a] 5 [35] D [44] : [3a] 1 [31] - [2d] 3 [33] M [4d] 2 [32] [20] ( [28] A [41] 0 [30] . [2e] 5 [35] 9 [39] B [42] 1 [31] D [44] . [2e] 0 [30] ) [29] . [00] avrdude: received 32 bytes [0x41, 0x56, 0x52, 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x3a, 0x35, 0x44, 0x3a, 0x31, 0x2d, 0x33, 0x4d, 0x32, 0x20, 0x28, 0x41, 0x30, 0x2e, 0x35, 0x39, 0x42, 0x31, 0x44, 0x2e, 0x30, 0x29, 0x00] avrdude: received SIB: [AVR P:5D:1-3M2 (A0.59B1D.0)] avrdude: Device family ID: AVR avrdude: NVM interface: P:5 avrdude: Debug interface: D:1 avrdude: PDI oscillator: 3M2 avrdude: Extra information: (A0.59B1D.0) avrdude serialupdi_decode_sib() [serialupdi.c:169] warning: unsupported NVM type: 5, please update software avrdude serialupdi_initialize() [serialupdi.c:631] error: decode SIB_INFO failed avrdude main() [main.c:1399] error: initialization failed, rc=-1 - double check the connections and try again - use -b to set lower baud rate, e.g. -b 57600 - use -F to override this check avrdude: leaving NVM programming mode avrdude: sending reset request avrdude: STCS 0x59 to address 0x08 avrdude: sending 3 bytes [0x55, 0xc8, 0x59] avrdude: send: U [55] . [c8] Y [59] avrdude: recv: U [55] . [c8] Y [59] avrdude: sending release reset request avrdude: STCS 0x00 to address 0x08 avrdude: sending 3 bytes [0x55, 0xc8, 0x00] avrdude: send: U [55] . [c8] . [00] avrdude: recv: U [55] . [c8] . [00] avrdude: STCS 0x0C to address 0x03 avrdude: sending 3 bytes [0x55, 0xc3, 0x0c] avrdude: send: U [55] . [c3] . [0c] avrdude: recv: U [55] . [c3] . [0c] avrdude done. Thank you. ```
MCUdude commented 1 year ago

The jtag2updi programmer can establish connection with the AVR16EB32, but it fails to write to flash, and when I dump the flash content after an erase, there's still corrupted content present. Not sure if this is because the jtag2updi fails to erase the part or fails to read the content.

$ ./avrdude -cjtag2updi -pavr16eb32 -P ch340 -Uflash:w:0x55_16B.hex 
avrdude error: bad response to set parameter command: RSP_ILLEGAL_PARAMETER
avrdude error: bad response to set parameter command: RSP_ILLEGAL_PARAMETER
avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1e943e (probably avr16eb32)
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: processing -U flash:w:0x55_16B.hex:i
avrdude: reading input file 0x55_16B.hex for flash
         with 16 bytes in 1 section within [0, 15]
         using 1 page and 48 pad bytes
avrdude: writing 16 bytes flash ...
Writing | ################################################## | 100% 0.03 s 
avrdude: 16 bytes of flash written
avrdude: verifying flash memory against 0x55_16B.hex
Reading | ################################################## | 100% 0.02 s 
avrdude warning: verification mismatch
        device 0x00 != input 0x55 at addr 0x0001 (error)
avrdude error: verification mismatch

avrdude done.  Thank you.

EDIT: The SerialUPDI programmer works great with the AVR64EA48, but has NVM type 3: 24-bit, page oriented. The jtag2updi also struggles with the AVR64EA48, similar to how it behaved when trying to interact with the AVR16EB32. I don't think there's much we can do about the jtag2updi programmer, since this would require a firmware update.

To summarize:

AVR-EA AVR-EB
SerialUPDI
jtag2updi
stefanrueger commented 1 year ago

Can you read the memories OK? Seeing as you can r/w the EB part with the pkobn_updi programmer you could prep the part to have a certain contents and then try to verify with jtag2updi.

I wonder where the

avrdude error: bad response to set parameter command: RSP_ILLEGAL_PARAMETER

messages come from. I pushed a commit onto PR #1538 that shows that.

Is it just flash that cannot be written?

MCUdude commented 1 year ago

@stefanrueger I'm having a hard time getting the same error messages as earlier. It seems like the jtag2updi programmer fails with a different kind of error. I'll try to prep the AVR-EB using the pkobn_updi.

``` $ ./avrdude -cjtag2updi -pavr64ea48 -P ch340 -Uflash:w:0x55_64B.hex:i -v avrdude: Version 7.2-20230720 Copyright the AVRDUDE authors; see https://github.com/avrdudes/avrdude/blob/main/AUTHORS System wide configuration file is /Users/hans/Downloads/avrdude-terminal/src/avrdude.conf User configuration file is /Users/hans/.avrduderc Using Port : /dev/cu.usbserial-1410 Using Programmer : jtag2updi JTAG ICE mkII sign-on message: Communications protocol version: 1 M_MCU: boot-loader FW version: 1 firmware version: 6.00 hardware version: 1 S_MCU: boot-loader FW version: 1 firmware version: 6.00 hardware version: 1 Serial number: 00:00:00:00:00:00 Device ID: JTAGICE mkII AVR Part : AVR64EA48 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 ----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- --------- fuse0 wdtcfg 0 0 0 0 no 1 1 0 0 0 0x00 0x00 fuse1 bodcfg 0 0 0 0 no 1 1 0 0 0 0x00 0x00 fuse2 osccfg 0 0 0 0 no 1 1 0 0 0 0x00 0x00 fuse5 syscfg0 0 0 0 0 no 1 1 0 0 0 0x00 0x00 fuse6 syscfg1 0 0 0 0 no 1 1 0 0 0 0x00 0x00 fuse7 codesize 0 0 0 0 no 1 1 0 0 0 0x00 0x00 fuse8 bootsize 0 0 0 0 no 1 1 0 0 0 0x00 0x00 fuses 0 0 0 0 no 16 16 0 0 0 0x00 0x00 lock 0 0 0 0 no 4 1 0 0 0 0x00 0x00 prodsig sigrow 0 0 0 0 no 128 128 0 0 0 0x00 0x00 signature 0 0 0 0 no 3 1 0 0 0 0x00 0x00 tempsense 0 0 0 0 no 4 1 0 0 0 0x00 0x00 sernum 0 0 0 0 no 16 1 0 0 0 0x00 0x00 userrow usersig 0 0 0 0 no 64 64 0 0 0 0x00 0x00 data 0 0 0 0 no 0 1 0 0 0 0x00 0x00 io 0 0 0 0 no 4160 1 0 0 0 0x00 0x00 sib 0 0 0 0 no 32 1 0 0 0 0x00 0x00 eeprom 0 0 0 0 no 512 8 0 0 0 0x00 0x00 flash 0 0 0 0 no 65536 128 0 0 0 0x00 0x00 Programmer Type : JTAGMKII_UPDI Description : JTAGv2 to UPDI bridge M_MCU HW version: 1 M_MCU FW version: 6.00 S_MCU HW version: 1 S_MCU FW version: 6.00 Serial number : 00:00:00:00:00:00 avrdude: silicon revision: 2.0 avrdude: AVR device initialized and ready to accept instructions avrdude: device signature = 0x1e961e (probably avr64ea48) 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: processing -U flash:w:0x55_64B.hex:i avrdude: reading input file 0x55_64B.hex for flash with 64 bytes in 1 section within [0, 0x3f] using 1 page and 64 pad bytes avrdude: writing 64 bytes flash ... Writing | -------------------------------------------------- | 0% 0.15 s avrdude jtagmkII_paged_write() error: bad response to write memory command: RSP_NO_TARGET_POWER avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude jtagmkII_write_byte() error: bad response to write memory command: RSP_NO_TARGET_POWER ***failed; avrdude: 64 bytes of flash written avrdude: verifying flash memory against 0x55_64B.hex Reading | -------------------------------------------------- | 0% 0.01 s avrdude jtagmkII_paged_load() error: bad response to read memory command: RSP_NO_TARGET_POWER avrdude jtagmkII_read_byte() error: bad response to read memory command: RSP_NO_TARGET_POWER avrdude avr_read_mem() error: unable to read byte at address 0x0000 avrdude avr_read_mem() error: read operation not supported for memory flash avrdude do_op() error: unable to read all of flash memory, rc=-2 avrdude jtagmkII_program_disable() error: bad response to leave progmode command: RSP_NO_TARGET_POWER avrdude jtagmkII_close() error: bad response to GO command: RSP_NO_TARGET_POWER avrdude jtagmkII_close() error: bad response to sign-off command: RSP_NO_TARGET_POWER avrdude done. Thank you. ```
stefanrueger commented 1 year ago

to avoid irrecoverable failures [...] back up [fuses] to a file and write back

@askn37 The AVRDUDE project likes avrdude.conf to describe the part close to its description in the data sheet or the .atdf files. Yes, there are risks of setting fuses to values one doesn't want or cannot recover. This comes with the territory of some individual fuses and, as a consequence, the fuses umbrella memory.

AVRDUDE enables backup and restoration of the full configuration state of modern chips via the fuses memory even though that entails risks. The manual warns in the description of the config terminal command: "It is quite possible, as is with direct writing to the underlying fuses and lock bits, to brick a part, i.e., make it unresponsive to further programming with the chosen programmer: here be dragons." I am sure the project would be amenable to a PR that adds similar warnings to other places.

@mcuee @MCUdude BTW, fuses as an explicit memory for the configuration state has been introduced for parts that have a UPDI interface (the "modern" parts). I like that concept and might suggest to introduce fuses for all other parts too. This enables backup and restoration of the configuration settings without having to know how many fuses a part has (and how they are called).

MCUdude commented 1 year ago

Let's focus on the AVR-EB

I'm having issues reading the fuses in terminal mode when using the pkobn_updi and PR #1538:

$ ./avrdude -cpkobn_updi -pavr16eb32 -qq -Ufuses:r:-:h
0x0,0x0,0x0,0xff,0xff,0xd0,0x7,0x0,0x0,0xff,0x3,0x0,0xff,0xff,0xff,0xff
$ ./avrdude -cpkobn_updi -pavr16eb32 -qq -Ufuse0:r:-:h
0x0
$ ./avrdude -cpkobn_updi -pavr16eb32 -qq -Ufuse1:r:-:h
0x0
$ ./avrdude -cpkobn_updi -pavr16eb32 -qq -Ufuse2:r:-:h
0xff
$ ./avrdude -cpkobn_updi -pavr16eb32 -qq -Ufuse5:r:-:h
0x3
$ ./avrdude -cpkobn_updi -pavr16eb32 -qq -Ufuse6:r:-:h
0xff
$ ./avrdude -cpkobn_updi -pavr16eb32 -qq -Ufuse7:r:-:h
0xff
$ ./avrdude -cpkobn_updi -pavr16eb32 -qq -Ufuse8:r:-:h
0x21
$ ./avrdude -cpkobn_updi -pavr16eb32 -qq -Ufusea:r:-:h
0xff,0xff

$ ./avrdude -cpkobn_updi -pavr16eb32 -qq -T 'read fuses'
0000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
$ ./avrdude -cpkobn_updi -pavr16eb32 -qq -T 'read fuse0'
0000  00                                                |.               |
$ ./avrdude -cpkobn_updi -pavr16eb32 -qq -T 'read fuse1'
0000  00                                                |.               |
$ ./avrdude -cpkobn_updi -pavr16eb32 -qq -T 'read fuse2'
0000  ff                                                |.               |
$ ./avrdude -cpkobn_updi -pavr16eb32 -qq -T 'read fuse5'
0000  03                                                |.               |
$ ./avrdude -cpkobn_updi -pavr16eb32 -qq -T 'read fuse6'
0000  ff                                                |.               |
$ ./avrdude -cpkobn_updi -pavr16eb32 -qq -T 'read fuse7'
0000  ff                                                |.               |
$ ./avrdude -cpkobn_updi -pavr16eb32 -qq -T 'read fuse8'
0000  21                                                |!               |
$ ./avrdude -cpkobn_updi -pavr16eb32 -qq -T 'read fusea'
0000  ff ff                                             |..              |

However, I'm not having any issues when using git main:

$ ./avrdude -cpkobn_updi -pavr16eb32 -qq -T 'read fuses'
0000  00 00 00 ff ff d0 07 00  00 ff 03 00 ff ff ff ff  |................|

EDIT: Let me check if this is because I forgot to run make clean first.

EDIT2: running make clean didn't help. PR #1538 breaks reading fuses in terminal mode on AVR-EBs.

Even -U fuse readings (see fusea output) is wrong:

$ ./avrdude -cpkobn_updi -pavr16eb32 -qq -Ufuses:r:-:h
0x0,0x0,0x0,0xff,0xff,0xd0,0x7,0x0,0x0,0xff,0x3,0x0,0xff,0xff,0xff,0xff
$ ./avrdude -cpkobn_updi -pavr16eb32 -qq -Ufusea:r:-:h
0xff,0xff
askn37 commented 1 year ago

@mcuee , @MCUdude , @stefanrueger

Important information. AVR16EB32's UPDI_SIB seems to return P:5. Please check with actual chip. After that, a new patch will be required. However, looking at the datasheet and ATDF, it is expected that it will be the same method as P:3, so it seems better to tentatively treat P:5 and P:3 equally.

[Source] https://github.com/avrdudes/avrdude/issues/1546#issuecomment-1785787992

[Related source files] "serialupdi.c" "updi_nvm.c" "updi_state.h" (And more)

[P.S. 1] JTAG2UPDI usually does not check UPDI_SIB. Switch NVMCTRLv0/2 by guessing from the page size. And there probably isn't any code for v3 yet. (To add SIB check to JTAG2UPDI, "DEDUCE_NVM_VERSION_FROM_SIB" macro definition and rebuild are required)

[P.S.2] "pkobn_updi = Curiosity nano (nEDBG) via UPDI" is running in Microchip's firmware, so the P:5 should know about it. If there is a problem with the memory map, the problem is most likely on the "avrdude" side.

PKOB nano support 1.13.715 (2023-10-25) https://packs.download.microchip.com From pack-status-202310252033.3108.xml NB: This toolpack supersedes and replaces version 1.12.711 which is now deprecated. FW5G-1305 Post-build processing of artifact to workaround MPLABX-8013 FW5G-1306 nEDBG 1.30.35 Firmware release process

askn37 commented 1 year ago

@MCUdude

We have created a PR to continue this research. "serialupdi" should also allow the AVR_EB handling process to continue. Please try it.

dbuchwald commented 1 year ago

@stefanrueger sorry for delay in reply. The error message you are observing (avrdude warning: unsupported NVM type: 5, please update software) comes directly from the pymcuprog port, and is related to chip reporting NVM protocol version 5 which (at the time) has not been supported. Thing is, I don't really know if this is the right value (as @askn37 mentioned, ATDF file seems to indicate it should be NVM version 3), and even if it really is NVM v5, then the protocol doesn't seem to be documented. Maybe there is something wrong with the engineering samples batch?

I can see that fix proposal has already been posted, and I reviewed it.

If it turns out that new memory map and using NVM v5 as if it was NVM v3 doesn't work (and it might not), I will need to compare datasheets of working chips (like the EA family) against EB and see if there are any functional differences between them. Not having access to the actual device will slow things down probably, but it's not like we have other options anyway...

MCUdude commented 1 year ago

Thing is, I don't really know if this is the right value (as @askn37 mentioned, ATDF file seems to indicate it should be NVM version 3), and even if it really is NVM v5, then the protocol doesn't seem to be documented. Maybe there is something wrong with the engineering samples batch?

@xedbg probably knows whenever the AVR-EBs are NVM v3 or v5, or what the deal is. The date code on my AVR16EB32 is 2332 (week 32 year 2023), and the Curiosity Nano board it's soldered on says "2023.09.25", so they are both pretty fresh out of the oven.

I'll carry out some tests to see if the AVR-EB will work with PR #1549

xedbg commented 1 year ago

AVR EB: pymcuprog.serialupdi.application - INFO - SIB: 'AVR P:5D:1-3M2 (A0.59B1D.0)'

also FYI: we are hoping to squeeze out an update to pymcuprog this sprint.

MCUdude commented 1 year ago

AVR EB: pymcuprog.serialupdi.application - INFO - SIB: 'AVR P:5D:1-3M2 (A0.59B1D.0)'

Good! This is exactly what I'm getting as well:

$ ./avrdude -cpkobn_updi -pavr16eb32 -qq -Usib:r:-:r
AVR     P:5D:1-3M2 (A0.59B1D.0)

Important information. AVR16EB32's UPDI_SIB seems to return P:5. Please check with actual chip. After that, a new patch will be required. However, looking at the datasheet and ATDF, it is expected that it will be the same method as P:3, so it seems better to tentatively treat P:5 and P:3 equally.

Are there any differences between NVM v3 and NVM v5 that we should take into account?

dbuchwald commented 1 year ago

Are there any differences between NVM v3 and NVM v5 that we should take into account?

This is very good question. @xedbg mentioned update to pymcuprog is coming - if it does provide support for NVM v5, I will be able to "copy-paste" the same thing to AVRDUDE, following the initial implementation. Otherwise we can try to compare datasheets and try to find discrepancies, but again, this is based on the assumptions that datasheets at this point will be correct and up-to-date.

mcuee commented 1 year ago

EDIT: The SerialUPDI programmer works great with the AVR64EA48, but has NVM type 3: 24-bit, page oriented. The jtag2updi also struggles with the AVR64EA48, similar to how it behaved when trying to interact with the AVR16EB32. I don't think there's much we can do about the jtag2updi programmer, since this would require a firmware update.

To summarize:

AVR-EA AVR-EB
SerialUPDI
jtag2updi

@ElTangas

Just wondering if you can upgrade the jtag2updi FW (and maybe also avrdude codes) to support AVR EA and AVR EB. https://github.com/ElTangas/jtag2updi

askn37 commented 1 year ago

Just wondering if you can upgrade the jtag2updi FW (and maybe also avrdude codes) to support AVR EA and AVR EB.

No, I'm sure you can write it... For reference, the firmware implementation of UPDI4AVR's "JTAGmkII compatible" AVR_EA (P:3) was completed half a year ago and is running very smoothly.

https://github.com/askn37/multix-zinnia-updi4avr-firmware-builder/blob/main/libraries/UPDI4AVR/examples/UPDI4AVR_FW753B/src/NVM.cpp#L559

MCUdude commented 1 year ago

@askn37 so updi4avr is a drop-in replacement for the jtag2updi firmware that hasn't seen any updates recently?

askn37 commented 1 year ago

We will explain the main points of the NVMCTRL algorithm for AVR_EA(P:3).

All memory reads on P:3 are compatible with P:2 (AVR_Dx). Flash address width is 24 bits. Others are 16bit.

Memory writing for P:3 is different from P:2. It's more like P:0. Because there is a hidden memory buffer. That is, after filling the buffer, we tell NVMCTRL to really write the memory. The difference with P:0 is that the flash address width is 24 bits instead of 16 bits. The NVMCTRL command table is also specific to P:3. Because of this, AVR-LIBC has made mistakes in the past.

Below, when writing a command to NVMCTRL, write CMD_NOCMD in advance and wait until the busy bit of NVMCTRL_STATUS becomes empty.

When writing to FLASH with P:3

When writing to EEPROM with P:3

Note

The USERROW of P:0 is EEPROM, but the USERROW of P:2 and P:3 is FLASH. Chip erase is not supported, so blocks must be erased and written in words before writing. However, terminal mode is a byte-by-byte access interface. So writing USERROW byte by byte to the unlocked device on P:2/P:3 from terminal mode requires a logic synthesis trick. (When writing in bulk with normal -U, it is not difficult if you also perform block erase as a set.)

askn37 commented 1 year ago

@askn37 so updi4avr is a drop-in replacement for the jtag2updi firmware that hasn't seen any updates recently?

From avrdude, it can be treated as upward compatible with JTAG2UPDI. Works with old "jtagmkII_pdi + has_updi" or new "jtagmkii_updi + PM_UPDI" configuration files.

However, the chip running the firmware must be newer than the tinyAVR-2. The UPDI interface utilizes the single wire RS485 mode of the hardware UART. Therefore, this is not a fork or variant of JTAG2UPDI. The source code also doesn't match.

I used to be satisfied with mEDBG, but I had a job that required AVR_DB, so I created 24-bit compatible firmware, created a dedicated circuit, and created and wrote a bootloader myself. After repeated improvements, it is now possible to control the high voltage of AVR_EA. The reason I have so many bare chips is to verify my work. And the rival is "serialupdi". Well, because I always want to be fair...

"It's noble to extend a helping hand to your enemy, if only for a short while."

stefanrueger commented 1 year ago

extend a helping hand to your enemy

:smile: Yes, Open Source at its best is healthy co-petition (co-operation and competition). As you know, @askn37, AVRDUDE is quite modular, and you (or anyone else for that matter) are welcome to contribute -c programmers.

mcuee commented 1 year ago

I used to be satisfied with mEDBG, but I had a job that required AVR_DB, so I created 24-bit compatible firmware, created a dedicated circuit, and created and wrote a bootloader myself. After repeated improvements, it is now possible to control the high voltage of AVR_EA. The reason I have so many bare chips is to verify my work. And the rival is "serialupdi". Well, because I always want to be fair...

Indeed serialupdi is probably the way to go for hobbist users when it comes to UPDI parts. jtag2updi is of course another contender. For users who are willing to pay a bit more, I think Microchip SNAP may be the way to go. It is a pity that PICKit 4 is now considered obsolete.

For classic AVRs, usbasp may be the way to go for hobbist users who want to get started. Of course you can also use things like Arduino as ISP as well. For users who are willing to pay a bit more, maybe AVRISP mkII clone or Microchip SNAP is the way to go. Again it is a pity that PICKit 4 is now considered obsolete.

askn37 commented 1 year ago

@mcuee

Indeed serialupdi is probably the way to go for hobbist users when it comes to UPDI parts.

This invention was revolutionary. It's very cheap and easy to make. Feel free to give it away to your friends for free. But there was another problem.

On the other hand, classic approaches like the STK500 version 1/2 protocol are simple on the host PC side. Basically, you can speak in your native language and let the adapter do the translation to his UPDI/PDI/TPI. Depending on the design, it is possible to maintain high communication quality. Those who create adapters are free to choose the method that works best for them. It can then be turned into a black box or its design can be made widely available for cloning. If you have someone who can handle the tedious task of updating firmware, you may want to ask that person to keep an eye on it. (I don't know if I can contact you or not)

dbuchwald commented 1 year ago

Again it is a pity that PICKit 4 is now considered obsolete.

Maybe this is not the right forum for it, but this is one of the problems I have with Microchip products - they become obsolete too often and too fast. This is probably irrelevant to corporate customers with deep pockets, but for hobbyists like myself this is showstopper.

To be fair, my whole involvement with AVRDUDE started with a hobbyist project based on 128DB64 chip, but I have never completed it, as the main issue is the availability of the chips and constant stream of "newer, better" chips which become obsolete before they get really available on the market. I don't want to spend months on writing software and designing schematic for something that simply can't be built and used by anyone else because the chip has been superseded by something no longer backwards compatible.

As for the UPDI - it seemed like a perfect solution, but it's a solution in the making. My concern is that when we finally reach some maturity level of NVM protocol it will get superseded by something "newer and better"...

Anyway, sorry for the rant.

mcuee commented 1 year ago

Maybe this is not the right forum for it, but this is one of the problems I have with Microchip products - they become obsolete too often and too fast. This is probably irrelevant to corporate customers with deep pockets, but for hobbyists like myself this is showstopper.

To be fair, the Microchip part of the current Microchip does not obsolete chips often -- for example, they still provide old PICs. The Atmel part of the current Microchip is not so well-known to keep parts alive as long as the Microchip part. Just a simple example, the first gen AT90 AVRs did not last long. Luckily I chose the right part (PIC16C72A) back in 1999 for a new project in my previous job. My colleagues in Germany liked AVR more at that time (and for sure I agreed with them that AVRs had a better architecture than PICs). Microchip still support PIC16C72A now -- just not recommended for new design. https://www.microchip.com/en-us/product/pic16c72a

On the development tool side, I think PICKit 4 is a bit unfortunate. Microchip did obsolete old tools more often compared to chips but I think usually not so fast.

In this word of 32bit MCUs (At work, we mainly use ARM Cortex MCUs now. Even Arduino Uno 4 is now based on ARM Cortex MCUs), I think we still need to pay respect to Microchip to continue the development of PICs and AVRs.

BTW, in my current job and previous job, the product life cycle is very long (it can be more than 30 years). So I am pretty careful in choosing parts. For sure, you can not avoid component obsolescences, but it is better to have less big redesigns which involves MCU changes.

The chip shortages in the past few years are probably not the norm either and indeed Microhip MCU lead time was super long, same for STM32.

askn37 commented 1 year ago

@dbuchwald

As for the UPDI - it seemed like a perfect solution, but it's a solution in the making. My concern is that when we finally reach some maturity level of NVM protocol it will get superseded by something "newer and better"...

It is expected that the next 10 years or so will continue to be based on UPDI. Since there is only one wire, it is not possible to reduce the number of wires any further. Also note that the USART peripheral on modern AVRs can easily implement native host/guest for the UPDI protocol. This technology is derived from a low-speed, low-cost, single-wire communication standard for automotive applications. Microchip let the former ATMEL development team they had acquired use it. In addition to a regular CPU, all modern AVRs have a small, simple, and inexpensive sub-CPU dedicated to UPDI, and a sub-UART dedicated to UPDI with reduced circuitry. This quickly replaced the large, complex, and expensive PDI-specific logic circuits. That's probably why the wholesale price of chips has almost halved.

MPLAB SNAP

In Japan, prices have increased several times over the past few years. It's not cheap at all. We only offer low prices during the campaign period for new products. To support AVR_DA and later, a soldering iron must be prepared and modified. Also, just rewriting the firmware requires downloading dozens of GiB of his MPLAB. Since there is no insulating case, it is not suitable for children's education. Speaking of insulation, the PICkit4's decorative panels are unpainted and conduct electricity. If you put other exposed boards on top of it and turn it on, you'll be in trouble. (I did it. LIB rechargeable battery caught fire)

askn37 commented 1 year ago

Anxiety about future product development

Why is AVR_DU on hold? It was a promising replacement for his outdated AT90USB. (With this, UPDI4AVR can be modified to replace USBASP.)

I don't understand why AVR_EA was created. There is no price difference with AVR_DB, but it is a mystery whether it is the same clock as the ****AVR generation.

However, one can imagine that his AVR_EB and derivative products based on it are specifically designed for certain large customers. They removed his TCA timer. Also equipped with a wave generator and new TCE/TCF. This is a much more complex circuit than his TCD for synchronous motor control, and it's hard to immediately think of what it could be used for. It feels a bit extravagant to incorporate it into hundreds of spotlights for stage lighting.

AVR_Ex appears to be an application-specific derivative series that replaces part of the PIC. The advantage is that it can be written in C/C++ and can also be easily written using assembly instructions such as PIC. It is much more reliable than ARM in terms of high temperature resistance. On the other hand, it is not very suitable for enthusiasts.

mcuee commented 1 year ago

Due to USB-CDC limitations, reliability above a certain speed cannot be expected. It is impossible for the response speed to be less than 1ms, and if you connect a hub, it will become slower and slower, and packet loss will occur frequently. Code without a retry loop will always have problems

Actually the moderin USB to Serial chip (dedicated IC like CH340x, FT232R, FT232H, FT2232H, CP2102, PL2303, etc) do not use USB CDC-ACM protocol in general. FT232H/FT2232H are capable of high speed USB.

And full speed USB (12Mbps line rate, but slower at real world) is good enough to go with 230400bps which is good enough for AVR programming. 1ms polling interval is an issue for USB interrupt endpoint (up to 64B/1ms) but not USB bulk endpoint (you can have up to 9 bulk packets within the 1ms USB frame --> 64B x 19 /ms= 1216B/1ms ). https://github.com/SpenceKonde/AVR-Guidance/blob/master/UPDI/jtag2updi.md

Even the low cost CH340x based serialupdi adapter can do 230,400 bps as per the above article (and I tested it as well).

xedbg commented 1 year ago

FYI an untested pymcuprog has been pushed to pypi-test: https://test.pypi.org/project/pymcuprog/3.16.7.38/ (its a wheel, but can be unzipped. basics work, but if there are obvious issues or glaring questions, please shout asap)

MCUdude commented 1 year ago

Thanks @xedbg!

For those who are interested, here are the source files: pymcuprog-3.16.7.38-py3-none-any.zip

It turns out that:

NVM version Chip family File
0 tiny0/1/2, mega8 nvmp0.py
1
2 AVR DA/DB/DD nvmp2.py
3 AVR EA nvmp3.py
4 AVR DU nvmp4.py
5 AVR EB nvmp5.py

The only difference I can spot between version 3 and version 5 is the addition of NVMCTRLC:

$ git diff nvmp3.py nvmp5.py
diff --git a/nvmp3.py b/nvmp5.py
index 456ad1b..51e8dc1 100755
--- a/nvmp3.py
+++ b/nvmp5.py
@@ -1,21 +1,22 @@
 """
-NVM controller implementation for P:3.
+NVM controller implementation for P:5.

-Present on, for example, AVR EA
+Present on, for example, AVR EB
 """
 from logging import getLogger
 from .nvm import NvmUpdi
 from .timeout import Timeout
 from ..pymcuprog_errors import PymcuprogSerialUpdiNvmTimeout, PymcuprogSerialUpdiNvmError

-class NvmUpdiP3(NvmUpdi):
+class NvmUpdiP5(NvmUpdi):
     """
-    Version P:3 UPDI NVM properties
+    Version P:5 UPDI NVM properties
     """

     # NVM CTRL peripheral definition
     NVMCTRL_CTRLA = 0x00
     NVMCTRL_CTRLB = 0x01
+    NVMCTRL_CTRLC = 0x02
     NVMCTRL_INTCTRL = 0x04
     NVMCTRL_INTFLAGS = 0x05
     NVMCTRL_STATUS = 0x06

And NVMCTRL_CTRLC doesn't seem to be utilized anywhere...

hans@Bull:/mnt/c/Users/Hans/Downloads/pymcuprog-3.16.7.38-py3-none-any/pymcuprog$ grep -r NVMCTRL_CTRLC *
serialupdi/nvmp4.py:    NVMCTRL_CTRLC = 0x02
serialupdi/nvmp5.py:    NVMCTRL_CTRLC = 0x02

There are, however, much longer diff between version 3 and version 4:

diff nvmp3.py nvmp4.py ```diff $ git diff nvmp3.py nvmp4.py diff --git a/nvmp3.py b/nvmp4.py index 456ad1b..4f3567a 100755 --- a/nvmp3.py +++ b/nvmp4.py @@ -1,21 +1,22 @@ """ -NVM controller implementation for P:3. +NVM controller implementation for P:4. -Present on, for example, AVR EA +Present on, for example, AVR DU """ from logging import getLogger from .nvm import NvmUpdi from .timeout import Timeout from ..pymcuprog_errors import PymcuprogSerialUpdiNvmTimeout, PymcuprogSerialUpdiNvmError -class NvmUpdiP3(NvmUpdi): +class NvmUpdiP4(NvmUpdi): """ - Version P:3 UPDI NVM properties + Version P:4 UPDI NVM properties """ # NVM CTRL peripheral definition NVMCTRL_CTRLA = 0x00 NVMCTRL_CTRLB = 0x01 + NVMCTRL_CTRLC = 0x02 NVMCTRL_INTCTRL = 0x04 NVMCTRL_INTFLAGS = 0x05 NVMCTRL_STATUS = 0x06 @@ -25,14 +26,11 @@ class NvmUpdiP3(NvmUpdi): # CTRLA commands NVMCMD_NOCMD = 0x00 NVMCMD_NOOP = 0x01 - NVMCMD_FLASH_PAGE_WRITE = 0x04 - NVMCMD_FLASH_PAGE_ERASE_WRITE = 0x05 + NVMCMD_FLASH_WRITE = 0x02 NVMCMD_FLASH_PAGE_ERASE = 0x08 - NVMCMD_FLASH_PAGE_BUFFER_CLEAR = 0x0F - NVMCMD_EEPROM_PAGE_WRITE = 0x14 - NVMCMD_EEPROM_PAGE_ERASE_WRITE = 0x15 - NVMCMD_EEPROM_PAGE_ERASE = 0x17 - NVMCMD_EEPROM_PAGE_BUFFER_CLEAR = 0x1F + NVMCMD_EEPROM_WRITE = 0x12 + NVMCMD_EEPROM_ERASE_WRITE = 0x13 + NVMCMD_EEPROM_BYTE_ERASE = 0x18 NVMCMD_CHIP_ERASE = 0x20 NVMCMD_EEPROM_ERASE = 0x30 @@ -42,7 +40,6 @@ class NvmUpdiP3(NvmUpdi): STATUS_EEPROM_BUSY_bp = 0 STATUS_FLASH_BUSY_bp = 1 - def __init__(self, readwrite, device): NvmUpdi.__init__(self, readwrite, device) self.logger = getLogger(__name__) @@ -51,7 +48,7 @@ class NvmUpdiP3(NvmUpdi): """ Does a chip erase using the NVM controller - Note that on locked devices this is not possible and the ERASE KEY has to be used instead, see the unlock method + Note that on locked devices this it not possible and the ERASE KEY has to be used instead """ self.logger.debug("Chip erase using NVM CTRL") @@ -65,9 +62,9 @@ class NvmUpdiP3(NvmUpdi): # And wait for it status = self.wait_nvm_ready() - # Remove command + # Remove command from NVM controller + self.logger.debug("Clear NVM command") self.execute_nvm_command(self.NVMCMD_NOCMD) - if not status: raise PymcuprogSerialUpdiNvmTimeout("Timeout waiting for NVM controller to be ready after chip erase") @@ -85,21 +82,22 @@ class NvmUpdiP3(NvmUpdi): if not self.wait_nvm_ready(): raise PymcuprogSerialUpdiNvmTimeout("Timeout waiting for NVM controller to be ready before flash page erase") + # Erase command + self.execute_nvm_command(self.NVMCMD_FLASH_PAGE_ERASE) + # Dummy write self.readwrite.write_data(address, [0xFF]) - # Erase - self.execute_nvm_command(self.NVMCMD_FLASH_PAGE_ERASE) - # And wait for it status = self.wait_nvm_ready() - # Remove command + # Remove command from NVM controller + self.logger.debug("Clear NVM command") self.execute_nvm_command(self.NVMCMD_NOCMD) - if not status: raise PymcuprogSerialUpdiNvmTimeout("Timeout waiting for NVM controller to be ready after flash page erase") + def erase_eeprom(self): """ Erase EEPROM memory only @@ -116,12 +114,13 @@ class NvmUpdiP3(NvmUpdi): # And wait for it status = self.wait_nvm_ready() - # Remove command + # Remove command from NVM controller + self.logger.debug("Clear NVM command") self.execute_nvm_command(self.NVMCMD_NOCMD) - if not status: raise PymcuprogSerialUpdiNvmTimeout("Timeout waiting for NVM controller to be ready after EEPROM erase") + def erase_user_row(self, address, size=0): """ Erase User Row memory only @@ -131,11 +130,9 @@ class NvmUpdiP3(NvmUpdi): :param size: Size of user row :type size: int, optional, not used for this variant """ - self.logger.debug("Erase user row") - # size is not used for this NVM version _dummy = size - # On this NVM version user row is implemented as FLASH + # On this NVM version user row is implemented as flash return self.erase_flash_page(address) def write_flash(self, address, data): @@ -158,20 +155,40 @@ class NvmUpdiP3(NvmUpdi): :param data: data to write :type data: list of bytes """ - # On this NVM variant user row is implemented as FLASH - return self.write_nvm(address, data, use_word_access=True) + # On this NVM variant user row is implemented as Flash + return self.write_nvm(address, data, use_word_access=False) def write_eeprom(self, address, data): """ - Write data to EEPROM + Writes data to NVM (EEPROM) :param address: address to write to :type address: int :param data: data to write :type data: list of bytes """ - return self.write_nvm(address, data, use_word_access=False, - nvmcommand=self.NVMCMD_EEPROM_PAGE_ERASE_WRITE) + nvm_command = self.NVMCMD_EEPROM_ERASE_WRITE + + # Check that NVM controller is ready + if not self.wait_nvm_ready(): + raise PymcuprogSerialUpdiNvmTimeout("Timeout waiting for NVM ready before command write") + + # Write the command to the NVM controller + self.logger.debug("NVM EEPROM erase/write command") + self.execute_nvm_command(nvm_command) + + # Write the data + self.readwrite.write_data(address, data) + + # Wait for NVM controller to be ready again + status = self.wait_nvm_ready() + # Remove command from NVM controller + self.logger.debug("Clear NVM command") + self.execute_nvm_command(self.NVMCMD_NOCMD) + + if not status: + raise PymcuprogSerialUpdiNvmTimeout("Timeout waiting for NVM ready after data write") + def write_fuse(self, address, data): """ @@ -182,14 +199,14 @@ class NvmUpdiP3(NvmUpdi): :param data: data to write :type data: list of bytes """ + # Fuses are EEPROM-based in this variant return self.write_eeprom(address, data) - def write_nvm(self, address, data, use_word_access, nvmcommand=NVMCMD_FLASH_PAGE_WRITE): + def write_nvm(self, address, data, use_word_access=True): """ - Writes a page of data to NVM + Writes data to NVM. - By default the PAGE_WRITE command is used, which requires that the page is already erased. - By default word access is used (required for flash) + This version of the NVM block has no page buffer, so words are written directly. :param address: address to write to :type address: int @@ -197,40 +214,33 @@ class NvmUpdiP3(NvmUpdi): :type data: list of bytes :param use_word_access: True for 16-bit writes (eg: flash) :type use_word_access: bool, defaults to True - :param nvmcommand: command to use for commit - :type nvmcommand: int, defaults to NVMCMD_PAGE_WRITE :raises: PymcuprogSerialUpdiNvmTimeout if a timeout occurred :raises: PymcuprogSerialUpdiNvmError if an error condition is encountered """ + nvm_command = self.NVMCMD_FLASH_WRITE # Check that NVM controller is ready if not self.wait_nvm_ready(): raise PymcuprogSerialUpdiNvmTimeout("Timeout waiting for NVM controller to be ready before page buffer clear") - # Clear the page buffer - self.logger.debug("Clear page buffer") - self.execute_nvm_command(self.NVMCMD_FLASH_PAGE_BUFFER_CLEAR) - - # Wait for NVM controller to be ready - if not self.wait_nvm_ready(): - raise PymcuprogSerialUpdiNvmTimeout("Timeout waiting for NVM controller to be ready after page buffer clear") + # Write the command to the NVM controller + self.logger.debug("NVM write command") + self.execute_nvm_command(nvm_command) - # Load the page buffer by writing directly to location + # Write the data if use_word_access: self.readwrite.write_data_words(address, data) else: self.readwrite.write_data(address, data) - # Write the page to NVM, maybe erase first - self.logger.debug("Committing data") - self.execute_nvm_command(nvmcommand) - # Wait for NVM controller to be ready again - if not self.wait_nvm_ready(): - raise PymcuprogSerialUpdiNvmTimeout("Timeout waiting for NVM controller to be ready after page write") + status = self.wait_nvm_ready() - # Remove command + # Remove command from NVM controller + self.logger.debug("Clear NVM command") self.execute_nvm_command(self.NVMCMD_NOCMD) + if not status: + raise PymcuprogSerialUpdiNvmTimeout("Timeout waiting for NVM controller to be ready after data write") def wait_nvm_ready(self, timeout_ms=100): """ ```
xedbg commented 1 year ago

"Versioning" in the SIB should not really be interpreted as "linear progression from the previous" - the Dx and Ex families have some fundamental differences (like page vs word-oriented), and the order in which these family members have been designed makes the SIB versioning more like "odds vs evens". Just how it is :)

askn37 commented 1 year ago

https://ww1.microchip.com/downloads/aemDocuments/documents/MCU08/ProductDocuments/DataSheets/AVR16EB14_20_28_32-Prelim-DataSheet-DS40002522.pdf

11. NVMCTRL - Nonvolatile Memory Controller
11.5 Register Description
11.5.3 Control C

Name:  CTRLC
Offset: 0x02
Reset: 0x0
Property: Configuration Change Protection
Reset:  x x x x x x 0 0

Bit 1 – BOOTROWWP Boot Row Write Protection

- Writing this bit to ‘1’ prevents further updates to the Boot Row. Only a Reset can clear this bit. 

Bit 0 – UROWWP User Row Write Protection

- Writing this bit to ‘1’ prevents further updates to the User Row. Only a Reset can clear this bit.
stefanrueger commented 1 year ago

I think this Issue has undergone a bit of a shift but hope that once #1549 is merged we can close it

mcuee commented 1 year ago

I think this Issue has undergone a bit of a shift but hope that once #1549 is merged we can close it

I agree.