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

[Atmega16/32][C] Zawieszanie, zapętlanie się programu a stos

rsikon 22 Paź 2008 11:47 2191 8
  • #1 5656829
    rsikon
    Poziom 26  
    Witam, w sumie nie używam w programie komendy gosub.

    Czy wywoływanie procedur (podprogramów) może powodować zapętlanie się programu, przepełnienie stosu i w skutek tego zwieszanie, resetowanie?

    Czy wywołanie tego typu:

    podprogram();

    wymaga jakiegoś specjalnego "wyskoczenia"? (odpowiednik return w gosub)


    Jak to sprawdzić - ten stos, jak go zresetować?

    Radzio
  • #3 5656867
    rsikon
    Poziom 26  
    A może kolega ciut jaśniej?

    Duże zagnieżdzenie to? 10 czy 100 podprogramów :)

    Radzio
  • #4 5656935
    szelus
    Poziom 34  
    Podprogramy w C zwykło nazywać się funkcjami. Każde wywołanie funkcji potrzebuje miejsca na stosie, co najmniej na adres powrotu, ale zwykle również na przechowanie rejestrów i lokalne zmienne. W avr-gcc normalnie cała pamięć nie wykorzystana na zmienne globalne i statyczne jest dostępna na stos.
    Podsumowując, nie da się powiedzieć, w ogólnym przypadku, ile poziomów zagłębienia spowoduje przepełnienie stosu. Wszystko zależy od konkretnego programu.
  • #5 5656970
    rsikon
    Poziom 26  
    Zakładając, że problem jest z przepełnieniem stosu - jak temu przeciwdziałać?

    Czy tylko i wyłącznie "przemyslana" konstrukcja programu?

    Radzio
  • #6 5657057
    szelus
    Poziom 34  
    Niestety...

    Sprawdź, ile wykorzystujesz RAMu na zmienne globalne (łączny rozmiar sekcji data i bss raportowany przez kompilator) - będziesz wiedział, ile Ci zostało na stos.
  • #7 5657082
    rsikon
    Poziom 26  
    program zajmuje....

    max całe 3,6% :)

    taki prosty programik:

    
    
    // Testowanie timera 2
    
    
    #define F_CPU 8000000UL
    #include <inttypes.h>
    #include <lcd.h>
    #include <avr/io.h>                // dostęp do rejestrów
    #include <avr/interrupt.h>        // funkcje sei(), cli()
    
    int b=0;
    char buff[3];
    volatile uint8_t opoznienie;        // zmienna określająca częstotliwość
    uint32_t sss=0;
    
    
    SIGNAL (SIG_OVERFLOW2)                // przerwanie od przepełnienia
    {
      TCNT2 = opoznienie;                 // przeładuj TIMER2
      b++;
     if (b==46) {
    PORTD ^= _BV(5);
    b=0;
    sss++;
    if (sss>86399) sss=0;
    }
    }
    
    
    
    
    
    
    void godzina(int wx, int wy)
    {
    
        LCD_xy(wx,wy);
    	write_text(itoa(sss/3600,buff,10));
    	write_text(":");
    	write_text(itoa(sss/60-(sss/3600*60),buff,10));
    	write_text(":");
    	write_text(itoa(sss-(sss/60*60),buff,10));
    	write_text(" ");
    
    }
    
    
    
    int main(void)                        // program główny
    {
    LCD_init();
    LCD_clr();
    
    DDRD=0xFF;		// cały port C jako wyjscie
    PORTD=0x00;
    
    
    
    
      opoznienie = 0x55;                        // domyślna wartość dla TIMERA2
      
      
      
      
      TIMSK=_BV(TOIE2);         // włącz przerwania od przepełnienia 
      TCNT2=opoznienie;                         // zainicjuj TIMER2
      TCCR2=_BV(CS20)|_BV(CS21)|_BV(CS22); // czasomierz 2 taktowany F_CPU/1024
    
     
     
     
     
     
     
      sei();                        // włącz obsługę przerwań
      while(1)                        // pętla nieskończona
      {
    
        godzina(0,0);
    
    
      }
    }
    
    
    
  • #8 5657176
    szelus
    Poziom 34  
    Taa....

    sss powinno być zadeklarowane jako volatile, bo jest używane w przerwaniu i poza. To od razu uwidoczniłoby, że efekty obliczeń w funkcji godzina są nieprzewidywalne, bo sss może się zmienić w każdym momencie. W związku z tym, wyliczony przez itoa() łańcuch może być dłuższy niż dwa znaki i może nie mieścić się w buforze zajeżdżając pamięć.
    Pomijając nieefektywność wielokrotnego powtarzania tych samych operacji w funkcji godzina(), przede wszystkim zadeklaruj sss jako volatile a w funkcji godzina() zrób kopię i tej kopii używaj do obliczeń.

    Na przepełnienie stosu to zupełnie nie wygląda...
  • #9 5659026
    rsikon
    Poziom 26  
    Wprowadzenie zmiennych volatile ciut pomogło - tak mi się zdaje, jednak układ i tak nie działał idealnie, wieszał się.

    Zmiana układu na Atmega16 (z przekompilowaniem programu oczywiscie) pomogła w 100%.

    Najwidoczniej poprzedni układ jest coś do bani.

    Radzio
REKLAMA