buserror / simavr

simavr is a lean, mean and hackable AVR simulator for linux & OSX
GNU General Public License v3.0
1.58k stars 368 forks source link

Timer keeps running after turning its power supply off #202

Open gergoerdi opened 7 years ago

gergoerdi commented 7 years ago

On a real ATMega328P, the following program strobes PORTB5 5 times, then stops:

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

int main ()
{
    DDRB |= _BV(DDB5);

    TCCR1B |= _BV(CS10);
    TCCR1B |= _BV(CS12);

    int count = 0;
    for (;;)
    {
        if (TCNT1 >= 4000)
        {
            PORTB ^= _BV(PB5);
            TCNT1 = 0;
            if (++count == 10)
                power_timer1_disable();
        }
    }
}

However, in SimAVR, I see that PORTB5 keeps changing even after the 5th on/off cycle. It seems that shutting off TIMER1's power is not simulated.

buserror commented 7 years ago

Interesting, I'll have a look at that. We already had a test case for the timer16 like that, so perhaps there is a regression there..?

hovercraft-github commented 7 years ago

This certainly related to PRR handling (power_timer1_disable() doing that). The avr_timer_t structure has a 'disabled' regbit, but its handling never been implemented yet, as far as I know. Or I miss something obvious?

buserror commented 7 years ago

I think we need to start by using a AVR_IRQ_FLAG_FLOAT... And also add accessors to get/set the flags...

The idea would be to do.. if () avr_irq_set_flag(irq, AVR_IRQ_FLAG_FLOAT); else avr_irq_raise(irq, value...);

And/Or add an accessor that does avr_irq_raise_float(avr, value, input ? true : false);

The receiving handler would have to do a getflag and/or use a new avr_irq_floating(irq) to know if the value passed is valid, or not.

So the IRQ propagation code would be converted to avr_irq_raise_float to propagate the flag down the chain, wether it's true or false...

Doesn't look terribly complicated to do. See any problem with that?

hovercraft-github commented 7 years ago

Your post just accidentally get into issue #202 (Timer keeps running after turning its power supply off)02.03.2017, 00:49, "Michel Pollet" notifications@github.com:I think we need to start by using a AVR_IRQ_FLAG_FLOAT... And also add accessors to get/set the flags... The idea would be to do.. if () avr_irq_set_flag(irq, AVR_IRQ_FLAG_FLOAT); else avr_irq_raise(irq, value...); And/Or add an accessor that does avr_irq_raise_float(avr, value, input ? true : false); The receiving handler would have to do a getflag and/or use a new avr_irq_floating(irq) to know if the value passed is valid, or not. So the IRQ propagation code would be converted to avr_irq_raise_float to propagate the flag down the chain, wether it's true or false... Doesn't look terribly complicated to do. See any problem with that?

—You are receiving this because you commented.Reply to this email directly, view it on GitHub, or mute the thread.

gergoerdi commented 7 years ago

@hovercraft-github: and now your comment is also on the wrong ticket :D

buserror commented 7 years ago

Yeah well, it was probably my fault, I had loads of tabs open, must have typed it all in the wrong one! :-)

buserror commented 7 years ago

I had a look and yes, the PRR register bit isn't handled at all, my assumption was that the PRR is good to save power, but is not an 'on off switch'. Seems the avr-libc has decided otherwise :-)

So let's keep this issue open, we might have to make a special driver for the PRR register and dispatch IOctl's around for corresponding bits, instead of implementing the on/off for each of the drivers that might be affected.