[ rsinisa @ 14.06.2009. 11:36 ] @
Ne znam koliko ljudi koristi PicBasic Pro kompajler, ali sam često vidjao početnike kako pišu programe koji su prilično neoptimizovani pa mislim da bi ova tema mogla da bude od koristi.
Ja spadam u ljude koji su počeli sa ZX-81 i SPECTRUM-om, pa sam počeo da radim uredjaje sa Z80 procesorom u vreme kada nije mogao lako da se nabavi EPROM većeg kapaciteta, te mi je optimizacija "u krvi" i jednostavno mi bode oči kada vidim loše pisan program.
Namera viših programskih jezika je da omogući brži razvoj aplikacije i samim tim program zna da bude neoptimizovan i da zauzima više memorije ako se ne pazi na neke stvari. Neki će reći da danas, sa relativno niskim cenama PIC kontrolera, optimizacija i nije potrebna i da samo može da oduzme vreme i ja sa tim mogu donekle da se složim. Medjutim, šta ako imate pri ruci kontroler sa manje memorije i zafali vam par memorijskih lokacija. Ili pravite uredjaj koji planirate da pravite u "većem tiražu" i ušteda od par desetina dinara na veću količinu može da Vam obezbedi nižu cenu na tržištu i time veću konkurentnost. Optimizacija može da pomogne i da kasnije, ako treba da dodate nove delove programa, to uradite jednostavnije i brže. Ne bih da se ova tema pretvori u raspravu o tome da li je optimizacija potrebna ili ne (ko hoće neka otvori novu temu), već da se priča o optimizaciji pa kome je interesantna neka čita i piše na tu temu. Optimizacija podrazumeva i pravilan stil pisanja program pa možemo i o tome da pričamo ovde. Mada, da ne bude zabune, ni ja nemam svaki put vremena da optimizujem program - ako proradi i hitno je, ne pipam ništa više.
Iako je u ovoj temi reč o PBP-u, daću primere koji koriste i neke asemblerske instrukcije jer mislim da upotreba par ASM intrukcija može znanto da uštedi memoriju, a njihova upotreba ne zahteva kompletno poznavanje asemblera.
Krenuću ja sa par primera, a ko hoće neka se priključi sa svojim savetima ili pitanjima.

Pozdrav.
Sinisha


[Ovu poruku je menjao rsinisa dana 14.06.2009. u 12:52 GMT+1]
[ rsinisa @ 14.06.2009. 11:37 ] @
Upotreba pauze
--------------
Često u programima ima potrebe za pravljenjem pauza pa da razmotrimo dve naredbe: PAUSE i PAUSEUS. Prva pravi pauzu u milisekundama, a druga u mikrosekundama, prva troši 43 worda programske memorije, a druga čak 18 manje - svega 25 worda. Znači, ako vam u programu treba pauza koja je manja od 65,535 ms upotrebite naredbu PAUSEUS.
Dobar deo instrukcija PBP-a su u stvari asemblerski potprogrami pa ih kompajler samo jednom smesti u memoriju i posle ih poziva prenosom parametara. U konkretnom slučaju svaki sledeći poziv naredbe PAUSEUS (takodje i PAUSE) troši svega 4 worda, tako da ako vam treba pauza do 327,68 ms upotrebom pet uzastopnih poziva PAUSEUS uštedećete 2 worda više nego da upotrebite jednom naredbu PAUSE 327. Medjutim, ako vam na više mesta u programu treba ovakva pauza, potrebno je ipak experimentalno utvrditi koju instrukciju upotrebiti, sve zavisi od broja pauza koje imate.

Pozdrav.
Sinisha


[Ovu poruku je menjao rsinisa dana 14.06.2009. u 20:57 GMT+1]
[ rsinisa @ 14.06.2009. 11:41 ] @
Aritmetika
----------
Jedna od prednosti viših programskih jezika je što složeni matematički izrazi mogu da se pišu u jednoj liniji programa, ali sa aspekta utroška memorije takav stil pisanja nije ekonomičan.
Pogledajmo primer koji stiže uz PBP za rad sa DS1820. U njemu su dva složena matematička izraza koji zauzimaju 137 worda.

' Calculate temperature in degrees C to 2 decimal places (not valid for negative temperature)
temperature = (((temperature >> 1) * 100) - 25) + (((count_per_c - count_remain) * 100) / count_per_c)

' Calculate temperature in degrees F to 2 decimal places (not valid for negative temperature)
temperature = (temperature */ 461) + 3200


Ako prvi izraz razložimo na nekoliko prostih:
temperature=temperature >> 1
temperature=temperature * 100
temperature=temperature - 25

count_remain=count_per_c - count_remain
count_remain=count_remain * 100
count_remain=count_remain / count_per_c

imaćemo uštedu od 19 worda.

Ako isto uradimo i sa drugim izrazom:
temperature = temperature */ 461
temperature = temperature + 3200
uštedećemo ukupno, za oba izraza, 21 word.

Ovde može da se uštedi još koji bajt ako se šiftovanje u prvom izrazu:
temperature=temperature >> 1
zameni sa asemblerskim instrukcijama, ali o tome u sledećoj poruci.
[ Robinzon Kruso @ 14.06.2009. 12:21 ] @
ili ti koriscenje komandi:

PORTB=%00000011 ili PORTB=3

umesto:

HIGH PORTB.0
HIGH PORTB.1

pretpostavljam da je tako posto nisam bas upucen u odnos PBP komandi i reci u memoriji...

[ rsinisa @ 14.06.2009. 16:00 ] @
Ups, izgleda da sam duplirao prvu poruku. Izvinjenje moderatoru koji je morao da je briše. :).

@ Robinzon Kruso
Jeste, u pravu si. Pomenuću HIGH i LOW naredbe, samo da prvo obradim šiftovanje.

Treba napomenuti da ušteda može da bude i drugačija jer neke naredbe koriste deo druge naredbe ili iste potprograme pa ušteda može da bude manja. Konkretno, naredba PAUSE je u stvari proširenje naredbe PAUSEUS. Takodje, cifre koje navodim kao ušteda odnose se na slučaj kada je upotrebljeno DEFINE no_crlwdt jer bez nje se stvari malo razlikuju, najpre u ubacivanju asemblerske naredbe CRLWDT (koju ubacuje kompajler na pogodna mesta).
[ rsinisa @ 14.06.2009. 17:08 ] @
Šiftovanje
----------
Šiftovanje je pomeranje celog sadržaja registra na nivou bitova u levo ili u desno. Bit koji je bio na kraju "izlazi" iz registra i zauvek se gubi, a na njegovo mesto sa druge strane ulazi nula. Naredba je u stvari matematički operator "<<" za šiftovanje ulevo i ">>" za šiftovanje udesno. Na primer naredba:

tempb=tempb << 1

koja šiftuje sadržaj registra tempb za jedno mesto ulevo troši 15 worda programske memorije za promenljivu tipa bajt, odn. 16 za word. Ona može da se zameni sa samo dve asemblerske instrukcije za bajt i tri za word promenljivu. Asembler, doduše, nema naredbu za šiftovanje već za rotiranje kroz CARRY flag, pa je potrebno prvo resetovati taj fleg i onda uraditi rotiranje:

ASM
bcf status, c
rlf _tempb, 1
ENDASM

za promenljivu tipa bajt. Za word treba dodati pre ENDASM još naredbu:

rlf _tempb + 1, 1

Ovo sve važi kada se šiftuje za jedno mesto. Ono što je zanimljivo i prilično neobično je to da su pisci kompajlera izgleda ovde napravili grešku (ovi primeri su radjeni u PBP-u 2.47). Naime, kada se radi šiftovanje za jedno mesto u program se ubaci asemblerski potprogram za ovu operaciju, ali se uopšte ne poziva već se na mesto naredbe stave upravo ove koje sam naveo. Kada se vrši šiftovanje za više od jednog mesta, onda se pripreme parametri pa se pozove potprogram. Verovatno nepažnja autora kompajlera.
I za ovu optimizaciju važi da treba da preračunate ili eksperimentalno utvrdite da li se isplati ako imate više upotreba te naredbe, ali ovde treba obratiti pažnju na još jednu stvar. Promenljive koje se koriste u programima se nalaze u nekoliko banaka, zavisno od mikrokontrolera; PBP vodi računa o tome i sam postavlja bitove za odabir banke onako kako je potrebno. Medjutim, kada upotrebite asemblerske instrukcije tu PBP više nije u stanju da prati banke pa može da se desi da program ne radi kako treba. Obzirom da PBP najčešće redom popunjava banku (sem ako mu se drugačije ne kaže) vrlo verovatno da će sve biti u redu ako u programu nemate previše definisanih promenljivih, ali ipak treba biti oprezan.

[Ovu poruku je menjao rsinisa dana 14.06.2009. u 21:01 GMT+1]
[ korak @ 14.06.2009. 18:36 ] @
Najzad jedna ozbilja tema, bez obzira sto je u pitanju BASIC i PIC, ona je opsta.

Ovako nesto moze da pise samo znalac, cestitam i na naporu da se podigne nivo ovog podforuma.

Slazem se sa tobom, i ja se radije opredeljujem za kraci program u zamenu za eventualno duze izvrsavanje.

Pozdrav.
[ rsinisa @ 14.06.2009. 20:15 ] @
Drago mi je da neko misli pozitivno o ovoj temi i hvala na podršci.
Iako BASIC možda deluje neozbiljno ja ga rado koristim jer u njemu pišem programe skoro kao da su pisani u asmebleru što odgovara mom stilu pisanja programa - dobijem prilično efikasan kod za kratko vreme.

Pozdrav.
Sinisha
[ rsinisa @ 14.06.2009. 21:35 ] @
Pre nego što nastavim treba da dodam nešto vezano za upotrebu asemblerskih naredbi u PBP programu.
Prva stvar je da ASM (kao i naredba @) postave stranicu za registre na nulu, i ako ste menjali stranicu u asmeblerskom delu, pre povratka u PBP morate opet da je vratite na nulu.
Druga stvar je vezana za naziv promenljive kada se koristi u asemblerskom delu programa; ispred naziva promenljive morate da stavite donju crtu (_) kako bi asembler znao da radi sa njom; u protivnom dobićete poruku o grešci.

Šiftovanje umesto množenja i deljenja
-------------------------------------
Kada se pogleda vrednost promenljive koja je šiftovana ulevo, primećuje se da je ona duplo veća od početne. Za promenljive šiftovane udesno nova vrednost je upola manja od početne. Prema tome, šiftovanje može da se koristi za množenje i deljenje ako je množitelj odn. delitelj stepen broja 2 (2, 4, 8, 16, 32, ...). Pogledajmo naredbu:

tempb=tempb * 8

koja, kada je u pitanju promenljiva bajt tipa, troši 35 worda i koja se u program smešta u obliku potprograma što znači da svaki sledeći poziv troši manje memorije jer prenosi samo parametre i poziva je. Ista stvar može da se dobije šiftovanjem ulevo 3 puta:

tempb=tempb << 3

čijom upotrebom štedimo 16 worda. Medjutim, pošto smo naučili da šiftovanje radimo u asmebleru možemo da napišemo sledeće:

ASM
bcf status, c
rlf _tempb, 1
rlf _tempb, 1
rlf _tempb, 1
ENDASM

i utrošimo samo 4 worda - ušteda od čak 31 word u odnosu na množenje.

Činjenica je da nije moguće ovo uvek korisiti, ali čak i ako množitelj nije stepen broja 2 moguće je upotrebiti šiftovanje ako taj broj može da se napravi uz relativno malo kombinovanja brojeva 2, 4, 8, 16, 32 ...
Recimo da treba da pomonožimo broj sa 10. Vidimo da 10 može da se rastavi na 8 + 2, a to su stepeni broja 2. Znači umesto:

tempb=tempb * 10

možemo upotrebom šiftovanja da napišemo:

ASM
bcf status, c ; resetuj CARRY flag
rlf _tempb, 1 ; pomnoži tempb sa 2
movf _tempb, w ; sačuvaj taj broj u W registru
rlf _tempb, 1 ; pomnoži tempb sa 2 (ukupno 4)
rlf _tempb, 1 ; pomnoži tempb sa 2 (ukupno 8)
addwf _tempb, 1 ; i dodaj još 2*tempb (ukupno 10)
ENDASM

i dobijemo rutinu za množenje sa 10 koja troši 6 worda programske memorije. Slično je i sa brojem 100, on može da se razloži na 64 + 32 + 4. Ako imate dosta množenja sa različitim brojevima, ova tehnika neće moći da Vam uštedi memoriju.


[Ovu poruku je menjao rsinisa dana 14.06.2009. u 23:07 GMT+1]

[Ovu poruku je menjao rsinisa dana 14.06.2009. u 23:09 GMT+1]
[ korak @ 15.06.2009. 11:11 ] @
Izgleda kao da samo ja pratim ono sto pises. Interesantno mi je jer sam nekada radio sa BASIC-om na kucnim racunarima, a PIC poznajem ali se nisam usudio da radim sa njim.

Cudi me da Mikroelektronika nije vodila racuna o strukturi asm..end za pisanje asemblerskih iskaza. Pravilo je da kompajler vodi racuna da stek pointer i ukazatelj stranica bude na istoj vrednosti pri ulasku i pri izlasku iz asm..end strukture. To kompajler moze lako da proveri i da prijavi gresku ako je tu nesto menjano.

I ja cesto vodim racuna da koristim siftanje umesto mnozenja kada ono nije potrebno. Za mnozenje sa 10 imam naviku da to radim kao (4+1)*2 sto se svodi na isto. Da li znas za pravilo kod mnozenja oznacenih brojeva:

1. ako mnozis N bajtova sa N bajtova i rezultat je N bajtova onda dobijas tacan rezultat bez obzira na znak.

2. ako mnozis N bajtova sa N bajtova i rezultat je 2*N bajtova onda ako su A i B vrednosti koje mnozis a rezultat Ch:Cl onda:

A*B -> Ch:Cl
if B < 0 => Ch <- Ch-A
if A < 0 => Ch <- Ch-B

Interesuje me kako to radi BASIC kompajler kojeg vidim da analiziras.

Pozdrav.
[ veselinovic @ 15.06.2009. 19:59 ] @
Citat:
korak: Izgleda kao da samo ja pratim ono sto pises. Interesantno mi je jer sam nekada radio sa BASIC-om na kucnim racunarima, a PIC poznajem ali se nisam usudio da radim sa njim.



Ima nas jos koji pratimo.
Sinisa, svaka cast za temu i za zelju da u ovom vremenu teraherca i ultramega bajtova pricu vratis na pocetak razvoja kad se vagalo u milibajte.
Mozda se cini da je sada uz dzaba hardver besmisleno pricati ovakve price, ali to razmisljanje lici na sto uopste neko pise knjige kad je sve vec napisano.
Meni je strasno zao sto me zivot ( hljeb) otjerao na stranu energetike umjesto moje ljubavi elektronike i kontrolera, ali zaista vrijedi tvrdnja
mA==mEvri
kA==kEvri
[ rsinisa @ 15.06.2009. 20:45 ] @
Citat:
korak: Izgleda kao da samo ja pratim ono sto pises.

Eto, dok sam ja našao vremena da odgovorim javio se jedan posmatrač ;). Pretpostavljam da ljudi prate, ali ih ne zanima jer, ili ne poznaju suštinu i ne znaju koliko to ponekad može da znači, ili je ovo što Jovan kaže - koga danas briga za par desetina bajtova uštede uz ovakve cene. Medjutim, ja sam tako naučio i to je moj stil pisanja, a sreća pa ovde na ES-u čovek može da kaže šta ga tišti, dokle god je vezano za temu :).

Citat:
korak:Interesantno mi je jer sam nekada radio sa BASIC-om na kucnim racunarima, a PIC poznajem ali se nisam usudio da radim sa njim.

Razlog?

Citat:
korak:Cudi me da Mikroelektronika nije vodila racuna o strukturi asm..end za pisanje asemblerskih iskaza.

Probao sam pre par godina ME BASIC kompajler, ali za manje od pola sata sam odustao - našao sam mu 3 velike zamerke (ne sećam se više dve, negde sam to opisao tada, sećam se samo da nije mogao da radi sa promenljivom tipa bit) i još par manjih, ali možda su do sada popravili sve to. Svejedno, mom stilu pisanja više odgovara PBP i, čini mi se, da može da da prilično optimalan kod, što je moj prevashodni cilj.

Citat:
korak:Da li znas za pravilo kod mnozenja oznacenih brojeva:

Trenutno se ne sećam da sam ga znao, ali ako se to učilo u klasičnoj školi onda sam znao pa zaboravio. :)

Citat:
korak:Interesuje me kako to radi BASIC kompajler kojeg vidim da analiziras.

PBP ne radi sa označenim brojevima, a pravo da ti kažem, do sada nisam imao potrebe za tim. Analizu sam počeo pre par godina kada sam dobio ideju da napravim svoj BASIC kompajler (izmenili smo par PP na tu temu) jer imam utisak da bih mogao da napravim bolji, ali eto ... do danas ništa, jednostavno nemam vremena.

Citat:
veselinovic:Meni je strasno zao sto me zivot ( hljeb) otjerao na stranu energetike umjesto moje ljubavi elektronike i kontrolera, ali zaista vrijedi tvrdnja
mA==mEvri
kA==kEvri

Šta da kažem sem da se slažem sa tobom, pogotovo sa matematičkim formulama :), tj. jednačinama.

[Ovu poruku je menjao rsinisa dana 15.06.2009. u 22:15 GMT+1]
[ zofr @ 15.06.2009. 22:08 ] @
Da se oglasim, i ja pratim ovu interesantnu temu.

Misliti da gigaherci i mega bajtovi resavaju sve, je podilazenje losem ukusu kada je programiranje u pitaju. Koloko god da imate megabajta docicete nekada u situaciju da vam je to malo, isto vazi i za gigaherce. A kada je tema 8-bitni mikrokontroler to je posebno vazno. Neka neko objasni zasto svi vrhunski kompajleri imaju opciju za optimizaciju po brzini ili po duzini koda. Verovatno nemaju pojna tvorci tih kompajlera.

Flash (posle RAM-a) zauzima najveci deo povrsine mikrokontrolera, a to na ustrb integrisanog hardvera. Do pre 3-4 godine gigaherci PC-a su se povecavali geometrijskom progresijom, sada se stagnira na 2-3GHz. Kako dalje kada za 1ns (1GHz) svetlost predje 30cm.

Usteda u duzini programa od 5% na 60KB je 3KB, nije malo, a na 1MB je 50KB sto tek nije za bacanje.

Ti silni gigaherci i megaherci su samo razmazili programere pa pisu los softver ali sa raznobojnim fascinantnim ekranima. Ko se seca DOS programa ili cak CP/M-a za Z80 i 128KB memorije na cemu se vodilo poslovanje banaka i preduzeca. Tada je razvoj softvera bio skup, ali je softver bio pouzdan.

Ko se razume, zna koliko je tesko dokazivanje ispravnosti programa koji ima izvrsni kod od nekoliko desetina KB, a ako su u pitanju megabajti, od tog dokazivanja se odustaje, i ide se na testiranje koje nikada nije kompletno. Svi veliki programi su osudjeni da imaju bagove.

Ovo je beskonacna tema, pa ovde prekidam.

Pozdrav, samo napred.
[ rsinisa @ 15.06.2009. 23:40 ] @
Postavljanje stanja na izlazne pinove
-------------------------------------
Na prvi pogled PBP ima veoma zgodne naredbe za postavljanje željenog stanja na neki pin, HIGH i LOW. Medjutim, njihovo korišćenje i nije baš najsrećniji izbor, a evo i zašto: da bi se odredilo da li je neki pin izlazni ili ulazni (tzv. odredjivanje smera) potrebno je "podesiti" odgovarajući TRIS registar (npr. TRISA). Najčešće se u jednom uredjaju smer jednog pina ne menja tako da je to dovoljno uraditi samo jednom, u delu programa koji se naziva inicijalizacija. Medjutim, naredbe HIGH i LOW svaki put postavljaju smer pina i time nepotrebno troše programsku memoriju, tačnije svaka njihova upotreba utroši 4 worda jer se te naredbe ne prevode u potprogram. Umesto toga najbolje je na početku postaviti potrebna stanja u TRIS registre, 0 za pin koji treba da bude izlazni i 1 za ulazni, a zatim, kada je potrebno postaviti stanje na izlazni pin jednostavno dodeliti tom bitu željeno stanje:

inicijalizacija:
trisb=%11111010
....

glavni:
....
portb.0=1

Na ovaj način se štedi po 3 worda za svako postavljanje stanja sem u slučaju kada je pre te naredbe bila izabrana strana u kojoj nije dostupan izlazni registar. Medjutim, u većem delu programa često je odabrana nulta strana tako da bi ušteda trebalo da bude očigledna.
Ako je potrebno odjednom postaviti stanja za više pinova može da se upotrebi direktno dodeljivanje, kao što je naveo Robinzon Kruso:

portb=%00000101

medjutim, ovo je zgodno samo ako želite da postavite stanja za ceo port odjednom, ne i za pojedinačne pinove.
[ rsinisa @ 15.06.2009. 23:43 ] @
Postavljanje stanja na izlazne pinove (2)
--------------------------------------
Iako nema direktne veze sa optimizacijom, ovde treba navesti još jednu stvar koja može da napravi problem u realnoj aplikaciji (kao što se meni desilo) - ako se vrše dva uzastopna postavljanja pinova jednog porta, može da dodje do nepravilnog postavljanja jer se svaki pristup portovima vrši u 3 koraka: čitaj-izmeni-upiši što konkretno znači da se sadržaj pinova (pinova, a ne leč registra) prvo pročita u interni registar, zatim se izmeni sadržaj tog registra i na kraju se njegovo stanje prosledi na port. Ako se na jednom od pinova nalazi neko kapacitivno opterećenje ili je pin strujno preopterećen, velike su šanse da će druga izmena porta da poništi prvu. Da bi bilo jasnije evo i konkretnog primera: zamislimo da je na RB0 priključen kapacitivni potrošač kome je potrebno neko vreme da se napuni i napon stabilizuje, a na RB1 neki drugi potrošač i da imamo sledeći program:

portb=%00000000
....
....
portb.0=1
portb.1=1

Prva naredba, očigledno, postavlja sve pinove na logičku nulu. Kod sledeće naredbe biće pročitano stanje sa pinova u interni registar, setovan nulti bit, i to novo stanje vraćeno na port. Kod treće naredbe takodje će prvo da bude pročitano stanje sa pinova B porta, i pošto je na pin 0 priključeno kapacitivno opterećenje, stanje na njemu će da bude i dalje logička nula (jer se kondenzator nije napunio) pa će umesto 00000001 biti pročitano 00000000, zatim će biti setovan prvi bit i takvo stanje vraćeno na port pa će na kraju umesto 00000011 na pinovima biti 00000010. Ovo može da se prevazidje ubacivanjem nekih drugih naredbi izmedju ove dve, ili običnih asmeblerskih NOP instrukcija, jedne ili više:

portb.0=1
@ nop
portb.1=1

Ovaj problem je rešen kod nekih familija PIC-eva tako što je uvedena naredba koja čita stanja iz leča umesto sa pinova.
[ _str_ @ 15.06.2009. 23:51 ] @
Redovno citam bla lba bla... Nekako se osecam prozvanim posle jednog komentara "temp=temp<<1 , a ja temp=temp*2". Malo sam ishitreno reagovao jer ne koristim pic a pogotovu pbp, pa mi je sintaksa "<<" licila na C.
BASIC je tek nesto malo jaci od asemblera i nije mi jasno zasto je cesto zasut drvljem i kamenjem? Ja sam ga koristio (isto tako) od vremena zx-a i vec tada se ukazala potreba za optimizacijom, cesta upotreba IF THEN petlje je dosta usporavala komp (isto tako se na asm. z80 koristila "and" komanda za brisanje registra jer se brze izvrsavala).
Sa ove tacke gledista bi mogao reci da postoji mikro i makro optimizacija. Mikro optimizacija bi bila ovo o cemu tavaris rsinisa pise, a makro optimizacija bi se odnosila na celokupnu strukturu programa koja je isto toliko bitan sto se tice izvrsenja ili duzine napisanog programa. Ja se cesce srecem sa problem manjka I/O pinova nego manjka flash-a ili brzine programa. AVRovatno mi je takav horoskop jer na programiranje odlazi 25% posla a ostalo je sitni, teski i bas teski hardver.
Pozdrav i samo tako nastavite...
[ rsinisa @ 16.06.2009. 00:03 ] @
Citat:
_str_:Nekako se osecam prozvanim posle jednog komentara "temp=temp<<1 , a ja temp=temp*2". Malo sam ishitreno reagovao jer ne koristim pic a pogotovu pbp, pa mi je sintaksa "<<" licila na C.

Ideja za ovu temu postoji u meni odavno, ali moglo bi da se kaže da si malo ubrzao njen izlazak u javnost. Medjutim, ne treba da se osećaš prozvanim - nije mi bila namera ni da prozivam ni da kritikujem nikoga; pa i meni se desi da napišem neku glupost koju možda i ne vidim. Ja sam ti u stvari zahvalan jer si ubrzao pokretanje ove teme i zaista nema potrebe da se osećaš negativno zbog toga. Da nisi ti, pre ili kasnije bio bi to neko drugi sa, možda, nekim drugim primerom. Znači, cilj mi nije da nekoga ponižavam već da pomognem onima koji rade u PBP-u koji su zainteresovani da dobiju kraći program koji je najčešće i brži.

Citat:
_str_:BASIC je tek nesto malo jaci od asemblera i nije mi jasno zasto je cesto zasut drvljem i kamenjem?

Da, baš zato mi PBP i "leži".

Citat:
_str_:Sa ove tacke gledista bi mogao reci da postoji mikro i makro optimizacija. Mikro optimizacija bi bila ovo o cemu tavaris rsinisa pise, a makro optimizacija bi se odnosila na celokupnu strukturu programa koja je isto toliko bitan sto se tice izvrsenja ili duzine napisanog programa.

Slažem se, i ako bude zainteresovanih možda nešto bude napisano i na temu pravilnog pisanja programa.

Pozdrav.
Sinisha
[ korak @ 16.06.2009. 10:24 ] @
Sta je to pravilno napisan program? Da li je to program koji je kompajler preveo bez prijavljivanja bilo koje greske?, Da li je to program koji radi ono sto je programer zamislio?

Ja mislim da je u pitanju nesto drugo. Na fakultetu se uce pravila po kojima treba pisati program. Ta pravila nisu izmisljena tek tako, vec imaju za silj da napisani izvorni kod jasno izrazava ideju programera, da je stoga on razumljiv i lako citljiv. Takvom programu skoro da nisu potrebni komentari. No to sto studenti uce je samo vrh ledenog brega i svako kasnije treba da ta pravila primenjuje shodno racunaru koji programira. Mikrokontroleri su u tom smislu specificni. Da ne nabrajam: ogranicen flash, RAM i broj I/O pinova traze i dosetke od programera, a to je upravo u suprotnosti sa pomenutim pravilima. Tehnike programiranja se razlikuju od MCU-a do MCU-a. Ono sto daje dobar rezultat kod jednog, ne mora da da isti rezultat i kod drugog.

Sinisa, kako tvoj BASIC prevodi petlje (ponavljajuce strukture) for, while..do i repeat..until tu ima mnogo mesta za optimizaciju, ako vec nije izvrsena kako valja.

Pozdrav.
[ rsinisa @ 16.06.2009. 19:19 ] @
Slažem se sa tobom da je teško reći šta je pravilno napisan program. Možda bi to bio program koji radi ono što treba na maksimalno efikasan način, što je opet, samo po sebi, veoma nedefinisano. Slažem se da je programiranje veoma kreativan proces i da ga ne treba šablonizovati, ali ipak mislim da postoje neka osnovna pravila koja treba ispoštovati od kojih će da zavisi kojim putem će programer da krene. Npr. po meni, pre početka pisanja treba što bolje analizirati šta će sve tu da se dešava i na osnovu toga odrediti šta ide u inicijalizaciju, da li koristiti interapte ili ne, gledati da interapt bude što kraći, zatim da li je proces takav da je bolje upotrebiti stejt mašinu ili ne, da li neki deo programa koji se izvršava više puta staviti u potprogram ili ne (zavisno od potrebne brzine izvršavanja tog dela) i sl. Na to sam mislio kada sam pomenuo pravilno pisanje.

Što se tiče petlji, da prvo obradim FOR.
Za program gde je i bajt tip:

Code:
    for i=0 to 3
      ....
    next

kompajler prvi sledeći kod:

Code:
    CLRF    i
L1
    MOVLW   0x04
    SUBWF   i, W
    BTFSC   STATUS, C
    GOTO    for_kraj
      ....
    INCFSZ  i, f
    GOTO    L1
kraj_for


koji je, koliko vidim, saasvim korektan i u principu nemam zamerki, mada imam utisak da je naredba INCFSZ stavljena kao neka vrsta "osigurača". Možda logika autora kompajlera u ovom slučaju izlazi na videlo kada se u FOR petlji za promenljivu tipa bajt stavi vrednost veća od 255. Umesto da kompajler javi grešku i onemogući kompajliranje, on to bez problema prevede, mada malo drugačije, gde navedena naredba upravo deluje kao zaštita da se program ne zaglavi u mrtvoj petlji. Program:

Code:
    for i=254 to 257
      ....
    next


PBP će da prevede u:

Code:
    MOVLW   0xE6
    MOVWF   i
L1
      ....
    INCFSZ  i, f
    GOTO    L1
for_kraj



Ovakva petlja će uvek da se izvrši bar jednom, ili više puta i to sve dok promenljiva "i" ne predje sa 255 na 0. Zaista neobično i prilično bezvezno.
Toliko za danas, ostatak sutra, nemam sad vremena za ostale petlje.

Pozdrav.
Sinisha
[ lm741 @ 01.01.2010. 01:31 ] @
pozdrav rsinisa
veoma korisno, bilo bi dobro ako sledi nastavak
[ rsinisa @ 02.01.2010. 08:44 ] @
Znaš kako to ide - naidje period kada ima manje posla pa se nadje vremena i za ovakvu pisaniju, a onda naidje period kada slobodnog vremena nema, pa čak ako i naidje, zaboravi se šta je započeto ... Na žalost, sad sam u periodu kada imam dosta obaveza raznih vrsta tako da za sada ništa od nastavka, ali trudiću se da nekom prilikom napišem još po nešto na tu temu.

Pozdrav.
Sinisha
[ lm741 @ 02.01.2010. 10:27 ] @
potpuno te razumem,..ja sam trenutno u toj situaciji da imam vremena pa koristim priliku da nešto naučim jer znam da će naići period 2-3 meseca nekad i više, da neću imati vremena.
u svakom slučaju hvala ti za raniji a i budući trud,..
pozdrav,..

[ rsinisa @ 08.03.2010. 01:54 ] @
DEFINE no_clrwdt, greška ili ne?
------------------------------
PIC kontroleri (kao i mnogi drugi) imaju u sebi tzv. watchdog, tj. mehanizam za izlazak iz eventualne mrtve petlje koji radi na principu tajmera i kojeg treba povremeno resetovati. Da bi se to uradilo potrebno je u konfiguracionoj reči uključiti watchdog tajmer (u daljem tekstu WDT) i u programu ga povremeno resetovati. Upotreba tog mehanizma nije obavezna, pa se i program razlikuje u zavisnosti da li nam taj mehanizam treba ili ne.
PBP nema direktnu naredbu koja resetuje WDT u slučaju da ga koristimo što u prvom momentu može da deluje neverovatno, ali to i ne čudi jer je cilj višeg programskog jezika da korisnika maksimalno oslobodi razmišljanja o sporednim stvarima, a i odredjivanje mesta gde treba staviti naredbu za njegovo resetovanje (a da nema preterivanja) zahteva malo iskustva. Medjutim, on ima dve DEFINE pseudo-naredbe koje oslobadjaju programera razmišljanja o WDT-u; programeru samo ostaje da odluči hoće li ili neće da ga koristi i da podesi konfiguracionu reč u skladu sa tim. To su naredbe DEFINE no_clrwdt i DEFINE clrwdt; prva kaže kompajleru da se WDT ne koristi, a druga da se koristi. Prva ne predstavlja problem, ali to kako se ponaša druga može da se svrsta u, po meni, grešku tvoraca PBP-a koja ni do dan-danas u najnovijoj verziji nije ispravljena. No, možda oni ne smatraju da je to greška i zato ostavljaju tako u novim verzijama. Evo o čemu se radi:
Dobar deo PBP naredbi su u stvari kompletni potprogrami od kojih su neki vremenski zavisni, tj. jako je bitno trajanje tih potprograma kako bi se izvršavali za tačno odredjeno vreme. Neki od tih potprograma mogu da se izvršavaju jako dugo (npr naredba PAUSE) pa je moguće da, u slučaju kada se koristi WDT, njihovo trajanje bude duže od WDT perioda pa će doći do WDT reseta i program neće da radi onako kako očekujemo. Zato PBP u takvim potprogramima ima makro koji na osnovu DEFINE naredbe na odgovarajuće mesto stavlja ASM naredbe "NOP" ili "CLRWDT" u zavisnosti od upotrebljene DEFINE naredbe. I to za sada sve izgleda u redu. Znači, kada se ne koristi WDT i upotrebi se DEFINE no_clrwdt na svim kritičnim mestima biće umetnutna ASM naredba "NOP".
Medjutim, kada se koristi WDT i upotrebi DEFINE clrwdt, pored ASM naredbi "CRLWDT" u tim potprogramima, PBP postavlja tu naredbu i kroz program na mesta koja, po njegovoj logici, mogu da budu kritična. Problem je što to i nisu uvek kritična mesta pa program ume da bude znanto duži i to čak preko 100 worda na 1 kword prog. memorije. Svaki programer koji drži do sebe će da isključi tu PBP-ovu logiku tako što će DEFINE clrwdt da zameni za no_clrwdt i da sam na pogodna mesta ubaci ASM naredbu "CLRWDT". Medjutim tu dolazi do problema zbog onog makroa koji će u svim, pa i onim kritičnim, potprogramima "CLRWDT" da zameni sa "NOP" i eto problema kod petlji koje se dugo izvršavaju (npr. PAUSE 1000).
Meni je ovo zadalo dosta muka jednom prilikom pa sam rešio da ispitam gde je problem (tada to, naravno, nisam znao) i gornji tekst je rezultat tog ispitivanja. Pošto mi je sve to delovalo nelogično, tj. više kao greška tvoraca PBP-a, rešio sam da napravim novu DEFINE naredbu i prepravim sve kritične PBP naredbe tako da mogu da izbegnem logiku PBP-a koja neumoljivo troši prog. memoriju, a da opet u vremenski kritičnim PBP naredbama ostanu "CLRWDT" instrukcije. I tako sam pre 4 godine izmenio "DEFINE no_clrwdt", dodao novu "DEFINE no_clrwdt_atall" i izmenio sve relevatne PBP naredbe u skladu sa tim.
Nova "DEFINE no_clrwdt_atall" naredba se sada ponaša kao "fabrička" no_clrwdt i upotrebljava se u slučaju kada se ne koristi WDT, a "DEFINE no_clrwdt" je izmenjena tako da PBP u kritičnim PBP naredbama ostavlja "CLRWDT" instrukciju, a da ne ubacuje u ostatak programa tu naredbu kako bi se dobio kraći program. Naredba "DEFINE clrwdt" radi i dalje kao i pre, tj. preterano troši programsku memoriju :)
Ako bude zainteresovanih, omogućiću im da dodju do izmenjenog PBP-a (zahtevi isključivo na PP ili email).

Pozdrav.
Sinisha

[ rsinisa @ 08.03.2010. 02:08 ] @
Prethodni post je malo duži pa ću u ovom da dam još neke informacije.
Ovu izmenu sam uradio za PBP 2.46 i to samo za 14-bitno jezgro jer mi za druga nije bilo potrebno. Pošto mi je večeras zatrebalo da pišem program za 16F886, morao sam da predjem na drugi PBP jer ga 2.46 ne podržava pa sam uzeo 2.60 i u njemu napravio gore navedene izmene. Medjutim, kada sam kompajlirao ranije napisan program za 16F627 (dužine tačno 1024 worda) video sam da 2.60 pravi duži kod za čak 34 worda! Neobično da nova verzija to radi pa ću da ispitam nekom prilikom o čemu se radi, a za sada prelazim na verziju 2.47 koja podržava F886 (i pravi kod iste dužine kao 2.46) tako da će sutra uveče postojati izmene za 3 verzije PBP-a: 2.46, 2.47 i 2.60. Ko bude zainteresovan neka naglasi koja verzija ga zanima.
Još jednom da napomenem da su izmene za sada napravljene samo za PIC-eve sa 14-bitnim jezgrom.

Naredbe koje su izmenjene (za druge nema potrebe) su:
count
debugin
freqout (samo u verziji 2.60)
hserin
pot
pulsout
serin2
serout2
pauseus
i jedan sistemski makro

Pozdrav.
Sinisha
[ yt1nvs @ 09.03.2010. 22:43 ] @
Znaci li to da ovaj PBP 2.60 nije bas pod vinklu!
Meni je cak i 2.50 pravio probleme pri ispisu na LCD doduse neki krekovani.

primer:

lcdout $fe,1,"PROBA"
u 2.45 je OK

lcdout $fe,1,"ROBA"
u 2.50 hvali prvi karakter
[ rsinisa @ 10.03.2010. 09:55 ] @
Ne znam, nisam ga probao sem tog kompajliranja gotovog programa. Za sada ostajem na 2.47, a kad nadjem vremena pogledaću šta se dešava sa 2.60.

Pozdrav.
Sinisha