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.
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).
@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
@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.
@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.
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:
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.
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).
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:
A debug() issue. The below code works properly with Pnut v46. But in Flexspin it fails to adjust the baud for the changing sysclock frequency. I presume Flexspin's -gbrk blob is out of date.
@evanh Actually the problem was that _clkset wasn't writing the frequency into the smart pin repository, it was only setting the value in memory (why doesn't the gbrk debugger use that? Oh well, another mystery). I've updated _clkset to do that now.
Eric,
Recently, and I can't say if and when it might have changed, I've noticed when I majorly restructure a program, that also uses my SD card driver, and leave a dangling reference in the source I'll get a compile error message of "Unknown symbol", which is expected, but gets the wrong source file. eg: I know perfectly well the errors are on lines 137 and 229 of source file sdfat_accesstest.c. Both after a struct __using("blkdrvr/sdsd.cc") drv_t;
/home/evanh/hoard/coding/prop2/testing/files/blkdrvr/sdsd.cc:1385: error: Unknown symbol 'DRV2'
/home/evanh/hoard/coding/prop2/testing/files/blkdrvr/sdsd.cc:1385: error: Unknown symbol 'filename'
Looking at sdsd.cc, Line 1385 is the extended line with __builtin_bswap32()
When I remove -DSD_DEBUG from the compile command, the compile error messages identify the locations correctly:
/home/evanh/hoard/coding/prop2/testing/files/sdfat-accesstest.c:137: error: Unknown symbol 'DRV2'
/home/evanh/hoard/coding/prop2/testing/files/sdfat-accesstest.c:229: error: Unknown symbol 'filename'
It compiles fine either way once the dangling references are fixed up.
@evanh : thanks for the bug report. The key was that the bug stopped showing up when "%X" was replaced with "%x"; the former isn't one of the formats directly handled by __builtin_printf (probably it should be,, but that's another matter). The code for falling back to the library printf wasn't properly restoring the error handling state. That should be fixed in github now.
I think it'd be better if a lacking support situation generated an error instead of silently switching to printf(). That way I'd know when bloat is being generated. EDIT: Not that it actually matters for the SD driver. Those are present only with debug compiles.
@evanh said:
I think it'd be better if a lacking support situation generated an error instead of silently switching to printf(). That way I'd know when bloat is being generated.
Well, stdio.h actually has #define printf __builtin_printf, so for now it has to fall back. I could add an optional warning about falling back though.
Comments
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.
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).
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
The handle you pass to
_vfs_open_fat_handle(h)
(e.g. the result of_sdmm_open
is aFILE *
, so you can usefread
orfwrite
on it. This may not be obvious in the headers, which tend to use the namestruct vfs_file_t *
for this pointer, butFILE
is an alias forstruct vfs_file_t
.huh, cool. Too easy.
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.
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.
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.
Actually I see the
stat()
function has anst_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: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.
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.
Yes, fstat() never got implemented, because not all file systems can do it easily (FATFS being one of them).
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:
And "/sd" gives me:
Looks like it ignores and returns without error.
Here's the relevant source code:
@evanh Aargh, there was another problem where stat() itself was just ignoring the root directory. That should be fixed now.
All good!
Thanks.
A debug() issue. The below code works properly with Pnut v46. But in Flexspin it fails to adjust the baud for the changing sysclock frequency. I presume Flexspin's -gbrk blob is out of date.
PS: pllset is from https://obex.parallax.com/obex/pllset/
@evanh Actually the problem was that
_clkset
wasn't writing the frequency into the smart pin repository, it was only setting the value in memory (why doesn't the gbrk debugger use that? Oh well, another mystery). I've updated_clkset
to do that now.Works nice thanks.
Good question. I don't remember a specific reason even though the dynamic handling was done on my request.
The debugger is generally supposed to survive hub memory corruption.
Eric,
Recently, and I can't say if and when it might have changed, I've noticed when I majorly restructure a program, that also uses my SD card driver, and leave a dangling reference in the source I'll get a compile error message of "Unknown symbol", which is expected, but gets the wrong source file. eg: I know perfectly well the errors are on lines 137 and 229 of source file sdfat_accesstest.c. Both after a
struct __using("blkdrvr/sdsd.cc") drv_t;
/home/evanh/hoard/coding/prop2/testing/files/blkdrvr/sdsd.cc:1385: error: Unknown symbol 'DRV2'
/home/evanh/hoard/coding/prop2/testing/files/blkdrvr/sdsd.cc:1385: error: Unknown symbol 'filename'
Looking at sdsd.cc, Line 1385 is the extended line with __builtin_bswap32()
When I remove -DSD_DEBUG from the compile command, the compile error messages identify the locations correctly:
/home/evanh/hoard/coding/prop2/testing/files/sdfat-accesstest.c:137: error: Unknown symbol 'DRV2'
/home/evanh/hoard/coding/prop2/testing/files/sdfat-accesstest.c:229: error: Unknown symbol 'filename'
It compiles fine either way once the dangling references are fixed up.
A little bit of experimenting I find the compile error is correct when I comment out the first and third printf()s.
Ah, and when replacing the two %X with %x that fixes the error too.
Hope that's narrowed it down enough for you.
@evanh : thanks for the bug report. The key was that the bug stopped showing up when "%X" was replaced with "%x"; the former isn't one of the formats directly handled by __builtin_printf (probably it should be,, but that's another matter). The code for falling back to the library printf wasn't properly restoring the error handling state. That should be fixed in github now.
Cool.
I think it'd be better if a lacking support situation generated an error instead of silently switching to printf(). That way I'd know when bloat is being generated. EDIT: Not that it actually matters for the SD driver. Those are present only with debug compiles.
Well, stdio.h actually has
#define printf __builtin_printf
, so for now it has to fall back. I could add an optional warning about falling back though.Yes please, that'd be great.