// List of Common Failures // ------------------------------------------------------------------------ // - mathematical overflows // - implement all available controller traps // - unexpected program states or values // - implement default branches // - make plausibility checks // - use greater-/smaller- instead equal-comparison // - invalid pointers // - memory failures // - overload // - make stress tests // - endless loops // - watchdog // - single reset inside main loop or idle task // - checks if all code segments were executed // can be made with flag-variables // - execution time observation // - stackoverflow // - detect by using stack-end-marker (magic-number) // - race condition // - control mutual used variables and resources // - dead lock // Basics Controller Mistakes // ------------------------------------------------------------------------ // - not initialized ports // - read/write (TRIS), analog/digital (ANSEL) // - floating unused I/O pins // - configured as output and driven to a logic-low state // - ISR executes too often // - clear interrupt flag // - execution stops or ends in unexpected behavior // - missing endless main-loop // - copied code segements // - changed only one code position instead of both // - wrong function qualifiers // - static/extern // - wrong variable qualifiers // - static/extern, volatile, const // - other register values after watchdog-reset compared to power-on-reset // Detailed Failure Descriptions // ------------------------------------------------------------------------ // Race Condition // -------------------------------------------------------------------- // - very hard to find, because they depends on the execution oder // from parallel code // - and furthermore very hard to locate // - debugging changes the runtime behavior of the program // execution and so also the RC occurrence probability // - example of two parallel executions (both codes uses the same // counter variable) // code 1: code 2: // ... ... // cnt = cnt + 1; cnt++; // ... ... // - race condition (e.g. assembler directives) // load cnt // --> load cnt // increase cnt // store cnt // increase cnt <-- // store cnt // // the counter will be incremented by 1, instead of 2 // // - solution depends on available methods // - locks, mutex, critical section, semaphore, // disable interrupt (for uC purpose), ... // - transactional memory // // lock example: // global: int var; bool var_written; // main loop: int var_buffer; if (!var_written) // read value at single point { // and use the buffer variable, GID; // which is used only by this task var_buffer = var; GIE; } GID; // write buffer and set flag var_buffer = x; var_written = true; GIE; // isr: if (var_written) // take over value { var = var_buffer; var_written = false; } // transactional memory example: // - start tansaction // - execute transaction // - test if transaction was interrupted // - if yes redo // global: int var; bool var_valid; // main loop: int var_buffer; do // if transaction was interrupted { // do it again var_valid = true; // advantage: no interrupt disable necassary var_buffer = var; } while (!var_valid); // isr: var_valid = false;