cancel
Showing results for 
Search instead for 
Did you mean: 

OPENAMP STM32H745 memory problems

MReus.2
Associate II

Hello,

i am trying to implement Openamp to in a project with touchgfx. In the beginning i started with openamp and it worked. M7 was the master, M4 the slave and i had a working implementation. It turned out that encoders etc are better handleled on the M7 near touchgfx so alot of the project was rewritten. What i added is 8 AD converter with 200kHz sampling frequency which is handled by DMA. 32kB of the D2 Ram where reserved and protected by the MPU. Since i want to calculate a fft, the ad samples get copied to the dtcmram which is i also added in the linker file. Since the M4 now only handles the network communication, it seemed better suited as the master for openamp. It can initiallice OPENAMP while touchgfx is busy setting up everything else and then starts a task to join as slave. I couldnt get it to work. I always got hard faults. I changed it back to the same configuration as it was before but i cant get it to work. There is a hardf fault every time the M4 try to init th MX_OPENAMP_Init(). It works its way up to metal_bus_register(struct metal_bus *bus) and then throws the error. Everything seems to me like the M4 has no access to the shared memory. The Ressource Table is at 0x38000000 (1kB) and shared memory starts at 0x38000400 (63kB). This is the beginning of D3 RAM. I read that the M4 has no access to the D3 RAM so i changed it to D2 0x30008000 and 0x30008400 (first 32kB of D2 are for DMA Buffer). This did not work for me either. Can aybody help me here?

 

  M4 Linker file

 

/*
******************************************************************************
**
**  File        : LinkerScript.ld
**
**  Author      : STM32CubeIDE
**
**  Abstract    : Linker script for STM32H7 series
**                1024Kbytes FLASH and 288Kbytes 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) 2023 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 */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x200;      /* required amount of heap  */
_Min_Stack_Size = 0x400; /* required amount of stack */

/* Specify the memory areas */
MEMORY
{
FLASH (rx)     : ORIGIN = 0x08100000, LENGTH = 1024K
RAM (xrw)      : ORIGIN = 0x10000000, LENGTH = 288K
OPENAMP_RSC_TAB (xrw)     : ORIGIN = 0x38000000, LENGTH = 1K
OPEN_AMP_SHMEM (xrw) : ORIGIN = 0x38000400, LENGTH = 63K
}
__OPENAMP_region_start__  = ORIGIN(OPEN_AMP_SHMEM);
__OPENAMP_region_end__ = ORIGIN(OPEN_AMP_SHMEM) + LENGTH(OPEN_AMP_SHMEM);

/* Define output sections */
SECTIONS
{
  /* The startup code goes first into FLASH */
  .isr_vector :
  {
    . = ALIGN(4);
    KEEP(*(.isr_vector)) /* Startup code */
    . = ALIGN(4);
  } >FLASH

  /* The program code and other data goes into FLASH */
  .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)

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

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

  /* Constant data goes into FLASH */
  .rodata :
  {
    . = ALIGN(4);
    *(.rodata)         /* .rodata sections (constants, strings, etc.) */
    *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
    . = ALIGN(4);
  } >FLASH

  .ARM.extab   : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
  .ARM : {
    __exidx_start = .;
    *(.ARM.exidx*)
    __exidx_end = .;
  } >FLASH

  .preinit_array     :
  {
    PROVIDE_HIDDEN (__preinit_array_start = .);
    KEEP (*(.preinit_array*))
    PROVIDE_HIDDEN (__preinit_array_end = .);
  } >FLASH
  .init_array :
  {
    PROVIDE_HIDDEN (__init_array_start = .);
    KEEP (*(SORT(.init_array.*)))
    KEEP (*(.init_array*))
    PROVIDE_HIDDEN (__init_array_end = .);
  } >FLASH
  .fini_array :
  {
    PROVIDE_HIDDEN (__fini_array_start = .);
    KEEP (*(SORT(.fini_array.*)))
    KEEP (*(.fini_array*))
    PROVIDE_HIDDEN (__fini_array_end = .);
  } >FLASH

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

  /* Initialized data sections goes into RAM, load LMA copy after code */
  .data :
  {
    . = ALIGN(4);
    _sdata = .;        /* create a global symbol at data start */
    *(.data)           /* .data sections */
    *(.data*)          /* .data* sections */
    *(.RamFunc)        /* .RamFunc sections */
    *(.RamFunc*)       /* .RamFunc* sections */

    . = ALIGN(4);
    _edata = .;        /* define a global symbol at data end */
  } >RAM AT> FLASH


  /* Uninitialized data section */
  . = 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 left */
  ._user_heap_stack :
  {
    . = ALIGN(8);
    PROVIDE ( end = . );
    PROVIDE ( _end = . );
    . = . + _Min_Heap_Size;
    . = . + _Min_Stack_Size;
    . = ALIGN(8);
  } >RAM

     .openamp_section (NOLOAD) : {
     . = ABSOLUTE(0x38000000);
     *(.resource_table) 
  } >OPENAMP_RSC_TAB  AT > FLASH
  
  .openamp_shmem (NOLOAD) :
  {
    . = ABSOLUTE(0x38000400);
  } >OPEN_AMP_SHMEM

  /* Remove information from the standard libraries */
  /DISCARD/ :
  {
    libc.a ( * )
    libm.a ( * )
    libgcc.a ( * )
  }

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

 

 

M7 Linker file

 

/*
******************************************************************************
**
**  File        : LinkerScript.ld
**
**  Author      : STM32CubeIDE
**
**  Abstract    : Linker script for STM32H7 series
**                      1024Kbytes FLASH
**                       800Kbytes 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
**
** <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
** All rights reserved.</center></h2>
**
** This software component is licensed by ST under BSD 3-Clause license,
** the "License"; You may not use this file except in compliance with the
** License. You may obtain a copy of the License at:
**                        opensource.org/licenses/BSD-3-Clause
**
*****************************************************************************
*/

/* Entry Point */
ENTRY(Reset_Handler)

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

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

/* Memories definition */
MEMORY
{
  RAM_D1 	(xrw)	: ORIGIN = 0x24000000, LENGTH =  512K
  FLASH  	(rx)    : ORIGIN = 0x08000000, LENGTH = 1024K    /* Memory is divided. Actual start is 0x08000000 and actual length is 2048K */
  DTCMRAM 	(xrw)  	: ORIGIN = 0x20000000, LENGTH = 128K
  RAM_D2_NC (rw)   	: ORIGIN = 0x30000000, LENGTH = 32K
  RAM_D2 	(xrw)   : ORIGIN = 0x30008000, LENGTH = 256K
  RAM_D3 	(xrw)   : ORIGIN = 0x38000000, LENGTH = 64K
  ITCMRAM 	(xrw)  	: ORIGIN = 0x00000000, LENGTH = 64K
  QUADSPI 	(r)    	: ORIGIN = 0x90000000, LENGTH = 126M
  SDRAM     (xrw)    : ORIGIN = 0xD0000000,   LENGTH = 16M
  OPENAMP_RSC_TAB (xrw)   : ORIGIN = 0x38000000, LENGTH = 1K
  OPEN_AMP_SHMEM (xrw) : ORIGIN = 0x38000400, LENGTH = 63K
}
__OPENAMP_region_start__  = ORIGIN(OPEN_AMP_SHMEM);
__OPENAMP_region_end__ = ORIGIN(OPEN_AMP_SHMEM) + LENGTH(OPEN_AMP_SHMEM);

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

  /* The program code and other data into "FLASH" Rom 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)

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

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

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

  .ARM.extab   : { 
    . = ALIGN(4);
    *(.ARM.extab* .gnu.linkonce.armextab.*)
    . = ALIGN(4);
  } >FLASH
  
  .ARM : {
    . = ALIGN(4);
    __exidx_start = .;
    *(.ARM.exidx*)
    __exidx_end = .;
    . = ALIGN(4);
  } >FLASH

  .preinit_array :
  {
    . = ALIGN(4);
    PROVIDE_HIDDEN (__preinit_array_start = .);
    KEEP (*(.preinit_array*))
    PROVIDE_HIDDEN (__preinit_array_end = .);
    . = ALIGN(4);
  } >FLASH
  
  .init_array :
  {
    . = ALIGN(4);
    PROVIDE_HIDDEN (__init_array_start = .);
    KEEP (*(SORT(.init_array.*)))
    KEEP (*(.init_array*))
    PROVIDE_HIDDEN (__init_array_end = .);
    . = ALIGN(4);
  } >FLASH
  
  .fini_array :
  {
    . = ALIGN(4);
    PROVIDE_HIDDEN (__fini_array_start = .);
    KEEP (*(SORT(.fini_array.*)))
    KEEP (*(.fini_array*))
    PROVIDE_HIDDEN (__fini_array_end = .);
    . = ALIGN(4);
  } >FLASH

  /* 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 */
    *(.RamFunc)        /* .RamFunc sections */
    *(.RamFunc*)       /* .RamFunc* sections */

    . = ALIGN(4);
    _edata = .;        /* define a global symbol at data end */
  } >RAM_D1 AT> FLASH

	.DTCMRAM (NOLOAD) :
	{
	    . = ALIGN(8);
	    *(.DTCMRAM)
	} >DTCMRAM
  
  /* 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_D1

  /* 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_D1
  
     .openamp_section (NOLOAD) : {
     . = ABSOLUTE(0x38000000);
     *(.resource_table) 
  } >OPENAMP_RSC_TAB  AT > FLASH
  
    .openamp_shmem (NOLOAD) :
  {
    . = ABSOLUTE(0x38000400);
  } >OPEN_AMP_SHMEM

  /*non cacheable ram init, selbt hinzugef?gt*/  
  .RAM_D2_NC (NOLOAD) :
  {
  	. = ALIGN(32);
  	*(.RAM_D2_NC)
  } > RAM_D2_NC

  /* Remove information from the compiler libraries */
  /DISCARD/ :
  {
    libc.a ( * )
    libm.a ( * )
    libgcc.a ( * )
  }

  .ARM.attributes 0 : { *(.ARM.attributes) }
  
    FontFlashSection :
  {
    *(FontFlashSection FontFlashSection.*)
    *(.gnu.linkonce.r.*)
    . = ALIGN(0x4);
  } >QUADSPI

  TextFlashSection :
  {
    *(TextFlashSection TextFlashSection.*)
    *(.gnu.linkonce.r.*)
    . = ALIGN(0x4);
  } >QUADSPI

  ExtFlashSection :
  {
    *(ExtFlashSection ExtFlashSection.*)
    *(.gnu.linkonce.r.*)
    . = ALIGN(0x4);
  } >QUADSPI

  BufferSection (NOLOAD) :
  {
    *(TouchGFX_Framebuffer TouchGFX_Framebuffer.*)
    *(.gnu.linkonce.r.*)
    . = ALIGN(0x4);

    *(Video_RGB_Buffer Video_RGB_Buffer.*)
    *(.gnu.linkonce.r.*)
    . = ALIGN(0x4);
   } >SDRAM
}

 

 

