AVR bootloader and serial uart

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

Datasheet for `ATMega328` says:

> When the BOOTRST Fuse is programmed, the Boot section size set to 2K
> bytes and the IVSEL bit in the MCUCR Register is set before any
> interrupts are enabled, the most typical and general program setup for
> the Reset and Interrupt Vector Addresses in ATmega328P is:

    Address Labels Code Comments
    ;
    .org 0x3C00
    0x3C00 jmp RESET ; Reset handler
    0x3C02 jmp EXT_INT0 ; IRQ0 Handler
    0x3C04 jmp EXT_INT1 ; IRQ1 Handler
    ... ... ... ; 

So I've set program origin correspondingly

-Wl,-section-start=.text=0x3C00

Then I set fuse bits to `DA`, which means bootsize `2KB` and starting from `0x3C00`.

This is my main program:

    void main() {
      SET_PIN_MODE_OUTPUT(LED_PIN);
      SET_PIN_MODE_INPUT(RX_PIN);
      SET_PIN_MODE_OUTPUT(TX_PIN);
    
      for(int i = 0; i < 5; i++)
      {
    	  TOGGLE_PIN_VALUE(LED_PIN);
    	  _delay_ms(100);
      }
      _delay_ms(1000);
    
      suart_init();
      MCUCR = (1<<IVCE);
      MCUCR = (1<<IVSEL);
      sei();
    
      sputs("Test!\n\r" );
    
      for(;;)
      {
    	  sputchar( '-' );
    	  sputchar(sgetchar());		
      }
    }

Optimization is set to O1 to maintain 4 cycle limit for `IVSEL`.
What happens with all this, the led will always blink, which makes me think that from somewhere code jumps to reset vector. If sei() commented out, hence global interrupts are disabled and I just have led blinks and that's it.

Here is what I see in the asm listing:

Disassembly of section .text:

    00003c00 <__vectors>:
    3c00:	0c 94 34 1e 	jmp	0x3c68	; 0x3c68 <__ctors_end>
    3c04:	0c 94 51 1e 	jmp	0x3ca2	; 0x3ca2 <__bad_interrupt>
    3c08:	0c 94 51 1e 	jmp	0x3ca2	; 0x3ca2 <__bad_interrupt>
    3c0c:	0c 94 51 1e 	jmp	0x3ca2	; 0x3ca2 <__bad_interrupt>
    3c10:	0c 94 51 1e 	jmp	0x3ca2	; 0x3ca2 <__bad_interrupt>
    3c14:	0c 94 51 1e 	jmp	0x3ca2	; 0x3ca2 <__bad_interrupt>
    3c18:	0c 94 51 1e 	jmp	0x3ca2	; 0x3ca2 <__bad_interrupt>
    3c1c:	0c 94 51 1e 	jmp	0x3ca2	; 0x3ca2 <__bad_interrupt>
    3c20:	0c 94 51 1e 	jmp	0x3ca2	; 0x3ca2 <__bad_interrupt>
    3c24:	0c 94 51 1e 	jmp	0x3ca2	; 0x3ca2 <__bad_interrupt>
    3c28:	0c 94 a6 1e 	jmp	0x3d4c	; 0x3d4c <__vector_10>
    3c2c:	0c 94 1a 1f 	jmp	0x3e34	; 0x3e34 <__vector_11>
    3c30:	0c 94 ca 1e 	jmp	0x3d94	; 0x3d94 <__vector_12>
    3c34:	0c 94 51 1e 	jmp	0x3ca2	; 0x3ca2 <__bad_interrupt>
    3c38:	0c 94 51 1e 	jmp	0x3ca2	; 0x3ca2 <__bad_interrupt>
    ...

Very strange thing is that vector address increment in my program is 4 bytes, but it's 2 bytes in datasheet. `__vector_10, __vector_11 and __vector_12` are software uart related. I suspect that whenever interrupt happens, it will not jump to those vectors, but will jump to `__bad_interrupt` causing reset.

Software UART works perfectly in program flash area. Why it doesn't work in bootloader?

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

A 32K micro surely has the BLS close to 0x7800 not 0x3C00.

Remember Atmel use words, gcc uses bytes!

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

thanks, that indeed worked!!!

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

clawson wrote:
A 32K micro surely has the BLS close to 0x7800 not 0x3C00.

Remember Atmel use words, gcc uses bytes!

Holy crap!!! This is my mistake too!!!
Thanks Clawson!