*****************************************************************************
Application Note:  Use Keil 8051 tools with Intel RISM51 on 51FX/151/251 Eval 
*****************************************************************************

This application note describes the usage of Keil 8051 development tools
together with the RISM51 Monitor which is installed on the Intel 51FX/151/251
evalution board (Rev. B).  The application note can be also used as guideline
for the Keil Monitor-51, when the application code must be place on other
addresses then the default.


1.  Writing Assembly Programs
-----------------------------

Introduction

We recommend that you are using relocateable programming techniques for writing
assembly programs.  In this way, you need just to change the locations of
the interrupt and reset vectors.  No other program code needs to be changed, if
you run the application without the Monitor-51/RISM51.  Only the L51/BL51
Linker/Locator invocation  (uVision Options - BL51 Linker) need to be altered.

The general way of writing assembly code is explained in the following example:

File:  MY_ASM.A51
;
; 
$NOMOD51		; disable the predefined 8051 register set
$INCLUDE (REG51F.INC)	; your controller definition file (example for 8051FX)

;****************************************************************************
;   Source Code Template for A51 Assembler Modules.
;   adapt names (in lower case letters) to your belongs.
;****************************************************************************

; This code template gives beginners an idea of how to use the A251/A51
; Assembler.  It is not required to build-up each module in this way. 
; All entries except the END statement at the End Of File are optionally. 
; Remove un-used segment declarations, if they do not contain variable space or
; not assembler instructions.  This file cannot contain all possibilities of
; the A51 Assembler.  Refer to the A51/A251 User's Guide for more
; information.

;
; Definition for Interrupt & Reset Vector Offsets
IOFFSET		EQU	4000H	; 4000H is the start for RISM51 boards
				; set this value to 0 for plain 8051 hardware

;----------------------------------------------------------------------------
;   give a module name (optionally)
NAME		module_name
;----------------------------------------------------------------------------

; import here symbols form other modules.; symbols in one module.

; Examples:
;EXTRN	CODE   (code_symbol)    ; can be a sub-routine entry declared in
				; CODE segments

;EXTRN	DATA   (data_symbol)	; can be any symbol declared in DATA segments

;EXTRN	BIT    (bit_symbol)	; can be any symbol declared in BIT segments

;EXTRN  NUMBER (typeless_symbol); can be any symbol declared with EQU or SET
				; directive

; you can also state more than one symbol in one EXTRN statement; example:

;EXTRN  	CODE (sub_routine1, sub_routine2), DATA (variable_1)
;----------------------------------------------------------------------------
$EJECT
;----------------------------------------------------------------------------
; export here symbols to other modules

; Examples:
PUBLIC	data_variable
PUBLIC  start		
PUBLIC  typeless_number
PUBLIC  bit_variable

; you can also state more than one symbol in one PUBLIC statement; example:
PUBLIC  data_variable1, typeless_num1

;----------------------------------------------------------------------------

; insert the STACK segment in the main module here
?STACK		SEGMENT	IDATA		; ?STACK goes into IDATA area of the
                                        ; 8051
		RSEG	?STACK		; switch to ?STACK segment.
		DS	1		; reserve 1 byte stack space
                                        ; this segment will be placed on the
                                        ; highest possible address, so that
                                        ; the maximum free space is available
                                        ; as stack

;----------------------------------------------------------------------------
$EJECT
;----------------------------------------------------------------------------
; insert segment and variable declarations here.; segments in each module

; Examples:
; DATA SEGMENT: reserves space in DATA RAM (delete segment if not used!)
data_seg_name	SEGMENT	DATA		; segment for DATA RAM.
		RSEG	data_seg_name	; switch to this data segment
data_variable:	DS	1		; reserve 1 Bytes for data_variable
data_variable1:	DS	2		; reserve 2 Bytes for data_variable1

; BIT SEGMENT: reserves space in BIT RAM (delete segment if not used!)
bit_seg_name	SEGMENT	BIT		; segment for BIT RAM.
		RSEG	bit_seg_name	; switch to this bit segment
bit_variable:	DBIT	1		; reserve 1 Bit for bit_variable
bit_variable1:	DBIT	4		; reserve 4 Bits for bit_variable1

;----------------------------------------------------------------------------

; Add any constant (typeless) numbers here.

; Examples:
typeless_number	EQU	0DH			; assign 0D hex
typeless_num1	EQU	typeless_number-8	; evaluate typeless_num1

;----------------------------------------------------------------------------
$EJECT
;****************************************************************************

; provide a LJMP to start at reset address (address 0FF0000H) in the main
; module. In the same style you can declare any interrupt functions
; (see later in the template file).  The reset vector (must be placed
; at 0xFF0000 without RISM and 0x004000 for RISM.  You simply use the form
; CSEG AT 0.  The relocation is done at L251 Level with the CLASSES directive.

		CSEG	AT  0+IOFFSET	; absolute Segment at Address 0
		LJMP	start		; reset location (jump to start)

;----------------------------------------------------------------------------
; CODE SEGMENT: reserves space in CODE ROM for assembler instructions
code_seg_name	SEGMENT	CODE
	
		RSEG	code_seg_name	; switch to this code segment

start:
		MOV	SP,#?STACK-1	; assign stack at beginning

;	insert here your assembler code
;---------------------------------------------------------------------------
;       examples:	(Note: the code itself is nonsens!)
repeat_label:	MOV	A,data_variable
		ADD	A,#typeless_number
		MOV	data_variable,A
		MOV	A,data_variable1+1
		ADD	A,#25
		MOV	data_variable1+1,A
		MOV	A,data_variable1
		ADDC	A,#0
		MOV	data_variable1,A
		JMP	repeat_label

;		
;----------------------------------------------------------------------------
$EJECT
;****************************************************************************
; The interrupt vectors can be placed in the same way as the reset vector.
; For the timer interrupt you simply write CSEG AT 0BH for others use instead
; of 0BH the interrupt vector location defined in the Hardware manual of the
; 251 derivative
;
; Example:
		CSEG	AT  0BH+IOFFSET	; 0BH is address for Timer 0 interrupt
		LJMP	timer0int

;---------------------------------------------------------------------------

; It is a good paractice to give each interrupt function an own code segment.
;
; Example:
int0_code_seg	SEGMENT	CODE		; segment for interrupt function
		RSEG	int0_code_seg	; switch to this code segment

		USING	1		; if you are using an own register
                                        ; bank for the interrupt routine
                                        ; you must state the USING directive
timer0int:	PUSH	PSW
		MOV	PSW,#08H	; register bank 1
		PUSH	ACC		; push registers above R7 to the stack
                PUSH	B               ; even when you change the register
                                        ; bank
		MOV	A,data_variable1+1
		ADD	A,#1
		MOV	data_variable1+1,A
		MOV	A,data_variable1
		ADDC	A,#0
		MOV	data_variable1,A
		POP	B
		POP	ACC
		POP	PSW
		RETI
		
;---------------------------------------------------------------------------

		END		; End Of File


2. Tool Setup of A51 and BL51
-----------------------------
The toolset up is performed in the project file MY_ASM.PRJ.  You can load this
project file in the uVision enviornment with Project - Open Project and then
select MY_ASM.PRJ.

The following describes the steps required for generating a new project file
with uVision:

a) Create a new Project file with  Project - New Project.  Then give a
file name for the project file.  We recommend that the project file is store
in the same directory as the source files.

b) Now, you must insert the assembler source files into the project.  You can
do this with the Add command in the dialog.  This dialog is shown directly
after the you have created a new project file.  If you want to modify the
project later, you can recall the dialog with  Project - Edit Project.

Insert now the assembler file  MY_ASM.A51.  If you have choosen a different
file extension  (example: ASM) make sure that you select A51 Assembler as the
translator and check the box for Include in Link/Lib.

You can add more source files to the project whenever you need this.  Once
you have completed the entry, click  SAVE  in this dialog.

c)  Now add the file RISM51DA.A51.  This file reserves the data space used
by the RISM51 Monitor.

d)  Setup the A51 Options
Use the dialog  Options - A51 Assembler Options - Object and check 
"include debug information" for symbolic debugging with dScope-51.
Save the options with OK.

d)  Setup the BL51 Options
The RISM Monitor requires, that you reserve some memory locations and that
the code starts at address 0x4000.  The RAMSIZE is 256.  To perform this,
set the following BL51 Options.  

Options - BL51 Linker - Size/Location
RAMSIZE:  256
CODE:     4000

The RISM Monitor requires that the STACK starts at 80H.  To setup the stack
pointer to this location enter the following BL51 Options.

Options - BL51 Linker - Segments
Stack:  ?STACK (80H)

3. Creating the executeable Program
-----------------------------------
You can create the executeable program with uVision when you press the 
Update button or select  Project - Make: Update Project.

