almost 5 years ago

BBT 即 "bad block table",請參考 Nand Flash 基本介紹
以下資訊基於2.6.32 kernel,很舊了

下圖以一2048 block nand flash 來解釋 Linux 是如何將 BBT 儲存在實體的nand中。
Linux 會使用兩個block來記錄bad block資訊,一塊為primary,一塊為mirror,兩塊的bad block 資訊完全相同,只是為了安全起見多使用一個備份的block。當初始化時,系統預設從最後一個block 往前找bad block table,預設最多找4個block,如果是Linux 的bad block table block,則在該block的oob第8byte後會放置一4byte的tag作為識別,如果是primary bbt,則是"Bbt0",如果是mirror bbt 則會是"1tbB",若想定義自已的bbt位置,辨視的tag,尋找的範圍,尋找的位置,都可以在初使化時指定使用自已的bbt descriptor結構,即可達到要求。之後如果要加入的security 功能,可以考慮使用自已定義的bbt descriptor
如果要啟用這個機制,要在driver initial 時在options 中設定NAND_USE_FLASH_BBT,若沒有啟用,目前無其他替代機製

在找到BBT後,系統會將該block 讀入且轉換成內部的格式。Linux 准許外部系統使用1, 2, 4, 8 bits的資料長度記錄bad block 資訊,但在內部實際只使用兩個bits,之間的轉換和其值的意義可以參見下圖,下圖為一外部使用4bits bbt tag的例子。要注意的事reserved block 和bad block 是不能共存的,這是兩個不同的機制,reserved block 用來提醒系統,我有些block 不想被access,不一定是壞掉。目前只有看到一個driver 用這個機制,暫時不用理他

 
almost 5 years ago

本文所有的內容請參考Figure 1和Figure 2,分別為small和large page 兩種型式的基本結構


文章內容基於2011 年的資訊,現在nand flash 單顆愈做愈大,也應該有新的技術出來,以後有機會再加吧

Page

為nand flash chip 讀取的最小單位,依顆粒製程不同有512, 2048, 4096, 8192 (bytes),目前最常見的為2048 (bytes)

Spare

以2k page 為例,每一個page在實體的結構中除了2k bytes的使用空間,還會有64 bytes額外的容量,供hw/sw儲存一些額外的資訊,通常會用來儲存ecc的data,來效正nand flash使用久後會有bit不能使用的問題

OOB (out of boundary)

即指spare,sw比較常用這個名詞

Small/Large

page 容量512 bytes 的稱 small page,大於等2k bytes 都稱為large page

Block

為nand flash chip 寫入的最小單位, 每64 page 即為一個block,因為page size 會有不同,block size 也就不同,一顆chip裡有多少block,是依nand flash的大小而定,但通常是2的冪次方。

Read/Write operation

nand flash 讀寫方式異於一般的磁性儲性裝置。因為結構上的問題,如果要針對特定的page 寫入,只能把資料寫由1 -> 0,如果要0->1,那只能針對整個block (64 pages)做動作,此動作稱為”erase“,而寫入page的動作稱為”program“,一般nand chip的資料都會標明erase/program的時間,以Micro MT29F2G08AABWP為例,erase/program的時間分別為(2ms/300us)

  • write
    標準寫入動作可分為下列幾步

    1. 將block 讀進ram
    2. 改變ram裡的資料
    3. erase block
    4. 依ram 裡block 的資料,program 64 個page
  • read 則以page 為單位,無特殊的限制。

Life cycle

nand flash 相較傳統磁性的儲存裝置有較低的資料可靠度和使用限製,主要為二個方面

  • endurance
    erase block/program page 這個二動作是破壞性的,每個block erase的次數是有限制的,通常為1k~100k次

  • retention
    這是指當資料儲放在nand中,可以保証有效多久,一般是10年。所以nand flash device 不適合當長時間的資料保存裝置

Bad blcok

指在chip中資料讀取出來有可能會發生錯誤的block,依形成的原因可以分為下列二種

  • factory-bad
    即出廠時即有問題的block,每個nand chip 都會標明這個型別的顆粒至少有多少block是可以用的,而且保証第一個block一定是好的,且第一個block在某個erase/program次數不會出問題(這是為了nand boot)。nand flash 出廠時會erase 所有的block,如經檢測為bad block,則會j把那個block的第一個page的oob的第一(Micro)或第六個byte(Samung, Toshiba and 其他)標示為0xFF以外的值,每顆nand flash 在使用之前應該要先把這個值備份出來,作為以後建立bad block table時使用

  • worn-out
    即不斷使用後所產生的bad block

ECC

ECC即error correct code,因為無法預測什麼時候會發生bad block,sw上會對每個page做ecc的效正機制以防止資料錯誤,這些效正的資料的會被存在同一個page的oob裡,一般用的演算法有下列三種,每種有不同的效正能力也需要不同的ecc效正資訊,可參考下圖。另外隨著page size愈來愈大,對ECC的能力要求來愈來愈高,依innodisk 資料,硬碟型的產品,單一page ECC能力要求到7x bits

  • Hamming code
  • reed-solomum
  • binary BCH

Wear leveling

使得每個block可以寫入的次數可以大致相同延長nand使用的機制,通常由軟體或韌體負責,有分為Dynamic和static兩種方

  • Dynamic
    在要寫入資料的時候,挑選比較少使用的block來寫入,原本的那個block就回收作為以後用,這方式的缺點為,假設磁碟中有2000個block,其中1500個儲放read only data,那可以用來置換block就只剩500個。

  • Static
    收集的統計數據,在沒讀寫的時候偷偷的把資料交換到較少使用的block,此方式可以避免dynammic 的缺點,即使是read-only data 所佔據的block 也可以釋放出來使用
    由此可知nand flash based 的儲存裝置如果可用的空間等於實際的空最好不要裝滿資料,留些額外的空間做為替代用的block,可延長使用期限。但是現今實際上的產品,會限縮可使用空間。實際256GB 可用的只有240GB。

Chip ID Definition Table

每顆nand chip 容量的相關值,可以透過”read id“這個命令讀出來,舊的格式有5bytes(目前常見),新的格式有8 bytes(目前找不到),下圖為舊格式bit field的定義


BBT

Bad Block Table,用來記錄整個nand flash 顆粒中,有那些block 是壞掉的。每個nand flash 在出廠後,會先被測試機台scan一次,把壞的block資訊寫在某個特定的地方。做板子的廠商需要先把他讀出來記起來,不然後重新erase就不見了

 
almost 5 years ago

來把一些以前整理的東西放上來吧

 
almost 5 years ago

Edit your .git/config and add

[svn-remote "foo"]
    url = http://server/svn/your_project/trunk
    fetch = :refs/remotes/git-foo

git-foo is the name shown with git branch -r
then do

git svn fetch foo

done

Ref

 
almost 5 years ago

My First post in Logdown!

printf("Hello World\n");
 
over 7 years ago

