楼主: 忠实的代码

[其他] 怎样定义某单个全局变量,使其在非上电复位后不初始化,保存复位之前的值(已解决)

[复制链接]

该用户从未签到

7

主题

66

帖子

0

注册会员

Rank: 2

积分
155
最后登录
2020-12-15
 楼主| 发表于 2013-2-20 21:38:06 | 显示全部楼层

回复:怎样定义某单个全局变量,使其在非上电复位后不初始化,保存复位之前的值

回复第 10 楼 于2013-02-20 18:35:22发表:
定义在FLASH,用汇编实现吧 

倘若定义在FLASH的话,每次复位后还得擦除该段FLASH空间,然后又编程写入,实在麻烦,太频繁地操作FLASH,浪费了点啊。
回复 支持 反对

使用道具 举报

该用户从未签到

3

主题

99

帖子

0

中级会员

Rank: 3Rank: 3

积分
322
最后登录
1970-1-1
发表于 2013-2-20 23:57:20 | 显示全部楼层

回复:怎样定义某单个全局变量,使其在非上电复位后不初始化,保存复位之前的值

回复第 7 楼 于2013-02-20 14:28:04发表:
回复第 6 楼 于2013-02-20 13:02:01发表:
回复第 5 楼 于2013-02-20 09:58:39发表:
回复第 4 楼 于2013-02-20 02:14:39发表:
回复第 3 楼 于2013-02-19 23:23:21发表:
不行。只能用FLASH来保存。 

 
 
他要保存的是“非上电复位”的数据,掉电后复位不算,应该行吧?
 

恩,谢谢您们啊,呵呵,安帮主和lwn71再次来帮我了。用FLASH的话,每次更新还要擦除,担心有些麻烦。根据我查的资料,修改启动汇编代码是可以做到非上电复位后不对RAM区清零。如lwn71所说,我选定某个保留地址不清零,比如地址在SRAM区0x40002000到0x40003000之间。那么我若直接强制读写一个地址:#define  RESET_COUNT   0x40002500。这样我每次复位启动后立即对RESET_COUNT++计数。能否做到对非上电复位的次数计数呢?还有Code Warrior2.10中,我若修改了启动汇编代码会对以后建立其它工程产生影响,是否有更好的方法呢?
 
你要实现的功能是不是计数非断电情况下系统软复位的次数?
如果是就把那段SRAM清零的汇编拿掉,或留两个字(节),一个当计数器,一个做标志。每次复位后查标志位是否是一个你写的特殊字(如0x5aa5):
 
如果不是说明是系统刚上电复位,内存数据无效,此时应对计数器清零同时把标志写成特殊字(0x5aa5)。
如过是说明是非掉电复位,内存数据有效,此时计数器+1。 计数值就是你要的东西
 
关于这段清零的汇编,每新建一个工程文件系统就会生成这段汇编,它保证你复位后你未初始化的变量都是零,如此而已,对你的工程是否产生影响可能你最清楚。对于我,我不用它;我对每个要用的变量都手动初始化--这样移植起来容易一些(有些编译器默认有这段清零程序,有些默认没有)
 
 嗯,你说的这个方法非常好。我之前做的是读复位状态寄存器,判断是上电复位还是非上电复位的,根据寄存器的值决定是否对复位计数。和你说的效果应该一样的。我想做的就是你说的,只计算非上电复位次数,但是只允许指定的复位计数变量不清零,而其它全局变量复位后正常清零。为此,我单独定义了一个段区间0x40002500到0x40003000。修改RAM初始化代码后,在该区间段定义了一个变量用以计数复位次数。调试时发现,变量虽然没有被清零,但是一直保持0x52这个值,没有按照我写的那样自加计数。不知道我修改的RAM初始化代码可正确,麻烦帮我看下,真是谢谢lwn71兄啊。
/* Initialize with zeros */
bii = _bss_init_info;
while (1) {
if (bii->addr == 0 && bii->size == 0) break;
if (bii->addr == _myDataStart) break;//这是我添加的代码,_myDataStart指向的是非初始化段的起始地址0x40002500
__init_bss_section(bii->addr, bii->size);
bii++;
}

