- LiTime Speicher und Akkus         
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 18

Thema: Feste Größe ändert sich beim Programmablauf (="Suchspiel" Memoryüberschneidung)

  1. #1
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.651

    Feste Größe ändert sich beim Programmablauf (="Suchspiel" Memoryüberschneidung)

    Anzeige

    Powerstation Test
    Bitte um Hilfe

    Die Größe int16_t tdek4 zur Dimensionierung einer Geschwindigkeitsrampe wird zu Beginn eines Programmslauf im main in einer Routine zur Dimensionierung verschiedener Größen mit einem Wert belegt und aktuell nicht weiter verwendet (wurde früher verwendet, aktuell inaktiv, wird später wieder benutzt) bis auf die hier erwähnte Ausgabe. Diese Größe belegt das Ende der dokumentierten Memorymap.

    Die Ausgabe der Größe in einer Liste zusammen mit anderen Werten zeigt unerklärliche Änderungen bei verschiedenen Ausgabeaufrufen >>obwohl<< sie, wie erwähnt, nur ein Mal mit einem festen Wert belegt wird. Sie nimmt dabei offensichtlich zufällige, soweit feststellbar stets andere Werte an. Auch ohne Aufruf der erwähnten Dimensionierungsroutine sind diese Schwankungen festzustellen.

    Die sinngleiche Größe tdek1 für eine andere Geschwindigkeit liegt in der memorymap weit entfernt; sie ist stabil. Auch die der tdek4 in der memorymap benachbarte Größe - die vor ihr liegt, zeigt nicht solche Veränderungen.

    Hier ein Auszug aus dem zugehörigen *.map-File, die "E E E.."-Einschübe markieren entfernte Passagen.

    Code:
    Archive member included because of file (symbol)
    E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E
    -------------------------------------------------------------
    Allocating common symbols
    Common symbol       size              file
    iyp12               0x2               R5MoCo.o
    kend1t1             0x2               R5MoCo.o
    E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E
    -------------------------------------------------------------
    m34vorlauf          0x2               R5MoCo.o
    nenc1               0x1               R5MoCo.o
    tdek4               0x2               R5MoCo.o                      <<==
    Memory Configuration
    Name             Origin             Length             Attributes
    text             0x00000000         0x00020000         xr
    data             0x00800060         0x0000ffa0         rw !x
    eeprom           0x00810000         0x00010000         rw !x
    fuse             0x00820000         0x00000400         rw !x
    lock             0x00830000         0x00000400         rw !x
    signature        0x00840000         0x00000400         rw !x
    *default*        0x00000000         0xffffffff
    Linker script and memory map
    Address of section .data set to 0x800100
    LOAD 
    E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E
    -------------------------------------------------------------
    c:/programme/winavr-20100110/bin/../lib/gcc/avr/4.3.3/../../../../avr/lib/avr5/crtm328p.o
                    0x000000a2                __vector_22
                    0x000000a2                __vector_12
                    0x000000a2                __bad_interrupt
                    0x000000a2                __vector_6
                    0x000000a2                __vector_3
                    0x000000a2                __vector_23
                    0x000000a2                __vector_25
                    0x000000a2                __vector_11
                    0x000000a2                __vector_13
                    0x000000a2                __vector_17
                    0x000000a2                __vector_5
                    0x000000a2                __vector_4
                    0x000000a2                __vector_9
                    0x000000a2                __vector_15
                    0x000000a2                __vector_10
                    0x000000a2                __vector_16
                    0x000000a2                __vector_20
     .text          0x000000a6     0x25d6 R5MoCo.o
                    0x00000430                TC2TMR_init
    E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E
    -------------------------------------------------------------
                    0x00000120                __vector_18
                    0x0000024a                itxt_rn
                    0x000002ee                init_twi_slave
     .text          0x0000267c        0x0 c:/programme/winavr-20100110/bin/../lib/gcc/avr/4.3.3/avr5\libgcc.a(_udivmodhi4.o)
     .text          0x0000267c        0x0 
    E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E
    -------------------------------------------------------------
     *(.fini0)
     .fini0         0x0000281e        0x4 c:/programme/winavr-20100110/bin/../lib/gcc/avr/4.3.3/avr5\libgcc.a(_exit.o)
     *(.fini0)
                    0x00002822                _etext = .
    .data           0x00800100      0x3b6 load address 0x00002822
                    0x00800100                PROVIDE (__data_start, .)
     *(.data)
     .data          0x00800100        0x0 c:/programme/winavr-20100110/bin/../lib/gcc/avr/4.3.3/../../../../avr/lib/avr5/crtm328p.o
     .data          0x00800100      0x3b6 R5MoCo.o
                    0x008004b3                Idelta1
                    0x008004a8                m12v
                    0x008004a9                m12z
    E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E
    -------------------------------------------------------------
                    0x008008a3                m34vorlauf
                    0x008008a5                nenc1
                    0x008008a6                tdek4                     <<==
                    0x008008a8                PROVIDE (__bss_end, .)
                    0x00002822                __data_load_start = LOADADDR (.data)
                    0x00002bd8                __data_load_end = (__data_load_start + SIZEOF (.data))
    .noinit         0x008008a8        0x0
                    0x008008a8                PROVIDE (__noinit_start, .)
     *(.noinit*)
                    0x008008a8                PROVIDE (__noinit_end, .)
                    0x008008a8                _end = .
                    0x008008a8                PROVIDE (__heap_start, .)
    .eeprom         0x00810000        0x0
     *(.eeprom*)
                    0x00810000                __eeprom_end = .
    .fuse
     *(.fuse)
     *(.lfuse)
     *(.hfuse)
     *(.efuse)
    Ich bitte um Hinweise woran es liegen könnte und wie ich das abstellen kann.

    Ist das RAM so voll, dass der Stackpointer überlauft?
    Wie könnte ich besser bzw. eindeutig feststellen, was die Ursache ist?

    Ich danke im Voraus für eure Tips und Hilfen.
    Ciao sagt der JoeamBerg

  2. #2
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    20.08.2008
    Ort
    Karlsruhe
    Alter
    36
    Beiträge
    1.225
    Zitat Zitat von oberallgeier Beitrag anzeigen
    Wie könnte ich besser bzw. eindeutig feststellen, was die Ursache ist?
    Kannst du uns den Quelltext zeigen? Der Fehler liegt vermutlich an anderer Stelle, es wäre ein großer Zufall wenn der Stack dir tdek4 "frisst" aber nenc1 verschont.

    Grüße,
    Markus
    Tiny ASURO Library: Thread und sf.net Seite

  3. #3
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.651
    Kannst du uns den Quelltext zeigen? Der Fehler liegt vermutlich an anderer Stelle ...
    Klar - im Prinzip. Aber sechstausend Zeilen Quelltext ist halt etwas viel . . . Vielleicht reichen diese Auszüge:

    Auszug main
    Code:
    // - - - - - - - - - - - - - - -
    // Ports+Pins als Ein- (0) oder Ausgänge (1) konfigurieren, Pull Ups (1) aktiv.
    //      A = Ausgang, E = Eingang ohne , EU = Eingang MIT PullUp
      DDRB  = 0b11111111;   // siehe aktuell oben oder Fortschrittsbericht
      PORTB = 0b00000000;   //    und Port/Pull Ups (1)  aktivieren
                            //
      DDRC  = 0b11000010;   // PC0 .. 6 , kein PC6+7-Pin bei m168/328 in THT
      PORTC = 0b00000000;   // PC0, ~2 und ~3 sind ADC-Eingänge ##>> OHNE Pullup !!
                            // 
      DDRD  = 0b11000000;   // RX+TX Eingang mit Pullup
      PORTD = 0b00111111;   //   Pull Ups aktivieren, mit pololuMot AUCH bei INT0/~1
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                            //
      for(i=0; i<10; i++)   // gLED2(PB5) blinken lassen bevor Interrupts erlaubt sind
      {                     //   um ungewollte Resets u.ä. besser erkennen zu können
        SetBit(PgLED, L1g); // gnLED1 schalten EIN, HELL, aktuelle PC1
        SetBit(PORTB,  3 ); // ###>>> TEST
        wms   (3);          // ###>>> Die onBoard-LEDs schalten A<->Portpin <<<###
        ClrBit(PgLED, L1g); // gnLED1 schalten AUS, Dunkel
        ClrBit(PORTB,  3 ); // ###>>> TEST
        wms   (97);         //
      }                     // Ende von for(i=0; i<10; i++)
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      Izthrznt      = 20000;        // Der ZeitHorizont für ISR(TIMER2_COMPA_vect)
    //ncx0          =   128;        // Messwert-Pointer auf "keine Messwerterfassung"
      ncxP          =   200;        // Prescaler für 1/100 sec bei Messwerterfassung
      ncxF          =     1;        // Messertflag; 1 <=> Wert darf gespeichert werden
      Izeit_1       = Izthrznt;     //
      Isecundn      = 1;    // Sekundenzähler, max 9 Stunden - NUR hier nullen
      TC2TMR_init(); // Init Timer/Cntr2-Interrupt 20 kHz/50 µsec           tmr
                            //   ISR gibt auf PB2 ein Servosignal aus
    // - - - - - - - - - - - - - - -//      Hier die notwendigen Werte für Motorbetrieb=Encoder, Regelfaktoren etc
    //        .. erforderlich VOR Initialisierung der externen Interrupts und Regelung
      nenc0         =    0; // Encoder-Prescaler, nur jeden nenc0-ten Übergang zählen
      nenc1         =    0;
      Kp12          =    1; // Regelfaktor P-Anteil !!! Divisor, lt fahrtest = 4 (1/4)
      Kp34          =    1; // Regelfaktor P-Anteil !!! Divisor ### war 5
      Ki12=Ki34     =   22; // Regelfaktor I-Anteil !!! Divisor
      Kd12=Kd34     =    4; // Regelfaktor D-Anteil !!! Divisor
    //ATSfak        = 1856; // AnTriebsStrang-faktor => Umrechnung von mm/s auf stupsi
      ATSfak        =  619; // AnTriebsStrang-faktor => Umrechnung von mm/s auf stupsi
      regel12=regel34 = 0;  // Ein-Ausschalter Regelung, regel = 1 => Regelung ist EIN
      rglsv12  = regel12; rglsv34  =  regel34;      // Regelflag, Sicherung
      XTI_0_1_init( );      // Init extINT 0 und 1                                 mot
      TC0CMPit();           // Init TmrCnt0 CmprMtchA, Regelungsaufruf 100Hz/Kanal tmr
      TC1PWM_init();        // Init Tmr/Cntr1 für PWMs/Mot12 + Mot34               mot
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      sei();  //Globalen Interrupt freigeben
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      inKOlst();            // Initialisierung, KOnstanten-Liste = div. Vorgaben   kal
                            // Aufruf NACH sei(), weil evtl irDME´s abgefragt werden.
      init_uart0 ( F_CPU / BAUD / 16 - 1 );  // Init UART0 (NICHT nach PDannegger)
      I2C_init ();          // I2C-Buffer initialisieren, I2C-Slave-Init           I2C
    // - - - - - - - - - - - - - - -
      wms ( 1000);          // Zeit fürs Startinfo - NUR FÜR TESTphase ! ! !
      info01();             // Startinfo über USART ausgeben                       main
    Auszug *com*.h
    Code:
      volatile s16  M12ocr; // temporärer Stellwert für OCR1A        -255...255
      volatile s16  M12inc; // vorzeichenbehaft. Incr, default:        -1, +1
      volatile s16  tdek1;  // Timer-Dekrement = Vorgabe für tmot1
      volatile s16  P4soll; // PWMsollwert bei Aufruf wird aus speed übernommen,
                            //   speed wird nicht weiter verwendet
      volatile s16  M34ocr; // temporärer Stellwert für OCR1A        -255...255
      volatile s16  M34inc; // vorzeichenbehaft. Incr, default:        -1, +1
      volatile s16  tdek4;  // Timer-Dekrement = Vorgabe für tmot4
    inKOlst
    Code:
    // ============================================================================== =
      void inKOlst (void)           // Initialisierungen
     {                              //
     //             war 50 bis 30. Dez. 2013
      tdek1         =    6;         // default Startwert PWM-Timer - wird dekrementiert
      tdek4         =    6;         // default Startwert PWM-Timer - wird dekrementiert
      return;                       //
     }                              //
    // ============================================================================== =
    Auszug Timer
    Code:
    // ============================================================================= =
    // ===  Nicht unterbrechbare ISR für timer2 =================================== */
    // Takt 20 Ips bei 20Mhz - Routine für regelmässige Abläufe mit 
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     ISR(TIMER2_COMPB_vect)         // Vekt 0x008, Timerroutine für "allgemeine Zwecke"
     {                              //   .. die nicht so eng zeitgebunden sind
    // - - - - - - - - - - - - - - - -
      Izeit_2 --;           //  ###>>> Izeit_2 ist aktuell int16_t ==>>
      if ( !Izeit_2 )       // WENN Izeit_2 != Null => wahr => Anweisung ausgeführen
      {                     // Eine Sekunde ist voll => Izeit_2 auf Hrznt_2 setzen
        Izeit_2 = Hrznt_2;  // ansonsten: Rückstellen auf Zeithorizont2
      }             // Ende if ( !Izeit_2 )
    // - - - - - - - - - - - - - - - -
    //      PWM-Rampe für Motor1/Mot12 - wird über tmoti/tdeki gesteuert
      if ( tmot1 )                          // Ist der Rampencounter != 0 ?
      {                                     //
        tmot1 --;                           // ... dann dekrementiere ihn bis
        if ( !tmot1 )                       // ... der Rampenwert abgelaufen ist
        {                                   //
          M12ocr    =  M12ocr + M12inc;     //##>>Übegang zu NEGATIVEn M12ocr möglich
    //      Es folgt Drehrichtungsumkehr NACH Nulldurchgang
    // war if (( M12ocr < 0) && (-1 == M12ocr)) Mrechtszur (); und sinngemäß //
          if (-1 == M12ocr) Mrechtszur ();  //
          if ( 1 == M12ocr) Mrechtsvor ();  //
    //      Setze OCR1A aus vorzeichenbehaftetem M12ocr
          if (M12ocr >= 0) OCR1A = M12ocr;  //
          else OCR1A = -1*M12ocr;           //
          if (M12ocr == P1soll) tmot1 = 0;  // Rampe12: Ende mit Sollwert erreicht
          else tmot1 = tdek1;               //   ansonsten ReInit Timer auf Rampenwert
        }                   // Ende if ( !tmot1 )
      }             // Ende von if ( tmot1 )
    // - - - - - - - - - - - - - - - -
    //      PWM-Rampe für Motor4/Mot34
      if ( tmot4 )                          // Rampencounter > 0
      {                                     //
        tmot4 --;                           //
        if ( !tmot4 )                       // Wenn Rampenwert abgelaufen ist
        {                                   //
          M34ocr    =  M34ocr + M34inc;     //##>>Übergang zu NEGATIVEn M34ocr möglich
    //      Es folgt Drehrichtungsumkehr NACH Nulldurchgang (siehe auch oben)
          if (-1 == M34ocr) Mlinksvor ();   //
          if ( 1 == M34ocr) Mlinkszur ();   //
    //      Setze OCR1A aus vorzeichenbehaftetem M34ocr
          if (M34ocr >= 0) OCR1B = M34ocr;  //
          else OCR1B = -1*M34ocr;           //
          if (M34ocr == P4soll) tmot4 = 0;  // Rampe34: Ende mit Sollwert erreicht
          else tmot4 = tdek4;               //   ansonsten ReInit Timer auf Rampenwert
        }                   // Ende if ( !tmot4 )
      }             // Ende von if ( tmot4 )
    // - - - - - - - - - - - - - - - -
      return;
     }       // Ende ISR(TIMER2_COMPA_vect)
    // ============================================================================= =

    Quelltext sprung (kplt) - hier wurde der falsche Wert entdeckt:
    Code:
    // ============================================================================= =
    // ==   Fahre Sprungfunktion, messe Sprungantwort       Aufruf aus r1n/do_MOSTL2
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      void sprung ( u8 m_buff[14] ) // Fahre Sprungfunktion, messe Sprungantwort
     {                              //
    // - - - - - - - - - - - - - - - -
    //char abc[12];                 // Übersetzungsfeld für Werteausgabe UART
      char s[10];                   // lok. String zum Dekodieren der SOLLFAHRT mm/sec
      s16   s16mot  = 0;            // SOLLfahrt Motor, 2 Bytes : unsigned int16_t
      u8    i       = 0;            // Variable
      u8    motNR;                  // MotorNummer 1 (mot12) oder 4 (mot34)
      u8    vz      = 0;            // Drehrichtungscode: 45 = li, 43 = re, 112 = aus
    // - - - - - - - - - - - - - - - -
    //      ncx0 wird mit Wert 255 im main initialisiert und damit "abgeschaltet"
    //      WENN ncx0 < 128 ist (erstes Bit ist 0) dann wird im Timer0 incrementiert
    //ncx0  =  255;                 // Initialisiere Pointer auf 1 vor Überlauf
    // - - - - - - - - - - - - - - - -
    //      Die aufrufenden Parameter als Kontrolle/Bestätigung auf UART ausgeben
      for ( i=0; i<9; i++) { s[i] = m_buff [i]; }  // Aufrufparameter kopieren
      s[9]         = 0;             // Markiere Stringende "0"=letzten Bitfeldelement
      uputs0 ("\r\t>>\t");uputs0 ( s );
    // - - - - - - - - - - - - - - - -
    //      Regelungen und sonstige Parameter abschalten:
      regel12  =  regel34  =  0;    // BEIDE REGELUNGen ausschalten
      
    // - - - - - - - - - - - - - - - -
    //      Dekodiere PWM-Vorzeichen und PWM-Stellwert
      vz    = m_buff[3];            // Drehrichtungscode: 45 = '-' => math neg
      for ( i=0; i<=2; i++) { s[i] = m_buff [i+3]; }  // im Byte 2 bis 5 {0-5}
      s[3]    = 0;                  // Markiere Stringende "0"  
      s16mot  = atoi ( s );         // vorzeichenbehafteter Motor-/PWM-Stellwert
    // - - - - - - - - - - - - - - - -
    //      Motor NR dekodieren und Daten melden
      motNR = m_buff[1] -  48;      // nmot ist die Motornummer 1 (12) oder 4 (34)
      if ( !(motNR == 1) && !(motNR == 4) ) return; // NUR mot12 oder mot34
      uputs0 ("\r\tmotNR "); uputs0i ( motNR );     // Nenne Motorkennung
      uputs0 ("\tSprung=> ");
      uputs0 ("\tPWM/tdek ");
      if ( s16mot < 0 ) s16mot = 0 - s16mot;        // s16mot MUSS positiv werden
    
    // - - - - - - - - - - - - - - - -
    //      Motor auswählen, einschalten und Test fahren; 
    //      Anmerkung: die Auswahl "5"<=> beide Motoren ist für die Messung der
    //      Sprungantwort nicht sinnvoll wegen der Datenerfassung
      switch ( motNR )              // Fallunterscheidung nach Motornummer
      {                             //
      case 1:                       // Anmerkung: ASCIIcode: 45 = '-' => math neg
        Mrechtsaus ();              // Zur Sprungaufnahme erstmal stoppen und
        wms ( 1000);                //      Auslauf abwarten
        uputs0i(s16mot);uputs0 ("/");uputs0i(tdek1);
        break;                      //
      case 4:                       //
        Mlinksaus ();               // Zur Sprungaufnahme erstmal stoppen und
        wms ( 1000);                //      Auslauf abwarten
        while ( Izeit_1 <= 15000 ) { }  // Nix tun, wenn Zeit zu kurz
        uputs0i(s16mot);uputs0 ("/");uputs0u(tdek4); // #####
        break;                      //
      default:
        break;
      }             // Ende switch ( motNR )
    //uputs0 ("\t\tMot=on");          // Gefahr von Zeitverzug beim Starten, daher
    //      diese Meldung lieber erstmal nicht ausgeben
    
    // - - - - - - - - - - - - - - - -
    //      Warten um nicht mit der Messung in einen Zeitüberlauf zu kommen
      while ( Izeit_1 <= 15000 ) { }        // Nix tun, wenn Zeit zu kurz, damit
                    //  die Messung nicht in einen Time-Überlauf läuft
    
    //      Fünf Messungen IM STILLSTAND VOR DEM MOTORSTART
      switch ( motNR )              // Fallunterscheidung nach Motornummer
      {                             //
      case 1:                       // Anmerkung: ASCIIcode: 45 = '-' => math neg
        for ( i = 0; i <  6; i++ )  //
        {                           //
          messdat1  [ i] = Izeit_1; // Zeit = volatile s16  messdat1..3[100]
          messdat2  [ i] = IencB0;  // s16 - Encoderstand
    //    messdat3  [ i] = OCR1A;   // PWM-Wert
          wms (   2);               // Ungefährer Messwert-Abstand
        }                   // Ende for ( i = 1; i < 100; i++ )
        if (vz==45) Mrechtszur ();  // Motortreiber 1 auf '+' math pos stellen
        else  Mrechtsvor ();        // Motortreiber 1 auf '-' math neg stellen
        OCR1A       = s16mot;       //
        break;              //
      case 4:                       //
        for ( i = 0; i <  6; i++ )  //
        {                           //
          messdat1  [ i] = Izeit_1; // Zeit = volatile s16  messdat1..3[100]
          messdat2  [ i] = IencB1;  // s16 - Encoderstand
    //    messdat3  [ i] = OCR1B;   // PWM-Wert
          wms (   2);               // Ungefährer Messwert-Abstand
        }                   // Ende for ( i = 1; i < 100; i++ )
        if (vz==45) Mlinksvor ();   // Motortreiber 4 auf '+' math pos stellen
        else  Mlinkszur ();         // Motortreiber 4 auf '-' math neg stellen
        OCR1B       = s16mot;       //
        break;                      //
      default:
        break;
      }             // Ende switch ( motNR )
    // - - - - - - - - - - - - - - - -
    // ####>>>>     Der Motor läuft jetzt, Daten also SOFORT beim Hochlaufen erfassen
      //              danach ne WEile warten !!! UND den Motor wieder ausschalten !!!
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    // Es werden jetzt die aktuellen Daten festgehalten für Messfahrt 
    //      Beispiel von ..C2\D01-3_40\D01-3_40_mot_x23.c vom 15. Oktober 2009, 11:12:46
    //      ##>> Der folgende, aktuelle Code ist neu gestaltet
      switch ( motNR )              // Fallunterscheidung nach Motornummer
      {                             //
      case 1:                       // Anmerkung: ASCIIcode: 45 = '-' => math neg
        for ( i = 6; i < 30; i++ )  //
        {                           //
          messdat1  [ i] = Izeit_1; // Zeit = volatile s16  messdat1..3[100]
          messdat2  [ i] = IencB0;  // s16 - Encoderstand
    //    messdat3  [ i] = OCR1A;   // PWM-Wert
          wms (   2);               // Ungefährer Messwert-Abstand
        }                   // Ende for ( i = 1; i < 100; i++ )
        break;              //
      case 4:                       //
        for ( i = 6; i <  30; i++ ) //
        {                           //
          messdat1  [ i] = Izeit_1; // Zeit = volatile s16  messdat1..3[100]
          messdat2  [ i] = IencB1;  // s16 - Encoderstand
    //    messdat3  [ i] = OCR1B;   // PWM-Wert
          wms (   2);               // Ungefährer Messwert-Abstand
        }                   // Ende for ( i = 1; i < 100; i++ )
        break;                      //
      default:
        break;
      }             // Ende switch ( motNR )
    
      switch ( motNR )              // Fallunterscheidung nach Motornummer
      {                             //
      case 1:                       // Anmerkung: ASCIIcode: 45 = '-' => math neg
        for ( i = 30; i < 100; i++ )  //
        {                           //
          messdat1  [ i] = Izeit_1; // Zeit = volatile s16  messdat1..3[100]
          messdat2  [ i] = IencB0;  // s16 - Encoderstand
    //    messdat3  [ i] = OCR1A;   // PWM-Wert
          wms (   4);               // Ungefährer Messwert-Abstand
        }                   // Ende for ( i = 1; i < 100; i++ )
        uputs0 ("\r\tiMessg\tIzeit_0\tIencB0\tOCR1A");
        break;              //
      case 4:                       //
        for ( i = 30; i < 100; i++ ) //
        {                           //
          messdat1  [ i] = Izeit_1; // Zeit = volatile s16  messdat1..3[100]
          messdat2  [ i] = IencB1;  // s16 - Encoderstand
    //    messdat3  [ i] = OCR1B;   // PWM-Wert
          wms (   4);               // Ungefährer Messwert-Abstand
        }                   // Ende for ( i = 1; i < 100; i++ )
        uputs0 ("\r\tiMessg\tIzeit_0\tIencB1\tOCR1B");
        break;                      //
      default:
        break;
      }             // Ende switch ( motNR )
    // - - - - - - - - - - - - - - - -
    //uputs0 ("\r\tiMessg\tIzeit_0\tIencB0");
      for ( i = 0; i < 100; i++ )
      {                             //
        uputs0 ("\r\t"); uputs0i ( i );
        uputs0 ("\t");   uputs0u (messdat1[i]);
        uputs0 ("\t");   uputs0u (messdat2[i]);
    //  uputs0 ("\t");   uputs0u (messdat3[i]);
      }                     // Ende for ( i = 0; i < 100; i++ )
      wms ( 2000);          // Warte Sprungantwort ab
      switch ( motNR )      // Motor aus mit Fallunterscheidung nach Motornummer
      {                     //
      case 1:               //
        Mrechtsaus ();      //                                                     mot
        break;
      case 4:               //
        Mlinksaus ();       //                                                     mot
        break;
      default:              //
        break;
      }             // Ende switch ( motNR )
      uputs0 ("\r\tSprungantwort steht\r");
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     }      // Ende void sprung ( void )
    // ============================================================================= =
    Ciao sagt der JoeamBerg

  4. #4
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    20.08.2008
    Ort
    Karlsruhe
    Alter
    36
    Beiträge
    1.225
    Hmm, interessant. Arbeitest du in der Ecke irgendwo mit Zeigern, von denen einer vielleicht das Ziel knapp verfehlt? Testweise könntest du noch eine weitere Variable nach tdek4 anlegen und Mal beobachten ob die auch betroffen ist.
    Wie sieht die Speichersituation auf dem AVR aus? Es gibt ein kleines Tool im RN-Wissen mit dem man auf eine Heap-Stack-Kollision prüfen kann: http://www.rn-wissen.de/index.php/Sp...en_mit_avr-gcc

    mfG
    Markus
    Tiny ASURO Library: Thread und sf.net Seite

  5. #5
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.651
    ... Arbeitest du ... irgendwo mit Zeigern ... Wie sieht die Speichersituation auf dem AVR aus? ...
    Markus - erstmal vielen Dank für Deine Mühe und Geduld.

    Zweitens: ich habe drei Messdaten-Felder, das dritte ist
    volatile s16 messdat3[100]; // Messwertspeicher für Tests

    Wenn das "an" ist, dann gibts:
    Program: 11224 bytes (34.3% Full)
    (.text + .data + .bootloader)
    Data: 1960 bytes (95.7% Full)
    (.data + .bss + .noinit)

    ... und die beschriebene Datenausgabepanne.

    Wenn ich dieses Feld streiche (und dessen Benutzung) dann gibts:
    Program: 11080 bytes (33.8% Full)
    (.text + .data + .bootloader)
    Data: 1762 bytes (86.0% Full)
    (.data + .bss + .noinit)

    ... und keine Datenausgabepanne. Nun müsste ich dem noch etwas mehr nachlaufen und schauen, ob vielleicht andere Daten noch korrumpiert sind. Mach ich im Moment nicht (faul, Zeitnot etc, Sprungfunktion läuft primstens - und ist fast erledigt) und daher

    Dank nochmal und ich höre mit dem Problem und dem leichten Verdacht auf irgendeinen Stacküberlauf auf.
    Ciao sagt der JoeamBerg

  6. #6
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    20.08.2008
    Ort
    Karlsruhe
    Alter
    36
    Beiträge
    1.225
    Zitat Zitat von oberallgeier Beitrag anzeigen
    Dank nochmal und ich höre mit dem Problem und dem leichten Verdacht auf irgendeinen Stacküberlauf auf.
    Leichter Verdacht? 1960 von 2048 Bytes belegt erklärt alles! Da küsst der Stack ziemlich sicher deine Daten. Die verbleibenden 88 Byte verknusperst du zum Frühstück mit irgendwelchen Funktionsargumenten, Stringarrays etc. (alleine im Kontext von sprung zähle ich grob überschlagen 29 Byte und ein ISR-Aufruf sichert alle genutzten Register, was auch mal 32 Bytes + Rücksprungadresse kosten kann).

    Tipp: Ich meine im Hinterkopf zu haben, dass statische Strings vom Compiler als Konstanten im RAM abgelegt werden. Du könntest also schon einiges an Speicher freimachen wenn du deine ganzen Strings im Flash ablegst (PROGMEM) und nur bei Bedarf in den RAM holst.

    mfG
    Markus
    Tiny ASURO Library: Thread und sf.net Seite

  7. #7
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.651
    Zitat Zitat von markusj Beitrag anzeigen
    ... alleine im Kontext von sprung zähle ich grob überschlagen 29 Byte und ein ISR-Aufruf sichert alle genutzten Register, was auch mal 32 Bytes + Rücksprungadresse kosten kann ...
    Danke - das ist mal wieder ein Abschnitt zur Programmierung, den ich ohne solche Bemerkungen (sprich ohne einen Leitfaden) garnicht angehen kann. Deshalb freue ich mich darüber - weil ich damit wenigstens ne Chance habe mich sinnvoll durchzudenken.

    Zitat Zitat von markusj Beitrag anzeigen
    ... im Hinterkopf ... dass statische Strings ... im RAM abgelegt werden ...
    Genau. Anfangs hatte ich einige im EEPROM. In meinem Servotester hatte ich festgestellt, dass merkbar lange Zugriffzeiten möglich sind, die mich dort das eine oder andere Mal wirklich gestört hatten. Deshalb sind hier die Strings (noch) im RAM - und ich war haarscharf dran, den 328er durch einen 1284er zu ersetzen - obwohl das ne neue Platine bedeutet hätte. Wenn ich über die Testphase drüber bin, dann gehen etliche Strings raus oder werden zurückgestutzt; der wesentliche Anteil davon sind Bemerkungen die für den laufenden (autonomen) Betrieb weniger bis gar keine Bedeutung haben. Da ich ausserdem das Thema PROGMEM immer noch als böhmisches Dorf vor mir herschiebe und meinem Zeitplan hinterherhinke bin ich über diese ramfressende Methode nicht hinausgekommen.

    Danke für Deine Unterstützung.
    Ciao sagt der JoeamBerg

  8. #8
    Erfahrener Benutzer Roboter-Spezialist Avatar von sast
    Registriert seit
    30.11.2004
    Alter
    53
    Beiträge
    502
    Hallo Joe,

    das mit dem Progmem ist kinderleicht und bewahrt einen wirklich vor bösen Überraschungen. Ich hab hier mal ein kleines Beispiel, wie ich das implementiert habe um Statusmeldungen auszugeben.
    Code:
    int main(void)
    {
    unsigned char actual_page = 0;
    char main_text[20];
    ...
    get_str_from_flash(6, main_text);//"Menue 4"
    tp_write_statusbar(&tp, main_text);
    ...
    Die flash_mem.c:
    Code:
    #include <stdint.h>
    #include <avr/pgmspace.h>
    #include <string.h>
    
    #include "main.h"
    #include "flash_mem.h"
    
    const char str1[] PROGMEM = "INFO allgemein";
    const char str2[] PROGMEM = "              ";//14 Leerzeichen
    const char str3[] PROGMEM = "Menue 1";
    const char str4[] PROGMEM = "Menue 2";
    const char str5[] PROGMEM = "Menue 3";
    const char str6[] PROGMEM = "Menue 4";
    const char str7[] PROGMEM = "Menue 5";
    ...
    
    const char *strarray1[] PROGMEM = {
        str1,
        str2,
        str3,
        str4,
        str5,
        str6,
        str7,
        str8,
        str9,
        str10,
        str11,
        str12,
    ...
    };
    
    void get_str_from_flash(uint16_t strnum, char* str)
    {
    if(strnum>0)strcpy_P(str, (const char*)(pgm_read_word(&(strarray1[strnum-1]))));
    else strcpy(str, "Invalid number!");
    }
    und in der flash_mem.h steht nur:
    Code:
    #ifndef _MEM_FLASH_H_
    #define _MEM_FLASH_H_
    
    extern void get_str_from_flash(uint16_t strnum, char* str);
    
    #endif  /* _MEM_FLASH_H_ */
    Geändert von sast (21.01.2014 um 15:38 Uhr)

    雅思特史特芬
    开发及研究

  9. #9
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    20.08.2008
    Ort
    Karlsruhe
    Alter
    36
    Beiträge
    1.225
    Zitat Zitat von sast Beitrag anzeigen
    das mit dem Progmem ist kinderleicht und bewahrt einen wirklich vor bösen Überraschungen. Ich hab hier mal ein kleines Beispiel, wie ich das implementiert habe um Statusmeldungen auszugeben.
    Leider nicht ganz, da das Timing in dem Fall sich verändert. Der EEPROM ist noch langsamer im Zugriff als der Flash, aber bei timingkritischen Anwendungen ist das eben ein relevanter Faktor. Außerdem: Warum so umständlich mit der zusätzlichen Zeigertabelle? Um von den zwei Byte des Pointers ein Byte einzusparen im Tausch gegen schlecht zu debuggende "Magic Numbers"? In dem Fall wäre es ratsam, anstatt der Zahlenwerte einen enum zu nutzen.

    mfG
    Markus
    Tiny ASURO Library: Thread und sf.net Seite

  10. #10
    Erfahrener Benutzer Roboter-Spezialist Avatar von sast
    Registriert seit
    30.11.2004
    Alter
    53
    Beiträge
    502
    Markus könntest du das mal bitte an einem konkreten Beispiel zeigen, was du meinst?

    Danke
    sast

    雅思特史特芬
    开发及研究

Seite 1 von 2 12 LetzteLetzte

Ähnliche Themen

  1. per TV-remote ein "move" programmablauf auslösen..
    Von carlitoco im Forum Robby RP6
    Antworten: 4
    Letzter Beitrag: 01.04.2008, 21:59
  2. Stecker in "Computer-Größe"
    Von danst im Forum Elektronik
    Antworten: 1
    Letzter Beitrag: 13.01.2007, 16:19
  3. "Leser stellen sich vor" - Was haltet ihr davon?
    Von Florian im Forum Umfragen
    Antworten: 31
    Letzter Beitrag: 17.03.2006, 17:52
  4. IO-Pins lassen sich nicht richtig mit "bsf"/"
    Von keiang im Forum PIC Controller
    Antworten: 3
    Letzter Beitrag: 21.07.2005, 20:12
  5. AT90S2313 - RX-Interupt - Der "hängt sich auf"
    Von Gottfreak im Forum AVR Hardwarethemen
    Antworten: 10
    Letzter Beitrag: 14.05.2004, 00:32

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

LiFePO4 Speicher Test