Skip to main content
Graduate
January 14, 2025
Question

How to Modify the Address of Stack

  • January 14, 2025
  • 3 replies
  • 1171 views

Hi, 

My application has a bootloader, recently, I allocated a large block of memory on top of SRAM to protect the data from system resets, this causes the highest address of user stack changes, when this highest addresses of user stack are different in Bootloader and App, the app does not work.

I assume that if I could modify the highest address of the user stack in the main() of App, it may make it work, but I don't know how to do this.

The highest address of the user stack of bootloader and App defined in .ld files are as below:

Bootloader:

_estack = ORIGIN(RAM) + LENGTH(RAM) - 256; /* end of "RAM" Ram type memory */

App:

_estack = ORIGIN(RAM) + LENGTH(RAM) - 14592; /* end of "RAM" Ram type memory */

 

The memory definitions for the both are:

bootloader:

MEMORY

{

RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 48K

FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 256K

}

App:

MEMORY

{

RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 48K

FLASH (rx) : ORIGIN = 0x08014000, LENGTH = 176K

}

Regards

Chao

 

    This topic has been closed for replies.

    3 replies

    Super User
    January 14, 2025

    Look at the mapfile to find out, whether the RAM used by your variables does not overlap with the stack you've allocated.

    JW

    Graduate
    January 14, 2025

    I belive the simplest solution is to reduce the size of RAM in .LD files in the same way for both the app and the bootloader, then define the separate XRAM memory area for your precious data at the top of physical RAM.

    ChaoAuthor
    Graduate
    January 14, 2025

    Hi @gbm ,

    Thanks!

    Yes, indeed. I tested this, it works. But the problem is, if I choose to do it this way, we have to upgrade the bootloader for all products already delivered to customers. 

    I am looking for a way to make it work without a need to upgrade the bootloader.

    A few minutes ago, after I modified the bootloader to use the same highest address of the user stack,  I printed out the values of the first address of my App (which is 0x08014000), it's 0x20008700, this is the highest address of the user stack being used in the Bootloader and App, 0x20008700 = _estack = ORIGIN(RAM) + LENGTH(RAM) - 14592. Then I did following test:

    1. change the _estack in Bootloader back to _estack = ORIGIN(RAM) + LENGTH(RAM) - 256

    2. in main() of App,add the following code to modify the value of the first address of the App:

    int main(void)
    {
     /* USER CODE BEGIN 1 */
    #ifdef	BOOTLOADER_PRESENT
    	uint32_t* sp = (uint32_t*)(APP_ADDR);
    #else
    	uint32_t* sp = (uint32_t*)0;
    #endif
     sp[0] = MAX_STACK_POINTER;
     /* USER CODE END 1 */

    APP_ADDR = 0x08014000 (the first address of the App)

    MAX_STACK_POINTER = 0x20008700, this is the value read out when the App was running correctly.

    Unfortunately, it didn't work!

    Any more idea?

     

    Super User
    January 14, 2025

    One more thing: how exactly do you transfer execution from bootloader to application?

    JW

    ChaoAuthor
    Graduate
    January 14, 2025

    Hi @waclawek.jan ,

    Thanks!

    The Bootloader code is mainly contributed by @gbm :

    struct app_vectable_
    {
     uint32_t Initial_SP;
     void (*Reset_Handler)(void);
    };
    
    #define APPVTAB	((struct app_vectable_ *)APP_ADDR)
    #define APP_ADDR 0x08014000
    
    void Bootloader::JumpToApp()
    {
    	// Confirm that stack and vector table is not empty in APP
    	uint *sp = (uint*)(APP_ADDR);
    
    	if ((sp[0] != 0xffffffff) && (sp[1] != 0xffffffff))
    	{
    		// undo some of our initialization in preparation to the jump to the application code
    
    		/* Set the clock to the default state */
    		HAL_RCC_DeInit();
    
    		/* Disable all interrupts */
    		__disable_irq();
    
    		/* Disable Systick timer */
    		SysTick->CTRL = 0;
    
    		/* Clear Interrupt Enable Registers & Interrupt Pending Registers */
    	 for (byte i = 0; i < sizeof(NVIC->ICER) / sizeof(NVIC->ICER[0]); i++)
    	 {
    	 NVIC->ICER[i] = 0xFFFFFFFF;
    	 NVIC->ICPR[i] = 0xFFFFFFFF;
    	 }
    
    		// set the vector table address to the application vector table
    		SCB->VTOR = APP_ADDR;
    
    		// Set the stack pointer
    		__set_MSP(APPVTAB->Initial_SP);
    
    		__DSB(); // Ensure the VTOR and SP operations are complete
    		__ISB(); // Flush the pipeline because of SP change
    
    		/* Re-enable all interrupts */
    		__enable_irq();
    
    		// and now jump to the application
    		APPVTAB->Reset_Handler();
    		while (1) { }
    	}
    }