Moin,
ich versuche mir schon seit geraumer Zeit ein Bild von den Internen
Abläufen eines AVR Mikrocontrollers zu schaffen.
Die Blockdiagramme von der AVR Architektur und die vielen Videos über
die Harvard Architektur auf YouTube sind ein guter Anfang, aber meiner
Meinung nach nicht vollständig oder zu ungenau.
Bis her musste ich Stückchenweise Informationen aus diversen Büchern
rausfiltern oder aus Internet Seiten beschaffen und vor allem eine Menge
Improvisieren damit es für mich logisch erscheint...
Ich habe jetzt mal aus meinem Wissen heraus ein eigenes Diagramm
entworfen und möchte die internen Abläufe während eines Zyklus hier
wiedergeben, in der Hoffnung, dass man mich auf Fehler hinweist und...
ich denke ihr wisst worauf ich eigentlich hinaus will.
Das Diagramm befindet sich im Anhang.
___________________________________
Vor dem Programmstart:
1. Programmierung des Bootloaders im Flash mittels Serieller
Schnittstelle
2. Programmierung des Flash-Speichers mittels Bootloader (Wieso man das
machen muss ist mir unklar)
___________________________________
Programm startet sobald der uC mit Strom versorgt wird:
Steuerwerk holt die Programmzähler Variable aus dem Register
1. Steuerwerk holt Instruktion und beide Konstanten aus dem Flash
2. Steuerwerk lädt Instruktion in den Instruktions Decoder (wieso auch
immer)
3. Steuerwerk lädt beide Konstanten in die Register
4. Alu verarbeitet die Daten, konfiguriert/schaltet Datenbus und gibt
das
Ergebnis weiter an den Datenbus (und evtl. Flags)
5. PC wird inkrementiert
6. Steuerwerk erhält die Anweisung noch mal von vorne zu beginnen
___________________________________
Wahrscheinlich macht das meiste von mir beschriebene überhaut keinen
Sinn oder ist unschlüssig, deshalb erwarte ich auch nicht, dass man mir
den Ablauf von Grund auf erklärt, aber eine sehr gute Quelle wäre
Hilfreich.
Danke
int 21h schrieb:> 2. Programmierung des Flash-Speichers mittels Bootloader (Wieso man das> machen muss ist mir unklar)
Weil das auszuführende Programm zwingend im Flash liegen muss. Das ist
ein "Nachteil" der Harvard Architektur: die Trennung von Daten- und
Programmspeicher.
int 21h schrieb:> Programm startet
Die Beschreibung des Programmablaufs könnte von einem beliebigen Rechner
stammen. Daran ist nicht erkennbar, ob es ein Von-Neumann- oder ein
Harvard- oder ein sonstiger Rechner ist. Auch ein Von-Neumann-Rechner
kann/wird einen Flash-Speicher haben, um das Programm und
Initialisierungswerte zu speichern.
Hallo,
und diese Aussage ist falsch:
"Vor dem Programmstart:
1. Programmierung des Bootloaders im Flash mittels Serieller
Schnittstelle
2. Programmierung des Flash-Speichers mittels Bootloader (Wieso man das
machen muss ist mir unklar)"
Der Ablauf vor dem Programmstart ist leider falsch. Vor jeglicher
Programmierung hat man im Flash lauter Einsen. Deswegen, sollte man den
MC mit Strom versorgen, wenn der nicht beschrieben ist, macht er nichts
(alles 1 = NOP, No Operation oder auch invalid OP-Code, weiß nicht, wie
es beim AVR gelöst ist). Um erstmal etwas ins Flash zu schreiben,
benutzt man herstellerspezifische Schnittstellen, die betrachten wir
hier mal nicht. Nehmen wir also an, wir hätten unser Programm schon als
Abfolge von Bytes im Flash. Beim Anlegen der Spannung, wenn der evt.
eingebaute Brownout Detection die Reset-Leitung loslässt, macht der MC
das, was schon beschrieben war mit PC, Steuerwerk etc.
Wichtig: Der Bootloader ist auch nur ein Programm wie jedes andere. Was
der macht ist - auf einer der seriellen Schnittstellen zuhören und,
sollte etwas kommen, was nach einem Programm aus einer seriösen Quelle
aussieht, dieses aus dem Buffer der Schnittstelle ins Flash zu
schaufeln.
Und zu Punkt 2: versuch mal, das Steuerwerk als eine kombinatorische
Schaltung zu zeichnen. Du wirst sehen, dass mehr Signale an die ALU
nötig sind, als die Instruktion freie Bits bereitstellt. Das heißt, man
braucht etwas, wo der OP-Code reinkommt und die Steuersignale an die ALU
rauskommen. Genau diese Anhäufung von Logik ist dieses Instruction
Decoder.
int 21h schrieb:> ich versuche mir schon seit geraumer Zeit ein Bild von den Internen> Abläufen eines AVR Mikrocontrollers zu schaffen.
Dann vergiß dein Diagramm. Es ist schlichtweg falsch - und zwar in allen
Teilen. Lies dazu lieber die Dokumentation zu den kleineren PIC's. also
PIC16Fxxx und so. Dort ist das deutlicher dargestellt, um den Leuten zu
erklären, daß es dort keine Load-Modify-Store Architektur gibt.
Du kennst hoffentlich den grundlegenden Unterschied zwischen Harvard und
v.Neumann?
Das ist für den Programmierer der eigentliche Knackpunkt:
Bei Harvard ist der Programm-Raum schlichtweg getrennt vom Daten-Raum.
Das hat Konsequenzen:
1. ein Programm kann nicht aus dem Daten-Raum ausgeführt werden
2. für Daten und Konstanten braucht man getrennte Zugriffs-Mechanismen.
3. bei Zeigern muß man strikt untescheiden zwischen Zeigern in den
Datenraum und Zeigern in den Programm- bzw. Konstantenraum.
Ansonsten weißt du ja, wa eine Turing-Maschine ist, falls dir nochmal in
den Sinn kommt, ein Diagramm zu erstellen.
W.S.
Viktor B. schrieb:> Wichtig: Der Bootloader ist auch nur ein Programm wie jedes andere.
Dein Bootloader. Also der, welchen der Anwender ins Flash geschrieben
hat, um damit seine Applikation komfortabel aktualisieren zu können.
Jeder moderne Controller hat auch noch einen primären Bootloader. Der
ist von Anfang an fest eingebaut und macht die Kommunikation mit dem
Programmiergerät (über JTAG, SPI, LPD4, ...), initialisiert die Hardware
(blendet z.B. gesperrte Flash-Pages aus) und übergibt dann beim normalen
Systemstart die Kontrolle an das Anwenderprogramm bzw den von Anwender
programmierten Bootloader (welcher auch nur ein Programm wie jedes
andere ist).
Für die Atmel AVR-Familie sind einige Funktionen des primären
Bootloaders in der Application Note "AVR910: In-System Programming"
beschrieben. Mit dem kommuniziert man über SPI während der Reset-Pin auf
Low liegt.
Viktor B. schrieb:> Der Ablauf vor dem Programmstart ist leider falsch. Vor jeglicher> Programmierung hat man im Flash lauter Einsen.
Kommt drauf an. Es gibt auch Flash, der dann nur Nullen enthält.
> macht er nichts> (alles 1 = NOP, No Operation oder auch invalid OP-Code, weiß nicht, wie> es beim AVR gelöst ist)
Da ist der Flash tatsächlich so gestrickt, dass er unprogrammiert nur
gesetzte Bits enthält. Allerdings wirken die (als Programm ausgeführt)
nicht wirklich 100%ig wie NOPs, denn das wäre regulär das genaue
Gegenteil: $00.
Im Wesentlichen tun sie aber effektiv schon das Gleiche wie ein
regulärer NOP.
Der einzige wesentliche Unterschied ist diese Pseudo-NOPs brauchen zwei
statt einem Takt pro Instruktion. D.h.: es dauert doppelt so lange,
einen nicht initialisierten Programmspeicher zu durchlaufen, als wenn
der nur Nullen enthalten würde.
int 21h schrieb:> ich versuche mir schon seit geraumer Zeit ein Bild von den Internen> Abläufen eines AVR Mikrocontrollers zu schaffen.> Die Blockdiagramme von der AVR Architektur und die vielen Videos über> die Harvard Architektur auf YouTube sind ein guter Anfang, aber meiner> Meinung nach nicht vollständig oder zu ungenau.
Praktisch jedes Datenblatt eines AVR Controllers enthält ein deutlich
genaueres Blockschaltbild als dein "Werk" oben ...
> Ich habe jetzt mal aus meinem Wissen heraus ein eigenes Diagramm> entworfen und möchte die internen Abläufe während eines Zyklus hier> wiedergeben, in der Hoffnung, dass man mich auf Fehler hinweist
Auch das ist relativ ausführlich im Datenblatt beschrieben. Abschnitt
"AVR CPU Core" und da spezifisch der Unterabschnitt "Instruction
Execution Timing"
> Vor dem Programmstart:> 1. Programmierung des Bootloaders im Flash mittels Serieller> Schnittstelle
Ein AVR enthält nicht zwingend einen Bootloader. Ab Werk ist der Flash
leer (gelöscht).
> 2. Programmierung des Flash-Speichers mittels Bootloader (Wieso man> das machen muss ist mir unklar)
Es muß irgendwie ein Programm in den Flash gelangt sein. Das kann
per Bootloader geschehen, muß aber nicht. Die weitaus meisten AVR
dürften ihren Flash per ISP-Schnittstelle programmiert bekommen haben.
> Programm startet sobald der uC mit Strom versorgt wird:
Hier fehlt die Initialisierung durch das Hardware-Reset. U.a. werden
dabei die meisten Register auf definierte Anfangswerte gesetzt.
> Steuerwerk holt die Programmzähler Variable aus dem Register
Der PC ist keine Variable und auch kein (separates) Register. Der PC ist
ein Teil des Steuerwerks.
> 1. Steuerwerk holt Instruktion und beide Konstanten aus dem Flash
Aus wievielen Worten ein Maschinensprach-Befehl besteht, ist von Befehl
zu Befehl verschieden. Deswegen wird immer das erste Wort geholt und
nach der Decodierung des ersten Worts weiß das Steuerwerk, ob und
wieviel weitere Worte dazu gehören.
> 2. Steuerwerk lädt Instruktion in den Instruktions Decoder (wieso auch> immer)
Das ist kein extra Schritt. Das erste Wort jedes Befehls wird direkt in
den Decoder (respektive dessen Eingangsregister) geladen. Allerdings ist
schon die Unterscheidung zwischen Steuerwerk und Befehlsdecoder
merkwürdig. Der Decoder ist der wesentliche Bestandteil des Steuerwerks.
> 3. Steuerwerk lädt beide Konstanten in die Register> 4. Alu verarbeitet die Daten, konfiguriert/schaltet Datenbus und gibt> das> Ergebnis weiter an den Datenbus (und evtl. Flags)
Die ALU schaltet keine Busse. Das macht das Steuerwerk.
> 5. PC wird inkrementiert
Wenn die Instruktion mehr als ein Wort lang ist, wird er das auch
zwischendurch schon mal.
> Wahrscheinlich macht das meiste von mir beschriebene überhaut keinen> Sinn oder ist unschlüssig, deshalb erwarte ich auch nicht, dass man mir> den Ablauf von Grund auf erklärt, aber eine sehr gute Quelle wäre> Hilfreich.
Wenn du die internen Vorgänge verstehen willst, dann fang mit einem
wesentlich einfacheren Prozessor an. Der 6502 wäre z.B. ein solcher. Auf
http://visual6502.org/ gibt es dafür einen Simulator auf Chip-Ebene. Da
kannst du den Transistoren beim Schalten zuschauen.
Oder halt eines der Selbstbau-CPU Projekte, die man im Netz findet.
Irgendwas mit zwei Registern und einer 4-Bit ALU reicht für das
Verständnis ja vollkommen aus.
Ob Harvard- oder von-Neumann-Architektur ist auf dieser Ebene übrigens
nur ein relativ unbedeutendes Detail.
Axel S. schrieb:> Wenn du die internen Vorgänge verstehen willst, dann fang mit einem> wesentlich einfacheren Prozessor an. Der 6502 wäre z.B. ein solcher. Auf> http://visual6502.org/ gibt es dafür einen Simulator auf Chip-Ebene. Da> kannst du den Transistoren beim Schalten zuschauen.
Super, danke vielmals.
Das wird mir sicher sehr nützlich sein.
Aber erstmal 300 Seiten über die 6502 CPU lesen... das wird ein Spaß
int21h ???
Ist das nicht der DOS interrupt? Wenn du vom PC kommst, musst du
Umdenken. Die uCs arbeiten ihr Programm so ab, wie der PC das BIOS. Das
war es dann.
PC intern schrieb:> int21h ???>> Ist das nicht der DOS interrupt?
Ja.
> Wenn du vom PC kommst, musst du> Umdenken. Die uCs arbeiten ihr Programm so ab, wie der PC das BIOS. Das> war es dann.
Nö. Auch unter DOS ist man noch sehr nah an den Grundkonzepten, die für
heutige kleine µC relevant sind.
Größere µC können allerdings schon sehr stark in Richtung heutiger PC
gehen, diesen vollständig erreichen oder sogar noch überschreiten. Da
hast du dann alles, vom Speicherschutz über SIMD-Instructions bis hin zu
FP-Einheiten und Crypto-Unterstützung und noch einen Haufen Scheiss
mehr.
Und darüber hinaus u.U. sogar noch weiteres Zeug, was sich in einem PC
normalerweise eher nicht findet, sondern allenfalls per Steckkarte
nachgerüstet werden kann, z.B. programmierbare Logik. Wobei zumindest
ein Teil dieser Sache sich natürlich auch mit den Fähigkeiten moderner
GPUs abbilden lässt, die ja zum Teil auch schon wieder in die CPUs
migriert sind.
Irgendwie scheint also alles in Richtung Eierlegende Wollmilchsau zu
laufen. Unheimlich leistungsfähig, aber genauso unheimlich
energiefressend...
UART mit einige zig Bytes Hardware-Puffer und Auto-Baudrate fände ich
auch super.
Ich finde den Parallax Propeller interessant, wegen der Multitasking
Fähigkeiten. Beim Lesen der Doku bekam mich allerdings so ein Gefühl,
dass zwischen den Zeilen viele unerwartete Haken darauf warten, entdeckt
zu werden.
c-hater schrieb:
> Irgendwie scheint also alles in Richtung Eierlegende Wollmilchsau zu laufen
Das Problem ist nur dass die "Sau" weitgehend dumm bleibt und alles und
jedes und überhaupt immer mehr immer mühsamer zu konfigurieren ist.
Besser wärs die Funktionalität würde nicht auf alles und jedes
ausgeweitet sondern auf das begrenzt was meistgebraucht wirklich
vonnöten ist, nur intelligenter! Kleines Beispiel UART: Immer mehr
Fähigkeiten (die keiner braucht), dafür in der Konfiguration komplex und
dumm wie ein Brot. Wie wärs man könnte die gewünschte Baudrate samt
Anschlusspins direkt übergeben? Das Teil konfiguriert sich dafür selbst?
Man könnte sich als Programmierer viele Vereinfachungen wünschen, der
Zug fährt aber leider in die umgekehrte Richtung.
Stefanus F. schrieb:> UART mit einige zig Bytes Hardware-Puffer und> Auto-Baudrate fände ich auch super.
Wie soll Auto-Baudrate eigentlich zuverlässig funktionieren? Wenn man zu
einem bestimmten Zeitpunkt mit einer bekannten Sequenz starten kann
(z.B. "AT" oder "ENTER"), dann geht das - aber so ganz allgemein?
Und was passiert, wenn die Erkennung mal schiefgeht, ist dann bis zum
Neustart alles kaputt, oder stellt die UART nach jedem Byte die Baudrate
neu ein?
S. R. schrieb:>> UART mit einige zig Bytes Hardware-Puffer und>> Auto-Baudrate fände ich auch super.>> Wie soll Auto-Baudrate eigentlich zuverlässig funktionieren?
Wenn ein Datenstrom nicht bloss aus sowas wie 0x0F besteht, sondern
genug verschiedene Zeichen dabei sind, dann entspricht der kürzeste
Abstand zweier Flanken ungefähr der Bitrate. Das kann man mit weiteren
Flanken dann noch präziser bekommen.
Bei UART-Protokollen mit expliziter Autobaud-Unterstützung (z.B. LIN)
sendet man ein definiertes Bitmuster (0x55) am Anfang jedes Telegrammes.
Das erwartet der Empfänger und misst dort die Flanken aus. Dann wird
entweder der Baudraten-Teiler oder der interne Highspeed-Oszillator
nachgestimmt.
Stefanus F. schrieb:> Ich finde den Parallax Propeller interessant, wegen der Multitasking> Fähigkeiten. Beim Lesen der Doku bekam mich allerdings so ein Gefühl,> dass zwischen den Zeilen viele unerwartete Haken darauf warten, entdeckt> zu werden.
Das einzige, was mich am Propeller fasziniert hat: Wie, zum Teufel, ist
es eigentlich dazu gekommen, dass der tatsächlich in Stückzahlen
produziert wurde? Denn eigentlich ist er ja nicht mehr als eine
Konzeptstudie. Und naja, was aus dem Konzept nach der Evaluierung wurde:
siehe Schicksal des "Propeller 2"...
War übrigens sicher nicht das erste fehlgeschlagene Multicore-Dingens.
Ich kann mich da aus Amiga-Zeiten dunkel an etwas erinnern, was
"Transmeta" hieß. Auch so ein Flop.
Wirklich praktisch umgesetzt wurde das Multicore-Konzept für kleine µC
eigentlich nie. Es lohnt dafür einfach nicht. Die zusätzlichen Probleme
können die Vorteile einfach nicht aufwiegen.
c-hater schrieb:> Ich kann mich da aus Amiga-Zeiten dunkel an etwas erinnern, was> "Transmeta" hieß. Auch so ein Flop.
Aber kein Multicore. VLIW mit x86 Emulation, lange nach Amiga.
A. K. schrieb:> Aber kein Multicore. VLIW mit x86 Emulation, lange nach Amiga.
Verdammt, wie das Gedächtnis doch nachläßt. Also, nicht "Transmeta",
sondern "Transputer" meinte ich.
Wobei: auch Transmeta hat mal irgendwie mit dem Amiga gemauschelt und
ein Flop war's auch. Allerdings ganz ohne Multi-Core und deswegen
wirklich bezüglich des Kontext wirklich eine völlig unpassende
Erwähnung.
c-hater schrieb:> Verdammt, wie das Gedächtnis doch nachläßt. Also, nicht "Transmeta",> sondern "Transputer" meinte ich.
Nur bildeten die Transputer zwar ein Multiprozessor-System, weil dabei
viele einzelne Cores in separaten Sockeln miteinander arbeiteten, aber
um Multicore im heute üblichen Sinn von mehreren Cores in einem Sockel
handelte es sich auch dabei nicht.
Gescheitert sind die Transputer letztlich auch an der Schere von
Anspruch und Realität in Gestalt einer um Jahre verzögerten
Weiterentwicklung. Um viel später in einem deutlich besseren Ansatz im
Controller-Bereich als ZMOS wieder aufzutauchen (dahinter steckt der
gleiche Kopf). Bei denen wiederum gibt es Multicores.