rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
storage.cpp
Go to the documentation of this file.
1/**
2 * @file storage.cpp
3 * @brief adapter for unify access to MFS and legacy 'internal flash' storage drivers
4 *
5 * @date Jan 4, 2025
6 * @author Andrey Gusakov
7 */
8
9#include "pch.h"
10
11#include "storage.h"
12
13#if EFI_CONFIGURATION_STORAGE
14#include "mpu_util.h"
15#endif
16
17/* If any setting storage is exist or we are in unit test */
18#if EFI_CONFIGURATION_STORAGE || defined(EFI_UNIT_TEST)
20{
21#if (EFI_STORAGE_INT_FLASH == TRUE) || defined(EFI_UNIT_TEST)
22 if ((id == EFI_SETTINGS_RECORD_ID) ||
24 // special case, settings can be stored in internal flash
25
26 // writing internal flash can cause cpu freeze
27 // check if HW support flash writing while executing
29 return true;
30 }
31
32#if EFI_SHAFT_POSITION_INPUT
33 // MCU does not support write while executing, check if engine is stopped
35 return true;
36 } else {
37 // rusEfi usually runs on hardware which halts execution while writing to internal flash, so we
38 // postpone writes to until engine is stopped. Writes in case of self-stimulation are fine.
39 return false;
40 }
41#endif // EFI_SHAFT_POSITION_INPUT
42 }
43#endif // EFI_STORAGE_INT_FLASH
44
45 // TODO: we expect every other ID to be stored in external flash...
46 return true;
47}
48#endif // EFI_CONFIGURATION_STORAGE || defined(EFI_UNIT_TEST)
49
50/* If any setting storage is exist */
51#if EFI_CONFIGURATION_STORAGE
52
53#if EFI_STORAGE_INT_FLASH == TRUE
54#include "storage_flash.h"
55#endif
56
57#if EFI_STORAGE_MFS == TRUE
58#include "storage_mfs.h"
59#endif
60
61#if EFI_STORAGE_SD == TRUE
62#include "storage_sd.h"
63#endif
64
65#define STORAGE_MANAGER_POLL_INTERVAL_MS 100
66
67static constexpr size_t storagesCount = STORAGE_TOTAL;
68
70
71chibios_rt::Mailbox<msg_t, 16> storageManagerMb;
72
73#define MSG_CMD_WRITE (0)
74// force settings save independently of mcuCanFlashWhileRunning()
75#define MSG_CMD_WRITE_NOW (1)
76#define MSG_CMD_READ (2)
77#define MSG_CMD_PING (3)
78#define MSG_CMD_REG (4)
79#define MSG_CMD_UNREG (5)
80
81#define MSG_ID_MASK 0x1f
82
83static bool storageWriteID(uint32_t id) {
84 // Do the actual flash write operation for given ID
85 if (id == EFI_SETTINGS_RECORD_ID) {
86 return writeToFlashNowImpl();
87 } else if (id == EFI_LTFT_RECORD_ID) {
88 engine->module<LongTermFuelTrim>()->store();
89 return true;
90 } else {
91 efiPrintf("Requested to write unknown record id %ld", id);
92 // to clear pending bit
93 return true;
94 }
95 return true;
96}
97
98static bool storageReadID(uint32_t id) {
99 // Do actual read and call consumers callback
100
101 if (id == EFI_LTFT_RECORD_ID) {
102 engine->module<LongTermFuelTrim>()->load();
103 return true;
104 } else {
105 efiPrintf("Requested to read unknown record id %ld", id);
106 // to clear pending bit
107 return true;
108 }
109}
110
111static const char *storageTypeToName(StorageType type) {
112 switch (type) {
114 return "INT_FLASH";
116 return "MFS_INT_FLASH";
118 return "MFS_EXT_FLASH";
119 case STORAGE_SD_CARD:
120 return "SD_CARD";
121 default:
122 break;
123 }
124
125 return "UNK";
126}
127
128#define for_all_storages SettingStorageBase* storage = nullptr; \
129 for (size_t i = 0; i < storagesCount; i++) \
130 if ((storage = storages[i]) != nullptr)
131
133 for_all_storages {
134 if ((storage->isReady()) && (storage->isIdSupported(id))) {
135 return true;
136 }
137 }
138
139 return false;
140}
141
142StorageStatus storageWrite(StorageItemId id, const uint8_t *ptr, size_t size) {
143 bool success = false;
145
146 for_all_storages {
147 if ((!storage->isReady()) || (!storage->isIdSupported(id))) {
148 continue;
149 }
150
151 status = storage->store(id, ptr, size);
152 if (status == StorageStatus::Ok) {
153 success = true;
154 }
155 }
156
157 return (success ? StorageStatus::Ok : status);
158}
159
160StorageStatus storageRead(StorageItemId id, uint8_t *ptr, size_t size) {
161 bool success = false;
163
164 for_all_storages {
165 if ((!storage->isReady()) || (!storage->isIdSupported(id))) {
166 continue;
167 }
168
169 status = storage->read(id, ptr, size);
170 if (status == StorageStatus::Ok) {
171 success = true;
172 }
173 }
174
175 return (success ? StorageStatus::Ok : status);
176}
177
178static bool storageManagerSendCmd(uint32_t cmd, uint32_t arg)
179{
180 msg_t msg = ((cmd & 0xff) << 24) | (arg & 0x00ffffff);
181 // Note: we are not sure about caller context and using universal (but not optimal) chSysGetStatusAndLockX()
182 chibios_rt::CriticalSectionLocker csl;
183 return (storageManagerMb.postI(msg) == MSG_OK);
184}
185
187 return storageManagerSendCmd(forced ? MSG_CMD_WRITE_NOW : MSG_CMD_WRITE, (uint32_t)id);
188}
189
191 return storageManagerSendCmd(MSG_CMD_READ, (uint32_t)id);
192}
193
195 if (type >= STORAGE_TOTAL) {
196 return false;
197 }
198
199 if (storageIsStorageRegistered(type)) {
200 /* already registered */
201 efiPrintf("Trying to register already exist storage %s", storageTypeToName(type));
202 return false;
203 }
204
205 storages[type] = storage;
206 efiPrintf("Storage %s registered", storageTypeToName(type));
207
208 storageManagerSendCmd(MSG_CMD_PING, 0);
209
210 return true;
211}
212
214 if (type >= STORAGE_TOTAL) {
215 return false;
216 }
217
218 if (!storageIsStorageRegistered(type)) {
219 /* already unregistered */
220 efiPrintf("Trying to unregister non-exist storage %s", storageTypeToName(type));
221 return false;
222 }
223
224 storages[type] = nullptr;
225 efiPrintf("Storage %s unregistered", storageTypeToName(type));
226
227 return true;
228}
229
231 if (type >= STORAGE_TOTAL) {
232 return false;
233 }
234
235 return (storages[type] != nullptr);
236}
237
239{
240 return storageManagerSendCmd(MSG_CMD_REG, (uint32_t)id);
241}
242
244{
245 return storageManagerSendCmd(MSG_CMD_UNREG, (uint32_t)id);
246}
247
248static uint32_t pendingWrites = 0;
249static uint32_t pendingReads = 0;
250
251#if (EFI_STORAGE_MFS == TRUE) || (EFI_STORAGE_SD == TRUE)
252/* in case of MFS or SD card we need more stack */
253static THD_WORKING_AREA(storageManagerThreadStack, 3 * UTILITY_THREAD_STACK_SIZE);
254#else
255static THD_WORKING_AREA(storageManagerThreadStack, UTILITY_THREAD_STACK_SIZE);
256#endif
257
258static void storageManagerThread(void*) {
259 chRegSetThreadName("storage manger");
260
261 while (true) {
262 msg_t ret;
263 msg_t msg;
264
265 // Wait for a request to come in or timeout
266 ret = storageManagerMb.fetch(&msg, TIME_MS2I(STORAGE_MANAGER_POLL_INTERVAL_MS));
267 if (ret == MSG_OK) {
268 uint8_t cmd = (msg >> 24) & 0xff;
269 uint32_t id = msg & MSG_ID_MASK;
270
271 switch (cmd) {
272 case MSG_CMD_READ:
273 pendingReads |= BIT(id);
274 break;
275 case MSG_CMD_WRITE:
276 pendingWrites |= BIT(id);
277 break;
278 case MSG_CMD_WRITE_NOW:
279 pendingWrites |= BIT(id);
280 // skip storageAllowWriteID() check
281 if (storageWriteID(id)) {
282 pendingWrites &= ~BIT(id);
283 }
284 break;
285 case MSG_CMD_PING:
286 /* nop */
287 break;
288 case MSG_CMD_REG:
289#if EFI_STORAGE_INT_FLASH == TRUE
290 if ((StorageType)id == STORAGE_INT_FLASH) {
292 }
293#endif // EFI_STORAGE_INT_FLASH
294#if EFI_STORAGE_MFS == TRUE
297 }
298#endif // EFI_STORAGE_MFS
299#if EFI_STORAGE_SD == TRUE
300 if ((StorageType)id == STORAGE_SD_CARD) {
302 }
303#endif // EFI_STORAGE_SD
304 break;
305 case MSG_CMD_UNREG:
307 break;
308 default:
309 /* ignore */
310 break;
311 }
312 }
313
314 // check if we can read some of pending IDs...
315 for (size_t i = 0; (i < EFI_STORAGE_TOTAL_ITEMS) && pendingReads; i++) {
316 if ((pendingReads & BIT(i)) == 0) {
317 continue;
318 }
319
321 if (!storageIsIdAvailableForId(id)) {
322 continue;
323 }
324
325 if (storageReadID(id)) {
326 pendingReads &= ~BIT(id);
327 }
328 }
329
330 // check if we can write some of pendind IDs...
331 for (size_t i = 0; (i < EFI_STORAGE_TOTAL_ITEMS) && pendingWrites; i++) {
332 if ((pendingWrites & BIT(i)) == 0) {
333 continue;
334 }
335
337 if (!storageIsIdAvailableForId(id)) {
338 continue;
339 }
340
341 if (!storageAllowWriteID(id)) {
342 continue;
343 }
344
345 if (storageWriteID(id)) {
346 pendingWrites &= ~BIT(id);
347 }
348 }
349 }
350}
351
352/* misc helpers */
356
358 bool settingsStorageReady = false;
359 // may be unused
360 (void)settingsStorageReady;
361
362#if EFI_STORAGE_INT_FLASH == TRUE
363 settingsStorageReady = initStorageFlash();
364#endif // EFI_STORAGE_INT_FLASH
365
366#if EFI_STORAGE_MFS == TRUE
367 if (settingsStorageReady) {
368 // Skip MFS if internal storage is used for persistentState
369 // Init of MFS may take significant time, lets postpone it until storage manager thread
371 } else {
372 // Set long timeout to watchdog as this code is called before any thread is started
373 // and no one is feeding watchdog
374 startWatchdog(WATCHDOG_MFS_START_TIMEOUT_MS);
375
377
378 // restart the watchdog with the default timeout
380 }
381#endif // EFI_STORAGE_MFS
382
383 chThdCreateStatic(storageManagerThreadStack, sizeof(storageManagerThreadStack), PRIO_STORAGE_MANAGER, storageManagerThread, nullptr);
384}
385
386#endif // EFI_CONFIGURATION_STORAGE
bool mcuCanFlashWhileRunning()
Definition mpu_util.cpp:10
void startWatchdog(int)
TriggerCentral triggerCentral
Definition engine.h:318
RpmCalculator rpmCalculator
Definition engine.h:306
constexpr auto & module()
Definition engine.h:200
bool isStopped() const override
static EngineAccessor engine
Definition engine.h:413
bool writeToFlashNowImpl()
static const char * storageTypeToName(StorageType type)
Definition storage.cpp:111
bool storageIsStorageRegistered(StorageType type)
Definition storage.cpp:230
static THD_WORKING_AREA(storageManagerThreadStack, 3 *UTILITY_THREAD_STACK_SIZE)
static uint32_t pendingReads
Definition storage.cpp:249
bool storageReqestReadID(StorageItemId id)
Definition storage.cpp:190
bool storageUnregisterStorage(StorageType type)
Definition storage.cpp:213
static bool storageWriteID(uint32_t id)
Definition storage.cpp:83
static bool storageReadID(uint32_t id)
Definition storage.cpp:98
bool storagRequestUnregisterStorage(StorageType id)
Definition storage.cpp:243
bool storageRegisterStorage(StorageType type, SettingStorageBase *storage)
Definition storage.cpp:194
chibios_rt::Mailbox< msg_t, 16 > storageManagerMb
Definition storage.cpp:71
static SettingStorageBase * storages[storagesCount]
Definition storage.cpp:69
StorageStatus storageRead(StorageItemId id, uint8_t *ptr, size_t size)
Definition storage.cpp:160
static uint32_t pendingWrites
Definition storage.cpp:248
bool storageRequestWriteID(StorageItemId id, bool forced)
Definition storage.cpp:186
bool storageAllowWriteID(StorageItemId id)
Definition storage.cpp:19
static constexpr size_t storagesCount
Definition storage.cpp:67
void initStorage()
Definition storage.cpp:357
static void storageManagerThread(void *)
Definition storage.cpp:258
StorageStatus storageWrite(StorageItemId id, const uint8_t *ptr, size_t size)
Definition storage.cpp:142
bool getNeedToWriteConfiguration()
Definition storage.cpp:353
static bool storageManagerSendCmd(uint32_t cmd, uint32_t arg)
Definition storage.cpp:178
static bool storageIsIdAvailableForId(StorageItemId id)
Definition storage.cpp:132
bool storagRequestRegisterStorage(StorageType id)
Definition storage.cpp:238
StorageType
Definition storage.h:37
@ STORAGE_INT_FLASH
Definition storage.h:38
@ STORAGE_TOTAL
Definition storage.h:43
@ STORAGE_SD_CARD
Definition storage.h:41
@ STORAGE_MFS_EXT_FLASH
Definition storage.h:40
@ STORAGE_MFS_INT_FLASH
Definition storage.h:39
StorageItemId
Definition storage.h:47
@ EFI_SETTINGS_BACKUP_RECORD_ID
Definition storage.h:50
@ EFI_LTFT_RECORD_ID
Definition storage.h:51
@ EFI_STORAGE_TOTAL_ITEMS
Definition storage.h:53
@ EFI_SETTINGS_RECORD_ID
Definition storage.h:49
StorageStatus
Definition storage.h:12
bool initStorageFlash()
Storage interface to internal MCU flash header.
bool initStorageMfs()
bool initStorageSD()
Storage interface to FatFS header.
composite packet size