Watchdog_Step-3_Edwin_Kadavy

Fork of Watchdog_sample_nocoverage by William Marsh

main.cpp

Committer:
edwinkad
Date:
2018-03-09
Revision:
6:d93fa1c57fd2
Parent:
3:32a940251192

File content as of revision 6:d93fa1c57fd2:

#include "mbed.h"
#include "rtos.h"
#include "wdt.h"

// Sample program using the Watchdog
// ---------------------------------
//    * Three threads co-operate to flash two LEDs
//    * A simple way to inject a fault, by pressing a button
//    * The watchdog is configured with a 32ms timeout

#define ON 1
#define OFF 0
DigitalOut led_red(LED_RED, ON);
DigitalOut led_blue(LED_BLUE, ON);
DigitalOut led_green(LED_GREEN, ON);
DigitalIn button(PTD0, PullUp);
DigitalOut led1(PTC12, OFF);
DigitalOut led2(PTC13, OFF);
AnalogIn ain1(A0) ;          // Analog input 1
AnalogIn ain2(A1) ;          // Analog input 2

// This ticker is used to feed the watch dog
Ticker tick1, tick2;

// Threads
Thread threadT ; // timer thread
Thread threadLED1 ; // thread LED1
Thread threadLED2 ; // thread LED2


//Detection of hardware failure

volatile int volts1 = 0 ;
volatile int volts2 = 0 ;
volatile int state=0 ;

Serial pc(USBTX, USBRX); // tx, rx, for debugging

// Message type1
typedef struct {
    uint16_t analog; /* Analog input value */
} message_t;

// Mail box
Mail<message_t, 2> mailbox;

// Function called every 10ms to read ADC
// Low pass filter
// Every 10th value is sent to mailbox
volatile int samples = 0 ;
volatile uint16_t smoothed = 0 ;
void readA0()
{
    smoothed = (smoothed >> 1) + (ain1.read_u16() >> 1) ;
    samples++ ;
    if (samples == 10) {
        // send to thread
        message_t *mess = mailbox.alloc() ; // may fail but does not block
        if (mess) {
            mess->analog = smoothed ;
            mailbox.put(mess); // fails but does not block if full
        }
        samples = 0;
    }
}

// Message type2
typedef struct {
    uint16_t analog2; /* Analog input value */
} message_t2;

// Mail box
Mail<message_t2, 2> mailbox2;

volatile int samples2 = 0 ;
volatile uint16_t smoothed2 = 0 ;
void readA1()
{
    smoothed2 = (smoothed2 >> 1) + (ain2.read_u16() >> 1) ;
    samples2++ ;
    if (samples2 == 10) {
        // send to thread
        message_t2 *mess = mailbox2.alloc() ; // may fail but does not block
        if (mess) {
            mess->analog2 = smoothed2 ;
            mailbox2.put(mess); // fails but does not block if full
        }
        samples2 = 0;
    }
}

// Write voltage digits
//   v  Voltage as scale int, e.g. 3.30 is 330
void vToString(int v, char* s)
{
    s[3] = '0' + (v % 10) ;
    v = v / 10 ;
    s[2] = '0' + (v % 10) ;
    v = v / 10 ;
    s[0] = '0' + (v % 10) ;
}



// ------------Fault Injection Button-------------
//  Wait while the button is down
//     Use this to simulate a STUCK fault
// -----------------------------------------------
void waitButton()
{
    while (!button) ;
}

// ---Thread for controlling LED 1----------------
//   Turn LED1 on/off in response to signals
// -----------------------------------------------
void led1_thread()    // method to run in thread
{
    osEvent evt ;
    while (true) {
        wdt_kickA();    // first part
        evt = Thread::signal_wait(0x0); // wait for any signal
        if (evt.status == osEventSignal) {
            if (evt.value.signals & 0x01) led1 = ON ;
            if (evt.value.signals & 0x02) led1 = OFF ;
        }
        //waitButton() ;  // POSSIBLE FAULT HERE
    }
}

// ---Thread for controlling LED 2----------------
//   Turn LED2 on/off in response to signals
// -----------------------------------------------
void led2_thread()    // method to run in thread
{
    osEvent evt ;
    while (true) {
        wdt_kickB();    // second part
        evt = Thread::signal_wait(0x0); // wait for any signal
        if (evt.status == osEventSignal) {
            if (evt.value.signals & 0x01) led2 = ON ;
            if (evt.value.signals & 0x02) led2 = OFF ;
        }
        waitButton() ; // POSSIBLE FAULT HERE
    }
}

// ---Thread for timing --------------------------
//   Send signals to the other threads
// -----------------------------------------------
void timer_thread()    // method to run in thread
{
    while (true) {
        Thread::wait(250) ;

        threadLED1.signal_set(0x1) ;
        threadLED2.signal_set(0x1) ;
        Thread::wait(250) ;
        threadLED1.signal_set(0x2) ;
        threadLED2.signal_set(0x2) ;
        // waitButton() ; // POSSIBLE FAULT HERE
    }
}

void detection(int volts)
{
    if(volts==0 ||state==1) {
        led_blue= OFF;
        state=1;
    } else if(volts>=300||state==2) {
        led_green= OFF;
        state=2;
    }
}

// -----------MAIN-------------------------------
//    Configure watchdog. Start threads.
//    Show start up with RED for 1sec
//    Remember the watchdog is running
//       - 1024ms to set it once
//       - then must feed it every 32ms
// ----------------------------------------------



int main(void)
{
    wdt_256ms() ; // initialise watchdog - 32ms timeout
    //wdt_kick_all;
    //tick.attach_us(callback(&wdt_kick_all), 20000); // ticks every 20ms

    // start threads
    threadT.start(&timer_thread) ; // start the timer thread
    threadLED1.start(&led1_thread) ; // start the LED1 control thread
    threadLED2.start(&led2_thread) ; // start the LED2 control thread


    // show start-up
    led_red = OFF;
    Thread::wait(1000) ;
    led_red = ON;

    //hardware failure detection
    int counter = 0 ;
    char vstring1[] = "X.XX\r\n" ;
    char vstring2[] = "X.XX\r\n" ;

    tick1.attach_us(callback(&readA0), 10000); // ticks every 10ms
    tick2.attach_us(callback(&readA1), 10000); // ticks every 10ms
    while (true) {
        osEvent evt = mailbox.get(); // wait for mail
        if (evt.status == osEventMail) {
            message_t* mess = (message_t*)evt.value.p ;
            volts1 = (mess->analog * 330) / 0xffff ;

            mailbox.free(mess) ;  // free the message space
        }

        osEvent evt2 = mailbox2.get(); // wait for mail
        if (evt2.status == osEventMail) {
            message_t2* mess = (message_t2*)evt2.value.p ;
            volts2 = (mess->analog2 * 330) / 0xffff ;
            mailbox2.free(mess) ;  // free the message space
        }

        counter++ ;
        if (counter == 5) {  // limit bandwidth of serial
            detection(volts1);  // hardware fault detecttion.(It is inside the counter which cause a small delay,...
            detection(volts2);  // putting it out side causes the first 0 value to be read showing an instant failure)
            vToString(volts1, vstring1) ;
            pc.printf("LED1 ");
            pc.printf(vstring1) ;
            vToString(volts2, vstring2) ;
            pc.printf("LED2 ");
            pc.printf(vstring2) ;
            counter = 0 ;
        }
    }

}