M4 main

 

   int32_t status = 0;
   memset((void *)SHMEM_ADDR, 0, SHMEM_SIZE);

   /* Initialize the mailbox use notify the other core on new message */
   MAILBOX_Init();

   /* Initialize OpenAmp and libmetal libraries */
   if (MX_OPENAMP_Init(RPMSG_REMOTE, NULL)!= HAL_OK)
   {
	   Error_Handler();
   }


   /* Create an endpoint for rmpsg communication */
   status = OPENAMP_create_endpoint(&rp_endpoint, RPMSG_SERVICE_NAME, RPMSG_ADDR_ANY, rpmsg_recv_callback, NULL);
   if (status < 0)
   {
     Error_Handler();
   }

 

 

M7 task

 

  MAILBOX_Init();

  /* Initialize the rpmsg endpoint to set default addresses to RPMSG_ADDR_ANY */
	rpmsg_init_ept(&rp_endpoint, RPMSG_CHAN_NAME, RPMSG_ADDR_ANY, RPMSG_ADDR_ANY, NULL, NULL);
	/* Initialize OpenAmp and libmetal libraries */
	if (MX_OPENAMP_Init(RPMSG_MASTER, new_service_cb)!= HAL_OK)
	{
		Error_Handler();
	}

	/*
	* The rpmsg service is initiate by the remote processor, on A7 new_service_cb
	* callback is received on service creation. Wait for the callback
	*/
	OPENAMP_Wait_EndPointready(&rp_endpoint);

	ipccMessage temp;
	temp.id = 0;
	temp.leftValue = 0;
	temp.rightValue = 0;
	temp.link = 0;
	status = OPENAMP_send(&rp_endpoint, &temp, sizeof(temp));
   if (status < 0)
   {
	 Error_Handler();
   }

	/* Wait that service is destroyed on remote side */
	while(1)
	{
		//HAL_Delay(1);
		OPENAMP_check_for_message();
	}

	/* De-initialize OpenAMP */
	OPENAMP_DeInit();
void new_service_cb(struct rpmsg_device *rdev, const char *name, uint32_t dest)
{
  /* create a endpoint for rmpsg communication */
  OPENAMP_create_endpoint(&rp_endpoint, name, dest, rpmsg_recv_callback,
                          service_destroy_cb);
  service_created = 1;
}

 

 

Please let me know if there is Information missing. 

Thanks

Martin

1 REPLY 1
MReus.2
Associate II

What I found is that it starts with this function, MX_OPENAMP_Init(...). The last function call is metal_bus_register(...), which gets a struct object named metal_generic_bus. The objects address can be read in the main and is valid, but the name is not accessible and has a very strange memory adress. Trying to access the name object leads to a hard fault. Shown below is the piece of code that cause the hard fault while trying to access the name varible.

 

 

int metal_bus_register(struct metal_bus *bus)

{

if (!bus || !bus->name || !strlen(bus->name))

return -EINVAL;

 

Here is a picture of the main, where i try to access the struct, and on the name there is no access.

Screenshot 2025-02-20 205732.png

I really do not understand why this is happening. 

If you need further informaitions about the files or the struct please let me know. Nothing has been changed in the openamp files.

Any help is highly appreciated

Thanks