rusEFI
The most advanced open source ECU
Enumerations | Functions | Variables
flash_main.cpp File Reference

Detailed Description

Higher-level logic of saving data into internal flash memory.

Date
Sep 19, 2013
Author
Andrey Belomutskiy, (c) 2012-2020

Definition in file flash_main.cpp.

Enumerations

enum class  FlashState { Ok , CrcFailed , IncompatibleVersion , BlankChip }
 

Functions

void boardInitMfs (void)
 
const MFSConfig * boardGetMfsConfig (void)
 
static uint32_t flashStateCrc (const persistent_config_container_s &state)
 
chibios_rt::BinarySemaphore flashWriteSemaphore (true)
 
static THD_WORKING_AREA (flashWriteStack, 3 *UTILITY_THREAD_STACK_SIZE)
 
static THD_WORKING_AREA (flashWriteStack, UTILITY_THREAD_STACK_SIZE)
 
static void flashWriteThread (void *)
 
bool allowFlashWhileRunning ()
 
void setNeedToWriteConfiguration ()
 
bool getNeedToWriteConfiguration ()
 
void writeToFlashIfPending ()
 
template<typename TStorage >
int eraseAndFlashCopy (flashaddr_t storageAddress, const TStorage &data)
 
void writeToFlashNow ()
 
static void doResetConfiguration ()
 
static FlashState validatePersistentState ()
 
static FlashState readOneConfigurationCopy (flashaddr_t address)
 
static FlashState readConfiguration ()
 
void readFromFlash ()
 
static void rewriteConfig ()
 
static void eraseConfig ()
 
void initFlash ()
 

Variables

static bool needToWriteConfiguration = false
 
MFSDriver mfsd
 
bool burnWithoutFlash = false
 

Enumeration Type Documentation

◆ FlashState

enum FlashState
strong
Enumerator
Ok 
CrcFailed 
IncompatibleVersion 
BlankChip 

Definition at line 234 of file flash_main.cpp.

234  {
235  Ok,
236  CrcFailed,
238  // all is well, but we're on a fresh chip with blank memory
239  BlankChip,
240 };
@ IncompatibleVersion

Function Documentation

◆ allowFlashWhileRunning()

bool allowFlashWhileRunning ( )

Definition at line 94 of file flash_main.cpp.

94  {
95  // either MCU supports flashing while executing
96  // either we store settings in external storage
97  return (mcuCanFlashWhileRunning() || (EFI_STORAGE_MFS_EXTERNAL == TRUE));
98 }
bool mcuCanFlashWhileRunning()
Definition: mpu_util.cpp:10

Referenced by initFlash(), setNeedToWriteConfiguration(), and writeToFlashIfPending().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ boardGetMfsConfig()

const MFSConfig* boardGetMfsConfig ( void  )

Definition at line 34 of file board_storage.cpp.

35 {
36  return &mfscfg1;
37 }
const MFSConfig mfscfg1

Referenced by initFlash().

Here is the caller graph for this function:

◆ boardInitMfs()

void boardInitMfs ( void  )

Definition at line 28 of file board_storage.cpp.

29 {
30  /* Starting EFL driver.*/
31  eflStart(&EFLD2, NULL);
32 }

Referenced by initFlash().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ doResetConfiguration()

static void doResetConfiguration ( )
static

Definition at line 230 of file flash_main.cpp.

230  {
232 }
void resetConfigurationExt(configuration_callback_t boardCallback, engine_type_e engineType)
engine_configuration_s * engineConfiguration

Referenced by initFlash(), and rewriteConfig().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ eraseAndFlashCopy()

template<typename TStorage >
int eraseAndFlashCopy ( flashaddr_t  storageAddress,
const TStorage &  data 
)

Definition at line 139 of file flash_main.cpp.

139  {
140  // error already reported, return
141  if (!storageAddress) {
142  return FLASH_RETURN_SUCCESS;
143  }
144 
145  auto err = intFlashErase(storageAddress, sizeof(TStorage));
146  if (FLASH_RETURN_SUCCESS != err) {
147  criticalError("Failed to erase flash at 0x%08x: %d", storageAddress, err);
148  return err;
149  }
150 
151  err = intFlashWrite(storageAddress, reinterpret_cast<const char*>(&data), sizeof(TStorage));
152  if (FLASH_RETURN_SUCCESS != err) {
153  criticalError("Failed to write flash at 0x%08x: %d", storageAddress, err);
154  return err;
155  }
156 
157  return err;
158 }
return FLASH_RETURN_SUCCESS
Definition: flash_int.cpp:80
int intFlashErase(flashaddr_t address, size_t size)
Erase the sectors containing the span of size bytes starting at address.
Definition: flash_int.cpp:115
int intFlashWrite(flashaddr_t address, const char *buffer, size_t size)
Copy data from a buffer to the flash memory.
Definition: flash_int.cpp:365

Referenced by writeToFlashNow().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ eraseConfig()

static void eraseConfig ( )
static

Definition at line 372 of file flash_main.cpp.

372  {
373  efitick_t startNt = getTimeNowNt();
374 
375  mfs_error_t err;
376  err = mfsErase(&mfsd);
377 
378  efitick_t endNt = getTimeNowNt();
379  int elapsed_Ms = US2MS(NT2US(endNt - startNt));
380  efiPrintf("erase done %d mS err %d", elapsed_Ms, err);
381 }
efitick_t getTimeNowNt()
Definition: efitime.cpp:19
MFSDriver mfsd
Definition: flash_main.cpp:50

Referenced by initFlash().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ flashStateCrc()

static uint32_t flashStateCrc ( const persistent_config_container_s state)
static

https://sourceforge.net/p/rusefi/tickets/335/

In order to preserve at least one copy of the tune in case of electrical issues address of second configuration copy should be in a different sector of flash since complete flash sectors are erased on write.

Definition at line 66 of file flash_main.cpp.

66  {
67  return crc32(&state.persistentConfiguration, sizeof(persistent_config_s));
68 }
static ScState state

Referenced by validatePersistentState(), and writeToFlashNow().

Here is the caller graph for this function:

◆ flashWriteSemaphore()

chibios_rt::BinarySemaphore flashWriteSemaphore ( true  )

Referenced by flashWriteThread(), and setNeedToWriteConfiguration().

Here is the caller graph for this function:

◆ flashWriteThread()

static void flashWriteThread ( void *  )
static

Definition at line 80 of file flash_main.cpp.

80  {
81  chRegSetThreadName("flash writer");
82 
83  while (true) {
84  // Wait for a request to come in
85  flashWriteSemaphore.wait();
86 
87  // Do the actual flash write operation
89  }
90 }
chibios_rt::BinarySemaphore flashWriteSemaphore(true)
void writeToFlashNow()
Definition: flash_main.cpp:162

Referenced by initFlash().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ getNeedToWriteConfiguration()

bool getNeedToWriteConfiguration ( )
Returns
true if an flash write is pending

Definition at line 112 of file flash_main.cpp.

112  {
114 }
static bool needToWriteConfiguration
Definition: flash_main.cpp:44

Referenced by updateFlags(), and writeToFlashIfPending().

Here is the caller graph for this function:

◆ initFlash()

void initFlash ( )

This would write NOW (you should not be doing this while connected to real engine)

This would schedule write to flash once the engine is stopped

Definition at line 384 of file flash_main.cpp.

384  {
385 #if EFI_STORAGE_MFS == TRUE
386  boardInitMfs();
387  const MFSConfig *mfsConfig = boardGetMfsConfig();
388 
389  /* MFS */
390  mfsObjectInit(&mfsd);
391  mfs_error_t err = mfsStart(&mfsd, mfsConfig);
392  if (err < MFS_NO_ERROR) {
393  /* hm...? */
394  }
395 
396  addConsoleAction("eraseconfig", eraseConfig);
397 #endif
398 
399  addConsoleAction("readconfig", readFromFlash);
400  /**
401  * This would write NOW (you should not be doing this while connected to real engine)
402  */
403  addConsoleAction(CMD_WRITECONFIG, writeToFlashNow);
404 #if EFI_TUNER_STUDIO
405  /**
406  * This would schedule write to flash once the engine is stopped
407  */
408  addConsoleAction(CMD_BURNCONFIG, requestBurn);
409 #endif
410  addConsoleAction("resetconfig", doResetConfiguration);
411  addConsoleAction("rewriteconfig", rewriteConfig);
412 
413 #if (EFI_FLASH_WRITE_THREAD == TRUE)
414  if (allowFlashWhileRunning()) {
415  chThdCreateStatic(flashWriteStack, sizeof(flashWriteStack), PRIO_FLASH_WRITE, flashWriteThread, nullptr);
416  } else {
417  efiPrintf("EFI_FLASH_WRITE_THREAD is enabled, but not used");
418  }
419 #endif
420 }
void addConsoleAction(const char *token, Void callback)
Register console action without parameters.
static void flashWriteThread(void *)
Definition: flash_main.cpp:80
void boardInitMfs(void)
bool allowFlashWhileRunning()
Definition: flash_main.cpp:94
const MFSConfig * boardGetMfsConfig(void)
static void doResetConfiguration()
Definition: flash_main.cpp:230
void readFromFlash()
Definition: flash_main.cpp:323
static void rewriteConfig()
Definition: flash_main.cpp:366
static void eraseConfig()
Definition: flash_main.cpp:372
void requestBurn()

Referenced by initHardwareNoConfig().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ readConfiguration()

static FlashState readConfiguration ( )
static

this method could and should be executed before we have any connectivity so no console output here

in this method we read first copy of configuration in flash. if that first copy has CRC or other issues we read second copy.

Definition at line 283 of file flash_main.cpp.

283  {
284 #if EFI_STORAGE_MFS == TRUE
285  size_t settings_size = sizeof(persistentState);
286  mfs_error_t err = mfsReadRecord(&mfsd, EFI_MFS_SETTINGS_RECORD_ID,
287  &settings_size, (uint8_t *)&persistentState);
288 
289  if (err >= MFS_NO_ERROR) {
290  // readed size is not exactly the same
291  if (settings_size != sizeof(persistentState))
293  return validatePersistentState();
294  } else {
295  return FlashState::BlankChip;
296  }
297 #endif
298 
299 #if EFI_STORAGE_INT_FLASH == TRUE
300  auto firstCopyAddr = getFlashAddrFirstCopy();
301  auto secondyCopyAddr = getFlashAddrSecondCopy();
302 
303  FlashState firstCopy = readOneConfigurationCopy(firstCopyAddr);
304 
305  if (firstCopy == FlashState::Ok) {
306  // First copy looks OK, don't even need to check second copy.
307  return firstCopy;
308  }
309 
310  /* no second copy? */
311  if (getFlashAddrSecondCopy() == 0x0) {
312  return firstCopy;
313  }
314 
315  efiPrintf("Reading second configuration copy");
316  return readOneConfigurationCopy(secondyCopyAddr);
317 #endif
318 
319  // In case of neither of those cases, return that things went OK?
320  return FlashState::Ok;
321 }
persistent_config_container_s persistentState
uintptr_t getFlashAddrFirstCopy(void)
Definition: mpu_util.cpp:236
uintptr_t getFlashAddrSecondCopy(void)
Definition: mpu_util.cpp:240
static FlashState readOneConfigurationCopy(flashaddr_t address)
Definition: flash_main.cpp:263
FlashState
Definition: flash_main.cpp:234
static FlashState validatePersistentState()
Definition: flash_main.cpp:242

Referenced by readFromFlash().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ readFromFlash()

void readFromFlash ( )

Definition at line 323 of file flash_main.cpp.

323  {
324 #if HW_CHECK_MODE
325  /*
326  * getFlashAddr does device validation, we want validation to be invoked even while we are
327  * HW_CHECK_MODE mode where we would not need actual address
328  * todo: rename method to emphasis the fact of validation check?
329  */
332 
333  resetConfigurationExt(DEFAULT_ENGINE_TYPE);
334 
335  FlashState result = FlashState::Ok;
336 #else
337  FlashState result = readConfiguration();
338 #endif
339 
340  switch (result) {
342  warning(ObdCode::CUSTOM_ERR_FLASH_CRC_FAILED, "flash CRC failed");
343  efiPrintf("Need to reset flash to default due to CRC mismatch");
344  [[fallthrough]];
346  resetConfigurationExt(DEFAULT_ENGINE_TYPE);
347  break;
349  // Preserve engine type from old config
350  efiPrintf("Resetting due to version mismatch but preserving engine type [%d]", (int)engineConfiguration->engineType);
352  break;
353  case FlashState::Ok:
354  // At this point we know that CRC and version number is what we expect. Safe to assume it's a valid configuration.
356  efiPrintf("Read valid configuration from flash!");
357  break;
358  }
359 
360  // we can only change the state after the CRC check
363  engine->preCalculate();
364 }
void preCalculate()
Definition: engine.cpp:352
void applyNonPersistentConfiguration()
Engine * engine
bool warning(ObdCode code, const char *fmt,...)
int getRusEfiVersion(void)
static FlashState readConfiguration()
Definition: flash_main.cpp:283
@ CUSTOM_ERR_FLASH_CRC_FAILED

Referenced by initFlash(), and loadConfiguration().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ readOneConfigurationCopy()

static FlashState readOneConfigurationCopy ( flashaddr_t  address)
static

Read single copy of rusEFI configuration from interan flash using custom driver

Definition at line 263 of file flash_main.cpp.

263  {
264  efiPrintf("readFromFlash %x", address);
265 
266  // error already reported, return
267  if (!address) {
268  return FlashState::BlankChip;
269  }
270 
271  intFlashRead(address, (char *) &persistentState, sizeof(persistentState));
272 
273  return validatePersistentState();
274 }
int intFlashRead(flashaddr_t source, char *destination, size_t size)
Copy data from the flash memory to a destination.
Definition: flash_int.cpp:130

Referenced by readConfiguration().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ rewriteConfig()

static void rewriteConfig ( )
static

Definition at line 366 of file flash_main.cpp.

366  {
368  writeToFlashNow();
369 }

Referenced by initFlash().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ setNeedToWriteConfiguration()

void setNeedToWriteConfiguration ( )

Definition at line 100 of file flash_main.cpp.

100  {
101  efiPrintf("Scheduling configuration write");
103 
104 #if (EFI_FLASH_WRITE_THREAD == TRUE)
105  if (allowFlashWhileRunning()) {
106  // Signal the flash writer thread to wake up and write at its leisure
107  flashWriteSemaphore.signal();
108  }
109 #endif // EFI_FLASH_WRITE_THREAD
110 }

Referenced by requestBurn().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ THD_WORKING_AREA() [1/2]

static THD_WORKING_AREA ( flashWriteStack  ,
3 *  UTILITY_THREAD_STACK_SIZE 
)
static

◆ THD_WORKING_AREA() [2/2]

static THD_WORKING_AREA ( flashWriteStack  ,
UTILITY_THREAD_STACK_SIZE   
)
static

◆ validatePersistentState()

static FlashState validatePersistentState ( )
static

Definition at line 242 of file flash_main.cpp.

242  {
243  auto flashCrc = flashStateCrc(persistentState);
244 
245  if (flashCrc != persistentState.crc) {
246  // If the stored crc is all 1s, that probably means the flash is actually blank, not that the crc failed.
247  if (persistentState.crc == ((decltype(persistentState.crc))-1)) {
248  return FlashState::BlankChip;
249  } else {
250  return FlashState::CrcFailed;
251  }
252  } else if (persistentState.version != FLASH_DATA_VERSION || persistentState.size != sizeof(persistentState)) {
254  } else {
255  return FlashState::Ok;
256  }
257 }
static uint32_t flashStateCrc(const persistent_config_container_s &state)
Definition: flash_main.cpp:66

Referenced by readConfiguration(), and readOneConfigurationCopy().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ writeToFlashIfPending()

void writeToFlashIfPending ( )

Definition at line 116 of file flash_main.cpp.

