STM32F Kesme(Callback) Rutinleri İçerisinde Fonksiyonlara Dallanma !

Başlatan bymrz, 26 Mayıs 2019, 20:32:13

bymrz

Arkadaşlar Merhaba,

Bir konu hakkında yardımlarınıza ihtiyacım var.

Daha önce kullandığım 8bit mikrodenetleyicilerde kesme rutini içerisinde dışarıdan fonksiyon çağırmamaya  dikkat ediyordum. Çünkü Program Counter ile sorun oluyor ve program kilitlenebiliyordu. En kötü ihtimalle interrupt içerisinde bir fonksiyon kullanmam gerekiyorsa da, sırf kesme için ayrı bir fonksiyon kopyalıyor, bu fonksiyonu ana programda kullanmıyordum.

Örneğin, ana program içerisinde :

FonksiyonOrnek(a,b);

kullanırken; kesme içerisinde ise :
FonksiyonOrnek_ISR(a,b);

fonksiyonunu çağırıyordum ki çakışma olmasın.

Fakat şimdi STM32 serisine geçtim ve kütüphanelerde bir çok yerde "callback" rutinleri var. Ve bu callback rutinlerini takip ettiğimde hepsi "kesme rutinlerinin" içerisinden dallanıyor.

Örneğin:
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{

}

Şimdi ben bu callback rutinleri içerisinde ana programda kullandığım bir fonksiyonu çağırırsam ne olur.(Aşağıdaki gibi)
void main (void)
{
sonuç = Topla(a,b);
}


void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
sonuç = Topla(a,b);
}

Aynı çakışma durumu burada da söz konusu olur mu? Yoksa ArmCortex lerde farklı bir mekanizma mı var bu çakışmayı önleyecek?


Şimdiden cevaplarınız için teşekkürler.

Elektroemre

Çağırdığınız fonksiyon re-entrant ise sıkıntı olmaz, re-entrant şartları için linkteki mesajların birinde güzel açıklanmış:

https://stackoverflow.com/questions/34758863/what-is-reentrant-function-in-c

Kısacası sorunuzun cevabı "Topla" fonksiyonunun içinde neler olduğuyla alakalı.

Amenofis

Kesmede niçin fonksiyon kullanılamasın ki? Ha mesela call yerine jump kullanılırsa, ya da bir şekilde bıraktığı noktaya geri dönmezse program kitlenir tabi. Bu kod kusurudur.

Bir fonksiyonun re-entrant yapıda olup olmaması fonksiyonun kendisiyle alakalı bişey, donanımla alakası yok. Eğer fonksiyon global değişkenlere yazıyorsa bu işlemin atomic olması lazım yoksa veri kaybı olabilir. Fonksiyonu çağıran taraf bunu bilemez.

bymrz

Hocam aslında "topla" örneği basit oldu... Örneği Şu şekilde değiştirelim
void main (void)
{
SendDataUsb(data_ptr,size);
}


void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
SendDataUsb(data_ptr,size);
}


Bu durumda büyük bir ihtimalle program çakışacaktır değil mi?
Usb veya spi vb bir transfer yapan bir fonksiyonu interrupttan çağırmak kesinlikle tehlikeli olacaktır???

bymrz

@Elektroemre , Hocam bu arada bir iki ay önce bi konu açmıştım..

https://www.picproje.org/index.php/topic,74928.0.html

Oradaki
Alıntı yapılan: Elektroemre - 22 Şubat 2019, 23:14:25Akıllı düşünürken deli yol alırmış :)

sözü beni çok etkiledi. Uzun zamandır yaptığım hata buymuş. Konuyu açtıktan sonra STM32F M4 çekirdekli 2 proje yaptım ve çalıştırdım. Donanımların da çoğunu(DMA dahil) kullandım...

 :)


Elektroemre

 Bir hayra vesile olduysam sevindim hocam :)  :) 1-2 yıl öncesine kadar bir çok konuda obsesif ve pimpirikliydim. Baktım böyle olmuyor. Artık projede çok fazla düşünmeden hemen bir pcb tasarlayıp baskıya gönderiyorum. Eksik yanlış hatalı sıkıntı etmeden taslak bir yazılımla prototipi çıkarıyorum. Müşteriye sunuyorum. İşten para gelecekse oturup, sıfırdan ve ilk prototipten elde ettiğim deneyimle obsesif ve pimprikli şekilde yine tasarımı yapıyorum.

Soruya dönecek olursak, SendDataUsb fonksyionun reentrant olmadığı kabak gibi ortada. Kendi projemde muhtemelen şu 2 çözümden birini seçerdim:
1 - Zamanlama çok önemli değilse, interrupt içinde flag set edip, "SendDataUsb" fonsksiyonunu sadece mainde kullanmak.
2 - Zamanlama önemliyse, mainden ve interupttan gelen istekleri 3. bir fonksiyonda güvenli şekilde kuyruğa sokardım. Arka planda kuyruktaki isteklere göre ya da kuruktaki isteklerin priority sine göre "SendDataUsb" fonskyonunu kullanan 3. bir rutin hazırlardım.