XIP : some progress

Hi Guys,

I have some progress here.

With the OpenOCD built here: Accessing external flash from OpenOCD

And a modified linker file (STM32H750VBTx_FLASH.ld) :

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

**  File        : LinkerScript.ld
**
**  Abstract    : Linker script for STM32H750VBTx Device with
**                128KByte FLASH, 1056KByte RAM
**
**                Set heap size, stack size and stack location according
**                to application requirements.
**
**                Set memory bank area and size if external memory is used.
**
**  Target      : STMicroelectronics STM32
**
**
**  Distribution: The file is distributed as is, without any warranty
**                of any kind.
**
**  (c)Copyright Ac6.
**  You may use this file as-is or modify it according to the needs of your
**  project. Distribution of this file (unmodified or modified) is not
**  permitted. Ac6 permit registered System Workbench for MCU users the
**  rights to distribute the assembled, compiled & linked contents of this
**  file as part of an application binary file, provided that it is built
**  using the System Workbench for MCU toolchain.
**
*****************************************************************************
*/

/* Entry Point */
ENTRY(Reset_Handler)

/* Highest address of the user mode stack */
_estack = 0x20020000;    /* end of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x200;      /* required amount of heap  */
_Min_Stack_Size = 0x400; /* required amount of stack */

/* Specify the memory areas */
MEMORY
{
DTCMRAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 128K
RAM_D1 (xrw)        : ORIGIN = 0x24000000, LENGTH = 212K
LTDC (rw)           : ORIGIN = 0x24035000, LENGTH = 300K
RAM_D2 (xrw)        : ORIGIN = 0x30000000, LENGTH = 288K
RAM_D3 (xrw)        : ORIGIN = 0x38000000, LENGTH = 64K
ITCMISR (xrw)       : ORIGIN = 0x00000000, LENGTH = 4K
ITCMRAM (xrw)       : ORIGIN = 0x00001000, LENGTH = 60K
FLASH (rx)          : ORIGIN = 0x08000000, LENGTH = 128K
EXT_FLASH (rx)      : ORIGIN = 0x90000000, LENGTH = 32768K
}

