EtherCAT hattında determinizmi belirleyen şey çoğu zaman saha cihazları değil, master tarafındaki yazılım yığınıdır. IgH (EtherLab) EtherCAT Master, Linux çekirdeği içinde çalışan açık kaynaklı bir master implementasyonu; PREEMPT_RT ile doğru yapılandırıldığında mikrosaniye mertebesinde döngü süresi ve 100ns altı DC senkronizasyonu ulaşılabilir hedefler. Bu rehber, çekirdek hazırlığından cyclic task tasarımına kadar sahada işleyen adımları toplar.
Ön Koşul: PREEMPT_RT Çekirdeği
IgH master vanilla çekirdekte de çalışır, ancak deterministik bir döngü hedefliyorsanız PREEMPT_RT şart. 6.12 itibarıyla RT desteği mainline'da; CONFIG_PREEMPT_RT=y ile derlemek yeterli. Çekirdek yapılandırmasının yanında üç şeyi mutlaka yapın:
- CPU izolasyonu: Cyclic task'ın koşacağı çekirdeği
isolcpus=3 nohz_full=3 rcu_nocbs=3ile genel zamanlayıcıdan ayırın. Generic sürücü kullanıyorsanız EtherCAT NIC'inin IRQ affinity'sini de aynı çekirdeğe sabitleyin. - Güç yönetimi: Derin C-state'lerden çıkış tek başına onlarca µs gecikme ekleyebilir.
/dev/cpu_dma_latencydosyasını 0'da tutan bir servis çalıştırın veya idle state'leri kernel cmdline'dan kapatın. - Doğrulama:
cyclictest -m -p95 -i 1000 -h 400komutunu en az bir gece koşturun. Doğru yapılandırılmış bir sistemde PREEMPT_RT worst-case zamanlama gecikmesini tipik olarak onlarca µs bandına çeker; yüzlerce µs görüyorsanız sorun genellikle SMI, firmware veya güç yönetimidir — master'a geçmeden önce bunu çözün.
IgH Master'ı Derlemek
git clone https://gitlab.com/etherlab.org/ethercat.git
cd ethercat
./bootstrap
./configure --prefix=/opt/etherlab \
--with-linux-dir=/usr/src/linux-headers-$(uname -r) \
--enable-generic --enable-igb
make -j$(nproc) all modules
sudo make modules_install install && sudo depmod
--enable-generic her NIC ile çalışan generic sürücüyü, --enable-igb gibi bayraklar ise belirli NIC ailelerine özel native sürücüleri derler. Native sürücüler çekirdek sürümüne sıkı bağlıdır; hedef çekirdeğiniz desteklenen listede değilse yama gerekir. İlk ayağa kaldırmada generic ile başlayıp hattı doğrulamak, sonra native'e geçmek pratik bir sıralamadır.
ethercat.conf ve Servis
Kurulum /opt/etherlab/etc/ethercat.conf dosyasını üretir; kritik iki alan var:
# /opt/etherlab/etc/ethercat.conf
MASTER0_DEVICE="00:1b:21:3c:9a:f2" # EtherCAT NIC'inin MAC adresi
DEVICE_MODULES="igb" # veya "generic"
MAC adresiyle eşleme, arayüz adlarının (eth0 → enp2s0) dağıtım geçişlerinde kaymasına karşı sizi korur. systemctl enable --now ethercat sonrası ethercat master çıktısında master'ın Idle fazında olduğunu, ethercat slaves ile de tüm slave'lerin PREOP durumunda listelendiğini doğrulayın. Slave sayısı eksikse önce kablolamaya ve port sırasına bakın; EtherCAT topolojisi fiziksel zincir sırasına birebir bağlıdır. PDO eşlemesini elle yazmakla uğraşmayın: ethercat cstruct komutu slave'in gerçek PDO yapılandırmasını doğrudan C kodu olarak döker ve register offset hatalarını daha en baştan eler.
Ağ Sürücüsü: Neden Polling Modu?
Generic sürücü frame'leri standart soket katmanı üzerinden geçirir: NIC IRQ'su, NAPI, softirq — her biri jitter'a katkı yapar; interrupt coalescing ayarları da frame'e değişken gecikme ekler. Native ec_* sürücüleri ise NIC'i tamamen master'a adar ve interrupt'ları devre dışı bırakır: frame gönderimi ve alımı, cyclic task'ın kendi bağlamında polling ile yapılır. Böylece ağ G/Ç'si IRQ gecikme denkleminden bütünüyle çıkar.
| Özellik | Generic sürücü | Native (ec_igb vb.) |
|---|---|---|
| Frame yolu | Soket katmanı + NAPI | Doğrudan register erişimi, polling |
| IRQ bağımlılığı | Var (coalescing dahil) | Yok |
| Jitter katkısı | µs mertebesinde, değişken | Mikrosaniye altı |
| NIC desteği | Tüm Linux NIC'leri | Sınırlı liste (igb, e1000e, 8139too...) |
| Çekirdek uyumu | Sorunsuz | Sürüme sıkı bağlı |
DC Senkronizasyonu: Başlangıç Kalibrasyonu
Distributed Clocks, hattaki ilk DC-yetenekli slave'in saatini referans alır; diğer slave'ler ve master bu saate hizalanır. Referans slave'i topoloji değişikliklerinin insafına bırakmak istemiyorsanız ecrt_master_select_reference_clock() ile açıkça seçin. Başlangıçta üç noktaya dikkat edin:
- Application time'ı planlanan zamanla besleyin.
ecrt_master_application_time()her döngüde, cyclic task'ın planlanan uyanma zamanıyla çağrılmalı — gerçekleşen zamanla değil. Gerçekleşen zamanı verirseniz kendi scheduling jitter'ınızı referans saate enjekte edersiniz. - Drift'in oturmasını bekleyin. OP durumuna geçtikten sonra drift compensation'ın yakınsaması birkaç bin döngü sürer.
ecrt_master_sync_monitor_queue()/process()ile ölçülen sapma eşiğinizin altına inene kadar (örneğin <1µs) eksenlere enable vermeyin. - SYNC0 shift verin. SYNC0 event'i, PDO frame'inin slave'e varışıyla çakışmamalı.
ecrt_slave_config_dc()çağrısında döngü periyodunun yaklaşık %30'u kadar shift, güvenli bir başlangıç noktasıdır.
Bu yaklaşımın sahada karşılığı var: i.MX8M Plus üzerinde PREEMPT_RT + IgH ile kurduğumuz bir hareket kontrol hattında döngü süresi 8µs'den 3.8µs'ye indi, slave senkron hatası ±5µs'den 100ns'nin altına düştü. Ölçüm yöntemi ve mimari kararların tamamı EtherCAT hareket kontrol vaka analizinde belgeli.
Cyclic Task Tasarımı
Cyclic task'ta üç kural: SCHED_FIFO ile yüksek öncelik, mlockall() ile sayfa kilidi ve clock_nanosleep(TIMER_ABSTIME) ile mutlak zamanlı uyanma. Göreli sleep kullanırsanız her döngüdeki işlem süresi perioda eklenir ve faz sürekli kayar. Bir de kernel.sched_rt_runtime_us=-1 ayarını unutmayın: varsayılan RT throttling, CPU'yu sürekli kullanan bir cyclic task'ı her saniyenin son 50ms'inde askıya alır ve bunun döngü kaydındaki görüntüsü, açıklanamayan periyodik kaçırmalardır.
struct timespec wakeup;
clock_gettime(CLOCK_MONOTONIC, &wakeup);
while (running) {
wakeup.tv_nsec += CYCLE_NS; /* örn. 1000000 → 1 kHz */
while (wakeup.tv_nsec >= 1000000000L) {
wakeup.tv_sec++;
wakeup.tv_nsec -= 1000000000L;
}
clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &wakeup, NULL);
ecrt_master_receive(master);
ecrt_domain_process(domain);
/* PDO oku, kontrol döngüsünü işlet, PDO yaz */
ecrt_master_application_time(master, TIMESPEC2NS(wakeup));
ecrt_master_sync_reference_clock(master);
ecrt_master_sync_slave_clocks(master);
ecrt_domain_queue(domain);
ecrt_master_send(master);
}
Sıralama önemli: receive/process döngünün başında, queue/send sonunda çalışır; DC senkron çağrıları application time güncellendikten sonra gelmeli. Kontrol algoritmanız uzuyorsa frame'i geciktirmek yerine hesaplamayı bir sonraki döngüye bölün — EtherCAT'te geç kalan frame, kaçırılmış döngü demektir.
Ölçmeden bitirmeyin: ethercat master çıktısındaki sayaçlar ve debug arayüzü döngü kaçırmalarını gösterir; kritik uygulamalarda donanım timestamp veya osiloskopla doğrulama şarttır. Fieldbus katmanının ötesinde CANopen-over-EtherCAT, PROFINET gibi protokollerle entegrasyon gerekiyorsa endüstriyel protokol yeteneklerimize göz atabilirsiniz.
Mevcut hattınızda jitter'ın nereden kaynaklandığından emin değilseniz, gerçek zamanlı yazılım yığınını uçtan uca inceleyen bir gömülü sistem mimari denetimi ile başlamak, körlemesine parametre değiştirmekten daha hızlı sonuç verir.
