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

📄 nios_germs_monitor.s

📁 ALTERA的NIOS处理器!文件直接可以打开直接选择器件重新编译!
💻 S
📖 第 1 页 / 共 2 页
字号:
; --------------------------
; File: nios_germs_monitor.s
;
; Contents: a Nios monitor,
;           this one with S-Record, I-Hex
;           records, and Flash Programming
;           for the Nios development board.
;
;
; GermsMon is build-time configurable to
; support various Nios configurations.
; The following variables control
; how it's built:
;
;	GM_UARTBase -- base of the uart for output, presumed
;	               to be Nios compatible registers
;
;	GM_FlashBase,
;	GM_FlashTop --
;			The flash to support, unless FlashTop is zero,
;			which means "no flash". The flash is presumed
;			to be AMD 29LV800, as on the Nios reference design.
;			Other AMD flashes might be compatible.
;
;	GM_FlashExec --
;			The address in flash to check for the Nios
;			signature "Ni". Reference design uses
;			0x14000c. If the signature is found, execution
;			is transferred to GM_FlashExec - 0x0c. If
;			GM_FlashExec is zero, the feature is disabled.
;	GM_PIO --
;			The pio to check bit zero of before executing
;			from flash.
;
;	GM_VectorTable --
;			Interrupt vector table base
;	
;	GM_Clear1Base,GM_Clear1Register,
;	GM_Clear2Base,GM_Clear2Register,
;	GM_Clear3Base,GM_Clear3Register --
;			Up to three addresses which are cleared
;			when GermsMon starts up. These can be
;			used to disable interrupts on peripherals,
;			and such.
;
; To set a variable, include the directive 
;
;	--defsym GM_whatever=value
;
; on the assembler's command line. With nios-build, include
; the directive
;
;	-as "--defsym GM_whatever=value"
;
;

	.include "nios.s"

	.ifndef GM_UARTBase
	 .ifdef nasys_printf_uart
	  .equ GM_UARTBase,nasys_printf_uart
	 .else
	  #
	  # If there's no UART defined, we'll compile
	  # as IF the uart address is 0x0000.
	  # This, of course, won't be a functioning
	  # monitor, but, hey, there's no UART. What
	  # were you expecting?
	  # At least it puts some bytes in your
	  # ROM, and you can see what code looks like.
	  #
	  #.equ GM_UARTBase,0
	  # !!!
	  # The above comment is obsolete, but is preserved here
	  # for future generations to look upon, and marvel.
	  # See the bottom of this file for the code that's generated
	  # when no UART exists.
	  # !!!
	 .endif
	.endif

	.ifndef GM_FlashBase
	 .ifdef nasys_main_flash
	  .equ GM_FlashBase,nasys_main_flash
	 .endif
	.endif

	.ifdef GM_FlashBase

	 .ifndef GM_FlashTop
	  .ifdef nasys_main_flash_end
	   .equ GM_FlashTop,nasys_main_flash_end
	  .else
	   .equ GM_FlashTop,GM_FlashBase+0x100000
	  .endif
	 .endif

	 .ifndef GM_FlashExec
	  .equ GM_FlashExec,GM_FlashBase+0x4000C
	 .endif

	.endif

	.ifndef GM_StackTop
	 .equ GM_StackTop,nasys_stack_top
	.endif

	.ifndef GM_VectorTable
	 .equ GM_VectorTable,nasys_vector_table
	.endif

	.ifndef GM_PIO
	 .ifdef na_button_pio
	  .equ GM_PIO,na_button_pio
	 .endif
	.endif

	.ifndef GM_WIDTHS
	 .equ GM_WIDTHS,1
	.endif


;-----------------------------------------
; A simple macro that stores a 16 bit
; word on either the nios32 or nios16
; It uses %g0 (%r0), no foolin!

	.macro	G_ST16	rDst,rSrc
.ifdef __nios32__
	FILL16	%r0,\rSrc
	ST16d	[\rDst],%r0
