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

Zephyr RTOS
MCU Geliştirme

Linux Foundation destekli gerçek zamanlı işletim sistemi — nRF52840, STM32F4 ve ESP32 üzerinde Devicetree, Kconfig, thread yönetimi ve periferallar.

00 Zephyr nedir

Zephyr, Linux Foundation çatısı altında geliştirilen, küçük MCU'lardan karmaşık SoC'lere kadar geniş donanım yelpazesini destekleyen açık kaynaklı gerçek zamanlı işletim sistemidir.

Proje özellikleri

Zephyr RTOS, 2016'da Intel tarafından Linux Foundation'a bağışlanan Rocket OS'tan türetilmiştir. Günümüzde Nordic Semiconductor, STMicroelectronics, NXP, Intel, Espressif ve diğer büyük yarı iletken firmaların katkılarıyla gelişmektedir. Apache 2.0 lisansıyla dağıtılır — ticari kullanımda lisans ücreti yoktur.

Kaynak verimliliğiMinimum konfigürasyonda 8 KB RAM ve 8 KB Flash ile çalışabilir — küçük Cortex-M0 için bile uygun
Geniş board desteği700+ board desteklenir — nRF52840, STM32 serisi, ESP32, RISC-V, ARM64, x86 dahil
Güvenlik odaklıMPU/MMU koruması, stack sentinel, TF-M (Trusted Firmware-M) entegrasyonu
Standart uyumlulukPOSIX threads, BSD sockets, BT stack (BlueZ tabanlı), Matter, Thread, Zigbee

Desteklenen önemli board'lar

BoardMCUÖzellikZephyr adı
nRF52840 DKARM Cortex-M4FBLE 5.0, Zigbee, Thread, USBnrf52840dk/nrf52840
nRF9160 DKARM Cortex-M33LTE-M, NB-IoT, GPS, TrustZonenrf9160dk/nrf9160
STM32F4 DiscoveryARM Cortex-M4FUSB OTG, CAN, SDIOstm32f4_disco
STM32H7 NucleoARM Cortex-M7480 MHz, Ethernet, DSPnucleo_h743zi
ESP32-S3Xtensa LX7WiFi, BLE 5.0, USB OTGesp32s3_devkitc
Raspberry Pi PicoARM Cortex-M0+PIO, USB, dual-corerpi_pico
BBC micro:bit v2ARM Cortex-M4FBLE, sensörler, eğitimbbc_microbit_v2

west — birleşik meta araç

west (Werkzeug for Embedded Systems Tool), Zephyr ekosisteminin bütünleşik komut satırı aracıdır. Birden fazla Git deposunu (Zephyr kernel + HAL'lar + modüller) yönetir ve build, flash, debug, boards gibi subcommand'lar sunar.

Bu bölümde

  • Zephyr: Linux Foundation, Apache 2.0, 700+ board, 8 KB RAM'de çalışır
  • Nordic, ST, NXP, Espressif — büyük fabrikalar tarafından desteklenir
  • west: çoklu repo yönetimi + build + flash + debug — tek araç

01 Geliştirme ortamı kurulumu

Zephyr geliştirme ortamı west, Python sanal ortamı, Zephyr SDK (toolchain) ve CMake'ten oluşur. Kurulum adımları tüm platformlarda benzerdir.

Sistem bağımlılıkları

bash — Ubuntu/Debian bağımlılıklar
# Temel araçlar
sudo apt install --no-install-recommends \
  git cmake ninja-build gperf \
  ccache dfu-util device-tree-compiler wget \
  python3-dev python3-pip python3-setuptools python3-tk \
  python3-wheel xz-utils file make gcc gcc-multilib \
  g++-multilib libsdl2-dev libmagic1

west ve Python sanal ortam

bash — west kurulumu
# Python sanal ortam oluştur (önerilir)
python3 -m venv ~/zephyrproject/.venv
source ~/zephyrproject/.venv/bin/activate

# west kur
pip install west

# Zephyr deposunu başlat (tüm bağımlılıklarla)
west init ~/zephyrproject
cd ~/zephyrproject

# Tüm bağımlı depoları indir (HAL'lar, modüller, vb.)
west update

# Python bağımlılıklarını kur
pip install -r ~/zephyrproject/zephyr/scripts/requirements.txt

Zephyr SDK (toolchain) kurulumu

bash — SDK kurulumu
# SDK indirme (aarch64 Linux için örnek — minimal)
wget https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.8/\
zephyr-sdk-0.16.8_linux-x86_64_minimal.tar.xz

tar xvf zephyr-sdk-0.16.8_linux-x86_64_minimal.tar.xz -C ~/

# SDK'yı kur (toolchain'leri ekle)
cd ~/zephyr-sdk-0.16.8
./setup.sh

# Yalnızca belirli toolchain'leri kur (ARM + RISC-V)
./setup.sh -t arm-zephyr-eabi -t riscv64-zephyr-elf

# udev kurallarını kur (Linux — USB probe erişimi)
sudo cp ~/zephyr-sdk-0.16.8/sysroots/x86_64-pokysdk-linux/usr/share/openocd/contrib/60-openocd.rules \
  /etc/udev/rules.d/
sudo udevadm control --reload

Ortam değişkenleri

bash — ~/.bashrc veya ~/.zshrc
# Zephyr ortam değişkenleri
export ZEPHYR_BASE=~/zephyrproject/zephyr
export ZEPHYR_SDK_INSTALL_DIR=~/zephyr-sdk-0.16.8

# west workspace'i aktifleştir
source ~/zephyrproject/.venv/bin/activate

# Zephyr cmake modüllerini aktifleştir
source $ZEPHYR_BASE/zephyr-env.sh

Bu bölümde

  • west init + west update: çoklu repo workspace oluşturur
  • Python venv: bağımlılık çakışmalarını önler — her zaman önerilir
  • Zephyr SDK: platform başına toolchain; minimal kurulumda yalnızca hedef mimari
  • ZEPHYR_BASE ve ZEPHYR_SDK_INSTALL_DIR ortam değişkenleri şart

02 İlk uygulama: hello world

Zephyr'de uygulama yapısı CMakeLists.txt, prj.conf ve kaynak dosyalardan oluşur. west build komutu hedef board için derler.

Uygulama yapısı

bash — proje dizin yapısı
my_app/
├── CMakeLists.txt
├── prj.conf
└── src/
    └── main.c
cmake — CMakeLists.txt
cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(my_app)

target_sources(app PRIVATE src/main.c)
C — src/main.c
#include <zephyr/kernel.h>
#include <zephyr/sys/printk.h>

int main(void)
{
    printk("Hello, Zephyr! Board: %s\n", CONFIG_BOARD);

    while (1) {
        printk("Uptime: %lld ms\n", k_uptime_get());
        k_msleep(1000);
    }
    return 0;
}

Build, flash ve debug

bash — build / flash / debug
# nRF52840 DK için derle
west build -b nrf52840dk/nrf52840 my_app

# STM32F4 Discovery için derle
west build -b stm32f4_disco my_app

# ESP32 için derle
west build -b esp32_devkitc_wroom/esp32/procpu my_app

# Build çıktısı
ls build/zephyr/
# zephyr.elf  zephyr.hex  zephyr.bin  zephyr.map

# Flash (probe otomatik algılanır)
west flash

# Temiz build (önce CMake cache'i temizle)
west build -p always -b nrf52840dk/nrf52840 my_app

# GDB ile debug başlat
west debug

# Seri konsol (minicom, picocom veya screen)
minicom -D /dev/ttyACM0 -b 115200

Mevcut board'ları listele

bash — board keşfi
# Tüm board'ları listele
west boards

# Belirli SoC ailesi için filtrele
west boards --soc-series stm32f4

# Board hakkında detay
west boards --arch arm | grep nrf52

Bu bölümde

  • Uygulama: CMakeLists.txt + prj.conf + src/main.c — minimal 3 dosya
  • west build -b <board>: board hedefini belirler; çoklu mimari için aynı kaynak
  • west flash: J-Link, OpenOCD veya ESP-IDF araçlarını otomatik seçer
  • -p always: temiz build; geliştirme sırasında nadiren gerekir

03 Devicetree

Devicetree, donanım topolojisini kaynak koddan ayıran bir veri formatıdır. Zephyr, Linux'la aynı DTS sözdizimini kullanır ancak runtime çözünürlük yerine derleme zamanında işler.

DTS dosya hiyerarşisi

Dosya türüYerGörev
.dtsiZephyr kaynak (SoC tanımı)SoC registerları, varsayılan konfigürasyon
.dtsBoard diziniBoard-spesifik bağlantılar, pinmux, flash/RAM boyutu
.overlayUygulama diziniUygulama ihtiyaçlarına göre board DTS'yi override et

DTS sözdizimi

dts — temel yapı
/* boards/arm/nrf52840dk_nrf52840/nrf52840dk_nrf52840.dts (sadeleştirilmiş) */
/dts-v1/;
#include <nordic/nrf52840.dtsi>
#include "nrf52840dk_nrf52840-pinctrl.dtsi"

/ {
    model = "Nordic nRF52840 DK";
    compatible = "nordic,nrf52840-dk-nrf52840";

    chosen {
        zephyr,console = &uart0;         /* konsol UART'ı */
        zephyr,shell-uart = &uart0;
        zephyr,sram = &sram0;
        zephyr,flash = &flash0;
    };

    aliases {
        led0 = &led0;
        sw0  = &button0;
    };

    leds {
        compatible = "gpio-leds";
        led0: led_0 {
            gpios = &gpio0 13 GPIO_ACTIVE_LOW;
            label = "Green LED 0";
        };
    };
};

&uart0 {
    compatible = "nordic,nrf-uarte";
    status = "okay";
    current-speed = <115200>;
    pinctrl-0 = &uart0_default;
    pinctrl-names = "default";
};

Overlay ile özelleştirme

dts — app.overlay
/* boards/nrf52840dk_nrf52840.overlay — uygulama dizininde */

/* Var olan UART baud hızını değiştir */
&uart0 {
    current-speed = <9600>;
};

/* Yeni bir I2C cihazı ekle */
&i2c0 {
    status = "okay";

    bme280: bme280@76 {
        compatible = "bosch,bme280";
        reg = <0x76>;
    };
};

/* Alias ekle */
/ {
    aliases {
        mysensor = &bme280;
    };
};

C kodunda DT makroları

C — DT makroları kullanımı
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/gpio.h>

/* DT nodespec'i al (alias üzerinden) */
#define LED0_NODE DT_ALIAS(led0)

/* GPIO spec oluştur */
static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(LED0_NODE, gpios);

int main(void)
{
    if (!gpio_is_ready_dt(&led)) {
        return -ENODEV;
    }
    gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE);

    while (1) {
        gpio_pin_toggle_dt(&led);
        k_msleep(500);
    }
    return 0;
}

Bu bölümde

  • .dtsi (SoC) → .dts (board) → .overlay (uygulama): katmanlı özelleştirme
  • chosen: konsol, sram, flash bağlamaları
  • aliases: cihaz bağımsız erişim — DT_ALIAS(led0)
  • DEVICE_DT_GET() / GPIO_DT_SPEC_GET(): derleme zamanı DT bağlaması

04 Kconfig

Kconfig, kernel özelliklerini seçmenin sistematik yoludur. Her CONFIG_ seçeneği derleme zamanında C koduna, bağlayıcıya ve CMake'e yansır.

prj.conf — uygulama konfigürasyonu

kconfig — prj.conf örneği
# Temel sistem
CONFIG_PRINTK=y
CONFIG_STDOUT_CONSOLE=y

# Thread yapılandırması
CONFIG_MAIN_STACK_SIZE=2048
CONFIG_HEAP_MEM_POOL_SIZE=4096

# BLE etkinleştir
CONFIG_BT=y
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_DEVICE_NAME="Zephyr BLE"

# UART
CONFIG_UART_ASYNC_API=y

# Logging
CONFIG_LOG=y
CONFIG_LOG_DEFAULT_LEVEL=3   # 3 = INFO

# Shell
CONFIG_SHELL=y
CONFIG_SHELL_BACKEND_SERIAL=y

menuconfig — interaktif konfigürasyon

bash — menuconfig ve Kconfig araçları
# Grafik Kconfig arayüzü (ncurses)
west build -t menuconfig

# Sadece Zephyr kernel Kconfig'i göster
west build -t guiconfig      # Qt tabanlı GUI

# Mevcut build konfigürasyonunu göster
cat build/zephyr/.config | grep CONFIG_BT

# Hangi dosyanın hangi CONFIG_'i ayarladığını bul
west build -t kconfig_old_defconfig

Kconfig fragment ve çakışma çözümü

bash — fragment (-DCONF_FILE)
# Birden fazla .conf dosyasını birleştir
west build -b nrf52840dk/nrf52840 \
  -DCONF_FILE="prj.conf;debug.conf"

# debug.conf — debug derlemesi için ek ayarlar
# CONFIG_DEBUG=y
# CONFIG_LOG_DEFAULT_LEVEL=4
# CONFIG_ASSERT=y

# Board spesifik override (boards/nrf52840dk_nrf52840.conf)
# west otomatik yükler

Kconfig C kodunda kullanım

C — CONFIG_ makrolarını kullanma
#include <zephyr/kernel.h>

int main(void)
{
#if defined(CONFIG_BT)
    printk("BLE desteği aktif\n");
    printk("Cihaz adı: %s\n", CONFIG_BT_DEVICE_NAME);
#endif

    /* Sayısal CONFIG değeri */
    printk("Main stack: %d bytes\n", CONFIG_MAIN_STACK_SIZE);

    /* IS_ENABLED makrosu — daha güvenli */
    if (IS_ENABLED(CONFIG_LOG)) {
        printk("Logging aktif\n");
    }

    return 0;
}

Bu bölümde

  • prj.conf: uygulama Kconfig seçimleri — CONFIG_X=y veya =n veya =sayı
  • west build -t menuconfig: interaktif ncurses arayüzü
  • Fragment: -DCONF_FILE ile birden fazla .conf birleştirme
  • C kodunda IS_ENABLED() — preprocessor güvenli kontrol

05 Thread'ler ve zamanlama

Zephyr, öncelik tabanlı preemptive (ve cooperative) zamanlama ile çoklu thread desteği sunar. Thread'ler statik veya dinamik olarak oluşturulabilir.

K_THREAD_DEFINE ile statik thread

C — statik thread tanımı
#include <zephyr/kernel.h>

/* Thread fonksiyonu */
void sensor_thread(void *arg1, void *arg2, void *arg3)
{
    ARG_UNUSED(arg1); ARG_UNUSED(arg2); ARG_UNUSED(arg3);

    while (1) {
        printk("Sensör okuyor...\n");
        k_msleep(500);
    }
}

/* Statik thread: stack 1024 byte, öncelik 5, hemen başlat */
K_THREAD_DEFINE(sensor_tid,       /* thread ID değişkeni */
                1024,              /* stack boyutu */
                sensor_thread,     /* giriş fonksiyonu */
                NULL, NULL, NULL,  /* arg1, arg2, arg3 */
                5,                 /* öncelik (düşük sayı = yüksek öncelik) */
                0,                 /* seçenekler */
                0);                /* gecikme (ms) — 0 = hemen başlat */

k_thread_create ile dinamik thread

C — dinamik thread oluşturma
#include <zephyr/kernel.h>

/* Stack tanımı (statik — gömülü sistemlerde heap yerine tercih edilir) */
K_THREAD_STACK_DEFINE(worker_stack, 2048);
static struct k_thread worker_data;

void worker_func(void *a, void *b, void *c)
{
    int *count = (int *)a;
    while (1) {
        (*count)++;
        k_msleep(100);
    }
}

int main(void)
{
    static int counter = 0;

    k_tid_t tid = k_thread_create(
        &worker_data,              /* k_thread struct */
        worker_stack,              /* stack bellek */
        K_THREAD_STACK_SIZEOF(worker_stack),
        worker_func,               /* giriş fonksiyonu */
        &counter, NULL, NULL,      /* argümanlar */
        3,                         /* öncelik */
        0,                         /* seçenekler */
        K_NO_WAIT                  /* hemen başlat */
    );

    k_thread_name_set(tid, "worker");

    while (1) {
        printk("Counter: %d\n", counter);
        k_msleep(1000);
    }
    return 0;
}

Öncelik sistemi ve zamanlama modları

KavramAçıklama
Öncelik aralığı-CONFIG_NUM_COOP_PRIORITIES (-16)…+CONFIG_NUM_PREEMPT_PRIORITIES (+15)
Cooperative (negatif)Gönüllü yield veya blocking çağrı olana kadar CPU bırakmaz
Preemptive (0 ve üzeri)Daha yüksek öncelikli thread hazır olduğunda kernel preempt eder
k_yield()Cooperative thread'de aynı öncelikli thread'e CPU ver
k_sleep() / k_msleep()Thread'i belirli süre uyut — scheduler başka thread çalıştırır
Round-robinAynı öncelikli preemptive thread'ler time-slice alır (CONFIG_TIMESLICING=y)
C — öncelik ve zaman dilimleme
/* prj.conf */
/* CONFIG_TIMESLICING=y */
/* CONFIG_TIMESLICE_SIZE=10  (10 ms time slice) */
/* CONFIG_TIMESLICE_PRIORITY=0 */

/* Runtime öncelik değiştirme */
k_thread_priority_set(tid, 2);

/* Thread'i askıya al / devam ettir */
k_thread_suspend(tid);
k_thread_resume(tid);

/* Thread sonlandırma */
k_thread_abort(tid);

