はじめに
NAND 型フラッシュメモリは、SSD(Solid State Drive)で使用されている新しい技術と思いがちですが、
組込み製品にはずいぶん前から搭載されていました。
ハードウェアや NAND 型フラッシュメモリを制御するソフトウェアの技術は枯れてきていますが、
何かと問題が生じやすい癖のあるデバイスです。
問題が顕著化した時に当時開発した担当者がいなければ、苦労することもしばしば。
本ページでは、そんなフラッシュメモリにまつわる話をプログラマ視点でまとめています。
そもそも NAND フラッシュとは?
NAND 型フラッシュメモリは、不揮発性記憶素子のフラッシュメモリの一種です。
よく比較される NOR 型フラッシュメモリと比べて、以下のメリットがあります。
- 回路規模が小さく、基板への実装面積を小さくできる
- 安価に大容量化できる
- バイト単位の書換えは不得意だが、書込みや消去が高速である
ポイント
USBメモリやソリッドステートドライブ(SSD)、デジタルカメラ用のメモリーカード、
携帯電話・スマホなど、様々な製品の記憶装置として使用されています。
構造
デジタルデータ(0か1)の1ビット情報を蓄積するのに必要な回路構成を「メモリセル」と呼びます。
メモリセルは、以下の図のように構成されています。

メモリセルの構造
NAND 型の場合、「シリコン基板(P型半導体)」を挟み込むように
「ソース」と「ドレイン」となるN型半導体を作ります。
そのシリコン基板の上に「トンネル酸化膜(絶縁体)」と呼ばれる薄い層を経て、
ポリシリコン製の「フローティング・ゲート(Floating Gate)を作ります。

さらに薄い酸化膜(絶縁体)を経て、「コントロール・ゲート(Control Gate)」を置きます。
フローティング・ゲート内の電子は、フローティング・ゲートを覆う酸化膜により保持されるため、
電源を供給することなくデータを保持することができる構造になっています。
単位
メモリセル(Memory Cell)
構造の章で説明したとおり、1ビットの情報を示します。単に「セル」と呼んだりもします。
セルの情報を制御するラインを「ビットライン」と呼びます。
ワードライン(Word Line)
NAND型フラッシュメモリの制御ライン数(Band Width)にもよりますが、
1バイトまたは2バイトにアクセスするラインを「ワードライン」と呼びます。
セクター(Sector)
ECC(後述)を付与する単位のことを「セクター」と呼びます。
512バイトくらいの情報を示すセルの集合です。
スペアエリア(Speare Area)
データを保持する領域の他に、スペアエリアと呼ばれる領域があります。
OOB(Out Of Band)や冗長領域と呼ぶ場合もあります。
各セクターごとに用意されていたり、各ページごとに用意されており、
ECCの値やBad Block Markerを書き込んだりします。
ページ(Page)
数セクターとスペアエリアを含む単位です。
一般的なNAND型フラッシュメモリで「読み書き(Read/Write)」できる最小の単位になります。
一般的な容量
(セクター(512バイト)+スペアエリア(16バイト))×4 = 2048バイト(Data)+64バイト(OOB)
ブロック(Block)
一定のページの集合を「ブロック」と呼びます。64ページくらいです。
一般的なNAND型フラッシュメモリで「消去(Erase)」できる最小の単位になります。
SLCとMLC
ここまでの説明では、1つのメモリセルが1ビット情報を示す場合(SLC:Single Level Cell)でした。
近年では、1つのメモリセルで2ビットを示すMLC(Multi Level Cell)や、
3ビット(TLC:Triple Level Cell)、4ビット(QLC:Quad Level Cell)などもあります。
これらはフローティング・ゲートに浮遊する電子の数(電位)を閾値で判定し、
1つのセルで表現できるビット数を増やしています。

プログラミングモデル
ここからNAND型フラッシュメモリ独特の内容になります。
記憶装置として使うわけなので、データの Read/Write を行うことができますが、
以下のような制約があります。
- Read、Write はページ単位で行う
- Write では上書きできない
- Write しなおす場合は、一度 Erase を行うことが必須
- Erase はブロック単位で行う
Read(読込み)、Write(書き込み)、Erase(消去)の3つの操作を組み合わせて
データの読み書きを行うのがNAND型フラッシュメモリの特徴です。
スポンサーリンク
書き込みの仕組み
データを書き込むには、コントロール・ゲートに電圧を引火し、
シリコン基板からフローティング・ゲートに電子を浮遊させます。
NAND型フラッシュメモリの場合は、電子が浮遊している状態で「0」を示します。
一方、書き込む前にデータを消去する場合は、
シリコン基板に電圧を引火し、浮遊している電子を抜きます。
NAND型フラッシュメモリの場合は、電子が無い状態で「1」を示します。
Bad Block
NAND型フラッシュメモリは、数億~数兆個以上のメモリセルの集合体です。
そのため、酸化膜のムラなどにより正常に使えないブロック(=Bad Block)を仕様として許容しています。
※多くて全体の2%程度で、たいていは0.5%以下
Bad Block は、Write/Read/Erase のいずれも正常に行うことができません。
これは、NANDフラッシュメモリを制御するソフトで考慮してプログラミングする必要があります。
識別情報は、各ブロックの所定位置に Bad Block Marker(BBM)が書き込まれており、
この情報を元に不良ブロックであることを識別します。

Factory Bad Block Marker(初期Bad Block)
NAND型フラッシュメモリの製造メーカーが、出荷前の検査でマーキングしているBBMです。
SLC メモリの場合、ブロック内の先頭/最終ページの最初の1バイトに書き込まれる場合が多いです。
User Bad Block Marker(後発Bad Block)
制御するソフトウェアが、正常に読み書きできなくなったことを検知した際にマーキングするBBMです。
後述する寿命問題とも関連しますが、何度かデータの読み書きを行っていると、
そのうち正常に行えなくなります。(10万回とか、そういうオーダー)
デバイスからのエラーコードや、ECC 誤り訂正範囲を超えた場合などで検知します。
スポンサーリンク
寿命問題
NAND型フラッシュメモリは、ハードウェアの構造からビット化け(Bitflip)の発生を許容しています。
ビット化けは進行性であり、長く使うほどどんどん化けやすくなります。
ビット化けが発生する原理としては、フローティング・ゲートを行き来する電子によって、
トンネル酸化膜が劣化することに起因して発生します。
ウェアレベリング(Wear Leveling)
NAND型フラッシュの劣化はブロック単位で起きるため、
チップの中のブロックを順にまんべんなく Erase/Write するような使い方をします。
しかし、何も考えずに設計すると大抵の場合は特定エリアのブロックに劣化が集中することになります。
そこで、まんべんなく劣化させるようなブロックのマッピングを行うアルゴリズムが必要になります。
これを Wear Leveling(ウェアレベリング)といいます。
リテンション(Retension)
NAND型フラッシュメモリは、一度Writeしたデータでも一定期間が経過すると
ビット化けすることを仕様として許容しています。

性能はともかく、メーカー保証のレベルでは1年も保持できれば良い方のオーダ。
またこの期間も一般的に Erase/Write 回数に応じて加速度的に悪化します。
この「Write してからどのくらいの期間を経過してもデータを正しく Read できるか」
のことを Retension(リテンション)と言います。
ポイント
この Retension 対策のため「時々関係ないところも含めてNANDフラッシュの全体をReadする」
ということをソフトウェアで行います。「時々」をどう担保するのかがプログラマからすると面倒で、
あまり Read しすぎると次の「Read Disturb」の問題を進行させてしまうので注意が必要です。
リードディスターブ(Read Disturb)
NAND型フラッシュメモリは、Read を繰り返すだけでもメモリセルに負荷をかけます。
Erase/Write ほど極端ではないですが、過度に Read を繰り返すとビット化けを起こす場合があります。
これを Read Disturb(リードディスターブ)と呼びます。
Read Disturb によるビット化けは、Retension と同じく書き直せば解決します。
しかし、過度に書き換えると寿命問題を悪化させるため、バランスを取った書き換えが必要です。
※なんてプログラマ泣かせなハードウェア仕様なんでしょうか・・・
スポンサーリンク
ECC誤り訂正
NAND型フラッシュメモリは、データがビット単位でちょっと化けるのを仕様として許容しています。
1ビット化けるなんてのははるか昔の話で、最近の MLC だと3桁ビット化けも当たり前となっています。
ビット化けに対処するため、ECC と呼ばれる値と一緒にデータを Read/Write しています。
Read 時に読み出したデータと ECC を照合し、データが化けていないことの確認や誤り訂正をしています。
一般的に、ECCの値は OOB(冗長領域)に書き込みます。
ECCの演算にはBCH符号を用いることが多く、Read/Write のスループットを上げるため、
一般的に演算はコントローラ(NANDフラッシュメモリを制御するハードウェア)側で行います。
おわりに
いかがでしたでしょうか。
これらの内容を理解してドライバーを読めば、問題が起きた場合の解析がスムーズに行えると思います。
Good Luck!
参考・出典