.else
	ST	[\rDst],\rSrc
.endif
	.endm

;
; Mostly, this is one big goto-tangle.
;
; No RAM used
;
; Global Register Usage:
;
; %l0: UART Base Address
; %g5: the value 0x0000000F
; %g6: the value 0x00000003	for masking addresses
; %g7: residual byte for writing to Flash in words

; %g0,%g1: Any routine's scratch
; %g3    : number of bytes read by getHex routine
; %l1-%l2: Any routine's scratch
; %o5: stashed return address
;
; %l3: Upper bytes (or segment) for I-Hex records
;
; %l4: Force-to address for S-Records/I-Hex records
; This gets set by an F command
;
; %l5: Address to read next from <CR>
; %i3: How many words to display on CR
;
; --------------
; During S-Record read
;    %i0 record type
;    %i1 record length in bytes
;    %i2 address we're reading bytes into
;
;
; -------------------------------
; Commands:
; G<address>               Go at address
; E<address>               Erase flash at address
; R<address>-<address>     Relocate S-Records from-to
; M<address>               Display at address
; M<address>-<address>     Display range
; M<address>:val val...    Write at attress
; M<address>-<address>     Display range
; S...                     S-record, no error checking
; :...                     Intel-Hex record, no error checking




	.text
	.global _start
_start:
	PFX	8
	WRCTL	%g0

.ifdef GM_UARTBase

	; (previous germs monitors cleared the vector table
	; here, but it's more useful to be able to still
	; see it after you finish. Also, every byte is
	; precious, to keep it under 1k bytes! so its gone.)

	;
	; Reset UART, SwitchPIO, and Timers
	;
	MOVIP	%l0,GM_UARTBase			; we'll keep this...
	MOVI	%g0,0
	STP	[%l0,np_uartcontrol],%g0	; control all 0's: no irq's

	;
	; Clear some registers (presumably
	; to disable interrupts)
	;

	.ifdef GM_Clear1Base
	MOVIP	%l1,GM_Clear1Base
	STP	[%l1,GM_Clear1Register],%g0
	.endif

	.ifdef GM_Clear2Base
	MOVIP	%l1,GM_Clear2Base
	STP	[%l1,GM_Clear2Register],%g0
	.endif

	.ifdef GM_Clear3Base
	MOVIP	%l1,GM_Clear3Base
	STP	[%l1,GM_Clear3Register],%g0
	.endif

	.ifdef GM_PIO
	MOVIP	%l1,GM_PIO
	STP	[%l1,np_piointerruptmask],%g0
	.endif

	;
	; Set CWP to top, and IRQ to bottom
	;
	PFX	2
	RDCTL	%g0
	LSRI	%g0,1				; HI_LIMIT in correct bit position
						; Also, the topmost bit IS zero now, after LSR
	ORIP	%g0,0x7e0f			; I_PRI set to 63, NZVC all true (why not)
	WRCTL	%g0

	;
	; Set the stack pointer
	;
	.ifdef GM_StackTop
	MOVIP	%sp,GM_StackTop
	.endif

	;
	; Look for Signature in flash, & jump there.
	;
	.ifdef GM_PIO
	LDP	%g0,[%l1,np_piodata]	; Unless the button is pressed
	IF0	%g0,0
	 BR	postFlash_start
	.endif

	.ifdef GM_FlashTop
	MOVIP	%l2,GM_FlashExec	; 2nd quadrant of four, in flash, + 0xC
	LD	%g0,[%l2]
.ifdef __nios32__
	EXT16d	%g0,%l2
.endif
	CMPIP	%g0,'N'+(256*'i')
	IFS	cc_ne
	 BR	postFlash_start

	SUBI	%l2,0x000c
	LSRI	%l2,1
	CALL	%l2			; (if it wants to return, no problem!)
	.endif

postFlash_start:

	NOP				; clears out possible delay-slot PFX's

        ;;  We end up here upon exit of a user-program run with the 'G'
        ;;  command.  User-programs can do -anything-, including exitng
        ;;  with interrupts left running.  This is inconvenient when
        ;;  using the monitor.  Disable CPU interrupts as a defensive measure.
	PFX	8
	WRCTL	%g0
        
	;
	; Registers which need certain
	; values for the rest of the monitor
	; to work.
	; (Other registers are used as
	; needed, although their reservations
	; for certain uses must be respected
	; while running.)
	
	MOVIP	%l0,GM_UARTBase
	MOVI	%g5,0x0f
	MOVI	%g6,0x03

	BSR	PutHash		; but up here, so delay slot is used.
	; Initial safe values

	MOVI	%l3,0
	MOVI	%l4,0
	MOVI	%l5,0		; # address to show on <CR>
	MOVIP	%i3,32		; # words to show on <CR>


	.ifndef __timeStamp__
	.equ __timeStamp__,0
	.endif

	MOVIP	%o1,__timeStamp__
	BSR	PutHex
	NOP

	PFX	6
	RDCTL	%o1
	BSR	PutHex
	NOP
	BSR	PutChar
	MOVI	%o0,13

	#
	# Print the system name GM_SystemName, if defined
	#

	BR	pastSystemNameString
	NOP
systemNameString:
	nm_monitor_string	; include monitor name string
	.align	1		; align by 2^n
pastSystemNameString:
	MOVIA	%i2,systemNameString
printSystemNameLoop:
	LD	%o0,[%i2]
	EXT8d	%o0,%i2
	IFRz	%o0
	 BR	donePrintSystemNameLoop
	NOP
	BSR	PutChar
	ADDI	%i2,1
	BR	printSystemNameLoop
	NOP
donePrintSystemNameLoop:
	BSR	PutChar
	MOVI	%o0,13

ReceiveCommand:
	MOVIP	%o0,'+'
	BSR	PutChar
	NOP

	BSR	GetChar
	NOP

	CMPIP	%o0,0x0060		; character from [60,7f]
	IFS	cc_ge				; mapped down to [40,5f]
	 ANDNIP	%o0,0x0020

	SUBIP	%o0,13
	IFRz	%o0
	BR	doCR

		
	SUBIP	%o0,'#'-13		; '#' (hash) is for comments: ignore to EOL
	IFRz	%o0
	BR	happyWaitForEOL

	SUBIP	%o0,':'-'#'
	IFRz	%o0
	BR	doColon

	SUBIP	%o0,'E'-':'
	IFRz	%o0
	BR	doE

	SUBIP	%o0,'G'-'E'
	IFRz	%o0
	BR	doG

	SUBIP	%o0,'M'-'G'
	IFRz	%o0
	BR	doM

	SUBIP	%o0,'R'-'M'
	IFRz	%o0
	BR	doR

	SUBIP	%o0,'S'-'R'
	IFRz	%o0
	BR	doS

	NOP

errorWaitForEOL:
	BSR	WaitForEOL
	NOP

	MOVIP	%o0,'?'			; Unknown Command
	BSR	PutChar
	NOP
	BSR	PutChar
	MOVI	%o0,13

	BR		ReceiveCommand
	NOP

doColon:
	; First 2 chars: record length, for data only
	BSR	GetHexBytes
	MOVI	%o3,1			; (delay slot) Fetch record length
	MOV	%i1,%o1			; record length stashed
	;
	; Next 4 chars: address offset
	;
	BSR	GetHexBytes
	MOVI	%o3,2			; (delay slot) we want 2 byte/4 chars of hex)
	MOV	%i2,%l3			; Get most recent upper-bytes address
	OR	%i2,%o1			; construct full address into %i2

	; Get record type
	;
	BSR	GetHexBytes
	MOVI	%o3,1			; (delay slot) 1 byte/2 chars for record type

	IFRz	%o1
	BR	doSReadData		; same code as reading S-Record data
	CMPI	%o1,4			; I-Hex 4 sets upper bits of destination address
	IFS	cc_ne
	 BR	doColonNot4
	NOP

	BSR	GetHexBytes
	MOVI	%o3,2			; (delay slot) upper 16 bits is 2 bytes worth

	LSLI	%o1,16
	MOV	%l3,%o1			; and save the upper bits there...

doColonNot4:
	BR	happyWaitForEOL
	NOP

;------------------------
; M Command
; M<addr>             show 16 bytes
; M<addr>-<addr>      show range
; M<addr>:val val val write values to addr
; M<addr>-<addr>:val  fill range
;
doM:
	MOVIP	%o2,':'
	BSR	GetHexUntil
	NOP

	;
	; Write operation?
	;

	CMPIP	%o0,':'
	IFS	cc_eq
	 BR	doMWrite
	NOP
	
	;
	; If showing range, compute it...
	;
	IFRnz	%o4
	 BR	doMShowRange
	NOP

	;
	; Show %i3 words... bytes
	;
	MOV	%l5,%o1
	BR	doCR

	;
	; Show Range
	; Show from %o4 to %o1, inclusive
	;
doMShowRange:
	MOV	%o3,%o1	
	SUB	%o3,%o4
	LSRI	%o3,1			; o3 = # words
	MOV	%i3,%o3			; if they hit return, they get this many, again
	MOV	%l5,%o4			; use %l5 to walk the addresses

doCR:
	MOV	%o3,%i3			; <CR> shows %i3 words from %l5

doMShowRangeLine:
	;
	; Come here with %o3 = #words to show, %l5 = address to show
	;

	MOVI	%l6,8			; countdown for this line

	; Print #addr:
	BSR	PutHash			; (watch out for delay slot)
	;
	; print the address
	;
.ifdef __nios32__
	; nios32? Show upper 16 bits of address first.
	MOV	%o1,%l5
	LSRI	%o1,16
	SKPRz	%o1
	BSR	PutHex
	NOP
.endif
	MOV	%o1,%l5
	BSR	PutHex
	NOP
	MOVIP	%o0,':'
	BSR	PutChar
	NOP
	BSR	PutChar
	BGEN	%o0,5			; (delay slot) hex 0x20 = space

doMShowRangeLoop:
	LD	%o1,[%l5]
	BSR	PutHex
.ifdef __nios32__
	EXT16d	%o1,%l5		; (delay slot)
.else
	NOP			; (delay slot)
.endif

	MOVIP	%o0,' '
	BSR	PutChar

	;
	; Bump address and decrement to-show count
	;
	ADDI	%l5,2
	SUBI	%o3,1
	IFS	cc_le
	 BR	doneMCR

	; See if it's time for a newline
	SUBI	%l6,1
	IFRnz	%l6
	 BR	doMShowRangeLoop
	NOP

	BSR	PutChar
	MOVI	%o0,13			; (delay slot)
	BR	doMShowRangeLine
	NOP
doneMCR:
	BSR	PutChar
	MOVI	%o0,13			; (delay slot)
	BR	ReceiveCommand
	NOP
	
	
doMWrite:
	IFRnz	%o4
	 BR	doMFill
	MOV	%l5,%o1			; (delay slot, sometimes) start for next <CR> show

	;
	; Write space-separated values until CR
	;
	MOV	%i2,%o1
doMWriteLoop:
	MOVIP	%o2,' '
	BSR	GetHexUntil
	MOVI	%g3,0	; (GetHexUntil needs this to count bytes)
	MOV	%l7,%o0			; save the break-character...

.if GM_WIDTHS
	; decide which kind of write to do: 8, 16, or 32

	CMPI	%g3,2
	IFS	cc_eq
	 BR	doMWrite16
	NOP
.ifdef __nios32__
	IFS	cc_lt
	 BR	doMWrite8
	NOP

	BR	doMWrite_did
	ST	[%i2],%o1
.endif
doMWrite8:
	BSR	StashByte

⌨️ 快捷键说明

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