cancel
Showing results for 
Search instead for 
Did you mean: 

STM32N6570-DK with FSBL and Appl - mapping external PSRAM in FSBL

Jack3
Senior III

Hello superhero MCU enthusiasts,

I'm playing with the STM32N6570-DK and have created a simple project with an FSBL that initializes the MCU and boots the Appl. Once booted, the Appl flashes a "Hello World" LED.
Both can be loaded to external flash using the STM32CubeProgrammer.

Now, I'm trying to map external PSRAM (XSPI1 -> 0x90000000) inside the FSBL, but it fails.

To do that, I change a line in a file in the FSBL, stm32_extmem_conf.h, line 35 of (PSRAM disabled):

#define EXTMEM_DRIVER_PSRAM 0

Now I try to enable and map the external PSRAM by setting the definition to 1:

#define EXTMEM_DRIVER_PSRAM 1

However, it doesn't succeed.

When debugging I see we land into a HardFault.

The FSBL generates a HardFault when executing SAL_XSPI_EnableMapMode, because the function HAL_XSPI_MemoryMapped fails.
I can't find the cause.
Anyone?
I posted a project here with a short Readme.md:

https://github.com/AngryCarrot61/STM32N6570-DK_004

Note: to see FSBL and Appl working one has to set EXTMEM_DRIVER_PSRAM to 0.
However the goal is to get PSRAM mapped (XSPI1 at 0x90000000).

Flashing:
the debug directories for FSBL and Appl contain a batch file: '0_SigningTool.bat'.
After compiling, run the batch files to sign the binaries.
Using STM32CubeProgrammer we select EL 'MX66UW1G45G_STM32N6570-DK'.
FSBL will be loaded at 0x70000000, and Appl at 0x70100000.
Enjoy!

 

Any help is much apreciated regarding the part to map the PSRAM!

Cheers!

2 REPLIES 2
prosacco478
Associate

 

The FSBL is crashing at HAL_XSPI_MemoryMapped() because:

  • The PSRAM isn’t properly initialized before entering memory-mapped mode.

  • The stm32_extmem_conf.c shipped with the BSP assumes OctoSPI NOR Flash by default.

  • The PSRAM device (like AP Memory APS256XXN used on the DK board) requires different initialization commands and timings.

So when you set

#define EXTMEM_DRIVER_PSRAM 1

the FSBL tries to map it, but the init structure for XSPI1 doesn’t match the PSRAM’s protocol → invalid command sequence → bus fault → HardFault.


The working fix:

You need to modify the external memory configuration used by FSBL to correctly initialize the PSRAM.

1. In stm32_extmem_conf.h

Leave:

#define EXTMEM_DRIVER_PSRAM 1

2. In stm32_extmem_conf.c

Locate the function that initializes external memory (usually something like EXTMEM_Init() or EXTMEM_InitPSRAM()).

Replace the PSRAM init with this correct configuration for the DK’s AP Memory PSRAM (OctoSPI1 → XSPI1):

 
#include "stm32h7rsxx_hal.h" // or stm32n6xx_hal.h depending on your package extern XSPI_HandleTypeDef hXSPI1; static void PSRAM_Init(void) { XSPI_MemoryMappedTypeDef sMemMappedCfg = {0}; XSPI_RegularCmdTypeDef sCommand = {0}; // Enable XSPI1 clock if not already done __HAL_RCC_XSPI1_CLK_ENABLE(); // Basic XSPI config hXSPI1.Instance = XSPI1; hXSPI1.Init.FifoThresholdByte = 4; hXSPI1.Init.MemoryType = HAL_XSPI_MEMTYPE_APMEM_PSRAM; // :white_heavy_check_mark: important hXSPI1.Init.MemorySize = HAL_XSPI_SIZE_64MB; // 512 Mbit PSRAM hXSPI1.Init.ChipSelectHighTimeCycle = 2; hXSPI1.Init.FreeRunningClock = HAL_XSPI_FREERUNCLK_DISABLE; hXSPI1.Init.ClockMode = HAL_XSPI_CLOCK_MODE_0; hXSPI1.Init.WrapSize = HAL_XSPI_WRAP_NOT_SUPPORTED; hXSPI1.Init.ClockPrescaler = 1; // 1 → max speed if clock configured hXSPI1.Init.SampleShifting = HAL_XSPI_SAMPLE_SHIFT_NONE; hXSPI1.Init.TransferRate = HAL_XSPI_TRANSFER_DTR; // :white_heavy_check_mark: PSRAM uses DTR hXSPI1.Init.DelayHoldQuarterCycle = HAL_XSPI_DHQC_ENABLE; if (HAL_XSPI_Init(&hXSPI1) != HAL_OK) { Error_Handler(); } // Memory-mapped mode config sMemMappedCfg.TimeOutActivation = HAL_XSPI_TIMEOUT_COUNTER_DISABLE; if (HAL_XSPI_MemoryMapped(&hXSPI1, &sMemMappedCfg) != HAL_OK) { Error_Handler(); // if it fails here, config mismatch } }