This runs the A51 Assembler, the BL51 Linker and OH51 Object Converter.
The resulting files are:

  MY_ASM.LST the listing file from A51 Assembler.  This file can be used
  to locate the exact resons for some of the A51 errors or you can print this
  file.
  
  MY_ASM.OBJ the relocateable object file from A51.  This file is used 
  as input for the BL51 linker.  You need not to worry about it, since 
  uVision will automatically invoce the linker with this file.

  MY_ASM.M51 the linker MAP file which shows all segments and symbol
  information.

  MY_ASM  (without extension) is the executeable program in Intel OMF-51
  format.

  MY_ASM.HEX  is the executeable program in Intel HEX format.  The HEX file
  contains per default the code address range 00000H .. 0FFFFH in HEX format.

Once you have modified your application program, simply press Project Update,
and uVision will create and updated version of your application, whereby only
the files you have modified are re-translated.


4.  Debugging your Application Code
-----------------------------------
a)  Start dScope 51 with a click to the dScope button in the uVision toolbar.

b)  within dScope select the RISM51.DLL with File - Load DLL driver.  dScope
    will try to establish the communication with the Intel target board.  The
    default values should fit most of the Intel boards.  However, if you get
    communication errors  (timeout, serail transmission fails, ect.) you should
    check the serial COM port settings with the dialog:
       Peripherals - Configuration

    We suggest that you are using the external UART on the Intel boards.  This
    means that the switch UARTC must be ON on the Intel board.  Use the serial
    channel labeled with UART.  The baudrate you have to select is 9600 baud
    (at least for the most configurartions).  The COM board depends on your
    PC.  You should enable the serial break, since this allows you to break
    the program run with Control+C.

c)  Load the object file  MY_ASM  with the dScope dialog  File - Load object
    file.  This will load the application program into the Intel target board.
    dScope shows the source of your assembly module in the Debug Window.

d)  Within dScope you can perform several operations.  Enclose is a quick
    overview:
    -  You can view the assembly program by selecting  Commands - View Mixed
       in the Debug Window.
    -  You can single step through the program with the StepInto! command
    -  You can set breakpoints by a double click in on the source line which
       contains the instruction.
    -  You can start program execution with the Go! command.
    -  You can view variables with the WS Command.  Enter in the command
       window: 
          WS data_variable               ; shows the byte data_variable
          WS uint (d: &data_variable1);  ; shows the word data_variable1
    -  You can terminate a program run with Ctrl+C
    -  You can change the current PC location by entering:
         $=0x4000
       in the command window.


e)  The Intel RISM Monitor has several restrictions which do not appear in
    the Keil Monitor-51.  This restrictions are listed below:
    -  It is not possible to single step, when the interrupts are disabled.
       RISM uses the serial interrupt for controlling the program execution.
       If the serial interrupt is disabled  (EXT INT0 when you are using the
       external UART) the program execution will be started in real time.

    -  If you single step over an instruction which affects the interrupt
       system  (i.e.  OR  IE0,#82H), RISM will execute two steps.

    -  If you single step over the instruction RETI, RISM will return in most
       cases to the wrong address.

    -  RISM uses the DATA memory locations 02EH .. 03DH.  You must ensure that
       you have not place any variables in this area.  With the Keil toolset
       this is done with the file RISM51DA.A51.


5.  Automatic Start of dScope
-----------------------------
You can select an INI file for dScope, so that all commands which should be
executed at dScope startup are taken from this file.  Within uVision, you
can use the Options - dScope Debugger dialog to specify the dScope INI file.
For the MY_ASM project, we have named the file  MY_ASM.INI.  It contains
the following commands:

load rism51.dll              /* load the RISM51 driver */
load my_asm                  /* load the executeable program */
ws data_variable             /* show data_variable in the Watch Window */
ws uint (d:data_variable1)   /* show the data_variable1 in the Watch Window */


6.  Creating a C Application
----------------------------
C Applications are created in the same way as assembler applications.  The
project file MY_C.PRJ contains the same program in C language which was
shown previously in assembly language.

Since RISM uses memory location in the on-chip RAM of the 8051 chip, you need
to change the STARTUP.A51 code.  This code cannot longer clear the data
memory to 0 since otherwise RISM51 stops working.  Therefore change the
setting of the DATA_LEN to 0 in STARTUP.A51 as shown in the following line.
STARTUP.A51 must then be part of your project file.
IDATALEN	EQU	0H	; the length of IDATA memory in bytes.

In the STARTUP.A51 file you must also change the location of the RESET vector.
This location is defined with the statement CSEG AT 0.  The location required
with the RISM51 target monitor is 4000H.

For other Interrupt Vectors you must enter under:
Options - C51 Compiler - Object - Interrupt Vectors Offset:  0x4000

Just load the project file MY_C.PRJ and see the compiler and linker setups.
All the other steps required are identical with the assembler project described
above.

