# S25FL032P NOR Flash interfacing over SPI Bit Banging

I am working with a NOR Flash memory chip: S25FL032P manufactured by Spansion. I am interfacing the NOR Flash over SPI by Bit Banging as I am going to use the dedicated SPI engine for some other peripheral.

I am not able to Read/Write the data over the Flash for some reason. I am attaching the screenshots from the datasheets and what I have so far implemented. Looking at the post, it might look too much of the data to find something that has gone wrong with the implementation, but thats the way I could think of. Any help is greatly appreciated.

void Write_Enable(void)
{
signed char cmd = WRITE_ENABLE;
int i = 0;
SPI_CS_H();
for(i = 0; i < 8; i++)
{
_delay_us(100);
//Make SCK Low
SPI_SCK_H();
//Make the MOSI (Master-Out-Slave-In) pin high or low depending on bit 7 of the data
if(cmd & 0x80)
{
SPI_MOSI_H();
#ifdef DEBUG_O
uart_print("1");
#endif // DEBUG
}
else
{
SPI_MOSI_L();
#ifdef DEBUG_O
uart_print("0");
#endif // DEBUG
}

_delay_us(100);
//Make SCK High
SPI_SCK_L();
//Left shift the next data to send the next bit
cmd = cmd << 1;
}
SPI_CS_L();
#ifdef DEBUG_O
uart_print(" ");
#endif // DEBUG
}


void Sector_Erase(void)
{
signed char cmd = SECTOR_ERASE;
int i = 0, j = 0;

SPI_CS_H();

for(i = 0; i < 8; i++)
{
_delay_us(100);
//Make SCK Low
SPI_SCK_H();
//Make the MOSI (Master-Out-Slave-In) pin high or low depending on bit 7 of the data
if(cmd & 0x80)
{
SPI_MOSI_H();
#ifdef DEBUG_O
uart_print("1");
#endif // DEBUG
}
else
{
SPI_MOSI_L();
#ifdef DEBUG_O
uart_print("0");
#endif // DEBUG
}

_delay_us(100);
//Make SCK High
SPI_SCK_L();
//Left shift the next data to send the next bit
cmd = cmd << 1;
}
#ifdef DEBUG_O
uart_print(" ");
#endif // DEBUG

for( j = 0; j < 3 ; j++)
{
for(i = 0; i < 8; i++)
{
_delay_us(100);
//Make SCK Low
SPI_SCK_H();
//Make the MOSI (Master-Out-Slave-In) pin high or low depending on bit 7 of the data
{
SPI_MOSI_H();
#ifdef DEBUG_O
uart_print("1");
#endif // DEBUG
}
else
{
SPI_MOSI_L();
#ifdef DEBUG_O
uart_print("0");
#endif // DEBUG
}

_delay_us(100);
//Make SCK High
SPI_SCK_L();
//Left shift the next data to send the next bit
}
}
#ifdef DEBUG_O
uart_print(" ");
#endif // DEBUG
SPI_CS_L();
}


void Write_Page(void)
{
signed char cmd = PAGE_PROG;
int i = 0, j = 0;
char data[4] = {0xAA, 0x55, 0xAA, 0x55};

SPI_CS_H();
for(i = 0; i < 8; i++)
{
_delay_us(100);
//Make SCK Low
SPI_SCK_H();
//Make the MOSI (Master-Out-Slave-In) pin high or low depending on bit 7 of the data
if(cmd & 0x80)
{
SPI_MOSI_H();
#ifdef DEBUG_O
uart_print("1");
#endif // DEBUG
}
else
{
SPI_MOSI_L();
#ifdef DEBUG_O
uart_print("0");
#endif // DEBUG
}

_delay_us(100);
//Make SCK High
SPI_SCK_L();
//Left shift the next data to send the next bit
cmd = cmd << 1;
}
#ifdef DEBUG_O
uart_print(" ");
#endif // DEBUG
for( j = 0; j < 3 ; j++)
{
for(i = 0; i < 8; i++)
{
_delay_us(100);
//Make SCK Low
SPI_SCK_H();
//Make the MOSI (Master-Out-Slave-In) pin high or low depending on bit 7 of the data
{
SPI_MOSI_H();
#ifdef DEBUG_O
uart_print("1");
#endif // DEBUG
}
else
{
SPI_MOSI_L();
#ifdef DEBUG_O
uart_print("0");
#endif // DEBUG
}

_delay_us(100);
//Make SCK High
SPI_SCK_L();
//Left shift the next data to send the next bit
}
}

#ifdef DEBUG_O
uart_print(" ");
#endif // DEBUG
for( j = 0; j < 4 ; j++)
{
for(i = 0; i < 8; i++)
{
_delay_us(100);
//Make SCK Low
SPI_SCK_H();
//Make the MOSI (Master-Out-Slave-In) pin high or low depending on bit 7 of the data
if(data[j] & 0x80)
{
SPI_MOSI_H();
#ifdef DEBUG_O
uart_print("1");
#endif // DEBUG
}
else
{
SPI_MOSI_L();
#ifdef DEBUG_O
uart_print("0");
#endif // DEBUG
}

_delay_us(100);
//Make SCK High
SPI_SCK_L();
//Left shift the next data to send the next bit
data[j] = data[j] << 1;
}
}
#ifdef DEBUG_O
uart_print(" ");
#endif // DEBUG
SPI_CS_L();
}


