all open files, size is also equal to _MAX_SS variable. This reduces the
amount of heap used when multiple files are open, but increases the number
of read and write operations which FATFS needs to make.
-
+
+
+config FATFS_ALLOC_PREFER_EXTRAM
+ bool "Perfer external RAM when allocating FATFS buffers"
+ default y
+ depends on SPIRAM_USE_CAPS_ALLOC || SPIRAM_USE_MALLOC
+ help
+ When the option is enabled, internal buffers used by FATFS will be allocated
+ from external RAM. If the allocation from external RAM fails, the buffer will
+ be allocated from the internal RAM.
+ Disable this option if optimizing for performance. Enable this option if
+ optimizing for internal memory size.
endmenu
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
+/* Some memory allocation functions are declared here in addition to ff.h, so that
+ they can be used also by external code when LFN feature is disabled.
+ */
+void* ff_memalloc (UINT msize);
+void* ff_memcalloc (UINT num, UINT size);
+
+
/*--- End of configuration options ---*/
/*------------------------------------------------------------------------*/
+#include <string.h>
#include "ff.h"
+#include "sdkconfig.h"
+#ifdef CONFIG_FATFS_ALLOC_EXTRAM_FIRST
+#include "esp_heap_caps.h"
+#endif
-#if FF_USE_LFN == 3 /* Dynamic memory allocation */
-
/*------------------------------------------------------------------------*/
/* Allocate a memory block */
/*------------------------------------------------------------------------*/
UINT msize /* Number of bytes to allocate */
)
{
- return malloc(msize); /* Allocate a new memory block with POSIX API */
+#ifdef CONFIG_FATFS_ALLOC_EXTRAM_FIRST
+ return heap_caps_malloc_prefer(size, 2, MALLOC_CAP_DEFAULT | MALLOC_CAP_SPIRAM,
+ MALLOC_CAP_DEFAULT | MALLOC_CAP_INTERNAL);
+#else
+ return malloc(msize);
+#endif
+}
+
+/*------------------------------------------------------------------------*/
+/* Allocate and zero out memory block */
+/*------------------------------------------------------------------------*/
+
+
+void* ff_memcalloc (UINT num, UINT size)
+{
+#ifdef CONFIG_FATFS_ALLOC_EXTRAM_FIRST
+ return heap_caps_calloc_prefer(num, size, 2, MALLOC_CAP_DEFAULT | MALLOC_CAP_SPIRAM,
+ MALLOC_CAP_DEFAULT | MALLOC_CAP_INTERNAL);
+#else
+ return calloc(num, size);
+#endif
}
free(mblock); /* Free the memory block with POSIX API */
}
-#endif
.utime_p = &vfs_fat_utime,
};
size_t ctx_size = sizeof(vfs_fat_ctx_t) + max_files * sizeof(FIL);
- vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) calloc(1, ctx_size);
+ vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ff_memcalloc(1, ctx_size);
if (fat_ctx == NULL) {
return ESP_ERR_NO_MEM;
}
- fat_ctx->o_append = malloc(max_files * sizeof(bool));
+ fat_ctx->o_append = ff_memalloc(max_files * sizeof(bool));
if (fat_ctx->o_append == NULL) {
free(fat_ctx);
return ESP_ERR_NO_MEM;
prepend_drive_to_path(fat_ctx, &n1, &n2);
const size_t copy_buf_size = fat_ctx->fs.csize;
FRESULT res;
- FIL* pf1 = calloc(1, sizeof(FIL));
- FIL* pf2 = calloc(1, sizeof(FIL));
- void* buf = malloc(copy_buf_size);
+ FIL* pf1 = ff_memcalloc(1, sizeof(FIL));
+ FIL* pf2 = ff_memcalloc(1, sizeof(FIL));
+ void* buf = ff_memalloc(copy_buf_size);
if (buf == NULL || pf1 == NULL || pf2 == NULL) {
_lock_release(&fat_ctx->lock);
ESP_LOGD(TAG, "alloc failed, pf1=%p, pf2=%p, buf=%p", pf1, pf2, buf);
vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ctx;
_lock_acquire(&fat_ctx->lock);
prepend_drive_to_path(fat_ctx, &name, NULL);
- vfs_fat_dir_t* fat_dir = calloc(1, sizeof(vfs_fat_dir_t));
+ vfs_fat_dir_t* fat_dir = ff_memcalloc(1, sizeof(vfs_fat_dir_t));
if (!fat_dir) {
_lock_release(&fat_ctx->lock);
errno = ENOMEM;
_lock_acquire(&fat_ctx->lock);
prepend_drive_to_path(fat_ctx, &path, NULL);
- file = (FIL*) calloc(1, sizeof(FIL));
+ file = (FIL*) ff_memcalloc(1, sizeof(FIL));
if (file == NULL) {
_lock_release(&fat_ctx->lock);
ESP_LOGD(TAG, "truncate alloc failed");
return ESP_ERR_NO_MEM;
}
esp_err_t err = ESP_OK;
+ // not using ff_memalloc here, as allocation in internal RAM is preferred
s_card = malloc(sizeof(sdmmc_card_t));
if (s_card == NULL) {
err = ESP_ERR_NO_MEM;
goto fail;
}
ESP_LOGW(TAG, "partitioning card");
- workbuf = malloc(workbuf_size);
+ workbuf = ff_memalloc(workbuf_size);
if (workbuf == NULL) {
err = ESP_ERR_NO_MEM;
goto fail;
result = ESP_FAIL;
goto fail;
}
- workbuf = malloc(workbuf_size);
+ workbuf = ff_memalloc(workbuf_size);
if (workbuf == NULL) {
result = ESP_ERR_NO_MEM;
goto fail;
CONFIG_WARN_WRITE_STRINGS=y
CONFIG_SPI_MASTER_IN_IRAM=y
CONFIG_SPIRAM_BANKSWITCH_ENABLE=n
+CONFIG_FATFS_ALLOC_EXTRAM_FIRST=y