cancel
Showing results for 
Search instead for 
Did you mean: 

How to Modify the Address of Stack

Chao
Senior

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

 

6 REPLIES 6

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

JW

gbm
Lead III

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.

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice

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

JW

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?

 

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) { }
	}
}

 

 

My previous test was invalid.

I checked the device memory in CubeProgrammer, the value of the first address of App was already set by the linker to 0x08008700 in the bin file according to the settings in .LD file.

Chao_0-1736874734765.png