wdt_enable may fail to enable the watchdog on ATmega1281

View: New views
5 Messages — Rating Filter:   Alert me  

wdt_enable may fail to enable the watchdog on ATmega1281

by Danjel McGougan-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi,

It seems the wdt_enable macro from "avr/wdt.h" may fail to enable the
watchdog at least on ATmega1281 devices and possibly on all devices
that keep the WDTCSR register in the extended I/O space. The macro
looks like this in my version:

#define wdt_enable(value)   \
    __asm__ __volatile__ (  \
        "in __tmp_reg__,__SREG__" "\n\t"    \
        "cli" "\n\t"    \
        "wdr" "\n\t"    \
        "sts %0,%1" "\n\t"  \
        "out __SREG__,__tmp_reg__" "\n\t"   \
        "sts %0,%2" \
        : /* no outputs */  \
        : "M" (_SFR_MEM_ADDR(_WD_CONTROL_REG)), \
        "r" (_BV(_WD_CHANGE_BIT) | _BV(WDE)), \
        "r" ((uint8_t) ((value & 0x08 ? _WD_PS3_MASK : 0x00) | \
            _BV(WDE) | (value & 0x07)) ) \
        : "r0"  \
    )

This macro seems to depend on the fact that at least one more
instruction will be executed after global interrupts are enabled
before an actual interrupt can happen. But this fact seems only to be
true for instructions using only one instruction word (16 bits).
Instructions such as sts that use two words (32 bits) are not
guaranteed to be executed before an interrupt may fire. I have learned
this the hard way after trying to optimize interrupt latency in my
application for ATmega1281. It does not seem to be documented by
Atmel.

Could possibly other macros/functions in avr-libc be affected by this?

Best regards,
Danjel McGougan


_______________________________________________
AVR-libc-dev mailing list
AVR-libc-dev@...
http://lists.nongnu.org/mailman/listinfo/avr-libc-dev

RE: wdt_enable may fail to enable the watchdog onATmega1281

by Weddington, Eric :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

 

> -----Original Message-----
> From:
> avr-libc-dev-bounces+eric.weddington=atmel.com@...
> [mailto:avr-libc-dev-bounces+eric.weddington=atmel.com@nongnu.
> org] On Behalf Of Danjel McGougan
> Sent: Friday, August 28, 2009 3:03 AM
> To: avr-libc-dev@...
> Subject: [avr-libc-dev] wdt_enable may fail to enable the
> watchdog onATmega1281
>
> This macro seems to depend on the fact that at least one more
> instruction will be executed after global interrupts are enabled
> before an actual interrupt can happen. But this fact seems only to be
> true for instructions using only one instruction word (16 bits).
> Instructions such as sts that use two words (32 bits) are not
> guaranteed to be executed before an interrupt may fire. I have learned
> this the hard way after trying to optimize interrupt latency in my
> application for ATmega1281. It does not seem to be documented by
> Atmel.

Have you tested this on the ATmega1281? Have you tested this on any other ATmega device?


_______________________________________________
AVR-libc-dev mailing list
AVR-libc-dev@...
http://lists.nongnu.org/mailman/listinfo/avr-libc-dev

Re: wdt_enable may fail to enable the watchdog onATmega1281

by Joerg Wunsch :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

As Weddington, Eric wrote:

> > Instructions such as sts that use two words (32 bits) are not
> > guaranteed to be executed before an interrupt may fire.

> Have you tested this on the ATmega1281?

This behaviour would surprise me a bit, given that the datasheet
chapter about interrupt latency explicitly mentions the increased
latency when the interrupt arrives while a multiword instruction is
currently being executed.

I'd be interested in setting up a test setup that experimentally
verifies this behaviour, as the assumption the next instruction will
still be executed without being interrupted is quite crucial to the
toolchain.

--
cheers, J"org               .-.-.   --... ...--   -.. .  DL8DTL

http://www.sax.de/~joerg/                        NIC: JW11-RIPE
Never trust an operating system you don't have sources for. ;-)


_______________________________________________
AVR-libc-dev mailing list
AVR-libc-dev@...
http://lists.nongnu.org/mailman/listinfo/avr-libc-dev

RE: wdt_enable may fail to enable the watchdogonATmega1281

by Weddington, Eric :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

 

> -----Original Message-----
> From:
> avr-libc-dev-bounces+eric.weddington=atmel.com@...
> [mailto:avr-libc-dev-bounces+eric.weddington=atmel.com@nongnu.
> org] On Behalf Of Joerg Wunsch
> Sent: Monday, August 31, 2009 12:13 PM
> To: avr-libc-dev@...
> Subject: Re: [avr-libc-dev] wdt_enable may fail to enable the
> watchdogonATmega1281
>
> As Weddington, Eric wrote:
>
> > > Instructions such as sts that use two words (32 bits) are not
> > > guaranteed to be executed before an interrupt may fire.
>
> > Have you tested this on the ATmega1281?
>
> This behaviour would surprise me a bit, given that the datasheet
> chapter about interrupt latency explicitly mentions the increased
> latency when the interrupt arrives while a multiword instruction is
> currently being executed.
>
> I'd be interested in setting up a test setup that experimentally
> verifies this behaviour, as the assumption the next instruction will
> still be executed without being interrupted is quite crucial to the
> toolchain.

Exactly. I'm interested to hear what the OP has to say about this.


_______________________________________________
AVR-libc-dev mailing list
AVR-libc-dev@...
http://lists.nongnu.org/mailman/listinfo/avr-libc-dev

Re: wdt_enable may fail to enable the watchdog onATmega1281

by Danjel McGougan-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Weddington, Eric wrote:

>> This macro seems to depend on the fact that at least one more
>> instruction will be executed after global interrupts are enabled
>> before an actual interrupt can happen. But this fact seems only to be
>> true for instructions using only one instruction word (16 bits).
>> Instructions such as sts that use two words (32 bits) are not
>> guaranteed to be executed before an interrupt may fire. I have learned
>> this the hard way after trying to optimize interrupt latency in my
>> application for ATmega1281. It does not seem to be documented by
>> Atmel.
>
> Have you tested this on the ATmega1281? Have you tested this on any other ATmega device?

Hi,

I tried to reproduce this using simpler code since posting and I can not trigger it again. It seems the construct that confused me was this little piece in my application:

This is the start of the USART0_RX_vect interrupt routine:

        push    r29 ; save r29
        in      r29, _SFR_IO_ADDR(SREG)
        push    r29 ; save SREG
        lds     r29, _SFR_MEM_ADDR(UCSR0B)
        andi    r29, ~_BV(RXCIE0)
        sts     _SFR_MEM_ADDR(UCSR0B), r29 ; clear RXCIE0 in UCSR0B
        sei

Here I disable the RXC-interrupt and then enable global interrupts to allow nested interrupts in my application. If I move sei one instruction up (to reduce interrupt latency) the code does not work anymore:

        push    r29 ; save r29
        in      r29, _SFR_IO_ADDR(SREG)
        push    r29 ; save SREG
        lds     r29, _SFR_MEM_ADDR(UCSR0B)
        andi    r29, ~_BV(RXCIE0)
        sei
        sts     _SFR_MEM_ADDR(UCSR0B), r29 ; clear RXCIE0 in UCSR0B
---> RXC interrupt fires here

It seems the CPU schedules an RXC interrupt when sei is executed and it doesn't matter that we then clear the RXCIE0 bit in the next instruction (which should always be executed). The RXC interrupt fires before the next instruction anyway.

So to conclude I don't think there is a problem in avr-libc. I was too quick to post.

BR,
Danjel McGougan



_______________________________________________
AVR-libc-dev mailing list
AVR-libc-dev@...
http://lists.nongnu.org/mailman/listinfo/avr-libc-dev