Warum muss der Pointer im Interrupt dran glauben?

Gast #488132
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
Gast #488521
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, ...
#488550
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
Persönliche Seite #488589
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:
1
make: *** No rule to make target `Utils/swi_handler.S', needed by `Utils/swi_handler.o'.  Stop.
2

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

Damit ist das Projekt dann erst recht nicht vollständig...
Persönliche Seite #488702
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...
#488855
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 :-)
Gast #488952
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
Gast #488984
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.
#489061
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,
....
Gast #491697
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

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