RTOS'ta ISR içinde hangi API'ler kullanılabilir? Deferred interrupt processing nasıl yapılır?
Cevap
ISR'lar mümkün olduğunca kısa olmalıdır: uzun ISR'lar diğer interrupt'ları geciktirir, jitter'ı artırır ve task'ların zamanlamasını bozar. Ayrıca ISR'lar bloklayamaz; bir ISR'ın "beklemesi" diye bir kavram yoktur.
ISR-safe API kuralları (FreeRTOS)
- Yalnızca adı `FromISR` ile biten fonksiyonlar kullanılır:
xQueueSendFromISR,xSemaphoreGiveFromISR,vTaskNotifyGiveFromISR,xEventGroupSetBitsFromISR. - Bu fonksiyonlar timeout almaz; queue doluysa hemen hata döner.
- Mutex ISR'da kullanılamaz (sahiplik ve inheritance task kavramıdır).
printf,malloc,vTaskDelaygibi bloklayan veya reentrant olmayan çağrılar yasaktır.- Cortex-M'de öncelik sınırı: RTOS API'si çağıran interrupt'ların donanım önceliği
configMAX_SYSCALL_INTERRUPT_PRIORITYdeğerinden daha yüksek (sayısal olarak daha küçük) olamaz. Bu sınırın üstündeki interrupt'lar RTOS tarafından hiç maskelenmez ama API de çağıramaz. Bu ayarın yanlış olması,configASSERTile yakalanan en yaygın hatalardan biridir.
Deferred interrupt processing
ISR yalnızca donanımı temizler, gerekli minimum veriyi alır ve asıl işi bir task'a devreder:
static TaskHandle_t rx_task_handle;
void USART1_IRQHandler(void) {
BaseType_t woken = pdFALSE;
uint8_t b = USART1->DR; /* bayrağı temizler */
xStreamBufferSendFromISR(rx_stream, &b, 1, &woken);
vTaskNotifyGiveFromISR(rx_task_handle, &woken);
portYIELD_FROM_ISR(woken); /* gerekiyorsa hemen context switch */
}
void rx_task(void *arg) {
for (;;) {
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
uint8_t buf[32];
size_t n = xStreamBufferReceive(rx_stream, buf, sizeof buf, 0);
parse_protocol(buf, n); /* uzun iş task bağlamında */
}
}pxHigherPriorityTaskWoken neden önemli?
FromISR çağrısı daha yüksek öncelikli bir task'ı uyandırdıysa bu değişken pdTRUE olur. ISR sonunda portYIELD_FROM_ISR çağrılmazsa uyanan task ancak bir sonraki tick'te çalışır; yanıt süresi bir tick kadar (ör. 1 ms) gecikir.
Diğer seçenekler
- Timer/daemon task'a havale:
xTimerPendFunctionCallFromISRile bir fonksiyonu timer service task'ında çalıştırmak. - Yüksek öncelikli handler task: Ertelenen işin ISR sonrası gecikmesiz çalışması için bu task'a sistemdeki en yüksek önceliklerden biri verilir.
- Linux karşılığı: top half / bottom half (tasklet, workqueue, threaded IRQ).
ISR ile task arasında paylaşılan veri
Task tarafında kısa kritik bölgeler için taskENTER_CRITICAL() / taskEXIT_CRITICAL(), ISR tarafında taskENTER_CRITICAL_FROM_ISR() kullanılır; paylaşılan değişkenler volatile olmalıdır.
İlgili RTOS soruları
- RTOS nedir? Bare-metal programlamadan farkı nedir?
- FreeRTOS'ta queue, binary semaphore, counting semaphore ve mutex arasındaki farklar nelerdir? Hangisi ne zaman kullanılır?
- Priority inversion nedir? Priority inheritance bu sorunu nasıl çözer?
- RTOS'ta preemptive priority-based scheduling nasıl çalışır? Bare-metal super loop yerine ne zaman RTOS tercih edilir?
Bu konuda başka bir soru biliyor musun?
Mülakatta karşılaştığın soruları ekle, onaylandıktan sonra yayına alınsın.