Hallo zusammen,
ich hab mal wieder Lust zum schreiben
Da manche blutigen Newbies mit der Digitaltechnik und vor allem mit den Innereien des Mikrocontrollers so ihre Probleme haben werde ich mal ein paar Grundlagen vermitteln.
Die Links in diesem Beitrag verweisen auf die entsprechenden Quellen.
Also wat isn Dampfmaschin (frei nach der Feuerzangenbowle - Pfeiffer mit 3 F - 1 vor dem EI und 2 hinter dem EI )
Wenn man früher mal mit nem Z80-Prozessor gearbeitet hat, dann kennt man das schon alles. Aber in der heutigen Zeit wird da meist ganz oberflächlich drüber weggearbeitet und ganz schnell irgendwas Java-mäßiges verzapft.
=== Die Architekturen ===
Fangen wir mal mit Rechnerarchitekturen an ... Da gibt es zwei unterschiedliche ...
1.) Die Von-Neumann-Architektur
2.) Die Harvard-Architektur
=== internes Speichergedöns ===
Wir haben es also mit der Harvard-Architektur zu tun. Das merkt man auch schon beim internen Aufbau des Prozessors. Das Flash mit dem ausführbaren Programmcode und das SRAM bzw EEPROM für die zu verarbeitenden Daten.
Ein kleiner Überblick aus dem Datenblatt
Der Flash-Speicher beinhaltet also nur das Programm und Tabellen/Konstanten, die für die Programmausführung benötigt werden. Er wird bei der Programmierung beschrieben und ist im normalen Betrieb nicht veränderbar.
Im SRAM werden die Daten abgelegt, die beim Programmablauf anfallen. Also zB für Berechnungen, Rücksprungadressen bei Unterprogrammaufrufen, usw. Kurz gesagt - alles was sich dauernd verändert.
Das EEPROM ist ein Mittelding zwischen SRAM und Flash (ganz grob). Es enthält Daten die bei der Programmausführung benötigt werden, hält aber den Speicherinhalt auch ohne Strom und kann während des normalen Betriebes verändert werden (aber auch beim Programmiervorgang). Hier werden zB Kallibrierdaten (zB für Meß-Sensoren), Log-Daten (GPS-Logger) und anderes abgelegt was man auch ohne Strom behalten möchte.
Was ist nun im Ruhezustand in den Speichern los ...
Wenn man einen neuen Atmel hat, dann sind im Flash und im EEPROM alle Bits mit 1 besetzt (also 0xFF(hex) oder 255 (dezimal) oder 0b11111111 (binär) ). Das hat mit dem Aufbau der Speicherstellen zu tun. Beim Löschvorgang werden Elektronen von der isoliert angebrachten Steuerelektrode des Speichertransistors entfernt. Damit ist dann dieses Bit auf 1. Beim Programmieren wird bei den Bits die 0 durch aufbringen (tunneln durch die Isolierschicht) von Elektronen erzeugt. Man kann beim Programmieren keine Einsen schreiben. Dafür müßte man also wieder löschen (beim Flash ganze Speicherseiten und beim EEPROM ganze Bytes). Aus dem Grund sieht man also bei neuen Atmels im Flash und EEPROM die ganzen 0xFF.
Das SRAM hat dagegen keinen definierten Zustand. Wenn man den Strom einschaltet, dann sind die Bits der Speicherstellen zufällig mit Einsen und Nullen besetzt. Das Bitmuster kann sich auch jedes mal ändern. Aus diesem Grund sollte man auch Variablen in einem Programm vor der ersten Benutzung auf einen definierten Anfangswert setzen. Einen Reset überlebt der Inhalt der SRAM-Zellen, einen Spannungsausfall jedoch nicht.
=== Die ALU - das Herz ===
Soviel erst einmal zu den Speicherbereichen im Atmel Mikrocontroller.
Jetzt weiter im Text mit dem Herz von allem. Der ALU (Arithmetisch Logische Einheit). Leider ist das bei Wikipedia nur sparsam erklärt. Darum mach ich das mal etwas länger ...
Also in der ALU läuft - kurz gesagt - die gesamte Datenverarbeitung ab. Sie berechnet (Addition, Subtraktion, Multiplikation, ...), vergleicht (Größer, Kleiner, Gleich, ...) und führt logische Operationen aus (AND, OR, NOT, XOR, ...). Ohne sie wäre der Atmel nur ein bischen Speicher mit nem Zähler dran.
Um Daten für diese Operationen zwischenzuspeichern stehen ihr die Register zur Seite. Beim Atmel sind diese Register ein Teil des SRAM. Das müssen sie aber nicht unbedingt sein. Weil das SRAM aber mit auf dem Prozessorchip sitzt hat sich das hier angeboten (Platz sparen und Aufbau einfacher machen).
Ein Bildausschnitt aus dem Datenblatt
Sie besitzt also zwei Eingangszweige wo die Daten eingefüttert werden und einen Ausgang wo die Daten nach der Verarbeitung wieder herauspurzeln. An die Eingangszweige werden je nach verwendeten Befehl die gewünschten Register angesetzt, die die zu verarbeitenden Daten enthalten. Wenn die Verarbeitung durchgeführt wurde landet das Ergebnis meist wieder in einem der Register, die die Eingangsdaten geliefert haben. Zusätzliche Informationen landen im Statusregister (Ergebnis war Null, Es gab einen Übertrag, Ergebnis war negativ, ...).
Die Informationen, die im Statusregister landen können bei einem bedingten Sprung im Programm verwendet werden. Zum Beispiel : springe wenn das Ergebnis Null war , oder : springe wenn es negativ war , oder : springe wenn es nicht Null war, ...
Wenn man einen Vergleich macht, werden eigentlich nur beide Eingangswerte voneinander abgezogen und wenn das Ergebnis Null ist, dann sind die Werte gleich. Bei negativ war das eine größer und bei nicht Null und nicht negativ war das andere größer. Das ist das ganze Geheimnis.
=== Die Steuerung ===
Was läuft eigentlich bei so einer Abarbeitung des Befehls ab ?
Wenn man den Strom anschaltet, dann setzt die Reset-Logik zuerst mal die internen Zähler des CPU-Kerns auf einen definierten Anfangszustand. Am wichtigsten ist hier der Programm-Counter (PC). Das ist eigentlich nur ein Zähler, der die Speicherstellen in Flash adressiert, die als Befehl abgearbeitet werden sollen.
Er fängt also im Normalfall bei der Flash-Zelle 0x0000 an den ersten Befehl in das Befehlsregister zu laden. Der Dekoder zerlegt den Befehlscode dann und gibt die Teile an die entsprechenden Einheiten in der Ablaufsteuerung weiter. Die Ablaufsteuerung sagt dann was intern alles passieren soll (Register in die ALU laden, springen, Register mit Wert laden, ... usw).
Die Befehle aus dem Flash werden stumpf und ohne nachdenken nacheinander geladen. Das heißt - wenn man irgendwo eine Tabelle im Flash hat und da reinspringt, dann werden diese Werte einfach als Befehle interpretiert. Woher soll der Prozessor auch wissen das es eine Tabelle ist ... Den Murks macht immer der vor der Tastatur Der Prozessor führt das nur eins nach dem anderen aus. Ein Arbeiter ohne Hirn sozusagen. Die Intelligenz entsteht erst durch die richtige Anordnung der Befehle im Flash und das ist die Arbeit des Programmierers.
Wenn man jetzt einen Sprung ausführt, dann wird einfach die Adresse, die im Sprungbefehl mit eingebaut ist, in den Progammzähler geladen. Und schon gehts an einer anderen Speicherstelle im Flash mit der Befehlsausführung weiter.
Bei einem Unterprogrammaufruf sieht das ähnlich aus wie bei einem Sprung. Die Adresse des neuen Befehls wird in den PC geladen. Vorher wird aber die alte Adresse gesichert. Dafür hat man den Stack (Stapel). Der Stack wird vom Stackpointer (SP) verwaltet. Der Stack ist eigentlich nur ein Bereich, den man am Anfang seines Programmes im SRAM definiert. Unser Stapel ist aber nicht so aufgebaut wie ein Stapel auf dem Tisch sondern hängt sozusagen an der Decke. Wenn man etwas auf unseren Stapel packt, dann klebt man sozusagen ein Post-It an die Decke auf die bereits existierenden. Er wächst also von der Decke nach unten. Aus dem Grund zeigt der Stack-Pointer auch am Anfang auf die höchste SRAM-Adresse. Wenn man jetzt ein Unterprogramm aufruft, dann wird also die alte Adresse auf den Stack gelegt und der SP wandert um die enstsprechenden Speicherzellen nach unten (gegen 0x0000 des SRAM-Bereichs). Wenn man jetzt das Unterprogramm mit einem Return wieder verläßt, dann wird diese alte Adresse von Stack wieder zurückgeholt und die CPU macht an der Stelle weiter, an der sie vorher ins Unterprogramm gesprungen ist.
Das war also erst einmal "des Pudels Kern" - Das Innerste des Prozessors.
Das dranhängende Gebamsel (UART, SPI, Timer, ...) und Interrupts kommt dann später.
Wobei die Interrupts davon wohl als erstes erklärt werden.
ich hab mal wieder Lust zum schreiben
Da manche blutigen Newbies mit der Digitaltechnik und vor allem mit den Innereien des Mikrocontrollers so ihre Probleme haben werde ich mal ein paar Grundlagen vermitteln.
Die Links in diesem Beitrag verweisen auf die entsprechenden Quellen.
Also wat isn Dampfmaschin (frei nach der Feuerzangenbowle - Pfeiffer mit 3 F - 1 vor dem EI und 2 hinter dem EI )
Wenn man früher mal mit nem Z80-Prozessor gearbeitet hat, dann kennt man das schon alles. Aber in der heutigen Zeit wird da meist ganz oberflächlich drüber weggearbeitet und ganz schnell irgendwas Java-mäßiges verzapft.
=== Die Architekturen ===
Fangen wir mal mit Rechnerarchitekturen an ... Da gibt es zwei unterschiedliche ...
1.) Die Von-Neumann-Architektur
Memory - Speicherwerk speichert sowohl Programme als auch Daten, welche für das Rechenwerk zugänglich sind.
...
Der von-Neumann-Flaschenhals der von-Neumann-Architektur bezeichnet den Sachverhalt, dass das Verbindungssystem (Daten- und Befehls-Bus) zum Engpass zwischen dem Prozessor und dem Speicher wird.
2.) Die Harvard-Architektur
Der Befehlsspeicher ist physisch vom Datenspeicher getrennt und beide werden über getrennte Busse angesteuert.
...
Ebenso basieren die Mikrocontroller der AVR-Reihe von Atmel auf der Harvard-Architektur.
=== internes Speichergedöns ===
Wir haben es also mit der Harvard-Architektur zu tun. Das merkt man auch schon beim internen Aufbau des Prozessors. Das Flash mit dem ausführbaren Programmcode und das SRAM bzw EEPROM für die zu verarbeitenden Daten.
Ein kleiner Überblick aus dem Datenblatt
Der Flash-Speicher beinhaltet also nur das Programm und Tabellen/Konstanten, die für die Programmausführung benötigt werden. Er wird bei der Programmierung beschrieben und ist im normalen Betrieb nicht veränderbar.
Im SRAM werden die Daten abgelegt, die beim Programmablauf anfallen. Also zB für Berechnungen, Rücksprungadressen bei Unterprogrammaufrufen, usw. Kurz gesagt - alles was sich dauernd verändert.
Das EEPROM ist ein Mittelding zwischen SRAM und Flash (ganz grob). Es enthält Daten die bei der Programmausführung benötigt werden, hält aber den Speicherinhalt auch ohne Strom und kann während des normalen Betriebes verändert werden (aber auch beim Programmiervorgang). Hier werden zB Kallibrierdaten (zB für Meß-Sensoren), Log-Daten (GPS-Logger) und anderes abgelegt was man auch ohne Strom behalten möchte.
Was ist nun im Ruhezustand in den Speichern los ...
Wenn man einen neuen Atmel hat, dann sind im Flash und im EEPROM alle Bits mit 1 besetzt (also 0xFF(hex) oder 255 (dezimal) oder 0b11111111 (binär) ). Das hat mit dem Aufbau der Speicherstellen zu tun. Beim Löschvorgang werden Elektronen von der isoliert angebrachten Steuerelektrode des Speichertransistors entfernt. Damit ist dann dieses Bit auf 1. Beim Programmieren wird bei den Bits die 0 durch aufbringen (tunneln durch die Isolierschicht) von Elektronen erzeugt. Man kann beim Programmieren keine Einsen schreiben. Dafür müßte man also wieder löschen (beim Flash ganze Speicherseiten und beim EEPROM ganze Bytes). Aus dem Grund sieht man also bei neuen Atmels im Flash und EEPROM die ganzen 0xFF.
Das SRAM hat dagegen keinen definierten Zustand. Wenn man den Strom einschaltet, dann sind die Bits der Speicherstellen zufällig mit Einsen und Nullen besetzt. Das Bitmuster kann sich auch jedes mal ändern. Aus diesem Grund sollte man auch Variablen in einem Programm vor der ersten Benutzung auf einen definierten Anfangswert setzen. Einen Reset überlebt der Inhalt der SRAM-Zellen, einen Spannungsausfall jedoch nicht.
=== Die ALU - das Herz ===
Soviel erst einmal zu den Speicherbereichen im Atmel Mikrocontroller.
Jetzt weiter im Text mit dem Herz von allem. Der ALU (Arithmetisch Logische Einheit). Leider ist das bei Wikipedia nur sparsam erklärt. Darum mach ich das mal etwas länger ...
Also in der ALU läuft - kurz gesagt - die gesamte Datenverarbeitung ab. Sie berechnet (Addition, Subtraktion, Multiplikation, ...), vergleicht (Größer, Kleiner, Gleich, ...) und führt logische Operationen aus (AND, OR, NOT, XOR, ...). Ohne sie wäre der Atmel nur ein bischen Speicher mit nem Zähler dran.
Um Daten für diese Operationen zwischenzuspeichern stehen ihr die Register zur Seite. Beim Atmel sind diese Register ein Teil des SRAM. Das müssen sie aber nicht unbedingt sein. Weil das SRAM aber mit auf dem Prozessorchip sitzt hat sich das hier angeboten (Platz sparen und Aufbau einfacher machen).
Ein Bildausschnitt aus dem Datenblatt
Sie besitzt also zwei Eingangszweige wo die Daten eingefüttert werden und einen Ausgang wo die Daten nach der Verarbeitung wieder herauspurzeln. An die Eingangszweige werden je nach verwendeten Befehl die gewünschten Register angesetzt, die die zu verarbeitenden Daten enthalten. Wenn die Verarbeitung durchgeführt wurde landet das Ergebnis meist wieder in einem der Register, die die Eingangsdaten geliefert haben. Zusätzliche Informationen landen im Statusregister (Ergebnis war Null, Es gab einen Übertrag, Ergebnis war negativ, ...).
Die Informationen, die im Statusregister landen können bei einem bedingten Sprung im Programm verwendet werden. Zum Beispiel : springe wenn das Ergebnis Null war , oder : springe wenn es negativ war , oder : springe wenn es nicht Null war, ...
Wenn man einen Vergleich macht, werden eigentlich nur beide Eingangswerte voneinander abgezogen und wenn das Ergebnis Null ist, dann sind die Werte gleich. Bei negativ war das eine größer und bei nicht Null und nicht negativ war das andere größer. Das ist das ganze Geheimnis.
=== Die Steuerung ===
Was läuft eigentlich bei so einer Abarbeitung des Befehls ab ?
Wenn man den Strom anschaltet, dann setzt die Reset-Logik zuerst mal die internen Zähler des CPU-Kerns auf einen definierten Anfangszustand. Am wichtigsten ist hier der Programm-Counter (PC). Das ist eigentlich nur ein Zähler, der die Speicherstellen in Flash adressiert, die als Befehl abgearbeitet werden sollen.
Er fängt also im Normalfall bei der Flash-Zelle 0x0000 an den ersten Befehl in das Befehlsregister zu laden. Der Dekoder zerlegt den Befehlscode dann und gibt die Teile an die entsprechenden Einheiten in der Ablaufsteuerung weiter. Die Ablaufsteuerung sagt dann was intern alles passieren soll (Register in die ALU laden, springen, Register mit Wert laden, ... usw).
Die Befehle aus dem Flash werden stumpf und ohne nachdenken nacheinander geladen. Das heißt - wenn man irgendwo eine Tabelle im Flash hat und da reinspringt, dann werden diese Werte einfach als Befehle interpretiert. Woher soll der Prozessor auch wissen das es eine Tabelle ist ... Den Murks macht immer der vor der Tastatur Der Prozessor führt das nur eins nach dem anderen aus. Ein Arbeiter ohne Hirn sozusagen. Die Intelligenz entsteht erst durch die richtige Anordnung der Befehle im Flash und das ist die Arbeit des Programmierers.
Wenn man jetzt einen Sprung ausführt, dann wird einfach die Adresse, die im Sprungbefehl mit eingebaut ist, in den Progammzähler geladen. Und schon gehts an einer anderen Speicherstelle im Flash mit der Befehlsausführung weiter.
Bei einem Unterprogrammaufruf sieht das ähnlich aus wie bei einem Sprung. Die Adresse des neuen Befehls wird in den PC geladen. Vorher wird aber die alte Adresse gesichert. Dafür hat man den Stack (Stapel). Der Stack wird vom Stackpointer (SP) verwaltet. Der Stack ist eigentlich nur ein Bereich, den man am Anfang seines Programmes im SRAM definiert. Unser Stapel ist aber nicht so aufgebaut wie ein Stapel auf dem Tisch sondern hängt sozusagen an der Decke. Wenn man etwas auf unseren Stapel packt, dann klebt man sozusagen ein Post-It an die Decke auf die bereits existierenden. Er wächst also von der Decke nach unten. Aus dem Grund zeigt der Stack-Pointer auch am Anfang auf die höchste SRAM-Adresse. Wenn man jetzt ein Unterprogramm aufruft, dann wird also die alte Adresse auf den Stack gelegt und der SP wandert um die enstsprechenden Speicherzellen nach unten (gegen 0x0000 des SRAM-Bereichs). Wenn man jetzt das Unterprogramm mit einem Return wieder verläßt, dann wird diese alte Adresse von Stack wieder zurückgeholt und die CPU macht an der Stelle weiter, an der sie vorher ins Unterprogramm gesprungen ist.
Das war also erst einmal "des Pudels Kern" - Das Innerste des Prozessors.
Das dranhängende Gebamsel (UART, SPI, Timer, ...) und Interrupts kommt dann später.
Wobei die Interrupts davon wohl als erstes erklärt werden.