Başta şunu söyleyeyim: Zephyr öğrenmek kolay değil. Zaman ve emek istiyor. Ama verdiği şeyler var.
Bu yazı, o yatırımın karşılığında neler aldığınızı ve henüz önemli olmayan kısımlarda aylar kaybetmeden bu yatırımı nasıl yapacağınızı anlatıyor.
İş kalitesi ve hız#
Zephyr’in sağladığı araçlar ve ekosistem sayesinde hem daha hızlı hem daha kaliteli iş çıkarabiliyorsunuz. Tekrar eden şeylere daha az zaman harcıyorsunuz, asıl probleme daha fazla odaklanabiliyorsunuz.
Tekrar eden şeyleri saymak kolay, çünkü her ürün onlara ihtiyaç duyuyor: bir log, bir debug shell’i, ayarları reboot’tan sonra da tutacak bir yer, güncelleme alabilen bir bootloader, bir test altyapısı, karttaki parçalar için driver’lar. Bare-metal’de bunların her biri günler ya da haftalar süren bir iş ve çoğu bir sonraki projede yeniden yapılıyor. Zephyr’de ise çoğu yalnızca yapılandırma.
Somut bir örnek: main() fonksiyonu hiçbir şey yapmayan bir uygulama, artı
prj.conf dosyasında şu satırlar:
CONFIG_SHELL=y
CONFIG_KERNEL_SHELL=y
CONFIG_DEVICE_SHELL=y
CONFIG_THREAD_MONITOR=y
CONFIG_THREAD_NAME=y
CONFIG_THREAD_STACK_INFO=y
CONFIG_INIT_STACKS=y
Bu kadarı, konsol UART’ında çalışan sistemi inceleme komutlarıyla birlikte etkileşimli bir shell veriyor. Zephyr 4.4.2 ile native_sim üzerinde şöyle görünüyor:
uart:~$ kernel version
Zephyr version 4.4.2
uart:~$ kernel thread list
Scheduler: 0 since last call
Threads:
*0x805e4e0 shell_uart
options: 0x0, priority: 14 timeout: 0
state: queued, entry: 0x804d871
stack size 2048, unused 2024, usage 24 / 2048 (1 %)
0x805ec80 idle
options: 0x1, priority: 15 timeout: 0
state: , entry: 0x8050df8
stack size 256, unused 232, usage 24 / 256 (9 %)
uart:~$ device list
devices:
- uart (READY)
DT node labels: uart0
Gerçek bir kartta aynı kernel thread list komutu, thread stack’lerini tahmin
yerine ölçerek boyutlandırmanın yolu. (Yukarıdaki stack rakamlarını fazla
ciddiye almayın: native_sim’de thread’ler aslında host stack’leri üzerinde
çalışıyor, bu yüzden görünen kullanım anlamsız. Donanımda ise gerçek.)
Bare-metal’de elle yazıldığında böyle bir komut satırı ciddi bir iş; burada
yedi satırlık yapılandırma.
Driver’lar da aynı şekilde çalışıyor. Zephyr 4.4.2, tek bir sensör API’sının arkasında 200’den fazla sensör driver’ıyla geliyor; ekranlar, flash entegreleri, radyolar ve diğerleri için de durum aynı. Karttaki parça destekleniyorsa onu kullanmak, bir datasheet ve register haritasıyla geçen bir hafta değil, bir devicetree node’u ve birkaç API çağrısı.
Daha iyi bir mühendis#
Bunun ötesinde Zephyr sizi daha iyi bir mühendis olmaya itiyor. Zephyr’den önce yazdığım kodlar yeterince soyutlanmış değildi. Bunu fark etmeden devam ediyorduk, çünkü bare-metal dünyasında bu bir zorunluluk değil. Ama iyi soyutlanmamış kod doğrudan test edilebilirliği ve modülerliği etkiliyor; yani teknik borç birikiyor, bakımı zorlaşıyor.
Pratikte nasıl göründüğüne bakalım. Bare-metal kodun genelde yazıldığı şekilde yazılmış bir buton debouncer’ı, pini kendisi okuyor:
bool button_pressed(void)
{
static uint8_t count;
static bool state;
bool level = (GPIOA->IDR & GPIO_IDR_ID0) != 0; /* reads the pin itself */
if (level == state) {
count = 0;
return false;
}
if (++count < THRESHOLD) {
return false;
}
state = level;
count = 0;
return state;
}
Çalışıyor. Ama yalnızca bir butona basarak, o tek kartta, o tek pinle test edilebiliyor. Mantık, donanım erişimi ve durum hep aynı yerde.
Zephyr’in driver modeli ve mimari yapısı sizi bunu doğru yapmaya neredeyse zorluyor. Donanım erişimi bir API üzerinden yapıldığı için doğal şekil, örneği argüman olarak alan bir mantık ve okumayı yapan bir çağıran oluyor:
bool debounce_update(struct debounce *d, bool sample);
/* the caller, once per tick: */
if (debounce_update(&btn, gpio_pin_get_dt(&button) > 0)) {
/* the debounced state changed */
}
Artık mantık her yerde çalışan düz C kodu; buna native_sim ile kendi bilgisayarınızda çalışan bir birim testi de dahil. Pin ise devicetree’nin işi. Başta ağır geliyor, zamanla alışkanlık haline geliyor. Bu alışkanlık Zephyr’den sonra da kalıyor: bir kez bu şekilde yazmak zorunda kaldıktan sonra FreeRTOS ve bare-metal kodunuz da daha iyi oluyor.
Bir de daha sessiz bir faydası var. Device Tree ve Kconfig, Zephyr’in icadı değil. İkisi de Linux kernel’inden geliyor ve U-Boot da ikisini kullanıyor. Onlara harcadığınız zaman, gömülü Linux’a dokunduğunuz gün de geri dönüyor.
Kariyer#
Türkiye’de henüz yaygın olmasa da Avrupa ve Amerika’daki iş ilanlarında Zephyr artık sıkça karşımıza çıkan bir yetenek haline geldi. Önümüzdeki yıllarda Türkiye’de de aynı trendin geleceğine inanıyorum. Şu an öğrenmek, o dalganın önünde olmak demek.
Yönü üreticiler tarafında da görmek mümkün. Nordic, nRF5 SDK’sını 2021’de bakım moduna aldı; yeni geliştirmesini Zephyr tabanlı nRF Connect SDK’da yapıyor. Projenin platinum üyeleri arasında Google, Meta, Intel, NXP, Nordic, Qualcomm, Renesas, Silicon Labs ve Analog Devices var; Ekim 2026’da Texas Instruments ve Infineon da bu seviyeye çıktı. Şirketler, üzerine ürün geliştirmeyi düşünmedikleri bir projenin en üst üyelik seviyesine para ödemez.
Gözden kaçması kolay bir şey daha: Zephyr deneyimi, çoğu gömülü işin olmadığı kadar herkese açık. İşte yazdığınız firmware ürünlerin ve gizlilik sözleşmelerinin içinde kayboluyor. Zephyr’de merge edilmiş bir pull request ise, küçük bir düzeltme bile olsa, adınızla birlikte herkesin görebileceği şekilde kalıcı olarak duruyor.
Aylar kaybetmeden nasıl başlanır#
- native_sim ile başlayın. Kart yok, flash’lama yok, debugger yok: bütün kernel bilgisayarınızda bir süreç olarak çalışıyor; deneme yapmanın en ucuz yolu bu.
- Sonra iyi desteklenen tek bir geliştirme kartı seçin, örneğin bir nRF52840 DK ya da bir STM32 Nucleo. Bu tür kartların ağaçta en çok örneği var; zamanınızı bring-up’a değil Zephyr’e harcıyorsunuz.
- Parçaları sırayla öğrenin: önce build, sonra Device Tree, sonra Kconfig, sonra tek bir driver sınıfı. Bu sıranın neden işe yaradığını serinin ilk yazısı anlatıyor.
- Küçük bir şeyi baştan sona yapın: I2C üzerinden bir sensör okuyun, değeri BLE ile gönderin ve mantık için CI’da bir birim testi koşturun. Bu tek proje devicetree’ye, Kconfig’e, bir driver’a, Bluetooth stack’ine ve test altyapısına dokunuyor.
- Dokümantasyon yetmediğinde örnekleri okuyun.
samples/klasörü çoğu zaman en net dokümantasyon, çünkü derlenmek zorunda. - Upstream’e bir katkı gönderin. Bir dokümantasyon düzeltmesi de sayılır. Size review sürecini öğretiyor ve herkese açık kaydı başlatıyor.
Zephyr’e yatırım yapmak aslında kendinize yatırım yapmak.