This package contains a simple test of tests for various elements of the SmartBoard hardware, which is a simple baseboard designed for easy embedding. It is able to run both a semi-automatic test suite as well as allow interactive testing.

Dependencies:   EthernetNetIf NTPClient_NetServices mbed

This program is most of what you need to test your SmartBoard baseboard hardware. It provides a means to test the following:

  • Two channels of CAN (with a loopback cable)
  • RS-232 Ports
  • Analog inputs
  • PWM outputs
  • Ethernet port
  • Real time clock
  • micro SD
  • USB Host port
Revision:
0:5db287f0060b
Child:
1:586392c0e935
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SmartBoard_Tester.cpp	Sun Jan 16 18:30:14 2011 +0000
@@ -0,0 +1,453 @@
+/// @file SmartBoard_Tester.cpp is the simple test framework
+///
+/// This file contains the startup, interactive, and test code
+/// to evaluate the SmartBoard baseboard.
+///
+/// @note Copyright © 2011 by Smartware Computing, all rights reserved.
+/// @author David Smart
+///
+#include "mbed.h"
+#include "SmartBoard.h"
+#include "ShowTime.h"
+#include "EthernetNetIf.h"
+#include "NTPClient.h"
+#include "SDFileSystem.h"
+#include "MSCFileSystem.h"
+
+Serial pc(USBTX, USBRX);    ///< Used as the console for interactively reporting progress
+
+const char * TicTocServer = "ntp.okstate.edu";  ///< time server since it is closer than "0.uk.pool.ntp.org"
+const int tzOffsetHr = -6;      ///< time zone offset hours to print time in local time
+const int tzOffsetMin = 0;      ///< time zone offset minutes to print time in local time
+
+void LED_Tests(void);
+void PWM_Tests(void);
+void AnalogIn_Tests(void);
+void RTC_Tests(void);
+void MicroSD_Tests(void);
+void RS_232_Tests(void);
+void CAN_Tests(void);
+void Ethernet_Tests(void);
+void USBHost_Tests(void);
+
+/// TestVector will execute a given test, based on the parameter
+///
+/// It can show the list of available commands, as for an interactive
+/// test session, or it can simply execute the chosen test. This is
+/// used for both the automated testing and the interactive testing,
+/// so a couple of the commands for interactive would not be used
+/// for the automated testing.
+/// '?' causes it to display the available commands.
+///
+/// @param i contains the single character value indicating the operation
+///         to perform.
+/// @returns false if the input paramter was 'X'.
+/// @returns true if the input parameters was not 'X'.
+///
+bool TestVector(int i) {
+    bool r = true;  ///< expect to return true
+
+    switch (i) {
+        default:
+        case '?':
+            pc.printf("Commands:\r\nx"
+                      "  L   LED_Tests();\r\n"
+                      "  P   PWM_Tests(); // note interaction between LEDs and PWMs\r\n"
+                      "  A   AnalogIn_Tests();\r\n"
+                      "  R   RTC_Tests();\r\n"
+                      "  M   MicroSD_Tests();\r\n"
+                      "  S   RS_232_Tests();\r\n"
+                      "  C   CAN_Tests();\r\n"
+                      "  E   Ethernet_Tests();\r\n"
+                      "  U   USBHost_Tests();\r\n"
+                      "  X   eXit to automatic testing\r\n");
+            break;
+        case 'X':
+            r = false;
+            break;
+        case 'L':
+            LED_Tests();
+            break;
+        case 'P':
+            PWM_Tests();
+            break;
+        case 'A':
+            AnalogIn_Tests();
+            break;
+        case 'R':
+            RTC_Tests();
+            break;
+        case 'M':
+            MicroSD_Tests();
+            break;
+        case 'S':
+            RS_232_Tests();
+            break;
+        case 'C':
+            CAN_Tests();
+            break;
+        case 'E':
+            Ethernet_Tests();
+            break;
+        case 'U':
+            USBHost_Tests();
+            break;
+    }
+    return r;
+}
+
+/// main is the main startup code.
+///
+/// This initializes the test environment, shows a banner,
+/// and starts the automated testing.
+/// It also detects if the user is attempting to interact, and
+/// between each test category there is the possibility to transfer
+/// to the interactive test mode.
+/// When in interactive test mode, the user determines which test
+/// to run. The user can also exit interactive mode back to the
+/// automated test mode.
+///
+/// @returns never
+///
+int main() {
+    bool init = true;                   ///< init is slightly different
+    bool interactive = false;           ///< track when in interactive mode
+    int test = 0;                       ///< which test to run
+    char TestList[] = "XLPARMSCEU";     ///< list of valid test commands
+
+    while (1) {
+        if (pc.readable() || init) {
+            pc.printf("\r\n\r\n");
+            pc.printf("SmartBoard Hardware Tester\r\n");
+            pc.printf("  SmartBoard Hardware    v0.05\r\n");
+            pc.printf("  SmartBoard Software    v0.07\r\n");
+            pc.printf("\r\n");
+            pc.printf("                      [USB]       [Eth/USB]    \r\n");
+            pc.printf(" +---------------+------------+---+-------+---+\r\n");
+            pc.printf(" |O [RS232 1-2]  |  |       | |   |       |  O|\r\n");
+            pc.printf(" |               |  |microSD| |   |       |   |\r\n");
+            pc.printf(" |S              |  |       | |   |       |  C|\r\n");
+            pc.printf(" |P              |  +-------+ |   |       |  A|\r\n");
+            pc.printf(" |I              |            |   |Yl   Gr|  N|\r\n");
+            pc.printf(" |1              |            |   +-------+  1|\r\n");
+            pc.printf(" |-              |            |              -|\r\n");
+            pc.printf(" |2              |     RTC    |              2|\r\n");
+            pc.printf(" |               |  (Battery) |               |\r\n");
+            pc.printf(" |               |            |               |\r\n");
+            pc.printf(" |               | 1  2  3  4 |               |\r\n");
+            pc.printf(" |               +------------+               |\r\n");
+            pc.printf(" |O[Analog In ]        O        [PWM Out]    O|\r\n");
+            pc.printf(" +--------------------------------------------+\r\n");
+            pc.printf("\r\n");
+            init = false;
+        }
+        if (pc.readable()) {
+            interactive = true;
+            while (pc.readable())
+                (void)pc.getc();
+
+            while (interactive) {
+                pc.printf("> ");
+                int i = pc.getc();
+                pc.putc(i);
+                pc.putc('\r');
+                pc.putc('\n');
+                interactive = TestVector(i);
+            }
+        } else {
+            if (test == 0)
+                pc.printf("\x07"); // Bell character indicating start of tests
+            TestVector(TestList[test++]);
+            if (TestList[test] == '\0')
+                test = 0;
+            wait(5.0);  // Extra pause
+        }
+    }
+}
+
+/// LED_Tests performs some simple digital output to the
+/// LEDs.
+///
+/// It will attempt to exercise the LEDs on the Ethernet ports
+/// as well, but by jumper configuration these may not be available.
+///
+void LED_Tests(void) {
+    int l;
+    int i;
+    struct {
+        const char * name;
+        DigitalOut led;
+    } Leds[] = {
+        {"Ethernet Green", ETHERGREEN},
+        {"Ethernet Yellow", ETHERYELLOW},
+        {"Led 1", LED1},
+        {"Led 2", LED2},
+        {"Led 3", LED3},
+        {"Led 4", LED4}
+    };
+    const int numLeds = sizeof(Leds) / sizeof(Leds[0]);
+
+    printf("LED Test:\r\n");
+    for (l=0; l<numLeds; l++) {
+        printf("   Blink %s LED 3 times\r\n", Leds[l].name);
+        for (i=0; i<3; i++) {
+            Leds[l].led = true;
+            wait(0.4);
+            Leds[l].led = false;
+            wait(0.4);
+        }
+    }
+}
+
+/// PWM_Tests performs some simple pwm output to the
+/// PWM channels and the LEDs.
+///
+/// It will attempt to exercise the outputs with a simple ramping
+/// signal, but by jumper configuration these may not be available.
+///
+void PWM_Tests(void) {
+    int l;
+    int i;
+    float f;
+    struct {
+        const char * name;
+        PwmOut pwm;
+    } Pwms[] = {
+        {"PWM 1", p21},
+        {"PWM 2", p22},
+        {"PWM 3", p23},
+        {"PWM 4", p24},
+        {"PWM 5", p25},
+        {"PWM 6", p26},
+        {"Led 1", LED1},
+        {"Led 2", LED2},
+        {"Led 3", LED3},
+        {"Led 4", LED4}
+    };
+    const int numPwms = sizeof(Pwms) / sizeof(Pwms[0]);
+
+    printf("PWM Test:\r\n");
+    for (l=0; l<numPwms; l++) {
+        printf("   Ramp %s PWM 3 times\r\n", Pwms[l].name);
+        for (i=0; i<3; i++) {
+            for (f=0.0; f<=1.0; f+= 0.1) {
+                Pwms[l].pwm = f;
+                wait(0.1);
+            }
+        }
+        Pwms[l].pwm = 0;    // off when done
+    }
+}
+
+/// AnalogIn_Tests takes a few sample measurements on each channel
+///
+/// It samples each channel a number of times and presents the
+/// converted results on the console.
+///
+void AnalogIn_Tests(void) {
+    int l;
+    int i;
+    const int samples = 20;
+    struct {
+        const char * name;
+        AnalogIn in;
+    } Analogs[] = {
+        {"Ain 1", p15},
+        {"Ain 2", p16},
+        {"Ain 3", p17},
+        {"Ain 4", p18},
+        {"Ain 5", p19},
+        {"Ain 6", p20}
+    };
+    const int numAnalogs = sizeof(Analogs) / sizeof(Analogs[0]);
+
+    printf("Analog Test:\r\n");
+    for (l=0; l<numAnalogs; l++) {
+        for (i=0; i<samples; i++) {
+            uint16_t raw = Analogs[l].in.read_u16();
+            float flt = Analogs[l].in.read();
+            printf("    Analog %i is %04X, %3.2f, %3.2fv\r", l, raw, flt, flt*3.3);
+            wait(0.1);
+        }
+        printf("\n");
+    }
+}
+
+/// RTC_Tests will perform simple tests on the Real Time Clock
+///
+/// It will first sample the time from the RTC and later restore
+/// it as best it can.
+/// In the middle of that it will set the clock, then simply show
+/// the time once per second for 5 seconds. After this it
+/// will restore the clock at best it can.
+///
+void RTC_Tests(void) {
+    time_t x;
+    int i;
+    const int oldTime = 1256729737;
+
+    printf("RTC Test:\r\n");
+    ShowTime(0, -6, 0);
+    x = time(NULL);         // Save the time before the test
+    printf("    Saving current time(%d)\r\n", x);
+
+    set_time(oldTime);  // Set RTC time to Wed, 28 Oct 2009 11:35:37
+    printf("    Set time to Wed, 28 Oct 2009 11:35:37\r\n");
+
+    for (i=0; i<5; i++) {
+        ShowTime();
+        wait(1.0);
+    }
+    set_time(x + time(NULL) - 1256729737);          // Approximately restored
+    ShowTime(0, -6, 0);
+    wait(1.0);
+    ShowTime(0, -6, 0);
+}
+
+/// Ethernet_Tests will attempt to test the Ethernet interface
+///
+/// It will connect to the network - if possible, then it will
+/// try to connect to a network time server and set the clock,
+/// using hard coded time server and time zone offset values.
+///
+/// It appears that the Ethernet interface cannot be instantiated,
+/// destroyed, and later instantiated again (it would reliably "hang").
+/// So, this test is "runonce" protected.
+///
+void Ethernet_Tests(void) {
+    EthernetNetIf eth;
+    NTPClient ntp;
+    static bool runonce = true;
+
+    printf("Ethernet Test:\r\n");
+    if (runonce) {
+        EthernetErr ethErr = eth.setup();
+        if (ethErr) {
+            printf("Error %d in setup.\r\n", ethErr);
+            return;
+        }
+        printf("    Ethernet Setup OK\r\n");
+        ShowTime(0, tzOffsetHr, tzOffsetMin);
+        printf("    Setting clock to %s\r\n", TicTocServer);
+        Host server(IpAddr(), 123, TicTocServer);
+        ntp.setTime(server);
+        printf("    Clock was set.\r\n");
+        wait(1.0);
+        ShowTime(0, tzOffsetHr, tzOffsetMin);
+        runonce = false;
+    } else {
+        printf("   only runs once per cold-boot.\r\n");
+    }
+}
+
+/// MicroSD_Tests attempts to access and write a file on the micro SD card
+///
+/// It will mount the file system, then attempt to write a simple
+/// file on the micro SD card.
+///
+void MicroSD_Tests(void) {
+    SDFileSystem sd(p5, p6, p7, p8, "sd"); // the pinout on the mbed Cool Components workshop board
+    FILE *fp;
+    char buffer[50];
+
+    printf("SD File System Tests:\r\n");
+    mkdir("/sd/mydir", 0777);
+    fp = fopen("/sd/mydir/sdtest.txt", "w");
+    if (fp == NULL) {
+        printf("    Could not open file for write\r\n");
+    } else {
+        fprintf(fp, "Write a message to the micro SD card!");
+        fclose(fp);
+        printf("    Closed file.\r\n");
+        fp = fopen("/sd/mydir/sdtest.txt", "r");
+        if (fp) {
+            printf("    Reading file back.\r\n");
+            if (fgets(buffer, sizeof(buffer), fp)) {
+                if (strlen(buffer) > 2)
+                    buffer[strlen(buffer)-2] = '\0';    // chomp the <LF>
+                printf("    Read: {%s}\r\n", buffer);
+            }
+            fclose(fp);
+        }
+    }
+    printf("    test complete!\r\n");
+}
+
+
+/// USBHost_Tests attempts to access and write a file on USB stick
+///
+/// It will mount the file system, then attempt to write a simple
+/// file on the USB interface.
+///
+void USBHost_Tests(void) {
+    MSCFileSystem fs ("fs");
+    FILE *fp;
+    char buffer[50];
+
+    printf("USB Host Tests: [installed memory stick required]\r\n");
+    fp = fopen("/fs/hello.txt","w");
+    if (fp) {
+        printf("    Writing to hello.txt file\r\n");
+        fprintf(fp,"Hello world!\r\n");
+        fclose (fp);
+        printf("    Closed file.\r\n");
+        fp = fopen("/fs/hello.txt", "r");
+        if (fp) {
+            printf("    Reading file back.\r\n");
+            if (fgets(buffer, sizeof(buffer), fp)) {
+                if (strlen(buffer) > 2)
+                    buffer[strlen(buffer)-2] = '\0';    // chomp the <LF>
+                printf("    Read: {%s}\r\n", buffer);
+            }
+            fclose(fp);
+        }
+    }
+}
+
+/// CAN_Tests will send some packets on one CAN port and expect them on the other
+///
+/// It will attempt to send 10 messages on one port and expect that
+/// all 10 messages were received on the other port. The two ports should
+/// be wired from one to the other with a loop-back cable and a termination
+/// resistor.
+///
+void CAN_Tests(void) {
+    CAN can1(p9, p10);
+    CAN can2(p30, p29);
+    char Txcounter = 0;
+    char Rxcounter = 0;
+    CANMessage msg;
+    int i;
+
+    printf("CAN Tests:\r\n");
+    for (i=0; i<10; i++) {
+        if (can1.write(CANMessage(1337, &Txcounter, 1))) {
+            Txcounter++;
+            printf("    Message sent: %d\r\n", Txcounter);
+            wait(0.05);
+        }
+        if (can2.read(msg)) {
+            printf("    Message received: %d\r\n", msg.data[0]);
+            Rxcounter++;
+        }
+        wait(0.2);
+    }
+    if (Txcounter == Rxcounter)
+        printf("    passed.\r\n");
+    else
+        printf("    **** Txcounter (%d) != Rxcounter (%d) ****\r\n", Txcounter, Rxcounter);
+}
+
+/// RS_232_Tests will say hello on each of the RS-232 channels
+///
+/// It will print a hello text string out each of the ports.
+///
+void RS_232_Tests(void) {
+    Serial s1(p13, p14);
+    Serial s2(p28, p27);
+
+    pc.printf("RS-232 Tests:\r\n");
+    s1.printf("    Hello going out S1\r\n");
+    s2.printf("    Hello going out S2\r\n");
+    pc.printf("    end tests.\r\n");
+}