OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 2008|回复: 8

请教一下bootloader程序跳转的问题

[复制链接]
回帖奖励 30 金钱 回复本帖可获得 5 金钱奖励! 每人限 1 次

74

主题

182

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
279
金钱
279
注册时间
2021-2-5
在线时间
133 小时
发表于 2023-9-11 11:59:12 | 显示全部楼层 |阅读模式
void JumptoAPP()
{
        if(((*(__IO uint32_t*)APP_FLASHADDR_S) & 0x2FFE0000 ) == 0x20000000)
        {
                log_i("T-BOX Loading App.");
                log_i("Jump Address:0x%08X", ((*(uint32_t*)APP_FLASHADDR_S) & 0x2FFE0000 ));
                vTaskDelay(10);
               
                __set_PRIMASK(1);        /*关闭总中断*/
                vTaskDelay(10);
               
                Jump = (fun)*(uint32_t*)(APP_FLASHADDR_S + 4);
                MSR_MSP(*(__IO uint32_t*) APP_FLASHADDR_S);
                Jump();        /*跳转App*/
        }
        {
                log_i("T-BOX Loading App ERROR.");
                vTaskDelay(50);
                log_i("Jump Address:0x%08X", ((*(__IO uint32_t*)APP_FLASHADDR_S) & 0x2FFE0000 ));
                vTaskDelay(50);
                HAL_NVIC_SystemReset();
        }
}

如上述跳转代码,执行跳转之后,app代码不运行,然后触发看门狗重启,这种情况是出现在设备升级完成之后的偶发现象,这里有个最大的疑问就是,能获取到栈顶地址说明什么,能不能说明升级之后,程序是完整写入flash中的
IAP和APP的外设都是一样的,这里也关了中断,中断向量表也偏移了,就是升级后就出问题了,还是偶发性的

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

2

主题

446

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4133
金钱
4133
注册时间
2018-5-14
在线时间
902 小时
发表于 2023-9-11 14:52:32 | 显示全部楼层

回帖奖励 +5 金钱

能获取栈顶地址不能说明什么,只能说APP存在合法性,如果更新后APP的将栈顶设置在SDRAM就会导致判断错误,所以不推荐判断栈顶。一般都是将加密的APP解密到SDRAM再从SDRAM运行程序。解密过程可以做自定义的合法性判断
回复 支持 反对

使用道具 举报

0

主题

451

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3316
金钱
3316
注册时间
2016-3-19
在线时间
815 小时
发表于 2023-9-11 16:19:18 | 显示全部楼层

回帖奖励 +5 金钱

获取栈顶地址不能说明程序的完整性

楼上所述  若程序中没有外置的SDRAM 怎么办?
Nothing is impossible
回复 支持 反对

使用道具 举报

70

主题

6698

帖子

0

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
12692
金钱
12692
注册时间
2012-11-26
在线时间
3711 小时
发表于 2023-9-11 16:23:14 | 显示全部楼层

回帖奖励 +5 金钱

是不是写入flash的过程中,写的有问题

写完有校验下吗?
学无止境
回复 支持 反对

使用道具 举报

74

主题

182

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
279
金钱
279
注册时间
2021-2-5
在线时间
133 小时
 楼主| 发表于 2023-9-11 16:56:05 | 显示全部楼层
jermy_z 发表于 2023-9-11 16:23
是不是写入flash的过程中,写的有问题

写完有校验下吗?

我用的是BCC校验,升级前上位机会给一个校验结果存储器来,然后底层再校验得出一个校验结果,对比校验结果,不对就会调用备份程序,我把代码贴出来
HAL_StatusTypeDef UpgradeMain(uint32_t UpgradeSize,uint8_t Code)
{
        uint8_t CheckCode = 0x00;
        char DataBuff[32];
        uint8_t ContinueBuff[20] = "continue";
        uint32_t FlashFrameNum,FlashStarAddr;
        uint16_t WriteLength;
        uint8_t *FlashBuff = pvPortMalloc(FLASH_BUFF_LENGTH);
        uint8_t Result = HAL_OK;
        UpgradeTypdef Upgrade;
       
        SemaphoreHandle_t UpgradexSemaphore;
        UpgradexSemaphore = xSemaphoreCreateBinary();       
        xSemaphoreGive(UpgradexSemaphore);
       
        memset(FlashBuff,0,FLASH_BUFF_LENGTH);
       
        /* 计算更新帧数量 */
        FlashFrameNum  = UpgradeSize % FLASH_WRITE_LENGTH ? (UpgradeSize / FLASH_WRITE_LENGTH) + 1 : UpgradeSize / FLASH_WRITE_LENGTH ;
        FlashStarAddr = APP_FLASHADDR_S;
        Upgrade.FrameLen = FlashFrameNum;   
        Upgrade.Finish = 0;                                 
       
        /* 非常重要 */
        memset(DataBuff,0,32);
        sprintf(DataBuff,"0;1;0");   /* 置位升级完成标识,避免升级中断无法恢复 */
        FlashErase(CORE_DATAADDR_S4,0x08061FFF);
        FlashWrite(CORE_DATAADDR_S4,(uint8_t *)DataBuff,strlen((char *)DataBuff));
       
       
        if(FlashErase(APP_FLASHADDR_S, APP_FLASHADDR_E) != HAL_OK)
                Result = 1;
       
        while(FlashFrameNum && !Result)
        {
               
                sprintf((char *)ContinueBuff,"continue:%0.0f%%*",((Upgrade.Finish)/(Upgrade.FrameLen))*100);
               
                /* 升级末尾进度作100%处理 */
                if(FlashFrameNum == 1)
                {
                        sprintf((char *)ContinueBuff,"continue:%0.0f%%*",100.0f);
                }
               
                if(USART3_Transmit(ContinueBuff, sizeof(ContinueBuff), 500) != HAL_OK)
                        Result = 2;
               
                xSemaphoreTake(UpgradexSemaphore,portMAX_DELAY);
               
                 /* 文件未传输提示错误码 */
                memset(DataBuff,0,32);
                sprintf(DataBuff,"0;1;30");  
                FlashErase(CORE_DATAADDR_S4,0x08061FFF);
                FlashWrite(CORE_DATAADDR_S4,(uint8_t *)DataBuff,strlen((char *)DataBuff));
               
                USART3_Receive(FlashBuff, portMAX_DELAY);
               
                memset(DataBuff,0,32);
                sprintf(DataBuff,"0;1;0");  
                FlashErase(CORE_DATAADDR_S4,0x08061FFF);
                FlashWrite(CORE_DATAADDR_S4,(uint8_t *)DataBuff,strlen((char *)DataBuff));
               
                if(FlashFrameNum > 1)
                {
                        WriteLength = FLASH_WRITE_LENGTH;
                       
                        if(FlashWrite(FlashStarAddr, FlashBuff, WriteLength) == HAL_OK)
                                FlashStarAddr += FLASH_WRITE_LENGTH;
                        else
                                Result = 4;
                }
                else
                {
                        WriteLength = UpgradeSize % FLASH_WRITE_LENGTH ? UpgradeSize % FLASH_WRITE_LENGTH : FLASH_WRITE_LENGTH;
                        FlashWrite(FlashStarAddr, FlashBuff, WriteLength);
                }       
               
                CheckCode = BccCheck(CheckCode, FlashBuff, WriteLength);
               
                FlashFrameNum--;
                Upgrade.Finish++;
               
                xSemaphoreGive(UpgradexSemaphore);
       
                memset(FlashBuff,0,FLASH_BUFF_LENGTH);               
               
                /* 规避传输过程中手机掉电 */
                IWDG_FeedDog();  
        }
       
        if(Code != CheckCode)
        {
                log_i("CheckError:%02X-%02X",Code,CheckCode);
                Result = 6;
        }
        vPortFree(FlashBuff);
       
        if(Result != 0)
        {
                log_i("Error Code(%d)",Result);
                return HAL_ERROR;
        }
        return HAL_OK;
}
回复 支持 反对

使用道具 举报

74

主题

182

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
279
金钱
279
注册时间
2021-2-5
在线时间
133 小时
 楼主| 发表于 2023-9-11 17:03:55 | 显示全部楼层
15284083060 发表于 2023-9-11 16:56
我用的是BCC校验,升级前上位机会给一个校验结果存储器来,然后底层再校验得出一个校验结果,对比校验结 ...

我们是通过蓝牙传输进行升级的,出问题的设备两个现象是:1、跳转到app之后代码不运行,看门狗重启  2、写到CORE_DATAADDR_S4位置的升级状态标识位被擦除了,读取不到(这里存储的状态标识位是把flash模拟eeprom进行存储的),发送这个continue进度指令就会把升级文件发下来,不知道这里触发串口中断会不会对这个标志位存储有影响
回复 支持 反对

使用道具 举报

2

主题

446

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4133
金钱
4133
注册时间
2018-5-14
在线时间
902 小时
发表于 2023-9-12 08:53:48 | 显示全部楼层
15284083060 发表于 2023-9-11 17:03
我们是通过蓝牙传输进行升级的,出问题的设备两个现象是:1、跳转到app之后代码不运行,看门狗重启  2、 ...

先简单做一个helloword打印的程序,并同时打印main的入口地址,看看有没有正常跳转,如果跳转了,可能写个定时器中断的Demo,看看定时器中断是否能打印输出。第一个可以判断跳转代码是否正确,第二个可以判断中断向量是否正确
回复 支持 反对

使用道具 举报

9

主题

796

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
2038
金钱
2038
注册时间
2017-8-2
在线时间
522 小时
发表于 2023-9-14 10:27:33 | 显示全部楼层

回帖奖励 +5 金钱

建议更新程序的时候做个校验吧,每次更新完程序看一下有没有传错的情况
猪猪熊呢?
回复 支持 反对

使用道具 举报

74

主题

182

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
279
金钱
279
注册时间
2021-2-5
在线时间
133 小时
 楼主| 发表于 2023-9-26 16:32:20 | 显示全部楼层
这个问题,多次模拟定位出问题,其实这个问题是代码逻辑问题,而且这个问题还是小概率问题,所以之前一直没找到问题,自己测试又没出问题,最近终于把这这个问题复现了,其实就是在接收升级文件的时候上面和下面两句代码有问题,其实也不能说有问题,只是说加上客户断电这个因素,就会出现问题,客户在升级过程中,把设备断电了,这个点刚好撞在标志位擦除完的点上,APP也没升级完成,标志位还被擦出了,上电之后就不能去调用备份,设备就这么死了,还好不是什么严重漏洞,这种都还可以规避一下,还是得谨慎
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-23 23:38

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表