Forum: Mikrocontroller und Digitale Elektronik ARM / Keil / Realview: Critical Section


von ARM-Fan (Gast)


Lesenswert?

Hallo!

Hat jemand mal nen  Tipp, wie man beim Realview Compiler
ne "Critical Section" programmiert?

Also was ich beim 8051er einfach in globales Interrupt-Sperren
eingeklammert habe

EA = 0;
// critical section
EA = 1;

funktioniert ja hier beim ARM, insbesondere dem Realview Compiler
nicht, da er mir im Inline Assembler keinen Zugriff auf die
entsprechenden Register gewährt.

Muß ich da nen "echten" kleinen Assembler-Schnipsel programmieren
und den dann aus "C" aufrufen?

Grüße, Frank

von ARM-Fan (Gast)


Lesenswert?

Ok, hat sich erledigt. Habs selbst gefunden...

Sind als Intrinsic-Functions implementiert:

void __disable_irq(void);
void __enable_irq(void);
void __disable_fiq(void);
void __enable_fiq(void);

... falls es noch jemanden interessiert ;-)

von Dietmar (Gast)


Lesenswert?

Welcher Controller? ARM7? RealView, ist sicher ein ARM7-er.

Nun, du hast schon eine Lösung gefunden? Etwas Reflektion über den 
Erfolg, wäre manchmal ganz nett.

Trotzdem, schreibe ich noch ein paar Worte dazu, möchte aber niemanden 
ins Bockshorn jagen. So ein ARM, braucht eben etwas mehr Aufmerksamkeit 
als ein 8051-er. ARM7, nichts was einen weltlichen Bürger vom Stuhl 
haut, aber der macht mir umso mehr Spaß, je mehr ich die Details kenne.

Critical Section: Ich nenne mal ein Beispiel für die LPC21xx/LPC22xx, 
wobei die Watchdog Feed Sequenz niemals von Interrupts unterbrochen 
werden darf, da sonst ganz klar ein Reset stattfindet. Dabei muß der 
Watchdog rechtzeitig nachgeladen werden, das soll schon ein wenig 
berechenbar sein!

Der Watchdog erzeugt einen Reset, wenn Interrupts die Feed-Sequenz 
stören. Aus dem User Manual geht das nicht hervor, auch nicht aus 
ERRATA. Das ist möglicherweise auch kein Bug, sondern eine Design-Frage.

Das Problem mit dem Watchdog z.B. im LPC2129 hatte ich schon Ende 2005 
mal hier gepostet, mittlerweile habe ich den Workaround dazu selbst 
erarbeitet. Zwar verfüge ich nicht über einen In-Circuit-Emulator, 
konnte das Problem trotzdem lokalisieren. Unter anderem installierte ich 
einen Watchdog-Interrupt für den Debugger, der jedoch laut User Manual 
auch nur für Debug-Zwecke vorgesehen ist.

Critical Section könnte so eine Watchdog Feed Sequenz sein, die man 
schon als SWI konfiguriert hat, damit sie nicht mehr von in der Regel 
mehreren konfigurierten IRQ unterbrochen werden kann. SWI: sperrt IRQ 
global.

Jetzt muß man aber auch noch in der Regel einen einzigen FIQ sperren, da 
dieser den SWI durchbrechen würde. Das kann man auf 2 Arten: Erstens, 
durch die von dir schon genannte Intrinsic-Funktion aus dem SWI-Mode, 
und zweitens, durch Sperrung des FIQ im VIC-Controller.

Bei FIQ-Sperrung über die Intrinsic-Funktionen entstehen je nach 
Interruptfrequenz mehr oder weniger so genannte Surprise-Interrupts, man 
bekommt das normalerweise gar nicht mit (es sei denn, man hat einen 
Surprise-FIQ-Handler mit Surprise-Zähler eingebaut gleich am 
Interrupt-Vektor, dann kann man den Zähler im Debugger betrachten), und 
die müssen auch nicht unbedingt stören: Beim Surprise-Ereignis schlägt 
noch ein FIQ während des Sperrbefehls zu und wird vor der Critical 
Section komplett abgearbeitet.

Entscheidend ist hier, wir befinden uns jetzt nach der Sperrung direkt 
an der Feed-Sequenz, wie lange die FIQ-Routine dauert! Denn, der 
Watchdog-Timer läuft, und wartet auf die Nachladung.

Wenn man entscheiden möchte, ob ein über Intrinsic-Funktion gesperrter 
FIQ noch abgearbeitet oder für später (nach Freigabe hinter der Critical 
Section) zurückgestellt wird, braucht man eben einen (zuschaltbaren) 
Surprise-FIQ-Handler in Assembler, direkt am Interrupt-Vektor.

Bei FIQ-Sperrung über den VIC-Controller entstanden bei meinem 
Watchdog-Problem absolut keinerlei Seiteneffekte mehr, auch keine so 
genannten Spurious Interrupts, denn die betreffen den FIQ nicht. Alles 
lief absolut sauber.

Damit wäre das für seltene Fälle im Zweifelsfall die bessere Lösung als 
die Sperrung über Intrinsic-Funktionen.

In einem Header für globale Definitionen definierte ich 3 Makros:

// Für FIQ-Sperrung über den VIC-Controller:
#define VICFIQBIT   (0x01 << 5) // Timer 1
#define DISABLE_FIQ {VICIntEnClr  = (VICFIQBIT);}
#define ENABLE_FIQ  {VICIntEnable = (VICFIQBIT);}

Oder, für FIQ-Sperrung über den ARM-Core:
#define DISABLE_FIQ {__disable_fiq();}
#define ENABLE_FIQ  {__enable_fiq();}

Im gesamten Source-Code, egal welcher Größe, setzt man dann DISABLE_FIQ 
und ENABLE_FIQ an die betreffenden Stellen ein.

So kann man die Art der Sperrung (VIC oder F-Bit im ARM-Core) über den 
gesamten Sourcecode hinweg von einer zentralen Stelle aus vorbestimmen, 
und etwas experimentieren.

Übrigens: Die Intrinsic-Funktionen können nur in Non-USER-Modes 
verwendet werden, da sie im USER-Mode einfach keine Wirkung haben. Da 
sind die Sperrungen über den VIC-Controller vielfältiger.

Den Default-Interrupt-Handler sollte man aber "immer" installiert haben, 
wenn auch nur als leere Funktion. Denn ohne, auch wenn die Anwendung 
wochenlang sauber läuft, und dann aber mal ein Spurious IRQ auftritt, 
stürzt die Anwendung gnadenlos ab.

Gruß

Dietmar

von ARM-Fan (Gast)


Lesenswert?

Wow! Vielen Dank für die superausführliche Antwort!
Muß das erstmal sacken lassen...

Und du hast richtig geraten: ARM7 (LPC23xx) und Keil (RealView) ;-)

von Martin (Gast)


Lesenswert?

Hallo Leute!

Ich selbst habe ein paar CARM-Projekte auf Realview umgestellt.
Dabei habe ich mit dem SWI herumhantiert, weil ich teilweise IRQs 
sperren musste.

Zuerst musste man dort im statup.s-file "IMPORT SWI_Handler"
eingtragen.
Danach das SWI.s inkludieren und in diesem File die einzelnen 
SWI-Funktionen eintragen.

Also total aufwändig.
Als ich euren Beitrag las, war ich positiv überrascht.
Dazu habe ich aus meinem aktuellen Projekt das SWI.S-File rausgeworfen 
und den Eintrag im startup.s-File gelöscht.
Danach habe ich die SWI-funktionen so umgeschrieben, dass die 
nachfolgenden Funkionen zur Anwendung kommen können:

void __disable_irq(void);
void __enable_irq(void);
void __disable_fiq(void);
void __enable_fiq(void);

Leider lässt sich der IRQ dadurch nicht sperren.
Das Programm kann compiliert und in den Prozessor gespielt werden, aber 
die IRQs werden nicht gesperrt.

Was kann ich falsch gemacht haben? Muss man noch etwas Zusätzliches 
beachten?

Danke für eure Antworten.

Tschüss
Martin

von Andreas K. (a-k)


Lesenswert?

Manche Startups halten es für nützlich, das Hauptprogramm im User-Modus 
laufen zu lassen. Dann lassen sich Interrupts nur via SWI sperren.

von Martin (Gast)


Lesenswert?

Ich habe gerade im Reference Guide gelesen, dass die Sperrung nur im 
privileg-mode funktioniert.

Wie kann ich vom user-mode auf den privileg-mode umschalten und wo 
liegen die Unterschiede?

Danke für eure Hilfe.

Tschüss
Martin

von Martin (Gast)


Lesenswert?

Hallo Leute!

Danke, habs schon geschafft.
Der Mode muss lediglich im Startup-File umgestellt werden.
Das PSR-Register muss mit dem entsprechenden Wert versehen werden.

Nur, wozu dient dieser Modus?
Welche Vorteile bzw. Nachteile oder Einschränkungen habe ich
damit?

Danke für eure Antworten.

Tschüss
Martin

von Andreas K. (a-k)


Lesenswert?

Martin wrote:

> Welche Vorteile bzw. Nachteile oder Einschränkungen habe ich
> damit?

Auf ARM7 bietet der User Mode fast keine zusätzliche Sicherheit.

von Martin (Gast)


Lesenswert?

Ich habe jetzt im Datenblatt nachgesehen. Leider habe ich keine Hinweise 
auf verschiedene User-Modes gefunden.

Es ist auch das Register PSR nicht zu finden.

Was meinst du damit, der User Mode bietet fast keine zusätzliche 
Sicherheit?
Besteht eine irgendeine Gefahr, wenn ich den Privileg-Mode in Zukunft 
verwende? Welche Vorteile bzw. Nachteile entstehen dadurch für mich?
Dieser hat den Init-Wert: 0x1F

Mich verwirren die verschienden Modi.

Tschüss
Martin

von Andreas K. (a-k)


Lesenswert?

Sieht so aus, also ob dir die entscheidene Lektüre fehlt: Das ARM ARM 
(ARM Architecture Reference Manual). Gibt's auf www.arm.com zum 
Download.

von ARM-Fan (Gast)


Lesenswert?

Hast du mal 'nen Link zum ARM ARM?

Außer das blaue Buch zum Kaufen finde ich keinen kostenlosen Download.

von Andreas K. (a-k)


Lesenswert?

Diesen Link kriegst du von mir gratis: 
http://www.amazon.com/ARM-Architecture-Reference-Manual-2nd/dp/0201737191/ref=pd_bbs_sr_3?ie=UTF8&s=books&qid=1207047658&sr=8-3

Mich an deiner Stelle auf arm.com suchen lassen kostet jedoch etwas. 
Sind ca. 3 Clicks, alle naheliegend.

von ARM-Fan (Gast)


Lesenswert?

Grrrr, Andreas! ;-)

Ich bin wirklich nicht der dümmste und schon gar nicht der faulste
Googler bzw. Internet-Sucher. Aber ich find das "DDI-0100" nicht
auf der ARM-Seite. Ums verrecken...

von Andreas K. (a-k)


Lesenswert?

Also gut... Documentation / ARM Architecture /
Reference Manuals / ARMv5.

von ARM-Fan (Gast)


Lesenswert?

Och neee. Über die Online-Hilfe bin ich natürlich schon 100x drüber.
Aber dass sich da drin dann nur ein PDF-Link befindet, kann ja keiner
ahnen...

Danke :-)

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.