AT25SF641B: Flash Read always returning 0xFF

Hello, 

The AT25SF641B device I am having issues with is interfaced with a TMS320F28379D.

Please see C code below.  The code performs the flash operations as defined in the Operations[] array every 10ms (FlashTestStateMachine_Task() is called every 10ms.  This is verified by noticing u16FlashEraseCounter counts up to 2999 during a flash erase).

In essence, the program performs the following flash operations and then goes to the FLASH_TEST_COMPLETE_STATE.
1. enable flash writes (opcode = 0x06)

2. erase flash chip (opcode = 0x60)

3. Read the flash status (opcode = 0x05)

4. Write a byte to address 0x7FF000 (opcode = 0x02)

5 Disables flash writes (opcode = 0x04)

6 Reads the Status (opcode = 0x05)

7. Reads a byte from address 0x7FF00  (opcode = 0x03)

The Flash Status is always reading three zeros and the flash read is always reading 0xFF. 

What am I doing wrong?


Enable Flash Writes:

Flash Erase:

Flash Write (Zoomed out and then Zoomed in):

Flash Read (Zoomed out and then Zoomed in):



Read Status Bytes:

Read of Manufacturer and Device IDs

Read Status

Clock Frequency (1MHz)

#include "driverlib.h"
#include "device.h"
#include "board.h"
#include "FlashTestStateMachine.h"
#include "string.h"

Uint16 u16StartCommand = 0;

Uint16 u16ChipEraseStarted = 0;

Uint16 u16FlashEraseCounter = 0;

Uint16 u16FlashTestAddress24_16 = 0x7F;
Uint16 u16FlashTestAddress15_8 = 0xF0;
Uint16 u16FlashTestAddress7_0 = 00;

Uint16 FlashTestDataRead1 = 0;
Uint16 FlashTestDataRead2 = 0;
Uint16 FlashTestDataWrite = 0x68;

int16 s16TestPassed = 0;
Uint16 u16TestCompleted = 0;
Uint16 WriteStarted = 0;
Uint16 ReadStarted = 0;
Uint16 u16tempReadData1 = 0;
Uint16 u16tempReadData2 = 0;
Uint16 u16tempReadData3 = 0;
Uint16 u16tempReadData4 = 0;

Uint16 u16DummyByte;
Uint16 ManufacturerID = 0x00;
Uint16 DeviceID1= 0x00;
Uint16 DeviceID2= 0x00;

#define CHIP_SELECT_LOW     GPIO_writePin(McBSP_ChipSelectPinNumber,0)
#define CHIP_SELECT_HIGH    GPIO_writePin(McBSP_ChipSelectPinNumber,1)

extern Uint16 Tsk4msPeriodInMiliseconds;

#define FLASH_TEST_STATE_MACHINE_TASK_PERIOD   (((float)Tsk4msPeriodInMiliseconds)*0.001)
#define THIRTY_SECONDS  ((Uint16)(30.0/FLASH_TEST_STATE_MACHINE_TASK_PERIOD))

Uint16 flashWriteCounter = 0;

Uint16 Status1 = 0;
Uint16 Status2 = 0;
Uint16 Status3 = 0;

typedef enum
{
    FLASH_OPCODE_WRITE = 0x02,
    FLASH_OPCODE_READ = 0x03,
    FLASH_OPCODE_DISABLE_WRITES = 0x04,
    FLASH_OPCODE_READ_STATUS = 0x05,
    FLASH_OPCODE_ENABLE_WRITES = 0x06,
    FLASH_OPCODE_CHIP_ERASE = 0x60,
    FLASH_OPCODE_READ_MANUFACTURER_AND_DEVICE_IDS = 0x9F
} FLASH_OPCODES;

typedef enum
{
    FLASH_TEST_WAIT_TO_START_STATE,
    FLASH_TEST_ERASE_FLASH_CHIP_STATE,
    FLASH_TEST_READ_MANUFACTURER_ID,
    FLASH_TEST_WRITE_SINGLE_BYTE_STATE,
    FLASH_TEST_READ_SINGLE_BYTE_STATE,
    FLASH_TEST_COMPLETE_STATE,
    FLASH_TEST_READ_STATUS,
    FLASH_TEST_ENABLE_WRITES,
    FLASH_TEST_DISABLE_WRITES
} FLASH_TEST_STATEMACHINE_STATE;

FLASH_TEST_STATEMACHINE_STATE FlashTestState = FLASH_TEST_WAIT_TO_START_STATE;

FLASH_TEST_STATEMACHINE_STATE Operations[] =
{       FLASH_TEST_ENABLE_WRITES,
        FLASH_TEST_ERASE_FLASH_CHIP_STATE,
        FLASH_TEST_READ_STATUS,
        FLASH_TEST_WRITE_SINGLE_BYTE_STATE,
        FLASH_TEST_DISABLE_WRITES,
        FLASH_TEST_READ_STATUS,
        FLASH_TEST_READ_SINGLE_BYTE_STATE,
        FLASH_TEST_COMPLETE_STATE
};

#define MAX_DEBUG_INDEX  20
FLASH_TEST_STATEMACHINE_STATE FlashTestDebugData[MAX_DEBUG_INDEX];
Uint16 FlashTestDebugArrayIndex = 0;

Uint16 OperationSize = 0;

void FlashTestStateMachine_Init(void)
{
    OperationSize = sizeof(Operations)/sizeof(FLASH_TEST_STATEMACHINE_STATE);

    memset((void*)FlashTestDebugData,0,sizeof(FlashTestDebugData));
}


