Ich versuche seit stunden eine möglichkeit zu finden meinen Speicher optimal auszunutzen und würde gerne in mein SRAM einige Bytes ablegen, das sind keine Variablen sondern Konstante die ich aber mit einem Pointer ansprechen muss. Das EEPROM ist bereits anderwertig belegt. Nun zu meinem eigentlich Problem, ich wollte gerne per AVR-Studio 4 den SRAM direkt beschreiben. Dafür gibt es ja angeblich solche tollen Befehle .db und .dw. Da ich ein Tiny26 nutze, habe ich natürlich auch nur ein SRAM mit 8 Bit! somit fällt .dw für mich sowieso weg. Nun habe ich schon überall nach einer erklärung gesucht wie ich nun meine Liste einfügen. Ich stelle euch mal vor was ich beisher gemacht habe. ... .dseg .org $0060 (habe bereits gemerkt das ich org weglassen kann) .db 9,25,37,40 .cseg loop: ldi YL,sram_start ld R16,Y out porta, R16 rjmp loop Ich habe auch schon versucht direkt das SRAM auszulesen mit lds aber egal welche teile ich auslese ich bekomme total flasche werte raus und auch wenn ich die werte im db ändere dann ändern sich die werte nicht, immer noch totaler müll. Als Hinweis, ich programmiere nur in Assembler, und wie oben erwähnt habe ich ein Tiny26 und der SRAM beginnt ab 0x60 ($0060). Und der SRAM hat 128 Byte größe. Ich hoffe ihr könnt mir helfen.
Der SRAM Speicher hat nach dem Reset undefinierte Werte, und kann auch nicht per ISP o.ä. "Vorprogrammiert" werden. (Der Ram-Inhalt ist auch nicht im HEX-File) Du müsstest also deine Konstanten im Flash ablegen, und beim Programmstart in das SRAM umkopieren, oder gleich dort lassen. (So macht das auch der C-Compiler, wenn man Variablen vorbelegt) /Ernst
Genau das habe ich vermutet ... aber gehofft das es nicht so ist :( Also müsste ich für meinen Pointer doch wieder auf den EEPROM umsteigen. Wenn ich die Daten aus dem Flash ins SRAM kopiere brauche ich mindestens 2 Befehle ... ldi R16,irgendeinWert sts 0x60,R16 gibts da vllt eine kürzere Variante, also das ich den Wert direkt in den SRAM schreiben kann beim Start des Programms, dann wäre es vllt doch noch eine überlegung ...
Einfach einen Bereich mit Konstanten im Flash ablegen, und beim Start in einer Schleife ins SRam kopieren? Braucht nur beim Start ein bischen Zeit, und danach ist der Zugriff aufs SRAM schnell... /Ernst
Müssen denn diese Konstanten während des Programmlaufs geändert werden? Wenn nicht, dann lässt du das Schreiben ins SRAM für die Konstanten ganz weg und liest direkt mit dem LPM-Befehl aus dem Flash. Bis auf den AT90S1200 haben den alle drin. ldi ZL, Low(Daten*2) ;StartAdresse setzen. ldi ZH, High(Daten*2) lpm R16, Z ;Wert in R16 laden. Und wenn du eine Tabelle abgrasen willst, pack den: lpm R16, Z+ ;Wert in R16 laden. in eine Schleife. Das + bedeutet, dass das Z-Register automatisch erhöht wird. Gruss Jadeclaw.
Darüber bin ich gerade am grübbeln, aber irgendwie habe ich wohl ein Brett vorm kopf, denn mir fällt dafür keine schleife ein. Da ich nicht alle Register belegen kann weiß ich nicht wie ich die daten per schleife jedesmal in ein (oberes)register ziehen kann. .equ erste_info = 0x05 .equ zweite_info = 0x38 .equ dritte_info = 0x44 ... ca 50 daten loop: ldi R16,erste_info sts y+,R16 und hier fällt mir nicht ein, wie ich ihm sagen soll was den das nächste ist was er in R16 laden soll. rjmp loop Ich muss zugeben, ich habe nicht gedacht das es doch noch so umständlich wird ... Eine 2. Frage noch nebenbei zu db und dw ... Ich weiß das die Befehle mit eseg funktionieren um das EEPROM zu beschreiben. Aber ich habe es auch schon mitten im asm code gesehen, und angeblich soll es da auch funktionieren ?! Also es stand mitten drin aber ich weiß nicht was der befehl dann zur folge haben soll, da es ja kein Befehl direkt ist sondern nur zum assemblieren. http://www.avr-asm-tutorial.net/avr_de/quellen/Lcd4IncC.asm Habe das da gelesen ... habe das programm mir nicht weiter angeschaut, nur das .db war mir aufgefallen.
.db sagt dem Assambler einfach dass hier ein Datenbyte kommt, er die Daten also nicht in Code übersetzten soll. .dw macht das gleiche mit einem Datenwort. Aber genaueres sagt dir die Hilfe deines Assamblers.
.db und .dw funktioniert auch im .cseg, also im Flash. In Verbindung mit Labels kannst du mit LPM über den Z-Pointer jederzeit darauf zugreifen. Aber das wurde weiter oben schon erklärt... ...
Das sind Konstanten, die im Flash abgelegt werden. Werden also wie normale opcodes mit ins Flash kopiert, man muss nur aufpassen das der AVR nie versucht die auszuführen. können dann mit der LPM Anweisung (drei Taktzyklen) gelesen werden. /Ernst
Wow, es hat gerade klick gemacht ;) Danke für die schnellen Antworten ... habe das mit dem LPM zwar mal gelesen aber noch nie bisher getestet ... werde mich morgen damit mal auseinandersetzen, dümmer machen kann es einen bestimmt nicht :) @Jadeclaw Du hast da YH und YL gewählt, ist das überhaupt nötig beim Tiny 26 ? und was ist den (daten*2), also muss ich für daten die position angeben im flash? Wenn ja wie finde ich die den raus, oder vorher einfach org $0000 setzen ? Wie ihr merkt, fehlt mir da noch ein wenig das Feingefühl und die Praxis, die ich gerade auffrischen möchte :) Nochmals Danke für die ganzen Infos, auch auf die (aus eurer Ansicht) dusseligen Fragen ... :)
Der AVR kennt keine 16Bit-Ladebefehle, deshalb muss man ZH und ZL separat laden. Das mit den 'Daten*2' hat einen einfachen Grund: Adressen beziehen sich für den Assembler immer auf 16bit-Worte, die Adressindexierung über X/Y/Z-Register beziehen sich aber auf 8Bit-Bytes, deshalb das 'Daten*2'. 'Daten' ist das Label, *2 verdoppelt den Wert, damit man den richtigen Adresswert für den Byte-Zugriff hat. Und man braucht dafür keinen Extra-.org setzen, wenn der Assembler auf ein Label mit daran folgenden .db oder .dw-Anweisungen findet, setzt er automatisch den richtigen Adresswert ein. So bringt man Daten in den Flash: Text: .db "Dies ist ein Test", 0x0D, 0x0A, "Zweite Zeile", 0x00 Abruf: ldi ZL, Low(Text*2) ;StartAdresse setzen. ldi ZH, High(Text*2) lpm R16, Z ;Wert in R16 laden. Der Assembler ersetzt nun 'Text' durch die beim Assemblieren errechnete tatsächliche Adresse. Lässt du das Stück Code laufen, landet der erste Buchstabe ('D') in R16. Übrigens, LPM geht nur mit dem Z-Register. Gruss Jadeclaw.
> und was ist den (daten*2), also muss ich für daten die position > angeben > im flash? Wenn ja wie finde ich die den raus, oder vorher einfach > org > $0000 setzen ? 'daten' ist das Label, das vor dem '.db' zu stehen hat. Dieses Label ist für uns Menschen ein (leicht merkbares) Wort, für den Compiler aber nur eine Zahl, in diesem Fall die (doppelbyte-orientierte) Adresse im Flash. Da LPM aber die Adresse byte-orientiert braucht, muss sie beim Setzen des Z-Pointers verdoppelt werden. ...
so habe ich das letzens gemacht. Erst habe ich den nötigen Platz reserviert, und dann die Sachen ins SRAM geschrieben. Und danach erst zum eigentlichen Programmanfang. Interessieren würde mich ob man auch halbe Bytes reservieren kann da ich in diesem Beispiel jeweils nur 4 Bits ablege. .DSEG ;Reserve jeweils 1 Byte eim SRAM Voll1: .byte 1 Voll2: .byte 1 Voll3: .byte 1 Voll4: .byte 1 ldi temp, 0b10100000 ;Speichere Schrittfolge im SRAM um Register zu sparen sts Voll1, temp ldi temp, 0b10010000 sts Voll2, temp ldi temp, 0b01010000 sts Voll3, temp ldi temp, 0b01100000 sts Voll4, temp ldi temp, 0b10100000 lds temp, Voll1 ; hier wird dann die Speicherstelle Voll1 ausgelesen bzw. nach temp geladen out porta, temp
Nun habe ich das wie folgt aufgebaut: char: .db 0x43,0x4F,0x52,0x53 ldi R30,low(char*2) ldi R31,high(char*2) lpm R16,z+ lpm R17,z Ich wollte das nur mal testen, aber nun schreibt der assembler mir: lpm R16,z+; unsupported insruction on ATtiny26 :( Hat einer eine Idee wie ich es ggf umgehen kann oder ob das beim tiny26 wirklich net möglich ist :(
Ok, die Frage hat sich ein wenig vereinfacht ich habe herausbekommen das man ja einfach folgendes tun kann um an den 2. wert zu gelangen. char: .db 0x43,0x4F,0x52,0x53 ldi R30,char*2 ;ldi R31,high(char*2) (den teil habe ich raus genommen da es den nicht gibt, besser gesagt ich kann ihn nicht direkt auslesen lpm R16,z inc R30 oder ldi R30,(char*2)+1 lpm R17,z Schade das z+ net geht, aber so gehts auch in einer schleife wird der eine inc befehle nicht soviel resourcen ausmachen ...
Prinzipiell funktionierts ganz einfach: Irgendwo definierst du wo das ganze hin soll im SRAM .equ SRAMStartposition = 0x60 (wenns das das .org gewesen sein sollte) dann hast du dein Programm ... bla bla bla LDI r31,high(Tabelle<<1) LDI r30,low(Tabelle<<1) LDI r29,high(TabelleEnde<<1) LDI r28,low(TabelleEnde<<1) LDI r27,high(SRAMStartposition) LDI r26,low(SRAMStartposition) loop: LPM r16,Z ;Kopiert vom Programmspeicher inc r30 ;Erhöht Z cpi r30,0x00 brne loop2 inc r31 loop2: STS X+,r16 ;Speichert r16 im SRAM cp r28,r30 ;Vergleicht ob schon am Ende brne loop cp r29,r31 brne loop weiter im Code .. bla bla bla Programm fertig. dann kannst du folgendes machen Tabelle: .db 0x00,0x01,0x02 ... (sollte gerade Anzahl haben) .db 0x10,0x11 .... TabelleEnde: Fertig
Upsa .. Fehler mit eingebaut STS X+,r16 ;Speichert r16 im SRAM FALSCH ST X+,r16 ;Speichert r16 im SRAM RICHTIG
> Hat einer eine Idee wie ich es ggf umgehen kann oder ob das beim > tiny26 wirklich net möglich ist :( Die Classics und die alten Tinys unterstützen LPM nur in seiner Urform, kopieren das adressierte Byte also nach R0. Ich helfe mir auf den Tinys meist damit, dass ich je ein unteres Register für 0 und 1 reserviere und dann den Zugriff so organisiere: lpm ;nächste Tondauer aus Liste nach R0 holen mov dauer,r0 ;und in Tondauerzähler kopieren add zl,eins ;Pointer erhöhen adc zh,null ;evtl: Übertrag auch Das Beispiel stammt aus einem Melodiegenerator mit Tiny15. ...
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.