cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H7B3LIHQ and MX25LM51245GXDI00 OctoSPI flash problem.

ABURM
Associate III

Hi.

I am using STM32H7B3LIHQ MCU, MX25LM51245GXDI00 OSPI flash, IS42S32800J-6BLI SDRAM and 24bit TFT screen. I used the schematic of the STM32H7B3I-EVAL (MB1331) board when creating the scheme. I wrote programs for FMC, OctoSPI and LTDC peripherals using the sample programs and they all worked. I also used the "AN5050" and "AN4861" application notes for OctoSPI and LTDC.Then I created a new project by bringing all these peripherals together. I activated TouchGFX and made the necessary configuration. I created a test screen with TouchGFX, compiled the project and it worked. I enabled external loader in debug configuration settings There are 2 different .stldr files. "MX25LM51245G_STM32H7B3I-EVAL-REVA.stldr" and "MX25LM51245G_STM32H7B3I-EVAL-REVB.stldr". I selected "MX25LM51245G_STM32H7B3I-EVAL-REVA.stldr".

Ekran görüntüsü 2024-05-31 160839.png

But when I want to add a new screen to the touchGfx project, I encounter the following error.

Ekran görüntüsü 2024-05-31 155348.png

I also need to see RAM, FLASH and OSPI details in the "memory region" window. But I can't see, it's empty.

Ekran görüntüsü 2024-05-31 155618.png

When I examined a few sample programs, the following lines in the content of the "FLASH.id" file caught my attention.

QUADSPI (r)    : ORIGIN = 0x90000000, LENGTH = 64M

and

      ExtFlashSection :
	{
		*(ExtFlashSection ExtFlashSection.*)
		*(.gnu.linkonce.r.*)
        . = ALIGN(0x4);
	} >QUADSPI

  FontFlashSection :
	{
		*(FontFlashSection FontFlashSection.*)
		*(.gnu.linkonce.r.*)
        . = ALIGN(0x4);
	} >QUADSPI

  TextFlashSection :
	{
		*(TextFlashSection TextFlashSection.*)
		*(.gnu.linkonce.r.*)
        . = ALIGN(0x4);
	} >QUADSPI

Frankly, I didn't fully understand this part. I couldn't find an explanation or example about this in the application notes or in internet. Do I need to manually edit the flash.id file to use OctoSPI memory?

Have a nice day.

1 ACCEPTED SOLUTION

Accepted Solutions

Hard Fault means you are accessing memory that you haven't memory mapped

No idea why you have this code

OSPI_WriteEnable(&hospi1);
OSPI_AutoPollingMemReady(&hospi1);

Or a global sCommand initialization.

Memory Mapping requires a suitable READ command template for the mode, address width, etc you have the memory device operating in.

For OSPI peripherals this is typically both a READ and WRITE, but you don't need a real write template.

https://github.com/STMicroelectronics/STM32CubeH7/tree/master/Projects/STM32H7B3I-DK/Examples/OSPI/OSPI_NOR_MemoryMapped_DTR

Also have a better Hard Fault Handler that outputs useful / actionable data, so it doesn't crash and die silently. Otherwise your support staff will have no means to diagnose / understand failures.

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

View solution in original post

7 REPLIES 7

The two versions of the board have slight different pin designations for the OCTOSPI interface. Your current battle is with the LINKER, not the LOADER

Your error with "FLASH Overflowed" is indicative that the .LD used is *NOT* directing content into the right MEMORY section. You need to make sure the linker is provided with the correct .LD file, and that describes the MEMORY, and steers the SECTIONs into it.

You can review the .MAP if the linker succeeds to see where things were physically placed.

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

Hi Tesla.

I examined the .map file of a working example program. All touchgfx images appear in QSPI (0x90000000).

ExtFlashSection
                0x0000000090000000  0x12f4db0
 *(ExtFlashSection ExtFlashSection.*)
 ExtFlashSection
                0x0000000090000000    0x2eff4 ./TouchGFX/generated/images/src/image_Antrikot.o
                0x0000000090000000                image_antrikot
 ExtFlashSection
                0x000000009002eff4    0x2eff4 ./TouchGFX/generated/images/src/image_AntrikotS.o
                0x000000009002eff4                image_antrikots
 ExtFlashSection
                0x000000009005dfe8     0x3300 ./TouchGFX/generated/images/src/image_Auto.o
                0x000000009005dfe8                image_auto

But in the project I created, all images are in internal flash (0x08000000). 

ExtFlashSection
                0x0804fd18   0x270598
 ExtFlashSection
                0x0804fd18   0x119400 ./TouchGFX/generated/images/src/wallpaper.o
                0x0804fd18            wallpaper
 ExtFlashSection
                0x08169118    0x38400 ./TouchGFX/generated/images/src/__generated/analog.o
                0x08169118              analog


 You said that; "You need to make sure the linker is provided with the correct .LD file, and that describes the MEMORY, and steers the SECTIONs into it." Could you please explain in detail how to do this?

No, STM32CubeIDE is not my IDE

The .LD should be pointed too somewhere in your project settings / metadata, presumably under some Linker Setting type tab or tree.

The Build dialog perhaps showing the paths and settings used in your Release / Debug build process.

Relate the settings in your working vs not-working projects, perhaps via a file viewer as these are typically ASCII / XML type constructs, so at least you should be able see or narrow down the associativity.

 

