cancel
Showing results for 
Search instead for 
Did you mean: 

Accessing external RAM on boot on the STM32H7S78-DK via XSPI

nico23
Senior III

I'm currently using an STM32H7S78-DK, and I'm correctly able to run TouchGFX with FreeRTOS and everything. I also an error handler function that, in case of a crash of TouchGFX it writes directly to the framebuffer.

Now, I would like to do a similar thing but on the boot code, so basically before the classic jump if (BOOT_OK != BOOT_Application())

I have an external RAM mapped at the address 0x90000000 which works correctly in TouchGFX with .icf like

define symbol __region_EXTRAM_start__  = 0x90000000;
define symbol __region_EXTRAM_end__    = 0x91FFFFFF;
define region EXTRAM_region   = mem:[from __region_EXTRAM_start__ to __region_EXTRAM_end__];
place in EXTRAM_region { first section TouchGFX_Framebuffer
                       , section Video_RGB_Buffer 
                       , section Nemagfx_Stencil_Buffer };

I wanted to use the same section of memory in the Boot, accessing the framebuffer directly, so I edited the .icf of the boot with

define symbol __region_EXTRAM_start__  = 0x90000000;
define symbol __region_EXTRAM_end__    = 0x91FFFFFF;
define region EXTRAM_region   = mem:[from __region_EXTRAM_start__ to __region_EXTRAM_end__];
place in EXTRAM_region { first section Boot_Framebuffer };

And in the main.c

#pragma location = "Boot_Framebuffer"
__no_init uint32_t frameBuf[(800 * 480 * 2 + 3) / 4 * 2];

Using J-Link and IAR, during the debug, I'm seeing the frameBuf is correctly mapped from address 0x90000000 but, as soon as I try to access the memory address, for instance wiping the frameBuf with

memset((void*)frameBuf, 0, sizeof(frameBuf));

The code goes into HardFault. I have set the correct address for the LTDC with

  LTDC_Layer1->CFBAR = (uint32_t)frameBuf;
  LTDC->SRCR = (uint32_t)LTDC_SRCR_IMR;

and I'm correctly initializing the XSPI as they return HAL_OK

  MX_XSPI1_Init();  // External flash
  MX_XSPI2_Init();  // External PSRAM

I've alos configured the MPU region for the EXT RAM with

static void MPU_Config(void)
{
  MPU_Region_InitTypeDef MPU_InitStruct = {0};

  /* Disables the MPU */
  HAL_MPU_Disable();
  
  MPU_InitStruct.Enable = MPU_REGION_ENABLE;
  MPU_InitStruct.Number = MPU_REGION_NUMBER3;
  MPU_InitStruct.BaseAddress = 0x90000000;
  MPU_InitStruct.Size = MPU_REGION_SIZE_32MB;
  MPU_InitStruct.SubRegionDisable = 0x00;
  MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;
  MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
  MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
  MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
  MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
  MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;

  HAL_MPU_ConfigRegion(&MPU_InitStruct);
  
  HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}

I suspect that the CPU does not have the address of the external RAM mapped in its internal registries; could it be? Is there a way to access this frame buffer and read/write it to/from the external RAM

1 ACCEPTED SOLUTION

Accepted Solutions
nico23
Senior III

The issue seemed to be that in the MX_EXTMEM_MANAGER_Init it wasn't defined 

  if (EXTMEM_MemoryMappedMode(EXTMEMORY_2, EXTMEM_ENABLE) != EXTMEM_OK)
  {
    Error_Handler();
  }

View solution in original post

3 REPLIES 3
Ozone
Principal III

> .. as soon as I try to access the memory address, for instance wiping the frameBuf with ... The code goes into HardFault.

This is to be expected.
External busses (and external RAM attached to it) need to be initialized before you can access it.
This is usually done in the context of the SystemInit() function, located in system_stm32xxxx.c.
So you most probably need to find and replicate this code in your bootloader.

nico23
Senior III

Hi @Ozone 

thanks for pointing it out; I didn't know it.

I've just checked my system_stm32h7rsxx.c

and I'm seeing the

void SystemInit(void)
{
  /* Configure the Vector Table location -------------------------------------*/
  SCB->VTOR = INTVECT_START;

  /* FPU settings ------------------------------------------------------------*/
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
  SCB->CPACR |= ((3UL << 20U)|(3UL << 22U));  /* set CP10 and CP11 Full Access */
#endif
}

Also, in the startup_stm32h7rsxx.s it is called like

THUMB
        PUBWEAK Reset_Handler
        SECTION .text:CODE:NOROOT:REORDER(2)
Reset_Handler
        LDR     R0, =SystemInit
        BLX     R0
        LDR     R0, =__iar_program_start
        BX      R0

Do I just need to call the SystemInit function from my main() in the Boot?

Also, in the boot the memory manager is initialized

/**
  * Init External memory manager
  * @retval None
  */
void MX_EXTMEM_MANAGER_Init(void)
{

  /* USER CODE BEGIN MX_EXTMEM_Init_PreTreatment */

  /* USER CODE END MX_EXTMEM_Init_PreTreatment */
  HAL_RCCEx_EnableClockProtection(RCC_CLOCKPROTECT_XSPI);

  /* Initialization of the memory parameters */
  memset(extmem_list_config, 0x0, sizeof(extmem_list_config));

  /* EXTMEMORY_1 */
  extmem_list_config[0].MemType = EXTMEM_NOR_SFDP;
  extmem_list_config[0].Handle = (void*)&hxspi2;
  extmem_list_config[0].ConfigType = EXTMEM_LINK_CONFIG_8LINES;

  /* EXTMEMORY_2 */
  extmem_list_config[1].MemType = EXTMEM_PSRAM;
  extmem_list_config[1].Handle = (void*)&hxspi1;
  extmem_list_config[1].ConfigType = EXTMEM_LINK_CONFIG_16LINES;

  extmem_list_config[1].PsramObject.psram_public.MemorySize = HAL_XSPI_SIZE_256MB;
  extmem_list_config[1].PsramObject.psram_public.FreqMax = 200 * 1000000u;
  extmem_list_config[1].PsramObject.psram_public.NumberOfConfig = 1u;

  /* Config */
  extmem_list_config[1].PsramObject.psram_public.config[0].WriteMask = 0x40u;
  extmem_list_config[1].PsramObject.psram_public.config[0].WriteValue = 0x40u;
  extmem_list_config[1].PsramObject.psram_public.config[0].REGAddress = 0x08u;

  /* Memory command configuration */
  extmem_list_config[1].PsramObject.psram_public.ReadREG           = 0x40u;
  extmem_list_config[1].PsramObject.psram_public.WriteREG          = 0xC0u;
  extmem_list_config[1].PsramObject.psram_public.ReadREGSize       = 2u;
  extmem_list_config[1].PsramObject.psram_public.REG_DummyCycle    = 4u;
  extmem_list_config[1].PsramObject.psram_public.Write_command     = 0xA0u;
  extmem_list_config[1].PsramObject.psram_public.Write_DummyCycle  = 4u;
  extmem_list_config[1].PsramObject.psram_public.Read_command      = 0x20u;
  extmem_list_config[1].PsramObject.psram_public.WrapRead_command  = 0x00u;
  extmem_list_config[1].PsramObject.psram_public.Read_DummyCycle   = 4u;

  EXTMEM_Init(EXTMEMORY_1, HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_XSPI2));
  EXTMEM_Init(EXTMEMORY_2, HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_XSPI1));

  /* USER CODE BEGIN MX_EXTMEM_Init_PostTreatment */

  /* USER CODE END MX_EXTMEM_Init_PostTreatment */
}

It seems that, when I try to debug the App, the memory is already attached and working, as TouchGFX is easily using it, when debugging the Boot, it doesn't work

nico23
Senior III

The issue seemed to be that in the MX_EXTMEM_MANAGER_Init it wasn't defined 

  if (EXTMEM_MemoryMappedMode(EXTMEMORY_2, EXTMEM_ENABLE) != EXTMEM_OK)
  {
    Error_Handler();
  }