summaryrefslogtreecommitdiffstats
path: root/doc/report/z80uPC.tex
blob: eaad987a3079dfdc5cf1d0320c1004dd6fa72957 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
\documentclass[a4paper, 11pt, twoside]{article}

\usepackage{array}
\usepackage{float}
\usepackage{wrapfig}

% source code
\usepackage{listings}

% set correct hypenation
\usepackage[italian]{babel}

% set margins
\usepackage[
    inner=2.5cm, 
    outer=2.5cm,
    top=3cm,
    bottom=3.75cm
]{geometry}

% set headers
\usepackage{fancyhdr}
\pagestyle{fancyplain}
\fancyhf{}
\setlength{\headheight}{1.3cm}
\rhead{\includegraphics[height=1.25cm]{res/logo_sam}}
\lfoot{SAM 3E - Naoki Pross}
\rfoot{\thepage}

% set font
\usepackage{fontspec}
\setmainfont{Roboto}
\setmonofont{Roboto Mono}

% to fix macros
\usepackage{xspace}
% commands
% macro for project name
\newcommand{\prj}{Z80μPC\xspace}

% invert signal (not, active low)
\newcommand{\inv}[1]{$\overline{\mbox{#1}}$}
 
% metadata
\title{\vspace{-1cm}\texttt{\prj} Single Board \\ Computer Development }
\author{Naoki Pross}

% document 
\begin{document}

\maketitle
\begin{abstract}
    Lo Zilog Z80 \`e un processore a 8 bit che fu introdotto nel 1976 che ebbe
    un grandissimo successo nel mondo dell'elettronica e dell'informatica
    nella fine del 20esimo secolo. In memoria di questo processore pioniere
    dell'industria di sistemi embedded ho deciso di costruire un computer a
    scopo generico intorno a questa piattaforma. L'obiettivo \`e di realizzare
    una scheda programmabile con tutti i componenti necessari come ROM, RAM e
    timers per far funzionare del software programmato se possibile sul
    dispositivo stesso.
\end{abstract}

\section{Specifiche tecniche dello Z80}
Lo Z80 \`e un processore molto minimalistico se paragonato a ci\`o che si
trova oggi sul mercato dei microcontrollori. Per il mio progetto ho deciso di
utilizzare il modello originale \texttt{Zilog Z8400} che non dispone di
sistemi integrati come i modelli SoC odierni. Le specifiche pi\`u importanti
sono elencate a seguire.

\begin{itemize}
    \item Architettura a 8 bit con bus a 16 bit con 64K indirizzi indirizzabili
    \item Registri a 16 bit per {\tt SP,PC} e registri di utilizzo generico a
        8 bit {\tt A..F} combinabili a coppie {\tt AF,BC,..} per utilizzare
        valori a 16 bit
    \item Clock fino a 8 MHz
    \item Segnali di controllo tra cui \texttt{\inv{RD}, \inv{WR},
        \inv{IOREQ}, \inv{MREQ}} e \texttt{\inv{RST}}
    \item Interrupts mascherabili e non con vettore a 8 bit
\end{itemize}

\section{Architettura di base}
Il minimo necessario per far funzionare un computer con lo Z80 sono una ROM e
una RAM, ma per il mio progetto ho scelto di aggiungere dell'hardware
aggiuntivo per lo sviluppo si sistemi pi\`u complessi per apprendere
conoscenze sia nel mondo dell'elettronica che dell'informatica. Per questa 
ragione lo \prj possiede i seguienti componenti:

\begin{center}
\begin{tabular}{ >{\tt}l >{\tt\bfseries}l p{.7\linewidth} }
    % \hline \\
    ROM & M28C64    & EEPROM da 8KB x 8 bit (64K) per il BIOS / Bootloader /
                      OS installata doppia per avere 16KB \\
    RAM & HM62256B  & SRAM da 32KB x 8bit (256K) \\
    CTC & Z8430     & Counter timer circuit ufficiale di Zilog a 4 canali che
                      permette di essere programmato \\
    PIO & Z8420     & Parallel input/output controller di Zilog per avere un
                      intefaccia digitale con due porte da 8 bit \\
    MMU & M4-32/32-15JC & CPLD programmabile che implementa una memory 
                          management unit semplificata in grado di gestire i 5
                          bit pi\`u significativi della linea di indirizzi \\
    USART & TL16C550C & Interfaccia USART per poter comunicare utilizzando il
                        protocollo RS232
\end{tabular}
\end{center}

Oltre a tutto ci\`o per uno scopo formativo lo \prj dispone anche di strumenti
da debug e analisi per comprendere ogni operazione del processore. Il modello
di Z80 scelto \`e in grado di utilizzare un clock fino a 8MHz, ma non
definisce un minimo dunque sono presenti 3 circuiti che generano 3 clock di
velocit\`a differenti.

\begin{center}
\begin{tabular}{ >{\bfseries}r p{.8\linewidth} }
    0Hz     & Questo clock \`e un bottone che permette di creare
              manualmente le pulsazioni del clock, per poter analizzare
              ogni istruzione \\
    200Hz   & Mediante un classico circuito con un LM555 si ha un clock da
              200Hz per eseguire i programmi a velocit\`a rallentata \\
    4MHz    & Clock per esecuzione a velocit\`a piena (normale)
\end{tabular}
\end{center}

Una seconda disposizione per aiutare la comprensione del funzionamento del
processore \`e data da 6 display a 7 segmenti che durante l'esecuzione
rallentata o a step (bottone) visualizzano i bytes presenti sulla bus di
indirizzi a 16 bit e sul bus di dati a 8 bit.

\begin{figure}[!h] \centering
    \includegraphics[width=\linewidth]{res/bus_displays}
    \caption{Display a 7 segmenti per visualizzare il flusso di dati della
    CPU}
\end{figure}

\section{Memory Management Unit}

Alcuni modelli successori dello Z8400 implementavano una MMU SoC che
permetteva di indirizzare un address space di dimensione maggiore. Per lo \prj
non necessito di un indirizzamento pi\`u grande ma piuttosto sono interessato
dalle operazioni di gestione della memoria di una MMU simile a ci\`o che
accade nelle architetture X86. Nelle architetture odierne basate sull'X86/64
\`e presente un sistema di traslazione di indirizzi di memoria da virtuale a
fisica. Con lo scopo di trarne solamente i vantaggi pi\`u fondamentali lo \prj
implementa nella CPLD MMU un sistema basilare di gestione di pagine di memoria
con traslazione di indirizzi in modo da poter allocare pi\`u programmi nella
RAM anche se il sistema non implementa il multitasking.

% TODO: write about this in more details

\subsection{Address Space}

\begin{wrapfigure}{r}{.4\linewidth} \centering
    \vspace{8mm}
    \includegraphics[width=.9\linewidth]{res/addrspace}
    \vspace{4mm}
    \caption{Address space dello \prj}
\end{wrapfigure}
La funzione primaria della MMU \`e di mappare i dispositivi I/O e le memorie
nell'address space. Nell'implementazione reale la MMU controlla i segnali {\tt
\inv{CS}} seguendo una logica combinatoria molto semplice che controlla se
l'indirizzo sul bus si trova in una zona definita per un dispositivo.
L'address space si presenta dunque nella seguente maniera, per cui la ROM
occupa il primo quarto, i dispositivi mappabili il secondo quarto e la RAM la
met\`a restante. Essendo un progetto pensato per essere esteso 16KB sono
liberi per mappare dispositivi esterni collegati attraverso il connettore 
DIN41612.

% \begin{wrapfigure}{l}{.4\linewidth} \centering
%     \includegraphics[width=.8\linewidth]{res/iospace}
% \end{wrapfigure}

\subsection{Page Table}

Per poter controllare la traslazione degli indirizzi la MMU dispone di una
Page Table a cui \`e possibile accedere attraversso un certo indirizzo
nell'I/O space. La page table di 5 bit permette la gestione delle regioni di
memoria da impostare per dei determinati processi. Questa funzione \`e 
importante perch\`e permette la separazione dello stack e della memoria della
kernel dai programmi normali. Per lo \prj potrebbe sembrare eccessivo ma
essendo uno strumento per apprendere le fondamenta dell'elettronica e
dell'informatica \`e interessante implementare questa funzionalit\`a che
comunque se necessario pu\`o essere disabilitata.

\section{Schema a blocchi}

\begin{figure}[!h] \centering
    \includegraphics[width=.85\linewidth]{res/block_diagram}
\end{figure}

\section{Software / Sistema operativo}

Negli sviluppi pi\`u recenti intorno allo Z80 esso veniva utilizzato come un
microcontrollore anzich\`e come processore da computer, per questa ragione non
sono presenti molti sistemi operativi per questa piattaforma. Dunque per lo
\prj il progetti implementa un sistema operativo soprannominato {\tt
HelvetiOS} con le funzioni minime necessarie come un interfaccia seriale a
comandi e un meccanismo per caricare i programmi.

\subsection{Componenti di base}

Per garantire un funzionamento minimo il sistema {\tt HelvetiOS} deve offrire
drivers e utility di base quali:

\begin{center}
\begin{minipage}[t]{.4\linewidth}
    \begin{itemize}
        \item USART driver and API
        \item PIO driver and API
        \item CTC driver and API
    \end{itemize}
\end{minipage}%
\begin{minipage}[t]{.4\linewidth}
    \begin{itemize}
        \item Bootloader
        \item Program launcher
        \item Shell-like interface
    \end{itemize}
\end{minipage}
\end{center}

\subsection{Interfacce dell'API} 

Nel corso dello sviluppo questa sezione verr\`a continuamente espansa per
documentare le interfacce dei vari drivers.

\subsubsection{USART}
\begin{lstlisting}[language=C, basicstyle=\ttfamily]
void usart_set_baudrate(uint16_t baudrate);
void usart_set_parity(int mode);
void usart_set_stop_bits(int count);
void usart_set_word_length(int length);
void usart_set_autoflow(int mode);

inline void usart_init(uint16_t baudrate, int parity, int stop_bits); 

void usart_transmit(uint8_t data);
uint8_t usart_receive();

int usart_write(uint8_t *data, size_t size);
int usart_read(uint8_t *buffer, size_t count);
\end{lstlisting}

% \subsection{PIO}

\subsection{Toolchain per la compilazione}

Per compilare il software del progetto si utilizza SDCC, un progetto
open-source che supporta la compilazione di binari per l'architettura dello
Z80. Nella mia configurazione utilizzo GNU make con il seguente makefile.

\newpage
\begin{lstlisting}[language=make, numbers=left, basicstyle=\ttfamily]
####
# Source code settings
#
OSNAME := helvetiOS

CSOURCES    := $(wildcard kernel/*.c) $(wildcard libc/*.c)
OBJECTS     := $(patsubst %.c,build/%.rel,$(CSOURCES))
HEXFILE     := build/$(OSNAME).hex
BINARY      := build/$(OSNAME).bin

###
# Compiler settings

CC      := sdcc

CFLAGS  := -mz80 \
            -I kernel/include -I libc/include -DDEBUG

LDFLAGS := -mz80 --no-std-crt0 crt0.rel \
            --code-loc 0x0800 --data-loc 0x8000

.PHONY: dirs dis clean
all: $(BINARY)

# build binary
$(BINARY): $(OBJECTS) dirs
    $(CC) $(LDFLAGS) $(OBJECTS) -o $(HEXFILE)
    xxd -r -p $(HEXFILE) $(BINARY)

$(OBJECTS): build/%.rel : %.c $(CSOURCES) dirs crt0.rel
    $(CC) $(CFLAGS) -c $< -o $@

crt0.rel: crt0.s
    sdasz80 -o $<

dirs:
    mkdir -p build build/kernel build/libc

dis: $(BINARY)
    z80dasm -a -g 0h $< -o $(OSNAME).s

clean:
    - rm -rd build/*
    - rm $(OSNAME).s
    - rm crt0.rel
\end{lstlisting}

\end{document}