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
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, ...
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
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.
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...
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 :)
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...
> 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 :-)
> 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
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.
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,
....
:-) 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.