cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H723 wrong data when interfacing QuadSPI & OctoSPI RAM

franckngatcha
Associate II

Starting from a working application based on the STM32U585A microcontroller, we changed the CPU to have the ETHERNET peripheral available. The flash is connected via quadSPI to the microcontroller, while the RAM is connected via octospi .

Microcontroller Model: STM32H723ZGT6 FLASH MODEL: S25FL064L DRAM MODEL: APS6408L

Regarding the configuration operations of both the flash and the RAM, everything seems to work, but when it comes to reading or writing, we receive incorrect data once out of 10 attempts. Note that we have a working application with the STM32U5 microcontroller using the same flash and RAM.

Any idea on what I’m I missing?

Flash initializzation

void MX_OCTOSPI2_Init(void)

{



  /* USER CODE BEGIN OCTOSPI2_Init 0 */



  /* USER CODE END OCTOSPI2_Init 0 */



  OSPIM_CfgTypeDef sOspiManagerCfg = {0};



  /* USER CODE BEGIN OCTOSPI2_Init 1 */



  /* USER CODE END OCTOSPI2_Init 1 */

  hospi2.Instance = OCTOSPI2;

  hospi2.Init.FifoThreshold = 1;

  hospi2.Init.DualQuad = HAL_OSPI_DUALQUAD_DISABLE;

  hospi2.Init.MemoryType = HAL_OSPI_MEMTYPE_MICRON;

  hospi2.Init.DeviceSize = 23;

  hospi2.Init.ChipSelectHighTime = 1;

  hospi2.Init.FreeRunningClock = HAL_OSPI_FREERUNCLK_DISABLE;

  hospi2.Init.ClockMode = HAL_OSPI_CLOCK_MODE_0;

  hospi2.Init.WrapSize = HAL_OSPI_WRAP_NOT_SUPPORTED;

  hospi2.Init.ClockPrescaler = 4;

  hospi2.Init.SampleShifting = HAL_OSPI_SAMPLE_SHIFTING_NONE;

  hospi2.Init.DelayHoldQuarterCycle = HAL_OSPI_DHQC_DISABLE;

  hospi2.Init.ChipSelectBoundary = 0;

  hospi2.Init.DelayBlockBypass = HAL_OSPI_DELAY_BLOCK_BYPASSED;

  hospi2.Init.MaxTran = 0;

  hospi2.Init.Refresh = 0;

  if (HAL_OSPI_Init(&hospi2) != HAL_OK)

  {

    Error_Handler();

  }

  sOspiManagerCfg.ClkPort = 2;

  sOspiManagerCfg.NCSPort = 2;

  sOspiManagerCfg.IOLowPort = HAL_OSPIM_IOPORT_2_LOW;

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

  {

    Error_Handler();

  }

  /* USER CODE BEGIN OCTOSPI2_Init 2 */



  /* USER CODE END OCTOSPI2_Init 2 */



}



Funzione per leggere la flash

uint8_t bsp_ospi_flash_Read       (uint8_t* pData, uint32_t ReadAddr, uint32_t Size)

