找回密码
 立即注册
查看: 442|回复: 15

关于写自己的升级程序时碰到的一个问题!~

[复制链接]

15

主题

101

回帖

451

积分

中级会员

积分
451
发表于 2026-4-22 17:11:29 | 显示全部楼层 |阅读模式
首先,官方的示例代码中使用的DFU保存在xdata中,如果升级程序到一半出错,下次启动就要按P33来启动到bootloader中了,但并不是所有产品都适合做按铵

那么在bootloader中,把状态写进EEPROM无疑是最佳的办法了。。。

也就是说单片机通电,启动到bootloader中,先读取EEPROM特定位置,状态字节为0xff,那么就启动到正常的程序中执行、

正常程序检测到上位机发来升级命令,先修改EEPROM特定位置,状态字节改为1,然后切换到bootloader中,等待上位机发送升级内容,

升级完成后,修改状态字节为0xff,重启,升级成功!即使升级到一半中断了,由于状态字节为1,下次启动还是会进入bootloader中,接着升级就好了。。。


但是问题就是,在bootloader 与 普通程序中,如何写addr的地址,才能保证两块程序都能定位到同一个扇区的相同位置的EEPROM呢???

回复

使用道具 举报 送花

已绑定手机

51

主题

2743

回帖

9543

积分

论坛元老

积分
9543
发表于 2026-4-22 18:58:59 | 显示全部楼层
在bootloader 与 普通程序中,操作EEPROM的地址是相同的,可设置地址在程序空间后面。
例如普通程序空间60K,前面50K存放程序,最后10K作为EEPROM存储数据。
那么EEPROM起始地址为:1024*50 = 0xC800

点评

问题就是两套程序的EEPROM是对不上的。我使用的STC32G144K246,搞了2天了,一头雾水  发表于 2026-4-23 08:43
回复

使用道具 举报 送花

已绑定手机

51

主题

2743

回帖

9543

积分

论坛元老

积分
9543
发表于 2026-4-23 09:52:32 | 显示全部楼层
STC32G144K246与AI8051U有专门的用户系统区,用法跟其它芯片不一样。

STC32G144K246用户系统区从EEPROM空间前面划分(Flash 超过64K的芯片EEPROM空间从前往后划分)。
例如EEPROM大小设置12K,用户系统区设置8K(地址0000H~1FFFH),那么实际的EEPROM空间是12K后面的4K(地址1FFFH~2FFFH)大小。
截图202604231008086648.jpg

AI8051U用户系统区从EEPROM空间后面划分(Flash 64K以内的芯片EEPROM空间从后往前划分)。
例如EEPROM大小设置12K,用户系统区设置8K(地址1000H~2FFFH),那么实际的EEPROM空间是12K前面的4K(地址0000H~0FFFH)大小。

截图202604231010211147.jpg

点评

我的6.96T的下载界面,设置用户系统区大小为12K,EEPROM为2K,没有提示EEPROM非得要大于用户系统区大小  发表于 2026-4-23 14:14
回复

使用道具 举报 送花

15

主题

101

回帖

451

积分

中级会员

积分
451
 楼主| 发表于 2026-5-8 14:25:41 | 显示全部楼层
乘风*** 发表于 2026-4-23 09:52
STC32G144K246与AI8051U有专门的用户系统区,用法跟其它芯片不一样。

STC32G144K246用户系统区从EEPROM空 ...

那么用户ISP程序中,使用的是绝对地址,在用户APP程序中,读写eeprom时,地址为0x000000时,其实是读到了哪个地址上的数据呢?

其实我就想知道,在用户ISP程序中,与用户APP程序中,能同时读写到EEPROM同一地址的同一位置就解决问题了,可是不知道两个地址怎么写,我使用的是STC32G144K246。
回复

使用道具 举报 送花

已绑定手机

51

主题

2743

回帖

9543

积分

论坛元老

积分
9543
发表于 2026-5-8 18:11:30 | 显示全部楼层
用户ISP区操作EEPROM使用Flash绝对地址,用户程序区操作EEPROM地址需要从用户ISP区(4K)地址后面开始

截图202605081808247167.jpg

附件例子供参考:
截图202605081811154696.jpg

STC-official-usys-UART-ISP-bootloader-demo-STC32G144K246-series-eeprom.zip

557.5 KB, 下载次数: 29

回复

使用道具 举报 送花

15

主题

101

回帖

451

积分

中级会员

积分
451
 楼主| 发表于 2026-5-9 09:46:18 | 显示全部楼层
乘风*** 发表于 2026-5-8 18:11
用户ISP区操作EEPROM使用Flash绝对地址,用户程序区操作EEPROM地址需要从用户ISP区(4K)地址后面开始

可能不太对,当我下载程序的时候,设置用户系统区大小为4K,设置用户EEPROM区大小为2K,我测试的结果与你的不同,我单片机断电重启,数据就全部恢复0xff,也就是User ISP Read=0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff


我又改设置,用户系统区大小为4K,用户EEPROM区大小也为4K,数据还是不行,断电就全0xff

只有当用户EEPROM区大小大于4K,数据才对,但下载软件上没有任何提示,而且即使不勾 下次下载程序时擦除EEPROM区的数据,只要重新下载程序,数据全部清除。。。



还有个疑问,就是用户ISP程序,会固定下载到FF:0000开始的位置,大小为4K(可设置),用户APP程序下载到FF:0000+4K的位置,用户的EEPROM,保存到FC:2800开始的位置,如何写代码实现呢?我之前一直是这么理解的。

回复

使用道具 举报 送花

已绑定手机

51

主题

2743

回帖

9543

积分

论坛元老

积分
9543
发表于 2026-5-9 10:16:13 | 显示全部楼层
先直接用例子测试,功能验证正常后再进行修改或者移植。
例子按照说明书设置用户系统区4K,用户EEPROM大小8K:

截图202605091013309670.jpg

修改用户系统区大小后,ISP程序"config.h"里面 LDR_SIZE 要跟着修改:
  1. #define LDR_SIZE                (4 * 1024UL)                //用户系统ISP空间大小(4K字节)
复制代码


用户APP程序里面的EEPROM起始地址也要跟着修改:
  1. #define OFFSET          0x1000L         //操作EEPROM的起始地址,用户应用程序区操作EEPROM地址需要从用户ISP区(4K)地址后面开始
复制代码

点评

如果我想要,用户ISP程序下载到FF:0000开始的位置,大小为4K(可设置),用户APP程序下载到FF:0000+4K的位置,用户的EEPROM,保存到FC:2800开始的位置,可以实现吗?   发表于 2026-5-9 10:48
回复

使用道具 举报 送花

15

主题

101

回帖

451

积分

中级会员

积分
451
 楼主| 发表于 2026-5-9 10:45:16 | 显示全部楼层
乘风*** 发表于 2026-5-9 10:16
先直接用例子测试,功能验证正常后再进行修改或者移植。
例子按照说明书设置用户系统区4K,用户EEPROM大小8 ...

问题就是,在你的userisp程序中,你的User ISP Read=的地址定义为IAP_BASE地址
  1. #define OFFSET      (IAP_BASE)  //操作EEPROM的起始地址,用户ISP操作EEPROM使用Flash绝对地址
复制代码
而这里又有一段代码的地址是addr += IAP_BASE;
  1. BOOL iap_write_byte(DWORD addr, BYTE dat)
  2. {
  3.     if (!iap_check_addr(addr))
  4.         return 0;
  5.     addr += IAP_BASE;
  6.     IAP_CMD = 2;
  7.     IAP_ADDRE = BYTE2(addr);
  8.     IAP_ADDRH = BYTE1(addr);
  9.     IAP_ADDRL = BYTE0(addr);
  10.     IAP_DATA = dat;
  11.     IAP_TRIG = 0x5a;
  12.     IAP_TRIG = 0xa5;
  13.     _nop_();
  14.     _nop_();
  15.     _nop_();
  16.     _nop_();
  17.     return (iap_read_byte(addr) == dat);
  18. }
复制代码
这两块地址是不是重复了呢?


回复

使用道具 举报 送花

已绑定手机

51

主题

2743

回帖

9543

积分

论坛元老

积分
9543
发表于 2026-5-9 11:58:32 | 显示全部楼层
例子ISP程序只用到读EEPROM功能,如果要在ISP程序里面写EEPROM的话,就不要再加偏移地址
  1. BYTE iap_read_byte(DWORD addr)
  2. {
  3.     IAP_CMD = 1;
  4.     IAP_ADDRE = BYTE2(addr);
  5.     IAP_ADDRH = BYTE1(addr);
  6.     IAP_ADDRL = BYTE0(addr);
  7.     IAP_TRIG = 0x5a;
  8.     IAP_TRIG = 0xa5;
  9.     _nop_();
  10.     _nop_();
  11.     _nop_();
  12.     _nop_();
  13.     return IAP_DATA;
  14. }
  15. BOOL iap_write_byte(DWORD addr, BYTE dat)
  16. {
  17.     if (!iap_check_addr(addr))
  18.         return 0;
  19.     addr += IAP_BASE;
  20.     IAP_CMD = 2;
  21.     IAP_ADDRE = BYTE2(addr);
  22.     IAP_ADDRH = BYTE1(addr);
  23.     IAP_ADDRL = BYTE0(addr);
  24.     IAP_DATA = dat;
  25.     IAP_TRIG = 0x5a;
  26.     IAP_TRIG = 0xa5;
  27.     _nop_();
  28.     _nop_();
  29.     _nop_();
  30.     _nop_();
  31.     return (iap_read_byte(addr) == dat);
  32. }
复制代码

点评

userapp始终下载到ff:0000处,至少中断向量表会在此处,userisp有的话下载到fc:2800处,eeprom接在后面  发表于 2026-5-9 15:33
非常感谢你耐心的解答我的问题,我终于弄懂了userisp,userapp,eeprom的存储地址逻辑了  发表于 2026-5-9 15:25
回复

使用道具 举报 送花

15

主题

101

回帖

451

积分

中级会员

积分
451
 楼主| 发表于 2026-5-9 13:51:30 | 显示全部楼层
乘风*** 发表于 2026-5-9 11:58
例子ISP程序只用到读EEPROM功能,如果要在ISP程序里面写EEPROM的话,就不要再加偏移地址
...

发现个有意思的问题。。。我在你的代码前面加了一段

  1.         if(P33 == 0)
  2.         {
  3.             printf("Read0=");   //增加的代码
  4.             for(i=0;i<10;i++)
  5.             {
  6.                 a[i] = IapRead(0+i);
  7.                 printf("0x%02x ",a[i]);
  8.             }
  9.             printf("\r\n");
  10.             printf("Read1=");   //读取EEPROM原先的内容
  11.             for(i=0;i<10;i++)
  12.             {
  13.                 a[i] = IapRead(OFFSET+i);
  14.                 printf("0x%02x ",a[i]);
  15.                 if(a[i] == 0xff) a[i] = i;  //如果内容为空,则写入初始化数据
  16.                 else a[i]++;    //如果内容非空,在原先基础上加1
  17.             }
  18.             printf("\r\n");
  19.             IapErase(OFFSET);
  20. //            IapErase(OFFSET+512);//跨扇区擦除下一个扇区
  21.             printf("Read2=");   //擦除、重写后,读取EEPROM现在的内容
  22.             for(i=0;i<10;i++)
  23.             {
  24.                 IapProgram(OFFSET+i, a[i]);
  25.                 a[i] = IapRead(OFFSET+i);
  26.                 printf("0x%02x ",a[i]);
  27.             }
  28.             printf("\r\n");
  29.             while(!P33);
  30.         }
复制代码
截图202605091348556112.jpg
下面这里是userisp的代码的内容
截图202605091349398815.jpg

程序运行后,,,结果把userisp的内容给读出来了。。。
截图202605091350532952.jpg

说明官方出的未例代码中的文档中,权限这一是错的。。。
回复

使用道具 举报 送花

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

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2026-9-22 11:24 , Processed in 0.082601 second(s), 87 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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