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?
SDRAM use
-
- Posts: 633
- Joined: Thu Dec 19, 2019 1:23 am
Re: SDRAM use
Are you already using off-chip RAM?
https://www.st.com/en/evaluation-tools/ ... overy.html
https://www.matrixtsl.com/mmforums/view ... 547#p89170
https://www.st.com/en/evaluation-tools/ ... overy.html
... and...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)
https://www.matrixtsl.com/mmforums/view ... 547#p89170
Re: SDRAM use
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
and the sdram output section to load variables with attribute 'extram'
* Third allocate the display memory with attribute 'extram' (I am using 16bit RGB565 pixels)
* 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
Code: Select all
__attribute__ ((section(".extram")))
uint16_t framebuffer1[LCD_WIDTH*LCD_HEIGHT];
Re: SDRAM use
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:
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.
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.
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);
}
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));
I also tried to manually edit the buffer memory in debugger. It doesn't work. I use Eclipse CDT and Sloeber.
Re: SDRAM use
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);
SDRAM as display buffer for STM32F746 Discovery
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:
In the future I will check first, examples in STM32CubeIDE. It is very easy to integrate in STM32 Arduino Core.
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)
In the future I will check first, examples in STM32CubeIDE. It is very easy to integrate in STM32 Arduino Core.
Re: SDRAM use
I forgot one point:
HAL_SDRAM_MODULE_ENABLED needs to be defined in variant.h.
HAL_SDRAM_MODULE_ENABLED needs to be defined in variant.h.