Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

issue #1600 Bootloader enhancements #1614

Closed
wants to merge 6 commits into from

Conversation

askn37
Copy link
Contributor

@askn37 askn37 commented Jan 9, 2024

This is the memory read enhancement patch for the Adruino compatible bootloader mentioned in issue #1600.

Allows the following memory reads similar to EEPROM only for PM_SPM + PM_UPDI parts.
This trick works for all bootloaders that support READ memchr == 'E'.
-U : userrow usersig bootrow sigrow prodsig and signature
-T dump : userrow and bootrow

This trick is useful if OCD or UPDI control becomes unavailable for some reason (damaged pins due to high voltage, unintentional FUSE rewrite, etc.) but the bootloader is still working. This is important for debugging and verification tasks because BOOTROW can only be read by boot code.

The good thing about bootloaders is that there is no risk of further damage to the chip.

There are some things that can be read with -U but not with -T dump. This is probably because it is currently prohibited by avr_has_paged_access(pgm, mem). Unfortunately, I can't read LOCK and FUSE as a result.

A similar implementation is possible in urclock.c, but it is not as easily extended as stk500.c. I tried it, but this time I gave up. It seems like there are too many things that need to be redone.

The ability to write USERROW and BOOTROW is not integrated at this time as it requires new BIGBOOT development. At least someone has to decide on memory types other than "F" and "E".
(Example: "X". For this he needs an absolute address in 64KiB space. Using a relative address like 'E' will make the boot code obese)

P.S.1 : I don't think this patch will be rushed to 7.3. Because that may still be up for debate.
P.S.2 : There is one place in the code to suppress extra warnings that are not related to the PM_UPDI part.

@mcuee mcuee added the enhancement New feature or request label Jan 10, 2024
@mcuee mcuee changed the title issue#1600 Bootloader enhancements issue #1600 Bootloader enhancements Jan 10, 2024
@stefanrueger
Copy link
Collaborator

The underlying trick is vvv cool, but the implementation looks too ad-hoc and specific. We should think bigger:

  • Check whether any UPDI memory can fully be reached with bootloader E or F addressing by applying the offset trick (currently the code uses the name of the memory but does not check whether the memory can actually be reached)
  • It should be implemented for all programmers that support the bootloader not just one
  • It should be documented otherwise how would users know they can do that?
  • It should be implemented in the terminal as well (which may require a rethink of the terminal caching model and what pagewise access means)

So, yes, it is a bigger piece of work for this PR (or another one with the same goal) to become truly useful.

Also, the suppression of the warning looks like doctoring the symptoms, rather than the underlying cause: I suspect that a programmer for UPDI parts piggy-backs on stk500 code that was originally developed for classic parts. It would be better if there was a clearer steer in the code what should happen if the to-be-programmed part is a UPDI part. For readability and otherwise.

@askn37
Copy link
Contributor Author

askn37 commented Jan 12, 2024

Also, the suppression of the warning looks like doctoring the symptoms, rather than the underlying cause:

Upon closer inspection, none of the variants of "optiboot_x" handle Cmnd_STK_SET_DEVICE and simply return Resp_STK_OK. So this can be handled more concisely.

   if ((rc = stk500_getparm(pgm, Parm_STK_SW_MAJOR, &maj)) < 0
      || (rc = stk500_getparm(pgm, Parm_STK_SW_MINOR, &min)) < 0 ) {
     pmsg_error("cannot obtain SW version\n");
     return rc;
   }
 
+  // For "optiboot_x" variant
+  // The responses after this are dummy and unnecessary.
+  if (str_eq(pgmid, "arduino") && p->prog_modes & PM_UPDI)
+    return pgm->program_enable(pgm, p);
+
   // MIB510 does not need extparams
   if (str_eq(pgmid, "mib510"))
     n_extparms = 0;

This looks like even more shoddy code. Therefore, it seems good to extend the "modernAVR" mode with the "-x" option...

rather than the underlying cause: I suspect that a programmer for UPDI parts piggy-backs on stk500 code that was originally developed for classic parts.

This should have been the best, at least when only tinyAVR and megaAVR existed. Due to its open design, his STK500v1 can be used with a serial port, data length and address can be specified in the request, and there is no checksum in the response. It's very simple. Other products, such as the AVR109, directly packetize SPI instructions, so they are not suitable for Microchip-era AVRs with linear memory.

It would be better if there was a clearer steer in the code what should happen if the to-be-programmed part is a UPDI part. For readability and otherwise.

Even if everything is integrated into urlock in the future, the STK500 code is confusing and outdated at first glance, but its purpose and implementation is clear and easy to add to and modify. Suitable for repeating various experiments and verifications. I think that's why code has historically been extended repeatedly to become larger code.

@askn37
Copy link
Contributor Author

askn37 commented Jan 14, 2024

Adopted -xem option.

avrdude -c arduino extended options:
  -xattempts=<arg>      Specify no. connection retry attempts
  -xem                  Enables enhanced memory instructions (optiboot_x etc.)
  -xhelp                Show this help menu and exit

There used to be an option that was not in the manual, but this was also fixed at the same time.
In other words, I stopped using STK500 and started using -c arduino dedicated processing functions.

Previous Usage
avrdude -c arduino extended options:
  -xattempts=<arg>      Specify no. connection retry attempts
  -xxtal=<arg>[M|k]     Set programmer xtal frequency
  -xhelp                Show this help menu and exit

If you do not use -xem, the behavior is unchanged. Nothing changes. I am careful to do so.

Memory optiboot_x read test summary without -xem option
askn@alicia BOOT_TEST % ./boot_noxem_test.sh
[target] -c arduino -p m4808 -P /dev/cu.usbserial-230

Memory            Size  Pg size  Offset
---------------------------------------
eeprom             256       64  0x1400 
flash            49152      128  0x4000 
fuses               10        1  0x1280 
fuse0/wdtcfg         1        1  0x1280 
fuse1/bodcfg         1        1  0x1281 
fuse2/osccfg         1        1  0x1282 
fuse5/syscfg0        1        1  0x1285 
fuse6/syscfg1        1        1  0x1286 
fuse7/append         1        1  0x1287 
fuse8/bootend        1        1  0x1288 
lock                 1        1  0x128a 
prodsig/sigrow     128      128  0x1100 
signature            3        1  0x1100 
sernum              10        1  0x1103 
osccal16             2        1  0x1118 
osccal20             2        1  0x111a 
tempsense            2        1  0x1120 
osc16err             2        1  0x1122 
osc20err             2        1  0x1124 
userrow/usersig     64       64  0x1300 
io                4352        1       0 
sram              6144        1  0x2800 
sib                 32        1       0 
[verify] eeprom size=256
[verify] flash size=49152
[verify] fuses avrdude error: (save) error reading fuses address 0x0 of part ATmega4808
[verify] fuse0 avrdude error: (save) error reading fuse0 address 0x0 of part ATmega4808
[verify] wdtcfg avrdude error: (save) error reading fuse0 address 0x0 of part ATmega4808
[verify] fuse1 avrdude error: (save) error reading fuse1 address 0x0 of part ATmega4808
[verify] bodcfg avrdude error: (save) error reading fuse1 address 0x0 of part ATmega4808
[verify] fuse2 avrdude error: (save) error reading fuse2 address 0x0 of part ATmega4808
[verify] osccfg avrdude error: (save) error reading fuse2 address 0x0 of part ATmega4808
[verify] fuse5 avrdude error: (save) error reading fuse5 address 0x0 of part ATmega4808
[verify] syscfg0 avrdude error: (save) error reading fuse5 address 0x0 of part ATmega4808
[verify] fuse6 avrdude error: (save) error reading fuse6 address 0x0 of part ATmega4808
[verify] syscfg1 avrdude error: (save) error reading fuse6 address 0x0 of part ATmega4808
[verify] fuse7 avrdude error: (save) error reading fuse7 address 0x0 of part ATmega4808
[verify] append avrdude error: (save) error reading fuse7 address 0x0 of part ATmega4808
[verify] fuse8 avrdude error: (save) error reading fuse8 address 0x0 of part ATmega4808
[verify] bootend avrdude error: (save) error reading fuse8 address 0x0 of part ATmega4808
[verify] lock avrdude error: (save) error reading lock address 0x0 of part ATmega4808
[verify] prodsig avrdude error: (save) error reading prodsig address 0x0 of part ATmega4808
[verify] sigrow avrdude error: (save) error reading prodsig address 0x0 of part ATmega4808
[verify] signature avrdude error: (save) error reading signature address 0x0 of part ATmega4808
[verify] sernum avrdude error: (save) error reading sernum address 0x0 of part ATmega4808
[verify] osccal16 avrdude error: (save) error reading osccal16 address 0x0 of part ATmega4808
[verify] osccal20 avrdude error: (save) error reading osccal20 address 0x0 of part ATmega4808
[verify] tempsense avrdude error: (save) error reading tempsense address 0x0 of part ATmega4808
[verify] osc16err avrdude error: (save) error reading osc16err address 0x0 of part ATmega4808
[verify] osc20err avrdude error: (save) error reading osc20err address 0x0 of part ATmega4808
[verify] userrow avrdude error: unable to read userrow page at addr 0x0000
avrdude error: (save) error reading userrow address 0x0 of part ATmega4808
[verify] usersig avrdude error: unable to read userrow page at addr 0x0000
avrdude error: (save) error reading userrow address 0x0 of part ATmega4808
done

Using -xem causes the following changes:

Memory optiboot_x read test summary with -xem option

boot_test.txt

askn@alicia BOOT_TEST % ./boot_xem_test.sh
[target] -c arduino -xem -p m4808 -P /dev/cu.usbserial-230

Memory            Size  Pg size  Offset
---------------------------------------
eeprom             256       64  0x1400 
flash            49152      128  0x4000 
fuses               10        1  0x1280 
fuse0/wdtcfg         1        1  0x1280 
fuse1/bodcfg         1        1  0x1281 
fuse2/osccfg         1        1  0x1282 
fuse5/syscfg0        1        1  0x1285 
fuse6/syscfg1        1        1  0x1286 
fuse7/append         1        1  0x1287 
fuse8/bootend        1        1  0x1288 
lock                 1        1  0x128a 
prodsig/sigrow     128      128  0x1100 
signature            3        1  0x1100 
sernum              10        1  0x1103 
osccal16             2        1  0x1118 
osccal20             2        1  0x111a 
tempsense            2        1  0x1120 
osc16err             2        1  0x1122 
osc20err             2        1  0x1124 
userrow/usersig     64       64  0x1300 
io                4352        1       0 
sram              6144        1  0x2800 
sib                 32        1       0 
[verify] eeprom size=256
[verify] flash size=49152
[verify] fuses size=10
[verify] fuse0 size=1
[verify] wdtcfg size=1
[verify] fuse1 size=1
[verify] bodcfg size=1
[verify] fuse2 size=1
[verify] osccfg size=1
[verify] fuse5 size=1
[verify] syscfg0 size=1
[verify] fuse6 size=1
[verify] syscfg1 size=1
[verify] fuse7 size=1
[verify] append size=1
[verify] fuse8 size=1
[verify] bootend size=1
[verify] lock size=1
[verify] prodsig size=128
[verify] sigrow size=128
[verify] signature size=3
[verify] sernum size=10
[verify] osccal16 size=2
[verify] osccal20 size=2
[verify] tempsense size=2
[verify] osc16err size=2
[verify] osc20err size=2
[verify] userrow size=64
[verify] usersig size=64
done
  • Common: Read Parm_STK_HW_VER.
  • Common: Pushing Cmnd_STK_SET_DEVICE and Cmnd_STK_SET_PARAMETER is omitted. If it does not support the expanded functions, it will probably cause an error stop at an early stage.

If you are using optiboot_x (tinyAVR, megaAVR);

  • All memory displayed by part -m (except UPDI-only sib) can now be read.
  • Can be written for userrow.
  • eeprom can be written without the -xem option. (Original function)

If optiboot_dx (AVR-Dx) is built with "BIGBOOT and TRY_USING_EEPROM";

  • All memory displayed by part -m (except UPDI-only sib) can now be read.
  • (Writing is not possible)
  • (eeprom can be written without the -xem option)

If you are using boot_ax (tinyAVR, megaAVR), boot_dx (AVR-Dx) and boot_ex (AVR-Ex);

  • All memory displayed by part -m (except UPDI-only sib) can now be read.
  • It returns a value containing the NVMCTRL version for Parm_STK_HW_VER, so it works correctly. (optboot_x variant always returns 3, this is not the case)
  • Can be written for userrow.
  • It can be written to the bootrow of AVR-EB series.

Other bootloader variants that use -c arduino have not been fully investigated, but these three appear to be the only ones that target UPDI at this time.

Other implementations that share STK500 code include stk500, mib510, and avrisp, but none of them handle UPDI, so there should be no conflicts. I'm sure that's the case.

Something I found useful while testing it myself is that FUSE_BOOTEND is now readable. This is a clear representation of the bootloader size without any guesswork involved. I think it was worth the effort just to be able to do this.

@askn37
Copy link
Contributor Author

askn37 commented Jan 15, 2024

Adoption of -xrtsdtr option and review of arduino_open()

Comparing arduino_open() and stk500_getsync(), they do the same thing inside a "attempt" loop. The difference is the content of the first loop and subsequent loops. This is probably because stk500_getsync() was changed later. Since this is an opportunity for maintenance, I decided to organize both of them.

(AVR now starts programming about 1 second earlier)

In addition to that, we added the -xrtsdtr option. For normal Arduino compatible designs this is not required. Connecting the AVR's RESET pin directly to DTR or RTS is only useful for beginners.

avrdude -c arduino extended options:
  -xattempts=<arg>      Specify no. connection retry attempts
  -xrtsdtr=low,high     Force RTS/DTR lines low or high state during programming
  -xem                  Enables enhanced memory instructions (optiboot_x etc.)
  -xhelp                Show this help menu and exit

@askn37
Copy link
Contributor Author

askn37 commented Jan 16, 2024

In addition to that, we added the -xrtsdtr option. For normal Arduino compatible designs this is not required. Connecting the AVR's RESET pin directly to DTR or RTS is only useful for beginners.

I forgot one thing. The reason I originally wanted this feature was because of the presence of a serial port switch that allows flash programs to coexist with the Arduino IDE's serial monitor/plotter. The IDE has the property of keeping RTS/DTR low while running a serial monitor/plotter. By designing a two-circuit bus switch that connects the -EN side to the console's serial port and the +EN side to serialupdi, two types of serial port devices can coexist without changing the physical ports. Sending "-carduino -xrtsdtr=low" to the Serialupdi board also allows writing with the normal bootloader. (Auto-reset support is also required) Actually, I am currently using this board as well.

@askn37
Copy link
Contributor Author

askn37 commented Jan 19, 2024

What I thought after trying out some uniquely designed serial adapters.

When the Arduino bootloader goes out of sync, it often fails to resync and reverts to normal running behavior. One reason is the get_sync loop implementation.

In the STK500 implementation, get_sync sends 2 bytes and reads 2 bytes. I have code in case the first byte of the returned set of 2 bytes is lost, and I'll catch that case and resynchronize.

In Arduino mode, an exception condition is executed and a reset signal is always sent in the retry loop after two rounds. Therefore, resynchronization will only succeed in the first round. On a retry, the delay after a reset is not the same as the first time, so the next reset is sent before the synchronization is successful. After all, synchronization is less likely to be successful after the second round.

The reason it is almost impractical to install a bootloader on a chip that cannot normally be reset, such as tinyAVR, is that the chip must be powered on or connected to a USB port after avrdude boots. Current avrdude does not allow that.

If you want to support tinyAVR's bootloader operations, you will need a get_sync retry loop that involves reopening the serial port and sending a reset. It's clear that you can't reuse STK500's get_sync to implement this.

As a challenge, I would like to consider starting the bootloader of tinyAVR (powering on after starting avrdude). This behavior differs from previous behavior, so we will also consider additional options.

@stefanrueger
Copy link
Collaborator

Thanks @askn37! This needs careful checking; it's a new feature request, so likely to be looked at after v7.3 release

@askn37
Copy link
Contributor Author

askn37 commented Jan 21, 2024

There's no need to rush. And it looks like the idea around get_sync needs more work. I have no objection to this PR being rejected. (And continues with my fork.)

@askn37
Copy link
Contributor Author

askn37 commented Jan 26, 2024

Adoption of -xrop option

% ./build_darwin/src/avrdude -P/dev/cu.usbserial-230 -carduino -xhelp
avrdude -c arduino extended options:
  -xattempts=<arg>      Specify no. connection retry attempts
  -xrop                 Reopen port on retry
  -xrtsdtr=low,high     Force RTS/DTR lines low or high state during programming
  -xem                  Enable enhanced memory. (implementation dependent)
  -xhelp                Show this help menu and exit

