Ynt: Program Memory İle ilgili

Başlatan serhat1990, 23 Temmuz 2012, 13:41:12

serhat1990

Örneğin bir veri alma rutini Hocam...

      
      if(RCIF)

{



      if(usart_rx_buffer[0]!='S')usart_rx_length=0;      //yani usarttan gelen verinin ilk byte'i 'S' ( ilk frame ) değil ise buffer sayacını sıfırla...
   
      usart_rx_buffer[usart_rx_length]=seri_al();            //Receiver tamponunun içerisini usart buffer'ına alalım :)   
         
      
      
      
      if(usart_rx_length>=4)      //4 byte veya daha fazla veri alındı mı ? Eğer alındıysa ilk 4 byte baslangıc frame'i olup olmadıgını sorgula....

         {
            if((usart_rx_buffer[1]=='T')&&   // frame kontrolü...
               (usart_rx_buffer[2]=='R')&&   // frame kontrolü...
               (usart_rx_buffer[3]=='T'))   // frame kontrolü...

               {
                  startframe=1;      //start frame dogru...
               }

            
            else{
      
                  startframe=0;       //start frame dogru değil...
                  usart_rx_length=0;   //buffer sayacını sıfırla...
               }
         }

      
         
       if((usart_rx_buffer[usart_rx_length]=='D')&& // frame kontrolü...
       (usart_rx_buffer[usart_rx_length-1]=='N')&&   // frame kontrolü...
       (usart_rx_buffer[usart_rx_length-2]=='E'))      // frame kontrolü...
    
   
   
            
               {
                  endframe=1;      //end frame dogru ...
               }

               usart_rx_length++;      //buffer sayacını bir arttır...

               if((usart_rx_buffer[1]!='D')&&
                  (usart_rx_length==2)){
               usart_rx_buffer[2]=seri_al();
               usart_rx_buffer[3]=seri_al();
               usart_rx_buffer[4]=seri_al();
               usart_rx_buffer[5]=seri_al();
               usart_rx_buffer[6]=seri_al();
               usart_rx_buffer[7]=seri_al();
               komut_kontrol();      //eğer frame'in 1.byte'i doğru değilse komut geliyormu kontrol et... 
               }
         }

eistain_54

aklma gelen son satırdaki
if((usart_rx_buffer[1]!='D')&&
                  (usart_rx_length==2)){
               usart_rx_buffer[2]=seri_al();
               usart_rx_buffer[3]=seri_al();
               usart_rx_buffer[4]=seri_al();
               usart_rx_buffer[5]=seri_al();
               usart_rx_buffer[6]=seri_al();
               usart_rx_buffer[7]=seri_al();
               komut_kontrol();      //eğer frame'in 1.byte'i doğru değilse komut geliyormu kontrol et...


kısmında bunun yerine
usart_rx_buffer[2]=seri_al(usart_rx_length);


şeklinde düzenlesen ve o fonksiton içinde usart_rx_length kadar arttırsan?Bilmiyorum yer konusunda sana bişey sağlarmı ama kod verimliliği açısından çok iyi değil bence.Gerçi seri_al(); fonksiyonu içinde neler var bilmiyorum ama böyle düzenleyebilirsen bişey olur sanki?Uzmanlar cevaplarsa bende öğrenmiş olurum.

İyi çalışmalar
Her gün 24 altın verilirken bunun için kime şükredersin ey ademoğlu!?!

serhat1990

Hocam seri_al fonksiyonu seri haberleşme dosyamda . RCREG içeriğini okuyup veriyor. Receiver interrupt flag gelince...

Önerilerinizi değerlendiriyorum.

NecroCapo

Hi-Tech için olmasa da, kullandığım bir döküman var (Microchip'in kendi dökümanı) ve gerçekten çok işe yarıyor C18 için. Belki aynı mantıkla Hi-Tech compiler da optimizasyon yapıyor olabilir. Denemekte fayda var.

ftp://pti.kpi.ua/pub/electric/Microchip/disc2/download/tools/picmicro/code/mplab18/optimize.pdf

Pyrodigy

Alıntı yapılan: z - 23 Temmuz 2012, 19:52:59
Yazdığın fonksiyonlardan bir yada iki tanesini yayınlarsan alternatif yazım şekilleri oluşturulabilir belki.

Bazı rutinler asm yazılabilir.
Hep C nin ASM ye göre üstünlüklerinden bahsedildi, işte şimdi ASM dilinin önemi bu gibi durumlarda ortaya çıkıyor. Kaynak kodunu ASM ye çevirmek yada belli yerleri ASM kanalında devam etmek mantıklı olacaktır.
Bir başka önerim ise Hi-Tech programını eğer öğrenci veya free versiyonunu kullanıyorsan optimize etmiyor diye duymuştum, o yüzden farklı versiyon veya kürekli versiyonlarla yelken açmanı tavsiye ederim.
Persistance is the name of the game in this business....

Erol YILMAZ

Program da bol bol instruction üreten bölgeler tesbit edilmeli ve buralara odaklanılmalı bence...
Matematik işlemler vs duruma göre çok optimize kaldırabilecek alanlar...

serhat1990

İnceliyorum Hocam. Önerilerinizin hepsini kontrol etmeye çalışıyorum .

Alıntı yapılan: Allegro - 24 Temmuz 2012, 10:12:32
Program da bol bol instruction üreten bölgeler tesbit edilmeli ve buralara odaklanılmalı bence...
Matematik işlemler vs duruma göre çok optimize kaldırabilecek alanlar...

Hocam biraz daha açarmısınız konuyu ?

Erol YILMAZ

bazı arkadaşların kodlarında görüyorum misal,

adcVolt = 0.00488 * adc;


gibi ifadelerle kod yazıyorlar.

Buna benzer gereksiz floating işlemler, içinde çarpma bölme komutları bile olmayan 8 bit mcu'yu her bakımdan üzüyor.


Kodlarınızda bunun gibi alanları göremediğim için birşey diyemiyorum...

serhat1990

Alıntı yapılan: Allegro - 24 Temmuz 2012, 10:35:09
bazı arkadaşların kodlarında görüyorum misal,

adcVolt = 0.00488 * adc;


gibi ifadelerle kod yazıyorlar.

Buna benzer gereksiz floating işlemler, içinde çarpma bölme komutları bile olmayan 8 bit mcu'yu her bakımdan üzüyor.


Kodlarınızda bunun gibi alanları göremediğim için birşey diyemiyorum...


Hocam şu şekilde bir sıcaklık hesaplaması var...

Örneğin.

   
   sicak=Sensor_Oku();
   sicak=(sicak/2)-64;
   seri_yaz("Sicaklik=");
   seri_gonder((sicak%100)/10+48);
   seri_gonder(sicak%10+48);
   seri_yaz("C\r\n");

Erol YILMAZ

Kaynak kodundan izole ederek görebilirsin bunları...

Örneğin bu kod kaç word tutuyor ?

  seri_gonder((sicak%100)/10+48);
   seri_gonder(sicak%10+48);


Daha az kod üretecek şekilde düzenlenebilir mi ?

serhat1990

Alıntı yapılan: Allegro - 24 Temmuz 2012, 11:12:36
Kaynak kodundan izole ederek görebilirsin bunları...

Örneğin bu kod kaç word tutuyor ?

  seri_gonder((sicak%100)/10+48);
   seri_gonder(sicak%10+48);


Daha az kod üretecek şekilde düzenlenebilir mi ?

Hocam dediğiniz gibi çok fazla yer kaplıyor... 74 word.

Tagli

74 word olayın görülen kısmı. O 74 word'ün bir kısmı ilgili alt rutinleri çağıran komutlar. Eğer ilgili işlemlerin tamamından kurtulursan, alt rutinlerden de kurtulursun. Programında bir tane bile o türden işlem olsa, mesela 16 bit iki integer'ın bölünmesi gibi, ilgili kod programa eklenir. Ondan sonra aynı işlemi 10 kez daha yapsan da koda yeni bir alt rutin eklemesi yapılmaz.
Gökçe Tağlıoğlu

serhat1990

Alıntı yapılan: Tagli - 24 Temmuz 2012, 11:33:32
74 word olayın görülen kısmı. O 74 word'ün bir kısmı ilgili alt rutinleri çağıran komutlar. Eğer ilgili işlemlerin tamamından kurtulursan, alt rutinlerden de kurtulursun. Programında bir tane bile o türden işlem olsa, mesela 16 bit iki integer'ın bölünmesi gibi, ilgili kod programa eklenir. Ondan sonra aynı işlemi 10 kez daha yapsan da koda yeni bir alt rutin eklemesi yapılmaz.

Dediğinizi doğru anladıysam şu şekildemi diyorsunuz Hocam...

Örneğin 16 bitlik bir registeri ikiye bölmek...

void bol(unsigned int deger)

{
...

...

}

vs gibi tek bir işleme yönlendirmi diyorsunuz .

İşlemi yapacak olan sayı degeriyle bu fonksiyona girsin şeklinde.

Tagli

Hayır, diyorum ki sen mesela kodda,
a = 16;
b= 5;
x = a / b;
yazdığın zaman bu işlem derleyici tarafından öyle bir fonksiyona yönlendiriliyor. Programındaki tüm x = a / b gibi işlemlerden kurtulursan, hafızada yer kaplayan o fonksiyondan da kurtulursun.

Aşağıdaki kodu, yazmış olduğum bir program için XC8'in ürettiği disassembly listing'den aldım. 16 bit integer bölme fonksiyonu. Bu yine çok uzun sayılmaz, floating point sayılar üzerinde işlem yapanlar daha uzun oluyor.
---  /opt/microchip/xc8/v1.00/sources/lwdiv.c  ----------------------------------------------------------
1:             // word unsigned division
2:             
3:             unsigned int
4:             #ifdef __PICC__
5:             #warning TODO: update cgpic and this file to use the other prototype
6:             __lwdiv(unsigned int divisor, unsigned int dividend)
7:             #else
8:             __lwdiv(unsigned int dividend, unsigned int divisor)
9:             #endif
05D5  1283     BCF STATUS, 0x5
05D6  1303     BCF STATUS, 0x6
05D7  01A5     CLRF out
05D8  01A6     CLRF 0x26
10:            {
05D9  0821     MOVF len, W
05DA  0420     IORWF ms, W
05DB  1903     BTFSC STATUS, 0x2
05DC  2DDE     GOTO 0x5DE
05DD  2DDF     GOTO 0x5DF
05DE  2E1D     GOTO 0x61D
11:            	unsigned int	quotient;
05DF  01A7     CLRF counter
05E0  1403     BSF STATUS, 0x0
05E1  0DA7     RLF counter, F
12:            	unsigned char	counter;
05E2  2DEF     GOTO 0x5EF
05EF  1FA1     BTFSS len, 0x7
05F0  2DF2     GOTO 0x5F2
05F1  2DF3     GOTO 0x5F3
05F2  2DE3     GOTO 0x5E3
05F3  2DF5     GOTO 0x5F5
05F4  2DF5     GOTO 0x5F5
13:            
05E3  3001     MOVLW 0x1
05E4  1003     BCF STATUS, 0x0
05E5  0DA0     RLF ms, F
05E6  0DA1     RLF len, F
05E7  3EFF     ADDLW 0xFF
05E8  1D03     BTFSS STATUS, 0x2
05E9  2DE4     GOTO 0x5E4
14:            	quotient = 0;
05EA  3001     MOVLW 0x1
05EB  00A4     MOVWF duty
05EC  0824     MOVF duty, W
05ED  07A7     ADDWF counter, F
05EE  2DEF     GOTO 0x5EF
15:            	if(divisor != 0) {
16:            		counter = 1;
17:            		while((divisor & 0x8000) == 0) {
05F5  3001     MOVLW 0x1
05F6  1003     BCF STATUS, 0x0
05F7  0DA5     RLF out, F
05F8  0DA6     RLF 0x26, F
05F9  3EFF     ADDLW 0xFF
05FA  1D03     BTFSS STATUS, 0x2
05FB  2DF6     GOTO 0x5F6
18:            			divisor <<= 1;
05FC  0821     MOVF len, W
05FD  0223     SUBWF counter, W
05FE  1D03     BTFSS STATUS, 0x2
05FF  2E02     GOTO 0x602
0600  0820     MOVF ms, W
0601  0222     SUBWF i, W
0602  1C03     BTFSS STATUS, 0x0
0603  2E05     GOTO 0x605
0604  2E06     GOTO 0x606
0605  2E0E     GOTO 0x60E
19:            			counter++;
0606  0820     MOVF ms, W
0607  02A2     SUBWF i, F
0608  0821     MOVF len, W
0609  1C03     BTFSS STATUS, 0x0
060A  03A3     DECF counter, F
060B  02A3     SUBWF counter, F
20:            		}
060C  1425     BSF out, 0x0
060D  2E0E     GOTO 0x60E
21:            		do {
22:            			quotient <<= 1;
060E  3001     MOVLW 0x1
060F  1003     BCF STATUS, 0x0
0610  0CA1     RRF len, F
0611  0CA0     RRF ms, F
0612  3EFF     ADDLW 0xFF
0613  1D03     BTFSS STATUS, 0x2
0614  2E0F     GOTO 0x60F
23:            			if(divisor <= dividend) {
0615  3001     MOVLW 0x1
0616  02A7     SUBWF counter, F
0617  1D03     BTFSS STATUS, 0x2
0618  2E1A     GOTO 0x61A
0619  2E1B     GOTO 0x61B
061A  2DF5     GOTO 0x5F5
061B  2E1D     GOTO 0x61D
061C  2E1D     GOTO 0x61D
24:            				dividend -= divisor;
25:            				quotient |= 1;
061D  0826     MOVF 0x26, W
061E  01A1     CLRF len
061F  07A1     ADDWF len, F
0620  0825     MOVF out, W
0621  01A0     CLRF ms
0622  07A0     ADDWF ms, F
0623  2E24     GOTO 0x624
26:            			}
0624  0008     RETURN
27:            			divisor >>= 1;
28:            		} while(--counter != 0);
29:            	}
30:            	return quotient;
31:            }
Gökçe Tağlıoğlu

ferit06

#29
program belleğinden tasarruf ile ilgili olarak ben de proton ile yazılmış bir kod parçasından örnek vereyim..

       If HAM>872 Then Hata=1   ' ölçüm hatalı -25 deceden düşük
' isaret=0
' ISI=HAM-872
' ISI=ISI*150
' ISI=ISI/356
' ISI=ISI+25
' ISI=ISI*(-1)
 'If ISI<0 Then ISI=ISI* (-1):isaret=1



' ISIT=ISI*10    ' 7 SEGMENT DISPLAY GÖSTERİMİ İÇİN FLOAT DEĞİŞKEN WORD 
            'DEĞİŞKENE AKTARILIYOR 10 İLE ÇARPARAK ONDALIK GÖSTERİM SAĞLANIYOR
            'ONDALIK 2 HANE İÇİN 100 İLE ÇARPILABİLİR BU ŞEKİLDE 7 SEGMENT D
            'ISPLAYDA ANCAK 5 HANE GÖSTERİLEBİLİR Dig Digit komutu yalnızca 5 
            'hane için çalışmaktadır.

'ISIT=ISIT/10   'ISI float iken kullanılan bölümün Word tipi ISI değişkeni
ISI=872-HAM     'ile değiştirilmesi sonucunda 1320 program word olan program belleği 
ISI=ISI*150     ' toplam kullanılan alan 649 program worde indirgenmiştir.
ISI=ISI/356
isaret=0
If ISI<25 Then
isaret=1
ISI=25-ISI
Else
ISI=ISI-25
EndIf


float olarak tanımlanan değişkenle  sadece 4   5 defa işlem yapılan bir uygulamada 1320(toplam program bellek alanı) aynı sonucu verecek işlemlerin  değişkenin word olarak tanımlanması ile toplam program bellek alanı 649 worde düşmüştür. 671 word lük  program belleği tasarrufu sağlanmıştır.