diff --git a/drivers/mmcsd/mmcsd_spi.c b/drivers/mmcsd/mmcsd_spi.c index 604fd94b562..fe7e3551734 100644 --- a/drivers/mmcsd/mmcsd_spi.c +++ b/drivers/mmcsd/mmcsd_spi.c @@ -50,6 +50,7 @@ #include #include #include +#include #include #include @@ -441,6 +442,12 @@ static int mmcsd_waitready(FAR struct mmcsd_slot_s *slot) } elapsed = ELAPSED_TIME(start); + + if (elapsed > MMCSD_DELAY_10MS) + { + // Give other threads time to run + usleep(10000); + } } while (elapsed < MMCSD_DELAY_500MS); diff --git a/fs/fat/Kconfig b/fs/fat/Kconfig index f24e6772bcd..baa93a5d70d 100644 --- a/fs/fat/Kconfig +++ b/fs/fat/Kconfig @@ -46,6 +46,31 @@ config FAT_MAXFNAME This setting may not exceed NAME_MAX. That will be verified at compile time. The minimum values is 12 due to assumptions in internal logic. +config FAT_LFN_ALIAS_HASH + bool "Use faster method for forming long filename 8.3 alias" + depends on FAT_LFN + default n + ---help--- + Long filenames on FAT filesystems have associated 8.3 character alias + short filenames. The traditional form of these is FILENA~1.EXT with + a running count of the number of similar names. However creating this + unique count can take several seconds if there are many similarly named + files in the directory. Enabling FAT_LFN_ALIAS_HASH uses an alternative + format of FI0123~1.TXT where the four digits are a hash of the original + filename. This method is similar to what is used by Windows 2000 and + later. + +config FAT_LFN_ALIAS_TRAILCHARS + int "Number of trailing characters to use for 8.3 alias" + depends on FAT_LFN + default 0 + ---help--- + Traditional format for long filename 8.3 aliases takes first 6 + characters of long filename. If this option is set to N > 0, + NuttX will instead take first 6-N and last N characters to form + the short name. This is useful for filenames like "datafile12.txt" + where the first characters would always remain the same. + config FS_FATTIME bool "FAT timestamps" default n diff --git a/fs/fat/fs_fat32dirent.c b/fs/fat/fs_fat32dirent.c index bd1655aa79d..5d678f0da55 100644 --- a/fs/fat/fs_fat32dirent.c +++ b/fs/fat/fs_fat32dirent.c @@ -754,6 +754,17 @@ static inline int fat_createalias(struct fat_dirinfo_s *dirinfo) return OK; } } + +#if defined(CONFIG_FAT_LFN_ALIAS_TRAILCHARS) && CONFIG_FAT_LFN_ALIAS_TRAILCHARS > 0 + /* Take first 6-N characters from beginning of filename and last N + * characters from end of the filename. Useful for filenames like + * "datafile123.txt". */ + if (ndx == 6 - CONFIG_FAT_LFN_ALIAS_TRAILCHARS + && namechars > CONFIG_FAT_LFN_ALIAS_TRAILCHARS) + { + src += namechars - CONFIG_FAT_LFN_ALIAS_TRAILCHARS; + } +#endif } } #endif @@ -837,6 +848,33 @@ static inline int fat_uniquealias(struct fat_mountpt_s *fs, lsdigit = tilde + 1; DEBUGASSERT(dirinfo->fd_name[lsdigit] == '1'); +#ifdef CONFIG_FAT_LFN_ALIAS_HASH + /* Add a hash of the long filename to the short filename, to reduce collisions. */ + if ((ret = fat_findalias(fs, dirinfo)) == OK) + { + uint16_t hash = dirinfo->fd_seq.ds_offset; + for (i = 0; dirinfo->fd_lfname[i] != '\0'; i++) + { + hash = ((hash << 5) + hash) ^ dirinfo->fd_lfname[i]; + } + + for (i = 0; i < tilde - 2; i++) + { + uint8_t nibble = (hash >> (i * 4)) & 0x0F; + const char *digits = "0123456789ABCDEF"; + dirinfo->fd_name[tilde - 1 - i] = digits[nibble]; + } + } + else if (ret == -ENOENT) + { + return OK; /* Alias was unique already */ + } + else + { + return ret; /* Other error */ + } +#endif + /* Search for the single short file name directory entry in this directory */ while ((ret = fat_findalias(fs, dirinfo)) == OK) diff --git a/fs/fat/fs_fat32util.c b/fs/fat/fs_fat32util.c index 9ff3ead1c30..91e67029e57 100644 --- a/fs/fat/fs_fat32util.c +++ b/fs/fat/fs_fat32util.c @@ -1465,7 +1465,7 @@ int fat_dirtruncate(struct fat_mountpt_s *fs, FAR uint8_t *direntry) writetime = fat_systime2fattime(); DIR_PUTWRTTIME(direntry, writetime & 0xffff); - DIR_PUTWRTDATE(direntry, writetime > 16); + DIR_PUTWRTDATE(direntry, writetime >> 16); /* This sector needs to be written back to disk eventually */ @@ -1526,7 +1526,7 @@ int fat_dirshrink(struct fat_mountpt_s *fs, FAR uint8_t *direntry, writetime = fat_systime2fattime(); DIR_PUTWRTTIME(direntry, writetime & 0xffff); - DIR_PUTWRTDATE(direntry, writetime > 16); + DIR_PUTWRTDATE(direntry, writetime >> 16); /* This sector needs to be written back to disk eventually */