Ich brauche mal eine Idee zur Fehlersuche. :-) Folgender etwas komplizierter Sachverhalt. Ich habe mir den neuen gcc, newlib und binutils runtergeladen um einen Crosscompiler fuer SH2A zu backen. (unter Linux) Das hat auch vollkommen problemlos funktioniert. Dann habe ich das Linkerscript passend zu meiner Hardware abgeaendert und einen eigenen Startupcode geschrieben. (Stack setze und bss nullen) CPU ist SH7262 Ich kann problemlos folgendes laufen lassen: [..] rs232_init(BAUD_115200); do { led_off(); i=400000; while(i--); rs232_printf("Wert: %x\r",0xaa); led_on(); i=400000; while(i--); } while(1); Das fuehrt dazu das etwa einmal pro Sekunde meine LED blinkt und der erwartete Text auf der seriellen Schnittstelle rauskommt. Mit anderen Worten es sieht so aus als wenn mein Compiler schon ganz gut laeuft da ja bereits eine ganze Menge Dinge problemlos laufen. (z.B die printf-funktion, stack, variablen) Als naechstes wollte ich die Interrupts in Betrieb nehmen. Dazu muss man folgendes wissen. Die SH7262 kennt einmal ganz normale Interruptaufrufe wie ihr sie alle kennt. Also alle Register auf den Stack, IRQ, alles wieder runter, reti. Sie kennt aber noch einen zweiten Modi. Alle Register der CPU sind 16mal vorhanden. Man kann nun bei jedem Interrupt, aber auch nur bei bestimmten Interruptleveln einfach nur die Banks umschalten. (Geschwindigkeitsvorteil) Der gcc unterstuetzt beide Moeglichkeiten! Wenn ich Interrupts verwenden will dann muss ich die Funktion in eine Tabelle eintragen, die Adresse in einem speziellen Register eintragen, dem Interrupt einen Level zuweisen und Interrupts fuer diesen Level freigeben. Das habe ich mit einem TimerIRQ gemacht. Der TimerIRQ kommt mit 76kHz. Ich zaehle dort bis 76000 und gebe etwas auf die RS232 aus oder lasse eine LED blinken, egal was. Und es funktioniert! set_imask(14); //IRQ erlauben led_on(); Obiges schaltet die IRQs ein. Alles was im IRQ laeuft wird gemacht. Die CPU stuerzt also nicht ab! Aber das Hauptrogramm steht! Starte ich den IRQ nicht so laeuft das Hauptprogramm ohne Probleme. Ich habe auch schon beide moeglichen Interruptaufrufarten ausprobiert. Jedesmal dasselbe Ergebnis. Ich habe mir den Source den den der Compiler erzeugt angeschaut und er sieht auch unauffaellig aus. Jemand eine Idee woran das liegen kann? Olaf
Olaf schrieb: > Jemand eine Idee woran das liegen kann? Die CPU verbringt 100% ihrer Zeit in der Interrupt-Routine, und hat deswegen keine Zeit mehr für main()?
> Die CPU verbringt 100% ihrer Zeit in der Interrupt-Routine, und hat > deswegen keine Zeit mehr für main()? Gut! Da bin ich gerade auch drauf gekommen. :-) Genauer gesagt ich habe einfach mal in meiner Interruptroutine den Interrupt abgeschaltet und schon laeuft das Hauptprogramm. Ich habe mich im uebrigen in obigen Post vertan. Nicht der IRQ laeuft 72kHz sondern das ist die Frequenz des Timers und der laeuft immer bis 72. Es sollte also ein IRQ 1ms auftreten. Interessanterweise sieht meine IRQfunktion derzeit so aus: TestTicker++; if (TestTicker>72000) { rs232_printf("aba[%i]\r",counter++); TestTicker=0; if (counter == 15) { INTC.IPR10.BIT._CMT0 = 1; //1= sehr niedrige Prioritaet, 15= sehr hoch rs232_printf("Selbstmord\r"); } } Das fuehrt zu einer Ausgabe etwa einmal pro Sekunde. Mit anderen Worten der Timer laeuft viel schneller als ich es erwarte. Das ist in sofern uberraschend weil ich die Timerfunktion von einem anderen Project das ich fuer den Renesascompiler geschrieben habe, uebernommen habe. Dies sind also getestet und lauffaehig. Jetzt habe ich aber ebenfalls von Renesas die Definition der internen Register der CPU uebernommen. Das wurde zwar problemlos uebersetzt, aber ich vermute das dort irgendwo ein Zugriff in falsche Wordbreite auf ein Register erfolgt oder etwas in der Art. Ich habe gerade auch mal das Compareregisters des Timers auf einen anderen Wert gesetzt ohne das dies die Ausgabegeschwindigkeit beinflusst hat. Jedenfalls bin ich erstmal weiter. Da erwartet man den Fehler in den tiefsten Untiefen und dann ist es etwas so banales... :-) Olaf
Funktionen wie printf sollte man nie aus einem Interrupthandler heraus aufrufen, auch nicht Funktionen, die mehrere Bytes an eine serielle Schnittstelle o.ä. ausgeben.
> Funktionen wie printf sollte man nie aus einem Interrupthandler heraus > aufrufen, auch nicht Funktionen, die mehrere Bytes an eine serielle > Schnittstelle o.ä. ausgeben. Mal etwas genauer: Man sollte den Interrupt so schnell wie möglich verlassen. Aber gerade auf kleineren Controllern mit wenig RAM wird printf oft ungepufftert verwendet, d.h. printf wartet bis der gesamte String über die UART raus gepurzelt ist. Bei niedrigen Baudraten kann das schon etwas dauern ;) 9600 Baud, 10 Zeichen bedeuten dann etwas über 8ms(!) bis der Interrupt beendet ist! Wenn es unbedingt eine Datenausgabe braucht, dann wären putchar() und Konsorten deutlich günstiger. Am besten ist ein Portpin wenn es nur darum geht zu signalisieren wann der IRQ angesprungen und verlassen wird.
> Funktionen wie printf sollte man nie aus einem Interrupthandler heraus > aufrufen, auch nicht Funktionen, die mehrere Bytes an eine serielle > Schnittstelle o.ä. ausgeben. Das weiss ich! War aber nur ein Test um zu sehen ob ueberhaubt was laeuft. Mittlerweile laeuft uebrigens alles. Fehler sass wie immer vor dem Bildschirm. Ich war der Meinung eine laufende Funktion zu testzwecken aus meinem Renesasverzeichnis kopiert zu haben, habe aber wohl versehentlich aus einer aelteren Programmversion kopiert und da hatte ich wohl vergessen im Interrupt das Ueberlaufflag des Timers zu loeschen. Deshalb ging die Kiste sofort wieder im Interrupt. Man denkt nur nicht daran das der Fehler so einfach sein kann wenn man einen neuen Compiler erstmals in Betrieb nimmt, gerade vor dem Hintergrund das der SH7262 bei den Interrupts viele Moeglichkeiten bietet etwas falsch zu machen. > Mal etwas genauer: Ich mache es normalerweise so das mein printf alles in eine Fifo wirft und die dann vom Interrupt Zeichenweise gelehrt wird. Aber erstmal muss mein System hier ueberhaubt funktionieren. Das war etwas komplizierter weil ich den Linker dazu bringen musste vor jedem Code einen Header zu erzeugen wo Groesseninformation des Codes, Zieladresse, Einsprungadresse und Magicnummer drin stehen. Sonst laedt mein Bootloader den Code nicht von der SD-Karten. Aber nachdem ich jetzt alles laufen habe kann ich ja mal was dickeres rueberziehen. :-) Olaf
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.