周未无事,发一段原创:
目前大多数CPU内置有Flash存储器,用于存放可执行代码。但由于Flash的可变性及运行环境复杂多变,如能在上电前对Flash中的数据进行一次全面检查是负责的做法。
IAR 为此功能提供了方便,在代码最后链接时,将对所有烧写在Flash中的代码运行CRC运算,并将结果保存在Flash存储器中。复位上电后从Flash引导,并执行位于Flash前部份的一小段自检代码,对整个Flash进行CRC运算。最终将结果与处于未尾的、由IAR链接时自动计算的CRC进行比较,如果匹配,则认为正常,否则进入出错处理。
有人可能说复位后先运行的就是Flash的代码,如果错误就在这一段呢?如果芯片只能从Flash引导,那就没有完美的方法了,只能说能减小运行出错代码的概率。就STM32来说,还有一种选择,那就是专门做一版掩膜~~~~
先看看IAR的帮助说明:
Generate checksum
Use Generate checksum to checksum all generated raw data bytes. This option can only be used if the Fill unused code memory option has been specified.
The linker will place the checksum byte(s) at the __checksum label in the CHECKSUM segment. This segment must be placed using the segment placement options like any other segment.
下面说说实现方法:
首先修改链接文件*.XCL,我们定义ROM的起始地址:
//定义ROM的开始和结束 -DROMSTART=0x8000000 -DROMEND=0x8007FFF // 将checksum放在最后 -Z(CODE)CHECKSUM#ROMSTART-ROMEND
注意到-Z(CODE)CHECKSUM#ROMSTART-ROMEND这个定义,中间使用了#页非一般的=,#表示从后往前堆放,=表示从前往后放。关于链接文件的详细定义,可以参看IAR帮助里的 xlink.pdf
0x8000000是STM32内部Flash的起始地址,注意不同容量的芯片有不同结束地址,要根据实际情况定义。
程序中增加一段定义:
extern u32 ROMSTART; extern u32 ROMEND; #define ROM_START ((u8 *)(&ROMSTART)) #define ROM_SIZE ((u32)&ROMEND -2 -(u32)&ROMSTART +1) #define REF_CRC16 __checksum
接着在程序中增加一段检测代码:
main() { // ......
if(calc_crc16(0,(u8 *)ROM_START, ROM_SIZE) != REF_CRC16) { // error while(1); } // pass
// ...... }
CRC有多种算式,可以选择IAR默认的,参考xlink.pdf实现,也可以把快算表计算出来,用查表方式实现: u16 calc_crc16(u16 sum, uc8 *p, u32 len) { while (len--) { sum = crc16_table[(sum >> 8) ^ *p++] ^ (sum << 8); } return sum; }
最后设置IAR,让他在链接时产生CRC:
Project->Option->Linker->Processing->Fill unused code memory(select)->General checksum(select)->2byte->CRC16(0x11021)->as it->MSB first->alignment(1)->initail(0) |