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

📄 ts101_prom.asm

📁 ADSP TS101 加载核。加载核在dsp上电或复位时从flash中加载应用程序
💻 ASM
字号:
/*********************************************************************************************** 		
	TigerSHARC eprom boot loader

	TS101_prom.asm

	This code is written unoptimized one instruction per line for clarity.

  	Revision history:

    	11/12/01  Boris Lerner 			Version	1.0.0 
    	3/25/2002  Boris Lerner 		Version	1.0.1	Added (NP) to all jumps

	Algorithm description:

		1. This boot loader resides in the eprom/flash memory 0x0000 - 0x03ff. It gets loaded 
		by DMA0 of the TigerSharc initially into memory 0x00000000 - 0x000000ff. After the 
		boot loader	is loaded, the DMA0 interrupt wakes the TigerSharc up and starts the
		execution of the loader at location 0x00000000. At this stage, the TigerSharc is at
		interrupt level of DMA0 and, thus, further DMA0 and global (PMASK[60]) interrupts 
		are disabled.

		2. The loader sets the NMOD bit in SQCTL register to insure supervisor mode. Then, 
		RDS reduces interrupt to subroutine level. Now, DMA0 and global interrupts are 
		enabled	again.

		3. DMA0 interrupt vector is set to dma_int. DMA0 is setup to move data from boot 
		prom starting at 0x0400 (0x0000-0x03ff was the boot loader) to internal memory 
		starting at 0x00000000. The DMA routine will start the DMA by programming the TCBs, 
		advance the prom pointer and sit in IDLE until the DMA interrupt wakes it up and 
		sends to dma_int. There RTI returns to DMA routine, which, in turn, returns to 
		loader execution.
		
		4. Since this is not a link port boot, all link port controls are reset and	link port 
		DMAs are disabled.

		5. Processor ID is computed and stored in xR10.

		6. Now, the loader parses the blocks of data from the prom. Two words are moved to
		locations 0x00000000 and 0x00000001. These are the tag words of the block to follow.
		In the first word, bits 31:30 are block TYPE (0=final init, 1=non-zero init, 2=zero init),
		bits 29:27 are the processor ID, bits 26:16 are reserved and bits 15:0 are the block 
		COUNT. The second tag word is pointer to DESTINATION.

		7. ID of the block is compared to the ID stored in xR10. If IDs are not the same, the
		prom block is skept.

		8. If IDs are the same, the type is examined.

		9. If type is 1, the COUNT number of words are moved one word at a time via location
		0x00000000 to the DESTINATION. Once finished, the steps starting with 5 are repeated.
 
		10. If type is 2, the COUNT number of zeros are moved to the DESTINATION. Once finished, 
		the steps starting with 5 are repeated.

		11.If type is 0, the loader performs the final init, i.e. it overwrites itself with 
		the user code. A DMA of 256 words into 0x00000000-0x000000ff with wake up from IDLE
		would do this, but would start user code execution at interrupt level of DMA0. To
		avoid this, the following algorithm is used:

			a. First four instrucions of user code (destined to locations 0x00000000-0x00000003)
			are DMAed from the prom and stored in the registers xR11:8.

			b. The following code is written into locations 0x00000000-0x00000003:

				RETI = 0;;
				NOP;;
				RTI (NP); Q[j31+=0] = xR11:8;;

			c. The DMA0 interrupt vector is set to 0x00000000.

			d. yR0 is preset to 0x80000000. This will be the new value for IMASKH to disable
			all interrupts except emulation.

			e. Branch Target Buffer is invalidated (BTBINV) to clear cached branches.

			f. The DMA is setup to transfer 252 words of user code destined to
			0x00000004-0x000000ff.

			g. DMA is started by writing to the TCBs and then processor goes IDLE.

			h. When the DMA is finished, interrupt wakes the TigerSharc up and jumps
			execution to code inserted at 0x00000000 in step b.

			i. This code executes IMASKH = yR0;; which disables all global interrupts, then
			RTI (NP); Q[j31+=0]=xR11:8;;, which reduces the interrupt level to none, puts user
			code into locations 0x00000000-0x00000003 and jumps execution to 0x00000000 (since
			RETI is set to 0x00000000). The user code starts cleanly at 0x00000000, with no
			interrupt level. Note that (NP) option is necessary so that RTI does not cache into
			BTB.

***********************************************************************************************/

/**********************************************************************************************/
.section seg_ldr;

/************************************** Start of code *****************************************/
_main:
	xr0 = 0x00000201;;					// set NMOD and BTB enable (1/24/00) bits in sequencer control register
	SQCTLST = xr0;;						// mnemonic changed to SQCTLST (12/19/00)
	rds;;								// reduce interrupt to subroutine level

										// INSERT CUSTOM INITS HERE - DRAM REGISTERS ETC...
	
	jL0 = 0;;
	jL1 = 0;;
	j0 = _dma_int;;						// set DMA interrupt vector
	IVDMA0 = j0;;						// global and DMA0 ints are already enabled

	yr0 = 0;;							// will be used for zero init and ints disable in patch
	LCTL0 = yr0;;						// Links disable and clear 
	LCTL1 = yr0;;
	LCTL2 = yr0;;
	LCTL3 = yr0;;

	xr1 = 0x00040004;;					// count = 4, modify = 4
	xr3 = 0x00000000;;					// disable DMA, int mem,prio=norm,2D=no,word=quad,int=yes,RQ=enbl,chain=no
	DC4 = xr3:0;;						// disable DMA
	DC5 = xr3:0;;						// disable DMA
	DC6 = xr3:0;;						// disable DMA
	DC7 = xr3:0;;						// disable DMA
	DC8 = xr3:0;;						// disable DMA
	DC9 = xr3:0;;						// disable DMA
	DC10 = xr3:0;;						// disable DMA
	DC11 = xr3:0;;						// disable DMA
	
	xr0 = 0x400;;						// xr0 = source index
	xr3 = 0xc3000000;;					// boot rom,prio=norm,2D=no,word=norm,int=yes,RQ=dsbl,chain=no
	xr4 = 0;;							// xr4 = destination index
	xr7 = 0x43000000;;					// int mem,prio=norm,2D=no,word=norm,int=yes,RQ=dsbl,chain=no
	xr8 = 1;;
	xr10 = SYSTAT;;
	xr1 = 0x00000007;;
	xr10 = r1 and r10;;					// xr10 = processor ID									

/**********************************************************************************************/
_boot_loop:	
	xr1 = 0x00020004;;					// source count = 2, modify = 4
	xr5 = 0x00020001;;					// dest count = 2, modify = 1
	xr9 = 8;;							// prom pointer modifier

	call _do_dma (NP);;					// do DMA transfer	
	
	xr2 = [j31+=0];;					// read ID, type and count
	j0 = [j31+1];;						// read destination

	xr1 = 0x0000FFFF;;
	xr9 = r1 and r2;;					// mask count
	xr6 = 0x00001B03;;
	xr6 = fext r2 by r6;;				// extract processor ID
	xcomp(r6,r10);;						// if not same...
	if nxaeq, jump _wrong_id (NP);;		// ...skip the block...
	xr6 = 0x00001E02;;
	xr6 = fext r2 by r6;;				// ...else, extract type
	if xseq, jump _final_init (NP);;	// if zero - final init...(xseq - 1/24/00)
 	xr6 = r6 - r8;;						// ...else if 1...
	if xaeq, jump _init_data (NP);;		// ...non-zero data init...

/***********************************************************************************************/
_zero_init:								// ...else zero-data init
	LC0 = xr9;;							// put count into counter

_zero_init_loop:
		[j0+=1] = yr0;;					// init with 0's
		if NLC0E, jump _zero_init_loop (NP);;

	jump _boot_loop (NP);;				// check next block
	
/***********************************************************************************************/
_init_data:
	LC0 = xr9;;							// put count into loop counter
	xr1 = 0x00010004;;					// source count = 1, modify = 4
	xr5 = 0x00010001;;					// dest count = 1, modify = 1
	xr9 = 4;;							// prom pointer modifier

_init_data_1:
	call _do_dma (NP);;					// do DMA transfer	
	xr6 = [j31 += 0];;					// read word
	[j0 += 1] = xr6;;					// write word
	if NLC0E, jump _init_data_1 (NP);;
	jump _boot_loop (NP);;				// check next block

/***********************************************************************************************/
_wrong_id:
	xr6 = 0x000001E02;;
	xr6 = fext r2 by r6;;				// extract type
	if xseq, jump _skip_255 (NP);;		// if zero - final init, skip 255... seq replaced by xseq (3/29/00)
	xr9 = lshift r9 by 2;;				// ...else, quadrupple the count...
	xr6 = r6 - r8;;						// ...if 1...
	if xaeq, jump _skip_block (NP);;	// ...skip block as is...
    xr9 = 0;;							// ...else zero init, skip none
   	jump _skip_block (NP);;

_skip_255:
	xr9 = 0x3FC;;						// prom pointer modifier = 255*4

_skip_block:
	xr0 = r0 + r9;;						// advance prom pointer
	jump _boot_loop (NP);;				// check next block

/**************************************************************************************************
	This routine transfers data via DMA0
		Input: xr3:0 = source TCB setup, xr7:4 = destination TCB setup, xr9 = prom pointer modifier
***************************************************************************************************/
_do_dma:
	DCS0 = xr3:0;;						// start DMA
	DCD0 = xr7:4;;
	idle;;								// wait till DMA interrupt
	xr0 = r0 + r9;;						// advance prom pointer
	cjmp (NP)(ABS);;					// and return

/*************************************************************************************************
	DMA0 ISR
*************************************************************************************************/
_dma_int:
	nop;;								// Note: RTI can not be the first instruction of an ISR!
	rti (ABS)(NP);;

/*************************************************************************************************
	 Final Init 
*************************************************************************************************/
_final_init:
	xr9 = 4;;							// since final init has only one tag,...
	xr0 = r0 - r9;;						// ...backup one word (4 bytes)
	xr1 = 0x00040004;;					// source count = 4, modify = 4
	xr5 = 0x00040001;;					// dest count = 4, modify = 1
	xr9 = 16;;

	call _do_dma (NP);;					// do DMA transfer
	
	xr11:8 = Q[j31 += 0];;				// put first four user instrucions into xr11:8

	j0 = _last_patch_code;;				// move patch into locations 0x00000000-0x00000003
	j1 = 0;;
	LC0 = 4;;

_patch_loop:
	xr6 = [j0 += 1];;
	[j1 += 1] = xr6;;
	if NLC0E, jump _patch_loop (NP);;

	j1 = 0;;							// set DMA0 int vector to 0x00000000
	IVDMA0 = j1;;						
	yr0 = 0x80000000;;					// IMASKH value - disable all ints except emulation
	xr1 = 0x00FC0004;;					// count = 0xFC, modifier = 4
	xr4 = 4;;							// start at location 0x4, patch is at loc 0x0-0x3
	xr5 = 0x00FC0001;;					// count = 0xFC, modifier = 1
	btbinv;;   							// invalidate cache
	DCS0 = xr3:0;;						// start DMA
	DCD0 = xr7:4;;						
	idle;;								// wait till dma is done...
										// ...by which time DMA0 interrupt takes over,...
										// ...and jumps execution to 0x0 to the last patch
										
/*********************************** Last Patch *************************************************/	
_last_patch_code:
	RETI = 0;;							// set RETI to 0x0 for patch
	IMASKH = yr0;;						// disable interrupts
	rti (ABS)(NP); Q[j31+=0] = xr11:8;;		// reduce interrupt and patch
	
	nop;;
	nop;;
	nop;;
	nop;;
	nop;;
	

⌨️ 快捷键说明

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