www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Stacktiefe AVR-Controller


Autor: Matthias Kölling (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

gibt es ein Tool, dass durch statische Codeanalyse die maximale 
Stacktiefe für AVR-Controller berechnen kann?

Gruß Matthias

Autor: Jens (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
warum simulierst Du das nicht im AVR-Studio?

mfg Jens

Autor: Benedikt K. (benedikt) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Matthias Kölling wrote:
> gibt es ein Tool, dass durch statische Codeanalyse die maximale
> Stacktiefe für AVR-Controller berechnen kann?

Ja -> Beitrag "StackViewer (RAM Rechner) für WinAVR"

Autor: Jens (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Benedikt K.

kann man mit Deinem Tool wirklich zu jedem Zeitpunkt
die Stack-Tiefe berechnen? Halte ich für ein Gerücht!
Dieses ist warscheinlich genau so unmöglich wie die exakte
Laufzeit einens Programmes zu berechnen. (Interrupts, ...)

mfg Jens

Autor: Matthias Kölling (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok,

das ist ja wirlich ein süßes Tool.
Aber die Probleme hören damit nicht auf. Wieso meldet es 9 errors, 0 
Warnings. Leider hat Benedikt nichts dazu in seiner Anleitung 
geschrieben.

Die "total RAM usage" ist aber laut Tool kleiner als der vorhandene RAM, 
trotzdem macht mein Teil resets...
Grübel, Grübel...

Gruß Matthias

Autor: Benedikt K. (benedikt) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jens wrote:
> kann man mit Deinem Tool wirklich zu jedem Zeitpunkt
> die Stack-Tiefe berechnen?

Ja, bis auf die Einschränkungen die dabei stehen.

> Halte ich für ein Gerücht!

Dann probiers aus.

> Dieses ist warscheinlich genau so unmöglich wie die exakte
> Laufzeit einens Programmes zu berechnen. (Interrupts, ...)

Es ist eine worst case Betrachtung, die solange funktioniert, bis 
irgendwelche Dinge auftreten die erst zur Laufzeit entschieden werden, 
wie rekursive Funktionen, IJMPs usw.
Klar, man kann Konstruktionen bauen, bei denen das Programm falsche 
Werte liefern wird, aber für praxisübliche Programme sollte der Wert 
doch relativ gut hinkommen.

Matthias Kölling wrote:
> das ist ja wirlich ein süßes Tool.
> Aber die Probleme hören damit nicht auf. Wieso meldet es 9 errors, 0
> Warnings. Leider hat Benedikt nichts dazu in seiner Anleitung
> geschrieben.

Ein Error heißt, dass irgendwas nicht so läuft wie es soll (ich habe aus 
Gründen der Einfachheit viele Annahmen getroffen).
Könntest du mal die lss und die elf Datei posten? Dann schau ich mir das 
mal an und versuche die Fehler zu beheben.
Das Programm ist alles andere als ausgereift, aber ich musste einen 
Kompromiss aus Zeit die ich dafür investieren wollte und Gründlichkeit 
machen.

Autor: Jens (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Matthias Kölling

lass es!

schreib Dir eine Routine, die
Du in den verdächtigen Programmteilen aufrufst,
die über irgendwas (LCD, RS232 ...) den Stackpointer
ausgibt. Oder die Routine merkt sich den Tiefsten
Stackpointer im RAM, den Du irgend wie abfragst.

Wenn Du den Stack-Verbrauch hast, rechne noch ein paar
Prozent dazu, dann bist Du auf der sicheren Seite.

Autor: Matthias Kölling (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Benedikt,

die Hilfe nehme ich doch gerne an! Aus Deinen Sourcen und dem 
Ausgabefile habe ich inzwischen rausbekommen, dass der Fehler "unknown 
function" mehrmals auftritt.

Gruß Matthias

Autor: Jens (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Benedikt K.

>> Dieses ist warscheinlich genau so unmöglich wie die exakte
>> Laufzeit einens Programmes zu berechnen. (Interrupts, ...)

>Es ist eine worst case Betrachtung, die solange funktioniert, bis
>irgendwelche Dinge auftreten die erst zur Laufzeit entschieden werden,
>wie rekursive Funktionen, IJMPs usw.
>Klar, man kann Konstruktionen bauen, bei denen das Programm falsche
>Werte liefern wird, aber für praxisübliche Programme sollte der Wert
>doch relativ gut hinkommen.

.. und die "praxisübliche Programme" entstehen bei mir bei
der Entwicklung in Serie. :)

Autor: Benedikt K. (benedikt) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Den Ursache für die Fehler habe ich gefunden, ich muss nur noch 
rausfinden, was der Compiler damit bezweckt:

     90c:  0f 93         push  r16
     90e:  1f 93         push  r17
     910:  df 93         push  r29
     912:  cf 93         push  r28
     914:  00 d0         rcall  .+0
     916:  00 d0         rcall  .+0

Kann mir jemand verraten, welchen Sinn "rcall .+0" hat?

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Benedikt K. wrote:

> Kann mir jemand verraten, welchen Sinn "rcall .+0" hat?

Platz auf dem Stack schaffen für lokale Variablen?

Autor: Jens (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
in ASM gibs das nicht

> rcall .+0

.+0 wäre ein Label das in ASM nicht zulässig ist!

mfg Jens

Autor: Jens (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Legend:
        r   any register
        d   `ldi' register (r16-r31)
        v   `movw' even register (r0, r2, ..., r28, r30)
        a   `fmul' register (r16-r23)
        w   `adiw' register (r24,r26,r28,r30)
        e   pointer registers (X,Y,Z)
        b   base pointer register and displacement ([YZ]+disp)
        z   Z pointer register (for [e]lpm Rd,Z[+])
        M   immediate value from 0 to 255
        n   immediate value from 0 to 255 ( n = ~M ). Relocation 
impossible
        s   immediate value from 0 to 7
        P   Port address value from 0 to 63. (in, out)
        p   Port address value from 0 to 31. (cbi, sbi, sbic, sbis)
        K   immediate value from 0 to 63 (used in `adiw', `sbiw')
        i   immediate value
        l   signed pc relative offset from -64 to 63
        L   signed pc relative offset from -2048 to 2047
        h   absolute code address (call, jmp)
        S   immediate value from 0 to 7 (S = s << 4)
        ?   use this opcode entry if no parameters, else use next opcode 
entry

     1001010010001000   clc
     1001010011011000   clh
     1001010011111000   cli
     1001010010101000   cln
     1001010011001000   cls
     1001010011101000   clt
     1001010010111000   clv
     1001010010011000   clz
     1001010000001000   sec
     1001010001011000   seh
     1001010001111000   sei
     1001010000101000   sen
     1001010001001000   ses
     1001010001101000   set
     1001010000111000   sev
     1001010000011000   sez
     100101001SSS1000   bclr    S
     100101000SSS1000   bset    S
     1001010100001001   icall
     1001010000001001   ijmp
     1001010111001000   lpm     ?
     1001000ddddd010+   lpm     r,z
     1001010111011000   elpm    ?
     1001000ddddd011+   elpm    r,z
     0000000000000000   nop
     1001010100001000   ret
     1001010100011000   reti
     1001010110001000   sleep
     1001010110011000   break
     1001010110101000   wdr
     1001010111101000   spm
     000111rdddddrrrr   adc     r,r
     000011rdddddrrrr   add     r,r
     001000rdddddrrrr   and     r,r
     000101rdddddrrrr   cp      r,r
     000001rdddddrrrr   cpc     r,r
     000100rdddddrrrr   cpse    r,r
     001001rdddddrrrr   eor     r,r
     001011rdddddrrrr   mov     r,r
     100111rdddddrrrr   mul     r,r
     001010rdddddrrrr   or      r,r
     000010rdddddrrrr   sbc     r,r
     000110rdddddrrrr   sub     r,r
     001001rdddddrrrr   clr     r
     000011rdddddrrrr   lsl     r
     000111rdddddrrrr   rol     r
     001000rdddddrrrr   tst     r
     0111KKKKddddKKKK   andi    d,M
     0111KKKKddddKKKK   cbr     d,n
     1110KKKKddddKKKK   ldi     d,M
     11101111dddd1111   ser     d
     0110KKKKddddKKKK   ori     d,M
     0110KKKKddddKKKK   sbr     d,M
     0011KKKKddddKKKK   cpi     d,M
     0100KKKKddddKKKK   sbci    d,M
     0101KKKKddddKKKK   subi    d,M
     1111110rrrrr0sss   sbrc    r,s
     1111111rrrrr0sss   sbrs    r,s
     1111100ddddd0sss   bld     r,s
     1111101ddddd0sss   bst     r,s
     10110PPdddddPPPP   in      r,P
     10111PPrrrrrPPPP   out     P,r
     10010110KKddKKKK   adiw    w,K
     10010111KKddKKKK   sbiw    w,K
     10011000pppppsss   cbi     p,s
     10011010pppppsss   sbi     p,s
     10011001pppppsss   sbic    p,s
     10011011pppppsss   sbis    p,s
     111101lllllll000   brcc    l
     111100lllllll000   brcs    l
     111100lllllll001   breq    l
     111101lllllll100   brge    l
     111101lllllll101   brhc    l
     111100lllllll101   brhs    l
     111101lllllll111   brid    l
     111100lllllll111   brie    l
     111100lllllll000   brlo    l
     111100lllllll100   brlt    l
     111100lllllll010   brmi    l
     111101lllllll001   brne    l
     111101lllllll010   brpl    l
     111101lllllll000   brsh    l
     111101lllllll110   brtc    l
     111100lllllll110   brts    l
     111101lllllll011   brvc    l
     111100lllllll011   brvs    l
     111101lllllllsss   brbc    s,l
     111100lllllllsss   brbs    s,l
     1101LLLLLLLLLLLL   rcall   L
     1100LLLLLLLLLLLL   rjmp    L
     1001010hhhhh111h   call    h
     1001010hhhhh110h   jmp     h
     1001010rrrrr0101   asr     r
     1001010rrrrr0000   com     r
     1001010rrrrr1010   dec     r
     1001010rrrrr0011   inc     r
     1001010rrrrr0110   lsr     r
     1001010rrrrr0001   neg     r
     1001000rrrrr1111   pop     r
     1001001rrrrr1111   push    r
     1001010rrrrr0111   ror     r
     1001010rrrrr0010   swap    r
     00000001ddddrrrr   movw    v,v
     00000010ddddrrrr   muls    d,d
     000000110ddd0rrr   mulsu   a,a
     000000110ddd1rrr   fmul    a,a
     000000111ddd0rrr   fmuls   a,a
     000000111ddd1rrr   fmulsu  a,a
     1001001ddddd0000   sts     i,r
     1001000ddddd0000   lds     r,i
     10o0oo0dddddbooo   ldd     r,b
     100!000dddddee-+   ld      r,e
     10o0oo1rrrrrbooo   std     b,r
     100!001rrrrree-+   st      e,r
     1001010100011001   eicall
     1001010000011001   eijmp

es existiert kein Op-Code bei AVR mit 0x00d0

mfg Jens

Autor: Benedikt K. (benedikt) (Moderator)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Stefan Ernst wrote:

> Platz auf dem Stack schaffen für lokale Variablen?

Stimmt. Wenn ich mir das so überlege, macht es sogar Sinn:
1 Befehl der 3 Takte braucht und 2 Bytes auf dem Stack schafft.
2x push würde dasselbe bewirken, wäre aber doppelt so groß und würde 1 
Takt länger brauchen.

Solche Zweckentfremdungen sind natürlich auch ein Hindernis für die 
Stackanalyse.

Ich habe mal eine neue Version angehängt. Damit läuft das Programm mit 0 
Fehlern und Warnungen durch. Ich vermute mal du verwendest einen mega128 
oder irgendwas in der Richtung mit 4kByte SRAM. Falls ja, dann kann man 
davon ausgehen, dass das Problem nicht am Stack liegt wenn der AVR 
neustartet.

Vielleicht ein Pointer der durcheinander kommt, oder ein ausgelöster 
Interrupt ohne passenden Interrupthandler?


Jens wrote:

> es existiert kein Op-Code bei AVR mit 0x00d0

Vertausch mal die Bytes, dann wird 0xd000 draus: 1101000000000000
Und das ist das hier:
1101LLLLLLLLLLLL   rcall   L
-> rcall 0

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Jens:

Denk dran: Little Endian.
Speicher 0x000d -> Opcode 1101000000000000 -> rcall mit Offset 0

Und dass der von dir verwendete Assembler ein .+0 nicht als Label 
akzeptiert, spielt absolut keine Rolle. Null ist als Offset trotzdem 
erlaubt.

Autor: Jens (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Benedikt K.

>Vertausch mal die Bytes, dann wird 0xd000 draus: 1101000000000000

ich Dummkopf hab das über sehen.

der Macht wirklich ein Warm-Start (Reset) :)

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jens wrote:

> der Macht wirklich ein Warm-Start (Reset) :)

Ernst gemeint oder Scherz?
Da ich den möglichen Scherz irgendwie nicht sehe, befürchte ich fast 
Ersteres. Die Null ist ein relativer Offset, keine absolute Adresse.

Autor: Jens (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>der Macht wirklich ein Warm-Start (Reset) :)

quatsch der ruft sich selst auf auf eigener Adresse auf
und verursacht dadurch eine Stack-Überlauf!

Autor: Matthias Kölling (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

das ist ja interessant! Heißt das, dass mir der Compiler einen reset 
einbaut???
Dann müßte er doch aber immer kommen, wenn die Funktion aufgerufen wird. 
Dieses Verhalten sehe ich aber nicht. Statt dessen läuft das Programm 
eine Weile normal. Ich compiliere jetzt noch mal die Version, wo der 
reset nicht aufgetreten ist und schau mir das .lss File noch mal an.
Danke erst mal!

Gruß Matthias

Autor: Jens (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
edit:

quatsch der ruft sich selbst, auf eigener Adresse auf
und verursacht dadurch einen Stack-Überlauf!

sorry Jens

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Matthias Kölling wrote:

> das ist ja interessant! Heißt das, dass mir der Compiler einen reset
> einbaut???

Hör nicht auf Jens, der schreibt hier nur Blödsinn.
Was der Compiler da macht, ist absolut korrekt.

Autor: Jens (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Stefan Ernst

label:
   rcall Label


;der schreibt nur Blödsinn

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>quatsch der ruft sich selbst, auf eigener Adresse auf
>und verursacht dadurch einen Stack-Überlauf!

Bevor du solche Enten in die Welt setzt, solltest dich mal informieren, 
von welcher Adresse aus der Offset berechnet wird.

MfG Spess

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jens wrote:

> label:
>    rcall Label

Das ist aber kein rcall mit Offset 0, sondern mit Offset -2 oder -1, je 
nachdem, ob du es lieber byte- oder wortweise betrachtest.

Autor: Jens (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok

rcall 0
rcall 0

wie oft kann mann rcall 0 nacheinander aufrufen bis der RAM
voll ist (ohne ret)?

mfg Jens

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> wie oft kann mann rcall 0 nacheinander aufrufen bis der RAM
> voll ist (ohne ret)?

Herrgott, am Ende der Funktion wird der Stackpointer dann wieder 
korrigiert, entweder mit Pops oder mit einer Addition auf den 
Stackpointer.

Autor: Benedikt K. (benedikt) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan Ernst wrote:
> Herrgott, am Ende der Funktion wird der Stackpointer dann wieder
> korrigiert

Genau:

Anfang:
     90a:  ff 92         push  r15
     90c:  0f 93         push  r16
     90e:  1f 93         push  r17
     910:  df 93         push  r29
     912:  cf 93         push  r28
     914:  00 d0         rcall  .+0
     916:  00 d0         rcall  .+0

Ende:
     cba:  0f 90         pop  r0
     cbc:  0f 90         pop  r0
     cbe:  0f 90         pop  r0
     cc0:  0f 90         pop  r0
     cc2:  cf 91         pop  r28
     cc4:  df 91         pop  r29
     cc6:  1f 91         pop  r17
     cc8:  0f 91         pop  r16
     cca:  ff 90         pop  r15

Autor: Jens (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Stefan Ernst

>Herrgott, am Ende der Funktion wird der Stackpointer dann wieder
>korrigiert, entweder mit Pops oder mit einer Addition auf den
>Stackpointer.

und wo steht das

>     90c:  0f 93         push  r16
>     90e:  1f 93         push  r17
>     910:  df 93         push  r29
>     912:  cf 93         push  r28
>     914:  00 d0         rcall  .+0
>     916:  00 d0         rcall  .+0

gerade die Zeilen:

     914:  00 d0         rcall  .+0
     916:  00 d0         rcall  .+0

.. gefallen mir "Nop"s mit 3-Takt-Zyklen + 3 fürs "Popen" wenns
   vorhanden

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jens wrote:

> .. gefallen mir "Nop"s mit 3-Takt-Zyklen + 3 fürs "Popen" wenns
>    vorhanden

Hast du irgendwie Langeweile?
Der Zweck ist doch längst geklärt. Hier wird auf sparsame Weise ein 
Stackframe erzeugt.

Autor: Matthias Kölling (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

um die Wogen etwas zu glätten:
Das Listfile ist an dieser Stelle bei beiden Varianten(funktionierend, 
nichtfunktionierend) identisch.
Was ich machen will ist ein scan einer Verzeichnisstruktur auf einer 
SD-card. Ich hatte diese Woche dazu schon einen Thread.
Ich habe mir wirklich einen abgebrochen, den Algorithmus hinzubekommen.
Wenn ich jetzt die Ausgabe auf der UART mache erfolgt nach dem scan 
genau 1 Reset. Nach dem zweiten Mal ist Ruhe?!
Wenn ich das Ergebnis in eine Datei schreibe, wird der scan irgendwo 
durch einen reset unterbrochen und das Ganze wiederholt sich.
Es scheint wohl etwas beim Schreiben in die Datei schiefzugehen. Das 
kann ich ja eruieren.
Komisch ist der erstere Fall.
Jetzt habe ich auch festgestellt, dass manchmal auch ein reset nach der 
Willkommensbotschaft, die als erste in der main verschickt wird, ein 
reset auftritt. Und da sollte noch kein Stack übergelaufen sein?!
Danke soweit!

Gruß Matthias

Autor: Jens (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Autor: Matthias Kölling (Gast)
>Datum: 09.01.2009 17:27

>Hallo,

>gibt es ein Tool, dass durch statische Codeanalyse die maximale
>Stacktiefe für AVR-Controller berechnen kann?

>Gruß Matthias


das war der Ausgang.

ich wollte nur helfen. Jens

Autor: Benedikt K. (benedikt) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Matthias Kölling wrote:

> Jetzt habe ich auch festgestellt, dass manchmal auch ein reset nach der
> Willkommensbotschaft, die als erste in der main verschickt wird, ein
> reset auftritt. Und da sollte noch kein Stack übergelaufen sein?!

Eher unwarscheinlich, außer du hast mehr globale Variablen als RAM 
vohanden ist.
Bleiben noch die üblichen Ursachen:
- Ein Interrupt ohne Handler
- Pointer überschreiben den Stack
- Instabile Betriebsspannung/Takt (CKOPT bei alten AVRs bei >8MHz)

Autor: Jens (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Wenn ich jetzt die Ausgabe auf der UART mache erfolgt nach dem scan
>genau 1 Reset.

ist das so gewollt?
wenn nicht, untersuche mal die Ursachen bevor Du weiter machst!

Jens

Autor: Matthias Kölling (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

das Problem scheint sich auf meine fprintf zu konzentrieren (im Anhang). 
Es hat aber scheinbar nichts mit dem Schreiben in eine Datei zu tun, 
denn das Problem tritt auch auf, wenn ich innerhalb der fprintf die 
Schreibfunktion auskommentiere. Erst wenn ich den ganzen Block unterhalb 
der for-Schleife auskommentiere sind die resets weg. Ich lasse mir in 
dieser Funktion die maximale Stacktiefe ausgeben und die liegt bei 
0x10AC. Das dürfte weit genug weg sein von den statischen Variablen, die 
2831 Bytes umfassen. Der RAM hat 4096 Bytes (644P).
Es ist auch insofern verblüffend, dass meine printf-Funktion genau so 
aussieht, nur dass die Ausgabefunktion eine andere ist. Diese Funktion 
macht aber keinen Ärger.
Hat jemand eine Idee, was es noch sein könnte?

Danke und Gruß Matthias

Autor: Benedikt K. (benedikt) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Matthias Kölling wrote:
> Erst wenn ich den ganzen Block unterhalb
> der for-Schleife auskommentiere sind die resets weg.

Dann dürfte es klar sein:
 va_end (ap); fehlt am Ende der Funktion, was dazu führen könnte, dass 
der Stack durcheinander kommt.

Autor: Eddy Current (chrisi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
va_end habe ich schon immer für unnötig gehalten :-)

Mich stört viel mehr, dass das Durchsuchen einer Verzeichnisstruktur 
sehr gerne rekursiv implementiert wird. Insofern sehr ich hier einen 
Verdächtigen.

@Matthias: Hast Du rekursive Aufrufe im Programm?

Autor: Matthias Kölling (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

sorry, ich meinte natürlich, dass die while-Schleife, die den String 
scannt und bei Erreichen des Endes va_end() aufruft als einziges in 
for-Schleife veblieben ist. Aber ich hatte auch schon die for-Schleife 
rausgeschmissen, so dass va_end() nicht aufgerufen wurde und da gabs 
komischerweise auch keine resets mehr?!
Rätsel über Rätsel...

Gruß Matthias

Autor: Benedikt K. (benedikt) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Eddy Current wrote:

> @Matthias: Hast Du rekursive Aufrufe im Programm?

Dürfte er nicht drin haben, das würde mein StackViewer anzeigen.


Matthias Kölling wrote:
> Aber ich hatte auch schon die for-Schleife
> rausgeschmissen, so dass va_end() nicht aufgerufen wurde und da gabs
> komischerweise auch keine resets mehr?!

Pack mal va_end ans Ende der Funktion und schau mal obs dann geht.
Ich muss mal nach offiziellen Angaben suchen, auf die Schnelle habe ich 
nur das hier gefunden 
(http://docs.codegear.com/docs/radstudio/radstudio2...

va_end: Dieses Makro hilft der aufrufenden Funktion, normal 
zurückzukehren. va_end kann ap so ändern, dass ap erst wieder verwendet 
werden kann, wenn va_start erneut aufgerufen wird. va_end sollte 
aufgerufen werden, nachdem va_arg alle Argumente gelesen hat; wird dies 
unterlassen, könnte ein seltsames, nicht definiertes Verhalten Ihres 
Programms die Folge sein.

Edit:
Auch K&R sagt, dass va_end zwingend notwendig ist:
Finally, va_end does whatever cleanup is necessary. It must be called 
before the program returns.

Autor: Matthias Kölling (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
@Eddy
Ich habe es vermieden,rekursive Aufrufe zu programmieren, da das sehr 
schnell den Stack sprengt, vor allem wenn man nicht weiß wie viele 
verschachtelte Aufrufe es letztendlich sein werden.

Ich hänge mal das File mit dem scan an. Vielleicht seht Ihr noch etwas, 
was ich bisher übersehen habe.

Gruß Matthias

Autor: Matthias Kölling (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

Asche auf mein Haupt! Es ist das Fwrite(). Einen Aufruf hatte ich 
vergessen auszukommentieren. Sobald es weg ist, funktioniert es.
Aaußerhalb des scans funktioniert es aber und es schreibt auch etwas 
sinvolles in das File.

Guß Matthias

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Asche auf mein Haupt! Es ist das Fwrite(). Einen Aufruf hatte ich
>vergessen auszukommentieren. Sobald es weg ist, funktioniert es.
>Aaußerhalb des scans funktioniert es aber und es schreibt auch etwas
>sinvolles in das File.

Das wird wohl daran liegen das du die fileid der offenen
Datei auch zum scannen des Verzeichnisses benutzt. Autsch!

Ich denke du würdest mit den Funktionen Findfirst(),
Findnext() und Chdir() auch zum Ziel kommen. Dann musst du das
DOS nicht so vergewaltigen.

Autor: Matthias Kölling (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Holger,

ich benutze nur eine fileid, und zwar die für das zu schreibende file. 
Ich dachte das Lesen von Verzeichnissen geht über dirbuf
(by=ReadSector(sector,dirbuf);), oder habe ich da was falsch verstanden?

Gruß Matthias

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Ich dachte das Lesen von Verzeichnissen geht über dirbuf
>(by=ReadSector(sector,dirbuf);), oder habe ich da was falsch verstanden?

Ja, das stimmt. Nach näherem hinsehen benutzt du fileid auch nur
für die Datei. Warum Fwrite() da jetzt scheinbar abschmiert
ist mir ein Rätsel.

Autor: Matthias Kölling (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Holger noch da?

Ich konnte die Ursache bis zu MMCWriteSector() zurückverfolgen. Eine 
Änderung der Geschwindigkeit brachte keine Besserung. Die 
eingeschalteten Debuginfos haben bis zum Reset keinen Fehler angezeigt.

Gruß Matthias

Autor: Benedikt K. (benedikt) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hast du vielleicht den Watchdog an? Falls nein, poste doch mal die 
entsprechende Datei mit der Funktion drin.

Autor: Matthias Kölling (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

der Watchdog kann nicht an sein. Ich gehe nach dem scan in eine 
Endlosschleife. Nach erfolgreichem scan, also ohne fprintf(), bleibt er 
da auch ganz brav.

Gruß Matthias

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Holger noch da?

Hier, wo die Hand leuchtet ;)

>Ich konnte die Ursache bis zu MMCWriteSector() zurückverfolgen. Eine
>Änderung der Geschwindigkeit brachte keine Besserung. Die
>eingeschalteten Debuginfos haben bis zum Reset keinen Fehler angezeigt.

Die Routine bleibt bei Problemen evtl. hängen, aber
einen Reset löst die bestimmt nicht aus. Hat sie
bei mir noch nie getan und so etwas wurde mir auch noch
nicht berichtet. Da muss was anderes faul sein.

Wenn du magst poste doch mal die Sources zum Projekt.
Oder schick mir ne Mail. Adresse kennst du.

Autor: Matthias Kölling (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Holger,

ich schick Dir ne mail mit dem Projekt.

Danke und Gruß Matthias

Autor: Matthias Kölling (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich möchte gerne diesen Post abschließen, da ich meinen Fehler nun 
gefunden habe. Dieser hat absolut nichts mit meiner Anfangsvermutung 
(Stackoverflow) zu tun. Nachdem Holger mein Projekt nun getest hat und 
bei ihm keine Resets festzustellen waren, mußte etwas an meiner Hardware 
foul sein. Nachdem ich am Resetpin mit einem Schätzoszi so etwas 
ähnliches wie Pulse gesehen habe, die AVRs interne Resets aber nicht 
nach außen spiegeln kam nur die umliegende Hardware in Frage. Der 
Übeltäter war schnell ausgemacht. Es war der Spannungsregler. Der kann 
scheinbar nicht genug Strom liefern, von dem guten Saft wird beim 
Schreiben auf die SD-Karte wohl etwas mehr gebraucht, die Spannung 
bricht ein und der Resetbaustein löst einen Reset aus.
Nachdem ich 3,3V direkt hinter dem Spannungsregler eingespeist hatte, 
war alles gut.
Peinlich wenn man für dieses Modul 89€ + 8€ Porto aus der Schweiz 
bezahlt hat.
Den Spannungsregler kann ich nicht identifizieren. Der Schaltplan hat 
eine ältere Versionsnummer als die Platine. Im Schaltplan ist er mit 
XC6202M322 angegeben. Es ist ein SOT23. Auf dem Gehäuse hat er aber die 
Markierung 252A.
Danke allen für die fleißige Mitarbeit!

Gruß Matthias

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.