#TeamKeil

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

Hi Tesla.

I copied the lines of code from the working example project and pasted them into the .ld file in my own project. In the .map file, I saw that touchgfx objects were moved to address 0x90000000. I tried to compile and install the project, but CubeIDE crashed and I could not programming. I then tried again by selecting REVB.stldr of the external loader and programmed both the MCU and the OctoSPI flash. The program did not work (no image appeared on the TFT screen), but at least I can program it properly. FMC, LTDC and touchgfx is working good but I think I missing something about the OctoSPI init codes. 

It is very interesting that I cannot find a detailed explanation or application note on this subject. I will review the project again on Monday. Thank you for your support.

Best regards.

ABURM
Associate III

Hi.

I added manually the following codes to the "STM32H7B3LIHXQ_FLASH.ld" file. 

  OCTOSPI (r)    : ORIGIN = 0x90000000, LENGTH = 64M

and 

      ExtFlashSection :
	{
		*(ExtFlashSection ExtFlashSection.*)
		*(.gnu.linkonce.r.*)
        . = ALIGN(0x4);
	} >OCTOSPI

  FontFlashSection :
	{
		*(FontFlashSection FontFlashSection.*)
		*(.gnu.linkonce.r.*)
        . = ALIGN(0x4);
	} >OCTOSPI

  TextFlashSection :
	{
		*(TextFlashSection TextFlashSection.*)
		*(.gnu.linkonce.r.*)
        . = ALIGN(0x4);
	} >OCTOSPI

I compiled the project and programmed it without any problems. But it doesn't work. "MX_TouchGFX_Init();" At this line the program hangs and goes to the following subroutine in "stm32h7cxx_it.c"

/**
  * @brief This function handles Hard fault interrupt.
  */
void HardFault_Handler(void)
{
  /* USER CODE BEGIN HardFault_IRQn 0 */

  /* USER CODE END HardFault_IRQn 0 */
  while (1)
  {
    /* USER CODE BEGIN W1_HardFault_IRQn 0 */
    /* USER CODE END W1_HardFault_IRQn 0 */
  }
}

 If I remove the lines of code I manually added in the "STM32H7B3LIHXQ_FLASH.ld" file, it works fine. I didn't understand exactly what caused the problem. Could I have made a mistake while initialization OctoSPI? 

static 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 */
  /* OCTOSPI1 parameter configuration*/
  hospi1.Instance = OCTOSPI1;
  hospi1.Init.FifoThreshold = 4;
  hospi1.Init.DualQuad = HAL_OSPI_DUALQUAD_DISABLE;
  hospi1.Init.MemoryType = HAL_OSPI_MEMTYPE_MACRONIX;
  hospi1.Init.DeviceSize = 26;
  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 = 0;
  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 */
  OSPI_OctalDtrModeCfg(&hospi1);

  sCommand.OperationType      = HAL_OSPI_OPTYPE_COMMON_CFG;
  sCommand.FlashId            = HAL_OSPI_FLASH_ID_1;
  sCommand.InstructionMode    = HAL_OSPI_INSTRUCTION_8_LINES;
  sCommand.InstructionSize    = HAL_OSPI_INSTRUCTION_16_BITS;
  sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_ENABLE;
  sCommand.AddressSize        = HAL_OSPI_ADDRESS_32_BITS;
  sCommand.AddressDtrMode     = HAL_OSPI_ADDRESS_DTR_ENABLE;
  sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;
  sCommand.DataDtrMode        = HAL_OSPI_DATA_DTR_ENABLE;
  sCommand.DQSMode            = HAL_OSPI_DQS_DISABLE;
  sCommand.SIOOMode           = HAL_OSPI_SIOO_INST_EVERY_CMD;

  OSPI_WriteEnable(&hospi1);
  OSPI_AutoPollingMemReady(&hospi1);
  /* USER CODE END OCTOSPI1_Init 2 */
}

 

Hard Fault means you are accessing memory that you haven't memory mapped

No idea why you have this code

OSPI_WriteEnable(&hospi1);
OSPI_AutoPollingMemReady(&hospi1);

Or a global sCommand initialization.

Memory Mapping requires a suitable READ command template for the mode, address width, etc you have the memory device operating in.

For OSPI peripherals this is typically both a READ and WRITE, but you don't need a real write template.

https://github.com/STMicroelectronics/STM32CubeH7/tree/master/Projects/STM32H7B3I-DK/Examples/OSPI/OSPI_NOR_MemoryMapped_DTR

Also have a better Hard Fault Handler that outputs useful / actionable data, so it doesn't crash and die silently. Otherwise your support staff will have no means to diagnose / understand failures.

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

Hi Tesla.

To understand how QSPI works, yesterday I watched many training videos and re-read the AN5050 application note from top to bottom. You hit the nail on the head. As you said, "OSPI_WriteEnable(&hospi1);"
"OSPI_AutoPollingMemReady(&hospi1);" I don't need procedures. I deleted these two procedures and I copied the "void EnableMemMapped(void)" section on page 65 of the AN5050 and added it to the program and it worked. 

I have to do many things (PCB, schematics, software, visual works, etc.) together and this makes it really difficult for the project to progress. Now I need to watch videos and read tutorials on Touchgfx to create various visuals and animations for the project.
Thanks so much for your support.
Have a nice work.