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

📄 nios_germs_monitor.s

📁 ALTERA的NIOS处理器!文件直接可以打开直接选择器件重新编译!
💻 S
📖 第 1 页 / 共 2 页
字号:
	NOP
	BR	doMWrite_did
	NOP

doMWrite16:
	BSR	Stash16
	NOP

.else
	; Send in two bytes to the StashByte routine
	; so that it handles writing to flash
	BSR	StashByte
	MOV	%l6,%o1			; reserve high (later) byte
	LSRI	%l6,8
	MOV	%o1,%l6			; send the high byte
	BSR	StashByte
	ADDI	%i2,1			; (delay slot) to the next address
.endif

doMWrite_did:
	CMPI	%l7,13			; %l7 has break char from GetHex
	IFS	cc_ne
	 BR	doMWriteLoop
	ADD	%i2,%g3			; (delay slot) increment address
	BR	ReceiveCommand
	NOP

doMFill:
	MOV	%l6,%o4			; preserve low end of range
	BSR	GetHex
	MOV	%l5,%o1			; (delay slot) preserve end of range
	BSR	FillRAM
	MOV	%o3,%l6			; preserve for <CR> later
	BR	ReceiveCommand
	MOV	%l5,%o3			; restore for <CR> later to show from start of range

;--------------
; FillRAM
;
; %l6 = start, %l5 = end, %o1 = value
;

FillRAM:
fillRAMLoop:
	G_ST16	%l6,%o1
	ADDI	%l6,2			; go by twos and hit every 16 bit word (nios16 _and_ 32)
	CMP	%l6,%l5
	IFS	cc_ne
	 BR	fillRAMLoop
	NOP
	JMP	%o7
	NOP

; -------------------------
; S-Record handlin'
;
doS:
	BSR	GetChar			; Fetch the record type
	NOP
	MOV	%i0,%o0			; record type stashed

	BSR	GetHexBytes
	MOVI	%o3,1				; (delay slot) Fetch record length
	MOV	%i1,%o1			; record length (including address) stashed
	SUBI	%i1,1				; decrement to ignore the checksum @ the end

	AND	%i0,%g5			; mask of low bits of presumed ascii digit
	IFS	cc_eq				; zero?
	 BR	ignoreS			; that's a kind we ignore
	CMPI	%i0,4				; data record?
	IFS	cc_lt
	BR		doS123			; yup! go do data record
	NOP
	SUBI	%i0,7				; 789->012
	IFS	cc_mi				; was a 45 or 6...
	 BR	ignoreS
	CMPI	%i0,3
	IFS	cc_lt
	BR	doS789
	NOP
ignoreS:
happyWaitForEOL:		; Ignores until the end of line, then begins anew.
	BSR	WaitForEOL
	NOP
	BR	ReceiveCommand
	NOP

doS123:
	ADDI	%i0,1				; got here with %i0 = 12 or 3, change to addr bytes
	SUB	%i1,%i0			; %i1 = number of data bytes to absorb, now
	BSR	GetHexBytes
	MOV	%o3,%i0			; (delay slot) count of bytes to get
	MOV	%i2,%o1			; %i2 = address to read into

; -----------------
; Come here with %i2 = address to read bytes into
;                %i1 = number of bytes to read
;                %l4 = forced offset (relocation) to apply to all addresses (or zero)
doSReadData:
	ADD	%i2,%l4			; Override the start address with %l4 (force address)
doSReadData1:
	BSR	GetHexBytes		; Read a byte of data
	MOVI	%o3,1			; (delay slot) bytecount = 1

	BSR	StashByte		; puts %o1 into [%i2], and does FLASH stuff if needed

	SUBI	%i1,1			; (delay slot, but OK)
	IFRnz	%i1			; zero bytes remaining?
	BR		doSReadData1	; no: loop back around
	ADDI	%i2,1			; (delay slot) bump to next byte in any case

	BR		ignoreS		; ignore the checksum, and continue onward
	NOP

doS789:
	NEG	%i0		; got here with %i0=012 for 789
	ADDI	%i0,4		; now 987->234, byte count for GO address
	BSR	GetHexBytes
	MOV	%o3,%i0		; (delay slot) bytes of address to read
	BSR	WaitForEOL	; don't do anything until the line is finished
	NOP
	BR	Go		; %o1 is ready...
	NOP

doG:
	BSR	GetHex
	NOP
Go:
	LSRI	%o1,1		; divide in half for JMP action
	CALL	%o1
	NOP
	BR	postFlash_start
	NOP

doE:
	BSR	GetHex
	NOP
	ANDN	%o1,%g6	; mask off low 2 bits if address

.ifdef GM_FlashTop
	BSR	InFlashRange
	MOV	%i2,%o1		; (delay slot, put address to check in %i2) see if it's flash
	IFS	cc_ne		; if not, just skip
	 BR	ReceiveCommand
	NOP

	;
	; Begin strange Flash-Erase sequence
	;

	BSR	flash555aa
	NOP
	BSR	flash2AA55
	NOP
	MOVIP	%g0,0x80
	BSR	flash555g0
	NOP
	BSR	flash555aa
	NOP
	BSR	flash2AA55
	NOP

; And finally tell the Flash what sector to erase...

	MOVIP	%g0,0x30
	G_ST16	%i2,%g0

; Loop until the data reads as 0xFFFF	(and we dont know whats in the high word)

.ifdef __nios32__
	BGEN	%g2,25			; watchdog timeout, an excessive number
.else
	BGEN	%g2,15			; (or a less-excessive number, scaled, on n16)
.endif

flashEraseLoop:

.ifdef __nios16__
	BGEN	%g1,10			; for nios 16, nest a loop here
flashEraseLoop_16:
	IFRnz	%g1
	 BR	flashEraseLoop_16
	SUBI	%g1,1
.endif

	IFRz	%g2
	 BR	ReceiveCommand
	SUBI	%g2,1

	LD	%g0,[%i2]
.ifdef __nios32__
	SEXT16	%g0
.endif
	ADDI	%g0,1				; IF done, %g0 == 0 now
	IFRnz	%g0
	 BR	flashEraseLoop
	NOP					; safety first

	;
	; Now, count to a million, just to be terribly sure.
	;

.ifdef __nios32__
	BGEN	%g0,20				; m32 only, eh.
.else
	BGEN	%g0,15			; (or a less-excessive number, scaled, on n16)
.endif

flashErasePostLoop:
	IFRnz	%g0
	 BR	flashErasePostLoop
	SUBI	%g0,#1				; (delay slot)

	BR	ReceiveCommand
	NOP

.endif  ; GM_FlashTop

; -------------------------
; doR: Set Relocate
; usage:
;          +r10800   <--- add 0x10800 to addresses in s-records/i-hex
;          +r40000-180000   <--- add 0x140000 to addresses in s-records/i-hex
doR:
	BSR	GetHex
	NOP
	SUB	%o1,%o4		; offset end address - start address (or just end)
	BR	ReceiveCommand
	MOV	%l4,%o1		; (delay slot)


; -----------------------
; GetChar and PutChar
; both work on %o0
; GetChar always echoes

getCharLFEcho:			; front end loopover *just* for echoing those ignored Linefeeds.
	LDP	%g0,[%l0,np_uartstatus]	; status register
	IF0	%g0,6
	 BR	getCharLFEcho
	NOP
	STP	[%l0,1],%o0		; (delay slot) send %o0 out

