Added hardware failure detection to watchdog example.
Fork of Watchdog_sample_nocoverage by
main.cpp@6:6f93bce60d98, 2018-03-09 (annotated)
- Committer:
- natgovor
- Date:
- Fri Mar 09 15:45:02 2018 +0000
- Revision:
- 6:6f93bce60d98
- Parent:
- 3:32a940251192
Added hardware failure detection to watchdog example.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Manel_Marin | 0:5ce3cfc57999 | 1 | #include "mbed.h" |
WilliamMarshQMUL | 3:32a940251192 | 2 | #include "rtos.h" |
WilliamMarshQMUL | 1:159a09ac60ba | 3 | #include "wdt.h" |
Manel_Marin | 0:5ce3cfc57999 | 4 | |
WilliamMarshQMUL | 2:c31a1758ac38 | 5 | // Sample program using the Watchdog |
WilliamMarshQMUL | 2:c31a1758ac38 | 6 | // --------------------------------- |
WilliamMarshQMUL | 3:32a940251192 | 7 | // * Three threads co-operate to flash two LEDs |
WilliamMarshQMUL | 3:32a940251192 | 8 | // * A simple way to inject a fault, by pressing a button |
WilliamMarshQMUL | 3:32a940251192 | 9 | // * The watchdog is configured with a 32ms timeout |
WilliamMarshQMUL | 3:32a940251192 | 10 | |
WilliamMarshQMUL | 3:32a940251192 | 11 | #define ON 1 |
WilliamMarshQMUL | 3:32a940251192 | 12 | #define OFF 0 |
WilliamMarshQMUL | 3:32a940251192 | 13 | DigitalOut led_red(LED_RED, ON); |
WilliamMarshQMUL | 3:32a940251192 | 14 | DigitalIn button(PTD0, PullUp); |
WilliamMarshQMUL | 3:32a940251192 | 15 | DigitalOut led1(PTC12, OFF); |
WilliamMarshQMUL | 3:32a940251192 | 16 | DigitalOut led2(PTC13, OFF); |
WilliamMarshQMUL | 3:32a940251192 | 17 | |
natgovor | 6:6f93bce60d98 | 18 | DigitalOut redLed(LED1); |
natgovor | 6:6f93bce60d98 | 19 | DigitalOut greenLed(LED2); |
natgovor | 6:6f93bce60d98 | 20 | |
natgovor | 6:6f93bce60d98 | 21 | // Analog inputs |
natgovor | 6:6f93bce60d98 | 22 | AnalogIn ain1(A0); |
natgovor | 6:6f93bce60d98 | 23 | AnalogIn ain2(A1); |
natgovor | 6:6f93bce60d98 | 24 | |
natgovor | 6:6f93bce60d98 | 25 | Serial pc(USBTX, USBRX); // tx, rx, for debugging |
natgovor | 6:6f93bce60d98 | 26 | |
WilliamMarshQMUL | 3:32a940251192 | 27 | // This ticker is used to feed the watch dog |
natgovor | 6:6f93bce60d98 | 28 | Ticker tick1; |
natgovor | 6:6f93bce60d98 | 29 | Ticker tick2; |
WilliamMarshQMUL | 3:32a940251192 | 30 | |
WilliamMarshQMUL | 3:32a940251192 | 31 | // Threads |
natgovor | 6:6f93bce60d98 | 32 | Thread threadT(osPriorityNormal, 1000); // timer thread |
natgovor | 6:6f93bce60d98 | 33 | Thread threadLED1(osPriorityNormal, 1000); // thread LED1 |
natgovor | 6:6f93bce60d98 | 34 | Thread threadLED2(osPriorityNormal, 1000); // thread LED2 |
natgovor | 6:6f93bce60d98 | 35 | Thread threadCheckLED1(osPriorityNormal, 1000); |
natgovor | 6:6f93bce60d98 | 36 | Thread threadCheckLED2(osPriorityNormal, 1000); |
natgovor | 6:6f93bce60d98 | 37 | |
natgovor | 6:6f93bce60d98 | 38 | // Message type |
natgovor | 6:6f93bce60d98 | 39 | typedef struct { |
natgovor | 6:6f93bce60d98 | 40 | uint16_t analog; /* Analog input value */ |
natgovor | 6:6f93bce60d98 | 41 | bool buttonPressed; |
natgovor | 6:6f93bce60d98 | 42 | } message_t; |
natgovor | 6:6f93bce60d98 | 43 | |
natgovor | 6:6f93bce60d98 | 44 | // Mail box |
natgovor | 6:6f93bce60d98 | 45 | Mail<message_t, 2> mailbox1; |
natgovor | 6:6f93bce60d98 | 46 | Mail<message_t, 2> mailbox2; |
natgovor | 6:6f93bce60d98 | 47 | |
natgovor | 6:6f93bce60d98 | 48 | volatile int samples1 = 0; |
natgovor | 6:6f93bce60d98 | 49 | volatile uint16_t smoothed1 = 0; |
natgovor | 6:6f93bce60d98 | 50 | void readA0() { |
natgovor | 6:6f93bce60d98 | 51 | smoothed1 = (smoothed1 >> 1) + (ain1.read_u16() >> 1); |
natgovor | 6:6f93bce60d98 | 52 | samples1++; |
natgovor | 6:6f93bce60d98 | 53 | if (samples1 == 10) { |
natgovor | 6:6f93bce60d98 | 54 | // send to thread |
natgovor | 6:6f93bce60d98 | 55 | message_t *mess = mailbox1.alloc(); // may fail but does not block |
natgovor | 6:6f93bce60d98 | 56 | if (mess) { |
natgovor | 6:6f93bce60d98 | 57 | mess->analog = smoothed1; |
natgovor | 6:6f93bce60d98 | 58 | mailbox1.put(mess); // fails but does not block if full |
natgovor | 6:6f93bce60d98 | 59 | } |
natgovor | 6:6f93bce60d98 | 60 | samples1 = 0; |
natgovor | 6:6f93bce60d98 | 61 | } |
natgovor | 6:6f93bce60d98 | 62 | } |
natgovor | 6:6f93bce60d98 | 63 | |
natgovor | 6:6f93bce60d98 | 64 | volatile int samples2 = 0; |
natgovor | 6:6f93bce60d98 | 65 | volatile uint16_t smoothed2 = 0; |
natgovor | 6:6f93bce60d98 | 66 | void readA1() { |
natgovor | 6:6f93bce60d98 | 67 | smoothed2 = (smoothed2 >> 1) + (ain2.read_u16() >> 1); |
natgovor | 6:6f93bce60d98 | 68 | samples2++; |
natgovor | 6:6f93bce60d98 | 69 | if (samples2 == 10) { |
natgovor | 6:6f93bce60d98 | 70 | // send to thread |
natgovor | 6:6f93bce60d98 | 71 | message_t *mess = mailbox2.alloc(); // may fail but does not block |
natgovor | 6:6f93bce60d98 | 72 | if (mess) { |
natgovor | 6:6f93bce60d98 | 73 | mess->analog = smoothed2; |
natgovor | 6:6f93bce60d98 | 74 | mailbox2.put(mess); // fails but does not block if full |
natgovor | 6:6f93bce60d98 | 75 | } |
natgovor | 6:6f93bce60d98 | 76 | samples2 = 0; |
natgovor | 6:6f93bce60d98 | 77 | } |
natgovor | 6:6f93bce60d98 | 78 | } |
natgovor | 6:6f93bce60d98 | 79 | |
natgovor | 6:6f93bce60d98 | 80 | // Write voltage digits |
natgovor | 6:6f93bce60d98 | 81 | // v Voltage as scale int, e.g. 3.30 is 330 |
natgovor | 6:6f93bce60d98 | 82 | void vToString(int v, char* s) { |
natgovor | 6:6f93bce60d98 | 83 | s[3] = '0' + (v % 10) ; |
natgovor | 6:6f93bce60d98 | 84 | v = v / 10 ; |
natgovor | 6:6f93bce60d98 | 85 | s[2] = '0' + (v % 10) ; |
natgovor | 6:6f93bce60d98 | 86 | v = v / 10 ; |
natgovor | 6:6f93bce60d98 | 87 | s[0] = '0' + (v % 10) ; |
natgovor | 6:6f93bce60d98 | 88 | } |
WilliamMarshQMUL | 3:32a940251192 | 89 | |
WilliamMarshQMUL | 3:32a940251192 | 90 | // ------------Fault Injection Button------------- |
WilliamMarshQMUL | 3:32a940251192 | 91 | // Wait while the button is down |
WilliamMarshQMUL | 3:32a940251192 | 92 | // Use this to simulate a STUCK fault |
WilliamMarshQMUL | 3:32a940251192 | 93 | // ----------------------------------------------- |
WilliamMarshQMUL | 3:32a940251192 | 94 | void waitButton() { |
WilliamMarshQMUL | 3:32a940251192 | 95 | while (!button) ; |
WilliamMarshQMUL | 3:32a940251192 | 96 | } |
WilliamMarshQMUL | 2:c31a1758ac38 | 97 | |
WilliamMarshQMUL | 3:32a940251192 | 98 | // ---Thread for controlling LED 1---------------- |
WilliamMarshQMUL | 3:32a940251192 | 99 | // Turn LED1 on/off in response to signals |
WilliamMarshQMUL | 3:32a940251192 | 100 | // ----------------------------------------------- |
WilliamMarshQMUL | 3:32a940251192 | 101 | void led1_thread() { // method to run in thread |
WilliamMarshQMUL | 3:32a940251192 | 102 | osEvent evt ; |
WilliamMarshQMUL | 3:32a940251192 | 103 | while (true) { |
WilliamMarshQMUL | 3:32a940251192 | 104 | evt = Thread::signal_wait(0x0); // wait for any signal |
WilliamMarshQMUL | 3:32a940251192 | 105 | if (evt.status == osEventSignal) { |
WilliamMarshQMUL | 3:32a940251192 | 106 | if (evt.value.signals & 0x01) led1 = ON ; |
WilliamMarshQMUL | 3:32a940251192 | 107 | if (evt.value.signals & 0x02) led1 = OFF ; |
natgovor | 6:6f93bce60d98 | 108 | wdt_kickA(); |
WilliamMarshQMUL | 3:32a940251192 | 109 | } |
natgovor | 6:6f93bce60d98 | 110 | //waitButton() ; // POSSIBLE FAULT HERE |
WilliamMarshQMUL | 3:32a940251192 | 111 | } |
WilliamMarshQMUL | 3:32a940251192 | 112 | } |
Manel_Marin | 0:5ce3cfc57999 | 113 | |
WilliamMarshQMUL | 3:32a940251192 | 114 | // ---Thread for controlling LED 2---------------- |
WilliamMarshQMUL | 3:32a940251192 | 115 | // Turn LED2 on/off in response to signals |
WilliamMarshQMUL | 3:32a940251192 | 116 | // ----------------------------------------------- |
WilliamMarshQMUL | 3:32a940251192 | 117 | void led2_thread() { // method to run in thread |
WilliamMarshQMUL | 3:32a940251192 | 118 | osEvent evt ; |
WilliamMarshQMUL | 3:32a940251192 | 119 | while (true) { |
WilliamMarshQMUL | 3:32a940251192 | 120 | evt = Thread::signal_wait(0x0); // wait for any signal |
WilliamMarshQMUL | 3:32a940251192 | 121 | if (evt.status == osEventSignal) { |
WilliamMarshQMUL | 3:32a940251192 | 122 | if (evt.value.signals & 0x01) led2 = ON ; |
WilliamMarshQMUL | 3:32a940251192 | 123 | if (evt.value.signals & 0x02) led2 = OFF ; |
natgovor | 6:6f93bce60d98 | 124 | wdt_kickB(); |
WilliamMarshQMUL | 3:32a940251192 | 125 | } |
natgovor | 6:6f93bce60d98 | 126 | //waitButton() ; // POSSIBLE FAULT HERE |
WilliamMarshQMUL | 3:32a940251192 | 127 | } |
WilliamMarshQMUL | 3:32a940251192 | 128 | } |
Manel_Marin | 0:5ce3cfc57999 | 129 | |
WilliamMarshQMUL | 3:32a940251192 | 130 | // ---Thread for timing -------------------------- |
WilliamMarshQMUL | 3:32a940251192 | 131 | // Send signals to the other threads |
WilliamMarshQMUL | 3:32a940251192 | 132 | // ----------------------------------------------- |
WilliamMarshQMUL | 3:32a940251192 | 133 | void timer_thread() { // method to run in thread |
WilliamMarshQMUL | 3:32a940251192 | 134 | while (true) { |
WilliamMarshQMUL | 3:32a940251192 | 135 | Thread::wait(250) ; |
WilliamMarshQMUL | 3:32a940251192 | 136 | threadLED1.signal_set(0x1) ; |
WilliamMarshQMUL | 3:32a940251192 | 137 | threadLED2.signal_set(0x1) ; |
WilliamMarshQMUL | 3:32a940251192 | 138 | Thread::wait(250) ; |
WilliamMarshQMUL | 3:32a940251192 | 139 | threadLED1.signal_set(0x2) ; |
WilliamMarshQMUL | 3:32a940251192 | 140 | threadLED2.signal_set(0x2) ; |
natgovor | 6:6f93bce60d98 | 141 | |
natgovor | 6:6f93bce60d98 | 142 | waitButton() ; // POSSIBLE FAULT HERE |
natgovor | 6:6f93bce60d98 | 143 | } |
natgovor | 6:6f93bce60d98 | 144 | } |
natgovor | 6:6f93bce60d98 | 145 | |
natgovor | 6:6f93bce60d98 | 146 | void check_led1() { |
natgovor | 6:6f93bce60d98 | 147 | int volts = 0; |
natgovor | 6:6f93bce60d98 | 148 | int counter = 0; |
natgovor | 6:6f93bce60d98 | 149 | char vstring[] = "X.XX\r\n"; |
natgovor | 6:6f93bce60d98 | 150 | |
natgovor | 6:6f93bce60d98 | 151 | while (true) { |
natgovor | 6:6f93bce60d98 | 152 | osEvent evt = mailbox1.get(); // wait for mail |
natgovor | 6:6f93bce60d98 | 153 | if (evt.status == osEventMail) { |
natgovor | 6:6f93bce60d98 | 154 | message_t* mess = (message_t*)evt.value.p; |
natgovor | 6:6f93bce60d98 | 155 | volts = (mess->analog * 330) / 0xffff; |
natgovor | 6:6f93bce60d98 | 156 | mailbox1.free(mess); // free the message space |
natgovor | 6:6f93bce60d98 | 157 | |
natgovor | 6:6f93bce60d98 | 158 | if (led1 == 1) { |
natgovor | 6:6f93bce60d98 | 159 | if (volts < 160 && volts > 140) { |
natgovor | 6:6f93bce60d98 | 160 | // normal |
natgovor | 6:6f93bce60d98 | 161 | } else if (volts == 0) { |
natgovor | 6:6f93bce60d98 | 162 | // failed open circuit |
natgovor | 6:6f93bce60d98 | 163 | pc.printf("Failed open circuit 1\n\r"); |
natgovor | 6:6f93bce60d98 | 164 | redLed = 0; |
natgovor | 6:6f93bce60d98 | 165 | } else if (volts > 300) { |
natgovor | 6:6f93bce60d98 | 166 | // failed short circuit |
natgovor | 6:6f93bce60d98 | 167 | pc.printf("Failed short circuit 1\n\r"); |
natgovor | 6:6f93bce60d98 | 168 | greenLed = 0; |
natgovor | 6:6f93bce60d98 | 169 | } |
natgovor | 6:6f93bce60d98 | 170 | } |
natgovor | 6:6f93bce60d98 | 171 | |
natgovor | 6:6f93bce60d98 | 172 | vToString(volts, vstring); |
natgovor | 6:6f93bce60d98 | 173 | counter++; |
natgovor | 6:6f93bce60d98 | 174 | if (counter == 10) { // limit bandwidth of serial |
natgovor | 6:6f93bce60d98 | 175 | pc.printf(vstring); |
natgovor | 6:6f93bce60d98 | 176 | counter = 0; |
natgovor | 6:6f93bce60d98 | 177 | } |
natgovor | 6:6f93bce60d98 | 178 | } |
natgovor | 6:6f93bce60d98 | 179 | } |
natgovor | 6:6f93bce60d98 | 180 | } |
natgovor | 6:6f93bce60d98 | 181 | |
natgovor | 6:6f93bce60d98 | 182 | void check_led2() { |
natgovor | 6:6f93bce60d98 | 183 | int volts = 0; |
natgovor | 6:6f93bce60d98 | 184 | int counter = 0; |
natgovor | 6:6f93bce60d98 | 185 | char vstring[] = "X.XX\r\n"; |
natgovor | 6:6f93bce60d98 | 186 | |
natgovor | 6:6f93bce60d98 | 187 | while (true) { |
natgovor | 6:6f93bce60d98 | 188 | osEvent evt = mailbox2.get(); // wait for mail |
natgovor | 6:6f93bce60d98 | 189 | if (evt.status == osEventMail) { |
natgovor | 6:6f93bce60d98 | 190 | message_t* mess = (message_t*)evt.value.p; |
natgovor | 6:6f93bce60d98 | 191 | volts = (mess->analog * 330) / 0xffff; |
natgovor | 6:6f93bce60d98 | 192 | mailbox2.free(mess); // free the message space |
natgovor | 6:6f93bce60d98 | 193 | |
natgovor | 6:6f93bce60d98 | 194 | if (led2 == 1) { |
natgovor | 6:6f93bce60d98 | 195 | if (volts < 160 && volts > 140) { |
natgovor | 6:6f93bce60d98 | 196 | // normal |
natgovor | 6:6f93bce60d98 | 197 | } else if (volts == 0) { |
natgovor | 6:6f93bce60d98 | 198 | // failed open circuit |
natgovor | 6:6f93bce60d98 | 199 | pc.printf("Failed open circuit 2\n\r"); |
natgovor | 6:6f93bce60d98 | 200 | redLed = 0; |
natgovor | 6:6f93bce60d98 | 201 | } else if (volts > 300) { |
natgovor | 6:6f93bce60d98 | 202 | // failed short circuit |
natgovor | 6:6f93bce60d98 | 203 | pc.printf("Failed open circuit 2\n\r"); |
natgovor | 6:6f93bce60d98 | 204 | greenLed = 0; |
natgovor | 6:6f93bce60d98 | 205 | } |
natgovor | 6:6f93bce60d98 | 206 | } |
natgovor | 6:6f93bce60d98 | 207 | |
natgovor | 6:6f93bce60d98 | 208 | vToString(volts, vstring); |
natgovor | 6:6f93bce60d98 | 209 | counter++; |
natgovor | 6:6f93bce60d98 | 210 | if (counter == 10) { // limit bandwidth of serial |
natgovor | 6:6f93bce60d98 | 211 | pc.printf(vstring); |
natgovor | 6:6f93bce60d98 | 212 | counter = 0; |
natgovor | 6:6f93bce60d98 | 213 | } |
natgovor | 6:6f93bce60d98 | 214 | } |
WilliamMarshQMUL | 3:32a940251192 | 215 | } |
WilliamMarshQMUL | 3:32a940251192 | 216 | } |
WilliamMarshQMUL | 3:32a940251192 | 217 | |
WilliamMarshQMUL | 3:32a940251192 | 218 | // -----------MAIN------------------------------- |
WilliamMarshQMUL | 3:32a940251192 | 219 | // Configure watchdog. Start threads. |
WilliamMarshQMUL | 3:32a940251192 | 220 | // Show start up with RED for 1sec |
WilliamMarshQMUL | 3:32a940251192 | 221 | // Remember the watchdog is running |
WilliamMarshQMUL | 3:32a940251192 | 222 | // - 1024ms to set it once |
WilliamMarshQMUL | 3:32a940251192 | 223 | // - then must feed it every 32ms |
WilliamMarshQMUL | 3:32a940251192 | 224 | // ---------------------------------------------- |
Manel_Marin | 0:5ce3cfc57999 | 225 | |
Manel_Marin | 0:5ce3cfc57999 | 226 | int main(void) { |
natgovor | 6:6f93bce60d98 | 227 | redLed = 1; |
natgovor | 6:6f93bce60d98 | 228 | greenLed = 1; |
natgovor | 6:6f93bce60d98 | 229 | |
natgovor | 6:6f93bce60d98 | 230 | wdt_1sec(); // initialise watchdog - 1sec timeout |
natgovor | 6:6f93bce60d98 | 231 | |
natgovor | 6:6f93bce60d98 | 232 | tick1.attach_us(callback(&readA0), 10000); // ticks every 10ms |
natgovor | 6:6f93bce60d98 | 233 | tick2.attach_us(callback(&readA1), 10000); // ticks every 10ms |
WilliamMarshQMUL | 1:159a09ac60ba | 234 | |
WilliamMarshQMUL | 3:32a940251192 | 235 | // start threads |
natgovor | 6:6f93bce60d98 | 236 | threadT.start(&timer_thread); // start the timer thread |
natgovor | 6:6f93bce60d98 | 237 | threadLED1.start(&led1_thread); // start the LED1 control thread |
natgovor | 6:6f93bce60d98 | 238 | threadLED2.start(&led2_thread); // start the LED2 control thread |
natgovor | 6:6f93bce60d98 | 239 | threadCheckLED1.start(&check_led1); // start the LED2 control thread |
natgovor | 6:6f93bce60d98 | 240 | threadCheckLED2.start(&check_led2); // start the LED2 control thread |
WilliamMarshQMUL | 1:159a09ac60ba | 241 | |
WilliamMarshQMUL | 1:159a09ac60ba | 242 | // show start-up |
WilliamMarshQMUL | 3:32a940251192 | 243 | led_red = OFF; |
natgovor | 6:6f93bce60d98 | 244 | Thread::wait(1000); |
WilliamMarshQMUL | 3:32a940251192 | 245 | led_red = ON; |
Manel_Marin | 0:5ce3cfc57999 | 246 | } |