From 85712a2c5f48a9b4af64b93b7be0ef6f4c2fc1e3 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 3 May 2017 12:35:19 +0100 Subject: [PATCH] FatFs: Update to release R0.12b. --- firmware/application/ffconf.h | 12 +- .../ext/fatfs/doc/00index_e.html | 4 +- .../ext/fatfs/doc/00index_j.html | 4 +- .../ext/fatfs/doc/en/appnote.html | 44 +-- .../ext/fatfs/doc/en/chdir.html | 8 +- .../ext/fatfs/doc/en/config.html | 16 +- .../ext/fatfs/doc/en/dinit.html | 2 +- .../ext/fatfs/doc/en/dioctl.html | 12 +- .../ext/fatfs/doc/en/dread.html | 8 +- .../ext/fatfs/doc/en/dstat.html | 2 +- .../ext/fatfs/doc/en/dwrite.html | 6 +- .../ext/fatfs/doc/en/expand.html | 6 +- .../ext/fatfs/doc/en/fattime.html | 4 +- .../ext/fatfs/doc/en/fdisk.html | 6 +- .../ext/fatfs/doc/en/filename.html | 8 +- .../ext/fatfs/doc/en/findfirst.html | 9 +- .../ext/fatfs/doc/en/forward.html | 3 +- .../ext/fatfs/doc/en/getcwd.html | 2 +- .../ext/fatfs/doc/en/mkdir.html | 2 +- .../ext/fatfs/doc/en/mkfs.html | 8 +- .../ext/fatfs/doc/en/mount.html | 12 +- .../ext/fatfs/doc/en/open.html | 6 +- .../ext/fatfs/doc/en/printf.html | 2 +- .../ext/fatfs/doc/en/rc.html | 23 +- .../ext/fatfs/doc/en/read.html | 3 +- .../ext/fatfs/doc/en/rename.html | 9 +- .../ext/fatfs/doc/en/sfatfs.html | 2 +- .../ext/fatfs/doc/en/sfileinfo.html | 2 +- .../ext/fatfs/doc/en/unlink.html | 2 +- .../ext/fatfs/doc/en/write.html | 3 +- .../ext/fatfs/doc/ja/appnote.html | 18 +- .../ext/fatfs/doc/ja/dinit.html | 2 +- .../ext/fatfs/doc/ja/dioctl.html | 2 +- .../ext/fatfs/doc/ja/dread.html | 2 +- .../ext/fatfs/doc/ja/dstat.html | 2 +- .../ext/fatfs/doc/ja/dwrite.html | 2 +- .../ext/fatfs/doc/ja/expand.html | 2 +- .../ext/fatfs/doc/ja/fattime.html | 2 +- .../ext/fatfs/doc/ja/fdisk.html | 6 +- .../ext/fatfs/doc/ja/findfirst.html | 5 +- .../ext/fatfs/doc/ja/forward.html | 2 +- .../ext/fatfs/doc/ja/mkdir.html | 2 +- .../ext/fatfs/doc/ja/mount.html | 4 +- .../ext/fatfs/doc/ja/open.html | 2 +- .../ext/fatfs/doc/ja/rc.html | 18 +- .../ext/fatfs/doc/ja/read.html | 2 +- .../ext/fatfs/doc/ja/rename.html | 2 +- .../ext/fatfs/doc/ja/sfatfs.html | 2 +- .../ext/fatfs/doc/ja/truncate.html | 2 +- .../ext/fatfs/doc/ja/unlink.html | 2 +- .../ext/fatfs/doc/ja/write.html | 2 +- .../ext/fatfs/doc/res/rwtest1.png | Bin 27860 -> 69114 bytes .../ext/fatfs/doc/updates.txt | 189 ++++++++++ .../ext/fatfs/src/00history.txt | 16 +- .../chibios-portapack/ext/fatfs/src/diskio.c | 2 +- firmware/chibios-portapack/ext/fatfs/src/ff.c | 337 +++++++++--------- firmware/chibios-portapack/ext/fatfs/src/ff.h | 6 +- 57 files changed, 532 insertions(+), 331 deletions(-) create mode 100644 firmware/chibios-portapack/ext/fatfs/doc/updates.txt diff --git a/firmware/application/ffconf.h b/firmware/application/ffconf.h index cfe0e890..44242d37 100644 --- a/firmware/application/ffconf.h +++ b/firmware/application/ffconf.h @@ -5,7 +5,7 @@ / FatFs - FAT file system module configuration file /---------------------------------------------------------------------------*/ -#define _FFCONF 80186 /* Revision ID */ +#define _FFCONF 68020 /* Revision ID */ /*---------------------------------------------------------------------------/ / Function Configurations @@ -207,14 +207,14 @@ #define _FS_TINY 0 /* This option switches tiny buffer configuration. (0:Normal or 1:Tiny) -/ At the tiny configuration, size of the file object (FIL) is reduced _MAX_SS bytes. +/ At the tiny configuration, size of file object (FIL) is reduced _MAX_SS bytes. / Instead of private sector buffer eliminated from the file object, common sector / buffer in the file system object (FATFS) is used for the file data transfer. */ #define _FS_EXFAT 0 -/* This option switches support of exFAT file system in addition to the traditional -/ FAT file system. (0:Disable or 1:Enable) To enable exFAT, also LFN must be enabled. +/* This option switches support of exFAT file system. (0:Disable or 1:Enable) +/ When enable exFAT, also LFN needs to be enabled. (_USE_LFN >= 1) / Note that enabling exFAT discards C89 compatibility. */ @@ -262,7 +262,9 @@ / The _FS_TIMEOUT defines timeout period in unit of time tick. / The _SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*, / SemaphoreHandle_t and etc.. A header file for O/S definitions needs to be -/ included somewhere in the scope of ff.c. */ +/ included somewhere in the scope of ff.h. */ + +/* #include // O/S definitions */ /*--- End of configuration options ---*/ diff --git a/firmware/chibios-portapack/ext/fatfs/doc/00index_e.html b/firmware/chibios-portapack/ext/fatfs/doc/00index_e.html index 9427acbe..905b7b8f 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/00index_e.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/00index_e.html @@ -121,7 +121,7 @@

Resources

The FatFs module is a free software opened for education, research and development. You can use, modify and/or redistribute it for personal projects or commercial products without any restriction under your responsibility. For further information, refer to the application note.

-

Each case does not affect the files that not opened in write mode. To minimize risk of data loss, the critical section can be minimized by minimizing the time that file is opened in write mode or using f_sync function as shown in Figure 5.

+

Each case does not affect any file not opened in write mode. To minimize risk of data loss, the critical section can be minimized by minimizing the time that file is opened in write mode or using f_sync function as shown in Figure 5.

Extended Use of FatFs API

These are examples of extended use of FatFs APIs. New item will be added whenever a useful code is found.

    -
  1. Open or create a file for append (for R0.12 and older)
  2. +
  3. Open or create a file for append (for only R0.12 and earlier)
  4. Empty a directory
  5. -
  6. Allocate contiguous area to the file (for R0.11a and older)
  7. -
  8. Function/compatibility checker for low level disk I/O module
  9. +
  10. Allocate contiguous area to the file (for only R0.11a and earlier)
  11. +
  12. Compatibility checker for low level disk I/O module
  13. FAT image creator
@@ -256,15 +256,15 @@ Figure 5. Minimized critical section

FatFs has being developped as a personal project of the author, ChaN. It is free from the code anyone else wrote at current release. Following code block shows a copy of the FatFs license document that included in the source files.

 /*----------------------------------------------------------------------------/
-/  FatFs - Generic FAT file system module  R0.12a                             /
+/  FatFs - Generic FAT file system module  Rx.xx                              /
 /-----------------------------------------------------------------------------/
 /
-/ Copyright (C) 2016, ChaN, all right reserved.
+/ Copyright (C) 20xx, ChaN, all right reserved.
 /
 / FatFs module is an open source software. Redistribution and use of FatFs in
 / source and binary forms, with or without modification, are permitted provided
 / that the following condition is met:
-
+/
 / 1. Redistributions of source code must retain the above copyright notice,
 /    this condition and the following disclaimer.
 /
diff --git a/firmware/chibios-portapack/ext/fatfs/doc/en/chdir.html b/firmware/chibios-portapack/ext/fatfs/doc/en/chdir.html
index b9009fc5..41935fc9 100644
--- a/firmware/chibios-portapack/ext/fatfs/doc/en/chdir.html
+++ b/firmware/chibios-portapack/ext/fatfs/doc/en/chdir.html
@@ -25,7 +25,7 @@ FRESULT f_chdir (
 

Parameters

path
-
Pointer to the null-terminated string that specifies a directory to go.
+
Pointer to the null-terminated string that specifies the directory to go.
@@ -50,7 +50,7 @@ FRESULT f_chdir (

Description

-

The f_chdir function changes the current directory of the logical drive. The current directory of a drive is initialized to the root directory when the drive is auto-mounted. Note that the current directory is retained in the each file system object so that it also affects other tasks that using the volume.

+

The f_chdir function changes the current directory of the logical drive. The current directory of a drive is set to the root directory when the drive is mounted. Note that the current directory is retained in the each file system object, so that it also affects other tasks that use the volume.

@@ -63,10 +63,10 @@ FRESULT f_chdir (

Example

-    /* Change current direcoty of the current drive (dir1 under root dir) */
+    /* Change current direcoty of the current drive ('dir1' under root directory) */
     f_chdir("/dir1");
 
-    /* Change current direcoty of drive 2 (parent dir) */
+    /* Change current direcoty of drive 2 (parent directory) */
     f_chdir("2:..");
 
diff --git a/firmware/chibios-portapack/ext/fatfs/doc/en/config.html b/firmware/chibios-portapack/ext/fatfs/doc/en/config.html index 880c3250..5ee685fe 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/en/config.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/en/config.html @@ -45,16 +45,16 @@

Disable (0) or Enable (1) f_mkfs function.

_USE_FASTSEEK

-

Disable (0) or Enable (1) fast seek function to enable accelerated mode of f_lseek, f_read and f_write function. For more information, read here.

+

Disable (0) or Enable (1) fast seek function to enable accelerated mode for f_lseek, f_read and f_write function. For more information, read here.

_USE_EXPAND

Disable (0) or Enable (1) , f_enpand function. Also _FS_READONLY needs to be 0.

_USE_CHMOD

-

Disable (0) or Enable (1) metadata manipulation functions, f_chmod and f_utime. Also _FS_READONLY needs to be 0.

+

Disable (0) or Enable (1) metadata control functions, f_chmod and f_utime. Also _FS_READONLY needs to be 0.

_USE_LABEL

-

Disable (0) or Enable (1) volume label functions, f_getlabel and f_setlabel.

+

Disable (0) or Enable (1) API functions for volume label, f_getlabel and f_setlabel.

_USE_FORWARD

Disable (0) or Enable (1) f_forward function.

@@ -147,7 +147,7 @@

Disable (0) or Enable (1). This option switches multi-partition function. By default (0), each logical drive number is bound to the same physical drive number and only an FAT volume in the physical drive is mounted. When enabled, each logical drive is bound to the partition on the physical drive listed in the user defined partition resolution table VolToPart[]. Also f_fdisk funciton will be available. For more information, read here.

_MIN_SS, _MAX_SS

-

This set of options defines the size of sector on low level disk I/O interface, disk_read and disk_write function. Valid values are 512, 1024, 2048 and 4096. _MIN_SS defines minimum sector size and _MAX_SS defines the maximum sector size. Always set both 512 for any type of memory card and harddisk. But a larger value may be required for on-board flash memory and some type of optical media. When _MAX_SS > _MIN_SS, FatFs is configured to variable sector size and GET_SECTOR_SIZE command must be implemented to the disk_ioctl function.

+

This set of options defines the size of sector on low level disk I/O interface, disk_read and disk_write function. Valid values are 512, 1024, 2048 and 4096. _MIN_SS defines minimum sector size and _MAX_SS defines the maximum sector size. Always set both 512 for memory card and harddisk. But a larger value may be required for on-board flash memory and some type of optical media. When _MAX_SS > _MIN_SS, support of variable sector size is enabled and GET_SECTOR_SIZE command needs to be implemented to the disk_ioctl function.

_USE_TRIM

Disable (0) or Enable (1). This option switches ATA-TRIM function. To enable Trim function, also CTRL_TRIM command should be implemented to the disk_ioctl function.

@@ -175,7 +175,7 @@

This option switches support for the exFAT file system in addition to the FAT file system, Enabled(1) or Disabled(1). To enable this feature, also LFN must be enabled and configureing _LFN_UNICODE = 1 and _MAX_LFN = 255 is recommended for full-featured exFAT function. Note that enabling exFAT discards C89 compatibility because of need for 64-bit integer type.

_FS_NORTC

-

Use RTC (0) or Do not use RTC (1). This option controls timestamp function. If the system does not have an RTC function or valid timestamp is not needed, set _FS_NORTC to 1 to disable the timestamp function. Any object modified by FatFs will have a fixed timestamp value defined by _NORTC_MON, _NORTC_MDAY and _NORTC_YEAR. To use the timestamp function, set _FS_NORTC = 0 and add get_fattime function to the project to get the current time form real-time clock. This option has no effect at read-only configuration.

+

Use RTC (0) or Do not use RTC (1). This option controls timestamp function. If the system does not have an RTC function or valid timestamp is not needed, set _FS_NORTC to 1 to disable the timestamp function. Any object modified by FatFs will have a fixed timestamp defined by _NORTC_MON, _NORTC_MDAY and _NORTC_YEAR. To use the timestamp function, set _FS_NORTC = 0 and add get_fattime function to the project to get the current time form real-time clock. This option has no effect at read-only configuration.

_NORTC_MON, _NORTC_MDAY, _NORTC_YEAR

This set of options defines the time to be used at no RTC systems. This option has no effect at read-only configuration or _FS_NORTC = 0.

@@ -184,12 +184,12 @@

This option switches file lock function to control duplicated file open and illegal operations to open objects. Note that the file lock function is independent of re-entrancy. This option must be 0 at read-only configuration.

- - + +
ValueDescription
0Disable file lock function. To avoid volume corruption, application program should avoid illegal open, remove and rename to the open objects.
>0Enable file lock function. The value defines how many files/sub-directories can be opened simultaneously under file lock control. Illigal operations to the open object will be rejected with FR_LOCKED.
0Disable file lock function. To avoid collapsing file by wrong file operation, application program needs to avoid illegal open, remove and rename to the open objects.
>0Enable file lock function. The value defines how many files/sub-directories can be opened simultaneously under the file lock control. Illigal operations to the open object will be rejected with FR_LOCKED.

_FS_REENTRANT

-

Disable (0) or Enable (1). This option switches the re-entrancy (thread safe) of the FatFs module itself. Note that file/directory access to the different volume is always re-entrant and it can work simultaneously regardless of this option but volume control functions, f_mount, f_mkfs and f_fdisk, are always not re-entrant. Only file/directory access to the same volume, in other words, exclusive use of each file system object, is under control of this function. To enable this feature, also user provided synchronization handlers, ff_req_grant, ff_rel_grant, ff_del_syncobj and ff_cre_syncobj, need to be added to the project. Sample code is available in option/syscall.c.

+

Disable (0) or Enable (1). This option switches the re-entrancy (thread safe) of the FatFs module itself. Note that file/directory access to the different volume is always re-entrant and it can work simultaneously regardless of this option but volume control functions. f_mount, f_mkfs and f_fdisk, are always not re-entrant. Only file/directory access to the same volume, in other words, exclusive use of each file system object, is under control of this function. To enable this feature, also user provided synchronization handlers, ff_req_grant, ff_rel_grant, ff_del_syncobj and ff_cre_syncobj, need to be added to the project. Sample code is available in option/syscall.c.

_FS_TIMEOUT

Number of time ticks to abort the file function with FR_TIMEOUT when wait time is too long. This option has no effect when _FS_REENTRANT = 0.

diff --git a/firmware/chibios-portapack/ext/fatfs/doc/en/dinit.html b/firmware/chibios-portapack/ext/fatfs/doc/en/dinit.html index 4a003e70..81b0ffd0 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/en/dinit.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/en/dinit.html @@ -13,7 +13,7 @@

disk_initialize

-

The disk_initialize function initializes the storage device.

+

The disk_initialize function is called to initializes the storage device.

 DSTATUS disk_initialize (
   BYTE pdrv           /* [IN] Physical drive number */
diff --git a/firmware/chibios-portapack/ext/fatfs/doc/en/dioctl.html b/firmware/chibios-portapack/ext/fatfs/doc/en/dioctl.html
index 7c692511..9a724915 100644
--- a/firmware/chibios-portapack/ext/fatfs/doc/en/dioctl.html
+++ b/firmware/chibios-portapack/ext/fatfs/doc/en/dioctl.html
@@ -13,7 +13,7 @@
 
 

disk_ioctl

-

The disk_ioctl function controls device specific features and miscellaneous functions other than generic read/write.

+

The disk_ioctl function is called to control device specific features and miscellaneous functions other than generic read/write.

 DRESULT disk_ioctl (
   BYTE pdrv,     /* [IN] Drive number */
@@ -59,9 +59,9 @@ DRESULT disk_ioctl (
 CommandDescription
 CTRL_SYNCMake sure that the device has finished pending write process. If the disk I/O module has a write back cache, the dirty buffers must be written back to the media immediately. Nothing to do for this command if each write operation to the media is completed within the disk_write function.
 GET_SECTOR_COUNTReturns number of available sectors on the drive into the DWORD variable pointed by buff. This command is used by only f_mkfs and f_fdisk function to determine the volume/partition size to be created. Required at _USE_MKFS == 1 or _MULTI_PARTITION == 1.
-GET_SECTOR_SIZEReturns sector size of the media into the WORD variable pointed by buff. Valid return values of this command are 512, 1024, 2048 and 4096. This command is required only at variable sector size configuration, _MAX_SS > _MIN_SS. At fixed sector size configuration, _MAX_SS == _MIN_SS, this command is not used and the device must work at that sector size.
-GET_BLOCK_SIZEReturns erase block size of the flash memory media in unit of sector into the DWORD variable pointed by buff. The allowable value is from 1 to 32768 in power of 2. Return 1 if the erase block size is unknown or non flash memory media. This command is used by only f_mkfs function and it attempts to align data area to the erase block boundary. Required at _USE_MKFS == 1.
-CTRL_TRIMInforms the device the data on the block of sectors that specified by DWORD array {<start sector>, <end sector>} pointed by buff is no longer needed and it may be erased. This is an identical command to Trim of ATA device. Nothing to do for this command if this funcion is not supported or not a flash memory device. The FatFs does not check the result code and the file function is not affected even if the sector block was not erased well. This command is called on remove a cluster chain and in the f_mkfs function. Required at _USE_TRIM == 1.
+GET_SECTOR_SIZEReturns sector size of the device into the WORD variable pointed by buff. Valid return values of this command are 512, 1024, 2048 and 4096. This command is required only at variable sector size configuration, _MAX_SS > _MIN_SS. At the fixed sector size configuration, _MAX_SS == _MIN_SS, this command is not used and the device must work at that sector size.
+GET_BLOCK_SIZEReturns erase block size of the flash memory media in unit of sector into the DWORD variable pointed by buff. The allowable value is from 1 to 32768 in power of 2. Return 1 if the erase block size is unknown or non flash memory media. This command is used by only f_mkfs function and it attempts to align data area on the erase block boundary. Required at _USE_MKFS == 1.
+CTRL_TRIMInforms the device the data on the block of sectors is no longer needed and it can be erased. The sector block is specified by DWORD array {<start sector>, <end sector>} pointed by buff. This is an identical command to Trim of ATA device. Nothing to do for this command if this funcion is not supported or not a flash memory device. The FatFs does not check the result code and the file function is not affected even if the sector block was not erased well. This command is called on remove a cluster chain and in the f_mkfs function. Required at _USE_TRIM == 1.
 
 
 

FatFs never uses any device dependent command nor user defined command. Following table shows an example of non-standard commands usable for some applications.

@@ -69,8 +69,8 @@ DRESULT disk_ioctl ( Example of optional ioctl command CommandDescription CTRL_FORMATCreate a physical format on the media. If buff is not null, it is pointer to the call-back function for progress notification. -CTRL_POWER_IDLEPut the device idle state. STA_NOINIT in status flag may not be set if the device goes active state by generic read/write function. -CTRL_POWER_OFFPut the device off state. Shut-down the power to the device and deinitialize the device interface if needed. STA_NOINIT in status flag must be set. The device goes active state by disk_initialize function. +CTRL_POWER_IDLEPut the device idle state. STA_NOINIT in the current status flags may not be set if the device goes active state by generic read/write function. +CTRL_POWER_OFFPut the device off state. Shut-down the power to the device and deinitialize the device interface if needed. STA_NOINIT in the current status flags must be set. The device goes active state by disk_initialize function. CTRL_LOCKLock media eject mechanism. CTRL_UNLOCKUnlock media eject mechanism. CTRL_EJECTEject media cartridge. STA_NOINIT and STA_NODISK in status flag are set after the function succeeded. diff --git a/firmware/chibios-portapack/ext/fatfs/doc/en/dread.html b/firmware/chibios-portapack/ext/fatfs/doc/en/dread.html index 14227de6..b7674a16 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/en/dread.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/en/dread.html @@ -13,7 +13,7 @@

disk_read

-

The disk_read function reads sector(s) from the storage device.

+

The disk_read function is called to read data from the sector(s) of storage device.

 DRESULT disk_read (
   BYTE pdrv,     /* [IN] Physical drive number */
@@ -30,7 +30,7 @@ DRESULT disk_read (
 
pdrv
Physical drive number to identify the target device.
buff
-
Pointer to the byte array to store the read data.
+
Pointer to the first item of the byte array to store read data.
sector
Start sector number in 32-bit LBA.
count
@@ -45,7 +45,7 @@ DRESULT disk_read (
RES_OK (0)
The function succeeded.
RES_ERROR
-
Any hard error occured during the read operation and could not recover it.
+
A hard error occured during the read operation and could not recover it.
RES_PARERR
Invalid parameter.
RES_NOTRDY
@@ -61,7 +61,7 @@ DRESULT disk_read (
  • Convert word transfer to byte transfer in this function if needed. - Recommended.
  • On the f_read calls, avoid long read request that includes a whole of sector. - Any direct transfer never occures.
  • -
  • On the f_read calls, make sure that (((UINT)data & 3) == (f_tell(fp) & 3)) is true. - Word alignment of buff is guaranteed.
  • +
  • On the f_read calls, make sure that (((UINT)data & 3) == (f_tell(fp) & 3)) is true. - Word alignment of buff is guaranteed.

Generally, a multiple sector transfer request must not be split into single sector transactions to the storage device, or you will not get good read throughput.

diff --git a/firmware/chibios-portapack/ext/fatfs/doc/en/dstat.html b/firmware/chibios-portapack/ext/fatfs/doc/en/dstat.html index 07514609..78508ba8 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/en/dstat.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/en/dstat.html @@ -13,7 +13,7 @@

disk_status

-

The disk_status function returns the current drive status.

+

The disk_status function is called to inquire the current drive status.

 DSTATUS disk_status (
   BYTE pdrv     /* [IN] Physical drive number */
diff --git a/firmware/chibios-portapack/ext/fatfs/doc/en/dwrite.html b/firmware/chibios-portapack/ext/fatfs/doc/en/dwrite.html
index 4ee6d09a..b99eccdc 100644
--- a/firmware/chibios-portapack/ext/fatfs/doc/en/dwrite.html
+++ b/firmware/chibios-portapack/ext/fatfs/doc/en/dwrite.html
@@ -13,7 +13,7 @@
 
 

disk_write

-

The disk_write writes sector(s) to the storage device.

+

The disk_write function is called to write data to the sector(s) of storage device.

 DRESULT disk_write (
   BYTE drv,         /* [IN] Physical drive number */
@@ -30,7 +30,7 @@ DRESULT disk_write (
 
pdrv
Physical drive number to identify the target device.
buff
-
Pointer to the byte array to be written. The size of data to be written is sector size * count bytes.
+
Pointer to the first item of the byte array to be written. The size of data to be written is sector size * count bytes.
sector
Start sector number in 32-bit LBA.
count
@@ -45,7 +45,7 @@ DRESULT disk_write (
RES_OK (0)
The function succeeded.
RES_ERROR
-
Any hard error occured during the write operation and could not recover it.
+
A hard error occured during the write operation and could not recover it.
RES_WRPRT
The medium is write protected.
RES_PARERR
diff --git a/firmware/chibios-portapack/ext/fatfs/doc/en/expand.html b/firmware/chibios-portapack/ext/fatfs/doc/en/expand.html index 434580cf..54f21d1b 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/en/expand.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/en/expand.html @@ -59,9 +59,9 @@ FRESULT f_expand (
  • The file has been opened in read-only mode.
  • Not allowable file size. (>= 4GiB on FAT volume)
  • -

    When opt is 0, the function finds a contiguous data area and set it as suggested point for next allocation instead of allocating it to the file. The next cluster allocation is started at top of the contiguous area found by this function. Thus the write file is guaranteed be contiguous and no allocation delay until the size reaches that size at least unless any other operation to the volume with changes of FAT is performed.

    -

    The contiguous file would have an advantage at time-critical read/write operations. It reduces some overheads in the file system and the storage media caused by random access due to fragmented file data. Especially, at the exFAT volume, any FAT access for the contiguous file is completely eliminated and storage media will be accessed sequentially.

    -

    Also the contiguous file data can be easily accessed directly via low-level disk functions but it is not recommended in consideration for future compatibility.

    +

    When opt is 0, the function finds a contiguous data area and set it as suggested point for next allocation instead of allocating it to the file. The next cluster allocation is started at top of the contiguous area found by this function. Thus the write file is guaranteed be contiguous and no allocation delay until the size reaches that size at least unless any other changes to the volume is performed.

    +

    The contiguous file would have an advantage at time-critical read/write operations. It reduces some overheads in the file system and the storage media caused by random access due to fragmented file data. Especially FAT access for the contiguous file on the exFAT volume is completely eliminated and storage media will be accessed sequentially.

    +

    Also the contiguous file data can be easily accessed directly via low-level disk functions. But this is not recommended in consideration for future compatibility.

    diff --git a/firmware/chibios-portapack/ext/fatfs/doc/en/fattime.html b/firmware/chibios-portapack/ext/fatfs/doc/en/fattime.html index e4ff768b..f2d8982c 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/en/fattime.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/en/fattime.html @@ -13,7 +13,7 @@

    get_fattime

    -

    The get_fattime function gets current time.

    +

    The get_fattime function is called to get the current time.

     DWORD get_fattime (void);
     
    @@ -22,7 +22,7 @@ DWORD get_fattime (void);

    Return Value

    -

    Currnet local time is returned with packed into a DWORD value. The bit field is as follows:

    +

    Currnet local time shall be returned as bit-fields packed into a DWORD value. The bit fields are as follows:

    bit31:25
    Year origin from the 1980 (0..127)
    diff --git a/firmware/chibios-portapack/ext/fatfs/doc/en/fdisk.html b/firmware/chibios-portapack/ext/fatfs/doc/en/fdisk.html index 6581d87c..8414f919 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/en/fdisk.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/en/fdisk.html @@ -74,10 +74,10 @@ FRESULT f_fdisk ( DWORD plist[] = {50, 50, 0, 0}; /* Divide drive into two partitions */ BYTE work[_MAX_SS]; - f_fdisk(0, plist, work); /* Divide physical drive 0 */ + f_fdisk(0, plist, work); /* Divide physical drive 0 */ - f_mkfs("0:", FMT_ANY, work, sizeof work); /* Create FAT volume on the logical drive 0 */ - f_mkfs("1:", FMT_ANY, work, sizeof work); /* Create FAT volume on the logical drive 1 */ + f_mkfs("0:", FM_ANY, work, sizeof work); /* Create FAT volume on the logical drive 0 */ + f_mkfs("1:", FM_ANY, work, sizeof work); /* Create FAT volume on the logical drive 1 */
    diff --git a/firmware/chibios-portapack/ext/fatfs/doc/en/filename.html b/firmware/chibios-portapack/ext/fatfs/doc/en/filename.html index 23e6c49c..25dc86cd 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/en/filename.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/en/filename.html @@ -10,7 +10,7 @@ -

    Path Names

    +

    Path Names on the FatFs

    Format of the path names

    @@ -19,7 +19,7 @@

    The FatFs module supports long file name (LFN) and 8.3 format file name (SFN). The LFN can be used when (_USE_LFN != 0). The sub directories are separated with a \ or / in the same way as DOS/Windows API. Duplicated separators are skipped and ignored. Only a difference is that the logical drive is specified in a numeral with a colon. When drive number is omitted, the drive number is assumed as default drive (drive 0 or current drive).

    Control characters ('\0' to '\x1F') are recognized as end of the path name. Leading/embedded spaces in the path name are valid as a part of the name at LFN configuration but the space is recognized as end of the path name at non-LFN configuration. Trailing spaces and dots are ignored at both configurations.

    In default configuration (_FS_RPATH == 0), it does not have a concept of current directory like OS oriented file system. All objects on the volume are always specified in full path name that follows from the root directory. Dot directory names (".", "..") are not allowed. Heading separator is ignored and it can be exist or omitted. The default drive is fixed to drive 0.

    -

    When relative path is enabled (_FS_RPATH >= 1), specified path is followed from the root directory if a heading separator is exist. If not, it is followed from the current directory of the drive set by f_chdir function. Dot names are also allowed for the path names. The default drive is the current drive set by f_chdrive function.

    +

    When relative path is enabled (_FS_RPATH >= 1), specified path is followed from the root directory if a heading separator is exist. If not, it is followed from the current directory of the drive set by f_chdir function. Dot names are also allowed for the path names. The default drive is the current drive set by f_chdrive function.

    @@ -36,12 +36,12 @@
    Path name_FS_RPATH == 0_FS_RPATH >= 1
    file.txtA file in the root directory of the drive 0A file in the current directory of the current drive
    /..Invalid nameThe root directory (sticks the top level)

    When option _STR_VOLUME_ID is specified, also pre-defined strings can be used as drive identifier in the path name instead of a numeral. e.g. "sd:file1.txt", "ram:swapfile.dat" and DOS/Windows style drive letter, of course.

    -

    Remark: In this revision, R0.12, double dot name ".." cannot follow the parent directory on the exFAT volume. It will work as "." and stay there.

    +

    Remark: In this revision, double dot name ".." cannot follow the parent directory on the exFAT volume. It will work as "." and stay there.

    Legal Characters and Case Sensitivity

    -

    On the FAT file system, legal characters for file name are, 0-9 A-Z ! # $ % & ' ( ) - @ ^ _ ` { } ~ and extended characters (\x80-\xFF). Under LFN supported system, also white space and + , ; = [ ] are legal for the file name and the white spaces and periods can be placed anywhere in the name except for end of the name string.

    +

    On the FAT file system, legal characters for object name (file/directory name) are, 0-9 A-Z ! # $ % & ' ( ) - @ ^ _ ` { } ~ and extended characters (\x80-\xFF). Under LFN supported system, also + , ; = [ ] and space are legal for the object name and the white spaces and periods can be placed anywhere in the path name except for end of the object name.

    FAT file system is case-insensitive to the object names on the volume. All object names are compared in case-insensitive. For example, these three names, file.txt, File.Txt and FILE.TXT, are identical. This is applied to also extended charactres. When an object is created on the FAT volume, upper converted name is recorded to the SFN entry, and the raw name is recorded to the LFN entry.

    As for the DBCS language MS-DOS, it was case-sensitive to the extended characters. To follow this specification, FatFs works with case-sensitive to the extended characters at only non-LFN with DBCS configuration (DOS/DBCS specs). But at LFN configuration, FatFs works with case-insensitive to all characters (WindowsNT specs). This can cause a problem on compatibility with Windows system when an object with extended characters is created on the volume at non-LFN and DBCS configuration; therfore the object names with DBCS extended characters should not be used on the FAT volume shared by those systems.

    diff --git a/firmware/chibios-portapack/ext/fatfs/doc/en/findfirst.html b/firmware/chibios-portapack/ext/fatfs/doc/en/findfirst.html index 5b4b1fbc..970055df 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/en/findfirst.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/en/findfirst.html @@ -61,11 +61,11 @@ FRESULT f_findfirst (

    Description

    -

    After the directory specified by path could be opened, it starts to search the directory for the items with a name specified by pattern. If found, the information about the object is stored into the file information structure. For more information about file information structure, refer to f_readdir function.

    +

    After the directory specified by path could be opened, it starts to search the directory for items with the name specified by pattern. If the first item is found, the information about the object is stored into the file information structure. For more information about file information structure, refer to f_readdir function.

    The matching pattern can contain wildcard characters (? and *). A ? matches an any character and an * matches an any string in length of zero or longer. When support of long file name is enabled, only fname[] is tested at _USE_FIND == 1 and also altname[] is tested at _USE_FIND == 2. In this revision, there are some differences listed below between FatFs and standard systems in matching condition.

      -
    • "*.*" never matches any name without extension while it matches any names at the standard systems.
    • -
    • Any patterns terminated with a period never matches any name while it matches any names without extensiton at the standard systems.
    • +
    • "*.*" never matches any name without extension while it matches any name with or without extension at the standard systems.
    • +
    • Any pattern terminated with a period never matches any name while it matches any name without extensiton at the standard systems.
    • DBCS extended characters are compared in case-sensitive at LFN with non-Unicode configuration.
    @@ -82,7 +82,7 @@ FRESULT f_findfirst (
     /* Search a directory for objects and display it */
     
    -void find_image (void)
    +void find_image_file (void)
     {
         FRESULT fr;     /* Return value */
         DIR dj;         /* Directory search object */
    @@ -94,6 +94,7 @@ void find_image (void)
             printf("%s\n", fno.fname);                /* Display the object name */
             fr = f_findnext(&dj, &fno);               /* Search for next item */
         }
    +
         f_closedir(&dj);
     }
     
    diff --git a/firmware/chibios-portapack/ext/fatfs/doc/en/forward.html b/firmware/chibios-portapack/ext/fatfs/doc/en/forward.html index eddb051f..b16a0758 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/en/forward.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/en/forward.html @@ -46,6 +46,7 @@ FRESULT f_forward ( FR_DISK_ERR, FR_INT_ERR, FR_INVALID_OBJECT, +FR_DENIED, FR_TIMEOUT

    @@ -114,7 +115,7 @@ FRESULT play_file ( /* Repeat until the file pointer reaches end of the file */ while (rc == FR_OK && !f_eof(&fil)) { - /* any other processes... */ + /* some processes... */ /* Fill output stream periodicaly or on-demand */ rc = f_forward(&fil, out_stream, 1000, &dmy); diff --git a/firmware/chibios-portapack/ext/fatfs/doc/en/getcwd.html b/firmware/chibios-portapack/ext/fatfs/doc/en/getcwd.html index c30aa650..52a7f3f8 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/en/getcwd.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/en/getcwd.html @@ -51,7 +51,7 @@ FRESULT f_getcwd (

    Description

    The f_getcwd function retrieves full path name of the current directory of the current drive. When _VOLUMES is larger than 1, a logical drive number is added to top of the path name.

    -

    Note: In this revision, R0.12, this function cannot retrieve the current directory path on the exFAT volume. It always returns the root directory path.

    +

    Note: In this revision, this function cannot retrieve the current directory path on the exFAT volume. It always returns the root directory path.

    diff --git a/firmware/chibios-portapack/ext/fatfs/doc/en/mkdir.html b/firmware/chibios-portapack/ext/fatfs/doc/en/mkdir.html index 970627c9..7417eacc 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/en/mkdir.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/en/mkdir.html @@ -39,7 +39,7 @@ FRESULT f_mkdir ( FR_NOT_READY, FR_NO_PATH, FR_INVALID_NAME, -FR_DENIED, +FR_DENIED, FR_EXIST, FR_WRITE_PROTECTED, FR_INVALID_DRIVE, diff --git a/firmware/chibios-portapack/ext/fatfs/doc/en/mkfs.html b/firmware/chibios-portapack/ext/fatfs/doc/en/mkfs.html index 52f5c3cb..180ffdf8 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/en/mkfs.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/en/mkfs.html @@ -29,13 +29,13 @@ FRESULT f_mkfs (

    Parameters

    path
    -
    Pointer to the null-terminated string specifies the logical drive to be formatted. If there is no drive number in it, it means the default drive. The logical drive does not need to be mounted.
    +
    Pointer to the null-terminated string specifies the logical drive to be formatted. If there is no drive number in it, it means the default drive. The logical drive may or may not be mounted for the format process.
    opt
    Specifies the format option in combination of FM_FAT, FM_FAT32, FM_EXFAT and bitwise-or of these three, FM_ANY. FM_EXFAT is ignored when exFAT is not enabled. These flags specify which FAT type to be created on the volume. If two or more types are specified, one out of them will be selected depends on the volume size. The flag FM_SFD specifies to place the volume on the drive in SFD format.
    au
    -
    Specifies size of the allocation unit (cluter) in unit of byte. The valid value is N times the sector size. N is power of 2 from 1 to 128 for FAT volume and upto 16MiB for exFAT volume. If zero is given, the default allocation unit size is selected depends on the volume size.
    +
    Specifies size of the allocation unit (cluter) in unit of byte. The valid value is n times the sector size. The n is power of 2 from 1 to 128 for FAT volume and upto 16MiB for exFAT volume. If zero is given, the default allocation unit size is selected depends on the volume size.
    work
    -
    Pointer to the working buffer for the format process.
    +
    Pointer to the working buffer used for the format process.
    len
    Size of the working buffer in unit of byte. It needs to be the sector size at least. Plenty of working buffer reduces number of write transaction to the device and the format process will be finished quickly.
    @@ -78,7 +78,7 @@ int main (void) FIL fil; /* File object */ FRESULT res; /* API result code */ UINT bw; /* Bytes written */ - BYTE work[_MAX_SS]; /* Work area (larger is better for process time) */ + BYTE work[_MAX_SS]; /* Work area (larger is better for processing time) */ /* Create FAT volume */ diff --git a/firmware/chibios-portapack/ext/fatfs/doc/en/mount.html b/firmware/chibios-portapack/ext/fatfs/doc/en/mount.html index f7176327..0999b9c0 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/en/mount.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/en/mount.html @@ -31,7 +31,7 @@ FRESULT f_mount (
    path
    Pointer to the null-terminated string that specifies the logical drive. The string without drive number means the default drive.
    opt
    -
    Initialization option. 0: Do not mount now (to be mounted later), 1: Force mounted the volume to check if the volume is ready to work.
    +
    Mounting option. 0: Do not mount now (to be mounted on the first access to the volume), 1: Force mounted the volume to check if it is ready to work.
    @@ -54,15 +54,15 @@ FRESULT f_mount (
  • Determines the logical drive which specified by path.
  • Clears and unregisters the regsitered work area of the drive if exist.
  • Clears and registers the new work area to the drive if fs is not NULL.
  • -
  • Performs volume mount process to the drive if forced mount is specified.
  • +
  • Performs volume mount process to the drive if forced mounting is specified.
  • -

    The file system object is the work area needed for each logical drive. It must be given to the logical drive with this function prior to use any other file functions except for f_fdisk function to the logical drive. To unregister the work area, specify a NULL to the fs, and then the work area can be discarded.

    -

    If forced mounting is not specified, this function always succeeds regardless of the physical drive status due to delayed mount feature. It only clears (de-initializes) the given work area and registers its address to the internal table. There is no activity of the physical drive in this function. It can also be used to force de-initialized the registered work area of a logical drive. The volume mount processes, initialize the corresponding physical drive, find the FAT volume in it and initialize the work area, is performed in the subsequent file access functions when either or both of following condition is true.

    +

    The file system object is the work area needed for each logical drive. It must be given to the logical drive with this function prior to use any API functions except for f_mkfs/f_fdisk function to the logical drive.

    +

    If forced mounting is not specified (opt = 0), this function always succeeds regardless of the physical drive status. It only clears (de-initializes) the given work area and registers its address to the internal table and no activity of the physical drive in this function. To unregister the work area, specify a NULL to the fs, and then the work area can be discarded. The volume mount processes, initialize the corresponding physical drive, find the FAT volume in it and initialize the work area, is performed in the subsequent file access functions when either or both of following condition is true.

      -
    • File system object is not initialized. It is de-initialized by f_mount function.
    • +
    • File system object has not been initialized. It is de-initialized by f_mount function.
    • Physical drive is not initialized. It is de-initialized by system reset or media removal.
    -

    If the function with forced mounting failed, it means that the file system object has been registered successfully but the volume is currently not ready to work. The volume mount process will also be attempted at subsequent file access functions.

    +

    If the function with forced mounting (opt = 1) failed, it means that the file system object has been registered successfully but the volume is currently not ready to work. The volume mount process will be attempted at subsequent file access functions if the file system object is not initialized. (delayed mounting)

    If implementation of the disk I/O layer lacks media change detection, application program needs to perform a f_mount function after each media change to force cleared the file system object.

    diff --git a/firmware/chibios-portapack/ext/fatfs/doc/en/open.html b/firmware/chibios-portapack/ext/fatfs/doc/en/open.html index 475b5944..de218e12 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/en/open.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/en/open.html @@ -40,7 +40,7 @@ FRESULT f_open ( FA_CREATE_NEWCreates a new file. The function fails with FR_EXIST if the file is existing. FA_CREATE_ALWAYSCreates a new file. If the file is existing, it will be truncated and overwritten. FA_OPEN_ALWAYSOpens the file if it is existing. If not, a new file will be created. -FA_OPEN_APPENDSame as FA_OPEN_ALWAYS except read/write pointer is set end of the file. +FA_OPEN_APPENDSame as FA_OPEN_ALWAYS except the read/write pointer is set end of the file. @@ -57,7 +57,7 @@ FRESULT f_open ( FR_NO_FILE, FR_NO_PATH, FR_INVALID_NAME, -FR_DENIED, +FR_DENIED, FR_EXIST, FR_INVALID_OBJECT, FR_WRITE_PROTECTED, @@ -74,7 +74,7 @@ FRESULT f_open (

    Description

    -

    Before using any file function, a work area (file system object) must be registered to the logical drive with f_mount function. All API functions except for f_mkfs and f_fdisk function can work after this procedure.

    +

    Before using any file function, a work area (file system object) needs to be registered to the logical drive with f_mount function. All API functions except for f_mkfs/f_fdisk function get ready to work after this procedure.

    After f_open function succeeded, the file object is valid. The file object is used for subsequent operations to the file to identify the file. Open file must be closed prior to power down, media removal or re-mount, or the file can be collapsed. To close an open file, use f_close function.

    If duplicated file open is needed, read here carefully. However duplicated open of a file with any write mode flag is always prohibited.

    diff --git a/firmware/chibios-portapack/ext/fatfs/doc/en/printf.html b/firmware/chibios-portapack/ext/fatfs/doc/en/printf.html index 7d917510..f6030528 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/en/printf.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/en/printf.html @@ -39,7 +39,7 @@ int f_printf (

    Return Values

    -

    When the function succeeded, it returns number of characters written. When the function failed due to disk full or any error, an EOF (-1) will be returned.

    +

    When the function succeeded, it returns number of characters written. If the function could not write the generated string to the file due to disk full or an error, EOF (-1) will be returned.

    diff --git a/firmware/chibios-portapack/ext/fatfs/doc/en/rc.html b/firmware/chibios-portapack/ext/fatfs/doc/en/rc.html index ecf2fd47..0e45fbee 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/en/rc.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/en/rc.html @@ -6,12 +6,12 @@ -FatFs - Return Codes +FatFs - API Return Code -

    Return Code of the File Functions

    -

    On the FatFs API, most of file functions return common result code as enum type FRESULT. When a function succeeded, it returns zero, otherwise returns non-zero value that indicates type of error.

    +

    Return Code of API Functions

    +

    Most of API functions return common result code as enum type FRESULT. When an API function succeeded, it returns zero (FR_OK), otherwise it returns non-zero value indicates type of error.

    @@ -25,7 +25,8 @@
    Assertion failed. An insanity is detected in the internal process. One of the following possibilities is suspected.
    • Work area (file system object, file object or etc...) has been broken by stack overflow or any other tasks. This is the reason in most case.
    • -
    • There is any error of the FAT structure on the volume.
    • +
    • There is an error of the FAT structure on the volume.
    • +
    • There is a bug in the FatFs module itself.
    Note that if once this error occured at any operation to an open file, the file object is aborted and all operations to the file except for close will be rejected.
    @@ -50,25 +51,25 @@ Note that if once this error occured at any operation to an open file, the file
  • Deleting the non-empty directory or current directory.
  • Reading the file opened without FA_READ flag.
  • Any modification to the file opened without FA_WRITE flag.
  • -
  • Could not create the file or directory due to the directory table is full.
  • +
  • Could not create the object due to root directory full or disk full.
  • Could not allocate a contiguous area to the file.
  • FR_EXIST
    -
    Name collision. Any object that has the same name is already existing.
    +
    Name collision. An object with the same name is already existing.
    FR_INVALID_OBJECT
    The file/directory object is invalid or a null pointer is given. There are some reasons as follows:
      -
    • It has been closed, it is not opened or it can be collapsed.
    • -
    • It has been invalidated by a voulme mount process. All open objects of the volume are invalidated as well.
    • -
    • The corresponding physical drive is not ready due to a media removal.
    • +
    • It has been closed, it has not been opened or it has been collapsed.
    • +
    • It has been invalidated by a voulme mount process. Open objects on the volume are invalidated by voulme mount process.
    • +
    • Physical drive is not ready to work due to a media removal.
    FR_WRITE_PROTECTED
    -
    Any write mode operation against the write-protected media.
    +
    A write mode operation against the write-protected media.
    FR_INVALID_DRIVE
    Invalid drive number is specified in the path name. A null pointer is given as the path name. (Related option: _VOLUMES)
    @@ -107,7 +108,7 @@ Note that if once this error occured at any operation to an open file, the file
    Number of open objects has been reached maximum value and no more object can be opened. (Related option: _FS_LOCK)
    FR_INVALID_PARAMETER
    -
    The given parameter is invalid or there is any inconsistent.
    +
    The given parameter is invalid or there is an inconsistent for the volume.

    Return

    diff --git a/firmware/chibios-portapack/ext/fatfs/doc/en/read.html b/firmware/chibios-portapack/ext/fatfs/doc/en/read.html index ccd4b85c..3751b7d4 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/en/read.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/en/read.html @@ -45,6 +45,7 @@ FRESULT f_read ( FR_OK, FR_DISK_ERR, FR_INT_ERR, +FR_DENIED, FR_INVALID_OBJECT, FR_TIMEOUT

    @@ -53,7 +54,7 @@ FRESULT f_read (

    Description

    -

    The function starts to read data from the file at the position pointed by the read/write pointer. The read/write pointer advances as number of bytes read. After the function succeeded, *br should be checked to detect end of the file. In case of *br is less than btr, it means the read/write pointer reached end of the file during read operation.

    +

    The function starts to read data from the file at the position pointed by the read/write pointer. The read/write pointer advances as number of bytes read. After the function succeeded, *br should be checked to detect end of the file. In case of *br < btr, it means the read/write pointer reached end of the file during read operation.

    diff --git a/firmware/chibios-portapack/ext/fatfs/doc/en/rename.html b/firmware/chibios-portapack/ext/fatfs/doc/en/rename.html index 47cca44f..efe6f269 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/en/rename.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/en/rename.html @@ -13,7 +13,7 @@

    f_rename

    -

    Renames a file or sub-directory.

    +

    The f_rename function renames and/or moves a file or sub-directory.

     FRESULT f_rename (
       const TCHAR* old_name, /* [IN] Old object name */
    @@ -28,7 +28,7 @@ FRESULT f_rename (
     
    old_name
    Pointer to a null-terminated string that specifies the existing file or sub-directory to be renamed.
    new_name
    -
    Pointer to a null-terminated string that specifies the new object name. Any drive number may be specified in this string but it is ignored and assumed as the same drive of the old_name.
    +
    Pointer to a null-terminated string that specifies the new object name. A drive number may be specified in this string but it is ignored and assumed as the same drive of the old_name. Any object with this path name except old_name must not be exist, or the function fails with FR_EXIST.
    @@ -43,7 +43,6 @@ FRESULT f_rename ( FR_NO_FILE, FR_NO_PATH, FR_INVALID_NAME, -FR_DENIED, FR_EXIST, FR_WRITE_PROTECTED, FR_INVALID_DRIVE, @@ -58,7 +57,7 @@ FRESULT f_rename (

    Description

    -

    Renames a file or sub-directory and can also move it to other directory in the same logical drive. The object to be renamed must not be an open object, or the FAT volume can be collapsed. Such the wrong operation can be rejected safely when file lock feature is enabled.

    +

    Renames a file or sub-directory and can also move it to other directory in the same volume. The object to be renamed must not be an open object, or the FAT volume can be collapsed. Such the wrong operation is rejected safely when file lock function is enabled.

    @@ -77,7 +76,7 @@ FRESULT f_rename ( /* Rename an object in the drive 2 */ f_rename("2:oldname.txt", "newname.txt"); - /* Rename an object and move it to other directory */ + /* Rename an object and move it to other directory in the volume */ f_rename("log.txt", "old/log0001.txt");
    diff --git a/firmware/chibios-portapack/ext/fatfs/doc/en/sfatfs.html b/firmware/chibios-portapack/ext/fatfs/doc/en/sfatfs.html index e701f441..75a31536 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/en/sfatfs.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/en/sfatfs.html @@ -13,7 +13,7 @@

    FATFS

    -

    The FATFS structure (file system object) holds dynamic work area of individual logical drives. It is given by application program and registerd/unregisterd to the FatFs module with f_mount function. Initialization is done on first API call after f_mount function or media change. Application program must not modify any member in this structure, or any data on the FAT volume can be collapsed.

    +

    The FATFS structure (file system object) holds dynamic work area of individual logical drives. It is given by application program and registerd/unregisterd to the FatFs module with f_mount function. Initialization of the structure is done by volume mount process whenever necessary. Application program must not modify any member in this structure, or the FAT volume can be collapsed.

     typedef struct {
         BYTE    fs_type;      /* File system type (0, FS_FAT12, FS_FAT16, FS_FAT32 or FS_EXFAT) */
    diff --git a/firmware/chibios-portapack/ext/fatfs/doc/en/sfileinfo.html b/firmware/chibios-portapack/ext/fatfs/doc/en/sfileinfo.html
    index 268b8c14..6dae1fe3 100644
    --- a/firmware/chibios-portapack/ext/fatfs/doc/en/sfileinfo.html
    +++ b/firmware/chibios-portapack/ext/fatfs/doc/en/sfileinfo.html
    @@ -33,7 +33,7 @@
     

    Members

    fsize
    -
    Indicates size of the file in unit of byte. Always zero for directories. FSIZE_t is an alias of integer type either DWORD(32-bit) or QWORD(64-bit) depends on the configuration option _FS_EXFAT.
    +
    Indicates size of the file in unit of byte. FSIZE_t is an alias of integer type either DWORD(32-bit) or QWORD(64-bit) depends on the configuration option _FS_EXFAT. Do not care when the item is a directory.
    fdate
    Indicates the date when the file was modified or the directory was created.
    diff --git a/firmware/chibios-portapack/ext/fatfs/doc/en/unlink.html b/firmware/chibios-portapack/ext/fatfs/doc/en/unlink.html index 4cd1f660..7d643576 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/en/unlink.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/en/unlink.html @@ -40,7 +40,7 @@ FRESULT f_unlink ( FR_NO_FILE, FR_NO_PATH, FR_INVALID_NAME, -FR_DENIED, +FR_DENIED, FR_EXIST, FR_WRITE_PROTECTED, FR_INVALID_DRIVE, diff --git a/firmware/chibios-portapack/ext/fatfs/doc/en/write.html b/firmware/chibios-portapack/ext/fatfs/doc/en/write.html index 644dd6df..a29f56fd 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/en/write.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/en/write.html @@ -45,6 +45,7 @@ FRESULT f_write ( FR_OK, FR_DISK_ERR, FR_INT_ERR, +FR_DENIED, FR_INVALID_OBJECT, FR_TIMEOUT

    @@ -53,7 +54,7 @@ FRESULT f_write (

    Description

    -

    The function starts to write data to the file at the position pointed by the read/write pointer. The read/write pointer advances as number of bytes written. After the function succeeded, *bw should be checked to detect the disk full. In case of *bw is less than btw, it means the volume got full during the write operation. The function can take a time when the volume is full or close to full.

    +

    The function starts to write data to the file at the position pointed by the read/write pointer. The read/write pointer advances as number of bytes written. After the function succeeded, *bw should be checked to detect the disk full. In case of *bw < btw, it means the volume got full during the write operation. The function can take a time when the volume is full or close to full.

    diff --git a/firmware/chibios-portapack/ext/fatfs/doc/ja/appnote.html b/firmware/chibios-portapack/ext/fatfs/doc/ja/appnote.html index b716ebd3..af934068 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/ja/appnote.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/ja/appnote.html @@ -47,7 +47,7 @@ FatFsモジュールはANSI C(C89)準拠で記述されているので、普通

    functional diagram

    ユーザの作成する関数

    -

    ポーティング作業は、要求されるデバイス制御関数を用意することが全てで、それ以外にすることは何もありません。既に動作しているデバイス制御モジュールがあるなら、そのAPIをFatFsに合わせるかグルー関数を介してつなぐだけで済みますが、無い場合はほかから移植するか最初から書くかする必要があります。定義されている全ての関数が常に必要なわけではありません。例えば、リード オンリ構成では書き込み系関数は必要ありません。次の表に構成オプションと要求される関数の対応を示します。

    +

    ポーティング作業は、要求されるデバイス制御関数を用意することが全てで、それ以外にすることは何もありません。既に動作しているデバイス制御モジュールがあるなら、そのインターフェースをFatFsに合わせるかグルー関数を介してつなぐだけで済みますが、無い場合はほかから移植するか最初から書くかする必要があります。定義されている全ての関数が常に必要なわけではありません。例えば、リード オンリ構成では書き込み系関数は必要ありません。次の表に構成オプションと要求される関数の対応を示します。

    @@ -81,16 +81,16 @@ FatFsモジュールはANSI C(C89)準拠で記述されているので、普通 - - - - + + + +
    必要な関数必要となる条件備考
    disk_status
    disk_initialize
    disk_read
    常時ffsample.zip (サンプル)
    その他web上に多数
    ARM7
    32bit
    ARM7
    Thumb
    CM3
    Thumb-2
    AVRH8/300HPIC24RL78V850ESSH-2ARX600IA-32
    CompilerGCCGCCGCCGCCCH38C30CC78K0RCA850SHCRXCMSC
    text (Full, R/W)10.1k6.6k6.2k12.1k10.5k11.2k12.6k8.5k8.7k6.3k8.4k
    text (Min, R/W) 6.6k4.5k4.2k 7.9k 7.0k 7.6k 8.8k5.9k5.8k4.3k5.8k
    text (Full, R/O) 4.8k3.1k2.9k 5.8k 5.1k 5.5k 6.4k4.1k4.0k3.1k4.0k
    text (Min, R/O) 3.5k2.4k2.3k 4.4k 3.9k 4.2k 5.0k3.3k3.1k2.4k3.1k
    text (Full, R/W)10.4k6.8k6.3k12.4k 9.8k11.1k12.8k8.6k8.9k6.4k8.5k
    text (Min, R/W) 6.8k4.6k4.3k 8.2k 6.7k 7.6k 9.1k6.0k5.9k4.5k5.9k
    text (Full, R/O) 4.8k3.1k2.8k 5.6k 4.6k 5.3k 6.3k4.0k3.9k3.0k3.9k
    text (Min, R/O) 3.6k2.4k2.3k 4.4k 3.5k 4.0k 4.9k3.3k3.0k2.4k3.1k
    bssV*4 + 2V*4 + 2V*4 + 2V*2 + 2V*4 + 2V*2 + 2V*2 + 2V*4 + 2V*4 + 2V*4 + 2V*4 + 2
    Work area
    (_FS_TINY == 0)
    V*564
    + F*552
    V*564
    + F*552
    V*564
    + F*552
    V*560
    + F*546
    V*560
    + F*546
    V*560
    + F*546
    V*560
    + F*546
    V*564
    + F*552
    V*564
    + F*552
    V*564
    + F*552
    V*564
    + F*552
    Work area
    (_FS_TINY == 1)
    V*564
    + F*40
    V*564
    + F*40
    V*564
    + F*40
    V*560
    + F*34
    V*560
    + F*34
    V*560
    + F*34
    V*560
    + F*34
    V*564
    + F*40
    V*564
    + F*40
    V*564
    + F*40
    V*564
    + F*40
    -FatFs R0.12 options:
    +FatFs R0.12b options:
     _FS_READONLY   0 (R/W) or 1 (R/O)
     _FS_MINIMIZE   0 (Full, with all basic functions) or 3 (Min, with fully minimized)
     _FS_TINY       0 (Default) or 1 (Tiny file object)
    @@ -254,13 +254,13 @@ And any other options are left not changed from default setting.
     
     

    FatFsのライセンスについて

    -

    FatFsは、作者(ChaN)の個人プロジェクトとして開発されています。現在のリビジョンにおいてコントリビューターはいないため、作者の書いたソース コード以外は含まれません。ソース ファイルにライセンス条件が記述されているので、利用の際はそれに従うこと。原文は英語ですが、参考までに以下に日本語訳を示しておきます。

    +

    FatFsは、作者(ChaN)の個人プロジェクトとして開発されています。現在までのリビジョンにおいてコントリビューターはいないため、作者以外の書いたソース コードは含まれません。ソース ファイルにライセンス条件が記述されているので、利用の際はそれに従うこと。原文は英語ですが、参考までに以下に日本語訳を示しておきます。

     /*----------------------------------------------------------------------------/
    -/  FatFs - Generic FAT file system module  R0.12a                             /
    +/  FatFs - Generic FAT file system module  Rx.xx                              /
     /-----------------------------------------------------------------------------/
     /
    -/ Copyright (C) 2016, ChaN, all right reserved.
    +/ Copyright (C) 20xx, ChaN, all right reserved.
     /
     / FatFsモジュールはオープンソースソフトウェアです。FatFsの再配布および使用は、
     / ソースコードかバイナリ形式か、また変更の有無にかかわらず、次の条件が満たされ
    diff --git a/firmware/chibios-portapack/ext/fatfs/doc/ja/dinit.html b/firmware/chibios-portapack/ext/fatfs/doc/ja/dinit.html
    index 68f4cc3f..bac8d016 100644
    --- a/firmware/chibios-portapack/ext/fatfs/doc/ja/dinit.html
    +++ b/firmware/chibios-portapack/ext/fatfs/doc/ja/dinit.html
    @@ -13,7 +13,7 @@
     
     

    disk_initialize

    -

    ストレージ デバイスを初期化します。

    +

    ストレージ デバイスの初期化の際に呼ばれます。

     DSTATUS disk_initialize (
       BYTE pdrv      /* [IN] 物理ドライブ番号 */
    diff --git a/firmware/chibios-portapack/ext/fatfs/doc/ja/dioctl.html b/firmware/chibios-portapack/ext/fatfs/doc/ja/dioctl.html
    index b37ffeaf..4b7b24b1 100644
    --- a/firmware/chibios-portapack/ext/fatfs/doc/ja/dioctl.html
    +++ b/firmware/chibios-portapack/ext/fatfs/doc/ja/dioctl.html
    @@ -13,7 +13,7 @@
     
     

    disk_ioctl

    -

    一般的なデータ読み書き以外のストレージ デバイス自体に対する様々な制御を行います。

    +

    一般的なデータ読み書き以外のストレージ デバイス自体に対する様々な制御を行うときに呼ばれます。

     DRESULT disk_ioctl (
       BYTE pdrv,    /* [IN] 物理ドライブ番号 */
    diff --git a/firmware/chibios-portapack/ext/fatfs/doc/ja/dread.html b/firmware/chibios-portapack/ext/fatfs/doc/ja/dread.html
    index 4c8ddba8..6810d709 100644
    --- a/firmware/chibios-portapack/ext/fatfs/doc/ja/dread.html
    +++ b/firmware/chibios-portapack/ext/fatfs/doc/ja/dread.html
    @@ -13,7 +13,7 @@
     
     

    disk_read

    -

    ストレージ デバイスからデータを読み出します。

    +

    ストレージ デバイスからデータを読み出すときに呼ばれます。

     DRESULT disk_read (
       BYTE pdrv,     /* [IN] 物理ドライブ番号 */
    diff --git a/firmware/chibios-portapack/ext/fatfs/doc/ja/dstat.html b/firmware/chibios-portapack/ext/fatfs/doc/ja/dstat.html
    index f965649f..ad503479 100644
    --- a/firmware/chibios-portapack/ext/fatfs/doc/ja/dstat.html
    +++ b/firmware/chibios-portapack/ext/fatfs/doc/ja/dstat.html
    @@ -13,7 +13,7 @@
     
     

    disk_status

    -

    ストレージ デバイスの状態を取得します。

    +

    ストレージ デバイスの状態を取得するために呼ばれます。

     DSTATUS disk_status (
       BYTE pdrv           /* [IN] 物理ドライブ番号 */
    diff --git a/firmware/chibios-portapack/ext/fatfs/doc/ja/dwrite.html b/firmware/chibios-portapack/ext/fatfs/doc/ja/dwrite.html
    index fa0de8d1..cec09768 100644
    --- a/firmware/chibios-portapack/ext/fatfs/doc/ja/dwrite.html
    +++ b/firmware/chibios-portapack/ext/fatfs/doc/ja/dwrite.html
    @@ -13,7 +13,7 @@
     
     

    disk_write

    -

    ストレージ デバイスにデータを書き込みます。

    +

    ストレージ デバイスにデータを書き込むときに呼ばれます。

     DRESULT disk_write (
       BYTE pdrv,        /* [IN] 物理ドライブ番号 */
    diff --git a/firmware/chibios-portapack/ext/fatfs/doc/ja/expand.html b/firmware/chibios-portapack/ext/fatfs/doc/ja/expand.html
    index 98667d10..27c4e66c 100644
    --- a/firmware/chibios-portapack/ext/fatfs/doc/ja/expand.html
    +++ b/firmware/chibios-portapack/ext/fatfs/doc/ja/expand.html
    @@ -43,8 +43,8 @@ FRESULT f_expand (
     FR_OK,
     FR_DISK_ERR,
     FR_INT_ERR,
    -FR_INVALID_OBJECT,
     FR_DENIED,
    +FR_INVALID_OBJECT,
     FR_TIMEOUT
     

    diff --git a/firmware/chibios-portapack/ext/fatfs/doc/ja/fattime.html b/firmware/chibios-portapack/ext/fatfs/doc/ja/fattime.html index ef694ca4..fc727927 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/ja/fattime.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/ja/fattime.html @@ -13,7 +13,7 @@

    get_fattime

    -

    現在時刻を取得します。

    +

    現在時刻を取得する際に呼ばれます。

     DWORD get_fattime (void);
     
    diff --git a/firmware/chibios-portapack/ext/fatfs/doc/ja/fdisk.html b/firmware/chibios-portapack/ext/fatfs/doc/ja/fdisk.html index 2598f7e6..82fc6c24 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/ja/fdisk.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/ja/fdisk.html @@ -74,10 +74,10 @@ FRESULT f_fdisk ( DWORD plist[] = {50, 50, 0, 0}; /* 第1区画,第2区画それぞれに50%ずつ割り当て */ BYTE work[_MAX_SS]; - f_fdisk(0, plist, work); /* 物理ドライブ 0 の分割 */ + f_fdisk(0, plist, work); /* 物理ドライブ 0 の分割 */ - f_mkfs("0:", FMT_ANY, work, sizeof work); /* 論理ドライブ 0: のフォーマット */ - f_mkfs("1:", FMT_ANY, work, sizeof work); /* 論理ドライブ 1: のフォーマット */ + f_mkfs("0:", FM_ANY, work, sizeof work); /* 論理ドライブ 0: のフォーマット */ + f_mkfs("1:", FM_ANY, work, sizeof work); /* 論理ドライブ 1: のフォーマット */
    diff --git a/firmware/chibios-portapack/ext/fatfs/doc/ja/findfirst.html b/firmware/chibios-portapack/ext/fatfs/doc/ja/findfirst.html index c788768b..1ccdd489 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/ja/findfirst.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/ja/findfirst.html @@ -80,9 +80,9 @@ FRESULT f_findfirst (

    使用例

    -/* ディレクトリ内のオブジェクトの検索と表示 */
    +/* ディレクトリ内のjpegファイルの検索 */
     
    -void find_image (void)
    +void find_image_file (void)
     {
         FRESULT fr;     /* API戻り値 */
         DIR dj;         /* ディレクトリ オブジェクト */
    @@ -94,6 +94,7 @@ void find_image (void)
             printf("%s\n", fno.fname);                /* 見つけた項目の名前を表示 */
             fr = f_findnext(&dj, &fno);               /* 次を検索 */
         }
    +
         f_closedir(&dj);
     }
     
    diff --git a/firmware/chibios-portapack/ext/fatfs/doc/ja/forward.html b/firmware/chibios-portapack/ext/fatfs/doc/ja/forward.html index 34f4f483..bdc66426 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/ja/forward.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/ja/forward.html @@ -45,7 +45,7 @@ FRESULT f_forward ( FR_OK, FR_DISK_ERR, FR_INT_ERR, -FR_DENIED, +FR_DENIED, FR_INVALID_OBJECT, FR_TIMEOUT

    diff --git a/firmware/chibios-portapack/ext/fatfs/doc/ja/mkdir.html b/firmware/chibios-portapack/ext/fatfs/doc/ja/mkdir.html index 5e92469a..e7fc916b 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/ja/mkdir.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/ja/mkdir.html @@ -39,7 +39,7 @@ FRESULT f_mkdir ( FR_NOT_READY, FR_NO_PATH, FR_INVALID_NAME, -FR_DENIED, +FR_DENIED, FR_EXIST, FR_WRITE_PROTECTED, FR_INVALID_DRIVE, diff --git a/firmware/chibios-portapack/ext/fatfs/doc/ja/mount.html b/firmware/chibios-portapack/ext/fatfs/doc/ja/mount.html index d7906bec..7fde855b 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/ja/mount.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/ja/mount.html @@ -52,8 +52,8 @@ FRESULT f_mount (

    FatFsモジュールでは、それぞれの論理ドライブにファイル システム オブジェクトというワーク エリアが必要です。この関数は論理ドライブにファイル システム オブジェクトを登録したり抹消したりします。何らかのファイル関数を使用する前に、この関数でその論理ドライブのファイル システム オブジェクトを与えておかなければなりません。fsにヌル ポインタを指定すると、その論理ドライブのファイル システム オブジェクトの登録は抹消されるだけです。登録抹消されたファイル システム オブジェクトのメモリは解放できます。操作の対象の論理ドライブ上に開かれたままのファイルやディレクトリがあった場合、それらに対して作成された構造体は全て無効になります。この関数の内部処理は次のような順に行われます。

    1. 対象の論理ドライブをpathから得る。
    2. -
    3. 既に登録されているファイル システム オブジェクトはクリア(無効化)し、登録を解除する。
    4. -
    5. fsが有効なポインタのときは、そのファイル システム オブジェクトをクリアし登録する。
    6. +
    7. 登録されているファイル システム オブジェクトがあるときは、それをクリア(無効化)し、登録を解除する。
    8. +
    9. fsが有効なポインタのときは、そのファイル システム オブジェクトをクリアし、登録する。
    10. マウント動作が指定されているときは、それを実行する。

    optに0を指定すると、マウント動作(物理ドライブの初期化、FATボリュームの検索、BPBを解析しファイル システム オブジェクトを初期化)は行われず、関数は物理ドライブの状態に関わらず常に成功します。関数内では下位レイヤへのアクセスは発生せず、指定されたファイル システム オブジェクトをクリア(無効化)し、そのアドレスを内部配列に登録するだけです。単に登録済みのファイル システム オブジェクトをクリアする目的にも使えます。実際のマウント動作は、ボリュームへのアクセス(パス名を渡すもの全て)が行われたときに、次のうちいずれかの条件が真の場合に行われます。

    diff --git a/firmware/chibios-portapack/ext/fatfs/doc/ja/open.html b/firmware/chibios-portapack/ext/fatfs/doc/ja/open.html index 9fb76427..9e1f2c13 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/ja/open.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/ja/open.html @@ -57,7 +57,7 @@ FRESULT f_open ( FR_NO_FILE, FR_NO_PATH, FR_INVALID_NAME, -FR_DENIED, +FR_DENIED, FR_EXIST, FR_INVALID_OBJECT, FR_WRITE_PROTECTED, diff --git a/firmware/chibios-portapack/ext/fatfs/doc/ja/rc.html b/firmware/chibios-portapack/ext/fatfs/doc/ja/rc.html index 561f3846..50005e8a 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/ja/rc.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/ja/rc.html @@ -11,22 +11,23 @@

    ファイル関数の戻り値

    -

    FatFsのAPIでは、一部の関数を除き結果に応じた共通のリザルト コード(FRESULT型(enum))を返します。関数が成功した場合は0を返します。失敗した場合は0以外の値を返し、値はエラーの種類を示します。

    +

    FatFsのAPIでは、一部の関数を除き結果に応じた共通のリザルト コード(FRESULT型(enum))を返します。関数が成功した場合は0 (FR_OK)を返します。失敗した場合は0以外の値を返し、値はエラーの種類を示します。

    FR_OK (0)
    関数は成功した。
    FR_DISK_ERR
    -
    下位レイヤ(disk_read/disk_write/disk_ioctl関数)で回復不能なエラーが発生した。
    ※開かれたファイルの操作においてこのエラーが発生すると、そのファイル オブジェクトはアボート状態となり、クローズ以外のの操作ができなくなります。
    +
    下位レイヤ(disk_read/disk_write/disk_ioctl関数)で回復不能なエラーが発生した。
    ※開かれたファイルの操作においてこのエラーが発生すると、そのファイル オブジェクトはアボート状態となり、クローズ以外の操作ができなくなります。
    FR_INT_ERR
    -
    内部処理の健全性に異常が検出された。原因としては次のようなことが考えられます。 +
    内部処理の健全性チェックで何らかの異常が検出された。原因としては次のようなことが考えられます。
      -
    • ボリューム上のFAT構造にエラーがある。
    • スタック不足や不正なメモリ操作等によるワーク エリアの破壊。多くはこれが原因。
    • +
    • ボリューム上のFAT構造にエラーがある。
    • +
    • FatFsモジュール自体のバグ。
    ※開かれたファイルの操作においてこのエラーが発生すると、そのファイル オブジェクトはアボート状態となり、クローズ以外の操作ができなくなります。
    FR_NOT_READY
    -
    disk_initialize関数の失敗。物理ドライブが動作可能な状態にない。
    +
    下位レイヤ(disk_initialize関数)の失敗。つまり、物理ドライブが動作可能な状態にない。
    FR_NO_FILE
    指定されたファイルが見つからなかった。
    FR_NO_PATH
    @@ -41,7 +42,8 @@
  • 空でないディレクトリまたはカレント ディレクトリを削除しようとした。
  • FA_READフラグを付けずに開いたファイルに対して読み出しを行った。
  • FA_WRITEフラグを付けずに開いたファイルに対して変更を加えようとした。
  • -
  • ボリュームまたは静的ディレクトリが満杯でオブジェクトの新規作成ができなかった。
  • +
  • ボリュームまたは静的ディレクトリ(FAT12/16のルート)が満杯でディレクトリ エントリの新規作成ができなかった。
  • +
  • ファイルに割り当てる連続領域が見つからなかった。
  • FR_EXIST
    @@ -50,8 +52,8 @@
    指定されたファイル オブジェクトやディレクトリ オブジェクトが無効、またはヌル ポインタが渡された。無効になる理由は次のことが考えられます。
    • オープンされていない、既に閉じられた、破損しているなど。
    • -
    • それの属するボリュームのマウント動作があった。ボリューム上で開かれたオブジェクトは全て無効化される。
    • -
    • 関連する物理ドライブがメディアの取り外しで動作不可能になっている。
    • +
    • そのボリュームでマウント動作があり、ボリューム上の開かれたオブジェクトが全て無効化された。
    • +
    • 物理ドライブがメディアの取り外しで動作不可能になっている。
    FR_WRITE_PROTECTED
    diff --git a/firmware/chibios-portapack/ext/fatfs/doc/ja/read.html b/firmware/chibios-portapack/ext/fatfs/doc/ja/read.html index e33e564e..c0c03a3e 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/ja/read.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/ja/read.html @@ -45,7 +45,7 @@ FRESULT f_read ( FR_OK, FR_DISK_ERR, FR_INT_ERR, -FR_DENIED, +FR_DENIED, FR_INVALID_OBJECT, FR_TIMEOUT

    diff --git a/firmware/chibios-portapack/ext/fatfs/doc/ja/rename.html b/firmware/chibios-portapack/ext/fatfs/doc/ja/rename.html index a768b9aa..84bb7978 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/ja/rename.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/ja/rename.html @@ -28,7 +28,7 @@ FRESULT f_rename (
    old_name
    変更対象のファイルまたはサブ ディレクトリのパス名を示すヌル文字'\0'終端の文字列へのポインタを指定します。
    new_name
    -
    新しいパス名を示すヌル文字'\0'終端の文字列へのポインタを指定します。既に存在するオブジェクトと同じ名前は使えません。また、ドライブ番号は指定しても無視され、old_nameで決められた論理ドライブ上のオブジェクトとして扱われます。
    +
    新しいパス名を示すヌル文字'\0'終端の文字列へのポインタを指定します。また、ドライブ番号は指定しても無視され、old_nameで決められたボリューム上のオブジェクトとして扱われます。これと同じパス名(old_nameは除く)のオブジェクトが存在すると、関数はFR_EXISTで失敗します。
    diff --git a/firmware/chibios-portapack/ext/fatfs/doc/ja/sfatfs.html b/firmware/chibios-portapack/ext/fatfs/doc/ja/sfatfs.html index 12e54e16..7079133c 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/ja/sfatfs.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/ja/sfatfs.html @@ -13,7 +13,7 @@

    FATFS

    -

    FATFS構造体(ファイル システム オブジェクト)は、個々の論理ドライブのダイナミック ワーク エリアを保持し、f_mount関数でFatFsモジュールに登録されます。初期化が行われるタイミングは、f_mount関数(強制マウント指定)の実行またはメディア交換の後の最初のファイル アクセスの時です。アプリケーションは、この構造体のメンバを書き換えてはなりません。

    +

    FATFS構造体(ファイル システム オブジェクト)は、個々の論理ドライブのダイナミック ワーク エリアを保持し、f_mount関数でFatFsモジュールに登録されます。構造体の作成は、随時ボリューム マウント プロセスにより行われます。アプリケーションは、この構造体のメンバを書き換えてはなりません。

     typedef struct {
    diff --git a/firmware/chibios-portapack/ext/fatfs/doc/ja/truncate.html b/firmware/chibios-portapack/ext/fatfs/doc/ja/truncate.html
    index 54026031..9d9298d9 100644
    --- a/firmware/chibios-portapack/ext/fatfs/doc/ja/truncate.html
    +++ b/firmware/chibios-portapack/ext/fatfs/doc/ja/truncate.html
    @@ -36,7 +36,7 @@ FRESULT f_truncate (
     FR_OK,
     FR_DISK_ERR,
     FR_INT_ERR,
    -FR_DENIED,
    +FR_DENIED,
     FR_INVALID_OBJECT,
     FR_TIMEOUT
     

    diff --git a/firmware/chibios-portapack/ext/fatfs/doc/ja/unlink.html b/firmware/chibios-portapack/ext/fatfs/doc/ja/unlink.html index d9b631b0..1f3c7ec2 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/ja/unlink.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/ja/unlink.html @@ -40,7 +40,7 @@ FRESULT f_unlink ( FR_NO_FILE, FR_NO_PATH, FR_INVALID_NAME, -FR_DENIED, +FR_DENIED, FR_WRITE_PROTECTED, FR_INVALID_DRIVE, FR_NOT_ENABLED, diff --git a/firmware/chibios-portapack/ext/fatfs/doc/ja/write.html b/firmware/chibios-portapack/ext/fatfs/doc/ja/write.html index a5ea4654..6286a594 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/ja/write.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/ja/write.html @@ -45,7 +45,7 @@ FRESULT f_write ( FR_OK, FR_DISK_ERR, FR_INT_ERR, -FR_DENIED, +FR_DENIED, FR_INVALID_OBJECT, FR_TIMEOUT

    diff --git a/firmware/chibios-portapack/ext/fatfs/doc/res/rwtest1.png b/firmware/chibios-portapack/ext/fatfs/doc/res/rwtest1.png index af51c5f9cf13ff09c65ba7fe0a8dc973dd476bcb..bc0330200bcf272a14b4d0a103764e25ceec1a3f 100644 GIT binary patch literal 69114 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 W{F2^CIIy;4x^~r2yYR}L(EkB`Cc@hQ diff --git a/firmware/chibios-portapack/ext/fatfs/doc/updates.txt b/firmware/chibios-portapack/ext/fatfs/doc/updates.txt new file mode 100644 index 00000000..ebb6026a --- /dev/null +++ b/firmware/chibios-portapack/ext/fatfs/doc/updates.txt @@ -0,0 +1,189 @@ +R0.12b (September 4, 2016) + Improved f_rename() to be able to rename objects with the same name but case. + Fixed an error in the case conversion teble of code page 866. (ff.c) + Fixed writing data is truncated at the file offset 4GiB on the exFAT volume. (appeared at R0.12) + Fixed creating a file in the root directory of exFAT volume can fail. (appeared at R0.12) + Fixed f_mkfs() creating exFAT volume with too small cluster size can collapse unallocated memory. (appeared at R0.12) + Fixed wrong object name can be returned when read directory at Unicode cfg. (appeared at R0.12) + Fixed large file allocation/removing on the exFAT volume collapses allocation bitmap. (appeared at R0.12) + Fixed some internal errors in f_expand() and f_lseek(). (appeared at R0.12) + +R0.12a (July 10, 2016) + Added support for creating exFAT volume with some changes of f_mkfs(). + Added a file open method FA_OPEN_APPEND. An f_lseek() following f_open() is no longer needed. + f_forward() is available regardless of _FS_TINY. + Fixed f_mkfs() creates wrong volume. (appeared at R0.12) + Fixed wrong memory read in create_name(). (appeared at R0.12) + Fixed compilation fails at some configurations, _USE_FASTSEEK and _USE_FORWARD. + +R0.12 (April 12, 2016) + Added support for exFAT file system. (_FS_EXFAT) + Added f_expand(). (_USE_EXPAND) + Changed some members in FINFO structure and behavior of f_readdir(). + Added an option _USE_CHMOD and removed an option _WORD_ACCESS. + Fixed errors in the case conversion teble of Unicode (cc*.c). + +R0.11a (September 5, 2015) + Fixed wrong media change can lead a deadlock at thread-safe configuration. + Added code page 771, 860, 861, 863, 864, 865 and 869. (_CODE_PAGE) + Removed some code pages actually not exist on the standard systems. (_CODE_PAGE) + Fixed errors in the case conversion teble of code page 437 and 850 (ff.c). + Fixed errors in the case conversion teble of Unicode (cc*.c). + +R0.11 (February 9, 2015) + Added f_findfirst() and f_findnext(). (_USE_FIND) + Fixed f_unlink() does not remove cluster chain of the file. (appeared at R0.10c) + Fixed _FS_NORTC option does not work properly. (appeared at R0.10c) + +R0.10c (November 9, 2014) + Added a configuration option for the platforms without RTC. (_FS_NORTC) + Fixed volume label created by Mac OS X cannot be retrieved with f_getlabel(). (appeared at R0.09b) + Fixed a potential problem of FAT access that can appear on disk error. + Fixed null pointer dereference on attempting to delete the root direcotry. (appeared at R0.08) + +R0.10b (May 19, 2014) + Fixed a hard error in the disk I/O layer can collapse the directory entry. + Fixed LFN entry is not deleted on delete/rename an object with its lossy converted SFN. (appeared at R0.07) + +R0.10a (January 15, 2014) + Added arbitrary strings as drive number in the path name. (_STR_VOLUME_ID) + Added an option for minimum sector size. (_MIN_SS) + 2nd argument of f_rename() can have a drive number and it will be ignored. + Fixed f_mount() with forced mount fails when drive number is larger than 0. (appeared at R0.10) + Fixed f_close() invalidates the file object without volume lock. + Fixed volume lock is left acquired after return from f_closedir(). (appeared at R0.10) + Fixed creation of a directory entry with LFN fails on too many SFN collisions. (appeared at R0.07) + +R0.10 (October 2, 2013) + Added an option for character encoding on the file. (_STRF_ENCODE) + Added f_closedir(). + Added forced full FAT scan option for f_getfree(). (_FS_NOFSINFO) + Added forced mount option with changes of f_mount(). + Improved behavior of volume auto detection. + Improved write throughput of f_puts() and f_printf(). + Changed argument of f_chdrive(), f_mkfs(), disk_read() and disk_write(). + Fixed f_write() can be truncated when the file size is close to 4GB. + Fixed f_open(), f_mkdir() and f_setlabel() can return incorrect result code on error. + +R0.09b (January 24, 2013) + Added f_getlabel() and f_setlabel(). (_USE_LABEL = 1) + +R0.09a (August 27, 2012) + Fixed assertion failure due to OS/2 EA on FAT12/16 volume. + Changed file functions reject null object pointer to avoid crash. + Changed option name _FS_SHARE to _FS_LOCK. + +R0.09 (September 6, 2011) + f_mkfs() supports multiple partition on a physical drive. + Added f_fdisk(). (_MULTI_PARTITION = 2) + +R0.08b (January 15, 2011) + Fast seek function is also applied to f_read() and f_write(). + f_lseek() reports required table size on creating CLMP. + Extended format syntax of f_printf(). + Ignores duplicated directory separators in given path names. + +R0.08a (August 16, 2010) + Added f_getcwd(). (_FS_RPATH = 2) + Added sector erase function. (_USE_ERASE) + Moved file lock semaphore table from fs object to the bss. + Fixed a wrong directory entry is created on non-LFN cfg when the given name contains ';'. + Fixed f_mkfs() creates wrong FAT32 volume. + +R0.08 (May 15, 2010) + Added a memory configuration option. (_USE_LFN) + Added support of file lock. (_FS_SHARE) + Added fast seek function. (_USE_FASTSEEK) + Changed some types on the API, XCHAR->TCHAR. + Changed fname member in the FILINFO structure on Unicode cfg. + String functions support UTF-8 encoding files on Unicode cfg. + +R0.07e (November 3, 2009) + Separated out configuration options from ff.h to ffconf.h. + Added a configuration option, _LFN_UNICODE. + Fixed f_unlink() fails to remove a sub-dir on _FS_RPATH. + Fixed name matching error on the 13 char boundary. + Changed f_readdir() to return the SFN with always upper case on non-LFN cfg. + +R0.07c (Junuary 21, 2009) + Fixed f_unlink() may return FR_OK on error. + Fixed wrong cache control in f_lseek(). + Added support of relative path. + Added f_chdir(). + Added f_chdrive(). + Added proper case conversion to extended characters. + +R0.07a (April 14, 2009) + Separated out OS dependent code on re-entrant configuration. + Added multiple sector size support. + +R0.07 (April 1, 2009) + Merged Tiny-FatFs into FatFs as a buffer configuration option. + Added long file name support. + Added multiple code page support. + Added re-entrancy for multitask operation. + Added auto cluster size selection to f_mkfs(). + Added rewind option to f_readdir(). + Changed result code of critical errors. + Renamed string functions to avoid name collision. + +R0.06 (April 1, 2008) + Added f_forward. (Tiny-FatFs) + Added string functions: fgets, fputc, fputs and fprintf. + Improved performance of f_lseek on moving to the same or following cluster. + +R0.05a (February 3, 2008) + Added f_truncate. + Added f_utime. + Fixed off by one error at FAT sub-type determination. + Fixed btr in f_read can be mistruncated. + Fixed cached sector is left not flushed when create and close without write. + +R0.05 (August 26, 2007) + Changed arguments of f_read, f_write. + Changed arguments of f_mkfs. (FatFs) + Fixed f_mkfs on FAT32 creates incorrect FSInfo. (FatFs) + Fixed f_mkdir on FAT32 creates incorrect directory. (FatFs) + +R0.04b (May 5, 2007) + Added _USE_NTFLAG option. + Added FSInfo support. + Fixed some problems corresponds to FAT32. (Tiny-FatFs) + Fixed DBCS name can result FR_INVALID_NAME. + Fixed short seek (<= csize) collapses the file object. + +R0.04a (April 1, 2007) + Supported multiple partitions on a plysical drive. (FatFs) + Added minimization level 3. + Added a capability of extending file size to f_lseek. + Fixed an endian sensitive code in f_mkfs. (FatFs) + Fixed a problem corresponds to FAT32 support. (Tiny-FatFs) + +R0.04 (February 4, 2007) + Supported multiple drive system. (FatFs) + Changed some APIs for multiple drive system. + Added f_mkfs. (FatFs) + Added _USE_FAT32 option. (Tiny-FatFs) + +R0.03a (December 11, 2006) + Improved cluster scan algolithm to write files fast. + Fixed f_mkdir creates incorrect directory on FAT32. + +R0.03 (September 22, 2006) + Added f_rename. + Changed option _FS_MINIMUM to _FS_MINIMIZE. + +R0.02a (June 10, 2006) + Added a configuration option _FS_MINIMUM. + +R0.02 (Jun 01, 2006) + Added FAT12. + Removed unbuffered mode. + Fixed a problem on small (<32M) patition. + +R0.01 (April 29, 2006) + First release + +R0.00 (February 26, 2006) + Prototype (not released) + diff --git a/firmware/chibios-portapack/ext/fatfs/src/00history.txt b/firmware/chibios-portapack/ext/fatfs/src/00history.txt index 151b6949..49aac282 100644 --- a/firmware/chibios-portapack/ext/fatfs/src/00history.txt +++ b/firmware/chibios-portapack/ext/fatfs/src/00history.txt @@ -260,8 +260,20 @@ R0.12a (July 10, 2016) Added support for creating exFAT volume with some changes of f_mkfs(). Added a file open method FA_OPEN_APPEND. An f_lseek() following f_open() is no longer needed. f_forward() is available regardless of _FS_TINY. - Fixed f_mkfs() creates wrong volume. + Fixed f_mkfs() creates wrong volume. (appeared at R0.12) + Fixed wrong memory read in create_name(). (appeared at R0.12) Fixed compilation fails at some configurations, _USE_FASTSEEK and _USE_FORWARD. - Fixed wrong memory read in create_name(). + +R0.12b (September 04, 2016) + + Improved f_rename() to be able to rename objects with the same name but case. + Fixed an error in the case conversion teble of code page 866. (ff.c) + Fixed writing data is truncated at the file offset 4GiB on the exFAT volume. (appeared at R0.12) + Fixed creating a file in the root directory of exFAT volume can fail. (appeared at R0.12) + Fixed f_mkfs() creating exFAT volume with too small cluster size can collapse unallocated memory. (appeared at R0.12) + Fixed wrong object name can be returned when read directory at Unicode cfg. (appeared at R0.12) + Fixed large file allocation/removing on the exFAT volume collapses allocation bitmap. (appeared at R0.12) + Fixed some internal errors in f_expand() and f_lseek(). (appeared at R0.12) + diff --git a/firmware/chibios-portapack/ext/fatfs/src/diskio.c b/firmware/chibios-portapack/ext/fatfs/src/diskio.c index 1d57ddb4..25f5e53b 100644 --- a/firmware/chibios-portapack/ext/fatfs/src/diskio.c +++ b/firmware/chibios-portapack/ext/fatfs/src/diskio.c @@ -41,7 +41,7 @@ DSTATUS disk_status ( return stat; - case DEB_USB : + case DEV_USB : result = USB_disk_status(); // translate the reslut code here diff --git a/firmware/chibios-portapack/ext/fatfs/src/ff.c b/firmware/chibios-portapack/ext/fatfs/src/ff.c index 04e197cf..ffc52409 100644 --- a/firmware/chibios-portapack/ext/fatfs/src/ff.c +++ b/firmware/chibios-portapack/ext/fatfs/src/ff.c @@ -1,5 +1,5 @@ /*----------------------------------------------------------------------------/ -/ FatFs - Generic FAT file system module R0.12a / +/ FatFs - Generic FAT file system module R0.12b / /-----------------------------------------------------------------------------/ / / Copyright (C) 2016, ChaN, all right reserved. @@ -28,7 +28,7 @@ ---------------------------------------------------------------------------*/ -#if _FATFS != 80186 /* Revision ID */ +#if _FATFS != 68020 /* Revision ID */ #error Wrong include file (ff.h). #endif @@ -396,7 +396,7 @@ typedef struct { #define BPB_NumFATs 16 /* Number of FATs (BYTE) */ #define BPB_RootEntCnt 17 /* Size of root directory area for FAT12/16 [entry] (WORD) */ #define BPB_TotSec16 19 /* Volume size (16-bit) [sector] (WORD) */ -#define BPB_Media 21 /* Media descriptor (BYTE) */ +#define BPB_Media 21 /* Media descriptor byte (BYTE) */ #define BPB_FATSz16 22 /* FAT size (16-bit) [sector] (WORD) */ #define BPB_SecPerTrk 24 /* Track size for int13h [sector] (WORD) */ #define BPB_NumHeads 26 /* Number of heads for int13h (WORD) */ @@ -409,6 +409,7 @@ typedef struct { #define BS_VolLab 43 /* Volume label string (8-byte) */ #define BS_FilSysType 54 /* File system type string (8-byte) */ #define BS_BootCode 62 /* Boot code (448-byte) */ +#define BS_55AA 510 /* Signature word (WORD) */ #define BPB_FATSz32 36 /* FAT32: FAT size [sector] (DWORD) */ #define BPB_ExtFlags32 40 /* FAT32: Extended flags (WORD) */ @@ -462,8 +463,6 @@ typedef struct { #define PTE_StLba 8 /* MBR PTE: Start in LBA */ #define PTE_SizLba 12 /* MBR PTE: Size in LBA */ -#define BS_55AA 510 /* Signature word (WORD) */ - #define DIR_Name 0 /* Short file name (11-byte) */ #define DIR_Attr 11 /* Attribute (BYTE) */ #define DIR_NTres 12 /* Lower case flag (BYTE) */ @@ -1141,7 +1140,7 @@ DWORD find_bitmap ( /* 0:No free cluster, 2..:Free cluster found, 0xFFFFFFFF:Dis if (clst >= fs->n_fatent - 2) clst = 0; scl = val = clst; ctr = 0; for (;;) { - if (move_window(fs, fs->database + val / 8 / SS(fs)) != FR_OK) return 0xFFFFFFFF; + if (move_window(fs, fs->database + val / 8 / SS(fs)) != FR_OK) return 0xFFFFFFFF; /* (assuming bitmap is located top of the cluster heap) */ i = val / 8 % SS(fs); bm = 1 << (val % 8); do { do { @@ -1180,7 +1179,7 @@ FRESULT change_bitmap ( clst -= 2; /* The first bit corresponds to cluster #2 */ - sect = fs->database + clst / 8 / SS(fs); /* Sector address */ + sect = fs->database + clst / 8 / SS(fs); /* Sector address (assuming bitmap is located top of the cluster heap) */ i = clst / 8 % SS(fs); /* Byte offset in the sector */ bm = 1 << (clst % 8); /* Bit mask in the byte */ for (;;) { @@ -1321,7 +1320,7 @@ DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk err if (clst == 0) { /* Create a new chain */ - scl = fs->last_clst; /* Get suggested cluster to start at */ + scl = fs->last_clst; /* Get suggested cluster to start from */ if (scl == 0 || scl >= fs->n_fatent) scl = 1; } else { /* Stretch current chain */ @@ -1333,7 +1332,7 @@ DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk err } #if _FS_EXFAT - if (fs->fs_type == FS_EXFAT) { /* At the exFAT */ + if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ ncl = find_bitmap(fs, scl, 1); /* Find a free cluster */ if (ncl == 0 || ncl == 0xFFFFFFFF) return ncl; /* No free cluster or hard error? */ res = change_bitmap(fs, ncl, 1, 1); /* Mark the cluster 'in use' */ @@ -1349,7 +1348,7 @@ DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk err } } else #endif - { /* At the FAT12/16/32 */ + { /* On the FAT12/16/32 volume */ ncl = scl; /* Start cluster */ for (;;) { ncl++; /* Next cluster */ @@ -1775,7 +1774,7 @@ void gen_numname ( /* itoa (hexdecimal) */ i = 7; do { - c = (seq % 16) + '0'; + c = (BYTE)((seq % 16) + '0'); if (c > '9') c += 7; ns[i--] = c; seq /= 16; @@ -2105,7 +2104,7 @@ FRESULT dir_read ( c = dp->dir[DIR_Name]; /* Test for the entry type */ if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of the directory */ #if _FS_EXFAT - if (fs->fs_type == FS_EXFAT) { /* At the exFAT */ + if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ if (_USE_LABEL && vol) { if (c == 0x83) break; /* Volume label entry? */ } else { @@ -2120,7 +2119,7 @@ FRESULT dir_read ( } } else #endif - { /* At the FAT12/16/32 */ + { /* On the FAT12/16/32 volume */ dp->obj.attr = a = dp->dir[DIR_Attr] & AM_MASK; /* Get attribute */ #if _USE_LFN != 0 /* LFN configuration */ if (c == DDEM || c == '.' || (int)((a & ~AM_ARC) == AM_VOL) != vol) { /* An entry without valid data */ @@ -2129,7 +2128,7 @@ FRESULT dir_read ( if (a == AM_LFN) { /* An LFN entry is found */ if (c & LLEF) { /* Is it start of an LFN sequence? */ sum = dp->dir[LDIR_Chksum]; - c &= ~LLEF; ord = c; + c &= (BYTE)~LLEF; ord = c; dp->blk_ofs = dp->dptr; } /* Check LFN validity and capture it */ @@ -2178,7 +2177,7 @@ FRESULT dir_find ( /* FR_OK(0):succeeded, !=0:error */ res = dir_sdi(dp, 0); /* Rewind directory object */ if (res != FR_OK) return res; #if _FS_EXFAT - if (fs->fs_type == FS_EXFAT) { /* At the exFAT */ + if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ BYTE nc; UINT di, ni; WORD hash = xname_sum(fs->lfnbuf); /* Hash value of the name to find */ @@ -2194,7 +2193,7 @@ FRESULT dir_find ( /* FR_OK(0):succeeded, !=0:error */ return res; } #endif - /* At the FAT12/16/32 */ + /* On the FAT12/16/32 volume */ #if _USE_LFN != 0 ord = sum = 0xFF; dp->blk_ofs = 0xFFFFFFFF; /* Reset LFN sequence */ #endif @@ -2212,7 +2211,7 @@ FRESULT dir_find ( /* FR_OK(0):succeeded, !=0:error */ if (!(dp->fn[NSFLAG] & NS_NOLFN)) { if (c & LLEF) { /* Is it start of LFN sequence? */ sum = dp->dir[LDIR_Chksum]; - c &= ~LLEF; ord = c; /* LFN start order */ + c &= (BYTE)~LLEF; ord = c; /* LFN start order */ dp->blk_ofs = dp->dptr; /* Start offset of LFN */ } /* Check validity of the LFN entry and compare it with given name */ @@ -2258,7 +2257,7 @@ FRESULT dir_register ( /* FR_OK:succeeded, FR_DENIED:no free entry or too many S for (nlen = 0; fs->lfnbuf[nlen]; nlen++) ; /* Get lfn length */ #if _FS_EXFAT - if (fs->fs_type == FS_EXFAT) { /* At the exFAT */ + if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ DIR dj; nent = (nlen + 14) / 15 + 2; /* Number of entries to allocate (85+C0+C1s) */ @@ -2284,7 +2283,7 @@ FRESULT dir_register ( /* FR_OK:succeeded, FR_DENIED:no free entry or too many S return FR_OK; } #endif - /* At the FAT12/16/32 */ + /* On the FAT12/16/32 volume */ mem_cpy(sn, dp->fn, 12); if (sn[NSFLAG] & NS_LOSS) { /* When LFN is out of 8.3 format, generate a numbered name */ dp->fn[NSFLAG] = NS_NOLFN; /* Find only SFN */ @@ -2361,9 +2360,9 @@ FRESULT dir_remove ( /* FR_OK:Succeeded, FR_DISK_ERR:A disk error */ res = move_window(fs, dp->sect); if (res != FR_OK) break; /* Mark an entry 'deleted' */ - if (_FS_EXFAT && fs->fs_type == FS_EXFAT) { /* At the exFAT */ + if (_FS_EXFAT && fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ dp->dir[XDIR_Type] &= 0x7F; - } else { /* At the FAT12/16/32 */ + } else { /* On the FAT12/16/32 volume */ dp->dir[DIR_Name] = DDEM; } fs->wflag = 1; @@ -2413,12 +2412,12 @@ void get_fileinfo ( /* No return code */ #if _USE_LFN != 0 /* LFN configuration */ #if _FS_EXFAT - if (fs->fs_type == FS_EXFAT) { /* At the exFAT */ + if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ get_xdir_info(fs->dirbuf, fno); return; } else #endif - { /* At the FAT12/16/32 */ + { /* On the FAT12/16/32 volume */ if (dp->blk_ofs != 0xFFFFFFFF) { /* Get LFN if available */ i = j = 0; while ((w = fs->lfnbuf[j++]) != 0) { /* Get an LFN character */ @@ -2628,7 +2627,7 @@ FRESULT create_name ( /* FR_OK: successful, FR_INVALID_NAME: could not create */ if (si) cf |= NS_LOSS | NS_LFN; while (di && lfn[di - 1] != '.') di--; /* Find extension (di<=si: no extension) */ - b = i = 0; ni = 8; + i = b = 0; ni = 8; for (;;) { w = lfn[si++]; /* Get an LFN character */ if (!w) break; /* Break on end of the LFN */ @@ -2955,7 +2954,7 @@ FRESULT find_volume ( /* FR_OK(0): successful, !=0: any error occurred */ UINT i; - /* Get logical drive number from the path name */ + /* Get logical drive number */ *rfs = 0; vol = get_ldnumber(path); if (vol < 0) return FR_INVALID_DRIVE; @@ -2967,7 +2966,7 @@ FRESULT find_volume ( /* FR_OK(0): successful, !=0: any error occurred */ ENTER_FF(fs); /* Lock the volume */ *rfs = fs; /* Return pointer to the file system object */ - mode &= ~FA_READ; /* Desired access mode, write access or not */ + mode &= (BYTE)~FA_READ; /* Desired access mode, write access or not */ if (fs->fs_type) { /* If the volume has been mounted */ stat = disk_status(fs->drv); if (!(stat & STA_NOINIT)) { /* and the physical drive is kept initialized */ @@ -3045,7 +3044,7 @@ FRESULT find_volume ( /* FR_OK(0): successful, !=0: any error occurred */ fs->volbase = bsect; fs->database = bsect + ld_dword(fs->win + BPB_DataOfsEx); fs->fatbase = bsect + ld_dword(fs->win + BPB_FatOfsEx); - if (maxlba < fs->database + nclst * fs->csize) return FR_NO_FILESYSTEM; /* (Volume size must not be smaller than the size requiered) */ + if (maxlba < (QWORD)fs->database + nclst * fs->csize) return FR_NO_FILESYSTEM; /* (Volume size must not be smaller than the size requiered) */ fs->dirbase = ld_dword(fs->win + BPB_RootClusEx); /* Check if bitmap location is in assumption (at the first cluster) */ @@ -3162,15 +3161,14 @@ FRESULT find_volume ( /* FR_OK(0): successful, !=0: any error occurred */ static FRESULT validate ( /* Returns FR_OK or FR_INVALID_OBJECT */ - void* dfp, /* Pointer to the FIL/DIR object to check validity */ + _FDID* obj, /* Pointer to the _OBJ, the 1st member in the FIL/DIR object, to check validity */ FATFS** fs /* Pointer to pointer to the owner file system object to return */ ) { - _FDID *obj = (_FDID*)dfp; /* Assuming .obj in the FIL/DIR is the first member */ FRESULT res; - if (!dfp || !obj->fs || !obj->fs->fs_type || obj->fs->id != obj->id || (disk_status(obj->fs->drv) & STA_NOINIT)) { + if (!obj || !obj->fs || !obj->fs->fs_type || obj->fs->id != obj->id || (disk_status(obj->fs->drv) & STA_NOINIT)) { *fs = 0; /* The object is invalid */ res = FR_INVALID_OBJECT; } else { @@ -3208,6 +3206,7 @@ FRESULT f_mount ( const TCHAR *rp = path; + /* Get logical drive number */ vol = get_ldnumber(&rp); if (vol < 0) return FR_INVALID_DRIVE; cfs = FatFs[vol]; /* Pointer to fs object */ @@ -3261,7 +3260,7 @@ FRESULT f_open ( if (!fp) return FR_INVALID_OBJECT; - /* Get logical drive number */ + /* Get logical drive */ mode &= _FS_READONLY ? FA_READ : FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_CREATE_NEW | FA_OPEN_ALWAYS | FA_OPEN_APPEND | FA_SEEKEND; res = find_volume(&path, &fs, mode); if (res == FR_OK) { @@ -3460,7 +3459,7 @@ FRESULT f_read ( *br = 0; /* Clear read byte counter */ - res = validate(fp, &fs); + res = validate(&fp->obj, &fs); /* Check validity of the file object */ if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); /* Check validity */ if (!(fp->flag & FA_READ)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ remain = fp->obj.objsize - fp->fptr; @@ -3495,9 +3494,7 @@ FRESULT f_read ( if (csect + cc > fs->csize) { /* Clip at cluster boundary */ cc = fs->csize - csect; } - if (disk_read(fs->drv, rbuff, sect, cc) != RES_OK) { - ABORT(fs, FR_DISK_ERR); - } + if (disk_read(fs->drv, rbuff, sect, cc) != RES_OK) ABORT(fs, FR_DISK_ERR); #if !_FS_READONLY && _FS_MINIMIZE <= 2 /* Replace one of the read sectors with cached data if it contains a dirty sector */ #if _FS_TINY if (fs->wflag && fs->winsect - sect < cc) { @@ -3517,12 +3514,10 @@ FRESULT f_read ( #if !_FS_READONLY if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */ if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); - fp->flag &= ~FA_DIRTY; + fp->flag &= (BYTE)~FA_DIRTY; } #endif - if (disk_read(fs->drv, fp->buf, sect, 1) != RES_OK) { /* Fill sector cache */ - ABORT(fs, FR_DISK_ERR); - } + if (disk_read(fs->drv, fp->buf, sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Fill sector cache */ } #endif fp->sect = sect; @@ -3563,7 +3558,7 @@ FRESULT f_write ( *bw = 0; /* Clear write byte counter */ - res = validate(fp, &fs); + res = validate(&fp->obj, &fs); /* Check validity of the file object */ if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); /* Check validity */ if (!(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ @@ -3603,7 +3598,7 @@ FRESULT f_write ( #else if (fp->flag & FA_DIRTY) { /* Write-back sector cache */ if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); - fp->flag &= ~FA_DIRTY; + fp->flag &= (BYTE)~FA_DIRTY; } #endif sect = clust2sect(fs, fp->clust); /* Get current sector */ @@ -3614,9 +3609,7 @@ FRESULT f_write ( if (csect + cc > fs->csize) { /* Clip at cluster boundary */ cc = fs->csize - csect; } - if (disk_write(fs->drv, wbuff, sect, cc) != RES_OK) { - ABORT(fs, FR_DISK_ERR); - } + if (disk_write(fs->drv, wbuff, sect, cc) != RES_OK) ABORT(fs, FR_DISK_ERR); #if _FS_MINIMIZE <= 2 #if _FS_TINY if (fs->winsect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */ @@ -3626,7 +3619,7 @@ FRESULT f_write ( #else if (fp->sect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */ mem_cpy(fp->buf, wbuff + ((fp->sect - sect) * SS(fs)), SS(fs)); - fp->flag &= ~FA_DIRTY; + fp->flag &= (BYTE)~FA_DIRTY; } #endif #endif @@ -3634,16 +3627,15 @@ FRESULT f_write ( continue; } #if _FS_TINY - if (fp->fptr >= fp->obj.objsize) { /* Avoid silly cache filling at growing edge */ + if (fp->fptr >= fp->obj.objsize) { /* Avoid silly cache filling on the growing edge */ if (sync_window(fs) != FR_OK) ABORT(fs, FR_DISK_ERR); fs->winsect = sect; } #else - if (fp->sect != sect) { /* Fill sector cache with file data */ - if (fp->fptr < fp->obj.objsize && - disk_read(fs->drv, fp->buf, sect, 1) != RES_OK) { - ABORT(fs, FR_DISK_ERR); - } + if (fp->sect != sect && /* Fill sector cache with file data */ + fp->fptr < fp->obj.objsize && + disk_read(fs->drv, fp->buf, sect, 1) != RES_OK) { + ABORT(fs, FR_DISK_ERR); } #endif fp->sect = sect; @@ -3660,7 +3652,7 @@ FRESULT f_write ( #endif } - fp->flag |= FA_MODIFIED; /* Set file change flag */ + fp->flag |= FA_MODIFIED; /* Set file change flag */ LEAVE_FF(fs, FR_OK); } @@ -3680,17 +3672,16 @@ FRESULT f_sync ( FATFS *fs; DWORD tm; BYTE *dir; -#if _FS_EXFAT DEF_NAMBUF -#endif - res = validate(fp, &fs); /* Check validity of the object */ + + res = validate(&fp->obj, &fs); /* Check validity of the file object */ if (res == FR_OK) { if (fp->flag & FA_MODIFIED) { /* Is there any change to the file? */ #if !_FS_TINY if (fp->flag & FA_DIRTY) { /* Write-back cached data if needed */ if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) LEAVE_FF(fs, FR_DISK_ERR); - fp->flag &= ~FA_DIRTY; + fp->flag &= (BYTE)~FA_DIRTY; } #endif /* Update the directory entry */ @@ -3715,7 +3706,7 @@ FRESULT f_sync ( res = store_xdir(&dj); /* Restore it to the directory */ if (res == FR_OK) { res = sync_fs(fs); - fp->flag &= ~FA_MODIFIED; + fp->flag &= (BYTE)~FA_MODIFIED; } } FREE_NAMBUF(); @@ -3733,7 +3724,7 @@ FRESULT f_sync ( st_word(dir + DIR_LstAccDate, 0); fs->wflag = 1; res = sync_fs(fs); /* Restore it to the directory */ - fp->flag &= ~FA_MODIFIED; + fp->flag &= (BYTE)~FA_MODIFIED; } } } @@ -3763,7 +3754,7 @@ FRESULT f_close ( if (res == FR_OK) #endif { - res = validate(fp, &fs); /* Lock volume */ + res = validate(&fp->obj, &fs); /* Lock volume */ if (res == FR_OK) { #if _FS_LOCK != 0 res = dec_lock(fp->obj.lockid); /* Decrement file open counter */ @@ -3796,10 +3787,11 @@ FRESULT f_chdrive ( int vol; + /* Get logical drive number */ vol = get_ldnumber(&path); if (vol < 0) return FR_INVALID_DRIVE; - CurrVol = (BYTE)vol; + CurrVol = (BYTE)vol; /* Set it as current volume */ return FR_OK; } @@ -3815,7 +3807,7 @@ FRESULT f_chdir ( FATFS *fs; DEF_NAMBUF - /* Get logical drive number */ + /* Get logical drive */ res = find_volume(&path, &fs, 0); if (res == FR_OK) { dj.obj.fs = fs; @@ -3874,7 +3866,7 @@ FRESULT f_getcwd ( *buff = 0; - /* Get logical drive number */ + /* Get logical drive */ res = find_volume((const TCHAR**)&buff, &fs, 0); /* Get current volume */ if (res == FR_OK) { dj.obj.fs = fs; @@ -3951,7 +3943,7 @@ FRESULT f_lseek ( DWORD cl, pcl, ncl, tcl, dsc, tlen, ulen, *tbl; #endif - res = validate(fp, &fs); /* Check validity of the object */ + res = validate(&fp->obj, &fs); /* Check validity of the file object */ if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); /* Check validity */ #if _USE_FASTSEEK if (fp->cltbl) { /* Fast seek */ @@ -3993,12 +3985,10 @@ FRESULT f_lseek ( #if !_FS_READONLY if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */ if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); - fp->flag &= ~FA_DIRTY; + fp->flag &= (BYTE)~FA_DIRTY; } #endif - if (disk_read(fs->drv, fp->buf, dsc, 1) != RES_OK) { /* Load current sector */ - ABORT(fs, FR_DISK_ERR); - } + if (disk_read(fs->drv, fp->buf, dsc, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Load current sector */ #endif fp->sect = dsc; } @@ -4021,7 +4011,7 @@ FRESULT f_lseek ( bcs = (DWORD)fs->csize * SS(fs); /* Cluster size (byte) */ if (ifptr > 0 && (ofs - 1) / bcs >= (ifptr - 1) / bcs) { /* When seek to same or following cluster, */ - fp->fptr = (ifptr - 1) & ~(bcs - 1); /* start from the current cluster */ + fp->fptr = (ifptr - 1) & ~(FSIZE_t)(bcs - 1); /* start from the current cluster */ ofs -= fp->fptr; clst = fp->clust; } else { /* When seek to back cluster, */ @@ -4045,13 +4035,15 @@ FRESULT f_lseek ( fp->obj.objsize = fp->fptr; fp->flag |= FA_MODIFIED; } - clst = create_chain(&fp->obj, clst); /* Force stretch if in write mode */ - if (clst == 0) { /* When disk gets full, clip file size */ + clst = create_chain(&fp->obj, clst); /* Follow chain with forceed stretch */ + if (clst == 0) { /* Clip file size in case of disk full */ ofs = 0; break; } } else #endif + { clst = get_fat(&fp->obj, clst); /* Follow cluster chain if not in write mode */ + } if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR); if (clst <= 1 || clst >= fs->n_fatent) ABORT(fs, FR_INT_ERR); fp->clust = clst; @@ -4064,26 +4056,22 @@ FRESULT f_lseek ( } } } + if (!_FS_READONLY && fp->fptr > fp->obj.objsize) { /* Set file change flag if the file size is extended */ + fp->obj.objsize = fp->fptr; + fp->flag |= FA_MODIFIED; + } if (fp->fptr % SS(fs) && nsect != fp->sect) { /* Fill sector cache if needed */ #if !_FS_TINY #if !_FS_READONLY if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */ if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); - fp->flag &= ~FA_DIRTY; + fp->flag &= (BYTE)~FA_DIRTY; } #endif - if (disk_read(fs->drv, fp->buf, nsect, 1) != RES_OK) { /* Fill sector cache */ - ABORT(fs, FR_DISK_ERR); - } + if (disk_read(fs->drv, fp->buf, nsect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Fill sector cache */ #endif fp->sect = nsect; } -#if !_FS_READONLY - if (fp->fptr > fp->obj.objsize) { /* Set file change flag if the file size is extended */ - fp->obj.objsize = fp->fptr; - fp->flag |= FA_MODIFIED; - } -#endif } LEAVE_FF(fs, res); @@ -4109,7 +4097,7 @@ FRESULT f_opendir ( if (!dp) return FR_INVALID_OBJECT; - /* Get logical drive number */ + /* Get logical drive */ obj = &dp->obj; res = find_volume(&path, &fs, 0); if (res == FR_OK) { @@ -4174,7 +4162,7 @@ FRESULT f_closedir ( FATFS *fs; - res = validate(dp, &fs); + res = validate(&dp->obj, &fs); /* Check validity of the file object */ if (res == FR_OK) { #if _FS_LOCK != 0 if (dp->obj.lockid) { /* Decrement sub-directory open counter */ @@ -4209,7 +4197,7 @@ FRESULT f_readdir ( DEF_NAMBUF - res = validate(dp, &fs); /* Check validity of the object */ + res = validate(&dp->obj, &fs); /* Check validity of the directory object */ if (res == FR_OK) { if (!fno) { res = dir_sdi(dp, 0); /* Rewind the directory object */ @@ -4297,7 +4285,7 @@ FRESULT f_stat ( DEF_NAMBUF - /* Get logical drive number */ + /* Get logical drive */ res = find_volume(&path, &dj.obj.fs, 0); if (res == FR_OK) { INIT_NAMBUF(dj.obj.fs); @@ -4336,7 +4324,7 @@ FRESULT f_getfree ( _FDID obj; - /* Get logical drive number */ + /* Get logical drive */ res = find_volume(&path, &fs, 0); if (res == FR_OK) { *fatfs = fs; /* Return ptr to the fs object */ @@ -4418,8 +4406,8 @@ FRESULT f_truncate ( DWORD ncl; - res = validate(fp, &fs); /* Check validity of the object */ - if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); /* Check validity */ + res = validate(&fp->obj, &fs); /* Check validity of the file object */ + if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); if (!(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ if (fp->obj.objsize > fp->fptr) { @@ -4442,7 +4430,7 @@ FRESULT f_truncate ( if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) { res = FR_DISK_ERR; } else { - fp->flag &= ~FA_DIRTY; + fp->flag &= (BYTE)~FA_DIRTY; } } #endif @@ -4473,7 +4461,7 @@ FRESULT f_unlink ( DEF_NAMBUF - /* Get logical drive number */ + /* Get logical drive */ res = find_volume(&path, &fs, FA_WRITE); dj.obj.fs = fs; if (res == FR_OK) { @@ -4567,7 +4555,7 @@ FRESULT f_mkdir ( DEF_NAMBUF - /* Get logical drive number */ + /* Get logical drive */ res = find_volume(&path, &fs, FA_WRITE); dj.obj.fs = fs; if (res == FR_OK) { @@ -4661,7 +4649,7 @@ FRESULT f_rename ( get_ldnumber(&path_new); /* Ignore drive number of new name */ - res = find_volume(&path_old, &fs, FA_WRITE); /* Get logical drive number of the old object */ + res = find_volume(&path_old, &fs, FA_WRITE); /* Get logical drive of the old object */ if (res == FR_OK) { djo.obj.fs = fs; INIT_NAMBUF(fs); @@ -4678,10 +4666,12 @@ FRESULT f_rename ( mem_cpy(buf, fs->dirbuf, SZDIRE * 2); /* Save 85+C0 entry of old object */ mem_cpy(&djn, &djo, sizeof djo); - res = follow_path(&djn, path_new); /* Make sure if new object name is not in use */ - if (res == FR_OK) res = FR_EXIST; /* Is new name already in use? */ - if (res == FR_NO_FILE) { /* It is a valid path and no name collision */ - res = dir_register(&djn); /* Register the new entry */ + res = follow_path(&djn, path_new); /* Make sure if new object name is not in use */ + if (res == FR_OK) { /* Is new name already in use by any other object? */ + res = (djn.obj.sclust == djo.obj.sclust && djn.dptr == djo.dptr) ? FR_NO_FILE : FR_EXIST; + } + if (res == FR_NO_FILE) { /* It is a valid path and no name collision */ + res = dir_register(&djn); /* Register the new entry */ if (res == FR_OK) { nf = fs->dirbuf[XDIR_NumSec]; nn = fs->dirbuf[XDIR_NumName]; nh = ld_word(fs->dirbuf + XDIR_NameHash); @@ -4698,7 +4688,9 @@ FRESULT f_rename ( mem_cpy(buf, djo.dir + DIR_Attr, 21); /* Save information about the object except name */ mem_cpy(&djn, &djo, sizeof (DIR)); /* Duplicate the directory object */ res = follow_path(&djn, path_new); /* Make sure if new object name is not in use */ - if (res == FR_OK) res = FR_EXIST; /* Is new name already in use? */ + if (res == FR_OK) { /* Is new name already in use by any other object? */ + res = (djn.obj.sclust == djo.obj.sclust && djn.dptr == djo.dptr) ? FR_NO_FILE : FR_EXIST; + } if (res == FR_NO_FILE) { /* It is a valid path and no name collision */ res = dir_register(&djn); /* Register the new entry */ if (res == FR_OK) { @@ -4761,7 +4753,7 @@ FRESULT f_chmod ( DEF_NAMBUF - res = find_volume(&path, &fs, FA_WRITE); /* Get logical drive number */ + res = find_volume(&path, &fs, FA_WRITE); /* Get logical drive */ dj.obj.fs = fs; if (res == FR_OK) { INIT_NAMBUF(fs); @@ -4805,7 +4797,7 @@ FRESULT f_utime ( DEF_NAMBUF - res = find_volume(&path, &fs, FA_WRITE); /* Get logical drive number */ + res = find_volume(&path, &fs, FA_WRITE); /* Get logical drive */ dj.obj.fs = fs; if (res == FR_OK) { INIT_NAMBUF(fs); @@ -4853,7 +4845,7 @@ FRESULT f_getlabel ( WCHAR w; #endif - /* Get logical drive number */ + /* Get logical drive */ res = find_volume(&path, &fs, 0); /* Get volume label */ @@ -4941,7 +4933,7 @@ FRESULT f_setlabel ( static const char badchr[] = "\"*+,.:;<=>\?[]|\x7F"; - /* Get logical drive number */ + /* Get logical drive */ res = find_volume(&label, &fs, FA_WRITE); if (res != FR_OK) LEAVE_FF(fs, res); dj.obj.fs = fs; @@ -4950,7 +4942,7 @@ FRESULT f_setlabel ( for (slen = 0; (UINT)label[slen] >= ' '; slen++) ; /* Get name length */ #if _FS_EXFAT - if (fs->fs_type == FS_EXFAT) { /* At the exFAT */ + if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ for (i = j = 0; i < slen; ) { /* Create volume label in directory form */ w = label[i++]; #if !_LFN_UNICODE @@ -4967,7 +4959,7 @@ FRESULT f_setlabel ( slen = j; } else #endif - { /* At the FAT12/16/32 */ + { /* On the FAT12/16/32 volume */ for ( ; slen && label[slen - 1] == ' '; slen--) ; /* Remove trailing spaces */ if (slen) { /* Is there a volume label to be set? */ dirvn[0] = 0; i = j = 0; /* Create volume label in directory form */ @@ -5008,7 +5000,7 @@ FRESULT f_setlabel ( res = dir_read(&dj, 1); /* Get volume label entry */ if (res == FR_OK) { if (_FS_EXFAT && fs->fs_type == FS_EXFAT) { - dj.dir[XDIR_NumLabel] = slen / 2; /* Change the volume label */ + dj.dir[XDIR_NumLabel] = (BYTE)(slen / 2); /* Change the volume label */ mem_cpy(dj.dir + XDIR_Label, dirvn, slen); } else { if (slen) { @@ -5028,7 +5020,7 @@ FRESULT f_setlabel ( mem_set(dj.dir, 0, SZDIRE); /* Clear the entry */ if (_FS_EXFAT && fs->fs_type == FS_EXFAT) { dj.dir[XDIR_Type] = 0x83; /* Create 83 entry */ - dj.dir[XDIR_NumLabel] = slen / 2; + dj.dir[XDIR_NumLabel] = (BYTE)(slen / 2); mem_cpy(dj.dir + XDIR_Label, dirvn, slen); } else { dj.dir[DIR_Attr] = AM_VOL; /* Create volume label entry */ @@ -5066,8 +5058,8 @@ FRESULT f_expand ( DWORD n, clst, stcl, scl, ncl, tcl, lclst; - res = validate(fp, &fs); /* Check validity of the object */ - if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); /* Check validity */ + res = validate(&fp->obj, &fs); /* Check validity of the file object */ + if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); if (fsz == 0 || fp->obj.objsize != 0 || !(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED); #if _FS_EXFAT if (fs->fs_type != FS_EXFAT && fsz >= 0x100000000) LEAVE_FF(fs, FR_DENIED); /* Check if in size limit */ @@ -5161,8 +5153,8 @@ FRESULT f_forward ( *bf = 0; /* Clear transfer byte counter */ - res = validate(fp, &fs); /* Check validity of the object */ - if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); /* Check validity */ + res = validate(&fp->obj, &fs); /* Check validity of the file object */ + if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); if (!(fp->flag & FA_READ)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ remain = fp->obj.objsize - fp->fptr; @@ -5191,7 +5183,7 @@ FRESULT f_forward ( #if !_FS_READONLY if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */ if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); - fp->flag &= ~FA_DIRTY; + fp->flag &= (BYTE)~FA_DIRTY; } #endif if (disk_read(fs->drv, fp->buf, sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); @@ -5226,14 +5218,14 @@ FRESULT f_mkfs ( { const UINT n_fats = 1; /* Number of FATs for FAT12/16/32 volume (1 or 2) */ const UINT n_rootdir = 512; /* Number of root directory entries for FAT12/16 volume */ - static const WORD cst[] = {1, 4, 16, 64, 256, 512, 0}; /* Cluster size boundary for FAT12/16 volume (4KS unit) */ - static const WORD cst32[] = {1, 2, 4, 8, 16, 32, 0}; /* Cluster size boundary for FAT32 volume (128KS unit) */ + static const WORD cst[] = {1, 4, 16, 64, 256, 512, 0}; /* Cluster size boundary for FAT12/16 volume (4Ks unit) */ + static const WORD cst32[] = {1, 2, 4, 8, 16, 32, 0}; /* Cluster size boundary for FAT32 volume (128Ks unit) */ BYTE fmt, sys, *buf, *pte, pdrv, part; WORD ss; - DWORD n, pau, n_clst, sz_blk, sect, szb_buf, sz_buf; + DWORD szb_buf, sz_buf, sz_blk, n_clst, pau, sect, nsect, n; DWORD b_vol, b_fat, b_data; /* Base LBA for volume, fat, data */ DWORD sz_vol, sz_rsv, sz_fat, sz_dir; /* Size for volume, fat, dir, data */ - UINT i, ns; + UINT i; int vol; DSTATUS stat; #if _USE_TRIM || _FS_EXFAT @@ -5246,34 +5238,33 @@ FRESULT f_mkfs ( if (vol < 0) return FR_INVALID_DRIVE; if (FatFs[vol]) FatFs[vol]->fs_type = 0; /* Clear mounted volume */ pdrv = LD2PD(vol); /* Physical drive */ - part = LD2PT(vol); /* Partition (0:create as new, 1-4:get by partition table) */ + part = LD2PT(vol); /* Partition (0:create as new, 1-4:get from partition table) */ /* Check physical drive status */ stat = disk_initialize(pdrv); if (stat & STA_NOINIT) return FR_NOT_READY; if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; - if (disk_ioctl(pdrv, GET_BLOCK_SIZE, &sz_blk) != RES_OK || !sz_blk || sz_blk > 32768 || (sz_blk & (sz_blk - 1))) sz_blk = 1; + if (disk_ioctl(pdrv, GET_BLOCK_SIZE, &sz_blk) != RES_OK || !sz_blk || sz_blk > 32768 || (sz_blk & (sz_blk - 1))) sz_blk = 1; /* Erase block to align data area */ #if _MAX_SS != _MIN_SS /* Get sector size of the medium */ if (disk_ioctl(pdrv, GET_SECTOR_SIZE, &ss) != RES_OK) return FR_DISK_ERR; if (ss > _MAX_SS || ss < _MIN_SS || (ss & (ss - 1))) return FR_DISK_ERR; #else ss = _MAX_SS; #endif - if ((au != 0 && au < ss) || (au & (au - 1))) return FR_INVALID_PARAMETER; /* Check if au is valid */ - au /= ss; /* Cluster size in byte to in sector */ - if (au > 32768) return FR_INVALID_PARAMETER; + if ((au != 0 && au < ss) || au > 0x1000000 || (au & (au - 1))) return FR_INVALID_PARAMETER; /* Check if au is valid */ + au /= ss; /* Cluster size in unit of sector */ - /* Set size and pointer of the working buffer */ - buf = (BYTE*)work; /* Use given working buffer */ - if (len < ss) return FR_MKFS_ABORTED; - szb_buf = len & ~(ss - 1); /* Round-down by sector size [byte] */ - sz_buf = szb_buf / ss; /* Size of sector buffer [sector] */ + /* Get working buffer */ + buf = (BYTE*)work; /* Working buffer */ + sz_buf = len / ss; /* Size of working buffer (sector) */ + szb_buf = sz_buf * ss; /* Size of working buffer (byte) */ + if (!szb_buf) return FR_MKFS_ABORTED; /* Determine where the volume to be located (b_vol, sz_vol) */ if (_MULTI_PARTITION && part != 0) { /* Get partition information from partition table in the MBR */ if (disk_read(pdrv, buf, 0, 1) != RES_OK) return FR_DISK_ERR; /* Load MBR */ - if (ld_word(buf + BS_55AA) != 0xAA55) return FR_MKFS_ABORTED; /* Check MBR is valid */ + if (ld_word(buf + BS_55AA) != 0xAA55) return FR_MKFS_ABORTED; /* Check if MBR is valid */ pte = buf + (MBR_Table + (part - 1) * SZ_PTE); if (!pte[PTE_System]) return FR_MKFS_ABORTED; /* No partition? */ b_vol = ld_dword(pte + PTE_StLba); /* Get volume start sector */ @@ -5285,16 +5276,16 @@ FRESULT f_mkfs ( if (sz_vol < b_vol) return FR_MKFS_ABORTED; sz_vol -= b_vol; /* Volume size */ } - if (sz_vol < 128) return FR_MKFS_ABORTED; /* Check volume size (>=128s) */ + if (sz_vol < 128) return FR_MKFS_ABORTED; /* Check if volume size is >=128s */ - /* Pre-determine the FAT type by argument */ + /* Pre-determine the FAT type */ do { if (_FS_EXFAT && (opt & FM_EXFAT)) { /* exFAT possible? */ - if ((opt & FM_ANY) == FM_EXFAT || sz_vol >= 0x4000000 || au >= 256) { /* exFAT only, vol >= 64Ms or au >= 256s ? */ + if ((opt & FM_ANY) == FM_EXFAT || sz_vol >= 0x4000000 || au > 128) { /* exFAT only, vol >= 64Ms or au > 128s ? */ fmt = FS_EXFAT; break; } } - if (au >= 256) return FR_INVALID_PARAMETER; /* Too large au for FAT/FAT32 */ + if (au > 128) return FR_INVALID_PARAMETER; /* Too large au for FAT/FAT32 */ if (opt & FM_FAT32) { /* FAT32 possible? */ if ((opt & FM_ANY) == FM_FAT32 || !(opt & FM_FAT)) { /* FAT32 only or no-FAT? */ fmt = FS_FAT32; break; @@ -5319,20 +5310,19 @@ FRESULT f_mkfs ( /* Determine FAT location, data location and number of clusters */ if (!au) { /* au auto-selection */ au = 8; - if (sz_vol >= 0x80000) au = 64; /* >= 512KS */ - if (sz_vol >= 0x4000000) au = 256; /* >= 64MS */ + if (sz_vol >= 0x80000) au = 64; /* >= 512Ks */ + if (sz_vol >= 0x4000000) au = 256; /* >= 64Ms */ } b_fat = b_vol + 32; /* FAT start at offset 32 */ - sz_fat = ((sz_vol / au + 2) * 4 + ss - 1) / ss; /* Numbef of FAT sectors */ + sz_fat = ((sz_vol / au + 2) * 4 + ss - 1) / ss; /* Number of FAT sectors */ b_data = (b_fat + sz_fat + sz_blk - 1) & ~(sz_blk - 1); /* Align data area to the erase block boundary */ if (b_data >= sz_vol / 2) return FR_MKFS_ABORTED; /* Too small volume? */ - n_clst = (sz_vol - (b_data - b_vol)) / au; /* Nunber of clusters */ + n_clst = (sz_vol - (b_data - b_vol)) / au; /* Number of clusters */ if (n_clst <16) return FR_MKFS_ABORTED; /* Too few clusters? */ if (n_clst > MAX_EXFAT) return FR_MKFS_ABORTED; /* Too many clusters? */ - szb_bit = (n_clst + 7) / 8; /* Size of allocation bitmap */ - tbl[0] = (szb_bit + au * ss - 1) / (au * ss); /* Number of bitmap clusters */ - tbl[2] = 1; /* Number of rootdir clusters */ + szb_bit = (n_clst + 7) / 8; /* Size of allocation bitmap */ + tbl[0] = (szb_bit + au * ss - 1) / (au * ss); /* Number of allocation bitmap clusters */ /* Create a compressed up-case table */ sect = b_data + au * tbl[0]; /* Table start sector */ @@ -5363,30 +5353,31 @@ FRESULT f_mkfs ( sum = xsum32(buf[i + 1] = (BYTE)(ch >> 8), sum); i += 2; szb_case += 2; if (!si || i == szb_buf) { /* Write buffered data when buffer full or end of process */ - ns = (i + ss - 1) / ss; - if (disk_write(pdrv, buf, sect, ns) != RES_OK) return FR_DISK_ERR; - sect += ns; i = 0; + n = (i + ss - 1) / ss; + if (disk_write(pdrv, buf, sect, n) != RES_OK) return FR_DISK_ERR; + sect += n; i = 0; } } while (si); - tbl[1] = (szb_case + au * ss - 1) / (au * ss); /* Number of up-case clusters */ + tbl[1] = (szb_case + au * ss - 1) / (au * ss); /* Number of up-case table clusters */ + tbl[2] = 1; /* Number of root dir clusters */ /* Initialize the allocation bitmap */ - sect = b_data; n = (szb_bit + ss - 1) / ss; /* Start of bitmap and number of the sectors */ + sect = b_data; nsect = (szb_bit + ss - 1) / ss; /* Start of bitmap and number of sectors */ nb = tbl[0] + tbl[1] + tbl[2]; /* Number of clusters in-use by system */ do { mem_set(buf, 0, szb_buf); for (i = 0; nb >= 8 && i < szb_buf; buf[i++] = 0xFF, nb -= 8) ; for (b = 1; nb && i < szb_buf; buf[i] |= b, b <<= 1, nb--) ; - ns = (n > sz_buf) ? sz_buf : n; /* Write the buffered data */ - if (disk_write(pdrv, buf, sect, ns) != RES_OK) return FR_DISK_ERR; - sect += ns; n -= ns; - } while (n); + n = (nsect > sz_buf) ? sz_buf : nsect; /* Write the buffered data */ + if (disk_write(pdrv, buf, sect, n) != RES_OK) return FR_DISK_ERR; + sect += n; nsect -= n; + } while (nsect); /* Initialize the FAT */ - sect = b_fat; n = sz_fat; /* Start of FAT and number of the sectors */ + sect = b_fat; nsect = sz_fat; /* Start of FAT and number of FAT sectors */ j = nb = cl = 0; do { - mem_set(buf, 0, szb_buf); i = 0; + mem_set(buf, 0, szb_buf); i = 0; /* Clear work area and reset write index */ if (cl == 0) { /* Set entry 0 and 1 */ st_dword(buf + i, 0xFFFFFFF8); i += 4; cl++; st_dword(buf + i, 0xFFFFFFFF); i += 4; cl++; @@ -5398,13 +5389,13 @@ FRESULT f_mkfs ( } if (!nb && j < 3) nb = tbl[j++]; /* Next chain */ } while (nb && i < szb_buf); - ns = (n > sz_buf) ? sz_buf : n; /* Write the buffered data */ - if (disk_write(pdrv, buf, sect, ns) != RES_OK) return FR_DISK_ERR; - sect += ns; n -= ns; - } while (n); + n = (nsect > sz_buf) ? sz_buf : nsect; /* Write the buffered data */ + if (disk_write(pdrv, buf, sect, n) != RES_OK) return FR_DISK_ERR; + sect += n; nsect -= n; + } while (nsect); /* Initialize the root directory */ - mem_set(buf, 0, ss); + mem_set(buf, 0, szb_buf); buf[SZDIRE * 0 + 0] = 0x83; /* 83 entry (volume label) */ buf[SZDIRE * 1 + 0] = 0x81; /* 81 entry (allocation bitmap) */ st_dword(buf + SZDIRE * 1 + 20, 2); @@ -5413,13 +5404,13 @@ FRESULT f_mkfs ( st_dword(buf + SZDIRE * 2 + 4, sum); st_dword(buf + SZDIRE * 2 + 20, 2 + tbl[0]); st_dword(buf + SZDIRE * 2 + 24, szb_case); - sect = b_data + au * (tbl[0] + tbl[1]); n = au; /* Start of directory and number of the sectors */ - do { /* Fill root direcotry sectors */ - ns = (n > sz_buf) ? sz_buf : n; - if (disk_write(pdrv, buf, sect, ns) != RES_OK) return FR_DISK_ERR; - sect += ns; + sect = b_data + au * (tbl[0] + tbl[1]); nsect = au; /* Start of the root directory and number of sectors */ + do { /* Fill root directory sectors */ + n = (nsect > sz_buf) ? sz_buf : nsect; + if (disk_write(pdrv, buf, sect, n) != RES_OK) return FR_DISK_ERR; mem_set(buf, 0, ss); - } while (n -= ns); + sect += n; nsect -= n; + } while (nsect); /* Create two set of the exFAT VBR blocks */ sect = b_vol; @@ -5465,7 +5456,7 @@ FRESULT f_mkfs ( } } else -#endif +#endif /* _FS_EXFAT */ { /* Create an FAT12/16/32 volume */ do { pau = au; @@ -5548,14 +5539,14 @@ FRESULT f_mkfs ( st_word(buf + BPB_BytsPerSec, ss); /* Sector size [byte] */ buf[BPB_SecPerClus] = (BYTE)pau; /* Cluster size [sector] */ st_word(buf + BPB_RsvdSecCnt, (WORD)sz_rsv); /* Size of reserved area */ - buf[BPB_NumFATs] = n_fats; /* Number of FATs */ + buf[BPB_NumFATs] = (BYTE)n_fats; /* Number of FATs */ st_word(buf + BPB_RootEntCnt, (WORD)((fmt == FS_FAT32) ? 0 : n_rootdir)); /* Number of root directory entries */ if (sz_vol < 0x10000) { st_word(buf + BPB_TotSec16, (WORD)sz_vol); /* Volume size in 16-bit LBA */ } else { - st_dword(buf + BPB_TotSec32, sz_vol); /* Volume size in 12-bit LBA */ + st_dword(buf + BPB_TotSec32, sz_vol); /* Volume size in 32-bit LBA */ } - buf[BPB_Media] = 0xF8; /* Media descriptor */ + buf[BPB_Media] = 0xF8; /* Media descriptor byte */ st_word(buf + BPB_SecPerTrk, 63); /* Number of sectors per track (for int13) */ st_word(buf + BPB_NumHeads, 255); /* Number of heads (for int13) */ st_dword(buf + BPB_HiddSec, b_vol); /* Volume offset in the physical drive [sector] */ @@ -5592,8 +5583,8 @@ FRESULT f_mkfs ( } /* Initialize FAT area */ - mem_set(buf, 0, szb_buf); - sect = b_fat; /* Start sector */ + mem_set(buf, 0, (UINT)szb_buf); + sect = b_fat; /* FAT start sector */ for (i = 0; i < n_fats; i++) { /* Initialize FATs each */ if (fmt == FS_FAT32) { st_dword(buf + 0, 0xFFFFFFF8); /* Entry 0 */ @@ -5602,22 +5593,22 @@ FRESULT f_mkfs ( } else { st_dword(buf + 0, (fmt == FS_FAT12) ? 0xFFFFF8 : 0xFFFFFFF8); /* Entry 0 and 1 */ } - n = sz_fat; /* Sector count of a FAT */ + nsect = sz_fat; /* Number of FAT sectors */ do { /* Fill FAT sectors */ - ns = (n > sz_buf) ? sz_buf : n; - if (disk_write(pdrv, buf, sect, ns) != RES_OK) return FR_DISK_ERR; - sect += ns; + n = (nsect > sz_buf) ? sz_buf : nsect; + if (disk_write(pdrv, buf, sect, (UINT)n) != RES_OK) return FR_DISK_ERR; mem_set(buf, 0, ss); - } while (n -= ns); + sect += n; nsect -= n; + } while (nsect); } /* Initialize root directory (fill with zero) */ - n = (fmt == FS_FAT32) ? pau : sz_dir; /* Sector count of root directory */ + nsect = (fmt == FS_FAT32) ? pau : sz_dir; /* Number of root directory sectors */ do { - ns = (n > sz_buf) ? sz_buf : n; - if (disk_write(pdrv, buf, sect, ns) != RES_OK) return FR_DISK_ERR; - sect += ns; - } while (n -= ns); + n = (nsect > sz_buf) ? sz_buf : nsect; + if (disk_write(pdrv, buf, sect, (UINT)n) != RES_OK) return FR_DISK_ERR; + sect += n; nsect -= n; + } while (nsect); } /* Determine system ID in the partition table */ diff --git a/firmware/chibios-portapack/ext/fatfs/src/ff.h b/firmware/chibios-portapack/ext/fatfs/src/ff.h index 5984c8eb..981a8863 100644 --- a/firmware/chibios-portapack/ext/fatfs/src/ff.h +++ b/firmware/chibios-portapack/ext/fatfs/src/ff.h @@ -1,5 +1,5 @@ /*----------------------------------------------------------------------------/ -/ FatFs - Generic FAT file system module R0.12a / +/ FatFs - Generic FAT file system module R0.12b / /-----------------------------------------------------------------------------/ / / Copyright (C) 2016, ChaN, all right reserved. @@ -19,7 +19,7 @@ #ifndef _FATFS -#define _FATFS 80186 /* Revision ID */ +#define _FATFS 68020 /* Revision ID */ #ifdef __cplusplus extern "C" { @@ -159,7 +159,7 @@ typedef struct { /* File object structure (FIL) */ typedef struct { - _FDID obj; /* Object identifier */ + _FDID obj; /* Object identifier (must be the 1st member to detect invalid object pointer) */ BYTE flag; /* File status flags */ BYTE err; /* Abort flag (error code) */ FSIZE_t fptr; /* File read/write pointer (Zeroed on file open) */