Optiboot / optiboot

Small and Fast Bootloader for Arduino and other Atmel AVR chips
Other
1.09k stars 399 forks source link

Atmega4809, "Xtiny" support? #260

Closed WestfW closed 4 years ago

WestfW commented 5 years ago

Most of the ATmega4809 board available so far have an on-board EDBG chip of some kind, and don't need a bootloader. (Uno WiFi 2, Atmel Xplained Pro, Atmel Curiosity) However, it might be nice to have a pure serial bootloader as well. In addition to "new" peripherals, the ATmega4809 has its "bootloader section" at the beginning of flash, which probably means applications should have a new linker script. Or perhaps we can just use the existing "virtual boot partition" and ignore the special behavior of the boot section.

The Tiny-0 and Tiny-1 have a lot in common with the mega-0, and can probably be done at the same time.

MCUdude commented 5 years ago

Here's something that may help you: MicroChip Appnote AN2634

SpenceKonde commented 5 years ago

I would LOVE to have this support, as it could be easily adaptable to the rest of the megaAVR line (such as my megaTinyCore.

There was a thread in some forum thread where I think you also posted, where someone suggested "well you could just put the bootloader at the end and adapt virtualboot", and set the whole chip to be application section, with the intent of making it so you didn't need to change the start of the app section when compiling. I realized this solution is no good though....

I have twice captured a chip using optiboot virtualboot where it erased the first page, but got reset or otherwise choked (don't know how it happened, just dumped flash over ISP) before it wrote that page - meaning that the reset vector wasn't pointing to the bootloader, and the chip thus needed ISP remediation to fix. That isn't so bad on a classic AVR in a development environment, but on a megaAVR chip, it's a show-stopper, requiring board work to fix, because to make PA0 act as reset, you need to set the fuses - and after that point, you need to use HV programming to further reprogram it - so if this event occurred on a megaAVR with the virtualboot approach, you'd need HV programmer to unbrick it - but it gets worse - the DTR reset circuit has a 10k pullup to Vcc on reset (which would act as a resistor divider and probably block UPDI programming), as well as a diode so when the serial adapter releases DTR, it cant generate a spike which trigger HV programming mode - but this would obviously also block use of a HV programmer to unbrick the chip - so two parts would need to be removed to re-bootload the chip using an HV programmer. Thus, a bootloader that can brick the chip if interrupted at the wrong point is not acceptable for the megaavr parts, since unbricking it will require reworking the board as well as an HV programmer.

So I think you're going to have to do it the way you're "supposed to", with the bootloader before the application and a different address for the start of app code if it's to be used with a bootloader.

Thanks for all the work on Optiboot, we are all in your debt. If you managed to get optiboot working on megaavr, such that I could adapt it to the megaavr tinies, I would be more than happy to ship you out an assembled development board for each family.

WestfW commented 5 years ago

to make PA0 act as reset, you need to set the fuses - and after that point, you need to use HV programming to further reprogram it

I'm pretty sure you can re-program an ATmega4809 using the dedicated UPDI pin without any access to RESET (HV or otherwise.) (Yep - I just checked my chip-scale board. It programs with just VTG, GND, and UPDI.)

ATtinys with UPDI shared with GPIO aren't as lucky...

SpenceKonde commented 5 years ago

Aaaaah - I honestly hadn't looked at the 4809 enough to realize that it had a separate reset pin...

MCUdude commented 5 years ago

I'm pretty sure you can re-program an ATmega4809 using the dedicated UPDI pin without any access to RESET (HV or otherwise.) (Yep - I just checked my chip-scale board. It programs with just VTG, GND, and UPDI.)

That's correct. You can actually use the reset pin on the Arduino UNO Wifi Rev2 as a regular pushbutton if you like, and still being able to re-program the board afterward.

It would be awesome to have proper Optiboot support for the ATmega4809 (and preferably the entire family; ATmega808/1608/3208/4808 and ATmega809/1609/3209/4809)! The UPDI interface can be fiddly, and AFAIK there doesn't exist a cheap ready-built programmer like the USBasp.

I understand that there's quite a bit of work to achieve this though.

WestfW commented 5 years ago

Notes: In addition to having multiple serial ports, the 4809 has a pinmux capability to change the location of the pins used (currently between two different choices.) Probably UART=2, UART=20, UART=21 (for UART2 default, default, and ALT1 settings, given the limitations of the C preprocessor.)

The need to set the IO bit for the UART output to output is annoying, since mapping a USART to a port/bit is unlikely to be consistent.

With a bit of care, this code should handle mega-0 (480x) AND most of the other Xmega, Tiny0, and Tiny1 series, which all have similar USART and flash support, I think. (well, crap. XMEGA USARTs are a bit different - they don't have separate RXDATA/TXDATA, nor 16bits...)

MCUdude commented 5 years ago

Yes, the pinmux adds complexity, but can't the pinmux position be "hardcoded" by a build parameter in make? Something like this perhaps?

make atmega4809 AVR_FREQ=16000000L BAUD_RATE=115200 LED=B5 LED_START_FLASHES=2 UART=0 UART_MUX=0 #Default UART port mux position

It would indeed be neat if xmega targets also could be added to Optiboot, but I'm more than happy if we can get the Mega0, Tiny0 and Tiny1 to work well.

WestfW commented 5 years ago

More notes: It doesn't seem to be possible to derive the pins (PORT/BIT) used by a UART (which you need to know, because you have to set it to be an output in the DDR registers in these chips) from the UART number itself, with or without pinmux info. (that is, given "UART0" and "PINMUX default", you'd need yet another variable for UART_TXPIN. Which is ... annoying.)

I wonder if it'd be easier or make more sense to have the user specify the TXpin: make atmega4809 UARTTX=A4 There is already infrastructure for parsing a pinname in that style to produce the LED port/bit. (it's not very pretty infrastructure, but the principle is "easier to use as long as you don't have to touch the infrastructure.)

MCUdude commented 5 years ago

I wonder if it'd be easier or make more sense to have the user specify the TXpin: make atmega4809 UARTTX=A4 There is already infrastructure for parsing a pinname in that style to produce the LED port/bit. (it's not very pretty infrastructure, but the principle is "easier to use as long as you don't have to touch the infrastructure.)

Sure! Most users will use pre-compiled files anyway. What's important is that it should be possible to build for any UART port and any PINMUX setting based on the input the makefile gets. This way I can provide a bunch of different files, just like I already do with my Arduino cores.

I'm sure this will be a gamechanger for the new mega0, tiny0, and tiny1 series. Proper serial uploading where you can upload code and print to your serial monitor using the same serial port os SO MUCH better than having to use an external programmer or a dedicated microcontroller (jtag2updi) just for uploading. Heck, the UNO Wifi Rev2 wouldn't even need its mEDBG chip if Optiboot support for it existed.

Even though we all want Optiboot support we also need a UPDI programmer, and preferably a standard pinout for the programming connector. we're currently discussing a new mEDBG based programmer over here. Do you agree on the pinout I've suggested?

wolframore commented 5 years ago

Please note there's a new datasheet as of 08/15/2019

http://ww1.microchip.com/downloads/en/DeviceDoc/ATmega4809-40-Pin-40002104B.pdf

WestfW commented 5 years ago

Sigh. So it looks like nothing can ever write to the "boot section" of the new chips, which means that making the whole memory be the boot section would make it all unprogrammable, rather than all programmable. Which is unfortunate :-( (On the bright side, writing to flash is really easy.)

JAndrassy commented 5 years ago

did you see this https://github.com/arduino/ArduinoCore-megaavr/blob/master/bootloaders/boot.c ?

WestfW commented 5 years ago

Woot!

/Applications/Arduino-1.8.9.app/Contents/Java/hardware/tools/avr/bin/avrdude -c arduino -P /dev/tty.wchusbserial3130 -b115200 -p atmega4809 -C /Applications/Arduino-1.8.9.app/Contents/Java/hardware/tools/avr/etc/avrdude.conf -Uflash:w:/tmp/OldArduBuild/Blink.ino.hex -D

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.02s

avrdude: Device signature = 0x1e9651 (probably m4809)
avrdude: reading input file "/tmp/OldArduBuild/Blink.ino.hex"
avrdude: input file /tmp/OldArduBuild/Blink.ino.hex auto detected as Intel Hex
avrdude: writing flash (2036 bytes):

Writing | ################################################## | 100% 0.48s

avrdude: 2036 bytes of flash written
avrdude: verifying flash memory against /tmp/OldArduBuild/Blink.ino.hex:
avrdude: load data flash data from input file /tmp/OldArduBuild/Blink.ino.hex:
avrdude: input file /tmp/OldArduBuild/Blink.ino.hex auto detected as Intel Hex
avrdude: input file /tmp/OldArduBuild/Blink.ino.hex contains 2036 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.45s

avrdude: verifying ...
avrdude: 2036 bytes of flash verified
MCUdude commented 5 years ago

WOOOOW!! You got a proof-of-concept Optiboot version to work???

MCUdude commented 5 years ago

Yah, but that bootloader isn't compatible with -c arduino, is it?

MCUdude commented 5 years ago

@WestfW does these lines means that the fuse bits can be stored in the compiled hex file and that they can be changed by the application at runtime?

Personally I prefer to handle the fuse bits separately like we have to do with "older" AVRs.

WestfW commented 5 years ago

Yes, this is optiboot (an optiboot), using "-c arduino" for programming. The existing bootloader that jandrassy noticed seems a bit weird - very primitive, and it's only triggered (the way I read it) by writing a special value into the "user row" space. It looks like it uses the serial port connected to the WiFi module - perhaps it is supposed to help with that "OTA upgrade?" On the bright side, this means that UnoWiFi2 boards already compile with a -section-start compatible with a bootloader.

The FUSES feature of avr-libc has been present for a while. https://www.nongnu.org/avr-libc/user-manual/group__avr__fuse.html It creates an extra segment in the .elf file, which a programming tool CAN extract and use. It's very similar to the EEPROM support. This doesn't mean that programmers WILL do this (to start with, they'd have to use the .elf file, or export a separate .hex file), and it doesn't mean that they can be written by the bootloader. I'm currently using MPLAB and a PICKit4 for debugging (on a Mac), and it's overall level of maturity for AVRs is a bit "poor", so this feature seems to be the only way I can burn the BOOTEND fuse (for example) (There's a "program fuses" option, but it doesn't include BOOTEND/etc!)

Next up - one of the ATtiny boards. "In theory", very little in the bootloader needs to change!

MCUdude commented 5 years ago

I'm currently using MPLAB and a PICKit4 for debugging (on a Mac), and it's overall level of maturity for AVRs is a bit "poor", so this feature seems to be the only way I can burn the BOOTEND fuse (for example) (There's a "program fuses" option, but it doesn't include BOOTEND/etc!)

Are you satisfied with MPLAB for AVRs? doesn't MPLAB uses a stripped-down version of avr-gcc without optimization? And how about the Pickit4? is it "better" than the Atmel ICE? I haven't used MPLAB for AVR development, only Atmel Studio and of course Arduino IDE. The mEDBG isn't very fast (they say), but it works great for my usage, especially after I designed dedicated hardware around it.

I recently got myself a cheap SNAP programmer. I haven't really used it yet, but I figured it may come in handy someday. Would be great if Avrdude supported it someday!

WestfW commented 5 years ago

We should think a bit about the "Reset Cause" dance on these new parts. They've add a "software-requested reset" capability, which shows up as a separate reset cause in the appropriate status register. (There's also a separate "reset by UPDI" bit!) In theory, I think that means that we could use the software-reset as the 'run the bootloader' request, regardless of any other bits being set (and maybe it should clear all the other bits?) Instead of the delicate "reset all the causes and jump to the bootloader" dance done currently...

MCUdude commented 5 years ago

In theory, I think that means that we could use the software-reset as the 'run the bootloader' request, regardless of any other bits being set (and maybe it should clear all the other bits?) Instead of the delicate "reset all the causes and jump to the bootloader" dance done currently...

So it may be possible to receive some kind of message over UART in order for it to jump to the bootloader? IMO I'll still prefer the standard DTR/RTS + 100n cap at the reset pin. It's just so incredibly simple! Maybe Optiboot could support both? However, the latter is most important I think.

But just think about how much more available the new mega-0 and tiny-0 and tiny-1 series will be to the masses when one can use a standard USB to serial chip instead of a programmer! Heck, the new Nano Every could theoretically have used a CH330N instead of a SAMD11D14 + level shiters. It would be super easy to make nice, cheap and small ATtiny boards where you can upload code communicate over UART trough the same serial port.

Next up - one of the ATtiny boards. "In theory", very little in the bootloader needs to change!

Cool! I'm planning to make myself a development board where I easily could swap between ATmega809, 1609, 3209 and 4809 by swapping out small 48-pin breakout boards. Could be useful when working on other "4809 compatible" chips.

WestfW commented 5 years ago

Are you satisfied with MPLAB for AVRs?

Not really. I'm not much of an IDE person in general. The AVR support is "new" and still has bugs that are moderately annoying (disassembly doesn't properly handle two-word instructions, for example.) Periodically the debugger will get in a weird state and (apparently) the best way to proceed involves restarting the IDE. You can find some pithy comments from me on avrfreaks. It is "adequate" and "useful", though.

doesn't MPLAB uses a stripped-down version of avr-gcc without optimization?

They're allowing -Os and -O1 for their packaging of "xc8 with AVR support." But it will happily noticed your existing avr-gcc install and use that instead. I've been using the last Atmel version, with manually installed "packs."

And how about the Pickit4? is it "better" than the Atmel ICE?

Well, it should do all the PIC families as well as AVR and ARM. It seems pretty similar to the Atmel ICE in overall performance/etc. For the things that work. It'll need adapter cables for all targets (while the ICE has trivial IDP cables for some.) It's supposed to do HV programming, but apparently "not quite yet" for the UPDI hosts.

just think about how much more available the new mega-0 and tiny-0 and tiny-1 series will be

I'm looking forward to to the tiny13 being forgotten. The Microchip SNAP programmer is only $8-20 (but it doesn't do HV programming at all.) And there's that ArduinoUPDI software. It's difficult to explain the "better-ness" of direct serial programming. But it is there! The $2.50 ATmega4809 in DIP40 is "exciting", too. Things that someone with limited experience can actually build!

