Răsfoiți Sursa

fatfs: add option to prefer ext. RAM for internal buffers

Ivan Grokhotkov 7 ani în urmă
părinte
comite
bbeb62547e

+ 12 - 1
components/fatfs/Kconfig

@@ -167,6 +167,17 @@ config FATFS_PER_FILE_CACHE
       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

+ 7 - 0
components/fatfs/src/ffconf.h

@@ -301,4 +301,11 @@
 #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 ---*/

+ 26 - 4
components/fatfs/src/ffsystem.c

@@ -4,12 +4,15 @@
 /*------------------------------------------------------------------------*/
 
 
+#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                                                */
 /*------------------------------------------------------------------------*/
@@ -18,7 +21,27 @@ void* ff_memalloc (	/* Returns pointer to the allocated memory block (null on no
 	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
 }
 
 
@@ -33,7 +56,6 @@ void ff_memfree (
 	free(mblock);	/* Free the memory block with POSIX API */
 }
 
-#endif
 
 
 

+ 7 - 7
components/fatfs/src/vfs_fat.c

@@ -150,11 +150,11 @@ esp_err_t esp_vfs_fat_register(const char* base_path, const char* fat_drive, siz
         .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;
@@ -512,9 +512,9 @@ static int vfs_fat_link(void* ctx, const char* n1, const char* n2)
     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);
@@ -591,7 +591,7 @@ static DIR* vfs_fat_opendir(void* ctx, const char* name)
     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;
@@ -766,7 +766,7 @@ static int vfs_fat_truncate(void* ctx, const char *path, off_t length)
     _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");

+ 2 - 1
components/fatfs/src/vfs_fat_sdmmc.c

@@ -55,6 +55,7 @@ esp_err_t esp_vfs_fat_sdmmc_mount(const char* base_path,
         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;
@@ -113,7 +114,7 @@ esp_err_t esp_vfs_fat_sdmmc_mount(const char* base_path,
             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;

+ 1 - 1
components/fatfs/src/vfs_fat_spiflash.c

@@ -80,7 +80,7 @@ esp_err_t esp_vfs_fat_spiflash_mount(const char* base_path,
             result = ESP_FAIL;
             goto fail;
         }
-        workbuf = malloc(workbuf_size);
+        workbuf = ff_memalloc(workbuf_size);
         if (workbuf == NULL) {
             result = ESP_ERR_NO_MEM;
             goto fail;

+ 1 - 0
tools/unit-test-app/sdkconfig.defaults

@@ -29,3 +29,4 @@ CONFIG_ADC2_DISABLE_DAC=n
 CONFIG_WARN_WRITE_STRINGS=y
 CONFIG_SPI_MASTER_IN_IRAM=y
 CONFIG_SPIRAM_BANKSWITCH_ENABLE=n
+CONFIG_FATFS_ALLOC_EXTRAM_FIRST=y