embedded-deck
TEKNİK REHBER GÖMÜLÜ eMMC 2026

eMMC Yönetimi
Gömülü Depolama.

JEDEC JESD84 standardından bölümleme stratejilerine, RPMB güvenliğinden sağlık izlemeye ve üretim hattı provisioning scriptlerine kadar eksiksiz eMMC yönetimi rehberi.

00 eMMC nedir?

eMMC (embedded MultiMediaCard), NAND flash bellek ve kontrolcüsünü tek bir BGA paketinde birleştiren, JEDEC JESD84 standardıyla tanımlanmış yönetilen depolama birimidir.

NAND flash ve yönetilen depolama

Ham NAND flash ile çalışmak son derece karmaşıktır: bozuk blok yönetimi, wear leveling, ECC (Error Correction Code) ve write endurance tümü yazılım katmanında çözülmelidir. eMMC, tüm bu düşük seviyeli sorumluluğu iç kontrolcüde gizleyerek sisteme standart bir MMC/SD arayüzü sunar. Geliştirici dosya sistemi yazma/okuma işlemleri yaparken; sayfa programlama, blok silme, ECC ve wear leveling eMMC içinde otomatik yürütülür.

Depolama teknolojisi karşılaştırması

ÖzellikHam NANDeMMCSD KartNVMe SSD
ArayüzParalel/SPIMMC (HS400)SD/SPIPCIe/NVMe
Hız (seq r)~100 MB/s250–300 MB/s10–100 MB/s2–7 GB/s
EntegrasyonMTD/UBIFS gerekirBlock device doğrudanBlock deviceBlock device
Boot desteğiManuelBoot0/Boot1 hardwiredCard detect gerekirNVMe boot
RPMBYokStandartYokYok (genelde)
EndurancepSLC: 100K cycleMLC: 3K–10K cycleDüşükTLC: 3K cycle
MaliyetDüşükOrtaDüşükYüksek

JEDEC JESD84 standardı

JESD84-B51 (eMMC 5.1) standardı; HS400 (400 MB/s), enhanced strobe modu, packed commands, command queuing ve gelişmiş sağlık registerları gibi özellikleri tanımlar. Çoğu modern SoC (i.MX8, RK3568, AM625) HS400 destekler.

01 Fiziksel yapı ve registerlar

eMMC'nin iç yapısını anlamak; boot partition seçimi, write protection ve kapasite hesaplama için gereklidir.

Mantıksal bölge yapısı

eMMC Fiziksel Yapısı
┌────────────────────────────────────────┐
│           User Data Area               │  ← normal disk bölümler
│  (mmcblk0 — GPT/MBR bölümleme)        │
├──────────────┬─────────────────────────┤
│  Boot Area 1 │  Boot Area 2            │  ← mmcblk0boot0 / mmcblk0boot1
│  (mmcblk0boot0)  (mmcblk0boot1)        │  U-Boot buraya yazılır
├──────────────┴─────────────────────────┤
│  RPMB (Replay Protected Memory Block)  │  ← mmcblk0rpmb
│  (TEE / güvenli depolama)              │
└────────────────────────────────────────┘
    

Önemli registerlar

CID (Card Identification)128-bit — üretici, model, seri numarası, üretim tarihi. Değiştirilemez, fabrikada yazılır
CSD (Card Specific Data)128-bit — eMMC sürümü, kapasite, blok boyutu, zaman sabitleri
EXT_CSD512-byte genişletilmiş register — boot partition boyutu, RPMB boyutu, timing modu, sağlık bitleri, WP grupları

EXT_CSD register haritası (önemli ofsetler)

OfsetAlanAçıklama
196BOOT_PARTITION_ENABLEHangi boot alanından önyükleneceği (boot0/boot1/user)
179PARTITION_CONFIGBoot partition access ve bus seçimi
241BOOT_SIZE_MULTIBoot partition boyutu = değer × 128 KB
267PRE_EOL_INFOÖmür sonu uyarısı (0x01=normal, 0x02=warning, 0x03=urgent)
268DEVICE_LIFE_TIME_EST_AType A (SLC) yıpranma tahmini — %10 adımlarla 0–100%
269DEVICE_LIFE_TIME_EST_BType B (MLC) yıpranma tahmini — %10 adımlarla 0–100%
# EXT_CSD registerını oku ve parse et
mmc extcsd read /dev/mmcblk0 | grep -E "BOOT|LIFE|EOL"

# Çıktı örneği:
# Boot Partition Size [BOOT_SIZE_MULTI]: 0x10
# Boot configuration bytes [PARTITION_CONFIG]: 0x48
# pre-EOL information [PRE_EOL_INFO]: 0x01
# Device life time estimation type A [DEVICE_LIFE_TIME_EST_TYP_A]: 0x01

02 GPT bölümleme

eMMC user data alanı, tıpkı bir SATA disk gibi GPT veya MBR bölüm tablosuyla yönetilir. Gömülü sistemlerde GPT tercih edilir.

Neden GPT?

MBR 4 birincil bölümle sınırlıdır ve 2 TB üstü diskleri desteklemez. GPT 128 bölüme kadar destek sunar, birincil ve yedek bölüm tablosu içerir ve her bölüme GUID ile benzersiz kimlik verir.

sgdisk ile bölümleme

#!/bin/bash
# Üretim bölümleme scripti
DEVICE=/dev/mmcblk0

# Mevcut bölüm tablosunu sil
sgdisk --zap-all $DEVICE

# Bölümleri oluştur
# U-Boot env (2 MB, offset 1 MB'dan başla — bootloader raw için yer)
sgdisk --new=1:2048:6143   --typecode=1:8300 --change-name=1:"uboot-env"  $DEVICE

# Boot: kernel + DTB + initramfs (64 MB)
sgdisk --new=2:6144:137215 --typecode=2:0700 --change-name=2:"boot"       $DEVICE

# RootFS A (512 MB — squashfs)
sgdisk --new=3:137216:1185791 --typecode=3:8300 --change-name=3:"rootfs-a" $DEVICE

# RootFS B (512 MB — A/B güncelleme)
sgdisk --new=4:1185792:2234367 --typecode=4:8300 --change-name=4:"rootfs-b" $DEVICE

# Data (kalan alan)
sgdisk --new=5:2234368:0 --typecode=5:8300 --change-name=5:"data" $DEVICE

# Bölüm tablosunu yazdır
sgdisk --print $DEVICE

# Kernel bölüm tablosunu güncelle
partprobe $DEVICE || partx -u $DEVICE

Bölüm düzeni

BölümBaşlangıçBoyutİçerikFS
mmcblk0p12048 (1 MB)2 MBU-Boot envRaw
mmcblk0p26144 (3 MB)64 MBKernel, DTB, initrdFAT32
mmcblk0p3137216512 MBRootFS A (squashfs)SquashFS
mmcblk0p41185792512 MBRootFS B (squashfs)SquashFS
mmcblk0p52234368KalanKalıcı data + overlayext4
NOT

eMMC'de ilk 1 MB (LBA 0–2047) bootloader için ayrılır ve bölüm tablosuna dahil edilmez. U-Boot çoğunlukla mmcblk0boot0'a yazılır; ancak bazı SoC tasarımları U-Boot'u user data alanının başına ham olarak yazar. Hedef boardunuzun boot flow diyagramını inceleyin.

03 Boot partitions

eMMC'nin iki adet 128 KB'nın katları şeklinde boyutlandırılmış özel boot alanı (boot0 / boot1) mevcuttur. SoC ROM kodu doğrudan bu alanlardan önyükleme yapabilir.

Boot partition erişimini etkinleştirme

# Boot0'ı erişilebilir yap
echo 0 > /sys/class/block/mmcblk0boot0/force_ro

# Boot1'i erişilebilir yap
echo 0 > /sys/class/block/mmcblk0boot1/force_ro

U-Boot'u boot0'a yazma

#!/bin/bash
# U-Boot'u eMMC boot0 partition'a yaz
UBOOT_BIN=/tmp/u-boot.imx    # i.MX8 formatı
BOOT0=/dev/mmcblk0boot0

# Write protect'i kaldır
echo 0 > /sys/class/block/mmcblk0boot0/force_ro

# Yazma (i.MX8 için offset 0, bazı SoC'lar 512 byte offset ister)
dd if=$UBOOT_BIN of=$BOOT0 bs=512 seek=0 conv=fsync status=progress

# Write protect'i geri aç
echo 1 > /sys/class/block/mmcblk0boot0/force_ro

echo "U-Boot yazıldı: $(stat -c %s $UBOOT_BIN) byte"

BOOT_PARTITION_ENABLE ayarlama

# mmc-utils ile boot0'dan önyüklemeyi etkinleştir
# PARTITION_CONFIG[5:3] = 001 = boot0
mmc bootpart enable 1 1 /dev/mmcblk0
# Argümanlar: boot_partition(1=boot0) boot_ack(1=etkin) device

# Mevcut ayarı doğrula
mmc extcsd read /dev/mmcblk0 | grep "Boot configuration"
# Boot configuration bytes [PARTITION_CONFIG]: 0x48
# 0x48 = 0100 1000: boot0 enabled, boot ACK enabled

Boot partition boyutu

# Boot partition boyutunu hesapla
mmc extcsd read /dev/mmcblk0 | grep "BOOT_SIZE_MULTI"
# Boot Partition Size [BOOT_SIZE_MULTI]: 0x10
# Boyut = 0x10 * 128KB = 16 * 128KB = 2MB

# Doğrula
blockdev --getsize64 /dev/mmcblk0boot0
# 4194304 = 4 MB (bazı cihazlarda 2× BOOT_SIZE_MULTI)

04 RPMB — Replay Protected Memory Block

RPMB, eMMC içinde kriptografik kimlik doğrulama kullanan özel bir bellek bölgesidir. Güvenli sayaç, cihaz kimliği ve güvenli boot durumu saklamak için kullanılır.

RPMB güvenlik modeli

TEE (Güvenli Dünya)        Normal Dünya
       |                        |
   HMAC-SHA256              mmc ioctl
   anahtarı bilir          (sadece RPMB erişimi)
       |                        |
       +------- eMMC RPMB ------+
                   |
           256-byte veri bloğu
           + write counter
           + MAC doğrulama
    

RPMB anahtar provisioning

#!/bin/bash
# RPMB anahtarını ilk kez yaz (bir kez yapılır — geri alınamaz!)
# Anahtar 32 byte HMAC-SHA256 anahtarı

# Donanımdan türetilmiş anahtar (örnek — gerçekte TEE/HSM'den gelir)
KEY_HEX="0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20"

# rpmb-tool veya mmc rpmb write-key kullan
mmc rpmb write-key /dev/mmcblk0rpmb /dev/mmcblk0 <<< "$KEY_HEX"

# Ya da rpmb-tool (daha güvenilir TEE entegrasyonu)
# rpmb_tool --key $KEY_HEX program /dev/mmcblk0

RPMB okuma/yazma (mmc-utils)

# RPMB'ye 256-byte veri yaz (blok 0)
echo -n "secure_data_here_padded_to_256b" | \
    mmc rpmb write-block /dev/mmcblk0rpmb /dev/mmcblk0 0x00 -

# RPMB'den veri oku
mmc rpmb read-block /dev/mmcblk0rpmb /dev/mmcblk0 0x00 1 -
GÜVENLİK

RPMB anahtarı eMMC'ye bir kez yazılır ve değiştirilemez. Aynı anahtar yedek olarak güvenli depolamada (HSM, TEE persistent storage) tutulmalıdır. RPMB'nin asıl amacı yüksek kapasiteli veri depolama değil; write counter ile replay saldırısına karşı dayanıklı küçük güvenli değer saklamaktır (örn: rollback counter, device binding key).

05 mmc-utils araçları

mmc-utils paketi, EXT_CSD okuma, boot partition yönetimi, sağlık sorgulama ve düşük seviyeli eMMC yapılandırması için temel CLI araçlarını sunar.

Temel komutlar

# EXT_CSD tüm alanları oku
mmc extcsd read /dev/mmcblk0

# eMMC durumu sorgula
mmc status get /dev/mmcblk0
# Çıktı: READY_FOR_DATA=1, CURRENT_STATE=Transfer, ...

# Cihaz bilgisi (CID, CSD)
mmc info /dev/mmcblk0

# Boot bus ayarlarını göster
mmc bootbus get /dev/mmcblk0

# Boot bus genişliği ayarla (x8, SDR, DDR)
mmc bootbus set /dev/mmcblk0 x8 sdr normal

Güvenli silme işlemleri

# Belirli LBA aralığını sil (DISCARD — hızlı, veri geri alınabilir)
mmc erase /dev/mmcblk0 0 8192

# Güvenli silme (SECURE ERASE — yavaş, NAND hücrelerini fiziksel sıfırlar)
mmc erase --secure /dev/mmcblk0 0 8192

# Tüm cihazı güvenli sil (üretim sonrası temizleme)
mmc sanitize /dev/mmcblk0

Write Protect (WP) yönetimi

# WP grup boyutunu öğren
mmc extcsd read /dev/mmcblk0 | grep "Write protect group size"

# Boot partition kalıcı write protect
mmc writeprotect boot set /dev/mmcblk0

# User area belirli bölge WP
mmc writeprotect user set pwron /dev/mmcblk0 0 8192
# pwron = power-on WP (her açılışta aktif)
# perm  = kalıcı WP (değiştirilemez)
# temp  = geçici WP
mmc extcsd read512-byte EXT_CSD registerını insan okunabilir formatta gösterir
mmc status getAnlık eMMC durum registerını sorgular — hata bayrakları dahil
mmc bootpart enableBoot0/boot1 seçimi ve boot ACK yapılandırması
mmc sanitizeSilinen blokları fiziksel olarak temizler (NAND cell erase)
mmc rpmbRPMB anahtar programlama, blok okuma/yazma

06 Sağlık izleme

eMMC JESD84-B51 standardı, cihaz ömrü ve wear durumunu izlemek için EXT_CSD içinde birkaç sağlık alanı tanımlar.

Temel sağlık alanları

#!/bin/bash
# eMMC sağlık raporu scripti
DEVICE=${1:-/dev/mmcblk0}

echo "=== eMMC Sağlık Raporu: $DEVICE ==="

EXTCSD=$(mmc extcsd read $DEVICE 2>/dev/null)

# PRE_EOL_INFO
EOL=$(echo "$EXTCSD" | grep "PRE_EOL_INFO" | grep -oP '0x[0-9a-fA-F]+' | tail -1)
case $EOL in
    0x00) EOL_STATUS="Undefined" ;;
    0x01) EOL_STATUS="Normal — kullanım %0-80" ;;
    0x02) EOL_STATUS="WARNING — kullanım %80-90" ;;
    0x03) EOL_STATUS="URGENT — kullanım >%90, değiştirin!" ;;
    *)    EOL_STATUS="Bilinmiyor: $EOL" ;;
esac
echo "Pre-EOL Info: $EOL_STATUS"

# LIFE TIME EST A/B
LIFE_A=$(echo "$EXTCSD" | grep "DEVICE_LIFE_TIME_EST_TYP_A" | grep -oP '0x[0-9a-fA-F]+' | tail -1)
LIFE_B=$(echo "$EXTCSD" | grep "DEVICE_LIFE_TIME_EST_TYP_B" | grep -oP '0x[0-9a-fA-F]+' | tail -1)

echo "Life Time Est Type A (SLC): $((16#${LIFE_A#0x} * 10))% tüketildi"
echo "Life Time Est Type B (MLC): $((16#${LIFE_B#0x} * 10))% tüketildi"

Sağlık alanı yorumlama tablosu

DeğerPRE_EOL_INFOLIFE_TIME_EST
0x00TanımsızTanımsız
0x01Normal%0–10 kullanıldı
0x02Uyarı (SLC kopyaları tükeniyor)%10–20 kullanıldı
0x03Acil (cihazı değiştirin)%20–30 kullanıldı
0x0A%90–100 kullanıldı
0x0B>%100 (aşılmış!)

Sistemd sağlık izleme servisi

# /etc/systemd/system/emmc-health-check.service
[Unit]
Description=eMMC Health Monitor
After=multi-user.target

[Service]
Type=oneshot
ExecStart=/usr/sbin/emmc-health-report.sh
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

---
# /etc/systemd/system/emmc-health-check.timer
[Unit]
Description=eMMC Health Check — günlük

[Timer]
OnCalendar=daily
Persistent=true

[Install]
WantedBy=timers.target

07 Wear leveling ve tuning

eMMC iç wear leveling algoritması otomatik çalışır; ancak host tarafında scheduler, fstrim ve ext4 seçenekleri ek optimizasyon sağlar.

I/O Scheduler seçimi

eMMC managed storage olduğundan, iç kontrolcü komut sıralamasını kendisi yapar. Host scheduler'ın ek maliyet getirmemesi için mq-deadline veya none tercih edilir.

# Mevcut scheduler'ı gör
cat /sys/block/mmcblk0/queue/scheduler
# [mq-deadline] none kyber bfq

# mq-deadline olarak ayarla
echo mq-deadline > /sys/block/mmcblk0/queue/scheduler

# Udev kuralı ile kalıcı yap:
# /etc/udev/rules.d/60-mmc-scheduler.rules
ACTION=="add|change", KERNEL=="mmcblk[0-9]", \
    ATTR{queue/rotational}=="0", \
    ATTR{queue/scheduler}="mq-deadline"

ext4 tuning

# ext4 data bölümünü flash için optimize et
# Zaten oluşturulmuş bölümde:
tune2fs -o journal_data_writeback /dev/mmcblk0p5
tune2fs -O ^has_journal /dev/mmcblk0p5   # journal'ı kapat (kritik veri yoksa)
tune2fs -E discard /dev/mmcblk0p5        # TRIM/DISCARD etkinleştir

# fstab mount seçenekleri:
# /dev/mmcblk0p5 /data ext4 noatime,nodiratime,discard,data=writeback 0 2

fstrim ile düzenli TRIM

# Manuel trim
fstrim -v /data
# /data: 256 MiB (268435456 bytes) trimmed

# Systemd timer ile haftalık trim
systemctl enable fstrim.timer
systemctl start fstrim.timer

# fstrim.timer ne kadar sıklıkla çalışıyor?
systemctl cat fstrim.timer | grep OnCalendar
# OnCalendar=weekly
İPUCU

eMMC'de discard mount seçeneği her silme işleminde eMMC'ye DISCARD komutu gönderir. Bu, sık yazma/silme işlemlerinde performans düşüşüne neden olabilir. Bunun yerine periyodik fstrim (ör: gece yarısı) daha dengeli bir yaklaşımdır.

Yazma I/O'yu azaltma stratejileri

tmpfs log/var/log'u tmpfs'e taşı — syslog flash'a yazma yükü ortadan kalkar
journal kompressystemd-journald Storage=volatile veya log_level azaltma
noatimeHer dosya erişiminde atime güncellemesini kapat — %20–30 yazma azalması
ro rootfsRootfs bölümüne sıfır yazma — en büyük kazanım

08 Pratik: Üretim eMMC provision scripti

Üretim hattında her cihaza uygulanacak eksiksiz provision scripti: bölümleme, imaj yazma, boot partition yapılandırması ve RPMB anahtar programlama.

Tam provision scripti

#!/bin/bash
# production-provision.sh — Üretim eMMC Provision
# Kullanım: ./production-provision.sh /dev/mmcblk0 images/
set -euo pipefail

DEVICE=${1:?Cihaz gerekli: /dev/mmcblk0}
IMG_DIR=${2:?İmaj dizini gerekli}
LOG=/var/log/provision-$(date +%Y%m%d-%H%M%S).log

log() { echo "[$(date '+%T')] $*" | tee -a $LOG; }

log "=== Üretim Provision Başlıyor: $DEVICE ==="

# 1. Eski bölüm tablosunu temizle
log "Bölüm tablosu temizleniyor..."
sgdisk --zap-all $DEVICE

# 2. GPT bölümleme
log "GPT bölümleri oluşturuluyor..."
sgdisk \
    --new=1:2048:6143    --change-name=1:"uboot-env" \
    --new=2:6144:137215  --change-name=2:"boot"      \
    --new=3:137216:1185791 --change-name=3:"rootfs-a" \
    --new=4:1185792:2234367 --change-name=4:"rootfs-b" \
    --new=5:2234368:0    --change-name=5:"data"       \
    $DEVICE

partprobe $DEVICE
sleep 1

# 3. Boot filesystem
log "Boot bölümü formatlanıyor..."
mkfs.vfat -F 32 -n "BOOT" ${DEVICE}p2

# 4. Data bölümü
log "Data bölümü formatlanıyor..."
mkfs.ext4 -L data -O ^has_journal -E discard ${DEVICE}p5

# 5. Boot partitionları aç, U-Boot yaz
log "U-Boot boot0'a yazılıyor..."
echo 0 > /sys/class/block/$(basename ${DEVICE})boot0/force_ro
dd if=$IMG_DIR/u-boot.imx of=${DEVICE}boot0 bs=512 seek=0 conv=fsync
echo 1 > /sys/class/block/$(basename ${DEVICE})boot0/force_ro

# 6. Boot partition etkinleştir
log "Boot partition etkinleştiriliyor..."
mmc bootpart enable 1 1 $DEVICE

# 7. Kernel + DTB boot bölümüne kopyala
log "Kernel ve DTB kopyalanıyor..."
MNT=$(mktemp -d)
mount ${DEVICE}p2 $MNT
cp $IMG_DIR/Image       $MNT/
cp $IMG_DIR/*.dtb        $MNT/
cp $IMG_DIR/initramfs.cpio.gz $MNT/ 2>/dev/null || true
umount $MNT

# 8. RootFS A'ya squashfs yaz
log "RootFS A yazılıyor..."
dd if=$IMG_DIR/rootfs.squashfs of=${DEVICE}p3 bs=4M conv=fsync status=progress

# 9. RootFS B'ye aynısını yaz (başlangıç senkron)
log "RootFS B (kopya) yazılıyor..."
dd if=$IMG_DIR/rootfs.squashfs of=${DEVICE}p4 bs=4M conv=fsync status=progress

# 10. RPMB anahtar provision (varsa)
if [ -f "$IMG_DIR/rpmb.key" ]; then
    log "RPMB anahtarı programlanıyor..."
    mmc rpmb write-key ${DEVICE}rpmb $DEVICE < $IMG_DIR/rpmb.key
fi

# 11. Doğrulama
log "=== Provision Doğrulama ==="
sgdisk --print $DEVICE | tee -a $LOG
mmc extcsd read $DEVICE | grep -E "Boot|PARTITION_CONFIG" | tee -a $LOG

log "=== PROVISION TAMAMLANDI ==="
echo "Log: $LOG"

Provision sonrası sağlık kontrolü

#!/bin/bash
# post-provision-check.sh
DEVICE=${1:-/dev/mmcblk0}

echo "Bölüm düzeni:"
lsblk $DEVICE -o NAME,SIZE,FSTYPE,LABEL,MOUNTPOINT

echo ""
echo "eMMC sağlık:"
mmc extcsd read $DEVICE | grep -E "PRE_EOL|LIFE_TIME|BOOT_SIZE"

echo ""
echo "Boot partition:"
mmc bootpart get $DEVICE
ÖZET

eMMC, ham NAND'ın tüm düşük seviyeli karmaşıklığını soyutlayan yönetilen bir depolama standardıdır. Üretim kaliteli sistemlerde; GPT bölümleme, boot0 kullanımı, RPMB key provisioning ve düzenli sağlık izleme birlikte ele alınmalıdır. mmc-utils bu işlemlerin tamamını komut satırından gerçekleştirmenizi sağlar.