skip navigational linksPJRC
Shopping Cart Checkout Shipping Cost Download Website
Home Products Teensy Blog Forum
You are here: 8051 Tools PAULMON Monitor Manual Adding Commands

PJRC Store
8051 Board, $79
LCD 128x64 Pixel, $29
LCD 16x2 Char, $14
Serial Cable, $5
9 Volt Power, $6
More Components...
8051 Tools
Main Page
Development Board
Code Library
89C2051 Programmer
Other Resources

Adding Commands to PAULMON2

Commands can be easily added to PAULMON2 by attaching the required program header. These commands can add new functions or replace the existing commands. The extras package is an example of three such commands. The List and Single-Step add new commands, and the Memory Editor replaces the built-in memory editor by using the same key ("E").

Creating external commands with the program header is very easy way to add functionality to PAULMON2, because each new attempt can be downloaded and tried in RAM without reprogramming the EPROM with PAULMON2.

Here is a very simple example:

.equ    locat, 0x3D00     ;Location for this code

;This very simple paulmon2 command sets the memory location
;pointer to 3000 when the '3' key is pressed.  That's a very simple
;command, but it can be nice when developing a program for
;use at 3000 when the default memory location is at 2000...
;Just press '3' at the prompt rather than typing "N" and "3000"

.org    locat
.db     0xA5,0xE5,0xE0,0xA5     ;signiture bytes
.db     254,'3',0,0             ;id (254=cmd)
.db     0,0,0,0                 ;prompt code vector
.db     0,0,0,0                 ;reserved
.db     0,0,0,0                 ;reserved
.db     0,0,0,0                 ;reserved
.db     0,0,0,0                 ;user defined
.db     255,255,255,255         ;length and checksum (255=unused)
.db     "Memory Location 3000",0
.org    locat+64                ;executable code begins here

        mov     r6, #0
        mov     r7, #0x30
The "locat" symbol makes reassembling this command for a different location much easier. The group of ".db" lines create the header. The code only contains three instructions. The "memory pointer" that PAULMON2 uses is kept in r6 and r7, so these two registers are overwritten with the value 3000, and finally the command returns back to PAULMON2 with the "ret" instruction.

When this simple command is downloaded to PAULMON2:

PAULMON2 (beta7) Loc:2000 > Download

Begin ascii transfer of Intel hex file, or ESC to abort

Download completed

 6  lines received
 58  bytes received
 58  bytes written
No errors detected
Immediately after the program is placed into memory, it is available for use in PAULMON2. The List Programs command ("M") should display this program in the list if the header is correct:
PAULMON2 (beta7) Loc:2000 > List programs

Program Name                     Location      Type
  List                             1000      External command
  Single-Step                      1400      External command
  Memory Editor (VT100)            1800      External command
  Memory Location 3000             3D00      External command
And the Help command should find the header for this new program and correctly display its name and the key which will run the command:
PAULMON2 (beta7) Loc:2000 > Help

Standard Commands
  ?- This help list
  M- List programs
  R- Run program
  D- Download
  U- Upload
  N- New location
  J- Jump to memory location
  H- Hex dump external memory
  I- Hex dump internal memory
  E- Editing external ram
  C- Clear memory
  Z- Erase flash rom
User Installed Commands
  L- List
  S- Single-Step
  E- Memory Editor (VT100)
  3- Memory Location 3000
Finally, when the program is run, nothing dramatic is expected to happen, except change the memory location pointer within PAULMON2. Here is what actually happens when "3" is pressed:
PAULMON2 (beta7) Loc:2000 >  Memory Location 3000
PAULMON2 (beta7) Loc:3000 >

Rules For Writing PAULMON2 Commands

  • Use the 64-byte program header, type 254.
  • R6 and R7 hold PAULMON2's memory pointer. The other 6 registers, Acc, B may be changed. R6 and R7 may be changed to any value, but this will be reflected in the value of the memory pointer when your code returns to PAULMON2.
  • Don't change the stack pointer. If the stack pointer value is different or the values that PAULMON2 pushed onto the stack before running your command are altered, PAULMON2 will probably crash when your command returns.
  • Don't alter timer1 or the serial port setup (or carefully restore it if you do). The built-in uart is required when your code returns to PAULMON2. The assumption is that your external command won't mess up the special function registers.
  • Is it advisable to do all serial I/O using PAULMON2's I/O routines. See PAULMON2.EQU for details.
  • If static data storage between uses of your new command is required, memory must be selected which will not conflict with the stack, the 8 registers, the 16 bytes of temporary space used by the download command, and the baud rate parameter storage. (add link to a place which tells where all those things are) Your new command should be able to deal with any static storage variables being overwritten, because PAULMON2 may be used to Jump to a program that could overwrite any memory while it has control of the 8051.
  • Any of the PAULMON2 commands may be replaced with a external command. It is not wise to replace the Download ("D") command, and perhaps a couple of the others as well.
  • If your new command makes use of interrupts (the single-step command is an example of this), do not return to PAULMON2 while inside an interrupt service routine. If your command must abort while servicing an interrupt, LJMP to location zero, where PAULMON2 will clear any pending interrupts with two RETI instructions.
  • Return back to PAULMON2 with a "ret" instruction.

