Make gtk build conditional
[jelmer/at89prog.git] / at89prog.tex
1 \documentclass[a4paper]{article}
2
3 \usepackage{listings}
4 \usepackage{graphicx}
5 \begin{document}
6
7 \title{Programming the AT89S8252 using SPI}
8 \date{August 5, 2003}
9 \author{Jelmer Vernooij}
10 \maketitle
11
12 \begin{center}
13         Thanks to Hans Tjeerdsma for his help with understanding the datasheets and debugging
14 \end{center}
15
16 \begin{abstract}
17     Copyright \copyright\ 2003---2004  Jelmer Vernooij (jelmer@samba.org).
18         This documentation is distributed under the GNU General Public License (GPL) version 2 or later.
19 \end{abstract}
20
21 \lstset{language=C}
22
23 \tableofcontents
24
25 \section{Introduction}
26
27 The 8051 and 8052 microprocessors are very common processors. Quite some 
28 manufacturers (among them are Intel, Atmel and Analog Devices) produce 8051
29 processors. Personally, I have experience with the Atmel and the Analog Devices
30 processors. 
31
32 Atmel's 8051 processors can be programmed with two different protocols: 
33 a parallel protocol that I will not discuss here, and the SPI protocol. 
34
35 \section{Reasons for writing my own programmer}
36
37 There are several SPI programmers available for the Atmel 8051 series, however
38 only few of them are available for Linux, and none that I could find used 
39 a serial port or had a GUI.
40
41 Available programmers (and reasons not to use them):
42
43 \begin{itemize}
44 \item ponyprog --- has a GUI and is written in C++
45 \item 89prog --- uses the parallel port
46 \item sp89 --- uses the parallel port
47 \item atmel-isp --- only for windows, no source code available
48 \end{itemize}
49
50 And of course, figuring out the protocol with the help of a logic analyser and 
51 some datasheets is a lot of fun...
52
53 \section{The way other manufacturers do it}
54
55 Previously, for my work, I have written a programmer for Analog Devices
56 8051. Their protocol is quite a bit better since it uses the standard RS232
57 protocol. Something that also helps is the fact that their microcontroller 
58 acknowledges or (refuses) commands it gets, while with the AT89 processors, 
59 you just have to guess that the processor understood what you wanted.
60
61 Next to that, Analog Devices provided an example program that could be 
62 used to program the microcontroller of the serial port.
63
64 \section{Other data lines used by the Atmel}
65
66 Next to the lines necessary for SPI, there is another used for putting 
67 the processor in programmable mode:
68
69 \begin{itemize}
70 \item[RST] Reset. Used to put microprocessor in programmable state. Also used to restart running program (by toggling). (Connected to DTR on my board)
71 \end{itemize}
72
73 My own circuit board has uses an additional port that is used to confirm 
74 that CHK has been set.
75
76 When the RST port on the 8051 has been set, the processor listens for SPI 
77 input and handles incoming data.
78
79 \section{The SPI protocol}
80
81 So, what is SPI? SPI is a very simple serial data protocol. This means 
82 that bytes are send serially instead of parallel. SPI is a standard protocol 
83 that is used mainly in embedded devices. It falls in the same family as 
84 $I2C$ or $RS232$.
85
86 As can be read in Atmel's datasheets (document 0401 to be precise), 
87 the SPI protocol uses 3 lines:
88
89 \begin{itemize}
90 \item[MOSI] {\em (Master Out, Slave In)} Data line, in my case sitting on the TxD of my serial port
91 \item[MISO] {\em (Master In, Slave Out)} Data line, controlled by client. (In my case on CTS)
92 \item[SCK] The Clock (in my case on RTS of the serial port)
93 \end{itemize}
94
95 \subsection{How does SPI work?}
96
97 The SPI works with two parties: the slave and the master. The master controls 
98 the line. In my case the personal computer is the master and the 8051 is 
99 the slave. There is another data line ({\em Slave Select}) that is used to select 
100 who the slave is, but I didn't need to use that bit.
101
102 The master sets a bit on the {\em MOSI} and then generates a clock pulse, after 
103 which the next bit is set and another clock pulse is generated, etc.
104
105 \begin{figure}
106 \caption{Sending the bit pattern $0011 0100$ using SPI}
107
108 \includegraphics{SPI1}
109 \end{figure}
110
111 A clock pulse is generated by simply setting the {\em SCK} bit high and then low 
112 again after a few microseconds.
113
114 Here is my {\em SPI\_Out} function:
115
116 \begin{lstlisting}
117
118 void SPI_Out(int b)
119 {
120         int i;
121         for(i = 7; i >= 0; i--) {
122                 if(b & (1 << i)) SetMOSI();
123                 else ClearMOSI();
124                 waitmicrosec(2);
125                 SetSCK();
126                 waitmicrosec(3);
127                 ClearSCK();
128                 waitmicrosec(2);
129         }
130 }
131
132 \end{lstlisting}
133
134 Reading data from the slave is done in a similar way. The server requests 
135 data from the slave, after which it generates clock pulses on which the slave
136 sets the MISO line.
137
138 My {\em SPI\_In} function:
139
140 \begin{lstlisting}
141 int SPI_In()
142 {
143         int i, b = 0;
144         for(i = 7; i >= 0; i--) {
145                 SetSCK();
146                 waitmicrosec(2);
147                 if(GetMISO())b |= 1 << i;
148                 waitmicrosec(3);
149                 ClearSCK();
150                 waitmicrosec(2);
151         }
152         return b;
153 }
154 \end{lstlisting}
155
156 That's basically all that SPI does. It's that simple!
157
158 \section{AT89* commands}
159
160 This section describes the various commands that can be sent 
161 to the 8051 over SPI when it's {\em RST} bit is set.
162
163 \subsection{Enabling program modus}
164
165 Before the 8051 accepts any commands, it needs to be put into command mode.
166 That's what this command is for. Always run this command before you 
167 run any other command.
168
169 \begin{lstlisting}
170 void programming()
171 {
172         /* Send enable serial instruction to MOSI */
173         SPI_Out(0xAC); /* 1010 1100 */
174         SPI_Out(0x53); /* 0101 0011 */
175         SPI_Out(0x00); /* xxxx xxxx (don't care) */
176         waitmillisec(9);
177 }
178 \end{lstlisting}
179
180 \subsection{Erasing code and data memory}
181
182 When the erase command is given, both the code and the data memory 
183 are filled with zeroes.
184
185 \begin{lstlisting}
186 void erase()
187 {
188         SPI_Out(0xAC); /* 1010 1100 */
189         SPI_Out(0x04); /* xxxx x100 (x = don't care) */
190         SPI_Out(0x00); /* xxxx xxxx (don't care) */
191         waitmillisec(9);
192 }
193 \end{lstlisting}
194
195
196 \subsection{Writing data to code memory}
197
198 \begin{lstlisting}
199 void writecode(int addr, char b)
200 {
201      /* hhhh h010 */
202         SPI_Out(0x02 | ((addr >> 5) & 0xF8) | ((addr >> 11) & 0x04));
203         SPI_Out(addr & 0xFF); /* llll llll */
204         SPI_Out(b);
205         waitmillisec(6);
206 }
207 \end{lstlisting}
208
209 \subsection{Reading from code memory}
210
211 \begin{lstlisting}
212 int readcode(int addr)
213 {
214     /* hhhh h001 */
215         SPI_Out(0x01 | ((addr >> 5) & 0xF8) | ((addr >> 11) & 0x04));
216         SPI_Out(addr & 0xFF); /* llll llll */
217         return SPI_In();
218 }
219 \end{lstlisting}
220
221 \subsection{Writing to data memory}
222
223 \begin{lstlisting}
224 void writedata(int addr, char b)
225 {
226         SPI_Out(0x06 | ((addr >> 5) & 0xF8));
227         SPI_Out(addr & 0xFF); /* llll llll */
228         SPI_Out(b);
229 }
230 \end{lstlisting}
231
232 \subsection{Reading from data memory}
233 \begin{lstlisting}
234 int readdata(int addr)
235 {
236 \
237         SPI_Out(0x05 | ((addr >> 5) & 0xF8));
238         SPI_Out(addr & 0xFF); /* llll llll */
239         return SPI_In();
240 }
241 \end{lstlisting}
242
243 \subsection{Locking memory}
244
245 The 3 bits $p$, $q$ and $r$ in the function below specify what should be locked.
246
247 \begin{itemize}
248 \item[p] External movc access to the device is not possible. The device is 
249 write protected.
250 \item[q] The device is read-protected..
251 \item[r] No external execution.
252 \end{itemize}
253
254 \begin{lstlisting}
255 void lock(int byte)
256 {
257         int mask = 0xff & ~byte;
258
259         SPI_Out(0xAC);          /* 1010 1100 */
260         SPI_Out(mask | 0x07);   /* pqrx x111 */
261         SPI_Out(0);             /* xxxx xxxx */
262         waitmillisec(9);
263 }
264 \end{lstlisting}
265
266 \section{Tips}
267
268 These are some random tips that might be useful when you are interested in
269 implementing the SPI protocol or the 8051 programming that is running over it.
270
271 \begin{itemize}
272 \item Make sure you clear and set the RST line in 
273 the beginning of your program
274 \item Make sure you wait long enough between clock pulses and that 
275 clock pulses are long enough
276 \item A logic analyser is very useful when debugging timing problems
277 \end{itemize}
278
279 \nocite{*}
280
281 \begin{thebibliography}{99}
282 \bibitem{} Atmel: AT89S8252 Datasheet, \emph{http://www.atmel.com/dyn/resources/prod\_documents/doc0401.pdf}
283 \bibitem{} Rob~Melby: Atmel 89 programmer, \emph{http://www.cc.gatech.edu/gvu/ccg/people/rob/software/89prog.tar.gz}
284 \end{thebibliography}
285
286 \end{document}