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

AVR Studio omijanie niektórych funkcji

Krzych12 22 Lis 2009 16:05 1098 5
  • #1 7294459
    Krzych12
    Poziom 12  
    W jaki sposób "zmusić" kompilator gcc gnu w AVR Studio aby nie omijał podczas Buildu funkcji?
    Problem ten zauważyłem podczas napisania prostego programu:
    
    #include<avr/io.h>
    #include<avr/sfr_defs.h>
    
    void czekaj(unsigned int pt)
    {
    	unsigned int tp1 ;
    
    	for(; pt > 0; pt--)
    	{
    		for(tp1 = 0; tp1 < 255; tp1++) ;
    	}
    }
    
    int main(void)
    {
    	DDRD  = 0xFF ;
    	PORTD = 0x55 ;
    	while(1)
    	{
    		if(bit_is_set(PORTD,PD7))
    		{
    			PORTD <<= 1 ;
    			PORTD |=  0x01 ;
    			czekaj(1500) ;
    		}
    		else
    		{
    			PORTD <<= 1 ;
    			czekaj(1500) ;
    		}
    	}
    	return(0) ;
    }
    

    Po deasemblacji widać, że linker nie dołączył do programu funkcji czekaj.
    Dopiero po zmianie optymalizacji na -O0 linker dołączał tą funkcje.
    Jednak program strasznie się "rozrósł".
    Czy istnieje jakiś inny sposób na dołączenie funkcji, przy optymalizacji -Os?
  • #2 7294771
    mirekk36
    Poziom 42  
    Gwarantuję ci, że na obecnym etapie znajomości AVR GCC nie potrzeba ci innej optymalizacji niż -Os. A przy użyciu tej opcji kompilator wcale nie pominął twojej funkcji czekaj. Zareagował całkiem poprawnie i prawdopodobnie twoja funkcja czekaj po kompilacji składa się z samego rozkazu return .

    Po prostu została ona zoptymalizowana bo jest hmmm delikatnie mówiąc b.dziwnie napisana - i tak samo kompilator ją kompiluje ;) tzn dziwnie

    a spróbuj sobie w tej wewnętrznej pętli tę drugą - środkową napisać tak:

    for(tp1 = 0; tp1 < 255; tp1++) asm("nop"); 


    i wtedy podejrzyj sobie kod, i spróbuj dojść sam dlaczego jest taki efekt w twoim przypadku i w tym przypadku

    poza tym - zapoznaj się też z funkcją typu _delay_ms()
  • #3 7294835
    Krzych12
    Poziom 12  
    Taki zapis faktycznie gwarantuje dołączenie tej funkcji. Tylko zastanawia mnie dlaczego bez optymalizacji (-O0) nie potrzeba uciekać się do wstawek asemblerowych .
  • #4 7294919
    mirekk36
    Poziom 42  
    tu nie chodzi o żadną wtsawkę asemblerową - możesz w to miejsce wykonać jakiekolwiek inne działanie na zmiennej i zrobić jeszcze jakiś warunek z tą zmienną albo dać jej status volatile.

    np tak:

    void czekaj(unsigned int pt) 
    { 
       unsigned int tp1 ; 
       uint8_t a;
    
       for(; pt > 0; pt--) 
       { 
          for(tp1 = 0; tp1 < 255; tp1++)
          {
              a+=1;
              if(a) a=0;
          } 
       } 
    } 


    albo tak:

    void czekaj(unsigned int pt) 
    { 
       unsigned int tp1 ; 
       volatile int a;
    
       for(; pt > 0; pt--) 
       { 
          for(tp1 = 0; tp1 < 255; tp1++) a+=1; 
       } 
    } 


    oczywiście to działanie na zmiennej a - jest całkowicie bez sensu - ale chodzi o to żebyś zwrócił uwagę dlaczego kompilator w ten sposób traktuje pustą i z jego punktu widzenia bezużytczną pętlę

    optymalizacja -Os jest i jeszcze będzie długo dla ciebie (zresztą ja jej cały czas używam) najlepszą. Musisz tylko troszkę poczytać o C oraz co i jak się kompiluje, co to znaczy volatile itp
  • #5 7295055
    Krzych12
    Poziom 12  
    Faktycznie użycie zmiennej jako "ulotnej" - zachowaj szczególną uwagę na zmienną daje oczekiwany efekt końcowy
    
    #include<avr/io.h>
    #include<avr/sfr_defs.h>
    
    void czekaj(unsigned int pt)
    {
    	volatile unsigned int tp1 ;
    
    	for(; pt > 0; pt--)
    	{
    		for(tp1 = 0; tp1 < 255; tp1++) ;
    	}
    }
    
    int main(void)
    {
    	DDRD  = 0xFF ;
    	PORTD = 0xFC ;
    	while(1)
    	{
    		if(bit_is_set(PORTD,PD7))
    		{
    			PORTD <<= 1 ;
    			PORTD |=  0x01 ;
    			czekaj(1500) ;
    		}
    		else
    		{
    			PORTD <<= 1 ;
    			czekaj(1500) ;
    		}
    	}
    	return(0) ;
    }
    
    


    Jednak powstaje inny problem. Jeśli zobaczymy do źródła w asmie to widać że ciało funkcji jest wstawiane do programu za każdym razem użycia jej nazwy. Nie ma wywołania Recall'a co przy długim programie sprawia znaczne jego wydłużenie.
REKLAMA