📄 test_dram.asm
字号:
; MP3 Player, Test DRAM, http://www.pjrc.com/tech/mp3; Copyright (c) 2000, PJRC.COM, LLC; This program is free software; you can redistribute it and/or; modify it under the terms of the GNU General Public License; as published by the Free Software Foundation; either version 2; of the License, or (at your option) any later version.; This program is distributed in the hope that it will be useful,; but WITHOUT ANY WARRANTY; without even the implied warranty of; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the; GNU General Public License for more details.; You should have received a copy of the GNU General Public License; along with this program; if not, write to the Free Software; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.; As a specific exception to the GPL, the executable object code built; from this source code may be combined with hardware configuration data; files. A hardware configuration data file is a set of data that is; transmitted to an intergrated circuit that is not a general purpose; microprocessor or microcontroller, in order to establish its normal; operation. The process of combining the executable ojbect code built; from the GPL licensed source code with the hardware configuration data; shall be considered an aggregation of another work not based on the; Program. While the GPL does not restrict use of the program, any; use restriction associated with the hardware configuration data (for; example, that it only be used with particular hardware) shall apply; to the combined file which includes a copy of the hardware configuration; data.; Contact: paul@pjrc.com.equ location, 0xE000 ;where this program will exist.equ cout, 0x0030 ;Send Acc to serial port.equ cin, 0x0032 ;Get Acc from serial port.equ phex, 0x0034 ;Print Hex value of Acc.equ phex1, 0x002E.equ phex16, 0x0036 ;Print Hex value of DPTR.equ pstr, 0x0038 ;Print string pointed to by DPTR,.equ upper, 0x0040 ;Convert Acc to uppercase.equ pint8u, 0x004D ;print Acc at an integer, 0 to 255.equ pint8, 0x0050 ;print Acc at an integer, -128 to 127.equ pint16u, 0x0053 ;print DPTR as an integer, 0 to 65535.equ newline, 0x0048 ;print CR/LF (13 and 10).equ cin_filter, 0x0062 ;get a character, but look for esc sequences.equ call_bank1, 0x0FE0.equ alt_xdownload, 0x3000 + 73.equ sta013_init, 0x3000 + 67.equ test_sta013_driver, 0x3000 + 148.equ test_count, 0x28.equ good_mem_mask, 0x29 ;4 bytes (1 bit for each 32 megs).org location.db 0xA5,0xE5,0xE0,0xA5 ;signiture bytes.db 254,'T',0,0 ;id.db 0,0,0,0 ;reserved.db 0,0,0,0 ;reserved.db 0,0,0,0 ;reserved.db 0,0,0,0 ;reserved.db 0,0,0,0 ;user defined.db 255,255,255,255 ;length and checksum (255=unused).db "DRAM and STA013 DMA Test",0.org location+64 ;executable code begins here;memory map:;;4 megs, pages 0 to 1023;8 megs, pages 0 to 2047;16 mges, pages 0 to 1023, 2048 to 3071, 4096 to 5119, and 6144 to 7167;32 megs, pages 0 to 8191 mov test_count, #0 ;count # of testsdram_test: lcall cfg_fpga clr a mov good_mem_mask+0, a mov good_mem_mask+1, a mov good_mem_mask+2, a mov good_mem_mask+3, a ; loop1 traverses all 32 sections and checks if each is ok mov r2, #0 mov r4, #0 ;r4 to count # of megabytes foundsimmsz_loop1: ; loop2 writes known data into every good section we've ; found so far. This is necessary because we will check ; it all to make sure it didn't change unexpectedly mov r3, #0simmsz_loop2: mov a, r3 clr c subb a, r2 jnc simmsz_loop2_end mov b, r3 lcall is_section_ok jnz simmsz_loop2_next mov dpl, #0 mov dph, r3 acall set_page acall wr_dramsimmsz_loop2_next: inc r3 sjmp simmsz_loop2simmsz_loop2_end: ; now check if this 1-meg section works by writing & reading mov dpl, #0 mov dph, r2 acall simm_test_page jc simmsz_skip_setting_ok ; loop3 checks all other previously known good sections to ; see if the write into this one also corrupted data in ; any other good memory. mov r3, #0simmsz_loop3: mov a, r3 clr c subb a, r2 jnc simmsz_loop3_end ;check all other pages mov b, r3 lcall is_section_ok ;that were previously found good jz simmsz_loop3_next mov dpl, #0 mov dph, r3 acall simm_test_page_rdonly ;and if they got corrupted, then jc simmsz_skip_setting_ok ;this current page (r2) is bad!simmsz_loop3_next: inc r3 sjmp simmsz_loop3simmsz_loop3_end: ; since this page had good memory and using it didn't corrupt ; and other pages, we'll consider it usable memory mov b, r2 acall mark_section_as_ok inc r4simmsz_skip_setting_ok:simmsz_loop1_next: inc r2 cjne r2, #32, simmsz_loop1 mov dptr, #msg_found lcall pstr mov a, r4 lcall pint8u mov dptr, #msg_usable_mem lcall pstr mov a, good_mem_mask+3 lcall phex mov a, good_mem_mask+2 lcall phex mov a, good_mem_mask+1 lcall phex mov a, good_mem_mask+0 lcall phex lcall newlinesimm_4k_check: mov dptr, #msg_ck_simm_block lcall pstr mov dptr, #0 acall set_page acall wr_dram_4k mov dptr, #0 acall set_page acall ck_dram_4k jc simm_4k_check_err mov dptr, #mesg_ok lcall pstr sjmp simm_4k_check_donesimm_4k_check_err: mov dptr, #msg_simm_block_err lcall pstrsimm_4k_check_done: ;let's do some more tests, which aren't really needed for ;figuring out the simm size, but it'd be nice to do. All ;pages under 1024 should work in all simm sizesdtest3: mov dptr, #0 acall v_simm_test_page mov dptr, #1023 acall v_simm_test_page mov dptr, #341 acall v_simm_test_page mov dptr, #682 acall v_simm_test_page mov dptr, #981 acall v_simm_test_page mov dptr, #154 acall v_simm_test_page mov dptr, #256 acall v_simm_test_page mov dptr, #512 acall v_simm_test_page mov dptr, #2 acall v_simm_test_page mov dptr, #73 acall v_simm_test_page mov dptr, #1 acall v_simm_test_page mov dptr, #4 acall v_simm_test_page mov dptr, #555 acall v_simm_test_page mov dptr, #16 acall v_simm_test_page mov dptr, #1014 acall v_simm_test_page mov dptr, #8 acall v_simm_test_page mov dptr, #136 acall v_simm_test_page mov dptr, #32 acall v_simm_test_page mov dptr, #777 acall v_simm_test_page mov dptr, #128 acall v_simm_test_page mov dptr, #31 acall v_simm_test_page mov dptr, #64 acall v_simm_test_page mov dptr, #89 acall v_simm_test_page mov dptr, #224 acall v_simm_test_page mov dptr, #123 acall v_simm_test_page mov dptr, #765 acall v_simm_test_page mov dptr, #777 acall v_simm_test_page_rdonly mov dptr, #154 acall v_simm_test_page_rdonly mov dptr, #256 acall v_simm_test_page_rdonly mov dptr, #1 acall v_simm_test_page_rdonly mov dptr, #8 acall v_simm_test_page_rdonly mov dptr, #2 acall v_simm_test_page_rdonly mov dptr, #682 acall v_simm_test_page_rdonly mov dptr, #4 acall v_simm_test_page_rdonly mov dptr, #341 acall v_simm_test_page_rdonly mov dptr, #16 acall v_simm_test_page_rdonly mov dptr, #0 acall v_simm_test_page_rdonly mov dptr, #1023 acall v_simm_test_page_rdonlytest_sta013: mov dptr, #msg_dma_test lcall pstr mov dptr, #sta013_init lcall call_bank1 jc test_sta013_fail mov dptr, #mesg_ok lcall pstr mov dptr, #test_sta013_driver lcall call_bank1 mov a, dpl jnz test_sta013_fail mov dptr, #mesg_ok lcall pstr rettest_sta013_fail: mov dptr, #mesg_error lcall pstr ret ;value in b between 0-31, returns zero if that bit in ;good_mem_mask is clear, or non-zero if it is setis_section_ok: acall mem_mask_setup anl a, @r0 ret ;value in b between 0-31, mark that megabyte of memory as okmark_section_as_ok: acall mem_mask_setup orl a, @r0 mov @r0, a ret ;given a number in b from 0 to 31, set up r0 to point ;to the byte within "good_mem_mask", and return Acc ;with the bitmask for the bit within that bytemem_mask_setup: mov a, b swap a rl a anl a, #3 add a, #good_mem_mask mov r0, a mov a, b anl a, #7 inc a movc a, @a+pc ret .db 1, 2, 4, 8, 16, 32, 64, 128;test a page of DRAM memory (specified by dptr). Return C=1 if;an error, or C=0 if ok. Normally bytes are written to the;page and then read back, but "simm_test_page_rdonly" may be;called to read the page and see if previously written data;is ok.simm_test_page: push dpl push dph acall set_page acall wr_dram pop dph pop dplsimm_test_page_rdonly: acall set_page ajmp ck_dramv_simm_test_page: push dpl push dph acall simm_test_page jnc no_news_is_good_newssimm_test_error: mov dptr, #msg_warn_simm lcall pstr pop dph pop dpl mov a, dph lcall phex mov a, dpl lcall phex lcall newline acall print_test_buffer acall set_page acall print_test_buffer lcall newline retv_simm_test_page_rdonly: push dpl push dph acall simm_test_page_rdonly jc simm_test_errorno_news_is_good_news: pop dph pop dpl retprint_test_buffer: mov r1, #test_data_bufferprint_test_buffer_loop: mov a, @r1 lcall phex inc r1 cjne r1, #test_data_buffer+num_test_bytes, print_test_buffer_loop lcall newline ret ;maps a block at 0000, and also sets up r5 as a seed ;for that block number, so that we can write some ;data into that block that's different from any ;other block (we hope).set_page: mov a, dpl xrl a, #01001101b xrl a, dph xrl a, #10110010b mov r5, a ;set rand seed based on block # mov r1, #test_data_buffer mov a, dpl xrl a, #01110101b mov @r1, a ;store block # into buffer inc r1 mov a, dph xrl a, #01110101b mov @r1, a inc r1set_page_loop: acall rand8 mov @r1, a ;fill rest of buffer with "rand" data inc r1 cjne r1, #test_data_buffer+num_test_bytes, set_page_loop mov a, dpl mov b, dph mov dptr, #dram_page_cfg movx @dptr, a ;and map this block at 0000-0FFF inc dptr mov a, b movx @dptr, a ret.equ num_test_bytes, 16.equ test_data_buffer, 0xC0 ;write data in test_data_buffer to DRAMwr_dram: mov dptr, #0 mov r1, #test_data_bufferwr_dram_loop: mov a, @r1 inc r1 movx @dptr, a inc dptr cjne r1, #test_data_buffer+num_test_bytes, wr_dram_loop ret ;compare data in DRAM to test_data_buffer ;return C=0 if good, C=1 if any error ;test_data_buffer is filled with data from DRAMck_dram: mov dptr, #0 mov r1, #test_data_buffer clr psw.5ck_dram_loop: movx a, @dptr mov b, a clr c subb a, @r1 jz ck_dram_next mov @r1, b setb psw.5ck_dram_next: inc dptr inc r1 cjne r1, #test_data_buffer+num_test_bytes, ck_dram_loop mov c, psw.5 ret ;fill a block with short clips of data at 256 byte intervalswr_dram_4k: mov r0, #0wr_4k_1:mov dph, r0 mov dpl, #0wr_4k_2:acall rand8 movx @dptr, a inc dptr mov a, dpl cjne a, #9, wr_4k_2 inc r0 cjne r0, #16, wr_4k_1 ret ;check a block with short clips of data at 256 byte intervals ;C=0 if the data is all good, C=1 if there's a problemck_dram_4k: mov r0, #0ck_4k_1:mov dph, r0 mov dpl, #0ck_4k_2:acall rand8 mov b, a movx a, @dptr cjne a, b, ck_4k_err inc dptr mov a, dpl cjne a, #9, ck_4k_2 inc r0 cjne r0, #16, ck_4k_1 clr c retck_4k_err: setb c ret; generate an 8 bit random number, r5 holds the "seed"rand8: mov a, r5 jnz rand8b cpl a mov r5, arand8b: anl a, #10111000b mov c, p mov a, r5 rlc a mov r5, a retcfg_fpga: mov dptr, #mesg_xilinx_cfg lcall pstr mov dptr, #alt_xdownload lcall call_bank1 jc error mov dptr, #mesg_ok lcall pstr reterror: mov dptr, #mesg_error lcall pstr ljmp 0; Simple communication with an IDE disk drive.equ buffer, 0x0000 ;a 512 byte buffer;registers implemented in the FPGA.equ dram_page_cfg, 0xFF00.equ ide_data, 0xFF60.equ ide_err, 0xFF62.equ ide_sec_cnt, 0xFF64.equ ide_sector, 0xFF66.equ ide_cyl_lsb, 0xFF68.equ ide_cyl_msb, 0xFF6A.equ ide_head, 0xFF6C.equ ide_command, 0xFF6E.equ ide_status, 0xFF6E.equ ide_control, 0xFF7C.equ ide_astatus, 0xFF7E.equ ide_rst_bit, 0xFF40.equ ide_data_buf_msb, 0xFF43.equ dma_ide_dest, 0xFF22.equ dma_ide_count, 0xFF24.equ irq_dma_ide_ack,0xFF5C.equ dma_ide_go, 0xFF58.equ irq_ident, 0xFF50.equ dma_mp3_src, 0xFF28.equ dma_mp3_count, 0xFF2A.equ dma_mp3_go, 0xFF59.equ irq_dma_mp3_ack,0xFF5D;IDE Command Constants. These should never change..equ ide_cmd_recal, 0x10.equ ide_cmd_read, 0x20.equ ide_cmd_write, 0x30.equ ide_cmd_init, 0x91.equ ide_cmd_id, 0xEC.equ ide_cmd_spindown, 0xE6.equ ide_cmd_spinup, 0xE1.equ ide_cmd_sleep, 0xE6.equ ide_cmd_initparms, 0x91;------------------------------------------------------------------;internal ram usage.equ lba, 0x70 ;4 bytes, 28 bit Logical Block Address.equ sec_count, 0x74;------------------------------------------------------------------; Main Program, a simple menu driven interface..org location+0x400.db 0xA5,0xE5,0xE0,0xA5 ;signiture bytes.db 35,255,0,0 ;id, 35=program.db 0,0,0,0 ;reserved.db 0,0,0,0 ;reserved.db 0,0,0,0 ;reserved.db 0,0,0,0 ;reserved.db 0,0,0,0 ;user defined.db 255,255,255,255 ;length and checksum (255=unused).db "IDE Disk Drive Test",0.org location+0x400+64 ;executable code begins here lcall cfg_fpga mov dptr, #msg_1 ;print a welcome message lcall pstr ;initialize the drive. If there is no drive, this may hang acall ide_init ;get the drive id info. If there is no drive, this may hang acall drive_id ; print the drive's model number mov dptr, #msg_mdl lcall pstr mov dptr, #buffer + 60 mov r0, #40 acall print_name lcall newline ; print the drive's serial number mov dptr, #msg_sn lcall pstr mov dptr, #buffer + 20 mov r0, #20 acall print_name lcall newline ; print the drive's cylinder, head, and sector specs mov dptr, #msg_cy lcall pstr mov dptr, #buffer + 2 acall print_parm mov dptr, #msg_hd lcall pstr
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -