<?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_SDRAM_on_StarSOM-STM32H757</id>
	<title>How to use external SDRAM on StarSOM-STM32H757 - 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_SDRAM_on_StarSOM-STM32H757"/>
	<link rel="alternate" type="text/html" href="https://wiki.somlabs.com/index.php?title=How_to_use_external_SDRAM_on_StarSOM-STM32H757&amp;action=history"/>
	<updated>2026-04-28T08:52:38Z</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_SDRAM_on_StarSOM-STM32H757&amp;diff=4407&amp;oldid=prev</id>
		<title>KrzysztofChojnowski: Created page with &quot;{{PageHeader|How to use external SDRAM on the StarSOM-STM32H757}}  This tutorial explains how to configure the external SDRAM memory on StarSOM-STM32H757 module. Please note, that it does not allow to execute code directly from it. It may serve as a large temporary data storage or buffer memory for graphics library etc.  This tutorial was prepared for the STM32CubeIDE (Version: 1.17.0). The base project can be created using this example:  * How_to_create_and_run_the_fi...&quot;</title>
		<link rel="alternate" type="text/html" href="https://wiki.somlabs.com/index.php?title=How_to_use_external_SDRAM_on_StarSOM-STM32H757&amp;diff=4407&amp;oldid=prev"/>
		<updated>2025-04-28T10:36:47Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;{{PageHeader|How to use external SDRAM on the StarSOM-STM32H757}}  This tutorial explains how to configure the external SDRAM memory on StarSOM-STM32H757 module. Please note, that it does not allow to execute code directly from it. It may serve as a large temporary data storage or buffer memory for graphics library etc.  This tutorial was prepared for the STM32CubeIDE (Version: 1.17.0). The base project can be created using this example:  * How_to_create_and_run_the_fi...&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 SDRAM on the StarSOM-STM32H757}}&lt;br /&gt;
&lt;br /&gt;
This tutorial explains how to configure the external SDRAM memory on StarSOM-STM32H757 module. Please note, that it does not allow to execute code directly from it. It may serve as a large temporary data storage or buffer memory for graphics library etc.&lt;br /&gt;
&lt;br /&gt;
This tutorial was prepared for the STM32CubeIDE (Version: 1.17.0). The base project can be created using this example:&lt;br /&gt;
&lt;br /&gt;
* [[How_to_create_and_run_the_first_application_on_the_StarSOM-STM32H757|How to create and run the first application on the StarSOM-STM32H757]]&lt;br /&gt;
&lt;br /&gt;
== Adding FMC configuration in CubeMX ==&lt;br /&gt;
&lt;br /&gt;
The base configuration of the FMC peripheral can be generated by CubeMX tool available in STM32CubeIDE. After adding the FMC to the Cortex-M7 context it should be configured as shown below:&lt;br /&gt;
&lt;br /&gt;
[[Image:stm32h757_sdram_1.png|center|450px]]&lt;br /&gt;
&lt;br /&gt;
with the following control and timing parameters:&lt;br /&gt;
&lt;br /&gt;
[[Image:stm32h757_sdram_3.png|center|600px]]&lt;br /&gt;
&lt;br /&gt;
The GPIO lines should be configured automatically. Below is the full IO list for reference:&lt;br /&gt;
&lt;br /&gt;
[[Image:stm32h757_sdram_2.png|center|600px]]&lt;br /&gt;
&lt;br /&gt;
Finally the FMC clock should also be enabled:&lt;br /&gt;
&lt;br /&gt;
[[Image:stm32h757_sdram_4.png|center|800px]]&lt;br /&gt;
&lt;br /&gt;
== SDRAM initialization code == &lt;br /&gt;
&lt;br /&gt;
The CubeMX creates a new MX_FMC_Init function in main.c, that requires custom initialization. The full code of this function should look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define SDRAM_TIMEOUT                           ((uint32_t)0xFFFF)&lt;br /&gt;
#define SDRAM_MR_BURST_LENGTH_1                 ((uint16_t)0x0000)&lt;br /&gt;
#define SDRAM_MR_BURST_TYPE_SEQUENTIAL          ((uint16_t)0x0000)&lt;br /&gt;
#define SDRAM_MR_CAS_LATENCY_2                  ((uint16_t)0x0020)&lt;br /&gt;
#define SDRAM_MR_OPERATING_MODE_STANDARD        ((uint16_t)0x0000)&lt;br /&gt;
#define SDRAM_MR_WRITEBURST_MODE_SINGLE         ((uint16_t)0x0200)&lt;br /&gt;
#define REFRESH_COUNT                           ((uint32_t)0x0603)&lt;br /&gt;
&lt;br /&gt;
void MX_FMC_Init(void)&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
  /* USER CODE BEGIN FMC_Init 0 */&lt;br /&gt;
&lt;br /&gt;
  /* USER CODE END FMC_Init 0 */&lt;br /&gt;
&lt;br /&gt;
  FMC_SDRAM_TimingTypeDef SdramTiming = {0};&lt;br /&gt;
