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..."
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
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
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
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:
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.