Booting from XMEGA application code into the bootloader (and staying there!)

Go To Last Post
28 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I’m using a XMEGA256A3BU on the A3BU-XPLAINED evaluation board. I’m trying to implement the DFU runtime interface like I already have on the AT90USB1287. The LUFA-inspired code for the AVR8 architecture is here which works really well on the USBKEY2 and now I’m trying to do the same for the XMEGA architecture.

 

What I need to do is boot from application code back into the bootloader, and stay in DFU mode. Using the traditional wdt_enable(WDTO_500MS); while(1) {}; of course resets the chip, but it does not stay in the bootloader mode and instead jumps to user code (as it probably should).

 

For AVR8 you can just jump to 0x1e000 directly, but jumping to BOOT_SECTION_START (0x40000) doesn’t work on XMEGA. I’ve tried setting EIND=0x02 before the jump with no effect, and also tried disabling interrupts with PMIC.CTRL=0 and even doing a software reset using CCP = CCP_IOREG_gc; RST.CTRL = RST_SWRST_bm;

 

I guess my question really boils down to what’s in the USB DFU Boot Loader for XMEGA document – i.e. figure 5.1 seems to suggest the only way to stay in the DFU bootloader is to:

 

  • Not do a Software Reset i.e. RST.STATUS
  • Pass the “part is blank” test, which I assumes looks at the application init vector table

 

According to figure 5.1 the only way to do this (assuming I have application code present) would be to do a WDT reset and just solder a link across the SW0 button to enforce the “special pin condition” for the A3BU-XPLAINED evaluation board. I'd really like to avoid modifying the PCB unless I really have to, as it also means I'd have to "DFU attach" to jump from the bootloader to application every time the USB cable is plugged in.

 

Is there really no BOOTRST for XMEGA? Does anyone know any “fun” tricks to get the device to stay in bootloader mode? Thanks.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Can't you just modify/rebuild the DFU sources to behave in whatever way you desire? Atmel supply the source and IAR projects - the project is small enough that you can build it with the "Kickstart" copy of IAR rather than having to spend $3,000 on the full version

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes, I guess that's the back-up plan. I wanted to avoid changing the evaluation board if I could avoid it, as then it means anyone trying to run the fwupd hardware tests would need a JTAG programmer too. I don't think the LUFA bootloader supports XMEGA, but if you know of a DFU bootloader than can be compiled in avr-gcc (I work for Red Hat, so this all needs to be Open Source if possible) then I'd be very welcome. Thanks for the quick response!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Silly question but why would you want it to "stick" in DFU anyway? Surely it makes the AVR unusable for the actual application that is being programmed into the main flash? What you want from a bootloader is that if it starts there ihangs around a short while to see if its needed but otherwise it drops out of the picture and starts the app that is the whole point of the AVR. Only if it cannot find such an app would it then decide "nothing else to do - might as well wait here then".

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Not a silly question at all. The DFU runtime interface allows a client to switch the device automatically to bootloader mode so it can be automatically updated with new firmware. A userspace daemon like fwupd (I'm the maintainer...) can then update the user firmware automatically without the user needing to:

 

  • know what microprocessor is used
  • know what firmware version is currently installed
  • hold a magic button when inserting the hardware

 

The DFU runtime is super useful when the device either doesn't (or can't) have a button that is tied to the “special pin condition”. The general sequence of events is:

 

  1. User inserts hardware which automatically boots to user mode
  2. fwupd reads the current version and checks a web service for updates
  3. fwupd prompts the user if they want to do the update
  4. fwupd detaches the device to bootloader mode using the DFU runtime interface
  5. the device replugs, into DFU mode
  6. fwupd squirts in the firmware using DFU (or STM32/AVR/AVR32 variants of it)
  7. fwupd "attaches" the firmware out of bootloader mode using the DFU interface
  8. the device replugs, into user mode
  9. fwupd gets the new firmware version from the device

 

The actual web-service of this is the LVFS and you can see the vendor list we have already: https://fwupd.org/vendorlist -- more vendors are currently testing the service but that's the vendors that are not testing in secret.

 

