Back to Developer 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ühendislikApril 13, 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

Frequently Asked Questions

What is the most accurate method for IRQ latency measurement on STM32?+
Reading DWT->CYCCNT for software timestamps measures from the ISR entry point — not from when the interrupt signal was generated. The correct method is GPIO toggle + oscilloscope: set GPIO when interrupt source triggers, reset at the first line of the ISR. The oscilloscope measures the time between these two edges.
What is priority inversion in FreeRTOS and how to prevent it?+
Priority inversion occurs when a high-priority task waits for a mutex held by a low-priority task. FreeRTOS solution: enable mutex priority inheritance with configUSE_MUTEXES=1. This temporarily elevates the low-priority task to high priority so it releases the mutex quickly.
What is the advantage of using DMA with FreeRTOS on STM32H7?+
DMA-based sensor sampling occurs without CPU intervention. At 4000 Hz sampling, instead of a CPU interrupt per sample, a single semaphore is given when the circular DMA buffer fills. This dramatically reduces CPU load and keeps task scheduling jitter below 50µs.

Using this technology in your project?

Schedule an architecture audit with Spikedge engineers.

Schedule Architecture Audit