Skip to main content
Explorer
July 5, 2024
Question

Problem with integration of W25Q128JV on STM32U5A9

  • July 5, 2024
  • 3 replies
  • 4188 views

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;

}

 

    This topic has been closed for replies.

    3 replies

    Graduate II
    July 5, 2024

    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;
    ...
    Graduate II
    July 5, 2024
    Graduate II
    July 5, 2024

    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

    Explorer
    July 6, 2024

    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

    Graduate II
    July 6, 2024

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

    Well it will preclude XIP / Memory Mapped mode operation.