Skip to content

Commit f22611a

Browse files
committed
WIP: Define manager for file system state
1 parent cea6d8b commit f22611a

File tree

2 files changed

+63
-102
lines changed

2 files changed

+63
-102
lines changed

lib/storage/storage.cpp

Lines changed: 63 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,49 @@ static constexpr std::uint16_t blockSize = 512; // Should be 512
2727
static const esp_partition_t *partition = nullptr;
2828
static const char *const TAG = "STORAGE";
2929

30+
/**
31+
* Lists files and directories at path.
32+
*/
33+
static void listFiles(const char *const dirname)
34+
{
35+
std::cout << "Directory: '" << dirname << "'" << std::endl;
36+
File root = FFat.open(dirname);
37+
if (!root || !root.isDirectory())
38+
{
39+
ESP_LOGE(TAG, "Error: '%s' is not a directory!\n", dirname);
40+
return;
41+
}
42+
43+
File file = root.openNextFile();
44+
while (file)
45+
{
46+
std::cout << "\t" << file.name() << " (" << (file.isDirectory() ? "d" : "f") << ", " << file.size() << " Bytes)"
47+
<< std::endl;
48+
file.close();
49+
file = root.openNextFile();
50+
}
51+
file.close();
52+
root.close();
53+
}
54+
3055
class FileSystemSwitcher
3156
{
3257
public:
33-
typedef decltype(FFat) FileSystem;
34-
std::shared_ptr<FileSystem> getFileSystem_locking()
58+
void begin(const bool fsIsActive)
59+
{
60+
fileSystemIsActive = fsIsActive;
61+
stateMachine = std::thread(&FileSystemSwitcher::processStateRequests, this);
62+
}
63+
64+
std::shared_ptr<fs::FS> getFileSystem_locking()
3565
{
3666
std::unique_lock fs_state_lock{fileSystemState_mutex};
3767
if (!fileSystemIsActive)
3868
{
3969
stateChanged.wait(fs_state_lock, [this]() { return fileSystemIsActive; });
4070
}
4171
fs_state_lock.release();
42-
return {&FFat, [this](FileSystem *) { fileSystemState_mutex.unlock(); }};
72+
return {&FFat, [this](fs::FS *) { fileSystemState_mutex.unlock(); }};
4373
}
4474
void requestState(const bool fileSystemActive)
4575
{
@@ -52,7 +82,27 @@ class FileSystemSwitcher
5282
{
5383
return fileSystemIsActive;
5484
}
55-
void refreshState();
85+
void processStateRequests()
86+
{
87+
while (true)
88+
{
89+
std::unique_lock fs_state_lock{fileSystemState_mutex};
90+
stateChangeRequested.wait(fs_state_lock,
91+
[this]() { return requestFileSystemActive != fileSystemIsActive; });
92+
if (fileSystemIsActive = requestFileSystemActive)
93+
{
94+
usbMsc.mediaPresent(false);
95+
FFat.end(); // invalidate cache
96+
assert(FFat.begin()); // update data
97+
listFiles("/");
98+
}
99+
else
100+
{
101+
FFat.end(); // flush and unmount
102+
usbMsc.mediaPresent(true);
103+
}
104+
}
105+
}
56106

57107
private:
58108
std::condition_variable stateChangeRequested;
@@ -63,31 +113,7 @@ class FileSystemSwitcher
63113
bool fileSystemIsActive; //!< describes the current state
64114
};
65115

66-
class ReadyCondition
67-
{
68-
public:
69-
void setReady(const bool new_state)
70-
{
71-
ready = new_state;
72-
conditionVariable.notify_all();
73-
}
74-
bool isReady() const
75-
{
76-
return ready;
77-
}
78-
void wait_unitl_ready() const
79-
{
80-
std::mutex cv_m;
81-
std::unique_lock<std::mutex> lock(cv_m);
82-
conditionVariable.wait(lock, [this] { return isReady(); });
83-
}
84-
85-
private:
86-
mutable std::condition_variable conditionVariable;
87-
std::atomic<bool> ready;
88-
};
89-
90-
static ReadyCondition fileSystemState;
116+
static FileSystemSwitcher fileSystemSwitcher;
91117

92118
/**
93119
* Callback invoked when received WRITE10 command.
@@ -135,79 +161,20 @@ std::size_t Storage::size()
135161
return FFat.totalBytes();
136162
}
137163

138-
/**
139-
* Lists files and directories at path.
140-
*/
141-
static void listFiles(const char *const dirname)
142-
{
143-
std::cout << "Directory: '" << dirname << "'" << std::endl;
144-
File root = FFat.open(dirname);
145-
if (!root || !root.isDirectory())
146-
{
147-
ESP_LOGE(TAG, "Error: '%s' is not a directory!\n", dirname);
148-
return;
149-
}
150-
151-
File file = root.openNextFile();
152-
while (file)
153-
{
154-
std::cout << "\t" << file.name() << " (" << (file.isDirectory() ? "d" : "f") << ", " << file.size() << " Bytes)"
155-
<< std::endl;
156-
file.close();
157-
file = root.openNextFile();
158-
}
159-
file.close();
160-
root.close();
161-
}
162-
163-
/**
164-
* Switch from USB MSC to application mode (file system).
165-
*/
166-
static void switchToApplicationMode()
167-
{
168-
usbMsc.mediaPresent(false);
169-
FFat.end(); // invalidate cache
170-
assert(FFat.begin()); // update data
171-
fileSystemState.setReady(true);
172-
}
173-
174-
/**
175-
* Switch from application mode (file system) to USB MSC.
176-
*/
177-
static void switchToUSBMode()
178-
{
179-
FFat.end(); // flush and unmount
180-
fileSystemState.setReady(false);
181-
usbMsc.mediaPresent(true);
182-
}
183-
184-
static void usb_stopped_cb(void *const pvParameters)
185-
{
186-
switchToApplicationMode();
187-
listFiles("/");
188-
vTaskDelete(nullptr);
189-
}
190-
191-
static void usb_started_cb(void *const pvParameters)
192-
{
193-
switchToUSBMode();
194-
vTaskDelete(nullptr);
195-
}
196-
197-
static bool usbIsRunning = false;
164+
static std::atomic<bool> usbIsRunning = false;
198165
static void usbStoppedCallback(void *, esp_event_base_t, int32_t, void *)
199166
{
200167
if (!usbIsRunning)
201168
{
202169
return;
203170
}
204171
usbIsRunning = false;
205-
xTaskCreate(usb_stopped_cb, "USB_Stopped_CB", 4096, nullptr, 5, nullptr);
172+
fileSystemSwitcher.requestState(true);
206173
}
207174
static void usbStartedCallback(void *, esp_event_base_t, int32_t, void *)
208175
{
209176
usbIsRunning = true;
210-
xTaskCreate(usb_started_cb, "USB_Started_CB", 4096, nullptr, 5, nullptr);
177+
fileSystemSwitcher.requestState(false);
211178
}
212179

213180
void Storage::begin()
@@ -228,17 +195,18 @@ void Storage::begin()
228195
}
229196
ESP_LOGI(TAG, "Flash has a size of %u bytes\n", FFat.totalBytes());
230197

231-
USB.onEvent(ARDUINO_USB_STARTED_EVENT, usbStartedCallback);
232-
USB.onEvent(ARDUINO_USB_STOPPED_EVENT, usbStoppedCallback);
198+
fileSystemSwitcher.begin(true); // define state before callbacks are activated
199+
233200
usbMsc.vendorID("ESP32"); // max 8 chars
234201
usbMsc.productID("USB_MSC"); // max 16 chars
235202
usbMsc.productRevision("1.0"); // max 4 chars
236203
usbMsc.onStartStop(usbMsc_onStartStop);
204+
usbMsc.mediaPresent(false);
237205
// Set callback
238206
usbMsc.onRead(usbMsc_onRead);
239207
usbMsc.onWrite(usbMsc_onWrite);
240-
// MSC is ready for read/write
241-
usbMsc.mediaPresent(true);
208+
USB.onEvent(ARDUINO_USB_STARTED_EVENT, usbStartedCallback);
209+
USB.onEvent(ARDUINO_USB_STOPPED_EVENT, usbStoppedCallback);
242210

243211
// Set disk size, block size should be 512 regardless of spi flash page size
244212
if (!usbMsc.begin(FFat.totalBytes() / blockSize, blockSize))
@@ -257,9 +225,3 @@ void Storage::end()
257225
usbIsRunning = false;
258226
FFat.end();
259227
}
260-
261-
void Storage::waitForFileSystem()
262-
{
263-
fileSystemState.wait_unitl_ready();
264-
listFiles("/");
265-
}

lib/storage/storage.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
struct Storage
55
{
66
static void begin();
7-
static void waitForFileSystem();
87
static void end();
98
static std::size_t size();
109
};

0 commit comments

Comments
 (0)