bootloader atmega problem

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

Hi all!

I have some problem with my bootloader (using AVR Studio 6.2). Bootloader writes flash without any problem. I read flash using programmer and compare both files (original and readed). They are fully identical, data and addresses the same. But main program isn't started. Bootloader writes flash and then ... nothing. I think that problem is in jump to 0 address. I do the following:

static void (*jump_to_app)(void)=0x0000;
int main(void)
{
   // write flash
   jump_to_app(); // Jump to Reset vector 0x0000 in Application Section.
   return 0;
}

I don't have any ideas why it is happening. Maybe you help? Many thanks.

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

What assembly code does it produce?

Optiboot uses:

  __asm__ __volatile__ (
    // Jump to RST vector
    "clr r30\n"
    "clr r31\n"
    "ijmp\n"
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes, thank you westfw. Your code works. But why my code doesn't work? This is code from AVR109: Self Programming manual. Atmel recommends doing so. Why? It is not essentially but very interesting why.

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

just a guess:
is it a chip with more than 128k flash?
then perhaps a page register needs to be cleared aswell.

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

The code you showed should have worked. In fact if I build it as follows:

$ cat avr.c
#include 

static void (*jump_to_app)(void)=0x0000;
int main(void)
{
   // write flash
   jump_to_app(); // Jump to Reset vector 0x0000 in Application Section.
   return 0;
} 

$ avr-gcc -mmcu=atmega16 -g -Os avr.c -o avr.elf
$ avr-objdump -S avr.elf

avr.elf:     file format elf32-avr


Disassembly of section .text:

00000000 <__vectors>:
   0:	0c 94 2a 00 	jmp	0x54	; 0x54 <__ctors_end>

[SNIP!]

00000054 <__ctors_end>:
  54:	11 24       	eor	r1, r1
  56:	1f be       	out	0x3f, r1	; 63
  58:	cf e5       	ldi	r28, 0x5F	; 95
  5a:	d4 e0       	ldi	r29, 0x04	; 4
  5c:	de bf       	out	0x3e, r29	; 62
  5e:	cd bf       	out	0x3d, r28	; 61
  60:	0e 94 36 00 	call	0x6c	; 0x6c 
64: 0c 94 3c 00 jmp 0x78 ; 0x78 <_exit> 00000068 <__bad_interrupt>: 68: 0c 94 00 00 jmp 0 ; 0x0 <__vectors> 0000006c
: static void (*jump_to_app)(void)=0x0000; int main(void) { // write flash jump_to_app(); // Jump to Reset vector 0x0000 in Application Section. 6c: e0 e0 ldi r30, 0x00 ; 0 6e: f0 e0 ldi r31, 0x00 ; 0 70: 09 95 icall return 0; } 72: 80 e0 ldi r24, 0x00 ; 0 74: 90 e0 ldi r25, 0x00 ; 0 76: 08 95 ret 00000078 <_exit>: 78: f8 94 cli 0000007a <__stop_program>: 7a: ff cf rjmp .-2 ; 0x7a <__stop_program>

As you can see the compiler pretty much agrees with westfw (though C calls not jumps) so this should have worked for you.

As he said, "what assembly code does your code produce"?

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

This my disassembler:

Disassembly of section .text:

00000000 <__vectors>:
   0:	29 c0       	rjmp	.+82     	; 0x54 <__ctors_end>
   2:	00 00       	nop
   4:	2f c0       	rjmp	.+94     	; 0x64 <__bad_interrupt>
   6:	00 00       	nop
   8:	2d c0       	rjmp	.+90     	; 0x64 <__bad_interrupt>
   a:	00 00       	nop
   c:	2b c0       	rjmp	.+86     	; 0x64 <__bad_interrupt>
   e:	00 00       	nop
  10:	29 c0       	rjmp	.+82     	; 0x64 <__bad_interrupt>
  12:	00 00       	nop
  14:	27 c0       	rjmp	.+78     	; 0x64 <__bad_interrupt>
  16:	00 00       	nop
  18:	25 c0       	rjmp	.+74     	; 0x64 <__bad_interrupt>
  1a:	00 00       	nop
  1c:	23 c0       	rjmp	.+70     	; 0x64 <__bad_interrupt>
  1e:	00 00       	nop
  20:	21 c0       	rjmp	.+66     	; 0x64 <__bad_interrupt>
  22:	00 00       	nop
  24:	1f c0       	rjmp	.+62     	; 0x64 <__bad_interrupt>
  26:	00 00       	nop
  28:	1d c0       	rjmp	.+58     	; 0x64 <__bad_interrupt>
  2a:	00 00       	nop
  2c:	1b c0       	rjmp	.+54     	; 0x64 <__bad_interrupt>
  2e:	00 00       	nop
  30:	19 c0       	rjmp	.+50     	; 0x64 <__bad_interrupt>
  32:	00 00       	nop
  34:	17 c0       	rjmp	.+46     	; 0x64 <__bad_interrupt>
  36:	00 00       	nop
  38:	15 c0       	rjmp	.+42     	; 0x64 <__bad_interrupt>
  3a:	00 00       	nop
  3c:	13 c0       	rjmp	.+38     	; 0x64 <__bad_interrupt>
  3e:	00 00       	nop
  40:	11 c0       	rjmp	.+34     	; 0x64 <__bad_interrupt>
  42:	00 00       	nop
  44:	0f c0       	rjmp	.+30     	; 0x64 <__bad_interrupt>
  46:	00 00       	nop
  48:	0d c0       	rjmp	.+26     	; 0x64 <__bad_interrupt>
  4a:	00 00       	nop
  4c:	0b c0       	rjmp	.+22     	; 0x64 <__bad_interrupt>
  4e:	00 00       	nop
  50:	09 c0       	rjmp	.+18     	; 0x64 <__bad_interrupt>
	...

00000054 <__ctors_end>:
  54:	11 24       	eor	r1, r1
  56:	1f be       	out	0x3f, r1	; 63
  58:	cf e5       	ldi	r28, 0x5F	; 95
  5a:	d4 e0       	ldi	r29, 0x04	; 4
  5c:	de bf       	out	0x3e, r29	; 62
  5e:	cd bf       	out	0x3d, r28	; 61
  60:	02 d0       	rcall	.+4      	; 0x66 
62: 07 c0 rjmp .+14 ; 0x72 <_exit> 00000064 <__bad_interrupt>: 64: cd cf rjmp .-102 ; 0x0 <__vectors> 00000066
: static void (*jump_to_app)(void)=0x0000; int main(void) { jump_to_app(); 66: e0 e0 ldi r30, 0x00 ; 0 68: f0 e0 ldi r31, 0x00 ; 0 6a: 09 95 icall return 0; 6c: 80 e0 ldi r24, 0x00 ; 0 6e: 90 e0 ldi r25, 0x00 ; 0 70: 08 95 ret 00000072 <_exit>: 72: f8 94 cli 00000074 <__stop_program>: 74: ff cf rjmp .-2 ; 0x74 <__stop_program>

As you can see it is the same. In fact, code is for atmega256rfr2 with my own make file. Can it be reason?

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

Ah now 256K devices (I assume it is) are something a bit special because they go beyond 16bit program addressing so you often have to consider the RAMPZ register. As bootloader code is located "up high" I imagine RAMPZ is non-zero in the bootloader and yet to get to 0x000000 you need it to be 0. Maybe try

RAMPZ = 0;

before

jump_to_app();

Or just hard code a "JMP 0x0000" which will be a 24 bit address on that CPU. Or the classic is LDI Rn,0; PUSH Rn;PUSH Rn;PUSH Rn;RET

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

Quote:
Can it be reason?

No not when you compile it to ijmp (or icall) aswell, they are by def. 16 bit.

edit
not for the jump itself, but perhaps your app. program don't like it! (but then both programs should fail).

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

one thing more make sure that interrupt are disabled :)

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

Interrupts are disabled because I haven't turned on it.

RAMPZ = 0;

is helped! It is for more than 64KB flash. I see my mistake, simply I didn't know about this AVR peculiarity.

Thank you, guys!

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

But why does westfw's code work, it don't clear RAMPZ?

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

Good question. I can say more: sometimes my code works too. Yesterday I saw how after boot update main program is starting. And several times before. I do not know how to explain it. Why sometimes RAMPZ clears in end of update?

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

perhaps some of your code move over and under the 64K limit for flash data, and 128K (64k words) for code.
Ex if your init code move over and under it will make a big difference.