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.

Keine Kommentare:

Kommentar veröffentlichen