Previously, when starting avrdude, it would exit immediately if the port was invalid. This is by design.

 % ./build_darwin/src/avrdude -P/dev/cu.usbserial-230 -carduino -pt824 -Tsig      
avrdude OS error: cannot open port /dev/cu.usbserial-230: No such file or directory
avrdude error: unable to open port /dev/cu.usbserial-230 for programmer arduino
Possible candidate serial ports are:
  -P /dev/cu.Bluetooth-Incoming-Port
  -P /dev/cu.wlan-debug
Note that above ports might not be connected to a target board or an AVR programmer.
Also note there may be other direct serial ports not listed above.

avrdude done.  Thank you.

-xrop enables retries when opening ports. Allows the device to be powered on even after avrdude has started. This facilitates bootloader startup on devices that require Power-On-Reset, such as tinyAVR.

askn@alicia avrdude_preq % ./build_darwin/src/avrdude -P/dev/cu.usbserial-230 -carduino -pt824 -Tsig -xrop   
avrdude OS error: cannot open port /dev/cu.usbserial-230: No such file or directory
avrdude warning: attempt 1 of 10: not in sync: resp=0x50
avrdude OS error: cannot open port /dev/cu.usbserial-230: No such file or directory
avrdude warning: attempt 2 of 10: not in sync: resp=0x50
avrdude OS error: cannot open port /dev/cu.usbserial-230: No such file or directory
avrdude warning: attempt 3 of 10: not in sync: resp=0x50
avrdude OS error: cannot open port /dev/cu.usbserial-230: No such file or directory
avrdude warning: attempt 4 of 10: not in sync: resp=0x50
avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1e9329 (probably t824)

avrdude: processing -T sig
Device signature = 0x1e9329

avrdude done.  Thank you.

Similarly, if the port is opened by another application, it will be retried. The bootloader gets a chance to start even if you close other applications.

% ./build_darwin/src/avrdude -P/dev/cu.usbserial-230 -carduino -pt824 -Tsig -xrop
avrdude OS error: cannot open port /dev/cu.usbserial-230: Resource busy
avrdude warning: attempt 1 of 10: not in sync: resp=0xb0
avrdude OS error: cannot open port /dev/cu.usbserial-230: Resource busy
avrdude warning: attempt 2 of 10: not in sync: resp=0xb0
avrdude OS error: cannot open port /dev/cu.usbserial-230: Resource busy
avrdude warning: attempt 3 of 10: not in sync: resp=0xb0
avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1e9329 (probably t824)

avrdude: processing -T sig
Device signature = 0x1e9329

avrdude done.  Thank you.

@mcuee
Copy link
Collaborator

mcuee commented Feb 23, 2024

@askn37
Just wondering if you still want to further develop this PR. Thanks.

@stefanrueger
Copy link
Collaborator

After all, synchronization is less likely to be successful after the second round.

Correct, I have never seen -c avrdude recover from an initial failure to sync. One reason for this is a super large receive timeout. Another problem with the -c arduino sync model is that it does not consider urboot autobaud bootloaders: they eat up the first byte sent by AVRDUDE to figure out the baud rate, so need a different synchronisation model, too.

@askn37 Have a look at the -c urclock synchronisation, and see how that works with modern parts (or could be improved with these).

@mcuee and @askn37 This PR is generally problematic insofar as it focuses on -c arduino, which by and large is less good at supporting classic part bootloaders (including optiboot) than -c urclock. I believe it would be better to improve -c urclock to support modern parts better.

@mcuee
Copy link
Collaborator

mcuee commented Feb 23, 2024

@mcuee and @askn37 This PR is generally problematic insofar as it focuses on -c arduino, which by and large is less good at supporting classic part bootloaders (including optiboot) than -c urclock. I believe it would be better to improve -c urclock to support modern parts better.

@askn37
I agree with @stefanrueger. Just wondering if you want to spend the efforts instead on enhancing urboot bootloader. Thanks.

@mcuee
Copy link
Collaborator

mcuee commented Feb 23, 2024

Just an example how -c urclock can recover from a failure -- CH340 does not support 2M baud reliably (tested under Windows 10/11 and Ubuntu 20.04), but -c urclock (with urboot) manages to recover in the end.

mcuee@UbuntuSwift3 ~/build/avr/avrdude_benchmark $
 avrdude -c urclock -P ch340 -b 2000000 -p m328p -U flash:r:atmega328p_urboot_readback.hex:i
avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1e950f (probably m328p)

avrdude: processing -U flash:r:atmega328p_urboot_readback.hex:i
avrdude: reading flash memory ...
Reading |                                                    | 0% 0.00 s 
avrdude: en passant forcing reset vector to point to vector bootloader
Reading | ###########################                        | 53% 0.43 s 
avrdude warning: programmer is not responding
Reading | ################################################## | 100% 88.51 s 
avrdude: writing output file atmega328p_urboot_readback.hex

avrdude done.  Thank you.

@mcuee
Copy link
Collaborator

mcuee commented Feb 23, 2024

Another more extreme example, using urboot stk500v1 autobaud firmware. Look at the 167.72 s number. But at least -c urclock can recover.

mcuee@UbuntuSwift3 ~/build/avr/avrdude_benchmark $
 avrdude -c urclock -P ch340 -b 2000000 -p m328p -U flash:r:atmega328p_urboot_readback.hex:i
avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1e950f (probably m328p)

avrdude: processing -U flash:r:atmega328p_urboot_readback.hex:i
avrdude: reading flash memory ...
Reading | ################                                   | 32% 0.47 s 
avrdude warning: programmer is not responding
Reading | ################################################## | 100% 167.62 s 
avrdude: writing output file atmega328p_urboot_readback.hex

avrdude done.  Thank you.

-c arduino will be dead with the same firmware.

mcuee@UbuntuSwift3 ~/build/avr/avrdude_benchmark $
 avrdude -c arduino -P ch340 -b 2000000 -p m328p -U flash:r:atmega328p_urboot_readback.hex:i
avrdude: AVR device initialized and ready to accept instructions
avrdude: device signature = 0x1e950f (probably m328p)

avrdude: processing -U flash:r:atmega328p_urboot_readback.hex:i
avrdude: reading flash memory ...
Reading | ########------------------------------------------ | 16% 5.25 s 
avrdude error: programmer is not responding
avrdude error: programmer is not responding
avrdude error: unable to read byte at address 0x0000
avrdude error: read operation not supported for memory flash
avrdude error: unable to read all of flash memory, rc=-2
avrdude error: programmer is not responding

avrdude done.  Thank you.

@askn37
Copy link
Contributor Author

askn37 commented Feb 24, 2024

I think you are absolutely right that there is no point in further improving the Arduino protocol. In particular, it doesn't have enough power to cover his UPDI generation of hardware, which I'm eyeing. More than 97 models have already been released in this category, which is more than 1/4 of all 8bit-AVR models.

The problem is that using the urboot protocol doesn't seem to take advantage of the performance of the hardware you have. In particular, we do not believe that the following hardware UART features will be supported:

  • Full hardware automatic baud rate adjustment feature uses 0x55 for the sync character. The UPDI protocol is actually implemented based on this.
    • As a side note, TPI/PDI/UPDI can share the same UART frame 8E2, except for the synchronization method and the presence or absence of the CLK pin. Not SPI based.
  • By expanding the frame to 9 bits, multi-CPU communication function of up to 256 nodes can be used. This is probably a required feature for ISO 26262 compliance. Unfortunately, there are no known implementations of this open source protocol, but it may already be popular in the automotive industry. (Like UPDI-OCD and QT-Touch, as a private specification)

My personal challenge will ultimately involve designing a new open source protocol. This effort is very important, but if AVR-DU can be used as expected (protocol conversion from AVRISP/JTAGmkII becomes easier, etc.), the difficulty will be significantly reduced. We're still halfway through.

@mcuee
Copy link
Collaborator

mcuee commented Feb 24, 2024

I think you are absolutely right that there is no point in further improving the Arduino protocol. In particular, it doesn't have enough power to cover his UPDI generation of hardware, which I'm eyeing. More than 97 models have already been released in this category, which is more than 1/4 of all 8bit-AVR models.

@askn37

Thanks a lot for the contributions.

In this case, I will close this PR as not planned.

I will move the other part about urboot and modern UPDI AVRs into a discussion.

@mcuee mcuee closed this Feb 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants