Hallo Leute, nun, der ARM7 (LPC21xx) läuft und läuft, ganz gut, ich möchte nur noch mal heraus finden, ob ich mit einfachen Mitteln den Code vereinfachen und die Performance verbessern kann, ohne der Anwendung zu schaden. Ich möchte heute mal in Erfahrung bringen, in welchem Mode man seine Anwendung auf einem ARM7 sinnvoll betreiben kann. Nicht, daß ich die Modes und deren jeweilige Einschränkung und Vorteile nicht kenne. Gehen, tut ja vieles, und im Grunde kann ich auch machen was ich will, Hauptsache die Anwendung läuft hinterher sauber. Aber: ARM gibt in seinen Manuals die bevorzugte Benutzung des USER-Modes an, stellt aber andere Modes zur Debatte. Im USER-Mode jedoch, ist man auch am weitesten in der Benutzung des Controllers eingeschränkt. Ein Kollege, mit anderen ARM, ARM9, beschäftigt, sagte mir dazu, der USER-Mode sei schon sinnvoll, verhindere eine Menge Unfug und unstrukturierte Programmierung. Nun, ich kann das noch nicht ganz nachvollziehen. An anderen Stellen liest man wieder Diskussionen, ob der Betriebsmode der Anwendung der USER-Mode, SYSTEM-Mode oder SUPERVISOR-Mode sein kann. Meine Anwendung läuft zur Zeit im USER-Mode. Möchte ich Teile des Codes gegen alle IRQ gesperrt haben, z.B. so sensible Dinge wie FIFO-Zugriffe, die keinesfalls reentrant sein dürfen, muß ich diese im SWI-Mode laufen lassen, da aus dem USER-Mode kein Zugriff auf CPSR, um IRQ- und FIQ- Line direkt zu sperren. Interrupt-Sperre geht aus dem USER-Mode nur über VIC mit Sicherung aller Flags in einer Variablen. Im SYSTEM-Mode könnte ich Interrupts IRQ und FIQ direkt über CPSR sperren und hätte den Code-Overhead des SWI nicht. Die SWI-Numerierung muß ich unter GCC oder RealView parallel an 2 Stellen und zwar für das SWI-Assembler-File und in einem C-Header-File verwalten. Bei Fehlern in der Numerierung, gibt es keine Compiler-Errors, weil logische Fehler. Hinzu kommt, daß es auch mehrere Targets gibt, wobei jeweils Teilmengen der SWI-Funktionen benötigt werden. Das macht das ganze zur Compile-Time schon störungsanfällig. Keil CARM, 2005 eingestellt und nicht mehr zur weiteren Verwendung empfohlen, generiert die SWI-Tabelle noch automatisch, da fiel eine der beiden Definitionsquellen weg, und es war problemlos. Das sind jetzt nur mal ein paar Überlegungen, Details und Anregungen. Wer hat denn da gute Erfahrung mit der einen oder anderen Lösung? Gruß Dietmar
Ich sehe wenig Sinn darin, auf einem Controller mit in jedem Modus unbeschränker Adressierfähigkeit ein paar kleine Systemfunktionen wie Interrupt-Steuerung über User/System Trennung einschränken zu wollen. In Controllern ohne MMU gibt es heutzutage keine unkontrollierten Anwenderprozesse, vor denen sich zu schützen es sich lohnt. Diese Trennung ergibt erst dann wirklich Sinn, wenn der Adressraum eines USER Prozesses auf seine eigenen Code+Daten-Bereiche beschränkt ist, d.h. eine MMU verwendet wird. DANN erst entsteht durch die Privilegientrennung ein erhebliches Mass an Sicherheit. Die meisten Programmfehler entstehen in C durch unbeabsichtigten Speicherzugriff, nicht durch unberechtigte Interrupt-Steuerung. Historisch gesehen hatte bereits die erste eingesetzte Generation von ARM Prozessoren eine MMU, wenngleich extern. Und so wurde die User/System-Privilegientrennung von Anfang an auch verwendet. Die Eignung von ARM für Embedded Systems war nicht Ziel der Entwicklung sondern ergab sich ursprünglich als Nebeneffekt. Und so steckt das halt auch im ARM7 Core drin, ohne dass es im Kontext monolithischer Microcontroller-Programme sonderlich viel bringt.
> Ein Kollege, mit anderen ARM, ARM9, beschäftigt, sagte mir dazu, der > USER-Mode sei schon sinnvoll, verhindere eine Menge Unfug und > unstrukturierte Programmierung. Könnte daran liegen, dass viele ARM9 Systeme über eine MMU verfügen und nicht selten echte Betriebssysteme wie Linux eingesetzt werden, die eine MMU auch erforderlich machen. ARM7 mit MMU ist hingegen eher selten und die verwendeten Programme sind meist von monolithischem Charakter. Entsprechen also weniger einem PC mit separatem Betriebssystem und all seinen darauf laufenden unabhängigen Programmen als vielmehr einem einzelnen PC-Programm, möglicherweise mit RTOS-Library vgl. manchen älteren reinen Userspace-Threadings in Unix.
Apropos unstrukturierter Code: Es stimmt schon, dass man bei Privilegientrennung dazu gezwungen wird, Funktionen (SWIs) für Interrupt-Steuerung zu verwenden. Nichts und niemand ausser dem inneren Schweinehund hindert einen jedoch daran, auch ohne Privilegientrennung strukturiert zu programmieren. Mit dieser gleichen Logik sollte man lieber nicht in C programmieren. Es gibt weiteraus besser definierte und kontrollierende Programmiersprachen (Ada beispielsweise). Da man jedoch um C in der Praxis meist nicht herum kommt, hat man ohne eine gewisse Disziplin hinsichtlich Programmiertechnik und Programmstrukturierung ohnehin schnell verloren. Um zu einem konkreten Beispiel zu kommen: Was Interrupt-Steuerung angeht, kommt man mit C++ weitaus weiter. Darin sieht eine vor Interrupt geschützte Funktion nämlich so aus:
1 | void
|
2 | UARTbase::put(int c) |
3 | {
|
4 | OS::Critical cs; |
5 | if (txidle) { |
6 | uart->thr = c; |
7 | txidle = false; |
8 | } else { |
9 | tx.put(c); |
10 | }
|
11 | }
|
Die ganze Interrupt-Steuerung steckt hier in Konstruktur (save+disable) und Destruktor (restore) vom Objekt "cs". Insbesondere kann man so nicht versehentlich vergessen, die Interrupts wieder einzuschalten (per return irgendwo zwischendrin) weil der Compiler selber dafür sorgt, dass der Destruktor garantiert und an der richtigen Stelle aufgerufen wird. Ob man in der Implementierung von OS::Critical die Interrupt-Flags direkt steuert oder auf SWIs abstützt, ist dann gleichwertig, das eine nicht sicherer als das andere. Und weil das Zeug ggf. nur aus inline-Funktionen besteht, ist es auch effizient.
> Die SWI-Numerierung muß ich unter GCC oder RealView parallel an 2 > Stellen und zwar für das SWI-Assembler-File und in einem C-Header-File > verwalten. Warum? > Wer hat denn da gute Erfahrung mit der einen oder anderen Lösung? Ich benutze einen ARM7, bei dem das Programm im System-Modus läuft. Ich sehe keinen Sinn darin, die Interruptsperrung durch einen SWI zu leiten. Letztendlich kann das Programm dann immer noch die Interrupts sperren, wenn auch nur indirekt. Welche Fehler willst du konkret dadurch vermeiden?
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.