Go Down

Topic: Accedere ad una SRAM parallela (Read 2767 times) previous topic - next topic

leo72

Feb 04, 2011, 04:55 pm Last Edit: Feb 04, 2011, 05:02 pm by leo72 Reason: 1
Riesumo l'argomento perché volevo informarvi che l'altro giorno ho risolto i miei problemi!
Sono riuscito a gestire in lettura/scrittura una SRAM esterna di tipo parallelo, non una seriale a cui si può accedere tramite I2C o SPI ma una classica memoria con un bus indirizzi ed un bus dati indipendenti. Il problema che avevo era che avevo sbagliato la sintassi della libreria di lettura dei dati, il circuito era OK. Il tutto è stato realizzato con 1 chip di SRAM (ovviamente), tre 74595 ed un 74165, interfacciati ad un Arduino. La SRAM è una Cypress 7C185 da 64 Kbit (8Kx8) ma può essere usato qualunque chip, con le dovute modifiche.

Il progetto lo reputo interessante perché apre la possibilità di immagazzinare su una ordinaria RAM, con la velocità di immagazzinamento tipica di questo dispositivo, grandi quantitativi di dati facilmente gestibili. Pensate all'uso della SRAM per immagazzinare le variabili di un programma, ad esempio un array di notevoli dimensioni: basta implementare la giusta libreria (che vorrei fare) e si possono memorizzare i dati sulla memoria esterna invece che sulla limitata SRAM interna.

Questo progetto è la base per una futura espansione dell'altro mio progetto, ovvero un Arduino come GPU per la visualizzazione di informazioni su una comune TV. La RAM esterna sarebbe usata da 2 Arduini (se non gli Atmega nudi e crudi), uno che acceda in scrittura ed uno in lettura.

Chi fosse interessato, può dare un'occhiata a questo thread. Allegati trovate lo schema ed una rappresentazione su Frizting nonché una foto di un prototipo del circuito (non è l'attuale, che ho ridimensionato come numero di pin impiegati sull'Arduino, ridotti a solo 11 contro i 15 iniziali).

Il codice usato per leggere/scrivere sulla RAM è il seguente:
Code: [Select]


/* CONNECTION TEST TO A SRAM CHIP OF 8Kx8
USING 2 74595 SHIFT REGISTERS TO MANAGE THE ADDRESS,
1 74595 TO MANAGE THE DATA TO BE READ/WRITTEN INTO THE RAM
AND 1 74165 P/S SHIFT REG. TO READ DATA FROM RAM

*/
#include <EEPROM.h>

// Connecting the pins
//1st and 2nd 595
#define data1pin 2 //pin DS
#define latch1pin 3 //pin ST_CP
#define clock1pin 4 //pin SH_CP

//3rd chip 595
#define data2pin 7 //pin DS
#define latch2pin 8 //pin ST_CP
#define clock2pin 9 //pin SH_CP

//SRAM Chip
#define ram_we 5 //pin WE/ + 3rd 595 OE/
#define ram_oe 6 //pin OE/

//chip 165
#define load_data 11 //pin CP
#define set_load 12 //pin PL/
#define clock_pin 10 //pin Q7

void setup() {
   //initial pin setup

   //pin of the shift registers 1, 2 and 3: OUTPUT
   pinMode(latch1pin, OUTPUT);
   pinMode(clock1pin, OUTPUT);
   pinMode(data1pin, OUTPUT);
   pinMode(data2pin, OUTPUT);
   pinMode(clock2pin, OUTPUT);
   pinMode(latch2pin, OUTPUT);
   
   //RAM pins: OUTPUT
   pinMode(ram_we, OUTPUT);
   pinMode(ram_oe, OUTPUT);
   
   //S/r 165
   pinMode(clock_pin, OUTPUT);
   pinMode(set_load, OUTPUT);
   pinMode(load_data, INPUT);  
   
   //initialize ram
   digitalWrite(ram_oe, HIGH);
   digitalWrite(ram_we, HIGH);
   
   //set D13 for LED flashes
   pinMode(13, OUTPUT);
   
   for (unsigned int mem_address = 0; mem_address <20; mem_address++) {
       write_ram(mem_address, 0);
   }
}

void loop() {
unsigned int mem_address; //the address to be used
byte value = 3; //the value to be used

   // clear 10 locations in the SRAM and then write a sequence of numbers
   for (mem_address = 0; mem_address < 20; mem_address++) {
       write_ram(mem_address, value);
       value += 3;
   }
   delay(500);
   
   value = 255;
   //read the first 10 bytes and then write them into the uC EEPROM
   for (mem_address = 0; mem_address < 20; mem_address++) {
       value = read_ram(mem_address);
       EEPROM.write(mem_address, value);
       delay(10);
   }
   digitalWrite(13, HIGH);
   delay(3000);
   digitalWrite(13, LOW);
   
}

void write_ram(unsigned int mem_address, byte value) {
   byte hbyte, lbyte;
   
   digitalWrite(set_load, HIGH); // put the 165 pins in H.I. to prevent short circuits on the data bus
   //write the address into the shift registers 1 and 2
   digitalWrite(latch1pin, LOW);
   digitalWrite(latch2pin, LOW);
   digitalWrite(clock1pin, LOW);
   digitalWrite(clock2pin, LOW);
   hbyte = highByte(mem_address);
   lbyte = lowByte(mem_address);
   shiftOut(data1pin, clock1pin, MSBFIRST, hbyte);
   shiftOut(data1pin, clock1pin, MSBFIRST, lbyte);
   //write the value into the 3rd s/r
   shiftOut(data2pin, clock2pin, MSBFIRST, value);
   //set the address and data "visibile" on the busses
   digitalWrite(latch1pin, HIGH);
   digitalWrite(latch2pin, HIGH);
   //write to RAM
   digitalWrite(ram_we, LOW);
   digitalWrite(ram_we, HIGH);
   
   //disable all the chips
   digitalWrite(latch1pin, LOW);
   digitalWrite(latch2pin, LOW);
}

byte read_ram(unsigned int mem_address) {
byte value, hbyte, lbyte;
   
   //read the content of the byte "indirizzo"
   //write the address
   digitalWrite(latch1pin, LOW);
   digitalWrite(latch2pin, LOW);
   digitalWrite(ram_we, HIGH); //disable the 3rd 595 and tell the RAM not to write in itself
   hbyte = highByte(mem_address);
   lbyte = lowByte(mem_address);
   shiftOut(data1pin, clock1pin, MSBFIRST, hbyte);
   shiftOut(data1pin, clock1pin, MSBFIRST, lbyte);
   
   //set the address "visible" on the bus
   digitalWrite(latch1pin, HIGH);
   digitalWrite(latch2pin, HIGH);
   //prepare the 165
   digitalWrite(clock_pin, HIGH);
   digitalWrite(set_load, LOW);
   //read from RAM
   digitalWrite(ram_oe, LOW);
   //load the data from the 165
   digitalWrite(set_load, HIGH);
   digitalWrite(ram_oe, HIGH);
   value = shiftIn(load_data, clock_pin, MSBFIRST);
   digitalWrite(latch1pin, LOW);
   digitalWrite(latch2pin, LOW);
   return value;
   
}

Contiene anche l'accesso alla EEPROM dell'Atmega ma questa parte può essere omessa perché l'avevo usata solo come test per verificare che i dati scritti fossero corretti.

CrossRoads

"This project is the basis for a future expansion of my other project, which is an Arduino as the GPU to display information on a common TV. The external RAM is used by 2 Arduini (if not the Atmega naked and raw), one that accesses a read and write. "
Leo72,
I suggest you look into dualport SRAMs also.
http://www.cypress.com/?docID=24950
This will have the advantage of either processor being able to access the memory without needing the extra steps of turning the address & data buffers on/off for both sides. The BUSY line can be used to make the reading processor is accessing an address while  the writing processer is using.
You may have to search around more to find DIP part that you can use on a breadboard.
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

KrashNet

Complimenti bel lavoro... mi fuma il cervello sono a leggere il tutto ma è indubbiamente un mod bello utile!
(non so se riuscirò a farlo funzionare ma nel prossimo ordine aggiungerò comunque i 74595 e i  74165)

Ma se per esempio dovessi creare uno Shield basato su questo schema...  ci sarebbero differenze tra metterlo fra arduino e ethernetshield o metterlo alla fine sopra ai primi due?
.

Si può dare +1 solo perchè il progetto è interessante?
Comunque te lo meriti, sia per la testardagine che per come hai proceduto a realizzare la cosa cioè condividendo.

Io ricordo come è nato tutto qui sul forum, come è sfumata la possibilità di avviare codice residente in ram esterna per il 328.
Ora il prossimo passo come hai detto è quello di creare un libreria. Se ricordo questa ram ti serve per un buffer video dedicato e in questo caso forse è meglio fare delle librerie dedicate cercando di ottimizzare il codice al meglio, per te che hai già dimestichezza con l'assembley non dovrebbe essere un gran problema.

Bello mi piace.
Grazie Ciao.



AvrDudeQui front end per avrdude https://gitorious.org/avrdudequi/pages/Home

leo72

Dunque, sì: il tutto era nato dall'idea di poter realizzare un microcomputer basato sull'Atmega ma ho dovuto arrendermi alla realtà dei fatti, e cioè che un microcontrollore quale l'Atmega328 non può eseguire codice esterno alla sua memoria interna. Per cui avevo pensato ad un approccio differente: quello appunto di realizzare qualcosa di nuovo.

Di idee in giro per il web ce ne sono molte, io volevo vedere se mescolando il tutto potesse venir fuori qualcosa di interessante. Ad esempio, pensate ad un Atmega su cui giri l'interprete Bitlash e che manda i risultati invece che su un terminale virtuale ad un chip RAM: da qui un altro Atmega li preleva e li invia a video. Se al primo Atmega riesco a collegare una porta PS/2 ed una tastiera, ho costruito un terminale!  Chissà... sogni? Boh  XD

BrainBooster

CrossRoads, thank you for your advice, you're right! in case of two arduino that kind of memory could really speed up the whole job :) i didn't know them.
Belle memorie! ci puoi leggere e scrivre contemporaneamente.

leo72

#6
Feb 04, 2011, 08:43 pm Last Edit: Feb 04, 2011, 08:52 pm by leo72 Reason: 1
Dual port SRAMs are nice but have a "little" problem: they are in TQFP package, that is not as user friendly as the DIP one...

EDIT:
they have a DIP chip, but it's only 8 Kb (1 KB x 8), too small for my needs.

leo72

@KrashNet:
mi ero dimenticato della tua domanda.
Il progetto, così com'è, credo sia incompatibile con altre cose complesse per via del fatto che usa 11 pin (volendo star bassi) dell'Arduino per cui rimangono solo i 2 pin D0 e D1 (usati per le comunicazioni seriali) e quelli analogici, che non sono molti.

CrossRoads

Leo72,
I looked around, I did not see any dual port parts in DIP packages.
Sorry about that. DIP memory used to be more available.
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

leo72

Yes, they are (and more noob-friendly too  XD).
As soon as I get another Atmega328 (I have 1 chip that I used to build a replice of the Hackvision miniconsole to play Space Invaders  ^_^ ) I'll evolve my little project in a dual chip system.  ;)

Testato

molto interessante  :)
x iscrizione
- [Guida] IDE - http://goo.gl/ln6glr
- [Lib] ST7032i LCD I2C - http://goo.gl/GNojT6
- [Lib] PCF8574+HD44780 LCD I2C - http://goo.gl/r7CstH

leo72


molto interessante  :)
x iscrizione

Sarebbe stato bello se qualcuno avesse sviluppato una libreria per poter leggere/salvare variabili nella ram esterna. Ma a distanza di 1 anno è un progettino che non ha avuto molto seguito. Sicuramente anche perché una Ram parallela consuma un bel po' di pin.

uwefed

Cambio tema, solo un pochettino.
Il ATmega1280 e 2560 ha previsto di poter collegare su 2 porte (con un buffer a 8 bit) una SRAM paralella e settando i registri giusti viene considerata come RAM interna espandendo i 8KB a 64kB
Una cosa simile funziona anche con il 1280 e 2560 http://www.scienceprog.com/adding-external-memory-to-atmega128/
Ciao Uwe

leo72


Cambio tema, solo un pochettino.
Il ATmega1280 e 2560 ha previsto di poter collegare su 2 porte (con un buffer a 8 bit) una SRAM paralella e settando i registri giusti viene considerata come RAM interna espandendo i 8KB a 64kB
Una cosa simile funziona anche con il 1280 e 2560 http://www.scienceprog.com/adding-external-memory-to-atmega128/
Ciao Uwe

Vero, un utente MEGA potrebbe pensare di riprendere quel progetto e farne un qualcosa di utilizzabile.

ratto93

Se è compatibile con il mio seeeduino mega, potrei farci un pensierino, magari riesco a farci qualcosa di bello :)
http://hackaday.com/2011/09/05/upgrading-ram-in-an-arduino-mega/

http://andybrown.me.uk/ws/2011/08/28/512kb-sram-expansion-for-the-arduino-mega-design/
http://andybrown.me.uk/ws/2011/08/28/512kb-sram-expansion-for-the-arduino-mega-software/
http://andybrown.me.uk/ws/2011/08/28/512kb-sram-expansion-for-the-arduino-mega-design/
Se corri veloce come un fulmine, ti schianterai come un tuono.

Go Up