Hallo, welche andere Programmiersprachen könnt ihr für ARM cortex M empfehlen, die auch mit wenig ram&rom (4kB/32kB) auskommt? Die allgegenwärtigen libs (in C geschrieben!) sollte man aber noch weiter verwenden können. (Ich habe über die Jahre eine leichte C-Allergie entwickelt, die auch bei C++ und ähnlichen auftritt)
Arduino F. schrieb: > Ich würde dir eine Desensibilisierung empfehlen... Entweder das oder gleich Assembler schreiben. Bei nur 4kB RAM kennt man noch jedes Byte mit Namen. ARM Cortex-M an sich ist aber für C-Compiler optimiert. Es ist auch in Assembler nicht übermäßig schwierig C-Libraries zu benutzen, aber die müssten erstmal in das enge RAM und Flash Korsett passen...
Selbst wenn es eine andere Programmiersprache gäbe, dann fehlen meist noch die Registerbeschreibungen, Bitkonstanten u.ä. wie man sie üblicherweise in den C-Include-Dateien der Hersteller findet. Aber vielleicht ist das ja ganz interessant: http://blog.japaric.io/quickstart/ Oliver
Programierer schrieb: > welche andere Programmiersprachen könnt ihr für ARM cortex M empfehlen, > die auch mit wenig ram&rom (4kB/32kB) auskommt? Free Pascal, weil C-Allergiker oftmals Pascal mögen.
Programierer schrieb: > welche andere Programmiersprachen könnt ihr für ARM cortex M empfehlen, > die auch mit wenig ram&rom (4kB/32kB) auskommt? Das hängt nur sehr wenig von der Programmiersprache ab, sondern im wesentlichen von der Qualität des Compilers. 32K Flash und 2K RAM reichen auch in C für sehr viele Dinge aus. > Die allgegenwärtigen libs (in C geschrieben!) sollte man aber noch > weiter verwenden können. Dann wäre ein C-Compiler die kanonische Wahl. Obwohl natürlich auch viele andere Sprachen mit C-Linkage umgehen können. Notfalls sogar Assembler, obwohl das eher Masochismus ist als alles andere. Aber deiner Intention, Speicher zu sparen, entspricht das nicht. Denn das, was ein C-Programm typischerweise fett macht, sind eben die verwendeten Libraries. > (Ich habe über die Jahre eine leichte C-Allergie entwickelt, die auch > bei C++ und ähnlichen auftritt) Dann wünsche ich baldige Genesung. Gesund ist das nämlich nicht.
Programierer schrieb: > welche andere Programmiersprachen könnt ihr für ARM cortex M empfehlen, > die auch mit wenig ram&rom (4kB/32kB) auskommt? Hier würde ich die GCC einsetzen mit wahrscheinlich stark eingeschränktem C++. ... manchmal im Leben gibt es einfach keine sinnvollen Alternativen ;) Grüße Oliver
Rainer S. schrieb: > https://www.mikroe.com/mikropascal/#arm Finger weg... Das Drumherum von Mikroelektronika (Boards, Bibliotheken, IDE usw.) ist wirklich hübsch eingerichtet und es macht echt Spaß, damit zu basteln. Die Compiler würde ich mir aber genau angucken, bevor ich damit professionell loslege. Zumindest die AVR-Compiler sind/waren unter aller Sau(*), inklusive lächerlichem Optimierer und extrem subtilen Bugs(**). In die mitgelieferten Bibliotheken kann man halt größtenteils nicht reingucken. (*) Der optimiert meistens garnix, aber wenn, dann auch mal versehentlich großzügig Teile des Programms weg... (**) Konkret hat der C-Compiler an verschiedenen Stellen ein char-Argument nicht zu int promoted, wie es im Standard gefordert ist.
Markus F. schrieb: > wie wär's mit Ada? > > https://www.adacore.com/download Interessant. Ich hab hier viele libXYZ.a und dazu passende XYZ.h Wie kann ich die weiterhin verwenden? Ein "use XYZ.h;" (oder so ähnlich) geht wohl nicht..
Die *.h Dateien, wirst du wohl in ADA Packages umschreiben dürfen. Dann sollte es auch mit deinen *.a klappen. -- Ungetestet (bin nicht so der ADA Spezi) Jedes gute ADA Buch sollte einen Abschitt "Interfacing to Other Languages", o.ä. beinhalten.
Arduino F. schrieb: > Die *.h Dateien, wirst du wohl in ADA Packages umschreiben dürfen. Das ist nur die halbe Miete. > Dann sollte es auch mit deinen *.a klappen. Das ist nicht gesagt. Dazu muß der ADA-Compiler entweder das gleiche ABI (Aufrufkonvention, Typcodierung) benutzen wie der C-Compiler oder es zumindest als Variante unterstützen.
u8g2 schrieb: > Selbst wenn es eine andere Programmiersprache gäbe, dann fehlen meist > noch die Registerbeschreibungen, Bitkonstanten u.ä. wie man sie > üblicherweise in den C-Include-Dateien der Hersteller findet. Ja. Jemand der nicht zur Fraktion "Dumm, faul und gefräßig" zählt würde womöglich auch über den Einsatz von Nim nachdenken. Einige Leute hatten damit im Embeded-Bereich ja schon experimentiert. Aber >wenig ram&rom (4kB/32kB) ist schon extrem wenig.
Ich hatte damals als Schüler das Programmieren in Pascal gelernt. Die Windows API war in C geschrieben, jedoch hatte Borland sie weitgehend in Pascal Libraries gekapselt. Der Haken war, dass die Dokumentation dieser Kapselungen stets veraltet und oft unvollständig war. Dazu kam, dass ich gelegentlich Windows Features nutzen wollte, die Pascal nicht gekapselt hatte. Zum Beispiel wollte ich damals den Status eines Fensterlosen Programmes (IR Empfänger) mit einem Taskleisten-Icon in der rechten unteren Ecke anzeigen. So wurde ich gezwungen, ziemlich oft in die API Dokumentation von Microsoft zu schauen. Dort fand ich oft auch oft hilfreiche Programmbeispiele, aber eben immer nur in C (manhcmal auch C++). So musste ich gezwungenermaßen auch wenigstens ein bisschen C und C++ lernen. Und als ich so weit war, fragte ich mich "Warum programmiere ich eigentlich in Pascal"? Mir fielen nur wenige starke Argumente für Pascal ein. Deswegen wechselte ich nach C/C++ obowhl das technisch gesehen ein Rückschritt war und die Sprache definitiv hässlicher ist. Trotzdem bin ich bis heute dabei geblieben und hatte nie das Gefühl, dabei auf dem Holzweg zu sein. Nun programmiere ich nur noch selten Windows/Linux Programme, dafür mehr Mikrocontroller. Dass man die auch in C/C++ programmieren kann, erwies sich für mich als äußerst praktisch. Nach wie vor sind diese Sprachen mit hässlichen Details durchsetzt, aber das ist für mich noch lange kein Grund, sie nicht zu benutzen. Egal welche andere Sprache zu benutzt, du wirst dich trotzdem auch mit C auseinander setzen müssen. Alleine schon wegen der Libraries.
Stefan U. schrieb: > Egal welche andere Sprache zu benutzt, du wirst dich trotzdem auch mit C > auseinander setzen müssen. Alleine schon wegen der Libraries. Genauso ist das. Man muss C nicht lieben, aber man muss es trotzdem beherrschen, wenn man in dieser Welt programmiermässig mit dem Arsch an die Wand kommen will. Und natürlich: Es läßt sich auch viel besser über Sachen lästern, die man kennt und gerade deswegen hasst, weil man sie kennt. ;o)
c-hater schrieb: > Man muss C nicht lieben, aber man muss es trotzdem > beherrschen, wenn man in dieser Welt programmiermässig mit dem Arsch an > die Wand kommen will. In der Systemprogrammierung vielleicht. Bei normaler PC/Server-Anwendungs- oder Web-Entwicklung kann man gut ohne auskommen. Stefan U. schrieb: > Deswegen > wechselte ich nach C/C++ obowhl das technisch gesehen ein Rückschritt > war und die Sprache definitiv hässlicher ist. C und C++ so über einen Kamm zu scheren ist etwas gemein, schließlich ist C++ vielfach mächtiger. C++ hat einen Gutteil seiner Hässlichkeit aus C geerbt und der bezieht sich hauptsächlich auf die Syntax, und die ist weiter hinten auf der Lernkurve eh nicht mehr so wichtig. Dafür kann C++ auch mehr als Pascal...
Ich habe früher in PL/M programmiert, das ist irgendwo zwischen C und Assembler. Bin aber froh das ich das nicht mehr brauche, ein bisschen Luxus möchte man beim Programmieren ja schon haben. Und das ist doch eher der Punkt, man benutzt C oder C++ um einen höheren Abstraktionslebel zu haben und besser lesbare, wartbare und erweiterbare Software zu bekommen. C/C++ sind schon sehr effizient mit den modernen Compilern, ein Register = 0x1234 wird auch zu wenigen Bytes Maschinencode. Dann hängt die Programmgrösse weniger von der Sprache ab als vielmehr von den Bibliotheken die ich dazupacke. Wenn ich den Komfort eines printf(), vielleicht sogar noch mit float Unterstüzung haben möchte, dann kostet das halt ein paar kB mehr. Das Schöne bei den Cortex-M ist doch gerade das die in ihren Familien viele Geschwister haben und man mit wenig Aufwand einen Controller mit mehr Dampf auswählen kann. 256 kB Flash bekommt man auch für 2€, warum da alles abspecken und dem Performancegott opfern?
Dr. Sommer schrieb: > [...] schließlich ist C++ vielfach mächtiger [als C]. Papperlapapp, C++ ist nicht mächtiger als C oder Assembler: sind alle "nur" Turing-vollständig. *wegduck*
Johann L. schrieb: > Papperlapapp, C++ ist nicht mächtiger als C oder Assembler: sind alle > "nur" Turing-vollständig. *wegduck* Mit dem Argument kannst du auch gleich in Brainfuck programmieren...
Programierer schrieb: > welche andere Programmiersprachen könnt ihr für ARM cortex M empfehlen, > die auch mit wenig ram&rom (4kB/32kB) auskommt? Leider gar keine. Es hat sich C mittlerweile zu einer Monokultur entwickelt und Alternativen sind nicht in Sicht. Es haben die Leute von Mikroe mal versucht, mit Basic und Pascal zu landen, aber sie haben es falsch angestellt, nämlich so, daß ihr Produkt eben nicht vom Anwender auf einen µC eingerichtet werden kann, der nicht bereits in der Liste der unterstützten Chips steht. Hätten sie lediglich zwischen den Architekturen (M0...M4F..M7) unterschieden und all die Registeranpassungen einfach in einen Hardwareunit (für C-Leute: sowas wie "LPC408x.h") gepackt, dann hätten diese Compiler eine Anwender-Basis bekommen können. Die Sprache gibt's ja her:
1 | was in C so lautet: |
2 | #define NVIC_ISPR (*((volatile unsigned long *) (0xE000E200)))
|
3 | |
4 | wäre in Pascal etwa so: |
5 | NVIC_ISPR : dword absolute $E000E200; |
easy, gelle? aber leider eben nicht zu kriegen. W.S.
Axel S. schrieb: > Arduino F. schrieb: >> Die *.h Dateien, wirst du wohl in ADA Packages umschreiben dürfen. > > Das ist nur die halbe Miete. > >> Dann sollte es auch mit deinen *.a klappen. > > Das ist nicht gesagt. Dazu muß der ADA-Compiler entweder das gleiche ABI > (Aufrufkonvention, Typcodierung) benutzen wie der C-Compiler oder es > zumindest als Variante unterstützen. Der Ada gnat-Compiler ist Teil der GCC. gcc und gnat stammen also aus demselben Stall und kennen sich. Wie man C-Funktionen von Ada aus aufruft (und umgekehrt) steht hier: https://gcc.gnu.org/onlinedocs/gcc-5.4.0/gnat_ugn/Interfacing-to-C.html Fertig ist man damit allerdings längst nicht. Die gnat runtime gibt es fertig nur für bestimmte ausgesuchte Boards. Andere benötigen wenigstens eine rudimentäre Portierung -> http://blog.adacore.com/porting-the-ada-runtime-to-a-new-arm-board. Das dürfte für so ein "kleines" Board relativ simpel sein - viel Runtime passt da ja gar nicht drauf.
Programierer schrieb: > (Ich habe über die Jahre eine leichte C-Allergie entwickelt, die auch > bei C++ und ähnlichen auftritt) Ich würde Dir empfehlen, alles was Du bisher über C++ weißt, weg zu werfen und statt dessen modernes C++ mit viel moderner TMP neu(!) zu erlernen. Um C als common-ground kommst Du leider nicht herum ...
Programierer schrieb: > welche andere Programmiersprachen könnt ihr für ARM cortex M empfehlen, > die auch mit wenig ram&rom (4kB/32kB) auskommt? Wenn Dein Programm zu groß wird, dann nimm doch einfach einen größeren Cortex-M. Da gibt es nun wirklich genug Auswahl für jeden Geschmack. Deine Anfrage ist sehr unspezifisch. Ein "Blinky" Programm passt immer in 4kB/32kB, oder meinst Du, dass der Compiler/Linker mit 4kB/32kB auskommen muss?
Die gcc-Monokultur hat auch Vorteile:
Ein '-fdump-ada-spec' macht aus .h .ads
Ein schwer lesbares .h wird dardurch nicht lesbarer - aber ich
'with/use' es ja nur?
Oliver schrieb:
>http://blog.japaric.io/quickstart/
Danke! Die Rust Leute haben das gleiche Problem:
keine Registerbeschreibungen, keine Bitkonstanten..
Programierer schrieb: > keine Registerbeschreibungen, keine Bitkonstanten.. ..und wenn man die Seite nicht nur überfliegt, kann man lernen dass es für sehr viele MCUs *.svd files gibt und mit "svd2$SPRACHE" diese übersetzen kann:)
Programierer schrieb: > (Ich habe über die Jahre eine leichte C-Allergie entwickelt, die auch > bei C++ und ähnlichen auftritt) was stört Dich den an C, was Du hoffst, in anderen Sprachen zu finden? Wie sieht es mit Ada und Rust aus?
:
Bearbeitet durch User
> BASIC Es wird sogar asymmetrisches Multitasking mit Cortex-M Dual-Core unterstützt. Schaut mal auf die Memory Map: http://www.coridium.us/ARMhelp/index.htm#page=HWlpc54102.html
es gäbe auch noch forth, das kommt wirklich mit wenig RAM/ROM aus. https://github.com/jeelabs/mecrisp-stellaris läuft anscheinend schon mit 16kb flash und 1kb ram. Terminalprogramm für eine serielle Schnittstelle ist üblicherweise alles was man braucht, compiler und entwicklungsumgebung ist in den 16k inkludiert.
Torsten R. schrieb: > was stört Dich den an C, was Du hoffst, in anderen Sprachen zu finden? Unschön ist die Unmenge an undefined behaviour, besonders weil der Compiler dann halt "irgendwas" macht, aber garantiert nichts Nützliches. Das wird obendrein schlimmer, weil wegen angeblicher Performancegewinne solche UBs auf einmal beim Optimieren genutzt werden, was früher nicht der Fall war. Nicht, daß man dadurch wirklich schnelleren Code hätte, aber haufenweise reifgetestete Codebasen zeigen sich auf einmal doch buggy. Klar kann man sagen, der Programmierer muß wissen, was er macht, aber "design for safety" ist ein grundlegendes Engineering-Prinzip, das zumindest für Debug-Builds automatisch möglich sein sollte. Dann die z.T. unsinnige Operatoren-Rangfolge (z.B. ist & niedriger als ==), die Integer-Promotion ist auch immer wieder ein Quell der Freude, und Arrays zerfallen bei Aufruf an Funktionen zu Pointern, so daß automatische Längenchecks nicht optional eincompilierbar sein können. Dann sind da noch die haarsträubenden Library-Funktionen besonders rund ums Stringhandling, die auch mit den n-Versionen (strncpy) immer noch Händchenhalten brauchen, weil der resultierende String u.U. nicht nullterminiert ist. Bis hin zu völlig überflüssigen Späßen wie daß das Ergebnis von malloc(0) implementationsabhängig ist, was zur Fehlerbehandlung blöd werden kann. Überhaupt, wieso kriegt free() nicht einen Pointer auf einen Pointer, um den automatisch zu nullen? Dann hätte man bei "use after free" automatisch zu einem Crash, was leicht zu entdecken wäre. Also ich mag C, mehr als Pascal jedenfalls, aber C hat schon seine unschönen Seiten.
Lothar schrieb: > BASIC Hm .. die IDE wirkt wie ein mal schnell so zur Übung zusammengeklickter Dialog aus VC. Wenig vertrauenserweckend. Die Mathe-Funktionen der Runtime Library sind wohl ebenfalls "überschaubar". Kann es sein, dass das Produkt noch nicht ganz ausgereift ist? ;-)
W.S. schrieb: > was in C so lautet: > #define NVIC_ISPR (*((volatile unsigned long *) (0xE000E200))) > > wäre in Pascal etwa so: > NVIC_ISPR : dword absolute $E000E200; Und wo ist da das Pascal-Pendant zu "volatile"?
Nase schrieb: > Rainer S. schrieb: >> https://www.mikroe.com/mikropascal/#arm > Das Drumherum von Mikroelektronika (Boards, Bibliotheken, IDE usw.) ist > wirklich hübsch eingerichtet und es macht echt Spaß, damit zu basteln. Na, das ist doch schon mal was. Wenn man die IDE mit der von der oben erwähnten BASIC Variante vergleicht, tun sich da doch Welten auf. > Die Compiler würde ich mir aber genau angucken, bevor ich damit > professionell loslege. Zumindest die AVR-Compiler sind/waren unter aller > Sau(*), inklusive lächerlichem Optimierer und extrem subtilen Bugs(**). Ist dein Wissen dazu überhaupt noch aktuell? Oder sind die Bugs vielleicht schon längst fehlerbereinigt .. > In die mitgelieferten Bibliotheken kann man halt größtenteils nicht > reingucken. Wollen doch viele Anwender vielleicht auch gar nicht. Sie wollen die Libs einfach nur benutzen und damit schnell Ergebnisse erzielen. > (*) Der optimiert meistens garnix, Muss wirklich JEDES Codeschnipsel immer "hoch optimiert" sein? Sind wir nicht längst aus dem Zeitalter der "ich muss noch ein paar Bytes mehr rausquetschen" Analogie herausgewachsen? > aber wenn, dann auch mal > versehentlich großzügig Teile des Programms weg... Wäre nicht schön. Aber ist das wirklich noch so? Die verkaufen doch ihre Lizenzen nicht erst seit gestern. > (**) Konkret hat der C-Compiler an verschiedenen Stellen ein > char-Argument nicht zu int promoted, wie es im Standard gefordert ist. Bugs eben. Wie viele Bugs haben Compiler noch mal (generell und quasi immer)? Ein paar Dutzend, ein paar hundert, ein paar Tausend?
Thomas E. schrieb: > Und wo ist da das Pascal-Pendant zu "volatile"? Pascal hat kein volatile. > In FPC, every statement is basically considered to be a compiler-level > memory barrier for accesses to global variables. So within a single > statement multiple accesses can be optimised, but that cannot happen not > across statements. It's not perfect since it inhibits some optimisation, > but on the flip side it's very simple and easy to reason about. Quelle: http://lists.freepascal.org/pipermail/fpc-pascal/2015-December/046057.html
> Unschön ist die Unmenge an undefined behaviour In C ist alles nötige sehr genau definiert. "undefined behaviour" provoziert man nur, indem man etwas macht, was nicht vorgesehen ist. Und dann bekommt man vom Compiler eine deutliche Warnung. > auf einmal beim Optimieren genutzt werden Es steht Dir frei, den Optimierungs-Grad selbst einzustellen. Neue Optimierungen kommen immer nur in die höchste Stufe oder in eine neue Stufe. Du kannst die Optimierung auch ganz deaktivieren und ggf. manuell optimieren, wenn Dir das eher zusagt. Das alles sind aber nicht C spezifische Probleme. Das kann Dir in jeder beliebigen Programmiersprache ebenso passieren. Ich meine z.B. Java, da hast du obendrein noch viel weniger Einflussmöglichkeiten. > "design for safety" Das ist nicht das primäre Ziel der Sprache C. Allerdings kannst du den Optimizer deaktivieren und alle Warnungen aktivieren, dann bist du ganz nahe an der Anforderung dran. > die z.T. unsinnige Operatoren-Rangfolge Hm die ist bei fast allen Programmiersprachen ebenso. Und ich finde sie durchaus sinnvoll. Deine weiteren Kritikpunkte wurden längst durch C++ und zahlreiche andere Programmiersprachen ausgemerzt. Aber diesen Luxus bezahlt man mit geringerer Performance und mehr Speicherbedarf. Offensichtlich gibt es aber noch genug Fälle, wo man eben diese "Kosten" nicht toleriert, sonst wäre C schon lange tot. Was die Library angeht: Du musst sie nicht benutzen. Schreibe Dir eine eigene! > die ... immer noch Händchenhalten brauchen Du musst die alten Funktionen/Libraries ja nicht benutzen. Wenn ich heute mit einem Trabbi über die Autobahn knattere, kann ich mich auch nicht darüber beklagen, dass manche Auto immer noch so lahm und laut sind. > Bis hin zu völlig überflüssigen Späßen wie daß das Ergebnis > von malloc(0) implementationsabhängig ist Du wirfst da zu viel ein eine Topf. Malloc holt sich Speicher vom OS. Also hängt das Verhalten von Malloc direkt von OS ab. Wenn du das nicht willst, musst du eine eigene Speicherverwaltung nehmen, so wie Java es tut. Gibt es übrigens auch für C. Nur wundere Dich dann nicht, dass jedes kleine Popel-Programm per default erstmal etwa die Hälfte des RAM zu belegen versucht. Glücklicherweise vergibt Windows inzwischen nur noch virtuellen Speicher, so dass das kaum noch auffällt. Aber ich weiß noch, wie das unter Windows 3.11 und 95 lief. > Also ich mag C ... aber C hat schon seine unschönen Seiten. Da stimme ich Dir allerdings zu. Das trifft sicher auf jede Sprache zu. Ich arbeite beruflich viel mit Java, der Sprache, die angeblich alles besser machen sollte. Pustekuchen! Java hat genau so viele Fallstricke.
Brille schrieb: > Bugs eben. Wie viele Bugs haben Compiler noch mal (generell und quasi > immer)? Ein paar Dutzend, ein paar hundert, ein paar Tausend? Beim GCC sind derzeit mehr als 10000 bekannt und garantiert noch viel mehr unbekannt: https://gcc.gnu.org/bugzilla/buglist.cgi?bug_status=__open__&no_redirect=1&query_format=specific&order=priority%2Cbug_severity&limit=0 Und an dem arbeitet eine große Community die viele Fehler aufdeckt&behebt - dürfte der meistgenutzte Compiler der Welt sein. Bei "kleinen" proprietären Compilern sieht das wohl schon anders aus.
> Beim GCC sind derzeit mehr als 10000 bekannt
Wobei das vermutlich größtenteils nur mutmaßliche Bugs sind, die noch
untersucht und bestätigt oder abgewiesen werden müssen.
Stefan U. schrieb: > In C ist alles nötige sehr genau definiert. "undefined behaviour" > provoziert man nur, indem man etwas macht, was nicht vorgesehen ist. Und > dann bekommt man vom Compiler eine deutliche Warnung. Nein, die bekommt man nicht. Oder nur manchmal. Wie beispielsweise möchtest Du bei undefiniertem Verhalten den Compiler warnen lassen, wenn man eine Variable um eine andere Variable shiftet, deren Wert aber erst zur Laufzeit bekannt wird? Um DAS rauszufinden, brauchst Du sehr, sehr aufwendige und damit auch teure Tools. > Es steht Dir frei, den Optimierungs-Grad selbst einzustellen. C ohne Optimierungen ist ja ziemlich witzlos, weil dann das zentrale C-Argument mit der Geschwindigkeit nicht mehr vorhanden ist. > Das alles sind aber nicht C spezifische Probleme. Doch, das ist es, weil der Compiler sich beim Optimieren zwar darauf verläßt, daß kein undefiniertes Verhalten da ist, aber meistens nicht warnt. C enthält schlichtweg zuviel undefiniertes Verhalten, darunter auch solches, was man genausogut implementationsabhängig hätte machen können. > Das ist nicht das primäre Ziel der Sprache C. Genau das ist ja einer der unschönen Punkte an C. Besonders, weil man das nichtmal per Debugbuild optional haben kann. > Hm die ist bei fast allen Programmiersprachen ebenso. Und ich finde sie > durchaus sinnvoll. Ich finde sie unsinnig. if (x & MASK == MASK) geht nicht, sondern es muß wegen der unsinnigen Priorität if ((x & MASK) == MASK) heißen. Unsinnig ist das, weil es so gut wie keinen Fall gibt, in dem man wirklich die erstere Variante würde haben wollen. Daß man beim switch ein break setzen muß, wenn man enden will, anstatt ein continue, wenn man in den nächsten case reinlaufen will, ist auch so ein Mangel. > Du musst die alten Funktionen/Libraries ja nicht benutzen. Das ist keine Widerlegung meines Argumentes, sondern eine Bestätigung. > Du wirfst da zu viel ein eine Topf. Malloc holt sich Speicher vom OS. > Also hängt das Verhalten von Malloc direkt von OS ab. Das ist eben der Kritikpunkt.
Stefan U. schrieb: > Was die Library angeht: Du musst sie nicht benutzen. Schreibe Dir eine > eigene! Achja, übrigens ist schon die dahinterliegende implizite Grundannahme vollkommen verkehrt. Man schreibt sich in aller Regel nämlich die Codebasis, an der man arbeitet, nicht als Einzelner im stillen Kämmerlein from scratch selber.
> C ohne Optimierungen ist ja ziemlich witzlos, weil dann das zentrale > C-Argument mit der Geschwindigkeit nicht mehr vorhanden ist. Sage das nicht. Ich habe das mal bei meinen eigenen Programmen ausprobiert und war erstaunt, dass der Code nur wenig größer und langsamer wurde, als mit Optimierung. Ich hatte da ein Verhältnis von 1:5 erwartet, aber es war am Ende weniger als 1:2. > if (x & MASK == MASK) geht nicht Das ist ein schönes Beispiel, um zu erklären, warum du die Rangfolge nicht magst. Jetzt verstehe ich dich besser. >> Du musst die alten Funktionen/Libraries ja nicht benutzen. > Das ist keine Widerlegung meines Argumentes, sondern eine Bestätigung. Ok
Stefan U. schrieb: > Was die Library angeht: Du musst sie nicht benutzen. > Schreibe Dir eine eigene! Den Mangel, dass Arrays bei Übergabe zu Pointern ohne Längeninformation zerfallen, kann man damit aber auch nicht lösen. Oder ein paar andere Dinge, die im Kern der Sprache verankert sind.
Nop schrieb: > Torsten R. schrieb: > >> was stört Dich den an C, was Du hoffst, in anderen Sprachen zu finden? > > Unschön ist die Unmenge an undefined behaviour, besonders weil der > Compiler dann halt "irgendwas" macht, aber garantiert nichts Nützliches. Ja, wenn das Dein Hauptkriterium an einer Sprache ist, hast Du eingentlich nur 2 Möglichkeiten: 1) (fast) keine Abstraktionen: das wäre dann z.B. Assembler 2) In allen Abstraktionen, definiertes Verhalten: Du must Dich ja nicht alleine auf die Garantien stützen, die Dir die Sprache gibt. Wenn Du andere Garantien haben möchtest oder brauchst, dann gibt evtl. einen C-Compiler / Plattform, die das bieten. Undefined behaviour verbietet ja nicht, dass es Tools gibt, die Verhalten an der Stelle definieren. Der Code wäre dann halt nicht mehr protabel. Unter Umständen ist das dann aber das kleinere Übel. C ist aber halt eine multi-purpose language. Und genau zu definieren, wie sich strcpy( 0, 0 ) verhält bedingt halt z.T. teure Prüfungen, der derjenige, der das nicht braucht, nicht haben möchte.
Man kann aber Arrays und String durch Objekte ersetzen. Dann sind wir allerdings schon bei C++. Obwohl: Objekt-Orientiert kann man auch in C programmieren. Nur gewinnt man damit ebenfalls keinen Schönheitswettbewerb.
Nop schrieb: > Wie beispielsweise möchtest Du bei undefiniertem Verhalten den > Compiler warnen lassen, wenn man eine Variable um eine andere > Variable shiftet, deren Wert aber erst zur Laufzeit bekannt wird? > > Um DAS rauszufinden, brauchst Du sehr, sehr aufwendige und damit auch > teure Tools. 3.11 Program Instrumentation Options GCC supports a number of command-line options that control adding run-time instrumentation to the code it normally generates. [...] Another class of program instrumentation is adding run-time checking to detect programming errors like invalid pointer dereferences or out-of-bounds array accesses, as well as deliberately hostile attacks such as stack smashing or C++ vtable hijacking. There is also a general hook which can be used to implement other forms of tracing or function-level instrumentation for debug or program analysis purposes.
1 | -fsanitize=address |
2 | -fsanitize=kernel-address |
3 | -fsanitize=thread |
4 | -fsanitize=leak |
5 | -fsanitize=undefined |
6 | -fsanitize=shift |
7 | -fsanitize=shift-exponent |
8 | -fsanitize=shift-base |
9 | -fsanitize=integer-divide-by-zero |
10 | -fsanitize=unreachable |
11 | -fsanitize=vla-bound |
12 | -fsanitize=null |
13 | -fsanitize=return |
14 | -fsanitize=signed-integer-overflow |
15 | -fsanitize=bounds |
16 | -fsanitize=bounds-strict |
17 | -fsanitize=alignment |
18 | -fsanitize=object-size |
19 | -fsanitize=float-divide-by-zero |
20 | -fsanitize=float-cast-overflow |
21 | -fsanitize=nonnull-attribute |
22 | -fsanitize=returns-nonnull-attribute |
23 | -fsanitize=bool |
24 | -fsanitize=enum |
25 | -fsanitize=vptr |
26 | -fsanitize=pointer-overflow |
27 | -fsanitize=builtin |
28 | -fasan-shadow-offset=number |
29 | -fsanitize-sections=... |
30 | -fsanitize-recover= |
31 | -fsanitize-address-use-after-scope |
32 | -fsanitize-undefined-trap-on-error |
33 | -fsanitize-coverage=trace-pc |
34 | -fsanitize-coverage=trace-cmp |
35 | -fbounds-check |
36 | -fcheck-pointer-bounds |
37 | -fchkp-check-incomplete-type |
38 | -fchkp-narrow-bounds |
39 | -fchkp-first-field-has-own-bounds |
40 | -fchkp-flexible-struct-trailing-arrays |
41 | -fchkp-narrow-to-innermost-array |
42 | -fchkp-optimize |
43 | -fchkp-use-fast-string-functions |
44 | -fchkp-use-nochk-string-functions |
45 | -fchkp-use-static-bounds |
46 | -fchkp-use-static-const-bounds |
47 | -fchkp-treat-zero-dynamic-size-as-infinite |
48 | -fchkp-check-read |
49 | -fchkp-check-write |
50 | -fchkp-store-bounds |
51 | -fchkp-instrument-calls |
52 | -fchkp-instrument-marked-only |
53 | -fchkp-use-wrappers |
54 | -fcf-protection= |
55 | -fstack-protector |
56 | -fstack-protector-all |
57 | -fstack-protector-strong |
58 | -fstack-protector-explicit |
59 | -fstack-check |
60 | -fstack-clash-protection |
61 | -fstack-limit-register=reg |
62 | -fstack-limit-symbol=sym |
63 | -fstack-limit |
64 | -fsplit-stack |
65 | -fvtable-verify= |
Immerhin ein Anfang, auch wenn die Warning / Analyse nicht vom Compiler kommt sondern qua Instrumentierung zur Laufzeit. Naturgemäß ist sowas für Cross-Entwicklung schlechter zu nutzen und auch schlechter unterstützt als für Host-Entwicklung, aber die Behauptung, dass ohne teure [tm] Tools nix ginge, ist wohl etwas grobschlächtig. Dann sind da noch Tools wie Valgrind oder Mudflap, oder Tools zur statischen Analyse. Gegeben den Fall, dass man Embedded-Entwicklung ernsthaft betreibt, wird man den Code sauber in Hardware-Abhängiges und in Hardware-Unabhängiges wie Algorithmen und Verwaltungskrempel etc. aufgeteilt haben und entsprechend betesten. Der HW-unabhängige Teil läuft also auch auf einem Host mit voller Verfügbarkeit o.g. Instrumenter — wobei die Übertragbarkeit der Ergebnisse umso mehr eingeschränkt ist, je weiter die Plattformen voneinander abweichen (z.B. sind Ergebnisse für int=32 gröber als für int=16, und weil int-Promotion nicht portiert werden kann).
Torsten R. schrieb: > 2) In allen Abstraktionen, definiertes Verhalten: Daß das Performance kostet, ist schon klar. Deswegen würde ich das ja auch nur für Debug-Builds haben wollen. Quasi eine Art Pascal-Modus für den C-Compiler. Stefan U. schrieb: > Obwohl: Objekt-Orientiert kann man auch in C programmieren. Nur gewinnt > man damit ebenfalls keinen Schönheitswettbewerb. Zumal die grundlegenden Probleme sich damit auch nicht erledigen. Deswegen verwendet man in C++ ja tunlichst keine rohen C-Pointer.
Johann L. schrieb: > Immerhin ein Anfang, auch wenn die Warning / Analyse nicht vom Compiler > kommt sondern qua Instrumentierung zur Laufzeit. Geht aber auch nur unter Linux und hilft nicht besonders weiter, wenn man damit Mikrocontroller programmieren will.
Nop schrieb: > Torsten R. schrieb: > > Daß das Performance kostet, ist schon klar. Deswegen würde ich das ja > auch nur für Debug-Builds haben wollen. Quasi eine Art Pascal-Modus für > den C-Compiler. Wie wäre es mit --just-like-java ? ;-)
Torsten R. schrieb: > Wie wäre es mit --just-like-java ? ;-) Ein -fno-stupid wäre mir ja schon genug. ^^
> Deswegen würde ich das ja auch nur für Debug-Builds haben wollen.
Kannst du doch: Die Option dazu heisst -O0
Nop schrieb: > Johann L. schrieb: > >> Immerhin ein Anfang, auch wenn die Warning / Analyse nicht vom Compiler >> kommt sondern qua Instrumentierung zur Laufzeit. > > Geht aber auch nur unter Linux und hilft nicht besonders weiter, wenn > man damit Mikrocontroller programmieren will. Lies meinen Post einfach zu Ende :-/
Noch einer: 1 Seite Pascal ~ 1 Zeile C. Pascal ist so elend viel Tipparbeit ;)
Joachim D. schrieb: > Noch einer: 1 Seite Pascal ~ 1 Zeile C. > Pascal ist so elend viel Tipparbeit ;) Dann solltest du dir mal APL ansehen. ;-)
Programierer schrieb: > Hallo, > > welche andere Programmiersprachen könnt ihr für ARM cortex M empfehlen, > die auch mit wenig ram&rom (4kB/32kB) auskommt? > > Die allgegenwärtigen libs (in C geschrieben!) sollte man aber noch > weiter verwenden können. > > (Ich habe über die Jahre eine leichte C-Allergie entwickelt, die auch > bei C++ und ähnlichen auftritt) Konfuzius sagt: Wenn Du Dich einer Vergewaltigung nicht entziehen kannst dann lehne Dich zurück und genieße sie. Du wirst nicht um C herumkommen. Also mach das beste draus.
Stefan U. schrieb: >> Deswegen würde ich das ja auch nur für Debug-Builds haben > wollen. > > Kannst du doch: Die Option dazu heisst -O0 Und damit zerfallen dann z.B. Arrays nicht mehr zu Pointern unter Verlust der Längeninformation? Johann L. schrieb: > Lies meinen Post einfach zu Ende :-/ Habe ich. Ist in der Praxis aber nur begrenzt nützlich. Wenn auch noch ein µC-spezifisches OS zum Einsatz kommt, wird der Aufbau eines Mockups so richtig spaßig. Die dafür nötige zusätzliche Entwicklungszeit fällt übrigens auch nicht kostenlos vom Himmel. Es bleibt dabei, daß es diese Möglichkeit "gratis" nur dann gibt, wenn man sowieso Applikationen für Linux erstellt, was die Sache relativ nutzlos macht.
Brille schrieb: > Ist dein Wissen dazu überhaupt noch aktuell? Oder sind die Bugs > vielleicht schon längst fehlerbereinigt .. Ebendas gab ich zu bedenken. Mein Wissen datiert etwa auf Anfang 2017. Brille schrieb: > Muss wirklich JEDES Codeschnipsel immer "hoch optimiert" sein? Sind wir > nicht längst aus dem Zeitalter der "ich muss noch ein paar Bytes mehr > rausquetschen" Analogie herausgewachsen? Natürlich. Nur erzeugt z.B. der GCC selbst auf langweiligster Optimierungsstufe etwa um Faktor 5 weniger Code. Bei Mikroe fehl(ten damals) ja selbst simpelste Sachen wie Speicherzugriffe zusammenzuziehen. Ich erinnere mich düster an elendige Wüsten im Assembly aus "lds lds .. sts sts" (AVR), nur um ein paar Bits in einer lokalen Variable zu setzen (nee...ohne volatile natürlich).
Joachim D. schrieb: > Noch einer: 1 Seite Pascal ~ 1 Zeile C. > Pascal ist so elend viel Tipparbeit ;) So extrem ist das nicht. Das meiste macht doch die IDE automatisch auf Knopfdruck (Methoden und Interfaces implementieren, etc.) und begin geht mir auf ner deutschen Tastatur schneller von der Hand als die unsägliche geschweifte Klammer. Unterm Strich beibt da auch nicht viel mehr zu schreiben als bei den meisten anderen statisch getypten Syntaxen aus dieser Familie auch (C++, Java, C#, etc.). Und wenn man (wie ich) auch unter Pascal den 1TBS/Kernel-"Klammer"-stil pflegt (begin ans Ende der Zeile) kommt auch verkleichbar kompakter Code raus.
>was in C so lautet: >
1 | #define NVIC_ISPR (*((volatile unsigned long *) (0xE000E200)))
|
> >wäre in Pascal etwa so: >NVIC_ISPR : dword absolute $E000E200; naja... ist auch ein bisschen vom C Compiler abhängig. Bei IAR dürfte das gehen - und dann sind wir sogar noch etwas übersichtlicher als Pascal.
1 | uint32_t NVIC_ISPR @0xE000E200; |
Stefan U. schrieb: >> if (x & MASK == MASK) geht nicht ist doch if(x & MASK), da interessiert doch die Rangfolge zu == überhaupt nicht.
>> if (x & MASK == MASK) geht nicht > ist doch if(x & MASK), da interessiert doch die > Rangfolge zu == überhaupt nicht. Doch, denn beabsichtigt war ja das Verhalten von if ((x & MASK) == MASK)
dummschwaetzer schrieb: > Stefan U. schrieb: >>> if (x & MASK == MASK) geht nicht > > ist doch if(x & MASK), da interessiert doch die Rangfolge zu == > überhaupt nicht. Nein, das ist nicht das selbe.
if ((x & MASK) == MASK) ist für mich gleich if(x & MASK) oder wo ist der Unterschied?
dummschwaetzer schrieb: > if ((x & MASK) == MASK) > ist für mich gleich > if(x & MASK) > oder wo ist der Unterschied? Annahme MASK == 0x0F Oben: Alle Bits müssen gesetzt sein. Unten: Mindestens ein Bit muss gesetzt sein.
if(x & MASK) ist auch wahr, wenn Du 000001 mit der Maske 00001111 verUNDest
dummschwaetzer schrieb: > if ((x & MASK) == MASK) > ist für mich gleich > if(x & MASK) > oder wo ist der Unterschied? Laß MASK mal mehr als ein Bit gesetzt haben, dann wäre (x & MASK) gleich TRUE, auch wenn in x nur ein Tuil der Bits von MASK gesetzt sind. Außerdem ist (x & MASK == MASK) soviel wie (x & 1), unabhängig vom Inhalt von MASK.
> if ((x & MASK) == MASK) > ist für mich gleich > if(x & MASK) > oder wo ist der Unterschied? Setzen wir konkrete Werte ein: x=17 MASK=16 ((17 & 16) == 16) ist wahr (17 & 16) ist >0 also auch wahr Setzen wir andere Werte ein: x=0 MASK=16 ((0 & 16) == 0) ist wahr (0 & 16) ist 0, also falsch Jetzt verstanden?
Hallo, ((x&MASK)==MASK), dein Beispiel (((0 & 16) == 0) wird also zu (0 & 16) == 16) und falsch.klappt alo. gut, es wahren die mehr als ein Bit, ich verwende dieses Konstrukt nur zum Testen eines Bits.
Nase schrieb: > Die Compiler würde ich mir aber genau angucken, bevor ich damit > professionell loslege. Zumindest die AVR-Compiler sind/waren unter aller > Sau(*), inklusive lächerlichem Optimierer und extrem subtilen Bugs(**). Funktioniert hier hervorragend im produktiven Einsatz seit mehreren Jahren. In der Tat habe ich einen Bug gefunden, der selten auftritt. Der ist mittlerweile behoben und ich werde bei den Credits bei der Compilerinfo genannt.
> dein Beispiel > (((0 & 16) == 0) > wird also zu > (0 & 16) == 16) Oh ja, natürlich du hast Recht.
ich schätze mal Rust wurde schon genannt, dort gibt es mittlerweile alle Register namen dank der svd2rust tools.
Ben W. schrieb: > ich schätze mal Rust wurde schon genannt, > dort gibt es mittlerweile alle Register namen dank der svd2rust tools. Das Tool ist auch super, nur bringts leider nix wenn die SVD schlichtweg unbrauchbar sind. Und zumindest bei ST sind sie das...
Vincent H. schrieb: > Das Tool ist auch super, nur bringts leider nix wenn die SVD schlichtweg > unbrauchbar sind. Und zumindest bei ST sind sie das... Was genau ist denn unbrauchbar? AFAIK, werden die .svd Dateien auch von den Debuggern benutzt.
> welche andere Programmiersprachen könnt ihr für ARM cortex M empfehlen, > die auch mit wenig ram&rom (4kB/32kB) auskommt? Forth. Damit hast du dann auch ein Alleinstellungmerkmal. Olaf
>Forth. Damit hast du dann auch ein Alleinstellungmerkmal. Aber nur wenn Du die mindestens 20 verschiedenen Forthsystem ignorierst, die es für ARM-Controller gibt ;-)
Ich kann die PAscal wärmstens!! empfehlen. Von Mikroe. Wenn man sich dann in Pascal gut zurecht findet, schreibst Du Programme auf dem PC gleich auch in PAscal. Mit Lazarus Freepascal hast Du dann was, wo Du in kürzester Zeit super Sachen machen kannst. Das einzige was da dran komme wäre Visual C++ von MS nur unendlich komplexer. Daher meine dringende Empfehlung Pascal. Lass Dir keinen Unsinn einreden das PAscal nicht für Bitzugriffe taugt, Leute die das behaubten, haben nicht verstanden. Die vergleichen Pascal aus den 7=/80er Jahren mit dem C von heute..sinnvoller wäre es aber Pascal von heute mit C von heute zu vergleichen.. Dann würde viele eher Pascal verwenden als in C zu frickeln
dazu muss man sagen, mikroe unterstützt so ziemlich alle gängigen STM32 Chips und noch einige andere. Auch das Pascal eignet sich mittlerweile für den produktiven Einsatz. Viel Kritik die ich hier lese, galt noch vor einigen Jahren..aber die Welt dreht sich weiter
Nop schrieb: > Programierer schrieb: > >> welche andere Programmiersprachen könnt ihr für ARM cortex M empfehlen, >> die auch mit wenig ram&rom (4kB/32kB) auskommt? > > Free Pascal, weil C-Allergiker oftmals Pascal mögen. Ich mag C
Tina schrieb: > Dann würde viele eher Pascal verwenden als in C zu frickeln In C wird nicht gefrickelt. ASM dazu was brauchst du mehr?
Hat jemand Erfahrung mit micropython? https://github.com/micropython/micropython Hab ich jetzt gerade auf der oben verlinkten Wiki Seite entdeckt und scheint recht aktiv zu sein.
zu Mikroe..weshalb Thread nicht gelesen. Hatte gesehen das es bereits erwähnt wurde, aber ganz offensichltich nocha uf ganz frühe Versionen bezogen. Mittlerweile läuft das ganz brauchbar und wir auch im Kommerziellen Bereich eingesetzt, wie Lazarus Free Pascal übrigens auch
Tina schrieb: > ganz offensichltich nocha uf ganz frühe Versionen bezogen. Ist „Anfang 2017“ wirklich „ganz früh“? Beitrag "Re: Alternativen zu C, C++ auf ARM cortex M?"
Ist eigentlich das Pascal von Microe kompatibel mit Free Pascal?
W.S. schrieb: > was in C so lautet: > #define NVIC_ISPR (*((volatile unsigned long *) (0xE000E200))) > > wäre in Pascal etwa so: > NVIC_ISPR : dword absolute $E000E200; > easy, gelle? aber leider eben nicht zu kriegen. > > W.S. Du vergleichst Äppel Mit Kohlrouladen. Gruß, Holm
Nop schrieb: > Thomas E. schrieb: > >> Und wo ist da das Pascal-Pendant zu "volatile"? > > Pascal hat kein volatile. > >> In FPC, every statement is basically considered to be a compiler-level >> memory barrier for accesses to global variables. So within a single >> statement multiple accesses can be optimised, but that cannot happen not >> across statements. It's not perfect since it inhibits some optimisation, >> but on the flip side it's very simple and easy to reason about. > > Quelle: > http://lists.freepascal.org/pipermail/fpc-pascal/2015-December/046057.html Ist aber sowieso Wurscht da die obere Zeile nur ein Präprozessor Symbol definiert, ohne jede Funktionalität dahinter.Das ist nichts weiter als #define lehmann 5 ..jedes Auftreten von lehmann im folgenden Text wird durch 5 ersetzt. Das vergleicht W.W. mit einer Variablendefinition. Die ganze Sache wird in Pascal ohne volatile recht lustig wenn die Variable ohne Wissen des Compilers ihren Wert ändert (memory mapped register).. Gruß, Holm
Tina schrieb: [..] > Dann würde viele eher Pascal verwenden als in C zu frickeln Aha. Pascal verwendet man, in C frickelt man. Kompetente Auskunft. Gruß, Holm
Holm T. schrieb: > Die ganze Sache wird in Pascal ohne volatile recht lustig wenn die > Variable ohne Wissen des Compilers ihren Wert ändert (memory mapped > register).. Eben nicht, weil zumindest Free Pascal das von sich aus als volatile handhabt, wenn ich die genannte Quelle richtig verstehe. Dafür geht die Optimierung bei non-volatile halt nicht. Andere Pascal-Compiler könnten das natürlich anders machen, weil reales Pascal mangels brauchbarer Standard-Grundlage schon immer balkanisiert war.
Tina schrieb: > Ich kann die PAscal wärmstens!! empfehlen. > Von Mikroe. Der TE hat nach eigener Aussage eine C-Allergie. Da mikroPascal eher ein mutiertes C als ein echtes Pascal ist (was man durchaus auch positiv sehen kann), wird er vermutlich auch darauf allergisch reagieren. Nop schrieb: > Eben nicht, weil zumindest Free Pascal das von sich aus als volatile > handhabt, wenn ich die genannte Quelle richtig verstehe. Dafür geht die > Optimierung bei non-volatile halt nicht. > > Andere Pascal-Compiler könnten das natürlich anders machen, weil reales > Pascal mangels brauchbarer Standard-Grundlage schon immer balkanisiert > war. Das volatile-Qualifier ist einer der Punkte, wo mikroPascal etwas Sinnvolles von C geerbt hat.
BCPL schrieb: > Vincent H. schrieb: > >> Das Tool ist auch super, nur bringts leider nix wenn die SVD schlichtweg >> unbrauchbar sind. Und zumindest bei ST sind sie das... > > Was genau ist denn unbrauchbar? > > AFAIK, werden die .svd Dateien auch von den Debuggern benutzt. Teilweise fehlende/falsche Bits, teilweise selbst zwischen 2 sehr nah verwandten Derivaten komplett unterschiedliche Namensgebung (z.b. ADC_Common vs. ADC123_Common, etc.), von anderen Familien braucht man da gar nicht erst reden. Teilweise weit hinterher mit der Verfügbarkeit, zumindest verglichen zu den echten Headern, die wohl intern bei ST auch mit irgendeinem Tool erzeugt werden... usw. usf. Prinzipiell wären SVDs eine tolle Sache, aber nicht wenn man sie nicht ordnungsgemäß pflegt. :(
Yalu X. schrieb: > Das volatile-Qualifier ist einer der Punkte, wo mikroPascal etwas > Sinnvolles von C geerbt hat. Ist aber auch wieder typische Pascal-Balkanisierung: je nach Compiler sind ungekennzeichnete globale Variablen mal volatile und mal nicht. Das passiert halt, wenn's keinen praxistauglichen Standard gibt.
Holm T. schrieb: > Ist aber sowieso Wurscht da die obere Zeile nur ein Präprozessor Symbol > definiert, ohne jede Funktionalität dahinter. Sobald man das Prärozessorsymbol mit seinem darin enthaltenen volatile in seinen Code einbaut wird es genauso wirksam als hätte man es direkt selbst dort hingeschrieben. > Das ist nichts weiter als > #define lehmann 5 weder "lehmann" noch "5" kann ich im verlinkten Post finden. > Die ganze Sache wird in Pascal ohne volatile recht lustig Nein, denn wenn Du das von Dir zitierte Post auch gelesen hättest dann hättest Du gesehen daß in FPC jeder Strichpunkt eine Speicherbarriere ist, bzw der Compiler enthält schlichtweg keine Optimierungen die über solche Grenzen hinweg optimieren. Also ist praktisch von Haus aus alles immer volatile. Solange das so bleibt braucht man sich auch keine Gedanken um diesen gesamten Themenkomplex machen. Der Preis den man zahlt sind massiv schlechtere Compileroptimierungen. Das wird wahrscheinlich erst wieder interessant wenn irgendwann mal FPC wie seit Jahren geplant auf LLVM als Backend umsteigt, selbiges könnte wahrscheinlich potentiell bedeutend besser optimieren als der bisherige FPC und Nutzen aus nicht-volatilen Variablen ziehen, vielleicht wird es dann eingeführt.
Yalu X. schrieb: > Der TE hat nach eigener Aussage eine C-Allergie. Da mikroPascal eher ein > mutiertes C als ein echtes Pascal ist (was man durchaus auch positiv > sehen kann), wird er vermutlich auch darauf allergisch reagieren. Zumindest besteht eine deutliche Chance einer solchen Kreuzallergie.
:
Bearbeitet durch User
Bernd K. schrieb: > Holm T. schrieb: >> Ist aber sowieso Wurscht da die obere Zeile nur ein Präprozessor Symbol >> definiert, ohne jede Funktionalität dahinter. > > Sobald man das Prärozessorsymbol mit seinem darin enthaltenen volatile > in seinen Code einbaut wird es genauso wirksam als hätte man es direkt > selbst dort hingeschrieben. > Loriot: Ach!? Du definierst also Interrupt Service Routinen immer im cpp und nicht im Compiler oder Assembler? >> Das ist nichts weiter als >> #define lehmann 5 > > weder "lehmann" noch "5" kann ich im verlinkten Post finden. Wirklich nicht? Tatsache! Bernd K. aber auch nicht. > >> Die ganze Sache wird in Pascal ohne volatile recht lustig > > Nein, denn wenn Du das von Dir zitierte Post auch gelesen hättest dann > hättest Du gesehen daß in FPC jeder Strichpunkt eine Speicherbarriere > ist, bzw der Compiler enthält schlichtweg keine Optimierungen die über > solche Grenzen hinweg optimieren. Also ist praktisch von Haus aus alles > immer volatile. Solange das so bleibt braucht man sich auch keine > Gedanken um diesen gesamten Themenkomplex machen. Der Preis den man > zahlt sind massiv schlechtere Compileroptimierungen. > Nein! Doch! Oh.. > Das wird wahrscheinlich erst wieder interessant wenn irgendwann mal FPC > wie seit Jahren geplant auf LLVM als Backend umsteigt, selbiges könnte > wahrscheinlich potentiell bedeutend besser optimieren als der bisherige > FPC und Nutzen aus nicht-volatilen Variablen ziehen, vielleicht wird es > dann eingeführt. Du bekommst von mir einen grünen Gummipunkt zum Sammeln. Hast Du Dir echt verdient. Gruß, Holm
Bernd K. schrieb: > Nein, denn wenn Du das von Dir zitierte Post auch gelesen hättest dann > hättest Du gesehen daß in FPC jeder Strichpunkt eine Speicherbarriere > ist, bzw der Compiler enthält schlichtweg keine Optimierungen die über > solche Grenzen hinweg optimieren. Also ist praktisch von Haus aus alles > immer volatile. Solange das so bleibt braucht man sich auch keine > Gedanken um diesen gesamten Themenkomplex machen. Der Preis den man > zahlt sind massiv schlechtere Compileroptimierungen. Vorsicht bei derartigen Schlußfolgerungen, wenn man so C-orientiert argumentiert wie du grad eben. Normalerweise gilt bei Pascal das "immer volatile" nur für Variablen, die eine Prozedur oder Funktion nicht unter ihrer vollständigen Kontrolle hat. Das ist aber ne subtile Sache. Erstens sind lokale Variablen einer Prozedur oder Funktion nicht volatile, es sei denn, sie werden von lokalen Prozeduren/Funktionen verwendet. (ja, dieses Konzept gibt es in Pascal). Zweitens sind unit-interne globale Variablen nur dann volatile, wenn sie entweder im Interface veröffentlicht sind oder innerhalb des Units von mehreren Instanzen verwendet werden, so daß eine Instanz eben nicht davon ausgehen kann, daß sie den alleinigen Zugriff darauf hat. Und ein wirklich auf µC als Zielplattform portiertes Pascal müßte das "absolute" automatisch als volatile behandeln, das ist ja wohl klar. Nun ja, kommen wir noch kurz zu Mikroe und deren Pascal: Da ist nach wie vor nur eine beschränkte Auswahl an Zielplattformen möglich - und als Anwender kann man diese nicht erweitern. Genau das ist ein Disqualifizierungsmerkmal gegenüber den üblichen C-Compilern jenseitsvon Mikroe. Ich hab grad mal geschaut: einige Freescale MK22xx, dazu viele STM32, Texas/Stellaris - aber ansonsten weder LPC noch Nuvotons usw. W.S.
wowzu auch...das ist eben genau das Problem von diesem Opensource Gedanken..alles muss frei und toll und für alles sein.Schlussendlich ist alles ein wildes Gebastel. Wir sehen alle wie toll das bei linux klappt... Bei Mirko e. Download. Starten.. Hellow World tippen, übertragen ..läuft! Hallo world über Uart tippen..übetragen ..läuft.. Das gleiche bei Freepascal..download..Tippen..läuft.... In C geht das höchstens mit MS Visual C++ Mehr will ich damit nicht sagen. Und Sowohl Freepascal als auch mikroe werden in kommerziellen Produkten eingesetzt. Und diese Gejammer dieses und jenes ginge nicht..so ein Quatsch..im Alltag spielt das für 99,9% überhaupt keine Rolle Und sicher ginge auch Python..hier kenne ich mich aber nicht gut genug mit aus, als das ich das jetzt vergleichen könnte..was da mehr doer weniger Vorteile hätte im Vergleich zu Pascal. Lange Rede kein Sinn...teste das doch einfach mal, schau die einfache Beispiele an und entscheide selbst. Ich fände es aber super, wenn Du das Ergebnis hier schreiben würdest, egal wie es ausgefallen ist.
Beitrag #5210162 wurde vom Autor gelöscht.
W.S. schrieb: > Zweitens sind unit-interne globale Variablen nur dann volatile, wenn sie > entweder im Interface veröffentlicht sind oder innerhalb des Units von > mehreren Instanzen verwendet werden, so daß eine Instanz eben nicht > davon ausgehen kann, daß sie den alleinigen Zugriff darauf hat. Es gibt nicht nur I/O-Ports. Wie stellt sich das bei Interrupt-Handlern dar? Ohne das Wissen eines Compilers, welche der nur innerhalb der Unit oder Instanz verwendeten Variablen auch von Handlern genutzt werden, wird es dann doch etwas schwierig, oder? Ebenso Multithreading als Erweiterung dieses Prinzips. Das ist doch im Grunde genau das gleiche Problem. Auch in C wird "volatile" nur dort erforderlich, wo der Compiler nicht selber weiss worum es geht. Wenn ein non-C Compiler Unit- oder Instanz-lokale Variablen nicht optimieren darf, weil mehr dahinter ist als die für ihn sichtbare Reihenfolge der Codeausführung, dann muss man ihm das sagen. Man kann sich dann nur darüber streiten, in welcher Form man das macht. Weiss ein Compiler, dass eine Funktion ein Handler ist, und gibt es keine Pointer, dann geht es ohne "volatile", weil er es aus dem Code ableiten kann. Andernfalls sind wieder alle Wetten offen. Mit der erwähnten Beschränkung auf Optimierung nur innerhalb eines Statements ist man natürlich auf der sicheren Seite. Aber wenn man darüber hinaus will, muss man sich schon Gedanken um Interrupts und Multithreading machen. Das Ergebnis muss nicht dem "volatile" in C entsprechen, das geht auch anders. Aber irgendwas wird nötig.
:
Bearbeitet durch User
Tina schrieb: > Mehr will ich damit nicht sagen. Ist auch besser so, ehrlich. Das vermeidet, dass du dich hier weiter mit ausgesprochener „Sachkenntnis“ blamierst.
Die C Compiler der 70er und frühen 80er arbeiten ungefähr nach dem erwähnten Muster, Optimierungen mit Folgen für Zugriffe auf Variablen allenfalls innerhalb von Statements durchzuführen. Die Mainframes waren schon wesentlich weiter, aber die hatten auch die Kapazitäten dazu (dortige Erfahrungen führten zur RISC Philosophie). Ein Compiler, der ohne allzu viele Overlays in den 64KB grossen logischen Adressraums einer PDP-11 passen und dafür keine 12 Passes verbraten soll, der ist halt begrenzt. Es war der Druck neuer ernsthaft optimierender C Compiler auf 32-Bit Maschinen, der "volatile" überhaupt erst erforderlich machte. > wie seit Jahren geplant auf LLVM als Backend umsteigt, selbiges könnte > wahrscheinlich potentiell bedeutend besser optimieren als der bisherige > FPC Eine rigide Beschränkung der Optimierung kann Sinn ergeben. Es gibt Umgebungen, in denen Code grundsätzlich nur unoptimiert genutzt wird, weils sonst einfach zu gefährlich ist. Lieber mehr Bums in Hardware als ein Bums gegen den Baum. Mit der Vorgabe keiner Statement-übergreifender Optimierung landet man ähnlich. Was man nicht falsch machen kann, das macht man auch nicht falsch. Ob es dann allerdings überhaupt Sinn ergibt, hochkomplexe Compiler wie GCC oder LLVM als Grundlage zu nehmen, möchte ich in Frage stellen. Wenn Zuverlässigkeit höchste Priorität hat, dürfte es besser sein, kleine übersichtliche Compiler zu verwenden, die Statements ziemlich direkt in Code umsetzen. Statt sich mit zigmal grösseren Compilern abzukämpfen, in denen ein grosser Teil des Quellcodes überhaupt nicht genutzt wird. Denn mit jeder geänderten Zeile im Compiler geht das Test- und Zertifizierung-Gedöns erneut los, selbst wenn diese Zeile überhaupt nicht zum tragen kommt.
Jörg W. schrieb: > Ist auch besser so, ehrlich. Nee, laß mal. Für das, was die Leute von Mikroe vorgesehen haben, funktioniert es wohl. Aber das ist eben auch zugleich die Beschränkung. Wenn sich jeder seine Entsprechung zu "meinchip.h" selber schreiben könnte (Konjunktiv, kein MUSS), dann wäre das der Verbreitung extrem nützlich gewesen. Ist aber nicht, wohl aus Firmenpolitik, also war's das. W.S.
A. K. schrieb: > mit jeder geänderten Zeile im Compiler geht das Test- und > Zertifizierung-Gedöns erneut los, selbst wenn diese Zeile überhaupt > nicht zum tragen kommt. Ich hatte schon ein solches GCC-Update, bei dem der Test dann sehr schnell ging - das erzeugt Hexfile war nämlich dasselbe wie vorher.
A. K. schrieb: > Es gibt nicht nur I/O-Ports. > > Wie stellt sich das bei Interrupt-Handlern dar? A. K. schrieb: > Ebenso Multithreading als Erweiterung dieses Prinzips. Hast du es denn nicht gelesen, was ich geschrieben habe? Bei Interrupthandlern sieht das ganz genauso aus wie bei Threadfunktionen am PC. Meine Delphi-Programme benutzen schon seit ewig Threads und das funktioniert auch seit ewig, ohne daß dafür dedizierte Pendants zu "volatile" erforderlich wären. Die Regeln dazu hab ich doch umrissen. Bei C ist das erklärlicherweise schwieriger, weil es dort vieles nicht gibt und deshalb in erheblichem Maße mit Zeigern und Casts gearbeitet werden muß. Und mal ganz abgesehen davon.. ..schau dir bloß mal an, wie all die STM32-Jünger heutzutage ihre Controller programmieren: Da werden XYZ_InitStruct's bis zum Bersten gefüllt und ein Stück Libfunktion aufgerufen, wo doch ein simples Beschreiben der HW-Register es um Längen effizienter getan hätte. Glaubst du wirklich, daß bei solchem Programmierstil ein noch so hoch optimierender C-Compiler irgendwas ausrichten kann? Ich nicht. W.S.
"Ist auch besser so, ehrlich. Das vermeidet, dass du dich hier weiter mit ausgesprochener „Sachkenntnis“ blamierst."# Na versucht da wieder ein Moderator Unruhe zu stiften?.... Sorry, aber solch Kommentare sollte man sich als Mod klemmen
Nop schrieb: > Ich hatte schon ein solches GCC-Update, bei dem der Test dann sehr > schnell ging - das erzeugt Hexfile war nämlich dasselbe wie vorher. Das hilft dir nicht wirklich. Denn das besagt nicht, dass es bei einer Änderung in deinem Programm immer noch neutral bleibt. Wenn dann auch noch die verwendete Version des Compiler selbst Teil einer restriktiven Vorgabe ist, man also nicht einfach den Update der IDE ziehen und mal eben das Projekt neu übersetzen darf, dann dürften bekannte Bugs des Compilers, um die man herum programmiert, typischer sein als neue Versionen des Compilers mit Ausicht auf neue unbekannte Bugs.
W.S. schrieb: > ..schau dir bloß mal an, wie all die STM32-Jünger heutzutage ihre > Controller programmieren: Da werden XYZ_InitStruct's bis zum Bersten > gefüllt und ein Stück Libfunktion aufgerufen, wo doch ein simples > Beschreiben der HW-Register es um Längen effizienter getan hätte. Hast denn nicht gelesen, was ich schon vor langer Zeit geschrieben habe? Meine Rede seit Jahren. ;-) Effizienz ist aber weniger der Punkt, meistens jedenfalls, wenns dadurch immerhin einfacher und übersichtlicher würde. Was es schon aufgrund der umständlichen struct-Technik nicht ist. Unschön finde ich auch, dass dabei eine gut dokumentierte Hardware durch eine mässig bis schlecht dokumentierte Library ersetzt wird. Und man sich spätestens beim Debugging sowieso mit der Auswirkung auf die Hardware befassen muss, also um dessen Doku sowieso nicht herum kommt. > Hast du es denn nicht gelesen, was ich geschrieben habe? Wenn es in dem betreffenden Beitrag stand, dann habe ich es darin nicht gefunden. Und im Rest vom Thread auch nicht. Ich bin konkret weder mit Delphi noch sonst einem halbwegs aktuellen Pascal näher vertraut, weshalb ich deren Konzepte zur Kennzeichnung oder Vermeidung nebenläufigen Zugriffs nicht kenne. Genau die würden mich ja interessieren.
:
Bearbeitet durch User
Beitrag #5210271 wurde vom Autor gelöscht.
A. K. schrieb: > Wenn es in dem betreffenden Beitrag stand, dann habe ich es darin nicht > gefunden. Und im Rest vom Thread auch nicht. Mein Verstaendnis von der Sache: Nur lokale Variablen werden optimiert, globale Variablen sind implizit volatil (allerdings nur im Rahmen eines Statements). Welche Variablen genau unter lokal und global einsortiert werden, weiss ich aber auch nicht. Ein Interrupt greift auf Hardwareregister zu, diese sind global (= volatile). Werte werden in Puffervariablen geschrieben, diese sind global (=volatile).
W.S. schrieb: > Glaubst du wirklich, daß bei solchem Programmierstil ein noch so hoch > optimierender C-Compiler irgendwas ausrichten kann? Ich nicht. Das hat nix mit Glauben zu tun, das ist gar kein Problem. Gute Compiler wie der GCC können noch ganz andere Sachen optimieren, mit mehreren verschachtelten temporären Objekten, per templates generierten Algorithmen usw. Im konkreten Falle der ST HAL müsste man dazu aber die Optimierung erstmal erlauben, indem die Funktionen als "inline" markiert, was ST natürlich nicht getan hat. Schlau wäre es zudem, wo möglich die structs zu initialisieren und als constexpr zu markieren anstelle von nachträglichen Zuweisungen, sodass sie im Flash landen. Wird die entsprechende HAL-Funktion mehrfach genutzt, spart man so durchaus Flash gegenüber direkten Register-Zugriffen. Tina schrieb: > Hellow World tippen, übertragen ..läuft! > Hallo world über Uart tippen..übetragen ..läuft.. Schön, ein System was die schnelle Implementierung von Hello World ermöglicht! Das kann Arduino (C++) auch. Möchte man mehr Freiheiten für komplexere Aufgaben, freut man sich über flexiblere Systeme, die dann natürlich schwieriger zu handhaben sind. A. K. schrieb: > Aber wenn man > darüber hinaus will, muss man sich schon Gedanken um Interrupts und > Multithreading machen. Das Ergebnis muss nicht dem "volatile" in C > entsprechen, das geht auch anders. Aber irgendwas wird nöti Bei Multithreading ist aber volatile auch ungeeignet, schon alleine weil nicht-wegoptimierte Zugriffe noch lange kein "konsistentes" Verhalten bei Multiprozessor-Systemen garantieren. Dort nutzt man atomics, Mutexe usw. Beispiel:
1 | volatile int a = 0, b = 0; |
2 | void thread1(void) { |
3 | a = 1; |
4 | b = 2; |
5 | }
|
6 | void thread2(void) { |
7 | printf ("%d,", b); |
8 | printf ("%d\n", a); |
9 | }
|
Die Ausgabe kann z.B. "2, 0" sein, trotz volatile. Hier brauchts nicht nur Optimierungs-Barrieren, sondern auch Speicher-Barrieren, wie sie von atomics geboten werden. Vielleicht kann jemand was dazu sagen, wie Pascal das handhabt?
Dr. Sommer schrieb: > Das hat nix mit Glauben zu tun, das ist gar kein Problem. In diesem Falle habe ich da schon meine Zweifel. Da werden Bits in IO-Register gesetzt (die sind "volatile"), die da schon so drin stehen, weil man ja diese structs immer komplett befüllen muss als Nutzer, und die Bibliotheksfunktion sie dann auch komplett in die Hardware reinwirft. Hat allerdings nichts mit C oder Alternativen dazu zu tun. :-)
W.S. schrieb: > Bei C ist das erklärlicherweise schwieriger, weil es dort vieles nicht > gibt und deshalb in erheblichem Maße mit Zeigern und Casts gearbeitet > werden muß. Das ist falsch, denn in C hat volatile weder mit Zeigern noch mit Casts etwas zu tun. Es ist in C drin, weil C als Sprache zur Systemprogrammierung konzipiert und dann auch eingesetzt worden ist. Sobald man den ersten RX/TX-Interrupt hat, wird offensichtlich, daß man das braucht. Pascal hat das nicht, weil es als nutzlose Spielzeugsprache aus dem Elfenbeinturm ISO-standardisiert worden ist. In der Folge hat jeder Compiler-Hersteller sein eigenes Süppchen kochen müssen, um daraus etwas praktisch Brauchbares zu machen.
Feldstecher schrieb: > Mein Verstaendnis von der Sache: Nur lokale Variablen werden optimiert, > globale Variablen sind implizit volatil (allerdings nur im Rahmen eines > Statements). So gehts natürlich ohne Kennzeichnung, wie ich schon schrieb. Ist aber eben auch recht restriktiv hinsichtlich Optimierung. Im Kontext von Controllern kann das ein akzeptabler Kompromiss sein. Interessant sind Variablen, die nur innerhalb des Moduls (oder Unit, wie immer das heisst) bekannt sind, aber ausserhalb der Funktionen/Prozeduren. Wenn du diese in deinen Begriff "global" einschliesst, dann gibts keine Probleme.
Nop schrieb: > Pascal hat das nicht, weil es als nutzlose Spielzeugsprache aus dem > Elfenbeinturm ISO-standardisiert worden ist. In der Folge hat jeder > Compiler-Hersteller sein eigenes Süppchen kochen müssen, um daraus etwas > praktisch Brauchbares zu machen. Dass es hier nicht um das Wirth'sche Pascal der 70er geht ist offensichtlich. Wenn man plattformübergreifend programmiert ist das natürlich ein Kriterium, man ist mit Pascal-Deriviaten etwas festgelegt. Aber das muss im Controller-Umfeld nicht unbedingt ein grosses Problem sein.
Dr. Sommer schrieb: > Im konkreten Falle der ST HAL müsste man dazu aber die > Optimierung erstmal erlauben, indem die Funktionen als "inline" > markiert Nein. "inline" ist lediglich ein unverbindlicher Vorschlag an den Compiler, der aber gemäß der as-if-Philosophie mit und ohne inline inlinen kann oder auch nicht. > was ST natürlich nicht getan hat. Schlau wäre es zudem, wo > möglich die structs zu initialisieren und als constexpr zu markieren In C?! > Die Ausgabe kann z.B. "2, 0" sein, trotz volatile. Hier brauchts nicht > nur Optimierungs-Barrieren, sondern auch Speicher-Barrieren Die sind natürlich hardware-spezifisch, aber volatile ist die halbe Miete.
Nop schrieb: > Nein. "inline" ist lediglich ein unverbindlicher Vorschlag an den > Compiler, der aber gemäß der as-if-Philosophie mit und ohne inline > inlinen kann oder auch nicht. Korrekt. Aber beim inlinen hat der Compiler viel mehr Möglichkeiten zur Optimierung. Optimieren ist ja auch nicht vom Standard vorgeschrieben. Nop schrieb: > In C?! Das ist natürlich C++. "static const" hilft aber auch in C. Nop schrieb: > Die sind natürlich hardware-spezifisch, aber volatile ist die halbe > Miete. Was bringt die halbe Miete, wenn sie nicht funktioniert? Man nutzt einfach atomics wie sie vom Standard vorgeschrieben sind und kein volatile, und es funktioniert. volatile braucht man bei normalen Programmen mit klassischem Multithreading nie, das ist nur für Low-Level-Programmierung mit Interrupts und IO-Registern.
A. K. schrieb: > Es gibt nicht nur I/O-Ports. In C ist volatile nur für I/O Zugriffe relevant, oder? Volatile verhindert kein reordering, synchronisiert nicht und garantiert keine atomaren Zugriffe. Wie sieht das bei Free Pascal aus? Gibt es da so etwas wie _Atomic(Type) (C) und atomic<Type> (C++), oder werden alle Zugriffe auf "globale" Objekte automatisch voll synchronisiert (barrier,release/acquire, ...), oder muss man alles selbst synchronisieren?
Nop schrieb: > Sobald man den ersten RX/TX-Interrupt hat, wird offensichtlich, daß man > das braucht. In C ja. Aber es sind auch andere Konzepte vorstellbar. Denk dir eine Sprache, mit ein paar Eigenschaften: - Es gibt zumindest in Handlern keine Pointer. - Ein Handler nutzt nur Variablen aus dem Modul, in dem er definiert ist. - Ein Handler wird entsprechend gekennzeichnet. Dann hat der Compiler den vollen Überblick darüber, welche Variablen auf welche Weise nebenläufig sind, ohne dass man die extra kennzeichnen müsste. Nämlich nur die in Handlern. Und er könnte dann sogar besser optimieren als C, beispielsweise weil er mit einer Variable, die im Hauptkontext geschrieben und im Handler gelesen wird, anders umgehen kann als umgekehrt. Multithreading wäre dann ein eigenes Thema.
A. K. schrieb: > Dass es hier nicht um das Wirth'sche Pascal der 70er geht ist > offensichtlich. Schon, aber dieser Unsinn ist standardisiert worden. Eine Konsequenz ist, daß eventuelle Änderungen stets abwärtskompatibel sein müssen, weil man nicht einfach wie in C sagen kann, nach welchem Standard man denn compilieren will. Gibt ja keinen brauchbaren. > Wenn man plattformübergreifend programmiert ist das > natürlich ein Kriterium, man ist mit Pascal-Derivaten etwas festgelegt. Vor allem wird es lästig, wenn man z.B. Mockups erstellen will. Dann ist man direkt auf Compiler begrenzt, die auf PC und dem Controller verfügbar sind. Effektiv also auf FPC. Für Hobby OK, aber keine Firma würde sich auf etwas einlassen, wo man im Ernstfall mit Glück in irgendeinem Forum nachhaken kann. > Aber das muss im Controller-Umfeld nicht unbedingt ein grosses Problem > sein. Ist es aber. Da es keine Standards gibt, sondern nur proprietäres Gefrickel (und das schon weit vor Turbo-Pascal), finden Sprachdiskussionen nicht herstellerübergreifend statt wie bei C. Die Folge ist, daß jeder irgendwie erweitert und man überhaupt keine referenzierbare Baseline bekommt. Den Vendor-Lockin gibt's natürlich gratis dazu. Mit C muß ich mir keine Gedanken machen, was für einen Compiler und Hersteller ich da gerade habe, denn da das standardisiert ist, verhält es sich überall gleich. Stellenweise gleich krank, aber immerhin. Dennoch sehe ich Pascal als Lehrsprache im Vorteil gegenüber C, schon weil das strikte Typensystem den Anfänger von vornherein sensibilisiert. Zwei/Drei-Sterneprogrammierung braucht ein Anfänger eh nicht.
mh schrieb: > In C ist volatile nur für I/O Zugriffe relevant, oder? Jein. Man nimmt das auch, wenn Interrupts einem Sachen in einen Buffer schaufeln, den man aus der Applikation lesen will - und umgedreht. Also nicht nur direkt für die IO-Register-Zugriffe.
Jörg W. schrieb: > In diesem Falle habe ich da schon meine Zweifel. Sie sind aber unangebracht. Ich verstehe nicht ganz was du meinst, habe es aber ausprobiert: Die angehängte Datei ist eine Zusammenstellung der Funktion und Definitionen zur Initialisierung eines GPIO-Pins in der HAL. Die Funktion ist mit always_inline markiert. Das sieht dann ziemlich schlimm aus und die Funktion ist sehr lang, aber der GCC macht daraus bei -O3:
1 | 00000000 <test>: |
2 | 0: 4a03 ldr r2, [pc, #12] ; (10 <test+0x10>) |
3 | 2: 6813 ldr r3, [r2, #0] |
4 | 4: f023 030f bic.w r3, r3, #15 |
5 | 8: f043 0303 orr.w r3, r3, #3 |
6 | c: 6013 str r3, [r2, #0] |
7 | e: 4770 bx lr |
8 | 10: 40010800 .word 0x40010800 |
Besser geht's m.W. nicht. Ob Pascal-Compiler, oder proprietäre Compiler wie der ARMCC so gut sind, bliebe noch zu erforschen...
Dr. Sommer schrieb: > Was bringt die halbe Miete, wenn sie nicht funktioniert? Man nutzt > einfach atomics wie sie vom Standard vorgeschrieben sind Atomics in C? Nach welchem Standard? Ansonsten kann man ohne weiteres volatile kombinieren mit einem Macro, das einem einen hardwaremäßigen Memsync gibt, und schon hat man, was man braucht. Ich hab sowas auch schon gemacht, weil das zwar in gewisser Weise ein dirty hack ist, dafür aber portabel unter allen Betriebssystemen funktioniert. Sollte man halt nicht gerade so einbauen, daß es einem die Performance ruiniert.
Nop schrieb: > Atomics in C? Nach welchem Standard? C11. Nop schrieb: > Ansonsten kann man ohne weiteres volatile kombinieren mit einem Macro, > das einem einen hardwaremäßigen Memsync gibt, und schon hat man, was man > braucht. Über fiese Hacks und Inline-Assembler brauchen wir wohl nicht zu diskutieren...
Dr. Sommer schrieb: > Beispiel:
1 | volatile int a = 0, b = 0; |
2 | void thread1(void) { |
3 | a = 1; |
4 | b = 2; |
5 | }
|
6 | void thread2(void) { |
7 | printf ("%d,", b); |
8 | printf ("%d\n", a); |
9 | }
|
> Die Ausgabe kann z.B. "2, 0" sein, trotz volatile.
Das ist leider so nicht ganz richtig. Die schreibenden Zugriffe auf a
und b in thread1 dürfen nicht vertauscht werden weil a und b volatile
sind.
mh schrieb: > In C ist volatile nur für I/O Zugriffe relevant, oder? Nein, es ist auch für Interrupts und Multithreading relevant. Atomarer Zugriff ist zwar ein eigenes Thema, aber wenn aufgrund entsprechender Massnahmen gesichert ist, dass kein nicht-atomarer Zugriff unterbrochen wird, muss trotzdem sichergestellt werden, dass ein Zugriff überhaupt stattfindet. Der Klassiker hierfür ist:
1 | bool flag; |
2 | |
3 | void handler(void) |
4 | { |
5 | flag = true; |
6 | } |
7 | |
8 | void run(void) |
9 | { |
10 | .. egal was, aber lass "flag" in Ruhe .. |
11 | } |
12 | |
13 | void f(void) |
14 | { |
15 | for (;;) { |
16 | if (flag) { |
17 | run(); |
18 | flag = false; |
19 | } |
20 | } |
21 | } |
Ohne "volatile" bei "flag" wird ein optimierender Compiler in f() nicht jedesmal in der Schleife auf "flag" zugreifen, sondern genau 1x am Anfang und von der Änderung nichts mitkriegen.
mh schrieb: > Die schreibenden Zugriffe auf a > und b in thread1 dürfen nicht vertauscht werden weil a und b volatile > sind. Vom Compiler nicht. Der Prozessor weiß davon nix und kann die anordnen wie er lustig ist.
Hier noch eine Quelle dazu: https://stackoverflow.com/a/4558031 "Short & quick answer: volatile is (nearly) useless for platform-agnostic, multithreaded application programming. It does not provide any synchronization, it does not create memory fences, nor does it ensure the order of execution of operations. It does not make operations atomic. It does not make your code magically thread safe. volatile may be the single-most misunderstood facility in all of C++."
Nop schrieb: > mh schrieb: > >> In C ist volatile nur für I/O Zugriffe relevant, oder? > > Jein. Man nimmt das auch, wenn Interrupts einem Sachen in einen Buffer > schaufeln, den man aus der Applikation lesen will - und umgedreht. Also > nicht nur direkt für die IO-Register-Zugriffe. In dem Fall muss der Zugriff aber auch atomar sein. Die Zugriffe dürfen also nicht unterbrechbar sein und dürfen nicht umgeordnet werden.
Dr. Sommer schrieb: > Nop schrieb: >> Atomics in C? Nach welchem Standard? > C11. Ah, gut zu wissen, danke. > Über fiese Hacks und Inline-Assembler brauchen wir wohl nicht zu > diskutieren... Nix inline-Assembler, das geht mit "__sync_synchronize" sowohl mit GCC als auch mit LLVM. Sinnigerweise kapselt man das mit einem eigenen Macro, falls man auf einen Compiler stößt, bei dem man es anders machen müßte.
Nop schrieb: > Nix inline-Assembler, das geht mit "__sync_synchronize" sowohl mit GCC > als auch mit LLVM. Ah, weil compilerspezifische nichstandardisierte Builtins gleich viel besser sind als Assembler ;-) Vor C11 und C++11 haben die beiden Sprachen rein technisch gar kein Multithreading unterstützt, das wurde nur durch Spracherweiterungen möglich. C++11 hat dann Atomics eingeführt, und C hat sie abgekupfert - seitdem kann man plattformunabhängig und standardkonform mit Multithreading arbeiten, und das ganz ohne volatile. Atomics können einem aber leicht einen Knoten ins Hirn machen...
Nop schrieb: >> Aber das muss im Controller-Umfeld nicht unbedingt ein grosses Problem >> sein. > > Ist es aber. Da es keine Standards gibt, sondern nur proprietäres > Gefrickel Wenn sich jemand bei einer bestimmten Lösung für eine bestimmtes Werkzeug entscheidet, dann kann das auch sinnvoll sein. Auch dann, wenn er sich mit diesem Werkzeug festlegt. Das ist seine Entscheidung. Ich würde auch empfehlen, den Begriff "Gefrickel" nicht überzustrapazieren. Es sei denn man ist ohnehin auf Kravall aus. Nicht jede spezielle Lösung ist schon deshalb Gefrickel, weil sie speziell ist. Apropos Wirth: In diesem Sinn war Wirth ein Frickler erster Güte ;-). Seine Philosophie war nämlich, sich für jedes Problem, das er nicht mit einem seiner bestehendene Werkzeug sauber abdecken konnte, ein neues Werkzeug zu schaffen. Standards, Multiplattformfähigkeit und Vendor-Lockin hat ihn wenig interessiert (als Prof konnte ihm das auch egal sein).
mh schrieb: > In dem Fall muss der Zugriff aber auch atomar sein. Nein, muß er nicht. Immerhin hat man ja drei Variablen: Lese-Index, Schreib-Index und Buffer. Man muß das halt in der richtigen Reihenfolge machen und sich ggf. lokale Kopien der Indices anlegen, auf denen man arbeitet. Das ist eigentlich ziemlich straight-forward.
Dr. Sommer schrieb: > Ah, weil compilerspezifische nichstandardisierte Builtins gleich viel > besser sind als Assembler ;-) Wieso, wenn man, wie ich sagte, mit einem eigenen Macro kapselt, dann ist sowas nicht weiter wild.
A. K. schrieb: > Ohne "volatile" bei "flag" wird ein optimierender Compiler in f() nicht > jedesmal in der Schleife auf "flag" zugreifen, sondern genau 1x am > Anfang und von der Änderung nichts mitkriegen. Ja, in deinem Beispiel stimmt das. Aber der Compiler darf alles (natürlich nicht wirklich alles ;-) ) was nicht volatile ist um die volatile Zugriffe anders anordnen. Wenn der Inhalt deiner for-Schleife so aussieht:
1 | int foo = 0; |
2 | if (flag) { |
3 | foo = f(); |
4 | flag = false; |
5 | }
|
6 | // mache was mit foo
|
Und f sieht so aus:
1 | int f() { |
2 | // ... berechne Wert ...
|
3 | return Wert; |
4 | }
|
dann kann der Compiler daraus
1 | int foo = f(); |
2 | if (flag) { |
3 | flag = false; |
4 | }
|
5 | else { |
6 | f = 0; |
7 | }
|
8 | // mache was mit foo
|
machen, solange er sehen kann das f keine Nebeneffekte hat. Das in diesem Fall nicht sinnvoll und nicht wirklich schädlich, kann aber schnell ein Problem werden wenn das Flag andere Daten schützt, die im Handler gesetzt werden.
A. K. schrieb: > Nicht > jede spezielle Lösung ist schon deshalb Gefrickel, weil sie speziell > ist. Ich hab seinerzeit genug Frust mit der Balkanisierung von Pascal gehabt, weil im Unterricht Turbo-Pascal eingesetzt wurde, ich aber einen Atari ST hatte und mir somit ST-Pascal verfügbar gewesen wäre. Selbstverständlich inkompatibel. Mit C wäre das alles kein Problem gewesen, aber mit Pascal gab's dann abenteuerliche Klimmzüge, die allein dem Pascal-Sprachgefrickel geschuldet waren.
Dr. Sommer schrieb: > mh schrieb: >> Die schreibenden Zugriffe auf a >> und b in thread1 dürfen nicht vertauscht werden weil a und b volatile >> sind. > Vom Compiler nicht. Der Prozessor weiß davon nix und kann die anordnen > wie er lustig ist. Ist das so? Der Standard sagt soweit ich weiß, dass die Zugriffe nicht vertauscht werden dürfen und unterscheidet nicht zwischen Compiler und CPU. Also muss der Compiler dafür sorgen, dass die CPU nichts vertauscht (? oder .)
mh schrieb: > Ist das so? Lies doch meinen Link. Der Standard würde wohl kaum explizit vorschreiben, dass Atomics eine Reihenfolge definieren, wenn volatile Variablen es auch täten. Wie gesagt, alte C Standards können eigentlich kein Multithreading, und das dort enthaltene volatile ist nicht dafür gedacht oder geeignet.
mh schrieb: > Ist das so? Kann man übrigens auch einfach ausprobieren:
1 | #include <stdio.h> |
2 | |
3 | void print (int x) { |
4 | printf ("%d\n", x); |
5 | }
|
6 | |
7 | volatile int a = 0, b = 0; |
8 | void thread1(void) { |
9 | a = 1; |
10 | b = 2; |
11 | }
|
12 | void thread2(void) { |
13 | print (b); |
14 | print (a); |
15 | }
|
wird zu
1 | 0000000000000000 <print>: |
2 | 0: 89 fa mov %edi,%edx |
3 | 2: be 00 00 00 00 mov $0x0,%esi |
4 | 7: bf 01 00 00 00 mov $0x1,%edi |
5 | c: 31 c0 xor %eax,%eax |
6 | e: e9 00 00 00 00 jmpq 13 <thread1> |
7 | |
8 | 0000000000000013 <thread1>: |
9 | 13: c7 05 00 00 00 00 01 movl $0x1,0x0(%rip) # 1d <thread1+0xa> |
10 | 1a: 00 00 00 |
11 | 1d: c7 05 00 00 00 00 02 movl $0x2,0x0(%rip) # 27 <thread1+0x14> |
12 | 24: 00 00 00 |
13 | 27: c3 retq |
14 | |
15 | 0000000000000028 <thread2>: |
16 | 28: 48 83 ec 08 sub $0x8,%rsp |
17 | 2c: 8b 3d 00 00 00 00 mov 0x0(%rip),%edi # 32 <thread2+0xa> |
18 | 32: e8 00 00 00 00 callq 37 <thread2+0xf> |
19 | 37: 8b 3d 00 00 00 00 mov 0x0(%rip),%edi # 3d <thread2+0x15> |
20 | 3d: 58 pop %rax |
21 | 3e: eb c0 jmp 0 <print> |
(printf ausgelagert um Code zu verkürzen). Ich seh da nix mit Memory Barriers oder Synchronisierung. Der Compiler weiß an der Stelle nicht, ob die beiden Funktionen nacheinander oder von verschiedenen Threads aufgerufen werden, kann hier also auch nichts optimieren.
Nop schrieb: > gewesen, aber mit Pascal gab's dann abenteuerliche Klimmzüge, die allein > dem Pascal-Sprachgefrickel geschuldet waren. Ich will hier nicht speziell auf irgendein bestimmten Pascal raus. Oder auf irgendeine bestimmte Sprache. Sondern auf Entscheidungsprozesse allgemein. Denk dir folgende Situation: Eine Firma A bringt eine neue Technik raus, neue geniale Hardware, eine neuen Sprache mit neuen Eigenschaften, egal. Eine andere Firma B sieht im Gegensatz zur konservativen Konkurrenz frühzeitig das Potential und bringt auf dieser Basis ein Produkt, das halb so teuer oder doppelt so schnell ist wie die Konkurrenz. Eben weil sie als einzige oder zumindest erste auf etwas setzt, das neu ist und speziell. Wenn das Zeug von Firma A rechtzeitig funktioniert, hat B gewonnen und die Konkurrenz hat ein grosses Problem. Wenn nicht, hat B ein Problem. Beides hat es in der Vergangenheit schon öfter gegeben. Das macht diese Entscheidung zu einer wesentlichen unternehmerischen Entscheidung. Aber Begriffe wie "Gefrickel" sind in hier Schwachsinn (auch wenn die im Gefolge eines Fehlschlags garantiert aufkommen ;-). Deshalb: Nicht jede spezielle Lösung ist unangebracht. Es kann im Einzelfall mehr Kritierien geben als nur Standards. Oft sind es sinnvoll, der Herde zu folgen, aber nicht immer. Wenn eine neue Sprache, ob sie was mit Pascal zu tun hat oder nicht, besondere Mechanismen enthält, die ein neues Produkt wesentlich erleichtern, kann auch eine Einschränkung auf diese proprietäre oder exotische Sprache einen Sinn ergeben.
:
Bearbeitet durch User
Dr. Sommer schrieb: > Der Standard würde wohl kaum explizit > vorschreiben, dass Atomics eine Reihenfolge definieren, wenn volatile > Variablen es auch täten. Volatile verhindert das Umordnen der Zugriffe innerhalb eines Threads, verhindert aber nicht, dass sie mit Zugriffe in einem anderen Thread vertauscht werden. Atomics garantieren die Ordnung (und mehr) der Zugriffe in mehreren Threads.
mh schrieb: > Volatile verhindert das Umordnen der Zugriffe innerhalb eines Threads Jein. Das Gemeine ist, daß die nicht-volatile-Zugriffe sehr wohl über die volatile-Zugriffe hinweg umgeordnet werden dürfen.
mh schrieb: > Volatile verhindert das Umordnen der Zugriffe innerhalb eines Threads, > verhindert aber nicht, dass sie mit Zugriffe in einem anderen Thread > vertauscht werden. Sag ich doch. Um die Synchronisierung zwischen mehreren Threads ging es ja die ganze Zeit. Schön dass du mir es jetzt glaubst...
A. K. schrieb: > Ich will hier nicht speziell auf irgendein bestimmten Pascal raus. Oder > auf irgendeine bestimmte Sprache. Sondern auf Entscheidungsprozesse > allgemein. Nur sind die in Bezug auf Sprachen eben doch etwas anders gelagert. Wenn da jeder abseits des Standards frickelt, weil es keinen brauchbaren Standard gibt und geben wird, dann ist das Ergebnis einfach nur Balkanisierung und Vendor-Lockin. Und, wie am Beispiel Pascal zu sehen, die Erosion der ganzen Sprache in die weitgehende Bedeutungslosigkeit. Und das obwohl Pascal sehr wohl Vorzüge hat, mit die es gegen C antreten hätte können - wenn es standardisiert gewesen wäre. Der Grund ist fehlender Wettbewerb, weil es zwischen inkompatiblen Compilern keinen Wettbewerb gibt. Die Nutzer haben nämlich so hohe Opportunitätskosten beim Wechsel, daß er ohnehin kaum machbar ist. Das ist eben anders, wenn alle Wettbewerber denselben Standard implementieren, weil die Entwicklung Standard-getrieben und nicht als Frickelei erfolgt. Dann ist die Frage nämlich nicht, wer coolere proprietäre Features frickelt, die die Nutzer binden, sondern wer den Standard besser implementiert.
Auch in der Frage atomarer Zugriffe kann ich mir vorstellen, dass man Sprachen schaffen kann, in denen es der Compiler selbst herausfinden kann, welche Zugriffe wie abgesichert werden müssen. Oder das Ausmass an Zugriffskonflikten durch andere Programmier-Paradigmata erheblich reduziert wird. Und der Programmierer nicht fast in Assembler-Manier jeden Kleinscheiss explizit modellieren muss, wie in C11. Diese Sprache wird sicherlich nicht annähernd wie C aussehen, auch nicht wie ein bestehendes Pascal. Und es wird Fälle geben, in denen man mit den Freiheiten von C schneller ist als mit eher generischen Lösungen dieser Sprache. Aber umgekehrt könnte diese Sprache das Programmieren mit vielen Threads wesentlich erleichtern. Nicht immer ist das Tempo des Programms der wichtigste Faktor. Oft ist das Tempo des Programmierers wichtiger, oder die Zuverlässigkeit der Lösung. Das fände ich interessanter als eine Neuauflage von der alten Frage, ob man das Ei am dicken oder dünnen Ende aufschlägt, bzw. ob Pascal oder C.
A. K. schrieb: > Und der Programmierer nicht fast in Assembler-Manier > jeden Kleinscheiss explizit modellieren muss, wie in C11. Aber dafür ist C doch gedacht, als portabler Makro-Assembler zur Systemprogrammierung.
Nop schrieb: > Dann ist die Frage nämlich nicht, wer coolere > proprietäre Features frickelt, die die Nutzer binden, sondern wer den > Standard besser implementiert. Schön wärs, wie oft passiert das in der Realität? Wer interessiert sich dafür, wie gut Windows den POSIX-Standard oder den OpenGL-Standard implementiert, wenn Windows das leistungsfähigere DirectX und Games bietet im Gegensatz zu z.B. Linux? Wer fragt danach wie gut der Microsoft C++ Compiler den C++ Standard implementiert (lange Zeit ziemlich schlecht), wenn Visual Studio die benutzerfreundlichste IDE auf der Plattform ist? Sinngemäß sieht man das doch ständig im Forum, wo über Keil, IAR & Konsorten geschwärmt wird, die noch teilweise nicht einmal versuchen aktuelle Sprachstandards zu implementieren, aber soo tolle IDE's bieten. Weiter geht's mit FTDI-IC's die ein proprietäres Protokoll statt USB-CDC nutzen, Office Suites die proprietäre Formate nutzen, die Liste lässt sich endlos fortsetzen. A. K. schrieb: > Auch in der Frage atomarer Zugriffe kann ich mir vorstellen, dass > man > Sprachen schaffen kann, in denen es der Compiler selbst herausfinden > kann, welche Zugriffe wie abgesichert werden müssen. Richtig, gibts schon länger als C, nämlich rein funktionale Sprachen.
Nop schrieb: > Aber dafür ist C doch gedacht, als portabler Makro-Assembler zur > Systemprogrammierung. Aber vielleicht sind zwei falsche Lösungen nicht richtiger als eine. Also wenn man grad nicht dabei ist, ein Betriebssystem zu programmieren.
:
Bearbeitet durch User
Dr. Sommer schrieb: > mh schrieb: >> Ist das so? > Kann man übrigens auch einfach ausprobieren: Das ist x86? Dann ist das nicht sehr aussagekräftig, da x86 ein sehr striktes (mir ist keine besseres Wort eingefallen) Memory Model hat und Writes nur unter speziellen Bedingungen umordnet. Nen Arm mit OoO wäre da interessanter. Nop schrieb: > mh schrieb: > >> Volatile verhindert das Umordnen der Zugriffe innerhalb eines Threads > > Jein. Das Gemeine ist, daß die nicht-volatile-Zugriffe sehr wohl über > die volatile-Zugriffe hinweg umgeordnet werden dürfen. Ich wollte auch nicht das Gegenteil behaupten, mein Beispiel mit foo = f() und flag beruht ja genau darauf. Dr. Sommer schrieb: > Sag ich doch. Um die Synchronisierung zwischen mehreren Threads ging es > ja die ganze Zeit. Schön dass du mir es jetzt glaubst... Ok, vllt. haben wir dann etwas aneinander vorbei geschrieben. Ich bestreite nicht, dass in deinem Beispiel die Ausgabe 2, 0 möglich ist. Das liegt aber nicht daran, dass die Zugriffe von a = 1; b = 2; anders angeordnet werden dürfen (dürfen sie nicht soweit ich weiß, weder Compiler noch CPU), sondern daran, dass ein anderer Thread diese Zugriffe nicht zwingen in der gleichen Reihenfolge sehen muss.
A. K. schrieb: > Aber vielleicht sind zwei falsche Lösungen nicht richtiger als eine. > Also wenn man grad nicht dabei ist, ein Betriebssystem zu programmieren. Naja aber es ist doch relativ sinnfrei, sich darüber zu beklagen, daß C eben vorrangig darin gut ist, wofür es gedacht ist - wenn man eben was anderes will. Genauso ist Pascal als Lehrsprache durchaus gut, weil es Anfänger dazu zwingt, sich von vornherein über Datentypen Gedanken zu machen. Dr. Sommer schrieb: > Schön wärs, wie oft passiert das in der Realität? Ziemlich oft, weswegen C und C++ weiterhin sehr wichtige Sprachen sind. Windows ist keine Sprache und kein Compiler, also andere Baustelle. > Sinngemäß sieht man das doch ständig im Forum, wo > über Keil, IAR & Konsorten geschwärmt wird, die noch teilweise nicht > einmal versuchen aktuelle Sprachstandards zu implementieren Irrelevant, denn sie implementieren überhaupt mal Standards, und deswegen kann man zwischen ihnen wechseln, wenn man will. Es ist nicht so, daß die bestehende Codebasis einen auf einen Hersteller festnageln würde, das ist der Punkt. Es ist doch in der Realität weitgehend egal, wie sexy man einen Compiler findet, um ein neues Projekt zu starten. Der Knackpunkt ist doch, wieviel Aufwand es wäre, die bestehende Codebasis zu migrieren. Schließlich macht man weitaus mehr Bestandspflege als Neustart auf der grünen Wiese. Allein schon die Drohung, daß man seinen Compiler wechseln KÖNNTE, bewirkt Wettbewerb - aber eben auch nur, wenn die Drohung mit einer bestehenden Codebasis realistisch ist.
mh schrieb: > Das ist x86? Ja. mh schrieb: > Nen Arm mit OoO wäre da interessanter. Hab ich grad keinen Compiler für, kannst du ja mal ausprobieren. mh schrieb: > sondern daran, dass ein anderer Thread diese > Zugriffe nicht zwingen in der gleichen Reihenfolge sehen muss. Das ist die abstrakte Sichtweise. Dass ein anderer Thread eine andere Reihenfolge beobachtet, kann (muss aber nicht) daran liegen, dass die tatsächlichen schreibenden Speicherzugriffe in anderer Reihenfolge passieren (z.B. die Reihenfolge in der Cache-Pages rausgeschrieben werden). Oder es liegt daran, dass der CPU des beobachtenden Threads die Pages in anderer Reihenfolge liest.
Nop schrieb: > Irrelevant, denn sie implementieren überhaupt mal Standards, und > deswegen kann man zwischen ihnen wechseln, wenn man will. Es ist nicht > so, daß die bestehende Codebasis einen auf einen Hersteller festnageln > würde, das ist der Punkt. Tja, kompilier bspw. mal den LPC USB Stack mit dem GCC und freu dich über zufällige Hardfaults, weil der GCC undefiniertes Verhalten anders umsetzt als z.B. der Keil, mit welchem das wohl entwickelt wurde... ST versucht wenigstens, den GCC auch zu unterstützen. Nop schrieb: > aber eben auch nur, wenn die Drohung mit einer > bestehenden Codebasis realistisch ist. Genau, daher weichen schlaue Compilerhersteller auf subtile Art vom Standard ab, sodass man eben nicht mehr so leicht abhauen kann. Das ist doch Microsofts alte und bewährte Strategie... Ich bin zwar auch sehr für einheitliche Standards, aber die Realität ist dann doch nicht ganz so rosig. Am Ende gewinnt doch der mit dem besseren Marketing...
A. K. schrieb: > Auch in der Frage atomarer Zugriffe kann ich mir vorstellen, dass man > Sprachen schaffen kann, in denen es der Compiler selbst herausfinden > kann, welche Zugriffe wie abgesichert werden müssen. Oder das Ausmass an > Zugriffskonflikten durch andere Programmier-Paradigmata erheblich > reduziert wird. Und der Programmierer nicht fast in Assembler-Manier > jeden Kleinscheiss explizit modellieren muss, wie in C11. > > Diese Sprache wird sicherlich nicht annähernd wie C aussehen, auch nicht > wie ein bestehendes Pascal. Und es wird Fälle geben, in denen man mit > den Freiheiten von C schneller ist als mit eher generischen Lösungen > dieser Sprache. Aber umgekehrt könnte diese Sprache das Programmieren > mit vielen Threads wesentlich erleichtern. Nicht immer ist das Tempo des > Programms der wichtigste Faktor. Oft ist das Tempo des Programmierers > wichtiger, oder die Zuverlässigkeit der Lösung. > > Das fände ich interessanter als eine Neuauflage von der alten Frage, ob > man das Ei am dicken oder dünnen Ende aufschlägt, bzw. ob Pascal oder C. Die Sprache von der du redest heisst GO! Diese wurde mit den Bedürfnissen von Multithreading (in relativ großem Stil) im Fokus entwickelt.
Dr. Sommer schrieb: > weil der GCC undefiniertes Verhalten anders umsetzt Undefiniertes Verhalten (gemäß Standard) ist exakt das. Wer sich auf ein bestimmtes undefiniertes Verhalten verläßt, dem ist eh nicht mehr zu helfen.
Nop schrieb: > Wer sich auf ein bestimmtes undefiniertes Verhalten verläßt, dem ist eh > nicht mehr zu helfen. Jo. Sag das NXP. Auch im ST Code grassieren Dinge wie verbotene Bezeichner. Hier im Forum werden oft kategorisch die korrekten Lösungen abgelehnt und stattdessen undefinierte Frickelei bevorzugt, wie bspw. Pointer umcasten und unions zum Daten konvertieren zu nutzen, um sich dann über unerwartetes Verhalten zu wundern.
Dr. Sommer schrieb: > IAR & Konsorten geschwärmt wird, die noch teilweise nicht einmal > versuchen aktuelle Sprachstandards zu implementieren Kennst du IAR wirklich? Meiner Meinung nach tust du ihnen damit grob unrecht. Die hatten bspw. eine C99-Standard-Bibliothek, als man im GCC-Umfeld davon nur träumen konnte. Deren IDE habe ich nicht benutzt, aber der Compiler ist wirklich gut. Eine einzige Sache habe ich in Erinnerung, bei der sie ziemlich dünn sind: inline asm constraining. Das macht inline asm praktisch nutzlos, denn das Einzige, auf was man sich darin verlassen kann, sind globale Variable (aber dann könnte ich auch gleich die komplette Funktion in Assembler schreiben). Das inline asm constraining des GCC versteht man zwar wohl nur dann völlig, wenn man den Compiler versteht :), aber es gibt einem System(bibliotheks)programmierer ein mächtiges Werkzeug, welches man gerade im Embedded-Bereich gut benötigen kann.
Jörg W. schrieb: > Das inline asm constraining des GCC versteht > man zwar wohl nur dann völlig, wenn man den Compiler versteht :), aber > es gibt einem System(bibliotheks)programmierer ein mächtiges Werkzeug, > welches man gerade im Embedded-Bereich gut benötigen kann. Das Inline-ASM vom GCC ist enorm mächtig, gerade weil es sich nicht nur dazu eignet, ASM Funktionen zu schreiben, sondern sich recht weitgehend in die Optimierung des Compilers integriert und man oft nur sehr wenig ASM braucht, da der Compiler den Rest von sich aus erledigt. Aber wie viele mächtigen Werkzeuge eignet es sich auch vorzüglich dazu, sich in den Fuss zu schiessen.
:
Bearbeitet durch User
A. K. schrieb: > Aber wie viele mächtigen Werkzeuge eignet es sich auch vorzüglich dazu, > sich in den Fuss zu schiessen. Uneingeschränkte Zustimmung. :) Ist mir aber trotzdem viel lieber als das impotente inline asm des IAR. Da schreiben die Leute nämlich dann inline asm statements, die sich auf implizite Annahmen (wie lokale Variablen in Registern) verlassen, die sie per trial&error ermittelt haben und die bereits in der nächsten Compilerversion hinfällig sein können. Da weiß man dann gar nicht mehr, warum der Fuß plötzlich weh tut. :-))
Dr. Sommer schrieb: > Jo. Sag das NXP. Auch im ST Code grassieren Dinge wie verbotene > Bezeichner. Daß Software von Hardwarefirmen nicht unbedingt der Hit ist, kann ja nun keinen verwundern. > Pointer umcasten und unions zum Daten konvertieren zu nutzen Type punning über unions ist seit C99 einer der beiden korrekten Wege, das zu tun. Pointercasting ist abgesehen von wenigen Ausnahmen (char * darf alles aliasen) undefiniertes Verhalten. Da, wo es im Code nicht zu vermeiden ist, muß man striktes Aliasing im Build abschalten. Du nutzt direkt oder indirekt übrigens jeden Tag Code, bei dem das so ist - alles, was mit Linux gebaut wurde nämlich.
Nop schrieb: > Type punning über unions ist seit C99 einer der beiden korrekten Wege, > das zu tun. Der ist zwar erlaubt, aber das Ergebnis ist dennoch undefiniert (hängt bspw. von der Byte-Reihenfolge der Plattform ab). Und in C++ ists immer noch verboten. Nop schrieb: > Daß Software von Hardwarefirmen nicht unbedingt der Hit ist, kann ja nun > keinen verwundern. Dass sich Weltkonzerne wie ST keine kompetenten Informatiker leisten können wundert mich doch etwas. Nop schrieb: > Da, wo es im Code nicht zu vermeiden > ist, muß man striktes Aliasing im Build abschalten. An welchen Stellen ist es denn wirklich unvermeidbar? Mir fällt keine ein außer Register-Zugriffen, und das fällt glaube ich nicht unter Strict Aliasing... Nop schrieb: > Du nutzt direkt oder > indirekt übrigens jeden Tag Code, bei dem das so ist - alles, was mit > Linux gebaut wurde nämlich. Die Code-Qualität des Linux Kernels ist ohnehin... kaum in Worte zu fassen? Jörg W. schrieb: > Kennst du IAR wirklich? Ok, mit IAR war nur einfach ein proprietärer geraten. Hier bspw. http://en.cppreference.com/w/cpp/compiler_support sieht man bei den proprietären ganz viel rot...
Dr. Sommer schrieb: > Und in C++ ists immer > noch verboten. Das stimmt so nicht allgemein. Aus dem c++17 draft (N4687 §12.2.24)
1 | In a standard-layout union with an active member (12.3) of struct type T1, |
2 | it is permitted to read a non-static data member m of another union member of |
3 | struct type T2 provided m is part of the common initial sequence of T1 and T2; |
4 | the behavior is as if the corresponding member of T1 were nominated. |
5 | [ Example: |
6 | struct T1 { int a, b; }; |
7 | struct T2 { int c; double d; }; |
8 | union U { T1 t1; T2 t2; }; |
9 | int f() { |
10 | U u = { { 1, 2 } }; // active member is t1 |
11 | return u.t2.c; // OK, as if u.t1.a were nominated |
12 | } |
13 | — end example ] |
mh schrieb: > Das stimmt so nicht allgemein. Toll, man kann Variablen gleichen Typs auslesen. Kann man ja super zum Daten konvertieren nutzen!
Dr. Sommer schrieb: > Jörg W. schrieb: >> Kennst du IAR wirklich? > Ok, mit IAR war nur einfach ein proprietärer geraten. Hier bspw. > http://en.cppreference.com/w/cpp/compiler_support sieht man bei den > proprietären ganz viel rot... Da ist IAR nicht dabei. Allerdings kann ich zu neueren C++-Standards da auch nicht mehr viel sagen; ist zu lange her, dass ich ihn mal in den Fingern hatte.
Dr. Sommer schrieb: > Der ist zwar erlaubt, aber das Ergebnis ist dennoch undefiniert Nein, ist es nicht. > (hängt bspw. von der Byte-Reihenfolge der Plattform ab). Das ist implementation defined, nicht undefined. Undefined hieße beispielsweise, daß der Compiler das komplett wegoptimieren könnte - inklusive dem ganzen Rest des Programms. Ich hab schon type punning benutzt, wenn ich structs hatte, die aus 4 Bytes bestanden, die man aber mit einer Union auf uint32_t alle zusammen nicht nur nullen kann, sondern auch kopieren und vergleichen. Wo innerhalb des uint32_t welches Byte landet, ist dafür egal. > Und in C++ ists immer noch verboten. Das schon. > Dass sich Weltkonzerne wie ST keine kompetenten Informatiker leisten > können wundert mich doch etwas. Dürfte mit der Firmenkultur zu tun haben. Wenn man sich als Hardwarefirma versteht, dann gilt Software eher so als Dreingabe. Daß man wesentlich mehr Hardware verkaufen kann, wenn man sie den potentiellen Kunden mundgerecht vorlegt, ist eine Erkenntnis, die den Firmen immer noch neu ist. > An welchen Stellen ist es denn wirklich unvermeidbar? Mir fällt keine > ein außer Register-Zugriffen, und das fällt glaube ich nicht unter > Strict Aliasing... Beispielsweise, wenn man in C etwas memcpy-artiges programmieren will, was schneller als byteweises Kopieren geht. Bei Pascal ist es eine der Kritiken, daß zwar Funktionen mit variabler Argumentzahl vorkommen, man selber aber keine definieren kann. Dieselbe Kritik muß sich dann C an dieser Stelle auch gefallen lassen. > Die Code-Qualität des Linux Kernels ist ohnehin... kaum in Worte zu > fassen? Der Linuxkernel ist einfach nur sehr systemnah. Mal so vermutet, wo ich das plausibel fände: Wenn man beispielsweise einen Datenblob von einem Treiber bekommt, den man interpretieren oder auch modifizieren will, dann möchte man kein memcpy machen. Dann würde die Sache nämlich drastisch langsamer, falls der Compiler gerade mal nicht fähig ist, das memcpy wegzupotimieren. Etwa im Beispiel des Netzwerkstacks hängt ja das Format bestimmter Pakete überhaupt erst von einem Paket-Identifier ab. Da ein struct drüberzucasten und ggf. die relevanten Felder endianess-mäßig mit den host/network-Macros zu behandeln, ist da wohl der Weg der Wahl.
Nop schrieb: > Dr. Sommer schrieb: > >> Der ist zwar erlaubt, aber das Ergebnis ist dennoch undefiniert > > Nein, ist es nicht. > >> (hängt bspw. von der Byte-Reihenfolge der Plattform ab). > > Das ist implementation defined, nicht undefined. Undefined hieße > beispielsweise, daß der Compiler das komplett wegoptimieren könnte - > inklusive dem ganzen Rest des Programms. > > Ich hab schon type punning benutzt, wenn ich structs hatte, die aus 4 > Bytes bestanden, die man aber mit einer Union auf uint32_t alle zusammen > nicht nur nullen kann, sondern auch kopieren und vergleichen. Wo > innerhalb des uint32_t welches Byte landet, ist dafür egal. Das UB entsteht durch das Lesen des nicht-aktiven members der union. Das IB entsteht durch die endianness. Beides lässt sich aber lösen.
:
Bearbeitet durch User
Nop schrieb: > Das ist implementation defined, nicht undefined. Achja, richtig. Was ich eigentlich sagen wollte ist, dass man sich hier oft gewundert wird, warum so etwas nicht immer tut was man will:
1 | void test (void) { |
2 | uint32_t a = 0xAABBCCDD; |
3 | char b = ((char*) a) [2]; |
4 | assert (b == 0xBB); |
5 | }
|
Der cast nach "char*" und Dereferenzierung ist ja sogar erlaubt, aber das Ergebnis ist dennoch nicht was man haben wollte, weil keiner sich die Mühe macht dem Standard zu folgen. Nop schrieb: > Beispielsweise, wenn man in C etwas memcpy-artiges programmieren will, > was schneller als byteweises Kopieren geht. memcpy sollte bei guten Compilern auch nicht Byteweise, sondern i.A. effizient sein. Das ist dann aber Teil der Plattform (Compiler+C Library) und kann in der Tat nicht korrekt in C implementiert werden (außer man schaltet Strict Aliasing ab, was ja dann nicht Standard-Konform ist). Nop schrieb: > Dieselbe > Kritik muß sich dann C an dieser Stelle auch gefallen lassen. C++ kann's!
Nop schrieb: > Dann würde die Sache nämlich drastisch langsamer, falls > der Compiler gerade mal nicht fähig ist, das memcpy wegzupotimieren. Dafür muss man dann aber das strict Aliasing abschalten, was wiederum eine Menge Optimierungen verhindert. Man könnte in solchen Fällen auch korrekt mit Bit-Operationen arbeiten, aber das ist, insb. in C, viel Tipparbeit.
Wilhelm M. schrieb: > Das UB entsteht durch das Lesen des nicht-aktiven members der union. In C99 nicht. Natürlich geht das nur, wenn wir hier von gleichen Größen reden. Etwa einen 4-Byte-float schreiben und einen drüberliegenden uint32_t lesen geht. Aber wenn man einen uint8_t schreibt und dann den uint32_t liest, steht logischerweise nicht fest, was denn in den anderen drei Bytes des uint32_t ist. Dr. Sommer schrieb: > uint32_t a = 0xAABBCCDD; > char b = ((char*) a) [2]; Meintest Du "&a"? > das Ergebnis ist dennoch nicht was man haben wollte Kommt drauf an, vielleicht wollte man ja einen Endianess-Test schreiben.
Nop schrieb: > Meintest Du "&a"? Äh ja, natürlich. Nop schrieb: > Kommt drauf an, vielleicht wollte man ja einen Endianess-Test schreiben. ... den man in korrektem C grundsätzlich nicht braucht, denn wenn man Daten-Konvertierungen nur über Bitoperationen durchführt, wird das vom Compiler automatisch korrekt gemacht! Aber wenn man schon bei Nicht-Standard-Code ist, kann man auch _BYTE_ORDER_ o.ä. nutzen...
Nop schrieb: > Wilhelm M. schrieb: > >> Das UB entsteht durch das Lesen des nicht-aktiven members der union. > > In C99 nicht. Natürlich geht das nur, wenn wir hier von gleichen Größen > reden. Etwa einen 4-Byte-float schreiben und einen drüberliegenden > uint32_t lesen geht. Es bezog sich ja auf C++. Ab C99 ist das explizit erlaubt. In C++ (schon immer) explizit verboten wegen UB (Ctor/dtor-Prolematik).
:
Bearbeitet durch User
Dr. Sommer schrieb: > Nop schrieb: >> Meintest Du "&a"? > Äh ja, natürlich. > > Nop schrieb: >> Kommt drauf an, vielleicht wollte man ja einen Endianess-Test schreiben. > ... den man in korrektem C grundsätzlich nicht braucht, denn wenn man > Daten-Konvertierungen nur über Bitoperationen durchführt, wird das vom > Compiler automatisch korrekt gemacht! Aber wenn man schon bei > Nicht-Standard-Code ist, kann man auch _BYTE_ORDER_ o.ä. nutzen... Oder std::endian
Dr. Sommer schrieb: > Dafür muss man dann aber das strict Aliasing abschalten, was wiederum > eine Menge Optimierungen verhindert. Ja sicher, genau das tut man beim Build des Kernels ja auch. Jedenfalls seit strict aliasing auf einmal Default des GCC wurde, ich glaube bei 4.9 oder so. Ich entsinne mich, daß Torvalds sich über diese Default-Änderung ziemlich aufgeregt hat. Andererseits muß man auch konkret nachmessen, ob strict aliasing überhaupt Vorteile bringt. Bei dem Code, den ich bisher hatte, war da gar nichts meßbar. Deswegen schalte ich es jedenfalls zum Release einfach ab. Selbst in Benchmarks geht's da um kaum mehr als 1-2% oder so (IIRC). Selbst bei heftig numerischem Code bringt es wenig, weil das Aliasing kompatibler Datentypen (z.B. die ganzen doubles in Matrizen und Vektoren) immer noch da ist, und das kriegt man dann mit "restrict" in den Griff - welches aber auch bei abgeschaltetem strict aliasing geht.
Dr. Sommer schrieb: >> Kommt drauf an, vielleicht wollte man ja einen Endianess-Test schreiben. > ... den man in korrektem C grundsätzlich nicht braucht Datentausch mit anderen Systemen? > Daten-Konvertierungen nur über Bitoperationen durchführt Um das zu machen, muß man aber vorher schon die eigene Endianess wissen?
Nop schrieb: > Datentausch mit anderen Systemen? Nop schrieb: > Um das zu machen, muß man aber vorher schon die eigene Endianess wissen? Eben nicht, das ist ja der Witz. Angenommen, wir wollen einen Little Endian 4-Byte vorzeichenlosen Integer aus einer Datei einlesen:
1 | uint32_t convert (FILE* f) { |
2 | unsigned char data [4]; |
3 | if (fread (data, 1, 4, f) != 4) return 0; |
4 | return ((uint32_t) data[0]) |
5 | | (((uint32_t) data[1]) << 8) |
6 | | (((uint32_t) data[2]) << 16) |
7 | | (((uint32_t) data[3]) << 24); |
8 | }
|
Dann wird hier der Integer in der Reihenfolge der Host-Plattform zurückgegeben - automatisch korrekt BE/LE/Whatever. Für diesen Code muss man die eigene Reihenfolge überhaupt nicht wissen. Der Compiler weiß schon, ob "<<" im Speicher nach "oben" oder "unten" shiftet (d.h. ob höherwertige Bits "oben" oder "unten" gespeichert werden). Dieser Code wird von Compilern natürlich auch optimiert, also wenn kein Byte-Tauschen nötig ist weil die Reihenfolge passt, wird da auch nix gemacht. Und das alles ohne undefiniertes/implementation defined Behaviour oder Abschalten von Strict Aliasing usw.
Dr. Sommer schrieb: > Dann wird hier der Integer in der Reihenfolge der Host-Plattform > zurückgegeben - automatisch korrekt BE/LE/Whatever. Ooops. Mir fällt gerade auf, daß ich das EXAKT so auch schon implementiert habe. Bei der Ausgabe auf der anderen Seite dementsprechend auch, so daß das Format der gespeicherten Daten auch da nicht von der Endianess der speichernden Partei abhing. :-) > Und das alles ohne undefiniertes/implementation defined > Behaviour oder Abschalten von Strict Aliasing usw. Wird halt nochmal anders, wenn Du IP-Pakete hast, die je nach Format-Byte im Header einen ganz unterschiedlichen folgenden Aufbau haben können. Daß man da mit Pointercasting arbeitet, kann ich nachvollziehen. Ansonsten (also mit memcpy) würde man riskieren, daß bei sonstigen Code-Änderungen oder Compiler-Updates als Seiteneffekt das Wegoptimieren nicht mehr klappt. Was entsprechend ätzend zu debuggen wäre.
Nop schrieb: > Wird halt nochmal anders, wenn Du IP-Pakete hast, die je nach > Format-Byte im Header einen ganz unterschiedlichen folgenden Aufbau > haben können. Hm, warum? Man baut ein paar Fallunterscheidungen ein - je nach Format-Byte konvertiert man den Payload halt anders und speichert das Ergebnis in ein jeweils anderes struct. Die kann man sogar per union "übereinander" speichern um Speicher zu sparen (nicht zum Konvertieren!). Nop schrieb: > Daß man da mit Pointercasting arbeitet, kann ich > nachvollziehen. Der einzige wirkliche Grund dafür ist, dass Konvertieren über Bitshifts viel Tipparbeit ist. Nop schrieb: > Ansonsten (also mit memcpy) würde man riskieren, daß bei > sonstigen Code-Änderungen oder Compiler-Updates als Seiteneffekt das > Wegoptimieren nicht mehr klappt. Was entsprechend ätzend zu debuggen > wäre. Aber memcpy ist doch eh nicht zum konvertieren geeignet (Byte-Reihenfolge usw.). Und ich debugge lieber ein Performance-Problem als kurioses Fehlverhalten bei Compiler-Update...
Dr. Sommer schrieb: > Format-Byte konvertiert man den Payload halt anders und speichert das > Ergebnis in ein jeweils anderes struct. Eben letzteres wäre Kopieren, und das will man ja vermeiden. > Und ich debugge lieber ein Performance-Problem > als kurioses Fehlverhalten bei Compiler-Update... Wenn man strict-aliasing abschaltet, hat man bei einem Compiler-Update kein Fehlverhalten. Nur als das per Default eingeführt wurde, wird man das sicherlich gehabt haben - wenn man dann auch noch die Releasenotes nicht gelesen hat.
Nop schrieb: > Eben letzteres wäre Kopieren, und das will man ja vermeiden. Ich verstehe dein Problem nicht. Ob man jetzt per Fallunterscheidung auf unterschiedliche Member einer union die sich in einem umgecasteten struct befindet zugreift, oder per Fallunterscheidung die Bytes unterschiedlich konvertiert, macht jetzt keinen großen Unterschied. Nop schrieb: > Wenn man strict-aliasing abschaltet, hat man bei einem Compiler-Update > kein Fehlverhalten. Es sei denn das Verhalten des Compilers ändert sich nochmal irgendwie, worauf man sich ja nicht verlassen kann, weil Code ohne strict aliasing vom Standard nicht abgedeckt ist.
schön, das solche C Konversationen grundsätzlich kontrovers sind..der Themenstarter ist dadurch nicht ein Stück weiter.... Also Pascal Python Java welche Alternativen gibt es noch? Der Quatsch mit den Standard von Pascal kann man sich auch sparen.+Der Standard ist Delphi/Freepascal Und ja, es gibt kleinste Unterschiede zu Mikroe oder AVRco Pascal, genauso wie es bei C verschiedende Varianten gibt als auch bei Python..als spart man sich den Zirkus an Diskussion und sollte vielleicht mal wieder zum Thema Zurück Jemand der in Cöfter arbeitet hat mit den kleinen Unterschieden der Versionen genauso wenig Probleme wie jemand der in PAscal oder Python schreibt. Schlussendlich Programmiert man ja nur mit z.B: Freepascal und Mikroe Pascal. Das ist dann kein Drama..genauso wie andere in C mit gcc und VC arbeiten und da auch mit Unterschiefen leben müssen. Schlussendlich kommt man mit allen Sprachen ans Ziel, weshalb solceh Diskussionen müßig sind
Tina schrieb: > Schlussendlich kommt man mit allen Sprachen ans Ziel, weshalb solceh > Diskussionen müßig sind Na dann ist ja gut, wenn die Sprachauswahl derart irrelevant ist. Komisch, dass es trotzdem so viele verschiedene gibt.
A. K. schrieb: > Ich bin konkret weder mit > Delphi noch sonst einem halbwegs aktuellen Pascal näher vertraut Ja, das merkt man deutlich. Ich will da aber nicht weiter drauf herumreiten, weil sonst alle, die nur C und sonst nix kennen, mir "Missionieren" vorwerfen. Vorsorglich verweise ich dazu auf Adenauer. Ansonsten scheinen wir beim Thema "StLib des Grauens" und einschlägiger anderer Hersteller-Libs und -IDe's etc. ähnlicher nsicht zu sein. Meine kennst du ja: Texteditor, Totalcommander als IDE, Batchdatei als Make all" und die eigentliche Toolchain, bei ARM eben Keil. Hab mich einmal bei der Lernbetty mit dem Gcc herumgeärgert, geht zwar, aber wenn ich nicht muß, nehme ich den Gcc auch nicht. W.S.
Markus F. schrieb: > Tina schrieb: >> Jemand der in Cöfter arbeitet > > wo genau liegt denn das? Direkt neben Unterschiefen.
owe....und genau an diesem Punkt merkt man was für Leute hier ihre Argumente vortragen..viel Spaß noch.... Nur Kindergarten hier..er hat kaka gesagt...lol
Markus F. schrieb: > wie wär's mit Ada? > > https://www.adacore.com/download in gnat-gpl-2017-arm-elf-linux-bin/share/examples/gnat-cross/led_flasher-st m32f4 ist ein Beispiel:
1 | text data bss dec hex filename |
2 | 56860 3652 30504 91016 16388 obj/led_flasher |
Ich glaub das ist ein neure Weltrekord! led_flasher läßt 2 LEDs blinken und fragt einen Taster ab. Mit nur 60 kByte Flash und 34 kByte SRAM eine super Leistung ;->
Small Is Beautiful schrieb: > Mit nur 60 kByte Flash und 34 kByte SRAM eine super Leistung ;-> wenn Du schlanke Programme haben willst, musst Du mit dem zfp Profil compilieren ...
W.S. schrieb: > Ich will da aber nicht weiter drauf herumreiten, Schade. Denn von ihm werde ich sicherlich keine Antwort darauf erhalten: A. K. schrieb: > weshalb ich deren Konzepte zur Kennzeichnung oder Vermeidung > nebenläufigen Zugriffs nicht kenne. Genau die würden mich ja > interessieren.
:
Bearbeitet durch User
Markus F. schrieb: > wenn Du schlanke Programme haben willst, musst Du mit dem zfp Profil > compilieren ... Wenn ich "zfp-stm32f4" verwende, bekomm ich: "Ada.Interrupts" is not a predefined library unit" Also entweder schlanke Programme oder Interrupts?
W.S. schrieb: > Hab mich einmal bei der Lernbetty mit dem Gcc herumgeärgert Abgesehen davon, daß die Syntax des Inline-Assemblers eine Frage der Gewohnheit ist, und daß das Aufsetzen des Linkerfiles nicht ganz trivial ist, was für Probleme gab es da?
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.