]> git.sur5r.net Git - cc65/blob - doc/customizing.sgml
Code review adaptations, removed "cc65_" prefix from functions
[cc65] / doc / customizing.sgml
1 <!doctype linuxdoc system>
2
3 <article>
4 <title>Defining a Custom cc65 Target
5 <author>Bruce Reidenbach
6
7 <abstract>
8 This section provides step-by-step instructions on how to use the cc65
9 toolset for a custom hardware platform (a target system not currently
10 supported by the cc65 library set).
11 </abstract>
12
13 <!-- Table of contents -->
14
15 <toc>
16
17 <!-- Begin the document -->
18
19 <sect>Overview<p>
20
21 The cc65 toolset provides a set of pre-defined libraries that allow the
22 user to target the executable image to a variety of hardware platforms.
23 In addition, the user can create a customized environment so that the
24 executable can be targeted to a custom platform.  The following
25 instructions provide step-by-step instructions on how to customize the
26 toolset for a target that is not supported by the standard cc65
27 installation.
28
29 The platform used in this example is a Xilinx Field Programmable Gate
30 Array (FPGA) with an embedded 65C02 core.  The processor core supports
31 the additional opcodes/addressing modes of the 65SC02, along with the
32 STP and WAI instructions.  These instructions will create a set of files
33 to create a custom target, named SBC, for <bf>S</bf>ingle <bf>B</bf>oard
34 <bf>C</bf>omputer.
35
36 <sect>System Memory Map Definition<p>
37
38 The targeted system uses block RAM contained on the XILINX FPGA for the
39 system memory (both RAM and ROM).  The block RAMs are available in
40 various aspect ratios, and they will be used in this system as 2K*8
41 devices.  There will be two RAMs used for data storage, starting at
42 location $0000 and growing upwards.  There will be one ROM (realized as
43 initialized RAM) used code storage, starting at location $FFFF and
44 growing downwards.
45
46 The cc65 toolset requires a memory configuration file to define the
47 memory that is available to the cc65 run-time environment, which is
48 defined as follows:
49
50 <tscreen><code>
51 MEMORY {
52     ZP:        start =    $0, size =  $100, type   = rw, define = yes;
53     RAM:       start =  $200, size = $0E00, define = yes;
54     ROM:       start = $F800, size = $0800, file   = %O;
55 }
56 </code></tscreen>
57
58 ZP defines the available zero page locations, which in this case starts
59 at $0 and has a length of $100.  Keep in mind that certain systems may
60 require access to some zero page locations, so the starting address may
61 need to be adjusted accordingly to prevent cc65 from attempting to reuse
62 those locations.  Also, at a minimum, the cc65 run-time environment uses
63 26 zero page locations, so the smallest zero page size that can be
64 specified is $1A.  The usable RAM memory area begins after the 6502
65 stack storage in page 1, so it is defined as starting at location $200
66 and filling the remaining 4K of space (4096 - 2 *
67 256&nbsp;=&nbsp;3584&nbsp;=&nbsp;$0E00).  The 2K of ROM space begins at
68 address $F800 and goes to $FFFF (size&nbsp;=&nbsp;$0800).
69
70 Next, the memory segments within the memory devices need to be defined.
71 A standard segment definition is used, with one notable exception.  The
72 interrupt and reset vector locations need to be defined at locations
73 $FFFA through $FFFF.  A special segment named VECTORS is defined that
74 resides at these locations.  Later, the interrupt vector map will be
75 created and placed in the VECTORS segment, and the linker will put these
76 vectors at the proper memory locations.  The segment definition is:
77
78 <tscreen><code>
79 SEGMENTS {
80     ZEROPAGE: load = ZP,  type = zp,  define   = yes;
81     DATA:     load = ROM, type = rw,  define   = yes, run = RAM;
82     BSS:      load = RAM, type = bss, define   = yes;
83     HEAP:     load = RAM, type = bss, optional = yes;
84     STARTUP:  load = ROM, type = ro;
85     ONCE:     load = ROM, type = ro,  optional = yes;
86     CODE:     load = ROM, type = ro;
87     RODATA:   load = ROM, type = ro;
88     VECTORS:  load = ROM, type = ro,  start    = $FFFA;
89 }
90 </code></tscreen>
91
92 The meaning of each of these segments is as follows.
93
94 <p><tt>       ZEROPAGE:  </tt>Data in page 0, defined by ZP as starting at $0 with length $100
95 <p><tt>       DATA:      </tt>Initialized data that can be modified by the program, stored in RAM
96 <p><tt>       BSS:       </tt>Uninitialized data stored in RAM (used for variable storage)
97 <p><tt>       HEAP:      </tt>Uninitialized C-level heap storage in RAM, optional
98 <p><tt>       STARTUP:   </tt>The program initialization code, stored in ROM
99 <p><tt>       ONCE:      </tt>The code run once to initialize the system, stored in ROM
100 <p><tt>       CODE:      </tt>The program code, stored in ROM
101 <p><tt>       RODATA:    </tt>Initialized data that cannot be modified by the program, stored in ROM
102 <p><tt>       VECTORS:   </tt>The interrupt vector table, stored in ROM at location $FFFA
103
104 A note about initialized data:  any variables that require an initial
105 value, such as external (global) variables, require that the initial
106 values be stored in the ROM code image.  However, variables stored in
107 ROM cannot change; therefore the data must be moved into variables that
108 are located in RAM.  Specifying <tt>run&nbsp;=&nbsp;RAM</tt> as part of
109 the DATA segment definition will indicate that those variables will
110 require their initialization value to be copied via a call to the
111 <tt>copydata</tt> routine in the startup assembly code.  In addition,
112 there are system level variables that will need to be initialized as
113 well, especially if the heap segment is used via a C-level call to
114 <tt>malloc&nbsp;()</tt>.
115
116 The final section of the definition file contains the data constructors
117 and destructors used for system startup.  In addition, if the heap is
118 used, the maximum C-level stack size needs to be defined in order for
119 the system to be able to reliably allocate blocks of memory.  The stack
120 size selection must be greater than the maximum amount of storage
121 required to run the program, keeping in mind that the C-level subroutine
122 call stack and all local variables are stored in this stack.  The
123 <tt>FEATURES</tt> section defines the required constructor/destructor
124 attributes and the <tt>SYMBOLS</tt> section defines the stack size.  The
125 constructors will be run via a call to <tt>initlib</tt> in the startup
126 assembly code and the destructors will be run via an assembly language
127 call to <tt>donelib</tt> during program termination.
128
129 <tscreen><code>
130 FEATURES {
131     CONDES:    segment = STARTUP,
132                type    = constructor,
133                label   = __CONSTRUCTOR_TABLE__,
134                count   = __CONSTRUCTOR_COUNT__;
135     CONDES:    segment = STARTUP,
136                type    = destructor,
137                label   = __DESTRUCTOR_TABLE__,
138                count   = __DESTRUCTOR_COUNT__;
139 }
140
141 SYMBOLS {
142     # Define the stack size for the application
143     __STACKSIZE__:  value = $0200, weak = yes;
144 }
145 </code></tscreen>
146
147 These definitions are placed in a file named &quot;sbc.cfg&quot;
148 and are referred to during the ld65 linker stage.
149
150 <sect>Startup Code Definition<p>
151
152 In the cc65 toolset, a startup routine must be defined that is executed
153 when the CPU is reset.  This startup code is marked with the STARTUP
154 segment name, which was defined in the system configuration file as
155 being in read only memory.  The standard convention used in the
156 predefined libraries is that this code is resident in the crt0 module.
157 For this custom system, all that needs to be done is to perform a little
158 bit of 6502 housekeeping, set up the C-level stack pointer, initialize
159 the memory storage, and call the C-level routine <tt>main&nbsp;()</tt>.
160 The following code was used for the crt0 module, defined in the file
161 &quot;crt0.s&quot;:
162
163 <tscreen><code>
164 ; ---------------------------------------------------------------------------
165 ; crt0.s
166 ; ---------------------------------------------------------------------------
167 ;
168 ; Startup code for cc65 (Single Board Computer version)
169
170 .export   _init, _exit
171 .import   _main
172
173 .export   __STARTUP__ : absolute = 1        ; Mark as startup
174 .import   __RAM_START__, __RAM_SIZE__       ; Linker generated
175
176 .import    copydata, zerobss, initlib, donelib
177
178 .include  &quot;zeropage.inc&quot;
179
180 ; ---------------------------------------------------------------------------
181 ; Place the startup code in a special segment
182
183 .segment  &quot;STARTUP&quot;
184
185 ; ---------------------------------------------------------------------------
186 ; A little light 6502 housekeeping
187
188 _init:    LDX     #$FF                 ; Initialize stack pointer to $01FF
189           TXS
190           CLD                          ; Clear decimal mode
191
192 ; ---------------------------------------------------------------------------
193 ; Set cc65 argument stack pointer
194
195           LDA     #&lt;(__RAM_START__ + __RAM_SIZE__)
196           STA     sp
197           LDA     #&gt;(__RAM_START__ + __RAM_SIZE__)
198           STA     sp+1
199
200 ; ---------------------------------------------------------------------------
201 ; Initialize memory storage
202
203           JSR     zerobss              ; Clear BSS segment
204           JSR     copydata             ; Initialize DATA segment
205           JSR     initlib              ; Run constructors
206
207 ; ---------------------------------------------------------------------------
208 ; Call main()
209
210           JSR     _main
211
212 ; ---------------------------------------------------------------------------
213 ; Back from main (this is also the _exit entry):  force a software break
214
215 _exit:    JSR     donelib              ; Run destructors
216           BRK
217 </code></tscreen>
218
219 The following discussion explains the purpose of several important
220 assembler level directives in this file.
221
222 <tscreen><verb>
223 .export   _init, _exit
224 </verb></tscreen>
225
226 This line instructs the assembler that the symbols <tt>_init</tt> and
227 <tt>_exit</tt> are to be accessible from other modules.  In this
228 example, <tt>_init</tt> is the location that the CPU should jump to when
229 reset, and <tt>_exit</tt> is the location that will be called when the
230 program is finished.
231
232 <tscreen><verb>
233 .import   _main
234 </verb></tscreen>
235
236 This line instructs the assembler to import the symbol <tt>_main</tt>
237 from another module.  cc65 names all C-level routines as
238 {underscore}{name} in assembler, thus the <tt>main&nbsp;()</tt> routine
239 in C is named <tt>_main</tt> in the assembler.  This is how the startup
240 code will link to the C-level code.
241
242 <tscreen><verb>
243 .export   __STARTUP__ : absolute = 1        ; Mark as startup
244 </verb></tscreen>
245
246 This line marks this code as startup code (code that is executed when
247 the processor is reset), which will then be automatically linked into
248 the executable code.
249
250 <tscreen><verb>
251 .import   __RAM_START__, __RAM_SIZE__       ; Linker generated
252 </verb></tscreen>
253
254 This line imports the RAM starting address and RAM size constants, which
255 are used to initialize the cc65 C-level argument stack pointer.
256
257 <tscreen><verb>
258 .segment  &quot;STARTUP&quot;
259 </verb></tscreen>
260
261 This line instructs the assembler that the code is to be placed in the
262 STARTUP segment of memory.
263
264 <tscreen><verb>
265           JSR     zerobss              ; Clear BSS segment
266           JSR     copydata             ; Initialize DATA segment
267           JSR     initlib              ; Run constructors
268 </verb></tscreen>
269
270 These three lines initialize the external (global) and system
271 variables.  The first line sets the BSS segment -- the memory locations
272 used for external variables -- to 0.  The second line copies the
273 initialization value stored in ROM to the RAM locations used for
274 initialized external variables.  The last line runs the constructors
275 that are used to initialize the system run-time variables.
276
277 <tscreen><verb>
278           JSR     _main
279 </verb></tscreen>
280
281 This is the actual call to the C-level <tt>main&nbsp;()</tt> routine,
282 which is called after the startup code completes.
283
284 <tscreen><verb>
285 _exit:    JSR     donelib              ; Run destructors
286           BRK
287 </verb></tscreen>
288
289 This is the code that will be executed when <tt>main ()</tt>
290 terminates.  The first thing that must be done is run the destructors
291 via a call to <tt>donelib</tt>.  Then the program can terminate.  In
292 this example, the program is expected to run forever.  Therefore, there
293 needs to be a way of indicating when something has gone wrong and the
294 system needs to be shut down, requiring a restart only by a hard reset.
295 The BRK instruction will be used to indicate a software fault.  This is
296 advantageous because cc65 uses the BRK instruction as the fill byte in
297 the final binary code.  In addition, the hardware has been designed to
298 force the data lines to $00 for all illegal memory accesses, thereby
299 also forcing a BRK instruction into the CPU.
300
301 <sect>Custom Run-Time Library Creation<p>
302
303 The next step in customizing the cc65 toolset is creating a run-time
304 library for the targeted hardware.  The easiest way to do this is to
305 modify a standard library from the cc65 distribution.  In this example,
306 there is no console I/O, mouse, joystick, etc. in the system, so it is
307 most appropriate to use the simplest library as the base, which is for
308 the Watara Supervision and is named &quot;supervision.lib&quot; in the
309 lib directory of the distribution.
310
311 The only modification required is to replace the <tt>crt0</tt> module in
312 the supervision.lib library with custom startup code.  This is simply
313 done by first copying the library and giving it a new name, compiling
314 the startup code with ca65, and finally using the ar65 archiver to
315 replace the module in the new library.  The steps are shown below:
316
317 <tscreen><verb>
318 $ copy &quot;C:\Program Files\cc65\lib\supervision.lib&quot; sbc.lib
319 $ ca65 crt0.s
320 $ ar65 a sbc.lib crt0.o
321 </verb></tscreen>
322
323 <sect>Interrupt Service Routine Definition<p>
324
325 For this system, the CPU is put into a wait condition prior to allowing
326 interrupt processing.  Therefore, the interrupt service routine is very
327 simple:  return from all valid interrupts.  However, as mentioned
328 before, the BRK instruction is used to indicate a software fault, which
329 will call the same interrupt service routine as the maskable interrupt
330 signal IRQ.  The interrupt service routine must be able to tell the
331 difference between the two, and act appropriately.
332
333 The interrupt service routine shown below includes code to detect when a
334 BRK instruction has occurred and stops the CPU from further processing.
335 The interrupt service routine is in a file named
336 &quot;interrupt.s&quot;.
337
338 <tscreen><code>
339 ; ---------------------------------------------------------------------------
340 ; interrupt.s
341 ; ---------------------------------------------------------------------------
342 ;
343 ; Interrupt handler.
344 ;
345 ; Checks for a BRK instruction and returns from all valid interrupts.
346
347 .import   _stop
348 .export   _irq_int, _nmi_int
349
350 .segment  &quot;CODE&quot;
351
352 .PC02                             ; Force 65C02 assembly mode
353
354 ; ---------------------------------------------------------------------------
355 ; Non-maskable interrupt (NMI) service routine
356
357 _nmi_int:  RTI                    ; Return from all NMI interrupts
358
359 ; ---------------------------------------------------------------------------
360 ; Maskable interrupt (IRQ) service routine
361
362 _irq_int:  PHX                    ; Save X register contents to stack
363            TSX                    ; Transfer stack pointer to X
364            PHA                    ; Save accumulator contents to stack
365            INX                    ; Increment X so it points to the status
366            INX                    ;   register value saved on the stack
367            LDA $100,X             ; Load status register contents
368            AND #$10               ; Isolate B status bit
369            BNE break              ; If B = 1, BRK detected
370
371 ; ---------------------------------------------------------------------------
372 ; IRQ detected, return
373
374 irq:       PLA                    ; Restore accumulator contents
375            PLX                    ; Restore X register contents
376            RTI                    ; Return from all IRQ interrupts
377
378 ; ---------------------------------------------------------------------------
379 ; BRK detected, stop
380
381 break:     JMP _stop              ; If BRK is detected, something very bad
382                                   ;   has happened, so stop running
383 </code></tscreen>
384
385 The following discussion explains the purpose of several important
386 assembler level directives in this file.
387
388 <tscreen><verb>
389 .import   _stop
390 </verb></tscreen>
391
392 This line instructs the assembler to import the symbol <tt>_stop</tt>
393 from another module.  This routine will be called if a BRK instruction
394 is encountered, signaling a software fault.
395
396 <tscreen><verb>
397 .export   _irq_int, _nmi_int
398 </verb></tscreen>
399
400 This line instructs the assembler that the symbols <tt>_irq_int</tt> and
401 <tt>_nmi_int</tt> are to be accessible from other modules.  In this
402 example, the address of these symbols will be placed in the interrupt
403 vector table.
404
405 <tscreen><verb>
406 .segment  &quot;CODE&quot;
407 </verb></tscreen>
408
409 This line instructs the assembler that the code is to be placed in the
410 CODE segment of memory.  Note that because there are 65C02 mnemonics in
411 the assembly code, the assembler is forced to use the 65C02 instruction
412 set with the <tt>.PC02</tt> directive.
413
414 The final step is to define the interrupt vector memory locations.
415 Recall that a segment named VECTORS was defined in the memory
416 configuration file, which started at location $FFFA.  The addresses of
417 the interrupt service routines from &quot;interrupt.s&quot; along with
418 the address for the initialization code in crt0 are defined in a file
419 named &quot;vectors.s&quot;.  Note that these vectors will be placed in
420 memory in their proper little-endian format as:
421
422 <p><tt>       $FFFA&nbsp;-&nbsp;$FFFB:</tt> NMI interrupt vector (low byte, high byte)
423 <p><tt>       $FFFC&nbsp;-&nbsp;$FFFD:</tt> Reset vector (low byte, high byte)
424 <p><tt>       $FFFE&nbsp;-&nbsp;$FFFF:</tt> IRQ/BRK interrupt vector (low byte, high byte)
425
426 using the <tt>.addr</tt> assembler directive.  The contents of the file are:
427
428 <tscreen><code>
429 ; ---------------------------------------------------------------------------
430 ; vectors.s
431 ; ---------------------------------------------------------------------------
432 ;
433 ; Defines the interrupt vector table.
434
435 .import    _init
436 .import    _nmi_int, _irq_int
437
438 .segment  &quot;VECTORS&quot;
439
440 .addr      _nmi_int    ; NMI vector
441 .addr      _init       ; Reset vector
442 .addr      _irq_int    ; IRQ/BRK vector
443 </code></tscreen>
444
445 The cc65 toolset will replace the address symbols defined here with the
446 actual addresses of the routines during the link process.
447
448 <sect>Adding Custom Instructions<p>
449
450 The cc65 instruction set only supports the WAI (Wait for Interrupt) and
451 STP (Stop) instructions when used with the 65816 CPU (accessed via the
452 --cpu command line option of the ca65 macro assembler).  The 65C02 core
453 used in this example supports these two instructions, and in fact the
454 system benefits from the use of both the WAI and STP instructions.
455
456 In order to use the WAI instruction in this case, a C routine named
457 &quot;wait&quot; was created that consists of the WAI opcode followed by
458 a subroutine return.  It was convenient in this example to put the IRQ
459 interrupt enable in this subroutine as well, since interrupts should
460 only be enabled when the code is in this wait condition.
461
462 For both the WAI and STP instructions, the assembler is
463 &quot;fooled&quot; into placing those opcodes into memory by inserting a
464 single byte of data that just happens to be the opcode for those
465 instructions.  The assembly code routines are placed in a file, named
466 &quot;wait.s&quot;, which is shown below:
467
468 <tscreen><code>
469 ; ---------------------------------------------------------------------------
470 ; wait.s
471 ; ---------------------------------------------------------------------------
472 ;
473 ; Wait for interrupt and return
474
475 .export  _wait, _stop
476
477 ; ---------------------------------------------------------------------------
478 ; Wait for interrupt:  Forces the assembler to emit a WAI opcode ($CB)
479 ; ---------------------------------------------------------------------------
480
481 .segment  &quot;CODE&quot;
482
483 .proc _wait: near
484
485            CLI                    ; Enable interrupts
486 .byte      $CB                    ; Inserts a WAI opcode
487            RTS                    ; Return to caller
488
489 .endproc
490
491 ; ---------------------------------------------------------------------------
492 ; Stop:  Forces the assembler to emit a STP opcode ($DB)
493 ; ---------------------------------------------------------------------------
494
495 .proc _stop: near
496
497 .byte      $DB                    ; Inserts a STP opcode
498
499 .endproc
500 </code></tscreen>
501
502 The label <tt>_wait</tt>, when exported, can be called by using the
503 <tt>wait&nbsp;()</tt> subroutine call in C.  The section is marked as
504 code so that it will be stored in read-only memory, and the procedure is
505 tagged for 16-bit absolute addressing via the &quot;near&quot;
506 modifier.  Similarly, the <tt>_stop</tt> routine can be called from
507 within the C-level code via a call to <tt>stop&nbsp;()</tt>.  In
508 addition, the routine can be called from assembly code by calling
509 <tt>_stop</tt> (as was done in the interrupt service routine).
510
511 <sect>Hardware Drivers<p>
512
513 Oftentimes, it can be advantageous to create small application helpers
514 in assembly language to decrease codespace and increase execution speed
515 of the overall program.  An example of this would be the transfer of
516 characters to a FIFO (<bf>F</bf>irst-<bf>I</bf>n,
517 <bf>F</bf>irst-<bf>O</bf>ut) storage buffer for transmission over a
518 serial port.  This simple action could be performed by an assembly
519 language driver which would execute much quicker than coding it in C.
520 The following discussion outlines a method of interfacing a C program
521 with an assembly language subroutine.
522
523 The first step in creating the assembly language code for the driver is
524 to determine how to pass the C arguments to the assembly language
525 routine.  The cc65 toolset allows the user to specify whether the data
526 is passed to a subroutine via the stack or by the processor registers by
527 using the <tt/__fastcall__/ and <tt/__cdecl__/ function qualifiers (note that
528 there are two underscore characters in front of and two behind each
529 qualifier).  <tt/__fastcall__/ is the default.  When <tt/__cdecl__/ <em/isn't/
530 specified, and the function isn't variadic (i.e., its prototype doesn't have
531 an ellipsis), the rightmost argument in the function call is passed to the
532 subroutine using the 6502 registers instead of the stack.  Note that if
533 there is only one argument in the function call, the execution overhead
534 required by the stack interface routines is completely avoided.
535
536 With <tt/__cdecl__</tt>, the last argument is loaded into the A and X
537 registers and then pushed onto the stack via a call to <tt>pushax</tt>.
538 The first thing the subroutine does is retrieve the argument from the
539 stack via a call to <tt>ldax0sp</tt>, which copies the values into the A
540 and X.  When the subroutine is finished, the values on the stack must be
541 popped off and discarded via a jump to <tt>incsp2</tt>, which includes
542 the RTS subroutine return command.  This is shown in the following code
543 sample.
544
545 Calling sequence:
546
547 <tscreen><verb>
548         lda     #&lt;(L0001)  ;  Load A with the high order byte
549         ldx     #&gt;(L0001)  ;  Load X with the low order byte
550         jsr     pushax     ;  Push A and X onto the stack
551         jsr     _foo       ;  Call foo, i.e., foo (arg)
552 </verb></tscreen>
553
554 Subroutine code:
555
556 <tscreen><verb>
557 _foo:   jsr     ldax0sp    ;  Retrieve A and X from the stack
558         sta     ptr        ;  Store A in ptr
559         stx     ptr+1      ;  Store X in ptr+1
560         ...                ;  (more subroutine code goes here)
561         jmp     incsp2     ;  Pop A and X from the stack (includes return)
562 </verb></tscreen>
563
564 If <tt/__cdecl__/ isn't specified, then the argument is loaded into the A
565 and X registers as before, but the subroutine is then called
566 immediately.  The subroutine does not need to retrieve the argument
567 since the value is already available in the A and X registers.
568 Furthermore, the subroutine can be terminated with an RTS statement
569 since there is no stack cleanup which needs to be performed.  This is
570 shown in the following code sample.
571
572 Calling sequence:
573
574 <tscreen><verb>
575         lda     #&lt;(L0001)  ;  Load A with the high order byte
576         ldx     #&gt;(L0001)  ;  Load X with the low order byte
577         jsr     _foo       ;  Call foo, i.e., foo (arg)
578 </verb></tscreen>
579
580 Subroutine code:
581
582 <tscreen><verb>
583 _foo:   sta     ptr        ;  Store A in ptr
584         stx     ptr+1      ;  Store X in ptr+1
585         ...                ;  (more subroutine code goes here)
586         rts                ;  Return from subroutine
587 </verb></tscreen>
588
589 The hardware driver in this example writes a string of character data to
590 a hardware FIFO located at memory location $1000.  Each character is
591 read and is compared to the C string termination value ($00), which will
592 terminate the loop.  All other character data is written to the FIFO.
593 For convenience, a carriage return/line feed sequence is automatically
594 appended to the serial stream.  The driver defines a local pointer
595 variable which is stored in the zero page memory space in order to allow
596 for retrieval of each character in the string via the indirect indexed
597 addressing mode.
598
599 The assembly language routine is stored in a file names
600 &quot;rs232_tx.s&quot; and is shown below:
601
602 <tscreen><code>
603 ; ---------------------------------------------------------------------------
604 ; rs232_tx.s
605 ; ---------------------------------------------------------------------------
606 ;
607 ; Write a string to the transmit UART FIFO
608
609 .export         _rs232_tx
610 .exportzp       _rs232_data: near
611
612 .define         TX_FIFO $1000    ;  Transmit FIFO memory location
613
614 .zeropage
615
616 _rs232_data:    .res 2, $00      ;  Reserve a local zero page pointer
617
618 .segment  &quot;CODE&quot;
619
620 .proc _rs232_tx: near
621
622 ; ---------------------------------------------------------------------------
623 ; Store pointer to zero page memory and load first character
624
625         sta     _rs232_data      ;  Set zero page pointer to string address
626         stx     _rs232_data+1    ;    (pointer passed in via the A/X registers)
627         ldy     #00              ;  Initialize Y to 0
628         lda     (_rs232_data)    ;  Load first character
629
630 ; ---------------------------------------------------------------------------
631 ; Main loop:  read data and store to FIFO until \0 is encountered
632
633 loop:   sta     TX_FIFO          ;  Loop:  Store character in FIFO
634         iny                      ;         Increment Y index
635         lda     (_rs232_data),y  ;         Get next character
636         bne     loop             ;         If character == 0, exit loop
637
638 ; ---------------------------------------------------------------------------
639 ; Append CR/LF to output stream and return
640
641         lda     #$0D             ;  Store CR
642         sta     TX_FIFO
643         lda     #$0A             ;  Store LF
644         sta     TX_FIFO
645         rts                      ;  Return
646
647 .endproc
648 </code></tscreen>
649
650 <sect>Hello World! Example<p>
651
652 The following short example demonstrates programming in C using the cc65
653 toolset with a custom run-time environment.  In this example, a Xilinx
654 FPGA contains a UART which is connected to a 65c02 processor with FIFO
655 (<bf>F</bf>irst-<bf>I</bf>n, <bf>F</bf>irst-<bf>O</bf>ut) storage to
656 buffer the data.  The C program will wait for an interrupt generated by
657 the receive UART and then respond by transmitting the string &quot;Hello
658 World! &quot; every time a question mark character is received via a
659 call to the hardware driver <tt>rs232_tx&nbsp;()</tt>.  The driver
660 prototype uses the <tt>__fastcall__</tt> extension to indicate that the
661 driver does not use the stack.  The FIFO data interface is at address
662 $1000 and is defined as the symbolic constant <tt>FIFO_DATA</tt>.
663 Writing to <tt>FIFO_DATA</tt> transfers a byte of data into the transmit
664 FIFO for subsequent transmission over the serial interface.  Reading
665 from <tt>FIFO_DATA</tt> transfers a byte of previously received data out
666 of the receive FIFO.  The FIFO status data is at address $1001 and is
667 defined as the symbolic constant <tt>FIFO_STATUS</tt>.  For convenience,
668 the symbolic constants <tt>TX_FIFO_FULL</tt> (which isolates bit 0 of
669 the register) and <tt>RX_FIFO_EMPTY</tt> (which isolates bit 1 of the
670 register) have been defined to read the FIFO status.
671
672 The following C code is saved in the file &quot;main.c&quot;.  As this
673 example demonstrates, the run-time environment has been set up such that
674 all of the behind-the-scene work is transparent to the user.
675
676 <tscreen><code>
677 #define FIFO_DATA     (*(unsigned char *) 0x1000)
678 #define FIFO_STATUS   (*(unsigned char *) 0x1001)
679
680 #define TX_FIFO_FULL  (FIFO_STATUS &amp; 0x01)
681 #define RX_FIFO_EMPTY (FIFO_STATUS &amp; 0x02)
682
683 extern void wait ();
684 extern void __fastcall__ rs232_tx (char *str);
685
686 int main () {
687   while (1) {                                     //  Run forever
688     wait ();                                      //  Wait for an RX FIFO interrupt
689
690     while (RX_FIFO_EMPTY == 0) {                  //  While the RX FIFO is not empty
691       if (FIFO_DATA == '?') {                     //  Does the RX character = '?'
692         rs232_tx (&quot;Hello World!&quot;);                //  Transmit &quot;Hello World!&quot;
693       }                                           //  Discard any other RX characters
694     }
695   }
696
697   return (0);                                     //  We should never get here!
698 }
699 </code></tscreen>
700
701 <sect>Putting It All Together<p>
702
703 The following commands will create a ROM image named &quot;a.out&quot;
704 that can be used as the initialization data for the Xilinx Block RAM
705 used for code storage:
706
707 <tscreen><verb>
708 $ cc65 -t none -O --cpu 65sc02 main.c
709 $ ca65 --cpu 65sc02 main.s
710 $ ca65 --cpu 65sc02 rs232_tx.s
711 $ ca65 --cpu 65sc02 interrupt.s
712 $ ca65 --cpu 65sc02 vectors.s
713 $ ca65 --cpu 65sc02 wait.s
714 $ ld65 -C sbc.cfg -m main.map interrupt.o vectors.o wait.o rs232_tx.o
715           main.o sbc.lib
716 </verb></tscreen>
717
718 During the C-level code compilation phase (<tt>cc65</tt>), assumptions
719 about the target system are disabled via the <tt>-t none</tt> command
720 line option.  During the object module linker phase (<tt>ld65</tt>), the
721 target customization is enabled via inclusion of the <tt>sbc.lib</tt>
722 file and the selection of the configuration file via the <tt>-C
723 sbc.cfg</tt> command line option.
724
725 The 65C02 core used most closely matches the cc65 toolset processor
726 named 65SC02 (the 65C02 extensions without the bit manipulation
727 instructions), so all the commands specify the use of that processor via
728 the <tt>--cpu 65sc02</tt> option.
729
730 </article>