LPC2138 nach Timer Interrupt im Schilf

OP #852827
Lesenswert?

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:
1
#include "typedefs.h"
2
#include "lpc2138.h" /* div. defines */
3

4
void vTickISR( void )
5
{
6
  IOSET0 = 0x80000000;  //LED1 ON
7
  T0IR = 0x00000001;  //Clear Interrupt flag
8
  VICVectAddr = 0;
9
}
10

11
int main (void)
12
{
13
  PLLCON= 0x00000000;  //No PLL
14
  IODIR0 = 0xc0000000;  //Turn on the LED driver
15
  PINSEL1 |=0x00003000;  //P0.22 Match MAT 0.0
16
  asm("MSR CPSR,0x1f");  
17
  IOSET0 = 0x80000000;  //LED1 ON
18
  T0TCR = 0x00000000;  //Counter disable
19
  T0PR = 0x0000000;    //Prescaler Register = 0
20
  T0MR0 = 6000000;    //velocity
21
  T0MCR = 0x00000003;  //On MR0: TC reset & interrupt
22

23
  /* Setup the VIC for the timer. */
24
  VICIntSelect &= ~( 0x00000010);   //IRQ - Interrupt
25
  VICIntEnable |= 0x00000010;     //TIMER Enable
26
  
27
  VICVectAddr0 = (unsigned long) vTickISR;
28
  VICDefVectAddr = (unsigned long) vTickISR;
29
  VICVectAddr = 0;
30
  VICVectCntl0 = 0x00000024;
31
  
32
  T0EMR = 0x31;     //show match on pin P0.22
33
  T0TCR = 0x00000001;  //Counter Enable
34
  
35
  IOCLR0 = 0x80000000;  //LED1 OFF
36

37
  while(1) {
38
    IOSET0 = 0x40000000;  //LED2 ON
39
    IOCLR0 = 0x40000000;  //LED2 OFF
40
  }
41
  return(0);
42
}
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
Gast #853151
Lesenswert?

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.
OP #853187
Lesenswert?

Hallo Zusammen,

also zuerst danke für eure Bemühungen! Nun...

@Mark: Habe nun folgende ISR:
1
void vTickISR( void )__attribute__ ((interrupt("IRQ")));
2
void vTickISR( void )
3
{
4
  IOSET0 = 0x80000000;  //LED1 ON
5
  T0IR = 0x00000001;  //Clear Interrupt flag
6
  VICVectAddr = 0;
7
}

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
Angehängte Dateien:
Gast #853212
Lesenswert?

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.
Angehängte Dateien:
OP #863483
Lesenswert?

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.ddi0234b/DDI0234.pdf
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
Angehängte Dateien:
#863565
Lesenswert?

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.
OP #863621
Lesenswert?

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();)
1
static int  initialized = 0;
2

3
static void  led_init(void) {
4
  if (!initialized) {
5
    IODIR0 = 0xc0000000;
6
    initialized = 1;
7
  }
8
}
9

10
void led1_on(void){
11
    led_init();
12
    IOSET0=0x80000000;
13
}
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.
OP #863681
Lesenswert?

1
void vTickISR( void ) __attribute__((interrupt("IRQ")));
2
void vTickISR( void )
3
{
4
    led1_on();
5
  //IOSET0=0x80000000;
6
  /* Save the context of the interrupted task. */
7
  portSAVE_CONTEXT();
8
  /* Increment the RTOS tick count, then look for the highest priority
9
  task that is ready to run. */
10
  vTaskIncrementTick();
11

12
  #if configUSE_PREEMPTION == 1
13
    vTaskSwitchContext();
14
  #endif
15

16
  /* Ready for the next interrupt. */
17
  T0_IR = portTIMER_MATCH_ISR_BIT;
18
  VICVectAddr = portCLEAR_VIC_INTERRUPT;
19
    //led1_off();
20
    IOCLR0=0x80000000;
21
    /* Restore the context of the new task. */
22
  portRESTORE_CONTEXT();
23
}

ich könnte sonst auch mal den ganzen code schicken wenn das besser 
währe?
#863697
Lesenswert?

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.
OP #863736
Lesenswert?

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.
1
static void  init_task(void *parameters) {
2

3
    xTaskHandle blinkled1, blinkled2;
4

5
    int ld1,ld2;
6

7

8
    //create a tasks
9
    ld1 = xTaskCreate(blink_led1,(signed char *)"led1",512,NULL, 1, &blinkled1);
10
    ld2 = xTaskCreate(blink_led2,(signed char *)"led2",512,NULL, 1, &blinkled2);
11

12
  /* init task terminates */
13
  vTaskDelete(NULL);
14
  taskYIELD();
15
}
16

17
int  main(int argc, char *argv[]) {
18

19

20
    init_pll();
21
    led2_on();
22
    led2_off();
23

24
    xTaskHandle inittask;
25

26
    xTaskCreate(init_task, (signed char *)"init", 256, NULL, configMAX_PRIORITIES - 2, &inittask);
27

28
  /* start the scheduler */
29
  vTaskStartScheduler();
30
  while(1);
31
}
OP #863955
Lesenswert?

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):
1
SWIAddr:       .word SWIHandler
durch
1
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

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