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

📄 idefast.asm

📁 8051控制硬盘驱动
💻 ASM
字号:
; Somewhat faster communication with an IDE disk drive; see http://www.pjrc.com/tech/8051/ide/ for more info;  This code is an original work by Paul Stoffregen, written;  in December 1999.  This code has been placed in the;  public domain.  You may use it without any restrictions.;  You may include it in your own projects, even commercial;  (for profit) products.;  This code is distributed in the hope that they will be useful,;  but without any warranty; without even the implied warranty of;  merchantability or fitness for a particular purpose.; this code contains a modified copy of the code to read from an; IDE hard drive, which is optimized for speed.  These routines; were used in a homebrew MP3 player, which was able to sustain; reads of 192 kbit/sec data while feeding it to a MAS3507D MP3; decoder chip, using the UART in sync mode.  Reading 256 kbit/sec; did not not work.  The 8051 was clocked with a 14.7456 MHz crystal.; there is no documentation specific to this modified version,; other than the comments within this code..equ	location, 0x2000	;where this program will exist.equ	sect_buf, 0x2E00	;512 byte buffer;------------------------------------------------------------------; Hardware Configuration;8255 chip.  Change these to specify where the 8255 is addressed,;and which of the 8255's ports are connected to which ide signals.;The first three control which 8255 ports have the control signals,;upper and lower data bytes.  The last two are mode setting for the;8255 to configure its ports, which must correspond to the way that;the first three lines define which ports are connected..equ	ide_8255_lsb, 0x4000	;lower 8 bits.equ	ide_8255_msb, 0x4001	;upper 8 bits.equ	ide_8255_ctl, 0x4002	;control lines.equ	cfg_8255, 0x4003.equ	rd_ide_8255, 10010010b	;ide_8255_ctl out, ide_8255_lsb/msb input.equ	wr_ide_8255, 10000000b	;all three ports output;ide control lines for use with ide_8255_ctl.  Change these 8;constants to reflect where each signal of the 8255 each of the;ide control signals is connected.  All the control signals must;be on the same port, but these 8 lines let you connect them to;whichever pins on that port..equ	ide_a0_line, 0x01	;direct from 8255 to ide interface.equ	ide_a1_line, 0x02	;direct from 8255 to ide interface.equ	ide_a2_line, 0x04	;direct from 8255 to ide interface.equ	ide_cs0_line, 0x08	;inverter between 8255 and ide interface.equ	ide_cs1_line, 0x10	;inverter between 8255 and ide interface.equ	ide_wr_line, 0x20	;inverter between 8255 and ide interface.equ	ide_rd_line, 0x40	;inverter between 8255 and ide interface.equ	ide_rst_line, 0x80	;inverter between 8255 and ide interface;------------------------------------------------------------------; More symbolic constants... these should not be changed, unless of; course the IDE drive interface changes, perhaps when drives get; to 128G and the PC industry will do yet another kludge.;some symbolic constants for the ide registers, which makes the;code more readable than always specifying the address pins.equ	ide_data,	ide_cs0_line.equ	ide_err,	ide_cs0_line + ide_a0_line.equ	ide_sec_cnt,	ide_cs0_line + ide_a1_line.equ	ide_sector,	ide_cs0_line + ide_a1_line + ide_a0_line.equ	ide_cyl_lsb,	ide_cs0_line + ide_a2_line.equ	ide_cyl_msb,	ide_cs0_line + ide_a2_line + ide_a0_line.equ	ide_head,	ide_cs0_line + ide_a2_line + ide_a1_line.equ	ide_command,	ide_cs0_line + ide_a2_line + ide_a1_line + ide_a0_line.equ	ide_status,	ide_cs0_line + ide_a2_line + ide_a1_line + ide_a0_line.equ	ide_control,	ide_cs1_line + ide_a2_line + ide_a1_line.equ	ide_astatus,	ide_cs1_line + ide_a2_line + ide_a1_line + ide_a0_line;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, 0xE0.equ	ide_cmd_spinup, 0xE1;------------------------------------------------------------------;internal ram usage.equ	lba, 0x10		;4 bytes, 28 bit Logical Block Address.equ	stack, 0x40;------------------------------------------------------------------; 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	wr_lba	mov	a, #ide_command	mov	r2, #ide_cmd_read	acall	ide_wr	acall	ide_drq	jb	acc.0, rs_err	clr	a	retrs_err: mov	a, #ide_err	acall	ide_rd	mov	a, r2	jz	rs_err2	retrs_err2:mov	a, #255	ret	;initialize the ide driveide_init:	;acall	ide_hard_reset		;usually not necessary	mov	a, #ide_head	mov	r2, #10100000b	acall	ide_wr			;select the master device	mov	a, #ide_status	acall	ide_rd	mov	a, r2	;should probably check for a timeout here	jnb	acc.6, ide_init		;wait for RDY bit to be set	jb	acc.7, ide_init		;wait for BSY bit to be clear	mov	a, #ide_head	mov	r2, #0xAF	acall	ide_wr			;what should this config parm be?	mov	a, #ide_sec_cnt	mov	r2, #64	acall	ide_wr			;what should this config parm be?	mov	a, #ide_command	mov	r2, #ide_cmd_init	acall	ide_wr			;do init parameters command	acall	ide_busy	mov	a, #ide_command	mov	r2, #ide_cmd_recal	;do recal command (is this necessary?)	acall	ide_wr	acall	ide_busy	ret;------------------------------------------------------------------; 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.	;This is the parts that's faster.  Notice that it doesn't	;call to ide_rd and ide_wr, and it does less manipulation	;with the 8255.	;Read a block of 512 bytes (one sector) from the drive	;and store it in memory @ DPTRread_data:	mov	r0, #0	mov	r1, #2	mov	r2, dph	mov	p2, dph	mov	dptr, #cfg_8255	mov	a, #rd_ide_8255	movx	@dptr, a		;config 8255 chip, read moderdataloop:	mov	dptr, #ide_8255_ctl	;mov	a, #ide_data	;movx	@dptr, a		;drive address onto control lines	mov	a, #ide_data | ide_rd_line		movx	@dptr, a		;assert read pin	mov	dptr, #ide_8255_lsb	clr	a	movc	a, @a+dptr		;read the lower byte	movx	@r0, a	inc	r0	mov	dptr, #ide_8255_msb	clr	a	movc	a, @a+dptr		;read the upper byte	movx	@r0, a	inc	r0	mov	dptr, #ide_8255_ctl	clr	a	movx	@dptr, a		;deassert all control pins	mov	a, r0	jnz	rdataloop	mov	a, r2	inc	a	mov	p2, a	djnz	r1, rdataloop	mov	p2, #255	ret	;write the logical block address to the drive's registerswr_lba:	mov	a, lba+3	anl	a, #0x0F	orl	a, #0xE0	mov	r2, a	mov	a, #ide_head	acall	ide_wr	mov	a, #ide_cyl_msb	mov	r2, lba+2	acall	ide_wr	mov	a, #ide_cyl_lsb	mov	r2, lba+1	acall	ide_wr	mov	a, #ide_sector	mov	r2, lba+0	acall	ide_wr	;mov	a, #ide_sec_cnt	;mov	r2, #1	;acall	ide_wr	ret	;Wait for the ide drive to not be busy.	;Returns the drive's status in Accide_busy:	mov	a, #ide_status		;wait for RDY bit to be set	acall	ide_rd	mov	a, r2	;should probably check for a timeout here	jb	acc.7, ide_busy	ret	;note that this function is changed to have a call to an	;idle loop (commented out).	;Wait for the drive to be ready to transfer data.	;Returns the drive's status in Accide_drq:	mov	a, #ide_status		;wait for DRQ bit to be set	acall	ide_rd	;acall	idle	mov	a, r2	;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;------------------------------------------------------------------; Low Level I/O to the drive.  These are the routines that talk; directly to the drive, via the 8255 chip.  Normally a main; program would not call to these.	;Do a read bus cycle to the drive, using the 8255.  This	;is slow, because we have to manipulate the 8255 and use	;the 8051's limited moxv and movx to do it (via dptr).	;Note that the drive is read using MOVC, to run on a board	;where the 8255 is read using PSEN.  If your board uses	;RD instead of PSEN, chance the MOVC's to MOVX's.	;input acc = ide regsiter address	;output r2 = lower byte read from ide drive	;output r3 = upper byte read from ide drive	;dptr is changedide_rd:	push	acc	mov	dptr, #cfg_8255	mov	a, #rd_ide_8255	movx	@dptr, a		;config 8255 chip, read mode	mov	dptr, #ide_8255_ctl	pop	acc	movx	@dptr, a		;drive address onto control lines	orl	a, #ide_rd_line		movx	@dptr, a		;assert read pin	mov	dptr, #ide_8255_msb	;clr	a	;movc	a, @a+dptr		;read the upper byte	;mov	r3, a	mov	dptr, #ide_8255_lsb	clr	a	movc	a, @a+dptr		;read the lower byte	mov	r2, a	mov	dptr, #ide_8255_ctl	clr	a	movx	@dptr, a		;deassert all control pins	ret	;Do a write bus cycle to the drive, via the 8255	;input acc = ide register address	;input r2 = lsb to write	;input r3 = msb to write	;dptr is changedide_wr:	;push	acc	mov	r4, a	mov	dptr, #cfg_8255	mov	a, #wr_ide_8255	movx	@dptr, a		;config 8255 chip, write mode	mov	dptr, #ide_8255_lsb	mov	a, r2	movx	@dptr, a		;drive lower lines with lsb (r2)	;mov	dptr, #ide_8255_msb	;mov	a, r3	;movx	@dptr, a		;drive upper lines with msb (r3)	mov	dptr, #ide_8255_ctl	;pop	acc	mov	a, r4	movx	@dptr, a		;drive address onto control lines	orl	a, #ide_wr_line		movx	@dptr, a		;assert write pin	;nop	clr	a	movx	@dptr, a		;deassert all control pins	;mov	dptr, #cfg_8255	;mov	a, #rd_ide_8255	;movx	@dptr, a		;config 8255 chip, read mode	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, #cfg_8255	mov	a, #wr_ide_8255	movx	@dptr, a		;config 8255 chip, write mode	mov	dptr, #ide_8255_ctl	mov	a, #ide_rst_line	movx	@dptr, a		;hard reset the disk drive	mov	r2, #250	djnz	r2, *			;delay > 25 us (reset pulse width)	clr	a	movx	@dptr, a		;no ide control lines asserted	ret

⌨️ 快捷键说明

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