6. ünite / 11 · yaklaşık 5 saat
Kesmeler, EXTI ve NVIC
Yoklama yerine kesme; EXTI hatları; NVIC öncelikleri, iç içe kesme, kuyruk zincirleme; ISR yazım kuralları.
Bu ünitenin sonunda
- Yoklama (polling) ile kesmenin farkını ve kesme gecikmesini açıklamak
- Bir GPIO pinini EXTI hattına bağlamak ve hat paylaşımı kuralını uygulamak
- NVIC preempt ve alt önceliklerini ayarlayıp iç içe kesmeyi ve kuyruk zincirlemeyi okumak
- Kısa, volatile kullanan ve engellemeyen ISR yazmak
Ders notları
Ana döngüde butonu sürekli okumak (yoklama) işlemciyi meşgul eder ve döngü uzunsa basışı kaçırır. Kesme ile donanım olayı işlemciyi durdurur, kısa bir işleyici (ISR) çalışır, sonra ana kod kaldığı yerden devam eder. Cortex-M'de çekirdek yazmaçları yığına otomatik kaydeder; giriş yaklaşık 12 çevrimdir.
EXTI
EXTI (harici kesme) denetleyicisinin 16 GPIO hattı vardır ve hat numarası pin numarasıdır: PA0, PB0 ve PC0 aynı EXTI0 hattını paylaşır, hangisinin bağlanacağını SYSCFG_EXTICR seçer. Yani PA0 ve PB0'dan aynı anda kesme alınamaz. EXTI0–4'ün kendi vektörü vardır; 5–9 ve 10–15 ortak vektörü paylaşır, işleyici hangi hattın tetiklediğine bekleme (PR) yazmacından bakar.
NVIC ve öncelik
STM32'de öncelik için 4 bit vardır; küçük sayı yüksek önceliktir. Bitler preempt (araya girme) ve alt öncelik olarak bölünebilir. Kural: bekleyen bir kesme, ancak preempt önceliği çalışan işleyicininkinden kesin küçükse araya girer. Eşitse bekler; sıra alt önceliğe göre belirlenir. Bir işleyici bitince bekleyen varsa ana koda dönmeden ona geçilir: kuyruk zincirleme (tail-chaining), birkaç çevrim kazandırır.
ISR kuralları
- Kısa tut: bayrak kaldır, sayaç artır; ağır işi ana döngüye bırak.
- ISR ile paylaşılan değişkenler
volatile; çok baytlılarda kritik bölge. - ISR'de
HAL_Delayveprintfyok. Bekleme biti tekrar gelmeden temizlenmezse ikinci olay kaybolur.
Simülasyon
EXTI ve NVIC: kesme zaman çizelgesi
Üç kesmenin önceliğini ve süresini ayarla, istek anlarını değiştir. Zaman çizelgesi öncelikli kesmeyi (iç içe), bekleyen istekleri, kuyruk zincirlemeyi ve kaybolan ikinci isteği gösterir. EXTI hat çakışmasını da dene.
Kendin dene
Zaman çizelgesinde TIM2 (preempt 2) çalışırken EXTI0 (preempt 1) isteği gönder: iç içe geçişi gör. EXTI0'ın önceliğini 3 yap ve tekrarla: şimdi bekliyor mu? İki USART isteğini art arda gönder ve ikincisinin neden kaybolduğunu açıkla. EXTI sekmesinde PA0 ve PB0'ı birlikte seç ve çakışmayı oku.
Kod
volatile uint32_t presses = 0; /* ISR ile paylaşılan: volatile */
void button_init(void) {
__HAL_RCC_GPIOC_CLK_ENABLE();
GPIO_InitTypeDef g = {0};
g.Pin = GPIO_PIN_13; g.Mode = GPIO_MODE_IT_FALLING; g.Pull = GPIO_NOPULL; /* düşen kenarda kesme */
HAL_GPIO_Init(GPIOC, &g); /* SYSCFG_EXTICR4'te EXTI13 = port C */
HAL_NVIC_SetPriority(EXTI15_10_IRQn, 5, 0); /* preempt 5: motor zamanlayıcısından düşük */
HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
}
void EXTI15_10_IRQHandler(void) { HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13); } /* bekleme bitini temizler */
void HAL_GPIO_EXTI_Callback(uint16_t pin) {
if (pin == GPIO_PIN_13) presses++; /* yalnız işaretle; printf ve HAL_Delay yok */
}Sık yapılan hatalar
- ISR'de uzun iş yapmak: düşük öncelikli kesmeler ve ana döngü aç kalır, olaylar kaybolur.
- Paylaşılan değişkeni volatile yapmamak: derleyici değeri yazmaçta tutar, ana döngü değişikliği görmez.
- Aynı numaralı iki pinden EXTI beklemek (PA3 ve PB3).
- Önceliği yanlış yöne okumak: 0 en yüksek önceliktir; SysTick'i fazla düşük öncelikte bırakmak HAL_Delay'i bozar.
Yazılım mühendisliği bağlantısı
Kesmeler eşzamanlılık getirir; hatalar nadiren ve tekrarlanamaz biçimde görülür.
- ISR'den ana koda veriyi tek yazarlı tek okurlu bir halka tampon ile aktar; bunu bilgisayarda test et.
- Her kesmenin önceliğini ve gerekçesini bir tabloda belgele (öncelik haritası); kod incelemesinde kontrol edilir.
Kendini sına
PA3 ve PB3'ten aynı anda EXTI kesmesi alınabilir mi?
Preempt 2'deki işleyici çalışırken preempt 2'de başka bir kesme gelirse?
Kuyruk zincirleme nedir?
ISR ile ana döngünün paylaştığı sayaç nasıl tanımlanmalı?