Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
ArduinoFs.hxx
Go to the documentation of this file.
1
39#ifndef _FREERTOS_DRIVERS_ARDUINO_ARDUINOFS_HXX_
40#define _FREERTOS_DRIVERS_ARDUINO_ARDUINOFS_HXX_
41
42#ifndef ARDUINO_ARCH_STM32
43#error This module only works for STM32 boards.
44#endif
45
46#ifndef OPENMRN_HAVE_POSIX_FD
47#error You must add a file build_opt.h to the sketch directory and add -DOPENMRN_HAVE_POSIX_FD to it to make use of this module.
48#endif
49
50#include "stm32_eeprom.h"
51#include <errno.h>
52
53#define EEPROM_FILENAME "/dev/eeprom"
54
58{
59public:
61 static constexpr unsigned MAX_FD = 8;
63 static constexpr off_t UNUSED_FILE = (off_t)-1;
64
66 struct FileInfo
67 {
70
72 bool in_use()
73 {
74 return offset != UNUSED_FILE;
75 }
76
78 void open()
79 {
80 offset = 0;
81 }
82
84 void close()
85 {
87 }
88 };
89
92
97 static FileInfo *get_file(int fd)
98 {
99 if (fd >= MAX_FD || !fds[fd].in_use())
100 {
101 errno = EBADF;
102 return nullptr;
103 }
104 return &fds[fd];
105 }
106
110 static int new_fd()
111 {
112 for (int fd = 0; fd < MAX_FD; ++fd)
113 {
114 if (!fds[fd].in_use())
115 {
116 fds[fd].open();
117 return fd;
118 }
119 }
120 errno = ENFILE;
121 return -1;
122 }
123
125 static void flush_if_dirty()
126 {
127 if (dirty_)
128 {
129 eeprom_buffer_flush();
130 dirty_ = 0;
131 }
132 }
133
135 static uint8_t loaded_;
137 static uint8_t dirty_;
138};
139
141uint8_t FsStatic::loaded_ = 0;
142uint8_t FsStatic::dirty_ = 0;
143
144extern "C"
145{
146
147int _open_r(struct _reent *reent, const char *path, int flags, int mode)
148{
149 if (strcmp(path, EEPROM_FILENAME) != 0)
150 {
151 errno = ENOENT;
152 return -1;
153 }
155 {
156 eeprom_buffer_fill();
158 }
159 return FsStatic::new_fd();
160}
161
162int _close_r(struct _reent *reent, int fd)
163{
165 if (!finfo)
166 {
167 return -1;
168 }
169 finfo->close();
171 return 0;
172}
173
174ssize_t _read_r(struct _reent *reent, int fd, void *buf, size_t count)
175{
177 if (!finfo)
178 {
179 return -1;
180 }
181 ssize_t ret = 0;
182 uint8_t *dst = (uint8_t *)buf;
183 int left = (int)E2END - (int)finfo->offset;
184 if (left < 0)
185 {
186 left = 0;
187 }
188 if (left < count)
189 {
190 count = left;
191 }
192 while (count > 0)
193 {
194 *dst = eeprom_buffered_read_byte(finfo->offset);
195 ++dst;
196 ++finfo->offset;
197 --count;
198 ++ret;
199 }
200 return ret;
201}
202
203ssize_t _write_r(struct _reent *reent, int fd, const void *buf, size_t count)
204{
206 if (!finfo)
207 {
208 return -1;
209 }
210 ssize_t ret = 0;
211 const uint8_t *src = (const uint8_t *)buf;
212 int left = (int)E2END - (int)finfo->offset;
213 if (left < 0)
214 {
215 left = 0;
216 }
217 if (left < count)
218 {
219 count = left;
220 }
221 if (count)
222 {
224 }
225 while (count > 0)
226 {
227 eeprom_buffered_write_byte(finfo->offset, *src);
228 ++src;
229 ++finfo->offset;
230 --count;
231 ++ret;
232 }
233 return ret;
234}
235
236int fsync(int fd)
237{
239 if (!finfo)
240 {
241 return -1;
242 }
244 return 0;
245}
246
247int _stat_r(struct _reent *reent, const char *path, struct stat *stat)
248{
249 if (strcmp(path, EEPROM_FILENAME) != 0)
250 {
251 errno = ENOENT;
252 return -1;
253 }
254 memset(stat, 0, sizeof(*stat));
255 stat->st_size = E2END;
256 return 0;
257}
258
259int _fstat_r(struct _reent *reent, int fd, struct stat *stat)
260{
262 if (!finfo)
263 {
264 return -1;
265 }
266 memset(stat, 0, sizeof(*stat));
267 stat->st_size = E2END;
268 return 0;
269}
270
271_off_t _lseek_r(struct _reent *reent, int fd, _off_t offset, int whence)
272{
274 if (!finfo)
275 {
276 return -1;
277 }
278 off_t new_offset = finfo->offset;
279 switch (whence)
280 {
281 case SEEK_SET:
282 new_offset = offset;
283 break;
284 case SEEK_CUR:
285 new_offset += offset;
286 break;
287 case SEEK_END:
288 new_offset = E2END + offset;
289 break;
290 default:
291 new_offset = E2END + 1;
292 }
293 if (new_offset > E2END)
294 {
295 errno = EINVAL;
296 return -1;
297 }
298 finfo->offset = new_offset;
299 return new_offset;
300}
301
302} // extern "C"
303
304#endif // _FREERTOS_DRIVERS_ARDUINO_ARDUINOFS_HXX_
Class that holds information and code for the single-file filesystem for emulating eeprom.
Definition ArduinoFs.hxx:58
static FileInfo fds[MAX_FD]
Stores all file descriptors.
Definition ArduinoFs.hxx:91
static constexpr unsigned MAX_FD
Number of possible open file desriptors.
Definition ArduinoFs.hxx:61
static uint8_t loaded_
1 if we have filled the eeprom buffer at least once since startup.
static constexpr off_t UNUSED_FILE
Offset markng that a file descriptor is not in use.
Definition ArduinoFs.hxx:63
static void flush_if_dirty()
If there is unflushed writes, performs the flash write.
static FileInfo * get_file(int fd)
Lookup a file descriptor.
Definition ArduinoFs.hxx:97
static uint8_t dirty_
1 if we have unflushed written data in the eeprom buffer.
static int new_fd()
Allocates a new file descriptor.
We have one of these for each open file descriptor.
Definition ArduinoFs.hxx:67
off_t offset
POSIX file offset.
Definition ArduinoFs.hxx:69
void open()
Marks the file descriptor to be in use.
Definition ArduinoFs.hxx:78
void close()
Marks the file descriptor to be not in use.
Definition ArduinoFs.hxx:84