cancel
Showing results for 
Search instead for 
Did you mean: 

[STM32H750BX][QSPI] Issue with W25N01GVZEIG NAND Flash Driver

Ayoub Cheggari
Associate III

Hello,

Please, I am working on a Custom Project with STM32H7 platform and I am using a NAND Flash for Data Storage (W25N01GVZEIG). I can execute correctly all commands except :

  • (32h) Quad Program Data Load .

I can write using (02h) Program Data Load with SPI mode with no issues, but once I switch to Quad mode (32h) the data written is not correct, seems there is some bits corruption.

{0x11,0x22,0x44,0x88} is written {0x91,0x22,0x04,0x48}. I suspected the pinout first but the Quad read is working fine.

I saw a similar question QSPI of STM32L496A but didn't fix my issue.

Could you support on this?

Thanks,

Ayoub

1 ACCEPTED SOLUTION

Accepted Solutions

I was suspecting it to be a read issue, but when I write with SPI using cmd (02h), I can read data correctly.

Speaking about the erase, when I execute the Block Erase cmd (D8h), the bits are set to 0 not 1 which is very strange. I will do as you proposed thanks @Community member​  for supporting as always !

View solution in original post

16 REPLIES 16
Ahmet Yasin CİVAN
Associate III

Can you send your code? How do you do read, write, erase, execute operations?

I can write using Quad mode (32h) but some pages (2048 byte) are not correct. For example; in block 0, page from 0 to 10 is sucsess but in block 0, page from 10 to 15 wrong.

David Garcia (Community Member)'s answers are very helpful. In this question QSPI of STM32L496A, the codes found here are all working, I followed the instructions.

You problem is like dummyCycles.

Issues tend to be on the READ side, not the WRITE, READs can be tested/validated by either having existing patterns in memory, or using the READ 1, 2 and 4-bit modes and checking they all read the same data.

If on the WRITE side you're going to have to look at signal integrity issues, and meeting expectations of the memory device in terms of how quickly it can ingest data into internal buffers, and how quickly it can write complete blocks to its internal array.

Check that the correct dummy and alternate cycles are programmed.

Check that you are properly/completely initializing the command structures.

Check that the addressing/paging is correct for each command.

Check that data is erased properly.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

I was suspecting it to be a read issue, but when I write with SPI using cmd (02h), I can read data correctly.

Speaking about the erase, when I execute the Block Erase cmd (D8h), the bits are set to 0 not 1 which is very strange. I will do as you proposed thanks @Community member​  for supporting as always !

Here is the code I am using:

Write: here as we discussed in Linkedin, SPI write works fine but Quad is not as the written data is corrupted somehow. Also, don't need to execute the Program execute cmd to store the data into Physical mem.

uint8_t W25qxx_PageProgram(uint8_t *pData, uint32_t WriteAddr, uint32_t Size)

{

uint8_t result;

W25qxx_WriteEnable();

result = QSPI_Send_CMD(&hqspi,W25X_PageProgram,WriteAddr,QSPI_ADDRESS_16_BITS,0,QSPI_INSTRUCTION_1_LINE,QSPI_ADDRESS_1_LINE,QSPI_DATA_1_LINE,Size);

//result = QSPI_Send_CMD(&hqspi,W25X_QUAD_INPUT_PAGE_PROG_CMD,WriteAddr,QSPI_ADDRESS_16_BITS,0,QSPI_INSTRUCTION_1_LINE,QSPI_ADDRESS_1_LINE,QSPI_DATA_4_LINES,Size);

if(result == w25qxx_OK)

result = HAL_QSPI_Transmit(&hqspi,pData,HAL_QPSI_TIMEOUT_DEFAULT_VALUE);

if(result == w25qxx_OK)

W25QXX_Wait_Busy();

//W25qxx_ProgramExecute(WriteAddr);

return result;

}

Erase: the bits are set to 0 instead of 1

uint8_t W25qxx_EraseBlock(uint16_t BlockAddress)

{

uint8_t result;

uint8_t page = 0;

uint8_t block = 0;

uint32_t addr = (block << 6) | page;

block_add[0] = (uint8_t) (addr >> 8);

block_add[1] = (uint8_t) addr ;

W25qxx_WriteEnable();

W25QXX_Wait_Busy();

result = QSPI_Send_CMD(&hqspi,W25X_BlockErase,BlockAddress,QSPI_ADDRESS_8_BITS,8,QSPI_INSTRUCTION_1_LINE,QSPI_ADDRESS_NONE,QSPI_DATA_1_LINE,2);

result = HAL_QSPI_Transmit(&hqspi,(uint8_t *)block_add,HAL_QPSI_TIMEOUT_DEFAULT_VALUE);

if(result == w25qxx_OK)

W25QXX_Wait_Busy();

return result;

}

I tried to follow instructions written by David Garcia, but didn't work.

What is your "QSPI_Send_CMD" function? Please send, function and hqspi init instructions.

Here is the function:

static uint8_t QSPI_Send_CMD(QSPI_HandleTypeDef *hqspi,uint32_t instruction, uint32_t address,uint32_t addressSize,uint32_t dummyCycles, 

          uint32_t instructionMode,uint32_t addressMode, uint32_t dataMode, uint32_t dataSize)

{

  QSPI_CommandTypeDef Cmdhandler;

  Cmdhandler.Instruction    = instruction;  

  Cmdhandler.InstructionMode  = instructionMode;

  Cmdhandler.Address      = address;

  Cmdhandler.AddressSize    = addressSize;

  Cmdhandler.AddressMode    = addressMode;

  Cmdhandler.AlternateBytes   = 0x00;

  Cmdhandler.AlternateBytesSize = QSPI_ALTERNATE_BYTES_8_BITS;

  Cmdhandler.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;

  Cmdhandler.DummyCycles    = dummyCycles;          

  Cmdhandler.DataMode      = dataMode;

  Cmdhandler.NbData       = dataSize; 

  Cmdhandler.DdrMode      = QSPI_DDR_MODE_DISABLE;      

  Cmdhandler.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;

  Cmdhandler.SIOOMode      = QSPI_SIOO_INST_EVERY_CMD;

  if(HAL_QSPI_Command(hqspi, &Cmdhandler, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)

   return w25qxx_ERROR;

  return w25qxx_OK;

}

In the init I am doing just like you do but here it is:

void w25qxx_Init(void)

{

QSPI_ResetDevice(&hqspi);

w25qxx_ID = w25qxx_GetJEDECID();

w25qxx_ReadAllStatusReg();

w25qxx_WriteSR(W25X_ReadStatusReg1_Address, 0x04);

}

Have you gotten it to work? I am running into issue myself as well

STM32WB55  https://community.st.com/t5/stm32-mcus-products/stm32wb-qspi-flash-winbond-w25n01gv/td-p/607010

You might look at assorted Flight Controller implementations on GitHub, etc, as these likely had more examples of the W25N01 NAND devices for Black Box logger. As these devices don't support random access read they don't work in XIP mode on STM32, therefore a general dearth of examples. I've used these parts in the past

In the other thread I suggested the consistent use of clearing methods for auto/local variables as this can resolve a lot of odd / unexplained issues when interacting with the HAL library code.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..