Zurück zum Wiki
STM32

STM32'de IRQ Gecikme Ölçümü: GPIO Toggle + Osiloskop Yöntemi

STM32H7 ve STM32F4 serilerinde gerçek IRQ gecikme ölçümü için GPIO toggle + osiloskop yöntemi — yazılım timestamp neden yanıltır, donanımsal doğrulama nasıl yapılır.

Spikedge Mühendislik13. April 20269 dk okuma

STM32'de IRQ Gecikme Ölçümü: GPIO + Osiloskop

Neden Yazılım Timestamp Yanlıştır?

Firmware geliştiricilerin IRQ gecikme ölçümünde yaptığı en yaygın hata DWT->CYCCNT veya TIM->CNT okumaktır. Bu yöntem ISR giriş noktasından itibaren zamanı ölçer — interrupt sinyalinin donanımda üretilmesi ile ISR çalışması arasındaki süreyi değil.

Standart STM32H7 NVIC latency (Cortex-M7 dokümantasyonu): 12 cycle Gerçek observed latency (pipeline, cache miss, interrupt masking): 48–180 cycle

Bu fark, yüksek frekanslı kontrol döngülerinde (10kHz+) ciddi jitter kaynağıdır.

Doğru Yöntem: GPIO Toggle

Prensip: Interrupt kaynağı aktif olduğunda bir GPIO set, ISR'ın ilk satırında reset. Osiloskop bu iki kenar arasındaki süreyi ölçer.

// Interrupt kaynağı konfigürasyonu (TIM2 örneği)
void TIM2_IRQHandler(void) {
    // ISR'ın ilk ifadesi — cache miss öncesi
    GPIOA->BSRR = GPIO_BSRR_BR15;  // PA15 → LOW
    
    // ... gerçek ISR işlemleri ...
    
    HAL_TIM_IRQHandler(&htim2);
}

// Timer callback'te GPIO set
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
    if (htim->Instance == TIM2) {
        GPIOA->BSRR = GPIO_BSRR_BS15;  // PA15 → HIGH (sonraki periyot için hazırla)
    }
}

Kritik: GPIOA->BSRR = GPIO_BSRR_BR15 doğrudan register yazımı kullanın. HAL_GPIO_WritePin() fonksiyonu ek döngüler ekler ve ölçümü bozar.

Osiloskop Konfigürasyonu

  • Kanal A: Interrupt kaynağı (timer output veya external trigger)
  • Kanal B: GPIO (PA15)
  • Trigger: Kanal A yükselen kenar
  • Zaman tabanı: 1µs/div (STM32H7 @ 480MHz için 50ns/div önerilir)
  • Ölçüm: Kanal A yükselen kenar → Kanal B düşen kenar arası

STM32H7 Örnek Sonuçlar

Durum Ölçülen IRQ Latency
Sıfır yük, I-cache açık 125ns (60 cycle @ 480MHz)
Aktif FPU işlemi (float context save) 312ns
DCache miss (ilk çağrı) 480ns
FreeRTOS task context'i içinden 720ns
RTOS + DCache miss ~1.1µs

NVIC Priority Masking Tuzağı

FreeRTOS kullanan projelerde configMAX_SYSCALL_INTERRUPT_PRIORITY yanlış ayarlanmışsa taskENTER_CRITICAL() bölümleri tüm interrupt'ları maskeleyebilir:

// stm32h7xx_hal_conf.h
// Bu değer NVIC_EncodePriority ile encode edilmiş değerdir
#define configMAX_SYSCALL_INTERRUPT_PRIORITY  (5 << 4)  /* Priority 5 */

// Priority 5 ve üzeri interrupt'lar critical section içinde maskelenir
// EtherCAT veya motor kontrol IRQ'ları bu eşiğin altında olmalı
NVIC_SetPriority(TIM2_IRQn, 4);  // Critical section'dan etkilenmez

cyclictest Eşdeğeri: latency_test Pattern

Linux cyclictest aracına benzer şekilde, STM32'de minimum/maksimum/ortalama jitter ölçebilirsiniz:

#define SAMPLE_COUNT 100000

uint32_t samples[SAMPLE_COUNT];
uint32_t min_lat = UINT32_MAX, max_lat = 0, idx = 0;

// DWT cycle counter aktif et
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
DWT->CYCCNT = 0;
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;

void TIM2_IRQHandler(void) {
    uint32_t lat = DWT->CYCCNT;  // ISR giriş timestamp
    GPIOA->BSRR = GPIO_BSRR_BR15;
    
    // Beklenen periyot cycle sayısı çıkar (480MHz * 100µs = 48000)
    uint32_t jitter = lat > 48000 ? lat - 48000 : 48000 - lat;
    
    if (idx < SAMPLE_COUNT) samples[idx++] = jitter;
    if (jitter < min_lat) min_lat = jitter;
    if (jitter > max_lat) max_lat = jitter;
    
    DWT->CYCCNT = 0;  // Reset for next cycle
    HAL_TIM_IRQHandler(&htim2);
}

İlgili Kaynaklar

#STM32#IRQ#Latency#RTOS#Oscilloscope#NVIC#FreeRTOS#Cortex-M7

Häufig gestellte Fragen

Was ist die genaueste Methode zur IRQ-Latenzmessung auf STM32?+
Das Lesen von DWT->CYCCNT für Software-Timestamps misst ab dem ISR-Einstiegspunkt — nicht ab dem Zeitpunkt der Interrupt-Signalerzeugung. Die korrekte Methode ist GPIO-Toggle + Oszilloskop: GPIO setzen, wenn die Interrupt-Quelle auslöst, zurücksetzen in der ersten ISR-Zeile. Das Oszilloskop misst die Zeit zwischen diesen zwei Flanken.
Was ist Priority Inversion in FreeRTOS und wie verhindert man es?+
Priority Inversion tritt auf, wenn ein hochpriorer Task auf einen Mutex wartet, der von einem niederprioren Task gehalten wird. FreeRTOS-Lösung: Mutex Priority Inheritance mit configUSE_MUTEXES=1 aktivieren. Dies erhöht den niederprioren Task temporär auf hohe Priorität, damit er den Mutex schnell freigibt.
Was ist der Vorteil von DMA mit FreeRTOS auf STM32H7?+
DMA-basiertes Sensor-Sampling erfolgt ohne CPU-Eingriff. Bei 4000 Hz Abtastrate wird statt einem CPU-Interrupt pro Sample ein einzelnes Semaphore gegeben, wenn der zirkuläre DMA-Puffer voll ist. Dies reduziert die CPU-Last drastisch und hält den Task-Scheduling-Jitter unter 50µs.

Setzen Sie diese Technologie in Ihrem Projekt ein?

Planen Sie ein Architektur-Audit mit Spikedge-Ingenieuren.

Architektur-Audit planen