logo elektroda
logo elektroda
X
logo elektroda
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

odwołanie do konkretnego rejestru avr język C

waldus86 01 Sty 2009 23:44 1826 3
  • #1 5935208
    waldus86
    Poziom 13  
    Witam wszystkich!
    Poszukiwania odpowiedzi na moje pytanie nie przyniosły skutku, więc postanowiłem napisać tutaj. Otóż mam pytanie. Mam taki kod:
    asm("clc");
    			if(PS_WEJ&0x01)
    				{
    			asm("sec");
    				}
    			asm("ror r16");


    I jak teraz w C odwołać się do tego rejestru r16, np przypisać jakiejś zmiennej zawartość tego rejestru? Czy jest to możliwe, a jeśli tak to jak to zrobić? Z góry dzięki.
  • Pomocny post
    #2 5935468
    BoskiDialer
    Poziom 34  
    Zamiast pytać o to jak odwołać się do tego rejestru (co prawda można tworząc zmienną przez [register unsigned char jakas_zmienna asm("r16");]), to powinieneś zastanowić się, czy kompilator nie wtrąci instrukcji organizacyjnych pomiędzy wstawki lub czy nie usunie wstawek (brak volatile i powiązania ze zmiennymi). Jeśli już chcesz korzystać z assemblera, to albo robisz cały fragment w asm, albo cały moduł w asm (dla mnie łatwiej jest zrobić cały moduł).
    Kod w C po skompilowaniu też może wymagać rejestrów jak i flag, przez co zakłada się, że pomiędzy wstawkami rejestry tracą swoją wartość (chyba, że do wstawki przekazano zmienne bezpośrednio lub pośrednio). Dla przykładu sprawdzenie "PS_WEJ&0x01" wymagać będzie wczytania PS_WEJ do rejestru (nie wiesz którego), maskowania bitu (aktualizacja flagi Z) i skoku (kompilator nie rozwinie tego na sbic/sbis, gdyż nie może nic zakładać co do liczby instrukcji wstawki). Co prawda nie następuje tutaj zmiana flagi C, ale nigdy nie wiadomo do czego kompilator sprowadzi kod. Jeśli jesteś zmuszony do wykorzystania wstawek, to napisz cały fragment, kod będzie pewniejszy. Jeśli nie, to czy wstawki są aż tak bardzo potrzebne? Podany przez Ciebie kod można zapisać tak:
    jakas_zmienna >>= 1;
    if(PS_WEJ&0x01) 
    	jakas_zmienna |= 0x80;
    nie tracąc na szybkości (3 cykle przy rejestrze IO dostępnym przez sbic/sbis, 3 przy innym rejestrze [sbrc/sbrs], 5 przy komórce pamięci). Ze względu na skrajny bit można to zoptymalizować, kiedy zmienna jest w rejestrze, wtedy można zejść do 2 cykli przez wysunięcie bitu do C a potem przesunięcie do właściwego rejestru.
    Tak więc albo piszesz całość w C (kiedy kompilator potrafi sobie zoptymalizować kod), albo piszesz całość (większy fragment) w asm, kiedy to Ty sobie optymalizujesz całość. Rama na C i pojedyncze instrukcje w asemblerze to najgorsze co można zrobić, kompilator nie ma jak zoptymalizować kodu w C, jak i nie ma możliwości mu w tym pomóc.

    Jeśli korzystasz z gcc: GCC-AVR Inline Assembler Cookbook
  • #3 5935470
    Freddie Chopin
    Specjalista - Mikrokontrolery
    ciekawe po co taka kombinatoryka...

    
    uint8_t zmienna;
    
    ...
    
    zmienna>>=1;
    
    if(PS_WEJ&0x01)
    zmienna|=(1<<7);
    


    efekt ten sam, sprawa 10x prostsza.

    a jak koniecznie musi byc metoda na-okolo-specjalnie-utrudniam-zeby-nikt-nie-zrozumial-co-chce-osiagnac, to mozna:

    
    uint8_t zmienna;
    
    ...
    asm("ror %0"::"+r"(zmienna));
    


    albo jakos tak. w manualu do gcc jest to dobrze opisane.

    tak czy siak oryginalna koncepcja jest... chora.

    EDIT: damn! minute za pozno [;

    4\/3!!
  • #4 5936643
    waldus86
    Poziom 13  
    Dzięki!
    Kombinatoryka, bo inaczej nie umiałem i tyle.
REKLAMA