Datum: 25.04.2008 22:22
Hallo Zusammen, ich benutze seit kurzem ein LPC2138. Nun habe ich aber ein Problem. Alles was ich will ist ein Timer-interrupt auslösen. Ich habe dazu folgenden Code geschrieben:
#include "typedefs.h" #include "lpc2138.h" /* div. defines */ void vTickISR( void ) { IOSET0 = 0x80000000; //LED1 ON T0IR = 0x00000001; //Clear Interrupt flag VICVectAddr = 0; } int main (void) { PLLCON= 0x00000000; //No PLL IODIR0 = 0xc0000000; //Turn on the LED driver PINSEL1 |=0x00003000; //P0.22 Match MAT 0.0 asm("MSR CPSR,0x1f"); IOSET0 = 0x80000000; //LED1 ON T0TCR = 0x00000000; //Counter disable T0PR = 0x0000000; //Prescaler Register = 0 T0MR0 = 6000000; //velocity T0MCR = 0x00000003; //On MR0: TC reset & interrupt /* Setup the VIC for the timer. */ VICIntSelect &= ~( 0x00000010); //IRQ - Interrupt VICIntEnable |= 0x00000010; //TIMER Enable VICVectAddr0 = (unsigned long) vTickISR; VICDefVectAddr = (unsigned long) vTickISR; VICVectAddr = 0; VICVectCntl0 = 0x00000024; T0EMR = 0x31; //show match on pin P0.22 T0TCR = 0x00000001; //Counter Enable IOCLR0 = 0x80000000; //LED1 OFF while(1) { IOSET0 = 0x40000000; //LED2 ON IOCLR0 = 0x40000000; //LED2 OFF } return(0); } |
Wie äussert sich das problem: Mein LPC startet (led1 blitzt kurz), das while wird ausgeführt die LED2 blinkt. Doch sobald der Timer Interrupt kommt, springt mein ARM ins Schilf. D.h. Irgendwo hin. Das while wird nicht mehr ausgeführt. Die Interruptroutine vTickISR wird nie ausgeführt (Led1 leuchtet nicht). An Port P0.22 sehe ich jedoch noch mein Timer Match! Durch Nachforschungen in den .o-Files ist klar: alle Übergaben an die VICVectAddr0 usw. funktionieren richtig (heisst: Adresse der VTickISR wird übergeben). Dennoch springt mein ARM bei einem Interrupt ins Schilf! Warum das? Was ist an meiner Interrupt Initialisierung Falsch? Danke für eure Hilfe, Gruss Roman Gassmann
Datum: 26.04.2008 14:25
An dem Code fällt mir nichts auf außer das du Interrupts freigibst obwohl noch keine Handler installiert sind. Die Startup Datei (Startup.S, crt.S) sowie das Makefile könnten vielleicht zur Klärung beitragen.
Datum: 26.04.2008 14:43
Du solltest void vTickISR(void) mit _attribute_ ((interrupt("IRQ")))
versehen.
MfG Mark
Datum: 26.04.2008 15:05
Hallo Zusammen, also zuerst danke für eure Bemühungen! Nun... @Mark: Habe nun folgende ISR:
void vTickISR( void )__attribute__ ((interrupt("IRQ"))); void vTickISR( void ) { IOSET0 = 0x80000000; //LED1 ON T0IR = 0x00000001; //Clear Interrupt flag VICVectAddr = 0; } |
leider nützt dies nichts. Der ARM verhält sich immer noch gleich. @let: habe mein Makefile sowie das crt.S im zip im Anhang untergebracht. Gruss Roman
Datum: 26.04.2008 15:18
Klar dass er nicht in die ISR springt. Bei einem IRQ wird einfach eine Endlos-Schleife ausgeführt. Ersetz mal
ldr pc, IRQAddr /* IRQ interrupt */
|
in Zeile 72 von crt.S durch
ldr pc,[pc,#-0xFF0] // IRQ - read the VIC
|
Dann sollte es eigentlich klappen.
Datum: 26.04.2008 15:27
Das liegt wohl an der crt.S Datei. Dort ist ein default-handler
für den IRQ installiert, der eine Endlosschleife darstellt.
Ich habe mal eine crt.S und ein Linkerscript angehängt mit denen
das gehen müßte. Da kein IRQ-Wrapper in der crt verwendet wird,
muß das __attribute__((interrupt("IRQ"))) angegeben werden.
Das funktioniert aber (wahrscheinlich) nur wenn die Datei mit dem
Handler im ARM Modus übersetzt wird, was im Moment ja auch der Fall
ist.
Datum: 26.04.2008 15:30
> in Zeile 72 von crt.S durch > > ldr pc,[pc,#-0xFF0] // IRQ - read the VIC > >Dann sollte es eigentlich klappen. Ja, das ist wohl der einfachere Weg ;)
Datum: 26.04.2008 15:33
Hallo, naja klar :-S... aber hey es läuft!! hatte die Hoffnung schon fast aufgegeben! Vielen vielen Dank! Gruss Roman
Datum: 09.05.2008 15:03
hallo miteinander, tja habe mich wohl einwenig zu früh gefreut mit dem es geht. Denn bereits steht das nächste Problem an! Und auch wieder mit dem Interrupt. Diese Funktionieren jetzt zwar, leider ist es aber so, dass wenn ich in der Interruptroutine eine Funktion aufrufe der ARM wieder ins Schilf springt. Nachvorschungen haben ergeben, dass der Ablauf beim verlassen einer Funktion (Exception) noch Falsch ist. Der Aublauf steht im file: http://infocenter.arm.com/help/topic/com.arm.doc.d... unter punkt 2.9.3 Leaving an exception (Seite 63 bzw. 2-21). Mein problem ist nur, wo und wie muss ich dies definieren?? Ich nahm an, dass dies entweder im ld oder im crt0.s ist also habe ich diese zwei Files mal angehängt. Kann mir da jemand weiter Helfen? Vielen Dank für die Hilfe. Gruss Roman Gassmann
Datum: 09.05.2008 16:12
Eigentlich sollte der gcc das richtige machen, wenn die ISR ein
attribute ((interrupt("IRQ"))) hat. Um das Problem zu klären braucht
man den Quelltext, mit den beiden Dateien hat das wenig zu tun. Wie
viele Variablen legt denn diese Funktion an, die aus der ISR heraus
aufgerufen wird? Wenn es zu viele sind kann es zu einem Stack-Overflow
kommen, da der IRQ-Stack nur 256 Byte groß ist, also nur 64 Register
speichern kann.
Datum: 09.05.2008 17:16
Tja also mein Ziel wäre das FreeRTOS auf meinem ARM zum laufen zu bringen. Doch sobald ich im vTickISR (Scheduler tick interrupt) eine noch so kleine Funktion wie z.b. (led1_on();)
static int initialized = 0; static void led_init(void) { if (!initialized) { IODIR0 = 0xc0000000; initialized = 1; } } void led1_on(void){ led_init(); IOSET0=0x80000000; } |
einfüge ists vorbei. Ein Stackoverflow kann es auch nicht sein denn ich kann im ld-file den IRQ-stack auch auf 400 anstelle von 100 setzten ohne das dies was ändert. Irgendwie Verlasse ich die IRQ-routine nicht als IRQ-routine womit ich dann den falschen Stack verwende was natülich katastrophal endet.
Datum: 09.05.2008 18:07
Zeig mal den Code, wo die Funktion aufgerufen wird
Datum: 09.05.2008 18:15
void vTickISR( void ) __attribute__((interrupt("IRQ"))); void vTickISR( void ) { led1_on(); //IOSET0=0x80000000; /* Save the context of the interrupted task. */ portSAVE_CONTEXT(); /* Increment the RTOS tick count, then look for the highest priority task that is ready to run. */ vTaskIncrementTick(); #if configUSE_PREEMPTION == 1 vTaskSwitchContext(); #endif /* Ready for the next interrupt. */ T0_IR = portTIMER_MATCH_ISR_BIT; VICVectAddr = portCLEAR_VIC_INTERRUPT; //led1_off(); IOCLR0=0x80000000; /* Restore the context of the new task. */ portRESTORE_CONTEXT(); } |
ich könnte sonst auch mal den ganzen code schicken wenn das besser währe?
Datum: 09.05.2008 18:47
Ich weiss zwar grad nicht wo das in der Doku steht, bin mir aber fast sicher, dass Interrupt-Routinen in freeRTOS mit portSAVE/RETORE_CONTEXT nicht als "IRQ" sondern als "naked" deklariert werden müssen. Update: Jo, so steht's auch im Beispielcode von freeRTOS.
Datum: 09.05.2008 18:56
Also bei mir steht diese Funktion in der portISR.c. Habe das ganze auch mit "naked" versucht. Leider bringt dies keine Änderung :-(.
Datum: 09.05.2008 19:00
Du musst die Funktion nach 'portSAVE_CONTEXT();' aufrufen, sonst werden nicht gesicherte Register überschrieben.
Datum: 09.05.2008 19:04
ok stimmt. hab das ganze geändert... jetzt gehts aber leider nur ca 10-20sec dann ist Schluss. ok das war jetzt das "naked"... jetzt läufts stetig! hmm für was steht denn dieses naked genau?
Datum: 09.05.2008 19:16
"naked" sagt dem Compiler dass er beim Funktionseintritt keine Register auf dem Stack sichern soll. In diesem Fall macht es RTOS bzw portSAVE_CONTEXT(); selbst.
Datum: 09.05.2008 19:22
ah ok, dies bedeuted aber auch, dass ich bei einer Interruptroutine die ich selber schreibe die Register sichern muss? oder macht dies auch das RTOS??
Datum: 09.05.2008 19:36
Habe nun gedacht ich könnte weiter fahren und mein Code wieder langsam aufbauen doch irrgendwas scheint da immer noch nicht zu stimmen denn jetzt habe ich ein inittask gestarted, und im inittask dann zwei weitere Tasks welche die led ein bzw. aus schalted doch auch hier springt der ARM ins Nichts.
static void init_task(void *parameters) { xTaskHandle blinkled1, blinkled2; int ld1,ld2; //create a tasks ld1 = xTaskCreate(blink_led1,(signed char *)"led1",512,NULL, 1, &blinkled1); ld2 = xTaskCreate(blink_led2,(signed char *)"led2",512,NULL, 1, &blinkled2); /* init task terminates */ vTaskDelete(NULL); taskYIELD(); } int main(int argc, char *argv[]) { init_pll(); led2_on(); led2_off(); xTaskHandle inittask; xTaskCreate(init_task, (signed char *)"init", 256, NULL, configMAX_PRIORITIES - 2, &inittask); /* start the scheduler */ vTaskStartScheduler(); while(1); } |
Datum: 09.05.2008 20:12
Roman Gassmann wrote:
> oder macht dies auch das RTOS??
Guck doch einfach mal rein, was portSAVE_CONTEXT so macht.
Datum: 10.05.2008 10:37
nun gut ich glaube langsam aber sicher habe ich einwenig Übersicht über das ganze gewonnen. Nach einigen Tests bin ich mir zumindest sicher, dass mein Prozessor in den SWIHandler springt welcher nichts unternimmt. Klar denn ich habe im crt.s file die SWIAddr auf den SWIHandler gesetzt was ja dann nichts mehr macht (genau gleich wie beim IRQHandler). Das Problem ist nur, wie setzte ich ihn auf meine vPortYieldProcessor funktion? Das einfache ersetzen des Funktionsaufrufs (Zeile 78):
SWIAddr: .word SWIHandler
|
durch
SWIAddr: .word vPortYieldProcessor
|
ist leider nicht die Lösung. Dann ruft mein compiler aus und meint er kenne die Funktion nicht. Kann mir da jemand weiter Helfen? Vielen Dank. Gruss Roman Gassmann
Datum: 10.05.2008 12:31
Du musst dem Compiler durch
.extern vPortYieldProcessor |
mitteilen, dass es sie gibt. Die ISR muss dann mit
__attribute__((interrupt("SWI"))) definiert werden.
Antwort schreiben
Die Angabe einer Email-Adresse ist freiwillig. Wenn Sie automatisch per Email über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.
Wichtige Regeln - erst lesen, dann posten!
- Suchfunktion und Betreffsuche benutzen - vielleicht gibt es schon einen ähnlichen Beitrag
- Aussagekräftigen Betreff wählen
- Im Betreff angeben um welchen Controllertyp es geht (AVR, PIC, ...)
- Groß- und Kleinschreibung verwenden
- Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang
- JPEG-Dateien (.jpg) nur für Fotos verwenden, Schaltpläne, Screenshots usw. als PNG oder GIF anhängen
Formatierung (mehr Informationen...)
- [c]C-Code[/c]
- [avrasm]AVR-Assembler-Code[/avrasm]
- [pre]vorformatierter Text (z.B. Code in anderen Sprachen)[/pre]
- [math]Formel in LaTeX-Syntax[/math]
- [[Titel]] - Link zu Artikel


