现在的位置: 首页 > 综合 > 正文

計算CRC32和CRC16的小工具(主要用於驗證FLASH燒錄的正確性)

2013年09月15日 ⁄ 综合 ⁄ 共 2543字 ⁄ 字号 评论关闭

寫了一個小程序,主要用於驗證FLASH是否燒錄成功。應用場景是這樣的,工廠會將MCU的Firmware直接燒到Flash里,通常這個固件小於Flash的大小,燒錄進去的時候,空白區域會被填充“0xFF”,這個小工具就是驗證燒錄進去的Flash是否正確的。

代碼中使用了他人開源的CRC表生成算法,請參見這篇文章

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <libgen.h>

#define P_16 0xA001
#define P_32 0xEDB88320L
#define FILE_SIZE 1024*1024*16

typedef enum
{
	CRC32=0,
	CRC16
}CRCTYPE;

static uint8_t crcbuf[16384];
static uint16_t crc_tab16[256];
static uint32_t crc_tab32[256];

static void init_crc16_tab(void);
static void init_crc32_tab(void);

uint32_t get_crc16(uint32_t crcinit, uint8_t * bs, uint32_t bssize);
uint32_t get_crc32(uint32_t crcinit, uint8_t * bs, uint32_t bssize);
uint32_t GetFileCRC(int fd,int type);

static void init_crc16_tab(void)
{
    int i, j;
    unsigned short crc, c;

    for (i=0; i<256; i++)
    {
        crc = 0;
        c   = (unsigned short) i;
        for (j=0; j<8; j++)
        {
            if ((crc ^ c) & 0x0001)
            	crc = ( crc >> 1 ) ^ P_16;
            else
            	crc = crc >> 1;
            c = c >> 1;
        }
        crc_tab16[i] = crc;
    }
}  /* init_crc16_tab */

static void init_crc32_tab( void ) {

    int i, j;
    unsigned long crc;

    for (i=0; i<256; i++)
    {
        crc = (unsigned long)i;
        for (j=0; j<8; j++) 
        {
            if ( crc & 0x00000001L )
            	crc = ( crc >> 1 ) ^ P_32;
            else      
            	crc = crc >> 1;
        }
        crc_tab32[i] = crc;
    }
}  /* init_crc32_tab */

uint32_t get_crc16(uint32_t crcinit, uint8_t * bs, uint32_t bssize)
{
	uint32_t crc = 0;
	
	init_crc16_tab();
	while(bssize--)
	{
		crc=(crc >> 8)^crc_tab16[(crc & 0xff) ^ *bs++];
	}

	return crc;
}

uint32_t get_crc32(uint32_t crcinit, uint8_t * bs, uint32_t bssize)
{
	uint32_t crc = crcinit^0xffffffff;
	
	init_crc32_tab();
	while(bssize--)
	{
		crc=(crc >> 8)^crc_tab32[(crc & 0xff) ^ *bs++];
	}

	return crc^0xffffffff;
}

uint32_t GetFileCRC(int fd,int type)
{
	uint32_t rdlen;
	uint32_t crc = 0;
	
	uint32_t (*get_crc)(uint32_t crcinit, uint8_t * bs, uint32_t bssize);
	
	switch(type)
	{
		case CRC32:
			get_crc=get_crc32;
			break;
		case CRC16:
			get_crc=get_crc16;
			break;
		default:
			get_crc=get_crc32;
			break;
	}
	
	while((rdlen = read(fd, crcbuf, 4096)) > 0)
	{
		crc = get_crc(crc, crcbuf, rdlen);
	}

	return crc;
}

int main(int argc,char **argv)
{
	int fd;
	unsigned int value=0;
	int bytes_read=0,bin_size=0;
	unsigned char *buf;
	
	if(argc<3)
	{
		printf("Usage: %s file 32/16\n",basename(argv[0]));
		exit(1);
	}
	
	if((fd=open(argv[1],O_RDONLY))==-1)	
	{
		perror("Error:");
		exit(1);
	}
	
	if(argc>3)
	{
		bin_size=atoi(argv[3]);
		bin_size=(bin_size>FILE_SIZE?FILE_SIZE:bin_size);
	}
		
	buf=malloc(FILE_SIZE);
	memset(buf,0xFF,FILE_SIZE);
	
	bytes_read=read(fd,buf,FILE_SIZE);
	printf("File length: %d\n",bytes_read);
	
	if(strncmp(argv[2],"32",2)==0)
	{
		value=get_crc32(0,buf,(bytes_read>bin_size?bytes_read:bin_size));	/* crc32 */
		/* value=GetFileCRC(fd,CRC32); */
	}
	else
	{
		value=get_crc16(0,buf,(bytes_read>bin_size?bytes_read:bin_size));	/* crc16 */
		/* value=GetFileCRC(fd,CRC16); */
	}
			
	printf("CRC: %X\n",value);
	if(buf!=NULL)
		free(buf);
	close(fd);
	return 0;
}

這篇文章提供的代碼中還包含其它類型的CRC算法,值得收藏。

抱歉!评论已关闭.