0% found this document useful (0 votes)
66 views15 pages

Embedded Pascal For The Rabbit

This document provides an overview of using Embedded Pascal to develop applications for the Rabbit microprocessor. It describes the Thumper tool which is used for debugging Pascal code on the Rabbit via a host PC. The memory map layout reserves areas for application code and data, with the base segment at address 1000H and data segment at 6000H by default. Interrupts can target the vector table in the base segment. Extended memory is accessed via a sliding window in the stack segment.

Uploaded by

Carol Borges
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
66 views15 pages

Embedded Pascal For The Rabbit

This document provides an overview of using Embedded Pascal to develop applications for the Rabbit microprocessor. It describes the Thumper tool which is used for debugging Pascal code on the Rabbit via a host PC. The memory map layout reserves areas for application code and data, with the base segment at address 1000H and data segment at 6000H by default. Interrupts can target the vector table in the base segment. Extended memory is accessed via a sliding window in the stack segment.

Uploaded by

Carol Borges
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
You are on page 1/ 15

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.

Embedded Pascal adds Rabbit support if the line:

.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

Differences between Embedded Pascal and Dynamic C


when developing applications
Embedded Pascal is a stand-alone compiler featuring full modularity of applications on both the
Pascal as well as assembler level. When compared with C, Embedded Pascal has few files that
need inclusion in the final code, typically you would only use a single uses clause in your source
code specifying the use of the IntLib (Z80,Z180) or RabbitLib (Rabbit processor) library.
The only additional libraries are FPSLib and FPHLib that are used if floating point is required.
Embedded Pascal can be used in a manner similar to C with regards to header files but this has
been largely superceded using the unit system somewhat similar to Borland Pascal. The two
approaches may be mixed if required.

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.

; Default memory map for Embedded Pascal


; applications
;
; ----------------- FFFFH
; ! !
; ! Extended ! Used for Embedded Pascal code compiled in
; ! Segment ! the Extended segment
; ! !
; ----------------- E000H
; ! ! NOT used for the stack !
; ! Stack ! Used as general purpose sliding window on
; ! segment ! physical memory for both code and data access
; ! !
; ----------------- C000H
; ! ! This is mapped to the first 6000H of pysical RAM
; ! Data ! This area contains the stack (at the top) and
; ! Segment ! up to 24K of directly accessible data area
; ! ! Bottom of area is used for debugger (100H bytes)
; ----------------- 6000H
; ! ! Directly executable Embedded Pascal application code
; ! Base ! compiled in the CODE segment goes here. Loaded from
; ! Segment ! address 1002H. 1000H,1001H contains 55AAH as signal
; ! (application) ! to the debugger to start the application on reset.
; ! !
; ----------------- 1000H
; ! ! Code in this source file goes here. Maximum of 4K.
; ! Base !
; ! Segment !
; !(Bios/Debugger)!
; ! !
; ----------------- 0000H

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.

Rabbit specific link instructions (Pascal)


Every Embedded Pascal application starts with a few instructions intended for the assembler and
linker. These instructions tell the linker where you want to place various code and data items.
Here is a typical source file start for a somewhat extreme example, all code and data to be in
extended or banked segments:

Link $1006,$6100
Trim $1000
ExtendedLoad $D000
PagedConstLoad $18000
PagedDataLoad $10000

program Sample; Vector Farjmp $1002;

{#P ABS $1000}


{#P DW 55AAH}
{#P CODE}

uses RabbitLib;

{#X Extended} //All Pascal code into the extended segment


{#X BANK_DATA} //All data into paged RAM
{#X BANK_CONST} //All typed constants into paged ROM

var
……….. Normal Pascal code follows here

Let us have a look at each line:


Link $1006,$6100

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.

program Sample; Vector FarJmp $1002;

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.

{#P ABS $1000}


{#P DW 55AAH}
{#P CODE}
The above construct will place the 55AAH flag at location $1000. This is used to inform the
monitor that a valid application exists.

Locating code and data


Embedded Pascal provides you with a set of switches that you can use at any time to locate code
and data as you wish. These switches are:

{#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)

Please take note that constant strings such as:


S:=’Hello World”;
Can be stored either in the code or banked constant segment. This is selected in the options
menu.
Thumping your first program – getting started with
thumper
Thumper is designed to run on a Rabbit development system. Such a system may consist of a
Rabbit processor, Flash memory and RAM. It is possible to fully develop a system even if the
Rabbit development hardware has no Flash ROM but has only RAM.

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

This dumps 100 hex bytes at address 1000 hex.

* @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

Output value 55 hex to internal port at address 10.

* 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

Attempt to start the Flash ROM resident copy of Thumper.


Will signon with usual prompt and message "running from ROM" if successfull.
This would be the normal startup for an Embedded Pascal application if no development
system is connected. In that case the application will start after a short timeout
during which you can send "space" characters to serial port A in order to prevent
application startup and start Thumper instead. For example you may use this during
field debugging of a product when you need to have a quick look into memory.

*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.

Thumper debugging is intended to use as little resources as possible. No interrupts or


other hardware are required. Applications should be compiled using the "HLL debug" feature
"on" and must generate symbol info. Breakpoints are inserted by the compiler at the
beginning of every source line containing code. Breakpoints take the form of the one
byte RST 28H instruction.
Once your application is done - compile it with the breakpoints removed before
distributing it for maximum efficiancy.

Typical Thumper session based on one of the included


sample programs.
1) Start Embedded Pascal compiler. Open the project "Hello World" in the "Rabbit" folder.

2) Go to the options menu. Ensure device definition is set to "Rabbit". Ensure


HLL debugging in checked and symbol generation is checked as well.

3) Open the Hello.pas file in the Embedded Pascal editor.


Take note of the following lines at the beginning of the file. You will need these
lines on EVERY application that uses Thumper. (Of course you don't need to use
Thumper so you can do anything you like...)
link $1005,$6100 <-- This ensures that compiled code starts at address 1005H
and data area starts from 6100H. The first 100H bytes of the
data area are reserved for Thumper.
Trim $1000 <-- This ensures that the first 1000H bytes of the target ROM file
will be removed. Our code starts at 1000H

program Hello; Vector LongJMP Startup_Vector; <-standard way of inserting a jump


to our main routine.
Note: Use a FarJump directive if
Your main routine is in extended
program space. In that case your
link instruction must reserve an
extra byte: Link $1006,$6100

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).

5) Link the project. (Click on the right "chains" button).

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.

Now lets run the program on the Rabbit !

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:

12) Click on the "Debug RAM application" button.


This results in another reset, coldload and then Thumper issues an "X" to start the
debug process.

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.

15) Variable watches are available.

16) You'll figure out the rest...

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.

Obtaining extended addresses


Sometimes you may need to find the physical address of an item. In Pascal this is done using the
@ or Addr() function. These however return the 16 bit logical address of an item.
Embedded Pascal for the Rabbit includes a further pseudo function addr20() which returns the 20
bit physical address of an item. This function can also be used to construct tables of constant
addresses. Addr20() can be used on procedure and function addresses as well as variables and
typed constants.
Please note that Addr20() operates differently from the ordinary Pascal addr() function. Addr20()
produces code returning a longint containing the 20 bit base address of the item requested. This
item must have an identifier on the assembler level. Offsets from this base address as used in
array and record access cannot be used in the expression.
For example, the expression addr20(MyArray[20]) will fail, however addr20(MyArray)+20 can be
used (here assuming a byte array).
Using addr20() in typed constants leads to the generation of the assembler DAP instruction.

Input and output on the Rabbit


Embedded Pascal provides four Pascal procedures and functions to facilitate input and output.
These are:

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.

DAP – assembler extension


The DAP assembler extension is used to obtain a 20 bit physical address of an item. It can be
used to obtain the address of extended code, data or constants.
DAP operates similar to DB, DW, etc but returns a three byte entry (24 bits) of which the lower 20
bits are relevant.

CALLR and JPR assembler macros


Callr and Jpr are assembler/linker macros. These are used to perform far jumps on the rabbit
using the LCALL and LJP opcodes. Callr and Jpr calculate the required XPC value and lower 16
bit logical address for extended code operations.

PAGE assembler macro


The page assembler/linker macro evaluates the banked address of a given label and will perform
setting of the StackSeg register to make the item visible in the stack segment if required.
Page performes an evaluation of the required StackSeg value and will only insert the required
code if a change in value is required. Certain opcodes lead to the cancellation of this caching
scheme in order to force a new StackSeg initialization. These opcodes are typically Call and Ret
instructions, with the exception of library calls which are known not to touch the Stackseg register.
Should PAGE insert any code, no registers will be affected. The only register used is the
Accumulator which will be saved and restored on the stack.

Interrupts and Interrupt vector table location


In keeping with Embedded Pascal’s design philosophy of minimum system demands and fixed
requirements, you are completely free to place your interrupt vector table anywhere you choose.
The Thumper monitor initializes IIR to zero, thus locating the internal interrupt vector table to
address zero. The monitor only makes demand on a single vector – the RST 28H vector which is
used as a breakpiont. Note that this vectors to address 50H, not to 28H as on standard Z80/Z180
cores.
Should you want to use the vector table for your own application, we recommend that you create
such a table at the beginning of your code and locate it at 1000H (not using the first few bytes as
these are reserved).
Create a blank area (for example using the Assembler pass through directive #P) and let
Embedded Pascal fill in your interrupt vectors according to your requirements (See the “Vector”
keyword).
Your table should contain a jump to address 0050H located at the RST 28H vector in order to
keep the breakpoint system functioning.

You might also like