Forum: Mikrocontroller und Digitale Elektronik LPC2129 Problem mit CAN-Interrupt


von Klausi (Gast)


Lesenswert?

Hallo zusammen,
ich sitze gerade an einem Problem mit dem CAN-RX-Interrupt am LPC2129. 
Und aus irgendwelchen Gründen bin ich zu dämlich, das Problem zu finden. 
:(
Also ich habe ein Prog auf dem LPC2129, was Timer, UART, EINT etc via 
Interrupt bedient. Das funktioniert auch einwandfrei.
Jetzt wollte ich noch einen Interrupt für den Empfang eines CAN-Frames. 
CAN funktioniert prinzipiell auch (TX, RX im Polling-Betrieb, keine 
Übertragungsfehler gesehen).

Den Interrupt registriere ich wie die anderen auch am VIC:
1
VICVectAddr0 = (unsigned long) CAN1_ISR;
2
VICVectCntl0 = VICVectCntlEn | VIC_CAN1RX;
3
VICIntEnable |= (1<<VIC_CAN1RX);
meine Interrupt-Routine schaut folgendermaßen aus:
1
#define ISR void __attribute__ ((interrupt("IRQ")))
2
ISR CAN1_ISR(void)
3
{
4
  // Interrupt-Source suchen
5
  unsigned long ICR = CAN1ICR;
6
  if(ICR & CANICR_RI) {      // Receive-Interrupt
7
    CAN1_RI();
8
  }
9
10
  // Acknowledge IRQ
11
  VICVectAddr = 0;
12
}

Wenn ich direkt in der ISR arbeite, funktioniert das Ganze (CAN1CMR = 
CANCMR_RRB;). Auch lokale Variablen kann ich beackern.
Wenn ich das Puffer-Auslesen in einer Unterroutine mache, dann hängt 
sich der Controller auf. Zumindest wird kein Interrupt mehr aufgerufen. 
Durch Ausgaben am UART habe ich herausgefunden, daß er zumindest das 
VICVectAddr=0 noch ausführt.
Solange ich die Unterfunktion als Inline deklariere, mag es noch. Aber 
das hilft mir nichts, wenn ich später mal Callbacks (Funktionsvariablen)
integrieren möchte. In den anderen IRQs funktioniert das übrigens auch 
zuverlässig; habe ich schon über Tage im Dauerbertieb getestet.
In der Interrupt-Tabelle (Startup-Code) springe ich direkt zur ISR, also 
keine nested Interrupts. In allen übrigen ISRs funktioniert das auch
einwandfrei. Stackgröße IRQ-Mode = 0x100. Die anderen ISRs brauchen 
definitiv mehr und funzen trotzdem.

Da mein OpenOCD nicht mit dem Prozessor mag, kann ich auch nicht genau 
sagen, wo er hängenbleibt. Keine Ahnung, was da los ist; mit dem 
AT91SAM7x
lief es auf Anhieb. Schaltungsaufbau JTAG mit Pull-down am RTCK, den 
Rest schon gemäß Olimex-Vorlage ergänzt. Aber das ist eine andere 
Baustelle -
es gibt es zum Glück den UART-Bootloader...  ;)

Compiler ist WinARM-20080110. Glaube aber irgendwie nicht, daß es ein 
Compiler-Problem ist. Sonst würde der Rest ja auch nicht gehen, oder?

Weiß jemand, woran das mit dem CAN-Interrupt scheitern könnte? Oder 
zumindest wo ich zu suchen habe?

Danke!
Klausi

von (prx) A. K. (prx)


Lesenswert?

Irgendwo habe ich gelesen, dass GCC beim Stackframe von IRQ-Funktionen 
ab und zu Mist bauen kann (nachdem ich in den entsprechenden Code in GCC 
reingesehen hatte wundert mich nur, dass dies nicht noch öfter 
geschieht). Könnte sich lohnen, mal im generierten Code nachzusehen, ob 
das zutrifft.

Ich ziehe es auf ARM7 vor, Interrupts über einen zentralen Wrapper 
laufen zu lassen. Damit werden IRQ-Funktionen zu normalen Funktionen und 
dieses Problem kann jedenfalls nicht auftreten.

OpenOCD funktioniert mit diesem Controller. Bzw. funktionierte damals, 
als ich eine solche Lösung (LPC2119 mit CAN) zurechtgebastelt hatte. 
Tipps dazu habe ich aber keine, da ich mittlerweile von OpenOCD/Eclipse 
weg bin.

von Klausi (Gast)


Lesenswert?

Hallo A.K.
Danke für die Antwort!

Das mit dem Stack-Frame verstehe ich ehrlichgesagt nicht ganz. Der Stack 
wird vom Core umgeschaltet. Meinst Du, daß der Compiler beim Rücksprung 
einfach nicht mehr vernünftig aufräumt?
Wie sieht denn bei Dir der Wrapper aus? Eine zentrale Funktion in C, die 
angesprungen wird, die Spungadresse vom VIC ausliest und ggf ausführt?
Sowas ähnliches kenne ich aus den Startup-Codes von den 
AT91sam7x-Beispielen. Da gibt es noch eine zentrale Assembler-Funktion, 
die die C-ISR aufruft. Zentral deshalb, weil es da noch Aufräumarbeiten 
am VIC zu erledigen gibt, die überall gleich sind.
Vielleicht kann ich das ja portieren.Warum Atmel seine Beispielcodes 
immer mit nested Interrupts macht, ist mir hingegen ein Rätsel... 
Wieauchimmer.

Ich schaue mir den Code mit Insight an.
Danke!

Klausi

von (prx) A. K. (prx)


Lesenswert?

Klausi schrieb:

> Meinst Du, daß der Compiler beim Rücksprung
> einfach nicht mehr vernünftig aufräumt?

Ja. Wie oft das vorkommt weiss ich nicht und auch nicht ob dies dein 
Problem ist.

> Wie sieht denn bei Dir der Wrapper aus? Eine zentrale Funktion in C, die
> angesprungen wird, die Spungadresse vom VIC ausliest und ggf ausführt?

Ja. Und die danach gleich noch dem VIC die Quittung mitteilt. Sind ein 
paar Zeilen Assembler-Code im Startup.S.

> Vielleicht kann ich das ja portieren.Warum Atmel seine Beispielcodes
> immer mit nested Interrupts macht, ist mir hingegen ein Rätsel...

Weil dies zu den Vorzügen des Interrupt-Controllers von Atmel ist. NXPs 
alter VIC ist in dieser Hinsicht etwas umstritten.

von Klausi (Gast)


Lesenswert?

Ich schaue mir heute abend den kompilierten Code gezielt an. Lustig 
wird's nicht (mittlerweile ~51kB), aber mit dem MAP-File nebendran 
sollte es gehen.
Dann schauen wir mal. Wenn das ein Problem mit dem Compiler ist, werde 
ich den ASM-"Zwischenschritt" auf alle Fälle implementieren. So 
zeitkritisch ist die Anwendung dann auch wieder nicht.

Das mit Atmels VIC mag stimmen. Ich habe es entfernt, weil mir Zweifel 
an der Stackgröße kamen. Ist halt schwierig vorherzusagen, weil bei mir 
praktisch alles in ISRs läuft. Widerspricht zwar der landläufigen 
Meinung, hat sich aber mittlerweile über Jahre in verschiedensten 
Projekten bewährt.
Jedem Tierchen sein Pläsierchen...  ;)

Nochmals Danke für den Hinweis mit dem Stack-Frame!!!
Ich gebe nochmal Bescheid, wenn ich da definitives weiß.

von Klausi (Gast)


Lesenswert?

Das mit dem ISR-Makro scheint tatsächlich ein etwas tiefer verwurzeltes 
Problem zu sein.
Habe jetzt zunächst mal die Routinen umgestellt, die bisher auch 
funktionierten. Dabei ist folgendes Phänomen aufgetreten:
Der RTC-Timer, der nur ein bißchen LED blinken läßt, läuft stabil. Wenn 
Timer dazukommen, die mehr bedienen (z.B. UART=Konsole), dann stürzt der 
LPC ab. => Stackproblem?
Bis hierher lief der IRQ im IRQ-Modus mit 256 Byte Stack. Mit ISR-Makro 
stabil, ohne nicht.

Jetzt also meinen ASM-Handler geändert, daß der C-Handler im 
Supervisor-Mode läuft wie das Hautprogramm auch. Dieser Stack ist bei 
mir nach unten offen.
Jetzt läuft es stabil. Das Prog ist übrigens auch ~100Byte kleiner 
geworden.

Ergo: Da liegt wohl was im Pfeffer... und sei's nur ein Teil des Hasen. 
;)

Weiter geht's mit dem ursprünglichen Problem: dem CAN-IRQ.

von Klausi (Gast)


Lesenswert?

Ich bin vorsichtig optimistisch. Der CAN funktioniert auf Anhieb...

Bleibt mir nur ein fettes DANKE an A.K.!
Den Fehler hätte ich wohl nie selbst gefunden.

MERCI!!!

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.