Skip to content

System monitor (Watchdog)#1468

Open
avtolstoy wants to merge 16 commits into
developfrom
feature/watchdog
Open

System monitor (Watchdog)#1468
avtolstoy wants to merge 16 commits into
developfrom
feature/watchdog

Conversation

@avtolstoy

@avtolstoy avtolstoy commented Jan 18, 2018

Copy link
Copy Markdown
Member
submission notes
**Important:** Please sanitize/remove any confidential info like usernames, passwords, org names, product names/ids, access tokens, client ids/secrets, or anything else you don't wish to share.

Please Read and Sign the Contributor License Agreement ([Info here](https://github.com/spark/firmware/blob/develop/CONTRIBUTING.md)).

You may also delete this submission notes header if you'd like. Thank you for contributing!

Rebase on develop once #1469 is merged

Problem

Firmware does not utilize hardware watchdogs available on STM32F2 microcontroller (present on Photon/P1 and Electron), making it difficult for users to create robust solutions that behave deterministically and recover in case of various types of malfunctions.

Solution

See the original design spec for the ideas implemented in this PR ;)

Steps to Test

N/A

Example App

#include "application.h"
#include "system_threading.h"
#include "dct.h"

Serial1LogHandler dbg(115200, LOG_LEVEL_ALL);

// Enable threading. System thread automatically registers itself
// to be monitored.
SYSTEM_THREAD(ENABLED);
// Enable hardware watchdogs
STARTUP(System.enableFeature(WATCHDOG_FEATURE));
// Enable independent watchdog (along with the default one)
STARTUP(System.enableFeature(WATCHDOG_FEATURE_IWDG));

static void usage() {
    Serial.println("0 - write to DCT");
    Serial.println("1 - write to EEPROM");
    Serial.println("2 - run a while(true); loop (watchdog SHOULD be triggered)");
    Serial.println("3 - run a while(true); loop in system thread (watchdog SHOULD be triggered)");
    Serial.println("4 - System.sleep() for 10 seconds (watchdog SHOULD NOT be triggered)");
    Serial.println("5 - System.sleep() for 60 seconds (watchdog SHOULD be triggered)");
    Serial.println("6 - panic() from application thread");
    Serial.println("7 - HardFault");
}

static int endless_loop() {
    while(true);
    return 0;
}

static void endless_system_loop() {
    ActiveObjectThreadQueue* sys_thread = (ActiveObjectThreadQueue*)system_internal(1, nullptr);
    auto lambda = [=]() { endless_loop(); };
    sys_thread->invoke_async(FFL(lambda));
}

void setup() {
    // Enable watchdog for this thread
    // Use default timeout (1000ms)
    Watchdog.enable();

    waitUntil(Serial.isConnected);
    if (System.resetReason() == RESET_REASON_WATCHDOG) {
        Serial.println("We were reset by a watchdog!");
    }
    usage();
}

struct ThisIsALargeTestStruct {
    uint8_t data[1024];
};

/* executes continuously after setup() runs */
void loop() {
    if (Serial.available() > 0) {
        char c = Serial.read();
        switch (c) {
            case '0': {
                // DCT
                Serial.println("DCT");
                ThisIsALargeTestStruct testdata = {};
                for (int i = 0; i < 1024; i++) {
                    testdata.data[i] = random();
                }
                dct_write_app_data(&testdata, 9000, sizeof(testdata));
                Serial.println("DCT done");
                break;
            }
            case '1': {
                // EEPROM
                Serial.println("EEPROM");
                ThisIsALargeTestStruct testdata = {};
                EEPROM.put(0, testdata);
                Serial.println("EEPROM done");
                break;
            }
            case '2': {
                Serial.println("Entering while(true); loop");
                delay(2000);
                endless_loop();
                break;
            }
            case '3': {
                Serial.println("Making system thread go into while(true); loop");
                delay(2000);
                endless_system_loop();
                break;
            }
            case '4': {
                Serial.println("Going into sleep for 10 seconds. Watchdog SHOULD NOT be triggered");
                delay(2000);
                System.sleep(D1, FALLING, 10);
                break;
            }
            case '5': {
                Serial.println("Going into sleep for 60 seconds. Watchdog SHOULD be triggered");
                delay(2000);
                System.sleep(D1, FALLING, 60);
                break;
            }
            case '6': {
                Serial.println("Causing a panic from application thread");
                delay(2000);
                PANIC(UsageFault, "UsageFault");
                break;
            }
            case '7': {
                Serial.println("Causing a hardfault");
                delay(2000);
                HAL_USART_Write_NineBitData((HAL_USART_Serial)1000, 0x0000);
                break;
            }
            default: {
                break;
            }
        }
        waitUntil(Serial.isConnected);
        usage();
    }
}

References

  • [CH10636]
  • [CH9758]

Completeness

TODO: Documentation

  • User is totes amazing for contributing!
  • Contributor has signed CLA (Info here)
  • Problem and Solution clearly stated
  • Run unit/integration/application tests on device
  • Added documentation
  • Added to CHANGELOG.md after merging (add links to docs and issues)

@m-mcgowan m-mcgowan added this to the 0.8.0-rc.3 milestone Jan 18, 2018
@avtolstoy avtolstoy modified the milestones: 0.8.0-rc.3, 0.8.0-rc.4 Mar 26, 2018
@technobly technobly modified the milestones: 0.8.0-rc.4, 0.8.0-rc.5 May 6, 2018
@technobly technobly removed this from the 0.8.0-rc.5 milestone May 31, 2019
@antoniovazquezblanco

Copy link
Copy Markdown

What is the status on this PR?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants