天天看點

uboot 和linux 下flash 寫入速度差異分析

韓大衛@吉林師範大學

2015.1.27. 

轉載請表明出處

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

uboot 和linux 下flash 的寫入速度不一樣, 主要原因是兩者使用的延遲最小延時時間不一樣. linux比較大. 原因如下:

flash 晶片手冊中有兩個重要的時間參數:

uboot 和linux 下flash 寫入速度差異分析
uboot 和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 工具的源代碼)

繼續閱讀