SRAM Tester with Arduino Mega for retrocomputers - Page 1
Forum section: electronics / repair

author: mauroh
author_rank: Frequent Contributor
timestamp: January 03, 2019, 04:25:06 pm
content: SRAM Tester with Arduino Mega for TRS-80 Model 100 , Olivetti M10 , Kyotronic KC-85 , NEC PC-8201A ...If you happen to have one of this PC to repair or you need to test its SRAM Modules, with this simple ArduinoMega adapter and code you will be able to identify which IC in the module is bad and recover the module replacing only the bad ICAttached you will find the instruction to build it yourself and the Arduino Code.Please let me know if you will find this usefull or if you have a better simpler method to identify the bad IC in a module (I tried using a TL866 programmer with no luck).This tester is so flexible and it can be adapted to test several kind of ICMauroPs: I already posted this on another thread explaining how I repaired my Olivetti M10 but I hope this will help someone.https://www.eevblog.com/forum/repair/challenge-learn-something-new-from-something-really-old/Code: Arduino Mega SRAM Tester for TRS-80 Model 100 , Olivetti M10 , Kyotronic KC-85 , NEC PC-8201A ...Code://*******************************************************************************// ArduinoMega SRAM Tester for// TRS-80 Model 100 / Olivetti M10 / ...// Author: Mauro Pintus// Date : 2018 12 21// Ver : 1.7//*******************************************************************************// ___________SRAM PINs___________// | |// | _MEGA GPIO_ | TOP View Bottom View// | | | | _____U______ _____U______// A07  (D22) (+5V)  VCC | __u___ | .| ______ |.// A06  (D24) (D25)  A08 | | | | .| | | |.// A05  (D26) (D27)  A09 | | | | .| | | |.// A04  (D28) (D29)  _WE | | IC1 | | .| | IC4 | |.// A03  (D30) (D31)  CE4 | | | | .| | | |.// A02  (D32) (D33)  A10 | |______| | .| |__n___| |.// A01  (D34) (D35)  CEX | | .| |.// A00  (D36) (D37)  IO7 | __u___ | .| ______ |.// IO0  (D38) (D39)  IO6 | | | | .| | | |.// IO1  (D40) (D41)  IO5 | | | | .| | | |.// IO2  (D42) (D43)  IO4 | | IC2 | | .| | IC3 | |.// GND  (---) (D45)  IO3 | | | | .| | | |.// CE1  (D46) (---)  GND | |______| | .| |__n___| |.// CE2  (D48) (D49)  CE3 |____________| .|____________|.////If the test will FAIL some pin could be shorted to GND or to VCC//so all pins will be set as input to prevent damage to the Arduino//A small resistor (150 Ohm) between each Arduino GPIO and memory pin//should prevent any damage to the Arduino.#define pinCE1 46#define pinCE2 48#define pinCE3 49#define pinCE4 31#define pinCEX 35#define pin_WE 29#define pinA00 36#define pinA01 34#define pinA02 32#define pinA03 30#define pinA04 28#define pinA05 26#define pinA06 24#define pinA07 22#define pinA08 25#define pinA09 27#define pinA10 33#define pinIO0 38#define pinIO1 40#define pinIO2 42#define pinIO3 45#define pinIO4 43#define pinIO5 41#define pinIO6 39#define pinIO7 37#define max_addr 0x7ff// Configuration variables// Fill = 0 the tester will read the memory without writing on it// Fill = 1 the tester will test each cell of the memoryint Fill = 1;// Verb = 0 the tester will print only the test results// Verb = 1 the tester will print on the serial port all the memory contentint Verb = 1;uint8_t ctrl_pins[] = { pinCE1, pinCE2, pinCE3, pinCE4, pinCEX, pin_WE };uint8_t addr_pins[] = { pinA00, pinA01, pinA02, pinA03, pinA04, pinA05,pinA06, pinA07, pinA08, pinA09, pinA10 };uint8_t inout_pins[] = { pinIO0, pinIO1, pinIO2, pinIO3,pinIO4, pinIO5, pinIO6, pinIO7 };int failed = 0;int PassFail[]= {0,0,0,0};void setup(){Serial.begin(115200);Serial.println(F("\n*****************************************"));Serial.println(F("ArduinoMega SRAM Tester for"));Serial.println(F("TRS-80 Model 100 / Olivetti M10 / ..."));Serial.println(F("Author: Mauro Pintus"));Serial.println(F("Date : 2018 12 21"));Serial.println(F("Ver : 1.7"));Serial.println(F("*****************************************\n"));Serial.println(F(" ___________SRAM PINs___________ "));Serial.println(F(" | |"));Serial.println(F(" | _MEGA GPIO_ | TOP View Bottom View "));Serial.println(F(" | | | | _____U______ _____U______ "));Serial.println(F("A07  (D22) (+5V)  VCC | __u___ | .| ______ |."));Serial.println(F("A06  (D24) (D25)  A08 | | | | .| | | |."));Serial.println(F("A05  (D26) (D27)  A09 | | | | .| | | |."));Serial.println(F("A04  (D28) (D29)  _WE | | IC1 | | .| | IC3 | |."));Serial.println(F("A03  (D30) (D31)  CE4 | | | | .| | | |."));Serial.println(F("A02  (D32) (D33)  A10 | |______| | .| |__n___| |."));Serial.println(F("A01  (D34) (D35)  CEX | | .| |."));Serial.println(F("A00  (D36) (D37)  IO7 | __u___ | .| ______ |."));Serial.println(F("IO0  (D38) (D39)  IO6 | | | | .| | | |."));Serial.println(F("IO1  (D40) (D41)  IO5 | | | | .| | | |."));Serial.println(F("IO2  (D42) (D43)  IO4 | | IC2 | | .| | IC4 | |."));Serial.println(F("GND  (---) (D45)  IO3 | | | | .| | | |."));Serial.println(F("CE1  (D46) (---)  GND | |______| | .| |__n___| |."));Serial.println(F("CE2  (D48) (D49)  CE3 |____________| .|____________|."));Serial.println();}void checkPins(){int readback,index,i;String text;for (index = 0; index <= 1; index++){if (index == 0) text="HIGH "; else text="LOW ";for (i = 0; i < sizeof(ctrl_pins); i++){if (index == 0) pinMode(ctrl_pins, INPUT_PULLUP);else { pinMode(ctrl_pins, OUTPUT);digitalWrite(ctrl_pins, LOW);}readback = digitalRead(ctrl_pins);if (readback != index) {if (Verb==1) Serial.println("Check: Ctrl pin " + String(i, DEC) + " " + text +"PASS");pinMode(ctrl_pins, OUTPUT);digitalWrite(ctrl_pins, HIGH);} else {if (Verb==1) Serial.println("Check: Ctrl pin " + String(i, DEC) + " " + text +"FAIL");pinMode(ctrl_pins, INPUT);failed++;}}if (Verb==1) Serial.println();//set address pins as outputfor (i = 0; i < sizeof(addr_pins); i++){if (index == 0) pinMode(addr_pins, INPUT_PULLUP);else { pinMode(addr_pins, OUTPUT);digitalWrite(addr_pins, LOW);}if (readback != index) {if (Verb==1){if (i<10)Serial.println("Check: Addr pin " + String(i, DEC) + " " + text +"PASS");else Serial.println("Check: Addr pin " + String(i, DEC) + " " + text +"PASS");}} else {if (Verb==1){if (i<10)Serial.println("Check: Addr pin " + String(i, DEC) + " " + text +"FAIL");else Serial.println("Check: Addr pin " + String(i, DEC) + " " + text +"FAIL");}pinMode(addr_pins, INPUT);failed++;}}if (Verb==1) Serial.println();//set I/O pins as inputfor (i = 0; i < sizeof(inout_pins); i++){if (index == 0) pinMode(inout_pins, INPUT_PULLUP);else { pinMode(inout_pins, OUTPUT);digitalWrite(inout_pins, LOW);}if (readback != index) {if (Verb==1)Serial.println("Check: I/O pin " + String(i, DEC) + " " + text +"PASS");pinMode(inout_pins, INPUT_PULLUP);} else {if (Verb==1)Serial.println("Check: I/O pin " + String(i, DEC) + " " + text +"FAIL");pinMode(inout_pins, INPUT);failed++;}}if (Verb==1) Serial.println();}if (Verb==0){if (failed == 0) Serial.println(F("Check pins PASS\n"));else Serial.println(F("Check pins FAIL\n"));}}void setAddress(int address){for (int i = 0; i < sizeof(addr_pins); i++){digitalWrite(addr_pins, ((address >> i) & 1));}}void writeData(uint8_t data, int IC){int pinCEn;switch (IC) {case 1:pinCEn=pinCE1;break;case 2:pinCEn=pinCE2;break;case 3:pinCEn=pinCE3;break;case 4:pinCEn=pinCE4;break;}digitalWrite(pin_WE, LOW);digitalWrite(pinCEn, LOW);digitalWrite(pinCEX, LOW);for (int i = 0; i < sizeof(inout_pins); i++){pinMode(inout_pins, OUTPUT);digitalWrite(inout_pins, ((data >> i) & 1));}digitalWrite(pin_WE, HIGH);digitalWrite(pinCEn, HIGH);digitalWrite(pinCEX, HIGH);}int readData(int IC){int pinCEn;switch (IC) {case 1:pinCEn=pinCE1;break;case 2:pinCEn=pinCE2;break;case 3:pinCEn=pinCE3;break;case 4:pinCEn=pinCE4;break;}digitalWrite(pin_WE, HIGH);digitalWrite(pinCEn, LOW);digitalWrite(pinCEX, LOW);delayMicroseconds(1);uint8_t readback=0;for (int i = 0; i < sizeof(inout_pins); i++){pinMode(inout_pins, INPUT_PULLUP);readback = readback | ((digitalRead(inout_pins) << i));}digitalWrite(pinCEn, HIGH);digitalWrite(pinCEX, HIGH);return readback;}void test(int Fill, int Verb){if (Fill==0) Serial.println(F("Dump Entire Memory without writing on it"));else Serial.println(F("Test Entire Memory"));int Addr,index;uint8_t Data[]={0x55,0xAA}; //Data Fill 01010101,10101010uint8_t readback;int tab=0;int IC;PassFail = 1;PassFail = 1;PassFail = 1;PassFail = 1;for (IC=1; IC <= 4; IC++){for (index=0; index <= 1; index++){if ((Fill==0)&&(index==1)) break;Serial.print("IC"+String(IC)+" Content");if (Fill==1) Serial.println(" after filling it with 0x" + String(Data,HEX));else Serial.println();for (Addr=0; Addr <= max_addr; Addr++){if((tab==0)&&(Verb==1)){if(Addr<=0xF) Serial.print("00");else if(Addr<=0xFF) Serial.print("0");Serial.print(Addr,HEX);Serial.print(" ");}setAddress(Addr);if (Fill==1) writeData(Data,IC);readback = readData(IC);if ((Fill==1)&&(Verb==1)){if (readback == Data) Serial.print(" ");else{Serial.print("x");failed++;PassFail[IC-1]=0;}}else if ((Fill==1)&&(Verb==0)){if (readback != Data){failed++;PassFail[IC-1]=0;}}else if ((Fill==0)&&(Verb==1)) Serial.print(" ");if (Verb==1){if(readback<=0xF) Serial.print("0");Serial.print(readback,HEX);tab++;if(tab==32){tab=0;Serial.println();}}}if (Verb==1) Serial.println();}}if (Verb==0) Serial.println();}void loop(){checkPins();if (failed == 0){digitalWrite(LED_BUILTIN, HIGH);unsigned long duration = millis();test(Fill,Verb);duration = millis() - duration;Serial.println("Duration: " + String(duration/1000, DEC)+"S");}for (int IC=1; IC <= 4; IC++){if (PassFail[IC-1]) Serial.println("IC"+String(IC)+" PASS");else Serial.println("IC"+String(IC)+" FAIL");}if (failed > 0){Serial.println("Result: FAIL (" + String(failed, DEC) + ")");digitalWrite(LED_BUILTIN, LOW);}else{Serial.println("Result: PASS");}while(1);}

author: Armadillo
author_rank: Super Contributor
timestamp: January 03, 2019, 05:09:44 pm
content: Aside from functional testing, if you can include dynamic testing, that would be best, example rise time fall time bus access time etc....Ram is unlike PROM, speed without error is essential in Ram testing.Mega if I am not wrong, the clock speed is at 16Mhz.Maybe STM32 at 168Mhz or higher or custom sample circuit?

author: mauroh
author_rank: Frequent Contributor
timestamp: January 04, 2019, 08:06:07 am
content: Thank you for the suggestion, however since the SRAM modules of this old computers are made with 4 IC, the main goal was to identify which IC was preventing the PC to boot and fix at least one module out of 2.The followikng was the test result of one of my SRAM modules, replacing IC1 and IC2 I restored it and gained 8K of free RAM, who need that GByte ot TByte rubbish!!!___________SRAM PINs_______| || _MEGA GPIO_ | TOP View Bottom View| | | | _____U______ _____U______A07  (D22) (+5V)  VCC | __u___ | .| ______ |.A06  (D24) (D25)  A08 | | | | .| | | |.A05  (D26) (D27)  A09 | | | | .| | | |.A04  (D28) (D29)  _WE | | IC1 | | .| | IC3 | |.A03  (D30) (D31)  CE4 | | | | .| | | |.A02  (D32) (D33)  A10 | |______| | .| |__n___| |.A01  (D34) (D35)  CEX | | .| |.A00  (D36) (D37)  IO7 | __u___ | .| ______ |.IO0  (D38) (D39)  IO6 | | | | .| | | |.IO1  (D40) (D41)  IO5 | | | | .| | | |.IO2  (D42) (D43)  IO4 | | IC2 | | .| | IC4 | |.GND  (---) (D45)  IO3 | | | | .| | | |.CE1  (D46) (---)  GND | |______| | .| |__n___| |.CE2  (D48) (D49)  CE3 |___________| .|____________|.Check pins PASSTest Entire MemoryIC1 Content after filling it with 0x55IC1 Content after filling it with 0xaaIC2 Content after filling it with 0x55IC2 Content after filling it with 0xaaIC3 Content after filling it with 0x55IC3 Content after filling it with 0xaaIC4 Content after filling it with 0x55IC4 Content after filling it with 0xaaDuration: 5SIC1 FAILIC2 FAILIC3 PASSIC4 PASSResult: FAIL (8192)Mauro

author: Armadillo
author_rank: Super Contributor
timestamp: January 04, 2019, 09:15:28 am
content: For such static failure, module swap technique would yield the same result and save X numbers of days.For dynamic failure where bits failure only occurred at near peak RAM speed, this device may confused user eternally.I thought to highlight this when they used it.

author: mauroh
author_rank: Frequent Contributor
timestamp: January 04, 2019, 01:23:36 pm
content: Mot probably I'm missing the point here:The PC that use this kind of OLD SRAM modules have a maximum clock speed of 2.46MHzLooking in the TC5518BF datasheet, at best the read cycle time is 200ns and I guess this PC are accessing it way slower (1MHz MAX)Have you seen some of this retrocomputers failing because of a slow SRAM? Is there a recognizable behaviour?Unfortunately I was not able to easily find this kind of replacement modules so I did my best to recover at least one module out of two and I thought this could be the case for someone else struggling to repair his/her beloved old PC.Mauro

author: Armadillo
author_rank: Super Contributor
timestamp: January 04, 2019, 02:00:43 pm
content: Quote from: mauroh on January 03, 2019, 04:25:06 pmQuote from: mauroh on January 04, 2019, 01:23:36 pmNow is a fair qualification of the limits. I am satisfied.Quote from: mauroh on January 03, 2019, 04:25:06 pmModule swap, then for individual IC, by pin resistance measurement and comparison [for static defect that crashed the computer].

author: Armadillo
author_rank: Super Contributor
timestamp: January 04, 2019, 02:42:01 pm
content: Suggestion;The program should include clock selection routines for really really slow RAM devices in case the access time exceed really old device limits or should at least adjust itself to suit the devices under test example [not to exceed device access time limits.]In this case, because you have written it in arduino language with hidden opcodes, the access is by itself, slowed enough for it to work for this device.Also the fuse bids settings should be described in case others are not at its default.Thanks.

author: mauroh
author_rank: Frequent Contributor
timestamp: January 04, 2019, 04:11:54 pm
content: Quote from: Armadillo on January 04, 2019, 02:00:43 pmIn this specific modules all the 4 IC are in parallel but the CS pin.Unfortunately none of my IC have different resistance to VCC or GND, I was really stuckA short to GND or to VCC (diode protection shorted...) in the address lines , IO data bus or control pins (but the CS) will cause all the module to fail.In this case my code first it sets all the arduino pins to INPUT_PULLUP and verify if some pin is stuck to GND.Then it briefly set it all to LOW and if a read back will return some pins stuck to VCC it will revert all pins to INPUT and exit right away.Most probably a small series resistor on each line between the arduino and the memory module will prevent any damage to the arduino pins during testing.Thank you for all the advice and the suggestion of the clock selection, really appreciated!!Mauro