When the Atmel doesn't have enough memory capacity for the application, such as data logging, there are two alternatives, both of which use the SPI interface on the Atmel. One is to use a serially accessed Flash RAM, such as the M25P16, but this is only available up to a capacity of 16Mbits (2MBytes) in an easy to solder package which is probably too small. The other is to use an MMC memory card, with capacities of eg. 512Mb. I tried a 2Gb, and the particular one I tried didn't respond.
Hardware:
Have a look at this link, http://www.captain.at/electronic-atmega-mmc.php which features an ATMEGA8 running at 5V with dividers to convert the interface voltages back to 3.3V which is the voltage the MMC card requires. A better solution if the application can manage with 1K of RAM (eg direct write to sectors on the card, but not using the FAT filesystem) is to use the newer ATMEGA168, which will work at 3.3 volts. Alternatively, use the ATMEGA32L which will work at 3.3 Volts. For a serial interface, use the ICL3223 in place of the MAX232 shown, this too will work at 3.3 Volts.
MMC card data:
Look at http://elm-chan.org/docs/mmc/mmc_e.html for data on the commands and http://www.retroleum.co.uk/mmc_cards.html for a more detailed description of the specific reads and writes required to talk to the MMC card. Note that after a command has been sent, there is always a 1 byte period before the device will respond, both reading from the device via SPI and writing FF to the device via SPI should have the same effect. I found that if I started polling for a command response before I had sent this extra byte, I didn't get the command response. http://elm-chan.org/fsw/ff/00index_e.html refers to a FAT file system layer, which I tried implementing in 1K RAM before running into problems of lack of memory, and switching to using an ATMEGA32 to get 2K of RAM.
Gotchas:
I tried a 2Gb MMC device. The one I tried didn't work in SPI mode. I'll try others and add details.
The command numbers are listed in decimal, but the data is typically sent in hexadecimal, with bit 6 set, so eg command 17 is sent as 51h.
I found it vital to have a function which repeatedly checked for the expected return value, and timed out after n tries. (with n something like 100) This method isn't suitabe for CMD 1 - it can take hundreds of muilliseconds to reset the card.
When reading or writing a sector, the argument to the command frame is sent as 4 bytes BUT if the read or write isn't aligned with the sector size ( typically default is 512 bytes), the command fails. In practice, with a 512 bytes sector, this means that
Send 51h,00h,00h,01h,00h,00h (Command 17,0,0,1,0,CRC) will fail (address is not a multiple of 512 bytes) whereas
Send 51h,00h,00h,02h,00h,00h (Command 17,0,0,2,0,CRC) will work fine.
