Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Watchdog Object #52

Closed
DavidZemon opened this issue Nov 19, 2015 · 17 comments
Closed

Watchdog Object #52

DavidZemon opened this issue Nov 19, 2015 · 17 comments
Assignees
Milestone

Comments

@DavidZemon
Copy link
Collaborator

A common peripheral on other microcontrollers is the "watchdog" which will reset the CPU if the watchdog is not fed periodically. A watchdog object in PropWare would be a great addition.

@DavidZemon DavidZemon self-assigned this Nov 19, 2015
@DavidZemon DavidZemon added this to the Someday milestone Nov 19, 2015
@pmrobert
Copy link

That would be a very small object unless I'm misinterpreting your message.
I usually just code it in one of the free-running loops; it's only like 5
lines of code? BTW, thank you for PropWare!

-Mike

On Thu, Nov 19, 2015 at 1:51 PM, David Zemon [email protected]
wrote:

A common peripheral on other microcontrollers is the "watchdog" which will
reset the CPU if the watchdog is not fed periodically. A watchdog object in
PropWare would be a great addition.


Reply to this email directly or view it on GitHub
#52.

@DavidZemon
Copy link
Collaborator Author

It might well end up being a very small object - I'm okay with that. Care to post code for your idea?

And glad you like it! I haven't any questions on it in a very long time so I was wondering if anyone was still using it.

@DavidZemon
Copy link
Collaborator Author

Here's what I'm imagining:

  • Watchdog class inherits from the Runnable interface
namespace PropWare {
  class WatchDog : public Runnable {
    public:
      WatchDog(const unsigned int timeout, /* params for Runnable */)
        : Runnable(/* params for Runnable */),
          m_timeout(timeout),
          m_currentCog(cogid()) { }

      void reset () {
        this.m_timer = CNT;
      }

      void run () {
        unsigned int timeSinceLastReset;
        this->m_timer = CNT;

        while (1) {
          waitcnt(SLEEP_TIME + CNT);
          timeSinceLastReset = CNT - this->m_timer;
          if (timeSinceLastReset > this->timeout) {
            for (uint8_t cog = 0; cog < 8; ++cog) {
              if (this->m_currentCog != cog)
                cogstop(cog);
              cognew(main);
              cogstop(this->m_currentCog);
            }
          }
        }
      }

    private:
      const unsigned int m_timeout;
      const uint8_t m_currentCog;
      volatile unsigned int m_timer;
  }
}

@pmrobert
Copy link

Yes! A way to optionally reset the entire chip would be nice - I usually do
a clkset $7F if the watched cog times out after n tries - the nuclear
option. I know that's not elegant but it is reliable especially if the
watchdog is running in cog only - that's much less likely to get corrupted
by other code writing into hub where they shouldn't be.

On Fri, Nov 20, 2015 at 9:55 AM, David Zemon [email protected]
wrote:

Here's what I'm imagining:

namespace PropWare {
class WatchDog : public Runnable {
public:
WatchDog(const unsigned int timeout, /* params for Runnable /)
: Runnable(/
params for Runnable */),
m_timeout(timeout) { }

  void reset () {
    this.m_timer = CNT;
  }

  void run () {
    this->m_timer = CNT;


  }

private:
  const unsigned int m_timeout;
  volatile unsigned int m_timer;

}
}

  • One of the parameters of the constructor will be a timeout (units
    probably in clock ticks).
  • When the cog starts,


Reply to this email directly or view it on GitHub
#52 (comment).

@DavidZemon
Copy link
Collaborator Author

What does clkset $7f do?

@DavidZemon
Copy link
Collaborator Author

clkset simply changes the frequency right? That's what I'm seeing from the Spin documentation. But I don't understand what that would do for a watchdog.

Also, looks like I forgot a loop in my code above. Whoops!

@DavidZemon
Copy link
Collaborator Author

Thread started on how to reset the Propeller

@pmrobert
Copy link

Sorry, David, brainfart! it's actual $80,not $7F of CLK register. It does
in fact work as not-so-widely advertised.
This is the only place I think it's documented:

PropManual v1.2, p28 under CLK register definition for bit 7:

0
Always write ‘0’ here unless you intend to reset the chip.
1
Same as a hardware reset – reboots the chip. The Spin command REBOOT writes
a ‘1’ to the RESET bit.

On Fri, Nov 20, 2015 at 10:49 AM, David Zemon [email protected]
wrote:

Thread started
http://forums.parallax.com/discussion/162828/c-c-reset-propeller-via-software
on how to reset the Propeller


Reply to this email directly or view it on GitHub
#52 (comment).

@pmrobert
Copy link

0
Always write ‘0’ here unless you intend to reset the chip.
1
Same as a hardware reset – reboots the chip. The Spin command REBOOT writes
a ‘1’ to the RESET bit.

On Fri, Nov 20, 2015 at 10:49 AM, David Zemon [email protected]
wrote:

Thread started
http://forums.parallax.com/discussion/162828/c-c-reset-propeller-via-software
on how to reset the Propeller


Reply to this email directly or view it on GitHub
#52 (comment).

@DavidZemon
Copy link
Collaborator Author

Ha! How cool is that!? :D

@pmrobert
Copy link

Simple nuclear option! :-)

On Fri, Nov 20, 2015 at 11:33 AM, David Zemon [email protected]
wrote:

Ha! How cool is that!? :D


Reply to this email directly or view it on GitHub
#52 (comment).

@DavidZemon
Copy link
Collaborator Author

Okay, so new code as recommended, using the clkrst instruction. I'll give this a go soon as I have time. Unfortunately, my time at home has been more sparse than my time at work lately.

namespace PropWare {
  class WatchDog : public Runnable {
    public:
      WatchDog(const unsigned int timeout, /* params for Runnable */)
        : Runnable(/* params for Runnable */),
          m_timeout(timeout),
          m_currentCog(cogid()) { }

      void reset () {
        this.m_timer = CNT;
      }

      void run () {
        unsigned int timeSinceLastReset;
        this->m_timer = CNT;

        while (1) {
          waitcnt(SLEEP_TIME + CNT);
          timeSinceLastReset = CNT - this->m_timer;
          if (timeSinceLastReset > this->timeout)
            __builtin_propeller_clkset(0x80); // Hard reset
        }
      }

    private:
      const unsigned int m_timeout;
      const uint8_t m_currentCog;
      volatile unsigned int m_timer;
  }
}

@pmrobert
Copy link

That should do it for a full reset. Another variation would be to have the
ability to just stop the dead cog and restart it. As you mentioned earlier
(and you're a whole lot more knowledgeable re the inner workings of PropGCC
than I am) I also wonder if there might be orphaned stack or heap left over
with that scheme and, if so, how it would be freed. I hear you regarding
work/personal/hobby balance, the older I get the more important I realize
that is, I'm glad you realize that too.

-Mike

On Fri, Nov 20, 2015 at 1:46 PM, David Zemon [email protected]
wrote:

Okay, so no code as recommended, using the clkrst instruction. I'll give
this a go soon as I have time. Unfortunately, my time at home has been more
sparse than my time at work lately.

namespace PropWare {
class WatchDog : public Runnable {
public:
WatchDog(const unsigned int timeout, /* params for Runnable /)
: Runnable(/
params for Runnable */),
m_timeout(timeout),
m_currentCog(cogid()) { }

  void reset () {
    this.m_timer = CNT;
  }

  void run () {
    unsigned int timeSinceLastReset;
    this->m_timer = CNT;

    while (1) {
      waitcnt(SLEEP_TIME + CNT);
      timeSinceLastReset = CNT - this->m_timer;
      if (timeSinceLastReset > this->timeout)
        __builtin_propeller_clkset(0x80); // Hard reset
    }
  }

private:
  const unsigned int m_timeout;
  const uint8_t m_currentCog;
  volatile unsigned int m_timer;

}
}


Reply to this email directly or view it on GitHub
#52 (comment).

@DavidZemon
Copy link
Collaborator Author

I like the idea of expanding this to have 7 individual watchdogs, or optionally one global.... and it shouldn't require much more space at all to do so.

@pmrobert
Copy link

Yes, you have concisely stated what I wanted to concisely state.

On Fri, Nov 20, 2015 at 2:08 PM, David Zemon [email protected]
wrote:

I like the idea of expanding this to have 7 individual watchdogs, or
optionally one global.... and it shouldn't require much more space at all
to do so.


Reply to this email directly or view it on GitHub
#52 (comment).

DavidZemon added a commit that referenced this issue Nov 21, 2015
DavidZemon added a commit that referenced this issue Nov 21, 2015
DavidZemon added a commit that referenced this issue Nov 22, 2015
@DavidZemon
Copy link
Collaborator Author

Feel free to give it a try. The first couple tries were written at a coffee shop without a board, henceforth the re-committing multiple times.

@DavidZemon
Copy link
Collaborator Author

I've added another issue for expanding to 7 independent timers
#56

@DavidZemon DavidZemon modified the milestones: Version 2.0, Someday Mar 24, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants