się poprawnie?

Witam!

To moje pierwsze godziny z SAM7S :). Na razie udało się skompilować pierwszy program migający diodami i działa. Mam jednak pytanie na które nie potrafie doszukać się odpowiedzi w PDFie.

Mam trzy pliki:

main.c - glowny kod startup_SAM7S.S - plik z startup cpu (stos, przerwania, etc) AT91SAM7S64-ROM.ld - skrypt linkera

O ile dobrze rozumiem, to SAM7S startuje w trybie 32 bitowych instrukcji ARM. Plik startup_SAM7S.S kompilować muszę bez flagi -mthumb.

Aby mój program main.c zadziałał jego też muszę skompilować bez flagi

-mthumb.

Teraz pytanie:

a) w jaki sposób nalezy poprawnie kompilować kod tak, żeby main.c używał thumb? Przypuszczam że należy puścić 2 osobne jednostki translacji na kazdy z plików? Czyli startup.s - 32 bity arm, main.c - thumb, czy tak?

b) w jaki sposób procesor informowany jest o przejściu w tryb thumb ? Nie potrafie sie doszukać tej informacji w pdfie. Rozumiem że jest do tego jakas instrukcja czy bit rejestrze ? Jeśli tak, to powinna być za to odpowiedzialna pierwsza instrukcja w funkcji "main", czy tak?

Przypuszczam, że musze jakoś przestawić cpu do thumb ponieważ w tej chwili przekompilowanie kodu z flagą -mthumb powoduje pójście w maliny (pojawia się stan Abort).

PS. Nie korzystam z makefile, chce wiedzieć JAK to działa. Dlatego kompiluje z palca:

arm-elf-gcc -mcpu=arm7tdmi main.c startup_SAM7S.S -nostartfiles -O2 -o main.elf

Reply to
Sebastian Bialy
Loading thread data ...

Sebastian Bialy pisze:

Tak, dodatkowo do obu trzeba dolozyc -thumb-interwork

---------------------------- manual gcc:

-mthumb-interwork Generate code which supports calling between the ARM and Thumb instruction sets. Without this option the two instruction sets cannot be reliably used inside one program. The default is ‘-mno-thumb-interwork’, since slightly larger code is generated when ‘-mthumb-interwork’ is specified.

----------------------------

Pozdr AK

Reply to
AK

Witam

Sebastian Bialy pisze:

Tryb procesora (ARM czy Thumb) jest sygnalizowany przez jeden z bitów rejestru stanu procesora (CPSR[5]). Przejście do trybu Thumb może odbyć się poprzez wykonanie instrukcji ARM BX (branch and exchange) - skok do adresu przechowywanego w rejestrze ogólnego przeznaczenia połączony z zmianą trybu pracy - jeżeli najmniej znaczący bit tego rejestru jest równy 1. Jeżeli bit ten równy jest 0, procesor kontynuuje pracę w trybie ARM. Można także zmienić odpowiedni bit wspomnianego wcześniej rejestru stanu CPSR - tylko nie bezpośrednio, ale pośrednio poprzez modyfikację SPSR i przepisanie go do CPSR.

Reply to
Yrjola

OK, to teraz pytanie: czy odpowiedzialny za to powinien być mój program (np funkcja main) czy kod startup? Szukam tego w mojm startup (startup_SAM7S.S wyjęty .... z jakiegoś cudzego projektu, ale częto go widuje) ale jakoś nie mogę znaleźć flagi która to przełacza.

A może wiesz jak działa tryb mieszany ARM - czy wywołania wzajemne ARM<->Thumb muszą być jakoś wspomagane przez kompilator? Zastanawia mnie co robi flaga -mthumb-interwork.

Reply to
Sebastian Bialy

Sebastian Bialy pisze:

Kod w startup odpowiada za inicjalizację tablicy wektorów przerwań, wskaźników stosu dla poszczególnych trybów pracy (terminu 'tryb pracy' może używajmy dla określenia trybów 'user', 'supervisor', 'interrupt', 'fast interrupt', 'abort' i 'undefined', natomiast ARM i Thumb niech będą 'stanami' procesora) oraz ewentualnych układów peryferyjnych - timerów, uartów i innych takich. Na jego końcu następuje przełączenie do trybu użytkownika i skok do funkcji main i rozpoczęcie jej wykonywania w stanie ARM.