&lt;br /&gt;
  /* USER CODE BEGIN FMC_Init 1 */&lt;br /&gt;
&lt;br /&gt;
  /* USER CODE END FMC_Init 1 */&lt;br /&gt;
&lt;br /&gt;
  /** Perform the SDRAM1 memory initialization sequence&lt;br /&gt;
  */&lt;br /&gt;
  hsdram1.Instance = FMC_SDRAM_DEVICE;&lt;br /&gt;
  /* hsdram1.Init */&lt;br /&gt;
  hsdram1.Init.SDBank = FMC_SDRAM_BANK1;&lt;br /&gt;
  hsdram1.Init.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_9;&lt;br /&gt;
  hsdram1.Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_13;&lt;br /&gt;
  hsdram1.Init.MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_16;&lt;br /&gt;
  hsdram1.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4;&lt;br /&gt;
  hsdram1.Init.CASLatency = FMC_SDRAM_CAS_LATENCY_2;&lt;br /&gt;
  hsdram1.Init.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE;&lt;br /&gt;
  hsdram1.Init.SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_2;&lt;br /&gt;
  hsdram1.Init.ReadBurst = FMC_SDRAM_RBURST_ENABLE;&lt;br /&gt;
  hsdram1.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_0;&lt;br /&gt;
  /* SdramTiming */&lt;br /&gt;
  SdramTiming.LoadToActiveDelay = 2;&lt;br /&gt;
  SdramTiming.ExitSelfRefreshDelay = 7;&lt;br /&gt;
  SdramTiming.SelfRefreshTime = 4;&lt;br /&gt;
  SdramTiming.RowCycleDelay = 7;&lt;br /&gt;
  SdramTiming.WriteRecoveryTime = 3;&lt;br /&gt;
  SdramTiming.RPDelay = 2;&lt;br /&gt;
  SdramTiming.RCDDelay = 2;&lt;br /&gt;
