Tüm eğitimler
TEKNİK REHBER GÖMÜLÜ LİNUX FLASH 2026

MTD · UBI · UBIFS
Flash Yönetimi

NOR/NAND flash belleği Linux MTD altyapısıyla yönet — UBI wear leveling, UBIFS ve Yocto ile production image üretimi.

00 Flash bellek temelleri

Flash bellek, blok tabanlı elektriksel olarak silinip yazılabilen kalıcı depolama teknolojisidir; NOR ve NAND iki temel mimariyi temsil eder.

NOR ve NAND karşılaştırması

NOR flash her hücreyi doğrudan adresleyebilir (random access), bu yüzden XIP (execute-in-place) için uygundur; bootloader kodunu çalıştırmak için idealdir. NAND ise page/block organizasyonuyla çok daha yüksek yoğunluk ve düşük birim maliyet sunar; büyük veri depolama için tercih edilir. Ancak NAND, üretimden gelen bad block içerebilir ve yazma sırasında da yeni bad block oluşabilir — bu ECC ve bad block yönetimini zorunlu kılar.

Özellik NOR Flash NAND Flash
Bus arayüzüParalel veya SPI (QSPI)Paralel (raw) veya SPI (SPI NAND)
Erase boyutu4–64 KB (sector)64–512 KB (block = 64 × page)
Okuma hızıYüksek; XIP destekliDaha düşük; sayfalık okuma
Yazma hızıYavaş (byte-by-byte)Hızlı (page programlama)
Bad blockYok (pratik olarak)Var; fabrika + kullanım sürecinde
KapasiteDüşük (16 MB – 1 GB tipik)Yüksek (256 MB – 64 GB+)
Birim maliyetYüksekDüşük
Tipik kullanımBootloader, küçük firmwareRootfs, data partition, büyük image

SLC / MLC / TLC / QLC hücre tipleri

Bir flash hücresinin kaç bit sakladığı; silme döngüsü dayanıklılığını, güvenilirliğini ve maliyetini doğrudan belirler. Endüstriyel ve güvenlik kritik uygulamalarda SLC kesinlikle tercih edilmelidir.

SLC1 bit/hücre — P/E cycle: 100 000+. En dayanıklı, en pahalı. Endüstriyel, otomotiv.
MLC2 bit/hücre — P/E cycle: 3 000–10 000. Denge; embedded ve tüketici depolama.
TLC3 bit/hücre — P/E cycle: 300–1 000. Düşük maliyet; tüketici SSD, eMMC.
QLC4 bit/hücre — P/E cycle: 100–300. En yoğun, en ucuz; büyük kapasiteli tüketici depolama.

Page / Block / Plane yapısı

NAND organizasyonu hiyerarşik bir yapıdan oluşur. Okuma ve yazma işlemleri page granülüründe, silme ise block granülüründe gerçekleşir — bir block içindeki tek bir page'i silmek için tüm bloğu silmek zorundasınız.

Die → Plane → Block (erase unit) → Page (read/write unit) → Byte
KatmanTipik boyutOperasyon
Page2 KB – 16 KB (data) + OOB alanıProgram (write), Read
Block64 – 512 pages (= 128 KB – 8 MB)Erase
PlaneBinlerce blockParalel operasyon (multi-plane)
Die / LUNBirden fazla planeBağımsız komut kuyruğu

Her page'in sonunda OOB (Out-of-Band) alanı bulunur — tipik olarak 64–256 byte. Bu alan ECC paritesi, bad block işaretçisi ve dosya sistemi metadata'sı için kullanılır. Linux MTD sürücüleri OOB'u otomatik yönetir.

Wear leveling neden gerekli

Flash hücrelerinin programlama/silme (P/E) döngüsü sınırlıdır. Aynı blok tekrar tekrar yazılırsa diğerlerinden çok daha hızlı aşınır ve bad block haline gelir. Wear leveling, yazmaları tüm bloklar arasında eşit dağıtarak toplam flash ömrünü maksimize eder. UBI katmanı bu görevi yazılım katmanında üstlenir; eMMC/SD kartlarda ise bu işlev donanım flash controller'ı tarafından gerçekleştirilir.

NOT

Raw NAND flash üzerine doğrudan ext2/ext4 gibi block-tabanlı dosya sistemi kurmayın. Bu dosya sistemleri bad block yönetimi ve wear leveling yapmaz; veri bozulmasına ve erken arızaya yol açar. Bunun yerine UBI + UBIFS zincirini kullanın.

Bu bölümde

  • NOR: random access, XIP, küçük kapasite, bootloader için ideal
  • NAND: yüksek kapasite, düşük maliyet, bad block yönetimi gerektirir
  • SLC en dayanıklı (100 K P/E); TLC/QLC tüketici ürünler için
  • Silme block granüllü, yazma page granüllü; wear leveling şart

01 Linux MTD subsystem

MTD (Memory Technology Device), Linux'un flash bellek soyutlama katmanıdır — donanım sürücüsü ile üst katman araçları arasında standart bir arayüz sağlar.

/dev/mtd* ve /dev/mtdblock* farkı

MTD subsystem iki farklı cihaz dosyası türü sunar. Bu ikisinin farkını anlamak kritik önemdedir.

/dev/mtdNKarakter cihazı. Ham flash erişimi: erase, read, write. ECC ve bad block bilgisi korunur. flash_erase, nandwrite, nanddump bu arayüzü kullanır.
/dev/mtdblockNBlock cihazı emülasyonu. Bad block ve wear leveling YOKTUR. Sadece NOR flash üzerine read-only ya da çok dikkatli yazma için; NAND'da kesinlikle kullanmayın.

MTD partition listesini görüntüleme

bash
# Kernel tarafından tanınan MTD partition'larını listele
cat /proc/mtd
# dev:    size   erasesize  name
# mtd0: 00080000 00020000 "SPL"
# mtd1: 00060000 00020000 "SPL.backup"
# mtd2: 00140000 00020000 "u-boot"
# mtd3: 00020000 00020000 "u-boot.env"
# mtd4: 00800000 00020000 "kernel"
# mtd5: 0f560000 00020000 "rootfs"

# mtdinfo ile daha ayrıntılı bilgi (mtd-utils paketi)
mtdinfo /dev/mtd0
# Name:                           SPL
# Type:                           nand
# Eraseblock size:                131072 bytes, 128.0 KiB
# Amount of eraseblocks:          4 (524288 bytes, 512.0 KiB)
# Minimum input/output unit size: 2048 bytes
# Sub-page size:                  512 bytes
# OOB size:                       64 bytes
# Character device major/minor:   90:0
# Bad blocks are allowed:         true
# Device is writable:             true

# Tüm MTD cihazlarını listele
mtdinfo -a

MTD cihaz türleri

TürAçıklamaÖrnek donanım
MTD_NORFLASHCFI/JEDEC uyumlu NOR flashSpansion S25FL, Intel StrataFlash
MTD_NANDFLASHRaw NAND; page/block organizasyonluMicron MT29F, Samsung K9
MTD_SPI-NORSPI arayüzlü NOR (m25p80 sürücüsü)Winbond W25Q128, Macronix MX25L
MTD_SPI-NANDSPI arayüzlü NANDWinbond W25N, GigaDevice GD5F
MTD_DATAFLASHAtmel DataFlash (SPI)AT45DB serisi

Kernel konfigürasyonu

Kconfig — .config / menuconfig
# MTD altyapısını etkinleştir
CONFIG_MTD=y
CONFIG_MTD_CHAR=y          # /dev/mtdN karakter cihazları
CONFIG_MTD_BLOCK=y         # /dev/mtdblockN

# NAND flash desteği
CONFIG_MTD_NAND=y
CONFIG_MTD_NAND_ECC_SW_HAMMING=y  # yazılım ECC (donanım yoksa)
CONFIG_MTD_NAND_ECC_SW_BCH=y     # BCH ECC — daha güçlü

# SPI NOR (m25p80 sürücüsü)
CONFIG_MTD_SPI_NOR=y
CONFIG_SPI=y
CONFIG_SPI_MASTER=y

# Partition parser'ları
CONFIG_MTD_CMDLINE_PARTS=y    # cmdline'dan partition okuma
CONFIG_MTD_OF_PARTS=y         # Device Tree'den partition okuma (önerilen)

# UBI desteği
CONFIG_MTD_UBI=y
CONFIG_UBIFS_FS=y

Device Tree'de MTD partition tanımı

DTS — NAND flash partition layout
/* arch/arm/boot/dts/myboard.dts */
&gpmc {
    nand@0 {
        compatible = "ti,omap2-nand";
        reg = <0 0 4>;
        nand-bus-width = <8>;
        ti,nand-ecc-opt = "bch8";

        #address-cells = <1>;
        #size-cells = <1>;

        partition@0 {
            label = "SPL";
            reg = <0x0 0x80000>;         /* 512 KB */
        };
        partition@80000 {
            label = "u-boot";
            reg = <0x80000 0x140000>;    /* 1.25 MB */
        };
        partition@1c0000 {
            label = "u-boot.env";
            reg = <0x1c0000 0x40000>;   /* 256 KB */
        };
        partition@200000 {
            label = "kernel";
            reg = <0x200000 0xa00000>;  /* 10 MB */
        };
        partition@c00000 {
            label = "rootfs";
            reg = <0xc00000 0x0>;       /* kalan alan */
        };
    };
};
NOT

MTD partition'larını Device Tree ile tanımlamak (CONFIG_MTD_OF_PARTS) kernel cmdline yöntemine göre çok daha temiz ve board bağımlı konfigürasyonu yerinde tutar. Yeni tasarımlarda DTS yöntemini tercih edin.

Bu bölümde

  • /dev/mtdN ham karakter erişimi; /dev/mtdblockN blok emülasyonu — NAND'da sadece mtdN kullanın
  • cat /proc/mtd ve mtdinfo -a partition'ları listeler
  • Kernel config: CONFIG_MTD_NAND=y, CONFIG_MTD_UBI=y, CONFIG_UBIFS_FS=y
  • Partition layout: Device Tree tercih edilmeli

02 NAND flash operasyonları

mtd-utils paketi, NAND flash üzerinde erase, write ve dump işlemleri için komut satırı araçları sağlar; bad block yönetimi bu araçlar tarafından otomatik yapılır.

mtd-utils kurulumu

bash
# Host (Ubuntu/Debian)
sudo apt install mtd-utils

# Cross-compile (Yocto):
# IMAGE_INSTALL:append = " mtd-utils"
# Buildroot: BR2_PACKAGE_MTD=y

Flash erase

bash — flash_erase
# Tüm mtd0'ı sil (offset=0, count=0 → tüm partition)
flash_erase /dev/mtd0 0 0

# Sadece ilk 10 erase block'u sil
# Offset: 0x00000, Block count: 10
flash_erase /dev/mtd0 0 10

# Verbose mod — ilerleme göster
flash_erase --verbose /dev/mtd2 0 0

# JFFS2 clean marker yaz (JFFS2 mount için gerekli)
flash_erase --jffs2 /dev/mtd5 0 0

NAND'a yazma: nandwrite

bash — nandwrite
# Erase ardından image yaz (en yaygın kullanım)
flash_erase /dev/mtd4 0 0
nandwrite -p /dev/mtd4 kernel.bin
# -p: padding — image page sınırına tamamlanır

# Belirli bir offset'e yaz
nandwrite -p -s 0x200000 /dev/mtd4 kernel.bin

# Bad block'ları atla (-c: marklanmış bad block skip)
nandwrite -p -c /dev/mtd4 kernel.bin

# OOB alanıyla birlikte yaz (raw mod — dikkatli kullan)
nandwrite --raw /dev/mtd4 kernel_with_oob.bin

NAND'dan okuma: nanddump

bash — nanddump
# Tüm partition'ı dosyaya dump et
nanddump /dev/mtd4 -f kernel_dump.bin

# OOB alanı dahil dump
nanddump --oob /dev/mtd4 -f full_dump.bin

# Sadece belirli bir aralık: offset + uzunluk
nanddump -s 0x0 -l 0x100000 /dev/mtd4 -f first_1MB.bin

# Bad block'ları atla (-c flag)
nanddump -c /dev/mtd4 -f dump_skip_bad.bin

# Hexdump ile inceleme (küçük partition için)
nanddump /dev/mtd0 -f /tmp/spl.bin && hexdump -C /tmp/spl.bin | head -40

Bad block yönetimi

bash — bad block tarama
# Mevcut bad block'ları listele
nandtest -m /dev/mtd4
# bad eraseblock N at 0x...

# mtdinfo ile bad block sayısı
mtdinfo /dev/mtd4
# Bad blocks:                     3

# Bad block tablosunu görüntüle (kernel dmesg)
dmesg | grep -i "bad block"
# [    1.234567] nand: device found, Manufacturer ID: 0x2c, Chip ID: 0xda
# [    1.234890] nand: Bad block at 0x01fe0000
DİKKAT

nandwrite ile kernel veya bootloader yazarken bad block atlama (-c) flag'ini kullanın. Aksi takdirde bad block üzerine yazma girişimi hata döner ve image bozulabilir. UBI kullanıyorsanız bu yönetim otomatik yapılır.

Bu bölümde

  • flash_erase /dev/mtdN 0 0 tüm partition'ı siler
  • nandwrite -p /dev/mtdN image.bin en yaygın yazma komutu
  • nanddump /dev/mtdN -f dump.bin tam partition dump
  • -c flag'i bad block'ları otomatik atlar

03 NOR flash operasyonları

NOR flash, bad block yönetimi gerektirmez ve XIP kapasitesine sahiptir; flashcp ile doğrudan programlanabilir.

flashcp ile NOR yazma

bash — flashcp
# NOR flash'a firmware yaz (-v: verbose, ilerleme göster)
flashcp -v firmware.bin /dev/mtd0
# Flashing... (0% - 10% - ... - 100%)
# Verifying... done.

# flashcp hem erase hem write yapar — önceden flash_erase gerekmez

# SPI NOR üzerinde manuel erase + write
flash_erase /dev/mtd0 0 0
dd if=firmware.bin of=/dev/mtd0 bs=4096

# Sadece belirli bir bölgeyi güncelle (offset ile)
# flash_erase offset'i erase block sınırına hizalamalısın
flash_erase /dev/mtd0 0x10000 4   # 0x10000 offset, 4 blok sil
dd if=patch.bin of=/dev/mtd0 bs=4096 seek=16 # offset=16*4096=0x10000

/dev/mtdblock ile raw erişim (NOR)

bash — mtdblock (sadece NOR)
# NOR flash'ı read-only mount et (cramfs/squashfs için)
mount -t cramfs /dev/mtdblock2 /mnt/rom -o ro

# squashfs NOR üzerinde
mount -t squashfs /dev/mtdblock2 /mnt/rom -o ro

# FAT üzerinde U-Boot environment değişkenlerini oku
mount -t vfat /dev/mtdblock1 /mnt/env

# Doğrudan okuma (cat ile ham binary)
cat /dev/mtdblock0 > /tmp/nor_backup.bin

CFI probe — donanım tespiti

CFI (Common Flash Interface), NOR flash'ların parametrelerini (boyut, erase block, timing) standart bir sorgu protokolüyle raporlamasını sağlar. Linux CFI sürücüsü boot sırasında bu bilgiyi otomatik okur.

bash — CFI bilgisi
# Boot sırasında CFI probe çıktısı (dmesg)
dmesg | grep -i "cfi\|nor\|flash"
# [    0.456789] physmap-flash 10000000.flash: physmap platform flash device: [mem 0x10000000-0x10ffffff]
# [    0.456800] physmap-flash 10000000.flash: Found 1 x16 devices at 0x0 in 16-bit bank. Manufacturer ID 0x000089 Chip ID 0x8801
# [    0.457000] Intel/Sharp Extended Query Table at 0x0031
# [    0.457100] Using buffer write method
# [    0.457200] physmap-flash 10000000.flash: CFI conformant device (jedec_probe)

# SPI NOR tespiti (m25p80 / spi-nor sürücüsü)
dmesg | grep -i "spi.*nor\|m25p\|w25q"
# [    1.234567] m25p80 spi0.0: w25q128 (16384 Kbytes)
# [    1.234600] 3 fixed-partitions partitions found on MTD device spi0.0
NOT

SPI NOR flash için Device Tree'de compatible = "jedec,spi-nor" kullanmak, tek bir sürücüyle tüm JEDEC uyumlu cihazları kapsar. Cihaz kimliği kernel tarafından spi-nor tablosundan otomatik eşleştirilir.

Bu bölümde

  • flashcp -v firmware.bin /dev/mtd0 en güvenli NOR yazma yöntemi
  • /dev/mtdblock sadece NOR'da read-only kullanım için güvenli
  • CFI probe: kernel boot log'unda flash kapasitesi ve geometri otomatik raporlanır

04 UBI — Unsorted Block Images

UBI, ham NAND flash üzerinde wear leveling, bad block yönetimi ve I/O hata kurtarma sağlayan bir ara katmandır — UBIFS bu katman üzerine oturur.

UBI mimarisi

UBI, MTD katmanı ile dosya sistemi arasına girer. Fiziksel erase block'ları (PEB) ile mantıksal erase block'ları (LEB) arasında esnek bir eşleme tablası tutar; bu sayede wear leveling ve bad block yönetimini şeffaf biçimde gerçekleştirir.

UBIFS / diğer FS → UBI (LEB → PEB eşleme, wear leveling) → MTD driver → NAND donanımı
PEBPhysical Erase Block — donanımdaki gerçek erase bloğu. Bad olabilir.
LEBLogical Erase Block — UBI tarafından sunulan sanal blok. Bad block olmaz.
EC headerErase Count header — her PEB'de; kaç kez silindiği bilgisi, wear leveling için.
VID headerVolume ID header — hangi volume ve LEB'e ait olduğunu belirtir.

UBI format ve attach

bash — ubiformat / ubiattach
# Adım 1: NAND partition'ı UBI için hazırla (format)
# Bu komut tüm PEB'leri siler ve EC header yazar
ubiformat /dev/mtd2
# ubiformat: mtd2 (nand), size 268435456 bytes (256.0 MiB),
#            2048 eraseblocks of 131072 bytes (128.0 KiB)
# ubiformat: formatting eraseblock 0 -- 100 % complete

# Verbose + minimum I/O unit belirt
ubiformat -v -s 2048 /dev/mtd2

# Adım 2: UBI volume'ünü kernel'a attach et
ubiattach -m 2
# UBI device number 0, total 2048 LEBs
# /dev/ubi0 oluşur

# Belirli bir UBI device numarası ata
ubiattach -m 2 -d 0    # → /dev/ubi0
ubiattach -m 3 -d 1    # → /dev/ubi1

# Detach etmek için
ubidetach -m 2

UBI volume oluşturma

bash — ubimkvol
# rootfs volume oluştur (50 MiB)
ubimkvol /dev/ubi0 -N rootfs -s 50MiB
# /dev/ubi0_0 oluşur

# data volume oluştur (kalan tüm alanı kullan)
ubimkvol /dev/ubi0 -N data -m
# -m: maximum available size

# Volume'leri listele
ubinfo -a
# UBI device 0, total 2048 LEBs (260046848 bytes, 248.0 MiB),
# Volume 0: rootfs, size: 400 LEBs (50 MiB)
# Volume 1: data,   size: 1595 LEBs (197.7 MiB)

# Volume boyutunu güncelle (sadece dynamic volume)
ubirsvol /dev/ubi0_0 -s 80MiB

# Volume sil
ubirmvol /dev/ubi0 -N data

UBI image yazmak: ubiupdatevol

bash — UBI volume'e image yazma
# Önceden hazırlanmış UBIFS image'ını volume'e yaz
ubiupdatevol /dev/ubi0_0 rootfs.ubifs

# İlerleme göstererek yaz
ubiupdatevol -s $(stat -c %s rootfs.ubifs) /dev/ubi0_0 rootfs.ubifs
NOT

UBI volume türleri: dynamic (okuma/yazma, normal kullanım) ve static (sadece okunur; CRC korumalı; kernel image gibi değişmeyen veriler için). Static volume için ubimkvol --type static kullanın.

Bu bölümde

  • ubiformat /dev/mtdNubiattach -m Nubimkvol temel UBI hazırlık akışı
  • PEB/LEB ayrımı; EC ve VID header'lar wear leveling'in temeli
  • Static volume: CRC korumalı, değişmeyen veriler için
  • ubinfo -a tüm volume'leri listeler

05 UBIFS — UBI üzerine dosya sistemi

UBIFS, UBI logical volume üzerine kurulan log-yapılandırmalı bir dosya sistemidir; NAND flash'ın tüm özelliklerine uyum sağlar ve güç kaybında tutarlılık garantisi verir.

UBIFS'in avantajları

Log-structuredYazma her zaman boş alana gider; yerinde güncelleme olmaz. NAND doğasına uygun, yüksek yazma performansı.
JournalingGüç kaybına karşı atomik commit; fsck gerekmez, hızlı mount.
SıkıştırmaLZO, zlib veya zstd ile inline veri sıkıştırma; flash alanını verimli kullanır.
ÖlçeklenebilirlikMilyonlarca dosyaya kadar iyi performans; B-tree indeksi.

UBIFS mount etme

bash — UBIFS mount
# UBI volume adıyla mount (ubi0:rootfs sözdizimi)
mount -t ubifs ubi0:rootfs /mnt

# Cihaz dosyasıyla mount
mount -t ubifs /dev/ubi0_0 /mnt

# Sıkıştırma seçeneğiyle mount
mount -t ubifs -o compr=lzo ubi0:rootfs /mnt

# /etc/fstab satırı
# ubi0:rootfs  /  ubifs  defaults,noatime  0  0

# Kernel cmdline ile rootfs olarak boot
# root=ubi0:rootfs rootfstype=ubifs ubi.mtd=5

mkfs.ubifs ile image oluşturma

bash — mkfs.ubifs
# rootfs dizininden UBIFS image üret
# -r: kaynak dizin
# -m: minimum I/O birimi (page size, örn. 2048)
# -e: LEB boyutu (erase block - 2*page, örn. 131072 - 4096 = 126976 ≈ 0x1f000)
# -c: maksimum LEB sayısı (volume büyüklüğü / LEB boyutu)
mkfs.ubifs \
    -r /path/to/rootfs \
    -m 2048 \
    -e 126976 \
    -c 2000 \
    -o rootfs.ubifs

# Sıkıştırma belirterek (varsayılan lzo)
mkfs.ubifs -r rootfs/ -m 2048 -e 126976 -c 2000 \
    -x lzo -o rootfs.ubifs

# LEB boyutu hesabı:
# erase_block_size = 128 KiB = 131072 bytes
# LEB = erase_block_size - 2 * min_io_size  (EC + VID header alanı)
# LEB = 131072 - 2*2048 = 126976 bytes

ubinize ile UBI image üretme

Üretim programlaması için UBIFS image'ını UBI volume metadata'sıyla birleştiren bir .ubi image üretilebilir — bu image tek seferde ubiformat ile flash'a yazılır.

ubinize.cfg — konfigürasyon dosyası
[ubifs-volume]
mode=ubi
image=rootfs.ubifs
vol_id=0
vol_size=50MiB
vol_type=dynamic
vol_name=rootfs
vol_flags=autoresize

[data-volume]
mode=ubi
vol_id=1
vol_size=100MiB
vol_type=dynamic
vol_name=data
bash — ubinize
# UBI image üret
# -p: PEB boyutu (erase block), -m: minimum I/O, -s: sub-page (eğer varsa)
ubinize \
    -o rootfs.ubi \
    -p 128KiB \
    -m 2048 \
    -s 512 \
    ubinize.cfg

# Üretilen .ubi image'ı flash'a yaz (NAND önceden erase edilmemeli — ubiformat yapar)
ubiformat /dev/mtd5 -f rootfs.ubi
NOT

vol_flags=autoresize: Son volume, UBI attach sırasında mevcut tüm boş alanı otomatik olarak kaplar. Farklı flash kapasiteli kartlarda tek bir image ile çalışmak için kullanışlıdır.

Bu bölümde

  • mount -t ubifs ubi0:rootfs /mnt veya root=ubi0:rootfs cmdline
  • mkfs.ubifs -r rootfs/ -m 2048 -e 126976 -c 2000 -o rootfs.ubifs
  • ubinize ile çok-volume UBI image üretimi; ubiformat -f rootfs.ubi ile tek adımda yaz
  • LEB = erase_block_size - 2 × min_io_size

06 Partition layout tasarımı

Flash partition layout, erase block sınırlarına hizalı olmalı, bad block rezervasyonu içermeli ve her partition'ın amacına uygun boyutlandırılmalıdır.

Tipik NAND partition yapısı

PartitionBoyutTürİçerik
SPL512 KBRawSecondary Program Loader; ROM tarafından okunur
SPL.backup512 KBRawSPL yedek kopyası; güvenilirlik için
u-boot1.5 MBRawU-Boot binary (u-boot.img)
u-boot.env256 KBRawU-Boot environment değişkenleri; iki kopya önerilir
kernel8–16 MBRaw veya UBI staticzImage/Image + DTB veya FIT image
rootfs50–256 MBUBI + UBIFSKök dosya sistemi
datakalanUBI + UBIFSUygulama verisi, log, konfigürasyon

Boyut hesaplama ve hizalama

bash — partition boyut hesabı
# Örnek: 256 MB NAND, 128 KB erase block
# Toplam erase block sayısı
TOTAL_BLOCKS=$(( 256 * 1024 * 1024 / (128 * 1024) ))
# TOTAL_BLOCKS = 2048

# Bad block rezervasyonu: ~%2 önerilir
RESERVED_BAD=$(( TOTAL_BLOCKS * 2 / 100 ))
# RESERVED_BAD ≈ 40 block

# Kullanılabilir block sayısı
USABLE=$(( TOTAL_BLOCKS - RESERVED_BAD ))
# USABLE ≈ 2008 block = ~251 MB

# Her partition boyutu erase block katı olmalı
# SPL: 512 KB = 4 erase block
# u-boot: 1536 KB = 12 erase block
# kernel: 10 MB = 80 erase block
# rootfs: 128 MB = 1024 erase block
# data: kalan

Bad block rezervasyonu ve UBI overhead

UBI her PEB için EC ve VID header yazar; bu 2 × min_io_size alanı kullanır. Ayrıca UBI kendi iç yönetimi için birkaç PEB rezerve eder (genellikle 20 PEB). NAND flash standartları ise üretimden gelen bad block'lar için kapasitesi başına %2'ye kadar reserve edilmesini zorunlu kılar. Bunu hesaba katmadan UBI volume boyutu belirlemeyin.

DİKKAT

SPL ve U-Boot partition'larını kesinlikle UBI'ye dahil etmeyin. ROM bootrom UBI formatını bilmez; bu partition'lar raw olarak kalmalıdır. Yalnızca Linux'un kullandığı partition'larda (kernel sonrası) UBI uygulayın.

U-Boot environment çift kopya

include/configs/myboard.h — U-Boot config
/* U-Boot environment NAND üzerinde çift kopya */
#define CONFIG_ENV_IS_IN_NAND
#define CONFIG_ENV_OFFSET       0x1C0000   /* mtd3 başlangıcı */
#define CONFIG_ENV_OFFSET_REDUND 0x1E0000   /* yedek kopya */
#define CONFIG_ENV_SIZE         0x20000    /* 128 KB */
#define CONFIG_ENV_RANGE        0x40000    /* toplam 256 KB = 2 erase block */

Bu bölümde

  • Her partition boyutu erase block katı olmalı; hizalanmamış partition sorunlara yol açar
  • %2 bad block rezervasyonu ve UBI iç overhead (≈20 PEB) hesaba katılmalı
  • SPL ve U-Boot raw partition'da kalmalı; UBI sadece Linux'un kullandığı alanlarda
  • U-Boot environment için çift kopya (CONFIG_ENV_OFFSET_REDUND) önerilir

07 JFFS2 — eski alternatif

JFFS2 (Journalling Flash File System 2), UBI olmadan doğrudan MTD üzerinde çalışan eski bir flash dosya sistemidir; küçük NOR flash sistemlerde hâlâ kullanılabilir.

JFFS2 ne zaman tercih edilir

KriterJFFS2UBIFS
BağımlılıkDoğrudan MTD; UBI gerekmezUBI katmanı zorunlu
BoyutKüçük flash (<32 MB) için uygunBüyük flash için optimize
Mount süresiYavaş (log scan); büyük flash'ta çok yavaşHızlı; log boyutu sınırlı
Wear levelingTemel, log-structured yapıdan gelirUBI aracılığıyla daha iyi
Bad blockSınırlı destekUBI tam bad block yönetimi
SıkıştırmaZLIB, RTIME, LZOLZO, ZLIB, ZSTD
Tercih senaryosuKüçük NOR, basit sistem, legacyNAND, büyük rootfs, yeni tasarım

mkfs.jffs2 ile image oluşturma

bash — mkfs.jffs2
# rootfs dizininden JFFS2 image üret
# -r: kaynak dizin, -o: çıktı dosyası
# -e: erase block boyutu (NOR: 64KB, NAND: 128KB tipik)
# -p: image boyutunu erase block katına doldur
mkfs.jffs2 \
    -r rootfs/ \
    -o rootfs.jffs2 \
    -e 0x10000 \
    -p 0x2000000 \
    --squash   # root dışı dosyaları squash et (UID/GID normalize)

# LZO sıkıştırma ile
mkfs.jffs2 -r rootfs/ -o rootfs.jffs2 -e 0x10000 -l
# -l: little-endian (ARM için varsayılan)

# NAND için (128 KB erase block, no-cleanmarker)
mkfs.jffs2 -r rootfs/ -o rootfs.jffs2 -e 0x20000 \
    -n            # -n: cleanmarker yazma (NAND OOB kullanır, farklı yönetim)
    -l

JFFS2 flash'a yazma ve mount

bash — JFFS2 yaz ve mount et
# NOR flash'a yaz
flash_erase --jffs2 /dev/mtd5 0 0   # clean marker yaz
flashcp -v rootfs.jffs2 /dev/mtd5

# NAND flash'a yaz
flash_erase /dev/mtd5 0 0
nandwrite -p /dev/mtd5 rootfs.jffs2

# Mount et
mount -t jffs2 /dev/mtdblock5 /mnt

# Kernel cmdline ile boot
# root=/dev/mtdblock5 rootfstype=jffs2
DİKKAT

JFFS2 büyük flash partition'larında mount süresi dakikalar alabilir — başlangıçta tüm log yapısını taraması gerekir. 64 MB üzeri NAND flash için UBIFS kullanın; JFFS2'yi sadece küçük NOR partitionları veya legacy sistemler için tercih edin.

Bu bölümde

  • JFFS2 küçük NOR flash veya legacy sistemler için uygun; büyük NAND'da UBIFS kullanın
  • mkfs.jffs2 -r rootfs/ -e 0x10000 -o rootfs.jffs2
  • JFFS2 mount süresi flash büyüklüğüyle orantılı olarak uzar
  • Yeni tasarımlarda MTD → UBI → UBIFS zincirini tercih edin

08 Pratik: Yocto ile NAND image üretimi

Yocto Build System, UBIFS image üretimini ve ubinize ile UBI paketlenmesini yerleşik değişkenler aracılığıyla destekler.

IMAGE_FSTYPES ile flash image türleri

conf/local.conf veya distro.conf
# UBIFS ve UBI image türlerini etkinleştir
IMAGE_FSTYPES += "ubifs ubi"

# mkfs.ubifs parametreleri
# -m: min I/O, -e: LEB size, -c: max LEB count
MKUBIFS_ARGS = "-m 2048 -e 126976 -c 2000"

# ubinize parametreleri
# -p: PEB size, -m: min I/O, -s: sub-page size
UBINIZE_ARGS = "-p 128KiB -m 2048 -s 512"

# Kullanılan makine (BSP layer'dan gelir)
MACHINE = "myboard"

Machine konfigürasyonunda NAND parametreleri

conf/machine/myboard.conf
# NAND parametreleri — mkfs.ubifs ve ubinize için
MKUBIFS_ARGS = "-m 2048 -e 126976 -c 4096"
UBINIZE_ARGS = "-p 128KiB -m 2048 -s 512"

# Image türleri
IMAGE_FSTYPES = "ubifs ubi tar.gz"

# Kernel image türü
KERNEL_IMAGETYPE = "zImage"

# U-Boot yüklenecek binary
UBOOT_MACHINE = "myboard_defconfig"
UBOOT_SUFFIX = "img"

Yocto build ve çıktı dosyaları

bash — Yocto build
# Ortamı hazırla
source oe-init-build-env build/

# Image build et
bitbake core-image-minimal

# Çıktılar:
ls tmp/deploy/images/myboard/
# core-image-minimal-myboard.ubifs  — ham UBIFS image
# core-image-minimal-myboard.ubi    — UBI paketlenmiş image
# zImage                            — kernel
# myboard.dtb                       — device tree blob
# u-boot.img                        — U-Boot binary
# MLO                               — SPL (TI AM335x)

Flash layout DTS binding — Yocto ile

recipes-kernel/linux/linux-myboard.bbappend
# Kernel recipe'ye board DTS dosyasını ekle
FILESEXTRAPATHS:prepend := "${THISDIR}/files:"

SRC_URI += "file://myboard-nand-partitions.dts \
             file://0001-add-myboard-nand-partitions.patch"
bash — target'a flash etme
# U-Boot üzerinden TFTP ile kernel yükle ve flash et
# (U-Boot shell üzerinde)
# setenv serverip 192.168.1.100
# setenv ipaddr 192.168.1.200
# tftp 0x82000000 zImage
# nand erase.part kernel
# nand write 0x82000000 kernel $filesize

# Target üzerinde (Linux çalışırken) rootfs güncelle
ubiformat /dev/mtd5 -f core-image-minimal-myboard.ubi
ubiattach -m 5
mount -t ubifs ubi0:rootfs /mnt/newroot
NOT

Yocto MKUBIFS_ARGS ve UBINIZE_ARGS değerleri, hedef NAND flash'ın geometrisine tam uymalıdır. Yanlış -e (LEB size) veya -p (PEB size) değerleriyle üretilen image mount edilemez. Bu değerleri mtdinfo /dev/mtdN çıktısından alın.

Bu bölümde

  • IMAGE_FSTYPES += "ubifs ubi" ve MKUBIFS_ARGS / UBINIZE_ARGS değişkenleri
  • Machine config'e NAND geometrisini girin; mtdinfo çıktısından alın
  • Build çıktısı: .ubifs ham image, .ubi UBI paketlenmiş image
  • ubiformat /dev/mtdN -f image.ubi tek adımda hem format hem yaz