Cóż, właśnie się zreflektowałem, że prawdopodobnie nie piszesz w asemblerze, tylko próbujesz w C. W assemblerze sprawa jest prosta - odpowiednie fragmenty kodu opatruje się dyrektywą .arm lub .thumb. Natomiast chcąc w C użyć stanu ARM i Thumb, trzeba odpowiednie fragmenty kodu umieścić w różnych plikach, które należy odmiennie skompilować - w kompilatorze Keil jest bodajże flaga -arm oraz -thumb, w kompilatorach GNU -marm i -mthumb. Potem wyjściowe pliki kompilatora trzeba zlinkować i powinno hulać. Flaga -mthumb-interwork wskazuje właśnie kompilatorowi, że może wystąpić przełączanie pomiędzy stanami/zestawami instrukcji ARM i Thumb.

Reply to
Yrjola

OK, z tego co mówisz wynika że sprawa przełączenia na thumb jest raczej kwestią programu usera.

A co one powodują ? Rozumiem, że generują odpowiednie instrukcje dla każdego z trybów.

Tak, to wiem.

Wiem co ona pokazuje, interesuje mnie jednak kto to "przełaczanie" robi. Kod ARM i THUMB nie jest (a może ?) kompatybilny na poziomie binarnym? Tzn wymagana jest jakaś ingerencja ręczna jesli z fragmentu kodu ARM przechodze do thumb i odwrotnie? Zakładam, ze dodatnie tej flagi interwork powoduje dodanie takich dekoratorów do procedur w asm.

Reply to
Sebastian Bialy

Sebastian Bialy pisze:

Dokładnie tak - kody maszynowe ARM są 32-bitowe, mogą operować na wszystkich 16-tu rejestrach w danym trybie. Thumb ma z kolei kody maszynowe 16-bitowe, co za tym idzie stanowią one podzbiór zbioru instrukcji ARM, ze względu na 'mniej miejsca w rozkazie' mogą operować bezpośrednio tylko na 8 rejestrach.

Gdy masz jakąś funkcję skompilowaną do trybu Thumb, to podczas jej wywołania kompilator prawdopodobnie użyje instrukcji bx (skok do adresu umieszczonego w rejestrze ogólnego przeznaczenia), lub blx (skok ze śladem - adresem powrotu w rejestrze LR - R14). Aby wskazać procesorowi, że oprócz zmiany licznika rozkazów ma przełączyć się do innego stanu pracy, kompilator musi ustawić najmniej znaczący bit w rejestrze z adresem docelowym na jeden - ponieważ słowa maszynowe są 2 lub 4 bajtowe, ten bit jest zwykle równy 0. Gdybyś chciał wykonać skok do funkcji skompilowanej do ARMa, kompilator zostawiłby ten bit w spokoju. Będąc z kolei w trybie Thumb i mając tenże bit ustawiony na 0, procesor przełączy się do trybu ARM. Czyli reasumując - o przełączanie zadba kompilator, odpowiednio kompilując wywołania funkcji. Co do flagi interwork - jeżeli jest włączona, kompilator wszystkie powroty z funkcji zakoduje przy użyciu rozkazu bx i rejestru powrotu LR

- dzięki czemu kod który wywołał funkcję ustawiając adres powrotu może także ustawić (poprzez najmniej znaczący bit) odpowiedni tryb pracy po powrocie. Natomiast same wywołania funkcji mogą być zakodowane przy użyciu instrukcji blx (która może przełączać tryby pracy), lub też bl (która tego nie może robić). Gdy kompilator użyje bl, musi więc wygenerować kilka dodatkowych instrukcji, które przełączą procesor. Podobnie sytuacja wygląda, gdy kompilator zechce wywołać funkcję nie poprzez adres w rejestrze, ale poprzez adres jako stałą natychmiastową - do ewentualnego przełączenia będzie potrzebował kilka dodatkowych instrukcji.

Reply to
Yrjola

Dziękuje za wyczerpujące informacje.

Reply to
Sebastian Bialy

Polecam rowniez sciagawke kodu zrodlowego FreeRTOSa, ktory ma port na ten procesor i GCC.

pozdrawiam Janusz U.

Reply to
Janusz U.

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.