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

📄 fat32.s

📁 Frank s MP3 Player Source Files
💻 S
📖 第 1 页 / 共 5 页
字号:
;***************************************************************************
;*
;* Title:				FAT32 Routines
;* Version:				1.1
;* Last updated:		10 Mar 2003
;* Target:				ATMEGA128
;*
;*
;* DESCRIPTION:
;* This file contains routines for dealing with the FAT32 file system.
;*
;* Some notes & assumptions:
;*
;* It is required that the drive be jumpered as a master. Although this software
;* could be modified to look for a slave & then talk to it, the Cypress USB
;* code requires the drive to be a master. Hence this code follows suit.
;*
;* This code does NOT examine the MBR (master boot record in sector 0 of the
;* drive) to find the FAT32 partition. It assumes that the first partition on
;* the drive is a FAT32 partition, and that it's in the usual place, ie sector 63.
;*
;* Note that bytes are read off the drive low-byte first. For example, to read
;* a 32-bit value off the drive, the low (least significant, 0-7) 8 bites are read
;* first, then the next 8 bits, then the next 8 bits, and finally the most-
;* significant (high byte, bits 24-31) is read last.
;*
;* Variables in AVR memory are treated similarly: low byte first to high byte last
;* (Exception to this are the queueing routines, which store their internal addresses
;* - read, write, end pointers, hi-byte first)
;*
;* Stack parameter passing: push high byte first
;*
;***************************************************************************


/* Make the routines in this file available to other files */
		.global FAT32_init
		.global GetFatParams
		.global StreamFile
		.global StreamFileC
		.global CalcNextCluster
		.global Cluster2Sector
		.global ResetAVR

/* Make some variables global as well */
		.global SEC_PER_CLUS
		.global FAT_START_SEC
		.global DIR_START_SEC
		.global FINDFILE_RET_NAME
		.global FINDFILE_RET_CLUS
		.global FINDFILE_RET_SIZE
		.global FINDFILE_CLUS
		.global CURRENT_DIRCL
		.global FINDFILE_OFSET
		.global STREAMFILE_ST
		.global STREAMFILE_FILESZ
		.global STREAMFILE_CLUS
		.global STREAMFILE_QPOINTER
		.global STREAMFILE_CMD
		

/* Here are the definitions we need, both in included files and defined right here */
#include		"frankmp3.h"			
#include		"frankasm.h"



; Allocate SRAM space for the variables
		.comm	SEC_PER_CLUS,			1		; number of 512-byte sectors per cluster
		.comm	FAT_START_SEC,			2		; FAT32 table start sector number
		.comm	DIR_START_SEC,			4		; directory sector number (low byte first)
		
		.comm	CALNXCL_ST,				1		; state variable for CalcNextCluster
		.comm	CALNXCL_OF,				1		; number of 16-bit reads offset into sector
		.comm	CALNXCL_SN,				4		; store the sector number of interest
		.comm	CALNXCL_CLUS_LO,		4		; sequential cluster range low value
		.comm	CALNXCL_CLUS_HI,		4		; sequential cluster range high value
		
		.comm	STREAMFILE_ST,			1		; StreamFile state variable
		.comm	STREAMFILE_SEC_REM,		2		; StreamFile # bytes remaining in current sector
		.comm	STREAMFILE_SECCLUS_REM, 1		; Streamfile # sectors remaining in current cluster
		.comm	STREAMFILE_FILESZ,		4		; Streamfile # bytes remaining in file
		.comm	STREAMFILE_CLUS,		4		; Streamfile current cluster number
		.comm	STREAMFILE_CMD,			1		; Streamfile command variable
		.comm	STREAMFILE_QPOINTER,	2		; Streamfile data queue pointer
		
		.comm	FINDFILE_CLUS,			4		; cluster number FindFile's currently reading from
		.comm	FINDFILE_OFSET,			2		; byte offset into cluster to start looking for files
		.comm	FINDFILE_TEMPO,			2		; temporary copy of FINDFILE_OFSET
		.comm	CURRENT_DIRCL,			4		; first cluster number for current directory
		.comm	FINDFILE_RET_CLUS,		4		; FindFile result: starting cluster number
		.comm	FINDFILE_RET_SIZE,		4		; FindFile result: File size (in bytes)
		.comm	FINDFILE_RET_NAME,		((FindFile_NumLongDirs*13)+2) ; FindFile result: File name text array: first byte is length, string null-terminated
		.comm	FINDFILE_LNCOUNT,		1		; count of how many more longname dir entries to check
		
		.text




;**********************************************************************************
;*
;* FAT32_init
;*
;* Initialises any FAT32 routines which need it. Called during system initialization.
;* This routine does the following:
;*
;*		Set the initial state of CalcNextCluster to SeekDrive
;*		Set the initial state of StreamFile to Idle
;*		Set the initial command for StreamFile to Stop
;*		Set the initial state of FindFile to Idle
;*		Set both the initial cluster numbers for FindFile to the root directory
;*				(Note: by definition, this is cluster number 2)
;*		Set the initial byte offset for FindFile's cluster to zero
;*
;*
;* Accepts: nothing
;* Returns: Nothing
;* Uses:	flags.
;*
;**********************************************************************************
FAT32_init:
		push	temp
		push	ZL
		push	ZH
		
; Set the initial state of CalcNextCluster to SeekDrive, and zero both the low and high
; sequential cluster range variables.
		ldi		ZL,lo8(CALNXCL_ST)
		ldi		ZH,hi8(CALNXCL_ST)				; point Z to CalcNextCluster state variable
		ldi		temp,CalNxCl_SDS		
		st		Z,temp							; make initial state to be SeekDrive
		clr		temp
		sts		CALNXCL_CLUS_LO,temp
		sts		CALNXCL_CLUS_LO+1,temp
		sts		CALNXCL_CLUS_LO+2,temp
		sts		CALNXCL_CLUS_LO+3,temp			; sequential cluster range low value is zero
		sts		CALNXCL_CLUS_HI,temp
		sts		CALNXCL_CLUS_HI+1,temp
		sts		CALNXCL_CLUS_HI+2,temp
		sts		CALNXCL_CLUS_HI+3,temp			; sequential cluster range high value also zero

; Set the initial state of StreamFile to Idle
		ldi		ZL,lo8(STREAMFILE_ST)
		ldi		ZH,hi8(STREAMFILE_ST)			; point Z to StreamFile state variable
		ldi		temp,StreamFile_St_Idle
		st		Z,temp							; store Idle state 
; Set the initial command for StreamFile to Stop
		ldi		ZL,lo8(STREAMFILE_CMD)
		ldi		ZH,hi8(STREAMFILE_CMD)			; Z points to command variable
		ldi		temp,StreamFile_Cmd_Stop
		st		Z,temp							; command variable says Stop

		pop		ZH
		pop		ZL
		pop		temp
		ret






;**********************************************************************************
;*
;* GetFatParams
;*
;* This routine reads from the drive and performs a number of reads and calculations
;* to obtain some necessary information about the file system on the drive. These
;* items of interest are:
;*		- number of sectors per cluster
;*		- sector number of the FAT table start
;*		- sector number of the root directory start
;*
;* Now to describe each of these individually:
;*
;* Numbers of sectors per cluster is easy. That's read directly out of the
;* BPB (boot parameter block), ie drive sector 63, byte offset 13.
;*
;* Sector number of the start of the FAT table is also easy. It is equal to
;* BPD_ResvdSecCnt + 63. 
;*
;* Sector number of the root directory start is slightly more complex. We need to calc
;* the sector number of the "FirstDataSector" (as microsoft calls it). This is
;* actually the sector number ON THE DRIVE of the start of the directory entries.
;* We perform the following calculation:
;* FirstDataSector = BPD_ResvdSecCnt + (2 * BPD_FATSz32) + 0 + 63
;*				   = (63 + BPD_ResvdSecCnt) + (2 * BPD_FATSz32)
;*				   where BPD_FATSz32 is read from sector 63 bytes 36-39 off the drive
;* Note that sector 63 on the drive is the first sector of the FAT32 partition.
;* The above calculation is done using 32-bit arithmetic.
;*
;* In both of the calculations above requiring BPD_ResvdSecCnt, although this is strictly a
;* 16-bit number, the code below only reads the low 8 bits and calculates accordingly.
;* That's because microsoft seems to set BPD_ResvdSecCnt to either 32 or 34. So then
;* BPD_ResvdSecCnt+63 equals 95 or 97; well below the 255 value limit of a byte.
;* Which makes the code simpler. (It's a little cheat, I know :-)
;*
;* This routine does not itself require any initialization in the Fat32 init routine. However
;* it does call SeekSector, which is initialized in the IDE init routine.
;*
;*
;* This routine functions as follows:
;*
;* Seek to sector 63
;* Read byte offset 13 and store in SEC_PER_CLUS
;*		If SEC_PER_CLUS == 0 then jump to start (reboot system)
;* Store (63+BPD_ResvdSecCnt) in FAT_START_SEC
;* Read bytes offset 36 through 39 (this is the 32-bit FatSize)
;* Shift left 1 bit  (to multiply by 2)
;* Add (63+BPD_ResvdSecCnt)
;* Store result in DIR_START_SEC
;* Return
;* 
;* All values are read from the drive low-byte first and written into
;* memory low-byte first.
;*
;*
;* Accepts: nothing
;* Returns: Nothing
;* Uses:	flags
;*
;**********************************************************************************
GetFatParams:
		push	temp
		push	param1
		push	param2
		push	ZL
		push	ZH
		push	r0
		push	r1
		push	r2
		push	r3
        push    r4                      ; r4 used to hold BPD_ResvdSecCnt

; make sure SeekSector is idle before calling it
GetFatParamsAA:
		lds		temp,SEEKSECT_ST
		cpi		temp,SeekSect_ISS		; is SeekSector idle, ready for new command?
		breq	GetFatParamsS			; yes - branch forward
		call	SeekSector				; no  - call it (to give it some CPU time)
		jmp		GetFatParamsAA			; and repeat until it's idle

GetFatParamsS:

; seek to sector 63
		ldi		temp,0
		push	temp
		push	temp
		push	temp
		ldi		temp,63
		push	temp
		ldi		param1,1
		rcall	SeekSector				; seek to sector 63
		pop		temp
		pop		temp
		pop		temp
		pop		temp
		ldi		temp,SeekSect_Done		
		cp		param1,temp
		brne	GetFatParamsS			; loop until SeekSector says seek is complete

; read byte offset 13 from the drive & store in SEC_PER_CLUS
		ldi		param1,IDERD_DATA				; read 16-bit data word from the drive
		call	IDE_read16						; low byte returned in param1; high in param2	
		ldi		param1,IDERD_DATA				; read 16-bit data word from the drive
		call	IDE_read16						; low byte returned in param1; high in param2	
		ldi		param1,IDERD_DATA				; read 16-bit data word from the drive
		call	IDE_read16						; low byte returned in param1; high in param2	
		ldi		param1,IDERD_DATA				; read 16-bit data word from the drive
		call	IDE_read16						; low byte returned in param1; high in param2	
		ldi		param1,IDERD_DATA				; read 16-bit data word from the drive
		call	IDE_read16						; low byte returned in param1; high in param2	
		ldi		param1,IDERD_DATA				; read 16-bit data word from the drive
		call	IDE_read16						; low byte returned in param1; high in param2	
		ldi		param1,IDERD_DATA				; read 16-bit data word from the drive
		call	IDE_read16						; param2 contains our offset 13 data byte		
		ldi		ZL,lo8(SEC_PER_CLUS)
		ldi		ZH,hi8(SEC_PER_CLUS)			; point Z to SEC_PER_CLUS
		st		Z,param2						; store byte from offset 13 in SEC_PER_CLUS

		cpi		param2,0
		brne	GetFatParams_1					; reboot system if SectorsPerCluster == 0
		jmp		main							; as there's a problem reading the drive

GetFatParams_1:
; get value of BPD_ResvdSecCnt (offset 14)
		ldi		param1,IDERD_DATA				; read 16-bit data word from the drive
		call	IDE_read16						; low byte returned in param1; high in param2	
        mov     r4,param1                       ; BPD_ResvdSecCnt now in r4 (we only care about the low byte; high byte ignored)

; store 63 plus BPD_ResvdSecCnt in FAT_START_SEC
		ldi		ZL,lo8(FAT_START_SEC)
		ldi		ZH,hi8(FAT_START_SEC)			; point Z to FAT_START_SEC
		ldi		temp,63
        add     temp,r4                         ; temp now contains 63 + BPD_ResvdSecCnt
		st		Z+,temp							; write low byte first (all we care about; assume BPD_ResvdSecCnt small)
		ldi		temp,0
		st		Z,temp							; then high byte
		
; read bytes offset 36 through 39. r0 is low byte through r3 being high byte
		ldi		param1,IDERD_DATA				; read bytes 16 & 17
		call	IDE_read16						; low byte  in param1; high in param2
		ldi		param1,IDERD_DATA				; read bytes 18 & 19
		call	IDE_read16						; low byte  in param1; high in param2
		ldi		param1,IDERD_DATA				; read bytes 20 & 21
		call	IDE_read16						; low byte  in param1; high in param2
		ldi		param1,IDERD_DATA				; read bytes 22 & 23
		call	IDE_read16						; low byte  in param1; high in param2
		ldi		param1,IDERD_DATA				; read bytes 24 & 25
		call	IDE_read16						; low byte  in param1; high in param2
		ldi		param1,IDERD_DATA				; read bytes 26 & 27
		call	IDE_read16						; low byte  in param1; high in param2
		ldi		param1,IDERD_DATA				; read bytes 28 & 29
		call	IDE_read16						; low byte  in param1; high in param2
		ldi		param1,IDERD_DATA				; read bytes 30 & 31
		call	IDE_read16						; low byte  in param1; high in param2
		ldi		param1,IDERD_DATA				; read bytes 32 & 33
		call	IDE_read16						; low byte  in param1; high in param2
		ldi		param1,IDERD_DATA				; read bytes 34 & 35
		call	IDE_read16						; low byte  in param1; high in param2

⌨️ 快捷键说明

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