Interner Reset?

Gast #176983
Lesenswert?

Hallo,

Der Code auf meinem AT90s2313 sieht prinzipiell so aus:

int main (void) {
init ();
do {
//tut was
} while (1);
}

Anzunehmen ist nun, dass die do/while Schleife immer wiederholt wird,
während die init-Funktion nur einmal aufgerufen wird (Abgesehen vom
timerintrrupt). Nun führt der uc allerdings die init-Funktion in
unregelmässigen Zeitabständen aus (.5 - 10s). Das riecht schwer nach
unbeabsichtigtem Reset, doch sehe ich mit KO keine Änderung des
Reset-Pins. Den Watchdog timer habe ich ausgeschaltet. Kann mir da
jemand weiterhelfen?

Gruss Ralf
Gast #176987
Lesenswert?

Worauf ich damit hinaus wollte: gerade weil es diesen Handler gibt,
braucht man nicht die ganzen Deklarationen für jeden möglichen oder
unmöglichen Interrupt im Source vorzuhalten.

Benötigt man keinen Interrupt, dann braucht man auch die avr/signal.h
nicht. Allerdings darf man dann auch kein GIE-Flag setzen.
Gast #176988
Lesenswert?

Hi,
vielleicht sollte Ralf mal den gesamten Code posten. Er erwähnte einen
Timerinterrupt und, falls er den außer Acht lässt, resetet das Ding aus
Verzweiflung, weil es nicht weiß wohin mit sich....oder irr ich mich?
Bin ja auch noch ein Greenhorn ;)
Gast #176991
Lesenswert?

Hi!

Kann es sein, dass der Compiler das 'do {...} while(1);' wegoptimiert
und der µC den Inhalt des kompletten Code-Speichers ausführt? Verwendet
man nicht überlicherweise 'while(1){...}' ?

mfg
Reinhard
Gast #176994
Lesenswert?

Auch wenn es bei den 8051er Compilern tatsächlich so sein sollte,
ändert das nichts daran, daß es ein Bug wäre.

do { ... } while (1); besagt eindeutig, daß der Block in einer
Endlosschleife auszuführen ist, genauso wie while(1) { ... } oder
for (;;) { }.

Wegoptimiert darf da höchstens dann was werden, wenn in der Schleife
effektiv nichts passiert.  Also für

do {
  /* nix */
} while (1);

muß der Compiler keinen Code erzeugen, auch nicht für

int
main(void)
{
  int foo;

  do {
    foo++;
  } while (1);
}

(das Ergebnis von `foo' kann nirgends mehr benutzt werden), wohl aber
für

int foo;
extern int foobar(void);

int
main(void)
{

  do {
    foo++;
    foobar();
  } while (1);

}

da hier für den Compiler nicht ersichtlich ist, daß die externe
Funktion foobar() keinerlei Seiteneffekte bezüglich foo hat.
Gast #176995
Lesenswert?

Momentan habichs mit Optimierungsstufe 's' compiliert. Mit Stufe 1,2,3
geschieht dasselbe. Der Stufe 0 - Code ist zu gross für den uc.
Mit der 'while(1){...}' Methode dasselbe.
Die compilierte Hex-Datei der mainfkt. mit Stufe 's' und
'while(1){...}' ist im Anhang - vielleicht seht ihr etwas...
Angehängte Dateien:
Gast #176996
Lesenswert?

Ich glaub, ich hab das Problem gelöst!

Es war tatsächlich kein softwarproblem -> einfach ein 1uF C direkt in
die Speisung des uC und nun gehts ohne Probleme. Die Spannung schwankte
vorher scheinbar genug stark, dass der uC einen Reset auslösste...

Danke für die vielen Antworten!
Gast #176997
Lesenswert?

OK, nun kannst Du Dich zum Abschluß auch noch hinsetzen und all die
seit 2 Jahren schon veralteten inp/outp/sbi/cbi rauswerfen.  Teilweise
wie hier:

  if (USR & 0x18)

hast Du ja schon neue Syntax benutzt, warum dann nicht überall?

In der nächsten `major' Version der avr-libc wird sich Dein Code
sonst
nicht mehr compilieren lassen -- auf dem avr-libc-1.1er Arbeitsstand
schon jetzt nicht mehr.  Da ich bei mir diesen Arbeitsstand fahre,
werde ich notgedrungen auch irgendwann aufhören, Anfragen für Code,
den ich nicht mehr compilieren kann, zu beantworten.
Gast #177000
Lesenswert?

Naja, jubal.westnet.com war ein temporärer Standort.  Wo geistert die
URL denn noch herum?  Ich weiß nicht, ob die noch aktuell gehalten
wird.  Offiziell ist

http://www.nongnu.org/avr-libc/user-manual/index.html

Beschrieben ist das soweit dort schon, insbesondere sind die alten
Makros auch allesamt als `deprecated' markiert.

Die Syntax für cbi(x, y) sieht in Standard-C so aus:

x = x & ~(1 << y);

oder kurz

x &= ~(1 << y);

Sollte in jedem besseren C-Lehrbuch stehen. ;-) Der cbi-Makro macht
übrigens exakt das (insbesondere garantiert er Dir eben nicht, daß
auch wirklich ein CBI herauskommt).

Mit eingeschaltetem Optimierer und passenden Operanden kommt aber
am Ende ein CBI heraus.

Da der Konstrukt (1 << y) sehr häufig benöigt wird, bietet die
avr-libc dafür den Makro _BV().  Du kannst das also auch als

x &= ~_BV(y);

schreiben.
Gast #177002
Lesenswert?

Kannst du nicht! Das siehst du, wenn du dir einmal die einzelnen Schrite
des Befehls ansiehst.

(1<<y)  ->  Schiebt eine 1 an die Stelle y
~( )    ->  An der Stelle y steht eine 0 an allen anderen eine 1
x &     ->  Und-Verknüpfung

bei deiner Lösung würdest du eine 0 an die Stelle y schieben und dann
x den den Inhalt 0%00000000 zuweisen. Damit wären alle gelöscht.
Und selbst mit einen x &= (0<<y) würdest du alles löschen, weil 0 und
irgendwas immer noch 0 ist.

Mike
Gast #177003
Lesenswert?

Danke Mike,

Du hast recht, das ist nachvollziehbar. Würde dann eine
ODER-Verknüpfung gehen wie

x |= (0<<y);

Wenn ich mich nicht wieder vertue (was leider sehr gut sein kann), dann
bleiben die anderen Bits des Registers so wie sie sind (Wenn vorher eine
1 war: 1 ODER 0 = 1, wenn vorher eine 0 war: 0 ODER 0 = 0)und das Bit y
wird durch das Bit-Shift auch 0. Wenn ich das jetzt nicht mit Java
vermixe, dann wird doch erst der rechte Wert errechnet und dann dem
linken zugewiesen. Oder ist die Reihenfolge doch anders, dann kann das
gerade geschriebene natürlich Quatsch sein.

Ich hoffe, daß ich mich jetzt nicht gerade restlos blamiert habe!

Gruß
Lutz
Gast #177005
Lesenswert?

Ein bißchen hast Du das schon. ;-)

Der indirekte Beweis ist hier wohl einfacher.  Der Ausdruck "(0 <<
y)"
ergibt schlicht eine 0, mithin könntest Du gleich "0" schreiben.
Wenn
Du nun einen beliebigen Wert ODER 0 hast, kommt wieder der Wert selbst
heraus, ergo ist das nicht, was Du haben wolltest.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren