PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : TreiberBibliothek in ISO C99 für RNControl



DerMaddin
19.10.2008, 20:13
Hallo ;)

Ich habe das Wissen aus dem Roboternetzforum zusammengetragen und alle Treiberfunktionen des ATMega32 und des RNControl Boards in einer Bibliothek untergebracht. Der gesamte Code ist in ISO C 99 geschrieben, von einem Codebeautifier formatiert (GreatCode) und einer statischen Codeanalyse mit SPLint unterzogen worden (und natürlich ohne Warnungen des SPLint kompiliert). Das ArchiveFile kann in eine Applikation eingebunden werden.

Ich stelle euch hier zwei Versionen zur Verfügung: Die kleinere ist ein normales Release - Build und die größere gibt auf dem Terminal aus, wenn eine Funktion oder ein Interrupt betreten oder verlassen wurde. Das ist beim Debuggen hilfreich.
Wer jetzt denkt, dass die 33k große Bibliothek nicht in den 32k großen Speicher des ATMega passt, liegt falsch. Denn beim Linken gegen diese Bibliothek werden nur die Informationen verwendet, die im Programm benötigt werden.

Eine Besonderheit gibt es beim Thema Interrupts zu beachten. Alle Interrupts werden prinzipiell immer in der Bibliothek abgefangen (IRQ_Enable() muss natürlich vorher einmal ausgeführt werden). Um jetzt Funktionssprünge aus der Bibliothek heraus in Interrupthander zu ermöglichen, existiert diese Variable:

FunctionPointer interruptCallbacks[21];

Dieses Array aus Funktionszeigern ist standardmäßig mit Nullen befüllt. Eine Applikation, die diese Bibliothek verwendet, definiert sich einen Funktionspointer und fügt diesen an die entsprechende Stelle in diesem Array. Ein Enumerator hilft dabei. Um ein Beispiel zu zeigen:

static void RS232ReceiveHandler(void)
{
UInt16 receivedData = RS232_ReadData();

}

void SetInterruptCallbacks(void)
{
interruptCallbacks[RS232ReceiveComplete] = &RS232ReceiveHandler;
}

Diese Funktionen müssen void zurückgeben und dürfen keinen Parameter erhalten, um mit der ArrayDeklaration konform zu sein. Alle Datentypen sind in einem extra Header zu finden. Ich stelle die gesamten Sourcen ebenfalls zur Verfügung, damit ihr mir sagen könnt, wo man noch tweaken kann.

Ich stelle diese Bibliothek noch nicht ins RN-Wissen, weil mir noch ein entscheidender Teil fehlt: Ich habe noch keine verlässliche Implementierung einer passiven und einer aktiven Waitfunktion. Heisst:
Ich versuche noch, ohne Verwendung von Gleitkommazahlen (!) eine Waitfunktion zu schreiben, die in einer Schleife solange zählt, bis eine vorgegebene Anzahl Millisekunden verstrichen ist. Diese Implementierung muss wahrscheinlich von der Taktrate des Controllers, also dem Define F_CPU abhängig sein. Ich suche auch noch eine weitere Funktion, nämlich zum passiven Warten. Sie soll einen Timer starten, in einen Sleepmodus wechseln und nach einer vorgegebenen Zeitspanne wieder aufwachen.
Das wechseln in einen geeigneten Sleepmodus ist ebenfalls nicht Bestandteil der Bibliothek. Vielleicht könnt ihr mir helfen, diese Funktionalitäten (ohne Verwendung von Gleitkommarechnungen) zu implementieren? Das wär cool :)
Warum ist es mir so wichtig, Gleitkommazahlen zu vermeiden? Ganz einfach: Der ATMega32 kann nicht direkt mit Gleitkommazahlen rechnen. Alles wird in Software implementiert und bei Verwendung der Schlüsselwörter „double“ oder „float“ dazu gelinkt. Dummerweise hat das den Effekt, dass die Bibliothek um 12kb größer wird! Das will ich unbedingt vermeiden.

Folgende Funktionalitäten der Lib habe ich mit einer geeigneten Applikation getestet:
Battery, Buttons, LEDs, Speaker, ADC, Interrupts (mit Handlerfunktionen), Memory, Ports, Reset, RS232, Timer, Watchdog.

Ungetestet sind I2C und PWM.

Und jetzt noch ein kurzes HowTo für das Linken gegen diese Lib:

Baut eure Objectfiles wie gehabt mit dem GCC und inkludiert avrlib.h. Erweitert eure LinkerKommandozeile um „-Lk:\\RoboterProject\\App\\Source –lavr”. Das ist das Setzen eines LibraryPaths und das Angeben der Lib, gegen die gelinkt werden soll. Zum Beispiel sieht die Kommandozeile dann so aus:

-mmcu=atmega32 k:\\RoboterProject\\App\\\\Output\\Release\\Interm ediate\\BatteryHandler.obj k:\\RoboterProject\\App\\\\Output\\Release\\Interm ediate\\ButtonHandlers.obj k:\\RoboterProject\\App\\\\Output\\Release\\Interm ediate\\GP2D12.obj k:\\RoboterProject\\App\\\\Output\\Release\\Interm ediate\\InterruptHandlers.obj k:\\RoboterProject\\App\\\\Output\\Release\\Interm ediate\\Main.obj k:\\RoboterProject\\App\\\\Output\\Release\\Interm ediate\\MemoryHandlers.obj k:\\RoboterProject\\App\\\\Output\\Release\\Interm ediate\\SurroundingScan.obj
-o k:\\RoboterProject\\App\\\\Output\\Release\\progra m.elf -Os --relax -Wall,-Map,k:\\RoboterProject\\App\\\\Output\\Release\\pr ogram.map -Lk:\\RoboterProject\\App\\Source -lavr


Helft mir also bitte, die Bibliothek zu vervollständigen, dann kann sie im RN Wissen landen ;)
Ich danke euch schon mal!!

thewulf00
20.10.2008, 09:21
Hallo Maddin!

Eine tolle Bibliothek! Vielen Dank im Namen aller dafür.
Zu Deinen Fragen:
- Zum aktiven Warten kannst Du Dir mal die edelay.h angucken, die es hier im Roboternetz gibt. Es ist eine verbesserte Variante der delay.h, d.h. genauer. Aber ob sie mit Gleitkommazahlen rechnet, weiß ich nicht.
- Zum passiven Warten ist es eben wichtig, dass Du einen ungenutzten Timer nimmst. Wie willst Du das herausfinden? Ansonsten ist die Sleep-Variante "while (1);" eine gute.

DerMaddin
20.10.2008, 09:49
Hi :)

Ja, ich hab mir edelay.h schon angeguckt. Man müßte es ein bisschen umbauen. So, wie es jetzt ist, wird bei jeder Verwendung von delay(X) von Präprozessor ein riesen Codeblock kopiert. Besser wäre eine Implementierung als Funktion. Vielleicht kann ich es verwenden. Ich habe es erst vor Kurzem gefunden.
Es geht mir nicht unbedingt darum, einen ungenutzten Timer zu verwenden. Wer wait() aufruft muss halt damit leben, dass zB Timer 2 belegt ist. Vielleicht kann man auch mittels Parameter bestimmen, welcher Timer benutzt werden soll.
Mit der Variante mit while(1) wird es wohl nicht hin hauen, da die Taktrate nicht einbezogen wird.
...
Ich werd mich mit edelay.h beschäftigen und mich nochmal melden :)

DerMaddin
01.11.2008, 16:54
Hallo nochmal,
ich hab eine Routine für das aktive Warten in assembler gefunden, die sich sehr leicht anpassen läßt. Die SleepModi sollten jetzt auch funktionieren. Ein letzter Punkt fehlt:
Ein passiver Wartemodus, der einen Timer benutzt. Ich hab inzwischen das ganze Forum durch und komm nicht klar. Ich wüßte gern, die man z.B. Timer 0 so einrichtet, dass er alle 1ms einen interrupt wirft. Ich hab einen ATMega32 mit 16MHz und alle Fusebits sind so eingestellt wie im Auslieferungszustand.
Kann mir jemand erklären, wie ich diesen Timer hinkrieg?
Vielen Dank!

DerMaddin
05.11.2008, 09:22
Hallo nochmal,

schade, dass hier keiner mit mir redet. Aber nach endlosen Stunden im Forum hab ich jetzt alle fehlenden Funktionalitäten nachgerüstet :)
Im beiliegenden Zipfile findet ihr ein Architekturschema, ein Releasebuild, ein Build mit Traces und natürlich die Sourcen.

Nochmal kurz zur Verwendung:
Beim Kompilieren einfach den Header inkludieren. Beim Linken "-L" und den Pfad zur Lib angeben: "-LCode/Sources" (dabei kein Leerzeichen nach dem "L"), und noch die Lib selbst angeben. Dabei den Präfix "lib" und den Suffix ".a" weglassen, das weiss der Linker selbst. Also:
"-LCode/Sources -lavr". Das ist alles.

So fängt man einen Interrupt ein:

static void RS232ReceiveHandler(void)
{
UInt16 receivedData = RS232_ReadData();

}

void SetInterruptCallbacks(void)
{
interruptCallbacks[RS232ReceiveComplete] = &RS232ReceiveHandler;
}

Bitte testet die Lib ein bisschen, dann kann man sie ins RNWissen stellen!
Danke schonmal!

sternst
05.11.2008, 09:47
Bevor du es irgendwo veröffentlichst, solltest du vielleicht nochmal über den Namen nachdenken. AVRlib (-lavr) ist doch reichlich allgemein und kollidiert daher sicher schnell mit der einen oder anderen "privaten" Library. Wenn die Library schon für etwas spezielles ist, sollte sich das auch im Namen widerspiegeln. Z.B. RN-Control-Lib und dann -lrncontrol oder nur -lrnc. Davon abgesehen gibt es schon ein recht umfangreiches Projekt mit dem selben Namen: AVRlib (http://www.mil.ufl.edu/~chrisarnold/components/microcontrollerBoard/AVR/avrlib/)

DerMaddin
05.11.2008, 10:09
naja, alles, was auf dieser Seite funktioniert, ist die Dokumentation. Alle anderen Links sind tot. Aber du hast recht, ein anderer Name ist sicher nicht schlecht

sternst
05.11.2008, 10:24
naja, alles, was auf dieser Seite funktioniert, ist die Dokumentation. Alle anderen Links sind tot.

Sorry, war wohl ein alter Link.
Diese Seite (AVRlib (http://hubbard.engr.scu.edu/embedded/avr/avrlib/)) sieht zwar auch nicht unbedingt aktuell aus, aber die Links dort funktionieren wenigstens.