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:
- 1:586392c0e935
- Parent:
- 0:5db287f0060b
- Child:
- 2:02e7d896824f
--- a/SmartBoard_Tester.cpp Sun Jan 16 18:30:14 2011 +0000 +++ b/SmartBoard_Tester.cpp Mon Jan 24 00:41:01 2011 +0000 @@ -24,6 +24,7 @@ void PWM_Tests(void); void AnalogIn_Tests(void); void RTC_Tests(void); +void RTC_Set(void); void MicroSD_Tests(void); void RS_232_Tests(void); void CAN_Tests(void); @@ -50,7 +51,7 @@ switch (i) { default: case '?': - pc.printf("Commands:\r\nx" + 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" @@ -77,6 +78,9 @@ case 'R': RTC_Tests(); break; + case 'r': + RTC_Set(); + break; case 'M': MicroSD_Tests(); break; @@ -113,14 +117,14 @@ 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 + char TestList[] = "XLPARrMSCEU"; ///< list of valid test commands AUTOTESTS are uppercase 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(" SmartBoard Software v0.09\r\n"); pc.printf("\r\n"); pc.printf(" [USB] [Eth/USB] \r\n"); pc.printf(" +---------------+------------+---+-------+---+\r\n"); @@ -287,7 +291,7 @@ const int oldTime = 1256729737; printf("RTC Test:\r\n"); - ShowTime(0, -6, 0); + ShowTime(tzOffsetHr, tzOffsetMin); x = time(NULL); // Save the time before the test printf(" Saving current time(%d)\r\n", x); @@ -299,11 +303,94 @@ wait(1.0); } set_time(x + time(NULL) - 1256729737); // Approximately restored - ShowTime(0, -6, 0); + ShowTime(tzOffsetHr, tzOffsetMin); wait(1.0); - ShowTime(0, -6, 0); + ShowTime(tzOffsetHr, tzOffsetMin); +} + +/// GetNumber will get from the user a number using the +/// specified number of digits. +/// +/// They can enter a number from 0 to 10^(digits-1) +/// +/// @param digits is the number of digits to enter +/// @param pValue is a pointer to where to store the result +/// @returns true if a number was entered +/// @returns false if they entered a non-digit +/// +int GetNumber(int digits, int * pValue) { + int tempValue = 0; + int i; + + while (digits--) { + i = pc.getc(); + if (i == ' ') i = '0'; // special case for leading blank + if (i >= '0' && i <= '9') { + pc.putc(i); + tempValue = tempValue * 10 + (i - '0'); + } else + return false; + } + *pValue = tempValue; + return true; } +/// RTC_Set will interactively set the Real Time Clock +/// +/// It will allow you to enter the date and time information +/// and then create a timestamp. After this, it will set +/// the RTC to that timestamp. +/// +void RTC_Set(void) { + time_t seconds = time(NULL); + struct tm *t = localtime(&seconds); + int i; + + printf("RTC Set:\r\n"); + ShowTime(seconds, tzOffsetHr, tzOffsetMin); + printf(" Enter the time MM/DD/YYYY HH:MM:SS\r\n"); + while (1) { + printf(" > "); + if (GetNumber(2, &t->tm_mon)) { + pc.putc('/'); + if (!GetNumber(2, &t->tm_mday)) + continue; + pc.putc('/'); + if (!GetNumber(4, &t->tm_year)) + continue; + } else { + pc.printf("%02d/%02d/%04d", t->tm_mon+1, t->tm_mday, t->tm_year+1900); + } + pc.putc(' '); + if (!GetNumber(2, &t->tm_hour)) { + pc.printf("%02d:%02d:%02d\r\n", t->tm_hour, t->tm_min, t->tm_sec); + break; // they can bail here + } + pc.putc(':'); + if (!GetNumber(2, &t->tm_min)) + continue; + pc.putc(':'); + if (!GetNumber(2, &t->tm_sec)) + continue; + else { + t->tm_mon--; // 1-12 => 0-11 + t->tm_year -= 1900; + t->tm_hour -= tzOffsetHr; + t->tm_min -= tzOffsetMin; + pc.printf("\r\n"); + // convert to timestamp and display (1256729737) + time_t seconds = mktime(t); + set_time(seconds); + break; + } + } + for (i=0; i<5; i++) { + ShowTime(tzOffsetHr, tzOffsetMin); + wait(1.0); + } +} + + /// Ethernet_Tests will attempt to test the Ethernet interface /// /// It will connect to the network - if possible, then it will @@ -340,34 +427,54 @@ } } +/// isPrint tests the passed in character for being 'printable' +/// +/// It will evaluate the character on a simple ASCII range of +/// characters 0 to 127. +/// +/// @param i is the character to test +/// @returns true if the character is in the printable set (including <space>) +/// @returns false if the character is not printable (may be control code or extended character) +/// +bool isPrint(char i) { + if (i >= ' ' && i <= '~') + return true; + else + return false; +} + /// 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 + SDFileSystem sd(p5, p6, p7, p8, "ud"); // the pinout on the mbed Cool Components workshop board + DigitalIn cardIn(p11); 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); + 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); } - fclose(fp); } } printf(" test complete!\r\n"); @@ -404,6 +511,51 @@ } } + +/// 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 +/// +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); + return result; +} + + +/// ShowCANMessage will print to the console as specified +/// +/// This format is used in other tools, and is not explained +/// here except in the code. +/// +/// @param tx indicates it is a transmit message when non-zero, receive otherwise +/// @param ch is the communication channel of this message +/// @msg is the CAN message to be shown +/// @uSec is the timestamp in microseconds +/// @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); + for (int d=0; d<8; d++) { + if (d < msg.len) + pc.printf("%02X ", msg.data[d]); + else + pc.printf(" "); + } + pc.printf("0 0 %s\r\n", FormatMicroseconds(uSec)); +} + + /// 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 @@ -416,21 +568,39 @@ CAN can2(p30, p29); char Txcounter = 0; char Rxcounter = 0; - CANMessage msg; + CANMessage tMsg; + CANMessage rMsg; + Timer timer; int i; - printf("CAN Tests:\r\n"); - for (i=0; i<10; i++) { - if (can1.write(CANMessage(1337, &Txcounter, 1))) { + pc.printf("CAN Tests:\r\n"); + i = can1.frequency(250000); + pc.printf(" can1 frequency set: %i\r\n", i); + i = can2.frequency(250000); + pc.printf(" can2 frequency set: %i\r\n", i); + timer.start(); + for (i=0; i<25; i++) { // gets a few more passes to receive the messages + + for (int x=0; x<8; x++) + tMsg.data[x] = (char)(rand()); + tMsg.data[0] = Txcounter; + tMsg.id = rand(); + tMsg.len = rand() % 9; + tMsg.type = CANData; + tMsg.format = (rand() & 1) ? CANExtended : CANStandard; + + if (Txcounter < 10 && can1.write(tMsg)) { + pc.printf(" "); + ShowCANMessage(1, 1, tMsg, timer.read_us()); Txcounter++; - printf(" Message sent: %d\r\n", Txcounter); - wait(0.05); + //wait(0.05); } - if (can2.read(msg)) { - printf(" Message received: %d\r\n", msg.data[0]); + if (can2.read(rMsg)) { Rxcounter++; + pc.printf(" "); + ShowCANMessage(0, 2, rMsg, timer.read_us()); } - wait(0.2); + wait(0.005); } if (Txcounter == Rxcounter) printf(" passed.\r\n");