Shop OBEX P1 Docs P2 Docs Learn Events
flexspin compiler for P2: Assembly, Spin, BASIC, and C in one compiler - Page 126 — Parallax Forums

flexspin compiler for P2: Assembly, Spin, BASIC, and C in one compiler

1120121122123124126»

Comments

  • evanhevanh Posts: 16,352
    edited 2025-03-03 22:17

    Okay. Looking around I've found cluster size in struct FATFS. Which _vfs_open_fat_handle() creates and passes to f_mount(). The user program calls _vfs_open_fat_handle() during mounting, so access to cluster size is only just below. I'm not sure of C foo to reach it though.

  • ersmithersmith Posts: 6,147

    Worst case I suppose you could always read sector 0 (the BPB) and get it from there. Out of curiosity, why do you want the cluster size?

  • There's a way to grab the internal FATFS struct from the VFS. I think I used it once to proof-of-concept converting paths between long and short names - you'd need that if you had some kind of file explorer application with LFN support and want to launch e.g. MegaYume (no LFN support) with a given file through FC000 ARGv).

  • evanhevanh Posts: 16,352
    edited 2025-03-04 01:35

    @ersmith said:
    Worst case I suppose you could always read sector 0 (the BPB) and get it from there. Out of curiosity, why do you want the cluster size?

    From observation, I'm of the opinion that the file speed testing performs highest when the read/write chunk size (The tester's buffer size) matches the cluster size. Above that level seems to be slightly reduced speed even.

    And how does a program read partition blocks?
    something like fopen("/sd/.","rb"); ??
    EDIT: Nope, errno = 4: No such file or directory

  • ersmithersmith Posts: 6,147

    @evanh said:

    @ersmith said:
    Worst case I suppose you could always read sector 0 (the BPB) and get it from there. Out of curiosity, why do you want the cluster size?

    And how does a program read partition blocks?
    something like fopen("/sd/.","rb"); ??
    EDIT: Nope, errno = 4: No such file or directory

    The handle you pass to _vfs_open_fat_handle(h) (e.g. the result of _sdmm_open is a FILE *, so you can use fread or fwrite on it. This may not be obvious in the headers, which tend to use the name struct vfs_file_t * for this pointer, but FILE is an alias for struct vfs_file_t.

  • evanhevanh Posts: 16,352

    huh, cool. Too easy.

  • evanhevanh Posts: 16,352
    edited 2025-03-04 21:13

    Uh-oh, can't fseek(). It just doesn't do anything. I have to read every block sequentially to reach start of partition to then fetch the cluster size.

    PS: If it were to function, it'd make sense to use LBA block numbering rather than bytes.

  • ersmithersmith Posts: 6,147

    @evanh said:
    Uh-oh, can't fseek(). It just doesn't do anything. I have to read every block sequentially to reach start of partition to then fetch the cluster size.

    I forgot to warn you, fseek() on the SDMM device only works to seek to sector boundaries; it's also possible (probable) that fread() and fwrite() will only work on sector sized chunks.

    PS: If it were to function, it'd make sense to use LBA block numbering rather than bytes.

    You can actually open a FAT file image that's contained on another device (e.g. a FAT file on the host PC using the 9P file system). So not all underlying devices only work on block boundaries, just the kind of hacky SDMM one. Someday it would be nice to remove the SDMM restrictions, but that's a pretty niche case.

  • ersmithersmith Posts: 6,147

    Actually I see the stat() function has an st_blksize field, which we can fill in with the cluster size (at least for regular files). I've just pushed a change to do that. The patch looks like:

    diff --git a/include/filesys/fatfs/fatfs.cc b/include/filesys/fatfs/fatfs.cc
    index 272112d8..b49a87f7 100644
    --- a/include/filesys/fatfs/fatfs.cc
    +++ b/include/filesys/fatfs/fatfs.cc
    @@ -224,6 +224,7 @@ int v_stat(const char *name, struct stat *buf)
         int r;
         FILINFO finfo;
         unsigned mode;
    +    unsigned clustersize = 4096;
     #ifdef _DEBUG_FATFS
         __builtin_printf("v_stat(%s)\n", name);
     #endif
    @@ -234,6 +235,7 @@ int v_stat(const char *name, struct stat *buf)
             r = 0;
         } else {
             r = f_stat(name, &finfo);
    +        clustersize = finfo.fclust;
         }
         if (r != 0) {
             return _set_dos_error(r);
    @@ -248,8 +250,8 @@ int v_stat(const char *name, struct stat *buf)
         buf->st_mode = mode;
         buf->st_nlink = 1;
         buf->st_size = finfo.fsize;
    -    buf->st_blksize = 512;
    -    buf->st_blocks = (finfo.fsize + 511) / 512;
    +    buf->st_blksize = clustersize;
    +    buf->st_blocks = (finfo.fsize + clustersize - 1) / clustersize;
         buf->st_atime = buf->st_mtime = buf->st_ctime = unixtime(finfo.fdate, finfo.ftime);
     #ifdef _DEBUG_FATFS
         __builtin_printf("v_stat returning %d mode=0x%x\n", r, buf->st_mode);
    diff --git a/include/filesys/fatfs/ff.c b/include/filesys/fatfs/ff.c
    index e810c130..a8d66ec9 100644
    --- a/include/filesys/fatfs/ff.c
    +++ b/include/filesys/fatfs/ff.c
    @@ -4754,6 +4754,7 @@ FRESULT f_stat (
            FREE_NAMBUF();
        }
    
    +        if (fno) fno->fclust = (DWORD)dj.obj.fs->csize * SS(dj.obj.fs);
        LEAVE_FF(dj.obj.fs, res);
     }
    
    diff --git a/include/filesys/fatfs/ff.h b/include/filesys/fatfs/ff.h
    index 64bf79db..085cf6fd 100644
    --- a/include/filesys/fatfs/ff.h
    +++ b/include/filesys/fatfs/ff.h
    @@ -249,6 +249,7 @@ typedef struct {
        WORD    fdate;          /* Modified date */
        WORD    ftime;          /* Modified time */
        BYTE    fattrib;        /* File attribute */
    +   DWORD   fclust;         /* File cluster size in bytes */
     #if FF_USE_LFN
        TCHAR   altname[FF_SFN_BUF + 1];/* Altenative file name */
        TCHAR   fname[FF_LFN_BUF + 1];  /* Primary file name */
    
  • evanhevanh Posts: 16,352
    edited 2025-03-05 07:29

    Sounds good.

    Ah, stat() needs a path specified, would that be "/sd" this time?
    fstat() can presumably use the same file handle I already have. However fstat() is not implemented? It has a header entry declared but no source definition that I can see.

  • ersmithersmith Posts: 6,147

    @evanh said:
    Sounds good.

    Ah, stat() needs a path specified, would that be "/sd" this time?

    No, it would be the name of the file you plan to read from. The code I posted won't work on the root directory (e.g. "/sd", if that's where you mounted the fatfs) :(. However, I've pushed an update that will work, so that's always an option.

    fstat() can presumably use the same file handle I already have. However fstat() is not implemented? It has a header entry declared but no source definition that I can see.

    Yes, fstat() never got implemented, because not all file systems can do it easily (FATFS being one of them).

  • evanhevanh Posts: 16,352
    edited 2025-03-05 10:24

    Updated to the latest include/filesys/fatfs/ files.
    Okay, making progress. I correctly get buff->st_blksize == 32768 when I stat() one of the written files. But not the case for stat("/sd", buff);. It's just a zero value for all attempts at stat()ing the mounted volume directly.

    I am just blindly examining st_blksize without knowing anything else about what stat() has filled out. Don't know how it's normally used.

    EDIT: Turning on -D_DEBUG_FATFS and using a file gives me:

    SD Card Init Successful
    v_stat(speed1.bin)
    f_getvolinfo: ssize=512 csize=64
    v_stat returning 0 mode=0x1b6
     cluster size = 32768
    

    And "/sd" gives me:

    SD Card Init Successful
     cluster size = 0
    

    Looks like it ignores and returns without error.

    Here's the relevant source code:

        ...
        mount("/sd", _vfs_open_fat_handle(handle));
    
        struct stat  *buff = __builtin_alloca(sizeof(struct stat));
        if( !buff ) {
            printf(" malloc() failed!\n");
            exit(1);
        }
        _seterror(0);
        if( stat("/sd/", buff) )
            printf(" stat() failed!   errno = %d: %s\n", errno, strerror(errno));
        else {
            printf(" cluster size = %d\n", buff->st_blksize);
        }
    
  • ersmithersmith Posts: 6,147

    @evanh Aargh, there was another problem where stat() itself was just ignoring the root directory. That should be fixed now.

  • evanhevanh Posts: 16,352
    edited 2025-03-05 12:48

    All good! :) Thanks.

     CID decode:  ManID=1D   OEMID=AD  Name=USD
      Ver=2.0   Serial=000003A0   Date=2024-1
    SD Card Init Successful
     cluster size = 32768
    
     Buffer = 2 kB,  Written 512 kB at 1643 kB/s,  Verified,  Read 512 kB at 8404 kB/s
     Buffer = 2 kB,  Written 512 kB at 2021 kB/s,  Verified,  Read 512 kB at 8481 kB/s
     Buffer = 2 kB,  Written 512 kB at 1977 kB/s,  Verified,  Read 512 kB at 8481 kB/s
    
     Buffer = 4 kB,  Written 1024 kB at 3789 kB/s,  Verified,  Read 1024 kB at 13729 kB/s
     Buffer = 4 kB,  Written 1024 kB at 3801 kB/s,  Verified,  Read 1024 kB at 13632 kB/s
     Buffer = 4 kB,  Written 1024 kB at 3978 kB/s,  Verified,  Read 1024 kB at 13527 kB/s
    
     Buffer = 8 kB,  Written 2048 kB at 6513 kB/s,  Verified,  Read 2048 kB at 19781 kB/s
     Buffer = 8 kB,  Written 2048 kB at 6890 kB/s,  Verified,  Read 2048 kB at 19762 kB/s
     Buffer = 8 kB,  Written 2048 kB at 6303 kB/s,  Verified,  Read 2048 kB at 19936 kB/s
    
     Buffer = 16 kB,  Written 4096 kB at 17766 kB/s,  Verified,  Read 4096 kB at 26741 kB/s
     Buffer = 16 kB,  Written 4096 kB at 18544 kB/s,  Verified,  Read 4096 kB at 26749 kB/s
     Buffer = 16 kB,  Written 4096 kB at 18548 kB/s,  Verified,  Read 4096 kB at 26744 kB/s
    
     Buffer = 32 kB,  Written 4096 kB at 21362 kB/s,  Verified,  Read 4096 kB at 28900 kB/s
     Buffer = 32 kB,  Written 4096 kB at 23524 kB/s,  Verified,  Read 4096 kB at 29019 kB/s
     Buffer = 32 kB,  Written 4096 kB at 23633 kB/s,  Verified,  Read 4096 kB at 29021 kB/s
    
     Buffer = 64 kB,  Written 4096 kB at 22683 kB/s,  Verified,  Read 4096 kB at 29039 kB/s
     Buffer = 64 kB,  Written 4096 kB at 23727 kB/s,  Verified,  Read 4096 kB at 29025 kB/s
     Buffer = 64 kB,  Written 4096 kB at 23601 kB/s,  Verified,  Read 4096 kB at 28898 kB/s
    
     Buffer = 128 kB,  Written 4096 kB at 22694 kB/s,  Verified,  Read 4096 kB at 28628 kB/s
     Buffer = 128 kB,  Written 4096 kB at 23546 kB/s,  Verified,  Read 4096 kB at 28876 kB/s
     Buffer = 128 kB,  Written 4096 kB at 23727 kB/s,  Verified,  Read 4096 kB at 28882 kB/s
     Clear pins: 21 20 16 23 22
    
Sign In or Register to comment.