Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improved storage handling over 4 GB of FAT #45

Merged
merged 1 commit into from
Jun 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions LIMITATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ When using pico-vfs, there are several limitations and behavior specifics that u

## File System Limitations

1. **Multiple Open Instances**: The current implementations of littlefs and FatFs do not support opening the same file multiple times simultaneously[^1][^2]. This limitation can affect scenarios where multiple accesses to the same file are required concurrently.
1. **Max File Size for FAT**: The maximum single file size of a FAT file system depends on the capacity of the storage medium. Check the size of the SD card used and the type of FAT (FAT16/32/ExFat) automatically assigned.

2. **`core1` Usage with Onboard Flash Block Device**: When operating file systems using the onboard flash block device on `core1`, it is necessary to run the operations from RAM[^3].
2. **Multiple Open Instances**: The current implementations of littlefs and FatFs do not support opening the same file multiple times simultaneously[^1][^2]. This limitation can affect scenarios where multiple accesses to the same file are required concurrently.

3. **Memory map IO**: `mmap` system call not supported.
3. **`core1` Usage with Onboard Flash Block Device**: When operating file systems using the onboard flash block device on `core1`, it is necessary to run the operations from RAM[^3].

4. **Memory maped IO**: `mmap` system call not supported.

We recommend reviewing these limitations before designing systems that heavily rely on multicore operations or require high file access availability.

