cancel
Showing results for 
Search instead for 
Did you mean: 

LTDC Controller not displaying image

DHOUT19
Associate II

I am currently using the STM32N657 on the NUCLEO-N657X0-Q board to drive an 800x480 pixel display with 24-bit color. The display that I am using is the NHD-7.0-800480EF-ASXV#-T. I’m using the built in LTDC controller on the chip. I do know that the controller is working because the entire screen is black, the screen would be showing the backlight if it wasn’t. The problem is that I am unable to display anything at all when writing to the screen buffer.

Here are the configuration parameters that I am using based on the data sheet:

DHOUT19_0-1756245275614.png

Here are the layer settings that I am using:

DHOUT19_1-1756245305699.png

Here is the clock configuration for the LTDC:

DHOUT19_2-1756245348090.png

 

Here is the code that I am running:

main.c

int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_ICACHE_Init();
  MX_LTDC_Init();
  MX_RAMCFG_Init();
  /* USER CODE BEGIN 2 */
  hal_pointers_t halPointers = {0};
  halPointers.hltdc = &hltdc;
  /* USER CODE END 2 */

  /* Initialize leds */
  BSP_LED_Init(LED_BLUE);
  BSP_LED_Init(LED_RED);
  BSP_LED_Init(LED_GREEN);

  /* Initialize USER push-button, will be used to trigger an interrupt each time it's pressed.*/
  BSP_PB_Init(BUTTON_USER, BUTTON_MODE_EXTI);

  /* Initialize COM1 port (115200, 8 bits (7-bit data + 1 stop bit), no parity */
  BspCOMInit.BaudRate   = 115200;
  BspCOMInit.WordLength = COM_WORDLENGTH_8B;
  BspCOMInit.StopBits   = COM_STOPBITS_1;
  BspCOMInit.Parity     = COM_PARITY_NONE;
  BspCOMInit.HwFlowCtl  = COM_HWCONTROL_NONE;
  if (BSP_COM_Init(COM1, &BspCOMInit) != BSP_ERROR_NONE)
  {
    Error_Handler();
  }

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  __HAL_RCC_AXISRAM3_MEM_CLK_ENABLE();
  __HAL_RCC_AXISRAM4_MEM_CLK_ENABLE();
  __HAL_RCC_AXISRAM5_MEM_CLK_ENABLE();
  __HAL_RCC_AXISRAM6_MEM_CLK_ENABLE();

  HAL_RAMCFG_EnableAXISRAM(&hramcfg_SRAM3);
  HAL_RAMCFG_EnableAXISRAM(&hramcfg_SRAM4);
  HAL_RAMCFG_EnableAXISRAM(&hramcfg_SRAM5);
  HAL_RAMCFG_EnableAXISRAM(&hramcfg_SRAM6);

  main_app(halPointers);
  while (1)
  {

    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

main_app function

#include "main_application.h"

__attribute__((section(".screen_buffer")))
uint8_t screen_buffer[FRAME_BUFFER_SIZE];

void main_app(hal_pointers_t hal_pointers){

	for (uint32_t i = 0; i < FRAME_BUFFER_SIZE; i++){
		screen_buffer[i] = 0;
	}


	HAL_LTDC_SetAddress(hal_pointers.hltdc, (uint32_t) screen_buffer, 0);
	//HAL_LTDC_ReloadLayer(hal_pointers.hltdc, LTDC_RELOAD_IMMEDIATE, 0);
	//HAL_LTDC_SetOutputDisplay(hal_pointers.hltdc, LTDC_OUT_RGB);

	//Make a square
	for (uint32_t i = 0; i < FRAME_BUFFER_SIZE/3; i++){
		//for (uint32_t j = 0; j < 20; j++){
			//screen_buffer[(i*3) + (j*SCREEN_WIDTH*3)] = 255;
			screen_buffer[i*3] = 0x55;
		//}
	}

	while(1){
	}

}

Linker Script (Just in case):

/*
******************************************************************************
**
** @file        : STM32N6XX_AXISRAM2_fsbl.ld
**
** @author      : GPM Application Team
**
** @brief       : Linker script for STM32N6XX Device from STM32N6 series
**                      512 KBytes 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.
**
******************************************************************************
** @attention
**
** Copyright (c) 2025 STMicroelectronics.
** All rights reserved.
**
** This software is licensed under terms that can be found in the LICENSE file
** in the root directory of this software component.
** If no LICENSE file comes with this software, it is provided AS-IS.
**
******************************************************************************
*/

/* Entry Point */
ENTRY(Reset_Handler)

/* Highest address of the user mode stack */
_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of "RAM" Ram type memory */
_sstack = _estack - _Min_Stack_Size;

_Min_Heap_Size = 0x200; /* required amount of heap */
_Min_Stack_Size = 0x800; /* required amount of stack */

/* Memories definition */
MEMORY
{
  ROM    (xrw)    : ORIGIN = 0x34180400,   LENGTH = 255K
  RAM    (xrw)    : ORIGIN = 0x341C0000,   LENGTH = 256K
  SCREEN_BUFFER_SRAM   (rw)     : ORIGIN = 0x34200000,   LENGTH = 1300K
}

/* Sections */
SECTIONS
{
  /* The startup code into "RAM" Ram type memory */
  .isr_vector :
  {
    . = ALIGN(4);
    KEEP(*(.isr_vector)) /* Startup code */
    . = ALIGN(4);
  } >ROM

  /* The program code and other data into "RAM" Ram type memory */
  .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)
    *(.RamFunc)        /* .RamFunc sections */
    *(.RamFunc*)       /* .RamFunc* sections */

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

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

  /* Constant data into "RAM" Ram type memory */
  .rodata :
  {
    . = ALIGN(4);
    *(.rodata)         /* .rodata sections (constants, strings, etc.) */
    *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
    . = ALIGN(4);
  } >ROM

  .ARM.extab   (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */
   {
    . = ALIGN(4);
    *(.ARM.extab* .gnu.linkonce.armextab.*)
    . = ALIGN(4);
  } >ROM

  .ARM (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */
   {
    . = ALIGN(4);
    __exidx_start = .;
    *(.ARM.exidx*)
    __exidx_end = .;
    . = ALIGN(4);
  } >ROM

  .preinit_array     (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */
  {
    . = ALIGN(4);
    PROVIDE_HIDDEN (__preinit_array_start = .);
    KEEP (*(.preinit_array*))
    PROVIDE_HIDDEN (__preinit_array_end = .);
    . = ALIGN(4);
  } >ROM

  .init_array (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */
  {
    . = ALIGN(4);
    PROVIDE_HIDDEN (__init_array_start = .);
    KEEP (*(SORT(.init_array.*)))
    KEEP (*(.init_array*))
    PROVIDE_HIDDEN (__init_array_end = .);
    . = ALIGN(4);
  } >ROM

  .fini_array (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */
  {
    . = ALIGN(4);
    PROVIDE_HIDDEN (__fini_array_start = .);
    KEEP (*(SORT(.fini_array.*)))
    KEEP (*(.fini_array*))
    PROVIDE_HIDDEN (__fini_array_end = .);
    . = ALIGN(4);
  } >ROM

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

  /* Initialized data sections into "RAM" Ram type memory */
  .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 */

  } >RAM AT> ROM

  .noncacheable :
  {
    . = ALIGN(8);
    __snoncacheable = .;/* create symbol for start of section */
    KEEP(*(.noncacheable))
    . = ALIGN(8);
    __enoncacheable = .;  /* create symbol for end of section */
  } > RAM


  .gnu.sgstubs :
  {
    . = ALIGN(4);
    *(.gnu.sgstubs*)   /* Secure Gateway stubs */
    . = ALIGN(4);
  } >ROM
  /* Uninitialized data section into "RAM" Ram type memory */
  . = ALIGN(4);
  .bss :
  {
    /* This is used by the startup in order to initialize the .bss section */
    _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;
  } >RAM

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

  /* Remove information from the compiler libraries */
  /DISCARD/ :
  {
    libc.a ( * )
    libm.a ( * )
    libgcc.a ( * )
  }
  
  .screen_buffer (NOLOAD) :
  {
  	. = ALIGN(4);
  	_screen_buffer_start = .;
  	KEEP(*(.screen_buffer))
  	. = ALIGN(4);
  	_screen_buffer_end = .;
  } > SCREEN_BUFFER_SRAM

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

Here is what I’ve observed:

- I have run the code in debug mode and can see data being written at the screen buffer location

- I’ve hooked up a logic analyzer to the red data pins, HSYNC, VSYNC, DE, and DCLK (below is a snapshot). When the red data pins are not active HSYNC seems to be acting somewhat normally. When the data pins are active, HSYNC does not act normal at all. It pulses almost randomly. Please note that the logic analyzer is a cheap one from Amazon, so it may not even be reading this data correctly.

DHOUT19_3-1756245465102.png

DHOUT19_4-1756245505638.png

 

Here's what I’ve tried:

- I’ve tried using the following HAL functions: HAL_LTDC_ReloadLayer(hal_pointers.hltdc, LTDC_RELOAD_IMMEDIATE, 0), HAL_LTDC_SetOutputDisplay(hal_pointers.hltdc, LTDC_OUT_RGB). No change

- I’ve tried slightly adjusting the pulse width settings for both HSYNC and VSYNC. No change.

 

Let me know if I’ve forgotten to provide any information.

0 REPLIES 0