www.mikrocontroller.net

Forum: Compiler & IDEs Warum muss der Pointer im Interrupt dran glauben?


Autor: hahgeh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

Es geht um ein Programm auf einem LPC2141 compiliert mit arm-gcc.

Ich benutze das USB Interrupt. In einer Endlosschleife frage ich ab, ob 
durch ein Interrupt ein neuer Befehl empfangen wurde, dieser Befehl wird 
dann mittels puts() über UART ausgegeben.

main(){
U8 *zptr;
int cnt;
U8 * pointer;
while(1){
  if(serio_get_command(&pointer)!=2){
    zptr=ans;
    while(*pointer!=EOT){
      putchar(*pointer);
      pointer++;
      cnt++;
    }
  }
}
}

Das Problem:
Wenn in der while-Schleife ein weiteres Interrupt auftritt, ist mein 
pointer an einer ganz anderen Stelle als er sein sollte, und es wird 
zwangsweise Müll ausgegeben.

Mit static U8 * pointer funktioniert alles wunderbar. Aber bei einer 
Interruptroutine ist doch eigentlich kein static notwendig. Dann müßte 
man ja alle Variablen static deklarieren.

Der Pointer oder der Speicherinhalt wird auch nicht im interrupt 
geändert. Das cnt zählt auch ganz normal weiter.

Hab ich vielleicht bei der Interrupteinstellung was falsch gemacht? Ich 
habe mich sehr stark am Beispiel von Martin Thomas orientiert.

MfG hahgeh

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wer alloziert denn den Speicher, auf den pointer zeigt?  (Und wer
gibt ihn wieder frei, wenn er nicht mehr gebraucht wird?)

Autor: hahgeh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Naja,

der Speicher ein 400-Byte-Feld wird in einer includierten Datei global 
(also static) alloziiert und in einem Interrupt wird darauf zugegriffen, 
aber der Zugriff findet nur außerhalb des 'if' statt. Freigegeben wird 
der Speicher nie denke ich, weil er ja static ist.

Der pointer wird beim Aufruf der serio_get_command() Methode auf den 
Anfang des Feldes gerichtet.

Ich habe zwaar keinen richtigen Debugger aber laut Consolendebug wo ich 
in der inneren Schleife die letzten beiden Stellen des pointer 
ausgegeben habe, zählt er folgender maßen:
02, 03, 04,(hier kommt das Interrupt), 00, 01, 02, ...

Autor: Codesucher (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schau mal in Zeile 10 des Interrupts nach, wahrscheinlich liegt da der 
Fehler.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Solange keiner serio_get_command kennt, bleibt das hier ne Raterunde 
ohne Effekt.

Immer diese Krümel-Posterei und alles-aus-der-Nase-ziehen müssen.


Was ist daran so schwer zu verstehen, daß bei Softwareproblemen immer 
etwas fehlerfrei und warnungsfrei compilierbares geschickt werden muß ?


Peter

Autor: hahgeh (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ok, dann schicke ich einfach nochmal alles. Ich dachte nur es handelt 
sich um ein allgemeinen dummen Fehler oder ein bekanntes Problem.

Dazu gehört noch die LPCUSB.

Autor: Patrick Dohmen (oldbug) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Naja, das ist immer noch kein vollständiges Projekt und damit erst recht 
nicht kompilierbar. Die LPCUSB könnte man sich ja noch besorgen, das 
raubt mir jetzt allerdings zu viel Zeit ;)
Ausserdem erhalte ich als erste Fehlermeldung folgende:
make: *** No rule to make target `Utils/swi_handler.S', needed by `Utils/swi_handler.o'.  Stop.

Compilation exited abnormally with code 2 at Thu Feb 01 10:31:10

Damit ist das Projekt dann erst recht nicht vollständig...

Autor: hahgeh (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Oh die swi_handler.S habe ich wohl versehentlich beim manual-clean 
beseitigt.

Ich probiers nochmal...

Jetzt müßte es aber gehen, sogar LPCUSB ist noch dabei :)

Autor: Patrick Dohmen (oldbug) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hahgeh wrote:
>[...]
> Mit static U8 * pointer funktioniert alles wunderbar. Aber bei einer
> Interruptroutine ist doch eigentlich kein static notwendig. Dann müßte
> man ja alle Variablen static deklarieren.
>[...]

Hm, ich kann da jetzt auf Anhieb auch nichts wirklich falsches finden, 
aber für mich hört sich das nach 'nem zerhackten Stack an. Der - in 
diesem Fall - wesentlichste Unterschied zwischen 'U8 * pointer;' und 
'static U8 * pointer;' ist nämlich der, daß das 'static' dafür sorgt, 
daß 'pointer' nicht auf dem Stack landet.

HTH...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> aber für mich hört sich das nach 'nem zerhackten Stack an.

Ditto.
Beim Durchschauen ist nichts aufgefallen.

zerhackter Stack ensteht meist durch
* Array Zugriff ausserhalb der Array Grenzen (out of bounds)
* Pointer 'in the wood'
* Return type mismatch zwischen Protoyp und tatsächlicher
  Funktion

> ist nämlich der, daß das 'static' dafür sorgt,
> daß 'pointer' nicht auf dem Stack landet.

Und nur um das ganz klar zu stellen:
Auch wenn es scheinbar das Problem beseitigt: Es löst
nicht das Problem. Das Problem ist nach wie vor im Code
nur siehst man es zur Zeit nicht. Aber wie alle Probleme
wartet es nur darauf, erneut zuzuschlagen :-)

