uboot 和linux 下flash 写入速度差异分析

韩大卫@吉林师范大学

2015.1.27. 

转载请表明出处

*********************************************


uboot 和linux 下flash 的写入速度不一样, 主要原因是两者使用的延迟最小延时时间不一样. linux比较大. 原因如下:

flash 芯片手册中有两个重要的时间参数:



技术分享

技术分享


第一个是一般的块写入超时时间, 记为time-ty, 第二个是最大的块写入超时时间, 记为time-max. 

假设有两个CFI nor flash 芯片, A 的time-ty 为10, B 的time-ty 为8 ; A, B 的time-max 都为2.

下面会看到, 在uboot 下, A, B 的flash 写入速度差异很小. 但在linux 下, A和B的flash 写入时间有很大的差异. 假设时钟均稳定. 


uboot中的算法:


1,先得出超时时间  info->buffer_write_tout :

        info->buffer_write_tout = (((1 << time-ty) *   (1 << time-max)) + 999) / 1000;


A的flash : time-ty = 10, time-max = 2,  计算得  5 ms

B 的flash : time-ty = 8, time-max = 2,  计算得  2  ms


2, 再使用  info->buffer_write_tout :


 while (1) {

...

        if (ready)  //这个标志表示写指令已经完成,   

            break;

        if (get_timer() > info->buffer_write_tout) {

            return ERR_TIMOUT;

        }         

        udelay(1); //每次使用1 us 的延时, 直到出现 ready 退出循环. 一般地, 写指令的执行时间不会等到buffer_write_tout这么长时间就会成功, 因此很块快跳出循环

}

uboot写flash 时使用的延时都是在 us 级别的. 所以用户几乎感觉不到flash "Typical timeout for maximum size buffer program  " 时间参数不同所造成的影响. 


linux 下的延时时间:


1, 先得出chip->buffer_write_time

chips[i].buffer_write_time = 1<<time-ty; 


A : buffer_write_time = 1024 us

B : buffer_write_time = 256 us


2, linux 使用 buffer_write_time  作为最小延时函数的变量 :


static inline void cfi_udelay(int us){

    if (us >= 1000) { //A的buffer_write_time 为1024, 使用msleep 延时, 时间单位为 ms

        msleep((us+999)/1000);

    } else {

        udelay(us); // B 的buffer_write_time 为256, 使用udelay 延时, 时间单位为 us

        cond_resched();

    }

}


可以看到, 由于A和B 的flash 的 "Typical timeout for maximum size buffer program  " 参数不一样.  会导致了底层使用的延时函数差异很大. 

这就是在linux 下flash 的写入时间会有很大的差异的原因. 


备注:


一个 flash 芯片实例信息:


vendor ID is  2 (AMD 系列)

manufacturer id is 0x89

device id is 0x7e

device id2 is 0x2201

cfi version is 0x3133

芯片大小: 33554687 B, 32MB

扇区个数  256 

扇区大小/一次可以缓存擦写大小: 131072 B, 128KB

缓存写等待时间: 1024 us

缓存写最大时间: 4096 us



以上可以参考uboot/linux/openwrt的源代码:


uboot:


drivers/mtd/cfi_flash.c  (cfi 规范的flash驱动)

common/cmd_flash.c (uboot 的upgrade 命令的实现) 


linux:


drivers/mtd/chips/cfi_probe.c (CFI 规范通用驱动入口)

drivers/mtd/chips/cfi_cmdset_0002.c (AMD 规范flash驱动)

arch/mips/cavium-octeon/flash_setup.c (octeon平台flash驱动)

drivers/mtd/cmdlinepart.c (解析分区)

drivers/mtd/mtdpart.c (系统mtd操作调用中心)



openwrt:

package/mtd/src/mtd.c (mtd 工具的源代码)


郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。