cancel
Showing results for 
Search instead for 
Did you mean: 

Nor Flash

donmurdoch
New Contributor

I am using a S25FL256S - 256MBit FLASH, I am able to read register values, erase the entire device or just a few blocks, read and write to the device, everything... However, when I do a power cycle, all of the values written to FLASH  before power off and power up, are "erased" and the FLASH just contains all 1's (It seems like the flash is being initialized to an erased state on every power up)

I have checked the CR1 BPNV bit and it is set to 0

0 Likes
6 Replies
BushraH_91
Moderator
Moderator

Hello,

Thank you for contacting Cypress Technical Support, an Infineon Technologies company. Can you please share screenshot of your issue and share your codes.

Thank you

Regards,

Bushra

0 Likes
donmurdoch
New Contributor

Hello Bushra, 

We are using SPI Quad mode to communicate with the device. The code is below, it initializes communication with the flash device, reads the values from a particular region of the flash, then writes values to that region, then reads them again to verify they are there, and then enters an infinite loop waiting for the user to power cycle. After the power cycle and initialization, the code then tries to read the values that it wrote and verified before the power cycle, what we are seeing is that after every power cycle the values written are not there. The BPV bit 3 of the CR1 register is 0 so the flash should be non-volatile. 

Code is here:

STATIC void HM3FS_222_Flash_Driver_Manual_Test()
{
qspi_command_xfer_t qspi_command_xfer = {0};
qspi_register_xfer_t qspi_register_xfer = {0};

uint32_t startAddr = ((uint32_t) 0x80200000);
uint32_t endAddr = ((uint32_t) startAddr + 8);
//uint32_t endAddr = ((uint32_t) 0x82000000);

memset((void *)&qspi_command_xfer, 0, sizeof(qspi_command_xfer_t));
memset((void *)&qspi_register_xfer, 0, sizeof(qspi_register_xfer_t));

// Open the debug/printf port
m_usartHandle = DRV_USART_Open(DRV_USART_INDEX_0, DRV_IO_INTENT_READWRITE);
tx_thread_sleep(1000);

Print_Message("\nStarting Flash Memory Test!\n");

// INITIALIZE ================================================================================================
Print_Message("\nInitializing FLASH - ");

if( EFD_Init() )
{
Print_Message("PASS\n");
}
else
{
Print_Message("FAIL\n");
}


/* Code for EFD_Init():
bool EFD_Init(void)
{
bool status = false;

//Reset Flash to break any ongoing operations
EFD_Pvt_Reset_Flash();
/* Code for private reset flash:

memset((void *)&m_qspi_command_xfer, 0, sizeof(qspi_command_xfer_t));

m_qspi_command_xfer.instruction = S25FL_CMD_RESET;
m_qspi_command_xfer.width = SINGLE_BIT_SPI;

if (false == QSPI_CommandWrite(&m_qspi_command_xfer, BLANK_ADDRESS))
{
SW_ERROR(SW_ERROR_CODE_TRANSMIT_FAILED, SW_ERROR_VALUE_NOT_USED);
}
*/
/*
tx_thread_sleep(WAIT_TIMER); // sleep to allow

EFD_Pvt_Enable_Writes();
*/
/* Code for Private Enable Writes:

bool status = false;
bool retVal = false;

memset((void *)&m_qspi_command_xfer, 0, sizeof(qspi_command_xfer_t));
m_qspi_command_xfer.instruction = S25FL_CMD_WREN;
m_qspi_command_xfer.width = SINGLE_BIT_SPI;

// Issue the Write Enable (WREN) command
if (!false == QSPI_CommandWrite(&m_qspi_command_xfer, BLANK_ADDRESS))
{
// Check that the Write Enable Latch (WEL) bit is set to 1. Return error if not.
uint8_t regVal = 0;
status = EFD_Pvt_Read_Status_Register_1(&regVal);
if ((!false == status) && (EFL_SR1_WEL == (EFL_SR1_WEL & regVal)))
{
retVal = true;
}
}

return retVal;
*/
/*
tx_thread_sleep(WAIT_TIMER);

//Update CR1 and SR1
const uint8_t cr1_regVal = CR1_QUAD_ENABLE; // | CR1_WRITEPROTECT;//Enable QUAD bit in CR1
const uint8_t sr1_regVal = 0;//Reset SR1
uint16_t full_regVal = 0;
full_regVal = (uint16_t)(((uint16_t)cr1_regVal<<REG_OFFSET) | (uint16_t)sr1_regVal);

memset((void *)&m_qspi_register_xfer, 0, sizeof(qspi_register_xfer_t));
m_qspi_register_xfer.width = SINGLE_BIT_SPI;
m_qspi_register_xfer.instruction = S25FL_CMD_WRR;
QSPI_RegisterWrite( &m_qspi_register_xfer, (uint32_t*) &full_regVal, sizeof(full_regVal) );
tx_thread_sleep(WAIT_TIMER);

//Verify Device ID
if (!false == EFD_Pvt_Verify_Device_Id())
{
status = true;
}

return status; // This is successful, we are able to read the Device ID properly every time
}
*/
// ============ End EFD_Init Code, EFD_Init returns true and is able to read the device ID

// READ SECTOR ================================================================================================
Print_Message("Now try reading memory to see what is there before we write to it. \n");
Print_Message("Reading Memory - ");

uint32_t readData;
uint32_t firstVal;
uint32_t lastVal;

bool testStatus = true;
UINT readStatus = LX_SUCCESS;

/* Code for EFD_Service_Function_For_Lx_Read():
UINT EFD_Service_Function_For_Lx__Read(const ULONG* p_flashAddress, ULONG* p_destination, ULONG words)
{
UINT retVal = LX_ERROR;
bool status = false;

// HAL max transfer size is limited to USHRT_MAX
if ((NULL == p_flashAddress) || (NULL == p_destination))
{
SW_ERROR(SW_ERROR_CODE_NULL_POINTER, SW_ERROR_VALUE_NOT_USED);
}
else if ( (0UL == words) || (words > EFD_MAX_LX_WORDS_IN_UINT16) )
{
SW_ERROR(SW_ERROR_CODE_INVALID_VALUE, words);
}
else
{
uint16_t numBytes = (uint16_t)words * EFL_NUM_BYTES_IN_LX_WORD;

// External flash device addresses are a value for SPI but LevelX treats it as a pointer to the address
status = QSPI_MemoryRead( &m_qspi_memory_xfer, (uint32_t*)p_destination, numBytes, (uint32_t)p_flashAddress );
if ( false == status)
{
SW_ERROR(SW_ERROR_CODE_RECEIVE_FAILED, SW_ERROR_VALUE_NOT_USED);
}
}

memset((void *)&m_qspi_command_xfer, 0, sizeof(qspi_command_xfer_t));
m_qspi_command_xfer.instruction = S25FL_CMD_CLSR;
m_qspi_command_xfer.width = SINGLE_BIT_SPI;
QSPI_CommandWrite(&m_qspi_command_xfer, BLANK_ADDRESS);

m_qspi_command_xfer.instruction = S25FL_CMD_WRDI;
QSPI_CommandWrite(&m_qspi_command_xfer, BLANK_ADDRESS);

retVal = EFD_Pvt_Convert_Bool_Status_To_Lx_Retval(status);
return retVal;
}
*/
//Loop through all memory locations
for(uint32_t currAddr = startAddr; currAddr < endAddr; currAddr = currAddr + sizeof(uint32_t))
{ //Read out the value at each memory location
if(!LX_SUCCESS == EFD_Service_Function_For_Lx__Read( currAddr, &readData, sizeof(uint32_t)/EFL_NUM_BYTES_IN_LX_WORD))
{
readStatus = false;
break;
}

if(currAddr == startAddr)
{
firstVal = readData;
}

if( currAddr == endAddr - sizeof(uint32_t) )
{
lastVal = readData;
}

if(currAddr != readData)
{
testStatus = false;
}
}

if (LX_SUCCESS == readStatus)
{
Print_Message("PASS\n");
}
else
{
Print_Message("FAIL\n");
}

char bufferAdd [sizeof(uint32_t)*8+1];
char bufferVal [sizeof(uint32_t)*8+1];

utoa ( startAddr, bufferAdd, 10 ); //Print out the first and last memory locations
utoa ( firstVal , bufferVal, 10 );
Print_Message( "\nAddress: " );
Print_Message( bufferAdd );
Print_Message( " Value: " );
Print_Message( bufferVal );

if(firstVal != startAddr)
{
Print_Message("- FAIL ");
}
else {
Print_Message("- PASS ");
}

utoa ( endAddr - sizeof(uint32_t), bufferAdd, 10 );
utoa ( lastVal, bufferVal,10 );
Print_Message( "\nAddress: " );
Print_Message( bufferAdd );
Print_Message( " Value: " );
Print_Message( bufferVal );

if(lastVal != endAddr - sizeof(uint32_t))
{
Print_Message("- FAIL ");
}
else
{
Print_Message("- PASS ");
}

if(testStatus){ Print_Message("\nAll data written to Flash verified - Test Passed\n"); }
else { Print_Message("\nMismatch between data written to Flash and expected value - Test Failed\n");}

// END MESSAGE ================================================================================================

// WRITE SECTOR ==============================================================================================
Print_Message("Writing Memory - ");

UINT writeStatus = LX_SUCCESS;
for(uint32_t currAddr = startAddr; currAddr <= endAddr; currAddr = currAddr + sizeof(uint32_t) )
{ //Loop through all memory locations
if( currAddr%400000 == 0 )
{
Print_Message("*") ;
}
if( currAddr%4000000 == 0)
{
Print_Message("\n");
}

if( !LX_SUCCESS == EFD_Service_Function_For_Lx__Write( currAddr, &currAddr, sizeof(uint32_t)/EFL_NUM_BYTES_IN_LX_WORD) )
{
writeStatus = false;
break;
}
}

if (LX_SUCCESS == writeStatus)
{
Print_Message("PASS\n");
}
else
{
Print_Message("FAIL\n");
}

/* Code for EFD_Service_Write:
UINT EFD_Service_Function_For_Lx__Write(const ULONG* p_flashAddress, ULONG* p_source, ULONG words)
{
UINT retVal = LX_ERROR;
bool status = false;

if ((NULL == p_flashAddress) || (NULL == p_source))
{
SW_ERROR(SW_ERROR_CODE_NULL_POINTER, SW_ERROR_VALUE_NOT_USED);
}
else if ((0UL == words) || (words > EFD_MAX_LX_WORDS_IN_UINT32))
{
SW_ERROR(SW_ERROR_CODE_INVALID_VALUE, words);
}
else
{
uint32_t numBytes = words * EFL_NUM_BYTES_IN_LX_WORD;

// External flash device addresses are a value for SPI but LevelX treats it as a pointer to the address
status = EFD_Pvt_Write((uint32_t)p_flashAddress, (uint32_t*)p_source, numBytes);
}

retVal = EFD_Pvt_Convert_Bool_Status_To_Lx_Retval(status);
return retVal;
}
*/

/* Code for EFD_Private_Write
STATIC bool EFD_Pvt_Write(uint32_t addr, uint32_t* p_data, uint32_t dsize)
{
bool status = false;
uint32_t* p_localData = p_data;
uint32_t localAddr = addr;
uint32_t dataLeft = dsize;
uint32_t writeSize = dsize;

if (NULL == p_data)
{
SW_ERROR(SW_ERROR_CODE_NULL_POINTER, SW_ERROR_VALUE_NOT_USED);
}
else if ((0U == dsize) || (dsize > EFD_DATA_MAX_LEN) || (addr < EFL_START_ADDRESS) || (addr > EFL_END_ADDRESS) || (0U == m_EFD_ProgramPageSizeInBytes))
{
SW_ERROR(SW_ERROR_CODE_INVALID_VALUE, SW_ERROR_VALUE_NOT_USED);
}
else
{
// @par Write Data Loop
while (0U != dataLeft)
{
status = false;

// A. Calculate the size of the write data chunk.
writeSize = dataLeft;

// - ensure that writeSize is not larger than page size
if (m_EFD_ProgramPageSizeInBytes < writeSize)
{
writeSize = m_EFD_ProgramPageSizeInBytes;
}

// * - ensure that writeSize does not cross page boundary
// * Reason: All data that goes beyond the end of the current page is programmed from the start address
// * of the same page. i.e. the address wraps within the page aligned address boundaries.
if ((m_EFD_ProgramPageSizeInBytes - (localAddr % m_EFD_ProgramPageSizeInBytes)) < writeSize)
{
writeSize = (m_EFD_ProgramPageSizeInBytes - (localAddr % m_EFD_ProgramPageSizeInBytes));
}

// B. Enable flash write, write to flash, and check for completion (success/error).
if (!false == EFD_Pvt_Enable_Writes()) // error return indicates another operation is in progress and this one will be rejected
{
// errors: invalid args, HAL state errors, or HAL SPI errors
if (!false == EFD_QSPI_Write_Device(localAddr, p_localData, writeSize))
{
// Programming speed is 1.5 MBps, therefore 512 bytes takes 0.325 msec
#define WRITE_CHECK_PERIOD_IN_TICKS (1U * TICKS_PER_MILLISECOND)
#define WRITE_CHECK_COUNT (5)
if (!false == EFD_Pvt_Check_Write_Status(WRITE_CHECK_PERIOD_IN_TICKS, WRITE_CHECK_COUNT))
{
status = true;
}
else
{
break;
}
}
}

p_localData += writeSize;
localAddr += writeSize;
dataLeft -= writeSize;

} // End while dataleft and not error
}

EFD_Pvt_Reset_Memory_Read_Preset();

return status;
}
*/

// END MESSAGE ================================================================================================

// READ to Verify that values were written:
//Loop through all memory locations
Print_Message("Second Read test to verify values were written successfully:\n");
Print_Message("Reading Memory --");
for(uint32_t currAddr = startAddr; currAddr < endAddr; currAddr = currAddr + sizeof(uint32_t))
{ //Read out the value at each memory location
if(!LX_SUCCESS == EFD_Service_Function_For_Lx__Read( currAddr, &readData, sizeof(uint32_t)/EFL_NUM_BYTES_IN_LX_WORD))
{
readStatus = false;
break;
}

if(currAddr == startAddr)
{
firstVal = readData;
}

if( currAddr == endAddr - sizeof(uint32_t) )
{
lastVal = readData;
}

if(currAddr != readData)
{
testStatus = false;
}
}

if (LX_SUCCESS == readStatus)
{
Print_Message("PASS\n");
}
else
{
Print_Message("FAIL\n");
}

//char bufferAdd [sizeof(uint32_t)*8+1];
//char bufferVal [sizeof(uint32_t)*8+1];

utoa ( startAddr, bufferAdd, 10 ); //Print out the first and last memory locations
utoa ( firstVal , bufferVal, 10 );
Print_Message( "\nAddress: " );
Print_Message( bufferAdd );
Print_Message( " Value: " );
Print_Message( bufferVal );

if(firstVal != startAddr)
{
Print_Message("- FAIL ");
}
else {
Print_Message("- PASS ");
}

utoa ( endAddr - sizeof(uint32_t), bufferAdd, 10 );
utoa ( lastVal, bufferVal,10 );
Print_Message( "\nAddress: " );
Print_Message( bufferAdd );
Print_Message( " Value: " );
Print_Message( bufferVal );

if(lastVal != endAddr - sizeof(uint32_t))
{
Print_Message("- FAIL ");
}
else
{
Print_Message("- PASS ");
}

if(testStatus){ Print_Message("\nAll data written to Flash verified - Test Passed\n"); }
else { Print_Message("\nMismatch between data written to Flash and expected value - Test Failed\n");}
// ===================================== END READ ===============================================================

Print_Message("ALL TESTS COMPLETE\n\n");

// Enter infinite loop waiting for user to power cycle the device
Print_Message("Entering Infinite Loop, please power cycle device to see if Flash values are still there...");
int loopCounter = 0;
while(true) {
if(loopCounter++ % 1000000 == 0)
{
Print_Message(".");
}
}
}

 

0 Likes
BushraH_91
Moderator
Moderator

Hello,

Thank you so much. We will review and get back to you.

Regards,

Bushra

 

0 Likes
BushraH_91
Moderator
Moderator

Hello,

CR1 BPNV bit defines sector protection BP2-BP0 volatile or non-volatile. Flash array is always non-volatile regardless of CR1 BPNV bit value. The written data should exist in flash array after power cycle, unless erase operation is performed. Sounds like the data were not written into flash at all. However, read verify after programming passed, this is confusing. Can you please check the addresses for write/read are falling into flash region or somewhere in a volatile memory, i.e., RAM?

 

S25FL256S default supports 3-byte address after power cycle, reset. When Bank Address Register EXTADD bit is set to 1, then it requires 4-byte address.

 

A few more questions:

  1. Are you trying to write the 1st half (128Mb) of the flash array or 2nd half, or entire flash array? To access the 2nd half of flash array, Bank Address Register needs to be set – either set EXTADD=1 to use 4-byte address to access higher address range; or keeps EXTADD=0 and set BA24=1, so that all the 3-byte address sent with commands will be mapped to 2nd half (higher) address range of the flash array.
  2. Can you please share me the Device ID and CR1 value read from flash after power cycle?
  3. Is it possible to hook up a scope to the flash to probe signals while programming the flash?

 

0 Likes
BushraH_91
Moderator
Moderator

Hello 

Can you please send answers to following questions?

  1. Are you trying to write the 1st half (128Mb) of the flash array or 2nd half, or entire flash array? To access the 2nd half of flash array, Bank Address Register needs to be set – either set EXTADD=1 to use 4-byte address to access higher address range; or keeps EXTADD=0 and set BA24=1, so that all the 3-byte address sent with commands will be mapped to 2nd half (higher) address range of the flash array.
  2. Can you please share me the Device ID and CR1 value read from flash after power cycle?
  3. Is it possible to hook up a scope to the flash to probe signals while programming the flash?

Thank you

Regards,

Bushra

 

0 Likes
BushraH_91
Moderator
Moderator

Hello,

We are still waiting for your response.

Thank you

Regards,

Bushra

0 Likes