Autor: hahgeh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> zerhackter Stack ensteht meist durch
> * Array Zugriff ausserhalb der Array Grenzen (out of bounds)
> * Pointer 'in the wood'
> * Return type mismatch zwischen Protoyp und tatsächlicher
>   Funktion

Ist damit gemeint, dass solche Fehler in ganz anderen Fehlern in ganz 
anderen Variablen und Funktionen resultieren können?

Ich befürchte mal ja. Dann muss ich wohl nochmal den ganzen Code 
durchforsten, ich hoffe nicht den aus der LPCUSB.

> * Pointer 'in the wood'

Dürfte eigentlich nur gefährlich sein, wenn auf die Stelle wo der 
Pointer hinzeigt auch zugegriffen wird, oder? Ansonsten ist es ja nur 
ein willkürlicher Wert an irgendeiner Speicherstelle, der vor sich 
hinwartet.

> * Return type mismatch zwischen Protoyp und tatsächlicher
>   Funktion

Bei sowas müßte doch eigentlich eine Compilerwarnung kommen.

Danke ersmal

Autor: Patrick Dohmen (oldbug) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Möglicherweise geht Dir einfach nur der RAM aus!?

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wieviele Interrupts kommen denn auf dem fraglichen Interruptvektor an?

In irq.h steht was zu NESTED_INTERRUPT drin. Mir sieht der Code dort so 
aus, als ob, ein Zerschiessen des Stacks verhindert werden soll und ein 
Zerschiessen des Stacks passt gut zu deiner Fehlerbeschreibung.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hahgeh wrote:
>> zerhackter Stack ensteht meist durch
>> * Array Zugriff ausserhalb der Array Grenzen (out of bounds)
>> * Pointer 'in the wood'
>> * Return type mismatch zwischen Protoyp und tatsächlicher
>>   Funktion
>
> Ist damit gemeint, dass solche Fehler in ganz anderen Fehlern in ganz
> anderen Variablen und Funktionen resultieren können?

Ja.
Solche Fehler sind extrem unangenehm zu finden.

>> * Pointer 'in the wood'
>
> Dürfte eigentlich nur gefährlich sein, wenn auf die Stelle wo der
> Pointer hinzeigt auch zugegriffen wird,

Ja klar. Das ist damit gemeint

  *pPtr = irgendwas;

und pPtr hat einen völlig falschen Wert.

>> * Return type mismatch zwischen Protoyp und tatsächlicher
>>   Funktion
>
> Bei sowas müßte doch eigentlich eine Compilerwarnung kommen.

Nicht unbedingt. Wenn der Compiler immer nur eines von beiden
sieht, entweder Protoyp oder Funktion, aber nie beides gemeinsam,
....

Autor: hahgeh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
:-) ich habe den Fehler gefunden, danke nochmal.

Und zwar hatte es wirklich etwas Stacküberlauf (zerhackter Stack) und 
Nested Interrupts zu tun.

In dem Startup code sind immer nested interrupts eingestellt. Deshalb 
(so vermute ich) wird während der Abarbeitung des Interrupts in den 
supervisor mode geschaltet.
Für den supervisor mode hatte ich aber nur 128 Byte Stack eingestellt, 
was für diese aufwändige Interruptroutine wohl zu wenig war.
Wenn ich jetzt den Stack für den supervisor mode auf 512 Byte stelle, 
oder den Startupcode so verändere, dass nested interrupts ausgeschaltet 
sind und im irq mode weitergearbeitet wird (welcher sowieso schon 512 
Byte Stack eingestellt hatte), dann funktioniert alles wunderbar.

Vielleicht kann ich ja die Interrupt Routine auch noch etwas optimieren, 
um Speicher zu sparen.

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.