Serial Flash and SPI


Most Embedded systems need non-volatile memory. Non-Volatile memory is used to save software program, user configuration settings etc.
Non-Volatile: data is preserved even without power supply.
Flash Memory is enhanced version of EEPROM (Electrically erasable and programmable Read only memeory). Flash Memories consume less power with currents as low as microamps in standby and millamps in active modes.

Types of EEPROMS


There are two types of Flash memories available based on the layout and interfacing. NOR flash (Parallel EEPROM) and NAND flash (Serial EEPROM). As the names suggest NOR flash is accessed with a parallel interface and NAND is accessed over a serial interface. Hence Serial flash would have simpler hardware when compared to their counterparts in Parallel flash. At the same, the overall performance would be slower than that of the Parallel flash, considering that only one bit is transferred at a time. But, the writes are generally faster to the serial flash than the parallel flash.

Interfacing EEPROMS


Parallel flash in the system, would be referenced as additional memory. In other words, in a microcontroller, the processor would treat it as its own memory space. Using C, the location in the parallel flash could be accessed by pointers.
Serial flash cannot be accessed in the same way. In order to access serial flash, they must be interfaced to the chip (microcontroller) in a specific fashion. There are different technologies used to interface a serial EEPROM.


Serial EEPROM


Synchronous Communications:


Serial EEPROM works on synchronous interface. That means both the chip (communicating with the serial EEPROM) and the serial EEPROM use a common clock. The clock is usually defined by the master (chip).

Voltage and Capacity


Serial Flashes are available in different ranges of voltages and capacity. For smaller capacity (256K) of Flashes, the flash is divided into integral multiple of blocks. As the capacity increases (for medium and large flashes of more than 1M capability), the flash memory would be quantified into different ranges, Bytes, Pages and Sectors. Each page would consist so many (for example 256, 512) bytes.

Interfacing Serial EEPROM


The following are three of those types (of my knowledge). Microwire, SPI (Serial Peripheral interface) and I2C (called I square C). The following describes the SPI. For more information on interfacing serial flash with the other technologies refer to the following article by Jan Axelson published in Circuit Cellar. http://www.lvr.com/files/seeprom.pdf.

SPI


Introduction

SPI (Serial Peripheral Interface) is the full-duplex, synchronous serial data mechanism that is used to communicate among different chips on IC. SPI follows Master-Slave concept. During a data transfer, the system that controls the data flow would act as Master and the other one called the Slave.

Signals


SPI works on four signals. Two signals for read and write, a clock signal and a chip select signal. The names of these signals differ for master and slave. MOSI (Master out slave in) on Master is connected to SI(Serial In) on slave MISO (Master In Slave Out) on Master is connected to SO (Serial Out) on slave SCLK (Master clock) is connected to the slave clock. CS(Chip select on the master) can contain upto 4 slaves. 4 SPI slaves could be connected over the Chip select signal.

Clock


Depending on Clock Polarity and clock phase for receiving and transmiting data, SPI operates in four modes. SPI mode 0 to 3. SPI device's data sheets would specify the operating modes supported by the devices. For example most of the atmel flash memories support SPI mode 0 and 3. In breif, the mode specifies which edge controls the data transfer. Clocks for different modes are as shown in the figure. The timing diagrams are not to scale and they are used to explain the modes.
As shown in the figure,
SPI Mode 0: Data is shifted on rising edge and shifted out on falling edge. Initial clock level is low.
SPI Mode 1: Data is shifted on falling edge and shifted out on rising edge. Initial clock level is low.
SPI Mode 2: Data is shifted on rising edge and shifted out on falling edge. Initial clock level is high.
SPI Mode 3: Data is shifted on falling edge and shifted out on rising edge. Initial clock level is high.


Algorithms for data transfer

Algorithms for data transfers could be developed easily without spending lot of time, if the following things are kept in mind. 1. Flash memory provides internal buffers for data transfers.
2. Algorithms would be different for programming a whole page or programming individual bytes. Serial flash gives the flexibility to program byte wise. Auto Erase operation is provided. That means when ever the flash is programmed, an erase operation need not be given explicitly. 3. Make sure the mappings are taken care. The flash considers that every page starts from location that is an integral multiple of 2 power 10.
For Example consider the flash with 528 bytes per page. The second page should start from 529th byte onwards (which is true physically). But when writing the commands to the flash first page would start at 0, second page would start at 1024, third page would start at 2048 and so on. So to access 530th byte (which is the 2 byte of the 2 page), the location that would be specified to flash in command would be 1026(1024+2).

Programming serial Flash by emulating SPI over parallel port


Parallel Port


There are so many documents on the web that provide the information about parallel port and its programming. Here, I will just discuss emulating SPI over parallel port. For more information on parallel port refer to the follwoing links.
Parallel port has 25(DB25) pins. Out of the 25 pins
8 pins are tied to data
4 pins are tied to control
5 pins are tied to Status
and 8 pins are connected to ground. There are three registers assigned for the LPT1 (Windows 98/95). The registers can be checked out by going into settings->Control Panel->System->Device Manager->Ports (COM and LPT)->LPT1->Properties->Resoureces. In general the base address assigned for parallel port is 378h.
Base +0 (0x378)woule be data register
Base +1 (0x379) is status register
Base +2 (0x37a) is control register.


By default, the parallel port is configured as bi-directional. The configuration could be changed, if required, so that the parallel port can be configured as only output. The 5th bit in the control register corresponds to this configuration. Try this.
At Dos Prompt
C:> debug
i 0x37a
EC
That says the fifth bit in the control register is set to 1. The configuration could be set to "only output" by setting that bit to 0.

SPI Over Parallel Port

The following explanation considers c language development. In order to communicate with Serial EEPROM over SPI, 4 signals are required. MOSI, MISO, SCLK, CS. Out of which three are inputs(MOSI, SCLK, CS) to the Serial flash and one output(MISO).
Select three data pins (bits in the data register) for the three inputs and one status pin (Output). For modes 0 and 3 data would be shifted in on rising edge and out on falling edge. Reverse is the case with modes 1 and 2. Only one case would be considered here.. say modes 0 and 3. ON every clock cycle a bit would be shifted in on rising edge and a bit would be shifted out on falling edge. This means a byte is read and written in 8 clock cycles. In windows 98/DOS, the parallel port could be accessed directly over 0x378. But this is not the case with windows NT. Instead, VC++ provides the api necessary to access and manipulate on ports. Emulate the signals using macros or functions.
Example
Consider MOSI as Data0 pin. Bit 0 in data register.

#define MOSI(state) /
U8 Temp; /
Temp = *(0x378); /
Temp &= FE; /
Temp |= state; /

All the inputs follow the same pattern. The output should be considered differently though. The output should be inverted once it is read.
Once all the signals are emulated, a byte transfer could be considered as follows Note: Flash is accessed only when the chip select is set to low.

READ SPI_BYTE_TRANSFER(BYTE)
{
SPI_CS(0); /* Set the chip select to low */
SPI_CLK(0);
for(i=0; i<8; i++)
delay;
SPI_CLK(1); /* Rising Edge */
SPI_MOSI((BYTE >> 1) & (0x01)); delay

SPI_CLK(0);
ReadBit = SPI_MISO();
READ |= (ReadBit << i);


return READ;
}
1