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

Za duży rozmiar programu w Atmega 8 pisanego w języku C

LuznyTomasz 27 Cze 2005 03:55 4319 30
Najlepsze odpowiedzi LABEL_AI_GENERATED

Jak zmniejszyć rozmiar programu w ATmega8 napisanego w C, żeby zmieścić wszystkie planowane funkcje?

Najwięcej miejsca oszczędzisz, usuwając nieużywane funkcje z biblioteki NokiaLCD oraz rezygnując z ciężkich bibliotek `stdio` i `stdlib`, bo w mikrokontrolerach dołączają się statycznie razem z całym kodem, nawet jeśli używasz tylko części funkcji [#1609642] [#1609801] Przenieś też zmienne z globalnych na lokalne tam, gdzie się da, bo kompilator może trzymać je w rejestrach i wtedy kod bywa krótszy [#1609692] Warto sprawdzić wszystkie poziomy optymalizacji WinAVR/GCC, bo najwyższy poziom nie zawsze daje najmniejszy wynik [#1614855] [#1615005] W Twoim kodzie `wyswietl_czas()` jest skopiowane w obsłudze przerwania `SIG_OVERFLOW1`, więc lepiej wywołać jedną wspólną procedurę zamiast powielać ten sam blok [#1611699] Autor wątku odzyskał też kolejne `0x100` bajtów po wyrzuceniu zbędnej procedury z biblioteki LCD, więc to właśnie biblioteka była głównym źródłem nadmiaru kodu [#1614559] Funkcja `itoa` nie wyglądała na głównego „pożeracza” pamięci, więc większy zysk da porządkowanie biblioteki i kodu niż ręczne zastępowanie każdej konwersji [#1615086]
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA
  • #1 1609639
    LuznyTomasz
    Poziom 15  
    Posty: 204
    Pomógł: 13
    Ocena: 1
    Już za kilka dni muszę oddać moją pracę dyplomową. Moim problemem jest zbyt duży rozmiar kodu i jeśli nie zoptymalizuje programu to nie umieszczę w nim wszystkich założonych funkcji. Czy ktoś ma pomysł jak zaoszczędzić trochę pamięci patrząc na mój kod? (na program skłąda się jeszcze biblioteka do obsługi wyświetlacza z Nokii)

    #define _MAIN_MOD_ 1
    #define Histereza 6
    #define ILOSC_PROBEK 100

    #define ESC 0x02 // PA1
    #define BOK 0x04 // PA2
    #define GORA 0x08 // PA3
    #define ENTER 0x10 // PA4
    #define LADOWANIE 0x20 //PA5
    #define DIODA 0x40 //PA6
    #define BUZZER 0x80 //PA7
    // pliki dołączone ( include ) :
    #include <avr/io.h>
    #include <avr/signal.h>
    #include <avr/interrupt.h>

    //#include <stdio.h>
    #include <stdlib.h>
    #include <STRING.H>


    #include "NokiaLCD.h"
    // dane :

    char klawisz;
    unsigned char Str[12];
    unsigned char licznik_probek=0;
    unsigned char z=0,y=0, x=0;
    unsigned int okres=0;
    unsigned int liczba_uderzen;
    unsigned int tetno;
    //unsigned char bufor_tetno=0;
    unsigned int prog;
    unsigned int wynik[15];
    unsigned char tablica[100];
    enum Faza
    {
    wzrost = 0,
    spadek = 1
    }FazaPrzebiegu;

    //Faza FazaPrzebiegu;
    // funkcje :

    void USART_Init(unsigned char) ;
    void USART_Transmit( unsigned char);

    //====================
    //przetwornik a/c, wejscie analogowe ADC0
    char *komunikat[]={" Start"," Alarm "," Opcje"," Wyniki"," Zeruj "," Stop " };
    char *komunikat1[]={" Czas "," T.min "," T.max ", "Kalorie"};
    char *komunikat2[]={" Czas "," Tetno ","Kalorie"};

    char *wyswietl;
    struct time
    {
    unsigned int setne;
    unsigned int sekundy;
    unsigned int minuty;
    unsigned int godziny;
    };

    struct time czas;
    struct time alarm_czas;
    struct time bufor_alarm_czas;
    /**************************************************************************************************/
    void zwieksz_czas()
    {
    czas.setne++;
    if(czas.setne==100)
    {
    czas.setne=0;
    czas.sekundy++;
    }
    if(czas.sekundy==60)
    {
    czas.sekundy=0;
    czas.minuty++;
    }
    if(czas.minuty==60)
    {
    czas.minuty=0;
    czas.godziny++;
    }
    if(czas.godziny==24)
    {
    czas.godziny=0;
    }
    }

    /**************************************************************************************************/
    void wyswietl_czas()
    {
    LcdGotoXY(3,6);
    itoa(czas.godziny/10,&Str[0],10);
    itoa(czas.godziny%10,&Str[1],10);
    Str[2]=':';
    itoa(czas.minuty/10,&Str[3],10);
    itoa(czas.minuty%10,&Str[4],10);
    Str[5]=':';
    itoa(czas.sekundy/10,&Str[6],10);
    itoa(czas.sekundy%10,&Str[7],10);
    Str[8]=':';
    itoa(czas.setne/10,&Str[9],10);
    itoa(czas.setne%10,&Str[10],10);
    Str[11]=' ';
    LcdStr(1,&Str[0]);
    }

    /**************************************************************************************************/
    int main(void)
    {
    PORTD=0xff;
    DDRD=0x13; //ustawienie całego portu D jako wyjscia
    ADCSRA=ADCSRA | 1<<ADEN; //włączenie przetwornika
    ADMUX=ADMUX | 1<<ADLAR; //w
    ADCSRA|= (1<<ADATE)|(1<<ADSC)|(1<< ADPS2)|(1<< ADPS1)|(1<< ADPS0); //wynik równany do lewej - 8 bitów w ADCH i 2 w ADCL,free running mode ,start pojedynczej konwersji (bit zerowany po jej zakończeniu)zegar ADC/128 =62,5kHz
    USART_Init(51); //prędkosc transmisji dla 8MHz 9600 BAUD (błąd 0.2%)
    TCCR1B|=(1<<CS11)|(1<<CS10); //preskaler XTAL/64=8us
    TCNT1=65536-1250; //8us*1250=10ms
    TIMSK=1<<TOIE1; //odblokowanie przerwania od timera1
    LcdInit();
    LcdClear();
    DDRA=LADOWANIE;
    PORTA=LADOWANIE;
    DDRA=0xC0;
    PORTA=0x9f; //pa0-4 wejscie, pa5 w stan wysokiej impedancji,p6-7 wjscie stan wysoki
    wyswietl=komunikat[z];
    sei(); //odblokowanie globalnej maski przerwan
    PORTA^=DIODA;
    while(1)
    {Delay(250);}
    while(1)
    {
    PORTA=PORTA|BUZZER;
    klawisz=(~PINA)&0x1E;
    if(klawisz!=0) Delay(250);
    if((SREG&0x80)==0) //brak pomiaru tetna, globalna maska przerwań wyzerowana
    {
    if(klawisz==ESC){}
    if(klawisz==BOK){}
    if(klawisz==GORA)
    {
    if(++z==5)z=0;
    wyswietl=komunikat[z];
    }
    if(klawisz==ENTER)
    {
    do
    {
    klawisz=(~PINA)&0x1E;
    if(klawisz!=0) Delay(250);
    if(z==0)
    {
    PORTA^=DIODA;
    wyswietl=komunikat[5];
    sei();
    }
    if(z==1)
    {
    if(klawisz==GORA)if(++y==4)y=0;
    wyswietl=komunikat1[y];
    if(klawisz==ENTER)
    {
    if(y==0)//ustawienie czasu
    {
    do
    {
    // wyswietl_alarm();
    LcdUpdate();
    while((klawisz=(~PINA)&0x1E)==0){}
    Delay(250);
    if(klawisz==BOK)
    {
    if(++x==5)x=0;
    }
    if(klawisz==GORA)
    {
    if(x==0){if(++bufor_alarm_czas.godziny==10)bufor_alarm_czas.godziny=0;}
    if(x==1)
    {
    bufor_alarm_czas.minuty+=10;
    if(bufor_alarm_czas.minuty>59)bufor_alarm_czas.minuty=0;
    }
    if(x==2){if(++bufor_alarm_czas.minuty>59)bufor_alarm_czas.minuty=0;}
    if(x==3)
    {
    bufor_alarm_czas.sekundy+=10;
    if(bufor_alarm_czas.sekundy>59)bufor_alarm_czas.sekundy=0;
    }
    if(x==4) if(++bufor_alarm_czas.sekundy>59)bufor_alarm_czas.sekundy=0;
    }
    // wyswietl_alarm();
    LcdUpdate();
    //LcdClear();
    }
    while(klawisz==GORA || klawisz==BOK);
    if(klawisz==ESC)
    {
    bufor_alarm_czas.godziny=alarm_czas.godziny;
    bufor_alarm_czas.minuty=alarm_czas.minuty;
    bufor_alarm_czas.sekundy=alarm_czas.sekundy;
    }
    if(klawisz==ENTER)
    {
    alarm_czas.godziny=bufor_alarm_czas.godziny;
    alarm_czas.minuty=bufor_alarm_czas.minuty;
    alarm_czas.sekundy=bufor_alarm_czas.sekundy;
    }
    LcdClear();
    wyswietl=komunikat[z];
    x=0;
    klawisz=0x00;
    }
    if(y==1) //ustawienie tetna minimalnego
    {
    do
    {
    }
    while(klawisz==GORA || klawisz==BOK);
    if(klawisz==ESC)
    {
    }
    if(klawisz==ENTER)
    {
    }
    LcdClear();
    wyswietl=komunikat[z];
    x=0;
    klawisz=0x00;
    }
    if(y==2){}
    if(y==3){}
    }
    }
    if(z==2){}
    if(z==3){}
    if(z==4){}
    LcdGotoXY(1,2);
    LcdStr(2,wyswietl);
    //LcdStr(2,komunikat[z]);
    LcdUpdate();
    }
    while(klawisz!=ESC && (SREG&0x80)==0);
    }
    LcdGotoXY(1,2);
    LcdStr(2,wyswietl);
    //LcdStr(2,komunikat[z]);
    LcdUpdate();
    }
    else
    {
    }
    }
    return(0);
    }
    /***********************obsługa przerwania timera 0****************************************************************************/
    SIGNAL(SIG_OVERFLOW1)
    {
    TCNT1=65536-1250; //załadowanie licznika 8us*1250=10ms
    tablica[licznik_probek]=ADCH;
    USART_Transmit(tablica[licznik_probek]);
    for(char i=0;i<ILOSC_PROBEK;i++)
    {
    prog+=tablica[i];
    }
    prog/=(ILOSC_PROBEK);


    if(++licznik_probek==ILOSC_PROBEK)licznik_probek=0;

    okres++;
    zwieksz_czas();

    if(FazaPrzebiegu==spadek && tablica[licznik_probek]>prog-Histereza && ((licznik_probek!=0 && tablica[licznik_probek-1]<=prog-Histereza) ||(licznik_probek==0 && tablica[ILOSC_PROBEK-1]<=prog-Histereza)))
    {
    FazaPrzebiegu=wzrost;
    tetno=0;
    for(char i=0;i<14;i++)
    {
    wynik[i]=wynik[i+1];
    }
    wynik[14]=okres;
    for(char i=0;i<15;i++)
    {
    tetno+=wynik[i];
    }
    tetno=400/(tetno) ; //(6000/15)

    liczba_uderzen++;
    okres=0;
    }
    if(tablica[licznik_probek]<prog+Histereza && tablica[licznik_probek-1]>=prog+Histereza && FazaPrzebiegu==wzrost)
    {
    FazaPrzebiegu=spadek;
    }
    if(okres==300) //brak pulsu przez 3s lub tetno za niskie
    {
    okres=0;
    tetno=0;
    LcdGotoXY(1,4);
    LcdStr(2,"000");
    for(char i=0;i<15;i++)
    {
    wynik[i]=0;
    }
    }
    else
    {
    if(tetno<100 && tetno>29)
    {
    LcdGotoXY(1,4);
    LcdStr(2,"0");
    LcdGotoXY(3,4);
    LcdStr(2,itoa(tetno,&Str[0],10));
    }
    else if(tetno<240 && tetno>=100)
    {
    LcdGotoXY(1,4);
    LcdStr(2,itoa(tetno,&Str[0],10));
    }
    LcdGotoXY(7,4);
    LcdStr(2,"/min");
    }


    LcdGotoXY(3,6);
    itoa(czas.godziny/10,&Str[0],10);
    itoa(czas.godziny%10,&Str[1],10);
    Str[2]=':';
    itoa(czas.minuty/10,&Str[3],10);
    itoa(czas.minuty%10,&Str[4],10);
    Str[5]=':';
    itoa(czas.sekundy/10,&Str[6],10);
    itoa(czas.sekundy%10,&Str[7],10);
    Str[8]=':';
    itoa(czas.setne/10,&Str[9],10);
    itoa(czas.setne%10,&Str[10],10);
    Str[11]=' ';
    LcdStr(1,&Str[0]);


    LcdGotoXY(8,5);
    LcdStr(1,itoa(liczba_uderzen,&Str[0],10));
    LcdUpdate();

    }
    /***************************************************************************************************/
    void USART_Init( unsigned char baud )
    {
    //UBRRH = (unsigned char)(baud>>8);
    UBRRL = (unsigned char)baud;
    /* Enable receiver and transmitter */
    UCSRB = (1<<RXEN)|(1<<TXEN);
    /* Set frame format: 8data, 1stop bit Asynchronous mode*/
    UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
    }
    /***************************************************************************************************/
    void USART_Transmit( unsigned char data )
    {
    /* Wait for empty transmit buffer */
    while ( !( UCSRA & (1<<UDRE)) );
    /* Put data into buffer, sends the data */
    UDR = data;
    }
  • REKLAMA
  • #2 1609642
    LordBlick
    VIP Zasłużony dla elektroda
    Posty: 5438
    Pomógł: 549
    Ocena: 69
    To co tutaj zamieściłeś, to raczej pikuś. Co jeszcze kompilujesz (linia "SRC = $(TARGET).c ..." w Makefile) ? Podejrzewam "NokiaLCD.c" o spory rozmiar (definicje fontów ?). Pozostaje albo wyrzucić nieużywane procedury i definicje z tej biblioteki (oczywiście jej kopii... ;)), albo wykonanie przejściówki do Atmega 16... ;)
    B.T.W. Ciekawy projekt... ;)
    --
    Pozdrawiam, Daniel
  • REKLAMA
  • #3 1609692
    Tdv
    Poziom 34  
    Posty: 2237
    Pomógł: 150
    Ocena: 55
    O ile Ci się nie mieści? Przejrzałem ten kod brdzo pobieżnie i od razu nasuwa się wniosek, że masz same globalne zmienne, co tylko się da pozmieniaj na zmienne lokalne.
    Zmień optymalizację w kompilatorze - też powinno parę bajtów uszczknąć.
    Używanie gotowych funkcji też czasem bywa nie ekonomiczne (spróbuj zastąpić je (itoa) własnymi funkcjami).
  • #4 1609801
    fantom
    Poziom 31  
    Posty: 1649
    Pomógł: 108
    Ocena: 42
    Powywalaj stdio i stdlib zastepujac wszystkie uzywane tam funkcje swoimi.Te biblioteki to bardzo duze kombajny i w kompilatorach na mikrokontrolery z oczywistych wzgledow sa statyczne a co za tym idzie cala ich zawartosc jest ladowana do kodu (rowniez to czego nie uzywasz).
  • #5 1611696
    LuznyTomasz
    Poziom 15  
    Posty: 204
    Pomógł: 13
    Ocena: 1
    Na większy mikrokontroler niestety nie zdąże się przenieść. Płytka zlutowana i nie zdąże zrobić drugiej.
    Zastanawua mnie jak to jest z tymi zmiennymi globalnymi. Przerzuciłem deklarację unsigned char tablica[100]; do obsługi przerwania i kod zwiększył mi sie o 0x34 :/ Gdy przenosiłem deklarację zmiennej numerującej pęlle do jej środka [ for(unsigned char i=0;.....)] kod ulegał zmniejszeniu.
    Myślałem nad zastąpieniem itoa własną procedurą tylko nie wiem czy sobie poradze. Zastanaweiam się tez jak zastąpić procedurę modulo i czy warto poświęcać temu czas. W chwili obecnej kod zajmuje 0xC00 pamięci programu a w bibliotece niewiele już można zrobić. Fontów do ramu nie mogę przenieść bo wtedy wystąpi podobny problem z pamięcią danych. EEPROM też odpada ze względu na długi czas odczytu tej pamięci. W programie brakuje mi jedynie obsługi menu (reakcja na wciśnięcie klawisza, wyświetlenie odpowiedniego komunikatu i ewentualnie wykonanie jakiegoś działąnia) więc mam nadzieje że zmieszcze choćby podstawowe funkcje.

    EDIT: Ech...podglądając plik listingu zauważyłem że itoa nie zajmuje dużo miejsca ale za to znalazłem jedną procedurę w bibliotece Lcd której nie używam i rozmiar programu zmniejszył się do trochę poniżej 0xb00. To co mi zostało to dużo czy mało?
  • REKLAMA
  • #6 1611699
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    No i nie rób dwa (lub więcej) razy tego , co wystarczy zrobić tylko raz.Mam na myśli procedurę "void wyswietl_czas() " , którą powtórzyłeś "jota w jotę" w obsłudze przerwania "SIGNAL(SIG_OVERFLOW1)".A wystarczy ją tylko "wywołać".Kod - zapewne można troszkę "zoptymalizować".

    Pozdrawiam
    Piotrek
  • #7 1611757
    LuznyTomasz
    Poziom 15  
    Posty: 204
    Pomógł: 13
    Ocena: 1
    A co znajduje się w sekcjach <__ctors_end> i <__vector_8> jedno z nich to pewnie przerwanie. Te dwie rzeczy zajmują mi zdecydowanie za dużo miejsca.
  • #8 1612312
    Tdv
    Poziom 34  
    Posty: 2237
    Pomógł: 150
    Ocena: 55
    Coś dziwne rzeczy wypisujesz.... )0x0C00 to jak na mój gust trochę ponad 3000, czyli nawet zakładając, że podajesz słowa, a nie bajty nadal masz 1/4 pamięci wolną, a 0x0B00 to nieco ponad 2800 więc w czym problem?
    Po drugie nie piszesz nic o optymalizacji - próbowałeś coś z tym robić? Z jakim efektem?
    Po trzecie ze zmiennymi lokalnymi to jest tak, że kompilator stara się zmienne lokalne upychać w rejestrach o ile ma taką możliwość, stąd zmniejszenie kodu przy operacjach dostępu i zwiększenie szybkości działania. Niestety nie posiada 100 rejestrów na tablicę.
    Po czwarte zajrzyj do wątku:
    https://www.elektroda.pl/rtvforum/topic274287-30.html#1388340
    umieściłem tam bibliotekę do obsługi LCD (zwykły LCD alfanumeryczny), w tych bibliotekach są funkcje do zmiany liczb całkowitych 8 bit, 16 bit i 32 bity na kody ascii. Wprost tego nie zastosujesz w Twoim przypadku ale powinno Ci to nieco ułatwić stworzenie własnych funkcji.
  • #9 1614559
    LuznyTomasz
    Poziom 15  
    Posty: 204
    Pomógł: 13
    Ocena: 1
    No niby mam jeszcze 1/4 pamięci ale program nie jest skończony. Kompilator jest ustawiony na minimalizację kodu. W bibliotece NokiaLcd jest jedynie obsługa 8 bitowych zmiennych. Po wyrzuceniu z biblioteki niepotrzebnych funkcji zaoszczędziłem kolejne 0x100 pamięci. Muszę jednak policzyć zużywane kalorie na podstawie tętna a to wymaga mnożenia ułamków. Może się zmieszcze.
  • #10 1614855
    Tdv
    Poziom 34  
    Posty: 2237
    Pomógł: 150
    Ocena: 55
    LuznyTomasz napisał:
    Kompilator jest ustawiony na minimalizację kodu.


    Na jaką optymalizację? gcc ma kilka poziomów optymalizacji i nie zawsze poziom najwyższy daje kod najkrótszy. Sprawdź po kolei wszystkie poziomy, w końcu to niejst zbyt dużo robroty;-D.
  • #11 1614994
    LuznyTomasz
    Poziom 15  
    Posty: 204
    Pomógł: 13
    Ocena: 1
    Więc jeśli chodzi o opcje programu WinAvr to widze następujące optymalizacje: wyłączona, poziom1,2,3 i rozmiar kodu. Jeśli można ustawić inne poziomy optymalizacji proszę o dalsze instrukcje.
  • #12 1615005
    Tdv
    Poziom 34  
    Posty: 2237
    Pomógł: 150
    Ocena: 55
    LuznyTomasz napisał:
    Więc jeśli chodzi o opcje programu WinAvr to widze następujące optymalizacje: wyłączona, poziom1,2,3 i rozmiar kodu. Jeśli można ustawić inne poziomy optymalizacji proszę o dalsze instrukcje.

    Dokładnie, tyle że efekty bywają różne i proponuje sprawdzić po kolei każdy stopień.
    No i nadal otwarta kwestia funkcji itoa, robiłeś coś z tym?
  • #13 1615086
    LuznyTomasz
    Poziom 15  
    Posty: 204
    Pomógł: 13
    Ocena: 1
    Przeglądałem plik lst i zauważyłem że ta funkcja nie pożera dużo pamięci. Najwięcej miejsca zajmują te dwie tajemnicze sekcje <__ctors_end> i <__vector_8>
  • REKLAMA
  • #15 1615137
    LuznyTomasz
    Poziom 15  
    Posty: 204
    Pomógł: 13
    Ocena: 1
    Nie moge zagłębić jeszcze tylko tej tajemnicy :) <__ctors_end>
  • #16 1633409
    LuznyTomasz
    Poziom 15  
    Posty: 204
    Pomógł: 13
    Ocena: 1
    Potrifi mi ktoś odpowiedzieć na pytanie co oznacza ostrzeżenie "array subscript has type char" ???
  • #17 1633420
    fantom
    Poziom 31  
    Posty: 1649
    Pomógł: 108
    Ocena: 42
    LuznyTomasz napisał:
    Potrifi mi ktoś odpowiedzieć na pytanie co oznacza ostrzeżenie "array subscript has type char" ???

    Jakbys podal linie kodu w ktorej to wyskakuje to by bylo super.
  • #18 1633438
    LuznyTomasz
    Poziom 15  
    Posty: 204
    Pomógł: 13
    Ocena: 1
    Typy zmiennych:
    unsigned int prog;
    unsigned char wynik[15];
    unsigned char tablica[100];
    unsigned int tetno;

    Miejsca generujące warninga:

    prog+=tablica[i];
    wynik[i]=wynik[i+1];
    tetno+=wynik[i];
    wynik[i]=0;
  • #19 1633449
    fantom
    Poziom 31  
    Posty: 1649
    Pomógł: 108
    Ocena: 42
    Prawdopodobnie dlatego ze prog i tetno sa typu int a elementy wynik i tablica typu char.Musisz zrobic rzutowanie na int zeby sie nie czepial.Cos w ten desen:
    
    prog += (int)tablica[i];
    itd.
    

    Dziwie sie natomiast czemu nie wyrzucil konkretniejszego warninga typu "you should cast ..."
  • #20 1633465
    LuznyTomasz
    Poziom 15  
    Posty: 204
    Pomógł: 13
    Ocena: 1
    " Warn if an array subscript has type "char". This is a common cause
    of error, as programmers often forget that this type is signed on
    specified, and that the conversions specified in the format string
    make sense. This includes standard functions, and others specified
    by format attributes, in the "printf", "scanf", "strftime" and
    "strfmon" (an X/Open extension, not in the C standard) families.

    The formats are checked against the format features supported by
    GNU libc version 2.2. These include all ISO C89 and C99 features,
    as well as features from the Single Unix Specification and some BSD
    and GNU extensions. Other library implementations may not support
    all these features; GCC does not support warning about features
    that go beyond a particular library's limitations. However, if
    -pedantic is used with -Wformat, warnings will be given about for-
    mat features not in the selected standard version (but not for
    "strfmon" formats, since those are not in any version of the C
    standard).

    -Wformat is included in -Wall. For more control over some aspects
    of format checking, the options -Wno-format-y2k, -Wno-for-
    mat-extra-args, -Wformat-nonliteral, -Wformat-security and -Wfor-
    mat=2 are available, but are not included in -Wall."

    Nie wiem czy ja dobrze rozumiem...ale czy to oznacza, że kompilator przypuszcza że zmienna ma być stringiem i tylko ostrzega mnie przed popełnieniem błędu?
  • #21 1633478
    LordBlick
    VIP Zasłużony dla elektroda
    Posty: 5438
    Pomógł: 549
    Ocena: 69
    Czepia się słuszne, bo czyta tablicę na szerokość int-a (co nieraz bywa przydatne, jeśli jest użyte świadomie), a nie jak ją zadeklarowano - char...
  • #22 1633535
    fantom
    Poziom 31  
    Posty: 1649
    Pomógł: 108
    Ocena: 42
    Light'I napisał:
    Czepia się słuszne, bo czyta tablicę na szerokość int-a (co nieraz bywa przydatne, jeśli jest użyte świadomie), a nie jak ją zadeklarowano - char...

    Co wedlug ciebie oznacza ze "czyta tablice na szerokosc int-a" ? Jakbys mogl przyklad podac bo albo ja zle to rozumiem albo ty zle napisales.
  • #23 1633557
    LuznyTomasz
    Poziom 15  
    Posty: 204
    Pomógł: 13
    Ocena: 1
    Więc jak wybrnąć z tej sytuacji?

    Edit: DObra już wiem o co chodzi. Wszystkie 4 linijki wykonywane były w pętli for(char i, i<z;i++)

    Błąd nie dotyczył typu tamtych zmiennych tylko zmiennej i.
  • #24 1633583
    fantom
    Poziom 31  
    Posty: 1649
    Pomógł: 108
    Ocena: 42
    LuznyTomasz napisał:
    Więc jak wybrnąć z tej sytuacji?

    Czy rzutowanie ktore podalem wyzej nie dziala ?
  • #25 1636205
    LuznyTomasz
    Poziom 15  
    Posty: 204
    Pomógł: 13
    Ocena: 1
    Ech...mam kolejny dziwaczny problem z moim programem:

    for(i=0;i<14;i++)
    {
    wynik[i]=wynik[i+1];
    // tetno+=wynik[i];
    }
    wynik[14]=okres;
    for(i=0;i<15;i++)
    {
    tetno=tetno+wynik[i];
    }

    Mam dwie pętne...niby niczym się nie różnią. Jednak pierwsza z nich działa poprawnie (przepisuje dane w tablicy wynik) natomiast druga z nich nie działa!!! mimo że tablica wyniki zawiera dane to zmienna tetno pozostaje bez zmian. Zrobiłem eksperyment i w pierwszą pętle (komentarz) włożyłem również operacje wykonywane w 2 pętli i.... wszystko ładnie się przepisuje.... O co chodzi? Kompilator robi mi jakiegoś psikusa?

    PS Próbowałem zmieniać typy zmiennych ale nic to nie dało.

    PS2 Może jednak to problem zmiennych? tetno=tetno+wynik[i]; nie chce się wykonać.
    unsigned char wynik
    unsigned int tetno
  • #26 1636246
    fantom
    Poziom 31  
    Posty: 1649
    Pomógł: 108
    Ocena: 42
    Wrzuc kawalek listingu assemblerowego z .lss dotyczacy tego kawalka kodu to zobaczymy co on tam wyrabia.Mozesz rowniez sprobowac wposmnianego wczesniej rzutowania na int bo typy sie roznia.W jednym z kompilatorow natrafilem kiedys na taki blad ze bez rzutowania traktowal liczbe jako 0.
  • #27 1636313
    LuznyTomasz
    Poziom 15  
    Posty: 204
    Pomógł: 13
    Ocena: 1
    W pliku lst jest mi się ciężko połapać bo cały program ma prawie 8k. Zastanawia mnie czy to nie jest problem indeksowania tablicy. Jeśli robie przypisanie tetno=tablica[0]; tetno+=tablica[1]... tylko w tej cholernej pętli nie chce się to wykonać. Zauważyłem że mimo iż w pętli wykonywana jest operacja "i++" to przy debugowaniu progarmu i jest zmniejszane!!!
  • #28 1636344
    fantom
    Poziom 31  
    Posty: 1649
    Pomógł: 108
    Ocena: 42
    Nie no nie pisz mi tu takich rzeczy.Funkcja search nie dziala czy jak ? Poza tym o ile dobrze kojarze to nie chodzi o plik .lst tylko .lss.
  • #29 1636851
    LuznyTomasz
    Poziom 15  
    Posty: 204
    Pomógł: 13
    Ocena: 1
    Po prostu nie potrafię wyszukać tego w miejsca...
    Po wielkich bojach i szukaniu błędu po omacku zaczęło "coś" mi działać.
    Wcześniej zrezygnowałem nawet z pętli for i próbowałem dane przepisywać w następujacy sposób:
    tetno=tetno+wynik[0];
    tetno=tetno+wynik[1];
    ...
    tetno+=wynik[15];

    do tętna zapisywała się jedynie wartość z wynik[0]. Jak dla mnie czary-mary choć nie do końca. W kompletnej desperacji zmieniem zmienną indeksującą tablicę na int (wcześniej był unsigned char):
    for(int k=0;k<16;k++)
    {
    tetno+=wynik[k];
    }
    czy zatem tablice należy numerować zmiennymi typu int? Czy to nie tu leży problem a mój progaram za chwile znowu się wysypie?
  • #30 1638119
    fantom
    Poziom 31  
    Posty: 1649
    Pomógł: 108
    Ocena: 42
    Nie wydaje mi sie aby byla taka koniecznosc.Ja sam jesli nie potrzebuje wiekszej rozdzielczosci uzywam do indeksowania unsigneg char coby zaoszczedzic na stosie.Byc moze znalazles jakiegos bug-a.Jedyne co mi przychodzi do glowy to porobic te zmienne typu volatile bo byc moze optymalizator sie wlacza do gry.Przeslij mi calego lss-a i podaj mi funkcje w ktorej wystepuje ta konstrukcja.

Podsumowanie tematu

LABEL_AI_GENERATED
Problem dotyczy zbyt dużego rozmiaru programu napisanego w języku C dla mikrokontrolera Atmega8, który ma obsługiwać wyświetlacz Nokia LCD oraz realizować funkcje pomiaru tętna i obliczania kalorii. Program zajmuje około 0xC00 (ok. 3072 bajtów) pamięci programu, co stanowi znaczną część dostępnej pamięci, a autor musi zmieścić dodatkową obsługę menu. Dyskusja koncentruje się na metodach optymalizacji kodu: usuwaniu nieużywanych funkcji z biblioteki NokiaLCD, zastępowaniu standardowych funkcji (np. itoa) własnymi, zmianie zmiennych globalnych na lokalne, eksperymentach z poziomami optymalizacji kompilatora GCC (WinAVR), oraz unikaniu powielania kodu. Wskazano, że biblioteki stdio.h i stdlib.h są duże i statycznie linkowane, co zwiększa rozmiar kodu, więc warto je zastąpić własnymi implementacjami. Problemy z rozmiarem zajmują także sekcje <__ctors_end> i <__vector_8> (przerwania). Poruszono także kwestie typów zmiennych i indeksowania tablic, gdzie zmienna indeksująca pętlę typu char powodowała ostrzeżenia kompilatora i błędy logiczne, a zmiana na int rozwiązała problem. Dyskutowano też o optymalizacji operacji arytmetycznych, np. zastąpieniu dzielenia i modulo prostszymi operacjami bitowymi. Wskazano, że kompilator może optymalizować kod w sposób nieoczekiwany, eliminując pozornie potrzebne instrukcje, jeśli wykryje błędy w logice programu. Ogólnie zalecane jest dokładne przeglądanie kodu, usuwanie zbędnych funkcji, stosowanie lokalnych zmiennych, eksperymentowanie z różnymi poziomami optymalizacji GCC oraz tworzenie własnych, lekkich funkcji pomocniczych zamiast standardowych bibliotek.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA