Line 41... |
Line 41... |
#---- UART stuff
|
#---- UART stuff
|
.set UART_BASE, 0x20000000 # UART base address
|
.set UART_BASE, 0x20000000 # UART base address
|
.set UART_TX, 0x0000 # TX reg offset
|
.set UART_TX, 0x0000 # TX reg offset
|
.set UART_STATUS, 0x0020 # status reg offset
|
.set UART_STATUS, 0x0020 # status reg offset
|
|
|
|
#---- Debug register block -- 4 read-write, 32-bit registers
|
|
.set DEBUG_BASE, 0x2000f000 # Debug block base
|
|
|
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
|
|
.text
|
.text
|
.align 2
|
.align 2
|
.globl entry
|
.globl entry
|
Line 67... |
Line 70... |
|
|
start_test:
|
start_test:
|
li $a0,0x00000002
|
li $a0,0x00000002
|
mtc0 $a0,$12 # disable interrupts and cache
|
mtc0 $a0,$12 # disable interrupts and cache
|
|
|
.ifdef TEST_CACHE # if we're going to test the I-caches then
|
.ifdef TEST_CACHE # if we're going to test the caches then
|
jal init_cache # invalidate all the I-Cache lines now
|
jal init_cache # invalidate all the I- and D-Cache lines now
|
|
nop
|
|
jal test_dcache
|
nop
|
nop
|
.endif
|
.endif
|
|
|
la $a0,msg0
|
la $a0,msg0
|
jal puts
|
jal puts
|
Line 236... |
Line 241... |
|
|
$DONE:
|
$DONE:
|
j $DONE # ...and freeze here
|
j $DONE # ...and freeze here
|
nop
|
nop
|
|
|
|
test_dcache:
|
|
# This D-Cache test is extremely simplistic:
|
|
# We'll make a few I/O writes to a block of test registers and then readback
|
|
# all the data. The writes and reads will be done as fast as the CPU can,
|
|
# i.e. back to back. We rely on the I-Cache being active for this.
|
|
# Note that, while the CPU 'wants' to do the WR cycles back to back, it
|
|
# can't because of the D-Cache stalls. That's the interaction we want to
|
|
# test here, for both WR and RD cycles.
|
|
|
|
move $t8,$ra # Save $ra -- remember, there's no stack
|
|
la $a0,msg9 # Display 'testing cache' message
|
|
jal puts
|
|
nop
|
|
li $a0,DEBUG_BASE # We'll use the debug register block as the
|
|
li $a1,0x112200aa # target of a series of RD and WR cycles.
|
|
addi $a2,$a1,0x100 # Load $a1..$a2 with dummy data.
|
|
addi $a3,$a2,0x100
|
|
.align 4 # Align to 16 bytes (start of I-Cache line)
|
|
sw $a1,0x0($a0) # Perform 3 WR cycles...
|
|
sw $a2,0x4($a0)
|
|
sw $a3,0x8($a0)
|
|
|
|
lw $t0,0x0($a0) # ...followed by a RD cycle
|
|
bne $a1,$t0,test_dcache_ww_error
|
|
nop
|
|
lw $t0,0x4($a0) # Verify the other 2 WR cycles
|
|
bne $a2,$t0,test_dcache_ww_error
|
|
nop
|
|
lw $t0,0x8($a0)
|
|
bne $a3,$t0,test_dcache_ww_error
|
|
nop
|
|
|
|
la $a0,msg11 # display OK message...
|
|
jal puts
|
|
nop
|
|
|
|
test_dcache_done: # ...and quit.
|
|
move $ra,$t8 # Recover $ra and return
|
|
jr $ra
|
|
nop
|
|
|
|
test_dcache_ww_error: # We'll print the same error for all kinds of
|
|
la $a0,msg10 # failure; we'll diagnose it in simulation.
|
|
test_dcache_error:
|
|
jal puts
|
|
nop
|
|
b test_dcache_done
|
|
|
|
|
# This short routine will be copied to RAM and then executed there. This
|
# This short routine will be copied to RAM and then executed there. This
|
# will test the behavior of the I-Cache.
|
# will test the behavior of the I-Cache.
|
test_exec_sram:
|
test_exec_sram:
|
#jr $ra
|
#jr $ra
|
#nop
|
#nop
|
sw $ra,0($sp)
|
sw $ra,0($sp)
|
addi $sp,$sp,-4
|
addi $sp,$sp,-4
|
la $a0,msg3
|
la $a0,msg3
|
la $a1,puts
|
la $a1,puts
|
jalr $a1
|
jalr $a1
|
nop
|
nop
|
lw $ra,4($sp)
|
lw $ra,4($sp)
|
jr $ra
|
jr $ra
|
addi $sp,$sp,4
|
addi $sp,$sp,4
|
test_exec_sram_end:
|
test_exec_sram_end:
|
nop
|
nop
|
|
|
|
|
|
|
#---- Functions ----------------------------------------------------------------
|
|
|
|
# void dump_hex(int *address {a0}, int len {a1})
|
#---- Functions ----------------------------------------------------------------
|
dump_hex:
|
|
move $t7,$a0
|
|
move $t6,$a1
|
|
sw $ra,0($sp)
|
|
addi $sp,$sp,-4
|
|
|
|
dump_hex_loop_lines:
|
# void dump_hex(int *address {a0}, int len {a1})
|
move $a0,$t7
|
dump_hex:
|
li $a1,8
|
move $t7,$a0
|
|
move $t6,$a1
|
|
sw $ra,0($sp)
|
|
addi $sp,$sp,-4
|
|
|
|
dump_hex_loop_lines:
|
|
move $a0,$t7
|
|
li $a1,8
|
jal put_hex
|
jal put_hex
|
nop
|
nop
|
la $a0,msg6
|
la $a0,msg6
|
jal puts
|
jal puts
|
nop
|
nop
|
li $t9,4
|
li $t9,4
|
|
|
dump_hex_loop_words:
|
dump_hex_loop_words:
|
lw $a0,0($t7)
|
lw $a0,0($t7)
|
jal put_hex
|
jal put_hex
|
li $a1,8
|
li $a1,8
|
|
|
la $a0,space
|
la $a0,space
|
jal puts
|
jal puts
|
addi $t7,4
|
addi $t7,4
|
|
|
addi $t9,$t9,-1
|
addi $t9,$t9,-1
|
bnez $t9,dump_hex_loop_words
|
bnez $t9,dump_hex_loop_words
|
nop
|
nop
|
|
|
la $a0,crlf
|
la $a0,crlf
|
jal puts
|
jal puts
|
nop
|
nop
|
|
|
addi $t6,$t6,-1
|
addi $t6,$t6,-1
|
bnez $t6,dump_hex_loop_lines
|
bnez $t6,dump_hex_loop_lines
|
nop
|
nop
|
|
|
la $a0,msg7
|
la $a0,msg7
|
jal puts
|
jal puts
|
addi $t7,4
|
addi $t7,4
|
|
|
.ifgt 0
|
# Some debug hex dump...
|
lw $ra,4($sp)
|
.ifgt 0
|
move $a0,$ra
|
lw $ra,4($sp)
|
li $a1,8
|
move $a0,$ra
|
|
li $a1,8
|
jal put_hex
|
jal put_hex
|
nop
|
nop
|
qqqq:
|
stop_here:
|
j qqqq
|
j stop_here
|
nop
|
nop
|
.endif
|
.endif
|
|
|
nop
|
nop
|
lw $ra,4($sp)
|
lw $ra,4($sp)
|
jr $ra
|
jr $ra
|
addi $sp,$sp,4
|
addi $sp,$sp,4
|
|
|
|
|
#---- Cache-related functions --------------------------------------------------
|
#---- Cache-related functions --------------------------------------------------
|
|
|
# void init_cache(void) -- invalidates all I-Cache lines (uses no RAM)
|
# void init_cache(void) -- invalidates all I-Cache lines (uses no RAM)
|
init_cache:
|
init_cache:
|
li $a0,0x00010000 # Disable cache, enable I-cache line invalidation
|
li $a0,0x00010000 # Disable cache, enable I-cache line invalidation
|
mfc0 $a1,$12
|
mfc0 $a1,$12
|
or $a0,$a0,$a1
|
or $a0,$a0,$a1
|
mtc0 $a0,$12
|
mtc0 $a0,$12
|
|
|
# In order to invalidate a I-Cache line we have to write its tag number to
|
# In order to invalidate a I-Cache line we have to write its tag number to
|
# any address while bits CP0[12].17:16=01. The write will be executed as a
|
# any address while bits CP0[12].17:16=01. The write will be executed as a
|
# regular write too, as a side effect, so we need to choose a harmless
|
# regular write too, as a side effect, so we need to choose a harmless
|
# target address.
|
# target address.
|
|
|
li $a0,XRAM_BASE
|
li $a0,XRAM_BASE
|
li $a2,0
|
li $a2,0
|
li $a1,ICACHE_NUM_LINES-1
|
li $a1,ICACHE_NUM_LINES-1
|
|
|
inv_i_cache_loop:
|
inv_i_cache_loop:
|
sw $a2,0($a0)
|
sw $a2,0($a0)
|
blt $a2,$a1,inv_i_cache_loop
|
blt $a2,$a1,inv_i_cache_loop
|
addi $a2,1
|
addi $a2,1
|
|
|
mfc0 $a0,$12
|
mfc0 $a0,$12
|
li $a1,0x00020000 # Leave cache enabled
|
li $a1,0x00020000 # Leave cache enabled
|
or $a0,$a0,$a1
|
or $a0,$a0,$a1
|
jr $ra
|
jr $ra
|
mtc0 $a0,$12
|
mtc0 $a0,$12
|
|
|
|
|
|
|
#--- Special functions that do not use any RAM ---------------------------------
|
#--- Special functions that do not use any RAM ---------------------------------
|
# WARNING: Not for general use!
|
# WARNING: Not for general use!
|
# All parameters in $a0..$a4, stack unused. No attempt to comply with any ABI
|
# All parameters in $a0..$a4, stack unused. No attempt to comply with any ABI
|
# has been made.
|
# has been made.
|
# Since we can't use any RAM, registers have been used with no regard for
|
# Since we can't use any RAM, registers have been used with no regard for
|
# intended usage -- have to share reg bank with calling function.
|
# intended usage -- have to share reg bank with calling function.
|
|
|
# void puts(char *s) -- print zero-terminated string
|
# void puts(char *s) -- print zero-terminated string
|
puts:
|
puts:
|
la $a2,UART_BASE # UART base address
|
la $a2,UART_BASE # UART base address
|
puts_loop:
|
puts_loop:
|
lb $v0,0($a0)
|
lb $v0,0($a0)
|
beqz $v0,puts_end
|
beqz $v0,puts_end
|
addiu $a0,1
|
addiu $a0,1
|
puts_wait_tx_rdy:
|
puts_wait_tx_rdy:
|
lw $v1,UART_STATUS($a2)
|
lw $v1,UART_STATUS($a2)
|
andi $v1,$v1,0x02
|
andi $v1,$v1,0x02
|
beqz $v1,puts_wait_tx_rdy
|
beqz $v1,puts_wait_tx_rdy
|
nop
|
nop
|
sw $v0,UART_TX($a2)
|
sw $v0,UART_TX($a2)
|
b puts_loop
|
b puts_loop
|
nop
|
nop
|
|
|
puts_end:
|
puts_end:
|
jr $ra
|
jr $ra
|
nop
|
nop
|
|
|
# void put_hex(int n, int d) -- print integer as d-digit hex
|
# void put_hex(int n, int d) -- print integer as d-digit hex
|
put_hex:
|
put_hex:
|
la $a2,UART_BASE
|
la $a2,UART_BASE
|
la $a3,put_hex_table
|
la $a3,put_hex_table
|
addi $a1,-1
|
addi $a1,-1
|
add $a1,$a1,$a1
|
add $a1,$a1,$a1
|
add $a1,$a1,$a1
|
add $a1,$a1,$a1
|
|
|
put_hex_loop:
|
put_hex_loop:
|
srlv $v0,$a0,$a1
|
srlv $v0,$a0,$a1
|
andi $v0,$v0,0x0f
|
andi $v0,$v0,0x0f
|
addu $s2,$a3,$v0
|
addu $s2,$a3,$v0
|
lb $v0,0($s2)
|
lb $v0,0($s2)
|
put_hex_wait_tx_rdy:
|
put_hex_wait_tx_rdy:
|
lw $v1,UART_STATUS($a2)
|
lw $v1,UART_STATUS($a2)
|
andi $v1,$v1,0x02
|
andi $v1,$v1,0x02
|
beqz $v1,put_hex_wait_tx_rdy
|
beqz $v1,put_hex_wait_tx_rdy
|
nop
|
nop
|
sw $v0,UART_TX($a2)
|
sw $v0,UART_TX($a2)
|
|
|
bnez $a1,put_hex_loop
|
bnez $a1,put_hex_loop
|
addi $a1,-4
|
addi $a1,-4
|
|
|
jr $ra
|
jr $ra
|
nop
|
nop
|
|
|
|
|
#---- Constant data (note we keep it in the text section) ----------------------
|
#---- Constant data (note we keep it in the text section) ----------------------
|
|
|
put_hex_table:
|
put_hex_table:
|
.ascii "0123456789abcdef"
|
.ascii "0123456789abcdef"
|
|
|
msg0:
|
msg0:
|
.ascii "\n\r"
|
.ascii "\n\r"
|
.asciz "Scanning external memory at 0x"
|
.asciz "Scanning external memory at 0x"
|
msg1:
|
msg1:
|
.asciz "Found XRAM top at 0x"
|
.asciz "Found XRAM top at 0x"
|
crlf:
|
crlf:
|
.asciz "\n\r"
|
.asciz "\n\r"
|
space:
|
space:
|
.asciz " "
|
.asciz " "
|
msg_mirror:
|
msg_mirror:
|
.asciz "hit mirror!\n\r"
|
.asciz "hit mirror!\n\r"
|
msg_bad:
|
msg_bad:
|
.asciz "bad readback!\n\r"
|
.asciz "bad readback!\n\r"
|
msg2:
|
msg2:
|
.asciz "\n\rDumping the first few words of FLASH at address 0x"
|
.asciz "\n\rDumping the first few words of FLASH at address 0x"
|
msg3:
|
msg3:
|
.ascii "\n\rTesting code execution from SRAM... "
|
.ascii "\n\rTesting code execution from SRAM... "
|
.asciz "if you see this, it worked\n\r"
|
.asciz "if you see this, it worked\n\r"
|
msg4:
|
msg4:
|
.ascii "\n\r\n\r"
|
.ascii "\n\r\n\r"
|
.asciz "End of test.\n\r\n\r"
|
.asciz "End of test.\n\r\n\r"
|
msg5:
|
msg5:
|
.asciz "Dump of first few words of XRAM after initialization:\n\r"
|
.asciz "Dump of first few words of XRAM after initialization:\n\r"
|
msg6:
|
msg6:
|
.asciiz ": "
|
.asciiz ": "
|
msg7:
|
msg7:
|
.asciiz "<end of dump>"
|
.asciiz "<end of dump>"
|
msg8:
|
msg8:
|
.ascii "\n\r"
|
.ascii "\n\r"
|
.asciiz "Testing execution from 8-bit static memory (FLASH)\n\r"
|
.asciz "Testing execution from 8-bit static memory (FLASH)\n\r"
|
|
msg9:
|
|
.asciz "Testing D-Cache with back-to-back pairs of RD & WR cycles...\n\r"
|
|
msg10:
|
|
.asciz "Error in WR+WR sequence\n\r"
|
|
msg11:
|
|
.asciz "OK\n\r"
|
|
|
.set reorder
|
|
.end entry
|
|
|
|
|
.set reorder
|
|
.end entry
|
|
|
No newline at end of file
|
No newline at end of file
|
|
|
No newline at end of file
|
No newline at end of file
|