Needed an advice [using the watchdog]

Go To Last Post
15 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

/* Atmega324p with Winavr */

Hi all,

I need a theoretical and probably logical help here
if you think this is silly question please be patient.
But i am actually stuck and don't know how to go about it!

I have been asking myself how i will be able to achieve the waiting delay of 10 secs and do something afterwards. this might sound trivial,
but the actual dilemma is that there is a WDT which is reseting in every 2 secs.

This is the application: If it rains, ADC will give me some update data and if they exceed the threshold, then I will need to turn ON some LEDs and then OFF them after 10 secs.

The Real problem here was that since the WDT reset will clears all the timers, even the heap and empty all the variables with probably 0xFF at the start up again (By the way I am using GCC compiler) upon the reset.
Therefore my approach is now completely obsolete. I have been thinking of using some increment value with a timer, let's say CTC mode and everytime I got a CTC i would increment the variable "i" until "i" 's value is equivalent to about 10 secs then i could do LED OFF

I think that since I want to wait the period longer than the WDT reset period,
all the variables will be dynamically refreshing which will fail to wait until 10 secs!

My only option left now was to disable the WDT during this time which involves waiting
and re-enable back again when it's done. But again this will de contradicting the use of WDT which is meant to recover the system in case of some lock up & infinite loops.

Unless i have to settle down and ask myself if i really need a WDT in my application
but is there any other alternative way I can do this?

Any advice or though is very much appreciated.

Cheers.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You either implement the delay with a Timer or by time-wasting e.g. _delay_ms()

Instead of doing a single 10 seconds, do 10 one-second intervals. Update WDT every one-second.

The CodeVision delay_ms() is a function that takes variable arguments. It kicks the Watchdog regularly.

The avr-gcc _delay_ms() is a macro that only takes constant arguments, and does NOT kick the dog.

Incidentally, you must have realised that you can write your own 'wiser' delay_ms()

void delay_MS(int ms)
{
    while (ms--) {
        _delay_us(1000);
        kick_watchdog();  // every ms (or whatever interval)
    }
}

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In future:

(a) please use a thread title that gives some idea what the thread is about

(b) consider which is the most appropriate forum for the post. Your original question does not appear to be asking anything specifically about the use of GCC

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Did i use the wrong forum again Cliff?
should this post have been in AVR Forum in steady?

@ David.

Hey, I am not sure what you are trying to mean by "kicking the watchdog"
So are you suggesting that i will need to stop the WDT (from reseting) by so called "kicking it" during this delay_ms () until i get to 10 secs?

Thank you.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry but why even enable the watchdog in the first place if you don't know how to use it?

When it is enabled the WDT starts to count down. When it reaches 0 it will reset the AVR. You stop it from doing this and make it start the count period over again by issuing the WDR opcode. The idea is that if the AVR goes for too long without WDR being executed (it is stuck in a loop) then the AVR will be reset to get it out of the "stuck" condition.

Of course a software delay such as _delay_ms() will look like a "stuck" AVR for this purpose. So what David was suggesting is that you break up a long wait period into a number of shorter ones and have the AVR execute the WDR opcode every now and again to prevent the CPU from resetting.

The AVR-LibC mechanism to execute the WDR opcode is wdt_reset() as shown on this page:

http://www.nongnu.org/avr-libc/u...

But I ask again - why mess with the watchdog if you didn't know what it's for or how to use it properly?

If WDT is being used to wake from sleep where does _delay_ms() come into it? While you are looping inside _delay_ms() the AVR is eating your batteries. The whole idea is that you enable the watchdog then sleep the CPU to reduce power consumption then after 2ms or 15ms or whatever the watchdog interrupt "fires" (because no WDRs while sleeping) and wakes the AVR from sleep. Is *this* what you meant to use the watchdog for?

I'm still fairly certain that apart from mentions about how GCC handles _delay_ms() and wdt_reset() etc. this thread is not specifically about GCC so I'll move this thread to AVR Forum.

I would also edit the thread title (which you can do too by editing the subject in the first post) if I actually understood what this thread was about - as yet I don't so I'll leave it to you to give it a sensible title.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you all,

Cliff, i was aware that Watchdog reset is used to recover MCU from trapping into Some system Lock ups, but i didn't know what might be the best approach,
so since it is all about stopping the WDT from resetting the avr during this
instances, why can't we go a head and even completely disable the WDT during these cases and then re-enable it back when we are done?
will this really make any difference with
keep stopping it from reseting until you reach that desired value?

#define wdt_disable ( ) ;  

// and some later time

#define wdt_enable ( ) ; 

?

Yes I have sleep mode "ADCNRM" But I wasn't using WDT reset for the purpose of waking up the MCU from sleep, (although it will still do it anyways)
but i usually had many PCINTs which will be handling this.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You are defeating the object of a Watchdog. Of course you can disable it if you want.

If it is set to two-seconds, you must call wdt_reset() at a more frequent interval.

Regarding sleep, many peripherals can do the waking up. You can always go straight back to sleep after a swift kick.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

haha.. I am not trying to defeat anything here David.
I think it's that it is something i haven't probably done before
so whatever thought i had in all this was just under my logic.
I am pretty sure i will get there sometimes.

I think i do understand what yours and Cliff's approach
was all about and i must surely thank you for your contribution.

Thanks.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Can you take a step back and explain the system design and where the watchdog fits into it?

Are you:

(a) using the watchdog as it's a handy "long period" timer and it allows the AVR to sleep for long periods between short bursts of activity, or

(b) using the watchdog as you are worried that somewhere in the code there may be a bug that takes the CPU into an infinite loop and you want to be able to recover from this.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It's surely the (b) option

In facts the mcu sleeps and is woken up by some Interrupts later
when some events occurs,
however since there also is a WDT reset enabled, It is repeatedly
waking the mcu up aswell. but going back to the actual need, It is provided for mcu's recovery in case of some infinite loops.
which is what i said earlier that in this instance
The WDT will be playing both roles.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Then if you deliberately enabled the watchdog to catch bugs in your code and that watchdog keeps resetting your AVR what does that tell you about the presence of bugs in your code? ;-)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It means the presence of bugs in my code will be even more....
hahaha... of course not.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
a WDT which is reseting in every 2 secs.

It is clocked from a very unstable RC. Prescaller is configurable so you can change it and extend it up to about 8s IIRC.
Quote:
WDT reset will clears all the timers, even the heap and empty all the variables with probably 0xFF at the start up again (By the way I am using GCC compiler) upon the reset.

No it will not. It only changes some IO registers and a PC. It is you who "empties all the variables" (with GCC start-up code).

No RSTDISBL, no fun!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you all for your contribution,

Can Somone please give me a clue about how to initialize
some variables in such ways that they won't be cleared
as the result of GCC start-up code which clears up all the RAM?
I saw some where the code and something looks like

#pragma data:noinit 
int noinitvar; 

But to be honest i don't know what it does at all :/
I will very much appreciated if someone can help me
understanding how this is achieved!
I think the whole point of bothering kicking or disabling WDT in
my case was the loosing of these variable values during the GCC start up.

Thanks all.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Read/search ".noinit" and I can recommend AVR-libc which briefly explains sections in AVR-GCC.
Also MCUSR register is a good idea to know about.

No RSTDISBL, no fun!