cancel
Showing results for 
Search instead for 
Did you mean: 

STM32CubeMx configuration of the OCTOSPI for QUAD SPI NOR Flash.

Asantos
Senior

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?

9 REPLIES 9
TDK
Guru

There's quite a few octospi examples in the STM32CubeH7 repository. Here's one:

https://github.com/STMicroelectronics/STM32CubeH7/blob/beced99ac090fece04d1e0eb6648b8075e156c6c/Projects/STM32H735G-DK/Examples/OSPI/OSPI_HyperRAM_MemoryMapped/Src/main.c

Examples for other chips within the family should not need many, if any, changes.

If you feel a post has answered your question, please click "Accept as Solution".
Asantos
Senior

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.

Asantos
Senior

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);

 }

Asantos
Senior

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?

SMoon.2
Associate III

Raising this from the dead...but were you/anyone able to figure this out? I'm also attempting to do the same. 

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);
}

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

  

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

>>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.

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

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

https://community.st.com/t5/stm32-mcus-products/migrating-from-quad-spi-stm32h750-to-octo-spi-stm32h733/td-p/755438

>>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

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