嵌入式工程一般至少分为两个部分,一个是bootloader,一个是主程序。主程序又可以分成多个工程。程序的工作地址不同,启动地址也不同。stm32默认的是从0x08000000开始启动程序,所以bootloader也存在于这个地址。启动地址和占位大小是可以通过keil软件设置的,设置后下载地址也会改变。程序的工作地址默认是在0x20000000,工作地址大小也可以设置,如果只有一个程序在运行,就可以不用更改工作地址。
bootloader也叫做IAP,主程序叫APP。bootloader的作用一般是用作更新APP,和初始化后设定跳转到对应的APP。如果APP不加更新功能的话也可以直接将APP写入到0x08000000这个地址里。更新程序就是数据包的接收、校验、写入,全部写入完成后检查APP的启动向量为合格就可以跳转到APP里。
//跳转到APP
void BootLoad_Jump(void)
{
/* Check Vector Table: Test if user code is programmed starting from address
"APPLICATION_ADDRESS" */
d_printfhex32((*(__IO uint32_t*)APPLICATION_ADDRESS));d_printf("\n");
if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000)
{
JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS +4);
d_printfhex32(JumpAddress);d_printf("\n");
HAL_Delay(100);
Jump_To_Application = (pFunction) JumpAddress;
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
Jump_To_Application();
}
}
//跳回IAP
void JumpToIAP(void)
{
INT32U IapSpInitVal;
INT32U IapJumpAddr;
void (*pIapFun)(void);
RCC_DeInit();
NVIC_DeInit();
__disable_irq(); //关中断()
// APP如跳转前关中断,跳转到IAP后,IAP初始化后要打开中断
IapSpInitVal = *(INT32U *)IAP_ADDR;
IapJumpAddr = *(INT32U *)(IAP_ADDR + 4);
__set_CONTROL(0);
//进入用户级线程模式 进入软中断后才可以回到特权级线程模式
//APP如使用系统如ucos必须要有此过程否则跳到IAP后,无法再次跳到APP
__set_MSP (IapSpInitVal);
pIapFun = (void (*)(void))IapJumpAddr;
(*pIapFun) ();
}
跳转都是先校验程序启动向量,关外部、内部中断,设置用户工作线程,跳转。
//跳转,两边都可以用,改一下地址(address_user_app)就可以了
void Jump_To_App(uint32_t address_user_app)
{
uint32_t JumpAddress;
JumpAddress = *(__IO uint32_t*) (address_user_app + 4);
/* Jump to user application */
Jump_To_Application = (pFunction) JumpAddress;//设置启动向量地址
/* Initialize user application's Stack Pointer*/
__set_MSP(*(__IO uint32_t*) address_user_app);//设置启动地址
//指针函数,Jump_To_Application就是指向程序启动地址的一个指针函数
Jump_To_Application();
}
//获取CPU的唯一序列号
static u32 CpuID[3];
void GetLockCode(void)
{
//获取CPU唯一ID
CpuID[0]=*(vu32*)(0x1ffff7e8);(stm32f1系列)
CpuID[1]=*(vu32*)(0x1ffff7ec);
CpuID[2]=*(vu32*)(0x1ffff7f0);
}
//内部中断初始化
void driver_nvic_initial(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x08000000); //设置中断起始地址,该地址为当前程序的起始地址,设置错误导致程序无法启动
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3); //中断为三级
}
下面是查资料时找到的一些很好的博客,借鉴之
IAR介绍
IAR跳转
IAR介绍
IAR详细介绍
IAR介绍
IAR介绍
IAR的keil设置
IAR介绍中断向量重定向
IAR介绍
IAR和APP互跳
IAR和APP互跳
系统时钟设置
系统时钟设置