void Read_Page(void)
{
int i = 0, j = 0;
signed char val[32];
signed char pinState = 0;

SPI_CS_H();

for(i = 0; i < 8; i++)
{
_delay_us(100);
//Make SCK Low
SPI_SCK_H();
//Make the MOSI (Master-Out-Slave-In) pin high or low depending on bit 7 of the data
if(cmd & 0x80)
{
SPI_MOSI_H();
#ifdef DEBUG_O
uart_print("1");
#endif // DEBUG
}
else
{
SPI_MOSI_L();
#ifdef DEBUG_O
uart_print("0");
#endif // DEBUG
}

_delay_us(100);
//Make SCK High
SPI_SCK_L();
//Left shift the next data to send the next bit
cmd = cmd << 1;
}
#ifdef DEBUG_O
uart_print(" ");
#endif // DEBUG
for( j = 0; j < 3 ; j++)
{
for(i = 0; i < 8; i++)
{
_delay_us(100);
//Make SCK Low
SPI_SCK_H();
//Make the MOSI (Master-Out-Slave-In) pin high or low depending on bit 7 of the data
{
SPI_MOSI_H();
#ifdef DEBUG_O
uart_print("1");
#endif // DEBUG
}
else
{
SPI_MOSI_L();
#ifdef DEBUG_O
uart_print("0");
#endif // DEBUG
}

_delay_us(100);
//Make SCK High
SPI_SCK_L();
//Left shift the next data to send the next bit
}
}
#ifdef DEBUG_O
uart_print(" ");
#endif // DEBUG

for(i = 0; i < 32; i++)
{
for(j = 0; j < 8 ; j++)
{
_delay_us(100);

//Make SCK Low
SPI_SCK_L();
//Make the MOSI (Master-Out-Slave-In) pin high or low depending on bit 7 of the data

pinState = CHECK_BIT(SPI_PIN, SPI_MISO_BIT);
if( pinState )
{
#ifdef DEBUG_O
uart_print("1");
#endif // DEBUG
}
else
{
#ifdef DEBUG_O
uart_print("0");
#endif // DEBUG
}
_delay_us(100);
//Make SCK High
SPI_SCK_H();
val[i] = (pinState << j)|(val[i]);
}
}
#ifdef DEBUG_O
uart_print(" ");
#endif // DEBUG
SPI_CS_L();
}


The order in which they are called is:

    Write_Enable();
Sector_Erase();
Write_Page();

• How long do you wait between erase and write I don't see you ever checking status bits to know it's done. An erase can take a while. Also not sure on this part but you may need to set wren again before the write – Some Hardware Guy May 19 '15 at 12:52

Got it to work. I wasn't clocking the device right. The issue had roots in timings. I was following the sequence exactly well, but the way I implemented, synchronization was too theoretical and needed to manage rise time and fall times more practically than the way I comprehended from the timing diagrams.

Following are the functions to Read and Write a byte.

void SPI_Transmit(unsigned char data)
{

// Does not explicitly selects and deselects the Slave
// device since this function may be called up upon
// requirement for sending more than one byte.

int i = 0;

// send data in bits
for (i = 0; i < 8; i++)
{
SPI_SCK_L();
_delay_us(2);

// Consider leftmost bit, set line high if bit is 1, low if bit is 0
if(data & 0x80)
{
SPI_MOSI_H();
}
else
{
SPI_MOSI_L();
}

_delay_us(5);
// Pulse clock to indicate that bit value should be read
SPI_SCK_H();
// shift byte left so next bit will be leftmost
data <<= 1;
_delay_us(5);
}
}

{
int i = 0;
unsigned char data = 0x00;

for(i = 0; i < 8; i++)
{
data = (CHECK_BIT(SPI_PIN, SPI_MISO_BIT) & (1<<SPI_MISO_BIT) );
_delay_us(10);
SPI_SCK_H();
_delay_us(10);
SPI_SCK_L();
data = data << 1;
_delay_us(2);
}
return data;
}