static BOOL FlashTestStateMachine(FLASH_TEST_STATEMACHINE_STATE FlashTestState)
{
    BOOL CompletedTask = FALSE;

    switch(FlashTestState)
    {
        case FLASH_TEST_READ_MANUFACTURER_ID:
            GPIO_writePin(McBSP_ChipSelectPinNumber,0);
            McBSP_transmit16BitDataBlocking(MCBSPB_BASE,FLASH_OPCODE_READ_MANUFACTURER_AND_DEVICE_IDS);
            McBSP_receive16BitDataBlocking(MCBSPB_BASE,&u16DummyByte);
            McBSP_transmit16BitDataBlocking(MCBSPB_BASE,0x00);
            McBSP_receive16BitDataBlocking(MCBSPB_BASE,&ManufacturerID);
            McBSP_transmit16BitDataBlocking(MCBSPB_BASE,0x00);
            McBSP_receive16BitDataBlocking(MCBSPB_BASE,&DeviceID1);
            McBSP_transmit16BitDataBlocking(MCBSPB_BASE,0x00);
            McBSP_receive16BitDataBlocking(MCBSPB_BASE,&DeviceID2);
            GPIO_writePin(McBSP_ChipSelectPinNumber,1);

            CompletedTask = TRUE;

            break;

        case FLASH_TEST_READ_STATUS:
            GPIO_writePin(McBSP_ChipSelectPinNumber,0);
            McBSP_transmit16BitDataBlocking(MCBSPB_BASE,FLASH_OPCODE_READ_STATUS);
            McBSP_receive16BitDataBlocking(MCBSPB_BASE,&u16DummyByte);
            McBSP_transmit16BitDataBlocking(MCBSPB_BASE,0x00);
            McBSP_receive16BitDataBlocking(MCBSPB_BASE,&Status1);
            McBSP_transmit16BitDataBlocking(MCBSPB_BASE,0x00);
            McBSP_receive16BitDataBlocking(MCBSPB_BASE,&Status2);
            McBSP_transmit16BitDataBlocking(MCBSPB_BASE,0x00);
            McBSP_receive16BitDataBlocking(MCBSPB_BASE,&Status3);
            GPIO_writePin(McBSP_ChipSelectPinNumber,1);

            CompletedTask = TRUE;

            break;

        case FLASH_TEST_ENABLE_WRITES:
            CHIP_SELECT_LOW;
            McBSP_transmit16BitDataBlocking(MCBSPB_BASE,FLASH_OPCODE_ENABLE_WRITES);
            McBSP_receive16BitDataBlocking(MCBSPB_BASE,&u16DummyByte);
            CHIP_SELECT_HIGH;

            CompletedTask = TRUE;

            break;

        case FLASH_TEST_ERASE_FLASH_CHIP_STATE:

            if (!u16ChipEraseStarted)
            {
                CHIP_SELECT_LOW;
                McBSP_transmit16BitDataBlocking(MCBSPB_BASE,FLASH_OPCODE_CHIP_ERASE);
                McBSP_receive16BitDataBlocking(MCBSPB_BASE,&u16DummyByte);
                CHIP_SELECT_HIGH;
                u16ChipEraseStarted = 1;
            }

            u16FlashEraseCounter++;

            //Wait 30 seconds
            if (u16FlashEraseCounter >= THIRTY_SECONDS)
            {

                CompletedTask = TRUE;
            }

            break;

        case FLASH_TEST_WRITE_SINGLE_BYTE_STATE:

            if (!WriteStarted)
            {
                WriteStarted = 1;
                CHIP_SELECT_LOW;
                McBSP_transmit16BitDataBlocking(MCBSPB_BASE,FLASH_OPCODE_WRITE);
                McBSP_receive16BitDataBlocking(MCBSPB_BASE,&u16DummyByte);
                McBSP_transmit16BitDataBlocking(MCBSPB_BASE,u16FlashTestAddress24_16);
                McBSP_receive16BitDataBlocking(MCBSPB_BASE,&u16DummyByte);
                McBSP_transmit16BitDataBlocking(MCBSPB_BASE,u16FlashTestAddress15_8);
                McBSP_receive16BitDataBlocking(MCBSPB_BASE,&u16DummyByte);
                McBSP_transmit16BitDataBlocking(MCBSPB_BASE,u16FlashTestAddress7_0);
                McBSP_receive16BitDataBlocking(MCBSPB_BASE,&u16DummyByte);
                McBSP_transmit16BitDataBlocking(MCBSPB_BASE,FlashTestDataWrite);
                McBSP_receive16BitDataBlocking(MCBSPB_BASE,&u16DummyByte);
                CHIP_SELECT_HIGH;

                CompletedTask = TRUE;
            }

            break;

        case FLASH_TEST_DISABLE_WRITES:
            CHIP_SELECT_LOW;
            McBSP_transmit16BitDataBlocking(MCBSPB_BASE,FLASH_OPCODE_DISABLE_WRITES);
            McBSP_receive16BitDataBlocking(MCBSPB_BASE,&u16DummyByte);
            CHIP_SELECT_HIGH;

            CompletedTask = TRUE;

            break;

        case FLASH_TEST_READ_SINGLE_BYTE_STATE:

            if (!ReadStarted)
            {
                ReadStarted = 1;
                CHIP_SELECT_LOW;
                McBSP_transmit16BitDataBlocking(MCBSPB_BASE,FLASH_OPCODE_READ);
                McBSP_receive16BitDataBlocking(MCBSPB_BASE,&u16DummyByte);
                McBSP_transmit16BitDataBlocking(MCBSPB_BASE,u16FlashTestAddress24_16);
                McBSP_receive16BitDataBlocking(MCBSPB_BASE,&u16DummyByte);
                McBSP_transmit16BitDataBlocking(MCBSPB_BASE,u16FlashTestAddress15_8);
                McBSP_receive16BitDataBlocking(MCBSPB_BASE,&u16DummyByte);
                McBSP_transmit16BitDataBlocking(MCBSPB_BASE,u16FlashTestAddress7_0);
                McBSP_receive16BitDataBlocking(MCBSPB_BASE,&u16DummyByte);
                McBSP_transmit16BitDataBlocking(MCBSPB_BASE,0x00);
                McBSP_receive16BitDataBlocking(MCBSPB_BASE,&FlashTestDataRead1);
                CHIP_SELECT_HIGH;
            }
            else
            {
                if (FlashTestDataRead1 == FlashTestDataWrite)
                {
                    s16TestPassed = 1;
                }
                else
                {
                    s16TestPassed = -1;
                }

                CompletedTask = TRUE;
            }

            break;

        case FLASH_TEST_COMPLETE_STATE:

            u16TestCompleted = 1;

            CompletedTask = TRUE;

            break;
    }

    return CompletedTask;
}

Uint16 OperationArrayIndex = 0;

void FlashTestStateMachine_Task(void)
{
    if (u16StartCommand)
    {
        if (OperationArrayIndex < OperationSize)
        {
            Uint16 CompletedTask;

            FlashTestState = Operations[OperationArrayIndex];
            CompletedTask = FlashTestStateMachine(FlashTestState);

            if (CompletedTask)
            {
                OperationArrayIndex++;
            }

            if (FlashTestDebugArrayIndex < MAX_DEBUG_INDEX)
            {
                FlashTestDebugData[FlashTestDebugArrayIndex] = FlashTestState;

                if (FlashTestState != FLASH_TEST_ERASE_FLASH_CHIP_STATE)
                {
                    FlashTestDebugArrayIndex++;
                }
            }
        }
        else
        {
            u16StartCommand = 0;
            OperationArrayIndex = 0;
        }
    }
}

  • After reading through https://community.renesas.com/memory/f/memory-products/28547/erase-chip-function-didn-t-erase-the-hole-chip post, I decided to do a block erase instead of a chip erase.  I am now able to write and read the correct value from flash.  I have to also mentioned that I changed the address to 0x7F6000.  Maybe there is an issue with the 0x7FF000 address?

    I will do some more testing, but why would there be an issue with chip erase?

  • I changed the chip erase timeout to 60 seconds (max should be 40 seconds) and it still not working for two different addresses in two different blocks.

    Why isn't chip erase working?

  • Hi There,

    Thank you for posting your question online and apologies for the delay.
    We have created an internal ticket regarding this and we will get back to you as soon as possible.

    Best Regards,
    OV_Renesas

  • Hi There,

    Apologies for the delay.
    Please find below the answer from the Memories Support Team:

    If this sequence is performed every 10ms as is then it is wrong:

    • Step 1 and 2 should be performed only once to initiate chip erase. They should not be repeated each 10ms.
    • In step 3 it's enough to read one byte. It will provide the value of status register 1 (SR1), The wave form in the datasheet shows 3 bytes just to demonstrate that SR1 can be read continuously any number of times. But its really not necessary here.
    • Steps 4 and above should be executed only if the RDY/BSY bit (bit 0 of SR1) is 0. If it's 1 the flash is still busy with chip erase and program/read operation should will not be allowed.
    • Step 4 requires a write enable (opcode 06h) before it. Note: every erase/program/write-status-register operation requires its own write-enable. The write-enable status expires after erase/program/write-status-register command. In other words the write-enable command enables write only for one command.
    • Step 4 should be executed only once.
    • Step 5 is redundant. As explained above write-enable expires after any erase/program/write-status-register command.
    • Step 7 should be executed only if RDY/BSY bit in SR1 is 0. Otherwise the flash is still busy programming.

     

    In general a correct sequence is this:

     

    • Send write-enable (06h)
    • Send erase command (whether chip erase or any block erase).
    • Poll RDY/BSY bit by reading SR1 (opcode 05h) continuously. Stop when it's 0.
    • Send write-enable (06h)
    • Send program command with address and data to be programmed.
    • Poll RDY/BSY bit by reading SR1 (opcode 05h) continuously. Stop when it's 0.
    • Read data to verify (opcode 03h or any other read opcode).

    Best Regards,
    OV_Renesas