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

📄 test_dram.asm

📁 一款MP3 Player Firmware 的原代码,非常有参考价值
💻 ASM
📖 第 1 页 / 共 2 页
字号:
	mov	dptr, #buffer + 6	acall	print_parm	mov	dptr, #msg_sc	lcall	pstr	mov	dptr, #buffer + 12	acall	print_parm	lcall	newline	lcall	newline	mov	dptr, #buffer + 6	movx	a, @dptr	dec	a	mov	lba+0, a	mov	dptr, #buffer + 12	movx	a, @dptr	mov	lba+1, a	lcall	init_parms	; default position will be first block (master boot record)	clr	a	mov	lba+0, a	mov	lba+1, a	mov	lba+2, a	mov	lba+3, amain_loop:				;print a 1-line prompt	mov	dptr, #msg_l	lcall	pstr	mov	a, lba+3	lcall	phex	mov	a, lba+2	lcall	phex	mov	a, lba+1	lcall	phex	mov	a, lba+0	lcall	phex	mov	dptr, #msg_pmt	lcall	pstr	lcall	cin	lcall	uppermain1:	cjne	a, #'R', main2		;read a sector		acall	read_sector	jz	main1b	push	acc	mov	dptr, #msg_err	lcall	pstr	pop	acc	lcall	phex	lcall	newline	ajmp	main_loopmain1b:	mov	dptr, #msg_rd	lcall	pstr	ajmp	main_loopmain2:	cjne	a, #'W', main3		;write a sector	mov	dptr, #msg_sure	lcall	pstr	lcall	cin	lcall	upper	cjne	a, #'Y', main2c	acall	write_sector	jz	main2b	push	acc	mov	dptr, #msg_err	lcall	pstr	pop	acc	lcall	phex	lcall	newline	ajmp	main_loopmain2b:	mov	dptr, #msg_wr	lcall	pstrmain2c: ajmp	main_loopmain3:	cjne	a, #'L', main4		;set the logical block address	mov	dptr, #msg_cyh	lcall	pstr	lcall	ghex32_lba	jc	main3b	mov	lba+0, r3	mov	lba+1, r4	mov	lba+2, r5	mov	lba+3, r6main3b:	lcall	newline	ajmp	main_loopmain4:	cjne	a, #'U', main5		;cause the drive to spin up	acall	spinup	ajmp	main_loopmain5:	cjne	a, #'D', main6		;cause the drive to spin down	acall	spindown	ajmp	main_loopmain6:	cjne	a, #'Q', main7		;quit	ljmp	0main7:	cjne	a, #'H', main8	acall	hexdump	ajmp	main_loopmain8:	ajmp	main_loop;------------------------------------------------------------------; Routines that talk with the IDE drive, these should be called by; the main program.	;read a sector, specified by the 4 bytes in "lba",	;Return, acc is zero on success, non-zero for an errorread_sector:	acall	ide_busy		;make sure drive is ready	acall	wr_lba			;tell it which sector we want	mov	dptr, #ide_command	mov	a, #ide_cmd_read	movx	@dptr, a		;ask the drive to read it	acall	ide_drq			;wait until it's got the data	jb	acc.0, get_err	mov	dptr, #buffer	acall	read_data		;grab the data	clr	a	ret	;when an error occurs, we get acc.0 set from a call to ide_drq	;or ide_busy (which read the drive's status register).  If	;that error bit is set, we should jump here to read the drive's	;explaination of the error, to be returned to the user.  If for	;some reason the error code is zero (shouldn't happen), we'll	;return 255, so that the main program can always depend on a	;return of zero to indicate success.get_err:mov	dptr, #ide_err	movx	a, @dptr	jz	gerr2	retgerr2:	mov	a, #255	ret	;write a sector, specified by the 4 bytes in "lba",	;whatever is in the buffer gets written to the drive!	;Return, acc is zero on success, non-zero for an errorwrite_sector:	acall	ide_busy		;make sure drive is ready	acall	wr_lba			;tell it which sector we want	mov	dptr, #ide_command	mov	a, #ide_cmd_write	movx	@dptr, a		;tell drive to write a sector	acall	ide_drq			;wait unit it wants the data	jb	acc.0, get_err	mov	dptr, #buffer	acall	write_data		;give the data to the drive	acall	ide_busy		;wait until the write is complete	jb	acc.0, get_err	clr	a	retinit_parms:	acall	ide_busy	mov	a, lba+0		;get # heads for this drive	anl	a, #0x0F	orl	a, #0xA0		;master device assumed	mov	dptr, #ide_head	movx	@dptr, a	mov	a, lba+1	mov	dptr, #ide_sec_cnt	;get # sec/track for this drive	movx	@dptr, a	mov	a, #ide_cmd_initparms	mov	dptr, #ide_command	movx	@dptr, a	acall	ide_busy	ret	;do the identify drive command, and return with the buffer	;filled with info about the drivedrive_id:	acall	ide_busy	mov	dptr, #ide_command	mov	a, #ide_cmd_id	movx	@dptr, a	acall	ide_drq	mov	dptr, #buffer	acall	read_data	ret	;tell the drive to spin upspinup:	mov	dptr, #ide_command	mov	a, #ide_cmd_spinup	movx	@dptr, a	ajmp	ide_busy	;tell the drive to spin downspindown:	acall	ide_busy	mov	dptr, #ide_command	mov	a, #ide_cmd_spindown	movx	@dptr, a	ajmp	ide_busy	;initialize the ide driveide_init:	acall	ide_hard_resetide_init_wait:	mov	dptr, #ide_head	mov	a, #10100000b	movx	@dptr, a		;select the master device	acall	wait	mov	a, #'*'	lcall	cout	mov	dptr, #ide_status	movx	a, @dptr	;should probably check for a timeout here	jnb	acc.6, ide_init_wait	;wait for RDY bit to be set	jb	acc.7, ide_init_wait	;wait for BSY bit to be clear	lcall	newline	mov	dptr, #ide_command	mov	a, #ide_cmd_recal	;do recal command (is this necessary?)	movx	@dptr, a	ajmp	ide_busy;------------------------------------------------------------------; Not quite as low, low level I/O.  These routines talk to the drive,; using the low level I/O.  Normally a main program should not call; directly to these.	;Read a block of 512 bytes (one sector) from the drive	;and store it in memory @ DPTRread_data:	;ajmp	read_data_pio	;read 512 bytes of data using fast DMAread_data_dma:	mov	a, dpl	mov	b, dph	mov	dptr, #dma_ide_dest	movx	@dptr, a		;write LSB of dest addr	inc	dptr	mov	a, b	movx	@dptr, a		;write LSB of dest addr	mov	dptr, #dma_ide_count	clr	a	movx	@dptr, a	inc	dptr	mov	a, #1	movx	@dptr, a		;request 256 16 bit reads	mov	dptr, #irq_dma_ide_ack	movx	@dptr, a		;clear any previous interrupt	mov	dptr, #dma_ide_go	movx	@dptr, a		;begin the transfer	;now we just wait for it to finish	mov	dptr, #irq_identdma_wait:	movx	a, @dptr		;2  1 psen = 2 bytes transfered	jnb	acc.0, dma_wait		;2  3 psen = 6 bytes transfered	ret	;speed = 8 bytes per 4 cycles -> 1229 kbyte/sec	;  remember, this is raw transfer speed, and doesn't	;  include the time to set up the transfer.		;Ideally, we'd be executing real code instead of this	;busy loop.  With some luck, real code would have more	;psen's per second than movx (only mul and div have less).	;If we call into PM2, the psens (and dma) will stall!	;Maybe someday the DMA controller will be able to detect	;unused bus time and use it... that'd double the speed for	;this test case.  Will need to investigate actual speed once	;the drivers are written and somewhat mature.  A really	;ambitious approach would be to watch the psen fetch and	;do a little table lookup of the opcode, and let the state	;machine run full speed for the entire instruction and	;into the fetch of the next opcode, so we could use all	;the available time.  Maybe someday when I have lots of	;free time (highly unlikely).	;read 512 bytes of data using slow I/Oread_data_pio:	mov	r5, #0rdblk2: push	dph			;2	push	dpl			;2	mov	dptr, #ide_data		;2	movx	a, @dptr		;2  read lsb	mov	r2, a			;1	mov	dptr, #ide_data_buf_msb	;2	movx	a, @dptr		;2  read msb	mov	r3, a			;1	pop	dpl			;2	pop	dph			;2	mov	a, r2			;1	movx	@dptr, a		;2  write lsb	inc	dptr			;2	mov	a, r3			;1	movx	@dptr, a		;2  write msb	inc	dptr			;2	djnz	r5, rdblk2		;2	ret	;speed = 2 bytes per 30 cycles -> 41 kbyte/sec	;Write a block of 512 bytes (at DPTR) to the drivewrite_data:	mov	r5, #0wrblk2: movx	a, @dptr		;read lsb	mov	r2, a	inc	dptr	movx	a, @dptr		;read msb	mov	r3, a	inc	dptr	push	dph	push	dpl	mov	dptr, #ide_data_buf_msb	mov	a, r3	movx	@dptr, a		;write msb	mov	dptr, #ide_data	mov	a, r2	movx	@dptr, a		;write lsb	pop	dpl	pop	dph	djnz	r5, wrblk2	ret	;write the logical block address to the drive's registerswr_lba:	mov	a, lba+3	anl	a, #0x0F	orl	a, #0xE0	mov	dptr, #ide_head	movx	@dptr, a	mov	a, lba+2	mov	dptr, #ide_cyl_msb	movx	@dptr, a	mov	a, lba+1	mov	dptr, #ide_cyl_lsb	movx	@dptr, a	mov	a, lba+0	mov	dptr, #ide_sector	movx	@dptr, a	mov	a, #1	mov	dptr, #ide_sec_cnt	movx	@dptr, a	ret	;Wait for the ide drive to not be busy.	;Returns the drive's status in Accide_busy:	acall	wait	;mov	a, #'.'	;lcall	cout	mov	dptr, #ide_status	;wait for RDY bit to be set	movx	a, @dptr	;should probably check for a timeout here	jb	acc.7, ide_busy	ret	;Wait for the drive to be ready to transfer data.	;Returns the drive's status in Accide_drq:	acall	wait	;mov	a, #'_'	;lcall	cout	mov	dptr, #ide_status	;wait for DRQ bit to be set	movx	a, @dptr	;should probably check for a timeout here	jb	acc.7, ide_drq		;wait for BSY to be clear	jnb	acc.3, ide_drq		;wait for DRQ to be set	ret	;do a hard reset on the drive, by pulsing its reset pin.	;this should usually be followed with a call to "ide_init".ide_hard_reset:	mov	dptr, #ide_rst_bit	clr	a	movx	@dptr, a		;assert the reset pin	acall	delay_10ms		;IDE requires reset > 25 ms	acall	delay_10ms	acall	delay_10ms	mov	a, #1	movx	@dptr, a		;de-assert the reset pin	acall	delay_10ms		;brief delay while drive inits	ret	;delay for 10 ms	;10ms at 7.3728 MHz is 6144 machine cycles	;6144 = 256 * 24delay_10ms:	mov	r0, #0d1ms:	mov	r1, #10		;1 cycle	djnz	r1, *		;20 cycles	nop			;1 cycle	djnz	r0, d1ms	;2 cyclesfive_cy:nop	ret;------------------------------------------------------------------; Some additional serial I/O routines not available in PAULMON	;print a 16 bit number, located at DPTRprint_parm:	movx	a, @dptr	push	acc	inc	dptr	movx	a, @dptr	mov	dph, a	pop	dpl	ljmp	pint16u	;print a string, no more than R0 chars longprint_name:	movx	a, @dptr	jz	pn_end	lcall	cout	inc	dptr	djnz	r0, print_namepn_end:	ret	;get a 32 bit input, in hexghex32_lba:	mov	r2, #8	mov	r3, #0	mov	r4, #0	mov	r5, #0	mov	r6, #0gh32c:	lcall	cin_filter	lcall	upper	cjne	a, #27, gh32d	setb	c	retgh32d:	cjne	a, #8, gh32f	sjmp	gh32kgh32f:	cjne	a, #127, gh32ggh32k:	cjne	r2, #8, gh32e	sjmp	gh32cgh32e:	lcall	cout	mov	r0, #4gh32yy:	clr	c	mov	a, r6	rrc	a	mov	r6, a	mov	a, r5	rrc	a	mov	r5, a	mov	a, r4	rrc	a	mov	r4, a	mov	a, r3	rrc	a	mov	r3, a	djnz	r0, gh32yy	inc	r2	sjmp	gh32cgh32g:	cjne	a, #13, gh32i	clr	c	retgh32i: 	mov	r7, a	acall	asc2hex	jc	gh32c	xch	a, r7	lcall	cout	mov	a, r7	swap	a	mov	r7, a	mov	r0, #4gh32j:	mov	a, r7	rlc	a	mov	r7, a	mov	a, r3	rlc	a	mov	r3, a	mov	a, r4	rlc	a	mov	r4, a	mov	a, r5	rlc	a	mov	r5, a	mov	a, r6	rlc	a	mov	r6, a	djnz	r0, gh32j	djnz	r2, gh32c	clr	c	ret        ;carry set if invalid inputasc2hex:        clr     c        add     a, #208        jnc     hex_not        add     a, #246        jc      hex_maybe        add     a, #10        clr     c        rethex_maybe:        add     a, #249        jnc     hex_not        add     a, #250        jc      hex_not        add     a, #16        clr     c        rethex_not:setb    c        ret	;print a hexdump of the data in the 512 byte bufferhexdump:	lcall	newline	mov	r2, #32		;print 32 lines	mov	dptr, #bufferhd1:	mov	a, dph	mov	r5, a	clr	c	subb	a, #buffer >> 8	lcall	phex		;print address, starting at zero	mov	a, dpl	mov	r4, a	lcall	phex	mov	a, #':'	lcall	cout	acall	space	mov	r3, #16		;print 16 hex bytes per linehd2:	movx	a, @dptr	inc	dptr	lcall	phex		;print each byte in hex	acall	space	djnz	r3, hd2	acall	space	acall	space	acall	space	mov	dpl, r4	mov	dph, r5	mov	r3, #16		;print 16 ascii bytes per linehd3:	movx	a, @dptr	inc	dptr	anl	a, #01111111b	;only 7 bits for ascii	cjne	a, #127, hd3b	clr	a		;avoid 127/255 (delete/rubout) charhd3b:	add	a, #224	jc	hd3c	clr	a		;avoid control charactershd3c:	add	a, #32	lcall	cout	djnz	r3, hd3	lcall	newline	djnz	r2, hd1	lcall	newline	retspace:	push	acc	mov	a, #' '	lcall	cout	pop	acc	retwait:	jb	ri, quitwait_ret:	retquit:	lcall	cin	cjne	a, #27, wait_ret	ljmp	0map_block:	anl	a, #15	rl	a	add	a, #dram_page_cfg & 255	mov	dpl, a	clr	a	addc	a, #dram_page_cfg >> 8	mov	dph, a	mov	a, r2	movx	@dptr, a	inc	dptr	mov	a, r3	movx	@dptr, a	retmsg_dma_test:	.db	13,10,"Testing SIMM->STA013 DMA...",13,10        .db     "Config STA013: ",0msg_warn_simm:	.db	"ERROR: at "msg_block:	.db	"block=",0msg_1:	.db	"IDE Disk Drive Utility",13,10,13,10,0msg_mdl:.db	"Model: ",0msg_sn: .db	"S/N:   ",0msg_cy:	.db	"Cylinders: ", 0msg_hd:	.db	", Heads: ", 0msg_sc:	.db	", Sectors: ", 0msg_cyh:.db	"Enter LBA (in hex): ", 0msg_l:	.db	"LBA=0x",0msg_pmt:.db	", (R)ead (W)rite (L)BA (U)p (D)own (H)exdump (Q)uit",13,10,0msg_sure:.db	"Warning: this will change data on the drive, are you sure?",13,10,0msg_rd:	.db	"Sector Read OK",13,10,0msg_wr:	.db	"Sector Write OK",13,10,0msg_err:.db	"Error, code = ",0mesg_xilinx_cfg:	.db	"Config Xilinx: ",0mesg_ok:	.db	"Ok",13,10,0mesg_error:	.db	"Error!",13,10,0msg_found:	.db	"Found ",0msg_usable_mem:	.db	" megs, mask=",0msg_ck_simm_block:	.db	"4k block integrity: ",0msg_simm_block_err:	.db	"Incompatible SIMM!!",13,10,0

⌨️ 快捷键说明

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