GetChar:
	LDP	%g0,[%l0,np_uartstatus]
	IF0	%g0,np_uartstatus_rrdy_bit	; bit 7: RRdy
	 BR	GetChar
	NOP
	LDP	%o0,[%l0,np_uartrxdata]
	CMPI	%o0,0x0A		; Ignore LF's
	SKPS	cc_ne
	BR	getCharLFEcho		; (echo the LF, but don't return it)
	CMPI	%o0,0x1B		; <ESC> restarts monitor: the only line editing.
	IFS	cc_eq
	 BR	postFlash_start
	NOP
	; and fall into PutChar for echo

.ifdef __supportGDB__
	;
	; Unless we're supporting GDB! in which
	; case, a $ immediately yanks us over
	; to the echo-less GDB parser!
	;
	; Once we get a $ and start doing GDB commands,
	; we stay in GDB mode.
	;

	CMPIP	%o0,'$'
	IFS	cc_eq
	 BR	doGDBCommand
.endif

PutChar:
	LDP	%g0,[%l0,np_uartstatus]	; status register
	SKP1	%g0,6		; bit 6: TRdy
	BR	PutChar
	NOP
	JMP	%o7
	STP	[%l0,1],%o0	; (delay slot) send %o0 out

PutHash:
	MOVIP	%o0,'#'
	BR	PutChar		; (watch out for delay slot below...)

WaitForEOL:
	MOV	%o5,%o7
waitForEOLLoop:
	BSR	GetChar
	NOP
	CMPI	%o0,0x0D
	SKPS	cc_eq
	BR	waitForEOLLoop
	NOP
	JMP	%o5
	NOP

; --------------
; PutHex %o1
;
; Prints four characters (16 bit value)
;
; Uses %o2 for shift amount
; Uses %o5 as alternate return address
;

PutHex:									; value %o1
	MOV	%o5,%o7
	MOVI	%o2,12
putHexLoop:
	MOV	%o0,%o1
	LSR	%o0,%o2
	AND	%o0,%g5
	CMPI	%o0,9
	SKPS	cc_le
	ADDI	%o0,'A'-'0'-10
	ADDIP	%o0,'0'
	BSR	PutChar
	NOP
	SKPRz	%o2
	BR		putHexLoop
	SUBI	%o2,4					; (delay slot) decrement shift amount
	JMP	%o5
	NOP

; -----------------------
; GetHex
;
; In: %o3 - number of characters to read (GetHexBytes only)
;     %o2 - character to break on, in addition to CR
;
; Out: %o1 - value read
;      %o0 - last character typed (CR or %o2 break char)
;      %g3 - number of bytes read (if caller cleared %g3 first)
;
;
; Gets hex value until CR
; returns value in %o1
; A hyphen-separated pair returns
; the 2nd on %o1, and the 1st in %o4
;
; GetHexUntil will scan hex chars until either a CR
; or the character in %o2 (still with a hyphen moving
; stuff to %o4).
;
; Return number of bytes read in %g3 (caller MUST clear
; %g3 first, for this feature to work)

GetHexUntil:
	BR		getHexEntry1	; dive in with user's %o2 and 31 char limit
	MOVI	%o3,31

GetHex:
	MOVI	%o3,31		; maximum character count
GetHexBytes:			; entry point to use %o3 to signify byte count
	MOVI	%o2,13		; default return-break char
getHexEntry1:
	ADD	%o3,%o3		; double for chars
	MOV	%o5,%o7		; return address...
	MOVI	%o1,0		; result
getNextHex:
	MOV	%o4,%o1		; come here after a hypen, too
	MOVI	%o1,0		; result'

getHexLoop:
	BSR	GetChar
	ADDI	%g3,1		; bump char count

	CMPIP	%o0,'-'		; hyphen separated pair...
	IFS	cc_eq
	 BR	getNextHex

	CMP	%o0,%o2		; user-passed return character?
	IFS	cc_eq		; go home
	 BR	getHexDone	; exit loop from here
	CMPI	%o0,13		; carriage return?
	IFS	cc_eq		; go home
	 BR	getHexDone	; exit loop from here
	SUBI	%o3,1		; decrement char count
	SKP0	%o0,6		; bit 6 indicates alpha char
	ADDI	%o0,9		; if so, move up to 10-15
	AND	%o0,%g5		; and with 0x0f.
	LSLI	%o1,4
	SKPRz	%o3		; was this the last character?
	BR	getHexLoop	; loop back if not
	ADD	%o1,%o0		; (delay slot) last or not, add in the last nibble
getHexDone:
	JMP	%o5		; return
	LSRI	%g3,1		; turn char count to byte count

;--------------------
; Return Z flag set if %i2 is in flash range.
; Trash %l1.

	.ifdef GM_FlashTop		; nonzero FlashTop means we have some flash
InFlashRange:

	.if ((GM_FlashBase==0x100000)&&(GM_FlashTop==0x200000))
	; Clever trick because flash range is [0x100000,0x200000)
	MOV	%l1,%i2
	LSRI	%l1,20
	JMP	%o7
	CMPI	%l1,1
	.else
	MOVI	%l1,1
	MOVIP	%r0,GM_FlashBase
	CMP	%i2,%r0
	IFS	cc_mi
	 MOVI	%l1,0			; out of range
	MOVIP	%r0,GM_FlashTop
	CMP	%i2,%r0
	IFS	cc_pl
	 MOVI	%l1,0			; out of range
	JMP	%o7
	CMPI	%l1,1
	.endif

	.endif

.if GM_WIDTHS
;--------------------
; Stash16 -- either
; do a st16 (or st, on nios16)
; or pass it off to flashwrite
Stash16:
 .ifdef GM_FlashTop
	MOV	%o4,%o7		; stash return address, deeper than usual!
	BSR	InFlashRange
	NOP
	IFS	cc_eq
	 BR	FlashWrite16
	NOP
	G_ST16	%i2,%o1
	JMP	%o4
	NOP
 .else
	G_ST16	%i2,%o1
	JMP	%o7
	NOP
 .endif
.endif
	 

;--------------------
; Stash byte routine shared
; by S-records and 'W' command
;
; Store byte %o1 into address %i2
; and don't corrupt anything important!
;
StashByte:
	MOV	%o4,%o7		; stash return address, deeper than usual!

	.ifdef GM_FlashTop
	BSR	InFlashRange
	NOP
	IFS	cc_ne
	 BR	stashByteRAM
	NOP
	; --------------
	; We're storing to flash here...
	IF1	%i2,0		; odd address? then do the FlashWrite routine
	 BR	FlashWrite
	EXT8s	%o1,0		; (delay slot) always clear out the high bits

	JMP	%o4		; return
	MOV	%g7,%o1		; (delay slot) save the low byte

FlashWrite:
	LSLI	%o1,8
	OR	%o1,%g7		; %o1 has word to write, and %i2 is address+1

FlashWrite16:			; %o4 must have return address already...
	; -----------
	; Begin bizarre Write Word flash sequence

	BSR	flash555aa
	NOP
	BSR	flash2AA55
	NOP
	MOVIP	%g0,0xa0
	BSR	flash555g0
	NOP

	;
	; And the actual data halfword
	;
	G_ST16	%i2,%o1

	;
	; Now, follow the AMD polling algorithm...
	;
.ifdef __nios32__
	MOVIP	%g2,0x80000	; watchdog timeout, an excessive number, n32 only (~.5M)
.else
	MOVIP	%g2,0x8000
.endif


flashWriteLoop:
	;
	; Decrement watchdog
	;
	IFRz	%g2
	 BR	flashWriteFail
	SUBI	%g2,1

.ifdef __nios16__
	MOVI	%g1,20		; add extra cycles on n16, !!! could be made a subroutine?
flashWriteLoop_16:
	IFRnz	%g1
	 BR	flashWriteLoop_16
	SUBI	%g1,1
.endif

	LD	%g0,[%i2]	; (historically, this line of code was missing for a while...)
.ifdef __nios32__
;
; On Nios 32, be sure to look only at
; the correct 16 bits
;
	EXT16d	%g0,%i2
.endif
	CMP	%o1,%g0		; match originally written data?
	IFS	cc_eq
	 BR	flashWriteOK	; yes, we're done
	NOP			; (delay slot);
	
	BR	flashWriteLoop	; no, keep trying
	NOP			; (delay slot);

flashWriteFail:
	;
	; the write failed, we shall print '!' for error.
	;
	MOVIP	%o0,'!'
	BSR	PutChar
	NOP
flashWriteOK:
	JMP	%o4
	NOP

stashByteRAM:
	.endif			; if not handling flash case...

	FILL8	%r0,%o1
	JMP	%o4		; return
	ST8d	[%i2],%r0	; (delay slot) actually stash the byte


; ----------------------------------
; particles of flash routines...
.ifdef GM_FlashTop
flash555aa:				; write aa to 555
	MOVIP	%g0,0xAA
flash555g0:					; write %r0 to 555
	MOVIP	%l1,GM_FlashBase+(2*0x555)	; magic programming address 1
flashSharedWrite:
	G_ST16	%l1,%g0		; do the store in the delay slot
	JMP	%o7				; return
	NOP

flash2AA55:					; write 55 to 2AA
	MOVIP	%g0,0x55
	MOVIP	%l1,GM_FlashBase+(2*0x2AA)	; magic programming address 2
	BR	flashSharedWrite
	NOP
.endif	; GM_FlashTop


.else	
# GM_UARTBase -- no uart, the monitor is empty
; There is no monitor here, since the system has no UART.
; Here's an infinite loop for your CPU to enjoy.
NoUART:
	BR	NoUART
	NOP
	.asciz	"There is no monitor here."
.endif


# End of file

⌨️ 快捷键说明

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