Code-Templates für AVR-Register

Warum sollte man sich für Dinge abmühen, die der Computer viel besser kann als man selbst?

Dieser Gedanke rückt viel zu oft in den Hintergrund. Auch wenn ich mich selbst immer wieder dabei erwische, Dinge manuell zu machen (weil man es halt doch nicht so oft braucht), poppt immer wieder folgender Gedanke hoch:

Wenn man einmal 2 Stunden für die Automatisierung einer 10-minütigen Aufgabe investiert, hat es sich nach 12-maliger Benutzung schon gelohnt. Mal ganz zu Schweigen von Flüchtigkeitsfehlern, Wiederholbarkeit, etc.

Mir war schon länger bekannt, dass Microchip Studio Definitionsdateien für Register mitbringt, das erste Mal aktiv genutzt habe ich sie beim updizombi (den ich im Nachhinein lieber updipuppeteer genannt hätte, weniger apokalyptisch), auf dessen Hilfsscript ein Tool entstand, das viel Fleißarbeit abnimmt:

Für die bessere Lesbar- und Wartbarkeit beim Schreiben von Registern habe ich mir angewöhnt, die Namensdefinitionen der Bits zu nutzen. Dafür liegt dann mindestens die Register Summary des Chips auf dem zweiten Bildschirm:

Das Abtippen ist reine (nervige, aber sinnvolle) Fleißarbeit. Nach einigen Jahren hat dann doch die Faulheit – oder Motivation? – gesiegt und es ist ein zusammengehacktes Script entstanden, das die beim Microchip Studio mitgelieferten Definitionsdateien in Codetemplates umwandelt.

Die Ausgabe sieht dann wahlweise so

...
/// Module USART - USART
/// Register group USART0 - USART
/// Register UDR0 - USART I/O Data Register 0
UDR0 = ;
/// Register UCSR0A - USART Control and Status Register A
UCSR0A = (0<<RXC0) | (0<<TXC0) | (0<<UDRE0) | (0<<FE0) | (0<<DOR0) | (0<<UPE0) | (0<<U2X0) | (0<<MPCM0);
/// Register UCSR0B - USART Control and Status Register B
...

oder so

...
/// Module USART - USART
/// Register group USART0 - USART
/// Register UDR0 - USART I/O Data Register 0
UDR0 = 
/// Register UCSR0A - USART Control and Status Register A
UCSR0A = 
      (0<<RXC0) // USART Receive Complete
    | (0<<TXC0) // USART Transmitt Complete
    | (0<<UDRE0) // USART Data Register Empty
    | (0<<FE0) // Framing Error
    | (0<<DOR0) // Data overRun
    | (0<<UPE0) // Parity Error
    | (0<<U2X0) // Double the USART transmission speed
    | (0<<MPCM0); // Multi-processor Communication Mode
...

aus.

Den Code und Details zur Benutzung gibt es im Git-Repository. Mal sehen, welche Tülchen in dem Dunstkreis sonst noch entstehen.

AVR, ferngesteuert

Die AVRs der 0/1-Serie verwenden zum Programmieren und Debuggen UPDI, welches etwas vereinfacht gesprochen ein auf UART basierendes Protokoll ist.

Dementsprechend hat es nicht lange gedauert, bis es pyupdi entstanden ist. Mit diesem Tool bzw. Library reicht eine serielle Schnittstelle vom PC (mit TTL-Level) und ein Widerstand, um Programmcode auf den Mikrocontroller zu bekommen.

Neben den Programmierfunktionen bietet die Schnittstelle ebenfalls die Möglichkeit zu Debuggen. Zu dem Funktionsumfang gehört gleichermaßen das Auslesen und Schreiben von Registern. Warum das nicht einfach nutzen, um direkt über den PC die Ports und Peripherie-Module des Chips zu verwenden?

Das Schreiben und Lesen im Adressraum der CPU sind gut dokumentiert, der einzige Haken ist, dass eine etwaig geflashte Firmware weiterläuft und einem die Suppe versalzen kann (oder andersrum). Zum Debuggen gehört natürlich auch, die Ausführung der CPU anzuhalten, wozu ich allerdings keine Dokumentation bzw. Informationen finden konnte. Aber macht nichts, einiges vom Protokoll ist ja bekannt und ein bisschen Reverse Engineering bin ich ja nicht abgeneigt. Unterm Strich ist es anscheinend recht trivial: Es muss ein Key geschrieben werden und in ein „reserviertes“ Control-Register eine 1 zum Anhalten und eine 2 zum Ausführen schreiben.

Mehr Details und ein kurzes Demo-Video ist im updizombie-Repository zu finden.

Das „Custom Programming Tool“ in Atmel Studio

Schon länger gibt es in Atmel Studio die Möglichkeit, ein eigenes Programming tool zu verwenden:

