0
\$\begingroup\$

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();
\$\endgroup\$
  • \$\begingroup\$ 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 \$\endgroup\$ – Some Hardware Guy May 19 '15 at 12:52
0
\$\begingroup\$

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;
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.