美文网首页
bootloader的简单说明和跳转功能的实现

bootloader的简单说明和跳转功能的实现

作者: 赋闲 | 来源:发表于2017-12-20 22:06 被阅读0次

    嵌入式工程一般至少分为两个部分,一个是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互跳
    系统时钟设置
    系统时钟设置

    相关文章

      网友评论

          本文标题:bootloader的简单说明和跳转功能的实现

          本文链接:https://www.haomeiwen.com/subject/tgpnwxtx.html