打印

可能发现RVMDK V4.21编译器一个bug,请高手鉴定

[复制链接]
14246|25
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
junsi|  楼主 | 2011-9-7 16:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 junsi 于 2011-9-7 16:48 编辑

以前正常的程序,突然出现重启问题,编译器才换了V4.21,最后跟踪在以下函数出问题:void BlockTransStart(u16 count,u32 ms)
{
WaitTransOver();//等待usb发送不忙
TrBuf[0] = 11;
TrBuf[1] = TYPE_ORDER;
TrBuf[2] = TYPE_ORDER_STARTBULK;
*((u32 *)(&TrBuf[3])) = (u32)count;
*((u32 *)(&TrBuf[7])) = ms;
BlockTrans(11);
} 程序在红色处重启,汇编码如下:


    67: void BlockTransStart(u16 count,u32 ms)
0x08008C62 2140      MOVS     r1,#0x40
0x08008C64 48D6      LDR      r0,[pc,#856]  ; @0x08008FC0
0x08008C66 F7FFBF5F  B.W      Trans (0x08008B28)
    68: {               
0x08008C6A B570      PUSH     {r4-r6,lr}
0x08008C6C 4604      MOV      r4,r0
0x08008C6E 460D      MOV      r5,r1
    69:         WaitTransOver();//等待usb发送不忙
0x08008C70 F7FFFF4C  BL.W     WaitTransOver (0x08008B0C)
    70:         TrBuf[0] = 11;
0x08008C74 4AD2      LDR      r2,[pc,#840]  ; @0x08008FC0
0x08008C76 200B      MOVS     r0,#0x0B
    71:         TrBuf[1] = TYPE_ORDER;
0x08008C78 2320      MOVS     r3,#0x20
0x08008C7A 7010      STRB     r0,[r2,#0x00]
0x08008C7C 7053      STRB     r3,[r2,#0x01]
    72:         TrBuf[2] = TYPE_ORDER_STARTBULK;
    73:         *((u32 *)(&TrBuf[3])) = (u32)count;           
    74:         *((u32 *)(&TrBuf[7])) = ms;
0x08008C7E 7093      STRB     r3,[r2,#0x02]
0x08008C80 1CD2      ADDS     r2,r2,#3
0x08008C82 C230      STM      r2!,{r4-r5}
    75:         BlockTrans(11);
    76: }

把程序改为:
void BlockTransStart(u16 count,u32 ms)
{
WaitTransOver();//等待usb发送不忙
TrBuf[0] = 11;
TrBuf[1] = TYPE_ORDER;
*((u32 *)(&TrBuf[3])) = (u32)count;
TrBuf[2] = TYPE_ORDER_STARTBULK;
*((u32 *)(&TrBuf[7])) = ms;
BlockTrans(11);
} 编译后问题才得以解决,汇编码如下:


    67: void BlockTransStart(u16 count,u32 ms)
0x08008C62 2140      MOVS     r1,#0x40
0x08008C64 48D7      LDR      r0,[pc,#860]  ; @0x08008FC4
0x08008C66 F7FFBF5F  B.W      Trans (0x08008B28)
    68: {               
0x08008C6A B570      PUSH     {r4-r6,lr}
0x08008C6C 4604      MOV      r4,r0
0x08008C6E 460D      MOV      r5,r1
    69:         WaitTransOver();//等待usb发送不忙
0x08008C70 F7FFFF4C  BL.W     WaitTransOver (0x08008B0C)
    70:         TrBuf[0] = 11;
0x08008C74 4AD3      LDR      r2,[pc,#844]  ; @0x08008FC4
0x08008C76 200B      MOVS     r0,#0x0B
    71:         TrBuf[1] = TYPE_ORDER;
0x08008C78 2320      MOVS     r3,#0x20
0x08008C7A 7010      STRB     r0,[r2,#0x00]
0x08008C7C 7053      STRB     r3,[r2,#0x01]
    72:         *((u32 *)(&TrBuf[3])) = (u32)count;      
0x08008C7E F8C24003  STR      r4,[r2,#0x03]
    73:         TrBuf[2] = TYPE_ORDER_STARTBULK;         
0x08008C82 7093      STRB     r3,[r2,#0x02]
    74:         *((u32 *)(&TrBuf[7])) = ms;
0x08008C84 F8C25007  STR      r5,[r2,#0x07]
    75:         BlockTrans(11);
    76: }
我不懂汇编,请高手看看是否是编译器的问题?如何避免类似的问题出现? 对了程序中 Trbuf 为全局变量 u8 Trbuf[64]; 我也改成vu8 Trbuf[64] 但问题依旧.
编译优化等级:default;Use Cross-Module Optimization;Use MicroLIB
来自 2楼
acgean| | 2011-9-8 12:03 | 只看该作者
本帖最后由 acgean 于 2011-9-8 12:19 编辑

没有 bug 呀.

STM      r2!,{r4-r5}
这里一下写入 两个 32 位数据.
而经过你修改以后, 这两个 32 位数据分两次写入了.

也许楼主发现 使用 STM 指令后出现问题了.
是的,  因为你的 *((u32 *)(&TrBuf[3]))  应该不会是字对齐的.

Cortex M3 的非对齐的数据数据访问只能用 LDR STR 这样的指令.
也就是说: STM 不允许进行非对齐的数据访问. 否则用法 faults  异常.

结论, 这不能算是编译器的 BUG, 而是由楼主不规范地址导致的
同时, 也希望大家在使用 *((u32 *)(&TrBuf[3]))  
这样简化数据访问的时候, 最好使用对齐地址, 以免不必要的麻烦

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
auzxj + 1
板凳
xsgy123| | 2011-9-7 16:48 | 只看该作者
表示看不懂

使用特权

评论回复
地板
sjnh| | 2011-9-8 13:50 | 只看该作者
楼上说得对

使用特权

评论回复
5
junsi|  楼主 | 2011-9-8 13:57 | 只看该作者
非常感谢acqean的精彩解释,小生受益!上分

使用特权

评论回复
6
yanghao9123| | 2011-9-8 15:56 | 只看该作者
非常准确

使用特权

评论回复
7
yybj| | 2011-9-8 19:11 | 只看该作者
没有BUG

使用特权

评论回复
8
txcy| | 2011-9-8 22:34 | 只看该作者
3楼大侠鉴定的很有道理

使用特权

评论回复
9
hdp7891000| | 2011-9-9 12:11 | 只看该作者
mark

使用特权

评论回复
10
sinadz| | 2011-9-9 16:00 | 只看该作者
3楼大侠分析的很有条理啊,是该给条棉裤

使用特权

评论回复
11
1212yin| | 2011-9-12 13:37 | 只看该作者
1# junsi
请问你的Trbuf是多大的空间,Trbuf是整形的还是字节形式的,都没说明白怎么好帮你解决,再者,不要轻易怀疑编译器的问题,因为99%的问题都是因为程序书写不当引起问题,只有当分析自己写得代码没有逻辑或者语法的问题时,或者堆栈都正常的情况下,才有可能去怀疑是否是编译器出了问题,不过往往分析的最后还是程序本身的问题,呵呵

使用特权

评论回复
12
HORSE7812| | 2011-9-13 11:44 | 只看该作者
mark.......

使用特权

评论回复
13
huanben| | 2011-9-13 16:50 | 只看该作者
为什么你用老版本的会没有问题呢?

使用特权

评论回复
14
nongfuxu| | 2011-9-13 21:50 | 只看该作者
学习中

使用特权

评论回复
15
lcq07| | 2011-10-10 16:03 | 只看该作者
其实楼主注意观察一下可以看到
*((u32 *)(&TrBuf[3])) = (u32)count;
*((u32 *)(&TrBuf[7])) = ms;

这两句被编译做了点小聪明编译成了
0x08008C7E 7093      STRB     r3,[r2,#0x02]
0x08008C80 1CD2      ADDS     r2,r2,#3

0x08008C82 C230      STM      r2!,{r4-r5}
也就是说编译器认为你这是连续对同一数组中不同元素赋值,而数组元素TrBuf[3]和TrBuf[7]之间刚好为4字节间隔,这样编译器编译成STM可以省去一部分指令,但是编译器并不知道你的地址是否4字节对齐的 。
对于3楼所说STM指令不允许非对齐访问之一点还不够正确,准确的说对于所有4字节存储访问指令其访问地址都必须4字节对齐,否则就会出现异常

还有对于你后面
    72:         *((u32 *)(&TrBuf[3])) = (u32)count;      
0x08008C7E F8C24003  STR      r4,[r2,#0x03]
明显是非对齐访问,这一句运行肯定也会出问题,至于你说的没问题我就很奇怪了

使用特权

评论回复
16
linfuchi| | 2011-11-24 22:15 | 只看该作者
路过,嘿嘿

使用特权

评论回复
17
hhhhuuii| | 2011-12-1 11:51 | 只看该作者
顶顶

使用特权

评论回复
18
linqing171| | 2011-12-5 12:07 | 只看该作者
哈哈,pack的问题。
新版本优化的原因。新版本也符合C标准,默认pack为sizeof(int)。而arm是32位机,int为四字节。

使用特权

评论回复
19
open_free| | 2011-12-5 13:16 | 只看该作者
很久前遇到过 micro库bug问题,折腾后自己实现了该函数,再后来新版本就没有问题了,不过我也尽量不用该库了。。。

使用特权

评论回复
20
liuzhuo1978| | 2011-12-5 13:18 | 只看该作者
看完学到不少东西呢

使用特权

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

本版积分规则

7

主题

39

帖子

1

粉丝