FAT_FS SD Card "file open error -2" when file name is longer than 14 characters

nrf52840 DK, nRF Connect SDK 2.3.0 using vsCode, FAT Filesystem Sample Application

Working with the FAT_FS sample code, I am able to communicate with the SD card perfectly fine, as far as I can tell. The call to lsdir() functions as expected. However, when calling fs_open() to open a file to write to on an external SD card, it is returning error code -2 IF the filepath (mount point + filename) is longer than 14 characters. If the filepath is less than 14 characters then it will successfully write data. I thought it might be resolved by enabling CONFIG_FS_FATFS_LFN, however it did not work. See the code below for my example.

What does error code -2 mean? I wasn't able to find a clear answer anywhere. Is it the same as ENOENT, found in /zephyr/lib/libc/minimal/include/errno.h?
If I get a little deeper with the error, it fails in fs.c at line 163, in fs_open.
fs.c (in the code snippet below the failure is at line 33)

/* File operations */
int fs_open(struct fs_file_t *zfp, const char *file_name, fs_mode_t flags)
{
	struct fs_mount_t *mp;
	int rc = -EINVAL;

	if ((file_name == NULL) ||
			(strlen(file_name) <= 1) || (file_name[0] != '/')) {
		LOG_ERR("invalid file name!!");
		return -EINVAL;
	}

	if (zfp->mp != NULL) {
		return -EBUSY;
	}

	rc = fs_get_mnt_point(&mp, file_name, NULL);
	if (rc < 0) {
		LOG_ERR("mount point not found!!");
		return rc;
	}

	if (((mp->flags & FS_MOUNT_FLAG_READ_ONLY) != 0) &&
	    (flags & FS_O_CREATE || flags & FS_O_WRITE)) {
		return -EROFS;
	}

	CHECKIF(mp->fs->open == NULL) {
		return -ENOTSUP;
	}

	zfp->mp = mp;
	rc = mp->fs->open(zfp, file_name, flags);
	if (rc < 0) {
		LOG_ERR("file open error (%d)", rc);
		zfp->mp = NULL;
		return rc;
	}

	/* Copy flags to zfp for use with other fs_ API calls */
	zfp->flags = flags;

	return rc;
}

main.c

#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/storage/disk_access.h>
#include <zephyr/logging/log.h>
#include <zephyr/fs/fs.h>
#include <ff.h>

static FATFS fat_fs;
/* mounting info */
static struct fs_mount_t mp = {
	.type = FS_FATFS,
	.fs_data = &fat_fs,
};

static const char *disk_mount_pt = "/SD:";

void main(void)
{
	mp.mnt_point = disk_mount_pt;

	int res = fs_mount(&mp);

	if (res == FR_OK) {
		printk("Disk mounted.\n");
		lsdir(disk_mount_pt);
	} else {
		printk("Error mounting disk.\n");
	}

	char datatest[] = "1,2,3,4,5,6\n";
	size_t datatest_size = strlen(datatest);

	struct fs_file_t dfile;
	size_t written_size = 0;

	fs_file_t_init(&dfile);

    // This is where the code fails.
	res = fs_open(&dfile, "/SD:/DKlog.txt", FS_O_RDWR | FS_O_APPEND);

	if(res < 0)
		return false;

	written_size = fs_write(&dfile, datatest, datatest_size);

	res = fs_close(&dfile);

	while (1) {
		ret = toggle_leds();
		k_msleep(SLEEP_TIME_MS);
	}
}

Relevant prj.conf settings

CONFIG_DISK_ACCESS=y
CONFIG_FILE_SYSTEM=y
CONFIG_FAT_FILESYSTEM_ELM=y
CONFIG_DISK_DRIVER_SDMMC=y
CONFIG_FS_FATFS_LFN=y
CONFIG_MAIN_STACK_SIZE=4096
CONFIG_SPI=y

Parents
  • Hi,

     

    Here's an example of fatfs with and without FS_FATFS_LFN:

    *** Booting Zephyr OS build v3.2.99-ncs2-5067-gb54c8baeeafb ***
    [00:00:00.249,694] <inf> flashdisk: Initialize device NAND
    [00:00:00.249,694] <inf> flashdisk: offset 0, sector size 512, page size 4096, volume size 1048576
    Area 0 at 0x0 on mx25r6435f@0 for 1048576 bytes
    [00:00:00.250,457] <inf> flashdisk: Initialize device NAND
    [00:00:00.250,457] <inf> flashdisk: offset 0, sector size 512, page size 4096, volume size 1048576
    Mount /NAND:: 0
    /NAND:: bsize = 512 ; frsize = 512 ; blocks = 2008 ; bfree = 2007
    /NAND: opendir: 0
      F 10 LONG_T~1.TXT
    End of files
    [00:00:00.307,952] <inf> main: The device is put in USB mass storage mode.
    
    *** Booting Zephyr OS build v3.2.99-ncs2-5067-gb54c8baeeafb ***
    [00:00:00.252,471] <inf> flashdisk: Initialize device NAND
    [00:00:00.252,471] <inf> flashdisk: offset 0, sector size 512, page size 4096, volume size 1048576
    Area 0 at 0x0 on mx25r6435f@0 for 1048576 bytes
    [00:00:00.253,295] <inf> flashdisk: Initialize device NAND
    [00:00:00.253,295] <inf> flashdisk: offset 0, sector size 512, page size 4096, volume size 1048576
    Mount /NAND:: 0
    /NAND:: bsize = 512 ; frsize = 512 ; blocks = 2008 ; bfree = 2007
    /NAND: opendir: 0
      F 10 long_text_file_name_for_testing_purposes.txt
    End of files
    [00:00:00.310,821] <inf> main: The device is put in USB mass storage mode.

     

    What does error code -2 mean? I wasn't able to find a clear answer anywhere. Is it the same as ENOENT, found in /zephyr/lib/libc/minimal/include/errno.h?
    If I get a little deeper with the error, it fails in fs.c at line 163, in fs_open.
    fs.c (in the code snippet below the failure is at line 33)

    This means that it could not find the file. Is it already present in your fatfs partition?

    I used the sample zephyr/samples/subsys/usb/mass as a basis for my testing.

    I got the same issue if I tried to append to a non-existing file. Once it was created, it worked as expected:

    File not existing:
    
    *** Booting Zephyr OS build v3.2.99-ncs2-5067-gb54c8baeeafb ***
    [00:00:00.251,312] <inf> flashdisk: Initialize device NAND
    [00:00:00.251,312] <inf> flashdisk: offset 0, sector size 512, page size 4096, volume size 1048576
    Area 0 at 0x0 on mx25r6435f@0 for 1048576 bytes
    [00:00:00.252,105] <inf> flashdisk: Initialize device NAND
    [00:00:00.252,136] <inf> flashdisk: offset 0, sector size 512, page size 4096, volume size 1048576
    Mount /NAND:: 0
    /NAND:: bsize = 512 ; frsize = 512 ; blocks = 2008 ; bfree = 2007
    /NAND: opendir: 0
    [00:00:00.309,417] <err> fs: file open error (-2)
    fs_open failed: -2
    [00:00:00.309,661] <inf> main: The device is put in USB mass storage mode.
    
    File exists:
    ** Booting Zephyr OS build v3.2.99-ncs2-5067-gb54c8baeeafb ***
    [00:00:00.251,281] <inf> flashdisk: Initialize device NAND
    [00:00:00.251,281] <inf> flashdisk: offset 0, sector size 512, page size 4096, volume size 1048576
    Area 0 at 0x0 on mx25r6435f@0 for 1048576 bytes
    [00:00:00.252,075] <inf> flashdisk: Initialize device NAND
    [00:00:00.252,105] <inf> flashdisk: offset 0, sector size 512, page size 4096, volume size 1048576
    Mount /NAND:: 0
    /NAND:: bsize = 512 ; frsize = 512 ; blocks = 2008 ; bfree = 2007
    /NAND: opendir: 0
    Wrote 12 bytes
      F 10 long_text_file_name_for_testing_purposes.txt
    Wrote 12 bytes
      F 12 SomeOtherFile.txt
    End of files
    [00:00:00.586,547] <inf> main: The device is put in USB mass storage mode.
    
     

     

    Kind regards,

    Håkon

  • Thank you for the response! Apologies, I see I failed to mention I'm commincating over SPI with the SD card. Overlay is below.

    nrf52840dk_nrf52840.overlay

    &spi1 {
        status = "okay";
        cs-gpios = <&gpio0 29 GPIO_ACTIVE_LOW>;
    
        sdhc0: sdhc@0 {
                compatible = "zephyr,sdhc-spi-slot";
                reg = <0>;
                status = "okay";
                mmc {
                    compatible = "zephyr,sdmmc-disk";
                    status = "okay";
                };
                spi-max-frequency = <24000000>;
        };
    };

    That's very interesting about requiring the file to already exist. In the fs_open() call,

    res = fs_open(&dfile, "/SD:/DKlog.txt", FS_O_RDWR | FS_O_APPEND);

    The FS_O_APPEND flag is described in fs.h as "Open/Create file for append". I should have clarified this earlier, I am able to create/append if the filepath is less than 14 characters, but if it is over then I get the -2 error code. It doesn't seem to matter if the file exists or not.

    Here is the output that I should have provided above as well.

    *** Booting Zephyr OS build v3.2.99-ncs2 ***
    [00:00:02.389,617] <inf> sd: Detected SD card
    [00:00:02.408,996] <inf> sd: Maximum SD clock is under 25MHz, using clock of 24000000Hz
    Disk mounted.
    
    Listing dir /SD: ...
    Filepath: /SD:/14len.txt
    [00:00:02.416,748] <err> fs: file open error (-2)

    Could it have something to do with my SPI settings?

Reply
  • Thank you for the response! Apologies, I see I failed to mention I'm commincating over SPI with the SD card. Overlay is below.

    nrf52840dk_nrf52840.overlay

    &spi1 {
        status = "okay";
        cs-gpios = <&gpio0 29 GPIO_ACTIVE_LOW>;
    
        sdhc0: sdhc@0 {
                compatible = "zephyr,sdhc-spi-slot";
                reg = <0>;
                status = "okay";
                mmc {
                    compatible = "zephyr,sdmmc-disk";
                    status = "okay";
                };
                spi-max-frequency = <24000000>;
        };
    };

    That's very interesting about requiring the file to already exist. In the fs_open() call,

    res = fs_open(&dfile, "/SD:/DKlog.txt", FS_O_RDWR | FS_O_APPEND);

    The FS_O_APPEND flag is described in fs.h as "Open/Create file for append". I should have clarified this earlier, I am able to create/append if the filepath is less than 14 characters, but if it is over then I get the -2 error code. It doesn't seem to matter if the file exists or not.

    Here is the output that I should have provided above as well.

    *** Booting Zephyr OS build v3.2.99-ncs2 ***
    [00:00:02.389,617] <inf> sd: Detected SD card
    [00:00:02.408,996] <inf> sd: Maximum SD clock is under 25MHz, using clock of 24000000Hz
    Disk mounted.
    
    Listing dir /SD: ...
    Filepath: /SD:/14len.txt
    [00:00:02.416,748] <err> fs: file open error (-2)

    Could it have something to do with my SPI settings?

Children
Related