ATMega128 - Programm Reset nach Portzugriff (PORTA)

Gast #6008133
Hallo zusammen,

ich benutze für ein Funkgeräteprojekt einen ATMega128 (8MHz interner 
Takt). Der entscheidenden Teil des Codes ist herauskopiert. Dieser Teil 
soll einen ST7920 LCD-Controller in einem 12864 LCD ansprechen. Die 
Datenübertragung ist im  8-Bit-Mode. Datenport ist PORTC, Über PA4..PA7 
laufen RS, RW, E und RST.

Der ATMega128 hat folgende Fuses: L:E4, H:D1, E:FF.

Problem: Sobald ich PA7 auf "hi" setze (also nach dem RESET des LCD) und 
einen weiteren Schreibzugriff auf PORTA durchführe (im Code das 
Schreiben einer "0"), resettet sich der Controller und das Programm 
startet neu.

Auslöser ist dabei nicht die "0" sondern das Setzen von wahlweise RS, RW 
oder E in der Funktion lcd_write().

Der Codeschnipsel hängt an (dk7ih.c).

Hat jemand eine Idee, worin das Verhalten des Controllers begründet sein 
könnte?

Grüße

Peter
Angehängte Dateien:
Gast
DK7IH (Peter) schrieb:
> AVCC anzuschließen hatte leider bezüglich des Problems keinen Effekt.
> Schade. :-(

Sind auch alle GNDs angeschlossen, ist jedes (A)VCC/GND-Pärchen mit 
jeweils 100nF abgeblockt?

Wenn der Compiler keinen Murks baut, gibt es bei dem gezeigten Code, der 
nichts anderes macht, als ein paar Pins zu beschreiben, keinen Grund 
dasfür einen Softwarefehler zu vermuten. Ergo: Hardware.
Gast
So, leider war diese Prüfung auch unergiebig. Alle VCCs, GNDs und 100nF 
Kondensatoren sind korrekt angeschlossen. Spannungen liegen korrekt an, 
Controller wurde auch probehalber gewechselt, immer noch der gleiche 
Effekt.

Compiler ist AVR GCC unter Linux.

Grüße
Peter
Gast
Hallo,

ja, das Target stimmt, das Projekt läuft unter "mini6" und wird auch so 
von AVRDUDE auf den Controller geladen. Hier mal die entsprechenden 
Zeilen aus dem Makefile:

MCU = atmega128
FORMAT = ihex
TARGET = mini6
OPT = 3

Optimierungslevels habe ich verschiedene getestet, jedes Mal das gleiche 
Ergebnis.

Dann habe ich mal probehalber alle Zeilen aus der Funktion lcd_init() in 
das Hauptprogramm geschrieben. Jetzt tritt der Fehler, was mich sehr 
verwundert, NICHT mehr auf, wenn lcd_init() nun nicht mehr aufgerufen 
wird. Dieses Ergebnis ist nicht zufällig sondern reproduzierbar. Könnte 
es sein, dass der Compiler da einen Fehler macht?

Das HEX-File hänge ich an.

Gruß

Peter
Angehängte Dateien:
Gast
Kann es sein, dass die Versorgungsspannung des Controllers einbricht, 
wenn du in der lcd_write etwas auf den Port ausgibst?

Dann eventuell extern ein Kurzschluss am Pin gebaut?
Gast
Hallo,

die Versorgungsspannung habe ich mit dem Scope überprüft, die ist 
vollkommen glatt.

Interessant ist ja, dass wenn ich lcd_write() weglasse und die 
entsprechenden Aufrufe identisch in das Hauptprogramm setze, der Fehler 
dann nicht mehr auftritt. Dann habe die PINs an PORTA und PORTC bei 
Überprüfung mit dem Scope die korrekten Signale und Soft- und Hardware 
arbeiten einwandfrei.

Die Platine habe ich auch überprüft. Zwei ATMega128 (jeweils auf 
Breakoutboards verlötet) zeigen ebenfalls identisches Verhalten.

Daher meine Vermutung, dass der Fehler vom Compiler kommt, der mit dem 
Handling der Funktion ein Problem hat.

Gruß

Peter
Gast
Ok, dann könnte die Vermutung darin liegen, dass der Stackpointer nicht 
eingestellt wurde, womit der Controller bei Funktionsaufruf bestimmte 
Infos nicht auf den Stack bekommt und deshalb einen Reset macht.

Allerdings nutzt du C und der Compiler sollte sich darum kümmern, anders 
als bei Assembler, wo man das selbst einstellen muss. Vielleicht hier 
was verstellt?

Andererseits dürte dann bereits das Betreten der Funktion schon ein 
Problem sein...

Erzeugt dein Compiler ein .lss-File mit Assemblercode und Kommentaren, 
in denen die C-Befehle stehen? Darüber ließe sich auch einiges heraus 
finden, denke ich.
Gast
DK7IH (Peter) schrieb:
> Das HEX-File hänge ich an.

Das Hex entspricht nicht dem oben gezeigten Code.
Denn:
1
int main(void)
2
{
3
    DDRA = 0xFF;
4
        
5
  PORTA |= 128;
nach PortA |= 128 sitzt ein Delay drin, dass der Compiler sicher nicht 
selbst reingebastelt hat, sieht so aus:
1
  ldi r24,k66
2
  ldi r25,k0E
3
L0069:
4
  sbiw r24,k01
5
  brne L0069
und dauert 14744 Takte gleich 1,8ms@8MHz.
Außerdem wird in der Main Bit 7 von PortA nach dem Delay wieder 
gelöscht, bevor's in die lcd_write() geht.

Ansonsten sieht der Code aus dem Hex dem geposteten C ähnlich, er rennt 
zum Schluss in eine Endlosschleife.

Du verwechselst da aber nicht eine Endlosschleife mit einem Neustart?

Wie willst Du bei diesem Code das Eine vom Anderen unterscheiden?
Du müsstest mindestens eine Led beim Startup blinken lassen, um das zu 
erkennen.
Gast
Hi,

ja, ich habe den Code zum Testen nochmal zwischendurch etwas verändert. 
Das Delay hat in der Tat ca. 1ms und ist natürlich von mir. ;-)

Der Unterschied zwischen normalem Programmlauf und Dauer-Neustart ist 
für mich erkennbar, weil ein Scope an PA7 hängt. Wenn das Programm 
korrekt arbeitet (also der Funktionsaufruf nicht stattfindet) bleibt der 
Pegel nach dem Togglen auf "hi".

Wenn das Programm sich selbst neu startet, wechselt PA7 zwischen 0 
(PORTA &= ~(128);) und 1 (PORTA |= 128;). Die Endlosschleife ist ja 
leer, da passiert dann bei korrektem Programmablauf nichts mehr, was PA7 
verändert.

Ich hänge nochmal ein .C-, ein .lss und ein HEX-File an, die jetzt 
zueinander passen.

Gruß
Angehängte Dateien:
Gast
Stackpointer wird konfiguriert. Es wird der Speicherbereich des 
ATmega128 genommen. Im M103C Compatible Mode würde das jedoch über den 
SRAM hinaus springen, siehe Datenblatt Abschnitt "SRAM Data Memory" (bei 
mir Seite 17).
Gast
Das mit dem M103-Mode war ein guter Tipp. Ich hatte übersehen, dass die 
Kommandozeile, mit der ich den zweiten ATMega128 eingestellt hatte, ein 
fehlerhaftes Zeichen hatte. Jetzt sehe ich die ersten Zeichen auf dem 
Display. Vielen Dank!

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 7 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.