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:
4:ca93a8d4874d
Parent:
3:2b4fe31e8d15
--- a/SmartBoard_Tester.cpp	Tue Jan 25 02:02:19 2011 +0000
+++ b/SmartBoard_Tester.cpp	Thu Mar 31 11:22:00 2011 +0000
@@ -4,6 +4,8 @@
 /// to evaluate the SmartBoard baseboard.
 ///
 /// @note Copyright © 2011 by Smartware Computing, all rights reserved.
+///     This software may be used to derive new software, as long as
+///     this copyright statement remains in the source file.
 /// @author David Smart
 ///
 #include "mbed.h"
@@ -13,6 +15,14 @@
 #include "NTPClient.h"
 #include "SDFileSystem.h"
 #include "MSCFileSystem.h"
+#include "Watchdog.h"
+
+extern "C" void HardFault_Handler() {
+    printf("Hard Fault!\n");
+    while (1);
+}
+
+Watchdog wdt;
 
 Serial pc(USBTX, USBRX);    ///!< Used as the console for interactively reporting progress
 
@@ -30,6 +40,7 @@
 void CAN_Tests(void);
 void Ethernet_Tests(void);
 void USBHost_Tests(void);
+void FileSystem_Tests(void);
 
 /// TestVector will execute a given test, based on the parameter
 ///
@@ -52,15 +63,16 @@
         default:
         case '?':
             pc.printf("Commands:\r\n"
-                      "  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"
+                      "  L   LED_Tests();          // Blink each in turn\r\n"
+                      "  P   PWM_Tests();          // Ramps the PWM channels\r\n"
+                      "  A   AnalogIn_Tests();     // Measures voltage on each\r\n"
+                      "  R   RTC_Tests();          // Saves current time, alters it, restores it\r\n"
+                      "  M   MicroSD_Tests();      // Writes and Reads file on an installed card\r\n"
+                      "  S   RS_232_Tests();       // Outputs simple text\r\n"
+                      "  C   CAN_Tests();          // Requires CAN1 wired to CAN2, loops messages\r\n"
+                      "  E   Ethernet_Tests();     // Sets the clock from a time server\r\n"
+                      "  U   USBHost_Tests();      // Writes and Reads file on a memory stick\r\n"
+                      "  F   FileSystems_Tests();  // Writes and Reads file on internal file system\r\n"
                       "  X   eXit to automatic testing\r\n");
             break;
         case 'X':
@@ -96,6 +108,9 @@
         case 'U':
             USBHost_Tests();
             break;
+        case 'F':
+            FileSystem_Tests();
+            break;
     }
     return r;
 }
@@ -119,12 +134,22 @@
     int test = 0;                       ///!< which test to run
     char TestList[] = "XLPARrMSCEU";    ///!< list of valid test commands AUTOTESTS are uppercase
 
+    pc.printf("Set your baudrate from 9600 to 921600\r\n");
+    pc.baud(921600);
+    if (wdt.WatchdogCausedReset())
+        pc.printf("Watchdog caused reset. WD is armed for 30s cycle.\r\n");
+
+    wdt.Configure(30.0);     // longest test should be under this interval
+
+    wait(3.0);  // just wait a little while in case they want to inject a '?'
     while (1) {
+        wdt.Service();     // do this often enough
+
         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.10\r\n");
+            pc.printf("SmartBoard Hardware Tester [" __DATE__ " " __TIME__ "]\r\n");
+            pc.printf("  SmartBoard Hardware                    v0.05\r\n");
+            pc.printf("  SmartBoard Software                    v0.13\r\n");
             pc.printf("\r\n");
             pc.printf("                      [USB]       [Eth/USB]    \r\n");
             pc.printf(" +---------------+------------+---+-------+---+\r\n");
@@ -151,7 +176,10 @@
                 (void)pc.getc();
 
             while (interactive) {
+                wdt.Service();     // do this often enough
                 pc.printf("> ");
+                while (!pc.readable())
+                    wdt.Service();
                 int i = pc.getc();
                 pc.putc(i);
                 pc.putc('\r');
@@ -161,7 +189,9 @@
         } else {
             if (test == 0)
                 pc.printf("\x07"); // Bell character indicating start of tests
-            TestVector(TestList[test++]);
+            if (TestList[test] >= 'A' && TestList[test] <= 'Z') // Tests are UPPER-case only
+                TestVector(TestList[test]);
+            test++;
             if (TestList[test] == '\0')
                 test = 0;
             wait(5.0);  // Extra pause
@@ -193,7 +223,8 @@
 
     printf("LED Test:\r\n");
     for (l=0; l<numLeds; l++) {
-        printf("   Blink %s LED 3 times\r\n", Leds[l].name);
+        wdt.Service();
+        printf("    Blink %s LED 3 times\r\n", Leds[l].name);
         for (i=0; i<3; i++) {
             Leds[l].led = true;
             wait(0.4);
@@ -232,7 +263,8 @@
 
     printf("PWM Test:\r\n");
     for (l=0; l<numPwms; l++) {
-        printf("   Ramp %s PWM 3 times\r\n", Pwms[l].name);
+        wdt.Service();
+        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;
@@ -267,6 +299,7 @@
 
     printf("Analog Test:\r\n");
     for (l=0; l<numAnalogs; l++) {
+        wdt.Service();
         for (i=0; i<samples; i++) {
             uint16_t raw = Analogs[l].in.read_u16();
             float flt = Analogs[l].in.read();
@@ -323,6 +356,8 @@
     int i;
 
     while (digits--) {
+        while (!pc.readable())
+            wdt.Service();
         i = pc.getc();
         if (i == ' ') i = '0';      // special case for leading blank
         if (i >= '0' && i <= '9') {
@@ -381,7 +416,7 @@
             pc.printf("%02d:%02d:%02d\r\n", t->tm_hour, t->tm_min, t->tm_sec);
             // convert to timestamp and display (1256729737)
             time_t seconds = mktime(t);
-            seconds = seconds - (tzOffsetHr * 3600 + tzOffsetMin * 60);
+            seconds = seconds - (time_t)(tzOffsetHr * 3600 + tzOffsetMin * 60);
             set_time(seconds);
             break;
         } else {
@@ -448,6 +483,73 @@
         return false;
 }
 
+/// common file system test to write and then read a moderately large file
+///
+/// This will create a folder and then open a file for write. It will write a
+/// text string to the file and defined number of times and close the file.
+/// It will then report the performance metrics in bytes/sec write.
+/// It will then open the same file for read and read the file back, one record
+/// at a time. It will then report the performance metrics for the read in bytes/sec.
+///
+/// @param folder is the folder name to create
+/// @param file is the filename to create
+/// @param textMessage is the text message to use in the test
+/// @param COUNTLIMIT is the number of times the text is written to the file
+/// @returns nothing
+///
+void RunFileSystemTest(const char * folder, const char * file, const char * textMessage, int COUNTLIMIT) {
+    FILE *fp;
+    Timer timer;
+    char * buffer = (char *)malloc(strlen(textMessage)+2);  // just a bit bigger
+
+    if (strlen(folder))
+        mkdir(folder, 0777);
+    // Write test
+    printf("    Starting write test of %i chars.\r\n", strlen(textMessage) * COUNTLIMIT);
+    int begin = timer.read_us();
+    fp = fopen(file, "w");
+    if (fp == NULL) {
+        printf("    Could not open file for write\r\n");
+    } else {
+        int counter;
+        for (counter=0; counter<COUNTLIMIT; counter++) {
+            fprintf(fp, textMessage);
+        }
+        fclose(fp);
+        int end = timer.read_us();
+        printf("    Closed file. Wrote %i chars in %i uSec.\r\n",
+               strlen(textMessage) * COUNTLIMIT,
+               end - begin);
+        printf("        %6.0f bytes/sec.\r\n",
+               1.0e6f * (float)(strlen(textMessage) * COUNTLIMIT) / (end - begin));
+
+        // read test
+        printf("    Read test.\r\n");
+        begin = timer.read_us();
+        fp = fopen(file, "r");
+        if (fp == NULL) {
+            printf("    could not open file for read\r\n");
+        } else {
+            while (fgets(buffer, sizeof(buffer), fp)) {
+                while (strlen(buffer) > 0 && !isPrint(buffer[strlen(buffer)-1]))
+                    buffer[strlen(buffer)-1] = '\0';    // chomp the <LF>
+                //printf("    Read: {%s}\r\n", buffer);
+            }
+            fclose(fp);
+            end = timer.read_us();
+            printf("    Closed file. Read %i chars in %i uSec.\r\n",
+                   strlen(textMessage) * COUNTLIMIT,
+                   end - begin);
+            printf("        %6.0f bytes/sec.\r\n",
+                   1.0e6f * (float)(strlen(textMessage) * COUNTLIMIT) / (end - begin));
+        }
+    }
+    free(buffer);
+}
+
+
+
+
 /// 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
@@ -455,37 +557,20 @@
 ///
 void MicroSD_Tests(void) {
     SDFileSystem sd(p5, p6, p7, p8, "ud"); // the pinout on the mbed Cool Components workshop board
+    char folder[] = "/ud/testDir";
+    char file[] = "/ud/testDir/sdtest.txt";
     DigitalIn cardIn(p11);
-    FILE *fp;
-    char buffer[50];
+    const int COUNTLIMIT = 10000;
+    const char textMessage[] = "Write a message to the micro SD card!   50 chars\r\n";
 
-    printf("SD File System Tests:\r\n");
+    printf("SD File System Tests: [installed microSD card required]\r\n");
     printf("    Card Detection: %s\r\n", (cardIn) ? "in" : "out");
     if (cardIn) {
-        mkdir("/ud/testDir", 0777);
-        fp = fopen("/ud/testDir/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!\n");
-            fclose(fp);
-            printf("    Closed file.\r\n");
-            fp = fopen("/ud/testDir/sdtest.txt", "r");
-            if (fp) {
-                printf("    Reading file back.\r\n");
-                if (fgets(buffer, sizeof(buffer), fp)) {
-                    while (strlen(buffer) > 0 && !isPrint(buffer[strlen(buffer)-1]))
-                        buffer[strlen(buffer)-1] = '\0';    // chomp the <LF>
-                    printf("    Read: {%s}\r\n", buffer);
-                }
-                fclose(fp);
-            }
-        }
+        RunFileSystemTest(folder, file, textMessage, COUNTLIMIT);
     }
     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
@@ -493,47 +578,51 @@
 ///
 void USBHost_Tests(void) {
     MSCFileSystem fs ("fs");
-    FILE *fp;
-    char buffer[50];
+    char folder[] = "/fs/testDir";
+    char file[] = "/fs/testDir/sdtest.txt";
+    const int COUNTLIMIT = 10000;
+    const char textMessage[] = "Write a message to the USB Memory stick 50 chars\r\n";
 
     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);
-        }
-    }
+    RunFileSystemTest(folder, file, textMessage, COUNTLIMIT);
+    printf("    test complete!\r\n");
 }
 
 
+/// FileSystem_Tests attempts to access and write a file on the local file system
+///
+/// It will mount the file system, then attempt to write a simple
+/// file on the interface. While file handles are open, the USB drive will
+/// be unavailable.
+///
+void FileSystem_Tests(void) {
+    LocalFileSystem local("local");
+    char folder[] = "";
+    char file[] = "/local/fstest.txt";
+    const int COUNTLIMIT = 10000;
+    const char textMessage[] = "Write a message to the Local Files      50 chars\r\n";
+
+    printf("Local File System Tests: [mbed onboard file system]\r\n");
+    RunFileSystemTest(folder, file, textMessage, COUNTLIMIT);
+    printf("    test complete!\r\n");
+}
+
+
+
 /// FormatMicroseconds will format a number of microseconds int ascii seconds.
 ///
 /// It will support formatting the number with decimal and thousands
 /// separators.
 ///
 /// @param value to format
-/// @returns the formatted string
+/// @returns the formatted string "0034.123456"
 ///
 char * FormatMicroseconds(int value) {
     static char result[15] = "";
     int uSec = value % 1000000;
     int Sec = value / 1000000;
 
-    if (Sec > 1000)
-        sprintf(result, "%3i,%3i.%06i", Sec/1000, Sec%1000, uSec);
-    else
-        sprintf(result, "%7i.%06i", Sec, uSec);
+    sprintf(result, "%04i.%06i", Sec, uSec);
     return result;
 }
 
@@ -541,7 +630,21 @@
 /// ShowCANMessage will print to the console as specified
 ///
 /// This format is used in other tools, and is not explained
-/// here except in the code.
+/// here beyond what you see
+///
+/// +--- 'r'eceive or 't'ransmit
+/// |  +--- 'nrm' 11 bit identifier, 'xtd' 29 bit identifier
+/// |  |  +--- channel '1' to '2'
+/// |  |  |     +--- identifier in hex
+/// |  |  |     |     +-- dlc - data length control
+/// |  |  |     |     |  +--------------------+  data bytes 1 to 8
+/// |  |  |     |     |            |            +--- fixed zero for compatibility with other tools
+/// |  |  |     |     |            |            |   +-- fixed zero for compat
+/// |  |  |     |     |            |            |   |    +--- timestamp
+/// |  |  |     |     |            |            |   |    |
+/// _ ___ _ ________ __ _______________________ _ ___ ___________
+/// r xtd 2 1CF00400 08 11 22 33 44 55 66 77 88 0   0 1234.567890
+/// t xtd 1 18EAFF03 03 EE EE 00                0   0 1235.654321
 ///
 /// @param tx indicates it is a transmit message when non-zero, receive otherwise
 /// @param ch is the communication channel of this message
@@ -550,7 +653,9 @@
 /// @returns nothing
 ///
 void ShowCANMessage(int tx, int ch, CANMessage msg, int uSec) {
-    pc.printf("%c %s %d %08X %02X ", (tx) ? 't' : 'r', (msg.format == CANExtended) ? "xtd" : "nrm", ch, msg.id, msg.len);
+    pc.printf("%c %s %d %08X %02X ",
+              (tx) ? 't' : 'r',
+              (msg.format == CANExtended) ? "xtd" : "nrm", ch, msg.id, msg.len);
     for (int d=0; d<8; d++) {
         if (d < msg.len)
             pc.printf("%02X ", msg.data[d]);