Program kodu üzerinde zaman ölçümü nasıl yapılır?

taydin

Timur Aydın
Staff member
Katılım
24 Şubat 2018
Mesajlar
24,575
Çok kısa sürede yaptığı işlemi tamamlaması gereken ve bir kesmenin parçası olarak çalışan bir program kodunun ne kadar sürede tamamlandığını nasıl ölçeriz? Bunu yapmanın birçok farklı yolu vardır elbet, ama burada biz iki tane yöntemi ele alacağız.

Elimizde aşağıdaki gibi bir kesme fonksiyonu olduğunu varsayacağz. Bu fonksiyon tabiki bu haliyle faydalı bir iş yapmıyor, ama burada bizim için önemli olan belli bir süre işlemciyi alıkoyan bir kod olması.

C++:
static void isr_func(void)
{
    for (unsigned int i = 0; i < 100000; ++i)
    {
        ;
    }
}
 
Birinci yönten, bir GPIO kullanmak. Mesela bir kesme fonksiyonunun ne kadar zamanda işlediğini görmek istiyoruz. Bunun için fonksiyonun başında pini 1 yapacağız, fonksiyondan çıkmadan hemen önce de 0 yapacağız. Sonra da osiloskop ile burada oluşan palsin süresini ölçeceğiz. Aşağıda, Renesas RA6M2 işlemcisi için fonksiyonumuza bu metodu uygulayalım

C++:
static void isr_func(void)
{
    R_BSP_PinWrite(DEBUG, 1);

    for (unsigned int i = 0; i < 100000; ++i)
    {
        ;
    }

    R_BSP_PinWrite(DEBUG, 0);
}

Bu fonksiyonu sıkı bir döngü içerisinde çalıştırıp palsı ölçelim

a.png
 
İkinci yöntem de, eğer kullandığımız MCU'da bir timer çevre birimi varsa (neredeyse tamamında vardır) bu çevre birimini kullanarak zaman ölçmek. Benim kullandığım RA6M2 de 32 bitlik bolca timer var. Bir tanesini 120 MHz de çalışacak şekilde ve serbest olarak sayacak şekilde yapılandırıyorum. Sonra da fonksiyonun girişinde ve çıkışında timer sayaç değerini not ediyoruz. Son olarak da, not edilen bu zamanların farkını alarak, çok yüksek çözünürlüklü bir zaman ölçümü yapmış oluyoruz.

Aşağıda, fonksiyonu bizim 32 bit timer değerlerini okuyacak şekilde elden geçiriyoruz

C++:
static void isr_func(void)
{
    unsigned int t1 = *hrtimer;

    for (unsigned int i = 0; i < 100000; ++i)
    {
        ;
    }

    unsigned int t2 = *hrtimer;

    unsigned int dt = t2 - t1;
}

Sonra da programı debugger'da çalıştırıp dt değişkenine yazılan değere bakıyoruz.

a.png


istikrarlı bir şekilde 1100020 değerini okuyoruz. Timer saat frekansını biliyoruz, buradan da toplam süreyi hesaplayalım

[math]t = \frac{1}{120\times10^6}\times 1100020 = 0.00916683\ s[/math]
 
İki yöntemle de birbirine çok yakın sonuç alıyoruz, ama ikinci yöntemin doğruluğu ve çözünürlüğü ilk yöntemden çok daha iyi olacaktır. Timer saat hızı 120 MHz olduğu için zaman çözünürlüğümüz 8.33 ns olacaktır. Ayrıca timer bir kristal osilatör ile çalıştırıldığı için bu zamanlama da çok istikrarlı olacaktır. Ayrıca osiloskop bant genişliğinden kaynaklanan pals uzunluğu belirleme hataları da elimine edilmiş olacaktır. Bunun dışında pin değerini set eden fonksiyonun katacağı ilave zaman belirsizliği de olmayacaktır. Bakacak olursak, timer değerini okumak sadece 4 makina dili komutundan ibaret. 240 MHz de çalışan bir RISC işlemci için bu 16.6 ns lik bir zaman alır. Ama pin set etmek fonksiyonunun çağrılması, işini yapması ve geri dönmesi bundan çok daha uzun sürecektir.

a.png
 
Zaten osiloskopta yapılan ölçümde, peş peşe yapılan ölçüm değerlerinde belli bir varyans var. Ama timer ile yapılan ölçümde HİÇ varyans yok. HER ZAMAN aynı değer okunuyor timer sayacından.

Bir de pin yazma ile oluşan koda bakalım. fonksiyonun kendisinde fazla bir kod görünmüyor

a.png


Ama çağrılan fonksiyona bakarsak işin boyutu net bir şekilde görülüyor

a.png
 
Neticede her iki yöntem de pratikte kullanışlıdır. Ama mikrosaniye altı çok hassas ölçümler yapılması istendiğinde, timer metodunu kullanmak lazım.

Eğer kullanılan işlemcide TRACE desteği varsa ve bu trace verilerini de toplayabilen bir debug adaptörünüz varsa, bunların hiçbirisi ile uğraşmadan işlemcinin doğrudan kendisinden alınabiliyor her bir komutun ne kadar sürdüğü, programın herhangi bir noktasında zamanın tam olarak ne olduğu. Ve burada ölçüm hatası neredeyse sıfır olacak, çünkü ölçüm yapabilmek için programı değiştirmek zorunda olmuyoruz. Program olduğu gibi, orijinal hali ile çalışıyor. Ama bu hem yaygın kullanılan bir yöntem değil, hem de trace özelliği olan debug adaptörleri son derece pahalı.
 
Kullandığın kristalin TAM değerini doğrulamak gerekir mi? Geçen gün ben ölçüm yaptığımda (atıyorum) 6 MHz kristal 5.998 MHz gibi farklı bir değer çıkmıştı.
 
Program kodunda zaman ölçümü için gözardı edilebilir. Ortalama bir kristalin toleransı 50 ppm dir. Bu da yüzde olarak %0.005 lik bir hata demektir.
 

Forum istatistikleri

Konular
7,185
Mesajlar
121,926
Üyeler
2,908
Son üye
coco45

Son kaynaklar

Son profil mesajları

Freemont2.0 wrote on herbokolog's profile.
nick iniz yakıyor
:D
Freemont2.0 wrote on posta's profile.
Merhabalar :)
az bilgili çok meraklı
Prooffy wrote on semih_s's profile.
Merhaba, sizden DSO2C10 hakkında bilgi rica ettim. Yanıtlarsanız sevinirim...
Unal wrote on taydin's profile.
Timur Bey, Arduino kontrollü bir akü şarj cihazı yapmaya çalışıyorum. Aklımdaki fikri basit bir çizim olarak konu açmıştım. Özellikle sizin fikirlerinizi çok önemsiyorum.
Back
Top