⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lpc_isp_8k_v01.a51

📁 LPC9XX单片机ISP引导程序,实现在线烧写程序及网络更新
💻 A51
字号:

;89LPC2 boot flash program for IN-SYSTEM PROGRAMMING
;copyright Philips Semiconductors 2002, 2003
;$MOD52

;FILENAME: 		LPC2_ISP_8K_V01.TXT
;CODE TYPE: 		ISP
;VERSION: 		01
;RELEASE DATE: 		05 JUN 02
;CODE MEMORY SIZE: 	8KB
;CODE ADDRESS RANGE: 	1E00h - 1FFFh
;BOOT VECTOR: 		1E00h
;USES IAP VERSION: 	01
;USES IAP ENTRY: 	FF00h
;Author:		Bill Houghton
;
;Features:
;
;Version 1:
;- Original P89LPC932 release.
;

;code memory space for LPC2
;
;block 0, 1KB, 0000h - 03FFh
;block 1, 1KB, 0400h - 07FFh
;block 2, 1KB, 0800h - 0BFFh
;block 3, 1KB, 0C00h - 0FFFh
;block 4, 1KB, 1000h - 13FFh
;block 5, 1KB, 1400h - 17FFh
;block 6, 1KB, 1800h - 1BFFh
;block 7, 1KB, 1C00h - 1FFFh

;Bootrom, 240 bytes , FF00h - FFEF


PGMU	EQU	00
VRD	EQU	01               
MWR	EQU	02               
MRD	EQU	03               
ERS	EQU	04               
SCRC	EQU	05               
GCRC	EQU	06               
RUSR	EQU	07
               
PGM_MTP	EQU	0FF00H


;byte variables definition

DSEG	AT	30H

ADR0:		DS	1		;low byte of address
ADR1:		DS	1		;high byte of address
CHKSUM:	DS	1		;record checksum
NBYTES:	DS	1		;number of bytes in record
RTYPE:	DS	1		;record type
TMP3:		DS	1		;temporary storage

;***************  FMCON "CONF" addresses   *****************
;

UCFG1:	DS	1	;User configuration register 1
UCFG2:	DS	1	;User configuration register 2
BOOTV:	DS	1	;Boot Vector
STATBY:	DS	1	;Status Byte
FCFG1:	DS	1	;Factory config 1, read only
FCFG2:	DS	1	;Factory config 2, read only 
DERIV:	DS	1	;Derivative
TMEB_v:	DS	1	;TMEB
SEC0:		DS	1	;Security byte 0
SEC1:		DS	1	;Security byte 1
SEC2:		DS	1	;Security byte 2
SEC3:		DS	1	;Security byte 3
SEC4:		DS	1	;Security byte 4
SEC5:		DS	1	;Security byte 5
SEC6:		DS	1	;Security byte 6
SEC7:		DS	1	;Security byte 7
MF_ID:	DS	1	;Signature byte 0 (mfg id)
ID_1:		DS	1	;Signature byte 1 (device id)
ID_2:		DS	1	;Signature byte 2 (derivative id)

CRC0:		DS	1	;CRC data
CRC1:		DS	1	;CRC data
CRC2:		DS	1	;CRC data
CRC3:		DS	1	;CRC data

DSEG	AT 0B0H

PAGE:		DS	64	;64 byte page register data



;*************** equates list       ************************
;

CONFB		EQU	UCFG1		;start of CONF register space


RXDn		EQU	P1.1		;RxD pin

ISP_VER	EQU	01H		;ISP version id
AUXR		EQU	08EH		;auxr register
AUXR1		EQU	0A2H		;auxr 1 register
SRST		EQU	8H		;OR mask for software reset bit
TAMOD		EQU	8FH		;timer aux mode register
P1M1		EQU	91H
P1M2		EQU	92H

OI		EQU	ACC.0		;operation aborted by interrupt 
SV		EQU	ACC.1		;security violation
HVE		EQU	ACC.2		;high voltage error 

SBVAL		EQU	0FFH		;status byte default value
BVVAL		EQU	0FCH		;boot vector default value
DBYTES	EQU	80H		;start of RAM buffer for hex string


;bit variables definition

BSEG	AT	0H			; 


CSEG	AT	2000H-512

;CSEG	AT 0				;********** DEBUG ****************

;*********************************************************
;
;	START OF PROGRAM
;
;*********************************************************

;	First, we need to measure the baud rate of
;the host in terms of our own clock speed. This
;measurement can be made on a start bit provided
;the first data bit is a logical one. A capital "U"
;is a good choice since it has alternating 1s and 0s . 
;	Our measurement uses T1 which is clocked at
;fosc/2, which is the same as when T1 is used as 
;a baud rate generator. The UART uses 16x sampling
;so we need to divide the T1 count by 16. Even
;though the timer will be used in the 8-bit
;auto-reload mode for baud rate generation, non-reload
;16-bit mode is used for the measurement to give
;more clock counts for slower baud rates. This number
;will be divided by 16. This method allows the timer
;to count up to 4096 counts (16 x 256). The timer
;counts up towards zero thus counts loaded into the
;timer counter need to be negative numbers. A two's
;complement of the adjusted count produces this result.


