IAP_09_ISP程序无法成功跳转到iap
我使用STC8H1K17,升级流程和逻辑大部分是参照官方例程,目前是:1、上位机发送bin文件
2、如果全部接收完成并且经过了校验(目前是校验bin的前16字节),设置DfuFlag为DFU_TAG,然后软件复位
3、软件复位后进行DFU Check
match的作用
我在app的代码中,会对Flash的固定位置写入固定数据,如果mcu已经加载了app,则去读取Flash中的数据,如果匹配,则表示此mcu已经加载过app了,可以直接跳转app
因为现在刚从isp加载了app,还未进入app,所以判断DfuFlag是否为DFU_TAG,如果是,则表示是刚接收完bin文件,经过软复位跳转过来的
从打印信息可以看到,DfuFlag等于DFU_TAG,且else if的判断条件也成立。
现在的问题是,既然进入了else if,为什么没有跳转到app,后面还执行了printf("Stay in·ISP mode\r\n"); ?
而且可以看到,我的bin文件前3个字节是:
已确认首字节0x02(LMP),再确认目标地址(0x1F6F)确实落在APP已写入且未空洞的区域内。
我的isp工程未使用任何中断,且我尝试过在跳转前关闭中断,复位栈指针,关闭看门狗。
我STC8H1K17 app 在keil的设置,大家看看是不是哪里设置错了:
附件:
根据你提供的信息和代码逻辑,我们来逐步分析你当前遇到的问题:IAP09ISP程序无法成功跳转到App。你的整体设计逻辑是合理的,但存在几个可能影响跳转成功的关键点。
一、问题现象总结
DfuFlag 已正确设置为 DFUTAG,复位后也正确识别;
逻辑判断进入了 else if (DfuFlag == DFUTAG) 分支;
但没有执行跳转 App 的操作,而是继续执行了 printf("Stay in·ISP mode\r\n");;
bin 文件前三个字节为 0x02, 0x6F, 0x1F,即目标地址为 0x1F6F;
Keil 设置的 App 起始地址为 0x1F00,与跳转地址一致;
硬件平台为 STC8H1K17。
二、跳转失败的可能原因分析
1. 函数未正确跳转 App
你代码中使用的是:
c
((void()(void))APPADDR)();
这是一种常见的跳转方式,但有几个前提条件必须满足:
✅ 条件一:App 地址是有效的代码入口地址
你提供的 bin 文件首字节为 0x02(LMP),表示这是一个标准的 STC bin 文件格式;
第 2、3 字节是目标地址 0x1F6F,应为跳转地址;
需要确认该地址是否是 App 的合法入口地址(即 ResetHandler 的地址);
建议查看 App 的反汇编文件或 .map 文件确认入口地址是否为 0x1F6F;
✅ 条件二:App 区域已完整写入且未被破坏
你提到已经接收并校验 bin 文件,但需确认是否完整写入 Flash;
特别注意:STC 单片机 Flash 写入前必须先擦除;
若写入时未正确擦除或写入失败,可能导致跳转地址处数据无效;
✅ 条件三:跳转前关闭所有外设中断及系统中断
跳转前应关闭全局中断、定时器、串口等外设中断;
否则在跳转后中断可能触发,导致行为异常;
示例代码建议:
c
EA = 0; // 关闭全局中断
TM0C &= ~0x40; // 关闭定时器0中断
✅ 条件四:跳转函数执行后不应有任何后续代码
你当前的代码结构如下:
c
else if (DfuFlag == DFUTAG)
{
((void()(void))APPADDR)();
}
printf("Stay in·ISP mode\r\n");
问题在于:C 编译器并不知道 ((void()(void))APPADDR)(); 是一个跳转函数,不会自动优化后续代码;
即使跳转成功,编译器仍然会生成 printf 的代码,可能导致跳转后执行异常;
建议使用 asm("ljmp 0x1F6F") 或 asm("ljmp APPADDR") 来强制跳转,避免编译器优化干扰。
2. App 地址设置错误或偏移问题
你 Keil 设置的 App 起始地址为 0x1F00,但跳转地址为 0x1F6F;
需要确认 0x1F6F 是否确实是 App 的 ResetHandler 地址;
可以通过 Keil 的 .map 文件查看 App 的入口地址;
若 App 的入口地址不是 0x1F6F,则跳转失败;
3. DfuFlag 清除时机问题
你设置了 DfuFlag = DFUTAG,然后软复位;
复位后进入 DFU Check,判断 DfuFlag == DFUTAG;
但如果你没有在跳转前清除 DfuFlag,下次复位还会进入 DFU 模式;
建议在跳转前清除标志位,防止死循环;
三、建议修改方案
✅ 修改跳转方式为汇编跳转
c
if (DfuFlag == APPVALIDTAG)
{
asm("ljmp 0x1F6F"); // 使用汇编跳转
}
✅ 清除 DfuFlag 标志
c
if (DfuFlag == DFUTAG)
{
DfuFlag = 0;
WriteFlashFlag(); // 将标志写入 Flash 或 EEPROM
asm("ljmp 0x1F6F");
}
✅ 关闭中断及外设
c
EA = 0;
TM0C &= ~0x40;
TM1C &= ~0x40;
四、App 编译配置建议
App 起始地址应设置为 0x1F00;
中断向量表偏移应设置为 0x1F00;
Keil 中应勾选“Use Memory Layout from Target Dialog”;
确保链接脚本或 scatter 文件正确配置了 App 地址空间;
生成的 bin 文件应使用 fromelf 或 sreccat 工具验证起始地址;
五、其他调试建议
1. 使用调试器查看跳转地址内容:
打开 Keil uVision,进入 Memory 窗口;
查看 0x1F6F 地址处是否有合法的指令码(如 LJMP、MOV 等);
若为 0xFF 或其他无效码,说明 App 写入失败;
2. 验证 Flash 写入流程:
确认写入前是否擦除了目标扇区;
写入过程中是否发生错误(如地址越界、长度错误);
3. 使用串口打印辅助调试:
在跳转前加入 printf("Jump to App at 0x1F6F\r\n");;
若该打印出现但未跳转,说明跳转失败;
六、总结
你当前的跳转失败,主要可能原因如下:
| 原因 | 说明 | 建议 |
|------|------|------|
| 跳转方式问题 | C 函数跳转不可靠 | 改为汇编 ljmp |
| App 地址不匹配 | 跳转地址非合法入口 | 检查 .map 文件 |
| App 写入失败 | Flash 写入未完成或出错 | 检查写入流程 |
| 中断未关闭 | 跳转后中断干扰 | 跳转前关闭中断 |
| DfuFlag 未清除 | 导致反复进入 DFU | 跳转前清除标志 |
七、结语
IAP 开发是一个涉及 Bootloader、Flash 操作、地址跳转、中断管理等多个模块的复杂过程,建议你在调试过程中:
使用调试器辅助分析;
保持代码逻辑清晰;
逐步验证每个模块的功能;
最终确保跳转流程完全可靠。
如需进一步协助,欢迎提供 .map 文件片段、bin 文件写入流程代码、Flash 写入函数等详细信息。
祝你调试顺利!
[本文内容由国芯人工智能辅助生成,仅供参考] 方便上传完整工程看看?
这个APP主程序什么都没干就退出了?
ercircle 发表于 2025-9-11 17:21
方便上传完整工程看看?
这个APP主程序什么都没干就退出了?
您好,iap和app已经补充到文末 1.将与APP IAP跳转无关功能暂时注释掉,调通功能后再联调,减少耦合影响。
2.关注一下告警,APP中未定义DFUFLAG
3.建议全局变量在主函数内初始化,而不是声明时初始化,尤其是data空间内的
4.读取APP位置前12个字节不应该这么多0,ISP+APP联合烧录方法参考我此贴:
一种简单合并ISP和APP程序文件的方法 - ISP下载/做自己的ISP 国芯人工智能技术交流网站 - AI32位8051交流社区
新手必读!新手必读!新手必读!新手必读!新手必读!新手必读!新手必读!新手必读! - 老鸟反刍/吐槽,新手乐园,毕业设计 国芯人工智能技术交流网站 - AI32位8051交流社区
ercircle 发表于 2025-9-11 18:03
1.将与APP IAP跳转无关功能暂时注释掉,调通功能后再联调,减少耦合影响。
2.关注一下告警,APP中未定义DF ...
会不会是我的hex转bin工具,导致bin文件出错了?你们是怎么将stc的hex文件转成bin文件的? zhouq 发表于 2025-9-12 09:43
会不会是我的hex转bin工具,导致bin文件出错了?你们是怎么将stc的hex文件转成bin文件的? ...
使用ISP加载hex,点击保存数据,再用winhex编辑也可自己定义程序读写合并。
可以先用我上面发的合并烧录方法验证
ercircle 发表于 2025-9-12 09:48
使用ISP加载hex,点击保存数据,再用winhex编辑也可自己定义程序读写合并。
可以先用我上面发的合并烧录 ...
我使用你发送的合并烧录方法,结果还是没有跳转到app。
先确认下操作:
1、按照合并烧录方法,得到一份all.bin文件
我的app.hex还是按照之前的方法编译得到的
2、按照之前的isp加载app教程,设置stcisp,烧录isp.hex
3、上位机发送all.bin
看下是不是这3个步骤哪里错了。我感觉是有问题的,因为app.bin是从EEPROM的0地址写入,现在的all.bin还增加了isp的部分,再从EEPROM的0地址写入,这不是额外增加了数据吗
1、按照合并烧录方法,得到一份all.bin文件
2、按照之前的isp加载app教程,设置stcisp,烧录isp.hex
这个表述到底是烧录all.bin还是isp.hex呢,楼上的合并烧录有操作视频,应该就EEPROM大小选项不一样而已,可以按照视频操作。
另外EEPROM的IAP操作由0开始,但是现在APP在EEPROM区,所以要自己偏移APP大小,不然APP程序代码就被破坏。
可以发下修改后的工程我试下 ercircle 发表于 2025-9-12 10:31
1、按照合并烧录方法,得到一份all.bin文件
2、按照之前的isp加载app教程,设置stcisp,烧录isp.hex
单片机肯定要有程序来接收我电脑发送的bin文件,所以我得到all.bin后,给stc烧录了isp.hex,用来接收电脑发送的all.bin
页:
[1]
2