cancel
Showing results for 
Search instead for 
Did you mean: 

w25q128jv

Snm.1
Associate III

I want to read and write to w25q128jv with stm32l5 octo spi insted of quad spi.. is there anybody help me. ı could not write correctly.. and ı could not erase. correctly. first problem is when ı was write whiel start addres 0 my code write start to the 2. I added my write code. 

 

/**
 * @brief this method can used program page with quad
 * @PAram dat_buffer     : Data storage area
 * @PAram column_address: The address to start reading (maximum 32bit) WB_Serial_NAND_PageDataRead
 * @PAram buffer_size   : The number of bytes to read (maximum 65535)
 * @retval  none
 * NOTE : If you want to this mode you should set QE into the SR2
 */
bool W25Q128JVS::pageProgramWithQuad(uint8_t *dat_buffer, const uint32_t column_address, const uint16_t buffer_size)
{
if(m_ospi == nullptr)
{
return false;
}
 
if(dat_buffer == nullptr)
{
return false;
}
 
return m_ospi->transmitWith0Dummy1LineInstruction1LineAddress4lineData(dat_buffer, QUAD_INPUT_PAGE_PROGRAM, column_address, buffer_size);
}
/**
 * @brief this method can used program page
 * @PAram dat_buffer     : Data storage area
 * @PAram column_address: The address to start reading (maximum 32bit) WB_Serial_NAND_PageDataRead
 * @PAram buffer_size   : The number of bytes to read (maximum 65535)
 * @retval  none
 * NOTE : If you want to this mode you should set QE into the SR2
 */
bool W25Q128JVS::pageProgram(uint8_t *dat_buffer, const uint32_t column_address, const uint16_t buffer_size)
{
if(m_ospi == nullptr)
{
return false;
}
 
if(dat_buffer == nullptr)
{
return false;
}
return m_ospi->transmitWith0Dummy1LineInstruction1Line3ByteAddress(dat_buffer, PAGE_PROGRAM, column_address, column_address);
}

/***************************************************************************************************************/

bool OSPIL552::transmitWith0Dummy1LineInstruction1LineAddress4lineData(uint8_t *data_buffer, const uint32_t instruction, const uint32_t address, const uint16_t buffer_size)
 {
if(data_buffer == NULL)
{
return false;
}
 
OSPI_RegularCmdTypeDef cmd = {0};
 
cmd.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;
cmd.Instruction = instruction;
cmd.AddressMode = HAL_OSPI_ADDRESS_1_LINE;
cmd.AddressSize = HAL_OSPI_ADDRESS_24_BITS;
cmd.Address = address;
cmd.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;
cmd.AlternateBytes = HAL_OSPI_ALTERNATE_BYTES_NONE;
cmd.AlternateBytesSize = HAL_OSPI_ALTERNATE_BYTES_NONE;
cmd.DummyCycles = 4;
cmd.DataMode = HAL_OSPI_DATA_4_LINES;
cmd.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE;
cmd.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD;
cmd.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG;
cmd.NbData = buffer_size;
 
   if (HAL_OSPI_Command(ospi_handle, &cmd, HAL_OSPI_TIMEOUT_DEFAULT_VALUE))
   {
return false;
   }
 
   if (HAL_OSPI_Transmit(ospi_handle, reinterpret_cast<uint8_t *>(data_buffer), HAL_OSPI_TIMEOUT_DEFAULT_VALUE))
   {
return false;
   }
 
   return true;
 }
 

bool OSPIL552::transmitWith0Dummy1LineInstruction1Line3ByteAddress(uint8_t *data_buffer, const uint32_t instruction, const uint32_t address, const uint16_t buffer_size)
{
if(data_buffer == NULL)
{
return false;
}

OSPI_RegularCmdTypeDef cmd = {0};

cmd.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;
cmd.Instruction = instruction;
cmd.AddressMode = HAL_OSPI_ADDRESS_1_LINE;
cmd.AddressSize = HAL_OSPI_ADDRESS_24_BITS;
cmd.Address = address;
cmd.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;
cmd.AlternateBytes = HAL_OSPI_ALTERNATE_BYTES_NONE;
cmd.AlternateBytesSize = HAL_OSPI_ALTERNATE_BYTES_NONE;
cmd.DummyCycles = 0;
cmd.DataMode = HAL_OSPI_DATA_1_LINE;
cmd.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE;
cmd.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD;
cmd.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG;
cmd.NbData = buffer_size;

if (HAL_OSPI_Command(ospi_handle, &cmd, HAL_OSPI_TIMEOUT_DEFAULT_VALUE))
{
return false;
}

if (HAL_OSPI_Transmit(ospi_handle, reinterpret_cast<uint8_t *>(data_buffer), HAL_OSPI_TIMEOUT_DEFAULT_VALUE))
{
return false;
}

return true;

}

 

hospi1.Instance = OCTOSPI1;
hospi1.Init.FifoThreshold = 1;
hospi1.Init.DualQuad = HAL_OSPI_DUALQUAD_DISABLE;
hospi1.Init.MemoryType = HAL_OSPI_MEMTYPE_MICRON;
hospi1.Init.DeviceSize = 32;
hospi1.Init.ChipSelectHighTime = 1;
hospi1.Init.FreeRunningClock = HAL_OSPI_FREERUNCLK_DISABLE;
hospi1.Init.ClockMode = HAL_OSPI_CLOCK_MODE_0;
hospi1.Init.WrapSize = HAL_OSPI_WRAP_NOT_SUPPORTED;
hospi1.Init.ClockPrescaler = 1;
hospi1.Init.SampleShifting = HAL_OSPI_SAMPLE_SHIFTING_NONE;
hospi1.Init.DelayHoldQuarterCycle = HAL_OSPI_DHQC_DISABLE;
hospi1.Init.ChipSelectBoundary = 0;
hospi1.Init.DelayBlockBypass = HAL_OSPI_DELAY_BLOCK_BYPASSED;
hospi1.Init.Refresh = 0;
if (HAL_OSPI_Init(&hospi1) != HAL_OK)
{
Error_Handler();
}

}

10 REPLIES 10
KDJEM.1
ST Employee

Hi @Snm.1 ,

Could you please check the DeviceSize and the dummy cycles values.

Note that the Device size defines the memory size in number of bytes = 2**(DEVSIZE+1).

Thank you.

Kaouthar

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Note further that DeviceSize in the .ioc file and in the structure initialization for HAL_OSPI_Init() is the actual device size, not that "-1" BS.  The HAL adjusts the DeviceSize value before writing the register field.  Thanks for the constant source of confusion, ST!

+1  off-by-one and changing parameter meanings and enumerations between releases and families has been a persistent source of headaches..  https://community.st.com/t5/stm32-mcus/how-to-set-up-the-ospi-peripheral-to-interface-with-the/ta-p/49474

#UseTheSourceLuke

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

With the Winbond devices be particularly cognoscente of the dummy cycles and address widths. Device can be in different modes during initialization, and dummy cycles are not configurable on the device side like they are on Micron devices.

The mode switching and protection bits can be different. And Winbond has multiple part variants with different command sets. A large number of the older/smaller parts don't support Status Register 2 writes, you have to write BOTH Status Register 1 and 2 as a PAIR. Watch this as your buyer might not be able to source the same parts for every build, especially buying on the spot market.

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

Perhaps related? Not clear what your defines are, please post code using the appropriate formatting tool, and provide enough context to unpack what's actually going on.

https://community.st.com/t5/stm32-mcu-products/stm32h563vi-octo-spi-interface-dummy-cycles/td-p/581689

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

Hello @David Littell & @Tesla DeLorean ,

Thank you for bringing these issues to our attention. I will check internally.

Sorry for any inconvenience.

Kaouthar

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Hello,

I made some tests based on OSPI_NOR_MemoryMapped example with STM32L552E-EV board.

The Device Size configured in STM32Cube MX indicates the size of the OSPI memory in bytes and expressed in 2^n. The datasheet of the MX25L51245G is 512M-Bit = 64Mbytes = 0x400 0000. We see the bit 26 is set meaning 2^26 = 64 Mbytes. In STM32CubeMx we set the device size field to 26.

KDJEM1_0-1692089264880.pngKDJEM1_1-1692089502935.png

How to configure "Device Size" in STM32CubeMX is descripted in How to set up the OSPI peripheral to interface with the IS25LX256 from ISSI and in table Table 7. STM32CubeMX - Configuration of OCTOSPI parameters in AN5050.

 The device size configuration is down in the HAL_OSPI_Init function by using this code

 

/* Configure memory type, device size, chip select high time, delay block bypass,free running clock, clock mode */
MODIFY_REG(hospi->Instance->DCR1,(OCTOSPI_DCR1_MTYP | OCTOSPI_DCR1_DEVSIZE | OCTOSPI_DCR1_CSHT | OCTOSPI_DCR1_DLYBYP | OCTOSPI_DCR1_FRCK | OCTOSPI_DCR1_CKMODE),
hospi->Init.MemoryType | ((hospi->Init.DeviceSize - 1U) << OCTOSPI_DCR1_DEVSIZE_Pos) |((hospi->Init.ChipSelectHighTime - 1U) << OCTOSPI_DCR1_CSHT_Pos) |hospi->Init.DelayBlockBypass | hospi->Init.ClockMode));

 

 

So, the DEVSIZE bits filed in OCTOSPI_DCR1 registers get the Init.DeviceSize (configured in ioc file) - 1U, which is in line with RM0438 description. 

KDJEM1_3-1692090193138.png

For this example: 512 M-bit memory size is represented with the DEVSIZE=25 decimal=0x19 hex, that we see when debugging the project as shown in the below figure. 

KDJEM1_2-1692089659313.png

In conclusion the "Device Size" in STM32cubeMX  is DCR1_DEVSIZE+1. 

This confusion will be explained in the AN5050 next revision.

Thank you.

Kaouthar

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

>>For this example: 512 Mbytes memory size is represented with the DEVSIZE=25 decimal=0x19 hex, that we see when debugging the project as shown in the below figure. 

2**26 = 64 MByte or 512 Mbit

0x90000000..0x9FFFFFFF decode window is 256 MByte (2 Gbit)

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

I met same "ST HAL calamity" when develop with NUCLEO-L552ZE-Q + W25Q128JVSIQ.
But finally achived to read FONTX2 datas by MemoryMappedMode.

Here is my GCC example for STM32L5,and see ./src/ospi_mmap_if.c for OCTO-SPI detail codes.
http://nemuisan.blog.bai.ne.jp/?eid=192848#STM32L5

Cheers, Nemui.