cancel
Showing results for 
Search instead for 
Did you mean: 

IAP Jump to application not working

Bob_Walton
Associate II

I am using STM32Cube Version: 1.15.0 Build: 20695_20240315_1429 (UTC) and on an STM32F767ZGTx with FW_F7 V1.17.1

I have a running and tested application for which I am now including FW Update from SDCard.

I got two examples on which to base the new code:

  1. The example project for IAP_Main (in STM32769I_EVAL)
  2. en.x-cube-iap-sd

The IAP occupies sectors 0 & 1 from 0x0800 0000 - 0x0800 FFFF

Linker:

 

 

/* Entry Point */
ENTRY(Reset_Handler)

/* Highest address of the user mode stack */
_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of "RAM" Ram type memory */

_Min_Heap_Size = 0x200; /* required amount of heap */
_Min_Stack_Size = 0x400; /* required amount of stack */

/* Memories definition */
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 512K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 64K
}

 

The application is from 0x0801 0000 to 0x080F FFFF

Linker:

 

 

/* Entry Point */
ENTRY(Reset_Handler)
/* Highest address of the user mode stack */
_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of "RAM" Ram type memory */

_Min_Heap_Size = 0x200; /* required amount of heap */
_Min_Stack_Size = 0x400; /* required amount of stack */

/* Memories definition */
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 512K
FLASH (rx) : ORIGIN = 0x8010000, LENGTH = 960K
}

 

 

and system_stm32f7xx.c set to USER_VECT_TAB_ADDRESS producing:

 

 

#if defined(USER_VECT_TAB_ADDRESS)
  /*!< Uncomment the following line if you need to relocate your vector Table
  in Sram else user remap will be done in Flash. */
  /* #define VECT_TAB_SRAM */
  #if defined(VECT_TAB_SRAM)
    #define VECT_TAB_BASE_ADDRESS RAMDTCM_BASE /*!< Vector Table base address field.
    This value must be a multiple of 0x200. */
    #define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table base offset field.
    This value must be a multiple of 0x200. */
  #else
    #define VECT_TAB_BASE_ADDRESS FLASH_BASE 
    /*!< Vector Table base address field. This value must be a multiple of 0x200. */
    #define VECT_TAB_OFFSET 0x08010000U /*!< Vector Table base offset field. This value 
    must be a multiple of 0x200. */
  #endif /* VECT_TAB_SRAM */
#endif /* USER_VECT_TAB_ADDRESS */

 

*******************************************************************************

Both examples use a similar method to launch the application

/* Test if user code is programmed starting from address "APPLICATION_ADDRESS" */

 

if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20080000)
{
  /* Jump to user application */
  jumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
  jumpToApplication = (pFunction) jumpAddress;
  /* Initialize user application's Stack Pointer */
  __set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
  jumpToApplication();
}

 

where APPLICATION_ADDRESS = 0x08010000

This appears to make the jump but the application does not run.

*******************************************************************************

I have read all the post I could find and ended up with:

/* Test if user code is programmed starting from address "APPLICATION_ADDRESS" */

 

