relocate Interrupt vector start address

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

Hi,

I am trying to write a bootloader for the mega128. I want to equally separate the application section of the flash into two parts. I have programmed the necessary fuses to produce a bootloader section of 2048 bytes. The idea is to let the bootloader decide based on version number stored in eeprom which section has the latest code, and run it when the part comes out of reset. This way, i'll always have a backup in flash.

I have sucessfully written some test code which starts executing at 0x7c00. The IVSEL is clear so that the interrupt vector table starts at address 0x0002. The problem is, my interrupts don't work after the code jumps into the application section from boot section.

Is there a way to rewire the interrupt vector start address so that it starts at an address other than 0x0002 or, in my case, 0xF802? If someone could point me in the right direction, i'd greatly appreciate it.

hodgeep

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

You can, respectively you have to map your ISR-Vectors either to the bootloader section or to the application section.

//---------------------------------------
// Map ISR vectors to bootloader section
//---------------------------------------
cli();               // disable interupts
MCUCR = (1<<IVCE);   // enable interruptvectors change
MCUCR = (1<<IVSEL);  // move interruptvectors to bootloader
sei();               // reenable interrupts
//---------------------------------------
//---------------------------------------
// Map ISR vectors to application section
//---------------------------------------
cli();               // disable interupts
MCUCR = (1<<IVCE);   // enable interruptvectors change
MCUCR = (0<<IVSEL);  // move interruptvectors to application
sei();               // reenable interrupts
//---------------------------------------

Regrds Peter

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

Thank Peter.

You are absolutely right, and I had already implemented your suggestion. But I was looking for information on relocating the ISR-Vector to a specific address in the application section. I believe those instructions put the vector table at either of two addresses (0x0002, or in my case, 0xF802).

Remember that the application section will be divided in two. The version that starts at address 0x0000 works fine. The version that starts at 0x7C00 doesn't. I believe the ISR-vector start address is responsible. Therefore I think I need to relocate it to interrupt vector start address 0x7C02 if I want the interrupts to work . The reset vector is 0x7C00 in the second version of the code.

hodgeep

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

You cannot re-map the locations beyond the app/boot section switch available via the IVSEL bit.

Does your boot section use interrupts? If not use the boot table for the first version, the the application section table for the second.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

Thanks Dean.

The bootloader does not need to use interrupts. It does so now only for test, but I can switch to polling very easily.

Any tips on how I can accomplish your suggested task? How do I tell the code loaded in my reserve application section to use the interrupt vector table from the bootloader section?

hodgeep

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

By messing with IVSEL as peter.sager says. You'll have to do a song and dance to get the darn thing to all link correctly. I've personally never tried it, but it's possible.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

Apologies for bringing this thread back from the mists of time, but I'm trying to do almost exactly what the original was trying, and have yet to find a solution better than those above, which will work, but don't seem optimal.

 

Fiddling with MCUCR and IVSEL will work, but only allows two interrupt tables, and as Deans said, will likely need a song and dance with the linker.

 

I'm trying to do this almost with an ATmega128, specifically an ATmegaS128, so my purpose is plausibly guessed as involving a higher level radiation environment than normal. smiley

 

I'd like to have several copies of my program available, and will generally patch an unused copy, before changing the reboot location (probably stored in EEPROM) and then initiating a reboot using the Watchdog.  There may also be a CRC or Checksum done on the code, before allowing switching into that program space.  Being able to have more than a bare minimum two copies, would be preferable, so I'm considering just sending all of the interrupts to a part of the "bootloader" (which won't really do any loading), where it looks up the interrupt from a RAM based table, and jumps to that location.

 

There will be a slight cost in speed and RAM use, but I guess that will probably be tolerable.  I'm still going to have to fiddle with the linker, and write a few small functions to handle interrupt setup, but probably nothing particularly onerous.  There's also an increased risk of failure, since corruption/failure of either the relevant part of the Flash or the secondary interrupt lookup table in RAM would cause an interrupt to fail.

 

Has anyone thought of a tidier or better way of doing this, in the intervening decade ?

Actually, I am a rocket scientist.

Last Edited: Mon. May 14, 2018 - 07:29 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Flexagain wrote:
where it looks up the interrupt from a RAM based table, and jumps to that location.
Sorry but you are working in a rad-hard environment and you actually want to have the vectors go via RAM which is even more hazardous than the flash?!?

 

AVRs only allow for two copies of the vector table - the one at 0 and the one at the BOOTSZ location (and enabled by IVSEL) and that is it. So you are going to have to "trust" one or other of those as that's the only place the AVR will (initially) be headed on the occasion of an interrupt event. Sure, one or other of those could then have some fancy function pointer based redefinable destination but the stuff at the initial vector location has to be trusted. Also, like I say, taking execution out through RAM (which might be blown away in a cosmic nanosecond) is "dangerous" at best.

 

I would advise you write any code for a "hostile" environment with a minimum of MISRA as your guiding standard and one of the first things you are going to find there is that RAM based vectoring is a no-no.

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

clawson wrote:
Flexagain wrote:
where it looks up the interrupt from a RAM based table, and jumps to that location.

Sorry but you are working in a rad-hard environment and you actually want to have the vectors go via RAM which is even more hazardous than the flash?!?

 

Well, without a detailed radiation report, whether Flash or RAM is the most radiation tolerant is an arguable point, neither is generally very rad hard.  If we were really worried about radiation effects, we wouldn't be using an AVR, which only has a TID of 30 kRad anyway.

 

clawson wrote:
... Also, like I say, taking execution out through RAM (which might be blown away in a cosmic nanosecond) is "dangerous" at best.

 

In an ideal world, I'd find other ways to do it.  I could put the patch table into Flash or EEPROM too, but that would substantially complicate the code, which itself is generally undesirable, and may be just as bad from an SEU point-of-view.  Having to patch a single copy of the code, whilst it's executing would also be undesirable.

 

clawson wrote:
I would advise you write any code for a "hostile" environment with a minimum of MISRA as your guiding standard and one of the first things you are going to find there is that RAM based vectoring is a no-no.

 

If I had the time to deal with proper software management standards, I'd being using far more stringent than MISRA, but unfortunately this is a small mission, where available manpower and costs are minimal, so we have to get by with what's available.  I'd love to be able to write stringent code, and undertake a lot of testing, but practically I've barely got the time to write the code and get it working !

 

The best we can do to make things more tolerant, is follow Atmel's guidance (ie Application Note 41086A), use the Watchdog and throw CRC/checksums at things, when I can.  A temporary flip in RAM is just likely to crash the CPU, and hopefully that's recoverable with a Watchdog reboot.  A flip in the Flash could be more permanent, and a minimal bootloader, doing some sort of consistency checking on the Flash, before it switches to the most reliable codeset has some advantages.  The bootloader itself is always going to be a single point of failure, but there's nothing that can be done about that, with a single chip solution, like an AVR.

Actually, I am a rocket scientist.

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

Well like I say, the AVR does not give you much choice. There are only two possible locations for the IVT (and only one can be active) so you have to trust the active one.

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

You can use a common interrupt jump table to another set of addresses, that will execute a jump to an address recorded in a table at the eeprom.  So, whenever your application starts, address zero or bootload address, it will transfer its own jump address table to this common address at eeprom, if the eeprom doesn't contain the exact copy of it (saving erase/write life count of eeprom).  So, no matter which application is running, the eeprom will contain the jump addresses for that application, and interrupts will jump to the right addresses.

 

I used a similar technique with 8051 microcontroller accessing more than 64k of program code, when the code by itself switch eproms (or banks in the same 512kBytes eprom), he had the same jump table at the interrupt address on both eproms, and both eproms had the exactly the same interrupt routines, so it never get lost.  I even wrote this on my very old (many years ago) website http://www.ustr.net/electronics/512k.shtml

Wagner Lipnharski
Orlando Florida USA

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

My approach to this sort of problem was to partition the Flash into N+1 sections. (Where N is the number of possible applications which you want to be able to fall back on at any point in time.)

 

The running application always resides in the zeroth Flash partition, and the higher partitions are only used to hold the archived alternate applications.

 

The bootloader determines which application needs to run in any given circumstance, and copies it into the zeroth partition, where it is always mapped directly into the AVR's native interrupt vector table, no extra indirect jumps need to be computed or evaluated, and the linker doesn't need any trickery to know how to call functions, compute interrupt addresses, etc.

 

For good measure, of course, all Flash partitions are signed with a CRC so that the bootloader can be certain, in advance, that the application it's about to run hasn't experienced any accidental corruption.

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

I would advise you write any code for a "hostile" environment with a minimum of MISRA as your guiding standard

If you don't, you will likely be rather "misrable".  crying 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

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

place an universal interrupt-vector-table at $0000 and all of your applications (with their own interrupt-vector-tables in the beginning) on page boundaries from $0100 on

 

an interrupt-vector on page $00 has room for two 1-word-assembler instructions: the first will fetch his own vector-address low-byte and 'rjmp' to the universal interrupt-handler. the handler will fetch the high-byte of the active application from EEPROM (or SRAM or an unused IO-register [GPIO would be fine but there isn't one on mega128, is it?]), push the two bytes in the right order onto stack and perform an 'ret' 

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

My question is related to ATMega 640/1280/2560. Let us suppose that the Reset Vector is moved to BLS and the IVT resides in the app section. Under the stated condition, I assume that the app section address 0x0000 is like any other normal flash location, but can not be used for useful purpose. Is it correct?

Vinu Raja Kumar C

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

If you do use interrupts in a bootloader usually youd have TWO interrupt vector tables in the AVR. One is built at the BLS address and is used by the bootloader. When it first starts it sets IVSEL so that one is active. Once it has done its thing and is about to start the app it resets IVSEL then jumps to the app that can then use it's own set of interrupts. Obviously if either program will not use interrupts you can build it with -nostartfiles and reclaim the flash space the IVT from the CRT would have occupied.

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

Why interrupt vectors that are in application section does not work in bootloader section ???

 

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

Thing about it. You build:

#include <avr/io.h>
#include <avr/interrupt.h>

ISR(USART_RX_vect) {
	// stuff
}

int main()
{
	init_uart();
	while (1) {
		
	}
}

but because it's a bootloader you also specify -Text=0x7000 (say) to have the entire thing positioned from 7000 onwards) so what do you actually build? It's something like:

00007000 <__vectors>:
    7000:	33 c0       	rjmp	.+102    	; 0x7068 <__ctors_end>
    7002:	00 00       	nop
    7004:	39 c0       	rjmp	.+114    	; 0x7078 <__bad_interrupt>
    7006:	00 00       	nop
    7008:	37 c0       	rjmp	.+110    	; 0x7078 <__bad_interrupt>
    700a:	00 00       	nop
    700c:	35 c0       	rjmp	.+106    	; 0x7078 <__bad_interrupt>
    700e:	00 00       	nop
    7010:	33 c0       	rjmp	.+102    	; 0x7078 <__bad_interrupt>
    7012:	00 00       	nop
    7014:	31 c0       	rjmp	.+98     	; 0x7078 <__bad_interrupt>
    7016:	00 00       	nop
    7018:	2f c0       	rjmp	.+94     	; 0x7078 <__bad_interrupt>
    701a:	00 00       	nop
    701c:	2d c0       	rjmp	.+90     	; 0x7078 <__bad_interrupt>
    701e:	00 00       	nop
    7020:	2b c0       	rjmp	.+86     	; 0x7078 <__bad_interrupt>
    7022:	00 00       	nop
    7024:	29 c0       	rjmp	.+82     	; 0x7078 <__bad_interrupt>
    7026:	00 00       	nop
    7028:	27 c0       	rjmp	.+78     	; 0x7078 <__bad_interrupt>
    702a:	00 00       	nop
    702c:	25 c0       	rjmp	.+74     	; 0x7078 <__bad_interrupt>
    702e:	00 00       	nop
    7030:	23 c0       	rjmp	.+70     	; 0x7078 <__bad_interrupt>
    7032:	00 00       	nop
    7034:	21 c0       	rjmp	.+66     	; 0x7078 <__bad_interrupt>
    7036:	00 00       	nop
    7038:	1f c0       	rjmp	.+62     	; 0x7078 <__bad_interrupt>
    703a:	00 00       	nop
    703c:	1d c0       	rjmp	.+58     	; 0x7078 <__bad_interrupt>
    703e:	00 00       	nop
    7040:	1b c0       	rjmp	.+54     	; 0x7078 <__bad_interrupt>
    7042:	00 00       	nop
    7044:	19 c0       	rjmp	.+50     	; 0x7078 <__bad_interrupt>
    7046:	00 00       	nop
    7048:	19 c0       	rjmp	.+50     	; 0x707c <__vector_18>
    704a:	00 00       	nop
    704c:	15 c0       	rjmp	.+42     	; 0x7078 <__bad_interrupt>
    704e:	00 00       	nop
    7050:	13 c0       	rjmp	.+38     	; 0x7078 <__bad_interrupt>
    7052:	00 00       	nop
    7054:	11 c0       	rjmp	.+34     	; 0x7078 <__bad_interrupt>
    7056:	00 00       	nop
    7058:	0f c0       	rjmp	.+30     	; 0x7078 <__bad_interrupt>
    705a:	00 00       	nop
    705c:	0d c0       	rjmp	.+26     	; 0x7078 <__bad_interrupt>
    705e:	00 00       	nop
    7060:	0b c0       	rjmp	.+22     	; 0x7078 <__bad_interrupt>
    7062:	00 00       	nop
    7064:	09 c0       	rjmp	.+18     	; 0x7078 <__bad_interrupt>
	...

00007068 <__ctors_end>:
    7068:	11 24       	eor	r1, r1
    706a:	1f be       	out	0x3f, r1	; 63
    706c:	cf ef       	ldi	r28, 0xFF	; 255
    706e:	d8 e0       	ldi	r29, 0x08	; 8
    7070:	de bf       	out	0x3e, r29	; 62
    7072:	cd bf       	out	0x3d, r28	; 61
    7074:	0d d0       	rcall	.+26     	; 0x7090 <main>
    7076:	0e c0       	rjmp	.+28     	; 0x7094 <_exit>

00007078 <__bad_interrupt>:
    7078:	c3 cf       	rjmp	.-122    	; 0x7000 <__vectors>

0000707a <init_uart>:
 * file1.c
 *
 * Created: 17/02/2020 09:37:41
 *  Author: uid23021
 */ 
    707a:	08 95       	ret

0000707c <__vector_18>:
#include <avr/io.h>
#include <avr/interrupt.h>

ISR(USART_RX_vect) {
    707c:	1f 92       	push	r1
    707e:	0f 92       	push	r0
    7080:	0f b6       	in	r0, 0x3f	; 63
    7082:	0f 92       	push	r0
    7084:	11 24       	eor	r1, r1
	// stuff
}
    7086:	0f 90       	pop	r0
    7088:	0f be       	out	0x3f, r0	; 63
    708a:	0f 90       	pop	r0
    708c:	1f 90       	pop	r1
    708e:	18 95       	reti

00007090 <main>:

int main()
{
	init_uart();
    7090:	f4 df       	rcall	.-24     	; 0x707a <init_uart>
    7092:	ff cf       	rjmp	.-2      	; 0x7092 <main+0x2>

The code starts at 0x7000. Because you will have set BOOTRST and BOOTSZ then when the AVR powers on the first instruction it fetches will be that:

00007000 <__vectors>:
    7000:	33 c0       	rjmp	.+102    	; 0x7068 <__ctors_end>

which is the actual reset jump but look at what comes next:

    7004:	39 c0       	rjmp	.+114    	; 0x7078 <__bad_interrupt>
    7006:	00 00       	nop
    7008:	37 c0       	rjmp	.+110    	; 0x7078 <__bad_interrupt>
    700a:	00 00       	nop
    700c:	35 c0       	rjmp	.+106    	; 0x7078 <__bad_interrupt>
    700e:	00 00       	nop
    7010:	33 c0       	rjmp	.+102    	; 0x7078 <__bad_interrupt>
    7012:	00 00       	nop
    7014:	31 c0       	rjmp	.+98     	; 0x7078 <__bad_interrupt>
    7016:	00 00       	nop
    7018:	2f c0       	rjmp	.+94     	; 0x7078 <__bad_interrupt>
    701a:	00 00       	nop
    701c:	2d c0       	rjmp	.+90     	; 0x7078 <__bad_interrupt>
    701e:	00 00       	nop
    7020:	2b c0       	rjmp	.+86     	; 0x7078 <__bad_interrupt>
    7022:	00 00       	nop
    7024:	29 c0       	rjmp	.+82     	; 0x7078 <__bad_interrupt>
    7026:	00 00       	nop
    7028:	27 c0       	rjmp	.+78     	; 0x7078 <__bad_interrupt>
    702a:	00 00       	nop
    702c:	25 c0       	rjmp	.+74     	; 0x7078 <__bad_interrupt>
    702e:	00 00       	nop
    7030:	23 c0       	rjmp	.+70     	; 0x7078 <__bad_interrupt>
    7032:	00 00       	nop
    7034:	21 c0       	rjmp	.+66     	; 0x7078 <__bad_interrupt>
    7036:	00 00       	nop
    7038:	1f c0       	rjmp	.+62     	; 0x7078 <__bad_interrupt>
    703a:	00 00       	nop
    703c:	1d c0       	rjmp	.+58     	; 0x7078 <__bad_interrupt>
    703e:	00 00       	nop
    7040:	1b c0       	rjmp	.+54     	; 0x7078 <__bad_interrupt>
    7042:	00 00       	nop
    7044:	19 c0       	rjmp	.+50     	; 0x7078 <__bad_interrupt>
    7046:	00 00       	nop
    7048:	19 c0       	rjmp	.+50     	; 0x707c <__vector_18>
    704a:	00 00       	nop
    704c:	15 c0       	rjmp	.+42     	; 0x7078 <__bad_interrupt>
    704e:	00 00       	nop
    7050:	13 c0       	rjmp	.+38     	; 0x7078 <__bad_interrupt>
    7052:	00 00       	nop
    7054:	11 c0       	rjmp	.+34     	; 0x7078 <__bad_interrupt>
    7056:	00 00       	nop
    7058:	0f c0       	rjmp	.+30     	; 0x7078 <__bad_interrupt>
    705a:	00 00       	nop
    705c:	0d c0       	rjmp	.+26     	; 0x7078 <__bad_interrupt>
    705e:	00 00       	nop
    7060:	0b c0       	rjmp	.+22     	; 0x7078 <__bad_interrupt>
    7062:	00 00       	nop
    7064:	09 c0       	rjmp	.+18     	; 0x7078 <__bad_interrupt>

That is the entire interrupt vector table. You can see the USART_RX_vect hook at location 7048 - that is a jump to "__vector_18". So you want the AVR, when it sees an RXC interrupt event to jump to that vector location - but it is at 7048 not 0048 (which is the power on default location for such an event to route via. In this AVR, because it only has a bootloader and no application programmed yet then what you most definitely do not want is the RXC interrupt to go to 0048. But that is exactly what the default action of an AVR is.

 

Now you could maybe have hoped that by setting BOOTRST (and BOOTSZ01/ being known) that the AVR might default to use an interrupt vector table just beyond the BLS address chosen by BOOTSZ but this is not the case - you have to do it manually. So the first thing your interrupt using bootloader code does after power on (and most definitely before any SEI) is to use IVSEL (Interrupt Vectors Select) to say "use a table at the BOOTSZ location, not the default one down at 0x0000.

 

Of cause the corollary of this is that once your bootloading is finished and just before you jump to 0x0000 to start the newly programmed code you have to switch IVSEL back as the new app has almost certainly brought its own set of vectors down above 0000 and it will want those ones, not the ones up at 70000 owned by the bootloader to now be the active ones.

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

thank you

but 1 question

if I program application this problem will be solve?

does application and bootloader section use same interrupt vector ?

If interrupt vectors be at the bootsection ,where is application interrupts? is it use same=bootloder section interrupt?

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

hasanzadeh99 wrote:
if I program application this problem will be solve?
Of course it won't. When using a bootloader (and more so when using a bootloader with interrupts) you have two completely distinct and separate programs in the AVR. The bootloader may have interrupt vectors it uses for its own operation and you want the vectors for those to be provided by a table that the bootloader has built in (and then activates with IVSEL). The application very likely has a completely different use of interrupts - it has it's own vector table and you want that to route to its own vector handlers when it is active (so that is the IVSEL=1 state).

 

IVSEL is a binary value saying which of the two programs currently "owns" the interrupts. When set 0 (low) it means the app has its active vectors down near 0000 and then it is 1 (high) is means the bootloader has the active vectors just above the BLS address set by BOOTSZ.

 

Only one vector table can be active at any time (IVSEL is a single bit meaning effectively app or boot). So when IVSEL is set one way the "other" vector table is completely dead.

 

PS of course if you follow my advice in some other thread you have where you even suggested using interrupts in a bootloader then if you never actually use interrupts you don't have to understand IVSEL !

Last Edited: Wed. Feb 19, 2020 - 01:34 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you clawson

I before use codevision and in bootloader section never write IVSEL or ...

it means every thing was OK and there is no need to determine place of the bootloader interrupt or else....

How it works?

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

It would be the same for Codevision as it is for GCC. As soon as you lift the "entire program" (and that means the reset vector, the IVT, the CRT and the code itself) and dump it at a "high" location then you need to tell the AVR (IVSEL) that the active vector table is not in the default (just above 0000) location. That is the same whatever programming system you use. It would be equally true for Asm only code too.

 

PS it is possible you may be able to "fool yourself" into thinking something else works. If you have both boot and app in a device at one time and the "wrong" table is active it's possible that its vectors handle the situation benignly (for instance the one being use is all RETIs anyway).

 

But avr-gcc maps all unprogrammed vectors to "_bad_interrupt" and that deliberately "crashes" the AVR so you can't avoid the fact that you activated a vector without a valid handler. It could be that Codevision's handling of unassigned vectors takes a "softer" approach that seems to "work" (even if the "wrong" vectors are being used)

Last Edited: Wed. Feb 19, 2020 - 01:47 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
it is possible you may be able to "fool yourself" into thinking something else works.

Indeed.

 

Only this morning - another example of stuff that's "wrong" but yet still "works":

 

https://www.avrfreaks.net/commen...

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

yeah I saw gcc bad interrupts but codevision withoud IVSEL and other setting probably place interrupt vector at beginnig of the bootloader maybe!

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

clawson wrote:
But avr-gcc maps all unprogrammed vectors to "_bad_interrupt" and that deliberately "crashes" the AVR so you can't avoid the fact that you activated a vector without a valid handler.
I certainly could and I'm not the only one.

__bad_interrupt does a pseudo-reset, i.e. a jump to the beginning of the vector table, i.e. the reset vector.

In a production system, that is probably close to what you want.

For debugging, not so much.

Iluvatar is the better part of Valar.

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

If an app follow the usual pattern of one time init, infinite while loop, then the fact that a missing vector keeps taking it out of the loop and back through one time stuff is surely some kind of clue that you have done something very wrong?

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

hasanzadeh99 wrote:
but codevision withoud IVSEL and other setting probably place interrupt vector at beginnig of the bootloader maybe!

"Probably" and "Maybe"?

 

[flame alert] clawson just today pointed out that CV generates bloated and pointless code.  Perhaps it is some of this precautionary stuff, like disabling the watchdog at reset in the default prologue, that is saving people's butts.  devil

 

More likely, it is you that told CV that you were making a bootloader, and it was you that told CV that you were making an application.  Tell version; tell/show compiler options; show a complete test program with generated code to see if IVSEL is handled for you.

 

[edit]

                 __RESET:
003841 94f8      	CLI
003842 27ee      	CLR  R30
003843 bbec      	OUT  EECR,R30

                 ;INTERRUPT VECTORS ARE PLACED
                 ;AT THE START OF THE BOOT LOADER
003844 e0f1      	LDI  R31,1
003845 bff5      	OUT  MCUCR,R31
003846 e0f2      	LDI  R31,2
003847 bff5      	OUT  MCUCR,R31

                 ;CLEAR R2-R14
0038...

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

Last Edited: Wed. Feb 19, 2020 - 10:13 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:
clawson just today pointed out that CV generates bloated and pointless code.
To be fair in the same sentence I also said that there are many ways in which CV is "better" than GCC too. Clearly it's automatic setting of IVSEL for bootloader code is yet another of them! :-)

 

(devils advocate: I assume there's also an option to say whether you want an IVT or not and, if you select "not" it does not waste space generating the IVSEL setting stuff too? ;-)

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

clawson wrote:
(devils advocate: I assume there's also an option to say whether you want an IVT or not and, if you select "not" it does not waste space generating the IVSEL setting stuff too? ;-)

I didn't see it at first pass. 

 

I'm not a bootloader person, so haven't examined the startup.  Indeed an item such as this takes a few extra words.  Indeed that can be of critical importance in some apps.  But you can always roll your own.

 

I could probably dig up the threads on the smallest program -- "CV is inferior to GCC because the null program is larger".  As I mentioned above, one thing it does is take care of the watchdog.  That seems like it is helpful for the common programmer to avoid the pitfall of cascading watchdogs as some have posted.

 

In this case it helped the OP develop a bootloader without understanding the nuances of IVSEL.

 

LOL -- what a tangled web we weave...if OP has the IVSEL in the bootloader and does the naive jump to zero when done, then there is probably no default code [au contraire; see below] in the application aria [not an opera I guess] area prologue to clear IVSEL.

 

[edit]  Indeed when building code for Mega32 IVSEL clear is the first thing in the prologue:

                 
                 __RESET:
000041 94f8      	CLI
000042 27ee      	CLR  R30
000043 bbec      	OUT  EECR,R30
                 
                 ;INTERRUPT VECTORS ARE PLACED
                 ;AT THE START OF FLASH
000044 e0f1      	LDI  R31,1
000045 bff5      	OUT  MCUCR,R31
000046 bfe5      	OUT  MCUCR,R30
                 
                 ;CLEAR R2-R14
0000...

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

Last Edited: Thu. Feb 20, 2020 - 12:46 PM