打印
[STM32F4]

STM32F4 SWD调试,全速运行错误,单步运行正确

[复制链接]
6141|22
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
香草源|  楼主 | 2015-10-23 18:44 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 香草源 于 2015-10-25 19:42 编辑

由于涉及到公司保密问题,来一个简化版的代码
volatile uint8_t *ab=0X20000400;
volatile uint8_t *ac=0X20000600;
volatile uint8_t *ad=0X20000800;
/***********************************
函数 取变量地址
入口参数  a  变量类型
入口参数  b  变量偏移量
入口出口参数  c  1/0  地址正常/地址不正常
**********************************/
volatile uint8_t *ReadRegisterAddr(uint8_t a,uint32_t b,uint8_t *c)
{
        volatile uint8_t *d;
        *c=1;
        switch(a)
        {
                case 0: if(b<256) d=&ab;
                        else{*c=0; d=0x20000000;}
                break;
                case 1: if(b<512) d=&ac;
                        else{*c=0; d=0x20000000;}
                break;
                case 2: if(b<256) d=&ad;
                        else{*c=0; d=0x20000000;}
                break;
                default: {*c=0; d=0x20000000;}        
        }
        return d;

}

uint8_t ReadAddr()
{
        volatile uint8_t *d; //变量地址指针
        uint8_t k;
        d=ReadRegisterAddr(1,10,&k);
        if(k==1)
        {
                *d=10;
        }
}

问题:
这个函数ReadRegisterAddr,不进入运行,单步执行跳过,函数返回值,就是错误。如果单步执行进入,这样函数返回值正常。
非常不理解,而且是偶尔出错,出错后,再调试,就出现前面说的现象
沙发
玛尼玛尼哄| | 2015-10-23 20:46 | 只看该作者
break放在大括号里吧,这样就会对了。

使用特权

评论回复
板凳
香草源|  楼主 | 2015-10-23 20:58 | 只看该作者
不管是 走if 还是else 分支都要break

使用特权

评论回复
地板
尤彼卡| | 2015-10-23 22:43 | 只看该作者
没有设置断点查看一下吗

使用特权

评论回复
5
香草源|  楼主 | 2015-10-24 09:03 | 只看该作者
尤彼卡 发表于 2015-10-23 22:43
没有设置断点查看一下吗

有啊,在这个*ReadRegisterAdd函数设置断点就正常,用MDK编译,连汇编每条指令单步执行都查看过

使用特权

评论回复
6
可可球| | 2015-10-24 16:53 | 只看该作者
没有找到是在哪跑飞的吗

使用特权

评论回复
7
309030| | 2015-10-24 17:02 | 只看该作者
我以前遇到过,后来发现是用的数组数据太多了,放到flash后就好了

使用特权

评论回复
8
香草源|  楼主 | 2015-10-24 17:39 | 只看该作者
可可球 发表于 2015-10-24 16:53
没有找到是在哪跑飞的吗

不是跑飞,是执行结果不正确。
有一点我要说明一下,程序是受干扰后,发生HardFault,在里面执行软复位,软复位后程序就有可能执行不正常

使用特权

评论回复
9
gejigeji521| | 2015-10-24 18:51 | 只看该作者
这个问题好复杂,会不会有时序代码?

使用特权

评论回复
10
moyanming2013| | 2015-10-24 19:09 | 只看该作者
本帖最后由 moyanming2013 于 2015-10-24 19:13 编辑
d=*ReadRegisterAddr(1,10,&k);

1.ReadRegisterAddr返回的指针是个局部变量,函数一退出,指针就无效了。你用全局的指针做返回值吧。
2.没见过d=*ReadRegisterAddr这么用的,直接ReadRegisterAddr就行了,它返回的就是个指针。或者我孤陋寡闻,你给我个资料我学下。或者你的意思是*d=*ReadRegisterAddr?那干脆让ReadRegisterAddr直接返回一个数值不就行了?!

使用特权

评论回复
11
可可球| | 2015-10-25 17:37 | 只看该作者
楼主说是全速运行错误,单步运行正确,会是d=*ReadRegisterAddr错吗

使用特权

评论回复
12
香草源|  楼主 | 2015-10-25 19:38 | 只看该作者
本帖最后由 香草源 于 2015-10-25 19:40 编辑
moyanming2013 发表于 2015-10-24 19:09
1.ReadRegisterAddr返回的指针是个局部变量,函数一退出,指针就无效了。你用全局的指针做返回值吧。
2.没 ...

不好意思,这里是我写错了,正确的应该是d=ReadRegisterAddr,就是返回一个地址,我看了汇编,返回地址是放在寄存器R0,返回后汇编后,还有有一个MOV d,r0  这里暂且用d表示,或许可以像你说的那样用,返回一个值,不用指针

使用特权

评论回复
13
香草源|  楼主 | 2015-10-26 08:18 | 只看该作者
309030 发表于 2015-10-24 17:02
我以前遇到过,后来发现是用的数组数据太多了,放到flash后就好了

数组数据确实蛮多的,实际使用时几个加起来有几K,就是要读和写数组数据,不可能放flash

使用特权

评论回复
14
fclmyl2| | 2015-10-26 10:23 | 只看该作者
volatile uint8_t *d; //变量地址指针  是没有地址的,你可以直接定义一个数组,或外部带入一个数组

使用特权

评论回复
15
moyanming2013| | 2015-10-26 11:54 | 只看该作者
本帖最后由 moyanming2013 于 2015-10-26 12:08 编辑
香草源 发表于 2015-10-25 19:38
不好意思,这里是我写错了,正确的应该是d=ReadRegisterAddr,就是返回一个地址,我看了汇编,返回地址是 ...

在debug和release下程序的汇编代码是截然不同的。
返回一个局部的指针在语法上虽然没有什么错误,但是实际上是错误的!因为编译完成后,局部的变量就没有了(优化了)。
针对:
int *p = NULL;
注意:没有是指*p没有了,但p在返回前还是存在的(暂存在一个寄存器中),亦即p暂时还有,但*p是没有了!
这是有很大区别的,也就是你的程序实际上用这种返回局部指针是错误的!
你可以返回一个全局的指针;
或者直接返回一个值而不是指针。比如返回0X20000800(根据需要你再把这个数值强制类型转换为你确定知道的指针),而不是返回指向它的一个局部的指针(编译器不知道局部指针指向的内容,也没必要知道,但确定的是编译器会优化掉它)。


使用特权

评论回复
16
豆腐块| | 2015-10-26 23:21 | 只看该作者
数组数据确实蛮多的,实际使用时几个加起来有几K

楼主可以试试放入flash里,数组前加const

使用特权

评论回复
17
香草源|  楼主 | 2015-10-27 08:12 | 只看该作者
moyanming2013 发表于 2015-10-26 11:54
在debug和release下程序的汇编代码是截然不同的。
返回一个局部的指针在语法上虽然没有什么错误,但是实际 ...

你说的可以试试

使用特权

评论回复
18
香草源|  楼主 | 2015-10-27 08:13 | 只看该作者
豆腐块 发表于 2015-10-26 23:21
楼主可以试试放入flash里,数组前加const

需要读写,所以只能在内存

使用特权

评论回复
19
Snow7| | 2015-10-28 21:58 | 只看该作者
可以分段屏蔽,找找是哪段出现问题了

使用特权

评论回复
20
zhuotuzi| | 2015-10-28 22:42 | 只看该作者
感觉是时序的问题,楼主目前解决了这个问题吗?因为单步时候不纯在延时过短的问题。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

14

帖子

0

粉丝