;*****************************************************************************
; File Name:	SFLSH_B0.ASM  
; Project:	F240 Serial Boot loader
; Originator:	TMS320F24x Applications Group, Texas Instruments.
;
; Target Sys:	
;
; Description:	Serial Boot loader using an Intelligent Windows based PC Host
;		communicating via the SCI on the target F240.
;
; Status:	Standard Release
;	      
;	      
; Last Update: 1 August,1999

;*****************************************************************************
;
;Conditional assembly directives
USER_VERSION	.set	1		;Set to 1 if for User version
					;Set to 0 if for PE version

;-----------------------------------------------------------------------------
; Debug directives
;-----------------------------------------------------------------------------
		.def	GPR0		;General purpose registers.
		.def	GPR1
		.def	GPR2
		.def	GPR3
		.def	data_buf
		.def	length
		.def	dest_addr
		.def	B2_0
		.def	B2_1
		.def	B2_2
		.def	B2_3
		.def	B2_4
		.def	B2_5
		.def	B2_6
		.def	SPAD1
		.def	SPAD2

		.def	DUMMY
		.def	DLY10
		.def	DLY100
		.def	DLY3K3
		.def	SEG_ST
		.def	SEG_END
		.def	PROTECT

		.def	FL_ADRS
		.def	FL_DATA
		.def	ERROR

;Variables for ERASE and CLEAR
		.def	RPG_CNT
		.def	FL_ST
		.def	FL_END

;Variables for PROGRAM
		.def	PRG_paddr
		.def	PRG_length
		.def	PRG_bufaddr
		.def	BYTE_MASK


		.include	C240app.h

;Miscellaneous
BUF_SADDR	.set	0330h		;Start address for Data buffer
WSGR		.set	0FFFFh
USER_START	.set	040h		;Start of User's code
VBR_MAX 	.set	09h		;# times valid char needs to be received
CRC_MAX	.set	03h		;# retries at each PLL setting before giving up.

;-----------------------------------------------------------------------------
; Variable Declarations for on chip RAM Blocks
;-----------------------------------------------------------------------------
		.bss	GPR0,1		;General purpose registers.
		.bss	GPR1,1
		.bss	GPR2,1
		.bss	GPR3,1
		.bss	stk0,1
		.bss	stk1,1
		.bss	data_buf,1
		.bss	length,1
		.bss	dest_addr,1
		.bss	PRG_paddr,1
		.bss	PRG_length,1
		.bss	PRG_bufaddr,1
		.bss	BYTE_MASK,1

		.bss	B2_0,1
		.bss	B2_1,1
		.bss	B2_2,1
		.bss	B2_3,1
		.bss	B2_4,1
		.bss	B2_5,1
		.bss	B2_6,1
		.bss	SPAD1,1
		.bss	SPAD2,1

		.bss	DUMMY,1
		.bss	DLY10,1
		.bss	DLY100,1
		.bss	DLY3K3,1
		.bss	SEG_ST,1
		.bss	SEG_END,1
		.bss	PROTECT,1

		.bss	FL_ADRS,1	;Flash load address.
		.bss	FL_DATA,1	;Flash load data.
		.bss	ERROR,1 	;Error flag register.

;Variables for ERASE and CLEAR
		.bss	RPG_CNT,1	;Program pulse count.
		.bss	FL_ST,1 	;Flash start addr/Seg Cntrl Reg.
		.bss	FL_END,1	;Flash end address.

;Misc variables
		.bss	VBR_CNTR,1
		.bss	DELAY,1
		.bss	CHAR_RETRY_CNTR,1

;-----------------------------------------------------------------------------
; M A C R O - Definitions
;-----------------------------------------------------------------------------
SBIT0		.macro	DMA, MASK	;Clear bit Macro
		LACC	DMA
		AND	#(0FFFFh-MASK)
		SACL	DMA
		.endm

SBIT1		.macro	DMA, MASK	;Set bit Macro
		LACC	DMA
		OR	#MASK
		SACL	DMA
		.endm

KICK_DOG	.macro			;Watchdog reset macro
		LDP	#00E0h
		SPLK	#05555h, WD_KEY
		SPLK	#0AAAAh, WD_KEY
		LDP	#0h
		.endm

POINT_0 	.macro
		LDP	#00h
		.endm

POINT_B0	.macro
		LDP	#04h
		.endm

POINT_B1	.macro
		LDP	#06h
		.endm

POINT_PF1	.macro
		LDP	#0E0h
		.endm

;==============================================================================
; Start here after Reset - NOTE: NO reset vector!
;==============================================================================
		.text
START:
		POINT_0

		.if (USER_VERSION)
		BCND	USER_START, BIO 	;If BIO=0 go to User's code
		.endif				;Else continue with Flsh prg.

		SETC	INTM			;Disable interrupts
		SPLK	#0h, IMR		;Mask all Ints
		SPLK	#0FFh, IFR		;Clear all Int flags
		CLRC	SXM			;Clear Sign Extension Mode
		CLRC	OVM			;Reset Overflow Mode
		CLRC	CNF			;Config Block B0 to Data
		CLRC	XF			;set XF low (used to assert CTS on EVM 0nly)


		POINT_PF1
		SPLK	#006Fh, WD_CNTL		;Disable WD if VCCP=5V
		KICK_DOG

		B	UART_INIT

;PLL & BAUD param table
PARAM_TBL	.word	0060h		;PLL x 1 mode
		.word	0020h  ;20MHz	Baudrate value for BRR
		.word	00AAh		;PLL x 1.5 mode
		.word	001Ch  ;12MHz
		.word	00B1h		;PLL x 2.0 mode
		.word	0020h  ;10MHz
		.word	00CCh		;PLL x 2.5 mode
		.word	0020h  ; 8MHz
		.word	00D2h		;PLL x 3.0 mode
		.word	001Ch  ; 6MHz
		.word	00E3h		;PLL x 4.0 mode
		.word	0020h  ; 5MHz
		.word	00EDh		;PLL x 4.5 mode
		.word	001Ch  ; 4MHz
		.word	00E4h		;PLL x 5.0 mode
		.word	001Ch  ; 3.58MHz
		.word	00F5h		;PLL x 9.0 mode
PARAM_TBL_END	.word	001Ch  ; 2MHz

;===========================================================================
;Uart Initialisation
;===========================================================================
UART_INIT:
	;Copy Parameter table to B1
		POINT_B1
		MAR	*, AR1
		LAR	AR1, #BUF_SADDR
		LACC	#PARAM_TBL_END
		SUB	#PARAM_TBL
		SACL	GPR1
		LACC	#PARAM_TBL
		RPT	GPR1
		TBLR	*+

		SPLK	#0h, VBR_CNTR		;Clear valid baud rate counter
		SPLK	#0h, CHAR_RETRY_CNTR	;Clear retry counter
		SPLK	#0FFFFh, DELAY

		POINT_PF1
		SPLK    #0017h, SCI_CCNTL     ;One stop bit, No parity, 8 char/byte
		SPLK    #0013h, SCI_CNTL1     ;Enable TX, RX, internal SCICLK 
							;Disable RX ERR, SLEEP, TXWAKE
	;Enable TXD & RXD pins
		SPLK    #0022h, SCI_PORT_C2      
	
	;Disable RX & TX INTs                                
		SPLK    #0000h, SCI_CNTL2       
	
;===========================================================================
;Baudrate lock protocol with Host
;===========================================================================
	;Set PLL to x1 mode initially
		LAR	AR1, #BUF_SADDR
UI00		CALL	SET_CLOCK

UI01		BIT	SCI_RX_STAT, 9	;Test RXRDY bit
		BCND	UI01, NTC		;If RXRDY=0,then repeat loop
		LACC	SCI_RX_BUF		;First byte is Lo byte

	;Check if Char is as expected
CHECK_CHAR	AND	#0FFh			;Clear upper byte
		SUB	#00Dh			;Compare with "CR"
		BCND	BAUD_RETRY, NEQ

INC_VBRC	POINT_B1
		LACC	VBR_CNTR		;Inc VBR counter
		ADD	#1h
		SACL	VBR_CNTR
		SUB	#VBR_MAX		;Is VBR counter > max value ?
		POINT_PF1
		BCND	UI01, NEQ		;No! fetch another char

SND_ECHO	LACC	#0AAh			;Yes!
		SACL	SCI_TX_BUF		;Indicate to Host Baudrate locked
		B	FLSH_INIT

BAUD_RETRY	POINT_B1
		SPLK	#0h, VBR_CNTR
		LACC	CHAR_RETRY_CNTR	;Inc CRC counter
		ADD	#1h
		SACL	CHAR_RETRY_CNTR
		SUB	#CRC_MAX		;Is CRC > max value ?
		BCND	INC_TBL_PTR, GEQ	;Yes! try next baudrate
		POINT_PF1
		B	UI01			;No! fetch another char

INC_TBL_PTR
	 	MAR	*+,AR1
		SPLK	#0h, CHAR_RETRY_CNTR
		B	UI00

;===========================================================================
;Init Flash parameters
;===========================================================================
FLSH_INIT	POINT_B1
		SPLK	#0h, SEG_ST		;Start addr of Flash array
		SPLK	#3FFFh, SEG_END 	;End Addr of Flash array
		SPLK	#0FF00h, PROTECT	;Enable all segments
		SPLK	#0h, ERROR		;Clear error flag
		SPLK	#0h, FL_ST		;Select Flash array 0
						; F240 only has Array 0 present
		B	XFER_KERNEL
               

;===========================================================================
; Routine Name: S E T _ C L O C K	       Routine Type: SR
;
; Description:	Assumes AR1 is pointer to PARAM_TBL in Data mem
;===========================================================================
SET_CLOCK:
		POINT_PF1
	;Configure PLL for
		SPLK	#0041h,PLL_CNTL1	;Disable PLL first
		LACC	*+
		SACL	PLL_CNTL2
		SPLK	#0081h,PLL_CNTL1	;Enable PLL			
		SPLK	#40C0h,SYSCR	;CLKOUT=CPUCLK

;		SPLK	#0013h, SCI_CNTL1	;keep SCI reset
	;Set the Baud Rate
		SPLK    #0000h, SCI_HBAUD
		LACC	*
		SACL	SCI_LBAUD
	
	;Relinquish SCI from Reset.        
		LACL    SCI_CNTL1
		OR      #20h
		SACL    SCI_CNTL1
		RET

;===========================================================================
;Transfer Comms Kernel + sequencer to B0 & set CNF=1 (i.e. B0 = FE00)
;===========================================================================
XFER_KERNEL	MAR	*, AR1
		LAR	AR1, #B0_SADDR
		LACC	#kernel_end
		SUB	#kernel_strt
		SACL	GPR1
		LACC	#kernel_strt
		RPT	GPR1
		TBLR	*+

		SETC	CNF
		B	MAIN

;===========================================================================
;M A I N   P R O G R A M 
;===========================================================================
		.sect	"kernel"
		.label	kernel_strt
MAIN:
	;Load & Execute CLEAR
M00		CALL	FETCH_HEADER
		CALL	XFER_SCI_2_PROG


		CALL	ALGO_START
		LACC	ERROR
		CALL	SEND_CHAR	;Indicate to host Clear finished.

	;Load & Execute ERASE
M01		CALL	FETCH_HEADER
		CALL	XFER_SCI_2_PROG
		CALL	ALGO_START
		LACC	ERROR
		CALL	SEND_CHAR	;Indicate to host Erase finished.

	;Load & Execute PROG
M02		CALL	FETCH_HEADER
		CALL	XFER_SCI_2_PROG

M03		CALL	FETCH_HEADER		;Get info on Data block
		LACC	dest_addr
		SACL	PRG_paddr		;Pass Flash dest addr
		LACC	length
		ADD	#01h			;adjust for actual length
		SACL	PRG_length		;Pass Data block length
		SPLK	#BUF_SADDR, PRG_bufaddr ;Pass Data buffer start addr