Bu bölümde

  • K_THREAD_DEFINE: derleme zamanı statik thread — gömülü için ideal
  • k_thread_create: çalışma zamanı dinamik thread oluşturma
  • Negatif öncelik = cooperative; 0+ = preemptive
  • CONFIG_TIMESLICING ile aynı öncelikli thread'ler round-robin paylaşır

06 Senkronizasyon primitifleri

Zephyr, thread'ler ve ISR'lar arasında güvenli veri paylaşımı için zengin senkronizasyon API'si sunar. Her primitifin kullanım amacı farklıdır.

k_sem — semafor

C — semaphore kullanımı
#include <zephyr/kernel.h>

/* Statik semafor: başlangıç değeri 0, maksimum 1 */
K_SEM_DEFINE(data_ready_sem, 0, 1);

/* ISR içinden semafor ver (sinyal gönder) */
void uart_isr_callback(const struct device *dev, void *user_data)
{
    k_sem_give(&data_ready_sem);   /* ISR güvenli */
}

/* Thread: veriyi bekle */
void consumer_thread(void *a, void *b, void *c)
{
    while (1) {
        /* Semafor alınana kadar bekle (500 ms timeout) */
        int ret = k_sem_take(&data_ready_sem, K_MSEC(500));
        if (ret == 0) {
            printk("Veri hazır, işleniyor\n");
        } else {
            printk("Timeout!\n");
        }
    }
}

k_mutex — mutex

C — mutex ile kritik bölge
#include <zephyr/kernel.h>

K_MUTEX_DEFINE(shared_resource_mutex);
static int shared_counter = 0;

void increment_safely(void)
{
    k_mutex_lock(&shared_resource_mutex, K_FOREVER);
    /* Kritik bölge başlangıcı */
    shared_counter++;
    /* Kritik bölge sonu */
    k_mutex_unlock(&shared_resource_mutex);
}

/* NOT: Zephyr mutex öncelik devralma (priority inheritance) destekler */
/* CONFIG_MUTEX_INIT_PRIORITY_DEFAULT ile yapılandırılır */

k_fifo ve k_msgq — kuyruk yapıları

C — FIFO ve mesaj kuyruğu
#include <zephyr/kernel.h>

/* ─── k_fifo: dinamik bağlı liste ─── */
K_FIFO_DEFINE(sensor_fifo);

struct sensor_data {
    void *fifo_reserved;    /* k_fifo için ilk alan ayrılmış kalmalı */
    uint32_t timestamp;
    int16_t temperature;
};

/* Üretici thread */
void producer(void *a, void *b, void *c)
{
    while (1) {
        struct sensor_data *data = k_malloc(sizeof(*data));
        data->timestamp = k_uptime_get_32();
        data->temperature = 2500;   /* 25.00 °C */
        k_fifo_put(&sensor_fifo, data);
        k_msleep(100);
    }
}

/* Tüketici thread */
void consumer(void *a, void *b, void *c)
{
    while (1) {
        struct sensor_data *data = k_fifo_get(&sensor_fifo, K_FOREVER);
        printk("T=%u, temp=%d\n", data->timestamp, data->temperature);
        k_free(data);
    }
}

/* ─── k_msgq: sabit boyutlu, statik bellek ─── */
K_MSGQ_DEFINE(uart_msgq, sizeof(char), 64, 1);  /* 64 char kapasiteli kuyruk */

void uart_isr(void)
{
    char c = uart_read_char();
    k_msgq_put(&uart_msgq, &c, K_NO_WAIT);      /* ISR güvenli */
}

void uart_consumer(void *a, void *b, void *c)
{
    char c;
    while (1) {
        k_msgq_get(&uart_msgq, &c, K_FOREVER);
        printk("%c", c);
    }
}

Senkronizasyon primitif karşılaştırması

PrimitifKullanım senaryosuISR güvenliBellek
k_semOlay sinyali, kaynak sayacıEvet (give)Statik
k_mutexKritik bölge korumasıHayırStatik
k_condvarKoşul değişkeni (mutex ile birlikte)HayırStatik
k_fifoDeğişken boyutlu veri kuyruğuEvetDinamik (heap)
k_msgqSabit boyutlu mesaj kuyruğuEvetStatik
k_pipeByte akışı (üretici-tüketici)KısıtlıStatik

Bu bölümde

  • k_sem: olay sinyali — ISR'dan thread'e en yaygın iletişim yolu
  • k_mutex: öncelik devralmalı — gömülü RT sistemlerde kritik
  • k_msgq: sabit boyut, statik bellek — ISR güvenli, gömülü için tercih edilir
  • k_fifo: dinamik bağlı liste — heap gerektirir; büyük değişken veri için

