← Tüm makaleler

Gömülü Sistemlerde C Programlama Dili

Neden C? Donanıma yakınlık, bellek kontrolü ve deterministik zamanlama

Gömülü Sistemlerde C Programlama Dili

C, 1972'de Dennis Ritchie tarafından Bell Labs'ta yazıldı. O tarihten bu yana pek çok dil doğdu, popülerleşti ve unutuldu. C hâlâ burada. Ve gömülü sistemler dünyasında C'nin yerini alacak başka bir dil görünmüyor.

Bu yazının sonunda şunları anlayacaksınız: Gömülü sistemlerin neden C gerektirdiğini; diğer dillerin nerede yetersiz kaldığını; C'nin donanıma yakınlığının size somut olarak ne kazandırdığını.


Neden C, Neden Başka Bir Dil Değil?

Donanıma yakınlık — soyutlama olmadan kontrol

Bir mikrodenetleyicide bir GPIO pinine HIGH vermek istiyorsunuz. ARM Cortex-M bir işlemcide bu işlem şu anlama gelir: belirli bir bellek adresine belirli bir değer yaz.

// STM32'de GPIOA'nın 5. pinini HIGH yap
GPIOA->BSRR = (1 << 5);

Bu satır, derleyici tarafından tek bir STR assembly komutuna çevrilir. Arada hiçbir çalışma zamanı katmanı yoktur. Bellek adresine yazan komut, doğrudan donanım register'ını değiştirir.

Python, Java veya C# ile aynı işlemi yapabilirsiniz — ancak bu dillerin çalışma zamanları (sanal makine, çöp toplayıcı, JIT derleyici) onlarca kilobayt RAM ve belirli bir işletim sistemi gerektirir. 2 KB RAM'e sahip bir ATmega328P'de bunların hiçbiri çalışmaz.

Bellek yönetimi — tam kontrol, tam sorumluluk

Gömülü sistemlerde bellek sabittir ve kısıtlıdır:

C, bu belleği tamamen sizin kontrolünüze bırakır. Stack'te ne var, heap'te ne var, .bss segmentinde ne var — hepsini bilirsiniz çünkü hepsini siz koyarsınız.

uint8_t sensor_buffer[64];   // Stack'te 64 byte, derleme anında bilinir
uint16_t *dma_buffer = (uint16_t *)0x20000000; // Belirli bir adresi doğrudan kullan

Dinamik bellek (malloc) gömülü sistemlerde genellikle kaçınılan bir pratiktir — heap parçalanması öngörülemeyen çökmeler üretir. C bu seçimi size bırakır. Diğer diller çoğunlukla bu seçimi sizin elinizden alır.

Deterministik zamanlama — tahmin edilebilir davranış

Gerçek zamanlı sistemlerde "genellikle hızlı" yetmez. Motor kontrol döngüsünün her 50 µs'de bir çalışması gerekiyor. PWM sinyalinin her kenarının tam zamanında oluşması gerekiyor. Çöp toplayıcının tam bu anda devreye girmesi kabul edilemez.

C'de çöp toplayıcı yoktur. Jitter yoktur. Her fonksiyon çağrısı, her döngü adımı öngörülebilir zaman alır — ya da en azından öngörülebilir hale getirilebilir. Bu, gerçek zamanlı kontrol sistemlerinin temel gereksinimi olan determinizmdir.


Somut Farklar: C ve Diğer Diller

C vs C++

C++, C'nin üzerine inşa edilmiştir ve gömülü sistemlerde de kullanılır. STM32 HAL kütüphanesi C ile yazılmıştır, ancak birçok proje C++ kullanır. Fark nerededir?

C++ şunları ekler:

Standart kütüphane ve exception handling gömülü sistemlerde genellikle devre dışı bırakılır — çünkü dinamik bellek kullanırlar. C++'ın gömülü sistemlere uygun alt kümesi ile çalışmak mümkündür ve birçok profesyonel proje bunu yapar. Ancak başlangıç için C, davranışları daha öngörülebilir ve araç desteği daha geniştir.

C vs MicroPython / CircuitPython

MicroPython, Python sözdizimi ile mikrodenetleyici programlamaya olanak tanır — ESP32, RP2040, STM32 gibi yeterince güçlü işlemcilerde. Prototipleme için mükemmeldir.

Ancak şunlar MicroPython'da yoktur veya kısıtlıdır:

Bir ürün geliştiriyorsanız ve maliyet, güç tüketimi veya zamanlama kritikse, son aşama genellikle C'ye dönüştür.

C vs Assembly

Assembly, C'den önce gelen ve doğrudan işlemci komutlarını yazan dildir. C'den daha fazla kontrol sağlar mı? Teoride evet — her komutu kendiniz seçersiniz. Pratikte modern C derleyicileri (GCC, Clang) genellikle elle yazılmış assembly kadar veya daha iyi optimize edilmiş kod üretir.

Assembly bugün gömülü sistemlerde yalnızca çok özel yerlerde kullanılır:

Gömülü sistemler öğrenmek istiyorsanız, C'den başlamak doğru tercihtir. Assembly'yi gerektiği yerde öğrenirsiniz.


C'nin Gömülü Sistemlere Özel Avantajları

Taşınabilirlik

Aynı C kodu, AVR işlemcide de ARM Cortex-M'de de ESP32'de de derlenebilir. Peripheral-bağımsız mantık (protokol ayrıştırma, veri yapıları, hesaplamalar) platforma taşınır. Bu, büyük projelerde ciddi zaman tasarrufu sağlar.

Araç ekosistemi

Bu araçların tamamı C'yi birinci sınıf olarak destekler.

Kütüphane ekosistemi

Mikrodenetleyici üreticilerinin sağladığı kütüphaneler C ile yazılır:

Bu kütüphanelerle doğrudan çalışmak için C bilmek zorunludur.


İlk C Programı: Temel Yapı

Gömülü bir C programının iskeletine bakın:

#include <avr/io.h>
#include <util/delay.h>

int main(void) {
    DDRB |= (1 << PB5);  // PB5 pinini çıkış yap

    while (1) {
        PORTB |= (1 << PB5);   // LED yak
        _delay_ms(500);
        PORTB &= ~(1 << PB5);  // LED söndür
        _delay_ms(500);
    }

    return 0;  // Buraya hiç ulaşılmaz
}

Bu programda dikkat edilecek noktalar:

  1. #include <avr/io.h> — Bu başlık dosyası, ATmega328P'nin register adreslerini (DDRB, PORTB, PB5 gibi) tanımlar. Donanıma özgü sabitleri siz yazmıyorsunuz; üretici size sunuyor.

  2. int main(void) — Her C programının giriş noktası main fonksiyonudur. Gömülü sistemlerde main hiçbir zaman döndürmez — sonsuz döngü içinde kalır.

  3. while (1) — Gömülü sistemlerde "program bitti" diye bir kavram yoktur. Program, güç kesilene kadar çalışır.

  4. Bit işlemleri — |=, &=~, << operatörleri register'ların tek bitlerini değiştirmek için kullanılır. Bu, C'nin gömülü sistemlerdeki temel dili olmasının somut bir göstergesidir.


C Öğrenirken Nereye Odaklanmalı?

Gömülü sistemler bağlamında C öğrenirken şu konuların önceliği vardır:

Konu Neden önemli
Veri tipleri ve boyutları (uint8_t, uint16_t, int32_t) Register genişliği ile eşleşmesi gerekiyor
Bit operatörleri (&, |, ^, ~, <<, >>) Register konfigürasyonunun temeli
İşaretçiler (pointers) Bellek adresi ile doğrudan çalışmak için zorunlu
Fonksiyonlar ve çağrı yığını (call stack) Interrupt servis rutinleri için kritik
Yapılar (struct) Peripheral register haritalarını modelleme
volatile anahtar kelimesi Derleyici optimizasyonunun register erişimini bozmaması için

Bu konuların gömülü sistemler bağlamında nasıl uygulandığını sonraki derslerde adım adım işleyeceğiz.


Özet

C, gömülü sistemler için tasarlanmış bir dil değildir — ancak gömülü sistemlerin ihtiyaçlarına bu kadar uygun başka bir dil de yoktur. Donanıma doğrudan erişim, öngörülebilir bellek kullanımı, deterministik zamanlama ve geniş araç ekosistemi, C'yi bu alanda 50 yılı aşkın süredir birinci tercih yapan özelliklerdir.

Özellik C'nin Sağladığı
Donanım erişimi Register adresleri doğrudan okunur/yazılır
Bellek kontrolü Stack ve global değişkenler derleme anında bilinir
Zamanlama Çöp toplayıcı veya çalışma zamanı yok — deterministik
Taşınabilirlik Aynı kod AVR, ARM, ESP32'de derlenebilir
Araç desteği GCC, GDB, OpenOCD, tüm üretici SDK'ları
Kitap serisini incele →