cancel
Showing results for 
Search instead for 
Did you mean: 

Problem with integration of W25Q128JV on STM32U5A9

Edward_1583
Associate II

I'm working on a project where I use the STM32U5A9 microcontroller to control the W25Q128JV flash memory. I wrote a library to interact with this flash memory, but unfortunately I can't get it set up correctly.

The problem is that commands are sent incorrectly when this piece of code in the enableQuadMode function is executed:

 

 CS_ENABLE();



OSPI_RegularCmdTypeDef sCommand = {0};

uint8_t reg;

HAL_StatusTypeDef res;



sCommand.OperationType = READ_STATUS_REG_CMD;

sCommand.FlashId = HAL_OSPI_FLASH_ID_1;

sCommand.DQSMode = HAL_OSPI_DQS_DISABLE;

sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD;

sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;

sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS;

sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE;

sCommand.Instruction = READ_STATUS_REG2_CMD;

sCommand.AddressMode = HAL_OSPI_ADDRESS_NONE;

sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;

sCommand.DataMode = HAL_OSPI_DATA_NONE;

sCommand.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE;

sCommand.DummyCycles = 0;

sCommand.NbData = 1;



res = HAL_OSPI_Command(&hospi1, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE);

if(res != HAL_OK) {

return res;

}

 

the logic analyzer displays this:

Edward_1583_0-1720183493377.png

Maybe any of you have faced a similar problem or can suggest some steps to solve it? Any help or guidance would be greatly appreciated!

Thanks in advance!

Settings OCTOSPI:

 

void MX_OCTOSPI1_Init(void)

{



/* USER CODE BEGIN OCTOSPI1_Init 0 */



/* USER CODE END OCTOSPI1_Init 0 */



OSPIM_CfgTypeDef sOspiManagerCfg = {0};

 HAL_OSPI_DLYB_CfgTypeDef HAL_OSPI_DLYB_Cfg_Struct = {0};



/* USER CODE BEGIN OCTOSPI1_Init 1 */



/* USER CODE END OCTOSPI1_Init 1 */

 hospi1.Instance = OCTOSPI1;

 hospi1.Init.FifoThreshold = 1;

 hospi1.Init.DualQuad = HAL_OSPI_DUALQUAD_DISABLE;

 hospi1.Init.MemoryType = HAL_OSPI_MEMTYPE_MICRON;

 hospi1.Init.DeviceSize = 24;

 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 = 64-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.MaxTran = 0;

 hospi1.Init.Refresh = 0;

if (HAL_OSPI_Init(&hospi1) != HAL_OK)

{

Error_Handler();

}

sOspiManagerCfg.ClkPort = 1;

sOspiManagerCfg.IOLowPort = HAL_OSPIM_IOPORT_1_LOW;

sOspiManagerCfg.Req2AckTime = 1;

if (HAL_OSPIM_Config(&hospi1, &sOspiManagerCfg, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)

{

Error_Handler();

}

HAL_OSPI_DLYB_Cfg_Struct.Units = 0;

HAL_OSPI_DLYB_Cfg_Struct.PhaseSel = 0;

if (HAL_OSPI_DLYB_SetConfig(&hospi1, &HAL_OSPI_DLYB_Cfg_Struct) != HAL_OK)

{

Error_Handler();

}

/* USER CODE BEGIN OCTOSPI1_Init 2 */



/* USER CODE END OCTOSPI1_Init 2 */



}

 


My code:

 

/*

 * external_flash_driver.c

 *

 * Created on: Jun 11, 2024

 * Author: nhrabets

 */



#include "main.h"



#include "octospi.h"



#include "external_flash_driver.h"





#define CS_ENABLE() HAL_GPIO_WritePin(QSPI_CS_GPIO_Port, QSPI_CS_Pin, 0)

#define CS_DISABLE() HAL_GPIO_WritePin(QSPI_CS_GPIO_Port, QSPI_CS_Pin, 1)





static uint8_t writeEnable(void)

{

 CS_ENABLE();



OSPI_RegularCmdTypeDef sCommand = {0};

OSPI_AutoPollingTypeDef sConfig = {0};

HAL_StatusTypeDef res;



sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG;

sCommand.FlashId = HAL_OSPI_FLASH_ID_1;

sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;

sCommand.Instruction = WRITE_ENABLE_CMD;

sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS;

sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE;

sCommand.AddressMode = HAL_OSPI_ADDRESS_NONE;

sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;

sCommand.DataMode = HAL_OSPI_DATA_NONE;

sCommand.DummyCycles = 0;

sCommand.DQSMode = HAL_OSPI_DQS_DISABLE;

sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD;



res = HAL_OSPI_Command(&hospi1, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE);

if(res != HAL_OK) {

return res;

}



 CS_DISABLE();



return HAL_OK;



}



static uint8_t enableQuadMode(void)

{

 CS_ENABLE();



OSPI_RegularCmdTypeDef sCommand = {0};

uint8_t reg;

HAL_StatusTypeDef res;



sCommand.OperationType = READ_STATUS_REG_CMD;

sCommand.FlashId = HAL_OSPI_FLASH_ID_1;

sCommand.DQSMode = HAL_OSPI_DQS_DISABLE;

sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD;

sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;

sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS;

sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE;

sCommand.Instruction = READ_STATUS_REG2_CMD;

sCommand.AddressMode = HAL_OSPI_ADDRESS_NONE;

sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;

sCommand.DataMode = HAL_OSPI_DATA_NONE;

sCommand.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE;

sCommand.DummyCycles = 0;

sCommand.NbData = 1;



res = HAL_OSPI_Command(&hospi1, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE);

if(res != HAL_OK) {

return res;

}



res = HAL_OSPI_Receive(&hospi1, &reg, HAL_OSPI_TIMEOUT_DEFAULT_VALUE);

if(res != HAL_OK) {

return res;

}



sCommand.DataMode = HAL_OSPI_DATA_NONE;

sCommand.Instruction = VOLATILE_SR_WRITE_ENABLE;



res = HAL_OSPI_Command(&hospi1, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE);

if(res != HAL_OK) {

return res;

}



sCommand.DataMode = HAL_OSPI_DATA_1_LINE;

sCommand.Instruction = WRITE_STATUS_REG2_CMD;

reg |= 0x02;



res = HAL_OSPI_Command(&hospi1, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE);

if(res != HAL_OK) {

return res;

}



res = HAL_OSPI_Transmit(&hospi1, &reg, HAL_OSPI_TIMEOUT_DEFAULT_VALUE);

if(res != HAL_OK) {

return res;

}



 CS_DISABLE();



return HAL_OK;

}



static uint8_t qspiConfiguration(void)

{

 CS_ENABLE();



OSPI_RegularCmdTypeDef sCommand = {0};

HAL_StatusTypeDef res;

uint8_t reg;



sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;

sCommand.Instruction = READ_STATUS_REG3_CMD;

sCommand.AddressMode = HAL_OSPI_ADDRESS_NONE;

sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;

sCommand.DataMode = HAL_OSPI_DATA_1_LINE;

sCommand.DummyCycles = 0;

sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD;

sCommand.NbData = 1;



res = HAL_OSPI_Command(&hospi1, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE);

if(res != HAL_OK) {

return res;

}



res = HAL_OSPI_Receive(&hospi1, &reg, HAL_OSPI_TIMEOUT_DEFAULT_VALUE);

if(res != HAL_OK) {

return res;

}



sCommand.Instruction = WRITE_STATUS_REG3_CMD;

reg &= 0x9F;



res = HAL_OSPI_Command(&hospi1, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE);

if(res != HAL_OK) {

return res;

}



res = HAL_OSPI_Transmit(&hospi1, &reg, HAL_OSPI_TIMEOUT_DEFAULT_VALUE);

if(res != HAL_OK) {

return res;

}



 CS_DISABLE();



return HAL_OK;

}



uint8_t EFD_init(void)

{

if(enableQuadMode() != HAL_OK) {

return HAL_ERROR;

}



if(writeEnable() != HAL_OK) {

return HAL_ERROR;

}



if(qspiConfiguration() != HAL_OK) {

return HAL_ERROR;

}



HAL_Delay(100);



return HAL_OK;

}



uint8_t EFD_eraseChip(void)

{

 CS_ENABLE();



OSPI_RegularCmdTypeDef sCommand = {0};

HAL_StatusTypeDef res;



if(writeEnable() != HAL_OK) {

return HAL_ERROR;

}



sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;

sCommand.Instruction = CHIP_ERASE_CMD;

sCommand.AddressMode = HAL_OSPI_ADDRESS_NONE;

sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;

sCommand.DataMode = HAL_OSPI_DATA_NONE;

sCommand.DummyCycles = 0;

sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD;



res = HAL_OSPI_Command(&hospi1, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE);

if(res != HAL_OK) {

return HAL_ERROR;

}



 CS_DISABLE();



return HAL_OK;

}



uint8_t EFD_writeData(uint8_t* pBuffer, uint32_t address, uint32_t bufferSize)

{

 CS_ENABLE();



OSPI_RegularCmdTypeDef sCommand = {0};

HAL_StatusTypeDef res;

uint32_t endAddr;

uint32_t currentSize;

uint32_t currentAddr = 0;



while(currentAddr <= address) {

currentAddr += MEMORY_PAGE_SIZE;

}

currentSize = currentAddr - address;



if(currentSize > bufferSize) {

currentSize = bufferSize;

}



currentAddr = address;

endAddr = address + bufferSize;



sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;

sCommand.Instruction = QUAD_IN_FAST_PROG_CMD;

sCommand.AddressMode = HAL_OSPI_ADDRESS_1_LINE;

sCommand.AddressSize = HAL_OSPI_ADDRESS_24_BITS;

sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;

sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD;

sCommand.DataMode = HAL_OSPI_DATA_1_LINE;

sCommand.NbData = bufferSize;

sCommand.Address = address;

sCommand.DummyCycles = 0;



do {

sCommand.Address = currentAddr;

sCommand.NbData = currentSize;



if(currentSize == 0) {

return HAL_OK;

}



if(writeEnable() != HAL_OK) {

return HAL_ERROR;

}



res = HAL_OSPI_Command(&hospi1, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE);

if(res != HAL_OK) {

return HAL_ERROR;

}



res = HAL_OSPI_Transmit(&hospi1, pBuffer, HAL_OSPI_TIMEOUT_DEFAULT_VALUE);

if(res != HAL_OK) {

return HAL_ERROR;

}



currentAddr += currentSize;

pBuffer += currentSize;

currentSize = ((currentAddr + MEMORY_PAGE_SIZE) > endAddr) ?

(endAddr - currentAddr) : MEMORY_PAGE_SIZE;

} while(currentAddr <= endAddr);



 CS_DISABLE();



return HAL_OK;

}



uint8_t EFD_readData(uint8_t* pBuffer, uint32_t address, uint32_t bufferSize)

{

 CS_ENABLE();



OSPI_RegularCmdTypeDef sCommand = {0};

HAL_StatusTypeDef res;



sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;

sCommand.Instruction = QUAD_OUT_FAST_READ_CMD;

sCommand.AddressMode = HAL_OSPI_ADDRESS_4_LINES;

sCommand.AddressSize = HAL_OSPI_ADDRESS_24_BITS;

sCommand.Address = address;

sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;

sCommand.DataMode = HAL_OSPI_DATA_4_LINES;

sCommand.DummyCycles = 0;

sCommand.NbData = bufferSize;

sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD;



res = HAL_OSPI_Command(&hospi1, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE);

if(res != HAL_OK) {

return HAL_ERROR;

}



res = HAL_OSPI_Receive(&hospi1, pBuffer, HAL_OSPI_TIMEOUT_DEFAULT_VALUE);

if(res != HAL_OK) {

return HAL_ERROR;

}



 CS_DISABLE();



return HAL_OK;

}

 

11 REPLIES 11

Not clear what you see vs expect.

Certainly an excessive amount of whitespace, like you've not directly pasted from the original  source

sCommand.OperationType = READ_STATUS_REG_CMD; // << NO !! THIS IS NOT THE COMMAND

Lot of code missing on nearly every subroutine using sCommand

sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG;

sCommand.FlashId = HAL_OSPI_FLASH_ID_1;

sCommand.DQSMode = HAL_OSPI_DQS_DISABLE;
sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD;
...
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Related to this poster, or strange coincident?  https://community.st.com/t5/stm32-mcus-embedded-software/connecting-w25q128jv-via-octospi-in-quadspi-mode-on-stm32u5a9/td-p/693688

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

Why on Earth are you driving the Chip Select manually? Chose the wrong pin in fabricated PCB?

Please enumerate the pins use in your implementation

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

Thank you for your response.
Yes, on the board I am using, the Chip Select is chosen incorrectly. Can this significantly affect the operation if I control it manually?
Pinout:
OCTOSPIM_P1_IO3 - PF6
OCTOSPIM_P1_IO2 - PF7
OCTOSPIM_P1_IO0 - PF8
OCTOSPIM_P1_IO1 - PF9
OCTOSPIM_P1_CLK - PF10
CS - PF11

>>Can this significantly affect the operation if I control it manually?

Well it will preclude XIP / Memory Mapped mode operation.

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

Soldered a jumper and set CS in .ioc, but it always remains in the high state. What could this be related to? Could you possibly provide an example? That would be really helpful.

Wired it to what/how exactly, I've got zero visibility here. Are you scoping the right pins?

Still as a GPIO, or to a pin designated for OCTO SPI NCS?

Writing comprehensive examples gets to be actual work.

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

Ok, I`m trying to send data by sending instruction 0x32 Quad Input Page Program but during HAL_OSPI_Transmit function executing I have problem that hospi->State = HAL_OSPI_STATE_WRITE_CMD_CFG but in function we have the checking  if (hospi->State == HAL_OSPI_STATE_CMD_CFG) and I got error. What I need to do to write data to this Flash? Can you give me some information for workflow to do this process with this config (STm32U5 + W25Q32JVSIQ)?

 

 

Wow, that's a bit of a dog's breakfast of random cut-n-paste. Couple of hours of work to fix that mess.

For things to work everything needs to be consistent and correct. When not in 4-4-4 you can't send things in 4-4-4. Winbond's need the QE bit in Status Registers to enable the extending bit pins. When writing registers / memory or erasing, need to wait for operations to complete.

PA4:AF3 NCS

PF10:AF3 CLK

PF8:AF10 D0

PF9:AF10 D1

PF7:AF10 D2

PF6:AF10 D3

https://github.com/cturvey/stm32extldr/tree/main/u5_w25q32

 

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