SDRAM use

Post here first, or if you can't find a relevant section!
Post Reply
Patrick
Posts: 17
Joined: Thu Dec 19, 2019 9:50 am
Answers: 1

SDRAM use

Post by Patrick »

I am using a STM32F746 Discovery board.
I am slowly adding fonctionnalities.
First, LTDC, touch and LVGL. Working fine.
Then SD, still OK.
And finally, Ethernet.
Et là, c'est le drame... Blank screen.
The problem is that i am running out of memory: when I try to allocate buffer for LTDC, malloc fails.
Is it possible to use the external SDRAM of the board to handle the LTDC buffer?

mrburnette
Posts: 311
Joined: Thu Dec 19, 2019 1:23 am
Answers: 1

Re: SDRAM use

Post by mrburnette »

Are you already using off-chip RAM?
https://www.st.com/en/evaluation-tools/ ... overy.html
STM32F746NGH6 Arm® Cortex® core-based microcontroller with 1 Mbyte of Flash memory and 340 Kbytes of RAM, in BGA216 package

128-Mbit SDRAM (64 Mbits accessible)
... and...
https://www.matrixtsl.com/mmforums/view ... 547#p89170

mlundin
Posts: 35
Joined: Wed Nov 04, 2020 1:20 pm
Answers: 2

Re: SDRAM use

Post by mlundin »

Yes the external SDRAM on the STM32F746 can be be used.

* First the memory must be initialized
* Second, add this memory in the linker script for this variant

Code: Select all

/* Specify the memory areas */
MEMORY
{
RAM (xrw)      : ORIGIN = 0x20010000, LENGTH = 320K
FLASH (rx)     : ORIGIN = 0x8000000,  LENGTH = 1024K
SDRAM (rwx)    : ORIGIN = 0xC0000000, LENGTH = 8M    /* sdram, 8MB */
}

and the sdram output section to load variables with attribute 'extram'

Code: Select all

  /* 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);
  } >RAM

  .sdram (NOLOAD) :
  {
    . = ALIGN(4);
    _ssdram = .;
    *(.extram .extram.*);
    . = ALIGN(4);
    _esdram = .;
  } > SDRAM
* Third allocate the display memory with attribute 'extram' (I am using 16bit RGB565 pixels)

Code: Select all

__attribute__ ((section(".extram")))  
uint16_t framebuffer1[LCD_WIDTH*LCD_HEIGHT];

Patrick
Posts: 17
Joined: Thu Dec 19, 2019 9:50 am
Answers: 1

Re: SDRAM use

Post by Patrick »

Hello @mrburnette , @mlundin,
Thank you for your answers.

I tried to use SDRAM as a special memory section. I modified the ldscript.ld. Then I added function to initialize SDRAM:

Code: Select all

#include "stm32f7xx_hal_sdram.h"

void HAL_SDRAM_MspInit(SDRAM_HandleTypeDef *hsdram) {
	GPIO_InitTypeDef gpio_init_structure;
	/* Enable FMC clock */
	__HAL_RCC_FMC_CLK_ENABLE();
	/* Enable GPIOs clock */
	__HAL_RCC_GPIOC_CLK_ENABLE();
	__HAL_RCC_GPIOD_CLK_ENABLE();
	__HAL_RCC_GPIOE_CLK_ENABLE();
	__HAL_RCC_GPIOF_CLK_ENABLE();
	__HAL_RCC_GPIOG_CLK_ENABLE();
	__HAL_RCC_GPIOH_CLK_ENABLE();
	/* Common GPIO configuration */
	gpio_init_structure.Mode = GPIO_MODE_AF_PP;
	gpio_init_structure.Pull = GPIO_PULLUP;
	gpio_init_structure.Speed = GPIO_SPEED_FAST;
	gpio_init_structure.Alternate = GPIO_AF12_FMC;
	/* GPIOC configuration */
	gpio_init_structure.Pin = GPIO_PIN_3;
	HAL_GPIO_Init(GPIOC, &gpio_init_structure);
	/* GPIOD configuration */
	gpio_init_structure.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_8 | GPIO_PIN_9
			| GPIO_PIN_10 | GPIO_PIN_14 | GPIO_PIN_15;
	HAL_GPIO_Init(GPIOD, &gpio_init_structure);
	/* GPIOE configuration */
	gpio_init_structure.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_7 | GPIO_PIN_8
			| GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13
			| GPIO_PIN_14 | GPIO_PIN_15;
	HAL_GPIO_Init(GPIOE, &gpio_init_structure);
	/* GPIOF configuration */
	gpio_init_structure.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3
			| GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13
			| GPIO_PIN_14 | GPIO_PIN_15;
	HAL_GPIO_Init(GPIOF, &gpio_init_structure);
	/* GPIOG configuration */
	gpio_init_structure.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5
			| GPIO_PIN_8 | GPIO_PIN_15;
	HAL_GPIO_Init(GPIOG, &gpio_init_structure);
	/* GPIOH configuration */
	gpio_init_structure.Pin = GPIO_PIN_3 | GPIO_PIN_5;
	HAL_GPIO_Init(GPIOH, &gpio_init_structure);
}

SDRAM_HandleTypeDef hsdram1;

void SDRAM() {
	FMC_SDRAM_TimingTypeDef SdramTiming;
	hsdram1.State = HAL_SDRAM_STATE_RESET;
	hsdram1.Instance = FMC_SDRAM_DEVICE;
	/* hsdram1.Init */
	hsdram1.Init.SDBank = FMC_SDRAM_BANK1;
	hsdram1.Init.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_8;
	hsdram1.Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_12;
	hsdram1.Init.MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_16;
	hsdram1.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4;
	hsdram1.Init.CASLatency = FMC_SDRAM_CAS_LATENCY_3;
	hsdram1.Init.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE;
	hsdram1.Init.SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_2;
	hsdram1.Init.ReadBurst = FMC_SDRAM_RBURST_ENABLE;
	hsdram1.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_0;
	/* SdramTiming */
	SdramTiming.LoadToActiveDelay = 2;
	SdramTiming.ExitSelfRefreshDelay = 7;
	SdramTiming.SelfRefreshTime = 4;
	SdramTiming.RowCycleDelay = 7;
	SdramTiming.WriteRecoveryTime = 3;
	SdramTiming.RPDelay = 2;
	SdramTiming.RCDDelay = 2;
	HAL_SDRAM_Init(&hsdram1, &SdramTiming);
}
I call SDRAM() at the beginning of the setup function. The code execute fine, without error.
The display buffer is correctly declared at the right address (checked in debugger), but when I try yo initialize, the board hangs.

Code: Select all

__attribute__ ((section(".extram")))
uint16_t buffer[480*272];
...
memset(buffer, 0xFF, 480 * 272 * sizeof(uint16_t));
Did I missed something?
I also tried to manually edit the buffer memory in debugger. It doesn't work. I use Eclipse CDT and Sloeber.

mlundin
Posts: 35
Joined: Wed Nov 04, 2020 1:20 pm
Answers: 2

Re: SDRAM use

Post by mlundin »

I did this work 2 years ago, found example code somewhere in STM codebase and then adapted to the specific memory chip, details long forgotten. The main difference from your code is I dont use the HAL and configuration structures but direct register calls. GPIO pin configuration seems same but here is my FMC configuration:

Code: Select all

/*-- FMC Configuration ------------------------------------------------------*/
  /* Enable the FMC interface clock */
  RCC->AHB3ENR |= 0x00000001;
  
  /* Delay after an RCC peripheral clock enabling */
  tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN);

  /* Configure and enable SDRAM bank1 */
  /* MT48LC4M32B2B5-6A 16 DATA, 12 ROW , 8 COL, 4 BANKS */
  FMC_Bank5_6->SDCR[0] = FMC_SDCR1_RBURST | FMC_SDCR1_SDCLK_1 | FMC_SDCR1_CAS_1 | FMC_SDCR1_NB | FMC_SDCR1_MWID_0 | FMC_SDCR1_NR_0; 

  FMC_Bank5_6->SDTR[0] = 0x01116361;      
  
  /* SDRAM initialization sequence */
  /* Clock enable command */
  FMC_Bank5_6->SDCMR = 0x00000011; 
  tmpreg = FMC_Bank5_6->SDSR & 0x00000020; 
  while((tmpreg != 0) && (timeout-- > 0))
  {
    tmpreg = FMC_Bank5_6->SDSR & 0x00000020; 
  }

  /* Delay */
  for (index = 0; index<1000; index++);
  
  /* PALL command */
  FMC_Bank5_6->SDCMR = 0x00000012;           

  timeout = 0xFFFF;
  while((tmpreg != 0) && (timeout-- > 0))
  {
    tmpreg = FMC_Bank5_6->SDSR & 0x00000020; 
  }
  
  /* Auto refresh command */
  FMC_Bank5_6->SDCMR = 0x000000F3;
  timeout = 0xFFFF;
  while((tmpreg != 0) && (timeout-- > 0))
  {
    tmpreg = FMC_Bank5_6->SDSR & 0x00000020; 
  }
 
  /* MRD register program */
  /* MRD = 0x000220 CL=2 */
  FMC_Bank5_6->SDCMR = 0x00044014;
  timeout = 0xFFFF;
  while((tmpreg != 0) && (timeout-- > 0))
  {
    tmpreg = FMC_Bank5_6->SDSR & 0x00000020; 
  } 
  
  /* Set refresh count */
  tmpreg = FMC_Bank5_6->SDRTR;
  FMC_Bank5_6->SDRTR = (tmpreg | (0x00000603<<1));
  
  /* Disable write protection */
  tmpreg = FMC_Bank5_6->SDCR[0]; 
  FMC_Bank5_6->SDCR[0] = (tmpreg & 0xFFFFFDFF);

Patrick
Posts: 17
Joined: Thu Dec 19, 2019 9:50 am
Answers: 1

SDRAM as display buffer for STM32F746 Discovery

Post by Patrick »

It is working now. I was missing to program the SDRAM chip.
I found a working example with STM32CubeIDE in folder STM32Cube\Repository\STM32Cube_FW_F7_V1.16.0\Projects\STM32746G-Discovery\Examples\FMC\FMC_SDRAM\SW4STM32.
I just had to copy the relevant functions and constants:
  • void HAL_SDRAM_MspInit(SDRAM_HandleTypeDef *hsdram)
  • static void BSP_SDRAM_Initialization_Sequence(SDRAM_HandleTypeDef *hsdram, FMC_SDRAM_CommandTypeDef *Command)
  • main (relevant part)
Now, it works well with buffer as a pointer to 0xC0000000 (SDRAM base address), DMA2D acceleration, and all others peripherals (TS, SD, Ethernet).
In the future I will check first, examples in STM32CubeIDE. It is very easy to integrate in STM32 Arduino Core.

Patrick
Posts: 17
Joined: Thu Dec 19, 2019 9:50 am
Answers: 1

Re: SDRAM use

Post by Patrick »

I forgot one point:
HAL_SDRAM_MODULE_ENABLED needs to be defined in variant.h.

Post Reply

Return to “General discussion”