Skip to main content
Associate
June 12, 2026
Question

Getting started image classification and standby mode

  • June 12, 2026
  • 2 replies
  • 84 views

I am developing an application on NUCLEO-N657X0-Q using Getting started image classification as base code. I need to add to the project the standby mode and right now when it enters standby mode, then it fails to resume correctly, i guess because part of the application is lost when system wakes up (retention is only 80 KB).

The total size of the application is much bigger then 80KB and I am not sure how to extend the actual retention memory in use adding the TCM retention memories.

Actually the application code is placed at 0x34000400.

Is there an example on how to place the application also in TCM?

 

I thought that another solution could be placing in retention at 0x34000000 the fsbl code and maybe in axisram2 the application, so that when the system wakes up after a standby it executes again fsbl and gets from external flash the application code.

I tried this last part changing the linker files, setting 0x34000000 for fsbl and 0x34100400 for application, then in fsbl code i set address 0x34100400 in 

#define EXTMEM_LRUN_DESTINATION_ADDRESS

to be used when fsbl must copy application code from flash and then jump to it.

This solution doesn’t work, maybe I am missing something or is not a solution at all.

 

Can you help me to find the right way to have standby mode working on a big application?

Thank you

2 replies

ST Technical Moderator
June 15, 2026

Hello ​@mfcheckup 

For STM32N6, the recommended standby strategy is not to retain the whole application, but to keep only a small wake-up program in the retained memory and let it reconfigure clocks/XSPI and then reload or jump to the main application after wake-up.

Please refer to the article STM32N6 low-power modes and Standby demo

In order to give better visibility on the answered topics, please click on 'Best answer' on the reply which solved your issue or answered your question. Saket_Om
mfcheckupAuthor
Associate
June 16, 2026

Thank you. 

I am trying to run the solution with a second bootloader using the example for NUCLEO-N657X0-Q PWR_STANDBY as test.

Currently, in external flash I place the FSBL at 0x70000000, the wake-up program at 0x70080000, and the application at 0x70100000.

In RAM instead:

  •  the FSBL is in AXISRAM2, the linker file configuration is: 

    MEMORY

    {

    ROM (xrw) : ORIGIN = 0x34180400, LENGTH = 255K

    RAM (xrw) : ORIGIN = 0x341C0000, LENGTH = 256K

    }

 

  • the wake-up program is at 0x34000000 with 80 KB reserved, the linker file configuration is: 

    MEMORY

    {

    RAM (xrw) : ORIGIN = 0x34000400, LENGTH = 80K

    }

 

  • the application is at 0x34020000, the linker file configuration is: 

    MEMORY

    {

    ROM (xrw) : ORIGIN = 0x34020400, LENGTH = 896K

    RAM (xrw) : ORIGIN = 0x34100000, LENGTH = 1024K

    }

 

I modified the original fsbl from the example by adding the copy of the wake-up program from flash into RAM, before copying the application and performing the jump, as follows:

 

BOOTStatus_TypeDef CopyApplication(void)
{
BOOTStatus_TypeDef retr = BOOT_OK;
uint8_t *source;
uint8_t *destination;
uint32_t MapAddress;
uint32_t img_size;


/*** 2^ BOOTLOADER ***/
destination = (uint8_t *)EXTMEM_2BOOT_DESTINATION_ADDRESS;

/* Get the map address of the source memory */
switch (EXTMEM_GetMapAddress(EXTMEM_LRUN_SOURCE, &MapAddress))
{
case EXTMEM_OK :
{
source = (uint8_t *)(MapAddress + EXTMEM_2BOOT_SOURCE_ADDRESS);
img_size = (EXTMEM_2BOOT_SOURCE_SIZE);
for (uint32_t index = 0; index < img_size; index++)
{
destination[index] = source[index];
}

break;
}

case EXTMEM_ERROR_NOTSUPPORTED:
{
img_size = (EXTMEM_2BOOT_SOURCE_SIZE);
if (EXTMEM_OK != EXTMEM_Read(EXTMEM_LRUN_SOURCE, EXTMEM_2BOOT_SOURCE_ADDRESS, destination, img_size))
{
retr = BOOT_ERROR_COPY;
}
break;
}

default :
{
retr = BOOT_ERROR_MAPPEDMODEFAIL;
break;
}
}
if(retr != BOOT_OK)
return retr;

/*** APPLI ***/

/* This case correspond to copy the SW from external memory into internal memory */
destination = (uint8_t *)EXTMEM_LRUN_DESTINATION_ADDRESS;

/* Get the map address of the source memory */
switch (EXTMEM_GetMapAddress(EXTMEM_LRUN_SOURCE, &MapAddress))
{
case EXTMEM_OK :
{
/* Manage the copy in mapped mode */
source = (uint8_t *)(MapAddress + EXTMEM_LRUN_SOURCE_ADDRESS);
img_size = BOOT_GetApplicationSize((uint32_t) source);
/* Copy from source to destination in mapped mode */
for (uint32_t index = 0; index < img_size; index++)
{
destination[index] = source[index];
}

break;
}

case EXTMEM_ERROR_NOTSUPPORTED:
{
img_size = BOOT_GetApplicationSize(EXTMEM_LRUN_SOURCE_ADDRESS);
/* Manage the copy using EXTMEM_Read */
if (EXTMEM_OK != EXTMEM_Read(EXTMEM_LRUN_SOURCE, EXTMEM_LRUN_SOURCE_ADDRESS, destination, img_size))
{
retr = BOOT_ERROR_COPY;
}

break;
}

default :
{
/* Returns an error */
retr = BOOT_ERROR_MAPPEDMODEFAIL;
break;
}
}
return retr;
}

with:

#define EXTMEM_HEADER_OFFSET 0x400

#define EXTMEM_LRUN_SOURCE EXTMEMORY_1
#define EXTMEM_LRUN_SOURCE_ADDRESS 0x00100000u
#define EXTMEM_LRUN_SOURCE_SIZE 0x00080000u
#define EXTMEM_LRUN_DESTINATION_INTERNAL 1
#define EXTMEM_LRUN_DESTINATION_ADDRESS 0x34020000u



#define EXTMEM_2BOOT_SOURCE_ADDRESS 0x00080000u
#define EXTMEM_2BOOT_SOURCE_SIZE 0x00080000u
#define EXTMEM_2BOOT_DESTINATION_INTERNAL 1
#define EXTMEM_2BOOT_DESTINATION_ADDRESS 0x34000000u

Inside Appli code, before entering standby I set: 

  /* enable memory retention top keep application in standby */
HAL_PWREx_EnableTCMRetention();
HAL_PWREx_EnableTCMFLXRetention();

/* clear any wake up flag before activating WKUP pin 3 */
HAL_PWR_ClearWakeupFlag(PWR_WAKEUP_FLAG_ALL);

SYSCFG->INITSVTORCR = 0x34000000;

/* Enter STANDBY mode */
HAL_PWR_EnterSTANDBYMode();

 

Doing cold boot, fsbl starts and executes appli, I can see the green led blinking and then it goes correctly in standby, but I can’t wake up correctly the system with this solution with the second bootloader. The wake up signal is correct and the original example works well.

So of course I am missing something, probably about vector table, reset handler, I’m not sure.

I can see that giving wake up signal the power consuption is increasing, but it’s all stuck somewhere, i think that the second bootloader is not really executed.

Below the wake-up program main:

int main(void)
{

/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

/* Enable the CPU Cache */

/* Enable I-Cache---------------------------------------------------------*/
SCB_EnableICache();

/* Enable D-Cache---------------------------------------------------------*/
SCB_EnableDCache();

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

/* USER CODE BEGIN Init */
BSP_LED_Init(LED_BLUE);
BSP_LED_On(LED_BLUE);
/* 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_XSPI2_Init();
// MX_BSEC_Init();
MX_EXTMEM_MANAGER_Init();
/* USER CODE BEGIN 2 */


/* USER CODE END 2 */

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

/* Launch the application */
if (BOOT_OK != BOOT_Application())
{
BSP_LED_On(LED_GREEN);
Error_Handler();
}
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{

/* USER CODE END WHILE */

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

It copies application in ram: 

BOOTStatus_TypeDef CopyApplication(void)
{
BOOTStatus_TypeDef retr = BOOT_OK;
uint8_t *source;
uint8_t *destination;
uint32_t MapAddress;
uint32_t img_size;


/*** APPLI ***/

/* This case correspond to copy the SW from external memory into internal memory */
destination = (uint8_t *)EXTMEM_LRUN_DESTINATION_ADDRESS;

/* Get the map address of the source memory */
switch (EXTMEM_GetMapAddress(EXTMEM_LRUN_SOURCE, &MapAddress))
{
case EXTMEM_OK :
{
/* Manage the copy in mapped mode */
source = (uint8_t *)(MapAddress + EXTMEM_LRUN_SOURCE_ADDRESS);
img_size = BOOT_GetApplicationSize((uint32_t) source);
/* Copy from source to destination in mapped mode */
for (uint32_t index = 0; index < img_size; index++)
{
destination[index] = source[index];
}

break;
}

case EXTMEM_ERROR_NOTSUPPORTED:
{
img_size = BOOT_GetApplicationSize(EXTMEM_LRUN_SOURCE_ADDRESS);
/* Manage the copy using EXTMEM_Read */
if (EXTMEM_OK != EXTMEM_Read(EXTMEM_LRUN_SOURCE, EXTMEM_LRUN_SOURCE_ADDRESS, destination, img_size))
{
retr = BOOT_ERROR_COPY;
}

break;
}

default :
{
/* Returns an error */
retr = BOOT_ERROR_MAPPEDMODEFAIL;
break;
}
}
return retr;
}

 

#define EXTMEM_HEADER_OFFSET 0x400

#define EXTMEM_LRUN_SOURCE EXTMEMORY_1
#define EXTMEM_LRUN_SOURCE_ADDRESS 0x00100000u
#define EXTMEM_LRUN_SOURCE_SIZE 0x00080000u
#define EXTMEM_LRUN_DESTINATION_INTERNAL 1
#define EXTMEM_LRUN_DESTINATION_ADDRESS 0x34020000u

 

Can you help me?

thank you