
1.1 Overview
The XA Single Board Computer from HI-TECH Software is designed to allow a potential user of the XA microcontroller to evaluate the chip, or implement a first prototype without the time and expense of producing a custom PCB. Included on the board are:
- XA-G30 microcontroller operating at 30MHz
- 128K bytes of low-power static RAM
- 32-128K bytes of EPROM (in standard 28 or 32 pin DIP socket)
- Dual serial ports with RS232 drivers on DB9 connectors
- 8 LEDs for debugging purposes
- Two external interrupt inputs and two timer inputs
- 8 bits each of parallel input and output
- Data bus with address decoding for I/O expansion.
- Remote debugger in EPROM with matching PC software for easy downloading and debugging.
- Socket for the Maxim MAX186 8-channel 12-bit A/D converter
- Requires unregulated 7-9V DC supply (plug-pack or similar)
- Breadboard area for prototyping
1.2 Physical characteristics
The XA Single Board Computer is approximately 4 inches (10cm) square. On one side are two DB9 connectors for serial interfacing. Each connector is a female DB9 wired as a DCE, and thus requiring only a straight cable to plug into a standard PC 9 pin serial connector (supplied). Adjacent to the serial connectors is a coaxial DC connector, with a 2.1mm centre pin. This is wired to a bridge rectifier, so the DC power supply polarity does not have to be specific.
Behind the serial connectors are 8 LEDs, for debugging purposes. The lower third of the board is a prototyping area with an unconnected hole matrix, and ground and power holes. Provided on the board are two 20 way connector pads for connecting parallel input and output, and access to the data bus. The XA EX0 and EX1 pins (labelled as INT0 and INT1 respectively on the board), and T0 and T1 are accessible via pads at the top of the prototyping area.
1.3 Power requirements
The board requires 7 to 9V DC, supplied to the coaxial DC connector. Included is a single phase diode bridge to allow either polarity from the power supply. Current drain is approximately 300mA. A 7805 regulator is provided on board, next to the power connector. This is not provided with a heatsink and should not require one unless the input voltage is higher than 9V or the current drain is significantly increased by additional components. If you do fit a heatsink, it must be insulated from the board, as there are tracks on top of the board underneath the regulator. A fibre washer between the heatsink and board will suffice.
1.4 Setting up
To set the board up, it may be useful to mount it on insulating standoffs with the four holes at the corners of the board. Plug the supplied EPROM into the ROM socket. Note that the socket is a 32 pin socket, but the supplied EPROM has 28 pins (27256). It should be plugged into the socket bottom-aligned, i.e. there should be four spare pins adjacent to the LEDs.
Plug the supplied straight cable (i.e. not a null-modem cable) with a DB9 male connector into the DB9 connector J2 (on the opposite side of the board from the power connector). The other end of this cable should plug into COM1 or COM2 of your PC.
Connect a plug-pack or other DC power supply, providing 7-9V at 300mA, into the DC power connector.
Turn the plug-pack on. The LEDs will sweep up and down once, and then leave at least one LED illuminated. If you do not see this, check the power supply.
Once the board is connected to the serial port of your PC, you can then download and debug programs with the software provide. The software agent is called Lucifer. It is a remote source-level debugger, the usage for this software is outlined in the manual.
1.6 Compiling your own programs
To compile your own programs, use HPDXA as supplied with the HI-TECH C compiler for the XA. You must select large model from the Options/Memory model and chip type dialog, and you should set the following memory addresses:
ROM address 88000 RAM address 20 RAM size 7F00 NVRAM address 0 Far RAM address 0 Far NVRAM address 0 This will allow you to access nearly 32K bytes of data memory (Lucifer uses 7F00-7FFF) and 96K bytes of code memory. Note that the data memory at 0 is also mapped as code memory at 80000h, which is why the ROM address should be set at 88000h, to avoid conflict with RAM used as data memory.
1.7 On-board I/O
Most of the XA I/O pins are used for address and data lines on the board. The remaining I/O pins are either connected to the serial ports, or brought out to labelled pads at the top right of the breadboard area. These pins allow access to the external interrupts and timer inputs.
Additional I/O is provided with 74HC373 latches, and a 74HC244 input buffer. The LEDs are driven by a latch at address E0000h (note that two of the LED bits are shared with the ADC). Writing to address E8000h will latch data into another 74HC373, while reading the same address will gate data in through a 74HC244. These input and output lines are available on J1 along with power and ground. There is no handshaking on these ports.
For further I/O expansion, J5 provides access to the data bus, 5 address lines, a select signal and read and write strobes. You can use these to address up to 32 bytes of data at address F0000h.
Lucifer is a source level remote debugger for use with the HI-TECH C compilers. It
consists of a program which runs on a host machine (usually MS-DOS or UNIX) and
communicates with an XA- based microcontroller system via a serial line. The host program
provides the user interface, including source code display, disassembly, displaying memory
etc. The target system must have logic to read and write memory and registers, and
implement single stepping. With each version of Lucifer a small program is provided which
can be compiled and placed in a ROM in a target system to implement these features. The
standard host program is set up to communicate with this ROM program via a serial line.
2.1 Using Lucifer
To use Lucifer you will need to have the compiler generate a symbol file, with symbol
name, line number and file name symbols included. This can be produced using the XAC -G
option. If you use the -H option you will get a symbol file which can be used by Lucifer,
but which does not contain any source code level information.
You can also use HPDXA to produce HEX and symbol files suitable for use with Lucifer. The
LUCIFER directory contains luctest.prj, a sample project file which you can use as a guide
to compiling your own programs with HPDXA. See the Using HPDXA chapter for more details.
The basic option needed is Options/Source level debug info. Lucifer can be invoked from
the Run/Download ... menu item. Otherwise once you have produced HEX and symbol files,
invoke Lucifer as follows:
lucxa -sSPEED -pCOMn test
If you are using an MS-DOS system, COMn should be COM1 or COM2. Lucifer will access a
standard serial port addressed as either port. For UNIX simply specify the name of the
serial port connected to your target, for example -p/dev/tty006 .
The default baud rate is 38400 for both MS-DOS and UNIX. The default serial port is COM1
for MS-DOS and /dev/ttya for UNIX. The -s (speed) and -p (port) options may be used to
access ports other than the default. For UNIX /dev may be left off the device name and
will automatically added, thus -ptty0 and -p/dev/tty0 will access the same device. For
example, under MS-DOS, lucxa -s9600 -pcom2 will access COM2 at 9600 baud.
New default speed and port values may be set using the environment variable LUCXA_ARGS .
LUCXA_ARGS may specify any mixture of valid Lucifer ` - ' options except filename options.
For example, if you want the default options to be 4800 baud on port COM2, add the
following line to your AUTOEXEC.BAT file:
SET LUCXA_ARGS=-s4800 -pCOM2
In addition to the speed and port options Lucifer takes two optional arguments which are,
in order of appearance, the name of the symbol file to use and the name of the .hex or
.bin file to download. If no download file is specified, Lucifer will automatically search
for .sym , .hex and .bin files which the same base name as the symbol name given. Thus the
command:
lucxa test
would automatically locate and use test.sym and test.hex or test.bin . If you do not want
to autoload your HEX or BIN file, give your symbol file a different base name to your HEX
file.
When downloading binary files, Lucifer normally prompts for the download address. When
downloading directly from the command line you can override this prompting by adding the
option -Baddr[:end] to the LUCXA command line. For example, if you want to download a file
test.bin at address $2000, you could use the command:
lucxa -b2000 test
The optional :end value is the address at which the download should be terminated. For
example, if you want to load the first $2000 bytes of test.bin from address $4000 to
address $6000, use the command:
lucxa -b4000:6000 test
Lucifer should announce itself, then attempt to communicate with the target. If successful
it prints a message sent by the target, identifying itself, e.g:
XA Lucifer Monitor (+ diagnostics) V4.3
Lucifer will then display a prompt : and wait for commands. For a list of commands, type ?
and press return. Note that all commands should be in lower case.
2.2 Symbol Names In Expressions
Where Lucifer commands take numeric values or addresses as arguments; symbol names,
register names and line numbers may be used. Symbols should be entered in exactly the same
case as they were defined in the source code. Note that Lucifer cannot access auto
variables or parameters by name. Where an expression is required, it may be of the forms
in See Lucifer expression forms.
Lucifer expression forms Expression form
Example
symbol_name
main
symbol+hexnum
barray+20
$hexnum
$2000
:linenumber
:10
regname
A5
By default, in the b (breakpoint) command any decimal number will be interpreted, as a
line number. However, in the u (unassemble) command any number will be interpreted, by
default, as a hex number representing an address. These assumptions can always be
overridden by using the colon or dollar prefixes. When entering a symbol, it is not
necessary to type the underscore prepended by the C compiler. However, when printing out
symbols the debugger will always print the underscore. Any register name may also be used
where a symbol is expected.
2.2.1 Auto Variables and Parameters
Auto variables and parameters cannot be accessed by name with Lucifer. To examine the
contents of an auto variable or parameter, the best approach is to disassemble (with the u
command) a line of code referencing the variable, and dump the corresponding memory
location (e.g. sp+4 ).
2.3 Lucifer Command Set
Lucifer recognizes the commands listed in See Lucifer Command Set .
Lucifer Command Set Command
Meaning
B [line|addr]
Set or display breakpoints
C
Display instruction at PC
D [addr [addr]]
Display memory contents
E fn|file
Examine C source code
G [addr]
Commence execution
I
Toggle instruction trace mode
L file
Load a HEX file
M addr val1 [val2 ...]
Modify memory
Q
Exit to operating system
R [breakpnt]
Remove breakpoints
S
Step one line
T
Trace one instruction
U [addr]
Disassemble machine instructions
W file addr length
Upload binary
X [reg1 val1 [reg2 val2 ...]]
Examine or change registers
@ type [indirection]expr
Display C variables
. [breakpoint]
Set a breakpoint and go
; [line]
Display from a source line
=
Display next page of source
-
Display previous page of source
/ [string]
Search source file for a string
! command
Execute a DOS command
2.3.1 The B command: set or display breakpoints
The b command is used to set and display breakpoints. If no expression is supplied after
the b command, a list of all currently set breakpoints will be displayed. If an expression
is supplied, a breakpoint will be set at the line or address specified. If you attempt to
set a breakpoint which already exists, or enter an expression which Lucifer cannot
understand, an appropriate error message will be displayed. Note: by default, any decimal
number specified will be interpreted as a line number. If you want to specify an absolute
address, prefix it with a dollar sign. For example:
: b 10
Set breakpoint at _main+$28
:
Breakpoints can also include a semicolon separated list of Lucifer commands, which will be
executed when the breakpoint is encountered. This makes it possible to create breakpoints
which stop, display a value and then restart execution. For example, the command:
: b 10 @f pi;g
creates a breakpoint which stops, displays the value of global variable pi and then
continues execution.
2.3.2 The C command: display instruction at PC
The c command is used to display the assembler instruction and C source line addressed by
the current value of the program counter. This is useful if you have been using other
Lucifer commands and aren't quite sure where in the program the program counter is
pointing. For example:
: c
10: printf("answer = %d\n",j);
_main+$22 MOV r0,_j
2.3.3 The D command: display memory contents
The d command is used to display a hex dump of the contents of memory on the target
system. If no expressions are specified, 16 bytes are dumped from the address reached by
the last d command. If one address is specified, 16 bytes are dumped from the address
given. If two addresses are specified, the contents of memory from the first address to
the second address are displayed. Dump addresses given can be symbols, line numbers,
register names or absolute memory addresses.
2.3.4 The E command: examine C source code
The e command is used to examine the C source code of a function or file. If a function
name is given, Lucifer will locate the source file containing the function requested and
display from just above the start of the function. If a file name is given, Lucifer will
display from line 1 of the requested file. For example:
: e main
2:
3:int value, result;
4:
5:main()
6:{
7: scanf("%d",&value);
8: result = (value << 1) + 6;
9: printf("result = %d\n",result);
10:}
:
2.3.5 The G command: commence execution
The g command is used to commence execution of code on the target system. If no expression
is supplied after the g command, execution will commence from the current value of PC (the
program counter). If an expression is supplied, execution will commence from the address
given. Execution will continue until a breakpoint is reached, or the user interrupts with
control -C . After a breakpoint has been reached, execution can be continued from the same
place using the g , s and t commands.
2.3.6 The I command: toggle instruction trace mode
The i command is used to toggle instruction trace mode. If instruction trace mode is
enabled, each instruction is displayed before it is executed while stepping by entire C
lines with the s command. For example, with instruction trace disabled, step behaves like
this:
: s
result = 20
Stepped to
10:}
:
With instruction trace enabled, step will instead behave like this:
: s
_memtest+30H push r4
_memtest+32H mov r0,#04A2H
_memtest+36H push r0
_memtest+38H fcall _printf
_memtest+3CH adds r7,#4
result = 20
Stepped to
10:}
:
Note that the library function printf() was not traced and thus operated properly and at
full speed.
2.3.7 The L command: load a hex file
The l command is used to load object files into the target system. Lucifer correctly
handles Motorola S-record format object files, Intel HEX files and binary images.
2.3.8 The M command: modify memory
The m command is used to write one or more values or ascii strings into memory at a
specified address. This command takes the form:
m addr val1 [val2 ...]
where addr is the address to write to and all following arguments are values or strings to
write to memory. Strings may use either single or double quotes. For example:
: m buf "hello" 13 10 'world' 0
2.3.9 The Q command: exit to operating system
The q command is used to exit from Lucifer to the operating system. Note: the q command
does not stop the target system (that is, the Lucifer monitor running on the target
system), so it is possible to re-enter Lucifer without re-initializing the target.
2.3.10 The R command: remove breakpoints
The r command is used to remove breakpoints which have been set with the b command. If no
arguments are given the user is prompted for each breakpoint in turn. For example:
: r
Remove _main+$28 ? y
Remove _main+$44 ? n
Remove _test ? n
: r main+$44
Removed breakpoint _main+$44
:
2.3.11 The S command: step one line
The s command is used to step by one line of C or assembler code. For example:
: s
Stepped to
7: scanf("%d", &value);
: s
Target wants input: 7
Stepped to
8: result = (value << 1) + 6;
: s
Stepped to
9: printf("result = %d\n",result);
: s
result = 20
Stepped to
10:}
:
This is normally implemented by executing several machine instruction single steps, and
therefore can be quite slow. If Lucifer can determine that there are no function calls or
control structures (break, continue, etc.) in the line, it will set a temporary breakpoint
on the next line and execute the line at full speed. When single stepping by machine
instructions, the step command will execute subroutine calls to external and library
functions at full speed. This avoids the slow process of single stepping through complex
library routines like printf(). Normal library console I/O works correctly during single
stepping using the s command. Where no line number information is available, such as
inside library routines, the s command becomes an assembler step like the t command.
2.3.12 The T command: trace one instruction
The t command is used to trace one machine instruction on the target. The current value of
PC (the program counter) is used as the address of the instruction to be executed. After
the instruction has been executed, the next instruction and the contents of all registers
will be displayed.
2.3.13 The U command: disassemble machine instructions
The u command disassembles object code from the target system's memory. For example:
: u
9: printf("result = %d\n", result);
_memtest+30H push r4,r5
_memtest+32H mov r0,#04A2H
_memtest+36H push r0
_memtest+38H fcall _printf
_memtest+3CH adds r7,#6
If an expression is supplied, the disassembly commences from the address supplied. If an
address is not supplied, the disassembly commences from the instruction where the last
disassembly ended. The disassembler automatically converts addresses in the object code to
symbols if the symbol table for the program being disassembled is available. If the source
code for a C program being disassembled is available, the C lines corresponding to each
group of instructions are also displayed. Note: by default, any values specified will be
interpreted as absolute addresses. If you want to specify a line number, prefix it with a
colon.
2.3.14 The W command: upload binary
The w command is used to upload and write a chunk of target memory as a binary file. This
command takes three arguments: filename, start address and length. The start address and
length values are in hex. For example, if the Lucifer monitor ROM were at $7000 to $7FFF
in the target system, it could be uploaded to a binary file with the command:
: w lucrom.bin 7000 1000
........
Uploaded 4096 (0x1000) bytes to lucrom.bin
:
2.3.15 The X command: examine or change registers
The x command is used to examine and change the contents of the target CPU registers. If
no parameters are given, the registers are displayed without change. To change the
contents of a register, two parameters must be supplied, a valid register name and the new
value of the register. After setting a new register value, the contents of the registers
are displayed. For example:
: x r1 1234 r0 3f
Any valid XA register name may be used. The PSW may be accessed as PSW for the entire 16
bit value, or as PSWL and PSWH for the low and high bytes respectively.
2.3.16 The @ command: display C variables
The @ command is used to examine the contents of memory interpreted as one of the standard
C types. The form of the @ command is:
@t/[*]expr
where t is the type of the variable to be displayed, * consists of zero or more
indirection operators (" * " or " n* "), and expr is the address of
the variable to be displayed. See Lucifer @ command variants , shows the available @
command variants.
For example, to display a long variable longvar in hex:
@lx longvar
To display a character, pointed to by a pointer cptr :
@c *cptr
To de-reference ihandle : a pointer to a pointer to an unsigned int:
@iu **ihandle
After displaying the variable, the current address is advanced by the size of the type
displayed. This, makes it possible to step through arrays by repeatedly pressing return.
On-line help for the @ command may be obtained by entering ?@ at the " : "
prompt.
Lucifer @ command variants Command
Type
Displays
@c
char
character and value
@cu
unsigned char
decimal
@cx
unsigned char
hexadecimal
@co
unsigned char
octal
@i
int
decimal
@iu
unsigned int
decimal
@ix
unsigned int
hexadecimal
@io
unsigned int
octal
@l
long
decimal
@lu
unsigned long
decimal
@lx
unsigned long
hexadecimal
@lo
unsigned long
octal
@f
float
decimal
@np
near pointer
symbol+offset
@p
pointer
symbol+offset
@s
string
string chars
2.3.17 The . command: set a breakpoint and go
The . command is used to set a temporary breakpoint and resume execution from the current
value of PC (the program counter). Execution continues until any breakpoint is reached or
the user interrupts with control -C , then the temporary breakpoint is removed. Note: the
temporary breakpoint is removed even if execution stops at a different breakpoint or is
interrupted. If no breakpoint address is specified, the . command will display a list of
active breakpoints.
: . 10
Target wants input: 7
result = 20
Breakpoint
10:}
main+$28 RET
:
2.3.18 The ; command: display from a source line
The ; command is used to display 10 lines of source code from a specified position in a
source file. If the line number is omitted, the last page of source code displayed will be
re-displayed. For example:
: ; 4
4:
5: main()
6: {
7: scanf("%d",&value);
8: result = (value << 1) + 6;
9: printf("result = %d\n",result);
10:}
2.3.19 The = command: display next page of source
The = command is used to display the next 10 lines of source code from the current file.
For example, if the last source line displayed was line 7, = will display 10 lines
starting from line 8.
2.3.20 The - command: display previous page of source
The - command is used to display the previous 10 lines of source code from the current
file. For example, if the last page displayed started at line 15, - will display 10 lines
starting from line 5.
2.3.21 The / command: search source file for a string
The / command is used to search the current source file for occurrences of a sequence of
characters. Any text typed after the / is used to search the source file. The first source
line containing the string specified is displayed. If no text is typed after the / , the
previous search string will be used. Each string search starts from the point where the
previous one finished, allowing the user to step through a source file finding all
occurrences of a string.
: /printf
10: printf("Enter a number:");
: /
14: printf("Result = %d\n",answer);
: /
Can't find printf
:
2.3.22 The ! command: execute a DOS command
The ! command is used to execute an operating system shell command line without exiting
from Lucifer. Any text typed after the ! is passed through to the shell without
modification.
2.3.23 Other commands
In addition to the commands listed above, Lucifer will interpret any valid decimal number
typed as a source line number and attempt to display the C source code for that line.
Pressing return without entering a command will result in re-execution of the previous
command. In most cases the command resumes where the previous one left off. For example,
if the previous command was d 2000 , pressing return will have the same effect as the
command d 2010 .
If return is pressed after a breakpoint or . command has executed, it is equivalent to
disassembling from the breakpoint address.
2.4 User Input and Output with Lucifer
The standard versions of the console I/O routines putch(), getch(), getche() and
init_uart() are configured to work automatically with LUCIFER. Code which is downloaded
under LUCIFER may use the standard I/O routines like printf() without any library
modifications. Once you have finished debugging your code, you will need to insert into
the library console, I/O routines suitable for your hardware. You can use the file
sources/getch.c as a starting point.
2.5 Installing Lucifer on a Target
In order to use Lucifer on your target system, you will need to compile the Lucifer
monitor and place it in a ROM. If your XA system already has a monitor in ROM, it is also
possible to download the Lucifer target code into RAM. In most cases you will be able to
use the Lucifer monitor program supplied without much modification.
Normally the only changes required will be the baud rate initialization in init_uart().
This requires modification for different baud rates or different clock frequencies. There
are self-explanatory comments, in the code, at that point.
If you do not wish to use one of the XA internal serial ports you will need to modify the
target code to access a different serial port.
2.5.1 Modifying the Target Code
Most modifications to target.c will be made to the serial I/O functions, putch(), getch()
and init_uart(). For Lucifer to work correctly, you will need to have a system with common
code and external RAM space as it is not possible to write to code memory on the XA. This
can be achieved by mapping 32K of ROM from 0000h to 7FFFh and 32K of static RAM from 8000h
to FFFFh and using PSEN and RD NOR'ed together for chip select.
2.5.2 Memory Mapping
Since the XA has separate, overlapping address spaces for code and data, special memory
mapping is required to allow code to be downloaded and executed. It is important to map
RAM into the first 64K of the data space, since the stack pointer in system mode is only
16 bits. Therefore a suggested arrangement is as follows. A ROM (size not important) is
mapped into code space at 0. This will hold the Lucifer target program. A RAM of adequate
size (say 128K bytes for example purposes) is mapped into data space at two locations; at
0, and at a higher address, say 80000h. It is also mapped into code space at the higher
address, i.e. at 80000h it appears as both code and data.
This now allows Lucifer to download code into the ROM at the high address, and execute it
from there. A portion of the RAM is reserved for data. The target code as supplied
reserves 32K bytes of RAM for data, so user programs are downloaded at 88000h. The monitor
program uses RAM from 7F00h to 7FFFh, so RAM from 20h (above the registers) to 7EFFh is
available for the user program. With this arrangement, you would compile the Lucifer
target program with the following addresses:
ROM address 0
RAM address 7F00
RAM size 100
and when compiling your application program you will compile with these addresses:
ROM address 88000
RAM address 20
RAM size 7EE0
2.5.3 Interrupts
Target.c reflects all unused interrupt vectors to the start of the user program area
(88000 in the example above). This address is selected by the macro RAMBASE in target.c .
All interrupts will be reflected to RAMBASE +vector, for example interrupt vector 84h will
be reflected to 88084h. This means you do not have to change your program whether it is
compiled to run under Lucifer or stand-alone in ROM, since the vector addresses are
interpreted as being relative to the ROM start address.
Back to Hitech Main Page | Back to Testech Home Page | Compiler | RTOS | Emulator/Debugging