Forum: Mikrocontroller und Digitale Elektronik ATMega und Threads?


von Mats M. (elektrofreak)


Lesenswert?

Hallo,

ich überlege für ein Projekt eine Art Betriebssystem zu verwenden oder 
selber zu schreiben.

Meine Idee war folgende:
- Folgende Komponenten sollten angesteuert werden:
  - LC-Display
  - I²C-Peripherie (mehrere ICs)
  - UART-Kommunikation (38.400 Baud)
  - Auswertung des/der ADC
  - Steuern von Peripherie
  - Berechnung von Werten aus den Daten der I²C-Peripherie
- Der UART muss wegen des kleinen Puffers eine hohe Priorität haben
- Da viele ICs am I²C-Bus hängen, dürfte dort viel gewartet werden auf 
ankommende Daten
- Es soll pro Aufgabe einen Thread geben, der einfach angehalten wird, 
wenn auf die Fertigstellung einer Sache (z.B. das Absenden eines Bytes 
über den I²C-Bus und das Ack des Slaves) gewartet wird, sodass z.B. das 
nächste Zeichen für das LC-Display auf den Bus gelegt werden kann
- Es werden Statusbytes verwendet, sodass ein Thread weiß, ob er 
weiterarbeiten darf oder z.B. auf die Aktualisierung eines Wertes warten 
muss.
- Praktisch gesehen könnte in der Mainloop eine Liste an Threads 
nacheinander oder Priorisiert gestartet werden und es wird immer bis zum 
nächsten "Breakpoint" gerechnet und dann zurück zur Mainloop gesprungen. 
Dann wird der nächste Thread wieder angestoßen.
- Es würde dann (für jeden einzelnden Thread) entweder
  - Eine Integervariable die aktuelle Position speichern und über 
swtich/case ein entsprechender Block gestartet (dürfte bei vielen 
Blöcken viele Rechnungen ergeben)
  - Die aktuelle Position wird in einer Variable gespeichert und dorthin 
wird beim erneuten Aufruf gesprungen
  - Ein Array beinhaltet Pointer auf Funktionen, die die Teilaufgaben 
eines Threads sind. Somit erreicht man sofort die "Unterfunktion" eines 
Threads

Alternativ könnte man natürlich zu den sog. Real-Time-Betriebssystemen 
greifen. Gelesen habe ich z.B. von FreeRTOS. Jedoch habe ich davon keine 
Erfahrung und würde ggf. lieber auf eine performantere Eigenentwicklung 
setzen.

Was für Vorschläge habt Ihr? Ich würde mich sehr über Anregungen und 
Kritik freuen ;-)


Mit freundlichen Grüßen
Mats Marcus

von Peter D. (peda)


Lesenswert?

Mats Marcus schrieb:
> - Da viele ICs am I²C-Bus hängen, dürfte dort viel gewartet werden auf
> ankommende Daten

"dürfte" sollte ein Programmierer nicht verwenden, sondern "wissen".
Du mußt ausrechnen, wie hoch der benötigte Datendurchsatz ist.
Vielleicht ist ja I2C garnicht geeignet für Deine Anforderungen.

Eine Lösung ist das Round-Robin Verfahren. Du legst im SRAM 
Schattenregister für alle I2C-Peripherie an. Und der I2C-Interupt 
schreibt und liest alle ICs immer der Reihe nach.
Das Main benutzt dann nur die Werte in den Schattenregister.


Peter

von weinbauer (Gast)


Lesenswert?

Nennt sich State Machine, was DU da vor hast und ist schon sehr 
fortgeschrittene Programmierkunst.
Die Hardware unterstützt aber schon einige der Funktionen, z.B. TXC- / 
RXC-Interrupts.

von Mats M. (elektrofreak)


Lesenswert?

zur zeit steht leider noch nicht fest, wie viele I²C-ICs an den Bs 
angeschossen werden und wie oft die Daten benötigt werden. Bei 400kHz 
dürften es ja ca. 20-25kByte/s sein, wenn die Übertragung 1 Adressbyte + 
1 Datenbyte groß ist. Ich denke dass ggf. ADCs noch etwas Wartezeit 
benötigen (müsste da mal in die Datenblätter schauen).

Es wird also schon schnell genug sein aber bei der Anzahl der 
Komponenten denke ich, macht es schon sinn, sich mit dem Gedanken der 
Threads zu beschäftigen.

Mit freundlichen Grüßen

von Peter D. (peda)


Lesenswert?

Mats Marcus schrieb:
> Es wird also schon schnell genug sein aber bei der Anzahl der
> Komponenten denke ich, macht es schon sinn, sich mit dem Gedanken der
> Threads zu beschäftigen.

Hast Du denn mehrere I2C-Busse?


Peter

von Mats M. (elektrofreak)


Lesenswert?

nein, nur den einzigen Hardware-Bus (ATMega 2560).

Allerdings habe ich auch andere Hardware wie die LCD-Displays

von xxx (Gast)


Lesenswert?

ein süßer kleiner kernel für avr:
http://www.barello.net/avrx/

von willibald (Gast)


Lesenswert?

Mats Marcus schrieb:
> Alternativ könnte man natürlich zu den sog. Real-Time-Betriebssystemen
> greifen. Gelesen habe ich z.B. von FreeRTOS. Jedoch habe ich davon keine
> Erfahrung und würde ggf. lieber auf eine *performantere Eigenentwicklung*
> setzen.

