Forum: Mikrocontroller und Digitale Elektronik ARM Cortex M3 Interrupt Probleme


von Christoph L. (lassi)


Lesenswert?

Hallo,

ich hab ein mehr oder minder schweres Problem. Ich versuch so weit wie 
es geht ein OS für ein Arduino-Due oder allgemein für den Atmel SAM3X8E 
zu programmieren. Deshalb benutze ich den gleich als 
Entwicklungsplattform.

Das komplette Projekt kann man hier einsehen: 
https://github.com/CsharpLassi/DueOS

So mein Problem ist wenn ich nur eine bestimmte Zeile (makierte Zeile) 
aus einer Funktion entferne macht meine Funktion was sie soll.
1
irqstate* HandleSysCall(irqstate* state)
2
{
3
  uint32_t* addr = (uint32_t*)(state->pc -2);
4
  uint8_t value = (*addr) & 0xFF;
5
6
  switch (value)
7
  {
8
    case 0:
9
      state =  closecurrenttask();
10
      break;
11
    case 1:
12
      state->r0=(uint32_t)pmm_malloc(state->r0); // <<---- makierte Zeile
13
      break;
14
    default:
15
      break;
16
  }
17
18
  return state;
19
}
20
21
irqstate* handle_irq(irqstate* state)
22
{
23
  IPSR_Type type;
24
  type.w = __get_IPSR();
25
26
  switch (type.b.ISR)
27
  {
28
    case 0:
29
    case 1:
30
    case 2:
31
      break;
32
    case 3:
33
    case 4:
34
    case 5:
35
    case 6:
36
      handle_fault_irq(type.b.ISR,state);
37
      break;
38
    case 15:
39
      state = nexttask(state);
40
      break;
41
    case 16:
42
      state = HandleSysCall(state);
43
      break;
44
    default :
45
      break;
46
  }
47
48
  return state;
49
}
1
asm_handle_irq:
2
  mov r0, sp
3
  add r0, #32
4
  push {r0}
5
6
  push {r4-r11,lr}
7
  mov r3,lr
8
  mov r0,sp
9
10
  bl handle_irq
11
12
  mov sp, r0
13
  mov lr, r3
14
15
  pop {r4-r11}
16
  pop {r1} // altes lr
17
  pop {r0}
18
  sub r0, #32
19
  mov sp,r0
20
21
  bx lr

Zur Erklärung die Funktion asm_handle_irq wird bei einem Interrupt 
aufgerufen, um alle Register zu speichern. Die C-Funktionen übernehmen 
dann das speichern und viele andere Aufgaben. Damit hab ich jetzt schon 
Multithreading implementiert was auch ohne Probleme funktioniert. Aber 
wenn ich mein SysCall einbauen will für malloc kommt es beim ersten 
SystemTick zu einer Excetion und ich weiß nicht warum, weil der Code 
auch nicht ausgeführt wird.

Wenn die Zeile drinnen ist bekomme ich eine Usage-Exception. Ich weiß 
das der Compiliere die beiden Funktionen zusammen nimmt, aber kennt 
jemand eine Limitierung der CPU was die Länge von Interrupts oder 
ähnlichem Angeht

Ach Ja, wenn ich das Problem behoben hab kommt eine große Aufräumaktion 
was Namen von Funktionen angeht.

viele dank und viele grüße
Lassi

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Christoph L. schrieb:
> Wenn die Zeile drinnen ist bekomme ich eine Usage-Exception.

Der CM3 hat doch diverse Register, in denen die Ursache der Exception
benannt wird (ggf. halt auch die Adresse).  Die würde ich mir als
erstes mal anschauen.

von Jim M. (turboj)


Lesenswert?

Christoph L. schrieb:

> bl handle_irq
>
>   mov sp, r0
>   mov lr, r3

Ist R3 nicht ein Clobber Register? Dann wäre das nach handle_irq 
invalid.

>  push {r4-r11,lr}
> [...]
>  pop {r4-r11}
>  pop {r1} // altes lr

Müsstest Du da nicht R1 vor R4-R11 poppen? Bin mir jetzt aber nicht 
100% sicher, aber einer der Befehle muss "rückwarts" arbeiten.

Es wäre schön zu erfahren wo genau der Fault auftritt (Single-Step)?

von Christoph L. (lassi)


Lesenswert?

Hallo,

@Jörg Wunsch:
Jep es steht in endlichen vieles drinnen, aber ich kann mir den halt den 
Effekt nicht erklären.

@Jim Meba:
Das mit R3 ist ein Punkt, wobei ich es nicht ganz verstehe siehe:
Wenn ich die Zeile Auskommentiere steht da:
1
irqstate* handle_irq(irqstate* state)
2
{
3
   804d4:  b508        push  {r3, lr}
4
   804d6:  4601        mov  r1, r0

Wenn ich die Zeile drinne lasse steht dann das da:
1
irqstate* handle_irq(irqstate* state)
2
{
3
   804d4:  b510        push  {r4, lr}
4
   804d6:  4604        mov  r4, r0

gut ich glaub das sollte der Fehler sein. Da springt er dann irgendwo in 
den Speicher und das ist natürlich nicht valide.

Das muss ich aber morgen mal testen.

Ach und zum Schluss ist noch zu deiner Frage:
Naja das Pop{R0] mach ich nur das der Wert aus dem Stack kommt den ich 
für Debug hinzugefügt hab. Das eigentliche R0 wird von der CPU nach dem 
Rücksprung bei bxlr gemacht.

viele grüße
Lassi

von Christoph L. (lassi)


Lesenswert?

Hallo,

so das hat soweit geklappt.
Vielen dank an dieser Stelle.

viele grüße
Lassi

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
Noch kein Account? Hier anmelden.