SRAM interface question

With the help of others, I've been able to interface a 64K SRAM to an UNO. I've written some code that allows me to break up a long into four byte and write it to the SRAM. I'm also able to read in the four bytes and convert to a long.

My questions:

  1. What is the best way to keep track of the addresses and etc of where the longs are stored in the SRAM?
  2. How does the compiler keep track of or knows "long var1" is at address 0x1234?
  3. Advice on what I didn't know enough about to be able to ask?

It all depends on what you intend using the RAM for.
It may be that “struct” are the natural construct to be written to the RAM.

I’m afraid that the compiler knows nothing about your extra RAM, so keeping track of what is where is up to you.

AWOL:
It all depends on what you intend using the RAM for.
It may be that "struct" are the natural construct to be written to the RAM.

I don't know if it is possible or not, but it would be nice to be able to handle the variables the way the UNO does in RAM

I'm afraid that the compiler knows nothing about your extra RAM, so keeping track of what is where is up to you.

That is the reason I'm asking the question - would it be hard to write code to handle it the way the compiler does or is that to hard and would take up too much of my 32K program memory - keeping track of ints and floats would be nice but thinking it was use up more of my 32K of program memory so I'll just store everything as a long (64K/4 = 16K longs) ...any advice on how to handle this issue?

As I said, it really depends on how you intend using the RAM.
You may just want to treat it as a big array, in which case, handling it is simple, just a read primitive and a write primitive.

AWOL:
As I said, it really depends on how you intend using the RAM.
You may just want to treat it as a big array, in which case, handling it is simple, just a read primitive and a write primitive.

But how do I keep track of "var1" starts at location 0xABCD without using up too much of my UNOs ram
Maybe my question should be: is it possible to use external ram somewhat like UNOs ram

Since AWOL is probably tired of saying it, it all depends on how you intend to use the RAM, which you haven't really said. I think you are implying you want to use it as an extension of the 328's RAM with total random access.

If that is the case, Don't use a screwdriver when you need a hammer.

Use a processor that had more ram or supports external RAM chips, like the 2560.

Sorry about that and thank you both AWOL and James C4S, yes, I would like to use it as an extension of the 328's RAM with total random access - unfortunately, presently, I only have the availability of a screwdriver

I don't believe you can use your Uno external SRAM the way you want as the compiler will never treat it as SRAM available for directly reading and writing of variables and/or arrays. The mega1280/2560 chips do have internal hardware support for adding external SRAM and can have the compiler be able to access it directly, but perhaps only as heap memory?

Rugged Circuits is the only firm I know of that sells external SRAM modules that allows one to add such memory but again only for mega boards not 328P based boards. Here is a link that also has some example code to show you how it can make that memory available to the compiler code you write.

http://ruggedcircuits.com/html/megaram.html

Lefty

retrolefty:
I don't believe you can use your Uno external SRAM the way you want as the compiler will never treat it as SRAM available for directly reading and writing of variables and/or arrays. The mega1280/2560 chips do have internal hardware support for adding external SRAM and can have the compiler be able to access it directly, but perhaps only as heap memory?

Rugged Circuits is the only firm I know of that sells external SRAM modules that allows one to add such memory but again only for mega boards not 328P based boards. Here is a link that also has some example code to show you how it can make that memory available to the compiler code you write.

http://ruggedcircuits.com/html/megaram.html

Lefty

WOW, that's pretty cool and only $20 - thanks for the info but presently, I don't have an available mega

For what everyone says: it's not a good idea but if I wanted to try it, what would be the best way to do it (advice)

Obviously, I should have asked these question before I bought the SRAM ...but it was fun getting the SRAM to work

sparkfuntoday:
Maybe my question should be: is it possible to use external ram somewhat like UNOs ram

If you are sufficiently clever and determined, I expect it would be possible to persuade the linker to create a new data section representing your external RAM. You would need to build your sketch outside of the IDE. You would need to provide a mechanism to dereference addresses within that section - perhaps uses approaches similar to the ones Arduino uses to access PROGMEM - and transfer the data to/from the local SRAM in order to use it. If you understand what all that means, you have a cat-in-hell's chance of making it work; if you're scratching your head at the unfamiliar terms, I suggest you file this under "Yeah, maybe possible in theory, but realistically it would be extraordinarily difficult and perhaps impossible". In any case it is not feasible to make the external RAM behave transparently as if it was local RAM.

PeterH:

sparkfuntoday:
Maybe my question should be: is it possible to use external ram somewhat like UNOs ram

