Arkadaşlar bir projede kullandığım işlemcinin program memory doldu. Artık içine yazamıyorum . Sizce programda ne tür kısaltmalara gitmek bellek açısından tasarruf sağlar . Hangi fonksiyonlardan kaçınmalıyım. Önerilerinizi bekliyorum ... İyi çalışmalar...
Alıntı yapılan: gerbay - 23 Temmuz 2012, 13:57:01
kodunuz çok özel değilse görme imkanımız var mı? hangi MCU kullanıyorsunuz?
Hocam bir firma için proje o yüzden açık kaynak kodu veremiyorum yanlış anlamayın lütfen . İşlemci olarak 16f1827 kullanıyorum ... Programda eklenmesi gereken bir kaç özellik kaldı fakat onları eklemeye çalşırsam program memory hatası alıyorum ... İşlemci değiştirmek gibi bir şansımda yok. Tıkandım kaldım...
neden işlemci değiştiremiyorsun ki? hazır bir sistemin üzerinde değişiklik mi yapıyorsun?
Alıntı yapılan: serdararikan - 23 Temmuz 2012, 14:43:09
neden işlemci değiştiremiyorsun ki? hazır bir sistemin üzerinde değişiklik mi yapıyorsun?
Hocam Sistemi baştan yaptım onda değil sıkıntı . Firmanın çabucak istemesi nedeniyle ve pcblerin montajlarının yapılması nedeniyle sorun... Ondan dolayı diyorum. Benim uyarılarıma rağmen sıkıntı olmaz demeleri işlemcinin yazılımı tamamıyla bitmeden böyle bir işe kalkışmaları sorun. Diğer türlü daha büyük program memory'li bir chip'e geçerek sorun çok kolaya indirgenebilirdi ama sizde bilirsinizki bazı firmalar bu konuda çok ama çok aceleci ...
Alıntı yapılan: gerbay - 23 Temmuz 2012, 14:51:53
7 KB flash, 384 byte RAM var, yer çok dar..
eğer biten ROM değil de RAM ise read-only datalarınızı static const yapın, RAM kullanan hesaplama varsa mümkün olduğunca lookup-table oluşturarak çözmeye çalışın olayı.. 384 byte çok az..
Hocam dolan program memory , ram'in durumuda pek iç açıcı değil ama program memory doldu...
Yazılı metinlerde azaltmaya gidecem . Bakalım gerekli yer açılacakmı. Bu arada aklınıza gelebilecek program memory'den tasarruf yapabileceğim yönler varsa dinlemedeyim hocam...
muhtemelen LCD kullanıyorsun.LCD deki metinler çok fazla yer kaplıyor olabilir.
Lcd kullanmıyorım Hocam. Ama seri porttan veri gönderiyorum. Bu verilerin ne oldugunu belli eden metinler yer kaplıyor tahminimce.
Ayrıca matematiksel işlemler var. Bunlarda baya bir yer kaplıyor...
Hocam derleyiciniz kod optimizasyon seviyesini eğer en üst seviyede değilse en üst seviyeye çıkarmayı deneyin. Belki daha fazla optimizasyon yapılırsa kodlarınız daha az yer kaplayabilir.
Alıntı yapılan: serhat1990 - 23 Temmuz 2012, 15:19:23
Lcd kullanmıyorım Hocam. Ama seri porttan veri gönderiyorum. Bu verilerin ne oldugunu belli eden metinler yer kaplıyor tahminimce.
Ayrıca matematiksel işlemler var. Bunlarda baya bir yer kaplıyor...
sanırım sisteminiz PC ile seri porttan haberleşiyor.öyle ise hesaplamaların bir kısmını PC ye yaptırabilirsiniz.ayrıca bilgilerin ne olduğunu belirtmek için metin kullanmanıza gerek yok.bilgileri belirli bir sıra ile gönderebilirsiniz veya her bilginin başına 1-2 karakter ekleyerek bilgilerin ne olduğunu tesbit edebilirsin.
Alıntı yapılan: yamak - 23 Temmuz 2012, 15:27:15
Hocam derleyiciniz kod optimizasyon seviyesini eğer en üst seviyede değilse en üst seviyeye çıkarmayı deneyin. Belki daha fazla optimizasyon yapılırsa kodlarınız daha az yer kaplayabilir.
En üst seviyede Hocam ... Yanıt için teşekkür ederim...
Alıntı yapılan: serdararikan - 23 Temmuz 2012, 15:31:22
sanırım sisteminiz PC ile seri porttan haberleşiyor.öyle ise hesaplamaların bir kısmını PC ye yaptırabilirsiniz.ayrıca bilgilerin ne olduğunu belirtmek için metin kullanmanıza gerek yok.bilgileri belirli bir sıra ile gönderebilirsiniz veya her bilginin başına 1-2 karakter ekleyerek bilgilerin ne olduğunu tesbit edebilirsin.
Şimdi o şekilde düzenliyorum Hocam. Umarım açılan yer bana ekleyeceğim işlemler için yeterli gelecektir.
PIC içinde floating point sayılar üzerinde işlem yapılıyorsa bunların fonksiyonları hafızada baya yer kaplıyor. Sadece bunları bilgisayara hesaplatmak bile ciddi yer tasarrufu sağlayacaktır.
Fonksiyonların mümkün olduğunca daha küçük parçalara ayrılmasının
tasarruf sağlayacağını okumuştum.
Yani uzun bir fonksiyonu iki-üç parça tasarlayabilirsen tasarruf
sağlayabileceksin diye biliyorum, tecrübe etmedim.
Alıntı yapılan: Tagli - 23 Temmuz 2012, 15:42:49
PIC içinde floating point sayılar üzerinde işlem yapılıyorsa bunların fonksiyonları hafızada baya yer kaplıyor. Sadece bunları bilgisayara hesaplatmak bile ciddi yer tasarrufu sağlayacaktır.
Hocam bu tip işlemler var fazlasıyla , mümkün olduğunca azaltmaya çalışıyorum bilgi için çok teşekkür ederim...
Alıntı yapılan: ArGeMaNiA - 23 Temmuz 2012, 15:51:19
Fonksiyonların mümkün olduğunca daha küçük parçalara ayrılmasının
tasarruf sağlayacağını okumuştum.
Yani uzun bir fonksiyonu iki-üç parça tasarlayabilirsen tasarruf
sağlayabileceksin diye biliyorum, tecrübe etmedim.
Öneriniz için teşekkür ederim Hocam. Fonksiyon çok fazla fakat pek fazla uzun değil. Yinede kontrol edecem teşekkürler...
Kullandığın PIC 16K program memory li 32 Banklı bir PIC, bende kullanıyorum aynısından. Hangi dil ile yazıyorsun? Bankları, Pageleri düzgün kullanıyormusun?
Nasıl anladın dolduğunu? MPLab programında View kısmının en altında Memory usage var ona bas bi screenshot yap gönder bakalım nasıl doldurmuşsun:)
Edit: Kusura bakma 16f1527 ile karıştırdım.Bunun hafızası küçükmüş gerçekten.
Hocam Hi-Tech dilinde yazıyorum...
Hafızası gerçekten küçük hocam . Doldu :) :)Dediğiniz yerden görüntülüyorum zaten...
Yazdığın fonksiyonlardan bir yada iki tanesini yayınlarsan alternatif yazım şekilleri oluşturulabilir belki.
Bazı rutinler asm yazılabilir.
Ö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...
}
}
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
Hocam seri_al fonksiyonu seri haberleşme dosyamda . RCREG içeriğini okuyup veriyor. Receiver interrupt flag gelince...
Önerilerinizi değerlendiriyorum.
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
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.
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...
İ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 ?
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...
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");
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 ?
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.
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.
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.
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: }
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.
İnceliyorum Hocam... ASM en iyi çözüm gibi duruyor...
Kodu asm'de yazmanı önermem. Günümüz gelişmiş C derleyicilerinin, deneyimli bir asm programcısı kadar iyi (hatta daha iyi) kod üretebildiği söylenir. Bence yapman gereken şey asm mantığı ile düşünüp C'de kod yazmak.
Anladım Hocam... Çok teşekkür ederim . Cevabınız için....
Alıntı yapılan: Tagli - 24 Temmuz 2012, 13:55:22
Kodu asm'de yazmanı önermem. Günümüz gelişmiş C derleyicilerinin, deneyimli bir asm programcısı kadar iyi (hatta daha iyi) kod üretebildiği söylenir. Bence yapman gereken şey asm mantığı ile düşünüp C'de kod yazmak.
Şehir efsanesi bunlar. Çünkü yapay zeka konusunda bilgisayarlar henüz çok bebek.
@gerbay
Teşekkürler Hocam. Hesaplamayı PC' de yaptırmak yer açısından büyük bir avantaj olacak gibi . İşlemsel fonksiyonları çıkarıp eklediğimde farkı görebiliyorum.
gerbay hocam, söylediklerinde haklısın ama performansın ön planda olmadığı uygulamalarda string gönderilmesi, arayüzde evrenselliği arttırıyor ve insanı iletişim protokolü düşünme derdinden kurtarıyor. Veriler ham data olarak gönderildiğinde elbette daha verimli ve hızlı giderler, ancak framing, paket formatı, hata kontrolü vs. gibi şeyleri kodlamak zaman kaybettirebilir. Kimin sözüydü hatırlamıyorum ama "text, en evrensel iletişim protokolüdür" gibi bir söz görmüştüm ve kesinlikle katılıyorum. Hep daha hızlısını istiyoruz ama acaba gerçekten de o kadar hızlı olmasına ihtiyacımız var mı bunu da düşünmek lazım uygulamada.