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;
char addr[4];
int i = 0, j = 0;
addr[0] = 0x1E;
addr[1] = 0x00;
addr[2] = 0x00;
addr[3] = 0x00;
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
if(addr[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
addr[j] = addr[j] << 1;
}
}
#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 addr[4];
char data[4] = {0xAA, 0x55, 0xAA, 0x55};
//unsigned int addr = 0x1E000000;
addr[0] = 0x1E;
addr[1] = 0x00;
addr[2] = 0x00;
addr[3] = 0x00;
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
if(addr[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
addr[j] = addr[j] << 1;
}
}
#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)
{
signed char cmd = READ;
int i = 0, j = 0;
char addr[4];
signed char val[32];
signed char pinState = 0;
addr[0] = 0x1E;
addr[1] = 0x00;
addr[2] = 0x00;
addr[3] = 0x00;
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
if(addr[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
addr[j] = addr[j] << 1;
}
}
#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();
Read_Page();
Write_Page();
Read_Page();
Best Answer
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.