Vereinfachungen für PIC Assembler

i_hasser

Grand Admiral Special
Mitglied seit
06.06.2002
Beiträge
18.964
Renomée
85
Standort
IO 0x60
Moin moin

Hab vor kurzem mal in's Manual von gpasm geschaut, und da sind mir diverse schöne IF-Kontrukte aufgefallen, so richtig schön C-like. Also natürlich nicht genau gelesen und gleich erstmal ausprobiert.
Die Ernüchterung kam schnell, die Dinger sind nur für den Präprozessor, damit lässt sich bedingte Compilierung recht elegant umsetzen.
Hab mir darauf mal den Präprozessor genauer angeguckt, über Makros lassen sich solche Sachen auch realisieren (aber nicht für bedingte Compilierung, sondern wirklich für's Programm). Hab mal auf die Schnelle was zusammengeschustert.

Implementiert sind im Moment arithmetische Vergleiche (8bit in fast jeder Kombination von mem/W/immediate, 16bit für mem/mem) und IF-Blöcke.
Aussehen tut das so, dass einmal verglichen wird (das Ergebnis vom Vergleich wird in C und Z abgelegt), und man dann einen IF-Block für ein bestimmtes Ergebnis ausführen kann. Angelehnt ist die Sache an x86.

Statt zB.

Code:
; wenn A=B dann tu was, wenn nicht dann nicht

MOVF A, W
SUBWF B, W

SKPZ
GOTO tunix

; tuwas, zB. 
BSF GPIO, 1
BSF GPIO, 2
BCF GPIO, 3

tunix

kann man dann

Code:
CMP8_FF A, B
CIF_E
  BSF GPIO, 1
  BSF GPIO, 2
  BCF GPIO, 3
CFI

schreiben. Das CMP... ist der Vergleich, CIF... ... CFI der IF Block, der nur ausgeführt wird, wenn die angegebene Bedingung erfüllt ist.

Folgende Vergleiche gibt es im Moment:
CMP8_FF mem, mem
CMP8_LF value, mem
CMP8_FL mem, value

(ok, ich muss mich korrigieren, W gibt es noch nicht... noch)

und CMP16BE_FF (compare 16bit big endian mem, mem)

Die 8bit CMPs erzeugen 2 Programmwörter, der 16bit CMP erzeugt 6 Wörter.
Damit man damit auch nochwas anfangen kann, gibt's dafür auch bedingte Befehle, und zwar 4 Kategorien:

CDO_...

führe die nächste Anweisung aus, wenn Bedingung ... erfüllt (Umkehrung zu SKP../BTFS..)

CJMP_... LABEL
CCALL_... LABEL

springe zu label, wenn Bedingung erfüllt (GOTO/CALL), und die wichtigste:

CIF_...

CFI

führe alles, was zwischen CIF_.. und CFI steht, aus, wenn die Bedingung erfüllt ist (sonst nicht). Da können auch ganze Kolonnen von Anweisungen drinnen stehen, Aufrufe an Unterprogramme, andere CMP... CIF... CFI Blöcke usw.

Folgende Bedingungen gibt es im Moment:
A (also zB. CIF_A, CDO_A, usw.) - above, der erste Wert beim Vergleich ist größer als der 2.
AE - above or equal
E - equal
NE - not equal
BE - below or equal
B - below

Daneben gibt es noch Bedingungen um einzelne Bits zu testen:

BS - bit set
BC - bit clear

wobei wie bei BTF die Speicheradresse und dann das Bit angegeben werden müssen, also zB.

Code:
CIF_BS mem, bitnr
  ; tuwas
CFI

Für _BS und _BC muss vorher kein CMP ausgeführt werden (wofür auch...). Sowas ist übrigens nicht sinnvoll:

Code:
CMP8_FF A, B

CIF_AE
  MOVLW 0x12
  ADDWF X
CFI

CIF_B
  MOVLW 0x2
  SUBWF X
CFI

weil der erste If-Block die Flags überschreibt. Müsste dann so aussehen:

Code:
CMP8_FF A, B
CIF_A
  MOVLW 0x12
  ADDWF X
CFI

CMP8_FF A, B
CIF_B
  MOVLW 0x2
  SUBWF X
CFI

Ein else gibt es (noch?) nicht. Das Beispiel würden die Makros so realisieren:

Code:
; CMP8_FF A, B

	MOVF	A, W
	SUBWF	B, W

; CIF_A
	SKPNC	
        GOTO B_END_1

B_START_1

        MOVLW 0x12
        ADDWF X

; CFI
B_END_1

; CMP8_FF A, B

	MOVF	A, W
	SUBWF	B, W

; CIF_B

	SKPZ
	SKPC

        GOTO B_END_2

B_START_2

        MOVLW 0x2
        SUBWF X

; CFI

B_END_2

Ich hab mich bemüht die Makros so sparsam mit Programmwörtern umgehen zu lassen wie es geht. Labels setzt er dafür mehr als nötig, aber die stören ja net. Das Makro zur automatischen Durchnummerierung sieht ziemlich lustig aus, funktioniert aber.
Die Labels B_START..., B_END..., B_NUM_START, B_NUM_END und B_DC_... bitte nicht benutzen, sonst kommt sonstwas bei raus.

Da ich es noch nicht gesagt hab: Das ist im Moment alles BETA oder gar ALPHA! Mir sind bisher keine Fehler aufgefallen (auch nicht bei Verschachtelungen), aber ausschließen will ich es nich. Also Benutzung auf eigene Gefahr.

Ein paar Sachen will ich auch noch hinzufügen (zB. if overflow, if zero und sowas), vielleicht bekomm ich es sogar hin, die Bedingung in die IFs reinzunehmen (so wie CIF A E8 B ... für if A=B (8bit), oder CIF A BS 3, wenn das 3. Bit von A gesetzt ist).
Im Moment stecken da vielleicht 4 Stunden Arbeit drinnen, entsprechend steht noch so ziemlich garnix fest.
Getestet hab ich bisher auch nur auf einem 12F629, und von Bänken haben die Makros noch keine Ahnung. Außerdem hab ich keine Ahnung, ob das mit objektcode verträglich ist.

So, nun genug der Warnungen, hier das Makro: www.i-hasser.net/pic_asm/makro4.inc

Für diejenigen, die sich die Makros mal angucken wollen: Die Blöcke sind per BSTART, BEND und BSKIP realisiert, wobei BSKIP den nächsten Block überspringt. Der Rest ist dann eigentlich trivial, außer vielleicht noch CDO_B und CIF_A, die sind etwas komplexer (ich hab leider keine einfachere Möglichkeit gefunden).

Ach ja, nochwas: CDO... bezieht sich auf eine einzelne Anweisung. 2 CDOs hintereinander funktionieren nicht, genausowenig CDO... CIF... - es funktionieren wirklich nur einzelne Anweisungen.
 
Schöne Sache!
Erinnert mich an meine 4-Bit Assembler Zeit in den 90ern (Actron AB, das schnucklickste Telefon mit Antwortbeanrufer was es je gab) oder gar Z80 vor 20 Jahren (wie die Zeit vergeht). Makro-Sammlungen gehörten da auch immer dazu.
Hätte nicht gedacht, dass Du mal in die Embedded Welt absteigst, dann sogar noch PIC Programmierung. ;D
Die PICs hab ich ja selbst nie programmiert, allenfalls mal in einem Konzept für irgendeine Erweiterung von ich weiss nicht mehr aufgenommen. Wurde wegen dringender anderer Projekte nicht weiter verfolgt...

Wollte gerade für Dein Lüftersteuerungsprojekt den C167 (mit dem Core hatte ich ein paar Jahre zu tun) statt PIC vorschlagen, aber preislich sind die PICs schonmal unschlagbar.
 
Na macht ja auf dauer auch keinen Spaß immer nur solche GHz-Boliden zu programmieren, bei den PICs kann man wenigstens noch mit dem Multimeter nachmessen, ob sie auch das richtige machen ;).

Zu dem C167 hab ich nicht so viel gefunden (Reichelt und Conrad haben ihn auch net), aber >64kB Speicher klingt natürlich schonmal gut, da kann der 12F629 mit 64byte nicht ganz mithalten ;). Wie teuer ist der denn so ungefähr? Glaub aber, dass der ein bisschen überdimensioniert ist, die Hardware in den PICs reicht ziemlich genau für das aus, was ich bei der Lüftersteuerung brauch.
Die Geschwindigkeit könnte ein bisschen knapp werden, aber notfalls nehm ich die 20MHz Modelle, das sollte dann auch dicke reichen. Das Steuerungsprogramm ist im Moment noch ziemlich klein, irgendwas um die 300 Wörter. 1024 gehen rein, in die größeren gehen dann bis zu 8kWorte rein, das sollte locker reichen.
 
*g* ich dachte als ich die Überschrift las, dass du dir eine ASIC-CPU mit abgespecktem PIC-Befehlssatz baust. Bist aber doch n Softie ;)

Ein C167 ist sicherlich was Schönes, aber zur Lüftersteuerung IMHO echt überdimensioniert. Könntest ja gleich eine SPS nehmen und die Lüfter als dezentrale Peripherie per echtzeitfähigem Bus ansteuern 8)
 
*g* ich dachte als ich die Überschrift las, dass du dir eine ASIC-CPU mit abgespecktem PIC-Befehlssatz baust. Bist aber doch n Softie ;)

Ein C167 ist sicherlich was Schönes, aber zur Lüftersteuerung IMHO echt überdimensioniert. Könntest ja gleich eine SPS nehmen und die Lüfter als dezentrale Peripherie per echtzeitfähigem Bus ansteuern 8)

Kommt vielleicht noch... aber dann nicht als ASIC, sondernd auf Platinen ;D.
 
Ein C167 ist sicherlich was Schönes, aber zur Lüftersteuerung IMHO echt überdimensioniert.
Wenn noch Temperaturüberwachung, Pumpensteuerung, LCD, USB und weiss der Geier noch dazu kommt, man schon nen Haufen SW und Entwicklungswerkzeuge hat, sieht's schon anders aus.
Für mich privat würde ich einen 167er nehmen, für die Massenproduktion eher nicht.

Aber ich hab eh keine Zeit (und Lust) dafür, bin mit 40h-50h pro Woche Embedded & drum herum beruflich gut genug bedient.
 
Zuletzt bearbeitet:
War auch nicht untätig. Inzwischen gibt's Makros um Variablen zu deklarieren (inklusive Typ, also zB. "declare16be x"), Operationen die entsprechend dem Variablentyp und den Argumenten agieren (zB. add x, FV, y, 123 -> x=y+123 mit den Typen aus x und y, wobei zB. add x, FV, x, 123 auch geht), und halbwegs normale if-statements (zB. cif a, equal, b ... cfi).
Bei den Makros fehlen zwar ein paar Sachen in gpasm, aber da hat trotzdem einer mitgedacht, mit dem C Präprozessor wär das zB. nicht möglich gewesen, obwohl der ja auch ziemlich leistungsfähig ist.
 
Zuletzt bearbeitet:
Zurück
Oben Unten