Interrupt Handler Hakkında

Başlatan isoment01, 05 Nisan 2020, 13:24:48

isoment01

Arkadaşlar aklımı alan çoğunuzun bileceğini düşündüğüm bir sorum var. Interruptların çalışma mekanizması hakkında hemen hemen herşeyi biliyorum fakat bir nokta hariç. Bir örnek vererek bunu anlatayım. Bir işlemcim var 32 bit ST'nin olsun bu işlemci. Timer interruptı kullanalım ve saat hızı 84 mhz olsun ben 1 msn sinyal üretmek için 42000 prescaler'a böleyim ve frekans 2kHz'e düşsün sonra (0.5msn) sonra counter value'yu 1 vereyim ve (0,1) 1 ms lik bir interrupt elde edeyim. Interrupt handler'ımın içine de kod bloğumu yerleştireyim.
 Şimdi sorum benim bu interrupt handler'da kodlarımın işlenmesi için ne kadar vaktim olduğu ?
 1msn vaktin var diyorsanız bana bunu açıklayın.
 Ben şöyle düşünüyorum counter saymaya başlar 0, ve 1 olur flag set olur ve counter tekrar  1'den O'a geçeceği o sürede kodlar okunur. Yani 1 msn değil 0.5 ms sürem var gibi geliyor. Lütfen bana doğrusunu anlatın.
 Birde aklımı alan son bir konu interrupt priority. DMA kullanıyorum, timer kullanıyorum, CAN kullanıyorum mesela timer interrupt ile CAN Rx interruptım priority vermediğim için çakışır mı. Hepsinin önceliği 0 şu an. Böyle bir durumda işlemci nasıl davranır. Birden fazla interrupt kullandığımda illa priority vermeli miyim ?

Bilen arkadaşlar beni bu noktalarda aydınlatırsa artık bunları kafama takmaktan kurtulacam.

magnetron

ben HAL bilmiyorum
SPL de library içinde misc.h dosyası var
orda bütün prepriority - subpriority olayını anlatmış

bir de subpriority sayısı düşük olan öncelikli olur

yalnız interruptlar arasında öncelik vermek istersen preemptionpriority değiştirmen
lazım yani bir interrupt ötekini kesecekse preemption dan ayarlanıyor

yukardaki döküman açıklıyor

Monad

ARM Cortex M4 işlemcileri 256'ya kadar interrupt öncelik sıralaması yapabiliyor. Ama bazı yarı iletken firmaları kendi mikrodenetleyicilerinde bunun tamamını kullanmıyor. STM32 ler 4 bitlik interrupt sıralaması için yer ayırıyor ve bu preemptive priority ile sub priority arasında bölünüyor. Global bir değişken olarak interrupt grubunu 0'dan 4'e kadar seçebiliyorsun ve bunu kaç bit girersen preemptive priority için o kadar yer ayrılmış oluyor kalan da sub priority için ayrılıyor.

Preemptive priority için şöyle söyleyelim. Önceliği yüksek olan(sayı olarak düşük olan mesela 0) önceliği düşük olan(mesela 1), düşük öncelikli interrupt gerçekleşirken yüksek öncelikli interrupt tetiklenirse program düşük önceliklide kaldığı yeri kaydedip yüksek öncelikli interruptı tamamlayıp sonra geri düşük öncelikli interrupt'a dönüp kaldığı yerden devam eder. Preemptive priority işte bu önceliği belirler. Yüksek öncelikli interrupt devam ederken düşük öncelikli tetiklenirse, yüksek öncelikli bittikten sonra düşük öncelikli yapılır.

Sub priority ise aynı preemptive priority önceliğine sahip 2 interrupt olduğunu düşünelim, 2 interrupt aynı anda tetiklenirse hangisinin önce gerçekleşeceğini belirtir ancak biri gerçekleştirilirken bırakıp gidip diğerini yapmaz. İlk yapılan bittikten sonra diğerini yapar.

STM firması interrupt priority sıralamalarının boşta bırakılmamasını tavsiye ediyor.

Doğru anladıysam, 0.5 ms süren var. İnterrupt tetiklenme frekansın 2kHz. Başlangıç noktasına gelmen içinse 2 kere tetiklenmesi gerekiyor. Bu da eğer bir sinyal olarak düşünür ve başlangıç durumuna gelmesini kabul edersen 1kHz frekansına sahip olduğun anlamına geliyor. Yani LED Toggle olarak düşünürsek tekrar 0 başlangıcına(aynı noktaya) gelmen 1 mili saniye ancak bunun için 2 kere interrupt tetikleniyor.

isoment01

Alıntı yapılan: Monad - 05 Nisan 2020, 14:41:41ARM Cortex M4 işlemcileri 256'ya kadar interrupt öncelik sıralaması yapabiliyor. Ama bazı yarı iletken firmaları kendi mikrodenetleyicilerinde bunun tamamını kullanmıyor. STM32 ler 4 bitlik interrupt sıralaması için yer ayırıyor ve bu preemptive priority ile sub priority arasında bölünüyor. Global bir değişken olarak interrupt grubunu 0'dan 4'e kadar seçebiliyorsun ve bunu kaç bit girersen preemptive priority için o kadar yer ayrılmış oluyor kalan da sub priority için ayrılıyor.

Preemptive priority için şöyle söyleyelim. Önceliği yüksek olan(sayı olarak düşük olan mesela 0) önceliği düşük olan(mesela 1), düşük öncelikli interrupt gerçekleşirken yüksek öncelikli interrupt tetiklenirse program düşük önceliklide kaldığı yeri kaydedip yüksek öncelikli interruptı tamamlayıp sonra geri düşük öncelikli interrupt'a dönüp kaldığı yerden devam eder. Preemptive priority işte bu önceliği belirler. Yüksek öncelikli interrupt devam ederken düşük öncelikli tetiklenirse, yüksek öncelikli bittikten sonra düşük öncelikli yapılır.

Sub priority ise aynı preemptive priority önceliğine sahip 2 interrupt olduğunu düşünelim, 2 interrupt aynı anda tetiklenirse hangisinin önce gerçekleşeceğini belirtir ancak biri gerçekleştirilirken bırakıp gidip diğerini yapmaz. İlk yapılan bittikten sonra diğerini yapar.

STM firması interrupt priority sıralamalarının boşta bırakılmamasını tavsiye ediyor.

Doğru anladıysam, 0.5 ms süren var. İnterrupt tetiklenme frekansın 2kHz. Başlangıç noktasına gelmen içinse 2 kere tetiklenmesi gerekiyor. Bu da eğer bir sinyal olarak düşünür ve başlangıç durumuna gelmesini kabul edersen 1kHz frekansına sahip olduğun anlamına geliyor. Yani LED Toggle olarak düşünürsek tekrar 0 başlangıcına(aynı noktaya) gelmen 1 mili saniye ancak bunun için 2 kere interrupt tetikleniyor.
Monad hocam interrrupt priority ile alakalı yazdıklarını hemen bir yere kaydettim cidden çok iyi açıklamışsın teşekkür ederim.
İnterrupt kısmına gelirsek bende hala flu noktalar var. İnterrupt tetikleme zamanım 1ms. Yani yukarıda yaptığım hesabıma göre mcu her 1 msn bir interrupta gidecek ve Interrupt'ımın içerisindeki kod bloğu işlenecek. Peki tam olarak ne kadar bir işlenme zamanım var. Son dediğiniz iki kere interrupt tetikleniyor kısmını anlamadım.
Genelde interruptta çok bişey yazılmaz diye bir argüman var bunun ucu açık tamam yazılmaz doğru ama sınırlarımı bilirsem o sınırlar dahilinde istediğimi yazabilirim.

isoment01

#4
Şimdi bu asağıda gönderdiğim şekilde Flag set olarak kalıyor. Ben bunu software'de clear yapmazsam ne olacak ? Ki ben Stm32'de callbackleri kullanıyorum clear yapma ihtiyacı duymuyorum. Otomatik olarak bir yerde yapıyor mu onu da bulamadım. Sanki ben resetlemesem o hep oyle kalacak ve interrupta girmicek gibi ama bende giriyor. Flag set oldugu surece ınterruptta kalıyor demek oluyor degıl mı ? Yani ben ikinci bir interrupt gerceklesene kadar mümkün oldugunda hızlı bir şekilde flagi set etmem lazım ki CPU kendi işlerine dönsün. Flag set olmazsa sürekli handler'da kalacak ve işlemci düzgün çalışmıcak.
Peki atıyorum 1ms lik bir interruppta interuptın içine 1ms'nin üstünde sürecek bir  kod bloğu konursa ne olur ? Bir kere set olur daha sonra sapıtır galiba ne olacağını kestiremiyorum. Sesli düşündüm ama sorumun cevabını buldum galiba :D


Alıntı yapılan: isoment01 - 05 Nisan 2020, 15:41:10Monad hocam interrrupt priority ile alakalı yazdıklarını hemen bir yere kaydettim cidden çok iyi açıklamışsın teşekkür ederim.
İnterrupt kısmına gelirsek bende hala flu noktalar var. İnterrupt tetikleme zamanım 1ms. Yani yukarıda yaptığım hesabıma göre mcu her 1 msn bir interrupta gidecek ve Interrupt'ımın içerisindeki kod bloğu işlenecek. Peki tam olarak ne kadar bir işlenme zamanım var. Son dediğiniz iki kere interrupt tetikleniyor kısmını anlamadım.
Genelde interruptta çok bişey yazılmaz diye bir argüman var bunun ucu açık tamam yazılmaz doğru ama sınırlarımı bilirsem o sınırlar dahilinde istediğimi yazabilirim.

Monad

Hocam ben sizin sorunuzu yanlış anlamışım o yüzden de yanlış cevap vermişim. Siz 2 khz timer elde ettikten sonra periyotu 1 e çekip 0'dan 1'e saydığı için 1 kHz frekansa sahip bi timer oluşturuyorsunuz. 1ms interrupt tetikleme süreniz var. Dediğiniz gibi 0'dan 1'e gittikten sonra 1'den 0'a tekrar dönüp tetikleme oluşturması için center aligned mode seçip üzerine de çift tetiklenmeyi açmanız gerek. Böyle yapsanız bile 2khz frekansa sahip bir sinyal yine mutlak olarak aynı periyod değerine sahip olduğundan yine 1kHz değerine sahip olacaktır. Bu yüzden 1ms süreniz var.

Timer kullanırken interrupt handler içerisindeyken timer'lar hala saymaya devam ediyor. Bu yüzden timer tetiklendiğinde interrupt tekrar tetiklenmeden programın fonksiyonu bitirip çıkması gerek.

Interrupt tetiklendiğinde hangi interrupt'sa onun flagi 1 olur. Register seviyesinde programlarken kendiniz fonksiyondan çıkmadan 0'lıyorsunuz henüz HAL öğrenmeye yeni başladım o yüzden detaylı birşey diyemem ama interrupt'dan çıkması için software'den 0'lanması gerekiyor zaten datasheet'te de böyle yazıyor. Bu yüzden o kullandığınız fonksiyonlar da 0'lıyordur.

Daha uzun süren bir duruma girerse TIM interrupt'lar dediğiniz gibi sapıtır. Muhtemelen gerekli bazı Flag'leri 1 durumuna çekiliyordur ve software'den o flagler 0'lanmadıkça da düzelmiyordur.

isoment01

/* Transmit Mailbox 1 management *****************************************/
    if ((tsrflags & CAN_TSR_RQCP1) != 0U)
    {
      /* Clear the Transmission Complete flag (and TXOK1,ALST1,TERR1 bits) */
      __HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_RQCP1);

      if ((tsrflags & CAN_TSR_TXOK1) != 0U)
      {
        /* Transmission Mailbox 1 complete callback */
#if USE_HAL_CAN_REGISTER_CALLBACKS == 1
        /* Call registered callback*/
        hcan->TxMailbox1CompleteCallback(hcan);
#else
        /* Call weak (surcharged) callback */
        HAL_CAN_TxMailbox1CompleteCallback(hcan);
#endif /* USE_HAL_CAN_REGISTER_CALLBACKS */

      }
...
}

tamam mesela burada yapıyormus kendiliğinden silme işini.