最近一直努力在build toolchain,在GLIBC碰到一個不知道怎麼解的bug(segfault in __libc_start_main),轉用EGLIBC,目前起來頭好壯壯。不過同事擔心會不會有什麼問題,奉命survey一下。
EGLIBC (Embedded GLIBC)一開始應該是真的因為glibc太痴肥,在embedded的system上效能不張(西元2005是沒有cortex可用的)而發起的計畫,可參見jserv寫的"EGLIBC初探"和"EGLIBC於S3C2410 ARM SoC的體驗",但是後來2009-05-05 Debian 的maintainer Aurelien 宣布Debian以後要用EGLIBC,主要原因有:

  • More friendly upstream (especially with regard to embedded architectures): “Encourage cooperation, communication, civility, and respect among developers” (as opposed to this).
  • Stable branch with fixes for important bugs (a real one, not like the GLIBC one which is left unchanged).
  • Better support for embedded architectures.
  • Support for different shells (GLIBC only supports bash).
  • Support for building with -Os.
  • Configurable components (do we really need NIS or RPC support in debian-installer?).
  • Better testsuite for optimized or biarch packages.

    其實這都只是場面話,主要的原因是GLIBC的領導人Ulrich Drepper,是個很機車的人,怎麼機車不是很清楚,不過developer對他的形容有

  • Ulrich Drepper, is.. lets say very uncooperative when it comes to patches.
  • The maintainer of glibc (Ulrich Drepper) rules with an iron fist.
  • eglibc is a goodescape from the Fearless Leader (stated with no offense, Ulrich).
  • The switch is happening because maintainer of glibc is (I've heard) an asshole. ICBW.
  • Ulrich Drepper is a moron.
  • 比較激烈一點
    對於patches和架構有他自已堅持,以致於很多patch都不了mainline,GLIBC也有很嚴格的release procedure,一次就要搞六個月有對於某些平台的人似乎是太久了,這對Debian 這個支援許多平台的分支造成很大的困擾,所以只好fork另外一個branch出來自已maintain
    至於有什麼差別呢?目前看起來沒什麼差別,EGLIBC就是一個有拉新的patch進mainline 的GLIBC,不像GLIBC六個會有一次minor release,EGLIBC import GLIBC main release 的source code,然後就一直merge patch,所有的code要從svn上checkout下來。根據官網所言
    Embedded GLIBC (EGLIBC) is a variant of the GNU C Library (GLIBC) that is designed to work well on embedded systems. EGLIBC strives to be source and binary compatible with GLIBC. EGLIBC's goals include reduced footprint, configurable components, better support for cross-compilation and cross-testing.
    沒什麼特殊要求的話,應該可以安心使用

    COMMENT:
    AUTHOR: 雪莉
    DATE: 11/09/2010 02:11:56 PM
    IP: 122.116.222.246
    EMAIL:
    URL:
    最近剛好在看這個...感謝你的分享啦..
    不過因為eglibc 目前好像還是沒很普及,.. 還是驚驚....
    繼續委屈在uclibc 中.....

  •  
    over 7 years ago

    這星期去參加「阿魯巴國際學校"的"C級休閒獨木舟教練講習",其實只是想去玩水玩船,整理一下上課內容給大家參考一下

    報名綱址 :http://teamaruba.org/000/modules/eguide/event.php?eid=3
    facebook :http://www.facebook.com/#!/pages/zhong-hua-min-guo-du-mu-zhou-xie-hui/323508424326?ref=ts
    這次的活動照片:http://www.facebook.com/#!/album.php?aid=232829&id=323508424326&page=3
    時間:二天(約每三個月一期,冬天不一定有)
    地點:新站碧潭
    費用:1600
    第一天課程內容:早上:相關知識講解,下午:基本動作教學
    第二天課程內容:早上:練習,下午:考試
    協會提供器材:安全帽,半截式救生衣,船/槳(二人一艘,依報名組別,船型不同),鼻夾/防水裙(激流組才有)
    需自備:溯溪鞋,午餐(不然只有臭豆腐可以吃,一盤40)
    報名組別:休閒組,海洋組,激流組 (可以任意報,沒有限制)
    基本動作內容(7個):上下船,正槳(forward stroke),倒槳(reverse stroke)、掃槳(sweep, BigC)、直角左右轉,左右舵(rudder)
     休閒組:S turn
    海洋組:S turn 浮力袋救生
    激流組:askimo roll (約有1:30 練習時間)

    後續:下一梯可以來實習(不知道要不要錢,要再問問)

    心得:
    1碧潭水有時候會很濁(像我運氣就很屎)
    2 練習的時間有點少
    3askimo roll 一個半小時應該是練不起來(我報休閒組,不能練..)
    4 不能偷聽課
    5 三個組別要分開報名,沒有折價
    6如果有計畫要長期參與,而且人在北部的,可以考慮參加另外一個初級訓練班,報名費含入會費,以後有活動就以順便租船玩
    COMMENT:
    AUTHOR: joeltra72
    DATE: 09/30/2010 02:26:42 AM
    IP: 220.136.240.241
    EMAIL:
    URL: http://joeltra72.pixnet.net/blog
    我是路人甲~~~推推!!

     
    almost 8 years ago

    剛剛午餐吃好飽喔,對了,你知道嘛,阿花買了個古機包,好好喔,我們兩個從大學開始的夢想就是可以有自已一個古機包,雖然每個月還是會去五分埔逛街,不小心就會多買一個,現在我的櫃子已經放不太下,但是古機包就是了不一樣,我想如果真的買了,那我要放那呢?掛著嗎?可是我房間有時候會有螞蟻,被螞義爬過我會很心疼,而月以後如果賣價格就會掉下來了,雖然我沒講買家也不知道,但是我會心虛,古機包可是很保值的,這也是一種投資吧,不過我絕對不可能把他賣掉的,一輩子的夢說。那還是買個新櫃子來放呢?那顏色要再好好挑一下,我一直覺得櫃子的顏色跟我天花板不搭,租來的時候就是死白色,衣櫃又是要掉漆掉漆的假木頭色,一整個很奇怪,我都很怕那一天睡覺的時候木削掉到我嘴巴裡,會不會被插穿喉嚨阿,太可怕了。
    有人要我舉例,大概就是這樣,無止盡的發散

     
    about 8 years ago

    先解釋一什麼叫 Static Code Analysis(簡稱SCT好了),顧名思義:不會動的時候分析一下code。也可以看到wikipedia的條目

    這通常由自動化的工具來分析(不然,我想Code Review也算吧),主要希望能在source code 階段,發現一些邏輯上或程式相依上可以發現的潛在問題。有人會覺得這件事compiler不就會做了嗎?用gcc -Wall, 用vc /W4,開下去就幫你檢查完了。可是事實上compiler只會幫你檢查syntax是否符合語言的規範,一些邏輯上問題他不會幫你檢查,SCT就是補足這方面的不足。

    舉例以C/C++來說(引用自klocwork)
    Null Pointer dereference
    如果 x = (11 12 13 14 16 17 18 19) ,就爆了

    void foo(int* p) { 
        *p = 32;
    }
    void bar(int x) {
        int* p = NULL;
        if( x == 15 || x == 20 )
            p = &x;
        if( x > 10 && x <= 20 )
            foo(p);
    } 
    

    Buffer Overflow
    如果 data 指向的string 大小大於32 ?

    void foo(unsigned char* data) {
        unsigned char value[32];
        int len = (int)data [0];
        memcpy(value, data + 1, len);
    } 
    

    Memory Leak
    嗯,多插2G ram

    void foo() { malloc(32); }
    

    除了邏輯上的問題,SCT也可以協助檢查style的問題,比如果在constructor請問intial list 來初始化成員,或功能強一的可以檢查是否符合"Effective C++"建議的條目,並提供一些統計數據讓開發者可以對自已的程式碼品值有一定的掌控度。
    其實這種tool在早早以前就有,還記當時年紀小連class都不會寫的時候,跑去看圖書館看"C/C++ user journal"(停刊了,哭哭),側邊的廣告很多都是跟SCT相關。這樣的工具甘要錢,大概看了一下一套400us,但open source 界佛心來著,也提供了一套免錢的功能沒那麼強大工具,就是cppcheck
    我自已是使用ubuntu,apt-get裝一下就有了,使用方法非常簡單,以我pcmanx-gtk為例,0.3.9為例

    -f 是檢查所有可能條件編譯的路徑
    cppcheck --enable=all -f pcmanx-gtk/src 
    

    產生出的log大概長這樣

    Checking src/appconfig.cpp: USE_DOCKLET...
    [src/appconfig.cpp:54]: (style) Member variable not initialized in the constructor 'CAppConfig::ShowTrayIcon'
    Checking src/appconfig.cpp: USE_EXTERNAL...
    Checking src/appconfig.cpp: USE_MOUSE...
    [src/appconfig.cpp:54]: (style) Member variable not initialized in the constructor 'CAppConfig::MouseSupport'
    Checking src/appconfig.cpp: USE_PROXY...
    Checking src/appconfig.cpp: USE_WGET...
    [src/appconfig.cpp:54]: (style) Member variable not initialized in the constructor 'CAppConfig::UseWgetFiles'
    Checking src/appconfig.cpp: __GNUG__...
    1/41 files checked 2% done
    Checking src/autologinpage.cpp...
    2/41 files checked 4% done
    Checking src/configfile.cpp...
    Checking src/configfile.cpp: __GNUG__...
    3/41 files checked 7% done
    

    來看看他會檢查出什麼問題,底下是我節錄+整理的
    style

    [src/appconfig.cpp:54]: (style) Member variable not initialized in the constructor 'CAppConfig::SocketTimeout'
    [src/core/caret.cpp:32]: (style) Member variable not initialized in the constructor 'CCaret::m_GC'
    [src/core/fileutil.c:29]: (style) The scope of the variable fddest can be reduced
    [src/core/termview.cpp:895]: (style) Redundant condition. It is safe to deallocate a NULL pointer
    

    possible error

    [src/editfavdlg.cpp:147]: (possible error) Memory leak: dlg
    [src/editfavdlg.h:50]: (possible error) Memory leak: CEditFavDlg::m_List
    [src/nancy_bot/msgdata.cpp:345]: (possible error) Memory leak: vsm
    

    分析的結果只代表有修正的可能,不代表一定有錯,以memory leak 那項來說,只有2,3是真的有問題,第1個是因為gui的程式通常把child widget的釋放交給parent去做,所以不會有free的動作,還不賴吧。
    除了cppcheck,也有另一套針對C語言的SCT open source 工具 splint,但是我搞不定他的設定,有人搞定可以教我一下嘛。另外最近事業做很大的clang/llvm,也提供一套C/C++/object-c的SCT工具,裝是裝起來了,但是怎麼試都不會有檢測報告,也請用過的人教一下吧

     
    about 8 years ago

    身為一個open source 的阿宅,只有新toolchain就會很想試用看看,雖然Code Sourcery 每半年才release 一版,但有時候會需要做交插測試要換來要去。之前在晶心科技工作,在強力的toolchain team支援下,二三天就可以有一版新版,一直都缺少一個有方便的方法可以切換toolchain,想記錄一下用過的方法。
    基本的工作環境假設是連到沒有sudo 權限的server(這樣本機看叫叫叫片的時候才不會lag)

    方法一:設在 PATH 環境變數

    export PATH=$HOME/tool/gnuarm/arm-2010q1/bin:$PATH

    優點:這就是最常看到的方法 簡單,直覺,霸王硬上弓
    缺點:但如果要在同一個shell下換來換去,你的PATH 就會一次次長大,而且每次都要按tab 補齊buildtype,就是none-eabi-ooxx之類的

    方法二:用一個link指向現在要用的toolchain,PATH 一直都一樣

    export PATH=$HOME/tool/gnuarm/cur/bin #寫在 bashrc
    cd ~/tool/gnuarm/
    ln -s arm-2010q1 cur

    優點:看起來很厲害
    缺點:每次都要砍掉重link,然後command cache 要你重新export PATH 後才有效,超蠢,可是我用了很久,忍耐度超高

    方法三:在bashrc 裡寫一個小function alias toolchain

    很像這樣,看個人環境

    function nds_setup()
    {
    if [ ! -z $1 && ! -z $2]; then
    alias agcc "$2/bin/arm-$1-gcc;
    alias agcc "$2/bin/arm-$1-gcc;
    alias agcc "$2/bin/arm-$1-gcc;
    alias agcc "$2/bin/arm-$1-gcc;
    alias agcc "$2/bin/arm-$1-gcc;
    fi
    }

    $nds_setup linux $HOME/tool/gnuarm/arm-2010q1

    優點:感覺還不錯,
    缺點:實際使用時,都會忘記buildtype(其實是三不五時就在改,不是說ARM),要ls 一下才知道,然後要打二個參數,累....,另外bash 的subshell 不吃alias,下給CROSS_COMPILE 就會爛掉

    方法四:用wrapper 吃環境變數決定要選擇那個toolchain

    !/bin/bash

    arm-gcc

    if [ ! -z $ARM_TOOLPATH ]; then
    $ARM_TOOLPATH/bin/arm-$ARM_TOOLTYPE-gcc $*
    fi

    優點:指令固定,subshell 可以吃
    缺點:還是要看一下buildtype,另外toolchain 裡含binutil 大概有20隻指令,如果每個都寫一隻,之後要改會死人,還是要設二個參數

    方法五:比較厲害的wrapper
    用有點像busybox的方式,把所有的命令都link到同一隻script,再由script去分辦要執行的程式是什麼,版本為何
    優點:好像還不錯
    缺點:不知

    !/bin/bash

    set -x

    I assume

    the wrapper command format is "arm-command",

    the origin toolchain name is "arm-what-ever-you-want-gcc

    the gcc must exist

    toolname=echo ${0##/*/} | cut -d '-' -f 2;
    tooltype=ls $ARM_TOOLPATH/bin/arm-*-gcc

    if [ -z $ARM_TOOLPATH ]; then
    echo '$ARM_TOOLPATH' is not set;
    exit 1;
    fi

    if [ ! -e $tooltype ]; then
    echo "Can't find tooltype";
    exit 1;
    fi

    tooltype=${tooltype##*arm-}
    tooltype=${tooltype%%-gcc}

    realtool="$ARM_TOOLPATH/bin/arm-$tooltype-$toolname";

    if [ -z $toolname ]; then
    echo "Unknown ARM tool";
    exit 1;
    fi

    if [ ! -x $realtool ]; then
    "file is not executable"
    exit 1;
    fi

    $realtool $*

    COMMENT:
    AUTHOR: luse
    DATE: 05/18/2010 02:32:26 PM
    IP: 125.224.60.243
    EMAIL:
    URL: http://luse.blogspot.com/
    看到 function name 叫 nds 裡面卻設ARM的 toolchain XD

    版主回覆:(11/02/2009 12:55:23 AM)

    喔,沒注意到耶,Andy 哥有什麼好方法嗎?