📄 usbhost_fat.c
字号:
(FAT_BootSec.BytsPerSec - sec_offset) : num_bytes;
for (cnt = sec_offset; cnt < (sec_offset + n_bytes); cnt++) {
FATBuffer[cnt] = *buffer;
buffer++;
}
MS_BulkSend(sec_num, 1, FATBuffer);
tot_bytes_written += n_bytes;
clus_offset += n_bytes;
num_bytes -= n_bytes;
sec_num++;
}
if (num_bytes / FAT_BootSec.BytsPerSec) {
num_sec = num_bytes / FAT_BootSec.BytsPerSec;
MS_BulkSend(sec_num, num_sec, buffer);
buffer += (num_sec * FAT_BootSec.BytsPerSec);
tot_bytes_written += (num_sec * FAT_BootSec.BytsPerSec);
clus_offset += (num_sec * FAT_BootSec.BytsPerSec);
num_bytes -= (num_sec * FAT_BootSec.BytsPerSec);
sec_num += num_sec;
}
if (num_bytes) {
MS_BulkRecv(sec_num, 1, FATBuffer);
for (cnt = 0; cnt < num_bytes; cnt++) {
FATBuffer[cnt] = *buffer;
buffer++;
}
MS_BulkSend(sec_num, 1, FATBuffer);
tot_bytes_written += num_bytes;
}
return (tot_bytes_written);
}
/*
**************************************************************************************************************
* GET NEXT CLUSTER
*
* Description: This function returns next cluster of the current cluster in the cluster chain. If the current
* cluster is the last cluster then this function returns 0
*
* Arguments : clus_no The cluster number for which the next cluster to be found
*
* Returns : next_clus if the current cluster is not the last cluster
* 0 if the current cluster is the last cluster
* Note: In practical cluster number 0 doesn't exist
*
**************************************************************************************************************
*/
uint16_t FAT_GetNextClus (uint16_t clus_no)
{
uint32_t sec_num;
uint32_t ent_offset;
uint16_t next_clus;
/* Get the sector number in the FAT that contains current cluster */
sec_num = FAT_BootSec.RsvdSecCnt + ((clus_no * 2) / FAT_BootSec.BytsPerSec);
/* Get the sector offset in the FAT where the current cluster is located */
ent_offset = (clus_no * 2) % FAT_BootSec.BytsPerSec;
MS_BulkRecv(sec_num, 1, FATBuffer); /* Read that sector */
next_clus = ReadLE16U(&FATBuffer[ent_offset]); /* Read the next cluster */
if (next_clus >= 0xFFF8 && next_clus <= 0xFFFF) { /* If that value is in between 0xFFF8 and 0xFFFF */
next_clus = 0; /* Current cluster is the end cluster */
}
return (next_clus);
}
/*
**************************************************************************************************************
* GET FREE CLUSTER
*
* Description: This function returns the free cluster if available
*
* Arguments : None
*
* Returns : free_clus if available
* 0 if not available(means the disk is full)
*
**************************************************************************************************************
*/
uint16_t FAT_GetFreeClus (void)
{
uint32_t num_sec;
uint32_t cnt;
uint32_t sec_num;
uint16_t free_clus;
sec_num = FAT_BootSec.RsvdSecCnt;
num_sec = FAT_BootSec.FATSz16;
while (sec_num < (FAT_BootSec.RsvdSecCnt + num_sec)) {
MS_BulkRecv(sec_num, 1, FATBuffer);
for (cnt = 0; cnt < FAT_BootSec.BytsPerSec; cnt += 2) {
if (ReadLE16U(&FATBuffer[cnt]) == 0) {
free_clus = (((sec_num - FAT_BootSec.RsvdSecCnt) * FAT_BootSec.BytsPerSec) + cnt) / 2;
return (free_clus);
}
}
sec_num++;
}
return (0);
}
/*
**************************************************************************************************************
* UPDATE FILE ALLOCATION TABLE
*
* Description: This function updates the file allocation table
*
* Arguments : curr_clus Offset of the current cluster number in the file allocation table
* value Value with which this offset to be updated
*
* Returns : None
*
**************************************************************************************************************
*/
void FAT_UpdateFAT (uint16_t curr_clus,
uint16_t value)
{
uint32_t sec_num;
uint32_t sec_offset;
sec_num = FAT_BootSec.RsvdSecCnt + (curr_clus * 2) / FAT_BootSec.BytsPerSec;
sec_offset = (curr_clus * 2) % FAT_BootSec.BytsPerSec;
MS_BulkRecv(sec_num, 1, FATBuffer);
WriteLE16U(&FATBuffer[sec_offset], value);
MS_BulkSend(sec_num, 1, FATBuffer);
}
/*
**************************************************************************************************************
* UPDATE THE FILE ENTRY
*
* Description: This function updates the file entry that is located in the root directory
*
* Arguments : entry Pointer to the FILE ENTRY structure which contains the information about the file
*
* Returns : None
*
**************************************************************************************************************
*/
void FAT_UpdateEntry (FILE_ENTRY *entry)
{
uint32_t sec_num;
uint32_t offset;
sec_num = entry->EntrySec;
offset = entry->EntrySecOffset;
MS_BulkRecv(sec_num, 1, FATBuffer);
WriteLE32U(&FATBuffer[offset + 28], entry->FileSize);
MS_BulkSend(sec_num, 1, FATBuffer);
}
/*
**************************************************************************************************************
* CREATING AN ENTRY
*
* Description: This function creates a file entry in the root directory if the file does not exist
*
* Arguments : ent_name_given The file name with which the entry is to be created
* entry Pointer to FILE ENTRY structure
*
* Returns : OK If the entry already exists or successfully created if it doesn't exists
* ERROR If failed to create the entry
*
**************************************************************************************************************
*/
int32_t FAT_CreateEntry (uint8_t *ent_name_given,
FILE_ENTRY *entry)
{
int32_t rc;
rc = FAT_FindEntry(ent_name_given, entry); /* Find for the given file name in the root directory */
if (rc == MATCH_FOUND) { /* If match found, return */
return (rc);
} else {
rc = FAT_GetFreeEntry(entry); /* Else get a free entry from the root directory */
if (rc != OK) {
return (rc);
} else {
FAT_PutSFN(ent_name_given, entry); /* Store the given short file name in that entry */
return (rc);
}
}
}
/*
**************************************************************************************************************
* GET GREE ENTRY
*
* Description: This function searches for a free entry in the root directory. If a free entry is found, the
* sector number and sector offset where the entry is located will be stored
*
* Arguments : entry Pointer to FILE_ENTRY structure
*
* Returns : OK If a free entry is found
* ERROR If no free entry is found
*
**************************************************************************************************************
*/
int32_t FAT_GetFreeEntry (FILE_ENTRY *entry)
{
uint32_t sec_num;
volatile uint8_t *buf;
uint8_t ent_type;
for (sec_num = FAT_BootSec.RootDirStartSec;
sec_num < (FAT_BootSec.RootDirStartSec + FAT_BootSec.RootDirSec);
sec_num++) {
MS_BulkRecv(sec_num, 1, FATBuffer);
buf = FATBuffer;
while (buf < (FATBuffer + FAT_BootSec.BytsPerSec)) {
ent_type = FAT_ChkEntType(buf);
if (ent_type == FREE_ENTRY) {
entry->EntrySec = sec_num;
entry->EntrySecOffset = buf - FATBuffer;
return (OK);
}
if (ent_type == LAST_ENTRY) {
return (ERR_ROOT_DIR_FULL);
} else {
buf += 32;
}
}
}
return (ERR_ROOT_DIR_FULL);
}
/*
**************************************************************************************************************
* PUT SHORT FILE NAME
*
* Description: This function fills the file entry with the short file name given by the user
*
* Arguments : ent_name_given File name given by the user
* entry Pointer to the FILE_ENTRY structure
*
* Returns : None
*
**************************************************************************************************************
*/
void FAT_PutSFN (uint8_t *ent_name_given,
FILE_ENTRY *entry)
{
uint32_t idx;
/* Read the sector from root directory containing the free entry */
MS_BulkRecv(entry->EntrySec, 1, FATBuffer);
for (idx = 0; idx < 8; idx++) { /* Fill the first eight charecters of the entry with file name */
if (*ent_name_given == '.') {
while (idx < 8) {
FATBuffer[entry->EntrySecOffset + idx] = 0x20;
idx++;
}
ent_name_given++;
} else {
FATBuffer[entry->EntrySecOffset + idx] = *ent_name_given;
ent_name_given++;
}
}
for (idx = 8; idx < 11; idx++) { /* Fill the next 3 charecters with file extension */
if (*ent_name_given == '.') {
while (idx < 11) {
FATBuffer[entry->EntrySecOffset + idx] = 0x20;
idx++;
}
} else {
FATBuffer[entry->EntrySecOffset + idx] = *ent_name_given;
ent_name_given++;
}
}
FATBuffer[entry->EntrySecOffset + idx] = 0x20;
for (idx = 12; idx < 32; idx++) { /* Fill all the remaining bytes with 0's */
FATBuffer[entry->EntrySecOffset + idx] = 0;
}
MS_BulkSend(entry->EntrySec, 1, FATBuffer); /* Write the sector into the root directory */
}
/*
**************************************************************************************************************
* FILE CLOSE
*
* Description: This function closes the opened file by making all the elements of FILE_ENTRY structure to 0
*
* Arguments : fd File descriptor which points to the file to be closed
*
* Returns : None
*
**************************************************************************************************************
*/
void FILE_Close (int32_t fd)
{
FILE_ENTRY *entry;
entry = &FAT_FileEntry[fd-1];
MS_BulkRecv(entry->EntrySec, 1, FATBuffer);
WriteLE32U(&FATBuffer[entry->EntrySecOffset + 28], entry->FileSize); /* Update the file size */
MS_BulkSend(entry->EntrySec, 1, FATBuffer);
entry->CurrClus = 0;
entry->CurrClusOffset = 0;
entry->FileSize = 0;
entry->EntrySec = 0;
entry->EntrySecOffset = 0;
entry->FileStatus = 0;
}
/*
**************************************************************************************************************
* GET END CLUSTER
*
* Description: This function end cluster in the cluster chain of a cluster
*
* Arguments : clus_no Starting cluster of the cluster chain in which end cluster to be found
*
* Returns : End cluster in the cluster chain
*
**************************************************************************************************************
*/
uint16_t FAT_GetEndClus (uint16_t clus_no)
{
uint16_t next_clus;
next_clus = clus_no;
while (next_clus) {
next_clus = FAT_GetNextClus(clus_no);
if (next_clus) {
clus_no = next_clus;
}
}
return (clus_no);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -