打印
[开发工具]

IAR 4.42A For STM32 的危险 Bug !

[复制链接]
13038|35
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
seawwh|  楼主 | 2009-1-31 11:10 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
在试验SDIO 代码的时候发现了一个明显的运算错误:
  
 
测试环境:

   2G SD 卡, STM32
   IAR Assembler for ARM  4.42A (4.42.1.501)
   编译优化:none
   代码:

   SDIO 的 SD_Error SD_GetCardInfo(SD_CardInfo *cardinfo) 函数;

    ... ... ...

    /* Byte 9 */
    tmp = (u8)((CSD_Tab[2] & 0x00FF0000) >> 16);
    cardinfo->SD_csd.MaxWrCurrentVDDMin = (tmp & 0xE0) >> 5;
    cardinfo->SD_csd.MaxWrCurrentVDDMax = (tmp & 0x1C) >> 2;
    cardinfo->SD_csd.DeviceSizeMul = (tmp & 0x03) << 1;         // 执行后 cardinfo->SD_csd.DeviceSizeMul=0x06
    /* Byte 10 */
    tmp = (u8)((CSD_Tab[2] & 0x0000FF00) >> 8);                 // 执行后 tmp=0xFF
    cardinfo->SD_csd.DeviceSizeMul |= (tmp & 0x80) >> 7;        // 执行后 cardinfo->SD_csd.DeviceSizeMul=0x6F
                                                                // 正确的代码应改为  0x07 
    ... ... ...

    跟踪了一下汇编发现,关键的语句是
    ORRS  R3,R3,R2,LSR #7           // 其中 R3=0x06 对应于 cardinfo->SD_csd.DeviceSizeMul
                                    //      R2=0x002DB7FF   对应于 tmp

    错误在于没有对 R2 做取低8位处理,导致 R2 右移将高位数据移到了低8位。

简化程序做了一下试验,下面的三种语句都是一个结果 BB=0x68,显然是不对的。 
   编译优化:none

u8  AA,BB=0;
u32 CC;
    CC = 0x12345678;
    AA = CC >> 8;
    BB |= (AA & 0x80) >> 7;   // BB=0x68

    AA = (u8)CC >> 8;
    BB |= (AA & 0x80) >> 7;   // BB=0x68

    AA = (u8)(CC >> 8);
    BB |= (AA & 0x80) >> 7;   // BB=0x68


显然很危险,问题是如何有效的避免这种Bug 呢?

有IAR高版本的同行可以试验一下,是否改掉了这个错误。

沙发
Again_gyf| | 2009-1-31 20:30 | 只看该作者

不可能吧!

ORRS  R3,R3,R2,LSR #7 前面应该还有条UXTB指令
EWARM5.20上没有问题!

使用特权

评论回复
板凳
mcuisp| | 2009-2-1 00:07 | 只看该作者

我试过结果是正确的呢。

使用特权

评论回复
地板
seawwh|  楼主 | 2009-2-1 01:12 | 只看该作者

测试的屏幕拷贝

u8  AA,BB;
u32 CC;
    CC = 0x12345678;

    BB =0; 
    AA = CC >> 8;
    BB |= (AA & 0x80) >> 7;
                         // AA=0x56 BB=0x68  错
    BB =0; 
    AA = (u8)(CC >> 8);
    BB |= (AA & 0x80) >> 7;
                        // AA=0x56 BB=0x68  错

使用特权

评论回复
5
老狼| | 2009-2-1 01:37 | 只看该作者

BB |= ((AA & 0x80) >> 7);

使用特权

评论回复
6
mcuisp| | 2009-2-1 03:31 | 只看该作者

LZ用的软件仿真还是硬件仿真器?

我再试仍对。

使用特权

评论回复
7
masashinakayama| | 2009-2-1 09:19 | 只看该作者

看这个AA BB变量

就知道肯定是lz愚蠢的错误

使用特权

评论回复
8
seawwh|  楼主 | 2009-2-1 09:34 | 只看该作者

回答 mcuisp, 软件和硬件单步的结果都是错的

回答 mcuisp, 软件和硬件单步的结果都是错的。
正确的结果 BB的值应该为0x00.

mcuisp 你试验的环境和我一样吗? 包括版本和优化级别
另外, 编译CPU 是 ST STM32F10xxE

楼上老狼提出的使用下面的语句
BB |= ((AA & 0x80) >> 7);
其结果 BB=0x68 仍然是错的

使用特权

评论回复
9
香水城| | 2009-2-1 09:44 | 只看该作者

请注意:局部变量被分配到寄存器,不能在Watch窗口查看中间