I hope that explains a little of the requirement to stay in bootloader mode :) Most of the vendors implementing this actually don't use the DFU runtime descriptor and use something vendor specific or a manual "press button X+Y" (which is fine, but doesn't work in an automated test environment) -- but for the fwupd self tests we need to use hardware that can be flash over and over again every time a new commit gets merged -- hence why it needs to be done without a button.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Something like...

 

EIND = 0x02;
( (void(*)(void))0)();

 

Remember that once you set the EIND register the jump is to address 0.

 

Can you recompile the DFU yourself? If so, there are other options such as using a .noinit memory section.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I thought EIND was to jump above 128KB and was needed as 0x40000 > 0x20000 (128*1024) -- looking at the docs I saw:

 

EIND is concatenated with the Z-register to enable indirect jump and call to locations above the first 128KB (64K words) of the program memory.

 

If that's wrong, please let me know -- although I don't think that's going to help much staying in the bootloader

 

> Can you recompile the DFU yourself? If so, there are other options such as using a .noinit memory section.

 

I could, and this might be what I have to do. I was going to just make a modification so that on WDRST we stay in the bootloader (good enough for this evaluation board) but maybe setting and then checking a noinit variable might be a better idea. I'll admit I've not looked at the ATMEL DFU XMEGA bootloader sources, but it would be awesome if future versions could do something like this.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Right, Z is 16 bit so maximum 65535. Jumps are word addressed so maximum range of Z is 128k. You have a 256k device, so you need EIND to be 2.

 

The address of the bootloader section is 0x20000 (word addressing). Z contains the lower 16 bits and EIND contains the upper 2 bits. Hence EIND = 2, Z = 0;

 

If you can recompile the bootloader you could use a .noinit memory section to pass in a magic number, which survives reset.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hence EIND = 2, Z = 0;

 

Agreed, I've tried this and it goes back into bootloader mode. Thanks for taking the time to explain this. I'll have a look at how to do .noinit sections properly and post a patch back here when I'm done.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

the project is small enough that you can build it with the "Kickstart" copy of IAR

 

I've just tried this; I tried using the workspace from AVR1916/XMEGA_bootloaders_v104/source_code/common.services.usb.class.dfu_atmel.device.bootloader.atxmega256a3bu/common/services/usb/class/dfu_flip/device/bootloader/xmega/atxmega256a3bu/iar (phew!) in IAR Embedded Workbench - AVR 7.10.1 using the 'Release' target with zero modifications. Every time it says Error [e89]: Too much object code produced (more than 0x1000 bytes) for this package; Error while running linker -- with no more information.

 

I'm somewhat of a IAR newbie so if I've missed something obvious please let me know. IIUC the bootloader should be at most 0x2000 bytes in size, so I'm confused where all the stuff is coming from. Any help most welcome, thanks!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Is there some good documentation for the DFU protocol? I had a quick look but couldn't find any.

 

I'd like to add support to my open source bootloader if it isn't too much work.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Hi mojo-chan. The best document to describe DFU is the specification document from the USB consortium: http://www.usb.org/developers/do... -- this describes the "Vanilla" DFU that all upgradable devices are supposed to implement. Different vendors have proposed different specification enhancements over the years. ST proposed DfuSe for their STM32 microchips, but this never was adopted by the USB consortium as it was too specific to ST. ATMEL have done various things to DFU over the years, first adding dubious enhancements with the AVR specification, and then later the AVR32 specification as used by FLIP. ATMEL use "FLIP" interchangeably between describing the new protocol and the upload tool itself, so it's a bit chaotic reading the AVR-specific documentation.

 

My advice would be to implement the vanilla specification, which does mean putting all the "how big are the device pages" logic into the bootloader, but IMHO that's a much better place for it than trying to deal with sector offsets to specific devices in the flashing tool. The fwupd daemon that I maintain supports vanilla DFU, DfuSe and AVR/AVR32 variants, so I'm happy to help when you get stuck implementing it. I also adapted the LUFA bootloader on AT90USB1287 and XMEGA256A3BU, and also added support to m-stack for DFU 'runtime' and 'dfu' interfaces on the PIC18 devices from Microchip, so also yell if you get stuck on the device-side too.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hughsie wrote:
Too much object code produced (more than 0x1000 bytes) for this package; Error while running linker
Does it say exactly how many bytes over 0x1000? I'm guessing just a handful and it could be that a new version of the their compiler is generating just a few more bytes for the DFU that was always "tight"

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

Does it say exactly how many bytes over 0x1000?

 

No, no more information at all -- I've even tried looking at the linked debug output but the file is always empty. I guess I could try an older version of IAR if you think it might help.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

On a hunch, I tried to find out how big the compiled bootloader should be:

 

$ avr-size binaries/atxmega256a3bu_104.hex 

 

   text    data     bss     dec     hex filename

      0    5616       0    5616    15f0 binaries/atxmega256a3bu_104.hex

 

Hmm, that's certainly > 4k in size. Looking at the others:

 

$ avr-size binaries/*

   text    data     bss     dec     hex filename

      0    3944       0    3944     f68 binaries/atxmega32a4u_104.hex

      0    3944       0    3944     f68 binaries/atxmega32c4_104.hex

      0    3988       0    3988     f94 binaries/atxmega16a4u_104.hex

      0    3988       0    3988     f94 binaries/atxmega16c4_104.hex

      0    3992       0    3992     f98 binaries/atxmega64b1_104.hex

      0    3992       0    3992     f98 binaries/atxmega64b3_104.hex

      0    3992       0    3992     f98 binaries/atxmega64c3_104.hex

      0    3995       0    3995     f9b binaries/atxmega64a3u_104.hex

      0    3995       0    3995     f9b binaries/atxmega64a4u_104.hex

      0    4093       0    4093     ffd binaries/atxmega64a1u_104.hex

      0    5586       0    5586    15d2 binaries/atxmega128b1_104.hex

      0    5586       0    5586    15d2 binaries/atxmega128b3_104.hex

      0    5588       0    5588    15d4 binaries/atxmega128a4u_104.hex

      0    5610       0    5610    15ea binaries/atxmega128c3_104.hex

      0    5610       0    5610    15ea binaries/atxmega256c3_104.hex

      0    5610       0    5610    15ea binaries/atxmega384c3_104.hex

      0    5612       0    5612    15ec binaries/atxmega128a3u_104.hex

      0    5612       0    5612    15ec binaries/atxmega256a3u_104.hex

      0    5616       0    5616    15f0 binaries/atxmega256a3bu_104.hex

      0    5622       0    5622    15f6 binaries/atxmega192a3u_104.hex

      0    5952       0    5952    1740 binaries/atxmega128a1u_104.hex

 

(sorted by size, not filename)

 

Unless I'm mistaken, does that mean that the ATXMEGA >= 128 bootloaders can't be built using the evaluation version of IAR? I guess it also explains the Table 2-1. XMEGA A feature summary overview in doc8077.pdf where the boot memory is specified as "4-8"...

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Interesting finding. I thought they were all under the magic 4K mark. Indeed I even wondered if Atmel/IAR agreed the "free" boundary would be at 4K so that all those bootloaders could be built in the free version. So sadly it looks like some need a $3,000 investment if you want to build the big ones - gulp!

 

Wonder if Dean's DFU clone in LUFA builds/works for Xmega? He does make the point that Xmega and UC3 support is "experimental" but I wonder if that matters for something with a very fixed job like a DFU bootloader?

 

PS in our list half are almost the same size under 4K and half are almost the same size (well) above the 4K - wonder what's added in the "big ones" that pushes them over? Is it needed or is it some kind of eye-candy?

 

PPS this isn't about the size of the IVT is it by any chance? Presumably the vectors for USb on all Xmega are in the same place? if so maybe they don't need complete IVTs if that is what's pushing them over?

Last Edited: Mon. Nov 20, 2017 - 04:03 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

I wonder if Dean's DFU clone in LUFA builds/works for Xmega?

 

No, there's no XMEGA support there. Even if you hack in the XMEGA bits into LUFAConfig.h and change the target in the Makefile you still get:

 

/usr/avr/include/avr/boot.h:116:6: error: #error AVR processor does not provide bootloader support!

 

 

clawson wrote:

wonder what's added in the "big ones" that pushes them over?

 

My naive understanding is that the bigger flash devices need "larger pointers" to address the flash address space, and this would kind of make sense if the word address is the byte_address/2 then >= 128*1024/2 is 0x10000 i.e. needs 17 bits for the address, not 16 like smaller devices.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

I’m trying to implement the DFU runtime interface like I already have on the

Slightly off topic, but cool! (I haven't seen any DFU tools using the RT interface yet... smiley, or at least none of our tools...)

:: Morten

 

(yes, I work for Atmel, yes, I do this in my spare time, now stop sending PMs)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The DFU document is awful. If it was better I'd spend a day implementing it, but I can't find the motivation. Anyone have a better document?

 

Not trying to blow my own horn here, but a DFU bootloader based on fully open code that can be compiled to under 4k with GCC would be very valuable I think.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

mojo-chan wrote:
Not trying to blow my own horn here, but a DFU bootloader based on fully open code that can be compiled to under 4k with GCC would be very valuable I think.
well the majority of that is in LUFA already - the bit that seems to be a problem is the low level "hardware glue" for Xmega.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Will the LUFA code fit in 4k? Does it include the Windows custom descriptor support?

 

The custom descriptors use some space but mean you don't need to have a signed driver file, just plug the device in on Windows 7 or later.

 

In any case, I'll have a look at it, see if it is a better reference than that awful document.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

In case it's useful to anyone, I successfully built a modified XMEGA bootloader and am using it in the fwupd hardware self tests now. The documentation is here in case anyone wants to see how. I used the WDT reset to signal a detach into bootloader rather than a non-init variable for simplicity. There were several gotchas, from the > 4k size and the weird 10 pin PDI/JTAG socket but it seems to work. If anyone wants to add the low-level XMEGA parts to LUFA I'd gladly switch to that.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I now have a working DFU bootloader for XMEGA that compilers with GCC to well under 4k. I'll post it tomorrow most likely.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

mojo-chan wrote:

Will the LUFA code fit in 4k? Does it include the Windows custom descriptor support?

 

This is for AT90USB1287, with no custom descriptors:

 

$ avr-size BootloaderDFU.hex 

   text    data     bss     dec     hex filename

      0    3956       0    3956     f74 BootloaderDFU.hex

 

mojo-chan wrote:

The custom descriptors use some space but mean you don't need to have a signed driver file...

 

This is interesting; do you have any docs for this please?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

mojo-chan wrote:

I now have a working DFU bootloader for XMEGA...

 

Cool! Would it be a good idea to do a PR against LUFA?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Mine is with the Microsoft descriptors... It's open source, do what you like with it :-)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Cool!

hughsie wrote:
The documentation is ...

Download [AVR1916.zip] ...

fyi, atmel.com will be leaving the field at the end of this year.

The matching Microchip page is missing AVR1916.zip :

http://www.microchip.com/wwwappnotes/appnotes.aspx?appnote=en591085

that was from

http://www.atmel.com/products/microcontrollers/avr/avr_xmega.aspx?tab=documents

(Application Notes in Document Type)

...

 

Atmel AVR1916: USB DFU Boot Loader for Atmel XMEGA

Atmel AVR1916: USB DFU Boot Loader for Atmel XMEGA

Atmel AVR1916: USB DFU Boot Loader for Atmel XMEGA
(file size: 670KB, 13 pages, revision B, updated: 07/2012)

(Software package: file size: 5.8MB, revision C, updated: 12/2015)

 

The Atmel® AVR® XMEGA® devices now make easy to implement and use USB.

 

 

The USB boot loader allows performing in-system programming (ISP) from a USB host controller without removing the part from the system, and without any external programming interface other than the USB connector.

 

...

Just sent the web site correction request.

 

Ref.

http://www.avrfreaks.net/forum/beginning-end?page=1#comment-2323291

 

Edit: Application Notes ...

 

"Dare to be naïve." - Buckminster Fuller

Last Edited: Thu. Nov 23, 2017 - 06:44 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Okay, I posted it: https://github.com/kuro68k/xmega...

 

It works with dfu-util, and comes in a 3.5k so there is room to add a few more features like write verification.