Moin,
ich habe aktuell folgende Funktion. Diese Minifunktionen sollen aber als
Makros verschwinden, da sie mir die Lesbarkeit des Codes erschweren und
idealerweise sowieso Inline sein sollen. Codegröße spielt keine Rolex,
ist genug Platz da.
1
/* Liefert das TX_DS Flag des Status Register zurück */
2
uint8_tRF_Status_TX_DS(){
3
CSN_LOW;
4
uint8_tstat=SPI_TransferByte(0xff);
5
CSN_HIGH;
6
return(stat&_BV(NRF24L01_TX_DS);
7
}
CSN_LOW und _HIGH sind selbst Makros.
Wie kriege ich es hin, dass ein Makro mit gleichem Namen den 1 oder 0
Wert des letzten Ausdrucks liefert? Ich übergebe ja keinen Parameter wie
x.
Christian J. schrieb:> Wie kriege ich es hin, dass ein Makro mit gleichem Namen den 1 oder 0> Wert des letzten Ausdrucks liefert?
Lass dir den Satz mal auf der Zunge zergehen und überlege, ob du den
Satz selbst verstehen würdest!
Ingo L. schrieb:> Und ich verstehe nichtmal deine Frage
In Foren gehört zu den Grundregeln, dass man nur etwas sagt, wenn man
etwas zur Lösung zu sagen hat und ansonsten schweigt.
Christian J. schrieb:> Ingo L. schrieb:>> Und ich verstehe nichtmal deine Frage>> In Foren gehört zu den Grundregeln, dass man nur etwas sagt, wenn man> etwas zur Lösung zu sagen hat und ansonsten schweigt.
Also Rückfragen sind auch nicht erlaubt?
Schade. Ich wollte dich eigentlich auch gerade bitten, dein Anliegen mit
etwas anderen Worten nochmal zu erklären und eventuell ein Beispiel zu
zeigen, wie du es dir ungefähr vorstellst.
Aber das darf ich ja nicht, also schweige ich jetzt lieber.
Christian J. schrieb:> In Foren gehört zu den Grundregeln, dass man nur etwas sagt, wenn man> etwas zur Lösung zu sagen hat und ansonsten schweigt.
Olle, du bist ja ein ganz Schlauer. In Foren gehört es sich sein Problem
zu so zu schildern das das Forum was damit anfangen kann... Siehe
https://www.mikrocontroller.net/articles/Netiquette
> Wie kriege ich es hin, dass ein Makro mit gleichem Namen den 1 oder 0> Wert des letzten Ausdrucks liefert?
GCC extensions benutzen, die können das. Einfacher, sinnvoller, besser
und überhaupt und sowieso ist aber inlining.
Ingo L. schrieb:> Olle, du bist ja ein ganz Schlauer. In Foren gehört es sich sein Problem> zu so zu schildern das das Forum was damit anfangen kann... Siehe
Nur weil DU etwas nicht verstehst heisst das noch lange nicht, dass das
für das FORUM auch gilt. Und ich ändere da meine Ansichten auch nicht,
wenn man nichts zum Thema weiss hält man den Mund. Und fängt nicht an
mit nervtötenden Rückfragen oder "denk aml selbst nach" den TE zu
nerven. Ich schreibe hier NICHTS rein, was ich selbst ergooglen kann.
Christian J. schrieb:> Und fängt nicht an> mit nervtötenden Rückfragen oder "denk aml selbst nach" den TE zu> nerven. Ich schreibe hier NICHTS rein, was ich selbst ergooglen kann.
Wer lesen kann... Ich habe weder gesagt "denk mal selber nach" noch
"googel selber". Ich habe gesagt:
> Lass dir den Satz mal auf der Zunge zergehen und überlege, ob du den> Satz selbst verstehen würdest!
Soll heissen:
> Und ich verstehe nichtmal deine Frage
Aber da du nichtmal das erkennen kannst, wage ich zu bezweifeln das du
eine Suchmaschine bedienen kannst
Christian J. schrieb:> Nur weil DU etwas nicht verstehst heisst das noch lange nicht, dass das> für das FORUM auch gilt.
Somit kann ICH dir nicht helfen. Sag doch gleich wenn du Hilfe von
speziellen Leuten hier suchst
Christian J. schrieb:> Nur weil DU etwas nicht verstehst heisst das noch lange nicht, dass das> für das FORUM auch gilt.
gilt für mich auch - mist das darf ich gar nicht schreiben.
Christian J. schrieb:> @Moderator: Bitte mal diesen sinnlosen Flamewar "bereinigen", danke!
Ich glaube du würdest ohne einen Regenschirm bei Regen durch deine Nase
ertrinken...
https://stackoverflow.com/questions/2679182/have-macro-return-a-value
Wie schon oben gesagt und auch in stackoverflow erwähnt ist inline
allerdings erheblich sinnvoller als ein Macro.
bdw ... was ist an einem Macro besser lesbar?
Ich finde die Frage von Ingo übrigens keineswegs unangebracht.
Stefan K. schrieb:> erwähnt ist inline allerdings erheblich sinnvoller als ein Macro.
Natürlich, ein Makro is reine Textersetzung, somit Code-bloat ohne ende,
wenn das Ganze mehrmals aufgerufen wird. Gut, bei Inline kommt das Selbe
raus...
Stefan K. schrieb:> bdw ... was ist an einem Macro besser lesbar?
Die Frage stelle ich mir auch gerade
Ingo L. schrieb:> Die Frage stelle ich mir auch gerade
Ich glaube man muss das nicht hinterfragen. Aus dem Verhalten des
Fragestellers kann man schließen dass etwas ganz anderes,
nichttechnisches nicht stimmt.
Eine kurze Suche verrät übrigens, dass der Fragesteller hier seit zwei
Jahren gerne seine (beruflichen?) Probleme lösen lässt, aber in der Zeit
praktisch nie jemandem bei einer Frage geholfen hat. Wenn er einen
Thread nicht selber startet stört er gerne mit einem Problem einen
vorhanden Thread.
Christian J. schrieb:> @Moderator: Bitte mal diesen sinnlosen Flamewar "bereinigen", danke!
Die Rückfragen der Forenteilnehmer hier sind durchaus berechtigt, und
den Flameware ist zum einen kein Flameware (wenn ich hier nicht Mod
wäre, würde ich dir jetzt zeigen, was ein echter Flameware ist), zum
anderen hast du den Verlauf Diskussion mit deiner pampigen Aussage
> Diese Antwort löst nicht mein Problem.
selber zu deinen Ungunsten beeinflusst.
Christian J. schrieb:> Diese Minifunktionen sollen aber als Makros verschwinden, da sie mir> die Lesbarkeit des Codes erschweren
Willst du ein Makro, oder soll genau dieses verschwinden?
> und idealerweise sowieso Inline sein sollen.
Der Code für die Funktion soll also inline generiert werden. Hast du
nachgeschaut, ob das der Compiler nicht sowieso schon macht?
> Codegröße spielt keine Rolex
Aha.
> Wie kriege ich es hin, dass ein Makro mit gleichem Namen den 1 oder 0> Wert des letzten Ausdrucks liefert?
Soll das Makro, ähnlich einer Funktion, einen Rückgabewert liefern?
> Ich übergebe ja keinen Parameter wie x.
Was hat der Rückgabewert mit dem nicht übergebenen Parameter x zu tun?
Ich habe nach etwa viermaligem Durchlesen deiner Anfrage eine ganz
leise Ahnung, was du damit meinen könntest, aber sicher bin ich mir
keineswegs. Wenn ich meiner Ahnung richtig liege, wäre es noch
interessant zu wissen, was sich hinter den Makros CSN_LOW und CSN_HIGH
verbirgt.
Da meine Fragen dein Problem aber nicht direkt lösen, halte ich jetzt
lieber meine Klappe ;-)
Lukas T. schrieb:> Der hat gerade ... seinen Account gelöscht, oder?> Heftig. So löst man Probleme.
Wenn das Problem das Verhalten mancher K.-Chargen im Forum ist, dann ist
auch die einzig richtige Lösung.
Yalu X. schrieb:> Christian J. schrieb:>> @Moderator: Bitte mal diesen sinnlosen Flamewar "bereinigen", danke!>> Die Rückfragen der Forenteilnehmer hier sind durchaus berechtigt, und> den Flameware ist zum einen kein Flameware (wenn ich hier nicht Mod> wäre, würde ich dir jetzt zeigen, was ein echter Flameware ist), zum> anderen hast du den Verlauf Diskussion mit deiner pampigen Aussage
Sorry, aber ich habe den Thread nicht mehr weiter verfolgt, da das Thema
längst entgleist war. Zudem meinen Account, der seit 2004 durchgehend
bestand aus Datenschutzgründen entsorgt, da geht mir einiges zu weit was
hier "geschnüffelt" wird, das habe ich schon mehrmals beobachtet. Es
geht ja auch ohne und mit x-beliebigen Fake-Namen, schliesslich begegnet
man sich sowieso nie im realen Leben. Trotzdem Danke für Deine Mühe noch
etwas Sachliches zum Thema beizutragen.
Christian J. schrieb:> da geht mir einiges zu weit was hier "geschnüffelt" wird, das habe ich> schon mehrmals beobachtet.
Das ist eine ziemlich derbe Unterstellung.
Christian J. schrieb:> Diese Minifunktionen sollen aber als> Makros verschwinden, da sie mir die Lesbarkeit des Codes erschweren und> idealerweise sowieso Inline sein sollen.
Natürlich lässt sich das mit Makros lösen (Hinweis: der Komma-Operator
dürfte dabei möglicherweise hilfreich sein), aber lesbarer ist das
bestimmt nicht.
Schneller als eine inline-Funktion ist es ganz bestimmt auch nicht.
Ich würde mich mit etwas sinnvollerem beschäftigen...
Rufus Τ. F. schrieb:> Christian J. schrieb:>> da geht mir einiges zu weit was hier "geschnüffelt" wird, das habe ich>> schon mehrmals beobachtet.>> Das ist eine ziemlich derbe Unterstellung.
Nein, keinesfalls. Es gibt Leute und dazu gehöre ich, die gern anonym im
Web bleiben möchten, daher nutze ich keine Realnamen. Und es ist nicht
nur einmal passiert, dass ich e-mail bekam oder auch eine Facebook
Anfrage, weil jemand über diese Suche meinen Realnamen in einem Stück
Source von mir fand und dann im Netz damit auf die Suche ging. Es gibt
hier, wie auch sonst überall ziemlich kranke Typen, die einem regelrecht
nachstellen, wenn sie erst einmal "auf Spur sind, namentlich zb
Arduinoquäler, der obwohl ich ihn konsequent ignoriere seit 2-3 Jahren
so als existiere er gar nicht immer wieder aufs Neue versucht mich zu
provozieren, zu einer Reaktion zu bewegen. Das ist schon ziemlich krank.
Markus F. schrieb:> Natürlich lässt sich das mit Makros lösen (Hinweis: der Komma-Operator> dürfte dabei möglicherweise hilfreich sein), aber lesbarer ist das> bestimmt nicht.
Mit den besagten gcc Extension __inline attribute((... geht das auch so
ganz gut. Nur macht eine Fülle von Minifunktionen Code unübersichtlich.
Ich ziehe ein IsDataInBuffer() halt einem kryptischen Ausdruck vor. Nur
habe ich diese Extensions bisher nicht verwendet. Und einem Makro einen
Rückgabewert zu verpassen geht halt über (x), indem man x einen Wert zu
weist. #define ADD(a,b) {a+b} hat als "Rückgabewert"(hust...) a+b, auch
wenn es nur ein Textersatz ist.
Christian J. schrieb:> #define ADD(a,b) {a+b} hat als "Rückgabewert"(hust...) a+b, auch
Yo, und der ist auch noch falsch, wenn man z.B. mit
ADD(x & 0xf, 4)
aufruft (Operator-Precedence). Makros haben ihre Berechtigung. Aber
längst nicht überall und insbesondere nicht dort, wo es bessere Lösungen
gibt.
Christian J. schrieb:> Nur macht eine Fülle von Minifunktionen Code unübersichtlich.
Wieso ist denn eine Fülle an Mini-Makros besser?! Es ist generell
Konsens, dass viele kleine Funktionen wenigen großen Funktionen zu
bevorzugen sind. Eine Funktion macht genau eine Sache, das macht sie
leicht verständlich, wartbar und kombinierbar. Man kann seine Funktionen
ja in einzelne Dateien gruppieren, oder in C++ in einzelne Klassen &
Namespaces.
Klassisches Beispiel: In POSIX gibt es kleine Funktionen fork(), exec(),
dup2() mit denen man einen Prozess erstellen und stdout/in/err umleiten
kann. Die sind viel übersichtlicher als die eine Win32-Riesen-Funktion
CreateProcess, welche über mehrere große Parameter-Structs das gleiche
macht.
Dr. Sommer schrieb:> Klassisches Beispiel: In POSIX gibt es kleine Funktionen fork(), exec(),> dup2() mit denen man einen Prozess erstellen und stdout/in/err umleiten> kann. Die sind viel übersichtlicher als die eine Win32-Riesen-Funktion> CreateProcess, welche über mehrere große Parameter-Structs das gleiche> macht.
blödes Beispiel. Um die gleiche Funktionalität wie CreateProcess zu
erreichen muss man viel mehr code schreiben.
Peter II schrieb:> blödes Beispiel. Um die gleiche Funktionalität wie CreateProcess zu> erreichen muss man viel mehr code schreiben.
Nicht wenn man die dutzenden Zeilen zur Initialisierung der
Parameter-structs mitzählt. Ich beziehe mich hier auch nur auf die
stdout/in/err Funktionalität, die ganzen weiteren Parameter hab ich mal
außer Acht gelassen. Ich will hier auch nicht gegen Windows flamen, das
Win32-API hat auch Vorteile gegenüber beispielsweise dem von Linux.
Christian J. schrieb:> ....meinen Realnamen in einem Stück> Source von mir fand und dann im Netz damit auf die Suche ging. Es gibt> hier, wie auch sonst überall ziemlich kranke Typen, die einem regelrecht> nachstellen, wenn sie erst einmal "auf Spur sind, namentlich zb> Arduinoquäler, der obwohl ich ihn konsequent ignoriere seit 2-3 Jahren> so als existiere er gar nicht immer wieder aufs Neue versucht mich zu> provozieren, zu einer Reaktion zu bewegen. Das ist schon ziemlich krank.
Da gebe ich Dir Recht und sage Dir zum Trost: Da bist Du nicht der
Einzige, der sich mit solchen kranken Typen auseinanderzusetzen hatte.
Christian J. schrieb:> Nein, keinesfalls. Es gibt Leute und dazu gehöre ich, die gern anonym im> Web bleiben möchten, daher nutze ich keine Realnamen. Und es ist nicht> nur einmal passiert, dass ich e-mail bekam oder auch eine Facebook> Anfrage, weil jemand über diese Suche meinen Realnamen in einem Stück> Source von mir fand und dann im Netz damit auf die Suche ging. Es gibt> hier, wie auch sonst überall ziemlich kranke Typen, die einem regelrecht> nachstellen, wenn sie erst einmal "auf Spur sind, namentlich zb> Arduinoquäler, der obwohl ich ihn konsequent ignoriere seit 2-3 Jahren> so als existiere er gar nicht immer wieder aufs Neue versucht mich zu> provozieren, zu einer Reaktion zu bewegen. Das ist schon ziemlich krank.
Anhand dessen und deinem bisherigen Verhalten in diesem Thread schließe
ich, dass du dich wohl öfter mit anderen in die Haare kriegst. Scheinst
ja ein echt feiner Kerl und Sympathieträger zu sein. Was für herzensgute
Menschen hier unterwegs sind, dass überhaupt versucht wird dir zu
helfen.
Dr. Sommer schrieb:> Wieso ist denn eine Fülle an Mini-Makros besser?! Es ist generell> Konsens, dass viele kleine Funktionen wenigen großen Funktionen zu> bevorzugen sind.
Na schau mal, heri drin steckt alles,was der User konfigurieren muss.
Ist der ChanFat Code. Ich finde das sehr praktisch. Ok, vermutlich eine
Debatte um den heissen brei, weil es keinen kompilierten Nutzen bringt
aber wie ich finde schon einen Gewinn an Ästetik.
1
#define SPI_CH 1 /* SPI channel to use = 1: SPI1, 11: SPI1/remap, 2: SPI2 */
Ich finde das im Gegenteil besser lesbar, weil so klar ist dass bspw.
CS_HIGH() wie eine Funktion behandelt wird und da nicht irgendeine
weitere Makro-Syntax-Zauberei bei der Nutzung folgt.
Außerdem ist deine Anwendung von Code-Blöcken mit { } im Makro
problematisch: Du solltest "do { ... } while (0)" verwenden, siehe z.B.
hier:
https://stackoverflow.com/a/154138
Zudem sind Namen, die mit 2 Unterstrichen beginnen, wie
"__gpio_conf_bit", der C(++)-Standard-Library sowie dem Compiler
vorbehalten und sollten daher in User-Code nicht vorkommen.
PS: Letzteres gilt auch für Unterstrich + Großbuchstabe, also auch für
"_BV". Beim AVR-GCC ist das Teil der C-Library, also korrekt (da muss
es sogar so sein, denn einfach nur "BV" ist ja vom C-Standard nicht
zugewiesen und muss daher dem User als Bezeichner zur Verfügung stehen).
Wenn du aber "_BV" selbst im Code definierst, ist das verboten und kann
in zukünftigen Compiler/Library-Versionen zu Kollisionen führen.
Dr. Sommer schrieb:> Außerdem ist deine Anwendung von Code-Blöcken mit { } im Makro> problematisch: Du solltest "do { ... } while (0)" verwenden, siehe z.B.> hier:> https://stackoverflow.com/a/154138
Danke für den Link! Sehr aufschlussreich, wusste ich auch noch nicht!
Danke jetzt hab ich`s kapierT: RF_Status_TX_DS() soll mit Makro ersetzt
werden.
Das wuerde ich nur machen, wenn es signifikante
Geschwindigkeitsveraenderungen bringen würde. Hast du es mal gemessen?
Nachteil von Makros ist auch, dass kein Debug Breakpunkt in die Funktion
gesetzt werden kann.
Marc schrieb:> Das wuerde ich nur machen, wenn es signifikante> Geschwindigkeitsveraenderungen bringen würde. Hast du es mal gemessen?
Gegenüber einer inline-Funktions bringt es sicherlich keinen
Geschwindigkeitsvorteil. Falls der Compiler sich sträubt, zwingt man ihn
mit "inline __attribute__((always_inline))" dazu, wie ja auch schon
gesagt wurde.
Marc schrieb:> Das wuerde ich nur machen, wenn es signifikante> Geschwindigkeitsveraenderungen bringen würde. Hast du es mal gemessen?
Hi,
ich versuche diese Lib, an der ich schon seit Monaten herum schraube, um
sie immer besser zu machen weiter zu optimieren. Und dazu will ich jede
Abfrage eines Bits etc in einer leicht zu benutzende Funktion packen,
die die Hardware maximal abstrahiert. Es bringt kompiliert nichts,
erleichtert mir aber die Benutzung der Lib für die darüber liegende
Schicht.
Christian J. schrieb:> Wie kriege ich es hin, dass ein Makro mit gleichem Namen den 1 oder 0> Wert des letzten Ausdrucks liefert?
Ich weiß nicht, was es daran zu mäkeln gibt, die Frage ist klar und
eindeutig.
Und zumindest für den GCC gibt es eine Lösung. Der Returnwert eines
Macros ist der letzte Ausdruck:
Peter D. schrieb:> Der Returnwert eines Macros
Korrektur: ein Makro hat keinen „Returnwert“. Dies ist eine
GCC-Erweiterung, mit der ein Block (in geschweiften Klammern) einen
Wert haben kann, sodass man ihn als Teil eines Ausdrucks benutzen
kann.
Dass dieses Feature natürlich vorrangig dafür sinnvoll ist, dass man
einen Makro so bauen kann, dass er wie ein Wert benutzbar ist, ist
klar, aber trotzdem ist der Makro selbst nach wie vor nur eine reine
Textersetzung, sonst nichts. Damit kann er keinen Rückgabewert haben.
Christian J. schrieb:> Und dazu will ich jede> Abfrage eines Bits etc in einer leicht zu benutzende Funktion packen,> die die Hardware maximal abstrahiert
Und genau das ist das Problem. Du beschreibst dein Makro selbst als
Funktion. Wenn du eine Funktion willst, dann nimm auch eine.
Mit dem Makro fudelst du dich an dem Compiler vorbei. Der Code kann so
nicht vom Compiler überprüft werden. Praktisch, weil man die Warnings
dann nicht einmal ignorieren muss. Du, und später der Anwender, sehen
nicht einmal den selben Code wie der Compiler!
Nimm Funktionen. Makros sind ein archaischer Nebenkrieg in einer
weiteren Programmiersprache, die von kaum jemanden beherrscht wird.
Peter D. schrieb:> Ich weiß nicht, was es daran zu mäkeln gibt, die Frage ist klar und> eindeutig.> Und zumindest für den GCC gibt es eine Lösung. Der Returnwert eines> Macros ist der letzte Ausdruck:#define foo( )> \> ({> \> uint8_t i = 0;> \> /* some code */> \> i; /* return value of Macro */> \> })
Das habe ich inzwischen auch schon heraus gefunden und sparsam
verwendet. Es bringt nicht wirklich etwas, obwohl es echte Freaks gibt,
die Makros schreiben wie andere Romane. Die dicken Fehler kommen aber
mit den Datentypen.
Peter, wo ich Dich grad an der Strippe habe...... was ist eine
akzeptierte Methode um in C, nicht C++, wo das einfacher ist.
Zahlenwerte an eine Grafikfunktion zu übergeben?
Ich habe ein Histogramm geschrieben, was beschriftet ist. Aber bisher 4
einzelne Routine für jeden Wert: Druck, Temperatur, Feuchte,
Außentemperatur usw. Lag nahe.
Jetzt möchte ich eine Funktion haben, statt vier, der ich die Werte
übermitteln kann. Das sind:
Position X,Y
Beschriftung
Minimaler Wert der Historie
Maximaler Wert der Historie
Aktueller Wert
Mittelwert
Mittelwertbeschriftung
zusätzlich die Daten: Zeiger auf 144 Werte, von denen aber nicht
zwingend jeder auch vorhanden sein muss. Lücken sind erlaubt Darüber
gibt ein Bit Auskunft, 0 oder 1.
Das wird alles miteinander verrechnet, so dass sich ein maßstabsgetreues
Bild ergibt, egal wie gross oder klein die Werte sind, die werden intern
normiert.
Ich kenne nur Parameterlisten aber die wären mir hier echt zu lang.
Zudem müssen nicht alle Werte immer neu geschrieben werden für jedes
Diagramm, manches ist gleich wie die Position.
Gibt es was Bewährtes`?
Dasfür würde ich einen Pointer auf zwei struct verwenden. Pack diese
Werte
Position X,Y
Beschriftung
Mittelwertbeschriftung
alle in ein struct, für jedes Histogramm eines. Diese Werte sind
konstant, die struct kann also ins Flash, und Du übergibst Deiner
Funktion einen ptr auf eine Flash-struct.
Diese Werte
Minimaler Wert der Historie
Maximaler Wert der Historie
Aktueller Wert
Mittelwert
packst Du in eine zweite struct, die im RAM liegt.
Der Vorteil bei den structs ist nicht nur, dass Du keine ewig langen
Parameterübergaben hast. Du kannst auch sehr einfach zusätzliche Werte
in die structs einbauen, wenn siespäter benötigt werden, ohne überall
den Funktionskopf zu ändern.
Die Daten werden als ptr auf ein Array übergeben.
Gruß, Stefan
Wenn die Information beim Aufrufer ist (und bleibt), dann pflegt der ein
Feld mit den Daten und übergibt nur einen Pointer (oder 2).
Wenn die Information nicht beim Aufrufer bleibt, also mit Aufruf der
Funktion mal diese, mal jene Info beigestuert wird und die Daten in der
Funktion bleiben (dort gekapselt sind), dann musst Du kennzeichnen,
welche Informationen überschrieben werden sollen. Bei nur einer Funktion
gibt es u.a. folgende Mechnismen:
a) Übergabe der Daten mithilfe von Pointern, wobei die Pointer 0 sein
können
b) Gültigkeitsinformationen in den Daten (valid-Bit)
c) parallele Gültigkeitsinfo
d) Parameter- und Kommandokonzepte (verschiedene Kommandos, z.B. setze
Parameter 27 und interpretiere den obligatorischen void-pointer als
pointer auf einen Typ Y)
e) Globaler Speicher
f) festgelegte Reichenfolge.
ich habe alle Methoden schon sinnvoll angewendet gesehen, leider einige
auch völlig chaotisch (Write-Only-Code).
In den meisten Fällen ist "nur eine Funktion" unsinnig.
Moin,
klingt gut, so werde ich es machen. Die Messwerte liegen ja schon in
einem großen Struct und auch alle daraus abgeleiteten Werte. Allerdings
kann ich diesen Struct nicht einfach übergeben, da es ja verschiedene
Variablen sind, die die Werte enthalten. Also müssen die erst umkopiert
werden. Ich werde dann Grafik/Beschriftung und Daten voneinander
trennen. Strings sind mir in C zwar etwas ungewohnt aber Einarbeitung
tut not.
struct info {
char* text; // oder char text[20] ?
....
}
wird wohl mit *info.text = "Hallo Welt";
zu füttern sein, wobei ich nicht weiss, wo das "Hallo Welt" dann steht,
im Ram oder im Rom... oder im Initializer nach dem Startup des Codes.
Aber eines nach dem anderen....
Chris J. schrieb:> wird wohl mit *info.text = "Hallo Welt";>> zu füttern sein, wobei ich nicht weiss, wo das "Hallo Welt" dann steht,> im Ram oder im Rom. Aber eines nach dem anderen...
String-Literale sollten normalerweise im ROM liegen (siehe
Linkerscript). Dazu muss "text" aber als "const char*" definiert sein,
sonst gibts da eine Warnung/Fehler.
Dr. Sommer schrieb:> String-Literale sollten normalerweise im ROM liegen
Naja, die liegen erstmal alle im ROM. Nur werden die dann beim Start von
dort aus auch auf RAM Plätze kopiert imm Zuge der Initialisierung der
globalen Variablen. Ich gucke da sicherheitshalber immer nach im .map
File später.
Dr. Sommer schrieb:> String-Literale sollten normalerweise im ROM liegen (siehe> Linkerscript).
Hängt von der Architektur ab. Beim AVR bspw. liegen sie nicht im
ROM, da dieser mit völlig anderen Befehlen angesprochen werden muss
als ein regulärer char *. Damit könnte man ein Stringliteral dann
nicht mehr an Funktionen wie strcmp() übergeben, wenn es im Flash
abgelegt ist, denn strcmp() muss genauso damit klarkommen, dass
ein normales char-Array per Zeiger übergeben wird.
> Dazu muss "text" aber als "const char*" definiert sein,> sonst gibts da eine Warnung/Fehler.
Das wiederum muss man ohnehin tun, denn der Standard überlässt es
der Implementierung (also dem Compiler), ob er Stringliterale in einem
nicht beschreibbaren Speicher ablegt oder nicht. Zeiger auf solche
müssen daher stets so behandelt werden, als wären sie im ROM.
Chris J. schrieb:> Nur werden die dann beim Start von> dort aus auch auf RAM Plätze kopiert imm Zuge der Initialisierung der> globalen Variablen.
Kommt drauf an ob die globale Variable ein Array oder ein Pointer ist.
Ich seh hier gar keine globale Variable, sondern nur irgendeinen Pointer
auf das String-Literal. Da wird gar nix kopiert. Auch bei einem globalen
'const char* x = "asdf"; ' wird nur der Pointer-Wert vom ROM in den RAM
kopiert (falls nicht sowieso wegoptimiert). Der String selbst wird nur
bei einem 'char x [] = "asdf";' tatsächlich kopiert.
Jörg W. schrieb:> Hängt von der Architektur ab. Beim AVR bspw. liegen sie nicht im> ROM, da dieser mit völlig anderen Befehlen angesprochen werden muss> als ein regulärer char *.
Ich weiß. AVR ist auch eine komische Architektur. Der Chris arbeitet
aber mit STM32.
Jörg W. schrieb:> Das wiederum muss man ohnehin tun
Ja.
Man kann auch eigene Regions definieren und sie da mit
_attribute(section.... ö.ä. hinein zu legen. Habe ich auch schon gemacht
mit dem Backup RAM dews F429. Das wurde direkt beim Flashen auch dann
genau dahin kopiert.
Dr. Sommer schrieb:> Ich weiß. AVR ist auch eine komische Architektur.
Logische Folge, wenn man eine Harvard-Architektur mit einem
16-bit-Adressraum betreiben möchte und dabei jeweils 2 x 64 KiB
(beim instruction memory sogar 128 KiB) adressieren können möchte.
Gab's schon bei der PDP-11. :-)
Der MSP430 hat beide in einen Adressraum vereinigt, sodass die
Fummelei mit irgendwelchen Adressierungsklimmzügen schon deutlich
eher beginnt als beim AVR.
> Der Chris arbeitet> aber mit STM32.
Steht nirgends im Thread, ich hatte extra gesucht.
Jörg W. schrieb:> Gab's schon bei der PDP-11. :-)
Dann sollten die Probleme ja bekannt sein :-P
Jörg W. schrieb:> Steht nirgends im Thread, ich hatte extra gesucht.
Aber in seinen 5879321 weiteren Threads...
Stefan K. schrieb:> Die Daten werden als ptr auf ein Array übergeben.
Hmmm..... der Datenstruct sieht so aus:
1
/* --- Die Datenhistorie ----- */
2
typedefstruct{
3
floatPressure;// 4: History Druck[id_data]
4
uint8_tExt_Feuchte;// 4: History Feuchte Aussen[id_data]
5
Ext_Temperature;// 4: History Aussentemperatur[id_data]
6
_Boolf_data_valid;
7
}__attribute__((packed))volatilehist_data_t;
8
9
hist_data_thistdata[HISTORY_MAX_IDX+1];// Daten Historie
Die Grafikroutine habe ich inzwischen auf eine einzige geschrumpft, noch
nicht ganz fertig. Sie soll auf alle diese Datentypen passen, wobei es
optisch schon einen Unterschied macht, ob man da mit float oder int
arbeitet, es sieht softer aus, int erzeugt Treppchen. Der Druck muss
also float sein, alles andere geht mit int.
Wie würde man da eine Universallösung erzeugen? Mit unions?
union value_t {
float f _val;
uint8_t i_val;
}
Die Grafikroutine muss ja auch wissen welcher Wert dargestellt werden
soll, ein data->Ext_Temperature geht nicht. Den Array vorher umkopieren
finde ich zu aufwendig.
void DrawUniversal(struct* Grafikinfos, struct* Texte und Grenzwerte,
void* Datensatz)
?
Markus F. schrieb:> was macht das volatile da?
Variablen, die in Ints verwenden werden bezeichne ich so, da ich nicht
sicher bin, ob jede globale Variable volatile ist. Und wenn man es da
nicht hinschreibt meckert der GCC an anderer Stelle, nämlich bei extern
volatile ...
Und bevor noch ein anderer fragt, warum da __attribute__((packed))
steht: Ich tausche Daten per Funk mit einem 8 Bit Arduino aus, der hat
andere Datenbreiten, die sich nur so angleichen lassen.
Chris J. schrieb:> Variablen, die in Ints verwenden werden bezeichne ich so, da ich nicht> sicher bin, ob jede globale Variable volatile ist. Und wenn man es da> nicht hinschreibt meckert der GCC an anderer Stelle, nämlich bei extern> volatile ...
Uiuiui...