AMcTools Forum 
  HomeHelpSearchLogin  
 
Pages: 1
Send Topic Print
Interrupt Handling Failure (Read 9650 times)
Milwaukee
YaBB Newbies
*
Offline

I Love Coding!

Posts: 22

Gender: male
Interrupt Handling Failure
01/06/11 at 17:31:42
 
Hi,
I found an interrupt handling failure caused by VMLAB.
Hope there is already a work around out!
I recognized during verifying of timer0 of ATmega168b of ThVortex that's unpossible to reset an interrupt in an ISR through reseting of the interrupt flag. Following you'll find the code which I used.

[code]
.def temp = r16
.def leds = r17

.org 0x0000
       rjmp    main              ; Reset Handler
.org      $20
       rjmp    timer0_CompA      ; Timer/Counter0 Compare Match A = 0x0020
.org      $22
       reti      ;TIM0ovf      ; Timer/Counter0 overflow

main:
       ; Initialize Stackpointer
       ldi     temp, HIGH(RAMEND)
       out     SPH, temp
       ldi     temp, LOW(RAMEND)
       out     SPL, temp
     
       ldi     temp, 0xFF            ; Output Port B
       out     DDRB, temp
       ldi     leds, 0x00

       ; Initialization
       ldi     temp, (WGM01<<1)      ; Modus: Clear Timer on Compare Match
       out     TCCR0A, temp
       ldi     temp, (1<<CS01)       ; Internal/8
       out     TCCR0B, temp
       ldi     temp, (1<<OCF0A)      ; Timer/Counter0 Compare Match A
       sts     TIMSK0, temp
       ldi     temp, 4               ; Compare Match Value
       out     OCR0A, temp
       sei

loop:
       rjmp    loop               ; Endless loop

timer0_CompA:                      ; Timer/Counter0 Compare ISR
       out     PORTB, leds
       inc     leds
;use timer0
       ldi     temp, 1               ; Compare Match Value
       out     OCR0A, temp
       nop
       nop
       nop
       nop
       nop
       nop
       nop
       nop
       nop
       sbi      TIFR0,OCF0A      
       ldi     temp, 16
       out    OCR0A, temp
       reti
[/code]

The sbi command resets the regarding flag for timer0 compare A.
After the reti the µC goes back into the next isr without reason. It seems that the reset of interrupt flag does not forward the information!
Back to top
 
 
  IP Logged
Milwaukee
YaBB Newbies
*
Offline

I Love Coding!

Posts: 22

Gender: male
Re: Interrupt Handling Failure
Reply #1 - 01/07/11 at 16:25:26
 
Hi,
I found another mismatch between VMLAB and an atmel core. : :(
If an interrupt occurs then an atmel core needs 4 cycles (assumed to have a 16 bit pc) to change the pc to an interrupt vector address. I used GET_MICRO_INFO(INFO_CPU_CYCLES) in a timer model to prove how VMLAB behaves.
Back to top
 
 
  IP Logged
ThVortex
Global Moderator
*****
Offline



Posts: 160
Austin, TX, USA
Gender: male
Re: Interrupt Handling Failure
Reply #2 - 01/08/11 at 06:34:18
 
Ok, I'll start investigating this over the weekend.
Back to top
 
 
WWW   IP Logged
Milwaukee
YaBB Newbies
*
Offline

I Love Coding!

Posts: 22

Gender: male
Re: Interrupt Handling Failure
Reply #3 - 01/08/11 at 22:27:00
 
Thank you in advance!
...
Here some more information to the 2nd case. That's what avr says about it.

[font=Arial][b]Interrupt Response Time[/b]
The interrupt execution response for all the enabled AVR interrupts is four clock cycles minimum.
After four clock cycles the program vector address for the actual interrupt handling routine is executed. During this four clock cycle period, the Program Counter is pushed onto the Stack.
The vector is normally a jump to the interrupt routine, and this jump takes three clock cycles. If an interrupt occurs during execution of a multi-cycle instruction, this instruction is completed before the interrupt is served. If an interrupt occurs when the MCU is in sleep mode, the interrupt execution response time is increased by four clock cycles. This increase comes in addition to the start-up time from the selected sleep mode.
A return from an interrupt handling routine takes four clock cycles. During these four clock cycles, the Program Counter (two bytes) is popped back from the Stack, the Stack Pointer is incremented by two, and the I-bit in SREG is set.
[/font]
Back to top
 
 
  IP Logged
moderator
YaBB Administrator
*****
Offline

I love forums, don't
you?

Posts: 308
AMcTools (Spain)
Gender: male
Re: Interrupt Handling Failure
Reply #4 - 01/09/11 at 12:33:06
 
Hmmmm....  I am not sure if the problem is in the AVR core coding or in the GET_MICRO_INFO(...) API function.

I remember, there was some troubles reported by "ThVortex", some time ago, with geting the nr. of cycles.  The cause was this: GET_MICRO_INFO(..) is an asyncronous function, and it can be called at any time, therefore it was not easy to distinguish when the function is called after or before incrementing the cycle counter variable.

I'll take a look, as soon as I can...
Back to top
 
 
WWW   IP Logged
ThVortex
Global Moderator
*****
Offline



Posts: 160
Austin, TX, USA
Gender: male
Re: Interrupt Handling Failure
Reply #5 - 01/10/11 at 07:16:38
 
Ok. I did some testing to confirm both problems. Here's my analysis:

1. The interrupt failed to reset just like you noticed. The flag bit appears to reset in the register, but the interrupt remains pending. Right now, these flag registers are being handled internally by VMLAB so I can't fix them myself. The moderator will have to look into it.

The only workaround I could do is to re-implement the timer flag and mask registers in my own components. However, I don't know if the SET_INTERRUPT_FLAG(..., FLAG_CLEAR) will work correctly for this special case.

2. I also confirmed that the interrupt timing is wrong. You don't have to use INFO_CPU_CYCLES to get the cycle counts. Just enable TIMER1 with a direct clock (Internal / 1) and then you can use TCNT1 as a cycle counter.

What I observed is that while a multi-cycle instruction like "rjmp" does correctly finish its cycle count when the interrupt fires, there is no additional 4 cycle delay added. The interrupt dispatch is handled completely within VMLAB, so the moderator will have to fix that. On the plus side, the RETI instruction does correctly take 4 cycles to execute.

3. There is another bug that your example exposes. The "sbi" instruction in newer AVRs (e.g. mega168) is a true bit-wise operation. In your code, it should have only reset the OCF0A flag. However, VMLAB is emulating the older behavior (e.g. mega16) where the "sbi" is a read-modify-write on the entire byte and therefore resets both OCF0A and OCF0B.

I've already talked with the moderator about this. Part of the problem is that the peripheral API will have to change to handle this. Right now, the same On_register_write() could indicate both a byte or bit write, and the peripheral component cannot distinguish the two.
Back to top
 
 
WWW   IP Logged
Milwaukee
YaBB Newbies
*
Offline

I Love Coding!

Posts: 22

Gender: male
Re: Interrupt Handling Failure
Reply #6 - 01/10/11 at 21:14:21
 
For the mean time I figured out some work arounds which will do the trick. :-)

The first one is simple. In order to compensate the 4 missing cycles, I added 4 nop commands at the very beginning in the isr. Well, they have to be removed all the time the application is going to be in a microcontroller.

The function SET_INTERRUPT_FLAG(...,FLAG_CLEAR) does work fine if the function is called in a peripheral. So, I added a shadow register (a reserved one) and set this one to be the interrupt register. After that I added the real register to the peripheral and just added the SET_INTERRUPT_FLAG(...,FLAG_CLEAR) lines for the different bits in the On_register_write() callback function.

Hope in future they should not be necessary due to fix of VMLAB.
Back to top
 
 
  IP Logged
vuokko
YaBB Newbies
*
Offline

I Love YaBB 2!

Posts: 2

Re: Interrupt Handling Failure
Reply #7 - 03/15/11 at 12:11:35
 
[quote author=7C5A4C5B606D181B1A290 link=1294335103/0#6 date=1294694061]
The function SET_INTERRUPT_FLAG(...,FLAG_CLEAR) does work fine if the function is called in a peripheral. So, I added a shadow register (a reserved one) and set this one to be the interrupt register. After that I added the real register to the peripheral and just added the SET_INTERRUPT_FLAG(...,FLAG_CLEAR) lines for the different bits in the On_register_write() callback function.

Hope in future they should not be necessary due to fix of VMLAB.[/quote]
I believe this can't be put into the project.c code?
I can also confirm that in C interrupts work weird.

From .prj:
[code].MICRO "ATmega88" "CKDIV8=1"
K0 PD2 VSS[/code]
And in project.c
[code]EICRA |= (1 <<0)|(1 << 1);
EIMSK |= (1 << 0);
PORTD |= (1 << 2);
sei();[/code]
And that should be rising edge which triggers the interrupt. Anyway it is triggered Always when PD2 is 0.

I'm so waiting for the patch...
Back to top
 
 
  IP Logged
ThVortex
Global Moderator
*****
Offline



Posts: 160
Austin, TX, USA
Gender: male
Re: Interrupt Handling Failure
Reply #8 - 03/15/11 at 17:09:24
 
The "ATmega88" model is implemented internally in VMLAB.EXE and I don't have access to that code. Sorry, but I can't provide you with any patch. Maybe the moderator can help you out?
Back to top
 
 
WWW   IP Logged
PeHe
YaBB Newbies
*
Offline

I Love VMLAB !

Posts: 1
München
Gender: male
Re: Interrupt Handling Failure
Reply #9 - 05/02/11 at 21:35:23
 
Hello,

this problem seems not being solved in 3.15.

Maybe you are interested in a small script I wrote some years ago as a workaround. The script parses the *.hex file, and changes the sequence

[code]cli
out  SP_H, r?
out  SREG, r?
out  SP_L, r?[/code]

to

[code]cli
out  SP_H, r?
out  SP_L, r?
out  SREG, r?[/code]

This adds a small delay, but now VMLAB restores the stackpointer [i]before[/i] it re-enables the interrupts.

Problem summary:  
Everything works fine with a real microcontroller, but in VMLAB an interrupt is executed immediately after enabling it (out SREG...). At this time the stackpointer is not fully restored, and therefore a wrong value for the program pointer is reloaded from the stack (or from elsewhere).

The script is attached to http://www.mikrocontroller.net/topic/85212
(look for the latest version at the end)

hopefully it helps,
Peter H.
Back to top
 
 
  IP Logged
Pages: 1
Send Topic Print