#define RAM_START_ADDR (0x20000000)
#define VECTOR_SIZE (0xb0)//中断向量表的大小
typedef void (*pFunction)(void);
/**
* @brief Load and run user system
* @note
* @rmtoll
* @param None
* @retval None
*/
void LoadUserSystem(u32 address)
{
pFunction LoadAddress;
u32 JumpAddress;
if (((*(__IO uint32_t*)address) & 0x2FFE0000 ) == 0x20000000)
{
//关总中断
__disable_irq();
//复位地址
JumpAddress = *(volatile u32*)(address + 4);
LoadAddress = (pFunction)JumpAddress;
memcpy((void *)RAM_START_ADDR, (void *)address, VECTOR_SIZE);
LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_SYSCFG);
LL_SYSCFG_SetRemapMemory(LL_SYSCFG_REMAP_SRAM);
//将把用户代码的栈顶地址设为栈顶指针
__set_MSP(*(__IO uint32_t*)address);
//程序跳转
LoadAddress();
}
}
可以将C与汇编结合使用,将跳转函数转为汇编,其中C的代码部分
/**
* @brief Jump to user program
* @note
* @rmtoll
* @param None
* @retval None
*/
int SystemJump2Where(uint32_t address)
{
/* Test if user code is programmed starting from address "APPLICATION_ADDRESS" */
if (((*(__IO uint32_t*)address) & 0x2FFE0000 ) == 0x20000000)
{
extern void vJumpToWhere(int);
vJumpToWhere(address);
}
/*跳转失败,返回-1*/
return -1;
}
1.在MDK中,汇编
THUMB
REQUIRE8
PRESERVE8
AREA ||i.vJumpToWhere||, CODE, READONLY, ALIGN=4
vJumpToWhere PROC
cpsid i ;Disable interrupt
ldr r1, [r0] ;Get MSP location
ldr r2, [r0, #4] ;Get resethanler address
movs r0, #0
msr CONTROL, r0 ;Use MSP
msr MSP, r1
bx r2 ;Jump
ENDP
EXPORT vJumpToWhere [CODE]
END
2.在IAR中,汇编
RSEG CODE:CODE(2)
thumb
PUBLIC vJumpToWhere
/*-----------------------------------------------------------*/
/**
* @brief Jump to program start address and excute
* @param Program start address
* @retval None
*/
vJumpToWhere
cpsid i //Disable interrupt
ldr r1, [r0] //Get MSP location
ldr r2, [r0, #4] //Get resethanler address
movs r0, #0
msr CONTROL, r0 //Use MSP
msr MSP, r1
bx r2 //Jump
END
3.在STM32CubeIDE中(escplise),这部分代码还待优化
.global vJumpToWhere // 把vJumpToWhere链接属性改为外部,这样其他文件就可以看见了
.thumb
.section .text.vJumpToWhere //相关属性
.type vJumpToWhere, %function
.size vJumpToWhere, .-vJumpToWhere
.align 4
/*-----------------------------------------------------------*/
/**
* @brief Jump to program start address and excute
* @param Program start address
* @retval None
*/
vJumpToWhere:
cpsid i //Disable interrupt
ldr r1, [r0] //Get MSP location
ldr r2, [r0, #4] //Get resethanler address
movs r0, #0
msr CONTROL, r0 //Use MSP
msr MSP, r1
bx r2 //Jump