/* Define output sections */
SECTIONS
{
  ext_flash_code :
  {
    . = ALIGN(4);
	*(.ExtFlashCode*);
    . = ALIGN(4);
  } > EXT_FLASH

  ext_flash_data :
  {
    . = ALIGN(4);
	*(.ExtFlashData*);
    . = ALIGN(4);
  } > EXT_FLASH

  /* The startup code goes first into FLASH */
  .isr_vector :
  {
    . = ALIGN(4);
    KEEP(*(.isr_vector)) /* Startup code */
    . = ALIGN(4);
  } >FLASH

  /* The program code and other data goes into FLASH */
  .text :
  {
    . = ALIGN(4);
    *(.text)           /* .text sections (code) */
    *(.text*)          /* .text* sections (code) */
    *(.glue_7)         /* glue arm to thumb code */
    *(.glue_7t)        /* glue thumb to arm code */
    *(.eh_frame)

    KEEP (*(.init))
    KEEP (*(.fini))

    . = ALIGN(4);
    _etext = .;        /* define a global symbols at end of code */
  } >FLASH

  /* Constant data goes into FLASH */
  .rodata :
  {
    . = ALIGN(4);
    *(.rodata)         /* .rodata sections (constants, strings, etc.) */
    *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
    . = ALIGN(4);
  } >FLASH

  .ARM.extab   : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
  .ARM : {
    __exidx_start = .;
    *(.ARM.exidx*)
    __exidx_end = .;
  } >FLASH

  .preinit_array     :
  {
    PROVIDE_HIDDEN (__preinit_array_start = .);
    KEEP (*(.preinit_array*))
    PROVIDE_HIDDEN (__preinit_array_end = .);
  } >FLASH
  .init_array :
  {
    PROVIDE_HIDDEN (__init_array_start = .);
    KEEP (*(SORT(.init_array.*)))
    KEEP (*(.init_array*))
    PROVIDE_HIDDEN (__init_array_end = .);
  } >FLASH
  .fini_array :
  {
    PROVIDE_HIDDEN (__fini_array_start = .);
    KEEP (*(SORT(.fini_array.*)))
    KEEP (*(.fini_array*))
    PROVIDE_HIDDEN (__fini_array_end = .);
  } >FLASH

  /* used by the startup to initialize data */
  _sidata = LOADADDR(.data);

  /* Initialized data sections goes into RAM, load LMA copy after code */
  .data :
  {
    . = ALIGN(4);
    _sdata = .;        /* create a global symbol at data start */
    *(.data)           /* .data sections */
    *(.data*)          /* .data* sections */

    . = ALIGN(4);
    _edata = .;        /* define a global symbol at data end */
  } >DTCMRAM AT> FLASH


  /* Uninitialized data section */
  . = ALIGN(4);
  .bss :
  {
    /* This is used by the startup in order to initialize the .bss secion */
    _sbss = .;         /* define a global symbol at bss start */
    __bss_start__ = _sbss;
    *(.bss)
    *(.bss*)
    *(COMMON)

    . = ALIGN(4);
    _ebss = .;         /* define a global symbol at bss end */
    __bss_end__ = _ebss;
  } >DTCMRAM

  /* User_heap_stack section, used to check that there is enough RAM left */
  ._user_heap_stack :
  {
    . = ALIGN(8);
    PROVIDE ( end = . );
    PROVIDE ( _end = . );
    . = . + _Min_Heap_Size;
    . = . + _Min_Stack_Size;
    . = ALIGN(8);
  } >DTCMRAM

  itcm_data = LOADADDR(.itcm);
  .itcm :
  {
    . = ALIGN(4);
    itcm_text_start = .;
    *(.itcm)         /* ITCM code section */
    . = ALIGN(4);
    itcm_text_end = .;
  } >ITCMRAM AT> FLASH

  .ltdc (NOLOAD):
  {
    . = ALIGN(4);
    __ltdc_start = .;
    KEEP(*(.ltdc))         /* LTDC buffer section */
    __ltdc_end = .;
  } >LTDC

  .ss (NOLOAD):
  {
    . = ALIGN(4);
    *(.ss)           /* spritesheet */
  } >RAM_D2

  .fb (NOLOAD):
  {
    . = ALIGN(4);
    *(.fb)           /* framebuffer */
  } >RAM_D1

  .m (NOLOAD):
  {
    . = ALIGN(4);
    *(.m)           /* framebuffer */
  } >RAM_D2

  .dac_data (NOLOAD):
  {
    . = ALIGN(4);
    *(.dac_data)           /* dac_data */
  } >RAM_D3

  /* Remove information from the standard libraries */
  /DISCARD/ :
  {
    libc.a ( * )
    libm.a ( * )
    libgcc.a ( * )
  }

  .ARM.attributes 0 : { *(.ARM.attributes) }
}

We now have two new sections in external flash, ExtFlashCode for code and ExtFlashData for data:

__attribute__((section(".ExtFlashCode"))) char *testXIP(char *pszIn)
{
	while(*pszIn)
		*pszIn++='A';
}

__attribute__((section(".ExtFlashData"))) int  n1 = 0x11223344;
__attribute__((section(".ExtFlashData"))) int  n2 = 0x55667788;

These flash to external flash perfectly from the elf file via OpenOCD :)

So after qspi_init() and qspi_enable_memorymapped_mode() are called the data is accessible and the function can be called.

Things that are not yet working:

  1. Breakpoints in external flash. I have a horrible feeling this is because they are not in the code section which would mean we would have to run all code from external flash to debug. Looking into this.

  2. Data structures strings etc in external flash, this is causing a hard fault in _static_initialization_and_destruction() in 32blit.c, not sure what is going on here yet.