If you are sufficiently clever and determined, I expect it would be possible to persuade the linker to create a new data section representing your external RAM. You would need to build your sketch outside of the IDE. You would need to provide a mechanism to dereference addresses within that section - perhaps uses approaches similar to the ones Arduino uses to access PROGMEM - and transfer the data to/from the local SRAM in order to use it. If you understand what all that means, you have a cat-in-hell's chance of making it work; if you're scratching your head at the unfamiliar terms, I suggest you file this under "Yeah, maybe possible in theory, but realistically it would be extraordinarily difficult and perhaps impossible". In any case it is not feasible to make the external RAM behave transparently as if it was local RAM.

Thank you PeterH, yes, I was scratching my head at some of those terms - so clearly, I do not have the skills to make it happen

Many thanks to everyone for your help and patients with me not making myself as clear as I should have

Short of rewriting the compiler, I should think you can do something similar to how the
compiler works. Only you will be accessing the external RAM, so you don't have to worry
about where the compiler might be stuffing various program parts, and trying to stay
out of its way.

In a regular sketch [forgetting about malloc's], you have to "specifically" declare all of
your variables like so, and the compiler/linker will then allocate fixed memory locations
for them. Then, you use them symbolically in your program.

int var1, var2;
long lvar3, lvar4;

So, one thing that might work is to use something like the following, where the
values are offsets into external RAM,

#define eiVAR1 0
#define eiVAR2 2
#define elVAR3 4
#define elVAR4 8
....

Then, simply write a couple of functions for reading/writing the eRAM locations,

void ei_write( int eaddr, int data ) { ... }
int ei_read( int eaddr ) { ... }
void el_write( int eaddr, long data ) { ... }
long el_read( int eaddr ) { ... }

accessing:

ei_write( eiVAR1, var1 );
lvar3 = el_read( elVAR3 );

The only real difference between what this does and what the compiler/linker
does is you're creating your own hard fixed addresses.

Note - I just made this up on the fly, so don't ask how well it works, ;-).

EDIT: you can also make the blocks relocatable,

#define BLOCK1 100
#define SZINT 2
#define SZLNG 4

#define eiVAR1 BLOCK1
#define eiVAR2 BLOCK1+SZINT
#define elVAR3 BLOCK1+SZINT
#define elVAR4 BLOCK1+SZLNG

Obviously, you have to be a little careful to get the increments correct, based
upon the previous declaration.

thank you oric_dan, I can really use this info

Good, let us know how it works out. I just made it up on the spot the
other day, :-). I have those chips too, and need to get to using them
one of days.

Here’s some more thoughts:

Option 1:
If you are only storing one data type, you do not need offsets. Just the number of the variable you wish to store / retrieve, and its size.
To get the nth variable, just multiply (n-1) x .

eg:

#define varSize 4
...
long startAddress;
...
for (int i = 0; i< 100; i++) 
{
    startAddress := (i-1) * varSize;
    // get the four bytes and combine them
}

Option 2:
If you are going to store different types, set up areas in SRAM where they are stored and have a memory offset into each area, and keep track of how many you stored.

#define varSize 4
#define longOffset  2^15    // store longs in the second half of SRAM
...
long startAddress;
...
for (int i = 0; i< 100; i++) 
{
    startAddress := longOffset + (i-1) * varSize;
    // get the four bytes and combine them
}

My C++ is very rusty to non-existent but I reckon you could create a class with an internal data structure as required, then overload the = operator with code that read/writes to the external RAM so at the source level it almost looks like normal code. Like

XM.some_var = 1234;


Rob

Graynomad:
My C++ is very rusty to non-existent but I reckon you could create a class with an internal data structure as required, then overload the = operator with code that read/writes to the external RAM so at the source level it almost looks like normal code. Like

XM.some_var = 1234;


Rob

The variable would have to know where free space was, and once used, return it to free space. An array of such variable might help with that.

Yes, I'm assuming static data so knowing where free space is would not be an issue.

A "variable" could use offsetof() to determine it's location in the struct and therefore the XM, but this approach would need functions for the various variable types and I don't know how you would differentiate between variables of the same type.

It would get very messy I think unless a C++ guru can advise otherwise.

Certainly an array of same types would be a lot easier.

And of course if you can fit the struct in internal RAM there's little point in having the external RAM in the first place :slight_smile:


Rob

Between oric_dan and aarondc’s comments (thank you both) I’ve been able to get the following to work:

  for(int i=0; i<7; i++) {
    unsigned int rw_addr = exIntAry0+(i*sizeof(int));
    writeRamInt(i, rw_addr, sizeof(int));
  }

  for(int i=0; i<7; i++) {
    unsigned int rw_addr = exIntAry0+(i*sizeof(int));
    int numb = readRamInt(rw_addr, sizeof(int));
    Serial.print(F("numb= "));
    Serial.println(numb);
  }

The problem is, you have to program how many elements the array has… …any ideas on how to solve this issue?