Bit banging is creating the whole series of pulses in software, instead of relying on a piece of hardware inside the microcontroller.
Many microcontrollers have a hardware SPI, and then all you have to do is write a byte to the output register, and the SPI controller will shift the data out, and at the same time receive data from the slave. You can get an interrupt when the transfer is complete, and then read the received data.
But some microcontrollers don't have the SPI hardware on board and then you have to simulate it by doing everything manually. SPI has a number of different modes, I'll use this pulse diagram as an example:
So while a dedicated SPI controller takes care of all the pulses, data shifting and timing, when bit-banging you have to take every action yourself:
Make Slave Select low
Short delay
Do 8 times
Make the SCK (Serial Clock) pin low
Make the MOSI (Master-Out-Slave-In) pin high or low depending on bit 7 of the data
Add brief delay
Make the SCK output high
Read MISO (Master-In-Slave-Out) pin
Shift received data left, and shift the bit just read in as bit 0
Add brief delay
Shift the data byte 1 bit left
Make Slave Select high again
Bit-banging SPI is relatively simple, the code for bit-banging I2C for instance will be more complex, and you'll need a timer somehow if you want to bit-bang the UART protocol.
It turns out that my cheap junky logic analyzer was putting some noise on the MISO line, so the received data gets slightly shifted.
When I unplugged its MISO line - the data is now fine. Truly unbelievable...
Best Answer
SPI memories on AVR microcontrollers are not memory mappable: you can't tell the ATMEGA that you have connected a memory, and let it map the device in the memory area, and take care of all the commands required by the read/write operations.
Instead, you have to manually create your functions readByte/writeByte, to read and write a single byte to the FRAM through the SPI.
Then, you create the functions readBuffer/writeBuffer, and pass the pointer of that structure, and the sizeof that structure (and the destination address in the FRAM, of course).
Still, working directly on an external SPI memory will be extremely slow. A better idea is to work on a copy in the internal RAM, and then adopt one of the following strategies:
In any case, when the device is powered, you must copy the data from the FRAM back to the internal RAM.
EDIT:
As you said, you have already the functions that write and read a byte to/from the FRAM. You just need to create a function that read a larger amount of data, and writes a larger amount of data. Then you can do the following:
Then to read the structure:
To write: