Na klar, die LED, die z.B. durch langsames Blinken diverese Codes dem DAU übermittelt, kann als schneller Debug output Port mitgenutzt werden, wenn man ein scope dransetzt.
Na klar, die LED, die z.B. durch langsames Blinken diverese Codes dem DAU übermittelt, kann als schneller Debug output Port mitgenutzt werden, wenn man ein scope dransetzt.
Bei der Fülle an tollen Boards würde ich da nicht selber an SMD-Teilen mehr rumlöten, so hoch ist meine Motivation nicht. Besonders nett finde ich die Teensy-Boards: Arduino-kompatibel (ist für mich wichtig, die Arduino-Plattform hat so einen reichen Schatz an Libraries für quasi alles, in dem Ökosystem gibtes fast nix was nicht schon vorher jemand gemacht hat), relativ billig (15-25 Euro), gut supportet (der Entwickler Paul Stoffregen antwortet oft persönlich im Forum), in einem mechanisch praktischen Formfaktor (paßt in DIL-Sockel), und neuerdings auch rohe Power bis 600MHz.
Aber auch die Cortex M4 aus den kleineren Modellen sind deutlich komplexer als die 8-Bit-Atmels. Wenn man erst einsteigt in die Materie, ist das nicht so ohne.
Leider sind viele der im embedded-Bereich verwendeten Kalenderfunktionen und Zeitfunktionen stark simplifiziert: Schaltsekunden werden ignoriert, Sommerzeit-Wechsel nach irgendeinem starren Schema, etc.
Vor allem die fehlende Behandlung der Schaltsekunden tut mir weh. Wenn ich schon eine Atomuhr bastle, dann soll sie das hinkriegen (z.B. indem man die Ankündigung der Schaltsekunden aus DCF77 einliest oder mit einer Taste aktiviert, daß am nächsten Quartalsende eine eingefügt wird.
Allerdings werde ich viele viele andere Convenience-Libraries nutzen, die es fertig gibt: Ansteuern von billigen Chinesen-Displays mit dem TM1637-Treiberchip, parsen der NMEA-Sentences vom GPS an der seriellen Schnittstelle, etc.
Naja, in der Arduino-Umgebung ist das gut gekapselt, auch wenn dem ganzen der gcc zugrundeliegt. Bei bisherigen Projekten hab ich überhaupt noch nie so tief runtersteigen müssen, daß ich das Datenblatt des Controllers gelesen hätte. Bei den Countern muß das aber sein, dafür hat Arduino keine sinnvolle Abstraktion.
/ralph
Am 13.08.2019 um 18:52 schrieb Johannes Bauer:
Das geht seit ca. 5 Jahren auch einfacher:
Am 13.08.2019 um 19:54 schrieb Wolfgang Allinger:
Genau so ist das richtig gemacht.
Hmm, auf welchen Controllern soll das unsauberer oder langsamer sein?
DoDi
Am 14.08.2019 um 09:53 schrieb Joerg Niggemeyer:
Wenn schon Debuggen dann gleich richtig mit einem Logik-Analysator. Ist weit billiger als ein Scope und erlaubt bessere Diagnosen.
DoDi
Du vergleichst aber halt auch Äpfel mit Birnen. Das ist wie wenn du das Handbuch von ner Cessna 172 gelesen und verstanden hast und dich dann wunderst, dass das einer Boeing 737 deutlich dicker und komplizierter ist.
Die nächste Stufe vom AVR ist ein M0, M0+ oder vielleicht ein kleiner (!) M3 ohne viel Peripherie. Die M4s kommen dann schon deutlich dicker daher und die M7s sind eine GANZ andere Klasse.
Vermutlich ist das nicht gekapselt, sondern auch deine globalen const-Arrays liegen einfach im RAM. Das geht deshalb, weil der Mega2560 vergleichsweise viel RAM hat, ganz okay. Ist aber trotzdem eine Travestie.
Gruß, JOhannes
Naja, ob ich da jetzt PROGMEM stehen habe oder __flash ist ja Jacke wie Hose. Tatsache ist, dass du immernoch wissen musst, wo das Objekt liegt, damit die Zugriffe richtig generiert werden. Also beispielsweise:
int getx(const int *addr) { return *addr; }
erzeugt im Assembly:
a6: fc 01 movw r30, r24 a8: 80 81 ld r24, Z aa: 91 81 ldd r25, Z+1 ; 0x01
während
int getx(const int __flash *addr) { return *addr; }
a6: fc 01 movw r30, r24 a8: 85 91 lpm r24, Z+ aa: 95 91 lpm r25, Z+
erzeugt. So und jetzt nutzen wir die:
extern const int __flash x;
int main() { const int foo = 0; getx(&x); getx(&foo); }
Das gibt nicht mal eine WARNUNG (-Wall, avr-gcc 5.4.0) dass getx(&foo) eben totale Grütze macht, weil das Symbol woanders liegt. Und immernoch brauchst du also int getx_P() mit __flash und getx() ohne __flash. Das ist unendlich ätzend.
Gruß, Johannes
Das hat sogar *ausschließlich* mit der Architektur zu tun.
Du hast im AVR eine Pointergröße von 16 Bit, aber teilweise mehr als 64 kiB kombinierten Flash/SRAM. Das heißt, der Pointer kann notwendigerweise eben nicht die Information tragen, in welchen Bereich der jetzt zeigt.
Klar könnte ein Compiler das einfach emulieren und 24 oder 32-Bit Pointer machen oder so ein gemurkse. Dann wird halt *jede* Indirektion im Programm unendlich lahm. Und klar, in einfachen Fällen (also wenn der Compiler garantiert entscheiden kann, welcher Bereich addressiert ist) geht das natürlich auch. Aber *Allgemein* lässt es sich nicht lösen, ohne dass der Programmierer "hints" geben muss, was gemeint ist.
Teilweise brauchst du sogar, für die großen Devices, perverse Workarounds um das Laden von Programmspeicher überhalb der 16-Bit Grenze zu ermöglichen. Stichwort pgm_read_byte_far(). Das heißt, ich muss als Programmierer zur Compilezeit (!) wissen, wo mir mein Linker (!!) später ein Objekt hinlegt, damit ich unterscheiden kann, welche Funktion die geeignete ist. Oder natürlich die lahme _far() Variante immer nehmen. Das sind so viele Layer von Murks aufeinandergestapelt dass mir davon echt übel wird.
Und das zieht sich dann durch alle Layer durch und erzeugt eine elendige Kopplung von Code zu Datenstrukturen. Genau die Kopplung, die man bei modernen Prozessoren halt nicht mehr braucht, weswegen man eben auch viel schöneren und portableren Code schreiben kann.
Gruß, Johannes
Es ging darum, dass man Berechnungen, die vielleicht einmal am Tag notwendig sind, nicht jede Sekunde durchführen muss. Kann man wohl machen, da es die Rechenleistung vielleicht hergibt, ist aber IMHO schlechter Stil.
Über ein globales Flag einen Status zu übermitteln, ist eine Technik, die man anwenden kann, um entsprechend in einer anderen Wiederholschleife, die nicht in sync zu einem Timer stehen muss und auch unterbrochen werden kann z.B. in der main loop, dann Aktionen durchzuführen.Das Flag, ob eine Berechnung notwendig ist oder nicht , muss oder kann nicht unbedingt über den Timer Wert auslesbar sein. Insbesondere, wenn eine Berechnung nur sehr selten vorkommt.
Das Flag bietet zudem den Vorteil, eine Berechnung auch aus einem anderen Event zu triggern, z.B. die Uhr wurde gestellt oder User command.
Aktionen in dem T-IR nach Bedarf durchführen, falls häufige Reaktionen oder Berechnungen periodisch schnell dazu nötig sind.
Das Polling des Bits gibt die gewünschte Aktualisierungsrate vor. Im übrigen würde es in diesem Falle zu keinem "langem" Fehler führen, sondern lediglich zu einer langsamen Reaktion, die eine einstellbare Eigenschaft ist, falls man einem IR (1s) zu spät das Datum/Wochentag berechnen würde. Und das ist für mich auch ein wichtiges Kriterium, ob eine Funktion in einem IR laufen muss also zeitlich zu einem event kritisch ist oder nicht.
Verschlabbern von kritischen IRs, wie bei der Programmierung von DCDC, wenns denn mal etwas schneller gehen soll, ist schlecht, dann machts Puff..... Alt Neu Variablenvergleich, um z.B. eine Wertveränderung abzuprüfen, oder Fehler zu detektieren ist zweckmässig. Auch das Anhalten per Debugger im ungünstigen Moment kann zum Himmeln der HW führen. So etwas führt dann zu einer steilen Lernkurve oder man gibt frustiert auf ;-)
Am 14.08.2019 um 11:01 schrieb Johannes Bauer:
Tja, einen Tod muß man sterben. Entweder greift man auf Konstanten im ROM (flash...) zu, oder kopiert sie von dort beim Reset ins RAM.
Wobei ich nicht so recht verstehe, warum die Hardware Unterschiede zwischen Flash und RAM lesen macht. Beim EEPROM ist das noch verständlich, wenn dort die Zugriffe weit langsamer sind, aber beim schnellen Flash???
DoDi
Dann mußt Du aber mehrere Bits ausgeben und per LA abfragen.
Josef
Am 14.08.2019 um 11:10 schrieb Johannes Bauer:
Aus genau diesem Grund habe ich seinerzeit die Benutzung der 8086 Architektur (mit Segmentierung) nicht verstanden. Bis ich dann das (MS?) Modell mit SEGMENT und GROUP verstanden habe. Das hielt dann bis zum
486, ab dem die Segmentierung wegen zu schlechter Performance durch Paging und flachen Adressraum ersetzt wurde, mit freiwilliger Beschränkung auf 4GB.Entsprechend sollte man halt in µC nicht mehr Speicher einbauen als die Pointerregister verkraften, bzw. bei Mehrbedarf auf einen größeren (32... Bit) Kern umsteigen. Für den Entwickler ist es dann schön, wenn er seinen alten Arduino Code erst einmal auf dem neuen Controller weiterlaufen lassen kann.
DoDi
Es geht nicht um den Unterschied in der Geschwindigkeit sondern um die Tatsache, daß die Adresse X sowohl im RAM (LD/ST) als auch um Flash (LPM) liegen kann!
Josef
Achso ja ... wollte noch sagen: PIC24 kann einen Teil seines Flash in den RAM-Adressraum mappen. Was aber nicht wirklich hilft, weil Befehle
24 Bit lang sind und jeder 24-Bit lange Befehl ein zusätzliches "Phantom" Byte hat, welches immer 0 ist.
WIMRE hatte der Z80&Co kein JBC War damals(tm) eine Besonderheit im 8051, die vieles einfacher und besser machte. AFAIR ging das sogar mit PortBits. Leider gabs kein Bit_toggle. Und beim Port update gabs auch irgendwas als Falle für IR. HIV, Han Ich Verjässe.
JBC ist als atomarer Befehl nicht unterbrechbar. WOWEREIT.
Saludos (an alle Vernünftigen, Rest sh. sig) Wolfgang
Stimmt, so hab ichs auch immer gehandhabt... LA billiger? damals(tm) eher nicht... ..bis ich FORTH entdeckt habe, seitdem höchstens noch 2-3x einen LA im Einsatz gehabt. Nachdem ich FORTH dann richtig(?) kapiert habe, brauchte ich keinen LA mehr (konnte mir dann in meinem Ing.Büro diese Investition sparen :)
Für seltene Fälle dann wieder mit Portpin und Oscar. Meistens ein Port (wenn frei) mit einem WrapPfosten und 8 LEDs für guckometrische Überwachung. Reichte mir völlig, selbst bei dem Trumm mit den 14 aktiven IR Ebenen (selten, PWF, BrownOut, 50Hz, 100Hz, 1kHz, 20kHz, 19kBd, ...) und alles völlig asynchron, wobei dann auch noch bei bestimmten Umständen, die IR Prioritäten abgewandelt wurden.
Damals standen mir diverse edelste LA im Dutzend zur Verfügung, so hp1608 . hp16500(?) samt einem schweineteuren, aber völlig unbrauchbarem Dolch (8050?)
Mein Liebling war der hp1608|1604(?) nannte sich LogigStateAnalyzer, hatte nur 16 Speicherplätze aber ein grandioses Triggermenü mit sehr vielen Ebenen. Brauchte man auch, sonst waren die 16 Plätze ruckzuck voll. Hab ihn sogar fast immer benutzt, wenn ich mal Langzeit Protokolle abspeichern musste. Den hp als Trigger für den Dolch als Datengrab/ Speichererweiterung...
Mit dem hp konnte man leicht sowas fangen wie: 3x an pin1 gewackelt, dann
7 fallende Flanken an pin2, rückfall in pin1 Ebene, wenn pin3 7x gewackelt hat und pin4 positiv war, jedoch nicht wenn pin5 rattert... sonst nächste Ebene bit triggerung für Channel/Platz 1, dann wieder auf der Lauer legen... Man konnte sich dann auch anzeigen lassen, bis wo er gerade im Triggerbaum geklommen war.Hab sowas später nie mehr an anderen LA gefunden, allerdings auch die LA Schiene nie weiter benutzt, s.o.
Saludos (an alle Vernünftigen, Rest sh. sig) Wolfgang
Wechselrichtertrittgrenze, sehr lange her, jedesmal beim Anfahren der
simulieren kann. Damals gabs nur die KAWUMMMMM Methode.
beim debuggen auf.
bringen die Programme zum laufen :p
Wolfgang
Schöne Betätigung für meine Ätzerei: Bei C hat der Programmierer den Compiler im Kopp :)
Bei FORTH im Target ;)
Saludos (an alle Vernünftigen, Rest sh. sig) Wolfgang
Ja genau, so macht man das.
Wie ein Kollege (Ex-Siemens) mal sagte, du kannst doch zum Stromsparen den Empfänger erst dann einschalten, wenn ein Funktelegramm kommt, oder? Ja. tolle Idee. Und so praktisch. Und so Siemens. Warum hat sich der das nicht patentieren lassen?
Rest angepasst.
Weist Du das mit der Anmeldung wirklich? Gängig war ja eine vor Kollegen verheimlichte Anmeldung. Öfters erlebt, Idee geklaut und angemeldet :(
Saludos (an alle Vernünftigen, Rest sh. sig) Wolfgang
Have something to add? Share your thoughts — no account required.
Ask the community — no account required