cancel
Showing results for 
Search instead for 
Did you mean: 

external loader MX25L512G_STM32F769I-DISCO.stldr

rudolf.pribis
Associate II

Hello all,

I modified my .ld file as:

MEMORY

{

 RAM   (xrw)   : ORIGIN = 0x20000000,   LENGTH = 512K

 FLASH   (rx)   : ORIGIN = 0x8000000,   LENGTH = 2048K

 QUADSPI (rx) : ORIGIN = 0x90000000, LENGTH = 64M (added line)

}

And I replaced  FLASH with  QUADSPI in order to load all to external flash.

I copied MX25L512G_STM32F769I-DISCO.stldr file to external loader folder of CubeMXIDE.

I modified system_stm32f7xx.c to set 0x90000000L offset:

  /* Configure the Vector Table location add offset address ------------------*/
#ifdef VECT_TAB_SRAM
  SCB->VTOR = RAMDTCM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
#else
  //SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
  SCB->VTOR = 0x90000000L | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
#endif

When I debug the program with STM32CubeIDE

with external loader (MX25L512G_STM32F769I-DISCO, 0x90000000, NOR_FLASH, MX25L512G_STM32F769I-DISCO.stldr) my program reaches 0x90000000 and executes the code.

When I reset program (e.g. by button) or try to download program with STM32 ST-LINK Utility or STM32CubeProg... my program does not start.

https://github.com/rudoq32/STM32-QSPI.git

Do you have any useful hints for me?

Thank you

Rudo

9 REPLIES 9

You'd need code running from internal flash to stand-up the external interface before the processor can access it. That code would then need to transfer control to the image in external memory.

The CPU will start from 0x00000000, and thus your code in FLASH 0x08000000 that gets mapped their initially.

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

If I understood it correctly:

  • CPU starts from 0x00000000 (this is clear)
  • Flash 0x08000000 I erased, there is nothing.

Q: So you're saying that CPU jumps there? It is possible to say to CPU to jump to 0x90000000? Or it is better idea do load there a code which will jump to 0x90000000?

(Excuse me, as you can see, I am not so familiar with this topic, I am trying to build an embedded system. I am more C++ programmer)

I'm saying the board/chip unique aspects of the external memory aren't magically known to the MCU, you must configure them using code running ​inside the MCU first. You need to provide this code.

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

I am confused.

My memory looks like the one using internal FLASH, so I suppose that address of external flash was loaded to RAM

0690X00000ArvzgQAB.jpg

and I moved interrupt vector:

#ifdef VECT_TAB_SRAM
  SCB->VTOR = RAMDTCM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
#else
  //SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
  SCB->VTOR = 0x90000000L | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */  
#endif

What code i need to implement, modified?

The stuff bringing up the QSPI interface.​

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

May I kindly ask you about less generic answer?

I understood that after the reset board starts from internal flash. I do not know if it is by Option bytes or what....

I understood that QSPI is an external interface memory.

I already spent several days struggling whit it...

What I do not understand is, when my whole program is loaded to external flash 0x90000000, where I can say to MCU to use QSPI and jump to 0x90000000 after board is reset from debug and starts again from 0x08000000.

I was looking in UM2033, AN4760, AN5188 and googling a lot. So I am quite despered, not lazy. That's why I ask for help in this forum.

>>May I kindly ask you about less generic answer?

And I don't have hours to work on your problem or explain in excruciating detail typing on my phone.

This is a Horse+Cart scenario, you've built a Cart, now you have to put a Horse in front of it.

The Horse would be a small loader app, that you might want to build separately, that resides at 0x08000000. It contains the code to set up the clocks, set up the QSPI (using the BSP code for the F769I-DISCO), and then transfers control to your image at 0x90000000. Your main app should then avoid messing with the clocks or QSPI interface again.

Perhaps look at some of the IAP examples where the boot loader and application sections are split into two pieces.

>>I am more C++ programmer

And I'm an Electronics Engineer, not working for, or paid, by ST

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

What I do not understand is, when my whole program is loaded to external flash 0x90000000, where I can say to MCU to use QSPI and jump to 0x90000000 after board is reset from debug and starts again from 0x08000000.

Simply put: You can't at all. Your firmware has to consist of two parts: One resides in internal flash, and starts after reset by fetching stack pointer and start address from reset vector at 0x0800000. By this time, the CPU does know precisely NOTHING about QPSI, that is the QSPI memory is totally inaccessible. The code in the internal flash has to configure the QSPI interface, maybe even configure the external flash chip for proper operation (e.g. QPI mode vs. SPI mode, 4- vs. 3-byte addresses, drive impendance). Then QSPI has to be reconfigured for memory mapped mode (still by code in internal flash). Only then the external flash is mapped into the address space of the CPU and hence visible by the CPU. After that, the internal flash and the QSPI are almost indistinguishable by the CPU, so code execution can be transferred at will between internal and external flash.

rudolf.pribis
Associate II

I found QSPI_PreInitConfig example. It is not exactly what I need, but it seems that they initialize QSPI interface and then execute a code from 0x90000000. The readme contains text:

How to configure the QSPI IP in order to have access to external memory just after reset.

This example describes how to execute a part of the code from a QSPI memory. To do this,

a section is created where the function is stored.

The QSPI is configured in memory-mapped mode before to call main() function and QSPI memory

is then available after the reset.