2024-05-31 06:12 AM
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".
But when I want to add a new screen to the touchGfx project, I encounter the following error.
I also need to see RAM, FLASH and OSPI details in the "memory region" window. But I can't see, it's empty.
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.
Solved! Go to Solution.
2024-06-03 08:48 AM
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.
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.
2024-05-31 06:21 AM
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.
2024-05-31 07:12 AM
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?
2024-05-31 08:24 AM - edited 2024-05-31 08:25 AM
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
2024-05-31 02:32 PM - edited 2024-05-31 02:33 PM
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.
2024-06-03 03:27 AM
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 */
}
2024-06-03 08:48 AM
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.
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.
2024-06-03 10:51 PM
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.