Access to external RAM connected to a Mega2560

I have an external circuit connected to my Arduino Mega 2560. The interface on my circuit facing the Mega is a 2K X 8 static RAM, and its support chips, connected to the 36 pin (18 X 2) XIO connector. The XRAM feature of Mega's CPU is brought out on ports A, C, & G which are labeled digital pins 22-41. The low-order address/data lines are demux'ed with a 74AHC573 octal latch. The 5 highest-order address lines are decoded to map the RAM to start at 0x8000.

The only purpose for the Mega is to load the RAM.

The problem I have is how do I get my program to access the external RAM space. Ideally, I would like to somehow declare or allocate the entire space from 0x8000 to 0x87FF as a 2K array of bytes. I have not been able to dope out how to force the assignment of an address or pointer to a specific number.

Admittedly my hardware skills exceed my software expertise so any help would be much appreciated.

Regards,
Frank Hartley

I have an external RAM board for my Mega made by RuggedCircuits. This is one of their test programs:

/* This MegaRAM application is a production test that verifies that
 * all RAM locations are unique and can store values.
 *
 * Assumptions:
 *
 *   - MegaRAM plugged in to Arduino Mega 1280 or Mega 2560
 *
 * The behavior is as follows:
 *
 *   - Each one of 4 banks of 32 kbytes each is filled with a pseudorandom sequence of numbers
 *   - The 4 banks are read back to verify the pseudorandom sequence
 *   - On success, the Arduino's LED is turned on steadily, with a brief pulse off every 3 seconds
 *   - On failure, the Arduino's LED blinks rapidly
 *   - The serial port is used for status information (38400 bps)
 *
 * This software is licensed under the GNU General Public License (GPL) Version
 * 3 or later. This license is described at
 * http://www.gnu.org/licenses/gpl.html
 *
 * Application Version 1.0 -- August 2011 Rugged Circuits LLC
 * http://www.ruggedcircuits.com/html/megaram.html
 */

void setup(void)
{
  DDRD |= _BV(7); // PD7 is BANKSEL
  PORTD = 0x7F;   // Select bank 0, pullups on everything else

  /* Enable XMEM interface:

         SRE    (7)   : Set to 1 to enable XMEM interface
         SRL2-0 (6-4) : Set to 00x for wait state sector config: Low=N/A, High=0x2200-0xFFFF
         SRW11:0 (3-2) : Set to 00 for no wait states in upper sector
         SRW01:0 (1-0) : Set to 00 for no wait states in lower sector
   */
  XMCRA = 0x80;

  // Bus keeper, lower 7 bits of Port C used for upper address bits, bit 7 is under PIO control
  XMCRB = _BV(XMBK) | _BV(XMM0);
  DDRC |= _BV(7);
  PORTC = 0x7F; // Enable pullups on port C, select bank 0

  // PL7 is RAM chip enable, active high. Enable it now, and enable pullups on Port L.
  DDRL |= _BV(7);
  PORTL = 0xFF;

  // Open up a serial channel
  Serial.begin(115200);

  // Enable on-board LED
  pinMode(13, OUTPUT);

  Serial.println("Memory test begins ...");
}

// Blink the Arduino LED quickly to indicate a memory test failure
void blinkfast(void)
{
  digitalWrite(13, HIGH);
  delay(100);
  digitalWrite(13, LOW);
  delay(100);
}

// Provide information on which address failed. Then, sit in an infinite loop blinking
// the LED quickly.
void fail(uint8_t *addr, uint8_t expect, uint8_t got)
{
  Serial.print("At address "); Serial.print((uint16_t)addr);
  Serial.print(" expected "); Serial.print(expect, DEC);
  Serial.print(" got "); Serial.print(got, DEC);
  Serial.println();

  while (1) {
    blinkfast();
  }
}

#define STARTADDR ((uint8_t *)0x8000)
#define COUNT (0x8000-1)

long seed=1234;

// Select one of four 32 kilobyte banks
void banksel(uint8_t bank)
{
  switch (bank) {
    case 0:
      PORTD &= ~_BV(7);
      PORTC &= ~_BV(7);
      break;

    case 1:
      PORTD &= ~_BV(7);
      PORTC |=  _BV(7);
      break;

    case 2:
      PORTD |=  _BV(7);
      PORTC &= ~_BV(7);
      break;

    default:
      PORTD |=  _BV(7);
      PORTC |=  _BV(7);
      break;
  }
}

// Fill the currently selected 32 kilobyte bank of memory with a random sequence
void bankfill(void)
{
  uint8_t *addr;
  uint16_t count;

  for (addr=STARTADDR, count=COUNT; count; addr++, count--) {
    *addr = (uint8_t)random(256);
    if ((count & 0xFFFU) == 0) blinkfast();
  }

}

// Check the currently selected 32 kilobyte bank of memory against expected values
// in each memory cell.
void bankcheck(void)
{
  uint8_t expect;
  uint8_t *addr;
  uint16_t count;

  for (addr=STARTADDR, count=COUNT; count; addr++, count--) {
    expect = random(256);
    if (*addr != expect) fail(addr,expect,*addr);
    if ((count & 0xFFFU) == 0) blinkfast();
  }
}

void loop(void)
{
  uint8_t bank;

  // Always start filling and checking with the same random seed
  randomSeed(seed);

  // Fill all 4 banks with random numbers
  for (bank=0; bank < 4; bank++) {
    Serial.print("   Filling bank "); Serial.print(bank, DEC); Serial.println(" ...");
    banksel(bank); bankfill();
  }

  // Restore the initial random seed, then check all 4 banks against expected random numbers
  randomSeed(seed);
  for (bank=0; bank < 4; bank++) {
    Serial.print("  Checking bank "); Serial.print(bank, DEC); Serial.println(" ...");
    banksel(bank); bankcheck();
  }

  // If we got this far, there were no failures
  Serial.println("Success!");
  Serial.println();

  // Keep the LED on mostly, and pulse off briefly every 3 seconds
  while (1) {
    digitalWrite(13, HIGH);
    delay(3000);
    digitalWrite(13, LOW);
    delay(500);
  }
}
// vim: syntax=cpp ai ts=2 sw=2 cindent expandtab

See if that helps.

Hi all.

I have similiar/related problem.
I have build 32kb SRam shield from here:

The supplied test sketch works without any issues! So hardware is working fine.

I now want to use this in my apple 1 emulator using code from Mike Chambers for 6502 cpu emulation.
(This is c file, not cpp).

I use same definition as in test sketch.

but I get error now:
Arduino: 1.8.1 (Windows 10), Board: "Arduino/Genuino Mega or Mega 2560, ATmega2560 (Mega 2560)"

cpu.c:76: error: 'reinterpret_cast' undeclared here (not in a function)

static volatile uint8_t RAM = reinterpret_cast<volatile uint8_t>(0x8000);

^

cpu.c:76: error: expected expression before 'volatile'

static volatile uint8_t RAM = reinterpret_cast<volatile uint8_t>(0x8000);

^

exit status 1
'reinterpret_cast' undeclared here (not in a function)


I read through various articles yesterday and today. But I can't figure out, how to change my code in a way to get that working.. :frowning:
I also tried XMEM lib.. no success..

What I want is a RAM[] array of 32768 bytes (uint8_t) in the external sram, that I can:
read with: value = RAM[address];
write with: RAM[address] = value;

I need help! I am NOT an c or c++ expert! I just try to get around.

best regards,
Peter

reinterpret_cast is a C++ thing.

In C use

static volatile uint8_t *RAM = (uint8_t*)0x8000;

Thx! It compiles now - but apple 1 emulator / 6502 interpreter hangs somehow..?

I am using this to read and write a byte to this memory:

if (address < RAM_SIZE) return(RAM[address]);

void write6502(uint16_t address, uint8_t value) {
if (address < RAM_SIZE) RAM[address] = value;

Peter

Argh!#?#!?

Now it works - but what really is bad is a bad test program, that says all is ok, but in reality it isn't ok!!!

The test program supplied at above link is using the following test:
bool test() {
for (uint16_t i = 0; i<32768; ++i) {
extmem = i & 0xFF;

  • }*
  • for (uint16_t i = 0; i<32768; ++i) {*
    _ if (extmem != (i & 0xFF))_
    * return false;*
    * }*
    * return true;*
    }
    The problem here is and was in my case, that the data value is the SAME as the lower 8-bit of the address!
    Thats a bad idea with a multiplexed data/address bus.
    Now, I had a bad 74LS373 latch - and guess what - I read back the lower 8 address bits = same as extected data value => test program said all is ok!
    That took my hours to find that out! Before that I measured all pcb traces - all ok.
    Than I modified the test program:
    bool test() {
    * for (uint16_t i = 0; i<32768; ++i) {
    _ extmem = (i+1) & 0xFF;
    }_
    for (uint16_t i = 0; i<32768; ++i) {
    _ if (extmem != ((i+1) & 0xFF))
    return false;
    }
    return true;
    }*

    Now the expected value is address+1 - and yes - now the test program reported that it failed!
    Second 74LS373 was also bad - but third one was fine and now it runs as expected.
    thx, Peter_