Commit f1f1ce46 authored by Synthron's avatar Synthron
Browse files

final commit Techniker

parents
File added
\chapter{Anhang 1: Memory Map}
Die Memory-Map zeigt die Adressen, die den jeweiligen ICs/Modulen zur Verfügung stehen.
\begin{table}[H]
\centering
\begin{tabular}{|c|c|}
\hline
Adressraum & Modul \\ \hline \hline
0000 - 3FFF & Banked RAM \\ \hline
4000 - 7EFF & Common RAM \\ \hline
7F00 - 7F0F & PIA \\ \hline
7F10 - 7F1F & VIA1 \\ \hline
7F20 - 7F2F & VIA2 \\ \hline
7F30 - 7F3F & VIA3 \\ \hline
7F40 - 7F4F & ACIA1 \\ \hline
7F50 - 7F5F & ACIA2 \\ \hline
7F60 - 7F6F & Grafik \\ \hline
7F70 - 7F8F & Sound \\ \hline
7F90 - 7F9F & IO9 \\ \hline
7FA0 - 7FAF & IOA \\ \hline
7FB0 - 7FBF & IOB \\ \hline
7FC0 - 7FDF & IOC \\ \hline
7FE0 - 7FFF & IOD \\ \hline
8000 - FFFF & ROM \\ \hline
\end{tabular}
\caption{Memory Map}
\label{Memory Map}
\end{table}
\chapter{Credits}
\href{www.eater.net/6502}{Ben Eater}
\href{https://robin-6502-project.blogspot.com/2020/05/lcd-module-4-bit-mode-with-6522-via.html}{LCD Library} (in Auszügen, wurde angepasst/erweitert)
Datenblätter:
\begin{itemize}
\item 65C02
\item 65C22
\item 6551
\item 6520
\item 74HC00
\item 74HC08
\item 74HC30
\item 74HC154
\item UM61256
\item IS61C5128AS
\item LCDs
\item MAX232
\item AT28C256
\item BluePill
\item NE555
\end{itemize}
\ No newline at end of file
\chapter{Vorwort}
TEST
\begin{lstlisting}[frame=single,language=6502]
INIT:
ror %01011010 ;rotiere Bitmuster 5A
lda #$11 ;lade Accumulator mit "11"
STA $7F00 ;schreibe Accumulator in Adresse 7E00
jmp INIT
rts ;return from subroutine
.word message = "Hello World"
\end{lstlisting}
\ No newline at end of file
\chapter{Toolchain}
Um die Programme und Test-Software für den Computer zu schreiben, wird eine Toolchain benötigt, bestehend aus Editor, Compiler, Linker und Programmer. Bei mir sieht diese Toolchain wie folgt aus. Die Entwicklung wurde auf Ubuntu 20.04 LTS durchgeführt.
\section{Editor}
Als Editor wurde \textit{Visual Studio Code}, kurz VSC, verwendet. Dieses bietet den Vorteil ein ganzes Verzeichnis zu öffnen und hat die Möglichkeit, Erweiterungen zu laden. Eine der Erweiterungen für den Editor ist das Syntax-Highlighting für die 65C02 Assembler-Befehle.
\section{cc65}
Der cc65-Compiler besteht aus drei Modulen: dem cc65 C-Compiler, dem ca65 Assembler-Compiler und dem ld65 Linker.
In meiner Toolchain werden nur der ca65 und der ld65 genutzt. Diese dienen mir als Compiler und Linker für die Sourcecode-Dateien. Der ca65 übersetzt die Quelltexte in Maschinencode, welcher in Object-Dateien (Dateiendung .o) gespeichert wird. Der Linker nimmt nun die Object-Files und setzt diese so um, dass eine Binärdatei (.rom) erzeugt wird und die Adressen entsprechend der Compiler-Direktiven (im Quelltext mit einen . angekündigt, z.B. .word \$FFFC) richtig gesetzt werden. Mit der .rom-Datei kann dann das ROM beschrieben werden.
\section{Programmer}
Zur Programmierung des ROMs wird der TL866A Universal-Programmierer mit der Software \grqq minipro\grqq eingesetzt. Diese kommuniziert mit dem per USB angeschlossenen TL866A, lädt die .rom-Datei und startet den Programmiervorgang.
\section{Vereinfachung der Toolchain}
Um nicht jeden Befehl auf Kommandozeilenebene einzeln ausführen zu müssen, wurde ein BASH-Script erstellt, welches das Compilieren automatisiert. Dieses Script kann sowohl ohne, als auch mit Parametern ausgeführt werden. Folgende Optionen sind dabei möglich:
\begin{table}[H]
\begin{tabular}{ll}
./compile.bash & Compiler und Linker laufen lassen \\
./compile.bash -d & Compiler und Linker laufen lassen und einen Hexdump* ausgeben \\
./compile.bash -f & Compiler und Linker laufen lassen und .rom-Datei direkt flashen
\end{tabular}
\end{table}
*Ein Hexdump ist eine Ausgabe der .rom-Datei als hexadezimale Zeichen. Dadurch kann kontrolliert werden, ob z.B. die Einsprungvektoren an den richtigen Adressen stehen.
\vspace{0,5cm}
Das Script wurde parametrisiert geschrieben, sodass alle verfügbaren Quellcode-Dateien compiliert werden. Dabei muss allerdings die Ordnerstruktur eingehalten werden.
\ No newline at end of file
\chapter{Die Idee}
\section{Der 6502 Prozessor}
Der 6502-Prozessor von MOS-Technologies wurde 1975 auf den Markt gebracht und in vielen Systemen der damaligen Zeit verwendet. Am Bekanntesten davon sind der VIC-20, der Atari-800, Apple I und Apple II.
Gerade seine Einfachheit und sein Preis-Leistung-Verhältnis sorgten für eine große Popularität. Heute wird der 6502 unter anderem von Western Design Center (WDC) als W65C02 in einer C-MOS-Variante gefertigt, die auch statisch betrieben werden kann. Der MOS 6502 konnte dies nicht, da er auf dynamischen Speicher setzte, welcher regelmäßig "reaktiviert" werden musste.
\section{Projektidee}
Die Idee zu diesem Projekt kam mir durch den Youtuber Ben Eater, welcher nicht zuletzt durch seinen TTL-Steckbrett-Computer viel Aufsehen in der Bastler-Szene erregte. Er hat sich nun damit beschäftigt, mit dem 65C02 von WDC einen Steckbrett-Computer zu bauen. Allerdings legte er durch die Restriktion an Steckbretter viel Wert auf Einfachheit, wodurch auch sehr viel Adressraum verschwendet wurde. Auch hatte er nur wenig IO zur Verfügung und keinerlei Kommunikationsmöglichkeit. Lediglich ein LCD, fünf Taster und ROM und RAM waren vorgesehen.
Daher kam mir die Idee, ich könnte das Design nicht nur übernehmen, sondern auch entsprechend abändern, sodass mehr IO, eine Kommunikationsmöglichkeit und eine bessere Memory-Map zur Verfügung stehen.
Obohl die Schaltpläne für Commodore und Atari öffentlich zugänglich sind, wollte ich keinen kompatiblen Computer bauen, sondern etwas eigenes. Außerdem habe ich durch einen anderen Bastlerkollegen einige ICs aus der 65er Reihe bekommen, die ich in diesem Projekt einsetzen wollte.
\section{Überlegung 1: Speicher}
Im Bezug auf Speicher gibt es zwei unterschiedliche Typen: RAM und ROM. Beides braucht ein Computer, um zu funktionieren. Üblicherweise werden im ROM der Programmcode und im RAM die Daten gespeichert. In meinem Computer wollte ich möglichst eine 50:50-Einteilung einhalten. Durch die 16 Adressleitungen des 6502 können 64kB insgesamt adressiert werden, also wären das 32kB ROM und 32kB RAM.
Allerding werden auch für die IOs noch Adressen benötigt. Da mir der ROM etwas wichtiger ist, als der RAM (aus später behandelten Gründen), wurden vom RAM-Adressbereich die oberen 256 Adressen abgezogen und für die IOs benutzt. Da die 65er-ICs überwiegend 16 interne Register haben, die adressiert werden können, liegt eine Einteilung der 256 Adressen in 16x16 Adressen nahe. Da manche ICs aber auch 32 Adressen brauchen können, können bei dieser Einteilung auch Chip-Selects mithilfe von Dioden ver-ODER-t werden. Daduch ergibt sich ein relativ effektives Dekoding.
\subsection{RAM}
Das RAM an sich war eine etwas schwierigere Überlegung. Manchmal will man doch etwas mehr RAM als knapp 32kB zur Verfügung haben. Aber wie kann man mehr adressieren, wenn der Prozessor nur maximal 64kB adressieren kann? Richtig: durch Banking.
So kam der Einfall, man könne den RAM nochmals in zwei Bereiche unterteilen. Ein Teil als BANKED RAM, ein Teil als COMMON RAM, oder Shared RAM. meine Wahl fiel so, dass der untere Adressbereich (die ersten 16kB des RAMs) als Banken realisiert werden, die oberen knapp 16k als gemeinsam genutzter Speicher. Das ergibt viele Vorteile. Zum Einen kann man Daten von einer Bank in eine andere kopieren, zum Anderen sind damit sowohl der Stack-Pointer (Adressbereich 0100-01FF) als auch die so genannte Zero-Page (Adressbereich 0000-00FF) je Bank einzigartig. Daraus kann man vieles anstellen, was sonst zu Problemen führen könnte.
Als Beispiel sei mal Multi-Tasking genannt. Jeder Task kann so in eine eigene Bank des RAMs gelegt werden. Dadurch hat jeder Task seinen eigenen Stack, was einen Stack-Overflow (Überschreitung des Stack-Bereichs) vorbeugen kann. Außerdem kann jeder Task seine eigene Zero-Page benutzen, was für schnelleren Code und dadurch bessere Rechenleistung sorgt.
Da ich für den RAM aber keinen allzu großen IC benutzen wollte, fiel meine Wahl auf einen 512kB-RAM-IC, wodurch sich 32 Banken á 16kB ergeben.
Die Banken werden durch einen 6522 VIA-IC (Versatile Interface Adapter) ausgewählt. Dieser muss allerdings zu Anfang initialisiert werden.
\ No newline at end of file
\chapter{Schaltungsteile}
Im Folgenden werden einzelne Schaltungsteile erklärt.
\section{Power-On-Reset}
Damit der Prozessor bei einem Power-On zuverlässig bootet, wurde an der Reset-Leitung ein RC-Glied vorgesehen, welches die Reset-Leitung des 6502 zu Anfang auf LOW hält, damit der Prozessor zurückgesetzt wird.
\begin{center}
\begin{circuitikz}[european] \draw
(2,0) node[rground] {}
to[C, l=$10\mu F$] (2,2)
to[R, l=$100k\Omega$] (2,4)
to node[vcc] {$5V$} (2,4)
(2,2) to[short, *-] (3,2) node[right] {$\overline{RESET}$}
(2,2) -- (-1,2)
to[push button, mirror] (-1,0)
to node[rground] {} (-1,0)
;
\end{circuitikz}
\end{center}
Zusätzlich zum POR (Power-On-Reset) ist auch noch ein Taster für manuellen Reset vorhanden. Die Zeitkonstante für den POR berechnet sich wie folgt:
\large
\begin{equation}
\tau = R \cdot C = 100k \Omega \cdot 10 \mu F = 1s
\end{equation}
\normalsize
Gemäß Datenblatt Seite 24 ist am Reset-Eingang der HIGH-Pegel bei $Vdd - 0.4V$ Minimum und der LOW-Pegel bei $Vss + 0.4V$ Maximum. Der Raum dazwischen ist nicht definiert.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\newpage
\section{Adress-Decoding}
\subsection{Dekodierung}
Einer der schwierigsten Schaltungsteile war das Adress-Decoding. Dieses muss die Chip-Select Leitungen für die einzelnen Teilnehmer am Bus generieren, ohne größere Laufzeiten zu verursachen.
Um dem gerecht zu werden, wurden die schnellen AC-Varianten der 74er TTL-Reihe benutzt. Einzige Ausnahme bildet dabei der Baustein 74HC30D, ein NAND-Gatter mit acht Eingängen, welcher nicht in der AC-Variante verfügbar ist.
Das Decoding wurde gemacht, nachdem die Memory-Map stand. Diese ist in Anhang A abgebildet.
Anhand der Memory-Map kann nun die Boolsche Algebra gebildet werden. Um die Ausdrücke zu vereinfachen werden die Adressen 7F00 - 7FFF unter der Leitung \textit{IO} zusammengefasst.
\begin{align*}
RAM\_LO &= \overline{A15}\land \overline{A14}\\
RAM\_HI &= \overline{A15}\land A14 \land \overline{IO}\\
IO &= \overline{A15}\land A14 \land A13 \land A12 \land A11 \land A10 \land A9 \land A8\\
ROM &= A15
\end{align*}
Diese Gleichungen lassen sich wie folgt kürzen:\par
(1) ROM ist nur A15 invertiert, also kann in den anderen Termen $\overline{A15}$ durch ROM ersetzt werden. \par
(2) Da alle Chip-Select-Leitungen Low-aktiv sind, werden alle Terme invertiert. Dadurch wird gleichzeitig ersichtlich, dass alles mit NAND-Gattern gelöst werden kann.\\
Somit bilden sich folgende Terme:
\begin{align*}
\overline{RAM\_LO} &= \overline{\overline{ROM}\land \overline{A14}}\\
\overline{RAM\_HI} &= \overline{(\overline{ROM}\land A14)\land \overline{IO}}\\
\overline{IO} &= \overline{\overline{ROM}\land A14 \land A13 \land A12 \land A11 \land A10 \land A9 \land A8}\\
\overline{ROM} &= \overline{A15}
\end{align*}
Anhand dieser Algebra kann nun die Schaltung aus NAND und AND-Gattern gemacht werden. $\overline{IO}$ wird dabei mit einem 8-Input NAND-Gatter realisiert. Die Klammer in $\overline{RAM\_HI}$ ist eingefügt, um die Schaltung an Gatter mit 2 Inputs anzupassen. Ferner werden alle Signalinvertierungen durch NAND-Gatter realisiert, um einen zusätzlichen Inverer-IC zu sparen.
Nachfolgend ist die Schaltung zu sehen.
\begin{center}
\begin{circuitikz}[european]
%draw all gates
\ctikzset{tripoles/european not symbol=ieee circle}
\draw (2,6) node[nand port] (A) {};
\draw (8,4.5) node[nand port] (Lo) {};
\draw (8,2.5) node[nand port] (Hi) {};
\draw (5,4.273) node[nand port] (14) {};
\draw (5,2.727) node[and port] (ROM_14) {};
\begin{scope}
\ctikzset{tripoles/european nand port/height=2.285}
\draw (5,0.2) node[nand port,
number inputs=8] (IO) {};
\end{scope}
%draw all the Labels
\draw
(-2,6) node[right] (A15) {A15}
(-2,1.2) node[right] (A14) {A14}
(-2,0.8) node[right] (A13) {A13}
(-2,0.4) node[right] (A12) {A12}
(-2,0) node[right] (A11) {A11}
(-2,-0.4) node[right] (A10) {A10}
(-2,-0.8) node[right] (A9) {A9}
(-2,-1.2) node[right] (A8) {A8}
(10,6) node[right] (ROM) {$\overline{ROM}$}
(10,4.5) node[right] (LOW) {$\overline{RAM\_LOW}$}
(10,2.5) node[right] (HIGH) {$\overline{RAM\_HIGH}$}
(10,0.2) node[right] (IO_Out) {$\overline{IO}$};
%draw all the connections
\draw
(A.in 1) |- (A.in 2)
(A15) to[short, -*] (0.23,6)
(A.out) |- (IO.in 1)
(A14) -| (IO.in 2)
(A13) -| (IO.in 3)
(A12) -| (IO.in 4)
(A11) -| (IO.in 5)
(A10) -| (IO.in 6)
(A9) -| (IO.in 7)
(A8) -| (IO.in 8)
(IO.out) -| (Hi.in 2)
(14.out) -- (Lo.in 2)
(ROM_14.out) -- (Hi.in 1)
(A.out) to[short, *-] (5,6) -| (Lo.in 1)
(0,1.2) to[short, *-] (0,4.273) to[short, -*] (3.23,4.273)
(14.in 1) |- (14.in 2)
(0,2.5) to [short, *-] (ROM_14.in 2)
(2.2,2.95) to[short, *-] (ROM_14.in 1)
(6.24,6) to[short, *-] (ROM)
(Lo.out) -- (LOW)
(Hi.out) -- (HIGH)
(6.24,0.2) to[short, *-] (IO_Out)
;
;
\end{circuitikz}
\end{center}
Für das weitere IO-Decoding der Adressen 7F00 - 7FFF wird ein "4-zu-16"-Decoder benutzt. Dieser teilt die 256 Adressen durch 16, wodurch 16 Bereiche á 16 Adressen aufgeteilt. Falls ein Gerät am Bus mehr Leitungen braucht, können zwei Adressbereiche über ein Dioden-ODER miteinander verbunden werden. Damit gleich die richtigen Pegel anliegen, wird ein Decoder mit invertierten Ausgängen verwendet. Die Wahl fällt dabei auf den 74HC154. Die Enable-Pins des Decoders wird dabei von der $\overline{IO}$-Leitung angesteuert.
Nachfolgend ist die Schaltung dafür abgebildet.
\begin{center}
\begin{circuitikz}
\ctikzset{multipoles/thickness=3}
\ctikzset{multipoles/dipchip/width=2}
\ctikzset{diodes/scale=0.5}
%draw package
\draw (0,0) node[dipchip, num pins=32, hide numbers, no topmark, external pins width=0] (Mux) {4-to-16};
%draw pins
\node [right] at (Mux.bpin 1) {A};
\node [right] at (Mux.bpin 2) {B};
\node [right] at (Mux.bpin 3) {C};
\node [right] at (Mux.bpin 4) {D};
\node [right] at (Mux.bpin 15) {G1};
\node[notcirc, anchor=0](cs1) at (Mux.bpin 15) {};
\node [right] at (Mux.bpin 16) {G2};
\node[notcirc, anchor=0](cs2) at (Mux.bpin 16) {};
\node [left] at (Mux.bpin 32) {0};
\node[notcirc, anchor=w](o0) at (Mux.bpin 32) {};
\node [left] at (Mux.bpin 31) {1};
\node[notcirc, anchor=w](o1) at (Mux.bpin 31) {};
\node [left] at (Mux.bpin 30) {2};
\node[notcirc, anchor=w](o2) at (Mux.bpin 30) {};
\node [left] at (Mux.bpin 29) {3};
\node[notcirc, anchor=w](o3) at (Mux.bpin 29) {};
\node [left] at (Mux.bpin 28) {4};
\node[notcirc, anchor=w](o4) at (Mux.bpin 28) {};
\node [left] at (Mux.bpin 27) {5};
\node[notcirc, anchor=w](o5) at (Mux.bpin 27) {};
\node [left] at (Mux.bpin 26) {6};
\node[notcirc, anchor=w](o6) at (Mux.bpin 26) {};
\node [left] at (Mux.bpin 25) {7};
\node[notcirc, anchor=w](o7) at (Mux.bpin 25) {};
\node [left] at (Mux.bpin 24) {8};
\node[notcirc, anchor=w](o8) at (Mux.bpin 24) {};
\node [left] at (Mux.bpin 23) {9};
\node[notcirc, anchor=w](o9) at (Mux.bpin 23) {};
\node [left] at (Mux.bpin 22) {10};
\node[notcirc, anchor=w](o10) at (Mux.bpin 22) {};
\node [left] at (Mux.bpin 21) {11};
\node[notcirc, anchor=w](o11) at (Mux.bpin 21) {};
\node [left] at (Mux.bpin 20) {12};
\node[notcirc, anchor=w](o12) at (Mux.bpin 20) {};
\node [left] at (Mux.bpin 19) {13};
\node[notcirc, anchor=w](o13) at (Mux.bpin 19) {};
\node [left] at (Mux.bpin 18) {14};
\node[notcirc, anchor=w](o14) at (Mux.bpin 18) {};
\node [left] at (Mux.bpin 17) {15};
\node[notcirc, anchor=w](o15) at (Mux.bpin 17) {};
%Texte und Linien
\draw (Mux.bpin 1) -- ++(-1,0) coordinate(extpin) node[left] {A4}
(Mux.bpin 2) -- ++(-1,0) coordinate(extpin) node[left] {A5}
(Mux.bpin 3) -- ++(-1,0) coordinate(extpin) node[left] {A6}
(Mux.bpin 4) -- ++(-1,0) coordinate(extpin) node[left] {A7}
(cs1) -- ++(-0.5,0) coordinate(extpin) -- ++(0,-0.56)
(cs2) -- ++(-0.5,0) coordinate(extpin) to[short, *-] ++(-0.5,0) coordinate(extpin) node[left] {$\overline{IO}$}
(o0) -- ++(3,0) coordinate(extpin) node[right] {$\overline{PIA}$}
(o1) -- ++(3,0) coordinate(extpin) node[right] {$\overline{VIA1}$}
(o2) -- ++(3,0) coordinate(extpin) node[right] {$\overline{VIA2}$}
(o3) -- ++(3,0) coordinate(extpin) node[right] {$\overline{VIA3}$}
(o4) -- ++(3,0) coordinate(extpin) node[right] {$\overline{ACIA1}$}
(o5) -- ++(3,0) coordinate(extpin) node[right] {$\overline{ACIA2}$}
(o6) -- ++(3,0) coordinate(extpin) node[right] {$\overline{GPU}$}
(4.5,0) node[right] {$\overline{SID}$} to[short, -*] (3.5,0) |- (3.5,0.3) to[D] (o7)
(3.5,0) |- (3.5,-0.3) to[D] (o8)
(o9) -- ++(3,0) coordinate(extpin) node[right] {$\overline{IO9}$}
(o10) -- ++(3,0) coordinate(extpin) node[right] {$\overline{IOA}$}
(o11) -- ++(3,0) coordinate(extpin) node[right] {$\overline{IOB}$}
(4.5,-2.8) node[right] {$\overline{IOC}$} to[short, -*] (3.5,-2.8) |- (3.5,-2.5) to[D] (o12)
(3.5,-2.8) |- (3.5,-3.1) to[D] (o13)
(4.5,-3.9) node[right] {$\overline{IOD}$} to[short, -*] (3.5,-3.9) |- (3.5,-3.6) to[D] (o14)
(3.5,-3.9) |- (3.5,-4.2) to[D] (o15)
;
;
\end{circuitikz}
\end{center}
An den Leitungen $\overline{SID}$, $\overline{IOC}$ und $\overline{IOD}$ sind noch Pull-Up Widerstände angeschlossen. Das Dioden-ODER wurde so realisiert, um einen IC für die Verknüpfung zu sparen und den Adressbereich für diese Select-Leitungen zu erweitern.
\subsection{Laufzeitbetrachtung}
Um zu verifizieren, dass die Gatterlaufzeiten (Propagation Delay) nicht zu lange dauern, werden nun die Laufzeiten der Signale betrachtet. Alle Datenblätter sind von Nexperia bezogen.\par
Gemäß Datenblätter sind die Laufzeiten wie folg:
\begin{itemize}
\item 74HC00 = 7ns
\item 74HC08 = 7ns
\item 74HC30 = 12ns
\item 74HC154 = 11ns
\end{itemize}
Daraus schließen sich folgende Laufzeiten für die Signale:
\begin{align*}
\overline{ROM} &= 7ns &= 7ns\\
\overline{RAM\_LO} &= 7ns + 7ns &= 14ns\\
\overline{RAM\_HI} &= 7ns + 7ns + 7ns &= 21ns\\
\overline{IO} &= 12ns &= 12ns\\
\overline{PIA} &= 12ns + 11ns &= 23ns
\end{align*}
Die $\overline{PIA}$-Leitung wurde hierbei exemplarisch für die 16 IO-Adressbereiche gewählt.
\vspace{0,5cm}
Wie man sieht, sind die Laufzeiten sehr kurz. Bei einer Taktfrequenz von 1MHz (Periodendauer von 1000ns) fallen diese Zeiten nicht auf, da sie über 40 mal kleiner sind. Die Timings sind damit ausreichend klein um die Funktion nicht zu beeinträchtigen.
\chapter{Logic Analyzer}
Auf der Platine ist ein Sockel für das BluePill-Entwicklungsboard mit einem STM32F1-Controller vorgesehen. Dieses Board ist als integrierter Logic-Analyzer eingeplant, welcher über USB serielle Daten ausgibt.\par
Dabei wird folgendes Format im seriellen Monitor ausgegeben:
\vspace{0,25cm}
\begin{tabular}{|ccccc|}
\hline
Adresse Binär & Daten Binär & Adresse Hex & Daten Hex & R/W\\
1000000010110101 & 10010110 & 805E & 96 & R \\\hline
\end{tabular}
\vspace{0,25cm}
Der Logic-Analyzer zeichnet also den Adressbus, den Datenbus und die Read/Write-Leitung auf. Zum Triggern wird dabei die Clock-Leitung benutzt.
Wenn der Jumper auf dem BluePill-Board gesteckt wird, wird der Pin für die Clock-Leitung zum Ausgang und gibt den Takt für den Computer vor. Dies ist zu Testzwecken gedacht. Mit dem Trimmer auf der Hauptplatine lässt sich zudem die Frequenz im Bereich von 0,1Hz bis 1kHz einstellen.
\ No newline at end of file
\chapter{Text-Codes}
\section{ROM-Test}
Der Code für den ROM-Test ist relativ naheliegend. Da der Prozessor den Code aus dem ROM liest und ausführt, werden ein paar Zeilen Code für den ROM geschrieben und mit dem Logic-Analyzer werden die entsprechenden Instructions verifiziert.
Der Test-Code sieht dabei wie folgt aus.
\begin{lstlisting}[frame=single,language=6502]
.segment "VECTORS"
.word 8000
.word 8000
.word 8000
.code
LOOP:
nop
jmp LOOP
\end{lstlisting}
Die Compiler-Direktiven (mit . angekündigt) legen in diesem Falle fest, dass die Vektoren (NMI, Reset und Interrupt) definiert werden und der Code bei Adresse 8000 anfängt.
Der Testcode selbst besteht lediglich aus einem NOP-Befehl (No OPeration) und einer JuMP-Anweisung auf das Label LOOP, um so eine Endlosschleife zu durchlaufen.
\newpage
\section{RAM-Test}
Beim RAM-Test muss beachtet werden, dass es zwei RAMs im Design gibt. Der Common RAM ist einfach zu testen durch ein schreiben und Rücklesen eines Wertes. Der Banked RAM ist da anders. Da noch keine VIA-ICs eingesetzt sind, wird erstmal nur eine Bank getestet. Dafür müssen an VIA1 die Pins 10-14 auf Masse gelegt werden.
Der TestCode für den RAM sieht nun wie folgt aus:
\begin{lstlisting}[frame=single,language=6502]
.segment "VECTORS"
.word 8000
.word 8000
.word 8000
.code
LOOP:
lda #$55 ; lade Bitmuster 01010101 in A
sta $4000 ; schreibe A in Adresse 4000 (Common RAM)
lda #$AA ; lade Bitmuster 10101010 in A
sta $0200 ; schreibe A in Adresse 0200 (Banked RAM)
lda $4000 ; lade Wert Adresse 4000 in A
adc $0200 ; addiere den Wert von Adresse 0200
sta $00 ; schreibe Ergebnis in Adresse 0000
jmp LOOP ; wiederhole alles
\end{lstlisting}
Der ganze Prozess wird mit dem Logic-Analyzer angeschaut und nachvollzogen. Das Ergebnis sollte sein, dass der Wert 0xFF in einem Write-Zyklus nach Adresse 0x0000 (Erste Adresse in der Zero-Page) gespeichert wird.
\ No newline at end of file
\chapter{Inbetriebnahme}
\section{Zusammenbau}
Es wurde alles auf einmal verlötet, \textcolor{red}{wird noch genauer beschrieben}
Bei allen folgenden Tests ist das BluePill-Board als Logic-Analyzer angeschlossen.
\section{Adress-Decoding}
\section{CPU}
\section{ROM}
\section{Shared-RAM}
\section{PIA}
\section{VIA}
\section{Banked-RAM}
\section{LCD}
\section{IRQ}
\section{NMI}
\section{ACIA}
\chapter{Fehlerbesprechung}
Leider wurden Fehler gemacht. Das Erkennen und Beheben der Fehler gehört hierbei zum Lernprozess hinzu. Folgend werden alle Fehler und ihre Lösungen an der Hardware dokumentiert, erläutert und besprochen.
\section{BluePill Logic-Analyzer wird an Computer nicht erkannt}
\subsection{Fehlerverhalten}
Das BluePill-Board wird auf die 6502-Platine gesteckt und per USB mit einem Computer verbunden. Fehlermeldung des Betriebssystems liefert \grqq USB-Gerät wurde nicht erkannt!\grqq
Zu Testzwecken wird das BluePill-Board aus der 6502-Platine herausgenommen und mit einem Computer verbunden. Das Gerät wird nun erkannt und funktioniert.
\subsection{Grund des Fehlers}
Die USB-Pins am STM32 liegen an PA11 und PA12. Diese sind an die Adressleitungen A8 und A7 angeschlossen. Dies wurde gemacht, da laut Spezifikation diese Pins 5V-kompatibel sind. Die USB-Funktion der beiden Pins wurde übersehen. Dadurch kommt es zu Kollisionen und der USB-Verkehr wird gestört.
\subsection{Behebung des Fehlers}
Auf der 6502-Platine werden die beiden Buchsen für PA11 und PA12 entfernt, damit diese nicht mehr an das BluePill-Board verbunden sind. Auf dem BluePill sind noch zwei freie Pins, die allerdings nicht 5V-kompatibel sind. Mittels vier 22k$\Omega$-Widerständen als Spannungsteiler werden die Adressleitungen A7 und A8 nun an PC14 und PC15 verbunden. Der Firmware-Code für das BluePill-Board wird entsprechend angepasst.
\section{Fehlerhaftes Adress-Decoding}
\subsection{Fehlerverhalten}
Beim Testen des VIA2 hat dieser trotz richtiger Adresse auf dem Bus kein Chip-Select bekommen. Mit Multimeter bei statischem Takt wurde festgestellt, dass ACIA1 den Chip-Select bekam, welcher aber noch nict bestückt war.
\subsection{Grund des Fehlers}
Das IO-Decoding der CHip-Selects wird vom 74HC154 übernommen. Beim genaueren Betrachten des Schaltplans wurde festgestellt, dass A4 bis A7, welche die Auswahl der Chip-Selects vorgeben, in falscher Reihenfolge an den IC verdrahtet wurden. Dadurch ist die Memory-Map für die IOs verdreht. Da allerdings einige Ausgänge über ein Dioden-ODER miteinander verbunden sind, ist eine Software-Lösung komplizierter.
\subsection{Behebung des Fehlers}
Die Leitungen, welche an die Pins 20 bis 23 des IC führen, wurden auf der Unterseite der Platine durch abkratzen unterbrochen. Mit einem feinen Fädeldraht (Lack-isolierte dünne Kupferleitung) wurden nun die vier Adressleitungen in der richtigen Reihenfolge an den IC angeschlossen.
Damit das durch Kratzen freigelegte Kupfer nicht oxidiert und um den Fehler aus ästhetischen Gründen weniger sichtbar zu machen, wurden die Stellen zweischichtig mit schwarzem Edding übermalt. Dadurch wird die Stelle kaschiert und das Kupfer oxidiert nicht.
\section{Falsche Rücksprungadresse nach Interrupt}
\subsection{Fehlerverhalten}
Nach der Interrupt-Service-Routine springt der Prozessor an eine falsche Adresse und crasht. Rücksprung in das Programm nicht möglich.
\subsection{Grund des Fehlers}
Die /WE-Leitung des RAMs darf nicht LOW sein, wenn der Takt auf LOW ist. Es entstehen instabile Daten die nicht korrekt geschrieben werden.
\subsection{Behebung des Fehlers}
Das R/W-Signal des Prozessors wurde mittels neuem 74HC00 NAND-IC invertiert und mit dem Takt per NAND-Gatter verknüpft. Der /WE-Pin des RAMs wurde von der Leiterplatte hochgehoben und mittels Patch-Kabeln an den Output des Gatters verbunden. Somit ist sichergestellt, dass der /WE nur dann auf LOW gehen kann, wenn der Takt auf HIGH geht. Die Invertierung des R/W-Signals war dafür vonnöten.
Folgend die resultierende Boolsche Verknüpfung:
\begin{align*}
\overline{RAM\_WE} &= \overline{\overline{R/W}\land CLK}
\end{align*}
Gleichzeitig wurde bemerkt, dass der 65C22 von WDC bei 1MHz Taktung keinen Interrupt triggert. Da dieser eine CMOS-Endstufe hatte war kein externer Pullup nötig. Der 65C22 wurde durch einen R65C22 von Rockwell ausgetauscht. Dieser besitzt nur einen Open-Drain am IRQ-Pin, wodurch noch ein externer Pullup-Widerstand von 10kOhm nötig und eingebaut wurde.
\chapter{Rechtfertigung der Harware-Fixes}
Die Hardware-Bugs auf diese Art zu reparieren hat mehrere Gründe:
(1) Da das Board noch ein Prototyp ist, können noch weitere Fehler vorhanden sein. Bei jedem Fehler ein Redesign zu machen ist somit unwirtschaftlich.
(2) Da der 6502-Computer nach Technik aus den 80er-Jahren nachempfunden ist, so ist es weniger dramatisch, wenn so genannte "Bodge-Wires" vorhanden sind. Selbst in den ersten Revisionen der C64- und C128-Computer waren schon ab Werk Hardware-Fixes durch nachträglich eingelötete Drähte vorhanden. Dadurch kann man auch mit dem Punkt argumentieren, der Computer sei \grqq historisch akkurat\grqq.
\ No newline at end of file
\relax
\providecommand\hyper@newdestlabel[2]{}
\providecommand*\new@tpo@label[2]{}
\@nameuse{bbl@beforestart}
\catcode `"\active
\providecommand\HyperFirstAtBeginDocument{\AtBeginDocument}
\HyperFirstAtBeginDocument{\ifx\hyper@anchor\@undefined
\global\let\oldcontentsline\contentsline
\gdef\contentsline#1#2#3#4{\oldcontentsline{#1}{#2}{#3}}
\global\let\oldnewlabel\newlabel
\gdef\newlabel#1#2{\newlabelxx{#1}#2}
\gdef\newlabelxx#1#2#3#4#5#6{\oldnewlabel{#1}{{#2}{#3}}}
\AtEndDocument{\ifx\hyper@anchor\@undefined
\let\contentsline\oldcontentsline
\let\newlabel\oldnewlabel
\fi}
\fi}
\global\let\hyper@last\relax
\gdef\HyperFirstAtBeginDocument#1{#1}
\providecommand\HyField@AuxAddToFields[1]{}
\providecommand\HyField@AuxAddToCoFields[2]{}
\providecommand\BKM@entry[2]{}
\babel@aux{ngerman}{}
\pgfsyspdfmark {pgfid1}{33284474}{7065781}
\pgfsyspdfmark {pgfid2}{33284474}{7065781}
\BKM@entry{id=1,dest={636861707465722E32},srcline={134}}{436F64652D5665727A656963686E6973}
\@writefile{toc}{\contentsline {chapter}{\numberline {I}Code-Verzeichnis}{III}{chapter.2}\protected@file@percent }
\@writefile{lof}{\addvspace {10\p@ }}
\@writefile{lot}{\addvspace {10\p@ }}
\@writefile{lol}{\addvspace {10\p@ }}
\BKM@entry{id=2,dest={636861707465722E33},srcline={137}}{416262696C64756E67737665727A656963686E6973}
\@writefile{toc}{\contentsline {chapter}{\numberline {II}Abbildungsverzeichnis}{IV}{chapter.3}\protected@file@percent }
\@writefile{lof}{\addvspace {10\p@ }}
\@writefile{lot}{\addvspace {10\p@ }}
\@writefile{lol}{\addvspace {10\p@ }}
\BKM@entry{id=3,dest={636861707465722E34},srcline={1}}{566F72776F7274}
\@writefile{toc}{\contentsline {chapter}{\numberline {1}Vorwort}{1}{chapter.4}\protected@file@percent }
\@writefile{lof}{\addvspace {10\p@ }}
\@writefile{lot}{\addvspace {10\p@ }}
\@writefile{lol}{\addvspace {10\p@ }}
\BKM@entry{id=4,dest={636861707465722E3134},srcline={1}}{546F6F6C636861696E}
\BKM@entry{id=5,dest={73656374696F6E2E3135},srcline={5}}{456469746F72}
\BKM@entry{id=6,dest={73656374696F6E2E3136},srcline={8}}{63633635}
\BKM@entry{id=7,dest={73656374696F6E2E3137},srcline={13}}{50726F6772616D6D6572}
\BKM@entry{id=8,dest={73656374696F6E2E3138},srcline={16}}{56657265696E66616368756E672064657220546F6F6C636861696E}
\@writefile{toc}{\contentsline {chapter}{\numberline {2}Toolchain}{2}{chapter.14}\protected@file@percent }
\@writefile{lof}{\addvspace {10\p@ }}
\@writefile{lot}{\addvspace {10\p@ }}
\@writefile{lol}{\addvspace {10\p@ }}
\@writefile{toc}{\contentsline {section}{\numberline {2.1}Editor}{2}{section.15}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{\numberline {2.2}cc65}{2}{section.16}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{\numberline {2.3}Programmer}{2}{section.17}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{\numberline {2.4}Vereinfachung der Toolchain}{2}{section.18}\protected@file@percent }
\BKM@entry{id=9,dest={636861707465722E3139},srcline={1}}{4469652049646565}
\BKM@entry{id=10,dest={73656374696F6E2E3230},srcline={2}}{44657220363530322050726F7A6573736F72}
\BKM@entry{id=11,dest={73656374696F6E2E3231},srcline={7}}{50726F6A656B7469646565}
\BKM@entry{id=12,dest={73656374696F6E2E3232},srcline={14}}{5C3333346265726C6567756E6720313A205370656963686572}
\@writefile{toc}{\contentsline {chapter}{\numberline {3}Die Idee}{4}{chapter.19}\protected@file@percent }
\@writefile{lof}{\addvspace {10\p@ }}
\@writefile{lot}{\addvspace {10\p@ }}
\@writefile{lol}{\addvspace {10\p@ }}
\@writefile{toc}{\contentsline {section}{\numberline {3.1}Der 6502 Prozessor}{4}{section.20}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{\numberline {3.2}Projektidee}{4}{section.21}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{\numberline {3.3}Überlegung 1: Speicher}{4}{section.22}\protected@file@percent }
\BKM@entry{id=13,dest={73756273656374696F6E2E3233},srcline={18}}{52414D}
\@writefile{toc}{\contentsline {subsection}{\numberline {3.3.1}RAM}{5}{subsection.23}\protected@file@percent }
\BKM@entry{id=14,dest={636861707465722E3234},srcline={1}}{536368616C74756E67737465696C65}
\BKM@entry{id=15,dest={73656374696F6E2E3235},srcline={4}}{506F7765722D4F6E2D5265736574}
\@writefile{toc}{\contentsline {chapter}{\numberline {4}Schaltungsteile}{6}{chapter.24}\protected@file@percent }
\@writefile{lof}{\addvspace {10\p@ }}
\@writefile{lot}{\addvspace {10\p@ }}
\@writefile{lol}{\addvspace {10\p@ }}
\@writefile{toc}{\contentsline {section}{\numberline {4.1}Power-On-Reset}{6}{section.25}\protected@file@percent }
\BKM@entry{id=16,dest={73656374696F6E2E3237},srcline={32}}{4164726573732D4465636F64696E67}
\BKM@entry{id=17,dest={73756273656374696F6E2E3238},srcline={33}}{44656B6F64696572756E67}
\@writefile{toc}{\contentsline {section}{\numberline {4.2}Adress-Decoding}{7}{section.27}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {4.2.1}Dekodierung}{7}{subsection.28}\protected@file@percent }
\BKM@entry{id=18,dest={73756273656374696F6E2E3239},srcline={197}}{4C6175667A6569746265747261636874756E67}
\@writefile{toc}{\contentsline {subsection}{\numberline {4.2.2}Laufzeitbetrachtung}{9}{subsection.29}\protected@file@percent }
\BKM@entry{id=19,dest={636861707465722E3330},srcline={1}}{4C6F67696320416E616C797A6572}
\@writefile{toc}{\contentsline {chapter}{\numberline {5}Logic Analyzer}{10}{chapter.30}\protected@file@percent }
\@writefile{lof}{\addvspace {10\p@ }}
\@writefile{lot}{\addvspace {10\p@ }}
\@writefile{lol}{\addvspace {10\p@ }}
\BKM@entry{id=20,dest={636861707465722E3331},srcline={1}}{546578742D436F646573}
\BKM@entry{id=21,dest={73656374696F6E2E3332},srcline={2}}{524F4D2D54657374}
\@writefile{toc}{\contentsline {chapter}{\numberline {6}Text-Codes}{11}{chapter.31}\protected@file@percent }
\@writefile{lof}{\addvspace {10\p@ }}
\@writefile{lot}{\addvspace {10\p@ }}
\@writefile{lol}{\addvspace {10\p@ }}
\@writefile{toc}{\contentsline {section}{\numberline {6.1}ROM-Test}{11}{section.32}\protected@file@percent }
\BKM@entry{id=22,dest={73656374696F6E2E3434},srcline={22}}{52414D2D54657374}
\@writefile{toc}{\contentsline {section}{\numberline {6.2}RAM-Test}{12}{section.44}\protected@file@percent }
\BKM@entry{id=23,dest={636861707465722E3633},srcline={1}}{496E626574726965626E61686D65}
\BKM@entry{id=24,dest={73656374696F6E2E3634},srcline={2}}{5A7573616D6D656E626175}
\BKM@entry{id=25,dest={73656374696F6E2E3635},srcline={7}}{4164726573732D4465636F64696E67}
\BKM@entry{id=26,dest={73656374696F6E2E3636},srcline={9}}{435055}
\BKM@entry{id=27,dest={73656374696F6E2E3637},srcline={12}}{524F4D}
\BKM@entry{id=28,dest={73656374696F6E2E3638},srcline={14}}{5368617265642D52414D}
\BKM@entry{id=29,dest={73656374696F6E2E3639},srcline={16}}{504941}
\BKM@entry{id=30,dest={73656374696F6E2E3730},srcline={17}}{564941}
\BKM@entry{id=31,dest={73656374696F6E2E3731},srcline={18}}{42616E6B65642D52414D}
\BKM@entry{id=32,dest={73656374696F6E2E3732},srcline={19}}{4C4344}
\BKM@entry{id=33,dest={73656374696F6E2E3733},srcline={20}}{495251}
\BKM@entry{id=34,dest={73656374696F6E2E3734},srcline={21}}{4E4D49}
\BKM@entry{id=35,dest={73656374696F6E2E3735},srcline={22}}{41434941}
\@writefile{toc}{\contentsline {chapter}{\numberline {7}Inbetriebnahme}{13}{chapter.63}\protected@file@percent }
\@writefile{lof}{\addvspace {10\p@ }}
\@writefile{lot}{\addvspace {10\p@ }}
\@writefile{lol}{\addvspace {10\p@ }}
\@writefile{toc}{\contentsline {section}{\numberline {7.1}Zusammenbau}{13}{section.64}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{\numberline {7.2}Adress-Decoding}{13}{section.65}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{\numberline {7.3}CPU}{13}{section.66}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{\numberline {7.4}ROM}{13}{section.67}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{\numberline {7.5}Shared-RAM}{13}{section.68}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{\numberline {7.6}PIA}{13}{section.69}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{\numberline {7.7}VIA}{13}{section.70}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{\numberline {7.8}Banked-RAM}{13}{section.71}\protected@file@percent }