07 Peripheral sürüş

Zephyr'de tüm periferallar Devicetree tabanlı, tutarlı bir driver API'siyle sürülür. Cihaz nesnesi DT'den alınır; HAL fonksiyonları MCU bağımsızdır.

GPIO

C — GPIO çıkış ve girişi
#include <zephyr/kernel.h>
#include <zephyr/drivers/gpio.h>

/* DT alias'larından GPIO spec al */
static const struct gpio_dt_spec led  = GPIO_DT_SPEC_GET(DT_ALIAS(led0),  gpios);
static const struct gpio_dt_spec btn  = GPIO_DT_SPEC_GET(DT_ALIAS(sw0),   gpios);

/* GPIO interrupt callback */
static struct gpio_callback btn_cb_data;
void button_pressed(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
{
    printk("Butona basıldı!\n");
}

int main(void)
{
    /* Çıkış konfigürasyonu */
    gpio_pin_configure_dt(&led, GPIO_OUTPUT_INACTIVE);

    /* Giriş konfigürasyonu + interrupt */
    gpio_pin_configure_dt(&btn, GPIO_INPUT | GPIO_PULL_UP);
    gpio_pin_interrupt_configure_dt(&btn, GPIO_INT_EDGE_TO_ACTIVE);
    gpio_init_callback(&btn_cb_data, button_pressed, BIT(btn.pin));
    gpio_add_callback(btn.port, &btn_cb_data);

    while (1) {
        gpio_pin_toggle_dt(&led);
        k_msleep(1000);
    }
    return 0;
}

UART

C — UART async API
#include <zephyr/kernel.h>
#include <zephyr/drivers/uart.h>

#define UART_DEVICE_NODE DT_CHOSEN(zephyr_shell_uart)
static const struct device *uart_dev = DEVICE_DT_GET(UART_DEVICE_NODE);

static uint8_t rx_buf[64];

void uart_callback(const struct device *dev, struct uart_event *evt, void *user_data)
{
    switch (evt->type) {
    case UART_RX_RDY:
        printk("UART RX: %d byte\n", evt->data.rx.len);
        break;
    case UART_TX_DONE:
        printk("UART TX tamamlandı\n");
        break;
    default:
        break;
    }
}

int main(void)
{
    uart_callback_set(uart_dev, uart_callback, NULL);
    uart_rx_enable(uart_dev, rx_buf, sizeof(rx_buf), 100 /* timeout us */);

    const char *msg = "Merhaba UART!\r\n";
    uart_tx(uart_dev, msg, strlen(msg), SYS_FOREVER_US);
    return 0;
}

I2C

C — I2C okuma/yazma
#include <zephyr/drivers/i2c.h>

#define I2C_NODE DT_NODELABEL(i2c0)
static const struct device *i2c_dev = DEVICE_DT_GET(I2C_NODE);

#define BME280_ADDR 0x76
#define BME280_REG_ID 0xD0

int main(void)
{
    uint8_t chip_id;
    uint8_t reg = BME280_REG_ID;

    /* Register yaz, sonra oku (write-then-read) */
    struct i2c_msg msgs[] = {
        { .buf = ®,     .len = 1, .flags = I2C_MSG_WRITE },
        { .buf = &chip_id, .len = 1, .flags = I2C_MSG_READ | I2C_MSG_STOP },
    };

    int ret = i2c_transfer(i2c_dev, msgs, ARRAY_SIZE(msgs), BME280_ADDR);
    if (ret == 0) {
        printk("BME280 chip ID: 0x%02X (beklenen: 0x60)\n", chip_id);
    }
    return 0;
}

Bu bölümde

  • GPIO: GPIO_DT_SPEC_GET + gpio_pin_configure_dt — DT-first API
  • UART async: callback tabanlı, DMA arkasında — ISR overhead yok
  • I2C: i2c_transfer ile write-then-read; i2c_write_read kısayol
  • Tüm driver'lar: DEVICE_DT_GET ile cihaz nesnesi, derleme zamanı doğrulama

08 Logging ve Shell

Zephyr'nin yerleşik logging altyapısı defer modunda çalışır — ISR veya kritik bölgelerde log mesajı güvenle çağrılabilir. Interaktif shell komutları kolayca eklenir.

Logging — LOG_MODULE_REGISTER

C — logging kullanımı
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>

/* Modül kaydı — her .c dosyasında bir kez */
LOG_MODULE_REGISTER(my_sensor, LOG_LEVEL_DBG);

void sensor_read(void)
{
    int temperature = 2543;   /* 25.43 °C * 100 */

    LOG_DBG("Ham değer: %d", temperature);
    LOG_INF("Sıcaklık: %d.%02d C", temperature / 100, temperature % 100);
    LOG_WRN("Değer yüksek sınıra yakın: %d", temperature);
    LOG_ERR("Sensör iletişim hatası!");

    /* Hex dump */
    uint8_t buf[] = {0x01, 0x02, 0xAB, 0xCD};
    LOG_HEXDUMP_DBG(buf, sizeof(buf), "I2C yanıtı");
}
kconfig — logging yapılandırması
# prj.conf
CONFIG_LOG=y
CONFIG_LOG_DEFAULT_LEVEL=3        # 0=none 1=err 2=warn 3=inf 4=dbg
CONFIG_LOG_MAX_LEVEL=4            # derleme zamanı maksimum seviye
CONFIG_LOG_BACKEND_UART=y         # UART backend
CONFIG_LOG_BACKEND_RTT=y          # Segger RTT backend (J-Link)

# Modül bazlı seviye override
CONFIG_LOG_OVERRIDE_LEVEL=4       # Tüm modülleri debug seviyesine çek
# ya da bireysel:
# CONFIG_MY_SENSOR_LOG_LEVEL=4

Zephyr Shell — komut ekleme

C — özel shell komutu
#include <zephyr/shell/shell.h>

/* Shell komutu implementasyonu */
static int cmd_hello(const struct shell *sh, size_t argc, char **argv)
{
    if (argc > 1) {
        shell_print(sh, "Merhaba, %s!", argv[1]);
    } else {
        shell_print(sh, "Merhaba, Zephyr!");
    }
    return 0;
}

static int cmd_stats(const struct shell *sh, size_t argc, char **argv)
{
    shell_print(sh, "Uptime: %lld ms", k_uptime_get());
    shell_print(sh, "Free heap: %zu bytes", k_mem_free_get());
    return 0;
}

/* Komut ağacı tanımı */
SHELL_STATIC_SUBCMD_SET_CREATE(sub_demo,
    SHELL_CMD(hello, NULL, "Selamlama komutu", cmd_hello),
    SHELL_CMD(stats, NULL, "Sistem istatistikleri", cmd_stats),
    SHELL_SUBCMD_SET_END
);

SHELL_CMD_REGISTER(demo, &sub_demo, "Demo komutları", NULL);
kconfig — shell yapılandırması
# prj.conf
CONFIG_SHELL=y
CONFIG_SHELL_BACKEND_SERIAL=y    # UART üzerinden shell
CONFIG_SHELL_BACKEND_RTT=y       # RTT üzerinden shell (J-Link)
CONFIG_SHELL_HISTORY=y           # Yukarı/aşağı tuş geçmişi
CONFIG_SHELL_TAB=y               # Tab ile otomatik tamamlama
CONFIG_SHELL_CMDS_RESIZE=y       # Ekran boyutuna uyum

Bu bölümde

  • LOG_MODULE_REGISTER(name, level): her dosyada bir kez; LOG_INF/WRN/ERR/DBG
  • Backend: UART (her zaman) veya RTT (J-Link bağlıyken latency yok)
  • SHELL_CMD_REGISTER: tab-complete, history, subcmd ağacı — sıfır ekstra kod
  • Shell + RTT: seri kablo olmadan interaktif debug

09 Pratik uygulamalar

Üç mini uygulama: nRF52840'ta BLE beacon, STM32F4'te UART echo ve ESP32'de WiFi station.

nRF52840 — BLE iBeacon

C — BLE non-connectable advertisement
#include <zephyr/kernel.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/hci.h>

/* iBeacon veri yapısı */
static const struct bt_data ad[] = {
    BT_DATA_BYTES(BT_DATA_FLAGS, BT_LE_AD_NO_BREDR),
    BT_DATA_BYTES(BT_DATA_MANUFACTURER_DATA,
        0x4C, 0x00,         /* Apple Company ID */
        0x02, 0x15,         /* iBeacon type & length */
        /* UUID: 12345678-1234-1234-1234-123456789ABC */
        0x12, 0x34, 0x56, 0x78,
        0x12, 0x34, 0x12, 0x34,
        0x12, 0x34, 0x12, 0x34,
        0x56, 0x78, 0x9A, 0xBC,
        0x00, 0x01,         /* Major */
        0x00, 0x01,         /* Minor */
        0xC5)               /* TX Power (-59 dBm) */
};

int main(void)
{
    int err = bt_enable(NULL);
    if (err) {
        printk("BT etkinleştirme hatası: %d\n", err);
        return err;
    }

    /* Non-connectable undirected advertising */
    err = bt_le_adv_start(BT_LE_ADV_NCONN, ad, ARRAY_SIZE(ad), NULL, 0);
    if (err) {
        printk("Advertising başlatma hatası: %d\n", err);
        return err;
    }

    printk("iBeacon yayını başladı\n");
    return 0;
}
kconfig — BLE beacon
# prj.conf
CONFIG_BT=y
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_DEVICE_NAME="Zephyr Beacon"
CONFIG_BT_DEVICE_APPEARANCE=0

STM32F4 — UART echo

C — UART echo uygulaması
#include <zephyr/kernel.h>
#include <zephyr/drivers/uart.h>

static const struct device *uart = DEVICE_DT_GET(DT_CHOSEN(zephyr_console));
static uint8_t rx_buf[1];

void uart_cb(const struct device *dev, struct uart_event *evt, void *ud)
{
    switch (evt->type) {
    case UART_RX_RDY:
        /* Alınan karakteri geri gönder (echo) */
        uart_tx(dev, evt->data.rx.buf + evt->data.rx.offset,
                evt->data.rx.len, SYS_FOREVER_US);
        break;
    case UART_RX_DISABLED:
        /* RX yeniden etkinleştir */
        uart_rx_enable(dev, rx_buf, sizeof(rx_buf), 1000);
        break;
    default:
        break;
    }
}

int main(void)
{
    uart_callback_set(uart, uart_cb, NULL);
    uart_rx_enable(uart, rx_buf, sizeof(rx_buf), 1000);

    printk("UART Echo hazır — yazmaya başlayın\n");
    k_sleep(K_FOREVER);
    return 0;
}

ESP32 — WiFi Station

C — WiFi station bağlantısı
#include <zephyr/kernel.h>
#include <zephyr/net/net_if.h>
#include <zephyr/net/wifi_mgmt.h>
#include <zephyr/net/net_event.h>

#define WIFI_SSID     "MyNetwork"
#define WIFI_PASSWORD "MyPassword"

static struct net_mgmt_event_callback wifi_cb;

static void wifi_event_handler(struct net_mgmt_event_callback *cb,
                                uint32_t mgmt_event, struct net_if *iface)
{
    if (mgmt_event == NET_EVENT_WIFI_CONNECT_RESULT) {
        printk("WiFi bağlandı!\n");
    } else if (mgmt_event == NET_EVENT_WIFI_DISCONNECT_RESULT) {
        printk("WiFi bağlantısı kesildi\n");
    }
}

int main(void)
{
    struct net_if *iface = net_if_get_default();

    net_mgmt_init_event_callback(&wifi_cb, wifi_event_handler,
        NET_EVENT_WIFI_CONNECT_RESULT | NET_EVENT_WIFI_DISCONNECT_RESULT);
    net_mgmt_add_event_callback(&wifi_cb);

    struct wifi_connect_req_params params = {
        .ssid        = WIFI_SSID,
        .ssid_length = strlen(WIFI_SSID),
        .psk         = WIFI_PASSWORD,
        .psk_length  = strlen(WIFI_PASSWORD),
        .security    = WIFI_SECURITY_TYPE_PSK,
        .channel     = WIFI_CHANNEL_ANY,
    };

    int ret = net_mgmt(NET_REQUEST_WIFI_CONNECT, iface, ¶ms, sizeof(params));
    if (ret) {
        printk("WiFi bağlanma isteği hatası: %d\n", ret);
        return ret;
    }

    printk("WiFi bağlanıyor: %s\n", WIFI_SSID);
    k_sleep(K_FOREVER);
    return 0;
}
kconfig — ESP32 WiFi
# prj.conf
CONFIG_WIFI=y
CONFIG_WIFI_ESP32=y
CONFIG_NET_L2_ETHERNET=y
CONFIG_NET_IPV4=y
CONFIG_NET_DHCPV4=y
CONFIG_NET_MGMT=y
CONFIG_NET_MGMT_EVENT=y

Bu bölümde

  • BLE beacon: bt_enable + bt_le_adv_start — connectable olmadan advertisement
  • UART echo: async callback tabanlı — UART_RX_DISABLED'da RX yeniden etkinleştir
  • ESP32 WiFi: NET_REQUEST_WIFI_CONNECT + net_mgmt event callback
  • Her örnek aynı kaynak kodu farklı board overlay ile çalışır