XMEGA DFU

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

Hi All,

This is a recurring problem on the forum but there hasn't been a solution TMK, let's try again :)

The XMEGA DFU bootloader is supposed to be able to be entered by jumping to a magic offset inside the bootloader:

AVR1916 wrote:
Internal firmware request: The user application can decide to start a DFU session. This can be achieved by jumping to a specific address in the boot loader firmware. The entry point to start a DFU session initiated by a user application firmware jump is BOOT_SECTION_START + 0x1FC for all devices

but no amount of

void (*bl)(void) = (BOOT_SECTION_START + 0x1FC) / 2;
bl();

will get me there (with or without the divide-by-two, udc_stop() calls, interrupt vector table location changes etc.). Has anyone actually done this? Care to share? I'm on an ATXMEGA256A3BU FWIW.

Reported in, e.g.
https://www.avrfreaks.net/index.p...
https://www.avrfreaks.net/index.p...

Cheers.
-S.

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

Your link doesn't work with the /blaq at the end. :)

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

Surely in an Xmega there's got to be a strong chance that a bootloader function address is out of range of a 16bit pointer. The function pointer you are defining will only be 16 bit so can only reach 64K locations. Either hand code an Asm CALL or use ICALL/IJMP after setting the 24 bit register or push THREE bytes onto the stack and do a RET.

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

clawson wrote:
Surely in an Xmega there's got to be a strong chance that a bootloader function address is out of range of a 16bit pointer. The function pointer you are defining will only be 16 bit so can only reach 64K locations. Either hand code an Asm CALL or use ICALL/IJMP after setting the 24 bit register or push THREE bytes onto the stack and do a RET.
Right, thanks. I thought I had checked this as the ASM generated using an eicall, but the code never set up EIND.. Anyway, for the curious, the below trickery does the job:

udc_stop(); /*Required to stop USB interrupts messing you up before the vectors have been moved */

/* Jump to 0x401FC = BOOT_SECTION_START + 0x1FC which is
 * the stated location of the bootloader entry (AVR1916).
 * Note the address used is the word address = byte addr/2.
 * My ASM fu isn't that strong, there are probably nicer
 * ways to do this with, yennow, defined symbols .. */

asm ("ldi r30, 0xFE\n"  /* Low byte to ZL */
	  "ldi r31, 0x00\n" /* mid byte to ZH */
	  "ldi r24, 0x02\n" /* high byte to EIND which lives */
	  "out 0x3c, r24\n" /* at addr 0x3c in I/O space */
	  "eijmp":  :: "r24", "r30", "r31");