Embedded Pascal For The Rabbit
Embedded Pascal For The Rabbit
Prelimary documentation
This document should be used in conjunction with the standard Embedded Pascal
documentation related to the Z80/Z180 Embedded Pascal compiler.
Contents
General........................................................................................................................................... 3
Differences between Embedded Pascal and Dynamic C when developing applications................3
Thumper......................................................................................................................................... 3
Basic memory map (logical map).................................................................................................... 5
Rabbit specific link instructions (Pascal)......................................................................................... 6
Locating code and data................................................................................................................... 8
Thumping your first program – getting started with thumper...........................................................9
Typical Thumper session based on one of the included sample programs...................................10
Limitations of the banked constant and data section....................................................................13
Obtaining extended addresses..................................................................................................... 13
Input and output on the Rabbit...................................................................................................... 13
DAX – assembler extension.......................................................................................................... 14
DAP – assembler extension.......................................................................................................... 14
CALLR and JPR assembler macros............................................................................................. 14
PAGE assembler macro............................................................................................................... 14
Interrupts and Interrupt vector table location.................................................................................14
General
Embedded Pascal version 2.0 introduces support for the Rabbit processor. The Rabbit is loosely
based on a Z180, but with significant changes to architecture and instruction set rendering
ordinary Z80/Z180 compilers and assemblers quite useless.
.device Rabbit
exists in the device definition file selected for the application. This file is selected in the options
dialog.
Once Rabbit mode of operation is selected, the assembler and linker will not accept standard
Z80/Z180 mnemonics not available in the Rabbit and will add mnemonics available in this
processor.
In addition, the Pascal compiler will support code generation for the extended code segment as
well as banked data and typed constants via the stack segment.
Embedded Pascal can generate code that can be used via the Thumper interface and a Rabbit
development board or target system
Dynamic C and the Rabbit processor need to be connected via the serial port for development
purposes. Embedded Pascal is different in the sense that an external program is used to interface
to the Rabbit processor (aptly called “Thumper”). This allows application development on the
compiler/assembler independent of any development hardware.
Embedded Pascal outputs a ROM file format. This is a binary representation of what needs to go
into the final ROM device. Embedded Pascal can also produce a hex file output (Extended Hex
format), however this is not normally used for Rabbit development.
Thumper
Thumper consists of a PC based host and a small monitor program resisdent in the Rabbit
system. The monitor is loaded into the Rabbit system RAM on startup using the coldboot feature
via the serial port.
The monitor can duplicate or clone itself into Flash ROM.
The monitor supports basic interaction such as memory dump via the Thumper terminal but also
provides the interface for on-chip high level debugging.
High level debugging of Pascal source code is done by means of breakpoints that are compiled at
the beginning of each source line containing code. This is enabled in the Options menu. It is
recommended that once an application has been finalized that it is recompiled with the
breakpoints removed.
Thumper allows single stepping of code, breakpoints and variable watches.
Currently, no support for low level assembler debugging is provided (single step, breakpoints on
assembler level) but this is planned for a future release.
The Rabbit resident monitor can be executed from ROM or from RAM. Most applications can be
loaded either into RAM space or ROM space (Flash ROM) for debugging. The programmer may
need to be aware of ROM/RAM memory allocations to avoid problems.
Basic memory map (logical map)
Embedded Pascal makes no assumptions on how an applications memory is organized – this is
up to the programmer to decide.
When using Thumper however, certain assumptions are made. These would normally be very
similar to what most applications would require and should not pose a significant stumbling block.
The following illustrates the layout of the 64Kbyte logical memory space. This space is prepared
by the monitor program resident on the Rabbit. This program executes after reset.
The above map is valid for both operation out of RAM as well as ROM. The monitor uses MBXCR
registers to either map ROM to address zero and RAM to 80000H or RAM from zero and ROM
from 80000H.
A typical Embedded Pascal application starts at 1000H in the base segment. The first two bytes
should contain 55AAH. This signals the monitor that an application is present and should be
started after a reset. Entry to the application is at address 1002H. This would normally be a jump
to the start of the main routine. This routine may reside in the base segment or in the extended
segment.
The base segment would contain the library code, interrupt vector table, interrupt routines,
routines that are time critical or used very often. You have 20K available for this – usually more
than enough.
The data segment starts at 6000H and using the MMU registers would normally point to the first
available physical RAM. You have 24K of this RAM available. You should allocate often used
variables into this space, also anything that needs to be accessed from interrupt routines. The top
of this area is normally used for the stack. More than one stack could be used for a multitasking
system.
The Stack segment starts at C000H and is 8K in size. Contrary to its name, no stack is located
here. Instead, Embedded Pascal uses this area as a sliding window over the entire 1Mbyte
physical memory area. This is used to access data in extended RAM as well as typed constants
and constant strings which may reside in extended ROM. Embedded Pascal uses this instead of
the few available instructions that can directly access extended memory. The main reason is the
lack of an available instruction that can write a byte sized entity in extended memory. Also, this
scheme has merit with other processors such as the Z180 which could use this scheme as well.
Embedded Pascal uses a caching scheme for page switches of this area to avoid unnecessary
bank switches as far as safely possible. This results in a good performance when accessing
items in this memory segment.
Page switch caching is resolved at the linking stage.
Link $1006,$6100
Trim $1000
ExtendedLoad $D000
PagedConstLoad $18000
PagedDataLoad $10000
uses RabbitLib;
var
……….. Normal Pascal code follows here
This tells the linker that code must be linked from $1006 with data (base segment data) starting at
$6100. Why these numbers ?
$1006 leaves space for the 55AAH flag at $1000, then we have another four bytes to insert a far
jump (or LJP) instruction as we want to place all of our code, including the main routine into
Extended program space. If the main routine is in the base segment we can make do with a long
jump (or JP) instruction and we could save a byte and use $1005.
The jump is inserted by the vector keyword in the program heading.
Trim $1000
This instruction tells the final code generator to remove the first 1000H bytes from the produced
ROM file. The first byte of the ROM output file will be loaded to addess 1000H by the monitor.
ExtendedLoad $D000
This line informs the assembler and linker that we would like to place extended code into the
ROM output file starting at address $D000. As we are trimming the first $1000 bytes you would
find the Extended code starting at $C000 in the ROM file.
Note that this does not set the actual execution address of the extended code but only sets the
location of where to store the code. Extended code executes by default in the $E000 to $FFFF
extended memory area.
You would choose any suitable address in your ROM, usually after your reset code (or monitor if
your final code will be retaining it). So, in a practical case you could choose $1000.
Please note that the Embedded Pascal samples all choose $D000. This allows the code to
execute in RAM as we will be using the first portion of RAM for the monitor, base code and base
data.
PagedConstLoad $18000
This instruction sets the ROM file location that is to contain typed constants and constant strings.
You can choose on an individual bases which typed constants should be accessible in base code
or paged constant area. See below on how to do this.
The address given must fall into your ROM area and must not conflict with any code areas.
PagedDataLoad $10000
Similar to the typed constants, you may place any or all variables, static parameters and static
local variables into extended data space. The address specified must point to valid RAM (physical
address) and must not conflict with base data that is mapped to physical RAM via the MMU.
This is a typical Pascal program heading. Vector is an Embedded Pascal specific extension that
instructs the compiler to place a jump instruction to the main routine at a specific address ($1002
in this case). You can use FarJmp or LongJmp depending on where you will place your main
routine. LongJmp takes three bytes and the target must be within the 64K logical address range.
FarJmp takes four bytes and the target must be in extended code space.
$1002 is the entry address. The monitor program will execute a jump to this address to start the
application.
{#X Root}
{#X Extended}
Root causes all following procedures and functions to be placed in the base segment (Code
segment in assembler). This is the default segment.
Extended places all following procedures and functions into the extended code segment and
causes the compiler to generate code compatible with the extended segment requirements.
You can place these switches anywhere but they will only take effect with the next procedure or
function heading (or the main routine).
{#X ROOT_DATA}
{#X BANK_DATA}
These switches provide a means of locating variables, static parameters and static variables into
the base segment (DATA in assembler) or into paged RAM (using the Stack segment).
Here is an example:
Var
{#X ROOT_DATA}
a,b,c: word; //This goes into the base segment
{#X BANK_DATA}
x,y,z: word; //This goes into the banked (paged) data segment
Default is ROOT_DATA. The switch is effective immediately for the following definition and can
be placed anywhere, even inside procedure or function parameter declarations.
{#X ROOT_CONST}
{#X BANK_CONST}
These switches determine where typed constants should be stored. The switches take effect
immediately for the next definition.
Example:
Const
{#X ROOT_CONST}
TC: word = 100; //This is stored in the Code segment (Base segment)
{#X BANK_CONST}
TX: word = 200; //This is stored in the banked constant segment (Stack segment)
Thumper consists of several parts, designed to interface via the Rabbit serial port A
(cold loader port and PC serial port).
Locate the RabbitMon.asm file in the Thumper folder. This program will execute after a
coldboot has completed. Note settings in the file which may be relevant for your target
hardware, especialy type of Flash memory. Set the equates accordingly and assemble/link the
project file RabbitMon.prj.
The RabbitCold.prj is included for reference - you will not normally change anything here.
This is the secondary that loads RabbitMon via the Thumper.exe program.
Connect your target hardware. Start Thumper.exe and locate the small "terminal" button
on the lower right toolbar. Click this button to open a terminal window that you can
use to interact with the Rabbit resident Thumper program RabbitMon.
At this stage the Rabbit will have received a hardware reset and will be waiting for
the first cold boot sequence. Press the "ColdBoot" button. A few seconds will be required
to download the primary bootloader which loads RabbitCold.ROM and then executes it.
RabbitCold then gets RabbitMon from the Port A serial port at 19200 baud.
You may see the message "updating flash". Thumper, currently running in RAM
has made a copy of itself at the bottom of ROM.
After RabbitMon has been loaded you should see the signon prompt. You can now
interact with the Rabbit resident Thumper program. Here are some commands you can
use at the prompt:
* D1000
* @6000
Enters memory edit mode at address 6000 hex. After entering a value advances to
the next address. Use "." to exit.
* I10
Input from internal port at address 10. Will then advance to the next address.
Continue reading ports with <return>. <.> will exit.
* O10,55
* L0
Request current application ROM code from Thumper on the PC. Will load to Flash from
address 1000H (physical ROM address).
* L1
Request current application ROM code from Thumper on the PC. Will load to RAM from
address 1000H (physical RAM address).
*R
*X
This will start Thumper in debug mode. Once in debug mode, the HLL window can be activated
on the PC Thumper. You should press "Step" to start the loaded application (make sure you
have a valid application startiong at address 1000H).
The application will break at the first breakpoint (usualy the beginning of the main
routine). Now you can single step or run your application at will.
You can set up to five breakpoints (Turn the blue breakline indicators red by clicking on
the location of your desired breakpoint). Breakpoints are only active if you RUN the
application, they are not active during single step or "step over" or "step out".
Please note that Thumper uses port A to communicate during the debugging sessions. If your
application uses port A for other communication issues, this may interfere with the
debugging session.
uses RabbitLib; <-use the Rabbit runtime library. You cannot use the IntLib library.
{#P ABS $1000} <-This smart little construct inserts a 55AAH code at location
{#P DW 055AAH} 1000H. This is used by Thumper to find out if an application
{#P CODE} is available.
4) Compile the code (The left little gear button will do nicely).
6) Great - you have just created your first Rabbit code. Your executable file should
be located in the Rabbit folder. It has a "ROM" extension. You should also find
a symbol file for your project. It has a "SYM" extension.
7) Start Thumper.
8) Select your application on the main form. Use the "Browse" button to find the file
"Hello World.ROM".
9) Click on the "Load application to RAM" button. This coldboots your Rabbit, makes sure
that RabbitMon is loaded and then starts RabbitMon. Then it issues a "L1" command
(see above). You should see a few X's appearing on the terminal. Each X is one
sector sized block of code that was uploaded to the Rabbit. You define a sector size
when you compile RabbitMon (one of the equates in the source). One sector size would
be equal to one sector size of your Flash device, even if downloading to RAM.
10) Got the "*" prompt ? Good. You have the "Hello Word" application loaded from
$1000 onwards in RAM (currently you have RAM from $0000 to $BFFF at least), Thumper
is operating out of RAM.
11) Good. Now lets get fancy. We could at this point just enter the "X" command to start
debugging the application but let us have Thumper do it for us:
13) Run the HLL debugger (it should have been opened for you).
You should see a copy of your source file and after you pressed "F7" or clicked on
the "step" button you should see a highlight at the first line of the application
source code (first line of the main routine).
14) Press "step" again and we are now tracing into the writeln procedure.
A final note on Thumper - This program is still "work in progress". It can still fall
over, usually based on communications problems or sequencing problems. Thumper may
hang if it is waiting for some data from the Rabbit and it never gets it.
Have your CTRL-ALT-DELETE handy !
These issues will be dealt with soon, also some additions are still required.
For example a means of tracing through assembler code.
Limitations of the banked constant and data section
Generally, few limitations exist with respect to banked data or constants, however one particular
case must remain in the programmers mind.
Should you wish to move data blocks between two banked areas not residing in the same bank,
you must perform the move in two steps using base memory as intermediate.
This applies typically for record or array assignments which make use of the LDIR opcode. The
LDIR opcode is unable to switch source and destination banks.
This limitation does not apply for string assignments as strings are always moved via the stack. It
is thus quite safe to assign a banked constant string to a banked data string.
A further limitation relates to the size of a banked code or data item. Banked records and arrays
are limited to a maximum size of 4Kbytes.
Should you wish to bank larger structures, split them into smaller chunks, each a maximum of 4K.
Var
A: byte;
Begin
A:= INP(PortAddress); //External I/O, port input
A:= IINP(PortAddress); //Internal I/O, port input
OUT(PortAddress,value); //External I/O, port output
IOUT(PortAddress,value); //Internal I/O, port output
End;
DAX – assembler extension
The Embedded Pascal assembler has a new keyword: DAX. This works similar to DB, DW, etc
but results in a three byte (24 bit) entry containing the logical address for a code label in the
extended segment (16 bits, E000 to FFFF) followed by the required value for the XPC register to
make the code visible in the extended segment.