Watch窗口始终是显示变量对应的内存中数据的变化,如果在变量参与运算时是在寄存器中进行,则Watch窗口不能反映实际变量数值的变化。

请使用全局变量定义AA和BB,然后再操作结束后再观察Watch窗口。

使用特权

评论回复
10
seawwh|  楼主 | 2009-2-1 10:21 | 只看该作者

针对版主的建议的试验结果,仍然不对

我设计了一个全局变量 DD,执行完后仍然不对,代码如下:

static  u8 DD;

int main(void) {

u8  AA,BB;
u32 CC;
    CC = 0x12345678;

    BB =0; 
    AA = CC >> 8;
    BB |= (AA & 0x80) >> 7;
    DD = BB;
                         // AA=0x56 BB=0x68 DD=0x68  错
其实,如果看看汇编的情况,可以估计是编译器的问题

使用特权

评论回复
11
香水城| | 2009-2-1 10:25 | 只看该作者

请问,在单步操作过程中,是否看到watch窗口的内容有变化?

使用特权

评论回复
12
seawwh|  楼主 | 2009-2-1 10:29 | 只看该作者

DD 变为红色的 0x68

使用特权

评论回复
13
香水城| | 2009-2-1 10:40 | 只看该作者

请打开寄存器窗口,看看各个寄存器的变化

使用特权

评论回复
14
老狼| | 2009-2-1 12:27 | 只看该作者

不好用?

做以下实验
  将CPU 改为STM32F10x ,然后用软仿真,试一下,我的那个语句应该是正确的,如果是这样,说明你可能没有打补丁,去ST下一个吧,或者去万历的网站,因为4.42版本出来的早!(那个升级包有时候不太好用,建议直接下一个5.2的版本,重新装)

 如果还是有问题,建议将软件改为
   u8  AA=0;
   u8  BB=0;
   u8  dd=0;
   u32 CC;
   
    BB=0;
    CC = 0x12345678;
    AA = CC >> 8;
    //BB |= (AA & 0x80) >> 7;      
    dd = (AA & 0x80);   // BB=0x68
    dd=dd>>7;
    BB = BB|dd;   // BB=0x68
    一步步跟踪!

使用特权

评论回复
15
zkr| | 2009-2-1 18:00 | 只看该作者

Re

应该和C的整型位操作扩展有关系。没认真学习C标准,不知道标准对这个是怎么规定的。

但是拿8Bit进行计算的时候,有可能编译器会默认扩展到32位去算,位操作,要么强制类型转换,要么就需要去自己与上个东西缩小到合适的范围。

MISRA建议貌似是强制与范围。

使用特权

评论回复
16
mcuisp| | 2009-2-1 18:04 | 只看该作者

我没有打任何补丁.4.42版,优化None

呵呵,我也想看IAR出错呢。

使用特权

评论回复
17
seawwh|  楼主 | 2009-2-1 19:41 | 只看该作者

此问题的阶段小结


1. 下载的V5.3 (32K限制版)同样程序试验,结果OK。 正如2楼所说V5.3编译器在该指令之前加了一个UXTB指令
  UXTB
  ORRS  R3,R3,R2,LSR #7 
2. 同样一段程序在不同版本的编译器下的执行结果不一样,显然是编译器的Bug导致。而不是我们程序的表达问题。
3. 楼上老狼提出的针对4.42A的编译器的补丁,我没有找到。只是看到一些MCU器件扩充的补丁,相信这些补丁不会影响编译Bug。如果有同行发现4.42A的编译器的补丁下载,请通报一下。
4. 楼上的 mcuisp 始终没有验证这个问题,建议你看看汇编代码,是否含有UXTB指令。或者贴上你的调试画面。

Thanks

使用特权

评论回复
18
mcuisp| | 2009-2-1 23:26 | 只看该作者

同样的程序拷到万利的例子里,出现了楼主所说的Bug

呵呵。
我先前的试验里,AA/BB/CC都被分配到了SRAM里。
而万利的例子AA/BB/CC分别是R4,R5,R6

应该算是IAR的Bug了。
支持楼主!!!

使用特权

评论回复
19
lut1lut| | 2009-2-2 09:39 | 只看该作者

IAR4.42是有这个问题

我曾经找IAR的工程师确认过了,估计是前期版本的bug,在IAR5.2就好了。

所以说,请大家用最新的编译器咯。

使用特权

评论回复
20
zchong| | 2009-2-3 17:02 | 只看该作者

实验了一下,真有这个问题

太可怕了,不知道还有多少编译器隐含的问题。
为避免这类问题不知道在编程上需要注意些什么?

使用特权

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

本版积分规则

145

主题

368

帖子

0

粉丝