搜索
bottom↓
回复: 19

IAR在用唯一ID加密,在Release版本下被优化掉的问题请教

[复制链接]

出0入0汤圆

发表于 2018-1-22 13:30:24 | 显示全部楼层 |阅读模式
下面是用唯一ID加密的代码, 在Debug版本下运行正常,但是Release版本下,编译器认为 U_ID 都是0xFFFFFFFF, 所以将比较的过程给优化了,每次执行都是将唯一ID写入U_ID数组中,结果这份代码失去了作用。
而如果给U_ID变量加上 volatile 关键词,U_ID将被分配到RAM区域,也不能起作用。
请教各位高手怎么样解决这个问题。
如果要说是降低优化级别的,那就算了,我发布的版本从来都是最高优化级别的。


  1. bool bFirmwareOK;


  2. void FLASH_Write(u32 Addr, const void *buff, u32 len)
  3. {
  4.         FLASH_Unlock();
  5.         //写入
  6.         u16* p=(u16*)buff;
  7.         for (int i=0;i<len;i+=2)
  8.         {
  9.                 FLASH_WaitForLastOperation(100000);
  10.                 FLASH_ClearFlag(FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPRTERR);
  11.                 FLASH_ProgramHalfWord(Addr + i , *p++);
  12.         }
  13.         FLASH_Lock();
  14. }

  15. bool CheckU_ID()
  16. {
  17.         static u32 const U_ID[3]={0xffffffff,0xffffffff,0xffffffff};
  18.         u32 const *pID=(u32*)(0x1FFFF7E8);
  19.         u32 TmpID[]={pID[0],pID[1],pID[2]};
  20.         u32 ID[3]={U_ID[0],U_ID[1],U_ID[2]};
  21.        
  22.         if (ID[0]==0xffffffff && ID[1]==0xffffffff && ID[2]==0xffffffff)
  23.         {
  24.                 FLASH_Write((u32)U_ID, TmpID, sizeof(TmpID));
  25.                 return true;
  26.         }
  27.         else if (ID[0]==TmpID[0] && ID[1]==TmpID[1] && ID[2]==TmpID[2])
  28.                 return true;
  29.         return false;
  30. }



  31. int main()
  32. {
  33.         bFirmwareOK=CheckU_ID();
  34.         if (!bFirmwareOK) return 0;

  35.         while (1)
  36.         {
  37.         }
  38. }
复制代码

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2018-1-22 13:32:32 | 显示全部楼层
加 __root关键字,好像不会被优化的

出0入0汤圆

 楼主| 发表于 2018-1-22 13:35:00 | 显示全部楼层
这是测试工程,用的IAR版本是 6703, 请各位指教

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

 楼主| 发表于 2018-1-22 13:36:49 | 显示全部楼层
xivisi 发表于 2018-1-22 13:32
加 __root关键字,好像不会被优化的

加__root关键词只是保证编译器不管这个变量用不用,都会编译进目标文件中,但还是会把判断过程优化掉

出0入442汤圆

发表于 2018-1-22 13:44:57 来自手机 | 显示全部楼层
老生常谈,加volatile在你的指针上

出0入0汤圆

发表于 2018-1-22 13:57:18 | 显示全部楼层
你这种做法肯定不行了,需要点技巧吧:
1、先定义一个整形变量flash_addr,来保存U_ID的地址,该地址肯定为FLASH的的地址
2、写加密信息时,把flash_addr强制转换成指针来操作if((*((unsigned int *)flash_addr))==0xffffffff)//第一次上电,读取该指针的内容,即为U_ID的数据
3、验证加密信息时,和第2点一样,因为代码是固定好,所以U_ID在编译前已经确定好的,程序运行时也是先把地址读出来,然后再读取该地址的内容进行比对

你代码出来在ID[0] [1] [2]的赋值,应该先取U_ID的地址,再把该地址内容赋值给ID数组

出0入0汤圆

发表于 2018-1-22 14:37:54 | 显示全部楼层
貌似要去掉const,试试

出0入0汤圆

 楼主| 发表于 2018-1-22 16:11:40 | 显示全部楼层
wye11083 发表于 2018-1-22 13:44
老生常谈,加volatile在你的指针上

加 volatile 后, U_ID数组会被分配到了RAM上

出0入0汤圆

 楼主| 发表于 2018-1-22 16:18:20 | 显示全部楼层
Jacy 发表于 2018-1-22 13:57
你这种做法肯定不行了,需要点技巧吧:
1、先定义一个整形变量flash_addr,来保存U_ID的地址,该地址肯定为 ...

改成下面这样,也没有难过编译器
bool CheckU_ID()
{
        static u32 const U_ID[3]={0xffffffff,0xffffffff,0xffffffff};
        u32 const *pID=(u32*)(0x1FFFF7E8);
        u32 TmpID[]={pID[0],pID[1],pID[2]};
       
        volatile u32 const *p = U_ID;
        if (p[0]==0xffffffff && p[1]==0xffffffff && p[2]==0xffffffff)
        {
                FLASH_Write((u32)U_ID, TmpID, sizeof(TmpID));
                return true;
        }
        else if (p[0]==TmpID[0] && p[1]==TmpID[1] && p[2]==TmpID[2])
                return true;
        return false;
}

出0入0汤圆

 楼主| 发表于 2018-1-22 16:22:50 | 显示全部楼层
Jacy 发表于 2018-1-22 13:57
你这种做法肯定不行了,需要点技巧吧:
1、先定义一个整形变量flash_addr,来保存U_ID的地址,该地址肯定为 ...

甚至下面这样还是不行

u32 GetUIDAddr()
{
        static u32 const U_ID[3]={0xffffffff,0xffffffff,0xffffffff};
        return (u32)U_ID;
}

bool CheckU_ID()
{
        u32 const *pID=(u32*)(0x1FFFF7E8);
        u32 TmpID[]={pID[0],pID[1],pID[2]};
       
        volatile u32 const *p = (u32*)GetUIDAddr();
        if (p[0]==0xffffffff && p[1]==0xffffffff && p[2]==0xffffffff)
        {
                FLASH_Write((u32)p, TmpID, sizeof(TmpID));
                return true;
        }
        else if (p[0]==TmpID[0] && p[1]==TmpID[1] && p[2]==TmpID[2])
                return true;
        return false;
}

出300入477汤圆

发表于 2018-1-22 16:31:38 | 显示全部楼层
不同的文件可以随便设置不同的优化级别啊!你把这个函数丢到单独一个文件里面,给这个文件设置低优化级别即可。不需要折腾别的了~

出0入0汤圆

发表于 2018-1-22 16:35:00 | 显示全部楼层
U_ID 不能固定到某个地址么  ?  不让编译器去指定   比如FLASH最后一个PAGE  一般很少用到把

出0入0汤圆

发表于 2018-1-22 16:59:26 | 显示全部楼层
Release会比debug优化很多的,而且每个版本还不同

出0入0汤圆

发表于 2018-1-22 17:06:40 | 显示全部楼层
U_ID不是0xffffffff?没看懂。

出0入0汤圆

发表于 2018-1-22 17:14:28 | 显示全部楼层
dwj0 发表于 2018-1-22 16:22
甚至下面这样还是不行

u32 GetUIDAddr()

/************************************************************************/
//                      author:Jacy Huang                                              
//                      email :j.c-h@qq.com                                      
//                                                                        
/************************************************************************/
#include "platform_flash.h"

#define FLASH_PROTECT


const unsigned int seData = 0xffffffff;

unsigned int seAddr = 0;
unsigned int Fml_Constant = 0x2234ADAA;
unsigned char *C= (unsigned char*)&Fml_Constant;
unsigned char *Uid = (unsigned char *)(0x100007F4);
unsigned short Fml_CRC16;





unsigned short Formula_CRC16(unsigned char *p,unsigned char len)
{
        unsigned char i;
        while(len--)
        {
                for(i=0x80; i!=0; i>>=1)
                {
                        if((Fml_CRC16 & 0x8000) != 0)
                        {
                                Fml_CRC16 <<= 1;
                                Fml_CRC16 ^= 0x1021;
                        }
                        else
                        {
                                Fml_CRC16 <<= 1;
                        }
                         if((*p&i)!=0)
                        {
                                Fml_CRC16 ^= 0x1021;
                        }
                }
                p++;
        }
        return Fml_CRC16;
}

void Formula_102(unsigned char *D,unsigned char *Result)
{
        unsigned char *crc;
        unsigned short dat;
        crc = (unsigned char*)&dat;
        Fml_CRC16 = 0;
        dat = Formula_CRC16(D,6);
        Result[0] = C[0] ^ crc[0];
        Result[1] = C[1] ^ crc[1];
        Result[2] = C[2] ^ crc[1];
        Result[3] = C[3] ^ crc[0];
}

   
unsigned short CheckUid(void)
{
#ifdef FLASH_PROTECT
        unsigned int Result;
        unsigned int se;
        unsigned char D[6];
        D[0] = Uid[0];
        D[1] = Uid[4];
        D[2] = Uid[3];
        D[3] = Uid[5];
        D[4] = Uid[1];
        D[5] = Uid[2];
    se = *((unsigned int *)seAddr);
        Formula_102(D, (unsigned char *)&Result);
        if(Result != se)
        {
                return 0;
        }
#endif
        return 1;
}

void UID_Secure(void)
{
#ifdef FLASH_PROTECT
        unsigned char D[6];
        unsigned int Result;
        D[0] = Uid[0];
        D[1] = Uid[4];
        D[2] = Uid[3];
        D[3] = Uid[5];
        D[4] = Uid[1];
        D[5] = Uid[2];
        Formula_102(D, (unsigned char *)&Result);
    seAddr = (unsigned int)(&seData);   
        if((*((unsigned int *)seAddr))==0xffffffff)//第一次上电
        {
                platform_write_word(seAddr, Result);
        }
#endif
}

出0入0汤圆

发表于 2018-1-22 17:17:03 | 显示全部楼层
  1. #pragma optimize
复制代码


指定优化等级。

出0入0汤圆

发表于 2018-1-23 21:00:42 | 显示全部楼层
#pragma optimize=none

出0入0汤圆

 楼主| 发表于 2018-1-24 08:47:37 | 显示全部楼层

我试了,指定函数的优化等级可以解决。
但我还是想在代码上找方案

出0入0汤圆

发表于 2018-1-24 14:54:19 | 显示全部楼层
static u32 const U_ID[3]={0xffffffff,0xffffffff,0xffffffff}; 楼主这句话本身就有问题啊,没错重启等于都是重新赋值了U_ID的值,怎么可能不优化掉你的if语句

出0入0汤圆

发表于 2018-1-24 14:57:43 | 显示全部楼层
2种方法解决楼主的问题:
1、将U_ID定义到固定的地址上,不用赋值;
2、每次上电前读取芯片UID地址的实际数据赋值给U_ID数组
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-3-29 01:18

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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