当前位置:编程学习 > C/C++ >>

嵌入式系统中的代码压缩

    在我们的某一个POWERPC系统中,通过总线挂接一片FPGA,和NorFlash等外设。以前我们一直是通过jtag烧写NorFlash的,速度很慢,操作也比较麻烦。现在有了PGA,tpu决定在里面放4k的代码,用于通过串口下载bootloader,并烧写到NorFlash中。这样生产时只要FPGA烧写工具就行了。
    后来,在实现时发现,4k的代码空间,放上各种功能后,已经不够了。只好把各种功能打个折,勉强塞了进去。现在,可以用xmodem协议下载bootloader,但只能直接执行,没有足够的代码空间写NorFlash了。其实,如果把4k的二进制文件,用zip等工具压缩,能压到原来的一半大小。我们也可以仿照lzss等算法,实现一个自己的压缩功能。
 
    首先,我们定义好我们的压缩方案:
    用一到两个bit做标志,描述数据流。标志凑齐一个字节就输出到数据流。
        比如:  flag data data ...... data flag data ...... data
    标志1 : 数据流中下一个字节是未压缩数据,直接输出。
    标志00: 表示一个短的前向匹配。下一个字节包含距离和长度:
            高2位是匹配长度,0-3对应2-5的匹配长度。
            低6位是匹配距离,0-63对应1-64的匹配位置。
    标志01: 表示一个长的前向匹配。下面两个字节包含距离和长度:
            高4位是匹配长度,0-15对应3-18的匹配长度。
            低4位和下一个字节是匹配距离,0-4095对应1-4096的匹配位置。
    根据这个方案,就可以开始写解压与压缩的实现了。实际测试发现,这个压缩方案,可以把PowerPC的代码,压缩到原来的65%左右。基本的硬件初始化和解压代码,大概用了512字节,剩余的3.5k空间,大概可以放5.3k的代码。这样以来,最初的设想完全可以实现了,而且很有很多的剩余空间备用。
 
 
    C语言实现的压缩代码:
 
[cpp] 
static u8 *dst, *src;  
static int dp, sp, fp;  
static int flag, bits;  
  
void put_flag(int bit)  
{  
    if(bits==8){  
        if(c_debug) printf("flag %02x at %04x\n", flag, fp);  
        dst[fp] = flag;  
        fp = dp;  
        dp += 1;  
        bits = 0;  
        flag = 0;  
    }  
  
    flag >>= 1;  
    if(bit)  
        flag |= 0x80;  
    bits += 1;  
}  
  
int tlz_compress(u8 *dst_buf, u8 *src_buf, int src_len)  
{  
    int i, j, pp;  
    int match_len, match_pos;  
  
    dst = dst_buf;  
    src = src_buf;  
    sp = 0;  
    fp = 0;  
    dp = 1;  
    bits = 0;  
    flag = 0;  
  
  
    while(sp<src_len){  
        /* find match 
         * max windows: 1-4095 1-63 
         * max length: 3-18/2-5 
         */  
        match_len = 1;  
        match_pos = 1;  
        pp = sp-4095;  
        if(pp<0)  
            pp = 0;  
        for(i=pp; i<sp; i++){  
            for(j=0; (j<18 && sp+j<src_len); j++){  
                if(src[i+j]!=src[sp+j])  
                    break;  
            }  
            if(j>=match_len){  
                match_len = j;  
                match_pos = sp-i;  
            }  
        }  
  
        if(match_len==1 || (match_len==2 && match_pos>63)){  
            /* raw byte */  
            put_flag(1);  
            if(c_debug) printf("%04x raw: %02x\n", sp, src[sp]);  
            dst[dp++] = src[sp++];  
        }else{  
            put_flag(0);  
  
            if(match_len<6 && match_pos<64){  
                /* short match */  
                put_flag(0);  
  
                if(c_debug) printf("%04x short: pos=%4d len=%2d\n", sp, match_pos, match_len);  
                sp += match_len;  
  
                match_pos -= 1;  
                match_len -= 2;  
                match_pos |= (match_len<<6);  
  
                dst[dp++] = match_pos;  
  
            }else{  
                /* long match */  
                put_flag(1);  
  
                if(c_debug) printf("%04x  long: pos=%4d len=%2d\n", sp, match_pos, match_len);  
                sp += match_len;  
  
                match_pos -= 1;  
                match_len -= 3;  
                match_pos |= (match_len<<12);  
  
                dst[dp++] = (match_pos>>8);  
                dst[dp++] = (match_pos&0xff);  
            }  
        }  
  
    }  
  
    /* end of stream */  
    put_flag(0);  
    put_flag(0);  
    dst[dp++] = 0xff;  
  <
补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,