&lt;br /&gt;
  if (HAL_SDRAM_Init(&amp;amp;hsdram1, &amp;amp;SdramTiming) != HAL_OK)&lt;br /&gt;
  {&lt;br /&gt;
    Error_Handler( );&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  /* USER CODE BEGIN FMC_Init 2 */&lt;br /&gt;
&lt;br /&gt;
  __IO uint32_t tmpmrd = 0;&lt;br /&gt;
  FMC_SDRAM_CommandTypeDef command;&lt;br /&gt;
  HAL_StatusTypeDef halStatus;&lt;br /&gt;
&lt;br /&gt;
  /* Configure a clock config command */&lt;br /&gt;
  command.CommandMode = FMC_SDRAM_CMD_CLK_ENABLE;&lt;br /&gt;
  command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;&lt;br /&gt;
  command.AutoRefreshNumber = 1;&lt;br /&gt;
  command.ModeRegisterDefinition = 0;&lt;br /&gt;
&lt;br /&gt;
    /* Send configure command */&lt;br /&gt;
  halStatus = HAL_SDRAM_SendCommand(&amp;amp;hsdram1, &amp;amp;command, SDRAM_TIMEOUT);&lt;br /&gt;
&lt;br /&gt;
  if(halStatus != HAL_OK){&lt;br /&gt;
    Error_Handler();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  /* Delay between commands need to be at least 100us */&lt;br /&gt;
&lt;br /&gt;
  HAL_Delay(1);&lt;br /&gt;
&lt;br /&gt;
    /* Configure precharge command */&lt;br /&gt;
  command.CommandMode = FMC_SDRAM_CMD_PALL;&lt;br /&gt;
  command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;&lt;br /&gt;
  command.AutoRefreshNumber = 1;&lt;br /&gt;
  command.ModeRegisterDefinition = 0;&lt;br /&gt;
&lt;br /&gt;
    /* Send configure command */&lt;br /&gt;
  halStatus = HAL_SDRAM_SendCommand(&amp;amp;hsdram1, &amp;amp;command, SDRAM_TIMEOUT);&lt;br /&gt;
&lt;br /&gt;
  if(halStatus != HAL_OK){&lt;br /&gt;
    Error_Handler();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  /* Configure Autorefresh command */&lt;br /&gt;
  command.CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE;&lt;br /&gt;
  command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;&lt;br /&gt;
  command.AutoRefreshNumber = 8;&lt;br /&gt;
  command.ModeRegisterDefinition = 0;&lt;br /&gt;
&lt;br /&gt;
  /* Send configure command */&lt;br /&gt;
  halStatus = HAL_SDRAM_SendCommand(&amp;amp;hsdram1, &amp;amp;command, SDRAM_TIMEOUT);&lt;br /&gt;
&lt;br /&gt;
  if(halStatus != HAL_OK){&lt;br /&gt;
    Error_Handler();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  HAL_Delay(1);&lt;br /&gt;
  /* Program external memory mode register */&lt;br /&gt;
  tmpmrd = (uint32_t) SDRAM_MR_BURST_LENGTH_1          |\&lt;br /&gt;
                      SDRAM_MR_BURST_TYPE_SEQUENTIAL   |\&lt;br /&gt;
                      SDRAM_MR_CAS_LATENCY_2           |\&lt;br /&gt;
                      SDRAM_MR_OPERATING_MODE_STANDARD |\&lt;br /&gt;
                      SDRAM_MR_WRITEBURST_MODE_SINGLE;&lt;br /&gt;
  command.CommandMode = FMC_SDRAM_CMD_LOAD_MODE;&lt;br /&gt;
  command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;&lt;br /&gt;
  command.AutoRefreshNumber = 1;&lt;br /&gt;
  command.ModeRegisterDefinition = tmpmrd;&lt;br /&gt;
&lt;br /&gt;
  /* Send configure command */&lt;br /&gt;
  halStatus = HAL_SDRAM_SendCommand(&amp;amp;hsdram1, &amp;amp;command, SDRAM_TIMEOUT);&lt;br /&gt;
  if(halStatus != HAL_OK){&lt;br /&gt;
    Error_Handler();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  /* Set the refresh rate counter (15.62 us x Freq) - 20 */&lt;br /&gt;
  /* Set the device refresh counter */&lt;br /&gt;
  halStatus = HAL_SDRAM_ProgramRefreshRate(&amp;amp;hsdram1, REFRESH_COUNT);&lt;br /&gt;
  if(halStatus != HAL_OK){&lt;br /&gt;
    Error_Handler();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  /* USER CODE END FMC_Init 2 */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This function is called in main() after HAL initialization.&lt;br /&gt;
&lt;br /&gt;
== Testing SDRAM access ==&lt;br /&gt;
&lt;br /&gt;
The SDRAM memory is accessible starting from 0xC0000000 address. This example function can be used for testing each address in the external memory. The USART1 peripheral connected to ST-Link console on StarCB-STM32H757-STD was configured as shown in the [[How_to_create_and_run_the_first_application_on_the_StarSOM-STM32H757|example]] project &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
static inline void print(const char* msg) {&lt;br /&gt;
  HAL_UART_Transmit(&amp;amp;huart1, (const uint8_t*)msg, strlen(msg), 100);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static uint8_t testMem(uint32_t memAddr, uint32_t memLen, uint32_t step)&lt;br /&gt;
{&lt;br /&gt;
    uint32_t* memPtr = (uint32_t*)memAddr;&lt;br /&gt;
    for(int i = 0; i &amp;lt; 1000000; i++)&lt;br /&gt;
        __NOP();&lt;br /&gt;
&lt;br /&gt;
    print(&amp;quot;\r\nSDRAM testing\r\n&amp;quot;);&lt;br /&gt;
    print(&amp;quot;SDRAM testing...0xAA...&amp;quot;);&lt;br /&gt;
    // Test AA&lt;br /&gt;
    for(uint32_t i = 0; i &amp;lt; (memLen &amp;gt;&amp;gt; 2); i += step) {&lt;br /&gt;
        memPtr[i] = 0xAAAAAAAA;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    for(uint32_t i = 0; i &amp;lt; (memLen &amp;gt;&amp;gt; 2); i += step) {&lt;br /&gt;
        if(memPtr[i] != 0xAAAAAAAA) {&lt;br /&gt;
          print(&amp;quot;FAILED\r\n&amp;quot;);&lt;br /&gt;
            return 1;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    print(&amp;quot;DONE\r\n&amp;quot;);&lt;br /&gt;
    print(&amp;quot;SDRAM testing...0x55...&amp;quot;);&lt;br /&gt;
    // Test 55&lt;br /&gt;
    for(uint32_t i = 0; i &amp;lt; (memLen &amp;gt;&amp;gt; 2); i += step) {&lt;br /&gt;
        memPtr[i] = 0x55555555;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    for(uint32_t i = 0; i &amp;lt; (memLen &amp;gt;&amp;gt; 2); i += step) {&lt;br /&gt;
        if(memPtr[i] != 0x55555555) {&lt;br /&gt;
          print(&amp;quot;FAILED\r\n&amp;quot;);&lt;br /&gt;
            return 1;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    print(&amp;quot;DONE\r\n&amp;quot;);&lt;br /&gt;
    print(&amp;quot;SDRAM testing...0x00...&amp;quot;);&lt;br /&gt;
    // Test zero&lt;br /&gt;
    for(uint32_t i = 0; i &amp;lt; (memLen &amp;gt;&amp;gt; 2); i += 1) {&lt;br /&gt;
        memPtr[i] = 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    for(uint32_t i = 0; i &amp;lt; (memLen &amp;gt;&amp;gt; 2); i += step) {&lt;br /&gt;
        if(memPtr[i] != 0) {&lt;br /&gt;
          print(&amp;quot;FAILED\r\n&amp;quot;);&lt;br /&gt;
            return 1;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    print(&amp;quot;DONE\r\n&amp;quot;);&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The testing function can be called for the 32MB memory after HAL and MX_FMC_Init initialization functions:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  testMem(0xC0000000, 0x2000000, 1);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>KrzysztofChojnowski</name></author>
	</entry>
</feed>