IAR4.42AForSTM32的危险Bug!

sealfox   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高版本的同行可以试验一下,是否改掉了这个错误。

回复评论 (35)

不可能吧!

ORRS  R3,R3,R2,LSR #7 前面应该还有条UXTB指令
EWARM5.20上没有问题!
点赞  2009-1-31 20:30

我试过结果是正确的呢。

                                  
点赞  2009-2-1 00:07

测试的屏幕拷贝

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  错
点赞  2009-2-1 01:12

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

                                  
点赞  2009-2-1 01:37

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

                                 我再试仍对。
点赞  2009-2-1 03:31

看这个AA BB变量

                                 就知道肯定是lz愚蠢的错误
点赞  2009-2-1 09:19

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

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

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

楼上老狼提出的使用下面的语句
BB |= ((AA & 0x80) >> 7);
其结果 BB=0x68 仍然是错的
点赞  2009-2-1 09:34

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

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

请使用全局变量定义AA和BB,然后再操作结束后再观察Watch窗口。
点赞  2009-2-1 09:44

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

我设计了一个全局变量 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  错
其实,如果看看汇编的情况,可以估计是编译器的问题
点赞  2009-2-1 10:21

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

                                  
点赞  2009-2-1 10:25

DD 变为红色的 0x68

                                  
点赞  2009-2-1 10:29

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

                                  
点赞  2009-2-1 10:40

不好用?

做以下实验
  将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
    一步步跟踪!
点赞  2009-2-1 12:27

Re

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

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

MISRA建议貌似是强制与范围。
点赞  2009-2-1 18:00

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

                                 呵呵,我也想看IAR出错呢。
点赞  2009-2-1 18:04

此问题的阶段小结


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

点赞  2009-2-1 19:41

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

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

应该算是IAR的Bug了。
支持楼主!!!
点赞  2009-2-1 23:26

IAR4.42是有这个问题

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

所以说,请大家用最新的编译器咯。
点赞  2009-2-2 09:39

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

太可怕了,不知道还有多少编译器隐含的问题。
为避免这类问题不知道在编程上需要注意些什么?
点赞  2009-2-3 17:02
12下一页
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复