Demo-Projekt ARM LPC2292/94 =========================== Verwendete Hardware: SO-Dimm-Base Board von Embedded Artists mit uCLinux Quickstart Board v1.1 Dieses Board ist ausgerüstet mit einem LPC2292 Controller und besitzt ein externes, 16 Bit breites PSRAM. Details siehe www.embeddedartists.com. J-Link USB JTAG Adapter von Segger, www.segger.com Logicport 34 Channel Analyzer von Intronix,www.pcTestInstruments.com Verwendete Software und Tools, Entwicklung erfolgt unter XP: Compiler, Debugger aus WinARM Version 20060606 von Martin Thomas, http://www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects/index.html#winarm IDE Code::Blocks, www.codeblocks.org Terminalprogramm Termite, www.compuphase.com/productapps_en.htm Anwendung: Als Ausgangsbasis wurde das Paket LPC2148_Demo_v120 von J.C. Wren, erhältlich bei jcwren.com/arm, verwendet. Das Paket von J.C. Wren ist ein ausgezeichnetes Beispiel, welches das gesamte Spektrum abdeckt, welches vom LPC2148, FreeRTOS und GCC geboten wird. Ich empfehle dringend, zuerst die Ausführungen in der README von Wren bzw. sein Demo-Projekt zu studieren. Ich habe dieses Projekt lediglich an die HW des LPC2292 bzw. LPC2294 auf dem oben angeführten Entwicklungsboard angepasst. Weggefallen ist daher die Unterstützung des USB-Ports, dazugekommen sind die CAN -Schnittstellen. Weitere Änderungen sind: Anstatt des Multitaskers FreeRTOS wurde der TNKernel von Yuri Tiomkin (www.tnkernel.com) eingesetzt. Das FAT-Filesystem von Elm Chan (elm-chan.org/fsw/ff/00index_e.html) wurde auf Version R0.06 gebracht. Die MMC-Anbindung (low-level Routinen) wurden ebenfalls weitgehend von Elm Chan übernommen. Mit den von J.C. Wren verwendeten Treibern liefen nicht alle MMC-SD Karten. Download: http://members.aon.at/gpra/2294tnk.zip Beschreibung: Meine Zielsetzung ist ein schlankes und schnelles System, welches aus einem Multitasker, einem Filesystem und einem proprietären CAN- Bus besteht. Die Demo von Wren war eine ausgezeichnete Ausgangsbasis, an dieser Stelle meinen herzlichen Dank dafür! Leider läßt sich die Wren-Demo nicht so ohne weiteres unter WinARM übersetzen, Schuld daran ist die NewLib, welche sich in den aktuellen Versionen durch reentrante Fähigkeiten auszeichnet. Abgesehen von den nicht unerheblichen Änderungen, welche die zusätzlich notwendigen Stubs verursachen, ist der Preis für reentrante Eigenschaft ein hoher, für mich ein zu hoher. Konkret gibt es da den Impure-Pointer und die zugehörige Datenstruktur, welche von allen reentranten Funktionen benützt und daher vom Linker angelegt wird. Damit ist auf einen Schlag ca. 1K RAM weg, was bei den zur Verfügung stehenden 16K für mich unerträglich ist. Der Nutzen steht in keiner Relation: man kann eine Error-Variable abfragen und aus der Impure Struktur erfahren, warum ein konkurrierender File- oder Streamzugriff gescheitert ist. Lustig finde ich auch, dass diese Struktur auch dann angelegt wird, wenn die NewLib ohne reentrante Eigenschaft übersetzt wird! Das ist z.B. bei der Yagarto Distribution der Fall. Für das konkrete Projekt geht der Nutzen gegen Null, weil das Elm-Chan Filesystem nicht reentrant ist. Die Absicherung gegen nicht erlaubte konkurrierende Zugriffe erfolgt daher mit einer Mutex. Leider gibt es anscheinend keine Alternative zur NewLib, ich verwende daher deren Funktionen nur sehr verhalten. Auch der Code von Yuri Tiomkin geht in diese Richtung, so dass von putchar() bis printf() alles alternativ erstellt wurde. Auch malloc() musste eigenen Routinen weichen. Das vorliegende, sehr schlichte Mem_Alloc verwendet an Stelle einer verlinkten Liste eine Bitmap zur Kontrolle der Speicherbelegung. Zusätzlich kann gewählt werden, ob internes oder externes RAM alloziert werden soll. Kernel: Der TNKernel erscheint mir insgesamt schlanker und weniger mit Features überladen als FreeRTOS. Er ist sehr nahe an die ARM- Architektur angepasst und sehr klar strukturiert. Preemptives Multitasking, welches bei FreeRTOS die Standardbetriebsart zu sein scheint, erachte ich für Microcontroller-Anwendungen für wenig notwendig. Auch im kooperativen Modus wird ein Task, der z.B. in einer Endlos-Schleife läuft, unterbrochen, sobald ein höher priorisierter Task aktiv wird. Beim TNKernel kann, falls gewünscht, Round- Robin gezielt aktiviert werden. Interrupts: IRQ-Interrupts werden vom VIC vektorisiert. Der Kernel verwendet einen PWM- Kanal zur Erzeugung eines 1ms Interrupts. Die Timer sind somit dzt. unbenutzt. Im tn_cpu_irq_handler wird mittels tn_tick_int_processing das Task- Switching durchgeführt. Weiters werden die UARTS gepollt, derzeit nur UART0. Ja, richtig: die UARTS lösen keinen eigenen Interrupt aus. Diese Methode ist wesentlich effizienter, weil die UARTS ein 16 Byte Fifo besitzen und somit locker die Zeit bis zum nächsten 1ms -IRQ überstehen, ohne dass der Fifo überläuft. Das funktioniert bestens bis einschließlich 115200 Bd. Für jedes Zeichen einen Interrupt auslösen ist Resourcenverschwendung! Die Problematik sporadischer Interrupts ist mit einem default- Handler abgedeckt und der Assemblercode entsprechend der NXP- Empfehlung ahingehend angepasst, dass IRQ- und FIQ-Flag nicht im selben cpsr-Zugriff gesetzt werden. Der FIQ wird dem CAN-Bus zugewiesen. CAN-Bus: Für die Demo wurde ein Task angelegt, welcher periodisch Daten im Kanal 1 versendet und eingehende CAN-Messages entgegennimmt. Der Sender wird mit einem Monitorkommando aktiviert: "misc cantx 1" und mit "misc cantx 0" wieder abgeschaltet. Es müssen externe CAN-Bus- Treiber angeschlossen sein, ansonsten versagt die Initialisierung der HW. Alle an den Bus ngeschlossenen CAN-Receiver empfangen die Daten und lösen einen RX- Interrupt aus. Alle CAN-Rx-Interrupts landen in der selben FIQ-ISR. Die eingehenden CAN-Messages werden eine Daten-Queue gestellt. Der CAN-Task nimmt die Messages am anderen Ende der Queue heraus und gibt sie via Console aus. Ich habe mein Demo-Board auf einen LPC2294 umgerüstet und kann somit alle 4 Kanäle nutzen. Außerdem wurde der Quarz von 14.7456 MHz auf 12 MHz getauscht, damit die für CAN üblichen Baudraten erreicht werden können. Quarzfrequenz und Controllertyp sind in config.h definiert. FAT Filesystem, MMC-SD: Leider besitzt der LPC2292/94 erst in neueren Versionen SSP, der Datenstrom muss daher mit dem langsameren SPI-Interface erzeugt werden. Je nach SD-Karte lassen sich damit Transferraten bis ca. 230 KByts erreichen. Im Monitor ist dafür ein Test eingebaut, "thruput" ohne Parameter. Wie schon erwähnt, sind alle File-Funktionen per Mutex gesichert. Alle File- Funktionen beginnen mit einem Underscore und unterscheiden sich etwas vom üblichen Standard: der Rückgabewert ist 0 oder positiv für erfolgreiche Aktionen, negative Werte sind die Fehlercodes. Die Enumeration der Fehler wurde in ff.h entsprechend geändert. Monitor: Vieles, was nur in der Wren-Demo Sinn macht, wurde entfernt. Die Stringkonstanten sind aus dem data- in den text-Bereich gewandert. "mem stacks" zeigt die System- und Task-Stacks mit Auslastung an. "mem map" zeigt die Speicherzuordungen an. "misc cantx 0|1" zum Testen der CAN-Busse. RTC: Die RTC des LPC2292/2294 kann leider nicht unabhängig von der CPU mit Backup- Strom betrieben werden. Auf die Zeitumrechnungen via NewLib wurde aus o.a. Gründen komplett verzichtet. Die RTC wird dzt. nur vom Filesystem benutzt, alle von J.C. Wren eingeführten Kommandos funktionieren aber. Entwicklungsumgebung Das Projekt compiliert und läuft fehlerfrei unter WinARM und sollte auch in anderen Umgebungen funktionieren. Im Makefile kann als RUN_MODE entweder Flash oder EXTERNES RAM auf 0x81000000 gewählt werden. Mit U-boot im Flash und einem TFTP-Server kann eine sehr bequeme Übertragung ins X-RAM erfolgen. Damit das auch mit einem 12MHz-Quarz funktioniert, habe ich U-Boot entsprechend angepasst. Dieses U-Boot Image liegt hier: http://members.aon.at/gpra/u-boot-2294-12.zip Mit LPC21ISP und dem Philips-Flash-Tool funktioniert die Baudratenerkennung bei 12MHz nur bis 38400 Bd. Debuggen: Die Embedded-Artists Basisplatine hat einen Fehler in der Belegung der JTag- Stiftleiste. Pin 15 (Reset) ist dort mit dem Signal RST- out verbunden, Pin 15 muss natürlich mit RST-in verbunden werden! Das Debuggen mit dem J-Link-Adaper und GDB funktioniert bestens. Der Start von GDB kann z.B. mit der Batch-Datei Debug_RAM.cmd erfolgen, die Monitor- Kommandos stellen den J-Link auf die korrekten Parameter ein. Als bester Debug-Parameter für GCC hat sich ggdb3 erwiesen. Damit wird auch der Inhalt der LPC21xx.h mit den Registerdefinitionen in die Debug- Info gestellt. Allerdings kennt z.B. GDB 6.8.50 aus Yagarto diese Definitionen nicht mehr unterhalb des main()-Levels, GDB 6.6 dagegen schon. IDE: Eine tolle (und freie) IDE ist Code::Blocks. Obwohl für Embedded- Projekte noch nicht optimal angepasst, ist diese Umgebung sehr, sehr brauchbar und gefällt mir besser als Eclipse. Die Übersetzung kann per Makefile oder aus eigener Kraft per Projektverwaltung geschehen. Ich bevorzuge letzteres, die Einstellmöglichkeiten lassen keine Wünsche offen. Das einzige Problem in der aktuellen Version 8.02 ist das Remote- Debuggen. Es gibt da zwei Problempunkte: a) Start der Debuggersitzung: Unter Properties/Debugger/Additional Commands/After Connection/ werden die Kommandos eingetragen, die das JTag-Interface per monitor xxxx konfigurieren. Dort sind üblicherweise auch die Kommandos um das Target zu laden, starten und bis zum ersten Breakpoint auf main() zu fahren. Klickt man anschließend in der IDE die Schaltfläche Debug/Continue, dann sendet diese das Kommando run, sollte natürlich continue sein. Je nach GDB- Version wird das entweder ignoriert oder GDB verabschiedet sich. b) Break-Signal Wenn man das Target per continue ohne erreichbaren Breakpoint laufen lässt, kann man den Ablauf nur stoppen, indem man Ctrl-C an den Debugger sendet. Wohlgemerkt ist das aber kein Tastendruck, sondern ein Signal, welches vom Betriebssystem gesendet werden muss. Aufgrund von Windows-Gegebenheiten funktioniert das derzeit nicht, unter Linux aber wohl. Man kann das Target also nie mehr anhalten und muss den GDB-Server beenden, damit es weitergeht. Ich habe mich in der SVN-Version von Code::Blocks umgesehen und kann dzt. folgende Lösungen anbieten: a) Bei Remote-Sitzungen wird immer continue gesendet b) Weiss zu wenig über Wxsmith, WxWidgets um das Problem grundsätzlich lösen zu können, kann aber einen praktikablen Workaround anbieten: Der Debuggerprozess erstellt ein (leeres) Konsolenfenster. In diesem kann man dann bei Bedarf das rettende Ctrl-C eintippen und landet dann mit gestopptem Target wieder in der IDE. Ich stelle meinen modifizierten Code::Blocks zum Download bereit. Zusätzlich zu o.a. Änderungen ist Patch #2458 eingearbeitet. Es sind nur die gezippten Files, falls das nicht laufen sollte, dann zuerst CB 8.02 installieren. http://members.aon.at/gpra/CodeBlocks.zip Ich hoffe aber doch, dass die CB-Entwickler nicht locker lassen und ihre Ankündigungen bzgl. Embedded Entwicklung bald wahr machen! Erstellt am 16. 9. 2008 G.P.G
> ... was bei den zur Verfügung stehenden 16K ...
Soweit ich mich erinnere hat das SO-DIMM Board von EA einige Megabyte
Pseudo-SRAM auf dem Board. Die muss man nur aktivieren.
Hi Gottfried, vielen Dank für diesen Post. Ich versuche derzeit die YAGARTO GNU ARM toolchain, CodeBlocks v8.02 und den AT91SAM7X256 (OLIMEX SAM7-EX256 + ARM-USB-TINY) unter einen Hut zu bringen. Allerdings bin ich bisher gescheitert. Ich habe ein "Empty Project" als Ausgangspunkt gewählt und unter "Project build options" die Compilereinstellungen konfiguriert (einige Checkboxen + "Other options" -mcpu=arm7tdmi -T sram.lds). In den "Project/targets options" habe ich zudem die Checkbox "Auto-generate filename extension" deaktiviert und den "Output filename" auf *.elf gesetzt. Ergebnis ist zwar ein *.elf-File, aber das scheint nicht zu funktionieren. Kannst du eine Beschreibung geben, wie du vorgegangen bist bzw. was du alles wo eingestellt hast? Vielen Dank Daniel
Hallo nochmal, hab's hin bekommen. Wenn mann die Linker-Option "-T sram.lds" als Compiler-Option angibt geht's halt nicht. Jetzt stehe ich vor dem Debugging-Problem, das du oben beschrieben hast. Werde mich da jetzt reinarbeiten und ggf. nochmal melden. Daniel
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.