if(((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20080000)
{
  __disable_irq();
  HAL_PWR_DeInit();
  HAL_RCC_DeInit();
  HAL_DMA_DeInit(&hdma_usart6_rx);
  HAL_SPI_DeInit(&hspi4);
  SysTick->CTRL = 0;
  SysTick->LOAD = 0;
  SysTick->VAL = 0;
  SCB->ICSR = 0x00000000; // reset value;
  SCB->SCR = 0;
  SCB->CCR = 0x00000200; // reset value
  SCB->SHPR[0] = 0;
  SCB->SHCSR = 0;
  SCB->CFSR = (SCB_CFSR_DIVBYZERO_Msk | SCB_CFSR_UNALIGNED_Msk | SCB_CFSR_UNDEFINSTR_Msk 
  |SCB_CFSR_NOCP_Msk | SCB_CFSR_INVPC_Msk | SCB_CFSR_INVSTATE_Msk);
  SCB->HFSR = (SCB_HFSR_DEBUGEVT_Msk | SCB_HFSR_FORCED_Msk | SCB_HFSR_VECTTBL_Msk);
  SCB->VTOR = APPLICATION_ADDRESS;

  /* Get the application stack pointer (First entry in the application vector table) */
  jumpAddress = *(__IO uint32_t*)(APPLICATION_ADDRESS + 4);

  /* Get the application entry point (Second entry in the application vector table) */
  jumpToApplication = (pFunction)jumpAddress;

  /* Set the application stack pointer */
  __set_MSP(*(__IO uint32_t*)APPLICATION_ADDRESS);

  /* Start the application */
  jumpToApplication();
  while(1);
}

 

With still no joy.

*******************************************************************************

I also tried from ARM: How to Write a Bootloader

/* Test if user code is programmed starting from address "APPLICATION_ADDRESS" */

 

 

if(((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20080000)
{
  BootJump((__IO uint32_t*)APPLICATION_ADDRESS); // boot user application
}

void BootJump(uint32_t *address)
{
  // disable interrupts
  NVIC->ICER[ 0 ] = 0xFFFFFFFF ;
  NVIC->ICER[ 1 ] = 0xFFFFFFFF ;
  NVIC->ICER[ 2 ] = 0xFFFFFFFF ;
  NVIC->ICER[ 3 ] = 0xFFFFFFFF ;
  NVIC->ICER[ 4 ] = 0xFFFFFFFF ;
  NVIC->ICER[ 5 ] = 0xFFFFFFFF ;
  NVIC->ICER[ 6 ] = 0xFFFFFFFF ;
  NVIC->ICER[ 7 ] = 0xFFFFFFFF ;

  // clear pending interrupts
  NVIC->ICPR[ 0 ] = 0xFFFFFFFF ;
  NVIC->ICPR[ 1 ] = 0xFFFFFFFF ;
  NVIC->ICPR[ 2 ] = 0xFFFFFFFF ;
  NVIC->ICPR[ 3 ] = 0xFFFFFFFF ;
  NVIC->ICPR[ 4 ] = 0xFFFFFFFF ;
  NVIC->ICPR[ 5 ] = 0xFFFFFFFF ;
  NVIC->ICPR[ 6 ] = 0xFFFFFFFF ;
  NVIC->ICPR[ 7 ] = 0xFFFFFFFF ;

  // disable SysTick and clear its exception pending bit
  SysTick->CTRL = 0 ;
  SCB->ICSR |= SCB_ICSR_PENDSTCLR_Msk ;

  // disable individual fault handlers
  SCB->SHCSR &= ~(SCB_SHCSR_USGFAULTENA_Msk | \
  SCB_SHCSR_BUSFAULTENA_Msk | \
  SCB_SHCSR_MEMFAULTENA_Msk) ;

  /* Activate the MSP, if the core is found to currently run with the PSP.
  As the compiler might still use the stack, the PSP needs to be copied to the MSP 
  before this */

  if(CONTROL_SPSEL_Msk & __get_CONTROL()) // MSP is not active
  {
    __set_MSP(__get_PSP()) ;
    __set_CONTROL(__get_CONTROL() & ~CONTROL_SPSEL_Msk) ;
  }
  
  // load the vector table address of the user application into SCB->VTOR register
  SCB->VTOR = (uint32_t)address ;

  /* set the MSP to the value found in the user application vector table and then load 
  the PC with the reset vector value of the user application.
  This can't be done in C, as it is always possible, that the compiler uses the current 
  SP. But that would be gone after setting the new MSP.
  So, a call to a small assembler function is done */
  bootJumpASM(address[0], address[1]);

  // while(1);
}

__attribute__((naked, noreturn)) void bootJumpASM(uint32_t SP, uint32_t RH)
{
  __asm("MSR MSP,r0");
  __asm("BX r1");
}

 

*******************************************************************************

Sorry for the long post but I have run out of ideas, it seems I jump but do not

run the application.

I am obviously missing something but cannot see it.

Any help would be appreciated.

1 ACCEPTED SOLUTION

Accepted Solutions
Bob_Walton
Associate II

After a bit of head scratching I finally got STM32Cube and STLink to share the same debug session and therefore was able to debug my application code after the jump.

I went back to the original example code which showed I was jumping correctly to the application but I was getting locked up in a HAL DMA init loop.

I added the HAL_DeInit() before the jump and now everything is working after the jump.

	if(((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000) == 0x20080000)																								// test if user code is programmed
	{
		HAL_DeInit();																																																				// de-init hal due to dma usage
		jumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);																													// jump to user application
		jumpToApplication = (pFunction) jumpAddress;																																				// jump function
		__set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);																																		// initialize user application's stack pointer
		jumpToApplication();																																																// jump to main application
	}

 Thank you all for the feedback. 😁

View solution in original post

5 REPLIES 5
Pavel A.
Evangelist III

With still no joy.

 it seems I jump but do not

Could you maybe come with more technical description? Does the processor actually jump to your code and execute instructions? Does it spin in some exception handler?

Use the </> code pasting tool with walls of code, you can edit your post via the (V) icon and drop down menu at the top right of the post.

Use your debugger, and step the code, understand what IS happening, and WHY that's causing it to NOT WORK..

Disabling interrupts will make them not work.

Perhaps check that the Initial SP points to Internal SRAM, not a specific address

if(((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FC00000 ) == 0x20000000)

What value does YOUR build use?

Can you follow the control transfer into your own Reset_Handler on the far side? How far does that go?

Use a serial port and diagnostic output to see values, of SP/PC, and follow code flow. Do it on both sides, ideally early enough that you can observe what's happening.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

>> where APPLICATION_ADDRESS = 0x08000000

How's that going to work if you put it at 0x08010000 ?

The loaders going to live at 0x08000000, and would cyclically enter.

Perhaps check a TRM for the Cortex-M7, or ST's "Programming Manual", to understand the vector table.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Sorry typo APPLICATION_ADDRESS = 0x08010000

I have corrected and used <V> as requested.

I will investigate further given the comments so far and post the outcomes.

Thankyou everyone.

Bob_Walton
Associate II

After a bit of head scratching I finally got STM32Cube and STLink to share the same debug session and therefore was able to debug my application code after the jump.

I went back to the original example code which showed I was jumping correctly to the application but I was getting locked up in a HAL DMA init loop.

I added the HAL_DeInit() before the jump and now everything is working after the jump.

	if(((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000) == 0x20080000)																								// test if user code is programmed
	{
		HAL_DeInit();																																																				// de-init hal due to dma usage
		jumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);																													// jump to user application
		jumpToApplication = (pFunction) jumpAddress;																																				// jump function
		__set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);																																		// initialize user application's stack pointer
		jumpToApplication();																																																// jump to main application
	}

 Thank you all for the feedback. 😁