Open TheSlowGrowth opened 2 years ago
I definitely like the idea of this. Are you thinking that this would be a layer on top of fatfs (on the hardware, with whatever alternative for mock in unit tests), or would this actually be a new filesystem to replace fatfs? As those would be significantly different scopes.
Wrt to your "abstract" point -- as of the latest update that added FatFsInterface
, the actual fatfs usage itself does become independent of any hardware connections. Some of the legacy objects (WavFileReader
, etc.) haven't been thoroughly updated to deal with that yet.
As for error handling, this is something that I've been wanting to resolve for the existing media as well.
With USB you can take advantage of I/O level connect/disconnect callbacks due to the nature of the connection.
With SDMMC, without a detect pin wired up (which the vertical connector on most of our official boards doesn't have), you have to actually try, and fail to have a transaction. That could just be a simple GetStatus
or something, but its still a bit of overhead.
As for what happens to your return types when an error occurs: at the cost of some extra ram, we could store an error code within the ReadOnlyFile
, and other types. That way other functions, or the user could check if ReadOnlyFile.isValid()
or whatever.
I'm not sure that's the best way to do it, but but I'm definitely interested in what other people think as well.
Are you thinking that this would be a layer on top of fatfs
Yes definitely. For the production code, fatfs functions would be wrapped into the FileIoLayer
(or whatever we end up calling it). For test code, that layer would be replaced with a mock.
as of the latest update that added FatFsInterface, the actual fatfs usage itself does become independent of any hardware connections
Yers, and that in itself is a huge step. I'd like to take it further and abstract away the fatfs calls. That would allow us to write higher level code that can work on multiple types of storages, e.g. you could imagine a patch manager class that writes to a ReadWriteFile
object. We could then use this patch storage class with SD cards, USB drives (those would be using the fatfs-based low level file io) or the QSPI flash (which could have its own file io layer). The "high level" patch storage could be properly unit tested, of course.
I took a look at the current file system support in libDaisy, and I'd like to suggest an improved API. Before I get to work writing the code, I wanted to post here and get some feedback and collect some ideas.
Here's what I'd like to achieve:
WavFileReader
or serializers / file stream classes, etc.Viewed from an application, this is what I imagine such a filesystem API to look like:
This all works internally by providing a File-IO layer abstraction that the
FileSystemHandle
and the other classes use to actually access the hardware. Think of it like a wrapper around fatfs functions. There would be ONE instance of such an abstraction layer, per file system. The implementation ofFatFSInterface::InitAndMount()
would look something like this:while the
FileSystemHandle
essentially just redirects calls to the IO Layer:Similarly, the
ReadOnlyFile
or theDirectoryIterator
would take an IO Layer as a constructor argument. This makes sure that we can mock the IO Layer in Unit tests, meaning that we can do proper unit testing without having to hide fatfs-code behind#ifndef UNIT_TEST
.Long story short: I have some of this already sketched out, but I'd like some feedback. Would this be something you'd like to see in libDaisy? What would you improve? How would we best handle errors (SD card unplugged at runtime, etc) in a typesafe way?