1 | \input texinfo @c -*- Texinfo -*- |
---|
2 | @setfilename porting.info |
---|
3 | @settitle Embed with GNU |
---|
4 | |
---|
5 | @c |
---|
6 | @c This file documents the process of porting the GNU tools to an |
---|
7 | @c embedded environment. |
---|
8 | @c |
---|
9 | |
---|
10 | @finalout |
---|
11 | @setchapternewpage off |
---|
12 | @iftex |
---|
13 | @raggedbottom |
---|
14 | @global@parindent=0pt |
---|
15 | @end iftex |
---|
16 | |
---|
17 | @titlepage |
---|
18 | @title Embed With GNU |
---|
19 | @subtitle Porting The GNU Tools To Embedded Systems |
---|
20 | @sp 4 |
---|
21 | @subtitle Spring 1995 |
---|
22 | @subtitle Very *Rough* Draft |
---|
23 | @author Rob Savoye - Cygnus Support |
---|
24 | @page |
---|
25 | |
---|
26 | @vskip 0pt plus 1filll |
---|
27 | Copyright @copyright{} 1993, 1994, 1995 Cygnus Support |
---|
28 | |
---|
29 | Permission is granted to make and distribute verbatim copies of |
---|
30 | this manual provided the copyright notice and this permission notice |
---|
31 | are preserved on all copies. |
---|
32 | |
---|
33 | Permission is granted to copy and distribute modified versions of this |
---|
34 | manual under the conditions for verbatim copying, provided also that |
---|
35 | the entire resulting derived work is distributed under the terms of a |
---|
36 | permission notice identical to this one. |
---|
37 | |
---|
38 | Permission is granted to copy and distribute translations of this manual |
---|
39 | into another language, under the above conditions for modified versions. |
---|
40 | @end titlepage |
---|
41 | |
---|
42 | @ifnottex |
---|
43 | @format |
---|
44 | START-INFO-DIR-ENTRY |
---|
45 | * Embed with GNU: (porting-). Embed with GNU |
---|
46 | END-INFO-DIR-ENTRY |
---|
47 | @end format |
---|
48 | Copyright (c) 1993, 1994, 1995 Cygnus Support |
---|
49 | |
---|
50 | Permission is granted to make and distribute verbatim copies of |
---|
51 | this manual provided the copyright notice and this permission notice |
---|
52 | are preserved on all copies. |
---|
53 | |
---|
54 | Permission is granted to copy and distribute modified versions of this |
---|
55 | manual under the conditions for verbatim copying, provided also that |
---|
56 | the entire resulting derived work is distributed under the terms of a |
---|
57 | permission notice identical to this one. |
---|
58 | |
---|
59 | Permission is granted to copy and distribute translations of this manual |
---|
60 | into another language, under the above conditions for modified versions. |
---|
61 | |
---|
62 | @node Top |
---|
63 | @top Embed with GNU |
---|
64 | |
---|
65 | @end ifnottex |
---|
66 | @strong{Rough Draft} |
---|
67 | |
---|
68 | The goal of this document is to gather all the information needed to |
---|
69 | port the GNU tools to a new embedded target in one place. This will |
---|
70 | duplicate some info found in the other manual for the GNU tools, but |
---|
71 | this should be all you'll need. |
---|
72 | |
---|
73 | @menu |
---|
74 | * Libgloss:: Libgloss, a library of board support packages. |
---|
75 | * GCC:: Porting GCC/G++ to a new embedded target. |
---|
76 | * Libraries:: Making Newlib run on an new embedded target. |
---|
77 | * GDB:: Making GDB understand a new back end. |
---|
78 | * Binutils:: Using the GNU binary utilities. |
---|
79 | * Code Listings:: Listings of the commented source code from the |
---|
80 | text. |
---|
81 | @end menu |
---|
82 | |
---|
83 | @node Libgloss, GCC, Top, Top |
---|
84 | @chapter Libgloss |
---|
85 | Libgloss is a library for all the details that usually get glossed over. |
---|
86 | This library refers to things like startup code, and usually I/O support |
---|
87 | for @code{gcc} and @code{C library}. The C library used through out |
---|
88 | this manual is @code{newlib}. Newlib is a ANSI conforming C library |
---|
89 | developed by Cygnus Support. Libgloss could easily be made to |
---|
90 | support other C libraries, and it can be used standalone as well. The |
---|
91 | standalone configuration is typically used when bringing up new |
---|
92 | hardware, or on small systems. |
---|
93 | |
---|
94 | For a long time, these details were part of newlib. This approach worked |
---|
95 | well when a complete tool chain only had to support one system. A tool |
---|
96 | chain refers to the series of compiler passes required to produce a |
---|
97 | binary file that will run on an embedded system. For C, the passes are |
---|
98 | cpp, gcc, gas, ld. Cpp is the preprocessor, which process all the header |
---|
99 | files and macros. Gcc is the compiler, which produces assembler from the |
---|
100 | processed C files. Gas assembles the code into object files, and then ld |
---|
101 | combines the object files and binds the code to addresses and produces |
---|
102 | the final executable image. |
---|
103 | |
---|
104 | Most of the time a tool chain does only have to support one target |
---|
105 | execution environment. An example of this would be a tool chain for the |
---|
106 | AMD 29k processor family. All of the execution environments for this |
---|
107 | processor have the same interface, the same memory map, and the same |
---|
108 | I/O code. In this case all of the support code is under newlib/libc/sys. |
---|
109 | Libgloss's creation was forced initially because of the @code{cpu32} |
---|
110 | processor family. There are many different execution environments for |
---|
111 | this line, and they vary wildly. newlib itself has only a few |
---|
112 | dependencies that it needs for each target. These are explained later in |
---|
113 | this doc. The hardware dependent part of newlib was reorganized into a |
---|
114 | separate directory structure within newlib called the stub dirs. It was |
---|
115 | initially called this because most of the routines newlib needs for a |
---|
116 | target were simple stubs that do nothing, but return a value to the |
---|
117 | application. They only exist so the linker can produce a final |
---|
118 | executable image. This work was done during the early part of 1993. |
---|
119 | |
---|
120 | After a while it became apparent that this approach of isolating the |
---|
121 | hardware and systems files together made sense. Around this same time |
---|
122 | the stub dirs were made to run standalone, mostly so it could also be |
---|
123 | used to support GDB's remote debugging needs. At this time it was |
---|
124 | decided to move the stub dirs out of newlib and into it's own separate |
---|
125 | library so it could be used standalone, and be included in various other |
---|
126 | GNU tools without having to bring in all of newlib, which is large. The |
---|
127 | new library is called Libgloss, for Gnu Low-level OS support. |
---|
128 | |
---|
129 | @menu |
---|
130 | * Supported targets:: What targets libgloss currently |
---|
131 | supports. |
---|
132 | * Building libgloss:: How to configure and built libgloss |
---|
133 | for a target. |
---|
134 | * Board support:: How to add support for a new board. |
---|
135 | @end menu |
---|
136 | |
---|
137 | @node Supported targets, Building libgloss, Libgloss, Libgloss |
---|
138 | @section Supported Targets |
---|
139 | Currently libgloss is being used for the following targets: |
---|
140 | |
---|
141 | @menu |
---|
142 | * Sparclite:: Fujitsu's sparclite. |
---|
143 | * CPU32:: Various m68k based targets. |
---|
144 | * Mips:: Mips code based targets. |
---|
145 | * PA-RISC:: Precision Risc Organization.. |
---|
146 | @end menu |
---|
147 | |
---|
148 | @node Sparclite, CPU32, , Supported targets |
---|
149 | @subsection Sparclite Targets Supported |
---|
150 | @c FIXME: put links to the docs in etc/targetdoc |
---|
151 | This is for the Fujitsu Sparclite family of processors. Currently this |
---|
152 | covers the ex930, ex931, ex932, ex933, and the ex934. In addition to the |
---|
153 | I/O code a startup file, this has a GDB debug-stub that gets linked into |
---|
154 | your application. This is an exception handler style debug stub. For |
---|
155 | more info, see the section on Porting GDB. @ref{GDB,,Porting GDB}. |
---|
156 | |
---|
157 | The Fujitsu eval boards use a host based terminal program to load and |
---|
158 | execute programs on the target. This program, @code{pciuh} is relatively |
---|
159 | new (in 1994) and it replaced the previous ROM monitor which had the |
---|
160 | shell in the ROM. GDB uses the the GDB remote protocol, the relevant |
---|
161 | source files from the gdb sources are remote-sparcl.c. The debug stub is |
---|
162 | part of libgloss and is called sparcl-stub.c. |
---|
163 | |
---|
164 | @node CPU32, Mips, Sparclite, Supported targets |
---|
165 | @subsection Motorola CPU32 Targets supported |
---|
166 | This refers to Motorola's m68k based CPU32 processor family. The crt0.S |
---|
167 | startup file should be usable with any target environment, and it's |
---|
168 | mostly just the I/O code and linker scripts that vary. Currently there |
---|
169 | is support for the Motorola MVME line of 6U VME boards and IDP |
---|
170 | line of eval boards. All of the |
---|
171 | Motorola VME boards run @code{Bug}, a ROM based debug monitor. |
---|
172 | This monitor has the feature of using user level traps to do I/O, so |
---|
173 | this code should be portable to other MVME boards with little if any |
---|
174 | change. The startup file also can remain unchanged. About the only thing |
---|
175 | that varies is the address for where the text section begins. This can |
---|
176 | be accomplished either in the linker script, or on the command line |
---|
177 | using the @samp{-Ttext [address]}. |
---|
178 | |
---|
179 | @c FIXME: Intermetrics or ISI wrote rom68k ? |
---|
180 | There is also support for the @code{rom68k} monitor as shipped on |
---|
181 | Motorola's IDP eval board line. This code should be portable across the |
---|
182 | range of CPU's the board supports. There is also GDB support for this |
---|
183 | target environment in the GDB source tree. The relevant files are |
---|
184 | gdb/monitor.c, monitor.h, and rom58k-rom.c. The usage of these files is |
---|
185 | discussed in the GDB section. |
---|
186 | |
---|
187 | @node Mips, PA-RISC, CPU32, Supported targets |
---|
188 | @subsection Mips core Targets Supported |
---|
189 | The Crt0 startup file should run on any mips target that doesn't require |
---|
190 | additional hardware initialization. The I/O code so far only supports a |
---|
191 | custom LSI33k based RAID disk controller board. It should easy to |
---|
192 | change to support the IDT line of eval boards. Currently the two |
---|
193 | debugging protocols supported by GDB for mips targets is IDT's mips |
---|
194 | debug protocol, and a customized hybrid of the standard GDB remote |
---|
195 | protocol and GDB's standard ROM monitor support. Included here is the |
---|
196 | debug stub for the hybrid monitor. This supports the LSI33k processor, |
---|
197 | and only has support for the GDB protocol commands @code{g}, @code{G}, |
---|
198 | @code{m}, @code{M}, which basically only supports the register and |
---|
199 | memory reading and writing commands. This is part of libgloss and is |
---|
200 | called lsi33k-stub.c. |
---|
201 | |
---|
202 | The crt0.S should also work on the IDT line of eval boards, but has only |
---|
203 | been run on the LSI33k for now. There is no I/O support for the IDT eval |
---|
204 | board at this time. The current I/O code is for a customized version of |
---|
205 | LSI's @code{pmon} ROM monitor. This uses entry points into the monitor, |
---|
206 | and should easily port to other versions of the pmon monitor. Pmon is |
---|
207 | distributed in source by LSI. |
---|
208 | |
---|
209 | @node PA-RISC, , Mips, Supported targets |
---|
210 | @subsection PA-RISC Targets Supported |
---|
211 | This supports the various boards manufactured by the HP-PRO consortium. |
---|
212 | This is a group of companies all making variations on the PA-RISC |
---|
213 | processor. Currently supported are ports to the WinBond @samp{Cougar} |
---|
214 | board based around their w89k version of the PA. Also supported is the |
---|
215 | Oki op50n processor. |
---|
216 | |
---|
217 | There is also included, but never built an unfinished port to the HP 743 |
---|
218 | board. This board is the main CPU board for the HP700 line of industrial |
---|
219 | computers. This target isn't exactly an embedded system, in fact it's |
---|
220 | really only designed to load and run HP-UX. Still, the crt0.S and I/O |
---|
221 | code are fully working. It is included mostly because their is a barely |
---|
222 | functioning exception handler GDB debug stub, and I hope somebody could |
---|
223 | use it. The other PRO targets all use GDB's ability to talk to ROM |
---|
224 | monitors directly, so it doesn't need a debug stub. There is also a |
---|
225 | utility that will produce a bootable file by HP's ROM monitor. This is |
---|
226 | all included in the hopes somebody else will finish it. :-) |
---|
227 | |
---|
228 | Both the WinBond board and the Oki board download srecords. The WinBond |
---|
229 | board also has support for loading the SOM files as produced by the |
---|
230 | native compiler on HP-UX. WinBond supplies a set of DOS programs that |
---|
231 | will allow the loading of files via a bidirectional parallel port. This |
---|
232 | has never been tested with the output of GNU SOM, as this manual is |
---|
233 | mostly for Unix based systems. |
---|
234 | |
---|
235 | @node Building libgloss, Board support, Supported targets, Libgloss |
---|
236 | @section Configuring and building libgloss. |
---|
237 | |
---|
238 | Libgloss uses an autoconf based script to configure. Autoconf scripts |
---|
239 | are portable shell scripts that are generated from a configure.in file. |
---|
240 | Configure input scripts are based themselves on m4. Most configure |
---|
241 | scripts run a series of tests to determine features the various |
---|
242 | supported features of the target. For features that can't be determined |
---|
243 | by a feature test, a makefile fragment is merged in. The configure |
---|
244 | process leaves creates a Makefile in the build directory. For libgloss, |
---|
245 | there are only a few configure options of importance. These are --target |
---|
246 | and --srcdir. |
---|
247 | |
---|
248 | Typically libgloss is built in a separate tree just for objects. In this |
---|
249 | manner, it's possible to have a single source tree, and multiple object |
---|
250 | trees. If you only need to configure for a single target environment, |
---|
251 | then you can configure in the source tree. The argument for --target is |
---|
252 | a config string. It's usually safest to use the full canonical opposed |
---|
253 | to the target alias. So, to configure for a CPU32 (m68k) with a separate |
---|
254 | source tree, use: |
---|
255 | |
---|
256 | @smallexample |
---|
257 | ../src/libgloss/configure --verbose --target m68k-coff |
---|
258 | @end smallexample |
---|
259 | |
---|
260 | The configure script is in the source tree. When configure is invoked |
---|
261 | it will determine it's own source tree, so the --srcdir is would be |
---|
262 | redundant here. |
---|
263 | |
---|
264 | Once libgloss is configured, @code{make} is sufficient to build it. The |
---|
265 | default values for @code{Makefiles} are typically correct for all |
---|
266 | supported systems. The test cases in the testsuite will also built |
---|
267 | automatically as opposed to a @code{make check}, where test binaries |
---|
268 | aren't built till test time. This is mostly cause the libgloss |
---|
269 | testsuites are the last thing built when building the entire GNU source |
---|
270 | tree, so it's a good test of all the other compilation passes. |
---|
271 | |
---|
272 | The default values for the Makefiles are set in the Makefile fragment |
---|
273 | merged in during configuration. This fragment typically has rules like |
---|
274 | |
---|
275 | @smallexample |
---|
276 | CC_FOR_TARGET = `if [ -f $$@{OBJROOT@}/gcc/xgcc ] ; \ |
---|
277 | then echo $@{OBJROOT@}/gcc/xgcc -B$@{OBJROOT@}/gcc/ ; \ |
---|
278 | else t='$@{program_transform_name@}'; echo gcc | sed -e '' $$t ; fi` |
---|
279 | @end smallexample |
---|
280 | |
---|
281 | Basically this is a runtime test to determine whether there are freshly |
---|
282 | built executables for the other main passes of the GNU tools. If there |
---|
283 | isn't an executable built in the same object tree, then |
---|
284 | @emph{transformed}the generic tool name (like gcc) is transformed to the |
---|
285 | name typically used in GNU cross compilers. The names are |
---|
286 | typically based on the target's canonical name, so if you've configured |
---|
287 | for @code{m68k-coff} the transformed name is @code{m68k-coff-gcc} in |
---|
288 | this case. If you install with aliases or rename the tools, this won't |
---|
289 | work, and it will always look for tools in the path. You can force the a |
---|
290 | different name to work by reconfiguring with the |
---|
291 | @code{--program-transform-name} option to configure. This option takes a |
---|
292 | sed script like this @code{-e s,^,m68k-coff-,} which produces tools |
---|
293 | using the standard names (at least here at Cygnus). |
---|
294 | |
---|
295 | The search for the other GNU development tools is exactly the same idea. |
---|
296 | This technique gets messier when build options like @code{-msoft-float} |
---|
297 | support are used. The Makefile fragments set the @code{MUTILIB} |
---|
298 | variable, and if it is set, the search path is modified. If the linking |
---|
299 | is done with an installed cross compiler, then none of this needs to be |
---|
300 | used. This is done so libgloss will build automatically with a fresh, |
---|
301 | and uninstalled object tree. It also makes it easier to debug the other |
---|
302 | tools using libgloss's test suites. |
---|
303 | |
---|
304 | @node Board support, , Building libgloss, Libgloss |
---|
305 | @section Adding Support for a New Board |
---|
306 | |
---|
307 | This section explains how to add support for a new board to libgloss. |
---|
308 | In order to add support for a board, you must already have developed a |
---|
309 | toolchain for the target architecture. |
---|
310 | |
---|
311 | All of the changes you will make will be in the subdirectory named |
---|
312 | after the architecture used by your board. For example, if you are |
---|
313 | developing support for a new ColdFire board, you will modify files in |
---|
314 | the @file{m68k} subdirectory, as that subdirectory contains support |
---|
315 | for all 68K devices, including architecture variants like ColdFire. |
---|
316 | |
---|
317 | In general, you will be adding three components: a @file{crt0.S} file |
---|
318 | (@pxref{Crt0}), a linker script (@pxref{Linker Scripts}), and a |
---|
319 | hardware support library. Each should be prefixed with the name of |
---|
320 | your board. For example, if you ard adding support for a new Surf |
---|
321 | board, then you will be adding the assembly @file{surf-crt0.S} (which |
---|
322 | will be assembled into @file{surf-crt0.o}), the linker script |
---|
323 | @file{surf.ld}, and other C and assembly files which will be combined |
---|
324 | into the hardware support library @file{libsurf.a}. |
---|
325 | |
---|
326 | You should modify @file{Makefile.in} to define new variables |
---|
327 | corresponding to your board. Although there is some variation between |
---|
328 | architectures, the general convention is to use the following format: |
---|
329 | |
---|
330 | @example |
---|
331 | # The name of the crt0.o file. |
---|
332 | SURF_CRT0 = surf-crt0.o |
---|
333 | # The name of the linker script. |
---|
334 | SURF_SCRIPTS = surf.ld |
---|
335 | # The name of the hardware support library. |
---|
336 | SURF_BSP = libsurf.a |
---|
337 | # The object files that make up the hardware support library. |
---|
338 | SURF_OBJS = surf-file1.o surf-file2.o |
---|
339 | # The name of the Makefile target to use for installation. |
---|
340 | SURF_INSTALL = install-surf |
---|
341 | @end example |
---|
342 | |
---|
343 | Then, you should create the @code{$@{SURF_BSP@}} and |
---|
344 | @code{$@{SURF_INSTALL@}} make targets. Add @code{$@{SURF_CRT0@}} to |
---|
345 | the dependencies for the @code{all} target and add |
---|
346 | @code{$@{SURF_INSTALL@}} to the dependencies for the @code{install} |
---|
347 | target. Now, when libgloss is built and installed, support for your |
---|
348 | BSP will be installed as well. |
---|
349 | |
---|
350 | @node GCC, Libraries, Libgloss, Top |
---|
351 | @chapter Porting GCC |
---|
352 | |
---|
353 | Porting GCC requires two things, neither of which has anything to do |
---|
354 | with GCC. If GCC already supports a processor type, then all the work in |
---|
355 | porting GCC is really a linker issue. All GCC has to do is produce |
---|
356 | assembler output in the proper syntax. Most of the work is done by the |
---|
357 | linker, which is described elsewhere. |
---|
358 | |
---|
359 | Mostly all GCC does is format the command line for the linker pass. The |
---|
360 | command line for GCC is set in the various config subdirectories of gcc. |
---|
361 | The options of interest to us are @code{CPP_SPEC} and |
---|
362 | @code{STARTFILE_SPEC}. CPP_SPEC sets the builtin defines for your |
---|
363 | environment. If you support multiple environments with the same |
---|
364 | processor, then OS specific defines will need to be elsewhere. |
---|
365 | @c FIXME: Check these names |
---|
366 | |
---|
367 | @code{STARTFILE_SPEC} |
---|
368 | |
---|
369 | Once you have linker support, GCC will be able to produce a fully linked |
---|
370 | executable image. The only @emph{part} of GCC that the linker wants is a |
---|
371 | crt0.o, and a memory map. If you plan on running any programs that do |
---|
372 | I/O of any kind, you'll need to write support for the C library, which |
---|
373 | is described elsewhere. |
---|
374 | |
---|
375 | @menu |
---|
376 | * Overview:: An overview as to the compilation passes. |
---|
377 | * Options:: Useful GCC options for embedded systems. |
---|
378 | @end menu |
---|
379 | |
---|
380 | @node Overview, Options, , GCC |
---|
381 | @section Compilation passes |
---|
382 | |
---|
383 | GCC by itself only compiles the C or C++ code into assembler. Typically |
---|
384 | GCC invokes all the passes required for you. These passes are cpp, cc1, |
---|
385 | gas, ld. @code{cpp} is the C preprocessor. This will merge in the |
---|
386 | include files, expand all macros definitions, and process all the |
---|
387 | @code{#ifdef} sections. To see the output of ccp, invoke gcc with the |
---|
388 | @code{-E} option, and the preprocessed file will be printed on the |
---|
389 | stdout. cc1 is the actual compiler pass that produces the assembler for |
---|
390 | the processed file. GCC is actually only a driver program for all the |
---|
391 | compiler passes. It will format command line options for the other passes. |
---|
392 | The usual command line GCC uses for the final link phase will have LD |
---|
393 | link in the startup code and additional libraries by default. |
---|
394 | |
---|
395 | GNU AS started it's life to only function as a compiler pass, but |
---|
396 | these days it can also be used as a source level assembler. When used as |
---|
397 | a source level assembler, it has a companion assembler preprocessor |
---|
398 | called @code{gasp}. This has a syntax similar to most other assembler |
---|
399 | macros packages. GAS emits a relocatable object file from the assembler |
---|
400 | source. The object file contains the executable part of the application, |
---|
401 | and debug symbols. |
---|
402 | |
---|
403 | LD is responsible for resolving the addresses and symbols to something |
---|
404 | that will be fully self-contained. Some RTOS's use relocatable object |
---|
405 | file formats like @code{a.out}, but more commonly the final image will |
---|
406 | only use absolute addresses for symbols. This enables code to be burned |
---|
407 | into PROMS as well. Although LD can produce an executable image, there |
---|
408 | is usually a hidden object file called @code{crt0.o} that is required as |
---|
409 | startup code. With this startup code and a memory map, the executable |
---|
410 | image will actually run on the target environment. @ref{Crt0,,Startup |
---|
411 | Files}. |
---|
412 | |
---|
413 | The startup code usually defines a special symbol like @code{_start} |
---|
414 | that is the default base address for the application, and the first |
---|
415 | symbol in the executable image. If you plan to use any routines from the |
---|
416 | standard C library, you'll also need to implement the functions that |
---|
417 | this library is dependent on. @ref{Libraries,,Porting Newlib}. |
---|
418 | |
---|
419 | @node Options, , Overview, GCC |
---|
420 | @c FIXME: Need stuff here about -fpic, -Ttext, etc... |
---|
421 | |
---|
422 | Options for the various development tools are covered in more detail |
---|
423 | elsewhere. Still, the amount of options can be an overwhelming amount of |
---|
424 | stuff, so the options most suited to embedded systems are summarized |
---|
425 | here. If you use GCC as the main driver for all the passes, most of the |
---|
426 | linker options can be passed directly to the compiler. There are also |
---|
427 | GCC options that control how the GCC driver formats the command line |
---|
428 | arguments for the linker. |
---|
429 | |
---|
430 | @menu |
---|
431 | * GCC Options:: Options for the compiler. |
---|
432 | * GAS Options:: Options for the assembler. |
---|
433 | * LD Options:: Options for the linker. |
---|
434 | @end menu |
---|
435 | |
---|
436 | @node GCC Options, GAS Options, , Options |
---|
437 | Most of the GCC options that we're interested control how the GCC driver |
---|
438 | formats the options for the linker pass. |
---|
439 | |
---|
440 | @c FIXME: this section is still under work. |
---|
441 | @table @code |
---|
442 | @item -nostartfiles |
---|
443 | @item -nostdlib |
---|
444 | @item -Xlinker |
---|
445 | Pass the next option directly to the linker. |
---|
446 | |
---|
447 | @item -v |
---|
448 | @item -fpic |
---|
449 | @end table |
---|
450 | |
---|
451 | @node GAS Options, LD Options, GCC Options, Options |
---|
452 | @c FIXME: Needs stuff here |
---|
453 | |
---|
454 | @node LD Options, , GAS Options, Options |
---|
455 | @c FIXME: Needs stuff here |
---|
456 | |
---|
457 | |
---|
458 | @node Libraries, GDB, GCC, Top |
---|
459 | @chapter Porting newlib |
---|
460 | |
---|
461 | @menu |
---|
462 | * Crt0:: Crt0.S. |
---|
463 | * Linker Scripts:: Linker scripts for memory management. |
---|
464 | * What to do now:: Tricks for manipulating formats. |
---|
465 | * Libc:: Making libc work. |
---|
466 | @end menu |
---|
467 | |
---|
468 | @node Crt0, Linker Scripts, , Libraries |
---|
469 | @section Crt0, the main startup file |
---|
470 | |
---|
471 | To make a program that has been compiled with GCC to run, you |
---|
472 | need to write some startup code. The initial piece of startup code is |
---|
473 | called a crt0. (C RunTime 0) This is usually written in assembler, and |
---|
474 | it's object gets linked in first, and bootstraps the rest of the |
---|
475 | application when executed. This file needs to do the following things. |
---|
476 | |
---|
477 | @enumerate |
---|
478 | @item |
---|
479 | Initialize anything that needs it. This init section varies. If you are |
---|
480 | developing an application that gets download to a ROM monitor, then |
---|
481 | there is usually no need for any special initialization. The ROM monitor |
---|
482 | handles it for you. |
---|
483 | |
---|
484 | If you plan to burn your code in a ROM, then the crt0 typically has to |
---|
485 | do all the hardware initialization that is required to run an |
---|
486 | application. This can include things like initializing serial ports or |
---|
487 | run a memory check. It all depends on the hardware. |
---|
488 | |
---|
489 | @item |
---|
490 | Zero the BSS section. This is for uninitialized data. All the addresses in |
---|
491 | this section need to be initialized to zero so that programs that forget |
---|
492 | to check new variables default value will get unpredictable results. |
---|
493 | |
---|
494 | @item |
---|
495 | Call main() |
---|
496 | This is what basically starts things running. If your ROM monitor |
---|
497 | supports it, then first setup argc and argv for command line arguments |
---|
498 | and an environment pointer. Then branch to main(). For G++ the the main |
---|
499 | routine gets a branch to __main inserted by the code generator at the |
---|
500 | very top. __main() is used by G++ to initialize it's internal tables. |
---|
501 | __main() then returns back to your original main() and your code gets |
---|
502 | executed. |
---|
503 | |
---|
504 | @item |
---|
505 | Call exit() |
---|
506 | After main() has returned, you need to cleanup things and return control |
---|
507 | of the hardware from the application. On some hardware, there is nothing |
---|
508 | to return to, especially if your program is in ROM. Sometimes the best |
---|
509 | thing to do in this case is do a hardware reset, or branch back to the |
---|
510 | start address all over again. |
---|
511 | |
---|
512 | When there is a ROM monitor present, usually a user trap can be called |
---|
513 | and then the ROM takes over. Pick a safe vector with no side |
---|
514 | effects. Some ROMs have a builtin trap handler just for this case. |
---|
515 | @end enumerate |
---|
516 | portable between all the m68k based boards we have here. |
---|
517 | @ref{crt0.S,,Example Crt0.S}. |
---|
518 | |
---|
519 | |
---|
520 | @smallexample |
---|
521 | /* ANSI concatenation macros. */ |
---|
522 | |
---|
523 | #define CONCAT1(a, b) CONCAT2(a, b) |
---|
524 | #define CONCAT2(a, b) a ## b |
---|
525 | @end smallexample |
---|
526 | These we'll use later. |
---|
527 | |
---|
528 | @smallexample |
---|
529 | /* These are predefined by new versions of GNU cpp. */ |
---|
530 | |
---|
531 | #ifndef __USER_LABEL_PREFIX__ |
---|
532 | #define __USER_LABEL_PREFIX__ _ |
---|
533 | #endif |
---|
534 | |
---|
535 | /* Use the right prefix for global labels. */ |
---|
536 | #define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x) |
---|
537 | |
---|
538 | @end smallexample |
---|
539 | |
---|
540 | These macros are to make this code portable between both @emph{COFF} and |
---|
541 | @emph{a.out}. @emph{COFF} always has an @var{_ (underline)} prepended on |
---|
542 | the front of all global symbol names. @emph{a.out} has none. |
---|
543 | |
---|
544 | @smallexample |
---|
545 | #ifndef __REGISTER_PREFIX__ |
---|
546 | #define __REGISTER_PREFIX__ |
---|
547 | #endif |
---|
548 | |
---|
549 | /* Use the right prefix for registers. */ |
---|
550 | #define REG(x) CONCAT1 (__REGISTER_PREFIX__, x) |
---|
551 | |
---|
552 | #define d0 REG (d0) |
---|
553 | #define d1 REG (d1) |
---|
554 | #define d2 REG (d2) |
---|
555 | #define d3 REG (d3) |
---|
556 | #define d4 REG (d4) |
---|
557 | #define d5 REG (d5) |
---|
558 | #define d6 REG (d6) |
---|
559 | #define d7 REG (d7) |
---|
560 | #define a0 REG (a0) |
---|
561 | #define a1 REG (a1) |
---|
562 | #define a2 REG (a2) |
---|
563 | #define a3 REG (a3) |
---|
564 | #define a4 REG (a4) |
---|
565 | #define a5 REG (a5) |
---|
566 | #define a6 REG (a6) |
---|
567 | #define fp REG (fp) |
---|
568 | #define sp REG (sp) |
---|
569 | @end smallexample |
---|
570 | |
---|
571 | This is for portability between assemblers. Some register names have a |
---|
572 | @var{%} or @var{$} prepended to the register name. |
---|
573 | |
---|
574 | @smallexample |
---|
575 | /* |
---|
576 | * Set up some room for a stack. We just grab a chunk of memory. |
---|
577 | */ |
---|
578 | .set stack_size, 0x2000 |
---|
579 | .comm SYM (stack), stack_size |
---|
580 | @end smallexample |
---|
581 | |
---|
582 | Set up space for the stack. This can also be done in the linker script, |
---|
583 | but it typically gets done here. |
---|
584 | |
---|
585 | @smallexample |
---|
586 | /* |
---|
587 | * Define an empty environment. |
---|
588 | */ |
---|
589 | .data |
---|
590 | .align 2 |
---|
591 | SYM (environ): |
---|
592 | .long 0 |
---|
593 | @end smallexample |
---|
594 | |
---|
595 | Set up an empty space for the environment. This is bogus on any most ROM |
---|
596 | monitor, but we setup a valid address for it, and pass it to main. At |
---|
597 | least that way if an application checks for it, it won't crash. |
---|
598 | |
---|
599 | @smallexample |
---|
600 | .align 2 |
---|
601 | .text |
---|
602 | .global SYM (stack) |
---|
603 | |
---|
604 | .global SYM (main) |
---|
605 | .global SYM (exit) |
---|
606 | /* |
---|
607 | * This really should be __bss_start, not SYM (__bss_start). |
---|
608 | */ |
---|
609 | .global __bss_start |
---|
610 | @end smallexample |
---|
611 | |
---|
612 | Setup a few global symbols that get used elsewhere. @var{__bss_start} |
---|
613 | needs to be unchanged, as it's setup by the linker script. |
---|
614 | |
---|
615 | @smallexample |
---|
616 | /* |
---|
617 | * start -- set things up so the application will run. |
---|
618 | */ |
---|
619 | SYM (start): |
---|
620 | link a6, #-8 |
---|
621 | moveal #SYM (stack) + stack_size, sp |
---|
622 | |
---|
623 | /* |
---|
624 | * zerobss -- zero out the bss section |
---|
625 | */ |
---|
626 | moveal #__bss_start, a0 |
---|
627 | moveal #SYM (end), a1 |
---|
628 | 1: |
---|
629 | movel #0, (a0) |
---|
630 | leal 4(a0), a0 |
---|
631 | cmpal a0, a1 |
---|
632 | bne 1b |
---|
633 | @end smallexample |
---|
634 | |
---|
635 | The global symbol @code{start} is used by the linker as the default |
---|
636 | address to use for the @code{.text} section. then it zeros the |
---|
637 | @code{.bss} section so the uninitialized data will all be cleared. Some |
---|
638 | programs have wild side effects from having the .bss section let |
---|
639 | uncleared. Particularly it causes problems with some implementations of |
---|
640 | @code{malloc}. |
---|
641 | |
---|
642 | @smallexample |
---|
643 | /* |
---|
644 | * Call the main routine from the application to get it going. |
---|
645 | * main (argc, argv, environ) |
---|
646 | * We pass argv as a pointer to NULL. |
---|
647 | */ |
---|
648 | pea 0 |
---|
649 | pea SYM (environ) |
---|
650 | pea sp@@(4) |
---|
651 | pea 0 |
---|
652 | jsr SYM (main) |
---|
653 | movel d0, sp@@- |
---|
654 | @end smallexample |
---|
655 | |
---|
656 | Setup the environment pointer and jump to @code{main()}. When |
---|
657 | @code{main()} returns, it drops down to the @code{exit} routine below. |
---|
658 | |
---|
659 | @smallexample |
---|
660 | /* |
---|
661 | * _exit -- Exit from the application. Normally we cause a user trap |
---|
662 | * to return to the ROM monitor for another run. |
---|
663 | */ |
---|
664 | SYM (exit): |
---|
665 | trap #0 |
---|
666 | @end smallexample |
---|
667 | |
---|
668 | Implementing @code{exit} here is easy. Both the @code{rom68k} and @code{bug} |
---|
669 | can handle a user caused exception of @code{zero} with no side effects. |
---|
670 | Although the @code{bug} monitor has a user caused trap that will return |
---|
671 | control to the ROM monitor, this solution has been more portable. |
---|
672 | |
---|
673 | @node Linker Scripts, What to do now, Crt0, Libraries |
---|
674 | @section Linker scripts for memory management |
---|
675 | |
---|
676 | The linker script sets up the memory map of an application. It also |
---|
677 | sets up default values for variables used elsewhere by sbrk() and the |
---|
678 | crt0. These default variables are typically called @code{_bss_start} and |
---|
679 | @code{_end}. |
---|
680 | |
---|
681 | For G++, the constructor and destructor tables must also be setup here. |
---|
682 | The actual section names vary depending on the object file format. For |
---|
683 | @code{a.out} and @code{coff}, the three main sections are @code{.text}, |
---|
684 | @code{.data}, and @code{.bss}. |
---|
685 | |
---|
686 | Now that you have an image, you can test to make sure it got the |
---|
687 | memory map right. You can do this by having the linker create a memory |
---|
688 | map (by using the @code{-Map} option), or afterwards by using @code{nm} to |
---|
689 | check a few critical addresses like @code{start}, @code{bss_end}, and |
---|
690 | @code{_etext}. |
---|
691 | |
---|
692 | Here's a breakdown of a linker script for a m68k based target board. |
---|
693 | See the file @code{libgloss/m68k/idp.ld}, or go to the appendixes in |
---|
694 | the end of the manual. @ref{idp.ld,,Example Linker Script}. |
---|
695 | |
---|
696 | @smallexample |
---|
697 | STARTUP(crt0.o) |
---|
698 | OUTPUT_ARCH(m68k) |
---|
699 | INPUT(idp.o) |
---|
700 | SEARCH_DIR(.) |
---|
701 | __DYNAMIC = 0; |
---|
702 | @end smallexample |
---|
703 | |
---|
704 | The @code{STARTUP} command loads the file specified so that it's |
---|
705 | first. In this case it also doubles to load the file as well, because |
---|
706 | the m68k-coff configuration defaults to not linking in the crt0.o by |
---|
707 | default. It assumes that the developer probably has their own crt0.o. |
---|
708 | This behavior is controlled in the config file for each architecture. |
---|
709 | It's a macro called @code{STARTFILE_SPEC}, and if it's set to |
---|
710 | @code{null}, then when @code{gcc} formats it's command line, it doesn't |
---|
711 | add @code{crto.o}. Any file name can be specified here, but the default |
---|
712 | is always @code{crt0.o}. |
---|
713 | |
---|
714 | Course if you only use @code{ld} to link, then the control of whether or |
---|
715 | not to link in @code{crt0.o} is done on the command line. If you have |
---|
716 | multiple crto files, then you can leave this out all together, and link |
---|
717 | in the @code{crt0.o} in the makefile, or by having different linker |
---|
718 | scripts. Sometimes this is done for initializing floating point |
---|
719 | optionally, or to add device support. |
---|
720 | |
---|
721 | The @code{OUTPUT_ARCH} sets architecture the output file is for. |
---|
722 | |
---|
723 | @code{INPUT} loads in the file specified. In this case, it's a relocated |
---|
724 | library that contains the definitions for the low-level functions need |
---|
725 | by libc.a. This could have also been specified on the command line, but |
---|
726 | as it's always needed, it might as well be here as a default. |
---|
727 | @code{SEARCH_DIR} specifies the path to look for files, and |
---|
728 | @code{_DYNAMIC} means in this case there are no shared libraries. |
---|
729 | |
---|
730 | @c FIXME: Check the linker manual to make sure this is accurate. |
---|
731 | @smallexample |
---|
732 | /* |
---|
733 | * Setup the memory map of the MC68ec0x0 Board (IDP) |
---|
734 | * stack grows up towards high memory. This works for |
---|
735 | * both the rom68k and the mon68k monitors. |
---|
736 | */ |
---|
737 | MEMORY |
---|
738 | @{ |
---|
739 | ram : ORIGIN = 0x10000, LENGTH = 2M |
---|
740 | @} |
---|
741 | @end smallexample |
---|
742 | |
---|
743 | This specifies a name for a section that can be referred to later in the |
---|
744 | script. In this case, it's only a pointer to the beginning of free RAM |
---|
745 | space, with an upper limit at 2M. If the output file exceeds the upper |
---|
746 | limit, it will produce an error message. |
---|
747 | |
---|
748 | @smallexample |
---|
749 | /* |
---|
750 | * stick everything in ram (of course) |
---|
751 | */ |
---|
752 | SECTIONS |
---|
753 | @{ |
---|
754 | .text : |
---|
755 | @{ |
---|
756 | CREATE_OBJECT_SYMBOLS |
---|
757 | *(.text) |
---|
758 | etext = .; |
---|
759 | __CTOR_LIST__ = .; |
---|
760 | LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2) |
---|
761 | *(.ctors) |
---|
762 | LONG(0) |
---|
763 | __CTOR_END__ = .; |
---|
764 | __DTOR_LIST__ = .; |
---|
765 | LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2) |
---|
766 | *(.dtors) |
---|
767 | LONG(0) |
---|
768 | __DTOR_END__ = .; |
---|
769 | *(.lit) |
---|
770 | *(.shdata) |
---|
771 | @} > ram |
---|
772 | .shbss SIZEOF(.text) + ADDR(.text) : @{ |
---|
773 | *(.shbss) |
---|
774 | @} |
---|
775 | @end smallexample |
---|
776 | |
---|
777 | Set up the @code{.text} section. In a @code{COFF} file, .text is where |
---|
778 | all the actual instructions are. This also sets up the @emph{CONTRUCTOR} |
---|
779 | and the @emph{DESTRUCTOR} tables for @code{G++}. Notice that the section |
---|
780 | description redirects itself to the @emph{ram} variable setup earlier. |
---|
781 | |
---|
782 | @smallexample |
---|
783 | .talias : @{ @} > ram |
---|
784 | .data : @{ |
---|
785 | *(.data) |
---|
786 | CONSTRUCTORS |
---|
787 | _edata = .; |
---|
788 | @} > ram |
---|
789 | @end smallexample |
---|
790 | |
---|
791 | Setup the @code{.data} section. In a @code{coff} file, this is where all |
---|
792 | he initialized data goes. @code{CONSTRUCTORS} is a special command used |
---|
793 | by @code{ld}. |
---|
794 | |
---|
795 | @smallexample |
---|
796 | .bss SIZEOF(.data) + ADDR(.data) : |
---|
797 | @{ |
---|
798 | __bss_start = ALIGN(0x8); |
---|
799 | *(.bss) |
---|
800 | *(COMMON) |
---|
801 | end = ALIGN(0x8); |
---|
802 | _end = ALIGN(0x8); |
---|
803 | __end = ALIGN(0x8); |
---|
804 | @} |
---|
805 | .mstack : @{ @} > ram |
---|
806 | .rstack : @{ @} > ram |
---|
807 | .stab . (NOLOAD) : |
---|
808 | @{ |
---|
809 | [ .stab ] |
---|
810 | @} |
---|
811 | .stabstr . (NOLOAD) : |
---|
812 | @{ |
---|
813 | [ .stabstr ] |
---|
814 | @} |
---|
815 | @} |
---|
816 | @end smallexample |
---|
817 | |
---|
818 | Setup the @code{.bss} section. In a @code{COFF} file, this is where |
---|
819 | unitialized data goes. The symbols @code{_bss_start} and @code{_end} |
---|
820 | are setup here for use by the @code{crt0.o} when it zero's the |
---|
821 | @code{.bss} section. |
---|
822 | |
---|
823 | |
---|
824 | @node What to do now, Libc, Linker Scripts, Libraries |
---|
825 | @section What to do when you have a binary image |
---|
826 | |
---|
827 | A few ROM monitors load binary images, typically @code{a.out}, but most all |
---|
828 | will load an @code{srecord}. An srecord is an ASCII representation of a binary |
---|
829 | image. At it's simplest, an srecord is an address, followed by a byte |
---|
830 | count, followed by the bytes, and a 2's compliment checksum. A whole |
---|
831 | srecord file has an optional @emph{start} record, and a required @emph{end} |
---|
832 | record. To make an srecord from a binary image, the GNU @code{objcopy} program |
---|
833 | is used. This will read the image and make an srecord from it. To do |
---|
834 | this, invoke objcopy like this: @code{objcopy -O srec infile outfile}. Most |
---|
835 | PROM burners also read srecords or a similar format. Use @code{objdump -i} to |
---|
836 | get a list of support object files types for your architecture. |
---|
837 | |
---|
838 | @node Libc, , What to do now, Libraries |
---|
839 | @section Libraries |
---|
840 | |
---|
841 | This describes @code{newlib}, a freely available libc replacement. Most |
---|
842 | applications use calls in the standard C library. When initially linking |
---|
843 | in libc.a, several I/O functions are undefined. If you don't plan on |
---|
844 | doing any I/O, then you're OK, otherwise they need to be created. These |
---|
845 | routines are read, write, open, close. sbrk, and kill. Open & close |
---|
846 | don't need to be fully supported unless you have a filesystems, so |
---|
847 | typically they are stubbed out. Kill is also a stub, since you can't do |
---|
848 | process control on an embedded system. |
---|
849 | |
---|
850 | Sbrk() is only needed by applications that do dynamic memory |
---|
851 | allocation. It's uses the symbol @code{_end} that is setup in the linker |
---|
852 | script. It also requires a compile time option to set the upper size |
---|
853 | limit on the heap space. This leaves us with read and write, which are |
---|
854 | required for serial I/O. Usually these two routines are written in C, |
---|
855 | and call a lower level function for the actual I/O operation. These two |
---|
856 | lowest level I/O primitives are inbyte() and outbyte(), and are also |
---|
857 | used by GDB back ends if you've written an exception handler. Some |
---|
858 | systems also implement a havebyte() for input as well. |
---|
859 | |
---|
860 | Other commonly included functions are routines for manipulating |
---|
861 | LED's on the target (if they exist) or low level debug help. Typically a |
---|
862 | putnum() for printing words and bytes as a hex number is helpful, as |
---|
863 | well as a low-level print() to output simple strings. |
---|
864 | |
---|
865 | As libg++ uses the I/O routines in libc.a, if read and write work, |
---|
866 | then libg++ will also work with no additional changes. |
---|
867 | |
---|
868 | @menu |
---|
869 | * I/O Support:: Functions that make serial I/O work. |
---|
870 | * Memory Support:: Memory support. |
---|
871 | * Misc Support:: Other needed functions. |
---|
872 | * Debugging:: Useful Debugging Functions |
---|
873 | @end menu |
---|
874 | |
---|
875 | @node I/O Support, Memory Support, , Libc |
---|
876 | @subsection Making I/O work |
---|
877 | |
---|
878 | @node Memory Support, Misc Support, I/O Support, Libc |
---|
879 | @subsection Routines for dynamic memory allocation |
---|
880 | To support using any of the memory functions, you need to implement |
---|
881 | sbrk(). @code{malloc()}, @code{calloc()}, and @code{realloc()} all call |
---|
882 | @code{sbrk()} at there lowest level. @code{caddr_t} is defined elsewhere |
---|
883 | as @code{char *}. @code{RAMSIZE} is presently a compile time option. All |
---|
884 | this does is move a pointer to heap memory and check for the upper |
---|
885 | limit. @ref{glue.c,,Example libc support code}. @code{sbrk()} returns a |
---|
886 | pointer to the previous value before more memory was allocated. |
---|
887 | |
---|
888 | @smallexample |
---|
889 | /* _end is set in the linker command file * |
---|
890 | extern caddr_t _end;/ |
---|
891 | |
---|
892 | /* just in case, most boards have at least some memory */ |
---|
893 | #ifndef RAMSIZE |
---|
894 | # define RAMSIZE (caddr_t)0x100000 |
---|
895 | #endif |
---|
896 | |
---|
897 | /* |
---|
898 | * sbrk -- changes heap size size. Get nbytes more |
---|
899 | * RAM. We just increment a pointer in what's |
---|
900 | * left of memory on the board. |
---|
901 | */ |
---|
902 | caddr_t |
---|
903 | sbrk(nbytes) |
---|
904 | int nbytes; |
---|
905 | @{ |
---|
906 | static caddr_t heap_ptr = NULL; |
---|
907 | caddr_t base; |
---|
908 | |
---|
909 | if (heap_ptr == NULL) @{ |
---|
910 | heap_ptr = (caddr_t)&_end; |
---|
911 | @} |
---|
912 | |
---|
913 | if ((RAMSIZE - heap_ptr) >= 0) @{ |
---|
914 | base = heap_ptr; |
---|
915 | heap_ptr += nbytes; |
---|
916 | return (base); |
---|
917 | @} else @{ |
---|
918 | errno = ENOMEM; |
---|
919 | return ((caddr_t)-1); |
---|
920 | @} |
---|
921 | @} |
---|
922 | @end smallexample |
---|
923 | |
---|
924 | @node Misc Support, Debugging, Memory Support, Libc |
---|
925 | @subsection Misc support routines |
---|
926 | |
---|
927 | These are called by @code{newlib} but don't apply to the embedded |
---|
928 | environment. @code{isatty()} is self explanatory. @code{kill()} doesn't |
---|
929 | apply either in an environment withno process control, so it justs |
---|
930 | exits, which is a similar enough behavior. @code{getpid()} can safely |
---|
931 | return any value greater than 1. The value doesn't effect anything in |
---|
932 | @code{newlib} because once again there is no process control. |
---|
933 | |
---|
934 | @smallexample |
---|
935 | /* |
---|
936 | * isatty -- returns 1 if connected to a terminal device, |
---|
937 | * returns 0 if not. Since we're hooked up to a |
---|
938 | * serial port, we'll say yes and return a 1. |
---|
939 | */ |
---|
940 | int |
---|
941 | isatty(fd) |
---|
942 | int fd; |
---|
943 | @{ |
---|
944 | return (1); |
---|
945 | @} |
---|
946 | |
---|
947 | /* |
---|
948 | * getpid -- only one process, so just return 1. |
---|
949 | */ |
---|
950 | #define __MYPID 1 |
---|
951 | int |
---|
952 | getpid() |
---|
953 | @{ |
---|
954 | return __MYPID; |
---|
955 | @} |
---|
956 | |
---|
957 | /* |
---|
958 | * kill -- go out via exit... |
---|
959 | */ |
---|
960 | int |
---|
961 | kill(pid, sig) |
---|
962 | int pid; |
---|
963 | int sig; |
---|
964 | @{ |
---|
965 | if(pid == __MYPID) |
---|
966 | _exit(sig); |
---|
967 | return 0; |
---|
968 | @} |
---|
969 | @end smallexample |
---|
970 | |
---|
971 | @node Debugging, , Misc Support, Libc |
---|
972 | @subsection Useful debugging functions |
---|
973 | |
---|
974 | There are always a few useful functions for debugging your project in |
---|
975 | progress. I typically implement a simple @code{print()} routine that |
---|
976 | runs standalone in liblgoss, with no @code{newlib} support. The I/O |
---|
977 | function @code{outbyte()} can also be used for low level debugging. Many |
---|
978 | times print will work when there are problems that cause @code{printf()} to |
---|
979 | cause an exception. @code{putnum()} is just to print out values in hex |
---|
980 | so they are easier to read. |
---|
981 | |
---|
982 | @smallexample |
---|
983 | /* |
---|
984 | * print -- do a raw print of a string |
---|
985 | */ |
---|
986 | int |
---|
987 | print(ptr) |
---|
988 | char *ptr; |
---|
989 | @{ |
---|
990 | while (*ptr) @{ |
---|
991 | outbyte (*ptr++); |
---|
992 | @} |
---|
993 | @} |
---|
994 | |
---|
995 | /* |
---|
996 | * putnum -- print a 32 bit number in hex |
---|
997 | */ |
---|
998 | int |
---|
999 | putnum (num) |
---|
1000 | unsigned int num; |
---|
1001 | @{ |
---|
1002 | char buffer[9]; |
---|
1003 | int count; |
---|
1004 | char *bufptr = buffer; |
---|
1005 | int digit; |
---|
1006 | |
---|
1007 | for (count = 7 ; count >= 0 ; count--) @{ |
---|
1008 | digit = (num >> (count * 4)) & 0xf; |
---|
1009 | |
---|
1010 | if (digit <= 9) |
---|
1011 | *bufptr++ = (char) ('0' + digit); |
---|
1012 | else |
---|
1013 | *bufptr++ = (char) ('a' - 10 + digit); |
---|
1014 | @} |
---|
1015 | |
---|
1016 | *bufptr = (char) 0; |
---|
1017 | print (buffer); |
---|
1018 | return; |
---|
1019 | @} |
---|
1020 | @end smallexample |
---|
1021 | |
---|
1022 | If there are LEDs on the board, they can also be put to use for |
---|
1023 | debugging when the serial I/O code is being written. I usually implement |
---|
1024 | a @code{zylons()} function, which strobes the LEDS (if there is more |
---|
1025 | than one) in sequence, creating a rotating effect. This is convenient |
---|
1026 | between I/O to see if the target is still alive. Another useful LED |
---|
1027 | function is @code{led_putnum()}, which takes a digit and displays it as |
---|
1028 | a bit pattern or number. These usually have to be written in assembler |
---|
1029 | for each target board. Here are a number of C based routines that may be |
---|
1030 | useful. |
---|
1031 | |
---|
1032 | @code{led_putnum()} puts a number on a single digit segmented |
---|
1033 | LED display. This LED is set by setting a bit mask to an address, where |
---|
1034 | 1 turns the segment off, and 0 turns it on. There is also a little |
---|
1035 | decimal point on the LED display, so it gets the leftmost bit. The other |
---|
1036 | bits specify the segment location. The bits look like: |
---|
1037 | |
---|
1038 | @smallexample |
---|
1039 | [d.p | g | f | e | d | c | b | a ] is the byte. |
---|
1040 | @end smallexample |
---|
1041 | |
---|
1042 | The locations are set up as: |
---|
1043 | |
---|
1044 | @smallexample |
---|
1045 | a |
---|
1046 | ----- |
---|
1047 | f | | b |
---|
1048 | | g | |
---|
1049 | ----- |
---|
1050 | | | |
---|
1051 | e | | c |
---|
1052 | ----- |
---|
1053 | d |
---|
1054 | @end smallexample |
---|
1055 | |
---|
1056 | This takes a number that's already been converted to a string, and |
---|
1057 | prints it. |
---|
1058 | |
---|
1059 | @smallexample |
---|
1060 | #define LED_ADDR 0xd00003 |
---|
1061 | |
---|
1062 | void |
---|
1063 | led_putnum ( num ) |
---|
1064 | char num; |
---|
1065 | @{ |
---|
1066 | static unsigned char *leds = (unsigned char *)LED_ADDR; |
---|
1067 | static unsigned char num_bits [18] = @{ |
---|
1068 | 0xff, /* clear all */ |
---|
1069 | 0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x98, /* numbers 0-9 */ |
---|
1070 | 0x98, 0x20, 0x3, 0x27, 0x21, 0x4, 0xe /* letters a-f */ |
---|
1071 | @}; |
---|
1072 | |
---|
1073 | if (num >= '0' && num <= '9') |
---|
1074 | num = (num - '0') + 1; |
---|
1075 | |
---|
1076 | if (num >= 'a' && num <= 'f') |
---|
1077 | num = (num - 'a') + 12; |
---|
1078 | |
---|
1079 | if (num == ' ') |
---|
1080 | num = 0; |
---|
1081 | |
---|
1082 | *leds = num_bits[num]; |
---|
1083 | @} |
---|
1084 | |
---|
1085 | /* |
---|
1086 | * zylons -- draw a rotating pattern. NOTE: this function never returns. |
---|
1087 | */ |
---|
1088 | void |
---|
1089 | zylons() |
---|
1090 | @{ |
---|
1091 | unsigned char *leds = (unsigned char *)LED_ADDR; |
---|
1092 | unsigned char curled = 0xfe; |
---|
1093 | |
---|
1094 | while (1) |
---|
1095 | @{ |
---|
1096 | *leds = curled; |
---|
1097 | curled = (curled >> 1) | (curled << 7); |
---|
1098 | delay ( 200 ); |
---|
1099 | @} |
---|
1100 | @} |
---|
1101 | @end smallexample |
---|
1102 | |
---|
1103 | |
---|
1104 | @node GDB, Binutils, Libraries, Top |
---|
1105 | @chapter Writing a new GDB backend |
---|
1106 | |
---|
1107 | Typically, either the low-level I/O routines are used for debugging, or |
---|
1108 | LEDs, if present. It is much easier to use GDb for debugging an |
---|
1109 | application. There are several different techniques used to have GDB work |
---|
1110 | remotely. Commonly more than one kind of GDB interface is used to cober |
---|
1111 | a wide variety of development needs. |
---|
1112 | |
---|
1113 | The most common style of GDB backend is an exception handler for |
---|
1114 | breakpoints. This is also called a @emph{gdb stub}, and is requires the |
---|
1115 | two additional lines of init code in your @code{main()} routine. The GDB |
---|
1116 | stubs all use the GDB @emph{remote protocol}. When the application gets a |
---|
1117 | breakpoint exception, it communicates to GDB on the host. |
---|
1118 | |
---|
1119 | Another common style of interfacing GDB to a target is by using an |
---|
1120 | existing ROM monitor. These break down into two main kinds, a similar |
---|
1121 | protocol to the GDB remote protocol, and an interface that uses the ROM |
---|
1122 | monitor directly. This kind has GDB simulating a human operator, and all |
---|
1123 | GDB does is work as a command formatter and parser. |
---|
1124 | |
---|
1125 | @menu |
---|
1126 | * GNU remote protocol:: The standard remote protocol. |
---|
1127 | * Exception handler:: A linked in exception handler. |
---|
1128 | * ROM monitors:: Using a ROM monitor as a backend. |
---|
1129 | * Other remote protocols:: Adding support for new protocols. |
---|
1130 | @end menu |
---|
1131 | |
---|
1132 | @node GNU remote protocol, Exception handler, ,GDB |
---|
1133 | @section The standard remote protocol |
---|
1134 | |
---|
1135 | The standard remote protocol is a simple, packet based scheme. A debug |
---|
1136 | packet whose contents are @emph{<data>} is encapsulated for transmission |
---|
1137 | in the form: |
---|
1138 | |
---|
1139 | @smallexample |
---|
1140 | $ <data> # CSUM1 CSUM2 |
---|
1141 | @end smallexample |
---|
1142 | |
---|
1143 | @emph{<data>} must be ASCII alphanumeric and cannot include characters |
---|
1144 | @code{$} or @code{#}. If @emph{<data>} starts with two characters |
---|
1145 | followed by @code{:}, then the existing stubs interpret this as a |
---|
1146 | sequence number. For example, the command @code{g} is used to read the |
---|
1147 | values of the registers. So, a packet to do this would look like |
---|
1148 | |
---|
1149 | @smallexample |
---|
1150 | $g#67 |
---|
1151 | @end smallexample |
---|
1152 | |
---|
1153 | @emph{CSUM1} and @emph{CSUM2} are an ascii representation in hex of an |
---|
1154 | 8-bit checksum of @emph{<data>}, the most significant nibble is sent first. |
---|
1155 | the hex digits 0-9,a-f are used. |
---|
1156 | |
---|
1157 | A simple protocol is used when communicating with the target. This is |
---|
1158 | mainly to give a degree of error handling over the serial cable. For |
---|
1159 | each packet transmitted successfully, the target responds with a |
---|
1160 | @code{+} (@code{ACK}). If there was a transmission error, then the target |
---|
1161 | responds with a @code{-} (@code{NAK}). An error is determined when the |
---|
1162 | checksum doesn't match the calculated checksum for that data record. |
---|
1163 | Upon reciept of the @code{ACK}, @code{GDB} can then transmit the next |
---|
1164 | packet. |
---|
1165 | |
---|
1166 | Here is a list of the main functions that need to be supported. Each data |
---|
1167 | packet is a command with a set number of bytes in the command packet. |
---|
1168 | Most commands either return data, or respond with a @code{NAK}. Commands |
---|
1169 | that don't return data respond with an @code{ACK}. All data values are |
---|
1170 | ascii hex digits. Every byte needs two hex digits to represent t. This |
---|
1171 | means that a byte with the value @samp{7} becomes @samp{07}. On a 32 bit |
---|
1172 | machine this works out to 8 characters per word. All of the bytes in a |
---|
1173 | word are stored in the target byte order. When writing the host side of |
---|
1174 | the GDB protocol, be careful of byte order, and make sure that the code |
---|
1175 | will run on both big and little endian hosts and produce the same answers. |
---|
1176 | |
---|
1177 | These functions are the minimum required to make a GDB backend work. All |
---|
1178 | other commands are optional, and not supported by all GDB backends. |
---|
1179 | |
---|
1180 | @table @samp |
---|
1181 | @item read registers @code{g} |
---|
1182 | |
---|
1183 | returns @code{XXXXXXXX...} |
---|
1184 | |
---|
1185 | Registers are in the internal order for GDB, and the bytes in a register |
---|
1186 | are in the same order the machine uses. All values are in sequence |
---|
1187 | starting with register 0. All registers are listed in the same packet. A |
---|
1188 | sample packet would look like @code{$g#}. |
---|
1189 | |
---|
1190 | @item write registers @code{GXXXXXXXX...} |
---|
1191 | @code{XXXXXXXX} is the value to set the register to. Registers are in |
---|
1192 | the internal order for GDB, and the bytes in a register are in the same |
---|
1193 | order the machine uses. All values are in sequence starting with |
---|
1194 | register 0. All registers values are listed in the same packet. A sample |
---|
1195 | packet would look like @code{$G000000001111111122222222...#} |
---|
1196 | |
---|
1197 | returns @code{ACK} or @code{NAK} |
---|
1198 | |
---|
1199 | @item read memory @code{mAAAAAAAA,LLLL} |
---|
1200 | @code{AAAAAAAA} is address, @code{LLLL} is length. A sample packet would |
---|
1201 | look like @code{$m00005556,0024#}. This would request 24 bytes starting |
---|
1202 | at address @emph{00005556} |
---|
1203 | |
---|
1204 | returns @code{XXXXXXXX...} |
---|
1205 | @code{XXXXXXXX} is the memory contents. Fewer bytes than requested will |
---|
1206 | be returned if only part of the data can be read. This can be determined |
---|
1207 | by counting the values till the end of packet @code{#} is seen and |
---|
1208 | comparing that with the total count of bytes that was requested. |
---|
1209 | |
---|
1210 | @item write memory @code{MAAAAAAAA,LLLL:XXXXXXXX} |
---|
1211 | @code{AAAAAAAA} is the starting address, @code{LLLL} is the number of |
---|
1212 | bytes to be written, and @code{XXXXXXXX} is value to be written. A |
---|
1213 | sample packet would look like |
---|
1214 | @code{$M00005556,0024:101010101111111100000000...#} |
---|
1215 | |
---|
1216 | returns @code{ACK} or @code{NAK} for an error. @code{NAK} is also |
---|
1217 | returned when only part of the data is written. |
---|
1218 | |
---|
1219 | @item continue @code{cAAAAAAAAA} |
---|
1220 | @code{AAAAAAAA} is address to resume execution at. If @code{AAAAAAAA} is |
---|
1221 | omitted, resume at the curent address of the @code{pc} register. |
---|
1222 | |
---|
1223 | returns the same replay as @code{last signal}. There is no immediate |
---|
1224 | replay to @code{cont} until the next breakpoint is reached, and the |
---|
1225 | program stops executing. |
---|
1226 | |
---|
1227 | @item step sAA..AA |
---|
1228 | @code{AA..AA} is address to resume |
---|
1229 | If @code{AA..AA} is omitted, resume at same address. |
---|
1230 | |
---|
1231 | returns the same replay as @code{last signal}. There is no immediate |
---|
1232 | replay to @code{step} until the next breakpoint is reached, and the |
---|
1233 | program stops executing. |
---|
1234 | |
---|
1235 | @item last signal @code{?} |
---|
1236 | |
---|
1237 | This returns one of the following: |
---|
1238 | |
---|
1239 | @itemize @bullet |
---|
1240 | @item @code{SAA} |
---|
1241 | Where @code{AA} is the number of the last signal. |
---|
1242 | Exceptions on the target are converted to the most similar Unix style |
---|
1243 | signal number, like @code{SIGSEGV}. A sample response of this type would |
---|
1244 | look like @code{$S05#}. |
---|
1245 | |
---|
1246 | @item TAAnn:XXXXXXXX;nn:XXXXXXXX;nn:XXXXXXXX; |
---|
1247 | @code{AA} is the signal number. |
---|
1248 | @code{nn} is the register number. |
---|
1249 | @code{XXXXXXXX} is the register value. |
---|
1250 | |
---|
1251 | @item WAA |
---|
1252 | The process exited, and @code{AA} is the exit status. This is only |
---|
1253 | applicable for certains sorts of targets. |
---|
1254 | |
---|
1255 | @end itemize |
---|
1256 | |
---|
1257 | These are used in some GDB backends, but not all. |
---|
1258 | |
---|
1259 | @item write reg @code{Pnn=XXXXXXXX} |
---|
1260 | Write register @code{nn} with value @code{XXXXXXXX}. |
---|
1261 | |
---|
1262 | returns @code{ACK} or @code{NAK} |
---|
1263 | |
---|
1264 | @item kill request k |
---|
1265 | |
---|
1266 | @item toggle debug d |
---|
1267 | toggle debug flag (see 386 & 68k stubs) |
---|
1268 | |
---|
1269 | @item reset r |
---|
1270 | reset -- see sparc stub. |
---|
1271 | |
---|
1272 | @item reserved @code{other} |
---|
1273 | On other requests, the stub should ignore the request and send an empty |
---|
1274 | response @code{$#<checksum>}. This way we can extend the protocol and GDB |
---|
1275 | can tell whether the stub it is talking to uses the old or the new. |
---|
1276 | |
---|
1277 | @item search @code{tAA:PP,MM} |
---|
1278 | Search backwards starting at address @code{AA} for a match with pattern |
---|
1279 | PP and mask @code{MM}. @code{PP} and @code{MM} are 4 bytes. |
---|
1280 | |
---|
1281 | @item general query @code{qXXXX} |
---|
1282 | Request info about XXXX. |
---|
1283 | |
---|
1284 | @item general set @code{QXXXX=yyyy} |
---|
1285 | Set value of @code{XXXX} to @code{yyyy}. |
---|
1286 | |
---|
1287 | @item query sect offs @code{qOffsets} |
---|
1288 | Get section offsets. Reply is @code{Text=xxx;Data=yyy;Bss=zzz} |
---|
1289 | |
---|
1290 | @item console output Otext |
---|
1291 | Send text to stdout. The text gets display from the target side of the |
---|
1292 | serial connection. |
---|
1293 | |
---|
1294 | @end table |
---|
1295 | |
---|
1296 | Responses can be run-length encoded to save space. A @code{*}means that |
---|
1297 | the next character is an ASCII encoding giving a repeat count which |
---|
1298 | stands for that many repetitions of the character preceding the @code{*}. |
---|
1299 | The encoding is n+29, yielding a printable character where n >=3 |
---|
1300 | (which is where run length encoding starts to win). You can't use a |
---|
1301 | value of where n >126 because it's only a two byte value. An example |
---|
1302 | would be a @code{0*03} means the same thing as @code{0000}. |
---|
1303 | |
---|
1304 | @node Exception handler, ROM monitors, GNU remote protocol, GDB |
---|
1305 | @section A linked in exception handler |
---|
1306 | |
---|
1307 | A @emph{GDB stub} consists of two parts, support for the exception |
---|
1308 | handler, and the exception handler itself. The exception handler needs |
---|
1309 | to communicate to GDB on the host whenever there is a breakpoint |
---|
1310 | exception. When GDB starts a program running on the target, it's polling |
---|
1311 | the serial port during execution looking for any debug packets. So when |
---|
1312 | a breakpoint occurs, the exception handler needs to save state, and send |
---|
1313 | a GDB remote protocol packet to GDB on the host. GDB takes any output |
---|
1314 | that isn't a debug command packet and displays it in the command window. |
---|
1315 | |
---|
1316 | Support for the exception handler varies between processors, but the |
---|
1317 | minimum supported functions are those needed by GDB. These are functions |
---|
1318 | to support the reading and writing of registers, the reading and writing |
---|
1319 | of memory, start execution at an address, single step, and last signal. |
---|
1320 | Sometimes other functions for adjusting the baud rate, or resetting the |
---|
1321 | hardware are implemented. |
---|
1322 | |
---|
1323 | Once GDB gets the command packet from the breakpoint, it will read a few |
---|
1324 | registers and memory locations an then wait for the user. When the user |
---|
1325 | types @code{run} or @code{continue} a @code{continue} command is issued |
---|
1326 | to the backend, and control returns from the breakpoint routine to the |
---|
1327 | application. |
---|
1328 | |
---|
1329 | @node ROM monitors, Other remote protocols, Exception handler, GDB |
---|
1330 | @section Using a ROM monitor as a backend |
---|
1331 | GDB also can mimic a human user and use a ROM monitors normal debug |
---|
1332 | commands as a backend. This consists mostly of sending and parsing |
---|
1333 | @code{ASCII} strings. All the ROM monitor interfaces share a common set |
---|
1334 | of routines in @code{gdb/monitor.c}. This supports adding new ROM |
---|
1335 | monitor interfaces by filling in a structure with the common commands |
---|
1336 | GDB needs. GDb already supports several command ROM monitors, including |
---|
1337 | Motorola's @code{Bug} monitor for their VME boards, and the Rom68k |
---|
1338 | monitor by Integrated Systems, Inc. for various m68k based boards. GDB |
---|
1339 | also supports the custom ROM monitors on the WinBond and Oki PA based |
---|
1340 | targets. There is builtin support for loading files to ROM monitors |
---|
1341 | specifically. GDB can convert a binary into an srecord and then load it |
---|
1342 | as an ascii file, or using @code{xmodem}. |
---|
1343 | |
---|
1344 | @c FIXME: do I need trademark somethings here ? Is Integrated the right |
---|
1345 | @c company? |
---|
1346 | |
---|
1347 | @node Other remote protocols, ,ROM monitors, GDB |
---|
1348 | @section Adding support for new protocols |
---|
1349 | @c FIXME: write something here |
---|
1350 | |
---|
1351 | @node Binutils, Code Listings, GDB, Top |
---|
1352 | |
---|
1353 | @node Code Listings, idp.ld, Binutils, Top |
---|
1354 | @appendix Code Listings |
---|
1355 | |
---|
1356 | @menu |
---|
1357 | * idp.ld:: A m68k linker script. |
---|
1358 | * crt0.S:: Crt0.S for an m68k. |
---|
1359 | * glue.c:: C based support for for Stdio functions. |
---|
1360 | * mvme.S:: Rom monitor based I/O support in assembler. |
---|
1361 | * io.c:: C based for memory mapped I/O. |
---|
1362 | * leds.c:: C based LED routines. |
---|
1363 | @end menu |
---|
1364 | |
---|
1365 | @node idp.ld, crt0.S, Code Listings, Code Listings |
---|
1366 | @section Linker script for the IDP board |
---|
1367 | |
---|
1368 | This is the linker script script that is used on the Motorola IDP board. |
---|
1369 | |
---|
1370 | @example |
---|
1371 | STARTUP(crt0.o) |
---|
1372 | OUTPUT_ARCH(m68k) |
---|
1373 | INPUT(idp.o) |
---|
1374 | SEARCH_DIR(.) |
---|
1375 | __DYNAMIC = 0; |
---|
1376 | /* |
---|
1377 | * Setup the memory map of the MC68ec0x0 Board (IDP) |
---|
1378 | * stack grows up towards high memory. This works for |
---|
1379 | * both the rom68k and the mon68k monitors. |
---|
1380 | */ |
---|
1381 | MEMORY |
---|
1382 | @{ |
---|
1383 | ram : ORIGIN = 0x10000, LENGTH = 2M |
---|
1384 | @} |
---|
1385 | /* |
---|
1386 | * stick everything in ram (of course) |
---|
1387 | */ |
---|
1388 | SECTIONS |
---|
1389 | @{ |
---|
1390 | .text : |
---|
1391 | @{ |
---|
1392 | CREATE_OBJECT_SYMBOLS |
---|
1393 | *(.text) |
---|
1394 | etext = .; |
---|
1395 | __CTOR_LIST__ = .; |
---|
1396 | LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2) |
---|
1397 | *(.ctors) |
---|
1398 | LONG(0) |
---|
1399 | __CTOR_END__ = .; |
---|
1400 | __DTOR_LIST__ = .; |
---|
1401 | LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2) |
---|
1402 | *(.dtors) |
---|
1403 | LONG(0) |
---|
1404 | __DTOR_END__ = .; |
---|
1405 | *(.lit) |
---|
1406 | *(.shdata) |
---|
1407 | @} > ram |
---|
1408 | .shbss SIZEOF(.text) + ADDR(.text) : @{ |
---|
1409 | *(.shbss) |
---|
1410 | @} |
---|
1411 | .talias : @{ @} > ram |
---|
1412 | .data : @{ |
---|
1413 | *(.data) |
---|
1414 | CONSTRUCTORS |
---|
1415 | _edata = .; |
---|
1416 | @} > ram |
---|
1417 | |
---|
1418 | .bss SIZEOF(.data) + ADDR(.data) : |
---|
1419 | @{ |
---|
1420 | __bss_start = ALIGN(0x8); |
---|
1421 | *(.bss) |
---|
1422 | *(COMMON) |
---|
1423 | end = ALIGN(0x8); |
---|
1424 | _end = ALIGN(0x8); |
---|
1425 | __end = ALIGN(0x8); |
---|
1426 | @} |
---|
1427 | .mstack : @{ @} > ram |
---|
1428 | .rstack : @{ @} > ram |
---|
1429 | .stab . (NOLOAD) : |
---|
1430 | @{ |
---|
1431 | [ .stab ] |
---|
1432 | @} |
---|
1433 | .stabstr . (NOLOAD) : |
---|
1434 | @{ |
---|
1435 | [ .stabstr ] |
---|
1436 | @} |
---|
1437 | @} |
---|
1438 | @end example |
---|
1439 | |
---|
1440 | @node crt0.S, glue.c, idp.ld, Code Listings |
---|
1441 | @section crt0.S - The startup file |
---|
1442 | |
---|
1443 | @example |
---|
1444 | /* |
---|
1445 | * crt0.S -- startup file for m68k-coff |
---|
1446 | * |
---|
1447 | */ |
---|
1448 | |
---|
1449 | .title "crt0.S for m68k-coff" |
---|
1450 | |
---|
1451 | /* These are predefined by new versions of GNU cpp. */ |
---|
1452 | |
---|
1453 | #ifndef __USER_LABEL_PREFIX__ |
---|
1454 | #define __USER_LABEL_PREFIX__ _ |
---|
1455 | #endif |
---|
1456 | |
---|
1457 | #ifndef __REGISTER_PREFIX__ |
---|
1458 | #define __REGISTER_PREFIX__ |
---|
1459 | #endif |
---|
1460 | |
---|
1461 | /* ANSI concatenation macros. */ |
---|
1462 | |
---|
1463 | #define CONCAT1(a, b) CONCAT2(a, b) |
---|
1464 | #define CONCAT2(a, b) a ## b |
---|
1465 | |
---|
1466 | /* Use the right prefix for global labels. */ |
---|
1467 | |
---|
1468 | #define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x) |
---|
1469 | |
---|
1470 | /* Use the right prefix for registers. */ |
---|
1471 | |
---|
1472 | #define REG(x) CONCAT1 (__REGISTER_PREFIX__, x) |
---|
1473 | |
---|
1474 | #define d0 REG (d0) |
---|
1475 | #define d1 REG (d1) |
---|
1476 | #define d2 REG (d2) |
---|
1477 | #define d3 REG (d3) |
---|
1478 | #define d4 REG (d4) |
---|
1479 | #define d5 REG (d5) |
---|
1480 | #define d6 REG (d6) |
---|
1481 | #define d7 REG (d7) |
---|
1482 | #define a0 REG (a0) |
---|
1483 | #define a1 REG (a1) |
---|
1484 | #define a2 REG (a2) |
---|
1485 | #define a3 REG (a3) |
---|
1486 | #define a4 REG (a4) |
---|
1487 | #define a5 REG (a5) |
---|
1488 | #define a6 REG (a6) |
---|
1489 | #define fp REG (fp) |
---|
1490 | #define sp REG (sp) |
---|
1491 | |
---|
1492 | /* |
---|
1493 | * Set up some room for a stack. We just grab a chunk of memory. |
---|
1494 | */ |
---|
1495 | .set stack_size, 0x2000 |
---|
1496 | .comm SYM (stack), stack_size |
---|
1497 | |
---|
1498 | /* |
---|
1499 | * Define an empty environment. |
---|
1500 | */ |
---|
1501 | .data |
---|
1502 | .align 2 |
---|
1503 | SYM (environ): |
---|
1504 | .long 0 |
---|
1505 | |
---|
1506 | .align 2 |
---|
1507 | .text |
---|
1508 | .global SYM (stack) |
---|
1509 | |
---|
1510 | .global SYM (main) |
---|
1511 | .global SYM (exit) |
---|
1512 | /* |
---|
1513 | * This really should be __bss_start, not SYM (__bss_start). |
---|
1514 | */ |
---|
1515 | .global __bss_start |
---|
1516 | |
---|
1517 | /* |
---|
1518 | * start -- set things up so the application will run. |
---|
1519 | */ |
---|
1520 | SYM (start): |
---|
1521 | link a6, #-8 |
---|
1522 | moveal #SYM (stack) + stack_size, sp |
---|
1523 | |
---|
1524 | /* |
---|
1525 | * zerobss -- zero out the bss section |
---|
1526 | */ |
---|
1527 | moveal #__bss_start, a0 |
---|
1528 | moveal #SYM (end), a1 |
---|
1529 | 1: |
---|
1530 | movel #0, (a0) |
---|
1531 | leal 4(a0), a0 |
---|
1532 | cmpal a0, a1 |
---|
1533 | bne 1b |
---|
1534 | |
---|
1535 | /* |
---|
1536 | * Call the main routine from the application to get it going. |
---|
1537 | * main (argc, argv, environ) |
---|
1538 | * We pass argv as a pointer to NULL. |
---|
1539 | */ |
---|
1540 | pea 0 |
---|
1541 | pea SYM (environ) |
---|
1542 | pea sp@@(4) |
---|
1543 | pea 0 |
---|
1544 | jsr SYM (main) |
---|
1545 | movel d0, sp@@- |
---|
1546 | |
---|
1547 | /* |
---|
1548 | * _exit -- Exit from the application. Normally we cause a user trap |
---|
1549 | * to return to the ROM monitor for another run. |
---|
1550 | */ |
---|
1551 | SYM (exit): |
---|
1552 | trap #0 |
---|
1553 | @end example |
---|
1554 | |
---|
1555 | @node glue.c, mvme.S, crt0.S, Code Listings |
---|
1556 | @section C based "glue" code. |
---|
1557 | |
---|
1558 | @example |
---|
1559 | |
---|
1560 | /* |
---|
1561 | * glue.c -- all the code to make GCC and the libraries run on |
---|
1562 | * a bare target board. These should work with any |
---|
1563 | * target if inbyte() and outbyte() exist. |
---|
1564 | */ |
---|
1565 | |
---|
1566 | #include <sys/types.h> |
---|
1567 | #include <sys/stat.h> |
---|
1568 | #include <errno.h> |
---|
1569 | #ifndef NULL |
---|
1570 | #define NULL 0 |
---|
1571 | #endif |
---|
1572 | |
---|
1573 | /* FIXME: this is a hack till libc builds */ |
---|
1574 | __main() |
---|
1575 | @{ |
---|
1576 | return; |
---|
1577 | @} |
---|
1578 | |
---|
1579 | #undef errno |
---|
1580 | int errno; |
---|
1581 | |
---|
1582 | extern caddr_t _end; /* _end is set in the linker command file */ |
---|
1583 | extern int outbyte(); |
---|
1584 | extern unsigned char inbyte(); |
---|
1585 | extern int havebyte(); |
---|
1586 | |
---|
1587 | /* just in case, most boards have at least some memory */ |
---|
1588 | #ifndef RAMSIZE |
---|
1589 | # define RAMSIZE (caddr_t)0x100000 |
---|
1590 | #endif |
---|
1591 | |
---|
1592 | /* |
---|
1593 | * read -- read bytes from the serial port. Ignore fd, since |
---|
1594 | * we only have stdin. |
---|
1595 | */ |
---|
1596 | int |
---|
1597 | read(fd, buf, nbytes) |
---|
1598 | int fd; |
---|
1599 | char *buf; |
---|
1600 | int nbytes; |
---|
1601 | @{ |
---|
1602 | int i = 0; |
---|
1603 | |
---|
1604 | for (i = 0; i < nbytes; i++) @{ |
---|
1605 | *(buf + i) = inbyte(); |
---|
1606 | if ((*(buf + i) == '\n') || (*(buf + i) == '\r')) @{ |
---|
1607 | (*(buf + i)) = 0; |
---|
1608 | break; |
---|
1609 | @} |
---|
1610 | @} |
---|
1611 | return (i); |
---|
1612 | @} |
---|
1613 | |
---|
1614 | /* |
---|
1615 | * write -- write bytes to the serial port. Ignore fd, since |
---|
1616 | * stdout and stderr are the same. Since we have no filesystem, |
---|
1617 | * open will only return an error. |
---|
1618 | */ |
---|
1619 | int |
---|
1620 | write(fd, buf, nbytes) |
---|
1621 | int fd; |
---|
1622 | char *buf; |
---|
1623 | int nbytes; |
---|
1624 | @{ |
---|
1625 | int i; |
---|
1626 | |
---|
1627 | for (i = 0; i < nbytes; i++) @{ |
---|
1628 | if (*(buf + i) == '\n') @{ |
---|
1629 | outbyte ('\r'); |
---|
1630 | @} |
---|
1631 | outbyte (*(buf + i)); |
---|
1632 | @} |
---|
1633 | return (nbytes); |
---|
1634 | @} |
---|
1635 | |
---|
1636 | /* |
---|
1637 | * open -- open a file descriptor. We don't have a filesystem, so |
---|
1638 | * we return an error. |
---|
1639 | */ |
---|
1640 | int |
---|
1641 | open(buf, flags, mode) |
---|
1642 | char *buf; |
---|
1643 | int flags; |
---|
1644 | int mode; |
---|
1645 | @{ |
---|
1646 | errno = EIO; |
---|
1647 | return (-1); |
---|
1648 | @} |
---|
1649 | |
---|
1650 | /* |
---|
1651 | * close -- close a file descriptor. We don't need |
---|
1652 | * to do anything, but pretend we did. |
---|
1653 | */ |
---|
1654 | int |
---|
1655 | close(fd) |
---|
1656 | int fd; |
---|
1657 | @{ |
---|
1658 | return (0); |
---|
1659 | @} |
---|
1660 | |
---|
1661 | /* |
---|
1662 | * sbrk -- changes heap size size. Get nbytes more |
---|
1663 | * RAM. We just increment a pointer in what's |
---|
1664 | * left of memory on the board. |
---|
1665 | */ |
---|
1666 | caddr_t |
---|
1667 | sbrk(nbytes) |
---|
1668 | int nbytes; |
---|
1669 | @{ |
---|
1670 | static caddr_t heap_ptr = NULL; |
---|
1671 | caddr_t base; |
---|
1672 | |
---|
1673 | if (heap_ptr == NULL) @{ |
---|
1674 | heap_ptr = (caddr_t)&_end; |
---|
1675 | @} |
---|
1676 | |
---|
1677 | if ((RAMSIZE - heap_ptr) >= 0) @{ |
---|
1678 | base = heap_ptr; |
---|
1679 | heap_ptr += nbytes; |
---|
1680 | return (base); |
---|
1681 | @} else @{ |
---|
1682 | errno = ENOMEM; |
---|
1683 | return ((caddr_t)-1); |
---|
1684 | @} |
---|
1685 | @} |
---|
1686 | |
---|
1687 | /* |
---|
1688 | * isatty -- returns 1 if connected to a terminal device, |
---|
1689 | * returns 0 if not. Since we're hooked up to a |
---|
1690 | * serial port, we'll say yes and return a 1. |
---|
1691 | */ |
---|
1692 | int |
---|
1693 | isatty(fd) |
---|
1694 | int fd; |
---|
1695 | @{ |
---|
1696 | return (1); |
---|
1697 | @} |
---|
1698 | |
---|
1699 | /* |
---|
1700 | * lseek -- move read/write pointer. Since a serial port |
---|
1701 | * is non-seekable, we return an error. |
---|
1702 | */ |
---|
1703 | off_t |
---|
1704 | lseek(fd, offset, whence) |
---|
1705 | int fd; |
---|
1706 | off_t offset; |
---|
1707 | int whence; |
---|
1708 | @{ |
---|
1709 | errno = ESPIPE; |
---|
1710 | return ((off_t)-1); |
---|
1711 | @} |
---|
1712 | |
---|
1713 | /* |
---|
1714 | * fstat -- get status of a file. Since we have no file |
---|
1715 | * system, we just return an error. |
---|
1716 | */ |
---|
1717 | int |
---|
1718 | fstat(fd, buf) |
---|
1719 | int fd; |
---|
1720 | struct stat *buf; |
---|
1721 | @{ |
---|
1722 | errno = EIO; |
---|
1723 | return (-1); |
---|
1724 | @} |
---|
1725 | |
---|
1726 | /* |
---|
1727 | * getpid -- only one process, so just return 1. |
---|
1728 | */ |
---|
1729 | #define __MYPID 1 |
---|
1730 | int |
---|
1731 | getpid() |
---|
1732 | @{ |
---|
1733 | return __MYPID; |
---|
1734 | @} |
---|
1735 | |
---|
1736 | /* |
---|
1737 | * kill -- go out via exit... |
---|
1738 | */ |
---|
1739 | int |
---|
1740 | kill(pid, sig) |
---|
1741 | int pid; |
---|
1742 | int sig; |
---|
1743 | @{ |
---|
1744 | if(pid == __MYPID) |
---|
1745 | _exit(sig); |
---|
1746 | return 0; |
---|
1747 | @} |
---|
1748 | |
---|
1749 | /* |
---|
1750 | * print -- do a raw print of a string |
---|
1751 | */ |
---|
1752 | int |
---|
1753 | print(ptr) |
---|
1754 | char *ptr; |
---|
1755 | @{ |
---|
1756 | while (*ptr) @{ |
---|
1757 | outbyte (*ptr++); |
---|
1758 | @} |
---|
1759 | @} |
---|
1760 | |
---|
1761 | /* |
---|
1762 | * putnum -- print a 32 bit number in hex |
---|
1763 | */ |
---|
1764 | int |
---|
1765 | putnum (num) |
---|
1766 | unsigned int num; |
---|
1767 | @{ |
---|
1768 | char buffer[9]; |
---|
1769 | int count; |
---|
1770 | char *bufptr = buffer; |
---|
1771 | int digit; |
---|
1772 | |
---|
1773 | for (count = 7 ; count >= 0 ; count--) @{ |
---|
1774 | digit = (num >> (count * 4)) & 0xf; |
---|
1775 | |
---|
1776 | if (digit <= 9) |
---|
1777 | *bufptr++ = (char) ('0' + digit); |
---|
1778 | else |
---|
1779 | *bufptr++ = (char) ('a' - 10 + digit); |
---|
1780 | @} |
---|
1781 | |
---|
1782 | *bufptr = (char) 0; |
---|
1783 | print (buffer); |
---|
1784 | return; |
---|
1785 | @} |
---|
1786 | @end example |
---|
1787 | |
---|
1788 | @node mvme.S, io.c, glue.c, Code Listings |
---|
1789 | @section I/O assembler code sample |
---|
1790 | |
---|
1791 | @example |
---|
1792 | /* |
---|
1793 | * mvme.S -- board support for m68k |
---|
1794 | */ |
---|
1795 | |
---|
1796 | .title "mvme.S for m68k-coff" |
---|
1797 | |
---|
1798 | /* These are predefined by new versions of GNU cpp. */ |
---|
1799 | |
---|
1800 | #ifndef __USER_LABEL_PREFIX__ |
---|
1801 | #define __USER_LABEL_PREFIX__ _ |
---|
1802 | #endif |
---|
1803 | |
---|
1804 | #ifndef __REGISTER_PREFIX__ |
---|
1805 | #define __REGISTER_PREFIX__ |
---|
1806 | #endif |
---|
1807 | |
---|
1808 | /* ANSI concatenation macros. */ |
---|
1809 | |
---|
1810 | #define CONCAT1(a, b) CONCAT2(a, b) |
---|
1811 | #define CONCAT2(a, b) a ## b |
---|
1812 | |
---|
1813 | /* Use the right prefix for global labels. */ |
---|
1814 | |
---|
1815 | #define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x) |
---|
1816 | |
---|
1817 | /* Use the right prefix for registers. */ |
---|
1818 | |
---|
1819 | #define REG(x) CONCAT1 (__REGISTER_PREFIX__, x) |
---|
1820 | |
---|
1821 | #define d0 REG (d0) |
---|
1822 | #define d1 REG (d1) |
---|
1823 | #define d2 REG (d2) |
---|
1824 | #define d3 REG (d3) |
---|
1825 | #define d4 REG (d4) |
---|
1826 | #define d5 REG (d5) |
---|
1827 | #define d6 REG (d6) |
---|
1828 | #define d7 REG (d7) |
---|
1829 | #define a0 REG (a0) |
---|
1830 | #define a1 REG (a1) |
---|
1831 | #define a2 REG (a2) |
---|
1832 | #define a3 REG (a3) |
---|
1833 | #define a4 REG (a4) |
---|
1834 | #define a5 REG (a5) |
---|
1835 | #define a6 REG (a6) |
---|
1836 | #define fp REG (fp) |
---|
1837 | #define sp REG (sp) |
---|
1838 | #define vbr REG (vbr) |
---|
1839 | |
---|
1840 | .align 2 |
---|
1841 | .text |
---|
1842 | .global SYM (_exit) |
---|
1843 | .global SYM (outln) |
---|
1844 | .global SYM (outbyte) |
---|
1845 | .global SYM (putDebugChar) |
---|
1846 | .global SYM (inbyte) |
---|
1847 | .global SYM (getDebugChar) |
---|
1848 | .global SYM (havebyte) |
---|
1849 | .global SYM (exceptionHandler) |
---|
1850 | |
---|
1851 | .set vbr_size, 0x400 |
---|
1852 | .comm SYM (vbr_table), vbr_size |
---|
1853 | |
---|
1854 | /* |
---|
1855 | * inbyte -- get a byte from the serial port |
---|
1856 | * d0 - contains the byte read in |
---|
1857 | */ |
---|
1858 | .align 2 |
---|
1859 | SYM (getDebugChar): /* symbol name used by m68k-stub */ |
---|
1860 | SYM (inbyte): |
---|
1861 | link a6, #-8 |
---|
1862 | trap #15 |
---|
1863 | .word inchr |
---|
1864 | moveb sp@@, d0 |
---|
1865 | extbl d0 |
---|
1866 | unlk a6 |
---|
1867 | rts |
---|
1868 | |
---|
1869 | /* |
---|
1870 | * outbyte -- sends a byte out the serial port |
---|
1871 | * d0 - contains the byte to be sent |
---|
1872 | */ |
---|
1873 | .align 2 |
---|
1874 | SYM (putDebugChar): /* symbol name used by m68k-stub */ |
---|
1875 | SYM (outbyte): |
---|
1876 | link fp, #-4 |
---|
1877 | moveb fp@@(11), sp@@ |
---|
1878 | trap #15 |
---|
1879 | .word outchr |
---|
1880 | unlk fp |
---|
1881 | rts |
---|
1882 | |
---|
1883 | /* |
---|
1884 | * outln -- sends a string of bytes out the serial port with a CR/LF |
---|
1885 | * a0 - contains the address of the string's first byte |
---|
1886 | * a1 - contains the address of the string's last byte |
---|
1887 | */ |
---|
1888 | .align 2 |
---|
1889 | SYM (outln): |
---|
1890 | link a6, #-8 |
---|
1891 | moveml a0/a1, sp@@ |
---|
1892 | trap #15 |
---|
1893 | .word outln |
---|
1894 | unlk a6 |
---|
1895 | rts |
---|
1896 | |
---|
1897 | /* |
---|
1898 | * outstr -- sends a string of bytes out the serial port without a CR/LF |
---|
1899 | * a0 - contains the address of the string's first byte |
---|
1900 | * a1 - contains the address of the string's last byte |
---|
1901 | */ |
---|
1902 | .align 2 |
---|
1903 | SYM (outstr): |
---|
1904 | link a6, #-8 |
---|
1905 | moveml a0/a1, sp@@ |
---|
1906 | trap #15 |
---|
1907 | .word outstr |
---|
1908 | unlk a6 |
---|
1909 | rts |
---|
1910 | |
---|
1911 | /* |
---|
1912 | * havebyte -- checks to see if there is a byte in the serial port, |
---|
1913 | * returns 1 if there is a byte, 0 otherwise. |
---|
1914 | */ |
---|
1915 | SYM (havebyte): |
---|
1916 | trap #15 |
---|
1917 | .word instat |
---|
1918 | beqs empty |
---|
1919 | movel #1, d0 |
---|
1920 | rts |
---|
1921 | empty: |
---|
1922 | movel #0, d0 |
---|
1923 | rts |
---|
1924 | |
---|
1925 | /* |
---|
1926 | * These constants are for the MVME-135 board's boot monitor. They |
---|
1927 | * are used with a TRAP #15 call to access the monitor's I/O routines. |
---|
1928 | * they must be in the word following the trap call. |
---|
1929 | */ |
---|
1930 | .set inchr, 0x0 |
---|
1931 | .set instat, 0x1 |
---|
1932 | .set inln, 0x2 |
---|
1933 | .set readstr, 0x3 |
---|
1934 | .set readln, 0x4 |
---|
1935 | .set chkbrk, 0x5 |
---|
1936 | |
---|
1937 | .set outchr, 0x20 |
---|
1938 | .set outstr, 0x21 |
---|
1939 | .set outln, 0x22 |
---|
1940 | .set write, 0x23 |
---|
1941 | .set writeln, 0x24 |
---|
1942 | .set writdln, 0x25 |
---|
1943 | .set pcrlf, 0x26 |
---|
1944 | .set eraseln, 0x27 |
---|
1945 | .set writd, 0x28 |
---|
1946 | .set sndbrk, 0x29 |
---|
1947 | |
---|
1948 | .set tm_ini, 0x40 |
---|
1949 | .set dt_ini, 0x42 |
---|
1950 | .set tm_disp, 0x43 |
---|
1951 | .set tm_rd, 0x44 |
---|
1952 | |
---|
1953 | .set redir, 0x60 |
---|
1954 | .set redir_i, 0x61 |
---|
1955 | .set redir_o, 0x62 |
---|
1956 | .set return, 0x63 |
---|
1957 | .set bindec, 0x64 |
---|
1958 | |
---|
1959 | .set changev, 0x67 |
---|
1960 | .set strcmp, 0x68 |
---|
1961 | .set mulu32, 0x69 |
---|
1962 | .set divu32, 0x6A |
---|
1963 | .set chk_sum, 0x6B |
---|
1964 | |
---|
1965 | @end example |
---|
1966 | |
---|
1967 | @node io.c, leds.c, mvme.S, Code Listings |
---|
1968 | @section I/O code sample |
---|
1969 | |
---|
1970 | @example |
---|
1971 | #include "w89k.h" |
---|
1972 | |
---|
1973 | /* |
---|
1974 | * outbyte -- shove a byte out the serial port. We wait till the byte |
---|
1975 | */ |
---|
1976 | int |
---|
1977 | outbyte(byte) |
---|
1978 | unsigned char byte; |
---|
1979 | @{ |
---|
1980 | while ((inp(RS232REG) & TRANSMIT) == 0x0) @{ @} ; |
---|
1981 | return (outp(RS232PORT, byte)); |
---|
1982 | @} |
---|
1983 | |
---|
1984 | /* |
---|
1985 | * inbyte -- get a byte from the serial port |
---|
1986 | */ |
---|
1987 | unsigned char |
---|
1988 | inbyte() |
---|
1989 | @{ |
---|
1990 | while ((inp(RS232REG) & RECEIVE) == 0x0) @{ @}; |
---|
1991 | return (inp(RS232PORT)); |
---|
1992 | @} |
---|
1993 | @end example |
---|
1994 | |
---|
1995 | @node leds.c, ,io.c, Code Listings |
---|
1996 | @section Led control sample |
---|
1997 | |
---|
1998 | @example |
---|
1999 | /* |
---|
2000 | * leds.h -- control the led's on a Motorola mc68ec0x0 board. |
---|
2001 | */ |
---|
2002 | |
---|
2003 | #ifndef __LEDS_H__ |
---|
2004 | #define __LEDS_H__ |
---|
2005 | |
---|
2006 | #define LED_ADDR 0xd00003 |
---|
2007 | #define LED_0 ~0x1 |
---|
2008 | #define LED_1 ~0x2 |
---|
2009 | #define LED_2 ~0x4 |
---|
2010 | #define LED_3 ~0x8 |
---|
2011 | #define LED_4 ~0x10 |
---|
2012 | #define LED_5 ~0x20 |
---|
2013 | #define LED_6 ~0x40 |
---|
2014 | #define LED_7 ~0x80 |
---|
2015 | #define LEDS_OFF 0xff |
---|
2016 | #define LEDS_ON 0x0 |
---|
2017 | |
---|
2018 | #define FUDGE(x) ((x >= 0xa && x <= 0xf) ? (x + 'a') & 0x7f : (x + '0') & 0x7f) |
---|
2019 | |
---|
2020 | extern void led_putnum( char ); |
---|
2021 | |
---|
2022 | #endif /* __LEDS_H__ */ |
---|
2023 | |
---|
2024 | /* |
---|
2025 | * leds.c -- control the led's on a Motorola mc68ec0x0 (IDP)board. |
---|
2026 | */ |
---|
2027 | #include "leds.h" |
---|
2028 | |
---|
2029 | void zylons(); |
---|
2030 | void led_putnum(); |
---|
2031 | |
---|
2032 | /* |
---|
2033 | * led_putnum -- print a hex number on the LED. the value of num must be a char with |
---|
2034 | * the ascii value. ie... number 0 is '0', a is 'a', ' ' (null) clears |
---|
2035 | * the led display. |
---|
2036 | * Setting the bit to 0 turns it on, 1 turns it off. |
---|
2037 | * the LED's are controlled by setting the right bit mask in the base |
---|
2038 | * address. |
---|
2039 | * The bits are: |
---|
2040 | * [d.p | g | f | e | d | c | b | a ] is the byte. |
---|
2041 | * |
---|
2042 | * The locations are: |
---|
2043 | * |
---|
2044 | * a |
---|
2045 | * ----- |
---|
2046 | * f | | b |
---|
2047 | * | g | |
---|
2048 | * ----- |
---|
2049 | * | | |
---|
2050 | * e | | c |
---|
2051 | * ----- |
---|
2052 | * d . d.p (decimal point) |
---|
2053 | */ |
---|
2054 | void |
---|
2055 | led_putnum ( num ) |
---|
2056 | char num; |
---|
2057 | @{ |
---|
2058 | static unsigned char *leds = (unsigned char *)LED_ADDR; |
---|
2059 | static unsigned char num_bits [18] = @{ |
---|
2060 | 0xff, /* clear all */ |
---|
2061 | 0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x98, /* numbers 0-9 */ |
---|
2062 | 0x98, 0x20, 0x3, 0x27, 0x21, 0x4, 0xe /* letters a-f */ |
---|
2063 | @}; |
---|
2064 | |
---|
2065 | if (num >= '0' && num <= '9') |
---|
2066 | num = (num - '0') + 1; |
---|
2067 | |
---|
2068 | if (num >= 'a' && num <= 'f') |
---|
2069 | num = (num - 'a') + 12; |
---|
2070 | |
---|
2071 | if (num == ' ') |
---|
2072 | num = 0; |
---|
2073 | |
---|
2074 | *leds = num_bits[num]; |
---|
2075 | @} |
---|
2076 | |
---|
2077 | /* |
---|
2078 | * zylons -- draw a rotating pattern. NOTE: this function never returns. |
---|
2079 | */ |
---|
2080 | void |
---|
2081 | zylons() |
---|
2082 | @{ |
---|
2083 | unsigned char *leds = (unsigned char *)LED_ADDR; |
---|
2084 | unsigned char curled = 0xfe; |
---|
2085 | |
---|
2086 | while (1) |
---|
2087 | @{ |
---|
2088 | *leds = curled; |
---|
2089 | curled = (curled >> 1) | (curled << 7); |
---|
2090 | delay ( 200 ); |
---|
2091 | @} |
---|
2092 | @} |
---|
2093 | @end example |
---|
2094 | |
---|
2095 | @page |
---|
2096 | @contents |
---|
2097 | @c second page break makes sure right-left page alignment works right |
---|
2098 | @c with a one-page toc, even though we don't have setchapternewpage odd. |
---|
2099 | @page |
---|
2100 | @bye |
---|