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.
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