IAP Jump to application not working
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:
- The example project for IAP_Main (in STM32769I_EVAL)
- 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.
