📄 avrfat16.c
字号:
/** @file avrfat16.c @brief Fat16 Functions @author Nick Lott @date September 2004 Copyright (C) 2004 Nick Lott <brokentoaster@sf.net> This is a simple implementation of the FAT16 file system. It is designed to be small for use with MP3 players and MMC cards. Currently it is readonly.NOTE: The code acknowledges only the first partition on the drive. 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. Target(s)...: ATmega169 Compiler....: AVR-GCC 3.3.1; avr-libc 1.0**/#include <avr/io.h>#include <avr/pgmspace.h>#include <avr/interrupt.h>#include "types.h"#include "avrfat16.h"#include "utils.h"//void FAT_PrintRecord(uint8 *pRecord);/*** FAT_initFat16* @brief read MBR and bootsector and set global fat variables* @return non zero for error.**/uint8 FAT_initFat16(void) { uint8 result,type,lba_begin,sectors_per_cluster,number_of_fats; uint16 bytes_per_sector,number_of_reserved_sectors,BPB_RootEntCnt; uint16 sectors_per_fat; // Assume read and write routines have been setup and are not NULL :) // read the first sector (MBR) /* check for 55 AA signature Read Partition info at 446+4 = type check it's a vfat etc 446+8..11 = LBA Begin 446+12..15 =# of Sectors */ result = FAT_read(0); if (result) return result; // abort on read error if (FAT_buffer[510] != 0x55 || FAT_buffer[511] != 0xAA) return 0xAA; // abort if signature bytes not found in MBR type = FAT_buffer[PARTITION_START+4]; // get type code for partition one // TODO: check here for valid MMC types ie FAT16 = 0x // get start of FAT partition. lba_begin = FAT_buffer[PARTITION_START+11]; lba_begin <<=8; lba_begin += FAT_buffer[PARTITION_START+10]; lba_begin <<=8; lba_begin += FAT_buffer[PARTITION_START+9]; lba_begin <<=8; lba_begin += FAT_buffer[PARTITION_START+8]; /* Read Boot Sector at lba Begin bytes_per_sector at 0x0B sectors_per_cluster at 0x0D number_of_reserved_sectors at 0x0E number_of_fats at 0x10 secters_per_fat at 0x24 root_director_first_cluster 0x2c */ // read FAT Volume ID result = FAT_read(lba_begin); if (result) return result; // abort on read error //if (FAT_buffer[510] != 0x55 || FAT_buffer[511] != 0xAA) // return 0xAA; // abort if signature bytes not found in MBR sectors_per_cluster= FAT_buffer[0x0D]; number_of_reserved_sectors = FAT_buffer[ 0x0f]; number_of_reserved_sectors <<=8; number_of_reserved_sectors += FAT_buffer[ 0x0e]; number_of_fats = FAT_buffer[0x10]; bytes_per_sector = FAT_buffer[0x0c]; bytes_per_sector <<=8; bytes_per_sector += FAT_buffer[0x0b]; // BPB_FATSz16 sectors_per_fat = FAT_buffer[0x17]; sectors_per_fat <<=8; sectors_per_fat += FAT_buffer[0x16]; //BPB_RootEntCnt BPB_RootEntCnt = FAT_buffer[0x12]; BPB_RootEntCnt <<=8; BPB_RootEntCnt += FAT_buffer[0x11]; /* FOR FAT32.... sectors_per_fat = FAT_buffer[0x27]; sectors_per_fat <<=8; sectors_per_fat += FAT_buffer[0x26]; sectors_per_fat <<=8; sectors_per_fat += FAT_buffer[0x25]; sectors_per_fat <<=8; sectors_per_fat += FAT_buffer[0x24]; root_director_first_cluster = FAT_buffer[0x2f]; root_director_first_cluster <<=8; root_director_first_cluster += FAT_buffer[0x2e]; root_director_first_cluster <<=8; root_director_first_cluster += FAT_buffer[0x2d]; root_director_first_cluster <<=8; root_director_first_cluster += FAT_buffer[0x2c]; */ // note: FAT16 clusters start after root directory. FAT16_fat_begin_lba = lba_begin + number_of_reserved_sectors; FAT16_root_dir_first_cluster = FAT16_fat_begin_lba + ( number_of_fats * sectors_per_fat); FAT16_cluster_begin_lba = FAT16_root_dir_first_cluster+ ((BPB_RootEntCnt*32) + (bytes_per_sector-1))/bytes_per_sector; // ((BPB_RootEntCnt*32) + (bytes_per_sector))/bytes_per_sector; FAT16_sectors_per_cluster = sectors_per_cluster; FAT16_dir_first_cluster=FAT16_root_dir_first_cluster; FAT16_parent_dir_first_cluster = FAT16_root_dir_first_cluster; return 0;}/*** FAT_get_label* @brief copys the volume label* @param destentaion for label* @return non zero for error.**/uint8 FAT_get_label(uint8 label[]){ uint8 result,i,j; // read root dir result = FAT_read(FAT16_root_dir_first_cluster); if (result) return result; // abort on fail // find entry with ATTR_VOLUME_ID for (i=0;i<512/32;i++){ if (FAT_buffer[(i*32)+11] == FILE_ATTR_VOLUME_ID){ for (j=0;j<11;j++) label[j]=FAT_buffer[(i*32)+j]; label[11]=0; return 0;// we have a volume } } return 1; }/*** FAT_readCluster* @brief Reads a sector from a cluster into the buffer* @param cluster Clusterto read from* @param sector_offset Sector to read from within cluster* @return error code from FAT_read()**/uint8 FAT_readCluster(uint32 cluster, uint8 sector_offset) { uint8 result=0; uint32 lba_addr; // calculate sector to read lba_addr = FAT16_cluster_begin_lba + ((cluster-2) * FAT16_sectors_per_cluster); lba_addr += sector_offset; result = FAT_read(lba_addr); return result;}/*** FAT_NextCluster* @brief looks up a cluster in fat* @param cluster current cluster* @return next cluster* @return 0 for error * @return 0xffffff for end of file.**/uint32 FAT_NextCluster(uint32 cluster){ uint8 result=0; uint32 sector,position,next; if (cluster ==0 ) cluster = 2; // check for reserved cluster mishap ;) //sector = cluster / 128; sector = cluster / 256; // for fat 16 result = FAT_read(FAT16_fat_begin_lba+sector); if (result) return 0; //position = (cluster - (sector * 128)) * 4; for fat 32 position = (cluster - (sector * 256)) * 2; // for fat 16 /* // read 4 bytes (FAT32) next = FAT_buffer[position+3]; next <<= 8; next += FAT_buffer[position+2]; next <<= 8; next = FAT_buffer[position+1]; next <<= 8; next += FAT_buffer[position]; */ // read 2 Bytes (FAT16) next = FAT_buffer[position+1]; next <<= 8; next += FAT_buffer[position]; // mask off last 4 bits (FAT32) // next &= 0x0ffffff; if (next == 0xffff) next = 0xffffffff; return next;}/*** FAT_read * @param filenumber 32bit uInt pointing to file of interst. * @param dir_first_entry 32bit uInt pointing to first cluster of directory * @return error code * * Read any directory of the disk and obtain details * about FAT entry number <filenumber> * * error codes: * 0x00 mp3file found * 0x02 end of directory * 0x59 deleted file * **/uint8 FAT_readFile(uint32 filenumber, uint32 dir_first_cluster){ uint8 result,i,lfn; uint8 record,lfn_record,nmeChkSm,lfnchksm; uint8 attrib; uint16 lfn_entry,fat_entry; // position in buffer of entry 0-512 uint32 sector,lfn_sector;// uint16 cluster;// uint32 size; record = filenumber & 0x0F; sector = filenumber >> 4; fat_entry = record << 5; // read the root dir result = FAT_read(dir_first_cluster+sector); if (result) return result; // abort on non-zero reply // check firstByte if (FAT_buffer[fat_entry] == 0x00){ // end of directory FAT16_entryMAX = filenumber; return 2; } else if (FAT_buffer[fat_entry] != 0xe5){ // not used (aka deleted) // exit on . and .. if (FAT_buffer[fat_entry]=='.') return 0x59; // get the attrib byte attrib = FAT_buffer[fat_entry+FAT16_LDIR_Attr];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -