📄 usbhost_fat.c
字号:
cnt++;
}
cnt = 0;
while (cnt < 3) { /* Get 3 charecters from there */
*ext_ptr = *entry;
ext_ptr++;
entry++;
cnt++;
}
*ext_ptr = 0;
ext_ptr--;
while (*ext_ptr == ' ') { /* If any spaces exist after the file extension, replace them with 0 */
*ext_ptr = 0;
ext_ptr--;
}
}
/*
**************************************************************************************************************
* CASE INSENSITIVE COMPARISION OF STRINGS
*
* Description: This function compares two strings case insensitively
*
* Arguments : str1 Pointer to the first string
* str2 Pointer to the second string
*
* Returns : MATCH_FOUND if both the strings are same
* NATCH_NOT_FOUND if both the strings are different
*
**************************************************************************************************************
*/
int32_t FAT_StrCaseCmp (uint8_t *str1,
uint8_t *str2)
{
while (*str1 && *str2) {
if (*str1 == *str2 || *str1 == (*str2 + 32) || *str1 == (*str2 - 32)) {
str1++;
str2++;
continue;
} else {
return (MATCH_NOT_FOUND);
}
}
if (*str1 == 0 && *str2 == 0) {
return (MATCH_FOUND);
} else {
return (MATCH_NOT_FOUND);
}
}
/*
**************************************************************************************************************
* CHECK TYPE OF THE ENTRY
*
* Description: This function checks the type of file entry.
*
* Arguments : ent Pointer to the buffer containing the entry
*
* Returns : LAST_ENTRY if the entry is last entry
* FREE_ENTRY if the entry is free entry
* LFN_ENTRY if the entry is long file name entry
* SFN_ENTRY if the entry is short file name entry
*
**************************************************************************************************************
*/
uint32_t FAT_ChkEntType (volatile uint8_t *ent)
{
if (ent[0] == 0x00) { /* First byte is 0 means it is the last entry */
return (LAST_ENTRY);
}
if (ent[0] == 0xE5) { /* First byte is 0xE5 means it is the free entry */
return (FREE_ENTRY);
}
if (0x0F == ent[11]) { /* If 11th byte of an entry is 0x0F, it is LFN */
return (LFN_ENTRY);
} else {
return (SFN_ENTRY); /* Else it is the SFN */
}
}
/*
**************************************************************************************************************
* READ DATA REQUESTED BY THE USER
*
* Description: This function reads data requested by the application from the file pointed by file descriptor.
*
* Arguments : fd file descriptor that points to a file
* buffer buffer into which the data is to be read
* num_bytes number of bytes requested by the application
*
* Returns : total_bytes_read Total bytes actually read.
*
**************************************************************************************************************
*/
uint32_t FILE_Read ( int32_t fd,
volatile uint8_t *buffer,
uint32_t num_bytes)
{
uint32_t total_bytes_to_read; /* Total bytes requested by the application */
uint32_t total_bytes_read; /* Total bytes read */
uint32_t bytes_read; /* Bytes read from one cluster */
uint32_t bytes_to_read; /* Bytes to be read in one cluster */
FILE_ENTRY *entry; /* Entry that contains the file attribute information */
uint16_t next_clus; /* Next cluster of the current cluster in the cluster chain */
entry = &FAT_FileEntry[fd-1]; /* Get file entry from file descriptor */
total_bytes_read = 0;
if (entry->FileSize == 0) {
return (0);
}
if (num_bytes < entry->FileSize) {
total_bytes_to_read = num_bytes;
} else {
total_bytes_to_read = entry->FileSize;
}
do {
next_clus = FAT_GetNextClus(entry->CurrClus); /* Get next cluster */
if (next_clus == 0) { /* If the current cluster is the last cluster */
/* If the offset is at the end of the file */
if (entry->CurrClusOffset == (entry->FileSize % FAT_BootSec.BytsPerClus)) {
return (0); /* No more bytes to read */
} /* If requested number is > remaining bytes in the last cluster */
if (total_bytes_to_read > ((entry->FileSize % FAT_BootSec.BytsPerClus) - entry->CurrClusOffset)) {
total_bytes_to_read = (entry->FileSize % FAT_BootSec.BytsPerClus) - entry->CurrClusOffset;
}
bytes_to_read = total_bytes_to_read;
/* If requested number is > remaining bytes in the current cluster */
} else if (total_bytes_to_read > (FAT_BootSec.BytsPerClus - entry->CurrClusOffset)) {
bytes_to_read = FAT_BootSec.BytsPerClus - entry->CurrClusOffset;
} else {
bytes_to_read = total_bytes_to_read;
}
bytes_read = FAT_ClusRead(entry->CurrClus, /* Read bytes from a single cluster */
entry->CurrClusOffset,
buffer,
bytes_to_read);
buffer += bytes_read;
total_bytes_read += bytes_read;
total_bytes_to_read -= bytes_read;
/* If the cluster offset reaches end of the cluster, make it 0 */
if (entry->CurrClusOffset + bytes_read == FAT_BootSec.BytsPerClus) {
entry->CurrClusOffset = 0;
} else {
entry->CurrClusOffset += bytes_read; /* Else increment the cluster offset */
}
if (entry->CurrClusOffset == 0) {
entry->CurrClus = (next_clus > 0) ? next_clus : entry->CurrClus;
}
} while (total_bytes_to_read);
return (total_bytes_read);
}
/*
**************************************************************************************************************
* READ FROM ONE CLUSTER
*
* Description: This function reads the data from a single cluster.
*
* Arguments : curr_clus Current cluster from which the data has to read
* clus_offset Position in the current cluster from which the data has to read
* buffer Buffer into which the data has to read
* num_bytes Number of bytes to read
*
* Returns : tot_bytes_read Total bytes read from the current cluster
*
**************************************************************************************************************
*/
uint32_t FAT_ClusRead ( uint16_t curr_clus,
uint32_t clus_offset,
volatile uint8_t *buffer,
uint32_t num_bytes)
{
uint32_t tot_bytes_read; /* total bytes read in the current cluster */
uint32_t n_bytes; /* Bytes to read in the current sector */
uint32_t start_sec; /* Starting sector of the current cluster */
uint32_t sec_num; /*Current sector number */
uint16_t num_sec; /* Number of sectors to be read */
uint32_t sec_offset; /* Offset in the current sector */
uint32_t cnt;
tot_bytes_read = 0;
start_sec = ((curr_clus - 2) * FAT_BootSec.SecPerClus) + FAT_BootSec.FirstDataSec;
sec_num = start_sec + (clus_offset / FAT_BootSec.BytsPerSec);
num_sec = num_bytes / FAT_BootSec.BytsPerSec;
sec_offset = clus_offset % FAT_BootSec.BytsPerSec;
if (sec_offset) { /* If the sector offset is at the middle of a sector */
MS_BulkRecv(sec_num, 1, FATBuffer); /* Read the first sector */
n_bytes = (FAT_BootSec.BytsPerSec - sec_offset <= num_bytes) ?
(FAT_BootSec.BytsPerSec - sec_offset) : num_bytes;
for (cnt = sec_offset; cnt < sec_offset + n_bytes; cnt++) {
*buffer = FATBuffer[cnt]; /* Copy the required bytes to user buffer */
buffer++;
}
tot_bytes_read += n_bytes;
clus_offset += n_bytes;
num_bytes -= n_bytes;
sec_num++;
}
if (num_bytes / FAT_BootSec.BytsPerSec) { /* Read all the remaining full sectors */
num_sec = num_bytes / FAT_BootSec.BytsPerSec;
MS_BulkRecv(sec_num, num_sec, buffer);
buffer += (num_sec * FAT_BootSec.BytsPerSec);
tot_bytes_read += (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) { /* Read the last sector for the remaining bytes */
MS_BulkRecv(sec_num, 1, FATBuffer);
for (cnt = 0; cnt < num_bytes; cnt++) {
*buffer = FATBuffer[cnt]; /* Copy the required bytes to user buffer */
buffer++;
}
tot_bytes_read += num_bytes;
}
return (tot_bytes_read);
}
/*
**************************************************************************************************************
* WRITE THE DATA REQUESTED BY THE USER
*
* Description: This function writes data requested by the application to the file pointed by file descriptor
*
* Arguments : fd file descriptor that points to a file
* buffer buffer from which the data is to be written
* num_bytes number of bytes requested by the application
*
* Returns : total_bytes_written Total bytes actually written
*
**************************************************************************************************************
*/
uint32_t FILE_Write ( int32_t fd,
volatile uint8_t *buffer,
uint32_t num_bytes)
{
uint32_t total_bytes_to_write; /* Total bytes requested by application */
uint32_t total_bytes_written; /* Total bytes written */
uint32_t bytes_written; /* Bytes written in a single cluster */
uint32_t bytes_to_write; /* Bytes to write in a single cluster */
FILE_ENTRY *entry; /* Entry that contains the file attribute information */
uint16_t free_clus; /* Free cluster available in the disk */
entry = &FAT_FileEntry[fd-1]; /* Get file entry from file descriptor */
total_bytes_written = 0;
total_bytes_to_write = num_bytes;
if (num_bytes) {
if (entry->FileSize == 0) {
free_clus = FAT_GetFreeClus();
FAT_UpdateFAT(free_clus, 0xFFFF);
entry->CurrClus = free_clus;
MS_BulkRecv(entry->EntrySec, 1, FATBuffer);
WriteLE16U(&FATBuffer[(entry->EntrySecOffset) + 26], free_clus);
MS_BulkSend(entry->EntrySec, 1, FATBuffer);
}
} else {
return (0);
}
entry->CurrClus = FAT_GetEndClus(entry->CurrClus); /* Make the current cluster as end cluster */
entry->CurrClusOffset = entry->FileSize % FAT_BootSec.BytsPerClus; /* Move cluster offset to file end */
do {
if (total_bytes_to_write > FAT_BootSec.BytsPerClus - entry->CurrClusOffset) {
bytes_to_write = FAT_BootSec.BytsPerClus - entry->CurrClusOffset;
} else {
bytes_to_write = total_bytes_to_write;
}
bytes_written = FAT_ClusWrite(entry->CurrClus,
entry->CurrClusOffset,
buffer,
bytes_to_write);
buffer += bytes_written;
total_bytes_written += bytes_written;
total_bytes_to_write -= bytes_written;
entry->FileSize += bytes_written;
if (entry->CurrClusOffset + bytes_written == FAT_BootSec.BytsPerClus) {
entry->CurrClusOffset = 0;
} else {
entry->CurrClusOffset += bytes_written;
}
if (entry->CurrClusOffset == 0) {
free_clus = FAT_GetFreeClus();
if (free_clus == 0) {
return (total_bytes_written);
}
FAT_UpdateFAT(entry->CurrClus, free_clus);
FAT_UpdateFAT(free_clus, 0xFFFF);
entry->CurrClus = free_clus;
}
} while (total_bytes_to_write);
return (total_bytes_written);
}
/*
**************************************************************************************************************
* WRITE TO ONE CLUSTER
*
* Description: This function writes the data to a single cluster.
*
* Arguments : curr_clus Current cluster into which the data has to write
* clus_offset Position in the current cluster from which the data has to write
* buffer Buffer from which the data has to write
* num_bytes Number of bytes to write
*
* Returns : tot_bytes_read Total bytes written into the current cluster
*
**************************************************************************************************************
*/
uint32_t FAT_ClusWrite ( uint16_t curr_clus,
uint32_t clus_offset,
volatile uint8_t *buffer,
uint32_t num_bytes)
{
uint32_t tot_bytes_written;
uint32_t n_bytes;
uint32_t start_sec;
uint32_t sec_num;
uint16_t num_sec;
uint32_t sec_offset;
uint32_t cnt;
tot_bytes_written = 0;
start_sec = ((curr_clus - 2) * FAT_BootSec.SecPerClus) + FAT_BootSec.FirstDataSec;
sec_num = start_sec + (clus_offset / FAT_BootSec.BytsPerSec);
num_sec = num_bytes / FAT_BootSec.BytsPerSec;
sec_offset = clus_offset % FAT_BootSec.BytsPerSec;
if (sec_offset) {
MS_BulkRecv(sec_num, 1, FATBuffer);
n_bytes = (FAT_BootSec.BytsPerSec - sec_offset <= num_bytes) ?
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -