<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.somlabs.com/index.php?action=history&amp;feed=atom&amp;title=How_to_use_external_QSPI_flash</id>
	<title>How to use external QSPI flash - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.somlabs.com/index.php?action=history&amp;feed=atom&amp;title=How_to_use_external_QSPI_flash"/>
	<link rel="alternate" type="text/html" href="https://wiki.somlabs.com/index.php?title=How_to_use_external_QSPI_flash&amp;action=history"/>
	<updated>2026-04-28T10:18:23Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.42.3</generator>
	<entry>
		<id>https://wiki.somlabs.com/index.php?title=How_to_use_external_QSPI_flash&amp;diff=4387&amp;oldid=prev</id>
		<title>KrzysztofChojnowski: Created page with &quot;{{PageHeader|How to use external QSPI flash on the StarSOM-STM32H757}}  This tutorial explains how to write the data to the external QSPI Flash memory on StarSOM-STM32H757 module. Please note, that it does not allow to execute code directly from it. It may serve as a large, static data storage, like graphics, while the application code is executed from internal MCU flash memory.  == External flash loader ==  In order to program the external flash using the ST tools, an a...&quot;</title>
		<link rel="alternate" type="text/html" href="https://wiki.somlabs.com/index.php?title=How_to_use_external_QSPI_flash&amp;diff=4387&amp;oldid=prev"/>
		<updated>2025-04-08T14:38:40Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;{{PageHeader|How to use external QSPI flash on the StarSOM-STM32H757}}  This tutorial explains how to write the data to the external QSPI Flash memory on StarSOM-STM32H757 module. Please note, that it does not allow to execute code directly from it. It may serve as a large, static data storage, like graphics, while the application code is executed from internal MCU flash memory.  == External flash loader ==  In order to program the external flash using the ST tools, an a...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;{{PageHeader|How to use external QSPI flash on the StarSOM-STM32H757}}&lt;br /&gt;
&lt;br /&gt;
This tutorial explains how to write the data to the external QSPI Flash memory on StarSOM-STM32H757 module. Please note, that it does not allow to execute code directly from it. It may serve as a large, static data storage, like graphics, while the application code is executed from internal MCU flash memory.&lt;br /&gt;
&lt;br /&gt;
== External flash loader ==&lt;br /&gt;
&lt;br /&gt;
In order to program the external flash using the ST tools, an additional flash loader application is required. The External flash loader for StarSOM-STM32H757 is available as a pre-compiled binary, as well as the STM32CubeIDE (Version: 1.17.0).&lt;br /&gt;
&lt;br /&gt;
* https://github.com/SoMLabs/starsom-stm32h757-extflashloader/raw/refs/heads/main/CM7/starsom-stm32h757-extflashloader_CM7.stldr&lt;br /&gt;
* https://github.com/SoMLabs/starsom-stm32h757-extflashloader&lt;br /&gt;
&lt;br /&gt;
== Configuring external flash memory in STM32CubeIDE project ==&lt;br /&gt;
&lt;br /&gt;
The external flash address and size need to be configured in the linker script located in the project directory: CM7/STM32H757XIHX_FLASH.ld&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
MEMORY&lt;br /&gt;
{&lt;br /&gt;
  RAM_D1 (xrw)   : ORIGIN = 0x24000000, LENGTH =  512K&lt;br /&gt;
  FLASH   (rx)   : ORIGIN = 0x08000000, LENGTH = 1024K    /* Memory is divided. Actual start is 0x08000000 and actual length is 2048K */&lt;br /&gt;
  DTCMRAM (xrw)  : ORIGIN = 0x20000000, LENGTH = 128K&lt;br /&gt;
  RAM_D2 (xrw)   : ORIGIN = 0x30000000, LENGTH = 288K&lt;br /&gt;
  RAM_D3 (xrw)   : ORIGIN = 0x38000000, LENGTH = 64K&lt;br /&gt;
  ITCMRAM (xrw)  : ORIGIN = 0x00000000, LENGTH = 64K&lt;br /&gt;
  EXTFLASH (r)   : ORIGIN = 0x90000000, LENGTH = 16384K&lt;br /&gt;
  &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To easily add static variables to flash location, a new section should also be added in the linker script SECTIONS list, for example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  .big_flash (READONLY) :&lt;br /&gt;
  {&lt;br /&gt;
  	. = ALIGN(4);&lt;br /&gt;
  	*(.RoDataSection);&lt;br /&gt;
  } &amp;gt;EXTFLASH&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After that, each variable declared in &amp;#039;&amp;#039;.RoDataSection&amp;#039;&amp;#039; section will be placed in the external QSPI flash.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const __attribute__((section(&amp;quot;.RoDataSection&amp;quot;))) uint8_t big_table[] = { ... };&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== QUADSPI interface configuration ==&lt;br /&gt;
&lt;br /&gt;
The QSPI interface with required signals can be configured in the Device Configuration Tool:&lt;br /&gt;
&lt;br /&gt;
[[Image:stm32h757_flash_loader_1.png|center|600px]]&lt;br /&gt;
&lt;br /&gt;
[[Image:stm32h757_flash_loader_2.png|center|600px]]&lt;br /&gt;
&lt;br /&gt;
The generated code looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
static void MX_QUADSPI_Init(void)&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
  /* USER CODE BEGIN QUADSPI_Init 0 */&lt;br /&gt;
&lt;br /&gt;
  /* USER CODE END QUADSPI_Init 0 */&lt;br /&gt;
&lt;br /&gt;
  /* USER CODE BEGIN QUADSPI_Init 1 */&lt;br /&gt;
&lt;br /&gt;
  /* USER CODE END QUADSPI_Init 1 */&lt;br /&gt;
  /* QUADSPI parameter configuration*/&lt;br /&gt;
  hqspi.Instance = QUADSPI;&lt;br /&gt;
  hqspi.Init.ClockPrescaler = 1;&lt;br /&gt;
  hqspi.Init.FifoThreshold = 1;&lt;br /&gt;
  hqspi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_NONE;&lt;br /&gt;
  hqspi.Init.FlashSize = 23;&lt;br /&gt;
  hqspi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_3_CYCLE;&lt;br /&gt;
  hqspi.Init.ClockMode = QSPI_CLOCK_MODE_0;&lt;br /&gt;
  hqspi.Init.FlashID = QSPI_FLASH_ID_1;&lt;br /&gt;
  hqspi.Init.DualFlash = QSPI_DUALFLASH_DISABLE;&lt;br /&gt;
  if (HAL_QSPI_Init(&amp;amp;hqspi) != HAL_OK)&lt;br /&gt;
  {&lt;br /&gt;
    Error_Handler();&lt;br /&gt;
  }&lt;br /&gt;
  /* USER CODE BEGIN QUADSPI_Init 2 */&lt;br /&gt;
&lt;br /&gt;
  /* USER CODE END QUADSPI_Init 2 */&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void HAL_QSPI_MspInit(QSPI_HandleTypeDef* hqspi)&lt;br /&gt;
{&lt;br /&gt;
  GPIO_InitTypeDef GPIO_InitStruct = {0};&lt;br /&gt;
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};&lt;br /&gt;
  if(hqspi-&amp;gt;Instance==QUADSPI)&lt;br /&gt;
  {&lt;br /&gt;
  /* USER CODE BEGIN QUADSPI_MspInit 0 */&lt;br /&gt;
&lt;br /&gt;
  /* USER CODE END QUADSPI_MspInit 0 */&lt;br /&gt;
&lt;br /&gt;
  /** Initializes the peripherals clock&lt;br /&gt;
  */&lt;br /&gt;
    PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_QSPI;&lt;br /&gt;
    PeriphClkInitStruct.QspiClockSelection = RCC_QSPICLKSOURCE_D1HCLK;&lt;br /&gt;
    if (HAL_RCCEx_PeriphCLKConfig(&amp;amp;PeriphClkInitStruct) != HAL_OK)&lt;br /&gt;
    {&lt;br /&gt;
      Error_Handler();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /* Peripheral clock enable */&lt;br /&gt;
    __HAL_RCC_QSPI_CLK_ENABLE();&lt;br /&gt;
&lt;br /&gt;
    __HAL_RCC_GPIOE_CLK_ENABLE();&lt;br /&gt;
    __HAL_RCC_GPIOG_CLK_ENABLE();&lt;br /&gt;
    __HAL_RCC_GPIOF_CLK_ENABLE();&lt;br /&gt;
    __HAL_RCC_GPIOD_CLK_ENABLE();&lt;br /&gt;
    /**QUADSPI GPIO Configuration&lt;br /&gt;
    PE2     ------&amp;gt; QUADSPI_BK1_IO2&lt;br /&gt;
    PG6     ------&amp;gt; QUADSPI_BK1_NCS&lt;br /&gt;
    PF10     ------&amp;gt; QUADSPI_CLK&lt;br /&gt;
    PD11     ------&amp;gt; QUADSPI_BK1_IO0&lt;br /&gt;
    PD12     ------&amp;gt; QUADSPI_BK1_IO1&lt;br /&gt;
    PD13     ------&amp;gt; QUADSPI_BK1_IO3&lt;br /&gt;
    */&lt;br /&gt;
    GPIO_InitStruct.Pin = GPIO_PIN_2;&lt;br /&gt;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;&lt;br /&gt;
    GPIO_InitStruct.Pull = GPIO_NOPULL;&lt;br /&gt;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;&lt;br /&gt;
    GPIO_InitStruct.Alternate = GPIO_AF9_QUADSPI;&lt;br /&gt;
    HAL_GPIO_Init(GPIOE, &amp;amp;GPIO_InitStruct);&lt;br /&gt;
&lt;br /&gt;
    GPIO_InitStruct.Pin = GPIO_PIN_6;&lt;br /&gt;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;&lt;br /&gt;
    GPIO_InitStruct.Pull = GPIO_NOPULL;&lt;br /&gt;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;&lt;br /&gt;
    GPIO_InitStruct.Alternate = GPIO_AF10_QUADSPI;&lt;br /&gt;
    HAL_GPIO_Init(GPIOG, &amp;amp;GPIO_InitStruct);&lt;br /&gt;
&lt;br /&gt;
    GPIO_InitStruct.Pin = GPIO_PIN_10;&lt;br /&gt;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;&lt;br /&gt;
    GPIO_InitStruct.Pull = GPIO_NOPULL;&lt;br /&gt;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;&lt;br /&gt;
    GPIO_InitStruct.Alternate = GPIO_AF9_QUADSPI;&lt;br /&gt;
    HAL_GPIO_Init(GPIOF, &amp;amp;GPIO_InitStruct);&lt;br /&gt;
&lt;br /&gt;
    GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13;&lt;br /&gt;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;&lt;br /&gt;
    GPIO_InitStruct.Pull = GPIO_NOPULL;&lt;br /&gt;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;&lt;br /&gt;
    GPIO_InitStruct.Alternate = GPIO_AF9_QUADSPI;&lt;br /&gt;
    HAL_GPIO_Init(GPIOD, &amp;amp;GPIO_InitStruct);&lt;br /&gt;
&lt;br /&gt;
  /* USER CODE BEGIN QUADSPI_MspInit 1 */&lt;br /&gt;
&lt;br /&gt;
  /* USER CODE END QUADSPI_MspInit 1 */&lt;br /&gt;
&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== External QSPI flash mapping ==&lt;br /&gt;
&lt;br /&gt;
In order to access the external flash from the processor address space it should be first mapped as a read-only region:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
HAL_StatusTypeDef QSPI_Flash_Map(void)&lt;br /&gt;
{&lt;br /&gt;
  QSPI_CommandTypeDef s_command;&lt;br /&gt;
  QSPI_MemoryMappedTypeDef s_mem_mapped_cfg;&lt;br /&gt;
&lt;br /&gt;
  /* Initialize the read command */&lt;br /&gt;
  s_command.InstructionMode   = QSPI_INSTRUCTION_1_LINE;&lt;br /&gt;
  s_command.Instruction       = 0x6b;   // fast read quad output&lt;br /&gt;
  s_command.AddressMode       = QSPI_ADDRESS_1_LINE;&lt;br /&gt;
  s_command.AddressSize       = QSPI_ADDRESS_24_BITS;&lt;br /&gt;
  s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;&lt;br /&gt;
  s_command.DataMode          = QSPI_DATA_4_LINES;&lt;br /&gt;
  s_command.DummyCycles       = 8;&lt;br /&gt;
  s_command.DdrMode           = QSPI_DDR_MODE_DISABLE;&lt;br /&gt;
  s_command.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;&lt;br /&gt;
  s_command.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;&lt;br /&gt;
&lt;br /&gt;
  s_mem_mapped_cfg.TimeOutActivation = QSPI_TIMEOUT_COUNTER_DISABLE;&lt;br /&gt;
&lt;br /&gt;
  if (HAL_QSPI_MemoryMapped(&amp;amp;hqspi, &amp;amp;s_command, &amp;amp;s_mem_mapped_cfg) != HAL_OK)&lt;br /&gt;
  {&lt;br /&gt;
    return HAL_ERROR;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return HAL_OK;&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Using external flash loader in STM32CubeIDE ==&lt;br /&gt;
&lt;br /&gt;
In order to flash the external memory using the STM32CubeIDE, the external loader binary should be added in the Debug Configuration window:&lt;br /&gt;
&lt;br /&gt;
[[Image:stm32h757_flash_loader_3.png|center|600px]]&lt;br /&gt;
&lt;br /&gt;
== Using external flash loader in STM32CubeProgrammer ==&lt;br /&gt;
&lt;br /&gt;
The external loader binary (starsom-stm32h757-extflashloader_CM7.stldr) should be copied to the STM32CubeProgrammer directory &amp;#039;&amp;#039;STM32CubeProgrammer/bin/ExternalLoader&amp;#039;&amp;#039;. It can be then selected in the application window.&lt;br /&gt;
&lt;br /&gt;
[[Image:stm32h757_flash_loader_4.png|center|600px]]&lt;/div&gt;</summary>
		<author><name>KrzysztofChojnowski</name></author>
	</entry>
</feed>