M04		CALL	XFER_SCI_2_DATA		;Transfer Data block to B1
		CALL	ALGO_START		;Execute PROG routine
		LACC	ERROR
		CALL	SEND_CHAR

		CALL	FETCH_SCI_WORD		;Check if more blocks to come.
		LACC	data_buf		;If non-zero, then loop
		BCND	M03, NEQ		;If zero then finish up.

DEND		B	DEND			;Stay here until reset.

;===========================================================================
; Routine Name: F E T C H _ H E A D E R	       Routine Type: SR
;
;===========================================================================
FETCH_HEADER:
		CALL	FETCH_SCI_WORD
		LACC	data_buf
		SACL	dest_addr
		CALL	FETCH_SCI_WORD
		LACC	data_buf
		SACL	length
		RET


;===========================================================================
; Routine Name: X F E R _ S C I _ 2 _ P R O G	       Routine Type: SR
;
; Description:
;
;
; Originator: David Figoli
;
; Calling Convention:
;
;   Variables		on Entry		on Exit
; ----------------------------------------------------------------
;
;
;
; ----------------------------------------------------------------
;
; History:
;
; Last Update: 07 Oct 97
;===========================================================================
XFER_SCI_2_PROG:
		MAR	*, AR0
		LAR	AR0, length
		LACC	#ALGO_START		;ACC=dest address

XSP0		CALL	FETCH_SCI_WORD
		TBLW	data_buf		;data_buff-->[ACC]
		ADD	#01h			;ACC++
		BANZ	XSP0			;loop "length" times
		RET
		
;===========================================================================
; Routine Name: X F E R _ S C I _ 2 _ D A T A	       Routine Type: SR
;
; Description:
;
;
; Originator: David Figoli
;
; Calling Convention:
;
;   Variables		on Entry		on Exit
; ----------------------------------------------------------------
;
;
;
; ----------------------------------------------------------------
;
; History:
;
; Last Update: 07 Oct 97
;===========================================================================
XFER_SCI_2_DATA:
		MAR	*, AR1
		LAR	AR0, length		;AR0 is loop counter
		LAR	AR1, #BUF_SADDR 	;Dest --> B1 RAM

XSD0		CALL	FETCH_SCI_WORD
		LACC	data_buf
		SACL	*+, AR0
		BANZ	XSD0, AR1
		RET


;===========================================================================
; Routine Name: F E T C H _ S C I _ W O R D	       Routine Type: SR
;
; Description: Version which expects Lo byte / Hi byte sequence from Host &
;              also echos byte
;===========================================================================
FETCH_SCI_WORD:
		POINT_B1
		SACL	stk0
		POINT_PF1
FSW0		BIT   SCI_RX_STAT, 9  	;Test RXRDY bit
		BCND  FSW0, NTC	      ;If RXRDY=0,then repeat loop 
		LACC	SCI_RX_BUF		;First byte is Lo byte
		SACL	SCI_TX_BUF		;Echo byte back
		AND	#0FFh			;Clear upper byte
		
FSW1		BIT   SCI_RX_STAT, 9  	;Test RXRDY bit
		BCND  FSW1, NTC	      ;If RXRDY=0,then repeat loop
		NOP				;TEST ONLY
		ADD	SCI_RX_BUF,8	;Concatenate Hi byte to Lo
		SFL				;used because 7 is max in SACH
		SACH	SCI_TX_BUF,7	;Echo byte back (after SFL 8)

		POINT_B1
		SFR				;restore ACC as before
		SACL	data_buf		;Save received word

		LACC	stk0
		RET

;==============================================================================
; Transmit char to host subroutine.
;==============================================================================
SEND_CHAR	POINT_PF1
		SACL	SCI_TX_BUF		;Transmit byte to host.
		POINT_B1
		RET

;==============================================================================
;Down-loaded algorithms start here.
;==============================================================================
ALGO_START	.word	0	
		.label	kernel_end

