EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

Strange problem encountered with AVR and interrupts - 1 attachment

Started by Michael July 10, 2004
Hi - I was attempting to get the two external interrupts working on an 
AVR. I have attached the code I wrote. My problem is that it seems it is 
only detecting when INT0 is pressed - but I'm not sure about this. The 
way I wrote it I never use the RETI statement - and I don't know if 
other interrupts can be called when a interrupt handler is running. 

But also - another problem - so to try to reset the AVR - I just would 
unplug the power - then plug power back in. But for some odd reason this 
didn't work! This has worked just fine for me before - but for some 
reason after doing this - I would have to write a different piece of 
code to the AVR - then rewrite the program I was working on - for it to 
work again. If I simply rewrote the program I was working on to the AVR 
without first writing in a different program, the LEDs would just remain 
off, and it wouldn't work at all. I simply can't figure out what is 
going on here.

Oh - if it matters - my setup right now is that I have an AT90S8515. I 
am programming it with an Atmel AVR ISP. On Port B I have 8 LEDs 
connected to vcc. On port C I have 8 normally closed buttons connected 
to ground. On port D I have two normally open buttons connected to 
ground and to INT0 and INT1.

Also - to use the external interrupts - I set them as inputs with pull 
up resistors. Now I'm starting to think that might not be necessary - is 
it?

Lastly - is it necessary to include both the .device and the .include 
statements? I feel like I've seen code with just one of them.

Thanks!

-Michael






In case the attachment doesn't work properly - I'll include the code 
below as well:



.device	AT90S8515
.include "8515def.inc"

.ORG $000

	RJMP RESET
	RJMP INTER0            ;int0
	RJMP INPUTLOOP         ;int1

.ORG $00D

RESET:
	LDI R24, low(RAMEND)   ;stack
	OUT SPL, R24
	LDI R24, high(RAMEND)
	OUT SPH, R24
	CLR R24               ;enable interrupts
	OUT MCUCR, R24
	LDI R24, 0xC0
	OUT GIMSK, R24
	SEI
	CLR R24              ;set inputs and outputs and pull up resistors
	OUT DDRC, R24
	OUT DDRD, R24
	SER R24
	OUT PORTC, R24
	OUT PORTD, R24
	OUT DDRB, R24

INPUTLOOP:
	IN R24, PINC         ;write pinc to portb
	OUT PORTB, R24
	RJMP INPUTLOOP

INTER0:
	LDI R24, 0xAA        ;write 10101010 to portb
	OUT PORTB, R24
	RJMP INTER0

begin 644 LEDBUTTONS.ASM
M+F1E=FEC90E!5#DP4S@U,34*+FEN8VQU9&4@(C@U,35D968N:6YC(@H*+D]2
M1R`D,#`P"@H)4DI-4"!215-%5`T*"5)*35`@24Y415(P#0H)4DI-4"!)3E!5
M5$Q/3U`*#0HN3U)'("0P,$0*"E)%4T54.@T*"4Q$22!2,C0L(&QO=RA204U%
M3D0I#0H)3U54(%-03"P@4C(T#0H)3$1)(%(R-"P@:&EG:"A204U%3D0I#0H)
M3U54(%-02"P@4C(T#0H)0TQ2(%(R-`T*"4]55"!-0U5#4BP@4C(T#0H)3$1)
M(%(R-"P@,'A#,`T*"4]55"!'24U32RP@4C(T#0H)4T5)"@E#3%(@4C(T#0H)
M3U54($1$4D,L(%(R-`T*"4]55"!$1%)$+"!2,C0*"5-%4B!2,C0-"@E/550@
M4$]25$,L(%(R-`T*"4]55"!03U)41"P@4C(T"@E/550@1$120BP@4C(T#0H*
M24Y0551,3T]0.@H)24X@4C(T+"!024Y#"@E/550@4$]25$(L(%(R-`H)4DI-
M4"!)3E!55$Q/3U`-"@T*24Y415(P.@T*"4Q$22!2,C0L(#!X04$-"@E/550@
84$]25$(L(%(R-`T*"5)*35`@24Y415(P
`
end

Interrupts are automatically disabled on entry to INTER0 Interrupt Service
Routine.
Since you are not enabling interrupts in the INTER0 loop, no further
interrupts will be serviced.
If you used the RETI instruction,  flags (including interrupt status) and PC
would be restored.
A suggested approach would be to have a main loop that executes with
interrupts enabled, with Interrupt Service Routines returning to this loop
via RETI instructions.

Tanya


"Michael" <nleahcimathotmaildotcom@nowhere.com> wrote in message
news:Xns9522B6FABC699nleahcim@204.127.199.17...
> Hi - I was attempting to get the two external interrupts working on an > AVR. I have attached the code I wrote. My problem is that it seems it is > only detecting when INT0 is pressed - but I'm not sure about this. The > way I wrote it I never use the RETI statement - and I don't know if > other interrupts can be called when a interrupt handler is running. > > But also - another problem - so to try to reset the AVR - I just would > unplug the power - then plug power back in. But for some odd reason this > didn't work! This has worked just fine for me before - but for some > reason after doing this - I would have to write a different piece of > code to the AVR - then rewrite the program I was working on - for it to > work again. If I simply rewrote the program I was working on to the AVR > without first writing in a different program, the LEDs would just remain > off, and it wouldn't work at all. I simply can't figure out what is > going on here. > > Oh - if it matters - my setup right now is that I have an AT90S8515. I > am programming it with an Atmel AVR ISP. On Port B I have 8 LEDs > connected to vcc. On port C I have 8 normally closed buttons connected > to ground. On port D I have two normally open buttons connected to > ground and to INT0 and INT1. > > Also - to use the external interrupts - I set them as inputs with pull > up resistors. Now I'm starting to think that might not be necessary - is
> it? > > Lastly - is it necessary to include both the .device and the .include > statements? I feel like I've seen code with just one of them. > > Thanks! > > -Michael > > > > > > > In case the attachment doesn't work properly - I'll include the code > below as well: > > > > .device AT90S8515 > .include "8515def.inc" > > .ORG $000 > > RJMP RESET > RJMP INTER0 ;int0 > RJMP INPUTLOOP ;int1 > > .ORG $00D > > RESET: > LDI R24, low(RAMEND) ;stack > OUT SPL, R24 > LDI R24, high(RAMEND) > OUT SPH, R24 > CLR R24 ;enable interrupts > OUT MCUCR, R24 > LDI R24, 0xC0 > OUT GIMSK, R24 > SEI > CLR R24 ;set inputs and outputs and pull up resistors > OUT DDRC, R24 > OUT DDRD, R24 > SER R24 > OUT PORTC, R24 > OUT PORTD, R24 > OUT DDRB, R24 > > INPUTLOOP: > IN R24, PINC ;write pinc to portb > OUT PORTB, R24 > RJMP INPUTLOOP > > INTER0: > LDI R24, 0xAA ;write 10101010 to portb > OUT PORTB, R24 > RJMP INTER0 > >
"tanya" <tanya.anne@bigpond.com> wrote in
news:ccsoog$pks$1@newshost.mot.com: 

> Interrupts are automatically disabled on entry to INTER0 Interrupt > Service Routine. > Since you are not enabling interrupts in the INTER0 loop, no further > interrupts will be serviced. > If you used the RETI instruction, flags (including interrupt status) > and PC would be restored. > A suggested approach would be to have a main loop that executes with > interrupts enabled, with Interrupt Service Routines returning to this > loop via RETI instructions. > > Tanya
Instead of using RETI - could I simply set the global interrupt flag by executting SEI? Or is there more to it than that? Thanks, Michael
In article <Xns95247EC688106nleahcim@204.127.199.17>, 
nleahcimathotmaildotcom@nowhere.com says...
> "tanya" <tanya.anne@bigpond.com> wrote in > news:ccsoog$pks$1@newshost.mot.com: > > > Interrupts are automatically disabled on entry to INTER0 Interrupt > > Service Routine. > > Since you are not enabling interrupts in the INTER0 loop, no further > > interrupts will be serviced. > > If you used the RETI instruction, flags (including interrupt status) > > and PC would be restored. > > A suggested approach would be to have a main loop that executes with > > interrupts enabled, with Interrupt Service Routines returning to this > > loop via RETI instructions. > > > > Tanya > > Instead of using RETI - could I simply set the global interrupt flag by > executting SEI? Or is there more to it than that? Thanks, > > Michael
You need to restore the entire processor status not just the interrupt enable bit(s) to what it was before the interrupt occurred. That's why there is a separate unique instruction for returning from an interrupt as opposed to returning from a subroutine. If you don't use it then generally "Bad Things Happen". Robert
R Adsett <radsett@junk.aeolusdevelopment.cm> wrote in
news:95CIc.160914$rCA1.108583@news01.bloor.is.net.cable.rogers.com: 

> In article <Xns95247EC688106nleahcim@204.127.199.17>, > nleahcimathotmaildotcom@nowhere.com says... >> "tanya" <tanya.anne@bigpond.com> wrote in >> news:ccsoog$pks$1@newshost.mot.com: >> >> > Interrupts are automatically disabled on entry to INTER0 Interrupt >> > Service Routine. >> > Since you are not enabling interrupts in the INTER0 loop, no >> > further interrupts will be serviced. >> > If you used the RETI instruction, flags (including interrupt >> > status) and PC would be restored. >> > A suggested approach would be to have a main loop that executes >> > with interrupts enabled, with Interrupt Service Routines returning >> > to this loop via RETI instructions. >> > >> > Tanya >> >> Instead of using RETI - could I simply set the global interrupt flag >> by executting SEI? Or is there more to it than that? Thanks, >> >> Michael > > You need to restore the entire processor status not just the interrupt > enable bit(s) to what it was before the interrupt occurred. That's > why there is a separate unique instruction for returning from an > interrupt as opposed to returning from a subroutine. If you don't use > it then generally "Bad Things Happen". > > Robert >
LOL that's what I expected - but I thought I should check to be sure :) But does anyone have any idea about what was going on with not being able to reset it? I tested it out today after the AVR had been unpowered for about 12 hours - and it did the same exact thing. I just don't understand. Perhaps does it remember all the states of the registers when it turns on or something? Thanks, Michael
Michael wrote:

> But does anyone have any idea about what was going on with not being able > to reset it? I tested it out today after the AVR had been unpowered for > about 12 hours - and it did the same exact thing. I just don't understand. > Perhaps does it remember all the states of the registers when it turns on > or something?
Here's just a guess. You may have a sneak path for power back to your board. Unplug *all* cables, wait a minute, and see if it's reset.
On Mon, 12 Jul 2004 20:00:05 GMT, R Adsett
<radsett@junk.aeolusdevelopment.cm> wrote:

>In article <Xns95247EC688106nleahcim@204.127.199.17>, >nleahcimathotmaildotcom@nowhere.com says...
[...]
>> Instead of using RETI - could I simply set the global interrupt flag by >> executting SEI? Or is there more to it than that? Thanks,
[...]
>You need to restore the entire processor status not just the interrupt >enable bit(s) to what it was before the interrupt occurred. That's why >there is a separate unique instruction for returning from an interrupt as >opposed to returning from a subroutine. If you don't use it then >generally "Bad Things Happen".
Well, the subject _is_ the AVR. From Atmel's instruction set manual: RETI - Return from Interrupt [...] Returns from interrupt. The return address is loaded from the STACK and the global interrupt flag is set. Note that the status register is not automatically stored when entering the interrupt routine. This must be handled by the application program. The stack pointer uses a pre-increment scheme during the RETI. [...] Operation: PC(15:0) <- STACK Devices with 16 bits PC[...] [...] Status Register (SREG) and Boolean Formula [...I bit set, other bits unaffected...] That's it. No more. The processor status is not saved on entry into the ISR, and RETI does not "restore" any such state, other than setting the I bit in SREG. So SEI should take care of you. You should clear the stack every now and again to ensure it doesn't overflow, but I'm not sure that would affect your example code anyway... Regards, -=Dave -- Change is inevitable, progress is not.
> > But does anyone have any idea about what was going on with not being able > > to reset it? I tested it out today after the AVR had been unpowered for > > Here's just a guess. You may have a sneak path > for power back to your board. Unplug *all* cables, > wait a minute, and see if it's reset.
This is a known issue with the STK500. If you have it plugged into a PC that provides a ground return, the power switch is inoperative - both positions are "on".
In article <40f2fcc6.14228970@News.individual.net>, iddw@hotmail.com 
says...
> On Mon, 12 Jul 2004 20:00:05 GMT, R Adsett > <radsett@junk.aeolusdevelopment.cm> wrote: > > >In article <Xns95247EC688106nleahcim@204.127.199.17>, > >nleahcimathotmaildotcom@nowhere.com says... > [...] > >> Instead of using RETI - could I simply set the global interrupt flag by > >> executting SEI? Or is there more to it than that? Thanks, > [...] > >You need to restore the entire processor status not just the interrupt > >enable bit(s) to what it was before the interrupt occurred. That's why > >there is a separate unique instruction for returning from an interrupt as > >opposed to returning from a subroutine. If you don't use it then > >generally "Bad Things Happen". > > Well, the subject _is_ the AVR. From Atmel's instruction set manual: > > RETI - Return from Interrupt > [...] > Returns from interrupt. The return address is loaded from the > STACK and the global interrupt flag is set. > Note that the status register is not automatically stored when > entering the interrupt routine. This must be handled by the > application program. The stack pointer uses a pre-increment
<snip>
> That's it. No more. The processor status is not saved on entry into > the ISR, and RETI does not "restore" any such state, other than > setting the I bit in SREG.
Figures, it would be one of the architectures that don't fit in the 'generally'. I'd still want to use the reti for symmetry, documentation and parsimony but it appears the evil of avoiding it doesn't run very deep. Robert
larwe@larwe.com (Lewin A.R.W. Edwards) wrote in
news:608b6569.0407121839.23bc5397@posting.google.com: 

>> > But does anyone have any idea about what was going on with not >> > being able to reset it? I tested it out today after the AVR had >> > been unpowered for >> >> Here's just a guess. You may have a sneak path >> for power back to your board. Unplug *all* cables, >> wait a minute, and see if it's reset. > > This is a known issue with the STK500. If you have it plugged into a > PC that provides a ground return, the power switch is inoperative - > both positions are "on".
I don't have an STK500 - I'm just using a simple 5V power supply and a AVR ISP. I guess maybe it was getting power through the avr isp? It was still connected to the computer... -Michael

The 2024 Embedded Online Conference