Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 13 of 13

Thread: Watch Dog timer issue

  1. #1
    Junior Member
    Join Date
    Oct 2016
    Posts
    18

    Watch Dog timer issue

    I must be missing something, but a simple WD timer routine that will work on an Arduino fails to cooperate on the Teensy 3.2. Secret sauce please.

    Test code is below. Just a quick and slow flashing LED pattern to show me it has reset.
    //========================
    #include <avr/wdt.h>

    #define LED 16
    bool flipflop=false;

    void setup() {
    pinMode(LED, OUTPUT);
    digitalWrite(LED, HIGH);

    wdt_disable(); // Should kill the timer if it was on before reset.

    for(int i=0; i<20; i++){
    digitalWrite(LED, LOW); // Pulse a pattern of quick flashes
    delay(200);
    digitalWrite(LED, HIGH);
    delay(200);
    }

    wdt_enable(WDTO_4S); // Enable for a 4 sec timeout.
    delay(1);
    wdt_reset(); // Reset just in case.
    }

    void loop() {

    if(flipflop) digitalWrite(LED, HIGH); // Flash slowly here until we reset.
    else digitalWrite(LED, LOW);
    flipflop=!flipflop;
    delay(1000);
    }

  2. #2
    Senior Member
    Join Date
    Apr 2014
    Location
    -
    Posts
    9,735
    Looks like the WDT "lib" is a fake:

    Code:
    #define wdt_reset()
    #define wdt_enable(timeout)
    #define wdt_disable()
    No Idea why... an errormessage would be better instead of saying "yes, it exists!..and hurray, no error"

    I hope this helps? https://bigdanzblog.wordpress.com/20...y-3-1-and-3-2/

  3. #3
    Senior Member BriComp's Avatar
    Join Date
    Apr 2014
    Location
    Cheltenham, UK
    Posts
    1,138
    There was some discussion about watchdogs earlier today and some code was presented. See https://forum.pjrc.com/threads/69330...p-a-teensy-3-2
    I put that code together into some functions:-
    Code:
    /*Setup and use Watchdog in Teensy 3.2*/
    
    //See: https://forum.pjrc.com/threads/69330-Odd-request-How-can-i-lock-up-a-teensy-3-2
    
    /*Put in setup*/
    
    void SetWatchdog(uint32_t duration) {  // duration in 1/7.2MHz units...1 second = 7,200,000
    	// Setup WDT
    	int16_t hiWord;
    	int16_t loWord;
    
    	hiWord = duration >> 16;
    	loWord = duration & 0xFFFF;
    
    	noInterrupts();                                         // don't allow interrupts while setting up WDOG
    	WDOG_UNLOCK = WDOG_UNLOCK_SEQ1;                         // unlock access to WDOG registers
    	WDOG_UNLOCK = WDOG_UNLOCK_SEQ2;
    	delayMicroseconds(1);                                   // Need to wait a bit..
    
    	// for this demo, we will use 1 second WDT timeout (e.g. you must reset it in < 1 sec or a boot occurs)
    	//7.2mhz will require WDT reset < 1 second
    	//WDOG_TOVALH = 0x006d;
    	//WDOG_TOVALL = 0xdd00;
    
    	// Kris I want make timer to reboot over 1 second, maybe this is the correct way to do this
    //	WDOG_TOVALH = 0x0098;
    //	WDOG_TOVALL = 0x9680;
    	WDOG_TOVALH = hiWord;
    	WDOG_TOVALL = loWord;
    
    	// This sets prescale clock so that the watchdog timer ticks at 7.2MHz
    	// Kris, no clue what this is but leaving it alone
    	WDOG_PRESC = 0x400;
    
    	// Set options to enable WDT. You must always do this as a SINGLE write to WDOG_CTRLH
    	WDOG_STCTRLH |= WDOG_STCTRLH_ALLOWUPDATE |
    		WDOG_STCTRLH_WDOGEN | WDOG_STCTRLH_WAITEN |
    		WDOG_STCTRLH_STOPEN | WDOG_STCTRLH_CLKSRC;
    	interrupts();
    }
    /*Put in loop*/
    void ResetWatchdog() {
    	noInterrupts();                                     //   No - reset WDT
    // kris not sure what this does but it actually works just fine
    	WDOG_REFRESH = 0xA602;
    	WDOG_REFRESH = 0xB480;
    	interrupts();
    }
    
    void setup() {
    	SetWatchdog(7200000);
    }
    void loop() {
    	ResetWatchdog();
    }

  4. #4
    Senior Member
    Join Date
    Apr 2014
    Location
    -
    Posts
    9,735
    Quote Originally Posted by Frank B View Post

    Code:
    #define wdt_reset()
    #define wdt_enable(timeout)
    #define wdt_disable()
    Note, better would be
    Code:
    #define wdt_enable(timeout) do{}while(0)
    etc... which at least does not lead to syntax errors (but still does nothing)

  5. #5
    Junior Member
    Join Date
    Oct 2016
    Posts
    18
    Well, hell, you are right. the file is just a stub in the Teensy3 fork of the AVR library. So there must be some issues with the Teensy 3 pin assignments or some such. I'll have to resort to the "no macro" approach. thanks.

  6. #6
    Senior Member
    Join Date
    Apr 2014
    Location
    -
    Posts
    9,735
    Quote Originally Posted by kenhorner View Post
    So there must be some issues with the Teensy 3 pin assignments or some such.
    ? What are you talking about...

    Builtin LED is on pin 13.

  7. #7
    Senior Member
    Join Date
    Apr 2014
    Location
    -
    Posts
    9,735
    I'd perhaps add a #warning "AVR Watchdog does not work"... or better delete that file... as it is, it is a) confusing, b) leads to the wrong assumption "hey,wdt is there and will work", and c) wrong.

  8. #8
    Senior Member
    Join Date
    Nov 2012
    Posts
    1,911
    Paul ported an Arduino watchdog library. The basic example works fine on a T3.2

    Pete

  9. #9
    Senior Member
    Join Date
    Apr 2014
    Location
    -
    Posts
    9,735
    Quote Originally Posted by el_supremo View Post
    Paul ported an Arduino watchdog library. The basic example works fine on a T3.2

    Pete
    Hm. 64 commits behind master, readme says "

    Currently supports the following hardware:


    • Arduino Uno or compatible (ATmega328P)."
    Last commit (2016) mentiones Teensy LC (partial support)

    Code:
    int WatchdogKinetisKseries::sleep(int maxPeriodMS)
    {
    if (maxPeriodMS <= 0) return 0;
    // TODO....
    return 0;
    }
    Thanks for the link, Pete
    Last edited by Frank B; 01-24-2022 at 09:05 PM.

  10. #10
    Junior Member
    Join Date
    Oct 2016
    Posts
    18
    Well, some reading of the Freescale docs and testing proved out the code supplied by Bricomp above. Testing showed the WDT clock runs at 48mz on the T3.2 and is not dependent on the selected clock rate when compiling in the IDE. if you set the prescaler to max WDOG_PRESC =x0700, you can use a count of 6600000 and get a 1 sec trip. 2 sec needs 13200000, etc. Pretty simple, no libraries needed.

    And after reset it stays off... so no need for a disable command to make sure it doesn't keep looping. Now I'm off to try it on a T3.5.

    Thanks all.

  11. #11
    Junior Member
    Join Date
    Oct 2016
    Posts
    18
    In the true sense of a dog with a bone, I decided to work up a simple solution not dependent on device clock rates. The code below will work for any Teensy 3x (not having a model 4 around, I couldn't test it.) It should be self-explanatory enough
    for general use. Thanks all.

    //================================================== ======
    //==================Teensy Watchdog Timer Routine==================
    void Set_WatchDog_Timer(){ // A CPU Independent WD Timer
    // This code sets a 5 second timeout
    noInterrupts()
    WDOG_UNLOCK = WDOG_UNLOCK_SEQ1;
    WDOG_UNLOCK = WDOG_UNLOCK_SEQ2;
    delayMicroseconds(1); // Need to wait a bit..
    WDOG_STCTRLH = 0x0001; // Set Control Register... Enable WDG using the Low Power
    // 1khz clock, and reset only no interrupt triggering,
    // windowing disabled, allow updates, debug off, and
    // WD disabled in CPU Stop mode
    WDOG_TOVALL = 1000; // The next 2 lines set the time-out value. Low and High 16 bit values
    WDOG_TOVALH = 0; // This is the value that the watchdog timer compare itself to-- 1000 ticks.
    // Now set the clock prescaler.
    // WDOG_PRESC = 0x0000; // After reset, the default prescaler setting is 0x0400. The hardware adds
    // 1 to get a divisor of 5. This gives the default tick rate of
    // 1khz/5 = 200 hz. If we wanted another rate, we could set the value here.
    // Uncommenting the above line would produce a 1khz clock rate.
    interrupts();
    }

    void Reset_Watchdog_Timer(){ // Set for a delay;
    // Timer cycles at 200 hz. "count" value of 1000 = 5 secs
    noInterrupts();
    WDOG_REFRESH = 0xA602;
    WDOG_REFRESH = 0xB480;
    interrupts();
    }
    //================================================== =============

  12. #12
    I just got a watch dog timer working using the above code. You will need to call Reset_Watchdog_timer() before your time out. Meaning if you have a while statement that gets input, measures etc. you will need to have the reset call in there--otherwise the MCU will consider no activity and...reset.

    I tested my implementation, which was posted above in this thread and used some code to intentionally lock up a teensy 3.2--and after the set timeout, the MCU restarted. Which is what I was after.

  13. #13
    Senior Member BriComp's Avatar
    Join Date
    Apr 2014
    Location
    Cheltenham, UK
    Posts
    1,138
    Quote Originally Posted by kenhorner View Post
    In the true sense of a dog with a bone, I decided to work up a simple solution not dependent on device clock rates. The code below will work for any Teensy 3x (not having a model 4 around, I couldn't test it.) It should be self-explanatory enough
    for general use. Thanks all.

    //================================================== ======
    //==================Teensy Watchdog Timer Routine==================
    void Set_WatchDog_Timer(){ // A CPU Independent WD Timer
    // This code sets a 5 second timeout
    noInterrupts()
    WDOG_UNLOCK = WDOG_UNLOCK_SEQ1;
    WDOG_UNLOCK = WDOG_UNLOCK_SEQ2;
    delayMicroseconds(1); // Need to wait a bit..
    WDOG_STCTRLH = 0x0001; // Set Control Register... Enable WDG using the Low Power
    // 1khz clock, and reset only no interrupt triggering,
    // windowing disabled, allow updates, debug off, and
    // WD disabled in CPU Stop mode
    WDOG_TOVALL = 1000;// The next 2 lines set the time-out value. Low and High 16 bit values
    WDOG_TOVALH = 0; // This is the value that the watchdog timer compare itself to-- 1000 ticks.
    // Now set the clock prescaler.
    // WDOG_PRESC = 0x0000; // After reset, the default prescaler setting is 0x0400. The hardware adds
    // 1 to get a divisor of 5. This gives the default tick rate of
    // 1khz/5 = 200 hz. If we wanted another rate, we could set the value here.
    // Uncommenting the above line would produce a 1khz clock rate.
    interrupts();
    }

    void Reset_Watchdog_Timer(){ // Set for a delay;
    // Timer cycles at 200 hz. "count" value of 1000 = 5 secs
    noInterrupts();
    WDOG_REFRESH = 0xA602;
    WDOG_REFRESH = 0xB480;
    interrupts();
    }
    //================================================== =============
    Code:
    //================================================== ======
    //==================Teensy Watchdog Timer Routine==================
    void Set_WatchDog_Timer() { // A CPU Independent WD Timer
    // This code sets a 5 second timeout
    	noInterrupts()
    	WDOG_UNLOCK = WDOG_UNLOCK_SEQ1;
    	WDOG_UNLOCK = WDOG_UNLOCK_SEQ2;
    	delayMicroseconds(1);	// Need to wait a bit..
    	WDOG_STCTRLH = 0x0001;	// Set Control Register... Enable WDG using the Low Power
    							// 1khz clock, and reset only no interrupt triggering,
    							// windowing disabled, allow updates, debug off, and
    							// WD disabled in CPU Stop mode
    	WDOG_TOVALL = 1000;		// The next 2 lines set the time-out value. Low and High 16 bit values
    	WDOG_TOVALH = 0;		// This is the value that the watchdog timer compare itself to-- 1000 ticks.
    							// Now set the clock prescaler.
    							// WDOG_PRESC = 0x0000; // After reset, the default prescaler setting is 0x0400. The hardware adds
    							// 1 to get a divisor of 5. This gives the default tick rate of
    							// 1khz/5 = 200 hz. If we wanted another rate, we could set the value here.
    							// Uncommenting the above line would produce a 1khz clock rate.
    	interrupts();
    }
    
    void Reset_Watchdog_Timer() { // Set for a delay;
    // Timer cycles at 200 hz. "count" value of 1000 = 5 secs
    	noInterrupts();
    	WDOG_REFRESH = 0xA602;
    	WDOG_REFRESH = 0xB480;
    	interrupts();
    }
    //================================================== =============
    Do you think in future you could enclose your code between code tags.
    You can do this using the # button. I think you will agree it makes the code much more readable, and therefore more understandable.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •