przepisanie funkcji w C na Asembler

Dec 12, 2005 16 Replies

Witam. Zwracam sie do Was z moim problemem. Realizuje urzadzenie, ktorego mikrokontroler ma przepisywac stany pjawiajace sie na pinach do bufora. Funkcja napisana jest w C ale z powodu predkosci zmian stanow na pinach i ograniczenia czestotliwosci pracy zegara mikrokontrolera jestem zmuszony przepisac ja na asembler. O ile pisanie programow w C nie sprawia mi trudnosci o tyle asembler Atmegi owszem. Ktos kiedys wskazal mi pomoc w nauce asemblera w avr-libc-user-manual ale niestety nie jest to dla mnie wystarczajace. Moze pomozecie mi przepisac ta funkcje? Funkcja wyglada tak:



#define DI (PIND & (1<<PIND5)) #define CE (PIND & (1<<PIND2)) #define CL (PIND & (1<<PIND3))



do { oldStanCL=stanCL; do // czeka na narastajace zbocze sygnalu CE { oldStanCE=stanCE; stanCE=(uchar)CE; }while(stanCE>oldStanCE);



do // chip enable { stanCL=(uchar)(PIND & (1<<PIND3)); // czytanie linii portu CL



if(stanCL>oldStanCL) // detekcja narastajacego zbocza CL { if(DI) bajt |= (1<<itemBit); else bajt &= ~(1<<itemBit);



item++; if( ++itemBit>7 ) {



*ramkiPtr++=bajt; itemBit=0; } } oldStanCL=stanCL; }while(CE); // chip enable itemBit=0; if(item!=0x50) // jesli rekord jest o innej dlugosci powtorz odczyt rekordu { itemBit=0; item=0; ramkiPtr = ramkiPtrBuf; // odtworzenie wskaznika bufora odebranych ramek } }while(item != 0x50); // czytanie calego rekordu

Wszystkie zmienne s± jednobajtowe, poza ramkiPtr i ramkiPtrBuf ktore sa wskaznikami do bajtow. Monitorowany uklad podlaczony do mikrokontrolera z pomoca trzech linii CL, CE i DI. Odczyt rozpoczyna sie po pojawieniu sie zbocza narastajacego na pinie CE. Odczytywane wartosci sa z pinu DI po pojawieniu sie zbocza narastajacego na pinie CL. Po odczytaniu 0x50 wartosci odczyt jest zakonczony. Wiem, ze funkcja jest dosyc spora ale jestem zmuszony (czas) prosic Was pomoc. Bede wdzieczny rowniez za wskazanie innych miejsc, gdzie moglbym poczytac o wstawkach asemblerowych w GCC. Pozdrawiam



Jacek M.



Wiem, ze to jest bardzo duza prosba jak na zasady obowiazujace w grupie (glupio mi z tego powodu) ale zmusza mnie do tego moja sytuacja. Pozdrawiam

Jacek M.

Użytkownik Jacek M. napisał:

ldi ZL, Low(bufor) ldi ZH, High(bufor) ldi r16, 0x50 label1: sbic PIND, PIND2 rjmp label1 label2: sbis PIND, PIND2 rjmp label2

label3: sbic PIND, PIND3 rjmp label3 label4: sbis PIND, PIND3 rjmp label4

in r0, PIND st Z+, r0 dec r16 brne label3

Szybciej się już raczej nie da. Mozna jeszcze wykorzystać przerwania INT0 i INT1 ustawiając reakcje na zbocza narastające.

Pozdrawiam Grzegorz Kurczyk

P.S. Program pisałem z głowy na poczekaniu. Nie testowałem go, ale ogólna zasada jest jasna. "Wadą" jest to, że potrzeba 0x50 bajtów RAM-u na bufor, do którego zrzucane są całe wartości portu PIND. Po zakończeniu "próbkowania" możesz sobie wyANDować ;-) wartość interesującego bitu.

Pozdrawiam Grzegorz Kurczyk

Witam. Dziekuje Grzeskowi Kurczykowi za pomoc ale niestety nie umiem sobie poradzic dalej. W pliku read_Fram.S zbudowalem funkcje readFram i wkleilem do niego kod przez niego napisany. Uzupelnilem o deklaracje zmiennej zewnetrzej cos1, ktora w pliku C zdefiniowana jest jako globalna uchar cos1[80]. Oczywiscie umiescilem ten plik w makefile i skompilowalem. Niestety proba kompilacji zakonczyla sie komunikatami kompilatora o bledach. Nizej jest zawartosc pliku readFrame.S z komunikatami o bledach umieszczonymi w linii do ktorej sie odnosza. Plik frame.S: #include "avr/io.h"

.extern cos

.global readFram .func readFram

readFram: ldi ZL, Low(cos1) ; Warning: expression possibly out of 8-bit range, Error: garbage at end of line ldi ZH, High(cos1) ; Warning: expression possibly out of 8-bit range, Error: garbage at end of line ldi r16, 0x50 label1: sbic PIND, PIND2 ; Error: number must be less than 32 rjmp label1 label2: sbis PIND, PIND2 ; Error: number must be less than 32 rjmp label2

label3: sbic PIND, PIND3 ; Error: number must be less than 32 rjmp label3 label4: sbis PIND, PIND3 ; Error: number must be less than 32 rjmp label4

in r0, PIND st Z+, r0 dec r16 brne label3

.endfunc Nie moglem odnalezc makr (?) Low i High mimo poszukiwan, wiec nie moge skomentowac ostrzezen do tych lini sie odnoszacych. W ogole nie rozumiem komunikatow o bledach w liniach z instrukcjami asemblerowymi sbic i sbis. Przeciez ani port PIND, ani zaden pin z tego portu nie ma wartosci wiekszej niz 32? Z dokumentacji mikrokontrolera ATmega32 wynika, ze ta instrukcja asemblera jest uzyta dobrze. Prosze was o pomoc bo nie wiem jak wyjsc z tego. Pozdrawiam

Jacek M.

Jacek M. snipped-for-privacy@poczta.onet.pl> napisał(a): ..

Nie możesz traktować pliku *.S jak *.c , ponieważ ... sam wiesz dlaczego ;) przykład: #define OCR0 _SFR_IO8(0x31) //dla "C" i należy taki zapis zmienić na: #define OCR0 0x31 ;dla assemblera Również "low" zmień na "lo8" , a "high" na "hi8" . Wypadało by też poinformować linker , w jakiej sekcji umieścic dany obiekt. By z grubsza poznac tajniki assemblera , każ kompilatorowi "C" wygenerować pliki *.S i podejrzyj jak toto wygląda , a zobaczysz , że to kopalnia informacji.Nie pogardź dokumentacją avr-as.

Piotrek

PS Sam sie tego uczę , więc "znam ten ból" ;-)

Te definicje przeciez znajduja sie w pliku iom32.h do ktorego kompilator skierowany jest z pliku iom.h a ten jest dolaczony w pierwszej lini mojego pliku

To (przynajmniej na etapie kompilacji) pomoglo. Zobacze co bedzie dalej. :-))

Nie rozumiem. Prawdopodobnie chodzi Ci o plik raportu z rozszerzeniem *.lss a ten jest generowany dopiero po pomyslnym zakonczeniu kompilacji.

Dobrze wiedziec, ze nie jestem sam. Niestety dalej pozostaly komunikaty o bledach dotyczace linii z komendami sbic i sbis (: "Error: number must be less than 32"), nie rozumiem dlaczego . Proba zdefiniowania na nowo znaczenia PIND i PIND2 zakonczyla sie raportem kompilatora o bledzie dotyczacym definiowania na nowo znaczenia tych nazw co oznacza, ze kompilator widzi te definicje. Prosze jeszcze o pomoc jak usunac ten blad

Jacek M.

Ciekawa rzecz. Zmienilem te linie i wstawilem wartosci zdefiniowane w pliku iom32.h i kompilator juz nie zglasza bledu. Teraz ten fragmet wyglada tak: label1: sbic 10, 2 rjmp label1 label2: sbic 10, 2 rjmp label2 Tak jak pisalem poprzednio przy probie zdefiniowania na nowo tych nazw (PIND, PIND2...) kompilator generowal blad dotyczacy proby powtornego ich zdefiniowania. To juz nie mam pojecia dlaczego tak jest. Mozecie mi to wyjasnic? Pozdrawiam goraco.

Jacek M.

Jacek M. snipped-for-privacy@poczta.onet.pl> napisał(a): ..

To nie chce działać :( ..

Nie chodzi mi o plik *.lss a dokładnie o plik *.s (z małym "s") Tak kompiluję *.c do *.s

avr-gcc -S -mmcu=atmega32 -I. -gdwarf-2 -Os -funsigned-char

-funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes

-Wa,-adhlns=main.lst -std=gnu99 -DF_OSC=8000000 -MD -MP -MF .dep/main.s.d main.c -o main.s

..

Nie wiem (jeszcze ;) ) dlaczego tak się dzieje , ale asm "nie łyka" plików nagłówkowych kompilatora "C".Wczytałem assemblerowy includ "m32def.inc" do edytora, zamieniłem hurtowo wszystkie ".equ" na "#define" ,"$" na "0x" , jeszcze kilka kosmetycznych poprawek , zapisałem w kalatogu projektu jako "m32def.h" i działa ;-) Zrobiłem nawet test dla Ciebie ;)

#include "m32def.h" globl Fonts globl funkcja section .progmem.data Fonts: byte 1,2,3,4,5,6 byte 11,22,33,44,55,66 section .text func funkcja funkcja: push r16 sbic PIND,PIND2 out PIOTR,r16 // dla #define PIOTR _SFR_IO8(0x1e) - błąd // dla #define PIOTR 0x1e - OK

pop r16 ret

Należy byc baaaaaaardzo dociekliwym ;-)

Piotrek

.. #include "m32def.h" .globl Fonts .globl funkcja .section .progmem.data Fonts: .byte 1,2,3,4,5,6 .byte 11,22,33,44,55,66 .section .text .func funkcja funkcja: push r16 sbic PIND,PIND2 out PIOTR,r16 // dla #define PIOTR _SFR_IO8(0x1e) - błąd // dla #define PIOTR 0x1e - OK

pop r16 ret

Kurde! "wcięło" kropki przy dyrektywach

Piotrek

Sun, 18 Dec 2005 10:42:01 +0100, na pl.misc.elektronika, Jacek M. napisał(a):

To jest normalne - wynika ze sposobu definiowania SFR. Rejestry IO są w nim traktowane jako obszar pamięci - bez offsetu 0x20, a assembler tego nie wie. Wstaw zamiast PIND _SFR_IO_ADDR(PIND) i powinno zadziałać. Alternatywny sposób to zdefiniowanie #define __SFR_OFFSET 0 na początku pliku ale autorzy avr-libc raczej nie zalecają. Wszelkie takie szczegóły w avr/include/avr/sfr_defs.h

Jurek Szczesiul snipped-for-privacy@wycin.ep.com.pl> napisał(a):

Z tego wynika , ze sposobów jest ... hoho ;) W ramach eksperymentu , wstawiłem sbic PIND -__SFR_OFFSET,PIND2 i też działa ;)

Dzięki

Wielkie dzieki za taaaaaaaaaaaaaaaaaak duza pomoc. :-)) Chcialbym jeszcze o jedno zapytac. Czy znasz dobrego helpa asemblera dla WinAVR? Jakos nie moge na taki trafic. Wszystko co znajduje goglowaniem jest bardzo fragmentaryczne. W podprogramie napisanym wyzej jest dla mnie nie do konca jasne kilka dyrektyw i dlatego przydalby mi sie taki (np.) tutorial. Na przyklad problem z uzywaniem w pliku asm zmiennej wielobajtowej zdefiniowanej w pliku *.c. Zrobilem to na zasadzie podobnej jak kiedys rozwiazalem dla innego mikrokontrolera ale nie wiem czy optymalnie. Podobnych pytan mam wiecej wiec przydalby sie taki dobry help. Jeszcze raz dzieki...

Jacek M.

W koncu doszedlem do wniosku, ze najlepiej bedzie jak przesymuluje projekt z plikiem asemblerowym i wtedy usune bledy. Chcialem uzyc do tego AVR Studio

  1. Projekt skompilowal sie bez bledow ale przy probie symulowania w pracy krokowej nie "wchodzi mi" do funkcji z pliku *.S. Projekt zawiera dwa pliki napisane dla GCC i jeden w asemblerze. Nie widze nic w ustawieniach co mogloby wymagac ustawienia by uruchomic to. Czy nie mozna symulatora uzywac do symulowania asemblera z GCC? Prosze o pomoc.

Jacek M.

Prosze o pomoc nie wiem jak przesymulowac plik asemblerowy w AVR Studio4. Caly projek kompiluje sie bez bledow ale tak jak pisalem wyzej w trakcie symulacji (praca krokowa) nie wchodzi mi (z mozliwoscia sledzenia) do pliku asemblerowego *.S. Wszystko jest kompilowane w GCC. Poszukiwanie w necie doprowadzily mnie instrukcji kompilacji i symulacji w takiej konfiguracji jak moja ale bez plikow pisanych w asemblerze. Pewnie jest ktos, kto ma juz za soba ten problem. Pozdrawiam

Jacek M.

Jacek M. snipped-for-privacy@poczta.onet.pl> napisał(a): ..

Opiszę łopatologicznie ;-) a)uruchom debugger b)wybierz menu->view->disassember c)uaktywnij myszką okno z kodem źródłowym *.c (lub menu->window->źródło.c) i klikaj "step over" d)jak dojedziesz do miejsca wywołania interesującej Cię funkcji , to uaktywnij myszką okienko disassembler(lub menu->window->disassembler) e)klikaj "step into" i .... podziwiaj , niestety nie będzie Twoje źródło *.s :(

Piotrek

Dziekuje Piotrze, w wolnej chwili przetestuje. Pozdrawiam wszystkich, ktorzy starali sie mi pomoc.

Jacek M.

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required