3
\$\begingroup\$

I was using ATmega32A before and now I am migrating to ATmega324PA just to enhance power management. Now I am testing the new controller in every aspect. This is a simple code to check the watchdog timer but it keeps resetting the controller.

Code:

int main(void)
{
  uart_init();
  PORTA|=(1<<PORTA1);
  _delay_ms(1500);
  PORTA&=~(1<<PORTA1);
  _delay_ms(2000);
  uart_array("FFFFFFFFFFFFFFFFFF");
  wdt_enable(WDTO_2S);
  _delay_ms(5000);
}

void uart_init()
{
 /*set PinA1 as output for LED*/
 DDRA|=(1<<1);

 /*set PinD3 as output for UART*/
 DDRD|=(1<<3);

 /*set pinD2 as input for UART*/
 DDRD&=~(1<<2);

 /*enabling TX and RX*/
 UCSR1B |=(1<<TXEN1) | (1<<RXEN1);

 /*asynchronous mode selection*/
 UCSR1C&=~(1<<UMSEL11);
 UCSR1C&=~(1<<UMSEL10);

 /*setting data format to 8 bit*/
 UCSR1B &=~(1<<UCSZ12);
 UCSR1C|=(1<<UCSZ11)|(1<<UCSZ10);

 /* setting one bit as stop bit*/
 UCSR1C &=~(1<<USBS1);

 /*Disabling parity*/
 UCSR1C &= ~((1<<UPM11) | (1<<UPM10));

 /* loading 8 LSB to UBRRL*/
 UBRR1L = UBRRL_VALUE;

 /* loading 4 MSB to UBRRH*/
 UBRR1H = UBRRH_VALUE;
}

The code works well for the first time, but after that, LED keeps blinking.

Note: watchdog (WDTON) fuse bit is disabled.

\$\endgroup\$

2 Answers 2

4
\$\begingroup\$

Yeah, that is because after the watchdog fires, you have to reset the corresponding flag before main starts again (there is a register where you can read out, what caused the reset) and to disable the watchdog from firing over and over.

This code will fix your problem:

    // This function is called upon a HARDWARE RESET:
void reset(void) __attribute__((naked)) __attribute__((section(".init3")));

/*! Clear SREG_I on hardware reset. */
void reset(void)
{
     cli();
    // Note that for newer devices (any AVR that has the option to also
    // generate WDT interrupts), the watchdog timer remains active even
    // after a system reset (except a power-on condition), using the fastest
    // prescaler value (approximately 15 ms). It is therefore required
    // to turn off the watchdog early during program startup.
    MCUSR = 0; // clear reset flags
    wdt_disable();
}

This .init3 thing is a special code section where you can put code that is run before main starts. Here is a link that describes that, but you shouldn't worry too much about it, the code above will work just fine when put into the main.c.

\$\endgroup\$
4
  • \$\begingroup\$ It did work without adding .init3 stuff.. Thanks alot \$\endgroup\$
    – gzix
    Commented Jul 1, 2014 at 6:32
  • \$\begingroup\$ what do you mean, without init stuff? Did you just put the code at the beginning of main? If so, thats a bit unsafe, since you do not know how long it will take to enter main (there are some other inits that do sth before main) so you better put it as far forward as possible. This ensures you don't get unexpected behaviour. \$\endgroup\$
    – jjstcool
    Commented Jul 1, 2014 at 6:50
  • \$\begingroup\$ After wdt_enable, i checked the watchdog interrupt value. It has been disabled only. So from where the continuous reset came from? \$\endgroup\$
    – gzix
    Commented Jul 1, 2014 at 7:00
  • 1
    \$\begingroup\$ what do you mean with wdt interrupt value? Anyway: The watchdog stays enabled after a wdt reset, but the time after which it will trigger is set to 15 ms! So you have to disable it very fast, otherwise it will trigger over and over again. So the way to go is to disable it before main and enable it as you want it to work in the main. \$\endgroup\$
    – jjstcool
    Commented Jul 1, 2014 at 7:14
1
\$\begingroup\$

Beyond previous reset() function advice you need disable watchdog in bootloader (if used of course). There is/was e.g. known bug of original Arduino bootloader which did not disable watchdog.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.