Hi, ist es möglich, in Assembler für z.B. den ATtiny13a einen relative jump mit einem Wert aus einem Register auszuführen? Bzw. was ist die schnellste Methode, also die mit der geringsten Anzahl benötigter Taktzyklen, um abhängig von einem Wert aus dem RAM oder einem Register jeweils einen anderen Code auszuführen? Also sowas ähnlich dem Befehl switch (var) { case 1: //do something when var equals 1, for example jumping to another function break; case 2: //when var equals 2, jump to another function break; } in C. Ziel ist es, Code, der NICHT im Flash-Speicher des AVR-RISC-uCs ist, auszuführen. Sofern das möglich ist, ohne nacheinander jeden möglichen Wert mit den entsprechenden Befehlen zu vergleichen, was sehr ineffizient wäre und sehr viel Zeit kostet, dann würde das mir einige neue Möglichkeiten bieten: - Ausführen von Code aus dem RAM: Ich könnte Code testen, ohne immer neu zu flashen - Programmieren (und deutlich mehr Speicher für das Programm) durch das Speichern eines Hexfiles auf einer uSD-Karte. Die Firmware könnte den Code auf der uSD-Karte auslesen, in den RAM laden und ausführen. -> Programmieren ohne nötigen Programmer und: - die Firmware könnte ein Tool bereitstellen, das eine Programmierung ohne zusätzlichen Computer ermöglicht!!! Ohne eine zweite MCU zu brauchen, die die andere über isp flasht. Noch eine zweite Frage: Wie greift man in Assembler (ich nutze avra auf einem Linux-Desktop-PC zum Assemblieren im Terminal und avrdude, kompatibel mit Atmel-/AVR-Studio) auf den RAM zu? Ich meine damit nicht, einer Variable einen Wert zuzuordnen, sondern an einer festen Adresse ein Byte zu speichern. War das nicht irgendwie so, dass nach dem SREG usw. ab 0x60 oder so einfach der RAM losging? Danke für eure Hilfe schonmal jetzt von mir. Ich habe vor, AVRs in richtige Computer zu verwandeln. Sie haben zwar wenig Leistung, sind aber sparsam in Sachen Energieverbrauch. Ich überlege sogar, das Prinzip von BIOS, Bootloader (Bootstrapping) und Kernel auf AVRs anzuwenden (ungeachtet des Boot-ROM und dessen, dass Code normalerweise aus dem RAM ausgeführt wird) So könnte jeder, der gerne mal ein Betriebssystem schreiben würde, klein anfangen, da x86 Assembler ja ganz schön komplex ist. Vielleicht auch ein C-Compiler onboard? Das würde ich dann auf Github veröffentlichen ;) Thanks!
Auch wichtig: was haltet ihr davon? Hätte jemand Interesse, egal ob in C oder Assembler mit mir zusammen daran zu arbeiten? Assembler wäre v.a. bei den zeitkritischen Stellen wichtig (vielleicht als inline-assembler?) Was auch cool wäre, wäre ein leichtes Programmieren von GUIs (graphic user interface) Die Ein-/Ausgabe könnte sowohl mit Tastern/LEDs -> ähnlich TPS (tastenprogrammierbare Steuerung) als auch über ein serielles Signal (-> PC) oder über einen weiteren Mikrocontroller, der als GPU fungiert, an ein SPI/i2c Display-Modul sein. An dieser Stelle wäre auch eine Implementation von "Treibern" cool So könnte man auch EEPROM ICs über Treiber andprechen / von denen booten, Multiboot, externer RAM -> erweitern,....... Ihr seht schon, ich bin da sehr kreativ, aber vor allem auch offen für Vorschläge anderer (außer solche wie "Lass den Quatsch doch einfach. Was bringt's dir denn?! Zweckentfremdhng einer MCU und Zeitverschwendung..."
Pascal schrieb: > Ziel ist es, Code, der NICHT im Flash-Speicher des AVR-RISC-uCs ist, > auszuführen. Genau daran scheitert Deine Idee.
Hmmm schrieb: > Pascal schrieb: >> Ziel ist es, Code, der NICHT im Flash-Speicher des AVR-RISC-uCs ist, >> auszuführen. > > Genau daran scheitert Deine Idee. Das denke ich nicht. Der Flashspeicher bekommt eine Firmware, die dann vergleichbar mit einer Virtual Machine ein OS auf einem OS laufen lässt. Ein Code, der zur Firmware gehört, ist erforderlich, um die Befehle zu laden und auszuführen. Die Zeitverluste sind je nach Antwort auf die Frage entweder tolierierbar oder eben etwas schlechter.
Dann ist das aber keine Codeausführung aus dem RAM mehr, sondern die Emulation einer kompletten CPU mit allen damit verbundenen Nachteilen, und das auf einem ATtiny13A? Das Ziel, AVR-Code schnell testen zu können, erreichst Du schneller und besser mit einem Bootloader oder einem PC-basierten Simulator.
Hmmm schrieb: > die Emulation einer kompletten CPU mit allen damit verbundenen > Nachteilen, und das auf einem ATtiny13A? Naja, genau genommen die Emulation eines ATtiny13a der Code aus dem RAM ausführt auf einem ATtiny13a der Code aus dem Flash ausführt. Vielmehr ist es allgemein für AVRs gedacht, war nur ein Beispiel, der kleine Flashspeicher könnte mit einer mikroSD Karte von 1KB auf 32GB erweitert werden, und eine Programmierung ohne PC ohne die Opcodes auswendig zu lernen wäre möglich, wobei der Code im Flash (Firmware) sich nicht ändert
Pascal schrieb: > Naja, genau genommen die Emulation eines ATtiny13a der Code aus dem RAM > ausführt auf einem ATtiny13a der Code aus dem Flash ausführt. Und genau deshalb wirst du scheitern. Man braucht sich einfach nur die Größen von RAM und Flash anzuschauen. Der RAM ist immer deutlich kleiner. Außerdem wird die Emulation immer ganz erheblich langsamer sein als die Ausführung von Code aus dem Flash. RAM lesen ist teuer, zwei Takte pro Byte und das zusätzlich zur eigentlichen Arbeit der Instruktion. Zum Vergleich: bei der Ausführung aus dem Flash werden die Befehlsworte parallel zu ihrer Ausführung gelesen und zwar ein Wort (also zwei Bytes) pro Takt. Allein nur das Lesen der Instruktionen wird also vier mal langsamer erfolgen. > Vielmehr > ist es allgemein für AVRs gedacht, war nur ein Beispiel, der kleine > Flashspeicher könnte mit einer mikroSD Karte von 1KB auf 32GB erweitert > werden Damit könnte man zwar die Begrenzung der RAM-Größe umgehen. Der dazu nötige Layer für virtuellen Codespace würde aber die Sache nochmals erheblich weiter ausbremsen und vor allem auch die Laufzeiten des Codes völlig irregulär machen. Adé Echtzeit... > und eine Programmierung ohne PC ohne die Opcodes auswendig zu > lernen wäre möglich, wobei der Code im Flash (Firmware) sich nicht > ändert Du willst also nicht wirklich eine Emulation, sondern schlicht nur eine Interpretersprache realisieren. Das haben schon mehrere Leute gemacht. Mindestens ein solches Projekt findest du im Forum "Projekte und Code". Da ging es um einen Basic-Interpreter.
> Mindestens ein solches Projekt findest du im Forum "Projekte und Code". > Da ging es um einen Basic-Interpreter. Er könnte ja einen p-code Interpreter schreiben. Wenn UCSD-Pascal auf dem AVR läuft dann kauf ich mir auch mal wieder einen um die coole Nostalgie der 80er in Turbospeed zu geniessen. :-) Ansonsten würde ich sagen, wenn man so etwas will dann ganz bestimmt nicht auf einem AVR. Da nimmt man einen Controller der viel internen Ram hat und auch noch die Faehigkeit Code darin ablaufen zu lassen. In allen anderen Faellen begnuegt man sich mit einem guten Debugger... Olaf
Man kann doch gar keinen Code im RAM ausführen. Oder bei den Neuen doch?
Pascal schrieb: > Auch wichtig: > was haltet ihr davon? Super umständlich, wenn's auch viel einfacher ginge! Es gibt Controller die Code direkt aus dem RAM ausführen können, wie MSP430 und ARM. Da gibt's auch sehr Energie Sparende (zB EFM32) und günstige (zB STM32F0). Insbesondere ARM ist sogar dafür/ausgelegt/, dass man dafür Betriebssysteme schreibt, denn es unterstützt unprivilegierte Modi, Speicherschutz, und effiziente Kontextwechsel. Also ausgerechnet AVR dafür zu nehmen ist nur unnötige Arbeit mit zwangsweise mäßig gutem Ergebnis. Relative indirekte Sprünge sehen IIRC bei ARM z.B. so aus: add pc, r0 Es gibt sogar auch eine Anweisung welche Sprungtabellen direkt unterstützt. Viel einfacher als beim AVR... ;-)
Dr. Sommer schrieb: > Super umständlich, wenn's auch viel einfacher ginge! Es gibt Controller > die Code direkt aus dem RAM ausführen können, wie MSP430 und ARM. Und dafür gibt’s sogar fertige Betriebssysteme ;) Oliver
Oliver S. schrieb: > Und dafür gibt’s sogar fertige Betriebssysteme ;) Klar, aber so lernt man ja nix... gerade bei aktuellen ARMs ist die Programmierung von eigenen OS wunderschön elegant im Gegensatz zu z.B. x86.
Pascal schrieb: > ist es möglich, in Assembler für z.B. den ATtiny13a einen relative jump > mit einem Wert aus einem Register auszuführen? Du addierst den PC dazu und machst einen IJMP. Pascal schrieb: > Ziel ist es, Code, der NICHT im Flash-Speicher des AVR-RISC-uCs ist, > auszuführen. Also einen Interpreter + SD-Reader in nur 512 Worten, das ist sportlich. Ein ATmega2560 dürfte geeigneter sein. Pascal schrieb: > Ohne eine zweite > MCU zu brauchen, die die andere über isp flasht. Das dürfte erheblich schneller sein, als ein schnarchlahmer Interpreter. Du brauchst auch keinen 2. AVR, der AVR kann sich selber programmieren (SPM-Befehl).
Peter D. schrieb: > Ein ATmega2560 dürfte geeigneter sein. Oder ein ATMega1284. Hat zwar weniger Flash als der 2560 (128k statt 256k), aber dafuer mehr RAM, 16k statt 8k. Und es gibt ihn im DIP-Gehaeuse. Und er kann bis 20MHz :) EEPROM haben beide 4k. Der TO sollte sich aber auch ueberlegen, was er alles an Peripherie braucht: - Anzahl der Timer - Anzahl der Schnittstellen nach aussen (U(S)ART/I2C/SPI) Waere ja doof wenn er Anfaengt, und dann irgendwann feststellt das sein uC nicht genug Timer, etc. hat.
Na ja, der TO will’s halt sportlich: Pascal schrieb: > ATtiny13a Der hat immerhin 1k Flash und 64 Byte SRam. Mit ein paar Assemblertricks der Mobys und c-haters sollte das doch locker für ein emuliertes Linux ausreichen... ARM kann jeder ;) Oliver
Oliver S. schrieb: > sollte das doch locker für ein emuliertes Linux > ausreichen... Da faellt mir ein: Linux on an 8-bit micro http://dmitry.gr/index.php?r=05.Projects&proj=07.%20Linux%20on%208bit
Mit Tiny13? Illusorisch. Ein Mega128 sollte es da mindestens sein. Maschinencode aus dem SRAM auszuführen ist aber auch dort unmöglich. Eine Interpretersprache schon viel eher. Die Programme kann man gleich auf der angeschlossenen SD Karte belassen. Ich hab sowas mal mit einem Z80 gemacht. Programme befanden sich da noch auf einem EEPROM. Mehrere davon konnten gleichzeitig abgearbeitet werden- so ein Multitasking ist nicht allzu schwer zu realisieren. Kaj G. schrieb: > Da faellt mir ein: > Linux on an 8-bit micro Krass. Krass kastriert. Ein OS belastet auf 8er MCs mehr als daß es nützt.
Pascal schrieb: > Ich meine damit nicht, einer Variable einen Wert zuzuordnen, sondern an > einer festen Adresse ein Byte zu speichern. War das nicht irgendwie so, > dass nach dem SREG usw. ab 0x60 oder so einfach der RAM losging? Hi, hab's gerade ausprobiert. Meistens arbeitet man aber mit Predecrement oder Postincrement. (Das Listing wird sonst sehr schnell unübersichtlich.) Stichwort für ATMEL Doku: Indirect addressing (ist nicht ganz so trivial, wie es zunächst den Anschein hat.) ciao gustav
Pascal schrieb: > Noch eine zweite Frage: > Wie greift man in Assembler ... auf den RAM zu? > Ich meine damit nicht, einer Variable einen Wert zuzuordnen, sondern an > einer festen Adresse ein Byte zu speichern. Naja easy mit lds/sts oder indexiert mit ST/STD. c-hater schrieb: > Damit (SD Card Erweiterung) könnte man zwar die Begrenzung der RAM-Größe umgehen. Der dazu > nötige Layer für virtuellen Codespace würde aber die Sache nochmals > erheblich weiter ausbremsen und vor allem auch die Laufzeiten des Codes > völlig irregulär machen. Das ist auch total relativ. Für sehr vieles ist das immer noch mehr als schnell genug.
Karl B. schrieb: > Stichwort für ATMEL Doku: Indirect addressing (ist nicht ganz so > trivial, wie es zunächst den Anschein hat.) Hi, noch der Link: http://web.csulb.edu/~hill/ee346/Lectures/13-1%20AVR%20Addressing%20Indirect.pdf Seite 15 ist interessant. "...Each table entry (.DB) contains one byte. If we look at the first table entry we see 0b00111111 which corresponds to 3f in hexadecimal. Comparing this with the corresponding address and data fields on the left... Wait a minute - where did 06 come from?..." ciao gustav
:
Bearbeitet durch User
Danke für die Hilfe Karl B. schrieb: > Hi, > hab's gerade ausprobiert. Vielen Dank! Nur das Selfprogging ist für mich noch ein Rätsel
G.M. schrieb: > Das ist auch total relativ. Für sehr vieles ist das immer noch mehr als > schnell genug. Aus: Kaj G. schrieb: > Linux on an 8-bit micro > http://dmitry.gr/index.php?r=05.Projects&proj=07.%... „It takes about 2 hours to boot to bash prompt ("init=/bin/bash" kernel command line). Then 4 more hours to boot up the entire Ubuntu ("exec init" and then login)... Curiously enough, once booted, the system is somewhat usable. You can type a command and get a reply within a minute“ Relativ ist wirklich total relativ... Oliver
G.M. schrieb: > Krass. Krass kastriert. Ein OS belastet auf 8er MCs mehr als daß es > nützt. Deswegen emuliert man auch erstmal einen Core i5. Dann hat man wieder einen 64-Bit-Prozessor, auf dem sich das OS austoben kann.
Oliver S. schrieb: > Kaj G. schrieb: > Linux.. > Relativ ist wirklich total relativ... Meine Bemerkung bezog sich nicht auf diese Linux Installation sondern darauf, daß ein AVR für sehr viele Anwendungsfälle auch dann noch schnell genug ist, wenn er ein Interpretersprach-Programm fortlaufend von einer SD Karte bezieht. Dieses Linux auf einem AVR ist allerhöchstens eine Machbarkeitsstudie, fern jeder sinnvollen Anwendung.
Auf die Schnelle habe ich im "Instruction Set Manual" zwei Befehle gefunden. IJMP und ICALL Diese Hüpfen abhängig von Inhalt eines Registers. Kein Problem, dies aus einer Tabelle zu laden, irgendwie zu "berechnen" oder mittels Random vorzugeben;-) Habe aber keine Lust, mir den Befehlssatz des ATtiny13a reinzuziehen. Möglicherweise wird dieser Befehl ja nicht unterstützt.
Sebastian S. schrieb: > Habe aber keine Lust, mir den Befehlssatz des ATtiny13a reinzuziehen. > Möglicherweise wird dieser Befehl ja nicht unterstützt. Wird er, auch bei den noch kleineren Tinys.
Sebastian S. schrieb: > Habe aber keine Lust, mir den Befehlssatz des ATtiny13a reinzuziehen Fast alle Prozessoren haben so einen Befehl. I.A. braucht man dazu eine Tabelle, z.B. aus Sprungbefehlen, und das Register liefert den Index für die Tabelle. Georg
... und eine eventuelle Sprungtabelle füllt Dir der Assembler gerne, so Du ihm genau erklärst, wo es denn hingehen soll. Also nix mit rechnen, sondern: Rechnen lassen!
Sebastian S. schrieb: > IJMP Das ist zwar ein indirekter Sprung, allerdings ein absoluter und kein relativer wie vom TO gewünscht, d.h. der Sprung ist nicht PC-relativ. (Wobei der TO nicht wirklich zu wissen scheint was er will oder braucht, und auch nicht zwischen ausgeführtem und interpretiertem Code zu unterscheiden weiß). Eine weiter Möglichkeit für einen indirekten Sprung ist PUSH PUSH RET was aber auch eine absolute Adresse erfordert. Je nach Registerverwendung kann es allerdings günstiger sein, da man nicht ans Z-Register gebunden ist wie bei IJMP.
@Johann Ob der TO weiß was er will, kann ich auch nicht sagen, aber ich bin mir relativ sicher, dass er nicht "irgendwohin" springen will. Variable Ziele, abhängig von irgendwas im Programmablauf - ja; vorher definiert - ja; aber einfach irgendwohin kann ich mir kaum vorstellen.
georg schrieb: > Fast alle Prozessoren haben so einen Befehl. I.A. braucht man dazu eine > Tabelle, z.B. aus Sprungbefehlen, und das Register liefert den Index für > die Tabelle. Beim AVR8 hat man tatsächlich Instruktionen, die Indirektion für Sprünge und Unterprogrammaufrufe auch ohne den realtiv teuren Umweg über den RAM hinbekommen. Geile Architektur (in ihrer Klasse). Naja, der Fairness halber sollte man zumindest erwähnen, dass bei anderen Archtekturen der Umweg über den RAM, relativ gesehen, nicht ganz so teuer ist. Die sind einfach immer nur Scheisse-langsam. Auch wieder: relativ gesehen...
Vermutlich meint der TO einfach eine Sprungtabelle. Im einfachsten Fall erzeugt avr-gcc dafür folgenden Code, wobei die Tabelle für Werte von R24/25 = 1...9 verwendet wird:
1 | ;; R24/25 = 16-Bit Index |
2 | movw r30,r24 |
3 | ;; Index in [1..9] ? |
4 | sbiw r30,1 |
5 | cpi r30,9 |
6 | cpc r31,__zero_reg__ |
7 | ;; Falls nicht, die Sprungtabelle NICHT verwenden |
8 | brsh .Ldefault |
9 | ;; Word-Adresse der Tabbelle zum Index hinzuaddieren... |
10 | subi r30,lo8(-(gs(.LTable))) |
11 | sbci r31,hi8(-(gs(.LTable))) |
12 | ;; ...und springen |
13 | ijmp |
14 | .pushsection .jumptables.gcc,"ax",@progbits |
15 | .p2align 1 |
16 | .LTable: |
17 | rjmp .L1 |
18 | rjmp .L2 |
19 | rjmp .L3 |
20 | rjmp .L4 |
21 | rjmp .L5 |
22 | rjmp .L6 |
23 | rjmp .L7 |
24 | rjmp .L8 |
25 | rjmp .L9 |
26 | .popsection |
27 | .L1: |
28 | ;; Code fuer case 1: |
29 | .L2: |
30 | ;; Code fuer case 2: |
31 | ... |
Falls die Indices nicht in [1..9] sind sondern in [0..8], dann entfällt das "SBIW 1". Natürlich kann man auch die Labels anstatt die RJMPs in die Tabelle schreiben, was dann etwas anderen Code ergibt und z.B. dann erforderlich ist, wenn nicht alle Labels per RJMP erreichbar sind, hier für 16-Bit Index in X und ohne vorherige Bereichsprüfung:
1 | ;; X += WordAddr (.LTable) |
2 | subi XL,lo8(-(gs(.LTable))) |
3 | sbci XH,hi8(-(gs(.LTable))) |
4 | ;; X *= 2 |
5 | rol XL |
6 | lsl XH |
7 | ;; Z = *X++ |
8 | ld ZL, X+ |
9 | ld ZH, X+ |
10 | ;; PC = Z |
11 | ijmp |
12 | .pushsection .data.gcc,"a",@progbits |
13 | .LTable: |
14 | .word gs(.L0) |
15 | .word gs(.L1) |
16 | ... |
17 | .popsection |
18 | .L0: |
19 | ;; Code fuer case 0: |
20 | ... |
:
Bearbeitet durch User
Idee war es, von bspw. der SD-Karte oder dem RAM einen Wert in ein Register zu laden, der bestimmt, wie weit gesprungen wird. Warum? Um den Code, der nicht im Flash ist, schneller auszuführen 1. Code (Befehl enthaltend) laden 2. Sprung abhängig vom Code durchführen 3. Code (Daten enthaltend) nachladen 4. Code ausführen
Die Atmels springen nicht im RAM herum. Der Zugriff auf das RAM ist auch nicht schneller (min. 1 Clk.). Alles andere erledigen die vorherigen Ausführungen. Willst Du tatsächlich im RAM herumhüpfen, so benötigst Du eine andere Prozessorarchitektur.
c-hater schrieb: > Beim AVR8 hat man tatsächlich Instruktionen, die Indirektion für Sprünge > und Unterprogrammaufrufe auch ohne den realtiv teuren Umweg über den RAM > hinbekommen. Geile Architektur (in ihrer Klasse). Sowas ist doch selbstverständlich. Schon der alte 8051 von 1980 konnte mit "JMP @A+DPTR" und "MOVC A, @A+DPTR" bequem Sprungtabellen und Datentabellen adressieren. Ich hab mich immer gewundert, warum manche hinter einen MC noch 7-Segment Dekoder gesetzt haben. Die 10 Byte Tabelle kostet doch nix.
Peter D. schrieb: > Ich hab mich immer gewundert, warum manche hinter einen MC noch > 7-Segment Dekoder gesetzt haben Weil die nicht nur dekodieren, sondern auch treiben können.
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.