avr-libc-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[avr-libc-dev] [bug #44140] wdt_disable() macro clobbers prescaller bits


From: Pitchumani
Subject: [avr-libc-dev] [bug #44140] wdt_disable() macro clobbers prescaller bits and can cause unexpected resets
Date: Thu, 05 Mar 2015 11:35:38 +0000
User-agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.115 Safari/537.36 OPR/27.0.1689.76

Update of bug #44140 (project avr-libc):

                  Status:                    None => In Progress            
             Assigned to:                    None => pitchumani             

    _______________________________________________________

Follow-up Comment #1:

Hi Josh,

Below is the modified wdt_disable function. I have included wdr instruction
before modifying watch dog. Also avoided overwriting prescaler bits.


static __inline__
__attribute__ ((__always_inline__))
void wdt_disable (void)
{
    if (_SFR_IO_REG_P (_WD_CONTROL_REG))
    {
        uint8_t register temp_reg;
        __asm__ __volatile__ (
                "in __tmp_reg__,__SREG__"    "\n\t"
                "cli"                        "\n\t"
                "wdr"                        "\n\t"
                "in  %[TEMPREG],%[WDTREG]"   "\n\t"
                "ori %[TEMPREG],%[WDCE_WDE]" "\n\t"
                "out %[WDTREG],%[TEMPREG]"   "\n\t"
                "out %[WDTREG],__zero_reg__" "\n\t"
                "out __SREG__,__tmp_reg__"   "\n\t"
                : [TEMPREG] "=r" (temp_reg)
                : [WDTREG]  "I"  (_SFR_IO_ADDR(_WD_CONTROL_REG)),
                [WDCE_WDE]  "I"  ((uint8_t)(_BV(_WD_CHANGE_BIT) | _BV(WDE)))
                : "r0"
        );
    }
    else
    {
        uint8_t register temp_reg;
        __asm__ __volatile__ (
                "in __tmp_reg__,__SREG__"    "\n\t"
                "cli"                        "\n\t"
                "wdr"                        "\n\t"
                "lds %[TEMPREG],%[WDTREG]"   "\n\t"
                "ori %[TEMPREG],%[WDCE_WDE]" "\n\t"
                "sts %[WDTREG],%[TEMPREG]"   "\n\t"
                "sts %[WDTREG],__zero_reg__" "\n\t"
                "out __SREG__,__tmp_reg__"   "\n\t"
                : [TEMPREG] "=r" (temp_reg)
                : [WDTREG]  "M"  (_SFR_MEM_ADDR(_WD_CONTROL_REG)),
                [WDCE_WDE]  "I"  ((uint8_t)(_BV(_WD_CHANGE_BIT) | _BV(WDE)))
                : "r0"
        );
    }
}


Generated assembly for tiny84a it should be like:

    in __tmp_reg__,__SREG__
    cli
    wdr                  ; watchdog reset
    in  r24,33           ; load wdt register value
    ori r24,24           ; OR (WDCE | WDE)
    out 33,r24           ; write back to wdt register
    out 33,__zero_reg__  ; trun-off wdt
    out __SREG__,__tmp_reg__


Is this change ok?

Manually verified the generated assembly for all devices that has wdt.

    _______________________________________________________

Reply to this item at:

  <http://savannah.nongnu.org/bugs/?44140>

_______________________________________________
  Message sent via/by Savannah
  http://savannah.nongnu.org/




reply via email to

[Prev in Thread] Current Thread [Next in Thread]