Forum: Projekte & Code AVR Macro für Statusmaschine


von rapid (Gast)


Lesenswert?

Hi,
ich bin ein AVR neuling und möchte in C ein ATMega324P programmieren.
Mein Problem (aber ich bin mir sicher dass viele andere ein solche Macro 
brauchen könnten) ist eine sehr schnelle und effektive Umsetzung der 
Switch Case Anweisung für die Programmierung von Statusmaschinen.

Ein Macro könnte da helfen.
Ich nenne es CHOICE(char index)
Eine Variable enthält die Adressen von bis zu 255 Labels.

Diese Macro springt entsprechend dem Index in die Labels ,führt das 
Programmteil aus und springt dann am ende zu CHOICE_END.

Der Vorteil ist das man nur ein Sprung benötigt statt bis zu 255 
Abfragen.

Mit Codevision habe ich eine ähnliche Lösung schon realisiert:

eine Menge an Funktionen in der Form....
void Status1(void){....}
void Status2(void){....}

einen Feld....
int Z_choice[2...] (void)= {Status1, Status2...};

der Aufruf....
(*choice[index])();

Der Nachteil ist der relativ große Overhead durch Calls und die 
etsprechende push und pops, die mehr resourcen als das nutzprogramm 
verbrauchen.

Hat jemand ein Vorschlag wie ein solcher Macro aussehen könnte?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

rapid schrob:

> der Aufruf....
> (*choice[index])();
>
> Der Nachteil ist der relativ große Overhead durch Calls und die
> etsprechende push und pops, die mehr resourcen als das nutzprogramm
> verbrauchen.
>
> Hat jemand ein Vorschlag wie ein solcher Macro aussehen könnte?

Warum sollen das Funktionen sein? Wenn du den Call-Overhead sparen 
willst tun's doch auch switch/case.

Einguter Conmpiler macht da keine 256 Verleiche, sondern arbeitet 
entweder über ne Sprungtabelle oder splittet die Vergleiche binär, so 
daß man mit ner handvoll Vergleichen am Ziel ist.

Und Calls brauchen nicht soo viel Overhead in nem optimierenden 
Compiler.

Falls du Hack magst, bleibt noch die Möglichkeit von computed goto 
(GNU-C)
1
void foo (int i)
2
{
3
   void ** ll[] = { &&L1, &&L2, ...};
4
5
   goto *(ll[i]);
6
7
L1: ...
8
L2: ...
9
...
10
}

Und es gibt die Möglichkeit, Funktionen zu inlinen, was ebenfalls 
Optimierungspotential offen legt. Weil die Funktionen wohl (statisch) 
nur 1x aufgerufen werden (was ein guter Compiler ebenfalls ausnutzt, 
wenn du ihm die Info gibst, d.h. es muss nichtmal explizit geinlint 
werden).

...und du bist im falschen Forum...

von Genervter (Gast)


Lesenswert?

> ich bin ein AVR neuling

Und offensichtlich auch Neuling beim lesen...

von Manuel S. (thymythos) Benutzerseite


Lesenswert?

Noch ein schönes Kapitel fürs AVR-GCC-Tutorial...

von Rapid (Gast)


Lesenswert?

Hallo Johann,
vielen Dank für dein Vorschlag.
Immerhin  bist Du sachlich, im Gegensatz zu den viele Schlauberger 
danach. Ich bin mir sicher, dass auch sie mal feuchte Windeln hatten und 
Gott sei dank war jemand da der sie gewechselt hat...oder doch nicht?

Leider funktioniert das computed goto nicht mit mein Compiler
(Codevision 2) und es ist unnötig zu sagen was ein gute Compiler machen 
würde wenn.... ja wenn.. die Götter mit dem Programmierer gesprochen 
hätten... Diese Compiler macht es nun mal nicht.
switch() case wird in assembler als eine Ansammlung von if blabla else 
blabla  realisiert.
Er akzeptiert LabelNamen nicht als Pointer und kann kein
void ** ll[] = { &&L1, &&L2, ...}; und goto *(ll[i]);
Das ist ein Manko in Codevision 2.
Den habe ich für teures Geld gekauft und nun muss ich damit leben.

In meine HW-Anwendung zählt jede us, denn diese und manche andere 
Routinen werden ständig wiederholt.

Meine Idee war ein Assembler macro ein zu setzen der im Grunde ein 
computed Goto realisiert und nicht vom Compiler abhängig ist.

Trotz Recherchen habe ich nichts dergleichen gefunden.
Ich bin überzeugt dass ein solche Macro universell verwendbar ist.

PS.: wenn ich im falschem Forum bin gibt es hier was besseres?

von Manuel S. (thymythos) Benutzerseite


Lesenswert?

Rapid wrote:
> Hallo Johann,
> vielen Dank für dein Vorschlag.
> Immerhin  bist Du sachlich, im Gegensatz zu den viele Schlauberger
> danach. Ich bin mir sicher, dass auch sie mal feuchte Windeln hatten und
> Gott sei dank war jemand da der sie gewechselt hat...oder doch nicht?

Ich hoffe nicht, dass du mich damit gemeint hast. Ich wollte mit meinem 
Beitrag nur ausdrücken, dass dies ein häufiges Problem, gerade auch für 
Anfänger ist und man es deshalb im Tutorial behandeln sollte.

> switch() case wird in assembler als eine Ansammlung von if blabla else
> blabla  realisiert.

Der Compiler (Codevision vermutlich auch) hat normal eine Heuristik mit 
der er versucht die bessere Lösung zu finden. Jump tables werden z.B. 
dadurch verhindert, dass der Wertebereich der Variablen nicht bekannt 
ist (kann man dem GCC durch Definition eines enum mitteilen) oder die 
abgefragten Werte nicht zusammenhängend sind.

Vielleicht hilft dir auch das weiter: http://www.netrino.com/node/137

von Genervter (Gast)


Lesenswert?

@rapid:  Ja, ich war auch mal AVR Anfänger. Aber zu dem Zeitpunkt, war 
ich schon ca. 10 Jahre lang in der Lage, folgenden Satz zu verstehen:

> Wenn ihr eigene Programme oder Anleitungen geschrieben habt könnt ihr sie
> hier posten. Fragen werden gelöscht!

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.