hallo zusammen,
ich habe eine frage zu meinem code (siehe unten). ich bin anfänger in
maschinensprache. zuletzt habe ich einen commodore 64 in 6510
programmiert, seitdem schlummern meine bemühungen dort.
ich habe für meine modell-kirmesfahrgeschäfte die lauflichter und
motorsteuerungen alle mit verschiedenen atmels aufgebaut. für ein
fahrgeschäft, dass sehr wenig platz auf dem mittelbau hat, habe ich mir
jetzt ein paar attiny12 kommen lassen (sowohl dip zum testen als auch
smd für die endversion).
hier ein paar rahmendaten:
plattform: pc mit bascom, stk500
zielprozessor: attiny12 (ohne sram, die tücken hab ich schon gelöst)
das programm läuft, lädt aber nicht die daten aus dem .db-bereich zur
ausgabe. im simulator lädt er mit den z-pointer ordentlich, aber lpm
liefert müll. da ich anfänger bin, steh ich da jetzt mit meinem kurzen
hemd und frage mich, wieso das nicht geht. ich bitte um hinweise, wie
ich den code auf einem attiny12 ans rennen kriege (bitte keine
alternativen prozessorvorschläge oder plattformwechsel).
hier der code:
>im simulator lädt er mit den z-pointer ordentlich, aber lpm liefert müll.
Was heißt "liefert müll"? Irgendwelche Werte müssen ja nach lpm in r0
erscheinen. Ändere das erste Datenbyte mal von 0 in 53 und check das
allererste lpm. Erscheint 53 in r0 oder nicht?
in r30/r31 (zl/zh) steht im simulator 67/00 und in r0 steht f8. diese f8
(statt der beabsichtigten 00) schiebt er mir dann in r16 und das dann
auf den port. und eine f8 finde ich nirgendwo. das ist das, was der
simulator liefert, der prozessor wirft mir als letzte 5 bit laut
invertiertem led-status auf dem stk-500 (attiny12 mit 6 bit ausgabe,
aber einer weniger wegen reset für isp) xxx11000 aus.
Oberflächlich fallen mir zwei Dinge ins Auge. ADIW ist für Registerpaare
vorgesehen und nicht für Einzelregister:
falsch: adiw zl, 1
richtig: adiw zh:zl, 1
und die Warteschleife ist imho für Lauflicht zu kurz (hab ich aber nur
geschätzt, nicht gerechnet)
ich bin ja für jeden tipp dankbar - und habs ausprobiert. bascom mag die
notation zh:zl nicht und sagt "low pointer register expected" und bricht
den compiler mit error 200/201 ab. ich hatte die online-hilfe auch so
verstanden, dass man bascom da nur das low-register angibt.
die warteschleife ist schon ok so. ich habe ja ein funktionierendes
lauflicht, was aber immer wieder die daten direkt auf den port schreibt
statt über data-bereiche. da ist die gleiche warteschleife drin und es
funktioniert prima:
http://macs-modellwelt.de/video/octopussy/20091204-krakenarm.avi (der
ampelfarbene arm rechts arbeitet mit dem attiny12, die masten links mit
attiny2313).
Hoppla, wie mir ein Blick ins Datenblatt verriet, verfügt der ATtiny12
gar nicht über die Instruktion adiw!
@Markus: Definier Dir zwei Register _0 und _1, z. B.
.def _0 = r20
.def _1 = r21
und setz sie beim Programmstart entsprechend mit ldi auf 0 bzw. 1.
Ersetze anschließend alle "adiw zl,1" durch
add ZL, _1
adc ZH, _0
Läuft das Programm dann korrekt?
so, an alle zusammen: das war mal richtig cool, denn der code läuft nach
einigen modifikationen und etwas ausprobieren. und das in unter 3
stunden!
der tipp mit "adiw geht nicht auf dem attiny12" war sehr gut. kann er
wirklich nicht, der workaround mit den konstanten-registern klappt. lpm
z+ ist glaube ich noch fortschrittlicher uns somit auf dem alten ding
nicht implementiert. jetzt verstehe ich auch den hinweis "not
recommended for new design" im datenblatt.
spaßig an der sache: der simulator tut so, als könne der attiny12 aber
adiw. auf dem simulator klappte das prima. stützt sich der simulator auf
die def-files oder denkt der sich lustig was aus?
ein weiteres problem, was ich vermute und jetzt einfach mal abgestellt
habe: der attiny12 hat ja kein sram, also auch ein stack-problem. im
vorbeigehen habe ich irgendwo gelesen, dass er dafür die letzten 3
doppel-register nimmt. wenn das stimmt, muss ich mich nicht wundern,
wenn nach einem rcall mein z-register wuschig ist und nur noch mist
enthält. da die warteschleife jetzt eh nur noch einmal genutzt wird,
habe ich sie in den hauptcode verschoben und schenke mir den
unterprogramm-aufruf. so spare ich mir das retten vom z-register.
was ich mich jetzt noch frage: er hat im obigen code das
licht-daten-label "licht:" nicht korrekt übersetzt, es stand zwei bytes
zu früh (nach einblick mit einem hex-editor ins hex-file). jetzt addiere
ich 2 drauf und es geht.
entrümpelt habe ich den code jetzt auch noch etwas und nun sieht er so
aus und klappt (wer will, darf ihn verwenden):
1
$asm
1
.def Zaehler1 = R17
2
.def Zaehler2 = R18
3
.def Muster = R16
4
.def Wiederholung = R19
5
.def _0 = r20
6
.def _1 = r21
7
8
rjmp main ' zum hauptprogramm
9
10
Main:
11
ldi muster ,&b00011111 ' 3 Nullen und 5 Einsen in Universalregister
12
!Out Ddrb , Muster ' An Datenrichtungsregister
13
14
Mymain:
15
16
ldi _0,0
17
ldi _1,1
18
ldi zl, low(licht * 2)
19
ldi zh, high(licht * 2)
20
add ZL, _1
21
adc ZH, _0
22
add ZL, _1
23
adc ZH, _0
24
ldi wiederholung, 5
25
26
Vorwaerts:
27
lpm ' durch z-puffer adressiertes byte in R0 laden
28
add ZL, _1
29
adc ZH, _0
30
mov muster, r0 ' r0 ins muster schieben
31
!Out Portb , muster ' und auf portb ausgeben
32
lpm ' nächstes datenbyte
33
add ZL, _1
34
adc ZH, _0
35
mov zaehler1,r0 ' r0 in zaehler1 schieben
36
Outer2:
37
ldi zaehler2, 255
38
Inner2:
39
nop
40
nop
41
nop
42
dec zaehler2
43
cpi zaehler2,0
44
brne inner2
45
dec zaehler1
46
cpi zaehler1,0
47
brne outer2
48
49
dec wiederholung ' wiederholungszähler um 1 verringern
50
brne vorwaerts ' solange ungleich null, wieder nach anfang des lichtmusters
51
52
rjmp mymain ' endlosprogramm, wieder an anfang springen
weil ich 20 tiny12 bestellt hab :) und das einzige, was alle
atmel-prozessoren mit meiner lauflicht-applikation haben, ist große
langeweile. der arme fräst sich ja nur durch NOPs. da muss nix erweitert
werden und es reicht das, was da ist.
Glückwunsch.
>der simulator tut so, als könne der attiny12 aber adiw.
Das dürfte eigentlich nicht sein.
>stützt sich der simulator auf die def-files oder denkt der sich lustig was aus?
Öffne doch mal die zugehörige def-Datei in einem Editor und check, ob da
irgendwas mit lpm drin verzeichnet ist, etwa ein Eintrag der Art
INSTRUCTION_LPM = NO.
>ein weiteres problem, was ich vermute und jetzt einfach mal abgestellt>habe: der attiny12 hat ja kein sram, also auch ein stack-problem.
Der ATtiny12 hat kein SRAM, aber sehr wohl einen Stack, nämlich einen
3-Level-Hardware-Stack. Er besteht aus drei 9 Bit breiten
Extra-Registern, die vom Programm aus nicht addressierbar sind. Dieser
Stack wird für Interrupts und normale Subroutinen verwendet. Du kannst
also problemlos rcall und ret verwenden, solange die
Verschachtelungstiefe nicht größer als drei wird. Die drei
Stack-Register haben mit den Registern r0...r31 nichts zu tun.
>wenn das stimmt, muss ich mich nicht wundern, wenn nach einem rcall mein>z-register wuschig ist und nur noch mist enthält.
Nein, das hast Du falsch verstanden.
>er hat im obigen code das licht-daten-label "licht:" nicht korrekt>übersetzt, es stand zwei bytes zu früh
Sehr merkwürdig. Vielleicht werden die Datenbytes nach .DB von BASCOM
auf gerade Wortadressen ausgerichtet, aber das ist nur eine vage Idee.
>jetzt addiere ich 2 drauf und es geht.
Machs doch so und spar Dir die vier add/adc-Zeilen:
ldi zl, low(licht * 2 + 2)
ldi zh, high(licht * 2 + 2)
>entrümpelt habe ich den code jetzt auch noch etwas
Wenn Du noch was rauswerfen willst: cpi zaehler2,0 und cpi zaehler1,0
sind überflüssig, denn dec setzt ja schon das Z-Bit.
>irgendwas mit lpm drin verzeichnet ist, etwa ein Eintrag der Art>INSTRUCTION_LPM = NO.
Korrektur:
irgendwas mit adiw drin verzeichnet ist, etwa ein Eintrag der Art
INSTRUCTION_ADIW = NO.
so, die cpis sind auch noch raus - das war damals in
6502-maschinensprache auch so, dass das zero-flag automatisch gesetzt
wird. ich war mir hier nicht sicher, deshalb hab ich das cpi mit
reingesetzt, obwohl ich wie damals schon runterzählende schleifen
gemacht habe, um bei 0 den branch zu setzen.
die veränderungen beim setzen des z-registers auf
1
ldi zl, low(licht * 2 + 2)
2
ldi zh, high(licht * 2 + 2)
hat wieder alles zernagelt, dann indizierte er wieder falsch und die
liuchtmuster passen nicht mehr. alternativ habe ich nur 1 draufaddiert,
ging genauso in die hose (mit dem identisch falschen lichtmuster). ich
schieb das jetzt mal dreisterweise auf den bascom 1.11.9.1, den ich hier
benutze. ich habe es auch noch mit dem ! vor low und high probiert,
damit er die befehle nicht mit basic-tokens verwechselt (siehe out),
aber das produziert auch nicht das gewünschte. ich nehme das jetzt als
gegeben hin und freu mich, dass es geht, wobei ich das im normalfall
gern exakt wüsste. die lauflichtsteuerungen sind nicht mein hauptziel
beim modellbau.
danke für die hinweise zum hardware-stack. in das dat-file von bascom
habe ich auch reingesehen, die sperren oder erlauben da nichts mit
befehlen, wenn ich das jetzt auf die schnelle verstanden habe. dort
steht nur was über ram-ausstattung, i2c erlaubt oder gesperrt etc.