00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <avr/pgmspace.h>
00021 #include <avr/io.h>
00022 #include <avr/eeprom.h>
00023
00024
00025
00026 #include "ArduinoTestSuite.h"
00027
00028
00029 #include "WProgram.h"
00030 #include "HardwareSerial.h"
00031 #include "pins_arduino.h"
00032
00033
00034 #include "avr_cpunames.h"
00035
00036 #if defined(USART3_RX_vect)
00037 #define SERIAL_PORT_COUNT 4
00038 #elif defined(USART1_RX_vect)
00039 #define SERIAL_PORT_COUNT 2
00040 #else
00041 #define SERIAL_PORT_COUNT 1
00042 #endif
00043
00044
00045
00046
00047
00048 enum
00049 {
00050 ATS_Manufacturer = 1,
00051 ATS_CPU,
00052 ATS_GCC_version,
00053 ATS_LIBC_version,
00054 ATS_CompiledDate,
00055 ATS_TestSuiteName,
00056 ATS_FreeMemory,
00057
00058
00059 };
00060 unsigned long gTestStartTime;
00061 short gTagIndent;
00062 int gYotalErrors;
00063 int gTestCount;
00064
00065
00066
00067 prog_char gTextMsg_Manufacturer[] PROGMEM = "MANUFACTURER";
00068 prog_char gTextMsg_CPUname[] PROGMEM = "CPU-NAME";
00069 prog_char gTextMsg_GCC_VERSION[] PROGMEM = "GCC-Version";
00070 prog_char gTextMsg_AVR_LIBC[] PROGMEM = "AVR-LibC-Ver";
00071 prog_char gTextMsg_COMPILED_DATE[] PROGMEM = "Compiled-date";
00072 prog_char gTextMsg_TEST_SUITE_NAME[] PROGMEM = "Test-Suite-Name";
00073 prog_char gTextMsg_memoryUsage[] PROGMEM = "Free-memory";
00074 prog_char gTextMsg_dotdotdot[] PROGMEM = "... ";
00075 prog_char gTextMsg_ok[] PROGMEM = "ok";
00076 prog_char gTextMsg_FAIL[] PROGMEM = "FAIL";
00077 prog_char gTextMsg_spaceEqual[] PROGMEM = " = ";
00078 prog_char gTextMsg_info[] PROGMEM = "info.";
00079 prog_char gTextMsg_dashLine[] PROGMEM = "--------------------------";
00080 prog_char gTextMsg_DigitalRW[] PROGMEM = "DigitalReadWrite_";
00081 prog_char gTextMsg_PWMoutput[] PROGMEM = "PWMoutput_";
00082 prog_char gTextMsg_AnalogInput[] PROGMEM = "AnalogInput_";
00083
00084
00085 void Serial_print_P(prog_char *flashMemStr)
00086 {
00087 char theChar;
00088 int ii;
00089
00090 ii = 0;
00091 #if (FLASHEND > 0x10000)
00092 while (theChar = pgm_read_byte_far(flashMemStr + ii++))
00093 #else
00094 while (theChar = pgm_read_byte_near(flashMemStr + ii++))
00095 #endif
00096 {
00097 Serial.print(theChar);
00098 }
00099 }
00100
00101
00102 void Serial_println_P(prog_char *flashMemStr)
00103 {
00104 Serial_print_P(flashMemStr);
00105 Serial.println();
00106 }
00107
00108
00109
00110 static void ATS_PrintProperty( int propertyTagNum,
00111 char *propertyName,
00112 char *propertyValue)
00113 {
00114 char lineBuffer[64];
00115
00116 strcpy_P(lineBuffer, gTextMsg_info);
00117 switch(propertyTagNum)
00118 {
00119 case 0:
00120 strcat(lineBuffer, propertyName);
00121 break;
00122
00123 case ATS_Manufacturer:
00124 strcat_P(lineBuffer, gTextMsg_Manufacturer);
00125 break;
00126
00127 case ATS_CPU:
00128 strcat_P(lineBuffer, gTextMsg_CPUname);
00129 break;
00130
00131 case ATS_GCC_version:
00132 strcat_P(lineBuffer, gTextMsg_GCC_VERSION);
00133 break;
00134
00135 case ATS_LIBC_version:
00136 strcat_P(lineBuffer, gTextMsg_AVR_LIBC);
00137 break;
00138
00139 case ATS_CompiledDate:
00140 strcat_P(lineBuffer, gTextMsg_COMPILED_DATE);
00141 break;
00142
00143 case ATS_TestSuiteName:
00144 strcat_P(lineBuffer, gTextMsg_TEST_SUITE_NAME);
00145 break;
00146
00147 case ATS_FreeMemory:
00148 strcat_P(lineBuffer, gTextMsg_memoryUsage);
00149 break;
00150 }
00151
00152 while (strlen(lineBuffer) < 20)
00153 {
00154 strcat(lineBuffer, " ");
00155 }
00156
00157 strcat_P(lineBuffer, gTextMsg_spaceEqual);
00158 if (propertyValue != 0)
00159 {
00160 strcat(lineBuffer, propertyValue);
00161 }
00162 Serial.println(lineBuffer);
00163
00164 }
00165
00166
00167
00168
00169
00170 void ATS_begin(char *manufName, char *testSuiteName)
00171 {
00172 int freeMemory;
00173 char memoryMsg[48];
00174
00175 gYotalErrors = 0;
00176 gTestCount = 0;
00177
00178 Serial.begin(9600);
00179 delay(1000);
00180
00181 gTestStartTime = millis();
00182
00183 Serial.println();
00184 Serial.println();
00185 Serial.println();
00186
00187 ATS_PrintProperty(ATS_Manufacturer, 0, manufName);
00188 ATS_PrintProperty(ATS_CPU, 0, _AVR_CPU_NAME_);
00189 ATS_PrintProperty(ATS_GCC_version, 0, __VERSION__);
00190 ATS_PrintProperty(ATS_LIBC_version, 0, __AVR_LIBC_VERSION_STRING__);
00191 ATS_PrintProperty(ATS_CompiledDate, 0, __DATE__);
00192 ATS_PrintProperty(ATS_TestSuiteName, 0, testSuiteName);
00193
00194 freeMemory = ATS_GetFreeMemory();
00195 sprintf(memoryMsg, "%d bytes", freeMemory);
00196 ATS_PrintProperty(ATS_FreeMemory, 0, memoryMsg);
00197
00198 randomSeed(analogRead(0));
00199
00200 }
00201
00202
00203 void ATS_end()
00204 {
00205 long seconds;
00206 long milliSecs;
00207
00208
00209 Serial_println_P(gTextMsg_dashLine);
00210
00211
00212 Serial.print("Ran ");
00213 Serial.print(gTestCount);
00214 Serial.print(" tests in ");
00215
00216 seconds = millis() / 1000;
00217 milliSecs = millis() % 1000;
00218 Serial.print(seconds);
00219 Serial.print('.');
00220 Serial.print(milliSecs);
00221 Serial.print('s');
00222 Serial.println();
00223 Serial.println();
00224
00225 if (gYotalErrors == 0)
00226 {
00227 Serial.print("OK");
00228 }
00229 else
00230 {
00231 Serial.print("FAILED (failures=");
00232 Serial.print(gYotalErrors);
00233 Serial.print(")");
00234 }
00235 Serial.println();
00236
00237
00238 Serial.write(0x04);
00239 }
00240
00241
00242
00243
00244 void ATS_PrintTestStatus(char *testString, boolean passed)
00245 {
00246 int sLen;
00247
00248 Serial.print(testString);
00249 sLen = strlen(testString);
00250 while (sLen < 60)
00251 {
00252 Serial.print(' ');
00253 sLen++;
00254 }
00255 Serial_print_P(gTextMsg_dotdotdot);
00256 if (passed)
00257 {
00258 Serial_print_P(gTextMsg_ok);
00259 }
00260 else
00261 {
00262 Serial_print_P(gTextMsg_FAIL);
00263 gYotalErrors++;
00264 }
00265 Serial.println();
00266
00267 gTestCount++;
00268 }
00269
00270
00271
00272
00273
00274 int ATS_Test_DigitalPinWithHelper(uint8_t digitalPinToTest, uint8_t helperpin)
00275 {
00276 boolean passedOK;
00277 int pinValue;
00278 char testName[64];
00279 char numString[32];
00280
00281 strcpy_P(testName, gTextMsg_DigitalRW);
00282 sprintf(numString, "%02d", digitalPinToTest);
00283 strcat(testName, numString);
00284
00285 passedOK = true;
00286
00287
00288 pinMode(digitalPinToTest, OUTPUT);
00289 pinMode(helperpin, INPUT);
00290
00291 digitalWrite(digitalPinToTest, HIGH);
00292 pinValue = digitalRead(helperpin);
00293 if (pinValue != HIGH)
00294 {
00295 passedOK = false;
00296 }
00297
00298 digitalWrite(digitalPinToTest, LOW);
00299 pinValue = digitalRead(helperpin);
00300 if (pinValue != LOW)
00301 {
00302 passedOK = false;
00303 }
00304
00305
00306
00307 pinMode(digitalPinToTest, INPUT);
00308 pinMode(helperpin, OUTPUT);
00309
00310 digitalWrite(helperpin, HIGH);
00311 pinValue = digitalRead(digitalPinToTest);
00312 if (pinValue != HIGH)
00313 {
00314 passedOK = false;
00315 }
00316
00317 digitalWrite(helperpin, LOW);
00318 pinValue = digitalRead(digitalPinToTest);
00319 if (pinValue != LOW)
00320 {
00321 passedOK = false;
00322 }
00323
00324
00325 if (! passedOK)
00326 {
00327 sprintf(numString, " (helper pin=%02d)", helperpin);
00328 strcat(testName, numString);
00329 }
00330 ATS_PrintTestStatus(testName, passedOK);
00331 return(passedOK);
00332 }
00333
00334
00335 boolean ATS_Test_DigitalPin(uint8_t digitalPinToTest)
00336 {
00337 boolean passedOK;
00338 uint8_t helperpin;
00339
00340 if ((digitalPinToTest % 2) == 0)
00341 {
00342
00343 helperpin = digitalPinToTest + 1;
00344 }
00345 else
00346 {
00347
00348 helperpin = digitalPinToTest - 1;
00349 }
00350 passedOK = ATS_Test_DigitalPinWithHelper(digitalPinToTest, helperpin);
00351 return(passedOK);
00352 }
00353
00354
00355
00356
00357
00358 int ATS_TestTimer( uint8_t timerPinNumber,
00359 uint8_t inputPin,
00360 char *statusString,
00361 char *errorString)
00362 {
00363 boolean passedOK;
00364 unsigned long loopCounter;
00365 unsigned long lowCount;
00366 unsigned long highCount;
00367 unsigned long startTime;
00368 int percentLow;
00369 int percentHigh;
00370 int pinValue;
00371 char numString[48];
00372 int pwmValue;
00373
00374 pwmValue = 128;
00375 loopCounter = 0;
00376 lowCount = 0;
00377 highCount = 0;
00378 passedOK = true;
00379
00380 startTime = millis();
00381 pinMode(inputPin, INPUT);
00382 analogWrite(timerPinNumber, pwmValue);
00383 while ((millis() - startTime) < 500)
00384 {
00385 pinValue = digitalRead(inputPin);
00386 if (pinValue == HIGH)
00387 {
00388 highCount++;
00389 }
00390 else
00391 {
00392 lowCount++;
00393 }
00394 }
00395 analogWrite(timerPinNumber, 0);
00396
00397
00398 percentLow = lowCount / ((lowCount + highCount) / 100);
00399 percentHigh = highCount / ((lowCount + highCount) / 100);
00400 if ((percentLow > 45) && (percentLow < 55))
00401 {
00402 passedOK = true;
00403 }
00404 else
00405 {
00406 passedOK = false;
00407 strcat(errorString, " PWM ERROR");
00408 }
00409 sprintf(numString, " (PWM=%02d %d%% LOW %d%% HIGH)", pwmValue, percentLow, percentHigh);
00410 strcat(statusString, numString);
00411
00412 return(passedOK);
00413 }
00414
00415
00416
00417
00418 boolean ATS_Test_PWMPinWithHelper(uint8_t pwmPinToTest, uint8_t helperpin)
00419 {
00420 boolean passedOK;
00421 char testName[64];
00422 char errorString[48];
00423 char numString[8];
00424 uint8_t timerNumber;
00425
00426
00427
00428 strcpy_P(testName, gTextMsg_PWMoutput);
00429 sprintf(numString, "%02d", pwmPinToTest);
00430 strcat(testName, numString);
00431
00432 passedOK = true;
00433 errorString[0] = 0;
00434
00435
00436
00437 timerNumber = digitalPinToTimer(pwmPinToTest);
00438 if (timerNumber != NOT_ON_TIMER)
00439 {
00440 passedOK = ATS_TestTimer(pwmPinToTest, helperpin, testName, errorString);
00441 }
00442 else
00443 {
00444
00445 passedOK = false;
00446 }
00447
00448 ATS_PrintTestStatus(testName, passedOK);
00449
00450
00451 return(passedOK);
00452 }
00453
00454
00455 boolean ATS_Test_PWM_Pin(uint8_t pwmPinToTest)
00456 {
00457 boolean passedOK;
00458 uint8_t helperpin;
00459
00460 if ((pwmPinToTest % 2) == 0)
00461 {
00462
00463 helperpin = pwmPinToTest + 1;
00464 }
00465 else
00466 {
00467
00468 helperpin = pwmPinToTest - 1;
00469 }
00470 passedOK = ATS_Test_PWMPinWithHelper(pwmPinToTest, helperpin);
00471 return(passedOK);
00472 }
00473
00474
00475 #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
00476 #define kAnalogPinOffset 54
00477 #else
00478 #define kAnalogPinOffset 14
00479 #endif
00480
00481
00482
00483 boolean ATS_Test_AnalogInputWithHelper(uint8_t analogPintoTest, uint8_t helperPin)
00484 {
00485 boolean passedOK;
00486 char testName[64];
00487 char infoString[48];
00488 int analogValueHigh;
00489 int analogValueLow;
00490
00491
00492
00493 pinMode(analogPintoTest + kAnalogPinOffset, INPUT);
00494
00495 passedOK = true;
00496
00497 strcpy_P(testName, gTextMsg_AnalogInput);
00498 sprintf(infoString, "%02d", analogPintoTest);
00499 strcat(testName, infoString);
00500
00501
00502 pinMode(helperPin, OUTPUT);
00503
00504 digitalWrite(helperPin, LOW);
00505 analogValueLow = analogRead(analogPintoTest);
00506 if (analogValueLow > 100)
00507 {
00508 passedOK = false;
00509 }
00510
00511
00512 digitalWrite(helperPin, HIGH);
00513 analogValueHigh = analogRead(analogPintoTest);
00514 if (analogValueHigh < 1000)
00515 {
00516 passedOK = false;
00517 }
00518
00519
00520 sprintf(infoString, " (Low=%4d High=%4d helper pin=%d)", analogValueLow, analogValueHigh, helperPin);
00521 strcat(testName, infoString);
00522
00523 ATS_PrintTestStatus(testName, passedOK);
00524
00525 return(passedOK);
00526 }
00527
00528
00529
00530 boolean ATS_Test_AnalogInput(uint8_t analogPinToTest)
00531 {
00532 boolean passedOK;
00533 uint8_t helperpin;
00534
00535 if ((analogPinToTest % 2) == 0)
00536 {
00537
00538 helperpin = kAnalogPinOffset + analogPinToTest + 1;
00539 }
00540 else
00541 {
00542
00543 helperpin = kAnalogPinOffset + analogPinToTest - 1;
00544 }
00545 passedOK = ATS_Test_AnalogInputWithHelper(analogPinToTest, helperpin);
00546 return(passedOK);
00547 }
00548
00549
00550 #define kSerialTestBaudRate 9600
00551 #define kSerialTestDelay 3
00552
00553
00554 #if (SERIAL_PORT_COUNT > 1) && !defined(__AVR_ATmega32U4__)
00555
00556
00557 short ATS_TestSerialLoopback(HardwareSerial *theSerialPort, char *serialPortName)
00558 {
00559 char xmitChar;
00560 char rcvChar;
00561 short ii;
00562 short serialErrCt;
00563 short timeOutLoopCtr;
00564
00565
00566 serialErrCt = 1;
00567 if (theSerialPort != 0)
00568 {
00569 serialErrCt = 0;
00570 theSerialPort->begin(kSerialTestBaudRate);
00571
00572 for (ii=0; ii<150; ii++)
00573 {
00574 xmitChar = ii;
00575 theSerialPort->print(xmitChar);
00576
00577 timeOutLoopCtr = 0;
00578
00579 while (!theSerialPort->available() && (timeOutLoopCtr < kSerialTestDelay))
00580 {
00581 delay(1);
00582 timeOutLoopCtr++;
00583 }
00584
00585 if (theSerialPort->available())
00586 {
00587
00588 rcvChar = theSerialPort->read();
00589 if (rcvChar != xmitChar)
00590 {
00591 serialErrCt = 1;
00592 }
00593 }
00594 else
00595 {
00596 serialErrCt = 1;
00597 }
00598 }
00599 theSerialPort->end();
00600
00601 if (serialErrCt == 0)
00602 {
00603 ATS_PrintTestStatus(serialPortName, PASSED);
00604 }
00605 else
00606 {
00607 ATS_PrintTestStatus(serialPortName, FAILED);
00608 }
00609 }
00610
00611 return(serialErrCt);
00612 }
00613 #endif
00614
00615
00616
00617 boolean ATS_Test_EEPROM(void)
00618 {
00619 boolean passedOK;
00620 uint8_t dataByte;
00621 uint8_t dataByteRead;
00622 uint16_t dataWord;
00623 uint16_t dataWordRead;
00624 uint32_t dataLongWord;
00625 uint32_t dataLongWordRead;
00626 int addressPtr;
00627 char reportString[48];
00628
00629 passedOK = true;
00630
00631 addressPtr = random(E2END);
00632 dataByte = 0x5A;
00633 eeprom_write_byte((uint8_t *)addressPtr, dataByte);
00634 dataByteRead = eeprom_read_byte((uint8_t *)addressPtr);
00635
00636 sprintf(reportString, "EEPROM_byte_rw (addr= 0x%04X)", addressPtr);
00637 if (dataByteRead == dataByte)
00638 {
00639 ATS_PrintTestStatus(reportString, PASSED);
00640 }
00641 else
00642 {
00643 ATS_PrintTestStatus(reportString, FAILED);
00644 passedOK = false;
00645 }
00646
00647
00648
00649 addressPtr = random(E2END);
00650 dataWord = 0xA55A;
00651 eeprom_write_word((uint16_t *)addressPtr, dataWord);
00652 dataWordRead = eeprom_read_word((uint16_t *)addressPtr);
00653
00654 sprintf(reportString, "EEPROM_word_rw (addr= 0x%04X)", addressPtr);
00655 if (dataWordRead == dataWord)
00656 {
00657 ATS_PrintTestStatus(reportString, PASSED);
00658 }
00659 else
00660 {
00661 ATS_PrintTestStatus(reportString, FAILED);
00662 passedOK = false;
00663 }
00664
00665
00666
00667 addressPtr = random(E2END);
00668 dataLongWord = 0x5AA5A55A;
00669 eeprom_write_dword((uint32_t *)addressPtr, dataLongWord);
00670 dataLongWordRead = eeprom_read_dword((uint32_t *)addressPtr);
00671
00672 sprintf(reportString, "EEPROM_dword_rw (addr= 0x%04X)", addressPtr);
00673 if (dataLongWordRead == dataLongWord)
00674 {
00675 ATS_PrintTestStatus(reportString, PASSED);
00676 }
00677 else
00678 {
00679 ATS_PrintTestStatus(reportString, FAILED);
00680 passedOK = false;
00681 }
00682
00683
00684 return(passedOK);
00685 }
00686
00687
00688
00689
00690 extern unsigned int __data_start;
00691 extern unsigned int __data_end;
00692 extern unsigned int __bss_start;
00693 extern unsigned int __bss_end;
00694 extern unsigned int __heap_start;
00695 extern void *__brkval;
00696
00697
00698
00699
00700 int ATS_GetFreeMemory()
00701 {
00702 int free_memory;
00703
00704 if((int)__brkval == 0)
00705 {
00706 free_memory = ((int)&free_memory) - ((int)&__bss_end);
00707 }
00708 else
00709 {
00710 free_memory = ((int)&free_memory) - ((int)__brkval);
00711 }
00712 return free_memory;
00713 }
00714
00715