📄 nios2_germs_monitor.s
字号:
MOVUI r7, 31
BR getHexEntry1 # dive in with user's r6 and 31 char limit
GetHex:
MOVUI r7, 31 # maximum character count
GetHexBytes: # entry point to use r3 to signifiy byte count
MOVUI r6, CR # default return-break char
getHexEntry1:
ADD r7, r7, r7 # double for chars
MOV r23, ra # save return address
MOV r5, r0 # result
getNextHex:
MOV r3, r5 # come here after a hyphen, too
MOV r5, r0 # result
getHexLoop:
CALL GetChar
ADDI r18, r18, 1 # bump char count
CMPEQI r15, r4, '-' # hyphen separated pair...
BNE r0, r15, getNextHex
BEQ r4, r6, getHexDone # user-passed return character? then we're done!
CMPEQI r15, r4, CR # if carriage return, we're done, yay!
BNE r0, r15, getHexDone
ADDI r7, r7, -1 # decrement char count
ANDI r15, r4, 0b1000000 # bit 6 indicates alpha char
BEQ r0, r15, NoAlphaChar
ADDI r4, r4, 9 # if so, move up to 10-15
NoAlphaChar:
ANDI r4, r4, LOW_NIBBLE_MASK # mask out low nibble
SLLI r5, r5, 4
ADD r5, r5, r4 # last or not, add in the last nibble
BNE r0, r7, getHexLoop # loop if this was not the last character
getHexDone:
SRLI r18, r18, 1 # turn char count to byte count
JMP r23 # return
# End GetHexUntil/GetHex
###############################################################################
.if GM_WIDTHS
#----------------------------
# Stash16 -- either
# do a sthio
# or pass it off to flashwrite
Stash16:
.ifdef GM_FlashTop
MOV r3, ra # stash return address, deeper than usual!
CALL InFlashRange
BNE r0, r15, FlashWrite16
STHIO r5, 0(r21)
JMP r3
.else
STHIO r5, 0(r21)
RET
.endif
.endif
#-----------------------------------
# Stash byte routine shared
# by S-records and 'W' command
#
# Store byte r5 into address r21
# and don't corrupt anything important
#
StashByte:
MOV r3, ra # stash return address, deepter than usual!
.ifdef GM_FlashTop
CALL InFlashRange
BEQ r0, r15, stashByteRAM
#-------------------------------
# We're storing to flash here...
ANDI r5, r5, 0xFF # always clear out the high bits
BR1 r15, r21, 0, FlashWrite # odd address? then
# do the the Flash Write routine
MOV r11, r5 # save the low byte
JMP r3 # return
FlashWrite:
SLLI r5, r5, 8
OR r5, r5, r11 # r5 is word to write, r21 is address+1
FlashWrite16: # r3 must have return address already...
#
# At this point, r5, has a halfword to write,
# r21 is the halfword address+1
#
# call C routine to write a word to flash
# At this point, r5 has a word to write,
# r21 is the word address
MOV r6, r5
#
# When doM calls us, the address is definitely even
# When doS (S-record) calls us, the address is always on the
# odd phase, as it goes byte-by-byte.
#
# clear the low bit to force it to be the next-lowest even.
#
ANDHI r15, r21, 0xffff
ANDI r5, r21, 0xfffe
OR r5, r5, r15
CALL germs_write16
BNE r0, r2, flashWriteFail # succeeded?
JMP r3
flashWriteFail:
MOVUI r4, '!'
CALL PutChar
JMP r3
stashByteRAM:
.endif # if not handling flash case...
STBIO r5, 0(r21) # actualy stash the byte
JMP r3 # return
# +------------------------------------
# | For systems with flash memory only
# |
.ifdef GM_FlashTop
# +-------------------------------------
# | InFlashRange(address in r21)
# |
# | Return r15 nonzero if r21 in flash range.
# | else zero.
# |
InFlashRange:
MOVIK32 r15, GM_FlashBase # checking to see if below flash base
BLTU r21, r15, OutofRange
MOVIK32 r15, GM_FlashTop # checking to see if above flash top
BLTU r21, r15, InRange
OutofRange:
MOV r15, r0 # out of range: return 0
InRange:
RET # in range: return (nonzero) flashtop
.if 1
# ========================================
# | Asm versions of flash routines,
# | for a particular chip: amd29lv065d
# |
# +------------------------------
# | germs_erase_sector(address within flash in r5)
# |
# | use r15 for flash base
# | use r16 for temp bytes
# |
.macro _flash_put_byte _offset,_value
MOVI r16,\_value
STBIO r16,\_offset(r15)
.endm
germs_erase_sector:
MOVIK32 r15,GM_FlashBase
# | magic dance for erase sector
_flash_put_byte 0x555,0xAA
_flash_put_byte 0x333,0x55
_flash_put_byte 0x555,0x80
_flash_put_byte 0x555,0xAA
_flash_put_byte 0x333,0x55
# | tell chip the address to erase by
# | writing 0x30 to that address
MOVI r16,0x30
STBIO r16,0(r5)
# | wait for 0xff to show up at that address,
# | but only check approximately a zillion times
MOVI r15,0 # watchdog counter 4 billion
wait_for_erase:
ADDI r15,r15,1
BEQ r15,r0,erase_done # watchdog hit zero again
LDBIO r16,0(r5) # sign extends the single byte...
ADDI r16,r16,1 # will be 0x00000000 if we got 0xff
BNE r16,r0,wait_for_erase
erase_done:
MOV r2,r16 # return code: 0 is OK, anything else bad
RET
# +--------------------------------
# | germs_write16(address within flash:r5, 16-bit value:r6)
# |
germs_write16:
MOV r9,ra # stash return address to r2
CALL germs_write8
BNE r0,r2,germs_write16_done
ADDI r5,r5,1
SRLI r6,r6,8
CALL germs_write8
germs_write16_done:
JMP r9
# +---------------------------------
# | germs_write8(address within flash:r5, 8-bit value:r6)
germs_write8:
MOVIK32 r15,GM_FlashBase
ANDI r17,r6,0x000000ff # r17 has just the 8 bits
_flash_put_byte 0x555,0xAA
_flash_put_byte 0x333,0x55
_flash_put_byte 0x555,0xa0
STBIO r17,0(r5)
# reuse r15 now...
MOVHI r15,20 # watchdog counter
wait_for_write8_done:
LDBUIO r16,0(r5) # read byte back out of flash
BEQ r17,r16,write8_done # stopped changing?
ADDI r15,r15,-1
BNE r15,r0,wait_for_write8_done # watchdog hit zero again
write8_done:
CMPNE r2,r16,r17 # return 0 for ok, or 1 for bad
RET
.else
# ========================================
# | Invoke C versions of flash routines
# +------------------------------
# | germs_erase_sector(address within flash in r5)
# |
germs_erase_sector:
MOVI r4,-1
MOVI32 r15,nr_flash_erase_sector
BR call_c_routine
# +--------------------------------
# | germs_write16(address within flash:r5, 16-bit value:r6
# |
germs_write16:
MOVI r4,-1
MOVI32 r15,nr_flash_write
BR call_c_routine
# +----------------------------------
# | handy means to call C routine from
# | germs. Note: the full C environment
# | is *far* from complete here. You get
# | a stack and that's it. No globals,
# | no printf or device drivers, &c.
# |
call_c_routine:
#
# r15 should have the address to call and
# arguments in r5 and r6. All flash routines
# want nasys_main_flash in r4, with -1 indicating
# default, so we put that into r4 every time.
#
ADDI sp, sp, -124 # save all the registers. we are like that.
STWIO r1, 0(sp)
STWIO r2, 4(sp)
STWIO r3, 8(sp)
STWIO r4, 12(sp)
STWIO r5, 16(sp)
STWIO r6, 20(sp)
STWIO r7, 24(sp)
STWIO r8, 28(sp)
STWIO r9, 32(sp)
STWIO r10, 36(sp)
STWIO r11, 40(sp)
STWIO r12, 44(sp)
STWIO r13, 48(sp)
STWIO r14, 52(sp)
STWIO r15, 56(sp)
STWIO r16, 60(sp)
STWIO r17, 64(sp)
STWIO r18, 68(sp)
STWIO r19, 72(sp)
STWIO r20, 76(sp)
STWIO r21, 80(sp)
STWIO r22, 84(sp)
STWIO r23, 88(sp)
STWIO r24, 92(sp)
STWIO r25, 96(sp)
STWIO r26,100(sp)
STWIO r27,104(sp)
STWIO r28,108(sp)
STWIO r29,112(sp)
STWIO r30,116(sp)
STWIO r31,120(sp)
# |
# | call the C routine
# |
CALLR r15
# |
# | Restore registers and clean up stackframe
# |
# | All these registers are yours, except
# | r2. Attempt no landings there. r2 is for
# | the return value.
# |
LDWIO r1, 0(sp)
# LDWIO r2, 4(sp) It's the return value, leave intact.
LDWIO r3, 8(sp)
LDWIO r4, 12(sp)
LDWIO r5, 16(sp)
LDWIO r6, 20(sp)
LDWIO r7, 24(sp)
LDWIO r8, 28(sp)
LDWIO r9, 32(sp)
LDWIO r10, 36(sp)
LDWIO r11, 40(sp)
LDWIO r12, 44(sp)
LDWIO r13, 48(sp)
LDWIO r14, 52(sp)
LDWIO r15, 56(sp)
LDWIO r16, 60(sp)
LDWIO r17, 64(sp)
LDWIO r18, 68(sp)
LDWIO r19, 72(sp)
LDWIO r20, 76(sp)
LDWIO r21, 80(sp)
LDWIO r22, 84(sp)
LDWIO r23, 88(sp)
LDWIO r24, 92(sp)
LDWIO r25, 96(sp)
LDWIO r26,100(sp)
LDWIO r27,104(sp)
LDWIO r28,108(sp)
LDWIO r29,112(sp)
LDWIO r30,116(sp)
LDWIO r31,120(sp)
ADDI sp, sp, 124
RET
.endif # use_asm_routines or c routines
.endif # GM_FlashTop
# |
# | This used to be tucked within the code up above.
# | It's down here, now, for two reasons, one good
# | and one bad.
# |
# | The good reason: we no longer have to branch
# | over it! this saves us a branch instruction.
# |
# | The bad reason: due to an assembler bug
# | in the first release of the Nios II tool
# | chain, we cannot have arbitrary .align
# | directives in a .text section. (data
# | sections are ok, though.)
# |
systemNameString:
nm_monitor_string # include monitor name string
.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
.asciz "There is no monitor here."
.endif
# End of file
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -