8051 FAT16/32

14 отговора 1044 прегледа
#1

8051 FAT16/32

Noikoi ima li driver za FAT16/32 za 8051?

Отговор
в отговор на VlLO #2

Хах..

Какво е общото между File Allocation Table и 8051 Microcontroller ?
Не, че не би могло да има, ама въпросът ти е много олекнал във въздуха.

"Ако знаеш какво търсиш, леко ще го откриеш"

Отговор
в отговор на lnfrared Remote #3

Re: Хах..

"Какво е общото между File Allocation Table и 8051 Microcontroller ? "
Драйвера!

Бог да пази познати и непознати!

Редактирано от brains на

Отговор
в отговор на VlLO #4

Re: 8051 FAT16/32

Едно време по нета имаше няколко МП3 проекта с 8051 и твърд диск с ФАТ и ЦД, ако става дума за нова разработка по-добре виж за някой АРМ - можеш направо на ембедед линукс да си пуснеш проекта.

Отговор
в отговор на kk #5

Re: 8051 FAT16/32

Abe mom4eta za kakav draiver si govorite tuka bre tva da ne ti e PC ?

Mejdo drugoto ne znam za "edno vreme" ama v momenta v neta ima dosta ne6ta koito 6te ti pomognat da varjej edin ATA hard kam 8051.

I o6te ne6to, lo6o si se sprql to4no na tezi MCU'ta probvai da mine6 na ATMEL AVR MCU'ta, mnogo po mo6tni sa s ilqdi funkcii, lesni za sajivqvane i nai vajnoto :

EVTINI SA ! i moje6 da si gi zeme6 po4ti ot vsakade.

Osvem tova v neta info za tqh ima mnogo AVR-ATA; AVR-CFcard; AVR-SDcard; AVR-MMC;

Отговор
в отговор на Brainstorm #6

Re: 8051 FAT16/32

Хе-хе, че то само РС-тата ли имат драйвери ;)
един полезен линк:
[линк]
Междодругото Атмел все още произвеждат процесори 100% съвместими с 8051 ;)

Отговор
в отговор на imagination #7

Re: 8051 FAT16/32

Definiciata na "Driver" e programe koqto da se uprqvq s fizi4eskata 4ast na predavaneto na danni (protokola).

V konkretniq slu4ei za draiver ne mojem da govorim i pri4inita e slednata:
4oveka ne e definiral fizi4eskata 4ast na vrazkata MCU<>ATA !

6toto priatelu az moga da ti izpratq sorsa, ama ti ako ne si svarzal pravilno 4ipa, edva li 6te stane ne6to nali ?

Lo6oto e 4e ako ne poznava6 protokola za transver po ATA edvali 6te moje6 da se useti6 i da si korigira6 sorca.

Moq savet e da potarsite info otnosno kak to4no da 4etete i zapisvate v registrite na edin ATA hard i sled tova da si tarsite info otnosno struktorata na FAT.

Mejdo drugoto toq link go znam ot dosta vreme(i az ot tam razbrah kak stavat ne6tata), no vse pak mersi :)

I da, Atmel pravqt 8051 no prosto AVR sa po dobri ;)

Редактирано от brainstorm_bg на

Отговор
в отговор на brainstorm_bg #8

Re: 8051 FAT16/32

Blagodaria!

Mmnogo prikazki, a nishto konkretno, daje drivera koito mi tribva vuv linka koito mi dadohte - niama source.

Mersi vse pak.

Отговор
в отговор на brainstorm_bg #9

Re: 8051 FAT16/32

Всъщност лик-а беше за VILO, мо щом ти е свършил работа :) данеговорим че е първият, който излиза в google. Дали ATMEL са по-добри - немога да твърдя, това е като спора блондинки <-> брюнетки, windows <-> linux, зависи от конкретното приложение ;)
А драйвера не винаги обслужва физическа част :) Има драйвери, които седят на "междинно" ниво (ramdrive.sys, EMM386.exe) ако си работил навремето с ДОС. Погледни OSI модела имаш дравер за мрежовият интерфейст, дриг който ти обслужва tcp/ip, треи за netbios и т.н.
За конкретният случай, аз бих написал един драйвер за физическото ниво и отделно друг за файловата система :)
Поздрави.

Отговор
в отговор на Vilo #10

Re: 8051 FAT16/32

Това, че неможеш да четеш е напрво срамно :(

Отговор
в отговор на imagination #11

Re: 8051 FAT16/32

Prav si priatelu, krai na spora :)

Отговор
в отговор на Vilo #12

Re: 8051 FAT16/32

i men mi trebvase FAT i zeh si napisah!
hic ne sam i tarsil po internet!
ne e slojno!

Отговор
в отговор на brainstorm_bg #13

Re: 8051 FAT16/32

Izkliuchvam"kompetentnostta na niakoi komentirali".
Eto za CALL-151 i ostanalite, ne slojen DRIVER za FAT16 s funkcii samo za chetene ot root dir:

#ifndef FILE_SYS_H
#define FILE_SYS_H

#ifndef NULL
#define NULL 0
#endif

#ifndef EOF
#define EOF -1
#endif

typedef struct
{
unsigned char name[13];
unsigned char attr;
unsigned int ftime;
unsigned int fdate;
unsigned long fsize;
unsigned long folder_place;
} ffblk;

typedef struct
{
unsigned int day : 5;
unsigned int month : 4;
unsigned int year : 7;
} DATE_BITFIELD;
typedef union
{
unsigned int date_word;
DATE_BITFIELD date;
sHILO16c dateHILO;
} DIR_ENT_DATE;

typedef struct
{
unsigned int x2sec : 5;
unsigned int min : 6;
unsigned int hour : 5;
} TIME_BITFIELD;
typedef union
{
unsigned int time_word;
TIME_BITFIELD time;
sHILO16c timeHILO;
} DIR_ENT_TIME;

typedef struct
{ // 32 byte structure
unsigned char name_entry[11];
unsigned char attr;
unsigned char reserved;
unsigned char crt_tenth_sec;
DIR_ENT_TIME crt_time;
DIR_ENT_DATE crt_date;
DIR_ENT_DATE acc_date;
unsigned int start_clus_hi;
DIR_ENT_TIME mod_time;
DIR_ENT_DATE mod_date;
uHILO16 start_clus_lo;
uHILO32 file_size;
} FILE_DIR_ENTRY;

typedef struct
{ // 552 bytes (+4 overhead using malloc) ==> 556 bytes required per file opened
// unsigned char name[12]; // Filename as 8.3 0x20-padded string
unsigned int clus_start; // Starting cluster of open file
unsigned int clus_current; // Current cluster of open file
unsigned int clus_next; // Next (reading) cluster of open file
unsigned int clus_prev; // Previous cluster of open file
unsigned char sec_offset; // Current sector withing current cluster
unsigned long entry_sec_addr; // Sector address of File entry of open file
FILE_DIR_ENTRY *file_dep; // Entry Pointer to the offset of the File Info
unsigned char buff[512]; // Open file read/write buffer
unsigned long length; // Length of file
unsigned long position; // Current position in file relative to begining
unsigned char mode; // 0=>closed, 1=>open for read, 2=>open for write, 3=> open for append
unsigned char error; // Error indicator
unsigned char EOF_flag; // End of File Flag
unsigned char *pntr; // Pointer for file data use
unsigned char used_flag; // Flag to see if the file is used or not
} FILE;

enum {CLOSED=0,READ, WRITE, APPEND};
enum {SCAN_DIR_R, SCAN_DIR_W, SCAN_FILE_R, SCAN_FILE_W};
enum {CHAIN_R, CHAIN_W, SINGLE, START_CHAIN, END_CHAIN};

#define ATTR_READ_ONLY 0x01
#define ATTR_HIDDEN 0x02
#define ATTR_SYSTEM 0x04
#define ATTR_VOL_ID 0x08
#define ATTR_DIRECTORY 0x10
#define ATTR_ARCHIVE 0x20
#define ATTR_LONG_NAME 0x0F

#define fgetc fgetc_
#define fputc fputc_

enum {SEEK_CUR, SEEK_END, SEEK_SET};

unsigned char ascii_to_char(unsigned char ascii_char);
unsigned char valid_file_char(unsigned char file_char);
unsigned long clust_to_addr (unsigned int clust_no);
unsigned int next_cluster(unsigned int current_cluster, unsigned char mode);
signed char file_name_conversion(unsigned char *input_name, unsigned char *save_name);
FILE *fopenc(unsigned char code *NAMEC, unsigned char MODEC);
FILE *fopen(unsigned char *NAME, unsigned char MODE);
signed int fclose(FILE *rp);
signed int fget_file_info(unsigned char *NAME, unsigned long *F_SIZE, unsigned char *F_CREATE,
unsigned char *F_MODIFY, unsigned char *F_ATTRIBUTE, unsigned int *F_CLUS_START);
signed int fget_file_infoc(unsigned char code *NAMEC, unsigned long *F_SIZE, unsigned char *F_CREATE,
unsigned char *F_MODIFY, unsigned char *F_ATTRIBUTE, unsigned int *F_CLUS_START);
signed int fgetc_(FILE *rp);
signed int fread(void *rd_buff, unsigned int dat_size, unsigned int num_items, FILE *rp);
signed int fread_play(FILE *rp);
void read_directory(void);

#endif


#include "file_sys.h"



extern unsigned char _FF_buff[512];
extern unsigned char BPB_SecPerClus;
extern uHILO16 BPB_RsvdSecCnt;
extern uHILO16 BPB_RootEntCnt;
extern uHILO16 BPB_FATSz16;
extern unsigned char BPB_FATType;
extern unsigned char BS_VolLab[12];
extern unsigned int _FF_PART_ADDR;
extern unsigned long _FF_ROOT_ADDR;
extern uHILO32 BS_VolSerial;
extern unsigned int _FF_FAT1_ADDR;
extern unsigned long _FF_FAT2_ADDR;
extern unsigned int FirstDataSector;
extern unsigned char _FF_error;
extern unsigned long _FF_buff_addr;
extern unsigned int DataClusTot;
unsigned char NextClusterValidFlag;
extern unsigned char _FF_FULL_PATH[_FF_PATH_LENGTH];
extern unsigned int clus_0_counter;
unsigned long _FF_scan_addr;
extern unsigned long OFFSET;
//
extern volatile unsigned int data PBptr;
extern unsigned char xdata PlayBuffer[PLAY_BUFFSIZE];
//

FILE _FF_File_Space_Allocation[_FF_MAX_FILES_OPEN];

FILE *_FF_MALLOC(void)
{
unsigned char c;

for (c=0; c<_FF_MAX_FILES_OPEN; c++)
{ // Look for the first unused area
if (_FF_File_Space_Allocation[c].used_flag == 0)
{ // If not in use, flag that it is in use and return pointer location
_FF_File_Space_Allocation[c].used_flag = 1;
return (&_FF_File_Space_Allocation[c]);
}
}

return (NULL); // All file allocated space is currently in use
}

#define _FF_free(qp) qp->used_flag = 0

#define _FF_strcpyf strcpy
#define _FF_sprintf sprintf
#define _FF_printf printf
#define _FF_strlen strlen
#define _FF_strncmp strncmp
#define _FF_strrchr strrchr



// Conversion file to change an ASCII valued character into the calculated value
unsigned char ascii_to_char(unsigned char ascii_char)
{
unsigned char temp_char;

if (ascii_char < 0x30) // invalid, return error
return (0xFF);
else if (ascii_char < 0x3A)
{ //number, subtract 0x30, retrun value
temp_char = ascii_char - 0x30;
return (temp_char);
}
else if (ascii_char < 0x41) // invalid, return error
return (0xFF);
else if (ascii_char < 0x47)
{ // lower case a-f, subtract 0x37, return value
temp_char = ascii_char - 0x37;
return (temp_char);
}
else if (ascii_char < 0x61) // invalid, return error
return (0xFF);
else if (ascii_char < 0x67)
{ // upper case A-F, subtract 0x57, return value
temp_char = ascii_char - 0x57;
return (temp_char);
}
else // invalid, return error
return (0xFF);
}

// Function to see if the character is a valid 8.3 FILENAME character
unsigned char valid_file_char(unsigned char file_char)
{
if ((file_char < 0x20) || (file_char==0x22) || (file_char==0x2A) || (file_char==0x2B) ||
(file_char==0x2C) || (file_char==0x2E) || (file_char==0x2F) ||
((file_char>=0x3A)&&(file_char<=0x3F)) || ((file_char>=0x5B)&&(file_char<=0x5D)) ||
(file_char==0x7C) || (file_char==0xE5) )
return (0);
else
return (file_char);
}

#ifdef _DEBUG_FUNCTIONS_
#define _DEBUG_SCANDIR_
#ifdef _DEBUG_SCANDIR_
code signed char _scandir_start_str_[] = "\r\nSCAN_DIRECTORY(\"%s\", 0x%lX, Mode-%d) - ";
code signed char _scandir_debug_str_[] = "\t[ScanDirHere-%02d](%lX)";
code signed char _scandir_info_str_[] = "\t[%s=?%s]";
#endif
#endif

// Function will scan the directory @ _FF_ROOT_ADDR or _FF_DIR_ADDR (which ever
// is applicable and will return a FILE_DIR_ENTRY pointer if successful (depends
// on the mode) or a NULL if an error occurs.
FILE_DIR_ENTRY *scan_directory(unsigned char *NAME, unsigned char mode_flag)
{
unsigned int ent_cntr, ent_max, n;
unsigned long temp_addr;
unsigned char aval_flag, name_store[14];
FILE_DIR_ENTRY *dep, *dep_save;
#ifdef _DEBUG_SCANDIR_
printv(0,_scandir_start_str_, NAME, _FF_DIR_ADDR<<9, mode_flag);
#endif

aval_flag = 0;
ent_cntr = 0; // set to 0

// error if name not set right
if (file_name_conversion(NAME, name_store))
{
#ifdef _DEBUG_SCANDIR_
printv(0,_scandir_debug_str_, 1);
#endif
return (0);
}

_FF_scan_addr = _FF_ROOT_ADDR;
ent_max = BPB_RootEntCnt.ival;

#ifdef _DEBUG_SCANDIR_
printv(0,_scandir_debug_str_, 99, _FF_scan_addr<<9);
#endif
while (ent_cntr < ent_max)
{
if (mmcRead(_FF_scan_addr, _FF_buff))
{ // read error
#ifdef _DEBUG_SCANDIR_
printv(0,_scandir_debug_str_, 3, _FF_scan_addr<<9);
#endif
return (0);
}
dep = (FILE_DIR_ENTRY *) _FF_buff; // set directory entry pointer to the beginning of the entry buffer

for (n=0; n<16; n++)
{
if (dep->name_entry[0]==0)
{ // There are no more entries in this folder
if (aval_flag == 0)
{
dep_save = dep;
temp_addr = _FF_scan_addr;
aval_flag = 1;
}
#ifdef _DEBUG_SCANDIR_
printv(0,_scandir_debug_str_, 4, _FF_scan_addr<<9);
#endif
goto NoMoreEntries;
}
else if ((dep->name_entry[0]==0xE5) && (aval_flag==0))
{ // found a deleted entry space set temp_addr
dep_save = dep;
temp_addr = _FF_scan_addr;
aval_flag = 1;
}
else
{
#ifdef _DEBUG_SCANDIR_
printv(0,_scandir_info_str_,name_store,dep->name_entry);
#endif
if (_FF_strncmp(name_store, dep->name_entry, 11)==0)
{ // found entry set VALID_ADDR to the exact entry location (Full Address)
#ifdef _DEBUG_SCANDIR_
printv(0,_scandir_debug_str_, 5, (_FF_scan_addr<<9) & (n<<4));
#endif
switch (mode_flag)
{
#ifdef _DIRECTORIES_SUPPORTED_
case SCAN_DIR_W:
if (dep->attr & ATTR_DIRECTORY)
{
#ifdef _DEBUG_SCANDIR_
printv(0,_scandir_debug_str_, 51, 0);
#endif
return (0);
}
break;
case SCAN_DIR_R:
if (dep->attr & ATTR_DIRECTORY)
{
#ifdef _DEBUG_SCANDIR_
printv(0,_scandir_debug_str_, 52, 0);
#endif
return (dep);
}
break;
#endif
case SCAN_FILE_R:
case SCAN_FILE_W:
if ((dep->attr & ATTR_DIRECTORY) == 0)
{
return (dep);
}
break;
}
}
}
dep++; // increment the directory entry pointer
ent_cntr++;
}
_FF_scan_addr++;
}

NoMoreEntries:
switch (mode_flag)
{
#ifndef _READ_ONLY_
case SCAN_FILE_W:
if (aval_flag)
{ // If there was a previous avaliable entry
if (temp_addr != _FF_buff_addr)
{
if (mmcRead(temp_addr, _FF_buff))
{
#ifdef _DEBUG_SCANDIR_
printv(0,_scandir_debug_str_, 8, _FF_scan_addr<<9);
#endif
return (0);
}
}
#ifdef _DEBUG_SCANDIR_
printv(0,_scandir_debug_str_, 9, temp_addr<<9);
#endif
_FF_scan_addr = temp_addr;
return (dep_save);
}
else
{ // No more entries
#ifdef _DEBUG_SCANDIR_
printv(0,_scandir_debug_str_, 14, 0);
#endif
return (0);
}
break;
#endif
case SCAN_FILE_R:
#ifdef _DEBUG_SCANDIR_
printv(0,_scandir_debug_str_, 15, 0);
#endif
default:
return (0);
}
}

#ifdef _DEBUG_ON_
signed char code FileList_str[] = "\r\nFile Listing for: ROOT\x5c";
signed char code SC_str[] = "]\t(%X)";
signed char code Entry_str[] = "\t[%ld] bytes\t(%X)\t";

// Function to display all files and folders in the root directory,
// with the size of the file in bytes within the [brakets]
void read_directory(void)
{
unsigned char valid_flag;
unsigned int c, n, d, m, ent_max;
FILE_DIR_ENTRY *dep;
printv(0,FileList_str);
ent_max = BPB_RootEntCnt.ival;
d = 0;
m = 0;
while (d<ent_max)
{
if (mmcRead(_FF_ROOT_ADDR+m, _FF_buff)) break;
dep = (FILE_DIR_ENTRY *) _FF_buff;
for (n=0; n<16; n++)
{
valid_flag = 1;
if (dep->name_entry[0]==0)
{ // a '\0' in this location means no more entries avaliable
return; // clear entries
}
for (c=0; ((c<11)&&(valid_flag)); c++)
{ // make sure all the characters in the file/folder name are valid
if (valid_file_char(dep->name_entry[c]) == 0)
valid_flag = 0;
}
if (valid_flag)
{
putchar('\r');
putchar('\n');
putchar('\t');
if ((dep->attr) & ATTR_DIRECTORY)
putchar('[');
for (c=0; c<8; c++)
{
if (dep->name_entry[c]==0x20)
c=8;
else
putchar(dep->name_entry[c]);
}
if ((dep->attr) & ATTR_DIRECTORY)
{
printv(0,SC_str, dep->start_clus_lo);
}
else
{
putchar('.');
for (c=8; c<11; c++)
{
if ((dep->name_entry[c])==0x20)
c=11;
else
putchar(dep->name_entry[c]);
}
printv(0,Entry_str, dep->file_size, dep->start_clus_lo);
}
}
dep++;
d++;
}
m++;
}
putchar('\r');
putchar('\n');
}
#endif
signed char code VolSerialStr[] = "\r\n\tVolume Serial:\t[0x%08lX]";
signed char code VolLabelStr[] = "\r\n\tVolume Label:\t[%s]\r\n";

// Convert a cluster number into a read address
unsigned long clust_to_addr(unsigned int clust_no)
{
unsigned long FirstSectorofCluster;

if (clust_no < 2)
return (0);

FirstSectorofCluster = ((clust_no - 2) * (unsigned long) BPB_SecPerClus) + (unsigned long) FirstDataSector;

return (FirstSectorofCluster + _FF_PART_ADDR);
}

#ifdef _DEBUG_FUNCTIONS_
#define _DEBUG_NEXTCLUS_
#endif
#ifdef _DEBUG_NEXTCLUS_
code signed char _nextclus_debug_str_[] = "\tNextClusHere-%02d";
code signed char _nextclus_info_str_[] = "\r\nNextClus(%X,%d)";
#endif

// Find the cluster that the current cluster is pointing to
unsigned int next_cluster(unsigned int current_cluster, unsigned char mode)
{
unsigned int calc_sec, calc_offset;
uHILO16 next_clust;
unsigned long addr_temp;

#ifdef _DEBUG_NEXTCLUS_
printv(0,_nextclus_info_str_, current_cluster, mode);
#endif

if (current_cluster<=1) // If cluster is 0 or 1, its the wrong cluster
{
NextClusterValidFlag = 0;
#ifdef _DEBUG_NEXTCLUS_
printv(0,_nextclus_debug_str_, 1);
#endif
return (0);
}

if (BPB_FATType == 0x36) // if FAT16
{
// FAT16 table address calculations
calc_sec = (current_cluster >> 8) + BPB_RsvdSecCnt.ival;
calc_offset = (current_cluster & 0xFF) << 1;
}
else // not FAT12 or FAT16, return EOF
{
NextClusterValidFlag = 0;
#ifdef _DEBUG_NEXTCLUS_
printv(0,_nextclus_debug_str_, 2);
#endif
return (0);
}
addr_temp = _FF_PART_ADDR+(calc_sec);
switch (mode)
{
case SINGLE: // This is a single cluster lookup
if (mmcRead(addr_temp, _FF_buff))
{
NextClusterValidFlag = 0;
#ifdef _DEBUG_NEXTCLUS_
printv(0,_nextclus_debug_str_, 3);
#endif
return (0);
}
break;
case CHAIN_R:
if (addr_temp!=_FF_buff_addr)
{ // Is the address of lookup is different then the current buffere address
if (mmcRead(addr_temp, _FF_buff)) // Read new table info
{
NextClusterValidFlag = 0;
#ifdef _DEBUG_NEXTCLUS_
printv(0,_nextclus_debug_str_, 7);
#endif
return (0);
}
}
break;
}
next_clust.cval.HI = _FF_buff[calc_offset+1];
next_clust.cval.LO = _FF_buff[calc_offset];
NextClusterValidFlag = 1;
return (next_clust.ival);
}

// Convert a constant string file name into the proper 8.3 FAT format
signed char file_name_conversion(unsigned char *input_name, unsigned char *save_name)
{
unsigned char n, c;

c = 0;
for (n=0; n<14; n++)
{
if (valid_file_char(input_name[n])!=0)
{
// If the character is valid, save in uppercase to file name buffer
save_name[c] = toupper(input_name[n]);
c++;
}
else if (input_name[n]=='.')
{
// If it is a period, back fill buffer with [spaces], till 8 characters deep
while (c<8)
{
save_name[c] = 0x20;
c++;
}
}
else if (input_name[n]==0)
{ // If it is NULL, back fill buffer with [spaces], till 11 characters deep
while (c<11)
{
save_name[c] = 0x20;
c++;
}
break;
}
else
{
_FF_error = NAME_ERR;
return ((signed char)EOF);
}
if (c>=11)
break;
}
save_name[c] = 0;

return (0);
}

#ifdef _DEBUG_FUNCTIONS_
#define _DEBUG_PREVCLUS_
#endif
#ifdef _DEBUG_PREVCLUS_
code signed char _prevclus_debug_str_[] = "\tPrevClusHere-%02d";
code signed char _prevclus_info_str_[] = "\r\nPrevClus(%X)";
#endif
// Find the first cluster that is pointing to clus_no
unsigned int prev_cluster(unsigned int clus_no)
{
unsigned int calc_temp, calc_clus;

#ifdef _DEBUG_PREVCLUS_
printv(0,_prevclus_info_str_, clus_no);
#endif

if (clus_no==0)
{ // Start from the last previous known cluster pointing to 0
calc_temp = clus_0_counter;
}
else
{
calc_temp = 2;
}

_FF_buff_addr = 0; // Clear to make sure it reads the buffer the first time through
while (calc_temp <= DataClusTot)
{
calc_clus = next_cluster(calc_temp, CHAIN_R);
if (NextClusterValidFlag && (calc_clus == clus_no))
{
if (clus_no == 0)
clus_0_counter = calc_temp;
return (calc_temp);
}
else if (NextClusterValidFlag == 0)
{
#ifdef _DEBUG_PREVCLUS_
printv(0,_prevclus_debug_str_, 1);
#endif
return (0);
}
calc_temp++;
}

#ifdef _DEBUG_PREVCLUS_
printv(0,_prevclus_debug_str_, 2);
#endif
return (0);
}


// Open a file, name stored in string fileopen
FILE *fopenc(unsigned char code *NAMEC, unsigned char MODEC)
{
unsigned char temp_path[_FF_PATH_LENGTH];

_FF_strcpyf(temp_path, NAMEC);

return(fopen(temp_path, MODEC));
}

FILE *fopen(unsigned char *NAME, unsigned char MODE)
{
FILE *rp;
uHILO32 temp32;
if (MODE!=READ)
{
#ifdef _DEBUG_FOPEN_
printv(0,_fopen_debug_str_, 1);
#endif
return (NULL);
}
rp = _FF_MALLOC();
if (rp == 0)
{ // Could not allocate requested memory
_FF_error = ALLOC_ERR;
#ifdef _DEBUG_FOPEN_
printv(0,_fopen_debug_str_, 2);
#endif
return (NULL);
}
(rp->file_dep) = scan_directory(NAME, SCAN_FILE_R); // Find File
if ((rp->file_dep) == NULL)
{ // An Error Occurred // No file found
_FF_free(rp);
#ifdef _DEBUG_FOPEN_
printv(0,_fopen_debug_str_, 5);
#endif
return (NULL);
}
// Save Starting Cluster
temp32.cval.ML = (rp->file_dep)->start_clus_lo.cval.LO;
temp32.cval.LO = (rp->file_dep)->start_clus_lo.cval.HI;
rp->clus_start = temp32.ival.LO;
// Set Current Cluster
rp->clus_current = rp->clus_start;
// Set Previous Cluster to 0 (indicating @start)
rp->clus_prev = 0;
// Save file length
temp32.cval.HI = (rp->file_dep)->file_size.cval.LO;
temp32.cval.MH = (rp->file_dep)->file_size.cval.ML;
temp32.cval.ML = (rp->file_dep)->file_size.cval.MH;
temp32.cval.LO = (rp->file_dep)->file_size.cval.HI;
rp->length = temp32.lval;
// Set Current Position to 0
rp->position = 0;
{
// Set and save next cluster #
rp->clus_next = next_cluster(rp->clus_current, SINGLE);
if (NextClusterValidFlag == 0)
{ // Not valid cluster
_FF_free(rp);
#ifdef _DEBUG_FOPEN_
printv(0,_fopen_debug_str_, 10);
#endif
return (NULL);
}
}
if ((rp->length==0) && (rp->clus_start==0))
{ // Check for Blank File
// IF trying to open a blank file to read, ERROR
_FF_error = MODE_ERR;
_FF_free(rp);
#ifdef _DEBUG_FOPEN_
printv(0,_fopen_debug_str_, 11);
#endif
return (NULL);
}
// Save the file offset to read entry
rp->entry_sec_addr = _FF_scan_addr;
// Set sector offset to 0
rp->sec_offset = 0;
if (mmcRead(clust_to_addr(rp->clus_current), rp->buff))
{
_FF_free(rp);
#ifdef _DEBUG_FOPEN_
printv(0,_fopen_debug_str_, 13);
#endif
return (NULL);
}
rp->pntr = rp->buff;
rp->mode = MODE;
_FF_error = NO_ERR;
return(rp);
}

// Close an open file
signed int fclose(FILE *rp)
{
// Clear File Structure
_FF_free(rp);
return(0);
}

//
signed int fget_file_infoc(unsigned char code *NAMEC, unsigned long *F_SIZE, unsigned char *F_CREATE,
unsigned char *F_MODIFY, unsigned char *F_ATTRIBUTE, unsigned int *F_CLUS_START)
{
unsigned char temp_path[_FF_PATH_LENGTH];

_FF_strcpyf(temp_path, NAMEC);

return (fget_file_info(temp_path, F_SIZE, F_CREATE, F_MODIFY, F_ATTRIBUTE, F_CLUS_START));
}

signed char code _time_date_str[] = "%02d/%02d/%04d %02d:%02d:%02d";

signed int fget_file_info(unsigned char *NAME, unsigned long *F_SIZE, unsigned char *F_CREATE,
unsigned char *F_MODIFY, unsigned char *F_ATTRIBUTE, unsigned int *F_CLUS_START)
{
FILE_DIR_ENTRY *dep;
DIR_ENT_TIME ff_time;
DIR_ENT_DATE ff_date;
uHILO32 temp32;
uHILO16 temp16;
unsigned char *qp;

qp = NAME;
while (*qp !=0 )
{
if (valid_file_char(*qp++)==0) // verify that this is a valid charater
return ((signed int)EOF);
}
dep = scan_directory(NAME, SCAN_FILE_R); // Find File
if (dep==0)
{ // no entry found
return ((signed int)EOF);
}
// Save ATTRIBUTE Byte from location
*F_ATTRIBUTE = dep->attr;
// Get the Starting cluster and save it to the location *F_CLUS_START
temp16.cval.HI = dep->start_clus_lo.cval.LO;
temp16.cval.LO = dep->start_clus_lo.cval.HI;
*F_CLUS_START = temp16.ival;
// Get File Size and save it to the location *F_SIZE
temp32.cval.HI = dep->file_size.cval.LO;
temp32.cval.MH = dep->file_size.cval.ML;
temp32.cval.ML = dep->file_size.cval.MH;
temp32.cval.LO = dep->file_size.cval.HI;
*F_SIZE = temp32.lval;
// Get the Create time/date and save it to the location *F_CREATE
ff_time.timeHILO.HI = dep->crt_time.timeHILO.LO;
ff_time.timeHILO.LO = dep->crt_time.timeHILO.HI;
ff_date.dateHILO.HI = dep->crt_date.dateHILO.LO;
ff_date.dateHILO.LO = dep->crt_date.dateHILO.HI;
sprintf(F_CREATE, "%02d/%02d/%04d %02d:%02d:%02d",
ff_date.date.month, ff_date.date.day, ff_date.date.year+1980,
ff_time.time.hour, ff_time.time.min, ff_time.time.x2sec * 2);
// Get the Modify time/date and save it to the location *F_MODIFY
ff_time.timeHILO.HI = dep->mod_time.timeHILO.LO;
ff_time.timeHILO.LO = dep->mod_time.timeHILO.HI;
ff_date.dateHILO.HI = dep->mod_date.dateHILO.LO;
ff_date.dateHILO.LO = dep->mod_date.dateHILO.HI;
sprintf(F_MODIFY, "%02d/%02d/%04d %02d:%02d:%02d",
ff_date.date.month, ff_date.date.day, ff_date.date.year+1980,
ff_time.time.hour, ff_time.time.min, ff_time.time.x2sec * 2);
return (0);
}

