;***********************************************************************************
; LISTING NO.: 1
;
; FILE NAME: FE32.ASM
; PURPOSE: To provide a FLASH erase, program and verify program
; TARGET DEVICE: HC908GP32
;
; MEMORY USAGE - RAM: 1A0H BYTES
;			ROM: 280H BYTES
;
; ASSEMBLER: CASM08
; VERSION: 1.02
;
; PROGRAM DESCRIPTION:
; This program loads a RAM routine with instructions/data
; located in FLASH memory that:
;	Receives data over the SCI or Port A, bit 0
;	Row-erases FLASH block if necessary
;	Programs FLASH with received data
;	Dumps specified row out comm port
;	Bulk erases device upon command
;
; The program has assembler directives to be able to program in
; both user and monitor modes. In monitor mode, the generated S-record
; file will contain all of the necessary programming routines in RAM. It
; will not have any code that would reside out of RAM. In user mode, load
; routines are incorporated so that it could be contained in a user's
; application. The load routines load the programming routines into RAM and
; from there it looks just like the RAM routine executed in monitor mode.
;
;
; AUTHOR: Grant Whitacre
; LOCATION: Austin, Texas
;
; UPDATE HISTORY:
; REV	AUTHOR		DATE		DESCRIPTION OF CHANGE
; ===	============	========	=====================
; 0.0	GRANT WHITACRE	03/04/98	INITIAL VERSION
; 0.1	GRANT WHITACRE	04/15/98	SECOND VERSION (FP2.ASM)-
;					LOADS ALL RTNS INTO RAM
;					SO RE-ENTRY INTO FLASH IS
;					NOT NECESSARY. ALLOWS
;					REPROGRAMMING OF ENTIRE
;					FLASH ARRAY.
; 0.2	GRANT WHITACRE	06/22/98	CONSOLIDATES PROGRAM TO
;					ALLOW BOTH USER MODE AND
;					MONITOR MODE PROGRAMMING
;					SELECTABLE BY ASSEMBLER
;					DIRECTIVES
;
;
; GENERAL CODING NOTES:
; Bit names are labeled with <port name><bit number> and are
; used in the commands that operate on individual bits, such
; as BSET and BCLR. A bit name followed by a dot indicates
; a label that will be used to form a bit mask.
;
; FOR TESTING, HAD TO ADD AN ASSEMBLER SWITCH (TESTMOD) TO
; KEEP FROM TRIPPING ON AN ILLEGAL MEMORY WRITE BREAK IN
; THE DEBUGGER. OTHER SWITCHES ARE INSTALLED FOR EASE OF
; TESTING.
;
;***********************************************************************************
; ASSEMBLER DIRECTIVES
; (INCLUDES, BASE, MACROS, SETS, CONDITIONS, RAM DEFS, ETC.)
;***********************************************************************************
	       .radix	D			;DEFAULT TO BASE 10 NUMBER DESIGNATION
						;Remember: ACTIVE LOW!!!!!!!!!!!!!!!!!!
MONPROG		=	0				;IF SET, ALL (NECESSARY) ROUTINES WILL
						;BE ADDRESSED IN RAM INITIALLY; THIS
						;VERSION WOULD BE USED AS THE S19 RECORD
						;FILE THAT IS DOWNLOADED INTO RAM IN
						;MONITOR MODE FOR FLASH PROGRAMMING
;Be sure to manually set addresses of GET_PUT and PUT_BYTE if TESTMOD set!!
TESTMOD		=	0				;SINCE WE GET AN ILLEGAL WRITE ERROR
						;USING THE MMDS WHEN WE TRY TO WRITE TO
						;EMULATED MEMORY, TESTMOD CAUSES A READ
						;FROM FLASH LOCATION INSTEAD OF A WRITE
						;TO IT. OF COURSE VERIFY NEVER WORKS
						;UNDER THESE CIRCUMSTANCES. TURN OFF
						;TEST MODE FOR REAL TARGET EXECUTION.
ERSDTST		=	0		        ;SET TO FORCE A GOOD VERIFICATION OF
						;ERASED STATE
;***********************************************************************************
; PORT AND I/O REGISTER EQUATES
;***********************************************************************************
PORTA		=	$$00			;I/O PORT A
PORTB		=	$$01			;I/O PORT B
PORTC		=	$$02			;I/O PORT C
PORTD		=	$$03			;I/O PORT D
PORTE		=	$$07			;I/O PORT E
;***** FLASH CONTROL REGISTER ******************************************************
FLCR		=	$$FE08		;FLASH CONTROL REGISTER
; FDIV1		=	7
; FDIV0		=	6
; BLK1		=	5
; BLK0		=	4
HVEN		=	3
; VERF		=	2			;FOR 908GP20 ONLY
; MARG		=	2			;FOR 908XL36 ONLY
MASS            =       2                       ;FOR 908GP32
ERASE		=	1
PGM		=	0
; FDIV1.          =	$$80
; FDIV0.          =	$$40
; BLK1.		=	$$20
; BLK0.		=	$$10
HVEN.		=	$$08
; VERF.		=	$$04
; MARG.		=	$$04
MASS.           =       $$04
ERASE.          =	$$02
PGM.		=	$$01
;***** BLOCK PROTECTION REGISTER ***************************************************
; FLBPR		=	$$FF80		;FLASH BLOCK PROTECTION - This is for HC08HC908GP20
FLBPR		=	$$FF7E		;FLASH BLOCK PROTECTION - This is the right address for HC08HC908GP32
					;REGISTER
;***********************************************************************************
; APPLICATION-SPECIFIC MEMORY AND I/O EQUATES
;***********************************************************************************
; THE VALUE FOR CPUSPD DRIVES THE FDIV SETTING AND THE BAUD RATE
; PRESCALER FOR THE SCI.
; MAKE SURE THAT CPUSPD IS SET TO 2 IF THE PLL IS TO BE USED.
; IN MONITOR MODE THE BUS FREQUENCY IS 2.45 MHZ, SO USE 2
CPUSPD          =	2			;2 = 2.45 MHZ OPER. FREQ.
						;4 = 4.92 MHZ, 8 = 8.0 MHZ
; ABS. ADDRESS OF MONITOR ROUTINES COMMENTED OUT IN TEST VERSION
GET_PUT         =	$$FE97		        ;MON RTN TO GET A BYTE ON
						;PTA0 AND ECHO BACK
PUT_BYTE	=	$$FEAA		        ;SEND A BYTE OUT PTA0
MONRTNS	        =	$$B300		        ;MONITOR ROUTINES INCLUDED IN
						;PROGRAM FOR TESTING
RSTVLOC	        =	$$FFFE		        ;RESET VECTOR LOCATION
RAM		=	$$50			;FIRST ADDRESS OF RAM, ACTUALLY
						;$$40 BUT WILL START AT $50
RAMEND          =       $$240                   ;-- Salvi : RAM End
NXTPAGE         =	$$100
STCKSIZ         =	$$1C ;$$18
PRGSTRT         =	$$F000		        ;START OF FLASH PROGRAM
LASTBYT         =	$$F0F0
NXFPAGE         =	$$F100
RAMPRG          =	RAM+$$58		;START OF RAM ROUTINE
RAMPRSZ         =	$$197			;320 BYTES (MAX)
TESTDAT         =	$$C0
XFRCODE         =	PRGSTRT+RAMPRG
STUBINT         =	PRGSTRT+$$240		;PUT HERE FOR NOW -
						;SHOULD BE SAFE
VECSTRT         =	$$FFDC	                ;START OF USER VECTOR AREA
PRGTRIES	=	25			;MAX. NUMBER OF PROGRAM TRIES
; MASKS FOR ERASE RANGE
FARMASK         =	$$00			;FULL ARRAY
HARMASK         =	$$10			;HALF ARRAY
RW8MASK         =	$$20			;8 ROWS
ROWMASK         =	$$30			;1 ROW
; PROGRAMMING TIMES - CHANGE THESE VALUES IF NECESSARY TO
; CHANGE TIMES! ALL TIMES ARE IN MICROSECONDS
VTPGM		=	1000			;1000 - PROGRAM TIME
VHLFTER         =	50000		        ;1/2 ERASE TIME
VTKILL	        =	200			;HIGH-VOLTAGE KILL TIME
VTHVD		=	50			;RETURN TO READ TIME
VTHVTV          =	50			;HVEN LOW TO VERF HIGH TIME
VTVTP		=	150			;VERF HIGH TO PGM LOW TIME
; INTERMEDIATE PROGRAMMING TIMES (CALCULATION PURPOSES ONLY)
CTPGM		=	(VTPGM/6)		;DIVIDE BY 6 HERE TO NORMALIZE
CHLFTER         =	(VHLFTER/6)		;FOR NEXT STEP. PADDED FROM
CTKILL          =	(VTKILL/6)		;8 TO 6 TO COMPENSATE FOR ODD
CTHVD		=	(VTHVD/6)		;FREQUENCIES (2.45 AND 4.92 MHZ)
CTHVTV          =	(VTHVTV/6)		;AND TRUNCATION.
CTVTP		=	(VTVTP/6)
; CPU SPEED-CORRECTED PROGRAMMING TIMES (TIMES ACTUALLY USED)
TPGM		=	(CPUSPD*CTPGM)          ;Program time = 1000 µs @ 8 MHz
HLFTERA         =	(CPUSPD*CHLFTER)        ;Half of Erase time = 50 µs @ 8 MHz
TKILL		=	(CPUSPD*CTKILL)         ;HV Kill time = 200 µs
THVD		=	(CPUSPD*CTHVD)          ;Return to read time = 50 µs
THVTV		=	(CPUSPD*CTHVTV)         ;HVEN low to VERF high time = 50 µs
TVTP		=	(CPUSPD*CTVTP)          ;VERF high to PGM low time = 150 µs
;***********************************************************************************
; VARIABLE DEFINITIONS & RAM SPACE USAGE
;***********************************************************************************
; $$40-$4F	NOT USED			( 16 BYTES)
; $$50		TRANSFER SIZE			( 1 BYTE)
; $$51-$52	FIRST ADDRESS TO BE PROGRAMMED( 2 BYTES)
; $$53		DATA SIZE (DATASIZ)		( 1 BYTE)
; $$54-$93	DATA ARRAY			( 64 BYTES)
; $$94-$A7	VARIABLES			( 20 BYTES)
; $$A8-$EF	RAM PROGRAM			( 72 BYTES)
; $$F0-$FF	STACK				( 16 BYTES)
; $$100-$23F	RAM PROGRAM			(320 BYTES)
; $$50-$23F	TOTAL				(512 BYTES)
		.area	RAMPGM	(ABS)
		.org	RAM
XFRSIZE:	.blkb	1			;NUMBER OF BYTES TO BE TRANSFERRED
FRSTADR:	.blkb	2			;FIRST ADDR TO BE PROGRAMMED
DATASIZ:	.blkb	1			;NUMBER OF BYTES TO PROGRAM
DATARAY:	.blkb	64			;RESERVE 64 BYTES FOR DATA
DATA1:		.blkb	8			;DATA TO BE PROGR. IN PAGE-8 BYTES
REPROG:		.blkb	1			;A $$01 HERE SIGNALS NEED TO REPROGRAM
TEMPH:		.blkb	1			;RAM COUNTER (HI BYTE)
TEMPL:		.blkb	1			;RAM COUNTER (LOW BYTE)
TEMP2:		.blkb	1			;TEMP. HOLDING LOC. FOR TRANSFERS/PR
						;TRIES
FDIVMSK:	.blkb	1			;FDIV OF FLCR BIT MASK
BYTECNT:	.blkb	1			;BYTE COUNT USED DURING PAGE PROG.
ARAYIDX:	.blkb	1			;INDEX INTO THE DATA ARRAY
CURRBYT:	.blkb	1			;CURRENT BYTE BEING READ/WRITTEN (0-7)
STATBYT:	.blkb	1			;STATUS OF PROGRAM SUCCESS -
						;BIT 7 = FAILED; BIT 6 = SUCCEEDED
;***********************************************************************************
;	Program Algorithm (User Mode Programming)
;	1.	Initialize all variables and ports, PLL (if selected) and
;		SCI.
;	2.	Monitor SCI port for input of block of data to be
;		programmed and the start address. Load RAM with the data
;		array (up to 64 bytes), the start address and length of
;		data array.
;	3.	Transfer the following subroutines to
;		RAM at address RAMPRG
;		A.	LDDATA
;		B.	MAINPRG
;		C.	ERABLK
;		D.	DELNUS
;		E.	MASSERASE
;	4.	Jump to first byte of main RAM program (RAMPRG).
;	5	Execute RAM program MAINPRG and then return to SCI
;		port monitoring loop in RAM.
;
;	Program Algorithm - Monitor Mode Programming
;	1.	Monitor PTA0 for input of block of data to be
;		programmed and the start address. Load RAM with the data
;		array (up to 64 bytes), the start address and length of
;		data array.
;	2.	Execute RAM program MAINPRG and then return to PTA0
;		monitoring loop in RAM.
;***********************************************************************************
;
; START OF PROGRAM
;***********************************************************************************
; START OF THE MONITOR PROGRAM WHICH WE'LL .org IN RAM
		.org	RAMPRG		;CURRENTLY $$A8