Hat mich bis jetzt nie wirklich interessiert, da ich entweder über einen in-circuit-Programmer (der direkt unterstützt wird) flashe oder FastBoot manuell startete.

Zu viele Klicks bzw. Tastaturakrobatik. Also doch mal mit dem bereits Vorhandenem spielen.

echo „foo“ macht was es soll:

Prima, also kann ich einfach die burn.bat im Projektverzeichnis einfügen und los geht’s!

Nope. Da passt wohl das Arbeitsverzeichnis nicht. Aber wie kommt man ins aktuelle Projektverzeichnis? Zunächst versuchte ich mich an den Platzhalter der „External Tools“. Allerdings wurde „$(ProjectDir)“ zu leer ersetzt.

Hmpf. Für die Buildautomatisierung gibt es noch die Build Events – klickt man dort auf „Edit #-build …“ und dann auf Show Macros, bekommt man eine längere Liste an Platzhaltern:

echo „$(MSBuildProjectDirectory)“ zeigt das aktuelle Projektverzeichnis 🙂

also schnell „$(MSBuildProjectDirectory)\burn.bat“ eingegeben und ab dafür!

Jaa-eein. Die Batch-Datei wird zwar ausgeführt, aber im falschen Arbeitsverzeichnis. Mist.

Eine kurze Suche bei Stack Overflow lässt in das richtige Verzeichnis wechseln:

cmd /k pushd $(MSBuildProjectDirectory) & burn.bat

It verks!!1!

Jetzt steht in der dämlichen Batchdatei halt noch der feste Pfad zum Binary und es wird immer die Debug-Config über den UART geschoben. Ein bisschen mehr Makro-Magic und ein %1 an der richtigen Stelle (die zu flashende Datei) mit folgendem Command erledigt den Job:

cmd /k pushd $(MSBuildProjectDirectory) & burn.bat „$(Configuration)\$(OutputFileName).hex“

Da in der burn.bat in meinem Fall eh nicht mehr als ein Aufruf von fboot.exe ist, kann die Batch-Datei auch komplett weggelassen werden:

cmd /k pushd $(MSBuildProjectDirectory) & fboot /B57600 /C1 /P“$(Configuration)\$(OutputFileName).hex“

Jetzt müsste man nur noch die Ausgabe des Build und des Custom programming tool gleichzeitig anzeigen können, dann wäre ich richtig happy 😉

PS: Bitte beim Copy & Paste der Befehle die Anführungszeichen manuell ersetzen, WordPress macht sie typografisch korrekt aber funktional kaputt.

Aus Fehlern (nichts) lernen

Oh Mann, bin ich doof.

Am Samstag kamen meine Leiterkarten deutlich früher als erwartet. Darunter ein Board, auf dem ich einen SMD-Quarz verbaut habe.
Am Tag könnte ich sie nicht zusammenbauen, weil ein Umzug angesagt war, also wurde es in die Nachtstunden verlegt. Das Bestücken klappte dank ordentlich Flussmittel und passender Lötspitze (nichts geht über eine Hohlkehle!) gut und schnell.

Nachdem ich mich erst wieder erinnern musste, wie man den AVR-Programmer richtig einstellt damit er richtig funktioniert, ging auch der Zugriff auf den Mikrocontroller – bis ich die Fuses auf externe Taktversorgung durch Quarz einstellte. Sch…e! Warum mag der nicht mehr? Der Quarz wurde mit Heißluft aufgebraten und vielleicht hat er es nicht überlebt – mit einem fliegend aufgelisteten bedahteten hat es schließlich geklappt:

touchpad_quarz

 

Wie auch immer – einen Quarz habe ich auf die Weise noch nie kaputt bekommen.

Der Griff zum Datenblatt bestätigt es: die Padzuordnung war falsch. Bei den MQ- und MJ-Quarzen gibt es vier Pads und nur zwei gegenüberliegende sind funktional, die anderen beiden sind einfach nur da. Und natürlich war in meiner selbst erstellte Bauteilbibliothek genau dieser Fehler.

Ärgerlich, wenn das passiert. Richtig dumm, wenn es einem zweimal passiert – und genau das war der Fall. Wie das entstanden ist, kann ich h nicht mehr genau sagen. Es müsste schnell gehen, nicht gut genug kontrolliert und das Datenblatt falsch gelesen. Dort ist nämlich sowohl die Ansicht von oben und unten abgebildet. Später im Layout ist der Fehler auch nicht mehr aufgefallen – der DRC meckert kann den dummen User eben nicht erkennen.

Nachdem der Rest des Aufbaus bis jetzt sehr gut funktioniert (bis auf den Quarz funktionieren alle bisher getesteten Features), deshalb wird es keine zweite Runde Leiterkarten geben.

Demnächst gibt es dann auch mehr von dem Projekt mit dieser Leiterkarte.