// Get File data and increment file pointer
signed int fgetc_(FILE *rp)
{
unsigned char get_data;
unsigned long addr_temp;

if (rp==NULL)
return ((signed int)EOF);

if (rp->position == rp->length)
{
rp->error = POS_ERR;
return ((signed int)EOF);
}
get_data = *rp->pntr;
if (rp->pntr == &rp->buff[511])
{ // Check to see if pointer is at the end of a sector
if ((++(rp->sec_offset)) < BPB_SecPerClus)
{ // Goto next sector if not at the end of a cluster
addr_temp = clust_to_addr(rp->clus_current) + (rp->sec_offset);
}
else
{ // End of Cluster, find next
if (rp->clus_next>=0xFFF8) // No next cluster, EOF marker
{
rp->EOF_flag = 1; // Set flag so Putchar knows to get new cluster
rp->position++; // Only time doing this, position + 1 should equal length
return(get_data);
}
addr_temp = clust_to_addr(rp->clus_next);
rp->sec_offset = 0;
rp->clus_prev = rp->clus_current;
rp->clus_current = rp->clus_next;
rp->clus_next = next_cluster(rp->clus_current, SINGLE);
if (NextClusterValidFlag == 0)
return ((signed int)EOF);
}
if (mmcRead(addr_temp, rp->buff))
return ((signed int)EOF);
rp->pntr = &rp->buff[0];
}
else
rp->pntr++;

rp->position++;
return(get_data);
}

//
signed int fread(void *rd_buff, unsigned int dat_size, unsigned int num_items, FILE *rp)
{
unsigned char *temp_char_pntr;
unsigned int temp_int, temp_int2;
unsigned int no_bytes_cntr, i;

no_bytes_cntr = 0;
temp_char_pntr = rd_buff;
temp_int = dat_size * num_items;

for (i=0; i<temp_int; i++)
{
temp_int2 = fgetc_(rp);
if (temp_int2 == (unsigned int)EOF)
return (no_bytes_cntr);
else
{
*temp_char_pntr++ = (unsigned char) temp_int2;
no_bytes_cntr++;
}
}
return (no_bytes_cntr/dat_size);
}
//=========================================================

Отговор
в отговор на VlLO #14

Re: 8051 FAT16/32

Пирфекну!
Са остава да изкопираш и сите функции дето ги нема тук ами са #extern, плюс комуникацията с хардуера, плюс типа на контролера да кажеш, плюс.....
Да не обяснявам, че това ако го пуснеш на някой компилатор за микроконтролери най-вероятно ще се наложи да си го понапишеш наново, щото да кажем в майкрочипските микро-та до 18-та серия няма де да намериш 512 байта RAM и то само за ей туй:

unsigned char buff[512];

в оная сруктурка FILE дето иска петстотин педесе и кусур байта. Ако пък не дай си боже я има сичката тая мемори фри нейде, че да моеш да си я маллокваш ако компилираш на CCS PCW типа int ти е 8 бита , че и unsigned по дефоулт на сичкото отгоре.
......................
то инак е лесно да се копи-пейст

Отговор
в отговор на VlLO #15

Re: 8051 FAT16/32

e te ako tova e NE SLOJEN driver!
888reda!
moia izleze 588 i cete i pise po FAT16/32 i v pod-direktorii

tova razbirase mejdudrugoto... :-)

Отговор