Cortex-M4 referans kılavuzu kesme gecikmesini 12 çekirdek çevrimi olarak verir; 168 MHz'te yaklaşık 71 ns. Sahadaki bir STM32F4'te ise flash bekleme durumları, DMA bus çekişmesi, kritik bölümler ve yanlış NVIC önceliklendirmesi bu rakamı kolayca onlarca, kötü konfigürasyonda yüzlerce mikrosaniyeye taşır. Deterministik davranış iddia eden her sistemde IRQ gecikmesi ölçülmek zorundadır — ve ölçümün kendisi de yanlış yapılmaya son derece müsaittir. Bu yazıda, ground truth olarak kabul ettiğimiz GPIO toggle + osiloskop metodolojisini tuzaklarıyla birlikte anlatıyoruz.
Yazılım Timestamp Neden Yanıltır
İlk akla gelen yöntem bellidir: ISR'ın başında DWT->CYCCNT oku, referans değerden çıkar, farkı logla. Üç temel problemi vardır:
- Başlangıç anını göremezsiniz. Yazılım, kesmenin donanımda assert edildiği anı bilemez; sayaç ancak ISR prolog'u (register stacking, vektör fetch) bittikten sonra okunur. Ölçmek istediğiniz sürenin önemli bir kısmı ölçüme hiç girmez.
- Probe effect. Ölçüm kodu — hele ITM/printf üzerinden log atıyorsa — ISR süresini ve bus trafiğini değiştirir. Ölçtüğünüz sistem, sahaya çıkan sistem değildir.
- Nadir olaylar loglara sığmaz. Worst-case, on binlerce kesmede bir gelir. RAM'de tampon tutup sonradan boşaltmak hem probe effect'i büyütür hem de tam tamponu boşalttığınız anda gelen olayı kaçırır.
Yöntemlerin dürüst karşılaştırması:
| Yöntem | Çözünürlük | Neyi görür | Ana tuzak |
|---|---|---|---|
DWT->CYCCNT (ISR içi) |
1 çevrim | Prolog sonrasını | Donanım assert anı ölçüme girmez |
| SysTick delta | Tick periyodu | Kaba ortalamayı | Worst-case tamamen görünmez |
| Timer input capture | 1 timer çevrimi | Timer'ın gördüğü kenarı | Konfigürasyon hatası sessizce yanlış ölçer |
| GPIO + osiloskop | Nanosaniye mertebesi | Uçtan uca gerçek gecikmeyi | Yanlış tetikleme, faz kilitlenmesi |
Timer input capture ara çözüm olarak savunulabilir; ama sonucu doğrulayacağınız bağımsız referans yine osiloskoptur. O zaman doğrudan osiloskopla başlayın.
GPIO Toggle Yöntemi: Kurulum
Düzenek üç parçadan oluşur: bir sinyal jeneratörü EXTI olarak konfigüre edilmiş pini sürer (skop CH1), ISR ilk komut olarak ikinci bir pini set eder (skop CH2), skop CH1'in yükselen kenarına tetiklenir ve CH1→CH2 gecikmesini ölçer.
Kritik detaylar:
- BSRR'a doğrudan yazın.
HAL_GPIO_WritePinaraya fonksiyon çağrısı,HAL_GPIO_TogglePinüstüne bir de read-modify-write ekler.GPIOB->BSRRtek, atomik AHB yazımıdır; ölçüme kattığı süre tek çevrim mertebesindedir. - HAL EXTI zincirini atlayın.
HAL_GPIO_EXTI_IRQHandler→ callback yolculuğu araya onlarca çevrim sokar. Ölçüm sırasında ISR'ı vektör tablosuna doğrudan bağlayın. - Pini önceden output yapın, ISR içinde mod değiştirmeyin.
- -O0 ile ölçmeyin. Sahaya -O2 çıkıyorsanız -O2 ile ölçün.
// Stimulus: PC13 (EXTI13, jeneratörden ~997 Hz kare dalga)
// Ölçüm çıkışı: PB8 (önceden push-pull output konfigüre edilmiş)
void EXTI15_10_IRQHandler(void)
{
GPIOB->BSRR = GPIO_BSRR_BS8; // İLK komut: pini kaldır
EXTI->PR = EXTI_PR_PR13; // pending bayrağını temizle
/* ... asıl ISR işi ... */
GPIOB->BSRR = GPIO_BSRR_BR8; // çıkışta pini indir
}
Jeneratör frekansı bilinçli olarak 997 Hz gibi "çirkin" seçilir: 1 kHz SysTick ile faz kilitlenmesini engeller. Stimulus, tick frekansının tam katıysa SysTick ISR'ıyla çakışma ya her örnekte yaşanır ya hiç yaşanmaz — ikisi de istatistiği bozar. Asenkron frekans, çakışmanın rastgele örneklenmesini garanti eder.
Bonus: pini ISR çıkışında indirdiğiniz için CH2 darbe genişliği, ISR yürütme süresini de bedavaya verir.
Worst-Case vs Ortalama
Hard real-time'da ortalama gecikme neredeyse anlamsız bir metriktir; motor sürücünüzü durduran şey ortalama değil, elli bin kesmede bir gelen kuyruktur. Worst-case'i üreten tipik kaynaklar:
- Aynı veya daha yüksek öncelikli başka bir ISR'ın hâlihazırda çalışıyor olması,
- RTOS kernel kritik bölümleri (
taskENTER_CRITICAL, BASEPRI maskeleme), - Flash bekleme durumları — özellikle prefetch/ART kapalıysa,
- DMA burst'lerinin bus matrix'te çekirdekle çekişmesi.
Bu yüzden ölçüm boş sistemde değil, gerçek yük altında yapılır: Ethernet trafiği, DMA transferleri, USB — sahada ne varsa hepsi açıkken. Boş sistemdeki 400 ns'lik "harika" sonuç, yük altındaki onlarca mikrosaniyelik gerçeği gizler. Worst-case bütçelemesi hard real-time sistem tasarımının temel disiplinidir: kâğıt üstünde bütçe, skopta doğrulama.
10.000+ Örnekle İstatistik
Tek ölçüm anekdottur. Skopu infinite persistence moduna alın, measurement statistics'i açın (CH1→CH2 delay), en az 10.000 örnek toplayın; kritik sistemlerde geceye bırakıp milyonlarca örnek alın. Kaydedilecek değerler: min, ortalama, max, standart sapma (σ = jitter) ve mümkünse histogram.
10.000 alt sınırının nedeni basit aritmetiktir: her 1.000 kesmede bir gerçekleşen bir çakışmayı yüksek güvenle yakalamak için binlerce örnek gerekir; her 100.000 kesmede bir gelen olay içinse gece boyu koşu şarttır. Histogramda tek tepe yerine iki-üç tepe görüyorsanız bu bir bulgudur: her tepe ayrı bir girişim kaynağıdır (ana tepe + SysTick çakışma tepesi + DMA burst tepesi gibi) ve tek tek izole edilip açıklanmalıdır. Açıklayamadığınız tepe, sahada patlayacak tepedir.
NVIC Öncelik Hataları: Ölçümün Yakaladıkları
Bu düzenek en çok NVIC hatalarını yakalar, çünkü öncelik hataları ortalamayı değil kuyruğu bozar:
- Ters öncelik sezgisi. Cortex-M'de küçük sayı = yüksek öncelik. "En önemli kesmeye 15 verdim" klasik hatadır.
- Eksik bit farkındalığı. STM32'de
__NVIC_PRIO_BITStipik olarak 4'tür: 16 seviye vardır ve değerin üst 4 biti anlamlıdır. CMSISNVIC_SetPrioritykaydırmayı sizin için yapar; register'a elle yazan kod genellikle yanlış yazar. - Subpriority yanılgısı. Aynı preemption grubundaki kesmeler birbirini kesemez; subpriority yalnızca aynı anda pending olanların sırasını belirler.
- FreeRTOS maskeleme sınırı.
FromISRAPI çağıran her kesmenin önceliği numerik olarakconfigMAX_SYSCALL_INTERRUPT_PRIORITY'den düşük olmamalıdır (yani lojik olarak eşit ya da daha az öncelikli olmalıdır). Sınırın yanlış tarafındaki "en kritik" kesmeniz kernel kritik bölümlerinde maskelenir — histogramda ani 20-50 µs'lik ikinci tepe olarak görünür veconfigASSERTaçık değilse başka hiçbir yerde görünmez.
Pratik kural: her öncelik veya kritik bölüm değişikliğinden sonra ölçümü tekrarlayın. NVIC konfigürasyonu bir kere doğrulanıp unutulan bir şey değil, regresyon testine bağlanan bir şeydir.
Kapanış
Metodoloji mimariden bağımsızdır; aynı osiloskop doğrulamalı yaklaşımla Spikedge, TI AM6442 / TI-RTOS üzerinde worst-case IRQ gecikmesini 38.7 µs'den 4.2 µs'ye indirdi (jitter σ 0.3 µs) — adımların tamamı rtos-latency vaka analizinde belgelidir. Kendi sisteminizde kuyruğun varlığını skop söylüyor ama nedenini çözemiyorsanız, gerçek zamanlı sistem mimari denetimi tam olarak bu ölçüm disipliniyle başlar.