{

               OSPI_RegularCmdTypeDef     sCommand;

               /* Initialize the read command */

               sCommand.OperationType      = HAL_OSPI_OPTYPE_COMMON_CFG;

               sCommand.FlashId            = HAL_OSPI_FLASH_ID_1;

               sCommand.Instruction        = 0x6B;

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

               sCommand.AddressSize        = HAL_OSPI_ADDRESS_24_BITS;

               sCommand.AddressDtrMode     = HAL_OSPI_ADDRESS_DTR_DISABLE;

               sCommand.Address            = ReadAddr;

               sCommand.DataMode           = HAL_OSPI_DATA_4_LINES;

               sCommand.DummyCycles        = 8;

               sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;

               sCommand.DataDtrMode        = HAL_OSPI_DATA_DTR_DISABLE;

               sCommand.SIOOMode           = HAL_OSPI_SIOO_INST_EVERY_CMD;

               sCommand.NbData             = Size;



               /* Configure the command */

               if (HAL_OSPI_Command(&hospi2, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)

               {

                              return OSPI_ERROR;

               }



               /* Reception of the data */

               if (HAL_OSPI_Receive(&hospi2, pData, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)

               {

                              return OSPI_ERROR;

               }



               return OSPI_OK;

}



Flash write

uint8_t bsp_ospi_flash_WriteMemory      (uint8_t* pData, uint32_t WriteAddr, uint32_t Size)

{

               OSPI_RegularCmdTypeDef     sCommand;

               uint32_t end_addr, current_size, current_addr;



               /* Calculation of the size between the write address and the end of the page */

               current_size = S25FL064_PAGE_SIZE - (WriteAddr % S25FL064_PAGE_SIZE);



               /* Check if the size of the data is less than the remaining place in the page */

               if (current_size > Size)

               {

                              current_size = Size;

               }



               /* Initialize the adress variables */

               current_addr = WriteAddr;

               end_addr = WriteAddr + Size;



               /* Initialize the program command */

               sCommand.OperationType      = HAL_OSPI_OPTYPE_COMMON_CFG;

               sCommand.FlashId            = HAL_OSPI_FLASH_ID_1;

               sCommand.Instruction        = 0x32;

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

               sCommand.Address            = WriteAddr;

               sCommand.AddressSize        = HAL_OSPI_ADDRESS_24_BITS;

               sCommand.AddressDtrMode     = HAL_OSPI_ADDRESS_DTR_DISABLE;

               sCommand.DataMode           = HAL_OSPI_DATA_4_LINES;

               sCommand.DummyCycles        = 0;

               //           sCommand.DQSMode            = HAL_OSPI_DQS_ENABLE;

               sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;

               sCommand.DataDtrMode        = HAL_OSPI_DATA_DTR_DISABLE;

               sCommand.SIOOMode           = HAL_OSPI_SIOO_INST_EVERY_CMD;

               sCommand.NbData             = 0;



               /* Perform the write page by page */

               do

               {

                              sCommand.Address = current_addr;

                              sCommand.NbData  = current_size;



                              /* Enable write operations */

                              if (OSPI_WriteEnable(&hospi2) != OSPI_OK)

                              {

                                            return OSPI_ERROR;

                              }



                              /* Configure the command */

                              if (HAL_OSPI_Command(&hospi2, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)

                              {

                                            return OSPI_ERROR;

                              }



                              /* Transmission of the data */

                              if (HAL_OSPI_Transmit(&hospi2, pData, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)

                              {

                                            return OSPI_ERROR;

                              }



                              /* Configure automatic polling mode to wait for end of program */

                              if (OSPI_AutoPollingMemReady(&hospi2, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != OSPI_OK)

                              {

                                            return OSPI_ERROR;

                              }

                              /* Update the address and size variables for next page programming */

                              current_addr += current_size;

                              pData += current_size;

                              current_size = ((current_addr + S25FL064_PAGE_SIZE) > end_addr) ? (end_addr - current_addr) : S25FL064_PAGE_SIZE;

               }

               while (current_addr < end_addr);



               return OSPI_OK;

}

uint8_t bsp_ospi_flash_EnableMemoryMappedMode(void)

{

               uint8_t ret=OSPI_OK;

               OSPI_RegularCmdTypeDef     sCommand;

               OSPI_MemoryMappedTypeDef sMemMappedCfg;



               sCommand.OperationType      = HAL_OSPI_OPTYPE_COMMON_CFG;

               sCommand.FlashId            = HAL_OSPI_FLASH_ID_1;

               sCommand.Instruction        = 0xEB;

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

               sCommand.AddressSize        = HAL_OSPI_ADDRESS_24_BITS;

               sCommand.AddressDtrMode     = HAL_OSPI_ADDRESS_DTR_DISABLE;

               sCommand.DataMode           = HAL_OSPI_DATA_4_LINES;

               sCommand.DummyCycles        = S25FL064_DUMMY_CYCLES_READ;

               sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_4_LINES;

               sCommand.AlternateBytes     = 0x2;

               sCommand.AlternateBytesSize = HAL_OSPI_ALTERNATE_BYTES_8_BITS;

               sCommand.DataDtrMode        = HAL_OSPI_DATA_DTR_DISABLE;

               sCommand.SIOOMode           = HAL_OSPI_SIOO_INST_EVERY_CMD;



               if (HAL_OSPI_Command(&hospi2, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)

               {

                              return OSPI_ERROR;

               }

               sMemMappedCfg.TimeOutActivation = HAL_OSPI_TIMEOUT_COUNTER_DISABLE;

               sMemMappedCfg.TimeOutPeriod     = 0x34;

               if (HAL_OSPI_MemoryMapped(&hospi2, &sMemMappedCfg) != HAL_OK)

               {

                              return OSPI_ERROR;

               }



               return ret;

}





RAM OCTOSPI INIT

/* OCTOSPI1 init function */

void MX_OCTOSPI1_Init(void)

{



  /* USER CODE BEGIN OCTOSPI1_Init 0 */



  /* USER CODE END OCTOSPI1_Init 0 */



  OSPIM_CfgTypeDef sOspiManagerCfg = {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_APMEMORY;

  hospi1.Init.DeviceSize = 23;

  hospi1.Init.ChipSelectHighTime = 2;

  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 = 2;

  hospi1.Init.SampleShifting = HAL_OSPI_SAMPLE_SHIFTING_NONE;

  hospi1.Init.DelayHoldQuarterCycle = HAL_OSPI_DHQC_ENABLE;

  hospi1.Init.ChipSelectBoundary = 0;

  hospi1.Init.DelayBlockBypass = HAL_OSPI_DELAY_BLOCK_USED;

  hospi1.Init.MaxTran = 10;

  hospi1.Init.Refresh = 0;

  if (HAL_OSPI_Init(&hospi1) != HAL_OK)

  {

    Error_Handler();

  }

  sOspiManagerCfg.ClkPort = 1;

  sOspiManagerCfg.DQSPort = 1;

  sOspiManagerCfg.NCSPort = 1;

  sOspiManagerCfg.IOLowPort = HAL_OSPIM_IOPORT_1_LOW;

  sOspiManagerCfg.IOHighPort = HAL_OSPIM_IOPORT_1_HIGH;

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

  {

    Error_Handler();

  }

  /* USER CODE BEGIN OCTOSPI1_Init 2 */



  /* USER CODE END OCTOSPI1_Init 2 */



}



static void Configure_APMemory(void)

{

               /* MR0 register for read and write */

               uint8_t regW_MR0[2]={0x24,0x0D}; /* To configure AP memory Latency Type and drive Strength */

               uint8_t regR_MR0[2]={0};



               /* MR8 register for read and write */

               uint8_t regW_MR8[2]={0x0B,0x08}; /* To configure AP memory Burst Type */

               uint8_t regR_MR8[2]={0};



               /*Read Latency */

               uint8_t latency=6;



               /* Configure Read Latency and drive Strength */

               if (APS6408_WriteReg(&hospi1, MR0, regW_MR0) != HAL_OK)

               {

                              Error_Handler();

               }



               /* Check MR0 configuration */

               if (APS6408_ReadReg(&hospi1, MR0, regR_MR0, latency ) != HAL_OK)

               {

                              Error_Handler();

               }



               /* Check MR0 configuration */

               if (regR_MR0 [0] != regW_MR0 [0])

               {

                              Error_Handler() ;

               }



               /* Configure Burst Length */

               if (APS6408_WriteReg(&hospi1, MR8, regW_MR8) != HAL_OK)

               {

                              Error_Handler();

               }



               /* Check MR8 configuration */

               if (APS6408_ReadReg(&hospi1, MR8, regR_MR8, 6) != HAL_OK)

               {

                              Error_Handler();

               }



               if (regR_MR8[0] != regW_MR8[0])

               {

                              Error_Handler() ;

               }

}

Meory mapped mode



uint8_t bsp_ospi_ram_EnableMemoryMappedMode(void)

{

               OSPI_RegularCmdTypeDef sCommand = {0};

               OSPI_MemoryMappedTypeDef sMemMappedCfg;

               /*Configure Memory Mapped mode*/

               sCommand.OperationType      = HAL_OSPI_OPTYPE_WRITE_CFG;

               sCommand.FlashId            = HAL_OSPI_FLASH_ID_1;

               sCommand.Instruction        = WRITE_CMD;

               sCommand.InstructionMode    = HAL_OSPI_INSTRUCTION_8_LINES;

               sCommand.InstructionSize    = HAL_OSPI_INSTRUCTION_16_BITS;

               sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_ENABLE;

               sCommand.AddressMode        = HAL_OSPI_ADDRESS_8_LINES;

               sCommand.AddressSize        = HAL_OSPI_ADDRESS_32_BITS;

               sCommand.AddressDtrMode     = HAL_OSPI_ADDRESS_DTR_ENABLE;

               sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;

               sCommand.DataMode           = HAL_OSPI_DATA_8_LINES;

               sCommand.DataDtrMode        = HAL_OSPI_DATA_DTR_ENABLE;

               sCommand.DummyCycles        = DUMMY_CLOCK_CYCLES_WRITE;

               sCommand.DQSMode            = HAL_OSPI_DQS_ENABLE;

               sCommand.SIOOMode           = HAL_OSPI_SIOO_INST_EVERY_CMD;



               if (HAL_OSPI_Command(&hospi1, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)

               {

                              Error_Handler();

               }



               sCommand.OperationType = HAL_OSPI_OPTYPE_READ_CFG;

               sCommand.Instruction   = READ_CMD;

               sCommand.DummyCycles   = DUMMY_CLOCK_CYCLES_READ;



               if (HAL_OSPI_Command(&hospi1, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)

               {

                              Error_Handler();

               }



               sMemMappedCfg.TimeOutActivation = HAL_OSPI_TIMEOUT_COUNTER_ENABLE;

               sMemMappedCfg.TimeOutPeriod     = 0x34;



               if (HAL_OSPI_MemoryMapped(&hospi1, &sMemMappedCfg) != HAL_OK)

               {

                              Error_Handler();

               }

               return 0;

}

 


Edited to apply source code formatting - please see How to insert source code for future reference.

 

8 REPLIES 8
Saket_Om
ST Employee

Hello @franckngatcha 

Please refer to the example below: 

STM32CubeU5/Projects/STM32U5x9J-DK/Examples/OSPI/OSPI_NOR_MemoryMapped at main · STMicroelectronics/STM32CubeU5 · GitHub

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.
Saket_Om
franckngatcha
Associate II
Hi Saket,
 
I apologize if my previous message was unclear. I'm currently facing issues interfacing the STM32H723 microcontroller with the OCTSPI interface, despite using the same application driver, FLASH part number, and RAM part number as the STM32U585 microcontroller. We employ the same driver, but while the data read with the STM32U5 is accurate, the data read with the STM32H723 is not. Even reducing the speed hasn't resolved the issue. I'd like to share with you the OCTSPI1 (for the OSPI RAM) and OCTOSPI2 (for the QUADSPI flash initialization). At this moment, I'm unsure what's missing.
 
Best regards,
Franck

Hello @franckngatcha 

Did you set the same clock config for OCTOSPI as U5 ?

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.
Saket_Om
franckngatcha
Associate II

Hi sacket_Om,

we'd configure the flash and the ram to run at 50MHZ 

franckngatcha_0-1751879819868.png

 

franckngatcha_1-1751879819874.png

 

franckngatcha_2-1751879819881.png

i've tried to reduce that speed without result.

Franck

 

Hello @franckngatcha 

Please try to use the same OCTOSPI initialization setting as in U5 examples.

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.
Saket_Om
franckngatcha
Associate II

hi SACKET_OM ,

 i share with you the two examples i'd made, one for the SRAM and the other one for the QUADSPI flash? i already have a working application on the U5 microcontroller with both the flash and the SRAM and we've move the application to the STM32H723 microcontroller.  the only difference is on the use of SDR instead of DTR communication on the QUADSPI FLASH.

Hello @franckngatcha 

Did you try with DTR mode ?

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.
Saket_Om
franckngatcha
Associate II

hi Sacket,

i already use DTR for the RAM and SDR for the flash .

with the RAM on DTR writing a buffer and read it back some datas are correct some not ! 

 

Franck.