Mach es gut, es wird schlecht
Der Grund für den Beitrag war ein kürzlich veröffentlichter Artikel (als ich anfing, diesen Beitrag zu schreiben, war er wirklich neu, aber im Ordner "Unfinished" ging lange etwas weiter) über Habr in Bezug auf Aspekte der Implementierung von Software UART auf AVRs MK. Die von sich selbst aufgeworfenen Fragen sind nicht ohne Interesse, aber es werden so seltsame Antworten gegeben, dass sie es für seine Pflicht hielten, die notwendigen Erklärungen abzugeben. Das Thema ist markiert. Wer etwas über „Könige, Kohl und Schuhe“ lesen möchte, dh die Anforderungen der Normen, die (korrekte) technische Dokumentation und Aufzeichnungen in der Assembler-Programmierung für AVR lesen möchte, kann auf die Schaltfläche unten klicken.
Lassen Sie uns die Frage genauer skizzieren: Ist es möglich, IRPS (der übliche Name für die Schnittstelle im Namen von UART) auf einem AVR-Typ MK (insbesondere Tiny13) zu implementieren, wenn von einem internen Generator aus gearbeitet wird? Tatsache ist, dass dieser Generator keine sehr guten Indikatoren für die Frequenzerhaltungsgenauigkeit hat, weshalb diese Frage auftaucht. Ich muss sofort reservieren, dass es keine Rolle spielt, ob wir eine Software-Implementierung (wie im ursprünglichen Beitrag vorgeschlagen) in Betracht ziehen oder MK-Hardware-Blöcke verwenden. Die Ergebnisse einer Methode (in Bezug auf zeitliche Genauigkeitsparameter) werden fast vollständig in eine andere übersetzt.
Die grundlegende Frage ist, ob der interne Generator die erforderliche Betriebsgenauigkeit liefern kann, da bei einer negativen Antwort auf diese Frage weitere Studien bedeutungslos werden. Um die beiden unabhängigen Größen zu vergleichen, müssen wir beide kennen. Zunächst bestimmen wir die erforderliche Genauigkeit der Frequenzbegrenzung und die Fähigkeiten, die dieser bestimmte MK in diesem Teil bietet. Eine wichtige Bemerkung zum vorherigen Satz - dies bedeutet nicht einen bestimmten Fall, „der uns in Empfindungen gegeben wurde“, sondern einen bestimmten Typ von MK, der durch seine technische Beschreibung dargestellt wird.
Zunächst werden wir etwas finden, das leichter zu finden ist (nun, ich dachte schon) - Anforderungen an die Genauigkeit der Zeitparameter der Schnittstelle. Wir öffnen den Standard für RS232 und sehen sofort alles, was Sie brauchen. Es stellte sich heraus, dass "Sie es nicht einfach nehmen können und ...", weil der Standard bezahlt wird und alle Kopien im Web illegal sind. Okay, wir bringen die inländische Version von GOST zum Gelenk C2 und finden dort überhaupt keine Zeitparameter, mit Ausnahme der Dauer der Front und der Unterbrechung des Pulses. Dies verursachte zunächst eine leichte Unruhe - wie es sein könnte -, aber dann wurde klar, dass das C2-Gelenk nur den Schnittstellenteil des IRPS beschreibt und die Anforderungen in letzterem sein sollten. Im Prinzip ist alles logisch, es ist nicht nur klar, warum dies in GOST nicht explizit beschrieben wird, aber am Ende kann man manchmal selbst denken, obwohl es immer noch "irgendwie nicht ordentlich erhalten" ist.
Wenn Sie das Übertragungsprotokoll kennen, ist es natürlich aus allgemeinen Überlegungen möglich, die maximal zulässige Nichtübereinstimmung zwischen Sender- und Empfängergeschwindigkeit (0,5 / 9,5 = 5,2%) zu ermitteln. Dies ist jedoch eine Untersuchung des sphärischen Pferdes, von dem Sie wissen, wo:
- Die Anforderungen der Norm können und sollten strenger sein als eine ähnliche theoretische Berechnung der maximal zulässigen Nichtübereinstimmung.
- Wenn wir die endgültige Nichtübereinstimmungszahl kennen, erhalten wir in keiner Weise das Budget des Senders und Empfängers.
Das Wandern im Internet führte zu Atmels AppNote (nun, da wir immer noch das MK dieser Firma verwenden), es spricht direkt von einer zulässigen Nichtübereinstimmung von 2% bei gleichem Budget, was zu einer Anforderung an die Genauigkeit der Aufrechterhaltung der Senderfrequenz von 1% führt. Wir werden einem seriösen Unternehmen vertrauen und davon ausgehen, dass es Zugang zu klassifizierten Materialien hat und diese Zahl korrekt ist, zumal sie plausibel erscheint. Ich verstehe die Verwundbarkeit einer solchen Position, aber um ehrlich zu sein, bin ich es leid, nach der genauen Antwort auf eine so einfache Frage zu suchen, und kann es kaum erwarten, mit dem nächsten Teil fortzufahren.
Die nächste Hälfte der Antwort liegt im MK und wird durch die technische Dokumentation dafür bestimmt. Zunächst ein wenig über das Gerät des internen Generators, zumal es mehr oder weniger beschrieben wird. Der Generator verwendet eine RC-Kette als Zeitsteuerungselement, und da die Aufgabe, einen integrierten Kondensator aus einem exakten Kondensator und einem exakten Widerstand zu bilden, sehr nicht trivial ist, variiert die Endfrequenz von Instanz zu Instanz des MC erheblich. Um diesen Parameter vorhersehbarer zu machen, haben die Hersteller einen Hardwareknoten hinzugefügt, der über ein Kalibrierungsbyte gesteuert wird. Mit diesem Gerät können Sie die Frequenz des Generators über einen weiten Bereich ändern und dementsprechend den gewünschten Wert mit viel höherer Genauigkeit erhalten.
Es wäre interessant herauszufinden, wie genau die Steuerung in der Hardware implementiert ist. Ich sehe eine Option, entweder die Ladespannung des Kondensators über den DAC zu steuern oder die Vergleichsspannung am Komparator zu steuern. Beide Optionen führen jedoch zu einer signifikanten Nichtlinearität der Steuereigenschaften, obwohl sie einfach zu implementieren sind. Die interne Implementierung des Generators ist jedoch nicht Teil unserer Aufgabe, wir interessieren uns für seine externen Parameter.
Also öffnen wir die Dokumentation (Sie können die Datei im Viewer öffnen, aber ich habe eine typografische Version der Beschreibung, die vom Hersteller selbst gedruckt wurde - ja, früher) und suchen nach dem entsprechenden Abschnitt. Die Parameter, an denen wir interessiert sind, befinden sich im Abschnitt „Kalibrierter interner RC-Oszillator“. Folgen Sie dann gegebenenfalls den Links. Und hier haben wir (ich bin mir nicht sicher, ob Sie es sind) auf die erste Enttäuschung gewartet - ich habe lange Zeit (ungefähr 15 Jahre) mit Atmel-Produkten gearbeitet und immer geglaubt, dass sie eine gute Dokumentation für MK haben. Laut Psychiatern „gibt es keine gesunden Menschen, es gibt keine unerforschten Menschen“ und eine sorgfältige Untersuchung des entsprechenden Abschnitts bestätigte diese Wahrheit, da ich solche Fehler in der Dokumentation zuvor nicht feststellen konnte. Zu meiner Verteidigung kann ich nur Folgendes sagen:
- Ich habe in den MK-Daten nie einen internen Generator verwendet, daher habe ich ihn nicht besonders sorgfältig studiert.
- Als ich anfing, mit diesen MKs zu arbeiten (vor viel mehr als 10 Jahren), war ich jung (nun ja, definitiv jünger als jetzt) und dumm und verstand die Notwendigkeit einer guten (verständlichen, umfassenden und eindeutigen) Dokumentation nicht vollständig.
- Ich bin bereit, mir viel zu vergeben, einfach weil ich mir viel vergebe und alle meine Mängel nicht fatal sind (das letzte Argument ist besonders überzeugend, nicht wahr).
Nachdem ich meinen Kopf mit Asche bestäubt habe, werde ich meine Ansprüche an die Dokumentation geltend machen, und es kann keine Entschuldigung für den Hersteller geben. Wir öffnen den obigen Abschnitt und beginnen ihn sorgfältig zu studieren. Gegebenenfalls gehen wir zu den erforderlichen Seiten (Sie klicken immer noch auf die Links). Gemeinsam werden wir nach den folgenden Parametern suchen, die die Zeitcharakteristik des Generators charakterisieren: Nenngenauigkeit, Einfluss der Versorgungsspannung, Einfluss der Temperatur und Alterungsparameter - dies ist der Mindestsatz, der zur Bewertung der Genauigkeitsparameter eines Generators erforderlich ist.
Der erste Teil des Marleson-Balletts ist die nominelle Genauigkeit.
Sofort finden wir den gewünschten Parameter - die Generator-Abstimmgenauigkeitstabelle, in der zwei Zeilen „Werkskalibriert“ mit dem angegebenen Wert ± 10% und „Manuelle Kalibrierung“ mit demselben Parameter ± 2% angezeigt werden.
In Bezug auf diese Daten stellen sich sofort eine Reihe von Fragen: Was bedeuten sie und wie werden diese Parameter gemessen? In der ersten Zeile gibt die Tabelle selbst die Temperatur (der Umgebung oder des MK selbst an - es ist unklar, aber dies ist eine Laune von meiner Seite) und die Versorgungsspannung. Außerdem heißt es in der Notiz (meiner Meinung nach ist dies nicht erforderlich), dass diese Messung an einem bestimmten Punkt im Raum durchgeführt wird äußere Bedingungen. Man kann davon ausgehen, dass wir in diesem Fall den beim Hersteller aufgezeichneten Kalibrierungsfaktor verwenden sollten, obwohl es besser wäre, dies im Hinweis explizit anzugeben. Alles ist mehr oder weniger klar und wird fast eindeutig interpretiert (obwohl im Zusammenhang mit dem Studium der technischen Dokumentation gesagt werden sollte, dass alles verschwommen ist und Variationen in der Interpretation zulässt, und dies ist inakzeptabel, aber wenn wir dies tun, verschwindet das Thema der weiteren Diskussion einfach (und was kommt als nächstes) schreiben, es ist nicht klar, daher Nachsicht zeigen).
Bei der zweiten Zeile des Falls ist es jedoch schlimmer: Die Grenzen für Änderungen der Temperatur und der Versorgungsspannung sind angegeben, und es wird argumentiert, dass Sie mit einem magischen Kalibrierungsverfahren im gesamten Bereich deutlich bessere Ergebnisse erzielen können als im Werk. Meine Frage stellt sich sofort: Wenn dies überall erreicht werden kann (zu jedem Zeitpunkt der Temperatur- und Stromversorgung) und der Hersteller weiß, wie dies zu tun ist, warum hat sie dies dann nicht selbst bei der Werkskalibrierung zu einem bestimmten Zeitpunkt unter den Bedingungen getan? Wir wenden uns der Beschreibung des Kalibrierungsbytes zu und sehen, dass es 128 Werte annimmt. Dies deckt den Bereich von 50% bis 200% des Nennwerts ab, was 150/128 ~ 1,17% der Frequenzänderung pro Kalibrierungseinheit entspricht, was die erwartete Genauigkeit besser als in ergeben sollte 1% Aber dann sollten wir berücksichtigen, dass die Anpassungskennlinie eindeutig nicht linear ist und im Bereich großer Kalibrierungswerte 60% / 32 ~ 2% des Schritts liegen (Daten aus der Grafik, ich habe wiederholt meine Einstellung zu einer ähnlichen Methode zur Darstellung technischer Parameter zum Ausdruck gebracht, aber ich wiederhole - dies ist inakzeptabel Die Methode ist natürlich besser als nichts), was eine Genauigkeit von 1% ergibt. Wenn wir die Monotonie der Anpassungskennlinie berücksichtigen (ja, das steht in der Dokumentation, wird sie nicht in der Grafik gezeichnet, sondern im Text klar angegeben. Ich weigere mich kategorisch zu verstehen zu zu, und vor allem, warum wollte das Unternehmen ihm ein Gesetz der Anpassung machen, aber es geschaffen), die eindeutig in den Richtlinien angegeben ist, ist es notwendig, die Genauigkeit von 2% ist durchaus erreichbar zu betrachten. Ich mag es nicht wirklich, dass ich mir das Diagramm ansehen musste, aber das ist nicht notwendig und die tabellarischen Daten sind ausreichend. In diesem Teil sollte die Dokumentation als vollständig verständlich und konsistent angesehen werden. Das Kriterium der Richtigkeit liegt außerhalb unseres Kompetenzbereichs.
Der zweite Teil des Marleson-Balletts. - der Einfluss äußerer Bedingungen.
Und dann beginnt "Müll, Dämpfe und Sodomie". Anstelle von Wertetabellen sind wir eingeladen, Bilder anzusehen (aus irgendeinem Grund werden sie in der Dokumentation als Diagramme typischer Werte bezeichnet). Wie Sie wissen, "besteht der Hauptvorteil der grafischen Darstellung von Informationen in ihrer Sichtbarkeit und hat keine weiteren Vorteile." Es wäre möglich, auch solche Informationen zu verwenden und Grenzwerte aus dem Diagramm zu entfernen („obwohl dies für das Team anstößig ist“), wenn dieses Diagramm nicht im Abschnitt „Typische Merkmale“ angegeben wäre. Ich weiß nicht, wie jemand persönlich zutiefst davon überzeugt ist, dass die Angabe typischer (oder typischer, ich weiß nicht, wie man korrekter ist, in einem Film sagten sie "typisches Aussehen") Bedeutungen, zumindest in Form eines Diagramms, selbst in der Tabelle, einfach nichts anzeigt. Sie können im Design nicht geführt werden, da diese Parameter nicht klar sind, was sie bedeuten, und jede Abweichung von den typischen Werten akzeptabel ist, im Gegensatz zu den Minimal- und Maximalwerten, deren Übergang auf eine Fehlfunktion des Geräts hinweist.
Nun, wir haben bestanden, wir werden versuchen, zumindest einige Informationen zu extrahieren und festzustellen, dass sich die Frequenz des Generators um ± 4% ändert, wenn sich die Temperatur von -40 auf + 80 ° C ändert. Ein ähnliches Bild mit der Versorgungsspannung - nur typische Grafiken und der daraus resultierende Fehler in -6 + 2% von 3,3 bis 5,5. Daten zur Alterung des Generators werden einfach nicht angegeben, was im Allgemeinen logisch ist, da vor dem Hintergrund der bereits angegebenen Parameter die Genauigkeit von einem Prozent für 5 Jahre (ein charakteristischer Wert für Silizium) niemanden stört.
Jetzt haben wir alle Daten, um unsere erste Frage zu beantworten: Während der Werkskalibrierung erfüllt der Generator nicht die Schnittstellenanforderungen für die Genauigkeit, wenn er für bestimmte Anwendungsbedingungen kalibriert wird. Er erfüllt die Grenzanforderungen, entspricht jedoch nicht dem Standard. Es sollte auch beachtet werden, dass, wenn die Kalibrierung der Versorgungsspannung und eines bestimmten MK bei der Herstellung des Geräts durchgeführt werden kann und gehofft wird, dass sie sich nicht zeitlich ändern, die Temperatur nur im laufenden Betrieb berücksichtigt werden kann und einen externen Zeitstandard mit angemessener Genauigkeit erfordert. Da die Entwicklung von Geräten von der Regel „Wir glauben an Gott, alles andere erfordert Beweise“ geleitet werden sollte und wir die Möglichkeit der Erfüllung der Anforderungen nicht bewiesen haben, ist die richtige Antwort, dass es unmöglich ist, die Implementierung von IRPS, das die Anforderungen des Standards in diesem MC erfüllt, mit einem internen Generator zu garantieren. Beachten Sie, dass wir bei der Analyse der Dokumentation die obige Schlussfolgerung gezogen und sie so formuliert haben, dass betont wird, dass bei einer bestimmten Instanz von MK alles möglich ist und wird, wenn die Sterne erfolgreich aufgehen. Das heißt, unsere Schlussfolgerung widerspricht dem zuvor erwähnten Beitrag, wie könnte dies geschehen, weil für eine Person alles gut funktioniert - lassen Sie es uns herausfinden.
Nun beginnt die Kritik am obigen Beitrag. Lassen Sie uns zunächst überlegen, wie wir sicherstellen können, dass das Gerät auf die Anforderungen einer bestimmten Schnittstelle überprüft wird. Ich kann folgende Möglichkeiten vorschlagen:
- Eine gute Möglichkeit besteht darin, die kritischen Parameter der Geräteschnittstelle zu messen und mit den Anforderungen des Standards zu vergleichen. Dies kann mit universellen Instrumenten (in unserem Fall dem Oszilloskop und der Länge des Bitintervalls oder der vollständigen Übertragung) oder mit einem speziellen Gerät erfolgen, das zum Testen dieser Schnittstelle zertifiziert ist.
- So lala - Organisation der Interaktion mit einem anderen Gerät, das den Antwortteil der Schnittstelle implementiert und bewährt ist (entspricht den Anforderungen des Standards). Natürlich ist eine solche Prüfung völlig unzureichend und kann eher angewendet werden, um die Fehlfunktion des zu testenden Geräts zu bestätigen, tut aber zumindest etwas.
- Der schlechte Weg besteht darin, den Antwortteil der Schnittstelle (auf demselben oder einem anderen Gerät) unabhängig zu implementieren und mit ihm zu interagieren. Da beide Geräte offensichtlich nicht bewiesen sind, ist die Nützlichkeit einer solchen Prüfung sehr, sehr zweifelhaft. Ein gutes Beispiel für diesen Ansatz ist das „Echo“ auf einem seriellen Kanal, das nichts anderes beweist als die Tatsache, dass das Gerät im Grunde kaputt ist und etwas übertragen kann, und kaum mehr als nichts über die Übertragungsgeschwindigkeit meldet.
- Ein schrecklicher Weg ist es, als Tester ein Gerät zu nehmen, das die Anforderungen des Standards überhaupt nicht erfüllt (oder vielmehr widerspricht) und wie im vorherigen Absatz zu arbeiten.
Es ist die letztere Methode, die in der betrachteten Post verwendet wurde - ein serieller Kanalsoftwareempfänger ist implementiert, der entgegen den Anforderungen des Standards seine Frequenz ändert, um sich an das Eingangssignal (insbesondere die Länge des Startbits) anzupassen, was einen stabilen Empfang eines Signals schlechter Qualität in Bezug auf Zeitparameter ermöglicht. Dies bedeutet nicht, dass dies niemals durchgeführt werden sollte. Außerdem wurde bei analogen Modems die Abstimmung auf die eingehende Geschwindigkeit übernommen, die auf ähnliche Weise implementiert wurde, aber die Frequenz durch Ändern des Teilers genau umgeschaltet wurde, und dies ist eindeutig nicht unser Fall. Und in dieser Version wird alles perfekt erhalten und Informationen werden unter allen äußeren Bedingungen stabil übertragen. Wenn wir also über die Möglichkeit sprechen, Informationen zwischen zwei MCs zu übertragen, die von internen Generatoren über eine Schnittstelle arbeiten, die entfernt an IRPS erinnert, lautet die Antwort Ja. Wenn wir über die Interaktion mit externen Geräten sprechen, die den Anforderungen des Standards entsprechen, und nicht mehr, dann erwarten wir viele unangenehme Überraschungen.
Die allgemeine Schlussfolgerung aus dem Obigen:
- Beim Entwerfen von Geräten sollten Sie sich auf die Dokumentation (RTFM) konzentrieren.
- Sie müssen die Dokumentation studieren und richtig interpretieren, was Sie lesen (RTFMF).
- Denken Sie daran, dass Dokumentation in unserer Zeit daher zu Missverständnissen, Ungenauigkeiten (und sogar Fehlern) führen kann
- Überprüfen Sie die erhaltenen Informationen auf Konsistenz und Glaubwürdigkeit
- Verwenden Sie die experimentell erhaltenen Informationen nur, um die Schlussfolgerungen aus der Analyse der Dokumentation zu bestätigen
- Wählen Sie die Versuchsmethoden für Prüfgeräte sorgfältig aus, um ein zuverlässiges Ergebnis zu erhalten.
Nun, abschließend, wie versprochen, ein kleiner Monteur. Ich habe mir erlaubt, das vom Autor angegebene Codefragment in normaler Form umzuschreiben, da der in das GCC eingebaute Assembler nichts anderes als ein Spott über den Programmierer ist, den ich nennen kann. Nein, natürlich verstehe ich, dass die Entwickler des Compilers von guten Gründen geleitet wurden, aber das Ergebnis ähnelt schmerzlich dem Satz "Nun, es funktioniert".
.equ delay=15 TX_Byte: cli ; ld r18,Z+ ; cp r18,r1 ; breq Exit_Transmit ; dec r1 cbi port, TX_line Delay_TX: ldi r16,delay Do_Delay_TX: nop dec r16 brne Do_Delay_TX TX_Bit: sbrc r18,0 sbi port,TX_line sbrs r18,0 cbi port,TX_line lsr r18 lsr r17 brcs Delay_TX sbi port, TX_line ldi r16,delay Stop_Bit_TX: nop dec r16 brne Stop_Bit_TX Sei
Und sofort fällt ein Fehler im Programm auf - in Zeile 3 (auskommentiert) sollte der Wert von Register 1 Null sein, aber die Zuordnung wird nicht explizit in die Funktion geschrieben. Nach Abschluss eines Einzelbyte-Übertragungszyklus wird dieser Wert durch Zeile 12 garantiert, jedoch nicht beim ersten Durchgang. Daher muss eine Initialisierung hinzugefügt werden, die eine Erhöhung der Codegröße erfordert.
Der zweite Nachteil ist die tatsächliche Bildung des Pegels in den Zeilen 4 bis 7, da das vom Autor angewendete Verfahren zum Ausgeben des nächsten Bits zu Front-Jitter für 2 Taktzyklen bei verschiedenen Übergängen (0-1 und 1-0) führt, was eine Erhöhung der Anforderungen an die Genauigkeit des Haltens der Frequenz zur Folge hat. Nicht, dass dies einen sehr starken Einfluss hätte, aber wenn Sie einen Fehler korrigieren können, ohne das Programm zu erweitern, warum nicht - siehe Epigraph. Die ursprüngliche Version bestand aus 4 Wörtern und wurde in 4 Takten ausgeführt, die neue aus 4 Wörtern und wurde in denselben 4 Takten ausgeführt. Ja, die korrigierte Version erfordert eine eingehendere Untersuchung der MK-Architektur, aber wer hat gesagt, dass dies einfach ist? Andererseits ist in der ersten Version die Portmodifikation atomar und in der zweiten nicht, in diesem Fall spielt es keine Rolle (wir haben Unterbrechungen ausdrücklich verboten), aber das Sediment bleibt. Wenn der fragliche MK einen echten Bitprozessor hätte, wie in Architektur 51, dann könnten wir ein ideales Fragment schreiben, das alle Vorteile beider Ansätze kombiniert (und sogar etwas kürzer ist), aber was können wir von einem Wunschtraum träumen ...
Der dritte Nachteil ist das Thema mehr Stil. Ich habe wiederholt meine Einstellung zu den magischen Konstanten zum Ausdruck gebracht, die wir in der Präambel dieses Programms sehen. Ich betone noch einmal - von der Tatsache, dass der Autor in der Präambel des Programms eine Konstante setzt und nicht direkt im Operator, geht "gewöhnliche Straßenmagie" nirgendwo hin. Tatsache ist, dass wir dem Leser die Methode zur Bildung eines bestimmten Wertes explizit vorstellen müssen und kein Synonym für den auf unbekannte Weise erhaltenen Wert erstellen müssen. Sie können natürlich einen Kommentar in eine Zeile mit einem Wert schreiben, in dem die Berechnungsformel angegeben werden soll. Es ist jedoch besser, die Berechnungsformel explizit zur Bildung der Konstante zu verwenden, und dann benötigen Sie nur keinen Kommentar (natürlich mit den sprechenden Namen der angewendeten Konstanten). Dies geschieht im folgenden Text. Beachten Sie, dass wir erst im letzten Moment in eine Ganzzahl konvertieren und diese korrekt abrunden, damit wir die Genauigkeit des Ergebnisses nicht verlieren.
Es gibt einen weiteren Fehler: Die Länge des Startbits unterscheidet sich etwas vom Bitintervall für die Daten. Obwohl die Abweichung nicht zu signifikant ist (3 Taktzyklen), ist dies bei hohen Bitraten, bei denen das Bitintervall etwa 90 Taktzyklen dauert, bereits ein Fehler von einigen Prozent, was nicht akzeptabel ist. Dieser Fehler kann leicht durch Hinzufügen von Befehlen zum Erzeugen einer zusätzlichen Verzögerung behoben werden. Dies erhöht jedoch die Länge des Programms, sodass wir nur dessen Vorhandensein beheben und dann sicherstellen, dass die korrekte Architektur des Programms (dh auch diese kurzfristige Anwendung) automatisch beseitigt wird.
Nun, da wir die Fehler behoben haben (mit Ausnahme des letzten), werden wir versuchen, das Programm im Sinne des Hauptkriteriums (um in diesem speziellen Fall einen Datensatz zu erzielen) zu verbessern - der Länge des Codes. Das erste, was auffällt, ist das Vorhandensein von zwei Zeitverzögerungen, was schlecht ist, da es gegen das DRY-Prinzip (allgemeine Anforderung) verstößt und die Codegröße erhöht (spezifische Anforderung). Es wäre möglich, dieses Fragment in Form eines Unterprogramms anzuordnen, und wir würden immer noch an Länge gewinnen, da wir 3 Codewörter hinzufügen (1 für jeden Aufruf an zwei Stellen und 1 für die Rückgabe) und 4 speichern, aber es gibt einen viel schöneren Weg - ordentlich die Organisation des Byteübertragungszyklus, die im folgenden Text zu sehen ist.
.equ delay=15 TX_Byte: cli sec ; - clt ; - TransBit: ; in r17,port bld r17,Tx_line out port,r17 Delay_TX: ; ldi r17,delay Do_Delay_TX: nop dec r17 brne Do_Delay_TX TX_Bit: bst r16,0 ror r16 clc brne TransBit ; brcs TransBit ; - Exit_Transmit: Sei
Beachten Sie, wie wir das übertragene Byte zusammen mit dem Übertragsbit als Bitzähler verwenden, eine schöne Lösung, aber es hat einen Nachteil: Die Dauer des letzten Datenbits ist aufgrund der Verzögerung des Übergangs mehrere (2 Zyklen) länger als der Rest. Wenn wir über ein Stoppbit gesprochen haben, dann „egal und vergessen“, da wir nicht das Mindestintervall zwischen den Übertragungen erhalten haben, aber dies ist ein bedeutendes Bit, und wir haben gerade das ursprüngliche Programm für ein solches Verhalten kritisiert. Wir werden nicht mit dem biblischen Charakter aus dem Gleichnis vom Mote in den Augen anderer verglichen und Maßnahmen ergreifen, um ihn zu beseitigen. Dieses Phänomen könnte leicht durch die Einführung einer Verzögerung von 2 Takten kompensiert werden, aber die Codelänge nimmt zu, und dies ist ein Schlüsselparameter. Gehen wir also den klassischen Weg und ändern die Zeit für den Speicher - wir verwenden ein separates Register zum Organisieren des Zählers der übertragenen Bits und erhalten genau die gleichen Bitintervalle mit der gleichen Codegröße.
Die nächste Verbesserung ist mit der Bildung der Dauer des Bitintervalls verbunden, das im ursprünglichen Programm in einem 4-Zyklus-Zyklus ausgeführt wird. Wenn wir es 3-Takt machen (das kleinstmögliche in diesem MK), können wir ein Byte Code speichern und möglicherweise die Genauigkeitsparameter verbessern, da die Diskretion der Verzögerung geringer wird (die Abweichung überschreitet bei korrekter Rundung nicht die halbe Größe des Diskreten). Es sollte jedoch berücksichtigt werden, dass in einem bestimmten Fall die Genauigkeit verloren gehen kann. Dies hängt alles von den Quelldaten ab. Ein weiterer Umstand, der die Auswahl einer solchen Zyklusdauer beeinflussen könnte - die maximale Verzögerungsgröße für einen Bytezähler beträgt 256 Werte -, können Sie für die verfügbare Option Geschwindigkeiten ab 9600 Baud und höher verwenden. Bei einer Verzögerung von 3 Zyklen ist dies jedoch nicht möglich. Es wäre sehr schön, diesen Umstand (die minimal zulässige Portgeschwindigkeit) in den Kommentaren zum Programm wiederzugeben und gleichzeitig eine Warnmeldung anzuzeigen, falls diese Anforderung verletzt wird. Nehmen Sie die entsprechenden Änderungen an den Parameterbildungsmakros vor, um eine Verzögerung zu bilden, und vergessen Sie nicht, "sprechende" Namen zur Angabe von Variablen zu verwenden.
.equ Freq = 8000000 .equ BaudRate = 115200 .equ PayLoad = 9 ; .equ CycleTime = 3 ; .equ delay=((Freq*2/BaudRate - PayLoad*2)+CycleTime)/(CycleTime*2) TX_Byte: cli ldi r18,10 sec ; - clt ; - TransBit: in r17,port bld r17,Tx_line out port,r17 Delay_TX: ldi r17,delay Do_Delay_TX: dec r17 brne Do_Delay_TX TX_Bit: bst r16,0 ror r16 dec r18 brne TransBit Exit_Transmit: sei
Schauen wir uns nun das Ergebnis an - die Codegröße verringerte sich von 20 auf 16 Wörter (wenn wir nur die Übertragung selbst berücksichtigen, dann noch auffälliger - von 18 auf 14 verschwand der Jitter der Fronten (natürlich nur die Jitterkomponente, die durch die Programmfunktionen verursacht wird, auf der Hardwarekomponente, wir Wir verletzen nicht), die Genauigkeit der Einhaltung von Zeitintervallen hat sich verbessert, das Programm ist sichtbarer und verständlicher geworden (aufgrund von Kommentaren, da selbst ein gut geschriebenes Assembler-Programm normalerweise nicht selbst dokumentiert ist).
Die Schlussfolgerung aus dem letzten Teil lautet: Wenn wir Weltrekorde in der Assembler-Programmierung aufstellen wollen, sollten wir die Architektur eines bestimmten MK sehr gründlich studieren und das gewonnene Wissen anwenden, um das ideale Ergebnis zu erzielen, wobei wir alle Feinheiten berücksichtigen.
Gut und abschließend - die Aufgabe, Code mit der Mindestgröße zu schreiben, sieht heutzutage etwas kompliziert aus, erhält aber ganz unerwartet eine Bestätigung seiner Vitalität. Ende letzten Jahres (2016, so lange hat dieser Beitrag auf seinen Einsatz gewartet) wurde ein neuer MK aus der MSP430-Familie angekündigt, der neben dem einzigartig niedrigen Preis (26 Cent - wir warten auf das Erscheinen chinesischer Geräte, die darauf basieren) auch eine einzigartig kleine Programmspeichergröße hat - 512 Byte (nein, ich habe mich nicht geirrt, der Buchstabe "k" unmittelbar nach der Nummer ist nicht). Daher kann sich die Größe des Codes bei der Verwendung dieses Geräts als kritisch herausstellen, und das Schreiben derart extremer Programme erfordert im Allgemeinen eine eingehende Untersuchung von MK, und "die Arbeit selbst ist ein Segen".