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
Diff: SmartBoard_Tester.cpp
- 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]);