Einchipmikrorechner und Signalprozessoren
Für die Gemeinsamkeiten und Unterschiede von EµR und DSP gibt es eine Zusammenfassung.
Wer schon alles gelernt hat, kann sein Wissen mit Testfragen überprüfen.
Einleitung
Einordnung
- Einchipmikrorechner (EMR, µC)
- Digitaler Signalprozessor (DSP)
Gemeinsamkeiten
- Einchip-Konzept: wesentliche Bauteile alle auf einem Chip (CPU, Speicher, I/O, Taktgeber)
- minimierte (minimale) Außenbeschaltung: Abblockkondensator, Quarz
- autonomer Betrieb: Unbeaufsichtigter Betrieb, ohne (bzw. nur mit applikationsspezifischem) Bedienereingriff
- aufgabenspezifisch angepasst: "Nur soviel (Hardware) wie nötig"
- große Typenfamilien: viele Typen mit jeweils mehreren Ausführungen, Unterschiede in Speicher/Pins
- Crosswerkzeuge: Entwicklung auf PC, aber Code für Chips
- Software: muss sich nicht mehr verändern (ist in sich geschlossen)
Unterschiede
EMP | DSP | |
Leistung | niedrig bis mittel | mittel bis hoch |
Datenbreite | 4, 8, 16, 32 | 16, 32, 64 |
Speichergröße | ||
* intern | sehr wenig bis mittel | meist nur mittel |
* extern | wenig bis mittel | groß bis sehr groß |
Besondere Befehle | Bit-Befehle, Bit-Adressierung |
MAC (Multiplikation und Addition in einem Befehl), zirkuläre Adressierung, Saturation (Festkomma-Arithmetik) |
Typische Anwendungen | Steuergeräte in Industrie und Kraftfahrzeugtechnik, Haushaltselektronik, tragbare Geräte (MP3, Handy) |
digitale Filter/Regler, Bildverarbeitung und Mustererkennung, Messgeräte, Messtechnik, Audioeffektgeräte, Modems |
Bauteile
Rechnerkern
- RISC oder CISC
- Harvard oder von-Neumann (Princeton)
- viele Spezial(funktions)register (SFR)
- allg. Register häufig verbunden mit internem RAM
Speicher
<graphviz> digraph G { "Speicher" -> "intern"; "Speicher" -> "Speicherinterface";
"intern" -> "ROM"; "intern" -> "RAM";
"Speicherinterface" -> "Seriell"; "Speicherinterface" -> "Businterface"; "Speicherinterface" -> "\"glueless\"\n(Treiberlos)"; } </graphviz>
ROM
- Masken-ROM
- PROM/OTR
- EPROM
- EEPROM
- FLASH-EEPROM
- FRAM
- "Bondout"
- "ROM-less"
Ein- und Ausgabe
<graphviz> digraph G { "Ein- und Ausgabe" -> "digital, Standard"; "Ein- und Ausgabe" -> "analog"; "Ein- und Ausgabe" -> "speziell";
"digital, Standard" -> "parallel"; "digital, Standard" -> "seriell";
"seriell" -> "synchron"; "seriell" -> "asynchron";
node [shape=box]; "Kommunikation"; "Zähler/Zeitgeber"; "Geräte";
"speziell" -> "Kommunikation"; "speziell" -> "Zähler/Zeitgeber"; "speziell" -> "Geräte";
} </graphviz>
Sonstiges ("Hilfs"-baugruppen)
- Reset
- Takt
- Powermanagement
- Interruptsystem
- DMA
- Watchdog
Typenbeispiele
(nicht prüfungsrelevant)
Mikrocontroller am Beispiel der C166 Familie
- von Siemens, später Infineon
- 16bit Datenbreite
- CISC-Kern (eigentlich RISC, hat aber einige Erweiterungen)
- Intelähnlicher Befehlssatz
- von-Neumann-Architektur
- typischerweise bis 30 Mhz Taktfrequenz
- Adressbreite 16bit (mit Segmentierung 24bit)
- Mehrfachnutzung von Pins
Befehlssatzarchitektur
Allgemeiner Registersatz
- 16x16bit Register R0-R15
- Register R0-R7 lassen sich auch über H und L ansprechen
Spezialfunktionsregister (SFR)
- es existieren sehr viele Register
u.a. in:
- Prozessorkern
- Peripherieeinheiten
- Interruptsystem
- Chipsteuerung
- Adresseinheit
- ...
SFR im Prozessorkern
- PSW (processor status word, "Flagregister"), 16bit breit
- Beispiele für Flags:
- Statusflags:
- C: Carry (Übertrag)
- V: Overflow (Überlauf)
- Z: Zero
- N: Negative
- ...
- Steuerflags:
- IEN: Interrupt Enable
- USR0: frei verfügbar
- SP (Stackpointer)
- STKUV (Stackunderflow, untere Adressgrenze)
- STKOV (Stackoverflow, obere Adressgrenze)
- SYSCON: Systemkonfiguration
- ...
Speichermodell
- von-Neumann: ein Adressraum
- interner ROM
- interne RAMs
- SFRs (reservierte Speicheradressen)
- allgemeine Register (lassen sich im Speicherbereich verschieben -> Kontextwechsel sehr schnell möglich)
- reservierte Bereiche
- Rest: verwendbar für externen Speicher
kleines Speichermodell
- nicht segmentiert
- logische 16 Bit-Adresse wird umgesetzt auf physikalische 16 Bit-Adresse
- Speicherraum: Byte = 64 KiByte
großes Speichermodell
- segmentiert
- logische 16 Bit-Adresse erhält zusätzliche Segmentbeschreibung (Länge variiert)
- wird ungeformt auf physikalische 24 Bit-Adresse
- Speicherraum: Byte = 16 MiByte
Vorteil:
- mehr Speicherplatz
- Segment = Grobpositionierung
- Änderung davon seltener (wird nicht bei jedem Zugriff geändert)
Segmentierter Datenzugriff
Segmentierter Programmzugriff
Adressraumstruktur
- 000000H - 00FFFFH -> 64KiByte des nichtsegmentierten Bereichs
- Datenseite jeweils 16 KiByte groß (10bit Data Page Pointer [SFR])
- Codeseite jeweils 64 KiByte groß (8bit Code Segement Pointer [SFR])
Allgemeine Register: Mapping in den Speicherraum
- 32 Byte allgemeine Register
- können im Speicherbereich verschoben werden
- CP (context pointer, 10bit) zeigt auf erstes Register (R0)
- ermöglicht sehr einfachen Kontextwechsl ohne Umkopieren durch Verschieben des Registerbereichs
- schnell, grade für Echtzeitanwendungen; z.B. bei Interruptbehandlung
Befehlssatz
Transportbefehle
- MOV Ziel , Quelle : Wort
- MOV B Ziel , Quelle : Byte
- MOV BZ Ziel , Quelle : Wort <- Byte (Null auffüllen)
- MOV BS Ziel , Quelle : Wort <- Byte (Vorzeichen auffüllen)
ermöglichen arithmetisch korrekte Expansion von 8 auf 16bit
- MOV Register , Register
- MOV Register , #Zahlenwert // Konstante
- MOV Register , Zahlenwert // direkt
- MOV Register , [Register] // indirekt
- MOV [Register] , Register
- MOV Register , [Register+#Index]
- MOV Register , [Register+] // postdekrement um 2
- MOV [+Register] , Register // preinkrement um 2
- MOV [Register] , [Register] // nicht universell!
- Zahlenwerte mit # kennzeichnen sonst Speicheradresse
- Variablenangabe statt Zahlenwert für Adresse möglich
Stackbefehle
- PUSH Quelle -> Ziel = Stack
- Stackpointer geht 1 Speicherplatz nach unten (SP = SP - 2) und kopiert dann erst Inhalt aus Register in Stack
- POP Ziel -> Quelle = Stack
- Wert aus Stack wird gelesen und in Register geschrieben, dann geht Stackpointer 1 Speicherplatz nach oben (SP = SP + 2)
- Befehle gelten nur für 16 Bit Register
- LIFO-Prinzip beim Daten retten beachten
- Stack-Befehle müssen ausbalanciert sein (sonst Über-/Unterlauf)
- Stackgrenzen können festgelegt werden
- wenn der Stack über- oder unterläuft wird an eine Handleradresse gesprungen (Interrupt)
Arithmetik/Logik
16 Bit Befehle | 8 Bit Befehle | Bemerkung | ||
ADD | ADD B | |||
ADD C | ADD C B | Wert des Carry-Flags mit addieren | ||
SUB | SUB B | |||
SUB C | SUB C B | Wert des Carry-Flags mit subtrahieren | ||
AND | AND B | bitweise | ||
OR | OR B | bitweise | ||
XOR | XOR B | bitweise | ||
CMP | CMP B | beeinflusst nur Flags | ||
NEG | NEG B | Vorzeichen-Wechsel (2er-Komplement) | ||
CPL | CPL B | Bitweise Negation (1er-Komplement) (1->0 , 0->1) |
Multiplikation/Division
- MD - separates 32 Bit Register für Multiplikation/Division
- MDH , MHL = SFR
- Vorzeichenbehaftet - MUL
- Vorzeichenlos - MUL U
- Operationen nur mit Registern möglich
- DIV / DIV U -> MDL (16bit) : Op (16bit) = MDL (16bit) Rest: MDH (16bit)
- DIV L / DIV L U -> MD (32bit) : Op (16bit) = MDL (16bit) Rest: MDH (16bit) -> arithm. Überlauf möglich
- MD-Register wieder frei räumen vor neuer Multiplikation/Division
Schieben/Rotieren
- nur für 16 bit Register
Links | Rechts | Bemerkungen | |
SHL Register, Zahlenwert | SHR Register, Zahlenwert | <graphviz>
digraph G { rankdir = LR; node [shape = record, width = 0.1, height = 0.1]; Null [label = "0"]; subgraph "cluster Register" { rankdir = LR; 15 -> "..." -> 0; } Carry [label = "CF"]; Null -> 15; 0 -> Carry; } </graphviz> | |
- | ASHR Register, Zahlenwert | <graphviz>
digraph G { rankdir = LR; node [shape = record, width = 0.1, height = 0.1]; subgraph "cluster Register" { rankdir = LR; 15 -> "..." -> 0; } Carry [label = "CF"]; 15 -> 15; 0 -> Carry; } </graphviz> || Vorzeichenbehaftete Division durch 2 | |
ROL Register, Zahlenwert | ROR Register, Zahlenwert | <graphviz>
digraph G { rankdir = LR; node [shape = record, width = 0.1, height = 0.1]; subgraph "cluster Register" { rankdir = LR; 15 -> "..." -> 0 [weight = 100]; } Carry [label = "CF"]; 0 -> 15; 0 -> Carry [weight = 0]; } </graphviz> |
Steuerfluss-Befehle
Sprungbefehle
Wir unterscheiden Intrasegment und Intersegment Sprünge
Nur der IP (Instruction Pointer) wird geändert beim:
- segmentierten Modell (Sprung im Segment)
- nicht segmentierten Modell
Sowohl der IP (Instruction Pointer) als auch der CSP (Code Segment Pointer) wird geändert beim:
- segmentierten Modell (Sprung zwischen Segmenten)
Intrasegment
Direkt | Indirekt | |
Absolut | JMPA | JMPI |
Relativ | JMPR | - |
JMPA Condition Code, Label JMPR Condition Code, Label JMP Condition Code, Label // Assembler entscheidet sich für absoluten oder relativen Sprung JMPI cc_UC, [R4] // IP = [R4]
Condition Code
cc_UC: unconditional (unbedingt, immer!) cc_NC: not carry cc_C : carry cc_NZ: not zero cc_Z : zero cc_EQ: eqal (entspricht cc_Z) cc_NE: not eqal (entspricht cc_NZ) cc_V : overflow cc_NV: not overflow cc_SLT: signed less than cc_UGE: unsigned greater eqals
Vergleiche: werden aud dem Flags: C, Z, V und N gebildet
Intersegment
- nur absolut, direkt, unbedingt
JMP SEG Label, SOF Label \___ __/ \___ __/ \/ \/ Segment Offset (CSP) (IP) \________ ________/ \/ ergibt die 24bit-Speicheraddresse
Unterprogrammbefehle
Intrasegment
CALLA Condition Code, Label // IP -> Stack CALLR Condition Code, Label // IP -> Stack CALL Condition Code, Label // IP -> Stack, wird vom Assembler auf CALLA bzw. CALLR umgesetzt CALLI Condition Code, Label // IP -> Stack RET // Stack -> IP
Intersegment
CALLS Condition Code, Label // IP und CSP -> Stack RETS // Stack -> IP und CSP
Die Verwendung von RET bzw. RETS entscheidet darüber, ob eine Funktion aus einem anderem Segment erreichbar ist.
Bit-Befehle
- Bitaddressierbare Bereiche:
- 3x256 Byte im internen RAM
- 1x256 Byte SFR
- macht 1024x8 bit = 8 KiBit = Bitaddressierung
- 13bit Zellenadresse + 3bit Bitadresse = 16bit
- wenn Offset > 8, dann Adresse der nächsten Zelle + Offset MOD 8 als Offset
Beispiele für Bitadressen:
0FF10H.1 // (0-7) oder (0-15) mgl. \ PSW.1 // > sind alle äquivalent C // /
BMOV Zielbitadresse, Quellbitadresse BMOVN Zielbitadresse, Quellbitadresse BAND Zielbitadresse, Quellbitadresse BOR Zielbitadresse, Quellbitadresse BXOR Zielbitadresse, Quellbitadresse BCMP Zielbitadresse, Quellbitadresse BCLR Bitadresse BSET Bitadresse
- Bedingte Sprünge mit Bits nur intrasegment, direkt
JB Bitadresse, Label // Bit gesetzt JNB Bitadresse, Label // Bit nicht gesetzt
"Test & Set" Befehle (atomar, für Parallelprogrammierung):
JBC Bitadresse, Label | Bit gesetzt, zurücksetzen (CLEAR) JNBS Bitadresse, Label | Bit nicht gesetzt, setzen (SET)
Sonstige Befehle
<source lang=asm> NOP ; No Operation SRST ; Softwarereset PWRDW ; Schlafzustand aktivieren EINIT ; Ende der Initalisierung
; Privelegierte Einstellungen können nicht mehr ; verändert werden (wie z.B. Stackgrenzen)
</source>
SW-Entwicklung
Cross-Tools: (z.B. Programmierung auf PC für nicht PC-Zielsystem)
Tool-Chain: (Werkzeugkette)
IDE: (Integrated Development Enviroment)
<graphviz> digraph G {
rankdir = LR; node [fontsize = 11, width = 0.1, heigth = 0.1]; edge [fontsize = 11];
IDE [shape = box, label = "Interaktives\nKonfigurations\nWerkzeug\n\n\"DAVE\"", color = green4, fontcolor = green4];
ASM [shape = box, label = ".asm\nAssembler-\nQuelltext"]; XASM [shape = ellipse, label = "Cross-\nAssembler"]; AOBJ [shape = box, label = ".obj\nObjekt"];
C [shape = box, label = ".c\nC-Quell-\ntext"]; XCMP [shape = ellipse, label = "Cross-\nCompiler"]; COBJ [shape = box, label = ".obj\nObjekt"];
LIB [shape = box, label = ".lib\nBiblio-\ntheken"]; XLNK [shape = ellipse, label = "Cross-\nLinker"]; OUT [shape = box, label = ".out\nVerbunden-\nes Objekt"]; XLOC [shape = ellipse, label = "Cross-\nLocator"]; ABS [shape = box, label = ".abs\nAbsolutes\nObjekt"]; { node [shape = none, fontcolor = gray]; HINT1 [label = "noch keine endgültigen\nAddressen"]; HINT2 [label = "Vorgefertigte Module"]; HINT3 [label = "- endgültige Addressen\n- Reffenzen aufgelößt \n- Maschinencode "]; }
labeljust = l; USE [shape = box, label = "- Befehlssatz-Simulator\n- Remote Debugging \n- In-Circute-Emulation;\n JTAG (IEEE 1149.1) \n- Programmiergerät ", color = orange3];
{rank = 0; IDE} {rank = same; ASM; C; LIB; HINT2; OUT; HINT3} {rank = same; AOBJ; HINT1; COBJ}
IDE -> ASM [style = invis, weight = 0]; // Workaround zur Anordnung der Elemente ASM -> XASM -> AOBJ -> XLNK; IDE -> C [color = green4]; C -> XCMP -> COBJ -> XLNK; LIB -> XLNK [weight = 0, label = "Linker wählt\nbenötigten Code\naus, nicht ganze Lib", fontcolor = gray]; XLNK -> OUT [weight = 0]; OUT -> XLOC -> ABS; ABS -> USE [color = orange3];
{ edge [color = gray, arrowhead = none]; AOBJ -> HINT1 -> COBJ; LIB -> HINT2; OUT -> HINT3; }
} </graphviz>
Details zur internen Peripherie
Binärports (parallele digitale EA)
Datenregister: P2
Richtingsregister: DP2 (0 = input; 1 = output)
<source lang=asm> MOV DP2, #1FH ; #001FH = 0000000000011111
; freie Eingänge auf 0 -> weniger Stromverbrauch
</source> Output <source lang=asm> BCLR P2.3 ; PS = ************0*** BSET P2.3 ; PS = ************1*** </source> Input <source lang=asm> JB P2.7, m3 ; PS = ********?******* Test auf 1 JNB P2.7, m3 ; PS = ********?******* Test auf 0 </source>
Zähler/Zeitgeber ("Timer") T6
[Bild des T6 Timers]
Interrupt-System
[...]
<graphviz> digraph G {
node [fontsize = 11, width = 1.5]; edge [fontsize = 11];
{ node [shape = record]; 0 [label = "Normales Programm\nläuft"]; 1 [label = "{aktuellen Befehl\nbeenden | IP, (CSP), PSW\n-\> Stack | Spung zur ISR\n(mittels Tabelle)}"]; 2 [label = "{ISR | - Kontext retten\n-eigentl. Action\n- Kontext restaurieren\n- RETI}", color = green4, fontcolor = green4]; 3 [label = "{ Stack -\> IP, (CSP),\nPSW| fortsetzten des Progr.}"]; } 0 -> 1 [label = "\"Blitz\""]; 1 -> 2 -> 3 [color = orange3];
} </graphviz>
// TODO: Bild ist noch nicht ganz vollständig
Arten von Interrupts
- HW-Interrupts, maskierbar:
- "intern" von Elementen auf dem Chip
- "extern" jeder Pin als Interrupt
- NMI (nicht maskierbarer Interrupt)
- nicht abschaltbar
- für wichtige, dringende Sachen
- SW-Interrupts
- Systemauf(ruf?) bei BS
- Beispiel: TRAP #25H
- Interne Ausnahmen: unbekanter OPKode, Div 0, etc.