Example Commands

You can download both of the examples in a single zip file. These can be useful as a starting point to create your own commands. If you do create useful commands for PAULMON2, please consider contributing them to others.

Here is a second example, which actually contains two commands in one file. These commands are very similar to the built-in memory dump commands, but each one displays twice as much data.

.equ    locat, 0x3E00		;Location for this code

;This file demonstrates two external commands which are
;nearly identical to the built-in ones inside PAULMON2.
;The external memory dump prints 512 bytes (32 lines)
;and the internal memory dump prints all 256 locations.

.equ    dump_key, 'H'           ;hex dump memory
.equ    intm_key, 'I'           ;hex dump internal memory

.equ	cout, 0x0030		;routines to use from paulmon2
.equ	phex, 0x0034
.equ	phex16, 0x0036
.equ	newline, 0x0048

.org    locat
.db     0xA5,0xE5,0xE0,0xA5     ;signiture bytes
.db     254,dump_key,0,0        ;id (254=cmd)
.db     0,0,0,0                 ;prompt code vector
.db     0,0,0,0                 ;reserved
.db     0,0,0,0                 ;reserved
.db     0,0,0,0                 ;reserved
.db     0,0,0,0                 ;user defined
.db     255,255,255,255         ;length and checksum (255=unused)
.db     "Hex Dump External Memory",0
.org    locat+64                ;executable code begins here

	mov     r2, #32         ;number of lines to print
	lcall   newline
	lcall   newline
dump1:  mov     dpl, r6
	mov     dph, r7
	lcall   phex16          ;tell 'em the memory location
	mov     a,#':'
	lcall   cout
	acall   space
	mov     r3, #16         ;r3 counts # of bytes to print
	mov     dpl, r6
	mov     dph, r7
dump2:  clr     a
	movc    a, @a+dptr
	inc     dptr
	lcall   phex            ;print each byte in hex
	acall   space
	djnz    r3, dump2
	acall   space           ;print a couple extra space
	acall   space
	mov     r3, #16
	mov     dpl, r6
	mov     dph, r7
dump3:  clr     a
	movc    a, @a+dptr
	inc     dptr
	anl     a, #01111111b   ;avoid unprintable characters
	cjne	a, #127, dump3b
	clr	a		;avoid 127/255 (delete/rubout) char
dump3b:	add	a, #224
	jc      dump4
	clr	a		;avoid control characters
dump4:  add     a, #32
	lcall   cout
	djnz    r3, dump3
	lcall   newline
	mov     r6, dpl
	mov     r7, dph
	djnz    r2, dump1       ;loop back up to print next line
        lcall   newline

space:	mov	a, #' '
	lcall	cout

.org    locat+256
.db     0xA5,0xE5,0xE0,0xA5     ;signiture bytes
.db     254,intm_key,0,0        ;id (254=cmd)
.db     0,0,0,0                 ;prompt code vector
.db     0,0,0,0                 ;reserved
.db     0,0,0,0                 ;reserved
.db     0,0,0,0                 ;reserved
.db     0,0,0,0                 ;user defined
.db     255,255,255,255         ;length and checksum (255=unused)
.db     "Hex Dump Internal Memory",0
.org    locat+256+64            ;executable code begins here

intm:	lcall	newline
	lcall	newline
	mov	r0, #0
	sjmp	intm3
intm2:	lcall	newline
	cjne	r0, #0, intm3 
	ljmp	newline
intm3:	mov	a, r0
	lcall	phex
	mov	a, #':'
	lcall	cout
intm4:	acall	space
	mov	a, @r0
	lcall	phex
	inc	r0
	mov	a, r0
	anl	a, #00001111b
	jnz	intm4
	sjmp	intm2
The procedure for using these is the same as above. Just download the file and once it's in memory, pressing "H" or "I" will run the code shown here instead of the original memory dump commands which are built-in to PAULMON2.

Though these are simple examples, quite a lot can be done with external commands... in fact nearly anything that could have been included in PAULMON2 can be added as an external command. The extras package is an example of much more complex commands.

For boards with Flash ROM or other unused non-volatile memory, external commands can be used to make permanent additions to PAULMON2 which are nearly as easy to develop as ordinary applications, because PAULMON2 itself does not have to be modified to add the functionality.

PAULMON2 Documentation, Paul Stoffregen
Last updated: February 24, 2005
Status: This page is finished
Suggestions, comments, bug reports??? <>