Expand Down
12 changes: 7 additions & 5 deletions include/blockdevice/blockdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ extern "C" {
#include <stdint.h>
#include <stdbool.h>

typedef uint64_t bd_size_t;

enum bd_error {
BD_ERROR_OK = 0, /*!< no error */
BD_ERROR_DEVICE_ERROR = -4001, /*!< device specific error */
Expand All @@ -31,11 +33,11 @@ typedef struct blockdevice {
int (*init)(struct blockdevice *device);
int (*deinit)(struct blockdevice *device);
int (*sync)(struct blockdevice *device);
int (*read)(struct blockdevice *device, const void *buffer, size_t addr, size_t size);
int (*program)(struct blockdevice *device, const void *buffer, size_t addr, size_t size);
int (*erase)(struct blockdevice *device, size_t addr, size_t size);
int (*trim)(struct blockdevice *device, size_t addr, size_t size);
uint64_t (*size)(struct blockdevice *device);
int (*read)(struct blockdevice *device, const void *buffer, bd_size_t addr, bd_size_t size);
int (*program)(struct blockdevice *device, const void *buffer, bd_size_t addr, bd_size_t size);
int (*erase)(struct blockdevice *device, bd_size_t addr, bd_size_t size);
int (*trim)(struct blockdevice *device, bd_size_t addr, bd_size_t size);
bd_size_t (*size)(struct blockdevice *device);
size_t read_size;
size_t erase_size;
size_t program_size;
Expand Down
2 changes: 1 addition & 1 deletion include/filesystem/ChaN/ffconf.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@
/ GET_SECTOR_SIZE command. */


#define FF_LBA64 0
#define FF_LBA64 1
/* This option switches support for 64-bit LBA. (0:Disable or 1:Enable)
/ To enable the 64-bit LBA, also exFAT needs to be enabled. (FF_FS_EXFAT == 1) */

Expand Down
20 changes: 10 additions & 10 deletions src/blockdevice/flash.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,51 +41,51 @@ static int sync(blockdevice_t *device) {
return 0;
}

static int read(blockdevice_t *device, const void *buffer, size_t addr, size_t size) {
static int read(blockdevice_t *device, const void *buffer, bd_size_t addr, bd_size_t size) {
blockdevice_flash_config_t *config = device->config;

mutex_enter_blocking(&config->_mutex);
const uint8_t *flash_contents = (const uint8_t *)(XIP_BASE + flash_target_offset(device) + addr);
memcpy((uint8_t *)buffer, flash_contents, size);
const uint8_t *flash_contents = (const uint8_t *)(XIP_BASE + flash_target_offset(device) + (size_t)addr);
memcpy((uint8_t *)buffer, flash_contents, (size_t)size);
mutex_exit(&config->_mutex);

return BD_ERROR_OK;
}

static int erase(blockdevice_t *device, size_t addr, size_t size) {
static int erase(blockdevice_t *device, bd_size_t addr, bd_size_t size) {
blockdevice_flash_config_t *config = device->config;

mutex_enter_blocking(&config->_mutex);
uint32_t ints = save_and_disable_interrupts();
flash_range_erase(flash_target_offset(device) + addr, size);
flash_range_erase(flash_target_offset(device) + addr, (size_t)size);
restore_interrupts(ints);
mutex_exit(&config->_mutex);

return BD_ERROR_OK;
}

static int program(blockdevice_t *device, const void *buffer, size_t addr, size_t size) {
static int program(blockdevice_t *device, const void *buffer, bd_size_t addr, bd_size_t size) {
blockdevice_flash_config_t *config = device->config;

mutex_enter_blocking(&config->_mutex);
uint32_t ints = save_and_disable_interrupts();
flash_range_program(flash_target_offset(device) + addr, buffer, size);
flash_range_program(flash_target_offset(device) + addr, buffer, (size_t)size);
restore_interrupts(ints);
mutex_exit(&config->_mutex);

return BD_ERROR_OK;
}

static int trim(blockdevice_t *device, size_t addr, size_t size) {
static int trim(blockdevice_t *device, bd_size_t addr, bd_size_t size) {
(void)device;
(void)addr;
(void)size;
return BD_ERROR_OK;
}

static uint64_t size(blockdevice_t *device) {
static bd_size_t size(blockdevice_t *device) {
blockdevice_flash_config_t *config = device->config;
return (uint64_t)config->length;
return (bd_size_t)config->length;
}

blockdevice_t *blockdevice_flash_create(uint32_t start, size_t length) {
Expand Down
18 changes: 9 additions & 9 deletions src/blockdevice/heap.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,47 +94,47 @@ static int sync(blockdevice_t *device) {
return BD_ERROR_OK;
}

static int read(blockdevice_t *device, const void *buffer, size_t addr, size_t length) {
static int read(blockdevice_t *device, const void *buffer, bd_size_t addr, bd_size_t length) {
blockdevice_heap_config_t *config = device->config;
mutex_enter_blocking(&config->_mutex);

memcpy((uint8_t *)buffer, config->heap + addr, length);
memcpy((uint8_t *)buffer, config->heap + (size_t)addr, (size_t)length);

mutex_exit(&config->_mutex);
return BD_ERROR_OK;
}

static int erase(blockdevice_t *device, size_t addr, size_t length) {
static int erase(blockdevice_t *device, bd_size_t addr, bd_size_t length) {
blockdevice_heap_config_t *config = device->config;
mutex_enter_blocking(&config->_mutex);

assert(config->heap != NULL);
memset(config->heap + addr, PICO_VFS_BLOCKDEVICE_HEAP_ERASE_VALUE, length);
memset(config->heap + (size_t)addr, PICO_VFS_BLOCKDEVICE_HEAP_ERASE_VALUE, (size_t)length);

mutex_exit(&config->_mutex);
return BD_ERROR_OK;
}

static int program(blockdevice_t *device, const void *buffer, size_t addr, size_t length) {
static int program(blockdevice_t *device, const void *buffer, bd_size_t addr, bd_size_t length) {
blockdevice_heap_config_t *config = device->config;
mutex_enter_blocking(&config->_mutex);

memcpy(config->heap + addr, buffer, length);
memcpy(config->heap + (size_t)addr, buffer, (size_t)length);

mutex_exit(&config->_mutex);
return BD_ERROR_OK;
}

static int trim(blockdevice_t *device, size_t addr, size_t length) {
static int trim(blockdevice_t *device, bd_size_t addr, bd_size_t length) {
(void)device;
(void)addr;
(void)length;
return BD_ERROR_OK;
}

static uint64_t size(blockdevice_t *device) {
static bd_size_t size(blockdevice_t *device) {
blockdevice_heap_config_t *config = device->config;
return (uint64_t)config->size;
return (bd_size_t)config->size;
}

blockdevice_t *blockdevice_heap_create(size_t length) {
Expand Down
18 changes: 9 additions & 9 deletions src/blockdevice/loopback.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ static int __sync(blockdevice_t *device) {
return BD_ERROR_OK;
}

static int __read(blockdevice_t *device, const void *buffer, size_t addr, size_t length) {
static int __read(blockdevice_t *device, const void *buffer, bd_size_t addr, bd_size_t length) {
blockdevice_loopback_config_t *config = device->config;
mutex_enter_blocking(&config->_mutex);

Expand All @@ -85,12 +85,12 @@ static int __read(blockdevice_t *device, const void *buffer, size_t addr, size_t
return -errno;
}

ssize_t read_size = read(config->fildes, (void *)buffer, length);
ssize_t read_size = read(config->fildes, (void *)buffer, (size_t)length);
if (read_size == -1) {
mutex_exit(&config->_mutex);
return -errno;
}
if ((size_t)read_size < length) {
if ((size_t)read_size < (size_t)length) {
size_t remind = length - read_size;
memset((void *)buffer + read_size, 0, remind);
}
Expand All @@ -99,14 +99,14 @@ static int __read(blockdevice_t *device, const void *buffer, size_t addr, size_t
return BD_ERROR_OK;
}

static int erase(blockdevice_t *device, size_t addr, size_t length) {
static int erase(blockdevice_t *device, bd_size_t addr, bd_size_t length) {
(void)device;
(void)addr;
(void)length;
return BD_ERROR_OK;
}

static int program(blockdevice_t *device, const void *buffer, size_t addr, size_t length) {
static int program(blockdevice_t *device, const void *buffer, bd_size_t addr, bd_size_t length) {
blockdevice_loopback_config_t *config = device->config;
mutex_enter_blocking(&config->_mutex);

Expand All @@ -115,7 +115,7 @@ static int program(blockdevice_t *device, const void *buffer, size_t addr, size_
mutex_exit(&config->_mutex);
return -errno;
}
ssize_t write_size = write(config->fildes, buffer, length);
ssize_t write_size = write(config->fildes, buffer, (size_t)length);
if (write_size == -1) {
mutex_exit(&config->_mutex);
return -errno;
Expand All @@ -125,16 +125,16 @@ static int program(blockdevice_t *device, const void *buffer, size_t addr, size_
return BD_ERROR_OK;
}

static int trim(blockdevice_t *device, size_t addr, size_t length) {
static int trim(blockdevice_t *device, bd_size_t addr, bd_size_t length) {
(void)device;
(void)addr;
(void)length;
return BD_ERROR_OK;
}

static uint64_t size(blockdevice_t *device) {
static bd_size_t size(blockdevice_t *device) {
blockdevice_loopback_config_t *config = device->config;
return (uint64_t)config->capacity;
return (bd_size_t)config->capacity;
}

blockdevice_t *blockdevice_loopback_create(const char *path, size_t capacity, size_t block_size) {
Expand Down
16 changes: 8 additions & 8 deletions src/blockdevice/sd.c
Original file line number Diff line number Diff line change
Expand Up @@ -755,13 +755,13 @@ static int init(blockdevice_t *device) {
return BD_ERROR_OK;
}

static bool is_valid_read(blockdevice_t *device, size_t addr, size_t size) {
static bool is_valid_read(blockdevice_t *device, bd_size_t addr, bd_size_t size) {
return (addr % device->read_size == 0 &&
size % device->read_size == 0 &&
addr + size <= device->size(device));
}

static bool is_valid_program(blockdevice_t *device, size_t addr, size_t size) {
static bool is_valid_program(blockdevice_t *device, bd_size_t addr, bd_size_t size) {
return (addr % device->program_size == 0 &&
size % device->program_size == 0 &&
addr + size <= device->size(device));
Expand Down Expand Up @@ -807,7 +807,7 @@ static int _read(void *_config, uint8_t *buffer, uint32_t length) {
return 0;
}

static int read(blockdevice_t *device, const void *_buffer, size_t addr, size_t size) {
static int read(blockdevice_t *device, const void *_buffer, bd_size_t addr, bd_size_t size) {
blockdevice_sd_config_t *config = device->config;
mutex_enter_blocking(&config->_mutex);

Expand Down Expand Up @@ -895,7 +895,7 @@ static uint8_t _write(void *_config, const uint8_t *buffer, uint8_t token, uint3
}


static int program(blockdevice_t *device, const void *_buffer, size_t addr, size_t size) {
static int program(blockdevice_t *device, const void *_buffer, bd_size_t addr, bd_size_t size) {
blockdevice_sd_config_t *config = device->config;
mutex_enter_blocking(&config->_mutex);

Expand Down Expand Up @@ -970,22 +970,22 @@ static int program(blockdevice_t *device, const void *_buffer, size_t addr, size
return status;
}

static int erase(blockdevice_t *device, size_t addr, size_t size) {
static int erase(blockdevice_t *device, bd_size_t addr, bd_size_t size) {
(void)device;
(void)addr;
(void)size;
return 0;
}

static bool _is_valid_trim(blockdevice_t *device, size_t addr, size_t size) {
static bool _is_valid_trim(blockdevice_t *device, bd_size_t addr, bd_size_t size) {
blockdevice_sd_config_t *config = device->config;

return (addr % config->erase_size == 0 &&
size % config->erase_size == 0 &&
addr + size <= device->size(device));
}

static int trim(blockdevice_t *device, size_t addr, size_t size) {
static int trim(blockdevice_t *device, bd_size_t addr, bd_size_t size) {
blockdevice_sd_config_t *config = device->config;
mutex_enter_blocking(&config->_mutex);

Expand Down Expand Up @@ -1025,7 +1025,7 @@ static int trim(blockdevice_t *device, size_t addr, size_t size) {
return status;
}

static uint64_t size(blockdevice_t *device) {
static bd_size_t size(blockdevice_t *device) {
blockdevice_sd_config_t *config = device->config;
return config->block_size * config->total_sectors;
}
Expand Down
14 changes: 7 additions & 7 deletions src/filesystem/fat.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,17 +113,17 @@ DSTATUS disk_status(BYTE pdrv) {

DRESULT disk_read(BYTE pdrv, BYTE *buff, LBA_t sector, UINT count) {
DWORD ssize = disk_get_sector_size(pdrv);
size_t addr = sector * ssize;
size_t size = count * ssize;
bd_size_t addr = (bd_size_t)sector * ssize;
bd_size_t size = count * ssize;
int err = _ffs[(int)pdrv]->read(_ffs[(int)pdrv], (const void *)buff, addr, size);
return err ? RES_PARERR : RES_OK;
}

DRESULT disk_write(BYTE pdrv, const BYTE *buff, LBA_t sector, UINT count) {
debug_if(FFS_DBG, "disk_write [%d]\n", pdrv);
DWORD ssize = disk_get_sector_size(pdrv);
size_t addr = sector * ssize;
size_t size = count * ssize;
bd_size_t addr = (bd_size_t)sector * ssize;
bd_size_t size = count * ssize;

int err = _ffs[pdrv]->erase(_ffs[pdrv], addr, size);
if (err) {
Expand Down Expand Up @@ -170,8 +170,8 @@ DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff) {
} else {
DWORD *sectors = (DWORD *)buff;
DWORD ssize = disk_get_sector_size(pdrv);
size_t addr = sectors[0] * ssize;
size_t size = (sectors[1] - sectors[0] + 1) * ssize;
bd_size_t addr = (bd_size_t)sectors[0] * ssize;
bd_size_t size = (bd_size_t)(sectors[1] - sectors[0] + 1) * ssize;
int err = _ffs[pdrv]->trim(_ffs[pdrv], addr, size);
return err ? RES_PARERR : RES_OK;
}
Expand Down Expand Up @@ -240,7 +240,7 @@ static int format(filesystem_t *fs, blockdevice_t *device) {
}

// erase first handful of blocks
size_t header = 2 * device->erase_size;
bd_size_t header = 2 * device->erase_size;
int err = device->erase(device, 0, header);
if (err) {
mutex_exit(&context->_mutex_format);
Expand Down
1 change: 1 addition & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pico_enable_stdio_usb(unittests 1)

add_subdirectory(integration)
add_subdirectory(multicore)
add_subdirectory(large_file)

find_program(OPENOCD openocd)
if(OPENOCD)
Expand Down
22 changes: 22 additions & 0 deletions tests/large_file/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
set(CMAKE_BUILD_TYPE Debug)

add_executable(large_file main.c)
target_compile_options(large_file PRIVATE -Werror -Wall -Wextra -Wnull-dereference)
target_link_libraries(large_file PRIVATE
pico_stdlib
blockdevice_sd
filesystem_fat
filesystem_vfs
)
target_link_options(large_file PRIVATE -Wl,--print-memory-usage)
pico_add_extra_outputs(large_file)
pico_enable_stdio_usb(large_file 1)


find_program(OPENOCD openocd)
if(OPENOCD)
add_custom_target(run_large_file
COMMAND ${OPENOCD} -f interface/cmsis-dap.cfg -f target/rp2040.cfg -c "adapter speed 5000" -c "program large_file.elf verify reset exit"
DEPENDS large_file
)
endif()
Loading