若上面修改不正确,我又该如何正确修改RAM初始化,达到我想要的要求?
 

 
 

我没用过这款芯片,说的不一定对。
 
0x40002500到0x40003000这段是SRAM的结尾吗?如果是倒没看出初始化有什么错。
检查一下你的连接报告文件,系统没把你那段用作堆栈吧?或者你的定义被编译器忽略了,二次分配给其他变量用
 
能否把你预留那段地址挪个地方试一试,如换到0x40001500到0x40002000, 看看运行后还是0x52?初始化程序暂时改成
 
/* Initialize with zeros */
bii = _bss_init_info;
while (1) {
if (bii->addr == 0 && bii->size == 0) break;
if( (bii->addr addr >= _myDataStart+Max_offset ))  __init_bss_section(bii->addr, bii->size);
bii++;
}

 
回复 支持 反对

使用道具 举报

该用户从未签到

7

主题

66

帖子

0

注册会员

Rank: 2

积分
155
最后登录
2020-12-15
 楼主| 发表于 2013-2-21 09:26:52 | 显示全部楼层

回复:怎样定义某单个全局变量,使其在非上电复位后不初始化,保存复位之前的值

回复第 12 楼 于2013-02-20 23:57:20发表:
回复第 7 楼 于2013-02-20 14:28:04发表:
回复第 6 楼 于2013-02-20 13:02:01发表:
回复第 5 楼 于2013-02-20 09:58:39发表:
回复第 4 楼 于2013-02-20 02:14:39发表:
回复第 3 楼 于2013-02-19 23:23:21发表:
不行。只能用FLASH来保存。 

 
 
他要保存的是“非上电复位”的数据,掉电后复位不算,应该行吧?
 

恩,谢谢您们啊,呵呵,安帮主和lwn71再次来帮我了。用FLASH的话,每次更新还要擦除,担心有些麻烦。根据我查的资料,修改启动汇编代码是可以做到非上电复位后不对RAM区清零。如lwn71所说,我选定某个保留地址不清零,比如地址在SRAM区0x40002000到0x40003000之间。那么我若直接强制读写一个地址:#define  RESET_COUNT   0x40002500。这样我每次复位启动后立即对RESET_COUNT++计数。能否做到对非上电复位的次数计数呢?还有Code Warrior2.10中,我若修改了启动汇编代码会对以后建立其它工程产生影响,是否有更好的方法呢?
 
你要实现的功能是不是计数非断电情况下系统软复位的次数?
如果是就把那段SRAM清零的汇编拿掉,或留两个字(节),一个当计数器,一个做标志。每次复位后查标志位是否是一个你写的特殊字(如0x5aa5):
 
如果不是说明是系统刚上电复位,内存数据无效,此时应对计数器清零同时把标志写成特殊字(0x5aa5)。
如过是说明是非掉电复位,内存数据有效,此时计数器+1。 计数值就是你要的东西
 
关于这段清零的汇编,每新建一个工程文件系统就会生成这段汇编,它保证你复位后你未初始化的变量都是零,如此而已,对你的工程是否产生影响可能你最清楚。对于我,我不用它;我对每个要用的变量都手动初始化--这样移植起来容易一些(有些编译器默认有这段清零程序,有些默认没有)
 
 嗯,你说的这个方法非常好。我之前做的是读复位状态寄存器,判断是上电复位还是非上电复位的,根据寄存器的值决定是否对复位计数。和你说的效果应该一样的。我想做的就是你说的,只计算非上电复位次数,但是只允许指定的复位计数变量不清零,而其它全局变量复位后正常清零。为此,我单独定义了一个段区间0x40002500到0x40003000。修改RAM初始化代码后,在该区间段定义了一个变量用以计数复位次数。调试时发现,变量虽然没有被清零,但是一直保持0x52这个值,没有按照我写的那样自加计数。不知道我修改的RAM初始化代码可正确,麻烦帮我看下,真是谢谢lwn71兄啊。
/* Initialize with zeros */
bii = _bss_init_info;
while (1) {
if (bii->addr == 0 && bii->size == 0) break;
if (bii->addr == _myDataStart) break;//这是我添加的代码,_myDataStart指向的是非初始化段的起始地址0x40002500
__init_bss_section(bii->addr, bii->size);
bii++;
}

若上面修改不正确,我又该如何正确修改RAM初始化,达到我想要的要求?
 

 
 

我没用过这款芯片,说的不一定对。
 
0x40002500到0x40003000这段是SRAM的结尾吗?如果是倒没看出初始化有什么错。
检查一下你的连接报告文件,系统没把你那段用作堆栈吧?或者你的定义被编译器忽略了,二次分配给其他变量用
 
能否把你预留那段地址挪个地方试一试,如换到0x40001500到0x40002000, 看看运行后还是0x52?初始化程序暂时改成
 
/* Initialize with zeros */
bii = _bss_init_info;
while (1) {
if (bii->addr == 0 && bii->size == 0) break;
if( (bii->addr addr >= _myDataStart+Max_offset ))  __init_bss_section(bii->addr, bii->size);
bii++;
}

 
 
SRAM0x40002000到0x40002500这段空间是我单独腾出来的,没有用作堆和栈,其后的RAM空间被用作堆栈了。我后面试了几次,强行读写的RESET_COUNT又能够正确计数了,很奇怪,我程序一点没改,此时,在腾出来的RAM空间定义的变量test却不能正常计数,值为1。而RESET_COUNT和test所在地址都属于单独腾出来的RAM空间。进入调试模式后,我断开电源,再通过调试窗口使单片机复位,此后复位计数又固定在某个非正常值。
你这种修改初始化程序比较好,我试下。呵呵,谢谢啊
回复 支持 反对

使用道具 举报

该用户从未签到

3

主题

99

帖子

0

中级会员

Rank: 3Rank: 3

积分
322
最后登录
1970-1-1
发表于 2013-2-21 10:43:58 | 显示全部楼层

回复:怎样定义某单个全局变量,使其在非上电复位后不初始化,保存复位之前的值

SRAM0x40002000到0x40002500这段空间是我单独腾出来的,没有用作堆和栈,其后的RAM空间被用作堆栈了。我后面试了几次,强行读写的RESET_COUNT又能够正确计数了,很奇怪,我程序一点没改,此时,在腾出来的RAM空间定义的变量test却不能正常计数,值为1。而RESET_COUNT和test所在地址都属于单独腾出来的RAM空间。进入调试模式后,我断开电源,再通过调试窗口使单片机复位,此后复位计数又固定在某个非正常值。
你这种修改初始化程序比较好,我试下。呵呵,谢谢啊
 
 
 
你是用调试模式测的吗?如果是不妨烧写芯片脱机运行试一试。总感觉你预留的地址被重复利用了,或者是别的逻辑原因。
 
如果你预留的那段内存如果在系统尾部,我的初始化程序和你的功能上没区别。你的在碰到预留内存就停止清零了,预留内存后还有内存的话也不被清零,如此而已。
 
 
 
 

 
回复 支持 反对

使用道具 举报

该用户从未签到

27

主题

418

帖子

0

新手上路

Rank: 1

积分
228
最后登录
1970-1-1
发表于 2013-2-21 13:10:41 | 显示全部楼层

回复:怎样定义某单个全局变量,使其在非上电复位后不初始化,保存复位之前的值

就ram来说,上电后内容是随机的,所以不能用ram来实现你的要求,对于
回复 支持 反对

使用道具 举报

该用户从未签到

3

主题

99

帖子

0

中级会员

Rank: 3Rank: 3

积分
322
最后登录
1970-1-1
发表于 2013-2-21 22:01:47 | 显示全部楼层

回复:怎样定义某单个全局变量,使其在非上电复位后不初始化,保存复位之前的值

回复第 15 楼 于2013-02-21 13:10:41发表:
就ram来说,上电后内容是随机的,所以不能用ram来实现你的要求,对于 

这个要看楼主的具体应用吧,楼主应该知道RAM调电后会丢数据。楼主只说需要保存非上电复位前的计数值,并没有说调电后还要记录这个值。
 
