Come posso testare le DRAM ?

Capita di doversi cimentare nel riparare un vecchio computer o console che utilizza queste tipologie di RAM e fortunatamente ci sono dei modi che ci aiutano a trovare il banco (o più) difettoso.
Ma perché le DRAM? Queste RAM dinamiche (da cui il nome) a differenza di quelle statiche hanno necessità di rinfrescare i loro dati memorizzati riscrivendoli spesso ogni tot millisecondi. I dati su queste RAM vengono memorizzati e mantenuti da una carica di un condensatore presente sulla cella di memoria, ma questo condensatore anche se non mantiene la carica per molto tempo e  se il dato viene letto la carica si esaurisce molto più rapidamente, quindi i dati devono essere riscritti sia se si legge (solo la riga letta) che periodicamente (tutti i dati presenti).
Sono state scelte queste RAM per un semplice motivo, il costo!, infatti rispetto alle SRAM questo modello richiede molti meno transistor nella costruzione quindi si possono avere RAM con molta più capacità al costo di una SRAM 4 volte più piccola.

Beh, ora vediamo come risolvere i problemi di queste memorie, spesso a causa del deterioramento dei condensatori non mantengono più i dati scritti e un metodo per trovare la RAM guasta può essere quello di posizionarne un’altra sopra di essa (metodo Piggyback), in questo modo i dati verranno scritti e memorizzati sulle due ram e se un dato va perso sulla ram difettosa, sarà recuperato da quella buona.
Attenzione che non è un sistema infallibile, infatti se la RAM ha dei pin in corto, quella messa sopra non riuscirà a passare nessun dato sulla linea in corto, inoltre se ci sono più banchi difettosi il computer potrebbe non partire (se non ha un sistema per controllare la RAM all’avvio) e non saprete quale altra è rovinata.

Questo metodo invece richiede di costruirsi un piccolo tester basato su Arduino, lo schema si trova in rete ed è molto semplice, il funzionamento non fa altro che scrivere e leggere diverse volte per verificare che i dati siano effettivamente corretti.
Potete trovare le informazioni e lo schema a questo link: https://forum.defence-force.org/viewtopic.php?t=1699

Attenzione: il firmware di Arduino su questo link contiene un bug su l’indirizzamento della memoria, vi potrà dare ram ok mentre invece è guasta, perché non testa tutti gli indirizzi. Seguite la guida fino in fondo dove metterò il link con il firmware corretto!

Visto che lo schema è disegnato a mano, ve ne metto uno rifatto seguendo l’originale (by ISS):

Tester per 4164

 

#include <SoftwareSerial.h>

#define DI 15 // PC1
#define DO 8 // PB0
#define CAS 9 // PB1
#define RAS 17 // PC3
#define WE 16 // PC2

#define XA0 18 // PC4
#define XA1 2 // PD2
#define XA2 19 // PC5
#define XA3 6 // PD6
#define XA4 5 // PD5
#define XA5 4 // PD4
#define XA6 7 // PD7
#define XA7 3 // PD3
#define XA8 14 // PC0

#define M_TYPE 10 // PB2
#define R_LED 11 // PB3
#define G_LED 12 // PB4

#define RXD 0 // PD0
#define TXD 1 // PD1

#define BUS_SIZE 9 // impostare a 7 se utilizzato per 4116

volatile int bus_size;

//SoftwareSerial USB(RXD, TXD);

const unsigned int a_bus[BUS_SIZE] = {
XA0, XA1, XA2, XA3, XA4, XA5, XA6, XA7, XA8
};

void setBus(unsigned int a) {
int i;

//funzione corretta

for (i = 0; i < bus_size; i++) {

    if (bitRead(a, i)==1) {
      digitalWrite(a_bus[i], HIGH);
    } else {
      digitalWrite(a_bus[i], LOW);
    }
  }
}

void writeAddress(unsigned int r, unsigned int c, int v) {
/* row */
setBus(r);
digitalWrite(RAS, LOW);

/* rw */
digitalWrite(WE, LOW);

/* val */
digitalWrite(DI, (v & 1)? HIGH : LOW);

/* col */
setBus(c);
digitalWrite(CAS, LOW);

digitalWrite(WE, HIGH);
digitalWrite(CAS, HIGH);
digitalWrite(RAS, HIGH);
}

int readAddress(unsigned int r, unsigned int c) {
int ret = 0;

/* row */
setBus(r);
digitalWrite(RAS, LOW);

/* col */
setBus(c);
digitalWrite(CAS, LOW);

/* get current value */
ret = digitalRead(DO);

digitalWrite(CAS, HIGH);
digitalWrite(RAS, HIGH);

return ret;
}

void error(int r, int c)
{
unsigned long a = ((unsigned long)c << bus_size) + r;
digitalWrite(R_LED, LOW);
digitalWrite(G_LED, HIGH);
interrupts();
Serial.print(” FAILED $”);
Serial.println(a, HEX);
Serial.flush();
while (1)
;
}

void ok(void)
{
digitalWrite(R_LED, HIGH);
digitalWrite(G_LED, LOW);
interrupts();
Serial.println(” OK!”);
Serial.flush();
while (1)
;
}

void blink(void)
{
digitalWrite(G_LED, LOW);
digitalWrite(R_LED, LOW);
delay(1000);
digitalWrite(R_LED, HIGH);
digitalWrite(G_LED, HIGH);
}

void green(int v) {
digitalWrite(G_LED, v);
}

void fill(int v) {
int r, c, g = 0;
v %= 1;
for (c = 0; c < (1<<bus_size); c++) {
green(g? HIGH : LOW);
for (r = 0; r < (1<<bus_size); r++) {
writeAddress(r, c, v);
if (v != readAddress(r, c))
error(r, c);
}
g ^= 1;
}
blink();
}

void fillx(int v) {
int r, c, g = 0;
v %= 1;
for (c = 0; c < (1<<bus_size); c++) {
green(g? HIGH : LOW);
for (r = 0; r < (1<<bus_size); r++) {
writeAddress(r, c, v);
if (v != readAddress(r, c))
error(r, c);
v ^= 1;
}
g ^= 1;
}
blink();
}

void setup() {
int i;

Serial.begin(9600);
while (!Serial)
; /* wait */

Serial.println();
Serial.print(“DRAM TESTER “);

for (i = 0; i < BUS_SIZE; i++)
pinMode(a_bus[i], OUTPUT);

pinMode(CAS, OUTPUT);
pinMode(RAS, OUTPUT);
pinMode(WE, OUTPUT);
pinMode(DI, OUTPUT);

pinMode(R_LED, OUTPUT);
pinMode(G_LED, OUTPUT);

pinMode(M_TYPE, INPUT);
pinMode(DO, INPUT);

digitalWrite(WE, HIGH);
digitalWrite(RAS, HIGH);
digitalWrite(CAS, HIGH);

digitalWrite(R_LED, HIGH);
digitalWrite(G_LED, HIGH);

// se si usa la memoria 4146 non inserire questo ciclo if (digitalRead)… else ..

if (digitalRead(M_TYPE)) {
/* jumper not set – 41256 */
bus_size = BUS_SIZE;
Serial.print(“256Kx1 “);
} else {
/* jumper set – 4164 */
bus_size = BUS_SIZE – 1;
Serial.print(“64Kx1 “);
}

Serial.flush();

digitalWrite(R_LED, LOW);
digitalWrite(G_LED, LOW);

noInterrupts();
for (i = 0; i < (1 << BUS_SIZE); i++) {
digitalWrite(RAS, LOW);
digitalWrite(RAS, HIGH);
}
digitalWrite(R_LED, HIGH);
digitalWrite(G_LED, HIGH);
}

void loop() {
interrupts(); Serial.print(“.”); Serial.flush(); noInterrupts(); fillx(0);
interrupts(); Serial.print(“.”); Serial.flush(); noInterrupts(); fillx(1);
interrupts(); Serial.print(“.”); Serial.flush(); noInterrupts(); fill(0);
interrupts(); Serial.print(“.”); Serial.flush(); noInterrupts(); fill(1);
ok();
}

Realizzate questo circuito, programmate Arduino scaricando il file .ino oppure incollando il codice sorgente su di un progetto vuoto dell’ide di Arduino e programmatelo. Con Arduino connesso ad un pc potete vedere tramite il monitor seriale lo stato del test, oppure visibile tramite i led.

Funzionamento

1. Selezionate il tipo di RAM (4164 – 41256) tramite il jumper, se inserito si testano le 4164, se lasciato aperto si testano le 41256.
2. Inserite la RAM da testare facendo attenzione al corretto orientamento (una inversione di polarità vi brucerà il banco di RAM).
3. Alimentate Arduino che comincerà subito il test, attendete poco più di un minuto e se tutto ok si accenderà il led verde, in caso contrario il rosso.

Un altro esempio di DRAM tester (4164) V1

Questa è una realizzazione di un tester simile a quello descritto sopra.

E’ la prima versione che ho realizato e legge solo le 4164-256.
Il funzionamento è leggermente diverso e funziona con un display e due pulsanti, uno per scegliere il tipo di RAM da testare e uno per iniziare il test.

I vari test effettuati sono visibili nel display come il risultato finale.
In questo caso l’alimentazione della memoria viene gestita da Arduino che provvederà ad alimentare la RAM appena  si inizia il test e la interromperà quando finito. Una piccola sicurezza per evitare di bruciare la RAM se viene posizionata al contrario.

Ora tocca a voi inventare un vostro tester personale o più semplicemente usare quello descritto.

IL CODICE PRECEDENTE NON VA BENE PER QUESTO TESTER.

Ed ora ecco il nuovo tester adatto anche per le 4116 V2

Il funzionamento è identico al precedente solo che queste memorie hanno bisogno oltre della 5v anche di una 12v e una tensione negativa di -5v, oltre ad avere una linea di indirizzi in meno.
In questo schema del nuovo tester ho utilizzato un lcd per visualizzare lo stato (come in quello sopra) ed ho aggiunto la parte di alimentazione per il chip 4116 (qui ho usato uno switch a 4 poli per gestire le due memorie, ma ne basta uno da 3 canali, uno l’ho usato per segnalare ad Arduino il tipo di memoria selezionata, anzi anche da 2 poli se non vogliamo controllare lo stato da arduino).
Le resistenze da 47ohm sono opzionali, le ho usate come test e anche con queste si riesce a testare correttamente la memoria ed in caso di pin in corto sulla dram si evita di bruciare i pin di Arduino.
L’alimentazione deve essere di circa 14V per avere una 12V corretta, altrimenti è possibile utilizzare un dc-dc per portare la 5V di Arduino a 12V ed alimentare la ram così da evitare i 7812 e 7805 ed i diodi di protezione. Nella nuova revisione infatti ho alimentato tutto tramite la 5V di Arduino, portata a 12V con un booster e a -5V con il 7660.
 
Attenzione! non usate questo schema con il codice precedente, la piedinatura è differente sia per la gestionre della ram che per i pulstanti e lcd.

Ed Infine la versione 4

Questo utilizza l’alimentazione di Arduino e la eleva a 12V con il booster, pin più crea la -5V con il 7660.
Lo switch è stato sostituito con un jumper per evitare di spostarlo accidentalmente e bruciare la ram, per il resto è simile alla versione 3.

Anche questo PCB non è compatibile con il sorgente originale.

Se vuoi costruitlo visita la mia pagina github

Beta testing versione 4.2

non finisce qui, in test la versione software per testare anche le ram 4532 (parte alta o bassa), con finale animato! 🙂
Questa versione esegue 5 test:
1 scrittua-lettura bit 0-1
2 scrittura-lettura tutti 1
3 solo scrittura tutti 1
4 solo lettura attesi tutti 1 (verifica che i dati vengano mantenuti)
5 scrittura-lettura tutti 0