-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmedia.hpp
412 lines (351 loc) · 14.1 KB
/
media.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
#pragma once
#include "fxCommon.hpp"
#include "tickTimer.hpp"
#include <array>
#include <atomic>
#include <functional>
#include <span>
#include <string_view>
#include <utility>
namespace FileX
{
enum class FaultTolerantMode : bool
{
disable,
enable
};
enum class MediaSectorType : ThreadX::Uint
{
unknown = FX_UNKNOWN_SECTOR,
boot = FX_BOOT_SECTOR,
fat = FX_FAT_SECTOR,
dirctory = FX_DIRECTORY_SECTOR,
data = FX_DATA_SECTOR
};
enum class MediaDriverRequest : ThreadX::Uint
{
read = FX_DRIVER_READ,
write = FX_DRIVER_WRITE,
flush = FX_DRIVER_FLUSH,
abort = FX_DRIVER_ABORT,
init = FX_DRIVER_INIT,
bootRead = FX_DRIVER_BOOT_READ,
releaseSectors = FX_DRIVER_RELEASE_SECTORS,
bootWrite = FX_DRIVER_BOOT_WRITE,
uninit = FX_DRIVER_UNINIT
};
class MediaBase
{
protected:
explicit MediaBase() = default;
static inline std::atomic_flag m_fileSystemInitialised = ATOMIC_FLAG_INIT;
};
template <MediaSectorSize N = defaultSectorSize> class Media : ThreadX::Native::FX_MEDIA, MediaBase
{
public:
friend class File;
using NotifyCallback = std::function<void(Media &)>;
using Ulong64Pair = std::pair<Error, ThreadX::Ulong64>;
using StrPair = std::pair<Error, std::string_view>;
Media(const Media &) = delete;
Media &operator=(const Media &) = delete;
static constexpr MediaSectorSize sectorSize();
static auto setFileSystemTime();
// Once initialized by this constructor, the application should call fx_system_date_set and fx_system_time_set to start with an accurate system date and time.
explicit Media(std::byte *driverInfoPtr = nullptr, const NotifyCallback &openNotifyCallback = {}, const NotifyCallback &closeNotifyCallback = {});
auto open(const std::string_view name, const FaultTolerantMode mode = FaultTolerantMode::enable);
auto format(const std::string_view volumeName, const ThreadX::Ulong storageSize, const ThreadX::Uint sectorPerCluster = 1, const ThreadX::Uint directoryEntriesFat12_16 = 32);
auto volume(const std::string_view volumeName);
auto volume();
auto createDir(const std::string_view dirName);
auto deleteDir(const std::string_view dirName);
auto renameDir(const std::string_view dirName, const std::string_view newName);
auto createFile(const std::string_view fileName);
auto deleteFile(const std::string_view fileName);
auto renameFile(const std::string_view fileName, const std::string_view newFileName);
auto defaultDir(const std::string_view newPath);
auto defaultDir();
auto localDir(const std::string_view newPath);
auto localDir();
auto clearLocalDir();
auto space();
/// This service is typically called when I/O errors are detected
auto abort();
auto invalidateCache();
auto check();
auto flush();
auto close();
auto name() const;
auto writeSector(const ThreadX::Ulong sectorNo, const std::span<std::byte, std::to_underlying(N)> sectorData);
auto readSector(const ThreadX::Ulong sectorNo, std::span<std::byte, std::to_underlying(N)> sectorData);
auto driverInfo();
auto driverRequest();
auto driverStatus(const Error error);
auto driverBuffer();
auto driverLogicalSector();
auto driverSectors();
auto driverPhysicalSector();
auto driverPhysicalTrack();
auto driverWriteProtect(const bool writeProtect = true);
auto driverFreeSectorUpdate(const bool freeSectorUpdate = true);
auto driverSystemWrite();
auto driverDataSectorRead();
auto driverSectorType();
virtual void driverCallback() = 0;
protected:
virtual ~Media();
private:
static auto driverCallback(auto mediaPtr);
static auto openNotifyCallback(auto mediaPtr);
static auto closeNotifyCallback(auto mediaPtr);
#ifdef FX_ENABLE_FAULT_TOLERANT
static constexpr ThreadX::Uint m_faultTolerantCacheSize{FX_FAULT_TOLERANT_MAXIMUM_LOG_FILE_SIZE};
static_assert(m_faultTolerantCacheSize % ThreadX::wordSize == 0, "Fault tolerant cache size must be a multiple of word size.");
// the scratch memory size shall be at least 3072 bytes and must be multiple of sector size.
static constexpr auto cacheSize = []() {
return (std::to_underlying(N) > std::to_underlying(MediaSectorSize::oneKiloByte)) ? std::to_underlying(MediaSectorSize::fourKilobytes) / ThreadX::wordSize : m_faultTolerantCacheSize / ThreadX::wordSize;
};
std::array<ThreadX::Ulong, cacheSize()> m_faultTolerantCache{};
#endif
std::byte *m_driverInfoPtr;
const NotifyCallback m_openNotifyCallback;
const NotifyCallback m_closeNotifyCallback;
static constexpr size_t volumNameLength{12};
std::array<ThreadX::Ulong, std::to_underlying(N) / ThreadX::wordSize> m_mediaMemory{};
const ThreadX::Ulong m_mediaMemorySizeInBytes{m_mediaMemory.size() * ThreadX::wordSize};
};
template <MediaSectorSize N> constexpr MediaSectorSize Media<N>::sectorSize()
{
return N;
}
template <MediaSectorSize N> auto Media<N>::setFileSystemTime()
{
auto time{std::chrono::system_clock::to_time_t(std::chrono::system_clock::now())};
auto localTime{*std::localtime(std::addressof(time))};
if (Error error{ThreadX::Native::fx_system_date_set(localTime.tm_year + 1900, localTime.tm_mon + 1, localTime.tm_mday)}; error != Error::success)
{
return error;
}
if (Error error{ThreadX::Native::fx_system_time_set(localTime.tm_hour, localTime.tm_min, localTime.tm_sec)}; error != Error::success)
{
return error;
}
return Error::success;
}
template <MediaSectorSize N>
Media<N>::Media(std::byte *driverInfoPtr, const NotifyCallback &openNotifyCallback, const NotifyCallback &closeNotifyCallback)
: ThreadX::Native::FX_MEDIA{}, m_driverInfoPtr{driverInfoPtr}, m_openNotifyCallback{openNotifyCallback}, m_closeNotifyCallback{closeNotifyCallback}
{
if (not m_fileSystemInitialised.test_and_set())
{
ThreadX::Native::fx_system_initialize();
setFileSystemTime();
}
if (m_openNotifyCallback)
{
[[maybe_unused]] Error error{fx_media_open_notify_set(this, Media::openNotifyCallback)};
assert(error == Error::success);
}
if (m_closeNotifyCallback)
{
[[maybe_unused]] Error error{fx_media_close_notify_set(this, Media::closeNotifyCallback)};
assert(error == Error::success);
}
}
template <MediaSectorSize N> Media<N>::~Media()
{
[[maybe_unused]] auto error{close()};
assert(error == Error::success || error == Error::mediaNotOpen);
}
template <MediaSectorSize N> auto Media<N>::open(const std::string_view name, const FaultTolerantMode mode)
{
using namespace ThreadX::Native;
if (Error error{fx_media_open(this, const_cast<char *>(name.data()), Media::driverCallback, m_driverInfoPtr, m_mediaMemory.data(), m_mediaMemorySizeInBytes)}; error != Error::success)
{
return error;
}
if (mode == FaultTolerantMode::enable)
{
#ifdef FX_ENABLE_FAULT_TOLERANT
return Error{fx_fault_tolerant_enable(this, m_faultTolerantCache.data(), m_faultTolerantCacheSize)};
#else
assert(mode == FaultTolerantMode::disable);
#endif
}
return Error::success;
}
template <MediaSectorSize N> auto Media<N>::format(const std::string_view volumeName, const ThreadX::Ulong storageSize, const ThreadX::Uint sectorPerCluster, const ThreadX::Uint directoryEntriesFat12_16)
{
assert(storageSize % std::to_underlying(N) == 0);
return Error{
fx_media_format(this,
Media::driverCallback, // Driver entry
m_driverInfoPtr, // could be RAM disk memory pointer
reinterpret_cast<ThreadX::Uchar *>(m_mediaMemory.data()), // Media buffer pointer
m_mediaMemorySizeInBytes, // Media buffer size
const_cast<char *>(volumeName.data()), // Volume Name
1, // Number of FATs
directoryEntriesFat12_16, // Directory Entries
0, // Hidden sectors
storageSize / std::to_underlying(N), // Total sectors
std::to_underlying(N), // Sector size
sectorPerCluster, // Sectors per cluster
1, // Heads
1) // Sectors per track
};
}
template <MediaSectorSize N> auto Media<N>::volume(const std::string_view volumeName)
{
assert(volumeName.length() < volumNameLength);
return Error{fx_media_volume_set(this, const_cast<char *>(volumeName.data()))};
}
template <MediaSectorSize N> auto Media<N>::volume()
{
char volumeName[volumNameLength];
Error error{fx_media_volume_get(this, volumeName, FX_BOOT_SECTOR)};
return StrPair{error, volumeName};
}
template <MediaSectorSize N> auto Media<N>::createDir(const std::string_view dirName)
{
return Error{fx_directory_create(this, const_cast<char *>(dirName.data()))};
}
template <MediaSectorSize N> auto Media<N>::deleteDir(const std::string_view dirName)
{
return Error{fx_directory_delete(this, const_cast<char *>(dirName.data()))};
}
template <MediaSectorSize N> auto Media<N>::renameDir(const std::string_view dirName, const std::string_view newName)
{
return Error{fx_directory_rename(this, const_cast<char *>(dirName.data()), const_cast<char *>(newName.data()))};
}
template <MediaSectorSize N> auto Media<N>::createFile(const std::string_view fileName)
{
return Error{fx_file_create(this, const_cast<char *>(fileName.data()))};
}
template <MediaSectorSize N> auto Media<N>::deleteFile(const std::string_view fileName)
{
return Error{fx_file_delete(this, const_cast<char *>(fileName.data()))};
}
template <MediaSectorSize N> auto Media<N>::renameFile(const std::string_view fileName, const std::string_view newFileName)
{
return Error{fx_file_rename(this, const_cast<char *>(fileName.data()), const_cast<char *>(newFileName.data()))};
}
template <MediaSectorSize N> auto Media<N>::defaultDir(const std::string_view newPath)
{
return Error{fx_directory_default_set(this, const_cast<char *>(newPath.data()))};
}
template <MediaSectorSize N> auto Media<N>::defaultDir()
{
char *path = nullptr;
Error error{fx_directory_default_get(this, std::addressof(path))};
return StrPair{error, path};
}
template <MediaSectorSize N> auto Media<N>::localDir(const std::string_view newPath)
{
using namespace ThreadX::Native;
FX_LOCAL_PATH localPath;
return Error{fx_directory_local_path_set(this, std::addressof(localPath), const_cast<char *>(newPath.data()))};
}
template <MediaSectorSize N> auto Media<N>::localDir()
{
char *path = nullptr;
Error error{fx_directory_local_path_get(this, std::addressof(path))};
return StrPair{error, path};
}
template <MediaSectorSize N> auto Media<N>::clearLocalDir()
{
return Error{fx_directory_local_path_clear(this)};
}
template <MediaSectorSize N> auto Media<N>::space()
{
ThreadX::Ulong64 spaceLeft{};
Error error{fx_media_extended_space_available(this, std::addressof(spaceLeft))};
return Ulong64Pair{error, spaceLeft};
}
template <MediaSectorSize N> auto Media<N>::abort()
{
return Error{fx_media_abort(this)};
}
template <MediaSectorSize N> auto Media<N>::invalidateCache()
{
return Error{fx_media_cache_invalidate(this)};
}
template <MediaSectorSize N> auto Media<N>::flush()
{
return Error{fx_media_flush(this)};
}
template <MediaSectorSize N> auto Media<N>::close()
{
return Error{fx_media_close(this)};
}
template <MediaSectorSize N> auto Media<N>::name() const
{
return std::string_view{fx_media_name};
}
template <MediaSectorSize N> auto Media<N>::writeSector(const ThreadX::Ulong sectorNo, const std::span<std::byte, std::to_underlying(N)> sectorData)
{
return Error{fx_media_write(this, sectorNo, sectorData.data())};
}
template <MediaSectorSize N> auto Media<N>::readSector(const ThreadX::Ulong sectorNo, std::span<std::byte, std::to_underlying(N)> sectorData)
{
return Error{fx_media_read(this, sectorNo, sectorData.data())};
}
template <MediaSectorSize N> auto Media<N>::driverInfo()
{
return fx_media_driver_info;
}
template <MediaSectorSize N> auto Media<N>::driverRequest()
{
return MediaDriverRequest{fx_media_driver_request};
}
template <MediaSectorSize N> auto Media<N>::driverStatus(const Error error)
{
fx_media_driver_status = std::to_underlying(error);
}
template <MediaSectorSize N> auto Media<N>::driverBuffer()
{
return fx_media_driver_buffer;
}
template <MediaSectorSize N> auto Media<N>::driverLogicalSector()
{
return fx_media_driver_logical_sector;
}
template <MediaSectorSize N> auto Media<N>::driverSectors()
{
return fx_media_driver_sectors;
}
template <MediaSectorSize N> auto Media<N>::driverWriteProtect(const bool writeProtect)
{
fx_media_driver_write_protect = writeProtect;
}
template <MediaSectorSize N> auto Media<N>::driverFreeSectorUpdate(const bool freeSectorUpdate)
{
fx_media_driver_free_sector_update = freeSectorUpdate;
}
template <MediaSectorSize N> auto Media<N>::driverSystemWrite()
{
return static_cast<bool>(fx_media_driver_system_write);
}
template <MediaSectorSize N> auto Media<N>::driverDataSectorRead()
{
return static_cast<bool>(fx_media_driver_data_sector_read);
}
template <MediaSectorSize N> auto Media<N>::driverSectorType()
{
return MediaSectorType{fx_media_driver_sector_type};
}
template <MediaSectorSize N> auto Media<N>::driverCallback(auto mediaPtr)
{
auto &media{static_cast<Media &>(*mediaPtr)};
media.driverCallback();
}
template <MediaSectorSize N> auto Media<N>::openNotifyCallback(auto mediaPtr)
{
auto &media{static_cast<Media &>(*mediaPtr)};
media.m_openNotifyCallback(media);
}
template <MediaSectorSize N> auto Media<N>::closeNotifyCallback(auto mediaPtr)
{
auto &media{static_cast<Media &>(*mediaPtr)};
media.m_closeNotifyCallback(media);
}
} // namespace FileX