Posts mit dem Label PIC werden angezeigt. Alle Posts anzeigen
Posts mit dem Label PIC werden angezeigt. Alle Posts anzeigen

Montag, 25. April 2016

DevelOS Struktur

Ich habe mal ein Diagramm erstellt um die grundlegende Struktur von DevelOS aufzuzeigen.
Leider ist es im Moment nicht wirklich so lauffähig, wie ich es gerne hätte. Bei der erweiterung habe ich wohl einige inkompatibilitäten erzeugt, und die Performance lässt auch stark zu wünschen übrig. Teile des Systems werde ich wohl neu schreiben müssen. Aber die Struktur will ich gerne so belassen. Noch rot eingezeichnet ist das Konsolen-Modul. Das habe ich erst jetzt implementiert. Mir ist aufgefallen das der Zugriff auf den Buffer des Display-Moduls problematisch sein kann. Außerdem hätte ich die gesamten Ausgabe-Routinen für den UART nochmal neu schreiben müssen. Also habe ich mich entschloßen den Buffer und die Ausgabefunktionen aus dem Display-Modul heraus zu nehmen. Dieses Modul macht jetzt nur noch die Initialisierung und das Übertragen vom Konsolenbuffer in den Hardware-Puffer des jeweiligen Display Moduls. Allerdings ist da noch so einiges im argen. Ich glaube ich habe da noch jede Menge Speicherlöcher drin.
DevelOS Struktur
Wie man hier sieht belegt DevelOS selbst einen großen Teil der externen Schnittstellen des PIC. Es verwaltet den Taktgenerator, die AD Wandler und das EEProm. Über IO-Pins können weitere Geräte angebunden werden.
Freestyle-I2C
Im Moment habe ich an meiner Testplatine ein 4x20 Zeichen LCD Display angeschloßen, sowie zwei kleine I2C-EEproms. Eines ist ein Atmel 32kbit-EEPROM das nur eine Bus-Adresse hat, aber intern mit 16bit Adressen arbeitet. Das andere ist ein ST 8kbit, das intern mit 8 bit adressiert wird, dafür aber in 4 Bänke unterteilt ist, die jeweils über eigene Bus-Adressen angesprochen werden. Eine gute Möglichkeit, um einen wirklich universellen Treiber zu schreiben, der beide EEPROMs ansprechen und für das DevelOS einheitlich darstellen kann. Sie sind zwar etwas abenteuerlich angeschloßen, aber im Prinzip funktioniert es. Den UART habe ich auf eine Buchse heraus geführt, aber bisher funktioniert er nicht richtig. Da der PIC im Moment nur mit dem internen Oszillator läuft, ist die Baudrate wohl zu ungenau. Die Buchse habe ich von einem alten Mainboard geerntet. Eigentlich ist es ein Audio-Anschluß für ein CD oder DVD Laufwerk. Die drei belegten Pins machen ihn aber für alles mögliche einsetzbar, und die etwas besseren Kabel für diesen Port sind sogar abgeschirmt. Damit will ich später mal die
Verbindung von diesem PIC-Board zu meinem Server herstellen. Auf dem Bild hier links sieht man das Display, und die zwei Ports die ich eben beschrieben habe. Der linke, schwarze davon ist an den UART angeschloßen, der andere ist noch nicht belegt. geplant hatte ich dort den I2C-Bus heraus zu führen, um zusätzliche Chips mit anbinden zu können. Ganz am linken Rand sieht man oben den Anschlußblock für die Stromversorgung und den Anschluß der Lüfter, die der PIC einmal regeln soll. Die Stiftleiste rechts neben den Widerständen ist ein Anschluß für die Spannungen des ATX-Netzteils. Diese soll der PIC ebenfalls überwachen und dem Banana Pi über den UART mitteilen. Unter dem Anschlußblock links sieht man auch noch zwei Transistoren die ich ebenfalls von alten Mainboard habe. Für die Steuerung von Lüftern sind sie mit einer Schaltleistung von über 100 Ampere zwar völlig überdimensioniert, aber hey, was nichts kostet ist auch nicht verschwendet.


Zwischen dem Anschlußblock und dem Kabel für das Display sieht man noch den Anschluß für das Programmiergerät. Dafür verwende ich eine ehemalige PS2-Buchse. Ich wollte mein Programmiergerät nicht jedes mal wieder an eine Stiftleiste anschließen, sondern eine komfortable Möglichkeit haben ein Gerät auch von außen zu Programmieren.

Der weitere Ausbau gestaltet sich jedoch schwierig, da das Programm jetzt nur noch etwas mehr als 100 mal pro Sekunde durch läuft. Dabei wird aber schon zwei mal das Display neu geschrieben und einige Timer laufen. Es kann jedoch noch einiges optimiert werden. Zum Beispiel wird die Uhr im Moment von einem 8-bit Timer abgeleitet mithilfe eines Software-Zählers. Das ist extrem ineffizient. es wäre deutlich besser hierfür einen 16-bit Timer mit entsprechenden Preloadwerten zu verwenden.Und wenn ich mir die Zeit nehme, finde ich bestimmt noch hundert weitere Möglichkeiten zur Optimierung. Leider habe ich das Profiler-Plugin für MPLab-X nicht, und will auch keine 45 Euro dafür bezahlen. Also werde ich wohl so zurecht kommen müssen.