INIT:
	MOV	P1M1,#00H
	MOV	P1M2,#00H
	MOV	P1,#0FFH
	MOV	TMOD,#10H	;16-bit non-reload 
	ANL	TAMOD,#0EFH	;not pwm mode 
	MOV	PCON,#80H	;SMOD = 1 = baud rate = T1/16
	CLR	A		;
	MOV	TH1,A		;set T1 to zero since we will
	MOV	TL1,A		;use this to count the start bit
MEAS:	JNB	RXDn,$		;wait for RXD to be high
	JB	RXDn,$		;wait until RXD goes low
	SETB	TR1		;start measuring the bit time
	JNB	RXDn,$		;wait until RXD goes high
	CLR	TR1		;stop measuring
	MOV	RTYPE,TH1	;copy timer to RAM
	MOV	R1,#RTYPE	;for indirect addressing
	MOV	A,TL1		;get timer low byte
	XCHD	A,@R1		;acc= TL upper nibble & TH lower nibble
	SWAP	A		;acc= TH lower nibble & TL upper nibble
	CPL	A		;complement lower byte of count
	INC	A		;two's complement  = - count/16
	MOV	TL1,A		;
	MOV	TH1,A		;load counts & switch to
	MOV	TMOD,#20H	;8-bit auto-reload mode
	SETB	TR1		;start T1
	MOV	SCON,#52H	;init UART 8-bit variable, TI=1 RI=0
QRZ:	ACALL	ECHO		;wait until character is rcv'd & get it
	CJNE	A,#'U',QRZ	;check to see if uppercase "U"


;***** Intel Hex File Load routine *****
;
;This routine loads an Intel Hex formatted file into 
;the buffer memory. The hex file is received as a series
;of ASCII characters on the serial input line of the
;serial port. A record type of 00H is considered to be
;a data field. Any other type of record is considered
;to be an End-of-File marker. This routine also calculates
;the checksum on the field as it is received and compares
;this calculated checksum with the checksum field received
;in the record.

LCMD:	MOV	CHKSUM,#0	;begin record... zero checksum
	ACALL	ECHO		;get first char and echo
	CJNE	A,#':',LCMD	;record starts with ':' char
	ACALL	GET2		;get the number of bytes in record
	MOV	NBYTES,TMP3	;and save
	ACALL	GET2		;get MSB of load address
	MOV	ADR1,TMP3	;and save
	ACALL	GET2		;get LSB of load address
	MOV	ADR0,TMP3	;and save it
	ACALL	GET2		;get record type
	MOV	RTYPE,TMP3	;and save it
	MOV	A,NBYTES	;else, more than
	MOV	R2,A	
	JZ	EOR		;zero data bytes ?
	MOV	R1,#DBYTES	;pointer for data bytes
LDATA:	ACALL	GET2		;get data byte
	MOV	@R1,TMP3	;store it
	INC	R1		;and bump up the pointer	
	DJNZ	R2,LDATA	;repeat if more bytes in record
EOR:	MOV	R4,CHKSUM	;save my calculated checksum
	ACALL	GET2		;get the checksum byte
	MOV	A,R4		;
	CJNE	A,TMP3,CHKERR	;recv'd & calc'd chksums match ?
	AJMP	PROCESS		;YES, process command

CHKERR:	MOV	A,#'X'
	AJMP	RSPND1

GET2:	ACALL	ECHO		;get first char of length
	ACALL	A2HEX		;convert to hex
	SWAP	A		;set in high nibble
	MOV	TMP3,A		;store in NBYTES
	ACALL	ECHO		;get second char of length
	ACALL	A2HEX		;convert to hex
	ORL	TMP3,A		;add into NBYTES
	MOV	A,CHKSUM	;get checksum
	CLR	C		;subtract NBYTES
	SUBB	A,TMP3		;from checksum and
	MOV	CHKSUM,A	;store as new checksum
	RET

;***** console output routine *****
;
;Outputs character in the ACC to 
;the serial output line.

CO:	JNB	TI,CO		;wait till xmtr ready
	CLR	TI		;reset xmtr flag
	MOV	SBUF,A	;output char to SIO
	RET			;and done

;***** console input routine *****
;
;Waits until character has been received
;and then returns char in ACC.

CI:	JNB	RI,CI		;wait till char
	CLR	RI		;reset rcvr flag
	MOV	A,SBUF	;read the char
	ANL	A,#7FH	;strip off MSB
	RET			;and done

;***** character echo routine *****
;
;waits until a character is received from
;the console input and echos this character
;to the console output. The received char
;is also passed to the caller in the ACC.

ECHO:	ACALL	CI			;get char from console 
	ACALL	CO			;print the character
	JNB	ACC.6,EXECHO	;exit if not 4x,5x, or 6x Hex
	CLR	ACC.5			;convert to upper case
EXECHO:
RET				;and done

;***** ASCII to HEX routine *****
;
;This routine accepts an ASCII char in the ACC
;and converts it into the corresponding hex digit.
;The routine checks to see if the char is in the
;range of '0' through '9' or in the range of 'A'
;through 'F'. If not in either range then the ASCII
;char is not a valid hex entry from the operator
;and an error flag is returned true along with the
;original ASCII char returned in the ACC.

A2HEX:
	JNB	ACC.6,HEX1
	ADD	A,#09H
HEX1:	ANL	A,#0FH
	RET

;***** HEX to ASCII routine *****
;
;This routine receives a single hex digit
;(a four bit nibble) in the ACC and returns
;the equivilent ASCII char in the ACC.

HEX2A:
	ANL	A,#0FH
	CLR	C		;carry affects the testing
	SUBB	A,#0AH	;test for range of 0-9, A-F
	JNC	HAHIGH	;no carry then A-F range
	ADD	A,#3AH	;add offset for 0-9 range
	RET
HAHIGH:
	ADD	A,#41H	;add in offset for A-F range
	RET


PROCESS:
	MOV	A,RTYPE		;get record type
	RL	A			;double ACC for two byte jumps
	MOV	DPTR,#RECTBL	;pointer = start of table
	JMP	@A+DPTR		;branch on record type

RECTBL:
	AJMP	PROGRAM	;0 = program data bytes
	AJMP	RDVER		;1 = read code versions
	AJMP	AUXWR		;2 = misc 'write' functions
	AJMP	AUXRD		;3 = misc 'read' functions
	AJMP	ERASE		;4 = erase block or page
	AJMP	CRCS		;5 = sector CRC
	AJMP	CRCG		;6 = global CRC
	AJMP	SETBR		;7 = set baud rate
	AJMP	RESET		;8 = reset MCU
	AJMP	DCMD		;9 = display device data

PROGRAM:
	MOV	R3,NBYTES	;get the number of bytes in record
	MOV	A,R3		;get the number of bytes in record
	JZ	EOF		;exit if no bytes in record
	MOV	R5,ADR0	;get the load address
	MOV	R4,ADR1	;of the first byte in record
	MOV	R7,#DBYTES	;pointer to data
	MOV	A,#PGMU	;program user code
EXEC:	CALL	PGM_MTP	;write the entire record & verify
	JB	F0,ERROR	;check if an error occured

EOF:	MOV	A,#'.'	;no error
RSPND1:
	ACALL	CO		;send an okay message
	AJMP	DEXIT		;and done

ERROR:
	MOV	A,#'R'	;print a verify error
	ACALL	CO		;send an okay message
	MOV	A,R7		;get status
	ACALL	OUTBYT	;and print
	AJMP	DEXIT		;and done



;***** display buffer contents routine *****
;
;This routine displays the contents of the buffer memory
;over a user specified range. The displayed output is formatted
;into a series of lines on the console. A line begins with the
;address of the first byte in the line. Line length is limited
;to a maximum of 16 bytes per line. Once this limit is reached,
;new formatted lines are used.

DCMD:
	MOV	R0,#DBYTES	;
	MOV	DPH,@R0	;get high byte of starting address
	INC	R0		;point to low byte of starting address
	MOV	DPL,@R0	;get low byte of starting address
	INC	R0		;point to high byte of ending address
	MOV	ADR1,@R0	;get high byte of ending address
	INC	R0		;point to low byte of ending address
	MOV	ADR0,@R0	;get low byte of ending address
	INC	R0		;point to function either display or blankcheck
	JNB	RI,$		;wait till host ready to receive
	CLR	RI

DLINE:
	CJNE	@R0,#00H,DAGN	;ignore this if its not a display command
	ACALL	CRLF
	MOV	R2,#10H	;R2 = 16 bytes per line
	MOV	A,DPH
	ACALL	OUTBYT
	MOV	A,DPL
	ACALL	OUTBYT	;print the address
	MOV	A,#'='	;of first byte of
	ACALL	CO		;the line along with

DAGN:

	MOV	R4,DPH
	MOV	R5,DPL
	MOV	A,#RUSR	; READ_USER
	CALL	PGM_MTP	;read the byte
	MOV	A,R7		;get result
DPRN:
	CJNE	@R0,#00H,BLKCHK ;ignore this if its not a display command
	ACALL	OUTBYT	;and print it
	SJMP	CKDEND	;and then check if we've reached the end
BLKCHK:
	CJNE	A,#00H,BLANKERR
CKDEND:
	MOV	A,ADR1		;
	CJNE	A,DPH,DNEXT		;check if DPH = stop high
	MOV	A,ADR0		;
	CJNE	A,DPL,DNEXT		;check if DPL = stop low
	CJNE	@R0,#01H,DEXIT 	;if display command use display exit 
	AJMP	EOF			;blankcheck exit (print a period)

DEXIT:
	ACALL	CRLF		;print a CRLF
	JNB	TI,$
	SETB	REN		;TURN ON UART RECEIVER
	AJMP	LCMD		;branch to main loop
DNEXT:
	INC	DPTR		;more bytes so point to next byte
DNXT1:
	DJNZ	R2,DAGN
	AJMP	DLINE		;we start a new line or not

BLANKERR:
	MOV	A,DPH
	ACALL	OUTBYT	;print DPH
	MOV	A,DPL
	ACALL	OUTBYT	;print DPL
	AJMP	DEXIT		;and exit


AUXWR:
	MOV	R1,#DBYTES	;pointer for data
	MOV	A,@R1		;
	MOV	R7,A		;get the subfunction code 
	INC	R1		;
	MOV	A,@R1		;
	MOV	R5,A		;get the data to write 
	MOV	A,#MWR	;function code 
	AJMP	EXEC		;perform the function & check for errors

ERR:	AJMP	ERROR		;error vector

AUXRD:
	MOV	R1,#DBYTES	;pointer for data
	MOV	A,@R1		;
	MOV	R7,A		;get the subfunction code 
	MOV	A,#MRD	;function code 
	CALL	PGM_MTP	;and perform the function
	JB	F0,ERR	;exit if an error occured
	MOV	A,R7		;get the response 
	ACALL	OUTBYT	;and print it
	AJMP	EOF		;and we're done
	
ERASE:
	MOV	R1,#DBYTES	;pointer for data
	MOV	A,@R1		;
	MOV	R7,A		;get the block or page erase command 
	INC	R1		;
	MOV	A,@R1		;
	MOV	R4,A		;get the high address 
	INC	R1		;
	MOV	A,@R1		;
	MOV	R5,A		;get the low address 
	MOV	A,#ERS	;function code 
	AJMP	EXEC		;perform the function & check for errors

CRCG:
	MOV	A,#GCRC	;function code 
	AJMP	DO_CRC	;and do the CRC
CRCS:
	MOV	R1,#DBYTES	;pointer for data
	MOV	A,@R1		;
	MOV	R7,A		;get the sector number
	MOV	A,#SCRC	;function code 
DO_CRC:
	CALL	PGM_MTP	;and perform the function
	JB	F0,ERR	;exit if an error occured
	MOV	A,R4		;get CRC bits 31:24 
	ACALL	OUTBYT	;and print
	MOV	A,R5		;get CRC bits 23:16 
	ACALL	OUTBYT	;and print
	MOV	A,R6		;get CRC bits 15:8 
	ACALL	OUTBYT	;and print
	MOV	A,R7		;get CRC bits 7:0 
	ACALL	OUTBYT	;and print
	AJMP	EOF		;and we're done

CRLF:	MOV	A,#0DH
	ACALL	CO
	MOV	A,#0AH
	ACALL	CO
	RET

OUTBYT:	MOV	R4,A		;"push acc"
	SWAP	A
	ACALL	HEX2A
	ACALL	CO
	MOV	A,R4		;"pop acc"
	ACALL	HEX2A
	ACALL	CO
	RET

SETBR:
	MOV	A,#'.'	;respond with okay status before
	ACALL	CO		;changing the baud rate (i.e.- at the old baud rate)
	MOV	R1,#0FFH	;
	DJNZ	R1,$		;wait before proceeding	
	DJNZ	R1,$		;wait before proceeding	
	CLR	TR1		;stop the timer
	MOV	R1,#DBYTES	;pointer for data
	MOV	TH1,@R1	;get baud rate
	MOV	TL1,@R1	;get baud rate
	SETB	TR1		;start the timer
	RET			;and done

RESET:
	ORL	AUXR1,#SRST	;set the software reset bit

RDVER:
	MOV	DPTR,#ISPV		;pointer to version id for ISP
	CLR	A			;
	MOVC	A,@A+DPTR		;look up ISP version id
	ACALL	OUTBYT	;and print it
	MOV	A,#VRD	;function code 
	CALL	PGM_MTP	;and perform the function
	MOV	A,R7		;get the response 
	ACALL	OUTBYT	;and print it
	AJMP	EOF		;and we're done

; ****** debug ***************ORG	1FFFH

ISPV:	DB	ISP_VER		;ISP version id

END

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -