I'm using an ATmega8515 microcontroller for a one-off hobby project. This chip has an external memory interface which can directly address 64 kilobytes of external SRAM.
For my project I need more than 64 KB, so I'm supplementing this address space by manually bank-switching between four banks of 64 KB each. This bank-switching is achieved by using two normal GPIO pins as additional address lines. This gives me a grand total of 256 KB of external SRAM.
So far so good. I've wired up the first 128 KB onto the main board and I'm planning to have the second 128 KB on a plug-in expansion PCB, that I can add later on.
So, to be clear, I have Bank 0
and Bank 1
populated on the board and Bank 2
and Bank 3
do not exist yet. Circuitry is as described in the above datasheet.
I'd like my project to be able to automatically detect how much SRAM is available, so I've written a function that exercises the SRAM by writing a pattern of data to each bank in turn and then reads it back again and displays it over a UART which I can read using Minicom under Linux.
Bank 0
and Bank 1
both work as expected, and I'm reading out the same data that I stored there.
But I am seeing some weird results when attempting to access the nonexistent Bank 2
and Bank 3
. Since those chips are not present in the circuit yet, I was expecting to read back random garbage from those addresses since there would not be any SRAM chip to drive the data bus.
Perfect results from Banks 0 and 1...
Bank0[0x260]: 0x00
Bank0[0x261]: 0x01
Bank0[0x262]: 0x02
Bank0[0x263]: 0x03
Bank1[0x260]: 0x40
Bank1[0x261]: 0x41
Bank1[0x262]: 0x42
Bank1[0x263]: 0x43
Peculiar, yet somehow highly stable and consistent results from absent Banks 2 and 3...
Bank2[0x260]: 0x60
Bank2[0x261]: 0x61
Bank2[0x262]: 0x62
Bank2[0x263]: 0x63
Bank3[0x260]: 0x60
Bank3[0x261]: 0x61
Bank3[0x262]: 0x62
Bank3[0x263]: 0x63
The data read back from the non-existent addresses is not glitchy or noisy in any way. It's rock-solid and repeatable.
So I notice that the 8-bit values being read from the phantom RAM are identical to the low byte of the address (A7..A0) which is being latched by a 74HC573 chip.
What is happening here?
I understand that the low byte of the address is shared with the data lines and are controlled by the 74HC573. So if there is no SRAM chip present to drive the data bus then the data lines will be floating, effectively.
How come the data lines appear to "remember" their voltage state from immediately before they were tri-stated by the 74HC573? The ATmega8515 will be reading the data a few nanoseconds after the data bus is tri-stated - could this state be retained through some stray capacitance in the wiring?
All this said, I don't think there is actually anything malfunctioning here—I am attempting to access chips that are not there—which is obviously "undefined behaviour".
It just strikes me as interesting how the results are so very consistent.
Further information:
Here is my XMEM feature initialisation:
//Set wait states for UPPER sector to the maximum (slowest possible)
MCUCR |= (1 << SRW10);
EMCUCR |= (1 << SRW11);
//Set wait states for LOWER sector to the maximum (slowest possible)
EMCUCR |= (1 << SRW01) & (1 << SRW00);
//Enable the XMEM interface (p. 29, Mega8515 datasheet)
MCUCR |= (1 << SRE);
With many thanks to @TomCarpenter, the problem is solved...
Writing each byte in my 256KB XMEM address space to be the bit-wise NOT of the low byte of its own address causes any absent SRAM to reveal itself.
In other words, writing ~0x73
into address 0x0573
forces the data to be different to the low-byte of the address when the SRAM is present in that location.
When there is no SRAM present, the data read back from the SRAM is the same as the low-byte of the address, likely because of stray capacitance in the wiring.
I can now reliably detect present or absent SRAM chips!
Here's my new output from the terminal...
Bank0[0x260]: 0x9f //SRAM present
Bank0[0x261]: 0x9e //SRAM present
Bank0[0x262]: 0x9d //SRAM present
Bank0[0x263]: 0x9c //SRAM present
Bank1[0x260]: 0x9f //SRAM present
Bank1[0x261]: 0x9e //SRAM present
Bank1[0x262]: 0x9d //SRAM present
Bank1[0x263]: 0x9c //SRAM present
Bank2[0x260]: 0x60 // SRAM MISSING
Bank2[0x261]: 0x61 // SRAM MISSING
Bank2[0x262]: 0x62 // SRAM MISSING
Bank2[0x263]: 0x63 // SRAM MISSING
Bank3[0x260]: 0x60 // SRAM MISSING
Bank3[0x261]: 0x61 // SRAM MISSING
Bank3[0x262]: 0x62 // SRAM MISSING
Bank3[0x263]: 0x63 // SRAM MISSING
XMBK
) of theSFIOR
register set to 1? \$\endgroup\$