2020-11-27 04:38 AM
Hi,
There's no CubeMX example of STM32H72x OCTOSPI configuration for QUAD SPI NOR flash, neither in the AN5050.
Is there some example for that?
2020-11-27 04:44 AM
There's quite a few octospi examples in the STM32CubeH7 repository. Here's one:
Examples for other chips within the family should not need many, if any, changes.
2020-11-27 07:33 AM
Thanks TDK,
but I need an example or orientation how to use the OCTOSPI in QUAD SPI mode for NOR Flash. I don't understand how ST didn't predict that people would need to know how to use QUADSPI nor flash in the OCTOSPI interface. There should be an application note for that.
2020-12-07 02:11 PM
Hi,
I could port the erase function and the function that put the quad-spi flash in memory mapped mode. So I can erase and read the quad-spi nor flash. However, my flash programming function only programs the first two bytes.
For example:
if I do:
QSPI_EraseFlash(0);
for(i=0;i<256;i++) TxBuffer[i] = 0x31+i;
QSPI_WriteFlash(TxBuffer, 0,256);
Memory_Mapped_Mode();
QSPI_ReadFlash_MP(RxBuffer,0,256);
RxBuffer = 0x31, 0x32, 0xFF, 0xFF,...,0xFF
And, if I do:
QSPI_EraseFlash(0);
for(i=0;i<256;i++) TxBuffer[i] = 0x31+i;
QSPI_WriteFlash(TxBuffer, 0,256);
QSPI_WriteFlash(TxBuffer, 2,256);
Memory_Mapped_Mode();
QSPI_ReadFlash_MP(RxBuffer,0,256);
RxBuffer = 0x31, 0x32, 0x31, 0x32,0xFF,...,0xFF
I need help to figure out what's wrong with the function:
(The result is the same for sCommand.DataMode = HAL_OSPI_DATA_4_LINES and for sCommand.DataMode = HAL_OSPI_DATA_1_LINE)
void QSPI_WriteFlash(uint8_t* buf, uint32_t addr, uint32_t len)
{
OSPI_RegularCmdTypeDef sCommand;
OSPI_WriteEnable(&hospi1);
sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG;
sCommand.FlashId = HAL_OSPI_FLASH_ID_1;
sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;
sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS;
sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE;
sCommand.AddressSize = HAL_OSPI_ADDRESS_24_BITS;
sCommand.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE;
sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;
sCommand.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE;
sCommand.DQSMode = HAL_OSPI_DQS_DISABLE;
sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD;
sCommand.AddressMode = HAL_OSPI_ADDRESS_1_LINE;
//sCommand.DataMode = HAL_OSPI_DATA_4_LINES;
sCommand.DataMode = HAL_OSPI_DATA_1_LINE;
//sCommand.Instruction = 0x32; // QUAD_IN_FAST_PROG_CMD
sCommand.Instruction = 0x02; // QUAD_IN_FAST_PROG_CMD
sCommand.Address = addr;
sCommand.NbData = len;
sCommand.DummyCycles = 0;
if (HAL_OSPI_Command(&hospi1, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
if (HAL_OSPI_Transmit(&hospi1, buf,HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
//OSPI_AutoPollingMemReady(&hospi1);
HAL_Delay(200);
}
2020-12-08 05:42 AM
When call the funciont HAL_QSPI_Transmit from a H743 board. The transfer bytes between CS_LOW and CS_HIGH are: 0x02 0x00 0x00 0x00 0x41 0x42 0x43 0x44
Programming correctly the bytes 0x41, 0x42, 0x43 and 0x44 at address 0;
When call the HAL_OSPI_Transmit function in the function QSPI_WriteFlash above, from a H723 board. The transfer bytes between the first CS_LOW and CS_HIGH are: 0x02 0x00 0x00 0x00 0x41 0x42 and for the second CS_LOW and CS_HIGH are: 0x02 0x00 0x00 0x2 0x43 0x44. Programming only the bytes 0x41 and 0x42 at address 0.
I tried the HAL_OSPI_Transmit_IT function with the same result.
Does it have a bug in the function HAL_OSPI_Transmit when used in Quad SPI mode?
Has anyone used this function to program a QUAD SPI NOR FLASH?
2024-12-04 06:43 AM
Raising this from the dead...but were you/anyone able to figure this out? I'm also attempting to do the same.
2024-12-04 07:04 AM
Yes, it's not that hard. ie Not Rocket Sciencery
ST doesn't typically provide examples for every possible use case, they show how THEIR boards work, and they provide Reference Manuals defining HOW the HW works. Plus all the source to the HAL is provided.
For H7Ax / H72x how to send an 8-bit read command to a Quad SPI device in it's 1-Bit base mode
//****************************************************************************
static uint8_t OSPI_ReadStatus(OSPI_HandleTypeDef *hospi, uint32_t Reg, uint32_t *pStatusReg)
{
OSPI_RegularCmdTypeDef sCommand = {0};
uint32_t data[2] = {0};
sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG;
sCommand.FlashId = HAL_OSPI_FLASH_ID_1;
sCommand.NbData = 1;
switch(Reg)
{
case 0 : sCommand.Instruction = READ_STATUS_REG1_CMD; break; // REG1
case 1 : sCommand.Instruction = READ_STATUS_REG2_CMD; break; // REG2
case 2 : sCommand.Instruction = READ_STATUS_REG3_CMD; break; // REG3
case 0x9F : // READID
sCommand.Instruction = 0x9F;
sCommand.NbData = 3;
break;
default:
return(OSPI_ERROR);
}
#ifdef DUAL
sCommand.NbData <<= 1;
#endif // DUAL
sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;
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_1_LINE;
sCommand.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE;
sCommand.DummyCycles = 0;
sCommand.DQSMode = HAL_OSPI_DQS_DISABLE;
sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD;
/* Send the command */
if (HAL_OSPI_Command(hospi, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
return(OSPI_ERROR);
}
/* Receive the data */
if (HAL_OSPI_Receive(hospi, (void *)data, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
return(OSPI_ERROR);
}
#ifdef DUAL
if (Reg == 0x9F) // RDID
data[0] = (data[0] & 0xFF) | ((data[0] & 0xFF0000) >> 16) | ((data[1] & 0xFF) << 16);
#endif // DUAL
if (pStatusReg)
*pStatusReg = data[0];
return(OSPI_OK);
}
//****************************************************************************
2024-12-04 07:10 AM
>>Raising this from the dead...but were you/anyone able to figure this out? I'm also attempting to do the same.
Perhaps start by describing your exact situation, this is a 4 year old thread
What STM32 part?
What FLASH part?
What PINs are you using, details of clocks, board, etc.
Are you sure you've initialized the peripheral properly OSPI, OSPIM, high/low portion of the bus, ie IO[0..3]vs IO[4..7]. Chips paired an banked? Individual, etc.
2024-12-19 12:14 PM
I'll start a new thread for what I'm dealing with. I was hoping for a quick answer from the original poster to see if there was some obvious gotcha that he had worked through
2024-12-19 12:52 PM
>>obvious gotcha..
In the cutty-pasty sense, clearing large local/auto variables is strongly suggested, it helps when you skip field initialization, and random stack junk has undesirable results in HAL
OSPI_RegularCmdTypeDef sCommand = {0};
Part and command selection is done here now, and not in the HAL_xSPI_Init phase
sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG;
sCommand.FlashId = HAL_OSPI_FLASH_ID_1;
Some STM32 have OSPIM, others don't, and that can cause all kinds of pretzel logic in OSPI1 vs OSPI2, and pin mappings