2024-07-05 05:51 AM
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:
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, ®, 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, ®, 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, ®, 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, ®, 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;
}
2024-07-13 08:18 AM
What is this link?
2024-07-13 09:01 AM
An external loader for your pin configuration which should be usable with STM32 Cube Programmer.