TMR0 kesmesinde sayımı if else ile yakalayamamak

Başlatan dyonizos, 11 Temmuz 2012, 04:38:07

z

Hangi dili kullanırsan kullan sonuçta bir değişkene erişmek istediğinde

1. Değişkenin adresini registere yükle
2. Bu registerin içerdiği adrese erişerek oku yada yaz

Eğer bu iki adımı tek komutta (tek komut olsa bile 1 yada 2 cycleda işlemesi de önemli) işletemeyen işlemci ile çalışıyorsan (işlemcilerin çoğu bunu yapamaz) bu durumda değişkene erişim, en az 2 CPU komutunda (yada 3 cycle da) olacak demektir. Çünkü, 1. komut genelde 2 nolu komutun en az 2 katı zamanda işleyen bir komuttur.

Bu durumda farklı farklı değişkenlere erişim gerekiyorsa her defasında 1 ve 2 komutun işletilmesi gerekir.

Pointer erişiminde Baz adresi bir kereliğine yüklersin. bu 1. komutdur.
Bundan sonra sadece 2 komutu işletirsin. Farklı bir adrese erişmek istediğinde
durum değişir.

Eğer bir sonraki adrese erişeceksen;

Pointerin 1,2,4 gibi artırılması gerekir. Bu çoğu işlemcide zaman kaybına neden olur. Ancak işlemcinin komut kümesinde, adrese eriş (oku yada yaz) ve hemen ardından adres reğister içeriğini N artır komutu varsa bu kayıp zamandan kurtulursun. Çünkü bu komut pointer artırımını da aynı cycle'da otomatik yapar.

Eğer ardışıl adrese erişilmeyip daha uzaktaki bir değişkene erişim sözkonusu ise bu durumda;

Komut kümesinde; Adresdeki veriye erişen komutda ofset adres tanımlanabiliyorsa ve ofset adres bu komuta gömülebiliyorsa bu durumda sözkonusu adrese erişim de tek cycle da yapılır.

Ancak komut listesinde bu tip ofset ilavesi yapan komut yoksa değişken adresinin gene 1   tipi komutla yüklenmesi gerekir.

Eğer bu tip komutlar yoksa pointer kullanımının hız açısından hiçbir getirisi olmaz. Sonuçta bu tür işlemleri, index registerlere ait komutların yetenekleri belirler.




Bana e^st de diyebilirsiniz.   www.cncdesigner.com

CLR

#16
PIC serisinde index registerler var adresi ayrı tutuyor ve adres içeriğini ayrı ve istediğin adrese  dallanıp içeriğini okuyup yazabiliyorsun. Demek istedğimi kısa örnek vereyim

// karşılaştırma yöntemi: basit bişey yaptım çok mantık aramayın, basitlik için saniye kullanalım
// aşağıda görüldüğü gibi tüm karşılaştırmaları yapmak zorundayız, her if işlemi sallıyorum 5us olsa 40-50us zaman harcadık, bir tanesi çalışınca 5usnden fazla zaman harcıyacak
interrutp :
     if(tmr0 > 10) {....} //
     if(tmr0 > 20) {....} //
     if(tmr0 > 30) {....} //
     if(tmr0 > 40) {....} //
     if(tmr0 > 50) {....} //
     if(tmr0 > 60) {....} //
     if(tmr0 > 70) {....} //
     if(tmr0 > 80) {....} //


// pointer ile aynı işlemi 2 işlemde yapabiliyoruz 1. timer0'ı karşılaştırırsın sonra dizi taşmışmı onu karşılaştırsın
const u8  Times[]={10,20,30,40,50,60,70,80};
interrutp :
     static vu8 *TmrPtr=(static vu8 *)Times;
     if(Tmr0>(*TmrPtrPtr)){bu işlemi yap };


Knowledge and Experience are Power

z

Elbette şekil itibariyle pointer kullanımı yazılımı sade gösteriyor. Fakat interrupt rutini gibi rutinlerde hız önemli olduğundan pointer işlemi ile pointersiz işlemin CPU komutlarından oluşan asm dosyasına bir bakmak lazım.

Mesela ARM, 80x86 gibi aileler, verilere yada verialanlarına pointer erişimi için mükemmel makine komutları sunmuşlar.
C işlemciden bağımsız olarak pointer erişimi imkanını sunuyor.  Ben genel konuştum ve pointer ile erişiminin her zaman hızlı olacağı yanılgısının altını çizdim.

Bana e^st de diyebilirsiniz.   www.cncdesigner.com

CLR

Bende öyle anladım zaten, işlemcide index register yetenekli değilse veya sayısı azsa ve biz çok sayıda pointer kullanırsak işlemci olmayan bir özelliği kullanacak değil dolayısıyla sırasıyla point eder ve yavaş olur tabii ama pic18de aynı anda enaz 3 pointer kullanılabilir(working registerle 4), yeni serileri incelemedim belki arttırmışlardır. 
Knowledge and Experience are Power

Tagli

PIC18'lerde zaten donanımsal olarak yanlış hatırlamıyorsam 3, PIC16'larda ise 1 pointer var. Bunları derleyici de kullanıyor olabilir. C18'in bu pointer'lardan ikisini kendi software stack'i için kullandığını biliyorum. Üçüncüyü de galiba fonksiyon dönüş değerleri için kullanıyordu. O zaman geriye pointer kalmıyor... Normal pointer işlemlerini ne şekilde yaptığını bilmiyorum, ama muhtemelen bu 3 pointer'dan en az birini yedekleyip kullanıyor, işi bitince de eski değeri geri yazıyordur belki. Tamamen yanılıyor da olabilirim ama tahminim bu yönde. Eğer durum böyle ise, pointer kullanmanın işleri hızlandıracağını söyleyemeyiz.

z'nin de dediği gibi, durum işlemciden işlemciye değişir. ASM koduna bakmadan bilinemez.
Gökçe Tağlıoğlu

camby

#20
Şu işlemi pointer ile ( Pointer dediğiniz aslında dolaylı adresleme registerları ) daha hızlı yapabilir misiniz ?

Katsayıları hesaba katmadan basit bir örnek yazdım :


KESME					; 1ms'lik kesme
	....

		incf	sayac

	....
retfie






..............

ISLEM1
	
		btg		PORTB,1

		RETURN

..............

ISLEM2



..............



Ana_Program

		movlw		.10
		CPFSEQ		d1
		GOTO		NEXT2
		CALL		ISLEM1
		
NEXT2		movlw		.20
		CPFSEQ		d2
		GOTO		NEXT2
		CALL		ISLEM2

NEXT3		movlw		.30
		CPFSEQ		d3
		GOTO		NEXT4
		CALL		ISLEM3

NEXTN
...............


		GOTO		ANA_Program

	END





Ek :

- Eğer Ana program bu kontrol işlemleri dışında başka işlemler ile dolu ise zamanlamayı kaçırmadan bu işlemler nasıl yapılır ,    Hadi bunu da açıklayın C'ciler soruyorum size   : ))

mesaj birleştirme:: 12 Temmuz 2012, 16:10:51

Alıntı yapılan: Tagli - 12 Temmuz 2012, 15:40:46
PIC18'lerde zaten donanımsal olarak yanlış hatırlamıyorsam 3, PIC16'larda ise 1 pointer var. Bunları derleyici de kullanıyor olabilir. C18'in bu pointer'lardan ikisini kendi software stack'i için kullandığını biliyorum. Üçüncüyü de galiba fonksiyon dönüş değerleri için kullanıyordu. O zaman geriye pointer kalmıyor... Normal pointer işlemlerini ne şekilde yaptığını bilmiyorum, ama muhtemelen bu 3 pointer'dan en az birini yedekleyip kullanıyor, işi bitince de eski değeri geri yazıyordur belki. Tamamen yanılıyor da olabilirim ama tahminim bu yönde. Eğer durum böyle ise, pointer kullanmanın işleri hızlandıracağını söyleyemeyiz.

z'nin de dediği gibi, durum işlemciden işlemciye değişir. ASM koduna bakmadan bilinemez.

Evet , basit işlemlerde bile ( normalda asm'de dolaylı adresleme yapmadan yaptığımız işlemler ) hi-tech arka planda FSR ve INDF registerlarını kullanarak yapılıyordu C18'de öyledir diye tahmin ediyorum.

Tagli

Bence değişen birşey yok, ASM olsa da yine kaçırabilirsin. Çünkü yine eşitlik kontrolü yapıyorsun.

Uygulamanın bu kadar hassas zamanlama gereksinimleri olmaması lazım. Burada yöntem hatası var bence. Yine de en hassas sonuca uicroarm'ın başta önerdiği gibi, her kesmede yeni bir değerle timer'ı yeniden kurarak ulaşabilirsin.
Gökçe Tağlıoğlu

LukeSkywalker

@Camby
Asm tabiki çok daha hızlı çalışacaktır. Bunu bilmeyen yok fakat kulağı tersten tutmanın da anlamı yok arkadaşın sorununda.

camby

#23
Alıntı yapılan: Tagli - 12 Temmuz 2012, 16:17:43
Bence değişen birşey yok, ASM olsa da yine kaçırabilirsin. Çünkü yine eşitlik kontrolü yapıyorsun.

Uygulamanın bu kadar hassas zamanlama gereksinimleri olmaması lazım. Burada yöntem hatası var bence. Yine de en hassas sonuca uicroarm'ın başta önerdiği gibi, her kesmede yeni bir değerle timer'ı yeniden kurarak ulaşabilirsin.

- Yukarıdaki program kaçırmıyor , daha doğrusu kaçırıyor fakat hatalar üst üste binmiyor..

- Zamanlama gereksinimi hassas'dan ziyade öncelikli olabilir , yani kesmeden döndükten 400ms sonra eşitlik kontrolüne bakılırsa zamanlama baya bi şaşar , hatta kesmelerin anlamı kalmaz ( çünkü 1 ms yapmıştık bu örnekte ).

Örneğin bir fonksiyon işletiliyor ( bu bir hesaplama olabilir ) herhangi bir anda timer kesmesi geldi , kesme işletilip fonksiyona geri dönüldü ve fonksiyona devam edildi. Fonksiyondan çıkışa daha 400ms daha süre olabilir. Kesme dönüşü , kesmeden çıktıktan sonra araya işlem alınması gerekir.


- Timer'ı yeniden kurarsak paralel işlem yapamayız diyorum ben de. ( yada anlayamıyorum demek istenileni ) 1 sn timer kuruldu işlem yapıldı , 3 sn timer  kuruldu işlem yapıldı , 2 sn timer kuruldu işlem yapıldı . Toplam 6 sn süre geçti.

4 tane led olsun bu ledleri 1t , 3t , 5t , 7t periyotlarda açıp kapatalım . Bu işlemi her kesmede tekrar timer değeri girerek nasıl yaparız. Yaparız ama bu işlem parametrik olur mu ?  Diyelim bu uygulama bir PLC ve kullanıcı bu parametreleri dışarıdan kendisi giriyor.



mesaj birleştirme:: 12 Temmuz 2012, 16:31:13

Alıntı yapılan: maytere - 12 Temmuz 2012, 16:21:00
@Camby
Asm tabiki çok daha hızlı çalışacaktır. Bunu bilmeyen yok fakat kulağı tersten tutmanın da anlamı yok arkadaşın sorununda.

evet :) , ben tam onu yazacaktım arkadaşa. O konuya çözüm getirildi zaten belki arkadaş çoktan programını yazmıştır.

Ama şu an pointer işlemi ve sırayla karşılaştırmayı tartışıyoruz sadece.

Bu işlem tek başına çok basit gibi gözüküyor ancak başka işlemler ve fonksiyonlar ile birlikte kullanılmaya başlandığında çok önemli bir hale gelebilir.

Tagli

Alıntı yapılan: camby - 12 Temmuz 2012, 16:26:24
- Yukarıdaki program kaçırmıyor , daha doğrusu kaçırıyor fakat hatalar üst üste binmiyor..
Prescaler'e bağlı. Büyük olursa kaçmaz. Ama 1:1 ise kesin kaçar.

Alıntı yapılan: camby - 12 Temmuz 2012, 16:26:244 tane led olsun bu ledleri 1t , 3t , 5t , 7t periyotlarda açıp kapatalım . Bu işlemi her kesmede tekrar timer değeri girerek nasıl yaparız. Yaparız ama bu işlem parametrik olur mu ?  Diyelim bu uygulama bir PLC ve kullanıcı bu parametreleri dışarıdan kendisi giriyor.
Bekleme süreleri bir dizide saklanabilir. Çok kabaca yazarsak:
int periyod[] = {10, 30, 50, 70}
int index = 0;
void interrupt kesme(void){
    switch (indeks){
    case 0:
        //0 nolu isi yap
        break;
    case 1:
        .....
    }
    TMR0 = 255 - periyod[indeks];
    if (++index == 4) index = 0;
    TMR0IF = 0;
    return;
}

Tabi burada yapılacak işlerin LED yakmak gibi, kısa süreli işler olması gerekir. Zamanlama kesme sonundaki birkaç komut sebebiyle tam tutmayacak olsa da, oldukça yakın olabilir. Gerektiğinde dizi içindeki değerlerle oynanarak zamanlama tam olarak ayarlanabilir. uicroarm'ın dediği buydu zaten sanırım.

Tam anlamıyla bir çözüm üretebilmek için gereksinimleri, yani programın yapması gereken işleri ve kod akışının nasıl olması gerektiğini bilmek lazım. Tahminlere dayanarak her durum için en iyi sonuç veren çözüm çıkamaz ortaya. Duruma göre çözüm üretilir.
Gökçe Tağlıoğlu

CLR

Alıntı yapılan: camby - 12 Temmuz 2012, 16:05:07
Şu işlemi pointer ile ( Pointer dediğiniz aslında dolaylı adresleme registerları ) daha hızlı yapabilir misiniz ?

Katsayıları hesaba katmadan basit bir örnek yazdım :


KESME					; 1ms'lik kesme
	....

		incf	sayac

	....
retfie






..............

ISLEM1
	
		btg		PORTB,1

		RETURN

..............

ISLEM2



..............



Ana_Program

		movlw		.10
		CPFSEQ		d1
		GOTO		NEXT2
		CALL		ISLEM1
		
NEXT2		movlw		.20
		CPFSEQ		d2
		GOTO		NEXT2
		CALL		ISLEM2

NEXT3		movlw		.30
		CPFSEQ		d3
		GOTO		NEXT4
		CALL		ISLEM3

NEXTN
...............


		GOTO		ANA_Program

	END





Ek :

- Eğer Ana program bu kontrol işlemleri dışında başka işlemler ile dolu ise zamanlamayı kaçırmadan bu işlemler nasıl yapılır ,    Hadi bunu da açıklayın C'ciler soruyorum size   : ))

mesaj birleştirme:: 12 Temmuz 2012, 16:10:51

Evet , basit işlemlerde bile ( normalda asm'de dolaylı adresleme yapmadan yaptığımız işlemler ) hi-tech arka planda FSR ve INDF registerlarını kullanarak yapılıyordu C18'de öyledir diye tahmin ediyorum.

Merhaba ,

Camby , Yaşlaşık 10yıl kadar asm kod yazdım,  halende yeterince iyi biliyorum diyebilirim. Ama bir C derleyicisini yazan adamlar kadar iyi biliyorum diyemem çünkü onlar aşmışlar o nedenle birincisi senin yazdığın 2 satırlık asm kod ile C derleyicisininkini karşılaştırma, mesela yaz matematik gereken veya mantıksal ifadeler gereken orta büyüklükte bir program(mesela asm ile 10Kbyte'lık(yaklaşık 10bin satır) kod ama dolu kod olacak) sonra derleyici ile karşılaştır kim hatasız ve stable kod yazmış olacak bakalım yoksa 2 led, 3 butonla karşılaştırılmaz.   

Senin yazdığın asm koda gelelim ile bu kodla hassas timer zaten yazamazsın çünkü interupt içinde bir değişkenin değerini arttıyorsun sonra ana programa gidip orada karşılaştırıyorsun eğer ana program içinde azda olda bir delay işlemi olursa tüm zamanlar şaşar. Ki program büyüdükçe kesin olur. Bu yazdığın mantık sistem mantığı benzeridir yani interrupt geldiğinden haberim olsun ve geciksede çalışsın şeklindedir.   Mesela işlem1 içindeki yaptıkların uzun sürerse işlem2 gecikir. Diyorsanki benim hassas zaman dediğim ms'ler düzeyinde bu şekilde çalışabilirsin ama ana programda yine ms düzeyinde delay kullanmaman veya gecikmemen gerekir.
Knowledge and Experience are Power

carirt

uicroarm


diziye pointer atamak  ile interrupt bayrağı nasıl kontol edilebilir bir örnek verebilirmisiniz ben kafamda canlardıramadım bir türlü

camby

Alıntı yapılan: uicroarm - 12 Temmuz 2012, 17:47:49

...eğer ana program içinde azda olda bir delay işlemi olursa tüm zamanlar şaşar. Ki program büyüdükçe kesin olur. Bu yazdığın mantık sistem mantığı benzeridir yani interrupt geldiğinden haberim olsun ve geciksede çalışsın şeklindedir.  Mesela işlem1 içindeki yaptıkların uzun sürerse işlem2 gecikir.

- Ben aşağıdaki mesajlarımın ikisinde de bundan bahsettim. Şimdi siz ben aynısını söylememişim gibi yazıyorsunuz.


- Offset her zaman olur , kesmeye girip içine hiç kod yazmadan çıksak bile 4 cycle süre geçer. Bu bir gecikme olarak sayılabilir , ama timer sürekli çalıştığı için biliyorsunuz ki hatalar üst üste binmez.

- Yapılan işlemlerde kesmeler üst üste binip kaçırmadığımız sürece sapma olmaz.

Yazdığım basit kodların altında ,

Alıntı Yap
Ek :
- Eğer Ana program bu kontrol işlemleri dışında başka işlemler ile dolu ise zamanlamayı kaçırmadan bu işlemler nasıl yapılır ,    Hadi bunu da açıklayın C'ciler soruyorum size   : ))

Diyerek programın yetersizliğine de değindim.

- Bu şaşmanın olmaması için ne yapılır diye sordum ama cevap alamadım. Bunu da ben beraber tartışalım , kendi yöntemimi sizinkilerle karşılaştırayım diye sordum.


Sonuç olarak :

Alıntı Yap......tüm zamanlar şaşar. Ki program büyüdükçe kesin olur....

- Buna katılmıyorum.

CLR

Camby, 4 saykıldan bahsetmiyorum ben, mesela timer interrupt'ı kurdun 1ms'ye ve işlem2ye gitmek istiyorsun, işlem2den önce çalışan altprogramların var diyelim (program büyüdükçe dediğim bu nokta) burada 250us'lik işlemin olsun işlem2 interruptı oluştuktan maximum 250us sonra işlem2yi yapabilirsin.Eğer tam işlem2ye gelmeden interrupt oluşursa o zaman 1ms aralık olmuş olur ama bu zamanlar hep düzensiz olacaktır.

Ek :
- Eğer Ana program bu kontrol işlemleri dışında başka işlemler ile dolu ise zamanlamayı kaçırmadan bu işlemler nasıl yapılır ,    Hadi bunu da açıklayın C'ciler soruyorum size   : ))

Bu soruna cevap vereyim , kritik zaman gerektiren şeyler uzun sürmez mesela adc okursun veya birkaç pini set edersin veya okursun gibi bu işlemleri bahsettiğim gibi pointerle yaparsan daha az zamanda büyük işlem yaparsın.
Veya ana program içinde tüm yapılacakları hazırlarsın interrupt oluştuğunda işlemi sadece başlatırsın. Mesela işlem büyükse alıcıya veri göndereceksen, 10byte olsun ve kritik zamanlara gerektiriyorsa eğer donanımda öncelikle dma varsa onu kullanırsın o yoksa transmit interrupt kullan ki işlemci transfer ederken sende başka işleri halledersin. Transmit interrupt içinde de pointer veya array kullanırsan ardışık kolayca gönderebilirsin.
C'nin gücü asm'den gelir çünkü asmye yakındır, C'nin gücü pointerdan gelir bunun asm karşılı index registerlardır. Asm'cilerin çoğu kullanmaz kattığı avantajı göremezler. Bir işlemcide ne kadar çok index register varsa o kadar güçlüdür.   

Demek ki, kritik işlemler gerekiyorsa C içinde while, do-while, for gibi ifadelerden uzak durmak gerekiyor, Asm içinde sürekli bit/byte testleri gerçekleştirinceye kadar, verielr gönderilinceye kadar vs. beklemek gibi, mesela yukarıda sen eşit oluncaya kadar buda dön dur demişsin işlemciye. İşte gelinceye kadar bekle diye kod yazarsan ve o şart hiç gelmezse işlemcin kilitlenir bu yöntem yanlış kodlamadır mutlaka timeout koyman gerekir. (sadece örnek için yazdım yoksa gerçekte belki böyle yazmıyorsundur asm'yi)
Knowledge and Experience are Power

Tagli

Çok bulanık ifadelerle konuşuyoruz. Bir senaryo belirleyelim, gerçekçi bir senaryo olsun. Sonra bunu çözmek için program yapısının nasıl olması gerektiğini tartışalım.
Gökçe Tağlıoğlu