2025-08-21 4:13 AM - last edited on 2025-08-21 4:23 AM by STTwo-32
Hello,
I'm currently testing a bootloader-XIP application architecture on a NUCLEO-H7S3L8 board. The MRAM (XSPI2) test works perfectly in the bootloader, but when I move the same code to the XIP application, the system hangs during XSPI2 initialization. I would appreciate any advice on this issue.
System Environment
MCU: STM32H7S3L8
Board: NUCLEO-H7S3L8
IDE: STM32CubeIDE v1.19.0
Firmware: STM32Cube_FW_H7RS_V1.2.0
Project Goal and Progress
I have successfully completed all communication mode tests for the MRAM (XSPI2) in the bootloader (exercise_Boot).
The bootloader runs from internal flash, and through mram_spi_test.c, it has fully tested the MRAM connected to XSPI2 in all SDR/DDR and SPI/DSPI/QSPI modes, confirming perfect operation.
I have migrated the verified test code to the XIP application (exercise_Appli).
The bootloader loads the application to the external NOR flash (connected to XSPI1) and jumps to it in XIP mode.
I have successfully confirmed that the application boots in XIP mode and can output printf logs.
The Problem
In the application's main() function, the system hangs the moment MX_XSPI2_Init() is called to run the same MRAM test that was used in the bootloader.
Since MX_XSPI1_Init() and MX_XSPI2_Init() have already been executed in the bootloader, I expected that the hardware would be ready and calling MX_XSPI2_Init() again in the application should not be a problem, but it results in a system fault.
Key Questions
What is the standard initialization procedure for reliably using a secondary peripheral (like XSPI2) in an application that is running via XIP, where the peripherals were initially configured by a bootloader? I am looking for the correct way for the application to inherit and use the state set up by the bootloader.
A method is needed to initialize XSPI2 and safely change its communication speed in an application running via XIP, without calling the full MX_XSPI2_Init() function.
I am also curious if the issues described in questions 1 and 2 could be resolved if the application is run using a "Load and Run" approach (where the bootloader copies the app from NOR flash to internal RAM, and then executes from RAM) instead of XIP.
Below is the structure of the main function in exercise_Appli that is currently causing the hang. Any advice would be greatly appreciated. Thank you.
Current structure of exercise_Appli/main.c:
int main(void)
{
MPU_Config();
HAL_Init();
// Clock configuration function, identical to the one in the bootloader
SystemClock_Config();
// Other peripheral initializations
MX_GPIO_Init();
// The system hangs the moment this function is called for the MRAM test.
MX_XSPI2_Init();
// The MRAM test function is never reached
MRAM_Run_All_Tests();
while (1);
}
Note: The mram_spi_test.c file is verified code that passed all tests when run from the bootloader.
2025-08-21 5:26 AM
Hello @YoungKwan
Could you try to de-initialize the XSPI2 before jumping to application?
2025-08-21 6:05 AM
Hello @Saket_Om
I added HAL_XSPI_DeInit(&hxspi2); before if (HAL_XSPI_Init(&hxspi2) != HAL_OK)
but problem occured at if (HAL_XSPIM_Config(&hxspi2, &sXspiManagerCfg, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) .
I called with &hxspi2 but HAL_XSPIM_Config try to config both hxsp1 and 2 than hang occured at
CLEAR_BIT(XSPI1->CR, XSPI_CR_EN).
Thanks.
static void MX_XSPI2_Init(void)
{
.....
hxspi2.Init.MemorySelect = HAL_XSPI_CSSEL_NCS1;
HAL_XSPI_DeInit(&hxspi2); // Added De-init
if (HAL_XSPI_Init(&hxspi2) != HAL_OK)
{
Error_Handler();
}
sXspiManagerCfg.nCSOverride = HAL_XSPI_CSSEL_OVR_NCS1;
sXspiManagerCfg.IOPort = HAL_XSPIM_IOPORT_1;
if (HAL_XSPIM_Config(&hxspi2, &sXspiManagerCfg, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
....
}
HAL_StatusTypeDef HAL_XSPIM_Config(XSPI_HandleTypeDef *const hxspi, XSPIM_CfgTypeDef *const pCfg, uint32_t Timeout)
{
/********** Disable both XSPI to configure XSPI IO Manager **********/
if ((XSPI1->CR & XSPI_CR_EN) != 0U)
{
CLEAR_BIT(XSPI1->CR, XSPI_CR_EN); // <-- Hang occured
xspi_enabled |= 0x1U;
}
if ((XSPI2->CR & XSPI_CR_EN) != 0U)
{
CLEAR_BIT(XSPI2->CR, XSPI_CR_EN);
xspi_enabled |= 0x2U;
}