Then call PSRAM_Init() during your FSBL init sequence before jumping to the Application.


MPU setup (critical):

Ensure the FSBL enables MPU access for the PSRAM region before mapping it:

 

MPU_Region_InitTypeDef MPU_InitStruct = {0}; HAL_MPU_Disable(); MPU_InitStruct.Enable = MPU_REGION_ENABLE; MPU_InitStruct.BaseAddress = 0x90000000; MPU_InitStruct.Size = MPU_REGION_SIZE_64MB; MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE; MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE; MPU_InitStruct.Number = MPU_REGION_NUMBER1; MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0; MPU_InitStruct.SubRegionDisable = 0x00; MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE; HAL_MPU_ConfigRegion(&MPU_InitStruct); HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);

Without this, you’ll get a HardFault as soon as code or DMA touches 0x90000000.


verification

After boot:

uint32_t *psram = (uint32_t*)0x90000000; psram[0] = 0x12345678; if (psram[0] == 0x12345678) printf("PSRAM mapped OK!\n"); else printf("PSRAM test failed.\n");

If you apply those three key fixes (correct MemoryType, DTR mode, MPU region), HAL_XSPI_MemoryMapped() will succeed and the FSBL will no longer HardFault.

Would you like me to adapt this into a ready-to-paste STM32CubeIDE code snippet (with includes + call sequence for FSBL main.c)?

 

Thank you very much, I forgot to add the PSRAM into the MPU.
However, the initialization still failes, so I wouldn't be able to access it anyway.
My new STM32N6 MPU configuration:

static void MPU_Config(void)
{
  /*
   * XSPI2 0x70000000 128MB FLASH (1-Gbit   Octo-SPI)
   * XSPI1 0x90000000  32MB PSRAM (256-Mbit Hexadeca-SPI)
   */
  MPU_Region_InitTypeDef default_config = {0};
  MPU_Attributes_InitTypeDef attr_config = {0};
  uint32_t primask_bit = __get_PRIMASK();
  __disable_irq();

  /* disable the MPU */
  HAL_MPU_Disable();

  /* create an attribute configuration for the MPU */
  attr_config.Attributes = INNER_OUTER(MPU_WRITE_BACK | MPU_NON_TRANSIENT | MPU_RW_ALLOCATE);
  attr_config.Number = MPU_ATTRIBUTES_NUMBER0;

  HAL_MPU_ConfigMemoryAttributes(&attr_config);

  /* Create a region associated with memory address 0x70000000 */
  /*Normal memory type, code execution allowed */
  default_config.Number = MPU_REGION_NUMBER0;
  default_config.Enable = MPU_REGION_ENABLE;
  default_config.BaseAddress = XSPI2_BASE; /* FLASH 128MB 0x70000000 */
  default_config.LimitAddress = XSPI2_BASE + 0x08000000-1;
  default_config.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
  default_config.AccessPermission = MPU_REGION_ALL_RO;
  default_config.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
  default_config.AttributesIndex = MPU_ATTRIBUTES_NUMBER0;
  HAL_MPU_ConfigRegion(&default_config);

  /* Ensure the FSBL enables MPU access for the PSRAM region before mapping it: */
  default_config.Number = MPU_REGION_NUMBER1;
  default_config.Enable = MPU_REGION_ENABLE;
  default_config.BaseAddress = XSPI1_BASE; /* PSRAM 32MB 0x90000000 */
  default_config.LimitAddress = XSPI1_BASE + 0x02000000-1;
  default_config.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
  default_config.AccessPermission = MPU_REGION_ALL_RW;
  default_config.IsShareable = MPU_ACCESS_INNER_SHAREABLE | MPU_ACCESS_OUTER_SHAREABLE;
  default_config.AttributesIndex = MPU_ATTRIBUTES_NUMBER0;
  HAL_MPU_ConfigRegion(&default_config);

  /* enable the MPU */
  HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);

  /* Exit critical section to lock the system and avoid any issue around MPU mechanisme */
  __set_PRIMASK(primask_bit);
}

I still hope to find the problem soon. I'm looking into my XSPI1 configuration.
Thanks for helping!