Um diesen Plan beurteilen zu können, muss man wissen, was für dich 
"performant" bedeutet. Und wieso du glaubst, erprobte Systeme wie 
FreeRTOS mal so eben übertreffen zu können.

Mats Marcus schrieb:
> - Praktisch gesehen könnte in der Mainloop eine Liste an Threads
> nacheinander oder Priorisiert gestartet werden und es wird immer bis zum
> nächsten "Breakpoint" gerechnet und dann zurück zur Mainloop gesprungen.
> Dann wird der nächste Thread wieder angestoßen.

Was du da "Thread" nennst, ist nach verbreiteter Definition kein Thread, 
sondern eher ein "Job". Der gerade laufende Job hat dabei die absolute 
Macht. Er entscheidet, wie lange er läuft und wann (und ob überhaupt) er 
die Kontrolle an die Mainloop zurückgibt.

Mats Marcus schrieb:
> - Folgende Komponenten sollten angesteuert werden:
>   - LC-Display
>   - I²C-Peripherie (mehrere ICs)
>   - UART-Kommunikation (38.400 Baud)
>   - Auswertung des/der ADC
>   - Steuern von Peripherie
>   - Berechnung von Werten aus den Daten der I²C-Peripherie

Das sind recht viele Anforderungen, die sich auch voneinander stark 
unterscheiden. Dein "Jobsystem" muss so allgemein sein, dass es das 
alles ermöglicht. Und dann auch noch performant. Keine kleine Aufgabe.

> - Der UART muss wegen des kleinen Puffers eine hohe Priorität haben
> - Da viele ICs am I²C-Bus hängen, dürfte dort viel gewartet werden auf
> ankommende Daten
> - Es soll pro Aufgabe einen Thread geben, der einfach angehalten wird,
> wenn auf die Fertigstellung einer Sache (z.B. das Absenden eines Bytes
> über den I²C-Bus und das Ack des Slaves) gewartet wird, sodass z.B. das
> nächste Zeichen für das LC-Display auf den Bus gelegt werden kann
> - Es werden Statusbytes verwendet, sodass ein Thread weiß, ob er
> weiterarbeiten darf oder z.B. auf die Aktualisierung eines Wertes warten
> muss.

Also priorisierte Aufgaben und Aufgaben, die zwischendurch unterbrochen 
werden können und bei Eintreten einer Bedingung fortgesetzt werden 
sollen.
Das ist das typische Anforderungsprofil für ein RTOS.

Ich würde dringend empfehlen, dass du dich erst mal mit einem RTOS 
beschäftigst. FreeRTOS ist ein guter Kandidat. Und erst, wenn es sich 
als untauglich erweist, solltest du über eine Eigenerfindung nachdenken.

Gruß,
willibald

von Tom M. (tomm) Benutzerseite


Lesenswert?

Es gibt viele Scheduler und kleine OS für AVRs. Ich arbeite mit pico]OS, 
v.a. weil mir die Lizenz am besten passt, der Kernel gut konfigurierbar 
ist, die Sourcen lesbar sind (C).

Eine Herausforderung ist noch, den Stack für die Threads zu verwalten. 
Mit der Standardeinstellung (128 Bytes Stack pro Thread) ist man zwar 
auf der sicheren Seite, verbrennt aber viel kostbares SRAM. Wenn du 
einen atmega mit 1K SRAM oder mehr einsetzt, reicht das aber ne Weile. 
Wenn du einen Thread pro Funktionsblock verwendest, reicht das locker 
noch für ein paar Message Boxen, Mutexen, Ringpuffer etc.

Für die Peripherie kannst du ja mal mit der avrlib schauen und 
abkupfern, ausser du willst alles von Grund auf selbst implementieren. 
:)

von Mats M. (elektrofreak)


Lesenswert?

Ich denke dass der Einsatz eines vorhandenen OS (habe auch FemtoOS im 
Auge) viele Vorteile mit sich bringen wird. Ich werde mich da auch als 
nächstes erst mal einlesen und dann überlegen, ob ich den Aufwand 
eingehen möchte, selber was zu schreiben :-)

Vielen Dank für Eure Hinweise


Mit freundlichen Grüßen
Mats Marcus

von JW (Gast)


Lesenswert?

Hallo Marcus,

bin bin auch so einer, der lieber selbst was optimales schreibt/baut.

Aber dann doch bei FreeRTOS hängen geblieben, um (irgendwann) meine 
Heizung mit damit zu steuern. Das ist zwar nicht 100% optimal auf die 
AVR's zugeschnitten, weil es eben auch andere unterstützt, man könnte 
das ein oder andere Byte RAM sparen, usw.
Aber am Ende habe ich statt Mega32 einen 644 (ein 1284 liegt auch schon 
da) genommen und geniese, dass es jemanden gibt, der das Ding pflegt.

Auch bei der Hardware hab ich mich zu fertigem durchgerungen: MicroSPS. 
Die kann man ja auch in gnuC(++) befehligen.
Die shared die Anschlüsse von LCD und Tasten. ADC oversampled, wegen 
Temperaturmessung mit LM335 auf 12bit und ca. 10 samples/s auf 4 
Kanälen, nach Korrektur eines Designfehlers in der MicroSPS.
UART über OS-Queue geht. Treiber für I2C ist designed, aber wartet noch 
auf Implementierung.
Soweit wäre ich alleine nie gekommen.
(Auch wenn ich schon seit 35 Jahren Lötkolben halten kann und seit 25 
Jahren alles von Mainframe bis runter zu AVR programmiere.)

Gruß,
Jürgen

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
Noch kein Account? Hier anmelden.