Forum: Mikrocontroller und Digitale Elektronik Fehlermöglichkeiten in diesem Code


von mr.chip (Gast)


Lesenswert?

Hallo

Der folgende Code (von C aufgerufene Assembler-Routine) lässt offenbar 
meinen AVR abstürzen. Ich sehe aber trotz intensiver Analyse _keine 
einzige Möglichkeit_, wie dies geschehen könnte.

Sieht hier irgend jemand eine Möglichkeit, wann der Controller abstürzen 
könnte? VRAM und VRAM_SIZE sind Pointer bzw. Grössenangaben für ein 
Array. Die Werte sind so korrekt und funktionieren auch.
1
// clearscreen
2
.global clearscreen
3
.func clearscreen
4
5
clearscreen:
6
7
push ZL
8
push ZH
9
push TMPL
10
push TMPH
11
12
ldi ZL, lo8(VRAM)
13
ldi ZH, hi8(VRAM)
14
15
ldi TMPL, 0b00000000;
16
ldi TMPH, hi8(VRAM + VRAM_SIZE)
17
18
clearscreen_loop:
19
;mov TMPL, ZL
20
;andi TMPL, 0b00000001
21
;ld TMPL, Z
22
st Z+, TMPL
23
cpi ZL, lo8(VRAM + VRAM_SIZE)
24
cpc ZH, TMPH
25
brne clearscreen_loop
26
27
pop TMPH
28
pop TMPL
29
pop ZH
30
pop ZL
31
32
ret
33
34
.endfunc

Gruss

Michael

von AVRFan (Gast)


Lesenswert?

Funktionierts denn, wenn Du alle Zeilen dieser Routine (außer das "ret" 
am Schluss - klar) auskommentierst?  Ja?  Und was ist, wenn Du die push- 
und pop-Zeilen zuläßt?  Läufts dann auch noch?  Wenn dem so ist, 
aktivier die vier "ldi"-Zeilen nach den "push"-Zeilen.  Es funzt 
weiterhin?  Dann hast Du den Fehler auf die vier Zeilen der 
"clearscreen_loop"-Schleife eingegrenzt.

Ach so: Wenn es schon "vorher" nicht funktioniert, z. B. sobald Du die 
push- und pop-Zeilen zuläßt, solltest Du überprüfen, ob Du evtl. 
Interruptroutinen hast, die die in "clearscreen" benutzten Register 
verändern.  Das wäre eine mögliche Ursache für Deinen "unerklärlichen" 
Fehler.

Viel Erfolg :-).

von mr.chip (Gast)


Lesenswert?

Hallo

Jetzt ist einiges klar:

Die Schleife schreibt irgendwo in den Speicher, wo sie nicht sollte. 
Ersetze ich die st Anweisung durch eine ld Anweisung, dann stürzt nix 
mehr ab. Könnte es sein, dass der Compiler in den Speicherbereich meines 
Arrays noch eine andere Variable platziert, obwohl ich das Array im 
C-File korrekt deklariert habe?

Gruss

Michael

von Bernhard S. (bernhard)


Lesenswert?

clearscreen:

push ZL                        ; Hilfsregister sichern
push ZH
push TMPL
push TMPH

ldi ZL, lo8(VRAM)               ; Z-Zeiger initialisieren
ldi ZH, hi8(VRAM)

ldi TMPL,0                      ; Hilfsregister auf 0

clearscreen_loop:

st Z+, TMPL                      ; TMPL in Z schreiben Z+1

cpi ZH, hi8(VRAM + VRAM_SIZE)    ; vergleich H-Byte
brne clearscreen_loop            ; ist nicht gleich ==> SPRUNG

cpi ZL, lo8(VRAM + VRAM_SIZE)    ; vergleich L-Byte
brne clearscreen_loop            ; ist nicht gleich ==> SPRUNG


pop TMPH                          ; Hilfsregister wieder herstellen
pop TMPL
pop ZH
pop ZL

ret




Müsste so funktionieren


Bernhard

von mr.chip (Gast)


Lesenswert?

Hallo

Danke für eure Antworten.

Der Fehler liegt nicht wirklich in diesem Code. Das Problem ist 
folgendes: Ich habe einen Interrupt, der jeweils 32 mal in kurzer Zeit 
aufgerufen wird. Nach diesen 32 aufrufen folgt eine längere Pause, 
während der Funktionen wie die obige ausgeführt werden. Nun gibt es aber 
offensichtlich ein Problem, diese Funktion mit den Interrupts zu 
koordinieren, d.h. die Funktion rutscht irgendwie zwischen die 
Interrupts.

Eigentlich habe ich ja einen Zähler, der jeden Interrupt zählt und nach 
dem 32. ein Flag setzt, welches die Hauptschleife veranlasst, obige 
Funktion auszurufen, doch scheinbar kann die Funktion auch schonmal 
zwischen den Interrupts kommen. Ist Gegenstand der Untersuchung ;-)

Gruss

Michael

von AVRFan (Gast)


Lesenswert?

Sowas... Stell Dir mal vor, Du hättest einen Interrupt, der von 
"außerhalb des µC" zu völlig unvorhersehbaren Zeitpunkten ausgelöst 
wird, so dass es unmöglich wäre, irgendetwas in Deinem Programm mit 
diesem Interrupt zu "koordinieren"... Was meinst Du dazu? lach

Wodurch werden Deine Interrupts denn auf so seltsame Weise ausgelöst?

von mr.chip (Gast)


Lesenswert?

> Wodurch werden Deine Interrupts denn auf so seltsame Weise ausgelöst?

Von einem zweiten Controller, der diese 32 Interrupts alle 40 ms auslöst 
um Daten zu übertragen. Da die Controller synchron laufen, geht sowas 
eigentlich schon. Nur sollte man nicht zu blöd dazu sein, die 
Rechenarbeit in die Interrupt-Pause zu legen.

von AVRFan (Gast)


Lesenswert?

Zweiter synchron laufender Controller... Aha... Na dann mal noch viel 
Spaß und Erfolg :-)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.