I'm planning to make myself a development board

I bought sets from DrAzzy's Tindie store. One assembled, several blank boards for each of 8, 14, and 20pin chips. His prices are good enough that I decided it wasn't worth doing my own.

MCUdude commented 5 years ago

I'm looking forward to to the tiny13 being forgotten.

What's wrong with the ATtiny13? It's certainly limited, but it's not a "terrible" AVR in any way. Or maybe you mean that all new 8-pin tiny0/tiny1 is cheaper than the tiny13, and will gradually replace it?

The $2.50 ATmega4809 in DIP40 is "exciting", too. Things that someone with limited experience can actually build!

It's awesome that they did this! Microchip has a tradition for "DIPing" new chips, but Atmel really don't.

I've been thinking about making a dedicated Arduino style pinout for the DIP40. I already have a nice, logical pinout style for the TQFP48 variant, but this doesn't match the DIP40 very well (pin 8-13 + 20 and 21 not broken out). On the other side, different pinouts for the same chip makes it more difficult from migrating a project made for a TQFP48 to a DIP40 where many Arduino pins don't match due to different pinout styles.

WestfW commented 5 years ago

What's wrong with the ATtiny13?

Mostly, in the Arduino world, it "fails to meet user expectations." (and these days, it's overpriced.) It doesn't bootload and lacks basics features like Serial, unless you practically fill it up with code. One of the new Tiny-0 chips will support a bootloader and a "complete" Arduino Core, and still have room for the sort of tiny sketches that users expect to fit. And it'll be cheaper, too.

SpenceKonde commented 5 years ago

I bought sets from DrAzzy's Tindie store. One assembled, several blank boards for each of 8, 14, and 20pin chips. His prices are good enough that I decided it wasn't worth doing my own.

You should have one of the 24-pin ones in there too, I recognized your name and threw in one of those too. Sorry I haven't been commenting in here more - I've been watching this issue with great attention.

I have tested software reset - it absolutely does work to reset the part. I think uploading sketches, you need to do the DTR-reset trick, otherwise bad sketch code could render it impossible to reset back into the bootloader. Maybe having only a reset pin enter the bootloader by default would be ideal - because then you could use the software reset to start the sketch, so you don't have to manually reset the registers used by the bootloader to default settings?

WestfW commented 4 years ago

ATtiny416 board working, after fixing some obnoxious issues. It turns out that you have to read the documentation. Also, it turns out that the UPDI chips seem to need a "byte address" rather than a "word address" when programming flash, even though that should IMO be defined by the protocol rather than the chip. Grr.

/Applications/Arduino-1.8.9.app/Contents/Java/hardware/tools/avr/bin/avrdude -c arduino -P /dev/tty.usbmodem3122 -b57600 -p attiny416 -C /Downloads/avrdude-facchinm/avrdude.conf -Uflash:w:/tmp/OldArduBuild/Blink.ino.hex -D

avrdude: AVR device initialized and ready to accept instructions

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

avrdude: Device signature = 0x1e9221 (probably t416)
avrdude: reading input file "/tmp/OldArduBuild/Blink.ino.hex"
avrdude: input file /tmp/OldArduBuild/Blink.ino.hex auto detected as Intel Hex
avrdude: writing flash (1624 bytes):

Writing | ################################################## | 100% 0.18s

avrdude: 1624 bytes of flash written
avrdude: verifying flash memory against /tmp/OldArduBuild/Blink.ino.hex:
avrdude: load data flash data from input file /tmp/OldArduBuild/Blink.ino.hex:
avrdude: input file /tmp/OldArduBuild/Blink.ino.hex auto detected as Intel Hex
avrdude: input file /tmp/OldArduBuild/Blink.ino.hex contains 1624 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.14s

avrdude: verifying ...
avrdude: 1624 bytes of flash verified
WestfW commented 4 years ago

I'm thinking that I'll use a separate Makefile for these chips as well, since pin_defs.h and the .c source are already separate. I don't see a compelling reason to try to merge things together, since the logic is so different. (I'll probably move option parsing to a separate file so that it can be shared...) (and I guess I'll give up one the whole multi-environment (windows/mac/linux/arduino) attempts and insist that people who want to compile it set up a "proper cli tool environment"?)

Also, it seems that the binaries are likely to only differ in the pin-number-related constants. Start address, application address, presence of "jmp" vs "rjmp", peripheral behavior... all is the same across all of the chips!

SpenceKonde commented 4 years ago

Wonderful news indeed!

I've noticed the amazing similarity between the new megaavr attinies as well - I think that's what you get when you design a whole line of processors at once, with the same design team, as opposed to over a decade of different versions for different specific use cases like we had with the classic tinies. I'm sure in a few years, we'll end up with megaavr parts that differ in strange ways from these :-P

WestfW commented 4 years ago

Hmm. Another interesting property of the new chips is that they'll always start up running on the internal oscillator at either 16MHz or 20MHz, with a /6 prescaler. Other clock options require SW intervention that the bootloader shouldn't need. That means that you only need two builds (3.33MHz and 2.66MHz) to handle "all cases." (I guess that theoretically, turning off the div6 could allow faster bitrates. But even at 2.6MHz, it should support 500kbps.)

MCUdude commented 4 years ago

That is wonderful!

Is it possible for the microcontroller to read its SYSCFG0 fuse to determine if it's running from its 16 or 20 MHz oscillators? If so, the BAUD value could be calculated on the fly (just like Serial.begin does), and maybe we can get away with only one build? Just a thought.

WestfW commented 4 years ago

Putting this here, too.

Python code to reset an AVR with some EDBG debugger connected... works with an Xplained tiny416 nano (32u4 mEDBG) and a curiosity 4809 nano (SAMD nEDBG) Didn't work with an Xplained 4809 Pro (AVR32 EDBG)

# Preform a reset operation on an ABR controlled by some sort of EDBG
# Uses https://github.com/mraardvark/pyedbglib to do all the work.

# Import a transport provider
from pyedbglib.hidtransport.hidtransportfactory import hid_transport
from pyedbglib.protocols import avr8protocol
from time import sleep

# Create and connect to transport
transport = hid_transport()
quiet = transport.connect()

# Create protocol, passing in transport object
avr= avr8protocol.Avr8Protocol(transport)

def to_s(u):
    return u.encode('ascii')

# deactivate first, in case still activated
avr.deactivate_physical()

quiet = avr.activate_physical()
print ("Resetting: "+to_s(transport.hid_device.get_manufacturer_string())+ \
      to_s(transport.hid_device.get_product_string())+":"+ \
      to_s(transport.hid_device.get_serial_number_string()))
avr.attach()
avr.reset()
sleep(0.1)
avr.run()
avr.deactivate_physical()
WestfW commented 4 years ago

Since this is basically working (Makefile.mega0, optiboot_x.c), I'm going to close the issue and treat future enhancements or bugs as separate issues.