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?

  • Hi,

     

    Unfortunately, I do not have a SPI SD card connector, so I needed to emulate this with the QSPI flash IC on the nRF52840-DK. 

    One thing you should try to change is the max. frequency, as this will select the highest possible frequency now. This can be problematic if you have longer traces, and can introduce problems in the transmission.

    Could you try to lower it to 1 MHz and see if this works better?

     

    Kind regards,

    Håkon

  • Hi Hakon,

    Great suggestion, so I tried lowering the frequency from 24 MHz to 1 MHz but it still failed and returned the same error code. However, I started experimenting with the flags and it looks like by adding the FS_O_CREATE flag to the open function call has removed the issue.

    The comment for FS_O_APPEND in fs.h says "/** Open/create file for append */" as a comment, but it looks like in my case that this might be a mistake?

    fs.h

    /**
     * @name fs_open open and creation mode flags
     * @{
     */
    /** Open for read flag */
    #define FS_O_READ       0x01
    /** Open for write flag */
    #define FS_O_WRITE      0x02
    /** Open for read-write flag combination */
    #define FS_O_RDWR       (FS_O_READ | FS_O_WRITE)
    /** Bitmask for read and write flags */
    #define FS_O_MODE_MASK  0x03
    
    /** Create file if it does not exist */
    #define FS_O_CREATE     0x10
    /** Open/create file for append */
    #define FS_O_APPEND     0x20
    /** Bitmask for open/create flags */
    #define FS_O_FLAGS_MASK 0x30
    
    /** Bitmask for open flags */
    #define FS_O_MASK       (FS_O_MODE_MASK | FS_O_FLAGS_MASK)

    I think regardless, the symptom was weird as I was definitely able to create a file with a short name using only the FS_O_APPEND flag. Once I OR in the FS_O_CREATE flag to the FS_O_APPEND flag, then the system seems to work as intended.

    I think we can call this issue resolved.

  • Hi,

     

    I'm glad to hear that you got it working.

    This is what I also noticed wrt. the FS_O_APPEND flag. I believe the comment is incorrect, as the fs_open API conflicts with the comment on the FS_O_APPEND define:

    https://docs.zephyrproject.org/apidoc/latest/group__file__system__api.html#ga9c90031ba3e5a10da8e00e81d53ef63b

     

    Kind regards,

    Håkon

Reply Children
No Data
Related