Forum: Mikrocontroller und Digitale Elektronik Probleme mit "rjmp 0000" und "CLI" (ASSEMBLER) ATmega8


von Bernhard S. (bernhard)


Lesenswert?

Hallo,

mir fehlt momentan eine logische Erklärung auf folgendes Problem:

In meinem sehr umfangreichen ASSEMBLER-Programm für den ATmega8
(16MHz)möchte ich an einer bestimmten Stelle den µC Reset-en.

SPRUNGMARKE_NEUSTART:
        clt temp
        OUT MCUCSR, temp
  rjmp 0000

So weit, so gut.

Aber plötzlich dauert die Ausführung des Programms extrem lange
(5x soviel Zeit wie sonst), bis die Startprozedur (PORTS und TIMER
initialisieren, verschidene TEXTE an LCD ausgeben usw.) abgeschlossen
ist.

Anmerkung:
Über USART werden permanent ca. 500Byte pro Sekunde Daten von einer
GPS-MOUSE empfangen. Wenn ich die Datenzufuhr unterbreche geht es
gewohnt schnell.



Dann habe ich folgendes geändert:

SPRUNGMARKE_NEUSTART:
        clt temp
        OUT MCUCSR, temp
        CLI                ; Interrupt Enable FLAG löschen
  rjmp 0000

Und plötzlich funktioniert die Abarbeitung der Start-Prozedur in der
gewohnt schnellen Zeit.


Liegt die Ursache für die Programm-Verzögerung bei den noch aktivierten
Interrupts?

Danke


Bernhard

von johnny.m (Gast)


Lesenswert?

'clt temp'? was soll das bewirken? clt hat keine Operanden...

von johnny.m (Gast)


Lesenswert?

Ach, und ich glaube, die Betreffzeile ist a bissl lang geraten...

von Bernhard S. (bernhard)


Lesenswert?

> 'clt temp'? was soll das bewirken? clt hat keine Operanden...


sorry, hatte mich vertippt, muss natürlich heißen:

   clr temp



Bernhard

von Bernhard S. (bernhard)


Lesenswert?

>Ach, und ich glaube, die Betreffzeile ist a bissl lang geraten...

Habe es auch gerade bemerkt, wenn man antworte möchte, muss man vorher
ein paar Zeichen aus der Betreffzeile löschen.

Bernhard

von Niels H. (monarch2)


Lesenswert?

Vor einem Neustart empfiehlt es sich, die komplette MCU in einen
definierten Zustand zu bringen. Den Controller einfach den Codeanfang
zu zeigen führt zwangsläuftig zu Problemen.

Ich empfehle den Watchdog-Reset. (Bit3 im WDTCR setzen und einfach in
eine Endlosschleife treten).

von Bernhard S. (bernhard)


Lesenswert?

@Niels

>Ich empfehle den Watchdog-Reset. (Bit3 im WDTCR setzen und einfach in
>eine Endlosschleife treten).

Gute Idee, aber dann dann bleibt das (Bit3-WDTCR im MCUCSR gesetzt)

und das MCUCSR-Register soll bei Programmstart nicht glöscht werden,

denn ich möchte bei einem Programm-Absturz die Ursache des Absturzes
erfahren (BO/PO/WD/EXT).

Mein GPS-Projekt ist sehr komplex, bei Tests unterwegs auf dem Fahrrad
kam es mehrfach zu Neustarts.

War es nur ein Problem der Stromversorgung, oder habe ich noch einen
BUG in der Berechnung.

Bernhard

von Niels H. (monarch2)


Lesenswert?

Moment, jetzt verstehe ich die Problematik nicht.

Zuerst sagst du, das du den MCU an einer bestimmten Stelle resetten
möchtest, und postest einen Codeschnipsel, der das MCUCSR löscht und
zum Speicheranfang springt. (das das nicht ordnungsgemäss funktionieren
kann, sollte eigentlich jedem klar sein)

Jetzt sagst du, das du nicht möchtest, das das MCUCSR gelöscht wird?!

von Bernhard S. (bernhard)


Lesenswert?

>Jetzt sagst du, das du nicht möchtest, das das MCUCSR gelöscht wird?!

Das MCUCSR soll bei einem normalen Programmstart, z.B. einschalten des
Gerätes, nicht gelöscht werden.

