AVR Bootloader Interrupt Handling

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

I'm writting a bootloader, but I can't interrupt handling on bootloader section.

 

I would like using external interrupt.

 

My code is given below:

#define BAUDRATE (F_CPU / 19200 / 16)

void interrupt_enable(void)
{
   DDRD &= ~(1 << DDD2);
   PORTD |= (1 << PORTD2);

   MCUCR = (1 << IVCE);
   MCUCR = (1 << IVSEL);

   EIMSK = (1 << INT0);
   EICRA = (1 << ISC01);

   SREG |= 0b10000000;
}

void uart_initialization(void)
{
   UBRR0H = (BAUDRATE >> 8);
   UBRR0L = BAUDRATE;
   UCSR0B |= (1 << TXEN0);
}

void uart_write_character(char character)
{
   while (!( UCSR0A & (1 << UDRE0)));
   UDR0 = character;
}

void uart_write_character_array(char *character_array)
{
   while(*character_array != '\0')
   {
      uart_write_character(*character_array);
      character_array++;
   }
}

void main(void) __attribute__ ((naked)) __attribute__ ((section (".init9")));

void main(void)
{
   interrupt_enable();

   loop:
   goto loop;
}

ISR(INT0_vect)
{
   uart_initalization();

   uart_write_character_array("Interrupt has been occoured.");
}

My compiler options are given below:

-O1 -c -DF_CPU=16000000 -mmcu=atmega328p -Ttext=0x7000

My linker options are given below:

-O1 -mcall-prologues -DF_CPU=16000000 -mmcu=atmega328p -Ttext=0x7000

I'm using AVR GCC 7.3.0 and GNU AVR Binutils 2.29.1.

 

What mistake is made by me?

 

Thanks for replies.

Last Edited: Wed. Mar 14, 2018 - 01:33 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ercanersoy wrote:
What mistake is made by me?
The mistake is considering putting interrupts in a bootloader! The fact is that when you ship a product the application itself can be full of bugs because you know you can deliver updates via the bootloader. The only bit that HAS to work and be 100% fault free on day one is the bootloader itself as you cannot change that (well almost!). As soon as you add multiple paths of execution (ie interrupts) you magnify the complexity by X10.

 

However your approach seems fine here. There's no need for any of the .init9 stuff because before main() nothing is going to try to use vectors so if IVSEL defaults to them in the wrong place (near 0x0000) it does not matter. As you know the enabling of IVSEL so the vectors move to the BOOTSZ address is done by the double write to MCUCR so about the only reason I can think that it won't work for you is if you aren't using a high enough optimization level so that the double write is not occurring within 4 cycles yet -O1 should achieve this - but check the generated Asm and count the cycles.

 

I would replace:

   SREG |= 0b10000000;

with

    sei();

Also while I suppose it does not matter in this specific case but doing "long work" like:

  uart_write_character_array("Interrupt has been occoured.");

in an ISR is not a good habit to get into!

 

To be honest I don't really understand what your attempted use of interrupts gains you here anyway? Why not a simply loop in main() that polls the state of the INT0 pin and when it's active it does the uart stuff (oh and you can always do the uart init outside any such loop (or outside the ISR) so it's just the write string that is triggered by the pin change.

 

BTW if one were looking for mistakes I would check that the BOOTSZ is set to the 0x7000 / 0x3800 position and also that the BOOTRST fuse is enabled.

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

I using Arduino and fuses are standard.

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

I disassembled MCUCR section of my code:

   0x00007114 <+4>:	ldi	r25, 0x01	; 1
   0x00007116 <+6>:	out	0x35, r25	; 53
   0x00007118 <+8>:	ldi	r24, 0x02	; 2
   0x0000711a <+10>:	out	0x35, r24	; 53

I see this is correct.

 

What can I?

Last Edited: Wed. Mar 14, 2018 - 05:56 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry but what actually makes you think this is NOT working? What did you observe? How does it differ from your expectation?

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

I used Wiznet 5100 and the code is smaller than my orginal code. When the interrupt occours, the code has restarted.

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

I have no idea what you are talking about?

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

ercanersoy wrote:
I using Arduino and fuses are standard.
What exactly are the "Arduino standard fuses"?

Stefan Ernst

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

My Arduino's fuses are: E:0xFD, H:0xDE, L:0xFF

 

I have changed extended fuse to 0x05. But, avrdude have changed back when my program has uploaded.

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

ercanersoy wrote:
-Ttext=0x7000

ercanersoy wrote:
My Arduino's fuses are: ..., H:0xDE, ...
Does not match. Of course interrupts aren't working then.

As Cliff already mentioned, you have to change BOOTSZ according to your bootloader's starting address.

Stefan Ernst

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

I have changed extended fuse to 0x05. But, avrdude have changed back when my program has uploaded.

How are you 'uploading' your code to the target?  Show the exact command you're using, and show the complete output of that command.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

My current fuses are: E:0x00, H:0xD9, L:0xFF

 

I have set BOOTSZ[1:0].

 

I have disabled brown-out dedector of bootloader.

 

Thanks for all replies.

 

Ercan

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

joeymorin wrote:

I have changed extended fuse to 0x05. But, avrdude have changed back when my program has uploaded.

How are you 'uploading' your code to the target?

That "changed back" is no real problem. That are only the unused fuse bits that can't be programmed to 0 and which are then read back as 1 again.

Stefan Ernst

Last Edited: Wed. Mar 14, 2018 - 05:55 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That "changed back" is no real problem. That are only the unused fuse bits that can't be programmed to 0 and which are then read back as 1 again.

Perhaps.  A look at the output from avrdude would still tell us what's going on.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]