START:
;                LDHX    RAMEND
;                TXS                     ; Sets the upper limit of accessible RAM
;***********************************************************************************
; NAME: LDDATA
; PURPOSE: LOAD RAM WITH USER'S DATA AND START ADDRESS VIA THE SCI;
;          PROGRAMS AND THEN DUMPS DATA THAT IS DOWNLOADED; ONLY DUMPS DATA
;          IN ROW SPECIFIED IF NUMBER OF BYTES TO BE PROGRAMMED (DATASIZ) IS 0.
; ENTRY CONDITIONS:
; EXIT CONDITIONS:
; SUBROUTINES CALLED: PRGFLSH, DUMPROW
; EXTERNAL VARIABLES USED:
; DESCRIPTION: EXECUTED OUT OF RAM
; THE STRUCTURE OF THE DATA RECEIVED IS AS FOLLOWS:
;	LOCATION	DESCRIPTION				RAM LOC.
;	========	==================================	========
;	1		COUNT OF THE TOTAL NUMBER OF		$$40
;			BYTES TO BE SENT (INCL. THAT BYTE)
;	2-3		THE FIRST ADDRESS WHERE THE		$$41-$42
;			FOLLOWING DATA IS TO BE PROGRAMMED
;	4		NUMBER OF BYTES TO BE PROGRAMMED	$$43
;	5-68		ARRAY SPACE FOR DATA TO BE PROGRAMMED	$$44-$83
;
; IF A COUNT IS USED THAT IS GREATER THAN (PROGRAM LENGTH + 1)
; THEN THE ROUTINE WILL HANG AFTER THE LAST PROGRAM BYTE IS SENT.
; CONTINUOUSLY LOOPS LOOKING FOR NEW DATA ON THE SCI. MUST RESET
; AFTER THE LAST ROW DOWNLOAD.
; IF A DATA ARRAY IS RECEIVED WITH A NUMBER OF BYTES TO BE PROGRAMMED OF >= $$80
; THEN PROGRAM WILL CONSTRUE THIS AS A SIGNAL TO ERASE THE ENTIRE ARRAY. THIS
; WAS THE MOST CONVENIENT WAY TO IMPLEMENT BULK ERASE WITHOUT HAVING TO HAVE
; A COMMAND BYTE IN THE DATA STRUCTURE.
;***********************************************************************************
LDDATA:		CLRH
		CLRA
		LDX	#RAM			;POINT TO START OF RAM
		CLR	FDIVMSK
WAITRX:
		JSR	GET_PUT
		NOP
		NOP
CHKCHK:	        CPX	#RAM			;IF VALUE OF 1ST BYTE IS ZERO, THEN
		BNE	STORNOW		        ;BAD START - KEEP LOOPING FOR NON-
		TSTA                            ;ZERO FIRST BYTE
		BEQ	WAITRX
STORNOW:	STA	,X			;STORE THE DATA IN RAM
		INCX				;MOVE TO NEXT RAM LOCATION
		DBNZ	*RAM,WAITRX		;DEC. PROG SIZE CNTR (1st BYTE)
						;IF ENTIRE PROG NOT LODED, CONT.
		LDA	DATASIZ	                ;IF SIZE OF DATA TO BE PROGRAMMED
		LDHX	FRSTADR
                BSR     JMASSERASE
DUMP:		BSR	DUMPROW
		BRA	LDDATA
;***********************************************************************************
; NAME: DUMPROW
; PURPOSE: DUMPS THE ENTIRE 64-BYTE ROW THAT THE START ADDR IS IN
; ENTRY CONDITIONS: H-X CONTAINS THE NEXT ADDR TO BE PROGRAMMED
; EXIT CONDITIONS: NONE
; SUBROUTINES CALLED: ERACHK
; EXTERNAL VARIABLES USED:
; DESCRIPTION: EXECUTED OUT OF RAM
;***********************************************************************************
DUMPROW:	LDHX	FRSTADR	                ;PUT FIRST ADDR IN H-X
		TXA
		AND	#$$C0			;PUT ON ROW BOUNDARY
		TAX
RDBYTE:	LDA	,X
WAITTX:
		JSR	PUT_BYTE		;SEND OUT PTA0
		NOP
		NOP
		NOP
		NOP
		NOP
		NOP
		INCX				;MOVE TO NEXT ADDRESS
		TXA
		AND	#$$3F
		BNE	RDBYTE                  ;IF NOT FINISHED, CONTINUE
ENDDUMP:	RTS
;***********************************************************************************
; FOLLOWING IS RELOCATABLE, DEPENDING ON WHERE THE PAGE BREAK FOR THE
; STACK IS TO BE LOCATED. MUST PLACE IT SO THAT THE BRANCH TO THE NEXT
; PAGE IS AT LEAST PAST $$FF.
JERASE:         BSR	ERASEIT		        ;NEED A 1/2 BRANCH HERE
LASTBYTE:	RTS
;
;		.org	LASTBYTE+STCKSIZ	;STCKSIZ NEEDS TO BE SET AS EQUATE
                .ds STCKSIZ
;***********************************************************************************
JMASSERASE:       BSR     MASSERASE
                RTS
ERASEIT:	LDHX	FRSTADR	                ;RELOAD ADDRESS IN CASE ENTRY WAS AT ERASEIT
		RTS
;***********************************************************************************
; NAME: MASSERASE
; PURPOSE: PROGRAMS A PAGE (8 BYTES) OF FLASH
; ENTRY CONDITIONS: H-X REG. LOADED WITH FIRST ADDRESS TO BE
; PROGRAMMED; Programs data in DATARAY
; EXIT CONDITIONS: NONE
; SUBROUTINES CALLED: DELNUS
; EXTERNAL VARIABLES USED:
; DESCRIPTION: EXECUTED OUT OF RAM
;
; 1. Set both the ERASE bit, and the MASS bit in the FLASH control
;    register.
; 2. Read from the FLASH block protect register.
; 3. Write any data to any FLASH address* within the FLASH memory
;    address range.
; 4. Wait for a time, tnvs (min. 10µs)
; 5. Set the HVEN bit.
; 6. Wait for a time, tMErase (min. 4ms)
; 7. Clear the ERASE bit.
; 8. Wait for a time, tnvhl (min. 100µs)
; 9. Clear the HVEN bit.
;10. After a time, trcv (min. 1µs), the memory can be accessed again in
;    read mode.
;
; Osc = 9,8304 MHz Bus CLK = 2.45 MHz -> Cycle = 408 nS
; 5µs -> 13 Cycles
; 10µs -> 25 Cyles
; 30µs -> 74 Cycles
;
;***********************************************************************************
MASSERASE:        PSHA				;(A) SAVE CONTENTS OF ACCUMULATOR
;
; 1. Set both the ERASE bit, and the MASS bit in the FLASH control
;    register.
		LDA	#ERASE.+MASS.      ;SET PGM BIT
		STA	FLCR			;<1> WRITE THIS TO THE FLASH CONTROL REG.
; 2. Read from the FLASH block protect register.
		LDA	FLBPR		        ;<2> READ FROM BLOCK PROT. REG.
; 3. Write any data to any FLASH address* within the FLASH memory
;    address range.
		STA	,X			;<3> STORE DATA TO ADDR SPEC. BY H-X (the first byte to program)
; 4. Wait for a time, tnvs (min. 10µs)
		BSR	DEL10
; 5. Set the HVEN bit.
		LDA	#ERASE.+HVEN.+MASS.       ;SET PGM AND HVEN BIT
		STA	FLCR			;<1> WRITE THIS TO THE FLASH CONTROL REG.
; 6. Wait for a time, tMErase (min. 4ms)
		BSR	DEL4M
; 7. Clear the ERASE bit.
		LDA	#HVEN.+MASS.              ;SET HVEN BIT (CLEAR PGM)
		STA	FLCR			;<1> WRITE THIS TO THE FLASH CONTROL REG.
; 8. Wait for a time, tnvhl (min. 100µs)
		BSR	DEL100
; 9. Clear the HVEN bit.
		CLRA                            ;CLEAR ALL PROGRAMMING BITS
		STA	FLCR			;<1> WRITE THIS TO THE FLASH CONTROL REG.
;10. After a time, trcv (min. 1µs), the memory can be accessed again in
;    read mode.
                PULA				;(A') RESTORE ACCUM
                RTS
;
DEL4M:          LDX     #40         ; 40 * 100µs
DEL4ML:         BSR     DEL100      ; 100µs Delay
                DBNZX   DEL4ML
                RTS
;
DEL100:         BSR     DEL10                   ; 10
                BSR     DEL30                   ; 40
                BSR     DEL30                   ; 70 (+ 30 = 100)
DEL30:
                BSR     DEL10                   ; 4
                BSR     DEL10                   ; 4
DEL10:
                BSR     DEL5                    ; 4
DEL5:
                NOP
                NOP
                NOP
                NOP
                NOP
                NOP
                RTS                             ; 4 (+ 4 = BSR)


