diff --git a/testjig/production/electrical_test.cpp b/testjig/production/electrical_test.cpp index 6ad8813f9e440705b489575de39a1218813a1ab2..5e8d078c271f743fbd894b063dcee36af7204cba 100644 --- a/testjig/production/electrical_test.cpp +++ b/testjig/production/electrical_test.cpp @@ -23,6 +23,8 @@ #include <Arduino.h> #include "electrical_test.h" +#include "testjig.h" +#include "arm_kinetis_reg.h" float ElectricalTest::analogVolts(int pin) @@ -46,7 +48,7 @@ bool ElectricalTest::analogThreshold(int pin, float nominal, float tolerance) float upper = nominal + tolerance; if (volts < lower || volts > upper) { - target.log(target.LOG_ERROR, + target.log(LOG_ERROR, "ETEST: Analog value %d outside reference range! " "value = %.2fv, ref = %.2fv +/- %.2fv", pin, volts, nominal, tolerance); @@ -61,11 +63,12 @@ bool ElectricalTest::testOutputPattern(uint8_t bits) // Set the target's 8-bit output port to the given value, and check all analog values // Write the port all at once - target.digitalWritePort(outPin(0), bits); + if (!target.digitalWritePort(outPin(0), bits)) + return false; // Check power supply each time - if (!analogThreshold(8, 3.3)) return false; - if (!analogThreshold(9, 5.0)) return false; + if (!analogThreshold(analogTarget33vPin, 3.3)) return false; + if (!analogThreshold(analogTargetVUsbPin, 5.0)) return false; // Check all data signal levels for (unsigned n = 0; n < 8; n++) { @@ -79,7 +82,7 @@ bool ElectricalTest::testOutputPattern(uint8_t bits) bool ElectricalTest::testAllOutputPatterns() { - // Multiple output patterns + target.log(logLevel, "ETEST: Testing data output patterns"); // All on, all off if (!testOutputPattern(0x00)) return false; @@ -111,6 +114,10 @@ bool ElectricalTest::initTarget() return false; } + // Disable target USB USB pull-ups + if (!target.usbSetPullup(false)) + return false; + return true; } @@ -118,13 +125,16 @@ void ElectricalTest::setPowerSupplyVoltage(float volts) { // Set the variable power supply voltage. Usable range is from 0V to system VUSB. - const float fullScaleVoltage = 6.42; - int pwm = constrain(volts * (255 / fullScaleVoltage), 0, 255); - pinMode(10, OUTPUT); - analogWriteFrequency(10, 1000000); - analogWrite(10, pwm); + int pwm = constrain(volts * (255 / powerSupplyFullScaleVoltage), 0, 255); + pinMode(powerPWMPin, OUTPUT); + analogWriteFrequency(powerPWMPin, 1000000); + analogWrite(powerPWMPin, pwm); - delay(5); + /* + * Time for the PSU to settle. Our testjig's power supply settles very + * fast (<1ms), but the capacitors on the target need more time to charge. + */ + delay(30); } void ElectricalTest::powerOff() @@ -132,10 +142,90 @@ void ElectricalTest::powerOff() setPowerSupplyVoltage(0); } -void ElectricalTest::powerOn() +bool ElectricalTest::powerOn() { target.log(logLevel, "ETEST: Enabling power supply"); - setPowerSupplyVoltage(5.0); + const float volts = 5.0; + setPowerSupplyVoltage(volts); + return analogThreshold(analogTargetVUsbPin, volts); +} + +bool ElectricalTest::testHighZ(int pin) +{ + // Test a pin to make sure it's high-impedance, by using its parasitic capacitance + for (unsigned i = 0; i < 10; i++) { + pinMode(pin, OUTPUT); + digitalWrite(pin, i & 1); + pinMode(pin, INPUT); + if (digitalRead(pin) != (i & 1)) + return false; + } + return true; +} + +bool ElectricalTest::testPull(int pin, bool state) +{ + // Test a pin for a pull-up/down resistor + for (unsigned i = 0; i < 10; i++) { + pinMode(pin, OUTPUT); + digitalWrite(pin, i & 1); + pinMode(pin, INPUT); + if (digitalRead(pin) != state) + return false; + } + return true; +} + +bool ElectricalTest::testUSBConnections() +{ + target.log(logLevel, "ETEST: Testing USB connections"); + + // Run this test a few times + for (unsigned iter = 0; iter < 4; iter++) { + + // Start with pull-up disabled + if (!target.usbSetPullup(false)) + return false; + + // Test both USB ground connections + pinMode(usbShieldGroundPin, INPUT_PULLUP); + pinMode(usbSignalGroundPin, INPUT_PULLUP); + if (digitalRead(usbShieldGroundPin) != LOW) { + target.log(LOG_ERROR, "ETEST: Faulty USB shield ground"); + return false; + } + if (digitalRead(usbSignalGroundPin) != LOW) { + target.log(LOG_ERROR, "ETEST: Faulty USB signal ground"); + return false; + } + + // Test for a high-impedance USB D+ and D- by charging and discharging parasitic capacitance + if (!testHighZ(usbDMinusPin)) { + target.log(LOG_ERROR, "ETEST: Fault on USB D-, expected High-Z"); + return false; + } + if (!testHighZ(usbDPlusPin)) { + target.log(LOG_ERROR, "ETEST: Fault on USB D+, expected High-Z"); + return false; + } + + // Turn on USB pull-up on D+ + if (!target.usbSetPullup(true)) + return false; + + // Now D+ should be pulled up, and D- needs to still be high-Z + if (!testPull(usbDPlusPin, HIGH)) { + target.log(LOG_ERROR, "ETEST: Fault on USB D+, no pull-up found"); + return false; + } + if (!testHighZ(usbDMinusPin)) { + target.log(LOG_ERROR, "ETEST: Fault on USB D-, expected High-Z. Possible short to D+"); + return false; + } + + } + + return true; } bool ElectricalTest::runAll() @@ -145,6 +235,10 @@ bool ElectricalTest::runAll() if (!initTarget()) return false; + // USB tests + if (!testUSBConnections()) + return false; + // Output patterns if (!testAllOutputPatterns()) return false; diff --git a/testjig/production/electrical_test.h b/testjig/production/electrical_test.h index 63301e69ab09f77b96426167dd205576659be8ac..933b6cb679139e40db2ec510a49bb307ca426032 100644 --- a/testjig/production/electrical_test.h +++ b/testjig/production/electrical_test.h @@ -31,7 +31,7 @@ public: : target(target), logLevel(logLevel) {} void powerOff(); // Turn off target power supply - void powerOn(); // Set target power supply to default voltage + bool powerOn(); // Set target power supply to default voltage bool runAll(); // All normal electrical tests @@ -39,6 +39,8 @@ private: ARMKinetisDebug ⌖ int logLevel; + const int LOG_ERROR = ARMDebug::LOG_ERROR; + // Pin number for an LED output int outPin(int index) { return target.pin(target.PTD, index); @@ -46,8 +48,11 @@ private: void setPowerSupplyVoltage(float volts); float analogVolts(int pin); - bool analogThreshold(int pin, float nominal, float tolerance = 0.20); + bool analogThreshold(int pin, float nominal, float tolerance = 0.30); bool testOutputPattern(uint8_t bits); bool testAllOutputPatterns(); + bool testUSBConnections(); + bool testHighZ(int pin); + bool testPull(int pin, bool state); bool initTarget(); }; diff --git a/testjig/production/production.ino b/testjig/production/production.ino index 0acc06010086fe9684be2f5b63f692ab57975b18..713f94693a7dd4c6301c4b121e15e4ceedc0daa3 100644 --- a/testjig/production/production.ino +++ b/testjig/production/production.ino @@ -24,26 +24,36 @@ void setup() Serial.begin(115200); } -void loop() +void waitForButton() { + // Wait for button press, with debounce + Serial.println(""); Serial.println("--------------------------------------------"); Serial.println(" Fadecandy Test Jig : Press button to start"); Serial.println("--------------------------------------------"); Serial.println(""); - // Keep target power supply off when we're not using it - etest.powerOff(); - while (digitalRead(buttonPin) == LOW); - delay(20); // Debounce delay + delay(20); while (digitalRead(buttonPin) == HIGH) { // While we're waiting, blink the LED to indicate we're alive digitalWrite(ledPin, (millis() % 1000) < 150); } digitalWrite(ledPin, HIGH); +} - etest.powerOn(); +void loop() +{ + // Keep target power supply off when we're not using it + etest.powerOff(); + + // Button press starts the test + waitForButton(); + + // Turn on the target power supply + if (!etest.powerOn()) + return; // Start debugging the target if (!target.begin()) diff --git a/testjig/production/testjig.h b/testjig/production/testjig.h index 1a0837000d6190141f58f133f2aef5dc52d73e74..288409495a70ad1692480d93230f56dbede31241 100644 --- a/testjig/production/testjig.h +++ b/testjig/production/testjig.h @@ -2,7 +2,22 @@ #pragma once +// UI static const unsigned buttonPin = 2; static const unsigned ledPin = 13; + +// Debug port static const unsigned swclkPin = 3; static const unsigned swdioPin = 4; + +// Electrical testing +static const unsigned powerPWMPin = 10; +static const unsigned usbDMinusPin = 5; +static const unsigned usbDPlusPin = 6; +static const unsigned usbShieldGroundPin = 7; +static const unsigned usbSignalGroundPin = 8; +static const unsigned analogTarget33vPin = 8; +static const unsigned analogTargetVUsbPin = 9; + +// Analog constants +static const float powerSupplyFullScaleVoltage = 6.42;