116  {
117 #if (EFI_FLASH_WRITE_THREAD == TRUE)
118  // with a flash write thread, the schedule happens directly from
119  // setNeedToWriteConfiguration and writing happens from flash thread,
120  // so there's nothing to do here
121  if (allowFlashWhileRunning()) {
122  return;
123  }
124 #endif
126  // Allow sensor timeouts again now that we're done (and a little time has passed)
128  return;
129  }
130 
131  // Prevent sensor timeouts while flashing
133  writeToFlashNow();
134  // we do not want to allow sensor timeouts right away, we re-enable next time method is invoked
135 }
static void inhibitTimeouts(bool inhibit)
Definition: sensor.cpp:232
bool getNeedToWriteConfiguration()
Definition: flash_main.cpp:112

Referenced by doPeriodicSlowCallback().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ writeToFlashNow()

void writeToFlashNow ( )

Because of hardware-related issues, stm32f4 chip is totally frozen while we are writing to internal flash. Writing the configuration takes about 1-2 seconds, we cannot afford to do that while the engine is running so we postpone the write until the engine is stopped.

Definition at line 162 of file flash_main.cpp.

162  {
163  engine->configBurnTimer.reset();
164  bool isSuccess = false;
165 
166  if (burnWithoutFlash) {
167  needToWriteConfiguration = false;
168  return;
169  }
170  efiPrintf("Writing pending configuration... %d bytes", sizeof(persistentState));
171  efitick_t startNt = getTimeNowNt();
172 
173  // Set up the container
175  persistentState.version = FLASH_DATA_VERSION;
177 
178  // there's no wdgStop() for STM32, so we cannot disable it.
179  // we just set a long timeout of 5 secs to wait until flash is done.
180  startWatchdog(WATCHDOG_FLASH_TIMEOUT_MS);
181 
182 #if EFI_STORAGE_MFS == TRUE
183  mfs_error_t err;
184  /* In case of MFS:
185  * do we need to have two copies?
186  * do we need to protect it with CRC? */
187 
188  err = mfsWriteRecord(&mfsd, EFI_MFS_SETTINGS_RECORD_ID,
189  sizeof(persistentState), (uint8_t *)&persistentState);
190 
191  if (err >= MFS_NO_ERROR)
192  isSuccess = true;
193 #endif
194 
195 #if EFI_STORAGE_INT_FLASH == TRUE
196  // Flash two copies
198  int result2 = FLASH_RETURN_SUCCESS;
199  /* Only if second copy is supported */
200  if (getFlashAddrSecondCopy()) {
202  }
203 
204  // handle success/failure
205  isSuccess = (result1 == FLASH_RETURN_SUCCESS) && (result2 == FLASH_RETURN_SUCCESS);
206 #endif
207 
208  // restart the watchdog with the default timeout
209  startWatchdog();
210 
211  if (isSuccess) {
212  efitick_t endNt = getTimeNowNt();
213  int elapsed_Ms = US2MS(NT2US(endNt - startNt));
214 
215 #if EFI_STORAGE_MFS == TRUE
216  efiPrintf("FLASH_SUCCESS after %d mS MFS status %d", elapsed_Ms, err);
217 #else
218  efiPrintf("FLASH_SUCCESS after %d mS", elapsed_Ms);
219 #endif
220  } else {
221  efiPrintf("Flashing failed");
222  }
223 
224  resetMaxValues();
225 
226  // Write complete, clear the flag
227  needToWriteConfiguration = false;
228 }
void startWatchdog(int)
Timer configBurnTimer
Definition: engine.h:276
int eraseAndFlashCopy(flashaddr_t storageAddress, const TStorage &data)
Definition: flash_main.cpp:139
bool burnWithoutFlash
Definition: flash_main.cpp:160
void resetMaxValues()

Referenced by flashWriteThread(), handleCommandX14(), initFlash(), loadConfiguration(), rewriteConfig(), setEngineType(), and writeToFlashIfPending().

Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ burnWithoutFlash

bool burnWithoutFlash = false

Definition at line 160 of file flash_main.cpp.

Referenced by handleCommandX14(), and writeToFlashNow().

◆ mfsd

MFSDriver mfsd

Definition at line 50 of file flash_main.cpp.

Referenced by eraseConfig(), initFlash(), readConfiguration(), and writeToFlashNow().

◆ needToWriteConfiguration

bool needToWriteConfiguration = false
static

Go to the source code of this file.