打印

请教香主,STM32有内置的硬件CRC计算单元吗?

[复制链接]
7776|18
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
成成|  楼主 | 2009-3-17 23:14 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
请问香主,我在www.stmfans.com里面看到了一个帖子说STM32有内置的硬件CRC计算单元,我在库文件、datasheet上都没有找到。

请问真是的是有吗?如果有,在那个模块?
stmfans的链接如下:
http://www.stmfans.com/bbs/viewthread.php?tid=325&highlight=crc
沙发
香水城| | 2009-3-17 23:16 | 只看该作者

STM32有内置的硬件CRC计算单元

1)请看最新的参考手册 RM0008
2)请看最新的固件库

使用特权

评论回复
板凳
hotpower| | 2009-3-17 23:20 | 只看该作者

哈哈~~~看来俺要失业了~~~stm32的crc有逆运算吗?

使用特权

评论回复
地板
香水城| | 2009-3-17 23:21 | 只看该作者

回大叔:非也

啥叫逆运算?

使用特权

评论回复
5
hotpower| | 2009-3-17 23:24 | 只看该作者

哈哈~~~没看见前些日子的“CRC战斗”???



使用特权

评论回复
6
hotpower| | 2009-3-17 23:27 | 只看该作者

帮俺验证一下~~~

使用特权

评论回复
7
香水城| | 2009-3-17 23:27 | 只看该作者

只看见那边刀光剑影,没敢靠近,只敢远远眺望,看不仔细

怕被流弹击中。

谢谢大叔奉献秘籍,俺一定抽空研究一番。

使用特权

评论回复
8
hotpower| | 2009-3-17 23:32 | 只看该作者

找了几个数学家说晕,准备找密码学家论证一番~~~


HotC51 发表于 2009-3-8 15:03 裸奔式实时操作系统HotTask51 ←返回版面   

楼主: HotC51共产儿童团第十四课:HotWC3密码设计原理及其“天地巧合”

先祝大家节日愉快~~~

开课:(此课比较晕)

HotWC3密码是由星期(Week)算法、循环冗余码(CRC)、三角(Triangle)密码这三部分基本元素构成。

故简称WC3密码。

由于此密码算法依据菜农自己推导的菜农星期公式群魔乱舞的CRC密码和原创
三角密码作为算法之根基,故自称为HotWC3密码。

1. HotWC3密码强度。

基本的HotWC3密码为BCD码格式的万年历日期表达式,占用四个字节。
由于400年为20871周,故10000年=20871*25*7=521775*7=3652425

大约为2^22不到。就认为HotWC3是21位密码吧。但可再加入多位密码,来增加
密码强度。这里只讨论基本HotWC3.

形象点说银**为6位十进制密码,范围为0~999999
而HotWC3为8位BCD密码,实际10进制范围为0~3652424

2. HotWC3密码的设计原理
HotWC3为8位BCD密码bDate[4],分别表示 百年:年:月:日。
例如:BDate[]={0x20,0x09,0x03,0x05}

1)星期变换
为了使密码收敛,即将长密码得到一个极短的唯一码。
而万年历内的某年某月某日即可得到一个确定的星期Week(0~6,0表示星期日)

例如:BDate[]={0x20,0x09,0x03,0x05} 得到Keek=0x04

由于BDate为BCD码,故星期变异后,即W17=16*Week+Week=17*Week
将其累加的BDate上,即完成日期变异,即wDate[N]=BDate[N]+W17.

例如:BDate[]={0x20,0x09,0x03,0x05} 得到Keek=0x04
W17=16*Week+Week=17*Week=(Week<<4)| Week=0x44 
wDate[]={0x64,0x4d,0x47,0x49}

这样wDate就成了包含星期的日期表达式,此可谓“天地巧合”。
这就是HotWC3要求BCD格式的最重要的原因~~~

2)星期密钥
HotWC3需要一个内部的加密和解密“公钥”,而且不能从密码中推算出来。
HotWC3选用万年历做密码,得到的星期数大约为521775/7=74539个。
故不可能从星期推算出万年历密码。

HotWC3的星期密钥Key为W17与wDate[4]这5个数的异或结果。
wDate[]={0x64,0x4d,0x47,0x49}
W17=0x44
Key=0x63.

可以看出,从Key里看不出任何BDate的痕迹。
Key将作用于三角变换的输入,输出及密文的输出方面。

Key也对CRC运算结果施加影响,同时CRC运算结果又将作为下次
三角变换的输入。形成“闭环”的效果。

这样不解开Key就无法得出正确的结果。

由于HotWC3的星期密钥Key为W17与wDate[4]这5个数的异或结果。
每四个为一组。那么

在n=0时,Key XOR wDate[0]即需要百年、年、月及星期的影响。
在n=1时,Key XOR wDate[1]即需要百年、年、日及星期的影响。
在n=2时,Key XOR wDate[2]即需要百年、月、日及星期的影响。
在n=3时,Key XOR wDate[3]即需要年、月、日及星期的影响。

故解密时,每个密文字符实际都需要对应位的密码信息。
而星期密钥是最关键的,但星期却是不可逆的,即从星期是推不出
日期的~~~

这样逆向者即解密者只能用穷举法来**HotWC3密码,这正是菜农
梦寐以求的~~~

3)三角变换
因为在一个直角三角形中,已知一个整数直角边,则必有唯一一对的整数
直角边和斜边。早有苏联数学家进行过推论,菜农不过进行了形象话的解释。

本来 a^2 + b^2 = c^2 需要知道a,b才能算出c,否则有无穷多组解。
但是,在“直角三角形”和全为“整数边”这两个隐藏很深的“条件”下,
只需知道一个整数直角边,即可得到另一直角边和斜边。

用一个参数“扩散出”2个参数,这正是CRC运算所需求的,如“初值”和“权”

即:当一直角边为奇数时,平方砍半。
    例勾3股4弦5   3^2=9  9/2=4,5    即3^2+4^2=5^2

    当一直角边为偶数时,砍半平方再拉手。  
    例股4勾3弦5   4/2=2 2^2=4 3(4)5      即4^2+3^2=5^2

关于三角密码,这里不用多说,总之一个字节的三角值会“发散”为两个字节。

为了避免平方和开方运算,菜农特编写了《三角变换表》,这样只需给出
需要变换的三角值,查表可得出唯一的三角变换值。

三角变换值为2个字节,可作为每次CRC8运算的“初值”和“权”。
由于其不可能相等(直角边不等于斜边),故可比较其大小来确定CRC运算的“方向”~~~

再将“初值”和“权”相异或且再与星期密钥相异或后,即得到“三角密钥”。

4)CRC密码

CRC密码是菜农“私自”改动了其CRC运算架构来满足菜农对“CRC可逆”的需求。

这样任何(群魔乱舞的CRC)CRC即可进行加密和解密运算,可以从菜农发布的
《CRC/PEC网上计算器》看到其“可逆”之处~~~

这样,我们即可根据CRC的“三要素”:初值、权和方向。
正运算出CRC的结果,即加密过程。
逆还原出CRC的原貌,即解密过程。

“群魔乱舞的CRC”中的“权”是菜农领悟CRC后对其作出的“扩展”。
这样我们就没必要受制于X8+X5+X4+X0,X16+X12+X5+X0等束缚和制约。

这样即可作为CRC密码的初值和权即CRC密钥来实现CRC的可逆运算
即加密和解密过程。

HotWC3算法中的星期和三角变换的收敛和扩散都是起保护CRC“三要素”的作用。

5)密文输出
CRC运算的结果再异或星期密钥后作为真正的密文输出。
这样更深地掩盖了密文和星期、CRC及三角变换之间的关系。

HotWC3的设计宗旨:让逆向者只能通过“基于密钥攻击”(晕,知道密码还叫攻击)

这样的设计,使逆向者无法“基于明文攻击”或“基于密文攻击”。

哈哈~~~

祝大家“三八”愉快~~~

课毕

HotC51@126.com   2009.3.8于菜地。
团部:http://group.**/1623/

使用特权

评论回复
9
成成|  楼主 | 2009-3-19 09:14 | 只看该作者

16位的CRC,有没有办法?

如果想使用16位的CRC,能用STM32的CRC自动生成吗?怎么用?

使用特权

评论回复
10
香水城| | 2009-3-19 09:29 | 只看该作者

回9楼:请看STM32固件库中有如何使用内置硬件CRC计算单元的

STM32固件库可以在ST网站下载:

使用特权

评论回复
11
ijk| | 2009-3-19 09:44 | 只看该作者

16位的CRC

  16位的CRC,常用的生成多项式应该有2种,初值也有0x0000或者0xFFFF,印象里STM32只支持一种生成多项式,并且初值也只支持一种。
  建议注意一下。

使用特权

评论回复
12
成成|  楼主 | 2009-3-23 10:55 | 只看该作者

CRC的问题

请问香主,
是不是所有的STM32F10X都支持32bit的CRC?我用的处理器是STM32F103RBT6,在调试的时候发现对CRC->CR进行写操作时(也就是复位CRC),发现对别的模块有影响(目前发现有影响的模块是TIMER2,不知道别的模块还有没有)。

另外为什么用keil C调试时,发现里面没有CRC这个外设模块?

另外还有一个问题就是CRC模块中的IDR寄存器干嘛用的?计算用32位的,整个8位寄存器起什么作用呢?

使用特权

评论回复
13
香水城| | 2009-3-23 11:10 | 只看该作者

关于CRC的问题

我用的处理器是STM32F103RBT6,在调试的时候发现对CRC->CR进行写操作时(也就是复位CRC),发现对别的模块有影响(目前发现有影响的模块是TIMER2,不知道别的模块还有没有)。

请详细说明如何影响TIM2,最好贴出你的测试程序。


为什么用keil C调试时,发现里面没有CRC这个外设模块?

CRC模块是芯片内部的功能,与调试软件没有关系。“里面没有”是什么意思?没有模拟还是没有什么?不管怎样,肯定是KEIL软件的问题。


IDR寄存器是用于某种特定的算法,它独立于CRC计算,一般用不到,你可以不用管它。

使用特权

评论回复
14
成成|  楼主 | 2009-3-30 18:11 | 只看该作者

再问香主,关于CRC的问题

之前不能使用CRC模块的原因找到了,是忘记设置CRC模块的时钟。

但是现在又遇到一个新问题,用STM32的CRC进行效验得出了一个结果,并且记录下来后,但是用上位机的软件怎么也计算不出来STM32的结果。请问你们的算法是什么?能否提供以下你们的算法代码。

我的PC机程序在附上,这些算法是从网站download下来的,不问题出在哪里,请香主帮忙看看。

DWORD CRC_32(BYTE * DataBuf,unsigned long len)
{
    unsigned long oldcrc32;
    unsigned long crc32;
    unsigned long oldcrc;
    unsigned int charcnt;
    char c,t;

    oldcrc32 = 0xFFFFFFFF; //初值为0
    charcnt=0;
    while (len--) 
    {
        t= (oldcrc32 >> 24) & 0xFF; //要移出的字节的值
        oldcrc=Table_CRC[t]; //根据移出的字节的值查表
        c=DataBuf[charcnt]; //新移进来的字节值
        oldcrc32= (oldcrc32 << 8) | c; //将新移进来的字节值添在寄存器末字节中
        oldcrc32=oldcrc32^oldcrc; //将寄存器与查出的值进行xor 运算
        charcnt++;
    }
    crc32=oldcrc32;
    return crc32;
}


unsigned long int ulPolynomial = 0x04c11db7;
unsigned long int Reflect(unsigned long int ref, char ch)
{
    unsigned long int value(0);
    // 交换bit0 和bit7,bit1 和bit6,类推
    for(int i = 1; i < (ch + 1); i++)
    {
        if(ref & 1)
        value |= 1 << (ch - i);
        ref >>= 1; 
    }
    return value;
}

void BuildTable32(void)

    unsigned long int crc,temp;
    // 256 个值
    for(int i = 0; i <= 0xFF; i++)
    { 
        temp=Reflect(i, 8);
        Table_CRC= temp<< 24;
        for (int j = 0; j < 8; j++)
        {
            unsigned long int t1,t2;
            unsigned long int flag=Table_CRC&0x80000000;
            t1=(Table_CRC << 1);
            if(flag==0)
            t2=0;
            else
            t2=ulPolynomial;
            Table_CRC =t1^t2 ; 
        }
        crc=Table_CRC;
        Table_CRC = Reflect(Table_CRC, 32);
    }
}

使用特权

评论回复
15
香水城| | 2009-3-30 18:17 | 只看该作者

最好先看看手册

使用特权

评论回复
16
成成|  楼主 | 2009-3-30 20:00 | 只看该作者

我也是看了手册了的

不知道你注意到我的代码了吗?我的代码中已经有多项式设计,而且这个多项式与datasheet中相同。但是计算结果就是算得不一样,不知何解?
https://bbs.21ic.com/upfiles/img/20093/200933019554295.gif

 

使用特权

评论回复
17
成成|  楼主 | 2009-3-31 16:08 | 只看该作者

我用STM32算出来的结果和程序算出来的结果都不一样

STM32:
1、把STM32的寄存器复位,复位后的值为0xFFFFFFFF
2、按照双字操作方式,直接把0xA5A5A5A5写入DR寄存器
3、读取DR的结果为:0x29928E70
这跟Netjob你给的结果不一样

我的算法计算出的结果是:0xF9494ABA
这也跟Netjob你给的结果不一样

使用特权

评论回复
18
成成|  楼主 | 2009-4-1 09:15 | 只看该作者

硬件代码

/*
************************************************************
    函数名        CRC_WriteInfoTab
    功能        存储信息表,并计算CRC填充到信息表的最后
    输入参数    pDes    --  存储的信息表开始地址
                pSrc    --  信息表的开始地址
                Len        --  信息表的字节长度,注意是字节
    输出参数    UINT8 0    --  成功
                    非零--  错误代码
    调用        无
    变量        无
    注意        此函数的调用,CRC是存放在最后的4个字节
************************************************************
*/
UINT8 CRCChk_WriteInfo(UINT8 *pDes, UINT8 *pSrc, INT32 Len)
{
    UINT8 ucTmp;
    
    // 最后4个字节是CRC
    Len -= 4;

    // 参数检查
    if((pDes == 0) || (pSrc == 0) || (Len <0))
        return CRC_PARAERR;
    
    // 计算少于4个字节的字节数
    ucTmp = (UINT8)(Len & 0x3);
    
    CRC_ResetDR();        // 复位CRC初值,0xFFFFFFFF
    
    // 先把4个字节长度的双字处理
    Len >>= 2;
    while(Len>0)
    {
        *(UINT32*)pDes = *(UINT32*)pSrc;
        CRC->DR = *(UINT32*)pSrc;
        pDes += 4;
        pSrc += 4;
        Len--;
    }
    
    if(ucTmp != 0)
    {
        // 把余下的1~3个字节处理
        if(ucTmp == 1)
        {
            CRC->DR = (*(UINT8 *)pSrc) & 0x000000FF;
            *pDes++ = *pSrc++;
        }
        else if(ucTmp == 2)
        {
            CRC->DR = (*(UINT16*)pSrc) & 0x0000FFFF;
            *pDes++ = *pSrc++;
            *pDes++ = *pSrc++;
        }
        else if(ucTmp == 3)
        {
            CRC->DR = (*(UINT32*)pSrc) & 0x00FFFFFF;
            *pDes++ = *pSrc++;
            *pDes++ = *pSrc++;
            *pDes++ = *pSrc++;
        }
    }
    
    // 判断把计算出来的CRC存放于最后的4个字节
    *(UINT32*)pDes = CRC->DR;
    
    return CRC_OK;
}

使用特权

评论回复
19
成成|  楼主 | 2009-4-1 17:13 | 只看该作者

我确实是把4个字节一起给硬件算的

在STM32的算法当中,我确实是把4个字节一起发给硬件来计算的。但是软件的算法就是一个一个字节算的,为了验证另外一种可能性,所以我用硬件实现单个字节的计算方式以比较(仅仅是用于比较而已,没有在程序用)是否能够跟Netjob的计算结果相同。

你的STM32怎么没有CRC模块呢?我看了文档,所有的STM32都有这个模块呢

使用特权

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

本版积分规则

13

主题

56

帖子

0

粉丝