类似的手法在系统可靠性测试中很常用,特别在多任务系统测试中。有时测试时会把看门狗打开,不掉电情况下运行几天,并给系统模拟各总输入条件,然后从这个非上电复位计数值可以看出是否有某个模块出问题。
如果用户不知情,Freescale在启动程序里自动加的这段清零程序往往会搞砸以上功能。
 
回复 支持 反对

使用道具 举报

该用户从未签到

7

主题

66

帖子

0

注册会员

Rank: 2

积分
155
最后登录
2020-12-15
 楼主| 发表于 2013-2-22 13:35:16 | 显示全部楼层

回复:怎样定义某单个全局变量,使其在非上电复位后不初始化,保存复位之前的值

回复第 15 楼 于2013-02-21 13:10:41发表:
就ram来说,上电后内容是随机的,所以不能用ram来实现你的要求,对于 

这个我知道,所以我的要求就只是在非上电情况下的复位计数。掉电后计数值不保存。不知你可有很好的方法实现?
回复 支持 反对

使用道具 举报

该用户从未签到

7

主题

66

帖子

0

注册会员

Rank: 2

积分
155
最后登录
2020-12-15
 楼主| 发表于 2013-2-22 16:28:51 | 显示全部楼层

回复:怎样定义某单个全局变量,使其在非上电复位后不初始化,保存复位之前的值

回复第 14 楼 于2013-02-21 10:43:58发表:

SRAM0x40002000到0x40002500这段空间是我单独腾出来的,没有用作堆和栈,其后的RAM空间被用作堆栈了。我后面试了几次,强行读写的RESET_COUNT又能够正确计数了,很奇怪,我程序一点没改,此时,在腾出来的RAM空间定义的变量test却不能正常计数,值为1。而RESET_COUNT和test所在地址都属于单独腾出来的RAM空间。进入调试模式后,我断开电源,再通过调试窗口使单片机复位,此后复位计数又固定在某个非正常值。
你这种修改初始化程序比较好,我试下。呵呵,谢谢啊
 
 
 
你是用调试模式测的吗?如果是不妨烧写芯片脱机运行试一试。总感觉你预留的地址被重复利用了,或者是别的逻辑原因。
 
如果你预留的那段内存如果在系统尾部,我的初始化程序和你的功能上没区别。你的在碰到预留内存就停止清零了,预留内存后还有内存的话也不被清零,如此而已。
 
 恩,我之前是在调试模式下测的,然后直接看计数值地址内容是否复位后进行了自加。后来脱机运行,通过串口讲计数值发送到电脑,效果一样。目前的情况是,我强制给RAM某地址内容自加能够达到我的要求,但是我若在这个地址上定义一个变量,却达不到我计数的要求。总是被清零。 
有些编译器是在.map文件中没有映射的地址内容不会被初始化清零,不知道,我上面描述的情况符不符合这个条件?
 

 

 
回复 支持 反对

使用道具 举报

该用户从未签到

3

主题

99

帖子

0

中级会员

Rank: 3Rank: 3

积分
322
最后登录
1970-1-1
发表于 2013-2-22 22:09:09 | 显示全部楼层

回复:怎样定义某单个全局变量,使其在非上电复位后不初始化,保存复位之前的值

回复第 18 楼 于2013-02-22 16:28:51发表:
回复第 14 楼 于2013-02-21 10:43:58发表:

SRAM0x40002000到0x40002500这段空间是我单独腾出来的,没有用作堆和栈,其后的RAM空间被用作堆栈了。我后面试了几次,强行读写的RESET_COUNT又能够正确计数了,很奇怪,我程序一点没改,此时,在腾出来的RAM空间定义的变量test却不能正常计数,值为1。而RESET_COUNT和test所在地址都属于单独腾出来的RAM空间。进入调试模式后,我断开电源,再通过调试窗口使单片机复位,此后复位计数又固定在某个非正常值。
你这种修改初始化程序比较好,我试下。呵呵,谢谢啊
 
 
 
你是用调试模式测的吗?如果是不妨烧写芯片脱机运行试一试。总感觉你预留的地址被重复利用了,或者是别的逻辑原因。
 
如果你预留的那段内存如果在系统尾部,我的初始化程序和你的功能上没区别。你的在碰到预留内存就停止清零了,预留内存后还有内存的话也不被清零,如此而已。
 
 恩,我之前是在调试模式下测的,然后直接看计数值地址内容是否复位后进行了自加。后来脱机运行,通过串口讲计数值发送到电脑,效果一样。目前的情况是,我强制给RAM某地址内容自加能够达到我的要求,但是我若在这个地址上定义一个变量,却达不到我计数的要求。总是被清零。 
有些编译器是在.map文件中没有映射的地址内容不会被初始化清零,不知道,我上面描述的情况符不符合这个条件?
 

 

 

 

你是怎么定义这个变量的?如果用 #define RESET_COUNT  *(unsigned char*)0x40002500, 那和你直接操作地址没区别啊。
而且你引用RESET_COUNT时没有做别的运算吧?如果有,定义RESET_COUNT时多加一对括号好一些#define RESET_COUNT ( *(unsigned char*)0x40002500)
 
 
编译器对不对映射的地址清零就看那段清零程序,应该没有其它暗扣了。
回复 支持 反对

使用道具 举报

该用户从未签到

7

主题

66

帖子

0

注册会员

Rank: 2

积分
155
最后登录
2020-12-15
 楼主| 发表于 2013-2-23 08:12:11 | 显示全部楼层

回复:怎样定义某单个全局变量,使其在非上电复位后不初始化,保存复位之前的值

回复第 19 楼 于2013-02-22 22:09:09发表:
回复第 18 楼 于2013-02-22 16:28:51发表:
回复第 14 楼 于2013-02-21 10:43:58发表:

SRAM0x40002000到0x40002500这段空间是我单独腾出来的,没有用作堆和栈,其后的RAM空间被用作堆栈了。我后面试了几次,强行读写的RESET_COUNT又能够正确计数了,很奇怪,我程序一点没改,此时,在腾出来的RAM空间定义的变量test却不能正常计数,值为1。而RESET_COUNT和test所在地址都属于单独腾出来的RAM空间。进入调试模式后,我断开电源,再通过调试窗口使单片机复位,此后复位计数又固定在某个非正常值。
你这种修改初始化程序比较好,我试下。呵呵,谢谢啊
 
 
 
你是用调试模式测的吗?如果是不妨烧写芯片脱机运行试一试。总感觉你预留的地址被重复利用了,或者是别的逻辑原因。
 
如果你预留的那段内存如果在系统尾部,我的初始化程序和你的功能上没区别。你的在碰到预留内存就停止清零了,预留内存后还有内存的话也不被清零,如此而已。
 
 恩,我之前是在调试模式下测的,然后直接看计数值地址内容是否复位后进行了自加。后来脱机运行,通过串口讲计数值发送到电脑,效果一样。目前的情况是,我强制给RAM某地址内容自加能够达到我的要求,但是我若在这个地址上定义一个变量,却达不到我计数的要求。总是被清零。 
有些编译器是在.map文件中没有映射的地址内容不会被初始化清零,不知道,我上面描述的情况符不符合这个条件?
 

 

 

 

你是怎么定义这个变量的?如果用 #define RESET_COUNT  *(unsigned char*)0x40002500, 那和你直接操作地址没区别啊。
而且你引用RESET_COUNT时没有做别的运算吧?如果有,定义RESET_COUNT时多加一对括号好一些#define RESET_COUNT ( *(unsigned char*)0x40002500)
 
 
编译器对不对映射的地址清零就看那段清零程序,应该没有其它暗扣了。
 

嗯,我没有对RESET_COUNT进行其他操作。就是这样强行修改0x40002500地址内容;还有一种方法就是在该地址上定义一个全局变量,然后对该变量自加计数。这两种方法目前只有第一种有效。不知道这里面的具体原因是什么?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /3 下一条

Archiver|手机版|小黑屋|恩智浦技术社区

GMT+8, 2025-10-24 06:13 , Processed in 0.109070 second(s), 29 queries , MemCache On.

Powered by Discuz! X3.4

Copyright © 2001-2024, Tencent Cloud.

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