S25FL032P NOR Flash interfacing over SPI Bit Banging

spi

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.

enter image description here

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
}

enter image description here

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();
}

enter image description here

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();
}

enter image description here

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.

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);
    }
}

unsigned char SPI_ReadByte(void)
{
    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;
}