Das MCUCSR soll nur im o.g. Codeschnipsel gelöscht werden und
anschließend soll ein SOFTWARE-Neustart erfolgen.

Bernhard

von Philipp Sªsse (Gast)


Lesenswert?

Grenze den Fehler doch einmal ein, indem Du das SEI bei der
Initialisierung immer weiter nach vorne holst. Vermutlich wird der
Start ja auch so langsam sein, wenn Du gleich mit SEI anfängst, oder?
Vielleicht gibt es da einen Zwischenzustand in der Initialisierung, in
dem z.B. der RX als Digitaleingang mit Interrupt funktioniert oder so
etwas. Den findest Du auf diese Art.

Hat die Sache für Dich denn noch praktische Gründe (d.h. Du willst die
Interrupts beim Reset gerne aktiv lassen?) oder geht es Dir nur um das
beruhigende Gefühl, den Controller ganz zu verstehen?

von Niels H. (monarch2)


Lesenswert?

Ein Programmneustart durch einen Sprung nach 0000 funktioniert aber
nunmal nicht, da flags- und steuerregister keinen definierten zustand
haben und in deinen initialisierungsroutine wahrscheinlich etliches
schiefläuft.

Nochmal:
Wenn du an einer bestimmten stelle im Code neustarten willst, empfielt
es sich, den Watchdog gezielt den Chip resetten zu lassen. Dadurch
wird, wie gewünscht, MCUCSR gelöscht und an den Codeanfang gesprungen.

von Bernhard S. (bernhard)


Lesenswert?

@Philipp

>Grenze den Fehler doch einmal ein, indem Du das SEI bei der
>Initialisierung immer weiter nach vorne holst. Vermutlich wird der
>Start ja auch so langsam sein, wenn Du gleich mit SEI anfängst, oder?

Habe SEI mal an 1. STELLE gesetzt, Du hast Recht, da läuft das Programm
mit dem gleichen Fehler(alles dauert ziemlich lange) ab.

Danke für den Tipp :)


>Vielleicht gibt es da einen Zwischenzustand in der Initialisierung,
>indem z.B. der RX als Digitaleingang mit Interrupt funktioniert oder
>so etwas. Den findest Du auf diese Art.

Der USART-Interrupt verlangsamt, warum auch immer, sind sicherlich auch
undefinierte Zustände dabei, den Programm-Ablauf extrem.


>Hat die Sache für Dich denn noch praktische Gründe (d.h. Du willst
>die Interrupts beim Reset gerne aktiv lassen?)

Die Interrupts können/müssen beim SOFTWARE-RESET deaktiviert werden, da
erst alles in eine definierte Start-Position gebracht werden muss.

>oder geht es Dir nur
>um das beruhigende Gefühl, den Controller ganz zu verstehen?

Bei solchen komplexen Programmen untersuche ich gerne Anomalien, denn
diese können verheerende Auswirkungen haben, wenn man sie nicht
ergründet.

----------------------------------------------------------------

@Niels

>Ein Programmneustart durch einen Sprung nach 0000 funktioniert aber
>nunmal nicht, da flags- und steuerregister keinen definierten zustand
>haben und in deinen initialisierungsroutine wahrscheinlich etliches
>schiefläuft.

Ich gebe Dir nur zum Teil Recht, mit "rjmp 0" kann unter normalen
umständen ein Software-Reset durchgeführt werden, aber wenn sich
gewisse Steuerregister durch Elektro-Smog verrstellt haben
(z.B. OSCAL) könnte man Probleme bekommen.

Also "rjmp 0" ist mit Vorsicht zu genießen.

Man müsste alle Register beim Start in einen definierten Zustand
bringen, auch diese, die man im eigentlichen Programm nicht benötigt
(z.B. SPI oder TWI)
Der Aufwand hierfür wäre sehr umfangreich (ca. 100 Register)


>Nochmal:
>Wenn du an einer bestimmten stelle im Code neustarten willst,
>empfielt es sich, den Watchdog gezielt den Chip resetten zu lassen.
>Dadurch wird, wie gewünscht, MCUCSR gelöscht und an den Codeanfang
>gesprungen.

Ist eine sehr gute Idee, ich denke schon die ganze Zeit darüber nach,
weil dieses Verfahren viele Vorteile zeigt, alle Steuer-Register werden
definiert zurückgesetzt.

Aber

Ich möchte gern wissen, ob der µC durch einen WD-Reset neu gestartet
worden ist. (z.B. Berechnungen dauern zu lange)

Wenn ich mein Programm in eine Endlos-Schleife schicke, ohne "WDR",
dann wird gnadenlos der WD-Reset nach einigen Sekunden durchgeführt

und

WDRF-Bit wird gesetzt und bleibt auch gesetzt.


Man könnte natürlich vorher, bevor man den WD zubeissen lässt,
den µC sagen (im EEPROM diese Info hinterlegen), dass jetzt ein
WD-Reset bewusst durchgeführt wird.

Wäre doch eine Idee, oder?


Bernhard

von Hannes L. (hannes)


Lesenswert?

> Man könnte natürlich vorher, bevor man den WD zubeissen lässt,
> den µC sagen (im EEPROM diese Info hinterlegen), dass jetzt ein
> WD-Reset bewusst durchgeführt wird.

Dazu brauchst du kein EEPROM, da reicht sogar eine SRAM-Zelle. Da
kannst du auch vor Berechnungen eine Art Status-Byte hinterlegen,
welches eim Reset bzw. durch dein Benutzermenü am Display angezeigt
werden könnte. - Prima Debug-Feature...

...

@Admin:
Danke für das Feature zur Rettung des Textes!!

von Bernhard S. (bernhard)


Lesenswert?

@HanneS

Schön, wieder mal was von Dir zu lesen :)

>Dazu brauchst du kein EEPROM, da reicht sogar eine SRAM-Zelle. Da
>kannst du auch vor Berechnungen eine Art Status-Byte hinterlegen

Gute Idee, um den EEPROM zu schonen, denn der SRAM wird bei "rjmp 0"
nicht angetastet.

Eigentlich könnte man auch ein Register, z.B R0 für den gleichen Zweck
verwenden? Denn es wird ebenfalls nicht standart-mäßig durch "rjmp 0"
verändert.

Bernhard

von peter dannegger (Gast)


Lesenswert?

"Man könnte natürlich vorher, bevor man den WD zubeissen lässt,
den µC sagen (im EEPROM diese Info hinterlegen), dass jetzt ein
WD-Reset bewusst durchgeführt wird."


Man könnte das PORF-Bit setzen, ist es mit dem WDRF gesetzt, dann war
es ein absichtlicher WD-Reset.

Bei einem echten Power on wird ja das PORF gesetzt und das WDRF
gelöscht.


Peter

von Bernhard S. (bernhard)


Lesenswert?

@Peter

>Man könnte das PORF-Bit setzen, ist es mit dem WDRF gesetzt, dann war
>es ein absichtlicher WD-Reset.

Gute Idee

>Bei einem echten Power on wird ja das PORF gesetzt und das WDRF
>gelöscht.

was ist ein "echten Power on" ?
Wie kann man erreichen, das PORF-BIT gesetzt wird?
(ich meine nicht mit SBI...)


Habe gerade meiner Schaltung die Betriebsspannung verweigert:
     ===>BORF-BIT gesetzt

Nach betätigen der RESET-TASTE:
     ===>EXTRF-BIT gesetzt



Bernhard

von Thomas J. (Gast)


Lesenswert?

Ich glaube die Reset-Flags kann man nur loeschen, nicht setzen.

Gruss Thomas

von Rahul (Gast)


Lesenswert?

>Ich glaube die Reset-Flags kann man nur loeschen, nicht setzen.
Deswegen bin ich der Kirche abgeneigt... die glauben auch immer
Sachen...

Seite 39 im Datenblatt, Register MCUCR: Sämtliche Bits sind R/W.
MCUCR wird auf Seite 31 auch noch behandelt.

von Thomas J. (Gast)


Lesenswert?

Das Datenblatt hab ich auch gelesen, wo steht das sich die Bits setzen
lassen ? Ich hatte noch keinen Mega8, beim Mega8515 geht es definitiv
nicht.

Gruss Thomas

von Rahul (Gast)


Lesenswert?

Atmega8515: Seite 49 im Datenblatt.

[OT]
Ich nenn mich jetzt nur noch "88issmeineOma"...
[/OT]


Wenn man sich dann den "Balken" anguckt, in dem die Bits markiert
sind, dann steht links darunter "read/write" und unter dem jeweiligen
bit "R/W", was soviel bedeutet, dass das Bit auch beschreibbar ist.
Es gibt auch Bits, die nur lesbar sind, weiß jetzt aber keine ausm
Kopf.

von Rahul (Gast)


Lesenswert?

Bit 5 des MCUCR ist nur lesbar. (fällt einem natürlich erst auf, nachdem
man den Beitrag abgschickt hat...)

von Thomas J. (Gast)


Lesenswert?

Die Bits sind beschreibbar, aber nur von 1 auf 0.

Gruss Thomas

von Bernhard S. (bernhard)


Lesenswert?

@ALLE

Danke für die Zahlreichen Antworten und Hilfestellungen.


Wie würdet Ihr Euch folgendes erklären:

Die µC-Schaltung wird durch AKKU-Betrieb gestartet:   PORF-gesetzt

Die Schaltung wird durch NETZ-BETRIEB gestartet: BORF und PORF


Ich vermute, der Spannungsanstieg ist im Akku-Betrieb steiler, daher
der Unterschied?


Am RESET-PIN befindet sich ein Elko (10µ) gegen GND und ein Widerstand
4,7k gegen +5V.

Warum löst diese RC-Kombination keinen EXTRF im MCUCSR-Register beim
Einschalten der Schaltung aus?

Bernhard

von Bernhard S. (bernhard)


Lesenswert?

Ich wollte gerade mal nur das PORF-BIT löschen

        cbi MCUCSR,0   geht nicht !!

so funktionierts:

  in temp, MCUCSR
  andi temp, 0b11111110
  out MCUCSR,temp

Gibt es noch weitere Möglichkeiten?


Bernhard

von Thomas J. (Gast)


Lesenswert?

Nur die ersten 32 Ports sind bitadressierbar (SBI,CBI,SBIS,SBIC).

Das sollte auch funktionieren ist aber keine echte Alternative:

  lds temp,MCUCSR+32
  cbr temp,1
  sts MCUCSR+32,temp


Gruss Thomas

von uli (Gast)


Lesenswert?

wie wärs mit rjmp reset bzw. rjmp 0x00 dann wäre es etwas
übersichtlicher;
schönere alternative:
wenn du den resetpin per Outbefehl umschaltest dann hättest du die
gesammte chipinterne resetprozedur ausgeführt und müsstest nicht noch
davor in irgenwelchen registern etwas herumstellen, somit kannst du
dann gleich evtl. peripherie reseten; ---> Vorteile^n

von Hannes L. (hannes)


Lesenswert?

> schönere alternative:
> wenn du den resetpin per Outbefehl umschaltest dann hättest du die
> gesammte chipinterne resetprozedur ausgeführt und müsstest nicht
> noch
> davor in irgenwelchen registern etwas herumstellen, somit kannst du
> dann gleich evtl. peripherie reseten; ---> Vorteile^n

Hast du das schonmal praktisch gemacht? Wenn ja, dann berichte mal
Einzelheiten...

...

von TravelRec. (Gast)


Lesenswert?

Was vorstellbar ist, ist den Resetpin (über einen Widerstand) mit einem
anderen Portpin zu verbinden, der dann per "Out" den Reset auf Low
zieht und somit den Prozi resetet, aber was bringt das gegenüber der
Watchdog-Version?!

von Bernhard S. (bernhard)


Lesenswert?

@uli

>wie wärs mit rjmp reset bzw. rjmp 0x00 dann wäre es etwas
>übersichtlicher;


rjmp 0x00 =  rjmp reset = rjmp 0 = rjmp 0000

Ist nach meiner Meinung kein Unterschied, nur die Schreibweise ist
anders

>wenn du den resetpin per Outbefehl umschaltest dann hättest du die
>gesammte chipinterne resetprozedur ausgeführt

Ist auch eine mögliche Variante, aber ein zusätzlicher PIN wird
benötigt


@TravelRec

>der dann per "Out" den Reset auf Low
>zieht und somit den Prozi resetet, aber was bringt das gegenüber der
>Watchdog-Version?!

Deine Frage ist berechtigt, das Ergebnis ist absolut das gleiche, nur
der Hardware-Aufwand ist unterschidelich.


Bernhard

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.