newbie-problem with external interrupts on AT90CAN128 (asm)

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

dear avr-veterans,

i'm totally new to avr and microcontrollers in general. after two weeks playing around with an AT90CAN128 connected to a custom-made board that i got from work, i tried to write a tiny program which is supposed to send an external interrupt as soon as a logical change on a pin connected to a fuse is detected, i.e. if i pull out the fuse. if interrupt is detected, a LED should lighten.
when i debug, atmel studio shows me that everything is workin fine, every bit is set as i think it should be and even an interrupt flag is passed when i provoke a logical change on the concerning pin.
the thing is - it won't jump to the interrupt
routine and i just can't figure out why!
with polling method everything is working fine, the pin reacts. it just seems to have a severe aversion against being interrupted :/

i'd be really glad if some people could suggest something!

thank you very much in advance!!!

  .include"can128def.inc"	;include file 
;--------------------------------------------------
; interrupt vector table 
; (only INT1 enabled, every other interrupt will return to reset-label and reenable all interrupts)
;
jmp reset ; Reset Handler 
reti ; IRQ0 Handler
jmp interrupt1routine ; IRQ1 Handler
reti ; IRQ2 Handler
reti ; IRQ3 Handler
reti ; IRQ4 Handler
reti ; IRQ5 Handler
reti ; IRQ6 Handler
reti; IRQ7 Handler
reti ; Reset Handler
reti; IRQ0 Handler
reti; IRQ1 Handler
reti; IRQ2 Handler
reti ; IRQ3 Handler
reti ; IRQ4 Handler
reti ; IRQ5 Handler
reti ; IRQ6 Handler
reti ; IRQ7 Handler
reti ; Timer2 Compare Handler
reti ; Timer2 Overflow Handler
reti ; Timer1 Capture Handler
reti; Timer1 CompareA Handler
reti; Timer1 CompareB Handler
reti; Timer1 CompareC Handler
reti; Timer1 Overflow Handler
reti; Timer0 Compare Handler
reti; Timer0 Overflow Handler
reti; CAN Handler
reti; CAN Timer Overflow Handler
reti ; SPI Transfer Complete Handler
reti; USART0 RX Complete Handler
reti; USART0,UDR Empty Handler
reti; USART0 TX Complete Handler
reti; Analog Comparator Handler
reti; ADC Conversion Complete Handler
reti; EEPROM Ready Handler
reti; Timer3 Capture Handler
reti; Timer3 CompareA Handler
reti; Timer3 CompareB Handler
reti; Timer3 CompareC Handler
reti; Timer3 Overflow Handler
reti; USART1 RX Complete Handler
reti; USART1,UDR Empty Handler
reti; USART1 TX Complete Handler
reti ; TWI Interrupt Handler
reti ; SPM Ready Handler

;----------------------------------------------------
reset:						;start here after reset
 ;
 ldi r16, LOW(RAMEND)   ;set up stack
 out SPL, r16		;		
 ldi r16, HIGH(RAMEND)	;	
 out SPH, r16		;		
 ;
 ldi r16, 0x00		; set PORT D to input   
 out DDRD, r16          ;(this is where INT1 is,
 out PIND, r16          ; connected to the fuse)
 ;
 ldi r16, 0xff		; set PORT A to output
 out DDRA, r16          ;(here are the LEDs)
 ldi r16, 0x00		; all lights of PORT A off
 out PORTA, r16		;
 ;
 ldi r16, (1<<ISC10)    ; mask the isc to react to  
 sts EICRA, r16	        ; logical changes
 ;
 ldi r16,(1<<INT1)      ; activate INT01
 out EIMSK, r16         ;
 ;
 sei                    ; enable interrupts in SREG
;--------------------------------------------------
interrupt1routine:
 in r16, SREG            ; save status register
 sbi PORTA, 1		 ; light LED at PA1
 out SREG, r16		 ; restore status register
 reti                    ; return and reeanable ints

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

My guess is that the long Interrupt vector table is your problem.
Maybe try with hardcoded IRQ address.I have not checked if "int1addr" is the right name for your model but I suspect so. Otherwise you need to study the .inc file for your model.

.cseg
	jmp	reset			;program start
			
.org	int1addr
	jmp	interrupt1routine	;Ext Int1 handler

.org	wdtaddr
	jmp	dog_time		;save RTC

.org	ovf2addr
	rjmp	rtc_time		;tick RTC

.org	ovf0addr
	rjmp	timeout_timer	;tick TIMEOUT TIMER

reset:

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

BTW, I hope you have some more code after your "sei" otherwise your program will run into your interrupt handler and eventually cause a reset. A forever loop would prevent that.

ldi r16,(1<<INT1)      ; activate INT01
 out EIMSK, r16         ;
 ;
 sei                    ; enable interrupts in SREG
forever:
    rjmp forever        ;loop forever
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Lennart, you're awesome! the bug really seemed to be the interrupt vector table O.o
could you tell me how THAT possibly could be the reason??
i've read severeal times that it is vitally important to paste the complete interrupt vector table to prevent unintended interrupts messing up the addressing! the message was never to use .org-directives for interrupts :/
(yeah, i had the polling loop turning on another LED after the sei, just didn't paste it cause it worked.)

thank you so much :D

greetings,
malvina

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

It's highly likely (haven't looked at data sheet)that each interrupt vector entry needs a "jmp

You have a mixed set of jmp's and reti's for your table, so it almost certainly doesn't align correctly.

A proper job would be to define a label for every interrupt, put a jmp

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

MartinM57 wrote:
A proper job would be to define a label for every interrupt, put a jmp
A proper job would be to define a label for every USED interrupt, NOT put a jmp

Warning: Grumpy Old Chuff. Reading this post may severely damage your mental health.

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

Depends what you and I mean by "proper job" doesn't it.

Taking the one-time effort at the start of the project to fill the vector table with a set of jmp's targetted at a label with a reti at each, IMHO, sets out a framework that reduces the chance of error and makes it easy to add interrupt code later - just put it between the appropriate label and the reti and you're done

But I don't expect you to agree, so we'll leave it at that...:)

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

Stuffing the unused vectors with RETI is just useless and ignorant in any flavor. Just think about where those vectors would RETI'ed to without clearing the interrupt flags, and what would happen one cycle after.

Warning: Grumpy Old Chuff. Reading this post may severely damage your mental health.

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

malvina,

As you can see there is more than one way to skin a cat.
Personally I'm with MBedders team.
Since you write your code, there is no reason why you would enable an interrupt that you have not intended.
And thus no reason to have any method or code for interrupts not in use.
C-compilers often have a method to catch unintended interrupts.
Those who use assembler never make any mistakes, so they don't need it...