Hier nochmal ein Link zum Projekt auf Github: https://github.com/Stefanie80/DevelOS.X/tree/experimental

Samstag, 23. April 2016

DevelOS auf github

Ich habe mein DevelOS jetzt auf github veröffentlicht.
Am Anfang war es noch etwas gewöhnungsbedürftig, aber ich hab die Bedienung hin bekommen.

Leider läuft das System so wie es gerade ist nicht richtig. Vermutlich wird irgendwo eine Variable überschritten oder so, aber das habe ich auf die schnelle nicht gefunden. Es tritt interessanter Weise nur im production Image auf, das Debug Image läuft gut.

Die Sources sind hier zu finden: https://github.com/Stefanie80/DevelOS.X

Hoffe das es noch jemandem was bringt ...

Montag, 11. April 2016

DevelOS

Neben meiner Bastelei an PCs und meinem lokalen Netzwerk, beschäftige ich mich seit ein paar Jahren auch immer wieder mit der Programmierung von Microchip PIC Microcontrollern. Was ich daran besonders faszinierend finde ist die direkte verschmelzung von Code und Hardware, und das man damit quasi jedes Stückchen Elektronik irgendwie nutzen und ansprechen kann.
Inzwischen habe ich auch schon eine Menge kleinere Projekte umgesetzt, leider sind meine, teilweise sehr ausführlichen, Posts dazu verloren gegangen als blog.de abgeschaltet wurde.

Heute möchte ich etwas vorstellen was eigentlich eher ein Meta-Projekt ist. Wer sich mit PICs beschäftigt wird meistens recht schnell merken, das man bestimmte Funktionen immer wieder braucht, und dank der Programmierbarkeit in C kann man das meiste auch wiederverwenden. Aber dann muss man es immer wieder in ein neues Projekt kopieren, und mit neuen Funktionen zusammenbringen. Natürlich geht das, aber ich fand nach einiger Zeit ziemlich umständlich.

Daher habe ich irgendwann mal eine Art minimales Betriebssystem gebastelt, das beinahe beliebige Aufgaben erfüllen kann. Der Kern davon ist eine Pipeline, in die Nachrichten gesetzt werden können, die dann der Reihe nach abgearbeitet werden. Das passiert in einem einzigen langen switch()-Statement, das für jedes definierte Event ein Stückchen Code enthält.

Ein Beispiel:

Man verwendet einen AD-Kanal und möchte diesen periodisch auslesen. Am effektivsten geht das, indem man die Konvertierung startet, und dann auf den Interrupt wartet das der AD fertig ist. Dann bekommt man die Rohdaten zurück, die man dann umrechnen muß, um den tatsächlichen Wert zu erhalten. In meinem System sind das mehrere Events.

1. Das RTC-Modul meldet, das eine bestimmte Zeitspanne abgelaufen ist.
2. Dies löst ein Event aus um eine neue Konvertierung zu starten
3. Der AD konvertiert, die Rückgabe erfolgt per Interrupt
4. Im Interrupthandler wird nur ein neues Event erstellt, das die Rohdaten enthält
5. Die Rohdaten werden konvertiert, das Ergebnis wird wieder als Event in die Pipeline geschrieben
6. Je nach Funktion kann dieses Event wieder neue Events triggern, die Ausgabe auf ein Display z.B.

Das sieht auf den ersten Blick vielleicht etwas kompliziert aus, und mancher wird sich denken "Aber ein PIC hat doch gar keine RTC!". Nun, die RTC war eine der ersten Funktionen die ich auf diese Weise implementiert habe. Ein 16bit-Timer löst einen Interrupt aus, das wird als Event in die Pipeline geschrieben, und löst das hochzählen der RTC aus. Dort können wiederum andere Events ausgelöst werden. So kann man zum Beispiel angeben, das die Refresh-Routine für ein Display in einem bestimmten Intervall aufgerufen werden soll.

Das ist der Kern des DevelOS. Darum herum habe ich dann einige Module gebaut, z.B. das RTC-Modul, mehrere Module um Displays anzusprechen, ein Modul zur Verwaltung des internen EEProm und ähnliches. Um nicht jedes mal unnötig viel Speicher im PIC zu belegen, habe ich das ganze mit #define-Statements und #ifdef-Blöcken organisiert, so das man nur wenige Zeilen verändern muß um ganze Codeblöcke zu aktivieren, die über ettliche Dateien verteilt sein können.

Neben dieser rudimentären Modularisierung erreicht man auf diese Weise auch noch ein relativ gut funktionierendes Pseudo-Multitasking. Weil alles über die Pipeline läuft, können mehrere Aufgaben quasi nebeneinander laufen. Man muß nur aufpassen das man sie in möglichst kleine Stückchen zerlegt, so das der Chip mit einem einzelnen Event nicht zu lange hängen bleibt. In dem obigen Beispiel könnte man ja auch die Umrechnung des AD-Wertes direkt in der Interrupt-Routine unterbringen, aber das könnte eventuell die RTC aus dem Takt bringen.

Vielleicht erstelle ich dafür auch irgendwann ein Github-Projekt, mal sehen. Falls jemand Interesse an dem Code hat, darf mich gerne per Kommentar o.ä. kontaktieren, prinzipiell bin ich gerne bereit den Code zu teilen, unter der Bedingung, das darauf aufbauender Code wieder dem Gesamtprojekt zugute kommt.